diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index dccbe6804..3822456fa 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -21,7 +21,7 @@ jobs: strategy: fail-fast: false matrix: - target: [ 'cig_wf186h', 'cig_wf186w', 'cig_wf188n', 'cig_wf196', 'cig_wf660a', 'cybertan_eww622-a1', 'cybertan_eww631-a1', 'cybertan_eww631-b1', 'edgecore_eap101', 'edgecore_eap102', 'edgecore_eap104', 'edgecore_eap111', 'edgecore_ecw5211', 'edgecore_oap101', 'edgecore_oap101-6e', 'edgecore_oap101e', 'edgecore_oap101e-6e', 'edgecore_oap102', 'hfcl_ion4','hfcl_ion4xi_wp', 'hfcl_ion4xe', 'hfcl_ion4xi', 'hfcl_ion4x', 'hfcl_ion4x_2', 'hfcl_ion4xi_w', 'hfcl_ion4xi_HMR', 'hfcl_ion4x_w', 'indio_um-305ax', 'indio_um-325ac', 'indio_um-510ac-v3', 'indio_um-550ac', 'indio_um-310ax-v1', 'indio_um-510axp-v1', 'indio_um-510axm-v1', 'udaya_a5-id2', 'wallys_dr40x9', 'wallys_dr6018', 'wallys_dr6018_v4', 'yuncore_ax820', 'yuncore_ax840', 'yuncore_fap640', 'yuncore_fap650', 'yuncore_fap655' ] + target: [ 'cig_wf186h', 'cig_wf186w', 'cig_wf188n', 'cig_wf196', 'cig_wf189', 'cig_wf660a', 'cybertan_eww622-a1', 'cybertan_eww631-a1', 'cybertan_eww631-b1', 'edgecore_eap101', 'edgecore_eap102', 'edgecore_eap104', 'edgecore_eap111', 'edgecore_ecw5211', 'edgecore_oap101', 'edgecore_oap101-6e', 'edgecore_oap101e', 'edgecore_oap101e-6e', 'edgecore_oap102', 'hfcl_ion4','hfcl_ion4xi_wp', 'hfcl_ion4xe', 'hfcl_ion4xi', 'hfcl_ion4x', 'hfcl_ion4x_2', 'hfcl_ion4xi_w', 'hfcl_ion4xi_HMR', 'hfcl_ion4x_w', 'indio_um-305ax', 'indio_um-325ac', 'indio_um-510ac-v3', 'indio_um-550ac', 'indio_um-310ax-v1', 'indio_um-510axp-v1', 'indio_um-510axm-v1', 'sercomm_ap72tip', 'udaya_a5-id2', 'wallys_dr40x9', 'wallys_dr6018', 'wallys_dr6018-v4', 'yuncore_ax820', 'yuncore_ax840', 'yuncore_fap640', 'yuncore_fap650', 'yuncore_fap655' ] steps: - uses: actions/checkout@v3 diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..88ba6e5be --- /dev/null +++ b/LICENSE @@ -0,0 +1,28 @@ +BSD 3-Clause License + +Copyright (c) 2024, Telecom Infra Project + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/feeds/ipq40xx/ipq40xx/base-files/lib/upgrade/platform.sh b/feeds/ipq40xx/ipq40xx/base-files/lib/upgrade/platform.sh index fa6a16cf4..6a7155bd2 100644 --- a/feeds/ipq40xx/ipq40xx/base-files/lib/upgrade/platform.sh +++ b/feeds/ipq40xx/ipq40xx/base-files/lib/upgrade/platform.sh @@ -83,12 +83,12 @@ platform_do_upgrade() { part="$(awk -F 'ubi.mtd=' '{printf $2}' /proc/cmdline | cut -d " " -f 1)" case "$part" in rootfs1) - fw_setenv active 2 || exit 1 CI_UBIPART="rootfs2" + CI_FWSETENV="active 2" ;; rootfs2) - fw_setenv active 1 || exit 1 CI_UBIPART="rootfs1" + CI_FWSETENV="active 1" ;; *) # legacy bootloader diff --git a/feeds/ipq807x/ipq807x/base-files/etc/hotplug.d/firmware/10-ath11k-caldata b/feeds/ipq807x/ipq807x/base-files/etc/hotplug.d/firmware/10-ath11k-caldata index 27dae3e67..91e30c426 100755 --- a/feeds/ipq807x/ipq807x/base-files/etc/hotplug.d/firmware/10-ath11k-caldata +++ b/feeds/ipq807x/ipq807x/base-files/etc/hotplug.d/firmware/10-ath11k-caldata @@ -211,7 +211,7 @@ ath11k/IPQ5018/hw1.0/caldata.bin) optimcloud,d60|\ optimcloud,d60-5g|\ optimcloud,d50|\ - optimcloud,d50-5g|\ + optimcloud,d50-5g|\ qcom,ipq5018-mp03.1) caldata_extract "0:ART" 0x1000 0x20000 ;; @@ -298,7 +298,7 @@ ath11k-macs) optimcloud,d60|\ optimcloud,d60-5g|\ optimcloud,d50|\ - optimcloud,d50-5g|\ + optimcloud,d50-5g|\ cig,wf188n) ath11k_generate_macs ;; diff --git a/feeds/ipq807x/ipq807x/base-files/etc/init.d/bootcount b/feeds/ipq807x/ipq807x/base-files/etc/init.d/bootcount index 0a545d14b..3867ad463 100755 --- a/feeds/ipq807x/ipq807x/base-files/etc/init.d/bootcount +++ b/feeds/ipq807x/ipq807x/base-files/etc/init.d/bootcount @@ -16,7 +16,8 @@ boot() { ;; edgecore,eap101|\ edgecore,eap102|\ - edgecore,oap102) + edgecore,oap102|\ + edgecore.eap104) avail=$(fw_printenv -n upgrade_available) [ "${avail}" -eq 1 ] || fw_setenv upgrade_available 1 fw_setenv bootcount 0 diff --git a/feeds/ipq807x/ipq807x/base-files/lib/upgrade/nand.sh b/feeds/ipq807x/ipq807x/base-files/lib/upgrade/nand.sh index 41a2de529..e8f10668d 100644 --- a/feeds/ipq807x/ipq807x/base-files/lib/upgrade/nand.sh +++ b/feeds/ipq807x/ipq807x/base-files/lib/upgrade/nand.sh @@ -247,8 +247,8 @@ nand_do_upgrade_success() { local conf_tar="/tmp/sysupgrade.tgz" sync [ "$CI_BOOTCFG" = 1 ] && nand_qca_update_bootconfig + [ -f "$conf_tar" ] && nand_restore_config "$conf_tar" && sync [ -n "$CI_FWSETENV" ] && fw_setenv $CI_FWSETENV - [ -f "$conf_tar" ] && nand_restore_config "$conf_tar" echo "sysupgrade successful" umount -a reboot -f diff --git a/feeds/ipq807x/ipq807x/base-files/lib/upgrade/platform.sh b/feeds/ipq807x/ipq807x/base-files/lib/upgrade/platform.sh index ca17d3382..499c39622 100755 --- a/feeds/ipq807x/ipq807x/base-files/lib/upgrade/platform.sh +++ b/feeds/ipq807x/ipq807x/base-files/lib/upgrade/platform.sh @@ -194,8 +194,6 @@ platform_do_upgrade() { cig,wf194c4|\ cig,wf196|\ cybertan,eww622-a1|\ - cybertan,eww631-a1|\ - cybertan,eww631-b1|\ glinet,ax1800|\ glinet,axt1800|\ indio,um-310ax-v1|\ @@ -262,8 +260,8 @@ platform_do_upgrade() { else if [ -e /tmp/downgrade ]; then CI_UBIPART="rootfs1" - fw_setenv active 1 || exit 1 - fw_setenv upgrade_available 0 || exit 1 + { echo 'active 1'; echo 'upgrade_available 0'; } > /tmp/fw_setenv.txt || exit 1 + CI_FWSETENV="-s /tmp/fw_setenv.txt" elif grep -q rootfs1 /proc/cmdline; then CI_UBIPART="rootfs2" CI_FWSETENV="active 2" @@ -289,5 +287,18 @@ platform_do_upgrade() { } nand_upgrade_tar "$1" ;; + cybertan,eww631-a1|\ + cybertan,eww631-b1) + boot_part=$(fw_printenv bootfrom | cut -d = -f2) + echo "Current bootfrom is $boot_part" + if [[ $boot_part == 1 ]]; then + CI_UBIPART="rootfs" + CI_FWSETENV="bootfrom 0" + else + CI_UBIPART="rootfs_1" + CI_FWSETENV="bootfrom 1" + fi + nand_upgrade_tar "$1" + ;; esac } diff --git a/feeds/ipq807x_v5.4/ath11k-wifi/Makefile b/feeds/ipq807x_v5.4/ath11k-wifi/Makefile index 828c8e362..77c42b702 100644 --- a/feeds/ipq807x_v5.4/ath11k-wifi/Makefile +++ b/feeds/ipq807x_v5.4/ath11k-wifi/Makefile @@ -29,9 +29,9 @@ ALLWIFIBOARDS:= \ cig-wf660a \ cig-wf194c \ cig-wf194c4 \ - cig-wf196-ca \ - cig-wf196-us \ cybertan-eww622-a1 \ + cybertan-eww631-a1 \ + cybertan-eww631-b1 \ edgecore-eap101 \ gl-ax1800 \ gl-axt1800 \ @@ -89,14 +89,9 @@ $(call Package/ath11k-wifi-default) TITLE:=board-2.bin for QCOM IPQ6122 eval kits endef -define Package/ath11k-wifi-cig-wf196_6g-ca +define Package/ath11k-wifi-cig-wf196 $(call Package/ath11k-wifi-default) - TITLE:=cig-wf196 6G bdf CA -endef - -define Package/ath11k-wifi-cig-wf196_6g-us -$(call Package/ath11k-wifi-default) - TITLE:=cig-wf196 6G bdf US + TITLE:=cig-wf196 bdf endef define Package/ath11k-wifi-gl-ax1800 @@ -175,14 +170,9 @@ $(call Package/ath11k-wifi-default) TITLE:=edgecore-oap101e bdf endef -define Package/ath11k-wifi-cig-wf188n-ca +define Package/ath11k-wifi-cig-wf188n $(call Package/ath11k-wifi-default) - TITLE:=cig-wf188n bdf CA -endef - -define Package/ath11k-wifi-cig-wf188n-us -$(call Package/ath11k-wifi-default) - TITLE:=cig-wf188n bdf US + TITLE:=cig-wf188n bdf endef define ath11k-wifi-install-one-to @@ -262,16 +252,12 @@ define Package/ath11k-wifi-qcom-qcn9000/install $(INSTALL_DATA) ./board-2.bin.QCN9000 $(1)/lib/firmware/ath11k/QCN9074/hw1.0/board-2.bin endef -define Package/ath11k-wifi-cig-wf196_6g-ca/install - $(INSTALL_DIR) $(1)/lib/firmware/ath11k/QCN9074/hw1.0/ - $(INSTALL_DATA) ./board-cig-wf196_6g-ca.bin.QCN9074 $(1)/lib/firmware/ath11k/QCN9074/hw1.0/board.bin - echo -n 'CA' > $(1)/lib/firmware/country -endef - -define Package/ath11k-wifi-cig-wf196_6g-us/install - $(INSTALL_DIR) $(1)/lib/firmware/ath11k/QCN9074/hw1.0/ - $(INSTALL_DATA) ./board-cig-wf196_6g-us.bin.QCN9074 $(1)/lib/firmware/ath11k/QCN9074/hw1.0/board.bin - echo -n 'US' > $(1)/lib/firmware/country +define Package/ath11k-wifi-cig-wf196/install + $(INSTALL_DIR) $(1)/lib/firmware/ath11k/QCN9074/hw1.0/ $(1)/lib/firmware/ath11k/IPQ8074/hw2.0/ + $(INSTALL_DATA) ./board-cig-wf196_6g-ca.bin.QCN9074 $(1)/lib/firmware/ath11k/QCN9074/hw1.0/board.bin.CA + $(INSTALL_DATA) ./board-cig-wf196_6g-us.bin.QCN9074 $(1)/lib/firmware/ath11k/QCN9074/hw1.0/board.bin.US + $(INSTALL_DATA) ./board-cig-wf196-ca.bin.IPQ8074 $(1)/lib/firmware/ath11k/IPQ8074/hw2.0/board.bin.CA + $(INSTALL_DATA) ./board-cig-wf196-us.bin.IPQ8074 $(1)/lib/firmware/ath11k/IPQ8074/hw2.0/board.bin.US endef define Package/ath11k-wifi-optimcloud-d50/install @@ -365,16 +351,10 @@ define Package/ath11k-wifi-edgecore-oap101e/install $(INSTALL_DATA) ./board-2-edgecore-oap101e.bin.QCN6122 $(1)/lib/firmware/ath11k/qcn6122/hw1.0/board-2.bin endef -define Package/ath11k-wifi-cig-wf188n-ca/install +define Package/ath11k-wifi-cig-wf188n/install $(INSTALL_DIR) $(1)/lib/firmware/ath11k/IPQ6018/hw1.0/ - $(INSTALL_DATA) ./board-cig-wf188n-ca.bin.IPQ6018 $(1)/lib/firmware/ath11k/IPQ6018/hw1.0/board.bin - echo -n 'CA MY DE' > $(1)/lib/firmware/country -endef - -define Package/ath11k-wifi-cig-wf188n-us/install - $(INSTALL_DIR) $(1)/lib/firmware/ath11k/IPQ6018/hw1.0/ - $(INSTALL_DATA) ./board-cig-wf188n-us.bin.IPQ6018 $(1)/lib/firmware/ath11k/IPQ6018/hw1.0/board.bin - echo -n 'US MY DE' > $(1)/lib/firmware/country + $(INSTALL_DATA) ./board-cig-wf188n-ca.bin.IPQ6018 $(1)/lib/firmware/ath11k/IPQ6018/hw1.0/board.bin.CA + $(INSTALL_DATA) ./board-cig-wf188n-us.bin.IPQ6018 $(1)/lib/firmware/ath11k/IPQ6018/hw1.0/board.bin.US endef $(eval $(call generate-ath11k-wifi-package,cig-wf186w,Cigtech WF186w)) @@ -382,9 +362,9 @@ $(eval $(call generate-ath11k-wifi-package,cig-wf186h,Cigtech WF186h)) $(eval $(call generate-ath11k-wifi-package,cig-wf660a,Cigtech WF660a)) $(eval $(call generate-ath11k-wifi-package,cig-wf194c,Cigtech WF194c)) $(eval $(call generate-ath11k-wifi-package,cig-wf194c4,Cigtech WF194c4)) -$(eval $(call generate-ath11k-wifi-package,cig-wf196-ca,Cigtech WF196 CA)) -$(eval $(call generate-ath11k-wifi-package,cig-wf196-us,Cigtech WF196 US)) $(eval $(call generate-ath11k-wifi-package,cybertan-eww622-a1,CyberTan EWW622 A1)) +$(eval $(call generate-ath11k-wifi-package,cybertan-eww631-a1,CyberTan EWW631 A1)) +$(eval $(call generate-ath11k-wifi-package,cybertan-eww631-b1,CyberTan EWW631 B1)) $(eval $(call generate-ath11k-wifi-package,sercomm-wallaby,Sercomm Kiwi)) $(eval $(call generate-ath11k-wifi-package,wallys-dr6018,Wallys DR6018)) $(eval $(call generate-ath11k-wifi-package,wallys-dr6018-v4,Wallys DR6018 V4)) @@ -410,8 +390,7 @@ $(eval $(call BuildPackage,ath11k-wifi-qcom-ipq6122)) $(eval $(call BuildPackage,ath11k-wifi-qcom-ipq8074)) $(eval $(call BuildPackage,ath11k-wifi-qcom-ipq6018)) $(eval $(call BuildPackage,ath11k-wifi-qcom-qcn9000)) -$(eval $(call BuildPackage,ath11k-wifi-cig-wf196_6g-ca)) -$(eval $(call BuildPackage,ath11k-wifi-cig-wf196_6g-us)) +$(eval $(call BuildPackage,ath11k-wifi-cig-wf196)) $(eval $(call BuildPackage,ath11k-wifi-motorola-q14)) $(eval $(call BuildPackage,ath11k-wifi-optimcloud-d50)) $(eval $(call BuildPackage,ath11k-wifi-optimcloud-d60)) @@ -423,5 +402,4 @@ $(eval $(call BuildPackage,ath11k-wifi-hfcl-ion4x_w)) $(eval $(call BuildPackage,ath11k-wifi-hfcl-ion4xi_HMR)) $(eval $(call BuildPackage,ath11k-wifi-edgecore-oap101)) $(eval $(call BuildPackage,ath11k-wifi-edgecore-oap101e)) -$(eval $(call BuildPackage,ath11k-wifi-cig-wf188n-ca)) -$(eval $(call BuildPackage,ath11k-wifi-cig-wf188n-us)) +$(eval $(call BuildPackage,ath11k-wifi-cig-wf188n)) diff --git a/feeds/ipq807x_v5.4/ath11k-wifi/board-cybertan-eww631-a1.bin.IPQ5018 b/feeds/ipq807x_v5.4/ath11k-wifi/board-cybertan-eww631-a1.bin.IPQ5018 new file mode 100644 index 000000000..8fd712175 Binary files /dev/null and b/feeds/ipq807x_v5.4/ath11k-wifi/board-cybertan-eww631-a1.bin.IPQ5018 differ diff --git a/feeds/ipq807x_v5.4/ath11k-wifi/board-cybertan-eww631-a1.bin.QCN6122 b/feeds/ipq807x_v5.4/ath11k-wifi/board-cybertan-eww631-a1.bin.QCN6122 new file mode 100644 index 000000000..13fe8c447 Binary files /dev/null and b/feeds/ipq807x_v5.4/ath11k-wifi/board-cybertan-eww631-a1.bin.QCN6122 differ diff --git a/feeds/ipq807x_v5.4/ath11k-wifi/board-cybertan-eww631-b1.bin.IPQ5018 b/feeds/ipq807x_v5.4/ath11k-wifi/board-cybertan-eww631-b1.bin.IPQ5018 new file mode 100644 index 000000000..d0f3451f5 Binary files /dev/null and b/feeds/ipq807x_v5.4/ath11k-wifi/board-cybertan-eww631-b1.bin.IPQ5018 differ diff --git a/feeds/ipq807x_v5.4/ath11k-wifi/board-cybertan-eww631-b1.bin.QCN6122 b/feeds/ipq807x_v5.4/ath11k-wifi/board-cybertan-eww631-b1.bin.QCN6122 new file mode 100644 index 000000000..4bf645248 Binary files /dev/null and b/feeds/ipq807x_v5.4/ath11k-wifi/board-cybertan-eww631-b1.bin.QCN6122 differ diff --git a/feeds/ipq807x_v5.4/ipq50xx/base-files/etc/board.d/02_network b/feeds/ipq807x_v5.4/ipq50xx/base-files/etc/board.d/02_network index e52988b20..be617c9cc 100755 --- a/feeds/ipq807x_v5.4/ipq50xx/base-files/etc/board.d/02_network +++ b/feeds/ipq807x_v5.4/ipq50xx/base-files/etc/board.d/02_network @@ -18,6 +18,13 @@ qcom_setup_interfaces() cig,wf186h) ucidef_add_switch "switch0" "4:wan" "1:lan" "2:lan" "6@eth0" ;; + cybertan,eww631-a1) + ucidef_set_interface_wan "eth0" + ucidef_set_interface_lan "" + ;; + cybertan,eww631-b1) + ucidef_add_switch "switch1" "5:wan" "2:lan" "3:lan" "4:lan" "6@eth0" + ;; edgecore,oap101|\ edgecore,oap101-6e|\ edgecore,oap101e|\ @@ -63,6 +70,18 @@ qcom_setup_macs() ucidef_set_network_device_mac eth0 $wan_mac ip link set eth0 address $wan_mac ;; + cybertan,eww631-a1|\ + cybertan,eww631-b1) + mtd=$(find_mtd_chardev "0:APPSBLENV") + [ -z "$mtd" ] && return; + mac=$(grep BaseMacAddress= $mtd | cut -d '=' -f2) + [ -z "$mac" ] && return; + wan_mac=$(macaddr_canonicalize $mac) + lan_mac=$(macaddr_add "$wan_mac" 1) + ucidef_set_network_device_mac eth0 $wan_mac + ip link set eth0 address $wan_mac + ucidef_set_label_macaddr $wan_mac + ;; *) wan_mac=$(cat /sys/class/net/eth0/address) lan_mac=$(macaddr_add "$wan_mac" 1) diff --git a/feeds/ipq807x_v5.4/ipq50xx/base-files/etc/hotplug.d/firmware/10-ath11k-caldata b/feeds/ipq807x_v5.4/ipq50xx/base-files/etc/hotplug.d/firmware/10-ath11k-caldata index 8898d5e68..c49848d45 100755 --- a/feeds/ipq807x_v5.4/ipq50xx/base-files/etc/hotplug.d/firmware/10-ath11k-caldata +++ b/feeds/ipq807x_v5.4/ipq50xx/base-files/etc/hotplug.d/firmware/10-ath11k-caldata @@ -39,6 +39,28 @@ ath11k_generate_macs_ion4x() { echo -ne \\x${wifimac2//:/\\x} >> /lib/firmware/ath11k-macs } +ath11k_generate_macs_eww631_a1() { + touch /lib/firmware/ath11k-macs + local dev=$(find_mtd_chardev "0:APPSBLENV") + mac=$(grep BaseMacAddress= $dev | cut -d '=' -f2) + eth=$(macaddr_canonicalize $mac) + mac1=$(macaddr_add $eth 1) + mac2=$(macaddr_add $eth 2) + echo -ne \\x${mac1//:/\\x} >> /lib/firmware/ath11k-macs + echo -ne \\x${mac2//:/\\x} >> /lib/firmware/ath11k-macs +} + +ath11k_generate_macs_eww631_b1() { + touch /lib/firmware/ath11k-macs + local dev=$(find_mtd_chardev "0:APPSBLENV") + mac=$(grep BaseMacAddress= $dev | cut -d '=' -f2) + eth=$(macaddr_canonicalize $mac) + mac1=$(macaddr_add $eth 2) + mac2=$(macaddr_add $eth 3) + echo -ne \\x${mac1//:/\\x} >> /lib/firmware/ath11k-macs + echo -ne \\x${mac2//:/\\x} >> /lib/firmware/ath11k-macs +} + caldata_die() { echo "caldata: " "$*" exit 1 @@ -64,6 +86,8 @@ ath11k/IPQ5018/hw1.0/caldata.bin) case "$board" in cig,wf186w|\ cig,wf186h|\ + cybertan,eww631-a1|\ + cybertan,eww631-b1|\ edgecore,eap104|\ edgecore,oap101|\ edgecore,oap101-6e|\ @@ -84,6 +108,8 @@ ath11k/qcn6122/hw1.0/caldata_1.bin) case "$board" in cig,wf186w|\ cig,wf186h|\ + cybertan,eww631-a1|\ + cybertan,eww631-b1|\ edgecore,oap101|\ edgecore,oap101-6e|\ edgecore,oap101e|\ @@ -101,6 +127,10 @@ ath11k/qcn6122/hw1.0/caldata_2.bin) edgecore,oap101e-6e) caldata_extract "0:ART" 0x4c000 0x20000 ;; + cybertan,eww631-a1|\ + cybertan,eww631-b1) + caldata_extract "0:ART" 0x26800 0x20000 + ;; esac ;; ath11k/QCN9074/hw1.0/caldata_1.bin) @@ -119,6 +149,12 @@ ath11k-macs) cig,wf186h) ath11k_generate_macs_wf186w ;; + cybertan,eww631-a1) + ath11k_generate_macs_eww631_a1 + ;; + cybertan,eww631-b1) + ath11k_generate_macs_eww631_b1 + ;; edgecore,eap104|\ optimcloud,d60|\ optimcloud,d60-5g|\ diff --git a/feeds/ipq807x_v5.4/ipq50xx/base-files/lib/upgrade/nand.sh b/feeds/ipq807x_v5.4/ipq50xx/base-files/lib/upgrade/nand.sh index 41a2de529..e8f10668d 100644 --- a/feeds/ipq807x_v5.4/ipq50xx/base-files/lib/upgrade/nand.sh +++ b/feeds/ipq807x_v5.4/ipq50xx/base-files/lib/upgrade/nand.sh @@ -247,8 +247,8 @@ nand_do_upgrade_success() { local conf_tar="/tmp/sysupgrade.tgz" sync [ "$CI_BOOTCFG" = 1 ] && nand_qca_update_bootconfig + [ -f "$conf_tar" ] && nand_restore_config "$conf_tar" && sync [ -n "$CI_FWSETENV" ] && fw_setenv $CI_FWSETENV - [ -f "$conf_tar" ] && nand_restore_config "$conf_tar" echo "sysupgrade successful" umount -a reboot -f diff --git a/feeds/ipq807x_v5.4/ipq50xx/base-files/lib/upgrade/platform.sh b/feeds/ipq807x_v5.4/ipq50xx/base-files/lib/upgrade/platform.sh index bd14f9ed8..812088f51 100755 --- a/feeds/ipq807x_v5.4/ipq50xx/base-files/lib/upgrade/platform.sh +++ b/feeds/ipq807x_v5.4/ipq50xx/base-files/lib/upgrade/platform.sh @@ -70,6 +70,8 @@ platform_check_image() { case $board in cig,wf186w|\ cig,wf186h|\ + cybertan,eww631-a1|\ + cybertan,eww631-b1|\ edgecore,eap104|\ hfcl,ion4x_w|\ hfcl,ion4xi_w|\ @@ -130,5 +132,18 @@ platform_do_upgrade() { } nand_upgrade_tar "$1" ;; + cybertan,eww631-a1|\ + cybertan,eww631-b1) + boot_part=$(fw_printenv bootfrom | cut -d = -f2) + echo "Current bootfrom is $boot_part" + if [[ $boot_part == 1 ]]; then + CI_UBIPART="rootfs" + CI_FWSETENV="bootfrom 0" + else + CI_UBIPART="rootfs_1" + CI_FWSETENV="bootfrom 1" + fi + nand_upgrade_tar "$1" + ;; esac } diff --git a/feeds/ipq807x_v5.4/ipq50xx/files/arch/arm64/boot/dts/qcom/qcom-ipq5018-eww631-a1.dts b/feeds/ipq807x_v5.4/ipq50xx/files/arch/arm64/boot/dts/qcom/qcom-ipq5018-eww631-a1.dts new file mode 100644 index 000000000..622bf6b6b --- /dev/null +++ b/feeds/ipq807x_v5.4/ipq50xx/files/arch/arm64/boot/dts/qcom/qcom-ipq5018-eww631-a1.dts @@ -0,0 +1,915 @@ +/dts-v1/; +/* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. + * + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. + * + * 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. + */ + +#include "ipq5018.dtsi" + +/ { + #address-cells = <0x2>; + #size-cells = <0x2>; + model = "CyberTan EWW631-A1"; + compatible = "cybertan,eww631-a1", "qcom,ipq5018-mp03.5", "qcom,ipq5018"; + interrupt-parent = <&intc>; + + aliases { + sdhc1 = &sdhc_1; /* SDC1 eMMC slot */ + serial0 = &blsp1_uart1; + serial1 = &blsp1_uart2; + ethernet0 = "/soc/dp1"; + ethernet1 = "/soc/dp2"; + }; + + chosen { + bootargs = "console=ttyMSM0,115200,n8 rw init=/init"; + bootargs-append = " swiotlb=1 coherent_pool=2M"; + stdout-path = "serial0"; + }; + + reserved-memory { + #ifdef __IPQ_MEM_PROFILE_256_MB__ + /* 256 MB Profile + * +==========+==============+=========================+ + * | | | | + * | Region | Start Offset | Size | + * | | | | + * +----------+--------------+-------------------------+ + * | NSS | 0x40000000 | 8MB | + * +----------+--------------+-------------------------+ + * | Linux | 0x40800000 | Depends on total memory | + * +----------+--------------+-------------------------+ + * | uboot | 0x4A600000 | 4MB | + * +----------+--------------+-------------------------+ + * | SBL | 0x4AA00000 | 1MB | + * +----------+--------------+-------------------------+ + * | smem | 0x4AB00000 | 1MB | + * +----------+--------------+-------------------------+ + * | TZ | 0x4AC00000 | 4MB | + * +----------+--------------+-------------------------+ + * | Q6 | | | + * | code/ | 0x4B000000 | 20MB | + * | data | | | + * +----------+--------------+-------------------------+ + * | IPQ5018 | | | + * | data | 0x4C400000 | 13MB | + * +----------+--------------+-------------------------+ + * | IPQ5018 | | | + * | M3 Dump | 0x4D100000 | 1MB | + * +----------+--------------+-------------------------+ + * | IPQ5018 | | | + * | QDSS | 0x4D200000 | 1MB | + * +----------+--------------+-------------------------+ + * | QCN6122_1| | | + * | data | 0x4D300000 | 13MB | + * +----------+--------------+-------------------------+ + * | QCN6122_1| | | + * | M3 Dump | 0x4E000000 | 1MB | + * +----------+--------------+-------------------------+ + * | QCN6122_1| | | + * | QDSS | 0x4E100000 | 1MB | + * +----------+--------------+-------------------------+ + * | QCN6122_2| | | + * | data | 0x4E200000 | 13MB | + * +----------+--------------+-------------------------+ + * | QCN6122_2| | | + * | M3 Dump | 0x4EF00000 | 1MB | + * +----------+--------------+-------------------------+ + * | QCN6122_2| | | + * | QDSS | 0x4F000000 | 1MB | + * +----------+--------------+-------------------------+ + * | | + * | Rest of the memory for Linux | + * | | + * +===================================================+ + */ + q6_mem_regions: q6_mem_regions@4B000000 { + no-map; + reg = <0x0 0x4B000000 0x0 0x4100000>; + }; + + q6_code_data: q6_code_data@4B000000 { + no-map; + reg = <0x0 0x4B000000 0x0 0x1400000>; + }; + + q6_ipq5018_data: q6_ipq5018_data@4C400000 { + no-map; + reg = <0x0 0x4C400000 0x0 0xD00000>; + }; + + m3_dump: m3_dump@4D100000 { + no-map; + reg = <0x0 0x4D100000 0x0 0x100000>; + }; + + q6_etr_region: q6_etr_dump@4D200000 { + no-map; + reg = <0x0 0x4D200000 0x0 0x100000>; + }; + + q6_qcn6122_data1: q6_qcn6122_data1@4D300000 { + no-map; + reg = <0x0 0x4D300000 0x0 0xD00000>; + }; + + m3_dump_qcn6122_1: m3_dump_qcn6122_1@4E000000 { + no-map; + reg = <0x0 0x4E000000 0x0 0x100000>; + }; + + q6_qcn6122_etr_1: q6_qcn6122_etr_1@4E100000 { + no-map; + reg = <0x0 0x4E100000 0x0 0x100000>; + }; + + q6_qcn6122_data2: q6_qcn6122_data2@4E200000 { + no-map; + reg = <0x0 0x4E200000 0x0 0xD00000>; + }; + + m3_dump_qcn6122_2: m3_dump_qcn6122_2@4EF00000 { + no-map; + reg = <0x0 0x4EF00000 0x0 0x100000>; + }; + + q6_qcn6122_etr_2: q6_qcn6122_etr_2@4F000000 { + no-map; + reg = <0x0 0x4F000000 0x0 0x100000>; + }; + #else + /* 512MB/1GB Profiles + * +==========+==============+=========================+ + * | | | | + * | Region | Start Offset | Size | + * | | | | + * +----------+--------------+-------------------------+ + * | NSS | 0x40000000 | 16MB | + * +----------+--------------+-------------------------+ + * | Linux | 0x41000000 | Depends on total memory | + * +----------+--------------+-------------------------+ + * | uboot | 0x4A600000 | 4MB | + * +----------+--------------+-------------------------+ + * | SBL | 0x4AA00000 | 1MB | + * +----------+--------------+-------------------------+ + * | smem | 0x4AB00000 | 1MB | + * +----------+--------------+-------------------------+ + * | TZ | 0x4AC00000 | 4MB | + * +----------+--------------+-------------------------+ + * | Q6 | | | + * | code/ | 0x4B000000 | 20MB | + * | data | | | + * +----------+--------------+-------------------------+ + * | IPQ5018 | | | + * | data | 0x4C400000 | 13MB | + * +----------+--------------+-------------------------+ + * | IPQ5018 | | | + * | M3 Dump | 0x4D100000 | 1MB | + * +----------+--------------+-------------------------+ + * | IPQ5018 | | | + * | QDSS | 0x4D200000 | 1MB | + * +----------+--------------+-------------------------+ + * | IPQ5018 | | | + * | Caldb | 0x4D300000 | 2MB | + * +----------+--------------+-------------------------+ + * | QCN6122_1| | | + * | data | 0x4D500000 | 13MB | + * +----------+--------------+-------------------------+ + * | QCN6122_1| | | + * | M3 Dump | 0x4E200000 | 1MB | + * +----------+--------------+-------------------------+ + * | QCN6122_1| | | + * | QDSS | 0x4E300000 | 1MB | + * +----------+--------------+-------------------------+ + * | QCN6122_1| | | + * | Caldb | 0x4E400000 | 5MB | + * +----------+--------------+-------------------------+ + * | QCN6122_2| | | + * | data | 0x4E900000 | 13MB | + * +----------+--------------+-------------------------+ + * | QCN6122_2| | | + * | M3 Dump | 0x4F600000 | 1MB | + * +----------+--------------+-------------------------+ + * | QCN6122_2| | | + * | QDSS | 0x4F700000 | 1MB | + * +----------+--------------+-------------------------+ + * | QCN6122_2| | | + * | Caldb | 0x4F800000 | 5MB | + * +----------+--------------+-------------------------+ + * | | + * | Rest of the memory for Linux | + * | | + * +===================================================+ + */ + q6_mem_regions: q6_mem_regions@4B000000 { + no-map; + reg = <0x0 0x4B000000 0x0 0x4D00000>; + }; + + q6_code_data: q6_code_data@4B000000 { + no-map; + reg = <0x0 0x4B000000 0x0 01400000>; + }; + + q6_ipq5018_data: q6_ipq5018_data@4C400000 { + no-map; + reg = <0x0 0x4C400000 0x0 0xD00000>; + }; + + m3_dump: m3_dump@4D100000 { + no-map; + reg = <0x0 0x4D100000 0x0 0x100000>; + }; + + q6_etr_region: q6_etr_dump@4D200000 { + no-map; + reg = <0x0 0x4D200000 0x0 0x100000>; + }; + + q6_caldb_region: q6_caldb_region@4D300000 { + no-map; + reg = <0x0 0x4D300000 0x0 0x200000>; + }; + + q6_qcn6122_data1: q6_qcn6122_data1@4D500000 { + no-map; + reg = <0x0 0x4D500000 0x0 0xD00000>; + }; + + m3_dump_qcn6122_1: m3_dump_qcn6122_1@4E200000 { + no-map; + reg = <0x0 0x4E200000 0x0 0x100000>; + }; + + q6_qcn6122_etr_1: q6_qcn6122_etr_1@4E300000 { + no-map; + reg = <0x0 0x4E300000 0x0 0x100000>; + }; + + q6_qcn6122_caldb_1: q6_qcn6122_caldb_1@4E400000 { + no-map; + reg = <0x0 0x4E400000 0x0 0x500000>; + }; + + q6_qcn6122_data2: q6_qcn6122_data2@4E900000 { + no-map; + reg = <0x0 0x4E900000 0x0 0xD00000>; + }; + + m3_dump_qcn6122_2: m3_dump_qcn6122_2@4F600000 { + no-map; + reg = <0x0 0x4F600000 0x0 0x100000>; + }; + + q6_qcn6122_etr_2: q6_qcn6122_etr_2@4F700000 { + no-map; + reg = <0x0 0x4F700000 0x0 0x100000>; + }; + + q6_qcn6122_caldb_2: q6_qcn6122_caldb_2@4F800000 { + no-map; + reg = <0x0 0x4F800000 0x0 0x500000>; + }; + + #endif + }; + + soc { + serial@78af000 { + status = "ok"; + }; + + blsp1_uart2: serial@78b0000 { + pinctrl-0 = <&blsp1_uart_pins>; + pinctrl-names = "default"; + }; + + qpic_bam: dma@7984000{ + status = "ok"; + }; + + nand: qpic-nand@79b0000 { + pinctrl-0 = <&qspi_nand_pins>; + pinctrl-names = "default"; + status = "ok"; + }; + + spi_0: spi@78b5000 { /* BLSP1 QUP0 */ + pinctrl-0 = <&blsp0_spi_pins>; + pinctrl-names = "default"; + cs-select = <0>; + status = "ok"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + compatible = "n25q128a11"; + linux,modalias = "m25p80", "n25q128a11"; + spi-max-frequency = <50000000>; + use-default-sizes; + }; + }; + + mdio0: mdio@88000 { + status = "ok"; + + ethernet-phy@0 { + reg = <7>; + }; + }; + + mdio1: mdio@90000 { + status = "disabled"; + pinctrl-0 = <&mdio1_pins>; + pinctrl-names = "default"; + phy-reset-gpio = <&tlmm 39 0>; + + ethernet-phy@0 { + reg = <28>; + }; + }; + + ess-instance { + num_devices = <0x1>; + ess-switch@0x39c00000 { + switch_mac_mode = <0xf>; /* mac mode for uniphy instance*/ + cmnblk_clk = "internal_96MHz"; /* cmnblk clk*/ + qcom,port_phyinfo { + port@0 { + port_id = <1>; + phy_address = <7>; + mdiobus = <&mdio0>; + }; + /* + port@1 { + port_id = <2>; + phy_address = <0x1c>; + mdiobus = <&mdio1>; + port_mac_sel = "QGMAC_PORT"; + }; + */ + }; + + led_source@0 { + source = <0>; + mode = "normal"; + speed = "all"; + blink_en = "enable"; + active = "high"; + }; + + }; + }; + + dp1 { + device_type = "network"; + compatible = "qcom,nss-dp"; + clocks = <&gcc GCC_SNOC_GMAC0_AXI_CLK>; + clock-names = "nss-snoc-gmac-axi-clk"; + qcom,id = <1>; + reg = <0x39C00000 0x10000>; + interrupts = ; + qcom,mactype = <2>; + qcom,link-poll = <1>; + qcom,phy-mdio-addr = <7>; + mdio-bus = <&mdio0>; + local-mac-address = [000000000000]; + phy-mode = "sgmii"; + qcom,rx-page-mode = <0>; + }; + /* + dp2 { + device_type = "network"; + compatible = "qcom,nss-dp"; + clocks = <&gcc GCC_SNOC_GMAC1_AXI_CLK>; + clock-names = "nss-snoc-gmac-axi-clk"; + qcom,id = <2>; + reg = <0x39D00000 0x10000>; + interrupts = ; + qcom,mactype = <2>; + qcom,link-poll = <1>; + qcom,phy-mdio-addr = <28>; + mdio-bus = <&mdio1>; + local-mac-address = [000000000000]; + phy-mode = "sgmii"; + qcom,rx-page-mode = <0>; + }; + */ + + nss-macsec1 { + compatible = "qcom,nss-macsec"; + phy_addr = <0x1c>; + mdiobus = <&mdio1>; + }; + }; + + qcom,test@0 { + status = "ok"; + }; + + thermal-zones { + status = "ok"; + }; +}; + +&tlmm { + pinctrl-0 = <&blsp0_uart_pins &phy_led_pins>; + pinctrl-names = "default"; + + blsp0_uart_pins: blsp0_uart_pins { + blsp0_uart_rx_tx { + pins = "gpio20", "gpio21"; + function = "blsp0_uart0"; + bias-disable; + }; + }; + + blsp1_uart_pins: blsp1_uart_pins { + blsp1_uart_rx_tx { + pins = "gpio23", "gpio25", "gpio24", "gpio26"; + function = "blsp1_uart2"; + bias-disable; + }; + }; + + blsp0_spi_pins: blsp0_spi_pins { + mux { + pins = "gpio10", "gpio11", "gpio12", "gpio13"; + function = "blsp0_spi"; + drive-strength = <2>; + bias-disable; + }; + }; + + qspi_nand_pins: qspi_nand_pins { + qspi_clock { + pins = "gpio9"; + function = "qspi_clk"; + drive-strength = <8>; + bias-disable; + }; + + qspi_cs { + pins = "gpio8"; + function = "qspi_cs"; + drive-strength = <8>; + bias-disable; + }; + + qspi_data { + pins = "gpio4", "gpio5", "gpio6", "gpio7"; + function = "qspi_data"; + drive-strength = <8>; + bias-disable; + }; + }; + + mdio1_pins: mdio_pinmux { + mux_0 { + pins = "gpio36"; + function = "mdc"; + drive-strength = <8>; + bias-pull-up; + }; + + mux_1 { + pins = "gpio37"; + function = "mdio"; + drive-strength = <8>; + bias-pull-up; + }; + }; + + phy_led_pins: phy_led_pins { + gephy_led_pin { + pins = "gpio46"; + function = "led0"; + drive-strength = <8>; + bias-pull-down; + }; + }; + + i2c_pins: i2c_pins { + i2c_scl { + pins = "gpio25"; + function = "blsp2_i2c1"; + drive-strength = <8>; + bias-disable; + }; + + i2c_sda { + pins = "gpio26"; + function = "blsp2_i2c1"; + drive-strength = <8>; + bias-disable; + }; + }; + + button_pins: button_pins { + reset_button { + pins = "gpio28"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + }; + + audio_pins: audio_pinmux { + mux_1 { + pins = "gpio24"; + function = "audio_rxbclk"; + drive-strength = <8>; + bias-pull-down; + }; + + mux_2 { + pins = "gpio25"; + function = "audio_rxfsync"; + drive-strength = <8>; + bias-pull-down; + }; + + mux_3 { + pins = "gpio26"; + function = "audio_rxd"; + drive-strength = <8>; + bias-pull-down; + }; + + mux_4 { + pins = "gpio27"; + function = "audio_txmclk"; + drive-strength = <8>; + bias-pull-down; + }; + + mux_5 { + pins = "gpio28"; + function = "audio_txbclk"; + drive-strength = <8>; + bias-pull-down; + }; + + mux_6 { + pins = "gpio29"; + function = "audio_txfsync"; + drive-strength = <8>; + bias-pull-down; + }; + + mux_7 { + pins = "gpio30"; + function = "audio_txd"; + drive-strength = <8>; + bias-pull-down; + }; + }; + leds_pins: leds_pinmux { + sys_blue { + pins = "gpio30"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + sys_red { + pins = "gpio36"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + }; + sys_green { + pins = "gpio37"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + }; + }; +}; + +&soc { + gpio_keys { + compatible = "gpio-keys"; + pinctrl-0 = <&button_pins>; + pinctrl-names = "default"; + + button@1 { + label = "reset"; + linux,code = ; + gpios = <&tlmm 28 GPIO_ACTIVE_LOW>; + linux,input-type = <1>; + debounce-interval = <60>; + }; + }; + gpio_leds { + compatible = "gpio-leds"; + pinctrl-0 = <&leds_pins>; + pinctrl-names = "default"; + + led@30 { + label = "sys:blue"; + gpios = <&tlmm 30 GPIO_ACTIVE_HIGH>; /* GPIO_30 */ + default-state="on"; + /* linux,default-trigger = "timer"; + active-delay = <700>; + inactive-delay = <700>; + default-state="on"; */ + }; + led@36 { + label = "sys:red"; + gpios = <&tlmm 36 GPIO_ACTIVE_HIGH>; /* GPIO_36 */ + default-state="off"; + /* linux,default-trigger = "timer"; + active-delay = <700>; + inactive-delay = <700>; + default-state="on"; */ + }; + led@37 { + label = "sys:green"; + gpios = <&tlmm 37 GPIO_ACTIVE_HIGH>; /* GPIO_37 */ + default-state="off"; + /* linux,default-trigger = "timer"; + active-delay = <700>; + inactive-delay = <700>; + default-state="on"; */ + }; + }; + +}; + +&q6v5_wcss { + compatible = "qcom,ipq5018-q6-mpd"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + firmware = "IPQ5018/q6_fw.mdt"; + reg = <0x0cd00000 0x4040>, + <0x1938000 0x8>, + <0x193d204 0x4>; + reg-names = "qdsp6", + "tcsr-msip", + "tcsr-q6"; + resets = <&gcc GCC_WCSSAON_RESET>, + <&gcc GCC_WCSS_Q6_BCR>; + + reset-names = "wcss_aon_reset", + "wcss_q6_reset"; + + clocks = <&gcc GCC_Q6_AXIS_CLK>, + <&gcc GCC_WCSS_ECAHB_CLK>, + <&gcc GCC_Q6_AXIM_CLK>, + <&gcc GCC_Q6_AXIM2_CLK>, + <&gcc GCC_Q6_AHB_CLK>, + <&gcc GCC_Q6_AHB_S_CLK>, + <&gcc GCC_WCSS_AXI_S_CLK>; + clock-names = "gcc_q6_axis_clk", + "gcc_wcss_ecahb_clk", + "gcc_q6_axim_clk", + "gcc_q6_axim2_clk", + "gcc_q6_ahb_clk", + "gcc_q6_ahb_s_clk", + "gcc_wcss_axi_s_clk"; + + #ifdef __IPQ_MEM_PROFILE_256_MB__ + memory-region = <&q6_mem_regions>, <&q6_etr_region>; + #else + memory-region = <&q6_mem_regions>, <&q6_etr_region>, + <&q6_caldb_region>; + #endif + + qcom,rproc = <&q6v5_wcss>; + qcom,bootargs_smem = <507>; + boot-args = <0x1 0x4 0x3 0x0F 0x0 0x0>, + <0x2 0x4 0x2 0x12 0x0 0x0>; + status = "ok"; + q6_wcss_pd1: remoteproc_pd1@4ab000 { + compatible = "qcom,ipq5018-wcss-ahb-mpd"; + reg = <0x4ab000 0x20>; + reg-names = "rmb"; + firmware = "IPQ5018/q6_fw.mdt"; + m3_firmware = "IPQ5018/m3_fw.mdt"; + interrupts-extended = <&wcss_smp2p_in 8 0>, + <&wcss_smp2p_in 9 0>, + <&wcss_smp2p_in 12 0>, + <&wcss_smp2p_in 11 0>; + interrupt-names = "fatal", + "ready", + "spawn-ack", + "stop-ack"; + + resets = <&gcc GCC_WCSSAON_RESET>, + <&gcc GCC_WCSS_BCR>, + <&gcc GCC_CE_BCR>; + reset-names = "wcss_aon_reset", + "wcss_reset", + "ce_reset"; + + clocks = <&gcc GCC_WCSS_AHB_S_CLK>, + <&gcc GCC_WCSS_ACMT_CLK>, + <&gcc GCC_WCSS_AXI_M_CLK>; + clock-names = "gcc_wcss_ahb_s_clk", + "gcc_wcss_acmt_clk", + "gcc_wcss_axi_m_clk"; + + qcom,halt-regs = <&tcsr_q6_block 0xa000 0xd000 0x0>; + + qcom,smem-states = <&wcss_smp2p_out 8>, + <&wcss_smp2p_out 9>, + <&wcss_smp2p_out 10>; + qcom,smem-state-names = "shutdown", + "stop", + "spawn"; + #ifdef __IPQ_MEM_PROFILE_256_MB__ + memory-region = <&q6_ipq5018_data>, <&m3_dump>, + <&q6_etr_region>; + #else + memory-region = <&q6_ipq5018_data>, <&m3_dump>, + <&q6_etr_region>, <&q6_caldb_region>; + #endif + + }; + + q6_wcss_pd2: remoteproc_pd2 { + compatible = "qcom,ipq5018-wcss-pcie-mpd"; + firmware = "IPQ5018/q6_fw.mdt"; + m3_firmware = "qcn6122/m3_fw.mdt"; + interrupts-extended = <&wcss_smp2p_in 16 0>, + <&wcss_smp2p_in 17 0>, + <&wcss_smp2p_in 20 0>, + <&wcss_smp2p_in 19 0>; + interrupt-names = "fatal", + "ready", + "spawn-ack", + "stop-ack"; + + qcom,smem-states = <&wcss_smp2p_out 16>, + <&wcss_smp2p_out 17>, + <&wcss_smp2p_out 18>; + qcom,smem-state-names = "shutdown", + "stop", + "spawn"; + #ifdef __IPQ_MEM_PROFILE_256_MB__ + memory-region = <&q6_qcn6122_data1>, <&m3_dump_qcn6122_1>, + <&q6_qcn6122_etr_1>; + #else + memory-region = <&q6_qcn6122_data1>, <&m3_dump_qcn6122_1>, + <&q6_qcn6122_etr_1>, <&q6_qcn6122_caldb_1>; + #endif + + }; + + q6_wcss_pd3: remoteproc_pd3 { + compatible = "qcom,ipq5018-wcss-pcie-mpd"; + firmware = "IPQ5018/q6_fw.mdt"; + interrupts-extended = <&wcss_smp2p_in 24 0>, + <&wcss_smp2p_in 25 0>, + <&wcss_smp2p_in 28 0>, + <&wcss_smp2p_in 27 0>; + interrupt-names = "fatal", + "ready", + "spawn-ack", + "stop-ack"; + + qcom,smem-states = <&wcss_smp2p_out 24>, + <&wcss_smp2p_out 25>, + <&wcss_smp2p_out 26>; + qcom,smem-state-names = "shutdown", + "stop", + "spawn"; + #ifdef __IPQ_MEM_PROFILE_256_MB__ + memory-region = <&q6_qcn6122_data2>, <&m3_dump_qcn6122_2>, + <&q6_qcn6122_etr_2>; + #else + memory-region = <&q6_qcn6122_data2>, <&m3_dump_qcn6122_2>, + <&q6_qcn6122_etr_2>, <&q6_qcn6122_caldb_2>; + #endif + }; +}; + +&i2c_0 { + pinctrl-0 = <&i2c_pins>; + pinctrl-names = "default"; + status = "disabled"; +}; + +&wifi0 { + /* IPQ5018 */ + qcom,multipd_arch; + qcom,rproc = <&q6_wcss_pd1>; + qcom,userpd-subsys-name = "q6v5_wcss_userpd1"; +#ifdef __IPQ_MEM_PROFILE_256_MB__ + qcom,tgt-mem-mode = <2>; +#else + qcom,tgt-mem-mode = <1>; +#endif + qcom,board_id = <0x24>; +#ifdef __CNSS2__ + qcom,bdf-addr = <0x4C400000 0x4C400000 0x4C400000 0x0 0x0>; + qcom,caldb-addr = <0x4D300000 0x4D300000 0 0 0 0>; + qcom,caldb-size = <0x200000>; + mem-region = <&q6_ipq5018_data>; +1235 +#else + memory-region = <&q6_ipq5018_data>; +#endif + status = "ok"; +}; + +&wifi1 { + /* QCN6122 5G */ + qcom,multipd_arch; + qcom,userpd-subsys-name = "q6v5_wcss_userpd3"; + qcom,rproc = <&q6_wcss_pd3>; +#ifdef __IPQ_MEM_PROFILE_256_MB__ + qcom,tgt-mem-mode = <2>; +#else + qcom,tgt-mem-mode = <1>; +#endif + qcom,board_id = <0x60>; +#ifdef __CNSS2__ + qcom,bdf-addr = <0x4E900000 0x4E900000 0x4E200000 0x0 0x0>; + qcom,caldb-addr = <0x4F800000 0x4F800000 0 0 0>; + qcom,caldb-size = <0x500000>; + mem-region = <&q6_qcn6122_data2>; +#else + memory-region = <&q6_qcn6122_data2>; +#endif + status = "ok"; +}; + +&wifi2 { + /* QCN6122 6G */ + qcom,multipd_arch; + qcom,userpd-subsys-name = "q6v5_wcss_userpd3"; +#ifdef __IPQ_MEM_PROFILE_256_MB__ + qcom,tgt-mem-mode = <2>; +#else + qcom,tgt-mem-mode = <1>; +#endif + qcom,board_id = <0xb0>; + qcom,bdf-addr = <0x4ED00000 0x4ED00000 0x4E400000 0x0 0x0>; +#ifdef __CNSS2__ + qcom,caldb-addr = <0x4FF00000 0x4FF00000 0 0 0>; +#else + qcom,caldb-addr = <0x4FF00000>; + m3-dump-addr = <0x4FD00000>; +#endif + qcom,caldb-size = <0x500000>; + status = "disabled"; +}; + +&usb3 { + status = "ok"; + device-power-gpio = <&tlmm 24 1>; +}; + +&dwc_0 { + /delete-property/ #phy-cells; + /delete-property/ phys; + /delete-property/ phy-names; +}; + +&hs_m31phy_0 { + status = "ok"; +}; + +&eud { + status = "ok"; +}; + +&pcie_x1 { + perst-gpio = <&tlmm 18 GPIO_ACTIVE_LOW>; +}; + +&pcie_x2 { + perst-gpio = <&tlmm 15 GPIO_ACTIVE_LOW>; +}; + +&pcie_x1_rp { + status = "disabled"; + + mhi_0: qcom,mhi@0 { + reg = <0 0 0 0 0 >; + }; +}; + +&pcie_x2_rp { + status = "disabled"; + + mhi_1: qcom,mhi@1 { + reg = <0 0 0 0 0 >; + + }; +}; diff --git a/feeds/ipq807x_v5.4/ipq50xx/files/arch/arm64/boot/dts/qcom/qcom-ipq5018-eww631-b1.dts b/feeds/ipq807x_v5.4/ipq50xx/files/arch/arm64/boot/dts/qcom/qcom-ipq5018-eww631-b1.dts new file mode 100644 index 000000000..ae8adc384 --- /dev/null +++ b/feeds/ipq807x_v5.4/ipq50xx/files/arch/arm64/boot/dts/qcom/qcom-ipq5018-eww631-b1.dts @@ -0,0 +1,981 @@ +/dts-v1/; +/* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. + * + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. + * + * 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. + */ + +#include "ipq5018.dtsi" + +/ { + #address-cells = <0x2>; + #size-cells = <0x2>; + model = "CyberTan EWW631-B1"; + compatible = "cybertan,eww631-b1", "qcom,ipq5018-mp03.5", "qcom,ipq5018"; + interrupt-parent = <&intc>; + + aliases { + sdhc1 = &sdhc_1; /* SDC1 eMMC slot */ + serial0 = &blsp1_uart1; + serial1 = &blsp1_uart2; + ethernet0 = "/soc/dp1"; + ethernet1 = "/soc/dp2"; + }; + + chosen { + bootargs = "console=ttyMSM0,115200,n8 rw init=/init"; + bootargs-append = " swiotlb=1 coherent_pool=2M"; + stdout-path = "serial0"; + }; + + reserved-memory { + #ifdef __IPQ_MEM_PROFILE_256_MB__ + /* 256 MB Profile + * +==========+==============+=========================+ + * | | | | + * | Region | Start Offset | Size | + * | | | | + * +----------+--------------+-------------------------+ + * | NSS | 0x40000000 | 8MB | + * +----------+--------------+-------------------------+ + * | Linux | 0x40800000 | Depends on total memory | + * +----------+--------------+-------------------------+ + * | uboot | 0x4A600000 | 4MB | + * +----------+--------------+-------------------------+ + * | SBL | 0x4AA00000 | 1MB | + * +----------+--------------+-------------------------+ + * | smem | 0x4AB00000 | 1MB | + * +----------+--------------+-------------------------+ + * | TZ | 0x4AC00000 | 4MB | + * +----------+--------------+-------------------------+ + * | Q6 | | | + * | code/ | 0x4B000000 | 20MB | + * | data | | | + * +----------+--------------+-------------------------+ + * | IPQ5018 | | | + * | data | 0x4C400000 | 13MB | + * +----------+--------------+-------------------------+ + * | IPQ5018 | | | + * | M3 Dump | 0x4D100000 | 1MB | + * +----------+--------------+-------------------------+ + * | IPQ5018 | | | + * | QDSS | 0x4D200000 | 1MB | + * +----------+--------------+-------------------------+ + * | QCN6122_1| | | + * | data | 0x4D300000 | 13MB | + * +----------+--------------+-------------------------+ + * | QCN6122_1| | | + * | M3 Dump | 0x4E000000 | 1MB | + * +----------+--------------+-------------------------+ + * | QCN6122_1| | | + * | QDSS | 0x4E100000 | 1MB | + * +----------+--------------+-------------------------+ + * | QCN6122_2| | | + * | data | 0x4E200000 | 13MB | + * +----------+--------------+-------------------------+ + * | QCN6122_2| | | + * | M3 Dump | 0x4EF00000 | 1MB | + * +----------+--------------+-------------------------+ + * | QCN6122_2| | | + * | QDSS | 0x4F000000 | 1MB | + * +----------+--------------+-------------------------+ + * | | + * | Rest of the memory for Linux | + * | | + * +===================================================+ + */ + q6_mem_regions: q6_mem_regions@4B000000 { + no-map; + reg = <0x0 0x4B000000 0x0 0x4100000>; + }; + + q6_code_data: q6_code_data@4B000000 { + no-map; + reg = <0x0 0x4B000000 0x0 0x1400000>; + }; + + q6_ipq5018_data: q6_ipq5018_data@4C400000 { + no-map; + reg = <0x0 0x4C400000 0x0 0xD00000>; + }; + + m3_dump: m3_dump@4D100000 { + no-map; + reg = <0x0 0x4D100000 0x0 0x100000>; + }; + + q6_etr_region: q6_etr_dump@4D200000 { + no-map; + reg = <0x0 0x4D200000 0x0 0x100000>; + }; + + q6_qcn6122_data1: q6_qcn6122_data1@4D300000 { + no-map; + reg = <0x0 0x4D300000 0x0 0xD00000>; + }; + + m3_dump_qcn6122_1: m3_dump_qcn6122_1@4E000000 { + no-map; + reg = <0x0 0x4E000000 0x0 0x100000>; + }; + + q6_qcn6122_etr_1: q6_qcn6122_etr_1@4E100000 { + no-map; + reg = <0x0 0x4E100000 0x0 0x100000>; + }; + + q6_qcn6122_data2: q6_qcn6122_data2@4E200000 { + no-map; + reg = <0x0 0x4E200000 0x0 0xD00000>; + }; + + m3_dump_qcn6122_2: m3_dump_qcn6122_2@4EF00000 { + no-map; + reg = <0x0 0x4EF00000 0x0 0x100000>; + }; + + q6_qcn6122_etr_2: q6_qcn6122_etr_2@4F000000 { + no-map; + reg = <0x0 0x4F000000 0x0 0x100000>; + }; + #else + /* 512MB/1GB Profiles + * +==========+==============+=========================+ + * | | | | + * | Region | Start Offset | Size | + * | | | | + * +----------+--------------+-------------------------+ + * | NSS | 0x40000000 | 16MB | + * +----------+--------------+-------------------------+ + * | Linux | 0x41000000 | Depends on total memory | + * +----------+--------------+-------------------------+ + * | uboot | 0x4A600000 | 4MB | + * +----------+--------------+-------------------------+ + * | SBL | 0x4AA00000 | 1MB | + * +----------+--------------+-------------------------+ + * | smem | 0x4AB00000 | 1MB | + * +----------+--------------+-------------------------+ + * | TZ | 0x4AC00000 | 4MB | + * +----------+--------------+-------------------------+ + * | Q6 | | | + * | code/ | 0x4B000000 | 20MB | + * | data | | | + * +----------+--------------+-------------------------+ + * | IPQ5018 | | | + * | data | 0x4C400000 | 14MB | + * +----------+--------------+-------------------------+ + * | IPQ5018 | | | + * | M3 Dump | 0x4D200000 | 1MB | + * +----------+--------------+-------------------------+ + * | IPQ5018 | | | + * | QDSS | 0x4D300000 | 1MB | + * +----------+--------------+-------------------------+ + * | IPQ5018 | | | + * | Caldb | 0x4D400000 | 2MB | + * +----------+--------------+-------------------------+ + * | QCN6122_1| | | + * | data | 0x4D600000 | 16MB | + * +----------+--------------+-------------------------+ + * | QCN6122_1| | | + * | M3 Dump | 0x4E600000 | 1MB | + * +----------+--------------+-------------------------+ + * | QCN6122_1| | | + * | QDSS | 0x4E700000 | 1MB | + * +----------+--------------+-------------------------+ + * | QCN6122_1| | | + * | Caldb | 0x4E800000 | 5MB | + * +----------+--------------+-------------------------+ + * | QCN6122_2| | | + * | data | 0x4ED00000 | 16MB | + * +----------+--------------+-------------------------+ + * | QCN6122_2| | | + * | M3 Dump | 0x4FD00000 | 1MB | + * +----------+--------------+-------------------------+ + * | QCN6122_2| | | + * | QDSS | 0x4FE00000 | 1MB | + * +----------+--------------+-------------------------+ + * | QCN6122_2| | | + * | Caldb | 0x4FF00000 | 5MB | + * +----------+--------------+-------------------------+ + * | | + * | Rest of the memory for Linux | + * | | + * +===================================================+ + */ + q6_mem_regions: q6_mem_regions@4B000000 { + no-map; + reg = <0x0 0x4B000000 0x0 0x5400000>; + }; + + q6_code_data: q6_code_data@4B000000 { + no-map; + reg = <0x0 0x4B000000 0x0 01400000>; + }; + + q6_ipq5018_data: q6_ipq5018_data@4C400000 { + no-map; + reg = <0x0 0x4C400000 0x0 0xE00000>; + }; + + m3_dump: m3_dump@4D200000 { + no-map; + reg = <0x0 0x4D200000 0x0 0x100000>; + }; + + q6_etr_region: q6_etr_dump@4D300000 { + no-map; + reg = <0x0 0x4D300000 0x0 0x100000>; + }; + + q6_caldb_region: q6_caldb_region@4D400000 { + no-map; + reg = <0x0 0x4D400000 0x0 0x200000>; + }; + + q6_qcn6122_data1: q6_qcn6122_data1@4D600000 { + no-map; + reg = <0x0 0x4D600000 0x0 0x1000000>; + }; + + m3_dump_qcn6122_1: m3_dump_qcn6122_1@4E600000 { + no-map; + reg = <0x0 0x4E600000 0x0 0x100000>; + }; + + q6_qcn6122_etr_1: q6_qcn6122_etr_1@4E700000 { + no-map; + reg = <0x0 0x4E700000 0x0 0x100000>; + }; + + q6_qcn6122_caldb_1: q6_qcn6122_caldb_1@4E800000 { + no-map; + reg = <0x0 0x4E800000 0x0 0x500000>; + }; + + q6_qcn6122_data2: q6_qcn6122_data2@4E900000 { + no-map; + reg = <0x0 0x4ED00000 0x0 0x1000000>; + }; + + m3_dump_qcn6122_2: m3_dump_qcn6122_2@4FD00000 { + no-map; + reg = <0x0 0x4FD00000 0x0 0x100000>; + }; + + q6_qcn6122_etr_2: q6_qcn6122_etr_2@4FE00000 { + no-map; + reg = <0x0 0x4FE00000 0x0 0x100000>; + }; + + q6_qcn6122_caldb_2: q6_qcn6122_caldb_2@4FF00000 { + no-map; + reg = <0x0 0x4FF00000 0x0 0x500000>; + }; + + #endif + }; + + soc { + serial@78af000 { + status = "ok"; + }; +/* + blsp1_uart2: serial@78b0000 { + pinctrl-0 = <&blsp1_uart_pins>; + pinctrl-names = "default"; + }; +*/ + qpic_bam: dma@7984000{ + status = "ok"; + }; + + nand: qpic-nand@79b0000 { + pinctrl-0 = <&qspi_nand_pins>; + pinctrl-names = "default"; + status = "ok"; + }; + + spi_0: spi@78b5000 { /* BLSP1 QUP0 */ + pinctrl-0 = <&blsp0_spi_pins>; + pinctrl-names = "default"; + cs-select = <0>; + status = "ok"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + compatible = "n25q128a11"; + linux,modalias = "m25p80", "n25q128a11"; + spi-max-frequency = <50000000>; + use-default-sizes; + }; + }; + + mdio0: mdio@88000 { + status = "ok"; + + ethernet-phy@0 { + reg = <7>; + }; + }; + + mdio1: mdio@90000 { + status = "ok"; + pinctrl-0 = <&mdio1_pins>; + pinctrl-names = "default"; + phy-reset-gpio = <&tlmm 38 0>; + + ethernet-phy@0 { + reg = <0>; + }; + + ethernet-phy@1 { + reg = <1>; + }; + + ethernet-phy@2 { + reg = <2>; + }; + + ethernet-phy@3 { + reg = <3>; + }; + + ethernet-phy@4 { + reg = <4>; + }; + }; + + ess-instance { + num_devices = <0x2>; + ess-switch@0x39c00000 { + compatible = "qcom,ess-switch-ipq50xx"; + device_id = <0>; + switch_mac_mode = <0xf>; /* mac mode for uniphy instance*/ + cmnblk_clk = "internal_96MHz"; /* cmnblk clk*/ + qcom,port_phyinfo { + port@0 { + port_id = <1>; + phy_address = <7>; + }; + port@1 { + port_id = <2>; + forced-speed = <1000>; + forced-duplex = <1>; + }; + }; + led_source@0 { + source = <0>; + mode = "normal"; + speed = "all"; + blink_en = "enable"; + active = "high"; + }; + }; + ess-switch1@1 { + compatible = "qcom,ess-switch-qca83xx"; + device_id = <1>; + switch_access_mode = "mdio"; + mdio-bus = <&mdio1>; + reset_gpio = <&tlmm 0x26 0>; + switch_cpu_bmp = <0x40>; /* cpu port bitmap (Port 6 GMAC) */ + switch_lan_bmp = <0x3c>; /* lan port bitmap */ + switch_wan_bmp = <0x0>; /* wan port bitmap */ + qca,ar8327-initvals = < + 0x00004 0x7600000 /* PAD0_MODE */ + 0x00008 0x1000000 /* PAD5_MODE */ + 0x0000c 0x80 /* PAD6_MODE */ + 0x00010 0x2613a0 /* PORT6 FORCE MODE*/ + 0x000e4 0xaa545 /* MAC_POWER_SEL */ + 0x000e0 0xc74164de /* SGMII_CTRL */ + 0x0007c 0x4e /* PORT0_STATUS */ + 0x00094 0x4e /* PORT6_STATUS */ + >; + qcom,port_phyinfo { + port@0 { + port_id = <1>; + phy_address = <0>; + }; + port@1 { + port_id = <2>; + phy_address = <1>; + }; + port@2 { + port_id = <3>; + phy_address = <2>; + }; + port@3 { + port_id = <4>; + phy_address = <3>; + }; + port@4 { + port_id = <5>; + phy_address = <4>; + }; + }; + }; + }; + dp1 { + device_type = "network"; + compatible = "qcom,nss-dp"; + clocks = <&gcc GCC_SNOC_GMAC1_AXI_CLK>; + clock-names = "nss-snoc-gmac-axi-clk"; + qcom,id = <2>; + reg = <0x39D00000 0x10000>; + interrupts = ; + qcom,mactype = <2>; + local-mac-address = [000000000000]; + phy-mode = "sgmii"; + }; + + dp2 { + device_type = "network"; + compatible = "qcom,nss-dp"; + clocks = <&gcc GCC_SNOC_GMAC0_AXI_CLK>; + clock-names = "nss-snoc-gmac-axi-clk"; + qcom,id = <1>; + reg = <0x39C00000 0x10000>; + interrupts = ; + qcom,mactype = <2>; + qcom,link-poll = <1>; + qcom,phy-mdio-addr = <7>; + mdio-bus = <&mdio0>; + local-mac-address = [000000000000]; + phy-mode = "sgmii"; + }; + + qcom,test@0 { + status = "ok"; + }; + +/* + lpass: lpass@0xA000000{ + status = "disabled"; + }; + + pcm: pcm@0xA3C0000{ + pinctrl-0 = <&audio_pins>; + pinctrl-names = "default"; + status = "disabled"; + }; + + pcm_lb: pcm_lb@0 { + status = "disabled"; + }; +*/ + }; + + thermal-zones { + status = "ok"; + }; +}; + +&tlmm { + pinctrl-0 = <&blsp0_uart_pins>; //<&blsp0_uart_pins &phy_led_pins>; + pinctrl-names = "default"; + + blsp0_uart_pins: blsp0_uart_pins { + blsp0_uart_rx_tx { + pins = "gpio20", "gpio21"; + function = "blsp0_uart0"; + bias-disable; + }; + }; +/* + blsp1_uart_pins: blsp1_uart_pins { + blsp1_uart_rx_tx { + pins = "gpio23", "gpio25", "gpio24", "gpio26"; + function = "blsp1_uart2"; + bias-disable; + }; + }; +*/ + blsp0_spi_pins: blsp0_spi_pins { + mux { + pins = "gpio10", "gpio11", "gpio12", "gpio13"; + function = "blsp0_spi"; + drive-strength = <2>; + bias-disable; + }; + }; + + qspi_nand_pins: qspi_nand_pins { + qspi_clock { + pins = "gpio9"; + function = "qspi_clk"; + drive-strength = <8>; + bias-disable; + }; + + qspi_cs { + pins = "gpio8"; + function = "qspi_cs"; + drive-strength = <8>; + bias-disable; + }; + + qspi_data { + pins = "gpio4", "gpio5", "gpio6", "gpio7"; + function = "qspi_data"; + drive-strength = <8>; + bias-disable; + }; + }; + + mdio1_pins: mdio_pinmux { + mux_0 { + pins = "gpio36"; + function = "mdc"; + drive-strength = <8>; + bias-pull-up; + }; + + mux_1 { + pins = "gpio37"; + function = "mdio"; + drive-strength = <8>; + bias-pull-up; + }; + }; +/* + phy_led_pins: phy_led_pins { + gephy_led_pin { + pins = "gpio46"; + function = "led0"; + drive-strength = <8>; + bias-pull-down; + }; + }; +*/ + i2c_pins: i2c_pins { + i2c_scl { + pins = "gpio25"; + function = "blsp2_i2c1"; + drive-strength = <8>; + bias-disable; + }; + + i2c_sda { + pins = "gpio26"; + function = "blsp2_i2c1"; + drive-strength = <8>; + bias-disable; + }; + }; + + button_pins: button_pins { + reset_button { + pins = "gpio28"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + }; +/* + audio_pins: audio_pinmux { + mux_1 { + pins = "gpio24"; + function = "audio_rxbclk"; + drive-strength = <8>; + bias-pull-down; + }; + + mux_2 { + pins = "gpio25"; + function = "audio_rxfsync"; + drive-strength = <8>; + bias-pull-down; + }; + + mux_3 { + pins = "gpio26"; + function = "audio_rxd"; + drive-strength = <8>; + bias-pull-down; + }; + + mux_4 { + pins = "gpio27"; + function = "audio_txmclk"; + drive-strength = <8>; + bias-pull-down; + }; + + mux_5 { + pins = "gpio28"; + function = "audio_txbclk"; + drive-strength = <8>; + bias-pull-down; + }; + + mux_6 { + pins = "gpio29"; + function = "audio_txfsync"; + drive-strength = <8>; + bias-pull-down; + }; + + mux_7 { + pins = "gpio30"; + function = "audio_txd"; + drive-strength = <8>; + bias-pull-down; + }; + }; +*/ + poe_pins: poe_pinmux { + /* + LAN port PoE output enable + H --> enable; L --> disable (Default setting to H) + */ + mux_0 { /* PoE_OUT_EN */ + pins = "gpio24"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + output-high; + }; + + mux_1 { /* PSE_INT_N */ + pins = "gpio27"; + function = "gpio"; + bias-pull-up; + input; + }; + }; + + leds_pins: leds_pinmux { + sys_green { + pins = "gpio1"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + }; + sys_blue { + pins = "gpio30"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + sys_red { + pins = "gpio46"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + }; + }; +}; + +&soc { + gpio_keys { + compatible = "gpio-keys"; + pinctrl-0 = <&button_pins>; + pinctrl-names = "default"; + + button@1 { + label = "reset"; + linux,code = ; + gpios = <&tlmm 28 GPIO_ACTIVE_LOW>; + linux,input-type = <1>; + debounce-interval = <60>; + }; + }; + + gpio_leds { + compatible = "gpio-leds"; + pinctrl-0 = <&leds_pins>; + pinctrl-names = "default"; + + led@1 { + label = "sys:green"; + gpios = <&tlmm 1 GPIO_ACTIVE_HIGH>; /* GPIO_1/ATST_QP0 */ + default-state="off"; + }; + led@30 { + label = "sys:blue"; + gpios = <&tlmm 30 GPIO_ACTIVE_HIGH>; /* GPIO_30 */ + default-state="on"; + }; + led@46 { + label = "sys:red"; + gpios = <&tlmm 46 GPIO_ACTIVE_HIGH>; /* GPIO_46 */ + default-state="off"; + }; + }; +}; + +&q6v5_wcss { + compatible = "qcom,ipq5018-q6-mpd"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + firmware = "IPQ5018/q6_fw.mdt"; + reg = <0x0cd00000 0x4040>, + <0x1938000 0x8>, + <0x193d204 0x4>; + reg-names = "qdsp6", + "tcsr-msip", + "tcsr-q6"; + resets = <&gcc GCC_WCSSAON_RESET>, + <&gcc GCC_WCSS_Q6_BCR>; + + reset-names = "wcss_aon_reset", + "wcss_q6_reset"; + + clocks = <&gcc GCC_Q6_AXIS_CLK>, + <&gcc GCC_WCSS_ECAHB_CLK>, + <&gcc GCC_Q6_AXIM_CLK>, + <&gcc GCC_Q6_AXIM2_CLK>, + <&gcc GCC_Q6_AHB_CLK>, + <&gcc GCC_Q6_AHB_S_CLK>, + <&gcc GCC_WCSS_AXI_S_CLK>; + clock-names = "gcc_q6_axis_clk", + "gcc_wcss_ecahb_clk", + "gcc_q6_axim_clk", + "gcc_q6_axim2_clk", + "gcc_q6_ahb_clk", + "gcc_q6_ahb_s_clk", + "gcc_wcss_axi_s_clk"; + + #ifdef __IPQ_MEM_PROFILE_256_MB__ + memory-region = <&q6_mem_regions>, <&q6_etr_region>; + #else + memory-region = <&q6_mem_regions>, <&q6_etr_region>, + <&q6_caldb_region>; + #endif + + qcom,rproc = <&q6v5_wcss>; + qcom,bootargs_smem = <507>; + boot-args = <0x1 0x4 0x3 0x0F 0x0 0x0>, + <0x2 0x4 0x2 0x12 0x0 0x0>; + status = "ok"; + q6_wcss_pd1: remoteproc_pd1@4ab000 { + compatible = "qcom,ipq5018-wcss-ahb-mpd"; + reg = <0x4ab000 0x20>; + reg-names = "rmb"; + firmware = "IPQ5018/q6_fw.mdt"; + m3_firmware = "IPQ5018/m3_fw.mdt"; + interrupts-extended = <&wcss_smp2p_in 8 0>, + <&wcss_smp2p_in 9 0>, + <&wcss_smp2p_in 12 0>, + <&wcss_smp2p_in 11 0>; + interrupt-names = "fatal", + "ready", + "spawn-ack", + "stop-ack"; + + resets = <&gcc GCC_WCSSAON_RESET>, + <&gcc GCC_WCSS_BCR>, + <&gcc GCC_CE_BCR>; + reset-names = "wcss_aon_reset", + "wcss_reset", + "ce_reset"; + + clocks = <&gcc GCC_WCSS_AHB_S_CLK>, + <&gcc GCC_WCSS_ACMT_CLK>, + <&gcc GCC_WCSS_AXI_M_CLK>; + clock-names = "gcc_wcss_ahb_s_clk", + "gcc_wcss_acmt_clk", + "gcc_wcss_axi_m_clk"; + + qcom,halt-regs = <&tcsr_q6_block 0xa000 0xd000 0x0>; + + qcom,smem-states = <&wcss_smp2p_out 8>, + <&wcss_smp2p_out 9>, + <&wcss_smp2p_out 10>; + qcom,smem-state-names = "shutdown", + "stop", + "spawn"; + #ifdef __IPQ_MEM_PROFILE_256_MB__ + memory-region = <&q6_ipq5018_data>, <&m3_dump>, + <&q6_etr_region>; + #else + memory-region = <&q6_ipq5018_data>, <&m3_dump>, + <&q6_etr_region>, <&q6_caldb_region>; + #endif + + }; + + q6_wcss_pd2: remoteproc_pd2 { + compatible = "qcom,ipq5018-wcss-pcie-mpd"; + firmware = "IPQ5018/q6_fw.mdt"; + m3_firmware = "qcn6122/m3_fw.mdt"; + interrupts-extended = <&wcss_smp2p_in 16 0>, + <&wcss_smp2p_in 17 0>, + <&wcss_smp2p_in 20 0>, + <&wcss_smp2p_in 19 0>; + interrupt-names = "fatal", + "ready", + "spawn-ack", + "stop-ack"; + + qcom,smem-states = <&wcss_smp2p_out 16>, + <&wcss_smp2p_out 17>, + <&wcss_smp2p_out 18>; + qcom,smem-state-names = "shutdown", + "stop", + "spawn"; + #ifdef __IPQ_MEM_PROFILE_256_MB__ + memory-region = <&q6_qcn6122_data1>, <&m3_dump_qcn6122_1>, + <&q6_qcn6122_etr_1>; + #else + memory-region = <&q6_qcn6122_data1>, <&m3_dump_qcn6122_1>, + <&q6_qcn6122_etr_1>, <&q6_qcn6122_caldb_1>; + #endif + + }; + + q6_wcss_pd3: remoteproc_pd3 { + compatible = "qcom,ipq5018-wcss-pcie-mpd"; + firmware = "IPQ5018/q6_fw.mdt"; + interrupts-extended = <&wcss_smp2p_in 24 0>, + <&wcss_smp2p_in 25 0>, + <&wcss_smp2p_in 28 0>, + <&wcss_smp2p_in 27 0>; + interrupt-names = "fatal", + "ready", + "spawn-ack", + "stop-ack"; + + qcom,smem-states = <&wcss_smp2p_out 24>, + <&wcss_smp2p_out 25>, + <&wcss_smp2p_out 26>; + qcom,smem-state-names = "shutdown", + "stop", + "spawn"; + #ifdef __IPQ_MEM_PROFILE_256_MB__ + memory-region = <&q6_qcn6122_data2>, <&m3_dump_qcn6122_2>, + <&q6_qcn6122_etr_2>; + #else + memory-region = <&q6_qcn6122_data2>, <&m3_dump_qcn6122_2>, + <&q6_qcn6122_etr_2>, <&q6_qcn6122_caldb_2>; + #endif + }; +}; + +&i2c_0 { + pinctrl-0 = <&i2c_pins>; + pinctrl-names = "default"; + status = "ok"; +}; + +&wifi0 { + /* IPQ5018 */ + qcom,multipd_arch; + qcom,rproc = <&q6_wcss_pd1>; + qcom,userpd-subsys-name = "q6v5_wcss_userpd1"; +#ifdef __IPQ_MEM_PROFILE_256_MB__ + qcom,tgt-mem-mode = <2>; +#else + qcom,tgt-mem-mode = <1>; +#endif + qcom,board_id = <0x24>; +#ifdef __CNSS2__ + qcom,bdf-addr = <0x4C400000 0x4C400000 0x4C400000 0x0 0x0 0x0>; + qcom,caldb-addr = <0x4D300000 0x4D300000 0 0 0 0>; + qcom,caldb-size = <0x200000>; + mem-region = <&q6_ipq5018_data>; +#else + memory-region = <&q6_ipq5018_data>; +#endif + status = "ok"; +}; + +&wifi1 { + /* QCN6122 5G */ + qcom,multipd_arch; + qcom,userpd-subsys-name = "q6v5_wcss_userpd3"; + qcom,rproc = <&q6_wcss_pd3>; +#ifdef __IPQ_MEM_PROFILE_256_MB__ + qcom,tgt-mem-mode = <2>; +#else + qcom,tgt-mem-mode = <1>; +#endif + qcom,board_id = <0x60>; +#ifdef __CNSS2__ + qcom,bdf-addr = <0x4E900000 0x4E900000 0x4E200000 0x0 0x0>; + qcom,caldb-addr = <0x4F800000 0x4F800000 0 0 0>; + qcom,caldb-size = <0x500000>; + mem-region = <&q6_qcn6122_data2>; +#else + memory-region = <&q6_qcn6122_data2>; +#endif + status = "ok"; +}; + +&wifi2 { + /* QCN6122 6G */ + qcom,multipd_arch; + qcom,userpd-subsys-name = "q6v5_wcss_userpd3"; +#ifdef __IPQ_MEM_PROFILE_256_MB__ + qcom,tgt-mem-mode = <2>; +#else + qcom,tgt-mem-mode = <1>; +#endif + qcom,board_id = <0xb0>; + qcom,bdf-addr = <0x4ED00000 0x4ED00000 0x4E400000 0x0 0x0>; +#ifdef __CNSS2__ + qcom,caldb-addr = <0x4FF00000 0x4FF00000 0 0 0>; +#else + qcom,caldb-addr = <0x4FF00000>; + m3-dump-addr = <0x4FD00000>; +#endif + qcom,caldb-size = <0x500000>; + status = "disabled"; +}; + +&usb3 { + status = "ok"; + device-power-gpio = <&tlmm 24 1>; +}; + +&dwc_0 { + /delete-property/ #phy-cells; + /delete-property/ phys; + /delete-property/ phy-names; +}; + +&hs_m31phy_0 { + status = "ok"; +}; + +&eud { + status = "ok"; +}; + +&pcie_x1 { + perst-gpio = <&tlmm 18 GPIO_ACTIVE_LOW>; +}; + +&pcie_x2 { + perst-gpio = <&tlmm 15 GPIO_ACTIVE_LOW>; +}; + +&pcie_x1_rp { + status = "disabled"; + + mhi_0: qcom,mhi@0 { + reg = <0 0 0 0 0 >; + }; +}; + +&pcie_x2_rp { + status = "disabled"; + + mhi_1: qcom,mhi@1 { + reg = <0 0 0 0 0 >; + + }; +}; diff --git a/feeds/ipq807x_v5.4/ipq50xx/image/ipq50xx.mk b/feeds/ipq807x_v5.4/ipq50xx/image/ipq50xx.mk index 8f1f12edf..3e9de88a9 100644 --- a/feeds/ipq807x_v5.4/ipq50xx/image/ipq50xx.mk +++ b/feeds/ipq807x_v5.4/ipq50xx/image/ipq50xx.mk @@ -18,6 +18,28 @@ define Device/cig_wf186w endef TARGET_DEVICES += cig_wf186w +define Device/cybertan_eww631_a1 + DEVICE_TITLE := CyberTan EWW631-A1 + DEVICE_DTS := qcom-ipq5018-eww631-a1 + SUPPORTED_DEVICES := cybertan,eww631-a1 + DEVICE_PACKAGES := ath11k-wifi-cybertan-eww631-a1 ath11k-firmware-ipq50xx-spruce ath11k-firmware-qcn6122 + DEVICE_DTS_CONFIG := config@mp03.5-c1 + IMAGES := sysupgrade.tar nand-factory.bin nand-factory.ubi + IMAGE/nand-factory.ubi := append-ubi +endef +TARGET_DEVICES += cybertan_eww631_a1 + +define Device/cybertan_eww631_b1 + DEVICE_TITLE := CyberTan EWW631-B1 + DEVICE_DTS := qcom-ipq5018-eww631-b1 + SUPPORTED_DEVICES := cybertan,eww631-b1 + DEVICE_PACKAGES := ath11k-wifi-cybertan-eww631-b1 ath11k-firmware-ipq50xx-spruce ath11k-firmware-qcn6122 + DEVICE_DTS_CONFIG := config@mp03.5-c1 + IMAGES := sysupgrade.tar nand-factory.bin nand-factory.ubi + IMAGE/nand-factory.ubi := append-ubi +endef +TARGET_DEVICES += cybertan_eww631_b1 + define Device/edgecore_eap104 DEVICE_TITLE := EdgeCore EAP104 DEVICE_DTS := qcom-ipq5018-eap104 diff --git a/feeds/ipq807x_v5.4/ipq50xx/patches/301-diag_char.patch b/feeds/ipq807x_v5.4/ipq50xx/patches/301-diag_char.patch new file mode 100644 index 000000000..2e3642e05 --- /dev/null +++ b/feeds/ipq807x_v5.4/ipq50xx/patches/301-diag_char.patch @@ -0,0 +1,54 @@ +Index: linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/drivers/char/diag/diagchar_core.c +=================================================================== +--- linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d.orig/drivers/char/diag/diagchar_core.c ++++ linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/drivers/char/diag/diagchar_core.c +@@ -763,11 +763,6 @@ static void diag_cmd_invalidate_polling( + driver->polling_reg_flag = 0; + list_for_each_safe(start, temp, &driver->cmd_reg_list) { + item = list_entry(start, struct diag_cmd_reg_t, link); +- if (&item->entry == NULL) { +- pr_err("diag: In %s, unable to search command\n", +- __func__); +- return; +- } + polling = diag_cmd_chk_polling(&item->entry); + if (polling == DIAG_CMD_POLLING) { + driver->polling_reg_flag = 1; +@@ -829,11 +824,6 @@ struct diag_cmd_reg_entry_t *diag_cmd_se + + list_for_each_safe(start, temp, &driver->cmd_reg_list) { + item = list_entry(start, struct diag_cmd_reg_t, link); +- if (&item->entry == NULL) { +- pr_err("diag: In %s, unable to search command\n", +- __func__); +- return NULL; +- } + temp_entry = &item->entry; + if (temp_entry->cmd_code == entry->cmd_code && + temp_entry->subsys_id == entry->subsys_id && +@@ -907,12 +897,6 @@ void diag_cmd_remove_reg_by_pid(int pid) + mutex_lock(&driver->cmd_reg_mutex); + list_for_each_safe(start, temp, &driver->cmd_reg_list) { + item = list_entry(start, struct diag_cmd_reg_t, link); +- if (&item->entry == NULL) { +- pr_err("diag: In %s, unable to search command\n", +- __func__); +- mutex_unlock(&driver->cmd_reg_mutex); +- return; +- } + if (item->pid == pid) { + list_del(&item->link); + kfree(item); +@@ -931,12 +915,6 @@ void diag_cmd_remove_reg_by_proc(int pro + mutex_lock(&driver->cmd_reg_mutex); + list_for_each_safe(start, temp, &driver->cmd_reg_list) { + item = list_entry(start, struct diag_cmd_reg_t, link); +- if (&item->entry == NULL) { +- pr_err("diag: In %s, unable to search command\n", +- __func__); +- mutex_unlock(&driver->cmd_reg_mutex); +- return; +- } + if (item->proc == proc) { + list_del(&item->link); + kfree(item); diff --git a/feeds/ipq807x_v5.4/ipq50xx/patches/400-NAND-MX35UF2GE4AD-ECC-8BIT.patch b/feeds/ipq807x_v5.4/ipq50xx/patches/400-NAND-MX35UF2GE4AD-ECC-8BIT.patch new file mode 100644 index 000000000..109cfa348 --- /dev/null +++ b/feeds/ipq807x_v5.4/ipq50xx/patches/400-NAND-MX35UF2GE4AD-ECC-8BIT.patch @@ -0,0 +1,16 @@ +Index: linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d.orig/mtd/nand/raw/nand_ids.c +=================================================================== +--- linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d.orig/drivers/mtd/nand/raw/nand_ids.c ++++ linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/drivers/mtd/nand/raw/nand_ids.c +@@ -79,9 +79,9 @@ + { .id = {0xc2, 0xb7} }, + SZ_4K, SZ_512, SZ_256K, 0, 2, 256, NAND_ECC_INFO(8, SZ_512), 0}, + +- {"MX35UF2GE4AD-Z4I SPI NAND 2G 1.8V", ++ {"MX35UF2GE4AD-Z4I SPI NAND 2G 1.8V 8-bit", + { .id = {0xc2, 0xa6} }, +- SZ_2K, SZ_128, SZ_128K, 0, 2, 160, NAND_ECC_INFO(4, SZ_512), 0 }, ++ SZ_2K, SZ_256, SZ_128K, 0, 2, 128, NAND_ECC_INFO(8, SZ_512), 0 }, + + {"GD5F1GQ5REYIH SPI NAND 1G 1.8V", + { .id = {0xc8, 0x21} }, diff --git a/feeds/ipq807x_v5.4/ipq60xx/base-files/etc/hotplug.d/firmware/10-ath11k-caldata b/feeds/ipq807x_v5.4/ipq60xx/base-files/etc/hotplug.d/firmware/10-ath11k-caldata index 8feb7387a..f7c4a1a67 100755 --- a/feeds/ipq807x_v5.4/ipq60xx/base-files/etc/hotplug.d/firmware/10-ath11k-caldata +++ b/feeds/ipq807x_v5.4/ipq60xx/base-files/etc/hotplug.d/firmware/10-ath11k-caldata @@ -1,5 +1,4 @@ #!/bin/sh - [ -e /lib/firmware/$FIRMWARE ] && exit 0 . /lib/functions.sh @@ -98,6 +97,18 @@ ath11k-macs) ;; esac ;; +ath11k/IPQ6018/hw1.0/board.bin) + case "$board" in + cig,wf188n) + country=`cat /etc/ucentral/country` + if [ "$country" == "CA" ]; then + ln -s /lib/firmware/ath11k/IPQ6018/hw1.0/board.bin.CA /lib/firmware/ath11k/IPQ6018/hw1.0/board.bin + else + ln -s /lib/firmware/ath11k/IPQ6018/hw1.0/board.bin.US /lib/firmware/ath11k/IPQ6018/hw1.0/board.bin + fi + ;; + esac + ;; *) exit 1 ;; diff --git a/feeds/ipq807x_v5.4/ipq60xx/base-files/etc/init.d/bootcount b/feeds/ipq807x_v5.4/ipq60xx/base-files/etc/init.d/bootcount index c93c30060..b0f1f03bb 100755 --- a/feeds/ipq807x_v5.4/ipq60xx/base-files/etc/init.d/bootcount +++ b/feeds/ipq807x_v5.4/ipq60xx/base-files/etc/init.d/bootcount @@ -10,7 +10,8 @@ boot() { ;; edgecore,eap101|\ edgecore,eap102|\ - edgecore,oap102) + edgecore,oap102|\ + edgecore.eap104) avail=$(fw_printenv -n upgrade_available) [ ${avail} -eq 0 ] && fw_setenv upgrade_available 1 fw_setenv bootcount 0 diff --git a/feeds/ipq807x_v5.4/ipq60xx/base-files/lib/upgrade/nand.sh b/feeds/ipq807x_v5.4/ipq60xx/base-files/lib/upgrade/nand.sh index 41a2de529..e8f10668d 100644 --- a/feeds/ipq807x_v5.4/ipq60xx/base-files/lib/upgrade/nand.sh +++ b/feeds/ipq807x_v5.4/ipq60xx/base-files/lib/upgrade/nand.sh @@ -247,8 +247,8 @@ nand_do_upgrade_success() { local conf_tar="/tmp/sysupgrade.tgz" sync [ "$CI_BOOTCFG" = 1 ] && nand_qca_update_bootconfig + [ -f "$conf_tar" ] && nand_restore_config "$conf_tar" && sync [ -n "$CI_FWSETENV" ] && fw_setenv $CI_FWSETENV - [ -f "$conf_tar" ] && nand_restore_config "$conf_tar" echo "sysupgrade successful" umount -a reboot -f diff --git a/feeds/ipq807x_v5.4/ipq60xx/base-files/lib/upgrade/platform.sh b/feeds/ipq807x_v5.4/ipq60xx/base-files/lib/upgrade/platform.sh index cd0a59bd2..ecf141df1 100755 --- a/feeds/ipq807x_v5.4/ipq60xx/base-files/lib/upgrade/platform.sh +++ b/feeds/ipq807x_v5.4/ipq60xx/base-files/lib/upgrade/platform.sh @@ -122,10 +122,10 @@ platform_do_upgrade() { else if grep -q rootfs1 /proc/cmdline; then CI_UBIPART="rootfs2" - fw_setenv active 2 || exit 1 + CI_FWSETENV="active 2" else CI_UBIPART="rootfs1" - fw_setenv active 1 || exit 1 + CI_FWSETENV="active 1" fi fi nand_upgrade_tar "$1" diff --git a/feeds/ipq807x_v5.4/ipq60xx/image/ipq60xx.mk b/feeds/ipq807x_v5.4/ipq60xx/image/ipq60xx.mk index c35e6adb8..a8a29ccaf 100644 --- a/feeds/ipq807x_v5.4/ipq60xx/image/ipq60xx.mk +++ b/feeds/ipq807x_v5.4/ipq60xx/image/ipq60xx.mk @@ -2,23 +2,14 @@ KERNEL_LOADADDR := 0x41080000 DEVICE_VARS += CE_TYPE -define Device/cig_wf188n-ca +define Device/cig_wf188n DEVICE_TITLE := Cigtech WF-188n DEVICE_DTS := qcom-ipq6018-cig-wf188n DEVICE_DTS_CONFIG := config@cp03-c1 SUPPORTED_DEVICES := cig,wf188n - DEVICE_PACKAGES := ath11k-wifi-cig-wf188n-ca uboot-env + DEVICE_PACKAGES := ath11k-wifi-cig-wf188n uboot-env endef -TARGET_DEVICES += cig_wf188n-ca - -define Device/cig_wf188n-us - DEVICE_TITLE := Cigtech WF-188n - DEVICE_DTS := qcom-ipq6018-cig-wf188n - DEVICE_DTS_CONFIG := config@cp03-c1 - SUPPORTED_DEVICES := cig,wf188n - DEVICE_PACKAGES := ath11k-wifi-cig-wf188n-us uboot-env -endef -TARGET_DEVICES += cig_wf188n-us +TARGET_DEVICES += cig_wf188n define Device/hfcl_ion4xe DEVICE_TITLE := HFCL ION4Xe @@ -101,14 +92,14 @@ define Device/wallys_dr6018 endef TARGET_DEVICES += wallys_dr6018 -define Device/wallys_dr6018_v4 +define Device/wallys_dr6018-v4 DEVICE_TITLE := Wallys DR6018 V4 DEVICE_DTS := qcom-ipq6018-wallys-dr6018-v4 DEVICE_DTS_CONFIG := config@cp01-c4 SUPPORTED_DEVICES := wallys,dr6018-v4 DEVICE_PACKAGES := ath11k-wifi-wallys-dr6018-v4 uboot-envtools ath11k-firmware-qcn9000 endef -TARGET_DEVICES += wallys_dr6018_v4 +TARGET_DEVICES += wallys_dr6018-v4 define Device/glinet_ax1800 DEVICE_TITLE := GL-iNet AX1800 diff --git a/feeds/ipq807x_v5.4/ipq60xx/patches/301-diag_char.patch b/feeds/ipq807x_v5.4/ipq60xx/patches/301-diag_char.patch new file mode 100644 index 000000000..2e3642e05 --- /dev/null +++ b/feeds/ipq807x_v5.4/ipq60xx/patches/301-diag_char.patch @@ -0,0 +1,54 @@ +Index: linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/drivers/char/diag/diagchar_core.c +=================================================================== +--- linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d.orig/drivers/char/diag/diagchar_core.c ++++ linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/drivers/char/diag/diagchar_core.c +@@ -763,11 +763,6 @@ static void diag_cmd_invalidate_polling( + driver->polling_reg_flag = 0; + list_for_each_safe(start, temp, &driver->cmd_reg_list) { + item = list_entry(start, struct diag_cmd_reg_t, link); +- if (&item->entry == NULL) { +- pr_err("diag: In %s, unable to search command\n", +- __func__); +- return; +- } + polling = diag_cmd_chk_polling(&item->entry); + if (polling == DIAG_CMD_POLLING) { + driver->polling_reg_flag = 1; +@@ -829,11 +824,6 @@ struct diag_cmd_reg_entry_t *diag_cmd_se + + list_for_each_safe(start, temp, &driver->cmd_reg_list) { + item = list_entry(start, struct diag_cmd_reg_t, link); +- if (&item->entry == NULL) { +- pr_err("diag: In %s, unable to search command\n", +- __func__); +- return NULL; +- } + temp_entry = &item->entry; + if (temp_entry->cmd_code == entry->cmd_code && + temp_entry->subsys_id == entry->subsys_id && +@@ -907,12 +897,6 @@ void diag_cmd_remove_reg_by_pid(int pid) + mutex_lock(&driver->cmd_reg_mutex); + list_for_each_safe(start, temp, &driver->cmd_reg_list) { + item = list_entry(start, struct diag_cmd_reg_t, link); +- if (&item->entry == NULL) { +- pr_err("diag: In %s, unable to search command\n", +- __func__); +- mutex_unlock(&driver->cmd_reg_mutex); +- return; +- } + if (item->pid == pid) { + list_del(&item->link); + kfree(item); +@@ -931,12 +915,6 @@ void diag_cmd_remove_reg_by_proc(int pro + mutex_lock(&driver->cmd_reg_mutex); + list_for_each_safe(start, temp, &driver->cmd_reg_list) { + item = list_entry(start, struct diag_cmd_reg_t, link); +- if (&item->entry == NULL) { +- pr_err("diag: In %s, unable to search command\n", +- __func__); +- mutex_unlock(&driver->cmd_reg_mutex); +- return; +- } + if (item->proc == proc) { + list_del(&item->link); + kfree(item); diff --git a/feeds/ipq807x_v5.4/ipq807x/base-files/etc/board.d/01_leds b/feeds/ipq807x_v5.4/ipq807x/base-files/etc/board.d/01_leds index 765f000ba..1d0f1aad7 100755 --- a/feeds/ipq807x_v5.4/ipq807x/base-files/etc/board.d/01_leds +++ b/feeds/ipq807x_v5.4/ipq807x/base-files/etc/board.d/01_leds @@ -18,6 +18,9 @@ edgecore,oap102) ucidef_set_led_wlan "wlan5g" "WLAN5G" "green:wifi5" "phy0tpt" ucidef_set_led_wlan "wlan2g" "WLAN2G" "green:wifi2" "phy1tpt" ;; +cybertan,eww631-b1) + ucidef_set_led_default "power" "POWER" "sys:blue" "on" + ;; esac board_config_flush diff --git a/feeds/ipq807x_v5.4/ipq807x/base-files/etc/hotplug.d/firmware/10-ath11k-caldata b/feeds/ipq807x_v5.4/ipq807x/base-files/etc/hotplug.d/firmware/10-ath11k-caldata index 3e5a2a243..8140771ee 100755 --- a/feeds/ipq807x_v5.4/ipq807x/base-files/etc/hotplug.d/firmware/10-ath11k-caldata +++ b/feeds/ipq807x_v5.4/ipq807x/base-files/etc/hotplug.d/firmware/10-ath11k-caldata @@ -16,9 +16,9 @@ ath11k_generate_macs() { echo -ne \\x${mac3//:/\\x} >> /lib/firmware/ath11k-macs } -ath11k_generate_macs_wf194() { +ath11k_generate_macs_wf196() { touch /lib/firmware/ath11k-macs - mac=$(grep BaseMacAddress= /dev/mtd14 | cut -dx -f2) + mac=$(grep BaseMacAddress= /dev/mtd18 | cut -dx -f2) eth=$(macaddr_canonicalize $mac) mac1=$(macaddr_add $eth 2) mac2=$(macaddr_add $eth 3) @@ -92,8 +92,32 @@ ath11k-macs) edgecore,eap106) ath11k_generate_macs ;; - cig,wf194c) - ath11k_generate_macs_wf194 + cig,wf196) + ath11k_generate_macs_wf196 + ;; + esac + ;; +ath11k/IPQ8074/hw2.0/board.bin) + case "$board" in + cig,wf196) + country=`cat /etc/ucentral/country` + if [ "$country" == "CA" ]; then + ln -s /lib/firmware/ath11k/IPQ8074/hw2.0/board.bin.CA /lib/firmware/ath11k/IPQ8074/hw2.0/board.bin + else + ln -s /lib/firmware/ath11k/IPQ8074/hw2.0/board.bin.US /lib/firmware/ath11k/IPQ8074/hw2.0/board.bin + fi + ;; + esac + ;; +ath11k/QCN9074/hw1.0/board.bin) + case "$board" in + cig,wf196) + country=`cat /etc/ucentral/country` + if [ "$country" == "CA" ]; then + ln -s /lib/firmware/ath11k/QCN9074/hw1.0/board.bin.CA /lib/firmware/ath11k/QCN9074/hw1.0/board.bin + else + ln -s /lib/firmware/ath11k/QCN9074/hw1.0/board.bin.US /lib/firmware/ath11k/QCN9074/hw1.0/board.bin + fi ;; esac ;; diff --git a/feeds/ipq807x_v5.4/ipq807x/base-files/etc/init.d/bootcount b/feeds/ipq807x_v5.4/ipq807x/base-files/etc/init.d/bootcount index c93c30060..b0f1f03bb 100755 --- a/feeds/ipq807x_v5.4/ipq807x/base-files/etc/init.d/bootcount +++ b/feeds/ipq807x_v5.4/ipq807x/base-files/etc/init.d/bootcount @@ -10,7 +10,8 @@ boot() { ;; edgecore,eap101|\ edgecore,eap102|\ - edgecore,oap102) + edgecore,oap102|\ + edgecore.eap104) avail=$(fw_printenv -n upgrade_available) [ ${avail} -eq 0 ] && fw_setenv upgrade_available 1 fw_setenv bootcount 0 diff --git a/feeds/ipq807x_v5.4/ipq807x/base-files/lib/upgrade/nand.sh b/feeds/ipq807x_v5.4/ipq807x/base-files/lib/upgrade/nand.sh index 41a2de529..e8f10668d 100644 --- a/feeds/ipq807x_v5.4/ipq807x/base-files/lib/upgrade/nand.sh +++ b/feeds/ipq807x_v5.4/ipq807x/base-files/lib/upgrade/nand.sh @@ -247,8 +247,8 @@ nand_do_upgrade_success() { local conf_tar="/tmp/sysupgrade.tgz" sync [ "$CI_BOOTCFG" = 1 ] && nand_qca_update_bootconfig + [ -f "$conf_tar" ] && nand_restore_config "$conf_tar" && sync [ -n "$CI_FWSETENV" ] && fw_setenv $CI_FWSETENV - [ -f "$conf_tar" ] && nand_restore_config "$conf_tar" echo "sysupgrade successful" umount -a reboot -f diff --git a/feeds/ipq807x_v5.4/ipq807x/base-files/lib/upgrade/platform.sh b/feeds/ipq807x_v5.4/ipq807x/base-files/lib/upgrade/platform.sh index 777c44196..4f4585f62 100755 --- a/feeds/ipq807x_v5.4/ipq807x/base-files/lib/upgrade/platform.sh +++ b/feeds/ipq807x_v5.4/ipq807x/base-files/lib/upgrade/platform.sh @@ -61,12 +61,16 @@ platform_do_upgrade() { if [ "$(find_mtd_chardev rootfs)" ]; then CI_UBIPART="rootfs" else - if grep -q rootfs1 /proc/cmdline; then + if [ -e /tmp/downgrade ]; then + CI_UBIPART="rootfs1" + { echo 'active 1'; echo 'upgrade_available 0'; } > /tmp/fw_setenv.txt || exit 1 + CI_FWSETENV="-s /tmp/fw_setenv.txt" + elif grep -q rootfs1 /proc/cmdline; then CI_UBIPART="rootfs2" - fw_setenv active 2 || exit 1 + CI_FWSETENV="active 2" else CI_UBIPART="rootfs1" - fw_setenv active 1 || exit 1 + CI_FWSETENV="active 1" fi fi nand_upgrade_tar "$1" diff --git a/feeds/ipq807x_v5.4/ipq807x/files/arch/arm64/boot/dts/qcom/qcom-ipq807x-eap102.dts b/feeds/ipq807x_v5.4/ipq807x/files/arch/arm64/boot/dts/qcom/qcom-ipq807x-eap102.dts index 04382d999..f529c693d 100644 --- a/feeds/ipq807x_v5.4/ipq807x/files/arch/arm64/boot/dts/qcom/qcom-ipq807x-eap102.dts +++ b/feeds/ipq807x_v5.4/ipq807x/files/arch/arm64/boot/dts/qcom/qcom-ipq807x-eap102.dts @@ -29,8 +29,79 @@ stdout-path = "serial0"; }; + gpio-export { + compatible = "gpio-export"; + #size-cells = <0>; + + mcu-enable { + gpio-export,name = "mcu-enable"; + gpio-export,output = <0>; + gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; + }; + + usb-hub-enable { + gpio-export,name = "usb-hub-enable"; + gpio-export,output = <1>; + gpios = <&tlmm 55 GPIO_ACTIVE_HIGH>; + }; + + usb-rear-power { + gpio-export,name = "usb-rear-power"; + gpio-export,output = <1>; + gpios = <&tlmm 29 GPIO_ACTIVE_HIGH>; + }; + + usb-side-power { + gpio-export,name = "usb-side-power"; + gpio-export,output = <1>; + gpios = <&tlmm 30 GPIO_ACTIVE_HIGH>; + }; + }; + soc { pinctrl@1000000 { + pinctrl-0 = <&mcu_rst &mcu_rsv &usb_rear_pwr &usb_side_pwr &usb_hub_rst>; + pinctrl-names = "default"; + + mcu_rst: mcu_rst_pins { + pins = "gpio54"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + output-low; + }; + + mcu_rsv: mcu_rsv_pins { + pins = "gpio56"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + }; + + usb_rear_pwr: usb_rear_pwr_pins { + pins = "gpio29"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + output-high; + }; + + usb_side_pwr: usb_side_pwr_pins { + pins = "gpio30"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + output-high; + }; + + usb_hub_rst: usb_hub_rst_pins { + pins = "gpio55"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + output-high; + }; + button_pins: button_pins { reset_button { pins = "gpio66"; @@ -40,30 +111,6 @@ }; }; - usb_mux_sel_pins: usb_mux_pins { - mux { - pins = "gpio27"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - }; - - pcie0_pins: pcie_pins { - pcie0_rst { - pins = "gpio58"; - function = "pcie0_rst"; - drive-strength = <8>; - bias-pull-down; - }; - pcie0_wake { - pins = "gpio59"; - function = "pcie0_wake"; - drive-strength = <8>; - bias-pull-down; - }; - }; - mdio_pins: mdio_pinmux { mux_0 { pins = "gpio68"; @@ -170,19 +217,6 @@ status = "ok"; }; - phy@84000 { - status = "ok"; - }; - - phy@86000 { - status = "ok"; - }; - - pci@20000000 { - perst-gpio = <&tlmm 58 1>; - status = "ok"; - }; - gpio_keys { compatible = "gpio-keys"; pinctrl-0 = <&button_pins>; diff --git a/feeds/ipq807x_v5.4/ipq807x/files/arch/arm64/boot/dts/qcom/qcom-ipq807x-oap102.dts b/feeds/ipq807x_v5.4/ipq807x/files/arch/arm64/boot/dts/qcom/qcom-ipq807x-oap102.dts index 97c3b6b05..ef78cdf15 100644 --- a/feeds/ipq807x_v5.4/ipq807x/files/arch/arm64/boot/dts/qcom/qcom-ipq807x-oap102.dts +++ b/feeds/ipq807x_v5.4/ipq807x/files/arch/arm64/boot/dts/qcom/qcom-ipq807x-oap102.dts @@ -29,8 +29,79 @@ stdout-path = "serial0"; }; + gpio-export { + compatible = "gpio-export"; + #size-cells = <0>; + + mcu-enable { + gpio-export,name = "mcu-enable"; + gpio-export,output = <0>; + gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; + }; + + usb-hub-enable { + gpio-export,name = "usb-hub-enable"; + gpio-export,output = <1>; + gpios = <&tlmm 55 GPIO_ACTIVE_HIGH>; + }; + + usb-rear-power { + gpio-export,name = "usb-rear-power"; + gpio-export,output = <1>; + gpios = <&tlmm 29 GPIO_ACTIVE_HIGH>; + }; + + usb-side-power { + gpio-export,name = "usb-side-power"; + gpio-export,output = <1>; + gpios = <&tlmm 30 GPIO_ACTIVE_HIGH>; + }; + }; + soc { pinctrl@1000000 { + pinctrl-0 = <&mcu_rst &mcu_rsv &usb_rear_pwr &usb_side_pwr &usb_hub_rst>; + pinctrl-names = "default"; + + mcu_rst: mcu_rst_pins { + pins = "gpio54"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + output-low; + }; + + mcu_rsv: mcu_rsv_pins { + pins = "gpio56"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + }; + + usb_rear_pwr: usb_rear_pwr_pins { + pins = "gpio29"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + output-high; + }; + + usb_side_pwr: usb_side_pwr_pins { + pins = "gpio30"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + output-high; + }; + + usb_hub_rst: usb_hub_rst_pins { + pins = "gpio55"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + output-high; + }; + button_pins: button_pins { reset_button { pins = "gpio66"; @@ -40,30 +111,6 @@ }; }; - usb_mux_sel_pins: usb_mux_pins { - mux { - pins = "gpio27"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - }; - - pcie0_pins: pcie_pins { - pcie0_rst { - pins = "gpio58"; - function = "pcie0_rst"; - drive-strength = <8>; - bias-pull-down; - }; - pcie0_wake { - pins = "gpio59"; - function = "pcie0_wake"; - drive-strength = <8>; - bias-pull-down; - }; - }; - mdio_pins: mdio_pinmux { mux_0 { pins = "gpio68"; @@ -170,19 +217,6 @@ status = "ok"; }; - phy@84000 { - status = "ok"; - }; - - phy@86000 { - status = "ok"; - }; - - pci@20000000 { - perst-gpio = <&tlmm 58 1>; - status = "ok"; - }; - gpio_keys { compatible = "gpio-keys"; pinctrl-0 = <&button_pins>; diff --git a/feeds/ipq807x_v5.4/ipq807x/files/arch/arm64/boot/dts/qcom/qcom-ipq807x-wf196.dts b/feeds/ipq807x_v5.4/ipq807x/files/arch/arm64/boot/dts/qcom/qcom-ipq807x-wf196.dts index eb1f2a6ca..6bccaa97c 100644 --- a/feeds/ipq807x_v5.4/ipq807x/files/arch/arm64/boot/dts/qcom/qcom-ipq807x-wf196.dts +++ b/feeds/ipq807x_v5.4/ipq807x/files/arch/arm64/boot/dts/qcom/qcom-ipq807x-wf196.dts @@ -16,6 +16,7 @@ aliases { serial0 = &blsp1_uart5; + serial1 = &blsp1_uart3; /* Aliases as required by u-boot to patch MAC addresses */ ethernet0 = "/soc/dp1"; ethernet1 = "/soc/dp2"; @@ -29,6 +30,17 @@ stdout-path = "serial0"; }; + gpio-export { + compatible = "gpio-export"; + #size-cells = <0>; + + mcu-enable { + gpio-export,name = "mcu-enable"; + gpio-export,output = <0>; + gpios = <&tlmm 34 GPIO_ACTIVE_HIGH>; + }; + }; + reserved-memory { /* No Pine attach in 256M profile */ #if !defined(__IPQ_MEM_PROFILE_256_MB__) @@ -130,6 +142,26 @@ soc { pinctrl@1000000 { + pinctrl-0 = <&mcu_rst>; + pinctrl-names = "default"; + + mcu_rst: mcu_rst_pins { + pins = "gpio34"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + output-low; + }; + + mcu_uart: mcu_uart_pins { + mux { + pins = "gpio48", "gpio49"; + function = "blsp2_uart"; + drive-strength = <8>; + bias-disable; + }; + }; + button_pins: button_pins { wps_button { pins = "gpio67"; @@ -688,6 +720,12 @@ }; }; +&blsp1_uart3 { + pinctrl-0 = <&mcu_uart>; + pinctrl-names = "default"; + status = "ok"; +}; + &npu_cpr { status = "disabled"; }; diff --git a/feeds/ipq807x_v5.4/ipq807x/image/ipq807x.mk b/feeds/ipq807x_v5.4/ipq807x/image/ipq807x.mk index 41eb1e371..3bc6fdd2a 100644 --- a/feeds/ipq807x_v5.4/ipq807x/image/ipq807x.mk +++ b/feeds/ipq807x_v5.4/ipq807x/image/ipq807x.mk @@ -9,29 +9,17 @@ define Device/cig_wf194c4 endef TARGET_DEVICES += cig_wf194c4 -define Device/cig_wf196_us +define Device/cig_wf196 DEVICE_TITLE := CIG WF196 DEVICE_DTS := qcom-ipq807x-wf196 DEVICE_DTS_CONFIG=config@hk14 SUPPORTED_DEVICES := cig,wf196 BLOCKSIZE := 256k PAGESIZE := 4096 - DEVICE_PACKAGES := ath11k-wifi-cig-wf196-us aq-fw-download uboot-envtools kmod-usb3 kmod-usb2 \ - ath11k-firmware-qcn9000 ath11k-wifi-cig-wf196_6g-us + DEVICE_PACKAGES := ath11k-wifi-cig-wf196 aq-fw-download uboot-envtools kmod-usb3 kmod-usb2 \ + ath11k-firmware-qcn9000 endef -TARGET_DEVICES += cig_wf196_us - -define Device/cig_wf196_ca - DEVICE_TITLE := CIG WF196 - DEVICE_DTS := qcom-ipq807x-wf196 - DEVICE_DTS_CONFIG=config@hk14 - SUPPORTED_DEVICES := cig,wf196 - BLOCKSIZE := 256k - PAGESIZE := 4096 - DEVICE_PACKAGES := ath11k-wifi-cig-wf196-ca aq-fw-download uboot-envtools kmod-usb3 kmod-usb2 \ - ath11k-firmware-qcn9000 ath11k-wifi-cig-wf196_6g-ca -endef -TARGET_DEVICES += cig_wf196_ca +TARGET_DEVICES += cig_wf196 define Device/edgecore_eap102 DEVICE_TITLE := Edgecore EAP102 diff --git a/feeds/ipq807x_v5.4/ipq807x/patches/301-diag_char.patch b/feeds/ipq807x_v5.4/ipq807x/patches/301-diag_char.patch new file mode 100644 index 000000000..2e3642e05 --- /dev/null +++ b/feeds/ipq807x_v5.4/ipq807x/patches/301-diag_char.patch @@ -0,0 +1,54 @@ +Index: linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/drivers/char/diag/diagchar_core.c +=================================================================== +--- linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d.orig/drivers/char/diag/diagchar_core.c ++++ linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/drivers/char/diag/diagchar_core.c +@@ -763,11 +763,6 @@ static void diag_cmd_invalidate_polling( + driver->polling_reg_flag = 0; + list_for_each_safe(start, temp, &driver->cmd_reg_list) { + item = list_entry(start, struct diag_cmd_reg_t, link); +- if (&item->entry == NULL) { +- pr_err("diag: In %s, unable to search command\n", +- __func__); +- return; +- } + polling = diag_cmd_chk_polling(&item->entry); + if (polling == DIAG_CMD_POLLING) { + driver->polling_reg_flag = 1; +@@ -829,11 +824,6 @@ struct diag_cmd_reg_entry_t *diag_cmd_se + + list_for_each_safe(start, temp, &driver->cmd_reg_list) { + item = list_entry(start, struct diag_cmd_reg_t, link); +- if (&item->entry == NULL) { +- pr_err("diag: In %s, unable to search command\n", +- __func__); +- return NULL; +- } + temp_entry = &item->entry; + if (temp_entry->cmd_code == entry->cmd_code && + temp_entry->subsys_id == entry->subsys_id && +@@ -907,12 +897,6 @@ void diag_cmd_remove_reg_by_pid(int pid) + mutex_lock(&driver->cmd_reg_mutex); + list_for_each_safe(start, temp, &driver->cmd_reg_list) { + item = list_entry(start, struct diag_cmd_reg_t, link); +- if (&item->entry == NULL) { +- pr_err("diag: In %s, unable to search command\n", +- __func__); +- mutex_unlock(&driver->cmd_reg_mutex); +- return; +- } + if (item->pid == pid) { + list_del(&item->link); + kfree(item); +@@ -931,12 +915,6 @@ void diag_cmd_remove_reg_by_proc(int pro + mutex_lock(&driver->cmd_reg_mutex); + list_for_each_safe(start, temp, &driver->cmd_reg_list) { + item = list_entry(start, struct diag_cmd_reg_t, link); +- if (&item->entry == NULL) { +- pr_err("diag: In %s, unable to search command\n", +- __func__); +- mutex_unlock(&driver->cmd_reg_mutex); +- return; +- } + if (item->proc == proc) { + list_del(&item->link); + kfree(item); diff --git a/feeds/ipq807x_v5.4/libtcmd/patches/100-compile.patch b/feeds/ipq807x_v5.4/libtcmd/patches/100-compile.patch new file mode 100644 index 000000000..861c3d524 --- /dev/null +++ b/feeds/ipq807x_v5.4/libtcmd/patches/100-compile.patch @@ -0,0 +1,27 @@ +Index: libtcmd-11.5/libtcmd.h +=================================================================== +--- libtcmd-11.5.orig/libtcmd.h ++++ libtcmd-11.5/libtcmd.h +@@ -71,7 +71,9 @@ struct tcmd_cfg { + struct sigevent sev; + timer_t timer; + bool timeout; +-} tcmd_cfg; ++}; ++ ++extern struct tcmd_cfg tcmd_cfg; + + /* WLAN API */ + #ifdef WLAN_API_NL80211 +Index: libtcmd-11.5/nl80211.c +=================================================================== +--- libtcmd-11.5.orig/nl80211.c ++++ libtcmd-11.5/nl80211.c +@@ -23,6 +23,7 @@ + #endif + + int cb_ret; ++struct tcmd_cfg tcmd_cfg; + + #ifdef LIBNL_2 + static inline struct nl_sock *nl_handle_alloc(void) diff --git a/feeds/ipq807x_v5.4/mac80211/patches/pending/315-set_6G_txpower_via_iw.patch b/feeds/ipq807x_v5.4/mac80211/patches/pending/315-set_6G_txpower_via_iw.patch new file mode 100644 index 000000000..12de85ff0 --- /dev/null +++ b/feeds/ipq807x_v5.4/mac80211/patches/pending/315-set_6G_txpower_via_iw.patch @@ -0,0 +1,58 @@ +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -786,6 +786,7 @@ struct ath11k { + u32 max_tx_power; + u32 txpower_limit_2g; + u32 txpower_limit_5g; ++ u32 txpower_limit_6g; + u32 txpower_scale; + u32 power_scale; + u32 chan_tx_pwr; +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -633,6 +633,7 @@ static void ath11k_pdev_caps_update(stru + + ar->txpower_limit_2g = ar->max_tx_power; + ar->txpower_limit_5g = ar->max_tx_power; ++ ar->txpower_limit_6g = ar->max_tx_power; + ar->txpower_scale = WMI_HOST_TP_SCALE_MAX; + } + +@@ -803,6 +804,16 @@ static int ath11k_mac_txpower_recalc(str + ar->txpower_limit_5g = txpower; + } + ++ if ((ar->hw->wiphy->bands[NL80211_BAND_6GHZ]) && ++ ar->txpower_limit_6g != txpower) { ++ param = WMI_PDEV_PARAM_TXPOWER_LIMIT5G; ++ ret = ath11k_wmi_pdev_set_param(ar, param, ++ txpower, ar->pdev->pdev_id); ++ if (ret) ++ goto fail; ++ ar->txpower_limit_6g = txpower; ++ } ++ + return 0; + + fail: +@@ -3542,18 +3553,8 @@ static void ath11k_mac_op_bss_info_chang + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev_id %i txpower %d\n", + arvif->vdev_id, info->txpower); + +- if (ar->supports_6ghz && info->chandef.chan && +- info->chandef.chan->band == NL80211_BAND_6GHZ && +- (arvif->vdev_type == WMI_VDEV_TYPE_STA || +- arvif->vdev_type == WMI_VDEV_TYPE_AP) && +- test_bit(WMI_TLV_SERVICE_EXT_TPC_REG_SUPPORT, +- ar->ab->wmi_ab.svc_map)) { +- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, +- "discard tx power, change to set TPC power\n"); +- } else { +- arvif->txpower = info->txpower; +- ath11k_mac_txpower_recalc(ar); +- } ++ arvif->txpower = info->txpower; ++ ath11k_mac_txpower_recalc(ar); + } + + if (changed & BSS_CHANGED_MCAST_RATE && diff --git a/feeds/ipq807x_v5.4/qca-diag/Makefile b/feeds/ipq807x_v5.4/qca-diag/Makefile index 7cc9cb1e4..b3718fd30 100755 --- a/feeds/ipq807x_v5.4/qca-diag/Makefile +++ b/feeds/ipq807x_v5.4/qca-diag/Makefile @@ -29,7 +29,6 @@ define Package/qca-diag/Description stack. endef - QCASSDK_CONFIG_OPTS+= TOOL_PATH=$(TOOLCHAIN_DIR)/bin/ \ SYS_PATH=$(LINUX_DIR) \ TOOLPREFIX=$(TARGET_CROSS) \ diff --git a/feeds/ipq807x_v5.4/qca-diag/src/Makefile b/feeds/ipq807x_v5.4/qca-diag/src/Makefile index c87543f94..53e001743 100755 --- a/feeds/ipq807x_v5.4/qca-diag/src/Makefile +++ b/feeds/ipq807x_v5.4/qca-diag/src/Makefile @@ -2,7 +2,7 @@ INCLUDE_DIR += include -I src LIB := -lpthread -shared LDFLAGS += -Llib/ -ldiag -lpthread -pie FLAGS = -fPIC -g -DUSE_MUSL -EXTRA_CFLAGS = $(TARGET_CFLAGS) $(TARGET_LDFLAGS) $(TARGET_CPPFLAGS) -fstack-protector-all -znow -zrelro -Werror -Wno-error=attributes +EXTRA_CFLAGS = $(TARGET_CFLAGS) $(TARGET_LDFLAGS) $(TARGET_CPPFLAGS) -fstack-protector-all -znow -zrelro -Werror -Wno-error=address-of-packed-member -Wl,--allow-multiple-definition -Wno-error=attributes sample_cliobj := dci_client/diag_dci_sample.c klogobj := klog/diag_klog.c mdobj := mdlog/diag_mdlog.c diff --git a/feeds/ipq807x_v5.4/qca-diag/src/include/diag_lsm.h b/feeds/ipq807x_v5.4/qca-diag/src/include/diag_lsm.h index d781bac7b..3eaa64d39 100755 --- a/feeds/ipq807x_v5.4/qca-diag/src/include/diag_lsm.h +++ b/feeds/ipq807x_v5.4/qca-diag/src/include/diag_lsm.h @@ -123,17 +123,23 @@ when who what, where, why #define GUID_LEN 16 -#ifdef ANDROID +#if defined (ANDROID) || defined (USE_ANDROID_LOGGING) #define LOG_TAG "Diag_Lib" #define DIAG_LOGE(...) { \ ALOGE(__VA_ARGS__); \ if (!diag_disable_console) \ printf(__VA_ARGS__); \ } - #include - #include "common_log.h" + #define DIAG_LOGD(...) { \ + ALOGE(__VA_ARGS__); \ + if (!diag_disable_console) \ + printf(__VA_ARGS__); \ + } + #include + #include "common_log.h" #else #define DIAG_LOGE(...) printf (__VA_ARGS__) + #define DIAG_LOGD(...) printf (__VA_ARGS__) #endif #include #include @@ -167,6 +173,12 @@ typedef enum { DB_PARSER_STATE_CLOSE, } qsr4_db_file_parser_state; +/* enum to handle packet processing status */ +enum pkt_status{ + PKT_PROCESS_ONGOING, + PKT_PROCESS_DONE +}; + /* * Structure to keep track of diag callback interface clients. Please note that * there can be only client communicating with an ASIC at a given time. diff --git a/feeds/ipq807x_v5.4/qca-diag/src/socket_log/diag_socket_log.c b/feeds/ipq807x_v5.4/qca-diag/src/socket_log/diag_socket_log.c index 5b4dfbf4f..38d065d75 100755 --- a/feeds/ipq807x_v5.4/qca-diag/src/socket_log/diag_socket_log.c +++ b/feeds/ipq807x_v5.4/qca-diag/src/socket_log/diag_socket_log.c @@ -64,7 +64,7 @@ when who what, where, why #define PID_DIR "/root/diag_logs" #define MAX_CHAN 4 -static unsigned char read_buf[4096]; +static unsigned char read_buf[MAX_CHAN][4096]; static char ip_addr_name[FILE_NAME_LEN] = "192.168.0.10"; static char port_number_string[FILE_NAME_LEN] = "2500"; static int port_number = 2500; @@ -397,13 +397,22 @@ int open_connection(struct diag_socket *sock) int read_socket(struct diag_socket *socket) { int num_read; + int status; +repeat: /* Read from the socket */ - memset(read_buf, 0, 4096); - num_read = recv(socket->fd, (unsigned char *)read_buf, 4096, 0); + memset(read_buf[socket->id], 0, 4096); + num_read = recv(socket->fd, (unsigned char *)read_buf[socket->id], 4096, 0); if (num_read > 0) { - /* Send the data read off of the socket to the kernel via the library */ - diag_send_socket_data(socket->id, read_buf, num_read); + /* + * Process socket data to make sure full command is received before send it + * to the diag core via the library. If return value is not PKT_PROCESS_DONE + * then this is the case of partial packet and wait for pending bytes to + * get full diag command. + */ + status = diag_send_socket_data(socket->id, read_buf[socket->id], num_read); + if (status != PKT_PROCESS_DONE) + goto repeat; } else if (num_read == -1) { DIAG_LOGE("diag_socket_log: Read socket error: %s, errno: %d\n", strerror(errno), errno); diff --git a/feeds/ipq807x_v5.4/qca-diag/src/src/diag_lsm.c b/feeds/ipq807x_v5.4/qca-diag/src/src/diag_lsm.c index e98a73a82..0c43d6f2d 100755 --- a/feeds/ipq807x_v5.4/qca-diag/src/src/diag_lsm.c +++ b/feeds/ipq807x_v5.4/qca-diag/src/src/diag_lsm.c @@ -89,6 +89,9 @@ when who what, where, why #define MAX_CHANNELS 4 +#define MAX_USER_PKT_SIZE 16384 +#define USER_SPACE_DATA_TYPE_SIZE 4 + #define DCI_HEADER_LENGTH sizeof(int) #define DCI_LEN_FIELD_LENGTH sizeof(int) #define DCI_EVENT_OFFSET sizeof(uint16) @@ -134,6 +137,13 @@ when who what, where, why char dir_name[FILE_NAME_LEN]; char peripheral_name[FILE_NAME_LEN]; +/* enum defined to handle full/partial packet case */ +typedef enum { + PKT_START, + PKT_HEADER, + PKT_PAYLOAD +} diag_pkt_states; + static struct diag_callback_tbl_t cb_clients[NUM_PROC]; static int socket_inited = 0; static int (*socket_cb_ptr)(void *socket_cb_data_ptr, int socket_id); @@ -619,46 +629,246 @@ SIDE EFFECTS ===========================================================================*/ int diag_send_socket_data(int id, unsigned char buf[], int num_bytes) { - unsigned char send_buf[4100]; - unsigned char offset = 4; - int i; - int start = 0; - int end = 0; - int copy_bytes; - int success; + static unsigned char send_buf[MAX_CHANNELS][MAX_USER_PKT_SIZE]; + static unsigned char extra_header = USER_SPACE_DATA_TYPE_SIZE; + static unsigned char tmp_header[DIAG_NON_HDLC_HEADER_SIZE]; + static diag_pkt_states pkt_state = PKT_START; + static int hdlc_pkt_pending = FALSE; + static uint32_t total_pkt_size = 0; + static uint32_t bytes_required = 0; + static int s_char = 0, e_char = 0; + static uint32_t pkt_start_off = 0; + static uint32_t saved_bytes = 0; + int status = PKT_PROCESS_DONE; + int packet_len_index = 0; + uint16_t packet_len = 0; + int i = 0, j = 0; - if ((id >= 0) && (id < MAX_CHANNELS)) { - *(int *)send_buf = USER_SPACE_DATA_TYPE; - if (socket_token[id] != 0 ) { - *(int *)(send_buf + offset) = socket_token[id]; - offset += 4; - } - - for (i = 0; i < num_bytes; i++) { - if (hdlc_disabled) { - if (buf[i] == CONTROL_CHAR && i == 0) { - end = end + 1; - continue; - } - } - if (buf[i] == CONTROL_CHAR) { - copy_bytes = end-start+1; - memcpy(send_buf+offset, buf+start, copy_bytes); - diag_send_data(send_buf, copy_bytes+offset); - start = i+1; - end = i+1; - continue; - } - end = end+1; - } - success = 1; - } else { - DIAG_LOGE("diag: In %s, Error sending socket data. Invalid socket id: %d\n", - __func__, id); - success = 0; + if ((id < 0) || id >= MAX_CHANNELS) { + DIAG_LOGE("diag_socket_log: %s: Error sending socket data. socket id: %d, num_bytes: %d\n", + __func__, id, num_bytes); + return PKT_PROCESS_DONE; } - return success; + for (i = 0; i < num_bytes; i++) { + status = PKT_PROCESS_ONGOING; + switch (pkt_state) + { + case PKT_START: + if (buf[i] == CONTROL_CHAR && !hdlc_pkt_pending) { + s_char = buf[i]; + pkt_start_off = i; + /* probably it is non-HDLC packet */ + if (num_bytes >= (pkt_start_off + DIAG_NON_HDLC_HEADER_SIZE)) { + /* received full header */ + packet_len_index = pkt_start_off + 2; + packet_len = (uint16_t)(*(uint16_t *)(buf + packet_len_index)); + total_pkt_size = DIAG_NON_HDLC_HEADER_SIZE + packet_len + 1; + if (total_pkt_size <= (num_bytes - pkt_start_off)) { + e_char = buf[total_pkt_size-1]; + if (s_char == e_char) { + /* full non-HDLC packet received */ + memset(send_buf[id], 0, MAX_USER_PKT_SIZE); + *(int *)send_buf[id] = USER_SPACE_DATA_TYPE; + if (socket_token[id] != 0) { + *(int *)(send_buf[id] + extra_header) = socket_token[id]; + extra_header += sizeof(int); + } + memcpy(send_buf[id] + extra_header, buf, total_pkt_size); + /* send it diag core */ + diag_send_data(send_buf[id], total_pkt_size + extra_header); + i += total_pkt_size - 1; + s_char = 0; + e_char = 0; + total_pkt_size = 0; + extra_header = USER_SPACE_DATA_TYPE_SIZE; + status = PKT_PROCESS_DONE; + } + } else { + /* full header + partial packet received */ + pkt_state = PKT_PAYLOAD; + memset(send_buf[id], 0, MAX_USER_PKT_SIZE); + *(int *)send_buf[id] = USER_SPACE_DATA_TYPE; + if (socket_token[id] != 0) { + *(int *)(send_buf[id] + extra_header) = socket_token[id]; + extra_header += sizeof(int); + } + memcpy(send_buf[id] + extra_header, (buf + pkt_start_off), (num_bytes - pkt_start_off)); + saved_bytes = (num_bytes - pkt_start_off + extra_header); + bytes_required = total_pkt_size - (saved_bytes - extra_header); + i += num_bytes - 1; + DIAG_LOGD("%s:PKT_START: full header + partial pkt received, total_pkt_size %d recvd %d pending %d\n", + __func__, total_pkt_size, (saved_bytes - extra_header), bytes_required); + } + } else { + /* partial header received */ + memcpy(tmp_header, (buf + pkt_start_off), (num_bytes - pkt_start_off)); + saved_bytes = (num_bytes - pkt_start_off); + bytes_required = DIAG_NON_HDLC_HEADER_SIZE - saved_bytes; + i += num_bytes - 1; + pkt_state = PKT_HEADER; + DIAG_LOGD("%s:PKT_START: partial header received, recvd %d pending %d\n", + __func__, saved_bytes, bytes_required); + } + } else { + /* HDLC packet will enter here */ + if (!hdlc_pkt_pending) { + hdlc_pkt_pending = TRUE; + memset(send_buf[id], 0, MAX_USER_PKT_SIZE); + *(int *)send_buf[id] = USER_SPACE_DATA_TYPE; + if (socket_token[id] != 0) { + *(int *)(send_buf[id] + extra_header) = socket_token[id]; + extra_header += sizeof(int); + } + saved_bytes = extra_header; + } + /* iterate through the packet to find the delimiter */ + for (j = 0; j < num_bytes; j++) { + if (buf[j] == CONTROL_CHAR) { + if (j == (num_bytes - 1)) { + /* delimiter found at the end of current packet + * probably this is end of HDLC packet + */ + if (saved_bytes + num_bytes >= MAX_USER_PKT_SIZE) { + DIAG_LOGE("%s:hdlc: command too large, dropping pkt\n", __func__); + hdlc_pkt_pending = FALSE; + saved_bytes = 0; + i += num_bytes - 1; + break; + } + memcpy(send_buf[id] + saved_bytes, buf, num_bytes); + /* send it to diag core */ + diag_send_data(send_buf[id], saved_bytes + num_bytes); + hdlc_pkt_pending = FALSE; + i += num_bytes - 1; + saved_bytes = 0; + extra_header = USER_SPACE_DATA_TYPE_SIZE; + status = PKT_PROCESS_DONE; + } else { + /* delimiter character may come at the middle of packet + * just ignore as we cant handle this case + */ + DIAG_LOGD("%s:hdlc: Delimiter found at the middle index %d\n", __func__, j); + } + } + } + /* full HDLC packet has not received */ + if (hdlc_pkt_pending) { + if (saved_bytes + num_bytes >= MAX_USER_PKT_SIZE) { + DIAG_LOGE("%s:hdlc: command too large, dropping pkt\n", __func__); + hdlc_pkt_pending = FALSE; + saved_bytes = 0; + i += num_bytes - 1; + break; + } + memcpy(send_buf[id] + saved_bytes, buf, num_bytes); + saved_bytes += num_bytes; + i += num_bytes - 1; + DIAG_LOGD("%s:hdlc: Partial Packet received, recvd %d\n", __func__, + (saved_bytes - extra_header)); + } + } + break; + + case PKT_HEADER: + if(num_bytes >= bytes_required){ + /* we have full header now */ + memcpy(tmp_header+saved_bytes, buf, bytes_required); + packet_len = (uint16_t)(*(uint16_t *)(tmp_header + 2)); + total_pkt_size = DIAG_NON_HDLC_HEADER_SIZE + packet_len + 1; + if (total_pkt_size <= (num_bytes + saved_bytes)) { + /* might received full packet */ + e_char = buf[total_pkt_size - saved_bytes - 1]; + if (s_char == e_char) { + /* full non-HDLC packet received */ + memset(send_buf[id], 0, MAX_USER_PKT_SIZE); + *(int *)send_buf[id] = USER_SPACE_DATA_TYPE; + if (socket_token[id] != 0) { + *(int *)(send_buf[id] + extra_header) = socket_token[id]; + extra_header += sizeof(int); + } + memcpy(send_buf[id] + extra_header, tmp_header, saved_bytes); + memcpy(send_buf[id] + extra_header + saved_bytes, buf, + total_pkt_size - saved_bytes); + /* send it to diag core */ + diag_send_data(send_buf[id], total_pkt_size + extra_header); + i += total_pkt_size - saved_bytes - 1; + s_char = 0; + e_char = 0; + total_pkt_size = 0; + bytes_required = 0; + saved_bytes = 0; + extra_header = USER_SPACE_DATA_TYPE_SIZE; + pkt_state = PKT_START; + status = PKT_PROCESS_DONE; + } + } else { + /* full header + partial packet received */ + pkt_state = PKT_PAYLOAD; + memset(send_buf[id], 0, MAX_USER_PKT_SIZE); + *(int *)send_buf[id] = USER_SPACE_DATA_TYPE; + if (socket_token[id] != 0) { + *(int *)(send_buf[id] + extra_header) = socket_token[id]; + extra_header += sizeof(int); + } + /* copy partial header received */ + memcpy(send_buf[id] + extra_header, tmp_header, saved_bytes); + memcpy(send_buf[id] + extra_header + saved_bytes, buf, num_bytes); + bytes_required = total_pkt_size - saved_bytes - num_bytes; + i += num_bytes - 1; + saved_bytes += num_bytes + extra_header; + DIAG_LOGD("%s:PKT_HEADER: full header + partial pkt received, total_pkt_size %d recvd %d pending %d\n", + __func__, total_pkt_size, (saved_bytes - extra_header), bytes_required); + } + } else { + /* still full header not yet received */ + memcpy(tmp_header + saved_bytes, buf, num_bytes); + saved_bytes += num_bytes; + bytes_required = DIAG_NON_HDLC_HEADER_SIZE - saved_bytes; + i += num_bytes - 1; + DIAG_LOGD("%s:PKT_HEADER: still partial header received, recvd %d pending %d\n", + __func__, saved_bytes, bytes_required); + } + break; + + case PKT_PAYLOAD: + if(num_bytes >= bytes_required){ + /* received pending bytes */ + e_char = buf[bytes_required - 1]; + if (s_char == e_char) { + /* full non-HDLC packet received */ + memcpy(send_buf[id] + saved_bytes, buf, bytes_required); + /* send it to diag core */ + diag_send_data(send_buf[id], total_pkt_size + extra_header); + i += bytes_required - 1; + s_char = 0; + e_char = 0; + total_pkt_size = 0; + bytes_required = 0; + saved_bytes = 0; + extra_header = USER_SPACE_DATA_TYPE_SIZE; + pkt_state = PKT_START; + status = PKT_PROCESS_DONE; + } + } else { + /* still not yet received the full packet */ + memcpy(send_buf[id] + saved_bytes, buf, num_bytes); + bytes_required = total_pkt_size - (saved_bytes - + extra_header) - num_bytes; + i += num_bytes - 1; + saved_bytes += num_bytes; + DIAG_LOGD("%s:PKT_PAYLOAD: Still waiting for full packet,saved %d pending %d\n", + __func__, (saved_bytes - extra_header), bytes_required); + } + break; + default: + DIAG_LOGD("%s:default: Unexpected packet state\n", + __func__); + break; + } + } + + return status; } /*========================================================================== @@ -2300,6 +2510,7 @@ int diag_read_mask_file(void) if (!found_cmd) { DIAG_LOGE("Sorry, could not find valid commands in the mask file," "please check the mask file again\n"); + fclose(read_mask_fp); return -1; } } else { @@ -2321,6 +2532,7 @@ int diag_read_mask_file(void) if (mask_buf[count_mask_bytes] != CONTROL_CHAR && i == 0) { DIAG_LOGE("Sorry, the mask file doesn't adhere to framing definition," "please check the mask file again\n"); + fclose(read_mask_fp); return -1; } if (count_mask_bytes > payload && mask_buf[count_mask_bytes] == CONTROL_CHAR && i != 0) { diff --git a/feeds/ipq807x_v5.4/qca-diag/src/src/diag_lsmi.h b/feeds/ipq807x_v5.4/qca-diag/src/src/diag_lsmi.h index 426897df1..122e28b54 100755 --- a/feeds/ipq807x_v5.4/qca-diag/src/src/diag_lsmi.h +++ b/feeds/ipq807x_v5.4/qca-diag/src/src/diag_lsmi.h @@ -34,6 +34,14 @@ when who what, where, why #define DIAG_MDLOG_PID_FILE_SZ 100 #define NUM_PROC 10 #define HDLC_DISABLE 1 + +/* Non-HDLC Header: + * 1 byte - Control char + * 1 byte - Version + * 2 bytes - Packet length + */ +#define DIAG_NON_HDLC_HEADER_SIZE 4 + extern int diag_fd; extern int fd_md[NUM_PROC]; extern int gdwClientID; diff --git a/feeds/ipq807x_v5.4/qca-diag/src/src/diag_qshrink4_db_parser.c b/feeds/ipq807x_v5.4/qca-diag/src/src/diag_qshrink4_db_parser.c index 902620b6d..5b560a22c 100755 --- a/feeds/ipq807x_v5.4/qca-diag/src/src/diag_qshrink4_db_parser.c +++ b/feeds/ipq807x_v5.4/qca-diag/src/src/diag_qshrink4_db_parser.c @@ -249,6 +249,8 @@ static int diag_qsr4_db_file_mem_init(qsr4_db_file_list** file_entry) } if (entry->head == NULL) entry->head = file_block_offset; + else + free(file_block_offset); return TRUE; diff --git a/feeds/ipq95xx/ath12k-firmware/Makefile b/feeds/ipq95xx/ath12k-firmware/Makefile index 05e075182..e2d54bd38 100644 --- a/feeds/ipq95xx/ath12k-firmware/Makefile +++ b/feeds/ipq95xx/ath12k-firmware/Makefile @@ -1,11 +1,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ath12k-firmware +PKG_MIRROR_HASH:=a325f86b1d613f713d2e015abca4a9ff86c8448d4cd540fa022866da2c5aa042 PKG_SOURCE_PROTO:=git PKG_BRANCH:=main PKG_SOURCE_URL:=https://github.com/quic/upstream-wifi-fw.git -PKG_MIRROR_HASH:=ade4287ff2935ad1d54e5dabb8e6de28f648d0974fa76238fcc1616235e6773e -PKG_SOURCE_VERSION:=3417bb86645c5ff4c58258db7cc33e43260b4222 +PKG_SOURCE_VERSION:=e90d32aaa149800ea79760639cb5ac9ddcfc8281 PKG_MAINTAINER:=John Crispin @@ -18,20 +18,59 @@ define Package/ath12k-firmware-default DEPENDS:= endef +define Package/ath12k-firmware-qcn92xx-split-phy + $(Package/ath12k-firmware-default) + TITLE:=ath12k firmware for qcn92xx split phy devices + DEPENDS:=@(TARGET_ipq95xx||TARGET_ipq53xx) +endef + define Package/ath12k-firmware-qcn92xx $(Package/ath12k-firmware-default) TITLE:=ath12k firmware for qcn92xx devices - DEPENDS:=@TARGET_ipq95xx + DEPENDS:=@(TARGET_ipq95xx||TARGET_ipq53xx) +endef + +define Package/ath12k-firmware-ipq53xx + $(Package/ath12k-firmware-default) + TITLE:=ath12k firmware for ipq53xx devices + DEPENDS:=@TARGET_ipq53xx +endef + +define Package/ath12k-firmware-ipq53xx-wk-wk + $(Package/ath12k-firmware-default) + TITLE:=ath12k firmware for ipq53xx + wk + wk devices + DEPENDS:=@TARGET_ipq53xx endef define Build/Compile endef +define Package/ath12k-firmware-qcn92xx-split-phy/install + $(INSTALL_DIR) $(1)/lib/firmware/ath12k/QCN92XX/hw1.0 + $(CP) $(PKG_BUILD_DIR)/ath12k-firmware/QCN9274/hw2.0_split_phy/1.2.1/WLAN.WBE.1.2.1-00148-QCAHKSWPL_SILICONZ-1/* \ + $(1)/lib/firmware/ath12k/QCN92XX/hw1.0 +endef + define Package/ath12k-firmware-qcn92xx/install - $(INSTALL_DIR) $(1)/lib/firmware/ath12k/QCN92XX/hw2.0 - $(INSTALL_DATA) $(PKG_BUILD_DIR)/ath12k-firmware/QCN9274/hw2.0/1.1.1/WLAN.WBE.1.1.1-00126-QCAHKSWPL_SILICONZ-1/* \ - $(1)/lib/firmware/ath12k/QCN92XX/hw2.0 + $(INSTALL_DIR) $(1)/lib/firmware/ath12k/QCN92XX/hw1.0 + $(CP) $(PKG_BUILD_DIR)/ath12k-firmware/QCN9274/hw2.0/1.2.1/WLAN.WBE.1.2.1-00201-QCAHKSWPL_SILICONZ-1/* \ + $(1)/lib/firmware/ath12k/QCN92XX/hw1.0 +endef + +define Package/ath12k-firmware-ipq53xx/install + $(INSTALL_DIR) $(1)/lib/firmware/IPQ5332/ + $(CP) $(PKG_BUILD_DIR)/ath12k-firmware//IPQ5322/hw1.0/1.2.1/WLAN.WBE.1.2.1-00201-QCAHKSWPL_SILICONZ-1/* \ + $(1)/lib/firmware/IPQ5332/ +endef + +define Package/ath12k-firmware-ipq53xx-wk-wk/install + $(INSTALL_DIR) $(1)/lib/firmware/IPQ5332/ + $(CP) $(PKG_BUILD_DIR)/ath12k-firmware/IPQ5322_QCN6432_QCN6432/hw1.0/testing/1.3/WLAN.WBE.1.3-02907-QCAHKSWPL_SILICONZ-1/* \ + $(1)/lib/firmware/IPQ5332/ endef $(eval $(call BuildPackage,ath12k-firmware-qcn92xx)) +$(eval $(call BuildPackage,ath12k-firmware-qcn92xx-split-phy)) +$(eval $(call BuildPackage,ath12k-firmware-ipq53xx)) +$(eval $(call BuildPackage,ath12k-firmware-ipq53xx-wk-wk)) diff --git a/feeds/ipq95xx/ath12k-wifi/Makefile b/feeds/ipq95xx/ath12k-wifi/Makefile index 4fbd25470..b1f2f0aed 100644 --- a/feeds/ipq95xx/ath12k-wifi/Makefile +++ b/feeds/ipq95xx/ath12k-wifi/Makefile @@ -19,7 +19,7 @@ define Package/ath12k-wifi-default SUBMENU:=ath12k Board-Specific Overrides SECTION:=firmware CATEGORY:=Firmware - DEPENDS:=@TARGET_qcn9274 + DEPENDS:=@(TARGET_qcn9274||TARGET_ipq53xx) TITLE:=Custom Board endef @@ -33,4 +33,32 @@ define Package/ath12k-wifi-qcom-qcn9274/install $(INSTALL_DATA) ./board-2.bin.QCN9274 $(1)/lib/firmware/ath12k/QCN9274/hw1.0/board-2.bin endef +define Package/ath12k-wifi-cig-wf189 +$(call Package/ath12k-wifi-default) + TITLE:=board.bin for CIG WF189 +endef + +define Package/ath12k-wifi-sercomm-ap72tip +$(call Package/ath12k-wifi-default) + TITLE:=board.bin for Sercomm WIFI-7 +endef + +define Package/ath12k-wifi-cig-wf189/install + $(INSTALL_DIR) $(1)/lib/firmware/ath12k/QCN92XX/hw1.0 $(1)/lib/firmware/ath12k/IPQ5332/hw1.0 + $(INSTALL_DATA) ./regdb.bin $(1)/lib/firmware/ath12k/QCN92XX/hw1.0/ + $(INSTALL_DATA) ./board-cig-wf189.bin.qcn9224 $(1)/lib/firmware/ath12k/QCN92XX/hw1.0/board.bin + $(INSTALL_DATA) ./regdb.bin $(1)/lib/firmware/ath12k/IPQ5332/hw1.0/ + $(INSTALL_DATA) ./board-cig-wf189.bin.ipq53xx $(1)/lib/firmware/ath12k/IPQ5332/hw1.0/board.bin +endef + +define Package/ath12k-wifi-sercomm-ap72tip/install + $(INSTALL_DIR) $(1)/lib/firmware/ath12k/QCN92XX/hw1.0 $(1)/lib/firmware/ath12k/IPQ5332/hw1.0 + $(INSTALL_DATA) ./regdb.bin $(1)/lib/firmware/ath12k/QCN92XX/hw1.0/ + $(INSTALL_DATA) ./board-sercomm-ap72tip.bin.qcn9224 $(1)/lib/firmware/ath12k/QCN92XX/hw1.0/board.bin + $(INSTALL_DATA) ./regdb.bin $(1)/lib/firmware/ath12k/IPQ5332/hw1.0/ + $(INSTALL_DATA) ./board-sercomm-ap72tip.bin.ipq53xx $(1)/lib/firmware/ath12k/IPQ5332/hw1.0/board.bin +endef + $(eval $(call BuildPackage,ath12k-wifi-qcom-qcn9274)) +$(eval $(call BuildPackage,ath12k-wifi-cig-wf189)) +$(eval $(call BuildPackage,ath12k-wifi-sercomm-ap72tip)) diff --git a/feeds/ipq95xx/ath12k-wifi/board-cig-wf189.bin.ipq53xx b/feeds/ipq95xx/ath12k-wifi/board-cig-wf189.bin.ipq53xx new file mode 100755 index 000000000..48ebfd7ae Binary files /dev/null and b/feeds/ipq95xx/ath12k-wifi/board-cig-wf189.bin.ipq53xx differ diff --git a/feeds/ipq95xx/ath12k-wifi/board-cig-wf189.bin.qcn9224 b/feeds/ipq95xx/ath12k-wifi/board-cig-wf189.bin.qcn9224 new file mode 100755 index 000000000..2762ba247 Binary files /dev/null and b/feeds/ipq95xx/ath12k-wifi/board-cig-wf189.bin.qcn9224 differ diff --git a/feeds/ipq95xx/ath12k-wifi/board-sercomm-ap72tip.bin.ipq53xx b/feeds/ipq95xx/ath12k-wifi/board-sercomm-ap72tip.bin.ipq53xx new file mode 100644 index 000000000..d1e74c2d8 Binary files /dev/null and b/feeds/ipq95xx/ath12k-wifi/board-sercomm-ap72tip.bin.ipq53xx differ diff --git a/feeds/ipq95xx/ath12k-wifi/board-sercomm-ap72tip.bin.qcn9224 b/feeds/ipq95xx/ath12k-wifi/board-sercomm-ap72tip.bin.qcn9224 new file mode 100644 index 000000000..ec5164400 Binary files /dev/null and b/feeds/ipq95xx/ath12k-wifi/board-sercomm-ap72tip.bin.qcn9224 differ diff --git a/feeds/ipq95xx/ath12k-wifi/regdb.bin b/feeds/ipq95xx/ath12k-wifi/regdb.bin new file mode 100755 index 000000000..2f1afba52 Binary files /dev/null and b/feeds/ipq95xx/ath12k-wifi/regdb.bin differ diff --git a/feeds/ipq95xx/hostapd/Makefile b/feeds/ipq95xx/hostapd/Makefile index 439fe122d..ea59ef9b2 100644 --- a/feeds/ipq95xx/hostapd/Makefile +++ b/feeds/ipq95xx/hostapd/Makefile @@ -5,13 +5,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=hostapd -PKG_RELEASE:=$(AUTORELEASE) +PKG_VERSION:=2023-02-21-ath12.3-cs -PKG_SOURCE_URL:=http://w1.fi/hostap.git -PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2021-12-13 -PKG_SOURCE_VERSION:=b26f5c0fe3 -PKG_MIRROR_HASH:=2c5b72056b6efc3a16ca912118b324371527c7ac79c4b997349d94680538a7d8 +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 +PKG_HASH:=6153bacd614d9bb2dfba634dd698a698e37c043e08543a0802903718238a12fa +PKG_SOURCE_URL:=@KERNEL/software/utils/dtc PKG_MAINTAINER:=Felix Fietkau PKG_LICENSE:=BSD-3-Clause diff --git a/feeds/ipq95xx/hostapd/files/hostapd.sh b/feeds/ipq95xx/hostapd/files/hostapd.sh index 525da30cd..f5f65c777 100644 --- a/feeds/ipq95xx/hostapd/files/hostapd.sh +++ b/feeds/ipq95xx/hostapd/files/hostapd.sh @@ -126,6 +126,7 @@ hostapd_common_add_device_config() { config_add_int airtime_mode config_add_boolean multiple_bssid rnr_beacon he_co_locate ema + config_add_boolean mlo hostapd_add_log_config } @@ -140,7 +141,7 @@ hostapd_prepare_device_config() { acs_chan_bias local_pwr_constraint spectrum_mgmt_required airtime_mode cell_density \ rts_threshold beacon_rate rssi_reject_assoc_rssi rssi_ignore_probe_request maxassoc \ multiple_bssid he_co_locate rnr_beacon ema acs_exclude_dfs \ - maxassoc_ignore_probe + maxassoc_ignore_probe mlo hostapd_set_log_options base_cfg @@ -155,6 +156,7 @@ hostapd_prepare_device_config() { set_default multiple_bssid 0 set_default ema 0 set_default acs_exclude_dfs 0 + set_default mlo 0 [ -n "$country" ] && { append base_cfg "country_code=$country" "$N" @@ -252,6 +254,7 @@ hostapd_prepare_device_config() { # [ "$he_co_locate" -gt 0 ] && append base_cfg "he_co_locate=$he_co_locate" "$N" [ "$multiple_bssid" -gt 0 ] && append base_cfg "multiple_bssid=$multiple_bssid" "$N" [ "$ema" -gt 0 ] && append base_cfg "ema=$ema" "$N" + [ "$mlo" -gt 0 ] && append base_cfg "mlo=1" "$N" [ "$acs_exclude_dfs" -gt 0 ] && append base_cfg "acs_exclude_dfs=$acs_exclude_dfs" "$N" json_get_values opts hostapd_options diff --git a/feeds/ipq95xx/hostapd/patches/001-wolfssl-init-RNG-with-ECC-key.patch b/feeds/ipq95xx/hostapd/patches/001-wolfssl-init-RNG-with-ECC-key.patch new file mode 100644 index 000000000..269dcaac7 --- /dev/null +++ b/feeds/ipq95xx/hostapd/patches/001-wolfssl-init-RNG-with-ECC-key.patch @@ -0,0 +1,43 @@ +From 21ce83b4ae2b9563175fdb4fc4312096cc399cf8 Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Wed, 5 May 2021 00:44:34 +0200 +Subject: [PATCH] wolfssl: add RNG to EC key + +Since upstream commit 6467de5a8840 ("Randomize z ordinates in +scalar mult when timing resistant") WolfSSL requires a RNG for +the EC key when built hardened which is the default. + +Set the RNG for the EC key to fix connections for OWE clients. + +Signed-off-by: David Bauer +--- + src/crypto/crypto_wolfssl.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/src/crypto/crypto_wolfssl.c ++++ b/src/crypto/crypto_wolfssl.c +@@ -1340,6 +1340,7 @@ int ecc_projective_add_point(ecc_point * + + struct crypto_ec { + ecc_key key; ++ WC_RNG rng; + mp_int a; + mp_int prime; + mp_int order; +@@ -1394,6 +1395,8 @@ struct crypto_ec * crypto_ec_init(int gr + return NULL; + + if (wc_ecc_init(&e->key) != 0 || ++ wc_InitRng(&e->rng) != 0 || ++ wc_ecc_set_rng(&e->key, &e->rng) != 0 || + wc_ecc_set_curve(&e->key, 0, curve_id) != 0 || + mp_init(&e->a) != MP_OKAY || + mp_init(&e->prime) != MP_OKAY || +@@ -1425,6 +1428,7 @@ void crypto_ec_deinit(struct crypto_ec* + mp_clear(&e->order); + mp_clear(&e->prime); + mp_clear(&e->a); ++ wc_FreeRng(&e->rng); + wc_ecc_free(&e->key); + os_free(e); + } diff --git a/feeds/ipq95xx/hostapd/patches/021-fix-sta-add-after-previous-connection.patch b/feeds/ipq95xx/hostapd/patches/021-fix-sta-add-after-previous-connection.patch new file mode 100644 index 000000000..edf599e3e --- /dev/null +++ b/feeds/ipq95xx/hostapd/patches/021-fix-sta-add-after-previous-connection.patch @@ -0,0 +1,26 @@ +--- a/src/ap/ieee802_11.c ++++ b/src/ap/ieee802_11.c +@@ -4621,6 +4621,13 @@ static int add_associated_sta(struct hos + * drivers to accept the STA parameter configuration. Since this is + * after a new FT-over-DS exchange, a new TK has been derived, so key + * reinstallation is not a concern for this case. ++ * ++ * If the STA was associated and authorized earlier, but came for a new ++ * connection (!added_unassoc + !reassoc), remove the existing STA entry ++ * so that it can be re-added. This case is rarely seen when the AP could ++ * not receive the deauth/disassoc frame from the STA. And the STA comes ++ * back with new connection within a short period or before the inactive ++ * STA entry is removed from the list. + */ + wpa_printf(MSG_DEBUG, "Add associated STA " MACSTR + " (added_unassoc=%d auth_alg=%u ft_over_ds=%u reassoc=%d authorized=%d ft_tk=%d fils_tk=%d)", +@@ -4634,7 +4641,8 @@ static int add_associated_sta(struct hos + (!(sta->flags & WLAN_STA_AUTHORIZED) || + (reassoc && sta->ft_over_ds && sta->auth_alg == WLAN_AUTH_FT) || + (!wpa_auth_sta_ft_tk_already_set(sta->wpa_sm) && +- !wpa_auth_sta_fils_tk_already_set(sta->wpa_sm)))) { ++ !wpa_auth_sta_fils_tk_already_set(sta->wpa_sm)) || ++ (!reassoc && (sta->flags & WLAN_STA_AUTHORIZED)))) { + hostapd_drv_sta_remove(hapd, sta->addr); + wpa_auth_sm_event(sta->wpa_sm, WPA_DRV_STA_REMOVED); + set = 0; diff --git a/feeds/ipq95xx/hostapd/patches/022-hostapd-fix-use-of-uninitialized-stack-variables.patch b/feeds/ipq95xx/hostapd/patches/022-hostapd-fix-use-of-uninitialized-stack-variables.patch new file mode 100644 index 000000000..a25a8ecca --- /dev/null +++ b/feeds/ipq95xx/hostapd/patches/022-hostapd-fix-use-of-uninitialized-stack-variables.patch @@ -0,0 +1,27 @@ +From: Felix Fietkau +Date: Thu, 8 Jul 2021 16:33:03 +0200 +Subject: [PATCH] hostapd: fix use of uninitialized stack variables + +When a CSA is performed on an 80 MHz channel, hostapd_change_config_freq +unconditionally calls hostapd_set_oper_centr_freq_seg0/1_idx with seg0/1 +filled by ieee80211_freq_to_chan. +However, if ieee80211_freq_to_chan fails (because the freq is 0 or invalid), +seg0/1 remains uninitialized and filled with stack garbage, causing errors +such as "hostapd: 80 MHz: center segment 1 configured" + +Signed-off-by: Felix Fietkau +--- + +Index: hostapd-2023-02-21-ath12.3-cs/src/ap/hostapd.c +=================================================================== +--- hostapd-2023-02-21-ath12.3-cs.orig/src/ap/hostapd.c ++++ hostapd-2023-02-21-ath12.3-cs/src/ap/hostapd.c +@@ -4352,7 +4352,7 @@ static int hostapd_change_config_freq(st + struct hostapd_freq_params *old_params) + { + int channel; +- u8 seg0, seg1 = 0; ++ u8 seg0 = 0, seg1 = 0; + struct hostapd_hw_modes *mode; + + if (!params->channel) { diff --git a/feeds/ipq95xx/hostapd/patches/023-ndisc_snoop-call-dl_list_del-before-freeing-ipv6-add.patch b/feeds/ipq95xx/hostapd/patches/023-ndisc_snoop-call-dl_list_del-before-freeing-ipv6-add.patch new file mode 100644 index 000000000..9ff9b2398 --- /dev/null +++ b/feeds/ipq95xx/hostapd/patches/023-ndisc_snoop-call-dl_list_del-before-freeing-ipv6-add.patch @@ -0,0 +1,19 @@ +From: Felix Fietkau +Date: Wed, 28 Jul 2021 05:43:29 +0200 +Subject: [PATCH] ndisc_snoop: call dl_list_del before freeing ipv6 addresses + +Fixes a segmentation fault on sta disconnect + +Signed-off-by: Felix Fietkau +--- + +--- a/src/ap/ndisc_snoop.c ++++ b/src/ap/ndisc_snoop.c +@@ -61,6 +61,7 @@ void sta_ip6addr_del(struct hostapd_data + dl_list_for_each_safe(ip6addr, prev, &sta->ip6addr, struct ip6addr, + list) { + hostapd_drv_br_delete_ip_neigh(hapd, 6, (u8 *) &ip6addr->addr); ++ dl_list_del(&ip6addr->list); + os_free(ip6addr); + } + } diff --git a/feeds/ipq95xx/hostapd/patches/050-build_fix.patch b/feeds/ipq95xx/hostapd/patches/050-build_fix.patch new file mode 100644 index 000000000..8680b07c6 --- /dev/null +++ b/feeds/ipq95xx/hostapd/patches/050-build_fix.patch @@ -0,0 +1,20 @@ +--- a/hostapd/Makefile ++++ b/hostapd/Makefile +@@ -324,6 +324,7 @@ ifdef CONFIG_FILS + CFLAGS += -DCONFIG_FILS + OBJS += ../src/ap/fils_hlp.o + NEED_SHA384=y ++NEED_HMAC_SHA384_KDF=y + NEED_AES_SIV=y + ifdef CONFIG_FILS_SK_PFS + CFLAGS += -DCONFIG_FILS_SK_PFS +--- a/wpa_supplicant/Makefile ++++ b/wpa_supplicant/Makefile +@@ -331,6 +331,7 @@ endif + ifdef CONFIG_FILS + CFLAGS += -DCONFIG_FILS + NEED_SHA384=y ++NEED_HMAC_SHA384_KDF=y + NEED_AES_SIV=y + ifdef CONFIG_FILS_SK_PFS + CFLAGS += -DCONFIG_FILS_SK_PFS diff --git a/feeds/ipq95xx/hostapd/patches/100-daemonize_fix.patch b/feeds/ipq95xx/hostapd/patches/100-daemonize_fix.patch deleted file mode 100644 index 687bd4082..000000000 --- a/feeds/ipq95xx/hostapd/patches/100-daemonize_fix.patch +++ /dev/null @@ -1,97 +0,0 @@ ---- a/src/utils/os_unix.c -+++ b/src/utils/os_unix.c -@@ -10,6 +10,7 @@ - - #include - #include -+#include - - #ifdef ANDROID - #include -@@ -188,59 +189,46 @@ int os_gmtime(os_time_t t, struct os_tm - return 0; - } - -- --#ifdef __APPLE__ --#include --static int os_daemon(int nochdir, int noclose) -+int os_daemonize(const char *pid_file) - { -- int devnull; -+ int pid = 0, i, devnull; - -- if (chdir("/") < 0) -- return -1; -+#if defined(__uClinux__) || defined(__sun__) -+ return -1; -+#else /* defined(__uClinux__) || defined(__sun__) */ - -- devnull = open("/dev/null", O_RDWR); -- if (devnull < 0) -+#ifndef __APPLE__ -+ pid = fork(); -+ if (pid < 0) - return -1; -+#endif - -- if (dup2(devnull, STDIN_FILENO) < 0) { -- close(devnull); -- return -1; -+ if (pid > 0) { -+ if (pid_file) { -+ FILE *f = fopen(pid_file, "w"); -+ if (f) { -+ fprintf(f, "%u\n", pid); -+ fclose(f); -+ } -+ } -+ _exit(0); - } - -- if (dup2(devnull, STDOUT_FILENO) < 0) { -- close(devnull); -+ if (setsid() < 0) - return -1; -- } - -- if (dup2(devnull, STDERR_FILENO) < 0) { -- close(devnull); -+ if (chdir("/") < 0) - return -1; -- } -- -- return 0; --} --#else /* __APPLE__ */ --#define os_daemon daemon --#endif /* __APPLE__ */ - -- --int os_daemonize(const char *pid_file) --{ --#if defined(__uClinux__) || defined(__sun__) -- return -1; --#else /* defined(__uClinux__) || defined(__sun__) */ -- if (os_daemon(0, 0)) { -- perror("daemon"); -+ devnull = open("/dev/null", O_RDWR); -+ if (devnull < 0) - return -1; -- } - -- if (pid_file) { -- FILE *f = fopen(pid_file, "w"); -- if (f) { -- fprintf(f, "%u\n", getpid()); -- fclose(f); -- } -- } -+ for (i = 0; i <= STDERR_FILENO; i++) -+ dup2(devnull, i); -+ -+ if (devnull > 2) -+ close(devnull); - - return -0; - #endif /* defined(__uClinux__) || defined(__sun__) */ diff --git a/feeds/ipq95xx/hostapd/patches/110-mbedtls-TLS-crypto-option-initial-port.patch b/feeds/ipq95xx/hostapd/patches/110-mbedtls-TLS-crypto-option-initial-port.patch new file mode 100644 index 000000000..22107944d --- /dev/null +++ b/feeds/ipq95xx/hostapd/patches/110-mbedtls-TLS-crypto-option-initial-port.patch @@ -0,0 +1,8051 @@ +From e16f200dc1d2f69efc78c7c55af0d7b410a981f9 Mon Sep 17 00:00:00 2001 +From: Glenn Strauss +Date: Tue, 5 Jul 2022 02:49:50 -0400 +Subject: [PATCH 1/7] mbedtls: TLS/crypto option (initial port) + +Signed-off-by: Glenn Strauss +--- + hostapd/Makefile | 91 + + hostapd/defconfig | 15 +- + src/crypto/crypto_mbedtls.c | 4043 +++++++++++++++++ + src/crypto/tls_mbedtls.c | 3313 ++++++++++++++ + .../build/build-wpa_supplicant-mbedtls.config | 24 + + tests/hwsim/example-hostapd.config | 4 + + tests/hwsim/example-wpa_supplicant.config | 4 + + wpa_supplicant/Makefile | 74 + + wpa_supplicant/defconfig | 6 +- + 9 files changed, 7571 insertions(+), 3 deletions(-) + create mode 100644 src/crypto/crypto_mbedtls.c + create mode 100644 src/crypto/tls_mbedtls.c + create mode 100644 tests/build/build-wpa_supplicant-mbedtls.config + +--- a/hostapd/Makefile ++++ b/hostapd/Makefile +@@ -745,6 +745,40 @@ endif + CFLAGS += -DTLS_DEFAULT_CIPHERS=\"$(CONFIG_TLS_DEFAULT_CIPHERS)\" + endif + ++ifeq ($(CONFIG_TLS), mbedtls) ++ifndef CONFIG_CRYPTO ++CONFIG_CRYPTO=mbedtls ++endif ++ifdef TLS_FUNCS ++OBJS += ../src/crypto/tls_mbedtls.o ++LIBS += -lmbedtls ++ifndef CONFIG_DPP ++LIBS += -lmbedx509 ++endif ++endif ++OBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o ++HOBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o ++SOBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o ++ifdef NEED_FIPS186_2_PRF ++OBJS += ../src/crypto/fips_prf_internal.o ++SHA1OBJS += ../src/crypto/sha1-internal.o ++endif ++ifeq ($(CONFIG_CRYPTO), mbedtls) ++ifdef CONFIG_DPP ++LIBS += -lmbedx509 ++LIBS_h += -lmbedx509 ++LIBS_n += -lmbedx509 ++LIBS_s += -lmbedx509 ++endif ++LIBS += -lmbedcrypto ++LIBS_h += -lmbedcrypto ++LIBS_n += -lmbedcrypto ++LIBS_s += -lmbedcrypto ++# XXX: create a config option? ++CFLAGS += -DCRYPTO_RSA_OAEP_SHA256 ++endif ++endif ++ + ifeq ($(CONFIG_TLS), gnutls) + ifndef CONFIG_CRYPTO + # default to libgcrypt +@@ -924,9 +958,11 @@ endif + + ifneq ($(CONFIG_TLS), openssl) + ifneq ($(CONFIG_TLS), wolfssl) ++ifneq ($(CONFIG_TLS), mbedtls) + AESOBJS += ../src/crypto/aes-wrap.o + endif + endif ++endif + ifdef NEED_AES_EAX + AESOBJS += ../src/crypto/aes-eax.o + NEED_AES_CTR=y +@@ -936,38 +972,48 @@ AESOBJS += ../src/crypto/aes-siv.o + NEED_AES_CTR=y + endif + ifdef NEED_AES_CTR ++ifneq ($(CONFIG_TLS), mbedtls) + AESOBJS += ../src/crypto/aes-ctr.o + endif ++endif + ifdef NEED_AES_ENCBLOCK ++ifneq ($(CONFIG_TLS), mbedtls) + AESOBJS += ../src/crypto/aes-encblock.o + endif ++endif + ifneq ($(CONFIG_TLS), openssl) + ifneq ($(CONFIG_TLS), linux) + ifneq ($(CONFIG_TLS), wolfssl) ++ifneq ($(CONFIG_TLS), mbedtls) + AESOBJS += ../src/crypto/aes-omac1.o + endif + endif + endif ++endif + ifdef NEED_AES_UNWRAP + ifneq ($(CONFIG_TLS), openssl) + ifneq ($(CONFIG_TLS), linux) + ifneq ($(CONFIG_TLS), wolfssl) ++ifneq ($(CONFIG_TLS), mbedtls) + NEED_AES_DEC=y + AESOBJS += ../src/crypto/aes-unwrap.o + endif + endif + endif + endif ++endif + ifdef NEED_AES_CBC + NEED_AES_DEC=y + ifneq ($(CONFIG_TLS), openssl) + ifneq ($(CONFIG_TLS), linux) + ifneq ($(CONFIG_TLS), wolfssl) ++ifneq ($(CONFIG_TLS), mbedtls) + AESOBJS += ../src/crypto/aes-cbc.o + endif + endif + endif + endif ++endif + ifdef NEED_AES_DEC + ifdef CONFIG_INTERNAL_AES + AESOBJS += ../src/crypto/aes-internal-dec.o +@@ -982,12 +1028,16 @@ ifneq ($(CONFIG_TLS), openssl) + ifneq ($(CONFIG_TLS), linux) + ifneq ($(CONFIG_TLS), gnutls) + ifneq ($(CONFIG_TLS), wolfssl) ++ifneq ($(CONFIG_TLS), mbedtls) + SHA1OBJS += ../src/crypto/sha1.o + endif + endif + endif + endif ++endif ++ifneq ($(CONFIG_TLS), mbedtls) + SHA1OBJS += ../src/crypto/sha1-prf.o ++endif + ifdef CONFIG_INTERNAL_SHA1 + SHA1OBJS += ../src/crypto/sha1-internal.o + ifdef NEED_FIPS186_2_PRF +@@ -996,16 +1046,22 @@ endif + endif + ifneq ($(CONFIG_TLS), openssl) + ifneq ($(CONFIG_TLS), wolfssl) ++ifneq ($(CONFIG_TLS), mbedtls) + SHA1OBJS += ../src/crypto/sha1-pbkdf2.o + endif + endif ++endif + ifdef NEED_T_PRF ++ifneq ($(CONFIG_TLS), mbedtls) + SHA1OBJS += ../src/crypto/sha1-tprf.o + endif ++endif + ifdef NEED_TLS_PRF ++ifneq ($(CONFIG_TLS), mbedtls) + SHA1OBJS += ../src/crypto/sha1-tlsprf.o + endif + endif ++endif + + ifdef NEED_SHA1 + OBJS += $(SHA1OBJS) +@@ -1015,11 +1071,13 @@ ifneq ($(CONFIG_TLS), openssl) + ifneq ($(CONFIG_TLS), linux) + ifneq ($(CONFIG_TLS), gnutls) + ifneq ($(CONFIG_TLS), wolfssl) ++ifneq ($(CONFIG_TLS), mbedtls) + OBJS += ../src/crypto/md5.o + endif + endif + endif + endif ++endif + + ifdef NEED_MD5 + ifdef CONFIG_INTERNAL_MD5 +@@ -1058,56 +1116,81 @@ ifneq ($(CONFIG_TLS), openssl) + ifneq ($(CONFIG_TLS), linux) + ifneq ($(CONFIG_TLS), gnutls) + ifneq ($(CONFIG_TLS), wolfssl) ++ifneq ($(CONFIG_TLS), mbedtls) + OBJS += ../src/crypto/sha256.o + endif + endif + endif + endif ++endif ++ifneq ($(CONFIG_TLS), mbedtls) + OBJS += ../src/crypto/sha256-prf.o ++endif + ifdef CONFIG_INTERNAL_SHA256 + OBJS += ../src/crypto/sha256-internal.o + endif + ifdef NEED_TLS_PRF_SHA256 ++ifneq ($(CONFIG_TLS), mbedtls) + OBJS += ../src/crypto/sha256-tlsprf.o + endif ++endif + ifdef NEED_TLS_PRF_SHA384 ++ifneq ($(CONFIG_TLS), mbedtls) + OBJS += ../src/crypto/sha384-tlsprf.o + endif ++endif + ifdef NEED_HMAC_SHA256_KDF ++CFLAGS += -DCONFIG_HMAC_SHA256_KDF ++ifneq ($(CONFIG_TLS), mbedtls) + OBJS += ../src/crypto/sha256-kdf.o + endif ++endif + ifdef NEED_HMAC_SHA384_KDF ++CFLAGS += -DCONFIG_HMAC_SHA384_KDF ++ifneq ($(CONFIG_TLS), mbedtls) + OBJS += ../src/crypto/sha384-kdf.o + endif ++endif + ifdef NEED_HMAC_SHA512_KDF ++CFLAGS += -DCONFIG_HMAC_SHA512_KDF ++ifneq ($(CONFIG_TLS), mbedtls) + OBJS += ../src/crypto/sha512-kdf.o + endif ++endif + ifdef NEED_SHA384 + CFLAGS += -DCONFIG_SHA384 + ifneq ($(CONFIG_TLS), openssl) + ifneq ($(CONFIG_TLS), linux) + ifneq ($(CONFIG_TLS), gnutls) + ifneq ($(CONFIG_TLS), wolfssl) ++ifneq ($(CONFIG_TLS), mbedtls) + OBJS += ../src/crypto/sha384.o + endif + endif + endif + endif ++endif ++ifneq ($(CONFIG_TLS), mbedtls) + OBJS += ../src/crypto/sha384-prf.o + endif ++endif + ifdef NEED_SHA512 + CFLAGS += -DCONFIG_SHA512 + ifneq ($(CONFIG_TLS), openssl) + ifneq ($(CONFIG_TLS), linux) + ifneq ($(CONFIG_TLS), gnutls) + ifneq ($(CONFIG_TLS), wolfssl) ++ifneq ($(CONFIG_TLS), mbedtls) + OBJS += ../src/crypto/sha512.o + endif + endif + endif + endif ++endif ++ifneq ($(CONFIG_TLS), mbedtls) + OBJS += ../src/crypto/sha512-prf.o + endif ++endif + + ifdef CONFIG_INTERNAL_SHA384 + CFLAGS += -DCONFIG_INTERNAL_SHA384 +@@ -1152,11 +1235,13 @@ HOBJS += $(SHA1OBJS) + ifneq ($(CONFIG_TLS), openssl) + ifneq ($(CONFIG_TLS), linux) + ifneq ($(CONFIG_TLS), wolfssl) ++ifneq ($(CONFIG_TLS), mbedtls) + HOBJS += ../src/crypto/md5.o + endif + endif + endif + endif ++endif + + ifdef CONFIG_RADIUS_SERVER + CFLAGS += -DRADIUS_SERVER +@@ -1329,7 +1414,9 @@ NOBJS += ../src/utils/trace.o + endif + + HOBJS += hlr_auc_gw.o ../src/utils/common.o ../src/utils/wpa_debug.o ../src/utils/os_$(CONFIG_OS).o ../src/utils/wpabuf.o ../src/crypto/milenage.o ++ifneq ($(CONFIG_TLS), mbedtls) + HOBJS += ../src/crypto/aes-encblock.o ++endif + ifdef CONFIG_INTERNAL_AES + HOBJS += ../src/crypto/aes-internal.o + HOBJS += ../src/crypto/aes-internal-enc.o +@@ -1352,13 +1439,17 @@ SOBJS += ../src/common/sae.o + SOBJS += ../src/common/sae_pk.o + SOBJS += ../src/common/dragonfly.o + SOBJS += $(AESOBJS) ++ifneq ($(CONFIG_TLS), mbedtls) + SOBJS += ../src/crypto/sha256-prf.o + SOBJS += ../src/crypto/sha384-prf.o + SOBJS += ../src/crypto/sha512-prf.o ++endif + SOBJS += ../src/crypto/dh_groups.o ++ifneq ($(CONFIG_TLS), mbedtls) + SOBJS += ../src/crypto/sha256-kdf.o + SOBJS += ../src/crypto/sha384-kdf.o + SOBJS += ../src/crypto/sha512-kdf.o ++endif + + _OBJS_VAR := NOBJS + include ../src/objs.mk +--- a/hostapd/defconfig ++++ b/hostapd/defconfig +@@ -6,9 +6,21 @@ + # just setting VARIABLE=n is not disabling that variable. + # + # This file is included in Makefile, so variables like CFLAGS and LIBS can also +-# be modified from here. In most cass, these lines should use += in order not ++# be modified from here. In most cases, these lines should use += in order not + # to override previous values of the variables. + ++ ++# Uncomment following two lines and fix the paths if you have installed TLS ++# libraries in a non-default location ++#CFLAGS += -I/usr/local/openssl/include ++#LIBS += -L/usr/local/openssl/lib ++ ++# Some Red Hat versions seem to include kerberos header files from OpenSSL, but ++# the kerberos files are not in the default include path. Following line can be ++# used to fix build issues on such systems (krb5.h not found). ++#CFLAGS += -I/usr/include/kerberos ++ ++ + # Driver interface for Host AP driver + CONFIG_DRIVER_HOSTAP=y + +@@ -278,6 +290,7 @@ CONFIG_IPV6=y + # openssl = OpenSSL (default) + # gnutls = GnuTLS + # internal = Internal TLSv1 implementation (experimental) ++# mbedtls = mbed TLS + # linux = Linux kernel AF_ALG and internal TLSv1 implementation (experimental) + # none = Empty template + #CONFIG_TLS=openssl +--- /dev/null ++++ b/src/crypto/crypto_mbedtls.c +@@ -0,0 +1,4043 @@ ++/* ++ * crypto wrapper functions for mbed TLS ++ * ++ * SPDX-FileCopyrightText: 2022 Glenn Strauss ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include "utils/includes.h" ++#include "utils/common.h" ++ ++#include ++#include ++#include ++#include /* mbedtls_platform_zeroize() */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifndef MBEDTLS_PRIVATE ++#define MBEDTLS_PRIVATE(x) x ++#endif ++ ++/* hostapd/wpa_supplicant provides forced_memzero(), ++ * but prefer mbedtls_platform_zeroize() */ ++#define forced_memzero(ptr,sz) mbedtls_platform_zeroize(ptr,sz) ++ ++#ifndef __has_attribute ++#define __has_attribute(x) 0 ++#endif ++ ++#ifndef __GNUC_PREREQ ++#define __GNUC_PREREQ(maj,min) 0 ++#endif ++ ++#ifndef __attribute_cold__ ++#if __has_attribute(cold) \ ++ || __GNUC_PREREQ(4,3) ++#define __attribute_cold__ __attribute__((__cold__)) ++#else ++#define __attribute_cold__ ++#endif ++#endif ++ ++#ifndef __attribute_noinline__ ++#if __has_attribute(noinline) \ ++ || __GNUC_PREREQ(3,1) ++#define __attribute_noinline__ __attribute__((__noinline__)) ++#else ++#define __attribute_noinline__ ++#endif ++#endif ++ ++#include "crypto.h" ++#include "aes_wrap.h" ++#include "aes.h" ++#include "md5.h" ++#include "sha1.h" ++#include "sha256.h" ++#include "sha384.h" ++#include "sha512.h" ++ ++ ++/* ++ * selective code inclusion based on preprocessor defines ++ * ++ * future: additional code could be wrapped with preprocessor checks if ++ * wpa_supplicant/Makefile and hostap/Makefile were more consistent with ++ * setting preprocessor defines for named groups of functionality ++ */ ++ ++#if defined(CONFIG_FIPS) ++#undef MBEDTLS_MD4_C /* omit md4_vector() */ ++#undef MBEDTLS_MD5_C /* omit md5_vector() hmac_md5_vector() hmac_md5() */ ++#undef MBEDTLS_DES_C /* omit des_encrypt() */ ++#undef MBEDTLS_NIST_KW_C /* omit aes_wrap() aes_unwrap() */ ++#define CRYPTO_MBEDTLS_CONFIG_FIPS ++#endif ++ ++#if !defined(CONFIG_FIPS) ++#if defined(EAP_PWD) \ ++ || defined(EAP_LEAP) || defined(EAP_LEAP_DYNAMIC) \ ++ || defined(EAP_TTLS) || defined(EAP_TTLS_DYNAMIC) \ ++ || defined(EAP_MSCHAPv2) || defined(EAP_MSCHAPv2_DYNAMIC) \ ++ || defined(EAP_SERVER_MSCHAPV2) ++#ifndef MBEDTLS_MD4_C /* (MD4 not in mbedtls 3.x) */ ++#include "md4-internal.c"/* pull in hostap local implementation */ ++#endif /* md4_vector() */ ++#else ++#undef MBEDTLS_MD4_C /* omit md4_vector() */ ++#endif ++#endif ++ ++#if !defined(CONFIG_NO_RC4) && !defined(CONFIG_NO_WPA) ++#ifndef MBEDTLS_ARC4_C /* (RC4 not in mbedtls 3.x) */ ++#include "rc4.c" /* pull in hostap local implementation */ ++#endif /* rc4_skip() */ ++#else ++#undef MBEDTLS_ARC4_C /* omit rc4_skip() */ ++#endif ++ ++#if defined(CONFIG_MACSEC) \ ++ || defined(CONFIG_NO_RADIUS) \ ++ || defined(CONFIG_IEEE80211R) \ ++ || defined(EAP_SERVER_FAST) \ ++ || defined(EAP_SERVER_TEAP) \ ++ || !defined(CONFIG_NO_WPA) ++ /* aes_wrap() aes_unwrap() */ ++#else ++#undef MBEDTLS_NIST_KW_C /* omit aes_wrap() aes_unwrap() */ ++#endif ++ ++#if !defined(CONFIG_SHA256) ++#undef MBEDTLS_SHA256_C ++#endif ++ ++#if !defined(CONFIG_SHA384) && !defined(CONFIG_SHA512) ++#undef MBEDTLS_SHA512_C ++#endif ++ ++#if defined(CONFIG_HMAC_SHA256_KDF) ++#define CRYPTO_MBEDTLS_HMAC_KDF_SHA256 ++#endif ++#if defined(CONFIG_HMAC_SHA384_KDF) ++#define CRYPTO_MBEDTLS_HMAC_KDF_SHA384 ++#endif ++#if defined(CONFIG_HMAC_SHA512_KDF) ++#define CRYPTO_MBEDTLS_HMAC_KDF_SHA512 ++#endif ++ ++#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) \ ++ || defined(EAP_TEAP) || defined(EAP_TEAP_DYNAMIC) || defined(EAP_SERVER_FAST) ++#define CRYPTO_MBEDTLS_SHA1_T_PRF ++#endif ++ ++#if defined(CONFIG_DES) ++#define CRYPTO_MBEDTLS_DES_ENCRYPT ++#endif /* des_encrypt() */ ++ ++#if !defined(CONFIG_NO_PBKDF2) ++#define CRYPTO_MBEDTLS_PBKDF2_SHA1 ++#endif /* pbkdf2_sha1() */ ++ ++#if defined(EAP_IKEV2) \ ++ || defined(EAP_IKEV2_DYNAMIC) \ ++ || defined(EAP_SERVER_IKEV2) /* CONFIG_EAP_IKEV2=y */ ++#define CRYPTO_MBEDTLS_CRYPTO_CIPHER ++#endif /* crypto_cipher_*() */ ++ ++#if defined(EAP_PWD) || defined(EAP_SERVER_PWD) /* CONFIG_EAP_PWD=y */ ++#define CRYPTO_MBEDTLS_CRYPTO_HASH ++#endif /* crypto_hash_*() */ ++ ++#if defined(EAP_PWD) || defined(EAP_SERVER_PWD) /* CONFIG_EAP_PWD=y */ \ ++ || defined(CONFIG_SAE) /* CONFIG_SAE=y */ ++#define CRYPTO_MBEDTLS_CRYPTO_BIGNUM ++#endif /* crypto_bignum_*() */ ++ ++#if defined(EAP_PWD) /* CONFIG_EAP_PWD=y */ \ ++ || defined(EAP_EKE) /* CONFIG_EAP_EKE=y */ \ ++ || defined(EAP_EKE_DYNAMIC) /* CONFIG_EAP_EKE=y */ \ ++ || defined(EAP_SERVER_EKE) /* CONFIG_EAP_EKE=y */ \ ++ || defined(EAP_IKEV2) /* CONFIG_EAP_IKEV2y */ \ ++ || defined(EAP_IKEV2_DYNAMIC)/* CONFIG_EAP_IKEV2=y */ \ ++ || defined(EAP_SERVER_IKEV2) /* CONFIG_EAP_IKEV2=y */ \ ++ || defined(CONFIG_SAE) /* CONFIG_SAE=y */ \ ++ || defined(CONFIG_WPS) /* CONFIG_WPS=y */ ++#define CRYPTO_MBEDTLS_CRYPTO_DH ++#if defined(CONFIG_WPS_NFC) ++#define CRYPTO_MBEDTLS_DH5_INIT_FIXED ++#endif /* dh5_init_fixed() */ ++#endif /* crypto_dh_*() */ ++ ++#if !defined(CONFIG_NO_WPA) /* CONFIG_NO_WPA= */ ++#define CRYPTO_MBEDTLS_CRYPTO_ECDH ++#endif /* crypto_ecdh_*() */ ++ ++#if defined(CONFIG_ECC) ++#define CRYPTO_MBEDTLS_CRYPTO_BIGNUM ++#define CRYPTO_MBEDTLS_CRYPTO_EC ++#endif /* crypto_ec_*() crypto_ec_key_*() */ ++ ++#if defined(CONFIG_DPP) /* CONFIG_DPP=y */ ++#define CRYPTO_MBEDTLS_CRYPTO_EC_DPP /* extra for DPP */ ++#define CRYPTO_MBEDTLS_CRYPTO_CSR ++#endif /* crypto_csr_*() */ ++ ++#if defined(CONFIG_DPP3) /* CONFIG_DPP3=y */ ++#define CRYPTO_MBEDTLS_CRYPTO_HPKE ++#endif ++ ++#if defined(CONFIG_DPP2) /* CONFIG_DPP2=y */ ++#define CRYPTO_MBEDTLS_CRYPTO_PKCS7 ++#endif /* crypto_pkcs7_*() */ ++ ++#if defined(EAP_SIM) || defined(EAP_SIM_DYNAMIC) || defined(EAP_SERVER_SIM) \ ++ || defined(EAP_AKA) || defined(EAP_AKA_DYNAMIC) || defined(EAP_SERVER_AKA) \ ++ || defined(CONFIG_AP) || defined(HOSTAPD) ++/* CONFIG_EAP_SIM=y CONFIG_EAP_AKA=y CONFIG_AP=y HOSTAPD */ ++#if defined(CRYPTO_RSA_OAEP_SHA256) ++#define CRYPTO_MBEDTLS_CRYPTO_RSA ++#endif ++#endif /* crypto_rsa_*() */ ++ ++ ++static int ctr_drbg_init_state; ++static mbedtls_ctr_drbg_context ctr_drbg; ++static mbedtls_entropy_context entropy; ++ ++#ifdef CRYPTO_MBEDTLS_CRYPTO_BIGNUM ++#include ++static mbedtls_mpi mpi_sw_A; ++#endif ++ ++__attribute_cold__ ++__attribute_noinline__ ++static mbedtls_ctr_drbg_context * ctr_drbg_init(void) ++{ ++ mbedtls_ctr_drbg_init(&ctr_drbg); ++ mbedtls_entropy_init(&entropy); ++ if (mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, ++ NULL, 0)) { ++ wpa_printf(MSG_ERROR, "Init of random number generator failed"); ++ /* XXX: abort? */ ++ } ++ else ++ ctr_drbg_init_state = 1; ++ ++ return &ctr_drbg; ++} ++ ++__attribute_cold__ ++void crypto_unload(void) ++{ ++ if (ctr_drbg_init_state) { ++ mbedtls_ctr_drbg_free(&ctr_drbg); ++ mbedtls_entropy_free(&entropy); ++ #ifdef CRYPTO_MBEDTLS_CRYPTO_BIGNUM ++ mbedtls_mpi_free(&mpi_sw_A); ++ #endif ++ ctr_drbg_init_state = 0; ++ } ++} ++ ++/* init ctr_drbg on first use ++ * crypto_global_init() and crypto_global_deinit() are not available here ++ * (available only when CONFIG_TLS=internal, which is not CONFIG_TLS=mbedtls) */ ++mbedtls_ctr_drbg_context * crypto_mbedtls_ctr_drbg(void); /*(not in header)*/ ++inline ++mbedtls_ctr_drbg_context * crypto_mbedtls_ctr_drbg(void) ++{ ++ return ctr_drbg_init_state ? &ctr_drbg : ctr_drbg_init(); ++} ++ ++#ifdef CRYPTO_MBEDTLS_CONFIG_FIPS ++int crypto_get_random(void *buf, size_t len) ++{ ++ return mbedtls_ctr_drbg_random(crypto_mbedtls_ctr_drbg(),buf,len) ? -1 : 0; ++} ++#endif ++ ++ ++#if 1 ++ ++/* tradeoff: slightly smaller code size here at cost of slight increase ++ * in instructions and function calls at runtime versus the expanded ++ * per-message-digest code that follows in #else (~0.5 kib .text larger) */ ++ ++__attribute_noinline__ ++static int md_vector(size_t num_elem, const u8 *addr[], const size_t *len, ++ u8 *mac, mbedtls_md_type_t md_type) ++{ ++ mbedtls_md_context_t ctx; ++ mbedtls_md_init(&ctx); ++ if (mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 0) != 0){ ++ mbedtls_md_free(&ctx); ++ return -1; ++ } ++ mbedtls_md_starts(&ctx); ++ for (size_t i = 0; i < num_elem; ++i) ++ mbedtls_md_update(&ctx, addr[i], len[i]); ++ mbedtls_md_finish(&ctx, mac); ++ mbedtls_md_free(&ctx); ++ return 0; ++} ++ ++#ifdef MBEDTLS_SHA512_C ++int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) ++{ ++ return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_SHA512); ++} ++ ++int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) ++{ ++ return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_SHA384); ++} ++#endif ++ ++#ifdef MBEDTLS_SHA256_C ++int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) ++{ ++ return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_SHA256); ++} ++#endif ++ ++#ifdef MBEDTLS_SHA1_C ++int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) ++{ ++ return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_SHA1); ++} ++#endif ++ ++#ifdef MBEDTLS_MD5_C ++int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) ++{ ++ return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_MD5); ++} ++#endif ++ ++#ifdef MBEDTLS_MD4_C ++#include ++int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) ++{ ++ return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_MD4); ++} ++#endif ++ ++#else /* expanded per-message-digest functions */ ++ ++#ifdef MBEDTLS_SHA512_C ++#include ++__attribute_noinline__ ++static int sha384_512_vector(size_t num_elem, const u8 *addr[], ++ const size_t *len, u8 *mac, int is384) ++{ ++ struct mbedtls_sha512_context ctx; ++ mbedtls_sha512_init(&ctx); ++ #if MBEDTLS_VERSION_MAJOR >= 3 ++ mbedtls_sha512_starts(&ctx, is384); ++ for (size_t i = 0; i < num_elem; ++i) ++ mbedtls_sha512_update(&ctx, addr[i], len[i]); ++ mbedtls_sha512_finish(&ctx, mac); ++ #else ++ mbedtls_sha512_starts_ret(&ctx, is384); ++ for (size_t i = 0; i < num_elem; ++i) ++ mbedtls_sha512_update_ret(&ctx, addr[i], len[i]); ++ mbedtls_sha512_finish_ret(&ctx, mac); ++ #endif ++ mbedtls_sha512_free(&ctx); ++ return 0; ++} ++ ++int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) ++{ ++ return sha384_512_vector(num_elem, addr, len, mac, 0); ++} ++ ++int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) ++{ ++ return sha384_512_vector(num_elem, addr, len, mac, 1); ++} ++#endif ++ ++#ifdef MBEDTLS_SHA256_C ++#include ++int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) ++{ ++ struct mbedtls_sha256_context ctx; ++ mbedtls_sha256_init(&ctx); ++ #if MBEDTLS_VERSION_MAJOR >= 3 ++ mbedtls_sha256_starts(&ctx, 0); ++ for (size_t i = 0; i < num_elem; ++i) ++ mbedtls_sha256_update(&ctx, addr[i], len[i]); ++ mbedtls_sha256_finish(&ctx, mac); ++ #else ++ mbedtls_sha256_starts_ret(&ctx, 0); ++ for (size_t i = 0; i < num_elem; ++i) ++ mbedtls_sha256_update_ret(&ctx, addr[i], len[i]); ++ mbedtls_sha256_finish_ret(&ctx, mac); ++ #endif ++ mbedtls_sha256_free(&ctx); ++ return 0; ++} ++#endif ++ ++#ifdef MBEDTLS_SHA1_C ++#include ++int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) ++{ ++ struct mbedtls_sha1_context ctx; ++ mbedtls_sha1_init(&ctx); ++ #if MBEDTLS_VERSION_MAJOR >= 3 ++ mbedtls_sha1_starts(&ctx); ++ for (size_t i = 0; i < num_elem; ++i) ++ mbedtls_sha1_update(&ctx, addr[i], len[i]); ++ mbedtls_sha1_finish(&ctx, mac); ++ #else ++ mbedtls_sha1_starts_ret(&ctx); ++ for (size_t i = 0; i < num_elem; ++i) ++ mbedtls_sha1_update_ret(&ctx, addr[i], len[i]); ++ mbedtls_sha1_finish_ret(&ctx, mac); ++ #endif ++ mbedtls_sha1_free(&ctx); ++ return 0; ++} ++#endif ++ ++#ifdef MBEDTLS_MD5_C ++#include ++int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) ++{ ++ struct mbedtls_md5_context ctx; ++ mbedtls_md5_init(&ctx); ++ #if MBEDTLS_VERSION_MAJOR >= 3 ++ mbedtls_md5_starts(&ctx); ++ for (size_t i = 0; i < num_elem; ++i) ++ mbedtls_md5_update(&ctx, addr[i], len[i]); ++ mbedtls_md5_finish(&ctx, mac); ++ #else ++ mbedtls_md5_starts_ret(&ctx); ++ for (size_t i = 0; i < num_elem; ++i) ++ mbedtls_md5_update_ret(&ctx, addr[i], len[i]); ++ mbedtls_md5_finish_ret(&ctx, mac); ++ #endif ++ mbedtls_md5_free(&ctx); ++ return 0; ++} ++#endif ++ ++#ifdef MBEDTLS_MD4_C ++#include ++int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) ++{ ++ struct mbedtls_md4_context ctx; ++ mbedtls_md4_init(&ctx); ++ mbedtls_md4_starts_ret(&ctx); ++ for (size_t i = 0; i < num_elem; ++i) ++ mbedtls_md4_update_ret(&ctx, addr[i], len[i]); ++ mbedtls_md4_finish_ret(&ctx, mac); ++ mbedtls_md4_free(&ctx); ++ return 0; ++} ++#endif ++ ++#endif /* expanded per-message-digest functions */ ++ ++ ++__attribute_noinline__ ++static int hmac_vector(const u8 *key, size_t key_len, size_t num_elem, ++ const u8 *addr[], const size_t *len, u8 *mac, ++ mbedtls_md_type_t md_type) ++{ ++ mbedtls_md_context_t ctx; ++ mbedtls_md_init(&ctx); ++ if (mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 1) != 0){ ++ mbedtls_md_free(&ctx); ++ return -1; ++ } ++ mbedtls_md_hmac_starts(&ctx, key, key_len); ++ for (size_t i = 0; i < num_elem; ++i) ++ mbedtls_md_hmac_update(&ctx, addr[i], len[i]); ++ mbedtls_md_hmac_finish(&ctx, mac); ++ mbedtls_md_free(&ctx); ++ return 0; ++} ++ ++#ifdef MBEDTLS_SHA512_C ++int hmac_sha512_vector(const u8 *key, size_t key_len, size_t num_elem, ++ const u8 *addr[], const size_t *len, u8 *mac) ++{ ++ return hmac_vector(key, key_len, num_elem, addr, len, mac, ++ MBEDTLS_MD_SHA512); ++} ++ ++int hmac_sha512(const u8 *key, size_t key_len, const u8 *data, size_t data_len, ++ u8 *mac) ++{ ++ return hmac_vector(key, key_len, 1, &data, &data_len, mac, ++ MBEDTLS_MD_SHA512); ++} ++ ++int hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem, ++ const u8 *addr[], const size_t *len, u8 *mac) ++{ ++ return hmac_vector(key, key_len, num_elem, addr, len, mac, ++ MBEDTLS_MD_SHA384); ++} ++ ++int hmac_sha384(const u8 *key, size_t key_len, const u8 *data, size_t data_len, ++ u8 *mac) ++{ ++ return hmac_vector(key, key_len, 1, &data, &data_len, mac, ++ MBEDTLS_MD_SHA384); ++} ++#endif ++ ++#ifdef MBEDTLS_SHA256_C ++int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, ++ const u8 *addr[], const size_t *len, u8 *mac) ++{ ++ return hmac_vector(key, key_len, num_elem, addr, len, mac, ++ MBEDTLS_MD_SHA256); ++} ++ ++int hmac_sha256(const u8 *key, size_t key_len, const u8 *data, size_t data_len, ++ u8 *mac) ++{ ++ return hmac_vector(key, key_len, 1, &data, &data_len, mac, ++ MBEDTLS_MD_SHA256); ++} ++#endif ++ ++#ifdef MBEDTLS_SHA1_C ++int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, ++ const u8 *addr[], const size_t *len, u8 *mac) ++{ ++ return hmac_vector(key, key_len, num_elem, addr, len, mac, ++ MBEDTLS_MD_SHA1); ++} ++ ++int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, ++ u8 *mac) ++{ ++ return hmac_vector(key, key_len, 1, &data, &data_len, mac, ++ MBEDTLS_MD_SHA1); ++} ++#endif ++ ++#ifdef MBEDTLS_MD5_C ++int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem, ++ const u8 *addr[], const size_t *len, u8 *mac) ++{ ++ return hmac_vector(key, key_len, num_elem, addr, len, mac, ++ MBEDTLS_MD_MD5); ++} ++ ++int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, ++ u8 *mac) ++{ ++ return hmac_vector(key, key_len, 1, &data, &data_len, mac, ++ MBEDTLS_MD_MD5); ++} ++#endif ++ ++ ++#if defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA512_C) ++ ++#if defined(CRYPTO_MBEDTLS_HMAC_KDF_SHA256) \ ++ || defined(CRYPTO_MBEDTLS_HMAC_KDF_SHA384) \ ++ || defined(CRYPTO_MBEDTLS_HMAC_KDF_SHA512) ++ ++#include ++ ++/* sha256-kdf.c sha384-kdf.c sha512-kdf.c */ ++ ++/* HMAC-SHA256 KDF (RFC 5295) and HKDF-Expand(SHA256) (RFC 5869) */ ++/* HMAC-SHA384 KDF (RFC 5295) and HKDF-Expand(SHA384) (RFC 5869) */ ++/* HMAC-SHA512 KDF (RFC 5295) and HKDF-Expand(SHA512) (RFC 5869) */ ++__attribute_noinline__ ++static int hmac_kdf_expand(const u8 *prk, size_t prk_len, ++ const char *label, const u8 *info, size_t info_len, ++ u8 *okm, size_t okm_len, mbedtls_md_type_t md_type) ++{ ++ const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type); ++ #ifdef MBEDTLS_HKDF_C ++ if (label == NULL) /* RFC 5869 HKDF-Expand when (label == NULL) */ ++ return mbedtls_hkdf_expand(md_info, prk, prk_len, info, ++ info_len, okm, okm_len) ? -1 : 0; ++ #endif ++ ++ const size_t mac_len = mbedtls_md_get_size(md_info); ++ /* okm_len must not exceed 255 times hash len (RFC 5869 Section 2.3) */ ++ if (okm_len > ((mac_len << 8) - mac_len)) ++ return -1; ++ ++ mbedtls_md_context_t ctx; ++ mbedtls_md_init(&ctx); ++ if (mbedtls_md_setup(&ctx, md_info, 1) != 0) { ++ mbedtls_md_free(&ctx); ++ return -1; ++ } ++ mbedtls_md_hmac_starts(&ctx, prk, prk_len); ++ ++ u8 iter = 1; ++ const u8 *addr[4] = { okm, (const u8 *)label, info, &iter }; ++ size_t len[4] = { 0, label ? os_strlen(label)+1 : 0, info_len, 1 }; ++ ++ for (; okm_len >= mac_len; okm_len -= mac_len, ++iter) { ++ for (size_t i = 0; i < ARRAY_SIZE(addr); ++i) ++ mbedtls_md_hmac_update(&ctx, addr[i], len[i]); ++ mbedtls_md_hmac_finish(&ctx, okm); ++ mbedtls_md_hmac_reset(&ctx); ++ addr[0] = okm; ++ okm += mac_len; ++ len[0] = mac_len; /*(include digest in subsequent rounds)*/ ++ } ++ ++ if (okm_len) { ++ u8 hash[MBEDTLS_MD_MAX_SIZE]; ++ for (size_t i = 0; i < ARRAY_SIZE(addr); ++i) ++ mbedtls_md_hmac_update(&ctx, addr[i], len[i]); ++ mbedtls_md_hmac_finish(&ctx, hash); ++ os_memcpy(okm, hash, okm_len); ++ forced_memzero(hash, mac_len); ++ } ++ ++ mbedtls_md_free(&ctx); ++ return 0; ++} ++ ++#ifdef MBEDTLS_SHA512_C ++#ifdef CRYPTO_MBEDTLS_HMAC_KDF_SHA512 ++int hmac_sha512_kdf(const u8 *secret, size_t secret_len, ++ const char *label, const u8 *seed, size_t seed_len, ++ u8 *out, size_t outlen) ++{ ++ return hmac_kdf_expand(secret, secret_len, label, seed, seed_len, ++ out, outlen, MBEDTLS_MD_SHA512); ++} ++#endif ++ ++#ifdef CRYPTO_MBEDTLS_HMAC_KDF_SHA384 ++int hmac_sha384_kdf(const u8 *secret, size_t secret_len, ++ const char *label, const u8 *seed, size_t seed_len, ++ u8 *out, size_t outlen) ++{ ++ return hmac_kdf_expand(secret, secret_len, label, seed, seed_len, ++ out, outlen, MBEDTLS_MD_SHA384); ++} ++#endif ++#endif ++ ++#ifdef MBEDTLS_SHA256_C ++#ifdef CRYPTO_MBEDTLS_HMAC_KDF_SHA256 ++int hmac_sha256_kdf(const u8 *secret, size_t secret_len, ++ const char *label, const u8 *seed, size_t seed_len, ++ u8 *out, size_t outlen) ++{ ++ return hmac_kdf_expand(secret, secret_len, label, seed, seed_len, ++ out, outlen, MBEDTLS_MD_SHA256); ++} ++#endif ++#endif ++ ++#endif /* CRYPTO_MBEDTLS_HMAC_KDF_* */ ++ ++ ++/* sha256-prf.c sha384-prf.c sha512-prf.c */ ++ ++/* hmac_prf_bits - IEEE Std 802.11ac-2013, 11.6.1.7.2 Key derivation function */ ++__attribute_noinline__ ++static int hmac_prf_bits(const u8 *key, size_t key_len, const char *label, ++ const u8 *data, size_t data_len, u8 *buf, ++ size_t buf_len_bits, mbedtls_md_type_t md_type) ++{ ++ mbedtls_md_context_t ctx; ++ mbedtls_md_init(&ctx); ++ const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type); ++ if (mbedtls_md_setup(&ctx, md_info, 1) != 0) { ++ mbedtls_md_free(&ctx); ++ return -1; ++ } ++ mbedtls_md_hmac_starts(&ctx, key, key_len); ++ ++ u16 ctr, n_le = host_to_le16(buf_len_bits); ++ const u8 * const addr[] = { (u8 *)&ctr,(u8 *)label,data,(u8 *)&n_le }; ++ const size_t len[] = { 2, os_strlen(label), data_len, 2 }; ++ const size_t mac_len = mbedtls_md_get_size(md_info); ++ size_t buf_len = (buf_len_bits + 7) / 8; ++ for (ctr = 1; buf_len >= mac_len; buf_len -= mac_len, ++ctr) { ++ #if __BYTE_ORDER == __BIG_ENDIAN ++ ctr = host_to_le16(ctr); ++ #endif ++ for (size_t i = 0; i < ARRAY_SIZE(addr); ++i) ++ mbedtls_md_hmac_update(&ctx, addr[i], len[i]); ++ mbedtls_md_hmac_finish(&ctx, buf); ++ mbedtls_md_hmac_reset(&ctx); ++ buf += mac_len; ++ #if __BYTE_ORDER == __BIG_ENDIAN ++ ctr = le_to_host16(ctr); ++ #endif ++ } ++ ++ if (buf_len) { ++ u8 hash[MBEDTLS_MD_MAX_SIZE]; ++ #if __BYTE_ORDER == __BIG_ENDIAN ++ ctr = host_to_le16(ctr); ++ #endif ++ for (size_t i = 0; i < ARRAY_SIZE(addr); ++i) ++ mbedtls_md_hmac_update(&ctx, addr[i], len[i]); ++ mbedtls_md_hmac_finish(&ctx, hash); ++ os_memcpy(buf, hash, buf_len); ++ buf += buf_len; ++ forced_memzero(hash, mac_len); ++ } ++ ++ /* Mask out unused bits in last octet if it does not use all the bits */ ++ if ((buf_len_bits &= 0x7)) ++ buf[-1] &= (u8)(0xff << (8 - buf_len_bits)); ++ ++ mbedtls_md_free(&ctx); ++ return 0; ++} ++ ++#ifdef MBEDTLS_SHA512_C ++int sha512_prf(const u8 *key, size_t key_len, const char *label, ++ const u8 *data, size_t data_len, u8 *buf, size_t buf_len) ++{ ++ return hmac_prf_bits(key, key_len, label, data, data_len, buf, ++ buf_len * 8, MBEDTLS_MD_SHA512); ++} ++ ++int sha384_prf(const u8 *key, size_t key_len, const char *label, ++ const u8 *data, size_t data_len, u8 *buf, size_t buf_len) ++{ ++ return hmac_prf_bits(key, key_len, label, data, data_len, buf, ++ buf_len * 8, MBEDTLS_MD_SHA384); ++} ++#endif ++ ++#ifdef MBEDTLS_SHA256_C ++int sha256_prf(const u8 *key, size_t key_len, const char *label, ++ const u8 *data, size_t data_len, u8 *buf, size_t buf_len) ++{ ++ return hmac_prf_bits(key, key_len, label, data, data_len, buf, ++ buf_len * 8, MBEDTLS_MD_SHA256); ++} ++ ++int sha256_prf_bits(const u8 *key, size_t key_len, const char *label, ++ const u8 *data, size_t data_len, u8 *buf, ++ size_t buf_len_bits) ++{ ++ return hmac_prf_bits(key, key_len, label, data, data_len, buf, ++ buf_len_bits, MBEDTLS_MD_SHA256); ++} ++#endif ++ ++#endif /* MBEDTLS_SHA256_C || MBEDTLS_SHA512_C */ ++ ++ ++#ifdef MBEDTLS_SHA1_C ++ ++/* sha1-prf.c */ ++ ++/* sha1_prf - SHA1-based Pseudo-Random Function (PRF) (IEEE 802.11i, 8.5.1.1) */ ++ ++int sha1_prf(const u8 *key, size_t key_len, const char *label, ++ const u8 *data, size_t data_len, u8 *buf, size_t buf_len) ++{ ++ /*(note: algorithm differs from hmac_prf_bits() */ ++ /*(note: smaller code size instead of expanding hmac_sha1_vector() ++ * as is done in hmac_prf_bits(); not expecting large num of loops) */ ++ u8 counter = 0; ++ const u8 *addr[] = { (u8 *)label, data, &counter }; ++ const size_t len[] = { os_strlen(label)+1, data_len, 1 }; ++ ++ for (; buf_len >= SHA1_MAC_LEN; buf_len -= SHA1_MAC_LEN, ++counter) { ++ if (hmac_sha1_vector(key, key_len, 3, addr, len, buf)) ++ return -1; ++ buf += SHA1_MAC_LEN; ++ } ++ ++ if (buf_len) { ++ u8 hash[SHA1_MAC_LEN]; ++ if (hmac_sha1_vector(key, key_len, 3, addr, len, hash)) ++ return -1; ++ os_memcpy(buf, hash, buf_len); ++ forced_memzero(hash, sizeof(hash)); ++ } ++ ++ return 0; ++} ++ ++#ifdef CRYPTO_MBEDTLS_SHA1_T_PRF ++ ++/* sha1-tprf.c */ ++ ++/* sha1_t_prf - EAP-FAST Pseudo-Random Function (T-PRF) (RFC 4851,Section 5.5)*/ ++ ++int sha1_t_prf(const u8 *key, size_t key_len, const char *label, ++ const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len) ++{ ++ /*(note: algorithm differs from hmac_prf_bits() and hmac_kdf() above)*/ ++ /*(note: smaller code size instead of expanding hmac_sha1_vector() ++ * as is done in hmac_prf_bits(); not expecting large num of loops) */ ++ u8 ctr; ++ u16 olen = host_to_be16(buf_len); ++ const u8 *addr[] = { buf, (u8 *)label, seed, (u8 *)&olen, &ctr }; ++ size_t len[] = { 0, os_strlen(label)+1, seed_len, 2, 1 }; ++ ++ for (ctr = 1; buf_len >= SHA1_MAC_LEN; buf_len -= SHA1_MAC_LEN, ++ctr) { ++ if (hmac_sha1_vector(key, key_len, 5, addr, len, buf)) ++ return -1; ++ addr[0] = buf; ++ buf += SHA1_MAC_LEN; ++ len[0] = SHA1_MAC_LEN; /*(include digest in subsequent rounds)*/ ++ } ++ ++ if (buf_len) { ++ u8 hash[SHA1_MAC_LEN]; ++ if (hmac_sha1_vector(key, key_len, 5, addr, len, hash)) ++ return -1; ++ os_memcpy(buf, hash, buf_len); ++ forced_memzero(hash, sizeof(hash)); ++ } ++ ++ return 0; ++} ++ ++#endif /* CRYPTO_MBEDTLS_SHA1_T_PRF */ ++ ++#endif /* MBEDTLS_SHA1_C */ ++ ++ ++#ifdef CRYPTO_MBEDTLS_DES_ENCRYPT ++#ifdef MBEDTLS_DES_C ++#include ++int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) ++{ ++ u8 pkey[8], next, tmp; ++ int i; ++ ++ /* Add parity bits to the key */ ++ next = 0; ++ for (i = 0; i < 7; i++) { ++ tmp = key[i]; ++ pkey[i] = (tmp >> i) | next | 1; ++ next = tmp << (7 - i); ++ } ++ pkey[i] = next | 1; ++ ++ mbedtls_des_context des; ++ mbedtls_des_init(&des); ++ int ret = mbedtls_des_setkey_enc(&des, pkey) ++ || mbedtls_des_crypt_ecb(&des, clear, cypher) ? -1 : 0; ++ mbedtls_des_free(&des); ++ return ret; ++} ++#else ++#include "des-internal.c"/* pull in hostap local implementation */ ++#endif ++#endif ++ ++ ++#ifdef CRYPTO_MBEDTLS_PBKDF2_SHA1 ++/* sha1-pbkdf2.c */ ++#include ++int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len, ++ int iterations, u8 *buf, size_t buflen) ++{ ++ #if MBEDTLS_VERSION_NUMBER >= 0x03020200 /* mbedtls 3.2.2 */ ++ return mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA1, ++ (const u8 *)passphrase, os_strlen(passphrase), ++ ssid, ssid_len, iterations, 32, buf) ? -1 : 0; ++ #else ++ const mbedtls_md_info_t *md_info; ++ md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); ++ if (md_info == NULL) ++ return -1; ++ mbedtls_md_context_t ctx; ++ mbedtls_md_init(&ctx); ++ int ret = mbedtls_md_setup(&ctx, md_info, 1) ++ || mbedtls_pkcs5_pbkdf2_hmac(&ctx, ++ (const u8 *)passphrase, os_strlen(passphrase), ++ ssid, ssid_len, iterations, 32, buf) ? -1 : 0; ++ mbedtls_md_free(&ctx); ++ return ret; ++ #endif ++} ++#endif ++ ++ ++/*#include "aes.h"*/ /* prototypes also included in "crypto.h" */ ++ ++static void *aes_crypt_init_mode(const u8 *key, size_t len, int mode) ++{ ++ mbedtls_aes_context *aes = os_malloc(sizeof(*aes)); ++ if (!aes) ++ return NULL; ++ ++ mbedtls_aes_init(aes); ++ if ((mode == MBEDTLS_AES_ENCRYPT ++ ? mbedtls_aes_setkey_enc(aes, key, len * 8) ++ : mbedtls_aes_setkey_dec(aes, key, len * 8)) == 0) ++ return aes; ++ ++ mbedtls_aes_free(aes); ++ os_free(aes); ++ return NULL; ++} ++ ++void *aes_encrypt_init(const u8 *key, size_t len) ++{ ++ return aes_crypt_init_mode(key, len, MBEDTLS_AES_ENCRYPT); ++} ++ ++int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) ++{ ++ return mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, plain, crypt); ++} ++ ++void aes_encrypt_deinit(void *ctx) ++{ ++ mbedtls_aes_free(ctx); ++ os_free(ctx); ++} ++ ++void *aes_decrypt_init(const u8 *key, size_t len) ++{ ++ return aes_crypt_init_mode(key, len, MBEDTLS_AES_DECRYPT); ++} ++ ++int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) ++{ ++ return mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_DECRYPT, crypt, plain); ++} ++ ++void aes_decrypt_deinit(void *ctx) ++{ ++ mbedtls_aes_free(ctx); ++ os_free(ctx); ++} ++ ++ ++#include "aes_wrap.h" ++ ++ ++#ifdef MBEDTLS_NIST_KW_C ++ ++#include ++ ++/* aes-wrap.c */ ++int aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, u8 *cipher) ++{ ++ mbedtls_nist_kw_context ctx; ++ mbedtls_nist_kw_init(&ctx); ++ size_t olen; ++ int ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, ++ kek, kek_len*8, 1) ++ || mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KW, plain, n*8, ++ cipher, &olen, (n+1)*8) ? -1 : 0; ++ mbedtls_nist_kw_free(&ctx); ++ return ret; ++} ++ ++/* aes-unwrap.c */ ++int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher, u8 *plain) ++{ ++ mbedtls_nist_kw_context ctx; ++ mbedtls_nist_kw_init(&ctx); ++ size_t olen; ++ int ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, ++ kek, kek_len*8, 0) ++ || mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KW, cipher, ++ (n+1)*8, plain, &olen, n*8) ? -1 : 0; ++ mbedtls_nist_kw_free(&ctx); ++ return ret; ++} ++ ++#else ++ ++#ifndef CRYPTO_MBEDTLS_CONFIG_FIPS ++#include "aes-wrap.c" /* pull in hostap local implementation */ ++#include "aes-unwrap.c" /* pull in hostap local implementation */ ++#endif ++ ++#endif /* MBEDTLS_NIST_KW_C */ ++ ++ ++#ifdef MBEDTLS_CMAC_C ++ ++/* aes-omac1.c */ ++ ++#include ++ ++int omac1_aes_vector( ++ const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], ++ const size_t *len, u8 *mac) ++{ ++ mbedtls_cipher_type_t cipher_type; ++ switch (key_len) { ++ case 16: cipher_type = MBEDTLS_CIPHER_AES_128_ECB; break; ++ case 24: cipher_type = MBEDTLS_CIPHER_AES_192_ECB; break; ++ case 32: cipher_type = MBEDTLS_CIPHER_AES_256_ECB; break; ++ default: return -1; ++ } ++ const mbedtls_cipher_info_t *cipher_info; ++ cipher_info = mbedtls_cipher_info_from_type(cipher_type); ++ if (cipher_info == NULL) ++ return -1; ++ ++ mbedtls_cipher_context_t ctx; ++ mbedtls_cipher_init(&ctx); ++ int ret = -1; ++ if (mbedtls_cipher_setup(&ctx, cipher_info) == 0 ++ && mbedtls_cipher_cmac_starts(&ctx, key, key_len*8) == 0) { ++ ret = 0; ++ for (size_t i = 0; i < num_elem && ret == 0; ++i) ++ ret = mbedtls_cipher_cmac_update(&ctx, addr[i], len[i]); ++ } ++ if (ret == 0) ++ ret = mbedtls_cipher_cmac_finish(&ctx, mac); ++ mbedtls_cipher_free(&ctx); ++ return ret ? -1 : 0; ++} ++ ++int omac1_aes_128_vector(const u8 *key, size_t num_elem, ++ const u8 *addr[], const size_t *len, ++ u8 *mac) ++{ ++ return omac1_aes_vector(key, 16, num_elem, addr, len, mac); ++} ++ ++int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac) ++{ ++ return omac1_aes_vector(key, 16, 1, &data, &data_len, mac); ++} ++ ++int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac) ++{ ++ return omac1_aes_vector(key, 32, 1, &data, &data_len, mac); ++} ++ ++#else ++ ++#include "aes-omac1.c" /* pull in hostap local implementation */ ++ ++#ifndef MBEDTLS_AES_BLOCK_SIZE ++#define MBEDTLS_AES_BLOCK_SIZE 16 ++#endif ++ ++#endif /* MBEDTLS_CMAC_C */ ++ ++ ++/* These interfaces can be inefficient when used in loops, as the overhead of ++ * initialization each call is large for each block input (e.g. 16 bytes) */ ++ ++ ++/* aes-encblock.c */ ++int aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out) ++{ ++ mbedtls_aes_context aes; ++ mbedtls_aes_init(&aes); ++ int ret = mbedtls_aes_setkey_enc(&aes, key, 128) ++ || mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_ENCRYPT, in, out) ++ ? -1 ++ : 0; ++ mbedtls_aes_free(&aes); ++ return ret; ++} ++ ++ ++/* aes-ctr.c */ ++int aes_ctr_encrypt(const u8 *key, size_t key_len, const u8 *nonce, ++ u8 *data, size_t data_len) ++{ ++ unsigned char counter[MBEDTLS_AES_BLOCK_SIZE]; ++ unsigned char stream_block[MBEDTLS_AES_BLOCK_SIZE]; ++ os_memcpy(counter, nonce, MBEDTLS_AES_BLOCK_SIZE);/*(must be writable)*/ ++ ++ mbedtls_aes_context ctx; ++ mbedtls_aes_init(&ctx); ++ size_t nc_off = 0; ++ int ret = mbedtls_aes_setkey_enc(&ctx, key, key_len*8) ++ || mbedtls_aes_crypt_ctr(&ctx, data_len, &nc_off, ++ counter, stream_block, ++ data, data) ? -1 : 0; ++ forced_memzero(stream_block, sizeof(stream_block)); ++ mbedtls_aes_free(&ctx); ++ return ret; ++} ++ ++int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce, ++ u8 *data, size_t data_len) ++{ ++ return aes_ctr_encrypt(key, 16, nonce, data, data_len); ++} ++ ++ ++/* aes-cbc.c */ ++static int aes_128_cbc_oper(const u8 *key, const u8 *iv, ++ u8 *data, size_t data_len, int mode) ++{ ++ unsigned char ivec[MBEDTLS_AES_BLOCK_SIZE]; ++ os_memcpy(ivec, iv, MBEDTLS_AES_BLOCK_SIZE); /*(must be writable)*/ ++ ++ mbedtls_aes_context ctx; ++ mbedtls_aes_init(&ctx); ++ int ret = (mode == MBEDTLS_AES_ENCRYPT ++ ? mbedtls_aes_setkey_enc(&ctx, key, 128) ++ : mbedtls_aes_setkey_dec(&ctx, key, 128)) ++ || mbedtls_aes_crypt_cbc(&ctx, mode, data_len, ivec, data, data); ++ mbedtls_aes_free(&ctx); ++ return ret ? -1 : 0; ++} ++ ++int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) ++{ ++ return aes_128_cbc_oper(key, iv, data, data_len, MBEDTLS_AES_ENCRYPT); ++} ++ ++int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) ++{ ++ return aes_128_cbc_oper(key, iv, data, data_len, MBEDTLS_AES_DECRYPT); ++} ++ ++ ++/* ++ * Much of the following is documented in crypto.h as for CONFIG_TLS=internal ++ * but such comments are not accurate: ++ * ++ * "This function is only used with internal TLSv1 implementation ++ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need ++ * to implement this." ++ */ ++ ++ ++#ifdef CRYPTO_MBEDTLS_CRYPTO_CIPHER ++ ++#include ++ ++struct crypto_cipher ++{ ++ mbedtls_cipher_context_t ctx_enc; ++ mbedtls_cipher_context_t ctx_dec; ++}; ++ ++struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, ++ const u8 *iv, const u8 *key, ++ size_t key_len) ++{ ++ /* IKEv2 src/eap_common/ikev2_common.c:ikev2_{encr,decr}_encrypt() ++ * uses one of CRYPTO_CIPHER_ALG_AES or CRYPTO_CIPHER_ALG_3DES */ ++ ++ mbedtls_cipher_type_t cipher_type; ++ size_t iv_len; ++ switch (alg) { ++ #ifdef MBEDTLS_ARC4_C ++ #if 0 ++ case CRYPTO_CIPHER_ALG_RC4: ++ cipher_type = MBEDTLS_CIPHER_ARC4_128; ++ iv_len = 0; ++ break; ++ #endif ++ #endif ++ #ifdef MBEDTLS_AES_C ++ case CRYPTO_CIPHER_ALG_AES: ++ if (key_len == 16) cipher_type = MBEDTLS_CIPHER_AES_128_CTR; ++ if (key_len == 24) cipher_type = MBEDTLS_CIPHER_AES_192_CTR; ++ if (key_len == 32) cipher_type = MBEDTLS_CIPHER_AES_256_CTR; ++ iv_len = 16; ++ break; ++ #endif ++ #ifdef MBEDTLS_DES_C ++ case CRYPTO_CIPHER_ALG_3DES: ++ cipher_type = MBEDTLS_CIPHER_DES_EDE3_CBC; ++ iv_len = 8; ++ break; ++ #if 0 ++ case CRYPTO_CIPHER_ALG_DES: ++ cipher_type = MBEDTLS_CIPHER_DES_CBC; ++ iv_len = 8; ++ break; ++ #endif ++ #endif ++ default: ++ return NULL; ++ } ++ ++ const mbedtls_cipher_info_t *cipher_info; ++ cipher_info = mbedtls_cipher_info_from_type(cipher_type); ++ if (cipher_info == NULL) ++ return NULL; ++ ++ key_len *= 8; /* key_bitlen */ ++ #if 0 /*(were key_bitlen not already available)*/ ++ #if MBEDTLS_VERSION_NUMBER >= 0x03010000 /* mbedtls 3.1.0 */ ++ key_len = mbedtls_cipher_info_get_key_bitlen(cipher_info); ++ #else ++ key_len = cipher_info->MBEDTLS_PRIVATE(key_bitlen); ++ #endif ++ #endif ++ ++ #if 0 /*(were iv_len not known above, would need MBEDTLS_PRIVATE(iv_size))*/ ++ iv_len = cipher_info->MBEDTLS_PRIVATE(iv_size); ++ #endif ++ ++ struct crypto_cipher *ctx = os_malloc(sizeof(*ctx)); ++ if (!ctx) ++ return NULL; ++ ++ mbedtls_cipher_init(&ctx->ctx_enc); ++ mbedtls_cipher_init(&ctx->ctx_dec); ++ if ( mbedtls_cipher_setup(&ctx->ctx_enc,cipher_info) == 0 ++ && mbedtls_cipher_setup(&ctx->ctx_dec,cipher_info) == 0 ++ && mbedtls_cipher_setkey(&ctx->ctx_enc,key,key_len,MBEDTLS_ENCRYPT) == 0 ++ && mbedtls_cipher_setkey(&ctx->ctx_dec,key,key_len,MBEDTLS_DECRYPT) == 0 ++ && mbedtls_cipher_set_iv(&ctx->ctx_enc,iv,iv_len) == 0 ++ && mbedtls_cipher_set_iv(&ctx->ctx_dec,iv,iv_len) == 0 ++ && mbedtls_cipher_reset(&ctx->ctx_enc) == 0 ++ && mbedtls_cipher_reset(&ctx->ctx_dec) == 0) { ++ return ctx; ++ } ++ ++ mbedtls_cipher_free(&ctx->ctx_enc); ++ mbedtls_cipher_free(&ctx->ctx_dec); ++ os_free(ctx); ++ return NULL; ++} ++ ++int crypto_cipher_encrypt(struct crypto_cipher *ctx, ++ const u8 *plain, u8 *crypt, size_t len) ++{ ++ size_t olen = 0; /*(poor interface above; unknown size of u8 *crypt)*/ ++ return (mbedtls_cipher_update(&ctx->ctx_enc, plain, len, crypt, &olen) ++ || mbedtls_cipher_finish(&ctx->ctx_enc, crypt + olen, &olen)) ? -1 : 0; ++} ++ ++int crypto_cipher_decrypt(struct crypto_cipher *ctx, ++ const u8 *crypt, u8 *plain, size_t len) ++{ ++ size_t olen = 0; /*(poor interface above; unknown size of u8 *plain)*/ ++ return (mbedtls_cipher_update(&ctx->ctx_dec, crypt, len, plain, &olen) ++ || mbedtls_cipher_finish(&ctx->ctx_dec, plain + olen, &olen)) ? -1 : 0; ++} ++ ++void crypto_cipher_deinit(struct crypto_cipher *ctx) ++{ ++ mbedtls_cipher_free(&ctx->ctx_enc); ++ mbedtls_cipher_free(&ctx->ctx_dec); ++ os_free(ctx); ++} ++ ++#endif /* CRYPTO_MBEDTLS_CRYPTO_CIPHER */ ++ ++ ++#ifdef CRYPTO_MBEDTLS_CRYPTO_HASH ++ ++struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, ++ size_t key_len) ++{ ++ mbedtls_md_type_t md_type; ++ int is_hmac = 0; ++ ++ switch (alg) { ++ #ifdef MBEDTLS_MD5_C ++ case CRYPTO_HASH_ALG_MD5: ++ md_type = MBEDTLS_MD_MD5; ++ break; ++ #endif ++ #ifdef MBEDTLS_SHA1_C ++ case CRYPTO_HASH_ALG_SHA1: ++ md_type = MBEDTLS_MD_SHA1; ++ break; ++ #endif ++ #ifdef MBEDTLS_MD5_C ++ case CRYPTO_HASH_ALG_HMAC_MD5: ++ md_type = MBEDTLS_MD_MD5; ++ is_hmac = 1; ++ break; ++ #endif ++ #ifdef MBEDTLS_SHA1_C ++ case CRYPTO_HASH_ALG_HMAC_SHA1: ++ md_type = MBEDTLS_MD_SHA1; ++ is_hmac = 1; ++ break; ++ #endif ++ #ifdef MBEDTLS_SHA256_C ++ case CRYPTO_HASH_ALG_SHA256: ++ md_type = MBEDTLS_MD_SHA256; ++ break; ++ case CRYPTO_HASH_ALG_HMAC_SHA256: ++ md_type = MBEDTLS_MD_SHA256; ++ is_hmac = 1; ++ break; ++ #endif ++ #ifdef MBEDTLS_SHA512_C ++ case CRYPTO_HASH_ALG_SHA384: ++ md_type = MBEDTLS_MD_SHA384; ++ break; ++ case CRYPTO_HASH_ALG_SHA512: ++ md_type = MBEDTLS_MD_SHA512; ++ break; ++ #endif ++ default: ++ return NULL; ++ } ++ ++ const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type); ++ if (!md_info) ++ return NULL; ++ ++ mbedtls_md_context_t *mctx = os_malloc(sizeof(*mctx)); ++ if (mctx == NULL) ++ return NULL; ++ ++ mbedtls_md_init(mctx); ++ if (mbedtls_md_setup(mctx, md_info, is_hmac) != 0) { ++ os_free(mctx); ++ return NULL; ++ } ++ ++ if (is_hmac) ++ mbedtls_md_hmac_starts(mctx, key, key_len); ++ else ++ mbedtls_md_starts(mctx); ++ return (struct crypto_hash *)((uintptr_t)mctx | is_hmac); ++} ++ ++void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) ++{ ++ mbedtls_md_context_t *mctx = (mbedtls_md_context_t*)((uintptr_t)ctx & ~1uL); ++ #if 0 ++ /*(mbedtls_md_hmac_update() and mbedtls_md_update() ++ * make same modifications under the hood in mbedtls)*/ ++ if ((uintptr_t)ctx & 1uL) ++ mbedtls_md_hmac_update(mctx, data, len); ++ else ++ #endif ++ mbedtls_md_update(mctx, data, len); ++} ++ ++int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) ++{ ++ mbedtls_md_context_t *mctx = (mbedtls_md_context_t*)((uintptr_t)ctx & ~1uL); ++ if (mac != NULL && len != NULL) { /*(NULL if caller just freeing context)*/ ++ #if MBEDTLS_VERSION_NUMBER >= 0x03020000 /* mbedtls 3.2.0 */ ++ const mbedtls_md_info_t *md_info = mbedtls_md_info_from_ctx(mctx); ++ #else ++ const mbedtls_md_info_t *md_info = mctx->MBEDTLS_PRIVATE(md_info); ++ #endif ++ size_t maclen = mbedtls_md_get_size(md_info); ++ if (*len < maclen) { ++ *len = maclen; ++ /*(note: ctx not freed; can call again with larger *len)*/ ++ return -1; ++ } ++ *len = maclen; ++ if ((uintptr_t)ctx & 1uL) ++ mbedtls_md_hmac_finish(mctx, mac); ++ else ++ mbedtls_md_finish(mctx, mac); ++ } ++ mbedtls_md_free(mctx); ++ os_free(mctx); ++ return 0; ++} ++ ++#endif /* CRYPTO_MBEDTLS_CRYPTO_HASH */ ++ ++ ++#ifdef CRYPTO_MBEDTLS_CRYPTO_BIGNUM ++ ++#include ++ ++/* crypto.h bignum interfaces */ ++ ++struct crypto_bignum *crypto_bignum_init(void) ++{ ++ mbedtls_mpi *bn = os_malloc(sizeof(*bn)); ++ if (bn) ++ mbedtls_mpi_init(bn); ++ return (struct crypto_bignum *)bn; ++} ++ ++struct crypto_bignum *crypto_bignum_init_set(const u8 *buf, size_t len) ++{ ++ mbedtls_mpi *bn = os_malloc(sizeof(*bn)); ++ if (bn) { ++ mbedtls_mpi_init(bn); ++ if (mbedtls_mpi_read_binary(bn, buf, len) == 0) ++ return (struct crypto_bignum *)bn; ++ } ++ ++ os_free(bn); ++ return NULL; ++} ++ ++struct crypto_bignum *crypto_bignum_init_uint(unsigned int val) ++{ ++ #if 0 /*(hostap use of this interface passes int, not uint)*/ ++ val = host_to_be32(val); ++ return crypto_bignum_init_set((const u8 *)&val, sizeof(val)); ++ #else ++ mbedtls_mpi *bn = os_malloc(sizeof(*bn)); ++ if (bn) { ++ mbedtls_mpi_init(bn); ++ if (mbedtls_mpi_lset(bn, (int)val) == 0) ++ return (struct crypto_bignum *)bn; ++ } ++ ++ os_free(bn); ++ return NULL; ++ #endif ++} ++ ++void crypto_bignum_deinit(struct crypto_bignum *n, int clear) ++{ ++ mbedtls_mpi_free((mbedtls_mpi *)n); ++ os_free(n); ++} ++ ++int crypto_bignum_to_bin(const struct crypto_bignum *a, ++ u8 *buf, size_t buflen, size_t padlen) ++{ ++ size_t n = mbedtls_mpi_size((mbedtls_mpi *)a); ++ if (n < padlen) ++ n = padlen; ++ return n > buflen || mbedtls_mpi_write_binary((mbedtls_mpi *)a, buf, n) ++ ? -1 ++ : (int)(n); ++} ++ ++int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m) ++{ ++ /*assert(r != m);*//* r must not be same as m for mbedtls_mpi_random()*/ ++ #if MBEDTLS_VERSION_NUMBER >= 0x021B0000 /* mbedtls 2.27.0 */ ++ return mbedtls_mpi_random((mbedtls_mpi *)r, 0, (mbedtls_mpi *)m, ++ mbedtls_ctr_drbg_random, ++ crypto_mbedtls_ctr_drbg()) ? -1 : 0; ++ #else ++ /* (needed by EAP_PWD, SAE, DPP) */ ++ wpa_printf(MSG_ERROR, ++ "mbedtls 2.27.0 or later required for mbedtls_mpi_random()"); ++ return -1; ++ #endif ++} ++ ++int crypto_bignum_add(const struct crypto_bignum *a, ++ const struct crypto_bignum *b, ++ struct crypto_bignum *c) ++{ ++ return mbedtls_mpi_add_mpi((mbedtls_mpi *)c, ++ (const mbedtls_mpi *)a, ++ (const mbedtls_mpi *)b) ? -1 : 0; ++} ++ ++int crypto_bignum_mod(const struct crypto_bignum *a, ++ const struct crypto_bignum *b, ++ struct crypto_bignum *c) ++{ ++ return mbedtls_mpi_mod_mpi((mbedtls_mpi *)c, ++ (const mbedtls_mpi *)a, ++ (const mbedtls_mpi *)b) ? -1 : 0; ++} ++ ++int crypto_bignum_exptmod(const struct crypto_bignum *a, ++ const struct crypto_bignum *b, ++ const struct crypto_bignum *c, ++ struct crypto_bignum *d) ++{ ++ /* (check if input params match d; d is the result) */ ++ /* (a == d) is ok in current mbedtls implementation */ ++ if (b == d || c == d) { /*(not ok; store result in intermediate)*/ ++ mbedtls_mpi R; ++ mbedtls_mpi_init(&R); ++ int rc = mbedtls_mpi_exp_mod(&R, ++ (const mbedtls_mpi *)a, ++ (const mbedtls_mpi *)b, ++ (const mbedtls_mpi *)c, ++ NULL) ++ || mbedtls_mpi_copy((mbedtls_mpi *)d, &R) ? -1 : 0; ++ mbedtls_mpi_free(&R); ++ return rc; ++ } ++ else { ++ return mbedtls_mpi_exp_mod((mbedtls_mpi *)d, ++ (const mbedtls_mpi *)a, ++ (const mbedtls_mpi *)b, ++ (const mbedtls_mpi *)c, ++ NULL) ? -1 : 0; ++ } ++} ++ ++int crypto_bignum_inverse(const struct crypto_bignum *a, ++ const struct crypto_bignum *b, ++ struct crypto_bignum *c) ++{ ++ return mbedtls_mpi_inv_mod((mbedtls_mpi *)c, ++ (const mbedtls_mpi *)a, ++ (const mbedtls_mpi *)b) ? -1 : 0; ++} ++ ++int crypto_bignum_sub(const struct crypto_bignum *a, ++ const struct crypto_bignum *b, ++ struct crypto_bignum *c) ++{ ++ return mbedtls_mpi_sub_mpi((mbedtls_mpi *)c, ++ (const mbedtls_mpi *)a, ++ (const mbedtls_mpi *)b) ? -1 : 0; ++} ++ ++int crypto_bignum_div(const struct crypto_bignum *a, ++ const struct crypto_bignum *b, ++ struct crypto_bignum *c) ++{ ++ /*(most current use of this crypto.h interface has a == c (result), ++ * so store result in an intermediate to avoid overwritten input)*/ ++ mbedtls_mpi R; ++ mbedtls_mpi_init(&R); ++ int rc = mbedtls_mpi_div_mpi(&R, NULL, ++ (const mbedtls_mpi *)a, ++ (const mbedtls_mpi *)b) ++ || mbedtls_mpi_copy((mbedtls_mpi *)c, &R) ? -1 : 0; ++ mbedtls_mpi_free(&R); ++ return rc; ++} ++ ++int crypto_bignum_addmod(const struct crypto_bignum *a, ++ const struct crypto_bignum *b, ++ const struct crypto_bignum *c, ++ struct crypto_bignum *d) ++{ ++ return mbedtls_mpi_add_mpi((mbedtls_mpi *)d, ++ (const mbedtls_mpi *)a, ++ (const mbedtls_mpi *)b) ++ || mbedtls_mpi_mod_mpi((mbedtls_mpi *)d, ++ (mbedtls_mpi *)d, ++ (const mbedtls_mpi *)c) ? -1 : 0; ++} ++ ++int crypto_bignum_mulmod(const struct crypto_bignum *a, ++ const struct crypto_bignum *b, ++ const struct crypto_bignum *c, ++ struct crypto_bignum *d) ++{ ++ return mbedtls_mpi_mul_mpi((mbedtls_mpi *)d, ++ (const mbedtls_mpi *)a, ++ (const mbedtls_mpi *)b) ++ || mbedtls_mpi_mod_mpi((mbedtls_mpi *)d, ++ (mbedtls_mpi *)d, ++ (const mbedtls_mpi *)c) ? -1 : 0; ++} ++ ++int crypto_bignum_sqrmod(const struct crypto_bignum *a, ++ const struct crypto_bignum *b, ++ struct crypto_bignum *c) ++{ ++ #if 1 ++ return crypto_bignum_mulmod(a, a, b, c); ++ #else ++ mbedtls_mpi bn; ++ mbedtls_mpi_init(&bn); ++ if (mbedtls_mpi_lset(&bn, 2)) /* alt?: mbedtls_mpi_set_bit(&bn, 1) */ ++ return -1; ++ int ret = mbedtls_mpi_exp_mod((mbedtls_mpi *)c, ++ (const mbedtls_mpi *)a, &bn, ++ (const mbedtls_mpi *)b, NULL) ? -1 : 0; ++ mbedtls_mpi_free(&bn); ++ return ret; ++ #endif ++} ++ ++int crypto_bignum_rshift(const struct crypto_bignum *a, int n, ++ struct crypto_bignum *r) ++{ ++ return mbedtls_mpi_copy((mbedtls_mpi *)r, (const mbedtls_mpi *)a) ++ || mbedtls_mpi_shift_r((mbedtls_mpi *)r, n) ? -1 : 0; ++} ++ ++int crypto_bignum_cmp(const struct crypto_bignum *a, ++ const struct crypto_bignum *b) ++{ ++ return mbedtls_mpi_cmp_mpi((const mbedtls_mpi *)a, (const mbedtls_mpi *)b); ++} ++ ++int crypto_bignum_is_zero(const struct crypto_bignum *a) ++{ ++ /* XXX: src/common/sae.c:sswu() contains comment: ++ * "TODO: Make sure crypto_bignum_is_zero() is constant time" ++ * Note: mbedtls_mpi_cmp_int() *is not* constant time */ ++ return (mbedtls_mpi_cmp_int((const mbedtls_mpi *)a, 0) == 0); ++} ++ ++int crypto_bignum_is_one(const struct crypto_bignum *a) ++{ ++ return (mbedtls_mpi_cmp_int((const mbedtls_mpi *)a, 1) == 0); ++} ++ ++int crypto_bignum_is_odd(const struct crypto_bignum *a) ++{ ++ return mbedtls_mpi_get_bit((const mbedtls_mpi *)a, 0); ++} ++ ++#include "utils/const_time.h" ++int crypto_bignum_legendre(const struct crypto_bignum *a, ++ const struct crypto_bignum *p) ++{ ++ /* Security Note: ++ * mbedtls_mpi_exp_mod() is not documented to run in constant time, ++ * though mbedtls/library/bignum.c uses constant_time_internal.h funcs. ++ * Compare to crypto_openssl.c:crypto_bignum_legendre() ++ * which uses openssl BN_mod_exp_mont_consttime() ++ * mbedtls/library/ecp.c has further countermeasures to timing attacks, ++ * (but ecp.c funcs are not used here) */ ++ ++ mbedtls_mpi exp, tmp; ++ mbedtls_mpi_init(&exp); ++ mbedtls_mpi_init(&tmp); ++ ++ /* exp = (p-1) / 2 */ ++ int res; ++ if (mbedtls_mpi_sub_int(&exp, (const mbedtls_mpi *)p, 1) == 0 ++ && mbedtls_mpi_shift_r(&exp, 1) == 0 ++ && mbedtls_mpi_exp_mod(&tmp, (const mbedtls_mpi *)a, &exp, ++ (const mbedtls_mpi *)p, NULL) == 0) { ++ /*(modified from crypto_openssl.c:crypto_bignum_legendre())*/ ++ /* Return 1 if tmp == 1, 0 if tmp == 0, or -1 otherwise. Need ++ * to use constant time selection to avoid branches here. */ ++ unsigned int mask; ++ res = -1; ++ mask = const_time_eq((mbedtls_mpi_cmp_int(&tmp, 1) == 0), 1); ++ res = const_time_select_int(mask, 1, res); ++ mask = const_time_eq((mbedtls_mpi_cmp_int(&tmp, 0) == 0), 1); ++ res = const_time_select_int(mask, 0, res); ++ } else { ++ res = -2; ++ } ++ ++ mbedtls_mpi_free(&tmp); ++ mbedtls_mpi_free(&exp); ++ return res; ++} ++ ++#endif /* CRYPTO_MBEDTLS_CRYPTO_BIGNUM */ ++ ++ ++#ifdef CRYPTO_MBEDTLS_CRYPTO_DH ++ ++/* crypto_internal-modexp.c */ ++ ++#include ++#include ++ ++#if 0 /* crypto_dh_init() and crypto_dh_derive_secret() prefer to use mbedtls */ ++int crypto_mod_exp(const u8 *base, size_t base_len, ++ const u8 *power, size_t power_len, ++ const u8 *modulus, size_t modulus_len, ++ u8 *result, size_t *result_len) ++{ ++ mbedtls_mpi bn_base, bn_exp, bn_modulus, bn_result; ++ mbedtls_mpi_init(&bn_base); ++ mbedtls_mpi_init(&bn_exp); ++ mbedtls_mpi_init(&bn_modulus); ++ mbedtls_mpi_init(&bn_result); ++ ++ size_t len; ++ int ret = mbedtls_mpi_read_binary(&bn_base, base, base_len) ++ || mbedtls_mpi_read_binary(&bn_exp, power, power_len) ++ || mbedtls_mpi_read_binary(&bn_modulus, modulus, modulus_len) ++ || mbedtls_mpi_exp_mod(&bn_result,&bn_base,&bn_exp,&bn_modulus,NULL) ++ || (len = mbedtls_mpi_size(&bn_result)) > *result_len ++ || mbedtls_mpi_write_binary(&bn_result, result, (*result_len = len)) ++ ? -1 ++ : 0; ++ ++ mbedtls_mpi_free(&bn_base); ++ mbedtls_mpi_free(&bn_exp); ++ mbedtls_mpi_free(&bn_modulus); ++ mbedtls_mpi_free(&bn_result); ++ return ret; ++} ++#endif ++ ++static int crypto_mbedtls_dh_set_bin_pg(mbedtls_dhm_context *ctx, u8 generator, ++ const u8 *prime, size_t prime_len) ++{ ++ /*(could set these directly in MBEDTLS_PRIVATE members)*/ ++ mbedtls_mpi P, G; ++ mbedtls_mpi_init(&P); ++ mbedtls_mpi_init(&G); ++ int ret = mbedtls_mpi_lset(&G, generator) ++ || mbedtls_mpi_read_binary(&P, prime, prime_len) ++ || mbedtls_dhm_set_group(ctx, &P, &G); ++ mbedtls_mpi_free(&P); ++ mbedtls_mpi_free(&G); ++ return ret; ++} ++ ++__attribute_noinline__ ++static int crypto_mbedtls_dh_init_public(mbedtls_dhm_context *ctx, u8 generator, ++ const u8 *prime, size_t prime_len, ++ u8 *privkey, u8 *pubkey) ++{ ++ if (crypto_mbedtls_dh_set_bin_pg(ctx, generator, prime, prime_len) ++ || mbedtls_dhm_make_public(ctx, (int)prime_len, pubkey, prime_len, ++ mbedtls_ctr_drbg_random, ++ crypto_mbedtls_ctr_drbg())) ++ return -1; ++ ++ /*(enable later when upstream mbedtls interface changes require)*/ ++ #if 0 && MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */ ++ mbedtls_mpi X; ++ mbedtls_mpi_init(&X); ++ int ret = mbedtls_dhm_get_value(ctx, MBEDTLS_DHM_PARAM_X, &X) ++ || mbedtls_mpi_write_binary(&X, privkey, prime_len) ? -1 : 0; ++ mbedtls_mpi_free(&X); ++ return ret; ++ #else ++ return mbedtls_mpi_write_binary(&ctx->MBEDTLS_PRIVATE(X), ++ privkey, prime_len) ? -1 : 0; ++ #endif ++} ++ ++int crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey, ++ u8 *pubkey) ++{ ++ #if 0 /*(crypto_dh_init() duplicated (and identical) in crypto_*.c modules)*/ ++ size_t pubkey_len, pad; ++ ++ if (os_get_random(privkey, prime_len) < 0) ++ return -1; ++ if (os_memcmp(privkey, prime, prime_len) > 0) { ++ /* Make sure private value is smaller than prime */ ++ privkey[0] = 0; ++ } ++ ++ pubkey_len = prime_len; ++ if (crypto_mod_exp(&generator, 1, privkey, prime_len, prime, prime_len, ++ pubkey, &pubkey_len) < 0) ++ return -1; ++ if (pubkey_len < prime_len) { ++ pad = prime_len - pubkey_len; ++ os_memmove(pubkey + pad, pubkey, pubkey_len); ++ os_memset(pubkey, 0, pad); ++ } ++ ++ return 0; ++ #else ++ /* Prefer to use mbedtls to derive our public/private key, as doing so ++ * leverages mbedtls to properly format output and to perform blinding*/ ++ mbedtls_dhm_context ctx; ++ mbedtls_dhm_init(&ctx); ++ int ret = crypto_mbedtls_dh_init_public(&ctx, generator, prime, ++ prime_len, privkey, pubkey); ++ mbedtls_dhm_free(&ctx); ++ return ret; ++ #endif ++} ++ ++/*(crypto_dh_derive_secret() could be implemented using crypto.h APIs ++ * instead of being reimplemented in each crypto_*.c)*/ ++int crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len, ++ const u8 *order, size_t order_len, ++ const u8 *privkey, size_t privkey_len, ++ const u8 *pubkey, size_t pubkey_len, ++ u8 *secret, size_t *len) ++{ ++ #if 0 ++ if (pubkey_len > prime_len || ++ (pubkey_len == prime_len && ++ os_memcmp(pubkey, prime, prime_len) >= 0)) ++ return -1; ++ ++ int res = 0; ++ mbedtls_mpi pub; ++ mbedtls_mpi_init(&pub); ++ if (mbedtls_mpi_read_binary(&pub, pubkey, pubkey_len) ++ || mbedtls_mpi_cmp_int(&pub, 1) <= 0) { ++ res = -1; ++ } else if (order) { ++ mbedtls_mpi p, q, tmp; ++ mbedtls_mpi_init(&p); ++ mbedtls_mpi_init(&q); ++ mbedtls_mpi_init(&tmp); ++ ++ /* verify: pubkey^q == 1 mod p */ ++ res = (mbedtls_mpi_read_binary(&p, prime, prime_len) ++ || mbedtls_mpi_read_binary(&q, order, order_len) ++ || mbedtls_mpi_exp_mod(&tmp, &pub, &q, &p, NULL) ++ || mbedtls_mpi_cmp_int(&tmp, 1) != 0); ++ ++ mbedtls_mpi_free(&p); ++ mbedtls_mpi_free(&q); ++ mbedtls_mpi_free(&tmp); ++ } ++ mbedtls_mpi_free(&pub); ++ ++ return (res == 0) ++ ? crypto_mod_exp(pubkey, pubkey_len, privkey, privkey_len, ++ prime, prime_len, secret, len) ++ : -1; ++ #else ++ /* Prefer to use mbedtls to derive DH shared secret, as doing so ++ * leverages mbedtls to validate params and to perform blinding. ++ * ++ * Attempt to reconstitute DH context to derive shared secret ++ * (due to limitations of the interface, which ought to pass context). ++ * Force provided G (our private key) into context without validation. ++ * Regenerating GX (our public key) not needed to derive shared secret. ++ */ ++ /*(older compilers might not support VLAs)*/ ++ /*unsigned char buf[2+prime_len+2+1+2+pubkey_len];*/ ++ unsigned char buf[2+MBEDTLS_MPI_MAX_SIZE+2+1+2+MBEDTLS_MPI_MAX_SIZE]; ++ unsigned char *p = buf + 2 + prime_len; ++ if (2+prime_len+2+1+2+pubkey_len > sizeof(buf)) ++ return -1; ++ WPA_PUT_BE16(buf, prime_len); /*(2-byte big-endian size of prime)*/ ++ p[0] = 0; /*(2-byte big-endian size of generator)*/ ++ p[1] = 1; ++ p[2] = generator; ++ WPA_PUT_BE16(p+3, pubkey_len); /*(2-byte big-endian size of pubkey)*/ ++ os_memcpy(p+5, pubkey, pubkey_len); ++ os_memcpy(buf+2, prime, prime_len); ++ ++ mbedtls_dhm_context ctx; ++ mbedtls_dhm_init(&ctx); ++ p = buf; ++ int ret = mbedtls_dhm_read_params(&ctx, &p, p+2+prime_len+5+pubkey_len) ++ || mbedtls_mpi_read_binary(&ctx.MBEDTLS_PRIVATE(X), ++ privkey, privkey_len) ++ || mbedtls_dhm_calc_secret(&ctx, secret, *len, len, ++ mbedtls_ctr_drbg_random, ++ crypto_mbedtls_ctr_drbg()) ? -1 : 0; ++ mbedtls_dhm_free(&ctx); ++ return ret; ++ #endif ++} ++ ++/* dh_group5.c */ ++ ++#include "dh_group5.h" ++ ++/* RFC3526_PRIME_1536[] and RFC3526_GENERATOR_1536[] from crypto_wolfssl.c */ ++ ++static const unsigned char RFC3526_PRIME_1536[] = { ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, ++ 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, ++ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, ++ 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, ++ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, ++ 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, ++ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, ++ 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, ++ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, ++ 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, ++ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, ++ 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, ++ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, ++ 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, ++ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, ++ 0xCA, 0x23, 0x73, 0x27, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ++}; ++ ++static const unsigned char RFC3526_GENERATOR_1536[] = { ++ 0x02 ++}; ++ ++void * dh5_init(struct wpabuf **priv, struct wpabuf **publ) ++{ ++ const unsigned char * const prime = RFC3526_PRIME_1536; ++ const size_t prime_len = sizeof(RFC3526_PRIME_1536); ++ const u8 generator = *RFC3526_GENERATOR_1536; ++ struct wpabuf *wpubl = NULL, *wpriv = NULL; ++ ++ mbedtls_dhm_context *ctx = os_malloc(sizeof(*ctx)); ++ if (ctx == NULL) ++ return NULL; ++ mbedtls_dhm_init(ctx); ++ ++ if ( (wpubl = wpabuf_alloc(prime_len)) ++ && (wpriv = wpabuf_alloc(prime_len)) ++ && crypto_mbedtls_dh_init_public(ctx, generator, prime, prime_len, ++ wpabuf_put(wpriv, prime_len), ++ wpabuf_put(wpubl, prime_len))==0) { ++ wpabuf_free(*publ); ++ wpabuf_clear_free(*priv); ++ *publ = wpubl; ++ *priv = wpriv; ++ return ctx; ++ } ++ ++ wpabuf_clear_free(wpriv); ++ wpabuf_free(wpubl); ++ mbedtls_dhm_free(ctx); ++ os_free(ctx); ++ return NULL; ++} ++ ++#ifdef CRYPTO_MBEDTLS_DH5_INIT_FIXED ++void * dh5_init_fixed(const struct wpabuf *priv, const struct wpabuf *publ) ++{ ++ const unsigned char * const prime = RFC3526_PRIME_1536; ++ const size_t prime_len = sizeof(RFC3526_PRIME_1536); ++ const u8 generator = *RFC3526_GENERATOR_1536; ++ ++ mbedtls_dhm_context *ctx = os_malloc(sizeof(*ctx)); ++ if (ctx == NULL) ++ return NULL; ++ mbedtls_dhm_init(ctx); ++ ++ if (crypto_mbedtls_dh_set_bin_pg(ctx, generator, prime, prime_len)==0 ++ #if 0 /*(ignore; not required to derive shared secret)*/ ++ && mbedtls_mpi_read_binary(&ctx->MBEDTLS_PRIVATE(GX), ++ wpabuf_head(publ),wpabuf_len(publ))==0 ++ #endif ++ && mbedtls_mpi_read_binary(&ctx->MBEDTLS_PRIVATE(X), ++ wpabuf_head(priv),wpabuf_len(priv))==0) { ++ return ctx; ++ } ++ ++ mbedtls_dhm_free(ctx); ++ os_free(ctx); ++ return NULL; ++} ++#endif ++ ++struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public, ++ const struct wpabuf *own_private) ++{ ++ /*((mbedtls_dhm_context *)ctx must already contain own_private)*/ ++ /* mbedtls 2.x: prime_len = ctx->len; */ ++ /* mbedtls 3.x: prime_len = mbedtls_dhm_get_len(ctx); */ ++ size_t olen = sizeof(RFC3526_PRIME_1536); /*(sizeof(); prime known)*/ ++ struct wpabuf *buf = wpabuf_alloc(olen); ++ if (buf == NULL) ++ return NULL; ++ if (mbedtls_dhm_read_public((mbedtls_dhm_context *)ctx, ++ wpabuf_head(peer_public), ++ wpabuf_len(peer_public)) == 0 ++ && mbedtls_dhm_calc_secret(ctx, wpabuf_mhead(buf), olen, &olen, ++ mbedtls_ctr_drbg_random, ++ crypto_mbedtls_ctr_drbg()) == 0) { ++ wpabuf_put(buf, olen); ++ return buf; ++ } ++ ++ wpabuf_free(buf); ++ return NULL; ++} ++ ++void dh5_free(void *ctx) ++{ ++ mbedtls_dhm_free(ctx); ++ os_free(ctx); ++} ++ ++#endif /* CRYPTO_MBEDTLS_CRYPTO_DH */ ++ ++ ++#if defined(CRYPTO_MBEDTLS_CRYPTO_ECDH) || defined(CRYPTO_MBEDTLS_CRYPTO_EC) ++ ++#include ++ ++#define CRYPTO_EC_pbits(e) (((mbedtls_ecp_group *)(e))->pbits) ++#define CRYPTO_EC_plen(e) ((((mbedtls_ecp_group *)(e))->pbits+7)>>3) ++#define CRYPTO_EC_P(e) (&((mbedtls_ecp_group *)(e))->P) ++#define CRYPTO_EC_N(e) (&((mbedtls_ecp_group *)(e))->N) ++#define CRYPTO_EC_A(e) (&((mbedtls_ecp_group *)(e))->A) ++#define CRYPTO_EC_B(e) (&((mbedtls_ecp_group *)(e))->B) ++#define CRYPTO_EC_G(e) (&((mbedtls_ecp_group *)(e))->G) ++ ++static mbedtls_ecp_group_id crypto_mbedtls_ecp_group_id_from_ike_id(int group) ++{ ++ /* https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml */ ++ switch (group) { ++ #ifdef MBEDTLS_ECP_DP_SECP256R1_ENABLED ++ case 19: return MBEDTLS_ECP_DP_SECP256R1; ++ #endif ++ #ifdef MBEDTLS_ECP_DP_SECP384R1_ENABLED ++ case 20: return MBEDTLS_ECP_DP_SECP384R1; ++ #endif ++ #ifdef MBEDTLS_ECP_DP_SECP521R1_ENABLED ++ case 21: return MBEDTLS_ECP_DP_SECP521R1; ++ #endif ++ #ifdef MBEDTLS_ECP_DP_SECP192R1_ENABLED ++ case 25: return MBEDTLS_ECP_DP_SECP192R1; ++ #endif ++ #ifdef MBEDTLS_ECP_DP_SECP224R1_ENABLED ++ case 26: return MBEDTLS_ECP_DP_SECP224R1; ++ #endif ++ #ifdef MBEDTLS_ECP_DP_BP256R1_ENABLED ++ case 28: return MBEDTLS_ECP_DP_BP256R1; ++ #endif ++ #ifdef MBEDTLS_ECP_DP_BP384R1_ENABLED ++ case 29: return MBEDTLS_ECP_DP_BP384R1; ++ #endif ++ #ifdef MBEDTLS_ECP_DP_BP512R1_ENABLED ++ case 30: return MBEDTLS_ECP_DP_BP512R1; ++ #endif ++ #ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED ++ case 31: return MBEDTLS_ECP_DP_CURVE25519; ++ #endif ++ #ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED ++ case 32: return MBEDTLS_ECP_DP_CURVE448; ++ #endif ++ default: return MBEDTLS_ECP_DP_NONE; ++ } ++} ++ ++#ifdef CRYPTO_MBEDTLS_CRYPTO_EC ++static int crypto_mbedtls_ike_id_from_ecp_group_id(mbedtls_ecp_group_id grp_id) ++{ ++ /* https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml */ ++ /*(for crypto_ec_key_group())*/ ++ switch (grp_id) { ++ #ifdef MBEDTLS_ECP_DP_SECP256R1_ENABLED ++ case MBEDTLS_ECP_DP_SECP256R1: return 19; ++ #endif ++ #ifdef MBEDTLS_ECP_DP_SECP384R1_ENABLED ++ case MBEDTLS_ECP_DP_SECP384R1: return 20; ++ #endif ++ #ifdef MBEDTLS_ECP_DP_SECP521R1_ENABLED ++ case MBEDTLS_ECP_DP_SECP521R1: return 21; ++ #endif ++ #ifdef MBEDTLS_ECP_DP_SECP192R1_ENABLED ++ case MBEDTLS_ECP_DP_SECP192R1: return 25; ++ #endif ++ #ifdef MBEDTLS_ECP_DP_SECP224R1_ENABLED ++ case MBEDTLS_ECP_DP_SECP224R1: return 26; ++ #endif ++ #ifdef MBEDTLS_ECP_DP_BP256R1_ENABLED ++ case MBEDTLS_ECP_DP_BP256R1: return 28; ++ #endif ++ #ifdef MBEDTLS_ECP_DP_BP384R1_ENABLED ++ case MBEDTLS_ECP_DP_BP384R1: return 29; ++ #endif ++ #ifdef MBEDTLS_ECP_DP_BP512R1_ENABLED ++ case MBEDTLS_ECP_DP_BP512R1: return 30; ++ #endif ++ #ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED ++ case MBEDTLS_ECP_DP_CURVE25519: return 31; ++ #endif ++ #ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED ++ case MBEDTLS_ECP_DP_CURVE448: return 32; ++ #endif ++ default: return -1; ++ } ++} ++#endif ++ ++#endif /* CRYPTO_MBEDTLS_CRYPTO_ECDH || CRYPTO_MBEDTLS_CRYPTO_EC */ ++ ++ ++#if defined(CRYPTO_MBEDTLS_CRYPTO_ECDH) || defined(CRYPTO_MBEDTLS_CRYPTO_EC_DPP) ++ ++#include ++#include ++ ++static int crypto_mbedtls_keypair_gen(int group, mbedtls_pk_context *pk) ++{ ++ mbedtls_ecp_group_id grp_id = ++ crypto_mbedtls_ecp_group_id_from_ike_id(group); ++ if (grp_id == MBEDTLS_ECP_DP_NONE) ++ return -1; ++ const mbedtls_pk_info_t *pk_info = ++ mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY); ++ if (pk_info == NULL) ++ return -1; ++ return mbedtls_pk_setup(pk, pk_info) ++ || mbedtls_ecp_gen_key(grp_id, mbedtls_pk_ec(*pk), ++ mbedtls_ctr_drbg_random, ++ crypto_mbedtls_ctr_drbg()) ? -1 : 0; ++} ++ ++#endif ++ ++ ++#ifdef CRYPTO_MBEDTLS_CRYPTO_ECDH ++ ++#include ++#include ++#include ++#include ++ ++/* wrap mbedtls_ecdh_context for more future-proof direct access to components ++ * (mbedtls_ecdh_context internal implementation may change between releases) ++ * ++ * If mbedtls_pk_context -- specifically underlying mbedtls_ecp_keypair -- ++ * lifetime were guaranteed to be longer than that of mbedtls_ecdh_context, ++ * then mbedtls_pk_context or mbedtls_ecp_keypair could be stored in crypto_ecdh ++ * (or crypto_ec_key could be stored in crypto_ecdh, and crypto_ec_key could ++ * wrap mbedtls_ecp_keypair and components, to avoid MBEDTLS_PRIVATE access) */ ++struct crypto_ecdh { ++ mbedtls_ecdh_context ctx; ++ mbedtls_ecp_group grp; ++ mbedtls_ecp_point Q; ++}; ++ ++struct crypto_ecdh * crypto_ecdh_init(int group) ++{ ++ mbedtls_pk_context pk; ++ mbedtls_pk_init(&pk); ++ struct crypto_ecdh *ecdh = crypto_mbedtls_keypair_gen(group, &pk) == 0 ++ ? crypto_ecdh_init2(group, (struct crypto_ec_key *)&pk) ++ : NULL; ++ mbedtls_pk_free(&pk); ++ return ecdh; ++} ++ ++struct crypto_ecdh * crypto_ecdh_init2(int group, ++ struct crypto_ec_key *own_key) ++{ ++ mbedtls_ecp_group_id grp_id = ++ crypto_mbedtls_ecp_group_id_from_ike_id(group); ++ if (grp_id == MBEDTLS_ECP_DP_NONE) ++ return NULL; ++ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)own_key); ++ struct crypto_ecdh *ecdh = os_malloc(sizeof(*ecdh)); ++ if (ecdh == NULL) ++ return NULL; ++ mbedtls_ecdh_init(&ecdh->ctx); ++ mbedtls_ecp_group_init(&ecdh->grp); ++ mbedtls_ecp_point_init(&ecdh->Q); ++ if (mbedtls_ecdh_setup(&ecdh->ctx, grp_id) == 0 ++ && mbedtls_ecdh_get_params(&ecdh->ctx,ecp_kp,MBEDTLS_ECDH_OURS) == 0) { ++ /* copy grp and Q for later use ++ * (retrieving this info later is more convoluted ++ * even if mbedtls_ecdh_make_public() is considered)*/ ++ #if MBEDTLS_VERSION_NUMBER >= 0x03020000 /* mbedtls 3.2.0 */ ++ mbedtls_mpi d; ++ mbedtls_mpi_init(&d); ++ if (mbedtls_ecp_export(ecp_kp, &ecdh->grp, &d, &ecdh->Q) == 0) { ++ mbedtls_mpi_free(&d); ++ return ecdh; ++ } ++ mbedtls_mpi_free(&d); ++ #else ++ if (mbedtls_ecp_group_load(&ecdh->grp, grp_id) == 0 ++ && mbedtls_ecp_copy(&ecdh->Q, &ecp_kp->MBEDTLS_PRIVATE(Q)) == 0) ++ return ecdh; ++ #endif ++ } ++ ++ mbedtls_ecp_point_free(&ecdh->Q); ++ mbedtls_ecp_group_free(&ecdh->grp); ++ mbedtls_ecdh_free(&ecdh->ctx); ++ os_free(ecdh); ++ return NULL; ++} ++ ++struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh, int inc_y) ++{ ++ mbedtls_ecp_group *grp = &ecdh->grp; ++ size_t len = CRYPTO_EC_plen(grp); ++ #ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED ++ /* len */ ++ #endif ++ #ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED ++ if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) ++ len = inc_y ? len*2+1 : len+1; ++ #endif ++ struct wpabuf *buf = wpabuf_alloc(len); ++ if (buf == NULL) ++ return NULL; ++ inc_y = inc_y ? MBEDTLS_ECP_PF_UNCOMPRESSED : MBEDTLS_ECP_PF_COMPRESSED; ++ if (mbedtls_ecp_point_write_binary(grp, &ecdh->Q, inc_y, &len, ++ wpabuf_mhead_u8(buf), len) == 0) { ++ wpabuf_put(buf, len); ++ return buf; ++ } ++ ++ wpabuf_free(buf); ++ return NULL; ++} ++ ++#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) ++static int crypto_mbedtls_short_weierstrass_derive_y(mbedtls_ecp_group *grp, ++ mbedtls_mpi *bn, ++ int parity_bit) ++{ ++ /* y^2 = x^3 + ax + b ++ * sqrt(w) = w^((p+1)/4) mod p (for prime p where p = 3 mod 4) */ ++ mbedtls_mpi *cy2 = (mbedtls_mpi *) ++ crypto_ec_point_compute_y_sqr((struct crypto_ec *)grp, ++ (const struct crypto_bignum *)bn); /*x*/ ++ if (cy2 == NULL) ++ return -1; ++ ++ /*mbedtls_mpi_free(bn);*/ ++ /*(reuse bn to store result (y))*/ ++ ++ mbedtls_mpi exp; ++ mbedtls_mpi_init(&exp); ++ int ret = mbedtls_mpi_get_bit(&grp->P, 0) != 1 /*(p = 3 mod 4)*/ ++ || mbedtls_mpi_get_bit(&grp->P, 1) != 1 /*(p = 3 mod 4)*/ ++ || mbedtls_mpi_add_int(&exp, &grp->P, 1) ++ || mbedtls_mpi_shift_r(&exp, 2) ++ || mbedtls_mpi_exp_mod(bn, cy2, &exp, &grp->P, NULL) ++ || (mbedtls_mpi_get_bit(bn, 0) != parity_bit ++ && mbedtls_mpi_sub_mpi(bn, &grp->P, bn)); ++ mbedtls_mpi_free(&exp); ++ mbedtls_mpi_free(cy2); ++ os_free(cy2); ++ return ret; ++} ++#endif ++ ++struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y, ++ const u8 *key, size_t len) ++{ ++ if (len == 0) /*(invalid peer key)*/ ++ return NULL; ++ ++ mbedtls_ecp_group *grp = &ecdh->grp; ++ ++ #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) ++ if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { ++ /* add header for mbedtls_ecdh_read_public() */ ++ u8 buf[256]; ++ if (sizeof(buf)-1 < len) ++ return NULL; ++ buf[0] = (u8)(len); ++ os_memcpy(buf+1, key, len); ++ ++ if (inc_y) { ++ if (!(len & 1)) { /*(dpp code/tests does not include tag?!?)*/ ++ if (sizeof(buf)-2 < len) ++ return NULL; ++ buf[0] = (u8)(1+len); ++ buf[1] = 0x04; ++ os_memcpy(buf+2, key, len); ++ } ++ len >>= 1; /*(repurpose len to prime_len)*/ ++ } ++ else if (key[0] == 0x02 || key[0] == 0x03) { /* (inc_y == 0) */ ++ --len; /*(repurpose len to prime_len)*/ ++ ++ /* mbedtls_ecp_point_read_binary() does not currently support ++ * MBEDTLS_ECP_PF_COMPRESSED format (buf[1] = 0x02 or 0x03) ++ * (returns MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) */ ++ ++ /* derive y, amend buf[] with y for UNCOMPRESSED format */ ++ if (sizeof(buf)-2 < len*2 || len == 0) ++ return NULL; ++ buf[0] = (u8)(1+len*2); ++ buf[1] = 0x04; ++ mbedtls_mpi bn; ++ mbedtls_mpi_init(&bn); ++ int ret = mbedtls_mpi_read_binary(&bn, key+1, len) ++ || crypto_mbedtls_short_weierstrass_derive_y(grp, &bn, ++ key[0] & 1) ++ || mbedtls_mpi_write_binary(&bn, buf+2+len, len); ++ mbedtls_mpi_free(&bn); ++ if (ret != 0) ++ return NULL; ++ } ++ ++ if (key[0] == 0) /*(repurpose len to prime_len)*/ ++ len = CRYPTO_EC_plen(grp); ++ ++ if (mbedtls_ecdh_read_public(&ecdh->ctx, buf, buf[0]+1)) ++ return NULL; ++ } ++ #endif ++ #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) ++ if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { ++ if (mbedtls_ecdh_read_public(&ecdh->ctx, key, len)) ++ return NULL; ++ } ++ #endif ++ ++ struct wpabuf *buf = wpabuf_alloc(len); ++ if (buf == NULL) ++ return NULL; ++ ++ if (mbedtls_ecdh_calc_secret(&ecdh->ctx, &len, ++ wpabuf_mhead(buf), len, ++ mbedtls_ctr_drbg_random, ++ crypto_mbedtls_ctr_drbg()) == 0) { ++ wpabuf_put(buf, len); ++ return buf; ++ } ++ ++ wpabuf_clear_free(buf); ++ return NULL; ++} ++ ++void crypto_ecdh_deinit(struct crypto_ecdh *ecdh) ++{ ++ if (ecdh == NULL) ++ return; ++ mbedtls_ecp_point_free(&ecdh->Q); ++ mbedtls_ecp_group_free(&ecdh->grp); ++ mbedtls_ecdh_free(&ecdh->ctx); ++ os_free(ecdh); ++} ++ ++size_t crypto_ecdh_prime_len(struct crypto_ecdh *ecdh) ++{ ++ return CRYPTO_EC_plen(&ecdh->grp); ++} ++ ++#endif /* CRYPTO_MBEDTLS_CRYPTO_ECDH */ ++ ++ ++#ifdef CRYPTO_MBEDTLS_CRYPTO_EC ++ ++#include ++ ++struct crypto_ec *crypto_ec_init(int group) ++{ ++ mbedtls_ecp_group_id grp_id = ++ crypto_mbedtls_ecp_group_id_from_ike_id(group); ++ if (grp_id == MBEDTLS_ECP_DP_NONE) ++ return NULL; ++ mbedtls_ecp_group *e = os_malloc(sizeof(*e)); ++ if (e == NULL) ++ return NULL; ++ mbedtls_ecp_group_init(e); ++ if (mbedtls_ecp_group_load(e, grp_id) == 0) ++ return (struct crypto_ec *)e; ++ ++ mbedtls_ecp_group_free(e); ++ os_free(e); ++ return NULL; ++} ++ ++void crypto_ec_deinit(struct crypto_ec *e) ++{ ++ mbedtls_ecp_group_free((mbedtls_ecp_group *)e); ++ os_free(e); ++} ++ ++size_t crypto_ec_prime_len(struct crypto_ec *e) ++{ ++ return CRYPTO_EC_plen(e); ++} ++ ++size_t crypto_ec_prime_len_bits(struct crypto_ec *e) ++{ ++ return CRYPTO_EC_pbits(e); ++} ++ ++size_t crypto_ec_order_len(struct crypto_ec *e) ++{ ++ return (mbedtls_mpi_bitlen(CRYPTO_EC_N(e)) + 7) / 8; ++} ++ ++const struct crypto_bignum *crypto_ec_get_prime(struct crypto_ec *e) ++{ ++ return (const struct crypto_bignum *)CRYPTO_EC_P(e); ++} ++ ++const struct crypto_bignum *crypto_ec_get_order(struct crypto_ec *e) ++{ ++ return (const struct crypto_bignum *)CRYPTO_EC_N(e); ++} ++ ++const struct crypto_bignum *crypto_ec_get_a(struct crypto_ec *e) ++{ ++ static const uint8_t secp256r1_a[] = ++ {0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x01, ++ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, ++ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff, ++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc}; ++ static const uint8_t secp384r1_a[] = ++ {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, ++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, ++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, ++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe, ++ 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, ++ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xfc}; ++ static const uint8_t secp521r1_a[] = ++ {0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff, ++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, ++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, ++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, ++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, ++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, ++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, ++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, ++ 0xff,0xfc}; ++ static const uint8_t secp192r1_a[] = ++ {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, ++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe, ++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc}; ++ static const uint8_t secp224r1_a[] = ++ {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, ++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe, ++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, ++ 0xff,0xff,0xff,0xfe}; ++ ++ const uint8_t *bin = NULL; ++ size_t len = 0; ++ ++ /* (mbedtls groups matching supported sswu_curve_param() IKE groups) */ ++ switch (((mbedtls_ecp_group *)e)->id) { ++ #ifdef MBEDTLS_ECP_DP_SECP256R1_ENABLED ++ case MBEDTLS_ECP_DP_SECP256R1: ++ bin = secp256r1_a; ++ len = sizeof(secp256r1_a); ++ break; ++ #endif ++ #ifdef MBEDTLS_ECP_DP_SECP384R1_ENABLED ++ case MBEDTLS_ECP_DP_SECP384R1: ++ bin = secp384r1_a; ++ len = sizeof(secp384r1_a); ++ break; ++ #endif ++ #ifdef MBEDTLS_ECP_DP_SECP521R1_ENABLED ++ case MBEDTLS_ECP_DP_SECP521R1: ++ bin = secp521r1_a; ++ len = sizeof(secp521r1_a); ++ break; ++ #endif ++ #ifdef MBEDTLS_ECP_DP_SECP192R1_ENABLED ++ case MBEDTLS_ECP_DP_SECP192R1: ++ bin = secp192r1_a; ++ len = sizeof(secp192r1_a); ++ break; ++ #endif ++ #ifdef MBEDTLS_ECP_DP_SECP224R1_ENABLED ++ case MBEDTLS_ECP_DP_SECP224R1: ++ bin = secp224r1_a; ++ len = sizeof(secp224r1_a); ++ break; ++ #endif ++ #ifdef MBEDTLS_ECP_DP_BP256R1_ENABLED ++ case MBEDTLS_ECP_DP_BP256R1: ++ return (const struct crypto_bignum *)CRYPTO_EC_A(e); ++ #endif ++ #ifdef MBEDTLS_ECP_DP_BP384R1_ENABLED ++ case MBEDTLS_ECP_DP_BP384R1: ++ return (const struct crypto_bignum *)CRYPTO_EC_A(e); ++ #endif ++ #ifdef MBEDTLS_ECP_DP_BP512R1_ENABLED ++ case MBEDTLS_ECP_DP_BP512R1: ++ return (const struct crypto_bignum *)CRYPTO_EC_A(e); ++ #endif ++ #ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED ++ case MBEDTLS_ECP_DP_CURVE25519: ++ return (const struct crypto_bignum *)CRYPTO_EC_A(e); ++ #endif ++ #ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED ++ case MBEDTLS_ECP_DP_CURVE448: ++ return (const struct crypto_bignum *)CRYPTO_EC_A(e); ++ #endif ++ default: ++ return NULL; ++ } ++ ++ /*(note: not thread-safe; returns file-scoped static storage)*/ ++ if (mbedtls_mpi_read_binary(&mpi_sw_A, bin, len) == 0) ++ return (const struct crypto_bignum *)&mpi_sw_A; ++ return NULL; ++} ++ ++const struct crypto_bignum *crypto_ec_get_b(struct crypto_ec *e) ++{ ++ return (const struct crypto_bignum *)CRYPTO_EC_B(e); ++} ++ ++const struct crypto_ec_point * crypto_ec_get_generator(struct crypto_ec *e) ++{ ++ return (const struct crypto_ec_point *)CRYPTO_EC_G(e); ++} ++ ++struct crypto_ec_point *crypto_ec_point_init(struct crypto_ec *e) ++{ ++ mbedtls_ecp_point *p = os_malloc(sizeof(*p)); ++ if (p != NULL) ++ mbedtls_ecp_point_init(p); ++ return (struct crypto_ec_point *)p; ++} ++ ++void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear) ++{ ++ mbedtls_ecp_point_free((mbedtls_ecp_point *)p); ++ os_free(p); ++} ++ ++int crypto_ec_point_x(struct crypto_ec *e, const struct crypto_ec_point *p, ++ struct crypto_bignum *x) ++{ ++ mbedtls_mpi *px = &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(X); ++ return mbedtls_mpi_copy((mbedtls_mpi *)x, px) ++ ? -1 ++ : 0; ++} ++ ++int crypto_ec_point_to_bin(struct crypto_ec *e, ++ const struct crypto_ec_point *point, u8 *x, u8 *y) ++{ ++ /* crypto.h documents crypto_ec_point_to_bin() output is big-endian */ ++ size_t len = CRYPTO_EC_plen(e); ++ if (x) { ++ mbedtls_mpi *px = &((mbedtls_ecp_point *)point)->MBEDTLS_PRIVATE(X); ++ if (mbedtls_mpi_write_binary(px, x, len)) ++ return -1; ++ } ++ if (y) { ++ #if 0 /*(should not be necessary; py mpi should be in initial state)*/ ++ #ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED ++ if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e) ++ == MBEDTLS_ECP_TYPE_MONTGOMERY) { ++ os_memset(y, 0, len); ++ return 0; ++ } ++ #endif ++ #endif ++ mbedtls_mpi *py = &((mbedtls_ecp_point *)point)->MBEDTLS_PRIVATE(Y); ++ if (mbedtls_mpi_write_binary(py, y, len)) ++ return -1; ++ } ++ return 0; ++} ++ ++struct crypto_ec_point * crypto_ec_point_from_bin(struct crypto_ec *e, ++ const u8 *val) ++{ ++ size_t len = CRYPTO_EC_plen(e); ++ mbedtls_ecp_point *p = os_malloc(sizeof(*p)); ++ u8 buf[1+MBEDTLS_MPI_MAX_SIZE*2]; ++ if (p == NULL) ++ return NULL; ++ mbedtls_ecp_point_init(p); ++ ++ #ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED ++ if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e) ++ == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { ++ #if 0 /* prefer alternative to MBEDTLS_PRIVATE() access */ ++ mbedtls_mpi *px = &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(X); ++ mbedtls_mpi *py = &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Y); ++ mbedtls_mpi *pz = &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Z); ++ ++ if (mbedtls_mpi_read_binary(px, val, len) == 0 ++ && mbedtls_mpi_read_binary(py, val + len, len) == 0 ++ && mbedtls_mpi_lset(pz, 1) == 0) ++ return (struct crypto_ec_point *)p; ++ #else ++ buf[0] = 0x04; ++ os_memcpy(buf+1, val, len*2); ++ if (mbedtls_ecp_point_read_binary((mbedtls_ecp_group *)e, p, ++ buf, 1+len*2) == 0) ++ return (struct crypto_ec_point *)p; ++ #endif ++ } ++ #endif ++ #ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED ++ if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e) ++ == MBEDTLS_ECP_TYPE_MONTGOMERY) { ++ /* crypto.h interface documents crypto_ec_point_from_bin() ++ * val is length: prime_len * 2 and is big-endian ++ * (Short Weierstrass is assumed by hostap) ++ * Reverse to little-endian format for Montgomery */ ++ for (unsigned int i = 0; i < len; ++i) ++ buf[i] = val[len-1-i]; ++ if (mbedtls_ecp_point_read_binary((mbedtls_ecp_group *)e, p, ++ buf, len) == 0) ++ return (struct crypto_ec_point *)p; ++ } ++ #endif ++ ++ mbedtls_ecp_point_free(p); ++ os_free(p); ++ return NULL; ++} ++ ++int crypto_ec_point_add(struct crypto_ec *e, const struct crypto_ec_point *a, ++ const struct crypto_ec_point *b, ++ struct crypto_ec_point *c) ++{ ++ /* mbedtls does not provide an mbedtls_ecp_point add function */ ++ mbedtls_mpi one; ++ mbedtls_mpi_init(&one); ++ int ret = mbedtls_mpi_lset(&one, 1) ++ || mbedtls_ecp_muladd( ++ (mbedtls_ecp_group *)e, (mbedtls_ecp_point *)c, ++ &one, (const mbedtls_ecp_point *)a, ++ &one, (const mbedtls_ecp_point *)b) ? -1 : 0; ++ mbedtls_mpi_free(&one); ++ return ret; ++} ++ ++int crypto_ec_point_mul(struct crypto_ec *e, const struct crypto_ec_point *p, ++ const struct crypto_bignum *b, ++ struct crypto_ec_point *res) ++{ ++ return mbedtls_ecp_mul( ++ (mbedtls_ecp_group *)e, (mbedtls_ecp_point *)res, ++ (const mbedtls_mpi *)b, (const mbedtls_ecp_point *)p, ++ mbedtls_ctr_drbg_random, crypto_mbedtls_ctr_drbg()) ? -1 : 0; ++} ++ ++int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p) ++{ ++ if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e) ++ == MBEDTLS_ECP_TYPE_MONTGOMERY) { ++ /* e.g. MBEDTLS_ECP_DP_CURVE25519 and MBEDTLS_ECP_DP_CURVE448 */ ++ wpa_printf(MSG_ERROR, ++ "%s not implemented for Montgomery curves",__func__); ++ return -1; ++ } ++ ++ /* mbedtls does not provide an mbedtls_ecp_point invert function */ ++ /* below works for Short Weierstrass; incorrect for Montgomery curves */ ++ mbedtls_mpi *py = &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Y); ++ return mbedtls_ecp_is_zero((mbedtls_ecp_point *)p) /*point at infinity*/ ++ || mbedtls_mpi_cmp_int(py, 0) == 0 /*point is its own inverse*/ ++ || mbedtls_mpi_sub_abs(py, CRYPTO_EC_P(e), py) == 0 ? 0 : -1; ++} ++ ++#ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED ++static int ++crypto_ec_point_y_sqr_weierstrass(mbedtls_ecp_group *e, const mbedtls_mpi *x, ++ mbedtls_mpi *y2) ++{ ++ /* MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS y^2 = x^3 + a x + b */ ++ ++ /* Short Weierstrass elliptic curve group w/o A set treated as A = -3 */ ++ /* Attempt to match mbedtls/library/ecp.c:ecp_check_pubkey_sw() behavior ++ * and elsewhere in mbedtls/library/ecp.c where if A is not set, it is ++ * treated as if A = -3. */ ++ ++ #if 0 ++ /* y^2 = x^3 + ax + b */ ++ mbedtls_mpi *A = &e->A; ++ mbedtls_mpi t, A_neg3; ++ if (&e->A.p == NULL) { ++ mbedtls_mpi_init(&A_neg3); ++ if (mbedtls_mpi_lset(&A_neg3, -3) != 0) { ++ mbedtls_mpi_free(&A_neg3); ++ return -1; ++ } ++ A = &A_neg3; ++ } ++ mbedtls_mpi_init(&t); ++ int ret = /* x^3 */ ++ mbedtls_mpi_lset(&t, 3) ++ || mbedtls_mpi_exp_mod(y2, x, &t, &e->P, NULL) ++ /* ax */ ++ || mbedtls_mpi_mul_mpi(y2, y2, A) ++ || mbedtls_mpi_mod_mpi(&t, &t, &e->P) ++ /* ax + b */ ++ || mbedtls_mpi_add_mpi(&t, &t, &e->B) ++ || mbedtls_mpi_mod_mpi(&t, &t, &e->P) ++ /* x^3 + ax + b */ ++ || mbedtls_mpi_add_mpi(&t, &t, y2) /* ax + b + x^3 */ ++ || mbedtls_mpi_mod_mpi(y2, &t, &e->P); ++ mbedtls_mpi_free(&t); ++ if (A == &A_neg3) ++ mbedtls_mpi_free(&A_neg3); ++ return ret; /* 0: success, non-zero: failure */ ++ #else ++ /* y^2 = x^3 + ax + b = (x^2 + a)x + b */ ++ return /* x^2 */ ++ mbedtls_mpi_mul_mpi(y2, x, x) ++ || mbedtls_mpi_mod_mpi(y2, y2, &e->P) ++ /* x^2 + a */ ++ || (e->A.MBEDTLS_PRIVATE(p) ++ ? mbedtls_mpi_add_mpi(y2, y2, &e->A) ++ : mbedtls_mpi_sub_int(y2, y2, 3)) ++ || mbedtls_mpi_mod_mpi(y2, y2, &e->P) ++ /* (x^2 + a)x */ ++ || mbedtls_mpi_mul_mpi(y2, y2, x) ++ || mbedtls_mpi_mod_mpi(y2, y2, &e->P) ++ /* (x^2 + a)x + b */ ++ || mbedtls_mpi_add_mpi(y2, y2, &e->B) ++ || mbedtls_mpi_mod_mpi(y2, y2, &e->P); ++ #endif ++} ++#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ ++ ++#if 0 /* not used by hostap */ ++#ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED ++static int ++crypto_ec_point_y_sqr_montgomery(mbedtls_ecp_group *e, const mbedtls_mpi *x, ++ mbedtls_mpi *y2) ++{ ++ /* XXX: !!! must be reviewed and audited for correctness !!! */ ++ ++ /* MBEDTLS_ECP_TYPE_MONTGOMERY y^2 = x^3 + a x^2 + x */ ++ ++ /* y^2 = x^3 + a x^2 + x = (x + a)x^2 + x */ ++ mbedtls_mpi x2; ++ mbedtls_mpi_init(&x2); ++ int ret = /* x^2 */ ++ mbedtls_mpi_mul_mpi(&x2, x, x) ++ || mbedtls_mpi_mod_mpi(&x2, &x2, &e->P) ++ /* x + a */ ++ || mbedtls_mpi_add_mpi(y2, x, &e->A) ++ || mbedtls_mpi_mod_mpi(y2, y2, &e->P) ++ /* (x + a)x^2 */ ++ || mbedtls_mpi_mul_mpi(y2, y2, &x2) ++ || mbedtls_mpi_mod_mpi(y2, y2, &e->P) ++ /* (x + a)x^2 + x */ ++ || mbedtls_mpi_add_mpi(y2, y2, x) ++ || mbedtls_mpi_mod_mpi(y2, y2, &e->P); ++ mbedtls_mpi_free(&x2); ++ return ret; /* 0: success, non-zero: failure */ ++} ++#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ ++#endif ++ ++struct crypto_bignum * ++crypto_ec_point_compute_y_sqr(struct crypto_ec *e, ++ const struct crypto_bignum *x) ++{ ++ mbedtls_mpi *y2 = os_malloc(sizeof(*y2)); ++ if (y2 == NULL) ++ return NULL; ++ mbedtls_mpi_init(y2); ++ ++ #ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED ++ if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e) ++ == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ++ && crypto_ec_point_y_sqr_weierstrass((mbedtls_ecp_group *)e, ++ (const mbedtls_mpi *)x, ++ y2) == 0) ++ return (struct crypto_bignum *)y2; ++ #endif ++ #if 0 /* not used by hostap */ ++ #ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED ++ if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e) ++ == MBEDTLS_ECP_TYPE_MONTGOMERY ++ && crypto_ec_point_y_sqr_montgomery((mbedtls_ecp_group *)e, ++ (const mbedtls_mpi *)x, ++ y2) == 0) ++ return (struct crypto_bignum *)y2; ++ #endif ++ #endif ++ ++ mbedtls_mpi_free(y2); ++ os_free(y2); ++ return NULL; ++} ++ ++int crypto_ec_point_is_at_infinity(struct crypto_ec *e, ++ const struct crypto_ec_point *p) ++{ ++ return mbedtls_ecp_is_zero((mbedtls_ecp_point *)p); ++} ++ ++int crypto_ec_point_is_on_curve(struct crypto_ec *e, ++ const struct crypto_ec_point *p) ++{ ++ #if 1 ++ return mbedtls_ecp_check_pubkey((const mbedtls_ecp_group *)e, ++ (const mbedtls_ecp_point *)p) == 0; ++ #else ++ /* compute y^2 mod P and compare to y^2 mod P */ ++ /*(ref: src/eap_common/eap_pwd_common.c:compute_password_element())*/ ++ const mbedtls_mpi *px = &((const mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(X); ++ mbedtls_mpi *cy2 = (mbedtls_mpi *) ++ crypto_ec_point_compute_y_sqr(e, (const struct crypto_bignum *)px); ++ if (cy2 == NULL) ++ return 0; ++ ++ mbedtls_mpi y2; ++ mbedtls_mpi_init(&y2); ++ const mbedtls_mpi *py = &((const mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Y); ++ int is_on_curve = mbedtls_mpi_mul_mpi(&y2, py, py) /* y^2 mod P */ ++ || mbedtls_mpi_mod_mpi(&y2, &y2, CRYPTO_EC_P(e)) ++ || mbedtls_mpi_cmp_mpi(&y2, cy2) != 0 ? 0 : 1; ++ ++ mbedtls_mpi_free(&y2); ++ mbedtls_mpi_free(cy2); ++ os_free(cy2); ++ return is_on_curve; ++ #endif ++} ++ ++int crypto_ec_point_cmp(const struct crypto_ec *e, ++ const struct crypto_ec_point *a, ++ const struct crypto_ec_point *b) ++{ ++ return mbedtls_ecp_point_cmp((const mbedtls_ecp_point *)a, ++ (const mbedtls_ecp_point *)b); ++} ++ ++#if !defined(CONFIG_NO_STDOUT_DEBUG) ++void crypto_ec_point_debug_print(const struct crypto_ec *e, ++ const struct crypto_ec_point *p, ++ const char *title) ++{ ++ u8 x[MBEDTLS_MPI_MAX_SIZE]; ++ u8 y[MBEDTLS_MPI_MAX_SIZE]; ++ size_t len = CRYPTO_EC_plen(e); ++ /* crypto_ec_point_to_bin ought to take (const struct crypto_ec *e) */ ++ struct crypto_ec *ee; ++ *(const struct crypto_ec **)&ee = e; /*(cast away const)*/ ++ if (crypto_ec_point_to_bin(ee, p, x, y) == 0) { ++ if (title) ++ wpa_printf(MSG_DEBUG, "%s", title); ++ wpa_hexdump(MSG_DEBUG, "x:", x, len); ++ wpa_hexdump(MSG_DEBUG, "y:", y, len); ++ } ++} ++#endif ++ ++ ++struct crypto_ec_key * crypto_ec_key_parse_priv(const u8 *der, size_t der_len) ++{ ++ mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx)); ++ if (ctx == NULL) ++ return NULL; ++ mbedtls_pk_init(ctx); ++ #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */ ++ if (mbedtls_pk_parse_key(ctx, der, der_len, NULL, 0) == 0) ++ #else ++ if (mbedtls_pk_parse_key(ctx, der, der_len, NULL, 0, ++ mbedtls_ctr_drbg_random, ++ crypto_mbedtls_ctr_drbg()) == 0) ++ #endif ++ return (struct crypto_ec_key *)ctx; ++ ++ mbedtls_pk_free(ctx); ++ os_free(ctx); ++ return NULL; ++} ++ ++#ifdef CRYPTO_MBEDTLS_CRYPTO_HPKE ++#ifdef CONFIG_MODULE_TESTS ++/*(for crypto_module_tests.c)*/ ++struct crypto_ec_key * crypto_ec_key_set_priv(int group, ++ const u8 *raw, size_t raw_len) ++{ ++ mbedtls_ecp_group_id grp_id = ++ crypto_mbedtls_ecp_group_id_from_ike_id(group); ++ if (grp_id == MBEDTLS_ECP_DP_NONE) ++ return NULL; ++ const mbedtls_pk_info_t *pk_info = ++ mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY); ++ if (pk_info == NULL) ++ return NULL; ++ mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx)); ++ if (ctx == NULL) ++ return NULL; ++ mbedtls_pk_init(ctx); ++ if (mbedtls_pk_setup(ctx, pk_info) == 0 ++ && mbedtls_ecp_read_key(grp_id,mbedtls_pk_ec(*ctx),raw,raw_len) == 0) { ++ return (struct crypto_ec_key *)ctx; ++ } ++ ++ mbedtls_pk_free(ctx); ++ os_free(ctx); ++ return NULL; ++} ++#endif ++#endif ++ ++#include ++#include ++static int crypto_mbedtls_pk_parse_subpubkey_compressed(mbedtls_pk_context *ctx, const u8 *der, size_t der_len) ++{ ++ /* The following is modified from: ++ * mbedtls/library/pkparse.c:mbedtls_pk_parse_subpubkey() ++ * mbedtls/library/pkparse.c:pk_get_pk_alg() ++ * mbedtls/library/pkparse.c:pk_use_ecparams() ++ */ ++ mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; ++ const mbedtls_pk_info_t *pk_info; ++ int ret; ++ size_t len; ++ const unsigned char *end = der+der_len; ++ unsigned char *p; ++ *(const unsigned char **)&p = der; ++ ++ if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, ++ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) ++ { ++ return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); ++ } ++ ++ end = p + len; ++ ++ /* ++ if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, &alg_params ) ) != 0 ) ++ return( ret ); ++ */ ++ mbedtls_asn1_buf alg_oid, params; ++ memset( ¶ms, 0, sizeof(mbedtls_asn1_buf) ); ++ if( ( ret = mbedtls_asn1_get_alg( &p, end, &alg_oid, ¶ms ) ) != 0 ) ++ return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_ALG, ret ) ); ++ if( mbedtls_oid_get_pk_alg( &alg_oid, &pk_alg ) != 0 ) ++ return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); ++ ++ if( ( ret = mbedtls_asn1_get_bitstring_null( &p, end, &len ) ) != 0 ) ++ return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, ret ) ); ++ ++ if( p + len != end ) ++ return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, ++ MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); ++ ++ if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) ++ return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); ++ ++ if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 ) ++ return( ret ); ++ ++ /* assume mbedtls_pk_parse_subpubkey(&der, der+der_len, ctx) ++ * has already run with ctx initialized up to pk_get_ecpubkey(), ++ * and pk_get_ecpubkey() has returned MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ++ * ++ * mbedtls mbedtls_ecp_point_read_binary() ++ * does not handle point in COMPRESSED format ++ * ++ * (validate assumption that algorithm is EC) */ ++ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*ctx); ++ if (ecp_kp == NULL) ++ return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); ++ mbedtls_ecp_group *ecp_kp_grp = &ecp_kp->MBEDTLS_PRIVATE(grp); ++ mbedtls_ecp_point *ecp_kp_Q = &ecp_kp->MBEDTLS_PRIVATE(Q); ++ mbedtls_ecp_group_id grp_id; ++ ++ ++ /* mbedtls/library/pkparse.c:pk_use_ecparams() */ ++ ++ if( params.tag == MBEDTLS_ASN1_OID ) ++ { ++ if( mbedtls_oid_get_ec_grp( ¶ms, &grp_id ) != 0 ) ++ return( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE ); ++ } ++ else ++ { ++#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) ++ /*(large code block not copied from mbedtls; unsupported)*/ ++ #if 0 ++ if( ( ret = pk_group_id_from_specified( ¶ms, &grp_id ) ) != 0 ) ++ return( ret ); ++ #endif ++#endif ++ return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); ++ } ++ ++ /* ++ * grp may already be initialized; if so, make sure IDs match ++ */ ++ if( ecp_kp_grp->id != MBEDTLS_ECP_DP_NONE && ecp_kp_grp->id != grp_id ) ++ return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); ++ ++ if( ( ret = mbedtls_ecp_group_load( ecp_kp_grp, grp_id ) ) != 0 ) ++ return( ret ); ++ ++ ++ /* (validate assumption that EC point is in COMPRESSED format) */ ++ len = CRYPTO_EC_plen(ecp_kp_grp); ++ if( mbedtls_ecp_get_type(ecp_kp_grp) != MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ++ || (end - p) != 1+len ++ || (*p != 0x02 && *p != 0x03) ) ++ return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); ++ ++ /* Instead of calling mbedtls/library/pkparse.c:pk_get_ecpubkey() to call ++ * mbedtls_ecp_point_read_binary(), manually parse point into ecp_kp_Q */ ++ mbedtls_mpi *X = &ecp_kp_Q->MBEDTLS_PRIVATE(X); ++ mbedtls_mpi *Y = &ecp_kp_Q->MBEDTLS_PRIVATE(Y); ++ mbedtls_mpi *Z = &ecp_kp_Q->MBEDTLS_PRIVATE(Z); ++ ret = mbedtls_mpi_lset(Z, 1); ++ if (ret != 0) ++ return( ret ); ++ ret = mbedtls_mpi_read_binary(X, p+1, len); ++ if (ret != 0) ++ return( ret ); ++ /* derive Y ++ * (similar derivation of Y in crypto_mbedtls.c:crypto_ecdh_set_peerkey())*/ ++ ret = mbedtls_mpi_copy(Y, X) /*(Y is used as input and output obj below)*/ ++ || crypto_mbedtls_short_weierstrass_derive_y(ecp_kp_grp, Y, (*p & 1)); ++ if (ret != 0) ++ return( ret ); ++ ++ return mbedtls_ecp_check_pubkey( ecp_kp_grp, ecp_kp_Q ); ++} ++ ++struct crypto_ec_key * crypto_ec_key_parse_pub(const u8 *der, size_t der_len) ++{ ++ mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx)); ++ if (ctx == NULL) ++ return NULL; ++ mbedtls_pk_init(ctx); ++ /*int rc = mbedtls_pk_parse_subpubkey(&der, der+der_len, ctx);*/ ++ int rc = mbedtls_pk_parse_public_key(ctx, der, der_len); ++ if (rc == 0) ++ return (struct crypto_ec_key *)ctx; ++ else if (rc == MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) { ++ /* mbedtls mbedtls_ecp_point_read_binary() ++ * does not handle point in COMPRESSED format; parse internally */ ++ rc = crypto_mbedtls_pk_parse_subpubkey_compressed(ctx,der,der_len); ++ if (rc == 0) ++ return (struct crypto_ec_key *)ctx; ++ } ++ ++ mbedtls_pk_free(ctx); ++ os_free(ctx); ++ return NULL; ++} ++ ++#ifdef CRYPTO_MBEDTLS_CRYPTO_EC_DPP ++ ++static struct crypto_ec_key * ++crypto_ec_key_set_pub_point_for_group(mbedtls_ecp_group_id grp_id, ++ const mbedtls_ecp_point *pub, ++ const u8 *buf, size_t len) ++{ ++ const mbedtls_pk_info_t *pk_info = ++ mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY); ++ if (pk_info == NULL) ++ return NULL; ++ mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx)); ++ if (ctx == NULL) ++ return NULL; ++ mbedtls_pk_init(ctx); ++ if (mbedtls_pk_setup(ctx, pk_info) == 0) { ++ /* (Is private key generation necessary for callers?) ++ * alt: gen key then overwrite Q ++ * mbedtls_ecp_gen_key(grp_id, ecp_kp, ++ * mbedtls_ctr_drbg_random, ++ * crypto_mbedtls_ctr_drbg()) == 0 ++ */ ++ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*ctx); ++ mbedtls_ecp_group *ecp_kp_grp = &ecp_kp->MBEDTLS_PRIVATE(grp); ++ mbedtls_ecp_point *ecp_kp_Q = &ecp_kp->MBEDTLS_PRIVATE(Q); ++ mbedtls_mpi *ecp_kp_d = &ecp_kp->MBEDTLS_PRIVATE(d); ++ if (mbedtls_ecp_group_load(ecp_kp_grp, grp_id) == 0 ++ && (pub ++ ? mbedtls_ecp_copy(ecp_kp_Q, pub) == 0 ++ : mbedtls_ecp_point_read_binary(ecp_kp_grp, ecp_kp_Q, ++ buf, len) == 0) ++ && mbedtls_ecp_gen_privkey(ecp_kp_grp, ecp_kp_d, ++ mbedtls_ctr_drbg_random, ++ crypto_mbedtls_ctr_drbg()) == 0){ ++ return (struct crypto_ec_key *)ctx; ++ } ++ } ++ ++ mbedtls_pk_free(ctx); ++ os_free(ctx); ++ return NULL; ++} ++ ++struct crypto_ec_key * crypto_ec_key_set_pub(int group, const u8 *x, ++ const u8 *y, size_t len) ++{ ++ mbedtls_ecp_group_id grp_id = ++ crypto_mbedtls_ecp_group_id_from_ike_id(group); ++ if (grp_id == MBEDTLS_ECP_DP_NONE) ++ return NULL; ++ if (len > MBEDTLS_MPI_MAX_SIZE) ++ return NULL; ++ u8 buf[1+MBEDTLS_MPI_MAX_SIZE*2]; ++ buf[0] = 0x04; /* assume x,y for Short Weierstrass */ ++ os_memcpy(buf+1, x, len); ++ os_memcpy(buf+1+len, y, len); ++ ++ return crypto_ec_key_set_pub_point_for_group(grp_id,NULL,buf,1+len*2); ++} ++ ++struct crypto_ec_key * ++crypto_ec_key_set_pub_point(struct crypto_ec *e, ++ const struct crypto_ec_point *pub) ++{ ++ mbedtls_ecp_group_id grp_id = ((mbedtls_ecp_group *)e)->id; ++ mbedtls_ecp_point *p = (mbedtls_ecp_point *)pub; ++ return crypto_ec_key_set_pub_point_for_group(grp_id, p, NULL, 0); ++} ++ ++ ++struct crypto_ec_key * crypto_ec_key_gen(int group) ++{ ++ mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx)); ++ if (ctx == NULL) ++ return NULL; ++ mbedtls_pk_init(ctx); ++ if (crypto_mbedtls_keypair_gen(group, ctx) == 0) ++ return (struct crypto_ec_key *)ctx; ++ mbedtls_pk_free(ctx); ++ os_free(ctx); ++ return NULL; ++} ++ ++#endif /* CRYPTO_MBEDTLS_CRYPTO_EC_DPP */ ++ ++void crypto_ec_key_deinit(struct crypto_ec_key *key) ++{ ++ mbedtls_pk_free((mbedtls_pk_context *)key); ++ os_free(key); ++} ++ ++struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key) ++{ ++ /* (similar to crypto_ec_key_get_pubkey_point(), ++ * but compressed point format and ASN.1 DER wrapping)*/ ++#ifndef MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES /*(mbedtls/library/pkwrite.h)*/ ++#define MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES ( 30 + 2 * MBEDTLS_ECP_MAX_BYTES ) ++#endif ++ unsigned char buf[MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES]; ++ int len = mbedtls_pk_write_pubkey_der((mbedtls_pk_context *)key, ++ buf, sizeof(buf)); ++ if (len < 0) ++ return NULL; ++ /* Note: data is written at the end of the buffer! Use the ++ * return value to determine where you should start ++ * using the buffer */ ++ unsigned char *p = buf+sizeof(buf)-len; ++ ++ #ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED ++ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key); ++ if (ecp_kp == NULL) ++ return NULL; ++ mbedtls_ecp_group *grp = &ecp_kp->MBEDTLS_PRIVATE(grp); ++ /* Note: sae_pk.c expects pubkey point in compressed format, ++ * but mbedtls_pk_write_pubkey_der() writes uncompressed format. ++ * Manually translate format and update lengths in DER format */ ++ if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { ++ unsigned char *end = buf+sizeof(buf); ++ size_t n; ++ /* SubjectPublicKeyInfo SEQUENCE */ ++ mbedtls_asn1_get_tag(&p, end, &n, ++ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); ++ /* algorithm AlgorithmIdentifier */ ++ unsigned char *a = p; ++ size_t alen; ++ mbedtls_asn1_get_tag(&p, end, &alen, ++ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); ++ p += alen; ++ alen = (size_t)(p - a); ++ /* subjectPublicKey BIT STRING */ ++ mbedtls_asn1_get_tag(&p, end, &n, MBEDTLS_ASN1_BIT_STRING); ++ /* rewrite into compressed point format and rebuild ASN.1 */ ++ p[1] = (buf[sizeof(buf)-1] & 1) ? 0x03 : 0x02; ++ n = 1 + 1 + (n-2)/2; ++ len = mbedtls_asn1_write_len(&p, buf, n) + (int)n; ++ len += mbedtls_asn1_write_tag(&p, buf, MBEDTLS_ASN1_BIT_STRING); ++ os_memmove(p-alen, a, alen); ++ len += alen; ++ p -= alen; ++ len += mbedtls_asn1_write_len(&p, buf, (size_t)len); ++ len += mbedtls_asn1_write_tag(&p, buf, ++ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); ++ } ++ #endif ++ return wpabuf_alloc_copy(p, (size_t)len); ++} ++ ++#ifdef CRYPTO_MBEDTLS_CRYPTO_EC_DPP ++ ++struct wpabuf * crypto_ec_key_get_ecprivate_key(struct crypto_ec_key *key, ++ bool include_pub) ++{ ++#ifndef MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES /*(mbedtls/library/pkwrite.h)*/ ++#define MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES ( 29 + 3 * MBEDTLS_ECP_MAX_BYTES ) ++#endif ++ unsigned char priv[MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES]; ++ int privlen = mbedtls_pk_write_key_der((mbedtls_pk_context *)key, ++ priv, sizeof(priv)); ++ if (privlen < 0) ++ return NULL; ++ ++ struct wpabuf *wbuf; ++ ++ /* Note: data is written at the end of the buffer! Use the ++ * return value to determine where you should start ++ * using the buffer */ ++ /* mbedtls_pk_write_key_der() includes publicKey in DER */ ++ if (include_pub) ++ wbuf = wpabuf_alloc_copy(priv+sizeof(priv)-privlen, privlen); ++ else { ++ /* calculate publicKey offset and skip from end of buffer */ ++ unsigned char *p = priv+sizeof(priv)-privlen; ++ unsigned char *end = priv+sizeof(priv); ++ size_t len; ++ /* ECPrivateKey SEQUENCE */ ++ mbedtls_asn1_get_tag(&p, end, &len, ++ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); ++ /* version INTEGER */ ++ unsigned char *v = p; ++ mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER); ++ p += len; ++ /* privateKey OCTET STRING */ ++ mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); ++ p += len; ++ /* parameters ECParameters */ ++ mbedtls_asn1_get_tag(&p, end, &len, ++ MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED); ++ p += len; ++ ++ /* write new SEQUENCE header (we know that it fits in priv[]) */ ++ len = (size_t)(p - v); ++ p = v; ++ len += mbedtls_asn1_write_len(&p, priv, len); ++ len += mbedtls_asn1_write_tag(&p, priv, ++ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); ++ wbuf = wpabuf_alloc_copy(p, len); ++ } ++ ++ forced_memzero(priv, sizeof(priv)); ++ return wbuf; ++} ++ ++struct wpabuf * crypto_ec_key_get_pubkey_point(struct crypto_ec_key *key, ++ int prefix) ++{ ++ /*(similarities to crypto_ecdh_get_pubkey(), but different struct)*/ ++ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key); ++ if (ecp_kp == NULL) ++ return NULL; ++ mbedtls_ecp_group *grp = &ecp_kp->MBEDTLS_PRIVATE(grp); ++ size_t len = CRYPTO_EC_plen(grp); ++ #ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED ++ /* len */ ++ #endif ++ #ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED ++ if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) ++ len = len*2+1; ++ #endif ++ struct wpabuf *buf = wpabuf_alloc(len); ++ if (buf == NULL) ++ return NULL; ++ mbedtls_ecp_point *ecp_kp_Q = &ecp_kp->MBEDTLS_PRIVATE(Q); ++ if (mbedtls_ecp_point_write_binary(grp, ecp_kp_Q, ++ MBEDTLS_ECP_PF_UNCOMPRESSED, &len, ++ wpabuf_mhead_u8(buf), len) == 0) { ++ if (!prefix) /* Remove 0x04 prefix if requested */ ++ os_memmove(wpabuf_mhead(buf),wpabuf_mhead(buf)+1,--len); ++ wpabuf_put(buf, len); ++ return buf; ++ } ++ ++ wpabuf_free(buf); ++ return NULL; ++} ++ ++struct crypto_ec_point * ++crypto_ec_key_get_public_key(struct crypto_ec_key *key) ++{ ++ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key); ++ if (ecp_kp == NULL) ++ return NULL; ++ mbedtls_ecp_point *p = os_malloc(sizeof(*p)); ++ if (p != NULL) { ++ /*(mbedtls_ecp_export() uses &ecp_kp->MBEDTLS_PRIVATE(grp))*/ ++ mbedtls_ecp_point_init(p); ++ mbedtls_ecp_point *ecp_kp_Q = &ecp_kp->MBEDTLS_PRIVATE(Q); ++ if (mbedtls_ecp_copy(p, ecp_kp_Q)) { ++ mbedtls_ecp_point_free(p); ++ os_free(p); ++ p = NULL; ++ } ++ } ++ return (struct crypto_ec_point *)p; ++} ++ ++struct crypto_bignum * ++crypto_ec_key_get_private_key(struct crypto_ec_key *key) ++{ ++ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key); ++ if (ecp_kp == NULL) ++ return NULL; ++ mbedtls_mpi *bn = os_malloc(sizeof(*bn)); ++ if (bn) { ++ /*(mbedtls_ecp_export() uses &ecp_kp->MBEDTLS_PRIVATE(grp))*/ ++ mbedtls_mpi_init(bn); ++ mbedtls_mpi *ecp_kp_d = &ecp_kp->MBEDTLS_PRIVATE(d); ++ if (mbedtls_mpi_copy(bn, ecp_kp_d)) { ++ mbedtls_mpi_free(bn); ++ os_free(bn); ++ bn = NULL; ++ } ++ } ++ return (struct crypto_bignum *)bn; ++} ++ ++#endif /* CRYPTO_MBEDTLS_CRYPTO_EC_DPP */ ++ ++static mbedtls_md_type_t crypto_ec_key_sign_md(size_t len) ++{ ++ /* get mbedtls_md_type_t from length of hash data to be signed */ ++ switch (len) { ++ case 64: return MBEDTLS_MD_SHA512; ++ case 48: return MBEDTLS_MD_SHA384; ++ case 32: return MBEDTLS_MD_SHA256; ++ case 20: return MBEDTLS_MD_SHA1; ++ case 16: return MBEDTLS_MD_MD5; ++ default: return MBEDTLS_MD_NONE; ++ } ++} ++ ++struct wpabuf * crypto_ec_key_sign(struct crypto_ec_key *key, const u8 *data, ++ size_t len) ++{ ++ #ifndef MBEDTLS_PK_SIGNATURE_MAX_SIZE /*(defined since mbedtls 2.20.0)*/ ++ #if MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_MPI_MAX_SIZE ++ #define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN ++ #else ++ #define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE ++ #endif ++ #endif ++ size_t sig_len = MBEDTLS_PK_SIGNATURE_MAX_SIZE; ++ struct wpabuf *buf = wpabuf_alloc(sig_len); ++ if (buf == NULL) ++ return NULL; ++ if (mbedtls_pk_sign((mbedtls_pk_context *)key, ++ crypto_ec_key_sign_md(len), data, len, ++ wpabuf_mhead_u8(buf), ++ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */ ++ sig_len, ++ #endif ++ &sig_len, ++ mbedtls_ctr_drbg_random, ++ crypto_mbedtls_ctr_drbg()) == 0) { ++ wpabuf_put(buf, sig_len); ++ return buf; ++ } ++ ++ wpabuf_free(buf); ++ return NULL; ++} ++ ++#ifdef CRYPTO_MBEDTLS_CRYPTO_EC_DPP ++struct wpabuf * crypto_ec_key_sign_r_s(struct crypto_ec_key *key, ++ const u8 *data, size_t len) ++{ ++ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key); ++ if (ecp_kp == NULL) ++ return NULL; ++ ++ size_t sig_len = MBEDTLS_ECDSA_MAX_LEN; ++ u8 buf[MBEDTLS_ECDSA_MAX_LEN]; ++ if (mbedtls_ecdsa_write_signature(ecp_kp, crypto_ec_key_sign_md(len), ++ data, len, buf, ++ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */ ++ sig_len, ++ #endif ++ &sig_len, ++ mbedtls_ctr_drbg_random, ++ crypto_mbedtls_ctr_drbg())) { ++ return NULL; ++ } ++ ++ /*(mbedtls_ecdsa_write_signature() writes signature in ASN.1)*/ ++ /* parse ASN.1 to get r and s and lengths */ ++ u8 *p = buf, *r, *s; ++ u8 *end = p + sig_len; ++ size_t rlen, slen; ++ mbedtls_asn1_get_tag(&p, end, &rlen, ++ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); ++ mbedtls_asn1_get_tag(&p, end, &rlen, MBEDTLS_ASN1_INTEGER); ++ r = p; ++ p += rlen; ++ mbedtls_asn1_get_tag(&p, end, &slen, MBEDTLS_ASN1_INTEGER); ++ s = p; ++ ++ /* write raw r and s into out ++ * (including removal of leading 0 if added for ASN.1 integer) ++ * note: DPP caller expects raw r, s each padded to prime len */ ++ mbedtls_ecp_group *ecp_kp_grp = &ecp_kp->MBEDTLS_PRIVATE(grp); ++ size_t plen = CRYPTO_EC_plen(ecp_kp_grp); ++ if (rlen > plen) { ++ r += (rlen - plen); ++ rlen = plen; ++ } ++ if (slen > plen) { ++ s += (slen - plen); ++ slen = plen; ++ } ++ struct wpabuf *out = wpabuf_alloc(plen*2); ++ if (out) { ++ wpabuf_put(out, plen*2); ++ p = wpabuf_mhead_u8(out); ++ os_memset(p, 0, plen*2); ++ os_memcpy(p+plen*1-rlen, r, rlen); ++ os_memcpy(p+plen*2-slen, s, slen); ++ } ++ return out; ++} ++#endif /* CRYPTO_MBEDTLS_CRYPTO_EC_DPP */ ++ ++int crypto_ec_key_verify_signature(struct crypto_ec_key *key, const u8 *data, ++ size_t len, const u8 *sig, size_t sig_len) ++{ ++ switch (mbedtls_pk_verify((mbedtls_pk_context *)key, ++ crypto_ec_key_sign_md(len), data, len, ++ sig, sig_len)) { ++ case 0: ++ /*case MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH:*//* XXX: allow? */ ++ return 1; ++ case MBEDTLS_ERR_ECP_VERIFY_FAILED: ++ return 0; ++ default: ++ return -1; ++ } ++} ++ ++#ifdef CRYPTO_MBEDTLS_CRYPTO_EC_DPP ++int crypto_ec_key_verify_signature_r_s(struct crypto_ec_key *key, ++ const u8 *data, size_t len, ++ const u8 *r, size_t r_len, ++ const u8 *s, size_t s_len) ++{ ++ /* reimplement mbedtls_ecdsa_read_signature() without encoding r and s ++ * into ASN.1 just for mbedtls_ecdsa_read_signature() to decode ASN.1 */ ++ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key); ++ if (ecp_kp == NULL) ++ return -1; ++ mbedtls_ecp_group *ecp_kp_grp = &ecp_kp->MBEDTLS_PRIVATE(grp); ++ mbedtls_ecp_point *ecp_kp_Q = &ecp_kp->MBEDTLS_PRIVATE(Q); ++ ++ mbedtls_mpi mpi_r; ++ mbedtls_mpi mpi_s; ++ mbedtls_mpi_init(&mpi_r); ++ mbedtls_mpi_init(&mpi_s); ++ int ret = mbedtls_mpi_read_binary(&mpi_r, r, r_len) ++ || mbedtls_mpi_read_binary(&mpi_s, s, s_len) ? -1 : 0; ++ if (ret == 0) { ++ ret = mbedtls_ecdsa_verify(ecp_kp_grp, data, len, ++ ecp_kp_Q, &mpi_r, &mpi_s); ++ ret = ret ? ret == MBEDTLS_ERR_ECP_BAD_INPUT_DATA ? 0 : -1 : 1; ++ } ++ mbedtls_mpi_free(&mpi_r); ++ mbedtls_mpi_free(&mpi_s); ++ return ret; ++} ++#endif /* CRYPTO_MBEDTLS_CRYPTO_EC_DPP */ ++ ++int crypto_ec_key_group(struct crypto_ec_key *key) ++{ ++ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key); ++ if (ecp_kp == NULL) ++ return -1; ++ mbedtls_ecp_group *ecp_group = &ecp_kp->MBEDTLS_PRIVATE(grp); ++ return crypto_mbedtls_ike_id_from_ecp_group_id(ecp_group->id); ++} ++ ++#ifdef CRYPTO_MBEDTLS_CRYPTO_EC_DPP ++ ++int crypto_ec_key_cmp(struct crypto_ec_key *key1, struct crypto_ec_key *key2) ++{ ++#if 0 /*(DPP is passing two public keys; unable to use pk_check_pair())*/ ++ #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */ ++ return mbedtls_pk_check_pair((const mbedtls_pk_context *)key1, ++ (const mbedtls_pk_context *)key2) ? -1 : 0; ++ #else ++ return mbedtls_pk_check_pair((const mbedtls_pk_context *)key1, ++ (const mbedtls_pk_context *)key2, ++ mbedtls_ctr_drbg_random, ++ crypto_mbedtls_ctr_drbg()) ? -1 : 0; ++ #endif ++#else ++ mbedtls_ecp_keypair *ecp_kp1=mbedtls_pk_ec(*(mbedtls_pk_context *)key1); ++ mbedtls_ecp_keypair *ecp_kp2=mbedtls_pk_ec(*(mbedtls_pk_context *)key2); ++ if (ecp_kp1 == NULL || ecp_kp2 == NULL) ++ return -1; ++ mbedtls_ecp_group *ecp_kp1_grp = &ecp_kp1->MBEDTLS_PRIVATE(grp); ++ mbedtls_ecp_group *ecp_kp2_grp = &ecp_kp2->MBEDTLS_PRIVATE(grp); ++ mbedtls_ecp_point *ecp_kp1_Q = &ecp_kp1->MBEDTLS_PRIVATE(Q); ++ mbedtls_ecp_point *ecp_kp2_Q = &ecp_kp2->MBEDTLS_PRIVATE(Q); ++ return ecp_kp1_grp->id != ecp_kp2_grp->id ++ || mbedtls_ecp_point_cmp(ecp_kp1_Q, ecp_kp2_Q) ? -1 : 0; ++#endif ++} ++ ++void crypto_ec_key_debug_print(const struct crypto_ec_key *key, ++ const char *title) ++{ ++ /* TBD: what info is desirable here and in what human readable format?*/ ++ /*(crypto_openssl.c prints a human-readably public key and attributes)*/ ++ #if 0 ++ struct mbedtls_pk_debug_item debug_item; ++ if (mbedtls_pk_debug((const mbedtls_pk_context *)key, &debug_item)) ++ return; ++ /* ... */ ++ #endif ++ wpa_printf(MSG_DEBUG, "%s: %s not implemented", title, __func__); ++} ++ ++#endif /* CRYPTO_MBEDTLS_CRYPTO_EC_DPP */ ++ ++#endif /* CRYPTO_MBEDTLS_CRYPTO_EC */ ++ ++ ++#ifdef CRYPTO_MBEDTLS_CRYPTO_CSR ++ ++#include ++#include ++ ++struct crypto_csr * crypto_csr_init(void) ++{ ++ mbedtls_x509write_csr *csr = os_malloc(sizeof(*csr)); ++ if (csr != NULL) ++ mbedtls_x509write_csr_init(csr); ++ return (struct crypto_csr *)csr; ++} ++ ++struct crypto_csr * crypto_csr_verify(const struct wpabuf *req) ++{ ++ /* future: look for alternatives to MBEDTLS_PRIVATE() access */ ++ ++ /* sole caller src/common/dpp_crypto.c:dpp_validate_csr() ++ * uses (mbedtls_x509_csr *) to obtain CSR_ATTR_CHALLENGE_PASSWORD ++ * so allocate different object (mbedtls_x509_csr *) and special-case ++ * object when used in crypto_csr_get_attribute() and when free()d in ++ * crypto_csr_deinit(). */ ++ ++ mbedtls_x509_csr *csr = os_malloc(sizeof(*csr)); ++ if (csr == NULL) ++ return NULL; ++ mbedtls_x509_csr_init(csr); ++ const mbedtls_md_info_t *md_info; ++ unsigned char digest[MBEDTLS_MD_MAX_SIZE]; ++ if (mbedtls_x509_csr_parse_der(csr,wpabuf_head(req),wpabuf_len(req))==0 ++ && (md_info=mbedtls_md_info_from_type(csr->MBEDTLS_PRIVATE(sig_md))) ++ != NULL ++ && mbedtls_md(md_info, csr->cri.p, csr->cri.len, digest) == 0) { ++ switch (mbedtls_pk_verify(&csr->pk,csr->MBEDTLS_PRIVATE(sig_md), ++ digest, mbedtls_md_get_size(md_info), ++ csr->MBEDTLS_PRIVATE(sig).p, ++ csr->MBEDTLS_PRIVATE(sig).len)) { ++ case 0: ++ /*case MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH:*//* XXX: allow? */ ++ return (struct crypto_csr *)((uintptr_t)csr | 1uL); ++ default: ++ break; ++ } ++ } ++ ++ mbedtls_x509_csr_free(csr); ++ os_free(csr); ++ return NULL; ++} ++ ++void crypto_csr_deinit(struct crypto_csr *csr) ++{ ++ if ((uintptr_t)csr & 1uL) { ++ csr = (struct crypto_csr *)((uintptr_t)csr & ~1uL); ++ mbedtls_x509_csr_free((mbedtls_x509_csr *)csr); ++ } ++ else ++ mbedtls_x509write_csr_free((mbedtls_x509write_csr *)csr); ++ os_free(csr); ++} ++ ++int crypto_csr_set_ec_public_key(struct crypto_csr *csr, ++ struct crypto_ec_key *key) ++{ ++ mbedtls_x509write_csr_set_key((mbedtls_x509write_csr *)csr, ++ (mbedtls_pk_context *)key); ++ return 0; ++} ++ ++int crypto_csr_set_name(struct crypto_csr *csr, enum crypto_csr_name type, ++ const char *name) ++{ ++ /* specialized for src/common/dpp_crypto.c */ ++ ++ /* sole caller src/common/dpp_crypto.c:dpp_build_csr() ++ * calls this function only once, using type == CSR_NAME_CN ++ * (If called more than once, this code would need to append ++ * components to the subject name, which we could do by ++ * appending to (mbedtls_x509write_csr *) private member ++ * mbedtls_asn1_named_data *MBEDTLS_PRIVATE(subject)) */ ++ ++ const char *label; ++ switch (type) { ++ case CSR_NAME_CN: label = "CN="; break; ++ case CSR_NAME_SN: label = "SN="; break; ++ case CSR_NAME_C: label = "C="; break; ++ case CSR_NAME_O: label = "O="; break; ++ case CSR_NAME_OU: label = "OU="; break; ++ default: return -1; ++ } ++ ++ size_t len = strlen(name); ++ struct wpabuf *buf = wpabuf_alloc(3+len+1); ++ if (buf == NULL) ++ return -1; ++ wpabuf_put_data(buf, label, strlen(label)); ++ wpabuf_put_data(buf, name, len+1); /*(include trailing '\0')*/ ++ /* Note: 'name' provided is set as given and should be backslash-escaped ++ * by caller when necessary, e.g. literal ',' which are not separating ++ * components should be backslash-escaped */ ++ ++ int ret = ++ mbedtls_x509write_csr_set_subject_name((mbedtls_x509write_csr *)csr, ++ wpabuf_head(buf)) ? -1 : 0; ++ wpabuf_free(buf); ++ return ret; ++} ++ ++/* OBJ_pkcs9_challengePassword 1 2 840 113549 1 9 7 */ ++static const char OBJ_pkcs9_challengePassword[] = MBEDTLS_OID_PKCS9 "\x07"; ++ ++int crypto_csr_set_attribute(struct crypto_csr *csr, enum crypto_csr_attr attr, ++ int attr_type, const u8 *value, size_t len) ++{ ++ /* specialized for src/common/dpp_crypto.c */ ++ /* sole caller src/common/dpp_crypto.c:dpp_build_csr() passes ++ * attr == CSR_ATTR_CHALLENGE_PASSWORD ++ * attr_type == ASN1_TAG_UTF8STRING */ ++ ++ const char *oid; ++ size_t oid_len; ++ switch (attr) { ++ case CSR_ATTR_CHALLENGE_PASSWORD: ++ oid = OBJ_pkcs9_challengePassword; ++ oid_len = sizeof(OBJ_pkcs9_challengePassword)-1; ++ break; ++ default: ++ return -1; ++ } ++ ++ #if 0 /*(incorrect; sets an extension, not an attribute)*/ ++ return mbedtls_x509write_csr_set_extension((mbedtls_x509write_csr *)csr, ++ oid, oid_len, ++ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */ ++ 0, /*(critical flag)*/ ++ #endif ++ value, len) ? -1 : 0; ++ #else ++ (void)oid; ++ (void)oid_len; ++ #endif ++ ++ /* mbedtls does not currently provide way to set an attribute in a CSR: ++ * https://github.com/Mbed-TLS/mbedtls/issues/4886 */ ++ wpa_printf(MSG_ERROR, ++ "mbedtls does not currently support setting challengePassword " ++ "attribute in CSR"); ++ return -1; ++} ++ ++const u8 * mbedtls_x509_csr_attr_oid_value(mbedtls_x509_csr *csr, ++ const char *oid, size_t oid_len, ++ size_t *vlen, int *vtype) ++{ ++ /* Note: mbedtls_x509_csr_parse_der() has parsed and validated CSR, ++ * so validation checks are not repeated here ++ * ++ * It would be nicer if (mbedtls_x509_csr *) had an mbedtls_x509_buf of ++ * Attributes (or at least a pointer) since mbedtls_x509_csr_parse_der() ++ * already parsed the rest of CertificationRequestInfo, some of which is ++ * repeated here to step to Attributes. Since csr->subject_raw.p points ++ * into csr->cri.p, which points into csr->raw.p, step over version and ++ * subject of CertificationRequestInfo (SEQUENCE) */ ++ unsigned char *p = csr->subject_raw.p + csr->subject_raw.len; ++ unsigned char *end = csr->cri.p + csr->cri.len, *ext; ++ size_t len; ++ ++ /* step over SubjectPublicKeyInfo */ ++ mbedtls_asn1_get_tag(&p, end, &len, ++ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); ++ p += len; ++ ++ /* Attributes ++ * { ATTRIBUTE:IOSet } ::= SET OF { SEQUENCE { OID, value } } ++ */ ++ if (mbedtls_asn1_get_tag(&p, end, &len, ++ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) { ++ return NULL; ++ } ++ while (p < end) { ++ if (mbedtls_asn1_get_tag(&p, end, &len, ++ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { ++ return NULL; ++ } ++ ext = p; ++ p += len; ++ ++ if (mbedtls_asn1_get_tag(&ext,end,&len,MBEDTLS_ASN1_OID) != 0) ++ return NULL; ++ if (oid_len != len || 0 != memcmp(ext, oid, oid_len)) ++ continue; ++ ++ /* found oid; return value */ ++ *vtype = *ext++; /* tag */ ++ return (mbedtls_asn1_get_len(&ext,end,vlen) == 0) ? ext : NULL; ++ } ++ ++ return NULL; ++} ++ ++const u8 * crypto_csr_get_attribute(struct crypto_csr *csr, ++ enum crypto_csr_attr attr, ++ size_t *len, int *type) ++{ ++ /* specialized for src/common/dpp_crypto.c */ ++ /* sole caller src/common/dpp_crypto.c:dpp_build_csr() passes ++ * attr == CSR_ATTR_CHALLENGE_PASSWORD */ ++ ++ const char *oid; ++ size_t oid_len; ++ switch (attr) { ++ case CSR_ATTR_CHALLENGE_PASSWORD: ++ oid = OBJ_pkcs9_challengePassword; ++ oid_len = sizeof(OBJ_pkcs9_challengePassword)-1; ++ break; ++ default: ++ return NULL; ++ } ++ ++ /* see crypto_csr_verify(); expecting (mbedtls_x509_csr *) tagged |=1 */ ++ if (!((uintptr_t)csr & 1uL)) ++ return NULL; ++ csr = (struct crypto_csr *)((uintptr_t)csr & ~1uL); ++ ++ return mbedtls_x509_csr_attr_oid_value((mbedtls_x509_csr *)csr, ++ oid, oid_len, len, type); ++} ++ ++struct wpabuf * crypto_csr_sign(struct crypto_csr *csr, ++ struct crypto_ec_key *key, ++ enum crypto_hash_alg algo) ++{ ++ mbedtls_md_type_t sig_md; ++ switch (algo) { ++ #ifdef MBEDTLS_SHA256_C ++ case CRYPTO_HASH_ALG_SHA256: sig_md = MBEDTLS_MD_SHA256; break; ++ #endif ++ #ifdef MBEDTLS_SHA512_C ++ case CRYPTO_HASH_ALG_SHA384: sig_md = MBEDTLS_MD_SHA384; break; ++ case CRYPTO_HASH_ALG_SHA512: sig_md = MBEDTLS_MD_SHA512; break; ++ #endif ++ default: ++ return NULL; ++ } ++ mbedtls_x509write_csr_set_md_alg((mbedtls_x509write_csr *)csr, sig_md); ++ ++ #if 0 ++ unsigned char key_usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE ++ | MBEDTLS_X509_KU_KEY_CERT_SIGN; ++ if (mbedtls_x509write_csr_set_key_usage((mbedtls_x509write_csr *)csr, ++ key_usage)) ++ return NULL; ++ #endif ++ ++ #if 0 ++ unsigned char ns_cert_type = MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT ++ | MBEDTLS_X509_NS_CERT_TYPE_EMAIL; ++ if (mbedtls_x509write_csr_set_ns_cert_type((mbedtls_x509write_csr *)csr, ++ ns_cert_type)) ++ return NULL; ++ #endif ++ ++ #if 0 ++ /* mbedtls does not currently provide way to set an attribute in a CSR: ++ * https://github.com/Mbed-TLS/mbedtls/issues/4886 ++ * XXX: hwsim dpp_enterprise test fails due to this limitation. ++ * ++ * Current usage of this function is solely by dpp_build_csr(), ++ * so as a kludge, might consider custom (struct crypto_csr *) ++ * containing (mbedtls_x509write_csr *) and a list of attributes ++ * (i.e. challengePassword). Might have to totally reimplement ++ * mbedtls_x509write_csr_der(); underlying x509write_csr_der_internal() ++ * handles signing the CSR. (This is more work that appending an ++ * Attributes section to end of CSR and adjusting ASN.1 length of CSR.) ++ */ ++ #endif ++ ++ unsigned char buf[4096]; /* XXX: large enough? too large? */ ++ int len = mbedtls_x509write_csr_der((mbedtls_x509write_csr *)csr, ++ buf, sizeof(buf), ++ mbedtls_ctr_drbg_random, ++ crypto_mbedtls_ctr_drbg()); ++ if (len < 0) ++ return NULL; ++ /* Note: data is written at the end of the buffer! Use the ++ * return value to determine where you should start ++ * using the buffer */ ++ return wpabuf_alloc_copy(buf+sizeof(buf)-len, (size_t)len); ++} ++ ++#endif /* CRYPTO_MBEDTLS_CRYPTO_CSR */ ++ ++ ++#ifdef CRYPTO_MBEDTLS_CRYPTO_PKCS7 ++ ++#if 0 ++#include /* PKCS7 is not currently supported in mbedtls */ ++#include ++#endif ++ ++struct wpabuf * crypto_pkcs7_get_certificates(const struct wpabuf *pkcs7) ++{ ++ /* PKCS7 is not currently supported in mbedtls */ ++ return NULL; ++ ++#if 0 ++ /* https://github.com/naynajain/mbedtls-1 branch: development-pkcs7 ++ * (??? potential future contribution to mbedtls ???) */ ++ ++ /* Note: PKCS7 signature *is not* verified by this function. ++ * The function interface does not provide for passing a certificate */ ++ ++ mbedtls_pkcs7 mpkcs7; ++ mbedtls_pkcs7_init(&mpkcs7); ++ int pkcs7_type = mbedtls_pkcs7_parse_der(wpabuf_head(pkcs7), ++ wpabuf_len(pkcs7), ++ &mpkcs7); ++ wpabuf *buf = NULL; ++ do { ++ if (pkcs7_type < 0) ++ break; ++ ++ /* src/common/dpp.c:dpp_parse_cred_dot1x() interested in certs ++ * for wpa_supplicant/dpp_supplicant.c:wpas_dpp_add_network() ++ * (? are adding certificate headers and footers desired ?) */ ++ ++ /* development-pkcs7 branch does not currently provide ++ * additional interfaces to retrieve the parsed data */ ++ ++ mbedtls_x509_crt *certs = ++ &mpkcs7.MBEDTLS_PRIVATE(signed_data).MBEDTLS_PRIVATE(certs); ++ int ncerts = ++ mpkcs7.MBEDTLS_PRIVATE(signed_data).MBEDTLS_PRIVATE(no_of_certs); ++ ++ /* allocate buffer for PEM (base64-encoded DER) ++ * plus header, footer, newlines, and some extra */ ++ buf = wpabuf_alloc((wpabuf_len(pkcs7)+2)/3*4 + ncerts*64); ++ if (buf == NULL) ++ break; ++ ++ #define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n" ++ #define PEM_END_CRT "-----END CERTIFICATE-----\n" ++ size_t olen; ++ for (int i = 0; i < ncerts; ++i) { ++ int ret = mbedtls_pem_write_buffer( ++ PEM_BEGIN_CRT, PEM_END_CRT, ++ certs[i].raw.p, certs[i].raw.len, ++ wpabuf_mhead(buf, 0), wpabuf_tailroom(buf), ++ &olen)); ++ if (ret == 0) ++ wpabuf_put(buf, olen); ++ } else { ++ if (ret == MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) ++ ret = wpabuf_resize( ++ &buf,olen-wpabuf_tailroom(buf)); ++ if (ret == 0) { ++ --i;/*(adjust loop iterator for retry)*/ ++ continue; ++ } ++ wpabuf_free(buf); ++ buf = NULL; ++ break; ++ } ++ } ++ } while (0); ++ ++ mbedtls_pkcs7_free(&mpkcs7); ++ return buf; ++#endif ++} ++ ++#endif /* CRYPTO_MBEDTLS_CRYPTO_PKCS7 */ ++ ++ ++#ifdef MBEDTLS_ARC4_C ++#include ++int rc4_skip(const u8 *key, size_t keylen, size_t skip, ++ u8 *data, size_t data_len) ++{ ++ mbedtls_arc4_context ctx; ++ mbedtls_arc4_init(&ctx); ++ mbedtls_arc4_setup(&ctx, key, keylen); ++ ++ if (skip) { ++ /*(prefer [16] on ancient hardware with smaller cache lines)*/ ++ unsigned char skip_buf[64]; /*('skip' is generally small)*/ ++ /*os_memset(skip_buf, 0, sizeof(skip_buf));*/ /*(necessary?)*/ ++ size_t len; ++ do { ++ len = skip > sizeof(skip_buf) ? sizeof(skip_buf) : skip; ++ mbedtls_arc4_crypt(&ctx, len, skip_buf, skip_buf); ++ } while ((skip -= len)); ++ } ++ ++ int ret = mbedtls_arc4_crypt(&ctx, data_len, data, data); ++ mbedtls_arc4_free(&ctx); ++ return ret; ++} ++#endif ++ ++ ++/* duplicated in tls_mbedtls.c:tls_mbedtls_readfile()*/ ++__attribute_noinline__ ++static int crypto_mbedtls_readfile(const char *path, u8 **buf, size_t *n) ++{ ++ #if 0 /* #ifdef MBEDTLS_FS_IO */ ++ /*(includes +1 for '\0' needed by mbedtls PEM parsing funcs)*/ ++ if (mbedtls_pk_load_file(path, (unsigned char **)buf, n) != 0) { ++ wpa_printf(MSG_ERROR, "error: mbedtls_pk_load_file %s", path); ++ return -1; ++ } ++ #else ++ /*(use os_readfile() so that we can use os_free() ++ *(if we use mbedtls_pk_load_file() above, macros prevent calling free() ++ * directly #if defined(OS_REJECT_C_LIB_FUNCTIONS) and calling os_free() ++ * on buf aborts in tests if buf not allocated via os_malloc())*/ ++ *buf = (u8 *)os_readfile(path, n); ++ if (!*buf) { ++ wpa_printf(MSG_ERROR, "error: os_readfile %s", path); ++ return -1; ++ } ++ u8 *buf0 = os_realloc(*buf, *n+1); ++ if (!buf0) { ++ bin_clear_free(*buf, *n); ++ *buf = NULL; ++ return -1; ++ } ++ buf0[(*n)++] = '\0'; ++ *buf = buf0; ++ #endif ++ return 0; ++} ++ ++ ++#ifdef CRYPTO_MBEDTLS_CRYPTO_RSA ++#ifdef MBEDTLS_RSA_C ++ ++#include ++#include ++ ++struct crypto_rsa_key * crypto_rsa_key_read(const char *file, bool private_key) ++{ ++ /* mbedtls_pk_parse_keyfile() and mbedtls_pk_parse_public_keyfile() ++ * require #ifdef MBEDTLS_FS_IO in mbedtls library. Prefer to use ++ * crypto_mbedtls_readfile(), which wraps os_readfile() */ ++ u8 *data; ++ size_t len; ++ if (crypto_mbedtls_readfile(file, &data, &len) != 0) ++ return NULL; ++ ++ mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx)); ++ if (ctx == NULL) { ++ bin_clear_free(data, len); ++ return NULL; ++ } ++ mbedtls_pk_init(ctx); ++ ++ int rc; ++ rc = (private_key ++ ? mbedtls_pk_parse_key(ctx, data, len, NULL, 0 ++ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */ ++ ,mbedtls_ctr_drbg_random, ++ crypto_mbedtls_ctr_drbg() ++ #endif ++ ) ++ : mbedtls_pk_parse_public_key(ctx, data, len)) == 0 ++ && mbedtls_pk_can_do(ctx, MBEDTLS_PK_RSA); ++ ++ bin_clear_free(data, len); ++ ++ if (rc) { ++ /* use MBEDTLS_RSA_PKCS_V21 padding for RSAES-OAEP */ ++ /* use MBEDTLS_MD_SHA256 for these hostap interfaces */ ++ #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */ ++ /*(no return value in mbedtls 2.x)*/ ++ mbedtls_rsa_set_padding(mbedtls_pk_rsa(*ctx), ++ MBEDTLS_RSA_PKCS_V21, ++ MBEDTLS_MD_SHA256); ++ #else ++ if (mbedtls_rsa_set_padding(mbedtls_pk_rsa(*ctx), ++ MBEDTLS_RSA_PKCS_V21, ++ MBEDTLS_MD_SHA256) == 0) ++ #endif ++ return (struct crypto_rsa_key *)ctx; ++ } ++ ++ mbedtls_pk_free(ctx); ++ os_free(ctx); ++ return NULL; ++} ++ ++struct wpabuf * crypto_rsa_oaep_sha256_encrypt(struct crypto_rsa_key *key, ++ const struct wpabuf *in) ++{ ++ mbedtls_rsa_context *pk_rsa = mbedtls_pk_rsa(*(mbedtls_pk_context*)key); ++ size_t olen = mbedtls_rsa_get_len(pk_rsa); ++ struct wpabuf *buf = wpabuf_alloc(olen); ++ if (buf == NULL) ++ return NULL; ++ ++ /* mbedtls_pk_encrypt() takes a few more hops to get to same func */ ++ if (mbedtls_rsa_rsaes_oaep_encrypt(pk_rsa, ++ mbedtls_ctr_drbg_random, ++ crypto_mbedtls_ctr_drbg(), ++ #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */ ++ MBEDTLS_RSA_PRIVATE, ++ #endif ++ NULL, 0, ++ wpabuf_len(in), wpabuf_head(in), ++ wpabuf_put(buf, olen)) == 0) { ++ return buf; ++ } ++ ++ wpabuf_clear_free(buf); ++ return NULL; ++} ++ ++struct wpabuf * crypto_rsa_oaep_sha256_decrypt(struct crypto_rsa_key *key, ++ const struct wpabuf *in) ++{ ++ mbedtls_rsa_context *pk_rsa = mbedtls_pk_rsa(*(mbedtls_pk_context*)key); ++ size_t olen = mbedtls_rsa_get_len(pk_rsa); ++ struct wpabuf *buf = wpabuf_alloc(olen); ++ if (buf == NULL) ++ return NULL; ++ ++ /* mbedtls_pk_decrypt() takes a few more hops to get to same func */ ++ if (mbedtls_rsa_rsaes_oaep_decrypt(pk_rsa, ++ mbedtls_ctr_drbg_random, ++ crypto_mbedtls_ctr_drbg(), ++ #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */ ++ MBEDTLS_RSA_PUBLIC, ++ #endif ++ NULL, 0, &olen, wpabuf_head(in), ++ wpabuf_mhead(buf), olen) == 0) { ++ wpabuf_put(buf, olen); ++ return buf; ++ } ++ ++ wpabuf_clear_free(buf); ++ return NULL; ++} ++ ++void crypto_rsa_key_free(struct crypto_rsa_key *key) ++{ ++ mbedtls_pk_free((mbedtls_pk_context *)key); ++ os_free(key); ++} ++ ++#endif /* MBEDTLS_RSA_C */ ++#endif /* CRYPTO_MBEDTLS_CRYPTO_RSA */ ++ ++#ifdef CRYPTO_MBEDTLS_CRYPTO_HPKE ++ ++struct wpabuf * hpke_base_seal(enum hpke_kem_id kem_id, ++ enum hpke_kdf_id kdf_id, ++ enum hpke_aead_id aead_id, ++ struct crypto_ec_key *peer_pub, ++ const u8 *info, size_t info_len, ++ const u8 *aad, size_t aad_len, ++ const u8 *pt, size_t pt_len) ++{ ++ /* not yet implemented */ ++ return NULL; ++} ++ ++struct wpabuf * hpke_base_open(enum hpke_kem_id kem_id, ++ enum hpke_kdf_id kdf_id, ++ enum hpke_aead_id aead_id, ++ struct crypto_ec_key *own_priv, ++ const u8 *info, size_t info_len, ++ const u8 *aad, size_t aad_len, ++ const u8 *enc_ct, size_t enc_ct_len) ++{ ++ /* not yet implemented */ ++ return NULL; ++} ++ ++#endif +--- /dev/null ++++ b/src/crypto/tls_mbedtls.c +@@ -0,0 +1,3313 @@ ++/* ++ * SSL/TLS interface functions for mbed TLS ++ * ++ * SPDX-FileCopyrightText: 2022 Glenn Strauss ++ * SPDX-License-Identifier: BSD-3-Clause ++ * ++ * This software may be distributed under the terms of the BSD license. ++ * See README for more details. ++ * ++ * template: src/crypto/tls_none.c ++ * reference: src/crypto/tls_*.c ++ * ++ * Known Limitations: ++ * - no TLSv1.3 (not available in mbedtls 2.x; experimental in mbedtls 3.x) ++ * - no OCSP (not yet available in mbedtls) ++ * - mbedtls does not support all certificate encodings used by hwsim tests ++ * PCKS#5 v1.5 ++ * PCKS#12 ++ * DH DSA ++ * - EAP-FAST, EAP-TEAP session ticket support not implemented in tls_mbedtls.c ++ * - mbedtls does not currently provide way to set an attribute in a CSR ++ * https://github.com/Mbed-TLS/mbedtls/issues/4886 ++ * so tests/hwsim dpp_enterprise tests fail ++ * - DPP2 not supported ++ * PKCS#7 parsing is not supported in mbedtls ++ * See crypto_mbedtls.c:crypto_pkcs7_get_certificates() comments ++ * - DPP3 not supported ++ * hpke_base_seal() and hpke_base_seal() not implemented in crypto_mbedtls.c ++ * ++ * Status: ++ * - code written to be compatible with mbedtls 2.x and mbedtls 3.x ++ * (currently requires mbedtls >= 2.27.0 for mbedtls_mpi_random()) ++ * (currently requires mbedtls >= 2.18.0 for mbedtls_ssl_tls_prf()) ++ * - builds with tests/build/build-wpa_supplicant-mbedtls.config ++ * - passes all tests/ crypto module tests (incomplete coverage) ++ * ($ cd tests; make clean; make -j 4 run-tests CONFIG_TLS=mbedtls) ++ * - passes almost all tests/hwsim tests ++ * (hwsim tests skipped for missing features) ++ * ++ * RFE: ++ * - EAP-FAST, EAP-TEAP session ticket support not implemented in tls_mbedtls.c ++ * - client/server session resumption, and/or save client session ticket ++ */ ++ ++#include "includes.h" ++#include "common.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include /* mbedtls_calloc() mbedtls_free() */ ++#include /* mbedtls_platform_zeroize() */ ++#include ++#include ++#include ++#include ++ ++#if MBEDTLS_VERSION_NUMBER >= 0x02040000 /* mbedtls 2.4.0 */ ++#include ++#else ++#include ++#endif ++ ++#ifndef MBEDTLS_PRIVATE ++#define MBEDTLS_PRIVATE(x) x ++#endif ++ ++#if MBEDTLS_VERSION_NUMBER < 0x03020000 /* mbedtls 3.2.0 */ ++#define mbedtls_ssl_get_ciphersuite_id_from_ssl(ssl) \ ++ ((ssl)->MBEDTLS_PRIVATE(session) \ ++ ?(ssl)->MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(ciphersuite) \ ++ : 0) ++#define mbedtls_ssl_ciphersuite_get_name(info) \ ++ (info)->MBEDTLS_PRIVATE(name) ++#endif ++ ++#include "crypto.h" /* sha256_vector() */ ++#include "tls.h" ++ ++#ifndef SHA256_DIGEST_LENGTH ++#define SHA256_DIGEST_LENGTH 32 ++#endif ++ ++#ifndef MBEDTLS_EXPKEY_FIXED_SECRET_LEN ++#define MBEDTLS_EXPKEY_FIXED_SECRET_LEN 48 ++#endif ++ ++#ifndef MBEDTLS_EXPKEY_RAND_LEN ++#define MBEDTLS_EXPKEY_RAND_LEN 32 ++#endif ++ ++#if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */ ++static mbedtls_ssl_export_keys_t tls_connection_export_keys_cb; ++#elif MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */ ++static mbedtls_ssl_export_keys_ext_t tls_connection_export_keys_cb; ++#else /*(not implemented; return error)*/ ++#define mbedtls_ssl_tls_prf(a,b,c,d,e,f,g,h) (-1) ++typedef mbedtls_tls_prf_types int; ++#endif ++ ++ ++/* hostapd/wpa_supplicant provides forced_memzero(), ++ * but prefer mbedtls_platform_zeroize() */ ++#define forced_memzero(ptr,sz) mbedtls_platform_zeroize(ptr,sz) ++ ++ ++#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) \ ++ || defined(EAP_TEAP) || defined(EAP_SERVER_TEAP) ++#ifdef MBEDTLS_SSL_SESSION_TICKETS ++#ifdef MBEDTLS_SSL_TICKET_C ++#define TLS_MBEDTLS_SESSION_TICKETS ++#if defined(EAP_TEAP) || defined(EAP_SERVER_TEAP) ++#define TLS_MBEDTLS_EAP_TEAP ++#endif ++#if !defined(CONFIG_FIPS) /* EAP-FAST keys cannot be exported in FIPS mode */ ++#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) ++#define TLS_MBEDTLS_EAP_FAST ++#endif ++#endif ++#endif ++#endif ++#endif ++ ++ ++struct tls_conf { ++ mbedtls_ssl_config conf; ++ ++ unsigned int verify_peer:1; ++ unsigned int verify_depth0_only:1; ++ unsigned int check_crl:2; /*(needs :2 bits for 0, 1, 2)*/ ++ unsigned int check_crl_strict:1; /*(needs :1 bit for 0, 1)*/ ++ unsigned int ca_cert_probe:1; ++ unsigned int has_ca_cert:1; ++ unsigned int has_client_cert:1; ++ unsigned int has_private_key:1; ++ unsigned int suiteb128:1; ++ unsigned int suiteb192:1; ++ mbedtls_x509_crl *crl; ++ mbedtls_x509_crt ca_cert; ++ mbedtls_x509_crt client_cert; ++ mbedtls_pk_context private_key; ++ ++ uint32_t refcnt; ++ ++ unsigned int flags; ++ char *subject_match; ++ char *altsubject_match; ++ char *suffix_match; ++ char *domain_match; ++ char *check_cert_subject; ++ u8 ca_cert_hash[SHA256_DIGEST_LENGTH]; ++ ++ int *ciphersuites; /* list of ciphersuite ids for mbedtls_ssl_config */ ++#if MBEDTLS_VERSION_NUMBER < 0x03010000 /* mbedtls 3.1.0 */ ++ mbedtls_ecp_group_id *curves; ++#else ++ uint16_t *curves; /* list of curve ids for mbedtls_ssl_config */ ++#endif ++}; ++ ++ ++struct tls_global { ++ struct tls_conf *tls_conf; ++ char *ocsp_stapling_response; ++ mbedtls_ctr_drbg_context *ctr_drbg; /*(see crypto_mbedtls.c)*/ ++ #ifdef MBEDTLS_SSL_SESSION_TICKETS ++ mbedtls_ssl_ticket_context ticket_ctx; ++ #endif ++ char *ca_cert_file; ++ struct os_reltime crl_reload_previous; ++ unsigned int crl_reload_interval; ++ uint32_t refcnt; ++ struct tls_config init_conf; ++}; ++ ++static struct tls_global tls_ctx_global; ++ ++ ++struct tls_connection { ++ struct tls_conf *tls_conf; ++ struct wpabuf *push_buf; ++ struct wpabuf *pull_buf; ++ size_t pull_buf_offset; ++ ++ unsigned int established:1; ++ unsigned int resumed:1; ++ unsigned int verify_peer:1; ++ unsigned int is_server:1; ++ ++ mbedtls_ssl_context ssl; ++ ++ mbedtls_tls_prf_types tls_prf_type; ++ size_t expkey_keyblock_size; ++ size_t expkey_secret_len; ++ #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */ ++ unsigned char expkey_secret[MBEDTLS_EXPKEY_FIXED_SECRET_LEN]; ++ #else ++ unsigned char expkey_secret[MBEDTLS_MD_MAX_SIZE]; ++ #endif ++ unsigned char expkey_randbytes[MBEDTLS_EXPKEY_RAND_LEN*2]; ++ ++ int read_alerts, write_alerts, failed; ++ ++ #ifdef TLS_MBEDTLS_SESSION_TICKETS ++ tls_session_ticket_cb session_ticket_cb; ++ void *session_ticket_cb_ctx; ++ unsigned char *clienthello_session_ticket; ++ size_t clienthello_session_ticket_len; ++ #endif ++ char *peer_subject; /* peer subject info for authenticated peer */ ++ struct wpabuf *success_data; ++}; ++ ++ ++#ifndef __has_attribute ++#define __has_attribute(x) 0 ++#endif ++ ++#ifndef __GNUC_PREREQ ++#define __GNUC_PREREQ(maj,min) 0 ++#endif ++ ++#ifndef __attribute_cold__ ++#if __has_attribute(cold) \ ++ || __GNUC_PREREQ(4,3) ++#define __attribute_cold__ __attribute__((__cold__)) ++#else ++#define __attribute_cold__ ++#endif ++#endif ++ ++#ifndef __attribute_noinline__ ++#if __has_attribute(noinline) \ ++ || __GNUC_PREREQ(3,1) ++#define __attribute_noinline__ __attribute__((__noinline__)) ++#else ++#define __attribute_noinline__ ++#endif ++#endif ++ ++ ++__attribute_cold__ ++__attribute_noinline__ ++static void emsg(int level, const char * const msg) ++{ ++ wpa_printf(level, "MTLS: %s", msg); ++} ++ ++ ++__attribute_cold__ ++__attribute_noinline__ ++static void emsgrc(int level, const char * const msg, int rc) ++{ ++ #ifdef MBEDTLS_ERROR_C ++ /* error logging convenience function that decodes mbedtls result codes */ ++ char buf[256]; ++ mbedtls_strerror(rc, buf, sizeof(buf)); ++ wpa_printf(level, "MTLS: %s: %s (-0x%04x)", msg, buf, -rc); ++ #else ++ wpa_printf(level, "MTLS: %s: (-0x%04x)", msg, -rc); ++ #endif ++} ++ ++ ++#define elog(rc, msg) emsgrc(MSG_ERROR, (msg), (rc)) ++#define ilog(rc, msg) emsgrc(MSG_INFO, (msg), (rc)) ++ ++ ++struct tls_conf * tls_conf_init(void *tls_ctx) ++{ ++ struct tls_conf *tls_conf = os_zalloc(sizeof(*tls_conf)); ++ if (tls_conf == NULL) ++ return NULL; ++ tls_conf->refcnt = 1; ++ ++ mbedtls_ssl_config_init(&tls_conf->conf); ++ mbedtls_ssl_conf_rng(&tls_conf->conf, ++ mbedtls_ctr_drbg_random, tls_ctx_global.ctr_drbg); ++ mbedtls_x509_crt_init(&tls_conf->ca_cert); ++ mbedtls_x509_crt_init(&tls_conf->client_cert); ++ mbedtls_pk_init(&tls_conf->private_key); ++ ++ return tls_conf; ++} ++ ++ ++void tls_conf_deinit(struct tls_conf *tls_conf) ++{ ++ if (tls_conf == NULL || --tls_conf->refcnt != 0) ++ return; ++ ++ mbedtls_x509_crt_free(&tls_conf->ca_cert); ++ mbedtls_x509_crt_free(&tls_conf->client_cert); ++ if (tls_conf->crl) { ++ mbedtls_x509_crl_free(tls_conf->crl); ++ os_free(tls_conf->crl); ++ } ++ mbedtls_pk_free(&tls_conf->private_key); ++ mbedtls_ssl_config_free(&tls_conf->conf); ++ os_free(tls_conf->curves); ++ os_free(tls_conf->ciphersuites); ++ os_free(tls_conf->subject_match); ++ os_free(tls_conf->altsubject_match); ++ os_free(tls_conf->suffix_match); ++ os_free(tls_conf->domain_match); ++ os_free(tls_conf->check_cert_subject); ++ os_free(tls_conf); ++} ++ ++ ++mbedtls_ctr_drbg_context * crypto_mbedtls_ctr_drbg(void); /*(not in header)*/ ++ ++__attribute_cold__ ++void * tls_init(const struct tls_config *conf) ++{ ++ /* RFE: review struct tls_config *conf (different from tls_conf) */ ++ ++ if (++tls_ctx_global.refcnt > 1) ++ return &tls_ctx_global; ++ ++ tls_ctx_global.ctr_drbg = crypto_mbedtls_ctr_drbg(); ++ #ifdef MBEDTLS_SSL_SESSION_TICKETS ++ mbedtls_ssl_ticket_init(&tls_ctx_global.ticket_ctx); ++ mbedtls_ssl_ticket_setup(&tls_ctx_global.ticket_ctx, ++ mbedtls_ctr_drbg_random, ++ tls_ctx_global.ctr_drbg, ++ MBEDTLS_CIPHER_AES_256_GCM, ++ 43200); /* ticket timeout: 12 hours */ ++ #endif ++ /* copy struct for future use */ ++ tls_ctx_global.init_conf = *conf; ++ if (conf->openssl_ciphers) ++ tls_ctx_global.init_conf.openssl_ciphers = ++ os_strdup(conf->openssl_ciphers); ++ ++ tls_ctx_global.crl_reload_interval = conf->crl_reload_interval; ++ os_get_reltime(&tls_ctx_global.crl_reload_previous); ++ ++ return &tls_ctx_global; ++} ++ ++ ++__attribute_cold__ ++void tls_deinit(void *tls_ctx) ++{ ++ if (tls_ctx == NULL || --tls_ctx_global.refcnt != 0) ++ return; ++ ++ tls_conf_deinit(tls_ctx_global.tls_conf); ++ os_free(tls_ctx_global.ca_cert_file); ++ os_free(tls_ctx_global.ocsp_stapling_response); ++ char *openssl_ciphers; /*(allocated in tls_init())*/ ++ *(const char **)&openssl_ciphers = ++ tls_ctx_global.init_conf.openssl_ciphers; ++ os_free(openssl_ciphers); ++ #ifdef MBEDTLS_SSL_SESSION_TICKETS ++ mbedtls_ssl_ticket_free(&tls_ctx_global.ticket_ctx); ++ #endif ++ os_memset(&tls_ctx_global, 0, sizeof(tls_ctx_global)); ++} ++ ++ ++int tls_get_errors(void *tls_ctx) ++{ ++ return 0; ++} ++ ++ ++static void tls_connection_deinit_expkey(struct tls_connection *conn) ++{ ++ conn->tls_prf_type = 0; /* MBEDTLS_SSL_TLS_PRF_NONE; */ ++ conn->expkey_keyblock_size = 0; ++ conn->expkey_secret_len = 0; ++ forced_memzero(conn->expkey_secret, sizeof(conn->expkey_secret)); ++ forced_memzero(conn->expkey_randbytes, sizeof(conn->expkey_randbytes)); ++} ++ ++ ++#ifdef TLS_MBEDTLS_SESSION_TICKETS ++void tls_connection_deinit_clienthello_session_ticket(struct tls_connection *conn) ++{ ++ if (conn->clienthello_session_ticket) { ++ mbedtls_platform_zeroize(conn->clienthello_session_ticket, ++ conn->clienthello_session_ticket_len); ++ mbedtls_free(conn->clienthello_session_ticket); ++ conn->clienthello_session_ticket = NULL; ++ conn->clienthello_session_ticket_len = 0; ++ } ++} ++#endif ++ ++ ++void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn) ++{ ++ if (conn == NULL) ++ return; ++ ++ #if 0 /*(good intention, but never sent since we destroy self below)*/ ++ if (conn->established) ++ mbedtls_ssl_close_notify(&conn->ssl); ++ #endif ++ ++ if (conn->tls_prf_type) ++ tls_connection_deinit_expkey(conn); ++ ++ #ifdef TLS_MBEDTLS_SESSION_TICKETS ++ if (conn->clienthello_session_ticket) ++ tls_connection_deinit_clienthello_session_ticket(conn); ++ #endif ++ ++ os_free(conn->peer_subject); ++ wpabuf_free(conn->success_data); ++ wpabuf_free(conn->push_buf); ++ wpabuf_free(conn->pull_buf); ++ mbedtls_ssl_free(&conn->ssl); ++ tls_conf_deinit(conn->tls_conf); ++ os_free(conn); ++} ++ ++ ++static void tls_mbedtls_refresh_crl(void); ++static int tls_mbedtls_ssl_setup(struct tls_connection *conn); ++ ++struct tls_connection * tls_connection_init(void *tls_ctx) ++{ ++ struct tls_connection *conn = os_zalloc(sizeof(*conn)); ++ if (conn == NULL) ++ return NULL; ++ ++ mbedtls_ssl_init(&conn->ssl); ++ ++ conn->tls_conf = tls_ctx_global.tls_conf; /*(inherit global conf, if set)*/ ++ if (conn->tls_conf) { ++ ++conn->tls_conf->refcnt; ++ /* check for CRL refresh if inheriting from global config */ ++ tls_mbedtls_refresh_crl(); ++ ++ conn->verify_peer = conn->tls_conf->verify_peer; ++ if (tls_mbedtls_ssl_setup(conn) != 0) { ++ tls_connection_deinit(&tls_ctx_global, conn); ++ return NULL; ++ } ++ } ++ ++ return conn; ++} ++ ++ ++int tls_connection_established(void *tls_ctx, struct tls_connection *conn) ++{ ++ return conn ? conn->established : 0; ++} ++ ++ ++__attribute_noinline__ ++char * tls_mbedtls_peer_serial_num(const mbedtls_x509_crt *crt, char *serial_num, size_t len) ++{ ++ /* mbedtls_x509_serial_gets() inefficiently formats to hex separated by ++ * colons, so generate the hex serial number here. The func ++ * wpa_snprintf_hex_uppercase() is similarly inefficient. */ ++ size_t i = 0; /* skip leading 0's per Distinguished Encoding Rules (DER) */ ++ while (i < crt->serial.len && crt->serial.p[i] == 0) ++i; ++ if (i == crt->serial.len) --i; ++ ++ const unsigned char *s = crt->serial.p + i; ++ const size_t e = (crt->serial.len - i) * 2; ++ if (e >= len) ++ return NULL; ++ #if 0 ++ wpa_snprintf_hex_uppercase(serial_num, len, s, crt->serial.len-i); ++ #else ++ for (i = 0; i < e; i+=2, ++s) { ++ serial_num[i+0] = "0123456789ABCDEF"[(*s >> 4)]; ++ serial_num[i+1] = "0123456789ABCDEF"[(*s & 0xF)]; ++ } ++ serial_num[e] = '\0'; ++ #endif ++ return serial_num; ++} ++ ++ ++char * tls_connection_peer_serial_num(void *tls_ctx, ++ struct tls_connection *conn) ++{ ++ const mbedtls_x509_crt *crt = mbedtls_ssl_get_peer_cert(&conn->ssl); ++ if (crt == NULL) ++ return NULL; ++ size_t len = crt->serial.len * 2 + 1; ++ char *serial_num = os_malloc(len); ++ if (!serial_num) ++ return NULL; ++ return tls_mbedtls_peer_serial_num(crt, serial_num, len); ++} ++ ++ ++static void tls_pull_buf_reset(struct tls_connection *conn); ++ ++int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn) ++{ ++ /* Note: this function called from eap_peer_tls_reauth_init() ++ * for session resumption, not for connection shutdown */ ++ ++ if (conn == NULL) ++ return -1; ++ ++ tls_pull_buf_reset(conn); ++ wpabuf_free(conn->push_buf); ++ conn->push_buf = NULL; ++ conn->established = 0; ++ conn->resumed = 0; ++ if (conn->tls_prf_type) ++ tls_connection_deinit_expkey(conn); ++ ++ /* RFE: prepare for session resumption? (see doc in crypto/tls.h) */ ++ ++ return mbedtls_ssl_session_reset(&conn->ssl); ++} ++ ++ ++static int tls_wpabuf_resize_put_data(struct wpabuf **buf, ++ const unsigned char *data, size_t dlen) ++{ ++ if (wpabuf_resize(buf, dlen) < 0) ++ return 0; ++ wpabuf_put_data(*buf, data, dlen); ++ return 1; ++} ++ ++ ++static int tls_pull_buf_append(struct tls_connection *conn, ++ const struct wpabuf *in_data) ++{ ++ /*(interface does not lend itself to move semantics)*/ ++ return tls_wpabuf_resize_put_data(&conn->pull_buf, ++ wpabuf_head(in_data), ++ wpabuf_len(in_data)); ++} ++ ++ ++static void tls_pull_buf_reset(struct tls_connection *conn) ++{ ++ /*(future: might consider reusing conn->pull_buf)*/ ++ wpabuf_free(conn->pull_buf); ++ conn->pull_buf = NULL; ++ conn->pull_buf_offset = 0; ++} ++ ++ ++__attribute_cold__ ++static void tls_pull_buf_discard(struct tls_connection *conn, const char *func) ++{ ++ size_t discard = wpabuf_len(conn->pull_buf) - conn->pull_buf_offset; ++ if (discard) ++ wpa_printf(MSG_DEBUG, ++ "%s - %zu bytes remaining in pull_buf; discarding", ++ func, discard); ++ tls_pull_buf_reset(conn); ++} ++ ++ ++static int tls_pull_func(void *ptr, unsigned char *buf, size_t len) ++{ ++ struct tls_connection *conn = (struct tls_connection *) ptr; ++ if (conn->pull_buf == NULL) ++ return MBEDTLS_ERR_SSL_WANT_READ; ++ const size_t dlen = wpabuf_len(conn->pull_buf) - conn->pull_buf_offset; ++ if (dlen == 0) ++ return MBEDTLS_ERR_SSL_WANT_READ; ++ ++ if (len > dlen) ++ len = dlen; ++ os_memcpy(buf, wpabuf_head(conn->pull_buf)+conn->pull_buf_offset, len); ++ ++ if (len == dlen) { ++ tls_pull_buf_reset(conn); ++ /*wpa_printf(MSG_DEBUG, "%s - emptied pull_buf", __func__);*/ ++ } ++ else { ++ conn->pull_buf_offset += len; ++ /*wpa_printf(MSG_DEBUG, "%s - %zu bytes remaining in pull_buf", ++ __func__, dlen - len);*/ ++ } ++ return (int)len; ++} ++ ++ ++static int tls_push_func(void *ptr, const unsigned char *buf, size_t len) ++{ ++ struct tls_connection *conn = (struct tls_connection *) ptr; ++ return tls_wpabuf_resize_put_data(&conn->push_buf, buf, len) ++ ? (int)len ++ : MBEDTLS_ERR_SSL_ALLOC_FAILED; ++} ++ ++ ++static int ++tls_mbedtls_verify_cb (void *arg, mbedtls_x509_crt *crt, int depth, uint32_t *flags); ++ ++ ++static int tls_mbedtls_ssl_setup(struct tls_connection *conn) ++{ ++ #if 0 ++ /* mbedtls_ssl_setup() must be called only once */ ++ /* If this func might be called multiple times (e.g. via set_params), ++ * then we should set a flag in conn that ssl was initialized */ ++ if (conn->ssl_is_init) { ++ mbedtls_ssl_free(&conn->ssl); ++ mbedtls_ssl_init(&conn->ssl); ++ } ++ #endif ++ ++ int ret = mbedtls_ssl_setup(&conn->ssl, &conn->tls_conf->conf); ++ if (ret != 0) { ++ elog(ret, "mbedtls_ssl_setup"); ++ return -1; ++ } ++ ++ mbedtls_ssl_set_bio(&conn->ssl, conn, tls_push_func, tls_pull_func, NULL); ++ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */ ++ mbedtls_ssl_set_export_keys_cb( ++ &conn->ssl, tls_connection_export_keys_cb, conn); ++ #elif MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */ ++ mbedtls_ssl_conf_export_keys_ext_cb( ++ &conn->tls_conf->conf, tls_connection_export_keys_cb, conn); ++ #endif ++ if (conn->verify_peer) ++ mbedtls_ssl_set_verify(&conn->ssl, tls_mbedtls_verify_cb, conn); ++ ++ return 0; ++} ++ ++ ++static int tls_mbedtls_data_is_pem(const u8 *data) ++{ ++ return (NULL != os_strstr((char *)data, "-----")); ++} ++ ++ ++static void tls_mbedtls_set_allowed_tls_vers(struct tls_conf *tls_conf, ++ mbedtls_ssl_config *conf) ++{ ++ #if !defined(MBEDTLS_SSL_PROTO_TLS1_3) ++ tls_conf->flags |= TLS_CONN_DISABLE_TLSv1_3; ++ #endif ++ ++ /* unconditionally require TLSv1.2+ for TLS_CONN_SUITEB */ ++ if (tls_conf->flags & TLS_CONN_SUITEB) { ++ tls_conf->flags |= TLS_CONN_DISABLE_TLSv1_0; ++ tls_conf->flags |= TLS_CONN_DISABLE_TLSv1_1; ++ } ++ ++ const unsigned int flags = tls_conf->flags; ++ ++ /* attempt to map flags to min and max TLS protocol version */ ++ ++ int min = (flags & TLS_CONN_DISABLE_TLSv1_0) ++ ? (flags & TLS_CONN_DISABLE_TLSv1_1) ++ ? (flags & TLS_CONN_DISABLE_TLSv1_2) ++ ? (flags & TLS_CONN_DISABLE_TLSv1_3) ++ ? 4 ++ : 3 ++ : 2 ++ : 1 ++ : 0; ++ ++ int max = (flags & TLS_CONN_DISABLE_TLSv1_3) ++ ? (flags & TLS_CONN_DISABLE_TLSv1_2) ++ ? (flags & TLS_CONN_DISABLE_TLSv1_1) ++ ? (flags & TLS_CONN_DISABLE_TLSv1_0) ++ ? -1 ++ : 0 ++ : 1 ++ : 2 ++ : 3; ++ ++ if ((flags & TLS_CONN_ENABLE_TLSv1_2) && min > 2) min = 2; ++ if ((flags & TLS_CONN_ENABLE_TLSv1_1) && min > 1) min = 1; ++ if ((flags & TLS_CONN_ENABLE_TLSv1_0) && min > 0) min = 0; ++ if (max < min) { ++ emsg(MSG_ERROR, "invalid tls_disable_tlsv* params; ignoring"); ++ return; ++ } ++ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */ ++ /* mbed TLS 3.0.0 removes support for protocols < TLSv1.2 */ ++ if (min < 2 || max < 2) { ++ emsg(MSG_ERROR, "invalid tls_disable_tlsv* params; ignoring"); ++ if (min < 2) min = 2; ++ if (max < 2) max = 2; ++ } ++ #endif ++ ++ #if MBEDTLS_VERSION_NUMBER >= 0x03020000 /* mbedtls 3.2.0 */ ++ /* MBEDTLS_SSL_VERSION_TLS1_2 = 0x0303 *//*!< (D)TLS 1.2 */ ++ /* MBEDTLS_SSL_VERSION_TLS1_3 = 0x0304 *//*!< (D)TLS 1.3 */ ++ min = (min == 2) ? MBEDTLS_SSL_VERSION_TLS1_2 : MBEDTLS_SSL_VERSION_TLS1_3; ++ max = (max == 2) ? MBEDTLS_SSL_VERSION_TLS1_2 : MBEDTLS_SSL_VERSION_TLS1_3; ++ mbedtls_ssl_conf_min_tls_version(conf, min); ++ mbedtls_ssl_conf_max_tls_version(conf, max); ++ #else ++ #ifndef MBEDTLS_SSL_MINOR_VERSION_4 ++ if (min == 3) min = 2; ++ if (max == 3) max = 2; ++ #endif ++ /* MBEDTLS_SSL_MINOR_VERSION_0 0 *//*!< SSL v3.0 */ ++ /* MBEDTLS_SSL_MINOR_VERSION_1 1 *//*!< TLS v1.0 */ ++ /* MBEDTLS_SSL_MINOR_VERSION_2 2 *//*!< TLS v1.1 */ ++ /* MBEDTLS_SSL_MINOR_VERSION_3 3 *//*!< TLS v1.2 */ ++ /* MBEDTLS_SSL_MINOR_VERSION_4 4 *//*!< TLS v1.3 */ ++ mbedtls_ssl_conf_min_version(conf, MBEDTLS_SSL_MAJOR_VERSION_3, min+1); ++ mbedtls_ssl_conf_max_version(conf, MBEDTLS_SSL_MAJOR_VERSION_3, max+1); ++ #endif ++} ++ ++ ++__attribute_noinline__ ++static int tls_mbedtls_readfile(const char *path, u8 **buf, size_t *n); ++ ++ ++static int ++tls_mbedtls_set_dhparams(struct tls_conf *tls_conf, const char *dh_file) ++{ ++ size_t len; ++ u8 *data; ++ if (tls_mbedtls_readfile(dh_file, &data, &len)) ++ return 0; ++ ++ /* parse only if DH parameters if in PEM format */ ++ if (tls_mbedtls_data_is_pem(data) ++ && NULL == os_strstr((char *)data, "-----BEGIN DH PARAMETERS-----")) { ++ if (os_strstr((char *)data, "-----BEGIN DSA PARAMETERS-----")) ++ wpa_printf(MSG_WARNING, "DSA parameters not handled (%s)", dh_file); ++ else ++ wpa_printf(MSG_WARNING, "unexpected DH param content (%s)",dh_file); ++ forced_memzero(data, len); ++ os_free(data); ++ return 0; ++ } ++ ++ /* mbedtls_dhm_parse_dhm() expects "-----BEGIN DH PARAMETERS-----" if PEM */ ++ mbedtls_dhm_context dhm; ++ mbedtls_dhm_init(&dhm); ++ int rc = mbedtls_dhm_parse_dhm(&dhm, data, len); ++ if (0 == rc) ++ rc = mbedtls_ssl_conf_dh_param_ctx(&tls_conf->conf, &dhm); ++ if (0 != rc) ++ elog(rc, dh_file); ++ mbedtls_dhm_free(&dhm); ++ ++ forced_memzero(data, len); ++ os_free(data); ++ return (0 == rc); ++} ++ ++ ++/* reference: lighttpd src/mod_mbedtls.c:mod_mbedtls_ssl_append_curve() ++ * (same author: gstrauss@gluelogic.com; same license: BSD-3-Clause) */ ++#if MBEDTLS_VERSION_NUMBER < 0x03010000 /* mbedtls 3.1.0 */ ++static int ++tls_mbedtls_append_curve (mbedtls_ecp_group_id *ids, int nids, int idsz, const mbedtls_ecp_group_id id) ++{ ++ if (1 >= idsz - (nids + 1)) { ++ emsg(MSG_ERROR, "error: too many curves during list expand"); ++ return -1; ++ } ++ ids[++nids] = id; ++ return nids; ++} ++ ++ ++static int ++tls_mbedtls_set_curves(struct tls_conf *tls_conf, const char *curvelist) ++{ ++ mbedtls_ecp_group_id ids[512]; ++ int nids = -1; ++ const int idsz = (int)(sizeof(ids)/sizeof(*ids)-1); ++ const mbedtls_ecp_curve_info * const curve_info = mbedtls_ecp_curve_list(); ++ ++ for (const char *e = curvelist-1; e; ) { ++ const char * const n = e+1; ++ e = os_strchr(n, ':'); ++ size_t len = e ? (size_t)(e - n) : os_strlen(n); ++ mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE; ++ switch (len) { ++ case 5: ++ if (0 == os_memcmp("P-521", n, 5)) ++ grp_id = MBEDTLS_ECP_DP_SECP521R1; ++ else if (0 == os_memcmp("P-384", n, 5)) ++ grp_id = MBEDTLS_ECP_DP_SECP384R1; ++ else if (0 == os_memcmp("P-256", n, 5)) ++ grp_id = MBEDTLS_ECP_DP_SECP256R1; ++ break; ++ case 6: ++ if (0 == os_memcmp("BP-521", n, 6)) ++ grp_id = MBEDTLS_ECP_DP_BP512R1; ++ else if (0 == os_memcmp("BP-384", n, 6)) ++ grp_id = MBEDTLS_ECP_DP_BP384R1; ++ else if (0 == os_memcmp("BP-256", n, 6)) ++ grp_id = MBEDTLS_ECP_DP_BP256R1; ++ break; ++ default: ++ break; ++ } ++ if (grp_id != MBEDTLS_ECP_DP_NONE) { ++ nids = tls_mbedtls_append_curve(ids, nids, idsz, grp_id); ++ if (-1 == nids) return 0; ++ continue; ++ } ++ /* similar to mbedtls_ecp_curve_info_from_name() */ ++ const mbedtls_ecp_curve_info *info; ++ for (info = curve_info; info->grp_id != MBEDTLS_ECP_DP_NONE; ++info) { ++ if (0 == os_strncmp(info->name, n, len) && info->name[len] == '\0') ++ break; ++ } ++ if (info->grp_id == MBEDTLS_ECP_DP_NONE) { ++ wpa_printf(MSG_ERROR, "MTLS: unrecognized curve: %.*s",(int)len,n); ++ return 0; ++ } ++ ++ nids = tls_mbedtls_append_curve(ids, nids, idsz, info->grp_id); ++ if (-1 == nids) return 0; ++ } ++ ++ /* mod_openssl configures "prime256v1" if curve list not specified, ++ * but mbedtls provides a list of supported curves if not explicitly set */ ++ if (-1 == nids) return 1; /* empty list; no-op */ ++ ++ ids[++nids] = MBEDTLS_ECP_DP_NONE; /* terminate list */ ++ ++nids; ++ ++ /* curves list must be persistent for lifetime of mbedtls_ssl_config */ ++ tls_conf->curves = os_malloc(nids * sizeof(mbedtls_ecp_group_id)); ++ if (tls_conf->curves == NULL) ++ return 0; ++ os_memcpy(tls_conf->curves, ids, nids * sizeof(mbedtls_ecp_group_id)); ++ ++ mbedtls_ssl_conf_curves(&tls_conf->conf, tls_conf->curves); ++ return 1; ++} ++#else ++static int ++tls_mbedtls_append_curve (uint16_t *ids, int nids, int idsz, const uint16_t id) ++{ ++ if (1 >= idsz - (nids + 1)) { ++ emsg(MSG_ERROR, "error: too many curves during list expand"); ++ return -1; ++ } ++ ids[++nids] = id; ++ return nids; ++} ++ ++ ++static int ++tls_mbedtls_set_curves(struct tls_conf *tls_conf, const char *curvelist) ++{ ++ /* TLS Supported Groups (renamed from "EC Named Curve Registry") ++ * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 ++ */ ++ uint16_t ids[512]; ++ int nids = -1; ++ const int idsz = (int)(sizeof(ids)/sizeof(*ids)-1); ++ const mbedtls_ecp_curve_info * const curve_info = mbedtls_ecp_curve_list(); ++ ++ for (const char *e = curvelist-1; e; ) { ++ const char * const n = e+1; ++ e = os_strchr(n, ':'); ++ size_t len = e ? (size_t)(e - n) : os_strlen(n); ++ uint16_t tls_id = 0; ++ switch (len) { ++ case 5: ++ if (0 == os_memcmp("P-521", n, 5)) ++ tls_id = 25; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_SECP521R1 */ ++ else if (0 == os_memcmp("P-384", n, 5)) ++ tls_id = 24; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_SECP384R1 */ ++ else if (0 == os_memcmp("P-256", n, 5)) ++ tls_id = 23; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_SECP256R1 */ ++ break; ++ case 6: ++ if (0 == os_memcmp("BP-521", n, 6)) ++ tls_id = 28; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_BP512R1 */ ++ else if (0 == os_memcmp("BP-384", n, 6)) ++ tls_id = 27; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_BP384R1 */ ++ else if (0 == os_memcmp("BP-256", n, 6)) ++ tls_id = 26; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_BP256R1 */ ++ break; ++ default: ++ break; ++ } ++ if (tls_id != 0) { ++ nids = tls_mbedtls_append_curve(ids, nids, idsz, tls_id); ++ if (-1 == nids) return 0; ++ continue; ++ } ++ /* similar to mbedtls_ecp_curve_info_from_name() */ ++ const mbedtls_ecp_curve_info *info; ++ for (info = curve_info; info->tls_id != 0; ++info) { ++ if (0 == os_strncmp(info->name, n, len) && info->name[len] == '\0') ++ break; ++ } ++ if (info->tls_id == 0) { ++ wpa_printf(MSG_ERROR, "MTLS: unrecognized curve: %.*s",(int)len,n); ++ return 0; ++ } ++ ++ nids = tls_mbedtls_append_curve(ids, nids, idsz, info->tls_id); ++ if (-1 == nids) return 0; ++ } ++ ++ /* mod_openssl configures "prime256v1" if curve list not specified, ++ * but mbedtls provides a list of supported curves if not explicitly set */ ++ if (-1 == nids) return 1; /* empty list; no-op */ ++ ++ ids[++nids] = 0; /* terminate list */ ++ ++nids; ++ ++ /* curves list must be persistent for lifetime of mbedtls_ssl_config */ ++ tls_conf->curves = os_malloc(nids * sizeof(uint16_t)); ++ if (tls_conf->curves == NULL) ++ return 0; ++ os_memcpy(tls_conf->curves, ids, nids * sizeof(uint16_t)); ++ ++ mbedtls_ssl_conf_groups(&tls_conf->conf, tls_conf->curves); ++ return 1; ++} ++#endif /* MBEDTLS_VERSION_NUMBER >= 0x03010000 */ /* mbedtls 3.1.0 */ ++ ++ ++/* data copied from lighttpd src/mod_mbedtls.c (BSD-3-Clause) */ ++static const int suite_AES_256_ephemeral[] = { ++ /* All AES-256 ephemeral suites */ ++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, ++ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, ++ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, ++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, ++ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, ++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, ++ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, ++ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, ++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, ++ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, ++ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, ++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, ++ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8 ++}; ++ ++/* data copied from lighttpd src/mod_mbedtls.c (BSD-3-Clause) */ ++static const int suite_AES_128_ephemeral[] = { ++ /* All AES-128 ephemeral suites */ ++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, ++ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, ++ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, ++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, ++ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, ++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, ++ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, ++ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, ++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, ++ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, ++ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, ++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, ++ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8 ++}; ++ ++/* data copied from lighttpd src/mod_mbedtls.c (BSD-3-Clause) */ ++/* HIGH cipher list (mapped from openssl list to mbedtls) */ ++static const int suite_HIGH[] = { ++ MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, ++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, ++ MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, ++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, ++ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, ++ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, ++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, ++ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, ++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, ++ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, ++ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, ++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, ++ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, ++ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, ++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, ++ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, ++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, ++ MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, ++ MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, ++ MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, ++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384, ++ MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384, ++ MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384, ++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, ++ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, ++ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, ++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, ++ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, ++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, ++ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, ++ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, ++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, ++ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, ++ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, ++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, ++ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, ++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, ++ MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, ++ MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, ++ MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, ++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256, ++ MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256, ++ MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256, ++ MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, ++ MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, ++ MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, ++ MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, ++ MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, ++ MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, ++ MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, ++ MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, ++ MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, ++ MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, ++ MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, ++ MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384, ++ MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, ++ MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, ++ MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, ++ MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, ++ MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, ++ MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, ++ MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, ++ MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, ++ MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, ++ MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256, ++ MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, ++ MBEDTLS_TLS_RSA_WITH_AES_256_CCM, ++ MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, ++ MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, ++ MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, ++ MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, ++ MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, ++ MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384, ++ MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, ++ MBEDTLS_TLS_RSA_WITH_AES_128_CCM, ++ MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, ++ MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, ++ MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, ++ MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, ++ MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, ++ MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256, ++ MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256, ++ MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, ++ MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, ++ MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, ++ MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, ++ MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384, ++ MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, ++ MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, ++ MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, ++ MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, ++ MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256, ++ MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, ++ MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, ++ MBEDTLS_TLS_PSK_WITH_AES_256_CCM, ++ MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, ++ MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, ++ MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, ++ MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, ++ MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384, ++ MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, ++ MBEDTLS_TLS_PSK_WITH_AES_128_CCM, ++ MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, ++ MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, ++ MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, ++ MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, ++ MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256 ++}; ++ ++ ++__attribute_noinline__ ++static int ++tls_mbedtls_append_ciphersuite (int *ids, int nids, int idsz, const int *x, int xsz) ++{ ++ if (xsz >= idsz - (nids + 1)) { ++ emsg(MSG_ERROR, "error: too many ciphers during list expand"); ++ return -1; ++ } ++ ++ for (int i = 0; i < xsz; ++i) ++ ids[++nids] = x[i]; ++ ++ return nids; ++} ++ ++ ++static int ++tls_mbedtls_translate_ciphername(int id, char *buf, size_t buflen) ++{ ++ const mbedtls_ssl_ciphersuite_t *info = ++ mbedtls_ssl_ciphersuite_from_id(id); ++ if (info == NULL) ++ return 0; ++ const char *name = mbedtls_ssl_ciphersuite_get_name(info); ++ const size_t len = os_strlen(name); ++ if (len == 7 && 0 == os_memcmp(name, "unknown", 7)) ++ return 0; ++ if (len >= buflen) ++ return 0; ++ os_strlcpy(buf, name, buflen); ++ ++ /* attempt to translate mbedtls string to openssl string ++ * (some heuristics; incomplete) */ ++ size_t i = 0, j = 0; ++ if (buf[0] == 'T') { ++ if (os_strncmp(buf, "TLS1-3-", 7) == 0) { ++ buf[3] = '-'; ++ j = 4; /* remove "1-3" from "TLS1-3-" prefix */ ++ i = 7; ++ } ++ else if (os_strncmp(buf, "TLS-", 4) == 0) ++ i = 4; /* remove "TLS-" prefix */ ++ } ++ for (; buf[i]; ++i) { ++ if (buf[i] == '-') { ++ if (i >= 3) { ++ if (0 == os_memcmp(buf+i-3, "AES", 3)) ++ continue; /* "AES-" -> "AES" */ ++ } ++ if (i >= 4) { ++ if (0 == os_memcmp(buf+i-4, "WITH", 4)) { ++ j -= 4; /* remove "WITH-" */ ++ continue; ++ } ++ } ++ } ++ buf[j++] = buf[i]; ++ } ++ buf[j] = '\0'; ++ ++ return j; ++} ++ ++ ++__attribute_noinline__ ++static int ++tls_mbedtls_set_ciphersuites(struct tls_conf *tls_conf, int *ids, int nids) ++{ ++ /* ciphersuites list must be persistent for lifetime of mbedtls_ssl_config*/ ++ os_free(tls_conf->ciphersuites); ++ tls_conf->ciphersuites = os_malloc(nids * sizeof(int)); ++ if (tls_conf->ciphersuites == NULL) ++ return 0; ++ os_memcpy(tls_conf->ciphersuites, ids, nids * sizeof(int)); ++ mbedtls_ssl_conf_ciphersuites(&tls_conf->conf, tls_conf->ciphersuites); ++ return 1; ++} ++ ++ ++static int ++tls_mbedtls_set_ciphers(struct tls_conf *tls_conf, const char *ciphers) ++{ ++ char buf[64]; ++ int ids[512]; ++ int nids = -1; ++ const int idsz = (int)(sizeof(ids)/sizeof(*ids)-1); ++ const char *next; ++ size_t blen, clen; ++ do { ++ next = os_strchr(ciphers, ':'); ++ clen = next ? (size_t)(next - ciphers) : os_strlen(ciphers); ++ if (!clen) ++ continue; ++ ++ /* special-case a select set of openssl group names for hwsim tests */ ++ /* (review; remove excess code if tests are not run for non-OpenSSL?) */ ++ if (clen == 9 && os_memcmp(ciphers, "SUITEB192", 9) == 0) { ++ static int ssl_preset_suiteb192_ciphersuites[] = { ++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, ++ 0 ++ }; ++ return tls_mbedtls_set_ciphersuites(tls_conf, ++ ssl_preset_suiteb192_ciphersuites, ++ 2); ++ } ++ if (clen == 9 && os_memcmp(ciphers, "SUITEB128", 9) == 0) { ++ static int ssl_preset_suiteb128_ciphersuites[] = { ++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, ++ 0 ++ }; ++ return tls_mbedtls_set_ciphersuites(tls_conf, ++ ssl_preset_suiteb128_ciphersuites, ++ 2); ++ } ++ if (clen == 7 && os_memcmp(ciphers, "DEFAULT", 7) == 0) ++ continue; ++ if (clen == 6 && os_memcmp(ciphers, "AES128", 6) == 0) { ++ nids = tls_mbedtls_append_ciphersuite(ids, nids, idsz, ++ suite_AES_128_ephemeral, ++ (int)ARRAY_SIZE(suite_AES_128_ephemeral)); ++ if (nids == -1) ++ return 0; ++ continue; ++ } ++ if (clen == 6 && os_memcmp(ciphers, "AES256", 6) == 0) { ++ nids = tls_mbedtls_append_ciphersuite(ids, nids, idsz, ++ suite_AES_256_ephemeral, ++ (int)ARRAY_SIZE(suite_AES_256_ephemeral)); ++ if (nids == -1) ++ return 0; ++ continue; ++ } ++ if (clen == 4 && os_memcmp(ciphers, "HIGH", 4) == 0) { ++ nids = tls_mbedtls_append_ciphersuite(ids, nids, idsz, suite_HIGH, ++ (int)ARRAY_SIZE(suite_HIGH)); ++ if (nids == -1) ++ return 0; ++ continue; ++ } ++ /* ignore anonymous cipher group names (?not supported by mbedtls?) */ ++ if (clen == 4 && os_memcmp(ciphers, "!ADH", 4) == 0) ++ continue; ++ if (clen == 6 && os_memcmp(ciphers, "-aECDH", 6) == 0) ++ continue; ++ if (clen == 7 && os_memcmp(ciphers, "-aECDSA", 7) == 0) ++ continue; ++ ++ /* attempt to match mbedtls cipher names ++ * nb: does not support openssl group names or list manipulation syntax ++ * (alt: could copy almost 1200 lines (!!!) of lighttpd mod_mbedtls.c ++ * mod_mbedtls_ssl_conf_ciphersuites() to translate strings) ++ * note: not efficient to rewrite list for each ciphers entry, ++ * but this code is expected to run only at startup ++ */ ++ const int *list = mbedtls_ssl_list_ciphersuites(); ++ for (; *list; ++list) { ++ blen = tls_mbedtls_translate_ciphername(*list,buf,sizeof(buf)); ++ if (!blen) ++ continue; ++ ++ /* matching heuristics additional to translate_ciphername above */ ++ if (blen == clen+4) { ++ char *cbc = os_strstr(buf, "CBC-"); ++ if (cbc) { ++ os_memmove(cbc, cbc+4, blen-(cbc+4-buf)+1); /*(w/ '\0')*/ ++ blen -= 4; ++ } ++ } ++ if (blen >= clen && os_memcmp(ciphers, buf, clen) == 0 ++ && (blen == clen ++ || (blen == clen+7 && os_memcmp(buf+clen, "-SHA256", 7)))) { ++ if (1 >= idsz - (nids + 1)) { ++ emsg(MSG_ERROR, ++ "error: too many ciphers during list expand"); ++ return 0; ++ } ++ ids[++nids] = *list; ++ break; ++ } ++ } ++ if (*list == 0) { ++ wpa_printf(MSG_ERROR, ++ "MTLS: unrecognized cipher: %.*s", (int)clen, ciphers); ++ return 0; ++ } ++ } while ((ciphers = next ? next+1 : NULL)); ++ ++ if (-1 == nids) return 1; /* empty list; no-op */ ++ ++ ids[++nids] = 0; /* terminate list */ ++ ++nids; ++ ++ return tls_mbedtls_set_ciphersuites(tls_conf, ids, nids); ++} ++ ++ ++__attribute_noinline__ ++static int tls_mbedtls_set_item(char **config_item, const char *item) ++{ ++ os_free(*config_item); ++ *config_item = NULL; ++ return item ? (*config_item = os_strdup(item)) != NULL : 1; ++} ++ ++ ++static int tls_connection_set_subject_match(struct tls_conf *tls_conf, ++ const struct tls_connection_params *params) ++{ ++ int rc = 1; ++ rc &= tls_mbedtls_set_item(&tls_conf->subject_match, ++ params->subject_match); ++ rc &= tls_mbedtls_set_item(&tls_conf->altsubject_match, ++ params->altsubject_match); ++ rc &= tls_mbedtls_set_item(&tls_conf->suffix_match, ++ params->suffix_match); ++ rc &= tls_mbedtls_set_item(&tls_conf->domain_match, ++ params->domain_match); ++ rc &= tls_mbedtls_set_item(&tls_conf->check_cert_subject, ++ params->check_cert_subject); ++ return rc; ++} ++ ++ ++/* duplicated in crypto_mbedtls.c:crypto_mbedtls_readfile()*/ ++__attribute_noinline__ ++static int tls_mbedtls_readfile(const char *path, u8 **buf, size_t *n) ++{ ++ #if 0 /* #ifdef MBEDTLS_FS_IO */ ++ /*(includes +1 for '\0' needed by mbedtls PEM parsing funcs)*/ ++ if (mbedtls_pk_load_file(path, (unsigned char **)buf, n) != 0) { ++ wpa_printf(MSG_ERROR, "error: mbedtls_pk_load_file %s", path); ++ return -1; ++ } ++ #else ++ /*(use os_readfile() so that we can use os_free() ++ *(if we use mbedtls_pk_load_file() above, macros prevent calling free() ++ * directly #if defined(OS_REJECT_C_LIB_FUNCTIONS) and calling os_free() ++ * on buf aborts in tests if buf not allocated via os_malloc())*/ ++ *buf = (u8 *)os_readfile(path, n); ++ if (!*buf) { ++ wpa_printf(MSG_ERROR, "error: os_readfile %s", path); ++ return -1; ++ } ++ u8 *buf0 = os_realloc(*buf, *n+1); ++ if (!buf0) { ++ bin_clear_free(*buf, *n); ++ *buf = NULL; ++ return -1; ++ } ++ buf0[(*n)++] = '\0'; ++ *buf = buf0; ++ #endif ++ return 0; ++} ++ ++ ++static int tls_mbedtls_set_crl(struct tls_conf *tls_conf, const u8 *data, size_t len) ++{ ++ /* do not use mbedtls_x509_crl_parse() on PEM unless it contains CRL */ ++ if (len && data[len-1] == '\0' ++ && NULL == os_strstr((const char *)data,"-----BEGIN X509 CRL-----") ++ && tls_mbedtls_data_is_pem(data)) ++ return 0; ++ ++ mbedtls_x509_crl crl; ++ mbedtls_x509_crl_init(&crl); ++ int rc = mbedtls_x509_crl_parse(&crl, data, len); ++ if (rc < 0) { ++ mbedtls_x509_crl_free(&crl); ++ return rc == MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ? 0 : rc; ++ } ++ ++ mbedtls_x509_crl *crl_new = os_malloc(sizeof(crl)); ++ if (crl_new == NULL) { ++ mbedtls_x509_crl_free(&crl); ++ return MBEDTLS_ERR_X509_ALLOC_FAILED; ++ } ++ os_memcpy(crl_new, &crl, sizeof(crl)); ++ ++ mbedtls_x509_crl *crl_old = tls_conf->crl; ++ tls_conf->crl = crl_new; ++ if (crl_old) { ++ mbedtls_x509_crl_free(crl_old); ++ os_free(crl_old); ++ } ++ return 0; ++} ++ ++ ++static int tls_mbedtls_set_ca(struct tls_conf *tls_conf, u8 *data, size_t len) ++{ ++ /* load crt struct onto stack and then copy into tls_conf in ++ * order to preserve existing tls_conf value if error occurs ++ * ++ * hostapd is not threaded, or else should allocate memory and swap in ++ * pointer reduce race condition. (If threaded, would also need to ++ * keep reference count of use to avoid freeing while still in use.) */ ++ ++ mbedtls_x509_crt crt; ++ mbedtls_x509_crt_init(&crt); ++ int rc = mbedtls_x509_crt_parse(&crt, data, len); ++ if (rc < 0) { ++ mbedtls_x509_crt_free(&crt); ++ return rc; ++ } ++ ++ mbedtls_x509_crt_free(&tls_conf->ca_cert); ++ os_memcpy(&tls_conf->ca_cert, &crt, sizeof(crt)); ++ return 0; ++} ++ ++ ++static int tls_mbedtls_set_ca_and_crl(struct tls_conf *tls_conf, const char *ca_cert_file) ++{ ++ size_t len; ++ u8 *data; ++ if (tls_mbedtls_readfile(ca_cert_file, &data, &len)) ++ return -1; ++ ++ int rc; ++ if (0 == (rc = tls_mbedtls_set_ca(tls_conf, data, len)) ++ && (!tls_mbedtls_data_is_pem(data) /*skip parse for CRL if not PEM*/ ++ || 0 == (rc = tls_mbedtls_set_crl(tls_conf, data, len)))) { ++ mbedtls_ssl_conf_ca_chain(&tls_conf->conf, ++ &tls_conf->ca_cert, ++ tls_conf->crl); ++ } ++ else { ++ elog(rc, __func__); ++ emsg(MSG_ERROR, ca_cert_file); ++ } ++ ++ forced_memzero(data, len); ++ os_free(data); ++ return rc; ++} ++ ++ ++static void tls_mbedtls_refresh_crl(void) ++{ ++ /* check for CRL refresh ++ * continue even if error occurs; continue with previous cert, CRL */ ++ unsigned int crl_reload_interval = tls_ctx_global.crl_reload_interval; ++ const char *ca_cert_file = tls_ctx_global.ca_cert_file; ++ if (!crl_reload_interval || !ca_cert_file) ++ return; ++ ++ struct os_reltime *previous = &tls_ctx_global.crl_reload_previous; ++ struct os_reltime now; ++ if (os_get_reltime(&now) != 0 ++ || !os_reltime_expired(&now, previous, crl_reload_interval)) ++ return; ++ ++ /* Note: modifying global state is not thread-safe ++ * if in use by existing connections ++ * ++ * src/utils/os.h does not provide a portable stat() ++ * or else it would be a good idea to check mtime and size, ++ * and avoid reloading if file has not changed */ ++ ++ if (tls_mbedtls_set_ca_and_crl(tls_ctx_global.tls_conf, ca_cert_file) == 0) ++ *previous = now; ++} ++ ++ ++static int tls_mbedtls_set_ca_cert(struct tls_conf *tls_conf, ++ const struct tls_connection_params *params) ++{ ++ if (params->ca_cert) { ++ if (os_strncmp(params->ca_cert, "probe://", 8) == 0) { ++ tls_conf->ca_cert_probe = 1; ++ tls_conf->has_ca_cert = 1; ++ return 0; ++ } ++ ++ if (os_strncmp(params->ca_cert, "hash://", 7) == 0) { ++ const char *pos = params->ca_cert + 7; ++ if (os_strncmp(pos, "server/sha256/", 14) != 0) { ++ emsg(MSG_ERROR, "unsupported ca_cert hash value"); ++ return -1; ++ } ++ pos += 14; ++ if (os_strlen(pos) != SHA256_DIGEST_LENGTH*2) { ++ emsg(MSG_ERROR, "unexpected ca_cert hash length"); ++ return -1; ++ } ++ if (hexstr2bin(pos, tls_conf->ca_cert_hash, ++ SHA256_DIGEST_LENGTH) < 0) { ++ emsg(MSG_ERROR, "invalid ca_cert hash value"); ++ return -1; ++ } ++ emsg(MSG_DEBUG, "checking only server certificate match"); ++ tls_conf->verify_depth0_only = 1; ++ tls_conf->has_ca_cert = 1; ++ return 0; ++ } ++ ++ if (tls_mbedtls_set_ca_and_crl(tls_conf, params->ca_cert) != 0) ++ return -1; ++ } ++ if (params->ca_cert_blob) { ++ size_t len = params->ca_cert_blob_len; ++ int is_pem = tls_mbedtls_data_is_pem(params->ca_cert_blob); ++ if (len && params->ca_cert_blob[len-1] != '\0' && is_pem) ++ ++len; /*(include '\0' in len for PEM)*/ ++ int ret = mbedtls_x509_crt_parse(&tls_conf->ca_cert, ++ params->ca_cert_blob, len); ++ if (ret != 0) { ++ elog(ret, "mbedtls_x509_crt_parse"); ++ return -1; ++ } ++ if (is_pem) { /*(ca_cert_blob in DER format contains ca cert only)*/ ++ ret = tls_mbedtls_set_crl(tls_conf, params->ca_cert_blob, len); ++ if (ret != 0) { ++ elog(ret, "mbedtls_x509_crl_parse"); ++ return -1; ++ } ++ } ++ } ++ ++ if (mbedtls_x509_time_is_future(&tls_conf->ca_cert.valid_from) ++ || mbedtls_x509_time_is_past(&tls_conf->ca_cert.valid_to)) { ++ emsg(MSG_WARNING, "ca_cert expired or not yet valid"); ++ if (params->ca_cert) ++ emsg(MSG_WARNING, params->ca_cert); ++ } ++ ++ tls_conf->has_ca_cert = 1; ++ return 0; ++} ++ ++ ++static int tls_mbedtls_set_certs(struct tls_conf *tls_conf, ++ const struct tls_connection_params *params) ++{ ++ int ret; ++ ++ if (params->ca_cert || params->ca_cert_blob) { ++ if (tls_mbedtls_set_ca_cert(tls_conf, params) != 0) ++ return -1; ++ } ++ else if (params->ca_path) { ++ emsg(MSG_INFO, "ca_path support not implemented"); ++ return -1; ++ } ++ ++ if (!tls_conf->has_ca_cert) ++ mbedtls_ssl_conf_authmode(&tls_conf->conf, MBEDTLS_SSL_VERIFY_NONE); ++ else { ++ /* Initial setting: REQUIRED for client, OPTIONAL for server ++ * (see also tls_connection_set_verify()) */ ++ tls_conf->verify_peer = (tls_ctx_global.tls_conf == NULL); ++ int authmode = tls_conf->verify_peer ++ ? MBEDTLS_SSL_VERIFY_REQUIRED ++ : MBEDTLS_SSL_VERIFY_OPTIONAL; ++ mbedtls_ssl_conf_authmode(&tls_conf->conf, authmode); ++ mbedtls_ssl_conf_ca_chain(&tls_conf->conf, ++ &tls_conf->ca_cert, ++ tls_conf->crl); ++ ++ if (!tls_connection_set_subject_match(tls_conf, params)) ++ return -1; ++ } ++ ++ if (params->client_cert2) /*(yes, server_cert2 in msg below)*/ ++ emsg(MSG_INFO, "server_cert2 support not implemented"); ++ ++ if (params->client_cert) { ++ size_t len; ++ u8 *data; ++ if (tls_mbedtls_readfile(params->client_cert, &data, &len)) ++ return -1; ++ ret = mbedtls_x509_crt_parse(&tls_conf->client_cert, data, len); ++ forced_memzero(data, len); ++ os_free(data); ++ } ++ if (params->client_cert_blob) { ++ size_t len = params->client_cert_blob_len; ++ if (len && params->client_cert_blob[len-1] != '\0' ++ && tls_mbedtls_data_is_pem(params->client_cert_blob)) ++ ++len; /*(include '\0' in len for PEM)*/ ++ ret = mbedtls_x509_crt_parse(&tls_conf->client_cert, ++ params->client_cert_blob, len); ++ } ++ if (params->client_cert || params->client_cert_blob) { ++ if (ret < 0) { ++ elog(ret, "mbedtls_x509_crt_parse"); ++ if (params->client_cert) ++ emsg(MSG_ERROR, params->client_cert); ++ return -1; ++ } ++ if (mbedtls_x509_time_is_future(&tls_conf->client_cert.valid_from) ++ || mbedtls_x509_time_is_past(&tls_conf->client_cert.valid_to)) { ++ emsg(MSG_WARNING, "cert expired or not yet valid"); ++ if (params->client_cert) ++ emsg(MSG_WARNING, params->client_cert); ++ } ++ tls_conf->has_client_cert = 1; ++ } ++ ++ if (params->private_key || params->private_key_blob) { ++ size_t len = params->private_key_blob_len; ++ u8 *data; ++ *(const u8 **)&data = params->private_key_blob; ++ if (len && data[len-1] != '\0' && tls_mbedtls_data_is_pem(data)) ++ ++len; /*(include '\0' in len for PEM)*/ ++ if (params->private_key ++ && tls_mbedtls_readfile(params->private_key, &data, &len)) { ++ return -1; ++ } ++ const char *pwd = params->private_key_passwd; ++ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */ ++ ret = mbedtls_pk_parse_key(&tls_conf->private_key, ++ data, len, ++ (const unsigned char *)pwd, ++ pwd ? os_strlen(pwd) : 0, ++ mbedtls_ctr_drbg_random, ++ tls_ctx_global.ctr_drbg); ++ #else ++ ret = mbedtls_pk_parse_key(&tls_conf->private_key, ++ data, len, ++ (const unsigned char *)pwd, ++ pwd ? os_strlen(pwd) : 0); ++ #endif ++ if (params->private_key) { ++ forced_memzero(data, len); ++ os_free(data); ++ } ++ if (ret < 0) { ++ elog(ret, "mbedtls_pk_parse_key"); ++ return -1; ++ } ++ tls_conf->has_private_key = 1; ++ } ++ ++ if (tls_conf->has_client_cert && tls_conf->has_private_key) { ++ ret = mbedtls_ssl_conf_own_cert( ++ &tls_conf->conf, &tls_conf->client_cert, &tls_conf->private_key); ++ if (ret < 0) { ++ elog(ret, "mbedtls_ssl_conf_own_cert"); ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++ ++ ++/* mbedtls_x509_crt_profile_suiteb plus rsa_min_bitlen 2048 */ ++/* (reference: see also mbedtls_x509_crt_profile_next) */ ++/* ??? should permit SHA-512, too, and additional curves ??? */ ++static const mbedtls_x509_crt_profile tls_mbedtls_crt_profile_suiteb128 = ++{ ++ /* Only SHA-256 and 384 */ ++ MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | ++ MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ), ++ /* Only ECDSA */ ++ MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ) | ++ MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECKEY ), ++#if defined(MBEDTLS_ECP_C) ++ /* Only NIST P-256 and P-384 */ ++ MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) | ++ MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ), ++#else ++ 0, ++#endif ++ 2048, ++}; ++ ++ ++/* stricter than mbedtls_x509_crt_profile_suiteb */ ++/* (reference: see also mbedtls_x509_crt_profile_next) */ ++/* ??? should permit SHA-512, too, and additional curves ??? */ ++static const mbedtls_x509_crt_profile tls_mbedtls_crt_profile_suiteb192 = ++{ ++ /* Only SHA-384 */ ++ MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ), ++ /* Only ECDSA */ ++ MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ) | ++ MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECKEY ), ++#if defined(MBEDTLS_ECP_C) ++ /* Only NIST P-384 */ ++ MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ), ++#else ++ 0, ++#endif ++ 3072, ++}; ++ ++ ++/* stricter than mbedtls_x509_crt_profile_suiteb except allow any PK alg */ ++/* (reference: see also mbedtls_x509_crt_profile_next) */ ++/* ??? should permit SHA-512, too, and additional curves ??? */ ++static const mbedtls_x509_crt_profile tls_mbedtls_crt_profile_suiteb192_anypk = ++{ ++ /* Only SHA-384 */ ++ MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ), ++ 0xFFFFFFF, /* Any PK alg */ ++#if defined(MBEDTLS_ECP_C) ++ /* Only NIST P-384 */ ++ MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ), ++#else ++ 0, ++#endif ++ 3072, ++}; ++ ++ ++static int tls_mbedtls_set_params(struct tls_conf *tls_conf, ++ const struct tls_connection_params *params) ++{ ++ tls_conf->flags = params->flags; ++ ++ if (tls_conf->flags & TLS_CONN_REQUIRE_OCSP_ALL) { ++ emsg(MSG_INFO, "ocsp=3 not supported"); ++ return -1; ++ } ++ ++ if (tls_conf->flags & TLS_CONN_REQUIRE_OCSP) { ++ emsg(MSG_INFO, "ocsp not supported"); ++ return -1; ++ } ++ ++ int suiteb128 = 0; ++ int suiteb192 = 0; ++ if (params->openssl_ciphers) { ++ if (os_strcmp(params->openssl_ciphers, "SUITEB192") == 0) { ++ suiteb192 = 1; ++ tls_conf->flags |= TLS_CONN_SUITEB; ++ } ++ if (os_strcmp(params->openssl_ciphers, "SUITEB128") == 0) { ++ suiteb128 = 1; ++ tls_conf->flags |= TLS_CONN_SUITEB; ++ } ++ } ++ ++ int ret = mbedtls_ssl_config_defaults( ++ &tls_conf->conf, tls_ctx_global.tls_conf ? MBEDTLS_SSL_IS_SERVER ++ : MBEDTLS_SSL_IS_CLIENT, ++ MBEDTLS_SSL_TRANSPORT_STREAM, ++ (tls_conf->flags & TLS_CONN_SUITEB) ? MBEDTLS_SSL_PRESET_SUITEB ++ : MBEDTLS_SSL_PRESET_DEFAULT); ++ if (ret != 0) { ++ elog(ret, "mbedtls_ssl_config_defaults"); ++ return -1; ++ } ++ ++ if (suiteb128) { ++ mbedtls_ssl_conf_cert_profile(&tls_conf->conf, ++ &tls_mbedtls_crt_profile_suiteb128); ++ mbedtls_ssl_conf_dhm_min_bitlen(&tls_conf->conf, 2048); ++ } ++ else if (suiteb192) { ++ mbedtls_ssl_conf_cert_profile(&tls_conf->conf, ++ &tls_mbedtls_crt_profile_suiteb192); ++ mbedtls_ssl_conf_dhm_min_bitlen(&tls_conf->conf, 3072); ++ } ++ else if (tls_conf->flags & TLS_CONN_SUITEB) { ++ /* treat as suiteb192 while allowing any PK algorithm */ ++ mbedtls_ssl_conf_cert_profile(&tls_conf->conf, ++ &tls_mbedtls_crt_profile_suiteb192_anypk); ++ mbedtls_ssl_conf_dhm_min_bitlen(&tls_conf->conf, 3072); ++ } ++ ++ tls_mbedtls_set_allowed_tls_vers(tls_conf, &tls_conf->conf); ++ ret = tls_mbedtls_set_certs(tls_conf, params); ++ if (ret != 0) ++ return -1; ++ ++ if (params->dh_file ++ && !tls_mbedtls_set_dhparams(tls_conf, params->dh_file)) { ++ return -1; ++ } ++ ++ if (params->openssl_ecdh_curves ++ && !tls_mbedtls_set_curves(tls_conf, params->openssl_ecdh_curves)) { ++ return -1; ++ } ++ ++ if (params->openssl_ciphers) { ++ if (!tls_mbedtls_set_ciphers(tls_conf, params->openssl_ciphers)) ++ return -1; ++ } ++ else if (tls_conf->flags & TLS_CONN_SUITEB) { ++ /* special-case a select set of ciphers for hwsim tests */ ++ if (!tls_mbedtls_set_ciphers(tls_conf, ++ (tls_conf->flags & TLS_CONN_SUITEB_NO_ECDH) ++ ? "DHE-RSA-AES256-GCM-SHA384" ++ : "ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384")) ++ return -1; ++ } ++ ++ return 0; ++} ++ ++ ++int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, ++ const struct tls_connection_params *params) ++{ ++ if (conn == NULL || params == NULL) ++ return -1; ++ ++ tls_conf_deinit(conn->tls_conf); ++ struct tls_conf *tls_conf = conn->tls_conf = tls_conf_init(tls_ctx); ++ if (tls_conf == NULL) ++ return -1; ++ ++ if (tls_ctx_global.tls_conf) { ++ tls_conf->check_crl = tls_ctx_global.tls_conf->check_crl; ++ tls_conf->check_crl_strict = tls_ctx_global.tls_conf->check_crl_strict; ++ /*(tls_openssl.c inherits check_cert_subject from global conf)*/ ++ if (tls_ctx_global.tls_conf->check_cert_subject) { ++ tls_conf->check_cert_subject = ++ os_strdup(tls_ctx_global.tls_conf->check_cert_subject); ++ if (tls_conf->check_cert_subject == NULL) ++ return -1; ++ } ++ } ++ ++ if (tls_mbedtls_set_params(tls_conf, params) != 0) ++ return -1; ++ conn->verify_peer = tls_conf->verify_peer; ++ ++ return tls_mbedtls_ssl_setup(conn); ++} ++ ++ ++#ifdef TLS_MBEDTLS_SESSION_TICKETS ++ ++static int tls_mbedtls_clienthello_session_ticket_prep (struct tls_connection *conn, ++ const u8 *data, size_t len) ++{ ++ if (conn->tls_conf->flags & TLS_CONN_DISABLE_SESSION_TICKET) ++ return -1; ++ if (conn->clienthello_session_ticket) ++ tls_connection_deinit_clienthello_session_ticket(conn); ++ if (len) { ++ conn->clienthello_session_ticket = mbedtls_calloc(1, len); ++ if (conn->clienthello_session_ticket == NULL) ++ return -1; ++ conn->clienthello_session_ticket_len = len; ++ os_memcpy(conn->clienthello_session_ticket, data, len); ++ } ++ return 0; ++} ++ ++ ++static void tls_mbedtls_clienthello_session_ticket_set (struct tls_connection *conn) ++{ ++ mbedtls_ssl_session *sess = conn->ssl.MBEDTLS_PRIVATE(session_negotiate); ++ if (sess->MBEDTLS_PRIVATE(ticket)) { ++ mbedtls_platform_zeroize(sess->MBEDTLS_PRIVATE(ticket), ++ sess->MBEDTLS_PRIVATE(ticket_len)); ++ mbedtls_free(sess->MBEDTLS_PRIVATE(ticket)); ++ } ++ sess->MBEDTLS_PRIVATE(ticket) = conn->clienthello_session_ticket; ++ sess->MBEDTLS_PRIVATE(ticket_len) = conn->clienthello_session_ticket_len; ++ sess->MBEDTLS_PRIVATE(ticket_lifetime) = 86400;/* XXX: can hint be 0? */ ++ ++ conn->clienthello_session_ticket = NULL; ++ conn->clienthello_session_ticket_len = 0; ++} ++ ++ ++static int tls_mbedtls_ssl_ticket_write(void *p_ticket, ++ const mbedtls_ssl_session *session, ++ unsigned char *start, ++ const unsigned char *end, ++ size_t *tlen, ++ uint32_t *lifetime) ++{ ++ struct tls_connection *conn = p_ticket; ++ if (conn && conn->session_ticket_cb) { ++ /* see tls_mbedtls_clienthello_session_ticket_prep() */ ++ /* see tls_mbedtls_clienthello_session_ticket_set() */ ++ return 0; ++ } ++ ++ return mbedtls_ssl_ticket_write(&tls_ctx_global.ticket_ctx, ++ session, start, end, tlen, lifetime); ++} ++ ++ ++static int tls_mbedtls_ssl_ticket_parse(void *p_ticket, ++ mbedtls_ssl_session *session, ++ unsigned char *buf, ++ size_t len) ++{ ++ /* XXX: TODO: not implemented in client; ++ * mbedtls_ssl_conf_session_tickets_cb() callbacks only for TLS server*/ ++ ++ if (len == 0) ++ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; ++ ++ struct tls_connection *conn = p_ticket; ++ if (conn && conn->session_ticket_cb) { ++ /* XXX: have random and secret been initialized yet? ++ * or must keys first be exported? ++ * EAP-FAST uses all args, EAP-TEAP only uses secret */ ++ struct tls_random data; ++ if (tls_connection_get_random(NULL, conn, &data) != 0) ++ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; ++ int ret = ++ conn->session_ticket_cb(conn->session_ticket_cb_ctx, ++ buf, len, ++ data.client_random, ++ data.server_random, ++ conn->expkey_secret); ++ if (ret == 1) { ++ conn->resumed = 1; ++ return 0; ++ } ++ emsg(MSG_ERROR, "EAP session ticket ext not implemented"); ++ return MBEDTLS_ERR_SSL_INVALID_MAC; ++ /*(non-zero return used for mbedtls debug logging)*/ ++ } ++ ++ /* XXX: TODO always use tls_mbedtls_ssl_ticket_parse() for callback? */ ++ int rc = mbedtls_ssl_ticket_parse(&tls_ctx_global.ticket_ctx, ++ session, buf, len); ++ if (conn) ++ conn->resumed = (rc == 0); ++ return rc; ++} ++ ++#endif /* TLS_MBEDTLS_SESSION_TICKETS */ ++ ++ ++__attribute_cold__ ++int tls_global_set_params(void *tls_ctx, ++ const struct tls_connection_params *params) ++{ ++ /* XXX: why might global_set_params be called more than once? */ ++ if (tls_ctx_global.tls_conf) ++ tls_conf_deinit(tls_ctx_global.tls_conf); ++ tls_ctx_global.tls_conf = tls_conf_init(tls_ctx); ++ if (tls_ctx_global.tls_conf == NULL) ++ return -1; ++ ++ #ifdef MBEDTLS_SSL_SESSION_TICKETS ++ #ifdef MBEDTLS_SSL_TICKET_C ++ if (!(params->flags & TLS_CONN_DISABLE_SESSION_TICKET)) ++ #ifdef TLS_MBEDTLS_SESSION_TICKETS ++ mbedtls_ssl_conf_session_tickets_cb(&tls_ctx_global.tls_conf->conf, ++ tls_mbedtls_ssl_ticket_write, ++ tls_mbedtls_ssl_ticket_parse, ++ NULL); ++ #else ++ mbedtls_ssl_conf_session_tickets_cb(&tls_ctx_global.tls_conf->conf, ++ mbedtls_ssl_ticket_write, ++ mbedtls_ssl_ticket_parse, ++ &tls_ctx_global.ticket_ctx); ++ #endif ++ #endif ++ #endif ++ ++ os_free(tls_ctx_global.ocsp_stapling_response); ++ tls_ctx_global.ocsp_stapling_response = NULL; ++ if (params->ocsp_stapling_response) ++ tls_ctx_global.ocsp_stapling_response = ++ os_strdup(params->ocsp_stapling_response); ++ ++ os_free(tls_ctx_global.ca_cert_file); ++ tls_ctx_global.ca_cert_file = NULL; ++ if (params->ca_cert) ++ tls_ctx_global.ca_cert_file = os_strdup(params->ca_cert); ++ return tls_mbedtls_set_params(tls_ctx_global.tls_conf, params); ++} ++ ++ ++int tls_global_set_verify(void *tls_ctx, int check_crl, int strict) ++{ ++ tls_ctx_global.tls_conf->check_crl = check_crl; ++ tls_ctx_global.tls_conf->check_crl_strict = strict; /*(time checks)*/ ++ return 0; ++} ++ ++ ++int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn, ++ int verify_peer, unsigned int flags, ++ const u8 *session_ctx, size_t session_ctx_len) ++{ ++ /*(EAP server-side calls this from eap_server_tls_ssl_init())*/ ++ if (conn == NULL) ++ return -1; ++ ++ conn->tls_conf->flags |= flags;/* TODO: reprocess flags, if necessary */ ++ ++ int authmode; ++ switch (verify_peer) { ++ case 2: authmode = MBEDTLS_SSL_VERIFY_OPTIONAL; break;/*(eap_teap_init())*/ ++ case 1: authmode = MBEDTLS_SSL_VERIFY_REQUIRED; break; ++ default: authmode = MBEDTLS_SSL_VERIFY_NONE; break; ++ } ++ mbedtls_ssl_set_hs_authmode(&conn->ssl, authmode); ++ ++ if ((conn->verify_peer = (authmode != MBEDTLS_SSL_VERIFY_NONE))) ++ mbedtls_ssl_set_verify(&conn->ssl, tls_mbedtls_verify_cb, conn); ++ else ++ mbedtls_ssl_set_verify(&conn->ssl, NULL, NULL); ++ ++ return 0; ++} ++ ++ ++#if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */ ++static void tls_connection_export_keys_cb( ++ void *p_expkey, mbedtls_ssl_key_export_type secret_type, ++ const unsigned char *secret, size_t secret_len, ++ const unsigned char client_random[MBEDTLS_EXPKEY_RAND_LEN], ++ const unsigned char server_random[MBEDTLS_EXPKEY_RAND_LEN], ++ mbedtls_tls_prf_types tls_prf_type) ++{ ++ struct tls_connection *conn = p_expkey; ++ conn->tls_prf_type = tls_prf_type; ++ if (!tls_prf_type) ++ return; ++ if (secret_len > sizeof(conn->expkey_secret)) { ++ emsg(MSG_ERROR, "tls_connection_export_keys_cb secret too long"); ++ conn->tls_prf_type = MBEDTLS_SSL_TLS_PRF_NONE; /* 0 */ ++ return; ++ } ++ conn->expkey_secret_len = secret_len; ++ os_memcpy(conn->expkey_secret, secret, secret_len); ++ os_memcpy(conn->expkey_randbytes, ++ client_random, MBEDTLS_EXPKEY_RAND_LEN); ++ os_memcpy(conn->expkey_randbytes + MBEDTLS_EXPKEY_RAND_LEN, ++ server_random, MBEDTLS_EXPKEY_RAND_LEN); ++} ++#elif MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */ ++static int tls_connection_export_keys_cb( ++ void *p_expkey, ++ const unsigned char *ms, ++ const unsigned char *kb, ++ size_t maclen, ++ size_t keylen, ++ size_t ivlen, ++ const unsigned char client_random[MBEDTLS_EXPKEY_RAND_LEN], ++ const unsigned char server_random[MBEDTLS_EXPKEY_RAND_LEN], ++ mbedtls_tls_prf_types tls_prf_type ) ++{ ++ struct tls_connection *conn = p_expkey; ++ conn->tls_prf_type = tls_prf_type; ++ if (!tls_prf_type) ++ return -1; /*(return value ignored by mbedtls)*/ ++ conn->expkey_keyblock_size = maclen + keylen + ivlen; ++ conn->expkey_secret_len = MBEDTLS_EXPKEY_FIXED_SECRET_LEN; ++ os_memcpy(conn->expkey_secret, ms, MBEDTLS_EXPKEY_FIXED_SECRET_LEN); ++ os_memcpy(conn->expkey_randbytes, ++ client_random, MBEDTLS_EXPKEY_RAND_LEN); ++ os_memcpy(conn->expkey_randbytes + MBEDTLS_EXPKEY_RAND_LEN, ++ server_random, MBEDTLS_EXPKEY_RAND_LEN); ++ return 0; ++} ++#endif ++ ++ ++int tls_connection_get_random(void *tls_ctx, struct tls_connection *conn, ++ struct tls_random *data) ++{ ++ if (!conn || !conn->tls_prf_type) ++ return -1; ++ data->client_random = conn->expkey_randbytes; ++ data->client_random_len = MBEDTLS_EXPKEY_RAND_LEN; ++ data->server_random = conn->expkey_randbytes + MBEDTLS_EXPKEY_RAND_LEN; ++ data->server_random_len = MBEDTLS_EXPKEY_RAND_LEN; ++ return 0; ++} ++ ++ ++int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn, ++ const char *label, const u8 *context, ++ size_t context_len, u8 *out, size_t out_len) ++{ ++ /* (EAP-PEAP EAP-TLS EAP-TTLS) */ ++ #if MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */ ++ return (conn && conn->established && conn->tls_prf_type) ++ ? mbedtls_ssl_tls_prf(conn->tls_prf_type, ++ conn->expkey_secret, conn->expkey_secret_len, label, ++ conn->expkey_randbytes, ++ sizeof(conn->expkey_randbytes), out, out_len) ++ : -1; ++ #else ++ /* not implemented here for mbedtls < 2.18.0 */ ++ return -1; ++ #endif ++} ++ ++ ++#ifdef TLS_MBEDTLS_EAP_FAST ++ ++#if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */ ++/* keyblock size info is not exposed in mbed TLS 3.0.0 */ ++/* extracted from mbedtls library/ssl_tls.c:ssl_tls12_populate_transform() */ ++#include ++#include ++static size_t tls_mbedtls_ssl_keyblock_size (mbedtls_ssl_context *ssl) ++{ ++ #if !defined(MBEDTLS_USE_PSA_CRYPTO) /* XXX: (not extracted for PSA crypto) */ ++ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) ++ if (tls_version == MBEDTLS_SSL_VERSION_TLS1_3) ++ return 0; /* (calculation not extracted) */ ++ #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ ++ ++ int ciphersuite = mbedtls_ssl_get_ciphersuite_id_from_ssl(ssl); ++ const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ++ mbedtls_ssl_ciphersuite_from_id(ciphersuite); ++ if (ciphersuite_info == NULL) ++ return 0; ++ ++ const mbedtls_cipher_info_t *cipher_info = ++ mbedtls_cipher_info_from_type(ciphersuite_info->MBEDTLS_PRIVATE(cipher)); ++ if (cipher_info == NULL) ++ return 0; ++ ++ #if MBEDTLS_VERSION_NUMBER >= 0x03010000 /* mbedtls 3.1.0 */ ++ size_t keylen = mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8; ++ mbedtls_cipher_mode_t mode = mbedtls_cipher_info_get_mode(cipher_info); ++ #else ++ size_t keylen = cipher_info->MBEDTLS_PRIVATE(key_bitlen) / 8; ++ mbedtls_cipher_mode_t mode = cipher_info->MBEDTLS_PRIVATE(mode); ++ #endif ++ #if defined(MBEDTLS_GCM_C) || \ ++ defined(MBEDTLS_CCM_C) || \ ++ defined(MBEDTLS_CHACHAPOLY_C) ++ if (mode == MBEDTLS_MODE_GCM || mode == MBEDTLS_MODE_CCM) ++ return keylen + 4; ++ else if (mode == MBEDTLS_MODE_CHACHAPOLY) ++ return keylen + 12; ++ else ++ #endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */ ++ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) ++ { ++ const mbedtls_md_info_t *md_info = ++ mbedtls_md_info_from_type(ciphersuite_info->MBEDTLS_PRIVATE(mac)); ++ if (md_info == NULL) ++ return 0; ++ size_t mac_key_len = mbedtls_md_get_size(md_info); ++ size_t ivlen = mbedtls_cipher_info_get_iv_size(cipher_info); ++ return keylen + mac_key_len + ivlen; ++ } ++ #endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ ++ #endif /* !MBEDTLS_USE_PSA_CRYPTO *//* (not extracted for PSA crypto) */ ++ return 0; ++} ++#endif /* MBEDTLS_VERSION_NUMBER >= 0x03000000 *//* mbedtls 3.0.0 */ ++ ++ ++int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn, ++ u8 *out, size_t out_len) ++{ ++ /* XXX: has export keys callback been run? */ ++ if (!conn || !conn->tls_prf_type) ++ return -1; ++ ++ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */ ++ conn->expkey_keyblock_size = tls_mbedtls_ssl_keyblock_size(&conn->ssl); ++ if (conn->expkey_keyblock_size == 0) ++ return -1; ++ #endif ++ size_t skip = conn->expkey_keyblock_size * 2; ++ unsigned char *tmp_out = os_malloc(skip + out_len); ++ if (!tmp_out) ++ return -1; ++ ++ /* server_random and then client_random */ ++ unsigned char seed[MBEDTLS_EXPKEY_RAND_LEN*2]; ++ os_memcpy(seed, conn->expkey_randbytes + MBEDTLS_EXPKEY_RAND_LEN, ++ MBEDTLS_EXPKEY_RAND_LEN); ++ os_memcpy(seed + MBEDTLS_EXPKEY_RAND_LEN, conn->expkey_randbytes, ++ MBEDTLS_EXPKEY_RAND_LEN); ++ ++ #if MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */ ++ int ret = mbedtls_ssl_tls_prf(conn->tls_prf_type, ++ conn->expkey_secret, conn->expkey_secret_len, ++ "key expansion", seed, sizeof(seed), ++ tmp_out, skip + out_len); ++ if (ret == 0) ++ os_memcpy(out, tmp_out + skip, out_len); ++ #else ++ int ret = -1; /*(not reached if not impl; return -1 at top of func)*/ ++ #endif ++ ++ bin_clear_free(tmp_out, skip + out_len); ++ forced_memzero(seed, sizeof(seed)); ++ return ret; ++} ++ ++#endif /* TLS_MBEDTLS_EAP_FAST */ ++ ++ ++__attribute_cold__ ++static void tls_mbedtls_suiteb_handshake_alert (struct tls_connection *conn) ++{ ++ /* tests/hwsim/test_suite_b.py test_suite_b_192_rsa_insufficient_dh */ ++ if (!(conn->tls_conf->flags & TLS_CONN_SUITEB)) ++ return; ++ if (tls_ctx_global.tls_conf) /*(is server; want issue event on client)*/ ++ return; ++ #if 0 ++ /*(info not available on client; ++ * mbed TLS library enforces dhm min bitlen in ServerKeyExchange)*/ ++ if (MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 == ++ #if MBEDTLS_VERSION_NUMBER < 0x03020000 /* mbedtls 3.2.0 */ ++ mbedtls_ssl_get_ciphersuite_id_from_ssl(&conn->ssl) ++ #else ++ mbedtls_ssl_get_ciphersuite_id( ++ mbedtls_ssl_get_ciphersuite(&conn->ssl)) ++ #endif ++ && mbedtls_mpi_size(&conn->tls_conf->conf.MBEDTLS_PRIVATE(dhm_P)) ++ < 384 /*(3072/8)*/) ++ #endif ++ { ++ struct tls_config *init_conf = &tls_ctx_global.init_conf; ++ if (init_conf->event_cb) { ++ union tls_event_data ev; ++ os_memset(&ev, 0, sizeof(ev)); ++ ev.alert.is_local = 1; ++ ev.alert.type = "fatal"; ++ /*"internal error" string for tests/hwsim/test_suiteb.py */ ++ ev.alert.description = "internal error: handshake failure"; ++ /*ev.alert.description = "insufficient security";*/ ++ init_conf->event_cb(init_conf->cb_ctx, TLS_ALERT, &ev); ++ } ++ } ++} ++ ++ ++struct wpabuf * tls_connection_handshake(void *tls_ctx, ++ struct tls_connection *conn, ++ const struct wpabuf *in_data, ++ struct wpabuf **appl_data) ++{ ++ if (appl_data) ++ *appl_data = NULL; ++ ++ if (in_data && wpabuf_len(in_data)) { ++ /*(unsure why tls_gnutls.c discards buffer contents; skip here)*/ ++ if (conn->pull_buf && 0) /* disable; appears unwise */ ++ tls_pull_buf_discard(conn, __func__); ++ if (!tls_pull_buf_append(conn, in_data)) ++ return NULL; ++ } ++ ++ if (conn->tls_conf == NULL) { ++ struct tls_connection_params params; ++ os_memset(¶ms, 0, sizeof(params)); ++ params.openssl_ciphers = ++ tls_ctx_global.init_conf.openssl_ciphers; ++ params.flags = tls_ctx_global.tls_conf->flags; ++ if (tls_connection_set_params(tls_ctx, conn, ¶ms) != 0) ++ return NULL; ++ } ++ ++ if (conn->verify_peer) /*(call here might be redundant; nbd)*/ ++ mbedtls_ssl_set_verify(&conn->ssl, tls_mbedtls_verify_cb, conn); ++ ++ #ifdef TLS_MBEDTLS_SESSION_TICKETS ++ if (conn->clienthello_session_ticket) ++ /*(starting handshake for EAP-FAST and EAP-TEAP)*/ ++ tls_mbedtls_clienthello_session_ticket_set(conn); ++ ++ /* (not thread-safe due to need to set userdata 'conn' for callback) */ ++ /* (unable to use mbedtls_ssl_set_user_data_p() with mbedtls 3.2.0+ ++ * since ticket write and parse callbacks take (mbedtls_ssl_session *) ++ * param instead of (mbedtls_ssl_context *) param) */ ++ if (conn->tls_conf->flags & TLS_CONN_DISABLE_SESSION_TICKET) ++ mbedtls_ssl_conf_session_tickets_cb(&conn->tls_conf->conf, ++ NULL, NULL, NULL); ++ else ++ mbedtls_ssl_conf_session_tickets_cb(&conn->tls_conf->conf, ++ tls_mbedtls_ssl_ticket_write, ++ tls_mbedtls_ssl_ticket_parse, ++ conn); ++ #endif ++ ++ #if MBEDTLS_VERSION_NUMBER >= 0x03020000 /* mbedtls 3.2.0 */ ++ int ret = mbedtls_ssl_handshake(&conn->ssl); ++ #else ++ int ret = 0; ++ while (conn->ssl.MBEDTLS_PRIVATE(state) != MBEDTLS_SSL_HANDSHAKE_OVER) { ++ ret = mbedtls_ssl_handshake_step(&conn->ssl); ++ if (ret != 0) ++ break; ++ } ++ #endif ++ ++ #ifdef TLS_MBEDTLS_SESSION_TICKETS ++ mbedtls_ssl_conf_session_tickets_cb(&conn->tls_conf->conf, ++ tls_mbedtls_ssl_ticket_write, ++ tls_mbedtls_ssl_ticket_parse, ++ NULL); ++ #endif ++ ++ switch (ret) { ++ case 0: ++ conn->established = 1; ++ if (conn->push_buf == NULL) ++ /* Need to return something to get final TLS ACK. */ ++ conn->push_buf = wpabuf_alloc(0); ++ ++ if (appl_data /*&& conn->pull_buf && wpabuf_len(conn->pull_buf)*/) ++ *appl_data = NULL; /* RFE: check for application data */ ++ break; ++ case MBEDTLS_ERR_SSL_WANT_WRITE: ++ case MBEDTLS_ERR_SSL_WANT_READ: ++ case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS: ++ case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: ++ if (tls_ctx_global.tls_conf /*(is server)*/ ++ && conn->established && conn->push_buf == NULL) ++ /* Need to return something to trigger completion of EAP-TLS. */ ++ conn->push_buf = wpabuf_alloc(0); ++ break; ++ default: ++ ++conn->failed; ++ switch (ret) { ++ case MBEDTLS_ERR_SSL_CLIENT_RECONNECT: ++ case MBEDTLS_ERR_NET_CONN_RESET: ++ case MBEDTLS_ERR_NET_SEND_FAILED: ++ ++conn->write_alerts; ++ break; ++ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */ ++ case MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE: ++ #else ++ case MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE: ++ #endif ++ tls_mbedtls_suiteb_handshake_alert(conn); ++ /* fall through */ ++ case MBEDTLS_ERR_NET_RECV_FAILED: ++ case MBEDTLS_ERR_SSL_CONN_EOF: ++ case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: ++ case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE: ++ ++conn->read_alerts; ++ break; ++ default: ++ break; ++ } ++ ++ ilog(ret, "mbedtls_ssl_handshake"); ++ break; ++ } ++ ++ struct wpabuf *out_data = conn->push_buf; ++ conn->push_buf = NULL; ++ return out_data; ++} ++ ++ ++struct wpabuf * tls_connection_server_handshake(void *tls_ctx, ++ struct tls_connection *conn, ++ const struct wpabuf *in_data, ++ struct wpabuf **appl_data) ++{ ++ conn->is_server = 1; ++ return tls_connection_handshake(tls_ctx, conn, in_data, appl_data); ++} ++ ++ ++struct wpabuf * tls_connection_encrypt(void *tls_ctx, ++ struct tls_connection *conn, ++ const struct wpabuf *in_data) ++{ ++ int res = mbedtls_ssl_write(&conn->ssl, ++ wpabuf_head_u8(in_data), wpabuf_len(in_data)); ++ if (res < 0) { ++ elog(res, "mbedtls_ssl_write"); ++ return NULL; ++ } ++ ++ struct wpabuf *buf = conn->push_buf; ++ conn->push_buf = NULL; ++ return buf; ++} ++ ++ ++struct wpabuf * tls_connection_decrypt(void *tls_ctx, ++ struct tls_connection *conn, ++ const struct wpabuf *in_data) ++{ ++ int res; ++ struct wpabuf *out; ++ ++ /*assert(in_data != NULL);*/ ++ if (!tls_pull_buf_append(conn, in_data)) ++ return NULL; ++ ++ #if defined(MBEDTLS_ZLIB_SUPPORT) /* removed in mbedtls 3.x */ ++ /* Add extra buffer space to handle the possibility of decrypted ++ * data being longer than input data due to TLS compression. */ ++ out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); ++ #else /* TLS compression is disabled in mbedtls 3.x */ ++ out = wpabuf_alloc(wpabuf_len(in_data)); ++ #endif ++ if (out == NULL) ++ return NULL; ++ ++ res = mbedtls_ssl_read(&conn->ssl, wpabuf_mhead(out), wpabuf_size(out)); ++ if (res < 0) { ++ #if 1 /*(seems like a different error if wpabuf_len(in_data) == 0)*/ ++ if (res == MBEDTLS_ERR_SSL_WANT_READ) ++ return out; ++ #endif ++ elog(res, "mbedtls_ssl_read"); ++ wpabuf_free(out); ++ return NULL; ++ } ++ wpabuf_put(out, res); ++ ++ return out; ++} ++ ++ ++int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn) ++{ ++ /* XXX: might need to detect if session resumed from TLS session ticket ++ * even if not special session ticket handling for EAP-FAST, EAP-TEAP */ ++ /* (?ssl->handshake->resume during session ticket validation?) */ ++ return conn && conn->resumed; ++} ++ ++ ++#ifdef TLS_MBEDTLS_EAP_FAST ++int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, ++ u8 *ciphers) ++{ ++ /* ciphers is list of TLS_CIPHER_* from hostap/src/crypto/tls.h */ ++ int ids[7]; ++ const int idsz = (int)sizeof(ids); ++ int nids = -1, id; ++ for ( ; *ciphers != TLS_CIPHER_NONE; ++ciphers) { ++ switch (*ciphers) { ++ case TLS_CIPHER_RC4_SHA: ++ #ifdef MBEDTLS_TLS_RSA_WITH_RC4_128_SHA ++ id = MBEDTLS_TLS_RSA_WITH_RC4_128_SHA; ++ break; ++ #else ++ continue; /*(not supported in mbedtls 3.x; ignore)*/ ++ #endif ++ case TLS_CIPHER_AES128_SHA: ++ id = MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA; ++ break; ++ case TLS_CIPHER_RSA_DHE_AES128_SHA: ++ id = MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA; ++ break; ++ case TLS_CIPHER_ANON_DH_AES128_SHA: ++ continue; /*(not supported in mbedtls; ignore)*/ ++ case TLS_CIPHER_RSA_DHE_AES256_SHA: ++ id = MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA; ++ break; ++ case TLS_CIPHER_AES256_SHA: ++ id = MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA; ++ break; ++ default: ++ return -1; /* should not happen */ ++ } ++ if (++nids == idsz) ++ return -1; /* should not happen */ ++ ids[nids] = id; ++ } ++ if (nids < 0) ++ return 0; /* nothing to do */ ++ if (++nids == idsz) ++ return -1; /* should not happen */ ++ ids[nids] = 0; /* terminate list */ ++ ++nids; ++ ++ return tls_mbedtls_set_ciphersuites(conn->tls_conf, ids, nids) ? 0 : -1; ++} ++#endif ++ ++ ++int tls_get_version(void *ssl_ctx, struct tls_connection *conn, ++ char *buf, size_t buflen) ++{ ++ if (conn == NULL) ++ return -1; ++ os_strlcpy(buf, mbedtls_ssl_get_version(&conn->ssl), buflen); ++ return buf[0] != 'u' ? 0 : -1; /*(-1 if "unknown")*/ ++} ++ ++ ++#ifdef TLS_MBEDTLS_EAP_TEAP ++u16 tls_connection_get_cipher_suite(struct tls_connection *conn) ++{ ++ if (conn == NULL) ++ return 0; ++ return (u16)mbedtls_ssl_get_ciphersuite_id_from_ssl(&conn->ssl); ++} ++#endif ++ ++ ++int tls_get_cipher(void *tls_ctx, struct tls_connection *conn, ++ char *buf, size_t buflen) ++{ ++ if (conn == NULL) ++ return -1; ++ const int id = mbedtls_ssl_get_ciphersuite_id_from_ssl(&conn->ssl); ++ return tls_mbedtls_translate_ciphername(id, buf, buflen) ? 0 : -1; ++} ++ ++ ++#ifdef TLS_MBEDTLS_SESSION_TICKETS ++ ++int tls_connection_enable_workaround(void *tls_ctx, ++ struct tls_connection *conn) ++{ ++ /* (see comment in src/eap_peer/eap_fast.c:eap_fast_init()) */ ++ /* XXX: is there a relevant setting for this in mbed TLS? */ ++ /* (do we even care that much about older CBC ciphers?) */ ++ return 0; ++} ++ ++ ++int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn, ++ int ext_type, const u8 *data, ++ size_t data_len) ++{ ++ /* (EAP-FAST and EAP-TEAP) */ ++ if (ext_type == MBEDTLS_TLS_EXT_SESSION_TICKET) /*(ext_type == 35)*/ ++ return tls_mbedtls_clienthello_session_ticket_prep(conn, data, ++ data_len); ++ ++ return -1; ++} ++ ++#endif /* TLS_MBEDTLS_SESSION_TICKETS */ ++ ++ ++int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn) ++{ ++ return conn ? conn->failed : -1; ++} ++ ++ ++int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn) ++{ ++ return conn ? conn->read_alerts : -1; ++} ++ ++ ++int tls_connection_get_write_alerts(void *tls_ctx, ++ struct tls_connection *conn) ++{ ++ return conn ? conn->write_alerts : -1; ++} ++ ++ ++#ifdef TLS_MBEDTLS_SESSION_TICKETS ++int tls_connection_set_session_ticket_cb( ++ void *tls_ctx, struct tls_connection *conn, ++ tls_session_ticket_cb cb, void *ctx) ++{ ++ if (!(conn->tls_conf->flags & TLS_CONN_DISABLE_SESSION_TICKET)) { ++ /* (EAP-FAST and EAP-TEAP) */ ++ conn->session_ticket_cb = cb; ++ conn->session_ticket_cb_ctx = ctx; ++ return 0; ++ } ++ return -1; ++} ++#endif ++ ++ ++int tls_get_library_version(char *buf, size_t buf_len) ++{ ++ #ifndef MBEDTLS_VERSION_C ++ const char * const ver = "n/a"; ++ #else ++ char ver[9]; ++ mbedtls_version_get_string(ver); ++ #endif ++ return os_snprintf(buf, buf_len, ++ "mbed TLS build=" MBEDTLS_VERSION_STRING " run=%s", ver); ++} ++ ++ ++void tls_connection_set_success_data(struct tls_connection *conn, ++ struct wpabuf *data) ++{ ++ wpabuf_free(conn->success_data); ++ conn->success_data = data; ++} ++ ++ ++void tls_connection_set_success_data_resumed(struct tls_connection *conn) ++{ ++} ++ ++ ++const struct wpabuf * ++tls_connection_get_success_data(struct tls_connection *conn) ++{ ++ return conn->success_data; ++} ++ ++ ++void tls_connection_remove_session(struct tls_connection *conn) ++{ ++} ++ ++ ++#ifdef TLS_MBEDTLS_EAP_TEAP ++int tls_get_tls_unique(struct tls_connection *conn, u8 *buf, size_t max_len) ++{ ++ #if defined(MBEDTLS_SSL_RENEGOTIATION) /* XXX: renegotiation or resumption? */ ++ /* data from TLS handshake Finished message */ ++ size_t verify_len = conn->ssl.MBEDTLS_PRIVATE(verify_data_len); ++ char *verify_data = (conn->is_server ^ conn->resumed) ++ ? conn->ssl.MBEDTLS_PRIVATE(peer_verify_data) ++ : conn->ssl.MBEDTLS_PRIVATE(own_verify_data); ++ if (verify_len && verify_len <= max_len) { ++ os_memcpy(buf, verify_data, verify_len); ++ return (int)verify_len; ++ } ++ #endif ++ return -1; ++} ++#endif ++ ++ ++__attribute_noinline__ ++static void tls_mbedtls_set_peer_subject(struct tls_connection *conn, const mbedtls_x509_crt *crt) ++{ ++ if (conn->peer_subject) ++ return; ++ char buf[MBEDTLS_X509_MAX_DN_NAME_SIZE*2]; ++ int buflen = mbedtls_x509_dn_gets(buf, sizeof(buf), &crt->subject); ++ if (buflen >= 0 && (conn->peer_subject = os_malloc((size_t)buflen+1))) ++ os_memcpy(conn->peer_subject, buf, (size_t)buflen+1); ++} ++ ++ ++#ifdef TLS_MBEDTLS_EAP_TEAP ++const char * tls_connection_get_peer_subject(struct tls_connection *conn) ++{ ++ if (!conn) ++ return NULL; ++ if (!conn->peer_subject) { /*(if not set during cert verify)*/ ++ const mbedtls_x509_crt *peer_cert = ++ mbedtls_ssl_get_peer_cert(&conn->ssl); ++ if (peer_cert) ++ tls_mbedtls_set_peer_subject(conn, peer_cert); ++ } ++ return conn->peer_subject; ++} ++#endif ++ ++ ++#ifdef TLS_MBEDTLS_EAP_TEAP ++bool tls_connection_get_own_cert_used(struct tls_connection *conn) ++{ ++ /* XXX: availability of cert does not necessary mean that client ++ * received certificate request from server and then sent cert. ++ * ? step handshake in tls_connection_handshake() looking for ++ * MBEDTLS_SSL_CERTIFICATE_REQUEST ? */ ++ const struct tls_conf * const tls_conf = conn->tls_conf; ++ return (tls_conf->has_client_cert && tls_conf->has_private_key); ++} ++#endif ++ ++ ++#if defined(CONFIG_FIPS) ++#define TLS_MBEDTLS_CONFIG_FIPS ++#endif ++ ++#if defined(CONFIG_SHA256) ++#define TLS_MBEDTLS_TLS_PRF_SHA256 ++#endif ++ ++#if defined(CONFIG_SHA384) ++#define TLS_MBEDTLS_TLS_PRF_SHA384 ++#endif ++ ++ ++#ifndef TLS_MBEDTLS_CONFIG_FIPS ++#if defined(CONFIG_MODULE_TESTS) ++/* unused with CONFIG_TLS=mbedtls except in crypto_module_tests.c */ ++#if MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */ \ ++ && MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */ ++/* sha1-tlsprf.c */ ++#include "sha1.h" ++int tls_prf_sha1_md5(const u8 *secret, size_t secret_len, const char *label, ++ const u8 *seed, size_t seed_len, u8 *out, size_t outlen) ++{ ++ return mbedtls_ssl_tls_prf(MBEDTLS_SSL_TLS_PRF_TLS1, ++ secret, secret_len, label, ++ seed, seed_len, out, outlen) ? -1 : 0; ++} ++#else ++#include "sha1-tlsprf.c" /* pull in hostap local implementation */ ++#endif ++#endif ++#endif ++ ++#ifdef TLS_MBEDTLS_TLS_PRF_SHA256 ++/* sha256-tlsprf.c */ ++#if MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */ ++#include "sha256.h" ++int tls_prf_sha256(const u8 *secret, size_t secret_len, const char *label, ++ const u8 *seed, size_t seed_len, u8 *out, size_t outlen) ++{ ++ return mbedtls_ssl_tls_prf(MBEDTLS_SSL_TLS_PRF_SHA256, ++ secret, secret_len, label, ++ seed, seed_len, out, outlen) ? -1 : 0; ++} ++#else ++#include "sha256-tlsprf.c" /* pull in hostap local implementation */ ++#endif ++#endif ++ ++#ifdef TLS_MBEDTLS_TLS_PRF_SHA384 ++/* sha384-tlsprf.c */ ++#if MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */ ++#include "sha384.h" ++int tls_prf_sha384(const u8 *secret, size_t secret_len, const char *label, ++ const u8 *seed, size_t seed_len, u8 *out, size_t outlen) ++{ ++ return mbedtls_ssl_tls_prf(MBEDTLS_SSL_TLS_PRF_SHA384, ++ secret, secret_len, label, ++ seed, seed_len, out, outlen) ? -1 : 0; ++} ++#else ++#include "sha384-tlsprf.c" /* pull in hostap local implementation */ ++#endif ++#endif ++ ++ ++#if MBEDTLS_VERSION_NUMBER < 0x03020000 /* mbedtls 3.2.0 */ ++#define mbedtls_x509_crt_has_ext_type(crt, ext_type) \ ++ ((crt)->MBEDTLS_PRIVATE(ext_types) & (ext_type)) ++#endif ++ ++struct mlist { const char *p; size_t n; }; ++ ++ ++static int ++tls_mbedtls_match_altsubject(mbedtls_x509_crt *crt, const char *match) ++{ ++ /* RFE: this could be pre-parsed into structured data at config time */ ++ struct mlist list[256]; /*(much larger than expected)*/ ++ int nlist = 0; ++ if ( os_strncmp(match, "EMAIL:", 6) != 0 ++ && os_strncmp(match, "DNS:", 4) != 0 ++ && os_strncmp(match, "URI:", 4) != 0 ) { ++ wpa_printf(MSG_INFO, "MTLS: Invalid altSubjectName match '%s'", match); ++ return 0; ++ } ++ for (const char *s = match, *tok; *s; s = tok ? tok+1 : "") { ++ do { } while ((tok = os_strchr(s, ';')) ++ && os_strncmp(tok+1, "EMAIL:", 6) != 0 ++ && os_strncmp(tok+1, "DNS:", 4) != 0 ++ && os_strncmp(tok+1, "URI:", 4) != 0); ++ list[nlist].p = s; ++ list[nlist].n = tok ? (size_t)(tok - s) : os_strlen(s); ++ if (list[nlist].n && ++nlist == sizeof(list)/sizeof(*list)) { ++ wpa_printf(MSG_INFO, "MTLS: excessive altSubjectName match '%s'", ++ match); ++ break; /* truncate huge list and continue */ ++ } ++ } ++ ++ if (!mbedtls_x509_crt_has_ext_type(crt, MBEDTLS_X509_EXT_SUBJECT_ALT_NAME)) ++ return 0; ++ ++ const mbedtls_x509_sequence *cur = &crt->subject_alt_names; ++ for (; cur != NULL; cur = cur->next) { ++ const unsigned char san_type = (unsigned char)cur->buf.tag ++ & MBEDTLS_ASN1_TAG_VALUE_MASK; ++ char t; ++ size_t step = 4; ++ switch (san_type) { /* "EMAIL:" or "DNS:" or "URI:" */ ++ case MBEDTLS_X509_SAN_RFC822_NAME: step = 6; t = 'E'; break; ++ case MBEDTLS_X509_SAN_DNS_NAME: t = 'D'; break; ++ case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: t = 'U'; break; ++ default: continue; ++ } ++ ++ for (int i = 0; i < nlist; ++i) { ++ /* step over "EMAIL:" or "DNS:" or "URI:" in list[i].p */ ++ /* Note: v is not '\0'-terminated, but is a known length vlen, ++ * so okay to pass to os_strncasecmp() even though not z-string */ ++ if (cur->buf.len == list[i].n - step && t == *list[i].p ++ && 0 == os_strncasecmp((char *)cur->buf.p, ++ list[i].p+step, cur->buf.len)) { ++ return 1; /* match */ ++ } ++ } ++ } ++ return 0; /* no match */ ++} ++ ++ ++static int ++tls_mbedtls_match_suffix(const char *v, size_t vlen, ++ const struct mlist *list, int nlist, int full) ++{ ++ /* Note: v is not '\0'-terminated, but is a known length vlen, ++ * so okay to pass to os_strncasecmp() even though not z-string */ ++ for (int i = 0; i < nlist; ++i) { ++ size_t n = list[i].n; ++ if ((n == vlen || (n < vlen && v[vlen-n-1] == '.' && !full)) ++ && 0 == os_strncasecmp(v+vlen-n, list[i].p, n)) ++ return 1; /* match */ ++ } ++ return 0; /* no match */ ++} ++ ++ ++static int ++tls_mbedtls_match_suffixes(mbedtls_x509_crt *crt, const char *match, int full) ++{ ++ /* RFE: this could be pre-parsed into structured data at config time */ ++ struct mlist list[256]; /*(much larger than expected)*/ ++ int nlist = 0; ++ for (const char *s = match, *tok; *s; s = tok ? tok+1 : "") { ++ tok = os_strchr(s, ';'); ++ list[nlist].p = s; ++ list[nlist].n = tok ? (size_t)(tok - s) : os_strlen(s); ++ if (list[nlist].n && ++nlist == sizeof(list)/sizeof(*list)) { ++ wpa_printf(MSG_INFO, "MTLS: excessive suffix match '%s'", match); ++ break; /* truncate huge list and continue */ ++ } ++ } ++ ++ /* check subjectAltNames */ ++ if (mbedtls_x509_crt_has_ext_type(crt, MBEDTLS_X509_EXT_SUBJECT_ALT_NAME)) { ++ const mbedtls_x509_sequence *cur = &crt->subject_alt_names; ++ for (; cur != NULL; cur = cur->next) { ++ const unsigned char san_type = (unsigned char)cur->buf.tag ++ & MBEDTLS_ASN1_TAG_VALUE_MASK; ++ if (san_type == MBEDTLS_X509_SAN_DNS_NAME ++ && tls_mbedtls_match_suffix((char *)cur->buf.p, ++ cur->buf.len, ++ list, nlist, full)) { ++ return 1; /* match */ ++ } ++ } ++ } ++ ++ /* check subject CN */ ++ const mbedtls_x509_name *name = &crt->subject; ++ for (; name != NULL; name = name->next) { ++ if (name->oid.p && MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid) == 0) ++ break; ++ } ++ if (name && tls_mbedtls_match_suffix((char *)name->val.p, name->val.len, ++ list, nlist, full)) { ++ return 1; /* match */ ++ } ++ ++ return 0; /* no match */ ++} ++ ++ ++static int ++tls_mbedtls_match_dn_field(mbedtls_x509_crt *crt, const char *match) ++{ ++ /* RFE: this could be pre-parsed into structured data at config time */ ++ struct mlistoid { const char *p; size_t n; ++ const char *oid; size_t olen; ++ int prefix; }; ++ struct mlistoid list[32]; /*(much larger than expected)*/ ++ int nlist = 0; ++ for (const char *s = match, *tok, *e; *s; s = tok ? tok+1 : "") { ++ tok = os_strchr(s, '/'); ++ list[nlist].oid = NULL; ++ list[nlist].olen = 0; ++ list[nlist].n = tok ? (size_t)(tok - s) : os_strlen(s); ++ e = memchr(s, '=', list[nlist].n); ++ if (e == NULL) { ++ if (list[nlist].n == 0) ++ continue; /* skip consecutive, repeated '/' */ ++ if (list[nlist].n == 1 && *s == '*') { ++ /* special-case "*" to match any OID and value */ ++ s = e = "=*"; ++ list[nlist].n = 2; ++ list[nlist].oid = ""; ++ } ++ else { ++ wpa_printf(MSG_INFO, ++ "MTLS: invalid check_cert_subject '%s' missing '='", ++ match); ++ return 0; ++ } ++ } ++ switch (e - s) { ++ case 1: ++ if (*s == 'C') { ++ list[nlist].oid = MBEDTLS_OID_AT_COUNTRY; ++ list[nlist].olen = sizeof(MBEDTLS_OID_AT_COUNTRY)-1; ++ } ++ else if (*s == 'L') { ++ list[nlist].oid = MBEDTLS_OID_AT_LOCALITY; ++ list[nlist].olen = sizeof(MBEDTLS_OID_AT_LOCALITY)-1; ++ } ++ else if (*s == 'O') { ++ list[nlist].oid = MBEDTLS_OID_AT_ORGANIZATION; ++ list[nlist].olen = sizeof(MBEDTLS_OID_AT_ORGANIZATION)-1; ++ } ++ break; ++ case 2: ++ if (s[0] == 'C' && s[1] == 'N') { ++ list[nlist].oid = MBEDTLS_OID_AT_CN; ++ list[nlist].olen = sizeof(MBEDTLS_OID_AT_CN)-1; ++ } ++ else if (s[0] == 'S' && s[1] == 'T') { ++ list[nlist].oid = MBEDTLS_OID_AT_STATE; ++ list[nlist].olen = sizeof(MBEDTLS_OID_AT_STATE)-1; ++ } ++ else if (s[0] == 'O' && s[1] == 'U') { ++ list[nlist].oid = MBEDTLS_OID_AT_ORG_UNIT; ++ list[nlist].olen = sizeof(MBEDTLS_OID_AT_ORG_UNIT)-1; ++ } ++ break; ++ case 12: ++ if (os_memcmp(s, "emailAddress", 12) == 0) { ++ list[nlist].oid = MBEDTLS_OID_PKCS9_EMAIL; ++ list[nlist].olen = sizeof(MBEDTLS_OID_PKCS9_EMAIL)-1; ++ } ++ break; ++ default: ++ break; ++ } ++ if (list[nlist].oid == NULL) { ++ wpa_printf(MSG_INFO, ++ "MTLS: Unknown field in check_cert_subject '%s'", ++ match); ++ return 0; ++ } ++ list[nlist].n -= (size_t)(++e - s); ++ list[nlist].p = e; ++ if (list[nlist].n && e[list[nlist].n-1] == '*') { ++ --list[nlist].n; ++ list[nlist].prefix = 1; ++ } ++ /*(could easily add support for suffix matches if value begins with '*', ++ * but suffix match is not currently supported by other TLS modules)*/ ++ ++ if (list[nlist].n && ++nlist == sizeof(list)/sizeof(*list)) { ++ wpa_printf(MSG_INFO, ++ "MTLS: excessive check_cert_subject match '%s'", ++ match); ++ break; /* truncate huge list and continue */ ++ } ++ } ++ ++ /* each component in match string must match cert Subject in order listed ++ * The behavior below preserves ordering but is slightly different than ++ * the grossly inefficient contortions implemented in tls_openssl.c */ ++ const mbedtls_x509_name *name = &crt->subject; ++ for (int i = 0; i < nlist; ++i) { ++ int found = 0; ++ for (; name != NULL && !found; name = name->next) { ++ if (!name->oid.p) ++ continue; ++ /* special-case "*" to match any OID and value */ ++ if (list[i].olen == 0) { ++ found = 1; ++ continue; ++ } ++ /* perform equalent of !MBEDTLS_OID_CMP() with oid ptr and len */ ++ if (list[i].olen != name->oid.len ++ || os_memcmp(list[i].oid, name->oid.p, name->oid.len) != 0) ++ continue; ++ /* Note: v is not '\0'-terminated, but is a known length vlen, ++ * so okay to pass to os_strncasecmp() even though not z-string */ ++ if ((list[i].prefix ++ ? list[i].n <= name->val.len /* prefix match */ ++ : list[i].n == name->val.len) /* full match */ ++ && 0 == os_strncasecmp((char *)name->val.p, ++ list[i].p, list[i].n)) { ++ found = 1; ++ continue; ++ } ++ } ++ if (!found) ++ return 0; /* no match */ ++ } ++ return 1; /* match */ ++} ++ ++ ++__attribute_cold__ ++static void ++tls_mbedtls_verify_fail_event (mbedtls_x509_crt *crt, int depth, ++ const char *errmsg, enum tls_fail_reason reason) ++{ ++ struct tls_config *init_conf = &tls_ctx_global.init_conf; ++ if (init_conf->event_cb == NULL) ++ return; ++ ++ struct wpabuf *certbuf = wpabuf_alloc_copy(crt->raw.p, crt->raw.len); ++ char subject[MBEDTLS_X509_MAX_DN_NAME_SIZE*2]; ++ if (mbedtls_x509_dn_gets(subject, sizeof(subject), &crt->subject) < 0) ++ subject[0] = '\0'; ++ union tls_event_data ev; ++ os_memset(&ev, 0, sizeof(ev)); ++ ev.cert_fail.reason = reason; ++ ev.cert_fail.depth = depth; ++ ev.cert_fail.subject = subject; ++ ev.cert_fail.reason_txt = errmsg; ++ ev.cert_fail.cert = certbuf; ++ ++ init_conf->event_cb(init_conf->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev); ++ ++ wpabuf_free(certbuf); ++} ++ ++ ++__attribute_noinline__ ++static void ++tls_mbedtls_verify_cert_event (struct tls_connection *conn, ++ mbedtls_x509_crt *crt, int depth) ++{ ++ struct tls_config *init_conf = &tls_ctx_global.init_conf; ++ if (init_conf->event_cb == NULL) ++ return; ++ ++ struct wpabuf *certbuf = NULL; ++ union tls_event_data ev; ++ os_memset(&ev, 0, sizeof(ev)); ++ ++ #ifdef MBEDTLS_SHA256_C ++ u8 hash[SHA256_DIGEST_LENGTH]; ++ const u8 *addr[] = { (u8 *)crt->raw.p }; ++ if (sha256_vector(1, addr, &crt->raw.len, hash) == 0) { ++ ev.peer_cert.hash = hash; ++ ev.peer_cert.hash_len = sizeof(hash); ++ } ++ #endif ++ ev.peer_cert.depth = depth; ++ char subject[MBEDTLS_X509_MAX_DN_NAME_SIZE*2]; ++ if (depth == 0) ++ ev.peer_cert.subject = conn->peer_subject; ++ if (ev.peer_cert.subject == NULL) { ++ ev.peer_cert.subject = subject; ++ if (mbedtls_x509_dn_gets(subject, sizeof(subject), &crt->subject) < 0) ++ subject[0] = '\0'; ++ } ++ ++ char serial_num[128+1]; ++ ev.peer_cert.serial_num = ++ tls_mbedtls_peer_serial_num(crt, serial_num, sizeof(serial_num)); ++ ++ const mbedtls_x509_sequence *cur; ++ ++ cur = NULL; ++ if (mbedtls_x509_crt_has_ext_type(crt, MBEDTLS_X509_EXT_SUBJECT_ALT_NAME)) ++ cur = &crt->subject_alt_names; ++ for (; cur != NULL; cur = cur->next) { ++ const unsigned char san_type = (unsigned char)cur->buf.tag ++ & MBEDTLS_ASN1_TAG_VALUE_MASK; ++ size_t prelen = 4; ++ const char *pre; ++ switch (san_type) { ++ case MBEDTLS_X509_SAN_RFC822_NAME: prelen = 6; pre = "EMAIL:";break; ++ case MBEDTLS_X509_SAN_DNS_NAME: pre = "DNS:"; break; ++ case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: pre = "URI:"; break; ++ default: continue; ++ } ++ ++ char *pos = os_malloc(prelen + cur->buf.len + 1); ++ if (pos == NULL) ++ break; ++ ev.peer_cert.altsubject[ev.peer_cert.num_altsubject] = pos; ++ os_memcpy(pos, pre, prelen); ++ /* data should be properly backslash-escaped if needed, ++ * so code below does not re-escape, but does replace CTLs */ ++ /*os_memcpy(pos+prelen, cur->buf.p, cur->buf.len);*/ ++ /*pos[prelen+cur->buf.len] = '\0';*/ ++ pos += prelen; ++ for (size_t i = 0; i < cur->buf.len; ++i) { ++ unsigned char c = cur->buf.p[i]; ++ *pos++ = (c >= 32 && c != 127) ? c : '?'; ++ } ++ *pos = '\0'; ++ ++ if (++ev.peer_cert.num_altsubject == TLS_MAX_ALT_SUBJECT) ++ break; ++ } ++ ++ cur = NULL; ++ if (mbedtls_x509_crt_has_ext_type(crt, MBEDTLS_X509_EXT_CERTIFICATE_POLICIES)) ++ cur = &crt->certificate_policies; ++ for (; cur != NULL; cur = cur->next) { ++ if (cur->buf.len != 11) /* len of OID_TOD_STRICT or OID_TOD_TOFU */ ++ continue; ++ /* TOD-STRICT "1.3.6.1.4.1.40808.1.3.1" */ ++ /* TOD-TOFU "1.3.6.1.4.1.40808.1.3.2" */ ++ #define OID_TOD_STRICT "\x2b\x06\x01\x04\x01\x82\xbe\x68\x01\x03\x01" ++ #define OID_TOD_TOFU "\x2b\x06\x01\x04\x01\x82\xbe\x68\x01\x03\x02" ++ if (os_memcmp(cur->buf.p, ++ OID_TOD_STRICT, sizeof(OID_TOD_STRICT)-1) == 0) { ++ ev.peer_cert.tod = 1; /* TOD-STRICT */ ++ break; ++ } ++ if (os_memcmp(cur->buf.p, ++ OID_TOD_TOFU, sizeof(OID_TOD_TOFU)-1) == 0) { ++ ev.peer_cert.tod = 2; /* TOD-TOFU */ ++ break; ++ } ++ } ++ ++ struct tls_conf *tls_conf = conn->tls_conf; ++ if (tls_conf->ca_cert_probe || (tls_conf->flags & TLS_CONN_EXT_CERT_CHECK) ++ || init_conf->cert_in_cb) { ++ certbuf = wpabuf_alloc_copy(crt->raw.p, crt->raw.len); ++ ev.peer_cert.cert = certbuf; ++ } ++ ++ init_conf->event_cb(init_conf->cb_ctx, TLS_PEER_CERTIFICATE, &ev); ++ ++ wpabuf_free(certbuf); ++ char **altsubject; ++ *(const char ***)&altsubject = ev.peer_cert.altsubject; ++ for (size_t i = 0; i < ev.peer_cert.num_altsubject; ++i) ++ os_free(altsubject[i]); ++} ++ ++ ++static int ++tls_mbedtls_verify_cb (void *arg, mbedtls_x509_crt *crt, int depth, uint32_t *flags) ++{ ++ /* XXX: N.B. verify code not carefully tested besides hwsim tests ++ * ++ * RFE: mbedtls_x509_crt_verify_info() and enhance log trace messages ++ * RFE: review and add support for additional TLS_CONN_* flags ++ * not handling OCSP (not available in mbedtls) ++ * ... */ ++ ++ struct tls_connection *conn = (struct tls_connection *)arg; ++ struct tls_conf *tls_conf = conn->tls_conf; ++ uint32_t flags_in = *flags; ++ ++ if (depth > 8) { /*(depth 8 picked as arbitrary limit)*/ ++ emsg(MSG_WARNING, "client cert chain too long"); ++ *flags |= MBEDTLS_X509_BADCERT_OTHER; /* cert chain too long */ ++ tls_mbedtls_verify_fail_event(crt, depth, ++ "client cert chain too long", ++ TLS_FAIL_BAD_CERTIFICATE); ++ } ++ else if (tls_conf->verify_depth0_only) { ++ if (depth > 0) ++ *flags = 0; ++ else { ++ #ifdef MBEDTLS_SHA256_C ++ u8 hash[SHA256_DIGEST_LENGTH]; ++ const u8 *addr[] = { (u8 *)crt->raw.p }; ++ if (sha256_vector(1, addr, &crt->raw.len, hash) < 0 ++ || os_memcmp(tls_conf->ca_cert_hash, hash, sizeof(hash)) != 0) { ++ *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; ++ tls_mbedtls_verify_fail_event(crt, depth, ++ "cert hash mismatch", ++ TLS_FAIL_UNTRUSTED); ++ } ++ else /* hash matches; ignore other issues *except* if revoked)*/ ++ *flags &= MBEDTLS_X509_BADCERT_REVOKED; ++ #endif ++ } ++ } ++ else if (depth == 0) { ++ if (!conn->peer_subject) ++ tls_mbedtls_set_peer_subject(conn, crt); ++ /*(use same labels to tls_mbedtls_verify_fail_event() as used in ++ * other TLS modules so that hwsim tests find exact string match)*/ ++ if (!conn->peer_subject) { /* error copying subject string */ ++ *flags |= MBEDTLS_X509_BADCERT_OTHER; ++ tls_mbedtls_verify_fail_event(crt, depth, ++ "internal error", ++ TLS_FAIL_UNSPECIFIED); ++ } ++ /*(use os_strstr() for subject match as is done in tls_mbedtls.c ++ * to follow the same behavior, even though a suffix match would ++ * make more sense. Also, note that strstr match does not ++ * normalize whitespace (between components) for comparison)*/ ++ else if (tls_conf->subject_match ++ && os_strstr(conn->peer_subject, ++ tls_conf->subject_match) == NULL) { ++ wpa_printf(MSG_WARNING, ++ "MTLS: Subject '%s' did not match with '%s'", ++ conn->peer_subject, tls_conf->subject_match); ++ *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; ++ tls_mbedtls_verify_fail_event(crt, depth, ++ "Subject mismatch", ++ TLS_FAIL_SUBJECT_MISMATCH); ++ } ++ if (tls_conf->altsubject_match ++ && !tls_mbedtls_match_altsubject(crt, tls_conf->altsubject_match)) { ++ wpa_printf(MSG_WARNING, ++ "MTLS: altSubjectName match '%s' not found", ++ tls_conf->altsubject_match); ++ *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; ++ tls_mbedtls_verify_fail_event(crt, depth, ++ "AltSubject mismatch", ++ TLS_FAIL_ALTSUBJECT_MISMATCH); ++ } ++ if (tls_conf->suffix_match ++ && !tls_mbedtls_match_suffixes(crt, tls_conf->suffix_match, 0)) { ++ wpa_printf(MSG_WARNING, ++ "MTLS: Domain suffix match '%s' not found", ++ tls_conf->suffix_match); ++ *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; ++ tls_mbedtls_verify_fail_event(crt, depth, ++ "Domain suffix mismatch", ++ TLS_FAIL_DOMAIN_SUFFIX_MISMATCH); ++ } ++ if (tls_conf->domain_match ++ && !tls_mbedtls_match_suffixes(crt, tls_conf->domain_match, 1)) { ++ wpa_printf(MSG_WARNING, ++ "MTLS: Domain match '%s' not found", ++ tls_conf->domain_match); ++ *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; ++ tls_mbedtls_verify_fail_event(crt, depth, ++ "Domain mismatch", ++ TLS_FAIL_DOMAIN_MISMATCH); ++ } ++ if (tls_conf->check_cert_subject ++ && !tls_mbedtls_match_dn_field(crt, tls_conf->check_cert_subject)) { ++ *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; ++ tls_mbedtls_verify_fail_event(crt, depth, ++ "Distinguished Name", ++ TLS_FAIL_DN_MISMATCH); ++ } ++ if (tls_conf->flags & TLS_CONN_SUITEB) { ++ /* check RSA modulus size (public key bitlen) */ ++ const mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type(&crt->pk); ++ if ((pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS) ++ && mbedtls_pk_get_bitlen(&crt->pk) < 3072) { ++ /* hwsim suite_b RSA tests expect 3072 ++ * suite_b_192_rsa_ecdhe_radius_rsa2048_client ++ * suite_b_192_rsa_dhe_radius_rsa2048_client */ ++ *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; ++ tls_mbedtls_verify_fail_event(crt, depth, ++ "Insufficient RSA modulus size", ++ TLS_FAIL_INSUFFICIENT_KEY_LEN); ++ } ++ } ++ if (tls_conf->check_crl && tls_conf->crl == NULL) { ++ /* see tests/hwsim test_ap_eap.py ap_wpa2_eap_tls_check_crl */ ++ emsg(MSG_WARNING, "check_crl set but no CRL loaded; reject all?"); ++ *flags |= MBEDTLS_X509_BADCERT_OTHER; ++ tls_mbedtls_verify_fail_event(crt, depth, ++ "check_crl set but no CRL loaded; " ++ "reject all?", ++ TLS_FAIL_BAD_CERTIFICATE); ++ } ++ } ++ else { ++ if (tls_conf->check_crl != 2) /* 2 == verify CRLs for all certs */ ++ *flags &= ~MBEDTLS_X509_BADCERT_REVOKED; ++ } ++ ++ if (!tls_conf->check_crl_strict) { ++ *flags &= ~MBEDTLS_X509_BADCRL_EXPIRED; ++ *flags &= ~MBEDTLS_X509_BADCRL_FUTURE; ++ } ++ ++ if (tls_conf->flags & TLS_CONN_DISABLE_TIME_CHECKS) { ++ *flags &= ~MBEDTLS_X509_BADCERT_EXPIRED; ++ *flags &= ~MBEDTLS_X509_BADCERT_FUTURE; ++ } ++ ++ tls_mbedtls_verify_cert_event(conn, crt, depth); ++ ++ if (*flags) { ++ if (*flags & (MBEDTLS_X509_BADCERT_NOT_TRUSTED ++ |MBEDTLS_X509_BADCERT_CN_MISMATCH ++ |MBEDTLS_X509_BADCERT_REVOKED)) { ++ emsg(MSG_WARNING, "client cert not trusted"); ++ } ++ /* report event if flags set but no additional flags set above */ ++ /* (could translate flags to more detailed TLS_FAIL_* if needed) */ ++ if (!(*flags & ~flags_in)) { ++ enum tls_fail_reason reason = TLS_FAIL_UNSPECIFIED; ++ const char *errmsg = "cert verify fail unspecified"; ++ if (*flags & MBEDTLS_X509_BADCERT_NOT_TRUSTED) { ++ reason = TLS_FAIL_UNTRUSTED; ++ errmsg = "certificate not trusted"; ++ } ++ if (*flags & MBEDTLS_X509_BADCERT_REVOKED) { ++ reason = TLS_FAIL_REVOKED; ++ errmsg = "certificate has been revoked"; ++ } ++ if (*flags & MBEDTLS_X509_BADCERT_FUTURE) { ++ reason = TLS_FAIL_NOT_YET_VALID; ++ errmsg = "certificate not yet valid"; ++ } ++ if (*flags & MBEDTLS_X509_BADCERT_EXPIRED) { ++ reason = TLS_FAIL_EXPIRED; ++ errmsg = "certificate has expired"; ++ } ++ if (*flags & MBEDTLS_X509_BADCERT_BAD_MD) { ++ reason = TLS_FAIL_BAD_CERTIFICATE; ++ errmsg = "certificate uses insecure algorithm"; ++ } ++ tls_mbedtls_verify_fail_event(crt, depth, errmsg, reason); ++ } ++ #if 0 ++ /* ??? send (again) cert events for all certs in chain ??? ++ * (should already have been called for greater depths) */ ++ /* tls_openssl.c:tls_verify_cb() sends cert events for all certs ++ * in chain if certificate validation fails, but sends all events ++ * with depth set to 0 (might be a bug) */ ++ if (depth > 0) { ++ int pdepth = depth + 1; ++ for (mbedtls_x509_crt *pcrt; (pcrt = crt->next); ++pdepth) { ++ tls_mbedtls_verify_cert_event(conn, pcrt, pdepth); ++ } ++ } ++ #endif ++ /*(do not preserve subject if verification failed but was optional)*/ ++ if (depth == 0 && conn->peer_subject) { ++ os_free(conn->peer_subject); ++ conn->peer_subject = NULL; ++ } ++ } ++ else if (depth == 0) { ++ struct tls_config *init_conf = &tls_ctx_global.init_conf; ++ if (tls_conf->ca_cert_probe) { ++ /* reject server certificate on probe-only run */ ++ *flags |= MBEDTLS_X509_BADCERT_OTHER; ++ tls_mbedtls_verify_fail_event(crt, depth, ++ "server chain probe", ++ TLS_FAIL_SERVER_CHAIN_PROBE); ++ } ++ else if (init_conf->event_cb) { ++ /* ??? send event as soon as depth == 0 is verified ??? ++ * What about rest of chain? ++ * Follows tls_mbedtls.c behavior: */ ++ init_conf->event_cb(init_conf->cb_ctx, ++ TLS_CERT_CHAIN_SUCCESS, NULL); ++ } ++ } ++ ++ return 0; ++} +--- /dev/null ++++ b/tests/build/build-wpa_supplicant-mbedtls.config +@@ -0,0 +1,24 @@ ++CONFIG_TLS=mbedtls ++ ++CONFIG_WPS=y ++CONFIG_EAP_TLS=y ++CONFIG_EAP_MSCHAPV2=y ++ ++CONFIG_EAP_PSK=y ++CONFIG_EAP_GPSK=y ++CONFIG_EAP_AKA=y ++CONFIG_EAP_SIM=y ++CONFIG_EAP_SAKE=y ++CONFIG_EAP_PAX=y ++CONFIG_EAP_FAST=y ++CONFIG_EAP_IKEV2=y ++ ++CONFIG_SAE=y ++CONFIG_FILS=y ++CONFIG_FILS_SK_PFS=y ++CONFIG_OWE=y ++CONFIG_DPP=y ++CONFIG_SUITEB=y ++CONFIG_SUITEB192=y ++ ++CFLAGS += -Werror +--- a/tests/hwsim/example-hostapd.config ++++ b/tests/hwsim/example-hostapd.config +@@ -4,6 +4,7 @@ CONFIG_DRIVER_NONE=y + CONFIG_DRIVER_NL80211=y + CONFIG_RSN_PREAUTH=y + ++#CONFIG_TLS=mbedtls + #CONFIG_TLS=internal + #CONFIG_INTERNAL_LIBTOMMATH=y + #CONFIG_INTERNAL_LIBTOMMATH_FAST=y +@@ -39,6 +40,9 @@ endif + ifeq ($(CONFIG_TLS), wolfssl) + CONFIG_EAP_PWD=y + endif ++ifeq ($(CONFIG_TLS), mbedtls) ++CONFIG_EAP_PWD=y ++endif + CONFIG_EAP_EKE=y + CONFIG_PKCS12=y + CONFIG_RADIUS_SERVER=y +--- a/tests/hwsim/example-wpa_supplicant.config ++++ b/tests/hwsim/example-wpa_supplicant.config +@@ -2,6 +2,7 @@ + + CONFIG_TLS=openssl + #CONFIG_TLS=wolfssl ++#CONFIG_TLS=mbedtls + #CONFIG_TLS=internal + #CONFIG_INTERNAL_LIBTOMMATH=y + #CONFIG_INTERNAL_LIBTOMMATH_FAST=y +@@ -41,6 +42,9 @@ endif + ifeq ($(CONFIG_TLS), wolfssl) + CONFIG_EAP_PWD=y + endif ++ifeq ($(CONFIG_TLS), mbedtls) ++CONFIG_EAP_PWD=y ++endif + + CONFIG_USIM_SIMULATOR=y + CONFIG_SIM_SIMULATOR=y +--- a/wpa_supplicant/Makefile ++++ b/wpa_supplicant/Makefile +@@ -1163,6 +1163,29 @@ endif + CFLAGS += -DTLS_DEFAULT_CIPHERS=\"$(CONFIG_TLS_DEFAULT_CIPHERS)\" + endif + ++ifeq ($(CONFIG_TLS), mbedtls) ++ifndef CONFIG_CRYPTO ++CONFIG_CRYPTO=mbedtls ++endif ++ifdef TLS_FUNCS ++OBJS += ../src/crypto/tls_mbedtls.o ++LIBS += -lmbedtls -lmbedx509 ++endif ++OBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o ++OBJS_p += ../src/crypto/crypto_$(CONFIG_CRYPTO).o ++OBJS_priv += ../src/crypto/crypto_$(CONFIG_CRYPTO).o ++ifdef NEED_FIPS186_2_PRF ++OBJS += ../src/crypto/fips_prf_internal.o ++SHA1OBJS += ../src/crypto/sha1-internal.o ++endif ++ifeq ($(CONFIG_CRYPTO), mbedtls) ++LIBS += -lmbedcrypto ++LIBS_p += -lmbedcrypto ++# XXX: create a config option? ++CFLAGS += -DCRYPTO_RSA_OAEP_SHA256 ++endif ++endif ++ + ifeq ($(CONFIG_TLS), gnutls) + ifndef CONFIG_CRYPTO + # default to libgcrypt +@@ -1355,9 +1378,11 @@ endif + + ifneq ($(CONFIG_TLS), openssl) + ifneq ($(CONFIG_TLS), wolfssl) ++ifneq ($(CONFIG_TLS), mbedtls) + NEED_INTERNAL_AES_WRAP=y + endif + endif ++endif + ifdef CONFIG_OPENSSL_INTERNAL_AES_WRAP + # Seems to be needed at least with BoringSSL + NEED_INTERNAL_AES_WRAP=y +@@ -1371,9 +1396,11 @@ endif + + ifdef NEED_INTERNAL_AES_WRAP + ifneq ($(CONFIG_TLS), linux) ++ifneq ($(CONFIG_TLS), mbedtls) + AESOBJS += ../src/crypto/aes-unwrap.o + endif + endif ++endif + ifdef NEED_AES_EAX + AESOBJS += ../src/crypto/aes-eax.o + NEED_AES_CTR=y +@@ -1383,35 +1410,45 @@ AESOBJS += ../src/crypto/aes-siv.o + NEED_AES_CTR=y + endif + ifdef NEED_AES_CTR ++ifneq ($(CONFIG_TLS), mbedtls) + AESOBJS += ../src/crypto/aes-ctr.o + endif ++endif + ifdef NEED_AES_ENCBLOCK ++ifneq ($(CONFIG_TLS), mbedtls) + AESOBJS += ../src/crypto/aes-encblock.o + endif ++endif + NEED_AES_ENC=y + ifneq ($(CONFIG_TLS), openssl) + ifneq ($(CONFIG_TLS), linux) + ifneq ($(CONFIG_TLS), wolfssl) ++ifneq ($(CONFIG_TLS), mbedtls) + AESOBJS += ../src/crypto/aes-omac1.o + endif + endif + endif ++endif + ifdef NEED_AES_WRAP + NEED_AES_ENC=y + ifdef NEED_INTERNAL_AES_WRAP ++ifneq ($(CONFIG_TLS), mbedtls) + AESOBJS += ../src/crypto/aes-wrap.o + endif + endif ++endif + ifdef NEED_AES_CBC + NEED_AES_ENC=y + ifneq ($(CONFIG_TLS), openssl) + ifneq ($(CONFIG_TLS), linux) + ifneq ($(CONFIG_TLS), wolfssl) ++ifneq ($(CONFIG_TLS), mbedtls) + AESOBJS += ../src/crypto/aes-cbc.o + endif + endif + endif + endif ++endif + ifdef NEED_AES_ENC + ifdef CONFIG_INTERNAL_AES + AESOBJS += ../src/crypto/aes-internal-enc.o +@@ -1426,12 +1463,16 @@ ifneq ($(CONFIG_TLS), openssl) + ifneq ($(CONFIG_TLS), linux) + ifneq ($(CONFIG_TLS), gnutls) + ifneq ($(CONFIG_TLS), wolfssl) ++ifneq ($(CONFIG_TLS), mbedtls) + SHA1OBJS += ../src/crypto/sha1.o + endif + endif + endif + endif ++endif ++ifneq ($(CONFIG_TLS), mbedtls) + SHA1OBJS += ../src/crypto/sha1-prf.o ++endif + ifdef CONFIG_INTERNAL_SHA1 + SHA1OBJS += ../src/crypto/sha1-internal.o + ifdef NEED_FIPS186_2_PRF +@@ -1443,29 +1484,37 @@ CFLAGS += -DCONFIG_NO_PBKDF2 + else + ifneq ($(CONFIG_TLS), openssl) + ifneq ($(CONFIG_TLS), wolfssl) ++ifneq ($(CONFIG_TLS), mbedtls) + SHA1OBJS += ../src/crypto/sha1-pbkdf2.o + endif + endif + endif ++endif + ifdef NEED_T_PRF ++ifneq ($(CONFIG_TLS), mbedtls) + SHA1OBJS += ../src/crypto/sha1-tprf.o + endif ++endif + ifdef NEED_TLS_PRF ++ifneq ($(CONFIG_TLS), mbedtls) + SHA1OBJS += ../src/crypto/sha1-tlsprf.o + endif + endif ++endif + + ifndef CONFIG_FIPS + ifneq ($(CONFIG_TLS), openssl) + ifneq ($(CONFIG_TLS), linux) + ifneq ($(CONFIG_TLS), gnutls) + ifneq ($(CONFIG_TLS), wolfssl) ++ifneq ($(CONFIG_TLS), mbedtls) + MD5OBJS += ../src/crypto/md5.o + endif + endif + endif + endif + endif ++endif + ifdef NEED_MD5 + ifdef CONFIG_INTERNAL_MD5 + MD5OBJS += ../src/crypto/md5-internal.o +@@ -1520,12 +1569,17 @@ ifneq ($(CONFIG_TLS), openssl) + ifneq ($(CONFIG_TLS), linux) + ifneq ($(CONFIG_TLS), gnutls) + ifneq ($(CONFIG_TLS), wolfssl) ++ifneq ($(CONFIG_TLS), mbedtls) + SHA256OBJS += ../src/crypto/sha256.o + endif + endif + endif + endif ++endif ++ ++ifneq ($(CONFIG_TLS), mbedtls) + SHA256OBJS += ../src/crypto/sha256-prf.o ++endif + ifdef CONFIG_INTERNAL_SHA256 + SHA256OBJS += ../src/crypto/sha256-internal.o + endif +@@ -1538,50 +1592,68 @@ CFLAGS += -DCONFIG_INTERNAL_SHA512 + SHA256OBJS += ../src/crypto/sha512-internal.o + endif + ifdef NEED_TLS_PRF_SHA256 ++ifneq ($(CONFIG_TLS), mbedtls) + SHA256OBJS += ../src/crypto/sha256-tlsprf.o + endif ++endif + ifdef NEED_TLS_PRF_SHA384 ++ifneq ($(CONFIG_TLS), mbedtls) + SHA256OBJS += ../src/crypto/sha384-tlsprf.o + endif ++endif + ifdef NEED_HMAC_SHA256_KDF + CFLAGS += -DCONFIG_HMAC_SHA256_KDF ++ifneq ($(CONFIG_TLS), mbedtls) + OBJS += ../src/crypto/sha256-kdf.o + endif ++endif + ifdef NEED_HMAC_SHA384_KDF + CFLAGS += -DCONFIG_HMAC_SHA384_KDF ++ifneq ($(CONFIG_TLS), mbedtls) + OBJS += ../src/crypto/sha384-kdf.o + endif ++endif + ifdef NEED_HMAC_SHA512_KDF + CFLAGS += -DCONFIG_HMAC_SHA512_KDF ++ifneq ($(CONFIG_TLS), mbedtls) + OBJS += ../src/crypto/sha512-kdf.o + endif ++endif + OBJS += $(SHA256OBJS) + ifdef NEED_SHA384 + ifneq ($(CONFIG_TLS), openssl) + ifneq ($(CONFIG_TLS), linux) + ifneq ($(CONFIG_TLS), gnutls) + ifneq ($(CONFIG_TLS), wolfssl) ++ifneq ($(CONFIG_TLS), mbedtls) + OBJS += ../src/crypto/sha384.o + endif + endif + endif + endif ++endif + CFLAGS += -DCONFIG_SHA384 ++ifneq ($(CONFIG_TLS), mbedtls) + OBJS += ../src/crypto/sha384-prf.o + endif ++endif + ifdef NEED_SHA512 + ifneq ($(CONFIG_TLS), openssl) + ifneq ($(CONFIG_TLS), linux) + ifneq ($(CONFIG_TLS), gnutls) + ifneq ($(CONFIG_TLS), wolfssl) ++ifneq ($(CONFIG_TLS), mbedtls) + OBJS += ../src/crypto/sha512.o + endif + endif + endif + endif ++endif + CFLAGS += -DCONFIG_SHA512 ++ifneq ($(CONFIG_TLS), mbedtls) + OBJS += ../src/crypto/sha512-prf.o + endif ++endif + + ifdef NEED_ASN1 + OBJS += ../src/tls/asn1.o +@@ -1756,10 +1828,12 @@ ifdef CONFIG_FIPS + CFLAGS += -DCONFIG_FIPS + ifneq ($(CONFIG_TLS), openssl) + ifneq ($(CONFIG_TLS), wolfssl) ++ifneq ($(CONFIG_TLS), mbedtls) + $(error CONFIG_FIPS=y requires CONFIG_TLS=openssl) + endif + endif + endif ++endif + + OBJS += $(SHA1OBJS) $(DESOBJS) + +--- a/wpa_supplicant/defconfig ++++ b/wpa_supplicant/defconfig +@@ -10,8 +10,8 @@ + # to override previous values of the variables. + + +-# Uncomment following two lines and fix the paths if you have installed OpenSSL +-# or GnuTLS in non-default location ++# Uncomment following two lines and fix the paths if you have installed TLS ++# libraries in a non-default location + #CFLAGS += -I/usr/local/openssl/include + #LIBS += -L/usr/local/openssl/lib + +@@ -20,6 +20,7 @@ + # used to fix build issues on such systems (krb5.h not found). + #CFLAGS += -I/usr/include/kerberos + ++ + # Driver interface for generic Linux wireless extensions + # Note: WEXT is deprecated in the current Linux kernel version and no new + # functionality is added to it. nl80211-based interface is the new +@@ -326,6 +327,7 @@ CONFIG_BACKEND=file + # openssl = OpenSSL (default) + # gnutls = GnuTLS + # internal = Internal TLSv1 implementation (experimental) ++# mbedtls = mbed TLS + # linux = Linux kernel AF_ALG and internal TLSv1 implementation (experimental) + # none = Empty template + #CONFIG_TLS=openssl diff --git a/feeds/ipq95xx/hostapd/patches/120-mbedtls-fips186_2_prf.patch b/feeds/ipq95xx/hostapd/patches/120-mbedtls-fips186_2_prf.patch new file mode 100644 index 000000000..a48725264 --- /dev/null +++ b/feeds/ipq95xx/hostapd/patches/120-mbedtls-fips186_2_prf.patch @@ -0,0 +1,114 @@ +From c8dba4bd750269bcc80fed3d546e2077cb4cdf0e Mon Sep 17 00:00:00 2001 +From: Glenn Strauss +Date: Tue, 19 Jul 2022 20:02:21 -0400 +Subject: [PATCH 2/7] mbedtls: fips186_2_prf() + +Signed-off-by: Glenn Strauss +--- + hostapd/Makefile | 4 --- + src/crypto/crypto_mbedtls.c | 60 +++++++++++++++++++++++++++++++++++++ + wpa_supplicant/Makefile | 4 --- + 3 files changed, 60 insertions(+), 8 deletions(-) + +--- a/hostapd/Makefile ++++ b/hostapd/Makefile +@@ -759,10 +759,6 @@ endif + OBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o + HOBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o + SOBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o +-ifdef NEED_FIPS186_2_PRF +-OBJS += ../src/crypto/fips_prf_internal.o +-SHA1OBJS += ../src/crypto/sha1-internal.o +-endif + ifeq ($(CONFIG_CRYPTO), mbedtls) + ifdef CONFIG_DPP + LIBS += -lmbedx509 +--- a/src/crypto/crypto_mbedtls.c ++++ b/src/crypto/crypto_mbedtls.c +@@ -132,6 +132,12 @@ + #define CRYPTO_MBEDTLS_HMAC_KDF_SHA512 + #endif + ++#if defined(EAP_SIM) || defined(EAP_SIM_DYNAMIC) || defined(EAP_SERVER_SIM) \ ++ || defined(EAP_AKA) || defined(EAP_AKA_DYNAMIC) || defined(EAP_SERVER_AKA) ++/* EAP_SIM=y EAP_AKA=y */ ++#define CRYPTO_MBEDTLS_FIPS186_2_PRF ++#endif ++ + #if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) \ + || defined(EAP_TEAP) || defined(EAP_TEAP_DYNAMIC) || defined(EAP_SERVER_FAST) + #define CRYPTO_MBEDTLS_SHA1_T_PRF +@@ -813,6 +819,60 @@ int sha1_t_prf(const u8 *key, size_t key + + #endif /* CRYPTO_MBEDTLS_SHA1_T_PRF */ + ++#ifdef CRYPTO_MBEDTLS_FIPS186_2_PRF ++ ++/* fips_prf_internal.c sha1-internal.c */ ++ ++/* used only by src/eap_common/eap_sim_common.c:eap_sim_prf() ++ * for eap_sim_derive_keys() and eap_sim_derive_keys_reauth() ++ * where xlen is 160 */ ++ ++int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) ++{ ++ /* FIPS 186-2 + change notice 1 */ ++ ++ mbedtls_sha1_context ctx; ++ u8 * const xkey = ctx.MBEDTLS_PRIVATE(buffer); ++ u32 * const xstate = ctx.MBEDTLS_PRIVATE(state); ++ const u32 xstate_init[] = ++ { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 }; ++ ++ mbedtls_sha1_init(&ctx); ++ os_memcpy(xkey, seed, seed_len < 64 ? seed_len : 64); ++ ++ /* note: does not fill extra bytes if (xlen % 20) (SHA1_MAC_LEN) */ ++ for (; xlen >= 20; xlen -= 20) { ++ /* XSEED_j = 0 */ ++ /* XVAL = (XKEY + XSEED_j) mod 2^b */ ++ ++ /* w_i = G(t, XVAL) */ ++ os_memcpy(xstate, xstate_init, sizeof(xstate_init)); ++ mbedtls_internal_sha1_process(&ctx, xkey); ++ ++ #if __BYTE_ORDER == __LITTLE_ENDIAN ++ xstate[0] = host_to_be32(xstate[0]); ++ xstate[1] = host_to_be32(xstate[1]); ++ xstate[2] = host_to_be32(xstate[2]); ++ xstate[3] = host_to_be32(xstate[3]); ++ xstate[4] = host_to_be32(xstate[4]); ++ #endif ++ os_memcpy(x, xstate, 20); ++ if (xlen == 20) /*(done; skip prep for next loop)*/ ++ break; ++ ++ /* XKEY = (1 + XKEY + w_i) mod 2^b */ ++ for (u32 carry = 1, k = 20; k-- > 0; carry >>= 8) ++ xkey[k] = (carry += xkey[k] + x[k]) & 0xff; ++ x += 20; ++ /* x_j = w_0|w_1 (each pair of iterations through loop)*/ ++ } ++ ++ mbedtls_sha1_free(&ctx); ++ return 0; ++} ++ ++#endif /* CRYPTO_MBEDTLS_FIPS186_2_PRF */ ++ + #endif /* MBEDTLS_SHA1_C */ + + +--- a/wpa_supplicant/Makefile ++++ b/wpa_supplicant/Makefile +@@ -1174,10 +1174,6 @@ endif + OBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o + OBJS_p += ../src/crypto/crypto_$(CONFIG_CRYPTO).o + OBJS_priv += ../src/crypto/crypto_$(CONFIG_CRYPTO).o +-ifdef NEED_FIPS186_2_PRF +-OBJS += ../src/crypto/fips_prf_internal.o +-SHA1OBJS += ../src/crypto/sha1-internal.o +-endif + ifeq ($(CONFIG_CRYPTO), mbedtls) + LIBS += -lmbedcrypto + LIBS_p += -lmbedcrypto diff --git a/feeds/ipq95xx/hostapd/patches/130-mbedtls-annotate-with-TEST_FAIL-for-hwsim-tests.patch b/feeds/ipq95xx/hostapd/patches/130-mbedtls-annotate-with-TEST_FAIL-for-hwsim-tests.patch new file mode 100644 index 000000000..ae7620b90 --- /dev/null +++ b/feeds/ipq95xx/hostapd/patches/130-mbedtls-annotate-with-TEST_FAIL-for-hwsim-tests.patch @@ -0,0 +1,421 @@ +From 31bd19e0e0254b910cccfd3ddc6a6a9222bbcfc0 Mon Sep 17 00:00:00 2001 +From: Glenn Strauss +Date: Sun, 9 Oct 2022 05:12:17 -0400 +Subject: [PATCH 3/7] mbedtls: annotate with TEST_FAIL() for hwsim tests + +Signed-off-by: Glenn Strauss +--- + src/crypto/crypto_mbedtls.c | 124 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 124 insertions(+) + +--- a/src/crypto/crypto_mbedtls.c ++++ b/src/crypto/crypto_mbedtls.c +@@ -280,6 +280,9 @@ __attribute_noinline__ + static int md_vector(size_t num_elem, const u8 *addr[], const size_t *len, + u8 *mac, mbedtls_md_type_t md_type) + { ++ if (TEST_FAIL()) ++ return -1; ++ + mbedtls_md_context_t ctx; + mbedtls_md_init(&ctx); + if (mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 0) != 0){ +@@ -343,6 +346,9 @@ __attribute_noinline__ + static int sha384_512_vector(size_t num_elem, const u8 *addr[], + const size_t *len, u8 *mac, int is384) + { ++ if (TEST_FAIL()) ++ return -1; ++ + struct mbedtls_sha512_context ctx; + mbedtls_sha512_init(&ctx); + #if MBEDTLS_VERSION_MAJOR >= 3 +@@ -375,6 +381,9 @@ int sha384_vector(size_t num_elem, const + #include + int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) + { ++ if (TEST_FAIL()) ++ return -1; ++ + struct mbedtls_sha256_context ctx; + mbedtls_sha256_init(&ctx); + #if MBEDTLS_VERSION_MAJOR >= 3 +@@ -397,6 +406,9 @@ int sha256_vector(size_t num_elem, const + #include + int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) + { ++ if (TEST_FAIL()) ++ return -1; ++ + struct mbedtls_sha1_context ctx; + mbedtls_sha1_init(&ctx); + #if MBEDTLS_VERSION_MAJOR >= 3 +@@ -419,6 +431,9 @@ int sha1_vector(size_t num_elem, const u + #include + int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) + { ++ if (TEST_FAIL()) ++ return -1; ++ + struct mbedtls_md5_context ctx; + mbedtls_md5_init(&ctx); + #if MBEDTLS_VERSION_MAJOR >= 3 +@@ -441,6 +456,9 @@ int md5_vector(size_t num_elem, const u8 + #include + int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) + { ++ if (TEST_FAIL()) ++ return -1; ++ + struct mbedtls_md4_context ctx; + mbedtls_md4_init(&ctx); + mbedtls_md4_starts_ret(&ctx); +@@ -460,6 +478,9 @@ static int hmac_vector(const u8 *key, si + const u8 *addr[], const size_t *len, u8 *mac, + mbedtls_md_type_t md_type) + { ++ if (TEST_FAIL()) ++ return -1; ++ + mbedtls_md_context_t ctx; + mbedtls_md_init(&ctx); + if (mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 1) != 0){ +@@ -571,6 +592,9 @@ static int hmac_kdf_expand(const u8 *prk + const char *label, const u8 *info, size_t info_len, + u8 *okm, size_t okm_len, mbedtls_md_type_t md_type) + { ++ if (TEST_FAIL()) ++ return -1; ++ + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type); + #ifdef MBEDTLS_HKDF_C + if (label == NULL) /* RFC 5869 HKDF-Expand when (label == NULL) */ +@@ -663,6 +687,9 @@ static int hmac_prf_bits(const u8 *key, + const u8 *data, size_t data_len, u8 *buf, + size_t buf_len_bits, mbedtls_md_type_t md_type) + { ++ if (TEST_FAIL()) ++ return -1; ++ + mbedtls_md_context_t ctx; + mbedtls_md_init(&ctx); + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type); +@@ -938,6 +965,9 @@ int pbkdf2_sha1(const char *passphrase, + + static void *aes_crypt_init_mode(const u8 *key, size_t len, int mode) + { ++ if (TEST_FAIL()) ++ return NULL; ++ + mbedtls_aes_context *aes = os_malloc(sizeof(*aes)); + if (!aes) + return NULL; +@@ -996,6 +1026,9 @@ void aes_decrypt_deinit(void *ctx) + /* aes-wrap.c */ + int aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, u8 *cipher) + { ++ if (TEST_FAIL()) ++ return -1; ++ + mbedtls_nist_kw_context ctx; + mbedtls_nist_kw_init(&ctx); + size_t olen; +@@ -1010,6 +1043,9 @@ int aes_wrap(const u8 *kek, size_t kek_l + /* aes-unwrap.c */ + int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher, u8 *plain) + { ++ if (TEST_FAIL()) ++ return -1; ++ + mbedtls_nist_kw_context ctx; + mbedtls_nist_kw_init(&ctx); + size_t olen; +@@ -1041,6 +1077,9 @@ int omac1_aes_vector( + const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], + const size_t *len, u8 *mac) + { ++ if (TEST_FAIL()) ++ return -1; ++ + mbedtls_cipher_type_t cipher_type; + switch (key_len) { + case 16: cipher_type = MBEDTLS_CIPHER_AES_128_ECB; break; +@@ -1103,6 +1142,9 @@ int omac1_aes_256(const u8 *key, const u + /* aes-encblock.c */ + int aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out) + { ++ if (TEST_FAIL()) ++ return -1; ++ + mbedtls_aes_context aes; + mbedtls_aes_init(&aes); + int ret = mbedtls_aes_setkey_enc(&aes, key, 128) +@@ -1118,6 +1160,9 @@ int aes_128_encrypt_block(const u8 *key, + int aes_ctr_encrypt(const u8 *key, size_t key_len, const u8 *nonce, + u8 *data, size_t data_len) + { ++ if (TEST_FAIL()) ++ return -1; ++ + unsigned char counter[MBEDTLS_AES_BLOCK_SIZE]; + unsigned char stream_block[MBEDTLS_AES_BLOCK_SIZE]; + os_memcpy(counter, nonce, MBEDTLS_AES_BLOCK_SIZE);/*(must be writable)*/ +@@ -1160,11 +1205,17 @@ static int aes_128_cbc_oper(const u8 *ke + + int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) + { ++ if (TEST_FAIL()) ++ return -1; ++ + return aes_128_cbc_oper(key, iv, data, data_len, MBEDTLS_AES_ENCRYPT); + } + + int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) + { ++ if (TEST_FAIL()) ++ return -1; ++ + return aes_128_cbc_oper(key, iv, data, data_len, MBEDTLS_AES_DECRYPT); + } + +@@ -1407,6 +1458,10 @@ int crypto_hash_finish(struct crypto_has + } + mbedtls_md_free(mctx); + os_free(mctx); ++ ++ if (TEST_FAIL()) ++ return -1; ++ + return 0; + } + +@@ -1421,6 +1476,9 @@ int crypto_hash_finish(struct crypto_has + + struct crypto_bignum *crypto_bignum_init(void) + { ++ if (TEST_FAIL()) ++ return NULL; ++ + mbedtls_mpi *bn = os_malloc(sizeof(*bn)); + if (bn) + mbedtls_mpi_init(bn); +@@ -1429,6 +1487,9 @@ struct crypto_bignum *crypto_bignum_init + + struct crypto_bignum *crypto_bignum_init_set(const u8 *buf, size_t len) + { ++ if (TEST_FAIL()) ++ return NULL; ++ + mbedtls_mpi *bn = os_malloc(sizeof(*bn)); + if (bn) { + mbedtls_mpi_init(bn); +@@ -1442,6 +1503,9 @@ struct crypto_bignum *crypto_bignum_init + + struct crypto_bignum *crypto_bignum_init_uint(unsigned int val) + { ++ if (TEST_FAIL()) ++ return NULL; ++ + #if 0 /*(hostap use of this interface passes int, not uint)*/ + val = host_to_be32(val); + return crypto_bignum_init_set((const u8 *)&val, sizeof(val)); +@@ -1467,6 +1531,9 @@ void crypto_bignum_deinit(struct crypto_ + int crypto_bignum_to_bin(const struct crypto_bignum *a, + u8 *buf, size_t buflen, size_t padlen) + { ++ if (TEST_FAIL()) ++ return -1; ++ + size_t n = mbedtls_mpi_size((mbedtls_mpi *)a); + if (n < padlen) + n = padlen; +@@ -1477,6 +1544,9 @@ int crypto_bignum_to_bin(const struct cr + + int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m) + { ++ if (TEST_FAIL()) ++ return -1; ++ + /*assert(r != m);*//* r must not be same as m for mbedtls_mpi_random()*/ + #if MBEDTLS_VERSION_NUMBER >= 0x021B0000 /* mbedtls 2.27.0 */ + return mbedtls_mpi_random((mbedtls_mpi *)r, 0, (mbedtls_mpi *)m, +@@ -1513,6 +1583,9 @@ int crypto_bignum_exptmod(const struct c + const struct crypto_bignum *c, + struct crypto_bignum *d) + { ++ if (TEST_FAIL()) ++ return -1; ++ + /* (check if input params match d; d is the result) */ + /* (a == d) is ok in current mbedtls implementation */ + if (b == d || c == d) { /*(not ok; store result in intermediate)*/ +@@ -1540,6 +1613,9 @@ int crypto_bignum_inverse(const struct c + const struct crypto_bignum *b, + struct crypto_bignum *c) + { ++ if (TEST_FAIL()) ++ return -1; ++ + return mbedtls_mpi_inv_mod((mbedtls_mpi *)c, + (const mbedtls_mpi *)a, + (const mbedtls_mpi *)b) ? -1 : 0; +@@ -1549,6 +1625,9 @@ int crypto_bignum_sub(const struct crypt + const struct crypto_bignum *b, + struct crypto_bignum *c) + { ++ if (TEST_FAIL()) ++ return -1; ++ + return mbedtls_mpi_sub_mpi((mbedtls_mpi *)c, + (const mbedtls_mpi *)a, + (const mbedtls_mpi *)b) ? -1 : 0; +@@ -1558,6 +1637,9 @@ int crypto_bignum_div(const struct crypt + const struct crypto_bignum *b, + struct crypto_bignum *c) + { ++ if (TEST_FAIL()) ++ return -1; ++ + /*(most current use of this crypto.h interface has a == c (result), + * so store result in an intermediate to avoid overwritten input)*/ + mbedtls_mpi R; +@@ -1575,6 +1657,9 @@ int crypto_bignum_addmod(const struct cr + const struct crypto_bignum *c, + struct crypto_bignum *d) + { ++ if (TEST_FAIL()) ++ return -1; ++ + return mbedtls_mpi_add_mpi((mbedtls_mpi *)d, + (const mbedtls_mpi *)a, + (const mbedtls_mpi *)b) +@@ -1588,6 +1673,9 @@ int crypto_bignum_mulmod(const struct cr + const struct crypto_bignum *c, + struct crypto_bignum *d) + { ++ if (TEST_FAIL()) ++ return -1; ++ + return mbedtls_mpi_mul_mpi((mbedtls_mpi *)d, + (const mbedtls_mpi *)a, + (const mbedtls_mpi *)b) +@@ -1600,6 +1688,9 @@ int crypto_bignum_sqrmod(const struct cr + const struct crypto_bignum *b, + struct crypto_bignum *c) + { ++ if (TEST_FAIL()) ++ return -1; ++ + #if 1 + return crypto_bignum_mulmod(a, a, b, c); + #else +@@ -1650,6 +1741,9 @@ int crypto_bignum_is_odd(const struct cr + int crypto_bignum_legendre(const struct crypto_bignum *a, + const struct crypto_bignum *p) + { ++ if (TEST_FAIL()) ++ return -2; ++ + /* Security Note: + * mbedtls_mpi_exp_mod() is not documented to run in constant time, + * though mbedtls/library/bignum.c uses constant_time_internal.h funcs. +@@ -1702,6 +1796,9 @@ int crypto_mod_exp(const u8 *base, size_ + const u8 *modulus, size_t modulus_len, + u8 *result, size_t *result_len) + { ++ if (TEST_FAIL()) ++ return -1; ++ + mbedtls_mpi bn_base, bn_exp, bn_modulus, bn_result; + mbedtls_mpi_init(&bn_base); + mbedtls_mpi_init(&bn_exp); +@@ -1769,6 +1866,9 @@ static int crypto_mbedtls_dh_init_public + int crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey, + u8 *pubkey) + { ++ if (TEST_FAIL()) ++ return -1; ++ + #if 0 /*(crypto_dh_init() duplicated (and identical) in crypto_*.c modules)*/ + size_t pubkey_len, pad; + +@@ -1810,6 +1910,9 @@ int crypto_dh_derive_secret(u8 generator + const u8 *pubkey, size_t pubkey_len, + u8 *secret, size_t *len) + { ++ if (TEST_FAIL()) ++ return -1; ++ + #if 0 + if (pubkey_len > prime_len || + (pubkey_len == prime_len && +@@ -2512,6 +2615,9 @@ const struct crypto_ec_point * crypto_ec + + struct crypto_ec_point *crypto_ec_point_init(struct crypto_ec *e) + { ++ if (TEST_FAIL()) ++ return NULL; ++ + mbedtls_ecp_point *p = os_malloc(sizeof(*p)); + if (p != NULL) + mbedtls_ecp_point_init(p); +@@ -2536,6 +2642,9 @@ int crypto_ec_point_x(struct crypto_ec * + int crypto_ec_point_to_bin(struct crypto_ec *e, + const struct crypto_ec_point *point, u8 *x, u8 *y) + { ++ if (TEST_FAIL()) ++ return -1; ++ + /* crypto.h documents crypto_ec_point_to_bin() output is big-endian */ + size_t len = CRYPTO_EC_plen(e); + if (x) { +@@ -2563,6 +2672,9 @@ int crypto_ec_point_to_bin(struct crypto + struct crypto_ec_point * crypto_ec_point_from_bin(struct crypto_ec *e, + const u8 *val) + { ++ if (TEST_FAIL()) ++ return NULL; ++ + size_t len = CRYPTO_EC_plen(e); + mbedtls_ecp_point *p = os_malloc(sizeof(*p)); + u8 buf[1+MBEDTLS_MPI_MAX_SIZE*2]; +@@ -2615,6 +2727,9 @@ int crypto_ec_point_add(struct crypto_ec + const struct crypto_ec_point *b, + struct crypto_ec_point *c) + { ++ if (TEST_FAIL()) ++ return -1; ++ + /* mbedtls does not provide an mbedtls_ecp_point add function */ + mbedtls_mpi one; + mbedtls_mpi_init(&one); +@@ -2631,6 +2746,9 @@ int crypto_ec_point_mul(struct crypto_ec + const struct crypto_bignum *b, + struct crypto_ec_point *res) + { ++ if (TEST_FAIL()) ++ return -1; ++ + return mbedtls_ecp_mul( + (mbedtls_ecp_group *)e, (mbedtls_ecp_point *)res, + (const mbedtls_mpi *)b, (const mbedtls_ecp_point *)p, +@@ -2639,6 +2757,9 @@ int crypto_ec_point_mul(struct crypto_ec + + int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p) + { ++ if (TEST_FAIL()) ++ return -1; ++ + if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e) + == MBEDTLS_ECP_TYPE_MONTGOMERY) { + /* e.g. MBEDTLS_ECP_DP_CURVE25519 and MBEDTLS_ECP_DP_CURVE448 */ +@@ -2751,6 +2872,9 @@ struct crypto_bignum * + crypto_ec_point_compute_y_sqr(struct crypto_ec *e, + const struct crypto_bignum *x) + { ++ if (TEST_FAIL()) ++ return NULL; ++ + mbedtls_mpi *y2 = os_malloc(sizeof(*y2)); + if (y2 == NULL) + return NULL; diff --git a/feeds/ipq95xx/hostapd/patches/135-mbedtls-fix-owe-association.patch b/feeds/ipq95xx/hostapd/patches/135-mbedtls-fix-owe-association.patch new file mode 100644 index 000000000..0c29432d3 --- /dev/null +++ b/feeds/ipq95xx/hostapd/patches/135-mbedtls-fix-owe-association.patch @@ -0,0 +1,91 @@ +The code for hostapd-mbedtls did not work when used for OWE association. + +When handling association requests, the buffer offsets and length assumptions were incorrect, leading to never calculating the y point, thus denying association. + +Also when crafting the association response, the buffer contained the trailing key-type. + +Fix up both issues to adhere to the specification and make hostapd-mbedtls work with the OWE security type. + +--- a/src/crypto/crypto_mbedtls.c ++++ b/src/crypto/crypto_mbedtls.c +@@ -2299,25 +2299,30 @@ struct crypto_ecdh * crypto_ecdh_init2(i + struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh, int inc_y) + { + mbedtls_ecp_group *grp = &ecdh->grp; +- size_t len = CRYPTO_EC_plen(grp); ++ size_t prime_len = CRYPTO_EC_plen(grp); ++ size_t output_len = prime_len; ++ u8 output_offset = 0; ++ u8 buf[256]; ++ + #ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED + /* len */ + #endif + #ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED +- if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) +- len = inc_y ? len*2+1 : len+1; ++ if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { ++ output_len = inc_y ? prime_len * 2 + 1 : prime_len + 1; ++ output_offset = 1; ++ } + #endif +- struct wpabuf *buf = wpabuf_alloc(len); +- if (buf == NULL) ++ ++ if (output_len > sizeof(buf)) + return NULL; ++ + inc_y = inc_y ? MBEDTLS_ECP_PF_UNCOMPRESSED : MBEDTLS_ECP_PF_COMPRESSED; +- if (mbedtls_ecp_point_write_binary(grp, &ecdh->Q, inc_y, &len, +- wpabuf_mhead_u8(buf), len) == 0) { +- wpabuf_put(buf, len); +- return buf; ++ if (mbedtls_ecp_point_write_binary(grp, &ecdh->Q, inc_y, &output_len, ++ buf, output_len) == 0) { ++ return wpabuf_alloc_copy(buf + output_offset, output_len - output_offset); + } + +- wpabuf_free(buf); + return NULL; + } + +@@ -2379,10 +2384,7 @@ struct wpabuf * crypto_ecdh_set_peerkey( + os_memcpy(buf+2, key, len); + } + len >>= 1; /*(repurpose len to prime_len)*/ +- } +- else if (key[0] == 0x02 || key[0] == 0x03) { /* (inc_y == 0) */ +- --len; /*(repurpose len to prime_len)*/ +- ++ } else { /* (inc_y == 0) */ + /* mbedtls_ecp_point_read_binary() does not currently support + * MBEDTLS_ECP_PF_COMPRESSED format (buf[1] = 0x02 or 0x03) + * (returns MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) */ +@@ -2390,22 +2392,21 @@ struct wpabuf * crypto_ecdh_set_peerkey( + /* derive y, amend buf[] with y for UNCOMPRESSED format */ + if (sizeof(buf)-2 < len*2 || len == 0) + return NULL; ++ + buf[0] = (u8)(1+len*2); + buf[1] = 0x04; ++ os_memcpy(buf+2, key, len); ++ + mbedtls_mpi bn; + mbedtls_mpi_init(&bn); +- int ret = mbedtls_mpi_read_binary(&bn, key+1, len) +- || crypto_mbedtls_short_weierstrass_derive_y(grp, &bn, +- key[0] & 1) ++ int ret = mbedtls_mpi_read_binary(&bn, key, len) ++ || crypto_mbedtls_short_weierstrass_derive_y(grp, &bn, 0) + || mbedtls_mpi_write_binary(&bn, buf+2+len, len); + mbedtls_mpi_free(&bn); + if (ret != 0) + return NULL; + } + +- if (key[0] == 0) /*(repurpose len to prime_len)*/ +- len = CRYPTO_EC_plen(grp); +- + if (mbedtls_ecdh_read_public(&ecdh->ctx, buf, buf[0]+1)) + return NULL; + } diff --git a/feeds/ipq95xx/hostapd/patches/140-tests-Makefile-make-run-tests-with-CONFIG_TLS.patch b/feeds/ipq95xx/hostapd/patches/140-tests-Makefile-make-run-tests-with-CONFIG_TLS.patch new file mode 100644 index 000000000..e967cff42 --- /dev/null +++ b/feeds/ipq95xx/hostapd/patches/140-tests-Makefile-make-run-tests-with-CONFIG_TLS.patch @@ -0,0 +1,1358 @@ +From f24933dc175e0faf44a3cce3330c256a59649ca6 Mon Sep 17 00:00:00 2001 +From: Glenn Strauss +Date: Tue, 19 Jul 2022 23:01:17 -0400 +Subject: [PATCH 4/7] tests/Makefile make run-tests with CONFIG_TLS=... + +add test-crypto_module.c to run crypto_module_tests() + +adjust some tests/hwsim/*.py for mbed TLS (work in progress) + +option to build and run-tests with CONFIG_TLS=internal # (default) +$ cd tests; make clean +$ make run-tests + +option to build and run-tests with CONFIG_TLS=gnutls +$ cd tests; make clean CONFIG_TLS=gnutls +$ make run-tests CONFIG_TLS=gnutls + +option to build and run-tests with CONFIG_TLS=mbedtls +$ cd tests; make clean CONFIG_TLS=mbedtls +$ make run-tests CONFIG_TLS=mbedtls + +option to build and run-tests with CONFIG_TLS=openssl +$ cd tests; make clean CONFIG_TLS=openssl +$ make run-tests CONFIG_TLS=openssl + +option to build and run-tests with CONFIG_TLS=wolfssl +$ cd tests; make clean CONFIG_TLS=wolfssl +$ make run-tests CONFIG_TLS=wolfssl + +RFE: Makefile logic for crypto objects should be centralized + instead of being duplicated in hostapd/Makefile, + wpa_supplicant/Makefile, src/crypto/Makefile, + tests/Makefile, ... + +Signed-off-by: Glenn Strauss +--- + hostapd/Makefile | 6 + + src/crypto/Makefile | 129 ++++++++++++++++++++- + src/crypto/crypto_module_tests.c | 134 ++++++++++++++++++++++ + src/tls/Makefile | 11 ++ + tests/Makefile | 75 +++++++++--- + tests/hwsim/example-hostapd.config | 11 +- + tests/hwsim/example-wpa_supplicant.config | 12 +- + tests/hwsim/test_ap_eap.py | 114 +++++++++++++----- + tests/hwsim/test_ap_ft.py | 4 +- + tests/hwsim/test_authsrv.py | 9 +- + tests/hwsim/test_dpp.py | 19 ++- + tests/hwsim/test_erp.py | 16 +-- + tests/hwsim/test_fils.py | 5 +- + tests/hwsim/test_pmksa_cache.py | 4 +- + tests/hwsim/test_sae.py | 7 ++ + tests/hwsim/test_suite_b.py | 3 + + tests/hwsim/test_wpas_ctrl.py | 2 +- + tests/hwsim/utils.py | 8 +- + tests/test-crypto_module.c | 16 +++ + tests/test-https.c | 12 +- + tests/test-https_server.c | 12 +- + wpa_supplicant/Makefile | 6 + + 22 files changed, 524 insertions(+), 91 deletions(-) + create mode 100644 tests/test-crypto_module.c + +--- a/hostapd/Makefile ++++ b/hostapd/Makefile +@@ -696,6 +696,7 @@ CFLAGS += -DCONFIG_TLSV12 + endif + + ifeq ($(CONFIG_TLS), wolfssl) ++CFLAGS += -DCONFIG_TLS_WOLFSSL + CONFIG_CRYPTO=wolfssl + ifdef TLS_FUNCS + OBJS += ../src/crypto/tls_wolfssl.o +@@ -716,6 +717,7 @@ endif + endif + + ifeq ($(CONFIG_TLS), openssl) ++CFLAGS += -DCONFIG_TLS_OPENSSL + CFLAGS += -DCRYPTO_RSA_OAEP_SHA256 + CONFIG_CRYPTO=openssl + ifdef TLS_FUNCS +@@ -746,6 +748,7 @@ CFLAGS += -DTLS_DEFAULT_CIPHERS=\"$(CONF + endif + + ifeq ($(CONFIG_TLS), mbedtls) ++CFLAGS += -DCONFIG_TLS_MBEDTLS + ifndef CONFIG_CRYPTO + CONFIG_CRYPTO=mbedtls + endif +@@ -776,6 +779,7 @@ endif + endif + + ifeq ($(CONFIG_TLS), gnutls) ++CFLAGS += -DCONFIG_TLS_GNUTLS + ifndef CONFIG_CRYPTO + # default to libgcrypt + CONFIG_CRYPTO=gnutls +@@ -806,6 +810,7 @@ endif + endif + + ifeq ($(CONFIG_TLS), internal) ++CFLAGS += -DCONFIG_TLS_INTERNAL + ifndef CONFIG_CRYPTO + CONFIG_CRYPTO=internal + endif +@@ -884,6 +889,7 @@ endif + endif + + ifeq ($(CONFIG_TLS), linux) ++CFLAGS += -DCONFIG_TLS_INTERNAL + OBJS += ../src/crypto/crypto_linux.o + ifdef TLS_FUNCS + OBJS += ../src/crypto/crypto_internal-rsa.o +--- a/src/crypto/Makefile ++++ b/src/crypto/Makefile +@@ -1,10 +1,121 @@ +-CFLAGS += -DCONFIG_CRYPTO_INTERNAL +-CFLAGS += -DCONFIG_TLS_INTERNAL_CLIENT +-CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER + #CFLAGS += -DALL_DH_GROUPS + CFLAGS += -DCONFIG_SHA256 + CFLAGS += -DCONFIG_SHA384 ++CFLAGS += -DCONFIG_HMAC_SHA256_KDF + CFLAGS += -DCONFIG_HMAC_SHA384_KDF ++ ++# crypto_module_tests.c ++CFLAGS += -DCONFIG_MODULE_TESTS ++CFLAGS += -DCONFIG_DPP ++#CFLAGS += -DCONFIG_DPP2 ++#CFLAGS += -DCONFIG_DPP3 ++CFLAGS += -DCONFIG_ECC ++CFLAGS += -DCONFIG_MESH ++CFLAGS += -DEAP_PSK ++CFLAGS += -DEAP_FAST ++ ++ifeq ($(CONFIG_TLS),mbedtls) ++ ++# (enable features for 'cd tests; make run-tests CONFIG_TLS=mbedtls') ++CFLAGS += -DCRYPTO_RSA_OAEP_SHA256 ++CFLAGS += -DCONFIG_DES ++CFLAGS += -DEAP_IKEV2 ++CFLAGS += -DEAP_MSCHAPv2 ++CFLAGS += -DEAP_SIM ++ ++LIB_OBJS = tls_mbedtls.o crypto_mbedtls.o ++LIB_OBJS+= \ ++ aes-eax.o \ ++ aes-siv.o \ ++ dh_groups.o \ ++ milenage.o \ ++ ms_funcs.o ++ ++else ++ifeq ($(CONFIG_TLS),openssl) ++ ++# (enable features for 'cd tests; make run-tests CONFIG_TLS=openssl') ++ifndef CONFIG_TLS_DEFAULT_CIPHERS ++CONFIG_TLS_DEFAULT_CIPHERS = "DEFAULT:!EXP:!LOW" ++endif ++CFLAGS += -DTLS_DEFAULT_CIPHERS=\"$(CONFIG_TLS_DEFAULT_CIPHERS)\" ++CFLAGS += -DCRYPTO_RSA_OAEP_SHA256 ++CFLAGS += -DEAP_TLS_OPENSSL ++ ++LIB_OBJS = tls_openssl.o fips_prf_openssl.o crypto_openssl.o ++LIB_OBJS+= \ ++ aes-ctr.o \ ++ aes-eax.o \ ++ aes-encblock.o \ ++ aes-siv.o \ ++ dh_groups.o \ ++ milenage.o \ ++ ms_funcs.o \ ++ sha1-prf.o \ ++ sha1-tlsprf.o \ ++ sha1-tprf.o \ ++ sha256-kdf.o \ ++ sha256-prf.o \ ++ sha256-tlsprf.o ++ ++else ++ifeq ($(CONFIG_TLS),wolfssl) ++ ++# (wolfssl libraries must be built with ./configure --enable-wpas) ++# (enable features for 'cd tests; make run-tests CONFIG_TLS=wolfssl') ++CFLAGS += -DWOLFSSL_DER_LOAD ++CFLAGS += -DCONFIG_DES ++ ++LIB_OBJS = tls_wolfssl.o fips_prf_wolfssl.o crypto_wolfssl.o ++LIB_OBJS+= \ ++ aes-ctr.o \ ++ aes-eax.o \ ++ aes-encblock.o \ ++ aes-siv.o \ ++ dh_groups.o \ ++ milenage.o \ ++ ms_funcs.o \ ++ sha1-prf.o \ ++ sha1-tlsprf.o \ ++ sha1-tprf.o \ ++ sha256-kdf.o \ ++ sha256-prf.o \ ++ sha256-tlsprf.o ++ ++else ++ifeq ($(CONFIG_TLS),gnutls) ++ ++# (enable features for 'cd tests; make run-tests CONFIG_TLS=gnutls') ++LIB_OBJS = tls_gnutls.o crypto_gnutls.o ++LIB_OBJS+= \ ++ aes-cbc.o \ ++ aes-ctr.o \ ++ aes-eax.o \ ++ aes-encblock.o \ ++ aes-omac1.o \ ++ aes-siv.o \ ++ aes-unwrap.o \ ++ aes-wrap.o \ ++ dh_group5.o \ ++ dh_groups.o \ ++ milenage.o \ ++ ms_funcs.o \ ++ rc4.o \ ++ sha1-pbkdf2.o \ ++ sha1-prf.o \ ++ fips_prf_internal.o \ ++ sha1-internal.o \ ++ sha1-tlsprf.o \ ++ sha1-tprf.o \ ++ sha256-kdf.o \ ++ sha256-prf.o \ ++ sha256-tlsprf.o ++ ++else ++ ++CFLAGS += -DCONFIG_CRYPTO_INTERNAL ++CFLAGS += -DCONFIG_TLS_INTERNAL_CLIENT ++CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER + CFLAGS += -DCONFIG_INTERNAL_SHA384 + + LIB_OBJS= \ +@@ -13,7 +124,6 @@ LIB_OBJS= \ + aes-ctr.o \ + aes-eax.o \ + aes-encblock.o \ +- aes-gcm.o \ + aes-internal.o \ + aes-internal-dec.o \ + aes-internal-enc.o \ +@@ -37,6 +147,7 @@ LIB_OBJS= \ + sha1-tlsprf.o \ + sha1-tprf.o \ + sha256.o \ ++ sha256-kdf.o \ + sha256-prf.o \ + sha256-tlsprf.o \ + sha256-internal.o \ +@@ -53,6 +164,16 @@ LIB_OBJS += crypto_internal-modexp.o + LIB_OBJS += crypto_internal-rsa.o + LIB_OBJS += tls_internal.o + LIB_OBJS += fips_prf_internal.o ++ ++endif ++endif ++endif ++endif ++ ++ ++# (used by wlantest/{bip,gcmp,rx_mgmt}.c and tests/test-aes.c) ++LIB_OBJS += aes-gcm.o ++ + ifndef TEST_FUZZ + LIB_OBJS += random.o + endif +--- a/src/crypto/crypto_module_tests.c ++++ b/src/crypto/crypto_module_tests.c +@@ -2469,6 +2469,139 @@ static int test_hpke(void) + } + + ++static int test_ecc(void) ++{ ++#ifdef CONFIG_ECC ++#ifndef CONFIG_TLS_INTERNAL ++#ifndef CONFIG_TLS_GNUTLS ++#if defined(CONFIG_TLS_MBEDTLS) \ ++ || defined(CONFIG_TLS_OPENSSL) \ ++ || defined(CONFIG_TLS_WOLFSSL) ++ wpa_printf(MSG_INFO, "Testing ECC"); ++ /* Note: some tests below are valid on supported Short Weierstrass ++ * curves, but not on Montgomery curves (e.g. IKE groups 31 and 32) ++ * (e.g. deriving and comparing y^2 test below not valid on Montgomery) ++ */ ++#ifdef CONFIG_TLS_MBEDTLS ++ const int grps[] = {19, 20, 21, 25, 26, 28}; ++#endif ++#ifdef CONFIG_TLS_OPENSSL ++ const int grps[] = {19, 20, 21, 26}; ++#endif ++#ifdef CONFIG_TLS_WOLFSSL ++ const int grps[] = {19, 20, 21, 26}; ++#endif ++ uint32_t i; ++ struct crypto_ec *e = NULL; ++ struct crypto_ec_point *p = NULL, *q = NULL; ++ struct crypto_bignum *x = NULL, *y = NULL; ++#ifdef CONFIG_DPP ++ u8 bin[4096]; ++#endif ++ for (i = 0; i < ARRAY_SIZE(grps); ++i) { ++ e = crypto_ec_init(grps[i]); ++ if (e == NULL ++ || crypto_ec_prime_len(e) == 0 ++ || crypto_ec_prime_len_bits(e) == 0 ++ || crypto_ec_order_len(e) == 0 ++ || crypto_ec_get_prime(e) == NULL ++ || crypto_ec_get_order(e) == NULL ++ || crypto_ec_get_a(e) == NULL ++ || crypto_ec_get_b(e) == NULL ++ || crypto_ec_get_generator(e) == NULL) { ++ break; ++ } ++#ifdef CONFIG_DPP ++ struct crypto_ec_key *key = crypto_ec_key_gen(grps[i]); ++ if (key == NULL) ++ break; ++ p = crypto_ec_key_get_public_key(key); ++ q = crypto_ec_key_get_public_key(key); ++ crypto_ec_key_deinit(key); ++ if (p == NULL || q == NULL) ++ break; ++ if (!crypto_ec_point_is_on_curve(e, p)) ++ break; ++ ++ /* inverted point should not match original; ++ * double-invert should match */ ++ if (crypto_ec_point_invert(e, q) != 0 ++ || crypto_ec_point_cmp(e, p, q) == 0 ++ || crypto_ec_point_invert(e, q) != 0 ++ || crypto_ec_point_cmp(e, p, q) != 0) { ++ break; ++ } ++ ++ /* crypto_ec_point_to_bin() and crypto_ec_point_from_bin() ++ * imbalanced interfaces? */ ++ size_t prime_len = crypto_ec_prime_len(e); ++ if (prime_len * 2 > sizeof(bin)) ++ break; ++ if (crypto_ec_point_to_bin(e, p, bin, bin+prime_len) != 0) ++ break; ++ struct crypto_ec_point *tmp = crypto_ec_point_from_bin(e, bin); ++ if (tmp == NULL) ++ break; ++ if (crypto_ec_point_cmp(e, p, tmp) != 0) { ++ crypto_ec_point_deinit(tmp, 0); ++ break; ++ } ++ crypto_ec_point_deinit(tmp, 0); ++ ++ x = crypto_bignum_init(); ++ y = crypto_bignum_init_set(bin+prime_len, prime_len); ++ if (x == NULL || y == NULL || crypto_ec_point_x(e, p, x) != 0) ++ break; ++ struct crypto_bignum *y2 = crypto_ec_point_compute_y_sqr(e, x); ++ if (y2 == NULL) ++ break; ++ if (crypto_bignum_sqrmod(y, crypto_ec_get_prime(e), y) != 0 ++ || crypto_bignum_cmp(y, y2) != 0) { ++ crypto_bignum_deinit(y2, 0); ++ break; ++ } ++ crypto_bignum_deinit(y2, 0); ++ crypto_bignum_deinit(x, 0); ++ crypto_bignum_deinit(y, 0); ++ x = NULL; ++ y = NULL; ++ ++ x = crypto_bignum_init(); ++ if (x == NULL) ++ break; ++ if (crypto_bignum_rand(x, crypto_ec_get_prime(e)) != 0) ++ break; ++ crypto_bignum_deinit(x, 0); ++ x = NULL; ++ ++ crypto_ec_point_deinit(p, 0); ++ p = NULL; ++ crypto_ec_point_deinit(q, 0); ++ q = NULL; ++#endif /* CONFIG_DPP */ ++ crypto_ec_deinit(e); ++ e = NULL; ++ } ++ if (i != ARRAY_SIZE(grps)) { ++ crypto_bignum_deinit(x, 0); ++ crypto_bignum_deinit(y, 0); ++ crypto_ec_point_deinit(p, 0); ++ crypto_ec_point_deinit(q, 0); ++ crypto_ec_deinit(e); ++ wpa_printf(MSG_INFO, ++ "ECC test case failed tls_id:%d", grps[i]); ++ return -1; ++ } ++ ++ wpa_printf(MSG_INFO, "ECC test cases passed"); ++#endif ++#endif /* !CONFIG_TLS_GNUTLS */ ++#endif /* !CONFIG_TLS_INTERNAL */ ++#endif /* CONFIG_ECC */ ++ return 0; ++} ++ ++ + static int test_ms_funcs(void) + { + #ifndef CONFIG_FIPS +@@ -2590,6 +2723,7 @@ int crypto_module_tests(void) + test_fips186_2_prf() || + test_extract_expand_hkdf() || + test_hpke() || ++ test_ecc() || + test_ms_funcs()) + ret = -1; + +--- a/src/tls/Makefile ++++ b/src/tls/Makefile +@@ -1,3 +1,10 @@ ++LIB_OBJS= asn1.o ++ ++ifneq ($(CONFIG_TLS),gnutls) ++ifneq ($(CONFIG_TLS),mbedtls) ++ifneq ($(CONFIG_TLS),openssl) ++ifneq ($(CONFIG_TLS),wolfssl) ++ + CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH + CFLAGS += -DCONFIG_CRYPTO_INTERNAL + CFLAGS += -DCONFIG_TLSV11 +@@ -21,5 +28,9 @@ LIB_OBJS= \ + tlsv1_server_read.o \ + tlsv1_server_write.o \ + x509v3.o ++endif ++endif ++endif ++endif + + include ../lib.rules +--- a/tests/Makefile ++++ b/tests/Makefile +@@ -1,8 +1,10 @@ +-ALL=test-base64 test-md4 test-milenage \ +- test-rsa-sig-ver \ +- test-sha1 \ +- test-https test-https_server \ +- test-sha256 test-aes test-x509v3 test-list test-rc4 ++RUN_TESTS= \ ++ test-list \ ++ test-md4 test-rc4 test-sha1 test-sha256 \ ++ test-milenage test-aes \ ++ test-crypto_module ++ ++ALL=$(RUN_TESTS) test-base64 test-https test-https_server + + include ../src/build.rules + +@@ -24,13 +26,27 @@ CFLAGS += -DCONFIG_IEEE80211R_AP + CFLAGS += -DCONFIG_IEEE80211R + CFLAGS += -DCONFIG_TDLS + ++# test-crypto_module ++CFLAGS += -DCONFIG_MODULE_TESTS ++CFLAGS += -DCONFIG_DPP ++#CFLAGS += -DCONFIG_DPP2 ++#CFLAGS += -DCONFIG_DPP3 ++CFLAGS += -DCONFIG_ECC ++CFLAGS += -DCONFIG_HMAC_SHA256_KDF ++CFLAGS += -DCONFIG_HMAC_SHA384_KDF ++CFLAGS += -DCONFIG_MESH ++CFLAGS += -DCONFIG_SHA256 ++CFLAGS += -DCONFIG_SHA384 ++CFLAGS += -DEAP_PSK ++CFLAGS += -DEAP_FAST ++ + CFLAGS += -I../src + CFLAGS += -I../src/utils + + SLIBS = ../src/utils/libutils.a + +-DLIBS = ../src/crypto/libcrypto.a \ +- ../src/tls/libtls.a ++DLIBS = ../src/tls/libtls.a \ ++ ../src/crypto/libcrypto.a + + _OBJS_VAR := LLIBS + include ../src/objs.mk +@@ -42,12 +58,43 @@ include ../src/objs.mk + LIBS = $(SLIBS) $(DLIBS) + LLIBS = -Wl,--start-group $(DLIBS) -Wl,--end-group $(SLIBS) + ++ifeq ($(CONFIG_TLS),mbedtls) ++CFLAGS += -DCONFIG_TLS_MBEDTLS ++LLIBS += -lmbedtls -lmbedx509 -lmbedcrypto ++else ++ifeq ($(CONFIG_TLS),openssl) ++CFLAGS += -DCONFIG_TLS_OPENSSL ++LLIBS += -lssl -lcrypto ++else ++ifeq ($(CONFIG_TLS),gnutls) ++CFLAGS += -DCONFIG_TLS_GNUTLS ++LLIBS += -lgnutls -lgpg-error -lgcrypt ++else ++ifeq ($(CONFIG_TLS),wolfssl) ++CFLAGS += -DCONFIG_TLS_WOLFSSL ++LLIBS += -lwolfssl -lm ++else ++CFLAGS += -DCONFIG_TLS_INTERNAL ++CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER ++ALL += test-rsa-sig-ver ++ALL += test-x509v3 ++clean-config_tls_internal: ++ rm -f test_x509v3_nist.out.* ++ rm -f test_x509v3_nist2.out.* ++endif ++endif ++endif ++endif ++ + # glibc < 2.17 needs -lrt for clock_gettime() + LLIBS += -lrt + + test-aes: $(call BUILDOBJ,test-aes.o) $(LIBS) + $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) + ++test-crypto_module: $(call BUILDOBJ,test-crypto_module.o) $(LIBS) ++ $(LDO) $(LDFLAGS) -o $@ $< $(LLIBS) ++ + test-base64: $(call BUILDOBJ,test-base64.o) $(LIBS) + $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) + +@@ -83,17 +130,11 @@ test-x509v3: $(call BUILDOBJ,test-x509v3 + + + run-tests: $(ALL) +- ./test-aes +- ./test-list +- ./test-md4 +- ./test-milenage +- ./test-rsa-sig-ver +- ./test-sha1 +- ./test-sha256 ++ @set -ex; for i in $(RUN_TESTS); do ./$$i; done + @echo + @echo All tests completed successfully. + +-clean: common-clean ++clean: common-clean clean-config_tls_internal + rm -f *~ +- rm -f test_x509v3_nist.out.* +- rm -f test_x509v3_nist2.out.* ++ ++.PHONY: run-tests clean-config_tls_internal +--- a/tests/hwsim/example-hostapd.config ++++ b/tests/hwsim/example-hostapd.config +@@ -34,15 +34,7 @@ CONFIG_EAP_TNC=y + CFLAGS += -DTNC_CONFIG_FILE=\"tnc/tnc_config\" + LIBS += -rdynamic + CONFIG_EAP_UNAUTH_TLS=y +-ifeq ($(CONFIG_TLS), openssl) +-CONFIG_EAP_PWD=y +-endif +-ifeq ($(CONFIG_TLS), wolfssl) +-CONFIG_EAP_PWD=y +-endif +-ifeq ($(CONFIG_TLS), mbedtls) +-CONFIG_EAP_PWD=y +-endif ++CONFIG_EAP_PWD=$(if $(filter openssl wolfssl mbedtls,$(CONFIG_TLS)),y,) + CONFIG_EAP_EKE=y + CONFIG_PKCS12=y + CONFIG_RADIUS_SERVER=y +@@ -89,6 +81,7 @@ CFLAGS += -DCONFIG_RADIUS_TEST + CONFIG_MODULE_TESTS=y + + CONFIG_SUITEB=y ++CONFIG_SUITEB192=$(if $(filter openssl mbedtls,$(CONFIG_TLS)),y,) + + # AddressSanitizer (ASan) can be enabled by uncommenting the following lines. + # This can be used as a more efficient memory error detector than valgrind +--- a/tests/hwsim/example-wpa_supplicant.config ++++ b/tests/hwsim/example-wpa_supplicant.config +@@ -35,16 +35,7 @@ LIBS += -rdynamic + CONFIG_EAP_FAST=y + CONFIG_EAP_TEAP=y + CONFIG_EAP_IKEV2=y +- +-ifeq ($(CONFIG_TLS), openssl) +-CONFIG_EAP_PWD=y +-endif +-ifeq ($(CONFIG_TLS), wolfssl) +-CONFIG_EAP_PWD=y +-endif +-ifeq ($(CONFIG_TLS), mbedtls) +-CONFIG_EAP_PWD=y +-endif ++CONFIG_EAP_PWD=$(if $(filter openssl wolfssl mbedtls,$(CONFIG_TLS)),y,) + + CONFIG_USIM_SIMULATOR=y + CONFIG_SIM_SIMULATOR=y +@@ -137,6 +128,7 @@ CONFIG_TESTING_OPTIONS=y + CONFIG_MODULE_TESTS=y + + CONFIG_SUITEB=y ++CONFIG_SUITEB192=$(if $(filter openssl mbedtls,$(CONFIG_TLS)),y,) + + # AddressSanitizer (ASan) can be enabled by uncommenting the following lines. + # This can be used as a more efficient memory error detector than valgrind +--- a/tests/hwsim/test_ap_eap.py ++++ b/tests/hwsim/test_ap_eap.py +@@ -42,20 +42,42 @@ def check_eap_capa(dev, method): + res = dev.get_capability("eap") + if method not in res: + raise HwsimSkip("EAP method %s not supported in the build" % method) ++ if method == "FAST" or method == "TEAP": ++ tls = dev.request("GET tls_library") ++ if tls.startswith("mbed TLS"): ++ raise HwsimSkip("EAP-%s not supported with this TLS library: " % method + tls) + + def check_subject_match_support(dev): + tls = dev.request("GET tls_library") +- if not tls.startswith("OpenSSL") and not tls.startswith("wolfSSL"): ++ if tls.startswith("OpenSSL"): ++ return ++ elif tls.startswith("wolfSSL"): ++ return ++ elif tls.startswith("mbed TLS"): ++ return ++ else: + raise HwsimSkip("subject_match not supported with this TLS library: " + tls) + + def check_check_cert_subject_support(dev): + tls = dev.request("GET tls_library") +- if not tls.startswith("OpenSSL") and not tls.startswith("wolfSSL"): ++ if tls.startswith("OpenSSL"): ++ return ++ elif tls.startswith("wolfSSL"): ++ return ++ elif tls.startswith("mbed TLS"): ++ return ++ else: + raise HwsimSkip("check_cert_subject not supported with this TLS library: " + tls) + + def check_altsubject_match_support(dev): + tls = dev.request("GET tls_library") +- if not tls.startswith("OpenSSL") and not tls.startswith("wolfSSL"): ++ if tls.startswith("OpenSSL"): ++ return ++ elif tls.startswith("wolfSSL"): ++ return ++ elif tls.startswith("mbed TLS"): ++ return ++ else: + raise HwsimSkip("altsubject_match not supported with this TLS library: " + tls) + + def check_domain_match(dev): +@@ -70,7 +92,13 @@ def check_domain_suffix_match(dev): + + def check_domain_match_full(dev): + tls = dev.request("GET tls_library") +- if not tls.startswith("OpenSSL") and not tls.startswith("wolfSSL"): ++ if tls.startswith("OpenSSL"): ++ return ++ elif tls.startswith("wolfSSL"): ++ return ++ elif tls.startswith("mbed TLS"): ++ return ++ else: + raise HwsimSkip("domain_suffix_match requires full match with this TLS library: " + tls) + + def check_cert_probe_support(dev): +@@ -79,8 +107,15 @@ def check_cert_probe_support(dev): + raise HwsimSkip("Certificate probing not supported with this TLS library: " + tls) + + def check_ext_cert_check_support(dev): ++ if not openssl_imported: ++ raise HwsimSkip("OpenSSL python method not available") ++ + tls = dev.request("GET tls_library") +- if not tls.startswith("OpenSSL"): ++ if tls.startswith("OpenSSL"): ++ return ++ elif tls.startswith("mbed TLS"): ++ return ++ else: + raise HwsimSkip("ext_cert_check not supported with this TLS library: " + tls) + + def check_ocsp_support(dev): +@@ -91,14 +126,18 @@ def check_ocsp_support(dev): + # raise HwsimSkip("OCSP not supported with this TLS library: " + tls) + #if tls.startswith("wolfSSL"): + # raise HwsimSkip("OCSP not supported with this TLS library: " + tls) ++ if tls.startswith("mbed TLS"): ++ raise HwsimSkip("OCSP not supported with this TLS library: " + tls) + + def check_pkcs5_v15_support(dev): + tls = dev.request("GET tls_library") +- if "BoringSSL" in tls or "GnuTLS" in tls: ++ if "BoringSSL" in tls or "GnuTLS" in tls or "mbed TLS" in tls: + raise HwsimSkip("PKCS#5 v1.5 not supported with this TLS library: " + tls) + + def check_tls13_support(dev): + tls = dev.request("GET tls_library") ++ if tls.startswith("mbed TLS"): ++ raise HwsimSkip("TLS v1.3 not supported") + if "run=OpenSSL 1.1.1" not in tls and "run=OpenSSL 3.0" not in tls and "wolfSSL" not in tls: + raise HwsimSkip("TLS v1.3 not supported") + +@@ -118,11 +157,15 @@ def check_pkcs12_support(dev): + # raise HwsimSkip("PKCS#12 not supported with this TLS library: " + tls) + if tls.startswith("wolfSSL"): + raise HwsimSkip("PKCS#12 not supported with this TLS library: " + tls) ++ if tls.startswith("mbed TLS"): ++ raise HwsimSkip("PKCS#12 not supported with this TLS library: " + tls) + + def check_dh_dsa_support(dev): + tls = dev.request("GET tls_library") + if tls.startswith("internal"): + raise HwsimSkip("DH DSA not supported with this TLS library: " + tls) ++ if tls.startswith("mbed TLS"): ++ raise HwsimSkip("DH DSA not supported with this TLS library: " + tls) + + def check_ec_support(dev): + tls = dev.request("GET tls_library") +@@ -1595,7 +1638,7 @@ def test_ap_wpa2_eap_ttls_pap_subject_ma + eap_connect(dev[0], hapd, "TTLS", "pap user", + anonymous_identity="ttls", password="password", + ca_cert="auth_serv/ca.pem", phase2="auth=PAP", +- subject_match="/C=FI/O=w1.fi/CN=server.w1.fi", ++ check_cert_subject="/C=FI/O=w1.fi/CN=server.w1.fi", + altsubject_match="EMAIL:noone@example.com;DNS:server.w1.fi;URI:http://example.com/") + eap_reauth(dev[0], "TTLS") + +@@ -2830,6 +2873,7 @@ def test_ap_wpa2_eap_tls_neg_domain_matc + + def test_ap_wpa2_eap_tls_neg_subject_match(dev, apdev): + """WPA2-Enterprise negative test - subject mismatch""" ++ check_subject_match_support(dev[0]) + params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap") + hostapd.add_ap(apdev[0], params) + dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS", +@@ -2890,6 +2934,7 @@ def test_ap_wpa2_eap_tls_neg_subject_mat + + def test_ap_wpa2_eap_tls_neg_altsubject_match(dev, apdev): + """WPA2-Enterprise negative test - altsubject mismatch""" ++ check_altsubject_match_support(dev[0]) + params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap") + hostapd.add_ap(apdev[0], params) + +@@ -3430,7 +3475,7 @@ def test_ap_wpa2_eap_ikev2_oom(dev, apde + dev[0].request("REMOVE_NETWORK all") + + tls = dev[0].request("GET tls_library") +- if not tls.startswith("wolfSSL"): ++ if not tls.startswith("wolfSSL") and not tls.startswith("mbed TLS"): + tests = [(1, "os_get_random;dh_init")] + else: + tests = [(1, "crypto_dh_init;dh_init")] +@@ -4744,7 +4789,7 @@ def test_ap_wpa2_eap_tls_intermediate_ca + params["private_key"] = "auth_serv/iCA-server/server.key" + hostapd.add_ap(apdev[0], params) + tls = dev[0].request("GET tls_library") +- if "GnuTLS" in tls or "wolfSSL" in tls: ++ if "GnuTLS" in tls or "wolfSSL" in tls or "mbed TLS" in tls: + ca_cert = "auth_serv/iCA-user/ca-and-root.pem" + client_cert = "auth_serv/iCA-user/user_and_ica.pem" + else: +@@ -4810,6 +4855,7 @@ def test_ap_wpa2_eap_tls_intermediate_ca + run_ap_wpa2_eap_tls_intermediate_ca_ocsp(dev, apdev, params, "-sha1") + + def run_ap_wpa2_eap_tls_intermediate_ca_ocsp(dev, apdev, params, md): ++ check_ocsp_support(dev[0]) + params = int_eap_server_params() + params["ca_cert"] = "auth_serv/iCA-server/ca-and-root.pem" + params["server_cert"] = "auth_serv/iCA-server/server.pem" +@@ -4819,7 +4865,7 @@ def run_ap_wpa2_eap_tls_intermediate_ca_ + try: + hostapd.add_ap(apdev[0], params) + tls = dev[0].request("GET tls_library") +- if "GnuTLS" in tls or "wolfSSL" in tls: ++ if "GnuTLS" in tls or "wolfSSL" in tls or "mbed TLS" in tls: + ca_cert = "auth_serv/iCA-user/ca-and-root.pem" + client_cert = "auth_serv/iCA-user/user_and_ica.pem" + else: +@@ -4855,7 +4901,7 @@ def run_ap_wpa2_eap_tls_intermediate_ca_ + try: + hostapd.add_ap(apdev[0], params) + tls = dev[0].request("GET tls_library") +- if "GnuTLS" in tls or "wolfSSL" in tls: ++ if "GnuTLS" in tls or "wolfSSL" in tls or "mbed TLS" in tls: + ca_cert = "auth_serv/iCA-user/ca-and-root.pem" + client_cert = "auth_serv/iCA-user/user_and_ica.pem" + else: +@@ -4905,7 +4951,7 @@ def test_ap_wpa2_eap_tls_intermediate_ca + try: + hostapd.add_ap(apdev[0], params) + tls = dev[0].request("GET tls_library") +- if "GnuTLS" in tls or "wolfSSL" in tls: ++ if "GnuTLS" in tls or "wolfSSL" in tls or "mbed TLS" in tls: + ca_cert = "auth_serv/iCA-user/ca-and-root.pem" + client_cert = "auth_serv/iCA-user/user_and_ica.pem" + else: +@@ -4972,7 +5018,7 @@ def test_ap_wpa2_eap_tls_intermediate_ca + + hostapd.add_ap(apdev[0], params) + tls = dev[0].request("GET tls_library") +- if "GnuTLS" in tls or "wolfSSL" in tls: ++ if "GnuTLS" in tls or "wolfSSL" in tls or "mbed TLS" in tls: + ca_cert = "auth_serv/iCA-user/ca-and-root.pem" + client_cert = "auth_serv/iCA-user/user_and_ica.pem" + else: +@@ -5230,6 +5276,7 @@ def test_ap_wpa2_eap_ttls_server_cert_ek + + def test_ap_wpa2_eap_ttls_server_pkcs12(dev, apdev): + """WPA2-Enterprise using EAP-TTLS and server PKCS#12 file""" ++ check_pkcs12_support(dev[0]) + skip_with_fips(dev[0]) + params = int_eap_server_params() + del params["server_cert"] +@@ -5242,6 +5289,7 @@ def test_ap_wpa2_eap_ttls_server_pkcs12( + + def test_ap_wpa2_eap_ttls_server_pkcs12_extra(dev, apdev): + """EAP-TTLS and server PKCS#12 file with extra certs""" ++ check_pkcs12_support(dev[0]) + skip_with_fips(dev[0]) + params = int_eap_server_params() + del params["server_cert"] +@@ -5264,6 +5312,7 @@ def test_ap_wpa2_eap_ttls_dh_params_serv + + def test_ap_wpa2_eap_ttls_dh_params_dsa_server(dev, apdev): + """WPA2-Enterprise using EAP-TTLS and alternative server dhparams (DSA)""" ++ check_dh_dsa_support(dev[0]) + params = int_eap_server_params() + params["dh_file"] = "auth_serv/dsaparam.pem" + hapd = hostapd.add_ap(apdev[0], params) +@@ -5575,8 +5624,8 @@ def test_ap_wpa2_eap_non_ascii_identity2 + def test_openssl_cipher_suite_config_wpas(dev, apdev): + """OpenSSL cipher suite configuration on wpa_supplicant""" + tls = dev[0].request("GET tls_library") +- if not tls.startswith("OpenSSL"): +- raise HwsimSkip("TLS library is not OpenSSL: " + tls) ++ if not tls.startswith("OpenSSL") and not tls.startswith("mbed TLS"): ++ raise HwsimSkip("TLS library is not OpenSSL or mbed TLS: " + tls) + params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap") + hapd = hostapd.add_ap(apdev[0], params) + eap_connect(dev[0], hapd, "TTLS", "pap user", +@@ -5602,14 +5651,14 @@ def test_openssl_cipher_suite_config_wpa + def test_openssl_cipher_suite_config_hapd(dev, apdev): + """OpenSSL cipher suite configuration on hostapd""" + tls = dev[0].request("GET tls_library") +- if not tls.startswith("OpenSSL"): +- raise HwsimSkip("wpa_supplicant TLS library is not OpenSSL: " + tls) ++ if not tls.startswith("OpenSSL") and not tls.startswith("mbed TLS"): ++ raise HwsimSkip("wpa_supplicant TLS library is not OpenSSL or mbed TLS: " + tls) + params = int_eap_server_params() + params['openssl_ciphers'] = "AES256" + hapd = hostapd.add_ap(apdev[0], params) + tls = hapd.request("GET tls_library") +- if not tls.startswith("OpenSSL"): +- raise HwsimSkip("hostapd TLS library is not OpenSSL: " + tls) ++ if not tls.startswith("OpenSSL") and not tls.startswith("mbed TLS"): ++ raise HwsimSkip("hostapd TLS library is not OpenSSL or mbed TLS: " + tls) + eap_connect(dev[0], hapd, "TTLS", "pap user", + anonymous_identity="ttls", password="password", + ca_cert="auth_serv/ca.pem", phase2="auth=PAP") +@@ -6051,13 +6100,17 @@ def test_ap_wpa2_eap_tls_versions(dev, a + check_tls_ver(dev[0], hapd, + "tls_disable_tlsv1_0=1 tls_disable_tlsv1_1=1", + "TLSv1.2") +- elif tls.startswith("internal"): ++ elif tls.startswith("internal") or tls.startswith("mbed TLS"): + check_tls_ver(dev[0], hapd, + "tls_disable_tlsv1_0=1 tls_disable_tlsv1_1=1", "TLSv1.2") +- check_tls_ver(dev[1], hapd, +- "tls_disable_tlsv1_0=1 tls_disable_tlsv1_1=0 tls_disable_tlsv1_2=1", "TLSv1.1") +- check_tls_ver(dev[2], hapd, +- "tls_disable_tlsv1_0=0 tls_disable_tlsv1_1=1 tls_disable_tlsv1_2=1", "TLSv1") ++ if tls.startswith("mbed TLS"): ++ check_tls_ver(dev[2], hapd, ++ "tls_disable_tlsv1_0=0 tls_disable_tlsv1_1=1 tls_disable_tlsv1_2=1", "TLSv1.0") ++ else: ++ check_tls_ver(dev[1], hapd, ++ "tls_disable_tlsv1_0=1 tls_disable_tlsv1_1=0 tls_disable_tlsv1_2=1", "TLSv1.1") ++ check_tls_ver(dev[2], hapd, ++ "tls_disable_tlsv1_0=0 tls_disable_tlsv1_1=1 tls_disable_tlsv1_2=1", "TLSv1") + if "run=OpenSSL 1.1.1" in tls or "run=OpenSSL 3.0" in tls: + check_tls_ver(dev[0], hapd, + "tls_disable_tlsv1_0=1 tls_disable_tlsv1_1=1 tls_disable_tlsv1_2=1 tls_disable_tlsv1_3=0", "TLSv1.3") +@@ -6079,6 +6132,11 @@ def test_ap_wpa2_eap_tls_versions_server + tests = [("TLSv1", "[ENABLE-TLSv1.0][DISABLE-TLSv1.1][DISABLE-TLSv1.2][DISABLE-TLSv1.3]"), + ("TLSv1.1", "[ENABLE-TLSv1.0][ENABLE-TLSv1.1][DISABLE-TLSv1.2][DISABLE-TLSv1.3]"), + ("TLSv1.2", "[ENABLE-TLSv1.0][ENABLE-TLSv1.1][ENABLE-TLSv1.2][DISABLE-TLSv1.3]")] ++ tls = dev[0].request("GET tls_library") ++ if tls.startswith("mbed TLS"): ++ tests = [#("TLSv1.0", "[ENABLE-TLSv1.0][DISABLE-TLSv1.1][DISABLE-TLSv1.2][DISABLE-TLSv1.3]"), ++ #("TLSv1.1", "[ENABLE-TLSv1.0][ENABLE-TLSv1.1][DISABLE-TLSv1.2][DISABLE-TLSv1.3]"), ++ ("TLSv1.2", "[ENABLE-TLSv1.0][ENABLE-TLSv1.1][ENABLE-TLSv1.2][DISABLE-TLSv1.3]")] + for exp, flags in tests: + hapd.disable() + hapd.set("tls_flags", flags) +@@ -7138,6 +7196,7 @@ def test_ap_wpa2_eap_assoc_rsn(dev, apde + def test_eap_tls_ext_cert_check(dev, apdev): + """EAP-TLS and external server certification validation""" + # With internal server certificate chain validation ++ check_ext_cert_check_support(dev[0]) + id = dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS", + identity="tls user", + ca_cert="auth_serv/ca.pem", +@@ -7150,6 +7209,7 @@ def test_eap_tls_ext_cert_check(dev, apd + def test_eap_ttls_ext_cert_check(dev, apdev): + """EAP-TTLS and external server certification validation""" + # Without internal server certificate chain validation ++ check_ext_cert_check_support(dev[0]) + id = dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS", + identity="pap user", anonymous_identity="ttls", + password="password", phase2="auth=PAP", +@@ -7160,6 +7220,7 @@ def test_eap_ttls_ext_cert_check(dev, ap + def test_eap_peap_ext_cert_check(dev, apdev): + """EAP-PEAP and external server certification validation""" + # With internal server certificate chain validation ++ check_ext_cert_check_support(dev[0]) + id = dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="PEAP", + identity="user", anonymous_identity="peap", + ca_cert="auth_serv/ca.pem", +@@ -7170,6 +7231,7 @@ def test_eap_peap_ext_cert_check(dev, ap + + def test_eap_fast_ext_cert_check(dev, apdev): + """EAP-FAST and external server certification validation""" ++ check_ext_cert_check_support(dev[0]) + check_eap_capa(dev[0], "FAST") + # With internal server certificate chain validation + dev[0].request("SET blob fast_pac_auth_ext ") +@@ -7184,10 +7246,6 @@ def test_eap_fast_ext_cert_check(dev, ap + run_ext_cert_check(dev, apdev, id) + + def run_ext_cert_check(dev, apdev, net_id): +- check_ext_cert_check_support(dev[0]) +- if not openssl_imported: +- raise HwsimSkip("OpenSSL python method not available") +- + params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap") + hapd = hostapd.add_ap(apdev[0], params) + +--- a/tests/hwsim/test_ap_ft.py ++++ b/tests/hwsim/test_ap_ft.py +@@ -2474,11 +2474,11 @@ def test_ap_ft_ap_oom5(dev, apdev): + # This will fail to roam + dev[0].roam(bssid1, check_bssid=False) + +- with fail_test(hapd1, 1, "sha256_prf_bits;wpa_pmk_r1_to_ptk;wpa_ft_process_auth_req"): ++ with fail_test(hapd1, 1, "sha256_prf;wpa_pmk_r1_to_ptk;wpa_ft_process_auth_req"): + # This will fail to roam + dev[0].roam(bssid1, check_bssid=False) + +- with fail_test(hapd1, 3, "wpa_pmk_r1_to_ptk;wpa_ft_process_auth_req"): ++ with fail_test(hapd1, 2, "wpa_pmk_r1_to_ptk;wpa_ft_process_auth_req"): + # This will fail to roam + dev[0].roam(bssid1, check_bssid=False) + +--- a/tests/hwsim/test_authsrv.py ++++ b/tests/hwsim/test_authsrv.py +@@ -156,9 +156,12 @@ def test_authsrv_oom(dev, apdev): + if "FAIL" not in authsrv.request("ENABLE"): + raise Exception("ENABLE succeeded during OOM") + +- with alloc_fail(authsrv, 1, "tls_init;authsrv_init"): +- if "FAIL" not in authsrv.request("ENABLE"): +- raise Exception("ENABLE succeeded during OOM") ++ # tls_mbedtls.c:tls_init() does not alloc memory (no alloc fail trigger) ++ tls = dev[0].request("GET tls_library") ++ if not tls.startswith("mbed TLS"): ++ with alloc_fail(authsrv, 1, "tls_init;authsrv_init"): ++ if "FAIL" not in authsrv.request("ENABLE"): ++ raise Exception("ENABLE succeeded during OOM") + + for count in range(1, 3): + with alloc_fail(authsrv, count, "eap_sim_db_init;authsrv_init"): +--- a/tests/hwsim/test_dpp.py ++++ b/tests/hwsim/test_dpp.py +@@ -39,7 +39,8 @@ def check_dpp_capab(dev, brainpool=False + raise HwsimSkip("DPP not supported") + if brainpool: + tls = dev.request("GET tls_library") +- if (not tls.startswith("OpenSSL") or "run=BoringSSL" in tls) and not tls.startswith("wolfSSL"): ++ if (not tls.startswith("OpenSSL") or "run=BoringSSL" in tls) and not tls.startswith("wolfSSL") \ ++ and not tls.startswith("mbed TLS"): + raise HwsimSkip("Crypto library does not support Brainpool curves: " + tls) + capa = dev.request("GET_CAPABILITY dpp") + ver = 1 +@@ -3892,6 +3893,9 @@ def test_dpp_proto_auth_req_no_i_proto_k + + def test_dpp_proto_auth_req_invalid_i_proto_key(dev, apdev): + """DPP protocol testing - invalid I-proto key in Auth Req""" ++ tls = dev[0].request("GET tls_library") ++ if tls.startswith("mbed TLS"): ++ raise HwsimSkip("mbed TLS crypto_ecdh_set_peerkey() properly detects invalid key; no response") + run_dpp_proto_auth_req_missing(dev, 66, "Invalid Initiator Protocol Key") + + def test_dpp_proto_auth_req_no_i_nonce(dev, apdev): +@@ -3987,7 +3991,12 @@ def test_dpp_proto_auth_resp_no_r_proto_ + + def test_dpp_proto_auth_resp_invalid_r_proto_key(dev, apdev): + """DPP protocol testing - invalid R-Proto Key in Auth Resp""" +- run_dpp_proto_auth_resp_missing(dev, 67, "Invalid Responder Protocol Key") ++ tls = dev[0].request("GET tls_library") ++ if tls.startswith("mbed TLS"): ++ # mbed TLS crypto_ecdh_set_peerkey() properly detects invalid key ++ run_dpp_proto_auth_resp_missing(dev, 67, "Failed to derive ECDH shared secret") ++ else: ++ run_dpp_proto_auth_resp_missing(dev, 67, "Invalid Responder Protocol Key") + + def test_dpp_proto_auth_resp_no_r_nonce(dev, apdev): + """DPP protocol testing - no R-nonce in Auth Resp""" +@@ -4349,11 +4358,17 @@ def test_dpp_proto_pkex_exchange_resp_in + + def test_dpp_proto_pkex_cr_req_invalid_bootstrap_key(dev, apdev): + """DPP protocol testing - invalid Bootstrap Key in PKEX Commit-Reveal Request""" ++ tls = dev[0].request("GET tls_library") ++ if tls.startswith("mbed TLS"): ++ raise HwsimSkip("mbed TLS crypto_ecdh_set_peerkey() properly detects invalid key; no response") + run_dpp_proto_pkex_req_missing(dev, 47, + "Peer bootstrapping key is invalid") + + def test_dpp_proto_pkex_cr_resp_invalid_bootstrap_key(dev, apdev): + """DPP protocol testing - invalid Bootstrap Key in PKEX Commit-Reveal Response""" ++ tls = dev[0].request("GET tls_library") ++ if tls.startswith("mbed TLS"): ++ raise HwsimSkip("mbed TLS crypto_ecdh_set_peerkey() properly detects invalid key; no response") + run_dpp_proto_pkex_resp_missing(dev, 48, + "Peer bootstrapping key is invalid") + +--- a/tests/hwsim/test_erp.py ++++ b/tests/hwsim/test_erp.py +@@ -12,7 +12,7 @@ import time + + import hostapd + from utils import * +-from test_ap_eap import int_eap_server_params, check_tls13_support ++from test_ap_eap import int_eap_server_params, check_tls13_support, check_eap_capa + from test_ap_psk import find_wpas_process, read_process_memory, verify_not_present, get_key_locations + + def test_erp_initiate_reauth_start(dev, apdev): +@@ -276,6 +276,7 @@ def test_erp_radius_eap_methods(dev, apd + params['erp_domain'] = 'example.com' + params['disable_pmksa_caching'] = '1' + hapd = hostapd.add_ap(apdev[0], params) ++ tls = dev[0].request("GET tls_library") + + erp_test(dev[0], hapd, eap="AKA", identity="0232010000000000@example.com", + password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123") +@@ -289,7 +290,7 @@ def test_erp_radius_eap_methods(dev, apd + password="5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123") + erp_test(dev[0], hapd, eap="EKE", identity="erp-eke@example.com", + password="hello") +- if "FAST" in eap_methods: ++ if "FAST" in eap_methods and check_eap_capa(dev[0], "FAST"): + erp_test(dev[0], hapd, eap="FAST", identity="erp-fast@example.com", + password="password", ca_cert="auth_serv/ca.pem", + phase2="auth=GTC", +@@ -301,13 +302,14 @@ def test_erp_radius_eap_methods(dev, apd + password="password") + erp_test(dev[0], hapd, eap="PAX", identity="erp-pax@example.com", + password_hex="0123456789abcdef0123456789abcdef") +- if "MSCHAPV2" in eap_methods: ++ if "MSCHAPV2" in eap_methods and check_eap_capa(dev[0], "MSCHAPV2"): + erp_test(dev[0], hapd, eap="PEAP", identity="erp-peap@example.com", + password="password", ca_cert="auth_serv/ca.pem", + phase2="auth=MSCHAPV2") +- erp_test(dev[0], hapd, eap="TEAP", identity="erp-teap@example.com", +- password="password", ca_cert="auth_serv/ca.pem", +- phase2="auth=MSCHAPV2", pac_file="blob://teap_pac") ++ if check_eap_capa(dev[0], "TEAP"): ++ erp_test(dev[0], hapd, eap="TEAP", identity="erp-teap@example.com", ++ password="password", ca_cert="auth_serv/ca.pem", ++ phase2="auth=MSCHAPV2", pac_file="blob://teap_pac") + erp_test(dev[0], hapd, eap="PSK", identity="erp-psk@example.com", + password_hex="0123456789abcdef0123456789abcdef") + if "PWD" in eap_methods: +@@ -640,7 +642,7 @@ def test_erp_local_errors(dev, apdev): + dev[0].request("REMOVE_NETWORK all") + dev[0].wait_disconnected() + +- for count in range(1, 6): ++ for count in range(1, 4): + dev[0].request("ERP_FLUSH") + with fail_test(dev[0], count, "hmac_sha256_kdf;eap_peer_erp_init"): + dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS", +--- a/tests/hwsim/test_fils.py ++++ b/tests/hwsim/test_fils.py +@@ -1422,7 +1422,10 @@ def run_fils_sk_pfs(dev, apdev, group, p + check_erp_capa(dev[0]) + + tls = dev[0].request("GET tls_library") +- if not tls.startswith("wolfSSL"): ++ if tls.startswith("mbed TLS"): ++ if int(group) == 27: ++ raise HwsimSkip("Brainpool EC group 27 not supported by mbed TLS") ++ elif not tls.startswith("wolfSSL"): + if int(group) in [25]: + if not (tls.startswith("OpenSSL") and ("build=OpenSSL 1.0.2" in tls or "build=OpenSSL 1.1" in tls or "build=OpenSSL 3.0" in tls) and ("run=OpenSSL 1.0.2" in tls or "run=OpenSSL 1.1" in tls or "run=OpenSSL 3.0" in tls)): + raise HwsimSkip("EC group not supported") +--- a/tests/hwsim/test_pmksa_cache.py ++++ b/tests/hwsim/test_pmksa_cache.py +@@ -955,7 +955,7 @@ def test_pmksa_cache_preauth_wpas_oom(de + eap_connect(dev[0], hapd, "PAX", "pax.user@example.com", + password_hex="0123456789abcdef0123456789abcdef", + bssid=apdev[0]['bssid']) +- for i in range(1, 11): ++ for i in range(1, 10): + with alloc_fail(dev[0], i, "rsn_preauth_init"): + res = dev[0].request("PREAUTH f2:11:22:33:44:55").strip() + logger.info("Iteration %d - PREAUTH command results: %s" % (i, res)) +@@ -963,7 +963,7 @@ def test_pmksa_cache_preauth_wpas_oom(de + state = dev[0].request('GET_ALLOC_FAIL') + if state.startswith('0:'): + break +- time.sleep(0.05) ++ time.sleep(0.10) + + def test_pmksa_cache_ctrl(dev, apdev): + """PMKSA cache control interface operations""" +--- a/tests/hwsim/test_sae.py ++++ b/tests/hwsim/test_sae.py +@@ -177,6 +177,11 @@ def test_sae_groups(dev, apdev): + if tls.startswith("OpenSSL") and "run=OpenSSL 1." in tls: + logger.info("Add Brainpool EC groups since OpenSSL is new enough") + sae_groups += [27, 28, 29, 30] ++ if tls.startswith("mbed TLS"): ++ # secp224k1 and secp224r1 (26) have prime p = 1 mod 4, and mbedtls ++ # does not have code to derive y from compressed format for those curves ++ sae_groups = [19, 25, 20, 21, 1, 2, 5, 14, 15, 16, 22, 23, 24] ++ sae_groups += [27, 28, 29, 30] + heavy_groups = [14, 15, 16] + suitable_groups = [15, 16, 17, 18, 19, 20, 21] + groups = [str(g) for g in sae_groups] +@@ -2193,6 +2198,8 @@ def run_sae_pwe_group(dev, apdev, group) + logger.info("Add Brainpool EC groups since OpenSSL is new enough") + elif tls.startswith("wolfSSL"): + logger.info("Make sure Brainpool EC groups were enabled when compiling wolfSSL") ++ elif tls.startswith("mbed TLS"): ++ logger.info("Make sure Brainpool EC groups were enabled when compiling mbed TLS") + else: + raise HwsimSkip("Brainpool curve not supported") + start_sae_pwe_ap(apdev[0], group, 2) +--- a/tests/hwsim/test_suite_b.py ++++ b/tests/hwsim/test_suite_b.py +@@ -27,6 +27,8 @@ def check_suite_b_tls_lib(dev, dhe=False + return + if tls.startswith("wolfSSL"): + return ++ if tls.startswith("mbed TLS"): ++ return + if not tls.startswith("OpenSSL"): + raise HwsimSkip("TLS library not supported for Suite B: " + tls) + supported = False +@@ -520,6 +522,7 @@ def test_suite_b_192_rsa_insufficient_dh + + dev[0].connect("test-suite-b", key_mgmt="WPA-EAP-SUITE-B-192", + ieee80211w="2", ++ openssl_ciphers="DHE-RSA-AES256-GCM-SHA384", + phase1="tls_suiteb=1", + eap="TLS", identity="tls user", + ca_cert="auth_serv/rsa3072-ca.pem", +--- a/tests/hwsim/test_wpas_ctrl.py ++++ b/tests/hwsim/test_wpas_ctrl.py +@@ -1842,7 +1842,7 @@ def _test_wpas_ctrl_oom(dev): + tls = dev[0].request("GET tls_library") + if not tls.startswith("internal"): + tests.append(('NFC_GET_HANDOVER_SEL NDEF P2P-CR-TAG', 'FAIL', +- 4, 'wpas_ctrl_nfc_get_handover_sel_p2p')) ++ 3, 'wpas_ctrl_nfc_get_handover_sel_p2p')) + for cmd, exp, count, func in tests: + with alloc_fail(dev[0], count, func): + res = dev[0].request(cmd) +--- a/tests/hwsim/utils.py ++++ b/tests/hwsim/utils.py +@@ -141,7 +141,13 @@ def check_imsi_privacy_support(dev): + + def check_tls_tod(dev): + tls = dev.request("GET tls_library") +- if not tls.startswith("OpenSSL") and not tls.startswith("internal"): ++ if tls.startswith("OpenSSL"): ++ return ++ elif tls.startswith("internal"): ++ return ++ elif tls.startswith("mbed TLS"): ++ return ++ else: + raise HwsimSkip("TLS TOD-TOFU/STRICT not supported with this TLS library: " + tls) + + def vht_supported(): +--- /dev/null ++++ b/tests/test-crypto_module.c +@@ -0,0 +1,16 @@ ++/* ++ * crypto module tests - test program ++ * Copyright (c) 2022, Glenn Strauss ++ * ++ * This software may be distributed under the terms of the BSD license. ++ * See README for more details. ++ */ ++ ++#include "utils/includes.h" ++#include "utils/module_tests.h" ++#include "crypto/crypto_module_tests.c" ++ ++int main(int argc, char *argv[]) ++{ ++ return crypto_module_tests(); ++} +--- a/tests/test-https.c ++++ b/tests/test-https.c +@@ -75,7 +75,7 @@ static int https_client(int s, const cha + struct tls_connection *conn; + struct wpabuf *in, *out, *appl; + int res = -1; +- int need_more_data; ++ int need_more_data = 0; + + os_memset(&conf, 0, sizeof(conf)); + conf.event_cb = https_tls_event_cb; +@@ -93,8 +93,12 @@ static int https_client(int s, const cha + + for (;;) { + appl = NULL; ++#ifdef CONFIG_TLS_INTERNAL_SERVER + out = tls_connection_handshake2(tls, conn, in, &appl, + &need_more_data); ++#else ++ out = tls_connection_handshake(tls, conn, in, &appl); ++#endif + wpabuf_free(in); + in = NULL; + if (out == NULL) { +@@ -152,11 +156,15 @@ static int https_client(int s, const cha + + wpa_printf(MSG_INFO, "Reading HTTP response"); + for (;;) { +- int need_more_data; ++ int need_more_data = 0; + in = https_recv(s); + if (in == NULL) + goto done; ++#ifdef CONFIG_TLS_INTERNAL_SERVER + out = tls_connection_decrypt2(tls, conn, in, &need_more_data); ++#else ++ out = tls_connection_decrypt(tls, conn, in); ++#endif + if (need_more_data) + wpa_printf(MSG_DEBUG, "HTTP: Need more data"); + wpabuf_free(in); +--- a/tests/test-https_server.c ++++ b/tests/test-https_server.c +@@ -67,10 +67,12 @@ static struct wpabuf * https_recv(int s, + } + + ++#ifdef CONFIG_TLS_INTERNAL_SERVER + static void https_tls_log_cb(void *ctx, const char *msg) + { + wpa_printf(MSG_DEBUG, "TLS: %s", msg); + } ++#endif + + + static int https_server(int s) +@@ -79,7 +81,7 @@ static int https_server(int s) + void *tls; + struct tls_connection_params params; + struct tls_connection *conn; +- struct wpabuf *in, *out, *appl; ++ struct wpabuf *in = NULL, *out = NULL, *appl = NULL; + int res = -1; + + os_memset(&conf, 0, sizeof(conf)); +@@ -106,7 +108,9 @@ static int https_server(int s) + return -1; + } + ++#ifdef CONFIG_TLS_INTERNAL_SERVER + tls_connection_set_log_cb(conn, https_tls_log_cb, NULL); ++#endif + + for (;;) { + in = https_recv(s, 5000); +@@ -147,12 +151,16 @@ static int https_server(int s) + + wpa_printf(MSG_INFO, "Reading HTTP request"); + for (;;) { +- int need_more_data; ++ int need_more_data = 0; + + in = https_recv(s, 5000); + if (!in) + goto done; ++#ifdef CONFIG_TLS_INTERNAL_SERVER + out = tls_connection_decrypt2(tls, conn, in, &need_more_data); ++#else ++ out = tls_connection_decrypt(tls, conn, in); ++#endif + wpabuf_free(in); + in = NULL; + if (need_more_data) { +--- a/wpa_supplicant/Makefile ++++ b/wpa_supplicant/Makefile +@@ -1122,6 +1122,7 @@ CFLAGS += -DCONFIG_TLSV12 + endif + + ifeq ($(CONFIG_TLS), wolfssl) ++CFLAGS += -DCONFIG_TLS_WOLFSSL + ifdef TLS_FUNCS + CFLAGS += -DWOLFSSL_DER_LOAD + OBJS += ../src/crypto/tls_wolfssl.o +@@ -1137,6 +1138,7 @@ LIBS_p += -lwolfssl -lm + endif + + ifeq ($(CONFIG_TLS), openssl) ++CFLAGS += -DCONFIG_TLS_OPENSSL + CFLAGS += -DCRYPTO_RSA_OAEP_SHA256 + ifdef TLS_FUNCS + CFLAGS += -DEAP_TLS_OPENSSL +@@ -1164,6 +1166,7 @@ CFLAGS += -DTLS_DEFAULT_CIPHERS=\"$(CONF + endif + + ifeq ($(CONFIG_TLS), mbedtls) ++CFLAGS += -DCONFIG_TLS_MBEDTLS + ifndef CONFIG_CRYPTO + CONFIG_CRYPTO=mbedtls + endif +@@ -1183,6 +1186,7 @@ endif + endif + + ifeq ($(CONFIG_TLS), gnutls) ++CFLAGS += -DCONFIG_TLS_GNUTLS + ifndef CONFIG_CRYPTO + # default to libgcrypt + CONFIG_CRYPTO=gnutls +@@ -1213,6 +1217,7 @@ endif + endif + + ifeq ($(CONFIG_TLS), internal) ++CFLAGS += -DCONFIG_TLS_INTERNAL + ifndef CONFIG_CRYPTO + CONFIG_CRYPTO=internal + endif +@@ -1293,6 +1298,7 @@ endif + endif + + ifeq ($(CONFIG_TLS), linux) ++CFLAGS += -DCONFIG_TLS_INTERNAL + OBJS += ../src/crypto/crypto_linux.o + OBJS_p += ../src/crypto/crypto_linux.o + ifdef TLS_FUNCS diff --git a/feeds/ipq95xx/hostapd/patches/150-add-NULL-checks-encountered-during-tests-hwsim.patch b/feeds/ipq95xx/hostapd/patches/150-add-NULL-checks-encountered-during-tests-hwsim.patch new file mode 100644 index 000000000..c8c3ff33f --- /dev/null +++ b/feeds/ipq95xx/hostapd/patches/150-add-NULL-checks-encountered-during-tests-hwsim.patch @@ -0,0 +1,45 @@ +From 33afce36c54b0cad38643629ded10ff5d727f077 Mon Sep 17 00:00:00 2001 +From: Glenn Strauss +Date: Fri, 12 Aug 2022 05:34:47 -0400 +Subject: [PATCH 5/7] add NULL checks (encountered during tests/hwsim) + +sae_derive_commit_element_ecc NULL pwe_ecc check +dpp_gen_keypair() NULL curve check + +Signed-off-by: Glenn Strauss +--- + src/common/dpp_crypto.c | 6 ++++++ + src/common/sae.c | 7 +++++++ + 2 files changed, 13 insertions(+) + +--- a/src/common/dpp_crypto.c ++++ b/src/common/dpp_crypto.c +@@ -269,6 +269,12 @@ int dpp_get_pubkey_hash(struct crypto_ec + + struct crypto_ec_key * dpp_gen_keypair(const struct dpp_curve_params *curve) + { ++ if (curve == NULL) { ++ wpa_printf(MSG_DEBUG, ++ "DPP: %s curve must be initialized", __func__); ++ return NULL; ++ } ++ + struct crypto_ec_key *key; + + wpa_printf(MSG_DEBUG, "DPP: Generating a keypair"); +--- a/src/common/sae.c ++++ b/src/common/sae.c +@@ -1278,6 +1278,13 @@ void sae_deinit_pt(struct sae_pt *pt) + static int sae_derive_commit_element_ecc(struct sae_data *sae, + struct crypto_bignum *mask) + { ++ if (sae->tmp->pwe_ecc == NULL) { ++ wpa_printf(MSG_DEBUG, ++ "SAE: %s sae->tmp->pwe_ecc must be initialized", ++ __func__); ++ return -1; ++ } ++ + /* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */ + if (!sae->tmp->own_commit_element_ecc) { + sae->tmp->own_commit_element_ecc = diff --git a/feeds/ipq95xx/hostapd/patches/160-dpp_pkex-EC-point-mul-w-value-prime.patch b/feeds/ipq95xx/hostapd/patches/160-dpp_pkex-EC-point-mul-w-value-prime.patch new file mode 100644 index 000000000..db4fcfe23 --- /dev/null +++ b/feeds/ipq95xx/hostapd/patches/160-dpp_pkex-EC-point-mul-w-value-prime.patch @@ -0,0 +1,26 @@ +From 54211caa2e0e5163aefef390daf88a971367a702 Mon Sep 17 00:00:00 2001 +From: Glenn Strauss +Date: Tue, 4 Oct 2022 17:09:24 -0400 +Subject: [PATCH 6/7] dpp_pkex: EC point mul w/ value < prime + +crypto_ec_point_mul() with mbedtls requires point +be multiplied by a multiplicand with value < prime + +Signed-off-by: Glenn Strauss +--- + src/common/dpp_crypto.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/src/common/dpp_crypto.c ++++ b/src/common/dpp_crypto.c +@@ -1588,7 +1588,9 @@ dpp_pkex_derive_Qr(const struct dpp_curv + Pr = crypto_ec_key_get_public_key(Pr_key); + Qr = crypto_ec_point_init(ec); + hash_bn = crypto_bignum_init_set(hash, curve->hash_len); +- if (!Pr || !Qr || !hash_bn || crypto_ec_point_mul(ec, Pr, hash_bn, Qr)) ++ if (!Pr || !Qr || !hash_bn || ++ crypto_bignum_mod(hash_bn, crypto_ec_get_prime(ec), hash_bn) || ++ crypto_ec_point_mul(ec, Pr, hash_bn, Qr)) + goto fail; + + if (crypto_ec_point_is_at_infinity(ec, Qr)) { diff --git a/feeds/ipq95xx/hostapd/patches/180-driver_nl80211-fix-setting-QoS-map-on-secondary-BSSs.patch b/feeds/ipq95xx/hostapd/patches/180-driver_nl80211-fix-setting-QoS-map-on-secondary-BSSs.patch new file mode 100644 index 000000000..4929c581c --- /dev/null +++ b/feeds/ipq95xx/hostapd/patches/180-driver_nl80211-fix-setting-QoS-map-on-secondary-BSSs.patch @@ -0,0 +1,20 @@ +From: Felix Fietkau +Date: Thu, 14 Sep 2023 10:53:50 +0200 +Subject: [PATCH] driver_nl80211: fix setting QoS map on secondary BSSs + +The setting is per-BSS, not per PHY + +Signed-off-by: Felix Fietkau +--- + +--- a/src/drivers/driver_nl80211.c ++++ b/src/drivers/driver_nl80211.c +@@ -11341,7 +11341,7 @@ static int nl80211_set_qos_map(void *pri + wpa_hexdump(MSG_DEBUG, "nl80211: Setting QoS Map", + qos_map_set, qos_map_set_len); + +- if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_QOS_MAP)) || ++ if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_QOS_MAP)) || + nla_put(msg, NL80211_ATTR_QOS_MAP, qos_map_set_len, qos_map_set)) { + nlmsg_free(msg); + return -ENOBUFS; diff --git a/feeds/ipq95xx/hostapd/patches/181-driver_nl80211-update-drv-ifindex-on-removing-the-fi.patch b/feeds/ipq95xx/hostapd/patches/181-driver_nl80211-update-drv-ifindex-on-removing-the-fi.patch new file mode 100644 index 000000000..adfb21fb4 --- /dev/null +++ b/feeds/ipq95xx/hostapd/patches/181-driver_nl80211-update-drv-ifindex-on-removing-the-fi.patch @@ -0,0 +1,18 @@ +From: Felix Fietkau +Date: Thu, 14 Sep 2023 11:28:03 +0200 +Subject: [PATCH] driver_nl80211: update drv->ifindex on removing the first + BSS + +Signed-off-by: Felix Fietkau +--- + +--- a/src/drivers/driver_nl80211.c ++++ b/src/drivers/driver_nl80211.c +@@ -8867,6 +8867,7 @@ static int wpa_driver_nl80211_if_remove( + if (drv->first_bss->next) { + drv->first_bss = drv->first_bss->next; + drv->ctx = drv->first_bss->ctx; ++ drv->ifindex = drv->first_bss->ifindex; + os_free(bss); + } else { + wpa_printf(MSG_DEBUG, "nl80211: No second BSS to reassign context to"); diff --git a/feeds/ipq95xx/hostapd/patches/182-nl80211-move-nl80211_put_freq_params-call-outside-of.patch b/feeds/ipq95xx/hostapd/patches/182-nl80211-move-nl80211_put_freq_params-call-outside-of.patch new file mode 100644 index 000000000..395c64595 --- /dev/null +++ b/feeds/ipq95xx/hostapd/patches/182-nl80211-move-nl80211_put_freq_params-call-outside-of.patch @@ -0,0 +1,34 @@ +From: Felix Fietkau +Date: Mon, 18 Sep 2023 16:47:41 +0200 +Subject: [PATCH] nl80211: move nl80211_put_freq_params call outside of + 802.11ax #ifdef + +The relevance of this call is not specific to 802.11ax, so it should be done +even with CONFIG_IEEE80211AX disabled. + +Fixes: b3921db426ea ("nl80211: Add frequency info in start AP command") +Signed-off-by: Felix Fietkau +--- + +--- a/src/drivers/driver_nl80211.c ++++ b/src/drivers/driver_nl80211.c +@@ -5226,6 +5226,9 @@ static int wpa_driver_nl80211_set_ap(voi + nla_nest_end(msg, ftm); + } + ++ if (params->freq && nl80211_put_freq_params(msg, params->freq) < 0) ++ goto fail; ++ + #ifdef CONFIG_IEEE80211AX + if (params->he_spr_ctrl) { + struct nlattr *spr; +@@ -5260,9 +5263,6 @@ static int wpa_driver_nl80211_set_ap(voi + nla_nest_end(msg, spr); + } + +- if (params->freq && nl80211_put_freq_params(msg, params->freq) < 0) +- goto fail; +- + if (params->freq && params->freq->he_enabled) { + struct nlattr *bss_color; + diff --git a/feeds/ipq95xx/hostapd/patches/183-hostapd-cancel-channel_list_update_timeout-in-hostap.patch b/feeds/ipq95xx/hostapd/patches/183-hostapd-cancel-channel_list_update_timeout-in-hostap.patch new file mode 100644 index 000000000..fe8131838 --- /dev/null +++ b/feeds/ipq95xx/hostapd/patches/183-hostapd-cancel-channel_list_update_timeout-in-hostap.patch @@ -0,0 +1,28 @@ +From: Felix Fietkau +Date: Wed, 20 Sep 2023 13:41:10 +0200 +Subject: [PATCH] hostapd: cancel channel_list_update_timeout in + hostapd_cleanup_iface_partial + +Fixes a crash when disabling an interface during channel list update + +Signed-off-by: Felix Fietkau +--- + +--- a/src/ap/hostapd.c ++++ b/src/ap/hostapd.c +@@ -569,6 +569,7 @@ static void sta_track_deinit(struct host + void hostapd_cleanup_iface_partial(struct hostapd_iface *iface) + { + wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface); ++ eloop_cancel_timeout(channel_list_update_timeout, iface, NULL); + #ifdef NEED_AP_MLME + hostapd_stop_setup_timers(iface); + #endif /* NEED_AP_MLME */ +@@ -598,7 +599,6 @@ void hostapd_cleanup_iface_partial(struc + static void hostapd_cleanup_iface(struct hostapd_iface *iface) + { + wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface); +- eloop_cancel_timeout(channel_list_update_timeout, iface, NULL); + eloop_cancel_timeout(hostapd_interface_setup_failure_handler, iface, + NULL); + diff --git a/feeds/ipq95xx/hostapd/patches/200-multicall.patch b/feeds/ipq95xx/hostapd/patches/200-multicall.patch index 3d0e8035a..e3ed00f2d 100644 --- a/feeds/ipq95xx/hostapd/patches/200-multicall.patch +++ b/feeds/ipq95xx/hostapd/patches/200-multicall.patch @@ -18,7 +18,7 @@ OBJS += ../src/ap/vlan_init.o OBJS += ../src/ap/vlan_ifconfig.o OBJS += ../src/ap/vlan.o -@@ -349,10 +351,14 @@ CFLAGS += -DCONFIG_MBO +@@ -357,10 +359,14 @@ CFLAGS += -DCONFIG_MBO OBJS += ../src/ap/mbo_ap.o endif @@ -36,7 +36,7 @@ LIBS += $(DRV_AP_LIBS) ifdef CONFIG_L2_PACKET -@@ -1277,6 +1283,12 @@ install: $(addprefix $(DESTDIR)$(BINDIR) +@@ -1380,6 +1386,12 @@ install: $(addprefix $(DESTDIR)$(BINDIR) _OBJS_VAR := OBJS include ../src/objs.mk @@ -49,7 +49,7 @@ hostapd: $(OBJS) $(Q)$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS) @$(E) " LD " $@ -@@ -1351,6 +1363,12 @@ include ../src/objs.mk +@@ -1460,6 +1472,12 @@ include ../src/objs.mk _OBJS_VAR := SOBJS include ../src/objs.mk @@ -64,15 +64,15 @@ @$(E) " LD " $@ --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile -@@ -17,6 +17,7 @@ endif +@@ -10,6 +10,7 @@ ALL += dbus/fi.w1.wpa_supplicant1.servic EXTRA_TARGETS=dynamic_eap_methods CONFIG_FILE=.config +-include $(if $(MULTICALL),../hostapd/.config) include ../src/build.rules - ifdef LIBS -@@ -354,7 +355,9 @@ endif + ifdef CONFIG_BUILD_PASN_SO +@@ -382,7 +383,9 @@ endif ifdef CONFIG_IBSS_RSN NEED_RSN_AUTHENTICATOR=y CFLAGS += -DCONFIG_IBSS_RSN @@ -82,7 +82,7 @@ OBJS += ibss_rsn.o endif -@@ -886,6 +889,10 @@ ifdef CONFIG_DYNAMIC_EAP_METHODS +@@ -924,6 +927,10 @@ ifdef CONFIG_DYNAMIC_EAP_METHODS CFLAGS += -DCONFIG_DYNAMIC_EAP_METHODS LIBS += -ldl -rdynamic endif @@ -93,7 +93,7 @@ endif ifdef CONFIG_AP -@@ -893,9 +900,11 @@ NEED_EAP_COMMON=y +@@ -931,9 +938,11 @@ NEED_EAP_COMMON=y NEED_RSN_AUTHENTICATOR=y CFLAGS += -DCONFIG_AP OBJS += ap.o @@ -105,7 +105,7 @@ OBJS += ../src/ap/hostapd.o OBJS += ../src/ap/wpa_auth_glue.o OBJS += ../src/ap/utils.o -@@ -975,6 +984,12 @@ endif +@@ -1022,6 +1031,12 @@ endif ifdef CONFIG_HS20 OBJS += ../src/ap/hs20.o endif @@ -118,7 +118,7 @@ endif ifdef CONFIG_MBO -@@ -983,7 +998,9 @@ CFLAGS += -DCONFIG_MBO +@@ -1030,7 +1045,9 @@ CFLAGS += -DCONFIG_MBO endif ifdef NEED_RSN_AUTHENTICATOR @@ -128,7 +128,7 @@ NEED_AES_WRAP=y OBJS += ../src/ap/wpa_auth.o OBJS += ../src/ap/wpa_auth_ie.o -@@ -1878,6 +1895,12 @@ wpa_priv: $(BCHECK) $(OBJS_priv) +@@ -2010,6 +2027,12 @@ wpa_priv: $(BCHECK) $(OBJS_priv) _OBJS_VAR := OBJS include ../src/objs.mk @@ -141,7 +141,7 @@ wpa_supplicant: $(BCHECK) $(OBJS) $(EXTRA_progs) $(Q)$(LDO) $(LDFLAGS) -o wpa_supplicant $(OBJS) $(LIBS) $(EXTRALIBS) @$(E) " LD " $@ -@@ -1983,6 +2006,12 @@ eap_eke.so: ../src/eap_peer/eap_eke.c .. +@@ -2142,6 +2165,12 @@ eap_gpsk.so: $(SRC_EAP_GPSK) $(Q)sed -e 's|\@BINDIR\@|$(BINDIR)|g' $< >$@ @$(E) " sed" $< @@ -156,7 +156,7 @@ wpa_cli.exe: wpa_cli --- a/src/drivers/driver.h +++ b/src/drivers/driver.h -@@ -6018,8 +6018,8 @@ union wpa_event_data { +@@ -6667,8 +6667,8 @@ union wpa_event_data { * Driver wrapper code should call this function whenever an event is received * from the driver. */ @@ -167,7 +167,7 @@ /** * wpa_supplicant_event_global - Report a driver event for wpa_supplicant -@@ -6031,7 +6031,7 @@ void wpa_supplicant_event(void *ctx, enu +@@ -6680,7 +6680,7 @@ void wpa_supplicant_event(void *ctx, enu * Same as wpa_supplicant_event(), but we search for the interface in * wpa_global. */ @@ -178,7 +178,7 @@ /* --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c -@@ -1827,8 +1827,8 @@ err: +@@ -2184,8 +2184,8 @@ err: #endif /* CONFIG_OWE */ @@ -189,7 +189,7 @@ { struct hostapd_data *hapd = ctx; #ifndef CONFIG_NO_STDOUT_DEBUG -@@ -2073,7 +2073,7 @@ void wpa_supplicant_event(void *ctx, enu +@@ -2489,7 +2489,7 @@ void wpa_supplicant_event(void *ctx, enu } @@ -200,7 +200,7 @@ struct hapd_interfaces *interfaces = ctx; --- a/wpa_supplicant/wpa_priv.c +++ b/wpa_supplicant/wpa_priv.c -@@ -1038,8 +1038,8 @@ static void wpa_priv_send_ft_response(st +@@ -1039,8 +1039,8 @@ static void wpa_priv_send_ft_response(st } @@ -211,7 +211,7 @@ { struct wpa_priv_interface *iface = ctx; -@@ -1102,7 +1102,7 @@ void wpa_supplicant_event(void *ctx, enu +@@ -1103,7 +1103,7 @@ void wpa_supplicant_event(void *ctx, enu } @@ -220,7 +220,7 @@ union wpa_event_data *data) { struct wpa_priv_global *global = ctx; -@@ -1215,6 +1215,8 @@ int main(int argc, char *argv[]) +@@ -1217,6 +1217,8 @@ int main(int argc, char *argv[]) if (os_program_init()) return -1; @@ -231,7 +231,7 @@ os_memset(&global, 0, sizeof(global)); --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c -@@ -4666,8 +4666,8 @@ static void wpas_event_unprot_beacon(str +@@ -5353,8 +5353,8 @@ static void wpas_link_reconfig(struct wp } @@ -242,7 +242,7 @@ { struct wpa_supplicant *wpa_s = ctx; int resched; -@@ -5512,7 +5512,7 @@ void wpa_supplicant_event(void *ctx, enu +@@ -6272,7 +6272,7 @@ void wpa_supplicant_event(void *ctx, enu } @@ -253,7 +253,7 @@ struct wpa_supplicant *wpa_s; --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c -@@ -6814,7 +6814,6 @@ struct wpa_interface * wpa_supplicant_ma +@@ -7462,7 +7462,6 @@ struct wpa_interface * wpa_supplicant_ma return NULL; } @@ -261,7 +261,7 @@ /** * wpa_supplicant_match_existing - Match existing interfaces * @global: Pointer to global data from wpa_supplicant_init() -@@ -6849,6 +6848,11 @@ static int wpa_supplicant_match_existing +@@ -7497,6 +7496,11 @@ static int wpa_supplicant_match_existing #endif /* CONFIG_MATCH_IFACE */ @@ -273,7 +273,7 @@ /** * wpa_supplicant_add_iface - Add a new network interface -@@ -7105,6 +7109,8 @@ struct wpa_global * wpa_supplicant_init( +@@ -7753,6 +7757,8 @@ struct wpa_global * wpa_supplicant_init( #ifndef CONFIG_NO_WPA_MSG wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb); #endif /* CONFIG_NO_WPA_MSG */ @@ -284,7 +284,7 @@ wpa_debug_open_file(params->wpa_debug_file_path); --- a/hostapd/main.c +++ b/hostapd/main.c -@@ -590,6 +590,11 @@ fail: +@@ -698,6 +698,11 @@ fail: return -1; } @@ -296,14 +296,14 @@ #ifdef CONFIG_WPS static int gen_uuid(const char *txt_addr) -@@ -683,6 +688,8 @@ int main(int argc, char *argv[]) +@@ -791,6 +796,8 @@ int main(int argc, char *argv[]) return -1; #endif /* CONFIG_DPP */ + wpa_supplicant_event = hostapd_wpa_event; + wpa_supplicant_event_global = hostapd_wpa_event_global; for (;;) { - c = getopt(argc, argv, "b:Bde:f:hi:KP:sSTtu:vg:G:"); + c = getopt(argc, argv, "b:Bde:f:hi:KP:sSTtu:vg:G:q"); if (c < 0) --- a/src/drivers/drivers.c +++ b/src/drivers/drivers.c @@ -320,7 +320,7 @@ { --- a/wpa_supplicant/eapol_test.c +++ b/wpa_supplicant/eapol_test.c -@@ -30,7 +30,12 @@ +@@ -31,7 +31,12 @@ #include "ctrl_iface.h" #include "pcsc_funcs.h" #include "wpas_glue.h" @@ -333,7 +333,7 @@ const struct wpa_driver_ops *const wpa_drivers[] = { NULL }; -@@ -1292,6 +1297,10 @@ static void usage(void) +@@ -1303,6 +1308,10 @@ static void usage(void) "option several times.\n"); } @@ -344,7 +344,7 @@ int main(int argc, char *argv[]) { -@@ -1312,6 +1321,8 @@ int main(int argc, char *argv[]) +@@ -1323,6 +1332,8 @@ int main(int argc, char *argv[]) if (os_program_init()) return -1; diff --git a/feeds/ipq95xx/hostapd/patches/300-noscan.patch b/feeds/ipq95xx/hostapd/patches/300-noscan.patch index 98a431770..3b5f4325d 100644 --- a/feeds/ipq95xx/hostapd/patches/300-noscan.patch +++ b/feeds/ipq95xx/hostapd/patches/300-noscan.patch @@ -1,6 +1,6 @@ --- a/hostapd/config_file.c +++ b/hostapd/config_file.c -@@ -3439,6 +3439,10 @@ static int hostapd_config_fill(struct ho +@@ -3448,6 +3448,10 @@ static int hostapd_config_fill(struct ho if (bss->ocv && !bss->ieee80211w) bss->ieee80211w = 1; #endif /* CONFIG_OCV */ @@ -13,7 +13,7 @@ } else if (os_strcmp(buf, "ht_capab") == 0) { --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h -@@ -995,6 +995,8 @@ struct hostapd_config { +@@ -1075,6 +1075,8 @@ struct hostapd_config { int ht_op_mode_fixed; u16 ht_capab; @@ -24,7 +24,7 @@ int no_pri_sec_switch; --- a/src/ap/hw_features.c +++ b/src/ap/hw_features.c -@@ -517,7 +517,8 @@ static int ieee80211n_check_40mhz(struct +@@ -546,7 +546,8 @@ static int ieee80211n_check_40mhz(struct int ret; /* Check that HT40 is used and PRI / SEC switch is allowed */ @@ -36,7 +36,7 @@ hostapd_set_state(iface, HAPD_IFACE_HT_SCAN); --- a/src/ap/ieee802_11_ht.c +++ b/src/ap/ieee802_11_ht.c -@@ -230,6 +230,9 @@ void hostapd_2040_coex_action(struct hos +@@ -239,6 +239,9 @@ void hostapd_2040_coex_action(struct hos return; } @@ -46,7 +46,7 @@ if (len < IEEE80211_HDRLEN + 2 + sizeof(*bc_ie)) { wpa_printf(MSG_DEBUG, "Ignore too short 20/40 BSS Coexistence Management frame"); -@@ -390,6 +393,9 @@ void ht40_intolerant_add(struct hostapd_ +@@ -399,6 +402,9 @@ void ht40_intolerant_add(struct hostapd_ if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G) return; diff --git a/feeds/ipq95xx/hostapd/patches/301-mesh-noscan.patch b/feeds/ipq95xx/hostapd/patches/301-mesh-noscan.patch deleted file mode 100644 index a301e9fa5..000000000 --- a/feeds/ipq95xx/hostapd/patches/301-mesh-noscan.patch +++ /dev/null @@ -1,81 +0,0 @@ -Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/config.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/config.c -+++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/config.c -@@ -2532,6 +2532,7 @@ static const struct parse_data ssid_fiel - #else /* CONFIG_MESH */ - { INT_RANGE(mode, 0, 4) }, - #endif /* CONFIG_MESH */ -+ { INT_RANGE(noscan, 0, 1) }, - { INT_RANGE(proactive_key_caching, 0, 1) }, - { INT_RANGE(disabled, 0, 2) }, - { STR(id_str) }, -Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/config_file.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/config_file.c -+++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/config_file.c -@@ -769,6 +769,7 @@ static void wpa_config_write_network(FIL - #endif /* IEEE8021X_EAPOL */ - INT(mode); - INT(no_auto_peer); -+ INT(noscan); - INT(mesh_fwding); - INT(frequency); - INT(enable_edmg); -Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/mesh.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/mesh.c -+++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/mesh.c -@@ -505,6 +505,8 @@ static int wpa_supplicant_mesh_init(stru - frequency); - goto out_free; - } -+ if (ssid->noscan) -+ conf->noscan = 1; - - if (ssid->mesh_basic_rates == NULL) { - /* -Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/wpa_supplicant.c -+++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant.c -@@ -2433,7 +2433,7 @@ void ibss_mesh_setup_freq(struct wpa_sup - int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode); - enum hostapd_hw_mode hw_mode; - struct hostapd_hw_modes *mode = NULL; -- int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157, -+ int ht40plus[] = { 1, 2, 3, 4, 5, 6, 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157, - 184, 192 }; - int bw80[] = { 5180, 5260, 5500, 5580, 5660, 5745, 5955, - 6035, 6115, 6195, 6275, 6355, 6435, 6515, -@@ -2441,7 +2441,7 @@ void ibss_mesh_setup_freq(struct wpa_sup - int bw160[] = { 5955, 6115, 6275, 6435, 6595, 6755, 6915 }; - struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL; - u8 channel; -- int i, chan_idx, ht40 = -1, res, obss_scan = 1; -+ int i, chan_idx, ht40 = -1, res, obss_scan = !(ssid->noscan); - unsigned int j, k; - struct hostapd_freq_params vht_freq; - int chwidth, seg0, seg1; -@@ -2530,7 +2530,7 @@ void ibss_mesh_setup_freq(struct wpa_sup - #endif /* CONFIG_HE_OVERRIDES */ - - /* Setup higher BW only for 5 GHz */ -- if (mode->mode != HOSTAPD_MODE_IEEE80211A) -+ if (mode->mode != HOSTAPD_MODE_IEEE80211A && !(ssid->noscan)) - return; - - for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) { -Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/config_ssid.h -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/config_ssid.h -+++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/config_ssid.h -@@ -974,6 +974,8 @@ struct wpa_ssid { - */ - int no_auto_peer; - -+ int noscan; -+ - /** - * mesh_rssi_threshold - Set mesh parameter mesh_rssi_threshold (dBm) - * diff --git a/feeds/ipq95xx/hostapd/patches/310-rescan_immediately.patch b/feeds/ipq95xx/hostapd/patches/310-rescan_immediately.patch index 41f1b1e49..6e0244bca 100644 --- a/feeds/ipq95xx/hostapd/patches/310-rescan_immediately.patch +++ b/feeds/ipq95xx/hostapd/patches/310-rescan_immediately.patch @@ -1,6 +1,6 @@ --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c -@@ -5147,7 +5147,7 @@ wpa_supplicant_alloc(struct wpa_supplica +@@ -5769,7 +5769,7 @@ wpa_supplicant_alloc(struct wpa_supplica if (wpa_s == NULL) return NULL; wpa_s->scan_req = INITIAL_SCAN_REQ; diff --git a/feeds/ipq95xx/hostapd/patches/320-optional_rfkill.patch b/feeds/ipq95xx/hostapd/patches/320-optional_rfkill.patch index a703c7e13..01537790e 100644 --- a/feeds/ipq95xx/hostapd/patches/320-optional_rfkill.patch +++ b/feeds/ipq95xx/hostapd/patches/320-optional_rfkill.patch @@ -1,6 +1,6 @@ --- a/src/drivers/drivers.mak +++ b/src/drivers/drivers.mak -@@ -50,7 +50,6 @@ NEED_SME=y +@@ -54,7 +54,6 @@ NEED_SME=y NEED_AP_MLME=y NEED_NETLINK=y NEED_LINUX_IOCTL=y @@ -8,7 +8,7 @@ NEED_RADIOTAP=y NEED_LIBNL=y endif -@@ -107,7 +106,6 @@ DRV_WPA_CFLAGS += -DCONFIG_DRIVER_WEXT +@@ -111,7 +110,6 @@ DRV_WPA_CFLAGS += -DCONFIG_DRIVER_WEXT CONFIG_WIRELESS_EXTENSION=y NEED_NETLINK=y NEED_LINUX_IOCTL=y @@ -16,7 +16,7 @@ endif ifdef CONFIG_DRIVER_NDIS -@@ -133,7 +131,6 @@ endif +@@ -137,7 +135,6 @@ endif ifdef CONFIG_WIRELESS_EXTENSION DRV_WPA_CFLAGS += -DCONFIG_WIRELESS_EXTENSION DRV_WPA_OBJS += ../src/drivers/driver_wext.o @@ -24,7 +24,7 @@ endif ifdef NEED_NETLINK -@@ -142,6 +139,7 @@ endif +@@ -146,6 +143,7 @@ endif ifdef NEED_RFKILL DRV_OBJS += ../src/drivers/rfkill.o diff --git a/feeds/ipq95xx/hostapd/patches/330-nl80211_fix_set_freq.patch b/feeds/ipq95xx/hostapd/patches/330-nl80211_fix_set_freq.patch index e1070d0f4..c11c95721 100644 --- a/feeds/ipq95xx/hostapd/patches/330-nl80211_fix_set_freq.patch +++ b/feeds/ipq95xx/hostapd/patches/330-nl80211_fix_set_freq.patch @@ -1,8 +1,8 @@ --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c -@@ -4919,7 +4919,7 @@ static int nl80211_set_channel(struct i8 - freq->freq, freq->ht_enabled, freq->vht_enabled, freq->he_enabled, - freq->bandwidth, freq->center_freq1, freq->center_freq2); +@@ -5407,7 +5407,7 @@ static int nl80211_set_channel(struct i8 + freq->he_enabled, freq->eht_enabled, freq->bandwidth, + freq->center_freq1, freq->center_freq2); - msg = nl80211_drv_msg(drv, 0, set_chan ? NL80211_CMD_SET_CHANNEL : + msg = nl80211_bss_msg(bss, 0, set_chan ? NL80211_CMD_SET_CHANNEL : diff --git a/feeds/ipq95xx/hostapd/patches/341-mesh-ctrl-iface-channel-switch.patch b/feeds/ipq95xx/hostapd/patches/341-mesh-ctrl-iface-channel-switch.patch index 73f81f65e..f5ed0d294 100644 --- a/feeds/ipq95xx/hostapd/patches/341-mesh-ctrl-iface-channel-switch.patch +++ b/feeds/ipq95xx/hostapd/patches/341-mesh-ctrl-iface-channel-switch.patch @@ -1,13 +1,18 @@ ---- a/wpa_supplicant/ap.c -+++ b/wpa_supplicant/ap.c -@@ -1513,15 +1513,35 @@ int ap_switch_channel(struct wpa_supplic +Index: hostapd-2023-02-21-ath12.3-cs/wpa_supplicant/ap.c +=================================================================== +--- hostapd-2023-02-21-ath12.3-cs.orig/wpa_supplicant/ap.c ++++ hostapd-2023-02-21-ath12.3-cs/wpa_supplicant/ap.c +@@ -1852,25 +1852,35 @@ int ap_switch_channel(struct wpa_supplic #ifdef CONFIG_CTRL_IFACE +-int ap_ctrl_iface_chanswitch(struct wpa_supplicant *wpa_s, const char *pos) + +static int __ap_ctrl_iface_chanswitch(struct hostapd_iface *iface, + struct csa_settings *settings) -+{ + { +- struct csa_settings settings; +- int ret; +#ifdef NEED_AP_MLME + if (!iface || !iface->bss[0]) + return 0; @@ -17,17 +22,25 @@ + return -1; +#endif +} -+ -+ - int ap_ctrl_iface_chanswitch(struct wpa_supplicant *wpa_s, const char *pos) - { - struct csa_settings settings; - int ret = hostapd_parse_csa_settings(pos, &settings); +- if (wpa_s->ifmsh && wpa_s->ifmsh->conf->disable_csa_dfs == 1) { +- wpa_printf(MSG_DEBUG, "wpa chanswitch interface %s :" +- " cancelling radar handling timeout", +- wpa_s->ifmsh->conf->bss[0]->iface); +- eloop_cancel_timeout(hostapd_dfs_radar_handling_timeout, +- wpa_s->ifmsh, NULL); +- } + +- ret = hostapd_parse_csa_settings(pos, &settings); ++int ap_ctrl_iface_chanswitch(struct wpa_supplicant *wpa_s, const char *pos) ++{ ++ struct csa_settings settings; ++ int ret = hostapd_parse_csa_settings(pos, &settings); ++ + if (!(wpa_s->ap_iface && wpa_s->ap_iface->bss[0]) && + !(wpa_s->ifmsh && wpa_s->ifmsh->bss[0])) + return -1; -+ + + ret = __ap_ctrl_iface_chanswitch(wpa_s->ap_iface, &settings); if (ret) return ret; diff --git a/feeds/ipq95xx/hostapd/patches/350-nl80211_del_beacon_bss.patch b/feeds/ipq95xx/hostapd/patches/350-nl80211_del_beacon_bss.patch deleted file mode 100644 index 41e427c22..000000000 --- a/feeds/ipq95xx/hostapd/patches/350-nl80211_del_beacon_bss.patch +++ /dev/null @@ -1,54 +0,0 @@ ---- a/src/drivers/driver_nl80211.c -+++ b/src/drivers/driver_nl80211.c -@@ -2891,10 +2891,15 @@ static int wpa_driver_nl80211_del_beacon - struct nl_msg *msg; - struct wpa_driver_nl80211_data *drv = bss->drv; - -+ if (!bss->beacon_set) -+ return 0; -+ -+ bss->beacon_set = 0; -+ - wpa_printf(MSG_DEBUG, "nl80211: Remove beacon (ifindex=%d)", -- drv->ifindex); -+ bss->ifindex); - nl80211_put_wiphy_data_ap(bss); -- msg = nl80211_drv_msg(drv, 0, NL80211_CMD_DEL_BEACON); -+ msg = nl80211_bss_msg(bss, 0, NL80211_CMD_DEL_BEACON); - return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); - } - -@@ -5550,7 +5555,7 @@ static void nl80211_teardown_ap(struct i - nl80211_mgmt_unsubscribe(bss, "AP teardown"); - - nl80211_put_wiphy_data_ap(bss); -- bss->beacon_set = 0; -+ wpa_driver_nl80211_del_beacon(bss); - } - - -@@ -7990,8 +7995,6 @@ static int wpa_driver_nl80211_if_remove( - } else { - wpa_printf(MSG_DEBUG, "nl80211: First BSS - reassign context"); - nl80211_teardown_ap(bss); -- if (!bss->added_if && !drv->first_bss->next) -- wpa_driver_nl80211_del_beacon(bss); - nl80211_destroy_bss(bss); - if (!bss->added_if) - i802_set_iface_flags(bss, 0); -@@ -8388,7 +8391,6 @@ static int wpa_driver_nl80211_deinit_ap( - if (!is_ap_interface(drv->nlmode)) - return -1; - wpa_driver_nl80211_del_beacon(bss); -- bss->beacon_set = 0; - - /* - * If the P2P GO interface was dynamically added, then it is -@@ -8408,7 +8410,6 @@ static int wpa_driver_nl80211_stop_ap(vo - if (!is_ap_interface(drv->nlmode)) - return -1; - wpa_driver_nl80211_del_beacon(bss); -- bss->beacon_set = 0; - return 0; - } - diff --git a/feeds/ipq95xx/hostapd/patches/380-disable_ctrl_iface_mib.patch b/feeds/ipq95xx/hostapd/patches/380-disable_ctrl_iface_mib.patch index 80500414b..df01a0859 100644 --- a/feeds/ipq95xx/hostapd/patches/380-disable_ctrl_iface_mib.patch +++ b/feeds/ipq95xx/hostapd/patches/380-disable_ctrl_iface_mib.patch @@ -1,5 +1,7 @@ ---- a/hostapd/Makefile -+++ b/hostapd/Makefile +Index: hostapd-2023-02-21-ath12.3-cs/hostapd/Makefile +=================================================================== +--- hostapd-2023-02-21-ath12.3-cs.orig/hostapd/Makefile ++++ hostapd-2023-02-21-ath12.3-cs/hostapd/Makefile @@ -221,6 +221,9 @@ endif ifdef CONFIG_NO_CTRL_IFACE CFLAGS += -DCONFIG_NO_CTRL_IFACE @@ -10,9 +12,11 @@ ifeq ($(CONFIG_CTRL_IFACE), udp) CFLAGS += -DCONFIG_CTRL_IFACE_UDP else ---- a/hostapd/ctrl_iface.c -+++ b/hostapd/ctrl_iface.c -@@ -3388,6 +3388,7 @@ static int hostapd_ctrl_iface_receive_pr +Index: hostapd-2023-02-21-ath12.3-cs/hostapd/ctrl_iface.c +=================================================================== +--- hostapd-2023-02-21-ath12.3-cs.orig/hostapd/ctrl_iface.c ++++ hostapd-2023-02-21-ath12.3-cs/hostapd/ctrl_iface.c +@@ -3805,6 +3805,7 @@ static int hostapd_ctrl_iface_receive_pr reply_size); } else if (os_strcmp(buf, "STATUS-DRIVER") == 0) { reply_len = hostapd_drv_status(hapd, reply, reply_size); @@ -20,7 +24,7 @@ } else if (os_strcmp(buf, "MIB") == 0) { reply_len = ieee802_11_get_mib(hapd, reply, reply_size); if (reply_len >= 0) { -@@ -3429,6 +3430,7 @@ static int hostapd_ctrl_iface_receive_pr +@@ -3846,6 +3847,7 @@ static int hostapd_ctrl_iface_receive_pr } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply, reply_size); @@ -28,9 +32,11 @@ } else if (os_strcmp(buf, "ATTACH") == 0) { if (hostapd_ctrl_iface_attach(hapd, from, fromlen, NULL)) reply_len = -1; ---- a/wpa_supplicant/Makefile -+++ b/wpa_supplicant/Makefile -@@ -942,6 +942,9 @@ ifdef CONFIG_FILS +Index: hostapd-2023-02-21-ath12.3-cs/wpa_supplicant/Makefile +=================================================================== +--- hostapd-2023-02-21-ath12.3-cs.orig/wpa_supplicant/Makefile ++++ hostapd-2023-02-21-ath12.3-cs/wpa_supplicant/Makefile +@@ -987,6 +987,9 @@ ifdef CONFIG_FILS OBJS += ../src/ap/fils_hlp.o endif ifdef CONFIG_CTRL_IFACE @@ -40,9 +46,11 @@ OBJS += ../src/ap/ctrl_iface_ap.o endif ---- a/wpa_supplicant/ctrl_iface.c -+++ b/wpa_supplicant/ctrl_iface.c -@@ -2294,7 +2294,7 @@ static int wpa_supplicant_ctrl_iface_sta +Index: hostapd-2023-02-21-ath12.3-cs/wpa_supplicant/ctrl_iface.c +=================================================================== +--- hostapd-2023-02-21-ath12.3-cs.orig/wpa_supplicant/ctrl_iface.c ++++ hostapd-2023-02-21-ath12.3-cs/wpa_supplicant/ctrl_iface.c +@@ -2327,7 +2327,7 @@ static int wpa_supplicant_ctrl_iface_sta pos += ret; } @@ -51,7 +59,7 @@ if (wpa_s->ap_iface) { pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos, end - pos, -@@ -10602,6 +10602,7 @@ char * wpa_supplicant_ctrl_iface_process +@@ -11989,6 +11989,7 @@ char * wpa_supplicant_ctrl_iface_process reply_len = -1; } else if (os_strncmp(buf, "NOTE ", 5) == 0) { wpa_printf(MSG_INFO, "NOTE: %s", buf + 5); @@ -59,7 +67,7 @@ } else if (os_strcmp(buf, "MIB") == 0) { reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size); if (reply_len >= 0) { -@@ -10614,6 +10615,7 @@ char * wpa_supplicant_ctrl_iface_process +@@ -12001,6 +12002,7 @@ char * wpa_supplicant_ctrl_iface_process reply_size - reply_len); #endif /* CONFIG_MACSEC */ } @@ -67,7 +75,7 @@ } else if (os_strncmp(buf, "STATUS", 6) == 0) { reply_len = wpa_supplicant_ctrl_iface_status( wpa_s, buf + 6, reply, reply_size); -@@ -11102,6 +11104,7 @@ char * wpa_supplicant_ctrl_iface_process +@@ -12489,6 +12491,7 @@ char * wpa_supplicant_ctrl_iface_process reply_len = wpa_supplicant_ctrl_iface_bss( wpa_s, buf + 4, reply, reply_size); #ifdef CONFIG_AP @@ -75,7 +83,7 @@ } else if (os_strcmp(buf, "STA-FIRST") == 0) { reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size); } else if (os_strncmp(buf, "STA ", 4) == 0) { -@@ -11110,12 +11113,15 @@ char * wpa_supplicant_ctrl_iface_process +@@ -12497,12 +12500,15 @@ char * wpa_supplicant_ctrl_iface_process } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply, reply_size); @@ -91,17 +99,19 @@ } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) { if (ap_ctrl_iface_chanswitch(wpa_s, buf + 12)) reply_len = -1; ---- a/src/ap/ctrl_iface_ap.c -+++ b/src/ap/ctrl_iface_ap.c -@@ -25,6 +25,7 @@ - #include "mbo_ap.h" +Index: hostapd-2023-02-21-ath12.3-cs/src/ap/ctrl_iface_ap.c +=================================================================== +--- hostapd-2023-02-21-ath12.3-cs.orig/src/ap/ctrl_iface_ap.c ++++ hostapd-2023-02-21-ath12.3-cs/src/ap/ctrl_iface_ap.c +@@ -26,6 +26,7 @@ #include "taxonomy.h" + #include "wnm_ap.h" +#ifdef CONFIG_CTRL_IFACE_MIB - static size_t hostapd_write_ht_mcs_bitmask(char *buf, size_t buflen, - size_t curr_len, const u8 *mcs_set) -@@ -451,6 +452,7 @@ int hostapd_ctrl_iface_sta_next(struct h + typedef enum { + BAND_UNII_1 = 1, +@@ -760,6 +761,7 @@ int hostapd_ctrl_iface_sta_next(struct h return hostapd_ctrl_iface_sta_mib(hapd, sta->next, buf, buflen); } @@ -109,7 +119,7 @@ #ifdef CONFIG_P2P_MANAGER static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype, -@@ -807,12 +809,12 @@ int hostapd_ctrl_iface_status(struct hos +@@ -1192,12 +1194,12 @@ int hostapd_ctrl_iface_status(struct hos return len; len += ret; } @@ -124,9 +134,11 @@ if (iface->current_rates && iface->num_rates) { ret = os_snprintf(buf + len, buflen - len, "supported_rates="); if (os_snprintf_error(buflen - len, ret)) ---- a/src/ap/ieee802_1x.c -+++ b/src/ap/ieee802_1x.c -@@ -2712,6 +2712,7 @@ static const char * bool_txt(bool val) +Index: hostapd-2023-02-21-ath12.3-cs/src/ap/ieee802_1x.c +=================================================================== +--- hostapd-2023-02-21-ath12.3-cs.orig/src/ap/ieee802_1x.c ++++ hostapd-2023-02-21-ath12.3-cs/src/ap/ieee802_1x.c +@@ -2768,6 +2768,7 @@ static const char * bool_txt(bool val) return val ? "TRUE" : "FALSE"; } @@ -134,7 +146,7 @@ int ieee802_1x_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen) { -@@ -2898,6 +2899,7 @@ int ieee802_1x_get_mib_sta(struct hostap +@@ -2954,6 +2955,7 @@ int ieee802_1x_get_mib_sta(struct hostap return len; } @@ -142,9 +154,11 @@ #ifdef CONFIG_HS20 static void ieee802_1x_wnm_notif_send(void *eloop_ctx, void *timeout_ctx) ---- a/src/ap/wpa_auth.c -+++ b/src/ap/wpa_auth.c -@@ -4503,6 +4503,7 @@ static const char * wpa_bool_txt(int val +Index: hostapd-2023-02-21-ath12.3-cs/src/ap/wpa_auth.c +=================================================================== +--- hostapd-2023-02-21-ath12.3-cs.orig/src/ap/wpa_auth.c ++++ hostapd-2023-02-21-ath12.3-cs/src/ap/wpa_auth.c +@@ -5715,6 +5715,7 @@ static const char * wpa_bool_txt(int val return val ? "TRUE" : "FALSE"; } @@ -152,7 +166,7 @@ #define RSN_SUITE "%02x-%02x-%02x-%d" #define RSN_SUITE_ARG(s) \ -@@ -4653,7 +4654,7 @@ int wpa_get_mib_sta(struct wpa_state_mac +@@ -5867,7 +5868,7 @@ int wpa_get_mib_sta(struct wpa_state_mac return len; } @@ -161,9 +175,11 @@ void wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth) { ---- a/src/rsn_supp/wpa.c -+++ b/src/rsn_supp/wpa.c -@@ -2763,6 +2763,8 @@ static u32 wpa_key_mgmt_suite(struct wpa +Index: hostapd-2023-02-21-ath12.3-cs/src/rsn_supp/wpa.c +=================================================================== +--- hostapd-2023-02-21-ath12.3-cs.orig/src/rsn_supp/wpa.c ++++ hostapd-2023-02-21-ath12.3-cs/src/rsn_supp/wpa.c +@@ -3835,6 +3835,8 @@ static u32 wpa_key_mgmt_suite(struct wpa } @@ -172,7 +188,7 @@ #define RSN_SUITE "%02x-%02x-%02x-%d" #define RSN_SUITE_ARG(s) \ ((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff -@@ -2844,6 +2846,7 @@ int wpa_sm_get_mib(struct wpa_sm *sm, ch +@@ -3916,6 +3918,7 @@ int wpa_sm_get_mib(struct wpa_sm *sm, ch return (int) len; } @@ -180,9 +196,11 @@ #endif /* CONFIG_CTRL_IFACE */ ---- a/wpa_supplicant/ap.c -+++ b/wpa_supplicant/ap.c -@@ -1364,7 +1364,7 @@ int wpas_ap_wps_nfc_report_handover(stru +Index: hostapd-2023-02-21-ath12.3-cs/wpa_supplicant/ap.c +=================================================================== +--- hostapd-2023-02-21-ath12.3-cs.orig/wpa_supplicant/ap.c ++++ hostapd-2023-02-21-ath12.3-cs/wpa_supplicant/ap.c +@@ -1512,7 +1512,7 @@ int wpas_ap_wps_nfc_report_handover(stru #endif /* CONFIG_WPS */ diff --git a/feeds/ipq95xx/hostapd/patches/381-hostapd_cli_UNKNOWN-COMMAND.patch b/feeds/ipq95xx/hostapd/patches/381-hostapd_cli_UNKNOWN-COMMAND.patch index d2414faf0..e9083f6ec 100644 --- a/feeds/ipq95xx/hostapd/patches/381-hostapd_cli_UNKNOWN-COMMAND.patch +++ b/feeds/ipq95xx/hostapd/patches/381-hostapd_cli_UNKNOWN-COMMAND.patch @@ -1,6 +1,6 @@ --- a/hostapd/hostapd_cli.c +++ b/hostapd/hostapd_cli.c -@@ -744,7 +744,7 @@ static int wpa_ctrl_command_sta(struct w +@@ -757,7 +757,7 @@ static int wpa_ctrl_command_sta(struct w } buf[len] = '\0'; diff --git a/feeds/ipq95xx/hostapd/patches/390-wpa_ie_cap_workaround.patch b/feeds/ipq95xx/hostapd/patches/390-wpa_ie_cap_workaround.patch index 65a8b07e6..4592c3412 100644 --- a/feeds/ipq95xx/hostapd/patches/390-wpa_ie_cap_workaround.patch +++ b/feeds/ipq95xx/hostapd/patches/390-wpa_ie_cap_workaround.patch @@ -1,6 +1,6 @@ --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c -@@ -2444,6 +2444,31 @@ u32 wpa_akm_to_suite(int akm) +@@ -2841,6 +2841,31 @@ u32 wpa_akm_to_suite(int akm) } @@ -32,7 +32,7 @@ int wpa_compare_rsn_ie(int ft_initial_assoc, const u8 *ie1, size_t ie1len, const u8 *ie2, size_t ie2len) -@@ -2451,8 +2476,19 @@ int wpa_compare_rsn_ie(int ft_initial_as +@@ -2848,8 +2873,19 @@ int wpa_compare_rsn_ie(int ft_initial_as if (ie1 == NULL || ie2 == NULL) return -1; diff --git a/feeds/ipq95xx/hostapd/patches/400-wps_single_auth_enc_type.patch b/feeds/ipq95xx/hostapd/patches/400-wps_single_auth_enc_type.patch index 73a8c7694..edcd98525 100644 --- a/feeds/ipq95xx/hostapd/patches/400-wps_single_auth_enc_type.patch +++ b/feeds/ipq95xx/hostapd/patches/400-wps_single_auth_enc_type.patch @@ -11,7 +11,7 @@ bss->wpa_pairwise |= WPA_CIPHER_TKIP; #endif /* CONFIG_NO_TKIP */ bss->rsn_pairwise = bss->wpa_pairwise; -@@ -1178,8 +1177,7 @@ int hostapd_init_wps(struct hostapd_data +@@ -1181,8 +1180,7 @@ int hostapd_init_wps(struct hostapd_data WPA_CIPHER_GCMP_256)) { wps->encr_types |= WPS_ENCR_AES; wps->encr_types_rsn |= WPS_ENCR_AES; diff --git a/feeds/ipq95xx/hostapd/patches/410-limit_debug_messages.patch b/feeds/ipq95xx/hostapd/patches/410-limit_debug_messages.patch index d2713fc29..48a558920 100644 --- a/feeds/ipq95xx/hostapd/patches/410-limit_debug_messages.patch +++ b/feeds/ipq95xx/hostapd/patches/410-limit_debug_messages.patch @@ -60,7 +60,7 @@ #ifdef CONFIG_DEBUG_FILE static char *last_path = NULL; #endif /* CONFIG_DEBUG_FILE */ -@@ -636,7 +610,7 @@ void wpa_msg_register_ifname_cb(wpa_msg_ +@@ -644,7 +618,7 @@ void wpa_msg_register_ifname_cb(wpa_msg_ } @@ -69,7 +69,7 @@ { va_list ap; char *buf; -@@ -674,7 +648,7 @@ void wpa_msg(void *ctx, int level, const +@@ -682,7 +656,7 @@ void wpa_msg(void *ctx, int level, const } @@ -80,9 +80,9 @@ char *buf; --- a/src/utils/wpa_debug.h +++ b/src/utils/wpa_debug.h -@@ -50,6 +50,17 @@ int wpa_debug_reopen_file(void); - void wpa_debug_close_file(void); +@@ -51,6 +51,17 @@ void wpa_debug_close_file(void); void wpa_debug_setup_stdout(void); + void wpa_debug_stop_log(void); +/* internal */ +void _wpa_hexdump(int level, const char *title, const u8 *buf, @@ -98,7 +98,7 @@ /** * wpa_debug_printf_timestamp - Print timestamp for debug output * -@@ -70,9 +81,15 @@ void wpa_debug_print_timestamp(void); +@@ -71,9 +82,15 @@ void wpa_debug_print_timestamp(void); * * Note: New line '\n' is added to the end of the text when printing to stdout. */ @@ -115,7 +115,7 @@ /** * wpa_hexdump - conditional hex dump * @level: priority level (MSG_*) of the message -@@ -84,7 +101,13 @@ PRINTF_FORMAT(2, 3); +@@ -85,7 +102,13 @@ PRINTF_FORMAT(2, 3); * output may be directed to stdout, stderr, and/or syslog based on * configuration. The contents of buf is printed out has hex dump. */ @@ -130,7 +130,7 @@ static inline void wpa_hexdump_buf(int level, const char *title, const struct wpabuf *buf) -@@ -106,7 +129,13 @@ static inline void wpa_hexdump_buf(int l +@@ -107,7 +130,13 @@ static inline void wpa_hexdump_buf(int l * like wpa_hexdump(), but by default, does not include secret keys (passwords, * etc.) in debug output. */ @@ -145,7 +145,7 @@ static inline void wpa_hexdump_buf_key(int level, const char *title, const struct wpabuf *buf) -@@ -128,8 +157,14 @@ static inline void wpa_hexdump_buf_key(i +@@ -129,8 +158,14 @@ static inline void wpa_hexdump_buf_key(i * the hex numbers and ASCII characters (for printable range) are shown. 16 * bytes per line will be shown. */ @@ -162,7 +162,7 @@ /** * wpa_hexdump_ascii_key - conditional hex dump, hide keys -@@ -145,8 +180,14 @@ void wpa_hexdump_ascii(int level, const +@@ -146,8 +181,14 @@ void wpa_hexdump_ascii(int level, const * bytes per line will be shown. This works like wpa_hexdump_ascii(), but by * default, does not include secret keys (passwords, etc.) in debug output. */ @@ -179,7 +179,7 @@ /* * wpa_dbg() behaves like wpa_msg(), but it can be removed from build to reduce -@@ -183,7 +224,12 @@ void wpa_hexdump_ascii_key(int level, co +@@ -184,7 +225,12 @@ void wpa_hexdump_ascii_key(int level, co * * Note: New line '\n' is added to the end of the text when printing to stdout. */ @@ -193,7 +193,7 @@ /** * wpa_msg_ctrl - Conditional printf for ctrl_iface monitors -@@ -197,8 +243,13 @@ void wpa_msg(void *ctx, int level, const +@@ -198,8 +244,13 @@ void wpa_msg(void *ctx, int level, const * attached ctrl_iface monitors. In other words, it can be used for frequent * events that do not need to be sent to syslog. */ diff --git a/feeds/ipq95xx/hostapd/patches/420-indicate-features.patch b/feeds/ipq95xx/hostapd/patches/420-indicate-features.patch index f74db4c02..07df8e5a9 100644 --- a/feeds/ipq95xx/hostapd/patches/420-indicate-features.patch +++ b/feeds/ipq95xx/hostapd/patches/420-indicate-features.patch @@ -1,23 +1,24 @@ --- a/hostapd/main.c +++ b/hostapd/main.c -@@ -15,6 +15,7 @@ - #include "utils/common.h" - #include "utils/eloop.h" - #include "utils/uuid.h" -+#include "utils/build_features.h" - #include "crypto/random.h" - #include "crypto/tls.h" - #include "common/version.h" -@@ -691,7 +692,7 @@ int main(int argc, char *argv[]) +@@ -31,7 +31,7 @@ + #include "config_file.h" + #include "eap_register.h" + #include "ctrl_iface.h" +- ++#include "build_features.h" + + struct hapd_global { + void **drv_priv; +@@ -799,7 +799,7 @@ int main(int argc, char *argv[]) wpa_supplicant_event = hostapd_wpa_event; wpa_supplicant_event_global = hostapd_wpa_event_global; for (;;) { -- c = getopt(argc, argv, "b:Bde:f:hi:KP:sSTtu:vg:G:"); -+ c = getopt(argc, argv, "b:Bde:f:hi:KP:sSTtu:g:G:v::"); +- c = getopt(argc, argv, "b:Bde:f:hi:KP:sSTtu:vg:G:q"); ++ c = getopt(argc, argv, "b:Bde:f:hi:KP:sSTtu:g:G:qv::"); if (c < 0) break; switch (c) { -@@ -728,6 +729,8 @@ int main(int argc, char *argv[]) +@@ -836,6 +836,8 @@ int main(int argc, char *argv[]) break; #endif /* CONFIG_DEBUG_LINUX_TRACING */ case 'v': @@ -25,7 +26,7 @@ + exit(!has_feature(optarg)); show_version(); exit(1); - break; + case 'g': --- a/wpa_supplicant/main.c +++ b/wpa_supplicant/main.c @@ -12,6 +12,7 @@ @@ -33,10 +34,10 @@ #include "common.h" +#include "build_features.h" + #include "crypto/crypto.h" #include "fst/fst.h" #include "wpa_supplicant_i.h" - #include "driver_i.h" -@@ -201,7 +202,7 @@ int main(int argc, char *argv[]) +@@ -202,7 +203,7 @@ int main(int argc, char *argv[]) for (;;) { c = getopt(argc, argv, @@ -45,7 +46,7 @@ if (c < 0) break; switch (c) { -@@ -301,8 +302,12 @@ int main(int argc, char *argv[]) +@@ -302,8 +303,12 @@ int main(int argc, char *argv[]) break; #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */ case 'v': diff --git a/feeds/ipq95xx/hostapd/patches/430-hostapd_cli_ifdef.patch b/feeds/ipq95xx/hostapd/patches/430-hostapd_cli_ifdef.patch index 49ad781d4..a21f0bf7c 100644 --- a/feeds/ipq95xx/hostapd/patches/430-hostapd_cli_ifdef.patch +++ b/feeds/ipq95xx/hostapd/patches/430-hostapd_cli_ifdef.patch @@ -1,6 +1,6 @@ --- a/hostapd/hostapd_cli.c +++ b/hostapd/hostapd_cli.c -@@ -388,7 +388,6 @@ static int hostapd_cli_cmd_disassociate( +@@ -401,7 +401,6 @@ static int hostapd_cli_cmd_disassociate( } @@ -8,7 +8,7 @@ static int hostapd_cli_cmd_signature(struct wpa_ctrl *ctrl, int argc, char *argv[]) { -@@ -401,7 +400,6 @@ static int hostapd_cli_cmd_signature(str +@@ -414,7 +413,6 @@ static int hostapd_cli_cmd_signature(str os_snprintf(buf, sizeof(buf), "SIGNATURE %s", argv[0]); return wpa_ctrl_command(ctrl, buf); } @@ -16,7 +16,7 @@ static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc, -@@ -418,7 +416,6 @@ static int hostapd_cli_cmd_sa_query(stru +@@ -431,7 +429,6 @@ static int hostapd_cli_cmd_sa_query(stru } @@ -24,7 +24,7 @@ static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[]) { -@@ -644,7 +641,6 @@ static int hostapd_cli_cmd_wps_config(st +@@ -657,7 +654,6 @@ static int hostapd_cli_cmd_wps_config(st ssid_hex, argv[1]); return wpa_ctrl_command(ctrl, buf); } @@ -32,7 +32,7 @@ static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc, -@@ -1571,13 +1567,10 @@ static const struct hostapd_cli_cmd host +@@ -1610,13 +1606,10 @@ static const struct hostapd_cli_cmd host { "disassociate", hostapd_cli_cmd_disassociate, hostapd_complete_stations, " = disassociate a station" }, @@ -46,7 +46,7 @@ { "wps_pin", hostapd_cli_cmd_wps_pin, NULL, " [timeout] [addr] = add WPS Enrollee PIN" }, { "wps_check_pin", hostapd_cli_cmd_wps_check_pin, NULL, -@@ -1602,7 +1595,6 @@ static const struct hostapd_cli_cmd host +@@ -1641,7 +1634,6 @@ static const struct hostapd_cli_cmd host " = configure AP" }, { "wps_get_status", hostapd_cli_cmd_wps_get_status, NULL, "= show current WPS status" }, diff --git a/feeds/ipq95xx/hostapd/patches/432-missing-typedef.patch b/feeds/ipq95xx/hostapd/patches/432-missing-typedef.patch deleted file mode 100644 index 7a100f1a0..000000000 --- a/feeds/ipq95xx/hostapd/patches/432-missing-typedef.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/src/drivers/linux_wext.h -+++ b/src/drivers/linux_wext.h -@@ -26,6 +26,7 @@ typedef int32_t __s32; - typedef uint16_t __u16; - typedef int16_t __s16; - typedef uint8_t __u8; -+typedef int8_t __s8; - #ifndef __user - #define __user - #endif /* __user */ diff --git a/feeds/ipq95xx/hostapd/patches/460-wpa_supplicant-add-new-config-params-to-be-used-with.patch b/feeds/ipq95xx/hostapd/patches/460-wpa_supplicant-add-new-config-params-to-be-used-with.patch index e395faaf3..dc19553e2 100644 --- a/feeds/ipq95xx/hostapd/patches/460-wpa_supplicant-add-new-config-params-to-be-used-with.patch +++ b/feeds/ipq95xx/hostapd/patches/460-wpa_supplicant-add-new-config-params-to-be-used-with.patch @@ -22,7 +22,7 @@ Signed-hostap: Antonio Quartulli #include "common/defs.h" #include "common/ieee802_11_defs.h" #include "common/wpa_common.h" -@@ -851,6 +852,9 @@ struct wpa_driver_associate_params { +@@ -953,6 +954,9 @@ struct wpa_driver_associate_params { * responsible for selecting with which BSS to associate. */ const u8 *bssid; @@ -42,7 +42,7 @@ Signed-hostap: Antonio Quartulli #include "config.h" -@@ -2321,6 +2322,97 @@ static char * wpa_config_write_peerkey(c +@@ -2389,6 +2390,97 @@ static char * wpa_config_write_mac_value #endif /* NO_CONFIG_WRITE */ @@ -140,7 +140,7 @@ Signed-hostap: Antonio Quartulli /* Helper macros for network block parser */ #ifdef OFFSET -@@ -2606,6 +2698,8 @@ static const struct parse_data ssid_fiel +@@ -2674,6 +2766,8 @@ static const struct parse_data ssid_fiel { INT(ap_max_inactivity) }, { INT(dtim_period) }, { INT(beacon_int) }, @@ -162,7 +162,7 @@ Signed-hostap: Antonio Quartulli #define DEFAULT_EAP_WORKAROUND ((unsigned int) -1) -@@ -843,6 +845,9 @@ struct wpa_ssid { +@@ -879,6 +881,9 @@ struct wpa_ssid { */ void *parent_cred; @@ -174,7 +174,7 @@ Signed-hostap: Antonio Quartulli * macsec_policy - Determines the policy for MACsec secure session --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c -@@ -3673,6 +3673,12 @@ static void wpas_start_assoc_cb(struct w +@@ -4177,6 +4177,12 @@ static void wpas_start_assoc_cb(struct w params.beacon_int = ssid->beacon_int; else params.beacon_int = wpa_s->conf->beacon_int; diff --git a/feeds/ipq95xx/hostapd/patches/461-driver_nl80211-use-new-parameters-during-ibss-join.patch b/feeds/ipq95xx/hostapd/patches/461-driver_nl80211-use-new-parameters-during-ibss-join.patch deleted file mode 100644 index 19165d028..000000000 --- a/feeds/ipq95xx/hostapd/patches/461-driver_nl80211-use-new-parameters-during-ibss-join.patch +++ /dev/null @@ -1,59 +0,0 @@ -From ffc4445958a3ed4064f2e1bf73fa478a61c5cf7b Mon Sep 17 00:00:00 2001 -From: Antonio Quartulli -Date: Sun, 3 Jun 2012 18:42:25 +0200 -Subject: [PATCHv2 602/602] driver_nl80211: use new parameters during ibss join - -Signed-hostap: Antonio Quartulli ---- - src/drivers/driver_nl80211.c | 33 ++++++++++++++++++++++++++++++++- - 1 file changed, 32 insertions(+), 1 deletion(-) - ---- a/src/drivers/driver_nl80211.c -+++ b/src/drivers/driver_nl80211.c -@@ -5886,7 +5886,7 @@ static int wpa_driver_nl80211_ibss(struc - struct wpa_driver_associate_params *params) - { - struct nl_msg *msg; -- int ret = -1; -+ int ret = -1, i; - int count = 0; - - wpa_printf(MSG_DEBUG, "nl80211: Join IBSS (ifindex=%d)", drv->ifindex); -@@ -5913,6 +5913,37 @@ retry: - nl80211_put_beacon_int(msg, params->beacon_int)) - goto fail; - -+ if (params->fixed_freq) { -+ wpa_printf(MSG_DEBUG, " * fixed_freq"); -+ nla_put_flag(msg, NL80211_ATTR_FREQ_FIXED); -+ } -+ -+ if (params->beacon_int > 0) { -+ wpa_printf(MSG_DEBUG, " * beacon_int=%d", -+ params->beacon_int); -+ nla_put_u32(msg, NL80211_ATTR_BEACON_INTERVAL, -+ params->beacon_int); -+ } -+ -+ if (params->rates[0] > 0) { -+ wpa_printf(MSG_DEBUG, " * basic_rates:"); -+ i = 0; -+ while (i < NL80211_MAX_SUPP_RATES && -+ params->rates[i] > 0) { -+ wpa_printf(MSG_DEBUG, " %.1f", -+ (double)params->rates[i] / 2); -+ i++; -+ } -+ nla_put(msg, NL80211_ATTR_BSS_BASIC_RATES, i, -+ params->rates); -+ } -+ -+ if (params->mcast_rate > 0) { -+ wpa_printf(MSG_DEBUG, " * mcast_rate=%.1f", -+ (double)params->mcast_rate / 10); -+ nla_put_u32(msg, NL80211_ATTR_MCAST_RATE, params->mcast_rate); -+ } -+ - ret = nl80211_set_conn_keys(params, msg); - if (ret) - goto fail; diff --git a/feeds/ipq95xx/hostapd/patches/463-add-mcast_rate-to-11s.patch b/feeds/ipq95xx/hostapd/patches/463-add-mcast_rate-to-11s.patch deleted file mode 100644 index 395c6d31b..000000000 --- a/feeds/ipq95xx/hostapd/patches/463-add-mcast_rate-to-11s.patch +++ /dev/null @@ -1,68 +0,0 @@ -From: Sven Eckelmann -Date: Thu, 11 May 2017 08:21:45 +0200 -Subject: [PATCH] set mcast_rate in mesh mode - -The wpa_supplicant code for IBSS allows to set the mcast rate. It is -recommended to increase this value from 1 or 6 Mbit/s to something higher -when using a mesh protocol on top which uses the multicast packet loss as -indicator for the link quality. - -This setting was unfortunately not applied for mesh mode. But it would be -beneficial when wpa_supplicant would behave similar to IBSS mode and set -this argument during mesh join like authsae already does. At least it is -helpful for companies/projects which are currently switching to 802.11s -(without mesh_fwding and with mesh_ttl set to 1) as replacement for IBSS -because newer drivers seem to support 802.11s but not IBSS anymore. - -Signed-off-by: Sven Eckelmann -Tested-by: Simon Wunderlich - ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -1618,6 +1618,7 @@ struct wpa_driver_mesh_join_params { - #define WPA_DRIVER_MESH_FLAG_AMPE 0x00000008 - unsigned int flags; - bool handle_dfs; -+ int mcast_rate; - }; - - struct wpa_driver_set_key_params { ---- a/src/drivers/driver_nl80211.c -+++ b/src/drivers/driver_nl80211.c -@@ -10398,6 +10398,18 @@ static int nl80211_put_mesh_id(struct nl - } - - -+static int nl80211_put_mcast_rate(struct nl_msg *msg, int mcast_rate) -+{ -+ if (mcast_rate > 0) { -+ wpa_printf(MSG_DEBUG, " * mcast_rate=%.1f", -+ (double)mcast_rate / 10); -+ return nla_put_u32(msg, NL80211_ATTR_MCAST_RATE, mcast_rate); -+ } -+ -+ return 0; -+} -+ -+ - static int nl80211_put_mesh_config(struct nl_msg *msg, - struct wpa_driver_mesh_bss_params *params) - { -@@ -10459,6 +10471,7 @@ static int nl80211_join_mesh(struct i802 - nl80211_put_basic_rates(msg, params->basic_rates) || - nl80211_put_mesh_id(msg, params->meshid, params->meshid_len) || - nl80211_put_beacon_int(msg, params->beacon_int) || -+ nl80211_put_mcast_rate(msg, params->mcast_rate) || - nl80211_put_dtim_period(msg, params->dtim_period)) - goto fail; - ---- a/wpa_supplicant/mesh.c -+++ b/wpa_supplicant/mesh.c -@@ -600,6 +600,7 @@ int wpa_supplicant_join_mesh(struct wpa_ - - params->meshid = ssid->ssid; - params->meshid_len = ssid->ssid_len; -+ params->mcast_rate = ssid->mcast_rate; - ibss_mesh_setup_freq(wpa_s, ssid, ¶ms->freq); - wpa_s->mesh_ht_enabled = !!params->freq.ht_enabled; - wpa_s->mesh_vht_enabled = !!params->freq.vht_enabled; diff --git a/feeds/ipq95xx/hostapd/patches/464-fix-mesh-obss-check.patch b/feeds/ipq95xx/hostapd/patches/464-fix-mesh-obss-check.patch index 0e9d2590d..300491042 100644 --- a/feeds/ipq95xx/hostapd/patches/464-fix-mesh-obss-check.patch +++ b/feeds/ipq95xx/hostapd/patches/464-fix-mesh-obss-check.patch @@ -1,19 +1,14 @@ ---- a/wpa_supplicant/wpa_supplicant.c -+++ b/wpa_supplicant/wpa_supplicant.c -@@ -2403,11 +2403,13 @@ void ibss_mesh_setup_freq(struct wpa_sup - for (j = 0; j < wpa_s->last_scan_res_used; j++) { - struct wpa_bss *bss = wpa_s->last_scan_res[j]; +Index: hostapd-2023-02-21-ath12.3-cs/wpa_supplicant/wpa_supplicant.c +=================================================================== +--- hostapd-2023-02-21-ath12.3-cs.orig/wpa_supplicant/wpa_supplicant.c ++++ hostapd-2023-02-21-ath12.3-cs/wpa_supplicant/wpa_supplicant.c +@@ -2744,6 +2744,9 @@ void ibss_mesh_setup_freq(struct wpa_sup + bool is_24ghz, is_6ghz; -- if (ssid->mode != WPAS_MODE_IBSS) -+ /* Don't adjust control freq in case of fixed_freq */ -+ if (ssid->fixed_freq) { -+ obss_scan = 0; - break; -+ } + freq->freq = ssid->frequency; ++ if (ssid->fixed_freq) { ++ obss_scan = 0; ++ } -- /* Don't adjust control freq in case of fixed_freq */ -- if (ssid->fixed_freq) -+ if (ssid->mode != WPAS_MODE_IBSS) - break; - - if (!bss_is_ibss(bss)) + for (j = 0; j < wpa_s->last_scan_res_used; j++) { + struct wpa_bss *bss = wpa_s->last_scan_res[j]; diff --git a/feeds/ipq95xx/hostapd/patches/470-survey_data_fallback.patch b/feeds/ipq95xx/hostapd/patches/470-survey_data_fallback.patch index 4b791c7f6..79ab48c5c 100644 --- a/feeds/ipq95xx/hostapd/patches/470-survey_data_fallback.patch +++ b/feeds/ipq95xx/hostapd/patches/470-survey_data_fallback.patch @@ -1,44 +1,29 @@ -Index: hostapd-2021-12-13-b26f5c0f/src/ap/acs.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/ap/acs.c -+++ hostapd-2021-12-13-b26f5c0f/src/ap/acs.c -@@ -302,16 +302,12 @@ static void acs_fail(struct hostapd_ifac - static long double - acs_survey_interference_factor(struct freq_survey *survey, s8 min_nf) - { -- long double factor, busy, total; -+ long double factor, busy = 0, total; - - if (survey->filled & SURVEY_HAS_CHAN_TIME_BUSY) - busy = survey->channel_time_busy; - else if (survey->filled & SURVEY_HAS_CHAN_TIME_RX) - busy = survey->channel_time_rx; -- else { -- wpa_printf(MSG_ERROR, "ACS: Survey data missing"); -- return 0; -- } - - total = survey->channel_time; - -@@ -420,20 +416,19 @@ static int acs_usable_bw160_chan(const s +--- a/src/ap/acs.c ++++ b/src/ap/acs.c +@@ -455,17 +455,17 @@ static int acs_get_bw_center_chan(int fr static int acs_survey_is_sufficient(struct freq_survey *survey) { if (!(survey->filled & SURVEY_HAS_NF)) { + survey->nf = -95; - wpa_printf(MSG_INFO, "ACS: Survey is missing noise floor"); + wpa_printf(MSG_INFO, + "ACS: Survey for freq %d is missing noise floor", + survey->freq); - return 0; } if (!(survey->filled & SURVEY_HAS_CHAN_TIME)) { + survey->channel_time = 0; - wpa_printf(MSG_INFO, "ACS: Survey is missing channel time"); + wpa_printf(MSG_INFO, + "ACS: Survey for freq %d is missing channel time", + survey->freq); - return 0; } if (!(survey->filled & SURVEY_HAS_CHAN_TIME_BUSY) && - !(survey->filled & SURVEY_HAS_CHAN_TIME_RX)) { +@@ -473,7 +473,6 @@ static int acs_survey_is_sufficient(stru wpa_printf(MSG_INFO, - "ACS: Survey is missing RX and busy time (at least one is required)"); + "ACS: Survey for freq %d is missing RX and busy time (at least one is required)", + survey->freq); - return 0; } diff --git a/feeds/ipq95xx/hostapd/patches/500-lto-jobserver-support.patch b/feeds/ipq95xx/hostapd/patches/500-lto-jobserver-support.patch index 7ba3e096e..67312c500 100644 --- a/feeds/ipq95xx/hostapd/patches/500-lto-jobserver-support.patch +++ b/feeds/ipq95xx/hostapd/patches/500-lto-jobserver-support.patch @@ -1,6 +1,6 @@ --- a/hostapd/Makefile +++ b/hostapd/Makefile -@@ -1293,7 +1293,7 @@ hostapd_multi.a: $(BCHECK) $(OBJS) +@@ -1396,7 +1396,7 @@ hostapd_multi.a: $(BCHECK) $(OBJS) @$(AR) cr $@ hostapd_multi.o $(OBJS) hostapd: $(OBJS) @@ -9,7 +9,7 @@ @$(E) " LD " $@ ifdef CONFIG_WPA_TRACE -@@ -1304,7 +1304,7 @@ _OBJS_VAR := OBJS_c +@@ -1407,7 +1407,7 @@ _OBJS_VAR := OBJS_c include ../src/objs.mk hostapd_cli: $(OBJS_c) @@ -20,7 +20,7 @@ NOBJS = nt_password_hash.o ../src/crypto/ms_funcs.o $(SHA1OBJS) --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile -@@ -1905,31 +1905,31 @@ wpa_supplicant_multi.a: .config $(BCHECK +@@ -2037,31 +2037,31 @@ wpa_supplicant_multi.a: .config $(BCHECK @$(AR) cr $@ wpa_supplicant_multi.o $(OBJS) wpa_supplicant: $(BCHECK) $(OBJS) $(EXTRA_progs) diff --git a/feeds/ipq95xx/hostapd/patches/590-rrm-wnm-statistics.patch b/feeds/ipq95xx/hostapd/patches/590-rrm-wnm-statistics.patch index 737fdbb5d..0efa6db90 100644 --- a/feeds/ipq95xx/hostapd/patches/590-rrm-wnm-statistics.patch +++ b/feeds/ipq95xx/hostapd/patches/590-rrm-wnm-statistics.patch @@ -1,6 +1,6 @@ --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h -@@ -148,6 +148,21 @@ struct hostapd_sae_commit_queue { +@@ -163,6 +163,21 @@ struct hostapd_sae_commit_queue { }; /** @@ -22,9 +22,9 @@ * struct hostapd_data - hostapd per-BSS data structure */ struct hostapd_data { -@@ -161,6 +176,9 @@ struct hostapd_data { +@@ -182,6 +197,9 @@ struct hostapd_data { - u8 own_addr[ETH_ALEN]; + struct hostapd_data *mld_first_bss; + /* OpenWrt specific statistics */ + struct hostapd_openwrt_stats openwrt_stats; @@ -42,9 +42,9 @@ wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request to " MACSTR " dialog_token=%u req_mode=0x%x disassoc_timer=%u " "validity_interval=%u", -@@ -646,10 +647,12 @@ int ieee802_11_rx_wnm_action_ap(struct h - - switch (action) { +@@ -790,10 +791,12 @@ int ieee802_11_rx_wnm_action_ap(struct h + plen); + return 0; case WNM_BSS_TRANS_MGMT_QUERY: + hapd->openwrt_stats.wnm.bss_transition_query_rx++; ieee802_11_rx_bss_trans_mgmt_query(hapd, mgmt->sa, payload, @@ -55,7 +55,7 @@ ieee802_11_rx_bss_trans_mgmt_resp(hapd, mgmt->sa, payload, plen); return 0; -@@ -696,6 +699,7 @@ int wnm_send_disassoc_imminent(struct ho +@@ -840,6 +843,7 @@ int wnm_send_disassoc_imminent(struct ho pos = mgmt->u.action.u.bss_tm_req.variable; @@ -63,7 +63,7 @@ wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request frame to indicate imminent disassociation (disassoc_timer=%d) to " MACSTR, disassoc_timer, MAC2STR(sta->addr)); if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0, NULL, 0, 0) < 0) { -@@ -777,6 +781,7 @@ int wnm_send_ess_disassoc_imminent(struc +@@ -921,6 +925,7 @@ int wnm_send_ess_disassoc_imminent(struc return -1; } @@ -71,7 +71,7 @@ if (disassoc_timer) { /* send disassociation frame after time-out */ set_disassoc_timer(hapd, sta, disassoc_timer); -@@ -856,6 +861,7 @@ int wnm_send_bss_tm_req(struct hostapd_d +@@ -1001,6 +1006,7 @@ int wnm_send_bss_tm_req(struct hostapd_d } os_free(buf); diff --git a/feeds/ipq95xx/hostapd/patches/600-ubus_support.patch b/feeds/ipq95xx/hostapd/patches/600-ubus_support.patch index ad48368a2..c858abdee 100644 --- a/feeds/ipq95xx/hostapd/patches/600-ubus_support.patch +++ b/feeds/ipq95xx/hostapd/patches/600-ubus_support.patch @@ -1,7 +1,7 @@ -Index: hostapd-2021-02-20-59e9794c/hostapd/Makefile +Index: hostapd-2023-02-21-ath12.3-cs/hostapd/Makefile =================================================================== ---- hostapd-2021-02-20-59e9794c.orig/hostapd/Makefile -+++ hostapd-2021-02-20-59e9794c/hostapd/Makefile +--- hostapd-2023-02-21-ath12.3-cs.orig/hostapd/Makefile ++++ hostapd-2023-02-21-ath12.3-cs/hostapd/Makefile @@ -166,6 +166,12 @@ OBJS += ../src/common/hw_features_common OBJS += ../src/eapol_auth/eapol_auth_sm.o @@ -15,11 +15,11 @@ Index: hostapd-2021-02-20-59e9794c/hostapd/Makefile ifdef CONFIG_CODE_COVERAGE CFLAGS += -O0 -fprofile-arcs -ftest-coverage -Index: hostapd-2021-02-20-59e9794c/src/ap/hostapd.h +Index: hostapd-2023-02-21-ath12.3-cs/src/ap/hostapd.h =================================================================== ---- hostapd-2021-02-20-59e9794c.orig/src/ap/hostapd.h -+++ hostapd-2021-02-20-59e9794c/src/ap/hostapd.h -@@ -17,6 +17,7 @@ +--- hostapd-2023-02-21-ath12.3-cs.orig/src/ap/hostapd.h ++++ hostapd-2023-02-21-ath12.3-cs/src/ap/hostapd.h +@@ -18,6 +18,7 @@ #include "utils/list.h" #include "ap_config.h" #include "drivers/driver.h" @@ -27,15 +27,15 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/hostapd.h #define OCE_STA_CFON_ENABLED(hapd) \ ((hapd->conf->oce & OCE_STA_CFON) && \ -@@ -169,6 +170,7 @@ struct hostapd_data { - struct hostapd_iface *iface; +@@ -203,6 +204,7 @@ struct hostapd_data { + #endif struct hostapd_config *iconf; struct hostapd_bss_config *conf; + struct hostapd_ubus_bss ubus; int interface_added; /* virtual interface added for this BSS */ unsigned int started:1; unsigned int disabled:1; -@@ -626,6 +628,7 @@ hostapd_alloc_bss_data(struct hostapd_if +@@ -741,6 +743,7 @@ hostapd_alloc_bss_data(struct hostapd_if struct hostapd_bss_config *bss); int hostapd_setup_interface(struct hostapd_iface *iface); int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err); @@ -43,11 +43,11 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/hostapd.h void hostapd_interface_deinit(struct hostapd_iface *iface); void hostapd_interface_free(struct hostapd_iface *iface); struct hostapd_iface * hostapd_alloc_iface(void); -Index: hostapd-2021-02-20-59e9794c/src/ap/hostapd.c +Index: hostapd-2023-02-21-ath12.3-cs/src/ap/hostapd.c =================================================================== ---- hostapd-2021-02-20-59e9794c.orig/src/ap/hostapd.c -+++ hostapd-2021-02-20-59e9794c/src/ap/hostapd.c -@@ -376,6 +376,7 @@ void hostapd_free_hapd_data(struct hosta +--- hostapd-2023-02-21-ath12.3-cs.orig/src/ap/hostapd.c ++++ hostapd-2023-02-21-ath12.3-cs/src/ap/hostapd.c +@@ -471,6 +471,7 @@ void hostapd_free_hapd_data(struct hosta hapd->beacon_set_done = 0; wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface); @@ -55,7 +55,7 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/hostapd.c accounting_deinit(hapd); hostapd_deinit_wpa(hapd); vlan_deinit(hapd); -@@ -1398,6 +1399,8 @@ static int hostapd_setup_bss(struct host +@@ -1224,6 +1225,8 @@ static int hostapd_start_beacon(struct h if (hapd->driver && hapd->driver->set_operstate) hapd->driver->set_operstate(hapd->drv_priv, 1); @@ -64,15 +64,15 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/hostapd.c return 0; } -@@ -1983,6 +1986,7 @@ static int hostapd_setup_interface_compl +@@ -2331,6 +2334,7 @@ static int hostapd_setup_interface_compl if (err) goto fail; + hostapd_ubus_add_iface(iface); wpa_printf(MSG_DEBUG, "Completing interface initialization"); + if (iface->freq) { - #ifdef NEED_AP_MLME -@@ -2180,6 +2184,7 @@ dfs_offload: +@@ -2567,6 +2571,7 @@ dfs_offload: fail: wpa_printf(MSG_ERROR, "Interface initialization failed"); @@ -80,7 +80,7 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/hostapd.c hostapd_set_state(iface, HAPD_IFACE_DISABLED); wpa_msg(hapd->msg_ctx, MSG_INFO, AP_EVENT_DISABLED); #ifdef CONFIG_FST -@@ -2653,6 +2658,7 @@ void hostapd_interface_deinit_free(struc +@@ -3464,6 +3469,7 @@ void hostapd_interface_deinit_free(struc (unsigned int) iface->conf->num_bss); driver = iface->bss[0]->driver; drv_priv = iface->bss[0]->drv_priv; @@ -88,11 +88,21 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/hostapd.c hostapd_interface_deinit(iface); wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit", __func__, driver, drv_priv); -Index: hostapd-2021-02-20-59e9794c/src/ap/ieee802_11.c +Index: hostapd-2023-02-21-ath12.3-cs/src/ap/ieee802_11.c =================================================================== ---- hostapd-2021-02-20-59e9794c.orig/src/ap/ieee802_11.c -+++ hostapd-2021-02-20-59e9794c/src/ap/ieee802_11.c -@@ -3421,13 +3421,18 @@ static void handle_auth(struct hostapd_d +--- hostapd-2023-02-21-ath12.3-cs.orig/src/ap/ieee802_11.c ++++ hostapd-2023-02-21-ath12.3-cs/src/ap/ieee802_11.c +@@ -87,8 +87,7 @@ static size_t hostapd_eid_basic_resp_mle + + static void handle_auth(struct hostapd_data *hapd, + struct ieee80211_mgmt *mgmt, size_t len, +- int rssi, int from_queue, +- struct hostapd_frame_info *fi); ++ int rssi, int from_queue); + + + u8 * hostapd_eid_multi_ap(struct hostapd_data *hapd, u8 *eid) +@@ -2785,7 +2784,7 @@ static void handle_auth(struct hostapd_d u16 auth_alg, auth_transaction, status_code; u16 resp = WLAN_STATUS_SUCCESS; struct sta_info *sta = NULL; @@ -101,9 +111,10 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/ieee802_11.c u16 fc; const u8 *challenge = NULL; u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN]; - size_t resp_ies_len = 0; - u16 seq_ctrl; - struct radius_sta rad_info; +@@ -2800,6 +2799,11 @@ static void handle_auth(struct hostapd_d + const u8 *token = NULL; + size_t token_len = 0; + int parsed_len = 0; + struct hostapd_ubus_request req = { + .type = HOSTAPD_UBUS_AUTH_REQ, + .mgmt_frame = mgmt, @@ -112,7 +123,7 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/ieee802_11.c if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) { wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)", -@@ -3595,6 +3600,13 @@ static void handle_auth(struct hostapd_d +@@ -3019,6 +3023,13 @@ skip_ml_parsing: resp = WLAN_STATUS_UNSPECIFIED_FAILURE; goto fail; } @@ -126,7 +137,7 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/ieee802_11.c if (res == HOSTAPD_ACL_PENDING) return; -@@ -5322,7 +5334,7 @@ static void handle_assoc(struct hostapd_ +@@ -5519,7 +5530,7 @@ static void handle_assoc(struct hostapd_ int resp = WLAN_STATUS_SUCCESS; u16 reply_res = WLAN_STATUS_UNSPECIFIED_FAILURE; const u8 *pos; @@ -135,7 +146,7 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/ieee802_11.c struct sta_info *sta; u8 *tmp = NULL; #ifdef CONFIG_FILS -@@ -5535,6 +5547,11 @@ static void handle_assoc(struct hostapd_ +@@ -5733,6 +5744,11 @@ static void handle_assoc(struct hostapd_ left = res; } #endif /* CONFIG_FILS */ @@ -147,7 +158,7 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/ieee802_11.c /* followed by SSID and Supported rates; and HT capabilities if 802.11n * is used */ -@@ -5633,6 +5650,13 @@ static void handle_assoc(struct hostapd_ +@@ -5840,6 +5856,13 @@ static void handle_assoc(struct hostapd_ } #endif /* CONFIG_FILS */ @@ -161,31 +172,30 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/ieee802_11.c fail: /* -@@ -5726,6 +5750,7 @@ static void handle_disassoc(struct hosta - wpa_printf(MSG_DEBUG, "disassocation: STA=" MACSTR " reason_code=%d", - MAC2STR(mgmt->sa), - le_to_host16(mgmt->u.disassoc.reason_code)); +@@ -6019,6 +6042,7 @@ static void handle_deauth(struct hostapd + + /* Clear the PTKSA cache entries for PASN */ + ptksa_cache_flush(hapd->ptksa, mgmt->sa, WPA_CIPHER_NONE); ++ hostapd_ubus_notify(hapd, "deauth", mgmt->sa); + + sta = ap_get_sta(hapd, mgmt->sa); + if (sta == NULL) { +@@ -6141,6 +6165,7 @@ static int handle_action(struct hostapd_ + sta->last_seq_ctrl = seq_ctrl; + sta->last_subtype = WLAN_FC_STYPE_ACTION; + } + hostapd_ubus_notify(hapd, "disassoc", mgmt->sa); - sta = ap_get_sta(hapd, mgmt->sa); - if (sta == NULL) { -@@ -5792,6 +5817,8 @@ static void handle_deauth(struct hostapd - " reason_code=%d", - MAC2STR(mgmt->sa), le_to_host16(mgmt->u.deauth.reason_code)); - -+ hostapd_ubus_notify(hapd, "deauth", mgmt->sa); -+ - sta = ap_get_sta(hapd, mgmt->sa); - if (sta == NULL) { - wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " trying " -Index: hostapd-2021-02-20-59e9794c/src/ap/beacon.c + switch (mgmt->u.action.category) { + #ifdef CONFIG_IEEE80211R_AP +Index: hostapd-2023-02-21-ath12.3-cs/src/ap/beacon.c =================================================================== ---- hostapd-2021-02-20-59e9794c.orig/src/ap/beacon.c -+++ hostapd-2021-02-20-59e9794c/src/ap/beacon.c -@@ -823,6 +823,12 @@ void handle_probe_req(struct hostapd_dat - u16 csa_offs[2]; +--- hostapd-2023-02-21-ath12.3-cs.orig/src/ap/beacon.c ++++ hostapd-2023-02-21-ath12.3-cs/src/ap/beacon.c +@@ -1424,6 +1424,12 @@ void handle_probe_req(struct hostapd_dat size_t csa_offs_len; struct radius_sta rad_info; + struct multi_link_data ml_data; + struct hostapd_ubus_request req = { + .type = HOSTAPD_UBUS_PROBE_REQ, + .mgmt_frame = mgmt, @@ -193,9 +203,9 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/beacon.c + .elems = &elems, + }; - if (hapd->iconf->rssi_ignore_probe_request && ssi_signal && - ssi_signal < hapd->iconf->rssi_ignore_probe_request) -@@ -1009,6 +1015,12 @@ void handle_probe_req(struct hostapd_dat + os_memset(&ml_data, 0, sizeof(struct multi_link_data)); + +@@ -1612,6 +1618,12 @@ void handle_probe_req(struct hostapd_dat } #endif /* CONFIG_P2P */ @@ -208,11 +218,11 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/beacon.c /* TODO: verify that supp_rates contains at least one matching rate * with AP configuration */ -Index: hostapd-2021-02-20-59e9794c/src/ap/drv_callbacks.c +Index: hostapd-2023-02-21-ath12.3-cs/src/ap/drv_callbacks.c =================================================================== ---- hostapd-2021-02-20-59e9794c.orig/src/ap/drv_callbacks.c -+++ hostapd-2021-02-20-59e9794c/src/ap/drv_callbacks.c -@@ -145,6 +145,10 @@ int hostapd_notif_assoc(struct hostapd_d +--- hostapd-2023-02-21-ath12.3-cs.orig/src/ap/drv_callbacks.c ++++ hostapd-2023-02-21-ath12.3-cs/src/ap/drv_callbacks.c +@@ -147,6 +147,10 @@ int hostapd_notif_assoc(struct hostapd_d u16 reason = WLAN_REASON_UNSPECIFIED; int status = WLAN_STATUS_SUCCESS; const u8 *p2p_dev_addr = NULL; @@ -223,7 +233,7 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/drv_callbacks.c if (addr == NULL) { /* -@@ -237,6 +241,12 @@ int hostapd_notif_assoc(struct hostapd_d +@@ -239,6 +243,12 @@ int hostapd_notif_assoc(struct hostapd_d goto fail; } @@ -236,23 +246,11 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/drv_callbacks.c #ifdef CONFIG_P2P if (elems.p2p) { wpabuf_free(sta->p2p_ie); -@@ -981,9 +991,11 @@ void hostapd_event_ch_switch(struct host - - wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED - "freq=%d dfs=%d", freq, is_dfs); -+ hostapd_ubus_notify_csa(hapd, freq); - } else if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) { - wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED - "freq=%d dfs=%d", freq, is_dfs); -+ hostapd_ubus_notify_csa(hapd, freq); - } else if (is_dfs && - hostapd_is_dfs_required(hapd->iface) && - !hostapd_is_dfs_chan_available(hapd->iface) && -Index: hostapd-2021-02-20-59e9794c/src/ap/sta_info.c +Index: hostapd-2023-02-21-ath12.3-cs/src/ap/sta_info.c =================================================================== ---- hostapd-2021-02-20-59e9794c.orig/src/ap/sta_info.c -+++ hostapd-2021-02-20-59e9794c/src/ap/sta_info.c -@@ -458,6 +458,7 @@ void ap_handle_timer(void *eloop_ctx, vo +--- hostapd-2023-02-21-ath12.3-cs.orig/src/ap/sta_info.c ++++ hostapd-2023-02-21-ath12.3-cs/src/ap/sta_info.c +@@ -597,6 +597,7 @@ void ap_handle_timer(void *eloop_ctx, vo hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "deauthenticated due to " "local deauth request"); @@ -260,7 +258,7 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/sta_info.c ap_free_sta(hapd, sta); return; } -@@ -613,6 +614,7 @@ skip_poll: +@@ -752,6 +753,7 @@ skip_poll: mlme_deauthenticate_indication( hapd, sta, WLAN_REASON_PREV_AUTH_NOT_VALID); @@ -268,7 +266,7 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/sta_info.c ap_free_sta(hapd, sta); break; } -@@ -1298,12 +1300,25 @@ void ap_sta_set_authorized(struct hostap +@@ -1592,15 +1594,28 @@ void ap_sta_set_authorized(struct hostap sta->addr, authorized, dev_addr); if (authorized) { @@ -283,18 +281,21 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/sta_info.c + [WLAN_AUTH_PASN] = "pasn", + }; + const char *auth_alg = NULL; + const u8 *dpp_pkhash; const char *keyid; + char dpp_pkhash_buf[100]; char keyid_buf[100]; char ip_addr[100]; + char alg_buf[100]; + dpp_pkhash_buf[0] = '\0'; keyid_buf[0] = '\0'; ip_addr[0] = '\0'; + alg_buf[0] = '\0'; #ifdef CONFIG_P2P if (wpa_auth_get_ip_addr(sta->wpa_sm, ip_addr_buf) == 0) { os_snprintf(ip_addr, sizeof(ip_addr), -@@ -1313,22 +1328,31 @@ void ap_sta_set_authorized(struct hostap +@@ -1610,6 +1625,13 @@ void ap_sta_set_authorized(struct hostap } #endif /* CONFIG_P2P */ @@ -308,33 +309,35 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/sta_info.c keyid = ap_sta_wpa_get_keyid(hapd, sta); if (keyid) { os_snprintf(keyid_buf, sizeof(keyid_buf), - " keyid=%s", keyid); +@@ -1628,17 +1650,19 @@ void ap_sta_set_authorized(struct hostap + dpp_pkhash, SHA256_MAC_LEN); } -- wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s%s", -- buf, ip_addr, keyid_buf); -+ hostapd_ubus_notify_authorized(hapd, sta); -+ wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s%s%s", -+ buf, ip_addr, keyid_buf, alg_buf); +- wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s%s%s", +- buf, ip_addr, keyid_buf, dpp_pkhash_buf); ++ hostapd_ubus_notify_authorized(hapd, sta, auth_alg); ++ wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s%s%s%s", ++ buf, ip_addr, keyid_buf, dpp_pkhash_buf, alg_buf); if (hapd->msg_ctx_parent && hapd->msg_ctx_parent != hapd->msg_ctx) wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO, -- AP_STA_CONNECTED "%s%s%s", -- buf, ip_addr, keyid_buf); -+ AP_STA_CONNECTED "%s%s%s%s", -+ buf, ip_addr, keyid_buf, alg_buf); +- AP_STA_CONNECTED "%s%s%s%s", ++ AP_STA_CONNECTED "%s%s%s%s%s", + buf, ip_addr, keyid_buf, +- dpp_pkhash_buf); ++ dpp_pkhash_buf, alg_buf); } else { wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf); + hostapd_ubus_notify(hapd, "disassoc", sta->addr); if (hapd->msg_ctx_parent && hapd->msg_ctx_parent != hapd->msg_ctx) -Index: hostapd-2021-02-20-59e9794c/src/ap/wpa_auth_glue.c +Index: hostapd-2023-02-21-ath12.3-cs/src/ap/wpa_auth_glue.c =================================================================== ---- hostapd-2021-02-20-59e9794c.orig/src/ap/wpa_auth_glue.c -+++ hostapd-2021-02-20-59e9794c/src/ap/wpa_auth_glue.c -@@ -265,6 +265,7 @@ static void hostapd_wpa_auth_psk_failure +--- hostapd-2023-02-21-ath12.3-cs.orig/src/ap/wpa_auth_glue.c ++++ hostapd-2023-02-21-ath12.3-cs/src/ap/wpa_auth_glue.c +@@ -270,6 +270,7 @@ static void hostapd_wpa_auth_psk_failure struct hostapd_data *hapd = ctx; wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_POSSIBLE_PSK_MISMATCH MACSTR, MAC2STR(addr)); @@ -342,11 +345,11 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/wpa_auth_glue.c } -Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/Makefile +Index: hostapd-2023-02-21-ath12.3-cs/wpa_supplicant/Makefile =================================================================== ---- hostapd-2021-02-20-59e9794c.orig/wpa_supplicant/Makefile -+++ hostapd-2021-02-20-59e9794c/wpa_supplicant/Makefile -@@ -169,6 +169,13 @@ ifdef CONFIG_EAPOL_TEST +--- hostapd-2023-02-21-ath12.3-cs.orig/wpa_supplicant/Makefile ++++ hostapd-2023-02-21-ath12.3-cs/wpa_supplicant/Makefile +@@ -192,6 +192,13 @@ ifdef CONFIG_EAPOL_TEST CFLAGS += -Werror -DEAPOL_TEST endif @@ -360,7 +363,7 @@ Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/Makefile ifdef CONFIG_CODE_COVERAGE CFLAGS += -O0 -fprofile-arcs -ftest-coverage LIBS += -lgcov -@@ -946,6 +953,9 @@ ifdef CONFIG_CTRL_IFACE_MIB +@@ -991,6 +998,9 @@ ifdef CONFIG_CTRL_IFACE_MIB CFLAGS += -DCONFIG_CTRL_IFACE_MIB endif OBJS += ../src/ap/ctrl_iface_ap.o @@ -370,11 +373,11 @@ Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/Makefile endif CFLAGS += -DEAP_SERVER -DEAP_SERVER_IDENTITY -Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/wpa_supplicant.c +Index: hostapd-2023-02-21-ath12.3-cs/wpa_supplicant/wpa_supplicant.c =================================================================== ---- hostapd-2021-02-20-59e9794c.orig/wpa_supplicant/wpa_supplicant.c -+++ hostapd-2021-02-20-59e9794c/wpa_supplicant/wpa_supplicant.c -@@ -6943,6 +6943,8 @@ struct wpa_supplicant * wpa_supplicant_a +--- hostapd-2023-02-21-ath12.3-cs.orig/wpa_supplicant/wpa_supplicant.c ++++ hostapd-2023-02-21-ath12.3-cs/wpa_supplicant/wpa_supplicant.c +@@ -7640,6 +7640,8 @@ struct wpa_supplicant * wpa_supplicant_a } #endif /* CONFIG_P2P */ @@ -383,7 +386,7 @@ Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/wpa_supplicant.c return wpa_s; } -@@ -6969,6 +6971,8 @@ int wpa_supplicant_remove_iface(struct w +@@ -7666,6 +7668,8 @@ int wpa_supplicant_remove_iface(struct w struct wpa_supplicant *parent = wpa_s->parent; #endif /* CONFIG_MESH */ @@ -392,7 +395,7 @@ Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/wpa_supplicant.c /* Remove interface from the global list of interfaces */ prev = global->ifaces; if (prev == wpa_s) { -@@ -7272,8 +7276,12 @@ int wpa_supplicant_run(struct wpa_global +@@ -8012,8 +8016,12 @@ int wpa_supplicant_run(struct wpa_global eloop_register_signal_terminate(wpa_supplicant_terminate, global); eloop_register_signal_reconfig(wpa_supplicant_reconfig, global); @@ -405,19 +408,19 @@ Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/wpa_supplicant.c return 0; } -Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/wpa_supplicant_i.h +Index: hostapd-2023-02-21-ath12.3-cs/wpa_supplicant/wpa_supplicant_i.h =================================================================== ---- hostapd-2021-02-20-59e9794c.orig/wpa_supplicant/wpa_supplicant_i.h -+++ hostapd-2021-02-20-59e9794c/wpa_supplicant/wpa_supplicant_i.h -@@ -19,6 +19,7 @@ - #include "wps/wps_defs.h" +--- hostapd-2023-02-21-ath12.3-cs.orig/wpa_supplicant/wpa_supplicant_i.h ++++ hostapd-2023-02-21-ath12.3-cs/wpa_supplicant/wpa_supplicant_i.h +@@ -21,6 +21,7 @@ #include "config_ssid.h" #include "wmm_ac.h" + #include "pasn/pasn_common.h" +#include "ubus.h" extern const char *const wpa_supplicant_version; extern const char *const wpa_supplicant_license; -@@ -316,6 +317,8 @@ struct wpa_global { +@@ -319,6 +320,8 @@ struct wpa_global { #endif /* CONFIG_WIFI_DISPLAY */ struct psk_list_entry *add_psk; /* From group formation */ @@ -426,7 +429,7 @@ Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/wpa_supplicant_i.h }; -@@ -596,6 +599,7 @@ struct wpa_supplicant { +@@ -650,6 +653,7 @@ struct wpa_supplicant { unsigned char own_addr[ETH_ALEN]; unsigned char perm_addr[ETH_ALEN]; char ifname[100]; @@ -434,10 +437,10 @@ Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/wpa_supplicant_i.h #ifdef CONFIG_MATCH_IFACE int matched; #endif /* CONFIG_MATCH_IFACE */ -Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/wps_supplicant.c +Index: hostapd-2023-02-21-ath12.3-cs/wpa_supplicant/wps_supplicant.c =================================================================== ---- hostapd-2021-02-20-59e9794c.orig/wpa_supplicant/wps_supplicant.c -+++ hostapd-2021-02-20-59e9794c/wpa_supplicant/wps_supplicant.c +--- hostapd-2023-02-21-ath12.3-cs.orig/wpa_supplicant/wps_supplicant.c ++++ hostapd-2023-02-21-ath12.3-cs/wpa_supplicant/wps_supplicant.c @@ -33,6 +33,7 @@ #include "p2p/p2p.h" #include "p2p_supplicant.h" @@ -446,7 +449,7 @@ Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/wps_supplicant.c #ifndef WPS_PIN_SCAN_IGNORE_SEL_REG -@@ -392,6 +393,8 @@ static int wpa_supplicant_wps_cred(void +@@ -402,6 +403,8 @@ static int wpa_supplicant_wps_cred(void wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute", cred->cred_attr, cred->cred_attr_len); @@ -455,11 +458,11 @@ Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/wps_supplicant.c if (wpa_s->conf->wps_cred_processing == 1) return 0; -Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/main.c +Index: hostapd-2023-02-21-ath12.3-cs/wpa_supplicant/main.c =================================================================== ---- hostapd-2021-02-20-59e9794c.orig/wpa_supplicant/main.c -+++ hostapd-2021-02-20-59e9794c/wpa_supplicant/main.c -@@ -202,7 +202,7 @@ int main(int argc, char *argv[]) +--- hostapd-2023-02-21-ath12.3-cs.orig/wpa_supplicant/main.c ++++ hostapd-2023-02-21-ath12.3-cs/wpa_supplicant/main.c +@@ -203,7 +203,7 @@ int main(int argc, char *argv[]) for (;;) { c = getopt(argc, argv, @@ -468,7 +471,7 @@ Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/main.c if (c < 0) break; switch (c) { -@@ -267,6 +267,9 @@ int main(int argc, char *argv[]) +@@ -268,6 +268,9 @@ int main(int argc, char *argv[]) params.conf_p2p_dev = optarg; break; #endif /* CONFIG_P2P */ @@ -478,10 +481,10 @@ Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/main.c case 'o': params.override_driver = optarg; break; -Index: hostapd-2021-02-20-59e9794c/src/ap/rrm.c +Index: hostapd-2023-02-21-ath12.3-cs/src/ap/rrm.c =================================================================== ---- hostapd-2021-02-20-59e9794c.orig/src/ap/rrm.c -+++ hostapd-2021-02-20-59e9794c/src/ap/rrm.c +--- hostapd-2023-02-21-ath12.3-cs.orig/src/ap/rrm.c ++++ hostapd-2023-02-21-ath12.3-cs/src/ap/rrm.c @@ -89,6 +89,9 @@ static void hostapd_handle_beacon_report return; wpa_msg(hapd->msg_ctx, MSG_INFO, BEACON_RESP_RX MACSTR " %u %02x %s", @@ -492,10 +495,18 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/rrm.c } -Index: hostapd-2021-02-20-59e9794c/src/ap/vlan_init.c +@@ -360,6 +363,7 @@ void hostapd_handle_radio_measurement(st + break; + case WLAN_RRM_LINK_MEASUREMENT_REPORT: + hostapd_handle_link_mesr_report(hapd, buf, len); ++ hostapd_ubus_handle_link_measurement(hapd, buf, len); + break; + default: + wpa_printf(MSG_DEBUG, "RRM action %u is not supported", +Index: hostapd-2023-02-21-ath12.3-cs/src/ap/vlan_init.c =================================================================== ---- hostapd-2021-02-20-59e9794c.orig/src/ap/vlan_init.c -+++ hostapd-2021-02-20-59e9794c/src/ap/vlan_init.c +--- hostapd-2023-02-21-ath12.3-cs.orig/src/ap/vlan_init.c ++++ hostapd-2023-02-21-ath12.3-cs/src/ap/vlan_init.c @@ -22,6 +22,7 @@ static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan, int existsok) @@ -532,11 +543,11 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/vlan_init.c return hostapd_vlan_if_remove(hapd, vlan->ifname); } -Index: hostapd-2021-02-20-59e9794c/src/ap/dfs.c +Index: hostapd-2023-02-21-ath12.3-cs/src/ap/dfs.c =================================================================== ---- hostapd-2021-02-20-59e9794c.orig/src/ap/dfs.c -+++ hostapd-2021-02-20-59e9794c/src/ap/dfs.c -@@ -1226,6 +1226,8 @@ int hostapd_dfs_nop_finished(struct host +--- hostapd-2023-02-21-ath12.3-cs.orig/src/ap/dfs.c ++++ hostapd-2023-02-21-ath12.3-cs/src/ap/dfs.c +@@ -1331,6 +1331,8 @@ int hostapd_dfs_pre_cac_expired(struct h "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d", freq, ht_enabled, chan_offset, chan_width, cf1, cf2); @@ -545,11 +556,11 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/dfs.c /* Proceed only if DFS is not offloaded to the driver */ if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) return 0; -Index: hostapd-2021-02-20-59e9794c/src/ap/airtime_policy.c +Index: hostapd-2023-02-21-ath12.3-cs/src/ap/airtime_policy.c =================================================================== ---- hostapd-2021-02-20-59e9794c.orig/src/ap/airtime_policy.c -+++ hostapd-2021-02-20-59e9794c/src/ap/airtime_policy.c -@@ -108,8 +108,14 @@ static void set_sta_weights(struct hosta +--- hostapd-2023-02-21-ath12.3-cs.orig/src/ap/airtime_policy.c ++++ hostapd-2023-02-21-ath12.3-cs/src/ap/airtime_policy.c +@@ -112,8 +112,14 @@ static void set_sta_weights(struct hosta { struct sta_info *sta; @@ -566,7 +577,7 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/airtime_policy.c } -@@ -240,7 +246,10 @@ int airtime_policy_new_sta(struct hostap +@@ -244,7 +250,10 @@ int airtime_policy_new_sta(struct hostap unsigned int weight; if (hapd->iconf->airtime_mode == AIRTIME_MODE_STATIC) { @@ -578,11 +589,11 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/airtime_policy.c if (weight) return sta_set_airtime_weight(hapd, sta, weight); } -Index: hostapd-2021-02-20-59e9794c/src/ap/sta_info.h +Index: hostapd-2023-02-21-ath12.3-cs/src/ap/sta_info.h =================================================================== ---- hostapd-2021-02-20-59e9794c.orig/src/ap/sta_info.h -+++ hostapd-2021-02-20-59e9794c/src/ap/sta_info.h -@@ -323,6 +323,7 @@ struct sta_info { +--- hostapd-2023-02-21-ath12.3-cs.orig/src/ap/sta_info.h ++++ hostapd-2023-02-21-ath12.3-cs/src/ap/sta_info.h +@@ -322,6 +322,7 @@ struct sta_info { #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_AIRTIME_POLICY unsigned int airtime_weight; @@ -590,13 +601,13 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/sta_info.h struct os_reltime backlogged_until; #endif /* CONFIG_AIRTIME_POLICY */ -Index: hostapd-2021-02-20-59e9794c/src/ap/wnm_ap.c +Index: hostapd-2023-02-21-ath12.3-cs/src/ap/wnm_ap.c =================================================================== ---- hostapd-2021-02-20-59e9794c.orig/src/ap/wnm_ap.c -+++ hostapd-2021-02-20-59e9794c/src/ap/wnm_ap.c -@@ -442,7 +442,8 @@ static void ieee802_11_rx_bss_trans_mgmt - wpa_hexdump(MSG_DEBUG, "WNM: BSS Transition Candidate List Entries", - pos, end - pos); +--- hostapd-2023-02-21-ath12.3-cs.orig/src/ap/wnm_ap.c ++++ hostapd-2023-02-21-ath12.3-cs/src/ap/wnm_ap.c +@@ -495,7 +495,8 @@ static void ieee802_11_rx_bss_trans_mgmt + MAC2STR(addr), reason, hex ? " neighbor=" : "", hex); + os_free(hex); - ieee802_11_send_bss_trans_mgmt_request(hapd, addr, dialog_token); + if (!hostapd_ubus_notify_bss_transition_query(hapd, addr, dialog_token, reason, pos, end - pos)) @@ -604,7 +615,7 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/wnm_ap.c } -@@ -464,7 +465,7 @@ static void ieee802_11_rx_bss_trans_mgmt +@@ -517,7 +518,7 @@ static void ieee802_11_rx_bss_trans_mgmt size_t len) { u8 dialog_token, status_code, bss_termination_delay; @@ -613,7 +624,7 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/wnm_ap.c int enabled = hapd->conf->bss_transition; struct sta_info *sta; -@@ -511,6 +512,7 @@ static void ieee802_11_rx_bss_trans_mgmt +@@ -564,6 +565,7 @@ static void ieee802_11_rx_bss_trans_mgmt wpa_printf(MSG_DEBUG, "WNM: not enough room for Target BSSID field"); return; } @@ -621,7 +632,7 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/wnm_ap.c sta->agreed_to_steer = 1; eloop_cancel_timeout(ap_sta_reset_steer_flag_timer, hapd, sta); eloop_register_timeout(2, 0, ap_sta_reset_steer_flag_timer, -@@ -530,6 +532,10 @@ static void ieee802_11_rx_bss_trans_mgmt +@@ -583,6 +585,10 @@ static void ieee802_11_rx_bss_trans_mgmt MAC2STR(addr), status_code, bss_termination_delay); } @@ -632,10 +643,10 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/wnm_ap.c wpa_hexdump(MSG_DEBUG, "WNM: BSS Transition Candidate List Entries", pos, end - pos); } -Index: hostapd-2021-02-20-59e9794c/src/utils/eloop.c +Index: hostapd-2023-02-21-ath12.3-cs/src/utils/eloop.c =================================================================== ---- hostapd-2021-02-20-59e9794c.orig/src/utils/eloop.c -+++ hostapd-2021-02-20-59e9794c/src/utils/eloop.c +--- hostapd-2023-02-21-ath12.3-cs.orig/src/utils/eloop.c ++++ hostapd-2023-02-21-ath12.3-cs/src/utils/eloop.c @@ -77,6 +77,9 @@ struct eloop_sock_table { struct eloop_data { int max_sock; @@ -646,7 +657,7 @@ Index: hostapd-2021-02-20-59e9794c/src/utils/eloop.c size_t count; /* sum of all table counts */ #ifdef CONFIG_ELOOP_POLL size_t max_pollfd_map; /* number of pollfds_map currently allocated */ -@@ -1116,6 +1119,12 @@ void eloop_run(void) +@@ -1121,6 +1124,12 @@ void eloop_run(void) os_reltime_sub(&timeout->time, &now, &tv); else tv.sec = tv.usec = 0; @@ -659,7 +670,7 @@ Index: hostapd-2021-02-20-59e9794c/src/utils/eloop.c #if defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) timeout_ms = tv.sec * 1000 + tv.usec / 1000; #endif /* defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) */ -@@ -1185,7 +1194,8 @@ void eloop_run(void) +@@ -1190,7 +1199,8 @@ void eloop_run(void) eloop.exceptions.changed = 0; eloop_process_pending_signals(); @@ -669,7 +680,7 @@ Index: hostapd-2021-02-20-59e9794c/src/utils/eloop.c /* check if some registered timeouts have occurred */ timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, -@@ -1247,6 +1257,14 @@ out: +@@ -1252,6 +1262,14 @@ out: return; } @@ -684,10 +695,10 @@ Index: hostapd-2021-02-20-59e9794c/src/utils/eloop.c void eloop_terminate(void) { -Index: hostapd-2021-02-20-59e9794c/src/utils/eloop.h +Index: hostapd-2023-02-21-ath12.3-cs/src/utils/eloop.h =================================================================== ---- hostapd-2021-02-20-59e9794c.orig/src/utils/eloop.h -+++ hostapd-2021-02-20-59e9794c/src/utils/eloop.h +--- hostapd-2023-02-21-ath12.3-cs.orig/src/utils/eloop.h ++++ hostapd-2023-02-21-ath12.3-cs/src/utils/eloop.h @@ -65,6 +65,9 @@ typedef void (*eloop_timeout_handler)(vo */ typedef void (*eloop_signal_handler)(int sig, void *signal_ctx); @@ -717,10 +728,10 @@ Index: hostapd-2021-02-20-59e9794c/src/utils/eloop.h /** * eloop_run - Start the event loop * -Index: hostapd-2021-02-20-59e9794c/src/utils/uloop.c +Index: hostapd-2023-02-21-ath12.3-cs/src/utils/uloop.c =================================================================== --- /dev/null -+++ hostapd-2021-02-20-59e9794c/src/utils/uloop.c ++++ hostapd-2023-02-21-ath12.3-cs/src/utils/uloop.c @@ -0,0 +1,64 @@ +#include +#include "includes.h" diff --git a/feeds/ipq95xx/hostapd/patches/601-ucode_support.patch b/feeds/ipq95xx/hostapd/patches/601-ucode_support.patch index fabf81032..dd7af7c74 100644 --- a/feeds/ipq95xx/hostapd/patches/601-ucode_support.patch +++ b/feeds/ipq95xx/hostapd/patches/601-ucode_support.patch @@ -1,7 +1,7 @@ -Index: hostapd-2021-12-13-b26f5c0f/hostapd/Makefile +Index: hostapd-2023-02-21-ath12.3-cs/hostapd/Makefile =================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/hostapd/Makefile -+++ hostapd-2021-12-13-b26f5c0f/hostapd/Makefile +--- hostapd-2023-02-21-ath12.3-cs.orig/hostapd/Makefile ++++ hostapd-2023-02-21-ath12.3-cs/hostapd/Makefile @@ -168,9 +168,21 @@ OBJS += ../src/eapol_auth/eapol_auth_sm. ifdef CONFIG_UBUS @@ -26,11 +26,11 @@ Index: hostapd-2021-12-13-b26f5c0f/hostapd/Makefile endif ifdef CONFIG_CODE_COVERAGE -Index: hostapd-2021-12-13-b26f5c0f/hostapd/main.c +Index: hostapd-2023-02-21-ath12.3-cs/hostapd/main.c =================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/hostapd/main.c -+++ hostapd-2021-12-13-b26f5c0f/hostapd/main.c -@@ -898,6 +898,7 @@ int main(int argc, char *argv[]) +--- hostapd-2023-02-21-ath12.3-cs.orig/hostapd/main.c ++++ hostapd-2023-02-21-ath12.3-cs/hostapd/main.c +@@ -985,6 +985,7 @@ int main(int argc, char *argv[]) } hostapd_global_ctrl_iface_init(&interfaces); @@ -38,19 +38,19 @@ Index: hostapd-2021-12-13-b26f5c0f/hostapd/main.c if (hostapd_global_run(&interfaces, daemonize, pid_file)) { wpa_printf(MSG_ERROR, "Failed to start eloop"); -@@ -907,6 +908,7 @@ int main(int argc, char *argv[]) +@@ -994,6 +995,7 @@ int main(int argc, char *argv[]) ret = 0; out: + hostapd_ucode_free(); hostapd_global_ctrl_iface_deinit(&interfaces); - /* Deinitialize all interfaces */ - for (i = 0; i < interfaces.count; i++) { -Index: hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.h + /* Sending deauth to all stations before deinit */ + hostapd_deauthenticate_stations(&interfaces); +Index: hostapd-2023-02-21-ath12.3-cs/src/ap/hostapd.h =================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/ap/hostapd.h -+++ hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.h -@@ -18,6 +18,7 @@ +--- hostapd-2023-02-21-ath12.3-cs.orig/src/ap/hostapd.h ++++ hostapd-2023-02-21-ath12.3-cs/src/ap/hostapd.h +@@ -19,6 +19,7 @@ #include "ap_config.h" #include "drivers/driver.h" #include "ubus.h" @@ -58,7 +58,7 @@ Index: hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.h #define OCE_STA_CFON_ENABLED(hapd) \ ((hapd->conf->oce & OCE_STA_CFON) && \ -@@ -50,6 +51,10 @@ struct hapd_interfaces { +@@ -56,6 +57,10 @@ struct hapd_interfaces { struct hostapd_config * (*config_read_cb)(const char *config_fname); int (*ctrl_iface_init)(struct hostapd_data *hapd); void (*ctrl_iface_deinit)(struct hostapd_data *hapd); @@ -69,7 +69,7 @@ Index: hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.h int (*for_each_interface)(struct hapd_interfaces *interfaces, int (*cb)(struct hostapd_iface *iface, void *ctx), void *ctx); -@@ -173,6 +178,7 @@ struct hostapd_data { +@@ -205,6 +210,7 @@ struct hostapd_data { struct hostapd_config *iconf; struct hostapd_bss_config *conf; struct hostapd_ubus_bss ubus; @@ -77,7 +77,7 @@ Index: hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.h int interface_added; /* virtual interface added for this BSS */ unsigned int started:1; unsigned int disabled:1; -@@ -467,6 +473,7 @@ struct hostapd_sta_info { +@@ -540,6 +546,7 @@ struct hostapd_mld { */ struct hostapd_iface { struct hapd_interfaces *interfaces; @@ -85,7 +85,7 @@ Index: hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.h void *owner; char *config_fname; struct hostapd_config *conf; -@@ -641,6 +648,8 @@ struct hostapd_iface * hostapd_init(stru +@@ -752,6 +759,8 @@ struct hostapd_iface * hostapd_init(stru struct hostapd_iface * hostapd_interface_init_bss(struct hapd_interfaces *interfaces, const char *phy, const char *config_fname, int debug); @@ -94,11 +94,11 @@ Index: hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.h void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta, int reassoc); void hostapd_interface_deinit_free(struct hostapd_iface *iface); -Index: hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.c +Index: hostapd-2023-02-21-ath12.3-cs/src/ap/hostapd.c =================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/ap/hostapd.c -+++ hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.c -@@ -217,6 +217,8 @@ int hostapd_reload_config(struct hostapd +--- hostapd-2023-02-21-ath12.3-cs.orig/src/ap/hostapd.c ++++ hostapd-2023-02-21-ath12.3-cs/src/ap/hostapd.c +@@ -285,6 +285,8 @@ int hostapd_reload_config(struct hostapd struct hostapd_config *newconf, *oldconf; size_t j; @@ -107,7 +107,7 @@ Index: hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.c if (iface->config_fname == NULL) { /* Only in-memory config in use - assume it has been updated */ hostapd_clear_old(iface); -@@ -377,6 +379,7 @@ void hostapd_free_hapd_data(struct hosta +@@ -471,6 +473,7 @@ void hostapd_free_hapd_data(struct hosta hapd->beacon_set_done = 0; wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface); @@ -115,24 +115,15 @@ Index: hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.c hostapd_ubus_free_bss(hapd); accounting_deinit(hapd); hostapd_deinit_wpa(hapd); -@@ -534,6 +537,7 @@ void hostapd_cleanup_iface_partial(struc +@@ -637,6 +640,7 @@ void hostapd_cleanup_iface_partial(struc static void hostapd_cleanup_iface(struct hostapd_iface *iface) { wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface); + hostapd_ucode_free_iface(iface); - eloop_cancel_timeout(channel_list_update_timeout, iface, NULL); eloop_cancel_timeout(hostapd_interface_setup_failure_handler, iface, NULL); -@@ -1108,7 +1112,7 @@ static int db_table_create_radius_attrib - * initialized. Most of the modules that are initialized here will be - * deinitialized in hostapd_cleanup(). - */ --static int hostapd_setup_bss(struct hostapd_data *hapd, int first) -+int hostapd_setup_bss(struct hostapd_data *hapd, int first, bool set_beacon) - { - struct hostapd_bss_config *conf = hapd->conf; - u8 ssid[SSID_MAX_LEN + 1]; -@@ -1405,6 +1409,7 @@ static int hostapd_setup_bss(struct host + +@@ -1226,6 +1230,7 @@ static int hostapd_start_beacon(struct h hapd->driver->set_operstate(hapd->drv_priv, 1); hostapd_ubus_add_bss(hapd); @@ -140,16 +131,17 @@ Index: hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.c return 0; } -@@ -2116,7 +2121,7 @@ static int hostapd_setup_interface_compl - hapd = iface->bss[j]; - if (j) - os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN); -- if (hostapd_setup_bss(hapd, j == 0)) { -+ if (hostapd_setup_bss(hapd, j == 0, true)) { - for (;;) { - hapd = iface->bss[j]; - hostapd_bss_deinit_no_free(hapd); -@@ -2396,7 +2401,7 @@ hostapd_alloc_bss_data(struct hostapd_if +@@ -1248,8 +1253,7 @@ static int hostapd_start_beacon(struct h + * initialized. Most of the modules that are initialized here will be + * deinitialized in hostapd_cleanup(). + */ +-static int hostapd_setup_bss(struct hostapd_data *hapd, int first, +- bool start_beacon) ++int hostapd_setup_bss(struct hostapd_data *hapd, int first, bool start_beacon) + { + struct hostapd_bss_config *conf = hapd->conf; + u8 ssid[SSID_MAX_LEN + 1]; +@@ -2919,7 +2923,7 @@ hostapd_alloc_bss_data(struct hostapd_if } @@ -158,16 +150,7 @@ Index: hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.c { if (!hapd) return; -@@ -3013,7 +3018,7 @@ int hostapd_add_iface(struct hapd_interf - - if (start_ctrl_iface_bss(hapd) < 0 || - (hapd_iface->state == HAPD_IFACE_ENABLED && -- hostapd_setup_bss(hapd, -1))) { -+ hostapd_setup_bss(hapd, -1, true))) { - hostapd_cleanup(hapd); - hapd_iface->bss[hapd_iface->num_bss - 1] = NULL; - hapd_iface->conf->num_bss--; -@@ -3165,7 +3170,8 @@ int hostapd_remove_iface(struct hapd_int +@@ -4086,7 +4090,8 @@ int hostapd_remove_iface(struct hapd_int hapd_iface = interfaces->iface[i]; if (hapd_iface == NULL) return -1; @@ -177,11 +160,11 @@ Index: hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.c wpa_printf(MSG_INFO, "Remove interface '%s'", buf); hapd_iface->driver_ap_teardown = !!(hapd_iface->drv_flags & -Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/Makefile +Index: hostapd-2023-02-21-ath12.3-cs/wpa_supplicant/Makefile =================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/Makefile -+++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/Makefile -@@ -177,8 +177,20 @@ endif +--- hostapd-2023-02-21-ath12.3-cs.orig/wpa_supplicant/Makefile ++++ hostapd-2023-02-21-ath12.3-cs/wpa_supplicant/Makefile +@@ -195,8 +195,20 @@ endif ifdef CONFIG_UBUS CFLAGS += -DUBUS_SUPPORT OBJS += ubus.o @@ -203,7 +186,7 @@ Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/Makefile endif ifdef CONFIG_CODE_COVERAGE -@@ -969,6 +981,9 @@ OBJS += ../src/ap/ctrl_iface_ap.o +@@ -1001,6 +1013,9 @@ OBJS += ../src/ap/ctrl_iface_ap.o ifdef CONFIG_UBUS OBJS += ../src/ap/ubus.o endif @@ -213,11 +196,11 @@ Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/Makefile endif CFLAGS += -DEAP_SERVER -DEAP_SERVER_IDENTITY -Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant.c +Index: hostapd-2023-02-21-ath12.3-cs/wpa_supplicant/wpa_supplicant.c =================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/wpa_supplicant.c -+++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant.c -@@ -1033,6 +1033,7 @@ void wpa_supplicant_set_state(struct wpa +--- hostapd-2023-02-21-ath12.3-cs.orig/wpa_supplicant/wpa_supplicant.c ++++ hostapd-2023-02-21-ath12.3-cs/wpa_supplicant/wpa_supplicant.c +@@ -1044,6 +1044,7 @@ void wpa_supplicant_set_state(struct wpa sme_sched_obss_scan(wpa_s, 0); } wpa_s->wpa_state = state; @@ -225,7 +208,7 @@ Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant.c #ifdef CONFIG_BGSCAN if (state == WPA_COMPLETED && wpa_s->current_ssid != wpa_s->bgscan_ssid) -@@ -7155,6 +7156,7 @@ struct wpa_supplicant * wpa_supplicant_a +@@ -7641,6 +7642,7 @@ struct wpa_supplicant * wpa_supplicant_a #endif /* CONFIG_P2P */ wpas_ubus_add_bss(wpa_s); @@ -233,7 +216,7 @@ Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant.c return wpa_s; } -@@ -7182,6 +7184,7 @@ int wpa_supplicant_remove_iface(struct w +@@ -7668,6 +7670,7 @@ int wpa_supplicant_remove_iface(struct w struct wpa_supplicant *parent = wpa_s->parent; #endif /* CONFIG_MESH */ @@ -241,7 +224,7 @@ Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant.c wpas_ubus_free_bss(wpa_s); /* Remove interface from the global list of interfaces */ -@@ -7449,6 +7452,7 @@ struct wpa_global * wpa_supplicant_init( +@@ -7978,6 +7981,7 @@ struct wpa_global * wpa_supplicant_init( eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0, wpas_periodic, global, NULL); @@ -249,7 +232,7 @@ Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant.c return global; } -@@ -7487,12 +7491,8 @@ int wpa_supplicant_run(struct wpa_global +@@ -8016,12 +8020,8 @@ int wpa_supplicant_run(struct wpa_global eloop_register_signal_terminate(wpa_supplicant_terminate, global); eloop_register_signal_reconfig(wpa_supplicant_reconfig, global); @@ -262,7 +245,7 @@ Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant.c return 0; } -@@ -7525,6 +7525,8 @@ void wpa_supplicant_deinit(struct wpa_gl +@@ -8054,6 +8054,8 @@ void wpa_supplicant_deinit(struct wpa_gl wpas_notify_supplicant_deinitialized(global); @@ -271,19 +254,19 @@ Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant.c eap_peer_unregister_methods(); #ifdef CONFIG_AP eap_server_unregister_methods(); -Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant_i.h +Index: hostapd-2023-02-21-ath12.3-cs/wpa_supplicant/wpa_supplicant_i.h =================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/wpa_supplicant_i.h -+++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant_i.h -@@ -20,6 +20,7 @@ - #include "config_ssid.h" +--- hostapd-2023-02-21-ath12.3-cs.orig/wpa_supplicant/wpa_supplicant_i.h ++++ hostapd-2023-02-21-ath12.3-cs/wpa_supplicant/wpa_supplicant_i.h +@@ -22,6 +22,7 @@ #include "wmm_ac.h" + #include "pasn/pasn_common.h" #include "ubus.h" +#include "ucode.h" extern const char *const wpa_supplicant_version; extern const char *const wpa_supplicant_license; -@@ -707,6 +708,7 @@ struct wpa_supplicant { +@@ -654,6 +655,7 @@ struct wpa_supplicant { unsigned char perm_addr[ETH_ALEN]; char ifname[100]; struct wpas_ubus_bss ubus; @@ -291,11 +274,11 @@ Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant_i.h #ifdef CONFIG_MATCH_IFACE int matched; #endif /* CONFIG_MATCH_IFACE */ -Index: hostapd-2021-12-13-b26f5c0f/hostapd/ctrl_iface.c +Index: hostapd-2023-02-21-ath12.3-cs/hostapd/ctrl_iface.c =================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/hostapd/ctrl_iface.c -+++ hostapd-2021-12-13-b26f5c0f/hostapd/ctrl_iface.c -@@ -5023,6 +5023,7 @@ try_again: +--- hostapd-2023-02-21-ath12.3-cs.orig/hostapd/ctrl_iface.c ++++ hostapd-2023-02-21-ath12.3-cs/hostapd/ctrl_iface.c +@@ -5369,6 +5369,7 @@ try_again: return -1; } @@ -303,7 +286,7 @@ Index: hostapd-2021-12-13-b26f5c0f/hostapd/ctrl_iface.c wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb); return 0; -@@ -5124,6 +5125,7 @@ fail: +@@ -5470,6 +5471,7 @@ fail: os_free(fname); interface->global_ctrl_sock = s; @@ -311,11 +294,11 @@ Index: hostapd-2021-12-13-b26f5c0f/hostapd/ctrl_iface.c eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive, interface, NULL); -Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver.h +Index: hostapd-2023-02-21-ath12.3-cs/src/drivers/driver.h =================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/drivers/driver.h -+++ hostapd-2021-12-13-b26f5c0f/src/drivers/driver.h -@@ -3366,6 +3366,25 @@ struct wpa_driver_ops { +--- hostapd-2023-02-21-ath12.3-cs.orig/src/drivers/driver.h ++++ hostapd-2023-02-21-ath12.3-cs/src/drivers/driver.h +@@ -3899,6 +3899,25 @@ struct wpa_driver_ops { const char *ifname); /** @@ -341,7 +324,7 @@ Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver.h * set_sta_vlan - Bind a station into a specific interface (AP only) * @priv: Private driver interface data * @ifname: Interface (main or virtual BSS or VLAN) -@@ -5842,6 +5861,7 @@ union wpa_event_data { +@@ -6525,6 +6544,7 @@ union wpa_event_data { /** * struct ch_switch @@ -349,56 +332,58 @@ Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver.h * @freq: Frequency of new channel in MHz * @ht_enabled: Whether this is an HT channel * @ch_offset: Secondary channel offset -@@ -5850,6 +5870,7 @@ union wpa_event_data { - * @cf2: Center frequency 2 +@@ -6534,6 +6554,7 @@ union wpa_event_data { + * @link_id: Link ID of the MLO link */ struct ch_switch { + int count; int freq; int ht_enabled; int ch_offset; -Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211_event.c +Index: hostapd-2023-02-21-ath12.3-cs/src/drivers/driver_nl80211_event.c =================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/drivers/driver_nl80211_event.c -+++ hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211_event.c -@@ -684,6 +684,7 @@ static void mlme_event_ch_switch(struct - struct nlattr *ifindex, struct nlattr *freq, - struct nlattr *type, struct nlattr *bw, - struct nlattr *cf1, struct nlattr *cf2, +--- hostapd-2023-02-21-ath12.3-cs.orig/src/drivers/driver_nl80211_event.c ++++ hostapd-2023-02-21-ath12.3-cs/src/drivers/driver_nl80211_event.c +@@ -1002,6 +1002,7 @@ static void mlme_event_ch_switch(struct + struct nlattr *cf2, + struct nlattr *ru_punct_bitmap, + struct nlattr *ru_punct_ofdma, + struct nlattr *count, int finished) { struct i802_bss *bss; -@@ -745,6 +746,8 @@ static void mlme_event_ch_switch(struct - data.ch_switch.cf1 = nla_get_u32(cf1); - if (cf2) - data.ch_switch.cf2 = nla_get_u32(cf2); +@@ -1092,7 +1093,9 @@ static void mlme_event_ch_switch(struct + if (ru_punct_ofdma) + data.ch_switch.ru_punct_ofdma = nla_get_flag(ru_punct_ofdma); + } +- + if (count) + data.ch_switch.count = nla_get_u32(count); - ++ if (finished) bss->freq = data.ch_switch.freq; -@@ -3003,6 +3006,7 @@ static void do_process_drv_event(struct - tb[NL80211_ATTR_CHANNEL_WIDTH], - tb[NL80211_ATTR_CENTER_FREQ1], + +@@ -3833,6 +3836,7 @@ static void do_process_drv_event(struct tb[NL80211_ATTR_CENTER_FREQ2], + tb[NL80211_ATTR_RU_PUNCT_BITMAP], + tb[NL80211_ATTR_RU_PUNCT_SUPP_HE], + tb[NL80211_ATTR_CH_SWITCH_COUNT], 0); break; case NL80211_CMD_CH_SWITCH_NOTIFY: -@@ -3013,6 +3017,7 @@ static void do_process_drv_event(struct - tb[NL80211_ATTR_CHANNEL_WIDTH], - tb[NL80211_ATTR_CENTER_FREQ1], +@@ -3846,6 +3850,7 @@ static void do_process_drv_event(struct tb[NL80211_ATTR_CENTER_FREQ2], -+ NULL, + tb[NL80211_ATTR_RU_PUNCT_BITMAP], + tb[NL80211_ATTR_RU_PUNCT_SUPP_HE], ++ NULL, 1); break; case NL80211_CMD_DISCONNECT: -Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/events.c +Index: hostapd-2023-02-21-ath12.3-cs/wpa_supplicant/events.c =================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/events.c -+++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/events.c -@@ -4927,6 +4927,7 @@ void supplicant_event(void *ctx, enum wp +--- hostapd-2023-02-21-ath12.3-cs.orig/wpa_supplicant/events.c ++++ hostapd-2023-02-21-ath12.3-cs/wpa_supplicant/events.c +@@ -5294,6 +5294,7 @@ void supplicant_event(void *ctx, enum wp event_to_string(event), event); #endif /* CONFIG_NO_STDOUT_DEBUG */ @@ -406,11 +391,11 @@ Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/events.c switch (event) { case EVENT_AUTH: #ifdef CONFIG_FST -Index: hostapd-2021-12-13-b26f5c0f/src/ap/ap_drv_ops.h +Index: hostapd-2023-02-21-ath12.3-cs/src/ap/ap_drv_ops.h =================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/ap/ap_drv_ops.h -+++ hostapd-2021-12-13-b26f5c0f/src/ap/ap_drv_ops.h -@@ -367,6 +367,23 @@ static inline int hostapd_drv_stop_ap(st +--- hostapd-2023-02-21-ath12.3-cs.orig/src/ap/ap_drv_ops.h ++++ hostapd-2023-02-21-ath12.3-cs/src/ap/ap_drv_ops.h +@@ -415,6 +415,23 @@ static inline int hostapd_drv_stop_ap(st return hapd->driver->stop_ap(hapd->drv_priv); } @@ -434,11 +419,11 @@ Index: hostapd-2021-12-13-b26f5c0f/src/ap/ap_drv_ops.h static inline int hostapd_drv_channel_info(struct hostapd_data *hapd, struct wpa_channel_info *ci) { -Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211.c +Index: hostapd-2023-02-21-ath12.3-cs/src/drivers/driver_nl80211.c =================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/drivers/driver_nl80211.c -+++ hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211.c -@@ -1249,7 +1249,7 @@ static void wpa_driver_nl80211_event_rtm +--- hostapd-2023-02-21-ath12.3-cs.orig/src/drivers/driver_nl80211.c ++++ hostapd-2023-02-21-ath12.3-cs/src/drivers/driver_nl80211.c +@@ -1370,7 +1370,7 @@ static void wpa_driver_nl80211_event_rtm } wpa_printf(MSG_DEBUG, "nl80211: Interface down (%s/%s)", namebuf, ifname); @@ -447,7 +432,7 @@ Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211.c wpa_printf(MSG_DEBUG, "nl80211: Not the main interface (%s) - do not indicate interface down", drv->first_bss->ifname); -@@ -1285,7 +1285,7 @@ static void wpa_driver_nl80211_event_rtm +@@ -1406,7 +1406,7 @@ static void wpa_driver_nl80211_event_rtm } wpa_printf(MSG_DEBUG, "nl80211: Interface up (%s/%s)", namebuf, ifname); @@ -456,15 +441,15 @@ Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211.c wpa_printf(MSG_DEBUG, "nl80211: Not the main interface (%s) - do not indicate interface up", drv->first_bss->ifname); -@@ -7691,6 +7691,7 @@ static void *i802_init(struct hostapd_da - char master_ifname[IFNAMSIZ]; +@@ -8706,6 +8706,7 @@ static void *i802_init(struct hostapd_da int ifindex, br_ifindex = 0; int br_added = 0; + const u8 *set_addr; + int err; - bss = wpa_driver_nl80211_drv_init(hapd, params->ifname, - params->global_priv, 1, -@@ -7751,21 +7752,17 @@ static void *i802_init(struct hostapd_da + if (params->mld_addr) + set_addr = params->mld_addr; +@@ -8789,21 +8790,17 @@ static void *i802_init(struct hostapd_da add_ifidx(drv, br_ifindex, drv->ifindex); #ifdef CONFIG_LIBNL3_ROUTE @@ -496,7 +481,7 @@ Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211.c } #endif /* CONFIG_LIBNL3_ROUTE */ -@@ -8125,6 +8122,50 @@ static int wpa_driver_nl80211_if_remove( +@@ -9218,6 +9215,50 @@ static int wpa_driver_nl80211_if_remove( return 0; } @@ -547,7 +532,7 @@ Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211.c static int cookie_handler(struct nl_msg *msg, void *arg) { -@@ -9479,6 +9520,37 @@ static int driver_nl80211_if_remove(void +@@ -10784,6 +10825,37 @@ static int driver_nl80211_if_remove(void } @@ -585,7 +570,7 @@ Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211.c static int driver_nl80211_send_mlme(void *priv, const u8 *data, size_t data_len, int noack, unsigned int freq, -@@ -12183,6 +12255,8 @@ const struct wpa_driver_ops wpa_driver_n +@@ -13925,6 +13997,8 @@ const struct wpa_driver_ops wpa_driver_n .set_acl = wpa_driver_nl80211_set_acl, .if_add = wpa_driver_nl80211_if_add, .if_remove = driver_nl80211_if_remove, diff --git a/feeds/ipq95xx/hostapd/patches/610-hostapd_cli_ujail_permission.patch b/feeds/ipq95xx/hostapd/patches/610-hostapd_cli_ujail_permission.patch new file mode 100644 index 000000000..a03fcc9f9 --- /dev/null +++ b/feeds/ipq95xx/hostapd/patches/610-hostapd_cli_ujail_permission.patch @@ -0,0 +1,33 @@ +--- a/src/common/wpa_ctrl.c ++++ b/src/common/wpa_ctrl.c +@@ -135,7 +135,7 @@ try_again: + return NULL; + } + tries++; +-#ifdef ANDROID ++ + /* Set client socket file permissions so that bind() creates the client + * socket with these permissions and there is no need to try to change + * them with chmod() after bind() which would have potential issues with +@@ -147,7 +147,7 @@ try_again: + * operations to allow the response to go through. Those are using the + * no-deference-symlinks version to avoid races. */ + fchmod(ctrl->s, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); +-#endif /* ANDROID */ ++ + if (bind(ctrl->s, (struct sockaddr *) &ctrl->local, + sizeof(ctrl->local)) < 0) { + if (errno == EADDRINUSE && tries < 2) { +@@ -165,7 +165,11 @@ try_again: + return NULL; + } + +-#ifdef ANDROID ++#ifndef ANDROID ++ /* Set group even if we do not have privileges to change owner */ ++ lchown(ctrl->local.sun_path, -1, 101); ++ lchown(ctrl->local.sun_path, 101, 101); ++#else + /* Set group even if we do not have privileges to change owner */ + lchown(ctrl->local.sun_path, -1, AID_WIFI); + lchown(ctrl->local.sun_path, AID_SYSTEM, AID_WIFI); diff --git a/feeds/ipq95xx/hostapd/patches/701-reload_config_inline.patch b/feeds/ipq95xx/hostapd/patches/701-reload_config_inline.patch index 2f68e73e0..3c62bf670 100644 --- a/feeds/ipq95xx/hostapd/patches/701-reload_config_inline.patch +++ b/feeds/ipq95xx/hostapd/patches/701-reload_config_inline.patch @@ -1,6 +1,6 @@ --- a/hostapd/config_file.c +++ b/hostapd/config_file.c -@@ -4699,7 +4699,12 @@ struct hostapd_config * hostapd_config_r +@@ -4816,7 +4816,12 @@ struct hostapd_config * hostapd_config_r int errors = 0; size_t i; @@ -16,7 +16,7 @@ "for reading.", fname); --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c -@@ -318,8 +318,13 @@ struct wpa_config * wpa_config_read(cons +@@ -326,8 +326,13 @@ struct wpa_config * wpa_config_read(cons while (cred_tail && cred_tail->next) cred_tail = cred_tail->next; diff --git a/feeds/ipq95xx/hostapd/patches/710-vlan_no_bridge.patch b/feeds/ipq95xx/hostapd/patches/710-vlan_no_bridge.patch index 0459bd478..63d1b8a3b 100644 --- a/feeds/ipq95xx/hostapd/patches/710-vlan_no_bridge.patch +++ b/feeds/ipq95xx/hostapd/patches/710-vlan_no_bridge.patch @@ -1,6 +1,6 @@ --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h -@@ -115,6 +115,7 @@ struct hostapd_ssid { +@@ -121,6 +121,7 @@ struct hostapd_ssid { #define DYNAMIC_VLAN_OPTIONAL 1 #define DYNAMIC_VLAN_REQUIRED 2 int dynamic_vlan; @@ -30,7 +30,7 @@ --- a/hostapd/config_file.c +++ b/hostapd/config_file.c -@@ -3342,6 +3342,8 @@ static int hostapd_config_fill(struct ho +@@ -3351,6 +3351,8 @@ static int hostapd_config_fill(struct ho #ifndef CONFIG_NO_VLAN } else if (os_strcmp(buf, "dynamic_vlan") == 0) { bss->ssid.dynamic_vlan = atoi(pos); diff --git a/feeds/ipq95xx/hostapd/patches/711-wds_bridge_force.patch b/feeds/ipq95xx/hostapd/patches/711-wds_bridge_force.patch index f8bb39186..b7cca1b01 100644 --- a/feeds/ipq95xx/hostapd/patches/711-wds_bridge_force.patch +++ b/feeds/ipq95xx/hostapd/patches/711-wds_bridge_force.patch @@ -1,6 +1,8 @@ ---- a/hostapd/config_file.c -+++ b/hostapd/config_file.c -@@ -2341,6 +2341,8 @@ static int hostapd_config_fill(struct ho +Index: hostapd-2023-02-21-a9012070/hostapd/config_file.c +=================================================================== +--- hostapd-2023-02-21-a9012070.orig/hostapd/config_file.c ++++ hostapd-2023-02-21-a9012070/hostapd/config_file.c +@@ -2316,6 +2316,8 @@ static int hostapd_config_fill(struct ho sizeof(conf->bss[0]->iface)); } else if (os_strcmp(buf, "bridge") == 0) { os_strlcpy(bss->bridge, pos, sizeof(bss->bridge)); @@ -9,9 +11,11 @@ } else if (os_strcmp(buf, "vlan_bridge") == 0) { os_strlcpy(bss->vlan_bridge, pos, sizeof(bss->vlan_bridge)); } else if (os_strcmp(buf, "wds_bridge") == 0) { ---- a/src/ap/ap_drv_ops.c -+++ b/src/ap/ap_drv_ops.c -@@ -340,8 +340,6 @@ int hostapd_set_wds_sta(struct hostapd_d +Index: hostapd-2023-02-21-a9012070/src/ap/ap_drv_ops.c +=================================================================== +--- hostapd-2023-02-21-a9012070.orig/src/ap/ap_drv_ops.c ++++ hostapd-2023-02-21-a9012070/src/ap/ap_drv_ops.c +@@ -348,8 +348,6 @@ int hostapd_set_wds_sta(struct hostapd_d return -1; if (hapd->conf->wds_bridge[0]) bridge = hapd->conf->wds_bridge; diff --git a/feeds/ipq95xx/hostapd/patches/720-iface_max_num_sta.patch b/feeds/ipq95xx/hostapd/patches/720-iface_max_num_sta.patch index cecc6d3f4..64f87e8ea 100644 --- a/feeds/ipq95xx/hostapd/patches/720-iface_max_num_sta.patch +++ b/feeds/ipq95xx/hostapd/patches/720-iface_max_num_sta.patch @@ -1,6 +1,8 @@ ---- a/hostapd/config_file.c -+++ b/hostapd/config_file.c -@@ -2853,6 +2853,14 @@ static int hostapd_config_fill(struct ho +Index: hostapd-2023-02-21-ath12.3-cs/hostapd/config_file.c +=================================================================== +--- hostapd-2023-02-21-ath12.3-cs.orig/hostapd/config_file.c ++++ hostapd-2023-02-21-ath12.3-cs/hostapd/config_file.c +@@ -2778,6 +2778,14 @@ static int hostapd_config_fill(struct ho line, bss->max_num_sta, MAX_STA_COUNT); return 1; } @@ -15,22 +17,26 @@ } else if (os_strcmp(buf, "wpa") == 0) { bss->wpa = atoi(pos); } else if (os_strcmp(buf, "extended_key_id") == 0) { ---- a/src/ap/hostapd.h -+++ b/src/ap/hostapd.h -@@ -672,6 +672,7 @@ void hostapd_cleanup_cs_params(struct ho - void hostapd_periodic_iface(struct hostapd_iface *iface); +Index: hostapd-2023-02-21-ath12.3-cs/src/ap/hostapd.h +=================================================================== +--- hostapd-2023-02-21-ath12.3-cs.orig/src/ap/hostapd.h ++++ hostapd-2023-02-21-ath12.3-cs/src/ap/hostapd.h +@@ -790,6 +790,7 @@ void hostapd_periodic_iface(struct hosta int hostapd_owe_trans_get_info(struct hostapd_data *hapd); void hostapd_ocv_check_csa_sa_query(void *eloop_ctx, void *timeout_ctx); + void free_beacon_data(struct beacon_data *beacon); +int hostapd_check_max_sta(struct hostapd_data *hapd); - /* utils.c */ - int hostapd_register_probereq_cb(struct hostapd_data *hapd, ---- a/src/ap/hostapd.c -+++ b/src/ap/hostapd.c -@@ -209,6 +209,30 @@ static int hostapd_iface_conf_changed(st + void hostapd_switch_color(struct hostapd_data *hapd, u64 bitmap); + void hostapd_cleanup_cca_params(struct hostapd_data *hapd); +Index: hostapd-2023-02-21-ath12.3-cs/src/ap/hostapd.c +=================================================================== +--- hostapd-2023-02-21-ath12.3-cs.orig/src/ap/hostapd.c ++++ hostapd-2023-02-21-ath12.3-cs/src/ap/hostapd.c +@@ -277,6 +277,29 @@ static int hostapd_iface_conf_changed(st + return 0; } - +static inline int hostapd_iface_num_sta(struct hostapd_iface *iface) +{ + int num_sta = 0; @@ -54,13 +60,14 @@ + + return 0; +} -+ + int hostapd_reload_config(struct hostapd_iface *iface) { - struct hapd_interfaces *interfaces = iface->interfaces; ---- a/src/ap/beacon.c -+++ b/src/ap/beacon.c -@@ -1039,7 +1039,7 @@ void handle_probe_req(struct hostapd_dat +Index: hostapd-2023-02-21-ath12.3-cs/src/ap/beacon.c +=================================================================== +--- hostapd-2023-02-21-ath12.3-cs.orig/src/ap/beacon.c ++++ hostapd-2023-02-21-ath12.3-cs/src/ap/beacon.c +@@ -1642,7 +1642,7 @@ void handle_probe_req(struct hostapd_dat if (hapd->conf->no_probe_resp_if_max_sta && is_multicast_ether_addr(mgmt->da) && is_multicast_ether_addr(mgmt->bssid) && @@ -69,9 +76,11 @@ !ap_get_sta(hapd, mgmt->sa)) { wpa_printf(MSG_MSGDUMP, "%s: Ignore Probe Request from " MACSTR " since no room for additional STA", ---- a/src/ap/ap_config.h -+++ b/src/ap/ap_config.h -@@ -959,6 +959,8 @@ struct hostapd_config { +Index: hostapd-2023-02-21-ath12.3-cs/src/ap/ap_config.h +=================================================================== +--- hostapd-2023-02-21-ath12.3-cs.orig/src/ap/ap_config.h ++++ hostapd-2023-02-21-ath12.3-cs/src/ap/ap_config.h +@@ -1044,6 +1044,8 @@ struct hostapd_config { unsigned int track_sta_max_num; unsigned int track_sta_max_age; diff --git a/feeds/ipq95xx/hostapd/patches/730-ft_iface.patch b/feeds/ipq95xx/hostapd/patches/730-ft_iface.patch index 6bf85bfa5..0795ed15a 100644 --- a/feeds/ipq95xx/hostapd/patches/730-ft_iface.patch +++ b/feeds/ipq95xx/hostapd/patches/730-ft_iface.patch @@ -1,6 +1,6 @@ --- a/hostapd/config_file.c +++ b/hostapd/config_file.c -@@ -3011,6 +3011,8 @@ static int hostapd_config_fill(struct ho +@@ -3007,6 +3007,8 @@ static int hostapd_config_fill(struct ho wpa_printf(MSG_INFO, "Line %d: Obsolete peerkey parameter ignored", line); #ifdef CONFIG_IEEE80211R_AP @@ -11,17 +11,17 @@ hexstr2bin(pos, bss->mobility_domain, --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h -@@ -275,6 +275,7 @@ struct airtime_sta_weight { +@@ -283,6 +283,7 @@ struct airtime_sta_weight { struct hostapd_bss_config { char iface[IFNAMSIZ + 1]; char bridge[IFNAMSIZ + 1]; + char ft_iface[IFNAMSIZ + 1]; char vlan_bridge[IFNAMSIZ + 1]; char wds_bridge[IFNAMSIZ + 1]; - + int bridge_hairpin; /* hairpin_mode on bridge members */ --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c -@@ -1565,8 +1565,12 @@ int hostapd_setup_wpa(struct hostapd_dat +@@ -1727,8 +1727,12 @@ int hostapd_setup_wpa(struct hostapd_dat wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt)) { const char *ft_iface; diff --git a/feeds/ipq95xx/hostapd/patches/740-snoop_iface.patch b/feeds/ipq95xx/hostapd/patches/740-snoop_iface.patch index 667c73ffd..270891c0d 100644 --- a/feeds/ipq95xx/hostapd/patches/740-snoop_iface.patch +++ b/feeds/ipq95xx/hostapd/patches/740-snoop_iface.patch @@ -1,6 +1,8 @@ ---- a/src/ap/ap_config.h -+++ b/src/ap/ap_config.h -@@ -276,6 +276,7 @@ struct hostapd_bss_config { +Index: hostapd-2023-02-21-a9012070/src/ap/ap_config.h +=================================================================== +--- hostapd-2023-02-21-a9012070.orig/src/ap/ap_config.h ++++ hostapd-2023-02-21-a9012070/src/ap/ap_config.h +@@ -284,6 +284,7 @@ struct hostapd_bss_config { char iface[IFNAMSIZ + 1]; char bridge[IFNAMSIZ + 1]; char ft_iface[IFNAMSIZ + 1]; @@ -8,11 +10,13 @@ char vlan_bridge[IFNAMSIZ + 1]; char wds_bridge[IFNAMSIZ + 1]; ---- a/src/ap/x_snoop.c -+++ b/src/ap/x_snoop.c -@@ -31,28 +31,31 @@ int x_snoop_init(struct hostapd_data *ha - return -1; - } +Index: hostapd-2023-02-21-a9012070/src/ap/x_snoop.c +=================================================================== +--- hostapd-2023-02-21-a9012070.orig/src/ap/x_snoop.c ++++ hostapd-2023-02-21-a9012070/src/ap/x_snoop.c +@@ -33,28 +33,31 @@ int x_snoop_init(struct hostapd_data *ha + + hapd->x_snoop_initialized = true; - if (hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_HAIRPIN_MODE, + if (!conf->snoop_iface[0] && @@ -46,7 +50,7 @@ wpa_printf(MSG_DEBUG, "x_snoop: Failed to enable multicast snooping on the bridge"); return -1; -@@ -71,8 +74,12 @@ x_snoop_get_l2_packet(struct hostapd_dat +@@ -73,8 +76,12 @@ x_snoop_get_l2_packet(struct hostapd_dat { struct hostapd_bss_config *conf = hapd->conf; struct l2_packet_data *l2; @@ -60,32 +64,38 @@ if (l2 == NULL) { wpa_printf(MSG_DEBUG, "x_snoop: Failed to initialize L2 packet processing %s", -@@ -125,7 +132,10 @@ void x_snoop_mcast_to_ucast_convert_send +@@ -127,9 +134,12 @@ void x_snoop_mcast_to_ucast_convert_send void x_snoop_deinit(struct hostapd_data *hapd) { -- hostapd_drv_br_set_net_param(hapd, DRV_BR_NET_PARAM_GARP_ACCEPT, 0); + struct hostapd_bss_config *conf = hapd->conf; + + if (!hapd->x_snoop_initialized) + return; +- hostapd_drv_br_set_net_param(hapd, DRV_BR_NET_PARAM_GARP_ACCEPT, 0); + hostapd_drv_br_set_net_param(hapd, DRV_BR_NET_PARAM_GARP_ACCEPT, + conf->snoop_iface[0] ? conf->snoop_iface : NULL, 0); hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_PROXYARP, 0); hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_HAIRPIN_MODE, 0); - } ---- a/hostapd/config_file.c -+++ b/hostapd/config_file.c -@@ -2343,6 +2343,8 @@ static int hostapd_config_fill(struct ho - os_strlcpy(bss->bridge, pos, sizeof(bss->bridge)); - if (!bss->wds_bridge[0]) + hapd->x_snoop_initialized = false; +Index: hostapd-2023-02-21-a9012070/hostapd/config_file.c +=================================================================== +--- hostapd-2023-02-21-a9012070.orig/hostapd/config_file.c ++++ hostapd-2023-02-21-a9012070/hostapd/config_file.c +@@ -2320,6 +2320,8 @@ static int hostapd_config_fill(struct ho os_strlcpy(bss->wds_bridge, pos, sizeof(bss->wds_bridge)); -+ } else if (os_strcmp(buf, "snoop_iface") == 0) { -+ os_strlcpy(bss->snoop_iface, pos, sizeof(bss->snoop_iface)); } else if (os_strcmp(buf, "vlan_bridge") == 0) { os_strlcpy(bss->vlan_bridge, pos, sizeof(bss->vlan_bridge)); ++ } else if (os_strcmp(buf, "snoop_iface") == 0) { ++ os_strlcpy(bss->snoop_iface, pos, sizeof(bss->snoop_iface)); } else if (os_strcmp(buf, "wds_bridge") == 0) { ---- a/src/ap/ap_drv_ops.h -+++ b/src/ap/ap_drv_ops.h -@@ -340,12 +340,12 @@ static inline int hostapd_drv_br_port_se + os_strlcpy(bss->wds_bridge, pos, sizeof(bss->wds_bridge)); + } else if (os_strcmp(buf, "driver") == 0) { +Index: hostapd-2023-02-21-a9012070/src/ap/ap_drv_ops.h +=================================================================== +--- hostapd-2023-02-21-a9012070.orig/src/ap/ap_drv_ops.h ++++ hostapd-2023-02-21-a9012070/src/ap/ap_drv_ops.h +@@ -359,12 +359,12 @@ static inline int hostapd_drv_br_port_se static inline int hostapd_drv_br_set_net_param(struct hostapd_data *hapd, enum drv_br_net_param param, @@ -100,9 +110,11 @@ } static inline int hostapd_drv_vendor_cmd(struct hostapd_data *hapd, ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -3756,7 +3756,7 @@ struct wpa_driver_ops { +Index: hostapd-2023-02-21-a9012070/src/drivers/driver.h +=================================================================== +--- hostapd-2023-02-21-a9012070.orig/src/drivers/driver.h ++++ hostapd-2023-02-21-a9012070/src/drivers/driver.h +@@ -4117,7 +4117,7 @@ struct wpa_driver_ops { * Returns: 0 on success, negative (<0) on failure */ int (*br_set_net_param)(void *priv, enum drv_br_net_param param, @@ -111,9 +123,11 @@ /** * get_wowlan - Get wake-on-wireless status ---- a/src/drivers/driver_nl80211.c -+++ b/src/drivers/driver_nl80211.c -@@ -10825,7 +10825,7 @@ static const char * drv_br_net_param_str +Index: hostapd-2023-02-21-a9012070/src/drivers/driver_nl80211.c +=================================================================== +--- hostapd-2023-02-21-a9012070.orig/src/drivers/driver_nl80211.c ++++ hostapd-2023-02-21-a9012070/src/drivers/driver_nl80211.c +@@ -11732,7 +11732,7 @@ static const char * drv_br_net_param_str static int wpa_driver_br_set_net_param(void *priv, enum drv_br_net_param param, @@ -122,7 +136,7 @@ { struct i802_bss *bss = priv; char path[128]; -@@ -10851,8 +10851,11 @@ static int wpa_driver_br_set_net_param(v +@@ -11758,8 +11758,11 @@ static int wpa_driver_br_set_net_param(v return -EINVAL; } diff --git a/feeds/ipq95xx/hostapd/patches/750-qos_map_set_without_interworking.patch b/feeds/ipq95xx/hostapd/patches/750-qos_map_set_without_interworking.patch new file mode 100644 index 000000000..97c32df70 --- /dev/null +++ b/feeds/ipq95xx/hostapd/patches/750-qos_map_set_without_interworking.patch @@ -0,0 +1,97 @@ +--- a/hostapd/config_file.c ++++ b/hostapd/config_file.c +@@ -1604,6 +1604,8 @@ static int parse_anqp_elem(struct hostap + return 0; + } + ++#endif /* CONFIG_INTERWORKING */ ++ + + static int parse_qos_map_set(struct hostapd_bss_config *bss, + char *buf, int line) +@@ -1645,8 +1647,6 @@ static int parse_qos_map_set(struct host + return 0; + } + +-#endif /* CONFIG_INTERWORKING */ +- + + #ifdef CONFIG_HS20 + static int hs20_parse_conn_capab(struct hostapd_bss_config *bss, char *buf, +@@ -4062,10 +4062,10 @@ static int hostapd_config_fill(struct ho + bss->gas_frag_limit = val; + } else if (os_strcmp(buf, "gas_comeback_delay") == 0) { + bss->gas_comeback_delay = atoi(pos); ++#endif /* CONFIG_INTERWORKING */ + } else if (os_strcmp(buf, "qos_map_set") == 0) { + if (parse_qos_map_set(bss, pos, line) < 0) + return 1; +-#endif /* CONFIG_INTERWORKING */ + #ifdef CONFIG_RADIUS_TEST + } else if (os_strcmp(buf, "dump_msk_file") == 0) { + os_free(bss->dump_msk_file); +--- a/src/ap/hostapd.c ++++ b/src/ap/hostapd.c +@@ -1486,6 +1486,7 @@ int hostapd_setup_bss(struct hostapd_dat + wpa_printf(MSG_ERROR, "GAS server initialization failed"); + return -1; + } ++#endif /* CONFIG_INTERWORKING */ + + if (conf->qos_map_set_len && + hostapd_drv_set_qos_map(hapd, conf->qos_map_set, +@@ -1493,7 +1494,6 @@ int hostapd_setup_bss(struct hostapd_dat + wpa_printf(MSG_ERROR, "Failed to initialize QoS Map"); + return -1; + } +-#endif /* CONFIG_INTERWORKING */ + + if (conf->bss_load_update_period && bss_load_update_init(hapd)) { + wpa_printf(MSG_ERROR, "BSS Load initialization failed"); +--- a/wpa_supplicant/events.c ++++ b/wpa_supplicant/events.c +@@ -2683,8 +2683,6 @@ void wnm_bss_keep_alive_deinit(struct wp + } + + +-#ifdef CONFIG_INTERWORKING +- + static int wpas_qos_map_set(struct wpa_supplicant *wpa_s, const u8 *qos_map, + size_t len) + { +@@ -2717,8 +2715,6 @@ static void interworking_process_assoc_r + } + } + +-#endif /* CONFIG_INTERWORKING */ +- + + static void wpa_supplicant_set_4addr_mode(struct wpa_supplicant *wpa_s) + { +@@ -3098,10 +3094,8 @@ static int wpa_supplicant_event_associnf + wnm_process_assoc_resp(wpa_s, data->assoc_info.resp_ies, + data->assoc_info.resp_ies_len); + #endif /* CONFIG_WNM */ +-#ifdef CONFIG_INTERWORKING + interworking_process_assoc_resp(wpa_s, data->assoc_info.resp_ies, + data->assoc_info.resp_ies_len); +-#endif /* CONFIG_INTERWORKING */ + if (wpa_s->hw_capab == CAPAB_VHT && + get_ie(data->assoc_info.resp_ies, + data->assoc_info.resp_ies_len, WLAN_EID_VHT_CAP)) +--- a/src/ap/ieee802_11_shared.c ++++ b/src/ap/ieee802_11_shared.c +@@ -1116,13 +1116,11 @@ u8 * hostapd_eid_rsnxe(struct hostapd_da + u16 check_ext_capab(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *ext_capab_ie, size_t ext_capab_ie_len) + { +-#ifdef CONFIG_INTERWORKING + /* check for QoS Map support */ + if (ext_capab_ie_len >= 5) { + if (ext_capab_ie[4] & 0x01) + sta->qos_map_enabled = 1; + } +-#endif /* CONFIG_INTERWORKING */ + + if (ext_capab_ie_len > 0) { + sta->ecsa_supported = !!(ext_capab_ie[0] & BIT(2)); diff --git a/feeds/ipq95xx/hostapd/patches/750-wispr.patch b/feeds/ipq95xx/hostapd/patches/750-wispr.patch deleted file mode 100644 index f40cc2b90..000000000 --- a/feeds/ipq95xx/hostapd/patches/750-wispr.patch +++ /dev/null @@ -1,105 +0,0 @@ ---- a/src/ap/ieee802_1x.c -+++ b/src/ap/ieee802_1x.c -@@ -1904,6 +1904,25 @@ static int ieee802_1x_update_vlan(struct - } - #endif /* CONFIG_NO_VLAN */ - -+static int ieee802_1x_update_wispr(struct hostapd_data *hapd, -+ struct sta_info *sta, -+ struct radius_msg *msg) -+{ -+ memset(sta->bandwidth, 0, sizeof(sta->bandwidth)); -+ -+ if (radius_msg_get_wispr(msg, &sta->bandwidth)) -+ return 0; -+ -+ if (!sta->bandwidth[0] && !sta->bandwidth[1]) -+ return 0; -+ -+ hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, -+ HOSTAPD_LEVEL_INFO, -+ "received wispr bandwidth from RADIUS server %d/%d", -+ sta->bandwidth[0], sta->bandwidth[1]); -+ -+ return 0; -+} - - /** - * ieee802_1x_receive_auth - Process RADIUS frames from Authentication Server -@@ -2029,6 +2048,7 @@ ieee802_1x_receive_auth(struct radius_ms - ieee802_1x_check_hs20(hapd, sta, msg, - session_timeout_set ? - (int) session_timeout : -1); -+ ieee802_1x_update_wispr(hapd, sta, msg); - break; - case RADIUS_CODE_ACCESS_REJECT: - sm->eap_if->aaaFail = true; ---- a/src/ap/sta_info.h -+++ b/src/ap/sta_info.h -@@ -116,6 +116,7 @@ struct sta_info { - u8 supported_rates[WLAN_SUPP_RATES_MAX]; - int supported_rates_len; - u8 qosinfo; /* Valid when WLAN_STA_WMM is set */ -+ u32 bandwidth[2]; - - #ifdef CONFIG_MESH - enum mesh_plink_state plink_state; ---- a/src/radius/radius.c -+++ b/src/radius/radius.c -@@ -1182,6 +1182,35 @@ radius_msg_get_cisco_keys(struct radius_ - return keys; - } - -+#define RADIUS_VENDOR_ID_WISPR 14122 -+#define RADIUS_WISPR_AV_BW_UP 7 -+#define RADIUS_WISPR_AV_BW_DOWN 8 -+ -+int -+radius_msg_get_wispr(struct radius_msg *msg, u32 *bandwidth) -+{ -+ int i; -+ -+ if (msg == NULL || bandwidth == NULL) -+ return 1; -+ -+ for (i = 0; i < 2; i++) { -+ size_t keylen; -+ u8 *key; -+ -+ key = radius_msg_get_vendor_attr(msg, RADIUS_VENDOR_ID_WISPR, -+ RADIUS_WISPR_AV_BW_UP + i, &keylen); -+ if (!key) -+ continue; -+ -+ if (keylen == 4) -+ bandwidth[i] = ntohl(*((u32 *)key)); -+ os_free(key); -+ } -+ -+ return 0; -+} -+ - - int radius_msg_add_mppe_keys(struct radius_msg *msg, - const u8 *req_authenticator, ---- a/src/radius/radius.h -+++ b/src/radius/radius.h -@@ -205,6 +205,10 @@ enum { - RADIUS_VENDOR_ATTR_WFA_HS20_T_C_URL = 10, - }; - -+#define RADIUS_VENDOR_ID_WISPR 14122 -+#define RADIUS_WISPR_AV_BW_UP 7 -+#define RADIUS_WISPR_AV_BW_DOWN 8 -+ - #ifdef _MSC_VER - #pragma pack(pop) - #endif /* _MSC_VER */ -@@ -277,6 +281,7 @@ radius_msg_get_ms_keys(struct radius_msg - struct radius_ms_mppe_keys * - radius_msg_get_cisco_keys(struct radius_msg *msg, struct radius_msg *sent_msg, - const u8 *secret, size_t secret_len); -+int radius_msg_get_wispr(struct radius_msg *msg, u32 *bandwidth); - int radius_msg_add_mppe_keys(struct radius_msg *msg, - const u8 *req_authenticator, - const u8 *secret, size_t secret_len, diff --git a/feeds/ipq95xx/hostapd/patches/751-qos_map_ignore_when_unsupported.patch b/feeds/ipq95xx/hostapd/patches/751-qos_map_ignore_when_unsupported.patch new file mode 100644 index 000000000..f5ebab70d --- /dev/null +++ b/feeds/ipq95xx/hostapd/patches/751-qos_map_ignore_when_unsupported.patch @@ -0,0 +1,12 @@ +--- a/src/ap/ap_drv_ops.c ++++ b/src/ap/ap_drv_ops.c +@@ -927,7 +927,8 @@ int hostapd_start_dfs_cac(struct hostapd + int hostapd_drv_set_qos_map(struct hostapd_data *hapd, + const u8 *qos_map_set, u8 qos_map_set_len) + { +- if (!hapd->driver || !hapd->driver->set_qos_map || !hapd->drv_priv) ++ if (!hapd->driver || !hapd->driver->set_qos_map || !hapd->drv_priv || ++ !(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)) + return 0; + return hapd->driver->set_qos_map(hapd->drv_priv, qos_map_set, + qos_map_set_len); diff --git a/feeds/ipq95xx/hostapd/patches/760-acs_exclude_dfs.patch b/feeds/ipq95xx/hostapd/patches/760-acs_exclude_dfs.patch deleted file mode 100644 index 27b3a6161..000000000 --- a/feeds/ipq95xx/hostapd/patches/760-acs_exclude_dfs.patch +++ /dev/null @@ -1,13 +0,0 @@ ---- a/src/ap/acs.c -+++ b/src/ap/acs.c -@@ -668,6 +668,10 @@ acs_find_ideal_chan_mode(struct hostapd_ - continue; - } - -+ if (iface->conf->acs_exclude_dfs && -+ (chan->flag & HOSTAPD_CHAN_RADAR)) -+ continue; -+ - /* HT40 on 5 GHz has a limited set of primary channels as per - * 11n Annex J */ - if (mode->mode == HOSTAPD_MODE_IEEE80211A && diff --git a/feeds/ipq95xx/hostapd/patches/760-dynamic_own_ip.patch b/feeds/ipq95xx/hostapd/patches/760-dynamic_own_ip.patch index ad6fa287f..2c705a68c 100644 --- a/feeds/ipq95xx/hostapd/patches/760-dynamic_own_ip.patch +++ b/feeds/ipq95xx/hostapd/patches/760-dynamic_own_ip.patch @@ -1,6 +1,6 @@ --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h -@@ -301,6 +301,7 @@ struct hostapd_bss_config { +@@ -310,6 +310,7 @@ struct hostapd_bss_config { unsigned int eap_sim_db_timeout; int eap_server_erp; /* Whether ERP is enabled on internal EAP server */ struct hostapd_ip_addr own_ip_addr; @@ -10,7 +10,7 @@ int acct_interim_interval; --- a/src/radius/radius_client.c +++ b/src/radius/radius_client.c -@@ -162,6 +162,8 @@ struct radius_client_data { +@@ -163,6 +163,8 @@ struct radius_client_data { */ void *ctx; @@ -19,7 +19,7 @@ /** * conf - RADIUS client configuration (list of RADIUS servers to use) */ -@@ -719,6 +721,30 @@ static void radius_client_list_add(struc +@@ -720,6 +722,30 @@ static void radius_client_list_add(struc /** @@ -50,7 +50,7 @@ * radius_client_send - Send a RADIUS request * @radius: RADIUS client context from radius_client_init() * @msg: RADIUS message to be sent -@@ -1219,6 +1245,10 @@ radius_change_server(struct radius_clien +@@ -1238,6 +1264,10 @@ radius_change_server(struct radius_clien wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u", inet_ntoa(claddr.sin_addr), ntohs(claddr.sin_port)); @@ -61,7 +61,7 @@ } break; #ifdef CONFIG_IPV6 -@@ -1230,6 +1260,10 @@ radius_change_server(struct radius_clien +@@ -1249,6 +1279,10 @@ radius_change_server(struct radius_clien inet_ntop(AF_INET6, &claddr6.sin6_addr, abuf, sizeof(abuf)), ntohs(claddr6.sin6_port)); @@ -74,7 +74,7 @@ } --- a/src/radius/radius_client.h +++ b/src/radius/radius_client.h -@@ -244,6 +244,8 @@ int radius_client_register(struct radius +@@ -249,6 +249,8 @@ int radius_client_register(struct radius void radius_client_set_interim_error_cb(struct radius_client_data *radius, void (*cb)(const u8 *addr, void *ctx), void *ctx); @@ -85,7 +85,7 @@ RadiusType msg_type, const u8 *addr); --- a/src/ap/ieee802_1x.c +++ b/src/ap/ieee802_1x.c -@@ -535,6 +535,10 @@ int add_common_radius_attr(struct hostap +@@ -598,6 +598,10 @@ int add_common_radius_attr(struct hostap struct hostapd_radius_attr *attr; int len; @@ -98,7 +98,7 @@ hapd->conf->own_ip_addr.af == AF_INET && --- a/hostapd/config_file.c +++ b/hostapd/config_file.c -@@ -2696,6 +2696,8 @@ static int hostapd_config_fill(struct ho +@@ -2688,6 +2688,8 @@ static int hostapd_config_fill(struct ho } else if (os_strcmp(buf, "iapp_interface") == 0) { wpa_printf(MSG_INFO, "DEPRECATED: iapp_interface not used"); #endif /* CONFIG_IAPP */ diff --git a/feeds/ipq95xx/hostapd/patches/900-coa_multi.patch b/feeds/ipq95xx/hostapd/patches/761-shared_das_port.patch similarity index 86% rename from feeds/ipq95xx/hostapd/patches/900-coa_multi.patch rename to feeds/ipq95xx/hostapd/patches/761-shared_das_port.patch index 24927ea73..ed326778c 100644 --- a/feeds/ipq95xx/hostapd/patches/900-coa_multi.patch +++ b/feeds/ipq95xx/hostapd/patches/761-shared_das_port.patch @@ -1,5 +1,7 @@ ---- a/src/radius/radius_das.h -+++ b/src/radius/radius_das.h +Index: hostapd-2023-02-21-a9012070/src/radius/radius_das.h +=================================================================== +--- hostapd-2023-02-21-a9012070.orig/src/radius/radius_das.h ++++ hostapd-2023-02-21-a9012070/src/radius/radius_das.h @@ -44,6 +44,7 @@ struct radius_das_attrs { struct radius_das_conf { int port; @@ -8,9 +10,11 @@ size_t shared_secret_len; const struct hostapd_ip_addr *client_addr; unsigned int time_window; ---- a/src/ap/hostapd.c -+++ b/src/ap/hostapd.c -@@ -1325,6 +1325,7 @@ int hostapd_setup_bss(struct hostapd_dat +Index: hostapd-2023-02-21-a9012070/src/ap/hostapd.c +=================================================================== +--- hostapd-2023-02-21-a9012070.orig/src/ap/hostapd.c ++++ hostapd-2023-02-21-a9012070/src/ap/hostapd.c +@@ -1394,6 +1394,7 @@ int hostapd_setup_bss(struct hostapd_dat struct radius_das_conf das_conf; os_memset(&das_conf, 0, sizeof(das_conf)); das_conf.port = conf->radius_das_port; @@ -18,8 +22,10 @@ das_conf.shared_secret = conf->radius_das_shared_secret; das_conf.shared_secret_len = conf->radius_das_shared_secret_len; ---- a/src/radius/radius_das.c -+++ b/src/radius/radius_das.c +Index: hostapd-2023-02-21-a9012070/src/radius/radius_das.c +=================================================================== +--- hostapd-2023-02-21-a9012070.orig/src/radius/radius_das.c ++++ hostapd-2023-02-21-a9012070/src/radius/radius_das.c @@ -12,13 +12,26 @@ #include "utils/common.h" #include "utils/eloop.h" @@ -48,7 +54,7 @@ size_t shared_secret_len; struct hostapd_ip_addr client_addr; unsigned int time_window; -@@ -379,56 +392,17 @@ fail: +@@ -378,56 +391,17 @@ fail: } @@ -111,7 +117,7 @@ if (radius_msg_verify_das_req(msg, das->shared_secret, das->shared_secret_len, -@@ -495,9 +469,8 @@ static void radius_das_receive(int sock, +@@ -494,9 +468,8 @@ static void radius_das_receive(int sock, radius_msg_dump(reply); rbuf = radius_msg_get_buf(reply); @@ -123,11 +129,7 @@ if (res < 0) { wpa_printf(MSG_ERROR, "DAS: sendto(to %s:%d): %s", abuf, from_port, strerror(errno)); -@@ -505,10 +478,76 @@ static void radius_das_receive(int sock, - } - - fail: -- radius_msg_free(msg); +@@ -508,6 +481,72 @@ fail: radius_msg_free(reply); } @@ -193,7 +195,6 @@ + fromlen, abuf, from_port); + } + -+ radius_msg_free(msg); + if (!found) + wpa_printf(MSG_DEBUG, "DAS: Drop message from unknown client"); +} @@ -201,7 +202,7 @@ static int radius_das_open_socket(int port) { -@@ -534,6 +573,49 @@ static int radius_das_open_socket(int po +@@ -533,6 +572,49 @@ static int radius_das_open_socket(int po } @@ -251,7 +252,7 @@ struct radius_das_data * radius_das_init(struct radius_das_conf *conf) { -@@ -554,6 +636,8 @@ radius_das_init(struct radius_das_conf * +@@ -553,6 +635,8 @@ radius_das_init(struct radius_das_conf * das->ctx = conf->ctx; das->disconnect = conf->disconnect; das->coa = conf->coa; @@ -260,7 +261,7 @@ os_memcpy(&das->client_addr, conf->client_addr, sizeof(das->client_addr)); -@@ -566,19 +650,15 @@ radius_das_init(struct radius_das_conf * +@@ -565,19 +649,15 @@ radius_das_init(struct radius_das_conf * } das->shared_secret_len = conf->shared_secret_len; @@ -283,7 +284,7 @@ return das; } -@@ -589,11 +669,14 @@ void radius_das_deinit(struct radius_das +@@ -588,11 +668,14 @@ void radius_das_deinit(struct radius_das if (das == NULL) return; diff --git a/feeds/ipq95xx/hostapd/patches/770-radius_server.patch b/feeds/ipq95xx/hostapd/patches/770-radius_server.patch new file mode 100644 index 000000000..8837a2625 --- /dev/null +++ b/feeds/ipq95xx/hostapd/patches/770-radius_server.patch @@ -0,0 +1,154 @@ +--- a/hostapd/Makefile ++++ b/hostapd/Makefile +@@ -63,6 +63,10 @@ endif + OBJS += main.o + OBJS += config_file.o + ++ifdef CONFIG_RADIUS_SERVER ++OBJS += radius.o ++endif ++ + OBJS += ../src/ap/hostapd.o + OBJS += ../src/ap/wpa_auth_glue.o + OBJS += ../src/ap/drv_callbacks.o +--- a/hostapd/main.c ++++ b/hostapd/main.c +@@ -40,6 +40,7 @@ struct hapd_global { + + static struct hapd_global global; + ++extern int radius_main(int argc, char **argv); + + #ifndef CONFIG_NO_HOSTAPD_LOGGER + static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module, +@@ -771,6 +772,11 @@ int main(int argc, char *argv[]) + if (os_program_init()) + return -1; + ++#ifdef RADIUS_SERVER ++ if (strstr(argv[0], "radius")) ++ return radius_main(argc, argv); ++#endif ++ + os_memset(&interfaces, 0, sizeof(interfaces)); + interfaces.reload_config = hostapd_reload_config; + interfaces.config_read_cb = hostapd_config_read; +--- a/src/radius/radius_server.c ++++ b/src/radius/radius_server.c +@@ -63,6 +63,12 @@ struct radius_server_counters { + u32 unknown_acct_types; + }; + ++struct radius_accept_attr { ++ u8 type; ++ u16 len; ++ void *data; ++}; ++ + /** + * struct radius_session - Internal RADIUS server data for a session + */ +@@ -90,7 +96,7 @@ struct radius_session { + unsigned int macacl:1; + unsigned int t_c_filtering:1; + +- struct hostapd_radius_attr *accept_attr; ++ struct radius_accept_attr *accept_attr; + + u32 t_c_timestamp; /* Last read T&C timestamp from user DB */ + }; +@@ -394,6 +400,7 @@ static void radius_server_session_free(s + radius_msg_free(sess->last_reply); + os_free(sess->username); + os_free(sess->nas_ip); ++ os_free(sess->accept_attr); + os_free(sess); + data->num_sess--; + } +@@ -554,6 +561,36 @@ radius_server_erp_find_key(struct radius + } + #endif /* CONFIG_ERP */ + ++static struct radius_accept_attr * ++radius_server_copy_attr(const struct hostapd_radius_attr *data) ++{ ++ const struct hostapd_radius_attr *attr; ++ struct radius_accept_attr *attr_new; ++ size_t data_size = 0; ++ void *data_buf; ++ int n_attr = 1; ++ ++ for (attr = data; attr; attr = attr->next) { ++ n_attr++; ++ data_size += wpabuf_len(attr->val); ++ } ++ ++ attr_new = os_zalloc(n_attr * sizeof(*attr) + data_size); ++ if (!attr_new) ++ return NULL; ++ ++ data_buf = &attr_new[n_attr]; ++ for (n_attr = 0, attr = data; attr; attr = attr->next) { ++ struct radius_accept_attr *cur = &attr_new[n_attr++]; ++ ++ cur->type = attr->type; ++ cur->len = wpabuf_len(attr->val); ++ cur->data = memcpy(data_buf, wpabuf_head(attr->val), cur->len); ++ data_buf += cur->len; ++ } ++ ++ return attr_new; ++} + + static struct radius_session * + radius_server_get_new_session(struct radius_server_data *data, +@@ -607,7 +644,7 @@ radius_server_get_new_session(struct rad + eap_user_free(tmp); + return NULL; + } +- sess->accept_attr = tmp->accept_attr; ++ sess->accept_attr = radius_server_copy_attr(tmp->accept_attr); + sess->macacl = tmp->macacl; + eap_user_free(tmp); + +@@ -1118,11 +1155,10 @@ radius_server_encapsulate_eap(struct rad + } + + if (code == RADIUS_CODE_ACCESS_ACCEPT) { +- struct hostapd_radius_attr *attr; +- for (attr = sess->accept_attr; attr; attr = attr->next) { +- if (!radius_msg_add_attr(msg, attr->type, +- wpabuf_head(attr->val), +- wpabuf_len(attr->val))) { ++ struct radius_accept_attr *attr; ++ for (attr = sess->accept_attr; attr->data; attr++) { ++ if (!radius_msg_add_attr(msg, attr->type, attr->data, ++ attr->len)) { + wpa_printf(MSG_ERROR, "Could not add RADIUS attribute"); + radius_msg_free(msg); + return NULL; +@@ -1211,11 +1247,10 @@ radius_server_macacl(struct radius_serve + } + + if (code == RADIUS_CODE_ACCESS_ACCEPT) { +- struct hostapd_radius_attr *attr; +- for (attr = sess->accept_attr; attr; attr = attr->next) { +- if (!radius_msg_add_attr(msg, attr->type, +- wpabuf_head(attr->val), +- wpabuf_len(attr->val))) { ++ struct radius_accept_attr *attr; ++ for (attr = sess->accept_attr; attr->data; attr++) { ++ if (!radius_msg_add_attr(msg, attr->type, attr->data, ++ attr->len)) { + wpa_printf(MSG_ERROR, "Could not add RADIUS attribute"); + radius_msg_free(msg); + return NULL; +@@ -2512,7 +2547,7 @@ static int radius_server_get_eap_user(vo + ret = data->get_eap_user(data->conf_ctx, identity, identity_len, + phase2, user); + if (ret == 0 && user) { +- sess->accept_attr = user->accept_attr; ++ sess->accept_attr = radius_server_copy_attr(user->accept_attr); + sess->remediation = user->remediation; + sess->macacl = user->macacl; + sess->t_c_timestamp = user->t_c_timestamp; diff --git a/feeds/ipq95xx/hostapd/patches/770-wds-hack.patch b/feeds/ipq95xx/hostapd/patches/770-wds-hack.patch deleted file mode 100644 index 5fa58585f..000000000 --- a/feeds/ipq95xx/hostapd/patches/770-wds-hack.patch +++ /dev/null @@ -1,34 +0,0 @@ ---- a/src/ap/hostapd.c -+++ b/src/ap/hostapd.c -@@ -11,6 +11,8 @@ - #include - #endif /* CONFIG_SQLITE */ - -+#include -+ - #include "utils/common.h" - #include "utils/eloop.h" - #include "utils/crc32.h" -@@ -1198,6 +1200,22 @@ int hostapd_setup_bss(struct hostapd_dat - os_memcpy(hapd->own_addr, if_addr, ETH_ALEN); - } - -+ if (conf->wds_sta) { -+ char path[128]; -+ FILE *fp; -+ -+ sprintf(path, "/sys/kernel/debug/ieee80211/%s/netdev:%s/disable_offload", hostapd_drv_get_radio_name(hapd), conf->iface); -+ -+ fp = fopen(path, "w"); -+ if (fp) { -+ syslog(0, "WDS: disable encap - %s\n", path); -+ fprintf(fp, "1"); -+ fclose(fp); -+ } else { -+ syslog(0, "WDS: failed to disable encap - %s\n", path); -+ } -+ } -+ - if (conf->wmm_enabled < 0) - conf->wmm_enabled = hapd->iconf->ieee80211n; - diff --git a/feeds/ipq95xx/hostapd/patches/780-maxassoc.patch b/feeds/ipq95xx/hostapd/patches/780-maxassoc.patch deleted file mode 100644 index 07fc54e14..000000000 --- a/feeds/ipq95xx/hostapd/patches/780-maxassoc.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/src/ap/sta_info.c -+++ b/src/ap/sta_info.c -@@ -717,7 +717,7 @@ struct sta_info * ap_sta_add(struct host - return sta; - - wpa_printf(MSG_DEBUG, " New STA"); -- if (hapd->num_sta >= hapd->conf->max_num_sta) { -+ if (hostapd_check_max_sta(hapd)) { - /* FIX: might try to remove some old STAs first? */ - wpa_printf(MSG_DEBUG, "no more room for new STAs (%d/%d)", - hapd->num_sta, hapd->conf->max_num_sta); diff --git a/feeds/ipq95xx/hostapd/patches/800-fix-ap-sta-channel-setup-failed.patch b/feeds/ipq95xx/hostapd/patches/800-fix-ap-sta-channel-setup-failed.patch deleted file mode 100644 index 67e3d078c..000000000 --- a/feeds/ipq95xx/hostapd/patches/800-fix-ap-sta-channel-setup-failed.patch +++ /dev/null @@ -1,27 +0,0 @@ ---- a/src/common/hw_features_common.c -+++ b/src/common/hw_features_common.c -@@ -609,9 +609,21 @@ int hostapd_set_freq_params(struct hosta - center_segment0 == channel - 6) - data->center_freq1 = 5000 + center_segment0 * 5; - else { -- wpa_printf(MSG_ERROR, -- "Wrong coupling between HT and VHT/HE channel setting"); -- return -1; -+ if (channel <= 48) -+ center_segment0 = 42; -+ else if (channel <= 64) -+ center_segment0 = 58; -+ else if (channel <= 112) -+ center_segment0 = 106; -+ else if (channel <= 128) -+ center_segment0 = 122; -+ else if (channel <= 144) -+ center_segment0 = 138; -+ else if (channel <= 161) -+ center_segment0 = 155; -+ else if (channel <= 177) -+ center_segment0 = 171; -+ data->center_freq1 = 5000 + center_segment0 * 5; - } - } - break; diff --git a/feeds/ipq95xx/hostapd/patches/900-coa.patch b/feeds/ipq95xx/hostapd/patches/900-coa.patch deleted file mode 100644 index 3e1213a4d..000000000 --- a/feeds/ipq95xx/hostapd/patches/900-coa.patch +++ /dev/null @@ -1,22 +0,0 @@ ---- a/src/radius/radius_das.c -+++ b/src/radius/radius_das.c -@@ -48,6 +48,8 @@ static struct radius_msg * radius_das_di - RADIUS_ATTR_EVENT_TIMESTAMP, - RADIUS_ATTR_MESSAGE_AUTHENTICATOR, - RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, -+ RADIUS_ATTR_VENDOR_SPECIFIC, -+ RADIUS_ATTR_CALLED_STATION_ID, - #ifdef CONFIG_IPV6 - RADIUS_ATTR_NAS_IPV6_ADDRESS, - #endif /* CONFIG_IPV6 */ -@@ -205,9 +207,8 @@ static struct radius_msg * radius_das_co - RADIUS_ATTR_EVENT_TIMESTAMP, - RADIUS_ATTR_MESSAGE_AUTHENTICATOR, - RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, --#ifdef CONFIG_HS20 - RADIUS_ATTR_VENDOR_SPECIFIC, --#endif /* CONFIG_HS20 */ -+ RADIUS_ATTR_CALLED_STATION_ID, - #ifdef CONFIG_IPV6 - RADIUS_ATTR_NAS_IPV6_ADDRESS, - #endif /* CONFIG_IPV6 */ diff --git a/feeds/ipq95xx/hostapd/patches/901-cfg-section.patch b/feeds/ipq95xx/hostapd/patches/901-cfg-section.patch index 9122a4236..152e18a0c 100644 --- a/feeds/ipq95xx/hostapd/patches/901-cfg-section.patch +++ b/feeds/ipq95xx/hostapd/patches/901-cfg-section.patch @@ -1,6 +1,8 @@ ---- a/hostapd/config_file.c -+++ b/hostapd/config_file.c -@@ -2366,6 +2366,8 @@ static int hostapd_config_fill(struct ho +Index: hostapd-2023-02-21-ath12.3-cs/hostapd/config_file.c +=================================================================== +--- hostapd-2023-02-21-ath12.3-cs.orig/hostapd/config_file.c ++++ hostapd-2023-02-21-ath12.3-cs/hostapd/config_file.c +@@ -2271,6 +2271,8 @@ static int hostapd_config_fill(struct ho return 1; } conf->driver = driver; @@ -9,23 +11,27 @@ } else if (os_strcmp(buf, "driver_params") == 0) { os_free(conf->driver_params); conf->driver_params = os_strdup(pos); ---- a/src/ap/ap_config.h -+++ b/src/ap/ap_config.h -@@ -279,6 +279,7 @@ struct hostapd_bss_config { +Index: hostapd-2023-02-21-ath12.3-cs/src/ap/ap_config.h +=================================================================== +--- hostapd-2023-02-21-ath12.3-cs.orig/src/ap/ap_config.h ++++ hostapd-2023-02-21-ath12.3-cs/src/ap/ap_config.h +@@ -287,6 +287,7 @@ struct hostapd_bss_config { char snoop_iface[IFNAMSIZ + 1]; char vlan_bridge[IFNAMSIZ + 1]; char wds_bridge[IFNAMSIZ + 1]; + char *uci_section; - enum hostapd_logger_level logger_syslog_level, logger_stdout_level; - ---- a/src/ap/ap_config.c -+++ b/src/ap/ap_config.c -@@ -785,6 +785,7 @@ void hostapd_config_free_bss(struct host - os_free(conf->radius_req_attr_sqlite); - os_free(conf->rsn_preauth_interfaces); - os_free(conf->ctrl_interface); + #ifdef CONFIG_IEEE80211BE + unsigned int mlo_link_id; +Index: hostapd-2023-02-21-ath12.3-cs/src/ap/ap_config.c +=================================================================== +--- hostapd-2023-02-21-ath12.3-cs.orig/src/ap/ap_config.c ++++ hostapd-2023-02-21-ath12.3-cs/src/ap/ap_config.c +@@ -825,6 +825,7 @@ void hostapd_config_free_bss(struct host + os_free(conf->radius_server_clients); + os_free(conf->radius); + os_free(conf->radius_das_shared_secret); + os_free(conf->uci_section); - os_free(conf->ca_cert); - os_free(conf->server_cert); - os_free(conf->server_cert2); + hostapd_config_free_vlan(conf); + os_free(conf->time_zone); + diff --git a/feeds/ipq95xx/hostapd/patches/920-sta_driver_data.patch b/feeds/ipq95xx/hostapd/patches/920-sta_driver_data.patch deleted file mode 100644 index 4d11051d1..000000000 --- a/feeds/ipq95xx/hostapd/patches/920-sta_driver_data.patch +++ /dev/null @@ -1,53 +0,0 @@ ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -2175,6 +2175,10 @@ struct hostap_sta_driver_data { - u8 tx_mcs; - u8 rx_vht_nss; - u8 tx_vht_nss; -+ u8 rx_hemcs; -+ u8 tx_hemcs; -+ u8 rx_he_nss; -+ u8 tx_he_nss; - }; - - struct hostapd_sta_add_params { ---- a/src/drivers/driver_nl80211.c -+++ b/src/drivers/driver_nl80211.c -@@ -7010,6 +7010,8 @@ static int get_sta_handler(struct nl_msg - [NL80211_RATE_INFO_VHT_MCS] = { .type = NLA_U8 }, - [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG }, - [NL80211_RATE_INFO_VHT_NSS] = { .type = NLA_U8 }, -+ [NL80211_RATE_INFO_HE_NSS] = { .type = NLA_U8 }, -+ [NL80211_RATE_INFO_HE_MCS] = { .type = NLA_U8 }, - }; - - nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), -@@ -7102,6 +7104,10 @@ static int get_sta_handler(struct nl_msg - nla_get_u8(rate[NL80211_RATE_INFO_VHT_NSS]); - data->flags |= STA_DRV_DATA_TX_VHT_NSS; - } -+ if (rate[NL80211_RATE_INFO_HE_MCS]) -+ data->tx_hemcs = nla_get_u8(rate[NL80211_RATE_INFO_HE_MCS]); -+ if (rate[NL80211_RATE_INFO_HE_NSS]) -+ data->tx_he_nss = nla_get_u8(rate[NL80211_RATE_INFO_HE_NSS]); - } - - if (stats[NL80211_STA_INFO_RX_BITRATE] && -@@ -7132,11 +7138,16 @@ static int get_sta_handler(struct nl_msg - nla_get_u8(rate[NL80211_RATE_INFO_VHT_NSS]); - data->flags |= STA_DRV_DATA_RX_VHT_NSS; - } -+ if (rate[NL80211_RATE_INFO_HE_MCS]) -+ data->rx_hemcs = nla_get_u8(rate[NL80211_RATE_INFO_HE_MCS]); -+ if (rate[NL80211_RATE_INFO_HE_NSS]) -+ data->rx_he_nss = nla_get_u8(rate[NL80211_RATE_INFO_HE_NSS]); - } - - if (stats[NL80211_STA_INFO_TID_STATS]) - get_sta_tid_stats(data, stats[NL80211_STA_INFO_TID_STATS]); - -+ - return NL_SKIP; - } - - diff --git a/feeds/ipq95xx/hostapd/patches/990-ctrl-make-WNM_AP-functions-dependant-on-CONFIG_AP.patch b/feeds/ipq95xx/hostapd/patches/990-ctrl-make-WNM_AP-functions-dependant-on-CONFIG_AP.patch new file mode 100644 index 000000000..5809a3b7e --- /dev/null +++ b/feeds/ipq95xx/hostapd/patches/990-ctrl-make-WNM_AP-functions-dependant-on-CONFIG_AP.patch @@ -0,0 +1,33 @@ +From f0e9f5aab52b3eab85d28338cc996972ced4c39c Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Tue, 17 May 2022 23:07:59 +0200 +Subject: [PATCH] ctrl: make WNM_AP functions dependant on CONFIG_AP + +This fixes linking errors found when compiling wpa_supplicant with +CONFIG_WNM_AP enabled but CONFIG_AP disabled. + +Signed-off-by: David Bauer +--- + wpa_supplicant/ctrl_iface.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/wpa_supplicant/ctrl_iface.c ++++ b/wpa_supplicant/ctrl_iface.c +@@ -12763,7 +12763,7 @@ char * wpa_supplicant_ctrl_iface_process + if (wpas_ctrl_iface_coloc_intf_report(wpa_s, buf + 18)) + reply_len = -1; + #endif /* CONFIG_WNM */ +-#ifdef CONFIG_WNM_AP ++#if defined(CONFIG_AP) && defined(CONFIG_WNM_AP) + } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) { + if (ap_ctrl_iface_disassoc_imminent(wpa_s, buf + 18)) + reply_len = -1; +@@ -12773,7 +12773,7 @@ char * wpa_supplicant_ctrl_iface_process + } else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) { + if (ap_ctrl_iface_bss_tm_req(wpa_s, buf + 11)) + reply_len = -1; +-#endif /* CONFIG_WNM_AP */ ++#endif /* CONFIG_AP && CONFIG_WNM_AP */ + } else if (os_strcmp(buf, "FLUSH") == 0) { + wpa_supplicant_ctrl_iface_flush(wpa_s); + } else if (os_strncmp(buf, "RADIO_WORK ", 11) == 0) { diff --git a/feeds/ipq95xx/hostapd/patches/992-nl80211-add-extra-ies-only-if-allowed-by-driver.patch b/feeds/ipq95xx/hostapd/patches/992-nl80211-add-extra-ies-only-if-allowed-by-driver.patch new file mode 100644 index 000000000..c7b595da5 --- /dev/null +++ b/feeds/ipq95xx/hostapd/patches/992-nl80211-add-extra-ies-only-if-allowed-by-driver.patch @@ -0,0 +1,62 @@ +From: David Bauer +To: hostap@lists.infradead.org +Cc: =?utf-8?q?=C3=89tienne_Morice?= +Subject: [PATCH] nl80211: add extra-ies only if allowed by driver +Date: Sun, 30 Jan 2022 20:22:00 +0100 +Message-Id: <20220130192200.10883-1-mail@david-bauer.net> +List-Id: + +Upgrading wpa_supplicant from 2.9 to 2.10 breaks broadcom-wl +based adapters. The reason for it is hostapd tries to install additional +IEs for scanning while the driver does not support this. + +The kernel indicates the maximum number of bytes for additional scan IEs +using the NL80211_ATTR_MAX_SCAN_IE_LEN attribute. Save this value and +only add additional scan IEs in case the driver can accommodate these +additional IEs. + +Reported-by: Étienne Morice +Tested-by: Étienne Morice +Signed-off-by: David Bauer +--- + src/drivers/driver.h | 3 +++ + src/drivers/driver_nl80211_capa.c | 4 ++++ + src/drivers/driver_nl80211_scan.c | 2 +- + 3 files changed, 8 insertions(+), 1 deletion(-) + +--- a/src/drivers/driver.h ++++ b/src/drivers/driver.h +@@ -2283,6 +2283,9 @@ struct wpa_driver_capa { + /** Maximum number of iterations in a single scan plan */ + u32 max_sched_scan_plan_iterations; + ++ /** Maximum number of extra IE bytes for scans */ ++ u16 max_scan_ie_len; ++ + /** Whether sched_scan (offloaded scanning) is supported */ + int sched_scan_supported; + +--- a/src/drivers/driver_nl80211_capa.c ++++ b/src/drivers/driver_nl80211_capa.c +@@ -949,6 +949,10 @@ static int wiphy_info_handler(struct nl_ + nla_get_u32(tb[NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS]); + } + ++ if (tb[NL80211_ATTR_MAX_SCAN_IE_LEN]) ++ capa->max_scan_ie_len = ++ nla_get_u16(tb[NL80211_ATTR_MAX_SCAN_IE_LEN]); ++ + if (tb[NL80211_ATTR_MAX_MATCH_SETS]) + capa->max_match_sets = + nla_get_u8(tb[NL80211_ATTR_MAX_MATCH_SETS]); +--- a/src/drivers/driver_nl80211_scan.c ++++ b/src/drivers/driver_nl80211_scan.c +@@ -222,7 +222,7 @@ nl80211_scan_common(struct i802_bss *bss + wpa_printf(MSG_DEBUG, "nl80211: Passive scan requested"); + } + +- if (params->extra_ies) { ++ if (params->extra_ies && drv->capa.max_scan_ie_len >= params->extra_ies_len) { + wpa_hexdump(MSG_MSGDUMP, "nl80211: Scan extra IEs", + params->extra_ies, params->extra_ies_len); + if (nla_put(msg, NL80211_ATTR_IE, params->extra_ies_len, diff --git a/feeds/ipq95xx/hostapd/patches/999-das-proxy-state.patch b/feeds/ipq95xx/hostapd/patches/999-das-proxy-state.patch deleted file mode 100644 index 64b7aa4c0..000000000 --- a/feeds/ipq95xx/hostapd/patches/999-das-proxy-state.patch +++ /dev/null @@ -1,95 +0,0 @@ -Index: hostapd-2021-02-20-59e9794c/src/radius/radius_das.c -=================================================================== ---- hostapd-2021-02-20-59e9794c.orig/src/radius/radius_das.c -+++ hostapd-2021-02-20-59e9794c/src/radius/radius_das.c -@@ -63,6 +63,7 @@ static struct radius_msg * radius_das_di - RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, - RADIUS_ATTR_VENDOR_SPECIFIC, - RADIUS_ATTR_CALLED_STATION_ID, -+ RADIUS_ATTR_PROXY_STATE, - #ifdef CONFIG_IPV6 - RADIUS_ATTR_NAS_IPV6_ADDRESS, - #endif /* CONFIG_IPV6 */ -@@ -159,6 +160,12 @@ static struct radius_msg * radius_das_di - attrs.cui_len = len; - } - -+ if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_PROXY_STATE, -+ &buf, &len, NULL) == 0) { -+ attrs.proxy = buf; -+ attrs.proxy_len = len; -+ } -+ - res = das->disconnect(das->ctx, &attrs); - switch (res) { - case RADIUS_DAS_NAS_MISMATCH: -@@ -167,10 +174,11 @@ static struct radius_msg * radius_das_di - error = 403; - break; - case RADIUS_DAS_SESSION_NOT_FOUND: -- wpa_printf(MSG_INFO, "DAS: Session not found for request from " -- "%s:%d", abuf, from_port); -- error = 503; -- break; -+ return NULL; -+// wpa_printf(MSG_INFO, "DAS: Session not found for request from " -+// "%s:%d", abuf, from_port); -+// error = 503; -+// break; - case RADIUS_DAS_MULTI_SESSION_MATCH: - wpa_printf(MSG_INFO, - "DAS: Multiple sessions match for request from %s:%d", -@@ -192,6 +200,9 @@ fail: - if (reply == NULL) - return NULL; - -+ if (attrs.proxy) -+ radius_msg_add_attr(reply, RADIUS_ATTR_PROXY_STATE, attrs.proxy, attrs.proxy_len); -+ - if (error) { - if (!radius_msg_add_attr_int32(reply, RADIUS_ATTR_ERROR_CAUSE, - error)) { -@@ -222,6 +233,7 @@ static struct radius_msg * radius_das_co - RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, - RADIUS_ATTR_VENDOR_SPECIFIC, - RADIUS_ATTR_CALLED_STATION_ID, -+ RADIUS_ATTR_PROXY_STATE, - #ifdef CONFIG_IPV6 - RADIUS_ATTR_NAS_IPV6_ADDRESS, - #endif /* CONFIG_IPV6 */ -@@ -347,6 +359,12 @@ static struct radius_msg * radius_das_co - } - #endif /* CONFIG_HS20 */ - -+ if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_PROXY_STATE, -+ &buf, &len, NULL) == 0) { -+ attrs.proxy = buf; -+ attrs.proxy_len = len; -+ } -+ - res = das->coa(das->ctx, &attrs); - switch (res) { - case RADIUS_DAS_NAS_MISMATCH: -@@ -382,6 +400,9 @@ fail: - if (!reply) - return NULL; - -+ if (attrs.proxy) -+ radius_msg_add_attr(reply, RADIUS_ATTR_PROXY_STATE, attrs.proxy, attrs.proxy_len); -+ - if (error && - !radius_msg_add_attr_int32(reply, RADIUS_ATTR_ERROR_CAUSE, error)) { - radius_msg_free(reply); -Index: hostapd-2021-02-20-59e9794c/src/radius/radius_das.h -=================================================================== ---- hostapd-2021-02-20-59e9794c.orig/src/radius/radius_das.h -+++ hostapd-2021-02-20-59e9794c/src/radius/radius_das.h -@@ -36,6 +36,8 @@ struct radius_das_attrs { - size_t acct_multi_session_id_len; - const u8 *cui; - size_t cui_len; -+ const u8 *proxy; -+ size_t proxy_len; - - /* Authorization changes */ - const u8 *hs20_t_c_filtering; diff --git a/feeds/ipq95xx/hostapd/patches/999-ft-anonce.patch b/feeds/ipq95xx/hostapd/patches/999-ft-anonce.patch deleted file mode 100644 index 40956fa65..000000000 --- a/feeds/ipq95xx/hostapd/patches/999-ft-anonce.patch +++ /dev/null @@ -1,48 +0,0 @@ -Index: hostapd-2021-02-20-59e9794c/src/ap/wpa_auth_ft.c -=================================================================== ---- hostapd-2021-02-20-59e9794c.orig/src/ap/wpa_auth_ft.c -+++ hostapd-2021-02-20-59e9794c/src/ap/wpa_auth_ft.c -@@ -3067,6 +3067,7 @@ static int wpa_ft_process_auth_req(struc - size_t identity_len = 0, radius_cui_len = 0; - int use_sha384; - size_t pmk_r1_len, kdk_len; -+ struct os_reltime now; - - *resp_ies = NULL; - *resp_ies_len = 0; -@@ -3185,10 +3186,19 @@ pmk_r1_derived: - os_memcpy(sm->pmk_r1, pmk_r1, pmk_r1_len); - sm->pmk_r1_len = pmk_r1_len; - -- if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) { -- wpa_printf(MSG_DEBUG, "FT: Failed to get random data for " -- "ANonce"); -- return WLAN_STATUS_UNSPECIFIED_FAILURE; -+ if (os_get_reltime(&now) < 0 || -+ os_reltime_expired(&now, &sm->ANonce_time, 1)) { -+ if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) { -+ wpa_printf(MSG_DEBUG, "FT: Failed to get random data for " -+ "ANonce"); -+ return WLAN_STATUS_UNSPECIFIED_FAILURE; -+ } -+ sm->ANonce_time.sec = now.sec; -+ sm->ANonce_time.usec = now.usec; -+ wpa_printf(MSG_INFO, "FT: ANonce was randomized"); -+ } else { -+ wpa_printf(MSG_INFO, "FT: ANonce has not expired"); -+ - } - - wpa_hexdump(MSG_DEBUG, "FT: Received SNonce", -Index: hostapd-2021-02-20-59e9794c/src/ap/wpa_auth_i.h -=================================================================== ---- hostapd-2021-02-20-59e9794c.orig/src/ap/wpa_auth_i.h -+++ hostapd-2021-02-20-59e9794c/src/ap/wpa_auth_i.h -@@ -54,6 +54,7 @@ struct wpa_state_machine { - bool MICVerified; - bool GUpdateStationKeys; - u8 ANonce[WPA_NONCE_LEN]; -+ struct os_reltime ANonce_time; - u8 SNonce[WPA_NONCE_LEN]; - u8 alt_SNonce[WPA_NONCE_LEN]; - u8 alt_replay_counter[WPA_REPLAY_COUNTER_LEN]; diff --git a/feeds/ipq95xx/hostapd/patches/999-probe-request.patch b/feeds/ipq95xx/hostapd/patches/999-probe-request.patch index a239c8432..1a867d22f 100644 --- a/feeds/ipq95xx/hostapd/patches/999-probe-request.patch +++ b/feeds/ipq95xx/hostapd/patches/999-probe-request.patch @@ -1,6 +1,8 @@ ---- a/hostapd/config_file.c -+++ b/hostapd/config_file.c -@@ -3337,6 +3337,8 @@ static int hostapd_config_fill(struct ho +Index: hostapd-2023-02-21-ath12.3-cs/hostapd/config_file.c +=================================================================== +--- hostapd-2023-02-21-ath12.3-cs.orig/hostapd/config_file.c ++++ hostapd-2023-02-21-ath12.3-cs/hostapd/config_file.c +@@ -3286,6 +3286,8 @@ static int hostapd_config_fill(struct ho bss->ignore_broadcast_ssid = atoi(pos); } else if (os_strcmp(buf, "no_probe_resp_if_max_sta") == 0) { bss->no_probe_resp_if_max_sta = atoi(pos); @@ -9,9 +11,11 @@ #ifdef CONFIG_WEP } else if (os_strcmp(buf, "wep_default_key") == 0) { bss->ssid.wep.idx = atoi(pos); ---- a/src/ap/ap_config.h -+++ b/src/ap/ap_config.h -@@ -459,6 +459,7 @@ struct hostapd_bss_config { +Index: hostapd-2023-02-21-ath12.3-cs/src/ap/ap_config.h +=================================================================== +--- hostapd-2023-02-21-ath12.3-cs.orig/src/ap/ap_config.h ++++ hostapd-2023-02-21-ath12.3-cs/src/ap/ap_config.h +@@ -473,6 +473,7 @@ struct hostapd_bss_config { int ap_max_inactivity; int ignore_broadcast_ssid; int no_probe_resp_if_max_sta; @@ -19,9 +23,11 @@ int wmm_enabled; int wmm_uapsd; ---- a/src/ap/beacon.c -+++ b/src/ap/beacon.c -@@ -920,7 +920,8 @@ void handle_probe_req(struct hostapd_dat +Index: hostapd-2023-02-21-ath12.3-cs/src/ap/beacon.c +=================================================================== +--- hostapd-2023-02-21-ath12.3-cs.orig/src/ap/beacon.c ++++ hostapd-2023-02-21-ath12.3-cs/src/ap/beacon.c +@@ -1523,7 +1523,8 @@ void handle_probe_req(struct hostapd_dat } #endif /* CONFIG_P2P */ @@ -31,7 +37,7 @@ elems.ssid_list_len == 0 && elems.short_ssid_list_len == 0) { wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for " "broadcast SSID ignored", MAC2STR(mgmt->sa)); -@@ -967,7 +968,8 @@ void handle_probe_req(struct hostapd_dat +@@ -1570,7 +1571,8 @@ void handle_probe_req(struct hostapd_dat return; } diff --git a/feeds/ipq95xx/hostapd/patches/999-ssi_signal.patch b/feeds/ipq95xx/hostapd/patches/999-ssi_signal.patch deleted file mode 100644 index a5309d2db..000000000 --- a/feeds/ipq95xx/hostapd/patches/999-ssi_signal.patch +++ /dev/null @@ -1,75 +0,0 @@ ---- a/src/ap/ieee802_11.c -+++ b/src/ap/ieee802_11.c -@@ -57,6 +57,17 @@ - #include "gas_query_ap.h" - - -+static int -+ewma(int new, int old) -+{ -+ #define ALPHA 10 -+ if (!old) -+ return new; -+ if (new >= 0) -+ return old; -+ return ((ALPHA * new) + ((100 - ALPHA) * old)) / 100; -+} -+ - #ifdef CONFIG_FILS - static struct wpabuf * - prepare_auth_resp_fils(struct hostapd_data *hapd, -@@ -5873,7 +5882,7 @@ static int robust_action_frame(u8 catego - - static int handle_action(struct hostapd_data *hapd, - const struct ieee80211_mgmt *mgmt, size_t len, -- unsigned int freq) -+ unsigned int freq, int ssi_signal) - { - struct sta_info *sta; - u8 *action __maybe_unused; -@@ -5930,6 +5939,7 @@ static int handle_action(struct hostapd_ - - sta->last_seq_ctrl = seq_ctrl; - sta->last_subtype = WLAN_FC_STYPE_ACTION; -+ sta->signal_mgmt = ewma(ssi_signal, sta->signal_mgmt);; - } - - switch (mgmt->u.action.category) { -@@ -6109,6 +6119,8 @@ int ieee802_11_mgmt(struct hostapd_data - unsigned int freq; - int ssi_signal = fi ? fi->ssi_signal : 0; - -+ hapd->signal_mgmt = ewma(ssi_signal, hapd->signal_mgmt);; -+ - if (len < 24) - return 0; - -@@ -6208,7 +6220,7 @@ int ieee802_11_mgmt(struct hostapd_data - break; - case WLAN_FC_STYPE_ACTION: - wpa_printf(MSG_DEBUG, "mgmt::action"); -- ret = handle_action(hapd, mgmt, len, freq); -+ ret = handle_action(hapd, mgmt, len, freq, ssi_signal); - break; - default: - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, ---- a/src/ap/sta_info.h -+++ b/src/ap/sta_info.h -@@ -331,6 +331,7 @@ struct sta_info { - #ifdef CONFIG_PASN - struct pasn_data *pasn; - #endif /* CONFIG_PASN */ -+ int signal_mgmt; - }; - - ---- a/src/ap/hostapd.h -+++ b/src/ap/hostapd.h -@@ -451,6 +451,7 @@ struct hostapd_data { - #ifdef CONFIG_CTRL_IFACE_UDP - unsigned char ctrl_iface_cookie[CTRL_IFACE_COOKIE_LEN]; - #endif /* CONFIG_CTRL_IFACE_UDP */ -+ int signal_mgmt; - }; - - diff --git a/feeds/ipq95xx/hostapd/patches/a00-004-Add-provision-to-test-RADAR-detection-probablity-in-.patch b/feeds/ipq95xx/hostapd/patches/a00-004-Add-provision-to-test-RADAR-detection-probablity-in-.patch deleted file mode 100644 index 5df155ec7..000000000 --- a/feeds/ipq95xx/hostapd/patches/a00-004-Add-provision-to-test-RADAR-detection-probablity-in-.patch +++ /dev/null @@ -1,153 +0,0 @@ ---- a/hostapd/config_file.c -+++ b/hostapd/config_file.c -@@ -2424,6 +2424,8 @@ static int hostapd_config_fill(struct ho - conf->ieee80211d = atoi(pos); - } else if (os_strcmp(buf, "ieee80211h") == 0) { - conf->ieee80211h = atoi(pos); -+ } else if (os_strcmp(buf, "dfs_test_mode") == 0) { -+ conf->dfs_test_mode = atoi(pos); - } else if (os_strcmp(buf, "ieee8021x") == 0) { - bss->ieee802_1x = atoi(pos); - } else if (os_strcmp(buf, "eapol_version") == 0) { ---- a/src/ap/ap_config.h -+++ b/src/ap/ap_config.h -@@ -950,6 +950,7 @@ struct hostapd_config { - int ieee80211d; - - int ieee80211h; /* DFS */ -+ int dfs_test_mode; - - /* - * Local power constraint is an octet encoded as an unsigned integer in ---- a/src/ap/dfs.c -+++ b/src/ap/dfs.c -@@ -17,6 +17,8 @@ - #include "ap_drv_ops.h" - #include "drivers/driver.h" - #include "dfs.h" -+#include "beacon.h" -+#include "eloop.h" - - - static int dfs_get_used_n_chans(struct hostapd_iface *iface, int *seg1) -@@ -1015,6 +1017,73 @@ static int hostapd_dfs_start_channel_swi - return err; - } - -+void hostapd_dfs_test_mode_csa_timeout(void *eloop_data, void *user_data) -+{ -+ struct hostapd_data *hapd = eloop_data; -+ -+ wpa_printf(MSG_INFO, "Stopping CSA in dfs test mode"); -+ hostapd_cleanup_cs_params(hapd); -+ ieee802_11_set_beacon(hapd); -+} -+ -+static int hostapd_dfs_testmode_set_beacon_csa(struct hostapd_iface *iface) -+{ -+ struct hostapd_data *hapd = iface->bss[0]; -+ struct csa_settings csa_settings; -+ int secondary_channel; -+ u8 vht_oper_centr_freq_seg0_idx; -+ u8 vht_oper_centr_freq_seg1_idx; -+ int err = 0; -+ -+ eloop_cancel_timeout(hostapd_dfs_test_mode_csa_timeout, hapd, NULL); -+ secondary_channel = iface->conf->secondary_channel; -+ vht_oper_centr_freq_seg0_idx = -+ iface->conf->vht_oper_centr_freq_seg0_idx; -+ vht_oper_centr_freq_seg1_idx = -+ iface->conf->vht_oper_centr_freq_seg1_idx; -+ -+ /* Setup CSA request */ -+ os_memset(&csa_settings, 0, sizeof(csa_settings)); -+ err = hostapd_set_freq_params(&csa_settings.freq_params, -+ iface->conf->hw_mode, -+ iface->freq, -+ iface->conf->channel, -+ iface->conf->ieee80211n, -+ iface->conf->ieee80211ac, -+ secondary_channel, -+ iface->conf->vht_oper_chwidth, -+ vht_oper_centr_freq_seg0_idx, -+ vht_oper_centr_freq_seg1_idx, -+ iface->current_mode->vht_capab); -+ -+ if (err) { -+ wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params"); -+ goto fail; -+ } -+ -+ if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA)) { -+ wpa_printf(MSG_INFO, "CSA is not supported"); -+ hostapd_disable_iface(iface); -+ return -1; -+ } -+ -+ hapd->cs_freq_params = csa_settings.freq_params; -+ hapd->cs_count = 3; -+ hapd->cs_block_tx = 1; -+ err = ieee802_11_set_beacon(hapd); -+ if (err) -+ goto fail; -+ wpa_printf(MSG_DEBUG, "CSA beacon configured for dfs mode, count %d", -+ hapd->cs_count); -+ hapd->csa_in_progress = 1; -+ eloop_register_timeout(HOSTAPD_DFS_TEST_MODE_CSA_DUR, 0, -+ hostapd_dfs_test_mode_csa_timeout, hapd, NULL); -+ return 0; -+ -+fail: -+ hostapd_disable_iface(iface); -+ return err; -+} - - static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface) - { -@@ -1049,6 +1118,9 @@ static int hostapd_dfs_start_channel_swi - if (iface->dfs_domain == HOSTAPD_DFS_REGION_ETSI) - skip_radar = 0; - -+ if (iface->conf->dfs_test_mode) -+ return hostapd_dfs_testmode_set_beacon_csa(iface); -+ - /* Perform channel switch/CSA */ - channel = dfs_get_valid_channel(iface, &secondary_channel, - &oper_centr_freq_seg0_idx, -@@ -1172,6 +1244,12 @@ int hostapd_dfs_radar_detected(struct ho - if (!res) - return 0; - -+ if (iface->conf->dfs_test_mode) { -+ set_dfs_state(iface, freq, ht_enabled, chan_offset, -+ chan_width, cf1, cf2, -+ HOSTAPD_CHAN_DFS_AVAILABLE); -+ } -+ - /* Skip if reported radar event not overlapped our channels */ - res = dfs_are_channels_overlapped(iface, freq, chan_width, cf1, cf2); - if (!res) ---- a/src/ap/dfs.h -+++ b/src/ap/dfs.h -@@ -9,6 +9,11 @@ - #ifndef DFS_H - #define DFS_H - -+/* CSA beacon duration in seconds for dfs testing mode */ -+#define HOSTAPD_DFS_TEST_MODE_CSA_DUR 1 -+ -+void hostapd_dfs_test_mode_csa_timeout(void *eloop_data, void *user_data); -+ - int hostapd_handle_dfs(struct hostapd_iface *iface); - - int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq, ---- a/src/ap/hostapd.c -+++ b/src/ap/hostapd.c -@@ -2767,6 +2767,7 @@ int hostapd_disable_iface(struct hostapd - hostapd_cleanup_cs_params(hapd_iface->bss[j]); - #endif /* NEED_AP_MLME */ - -+ eloop_cancel_timeout(hostapd_dfs_test_mode_csa_timeout, hapd_iface, NULL); - /* same as hostapd_interface_deinit without deinitializing ctrl-iface */ - for (j = 0; j < hapd_iface->num_bss; j++) { - struct hostapd_data *hapd = hapd_iface->bss[j]; diff --git a/feeds/ipq95xx/hostapd/patches/b00-001-hostapd-fix-an-issue-related-with-wpa_group_state.patch b/feeds/ipq95xx/hostapd/patches/b00-001-hostapd-fix-an-issue-related-with-wpa_group_state.patch deleted file mode 100644 index ad96f8e73..000000000 --- a/feeds/ipq95xx/hostapd/patches/b00-001-hostapd-fix-an-issue-related-with-wpa_group_state.patch +++ /dev/null @@ -1,18 +0,0 @@ ---- a/src/ap/drv_callbacks.c -+++ b/src/ap/drv_callbacks.c -@@ -31,6 +31,7 @@ - #include "tkip_countermeasures.h" - #include "ieee802_1x.h" - #include "wpa_auth.h" -+#include "wpa_auth_glue.h" - #include "wps_hostapd.h" - #include "ap_drv_ops.h" - #include "ap_config.h" -@@ -2030,6 +2031,7 @@ void hostapd_wpa_event(void *ctx, enum w - * Try to re-enable interface if the driver stopped it - * when the interface got disabled. - */ -+ hostapd_reconfig_wpa(hapd); - if (hapd->wpa_auth) - wpa_auth_reconfig_group_keys(hapd->wpa_auth); - else diff --git a/feeds/ipq95xx/hostapd/patches/b00-004-hostap-fix-compilation-issue.patch b/feeds/ipq95xx/hostapd/patches/b00-004-hostap-fix-compilation-issue.patch deleted file mode 100644 index 9b16a456c..000000000 --- a/feeds/ipq95xx/hostapd/patches/b00-004-hostap-fix-compilation-issue.patch +++ /dev/null @@ -1,140 +0,0 @@ ---- a/src/ap/wpa_auth.c -+++ b/src/ap/wpa_auth.c -@@ -1051,7 +1051,7 @@ void wpa_receive(struct wpa_authenticato - mic_len, key_data_length); - wpa_hexdump(MSG_MSGDUMP, - "WPA: EAPOL-Key header (ending before Key MIC)", -- key, sizeof(*key)); -+ (u8 *)key, sizeof(*key)); - wpa_hexdump(MSG_MSGDUMP, "WPA: EAPOL-Key Key MIC", - mic, mic_len); - if (key_data_length > data_len - sizeof(*hdr) - keyhdrlen) { -@@ -3140,7 +3140,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) - idx = bitfield_get_first_zero(wpa_auth->ip_pool); - if (idx >= 0) { - u32 start = WPA_GET_BE32(wpa_auth->conf.ip_addr_start); -- bitfield_set(wpa_auth->ip_pool, idx); -+ bitfield_set_local(wpa_auth->ip_pool, idx); - WPA_PUT_BE32(sm->ip_addr, start + idx); - wpa_printf(MSG_DEBUG, - "P2P: Assigned IP address %u.%u.%u.%u to " ---- a/src/crypto/tls_openssl.c -+++ b/src/crypto/tls_openssl.c -@@ -1099,7 +1099,7 @@ void * tls_init(const struct tls_config - if (conf && conf->openssl_ciphers) - ciphers = conf->openssl_ciphers; - else -- ciphers = TLS_DEFAULT_CIPHERS; -+ ciphers = "DEFAULT:!EXP:!LOW"; - if (SSL_CTX_set_cipher_list(ssl, ciphers) != 1) { - wpa_printf(MSG_ERROR, - "OpenSSL: Failed to set cipher string '%s'", ---- a/src/utils/bitfield.c -+++ b/src/utils/bitfield.c -@@ -37,7 +37,7 @@ void bitfield_free(struct bitfield *bf) - } - - --void bitfield_set(struct bitfield *bf, size_t bit) -+void bitfield_set_local(struct bitfield *bf, size_t bit) - { - if (bit >= bf->max_bits) - return; ---- a/src/utils/bitfield.h -+++ b/src/utils/bitfield.h -@@ -13,7 +13,7 @@ struct bitfield; - - struct bitfield * bitfield_alloc(size_t max_bits); - void bitfield_free(struct bitfield *bf); --void bitfield_set(struct bitfield *bf, size_t bit); -+void bitfield_set_local(struct bitfield *bf, size_t bit); - void bitfield_clear(struct bitfield *bf, size_t bit); - int bitfield_is_set(struct bitfield *bf, size_t bit); - int bitfield_get_first_zero(struct bitfield *bf); ---- a/src/utils/utils_module_tests.c -+++ b/src/utils/utils_module_tests.c -@@ -142,7 +142,7 @@ static int bitfield_tests(void) - errors++; - if (i > 0 && bitfield_is_set(bf, i - 1)) - errors++; -- bitfield_set(bf, i); -+ bitfield_set_local(bf, i); - if (!bitfield_is_set(bf, i)) - errors++; - bitfield_clear(bf, i); -@@ -155,7 +155,7 @@ static int bitfield_tests(void) - errors++; - if (i > 0 && bitfield_is_set(bf, i - 1)) - errors++; -- bitfield_set(bf, i); -+ bitfield_set_local(bf, i); - if (bitfield_is_set(bf, i)) - errors++; - bitfield_clear(bf, i); -@@ -166,7 +166,7 @@ static int bitfield_tests(void) - for (i = 0; i < 123; i++) { - if (bitfield_is_set(bf, i) || bitfield_is_set(bf, i + 1)) - errors++; -- bitfield_set(bf, i); -+ bitfield_set_local(bf, i); - if (!bitfield_is_set(bf, i)) - errors++; - } -@@ -182,7 +182,7 @@ static int bitfield_tests(void) - for (i = 0; i < 123; i++) { - if (bitfield_get_first_zero(bf) != i) - errors++; -- bitfield_set(bf, i); -+ bitfield_set_local(bf, i); - } - if (bitfield_get_first_zero(bf) != -1) - errors++; -@@ -192,7 +192,7 @@ static int bitfield_tests(void) - bitfield_clear(bf, i); - if (bitfield_get_first_zero(bf) != i) - errors++; -- bitfield_set(bf, i); -+ bitfield_set_local(bf, i); - } - if (bitfield_get_first_zero(bf) != -1) - errors++; -@@ -205,7 +205,7 @@ static int bitfield_tests(void) - if (bitfield_get_first_zero(bf) != 0) - errors++; - for (i = 0; i < 8; i++) -- bitfield_set(bf, i); -+ bitfield_set_local(bf, i); - if (bitfield_get_first_zero(bf) != -1) - errors++; - bitfield_free(bf); ---- a/wpa_supplicant/rrm.c -+++ b/wpa_supplicant/rrm.c -@@ -1125,7 +1125,7 @@ static int wpas_rm_handle_beacon_req_sub - } - - for (i = 0; i < slen; i++) -- bitfield_set(data->eids, subelem[i]); -+ bitfield_set_local(data->eids, subelem[i]); - break; - case WLAN_BEACON_REQUEST_SUBELEM_AP_CHANNEL: - /* Skip - it will be processed when freqs are added */ ---- a/src/rsn_supp/tdls.c -+++ b/src/rsn_supp/tdls.c -@@ -1678,7 +1678,7 @@ static int copy_peer_he_capab(const stru - - peer->he_capab_len = kde->he_capab_len; - wpa_hexdump(MSG_DEBUG, "TDLS: Peer HE capabilities", -- peer->he_capabilities, peer->he_capab_len); -+ (u8 *)peer->he_capabilities, peer->he_capab_len); - - return 0; - } -@@ -1704,7 +1704,7 @@ static int copy_peer_he_6ghz_band_capab( - sizeof(struct ieee80211_he_6ghz_band_cap)); - - wpa_hexdump(MSG_DEBUG, "TDLS: Peer 6 GHz band HE capabilities", -- peer->he_6ghz_band_capabilities, -+ (u8 *)peer->he_6ghz_band_capabilities, - sizeof(struct ieee80211_he_6ghz_band_cap)); - - return 0; diff --git a/feeds/ipq95xx/hostapd/patches/b00-014-hostapd-add-ht40-allow-map.patch b/feeds/ipq95xx/hostapd/patches/b00-014-hostapd-add-ht40-allow-map.patch deleted file mode 100644 index a5bf71409..000000000 --- a/feeds/ipq95xx/hostapd/patches/b00-014-hostapd-add-ht40-allow-map.patch +++ /dev/null @@ -1,130 +0,0 @@ ---- a/hostapd/ctrl_iface.c -+++ b/hostapd/ctrl_iface.c -@@ -3112,6 +3112,92 @@ set: - return ret; - } - -+static int hostapd_2ghz_ht40_allow_map(struct hostapd_hw_modes *mode, -+ char *buf, size_t buflen) -+{ -+ int j, ret, len = 0; -+ -+ for (j = 0; j < mode->num_channels; j++) { -+ struct hostapd_channel_data *chan = &mode->channels[j]; -+ if (!(chan->flag & HOSTAPD_CHAN_DISABLED)) { -+ ret = os_snprintf(buf + len, buflen - len, -+ "Channel: %d : %d HT40%c%c\n", -+ chan->chan, chan->freq, -+ (chan->flag & HOSTAPD_CHAN_HT40MINUS) ? -+ '-' : ' ', -+ (chan->flag & HOSTAPD_CHAN_HT40PLUS) ? -+ '+' : ' '); -+ if (os_snprintf_error(buflen - len, ret)) -+ return len; -+ len += ret; -+ } -+ } -+ return len; -+} -+ -+static int hostapd_5ghz_ht40_allow_map(struct hostapd_hw_modes *mode, -+ char *buf, size_t buflen) -+{ -+ int j, k, ok, ret, len = 0, allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 140, -+ 149, 157, 184, 192 }; -+ -+ for (j = 0; j < mode->num_channels; j++) { -+ struct hostapd_channel_data *chan = &mode->channels[j]; -+ -+ if ((chan->flag & HOSTAPD_CHAN_HT40MINUS) || -+ (chan->flag & HOSTAPD_CHAN_HT40PLUS)) { -+ ok = 0; -+ for (k = 0; k < ARRAY_SIZE(allowed); k++) { -+ if (chan->chan < allowed[k]) -+ break; -+ if (chan->chan == allowed[k]) { -+ ok = 1; -+ break; -+ } -+ } -+ -+ if (!ok && chan->chan != (allowed[k - 1] + 4)) -+ ok = -1; -+ -+ if (ok == 1 && (mode->channels[j + 1].flag & -+ HOSTAPD_CHAN_DISABLED)) -+ ok = -1; -+ -+ if (ok != -1) { -+ ret = os_snprintf(buf + len, buflen - len, -+ "Channel: %d : %d HT40%s\n", -+ chan->chan, chan->freq, -+ ok == 1 ? "+" : "-"); -+ -+ if (os_snprintf_error(buflen - len, ret)) -+ return len; -+ -+ len += ret; -+ } -+ } -+ } -+ return len; -+} -+ -+static int hostapd_ctrl_iface_ht40_allow_map(struct hostapd_iface *iface, -+ char *buf, size_t buflen) -+{ -+ struct hostapd_data *hapd = iface->bss[0]; -+ struct hostapd_hw_modes *mode; -+ int len = 0; -+ u16 num_modes, flags; -+ u8 dfs_domain; -+ -+ mode = hostapd_get_hw_feature_data(hapd, &num_modes, &flags, -+ &dfs_domain); -+ -+ if (mode->mode != HOSTAPD_MODE_IEEE80211A) -+ len = hostapd_2ghz_ht40_allow_map(mode, buf, buflen); -+ else -+ len = hostapd_5ghz_ht40_allow_map(mode, buf, buflen); -+ -+ return len; -+} - - static int hostapd_ctrl_iface_remove_neighbor(struct hostapd_data *hapd, - char *buf) -@@ -3790,6 +3876,10 @@ static int hostapd_ctrl_iface_receive_pr - if (radius_server_dac_request(hapd->radius_srv, buf + 12) < 0) - reply_len = -1; - #endif /* RADIUS_SERVER */ -+ } else if (os_strcmp(buf, "HT40_ALLOW_MAP") == 0) { -+ reply_len = hostapd_ctrl_iface_ht40_allow_map(hapd->iface, -+ reply, -+ reply_size); - } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) { - reply_len = hostapd_ctrl_iface_get_capability( - hapd, buf + 15, reply, reply_size); ---- a/hostapd/hostapd_cli.c -+++ b/hostapd/hostapd_cli.c -@@ -1362,6 +1362,12 @@ static int hostapd_cli_cmd_driver_flags( - return wpa_ctrl_command(ctrl, "DRIVER_FLAGS"); - } - -+static int hostapd_cli_cmd_ht40_allow_map(struct wpa_ctrl *ctrl, -+ int argc, char *argv[]) -+{ -+ return wpa_ctrl_command(ctrl, "HT40_ALLOW_MAP"); -+} -+ - - #ifdef CONFIG_DPP - -@@ -1705,6 +1711,8 @@ static const struct hostapd_cli_cmd host - "=Add/Delete/Show/Clear deny MAC ACL" }, - { "poll_sta", hostapd_cli_cmd_poll_sta, hostapd_complete_stations, - " = poll a STA to check connectivity with a QoS null frame" }, -+ { "ht40_allow_map", hostapd_cli_cmd_ht40_allow_map, NULL, -+ "= show ht40 allow map status" }, - { "req_beacon", hostapd_cli_cmd_req_beacon, NULL, - " [req_mode=] = send a Beacon report request to a station" }, - { "reload_wpa_psk", hostapd_cli_cmd_reload_wpa_psk, NULL, diff --git a/feeds/ipq95xx/hostapd/patches/b00-029-hostapd-disable-MAC-ACL-if-WPS-enabled.patch b/feeds/ipq95xx/hostapd/patches/b00-029-hostapd-disable-MAC-ACL-if-WPS-enabled.patch deleted file mode 100644 index 66a4ad2da..000000000 --- a/feeds/ipq95xx/hostapd/patches/b00-029-hostapd-disable-MAC-ACL-if-WPS-enabled.patch +++ /dev/null @@ -1,18 +0,0 @@ ---- a/src/ap/ieee802_11_auth.c -+++ b/src/ap/ieee802_11_auth.c -@@ -174,6 +174,15 @@ static int hostapd_radius_acl_query(stru - int hostapd_check_acl(struct hostapd_data *hapd, const u8 *addr, - struct vlan_description *vlan_id) - { -+ -+#ifdef CONFIG_WPS -+ /* According to WPS spec 2.0, disable MAC address filtering -+ * if WPS is enabled on the AP. -+ */ -+ if (hapd->conf->wps_state) -+ return HOSTAPD_ACL_ACCEPT; -+#endif /*CONFIG_WPS */ -+ - if (hostapd_maclist_found(hapd->conf->accept_mac, - hapd->conf->num_accept_mac, addr, vlan_id)) - return HOSTAPD_ACL_ACCEPT; diff --git a/feeds/ipq95xx/hostapd/patches/b00-034-hostapd-Add-max-rate-information-into-STATUS-and-STA.patch b/feeds/ipq95xx/hostapd/patches/b00-034-hostapd-Add-max-rate-information-into-STATUS-and-STA.patch deleted file mode 100644 index ed325e3fb..000000000 --- a/feeds/ipq95xx/hostapd/patches/b00-034-hostapd-Add-max-rate-information-into-STATUS-and-STA.patch +++ /dev/null @@ -1,224 +0,0 @@ -commit 2dfbe0feb590dfebaf1e92c4006c1ae22ee482bb -Author: houbao -Date: Thu Dec 6 15:17:46 2018 +0800 - - Subject: [PATCH] hostapd: Add max rate information into STATUS and STA - commands - - These allow external programs to get max MCS, max nss, and rate - information of an interface or a STA. - ---- a/src/ap/ctrl_iface_ap.c -+++ b/src/ap/ctrl_iface_ap.c -@@ -51,6 +51,107 @@ static size_t hostapd_write_ht_mcs_bitma - } - - -+static u8 hostapd_maxnss(struct hostapd_data *hapd, struct sta_info *sta) -+{ -+ u8 *mcs_set = NULL; -+ u16 mcs_map; -+ u8 ht_rx_nss = 0; -+ u8 vht_rx_nss = 1; -+ u8 mcs; -+ u8 ht_supported = 0; -+ u8 vht_supported = 0; -+ int i; -+ -+ if (sta) { -+ if (sta->ht_capabilities && (sta->flags & WLAN_STA_HT)) { -+ mcs_set = sta->ht_capabilities->supported_mcs_set; -+ ht_supported = 1; -+ } -+ if (sta->vht_capabilities && (sta->flags & WLAN_STA_VHT)) { -+ mcs_map = le_to_host16(sta->vht_capabilities-> -+ vht_supported_mcs_set.rx_map); -+ vht_supported = 1; -+ } -+ } else { -+ struct hostapd_config *conf = hapd->iface->conf; -+ struct hostapd_hw_modes *mode = hapd->iface->current_mode; -+ -+ if (mode && conf->ieee80211ac && !hapd->conf->disable_11ac) { -+ mcs_map = mode->vht_mcs_set[4] | \ -+ (mode->vht_mcs_set[5] << 8); -+ vht_supported = 1; -+ } -+ if (mode && conf->ieee80211n && !hapd->conf->disable_11n) { -+ mcs_set = mode->mcs_set; -+ ht_supported = 1; -+ } -+ } -+ if (ht_supported && mcs_set != NULL) { -+ if (mcs_set[0]) -+ ht_rx_nss++; -+ if (mcs_set[1]) -+ ht_rx_nss++; -+ if (mcs_set[2]) -+ ht_rx_nss++; -+ if (mcs_set[3]) -+ ht_rx_nss++; -+ } -+ if (vht_supported) { -+ for (i = 7; i >= 0; i--) { -+ mcs = (mcs_map >> (2 * i)) & 0x03; -+ if (mcs != 0x03) { -+ vht_rx_nss = i + 1; -+ break; -+ } -+ } -+ } -+ -+ return ht_rx_nss > vht_rx_nss ? ht_rx_nss : vht_rx_nss; -+} -+ -+ -+static u8 hostapd_htmaxmcs(const u8 *mcs_set) -+{ -+ u8 rates[WLAN_SUPP_RATES_MAX]; -+ u8 i; -+ u8 j = 0; -+ -+ for (i = 0; i < WLAN_SUPP_HT_RATES_MAX; i++) { -+ if (mcs_set[i / 8] & (1 << (i % 8))) -+ rates[j++] = i; -+ if (j == WLAN_SUPP_RATES_MAX) { -+ wpa_printf(MSG_INFO, -+ "HT extended rate set too large; using only %u rates", -+ j); -+ break; -+ } -+ } -+ if (j <= WLAN_SUPP_RATES_MAX) -+ return rates[j - 1]; -+ -+ return 0; -+} -+ -+ -+static u8 hostapd_vhtmaxmcs(u16 rx_vht_mcs_map, u16 tx_vht_mcs_map) -+{ -+ u8 rx_max_mcs, tx_max_mcs, max_mcs; -+ -+ if (rx_vht_mcs_map && tx_vht_mcs_map) { -+ /* Refer to IEEE P802.11ac/D7.0 Figure 8-401bs -+ * for VHT MCS Map definition -+ */ -+ rx_max_mcs = rx_vht_mcs_map & 0x03; -+ tx_max_mcs = tx_vht_mcs_map & 0x03; -+ max_mcs = rx_max_mcs < tx_max_mcs ? rx_max_mcs : tx_max_mcs; -+ if (max_mcs < 0x03) -+ return 7 + max_mcs; -+ } -+ -+ return 0; -+} -+ -+ - static int hostapd_get_sta_info(struct hostapd_data *hapd, - struct sta_info *sta, - char *buf, size_t buflen) -@@ -161,6 +262,38 @@ static int hostapd_get_sta_info(struct - len += ret; - } - -+ ret = os_snprintf(buf + len, buflen - len, "max_nss=%u\n", -+ hostapd_maxnss(hapd, sta)); -+ if (!os_snprintf_error(buflen - len, ret)) -+ len += ret; -+ -+#ifdef CONFIG_IEEE80211AC -+ if ((sta->flags & WLAN_STA_VHT) && sta->vht_capabilities) { -+ u8 vht_maxmcs = hostapd_vhtmaxmcs( -+ le_to_host16(sta->vht_capabilities-> -+ vht_supported_mcs_set.rx_map), -+ le_to_host16(sta->vht_capabilities-> -+ vht_supported_mcs_set.tx_map)); -+ ret = os_snprintf(buf + len, buflen - len, "max_vhtmcs=%u\n", -+ vht_maxmcs); -+ if (!os_snprintf_error(buflen - len, ret)) -+ len += ret; -+ } -+#endif /* CONFIG_IEEE80211AC */ -+ -+#ifdef CONFIG_IEEE80211N -+ if ((sta->flags & (WLAN_STA_HT | WLAN_STA_VHT)) == WLAN_STA_HT && -+ sta->ht_capabilities) { -+ u8 ht_maxmcs; -+ -+ ht_maxmcs = hostapd_htmaxmcs(sta->ht_capabilities-> -+ supported_mcs_set); -+ ret = os_snprintf(buf + len, buflen - len, "max_mcs=%u\n", -+ ht_maxmcs); -+ if (!os_snprintf_error(buflen - len, ret)) -+ len += ret; -+ } -+#endif /* CONFIG_IEEE80211N */ - return len; - } - -@@ -798,6 +931,20 @@ int hostapd_ctrl_iface_status(struct hos - if (os_snprintf_error(buflen - len, ret)) - return len; - len += ret; -+ -+ if (mode) { -+ u16 rxmap = mode->vht_mcs_set[0] | -+ (mode->vht_mcs_set[1] << 8); -+ u16 txmap = mode->vht_mcs_set[4] | -+ (mode->vht_mcs_set[5] << 8); -+ -+ ret = os_snprintf(buf + len, buflen - len, -+ "vht_max_mcs=%u\n", -+ hostapd_vhtmaxmcs(rxmap, txmap)); -+ if (os_snprintf_error(buflen - len, ret)) -+ return len; -+ len += ret; -+ } - } - - if (iface->conf->ieee80211n && !hapd->conf->disable_11n) { -@@ -832,8 +979,33 @@ int hostapd_ctrl_iface_status(struct hos - if (os_snprintf_error(buflen - len, ret)) - return len; - len += ret; -+ -+ if (mode) { -+ ret = os_snprintf(buf + len, buflen - len, -+ "max_mcs=%u\n", -+ hostapd_htmaxmcs(mode->mcs_set)); -+ if (os_snprintf_error(buflen - len, ret)) -+ return len; -+ len += ret; -+ } - } - -+ if (mode && mode->rates && mode->num_rates && -+ mode->num_rates <= WLAN_SUPP_RATES_MAX) { -+ ret = os_snprintf(buf + len, buflen - len, -+ "max_rate=%u\n", -+ mode->rates[mode->num_rates - 1]); -+ if (os_snprintf_error(buflen - len, ret)) -+ return len; -+ len += ret; -+ } -+ -+ ret = os_snprintf(buf + len, buflen - len, "max_nss=%u\n", -+ hostapd_maxnss(hapd, NULL)); -+ if (os_snprintf_error(buflen - len, ret)) -+ return len; -+ len += ret; -+ - for (j = 0; mode && j < mode->num_channels; j++) { - if (mode->channels[j].freq == iface->freq) { - ret = os_snprintf(buf + len, buflen - len, ---- a/src/ap/sta_info.h -+++ b/src/ap/sta_info.h -@@ -46,6 +46,7 @@ - /* Maximum number of supported rates (from both Supported Rates and Extended - * Supported Rates IEs). */ - #define WLAN_SUPP_RATES_MAX 32 -+#define WLAN_SUPP_HT_RATES_MAX 77 - - struct hostapd_data; - diff --git a/feeds/ipq95xx/hostapd/patches/b00-036-hostapd-disable-40mhz-scan.patch b/feeds/ipq95xx/hostapd/patches/b00-036-hostapd-disable-40mhz-scan.patch deleted file mode 100644 index 3251904f4..000000000 --- a/feeds/ipq95xx/hostapd/patches/b00-036-hostapd-disable-40mhz-scan.patch +++ /dev/null @@ -1,41 +0,0 @@ ---- a/hostapd/config_file.c -+++ b/hostapd/config_file.c -@@ -4235,6 +4235,8 @@ static int hostapd_config_fill(struct ho - } else if (os_strcmp(buf, "wowlan_triggers") == 0) { - os_free(bss->wowlan_triggers); - bss->wowlan_triggers = os_strdup(pos); -+ } else if (os_strcmp(buf, "disable_40mhz_scan") == 0) { -+ conf->disable_40mhz_scan = atoi(pos); - #ifdef CONFIG_FST - } else if (os_strcmp(buf, "fst_group_id") == 0) { - size_t len = os_strlen(pos); ---- a/src/ap/ap_config.h -+++ b/src/ap/ap_config.h -@@ -1018,6 +1018,7 @@ struct hostapd_config { - } *acs_chan_bias; - unsigned int num_acs_chan_bias; - #endif /* CONFIG_ACS */ -+ int disable_40mhz_scan; - - struct wpabuf *lci; - struct wpabuf *civic; ---- a/src/ap/hw_features.c -+++ b/src/ap/hw_features.c -@@ -696,9 +696,14 @@ int hostapd_check_ht_capab(struct hostap - !ieee80211ac_supported_vht_capab(iface)) - return -1; - #endif /* CONFIG_IEEE80211AC */ -- ret = ieee80211n_check_40mhz(iface); -- if (ret) -- return ret; -+ if (!iface->conf->disable_40mhz_scan) { -+ ret = ieee80211n_check_40mhz(iface); -+ if (ret) -+ return ret; -+ } else { -+ wpa_printf(MSG_INFO, "%s:40mhz scan disabled", -+ iface->conf->bss[0]->iface); -+ } - if (!ieee80211n_allowed_ht40_channel_pair(iface)) - return -1; - diff --git a/feeds/ipq95xx/hostapd/patches/c00-002-hostapd-he-update-nl-header.patch b/feeds/ipq95xx/hostapd/patches/c00-002-hostapd-he-update-nl-header.patch deleted file mode 100644 index 8de804a54..000000000 --- a/feeds/ipq95xx/hostapd/patches/c00-002-hostapd-he-update-nl-header.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 1737f5a14528e32df1806471222176e507728fe0 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Fri, 3 May 2019 08:16:44 +0200 -Subject: [PATCH] update nl80211.h - -Sync with mac80211-next.git include/uapi/linux/nl80211.h - -This brings in nl80211 definitions as of 2019-06-19. - -Signed-off-by: John Crispin ---- - src/drivers/nl80211_copy.h | 75 +++++++++++++++++++++++----------------------- - 1 file changed, 37 insertions(+), 38 deletions(-) - -Index: hostapd-2021-02-08/src/drivers/nl80211_copy.h -=================================================================== ---- hostapd-2021-02-08.orig/src/drivers/nl80211_copy.h -+++ hostapd-2021-02-08/src/drivers/nl80211_copy.h -@@ -4541,6 +4541,10 @@ enum nl80211_chan_width { - NL80211_CHAN_WIDTH_4, - NL80211_CHAN_WIDTH_8, - NL80211_CHAN_WIDTH_16, -+ -+ /* keep last */ -+ __NL80211_CHAN_WIDTH_NUM, -+ NL80211_CHAN_WIDTH_MAX = __NL80211_CHAN_WIDTH_NUM - 1, - }; - - /** -Index: hostapd-2021-02-08/src/ap/dfs.c -=================================================================== ---- hostapd-2021-02-08.orig/src/ap/dfs.c -+++ hostapd-2021-02-08/src/ap/dfs.c -@@ -1051,13 +1051,17 @@ static int hostapd_dfs_testmode_set_beac - iface->conf->hw_mode, - iface->freq, - iface->conf->channel, -+ iface->conf->enable_edmg, -+ iface->conf->edmg_channel, - iface->conf->ieee80211n, - iface->conf->ieee80211ac, -+ iface->conf->ieee80211ax, - secondary_channel, -- iface->conf->vht_oper_chwidth, -+ hostapd_get_oper_chwidth(iface->conf), - vht_oper_centr_freq_seg0_idx, - vht_oper_centr_freq_seg1_idx, -- iface->current_mode->vht_capab); -+ iface->current_mode->vht_capab, -+ &iface->current_mode->he_capab[IEEE80211_MODE_AP]); - - if (err) { - wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params"); diff --git a/feeds/ipq95xx/hostapd/patches/c00-010-hostapd-fix-enabling-he-in-5G.patch b/feeds/ipq95xx/hostapd/patches/c00-010-hostapd-fix-enabling-he-in-5G.patch deleted file mode 100644 index 8232429c5..000000000 --- a/feeds/ipq95xx/hostapd/patches/c00-010-hostapd-fix-enabling-he-in-5G.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/wpa_supplicant/wpa_supplicant.c -+++ b/wpa_supplicant/wpa_supplicant.c -@@ -2653,7 +2653,7 @@ skip_ht40: - if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq, - freq->channel, ssid->enable_edmg, - ssid->edmg_channel, freq->ht_enabled, -- vht_freq.vht_enabled, freq->he_enabled, -+ vht_freq.vht_enabled, vht_freq.he_enabled, - freq->sec_channel_offset, - chwidth, seg0, seg1, vht_caps, - &mode->he_capab[ieee80211_mode]) != 0) diff --git a/feeds/ipq95xx/hostapd/patches/c00-011-hostapd-add-mbo-support.patch b/feeds/ipq95xx/hostapd/patches/c00-011-hostapd-add-mbo-support.patch deleted file mode 100644 index 3b10235d7..000000000 --- a/feeds/ipq95xx/hostapd/patches/c00-011-hostapd-add-mbo-support.patch +++ /dev/null @@ -1,370 +0,0 @@ ---- a/hostapd/config_file.c -+++ b/hostapd/config_file.c -@@ -4143,10 +4143,12 @@ static int hostapd_config_fill(struct ho - #ifdef CONFIG_MBO - } else if (os_strcmp(buf, "mbo") == 0) { - bss->mbo_enabled = atoi(pos); -- } else if (os_strcmp(buf, "mbo_cell_data_conn_pref") == 0) { -- bss->mbo_cell_data_conn_pref = atoi(pos); -+ } else if (os_strcmp(buf, "mbo_ap_cap_ind") == 0) { -+ bss->mbo_ap_cap_ind = atoi(pos); - } else if (os_strcmp(buf, "oce") == 0) { - bss->oce = atoi(pos); -+ } else if (os_strcmp(buf, "mbo_cell_data_conn_pref") == 0) { -+ bss->mbo_cell_data_conn_pref = atoi(pos); - #endif /* CONFIG_MBO */ - #ifdef CONFIG_TESTING_OPTIONS - #define PARSE_TEST_PROBABILITY(_val) \ ---- a/hostapd/ctrl_iface.c -+++ b/hostapd/ctrl_iface.c -@@ -882,10 +882,11 @@ static int hostapd_ctrl_iface_bss_tm_req - if (pos) { - pos += 10; - req_mode |= WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED; -- /* TODO: TSF configurable/learnable */ -+ /* TODO: TSF learnable */ - bss_term_dur[0] = 4; /* Subelement ID */ - bss_term_dur[1] = 10; /* Length */ -- os_memset(&bss_term_dur[2], 0, 8); -+ bss_term_dur[2] = atoi(pos); /* TSF */ -+ os_memset(&bss_term_dur[3], 0, 7); - end = os_strchr(pos, ','); - if (end == NULL) { - wpa_printf(MSG_DEBUG, "Invalid bss_term data"); -@@ -895,7 +896,7 @@ static int hostapd_ctrl_iface_bss_tm_req - WPA_PUT_LE16(&bss_term_dur[10], atoi(end)); - } - -- nei_len = ieee802_11_parse_candidate_list(cmd, nei_rep, -+ nei_len = ieee802_11_parse_candidate_list(cmd, sta, nei_rep, - sizeof(nei_rep)); - if (nei_len < 0) - return -1; ---- a/src/ap/ap_config.h -+++ b/src/ap/ap_config.h -@@ -714,6 +714,11 @@ struct hostapd_bss_config { - * - Set BIT(2) to enable OCE in AP mode - */ - unsigned int oce; -+ /** -+ * Set BIT(6) to advertise cellular data aware capability -+ * in AP mode -+ */ -+ unsigned int mbo_ap_cap_ind; - int mbo_cell_data_conn_pref; - #endif /* CONFIG_MBO */ - ---- a/src/ap/gas_serv.c -+++ b/src/ap/gas_serv.c -@@ -19,6 +19,7 @@ - #include "dpp_hostapd.h" - #include "sta_info.h" - #include "gas_serv.h" -+#include "neighbor_db.h" - - - #ifdef CONFIG_DPP -@@ -603,6 +604,28 @@ static void anqp_add_domain_name(struct - } - } - -+static void anqp_add_neighbor_report(struct hostapd_data *hapd, -+ struct wpabuf *buf) -+{ -+ if (anqp_add_override(hapd, buf, ANQP_NEIGHBOR_REPORT)) -+ return; -+ -+ if (hapd->conf->radio_measurements[0] & -+ WLAN_RRM_CAPS_NEIGHBOR_REPORT) { -+ u8* len, *nei_len; -+ len = gas_anqp_add_element(buf, ANQP_NEIGHBOR_REPORT); -+ wpabuf_put_u8(buf, WLAN_EID_NEIGHBOR_REPORT); -+ nei_len = (u8 *)wpabuf_put(buf, 1); -+ -+ if (hostapd_prepare_neighbor_buf(hapd, hapd->own_addr, -+ buf)) { -+ buf->used -= 2; -+ return; -+ } -+ *nei_len = ((u8 *)wpabuf_put(buf, 0) - nei_len - 1); -+ gas_anqp_set_element_len(buf, len); -+ } -+} - - #ifdef CONFIG_FILS - static void anqp_add_fils_realm_info(struct hostapd_data *hapd, -@@ -1028,6 +1051,8 @@ gas_serv_build_gas_resp_payload(struct h - anqp_add_elem(hapd, buf, ANQP_TDLS_CAPABILITY); - if (request & ANQP_REQ_EMERGENCY_NAI) - anqp_add_elem(hapd, buf, ANQP_EMERGENCY_NAI); -+ if (request & ANQP_REQ_NEIGHBOR_REPORT) -+ anqp_add_neighbor_report(hapd, buf); - - for (i = 0; i < num_extra_req; i++) { - #ifdef CONFIG_FILS -@@ -1172,6 +1197,12 @@ static void rx_anqp_query_list_id(struct - "Emergency NAI", - get_anqp_elem(hapd, info_id) != NULL, qi); - break; -+ case ANQP_NEIGHBOR_REPORT: -+ set_anqp_req(ANQP_REQ_NEIGHBOR_REPORT, -+ "Neighbor report", -+ (hapd->conf->radio_measurements[0] & -+ WLAN_RRM_CAPS_NEIGHBOR_REPORT), qi); -+ break; - default: - #ifdef CONFIG_FILS - if (info_id == ANQP_FILS_REALM_INFO && ---- a/src/ap/gas_serv.h -+++ b/src/ap/gas_serv.h -@@ -40,6 +40,8 @@ - (1 << (ANQP_TDLS_CAPABILITY - ANQP_QUERY_LIST)) - #define ANQP_REQ_EMERGENCY_NAI \ - (1 << (ANQP_EMERGENCY_NAI - ANQP_QUERY_LIST)) -+#define ANQP_REQ_NEIGHBOR_REPORT \ -+ (1 << (ANQP_NEIGHBOR_REPORT - ANQP_QUERY_LIST)) - /* - * First 15 Hotspot 2.0 vendor specific ANQP-elements can be included in the - * optimized bitmap. ---- a/src/ap/ieee802_11.h -+++ b/src/ap/ieee802_11.h -@@ -132,6 +132,9 @@ static inline void sae_clear_retransmit_ - } - #endif /* CONFIG_SAE */ - -+u8 * hostapd_eid_rm_enabled_capab(struct hostapd_data *hapd, -+ u8 *eid, size_t len); -+ - #ifdef CONFIG_MBO - - u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, size_t len); ---- a/src/ap/ieee802_11_shared.c -+++ b/src/ap/ieee802_11_shared.c -@@ -801,11 +801,13 @@ u8 * hostapd_eid_mbo(struct hostapd_data - !OCE_STA_CFON_ENABLED(hapd) && !OCE_AP_ENABLED(hapd)) - return eid; - -- if (hapd->conf->mbo_enabled) { -+ if (hapd->conf->mbo_enabled && hapd->conf->oce & OCE_AP) { - *mbo_pos++ = MBO_ATTR_ID_AP_CAPA_IND; - *mbo_pos++ = 1; -- /* Not Cellular aware */ -- *mbo_pos++ = 0; -+ if (hapd->conf->mbo_ap_cap_ind & MBO_AP_CAPA_CELL_AWARE) -+ *mbo_pos++ = MBO_AP_CAPA_CELL_AWARE; -+ else -+ *mbo_pos++ = 0; - } - - if (hapd->conf->mbo_enabled && hapd->mbo_assoc_disallow) { ---- a/src/ap/neighbor_db.c -+++ b/src/ap/neighbor_db.c -@@ -160,6 +160,24 @@ fail: - return -1; - } - -+int hostapd_prepare_neighbor_buf(struct hostapd_data *hapd, -+ const u8 *bssid, struct wpabuf *nrbuf) -+{ -+ struct hostapd_neighbor_entry *nr; -+ -+ nr = hostapd_neighbor_get(hapd, bssid, NULL); -+ if (!nr) -+ return -1; -+ -+ if (wpabuf_tailroom(nrbuf) < wpabuf_len(nr->nr)) { -+ wpa_printf(MSG_ERROR, -+ "Invalid buf size for Neighbor Report\n"); -+ return -1; -+ } -+ -+ wpabuf_put_buf(nrbuf, nr->nr); -+ return 0; -+} - - int hostapd_neighbor_remove(struct hostapd_data *hapd, const u8 *bssid, - const struct wpa_ssid_value *ssid) ---- a/src/ap/neighbor_db.h -+++ b/src/ap/neighbor_db.h -@@ -19,6 +19,8 @@ int hostapd_neighbor_set(struct hostapd_ - const struct wpabuf *nr, const struct wpabuf *lci, - const struct wpabuf *civic, int stationary); - void hostapd_neighbor_set_own_report(struct hostapd_data *hapd); -+int hostapd_prepare_neighbor_buf(struct hostapd_data *hapd, -+ const u8 *bssid, struct wpabuf *nrbuf); - int hostapd_neighbor_remove(struct hostapd_data *hapd, const u8 *bssid, - const struct wpa_ssid_value *ssid); - void hostapd_free_neighbor_db(struct hostapd_data *hapd); ---- a/src/ap/wnm_ap.c -+++ b/src/ap/wnm_ap.c -@@ -20,6 +20,7 @@ - #include "ap/wpa_auth.h" - #include "mbo_ap.h" - #include "wnm_ap.h" -+#include "neighbor_db.h" - - #define MAX_TFS_IE_LEN 1024 - -@@ -366,11 +367,27 @@ static int ieee802_11_send_bss_trans_mgm - u8 dialog_token) - { - struct ieee80211_mgmt *mgmt; -- size_t len; -+ size_t len, nr_len = 0; - u8 *pos; -+ u8 req_mode = 0; - int res; - -- mgmt = os_zalloc(sizeof(*mgmt)); -+#ifdef CONFIG_MBO -+ u8 *nr_pos; -+ struct hostapd_neighbor_entry *nr; -+ struct wpabuf *nrbuf = NULL; -+ if (hapd->conf->mbo_enabled) { -+ dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry, -+ list) -+ /* ID and length */ -+ nr_len += wpabuf_len(nr->nr) + 1 + 1; -+ -+ nrbuf = wpabuf_alloc(nr_len); -+ if (nrbuf == NULL) -+ return -1; -+ } -+#endif -+ mgmt = os_zalloc(sizeof(*mgmt) + nr_len); - if (mgmt == NULL) - return -1; - os_memcpy(mgmt->da, addr, ETH_ALEN); -@@ -381,7 +398,11 @@ static int ieee802_11_send_bss_trans_mgm - mgmt->u.action.category = WLAN_ACTION_WNM; - mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ; - mgmt->u.action.u.bss_tm_req.dialog_token = dialog_token; -- mgmt->u.action.u.bss_tm_req.req_mode = 0; -+#ifdef CONFIG_MBO -+ if (hapd->conf->mbo_enabled) -+ req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED; -+#endif -+ mgmt->u.action.u.bss_tm_req.req_mode = req_mode; - mgmt->u.action.u.bss_tm_req.disassoc_timer = host_to_le16(0); - mgmt->u.action.u.bss_tm_req.validity_interval = 1; - pos = mgmt->u.action.u.bss_tm_req.variable; -@@ -394,6 +415,25 @@ static int ieee802_11_send_bss_trans_mgm - le_to_host16(mgmt->u.action.u.bss_tm_req.disassoc_timer), - mgmt->u.action.u.bss_tm_req.validity_interval); - -+#ifdef CONFIG_MBO -+ if (hapd->conf->mbo_enabled) { -+ dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry, -+ list) { -+ wpabuf_put_u8(nrbuf, WLAN_EID_NEIGHBOR_REPORT); -+ /* Length to be filled */ -+ nr_pos = (u8 *)wpabuf_put(nrbuf, 1); -+ if (hostapd_prepare_neighbor_buf(hapd, nr->bssid, -+ nrbuf) < 0) { -+ res = -1; -+ } -+ /* Fill in the length field */ -+ *nr_pos = ((u8 *)wpabuf_put(nrbuf, 0) - nr_pos - 1); -+ } -+ os_memcpy(pos, nrbuf->buf, nr_len); -+ pos += nr_len; -+ wpabuf_free(nrbuf); -+ } -+#endif - len = pos - &mgmt->u.action.category; - res = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, - mgmt->da, &mgmt->u.action.category, len); ---- a/src/common/ieee802_11_common.c -+++ b/src/common/ieee802_11_common.c -@@ -2290,11 +2290,21 @@ bool is_6ghz_psc_frequency(int freq) - } - - --int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep, -- size_t nei_rep_len) -+int ieee802_11_parse_candidate_list(const char *pos, struct sta_info *sta, -+ u8 *nei_rep, size_t nei_rep_len) - { - u8 *nei_pos = nei_rep; - const char *end; -+#ifdef CONFIG_MBO -+ u8 non_pref_chan = 0; -+ u8 *pref_pos = NULL; -+ int i; -+ -+ struct mbo_non_pref_chan_info *info = NULL; -+ -+ if (sta && sta->non_pref_chan) -+ info = sta->non_pref_chan; -+#endif - - /* - * BSS Transition Candidate List Entries - Neighbor Report elements -@@ -2350,6 +2360,9 @@ int ieee802_11_parse_candidate_list(cons - pos++; - - *nei_pos++ = atoi(pos); /* Channel Number */ -+#ifdef CONFIG_MBO -+ non_pref_chan = atoi(pos); -+#endif - pos = os_strchr(pos, ','); - if (pos == NULL) { - wpa_printf(MSG_DEBUG, "Missing PHY Type"); -@@ -2381,6 +2394,25 @@ int ieee802_11_parse_candidate_list(cons - "Invalid neighbor subelement info"); - return -1; - } -+#ifdef CONFIG_MBO -+ if (info) { -+ for (i = 0; i < (len / 2); i++) -+ if (nei_pos[i] == WNM_NEIGHBOR_BSS_TRANSITION_CANDIDATE && -+ nei_pos[i + 1] == 0x1) /* length */ -+ pref_pos = (nei_pos + i + 2); -+ -+ /* If STA had updated MBO non-pref chan report, -+ * use the same candidate preference value in the -+ * BSS Transition Candidate sub-element. -+ */ -+ for ( ; info ; info = info->next) -+ for (i = 0; i < info->num_channels; i++) -+ if (non_pref_chan == info->channels[i]) -+ *pref_pos = info->pref; -+ -+ info = sta->non_pref_chan; -+ } -+#endif - nei_pos += len / 2; - pos = end; - } ---- a/src/common/ieee802_11_common.h -+++ b/src/common/ieee802_11_common.h -@@ -11,6 +11,7 @@ - - #include "defs.h" - #include "ieee802_11_defs.h" -+#include "ap/sta_info.h" - - struct element { - u8 id; -@@ -265,8 +266,8 @@ bool is_6ghz_freq(int freq); - bool is_6ghz_op_class(u8 op_class); - bool is_6ghz_psc_frequency(int freq); - --int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep, -- size_t nei_rep_len); -+int ieee802_11_parse_candidate_list(const char *pos, struct sta_info *sta, -+ u8 *nei_rep, size_t nei_rep_len); - - int ieee802_11_ext_capab(const u8 *ie, unsigned int capab); - int op_class_to_bandwidth(u8 op_class); ---- a/wpa_supplicant/wnm_sta.c -+++ b/wpa_supplicant/wnm_sta.c -@@ -1630,7 +1630,7 @@ int wnm_send_bss_transition_mgmt_query(s - return ret; - } - -- ret = ieee802_11_parse_candidate_list(btm_candidates, -+ ret = ieee802_11_parse_candidate_list(btm_candidates, NULL, - wpabuf_put(buf, 0), - max_len); - if (ret < 0) { diff --git a/feeds/ipq95xx/hostapd/patches/d00-002-set-supp-chan-width-for-40mghz.patch b/feeds/ipq95xx/hostapd/patches/d00-002-set-supp-chan-width-for-40mghz.patch deleted file mode 100644 index b8ee16442..000000000 --- a/feeds/ipq95xx/hostapd/patches/d00-002-set-supp-chan-width-for-40mghz.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 950186814b355d91bcb15ce544eed6f5727da791 Mon Sep 17 00:00:00 2001 -From: Lavanya Suresh -Date: Tue, 17 Nov 2020 19:23:46 +0530 -Subject: [PATCH] hostapd: Add channel width config in htcapab for 40MHz - -HT Support Channel Width field needs to be set in HT capabilities for -40MHz BW operation. - -Signed-off-by: Lavanya Suresh ---- - src/ap/hostapd.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c -index be9ef82..346d83c 100644 ---- a/src/ap/hostapd.c -+++ b/src/ap/hostapd.c -@@ -3532,6 +3532,9 @@ static int hostapd_fill_csa_settings(struct hostapd_data *hapd, - if (!iface || !iface->freq || hapd->csa_in_progress) - return -1; - -+ if (settings->freq_params.bandwidth != 20) -+ hapd->iconf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; -+ - switch (settings->freq_params.bandwidth) { - case 80: - if (settings->freq_params.center_freq2) --- -2.7.4 - diff --git a/feeds/ipq95xx/hostapd/patches/d00-003-wpa-supplicant-override-HE-toVHT-2G.patch b/feeds/ipq95xx/hostapd/patches/d00-003-wpa-supplicant-override-HE-toVHT-2G.patch deleted file mode 100644 index 63e49fa54..000000000 --- a/feeds/ipq95xx/hostapd/patches/d00-003-wpa-supplicant-override-HE-toVHT-2G.patch +++ /dev/null @@ -1,63 +0,0 @@ -Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/config_ssid.h -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/config_ssid.h -+++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/config_ssid.h -@@ -1124,7 +1124,6 @@ struct wpa_ssid { - * FT initial mobility domain association. - */ - int ft_eap_pmksa_caching; -- - /** - * beacon_prot - Whether Beacon protection is enabled - * -Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/wpa_supplicant.c -+++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant.c -@@ -2578,16 +2578,14 @@ void ibss_mesh_setup_freq(struct wpa_sup - return; - - /* Allow HE on 2.4 GHz without VHT: see nl80211_put_freq_params() */ -- if (is_24ghz) -- freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported; -+ if (is_24ghz) { - #ifdef CONFIG_HE_OVERRIDES -- if (is_24ghz && ssid->disable_he) -- freq->he_enabled = 0; -+ if (ssid->disable_he) -+ freq->he_enabled = 0; -+ else - #endif /* CONFIG_HE_OVERRIDES */ -- -- /* Setup higher BW only for 5 GHz */ -- if (mode->mode != HOSTAPD_MODE_IEEE80211A && !(ssid->noscan)) -- return; -+ freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported; -+ } - - for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) { - pri_chan = &mode->channels[chan_idx]; -@@ -2677,6 +2675,11 @@ void ibss_mesh_setup_freq(struct wpa_sup - - wpa_scan_results_free(scan_res); - } -+#ifdef CONFIG_HE_OVERRIDES -+skip_vht80: -+ if (ssid->disable_he) -+ vht_freq.he_enabled = 0; -+#endif /* CONFIG_HE_OVERRIDES */ - - #ifdef CONFIG_HT_OVERRIDES - skip_ht40: -@@ -2711,6 +2714,11 @@ skip_to_6ghz: - /* Enable HE with VHT for 5 GHz */ - freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported; - -+#ifdef CONFIG_HE_OVERRIDES -+ if (is_24ghz) -+ goto skip_vht80; -+#endif /* CONFIG_HE_OVERRIDES */ -+ - /* setup center_freq1, bandwidth */ - for (j = 0; j < ARRAY_SIZE(bw80); j++) { - if (freq->freq >= bw80[j] && diff --git a/feeds/ipq95xx/hostapd/patches/d00-007-fixing-warning.patch b/feeds/ipq95xx/hostapd/patches/d00-007-fixing-warning.patch deleted file mode 100644 index 814ef7bb9..000000000 --- a/feeds/ipq95xx/hostapd/patches/d00-007-fixing-warning.patch +++ /dev/null @@ -1,83 +0,0 @@ -From ed93959f61e103703d04b85351eed7a1c4fe644b Mon Sep 17 00:00:00 2001 -From: Karthikeyan Kathirvel -Date: Fri, 28 Aug 2020 14:16:10 +0530 -Subject: [PATCH] hostapd: Fixed compilation warnings - -Below warnings are fixed - -Uninitialized and redefined macro warnings has been fixed - -../src/crypto/sha1-internal.c:152:0: error: "R3" redefined [-Werror] - #define R3(v,w,x,y,z,i) \ - ^ -In file included from qsdk/staging_dir/toolchain-arm_cortex-a7_gcc-5.2.0_uClibc-1.0.14_eabi/include/signal.h:358:0, -from qsdk/build_dir/target-arm_cortex-a7_uClibc-1.0.14_eabi/hostapd-supplicant-full/hostapd-2021-12-13/src/utils/includes.h:26, -from ../src/crypto/sha1-internal.c:9: -qsdk/staging_dir/toolchain-arm_cortex-a7_gcc-5.2.0_uClibc-1.0.14_eabi/include/sys/ucontext.h:49:0: -note: this is the location of the previous definition -#define R3 R3 - -Signed-off-by: Karthikeyan Kathirvel ---- - src/ap/ieee802_11.c | 2 +- - src/ap/wpa_auth.c | 4 ++++ - src/rsn_supp/wpa.c | 2 +- - 3 files changed, 6 insertions(+), 2 deletions(-) - ---- a/src/drivers/driver_nl80211.c -+++ b/src/drivers/driver_nl80211.c -@@ -4859,7 +4859,7 @@ static int wpa_driver_nl80211_sta_add(vo - - if (params->he_capab) { - wpa_hexdump(MSG_DEBUG, " * he_capab", -- params->he_capab, params->he_capab_len); -+ (u8 *) params->he_capab, params->he_capab_len); - if (nla_put(msg, NL80211_ATTR_HE_CAPABILITY, - params->he_capab_len, params->he_capab)) - goto fail; ---- a/src/tls/tlsv1_client_ocsp.c -+++ b/src/tls/tlsv1_client_ocsp.c -@@ -322,7 +322,7 @@ tls_process_ocsp_responses(struct tlsv1_ - { - struct asn1_hdr hdr; - const u8 *pos, *end; -- enum tls_ocsp_result res; -+ enum tls_ocsp_result res = TLS_OCSP_NO_RESPONSE; - - pos = resp; - end = resp + len; ---- a/src/crypto/sha1-internal.c -+++ b/src/crypto/sha1-internal.c -@@ -141,17 +141,32 @@ A million repetitions of "a" - block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1)) - - /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ -+#ifdef R0 -+#undef R0 -+#endif - #define R0(v,w,x,y,z,i) \ - z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \ - w = rol(w, 30); -+#ifdef R1 -+#undef R1 -+#endif - #define R1(v,w,x,y,z,i) \ - z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \ - w = rol(w, 30); -+#ifdef R2 -+#undef R2 -+#endif - #define R2(v,w,x,y,z,i) \ - z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); w = rol(w, 30); -+#ifdef R3 -+#undef R3 -+#endif - #define R3(v,w,x,y,z,i) \ - z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \ - w = rol(w, 30); -+#ifdef R4 -+#undef R4 -+#endif - #define R4(v,w,x,y,z,i) \ - z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \ - w=rol(w, 30); diff --git a/feeds/ipq95xx/hostapd/patches/d00-009-hostapd-update-muedca-params.patch b/feeds/ipq95xx/hostapd/patches/d00-009-hostapd-update-muedca-params.patch deleted file mode 100644 index aaa83bde8..000000000 --- a/feeds/ipq95xx/hostapd/patches/d00-009-hostapd-update-muedca-params.patch +++ /dev/null @@ -1,291 +0,0 @@ ---- a/src/ap/drv_callbacks.c -+++ b/src/ap/drv_callbacks.c -@@ -1785,6 +1785,39 @@ static void hostapd_event_wds_sta_interf - ifname, MAC2STR(addr)); - } - -+static void hostapd_event_update_muedca_params(struct hostapd_data *hapd, -+ struct update_muedca *params) -+{ -+ int i; -+ u8 updated_count; -+ -+ /* Update current MU-EDCA parameters */ -+ for (i = 0; i < 3; i++) { -+ hapd->iface->conf->he_mu_edca.he_mu_ac_be_param[i] = -+ params->he_mu_ac_be_param[i]; -+ hapd->iface->conf->he_mu_edca.he_mu_ac_bk_param[i] = -+ params->he_mu_ac_bk_param[i]; -+ hapd->iface->conf->he_mu_edca.he_mu_ac_vo_param[i] = -+ params->he_mu_ac_vo_param[i]; -+ hapd->iface->conf->he_mu_edca.he_mu_ac_vi_param[i] = -+ params->he_mu_ac_vi_param[i]; -+ } -+ -+ /* Increment Parameter Set Update Count for MU-EDCA and WME EDCA only -+ * if any STA is connected -+ */ -+ if (hapd->num_sta) { -+ updated_count = (hapd->iface->conf->he_mu_edca.he_qos_info + 1) & 0xf; -+ hapd->iface->conf->he_mu_edca.he_qos_info &= 0xf0; -+ hapd->iface->conf->he_mu_edca.he_qos_info |= updated_count; -+ hapd->parameter_set_count++; -+ } -+ -+ /* Update beacon with updated MU-EDCA parameters */ -+ if (ieee802_11_update_beacons(hapd->iface)) -+ wpa_printf(MSG_DEBUG, -+ "Failed to update beacons with MU-EDCA parameters"); -+} - - #ifdef CONFIG_OWE - static int hostapd_notif_update_dh_ie(struct hostapd_data *hapd, -@@ -2093,6 +2126,9 @@ void hostapd_wpa_event(void *ctx, enum w - data->wds_sta_interface.ifname, - data->wds_sta_interface.sta_addr); - break; -+ case EVENT_UPDATE_MUEDCA_PARAMS: -+ hostapd_event_update_muedca_params(hapd, &data->update_muedca); -+ break; - default: - wpa_printf(MSG_DEBUG, "Unknown event %d", event); - break; ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -5135,6 +5135,15 @@ enum wpa_event_type { - * is required to provide more details of the frame. - */ - EVENT_UNPROT_BEACON, -+ -+ /** -+ * EVENT_UPDATE_MUEDCA_PARAMS - Updated MU-EDCA parameters received -+ * -+ * This event is emitted when updated MU-EDCA parameters from driver -+ * are received. Updated MU-EDCA parameters need to be updated in -+ * beacon. -+ */ -+ EVENT_UPDATE_MUEDCA_PARAMS, - }; - - -@@ -6027,6 +6036,16 @@ union wpa_event_data { - struct unprot_beacon { - const u8 *sa; - } unprot_beacon; -+ -+ /** -+ * struct update_muedca - Data for EVENT_UPDATE_MU_EDCA_PARAMS -+ */ -+ struct update_muedca { -+ u8 he_mu_ac_be_param[3]; -+ u8 he_mu_ac_bk_param[3]; -+ u8 he_mu_ac_vi_param[3]; -+ u8 he_mu_ac_vo_param[3]; -+ } update_muedca; - }; - - /** ---- a/src/drivers/driver_nl80211_event.c -+++ b/src/drivers/driver_nl80211_event.c -@@ -172,6 +172,8 @@ static const char * nl80211_command_to_s - C2S(NL80211_CMD_UNPROT_BEACON) - C2S(NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS) - C2S(NL80211_CMD_SET_SAR_SPECS) -+ C2S(NL80211_CMD_UPDATE_HE_MUEDCA_PARAMS) -+ C2S(NL80211_CMD_COLOR_CHANGE) - C2S(__NL80211_CMD_AFTER_LAST) - } - #undef C2S -@@ -2797,6 +2799,35 @@ static void nl80211_sta_opmode_change_ev - wpa_supplicant_event(drv->ctx, EVENT_STATION_OPMODE_CHANGED, &ed); - } - -+static void nl80211_update_muedca_params_event(struct wpa_driver_nl80211_data *drv, -+ struct nlattr **tb) -+{ -+ struct host_update_muedca { -+ u8 mu_qos_info; -+ u8 ac_be[3]; -+ u8 ac_bk[3]; -+ u8 ac_vi[3]; -+ u8 ac_vo[3]; -+ }; -+ -+ struct host_update_muedca *rx_muedca_params; -+ union wpa_event_data ed; -+ int i; -+ -+ if (!tb[NL80211_ATTR_HE_MUEDCA_PARAMS]) -+ return; -+ -+ rx_muedca_params = nla_data(tb[NL80211_ATTR_HE_MUEDCA_PARAMS]); -+ -+ for (i = 0; i< 3; i++) { -+ ed.update_muedca.he_mu_ac_be_param[i] = rx_muedca_params->ac_be[i]; -+ ed.update_muedca.he_mu_ac_bk_param[i] = rx_muedca_params->ac_bk[i]; -+ ed.update_muedca.he_mu_ac_vi_param[i] = rx_muedca_params->ac_vi[i]; -+ ed.update_muedca.he_mu_ac_vo_param[i] = rx_muedca_params->ac_vo[i]; -+ } -+ -+ wpa_supplicant_event(drv->ctx, EVENT_UPDATE_MUEDCA_PARAMS, &ed); -+} - - static void nl80211_control_port_frame(struct wpa_driver_nl80211_data *drv, - struct nlattr **tb) -@@ -2854,7 +2885,6 @@ nl80211_control_port_frame_tx_status(str - wpa_supplicant_event(drv->ctx, EVENT_EAPOL_TX_STATUS, &event); - } - -- - static void do_process_drv_event(struct i802_bss *bss, int cmd, - struct nlattr **tb) - { -@@ -3101,6 +3131,9 @@ static void do_process_drv_event(struct - tb[NL80211_ATTR_ACK], - tb[NL80211_ATTR_COOKIE]); - break; -+ case NL80211_CMD_UPDATE_HE_MUEDCA_PARAMS: -+ nl80211_update_muedca_params_event(drv, tb); -+ break; - default: - wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event " - "(cmd=%d)", cmd); ---- a/src/drivers/nl80211_copy.h -+++ b/src/drivers/nl80211_copy.h -@@ -1185,6 +1185,11 @@ - * passed using %NL80211_ATTR_SAR_SPEC. %NL80211_ATTR_WIPHY is used to - * specify the wiphy index to be applied to. - * -+ * @NL80211_CMD_UPDATE_HE_MUEDCA_PARAMS: Updated MU-EDCA parameters from driver. -+ * This event is used to update MU-EDCA parameters in Beacon frame, which -+ * were indicated by driver and now need to be reflected in -+ * Beacon frame. -+ * - * @NL80211_CMD_MAX: highest used command number - * @__NL80211_CMD_AFTER_LAST: internal use - */ -@@ -1417,6 +1422,7 @@ enum nl80211_commands { - - NL80211_CMD_SET_SAR_SPECS, - -+ NL80211_CMD_UPDATE_HE_MUEDCA_PARAMS, - /* add new commands above here */ - - /* used to define NL80211_CMD_MAX below */ -@@ -2560,6 +2566,9 @@ enum nl80211_commands { - * disassoc events to indicate that an immediate reconnect to the AP - * is desired. - * -+ * @NL80211_ATTR_HE_MUEDCA_PARAMS: MU-EDCA AC parameters for the -+ NL80211_CMD_UPDATE_HE_MUEDCA_PARAMS command. -+ * - * @NUM_NL80211_ATTR: total number of nl80211_attrs available - * @NL80211_ATTR_MAX: highest attribute number currently defined - * @__NL80211_ATTR_AFTER_LAST: internal use -@@ -3057,6 +3066,7 @@ enum nl80211_attrs { - - NL80211_ATTR_DISABLE_HE, - -+ NL80211_ATTR_HE_MUEDCA_PARAMS, - /* add attributes here, update the policy in nl80211.c */ - - __NL80211_ATTR_AFTER_LAST, ---- a/src/drivers/driver_common.c -+++ b/src/drivers/driver_common.c -@@ -90,6 +90,7 @@ const char * event_to_string(enum wpa_ev - E2S(WDS_STA_INTERFACE_STATUS); - E2S(UPDATE_DH); - E2S(UNPROT_BEACON); -+ E2S(UPDATE_MUEDCA_PARAMS); - } - - return "UNKNOWN"; ---- a/src/ap/hostapd.c -+++ b/src/ap/hostapd.c -@@ -3585,6 +3585,10 @@ static int hostapd_fill_csa_settings(str - hapd->cs_count = settings->cs_count; - hapd->cs_block_tx = settings->block_tx; - -+ /* reset MU-EDCA and WME EDCA parameter set count */ -+ hapd->iface->conf->he_mu_edca.he_qos_info &= 0xfff0; -+ hapd->parameter_set_count = 0; -+ - ret = hostapd_build_beacon_data(hapd, &settings->beacon_csa); - if (ret) { - free_beacon_data(&settings->beacon_after); ---- a/hostapd/ctrl_iface.c -+++ b/hostapd/ctrl_iface.c -@@ -1545,6 +1545,11 @@ static int hostapd_ctrl_iface_set(struct - } else if (os_strncmp(cmd, "wme_ac_", 7) == 0 || - os_strncmp(cmd, "wmm_ac_", 7) == 0) { - hapd->parameter_set_count++; -+ /* Incrementing MU-EDCA Parameter Set Update Count*/ -+ hapd->iface->conf->he_mu_edca.he_qos_info = -+ (hapd->iface->conf->he_mu_edca.he_qos_info & 0xf0) | -+ ((hapd->iface->conf->he_mu_edca.he_qos_info + 1) & -+ 0xf); - if (ieee802_11_update_beacons(hapd->iface)) - wpa_printf(MSG_DEBUG, - "Failed to update beacons with WMM parameters"); ---- a/src/ap/wmm.c -+++ b/src/ap/wmm.c -@@ -68,8 +68,8 @@ wmm_set_regulatory_limit(const struct ho - /* - * Calculate WMM regulatory limit if any. - */ --static void wmm_calc_regulatory_limit(struct hostapd_data *hapd, -- struct hostapd_wmm_ac_params *acp) -+void wmm_calc_regulatory_limit(struct hostapd_data *hapd, -+ struct hostapd_wmm_ac_params *acp) - { - struct hostapd_hw_modes *mode = hapd->iface->current_mode; - int c; -@@ -98,6 +98,10 @@ static void wmm_calc_regulatory_limit(st - os_memcpy(hapd->iface->prev_wmm, acp, - sizeof(hapd->iconf->wmm_ac_params)); - hapd->parameter_set_count++; -+ /* Incrementing MU-EDCA Parameter Set Update Count*/ -+ hapd->iface->conf->he_mu_edca.he_qos_info = -+ (hapd->iface->conf->he_mu_edca.he_qos_info & 0xf0) | -+ ((hapd->iface->conf->he_mu_edca.he_qos_info + 1) & 0xf); - } - } - ---- a/src/ap/ieee802_11_he.c -+++ b/src/ap/ieee802_11_he.c -@@ -18,6 +18,7 @@ - #include "sta_info.h" - #include "ieee802_11.h" - #include "dfs.h" -+#include "wmm.h" - - static u8 ieee80211_he_ppet_size(u8 ppe_thres_hdr, const u8 *phy_cap_info) - { -@@ -266,9 +267,16 @@ u8 * hostapd_eid_he_operation(struct hos - u8 * hostapd_eid_he_mu_edca_parameter_set(struct hostapd_data *hapd, u8 *eid) - { - struct ieee80211_he_mu_edca_parameter_set *edca; -+ struct hostapd_wmm_ac_params wmmp[WMM_AC_NUM]; - u8 *pos; - size_t i; - -+ /* Updating WME Parameter Set Count to avoid mismatch */ -+ os_memset(wmmp, 0, sizeof(wmmp)); -+ -+ if (hapd->conf->wmm_enabled) -+ wmm_calc_regulatory_limit(hapd, wmmp); -+ - pos = (u8 *) &hapd->iface->conf->he_mu_edca; - for (i = 0; i < sizeof(*edca); i++) { - if (pos[i]) ---- a/src/ap/wmm.h -+++ b/src/ap/wmm.h -@@ -13,6 +13,8 @@ - struct ieee80211_mgmt; - struct wmm_tspec_element; - -+void wmm_calc_regulatory_limit(struct hostapd_data *hapd, -+ struct hostapd_wmm_ac_params *acp); - u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid); - int hostapd_eid_wmm_valid(struct hostapd_data *hapd, const u8 *eid, - size_t len); diff --git a/feeds/ipq95xx/hostapd/patches/e00-003-hostapd-chan-switch-6ghz.patch b/feeds/ipq95xx/hostapd/patches/e00-003-hostapd-chan-switch-6ghz.patch deleted file mode 100644 index 485f313f1..000000000 --- a/feeds/ipq95xx/hostapd/patches/e00-003-hostapd-chan-switch-6ghz.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 917653b0674dfacc976e20956e999fef13c6e6ba Mon Sep 17 00:00:00 2001 -From: Muna Sinada -Date: Wed, 29 Jul 2020 09:41:31 -0700 -Subject: [PATCH] hostapd:remove 11A specific case to allow for 6 GHz - -With 6 GHz utilizing 11A/HE, frequency to channel conversions needed -to accomedate for 6 GHz frequencies in hostapd_event_ch_switch. Removed -5 GHz specific conversions for the 11A case due to incorrect 6 GHz -frequencies being incorrectly being converted in -hostapd_event_ch_switch - -Signed-off-by: Muna Sinada ---- - src/ap/drv_callbacks.c | 14 ++------------ - 1 file changed, 2 insertions(+), 12 deletions(-) - ---- a/src/ap/drv_callbacks.c -+++ b/src/ap/drv_callbacks.c -@@ -876,7 +876,7 @@ void hostapd_event_ch_switch(struct host - { - #ifdef NEED_AP_MLME - int channel, chwidth, is_dfs; -- u8 seg0_idx = 0, seg1_idx = 0; -+ u8 seg0_idx = 0, seg1_idx = 0, op_class; - size_t i; - - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, -@@ -922,27 +922,8 @@ void hostapd_event_ch_switch(struct host - break; - } - -- switch (hapd->iface->current_mode->mode) { -- case HOSTAPD_MODE_IEEE80211A: -- if (cf1 == 5935) -- seg0_idx = (cf1 - 5925) / 5; -- else if (cf1 > 5950) -- seg0_idx = (cf1 - 5950) / 5; -- else if (cf1 > 5000) -- seg0_idx = (cf1 - 5000) / 5; -- -- if (cf2 == 5935) -- seg1_idx = (cf2 - 5925) / 5; -- else if (cf2 > 5950) -- seg1_idx = (cf2 - 5950) / 5; -- else if (cf2 > 5000) -- seg1_idx = (cf2 - 5000) / 5; -- break; -- default: -- ieee80211_freq_to_chan(cf1, &seg0_idx); -- ieee80211_freq_to_chan(cf2, &seg1_idx); -- break; -- } -+ ieee80211_freq_to_channel_ext(cf1, offset, chwidth, &op_class, &seg0_idx); -+ ieee80211_freq_to_chan(cf2, &seg1_idx); - - hapd->iconf->channel = channel; - hapd->iconf->ieee80211n = ht; -@@ -977,6 +958,7 @@ void hostapd_event_ch_switch(struct host - hostapd_set_oper_chwidth(hapd->iconf, chwidth); - hostapd_set_oper_centr_freq_seg0_idx(hapd->iconf, seg0_idx); - hostapd_set_oper_centr_freq_seg1_idx(hapd->iconf, seg1_idx); -+ hapd->iconf->op_class = op_class; - if (hapd->iconf->ieee80211ac) { - hapd->iconf->vht_capab &= ~VHT_CAP_SUPP_CHAN_WIDTH_MASK; - if (chwidth == CHANWIDTH_160MHZ) diff --git a/feeds/ipq95xx/hostapd/patches/e00-014-hostapd-update-cfs0-and-cfs1-for-160MHz.patch b/feeds/ipq95xx/hostapd/patches/e00-014-hostapd-update-cfs0-and-cfs1-for-160MHz.patch deleted file mode 100644 index 9a03c58ca..000000000 --- a/feeds/ipq95xx/hostapd/patches/e00-014-hostapd-update-cfs0-and-cfs1-for-160MHz.patch +++ /dev/null @@ -1,142 +0,0 @@ -From d4c4ef302f98fd6bce173b8636e7e350d8b44981 Mon Sep 17 00:00:00 2001 -From: P Praneesh -Date: Fri, 19 Mar 2021 12:17:27 +0530 -Subject: [PATCH] hostapd: update cfs0 and cfs1 for 160MHz - -As per standard Draft P802.11ax_D8.0,( Table 26-9—Setting -of the VHT Channel Width and VHT NSS at an HE STA -transmitting the OM Control subfield ), center frequency of -160MHz should be published in HT information subset 2 of -HT information when EXT NSS BW field is enabled. - -If the supported number of NSS in 160MHz is at least max NSS -support, then center_freq_seg0 indicates the center frequency of 80MHz and -center_freq_seg1 indicates the center frequency of 160MHz. - -If the supported number of NSS in 160MHz is less than max NSS -support, then center_freq_seg0 indicates the center frequency of 80MHz and -center_freq_seg1 is 0. The center frequency of 160MHz is published in HT -operation information element instead. - -Signed-off-by: P Praneesh ---- - hostapd/config_file.c | 2 ++ - src/ap/ieee802_11_ht.c | 7 +++++++ - src/ap/ieee802_11_vht.c | 16 ++++++++++++++++ - src/common/hw_features_common.c | 1 + - src/common/ieee802_11_defs.h | 1 + - 5 files changed, 27 insertions(+) - ---- a/hostapd/config_file.c -+++ b/hostapd/config_file.c -@@ -1195,6 +1195,8 @@ static int hostapd_config_vht_capab(stru - conf->vht_capab |= VHT_CAP_RX_ANTENNA_PATTERN; - if (os_strstr(capab, "[TX-ANTENNA-PATTERN]")) - conf->vht_capab |= VHT_CAP_TX_ANTENNA_PATTERN; -+ if (os_strstr(capab, "[EXT-NSS-BW-SUPP]")) -+ conf->vht_capab |= VHT_CAP_EXTENDED_NSS_BW_SUPPORT; - return 0; - } - #endif /* CONFIG_IEEE80211AC */ ---- a/src/ap/ieee802_11_ht.c -+++ b/src/ap/ieee802_11_ht.c -@@ -82,7 +82,9 @@ u8 * hostapd_eid_ht_capabilities(struct - u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid) - { - struct ieee80211_ht_operation *oper; -+ le32 vht_capabilities_info; - u8 *pos = eid; -+ u8 chwidth; - - if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n || - is_6ghz_op_class(hapd->iconf->op_class)) -@@ -103,6 +105,13 @@ u8 * hostapd_eid_ht_operation(struct hos - oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW | - HT_INFO_HT_PARAM_STA_CHNL_WIDTH; - -+ vht_capabilities_info = host_to_le32(hapd->iface->current_mode->vht_capab); -+ chwidth = hostapd_get_oper_chwidth(hapd->iconf); -+ if (vht_capabilities_info & VHT_CAP_EXTENDED_NSS_BW_SUPPORT -+ && ((chwidth == CHANWIDTH_160MHZ) || (chwidth == CHANWIDTH_80P80MHZ))) { -+ oper->operation_mode = host_to_le16(hapd->iconf->vht_oper_centr_freq_seg0_idx << 5); -+ } -+ - pos += sizeof(*oper); - - return pos; ---- a/src/ap/ieee802_11_vht.c -+++ b/src/ap/ieee802_11_vht.c -@@ -25,6 +25,7 @@ u8 * hostapd_eid_vht_capabilities(struct - struct ieee80211_vht_capabilities *cap; - struct hostapd_hw_modes *mode = hapd->iface->current_mode; - u8 *pos = eid; -+ u8 chwidth; - - if (!mode || is_6ghz_op_class(hapd->iconf->op_class)) - return eid; -@@ -62,6 +63,17 @@ u8 * hostapd_eid_vht_capabilities(struct - host_to_le32(nsts << VHT_CAP_BEAMFORMEE_STS_OFFSET); - } - -+ chwidth = hostapd_get_oper_chwidth(hapd->iconf); -+ if (((host_to_le32(mode->vht_capab)) & VHT_CAP_EXTENDED_NSS_BW_SUPPORT) -+ && ((chwidth == CHANWIDTH_160MHZ) || (chwidth == CHANWIDTH_80P80MHZ))) { -+ cap->vht_capabilities_info |= VHT_CAP_EXTENDED_NSS_BW_SUPPORT; -+ cap->vht_capabilities_info &= ~(host_to_le32(VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)); -+ cap->vht_capabilities_info &= ~(host_to_le32(VHT_CAP_SUPP_CHAN_WIDTH_160MHZ)); -+ cap->vht_capabilities_info &= ~(host_to_le32(VHT_CAP_SUPP_CHAN_WIDTH_MASK)); -+ } else { -+ cap->vht_capabilities_info &= ~VHT_CAP_EXTENDED_NSS_BW_SUPPORT_MASK; -+ } -+ - /* Supported MCS set comes from hw */ - os_memcpy(&cap->vht_supported_mcs_set, mode->vht_mcs_set, 8); - -@@ -74,6 +86,7 @@ u8 * hostapd_eid_vht_capabilities(struct - u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid) - { - struct ieee80211_vht_operation *oper; -+ le32 vht_capabilities_info; - u8 *pos = eid; - - if (is_6ghz_op_class(hapd->iconf->op_class)) -@@ -96,6 +109,7 @@ u8 * hostapd_eid_vht_operation(struct ho - hapd->iconf->vht_oper_centr_freq_seg1_idx; - - oper->vht_op_info_chwidth = hapd->iconf->vht_oper_chwidth; -+ vht_capabilities_info = host_to_le32(hapd->iface->current_mode->vht_capab); - if (hapd->iconf->vht_oper_chwidth == 2) { - /* - * Convert 160 MHz channel width to new style as interop -@@ -109,6 +123,10 @@ u8 * hostapd_eid_vht_operation(struct ho - oper->vht_op_info_chan_center_freq_seg0_idx -= 8; - else - oper->vht_op_info_chan_center_freq_seg0_idx += 8; -+ -+ if (vht_capabilities_info & VHT_CAP_EXTENDED_NSS_BW_SUPPORT) -+ oper->vht_op_info_chan_center_freq_seg1_idx = 0; -+ - } else if (hapd->iconf->vht_oper_chwidth == 3) { - /* - * Convert 80+80 MHz channel width to new style as interop ---- a/src/common/hw_features_common.c -+++ b/src/common/hw_features_common.c -@@ -740,6 +740,7 @@ int ieee80211ac_cap_check(u32 hw, u32 co - VHT_CAP_CHECK(VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB); - VHT_CAP_CHECK(VHT_CAP_RX_ANTENNA_PATTERN); - VHT_CAP_CHECK(VHT_CAP_TX_ANTENNA_PATTERN); -+ VHT_CAP_CHECK(VHT_CAP_EXTENDED_NSS_BW_SUPPORT); - - #undef VHT_CAP_CHECK - #undef VHT_CAP_CHECK_MAX ---- a/src/common/ieee802_11_defs.h -+++ b/src/common/ieee802_11_defs.h -@@ -1304,6 +1304,8 @@ struct ieee80211_ampe_ie { - #define VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB ((u32) BIT(26) | BIT(27)) - #define VHT_CAP_RX_ANTENNA_PATTERN ((u32) BIT(28)) - #define VHT_CAP_TX_ANTENNA_PATTERN ((u32) BIT(29)) -+#define VHT_CAP_EXTENDED_NSS_BW_SUPPORT ((u32) BIT(30)) -+#define VHT_CAP_EXTENDED_NSS_BW_SUPPORT_MASK ((u32) BIT(30) | BIT(31)) - - #define VHT_OPMODE_CHANNEL_WIDTH_MASK ((u8) BIT(0) | BIT(1)) - #define VHT_OPMODE_CHANNEL_RxNSS_MASK ((u8) BIT(4) | BIT(5) | \ diff --git a/feeds/ipq95xx/hostapd/patches/f00-001-bss-coloring-add-support-for-handling-collision-events-and-triggering-CCA.patch b/feeds/ipq95xx/hostapd/patches/f00-001-bss-coloring-add-support-for-handling-collision-events-and-triggering-CCA.patch deleted file mode 100644 index eca545977..000000000 --- a/feeds/ipq95xx/hostapd/patches/f00-001-bss-coloring-add-support-for-handling-collision-events-and-triggering-CCA.patch +++ /dev/null @@ -1,278 +0,0 @@ -From: John Crispin -Subject: [PATCH V4 1/6] bss coloring: add support for handling collision - events and triggering CCA -Date: Wed, 26 Aug 2020 08:22:11 +0200 - -Add the core code for handling bss color collision events and triggering -CCA inside the kernel. - -Signed-off-by: John Crispin ---- - src/ap/ap_drv_ops.h | 12 ++++ - src/ap/hostapd.c | 119 +++++++++++++++++++++++++++++++++++ - src/ap/hostapd.h | 16 +++++ - src/common/ieee802_11_defs.h | 6 ++ - src/drivers/driver.h | 31 +++++++++ - 5 files changed, 184 insertions(+) - ---- a/src/ap/ap_drv_ops.h -+++ b/src/ap/ap_drv_ops.h -@@ -299,6 +299,18 @@ static inline int hostapd_drv_switch_cha - return hapd->driver->switch_channel(hapd->drv_priv, settings); - } - -+#ifdef CONFIG_IEEE80211AX -+static inline int hostapd_drv_switch_color(struct hostapd_data *hapd, -+ struct cca_settings *settings) -+{ -+ if (hapd->driver == NULL || hapd->driver->switch_color == NULL || -+ hapd->drv_priv == NULL) -+ return -1; -+ -+ return hapd->driver->switch_color(hapd->drv_priv, settings); -+} -+#endif -+ - static inline int hostapd_drv_status(struct hostapd_data *hapd, char *buf, - size_t buflen) - { ---- a/src/ap/hostapd.c -+++ b/src/ap/hostapd.c -@@ -65,6 +65,8 @@ static int setup_interface2(struct hosta - static void channel_list_update_timeout(void *eloop_ctx, void *timeout_ctx); - static void hostapd_interface_setup_failure_handler(void *eloop_ctx, - void *timeout_ctx); -+static void -+hostapd_switch_color_timeout_handler(void *eloop_data, void *user_ctx); - - - int hostapd_for_each_interface(struct hapd_interfaces *interfaces, -@@ -476,6 +478,9 @@ static void hostapd_free_hapd_data(struc - } - eloop_cancel_timeout(auth_sae_process_commit, hapd, NULL); - #endif /* CONFIG_SAE */ -+#ifdef CONFIG_IEEE80211AX -+ eloop_cancel_timeout(hostapd_switch_color_timeout_handler, hapd, NULL); -+#endif - } - - -@@ -3713,6 +3718,119 @@ hostapd_switch_channel_fallback(struct h - hostapd_enable_iface(iface); - } - -+ -+#ifdef CONFIG_IEEE80211AX -+void hostapd_cleanup_cca_params(struct hostapd_data *hapd) -+{ -+ hapd->cca_count = 0; -+ hapd->cca_color = 0; -+ hapd->cca_c_off_beacon = 0; -+ hapd->cca_c_off_proberesp = 0; -+ hapd->cca_in_progress = 0; -+} -+ -+ -+static int hostapd_fill_cca_settings(struct hostapd_data *hapd, -+ struct cca_settings *settings) -+{ -+ struct hostapd_iface *iface = hapd->iface; -+ u8 old_color; -+ int ret; -+ -+ if (!iface || iface->conf->he_op.he_bss_color_disabled) -+ return -1; -+ -+ old_color = iface->conf->he_op.he_bss_color; -+ iface->conf->he_op.he_bss_color = hapd->cca_color; -+ ret = hostapd_build_beacon_data(hapd, &settings->beacon_after); -+ iface->conf->he_op.he_bss_color = old_color; -+ -+ settings->cca_count = hapd->cca_count; -+ settings->cca_color = hapd->cca_color, -+ hapd->cca_in_progress = 1; -+ -+ ret = hostapd_build_beacon_data(hapd, &settings->beacon_cca); -+ if (ret) { -+ free_beacon_data(&settings->beacon_after); -+ return ret; -+ } -+ -+ settings->counter_offset_beacon = hapd->cca_c_off_beacon; -+ settings->counter_offset_presp = hapd->cca_c_off_proberesp; -+ -+ return 0; -+} -+ -+ -+static void -+hostapd_switch_color_timeout_handler(void *eloop_data, void *user_ctx) -+{ -+ struct hostapd_data *hapd = (struct hostapd_data *) eloop_data; -+ struct cca_settings settings; -+ struct os_time now; -+ int i, r, b, ret; -+ -+ if (os_get_time(&now)) -+ return; -+ -+ /* check if there has been a recent collision */ -+ if (now.sec - hapd->last_color_collision.sec > 50) -+ return; -+ -+ r = os_random() % HE_OPERATION_BSS_COLOR_MAX; -+ for (i = 0; i < HE_OPERATION_BSS_COLOR_MAX; i++) { -+ if (r && (hapd->color_collision_bitmap & (1 << r)) == 0) -+ break; -+ r = (r + 1) % HE_OPERATION_BSS_COLOR_MAX; -+ } -+ if (i == HE_OPERATION_BSS_COLOR_MAX) { -+ /* there are no free colors so turn bss coloring off */ -+ wpa_printf(MSG_INFO, "no free colors left, turning of BSS coloring"); -+ hapd->iface->conf->he_op.he_bss_color_disabled = 1; -+ for (b = 0; b < hapd->iface->num_bss; b++) -+ ieee802_11_set_beacon(hapd->iface->bss[b]); -+ return; -+ } -+ -+ for (b = 0; b < hapd->iface->num_bss; b++) { -+ struct hostapd_data *bss = hapd->iface->bss[b]; -+ -+ hostapd_cleanup_cca_params(bss); -+ bss->cca_color = r; -+ bss->cca_count = 10; -+ -+ if (hostapd_fill_cca_settings(bss, &settings)) { -+ hostapd_cleanup_cca_params(bss); -+ continue; -+ } -+ -+ ret = hostapd_drv_switch_color(bss, &settings); -+ free_beacon_data(&settings.beacon_cca); -+ free_beacon_data(&settings.beacon_after); -+ -+ if (ret) -+ hostapd_cleanup_cca_params(bss); -+ } -+} -+ -+ -+void -+hostapd_switch_color(struct hostapd_data *hapd, u64 bitmap) -+{ -+ if (hapd->cca_in_progress) -+ return; -+ -+ if (os_get_time(&hapd->last_color_collision)) -+ return; -+ -+ hapd->color_collision_bitmap = bitmap; -+ -+ if (!eloop_is_timeout_registered(hostapd_switch_color_timeout_handler, hapd, NULL)) -+ eloop_register_timeout(DOT11BSS_COLOR_COLLISION_AP_PERIOD, 0, -+ hostapd_switch_color_timeout_handler, hapd, NULL); -+} -+#endif -+ - #endif /* NEED_AP_MLME */ - - ---- a/src/ap/hostapd.h -+++ b/src/ap/hostapd.h -@@ -296,6 +296,16 @@ struct hostapd_data { - unsigned int cs_c_off_ecsa_beacon; - unsigned int cs_c_off_ecsa_proberesp; - -+#ifdef CONFIG_IEEE80211AX -+ int cca_in_progress; -+ u8 cca_count; -+ u8 cca_color; -+ unsigned int cca_c_off_beacon; -+ unsigned int cca_c_off_proberesp; -+ struct os_time last_color_collision; -+ u64 color_collision_bitmap; -+#endif -+ - #ifdef CONFIG_P2P - struct p2p_data *p2p; - struct p2p_group *p2p_group; -@@ -642,6 +652,12 @@ void hostapd_periodic_iface(struct hosta - int hostapd_owe_trans_get_info(struct hostapd_data *hapd); - void hostapd_ocv_check_csa_sa_query(void *eloop_ctx, void *timeout_ctx); - -+ -+#ifdef CONFIG_IEEE80211AX -+void hostapd_switch_color(struct hostapd_data *hapd, u64 bitmap); -+void hostapd_cleanup_cca_params(struct hostapd_data *hapd); -+#endif -+ - /* utils.c */ - int hostapd_register_probereq_cb(struct hostapd_data *hapd, - int (*cb)(void *ctx, const u8 *sa, ---- a/src/common/ieee802_11_defs.h -+++ b/src/common/ieee802_11_defs.h -@@ -2280,6 +2280,7 @@ struct ieee80211_spatial_reuse { - #define HE_OPERATION_BSS_COLOR_PARTIAL ((u32) BIT(30)) - #define HE_OPERATION_BSS_COLOR_DISABLED ((u32) BIT(31)) - #define HE_OPERATION_BSS_COLOR_OFFSET 24 -+#define HE_OPERATION_BSS_COLOR_MAX 64 - - /* Spatial Reuse defines */ - #define SPATIAL_REUSE_SRP_DISALLOWED BIT(0) -@@ -2430,4 +2431,9 @@ enum mscs_description_subelem { - #define TBTT_BSS_PARAM_CO_LOCATED BIT(6) - #define TBTT_PSD_MAX_TXPOWER 255 /* dBm */ - -+/* IEEE802.11/D6.0 - 26.17.3.5.1 -+ * the minimum default timeout between color collision and color change is defined as 50s -+ */ -+#define DOT11BSS_COLOR_COLLISION_AP_PERIOD 50 -+ - #endif /* IEEE802_11_DEFS_H */ ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -2417,6 +2417,26 @@ struct csa_settings { - u16 counter_offset_presp[2]; - }; - -+/** -+ * struct cca_settings - Settings for color switch command -+ * @cca_count: Count in Beacon frames (TBTT) to perform the switch -+ * @cca_color: The new color that we are switching to -+ * @beacon_cca: Beacon/probe resp/asooc resp info for color switch period -+ * @beacon_after: Next beacon/probe resp/asooc resp info -+ * @counter_offset_beacon: Offset to the count field in beacon's tail -+ * @counter_offset_presp: Offset to the count field in probe resp. -+ */ -+struct cca_settings { -+ u8 cca_count; -+ u8 cca_color; -+ -+ struct beacon_data beacon_cca; -+ struct beacon_data beacon_after; -+ -+ u16 counter_offset_beacon; -+ u16 counter_offset_presp; -+}; -+ - /* TDLS peer capabilities for send_tdls_mgmt() */ - enum tdls_peer_capability { - TDLS_PEER_HT = BIT(0), -@@ -3989,6 +4009,17 @@ struct wpa_driver_ops { - int (*switch_channel)(void *priv, struct csa_settings *settings); - - /** -+ * switch_color - Announce color switch and migrate the BSS to the -+ * given color -+ * @priv: Private driver interface data -+ * @settings: Settings for CCA period and new color -+ * Returns: 0 on success, -1 on failure -+ * -+ * This function is used to move the BSS to its new color. -+ */ -+ int (*switch_color)(void *priv, struct cca_settings *settings); -+ -+ /** - * add_tx_ts - Add traffic stream - * @priv: Private driver interface data - * @tsid: Traffic stream ID diff --git a/feeds/ipq95xx/hostapd/patches/f00-002-bss_coloring-add-the-code-required-to-generate-the-CCA-IE.patch b/feeds/ipq95xx/hostapd/patches/f00-002-bss_coloring-add-the-code-required-to-generate-the-CCA-IE.patch deleted file mode 100644 index 1075b9141..000000000 --- a/feeds/ipq95xx/hostapd/patches/f00-002-bss_coloring-add-the-code-required-to-generate-the-CCA-IE.patch +++ /dev/null @@ -1,104 +0,0 @@ -From: John Crispin -Subject: [PATCH V4 2/6] bss_coloring: add the code required to generate the - CCA IE -Date: Wed, 26 Aug 2020 08:22:12 +0200 - - -This IE is similar to the CSA one. It contains a counter and the target -color. Once the counter expired, the change to the new color happens. - -Signed-off-by: John Crispin ---- - src/ap/beacon.c | 12 ++++++++++++ - src/ap/ieee802_11.h | 1 + - src/ap/ieee802_11_he.c | 14 ++++++++++++++ - src/common/ieee802_11_defs.h | 1 + - 4 files changed, 28 insertions(+) - -Index: hostapd-2021-02-08/src/ap/beacon.c -=================================================================== ---- hostapd-2021-02-08.orig/src/ap/beacon.c -+++ hostapd-2021-02-08/src/ap/beacon.c -@@ -592,11 +592,17 @@ static u8 * hostapd_gen_probe_resp(struc - - #ifdef CONFIG_IEEE80211AX - if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) { -+ u8 *cca_pos; -+ - pos = hostapd_eid_he_capab(hapd, pos, IEEE80211_MODE_AP); - pos = hostapd_eid_he_operation(hapd, pos); - pos = hostapd_eid_spatial_reuse(hapd, pos); - pos = hostapd_eid_he_mu_edca_parameter_set(hapd, pos); - pos = hostapd_eid_he_6ghz_band_cap(hapd, pos); -+ cca_pos = hostapd_eid_cca(hapd, pos); -+ if (cca_pos != pos) -+ hapd->cca_c_off_proberesp = cca_pos - (u8 *) resp - 2; -+ pos = cca_pos; - } - #endif /* CONFIG_IEEE80211AX */ - -@@ -1646,12 +1652,18 @@ int ieee802_11_build_ap_params(struct ho - - #ifdef CONFIG_IEEE80211AX - if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) { -+ u8 *cca_pos; -+ - tailpos = hostapd_eid_he_capab(hapd, tailpos, - IEEE80211_MODE_AP); - tailpos = hostapd_eid_he_operation(hapd, tailpos); - tailpos = hostapd_eid_spatial_reuse(hapd, tailpos); - tailpos = hostapd_eid_he_mu_edca_parameter_set(hapd, tailpos); - tailpos = hostapd_eid_he_6ghz_band_cap(hapd, tailpos); -+ cca_pos = hostapd_eid_cca(hapd, tailpos); -+ if (cca_pos != tailpos) -+ hapd->cca_c_off_beacon = cca_pos - tail - 2; -+ tailpos = cca_pos; - } - #endif /* CONFIG_IEEE80211AX */ - -Index: hostapd-2021-02-08/src/ap/ieee802_11.h -=================================================================== ---- hostapd-2021-02-08.orig/src/ap/ieee802_11.h -+++ hostapd-2021-02-08/src/ap/ieee802_11.h -@@ -100,6 +100,7 @@ u16 copy_sta_he_6ghz_capab(struct hostap - const u8 *he_6ghz_capab); - int hostapd_get_he_twt_responder(struct hostapd_data *hapd, - enum ieee80211_op_mode mode); -+u8 * hostapd_eid_cca(struct hostapd_data *hapd, u8 *eid); - void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr, - const u8 *buf, size_t len, int ack); - void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst, -Index: hostapd-2021-02-08/src/ap/ieee802_11_he.c -=================================================================== ---- hostapd-2021-02-08.orig/src/ap/ieee802_11_he.c -+++ hostapd-2021-02-08/src/ap/ieee802_11_he.c -@@ -521,3 +521,17 @@ int hostapd_get_he_twt_responder(struct - - return !!(mac_cap[HE_MAC_CAPAB_0] & HE_MACCAP_TWT_RESPONDER); - } -+ -+ -+u8 * hostapd_eid_cca(struct hostapd_data *hapd, u8 *eid) -+{ -+ if (!hapd->cca_in_progress) -+ return eid; -+ *eid++ = WLAN_EID_EXTENSION; -+ *eid++ = 3; -+ *eid++ = WLAN_EID_EXT_COLOR_CHANGE_ANNOUNCEMENT; -+ *eid++ = hapd->cca_count; -+ *eid++ = hapd->cca_color; -+ -+ return eid; -+} -Index: hostapd-2021-02-08/src/common/ieee802_11_defs.h -=================================================================== ---- hostapd-2021-02-08.orig/src/common/ieee802_11_defs.h -+++ hostapd-2021-02-08/src/common/ieee802_11_defs.h -@@ -480,6 +480,7 @@ - #define WLAN_EID_EXT_HE_OPERATION 36 - #define WLAN_EID_EXT_HE_MU_EDCA_PARAMS 38 - #define WLAN_EID_EXT_SPATIAL_REUSE 39 -+#define WLAN_EID_EXT_COLOR_CHANGE_ANNOUNCEMENT 42 - #define WLAN_EID_EXT_OCV_OCI 54 - #define WLAN_EID_EXT_SHORT_SSID_LIST 58 - #define WLAN_EID_EXT_HE_6GHZ_BAND_CAP 59 diff --git a/feeds/ipq95xx/hostapd/patches/f00-002-hostap-Move-acl-related-code-to-generic-to-be-used-for-mesh.patch b/feeds/ipq95xx/hostapd/patches/f00-002-hostap-Move-acl-related-code-to-generic-to-be-used-for-mesh.patch deleted file mode 100644 index 4f160f28d..000000000 --- a/feeds/ipq95xx/hostapd/patches/f00-002-hostap-Move-acl-related-code-to-generic-to-be-used-for-mesh.patch +++ /dev/null @@ -1,603 +0,0 @@ -From 171c96df407c45e94d1fe8afd44ca6cc3a191157 Mon Sep 17 00:00:00 2001 -From: Nishant Pandey -Date: Tue, 22 Sep 2020 14:15:36 +0530 -Subject: [PATCH] hostap: Move ACL configuration callback to generic - -Move ACL configuration support callbacks to generic -place so that it can be utilized for mesh functionality. -No functional change as such made in this patch - -Signed-off-by: Nishant Pandey ---- - hostapd/config_file.c | 119 +----------------------------------- - hostapd/config_file.h | 5 -- - hostapd/ctrl_iface.c | 111 ---------------------------------- - src/ap/ctrl_iface_ap.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++++ - src/ap/ctrl_iface_ap.h | 10 ++++ - src/ap/ieee802_11.c | 81 +++++++++++++++++++++++++ - src/ap/ieee802_11.h | 9 +++ - 7 files changed, 260 insertions(+), 234 deletions(-) - ---- a/hostapd/config_file.c -+++ b/hostapd/config_file.c -@@ -23,6 +23,7 @@ - #include "radius/radius_client.h" - #include "ap/wpa_auth.h" - #include "ap/ap_config.h" -+#include "ap/ieee802_11.h" - #include "config_file.h" - - -@@ -118,124 +119,6 @@ static int hostapd_config_read_vlan_file - #endif /* CONFIG_NO_VLAN */ - - --int hostapd_acl_comp(const void *a, const void *b) --{ -- const struct mac_acl_entry *aa = a; -- const struct mac_acl_entry *bb = b; -- return os_memcmp(aa->addr, bb->addr, sizeof(macaddr)); --} -- -- --int hostapd_add_acl_maclist(struct mac_acl_entry **acl, int *num, -- int vlan_id, const u8 *addr) --{ -- struct mac_acl_entry *newacl; -- -- newacl = os_realloc_array(*acl, *num + 1, sizeof(**acl)); -- if (!newacl) { -- wpa_printf(MSG_ERROR, "MAC list reallocation failed"); -- return -1; -- } -- -- *acl = newacl; -- os_memcpy((*acl)[*num].addr, addr, ETH_ALEN); -- os_memset(&(*acl)[*num].vlan_id, 0, sizeof((*acl)[*num].vlan_id)); -- (*acl)[*num].vlan_id.untagged = vlan_id; -- (*acl)[*num].vlan_id.notempty = !!vlan_id; -- (*num)++; -- -- return 0; --} -- -- --void hostapd_remove_acl_mac(struct mac_acl_entry **acl, int *num, -- const u8 *addr) --{ -- int i = 0; -- -- while (i < *num) { -- if (os_memcmp((*acl)[i].addr, addr, ETH_ALEN) == 0) { -- os_remove_in_array(*acl, *num, sizeof(**acl), i); -- (*num)--; -- } else { -- i++; -- } -- } --} -- -- --static int hostapd_config_read_maclist(const char *fname, -- struct mac_acl_entry **acl, int *num) --{ -- FILE *f; -- char buf[128], *pos; -- int line = 0; -- u8 addr[ETH_ALEN]; -- int vlan_id; -- -- f = fopen(fname, "r"); -- if (!f) { -- wpa_printf(MSG_ERROR, "MAC list file '%s' not found.", fname); -- return -1; -- } -- -- while (fgets(buf, sizeof(buf), f)) { -- int rem = 0; -- -- line++; -- -- if (buf[0] == '#') -- continue; -- pos = buf; -- while (*pos != '\0') { -- if (*pos == '\n') { -- *pos = '\0'; -- break; -- } -- pos++; -- } -- if (buf[0] == '\0') -- continue; -- pos = buf; -- if (buf[0] == '-') { -- rem = 1; -- pos++; -- } -- -- if (hwaddr_aton(pos, addr)) { -- wpa_printf(MSG_ERROR, "Invalid MAC address '%s' at " -- "line %d in '%s'", pos, line, fname); -- fclose(f); -- return -1; -- } -- -- if (rem) { -- hostapd_remove_acl_mac(acl, num, addr); -- continue; -- } -- vlan_id = 0; -- pos = buf; -- while (*pos != '\0' && *pos != ' ' && *pos != '\t') -- pos++; -- while (*pos == ' ' || *pos == '\t') -- pos++; -- if (*pos != '\0') -- vlan_id = atoi(pos); -- -- if (hostapd_add_acl_maclist(acl, num, vlan_id, addr) < 0) { -- fclose(f); -- return -1; -- } -- } -- -- fclose(f); -- -- if (*acl) -- qsort(*acl, *num, sizeof(**acl), hostapd_acl_comp); -- -- return 0; --} -- - - #ifdef EAP_SERVER - ---- a/hostapd/config_file.h -+++ b/hostapd/config_file.h -@@ -13,10 +13,5 @@ struct hostapd_config * hostapd_config_r - int hostapd_set_iface(struct hostapd_config *conf, - struct hostapd_bss_config *bss, const char *field, - char *value); --int hostapd_acl_comp(const void *a, const void *b); --int hostapd_add_acl_maclist(struct mac_acl_entry **acl, int *num, -- int vlan_id, const u8 *addr); --void hostapd_remove_acl_mac(struct mac_acl_entry **acl, int *num, -- const u8 *addr); - - #endif /* CONFIG_FILE_H */ ---- a/hostapd/ctrl_iface.c -+++ b/hostapd/ctrl_iface.c -@@ -1363,42 +1363,6 @@ static int hostapd_ctrl_iface_get_config - } - - --static void hostapd_disassoc_accept_mac(struct hostapd_data *hapd) --{ -- struct sta_info *sta; -- struct vlan_description vlan_id; -- -- if (hapd->conf->macaddr_acl != DENY_UNLESS_ACCEPTED) -- return; -- -- for (sta = hapd->sta_list; sta; sta = sta->next) { -- if (!hostapd_maclist_found(hapd->conf->accept_mac, -- hapd->conf->num_accept_mac, -- sta->addr, &vlan_id) || -- (vlan_id.notempty && -- vlan_compare(&vlan_id, sta->vlan_desc))) -- ap_sta_disconnect(hapd, sta, sta->addr, -- WLAN_REASON_UNSPECIFIED); -- } --} -- -- --static void hostapd_disassoc_deny_mac(struct hostapd_data *hapd) --{ -- struct sta_info *sta; -- struct vlan_description vlan_id; -- -- for (sta = hapd->sta_list; sta; sta = sta->next) { -- if (hostapd_maclist_found(hapd->conf->deny_mac, -- hapd->conf->num_deny_mac, sta->addr, -- &vlan_id) && -- (!vlan_id.notempty || -- !vlan_compare(&vlan_id, sta->vlan_desc))) -- ap_sta_disconnect(hapd, sta, sta->addr, -- WLAN_REASON_UNSPECIFIED); -- } --} -- - - static int hostapd_ctrl_iface_set_band(struct hostapd_data *hapd, - const char *bands) -@@ -3470,81 +3434,6 @@ static int hostapd_ctrl_driver_flags2(st - return pos - buf; - } - -- --static int hostapd_ctrl_iface_acl_del_mac(struct mac_acl_entry **acl, int *num, -- const char *txtaddr) --{ -- u8 addr[ETH_ALEN]; -- struct vlan_description vlan_id; -- -- if (!(*num)) -- return 0; -- -- if (hwaddr_aton(txtaddr, addr)) -- return -1; -- -- if (hostapd_maclist_found(*acl, *num, addr, &vlan_id)) -- hostapd_remove_acl_mac(acl, num, addr); -- -- return 0; --} -- -- --static void hostapd_ctrl_iface_acl_clear_list(struct mac_acl_entry **acl, -- int *num) --{ -- while (*num) -- hostapd_remove_acl_mac(acl, num, (*acl)[0].addr); --} -- -- --static int hostapd_ctrl_iface_acl_show_mac(struct mac_acl_entry *acl, int num, -- char *buf, size_t buflen) --{ -- int i = 0, len = 0, ret = 0; -- -- if (!acl) -- return 0; -- -- while (i < num) { -- ret = os_snprintf(buf + len, buflen - len, -- MACSTR " VLAN_ID=%d\n", -- MAC2STR(acl[i].addr), -- acl[i].vlan_id.untagged); -- if (ret < 0 || (size_t) ret >= buflen - len) -- return len; -- i++; -- len += ret; -- } -- return len; --} -- -- --static int hostapd_ctrl_iface_acl_add_mac(struct mac_acl_entry **acl, int *num, -- const char *cmd) --{ -- u8 addr[ETH_ALEN]; -- struct vlan_description vlan_id; -- int ret = 0, vlanid = 0; -- const char *pos; -- -- if (hwaddr_aton(cmd, addr)) -- return -1; -- -- pos = os_strstr(cmd, "VLAN_ID="); -- if (pos) -- vlanid = atoi(pos + 8); -- -- if (!hostapd_maclist_found(*acl, *num, addr, &vlan_id)) { -- ret = hostapd_add_acl_maclist(acl, num, vlanid, addr); -- if (ret != -1 && *acl) -- qsort(*acl, *num, sizeof(**acl), hostapd_acl_comp); -- } -- -- return ret < 0 ? -1 : 0; --} -- -- - static int hostapd_ctrl_iface_get_capability(struct hostapd_data *hapd, - const char *field, char *buf, - size_t buflen) ---- a/src/ap/ctrl_iface_ap.c -+++ b/src/ap/ctrl_iface_ap.c -@@ -24,6 +24,7 @@ - #include "ap_drv_ops.h" - #include "mbo_ap.h" - #include "taxonomy.h" -+#include "ap/vlan.h" - - #ifdef CONFIG_CTRL_IFACE_MIB - -@@ -645,6 +646,164 @@ static int p2p_manager_disconnect(struct - #endif /* CONFIG_P2P_MANAGER */ - - -+int hostapd_add_acl_maclist(struct mac_acl_entry **acl, int *num, -+ int vlan_id, const u8 *addr) -+{ -+ struct mac_acl_entry *newacl; -+ -+ newacl = os_realloc_array(*acl, *num + 1, sizeof(**acl)); -+ if (!newacl) { -+ wpa_printf(MSG_ERROR, "MAC list reallocation failed"); -+ return -1; -+ } -+ -+ *acl = newacl; -+ os_memcpy((*acl)[*num].addr, addr, ETH_ALEN); -+ os_memset(&(*acl)[*num].vlan_id, 0, sizeof((*acl)[*num].vlan_id)); -+ (*acl)[*num].vlan_id.untagged = vlan_id; -+ (*acl)[*num].vlan_id.notempty = !!vlan_id; -+ (*num)++; -+ -+ return 0; -+} -+ -+ -+void hostapd_remove_acl_mac(struct mac_acl_entry **acl, int *num, -+ const u8 *addr) -+{ -+ int i = 0; -+ -+ while (i < *num) { -+ if (os_memcmp((*acl)[i].addr, addr, ETH_ALEN) == 0) { -+ os_remove_in_array(*acl, *num, sizeof(**acl), i); -+ (*num)--; -+ } else { -+ i++; -+ } -+ } -+} -+ -+int hostapd_disassoc_accept_mac(struct hostapd_data *hapd) -+{ -+ struct sta_info *sta; -+ struct vlan_description vlan_id; -+ -+ if (hapd->conf->macaddr_acl != DENY_UNLESS_ACCEPTED) -+ return 0; -+ -+ for (sta = hapd->sta_list; sta; sta = sta->next) { -+ if (!hostapd_maclist_found(hapd->conf->accept_mac, -+ hapd->conf->num_accept_mac, -+ sta->addr, &vlan_id) || -+ (vlan_id.notempty && -+ vlan_compare(&vlan_id, sta->vlan_desc))) { -+#ifdef CONFIG_MESH -+ if (hapd->iface->mconf) -+ return 1; -+#endif /* CONFIG_MESH */ -+ ap_sta_disconnect(hapd, sta, sta->addr, -+ WLAN_REASON_UNSPECIFIED); -+ } -+ } -+ return 0; -+} -+ -+int hostapd_disassoc_deny_mac(struct hostapd_data *hapd) -+{ -+ struct sta_info *sta; -+ struct vlan_description vlan_id; -+ -+ for (sta = hapd->sta_list; sta; sta = sta->next) { -+ if (hostapd_maclist_found(hapd->conf->deny_mac, -+ hapd->conf->num_deny_mac, sta->addr, -+ &vlan_id) && -+ (!vlan_id.notempty || -+ !vlan_compare(&vlan_id, sta->vlan_desc))) { -+#ifdef CONFIG_MESH -+ if (hapd->iface->mconf) -+ return 1; -+#endif /* CONFIG_MESH */ -+ ap_sta_disconnect(hapd, sta, sta->addr, -+ WLAN_REASON_UNSPECIFIED); -+ } -+ } -+ -+ return 0; -+} -+ -+int hostapd_ctrl_iface_acl_del_mac(struct mac_acl_entry **acl, int *num, -+ const char *txtaddr) -+{ -+ u8 addr[ETH_ALEN]; -+ struct vlan_description vlan_id; -+ -+ if (!(*num)) -+ return 0; -+ -+ if (hwaddr_aton(txtaddr, addr)) -+ return -1; -+ -+ if (hostapd_maclist_found(*acl, *num, addr, &vlan_id)) -+ hostapd_remove_acl_mac(acl, num, addr); -+ -+ return 0; -+} -+ -+ -+void hostapd_ctrl_iface_acl_clear_list(struct mac_acl_entry **acl, -+ int *num) -+{ -+ while (*num) -+ hostapd_remove_acl_mac(acl, num, (*acl)[0].addr); -+} -+ -+ -+int hostapd_ctrl_iface_acl_show_mac(struct mac_acl_entry *acl, int num, -+ char *buf, size_t buflen) -+{ -+ int i = 0, len = 0, ret = 0; -+ -+ if (!acl) -+ return 0; -+ -+ while (i < num) { -+ ret = os_snprintf(buf + len, buflen - len, -+ MACSTR " VLAN_ID=%d\n", -+ MAC2STR(acl[i].addr), -+ acl[i].vlan_id.untagged); -+ if (ret < 0 || (size_t) ret >= buflen - len) -+ return len; -+ i++; -+ len += ret; -+ } -+ return len; -+} -+ -+ -+int hostapd_ctrl_iface_acl_add_mac(struct mac_acl_entry **acl, int *num, -+ const char *cmd) -+{ -+ u8 addr[ETH_ALEN]; -+ struct vlan_description vlan_id; -+ int ret = 0, vlanid = 0; -+ const char *pos; -+ -+ if (hwaddr_aton(cmd, addr)) -+ return -1; -+ -+ pos = os_strstr(cmd, "VLAN_ID="); -+ if (pos) -+ vlanid = atoi(pos + 8); -+ -+ if (!hostapd_maclist_found(*acl, *num, addr, &vlan_id)) { -+ ret = hostapd_add_acl_maclist(acl, num, vlanid, addr); -+ if (ret != -1 && *acl) -+ qsort(*acl, *num, sizeof(**acl), hostapd_acl_comp); -+ } -+ -+ return ret < 0 ? -1 : 0; -+} -+ - int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd, - const char *txtaddr) - { ---- a/src/ap/ctrl_iface_ap.h -+++ b/src/ap/ctrl_iface_ap.h -@@ -36,5 +36,15 @@ int hostapd_ctrl_iface_pmksa_add(struct - int hostapd_ctrl_iface_pmksa_list_mesh(struct hostapd_data *hapd, - const u8 *addr, char *buf, size_t len); - void * hostapd_ctrl_iface_pmksa_create_entry(const u8 *aa, char *cmd); -+int hostapd_ctrl_iface_acl_add_mac(struct mac_acl_entry **acl, int *num, -+ const char *cmd); -+int hostapd_ctrl_iface_acl_show_mac(struct mac_acl_entry *acl, int num, -+ char *buf, size_t buflen); -+void hostapd_ctrl_iface_acl_clear_list(struct mac_acl_entry **acl, -+ int *num); -+int hostapd_ctrl_iface_acl_del_mac(struct mac_acl_entry **acl, int *num, -+ const char *txtaddr); -+int hostapd_disassoc_accept_mac(struct hostapd_data *hapd); -+int hostapd_disassoc_deny_mac(struct hostapd_data *hapd); - - #endif /* CTRL_IFACE_AP_H */ ---- a/src/ap/ieee802_11.c -+++ b/src/ap/ieee802_11.c -@@ -7099,6 +7099,87 @@ u8 * hostapd_eid_wb_chsw_wrapper(struct - } - - -+int hostapd_acl_comp(const void *a, const void *b) -+{ -+ const struct mac_acl_entry *aa = a; -+ const struct mac_acl_entry *bb = b; -+ -+ return os_memcmp(aa->addr, bb->addr, sizeof(macaddr)); -+} -+ -+int hostapd_config_read_maclist(const char *fname, -+ struct mac_acl_entry **acl, int *num) -+{ -+ FILE *f; -+ char buf[128], *pos; -+ int line = 0; -+ u8 addr[ETH_ALEN]; -+ int vlan_id; -+ -+ f = fopen(fname, "r"); -+ if (!f) { -+ wpa_printf(MSG_ERROR, "MAC list file '%s' not found.", fname); -+ return -1; -+ } -+ -+ while (fgets(buf, sizeof(buf), f)) { -+ int rem = 0; -+ -+ line++; -+ -+ if (buf[0] == '#') -+ continue; -+ pos = buf; -+ while (*pos != '\0') { -+ if (*pos == '\n') { -+ *pos = '\0'; -+ break; -+ } -+ pos++; -+ } -+ if (buf[0] == '\0') -+ continue; -+ pos = buf; -+ if (buf[0] == '-') { -+ rem = 1; -+ pos++; -+ } -+ -+ if (hwaddr_aton(pos, addr)) { -+ wpa_printf(MSG_ERROR, "Invalid MAC address '%s' at " -+ "line %d in '%s'", pos, line, fname); -+ fclose(f); -+ return -1; -+ } -+ -+ if (rem) { -+ hostapd_remove_acl_mac(acl, num, addr); -+ continue; -+ } -+ vlan_id = 0; -+ pos = buf; -+ while (*pos != '\0' && *pos != ' ' && *pos != '\t') -+ pos++; -+ while (*pos == ' ' || *pos == '\t') -+ pos++; -+ if (*pos != '\0') -+ vlan_id = atoi(pos); -+ -+ if (hostapd_add_acl_maclist(acl, num, vlan_id, addr) < 0) { -+ fclose(f); -+ return -1; -+ } -+ } -+ -+ fclose(f); -+ -+ if (*acl) -+ qsort(*acl, *num, sizeof(**acl), hostapd_acl_comp); -+ -+ return 0; -+} -+ -+ - static size_t hostapd_eid_nr_db_len(struct hostapd_data *hapd, - size_t *current_len) - { ---- a/src/ap/ieee802_11.h -+++ b/src/ap/ieee802_11.h -@@ -18,6 +18,7 @@ struct ieee80211_vht_capabilities; - struct ieee80211_mgmt; - struct radius_sta; - enum ieee80211_op_mode; -+struct mac_acl_entry; - - int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len, - struct hostapd_frame_info *fi); -@@ -25,6 +26,14 @@ void ieee802_11_mgmt_cb(struct hostapd_d - u16 stype, int ok); - void hostapd_2040_coex_action(struct hostapd_data *hapd, - const struct ieee80211_mgmt *mgmt, size_t len); -+ -+int hostapd_config_read_maclist(const char *fname, -+ struct mac_acl_entry **acl, int *num); -+int hostapd_acl_comp(const void *a, const void *b); -+int hostapd_add_acl_maclist(struct mac_acl_entry **acl, int *num, -+ int vlan_id, const u8 *addr); -+void hostapd_remove_acl_mac(struct mac_acl_entry **acl, int *num, -+ const u8 *addr); - #ifdef NEED_AP_MLME - int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen); - int ieee802_11_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, diff --git a/feeds/ipq95xx/hostapd/patches/f00-003-Extend-acl-config-support-to-mesh.patch b/feeds/ipq95xx/hostapd/patches/f00-003-Extend-acl-config-support-to-mesh.patch deleted file mode 100644 index 567e0d7a6..000000000 --- a/feeds/ipq95xx/hostapd/patches/f00-003-Extend-acl-config-support-to-mesh.patch +++ /dev/null @@ -1,229 +0,0 @@ -From d3447cf20a26072d294cd74a8b3e5c676a7421e7 Mon Sep 17 00:00:00 2001 -From: Nishant Pandey -Date: Tue, 22 Sep 2020 14:19:41 +0530 -Subject: [PATCH] mesh: Add ACL logic support to mesh configuration - -Extend AP-STA accept and deny acl list support to -mesh peer connection as well. Here mesh node uses -macaddr_acl value either ACCEPT_UNLESS_DENIED or -DENY_UNLESS_ACCEPTED. - -Signed-off-by: Nishant Pandey ---- - wpa_supplicant/config.c | 21 ++++++++++++++++++++- - wpa_supplicant/config_file.c | 6 ++++++ - wpa_supplicant/config_ssid.h | 5 +++++ - wpa_supplicant/mesh.c | 22 ++++++++++++++++++++++ - wpa_supplicant/mesh_mpm.c | 15 +++++++++++++++ - wpa_supplicant/wpa_supplicant.conf | 14 ++++++++++++++ - 6 files changed, 82 insertions(+), 1 deletion(-) - -Index: hostapd-2021-02-08/wpa_supplicant/config.c -=================================================================== ---- hostapd-2021-02-08.orig/wpa_supplicant/config.c -+++ hostapd-2021-02-08/wpa_supplicant/config.c -@@ -20,7 +20,9 @@ - #include "drivers/nl80211_copy.h" - #include "fst/fst.h" - #include "config.h" -- -+#ifdef CONFIG_MESH -+#include "ap/ap_config.h" -+#endif - - #if !defined(CONFIG_CTRL_IFACE) && defined(CONFIG_NO_CONFIG_WRITE) - #define NO_CONFIG_WRITE -@@ -2710,6 +2712,9 @@ static const struct parse_data ssid_fiel - { INT(dot11MeshRetryTimeout) }, - { INT(dot11MeshConfirmTimeout) }, - { INT(dot11MeshHoldingTimeout) }, -+ { STR(accept_mac_file) }, -+ { STR(deny_mac_file) }, -+ { INT(macaddr_acl) }, - #endif /* CONFIG_MESH */ - { INT(wpa_ptk_rekey) }, - { INT_RANGE(wpa_deny_ptk0_rekey, 0, 2) }, -@@ -2980,6 +2985,8 @@ void wpa_config_free_ssid(struct wpa_ssi - os_free(ssid->p2p_client_list); - os_free(ssid->bssid_ignore); - os_free(ssid->bssid_accept); -+ os_free(ssid->accept_mac_file); -+ os_free(ssid->deny_mac_file); - #ifdef CONFIG_HT_OVERRIDES - os_free(ssid->ht_mcs); - #endif /* CONFIG_HT_OVERRIDES */ -@@ -3344,6 +3351,18 @@ int wpa_config_set(struct wpa_ssid *ssid - } - ret = -1; - } -+#ifdef CONFIG_MESH -+ if (os_strcmp(var, "macaddr_acl") == 0) { -+ if (ssid->macaddr_acl != ACCEPT_UNLESS_DENIED && -+ ssid->macaddr_acl != DENY_UNLESS_ACCEPTED) { -+ wpa_printf(MSG_ERROR, -+ "Line %d: unknown macaddr_acl %d", -+ line, ssid->macaddr_acl); -+ ret = -1; -+ } -+ } -+#endif -+ - #ifdef CONFIG_SAE - if (os_strcmp(var, "ssid") == 0 || - os_strcmp(var, "psk") == 0 || -Index: hostapd-2021-02-08/wpa_supplicant/config_file.c -=================================================================== ---- hostapd-2021-02-08.orig/wpa_supplicant/config_file.c -+++ hostapd-2021-02-08/wpa_supplicant/config_file.c -@@ -18,6 +18,9 @@ - #include "common.h" - #include "config.h" - #include "base64.h" -+#ifdef CONFIG_MESH -+#include "ap/ap_config.h" -+#endif - #include "uuid.h" - #include "common/ieee802_1x_defs.h" - #include "p2p/p2p.h" -@@ -914,6 +917,9 @@ static void wpa_config_write_network(FIL - write_int(f, "mac_addr", ssid->mac_addr, -1); - #ifdef CONFIG_MESH - STR(mesh_basic_rates); -+ STR(accept_mac_file); -+ STR(deny_mac_file); -+ INT_DEF(macaddr_acl, ACCEPT_UNLESS_DENIED); - INT_DEF(dot11MeshMaxRetries, DEFAULT_MESH_MAX_RETRIES); - INT_DEF(dot11MeshRetryTimeout, DEFAULT_MESH_RETRY_TIMEOUT); - INT_DEF(dot11MeshConfirmTimeout, DEFAULT_MESH_CONFIRM_TIMEOUT); -Index: hostapd-2021-02-08/wpa_supplicant/config_ssid.h -=================================================================== ---- hostapd-2021-02-08.orig/wpa_supplicant/config_ssid.h -+++ hostapd-2021-02-08/wpa_supplicant/config_ssid.h -@@ -546,6 +546,11 @@ struct wpa_ssid { - int dot11MeshConfirmTimeout; /* msec */ - int dot11MeshHoldingTimeout; /* msec */ - -+ char *accept_mac_file; -+ char *deny_mac_file; -+ int macaddr_acl; -+ -+ - int ht; - int ht40; - -Index: hostapd-2021-02-08/wpa_supplicant/mesh.c -=================================================================== ---- hostapd-2021-02-08.orig/wpa_supplicant/mesh.c -+++ hostapd-2021-02-08/wpa_supplicant/mesh.c -@@ -16,6 +16,7 @@ - #include "common/hw_features_common.h" - #include "ap/sta_info.h" - #include "ap/hostapd.h" -+#include "ap/ieee802_11_auth.h" - #include "ap/ieee802_11.h" - #include "config_ssid.h" - #include "config.h" -@@ -459,6 +460,17 @@ static int wpa_supplicant_mesh_init(stru - ifmsh->bss[0]->dot11RSNASAERetransPeriod = - wpa_s->conf->dot11RSNASAERetransPeriod; - os_strlcpy(bss->conf->iface, wpa_s->ifname, sizeof(bss->conf->iface)); -+ bss->conf->macaddr_acl = ssid->macaddr_acl; -+ -+ if (ssid->accept_mac_file) -+ hostapd_config_read_maclist(ssid->accept_mac_file, -+ &bss->conf->accept_mac, -+ &bss->conf->num_accept_mac); -+ -+ if (ssid->deny_mac_file) -+ hostapd_config_read_maclist(ssid->deny_mac_file, -+ &bss->conf->deny_mac, -+ &bss->conf->num_deny_mac); - - mconf = mesh_config_create(wpa_s, ssid); - if (!mconf) -@@ -555,6 +567,16 @@ void wpa_mesh_notify_peer(struct wpa_sup - const u8 *ies, size_t ie_len) - { - struct ieee802_11_elems elems; -+ int acl_res; -+ struct hostapd_data *data = wpa_s->ifmsh->bss[0]; -+ struct radius_sta rad_info; -+ -+ acl_res = hostapd_allowed_address(data, addr, NULL, 0, &rad_info, 0); -+ if (acl_res == HOSTAPD_ACL_REJECT) { -+ wpa_printf(MSG_ERROR, "Ignore new peer notification\n"); -+ return; -+ -+ } - - wpa_msg(wpa_s, MSG_INFO, - "new peer notification for " MACSTR, MAC2STR(addr)); -Index: hostapd-2021-02-08/wpa_supplicant/mesh_mpm.c -=================================================================== ---- hostapd-2021-02-08.orig/wpa_supplicant/mesh_mpm.c -+++ hostapd-2021-02-08/wpa_supplicant/mesh_mpm.c -@@ -16,6 +16,7 @@ - #include "ap/hostapd.h" - #include "ap/sta_info.h" - #include "ap/ieee802_11.h" -+#include "ap/ieee802_11_auth.h" - #include "ap/wpa_auth.h" - #include "wpa_supplicant_i.h" - #include "driver_i.h" -@@ -1128,10 +1129,12 @@ void mesh_mpm_action_rx(struct wpa_suppl - enum plink_event event; - struct ieee802_11_elems elems; - struct mesh_peer_mgmt_ie peer_mgmt_ie; -+ struct radius_sta rad_info; - const u8 *ies; - size_t ie_len; - int ret; - u16 reason = 0; -+ int acl_res; - - if (mgmt->u.action.category != WLAN_ACTION_SELF_PROTECTED) - return; -@@ -1179,6 +1182,18 @@ void mesh_mpm_action_rx(struct wpa_suppl - return; - } - if (action_field != PLINK_CLOSE) { -+ if (action_field != PLINK_CLOSE) { -+ acl_res = hostapd_allowed_address(hapd, mgmt->sa, -+ (const u8 *) mgmt, -+ len, &rad_info, 0); -+ if (acl_res == HOSTAPD_ACL_REJECT) { -+ wpa_printf(MSG_DEBUG, -+ "MPM: Ignore action frame\n"); -+ return; -+ -+ } -+ } -+ - if (!elems.mesh_id || !elems.mesh_config) { - wpa_printf(MSG_DEBUG, - "MPM: No Mesh ID or Mesh Configuration element"); -Index: hostapd-2021-02-08/wpa_supplicant/wpa_supplicant.conf -=================================================================== ---- hostapd-2021-02-08.orig/wpa_supplicant/wpa_supplicant.conf -+++ hostapd-2021-02-08/wpa_supplicant/wpa_supplicant.conf -@@ -150,6 +150,20 @@ ap_scan=1 - # This timeout value is used in mesh STA to clean up inactive stations. - #mesh_max_inactivity=300 - -+# Mesh node address -based authentication -+# Please note that this kind of access control requires a driver that uses -+# wpa_supplicant to take care of management frame and mesh PLINK connection -+# processing and as such. -+# 0 = accept unless in deny list -+# 1 = deny unless in accept list -+macaddr_acl=0 -+ -+# Accept/deny lists are read from separate files (containing list of -+# MAC addresses, one per line). Use absolute path name to make sure that the -+# files can be read on SIGHUP configuration reloads. -+#accept_mac_file=/etc/hostapd.accept -+#deny_mac_file=/etc/hostapd.deny -+ - # cert_in_cb - Whether to include a peer certificate dump in events - # This controls whether peer certificates for authentication server and - # its certificate chain are included in EAP peer certificate events. This is diff --git a/feeds/ipq95xx/hostapd/patches/f00-003-bss-coloring-disable-BSS-color-during-CCA.patch b/feeds/ipq95xx/hostapd/patches/f00-003-bss-coloring-disable-BSS-color-during-CCA.patch deleted file mode 100644 index d0b401f36..000000000 --- a/feeds/ipq95xx/hostapd/patches/f00-003-bss-coloring-disable-BSS-color-during-CCA.patch +++ /dev/null @@ -1,24 +0,0 @@ -From: John Crispin -Subject: [PATCH V4 3/6] bss coloring: disable BSS color during CCA -Date: Wed, 26 Aug 2020 08:22:13 +0200 - - -While we are doing CCA the bss color disable bit inside the he oper field -needs to be set. - -Signed-off-by: John Crispin ---- - src/ap/ieee802_11_he.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/src/ap/ieee802_11_he.c -+++ b/src/ap/ieee802_11_he.c -@@ -198,7 +198,7 @@ u8 * hostapd_eid_he_operation(struct hos - params |= (hapd->iface->conf->he_op.he_rts_threshold << - HE_OPERATION_RTS_THRESHOLD_OFFSET); - -- if (hapd->iface->conf->he_op.he_bss_color_disabled) -+ if (hapd->iface->conf->he_op.he_bss_color_disabled || hapd->cca_in_progress) - params |= HE_OPERATION_BSS_COLOR_DISABLED; - if (hapd->iface->conf->he_op.he_bss_color_partial) - params |= HE_OPERATION_BSS_COLOR_PARTIAL; diff --git a/feeds/ipq95xx/hostapd/patches/f00-004-bss-coloring-add-the-switch_color-handler-to-the-nl80211-driver.patch b/feeds/ipq95xx/hostapd/patches/f00-004-bss-coloring-add-the-switch_color-handler-to-the-nl80211-driver.patch deleted file mode 100644 index 7debeddba..000000000 --- a/feeds/ipq95xx/hostapd/patches/f00-004-bss-coloring-add-the-switch_color-handler-to-the-nl80211-driver.patch +++ /dev/null @@ -1,156 +0,0 @@ -From 2113291e2fb20d82ac9f9740fed13abea2193a35 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Tue, 3 Nov 2020 20:15:08 -0800 -Subject: [PATCH V4 4/6] bss coloring: add the switch_color handler to the - nl80211 driver - -In order to start the CCA process we need to send NL80211_CMD_COLOR_CHANGE -to the kernel. This patch adds the required code. - -Signed-off-by: John Crispin ---- - src/drivers/driver_nl80211.c | 79 ++++++++++++++++++++++++++++++++++++ - src/drivers/nl80211_copy.h | 18 +++++++- - 2 files changed, 95 insertions(+), 2 deletions(-) - ---- a/src/drivers/driver_nl80211.c -+++ b/src/drivers/driver_nl80211.c -@@ -9977,6 +9977,82 @@ error: - } - - -+#ifdef CONFIG_IEEE80211AX -+static int nl80211_switch_color(void *priv, struct cca_settings *settings) -+{ -+ struct nl_msg *msg; -+ struct i802_bss *bss = priv; -+ struct wpa_driver_nl80211_data *drv = bss->drv; -+ struct nlattr *beacon_cca; -+ int ret = -ENOBUFS; -+ -+ wpa_printf(MSG_DEBUG, "nl80211: Color change request (cca_count=%u color=%d)", -+ settings->cca_count, settings->cca_color); -+ -+ if (drv->nlmode != NL80211_IFTYPE_AP) -+ return -EOPNOTSUPP; -+ -+ if (!settings->beacon_cca.tail) -+ return -EINVAL; -+ -+ if ((settings->beacon_cca.tail_len <= settings->counter_offset_beacon) || -+ (settings->beacon_cca.tail[settings->counter_offset_beacon] != -+ settings->cca_count)) -+ return -EINVAL; -+ -+ if (settings->beacon_cca.probe_resp && -+ ((settings->beacon_cca.probe_resp_len <= -+ settings->counter_offset_presp) || -+ (settings->beacon_cca.probe_resp[settings->counter_offset_presp] != -+ settings->cca_count))) -+ return -EINVAL; -+ -+ if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_COLOR_CHANGE)) || -+ nla_put_u8(msg, NL80211_ATTR_COLOR_CHANGE_ANNOUNCEMENT_COUNT, -+ settings->cca_count) || -+ nla_put_u8(msg, NL80211_ATTR_COLOR_CHANGE_ANNOUNCEMENT_COLOR, -+ settings->cca_color)) -+ goto error; -+ -+ /* beacon_after params */ -+ ret = set_beacon_data(msg, &settings->beacon_after); -+ if (ret) -+ goto error; -+ -+ /* beacon_csa params */ -+ beacon_cca = nla_nest_start(msg, NL80211_ATTR_COLOR_CHANGE_ANNOUNCEMENT_IES); -+ if (!beacon_cca) -+ goto fail; -+ -+ ret = set_beacon_data(msg, &settings->beacon_cca); -+ if (ret) -+ goto error; -+ -+ if (nla_put_u16(msg, NL80211_ATTR_CNTDWN_OFFS_BEACON, -+ settings->counter_offset_beacon) || -+ (settings->beacon_cca.probe_resp && -+ nla_put_u16(msg, NL80211_ATTR_CNTDWN_OFFS_PRESP, -+ settings->counter_offset_presp))) -+ goto fail; -+ -+ nla_nest_end(msg, beacon_cca); -+ ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); -+ if (ret) { -+ wpa_printf(MSG_DEBUG, "nl80211: switch_color failed err=%d (%s)", -+ ret, strerror(-ret)); -+ } -+ return ret; -+ -+fail: -+ ret = -ENOBUFS; -+error: -+ nlmsg_free(msg); -+ wpa_printf(MSG_DEBUG, "nl80211: Could not build color switch request"); -+ return ret; -+} -+#endif -+ -+ - static int nl80211_add_ts(void *priv, u8 tsid, const u8 *addr, - u8 user_priority, u16 admitted_time) - { -@@ -12242,6 +12318,9 @@ const struct wpa_driver_ops wpa_driver_n - .get_survey = wpa_driver_nl80211_get_survey, - .status = wpa_driver_nl80211_status, - .switch_channel = nl80211_switch_channel, -+#ifdef CONFIG_IEEE80211AX -+ .switch_color = nl80211_switch_color, -+#endif - #ifdef ANDROID_P2P - .set_noa = wpa_driver_set_p2p_noa, - .get_noa = wpa_driver_get_p2p_noa, ---- a/src/drivers/nl80211_copy.h -+++ b/src/drivers/nl80211_copy.h -@@ -1423,6 +1423,16 @@ enum nl80211_commands { - NL80211_CMD_SET_SAR_SPECS, - - NL80211_CMD_UPDATE_HE_MUEDCA_PARAMS, -+ -+ NL80211_CMD_OBSS_COLOR_COLLISION, -+ -+ NL80211_CMD_COLOR_CHANGE, -+ NL80211_CMD_COLOR_CHANGE_ANNOUNCEMENT_STARTED, -+ NL80211_CMD_COLOR_CHANGE_ANNOUNCEMENT_ABORTED, -+ NL80211_CMD_COLOR_CHANGE_ANNOUNCEMENT_COMPLETED, -+ -+ NL80211_CMD_SET_FILS_AAD, -+ - /* add new commands above here */ - - /* used to define NL80211_CMD_MAX below */ -@@ -3067,6 +3077,16 @@ enum nl80211_attrs { - NL80211_ATTR_DISABLE_HE, - - NL80211_ATTR_HE_MUEDCA_PARAMS, -+ -+ NL80211_ATTR_OBSS_COLOR_BITMAP, -+ -+ NL80211_ATTR_COLOR_CHANGE_ANNOUNCEMENT_COUNT, -+ NL80211_ATTR_COLOR_CHANGE_ANNOUNCEMENT_COLOR, -+ NL80211_ATTR_COLOR_CHANGE_ANNOUNCEMENT_IES, -+ -+ NL80211_ATTR_MBSSID_CONFIG, -+ NL80211_ATTR_MBSSID_ELEMS, -+ - /* add attributes here, update the policy in nl80211.c */ - - __NL80211_ATTR_AFTER_LAST, ---- a/src/drivers/driver_nl80211_event.c -+++ b/src/drivers/driver_nl80211_event.c -@@ -172,6 +172,7 @@ static const char * nl80211_command_to_s - C2S(NL80211_CMD_UNPROT_BEACON) - C2S(NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS) - C2S(NL80211_CMD_SET_SAR_SPECS) -+ C2S(NL80211_CMD_SET_FILS_AAD) - C2S(NL80211_CMD_UPDATE_HE_MUEDCA_PARAMS) - C2S(NL80211_CMD_COLOR_CHANGE) - C2S(__NL80211_CMD_AFTER_LAST) diff --git a/feeds/ipq95xx/hostapd/patches/f00-004-mesh-Dynamic-MAC-ACL-management-over-control-interface.patch b/feeds/ipq95xx/hostapd/patches/f00-004-mesh-Dynamic-MAC-ACL-management-over-control-interface.patch deleted file mode 100644 index 976a23a87..000000000 --- a/feeds/ipq95xx/hostapd/patches/f00-004-mesh-Dynamic-MAC-ACL-management-over-control-interface.patch +++ /dev/null @@ -1,299 +0,0 @@ -From 2173e65aa098ab130bfdbc9b9cfe8ac2fc2ae086 Mon Sep 17 00:00:00 2001 -From: Nishant Pandey -Date: Tue, 22 Sep 2020 14:23:08 +0530 -Subject: [PATCH] mesh: Dynamic MAC ACL management over control interface - -Extend support to modify MAC ACL and displayed it through -new control interface - -commands: - -ACCEPT_ACL [argument] -DENY_ACL [argument] -subcmd: ADD_MAC |DEL_MAC |SHOW|CLEAR - -Signed-off-by: Nishant Pandey ---- - wpa_supplicant/ap.c | 68 +++++++++++++++++++++++++++++++++++++++++ - wpa_supplicant/ap.h | 5 +++ - wpa_supplicant/ctrl_iface.c | 45 +++++++++++++++++++++++++++ - wpa_supplicant/events.c | 1 + - wpa_supplicant/mesh.c | 1 + - wpa_supplicant/wpa_cli.c | 19 ++++++++++++ - wpa_supplicant/wpa_supplicant.c | 3 +- - wpa_supplicant/wps_supplicant.c | 2 ++ - 8 files changed, 143 insertions(+), 1 deletion(-) - ---- a/wpa_supplicant/ap.c -+++ b/wpa_supplicant/ap.c -@@ -6,6 +6,7 @@ - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ -+#include - - #include "utils/includes.h" - -@@ -1616,6 +1617,73 @@ void wpas_ap_pmksa_cache_flush(struct wp - hostapd_ctrl_iface_pmksa_flush(wpa_s->ifmsh->bss[0]); - } - -+#ifdef CONFIG_MESH -+ -+int wpas_ap_acl_del_mac(struct wpa_supplicant *wpa_s, char *buf, bool accept) -+{ -+ struct hostapd_data *hapd = wpa_s->ifmsh->bss[0]; -+ -+ if (accept) { -+ if (!hostapd_ctrl_iface_acl_del_mac(&hapd->conf->accept_mac, -+ &hapd->conf->num_accept_mac, -+ buf)) -+ if (hostapd_disassoc_accept_mac(hapd)) -+ return 1; -+ } -+ -+ return hostapd_ctrl_iface_acl_del_mac(&hapd->conf->deny_mac, -+ &hapd->conf->num_deny_mac, -+ buf); -+} -+ -+int wpas_ap_acl_add_mac(struct wpa_supplicant *wpa_s, char *buf, bool accept) -+{ -+ struct hostapd_data *hapd = wpa_s->ifmsh->bss[0]; -+ -+ if (accept) { -+ return hostapd_ctrl_iface_acl_add_mac(&hapd->conf->accept_mac, -+ &hapd->conf->num_accept_mac, -+ buf); -+ } else { -+ if (!hostapd_ctrl_iface_acl_add_mac(&hapd->conf->deny_mac, -+ &hapd->conf->num_deny_mac, buf)) { -+ if (hostapd_disassoc_deny_mac(hapd)) -+ return 1; -+ return 0; -+ } -+ } -+ -+ return -1; -+} -+ -+int wpas_ap_acl_show_mac(struct wpa_supplicant *wpa_s, char *reply, -+ const int reply_size, bool accept) -+{ -+ struct hostapd_data *hapd = wpa_s->ifmsh->bss[0]; -+ -+ if (accept) -+ return hostapd_ctrl_iface_acl_show_mac( -+ hapd->conf->accept_mac, -+ hapd->conf->num_accept_mac, -+ reply, reply_size); -+ -+ return hostapd_ctrl_iface_acl_show_mac( -+ hapd->conf->deny_mac, -+ hapd->conf->num_deny_mac, -+ reply, reply_size); -+} -+ -+void wpas_ap_deny_acl_clear_list(struct wpa_supplicant *wpa_s) -+{ -+ struct hostapd_data *hapd = wpa_s->ifmsh->bss[0]; -+ -+ -+ return hostapd_ctrl_iface_acl_clear_list(&hapd->conf->deny_mac, -+ &hapd->conf->num_deny_mac); -+} -+ -+#endif /* CONFIG_MESH */ -+ - - #ifdef CONFIG_PMKSA_CACHE_EXTERNAL - #ifdef CONFIG_MESH ---- a/wpa_supplicant/ap.h -+++ b/wpa_supplicant/ap.h -@@ -99,6 +99,11 @@ void wpas_ap_event_dfs_cac_aborted(struc - struct dfs_event *radar); - void wpas_ap_event_dfs_cac_nop_finished(struct wpa_supplicant *wpa_s, - struct dfs_event *radar); -+int wpas_ap_acl_del_mac(struct wpa_supplicant *wpa_s, char *buf, bool accept); -+int wpas_ap_acl_add_mac(struct wpa_supplicant *wpa_s, char *buf, bool accept); -+int wpas_ap_acl_show_mac(struct wpa_supplicant *wpa_s, char *reply, -+ const int reply_size, bool accept); -+void wpas_ap_deny_acl_clear_list(struct wpa_supplicant *wpa_s); - - void ap_periodic(struct wpa_supplicant *wpa_s); - ---- a/wpa_supplicant/ctrl_iface.c -+++ b/wpa_supplicant/ctrl_iface.c -@@ -5,6 +5,7 @@ - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ -+#include - - #include "utils/includes.h" - #ifdef CONFIG_TESTING_OPTIONS -@@ -56,6 +57,7 @@ - #include "mesh.h" - #include "dpp_supplicant.h" - #include "sme.h" -+#include "ap/ieee802_11.h" - - #ifdef __NetBSD__ - #include -@@ -3284,6 +3286,18 @@ static int wpa_supplicant_ctrl_iface_mes - return wpas_mesh_peer_remove(wpa_s, addr); - } - -+static void wpas_ap_accept_acl_clear_list(struct wpa_supplicant *wpa_s) -+{ -+ struct hostapd_data *hapd = wpa_s->ifmsh->bss[0]; -+ struct mac_acl_entry **acl = &hapd->conf->accept_mac; -+ int *num = &hapd->conf->num_accept_mac; -+ -+ while (*num) { -+ wpas_mesh_peer_remove(wpa_s, (*acl)[0].addr); -+ hostapd_remove_acl_mac(acl, num, (*acl)[0].addr); -+ } -+} -+ - - static int wpa_supplicant_ctrl_iface_mesh_peer_add( - struct wpa_supplicant *wpa_s, char *cmd) -@@ -10655,6 +10669,38 @@ char * wpa_supplicant_ctrl_iface_process - reply_len = -1; - #endif /* CONFIG_IBSS_RSN */ - #ifdef CONFIG_MESH -+ } else if (os_strncmp(buf, "ACCEPT_ACL ", 11) == 0) { -+ if (os_strncmp(buf + 11, "ADD_MAC ", 8) == 0) { -+ wpas_ap_acl_add_mac(wpa_s, buf + 19, 1); -+ } else if (os_strncmp((buf + 11), "DEL_MAC ", 8) == 0) { -+ reply_len = wpas_ap_acl_del_mac(wpa_s, buf + 19, 1); -+ if (reply_len == 1) -+ wpa_supplicant_ctrl_iface_mesh_peer_remove( -+ wpa_s, buf + 19); -+ else if (reply_len) -+ reply_len = -1; -+ } else if (os_strcmp(buf + 11, "SHOW") == 0) { -+ reply_len = wpas_ap_acl_show_mac(wpa_s, reply, -+ reply_size, 1); -+ } else if (os_strcmp(buf + 11, "CLEAR") == 0) { -+ wpas_ap_accept_acl_clear_list(wpa_s); -+ } -+ } else if (os_strncmp(buf, "DENY_ACL ", 9) == 0) { -+ if (os_strncmp(buf + 9, "ADD_MAC ", 8) == 0) { -+ reply_len = wpas_ap_acl_add_mac(wpa_s, buf + 17, 0); -+ if (reply_len == 1) -+ wpa_supplicant_ctrl_iface_mesh_peer_remove( -+ wpa_s, buf + 17); -+ else if (reply_len) -+ reply_len = -1; -+ } else if (os_strncmp(buf + 9, "DEL_MAC ", 8) == 0) { -+ wpas_ap_acl_del_mac(wpa_s, buf + 17, 0); -+ } else if (os_strcmp(buf + 9, "SHOW") == 0) { -+ reply_len = wpas_ap_acl_show_mac(wpa_s, reply, -+ reply_size, 0); -+ } else if (os_strcmp(buf + 9, "CLEAR") == 0) { -+ wpas_ap_deny_acl_clear_list(wpa_s); -+ } - } else if (os_strncmp(buf, "MESH_INTERFACE_ADD ", 19) == 0) { - reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add( - wpa_s, buf + 19, reply, reply_size); ---- a/wpa_supplicant/events.c -+++ b/wpa_supplicant/events.c -@@ -5,6 +5,7 @@ - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ -+#include - - #include "includes.h" - ---- a/wpa_supplicant/mesh.c -+++ b/wpa_supplicant/mesh.c -@@ -5,6 +5,7 @@ - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ -+#include - - #include "utils/includes.h" - ---- a/wpa_supplicant/wpa_cli.c -+++ b/wpa_supplicant/wpa_cli.c -@@ -2113,6 +2113,19 @@ static int wpa_cli_cmd_mesh_link_probe(s - return wpa_cli_cmd(ctrl, "MESH_LINK_PROBE", 1, argc, argv); - } - -+static int wpa_cli_cmd_accept_macacl(struct wpa_ctrl *ctrl, int argc, -+ char *argv[]) -+{ -+ return wpa_cli_cmd(ctrl, "ACCEPT_ACL", 1, argc, argv); -+} -+ -+ -+static int wpa_cli_cmd_deny_macacl(struct wpa_ctrl *ctrl, int argc, -+ char *argv[]) -+{ -+ return wpa_cli_cmd(ctrl, "DENY_ACL", 1, argc, argv); -+} -+ - #endif /* CONFIG_MESH */ - - -@@ -3532,6 +3545,12 @@ static const struct wpa_cli_cmd wpa_cli_ - { "mesh_link_probe", wpa_cli_cmd_mesh_link_probe, NULL, - cli_cmd_flag_none, - " [payload=] = Probe a mesh link for a given peer by injecting a frame." }, -+ { "accept_acl", wpa_cli_cmd_accept_macacl, NULL, -+ cli_cmd_flag_none, -+ "=Add/Delete/Show/Clear accept MAC ACL" }, -+ { "deny_acl", wpa_cli_cmd_deny_macacl, NULL, -+ cli_cmd_flag_none, -+ "=Add/Delete/Show/Clear deny MAC ACL" }, - #endif /* CONFIG_MESH */ - #ifdef CONFIG_P2P - { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find, ---- a/wpa_supplicant/wpa_supplicant.c -+++ b/wpa_supplicant/wpa_supplicant.c -@@ -9,6 +9,7 @@ - * %wpa_supplicant interfaces. In addition, this file contains number of - * functions for managing network connections. - */ -+#include - - #include "includes.h" - #ifdef CONFIG_MATCH_IFACE -@@ -49,7 +50,6 @@ - #include "ibss_rsn.h" - #include "sme.h" - #include "gas_query.h" --#include "ap.h" - #include "p2p_supplicant.h" - #include "wifi_display.h" - #include "notify.h" -@@ -67,6 +67,7 @@ - #include "ap/ap_config.h" - #include "ap/hostapd.h" - #endif /* CONFIG_MESH */ -+#include "ap.h" - - const char *const wpa_supplicant_version = - "wpa_supplicant v" VERSION_STR "\n" ---- a/wpa_supplicant/wps_supplicant.c -+++ b/wpa_supplicant/wps_supplicant.c -@@ -5,6 +5,7 @@ - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ -+#include - - #include "includes.h" - -@@ -21,6 +22,7 @@ - #include "eap_peer/eap.h" - #include "eapol_supp/eapol_supp_sm.h" - #include "rsn_supp/wpa.h" -+#include "ap/hostapd.h" - #include "wps/wps_attr_parse.h" - #include "config.h" - #include "wpa_supplicant_i.h" diff --git a/feeds/ipq95xx/hostapd/patches/f00-005-bss-coloring-handle-the-collision-and-CCA-events-coming-from-the-kernel.patch b/feeds/ipq95xx/hostapd/patches/f00-005-bss-coloring-handle-the-collision-and-CCA-events-coming-from-the-kernel.patch deleted file mode 100644 index eb7a91e83..000000000 --- a/feeds/ipq95xx/hostapd/patches/f00-005-bss-coloring-handle-the-collision-and-CCA-events-coming-from-the-kernel.patch +++ /dev/null @@ -1,227 +0,0 @@ -From: John Crispin -Subject: [PATCH V4 5/6] bss coloring: handle the collision and CCA events - coming from the kernel -Date: Wed, 26 Aug 2020 08:22:15 +0200 - - -This patch activates the functionality of the previous patches by handling -the actual events that will trigger the CCA process. - -Signed-off-by: John Crispin ---- - src/ap/drv_callbacks.c | 45 ++++++++++++++++++++- - src/drivers/driver.h | 27 +++++++++++++ - src/drivers/driver_common.c | 4 ++ - src/drivers/driver_nl80211_event.c | 64 +++++++++++++++++++++++++++++- - 4 files changed, 138 insertions(+), 2 deletions(-) - ---- a/src/ap/drv_callbacks.c -+++ b/src/ap/drv_callbacks.c -@@ -44,7 +44,6 @@ - #include "fils_hlp.h" - #include "neighbor_db.h" - -- - #ifdef CONFIG_FILS - void hostapd_notify_assoc_fils_finish(struct hostapd_data *hapd, - struct sta_info *sta) -@@ -1801,6 +1800,39 @@ static void hostapd_event_update_muedca_ - "Failed to update beacons with MU-EDCA parameters"); - } - -+#ifdef CONFIG_IEEE80211AX -+static void hostapd_event_bss_color_collision(struct hostapd_data *hapd, -+ u64 bitmap) -+{ -+ /* the bss color is shared amongst all BBSs on a specific phy. -+ * therefore we always start the color change on the primary BSS -+ */ -+ wpa_printf(MSG_DEBUG, "BSS color collision on %s", hapd->conf->iface); -+ hostapd_switch_color(hapd->iface->bss[0], bitmap); -+} -+ -+static void hostapd_event_cca(struct hostapd_data *hapd, enum wpa_event_type event) -+{ -+ switch (event) { -+ case EVENT_CCA_STARTED_NOTIFY: -+ wpa_printf(MSG_DEBUG, "CCA started on %s", hapd->conf->iface); -+ break; -+ case EVENT_CCA_NOTIFY: -+ wpa_printf(MSG_DEBUG, "CCA finished on %s (new color: %d)", hapd->conf->iface, hapd->cca_color); -+ hapd->iface->conf->he_op.he_bss_color = hapd->cca_color; -+ hostapd_cleanup_cca_params(hapd); -+ break; -+ case EVENT_CCA_ABORTED_NOTIFY: -+ wpa_printf(MSG_DEBUG, "CCA aborted on %s for cca_color: %d", hapd->conf->iface, hapd->cca_color); -+ hostapd_cleanup_cca_params(hapd); -+ break; -+ default: -+ break; -+ } -+} -+#endif -+ -+ - #ifdef CONFIG_OWE - static int hostapd_notif_update_dh_ie(struct hostapd_data *hapd, - const u8 *peer, const u8 *ie, -@@ -2111,6 +2143,17 @@ void hostapd_wpa_event(void *ctx, enum w - case EVENT_UPDATE_MUEDCA_PARAMS: - hostapd_event_update_muedca_params(hapd, &data->update_muedca); - break; -+#ifdef CONFIG_IEEE80211AX -+ case EVENT_BSS_COLOR_COLLISION: -+ hostapd_event_bss_color_collision(hapd, -+ data->bss_color_collision.bitmap); -+ break; -+ case EVENT_CCA_STARTED_NOTIFY: -+ case EVENT_CCA_ABORTED_NOTIFY: -+ case EVENT_CCA_NOTIFY: -+ hostapd_event_cca(hapd, event); -+ break; -+#endif - default: - wpa_printf(MSG_DEBUG, "Unknown event %d", event); - break; ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -5175,6 +5175,26 @@ enum wpa_event_type { - * beacon. - */ - EVENT_UPDATE_MUEDCA_PARAMS, -+ -+ /** -+ * EVENT_BSS_COLOR_COLLISION - Notification of a BSS color collision -+ */ -+ EVENT_BSS_COLOR_COLLISION, -+ -+ /** -+ * EVENT_CCA_STARTED_NOTIFY - Notification that CCA has started -+ */ -+ EVENT_CCA_STARTED_NOTIFY, -+ -+ /** -+ * EVENT_CCA_ABORTED_NOTIFY - Notification that CCA has aborted -+ */ -+ EVENT_CCA_ABORTED_NOTIFY, -+ -+ /** -+ * EVENT_CCA_NOTIFY - Notification that CCA has completed -+ */ -+ EVENT_CCA_NOTIFY, - }; - - -@@ -6077,6 +6097,13 @@ union wpa_event_data { - u8 he_mu_ac_vi_param[3]; - u8 he_mu_ac_vo_param[3]; - } update_muedca; -+ -+ /** -+ * struct bss_color_collision - Data for EVENT_BSS_COLOR_COLLISION -+ */ -+ struct bss_color_collision { -+ u64 bitmap; -+ } bss_color_collision; - }; - - /** ---- a/src/drivers/driver_common.c -+++ b/src/drivers/driver_common.c -@@ -91,6 +91,10 @@ const char * event_to_string(enum wpa_ev - E2S(UPDATE_DH); - E2S(UNPROT_BEACON); - E2S(UPDATE_MUEDCA_PARAMS); -+ E2S(BSS_COLOR_COLLISION); -+ E2S(CCA_STARTED_NOTIFY); -+ E2S(CCA_ABORTED_NOTIFY); -+ E2S(CCA_NOTIFY); - } - - return "UNKNOWN"; ---- a/src/drivers/driver_nl80211_event.c -+++ b/src/drivers/driver_nl80211_event.c -@@ -175,6 +175,10 @@ static const char * nl80211_command_to_s - C2S(NL80211_CMD_SET_FILS_AAD) - C2S(NL80211_CMD_UPDATE_HE_MUEDCA_PARAMS) - C2S(NL80211_CMD_COLOR_CHANGE) -+ C2S(NL80211_CMD_OBSS_COLOR_COLLISION) -+ C2S(NL80211_CMD_COLOR_CHANGE_ANNOUNCEMENT_STARTED) -+ C2S(NL80211_CMD_COLOR_CHANGE_ANNOUNCEMENT_ABORTED) -+ C2S(NL80211_CMD_COLOR_CHANGE_ANNOUNCEMENT_COMPLETED) - C2S(__NL80211_CMD_AFTER_LAST) - } - #undef C2S -@@ -2863,6 +2867,51 @@ static void nl80211_control_port_frame(s - } - } - -+#ifdef CONFIG_IEEE80211AX -+static void mlme_event_obss_color_collision(struct wpa_driver_nl80211_data *drv, -+ struct nlattr *tb[]) -+{ -+ union wpa_event_data data; -+ -+ if (!tb[NL80211_ATTR_OBSS_COLOR_BITMAP]) -+ return; -+ -+ os_memset(&data, 0, sizeof(data)); -+ data.bss_color_collision.bitmap = nla_get_u64(tb[NL80211_ATTR_OBSS_COLOR_BITMAP]); -+ -+ wpa_printf(MSG_DEBUG, "nl80211: BSS color collision - bitmap %08llx", -+ (long long unsigned int)data.bss_color_collision.bitmap); -+ -+ wpa_supplicant_event(drv->ctx, EVENT_BSS_COLOR_COLLISION, &data); -+} -+ -+static void mlme_event_color_change_announcement_started(struct wpa_driver_nl80211_data *drv) -+{ -+ union wpa_event_data data = {}; -+ -+ wpa_printf(MSG_DEBUG, "nl80211: CCA started"); -+ -+ wpa_supplicant_event(drv->ctx, EVENT_CCA_STARTED_NOTIFY, &data); -+} -+ -+static void mlme_event_color_change_announcement_aborted(struct wpa_driver_nl80211_data *drv) -+{ -+ union wpa_event_data data = {}; -+ -+ wpa_printf(MSG_DEBUG, "nl80211: CCA aborted"); -+ -+ wpa_supplicant_event(drv->ctx, EVENT_CCA_ABORTED_NOTIFY, &data); -+} -+ -+static void mlme_event_color_change_announcement_completed(struct wpa_driver_nl80211_data *drv) -+{ -+ union wpa_event_data data = {}; -+ -+ wpa_printf(MSG_DEBUG, "nl80211: CCA completed"); -+ -+ wpa_supplicant_event(drv->ctx, EVENT_CCA_NOTIFY, &data); -+} -+#endif - - static void - nl80211_control_port_frame_tx_status(struct wpa_driver_nl80211_data *drv, -@@ -3135,6 +3184,20 @@ static void do_process_drv_event(struct - case NL80211_CMD_UPDATE_HE_MUEDCA_PARAMS: - nl80211_update_muedca_params_event(drv, tb); - break; -+#ifdef CONFIG_IEEE80211AX -+ case NL80211_CMD_OBSS_COLOR_COLLISION: -+ mlme_event_obss_color_collision(drv, tb); -+ break; -+ case NL80211_CMD_COLOR_CHANGE_ANNOUNCEMENT_STARTED: -+ mlme_event_color_change_announcement_started(drv); -+ break; -+ case NL80211_CMD_COLOR_CHANGE_ANNOUNCEMENT_ABORTED: -+ mlme_event_color_change_announcement_aborted(drv); -+ break; -+ case NL80211_CMD_COLOR_CHANGE_ANNOUNCEMENT_COMPLETED: -+ mlme_event_color_change_announcement_completed(drv); -+ break; -+#endif - default: - wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event " - "(cmd=%d)", cmd); diff --git a/feeds/ipq95xx/hostapd/patches/f00-006-bss_coloring-allow-using-a-random-starting-color.patch b/feeds/ipq95xx/hostapd/patches/f00-006-bss_coloring-allow-using-a-random-starting-color.patch deleted file mode 100644 index 685aa6aae..000000000 --- a/feeds/ipq95xx/hostapd/patches/f00-006-bss_coloring-allow-using-a-random-starting-color.patch +++ /dev/null @@ -1,44 +0,0 @@ -From: John Crispin -Subject: [PATCH V4 6/6] bss_coloring: allow using a random starting color -Date: Wed, 26 Aug 2020 08:22:16 +0200 - - -Enhance the possible values for he_bss_color. Anything greater than 63 will -make hostapd choose a random color. - -Signed-off-by: John Crispin ---- - hostapd/config_file.c | 7 +++++-- - hostapd/hostapd.conf | 5 ++++- - 2 files changed, 9 insertions(+), 3 deletions(-) - ---- a/hostapd/config_file.c -+++ b/hostapd/config_file.c -@@ -3367,8 +3367,11 @@ static int hostapd_config_fill(struct ho - } else if (os_strcmp(buf, "he_ul_mumimo") == 0) { - conf->he_phy_capab.he_ul_mumimo = atoi(pos); - } else if (os_strcmp(buf, "he_bss_color") == 0) { -- conf->he_op.he_bss_color = atoi(pos) & 0x3f; -- conf->he_op.he_bss_color_disabled = 0; -+ conf->he_op.he_bss_color = atoi(pos); -+ if (conf->he_op.he_bss_color > 63) -+ conf->he_op.he_bss_color = (os_random() % 63) + 1; -+ if (conf->he_op.he_bss_color) -+ conf->he_op.he_bss_color_disabled = 0; - } else if (os_strcmp(buf, "he_bss_color_partial") == 0) { - conf->he_op.he_bss_color_partial = atoi(pos); - } else if (os_strcmp(buf, "he_default_pe_duration") == 0) { ---- a/hostapd/hostapd.conf -+++ b/hostapd/hostapd.conf -@@ -810,7 +810,10 @@ wmm_ac_vo_acm=0 - # 1 = supported - #he_mu_beamformer=1 - --# he_bss_color: BSS color (1-63) -+# he_bss_color: -+# 0 = disable -+# 1-63 = pre-defined color -+# 64+ = random color - #he_bss_color=1 - - # he_bss_color_partial: BSS color AID equation diff --git a/feeds/ipq95xx/hostapd/patches/f00-007-bss_coloring-add-intelligence-color-choose-in-CCA.patch b/feeds/ipq95xx/hostapd/patches/f00-007-bss_coloring-add-intelligence-color-choose-in-CCA.patch deleted file mode 100644 index 4bfdb3817..000000000 --- a/feeds/ipq95xx/hostapd/patches/f00-007-bss_coloring-add-intelligence-color-choose-in-CCA.patch +++ /dev/null @@ -1,126 +0,0 @@ -From d0d7cc4647ecad26b7bf04e39a4e9403cab68a48 Mon Sep 17 00:00:00 2001 -From: Karthikeyan Periyasamy -Date: Sat, 15 Aug 2020 18:47:26 +0530 -Subject: [PATCH] hostapd: Add intelligence color choose in CCA - -Gather color information of the neighbor APs and choose available -free color after go through the neighbor colors to minimise the color collision - -Signed-off-by: Karthikeyan Periyasamy ---- - src/ap/ap_list.c | 29 +++++++++++++++++++++++++ - src/ap/ap_list.h | 7 ++++++ - src/ap/hostapd.c | 66 +++++++++++++++++++++++++++++--------------------------- - 3 files changed, 70 insertions(+), 32 deletions(-) - ---- a/src/ap/ap_list.c -+++ b/src/ap/ap_list.c -@@ -174,6 +174,7 @@ void ap_list_process_beacon(struct hosta - struct ap_info *ap; - int new_ap = 0; - int set_beacon = 0; -+ u32 he_operation; - - if (iface->conf->ap_table_max_size < 1) - return; -@@ -210,6 +211,17 @@ void ap_list_process_beacon(struct hosta - else - ap->ht_support = 0; - -+ if (iface->conf->ieee80211ax && -+ elems->he_operation) { -+ he_operation = *(u32 *)elems->he_operation; -+ -+ if (!(he_operation & HE_OPERATION_BSS_COLOR_DISABLED)) -+ ap->color = (he_operation & HE_OPERATION_BSS_COLOR_MASK) >> -+ HE_OPERATION_BSS_COLOR_OFFSET; -+ else -+ ap->color = 0; -+ } -+ - os_get_reltime(&ap->last_beacon); - - if (!new_ap && ap != iface->ap_list) { -@@ -295,6 +307,21 @@ void ap_list_timer(struct hostapd_iface - ieee802_11_update_beacons(iface); - } - -+u64 ap_list_get_color(struct hostapd_iface *iface) -+{ -+ u64 used_color_bitmap = 0; -+ struct ap_info *ap; -+ -+ if (!iface->ap_list) -+ return used_color_bitmap; -+ -+ ap = iface->ap_list; -+ while (ap != NULL) { -+ used_color_bitmap |= (u64)1 << ap->color; -+ ap = ap->next; -+ } -+ return used_color_bitmap; -+} - - int ap_list_init(struct hostapd_iface *iface) - { ---- a/src/ap/ap_list.h -+++ b/src/ap/ap_list.h -@@ -25,6 +25,7 @@ struct ap_info { - int channel; - - int ht_support; -+ u8 color; - - struct os_reltime last_beacon; - }; -@@ -40,6 +41,7 @@ void ap_list_process_beacon(struct hosta - int ap_list_init(struct hostapd_iface *iface); - void ap_list_deinit(struct hostapd_iface *iface); - void ap_list_timer(struct hostapd_iface *iface); -+u64 ap_list_get_color(struct hostapd_iface *iface); - #else /* NEED_AP_MLME */ - static inline int ap_list_init(struct hostapd_iface *iface) - { -@@ -53,6 +55,11 @@ static inline void ap_list_deinit(struct - static inline void ap_list_timer(struct hostapd_iface *iface) - { - } -+ -+static u64 ap_list_get_color(struct hostapd_iface *iface) -+{ -+ return 0; -+} - #endif /* NEED_AP_MLME */ - - #endif /* AP_LIST_H */ ---- a/src/ap/hostapd.c -+++ b/src/ap/hostapd.c -@@ -3769,6 +3769,7 @@ hostapd_switch_color_timeout_handler(voi - struct cca_settings settings; - struct os_time now; - int i, r, b, ret; -+ u64 neighbor_color; - - if (os_get_time(&now)) - return; -@@ -3777,11 +3778,16 @@ hostapd_switch_color_timeout_handler(voi - if (now.sec - hapd->last_color_collision.sec > 50) - return; - -- r = os_random() % HE_OPERATION_BSS_COLOR_MAX; -- for (i = 0; i < HE_OPERATION_BSS_COLOR_MAX; i++) { -- if (r && (hapd->color_collision_bitmap & (1 << r)) == 0) -+ neighbor_color = ap_list_get_color(hapd->iface); -+ neighbor_color |= hapd->color_collision_bitmap; -+ -+ r = os_random() % HE_OPERATION_BSS_COLOR_MAX - 1; -+ r++; -+ for (i = 1; i < HE_OPERATION_BSS_COLOR_MAX; i++) { -+ if ((neighbor_color & (1 << r)) == 0) - break; -- r = (r + 1) % HE_OPERATION_BSS_COLOR_MAX; -+ r = r % HE_OPERATION_BSS_COLOR_MAX - 1; -+ r++; - } - if (i == HE_OPERATION_BSS_COLOR_MAX) { - /* there are no free colors so turn bss coloring off */ diff --git a/feeds/ipq95xx/hostapd/patches/f00-008-bss_coloring_add_support_to_change_bss_color_by_user.patch b/feeds/ipq95xx/hostapd/patches/f00-008-bss_coloring_add_support_to_change_bss_color_by_user.patch deleted file mode 100644 index d2982dc06..000000000 --- a/feeds/ipq95xx/hostapd/patches/f00-008-bss_coloring_add_support_to_change_bss_color_by_user.patch +++ /dev/null @@ -1,194 +0,0 @@ -From baf3a982caee59ec08602a9e981d6742abc4fc7b Mon Sep 17 00:00:00 2001 -From: Lavanya Suresh -Date: Mon, 28 Sep 2020 23:21:43 +0530 -Subject: [PATCH] hostapd: Add support to change bss color by user - - -hostpad_cli command is added to change bss color in runtime, -for testing purpose. hostapd_cli status can be used to check -updated color. - -Usage: hostapd_cli color_change - -Signed-off-by: Lavanya Suresh ---- - hostapd/ctrl_iface.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ - hostapd/hostapd_cli.c | 23 +++++++++++++++++++++++ - src/ap/ctrl_iface_ap.c | 6 ++++-- - src/ap/hostapd.c | 4 ++-- - src/ap/hostapd.h | 3 ++- - 5 files changed, 76 insertions(+), 5 deletions(-) - -Index: hostapd-2021-12-13-b26f5c0f/hostapd/ctrl_iface.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/hostapd/ctrl_iface.c -+++ hostapd-2021-12-13-b26f5c0f/hostapd/ctrl_iface.c -@@ -2781,6 +2781,59 @@ static int hostapd_ctrl_check_freq_param - } - #endif /* NEED_AP_MLME */ - -+static int hostapd_ctrl_iface_color_change(struct hostapd_iface *iface, -+ char *pos) -+{ -+#ifdef NEED_AP_MLME -+ struct cca_settings settings; -+ struct hostapd_data *hapd = iface->bss[0]; -+ int ret, color; -+ unsigned int i; -+ char *end; -+ -+ os_memset(&settings, 0, sizeof(settings)); -+ color = strtol(pos, &end, 10); -+ if (pos == end || color < 0 || color > 63) { -+ wpa_printf(MSG_ERROR, "colorchange: invalid color provided"); -+ return -1; -+ } -+ -+ if (color == iface->conf->he_op.he_bss_color) { -+ wpa_printf(MSG_ERROR, "colorchange: provided color is already set"); -+ return -1; -+ } -+ -+ if (hapd->cca_in_progress) { -+ wpa_printf(MSG_ERROR, "colorchange: cca is in progress, so color change is now allowed"); -+ return -1; -+ } -+ -+ for (i = 0; i < iface->num_bss; i++) { -+ struct hostapd_data *bss = iface->bss[i]; -+ hostapd_cleanup_cca_params(bss); -+ bss->cca_color = color; -+ bss->cca_count = 10; -+ -+ if (hostapd_fill_cca_settings(bss, &settings)) { -+ wpa_printf(MSG_DEBUG, "hostapd fill cca settings failed for color: %d\n", color); -+ hostapd_cleanup_cca_params(bss); -+ continue; -+ } -+ -+ wpa_printf(MSG_DEBUG, "Setting user selected color: %d\n", color); -+ ret = hostapd_drv_switch_color(bss, &settings); -+ free_beacon_data(&settings.beacon_cca); -+ free_beacon_data(&settings.beacon_after); -+ -+ if (ret) -+ hostapd_cleanup_cca_params(bss); -+ } -+ -+ return 0; -+#else /* NEED_AP_MLME */ -+ return -1; -+#endif /* NEED_AP_MLME */ -+} - - static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface, - char *pos) -@@ -3813,6 +3866,9 @@ static int hostapd_ctrl_iface_receive_pr - } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) { - if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12)) - reply_len = -1; -+ } else if (os_strncmp(buf, "COLOR_CHANGE ", 12) == 0) { -+ if (hostapd_ctrl_iface_color_change(hapd->iface, buf + 12)) -+ reply_len = -1; - } else if (os_strncmp(buf, "VENDOR ", 7) == 0) { - reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply, - reply_size); -Index: hostapd-2021-12-13-b26f5c0f/hostapd/hostapd_cli.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/hostapd/hostapd_cli.c -+++ hostapd-2021-12-13-b26f5c0f/hostapd/hostapd_cli.c -@@ -1150,6 +1150,27 @@ static int hostapd_cli_cmd_fst(struct wp - } - #endif /* CONFIG_FST */ - -+static int hostapd_cli_cmd_color_change(struct wpa_ctrl *ctrl, -+ int argc, char *argv[]) -+{ -+ char cmd[256]; -+ int res; -+ -+ if (argc < 1) { -+ printf("Invalid color_change command: no argument given \n" -+ "usage: \n"); -+ return -1; -+ } -+ -+ res = os_snprintf(cmd, sizeof(cmd), "COLOR_CHANGE %s", -+ argv[0]); -+ if (os_snprintf_error(sizeof(cmd), res)) { -+ printf("Too long CHAN_CHANGE command\n"); -+ return -1; -+ } -+ -+ return wpa_ctrl_command(ctrl, cmd); -+} - - static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl, - int argc, char *argv[]) -@@ -1646,6 +1667,8 @@ static const struct hostapd_cli_cmd host - " [sec_channel_offset=] [center_freq1=]\n" - " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]\n" - " = initiate channel switch announcement" }, -+ { "color_change", hostapd_cli_cmd_color_change, NULL, -+ " = initiate bss color change to set user color\n" }, - { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif, NULL, - " \n" - " = send WNM-Notification Subscription Remediation Request" }, -Index: hostapd-2021-12-13-b26f5c0f/src/ap/ctrl_iface_ap.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/ap/ctrl_iface_ap.c -+++ hostapd-2021-12-13-b26f5c0f/src/ap/ctrl_iface_ap.c -@@ -1063,10 +1063,12 @@ int hostapd_ctrl_iface_status(struct hos - ret = os_snprintf(buf + len, buflen - len, - "he_oper_chwidth=%d\n" - "he_oper_centr_freq_seg0_idx=%d\n" -- "he_oper_centr_freq_seg1_idx=%d\n", -+ "he_oper_centr_freq_seg1_idx=%d\n" -+ "he_bss_color=%d\n", - iface->conf->he_oper_chwidth, - iface->conf->he_oper_centr_freq_seg0_idx, -- iface->conf->he_oper_centr_freq_seg1_idx); -+ iface->conf->he_oper_centr_freq_seg1_idx, -+ iface->conf->he_op.he_bss_color); - if (os_snprintf_error(buflen - len, ret)) - return len; - len += ret; -Index: hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/ap/hostapd.c -+++ hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.c -@@ -3429,7 +3429,7 @@ int hostapd_csa_in_progress(struct hosta - - #ifdef NEED_AP_MLME - --static void free_beacon_data(struct beacon_data *beacon) -+void free_beacon_data(struct beacon_data *beacon) - { - os_free(beacon->head); - beacon->head = NULL; -@@ -3834,7 +3834,7 @@ void hostapd_cleanup_cca_params(struct h - } - - --static int hostapd_fill_cca_settings(struct hostapd_data *hapd, -+int hostapd_fill_cca_settings(struct hostapd_data *hapd, - struct cca_settings *settings) - { - struct hostapd_iface *iface = hapd->iface; -Index: hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.h -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/ap/hostapd.h -+++ hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.h -@@ -680,10 +680,12 @@ int hostapd_owe_trans_get_info(struct ho - void hostapd_ocv_check_csa_sa_query(void *eloop_ctx, void *timeout_ctx); - int hostapd_check_max_sta(struct hostapd_data *hapd); - -+void free_beacon_data(struct beacon_data *beacon); - - #ifdef CONFIG_IEEE80211AX - void hostapd_switch_color(struct hostapd_data *hapd, u64 bitmap); - void hostapd_cleanup_cca_params(struct hostapd_data *hapd); -+int hostapd_fill_cca_settings(struct hostapd_data *hapd, struct cca_settings *settings); - #endif - - /* utils.c */ diff --git a/feeds/ipq95xx/hostapd/patches/f00-009-add-bcca-IE-with-countdown-zero-in-color-change-beacon.patch b/feeds/ipq95xx/hostapd/patches/f00-009-add-bcca-IE-with-countdown-zero-in-color-change-beacon.patch deleted file mode 100644 index 59cbc2d8b..000000000 --- a/feeds/ipq95xx/hostapd/patches/f00-009-add-bcca-IE-with-countdown-zero-in-color-change-beacon.patch +++ /dev/null @@ -1,96 +0,0 @@ -From f2cc86f874e09b0b1d1247de98f1720aa51080d8 Mon Sep 17 00:00:00 2001 -From: Lavanya Suresh -Date: Tue, 6 Oct 2020 21:37:04 +0530 -Subject: [PATCH] hostapd: Add BCCA IE with countdown zero - -During BCCA, BCCA IE with countdown zero has to be added -in the beacon in which new color is updated. Remove BCCA -IE in the beacon template after color change is -completed. - -Signed-off-by: Lavanya Suresh ---- - src/ap/drv_callbacks.c | 6 ++++++ - src/ap/hostapd.c | 10 ++++++++-- - src/ap/hostapd.h | 1 + - src/ap/ieee802_11_he.c | 2 +- - 4 files changed, 16 insertions(+), 3 deletions(-) - ---- a/src/ap/drv_callbacks.c -+++ b/src/ap/drv_callbacks.c -@@ -1802,14 +1802,29 @@ static void hostapd_event_bss_color_coll - - static void hostapd_event_cca(struct hostapd_data *hapd, enum wpa_event_type event) - { -+ int b, err; -+ - switch (event) { - case EVENT_CCA_STARTED_NOTIFY: - wpa_printf(MSG_DEBUG, "CCA started on %s", hapd->conf->iface); - break; - case EVENT_CCA_NOTIFY: - wpa_printf(MSG_DEBUG, "CCA finished on %s (new color: %d)", hapd->conf->iface, hapd->cca_color); -- hapd->iface->conf->he_op.he_bss_color = hapd->cca_color; -- hostapd_cleanup_cca_params(hapd); -+ -+ for (b = 0; b < hapd->iface->num_bss; b++) { -+ if (hapd->iface->bss[b]->cca_color != 0) { -+ hapd->iface->conf->he_op.he_bss_color = hapd->iface->bss[b]->cca_color; -+ hapd->iface->bss[b]->cca_in_progress = 0; -+ err = ieee802_11_set_beacon(hapd->iface->bss[b]); -+ if (err) { -+ wpa_printf(MSG_ERROR, "Failed to remove BCCA IE"); -+ hapd->iface->bss[b]->cca_in_progress = 1; -+ } -+ else -+ hostapd_cleanup_cca_params(hapd->iface->bss[b]); -+ } -+ } -+ - break; - case EVENT_CCA_ABORTED_NOTIFY: - wpa_printf(MSG_DEBUG, "CCA aborted on %s for cca_color: %d", hapd->conf->iface, hapd->cca_color); ---- a/src/ap/hostapd.c -+++ b/src/ap/hostapd.c -@@ -3742,12 +3742,18 @@ int hostapd_fill_cca_settings(struct hos - - old_color = iface->conf->he_op.he_bss_color; - iface->conf->he_op.he_bss_color = hapd->cca_color; -+ -+ settings->cca_count = hapd->cca_count; -+ settings->cca_color = hapd->cca_color; -+ hapd->cca_count = 0; -+ hapd->cca_zero_count = 1; -+ - ret = hostapd_build_beacon_data(hapd, &settings->beacon_after); - iface->conf->he_op.he_bss_color = old_color; - -- settings->cca_count = hapd->cca_count; -- settings->cca_color = hapd->cca_color, -+ hapd->cca_count = settings->cca_count; - hapd->cca_in_progress = 1; -+ hapd->cca_zero_count = 0; - - ret = hostapd_build_beacon_data(hapd, &settings->beacon_cca); - if (ret) { ---- a/src/ap/hostapd.h -+++ b/src/ap/hostapd.h -@@ -298,6 +298,7 @@ struct hostapd_data { - - #ifdef CONFIG_IEEE80211AX - int cca_in_progress; -+ int cca_zero_count; - u8 cca_count; - u8 cca_color; - unsigned int cca_c_off_beacon; ---- a/src/ap/ieee802_11_he.c -+++ b/src/ap/ieee802_11_he.c -@@ -496,7 +496,7 @@ int hostapd_get_he_twt_responder(struct - - u8 * hostapd_eid_cca(struct hostapd_data *hapd, u8 *eid) - { -- if (!hapd->cca_in_progress) -+ if (!hapd->cca_in_progress && !hapd->cca_zero_count) - return eid; - *eid++ = WLAN_EID_EXTENSION; - *eid++ = 3; diff --git a/feeds/ipq95xx/hostapd/patches/f00-010-bss_coloring-check-free-color-periodically.patch b/feeds/ipq95xx/hostapd/patches/f00-010-bss_coloring-check-free-color-periodically.patch deleted file mode 100644 index 87b767a05..000000000 --- a/feeds/ipq95xx/hostapd/patches/f00-010-bss_coloring-check-free-color-periodically.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 7c0383bf8883e2bad9c7beb47712105be38b5427 Mon Sep 17 00:00:00 2001 -From: Lavanya Suresh -Date: Wed, 7 Oct 2020 13:29:03 +0530 -Subject: [PATCH] hostapd: Check free colors periodically if no new color is - available - -In case of collision, if all the colors are in use, start dot11APcollision -timer(50s) and check for new color after timeout. - -Signed-off-by: Lavanya Suresh ---- - src/ap/hostapd.c | 20 +++++++++++++++++--- - src/ap/hostapd.h | 1 + - 2 files changed, 18 insertions(+), 3 deletions(-) - ---- a/src/ap/hostapd.c -+++ b/src/ap/hostapd.c -@@ -3781,11 +3781,12 @@ hostapd_switch_color_timeout_handler(voi - return; - - /* check if there has been a recent collision */ -- if (now.sec - hapd->last_color_collision.sec > 50) -+ if (now.sec - hapd->last_color_collision.sec > 50 && !hapd->no_free_color) - return; - - neighbor_color = ap_list_get_color(hapd->iface); -- neighbor_color |= hapd->color_collision_bitmap; -+ if (!hapd->no_free_color) -+ neighbor_color |= hapd->color_collision_bitmap; - - r = os_random() % HE_OPERATION_BSS_COLOR_MAX - 1; - r++; -@@ -3797,13 +3798,26 @@ hostapd_switch_color_timeout_handler(voi - } - if (i == HE_OPERATION_BSS_COLOR_MAX) { - /* there are no free colors so turn bss coloring off */ -- wpa_printf(MSG_INFO, "no free colors left, turning of BSS coloring"); -+ wpa_printf(MSG_INFO, "no free colors left, turning off BSS coloring"); - hapd->iface->conf->he_op.he_bss_color_disabled = 1; -+ hapd->no_free_color = 1; - for (b = 0; b < hapd->iface->num_bss; b++) - ieee802_11_set_beacon(hapd->iface->bss[b]); -+ -+ /* Enabling for next check after timeout*/ -+ hapd->iface->conf->he_op.he_bss_color_disabled = 0; -+ -+ /* start timer for DOT11BSS_COLOR_COLLISION_AP_PERIOD, and check free color on timeout */ -+ if (!eloop_is_timeout_registered(hostapd_switch_color_timeout_handler, hapd, NULL)) -+ eloop_register_timeout(DOT11BSS_COLOR_COLLISION_AP_PERIOD, 0, -+ hostapd_switch_color_timeout_handler, hapd, NULL); -+ - return; - } - -+ if (hapd->no_free_color) -+ hapd->no_free_color = 0; -+ - for (b = 0; b < hapd->iface->num_bss; b++) { - struct hostapd_data *bss = hapd->iface->bss[b]; - ---- a/src/ap/hostapd.h -+++ b/src/ap/hostapd.h -@@ -299,6 +299,7 @@ struct hostapd_data { - #ifdef CONFIG_IEEE80211AX - int cca_in_progress; - int cca_zero_count; -+ int no_free_color; - u8 cca_count; - u8 cca_color; - unsigned int cca_c_off_beacon; diff --git a/feeds/ipq95xx/hostapd/patches/g00-003-hostapd-fix-int-in-bool-context-Werror.patch b/feeds/ipq95xx/hostapd/patches/g00-003-hostapd-fix-int-in-bool-context-Werror.patch deleted file mode 100644 index 277cd1e15..000000000 --- a/feeds/ipq95xx/hostapd/patches/g00-003-hostapd-fix-int-in-bool-context-Werror.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 93f695bfe52dd725841fcca71ed4e14e9a90e1dc Mon Sep 17 00:00:00 2001 -From: Abinaya Kalaiselvan -Date: Wed, 25 Nov 2020 19:58:58 +0530 -Subject: [PATCH] hostapd: fix int-in-bool-context Werror - -Add changes to fix the below compilation error. - -./src/rsn_supp/wpa.c:621:35: error: ?: using integer constants -in boolean context, the expression will always evaluate -to 'true' [-Werror=int-in-bool-context] - -Signed-off-by: Abinaya Kalaiselvan ---- - src/rsn_supp/wpa.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c -index 3205527..88c1e3e 100644 ---- a/src/rsn_supp/wpa.c -+++ b/src/rsn_supp/wpa.c -@@ -615,10 +615,11 @@ static int wpa_handle_ext_key_id(struct wpa_sm *sm, - { - if (sm->ext_key_id) { - u16 key_id; -+ u8 use_ext_key_id; - - if (!kde->key_id) { -- wpa_msg(sm->ctx->msg_ctx, -- sm->use_ext_key_id ? MSG_INFO : MSG_DEBUG, -+ use_ext_key_id = sm->use_ext_key_id ? MSG_INFO : MSG_DEBUG; -+ wpa_msg(sm->ctx->msg_ctx, use_ext_key_id, - "RSN: No Key ID in Extended Key ID handshake"); - sm->keyidx_active = 0; - return sm->use_ext_key_id ? -1 : 0; --- -2.7.4 - diff --git a/feeds/ipq95xx/hostapd/patches/g00-004-hostapd-Initilize-chan-for-second-80-mhz-to-zero.patch b/feeds/ipq95xx/hostapd/patches/g00-004-hostapd-Initilize-chan-for-second-80-mhz-to-zero.patch deleted file mode 100644 index 0efa99e55..000000000 --- a/feeds/ipq95xx/hostapd/patches/g00-004-hostapd-Initilize-chan-for-second-80-mhz-to-zero.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 789bc909ea59671e43fa89e539cca3b8970275fb Mon Sep 17 00:00:00 2001 -From: Muna Sinada -Date: Mon, 30 Nov 2020 20:37:14 -0800 -Subject: [PATCH] hostapd: Initilize chan for second 80 mhz to zero - -CSA updates freq for CSA beacons and after CSA beacons utilizing -hostapd_change_config_freq(). In the case of 80+80 MHz, there are two -channels store, one for the 80 MHz and the second 80 MHz. In non -80+80 cases, the second channel needs to be initialized to zero or -else garbage values are stored in place. - -Signed-off-by: Muna Sinada ---- - src/ap/hostapd.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c -index 346d83cfda91..fa46667017f4 100644 ---- a/src/ap/hostapd.c -+++ b/src/ap/hostapd.c -@@ -3455,7 +3455,7 @@ static int hostapd_change_config_freq(struct hostapd_data *hapd, - struct hostapd_freq_params *old_params) - { - int channel; -- u8 seg0, seg1; -+ u8 seg0, seg1 = 0; - struct hostapd_hw_modes *mode; - - if (!params->channel) { --- -2.7.4 - diff --git a/feeds/ipq95xx/hostapd/patches/h00-001-wpa_supplicant-add-mesh-ID-IE-only-for-mesh-mode.patch b/feeds/ipq95xx/hostapd/patches/h00-001-wpa_supplicant-add-mesh-ID-IE-only-for-mesh-mode.patch deleted file mode 100644 index a8df94092..000000000 --- a/feeds/ipq95xx/hostapd/patches/h00-001-wpa_supplicant-add-mesh-ID-IE-only-for-mesh-mode.patch +++ /dev/null @@ -1,33 +0,0 @@ -From ed96951a0e08771570c950f42ebfd49ff0511756 Mon Sep 17 00:00:00 2001 -From: Lavanya Suresh -Date: Thu, 3 Dec 2020 18:58:19 +0530 -Subject: [PATCH] wpa_supplicant: add mesh ID IE only for mesh mode - -Mesh ID IE is added in probe request frame irrespective -of mode. Added check to avoid adding this IE for non-mesh -modes. - -Signed-off-by: Lavanya Suresh ---- - wpa_supplicant/scan.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c -index b9e4162..9992e42 100644 ---- a/wpa_supplicant/scan.c -+++ b/wpa_supplicant/scan.c -@@ -611,7 +611,10 @@ static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s) - } - #endif /* CONFIG_P2P */ - -- wpa_supplicant_mesh_add_scan_ie(wpa_s, &extra_ie); -+#ifdef CONFIG_MESH -+ if (wpa_s->conf->ssid && wpa_s->conf->ssid->mode == WPAS_MODE_MESH) -+ wpa_supplicant_mesh_add_scan_ie(wpa_s, &extra_ie); -+#endif /* CONFIG_MESH */ - - #endif /* CONFIG_WPS */ - --- -2.7.4 - diff --git a/feeds/ipq95xx/hostapd/patches/h00-002-hostapd-Enable-HE40-support-in-2G-11s-mesh.patch b/feeds/ipq95xx/hostapd/patches/h00-002-hostapd-Enable-HE40-support-in-2G-11s-mesh.patch deleted file mode 100644 index 2cabb0403..000000000 --- a/feeds/ipq95xx/hostapd/patches/h00-002-hostapd-Enable-HE40-support-in-2G-11s-mesh.patch +++ /dev/null @@ -1,189 +0,0 @@ -From 42bd9677183c6a71c56c9f36d32e2fb626fdb535 Mon Sep 17 00:00:00 2001 -From: P Praneesh -Date: Tue, 8 Dec 2020 00:28:00 +0530 -Subject: [PATCH] hostapd: Enable HE40 support in 2G 11s mesh - -This patch adds support for HE40 in 2G 11s mesh if -the driver advertise HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G -support in HE capability. - -Signed-off-by: P Praneesh ---- - wpa_supplicant/wpa_supplicant.c | 30 ++++++++++++++++++++++++++++++ - 1 file changed, 30 insertions(+) - -Index: hostapd-2021-02-18/wpa_supplicant/wpa_supplicant.c -=================================================================== ---- hostapd-2021-02-18.orig/wpa_supplicant/wpa_supplicant.c -+++ hostapd-2021-02-18/wpa_supplicant/wpa_supplicant.c -@@ -2378,6 +2378,57 @@ static int drv_supports_vht(struct wpa_s - return mode->vht_capab != 0; - } - -+static void ibss_mesh_setup_2G_he40(struct hostapd_freq_params *freq, -+ struct hostapd_hw_modes *mode, -+ struct wpa_supplicant *wpa_s, -+ const struct wpa_ssid *ssid, -+ int ieee80211_mode) -+{ -+ struct wpa_scan_results *scan_res; -+ int he40plus2G[] = { 2412, 2417, 2422, 2427, 2432, 2437}; -+ int i, res; -+ u8 pri_chan, sec_chan; -+ -+ freq->vht_enabled = vht_supported(mode); -+ freq->sec_channel_offset = -1; -+ -+ if (mode->he_capab[ieee80211_mode].phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] & -+ HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G) -+ freq->bandwidth = 40; -+ -+ /* Setting channel offset as 1 for channel 1 to 6 and -1 for -+ * channel 7 to 11 -+ */ -+ for (i = 0; i < ARRAY_SIZE(he40plus2G); i++) { -+ if (freq->freq == he40plus2G[i]) -+ freq->sec_channel_offset = 1; -+ } -+ -+ freq->center_freq1 = freq->freq + freq->sec_channel_offset * 10; -+ freq->center_freq2 = 0; -+ -+ if (ssid->disable_40mhz_scan) { -+ wpa_printf(MSG_DEBUG, "IBSSS: 40MHz Coex scan disabled"); -+ return; -+ } -+ -+ scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0); -+ if (scan_res == NULL) -+ goto HE20; -+ -+ pri_chan = freq->channel; -+ sec_chan = pri_chan + freq->sec_channel_offset * 4; -+ res = check_40mhz_2g4(mode, scan_res, pri_chan, sec_chan); -+ wpa_scan_results_free(scan_res); -+ if (!res) -+ goto HE20; -+ return; -+HE20: -+ freq->sec_channel_offset = 0; -+ freq->bandwidth = 20; -+ freq->center_freq1 = freq->freq + freq->sec_channel_offset * 10; -+} -+ - static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode) - { - int i; -@@ -2498,6 +2549,11 @@ void ibss_mesh_setup_freq(struct wpa_sup - else - #endif /* CONFIG_HE_OVERRIDES */ - freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported; -+ -+ if (freq->he_enabled) -+ ibss_mesh_setup_2G_he40(freq, mode, wpa_s, -+ ssid, ieee80211_mode); -+ return; - } - - for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) { -Index: hostapd-2021-02-18/src/drivers/driver.h -=================================================================== ---- hostapd-2021-02-18.orig/src/drivers/driver.h -+++ hostapd-2021-02-18/src/drivers/driver.h -@@ -1203,6 +1203,11 @@ struct wpa_driver_associate_params { - * 2 = both hunting-and-pecking loop and hash-to-element enabled - */ - int sae_pwe; -+ -+ /** -+ * Disable HE40MHz coexistence scan -+ */ -+ int disable_40mhz_scan; - }; - - enum hide_ssid { -Index: hostapd-2021-02-18/wpa_supplicant/config.c -=================================================================== ---- hostapd-2021-02-18.orig/wpa_supplicant/config.c -+++ hostapd-2021-02-18/wpa_supplicant/config.c -@@ -2804,6 +2804,7 @@ static const struct parse_data ssid_fiel - { INT_RANGE(beacon_prot, 0, 1) }, - { INT_RANGE(transition_disable, 0, 255) }, - { INT_RANGE(sae_pk, 0, 2) }, -+ { INT_RANGE(disable_40mhz_scan, 0, 1)}, - }; - - #undef OFFSET -Index: hostapd-2021-02-18/wpa_supplicant/config_file.c -=================================================================== ---- hostapd-2021-02-18.orig/wpa_supplicant/config_file.c -+++ hostapd-2021-02-18/wpa_supplicant/config_file.c -@@ -885,7 +885,7 @@ static void wpa_config_write_network(FIL - #ifdef CONFIG_HE_OVERRIDES - INT(disable_he); - #endif /* CONFIG_HE_OVERRIDES */ -- -+ INT(disable_40mhz_scan); - #undef STR - #undef INT - #undef INT_DEF -Index: hostapd-2021-02-18/wpa_supplicant/config_ssid.h -=================================================================== ---- hostapd-2021-02-18.orig/wpa_supplicant/config_ssid.h -+++ hostapd-2021-02-18/wpa_supplicant/config_ssid.h -@@ -1165,6 +1165,11 @@ struct wpa_ssid { - * 2 = both hunting-and-pecking loop and hash-to-element enabled - */ - int sae_pwe; -+ -+ /** -+ * disable_40mhz_scan - Disable 40MHz coex scan -+ */ -+ int disable_40mhz_scan; - }; - - #endif /* CONFIG_SSID_H */ -Index: hostapd-2021-02-18/wpa_supplicant/wpa_cli.c -=================================================================== ---- hostapd-2021-02-18.orig/wpa_supplicant/wpa_cli.c -+++ hostapd-2021-02-18/wpa_supplicant/wpa_cli.c -@@ -1482,7 +1482,8 @@ static const char *network_fields[] = { - #ifdef CONFIG_HS20 - "update_identifier", - #endif /* CONFIG_HS20 */ -- "mac_addr", "pbss", "wps_disabled" -+ "mac_addr", "pbss", "wps_disabled", -+ "disable_40mhz_scan", - }; - - -Index: hostapd-2021-02-18/wpa_supplicant/wpa_supplicant.conf -=================================================================== ---- hostapd-2021-02-18.orig/wpa_supplicant/wpa_supplicant.conf -+++ hostapd-2021-02-18/wpa_supplicant/wpa_supplicant.conf -@@ -158,6 +158,9 @@ ap_scan=1 - # 1 = deny unless in accept list - macaddr_acl=0 - -+# Disable 40MHz co-existence scan in Mesh -+#disable_40mhz_scan=1 -+ - # Accept/deny lists are read from separate files (containing list of - # MAC addresses, one per line). Use absolute path name to make sure that the - # files can be read on SIGHUP configuration reloads. -@@ -1983,6 +1986,15 @@ network={ - psk="very secret passphrase" - } - -+# Disable 40MHz Co-existence scan in mesh -+network={ -+ ssid="OpenWrt" -+ key_mgmt=SAE -+ mode=5 -+ frequency=2437 -+ psk="1234567890" -+ disable_40mhz_scan=1 -+} - - # Catch all example that allows more or less all configuration modes - network={ diff --git a/feeds/ipq95xx/hostapd/patches/h00-003-hostapd-allow-AP_VLAN-creation-for-dynamic-VLAN.patch b/feeds/ipq95xx/hostapd/patches/h00-003-hostapd-allow-AP_VLAN-creation-for-dynamic-VLAN.patch deleted file mode 100644 index 293d39e93..000000000 --- a/feeds/ipq95xx/hostapd/patches/h00-003-hostapd-allow-AP_VLAN-creation-for-dynamic-VLAN.patch +++ /dev/null @@ -1,95 +0,0 @@ -commit 120f4976cdb83e421459242db7a1b41c16b772f6 -Author: Sathishkumar Muruganandam -Date: Wed Jan 13 16:51:07 2021 +0530 - - hostapd: allow AP_VLAN creation with wpa_psk_file having vlan_id - - When WPA_DRIVER_FLAGS_VLAN_OFFLOAD is advertised from driver during - NSS offload enabled case, vlan_id is sent to mac80211 which is stored - in key_conf for dynamic VLAN support on NSS offload case. - - This flag blocks the AP_VLAN creation when using wpa_psk_file with - vlan_id which is needed for dynamic VLAN support on NSS offload case. - - Hence removing the check associated with _VLAN_OFFLOAD flag which is - advertised only when NSS offload is enabled to allow AP_VLAN creation. - - Signed-off-by: Sathishkumar Muruganandam - ---- a/src/ap/sta_info.c -+++ b/src/ap/sta_info.c -@@ -1060,8 +1060,7 @@ int ap_sta_bind_vlan(struct hostapd_data - if (sta->vlan_id == old_vlanid) - goto skip_counting; - -- if (sta->vlan_id > 0 && !vlan && -- !(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_VLAN_OFFLOAD)) { -+ if (sta->vlan_id > 0 && !vlan) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, "could not find VLAN for " - "binding station to (vlan_id=%d)", ---- a/src/ap/wpa_auth_glue.c -+++ b/src/ap/wpa_auth_glue.c -@@ -437,12 +437,8 @@ static int hostapd_wpa_auth_set_key(void - - if (vlan_id > 0) { - ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan, vlan_id); -- if (!ifname) { -- if (!(hapd->iface->drv_flags & -- WPA_DRIVER_FLAGS_VLAN_OFFLOAD)) -- return -1; -- ifname = hapd->conf->iface; -- } -+ if (!ifname) -+ return -1; - } - - #ifdef CONFIG_TESTING_OPTIONS -@@ -917,32 +913,27 @@ static int hostapd_wpa_auth_update_vlan( - #ifndef CONFIG_NO_VLAN - struct hostapd_data *hapd = ctx; - struct sta_info *sta; -+ struct vlan_description vlan_desc; - - sta = ap_get_sta(hapd, addr); - if (!sta) - return -1; - -- if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_VLAN_OFFLOAD)) { -- struct vlan_description vlan_desc; -- -- os_memset(&vlan_desc, 0, sizeof(vlan_desc)); -- vlan_desc.notempty = 1; -- vlan_desc.untagged = vlan_id; -- if (!hostapd_vlan_valid(hapd->conf->vlan, &vlan_desc)) { -- wpa_printf(MSG_INFO, -- "Invalid VLAN ID %d in wpa_psk_file", -- vlan_id); -- return -1; -- } -+ os_memset(&vlan_desc, 0, sizeof(vlan_desc)); -+ vlan_desc.notempty = 1; -+ vlan_desc.untagged = vlan_id; -+ if (!hostapd_vlan_valid(hapd->conf->vlan, &vlan_desc)) { -+ wpa_printf(MSG_INFO, -+ "Invalid VLAN ID %d in wpa_psk_file", -+ vlan_id); -+ return -1; -+ } - -- if (ap_sta_set_vlan(hapd, sta, &vlan_desc) < 0) { -- wpa_printf(MSG_INFO, -- "Failed to assign VLAN ID %d from wpa_psk_file to " -- MACSTR, vlan_id, MAC2STR(sta->addr)); -- return -1; -- } -- } else { -- sta->vlan_id = vlan_id; -+ if (ap_sta_set_vlan(hapd, sta, &vlan_desc) < 0) { -+ wpa_printf(MSG_INFO, -+ "Failed to assign VLAN ID %d from wpa_psk_file to " -+ MACSTR, vlan_id, MAC2STR(sta->addr)); -+ return -1; - } - - wpa_printf(MSG_INFO, diff --git a/feeds/ipq95xx/hostapd/patches/h00-004-hostapd-Add-support-for-beacon-tx-mode.patch b/feeds/ipq95xx/hostapd/patches/h00-004-hostapd-Add-support-for-beacon-tx-mode.patch deleted file mode 100644 index 09065f12b..000000000 --- a/feeds/ipq95xx/hostapd/patches/h00-004-hostapd-Add-support-for-beacon-tx-mode.patch +++ /dev/null @@ -1,279 +0,0 @@ -From a1d4da59739c2054eb46cf634320c8bd323a8069 Mon Sep 17 00:00:00 2001 -From: Maharaja Kennadyrajan -Date: Tue, 12 Jan 2021 18:12:37 +0530 -Subject: [PATCH] hostapd: Add support for beacon tx mode - -User can configure the beacon tx mode while bring-up the -AP via hostapd configuration and while bring-up MESH via -wpa_supplicant configuration. - -Use the below configuration in the hostapd/wpa_supplicant -to configure the beacon tx mode. - -"beacon_tx_mode=N", where N = 1 for STAGGERED beacon mode -and N = 2 for BURST beacon mode. - -Signed-off-by: Maharaja Kennadyrajan ---- - hostapd/config_file.c | 9 +++++++++ - src/ap/ap_config.c | 2 ++ - src/ap/ap_config.h | 1 + - src/ap/beacon.c | 2 ++ - src/ap/ctrl_iface_ap.c | 6 ++++-- - src/drivers/driver.h | 5 +++++ - src/drivers/driver_nl80211.c | 16 +++++++++++++++- - src/drivers/nl80211_copy.h | 4 ++++ - 8 files changed, 42 insertions(+), 3 deletions(-) - -Index: hostapd-2021-12-13-b26f5c0f/hostapd/config_file.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/hostapd/config_file.c -+++ hostapd-2021-12-13-b26f5c0f/hostapd/config_file.c -@@ -4621,6 +4621,15 @@ static int hostapd_config_fill(struct ho - bss->disable_11ac = !!atoi(pos); - } else if (os_strcmp(buf, "disable_11ax") == 0) { - bss->disable_11ax = !!atoi(pos); -+ } else if (os_strcmp(buf, "beacon_tx_mode") == 0) { -+ int val = atoi(pos); -+ -+ if (val < 0 || val > 2) { -+ wpa_printf(MSG_ERROR, "Line %d: invalid beacon_tx_mode %d", -+ line, val); -+ return 1; -+ } -+ bss->beacon_tx_mode = val; - #ifdef CONFIG_PASN - #ifdef CONFIG_TESTING_OPTIONS - } else if (os_strcmp(buf, "force_kdk_derivation") == 0) { -Index: hostapd-2021-12-13-b26f5c0f/src/ap/ap_config.h -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/ap/ap_config.h -+++ hostapd-2021-12-13-b26f5c0f/src/ap/ap_config.h -@@ -911,6 +911,7 @@ struct hostapd_bss_config { - u8 ext_capa[EXT_CAPA_MAX_LEN]; - - u8 rnr; -+ int beacon_tx_mode; - }; - - /** -Index: hostapd-2021-12-13-b26f5c0f/src/ap/beacon.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/ap/beacon.c -+++ hostapd-2021-12-13-b26f5c0f/src/ap/beacon.c -@@ -1779,6 +1779,8 @@ int ieee802_11_build_ap_params(struct ho - } - } - -+ params->beacon_tx_mode = hapd->conf->beacon_tx_mode; -+ - return 0; - } - -Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver.h -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/drivers/driver.h -+++ hostapd-2021-12-13-b26f5c0f/src/drivers/driver.h -@@ -1213,6 +1213,12 @@ struct wpa_driver_associate_params { - * Disable HE40MHz coexistence scan - */ - int disable_40mhz_scan; -+ /** -+ * Beacon Tx mode - To configure STAGGERED or BURST mode -+ * 1 = STAGGERED beacon tx mode -+ * 2 = BURST beacon tx mode -+ */ -+ int beacon_tx_mode; - }; - - enum hide_ssid { -@@ -1592,6 +1598,13 @@ struct wpa_driver_ap_params { - * Unsolicited broadcast Probe Response template length - */ - size_t unsol_bcast_probe_resp_tmpl_len; -+ -+ /** -+ * Beacon Tx mode - To configure STAGGERED or BURST mode -+ * 1 = STAGGERED beacon tx mode -+ * 2 = BURST beacon tx mode -+ */ -+ int beacon_tx_mode; - }; - - struct wpa_driver_mesh_bss_params { -@@ -1631,6 +1644,7 @@ struct wpa_driver_mesh_join_params { - unsigned int flags; - bool handle_dfs; - int mcast_rate; -+ int beacon_tx_mode; - }; - - struct wpa_driver_set_key_params { -Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/drivers/driver_nl80211.c -+++ hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211.c -@@ -4573,6 +4573,7 @@ static int wpa_driver_nl80211_set_ap(voi - wpa_printf(MSG_DEBUG, "nl80211: beacon_rate=%u", params->beacon_rate); - wpa_printf(MSG_DEBUG, "nl80211: rate_type=%d", params->rate_type); - wpa_printf(MSG_DEBUG, "nl80211: dtim_period=%d", params->dtim_period); -+ wpa_printf(MSG_DEBUG, "nl80211: beacon_tx_mode=%d", params->beacon_tx_mode); - wpa_printf(MSG_DEBUG, "nl80211: ssid=%s", - wpa_ssid_txt(params->ssid, params->ssid_len)); - if (!(msg = nl80211_bss_msg(bss, 0, cmd)) || -@@ -4584,7 +4585,9 @@ static int wpa_driver_nl80211_set_ap(voi - nl80211_put_beacon_rate(msg, drv->capa.flags, drv->capa.flags2, - params) || - nl80211_put_dtim_period(msg, params->dtim_period) || -- nla_put(msg, NL80211_ATTR_SSID, params->ssid_len, params->ssid)) -+ nla_put(msg, NL80211_ATTR_SSID, params->ssid_len, params->ssid) || -+ (params->beacon_tx_mode && -+ nla_put_u32(msg, NL80211_ATTR_BEACON_TX_MODE, params->beacon_tx_mode))) - goto fail; - if (params->proberesp && params->proberesp_len) { - wpa_hexdump(MSG_DEBUG, "nl80211: proberesp (offload)", -@@ -10648,7 +10651,9 @@ static int nl80211_join_mesh(struct i802 - nl80211_put_mesh_id(msg, params->meshid, params->meshid_len) || - nl80211_put_beacon_int(msg, params->beacon_int) || - nl80211_put_mcast_rate(msg, params->mcast_rate) || -- nl80211_put_dtim_period(msg, params->dtim_period)) -+ nl80211_put_dtim_period(msg, params->dtim_period) || -+ (params->beacon_tx_mode && -+ nla_put_u32(msg, NL80211_ATTR_BEACON_TX_MODE, params->beacon_tx_mode))) - goto fail; - - wpa_printf(MSG_DEBUG, " * flags=%08X", params->flags); -Index: hostapd-2021-12-13-b26f5c0f/src/drivers/nl80211_copy.h -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/drivers/nl80211_copy.h -+++ hostapd-2021-12-13-b26f5c0f/src/drivers/nl80211_copy.h -@@ -2579,6 +2579,10 @@ enum nl80211_commands { - * @NL80211_ATTR_HE_MUEDCA_PARAMS: MU-EDCA AC parameters for the - NL80211_CMD_UPDATE_HE_MUEDCA_PARAMS command. - * -+ * @NL80211_ATTR_BEACON_TX_MODE: used to configure the beacon tx mode as -+ * staggered mode or burst mode in %NL80211_CMD_START_AP from -+ * user-space. -+ * - * @NUM_NL80211_ATTR: total number of nl80211_attrs available - * @NL80211_ATTR_MAX: highest attribute number currently defined - * @__NL80211_ATTR_AFTER_LAST: internal use -@@ -3087,6 +3091,8 @@ enum nl80211_attrs { - NL80211_ATTR_MBSSID_CONFIG, - NL80211_ATTR_MBSSID_ELEMS, - -+ NL80211_ATTR_BEACON_TX_MODE, -+ - /* add attributes here, update the policy in nl80211.c */ - - __NL80211_ATTR_AFTER_LAST, -@@ -7333,4 +7339,13 @@ enum nl80211_sar_specs_attrs { - NL80211_SAR_ATTR_SPECS_MAX = __NL80211_SAR_ATTR_SPECS_LAST - 1, - }; - -+ -+/** -+ * enum nl80211_beacon_tx_mode - Beacon Tx Mode enum. -+ * Used to configure beacon staggered mode or beacon burst mode. -+ */ -+enum nl80211_beacon_tx_mode { -+ NL80211_BEACON_STAGGERED_MODE = 1, -+ NL80211_BEACON_BURST_MODE = 2, -+}; - #endif /* __LINUX_NL80211_H */ -Index: hostapd-2021-12-13-b26f5c0f/hostapd/hostapd.conf -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/hostapd/hostapd.conf -+++ hostapd-2021-12-13-b26f5c0f/hostapd/hostapd.conf -@@ -254,6 +254,9 @@ rts_threshold=-1 - # it. - fragm_threshold=-1 - -+# Beacon Tx mode; 1 = STAGGERED beacon tx mode; 2 = BURST beacon tx mode. -+beacon_tx_mode=1 -+ - # Rate configuration - # Default is to enable all rates supported by the hardware. This configuration - # item allows this list be filtered so that only the listed rates will be left -Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/config.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/config.c -+++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/config.c -@@ -2740,6 +2740,7 @@ static const struct parse_data ssid_fiel - { INT_RANGE(transition_disable, 0, 255) }, - { INT_RANGE(sae_pk, 0, 2) }, - { INT_RANGE(disable_40mhz_scan, 0, 1)}, -+ { INT_RANGE(beacon_tx_mode, 1, 2)}, - }; - - #undef OFFSET -@@ -3255,6 +3256,7 @@ void wpa_config_set_network_defaults(str - #endif /* CONFIG_MACSEC */ - ssid->mac_addr = -1; - ssid->max_oper_chwidth = DEFAULT_MAX_OPER_CHWIDTH; -+ ssid->beacon_tx_mode = DEFAULT_BEACON_TX_MODE; - } - - -Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/config_file.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/config_file.c -+++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/config_file.c -@@ -889,6 +889,7 @@ static void wpa_config_write_network(FIL - INT(disable_he); - #endif /* CONFIG_HE_OVERRIDES */ - INT(disable_40mhz_scan); -+ INT(beacon_tx_mode); - #undef STR - #undef INT - #undef INT_DEF -Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/config_ssid.h -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/config_ssid.h -+++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/config_ssid.h -@@ -47,6 +47,7 @@ - #define DEFAULT_AMPDU_DENSITY -1 /* no change */ - #define DEFAULT_USER_SELECTED_SIM 1 - #define DEFAULT_MAX_OPER_CHWIDTH -1 -+#define DEFAULT_BEACON_TX_MODE 0 - - /* Consider global sae_pwe for SAE mechanism for PWE derivation */ - #define DEFAULT_SAE_PWE 4 -@@ -1193,6 +1194,13 @@ struct wpa_ssid { - * disable_40mhz_scan - Disable 40MHz coex scan - */ - int disable_40mhz_scan; -+ -+ /** -+ * beacon_tx_mode - Beacon Tx mode -+ * 1 = STAGGERED MODE -+ * 2 = BURST MODE -+ */ -+ int beacon_tx_mode; - }; - - #endif /* CONFIG_SSID_H */ -Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/mesh.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/mesh.c -+++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/mesh.c -@@ -693,6 +693,7 @@ int wpa_supplicant_join_mesh(struct wpa_ - params->dtim_period = ssid->dtim_period; - else if (wpa_s->conf->dtim_period > 0) - params->dtim_period = wpa_s->conf->dtim_period; -+ params->beacon_tx_mode = ssid->beacon_tx_mode; - params->conf.max_peer_links = wpa_s->conf->max_peer_links; - if (ssid->mesh_rssi_threshold < DEFAULT_MESH_RSSI_THRESHOLD) { - params->conf.rssi_threshold = ssid->mesh_rssi_threshold; -Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_cli.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/wpa_cli.c -+++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_cli.c -@@ -1490,6 +1490,7 @@ static const char *network_fields[] = { - #endif /* CONFIG_HS20 */ - "mac_addr", "pbss", "wps_disabled", - "disable_40mhz_scan", -+ "beacon_tx_mode", - }; - - diff --git a/feeds/ipq95xx/hostapd/patches/h00-007-b-hostapd-Fix-HE-chan-switch-command-to-use-proper-BW.patch b/feeds/ipq95xx/hostapd/patches/h00-007-b-hostapd-Fix-HE-chan-switch-command-to-use-proper-BW.patch deleted file mode 100644 index 5f0b455fa..000000000 --- a/feeds/ipq95xx/hostapd/patches/h00-007-b-hostapd-Fix-HE-chan-switch-command-to-use-proper-BW.patch +++ /dev/null @@ -1,91 +0,0 @@ -From ebcd20553b63eb899b6983b5b205e374aba85e73 Mon Sep 17 00:00:00 2001 -From: Lavanya Suresh -Date: Tue, 18 May 2021 12:56:15 +0530 -Subject: [PATCH] hostapd: Fix HE chan switch command to use proper BW - -VHT is not enabled when HE mode is indicated in channel -switch command, due to which VHT operation IE is missing -in beacon causing STA to connect in HT40 mode. - -HE support for channel switch command patch is modified in -upstream commit causing this issue. It is reverted to the -previous version for fixing the same. - -Fixes: I4bd28058adbc27 (hostap: upgrade hostapd to 59e9794c7d7e) - -Signed-off-by: Lavanya Suresh ---- - src/ap/drv_callbacks.c | 38 ++++++++++++++++++++++---------------- - 1 file changed, 22 insertions(+), 16 deletions(-) - ---- a/src/ap/drv_callbacks.c -+++ b/src/ap/drv_callbacks.c -@@ -928,22 +928,30 @@ void hostapd_event_ch_switch(struct host - hapd->iconf->ieee80211n = ht; - if (!ht) { - hapd->iconf->ieee80211ac = 0; -- } else if (hapd->iconf->ch_switch_vht_config) { -- /* CHAN_SWITCH VHT config */ -- if (hapd->iconf->ch_switch_vht_config & -- CH_SWITCH_VHT_ENABLED) -- hapd->iconf->ieee80211ac = 1; -- else if (hapd->iconf->ch_switch_vht_config & -- CH_SWITCH_VHT_DISABLED) -- hapd->iconf->ieee80211ac = 0; -- } else if (hapd->iconf->ch_switch_he_config) { -- /* CHAN_SWITCH HE config */ -- if (hapd->iconf->ch_switch_he_config & -- CH_SWITCH_HE_ENABLED) -- hapd->iconf->ieee80211ax = 1; -- else if (hapd->iconf->ch_switch_he_config & -- CH_SWITCH_HE_DISABLED) -+ if (!is_6ghz_freq(hapd->iface->freq)) - hapd->iconf->ieee80211ax = 0; -+ } else { -+ if (hapd->iconf->ch_switch_vht_config) { -+ /* CHAN_SWITCH VHT config */ -+ if (hapd->iconf->ch_switch_vht_config & -+ CH_SWITCH_VHT_ENABLED) -+ hapd->iconf->ieee80211ac = 1; -+ else if (hapd->iconf->ch_switch_vht_config & -+ CH_SWITCH_VHT_DISABLED) -+ hapd->iconf->ieee80211ac = 0; -+ } -+ if (hapd->iconf->ch_switch_he_config) { -+ /* CHAN_SWITCH HE config */ -+ if (hapd->iconf->ch_switch_he_config & -+ CH_SWITCH_HE_ENABLED) { -+ hapd->iconf->ieee80211ax = 1; -+ if (!is_6ghz_freq(hapd->iface->freq)) -+ hapd->iconf->ieee80211ac = 1; -+ } -+ else if (hapd->iconf->ch_switch_he_config & -+ CH_SWITCH_HE_DISABLED) -+ hapd->iconf->ieee80211ax = 0; -+ } - } - hapd->iconf->ch_switch_vht_config = 0; - hapd->iconf->ch_switch_he_config = 0; ---- a/src/ap/hostapd.c -+++ b/src/ap/hostapd.c -@@ -3727,12 +3727,17 @@ hostapd_switch_channel_fallback(struct h - iface->freq = freq_params->freq; - iface->conf->channel = freq_params->channel; - iface->conf->secondary_channel = freq_params->sec_channel_offset; -- hostapd_set_oper_centr_freq_seg0_idx(iface->conf, seg0_idx); -- hostapd_set_oper_centr_freq_seg1_idx(iface->conf, seg1_idx); -- hostapd_set_oper_chwidth(iface->conf, bw); - iface->conf->ieee80211n = freq_params->ht_enabled; - iface->conf->ieee80211ac = freq_params->vht_enabled; - iface->conf->ieee80211ax = freq_params->he_enabled; -+ hostapd_set_oper_centr_freq_seg0_idx(iface->conf, seg0_idx); -+ hostapd_set_oper_centr_freq_seg1_idx(iface->conf, seg1_idx); -+ hostapd_set_oper_chwidth(iface->conf, bw); -+ -+ /* -+ * Resetting operating class to avoid referring previous values -+ */ -+ iface->conf->op_class = 0; - - /* - * cs_params must not be cleared earlier because the freq_params diff --git a/feeds/ipq95xx/hostapd/patches/h00-007-hostapd-Setting-Spectrum-Management-bit-for-chan-swi.patch b/feeds/ipq95xx/hostapd/patches/h00-007-hostapd-Setting-Spectrum-Management-bit-for-chan-swi.patch deleted file mode 100644 index c38e79127..000000000 --- a/feeds/ipq95xx/hostapd/patches/h00-007-hostapd-Setting-Spectrum-Management-bit-for-chan-swi.patch +++ /dev/null @@ -1,67 +0,0 @@ -From d2b5a9ed668829c04a8c86e8712cc045a9aaac5f Mon Sep 17 00:00:00 2001 -From: Muna Sinada -Date: Mon, 11 Jan 2021 17:30:34 -0800 -Subject: [PATCH] hostapd: Setting Spectrum Management bit for chan switch - -When CSA IEs are adversied by AP when CSA is initiated, spectrum -management bit in capability information located in management frame's -fixed field shoud be set. Therfore when channel switch is supported, -the spectrum management bit is set. - -Signed-off-by: Muna Sinada ---- - src/ap/ap_config.c | 4 +++- - src/ap/ieee802_11.c | 15 +++++++++------ - 2 files changed, 12 insertions(+), 7 deletions(-) - -Index: hostapd-2021-02-18/src/ap/ap_config.c -=================================================================== ---- hostapd-2021-02-18.orig/src/ap/ap_config.c -+++ hostapd-2021-02-18/src/ap/ap_config.c -@@ -229,6 +229,8 @@ struct hostapd_config * hostapd_config_d - conf->fragm_threshold = -2; /* user driver default: 2346 */ - /* Set to invalid value means do not add Power Constraint IE */ - conf->local_pwr_constraint = -1; -+ /* Set to invalid value means that user did not set this value */ -+ conf->spectrum_mgmt_required = -1; - - conf->wmm_ac_params[0] = ac_be; - conf->wmm_ac_params[1] = ac_bk; -@@ -1471,7 +1473,7 @@ int hostapd_config_check(struct hostapd_ - return -1; - } - -- if (full_config && conf->spectrum_mgmt_required && -+ if (full_config && conf->spectrum_mgmt_required != -1 && - conf->local_pwr_constraint == -1) { - wpa_printf(MSG_ERROR, "Cannot set Spectrum Management bit without Country and Power Constraint elements"); - return -1; -Index: hostapd-2021-02-18/src/ap/ieee802_11.c -=================================================================== ---- hostapd-2021-02-18.orig/src/ap/ieee802_11.c -+++ hostapd-2021-02-18/src/ap/ieee802_11.c -@@ -300,15 +300,18 @@ u16 hostapd_own_capab_info(struct hostap - capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; - - /* -- * Currently, Spectrum Management capability bit is set when directly -- * requested in configuration by spectrum_mgmt_required or when AP is -- * running on DFS channel. -+ * Currently, Spectrum Management capability bit is set by default when -+ * channel switch is supported. When CSA is not supported, then Spectrum -+ * Management capability bit is set when directly requested in -+ * configuration by spectrum_mgmt_required or when AP is running on DFS -+ * channel. - * TODO: Also consider driver support for TPC to set Spectrum Mgmt bit - */ - if (hapd->iface->current_mode && -- hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A && -- (hapd->iconf->spectrum_mgmt_required || dfs)) -- capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; -+ hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A) -+ if (!(hapd->iconf->spectrum_mgmt_required == 0 && !dfs) && -+ (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA || dfs)) -+ capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; - - for (i = 0; i < RRM_CAPABILITIES_IE_LEN; i++) { - if (hapd->conf->radio_measurements[i]) { diff --git a/feeds/ipq95xx/hostapd/patches/h00-008-a-add-support-for-6ghz-tpc.patch b/feeds/ipq95xx/hostapd/patches/h00-008-a-add-support-for-6ghz-tpc.patch deleted file mode 100644 index 468051063..000000000 --- a/feeds/ipq95xx/hostapd/patches/h00-008-a-add-support-for-6ghz-tpc.patch +++ /dev/null @@ -1,148 +0,0 @@ -From 2974dde2aa3273451b6a51c33a30fc98cee10b25 Mon Sep 17 00:00:00 2001 -From: Pradeep Kumar Chitrapu -Date: Sat, 30 Jan 2021 10:15:52 -0800 -Subject: [PATCH 1/4] hostapd: Add country Information element support for 6Ghz - -Signed-off-by: Pradeep Kumar Chitrapu ---- - src/ap/beacon.c | 66 +++++++++++++++++++++++++----------- - src/common/ieee802_11_defs.h | 10 ++++++ - 2 files changed, 56 insertions(+), 20 deletions(-) - ---- a/src/ap/beacon.c -+++ b/src/ap/beacon.c -@@ -187,7 +187,8 @@ static u8 * hostapd_eid_pwr_constraint(s - } - - --static u8 * hostapd_eid_country_add(u8 *pos, u8 *end, int chan_spacing, -+static u8 * hostapd_eid_country_add(struct hostapd_data *hapd, u8 *pos, -+ u8 *end, int chan_spacing, - struct hostapd_channel_data *start, - struct hostapd_channel_data *prev) - { -@@ -199,30 +200,20 @@ static u8 * hostapd_eid_country_add(u8 * - /* number of channels */ - *pos++ = (prev->chan - start->chan) / chan_spacing + 1; - /* maximum transmit power level */ -- *pos++ = start->max_tx_power; -+ if (!is_6ghz_op_class(hapd->iconf->op_class)) -+ *pos++ = start->max_tx_power; -+ else -+ *pos++ = 0; /* Reserved for 6GHz Band */ - - return pos; - } - -- --static u8 * hostapd_eid_country(struct hostapd_data *hapd, u8 *eid, -- int max_len) -+static u8 * hostapd_fill_triplets(struct hostapd_data *hapd, u8 *pos, -+ u8 *end) - { -- u8 *pos = eid; -- u8 *end = eid + max_len; -- int i; - struct hostapd_hw_modes *mode; - struct hostapd_channel_data *start, *prev; -- int chan_spacing = 1; -- -- if (!hapd->iconf->ieee80211d || max_len < 6 || -- hapd->iface->current_mode == NULL) -- return eid; -- -- *pos++ = WLAN_EID_COUNTRY; -- pos++; /* length will be set later */ -- os_memcpy(pos, hapd->iconf->country, 3); /* e.g., 'US ' */ -- pos += 3; -+ int i, chan_spacing = 1; - - mode = hapd->iface->current_mode; - if (mode->mode == HOSTAPD_MODE_IEEE80211A) -@@ -233,6 +224,7 @@ static u8 * hostapd_eid_country(struct h - struct hostapd_channel_data *chan = &mode->channels[i]; - if (chan->flag & HOSTAPD_CHAN_DISABLED) - continue; -+ - if (start && prev && - prev->chan + chan_spacing == chan->chan && - start->max_tx_power == chan->max_tx_power) { -@@ -241,7 +233,8 @@ static u8 * hostapd_eid_country(struct h - } - - if (start && prev) { -- pos = hostapd_eid_country_add(pos, end, chan_spacing, -+ pos = hostapd_eid_country_add(hapd, pos, end, -+ chan_spacing, - start, prev); - start = NULL; - } -@@ -251,10 +244,48 @@ static u8 * hostapd_eid_country(struct h - } - - if (start) { -- pos = hostapd_eid_country_add(pos, end, chan_spacing, -+ pos = hostapd_eid_country_add(hapd, pos, end, -+ chan_spacing, - start, prev); - } - -+ return pos; -+} -+ -+static u8 * hostapd_eid_country(struct hostapd_data *hapd, u8 *eid, -+ int max_len) -+{ -+ u8 *pos = eid; -+ u8 *end = eid + max_len; -+ -+ if (!hapd->iconf->ieee80211d || max_len < 6 || -+ hapd->iface->current_mode == NULL) -+ return eid; -+ -+ *pos++ = WLAN_EID_COUNTRY; -+ pos++; /* length will be set later */ -+ os_memcpy(pos, hapd->iconf->country, 3); /* e.g., 'US ' */ -+ pos += 3; -+ -+ if (is_6ghz_op_class(hapd->iconf->op_class)) { -+ /* Third octet of the country string to indicate -+ * Global Operating Class -+ */ -+ eid[4] = 0x4; -+ -+ *pos++ = WLAN_EID_EXT_OPERATING_TRIPLET; -+ /* Operating class*/ -+ *pos++ = hapd->iconf->op_class; -+ /* Coverage Class */ -+ *pos++ = 0; -+ /* Subband Triplets are required only for 20MHz case */ -+ if (hapd->iconf->op_class == 131 || -+ hapd->iconf->op_class == 136) -+ pos = hostapd_fill_triplets(hapd, pos, end); -+ } else { -+ pos = hostapd_fill_triplets(hapd, pos, end); -+ } -+ - if ((pos - eid) & 1) { - if (end - pos < 1) - return eid; ---- a/src/common/ieee802_11_defs.h -+++ b/src/common/ieee802_11_defs.h -@@ -494,6 +494,16 @@ - #define WLAN_EID_EXT_ANTI_CLOGGING_TOKEN 93 - #define WLAN_EID_EXT_PASN_PARAMS 100 - -+/* Operating Triplet can be any integer >= 201 -+ * From IEEE P802.11-REVmd/D4.0: The first octet in each Subband -+ * Triplet field or Operating Triplet field contains an unsigned -+ * integer and identifies the type of field. If the integer has -+ * a value less than or equal to 200, then the field is a -+ * Subband Triplet field. If the integer has a value of 201 or -+ * greater, then the field is an Operating Triplet field. -+ */ -+#define WLAN_EID_EXT_OPERATING_TRIPLET 201 -+ - /* Extended Capabilities field */ - #define WLAN_EXT_CAPAB_20_40_COEX 0 - #define WLAN_EXT_CAPAB_GLK 1 diff --git a/feeds/ipq95xx/hostapd/patches/h00-008-b-add-support-for-6ghz-tpc.patch b/feeds/ipq95xx/hostapd/patches/h00-008-b-add-support-for-6ghz-tpc.patch deleted file mode 100644 index 5937579b5..000000000 --- a/feeds/ipq95xx/hostapd/patches/h00-008-b-add-support-for-6ghz-tpc.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 5b23a6f5fba606cb76fe50e2fc73285caf935b32 Mon Sep 17 00:00:00 2001 -From: Pradeep Kumar Chitrapu -Date: Mon, 1 Feb 2021 11:16:07 -0800 -Subject: [PATCH 2/4] ieee80211: Regulatory info field definition for HE 6GHz - operation IE - -Regulatory info subfield is added per specification -IEEE P802.11ax/D7.0. - -Signed-off-by: Pradeep Kumar Chitrapu ---- - src/ap/ieee802_11_he.c | 9 ++++++++- - src/common/ieee802_11_defs.h | 1 + - 2 files changed, 9 insertions(+), 1 deletion(-) - -diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c -index 18436a6b336b..a78ed01a54b6 100644 ---- a/src/ap/ieee802_11_he.c -+++ b/src/ap/ieee802_11_he.c -@@ -226,7 +226,14 @@ u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid) - /* 6 GHz Operation Information field */ - *pos++ = hapd->iconf->channel; /* Primary Channel */ - -- /* Control: Channel Width */ -+ /* Control: -+ * bits 0-1: Channel Width -+ * bits 2-2: Duplicate Beacon -+ * bits 3-5: Regulatory Info -+ * - 0 (Indoor Access Point) -+ * - 1 (Standard Power Access Point) -+ * - Reserved in 5GHz and 2Ghz bands -+ */ - if (seg1) - *pos++ = 3; - else -diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h -index be37c9323ae2..3c065ab27f51 100644 ---- a/src/common/ieee802_11_defs.h -+++ b/src/common/ieee802_11_defs.h -@@ -2188,6 +2188,7 @@ struct ieee80211_he_6ghz_oper_info { - - #define HE_6GHZ_OPER_INFO_CTRL_CHAN_WIDTH_MASK (BIT(0) | BIT(1)) - #define HE_6GHZ_OPER_INFO_CTRL_DUP_BEACON BIT(2) -+#define HE_6GHZ_OPER_INFO_CTRL_REG_INFO_MASK (BIT(3) | BIT(4) | BIT(5)) - - /* IEEE P802.11ax/D6.0, 9.4.2.261 HE 6 GHz Band Capabilities element */ - struct ieee80211_he_6ghz_band_cap { --- -2.17.1 - diff --git a/feeds/ipq95xx/hostapd/patches/h00-008-c-add-support-for-6ghz-tpc.patch b/feeds/ipq95xx/hostapd/patches/h00-008-c-add-support-for-6ghz-tpc.patch deleted file mode 100644 index c9218ec05..000000000 --- a/feeds/ipq95xx/hostapd/patches/h00-008-c-add-support-for-6ghz-tpc.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 6ab1c08908767246cf0550787adb75371ab00c96 Mon Sep 17 00:00:00 2001 -From: Pradeep Kumar Chitrapu -Date: Tue, 2 Mar 2021 23:03:03 -0800 -Subject: [PATCH 3/4] hostapd: add config option to specify 6Ghz AP type - -IEEE P802.11ax/D7.0 introduces Regulatory info subfield which -is interpreted to 6Ghz ap type. - -When not specified, Indoor AP type is selected for 6GHz AP by -default. - -Signed-off-by: Pradeep Kumar Chitrapu ---- - hostapd/config_file.c | 2 ++ - hostapd/hostapd.conf | 7 +++++++ - src/ap/ap_config.h | 12 ++++++++++++ - 3 files changed, 21 insertions(+) - ---- a/hostapd/config_file.c -+++ b/hostapd/config_file.c -@@ -3536,6 +3536,8 @@ static int hostapd_config_fill(struct ho - line, pos); - return 1; - } -+ } else if (os_strcmp(buf, "he_6ghz_reg_pwr_type") == 0) { -+ conf->he_6ghz_reg_pwr_type = atoi(pos); - } else if (os_strcmp(buf, "he_oper_chwidth") == 0) { - conf->he_oper_chwidth = atoi(pos); - } else if (os_strcmp(buf, "he_oper_centr_freq_seg0_idx") == 0) { ---- a/hostapd/hostapd.conf -+++ b/hostapd/hostapd.conf -@@ -584,6 +584,13 @@ wmm_ac_vo_acm=0 - # Default: 0 (disabled) - #notify_mgmt_frames=0 - -+# 6GHz regulatory AP type -+# This config is to set 6GHz access point type. Possible options -+# are 0 = Indoor AP, 1 = Standard Power AP -+# If not specified Indoor AP is selected by default. -+# option is no operation for non 6GHz band. -+#he_6ghz_reg_pwr_type=0 -+ - ##### IEEE 802.11n related configuration ###################################### - - # ieee80211n: Whether IEEE 802.11n (HT) is enabled ---- a/src/ap/ap_config.h -+++ b/src/ap/ap_config.h -@@ -1083,6 +1083,9 @@ struct hostapd_config { - u8 he_6ghz_max_ampdu_len_exp; - u8 he_6ghz_rx_ant_pat; - u8 he_6ghz_tx_ant_pat; -+#define AP_TYPE_6GHZ_INDOOR_AP 0 -+#define AP_TYPE_6GHZ_STANDARD_POWER_AP 1 -+ u8 he_6ghz_reg_pwr_type; - #endif /* CONFIG_IEEE80211AX */ - - /* VHT enable/disable config from CHAN_SWITCH */ -@@ -1112,6 +1115,15 @@ struct hostapd_config { - #endif /* CONFIG_AIRTIME_POLICY */ - }; - -+static inline u8 hostapd_get_he_6ghz_reg_pwr_type(struct hostapd_config *conf) -+{ -+#ifdef CONFIG_IEEE80211AX -+ if (conf->ieee80211ax) -+ return conf->he_6ghz_reg_pwr_type; -+#endif /* CONFIG_IEEE80211AX */ -+ return 0; -+} -+ - - static inline u8 hostapd_get_oper_chwidth(struct hostapd_config *conf) - { diff --git a/feeds/ipq95xx/hostapd/patches/h00-008-d-add-support-for-6ghz-tpc.patch b/feeds/ipq95xx/hostapd/patches/h00-008-d-add-support-for-6ghz-tpc.patch deleted file mode 100644 index 5287cc440..000000000 --- a/feeds/ipq95xx/hostapd/patches/h00-008-d-add-support-for-6ghz-tpc.patch +++ /dev/null @@ -1,229 +0,0 @@ -From 7c79ef90001929dfa9f150135d672e7105a5ef44 Mon Sep 17 00:00:00 2001 -From: Pradeep Kumar Chitrapu -Date: Tue, 9 Feb 2021 16:51:13 -0800 -Subject: [PATCH 4/4] 6G: add TX power envelope IE in 6GHz - -Add power envelope element for 6GHz Indoor AP as per the -spec IEEE P802.11ax/D7.0. - -Currently uses fixed values for maximum transmit power limits -which are applicable to 6GHz operation in United states, Japan -and Korea. Support to extract the AP operation type and country -or channel specific power contraints will be added later on. - -Signed-off-by: Pradeep Kumar Chitrapu ---- - src/ap/beacon.c | 26 +++++++++++- - src/ap/ieee802_11_vht.c | 81 ++++++++++++++++++++++++++++-------- - src/common/ieee802_11_defs.h | 32 ++++++++++++++ - 3 files changed, 119 insertions(+), 20 deletions(-) - ---- a/src/ap/beacon.c -+++ b/src/ap/beacon.c -@@ -498,9 +498,14 @@ static u8 * hostapd_gen_probe_resp(struc - 3 + sizeof(struct ieee80211_he_operation) + - 3 + sizeof(struct ieee80211_he_mu_edca_parameter_set) + - 3 + sizeof(struct ieee80211_spatial_reuse); -- if (is_6ghz_op_class(hapd->iconf->op_class)) -+ if (is_6ghz_op_class(hapd->iconf->op_class)) { - buflen += sizeof(struct ieee80211_he_6ghz_oper_info) + - 3 + sizeof(struct ieee80211_he_6ghz_band_cap); -+ /* Additional TX Power envelope for subordinate client */ -+ if (hostapd_get_he_6ghz_reg_pwr_type(hapd->iconf) == -+ AP_TYPE_6GHZ_INDOOR_AP) -+ buflen += 4; -+ } - } - #endif /* CONFIG_IEEE80211AX */ - -@@ -1388,6 +1393,15 @@ static u8 * hostapd_gen_fils_discovery(s - buf_len = pos - buf; - total_len += buf_len; - -+ /* TX Power Envelopes */ -+ if (is_6ghz_op_class(hapd->iconf->op_class)) { -+ if (hostapd_get_he_6ghz_reg_pwr_type(hapd->iconf) == -+ AP_TYPE_6GHZ_INDOOR_AP) -+ total_len = total_len + 8; -+ else -+ total_len = total_len + 4; -+ } -+ - head = os_zalloc(total_len); - if (!head) - return NULL; -@@ -1460,6 +1474,9 @@ static u8 * hostapd_gen_fils_discovery(s - pos += buf_len; - } - -+ if (is_6ghz_op_class(hapd->iconf->op_class)) -+ pos = hostapd_eid_txpower_envelope(hapd, pos); -+ - *len = pos - (u8 *) head; - wpa_hexdump(MSG_DEBUG, "FILS Discovery frame template", - (u8 *) head, pos - (u8 *) head); -@@ -1534,9 +1551,14 @@ int ieee802_11_build_ap_params(struct ho - 3 + sizeof(struct ieee80211_he_operation) + - 3 + sizeof(struct ieee80211_he_mu_edca_parameter_set) + - 3 + sizeof(struct ieee80211_spatial_reuse); -- if (is_6ghz_op_class(hapd->iconf->op_class)) -+ if (is_6ghz_op_class(hapd->iconf->op_class)) { - tail_len += sizeof(struct ieee80211_he_6ghz_oper_info) + - 3 + sizeof(struct ieee80211_he_6ghz_band_cap); -+ /* Additional TX Power envelope for subordinate client */ -+ if (hostapd_get_he_6ghz_reg_pwr_type(hapd->iconf) == -+ AP_TYPE_6GHZ_INDOOR_AP) -+ tail_len += 4; -+ } - } - #endif /* CONFIG_IEEE80211AX */ - ---- a/src/common/ieee802_11_defs.h -+++ b/src/common/ieee802_11_defs.h -@@ -1938,8 +1938,40 @@ struct tpc_report { - u8 link_margin; - } STRUCT_PACKED; - -+ -+/* -+ * IEEE P802.11ax/D7.0, Table 9-275a—Maximum Transmit Power Interpretation -+ * subfield encoding. -+ */ -+enum max_tx_pwr_interpretation { -+ LOCAL_EIRP = 0, -+ LOCAL_EIRP_PSD = 1, -+ REGULATORY_CLIENT_EIRP = 2, -+ REGULATORY_CLIENT_EIRP_PSD = 3, -+}; -+ -+/* -+ * IEEE P802.11ax/D7.0,Table E-13 — Maximum Transmit Power -+ * Category subfield encoding in the United States. -+ */ -+enum reg_6g_client_type { -+ REG_DEFAULT_CLIENT = 0, -+ REG_SUBORDINATE_CLIENT = 1, -+}; -+ -+/* same Max Tx Pwr for all 20MHz bands */ -+#define DEFAULT_MAX_TX_POWER_COUNT_6G 0 -+/* -+ * These tx-power macros are present till the 6G regdomains are defined to -+ * support tx-power values for various client types. -+ */ -+#define REG_PSD_MAX_TXPOWER_FOR_DEFAULT_CLIENT (-1) /* dBm/MHz */ -+#define REG_PSD_MAX_TXPOWER_FOR_SUBORDINATE_CLIENT 5 /* dBm/MHz */ -+#define REG_EIRP_MAX_TXPOWER_FOR_SUBORDINATE_CLIENT 24 /* dBm */ -+ - #define RRM_CAPABILITIES_IE_LEN 5 - -+ - /* IEEE Std 802.11-2012, 8.5.7.4 - Link Measurement Request frame format */ - struct rrm_link_measurement_request { - u8 dialog_token; ---- a/src/ap/ieee802_11.c -+++ b/src/ap/ieee802_11.c -@@ -6817,6 +6817,30 @@ void ieee802_11_rx_from_unknown(struct h - WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - } - -+static u8 * hostapd_add_tpe_info(u8 *eid, u8 tx_pwr_count, -+ u8 tx_pwr_intrpn, u8 tx_pwr_cat, -+ u8 tx_pwr) -+{ -+ int i; -+ -+ *eid++ = WLAN_EID_TRANSMIT_POWER_ENVELOPE; -+ /* length */ -+ *eid++ = 2 + tx_pwr_count; -+ -+ /* -+ * Transmit Power Information -+ * bits 0-2 : Maximum Transmit Power Count -+ * bits 3-5 : Maximum Transmit Power Interpretation -+ * bits 6-7 : Maximum Transmit Power Category -+ */ -+ *eid++ = tx_pwr_count | ( tx_pwr_intrpn << 3) | (tx_pwr_cat << 6); -+ -+ /* Maximum transmit Power field */ -+ for (i = 0; i <= tx_pwr_count; i++) -+ *eid++ = tx_pwr; -+ -+ return eid; -+} - - u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid) - { -@@ -6826,8 +6850,8 @@ u8 * hostapd_eid_txpower_envelope(struct - struct hostapd_channel_data *chan; - int dfs, i; - u8 channel, tx_pwr_count, local_pwr_constraint; -+ u8 tx_pwr, tx_pwr_intrpn, tx_pwr_cat, ap_type; - int max_tx_power; -- u8 tx_pwr; - - if (!mode) - return eid; -@@ -6842,6 +6866,41 @@ u8 * hostapd_eid_txpower_envelope(struct - if (i == mode->num_channels) - return eid; - -+ /* For now, 6GHz has only support for Indoor AP type -+ * From IEEE P802.11ax/D7.0: An AP that is an -+ * Indoor Access Point per regulatory rules shall send at least -+ * two Transmit Power Envelope elements in Beacon and Probe -+ * Response frames as follows: -+ * - Maximum Transmit Power Category subfield = Default; -+ * Unit interpretation = Regulatory client EIRP PSD -+ * - Maximum Transmit Power Category subfield = Subordinate Device; -+ * Unit interpretation = Regulatory client EIRP PSD -+ */ -+ if (is_6ghz_op_class(iconf->op_class)) { -+ ap_type = hostapd_get_he_6ghz_reg_pwr_type(iconf); -+ -+ tx_pwr_count = DEFAULT_MAX_TX_POWER_COUNT_6G; -+ tx_pwr_intrpn = REGULATORY_CLIENT_EIRP_PSD; -+ -+ /* Indoor access point must include additional -+ * TPE for subordinate device -+ */ -+ if (ap_type == AP_TYPE_6GHZ_INDOOR_AP) { -+ tx_pwr_cat = REG_SUBORDINATE_CLIENT; -+ /* TODO: extract psd limits from channel data */ -+ tx_pwr = REG_PSD_MAX_TXPOWER_FOR_SUBORDINATE_CLIENT * 2; -+ eid = hostapd_add_tpe_info(eid, tx_pwr_count, tx_pwr_intrpn, -+ tx_pwr_cat, tx_pwr); -+ } -+ -+ /* Default Tx Power envelope for Global Operating class */ -+ tx_pwr_cat = REG_DEFAULT_CLIENT; -+ tx_pwr = REG_PSD_MAX_TXPOWER_FOR_DEFAULT_CLIENT * 2; -+ eid = hostapd_add_tpe_info(eid, tx_pwr_count, tx_pwr_intrpn, tx_pwr_cat, tx_pwr); -+ -+ return eid; -+ } -+ - switch (hostapd_get_oper_chwidth(iconf)) { - case CHANWIDTH_USE_HT: - if (iconf->secondary_channel == 0) { -@@ -6914,17 +6973,9 @@ u8 * hostapd_eid_txpower_envelope(struct - else - tx_pwr = max_tx_power; - -- *eid++ = WLAN_EID_TRANSMIT_POWER_ENVELOPE; -- *eid++ = 2 + tx_pwr_count; -- -- /* -- * Max Transmit Power count and -- * Max Transmit Power units = 0 (EIRP) -- */ -- *eid++ = tx_pwr_count; -- -- for (i = 0; i <= tx_pwr_count; i++) -- *eid++ = tx_pwr; -+ tx_pwr_intrpn = LOCAL_EIRP; -+ tx_pwr_cat = 0; /* Reserved for non 6GHz */ -+ eid = hostapd_add_tpe_info(eid, tx_pwr_count, tx_pwr_intrpn, tx_pwr_cat, tx_pwr); - - return eid; - } diff --git a/feeds/ipq95xx/hostapd/patches/h00-008-e-Fill-6G-TPE-IE-for-non-US-countries.patch b/feeds/ipq95xx/hostapd/patches/h00-008-e-Fill-6G-TPE-IE-for-non-US-countries.patch deleted file mode 100644 index 8f59f45fd..000000000 --- a/feeds/ipq95xx/hostapd/patches/h00-008-e-Fill-6G-TPE-IE-for-non-US-countries.patch +++ /dev/null @@ -1,131 +0,0 @@ -From 575b68536cb4e44a42de2d76b5702f13f8557d36 Mon Sep 17 00:00:00 2001 -From: Lavanya Suresh -Date: Fri, 26 Mar 2021 12:59:10 +0530 -Subject: [PATCH] hostapd: Fill 6G TPE IE for non-US countries - -Currently PSD power limits for 6GHz Regular and subordinate -clients in 6G TPE IE are hardcoded with the values defined -for country US, by default. - -It is extended to hardcode proper PSD values for all 6G countries -and supported AP power modes. - -PSD values will be fetched from kernel data instead of hardcoded -values, after complete regulatory support is added for 6G. - -Signed-off-by: Lavanya Suresh ---- - src/ap/ap_config.h | 1 + - src/ap/ieee802_11.c | 43 +++++++++++++++++++++++++++++++++++++++++-- - src/common/ieee802_11_defs.h | 25 ++++++++++++++++++++++--- - 3 files changed, 64 insertions(+), 5 deletions(-) - ---- a/src/ap/ap_config.h -+++ b/src/ap/ap_config.h -@@ -1085,6 +1085,7 @@ struct hostapd_config { - u8 he_6ghz_tx_ant_pat; - #define AP_TYPE_6GHZ_INDOOR_AP 0 - #define AP_TYPE_6GHZ_STANDARD_POWER_AP 1 -+#define AP_TYPE_6GHZ_VERY_LOW_POWER_AP 2 - u8 he_6ghz_reg_pwr_type; - #endif /* CONFIG_IEEE80211AX */ - ---- a/src/ap/ieee802_11.c -+++ b/src/ap/ieee802_11.c -@@ -6935,6 +6935,47 @@ void ieee802_11_rx_from_unknown(struct h - WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - } - -+u8 hostapd_get_6g_tx_power(struct hostapd_data *hapd, u8 ap_type, u8 tx_pwr_cat) -+{ -+ char country[3]; -+ -+ if (hapd->iconf->country[0] != '\0' && hapd->iconf->country[1] != '\0') -+ memcpy(country, hapd->iconf->country, 3); -+ else -+ hostapd_get_country(hapd, country); -+ -+ if ((memcmp(country, "US", 2) == 0) || (memcmp(country, "CL", 2) == 0)) { -+ /* FCC Regdomain */ -+ if (ap_type == AP_TYPE_6GHZ_INDOOR_AP && tx_pwr_cat == REG_DEFAULT_CLIENT) -+ return REG_FCC_PSD_MAX_TXPOWER_FOR_DEFAULT_CLIENT_LPI; -+ else if (ap_type == AP_TYPE_6GHZ_INDOOR_AP) -+ return REG_FCC_PSD_MAX_TXPOWER_FOR_SUBORDINATE_CLIENT_LPI; -+ else if (ap_type == AP_TYPE_6GHZ_STANDARD_POWER_AP) -+ return REG_FCC_PSD_MAX_TXPOWER_SP; -+ -+ } else if (memcmp(country, "GB", 2) == 0) { -+ /* ETSI2 Regdomain */ -+ if (ap_type == AP_TYPE_6GHZ_INDOOR_AP) -+ return REG_ETSI2_PSD_MAX_TXPOWER_DEFAULT_SUBORDINATE_CLIENT_LPI; -+ else if (ap_type == AP_TYPE_6GHZ_VERY_LOW_POWER_AP) -+ return REG_ETSI2_PSD_MAX_TXPOWER_DEFAULT_SUBORDINATE_CLIENT_VLP; -+ -+ } else if (memcmp(country, "KR", 2) == 0) { -+ /* APL1 Regdomain */ -+ if (ap_type == AP_TYPE_6GHZ_INDOOR_AP) -+ return REG_APL1_PSD_MAX_TXPOWER_DEFAULT_SUBORDINATE_CLIENT_LPI; -+ else if (ap_type == AP_TYPE_6GHZ_VERY_LOW_POWER_AP) -+ return REG_APL1_PSD_MAX_TXPOWER_DEFAULT_SUBORDINATE_CLIENT_VLP; -+ } else { -+ wpa_printf(MSG_DEBUG, "Invalid 6g regdomain/country(%s)", country); -+ return 0; -+ } -+ -+ wpa_printf(MSG_DEBUG, "Configured AP type(%d) is not supported for the country(%s) currently set", -+ ap_type, country); -+ return 0; -+} -+ - static u8 * hostapd_add_tpe_info(u8 *eid, u8 tx_pwr_count, - u8 tx_pwr_intrpn, u8 tx_pwr_cat, - u8 tx_pwr) -@@ -7006,14 +7047,14 @@ u8 * hostapd_eid_txpower_envelope(struct - if (ap_type == AP_TYPE_6GHZ_INDOOR_AP) { - tx_pwr_cat = REG_SUBORDINATE_CLIENT; - /* TODO: extract psd limits from channel data */ -- tx_pwr = REG_PSD_MAX_TXPOWER_FOR_SUBORDINATE_CLIENT * 2; -+ tx_pwr = (hostapd_get_6g_tx_power(hapd, ap_type, tx_pwr_cat) * 2); - eid = hostapd_add_tpe_info(eid, tx_pwr_count, tx_pwr_intrpn, - tx_pwr_cat, tx_pwr); - } - - /* Default Tx Power envelope for Global Operating class */ - tx_pwr_cat = REG_DEFAULT_CLIENT; -- tx_pwr = REG_PSD_MAX_TXPOWER_FOR_DEFAULT_CLIENT * 2; -+ tx_pwr = (hostapd_get_6g_tx_power(hapd, ap_type, tx_pwr_cat) * 2); - eid = hostapd_add_tpe_info(eid, tx_pwr_count, tx_pwr_intrpn, tx_pwr_cat, tx_pwr); - - return eid; ---- a/src/common/ieee802_11_defs.h -+++ b/src/common/ieee802_11_defs.h -@@ -1987,9 +1987,15 @@ enum reg_6g_client_type { - * These tx-power macros are present till the 6G regdomains are defined to - * support tx-power values for various client types. - */ --#define REG_PSD_MAX_TXPOWER_FOR_DEFAULT_CLIENT (-1) /* dBm/MHz */ --#define REG_PSD_MAX_TXPOWER_FOR_SUBORDINATE_CLIENT 5 /* dBm/MHz */ --#define REG_EIRP_MAX_TXPOWER_FOR_SUBORDINATE_CLIENT 24 /* dBm */ -+#define REG_FCC_PSD_MAX_TXPOWER_FOR_DEFAULT_CLIENT_LPI (-1) /* dBm/MHz */ -+#define REG_FCC_PSD_MAX_TXPOWER_FOR_SUBORDINATE_CLIENT_LPI 5 /* dBm/MHz */ -+#define REG_FCC_PSD_MAX_TXPOWER_SP 17 /* dBm/MHz */ -+ -+#define REG_ETSI2_PSD_MAX_TXPOWER_DEFAULT_SUBORDINATE_CLIENT_LPI 11 /* dBm/MHz */ -+#define REG_ETSI2_PSD_MAX_TXPOWER_DEFAULT_SUBORDINATE_CLIENT_VLP 11 /* dBm/MHz */ -+ -+#define REG_APL1_PSD_MAX_TXPOWER_DEFAULT_SUBORDINATE_CLIENT_LPI 2 /* dBm/MHz */ -+#define REG_APL1_PSD_MAX_TXPOWER_DEFAULT_SUBORDINATE_CLIENT_VLP 1 /* dBm/MHz */ - - #define RRM_CAPABILITIES_IE_LEN 5 - ---- a/hostapd/hostapd.conf -+++ b/hostapd/hostapd.conf -@@ -586,7 +586,7 @@ wmm_ac_vo_acm=0 - - # 6GHz regulatory AP type - # This config is to set 6GHz access point type. Possible options --# are 0 = Indoor AP, 1 = Standard Power AP -+# are 0 = Indoor AP, 1 = Standard Power AP, 2 = Very Low Power AP - # If not specified Indoor AP is selected by default. - # option is no operation for non 6GHz band. - #he_6ghz_reg_pwr_type=0 diff --git a/feeds/ipq95xx/hostapd/patches/i00-001-compile-fix.patch b/feeds/ipq95xx/hostapd/patches/i00-001-compile-fix.patch deleted file mode 100644 index 1d2cbd8b5..000000000 --- a/feeds/ipq95xx/hostapd/patches/i00-001-compile-fix.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 66f270e4bbf8ffcd645721042ffef36c9df54297 Mon Sep 17 00:00:00 2001 -From: Tamizh Chelvam -Date: Tue, 9 Mar 2021 10:20:47 +0530 -Subject: [PATCH] hostap: Add changes to fix compilation errors - -Signed-off-by: Tamizh Chelvam ---- - src/ap/beacon.c | 2 +- - src/drivers/driver_nl80211.c | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/ap/beacon.c b/src/ap/beacon.c -index 7296f23f0d85..c56aff1b915d 100644 ---- a/src/ap/beacon.c -+++ b/src/ap/beacon.c -@@ -1459,7 +1459,7 @@ static u8 * hostapd_gen_fils_discovery(struct hostapd_data *hapd, size_t *len) - - *len = pos - (u8 *) head; - wpa_hexdump(MSG_DEBUG, "FILS Discovery frame template", -- head, pos - (u8 *) head); -+ (u8 *) head, pos - (u8 *) head); - return (u8 *) head; - } - -diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c -index ab6c4281f366..bd56c6471630 100644 ---- a/src/drivers/driver_nl80211.c -+++ b/src/drivers/driver_nl80211.c -@@ -5135,7 +5135,7 @@ static int wpa_driver_nl80211_sta_add(void *priv, - - if (params->he_6ghz_capab) { - wpa_hexdump(MSG_DEBUG, " * he_6ghz_capab", -- params->he_6ghz_capab, -+ (u8 *) params->he_6ghz_capab, - sizeof(*params->he_6ghz_capab)); - if (nla_put(msg, NL80211_ATTR_HE_6GHZ_CAPABILITY, - sizeof(*params->he_6ghz_capab), --- -2.31.1 - diff --git a/feeds/ipq95xx/hostapd/patches/j00-001-hostapd-update-missing-5.9GHz-channels.patch b/feeds/ipq95xx/hostapd/patches/j00-001-hostapd-update-missing-5.9GHz-channels.patch deleted file mode 100644 index 843b297a0..000000000 --- a/feeds/ipq95xx/hostapd/patches/j00-001-hostapd-update-missing-5.9GHz-channels.patch +++ /dev/null @@ -1,61 +0,0 @@ -From b6bb46ef161e1c3890f517fdb04f081926fc1a08 Mon Sep 17 00:00:00 2001 -From: Seevalamuthu Mariappan -Date: Tue, 23 Mar 2021 19:57:43 +0530 -Subject: [PATCH] hostapd: update missing 5.9GHz channels - -Update channel 165 and 173 in allowed channel. -This fixes below upstream commit, -833cdbe - "Add support for new 5 GHz channels 173 and 177" - -Signed-off-by: Seevalamuthu Mariappan ---- - src/common/hw_features_common.c | 2 +- - wpa_supplicant/wpa_supplicant.c | 4 ++-- - 2 files changed, 3 insertions(+), 3 deletions(-) - -Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/wpa_supplicant.c -+++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant.c -@@ -2540,8 +2540,8 @@ void ibss_mesh_setup_freq(struct wpa_sup - enum hostapd_hw_mode hw_mode; - struct hostapd_hw_modes *mode = NULL; - int ht40plus[] = { 1, 2, 3, 4, 5, 6, 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157, -- 184, 192 }; -- int bw80[] = { 5180, 5260, 5500, 5580, 5660, 5745, 5955, -+ 165, 173, 184, 192 }; -+ int bw80[] = { 5180, 5260, 5500, 5580, 5660, 5745, 5825, 5955, - 6035, 6115, 6195, 6275, 6355, 6435, 6515, - 6595, 6675, 6755, 6835, 6915, 6995 }; - int bw160[] = { 5955, 6115, 6275, 6435, 6595, 6755, 6915 }; -Index: hostapd-2021-12-13-b26f5c0f/src/ap/acs.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/ap/acs.c -+++ hostapd-2021-12-13-b26f5c0f/src/ap/acs.c -@@ -369,7 +369,7 @@ acs_survey_chan_interference_factor(stru - static int acs_usable_bw40_chan(const struct hostapd_channel_data *chan) - { - const int allowed[] = { 5180, 5220, 5260, 5300, 5500, 5540, 5580, 5620, -- 5660, 5745, 5785, 4920, 4960, 5955, 5995, 6035, -+ 5660, 5745, 5785, 5825, 5865, 4920, 4960, 5955, 5995, 6035, - 6075, 6115, 6155, 6195, 6235, 6275, 6315, 6355, - 6395, 6435, 6475, 6515, 6555, 6595, 6635, 6675, - 6715, 6755, 6795, 6835, 6875, 6915, 6955, 6995, -@@ -386,7 +386,7 @@ static int acs_usable_bw40_chan(const st - - static int acs_usable_bw80_chan(const struct hostapd_channel_data *chan) - { -- const int allowed[] = { 5180, 5260, 5500, 5580, 5660, 5745, 5955, 6035, -+ const int allowed[] = { 5180, 5260, 5500, 5580, 5660, 5745, 5825, 5955, 6035, - 6115, 6195, 6275, 6355, 6435, 6515, 6595, 6675, - 6755, 6835, 6915, 6995 }; - unsigned int i; -@@ -401,7 +401,7 @@ static int acs_usable_bw80_chan(const st - - static int acs_usable_bw160_chan(const struct hostapd_channel_data *chan) - { -- const int allowed[] = { 5180, 5500, 5955, 6115, 6275, 6435, 6595, 6755, -+ const int allowed[] = { 5180, 5500, 5745, 5955, 6115, 6275, 6435, 6595, 6755, - 6915 }; - unsigned int i; - diff --git a/feeds/ipq95xx/hostapd/patches/k00-001-hostapd-cli-allowed-bw-on-each-channel.patch b/feeds/ipq95xx/hostapd/patches/k00-001-hostapd-cli-allowed-bw-on-each-channel.patch deleted file mode 100644 index 2731032d1..000000000 --- a/feeds/ipq95xx/hostapd/patches/k00-001-hostapd-cli-allowed-bw-on-each-channel.patch +++ /dev/null @@ -1,329 +0,0 @@ -From 6cbf57cd8899d8a531706c9f85393f602cd08219 Mon Sep 17 00:00:00 2001 -From: Hari Chandrakanthan -Date: Tue, 4 May 2021 12:35:55 +0530 -Subject: [PATCH] hostapd cli cmd to display allowed bw on each channel - -Signed-off-by: Hari Chandrakanthan ---- - hostapd/ctrl_iface.c | 235 ++++++++++++++++++++++++++++++++++++++------------ - hostapd/hostapd_cli.c | 10 +-- - 2 files changed, 185 insertions(+), 60 deletions(-) - -diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c -index bbe49aa..ea1a156 100644 ---- a/hostapd/ctrl_iface.c -+++ b/hostapd/ctrl_iface.c -@@ -3215,75 +3215,202 @@ set: - return ret; - } - --static int hostapd_2ghz_ht40_allow_map(struct hostapd_hw_modes *mode, -- char *buf, size_t buflen) -+static int hostapd_2ghz_channel_bw(struct hostapd_hw_modes *mode, char *buf, -+ size_t buflen) - { -- int j, ret, len = 0; -+ int ch, ret, len = 0; -+ char temp_buf[30] = {0}; - -- for (j = 0; j < mode->num_channels; j++) { -- struct hostapd_channel_data *chan = &mode->channels[j]; -- if (!(chan->flag & HOSTAPD_CHAN_DISABLED)) { -- ret = os_snprintf(buf + len, buflen - len, -- "Channel: %d : %d HT40%c%c\n", -- chan->chan, chan->freq, -- (chan->flag & HOSTAPD_CHAN_HT40MINUS) ? -- '-' : ' ', -- (chan->flag & HOSTAPD_CHAN_HT40PLUS) ? -- '+' : ' '); -- if (os_snprintf_error(buflen - len, ret)) -- return len; -- len += ret; -- } -+ for (ch = 0; ch < mode->num_channels; ch++) { -+ struct hostapd_channel_data *chan = &mode->channels[ch]; -+ if (chan->flag & HOSTAPD_CHAN_DISABLED) -+ continue; -+ ret = os_snprintf(temp_buf, 30, "Channel[%d]", chan->chan); -+ if (os_snprintf_error(30, ret)) -+ return len; -+ ret = os_snprintf(buf + len, buflen - len, -+ "%-13s : %d - 20MHz HT40%c%c\n", -+ temp_buf, chan->freq, -+ (chan->flag & HOSTAPD_CHAN_HT40MINUS)?'-':' ', -+ (chan->flag & HOSTAPD_CHAN_HT40PLUS)?'+':' '); -+ if (os_snprintf_error(buflen - len, ret)) -+ return len; -+ len += ret; - } - return len; - } - --static int hostapd_5ghz_ht40_allow_map(struct hostapd_hw_modes *mode, -- char *buf, size_t buflen) -+static int hostapd_get_channel_idx(struct hostapd_hw_modes *mode, -+ int channel_num) - { -- int j, k, ok, ret, len = 0, allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 140, -- 149, 157, 184, 192 }; -+ int j=0; - -- for (j = 0; j < mode->num_channels; j++) { -+ for(j = 0; j < mode->num_channels; j++) { - struct hostapd_channel_data *chan = &mode->channels[j]; -+ if(chan->chan == channel_num) -+ return j; -+ } -+ return -1; -+} - -- if ((chan->flag & HOSTAPD_CHAN_HT40MINUS) || -- (chan->flag & HOSTAPD_CHAN_HT40PLUS)) { -- ok = 0; -- for (k = 0; k < ARRAY_SIZE(allowed); k++) { -- if (chan->chan < allowed[k]) -- break; -- if (chan->chan == allowed[k]) { -- ok = 1; -- break; -- } -+static int hostapd_5ghz_vht_80_channel_bw(struct hostapd_hw_modes *mode, -+ int channel_idx) -+{ -+ int k, m, ok, allowed[][4] = {{36, 40, 44, 48}, {52, 56, 60, 64}, -+ {100, 104, 108, 112}, {116, 120, 124, 128}, -+ {132, 136, 140, 144}, {149, 153, 157, 161}}; -+ struct hostapd_channel_data *chan = &mode->channels[channel_idx]; -+ -+ ok = 0; -+ for (k = 0; k < ARRAY_SIZE(allowed); k++) { -+ for(m = 0; m < ARRAY_SIZE(allowed[0]); m++) { -+ if (chan->chan == allowed[k][m]) { -+ ok = 1; -+ break; - } -+ } -+ if(ok == 1) -+ break; -+ } - -- if (!ok && chan->chan != (allowed[k - 1] + 4)) -- ok = -1; -- -- if (ok == 1 && (mode->channels[j + 1].flag & -- HOSTAPD_CHAN_DISABLED)) -- ok = -1; -+ if (ok == 0) -+ return false; - -- if (ok != -1) { -- ret = os_snprintf(buf + len, buflen - len, -- "Channel: %d : %d HT40%s\n", -- chan->chan, chan->freq, -- ok == 1 ? "+" : "-"); -+ for(m = 0; m < ARRAY_SIZE(allowed[0]); m++) { -+ channel_idx = hostapd_get_channel_idx(mode, allowed[k][m]); -+ if((channel_idx == -1) || (mode->channels[channel_idx].flag & -+ HOSTAPD_CHAN_DISABLED)) -+ return false; -+ } - -- if (os_snprintf_error(buflen - len, ret)) -- return len; -+ return true; -+} - -- len += ret; -+static bool hostapd_5ghz_vht_160_channel_bw(struct hostapd_hw_modes *mode, -+ int channel_idx) -+{ -+ int k, m, ok, allowed[][8] = {{36, 40, 44, 48, 52, 56, 60, 64}, -+ {100, 104, 108, 112, 116, 120, 124, 128}}; -+ struct hostapd_channel_data *chan = &mode->channels[channel_idx]; -+ -+ ok = 0; -+ for (k = 0; k < ARRAY_SIZE(allowed); k++) { -+ for(m = 0; m < ARRAY_SIZE(allowed[0]); m++) { -+ if (chan->chan == allowed[k][m]) { -+ ok = 1; -+ break; - } - } -+ if(ok == 1) -+ break; -+ } -+ -+ if (ok == 0) -+ return false; -+ -+ for(m = 0; m < ARRAY_SIZE(allowed[0]); m++) { -+ channel_idx = hostapd_get_channel_idx(mode, allowed[k][m]); -+ if (channel_idx == -1 || (mode->channels[channel_idx].flag & -+ HOSTAPD_CHAN_DISABLED)) -+ return false; -+ } -+ return true; -+} -+ -+static int hostapd_5ghz_ht_40_channel_bw(struct hostapd_hw_modes *mode, -+ int channel_idx) -+{ -+ -+ int k, ok, allowed[] = {36, 44, 52, 60, 100, 108, 116, 124, 132, 140, -+ 149, 157, 184, 192}; -+ struct hostapd_channel_data *chan = &mode->channels[channel_idx]; -+ -+ if (!((chan->flag & HOSTAPD_CHAN_HT40MINUS) || -+ (chan->flag & HOSTAPD_CHAN_HT40PLUS))) -+ return 0; -+ -+ ok = 0; -+ for (k = 0; k < ARRAY_SIZE(allowed); k++) { -+ if (chan->chan < allowed[k]) -+ break; -+ if (chan->chan == allowed[k]) { -+ ok = 1; -+ break; -+ } -+ } -+ -+ if (!ok && chan->chan != (allowed[k - 1] + 4)) -+ ok = -1; -+ -+ if (ok == 1 && (mode->channels[channel_idx + 1].flag & -+ HOSTAPD_CHAN_DISABLED)) -+ ok = -1; -+ -+ if (ok != -1) { -+ if( ok == 1) -+ return HOSTAPD_CHAN_HT40PLUS; -+ else -+ return HOSTAPD_CHAN_HT40MINUS; -+ } -+ return 0; -+} -+ -+static int hostapd_5ghz_channel_bw(struct hostapd_hw_modes *mode, -+ char *buf, size_t buflen) -+{ -+ int j, ret, ret_val, len = 0; -+ char temp_buf[30] = {0}; -+ -+ for (j = 0; j < mode->num_channels; j++) { -+ struct hostapd_channel_data *chan = &mode->channels[j]; -+ if (chan->flag & HOSTAPD_CHAN_DISABLED) -+ continue; -+ -+ ret = os_snprintf(temp_buf, 30, "Channel[%d]", chan->chan); -+ if (os_snprintf_error(30, ret)) -+ return len; -+ -+ ret = os_snprintf(buf + len, buflen - len, "%-13s : %d - 20MHz ", -+ temp_buf, chan->freq); -+ if (os_snprintf_error(buflen - len, ret)) -+ return len; -+ len += ret; -+ -+ ret_val = hostapd_5ghz_ht_40_channel_bw(mode, j); -+ if(ret_val) { -+ ret = os_snprintf(buf + len, buflen - len, "HT40%s ", -+ ret_val == HOSTAPD_CHAN_HT40PLUS? "+":"-"); -+ if (os_snprintf_error(buflen - len, ret)) -+ return len; -+ len += ret; -+ } -+ -+ if(hostapd_5ghz_vht_80_channel_bw(mode, j)) { -+ ret = os_snprintf(buf + len, buflen - len, "80MHz "); -+ if (os_snprintf_error(buflen - len, ret)) -+ return len; -+ len += ret; -+ } -+ -+ if((mode->vht_capab & (VHT_CAP_SUPP_CHAN_WIDTH_160MHZ | -+ VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)) && -+ hostapd_5ghz_vht_160_channel_bw(mode, j)) { -+ ret = os_snprintf(buf + len, buflen - len, "160MHz "); -+ if (os_snprintf_error(buflen - len, ret)) -+ return len; -+ len += ret; -+ } -+ -+ ret = os_snprintf(buf + len, buflen - len,"\n"); -+ if (os_snprintf_error(buflen - len, ret)) -+ return len; -+ len += ret; - } - return len; - } - --static int hostapd_ctrl_iface_ht40_allow_map(struct hostapd_iface *iface, -- char *buf, size_t buflen) -+static int hostapd_ctrl_iface_channel_bw(struct hostapd_iface *iface, -+ char *buf, size_t buflen) - { - struct hostapd_data *hapd = iface->bss[0]; - struct hostapd_hw_modes *mode; -@@ -3295,11 +3422,12 @@ static int hostapd_ctrl_iface_ht40_allow_map(struct hostapd_iface *iface, - &dfs_domain); - - if (mode->mode != HOSTAPD_MODE_IEEE80211A) -- len = hostapd_2ghz_ht40_allow_map(mode, buf, buflen); -+ len = hostapd_2ghz_channel_bw(mode, buf, buflen); - else -- len = hostapd_5ghz_ht40_allow_map(mode, buf, buflen); -+ len = hostapd_5ghz_channel_bw(mode, buf, buflen); - - return len; -+ - } - - static int hostapd_ctrl_iface_remove_neighbor(struct hostapd_data *hapd, -@@ -3912,10 +4040,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, - if (radius_server_dac_request(hapd->radius_srv, buf + 12) < 0) - reply_len = -1; - #endif /* RADIUS_SERVER */ -- } else if (os_strcmp(buf, "HT40_ALLOW_MAP") == 0) { -- reply_len = hostapd_ctrl_iface_ht40_allow_map(hapd->iface, -- reply, -- reply_size); -+ } else if(os_strcmp(buf, "CHANNEL_BW") == 0) { -+ reply_len = hostapd_ctrl_iface_channel_bw(hapd->iface, reply, -+ reply_size); - } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) { - reply_len = hostapd_ctrl_iface_get_capability( - hapd, buf + 15, reply, reply_size); -diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c -index 6ee8d96..14317f5 100644 ---- a/hostapd/hostapd_cli.c -+++ b/hostapd/hostapd_cli.c -@@ -1384,13 +1384,11 @@ static int hostapd_cli_cmd_driver_flags(struct wpa_ctrl *ctrl, int argc, - return wpa_ctrl_command(ctrl, "DRIVER_FLAGS"); - } - --static int hostapd_cli_cmd_ht40_allow_map(struct wpa_ctrl *ctrl, -+static int hostapd_cli_cmd_channel_bw(struct wpa_ctrl *ctrl, - int argc, char *argv[]) - { -- return wpa_ctrl_command(ctrl, "HT40_ALLOW_MAP"); -+ return wpa_ctrl_command(ctrl, "CHANNEL_BW"); - } -- -- - #ifdef CONFIG_DPP - - static int hostapd_cli_cmd_dpp_qr_code(struct wpa_ctrl *ctrl, int argc, -@@ -1753,8 +1751,8 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = { - "=Add/Delete/Show/Clear deny MAC ACL" }, - { "poll_sta", hostapd_cli_cmd_poll_sta, hostapd_complete_stations, - " = poll a STA to check connectivity with a QoS null frame" }, -- { "ht40_allow_map", hostapd_cli_cmd_ht40_allow_map, NULL, -- "= show ht40 allow map status" }, -+ { "channel_bw", hostapd_cli_cmd_channel_bw, NULL, -+ "= show allowed bandwidth on each channel"}, - { "req_beacon", hostapd_cli_cmd_req_beacon, NULL, - " [req_mode=] = send a Beacon report request to a station" }, - { "reload_wpa_psk", hostapd_cli_cmd_reload_wpa_psk, NULL, --- -2.7.4 - diff --git a/feeds/ipq95xx/hostapd/patches/k00-001-hostapd-macsec-support-gcmaes256-cipher-suite-when-participant-act-as-key-server.patch b/feeds/ipq95xx/hostapd/patches/k00-001-hostapd-macsec-support-gcmaes256-cipher-suite-when-participant-act-as-key-server.patch deleted file mode 100644 index 91fcbccc3..000000000 --- a/feeds/ipq95xx/hostapd/patches/k00-001-hostapd-macsec-support-gcmaes256-cipher-suite-when-participant-act-as-key-server.patch +++ /dev/null @@ -1,195 +0,0 @@ -From cd028d950808096de588d99ef5a082a33d4965db Mon Sep 17 00:00:00 2001 -From: leiwei -Date: Fri, 23 Apr 2021 19:54:24 +0800 -Subject: [PATCH] hostap:Support GCM-AES-256 cipher suite select when - participant act as key server - -Signed-off-by: leiwei ---- - hostapd/config_file.c | 10 ++++++++++ - src/ap/ap_config.h | 7 +++++++ - src/ap/wpa_auth_kay.c | 3 ++- - src/pae/ieee802_1x_cp.c | 6 +++--- - src/pae/ieee802_1x_kay.c | 13 ++++++++++--- - src/pae/ieee802_1x_kay.h | 2 +- - wpa_supplicant/config.c | 1 + - wpa_supplicant/config_ssid.h | 7 +++++++ - wpa_supplicant/wpas_kay.c | 4 ++-- - 9 files changed, 43 insertions(+), 10 deletions(-) - -diff --git a/hostapd/config_file.c b/hostapd/config_file.c -index 08a5bcd..39ea156 100644 ---- a/hostapd/config_file.c -+++ b/hostapd/config_file.c -@@ -4530,6 +4530,16 @@ static int hostapd_config_fill(struct hostapd_config *conf, - return 1; - } - bss->mka_priority = mka_priority; -+ } else if (os_strcmp(buf, "macsec_csindex") == 0) { -+ int macsec_csindex = atoi(pos); -+ -+ if (macsec_csindex < 0 || macsec_csindex > 1) { -+ wpa_printf(MSG_ERROR, -+ "Line %d: invalid macsec_csindex (%d): '%s'.", -+ line, macsec_csindex, pos); -+ return 1; -+ } -+ bss->macsec_csindex = macsec_csindex; - } else if (os_strcmp(buf, "mka_cak") == 0) { - size_t len = os_strlen(pos); - -diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h -index 05f3c7d..ad37222 100644 ---- a/src/ap/ap_config.h -+++ b/src/ap/ap_config.h -@@ -850,6 +850,13 @@ struct hostapd_bss_config { - int mka_priority; - - /** -+ * macsec_csindex - chipher suite index of macsec -+ * -+ * Range: 0-1 (default: 0) -+ */ -+ int macsec_csindex; -+ -+ /** - * mka_ckn - MKA pre-shared CKN - */ - #define MACSEC_CKN_MAX_LEN 32 -diff --git a/src/ap/wpa_auth_kay.c b/src/ap/wpa_auth_kay.c -index 46d94b4..d5341e2 100644 ---- a/src/ap/wpa_auth_kay.c -+++ b/src/ap/wpa_auth_kay.c -@@ -329,7 +329,8 @@ int ieee802_1x_alloc_kay_sm_hapd(struct hostapd_data *hapd, - hapd->conf->macsec_replay_protect, - hapd->conf->macsec_replay_window, - hapd->conf->macsec_port, -- hapd->conf->mka_priority, hapd->conf->iface, -+ hapd->conf->mka_priority, -+ hapd->conf->macsec_csindex, hapd->conf->iface, - hapd->own_addr); - /* ieee802_1x_kay_init() frees kay_ctx on failure */ - if (!res) -diff --git a/src/pae/ieee802_1x_cp.c b/src/pae/ieee802_1x_cp.c -index cf41d8d..f0527fd 100644 ---- a/src/pae/ieee802_1x_cp.c -+++ b/src/pae/ieee802_1x_cp.c -@@ -20,7 +20,7 @@ - #define STATE_MACHINE_DATA struct ieee802_1x_cp_sm - #define STATE_MACHINE_DEBUG_PREFIX "CP" - --static u64 default_cs_id = CS_ID_GCM_AES_128; -+static u64 cs_id[]={CS_ID_GCM_AES_128, CS_ID_GCM_AES_256}; - - /* The variable defined in clause 12 in IEEE Std 802.1X-2010 */ - enum connect_type { PENDING, UNAUTHENTICATED, AUTHENTICATED, SECURE }; -@@ -473,8 +473,8 @@ struct ieee802_1x_cp_sm * ieee802_1x_cp_sm_init(struct ieee802_1x_kay *kay) - sm->orx = false; - sm->otx = false; - -- sm->current_cipher_suite = default_cs_id; -- sm->cipher_suite = default_cs_id; -+ sm->current_cipher_suite = cs_id[kay->macsec_csindex]; -+ sm->cipher_suite = cs_id[kay->macsec_csindex]; - sm->cipher_offset = CONFIDENTIALITY_OFFSET_0; - sm->confidentiality_offset = sm->cipher_offset; - sm->transmit_delay = MKA_LIFE_TIME; -diff --git a/src/pae/ieee802_1x_kay.c b/src/pae/ieee802_1x_kay.c -index ad5a34b..04a7e93 100644 ---- a/src/pae/ieee802_1x_kay.c -+++ b/src/pae/ieee802_1x_kay.c -@@ -222,7 +222,14 @@ ieee802_1x_mka_dump_dist_sak_body(struct ieee802_1x_mka_dist_sak_body *body) - wpa_printf(MSG_DEBUG, "\tKey Number............: %d", - be_to_host32(body->kn)); - /* TODO: Other than GCM-AES-128 case: MACsec Cipher Suite */ -- wpa_hexdump(MSG_DEBUG, "\tAES Key Wrap of SAK...:", body->sak, 24); -+ if(body_len == 28){ -+ wpa_hexdump(MSG_INFO, "\tAES Key Wrap of SAK...:", body->sak, 24); -+ } -+ else{ -+ wpa_hexdump(MSG_INFO, "\tMacsec Cipher Suite...:", body->sak, CS_ID_LEN); -+ wpa_hexdump(MSG_INFO, "\tAES Key Wrap of SAK...:", body->sak + CS_ID_LEN, -+ body_len - CS_ID_LEN - sizeof(body->kn)); -+ } - } - - -@@ -3458,7 +3465,7 @@ static void kay_l2_receive(void *ctx, const u8 *src_addr, const u8 *buf, - struct ieee802_1x_kay * - ieee802_1x_kay_init(struct ieee802_1x_kay_ctx *ctx, enum macsec_policy policy, - bool macsec_replay_protect, u32 macsec_replay_window, -- u16 port, u8 priority, const char *ifname, const u8 *addr) -+ u16 port, u8 priority, u32 macsec_csindex, const char *ifname, const u8 *addr) - { - struct ieee802_1x_kay *kay; - -@@ -3495,7 +3502,7 @@ ieee802_1x_kay_init(struct ieee802_1x_kay_ctx *ctx, enum macsec_policy policy, - kay->dist_time = 0; - - kay->pn_exhaustion = PENDING_PN_EXHAUSTION; -- kay->macsec_csindex = DEFAULT_CS_INDEX; -+ kay->macsec_csindex = macsec_csindex; - kay->mka_algindex = DEFAULT_MKA_ALG_INDEX; - kay->mka_version = MKA_VERSION_ID; - -diff --git a/src/pae/ieee802_1x_kay.h b/src/pae/ieee802_1x_kay.h -index 1d3c2ac..a3cf964 100644 ---- a/src/pae/ieee802_1x_kay.h -+++ b/src/pae/ieee802_1x_kay.h -@@ -240,7 +240,7 @@ u64 mka_sci_u64(struct ieee802_1x_mka_sci *sci); - struct ieee802_1x_kay * - ieee802_1x_kay_init(struct ieee802_1x_kay_ctx *ctx, enum macsec_policy policy, - bool macsec_replay_protect, u32 macsec_replay_window, -- u16 port, u8 priority, const char *ifname, const u8 *addr); -+ u16 port, u8 priority, u32 macsec_csindex, const char *ifname, const u8 *addr); - void ieee802_1x_kay_deinit(struct ieee802_1x_kay *kay); - - struct ieee802_1x_mka_participant * -diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c -index 7e7d9bb..f723b70 100644 ---- a/wpa_supplicant/config.c -+++ b/wpa_supplicant/config.c -@@ -2777,6 +2777,7 @@ static const struct parse_data ssid_fields[] = { - { INT(macsec_replay_window) }, - { INT_RANGE(macsec_port, 1, 65534) }, - { INT_RANGE(mka_priority, 0, 255) }, -+ { INT_RANGE(macsec_csindex, 0, 1) }, - { FUNC_KEY(mka_cak) }, - { FUNC_KEY(mka_ckn) }, - #endif /* CONFIG_MACSEC */ -diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h -index b655e39..747e4d0 100644 ---- a/wpa_supplicant/config_ssid.h -+++ b/wpa_supplicant/config_ssid.h -@@ -915,6 +915,13 @@ struct wpa_ssid { - int mka_priority; - - /** -+ * macsec_csindex - chipher suite index of macsec -+ * -+ * Range: 0-1 (default: 0) -+ */ -+ int macsec_csindex; -+ -+ /** - * mka_ckn - MKA pre-shared CKN - */ - #define MACSEC_CKN_MAX_LEN 32 -diff --git a/wpa_supplicant/wpas_kay.c b/wpa_supplicant/wpas_kay.c -index defd0f2..4d1ce02 100644 ---- a/wpa_supplicant/wpas_kay.c -+++ b/wpa_supplicant/wpas_kay.c -@@ -241,8 +241,8 @@ int ieee802_1x_alloc_kay_sm(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) - - res = ieee802_1x_kay_init(kay_ctx, policy, ssid->macsec_replay_protect, - ssid->macsec_replay_window, ssid->macsec_port, -- ssid->mka_priority, wpa_s->ifname, -- wpa_s->own_addr); -+ ssid->mka_priority, ssid->macsec_csindex, -+ wpa_s->ifname, wpa_s->own_addr); - /* ieee802_1x_kay_init() frees kay_ctx on failure */ - if (res == NULL) - return -1; --- -2.7.4 - diff --git a/feeds/ipq95xx/hostapd/patches/k00-002-hostapd-Fix-channel-switch-on-6g.patch b/feeds/ipq95xx/hostapd/patches/k00-002-hostapd-Fix-channel-switch-on-6g.patch deleted file mode 100644 index 09518d95a..000000000 --- a/feeds/ipq95xx/hostapd/patches/k00-002-hostapd-Fix-channel-switch-on-6g.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 6e1348ac1eaa8a4a62dccce588aa9306f876b068 Mon Sep 17 00:00:00 2001 -From: Anilkumar Kolli -Date: Mon, 24 May 2021 22:18:11 +0530 -Subject: [PATCH] hostapd: Fix channel switch on 6g - -Below cmd does not return fail, but fails to update beacon. -Center frequency used in command is not valid for 80M bandwidth. - - hostapd_cli -i wlan0 chan_switch 5 6315 sec_channel_offset=1 - center_freq1=6345 bandwidth=80 he - -This patch adds condition check to validate the center frequency. - -Signed-off-by: Anilkumar Kolli ---- - hostapd/ctrl_iface.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c -index ea1a1567278c..664711d5bd87 100644 ---- a/hostapd/ctrl_iface.c -+++ b/hostapd/ctrl_iface.c -@@ -2528,6 +2528,16 @@ static int hostapd_ctrl_get_pmk(struct hostapd_data *hapd, const char *cmd, - #ifdef NEED_AP_MLME - static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params) - { -+ int idx, bw, bw_idx[] = { 20, 40, 80, 160 }; -+ -+ if (is_6ghz_freq(params->freq) && params->center_freq1) { -+ idx = (params->center_freq1 - 5950) / 5; -+ bw = center_idx_to_bw_6ghz(idx); -+ -+ if (bw < 0 || (bw_idx[bw] != params->bandwidth)) -+ return -1; -+ } -+ - switch (params->bandwidth) { - case 0: - /* bandwidth not specified: use 20 MHz by default */ --- -2.7.4 - diff --git a/feeds/ipq95xx/hostapd/patches/l00-001-hostapd-avoid-filling-group-mgmt-cipher-type-in-FD-R.patch b/feeds/ipq95xx/hostapd/patches/l00-001-hostapd-avoid-filling-group-mgmt-cipher-type-in-FD-R.patch deleted file mode 100644 index 0afd86547..000000000 --- a/feeds/ipq95xx/hostapd/patches/l00-001-hostapd-avoid-filling-group-mgmt-cipher-type-in-FD-R.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 2149e44c4a1767645c889de3e1712465b7fe5137 Mon Sep 17 00:00:00 2001 -From: Sriram R -Date: Wed, 12 May 2021 20:03:07 +0530 -Subject: [PATCH] hostapd: avoid filling group mgmt cipher type in FD RSN to - reflect beacon RSN IE - -Currently we don’t advertise Group Management cipher suite -in beacons if management frame protection is not enabled or -if the group management cipher is default (WPA_CIPHER_AES_128_CMAC) -but we advertise the suite type in FD RSN IE. - -Hence set it to 63, if management frame protection is disabled or when -default cipher is used. - -Signed-off-by: Sriram R ---- - src/ap/wpa_auth_ie.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/src/ap/wpa_auth_ie.c -+++ b/src/ap/wpa_auth_ie.c -@@ -1177,11 +1177,9 @@ bool wpa_auth_write_fd_rsn_info(struct w - - /* Group Management Cipher Suite Selector (B22..B27) */ - cipher = 63; /* Default to no cipher suite selected */ -- if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) { -+ if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION && -+ conf->group_mgmt_cipher != WPA_CIPHER_AES_128_CMAC) { - switch (conf->group_mgmt_cipher) { -- case WPA_CIPHER_AES_128_CMAC: -- cipher = RSN_CIPHER_SUITE_AES_128_CMAC & 0xff; -- break; - case WPA_CIPHER_BIP_GMAC_128: - cipher = RSN_CIPHER_SUITE_BIP_GMAC_128 & 0xff; - break; diff --git a/feeds/ipq95xx/hostapd/patches/l00-002-hostapd-fix-enabling-HE-thru-cli-in-2ghz.patch b/feeds/ipq95xx/hostapd/patches/l00-002-hostapd-fix-enabling-HE-thru-cli-in-2ghz.patch deleted file mode 100644 index 2fbdebd3d..000000000 --- a/feeds/ipq95xx/hostapd/patches/l00-002-hostapd-fix-enabling-HE-thru-cli-in-2ghz.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 994bff7d74eba00244b481a7d164a44412908ad6 Mon Sep 17 00:00:00 2001 -From: Karthikeyan Kathirvel -Date: Fri, 4 Jun 2021 22:19:27 +0530 -Subject: [PATCH] hostapd: unable to set HE mode on 2.4Ghz - -Channel switch through hostapd_cli is not able to operate in HE mode in -2.4Ghz. This is because since the he mode is not enabled for 2ghz the -channel type is set to 20Mhz NO_HT. - -Enabled he for 2Ghz radio on 20Mhz bandwidth for channel switch. - -Signed-off-by: Karthikeyan Kathirvel ---- - src/drivers/driver_nl80211.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c -index cbf41c6..a0dd827 100644 ---- a/src/drivers/driver_nl80211.c -+++ b/src/drivers/driver_nl80211.c -@@ -4979,7 +4979,7 @@ static int nl80211_put_freq_params(struct nl_msg *msg, - nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ2, - freq->center_freq2))) - return -ENOBUFS; -- } else if (freq->ht_enabled) { -+ } else if (freq->ht_enabled || (freq->he_enabled && is_24ghz)) { - enum nl80211_channel_type ct; - - wpa_printf(MSG_DEBUG, " * sec_channel_offset=%d", --- -2.7.4 - diff --git a/feeds/ipq95xx/hostapd/patches/m00-001-hostap-Avoid-adjacent-channel-selection-in-DFS-for-q.patch b/feeds/ipq95xx/hostapd/patches/m00-001-hostap-Avoid-adjacent-channel-selection-in-DFS-for-q.patch deleted file mode 100644 index af0b01c70..000000000 --- a/feeds/ipq95xx/hostapd/patches/m00-001-hostap-Avoid-adjacent-channel-selection-in-DFS-for-q.patch +++ /dev/null @@ -1,138 +0,0 @@ -From 420852ff044c804a6487ccc060f85c12bbdaac31 Mon Sep 17 00:00:00 2001 -From: Seevalamuthu Mariappan -Date: Thu, 1 Jul 2021 10:15:29 +0530 -Subject: [PATCH] hostap: Avoid selecting UNII-1 channel after DFS switch - -Avoid UNII-1 band channel from getting selected after DFS when primary -channel is UNII-2 band with 80Mhz configuration. - -To enable this, 'skip_unii1_dfs_switch' config should be enabled -in hostapd config. - -Signed-off-by: Seevalamuthu Mariappan ---- - hostapd/config_file.c | 2 ++ - src/ap/ap_config.h | 1 + - src/ap/dfs.c | 25 +++++++++++++++++++++++++ - 3 files changed, 28 insertions(+) - ---- a/hostapd/config_file.c -+++ b/hostapd/config_file.c -@@ -3377,6 +3377,8 @@ static int hostapd_config_fill(struct ho - conf->require_ht = atoi(pos); - } else if (os_strcmp(buf, "obss_interval") == 0) { - conf->obss_interval = atoi(pos); -+ } else if (os_strcmp(buf, "skip_unii1_dfs_switch") == 0) { -+ conf->skip_unii1_dfs_switch = atoi(pos); - #ifdef CONFIG_IEEE80211AC - } else if (os_strcmp(buf, "ieee80211ac") == 0) { - conf->ieee80211ac = atoi(pos); ---- a/src/ap/ap_config.h -+++ b/src/ap/ap_config.h -@@ -1045,6 +1045,7 @@ struct hostapd_config { - - /* Use driver-generated interface addresses when adding multiple BSSs */ - u8 use_driver_iface_addr; -+ u8 skip_unii1_dfs_switch; - - #ifdef CONFIG_FST - struct fst_iface_cfg fst_cfg; ---- a/src/ap/dfs.c -+++ b/src/ap/dfs.c -@@ -199,6 +199,64 @@ static int is_in_chanlist(struct hostapd - return freq_range_list_includes(&iface->conf->acs_ch_list, chan->chan); - } - -+#define HOSTAPD_DFS_UNII2_CHANNELS(chan) (chan >= 52 && chan <= 64) -+ -+static bool is_skip_unii1_dfs_switch_applicable(struct hostapd_iface *iface, -+ struct hostapd_channel_data *chan) -+{ -+ if (!iface->conf->skip_unii1_dfs_switch) -+ return false; -+ -+ /* skip if the selected channel is 52/56/60/64 */ -+ if (HOSTAPD_DFS_UNII2_CHANNELS(iface->conf->channel) && -+ HOSTAPD_DFS_UNII2_CHANNELS(chan->chan)) -+ return true; -+ -+ /* Skip below mentioned adjacent channels if one of the following -+ * conditions is true -+ * i) The primary channel of the AP is 52/56/60/64 in 80MHz mode and -+ * moves to adjacent channel 36/44/48 in 80MHz -+ * ii) The primary channel of the AP is 36/44/48/52/56/60/64 in 160MHz -+ * and moves to 36/44/48 in 80MHz mode -+ * iii) The primary channel of the AP is 52/56/60/64 in 20MHz or 40MHz mode -+ * and moves to the adjacent channels 40/44/48 in 20MHz mode or 36/40/44/48 -+ * in 40MHz mode -+ */ -+ switch(hostapd_get_oper_chwidth(iface->conf)) -+ { -+ case CHANWIDTH_160MHZ: -+ if ((iface->conf->channel >= 36) && -+ (iface->conf->channel <= 64) && -+ (iface->conf->channel != 40) && -+ (chan->chan >= 36) && (chan->chan <= 48) && -+ (chan->chan != 40)) -+ return true; -+ break; -+ case CHANWIDTH_80MHZ: -+ if ((iface->conf->channel >= 52) && -+ (iface->conf->channel <= 64) && -+ (chan->chan >= 36) && (chan->chan <= 48) && -+ (chan->chan != 40)) -+ return true; -+ break; -+ case CHANWIDTH_USE_HT: -+ if ((iface->conf->channel >= 52) && -+ (iface->conf->channel <= 64)) { -+ if (iface->conf->secondary_channel) { -+ if ((chan->chan >= 36) && (chan->chan <= 48)) -+ return true; -+ } else { -+ if ((chan->chan >= 40) && (chan->chan <= 48)) -+ return true; -+ } -+ } -+ break; -+ default: -+ break; -+ } -+ -+ return false; -+} - - /* - * The function assumes HT40+ operation. -@@ -248,6 +306,13 @@ static int dfs_find_channel(struct hosta - continue; - } - -+ if (is_skip_unii1_dfs_switch_applicable(iface, chan)) { -+ wpa_printf(MSG_DEBUG, -+ "DFS: skip_unii1_dfs_switch enabled, skip adjacent channel: %d (%d)", -+ chan->freq, chan->chan); -+ continue; -+ } -+ - if (chan->max_tx_power < iface->conf->min_tx_power) - continue; - -@@ -963,8 +1028,15 @@ dfs_downgrade_bandwidth(struct hostapd_i - int oper_chwidth; - - oper_chwidth = hostapd_get_oper_chwidth(iface->conf); -- if (oper_chwidth == CHANWIDTH_USE_HT) -- break; -+ if (oper_chwidth == CHANWIDTH_USE_HT) { -+ /* try finding 20MHz channels if skip_unii1_dfs_switch is enabled */ -+ if (!iface->conf->skip_unii1_dfs_switch || -+ !iface->conf->secondary_channel) -+ break; -+ iface->conf->secondary_channel = 0; -+ *skip_radar = 1; -+ continue; -+ } - *skip_radar = 1; - hostapd_set_oper_chwidth(iface->conf, oper_chwidth - 1); - } diff --git a/feeds/ipq95xx/hostapd/patches/n00-001-hostapd-Add-support-to-awgn-mitigation-for-6Ghz.patch b/feeds/ipq95xx/hostapd/patches/n00-001-hostapd-Add-support-to-awgn-mitigation-for-6Ghz.patch deleted file mode 100644 index 2cc4539fb..000000000 --- a/feeds/ipq95xx/hostapd/patches/n00-001-hostapd-Add-support-to-awgn-mitigation-for-6Ghz.patch +++ /dev/null @@ -1,760 +0,0 @@ -From b581d1e5d5ef4adc4d60bca087942cc45fc653f1 Mon Sep 17 00:00:00 2001 -From: Hari Chandrakanthan -Date: Wed, 1 Dec 2021 21:27:36 +0530 -Subject: [PATCH] hostapd : Add support to awgn mitigation for 6Ghz - -when awgn interference is detected on operating channel, -AP is supposed to stop transmitting in that channel. -AP can reduce it's operating bandwidth or -completely move to another channel based on the -interference segment. - -hostapd receives awgn notification through NL80211_CMD_AWGN_DETECT -cmd and the NL attribute NL80211_ATTR_AWGN_INTERFERENCE_BITMAP -provides the channel interference information. - -Eg: For 80Mhz operating bandwidth, the chan bw interference -bitmap can be as follows. -segment chan_bw_interference_bitmap -0 0x01 -1 0x02 -2 0x04 -3 0x08 - -segment 0 - primary 20Mhz -segment 1 - secondary 20Mhz -segment 2 - secondary 40Mhz lower -segment 3 - secondary 40Mhz upper - -Signed-off-by: Hari Chandrakanthan ---- - hostapd/Makefile | 1 + - hostapd/config_file.c | 2 + - src/ap/Makefile | 1 + - src/ap/ap_config.c | 1 + - src/ap/ap_config.h | 1 + - src/ap/drv_callbacks.c | 13 + - src/ap/interference.c | 393 +++++++++++++++++++++++++++++ - src/ap/interference.h | 41 +++ - src/drivers/driver.h | 13 + - src/drivers/driver_common.c | 1 + - src/drivers/driver_nl80211_event.c | 30 +++ - src/drivers/nl80211_copy.h | 16 +- - wpa_supplicant/Makefile | 1 + - 13 files changed, 513 insertions(+), 1 deletion(-) - create mode 100644 src/ap/interference.c - create mode 100644 src/ap/interference.h - -diff --git a/hostapd/Makefile b/hostapd/Makefile -index 50f75bf2876a..002d68833c46 100644 ---- a/hostapd/Makefile -+++ b/hostapd/Makefile -@@ -1189,6 +1189,7 @@ OBJS += ../src/ap/ap_list.o - OBJS += ../src/ap/ieee802_11.o - OBJS += ../src/ap/hw_features.o - OBJS += ../src/ap/dfs.o -+OBJS += ../src/ap/interference.o - CFLAGS += -DNEED_AP_MLME - endif - OBJS += ../src/ap/ieee802_11_ht.o -diff --git a/hostapd/config_file.c b/hostapd/config_file.c -index afa07ef28f99..9f55bcd6ed2b 100644 ---- a/hostapd/config_file.c -+++ b/hostapd/config_file.c -@@ -3564,6 +3564,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, - return 1; - } - bss->unsol_bcast_probe_resp_interval = val; -+ } else if (os_strcmp(buf, "discard_6g_awgn_event") == 0) { -+ conf->discard_6g_awgn_event = atoi(pos); - #endif /* CONFIG_IEEE80211AX */ - } else if (os_strcmp(buf, "max_listen_interval") == 0) { - bss->max_listen_interval = atoi(pos); -diff --git a/src/ap/Makefile b/src/ap/Makefile -index a1e9b7c44d2f..22a21d31eda6 100644 ---- a/src/ap/Makefile -+++ b/src/ap/Makefile -@@ -36,6 +36,7 @@ LIB_OBJS= \ - ieee802_11_shared.o \ - ieee802_11_vht.o \ - ieee802_1x.o \ -+ interference.o \ - neighbor_db.o \ - ndisc_snoop.o \ - p2p_hostapd.o \ -diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c -index 9f86a4701ed4..1e27cb3d9416 100644 ---- a/src/ap/ap_config.c -+++ b/src/ap/ap_config.c -@@ -281,6 +281,7 @@ struct hostapd_config * hostapd_config_defaults(void) - conf->he_6ghz_max_ampdu_len_exp = 7; - conf->he_6ghz_rx_ant_pat = 1; - conf->he_6ghz_tx_ant_pat = 1; -+ conf->discard_6g_awgn_event = 0; - #endif /* CONFIG_IEEE80211AX */ - - /* The third octet of the country string uses an ASCII space character -diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h -index 32107f15bab8..261b1fafd74d 100644 ---- a/src/ap/ap_config.h -+++ b/src/ap/ap_config.h -@@ -1095,6 +1095,7 @@ struct hostapd_config { - #define AP_TYPE_6GHZ_STANDARD_POWER_AP 1 - #define AP_TYPE_6GHZ_VERY_LOW_POWER_AP 2 - u8 he_6ghz_reg_pwr_type; -+ bool discard_6g_awgn_event; - #endif /* CONFIG_IEEE80211AX */ - - /* VHT enable/disable config from CHAN_SWITCH */ -diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c -index 2c945b6d3f92..bf143beac9ac 100644 ---- a/src/ap/drv_callbacks.c -+++ b/src/ap/drv_callbacks.c -@@ -43,6 +43,7 @@ - #include "dpp_hostapd.h" - #include "fils_hlp.h" - #include "neighbor_db.h" -+#include "interference.h" - - #ifdef CONFIG_FILS - void hostapd_notify_assoc_fils_finish(struct hostapd_data *hapd, -@@ -1700,6 +1701,13 @@ static void hostapd_event_dfs_radar_detected(struct hostapd_data *hapd, - radar->cf1, radar->cf2); - } - -+static void hostapd_event_awgn_detected(struct hostapd_data *hapd, -+ struct awgn_event *awgn_info) -+{ -+ hostapd_intf_awgn_detected(hapd->iface, awgn_info->freq, awgn_info->chan_width, -+ awgn_info->cf1, awgn_info->cf2, -+ awgn_info->chan_bw_interference_bitmap); -+} - - static void hostapd_event_dfs_pre_cac_expired(struct hostapd_data *hapd, - struct dfs_event *radar) -@@ -2084,6 +2092,11 @@ void hostapd_wpa_event(void *ctx, enum wpa_event_type event, - break; - hostapd_event_dfs_radar_detected(hapd, &data->dfs_event); - break; -+ case EVENT_AWGN_DETECTED: -+ if (!data) -+ break; -+ hostapd_event_awgn_detected(hapd, &data->awgn_event); -+ break; - case EVENT_DFS_PRE_CAC_EXPIRED: - if (!data) - break; -diff --git a/src/ap/interference.c b/src/ap/interference.c -new file mode 100644 -index 000000000000..c51a4bfe9e30 ---- /dev/null -+++ b/src/ap/interference.c -@@ -0,0 +1,393 @@ -+/* -+ * AWGN - Additive white Gaussian Noise -+ * Copyright (c) 2002-2013, Jouni Malinen -+ * Copyright (c) 2013-2017, Qualcomm Atheros, Inc. -+ * -+ * This software may be distributed under the terms of the BSD license. -+ * See README for more details. -+ */ -+ -+/* -+ * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without modification, -+ * are permitted (subject to the limitations in the disclaimer below) provided that -+ * the following conditions are met: -+ * * Redistributions of source code must retain the above copyright notice, -+ * this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright notice, -+ * this list of conditions and the following disclaimer in the documentation and/or -+ * other materials provided with the distribution. -+ * * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its contributors -+ * may be used to endorse or promote products derived from this software without specific -+ * prior written permission. -+ * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS -+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include "utils/includes.h" -+ -+#include "utils/common.h" -+#include "common/ieee802_11_defs.h" -+#include "common/hw_features_common.h" -+#include "common/wpa_ctrl.h" -+#include "hostapd.h" -+#include "ap_drv_ops.h" -+#include "drivers/driver.h" -+#include "beacon.h" -+#include "eloop.h" -+#include "hw_features.h" -+ -+/* -+ * intf_awgn_chan_range_available - check whether the channel can operate -+ * in the given bandwidth in 6Ghz -+ * @first_chan_idx - channel index of the first 20Mhz channel in a segment -+ * @num_chans - number of 20Mhz channels needed for the operating bandwidth -+ */ -+static int intf_awgn_chan_range_available(struct hostapd_hw_modes *mode, -+ int first_chan_idx, int num_chans) -+{ -+ struct hostapd_channel_data *first_chan = NULL; -+ int allowed_40_6g[] = {1, 9, 17, 25, 33, 41, 49, 57, 65, 73, 81, 89, 97, 105, -+ 113, 121, 129, 137, 145, 153, 161, 169, 177, 185, 193, -+ 201, 209, 217, 225, 233}; -+ int allowed_80_6g[] = {1, 17, 33, 49, 65, 81, 97, 113, 129, 145, 161, 177, -+ 193, 209}; -+ int allowed_160_6g[] = {1, 33, 65, 97, 129, 161, 193}; -+ int chan_idx_match = 0; -+ int i; -+ -+ first_chan = &mode->channels[first_chan_idx]; -+ -+ if (!first_chan || !chan_pri_allowed(first_chan)) { -+ wpa_printf(MSG_DEBUG, "AWGN: primary channel not allowed"); -+ return 0; -+ } -+ -+ /* 20Mhz channel, so no need to check the range */ -+ if (num_chans == 1) -+ return 1; -+ -+ if (num_chans == 2) { /* 40Mhz channel */ -+ for (i = 0; i < ARRAY_SIZE(allowed_40_6g); i++) { -+ if (first_chan->chan == allowed_40_6g[i]) { -+ chan_idx_match = 1; -+ break; -+ } -+ } -+ } else if (num_chans == 4) { /* 80Mhz channel */ -+ for (i = 0; i < ARRAY_SIZE(allowed_80_6g); i++) { -+ if (first_chan->chan == allowed_80_6g[i]) { -+ chan_idx_match = 1; -+ break; -+ } -+ } -+ } else if (num_chans == 8) { /* 160Mhz channel */ -+ for (i = 0; i < ARRAY_SIZE(allowed_160_6g); i++) { -+ if (first_chan->chan == allowed_160_6g[i]) { -+ chan_idx_match = 1; -+ break; -+ } -+ } -+ } -+ -+ if (chan_idx_match == 1) -+ return 1; -+ -+ return 0; -+} -+ -+static int is_in_chanlist(struct hostapd_iface *iface, -+ struct hostapd_channel_data *chan) -+{ -+ if (!iface->conf->acs_ch_list.num) -+ return 1; -+ -+ return freq_range_list_includes(&iface->conf->acs_ch_list, chan->chan); -+} -+ -+/* -+ *intf_awgn_find_channel - find the channel that can operate with bandwidth chan_width. -+ If idx doesn't match with index of any of the existing channel, then the api -+ returns the total number of available chandefs that supports the provided bandwidth -+ * @idx - index of the channel -+ * @chan_width - bandwidth of the channel -+ */ -+static int intf_awgn_find_channel(struct hostapd_iface *iface, -+ struct hostapd_channel_data **ret_chan, -+ int idx, int chan_width) -+{ -+ struct hostapd_hw_modes *mode = iface->current_mode; -+ struct hostapd_channel_data *chan; -+ int i, channel_idx = 0, n_chans; -+ -+ switch (chan_width) { -+ case CHAN_WIDTH_20_NOHT: -+ case CHAN_WIDTH_20: -+ n_chans = 1; -+ break; -+ case CHAN_WIDTH_40: -+ n_chans = 2; -+ break; -+ case CHAN_WIDTH_80: -+ n_chans = 4; -+ break; -+ case CHAN_WIDTH_80P80: -+ case CHAN_WIDTH_160: -+ n_chans = 8; -+ break; -+ default: -+ n_chans = 1; -+ break; -+ } -+ -+ for (i = 0; i < mode->num_channels; i++) { -+ chan = &mode->channels[i]; -+ -+ /* Skip incompatible chandefs */ -+ if (!intf_awgn_chan_range_available(mode, i, n_chans)) { -+ wpa_printf(MSG_DEBUG, -+ "AWGN: range not available for %d (%d)", -+ chan->freq, chan->chan); -+ continue; -+ } -+ -+ if (!is_in_chanlist(iface, chan)) { -+ wpa_printf(MSG_DEBUG, -+ "AWGN: channel %d (%d) not in chanlist", -+ chan->freq, chan->chan); -+ continue; -+ } -+ -+ if (ret_chan && idx == channel_idx) { -+ wpa_printf(MSG_DEBUG, "AWGN: Selected channel %d (%d)", -+ chan->freq, chan->chan); -+ *ret_chan = chan; -+ return idx; -+ } -+ -+ wpa_printf(MSG_DEBUG, "AWGN: Adding channel %d (%d)", -+ chan->freq, chan->chan); -+ channel_idx++; -+ } -+ return channel_idx; -+} -+ -+enum chan_seg { -+ SEG_PRI20 = 0x1, -+ SEG_SEC20 = 0x2, -+ SEG_SEC40_LOWER = 0x4, -+ SEG_SEC40_UPPER = 0x8, -+ SEG_SEC40 = 0xC, -+ SEG_SEC80_LOWER = 0x10, -+ SEG_SEC80_LOWER_UPPER = 0x20, -+ SEG_SEC80_UPPER_LOWER = 0x40, -+ SEG_SEC80_UPPER = 0x80, -+ SEG_SEC80 = 0xF0, -+}; -+ -+#define BASE_6G_FREQ 5950 -+ -+int get_centre_freq_6g(int chan_idx, int chan_width, int *centre_freq) -+{ -+ if (!centre_freq) -+ return -1; -+ -+ *centre_freq = 0; -+ -+ switch (chan_width) { -+ case CHAN_WIDTH_40: -+ if (chan_idx >= 1 && chan_idx <= 229) -+ *centre_freq = ((chan_idx / 8) * 8 + 3) * 5 + BASE_6G_FREQ; -+ break; -+ case CHAN_WIDTH_80: -+ if (chan_idx >= 1 && chan_idx <= 221) -+ *centre_freq = ((chan_idx / 16) * 16 + 7) * 5 + BASE_6G_FREQ; -+ break; -+ case CHAN_WIDTH_160: -+ if (chan_idx >= 1 && chan_idx <= 221) -+ *centre_freq = ((chan_idx / 32) * 32 + 15) * 5 + BASE_6G_FREQ; -+ break; -+ default: -+ break; -+ } -+ -+ if (*centre_freq == 0) -+ return -1; -+ -+ return 0; -+} -+ -+/* -+ * hostapd_intf_awgn_detected - awgn interference is detected in the operating channel. -+ * The interference channel information is available as a -+ * bitmap(chan_bw_interference_bitmap). If interference has occurred in the -+ * primary channel, do a complete channel switch to a different channel else -+ * reduce the operating bandwidth and continue ap operation in the same channel. -+ */ -+int hostapd_intf_awgn_detected(struct hostapd_iface *iface, int freq, int chan_width, -+ int cf1, int cf2, u32 chan_bw_interference_bitmap) -+{ -+ struct csa_settings settings; -+ struct hostapd_channel_data *chan_data = NULL; -+ struct hostapd_channel_data *chan_temp = NULL; -+ int ret; -+ unsigned int i; -+ u32 _rand; -+ u32 chan_idx; -+ int num_available_chandefs; -+ u8 channel_switch = 0; -+ int new_chan_width; -+ int new_centre_freq; -+ struct hostapd_hw_modes *mode = iface->current_mode; -+ -+ wpa_printf(MSG_DEBUG, -+ "input freq=%d, chan_width=%d, cf1=%d cf2=%d" -+ " chan_bw_interference_bitmap=0x%x", -+ freq, -+ chan_width, -+ cf1, cf2, chan_bw_interference_bitmap); -+ -+ if (iface->conf->discard_6g_awgn_event) { -+ wpa_printf(MSG_DEBUG, "discard_6g_awgn_event set ignoring" -+ "AWGN DETECT event from driver"); -+ return 0; -+ } -+ -+ /* check whether interference has occurred in primary 20Mhz channel */ -+ if (!chan_bw_interference_bitmap || (chan_bw_interference_bitmap & SEG_PRI20)) -+ channel_switch = 1; -+ -+ if (channel_switch) { -+ /* Find a random channel to be switched */ -+ num_available_chandefs = intf_awgn_find_channel(iface, NULL, 0, -+ chan_width); -+ if (num_available_chandefs == 0) { -+ wpa_printf(MSG_ERROR, "AWGN: no available_chandefs"); -+ return 0; -+ } -+ -+ if (os_get_random((u8 *)&_rand, sizeof(_rand)) < 0) { -+ wpa_printf(MSG_ERROR, "AWGN: couldn't get random number"); -+ return 0; -+ } -+ -+ chan_idx = _rand % num_available_chandefs; -+ intf_awgn_find_channel(iface, &chan_data, chan_idx, chan_width); -+ -+ if (!chan_data) { -+ wpa_printf(MSG_ERROR, "AWGN: no random channel found, chan idx : %d", -+ chan_idx); -+ return 0; -+ } -+ -+ if(chan_data->freq == freq) { -+ /* New random channel is same as operating channel -+ * so choose another channel -+ */ -+ chan_data = NULL; -+ chan_idx = (chan_idx + 1) % num_available_chandefs; -+ intf_awgn_find_channel(iface, &chan_data, chan_idx, chan_width); -+ if (!chan_data) { -+ wpa_printf(MSG_ERROR, -+ "AWGN: random channel not found, chan idx : %d", -+ chan_idx); -+ return 0; -+ } -+ } -+ -+ wpa_printf(MSG_DEBUG, "AWGN: got random channel %d (%d)", -+ chan_data->freq, chan_data->chan); -+ new_chan_width = chan_width; -+ } else { -+ /* interference is not present in the primary 20Mhz, so reduce bandwidth*/ -+ for (i = 0; i < mode->num_channels; i++) { -+ chan_temp = &mode->channels[i]; -+ if (chan_temp->freq == freq) -+ chan_data = chan_temp; -+ } -+ if (!chan_data) { -+ wpa_printf(MSG_ERROR, "AWGN : no channel found"); -+ return 0; -+ } -+ -+ if ((chan_width > CHAN_WIDTH_80) && -+ !(chan_bw_interference_bitmap & SEG_SEC40) && -+ !(chan_bw_interference_bitmap & SEG_SEC20)) -+ new_chan_width = CHAN_WIDTH_80; -+ else if (chan_width > CHAN_WIDTH_40 && -+ !(chan_bw_interference_bitmap & SEG_SEC20)) -+ new_chan_width = CHAN_WIDTH_40; -+ else -+ new_chan_width = CHAN_WIDTH_20; -+ } -+ -+ if (new_chan_width > CHAN_WIDTH_20) { -+ ret = get_centre_freq_6g(chan_data->chan, new_chan_width, -+ &new_centre_freq); -+ if (ret) { -+ wpa_printf(MSG_ERROR, -+ "AWGN : couldn't find centre freq for chan : %d" -+ " chan_width : %d", chan_data->chan, new_chan_width); -+ return 0; -+ } -+ } else { -+ new_centre_freq = chan_data->freq; -+ } -+ -+ os_memset(&settings, 0, sizeof(settings)); -+ settings.cs_count = 5; -+ settings.freq_params.freq = chan_data->freq; -+ -+ switch (new_chan_width) { -+ case CHAN_WIDTH_40: -+ settings.freq_params.bandwidth = 40; -+ break; -+ case CHAN_WIDTH_80P80: -+ case CHAN_WIDTH_80: -+ settings.freq_params.bandwidth = 80; -+ break; -+ case CHAN_WIDTH_160: -+ settings.freq_params.bandwidth = 160; -+ break; -+ default: -+ settings.freq_params.bandwidth = 20; -+ break; -+ } -+ -+ settings.freq_params.center_freq1 = new_centre_freq; -+ settings.freq_params.ht_enabled = iface->conf->ieee80211n; -+ settings.freq_params.vht_enabled = iface->conf->ieee80211ac; -+ settings.freq_params.he_enabled = iface->conf->ieee80211ax; -+ -+ for (i = 0; i < iface->num_bss; i++) { -+ /* Save CHAN_SWITCH VHT and HE config */ -+ hostapd_chan_switch_config(iface->bss[i], -+ &settings.freq_params); -+ -+ wpa_printf(MSG_DEBUG, -+ "channel=%u, freq=%d, bw=%d, center_freq1=%d", -+ settings.freq_params.channel, -+ settings.freq_params.freq, -+ settings.freq_params.bandwidth, -+ settings.freq_params.center_freq1); -+ -+ ret = hostapd_switch_channel(iface->bss[i], &settings); -+ if (ret) { -+ /* FIX: What do we do if CSA fails in the middle of -+ * submitting multi-BSS CSA requests? -+ */ -+ return ret; -+ } -+ } -+ -+ return 0; -+} -diff --git a/src/ap/interference.h b/src/ap/interference.h -new file mode 100644 -index 000000000000..047818c0b2f6 ---- /dev/null -+++ b/src/ap/interference.h -@@ -0,0 +1,41 @@ -+/* -+ * INTF - Interference -+ * AWGN - Additive white Gaussian Noise -+ * Copyright (c) 2002-2013, Jouni Malinen -+ * Copyright (c) 2013-2017, Qualcomm Atheros, Inc. -+ * -+ * This software may be distributed under the terms of the BSD license. -+ * See README for more details. -+ */ -+ -+/* -+ * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without modification, -+ * are permitted (subject to the limitations in the disclaimer below) provided that -+ * the following conditions are met: -+ * * Redistributions of source code must retain the above copyright notice, -+ * this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright notice, -+ * this list of conditions and the following disclaimer in the documentation and/or -+ * other materials provided with the distribution. -+ * * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its contributors -+ * may be used to endorse or promote products derived from this software without specific -+ * prior written permission. -+ * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS -+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+int hostapd_intf_awgn_detected(struct hostapd_iface *iface, int freq, -+ int chan_width, -+ int cf1, int cf2, -+ u32 chan_bw_interference_bitmap); -+ -diff --git a/src/drivers/driver.h b/src/drivers/driver.h -index 01f1bc4091ab..57cfac622db5 100644 ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -5214,6 +5214,7 @@ enum wpa_event_type { - * EVENT_CCA_NOTIFY - Notification that CCA has completed - */ - EVENT_CCA_NOTIFY, -+ EVENT_AWGN_DETECTED, - }; - - -@@ -6123,6 +6124,18 @@ union wpa_event_data { - struct bss_color_collision { - u64 bitmap; - } bss_color_collision; -+ -+ /** -+ * Data for EVENT_AWGN -+ */ -+ struct awgn_event { -+ int freq; -+ enum chan_width chan_width; -+ int cf1; -+ int cf2; -+ u32 chan_bw_interference_bitmap; -+ } awgn_event; -+ - }; - - /** -diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c -index b06e7062d25c..198c2713b91e 100644 ---- a/src/drivers/driver_common.c -+++ b/src/drivers/driver_common.c -@@ -95,6 +95,7 @@ const char * event_to_string(enum wpa_event_type event) - E2S(CCA_STARTED_NOTIFY); - E2S(CCA_ABORTED_NOTIFY); - E2S(CCA_NOTIFY); -+ E2S(AWGN_DETECTED); - } - - return "UNKNOWN"; -diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c -index 7a357c07340f..9a32b7a0e0ca 100644 ---- a/src/drivers/driver_nl80211_event.c -+++ b/src/drivers/driver_nl80211_event.c -@@ -179,6 +179,7 @@ static const char * nl80211_command_to_string(enum nl80211_commands cmd) - C2S(NL80211_CMD_COLOR_CHANGE_ANNOUNCEMENT_STARTED) - C2S(NL80211_CMD_COLOR_CHANGE_ANNOUNCEMENT_ABORTED) - C2S(NL80211_CMD_COLOR_CHANGE_ANNOUNCEMENT_COMPLETED) -+ C2S(NL80211_CMD_AWGN_DETECT) - C2S(__NL80211_CMD_AFTER_LAST) - } - #undef C2S -@@ -1856,6 +1857,32 @@ static void nl80211_radar_event(struct wpa_driver_nl80211_data *drv, - } - } - -+static void nl80211_awgn_event(struct wpa_driver_nl80211_data *drv, -+ struct nlattr **tb) -+{ -+ union wpa_event_data data; -+ -+ os_memset(&data, 0, sizeof(data)); -+ -+ if (tb[NL80211_ATTR_WIPHY_FREQ]) -+ data.awgn_event.freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]); -+ -+ if (tb[NL80211_ATTR_CHANNEL_WIDTH]) -+ data.awgn_event.chan_width = -+ convert2width(nla_get_u32(tb[NL80211_ATTR_CHANNEL_WIDTH])); -+ -+ if (tb[NL80211_ATTR_CENTER_FREQ1]) -+ data.awgn_event.cf1 = nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ1]); -+ -+ if (tb[NL80211_ATTR_CENTER_FREQ2]) -+ data.awgn_event.cf2 = nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ2]); -+ -+ if (tb[NL80211_ATTR_AWGN_INTERFERENCE_BITMAP]) -+ data.awgn_event.chan_bw_interference_bitmap = -+ nla_get_u32(tb[NL80211_ATTR_AWGN_INTERFERENCE_BITMAP]); -+ -+ wpa_supplicant_event(drv->ctx, EVENT_AWGN_DETECTED, &data); -+} - - static void nl80211_spurious_frame(struct i802_bss *bss, struct nlattr **tb, - int wds) -@@ -3198,6 +3225,9 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd, - mlme_event_color_change_announcement_completed(drv); - break; - #endif -+ case NL80211_CMD_AWGN_DETECT: -+ nl80211_awgn_event(drv, tb); -+ break; - default: - wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event " - "(cmd=%d)", cmd); -diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h -index 85fe14ba9093..ea5fd565bb43 100644 ---- a/src/drivers/nl80211_copy.h -+++ b/src/drivers/nl80211_copy.h -@@ -1190,6 +1190,10 @@ - * were indicated by driver and now need to be reflected in - * Beacon frame. - * -+ * @NL80211_CMD_AWGN_DETECT: Once AWGN interference is detected on the operating -+ * channel, userspace is notified with the interference bitmap using -+ * %NL80211_ATTR_AWGN_INTERFERENCE_BITMAP -+ * - * @NL80211_CMD_MAX: highest used command number - * @__NL80211_CMD_AFTER_LAST: internal use - */ -@@ -1431,6 +1435,8 @@ enum nl80211_commands { - NL80211_CMD_COLOR_CHANGE_ANNOUNCEMENT_ABORTED, - NL80211_CMD_COLOR_CHANGE_ANNOUNCEMENT_COMPLETED, - -+ NL80211_CMD_AWGN_DETECT, -+ - NL80211_CMD_SET_FILS_AAD, - - /* add new commands above here */ -@@ -2583,6 +2589,9 @@ enum nl80211_commands { - * staggered mode or burst mode in %NL80211_CMD_START_AP from - * user-space. - * -+ * @NL80211_ATTR_AWGN_INTERFERENCE_BITMAP: u32 attribute specifying the -+ * interference bitmap of operating bandwidth for %NL80211_CMD_AWGN_DETECT -+ * - * @NUM_NL80211_ATTR: total number of nl80211_attrs available - * @NL80211_ATTR_MAX: highest attribute number currently defined - * @__NL80211_ATTR_AFTER_LAST: internal use -@@ -2678,7 +2687,6 @@ enum nl80211_attrs { - - NL80211_ATTR_FREQ_FIXED, - -- - NL80211_ATTR_WIPHY_RETRY_SHORT, - NL80211_ATTR_WIPHY_RETRY_LONG, - NL80211_ATTR_WIPHY_FRAG_THRESHOLD, -@@ -3093,6 +3101,12 @@ enum nl80211_attrs { - - NL80211_ATTR_BEACON_TX_MODE, - -+ NL80211_ATTR_WIPHY_ANTENNA_GAIN, -+ -+ NL80211_ATTR_STA_MGMT_RTS_CTS_CONFIG, -+ -+ NL80211_ATTR_AWGN_INTERFERENCE_BITMAP, -+ - /* add attributes here, update the policy in nl80211.c */ - - __NL80211_ATTR_AFTER_LAST, -diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile -index 9ff1e8d51568..4c6592b62f5b 100644 ---- a/wpa_supplicant/Makefile -+++ b/wpa_supplicant/Makefile -@@ -977,6 +977,7 @@ OBJS += ../src/ap/ap_list.o - OBJS += ../src/ap/ieee802_11.o - OBJS += ../src/ap/hw_features.o - OBJS += ../src/ap/dfs.o -+OBJS += ../src/ap/interference.o - CFLAGS += -DNEED_AP_MLME - endif - ifdef CONFIG_WPS --- -2.31.1 - diff --git a/feeds/ipq95xx/hostapd/patches/n00-001-hostapd-add-support-for-6GHz-operation.patch b/feeds/ipq95xx/hostapd/patches/n00-001-hostapd-add-support-for-6GHz-operation.patch deleted file mode 100644 index 82e90e09b..000000000 --- a/feeds/ipq95xx/hostapd/patches/n00-001-hostapd-add-support-for-6GHz-operation.patch +++ /dev/null @@ -1,564 +0,0 @@ -From 404211da041eef5ddfc52515048b04c70ef8579c Mon Sep 17 00:00:00 2001 -From: Aditya Kumar Singh -Date: Thu, 21 Oct 2021 12:51:38 +0530 -Subject: [PATCH] hostapd: add support for 6GHz operation - -6 GHz gives users ability to select the AP mode from LPI, SP and -VLP modes. This mode needs to be passed on to the cfg80211 -for further processing during AP bring up. Also, the regulatory -rules received by hostapd contains psd values for 6G rules. -Hostapd needs to store these values in order to later advertise -it in the tx power element in the beacon. - -This patch adds the support to send the user configured 6g power -type during set_channel command and as well to get and store the -psd values from reg rules which will be later on used in tpe -advertisement during beacon formation. - -Signed-off-by: Aditya Kumar Singh ---- - src/ap/ap_drv_ops.c | 9 ++++++--- - src/ap/beacon.c | 9 +++++++-- - src/ap/dfs.c | 6 ++++-- - src/ap/hostapd.c | 2 +- - src/ap/ieee802_11.c | 13 ++++++++++++- - src/ap/ieee802_11_he.c | 10 ++++++++-- - src/common/hw_features_common.c | 4 +++- - src/common/hw_features_common.h | 2 +- - src/common/ieee802_11_defs.h | 14 ++++++++++++++ - src/drivers/driver.h | 20 +++++++++++++++++++- - src/drivers/driver_hostap.c | 3 ++- - src/drivers/driver_nl80211.c | 15 ++++++++++++++- - src/drivers/driver_nl80211.h | 2 +- - src/drivers/driver_nl80211_capa.c | 28 +++++++++++++++++++++++----- - src/drivers/driver_nl80211_event.c | 2 +- - src/drivers/nl80211_copy.h | 19 +++++++++++++++++++ - wpa_supplicant/driver_i.h | 2 +- - wpa_supplicant/mesh.c | 2 +- - wpa_supplicant/wpa_supplicant.c | 2 +- - 19 files changed, 138 insertions(+), 26 deletions(-) - ---- a/src/ap/ap_drv_ops.c -+++ b/src/ap/ap_drv_ops.c -@@ -563,7 +563,8 @@ int hostapd_set_freq(struct hostapd_data - center_segment0, center_segment1, - cmode ? cmode->vht_capab : 0, - cmode ? -- &cmode->he_capab[IEEE80211_MODE_AP] : NULL)) -+ &cmode->he_capab[IEEE80211_MODE_AP] : NULL, -+ hapd->iconf->he_6ghz_reg_pwr_type)) - return -1; - - if (hapd->driver == NULL) -@@ -636,7 +637,8 @@ hostapd_get_hw_feature_data(struct hosta - hapd->driver->get_hw_feature_data == NULL) - return NULL; - return hapd->driver->get_hw_feature_data(hapd->drv_priv, num_modes, -- flags, dfs_domain); -+ flags, dfs_domain, -+ hapd->iconf->he_6ghz_reg_pwr_type); - } - - -@@ -836,7 +838,8 @@ int hostapd_start_dfs_cac(struct hostapd - oper_chwidth, center_segment0, - center_segment1, - cmode->vht_capab, -- &cmode->he_capab[IEEE80211_MODE_AP])) { -+ &cmode->he_capab[IEEE80211_MODE_AP], -+ hapd->iconf->he_6ghz_reg_pwr_type)) { - wpa_printf(MSG_ERROR, "Can't set freq params"); - return -1; - } ---- a/src/ap/beacon.c -+++ b/src/ap/beacon.c -@@ -1563,7 +1563,11 @@ int ieee802_11_build_ap_params(struct ho - if (is_6ghz_op_class(hapd->iconf->op_class)) { - tail_len += sizeof(struct ieee80211_he_6ghz_oper_info) + - 3 + sizeof(struct ieee80211_he_6ghz_band_cap); -- /* Additional TX Power envelope for subordinate client */ -+ /* Additional TX Power envelope for subordinate client -+ * Currently as per the spec, only AP LP mode should send -+ * the tpe for subordinate client. SP mode should not and -+ * no standard set yet for VLP mode. -+ */ - if (hostapd_get_he_6ghz_reg_pwr_type(hapd->iconf) == - AP_TYPE_6GHZ_INDOOR_AP) - tail_len += 4; -@@ -1988,7 +1992,8 @@ static int __ieee802_11_set_beacon(struc - hostapd_get_oper_centr_freq_seg0_idx(iconf), - hostapd_get_oper_centr_freq_seg1_idx(iconf), - cmode->vht_capab, -- &cmode->he_capab[IEEE80211_MODE_AP]) == 0) -+ &cmode->he_capab[IEEE80211_MODE_AP], -+ iconf->he_6ghz_reg_pwr_type) == 0) - params.freq = &freq; - - res = hostapd_drv_set_ap(hapd, ¶ms); ---- a/src/ap/dfs.c -+++ b/src/ap/dfs.c -@@ -1089,7 +1089,8 @@ static int hostapd_dfs_testmode_set_beac - vht_oper_centr_freq_seg0_idx, - vht_oper_centr_freq_seg1_idx, - iface->current_mode->vht_capab, -- &iface->current_mode->he_capab[IEEE80211_MODE_AP]); -+ &iface->current_mode->he_capab[IEEE80211_MODE_AP], -+ hapd->iconf->he_6ghz_reg_pwr_type); - - if (err) { - wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params"); -@@ -1230,7 +1231,8 @@ static int hostapd_dfs_start_channel_swi - oper_centr_freq_seg0_idx, - oper_centr_freq_seg1_idx, - cmode->vht_capab, -- &cmode->he_capab[ieee80211_mode]); -+ &cmode->he_capab[ieee80211_mode], -+ iface->conf->he_6ghz_reg_pwr_type); - - if (err) { - wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params"); ---- a/src/ap/hostapd.c -+++ b/src/ap/hostapd.c -@@ -3534,7 +3534,7 @@ static int hostapd_change_config_freq(st - hostapd_get_oper_centr_freq_seg1_idx(conf), - conf->vht_capab, - mode ? &mode->he_capab[IEEE80211_MODE_AP] : -- NULL)) -+ NULL, hapd->iconf->he_6ghz_reg_pwr_type)) - return -1; - - switch (params->bandwidth) { ---- a/src/ap/ieee802_11.c -+++ b/src/ap/ieee802_11.c -@@ -7017,6 +7017,8 @@ u8 * hostapd_eid_txpower_envelope(struct - int dfs, i; - u8 channel, tx_pwr_count, local_pwr_constraint; - u8 tx_pwr, tx_pwr_intrpn, tx_pwr_cat, ap_type; -+ s8 psd; -+ - int max_tx_power; - - if (!mode) -@@ -7053,15 +7055,24 @@ u8 * hostapd_eid_txpower_envelope(struct - */ - if (ap_type == AP_TYPE_6GHZ_INDOOR_AP) { - tx_pwr_cat = REG_SUBORDINATE_CLIENT; -- /* TODO: extract psd limits from channel data */ -+ psd = mode->psd_values[NL80211_REG_SUBORDINATE_CLIENT_LPI + ap_type]; -+#ifdef REG_DOM_SUPPORT_TX_POWER -+ tx_pwr = psd * 2; -+#else - tx_pwr = (hostapd_get_6g_tx_power(hapd, ap_type, tx_pwr_cat) * 2); -+#endif /* REG_DOM_SUPPORT_TX_POWER */ - eid = hostapd_add_tpe_info(eid, tx_pwr_count, tx_pwr_intrpn, - tx_pwr_cat, tx_pwr); - } - - /* Default Tx Power envelope for Global Operating class */ - tx_pwr_cat = REG_DEFAULT_CLIENT; -+ psd = mode->psd_values[NL80211_REG_REGULAR_CLIENT_LPI + ap_type]; -+#ifdef REG_DOM_SUPPORT_TX_POWER -+ tx_pwr = psd * 2; -+#else - tx_pwr = (hostapd_get_6g_tx_power(hapd, ap_type, tx_pwr_cat) * 2); -+#endif /* REG_DOM_SUPPORT_TX_POWER */ - eid = hostapd_add_tpe_info(eid, tx_pwr_count, tx_pwr_intrpn, tx_pwr_cat, tx_pwr); - - return eid; ---- a/src/ap/ieee802_11_he.c -+++ b/src/ap/ieee802_11_he.c -@@ -241,10 +241,16 @@ u8 * hostapd_eid_he_operation(struct hos - * - 1 (Standard Power Access Point) - * - Reserved in 5GHz and 2Ghz bands - */ -+ -+ u8 ap_type = hostapd_get_he_6ghz_reg_pwr_type(hapd->iconf); -+ - if (seg1) -- *pos++ = 3; -+ *pos++ = 3 | (IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO & -+ (ap_type << IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO_LSB)); - else -- *pos++ = center_idx_to_bw_6ghz(seg0); -+ *pos++ = center_idx_to_bw_6ghz(seg0) | -+ (IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO & -+ (ap_type << IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO_LSB)); - - /* Channel Center Freq Seg0/Seg1 */ - if (hapd->iconf->he_oper_chwidth == 2) { ---- a/src/common/hw_features_common.c -+++ b/src/common/hw_features_common.c -@@ -386,7 +386,7 @@ int hostapd_set_freq_params(struct hosta - int sec_channel_offset, - int oper_chwidth, int center_segment0, - int center_segment1, u32 vht_caps, -- struct he_capabilities *he_cap) -+ struct he_capabilities *he_cap, u8 reg_6g_pwr_mode) - { - if (!he_cap || !he_cap->he_supported) - he_enabled = 0; -@@ -477,6 +477,8 @@ int hostapd_set_freq_params(struct hosta - data->ht_enabled = 0; - data->vht_enabled = 0; - -+ /* Append 6G reg power info */ -+ data->he_6ghz_reg_pwr_type = reg_6g_pwr_mode; - return 0; - } - ---- a/src/common/hw_features_common.h -+++ b/src/common/hw_features_common.h -@@ -43,7 +43,7 @@ int hostapd_set_freq_params(struct hosta - int sec_channel_offset, - int oper_chwidth, int center_segment0, - int center_segment1, u32 vht_caps, -- struct he_capabilities *he_caps); -+ struct he_capabilities *he_caps, u8 reg_6g_pwr_mode); - void set_disable_ht40(struct ieee80211_ht_capabilities *htcaps, - int disabled); - int ieee80211ac_cap_check(u32 hw, u32 conf); ---- a/src/common/ieee802_11_defs.h -+++ b/src/common/ieee802_11_defs.h -@@ -1986,6 +1986,17 @@ enum reg_6g_client_type { - - /* same Max Tx Pwr for all 20MHz bands */ - #define DEFAULT_MAX_TX_POWER_COUNT_6G 0 -+ -+/* -+ * REG_DOM_SUPPORT_TX_POWER - regulatory domain -+ * supports tx power values or not. -+ * -+ * If this macro is undefined, tx-power macros will be used to -+ * get the tx-power, otherwise psd values from regulatory domain -+ * will be taken -+ */ -+#define REG_DOM_SUPPORT_TX_POWER 1 -+ - /* - * These tx-power macros are present till the 6G regdomains are defined to - * support tx-power values for various client types. -@@ -2372,6 +2383,9 @@ struct ieee80211_spatial_reuse { - #define HE_OPERATION_BSS_COLOR_OFFSET 24 - #define HE_OPERATION_BSS_COLOR_MAX 64 - -+#define IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO 0x38 -+#define IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO_LSB 3 -+ - /* Spatial Reuse defines */ - #define SPATIAL_REUSE_SRP_DISALLOWED BIT(0) - #define SPATIAL_REUSE_NON_SRG_OBSS_PD_SR_DISALLOWED BIT(1) ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -299,6 +299,12 @@ struct hostapd_hw_modes { - * for IEEE 802.11ay EDMG configuration. - */ - struct ieee80211_edmg_config edmg; -+ -+ /** -+ * This array is used to store the psd value of each power mode -+ * supported in 6G band. -+ */ -+ s8 psd_values[NL80211_REG_NUM_POWER_MODES]; - }; - - -@@ -783,6 +789,17 @@ struct hostapd_freq_params { - * for IEEE 802.11ay EDMG configuration. - */ - struct ieee80211_edmg_config edmg; -+ -+ /** -+ * he_6ghz_reg_pwr_type - 6G regulatory power mode -+ * Since many operation related to channel for 6G depends on the -+ * power mode, this parameter is added here. -+ * -+ * 0 - LPI_AP -+ * 1 - SP_AP -+ * 2 - VLP_AP -+ */ -+ u8 he_6ghz_reg_pwr_type; - }; - - /** -@@ -2926,12 +2943,13 @@ struct wpa_driver_ops { - * @num_modes: Variable for returning the number of returned modes - * flags: Variable for returning hardware feature flags - * @dfs: Variable for returning DFS region (HOSTAPD_DFS_REGION_*) -+ * @pwr_mode: Variable required for processing the support data for 6G - * Returns: Pointer to allocated hardware data on success or %NULL on - * failure. Caller is responsible for freeing this. - */ - struct hostapd_hw_modes * (*get_hw_feature_data)(void *priv, - u16 *num_modes, -- u16 *flags, u8 *dfs); -+ u16 *flags, u8 *dfs, u8 pwr_mode); - - /** - * send_mlme - Send management frame from MLME ---- a/src/drivers/driver_hostap.c -+++ b/src/drivers/driver_hostap.c -@@ -1099,7 +1099,8 @@ static int hostap_sta_disassoc(void *pri - - static struct hostapd_hw_modes * hostap_get_hw_feature_data(void *priv, - u16 *num_modes, -- u16 *flags, u8 *dfs) -+ u16 *flags, u8 *dfs, -+ u8 pwr_mode) - { - struct hostapd_hw_modes *mode; - int i, clen, rlen; ---- a/src/drivers/driver_nl80211.c -+++ b/src/drivers/driver_nl80211.c -@@ -5074,6 +5074,19 @@ static int nl80211_set_channel(struct i8 - return -1; - } - -+#ifdef CONFIG_IEEE80211AX -+ if (freq->freq && is_6ghz_freq(freq->freq)) { -+ wpa_printf(MSG_DEBUG, "%s: 6g_reg_pwr_mode=%d", -+ __func__, freq->he_6ghz_reg_pwr_type); -+ if (nla_put_u8(msg, NL80211_ATTR_6G_REG_POWER_MODE, -+ freq->he_6ghz_reg_pwr_type)) { -+ wpa_printf(MSG_ERROR, -+ "%s: Failed to put 6g_reg_pwr_mode", __func__); -+ nlmsg_free(msg); -+ return -1; -+ } -+ } -+#endif /* CONFIG_IEEE80211AX */ - ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); - if (ret == 0) { - bss->freq = freq->freq; -@@ -8353,7 +8366,7 @@ static int wpa_driver_nl80211_send_actio - int i; - - modes = nl80211_get_hw_feature_data(bss, &num_modes, -- &flags, &dfs_domain); -+ &flags, &dfs_domain, 0); - if (dfs_domain != HOSTAPD_DFS_REGION_ETSI && - ieee80211_is_dfs(bss->freq, modes, num_modes)) - offchanok = 0; ---- a/src/drivers/driver_nl80211.h -+++ b/src/drivers/driver_nl80211.h -@@ -288,7 +288,7 @@ int nl80211_send_monitor(struct wpa_driv - int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv); - struct hostapd_hw_modes * - nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags, -- u8 *dfs_domain); -+ u8 *dfs_domain, u8 pwr_mode); - - int process_global_event(struct nl_msg *msg, void *arg); - int process_bss_event(struct nl_msg *msg, void *arg); ---- a/src/drivers/driver_nl80211_capa.c -+++ b/src/drivers/driver_nl80211_capa.c -@@ -1468,6 +1468,7 @@ struct phy_info_arg { - int last_mode, last_chan_idx; - int failed; - u8 dfs_domain; -+ u8 pwr_mode; - }; - - static void phy_info_ht_capa(struct hostapd_hw_modes *mode, struct nlattr *capa, -@@ -2116,7 +2117,9 @@ static void nl80211_set_ht40_mode_sec(st - - - static void nl80211_reg_rule_max_eirp(u32 start, u32 end, u32 max_eirp, -- struct phy_info_arg *results) -+ struct phy_info_arg *results, -+ u8 config_pwr_mode, u8 pwr_mode, -+ s8 psd) - { - u16 m; - -@@ -2126,10 +2129,16 @@ static void nl80211_reg_rule_max_eirp(u3 - - for (c = 0; c < mode->num_channels; c++) { - struct hostapd_channel_data *chan = &mode->channels[c]; -+ -+ if (is_6ghz_freq(chan->freq) && config_pwr_mode != pwr_mode) -+ continue; -+ - if ((u32) chan->freq - 10 >= start && - (u32) chan->freq + 10 <= end) - chan->max_tx_power = max_eirp; - } -+ /* Update the psd rules */ -+ mode->psd_values[pwr_mode] = psd; - } - } - -@@ -2302,6 +2311,7 @@ static int nl80211_get_reg(struct nl_msg - [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 }, - }; - -+ u8 config_pwr_mode = results->pwr_mode; - nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); - if (!tb_msg[NL80211_ATTR_REG_ALPHA2] || -@@ -2326,6 +2336,8 @@ static int nl80211_get_reg(struct nl_msg - nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule) - { - u32 start, end, max_eirp = 0, max_bw = 0, flags = 0; -+ u8 pwr_mode = 0; -+ s8 psd = 0; - nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX, - nla_data(nl_rule), nla_len(nl_rule), reg_policy); - if (tb_rule[NL80211_ATTR_FREQ_RANGE_START] == NULL || -@@ -2339,9 +2351,13 @@ static int nl80211_get_reg(struct nl_msg - max_bw = nla_get_u32(tb_rule[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000; - if (tb_rule[NL80211_ATTR_REG_RULE_FLAGS]) - flags = nla_get_u32(tb_rule[NL80211_ATTR_REG_RULE_FLAGS]); -+ if (tb_rule[NL80211_ATTR_REG_POWER_MODE]) -+ pwr_mode = nla_get_u8(tb_rule[NL80211_ATTR_REG_POWER_MODE]); -+ if (tb_rule[NL80211_ATTR_POWER_RULE_PSD]) -+ psd = (s8) nla_get_u8(tb_rule[NL80211_ATTR_POWER_RULE_PSD]); - -- wpa_printf(MSG_DEBUG, "nl80211: %u-%u @ %u MHz %u mBm%s%s%s%s%s%s%s%s", -- start, end, max_bw, max_eirp, -+ wpa_printf(MSG_DEBUG, "nl80211: %u-%u @ %u MHz %u mBm pwr_mode: %u psd: %d%s%s%s%s%s%s%s%s", -+ start, end, max_bw, max_eirp, pwr_mode, psd, - flags & NL80211_RRF_NO_OFDM ? " (no OFDM)" : "", - flags & NL80211_RRF_NO_CCK ? " (no CCK)" : "", - flags & NL80211_RRF_NO_INDOOR ? " (no indoor)" : "", -@@ -2355,7 +2371,8 @@ static int nl80211_get_reg(struct nl_msg - nl80211_reg_rule_ht40(start, end, results); - if (tb_rule[NL80211_ATTR_POWER_RULE_MAX_EIRP]) - nl80211_reg_rule_max_eirp(start, end, max_eirp, -- results); -+ results, config_pwr_mode, -+ pwr_mode, psd); - } - - nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule) -@@ -2455,7 +2472,7 @@ static void nl80211_dump_chan_list(struc - - struct hostapd_hw_modes * - nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags, -- u8 *dfs_domain) -+ u8 *dfs_domain, u8 pwr_mode) - { - u32 feat; - struct i802_bss *bss = priv; -@@ -2468,6 +2485,7 @@ nl80211_get_hw_feature_data(void *priv, - .last_mode = -1, - .failed = 0, - .dfs_domain = 0, -+ .pwr_mode = pwr_mode - }; - - *num_modes = 0; ---- a/src/drivers/driver_nl80211_event.c -+++ b/src/drivers/driver_nl80211_event.c -@@ -1982,7 +1982,7 @@ static unsigned int chan_to_freq(struct - int i; - - modes = nl80211_get_hw_feature_data(drv->first_bss, &num_modes, -- &flags, &dfs_domain); -+ &flags, &dfs_domain, 0); - if (!modes) { - wpa_printf(MSG_DEBUG, - "nl80211: Fetching hardware mode failed"); ---- a/src/drivers/nl80211_copy.h -+++ b/src/drivers/nl80211_copy.h -@@ -3135,6 +3136,8 @@ enum nl80211_attrs { - - NL80211_ATTR_AWGN_INTERFERENCE_BITMAP, - -+ NL80211_ATTR_6G_REG_POWER_MODE, -+ - /* add attributes here, update the policy in nl80211.c */ - - __NL80211_ATTR_AFTER_LAST, -@@ -3799,6 +3802,20 @@ enum nl80211_band_attr { - - #define NL80211_BAND_ATTR_HT_CAPA NL80211_BAND_ATTR_HT_CAPA - -+enum nl80211_regulatory_power_modes { -+ NL80211_REG_AP_LPI, -+ NL80211_REG_AP_SP, -+ NL80211_REG_AP_VLP, -+ NL80211_REG_REGULAR_CLIENT_LPI, -+ NL80211_REG_REGULAR_CLIENT_SP, -+ NL80211_REG_REGULAR_CLIENT_VLP, -+ NL80211_REG_SUBORDINATE_CLIENT_LPI, -+ NL80211_REG_SUBORDINATE_CLIENT_SP, -+ NL80211_REG_SUBORDINATE_CLIENT_VLP, -+ -+ NL80211_REG_NUM_POWER_MODES, -+}; -+ - /** - * enum nl80211_wmm_rule - regulatory wmm rule - * -@@ -4023,6 +4040,9 @@ enum nl80211_reg_type { - * a given frequency range. The value is in mBm (100 * dBm). - * @NL80211_ATTR_DFS_CAC_TIME: DFS CAC time in milliseconds. - * If not present or 0 default CAC time will be used. -+ * @NL80211_ATTR_POWER_RULE_PSD: power spectral density (in dBm). -+ * This could be negative. -+ * @NL80211_ATTR_REG_POWER_MODE: the regulatory power mode for 6G rules - * @NL80211_REG_RULE_ATTR_MAX: highest regulatory rule attribute number - * currently defined - * @__NL80211_REG_RULE_ATTR_AFTER_LAST: internal use -@@ -4040,6 +4060,10 @@ enum nl80211_reg_rule_attr { - - NL80211_ATTR_DFS_CAC_TIME, - -+ NL80211_ATTR_POWER_RULE_PSD, -+ -+ NL80211_ATTR_REG_POWER_MODE, -+ - /* keep last */ - __NL80211_REG_RULE_ATTR_AFTER_LAST, - NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1 ---- a/wpa_supplicant/driver_i.h -+++ b/wpa_supplicant/driver_i.h -@@ -305,7 +305,7 @@ wpa_drv_get_hw_feature_data(struct wpa_s - if (wpa_s->driver->get_hw_feature_data) - return wpa_s->driver->get_hw_feature_data(wpa_s->drv_priv, - num_modes, flags, -- dfs_domain); -+ dfs_domain, 0); - return NULL; - } - ---- a/wpa_supplicant/mesh.c -+++ b/wpa_supplicant/mesh.c -@@ -232,7 +232,7 @@ static int wpas_mesh_update_freq_params( - hostapd_get_oper_centr_freq_seg0_idx(ifmsh->conf), - hostapd_get_oper_centr_freq_seg1_idx(ifmsh->conf), - ifmsh->conf->vht_capab, -- he_capab)) { -+ he_capab, ifmsh->conf->he_6ghz_reg_pwr_type)) { - wpa_printf(MSG_ERROR, "Error updating mesh frequency params"); - wpa_supplicant_mesh_deinit(wpa_s, true); - return -1; ---- a/wpa_supplicant/wpa_supplicant.c -+++ b/wpa_supplicant/wpa_supplicant.c -@@ -2824,7 +2824,7 @@ skip_to_6ghz: - vht_freq.vht_enabled, vht_freq.he_enabled, - freq->sec_channel_offset, - chwidth, seg0, seg1, vht_caps, -- &mode->he_capab[ieee80211_mode]) != 0) -+ &mode->he_capab[ieee80211_mode], 0) != 0) - return; - - *freq = vht_freq; ---- a/hostapd/config_file.c -+++ b/hostapd/config_file.c -@@ -3542,6 +3542,15 @@ static int hostapd_config_fill(struct ho - } - } else if (os_strcmp(buf, "he_6ghz_reg_pwr_type") == 0) { - conf->he_6ghz_reg_pwr_type = atoi(pos); -+ if (conf->he_6ghz_reg_pwr_type > AP_TYPE_6GHZ_VERY_LOW_POWER_AP || -+ conf->he_6ghz_reg_pwr_type < AP_TYPE_6GHZ_INDOOR_AP) { -+ wpa_printf(MSG_ERROR, -+ "Line %d: Invalid 6ghz regulatory power type('%s') " -+ "[min: %d and max: %d]", -+ line, pos, AP_TYPE_6GHZ_INDOOR_AP, -+ AP_TYPE_6GHZ_VERY_LOW_POWER_AP); -+ return 1; -+ } - } else if (os_strcmp(buf, "he_oper_chwidth") == 0) { - conf->he_oper_chwidth = atoi(pos); - } else if (os_strcmp(buf, "he_oper_centr_freq_seg0_idx") == 0) { diff --git a/feeds/ipq95xx/hostapd/patches/n00-002-hostapd-add-support-for-6g-client-type.patch b/feeds/ipq95xx/hostapd/patches/n00-002-hostapd-add-support-for-6g-client-type.patch deleted file mode 100644 index b48c74bfc..000000000 --- a/feeds/ipq95xx/hostapd/patches/n00-002-hostapd-add-support-for-6g-client-type.patch +++ /dev/null @@ -1,171 +0,0 @@ -From 2a556ebff47bebcda6a1c7c8cd760bd38de54ff4 Mon Sep 17 00:00:00 2001 -From: Aditya Kumar Singh -Date: Fri, 22 Oct 2021 22:50:37 +0530 -Subject: [PATCH] hostapd: add support for 6g client type - -IEEE Std 802.11ax™‐2021 introduces two types of client -namely DEFAULT and SUBORDINATE client for 6GHz device. - -This patch - - * add u8 he_6ghz_reg_client_type member in struct wpa_config - to store the 6g configured mode. - * add new nl80211 ops - set_6gclient_type, which will be used - to send the 6G client type via existing NL80211_CMD_SET_INTERFACE - command. - -Signed-off-by: Aditya Kumar Singh ---- - src/drivers/driver.h | 8 ++++++++ - src/drivers/driver_nl80211.c | 26 ++++++++++++++++++++++++++ - wpa_supplicant/config.c | 2 ++ - wpa_supplicant/config.h | 11 +++++++++++ - wpa_supplicant/driver_i.h | 8 ++++++++ - wpa_supplicant/wpa_supplicant.c | 9 +++++++++ - 6 files changed, 64 insertions(+) - ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -4694,6 +4694,14 @@ struct wpa_driver_ops { - * explicitly allow reception of broadcast Public Action frames. - */ - int (*dpp_listen)(void *priv, bool enable); -+ -+ /** -+ * set_6gclient_type - Set the client type for 6G interface -+ * @priv: Private driver interface data -+ * @client_type_6g: 0 - Default Client, 1 - Subordinate Client -+ * Returns: 0 on success, < 0 on failure -+ */ -+ int (*set_6gclient_type)(void *priv, u8 client_type_6g); - - #ifdef CONFIG_TESTING_OPTIONS - int (*register_frame)(void *priv, u16 type, ---- a/src/drivers/driver_nl80211.c -+++ b/src/drivers/driver_nl80211.c -@@ -12173,6 +12173,31 @@ static int nl80211_dpp_listen(void *priv - } - #endif /* CONFIG_DPP */ - -+static int nl80211_set_6gclient_type(void *priv, u8 client_type_6g) -+{ -+ struct i802_bss *bss = priv; -+ struct wpa_driver_nl80211_data *drv = bss->drv; -+ struct nl_msg *msg; -+ int ret = -ENOBUFS; -+ -+ wpa_printf(MSG_DEBUG, "nl80211: 6g client type: %d", -+ client_type_6g); -+ -+ msg = nl80211_cmd_msg(drv->first_bss, 0, NL80211_CMD_SET_INTERFACE); -+ if (!msg || nla_put_u8(msg, NL80211_ATTR_6G_REG_POWER_MODE, -+ client_type_6g)) -+ goto fail; -+ -+ ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); -+ -+ if(ret) -+ wpa_printf(MSG_DEBUG, "nl80211: 6g client type could not be set (%d)", -+ ret); -+ return ret; -+fail: -+ nlmsg_free(msg); -+ return ret; -+} - - const struct wpa_driver_ops wpa_driver_nl80211_ops = { - .name = "nl80211", -@@ -12315,4 +12340,5 @@ const struct wpa_driver_ops wpa_driver_n - #ifdef CONFIG_TESTING_OPTIONS - .register_frame = testing_nl80211_register_frame, - #endif /* CONFIG_TESTING_OPTIONS */ -+ .set_6gclient_type = nl80211_set_6gclient_type, - }; ---- a/wpa_supplicant/config.c -+++ b/wpa_supplicant/config.c -@@ -5394,6 +5394,8 @@ static const struct global_parse_data gl - { INT_RANGE(force_kdk_derivation, 0, 1), 0 }, - #endif /* CONFIG_TESTING_OPTIONS */ - #endif /* CONFIG_PASN */ -+ { INT_RANGE(he_6ghz_reg_client_type, 1, 2), -+ CFG_CHANGED_HE_6GHZ_CLIENT_TYPE}, - }; - - #undef FUNC ---- a/wpa_supplicant/config.h -+++ b/wpa_supplicant/config.h -@@ -378,6 +378,7 @@ struct wpa_cred { - #define CFG_CHANGED_WOWLAN_TRIGGERS BIT(18) - #define CFG_CHANGED_DISABLE_BTM BIT(19) - #define CFG_CHANGED_BGSCAN BIT(20) -+#define CFG_CHANGED_HE_6GHZ_CLIENT_TYPE BIT(21) - - /** - * struct wpa_config - wpa_supplicant configuration data -@@ -1650,6 +1651,16 @@ struct wpa_config { - int force_kdk_derivation; - #endif /* CONFIG_TESTING_OPTIONS */ - #endif /* CONFIG_PASN*/ -+ -+ /** -+ * he_6ghz_reg_client_type - Type of client in 6GHz band -+ * -+ * IEEE Std 802.11ax™‐2021 allows two kinds of client -+ * -+ * 1 = DEFAULT or REGULAR CLIENT -+ * 2 = SUBORDINATE CLIENT -+ */ -+ u8 he_6ghz_reg_client_type; - }; - - ---- a/wpa_supplicant/driver_i.h -+++ b/wpa_supplicant/driver_i.h -@@ -1117,4 +1117,12 @@ static inline int wpa_drv_dpp_listen(str - return wpa_s->driver->dpp_listen(wpa_s->drv_priv, enable); - } - -+static inline int wpa_drv_set_6gclient_type(struct wpa_supplicant *wpa_s, -+ u8 he_6ghz_reg_client_type) -+{ -+ if (!wpa_s->driver->set_6gclient_type) -+ return -1; -+ return wpa_s->driver->set_6gclient_type(wpa_s->drv_priv, -+ he_6ghz_reg_client_type); -+} - #endif /* DRIVER_I_H */ ---- a/wpa_supplicant/wpa_supplicant.c -+++ b/wpa_supplicant/wpa_supplicant.c -@@ -5212,6 +5212,15 @@ int wpa_supplicant_driver_init(struct wp - wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver"); - wpa_drv_flush_pmkid(wpa_s); - -+ /* Before starting scan, for 6g interface, set the client type */ -+ if (wpa_s->conf->changed_parameters & CFG_CHANGED_HE_6GHZ_CLIENT_TYPE) { -+ u8 he_6ghz_reg_client_type = wpa_s->conf->he_6ghz_reg_client_type; -+ /** -+ * Subtract 1 to map the client type with 0 indexing -+ */ -+ wpa_drv_set_6gclient_type(wpa_s, he_6ghz_reg_client_type - 1); -+ } -+ - wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN; - wpa_s->prev_scan_wildcard = 0; - ---- a/wpa_supplicant/wpa_supplicant.conf -+++ b/wpa_supplicant/wpa_supplicant.conf -@@ -589,6 +589,15 @@ fast_reauth=1 - # 1 = Publish - #ftm_initiator=0 - -+# 6GHz regulatory client type -+# This sets the 6GHz client type. Possible options are -+# 1 = Default Client -+# 2 = Subordinate Client -+# Note that value 0 is reserved and can not be used. For 6GHz operation -+# user has to choose from either 1 or 2. If not mentioned, no type will -+# be set from user side. Wireless stack will handle its own default case. -+#he_6ghz_reg_client_type=1 -+ - # credential block - # - # Each credential used for automatic network selection is configured as a set diff --git a/feeds/ipq95xx/hostapd/patches/o00-001-hostapd-fix-6GHz-chan-switch-issue.patch b/feeds/ipq95xx/hostapd/patches/o00-001-hostapd-fix-6GHz-chan-switch-issue.patch deleted file mode 100644 index 87c73a220..000000000 --- a/feeds/ipq95xx/hostapd/patches/o00-001-hostapd-fix-6GHz-chan-switch-issue.patch +++ /dev/null @@ -1,53 +0,0 @@ -From bd267ee2e6c1ce5165bf8be9411b398709f83a8f Mon Sep 17 00:00:00 2001 -From: Aditya Kumar Singh -Date: Fri, 19 Nov 2021 19:51:04 +0530 -Subject: [PATCH] hostapd: fix 6GHz chan switch issue - -If user doesnt provide HE parameter in the hostapd_cli chan_switch -command, by default HE should be enabled for 6 GHz frequency range. -This is because, 6 GHz does not support legacy mode. Similarly, if -bandwidth isnt provided, 20 MHz should be taken as default bandwidth. - -Signed-off-by: Aditya Kumar Singh ---- - hostapd/ctrl_iface.c | 24 ++++++++++++++++++------ - 1 file changed, 18 insertions(+), 6 deletions(-) - -diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c -index 664711d..3c2d51c 100644 ---- a/hostapd/ctrl_iface.c -+++ b/hostapd/ctrl_iface.c -@@ -2530,12 +2530,24 @@ static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params) - { - int idx, bw, bw_idx[] = { 20, 40, 80, 160 }; - -- if (is_6ghz_freq(params->freq) && params->center_freq1) { -- idx = (params->center_freq1 - 5950) / 5; -- bw = center_idx_to_bw_6ghz(idx); -- -- if (bw < 0 || (bw_idx[bw] != params->bandwidth)) -- return -1; -+ if (is_6ghz_freq(params->freq)) { -+ /* Verify if HE was enabled by user or not. 6 GHz does not -+ * support legacy mode. Hence, enable HE if not given */ -+ if (!params->he_enabled) -+ params->he_enabled = 1; -+ -+ /* By default in 6 GHz, HE 20 mode should be selected */ -+ if (!params->center_freq1 && params->bandwidth == 0) { -+ params->center_freq1 = params->freq; -+ /* If bw is not given by user, by default assuming 20 */ -+ params->bandwidth = 20; -+ } else { -+ idx = (params->center_freq1 - 5950) / 5; -+ bw = center_idx_to_bw_6ghz(idx); -+ -+ if (bw < 0 || (bw_idx[bw] != params->bandwidth)) -+ return -1; -+ } - } - - switch (params->bandwidth) { --- -2.7.4 - diff --git a/feeds/ipq95xx/hostapd/patches/p00-001-wpa-supplicant-support-5dot9-channels-in-mesh-160mhz.patch b/feeds/ipq95xx/hostapd/patches/p00-001-wpa-supplicant-support-5dot9-channels-in-mesh-160mhz.patch deleted file mode 100644 index 80620f883..000000000 --- a/feeds/ipq95xx/hostapd/patches/p00-001-wpa-supplicant-support-5dot9-channels-in-mesh-160mhz.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 473175ab3030092aa75c9e4e3daf81eb50da0278 Mon Sep 17 00:00:00 2001 -From: Thiraviyam Mariyappan -Date: Tue, 4 Jan 2022 13:22:18 +0530 -Subject: [PATCH] wpa_supplicant: support 5.9 channels in mesh 160mhz - -currently, mesh supported 5.9 channels on 80Mhz. This patch supports -5.9 channels to bring up at 160mhz based on channel availability. - -Signed-off-by: Thiraviyam Mariyappan ---- - wpa_supplicant/wpa_supplicant.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/wpa_supplicant.c -+++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant.c -@@ -2544,7 +2544,7 @@ void ibss_mesh_setup_freq(struct wpa_sup - int bw80[] = { 5180, 5260, 5500, 5580, 5660, 5745, 5825, 5955, - 6035, 6115, 6195, 6275, 6355, 6435, 6515, - 6595, 6675, 6755, 6835, 6915, 6995 }; -- int bw160[] = { 5955, 6115, 6275, 6435, 6595, 6755, 6915 }; -+ int bw160[] = { 5745, 5955, 6115, 6275, 6435, 6595, 6755, 6915 }; - struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL; - u8 channel; - int i, chan_idx, ht40 = -1, res, obss_scan = !(ssid->noscan); -@@ -2797,13 +2797,13 @@ skip_to_6ghz: - - if ((mode->he_capab[ieee80211_mode].phy_cap[ - HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] & -- HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G) && is_6ghz) { -+ HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G)) { - /* In 160 MHz, the initial four 20 MHz channels were validated - * above; check the remaining four 20 MHz channels for the total - * of 160 MHz bandwidth. - */ - if (!ibss_mesh_is_80mhz_avail(channel + 16, mode)) -- return; -+ break; - - for (j = 0; j < ARRAY_SIZE(bw160); j++) { - if (freq->freq == bw160[j]) { diff --git a/feeds/ipq95xx/hostapd/patches/p00-002-mesh-enable-more-160MHz-channels-in-6GHz.patch b/feeds/ipq95xx/hostapd/patches/p00-002-mesh-enable-more-160MHz-channels-in-6GHz.patch deleted file mode 100644 index f1599ded1..000000000 --- a/feeds/ipq95xx/hostapd/patches/p00-002-mesh-enable-more-160MHz-channels-in-6GHz.patch +++ /dev/null @@ -1,263 +0,0 @@ -From d6e52c4ef2bb8e915cae088564c412583f1794c9 Mon Sep 17 00:00:00 2001 -From: P Praneesh -Date: Fri, 21 Jan 2022 09:44:15 +0530 -Subject: [PATCH] mesh: enable more 160MHz channels in 6GHz - -Current 160MHz implementation supports mesh bringup in limited channels. -Allow all the 6GHz 80MHz channels to support 160MHz if the secondary 80MHz -is available. - -Ex: User can bringup 160MHz in 49th channel (primary 80MHz) based on 33rd -channel(secondary 80MHz) availablity. - -Signed-off-by: P Praneesh ---- - wpa_supplicant/wpa_supplicant.c | 21 ++++++++++++++++++--- - 1 file changed, 18 insertions(+), 3 deletions(-) - -Index: hostapd-2021-12-13-b26f5c0f/hostapd/config_file.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/hostapd/config_file.c -+++ hostapd-2021-12-13-b26f5c0f/hostapd/config_file.c -@@ -4280,6 +4280,8 @@ static int hostapd_config_fill(struct ho - } else if (os_strcmp(buf, "wowlan_triggers") == 0) { - os_free(bss->wowlan_triggers); - bss->wowlan_triggers = os_strdup(pos); -+ } else if (os_strcmp(buf, "enable_160mhz_bw") == 0) { -+ conf->enable_160mhz_bw = atoi(pos); - } else if (os_strcmp(buf, "disable_40mhz_scan") == 0) { - conf->disable_40mhz_scan = atoi(pos); - #ifdef CONFIG_FST -Index: hostapd-2021-12-13-b26f5c0f/src/ap/ap_config.h -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/ap/ap_config.h -+++ hostapd-2021-12-13-b26f5c0f/src/ap/ap_config.h -@@ -1083,6 +1083,7 @@ struct hostapd_config { - } *acs_chan_bias; - unsigned int num_acs_chan_bias; - #endif /* CONFIG_ACS */ -+ int enable_160mhz_bw; - int disable_40mhz_scan; - - struct wpabuf *lci; -Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver.h -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/drivers/driver.h -+++ hostapd-2021-12-13-b26f5c0f/src/drivers/driver.h -@@ -1236,6 +1236,10 @@ struct wpa_driver_associate_params { - * 2 = BURST beacon tx mode - */ - int beacon_tx_mode; -+ /** -+ * Enable 160MHz BW - set it 1 to enable mesh 160MHz 6G -+ */ -+ int enable_160mhz_bw; - }; - - enum hide_ssid { -Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/config.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/config.c -+++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/config.c -@@ -2742,6 +2742,7 @@ static const struct parse_data ssid_fiel - { INT_RANGE(sae_pk, 0, 2) }, - { INT_RANGE(disable_40mhz_scan, 0, 1)}, - { INT_RANGE(beacon_tx_mode, 1, 2)}, -+ { INT_RANGE(enable_160mhz_bw, 0, 1)}, - }; - - #undef OFFSET -Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/config_file.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/config_file.c -+++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/config_file.c -@@ -890,6 +890,7 @@ static void wpa_config_write_network(FIL - #endif /* CONFIG_HE_OVERRIDES */ - INT(disable_40mhz_scan); - INT(beacon_tx_mode); -+ INT(enable_160mhz_bw); - #undef STR - #undef INT - #undef INT_DEF -Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/config_ssid.h -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/config_ssid.h -+++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/config_ssid.h -@@ -1208,6 +1208,11 @@ struct wpa_ssid { - * 2 = BURST MODE - */ - int beacon_tx_mode; -+ -+ /** -+ * Enable 160MHz BW - set it 1 to enable mesh 160MHz 6G -+ */ -+ int enable_160mhz_bw; - }; - - #endif /* CONFIG_SSID_H */ -Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_cli.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/wpa_cli.c -+++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_cli.c -@@ -1491,6 +1491,7 @@ static const char *network_fields[] = { - "mac_addr", "pbss", "wps_disabled", - "disable_40mhz_scan", - "beacon_tx_mode", -+ "enable_160mhz_bw", - }; - - -Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant.conf -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/wpa_supplicant.conf -+++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant.conf -@@ -1699,6 +1699,11 @@ fast_reauth=1 - # In STA mode it defines the EDMG channel for connection (if supported by AP). - #edmg_channel=9 - -+#To configure 80MHz and 160MHz in Mesh mode. -+#Set 0 to enable 80MHz in Mesh mode -+#Set 1 to enable 160MHz in Mesh mode -+#enable_160mhz_bw=1 -+ - # Example blocks: - - # Simple case: WPA-PSK, PSK as an ASCII passphrase, allow all valid ciphers -Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/wpa_supplicant.c -+++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/wpa_supplicant.c -@@ -2541,12 +2541,20 @@ void ibss_mesh_setup_freq(struct wpa_sup - struct hostapd_hw_modes *mode = NULL; - int ht40plus[] = { 1, 2, 3, 4, 5, 6, 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157, - 165, 173, 184, 192 }; -- int bw80[] = { 5180, 5260, 5500, 5580, 5660, 5745, 5825, 5955, -- 6035, 6115, 6195, 6275, 6355, 6435, 6515, -- 6595, 6675, 6755, 6835, 6915, 6995 }; -- int bw160[] = { 5745, 5955, 6115, 6275, 6435, 6595, 6755, 6915 }; -+ /* bw_80_160 array members are 80MHz start freq, 80MHz end freq and so on -+ */ -+ unsigned int bw_80_160[] = { 5180, 5240, 5260, 5320, -+ 5500, 5560, 5580, 5660, -+ 5745, 5805, 5825, 5885, -+ 5955, 6015, 6035, 6095, -+ 6115, 6175, 6195, 6255, -+ 6275, 6335, 6355, 6415, -+ 6435, 6495, 6515, 6575, -+ 6595, 6655, 6675, 6735, -+ 6755, 6815, 6835, 6895, -+ 6915, 6975, 6995, 7055 }; - struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL; -- u8 channel; -+ u8 channel, chan_80mhz; - int i, chan_idx, ht40 = -1, res, obss_scan = !(ssid->noscan); - unsigned int j, k; - struct hostapd_freq_params vht_freq; -@@ -2769,60 +2777,79 @@ skip_to_6ghz: - return; - - /* Enable HE with VHT for 5 GHz */ -- freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported; -+ vht_freq.he_enabled = mode->he_capab[ieee80211_mode].he_supported; - - #ifdef CONFIG_HE_OVERRIDES - if (is_24ghz) - goto skip_vht80; - #endif /* CONFIG_HE_OVERRIDES */ - -- /* setup center_freq1, bandwidth */ -- for (j = 0; j < ARRAY_SIZE(bw80); j++) { -- if (freq->freq >= bw80[j] && -- freq->freq < bw80[j] + 80) -+ for (j = 0; j < ARRAY_SIZE(bw_80_160); j+=2) { -+ /* If the config provided freq available between any of two indices -+ * get the starting range of the channel to check chan availability -+ */ -+ if (freq->freq >= bw_80_160[j] && freq->freq <= bw_80_160[j+1]) { -+ ieee80211_freq_to_chan(bw_80_160[j], &chan_80mhz); -+ seg0 = chan_80mhz + 6; - break; -+ } - } - -- if (j == ARRAY_SIZE(bw80) || -- ieee80211_freq_to_chan(bw80[j], &channel) == NUM_HOSTAPD_MODES) -+ if (j == ARRAY_SIZE(bw_80_160)) - return; - - /* Back to HT configuration if channel not usable */ -- if (!ibss_mesh_is_80mhz_avail(channel, mode)) -+ if (!ibss_mesh_is_80mhz_avail(chan_80mhz, mode)) - return; - - chwidth = CHANWIDTH_80MHZ; -- seg0 = channel + 6; - seg1 = 0; - - if ((mode->he_capab[ieee80211_mode].phy_cap[ - HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] & -- HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G)) { -- /* In 160 MHz, the initial four 20 MHz channels were validated -- * above; check the remaining four 20 MHz channels for the total -- * of 160 MHz bandwidth. -- */ -- if (!ibss_mesh_is_80mhz_avail(channel + 16, mode)) -- break; -- -- for (j = 0; j < ARRAY_SIZE(bw160); j++) { -- if (freq->freq == bw160[j]) { -- chwidth = CHANWIDTH_160MHZ; -- seg0 = channel + 14; -+ HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G) && (ssid->enable_160mhz_bw)) { -+ chan_80mhz = freq->channel + 16; -+ for (j = 0; j < ARRAY_SIZE(bw_80_160); j+=2) { -+ if (freq->freq >= bw_80_160[j] && freq->freq <= bw_80_160[j+1]) { -+ if (j % 4 == 0) { -+ ieee80211_freq_to_chan(bw_80_160[j], -+ &chan_80mhz); -+ seg0 = chan_80mhz + 14; -+ -+ /* Get secondary 80MHz channel using freq by -+ * adding 16*5 ie., 80MHz. -+ */ -+ ieee80211_freq_to_chan((bw_80_160[j] + 16*5), -+ &chan_80mhz); -+ } else { -+ ieee80211_freq_to_chan(bw_80_160[j], -+ &chan_80mhz); -+ seg0 = chan_80mhz - 2; -+ /* Get secondary 80MHz channel using freq by -+ * subtracting 16*5 ie., 80MHz. -+ */ -+ ieee80211_freq_to_chan((bw_80_160[j] - 16*5), -+ &chan_80mhz); -+ } -+ -+ if (!ibss_mesh_is_80mhz_avail(chan_80mhz, mode)) -+ seg0 = freq->channel + 6; -+ else -+ chwidth = CHANWIDTH_160MHZ; - break; -- } -- } -- } -+ } -+ } -+ } - - if (ssid->max_oper_chwidth == CHANWIDTH_80P80MHZ) { - /* setup center_freq2, bandwidth */ -- for (k = 0; k < ARRAY_SIZE(bw80); k++) { -+ for (k = 0; k < ARRAY_SIZE(bw_80_160); k++) { - /* Only accept 80 MHz segments separated by a gap */ -- if (j == k || abs(bw80[j] - bw80[k]) == 80) -+ if (j == k || abs(bw_80_160[j] - bw_80_160[k]) == 80) - continue; - -- if (ieee80211_freq_to_chan(bw80[k], &channel) == -- NUM_HOSTAPD_MODES) -+ if (ieee80211_freq_to_chan(bw_80_160[k], -+ &channel) == NUM_HOSTAPD_MODES) - return; - - for (i = channel; i < channel + 16; i += 4) { diff --git a/feeds/ipq95xx/hostapd/patches/p00-003-hostapd-add-acs_exclude_6ghz_non_psc-option-for-acs-.patch b/feeds/ipq95xx/hostapd/patches/p00-003-hostapd-add-acs_exclude_6ghz_non_psc-option-for-acs-.patch deleted file mode 100644 index 501fe032e..000000000 --- a/feeds/ipq95xx/hostapd/patches/p00-003-hostapd-add-acs_exclude_6ghz_non_psc-option-for-acs-.patch +++ /dev/null @@ -1,369 +0,0 @@ -From daf67e765bcfa6ff6affb1a916696271014303b2 Mon Sep 17 00:00:00 2001 -From: P Praneesh -Date: Mon, 21 Feb 2022 11:49:50 +0530 -Subject: [PATCH] hostapd: add acs_exclude_6ghz_non_psc option for acs non - offload driver - -Hostapd configuration "acs_exclude_6ghz_non_psc" is supported for ACS -offloaded driver alone. Extend the support to ACS non offload driver -by adding 6G Preferred Scan Channel check and hostapd config flag -during scan and survey dump. - -Signed-off-by: P Praneesh ---- - src/ap/acs.c | 141 ++++++++++++++++++++++++++++++++++++++++--- - src/ap/ap_drv_ops.h | 6 +- - src/ap/bss_load.c | 3 +- - src/drivers/driver.h | 4 +- - src/drivers/driver_nl80211.c | 30 ++++++--- - 5 files changed, 166 insertions(+), 18 deletions(-) - ---- a/src/ap/acs.c -+++ b/src/ap/acs.c -@@ -641,6 +641,112 @@ static int is_common_24ghz_chan(int chan - #endif /* ACS_24GHZ_PREFER_1_6_11 */ - - static void -+acs_find_6g_psc_chan_mode(struct hostapd_iface *iface, -+ struct hostapd_hw_modes *mode, -+ int n_chans, u32 bw, -+ struct hostapd_channel_data **rand_chan, -+ struct hostapd_channel_data **ideal_chan, -+ long double *ideal_factor) -+{ -+ struct hostapd_channel_data *chan, *adj_chan = NULL; -+ long double factor; -+ int i, j; -+ unsigned int k; -+ -+ for (i = 0; i < mode->num_channels; i++) { -+ double total_weight; -+ struct acs_bias *bias; -+ -+ chan = &mode->channels[i]; -+ if (!chan_pri_allowed(chan)) -+ continue; -+ -+ if (!is_in_chanlist(iface, chan)) -+ continue; -+ -+ if (!is_in_freqlist(iface, chan)) -+ continue; -+ -+ if (!is_6ghz_psc_frequency(chan->freq)) -+ continue; -+ -+ if (!chan_bw_allowed(chan, bw, 1, 1)) { -+ wpa_printf(MSG_DEBUG, -+ "ACS: Channel %d: BW %u is not supported", -+ chan->chan, bw); -+ continue; -+ } -+ -+ factor = 0; -+ if (acs_usable_chan(chan)) -+ factor = chan->interference_factor; -+ total_weight = 1; -+ -+ /* Start index from -1 because all the PSC channels are located in -+ * secondary 20MHz of primary 40MHz. Ex: CH33 - CH61 has 160MHz BW, PSC -+ * CH37 which is secondary 20MHz of primary 40MHz. -+ */ -+ -+ for (j = -1; j < n_chans; j++) { -+ adj_chan = acs_find_chan(iface, chan->freq + (j * 20)); -+ if (!adj_chan) -+ break; -+ -+ if (!chan_bw_allowed(adj_chan, bw, 1, 0)) { -+ wpa_printf(MSG_DEBUG, -+ "ACS: PRI Channel %d: secondary channel %d BW %u is not supported", -+ chan->chan, adj_chan->chan, bw); -+ break; -+ } -+ -+ if (acs_usable_chan(adj_chan)) { -+ factor += adj_chan->interference_factor; -+ total_weight += 1; -+ } -+ } -+ -+ if (j != n_chans) { -+ wpa_printf(MSG_DEBUG, "ACS: Channel %d: not enough bandwidth", -+ chan->chan); -+ continue; -+ } -+ -+ factor /= total_weight; -+ -+ bias = NULL; -+ if (iface->conf->acs_chan_bias) { -+ for (k = 0; k < iface->conf->num_acs_chan_bias; k++) { -+ bias = &iface->conf->acs_chan_bias[k]; -+ if (bias->channel == chan->chan) -+ break; -+ bias = NULL; -+ } -+ } -+ -+ if (bias) { -+ factor *= bias->bias; -+ wpa_printf(MSG_DEBUG, -+ "ACS: * channel %d: total interference = %Lg (%f bias)", -+ chan->chan, factor, bias->bias); -+ } else { -+ wpa_printf(MSG_DEBUG, -+ "ACS: * channel %d: total interference = %Lg", -+ chan->chan, factor); -+ } -+ -+ if (acs_usable_chan(chan) && -+ (!*ideal_chan || factor < *ideal_factor)) { -+ *ideal_factor = factor; -+ *ideal_chan = chan; -+ } -+ -+ /* This channel would at least be usable */ -+ if (!(*rand_chan)) -+ *rand_chan = chan; -+ } -+} -+ -+static void - acs_find_ideal_chan_mode(struct hostapd_iface *iface, - struct hostapd_hw_modes *mode, - int n_chans, u32 bw, -@@ -874,10 +980,17 @@ bw_selected: - - for (i = 0; i < iface->num_hw_features; i++) { - mode = &iface->hw_features[i]; -- if (!hostapd_hw_skip_mode(iface, mode)) -- acs_find_ideal_chan_mode(iface, mode, n_chans, bw, -- &rand_chan, &ideal_chan, -- &ideal_factor); -+ if (!hostapd_hw_skip_mode(iface, mode)) { -+ if (iface->conf->acs_exclude_6ghz_non_psc) { -+ acs_find_6g_psc_chan_mode(iface, mode, n_chans, bw, -+ &rand_chan, &ideal_chan, -+ &ideal_factor); -+ } else { -+ acs_find_ideal_chan_mode(iface, mode, n_chans, bw, -+ &rand_chan, &ideal_chan, -+ &ideal_factor); -+ } -+ } - } - - if (ideal_chan) { -@@ -892,19 +1005,42 @@ bw_selected: - - static void acs_adjust_center_freq(struct hostapd_iface *iface) - { -- int offset; -+ int psc_chan[] = {37, 53, 69, 85, 101, 117, -+ 133, 149, 165, 181, 197, 213} ; -+ int offset, i; -+ u8 bw = hostapd_get_oper_chwidth(iface->conf); -+ bool acs_exclude_6ghz_non_psc = iface->conf->acs_exclude_6ghz_non_psc; -+ bool is_sec_psc_chan = false; - - wpa_printf(MSG_DEBUG, "ACS: Adjusting VHT center frequency"); - -- switch (hostapd_get_oper_chwidth(iface->conf)) { -+ if (acs_exclude_6ghz_non_psc && (bw == CHANWIDTH_160MHZ)) { -+ for (i = 0; i < ARRAY_SIZE(psc_chan); i++) { -+ if (psc_chan[i] == iface->conf->channel) { -+ is_sec_psc_chan = (i%2) ? true : false; -+ break; -+ } -+ } -+ } -+ -+ switch (bw) { - case CHANWIDTH_USE_HT: - offset = 2 * iface->conf->secondary_channel; - break; - case CHANWIDTH_80MHZ: -- offset = 6; -+ if (acs_exclude_6ghz_non_psc) -+ offset = 2; -+ else -+ offset = 6; - break; - case CHANWIDTH_160MHZ: -- offset = 14; -+ /* In 160MHz, if primary 20MHz present in secondary 80MHz, then -+ * subtract with -6 to find the center frequency of the 160MHz -+ */ -+ if (acs_exclude_6ghz_non_psc) -+ offset = is_sec_psc_chan ? -6 : 10; -+ else -+ offset = 14; - break; - default: - /* TODO: How can this be calculated? Adjust -@@ -1001,7 +1137,8 @@ static void acs_scan_complete(struct hos - wpa_printf(MSG_DEBUG, "ACS: Using survey based algorithm (acs_num_scans=%d)", - iface->conf->acs_num_scans); - -- err = hostapd_drv_get_survey(iface->bss[0], 0); -+ err = hostapd_drv_get_survey(iface->bss[0], 0, -+ iface->conf->acs_exclude_6ghz_non_psc); - if (err) { - wpa_printf(MSG_ERROR, "ACS: Failed to get survey data"); - goto fail; -@@ -1043,6 +1180,11 @@ static int * acs_request_scan_add_freqs( - if (!is_in_freqlist(iface, chan)) - continue; - -+ if (is_6ghz_freq(chan->freq) && -+ iface->conf->acs_exclude_6ghz_non_psc && -+ !is_6ghz_psc_frequency(chan->freq)) -+ continue; -+ - *freq++ = chan->freq; - } - ---- a/src/ap/ap_drv_ops.h -+++ b/src/ap/ap_drv_ops.h -@@ -266,13 +266,15 @@ static inline void hostapd_drv_poll_clie - } - - static inline int hostapd_drv_get_survey(struct hostapd_data *hapd, -- unsigned int freq) -+ unsigned int freq, -+ bool acs_exclude_6ghz_non_psc) - { - if (hapd->driver == NULL) - return -1; - if (!hapd->driver->get_survey) - return -1; -- return hapd->driver->get_survey(hapd->drv_priv, freq); -+ return hapd->driver->get_survey(hapd->drv_priv, freq, -+ acs_exclude_6ghz_non_psc); - } - - static inline int hostapd_get_country(struct hostapd_data *hapd, char *alpha2) ---- a/src/ap/bss_load.c -+++ b/src/ap/bss_load.c -@@ -49,7 +49,8 @@ static void update_channel_utilization(v - if (!(hapd->beacon_set_done && hapd->started)) - return; - -- err = hostapd_drv_get_survey(hapd, hapd->iface->freq); -+ err = hostapd_drv_get_survey(hapd, hapd->iface->freq, -+ hapd->iface->conf->acs_exclude_6ghz_non_psc); - if (err) { - wpa_printf(MSG_ERROR, "BSS Load: Failed to get survey data"); - return; ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -4186,6 +4186,8 @@ struct wpa_driver_ops { - * @priv: Private driver interface data - * @freq: If set, survey data for the specified frequency is only - * being requested. If not set, all survey data is requested. -+ * @acs_exclude_6ghz_non_psc: If set Include only preferred scan -+ * channels from 6 GHz band for ACS - * Returns: 0 on success, -1 on failure - * - * Use this to retrieve: -@@ -4204,7 +4206,7 @@ struct wpa_driver_ops { - * for each survey. The min_nf of the channel is updated for each - * survey. - */ -- int (*get_survey)(void *priv, unsigned int freq); -+ int (*get_survey)(void *priv, unsigned int freq, bool acs_exclude_6ghz_non_psc); - - /** - * status - Get driver interface status information ---- a/src/drivers/driver_nl80211.c -+++ b/src/drivers/driver_nl80211.c -@@ -9033,6 +9033,10 @@ static int check_survey_ok(struct nlattr - return freq_filter == surveyed_freq; - } - -+struct nl80211_get_survey_arg { -+ struct survey_results *survey_results; -+ bool acs_exclude_6ghz_non_psc; -+}; - - static int survey_handler(struct nl_msg *msg, void *arg) - { -@@ -9040,15 +9044,19 @@ static int survey_handler(struct nl_msg - struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); - struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1]; - struct survey_results *survey_results; -+ struct nl80211_get_survey_arg *arg_survey = -+ (struct nl80211_get_survey_arg *)arg; - u32 surveyed_freq = 0; - u32 ifidx; -+ bool acs_exclude_6ghz_non_psc; - - static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = { - [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 }, - [NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 }, - }; - -- survey_results = (struct survey_results *) arg; -+ survey_results = arg_survey->survey_results; -+ acs_exclude_6ghz_non_psc = arg_survey->acs_exclude_6ghz_non_psc; - - nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); -@@ -9077,6 +9085,11 @@ static int survey_handler(struct nl_msg - survey_results->freq_filter)) - return NL_SKIP; - -+ if (is_6ghz_freq(surveyed_freq) && -+ acs_exclude_6ghz_non_psc && -+ !is_6ghz_psc_frequency(surveyed_freq)) -+ return NL_SKIP; -+ - if (survey_results->freq_filter && - survey_results->freq_filter != surveyed_freq) { - wpa_printf(MSG_EXCESSIVE, "nl80211: Ignoring survey data for freq %d MHz", -@@ -9090,19 +9103,22 @@ static int survey_handler(struct nl_msg - } - - --static int wpa_driver_nl80211_get_survey(void *priv, unsigned int freq) -+static int wpa_driver_nl80211_get_survey(void *priv, unsigned int freq, -+ bool acs_exclude_6ghz_non_psc) - { - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - struct nl_msg *msg; - int err; - union wpa_event_data data; -- struct survey_results *survey_results; -+ struct nl80211_get_survey_arg arg; - - os_memset(&data, 0, sizeof(data)); -- survey_results = &data.survey_results; -+ os_memset(&arg, 0, sizeof(arg)); -+ arg.survey_results = &data.survey_results; -+ arg.acs_exclude_6ghz_non_psc = acs_exclude_6ghz_non_psc; - -- dl_list_init(&survey_results->survey_list); -+ dl_list_init(&arg.survey_results->survey_list); - - msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SURVEY); - if (!msg) -@@ -9114,7 +9130,7 @@ static int wpa_driver_nl80211_get_survey - do { - wpa_printf(MSG_DEBUG, "nl80211: Fetch survey data"); - err = send_and_recv_msgs(drv, msg, survey_handler, -- survey_results, NULL, NULL); -+ &arg, NULL, NULL); - } while (err > 0); - - if (err) -@@ -9122,7 +9138,7 @@ static int wpa_driver_nl80211_get_survey - else - wpa_supplicant_event(drv->ctx, EVENT_SURVEY, &data); - -- clean_survey_results(survey_results); -+ clean_survey_results(arg.survey_results); - return err; - } - diff --git a/feeds/ipq95xx/hostapd/patches/q00-001-crypto-Remove-unused-crypto_ec_point_solve_y_coord.patch b/feeds/ipq95xx/hostapd/patches/q00-001-crypto-Remove-unused-crypto_ec_point_solve_y_coord.patch deleted file mode 100644 index b6868f21b..000000000 --- a/feeds/ipq95xx/hostapd/patches/q00-001-crypto-Remove-unused-crypto_ec_point_solve_y_coord.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 1dc7e10a10275b8921e1417acc209ee8ee904c81 Mon Sep 17 00:00:00 2001 -From: Jouni Malinen -Date: Fri, 7 Jan 2022 19:44:10 +0200 -Subject: [PATCH 1/5] crypto: Remove unused crypto_ec_point_solve_y_coord() - -This wrapper function is not used anymore, so remove it. - -Signed-off-by: Jouni Malinen -Signed-off-by: Rameshkumar Sundaram -(cherry picked from commit 9b14aed90887e1ec35830d60eea9ebde6a2cf814) ---- - src/crypto/crypto.h | 12 ------------ - src/crypto/crypto_openssl.c | 15 --------------- - src/crypto/crypto_wolfssl.c | 24 ------------------------ - 3 files changed, 51 deletions(-) - -diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h -index 7d2ebd6..6ec4284 100644 ---- a/src/crypto/crypto.h -+++ b/src/crypto/crypto.h -@@ -858,18 +858,6 @@ int crypto_ec_point_mul(struct crypto_ec *e, const struct crypto_ec_point *p, - int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p); - - /** -- * crypto_ec_point_solve_y_coord - Solve y coordinate for an x coordinate -- * @e: EC context from crypto_ec_init() -- * @p: EC point to use for the returning the result -- * @x: x coordinate -- * @y_bit: y-bit (0 or 1) for selecting the y value to use -- * Returns: 0 on success, -1 on failure -- */ --int crypto_ec_point_solve_y_coord(struct crypto_ec *e, -- struct crypto_ec_point *p, -- const struct crypto_bignum *x, int y_bit); -- --/** - * crypto_ec_point_compute_y_sqr - Compute y^2 = x^3 + ax + b - * @e: EC context from crypto_ec_init() - * @x: x coordinate -diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c -index 72f93c1..55a62bc 100644 ---- a/src/crypto/crypto_openssl.c -+++ b/src/crypto/crypto_openssl.c -@@ -1880,21 +1880,6 @@ int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p) - } - - --int crypto_ec_point_solve_y_coord(struct crypto_ec *e, -- struct crypto_ec_point *p, -- const struct crypto_bignum *x, int y_bit) --{ -- if (TEST_FAIL()) -- return -1; -- if (!EC_POINT_set_compressed_coordinates_GFp(e->group, (EC_POINT *) p, -- (const BIGNUM *) x, y_bit, -- e->bnctx) || -- !EC_POINT_is_on_curve(e->group, (EC_POINT *) p, e->bnctx)) -- return -1; -- return 0; --} -- -- - struct crypto_bignum * - crypto_ec_point_compute_y_sqr(struct crypto_ec *e, - const struct crypto_bignum *x) -diff --git a/src/crypto/crypto_wolfssl.c b/src/crypto/crypto_wolfssl.c -index 2e4bf89..efe693b 100644 ---- a/src/crypto/crypto_wolfssl.c -+++ b/src/crypto/crypto_wolfssl.c -@@ -1626,30 +1626,6 @@ int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p) - } - - --int crypto_ec_point_solve_y_coord(struct crypto_ec *e, -- struct crypto_ec_point *p, -- const struct crypto_bignum *x, int y_bit) --{ -- byte buf[1 + 2 * MAX_ECC_BYTES]; -- int ret; -- int prime_len = crypto_ec_prime_len(e); -- -- if (TEST_FAIL()) -- return -1; -- -- buf[0] = y_bit ? ECC_POINT_COMP_ODD : ECC_POINT_COMP_EVEN; -- ret = crypto_bignum_to_bin(x, buf + 1, prime_len, prime_len); -- if (ret <= 0) -- return -1; -- ret = wc_ecc_import_point_der(buf, 1 + 2 * ret, e->key.idx, -- (ecc_point *) p); -- if (ret != 0) -- return -1; -- -- return 0; --} -- -- - struct crypto_bignum * - crypto_ec_point_compute_y_sqr(struct crypto_ec *e, - const struct crypto_bignum *x) --- -2.7.4 - diff --git a/feeds/ipq95xx/hostapd/patches/q00-002-EAP-pwd-Derive-the-y-coordinate-for-PWE-with-own-imp.patch b/feeds/ipq95xx/hostapd/patches/q00-002-EAP-pwd-Derive-the-y-coordinate-for-PWE-with-own-imp.patch deleted file mode 100644 index 0b2b75235..000000000 --- a/feeds/ipq95xx/hostapd/patches/q00-002-EAP-pwd-Derive-the-y-coordinate-for-PWE-with-own-imp.patch +++ /dev/null @@ -1,115 +0,0 @@ -From bd64d44e25795bfaf6232c0720fd6fe8f3674c7d Mon Sep 17 00:00:00 2001 -From: Jouni Malinen -Date: Fri, 7 Jan 2022 18:52:27 +0200 -Subject: [PATCH 2/5] EAP-pwd: Derive the y coordinate for PWE with own - implementation - -The crypto_ec_point_solve_y_coord() wrapper function might not use -constant time operations in the crypto library and as such, could leak -side channel information about the password that is used to generate the -PWE in the hunting and pecking loop. As such, calculate the two possible -y coordinate values and pick the correct one to use with constant time -selection. - -Signed-off-by: Jouni Malinen -Signed-off-by: Rameshkumar Sundaram -(cherry picked from commit 8c502336d40cdb8d211e4f8b8d59d7d282253733) ---- - src/eap_common/eap_pwd_common.c | 46 ++++++++++++++++++++++++++++++++--------- - 1 file changed, 36 insertions(+), 10 deletions(-) - -diff --git a/src/eap_common/eap_pwd_common.c b/src/eap_common/eap_pwd_common.c -index 2b2b8ef..ff22b29 100644 ---- a/src/eap_common/eap_pwd_common.c -+++ b/src/eap_common/eap_pwd_common.c -@@ -127,7 +127,8 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, - u8 qr_or_qnr_bin[MAX_ECC_PRIME_LEN]; - u8 x_bin[MAX_ECC_PRIME_LEN]; - u8 prime_bin[MAX_ECC_PRIME_LEN]; -- struct crypto_bignum *tmp2 = NULL; -+ u8 x_y[2 * MAX_ECC_PRIME_LEN]; -+ struct crypto_bignum *tmp2 = NULL, *y = NULL; - struct crypto_hash *hash; - unsigned char pwe_digest[SHA256_MAC_LEN], *prfbuf = NULL, ctr; - int ret = 0, res; -@@ -139,6 +140,7 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, - u8 found_ctr = 0, is_odd = 0; - int cmp_prime; - unsigned int in_range; -+ unsigned int is_eq; - - if (grp->pwe) - return -1; -@@ -151,11 +153,6 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, - if (crypto_bignum_to_bin(prime, prime_bin, sizeof(prime_bin), - primebytelen) < 0) - return -1; -- grp->pwe = crypto_ec_point_init(grp->group); -- if (!grp->pwe) { -- wpa_printf(MSG_INFO, "EAP-pwd: unable to create bignums"); -- goto fail; -- } - - if ((prfbuf = os_malloc(primebytelen)) == NULL) { - wpa_printf(MSG_INFO, "EAP-pwd: unable to malloc space for prf " -@@ -261,10 +258,37 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, - */ - crypto_bignum_deinit(x_candidate, 1); - x_candidate = crypto_bignum_init_set(x_bin, primebytelen); -- if (!x_candidate || -- crypto_ec_point_solve_y_coord(grp->group, grp->pwe, x_candidate, -- is_odd) != 0) { -- wpa_printf(MSG_INFO, "EAP-pwd: Could not solve for y"); -+ if (!x_candidate) -+ goto fail; -+ -+ /* y = sqrt(x^3 + ax + b) mod p -+ * if LSB(y) == LSB(pwd-seed): PWE = (x, y) -+ * else: PWE = (x, p - y) -+ * -+ * Calculate y and the two possible values for PWE and after that, -+ * use constant time selection to copy the correct alternative. -+ */ -+ y = crypto_ec_point_compute_y_sqr(grp->group, x_candidate); -+ if (!y || -+ dragonfly_sqrt(grp->group, y, y) < 0 || -+ crypto_bignum_to_bin(y, x_y, MAX_ECC_PRIME_LEN, primebytelen) < 0 || -+ crypto_bignum_sub(prime, y, y) < 0 || -+ crypto_bignum_to_bin(y, x_y + MAX_ECC_PRIME_LEN, -+ MAX_ECC_PRIME_LEN, primebytelen) < 0) { -+ wpa_printf(MSG_DEBUG, "SAE: Could not solve y"); -+ goto fail; -+ } -+ -+ /* Constant time selection of the y coordinate from the two -+ * options */ -+ is_eq = const_time_eq(is_odd, x_y[primebytelen - 1] & 0x01); -+ const_time_select_bin(is_eq, x_y, x_y + MAX_ECC_PRIME_LEN, -+ primebytelen, x_y + primebytelen); -+ os_memcpy(x_y, x_bin, primebytelen); -+ wpa_hexdump_key(MSG_DEBUG, "EAP-pwd: PWE", x_y, 2 * primebytelen); -+ grp->pwe = crypto_ec_point_from_bin(grp->group, x_y); -+ if (!grp->pwe) { -+ wpa_printf(MSG_DEBUG, "EAP-pwd: Could not generate PWE"); - goto fail; - } - -@@ -289,6 +313,7 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, - /* cleanliness and order.... */ - crypto_bignum_deinit(x_candidate, 1); - crypto_bignum_deinit(tmp2, 1); -+ crypto_bignum_deinit(y, 1); - crypto_bignum_deinit(qr, 1); - crypto_bignum_deinit(qnr, 1); - bin_clear_free(prfbuf, primebytelen); -@@ -296,6 +321,7 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, - os_memset(qnr_bin, 0, sizeof(qnr_bin)); - os_memset(qr_or_qnr_bin, 0, sizeof(qr_or_qnr_bin)); - os_memset(pwe_digest, 0, sizeof(pwe_digest)); -+ forced_memzero(x_y, sizeof(x_y)); - - return ret; - } --- -2.7.4 - diff --git a/feeds/ipq95xx/hostapd/patches/q00-003-SAE-Derive-the-y-coordinate-for-PWE-with-own-impleme.patch b/feeds/ipq95xx/hostapd/patches/q00-003-SAE-Derive-the-y-coordinate-for-PWE-with-own-impleme.patch deleted file mode 100644 index 38843a47a..000000000 --- a/feeds/ipq95xx/hostapd/patches/q00-003-SAE-Derive-the-y-coordinate-for-PWE-with-own-impleme.patch +++ /dev/null @@ -1,101 +0,0 @@ -From e900f6d2db719f18bd831dee0232ab485fafd740 Mon Sep 17 00:00:00 2001 -From: Jouni Malinen -Date: Fri, 7 Jan 2022 13:47:16 +0200 -Subject: [PATCH 3/5] SAE: Derive the y coordinate for PWE with own - implementation - -The crypto_ec_point_solve_y_coord() wrapper function might not use -constant time operations in the crypto library and as such, could leak -side channel information about the password that is used to generate the -PWE in the hunting and pecking loop. As such, calculate the two possible -y coordinate values and pick the correct one to use with constant time -selection. - -Signed-off-by: Jouni Malinen -Signed-off-by: Rameshkumar Sundaram -(cherry picked from commit 6c380f4c87fbda0bc1a2c8d522412cf1fc01d477) ---- - src/common/sae.c | 47 +++++++++++++++++++++++++++++++++-------------- - 1 file changed, 33 insertions(+), 14 deletions(-) - -diff --git a/src/common/sae.c b/src/common/sae.c -index b768c22..2440156 100644 ---- a/src/common/sae.c -+++ b/src/common/sae.c -@@ -290,14 +290,16 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1, - int pwd_seed_odd = 0; - u8 prime[SAE_MAX_ECC_PRIME_LEN]; - size_t prime_len; -- struct crypto_bignum *x = NULL, *qr = NULL, *qnr = NULL; -+ struct crypto_bignum *x = NULL, *y = NULL, *qr = NULL, *qnr = NULL; - u8 x_bin[SAE_MAX_ECC_PRIME_LEN]; - u8 x_cand_bin[SAE_MAX_ECC_PRIME_LEN]; - u8 qr_bin[SAE_MAX_ECC_PRIME_LEN]; - u8 qnr_bin[SAE_MAX_ECC_PRIME_LEN]; -+ u8 x_y[2 * SAE_MAX_ECC_PRIME_LEN]; - int res = -1; - u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_* - * mask */ -+ unsigned int is_eq; - - os_memset(x_bin, 0, sizeof(x_bin)); - -@@ -396,25 +398,42 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1, - goto fail; - } - -- if (!sae->tmp->pwe_ecc) -- sae->tmp->pwe_ecc = crypto_ec_point_init(sae->tmp->ec); -- if (!sae->tmp->pwe_ecc) -- res = -1; -- else -- res = crypto_ec_point_solve_y_coord(sae->tmp->ec, -- sae->tmp->pwe_ecc, x, -- pwd_seed_odd); -- if (res < 0) { -- /* -- * This should not happen since we already checked that there -- * is a result. -- */ -+ /* y = sqrt(x^3 + ax + b) mod p -+ * if LSB(save) == LSB(y): PWE = (x, y) -+ * else: PWE = (x, p - y) -+ * -+ * Calculate y and the two possible values for PWE and after that, -+ * use constant time selection to copy the correct alternative. -+ */ -+ y = crypto_ec_point_compute_y_sqr(sae->tmp->ec, x); -+ if (!y || -+ dragonfly_sqrt(sae->tmp->ec, y, y) < 0 || -+ crypto_bignum_to_bin(y, x_y, SAE_MAX_ECC_PRIME_LEN, -+ prime_len) < 0 || -+ crypto_bignum_sub(sae->tmp->prime, y, y) < 0 || -+ crypto_bignum_to_bin(y, x_y + SAE_MAX_ECC_PRIME_LEN, -+ SAE_MAX_ECC_PRIME_LEN, prime_len) < 0) { - wpa_printf(MSG_DEBUG, "SAE: Could not solve y"); -+ goto fail; -+ } -+ -+ is_eq = const_time_eq(pwd_seed_odd, x_y[prime_len - 1] & 0x01); -+ const_time_select_bin(is_eq, x_y, x_y + SAE_MAX_ECC_PRIME_LEN, -+ prime_len, x_y + prime_len); -+ os_memcpy(x_y, x_bin, prime_len); -+ wpa_hexdump_key(MSG_DEBUG, "SAE: PWE", x_y, 2 * prime_len); -+ crypto_ec_point_deinit(sae->tmp->pwe_ecc, 1); -+ sae->tmp->pwe_ecc = crypto_ec_point_from_bin(sae->tmp->ec, x_y); -+ if (!sae->tmp->pwe_ecc) { -+ wpa_printf(MSG_DEBUG, "SAE: Could not generate PWE"); -+ res = -1; - } - - fail: -+ forced_memzero(x_y, sizeof(x_y)); - crypto_bignum_deinit(qr, 0); - crypto_bignum_deinit(qnr, 0); -+ crypto_bignum_deinit(y, 1); - os_free(stub_password); - bin_clear_free(tmp_password, password_len); - crypto_bignum_deinit(x, 1); --- -2.7.4 - diff --git a/feeds/ipq95xx/hostapd/patches/q00-004-SAE-Move-sqrt-implementation-into-a-helper-function.patch b/feeds/ipq95xx/hostapd/patches/q00-004-SAE-Move-sqrt-implementation-into-a-helper-function.patch deleted file mode 100644 index 90f8a0e34..000000000 --- a/feeds/ipq95xx/hostapd/patches/q00-004-SAE-Move-sqrt-implementation-into-a-helper-function.patch +++ /dev/null @@ -1,100 +0,0 @@ -From e04120904221ac4c69a409451d53de04180ae4a3 Mon Sep 17 00:00:00 2001 -From: Jouni Malinen -Date: Fri, 7 Jan 2022 13:47:16 +0200 -Subject: [PATCH 4/5] SAE: Move sqrt() implementation into a helper function - -This implementation within SSWU can be helpful for other users of the -dragonfly design, so move it into a shared helper function. - -Signed-off-by: Jouni Malinen -Signed-off-by: Rameshkumar Sundaram -(cherry picked from commit 8ebd8aacc2343fae0374d07d66aea16c05abc5e2) ---- - src/common/dragonfly.c | 34 ++++++++++++++++++++++++++++++++++ - src/common/dragonfly.h | 2 ++ - src/common/sae.c | 14 ++------------ - 3 files changed, 38 insertions(+), 12 deletions(-) - -diff --git a/src/common/dragonfly.c b/src/common/dragonfly.c -index 547be66..1e84271 100644 ---- a/src/common/dragonfly.c -+++ b/src/common/dragonfly.c -@@ -213,3 +213,37 @@ int dragonfly_generate_scalar(const struct crypto_bignum *order, - "dragonfly: Unable to get randomness for own scalar"); - return -1; - } -+ -+ -+/* res = sqrt(val) */ -+int dragonfly_sqrt(struct crypto_ec *ec, const struct crypto_bignum *val, -+ struct crypto_bignum *res) -+{ -+ const struct crypto_bignum *prime; -+ struct crypto_bignum *tmp, *one; -+ int ret = 0; -+ u8 prime_bin[DRAGONFLY_MAX_ECC_PRIME_LEN]; -+ size_t prime_len; -+ -+ /* For prime p such that p = 3 mod 4, sqrt(w) = w^((p+1)/4) mod p */ -+ -+ prime = crypto_ec_get_prime(ec); -+ prime_len = crypto_ec_prime_len(ec); -+ tmp = crypto_bignum_init(); -+ one = crypto_bignum_init_uint(1); -+ -+ if (crypto_bignum_to_bin(prime, prime_bin, sizeof(prime_bin), -+ prime_len) < 0 || -+ (prime_bin[prime_len - 1] & 0x03) != 3 || -+ !tmp || !one || -+ /* tmp = (p+1)/4 */ -+ crypto_bignum_add(prime, one, tmp) < 0 || -+ crypto_bignum_rshift(tmp, 2, tmp) < 0 || -+ /* res = sqrt(val) */ -+ crypto_bignum_exptmod(val, tmp, prime, res) < 0) -+ ret = -1; -+ -+ crypto_bignum_deinit(tmp, 0); -+ crypto_bignum_deinit(one, 0); -+ return ret; -+} -diff --git a/src/common/dragonfly.h b/src/common/dragonfly.h -index ec3dd59..84d67f5 100644 ---- a/src/common/dragonfly.h -+++ b/src/common/dragonfly.h -@@ -27,5 +27,7 @@ int dragonfly_generate_scalar(const struct crypto_bignum *order, - struct crypto_bignum *_rand, - struct crypto_bignum *_mask, - struct crypto_bignum *scalar); -+int dragonfly_sqrt(struct crypto_ec *ec, const struct crypto_bignum *val, -+ struct crypto_bignum *res); - - #endif /* DRAGONFLY_H */ -diff --git a/src/common/sae.c b/src/common/sae.c -index 372905d..8974668 100644 ---- a/src/common/sae.c -+++ b/src/common/sae.c -@@ -766,19 +766,9 @@ static struct crypto_ec_point * sswu(struct crypto_ec *ec, int group, - const_time_select_bin(is_qr, bin1, bin2, prime_len, x_y); - wpa_hexdump_key(MSG_DEBUG, "SSWU: x = CSEL(l, x1, x2)", x_y, prime_len); - -- /* y = sqrt(v) -- * For prime p such that p = 3 mod 4 --> v^((p+1)/4) */ -- if (crypto_bignum_to_bin(prime, bin1, sizeof(bin1), prime_len) < 0) -- goto fail; -- if ((bin1[prime_len - 1] & 0x03) != 3) { -- wpa_printf(MSG_DEBUG, "SSWU: prime does not have p = 3 mod 4"); -- goto fail; -- } -+ /* y = sqrt(v) */ - y = crypto_bignum_init(); -- if (!y || -- crypto_bignum_add(prime, one, t1) < 0 || -- crypto_bignum_rshift(t1, 2, t1) < 0 || -- crypto_bignum_exptmod(v, t1, prime, y) < 0) -+ if (!y || dragonfly_sqrt(ec, v, y) < 0) - goto fail; - debug_print_bignum("SSWU: y = sqrt(v)", y, prime_len); - --- -2.7.4 - diff --git a/feeds/ipq95xx/hostapd/patches/q00-005-EAP-pwd-Fix-the-prefix-in-a-debug-message.patch b/feeds/ipq95xx/hostapd/patches/q00-005-EAP-pwd-Fix-the-prefix-in-a-debug-message.patch deleted file mode 100644 index 026306d3b..000000000 --- a/feeds/ipq95xx/hostapd/patches/q00-005-EAP-pwd-Fix-the-prefix-in-a-debug-message.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 39a124f8145c8751af95d4017b292d6b4ef423a1 Mon Sep 17 00:00:00 2001 -From: Jouni Malinen -Date: Tue, 1 Feb 2022 19:58:40 +0200 -Subject: [PATCH 5/5] EAP-pwd: Fix the prefix in a debug message - -This was copied from sae.c, but the debug message prefix was not changed -to match the use here. - -Signed-off-by: Jouni Malinen -Signed-off-by: Rameshkumar Sundaram -(cherry picked from commit 34575ad72ebbb5411e394af7090f79a27a60a9aa) ---- - src/eap_common/eap_pwd_common.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/eap_common/eap_pwd_common.c b/src/eap_common/eap_pwd_common.c -index ff22b29..0e3a7b2 100644 ---- a/src/eap_common/eap_pwd_common.c -+++ b/src/eap_common/eap_pwd_common.c -@@ -275,7 +275,7 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, - crypto_bignum_sub(prime, y, y) < 0 || - crypto_bignum_to_bin(y, x_y + MAX_ECC_PRIME_LEN, - MAX_ECC_PRIME_LEN, primebytelen) < 0) { -- wpa_printf(MSG_DEBUG, "SAE: Could not solve y"); -+ wpa_printf(MSG_DEBUG, "EAP-pwd: Could not solve y"); - goto fail; - } - --- -2.7.4 - diff --git a/feeds/ipq95xx/hostapd/patches/q003-001-hostapd-Add-config-to-truncate-ext-capabilities.patch b/feeds/ipq95xx/hostapd/patches/q003-001-hostapd-Add-config-to-truncate-ext-capabilities.patch deleted file mode 100644 index 4a51aff52..000000000 --- a/feeds/ipq95xx/hostapd/patches/q003-001-hostapd-Add-config-to-truncate-ext-capabilities.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 234aa775f8046dc823a0ce72267f62045d81ee08 Mon Sep 17 00:00:00 2001 -From: Harshitha Prem -Date: Wed, 6 Jul 2022 17:03:52 +0530 -Subject: [PATCH] hostapd: Add config to truncate ext capabilities - -Certain legacy clients are not able to scan 11ax vaps due to -extended capabilities which are more than 8bytes in length. -Hence added a work around to trucate the ext caps to 8bytes -based on the hostapd config ext_cap_len. -Legacy clients are able to scan and connect if hostapd config -as ext_cap_len=8, ieee80211ac=1, ieee80211ax=0 - -Signed-off-by: Harshitha Prem ---- - hostapd/config_file.c | 2 ++ - src/ap/ap_config.h | 1 + - src/ap/ieee802_11_shared.c | 3 +++ - 3 files changed, 6 insertions(+) - -diff --git a/hostapd/config_file.c b/hostapd/config_file.c -index ede28a7..d91f3fc 100644 ---- a/hostapd/config_file.c -+++ b/hostapd/config_file.c -@@ -2358,6 +2358,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, - conf->country[2] = strtol(pos, NULL, 16); - } else if (os_strcmp(buf, "ieee80211d") == 0) { - conf->ieee80211d = atoi(pos); -+ } else if (os_strcmp(buf, "ext_cap_len") == 0) { -+ conf->ext_cap_len = atoi(pos); - } else if (os_strcmp(buf, "ieee80211h") == 0) { - conf->ieee80211h = atoi(pos); - } else if (os_strcmp(buf, "dfs_test_mode") == 0) { -diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h -index 5d12cf5..5b14a7f 100644 ---- a/src/ap/ap_config.h -+++ b/src/ap/ap_config.h -@@ -1059,6 +1059,7 @@ struct hostapd_config { - /* Use driver-generated interface addresses when adding multiple BSSs */ - u8 use_driver_iface_addr; - u8 skip_unii1_dfs_switch; -+ u8 ext_cap_len; - - #ifdef CONFIG_FST - struct fst_iface_cfg fst_cfg; -diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c -index 9536747..98be1ec 100644 ---- a/src/ap/ieee802_11_shared.c -+++ b/src/ap/ieee802_11_shared.c -@@ -456,6 +456,9 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid) - if (len < hapd->iface->extended_capa_len) - len = hapd->iface->extended_capa_len; - -+ if (hapd->iconf->ext_cap_len > 0 && hapd->iconf->ext_cap_len < len) -+ len = hapd->iconf->ext_cap_len; -+ - *pos++ = WLAN_EID_EXT_CAPAB; - *pos++ = len; - for (i = 0; i < len; i++, pos++) { --- -2.17.1 - diff --git a/feeds/ipq95xx/hostapd/patches/q01-001-mbssid-add-configuration-options.patch b/feeds/ipq95xx/hostapd/patches/q01-001-mbssid-add-configuration-options.patch deleted file mode 100644 index 6421d4d50..000000000 --- a/feeds/ipq95xx/hostapd/patches/q01-001-mbssid-add-configuration-options.patch +++ /dev/null @@ -1,75 +0,0 @@ -From cb6afcaacd3f0de23882fdd5e341a986a860bb3e Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Fri, 10 Sep 2021 14:47:55 -0700 -Subject: [PATCH 01/15] mbssid: add configuration options - -Add configuration options to enable multiple BSSID (MBSSID) and -enhanced multiple BSSID advertisements (EMA). -MBSSID enablement is mandatory to enable EMA. - -Signed-off-by: John Crispin -Signed-off-by: Aloka Dixit ---- - hostapd/config_file.c | 4 ++++ - hostapd/hostapd.conf | 10 ++++++++++ - src/ap/ap_config.c | 5 +++++ - src/ap/ap_config.h | 2 ++ - 4 files changed, 21 insertions(+) - ---- a/hostapd/config_file.c -+++ b/hostapd/config_file.c -@@ -4658,6 +4658,10 @@ static int hostapd_config_fill(struct ho - return 1; - } else if (os_strcmp(buf, "rnr") == 0) { - bss->rnr = atoi(pos); -+ } else if (os_strcmp(buf, "mbssid") == 0) { -+ conf->mbssid = atoi(pos); -+ } else if (os_strcmp(buf, "ema") == 0) { -+ conf->ema = atoi(pos); - } else { - wpa_printf(MSG_ERROR, - "Line %d: unknown configuration item '%s'", ---- a/hostapd/hostapd.conf -+++ b/hostapd/hostapd.conf -@@ -986,6 +986,16 @@ wmm_ac_vo_acm=0 - # Valid range: 0..20 TUs; default is 0 (disabled) - #unsol_bcast_probe_resp_interval=0 - -+# Multiple BSSID element support in beacon and probe response frames. -+# 0 = Disabled -+# 1 = Enabled -+#mbssid=0 -+ -+# Enhanced multiple BSSID advertisements support in beacons. -+# 0 = Disabled -+# 1 = Enabled -+#ema=0 -+ - ##### IEEE 802.1X-2004 related configuration ################################## - - # Require IEEE 802.1X authorization ---- a/src/ap/ap_config.c -+++ b/src/ap/ap_config.c -@@ -1503,6 +1503,11 @@ int hostapd_config_check(struct hostapd_ - return -1; - } - -+ if (!conf->mbssid && conf->ema) { -+ wpa_printf(MSG_ERROR, "mbssid must be enabled to enable ema"); -+ return -1; -+ } -+ - for (i = 0; i < conf->num_bss; i++) { - if (hostapd_config_check_bss(conf->bss[i], conf, full_config)) - return -1; ---- a/src/ap/ap_config.h -+++ b/src/ap/ap_config.h -@@ -1123,6 +1123,8 @@ struct hostapd_config { - unsigned int airtime_update_interval; - #define AIRTIME_MODE_MAX (__AIRTIME_MODE_MAX - 1) - #endif /* CONFIG_AIRTIME_POLICY */ -+ u8 mbssid; -+ u8 ema; - }; - - static inline u8 hostapd_get_he_6ghz_reg_pwr_type(struct hostapd_config *conf) diff --git a/feeds/ipq95xx/hostapd/patches/q01-001-tests-Initial-EHT-testing.patch b/feeds/ipq95xx/hostapd/patches/q01-001-tests-Initial-EHT-testing.patch deleted file mode 100644 index 386bc773a..000000000 --- a/feeds/ipq95xx/hostapd/patches/q01-001-tests-Initial-EHT-testing.patch +++ /dev/null @@ -1,786 +0,0 @@ -From 5758cb14681541dfab829d1ae204c861c05072a7 Mon Sep 17 00:00:00 2001 -From: Muna Sinada -Date: Mon, 4 Oct 2021 11:05:51 -0700 -Subject: [PATCH] tests: Initial EHT testing - -Add initial tests for EHT. - -Tests include the following: - - - eht80_to_24g_eht - EHT with 80 MHz channel width reconfigured to - 2.4 GHz EHT - - eht_40 - EHT and 40 MHz channel - - eht_use_sta_nsts - EHT with 80 MHz channel width and use_sta_nsts=1 - - eht_open - EHT AP with open mode configuration - - eht80_invalid2 - EHT with invalid 80 MHz channel configuration (seg0) - - eht80b - EHT with 80 MHz channel width (HT40- channel 40) - - eht80d - EHT with 80 MHz channel width (HT40- channel 48) - - eht_on_24ghz - Subset of EHT features on 2.4 GHz - - eht_params - EHT AP parameters - - eht_wifi_generation_24 - - eht_wifi_generation - - eht80 - EHT with 80 MHz channel width - - eht_20 - EHT and 20 MHz channel - - eht_disabled_on_sta - EHT AP and EHT STA disabled on STA - - eht80c - EHT with 80 MHz channel width (HT40+ channel 44) - - eht80_params - EHT with 80 MHz channel width and number of optional - features enabled - - eht80_csa - EHT with 80 MHz channel width and CSA - - eht160 - EHT with 160 MHz channel width [long] - - eht80_invalid - EHT with invalid 80 MHz channel configuration - (seg1: 80+80 not supported) - -Signed-off-by: Muna Sinada ---- - tests/hwsim/example-hostapd.config | 1 + - tests/hwsim/example-wpa_supplicant.config | 2 + - tests/hwsim/test_eht.py | 691 ++++++++++++++++++++++++++++++ - tests/hwsim/wpasupplicant.py | 2 +- - 4 files changed, 695 insertions(+), 1 deletion(-) - create mode 100644 tests/hwsim/test_eht.py - -diff --git a/tests/hwsim/example-hostapd.config b/tests/hwsim/example-hostapd.config -index d01a1d2edcfe..17cde61069a3 100644 ---- a/tests/hwsim/example-hostapd.config -+++ b/tests/hwsim/example-hostapd.config -@@ -50,6 +50,7 @@ CONFIG_LIBNL3_ROUTE=y - CONFIG_IEEE80211R=y - CONFIG_IEEE80211AC=y - CONFIG_IEEE80211AX=y -+CONFIG_IEEE80211BE=y - - CONFIG_OCV=y - -diff --git a/tests/hwsim/example-wpa_supplicant.config b/tests/hwsim/example-wpa_supplicant.config -index 5e5acd695729..6ed491f7a713 100644 ---- a/tests/hwsim/example-wpa_supplicant.config -+++ b/tests/hwsim/example-wpa_supplicant.config -@@ -60,6 +60,7 @@ CONFIG_CTRL_IFACE_DBUS_INTRO=y - CONFIG_IEEE80211R=y - CONFIG_IEEE80211AC=y - CONFIG_IEEE80211AX=y -+CONFIG_IEEE80211BE=y - - CONFIG_OCV=y - -@@ -103,6 +104,7 @@ CONFIG_TLSV12=y - CONFIG_HT_OVERRIDES=y - CONFIG_VHT_OVERRIDES=y - CONFIG_HE_OVERRIDES=y -+CONFIG_EHT_OVERRIDES=y - - CONFIG_DEBUG_LINUX_TRACING=y - -diff --git a/tests/hwsim/test_eht.py b/tests/hwsim/test_eht.py -new file mode 100644 -index 000000000000..70206bcf375a ---- /dev/null -+++ b/tests/hwsim/test_eht.py -@@ -0,0 +1,691 @@ -+# EHT tests -+# Copyright (c) 2019, The Linux Foundation -+# Copyright (c) 2022, Qualcomm Innovation Center, Inc -+# -+# This software may be distributed under the terms of the BSD license. -+# See README for more details. -+ -+import logging -+logger = logging.getLogger() -+import os -+import subprocess, time -+ -+import hwsim_utils -+import hostapd -+from wpasupplicant import WpaSupplicant -+from utils import * -+from test_dfs import wait_dfs_event -+ -+def test_eht_open(dev, apdev): -+ """EHT AP with open mode configuration""" -+ params = {"ssid": "eht", -+ "ieee80211ax": "1", -+ "ieee80211be": "1"} -+ hapd = hostapd.add_ap(apdev[0], params) -+ if hapd.get_status_field("ieee80211be") != "1": -+ raise Exception("STATUS did not indicate ieee80211be=1") -+ dev[0].connect("eht", key_mgmt="NONE", scan_freq="2412") -+ sta = hapd.get_sta(dev[0].own_addr()) -+ if "[EHT]" not in sta['flags']: -+ raise Exception("Missing STA flag: EHT") -+ -+def test_eht_disabled_on_sta(dev, apdev): -+ """EHT AP and EHT STA disabled on STA""" -+ params = {"ssid": "eht", -+ "ieee80211ax": "1", -+ "ieee80211be": "1"} -+ hapd = hostapd.add_ap(apdev[0], params) -+ dev[0].connect("eht", key_mgmt="NONE", scan_freq="2412", disable_eht="1") -+ sta = hapd.get_sta(dev[0].own_addr()) -+ if "[EHT]" in sta['flags']: -+ raise Exception("Unexpected STA flag: EHT") -+ -+def test_eht_params(dev, apdev): -+ """EHT AP parameters""" -+ params = {"ssid": "eht", -+ "ieee80211ax": "1", -+ "ieee80211be": "1", -+ "eht_su_beamformer": "0", -+ "eht_mu_beamformer": "0", -+ "eht_oper_chwidth": "0", -+ "eht_oper_centr_freq_seg0_idx": "1"} -+ hapd = hostapd.add_ap(apdev[0], params) -+ if hapd.get_status_field("ieee80211be") != "1": -+ raise Exception("STATUS did not indicate ieee80211be=1") -+ dev[0].connect("eht", key_mgmt="NONE", scan_freq="2412") -+ -+def eht_supported(): -+ cmd = subprocess.Popen(["iw", "reg", "get"], stdout=subprocess.PIPE) -+ reg = cmd.stdout.read().decode() -+ if "@ 80)" in reg or "@ 160)" in reg: -+ return True -+ return False -+ -+def test_eht80(dev, apdev): -+ """EHT with 80 MHz channel width""" -+ try: -+ hapd = None -+ params = {"ssid": "eht", -+ "country_code": "FI", -+ "hw_mode": "a", -+ "channel": "36", -+ "ht_capab": "[HT40+]", -+ "ieee80211n": "1", -+ "ieee80211ac": "1", -+ "ieee80211ax": "1", -+ "vht_oper_chwidth": "1", -+ "vht_capab": "[MAX-MPDU-11454]", -+ "vht_oper_centr_freq_seg0_idx": "42", -+ "he_oper_chwidth": "1", -+ "he_oper_centr_freq_seg0_idx": "42", -+ "ieee80211be": "1", -+ "eht_oper_chwidth": "1", -+ "eht_oper_centr_freq_seg0_idx": "42"} -+ hapd = hostapd.add_ap(apdev[0], params) -+ bssid = apdev[0]['bssid'] -+ -+ dev[0].connect("eht", key_mgmt="NONE", scan_freq="5180") -+ hwsim_utils.test_connectivity(dev[0], hapd) -+ sig = dev[0].request("SIGNAL_POLL").splitlines() -+ if "FREQUENCY=5180" not in sig: -+ raise Exception("Unexpected SIGNAL_POLL value(1): " + str(sig)) -+ if "WIDTH=80 MHz" not in sig: -+ raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig)) -+ est = dev[0].get_bss(bssid)['est_throughput'] -+ if est != "600502": -+ raise Exception("Unexpected BSS est_throughput: " + est) -+ status = dev[0].get_status() -+ if status["ieee80211ac"] != "1": -+ raise Exception("Unexpected STATUS ieee80211ac value (STA)") -+ status = hapd.get_status() -+ logger.info("hostapd STATUS: " + str(status)) -+ if status["ieee80211n"] != "1": -+ raise Exception("Unexpected STATUS ieee80211n value") -+ if status["ieee80211ac"] != "1": -+ raise Exception("Unexpected STATUS ieee80211ac value") -+ if status["ieee80211ax"] != "1": -+ raise Exception("Unexpected STATUS ieee80211ax value") -+ if status["secondary_channel"] != "1": -+ raise Exception("Unexpected STATUS secondary_channel value") -+ if status["vht_oper_chwidth"] != "1": -+ raise Exception("Unexpected STATUS vht_oper_chwidth value") -+ if status["vht_oper_centr_freq_seg0_idx"] != "42": -+ raise Exception("Unexpected STATUS vht_oper_centr_freq_seg0_idx value") -+ if "vht_caps_info" not in status: -+ raise Exception("Missing vht_caps_info") -+ if status["he_oper_chwidth"] != "1": -+ raise Exception("Unexpected STATUS he_oper_chwidth value") -+ if status["he_oper_centr_freq_seg0_idx"] != "42": -+ raise Exception("Unexpected STATUS he_oper_centr_freq_seg0_idx value") -+ if status["ieee80211be"] != "1": -+ raise Exception("Unexpected STATUS ieee80211be value") -+ if status["eht_oper_chwidth"] != "1": -+ raise Exception("Unexpected STATUS eht_oper_chwidth value") -+ if status["eht_oper_centr_freq_seg0_idx"] != "42": -+ raise Exception("Unexpected STATUS eht_oper_centr_freq_seg0_idx value") -+ -+ sta = hapd.get_sta(dev[0].own_addr()) -+ logger.info("hostapd STA: " + str(sta)) -+ if "[HT]" not in sta['flags']: -+ raise Exception("Missing STA flag: HT") -+ if "[VHT]" not in sta['flags']: -+ raise Exception("Missing STA flag: VHT") -+ if "[HE]" not in sta['flags']: -+ raise Exception("Missing STA flag: HE") -+ if "[EHT]" not in sta['flags']: -+ raise Exception("Missing STA flag: EHT") -+ -+ except Exception as e: -+ if isinstance(e, Exception) and str(e) == "AP startup failed": -+ if not eht_supported(): -+ raise HwsimSkip("80 MHz channel not supported in regulatory information") -+ raise -+ finally: -+ dev[0].request("DISCONNECT") -+ clear_regdom(hapd, dev) -+ -+def _test_eht_wifi_generation(dev, apdev, conf, scan_freq): -+ """EHT and wifi_generation""" -+ try: -+ hapd = None -+ params = {"ssid": "eht", -+ "country_code": "FI", -+ "ieee80211n": "1", -+ "ieee80211ax": "1", -+ "ieee80211be": "1"} -+ params.update(conf) -+ hapd = hostapd.add_ap(apdev[0], params) -+ bssid = apdev[0]['bssid'] -+ -+ dev[0].connect("eht", key_mgmt="NONE", scan_freq=scan_freq) -+ status = dev[0].get_status() -+ if 'wifi_generation' not in status: -+ # For now, assume this is because of missing kernel support -+ raise HwsimSkip("Association Request IE reporting not supported") -+ if status['wifi_generation'] != "7": -+ raise Exception("Unexpected wifi_generation value: " + status['wifi_generation']) -+ -+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') -+ wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") -+ wpas.connect("eht", key_mgmt="NONE", scan_freq=scan_freq) -+ status = wpas.get_status() -+ if 'wifi_generation' not in status: -+ # For now, assume this is because of missing kernel support -+ raise HwsimSkip("Association Request IE reporting not supported") -+ if status['wifi_generation'] != "7": -+ raise Exception("Unexpected wifi_generation value (connect): " + status['wifi_generation']) -+ except Exception as e: -+ if isinstance(e, Exception) and str(e) == "AP startup failed": -+ if not eht_supported(): -+ raise HwsimSkip("80 MHz channel not supported in regulatory information") -+ raise -+ finally: -+ dev[0].request("DISCONNECT") -+ clear_regdom(hapd, dev) -+ -+def test_eht_wifi_generation(dev, apdev): -+ conf = {"hw_mode": "a", -+ "channel": "36", -+ "ht_capab": "[HT40+]", -+ "ieee80211ac": "1", -+ "vht_capab": "[MAX-MPDU-11454]", -+ "vht_oper_chwidth": "1", -+ "vht_oper_centr_freq_seg0_idx": "42", -+ "he_oper_chwidth": "1", -+ "he_oper_centr_freq_seg0_idx": "42", -+ "eht_oper_chwidth": "1", -+ "eht_oper_centr_freq_seg0_idx": "42"} -+ -+ _test_eht_wifi_generation(dev, apdev, conf, "5180") -+ -+def test_eht_wifi_generation_24(dev, apdev): -+ conf = {"hw_mode": "g", -+ "channel": "1"} -+ _test_eht_wifi_generation(dev, apdev, conf, "2412") -+ -+def eht80_test(apdev, dev, channel, ht_capab): -+ clear_scan_cache(apdev) -+ try: -+ hapd = None -+ params = {"ssid": "eht", -+ "country_code": "FI", -+ "hw_mode": "a", -+ "channel": str(channel), -+ "ieee80211n": "1", -+ "ht_capab": ht_capab, -+ "ieee80211ac": "1", -+ "vht_capab": "[MAX-MPDU-11454]", -+ "vht_oper_chwidth": "1", -+ "vht_oper_centr_freq_seg0_idx": "42", -+ "ieee80211ax": "1", -+ "he_oper_chwidth": "1", -+ "he_oper_centr_freq_seg0_idx": "42", -+ "ieee80211be": "1", -+ "eht_oper_chwidth": "1", -+ "eht_oper_centr_freq_seg0_idx": "42"} -+ hapd = hostapd.add_ap(apdev, params) -+ bssid = apdev['bssid'] -+ -+ dev[0].connect("eht", key_mgmt="NONE", -+ scan_freq=str(5000 + 5 * channel)) -+ hwsim_utils.test_connectivity(dev[0], hapd) -+ except Exception as e: -+ if isinstance(e, Exception) and str(e) == "AP startup failed": -+ if not eht_supported(): -+ raise HwsimSkip("80 MHz channel not supported in regulatory information") -+ raise -+ finally: -+ clear_regdom(hapd, dev) -+ -+def test_eht80b(dev, apdev): -+ """EHT with 80 MHz channel width (HT40- channel 40)""" -+ eht80_test(apdev[0], dev, 40, "[HT40-]") -+ -+def test_eht80c(dev, apdev): -+ """EHT with 80 MHz channel width (HT40+ channel 44)""" -+ eht80_test(apdev[0], dev, 44, "[HT40+]") -+ -+def test_eht80d(dev, apdev): -+ """EHT with 80 MHz channel width (HT40- channel 48)""" -+ eht80_test(apdev[0], dev, 48, "[HT40-]") -+ -+def test_eht80_params(dev, apdev): -+ """EHT with 80 MHz channel width and number of optional features enabled""" -+ try: -+ hapd = None -+ params = {"ssid": "eht", -+ "country_code": "FI", -+ "hw_mode": "a", -+ "channel": "36", -+ "ieee80211n": "1", -+ "ht_capab": "[HT40+][SHORT-GI-40][DSS_CCK-40]", -+ "ieee80211ac": "1", -+ "vht_capab": "[MAX-MPDU-11454][RXLDPC][SHORT-GI-80][TX-STBC-2BY1][RX-STBC-1][MAX-A-MPDU-LEN-EXP0]", -+ "vht_oper_chwidth": "1", -+ "vht_oper_centr_freq_seg0_idx": "42", -+ "require_vht": "1", -+ "ieee80211ax": "1", -+ "he_oper_chwidth": "1", -+ "he_oper_centr_freq_seg0_idx": "42", -+ "ieee80211be": "1", -+ "eht_oper_chwidth": "1", -+ "eht_oper_centr_freq_seg0_idx": "42", -+ "eht_su_beamformer": "1", -+ "eht_mu_beamformer": "1"} -+ hapd = hostapd.add_ap(apdev[0], params) -+ -+ dev[1].connect("eht", key_mgmt="NONE", scan_freq="5180", -+ disable_vht="1", wait_connect=False) -+ dev[0].connect("eht", key_mgmt="NONE", scan_freq="5180") -+ dev[2].connect("eht", key_mgmt="NONE", scan_freq="5180", -+ disable_sgi="1") -+ ev = dev[1].wait_event(["CTRL-EVENT-ASSOC-REJECT"]) -+ if ev is None: -+ raise Exception("Association rejection timed out") -+ if "status_code=104" not in ev: -+ raise Exception("Unexpected rejection status code") -+ dev[1].request("DISCONNECT") -+ hwsim_utils.test_connectivity(dev[0], hapd) -+ sta0 = hapd.get_sta(dev[0].own_addr()) -+ sta2 = hapd.get_sta(dev[2].own_addr()) -+ capab0 = int(sta0['vht_caps_info'], base=16) -+ capab2 = int(sta2['vht_caps_info'], base=16) -+ if capab0 & 0x60 == 0: -+ raise Exception("dev[0] did not support SGI") -+ if capab2 & 0x60 != 0: -+ raise Exception("dev[2] claimed support for SGI") -+ except Exception as e: -+ if isinstance(e, Exception) and str(e) == "AP startup failed": -+ if not eht_supported(): -+ raise HwsimSkip("80 MHz channel not supported in regulatory information") -+ raise -+ finally: -+ clear_regdom(hapd, dev, count=3) -+ -+def test_eht80_invalid(dev, apdev): -+ """EHT with invalid 80 MHz channel configuration (seg1: 80+80 not supported)""" -+ try: -+ hapd = None -+ params = {"ssid": "eht", -+ "country_code": "US", -+ "hw_mode": "a", -+ "channel": "36", -+ "ieee80211n": "1", -+ "ht_capab": "[HT40+]", -+ "ieee80211ac": "1", -+ "vht_capab": "[MAX-MPDU-11454]", -+ "vht_oper_chwidth": "1", -+ "vht_oper_centr_freq_seg0_idx": "42", -+ "vht_oper_centr_freq_seg1_idx": "159", -+ "ieee80211ax": "1", -+ "he_oper_chwidth": "1", -+ "he_oper_centr_freq_seg0_idx": "42", -+ "he_oper_centr_freq_seg1_idx": "159", -+ "ieee80211be": "1", -+ "eht_oper_chwidth": "1", -+ "eht_oper_centr_freq_seg0_idx": "42", -+ "ieee80211d": "1", -+ "ieee80211h": "1"} -+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) -+ # This fails due to unexpected seg1 configuration -+ ev = hapd.wait_event(["AP-DISABLED"], timeout=5) -+ if ev is None: -+ raise Exception("AP-DISABLED not reported") -+ except Exception as e: -+ if isinstance(e, Exception) and str(e) == "AP startup failed": -+ if not eht_supported(): -+ raise HwsimSkip("80/160 MHz channel not supported in regulatory information") -+ raise -+ finally: -+ clear_regdom(hapd, dev) -+ -+def test_eht80_invalid2(dev, apdev): -+ """EHT with invalid 80 MHz channel configuration (seg0)""" -+ try: -+ hapd = None -+ params = {"ssid": "eht", -+ "country_code": "US", -+ "hw_mode": "a", -+ "channel": "36", -+ "ieee80211n": "1", -+ "ht_capab": "[HT40+]", -+ "ieee80211ac": "1", -+ "vht_oper_chwidth": "1", -+ "vht_oper_centr_freq_seg0_idx": "42", -+ "ieee80211ax": "1", -+ "he_oper_chwidth": "1", -+ "he_oper_centr_freq_seg0_idx": "42", -+ "ieee80211be": "1", -+ "eht_oper_chwidth": "1", -+ "eht_oper_centr_freq_seg0_idx": "46", -+ "ieee80211d": "1", -+ "ieee80211h": "1"} -+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) -+ # This fails due to invalid seg0 configuration -+ ev = hapd.wait_event(["AP-DISABLED"], timeout=5) -+ if ev is None: -+ raise Exception("AP-DISABLED not reported") -+ except Exception as e: -+ if isinstance(e, Exception) and str(e) == "AP startup failed": -+ if not eht_supported(): -+ raise HwsimSkip("80/160 MHz channel not supported in regulatory information") -+ raise -+ finally: -+ clear_regdom(hapd, dev) -+ -+def test_eht80_to_24g_eht(dev, apdev): -+ """EHT with 80 MHz channel width reconfigured to 2.4 GHz EHT""" -+ try: -+ params = {"ssid": "eht", -+ "country_code": "FI", -+ "hw_mode": "a", -+ "channel": "36", -+ "ieee80211n": "1", -+ "ht_capab": "[HT40+]", -+ "ieee80211ac": "1", -+ "vht_capab": "[MAX-MPDU-11454]", -+ "vht_oper_chwidth": "1", -+ "vht_oper_centr_freq_seg0_idx": "42", -+ "ieee80211ax": "1", -+ "he_oper_chwidth": "1", -+ "he_oper_centr_freq_seg0_idx": "42", -+ "ieee80211be": "1", -+ "eht_oper_chwidth": "1", -+ "eht_oper_centr_freq_seg0_idx": "42"} -+ hapd = hostapd.add_ap(apdev[0], params) -+ bssid = apdev[0]['bssid'] -+ -+ hapd.disable() -+ hapd.set("ieee80211ac", "0") -+ hapd.set("hw_mode", "g") -+ hapd.set("channel", "1") -+ hapd.set("ht_capab", "") -+ hapd.set("vht_capab", "") -+ hapd.set("vht_oper_chwidth", "") -+ hapd.set("vht_oper_centr_freq_seg0_idx", "") -+ hapd.set("he_oper_chwidth", "") -+ hapd.set("he_oper_centr_freq_seg0_idx", "") -+ hapd.set("eht_oper_chwidth", "") -+ hapd.set("eht_oper_centr_freq_seg0_idx", "") -+ hapd.enable() -+ -+ dev[0].connect("eht", key_mgmt="NONE", scan_freq="2412") -+ except Exception as e: -+ if isinstance(e, Exception) and str(e) == "AP startup failed": -+ if not eht_supported(): -+ raise HwsimSkip("80 MHz channel not supported in regulatory information") -+ raise -+ finally: -+ dev[0].request("DISCONNECT") -+ clear_regdom(hapd, dev) -+ -+def test_eht_20(devs, apdevs): -+ """EHT and 20 MHz channel""" -+ dev = devs[0] -+ ap = apdevs[0] -+ try: -+ hapd = None -+ params = {"ssid": "eht", -+ "country_code": "DE", -+ "hw_mode": "a", -+ "channel": "36", -+ "ieee80211n": "1", -+ "ht_capab": "", -+ "ieee80211ac": "1", -+ "vht_capab": "", -+ "vht_oper_chwidth": "0", -+ "vht_oper_centr_freq_seg0_idx": "0", -+ "supported_rates": "60 120 240 360 480 540", -+ "require_vht": "1", -+ "ieee80211ax": "1", -+ "he_oper_chwidth": "0", -+ "he_oper_centr_freq_seg0_idx": "0", -+ "ieee80211be": "1", -+ "eht_oper_chwidth": "0", -+ "eht_oper_centr_freq_seg0_idx": "0"} -+ -+ hapd = hostapd.add_ap(ap, params) -+ dev.connect("eht", scan_freq="5180", key_mgmt="NONE") -+ hwsim_utils.test_connectivity(dev, hapd) -+ finally: -+ dev.request("DISCONNECT") -+ clear_regdom(hapd, devs) -+ -+def test_eht_40(devs, apdevs): -+ """EHT and 40 MHz channel""" -+ dev = devs[0] -+ ap = apdevs[0] -+ try: -+ hapd = None -+ params = {"ssid": "eht", -+ "country_code": "DE", -+ "hw_mode": "a", -+ "channel": "36", -+ "ieee80211n": "1", -+ "ht_capab": "[HT40+]", -+ "ieee80211ac": "1", -+ "vht_capab": "", -+ "vht_oper_chwidth": "0", -+ "vht_oper_centr_freq_seg0_idx": "38", -+ "ieee80211ax": "1", -+ "he_oper_chwidth": "0", -+ "he_oper_centr_freq_seg0_idx": "38", -+ "ieee80211be": "1", -+ "eht_oper_chwidth": "0", -+ "eht_oper_centr_freq_seg0_idx": "38", -+ "eht_su_beamformer": "1", -+ "eht_mu_beamformer": "1"} -+ hapd = hostapd.add_ap(ap, params) -+ dev.connect("eht", scan_freq="5180", key_mgmt="NONE") -+ hwsim_utils.test_connectivity(dev, hapd) -+ finally: -+ dev.request("DISCONNECT") -+ clear_regdom(hapd, devs) -+ -+@long_duration_test -+def test_eht160(dev, apdev): -+ """EHT with 160 MHz channel width""" -+ try: -+ hapd = None -+ params = {"ssid": "eht", -+ "country_code": "FI", -+ "hw_mode": "a", -+ "channel": "36", -+ "ieee80211n": "1", -+ "ht_capab": "[HT40+]", -+ "ieee80211ac": "1", -+ "vht_capab": "[VHT160]", -+ "vht_oper_chwidth": "2", -+ "vht_oper_centr_freq_seg0_idx": "50", -+ "ieee80211ax": "1", -+ "he_oper_chwidth": "2", -+ "he_oper_centr_freq_seg0_idx": "50", -+ "ieee80211be": "1", -+ "eht_oper_chwidth": "2", -+ "eht_oper_centr_freq_seg0_idx": "50", -+ "ieee80211d": "1", -+ "ieee80211h": "1"} -+ -+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) -+ bssid = apdev[0]['bssid'] -+ -+ ev = wait_dfs_event(hapd, "DFS-CAC-START", 5) -+ if "DFS-CAC-START" not in ev: -+ raise Exception("Unexpected DFS event") -+ -+ state = hapd.get_status_field("state") -+ if state != "DFS": -+ if state == "DISABLED" and not os.path.exists("dfs"): -+ # Not all systems have recent enough CRDA version and -+ # wireless-regdb changes to support 160 MHz and DFS. For now, -+ # do not report failures for this test case. -+ raise HwsimSkip("CRDA or wireless-regdb did not support 160 MHz") -+ raise Exception("Unexpected interface state: " + state) -+ -+ logger.info("Waiting for CAC to complete") -+ -+ ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70) -+ if "success=1" not in ev: -+ raise Exception("CAC failed") -+ if "freq=5180" not in ev: -+ raise Exception("Unexpected DFS freq result") -+ -+ ev = hapd.wait_event(["AP-ENABLED"], timeout=5) -+ if not ev: -+ raise Exception("AP setup timed out") -+ -+ dev[0].connect("eht", key_mgmt="NONE", scan_freq="5180") -+ dev[0].wait_regdom(country_ie=True) -+ hwsim_utils.test_connectivity(dev[0], hapd) -+ sig = dev[0].request("SIGNAL_POLL").splitlines() -+ if "FREQUENCY=5180" not in sig: -+ raise Exception("Unexpected SIGNAL_POLL value(1): " + str(sig)) -+ if "WIDTH=160 MHz" not in sig: -+ raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig)) -+ est = dev[0].get_bss(bssid)['est_throughput'] -+ if est != "1201002": -+ raise Exception("Unexpected BSS est_throughput: " + est) -+ except Exception as e: -+ if isinstance(e, Exception) and str(e) == "AP startup failed": -+ if not eht_supported(): -+ raise HwsimSkip("80/160 MHz channel not supported in regulatory information") -+ raise -+ finally: -+ if hapd: -+ hapd.request("DISABLE") -+ dev[0].disconnect_and_stop_scan() -+ subprocess.call(['iw', 'reg', 'set', '00']) -+ dev[0].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=0.5) -+ dev[0].flush_scan_cache() -+ -+def test_eht_on_24ghz(dev, apdev): -+ """Subset of EHT features on 2.4 GHz""" -+ hapd = None -+ params = {"ssid": "eht", -+ "hw_mode": "g", -+ "channel": "1", -+ "ieee80211n": "1", -+ "vht_oper_chwidth": "0", -+ "vht_oper_centr_freq_seg0_idx": "1", -+ "ieee80211ax": "1", -+ "he_oper_chwidth": "0", -+ "he_oper_centr_freq_seg0_idx": "1", -+ "ieee80211be": "1", -+ "eht_oper_chwidth": "0", -+ "eht_oper_centr_freq_seg0_idx": "1"} -+ hapd = hostapd.add_ap(apdev[0], params) -+ try: -+ dev[0].connect("eht", scan_freq="2412", key_mgmt="NONE") -+ hwsim_utils.test_connectivity(dev[0], hapd) -+ sta = hapd.get_sta(dev[0].own_addr()) -+ -+ dev[1].connect("eht", scan_freq="2412", key_mgmt="NONE") -+ sta = hapd.get_sta(dev[1].own_addr()) -+ -+ finally: -+ dev[0].request("DISCONNECT") -+ dev[1].request("DISCONNECT") -+ if hapd: -+ hapd.request("DISABLE") -+ subprocess.call(['iw', 'reg', 'set', '00']) -+ dev[0].flush_scan_cache() -+ dev[1].flush_scan_cache() -+ -+def test_eht80_csa(dev, apdev): -+ """EHT with 80 MHz channel width and CSA""" -+ csa_supported(dev[0]) -+ try: -+ hapd = None -+ params = {"ssid": "eht", -+ "country_code": "US", -+ "hw_mode": "a", -+ "channel": "149", -+ "ieee80211n": "1", -+ "ht_capab": "[HT40+]", -+ "ieee80211ac": "1", -+ "vht_oper_chwidth": "1", -+ "vht_oper_centr_freq_seg0_idx": "155", -+ "ieee80211ax": "1", -+ "he_oper_chwidth": "1", -+ "he_oper_centr_freq_seg0_idx": "155", -+ "ieee80211be": "1", -+ "eht_oper_chwidth": "1", -+ "eht_oper_centr_freq_seg0_idx": "155"} -+ hapd = hostapd.add_ap(apdev[0], params) -+ -+ dev[0].connect("eht", key_mgmt="NONE", scan_freq="5745") -+ hwsim_utils.test_connectivity(dev[0], hapd) -+ -+ hapd.request("CHAN_SWITCH 5 5180 ht vht he eht blocktx center_freq1=5210 sec_channel_offset=1 bandwidth=80") -+ ev = hapd.wait_event(["CTRL-EVENT-STARTED-CHANNEL-SWITCH"], timeout=10) -+ if ev is None: -+ raise Exception("Channel switch start event not seen") -+ if "freq=5180" not in ev: -+ raise Exception("Unexpected channel in CS started") -+ ev = hapd.wait_event(["CTRL-EVENT-CHANNEL-SWITCH"], timeout=10) -+ if ev is None: -+ raise Exception("Channel switch completion event not seen") -+ if "freq=5180" not in ev: -+ raise Exception("Unexpected channel in CS completed") -+ ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10) -+ if ev is None: -+ raise Exception("CSA finished event timed out") -+ if "freq=5180" not in ev: -+ raise Exception("Unexpected channel in CSA finished event") -+ time.sleep(0.5) -+ hwsim_utils.test_connectivity(dev[0], hapd) -+ -+ hapd.request("CHAN_SWITCH 5 5745") -+ ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10) -+ if ev is None: -+ raise Exception("CSA finished event timed out") -+ if "freq=5745" not in ev: -+ raise Exception("Unexpected channel in CSA finished event") -+ time.sleep(0.5) -+ hwsim_utils.test_connectivity(dev[0], hapd) -+ -+ # This CSA to same channel will fail in kernel, so use this only for -+ # extra code coverage. -+ hapd.request("CHAN_SWITCH 5 5745") -+ hapd.wait_event(["AP-CSA-FINISHED"], timeout=1) -+ except Exception as e: -+ if isinstance(e, Exception) and str(e) == "AP startup failed": -+ if not eht_supported(): -+ raise HwsimSkip("80 MHz channel not supported in regulatory information") -+ raise -+ finally: -+ dev[0].request("DISCONNECT") -+ clear_regdom(hapd, dev) -+ -+def test_eht_use_sta_nsts(dev, apdev): -+ """EHT with 80 MHz channel width and use_sta_nsts=1""" -+ try: -+ hapd = None -+ params = {"ssid": "eht", -+ "country_code": "FI", -+ "hw_mode": "a", -+ "channel": "36", -+ "ieee80211n": "1", -+ "ht_capab": "[HT40+]", -+ "ieee80211ac": "1", -+ "vht_oper_chwidth": "1", -+ "vht_oper_centr_freq_seg0_idx": "42", -+ "ieee80211ax": "1", -+ "he_oper_chwidth": "1", -+ "he_oper_centr_freq_seg0_idx": "42", -+ "ieee80211be": "1", -+ "eht_oper_chwidth": "1", -+ "eht_oper_centr_freq_seg0_idx": "42", -+ "use_sta_nsts": "1"} -+ hapd = hostapd.add_ap(apdev[0], params) -+ bssid = apdev[0]['bssid'] -+ -+ dev[0].connect("eht", key_mgmt="NONE", scan_freq="5180") -+ hwsim_utils.test_connectivity(dev[0], hapd) -+ except Exception as e: -+ if isinstance(e, Exception) and str(e) == "AP startup failed": -+ if not eht_supported(): -+ raise HwsimSkip("80/160 MHz channel not supported in regulatory information") -+ raise -+ finally: -+ clear_regdom(hapd, dev) -diff --git a/tests/hwsim/wpasupplicant.py b/tests/hwsim/wpasupplicant.py -index 160aa3e2df88..2aacbe046ecb 100644 ---- a/tests/hwsim/wpasupplicant.py -+++ b/tests/hwsim/wpasupplicant.py -@@ -1092,7 +1092,7 @@ class WpaSupplicant: - "wep_tx_keyidx", "scan_freq", "freq_list", "eap", - "eapol_flags", "fragment_size", "scan_ssid", "auth_alg", - "wpa_ptk_rekey", "disable_ht", "disable_vht", "bssid", -- "disable_he", -+ "disable_he", "disable_eht", - "disable_max_amsdu", "ampdu_factor", "ampdu_density", - "disable_ht40", "disable_sgi", "disable_ldpc", - "ht40_intolerant", "update_identifier", "mac_addr", --- -2.7.4 - diff --git a/feeds/ipq95xx/hostapd/patches/q01-002-mbssid-retrieve-driver-capabilities.patch b/feeds/ipq95xx/hostapd/patches/q01-002-mbssid-retrieve-driver-capabilities.patch deleted file mode 100644 index 799bc83ff..000000000 --- a/feeds/ipq95xx/hostapd/patches/q01-002-mbssid-retrieve-driver-capabilities.patch +++ /dev/null @@ -1,56 +0,0 @@ -From c35d82bffc9f5fe96d78b3817f20201c57a2248c Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Wed, 22 Sep 2021 17:00:05 -0700 -Subject: [PATCH 02/15] mbssid: retrieve driver capabilities - -Retrieve driver capabilities for maximum number of interfaces for -MBSSID and maximum allowed profile periodicity for enhanced MBSSID -advertisements. - -Signed-off-by: Aloka Dixit ---- - hostapd/main.c | 3 +++ - src/ap/hostapd.h | 5 +++++ - src/drivers/driver.h | 5 +++++ - 3 files changed, 13 insertions(+) - ---- a/hostapd/main.c -+++ b/hostapd/main.c -@@ -253,6 +253,9 @@ static int hostapd_driver_init(struct ho - wpa_printf(MSG_ERROR, "set_wowlan failed"); - } - os_free(triggs); -+ -+ iface->mbssid_max_interfaces = capa.mbssid_max_interfaces; -+ iface->ema_max_periodicity = capa.ema_max_periodicity; - } - - return 0; ---- a/src/ap/hostapd.h -+++ b/src/ap/hostapd.h -@@ -612,6 +612,11 @@ struct hostapd_iface { - /* Previous WMM element information */ - struct hostapd_wmm_ac_params prev_wmm[WMM_AC_NUM]; - -+ /* Maximum number of interfaces supported for MBSSID advertisements */ -+ u8 mbssid_max_interfaces; -+ /* Maximum profile periodicity for enhanced MBSSID advertisements */ -+ u8 ema_max_periodicity; -+ - int (*enable_iface_cb)(struct hostapd_iface *iface); - int (*disable_iface_cb)(struct hostapd_iface *iface); - }; ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -2185,6 +2185,11 @@ struct wpa_driver_capa { - - /* Maximum number of supported CSA counters */ - u16 max_csa_counters; -+ -+ /* Maximum number of interfaces supported for MBSSID advertisements */ -+ u8 mbssid_max_interfaces; -+ /* Maximum profile periodicity for enhanced MBSSID advertisements */ -+ u8 ema_max_periodicity; - }; - - diff --git a/feeds/ipq95xx/hostapd/patches/q01-003-mbssid-configure-all-BSSes-before-beacon-setup.patch b/feeds/ipq95xx/hostapd/patches/q01-003-mbssid-configure-all-BSSes-before-beacon-setup.patch deleted file mode 100644 index 36becfd68..000000000 --- a/feeds/ipq95xx/hostapd/patches/q01-003-mbssid-configure-all-BSSes-before-beacon-setup.patch +++ /dev/null @@ -1,140 +0,0 @@ -From 278ab7c6660beeb657a088736bc28fbb63ee296d Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Fri, 10 Sep 2021 15:02:05 -0700 -Subject: [PATCH 03/15] mbssid: configure all BSSes before beacon setup - -With existing design, the transmitted beacon is set before RSN -information element is formed for any nontransmitted profile hence the -beacon has these profiles with open encryption. -It also sets wrong DTIM period, profile periodicity values until all -non-transmitting BSSes are up. - -Retrieve configurations for all nontransmitted profiles before setting -the beacon to ensures that beacons reflect correct information. - -Signed-off-by: Aloka Dixit ---- - src/ap/hostapd.c | 93 +++++++++++++++++++++++++++++++++--------------- - 1 file changed, 65 insertions(+), 28 deletions(-) - -Index: hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/ap/hostapd.c -+++ hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.c -@@ -1131,6 +1131,47 @@ static int db_table_create_radius_attrib - - #endif /* CONFIG_NO_RADIUS */ - -+static int hostapd_set_beacon(struct hostapd_data *hapd) -+{ -+ struct hostapd_bss_config *conf = hapd->conf; -+ int flush_old_stations = 1; -+ -+#ifdef CONFIG_MESH -+ if ((hapd->conf->mesh & MESH_ENABLED) && hapd->iface->mconf == NULL) -+ flush_old_stations = 0; -+#endif /* CONFIG_MESH */ -+ -+ if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0) -+ return -1; -+ -+ if (flush_old_stations && !conf->start_disabled && -+ conf->broadcast_deauth) { -+ u8 addr[ETH_ALEN]; -+ -+ /* Should any previously associated STA not have noticed that -+ * the AP had stopped and restarted, send one more -+ * deauthentication notification now that the AP is ready to -+ * operate. -+ */ -+ wpa_dbg(hapd->msg_ctx, MSG_DEBUG, -+ "Deauthenticate all stations at BSS start"); -+ os_memset(addr, 0xff, ETH_ALEN); -+ hostapd_drv_sta_deauth(hapd, addr, -+ WLAN_REASON_PREV_AUTH_NOT_VALID); -+ } -+ -+ if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0) -+ return -1; -+ -+ if (hapd->driver && hapd->driver->set_operstate) -+ hapd->driver->set_operstate(hapd->drv_priv, 1); -+ -+ hostapd_ubus_add_bss(hapd); -+ hostapd_ucode_add_bss(hapd); -+ -+ return 0; -+} -+ - - /** - * hostapd_setup_bss - Per-BSS setup (initialization) -@@ -1432,32 +1473,8 @@ int hostapd_setup_bss(struct hostapd_dat - return -1; - } - -- if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0) -- return -1; -- -- if (flush_old_stations && !conf->start_disabled && -- conf->broadcast_deauth) { -- u8 addr[ETH_ALEN]; -- -- /* Should any previously associated STA not have noticed that -- * the AP had stopped and restarted, send one more -- * deauthentication notification now that the AP is ready to -- * operate. */ -- wpa_dbg(hapd->msg_ctx, MSG_DEBUG, -- "Deauthenticate all stations at BSS start"); -- os_memset(addr, 0xff, ETH_ALEN); -- hostapd_drv_sta_deauth(hapd, addr, -- WLAN_REASON_PREV_AUTH_NOT_VALID); -- } -- -- if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0) -- return -1; -- -- if (hapd->driver && hapd->driver->set_operstate) -- hapd->driver->set_operstate(hapd->drv_priv, 1); -- -- hostapd_ubus_add_bss(hapd); -- hostapd_ucode_add_bss(hapd); -+ if (set_beacon) -+ return hostapd_set_beacon(hapd); - - return 0; - } -@@ -2169,7 +2186,7 @@ static int hostapd_setup_interface_compl - hapd = iface->bss[j]; - if (j) - os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN); -- if (hostapd_setup_bss(hapd, j == 0, true)) { -+ if (hostapd_setup_bss(hapd, j == 0, (hapd->iconf->mbssid? 0 : 1))) { - for (;;) { - hapd = iface->bss[j]; - hostapd_bss_deinit_no_free(hapd); -@@ -2183,6 +2200,24 @@ static int hostapd_setup_interface_compl - if (is_zero_ether_addr(hapd->conf->bssid)) - prev_addr = hapd->own_addr; - } -+ -+ if (hapd->iconf->mbssid) { -+ for (j = 0; j < iface->num_bss; j++) { -+ hapd = iface->bss[j]; -+ if (hostapd_set_beacon(hapd)) { -+ for (;;) { -+ hapd = iface->bss[j]; -+ hostapd_bss_deinit_no_free(hapd); -+ hostapd_free_hapd_data(hapd); -+ if (j == 0) -+ break; -+ j--; -+ } -+ goto fail; -+ } -+ } -+ } -+ - hapd = iface->bss[0]; - - hostapd_tx_queue_params(iface); diff --git a/feeds/ipq95xx/hostapd/patches/q01-004-mbssid-get-and-set-configuration-parameters.patch b/feeds/ipq95xx/hostapd/patches/q01-004-mbssid-get-and-set-configuration-parameters.patch deleted file mode 100644 index 0bb77db92..000000000 --- a/feeds/ipq95xx/hostapd/patches/q01-004-mbssid-get-and-set-configuration-parameters.patch +++ /dev/null @@ -1,161 +0,0 @@ -From b5ab26896c423a8bf7761552018ce5e399dc6b6b Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Fri, 10 Sep 2021 14:48:07 -0700 -Subject: [PATCH 04/15] mbssid: get and set configuration parameters - -Add helper functions to retrieve the context for the transmitting -interfaces of the MBSSID set and the index of a given BSS. - -Set device parameters - BSS index, transmitting BSS and -total number of BSS in the MBSSID set. - -Signed-off-by: John Crispin -Signed-off-by: Aloka Dixit ---- - src/ap/beacon.c | 36 ++++++++++++++++++++++++++++++++++-- - src/ap/hostapd.c | 23 +++++++++++++++++++++++ - src/ap/hostapd.h | 2 ++ - src/drivers/driver.h | 15 +++++++++++++++ - 4 files changed, 74 insertions(+), 2 deletions(-) - ---- a/src/ap/beacon.c -+++ b/src/ap/beacon.c -@@ -459,6 +459,33 @@ static u8 * hostapd_eid_supported_op_cla - } - - -+static int hostapd_set_mbssid_beacon(struct hostapd_data *hapd, -+ struct wpa_driver_ap_params *params) -+{ -+ struct hostapd_iface *iface = hapd->iface; -+ -+ if (!iface->conf->mbssid || iface->num_bss == 1) -+ return 0; -+ -+ if (!iface->mbssid_max_interfaces) { -+ wpa_printf(MSG_ERROR, "MBSSID: Driver doesn't support " -+ "multi-BSSID advertisements"); -+ return -1; -+ } else if (iface->num_bss > iface->mbssid_max_interfaces) { -+ wpa_printf(MSG_ERROR, "MBSSID: Driver supports maximum %u " -+ "interfaces for multi-BSSID advertisements", -+ iface->mbssid_max_interfaces); -+ return -1; -+ } -+ -+ params->mbssid_tx_iface = hostapd_mbssid_get_tx_bss(hapd)->conf->iface; -+ params->mbssid_index = hostapd_mbssid_get_bss_index(hapd); -+ params->mbssid_count = iface->num_bss; -+ -+ return 0; -+} -+ -+ - static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, - const struct ieee80211_mgmt *req, - int is_p2p, size_t *resp_len) -@@ -1203,7 +1230,6 @@ static u8 * hostapd_probe_resp_offloads( - /* Generate a Probe Response template for the non-P2P case */ - return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len); - } -- - #endif /* NEED_AP_MLME */ - - -@@ -1498,7 +1524,11 @@ int ieee802_11_build_ap_params(struct ho - #ifdef NEED_AP_MLME - u16 capab_info; - u8 *pos, *tailpos, *tailend, *csa_pos; -+#endif /* NEED_AP_MLME */ -+ -+ os_memset(params, 0, sizeof(*params)); - -+#ifdef NEED_AP_MLME - #define BEACON_HEAD_BUF_SIZE 256 - #define BEACON_TAIL_BUF_SIZE 512 - head = os_zalloc(BEACON_HEAD_BUF_SIZE); -@@ -1632,6 +1662,9 @@ int ieee802_11_build_ap_params(struct ho - tailpos = hostapd_eid_ht_capabilities(hapd, tailpos); - tailpos = hostapd_eid_ht_operation(hapd, tailpos); - -+ if (hostapd_set_mbssid_beacon(hapd, params)) -+ return -1; -+ - tailpos = hostapd_eid_ext_capab(hapd, tailpos); - - /* -@@ -1743,7 +1776,6 @@ int ieee802_11_build_ap_params(struct ho - resp = hostapd_probe_resp_offloads(hapd, &resp_len); - #endif /* NEED_AP_MLME */ - -- os_memset(params, 0, sizeof(*params)); - params->head = (u8 *) head; - params->head_len = head_len; - params->tail = tail; ---- a/src/ap/hostapd.c -+++ b/src/ap/hostapd.c -@@ -89,6 +89,29 @@ int hostapd_for_each_interface(struct ha - } - - -+struct hostapd_data * hostapd_mbssid_get_tx_bss(struct hostapd_data *hapd) -+{ -+ if (hapd->iconf->mbssid) -+ return hapd->iface->bss[0]; -+ -+ return hapd; -+} -+ -+ -+int hostapd_mbssid_get_bss_index(struct hostapd_data *hapd) -+{ -+ if (hapd->iconf->mbssid) { -+ size_t i; -+ -+ for (i = 1; i < hapd->iface->num_bss; i++) -+ if (hapd->iface->bss[i] == hapd) -+ return i; -+ } -+ -+ return 0; -+} -+ -+ - void hostapd_reconfig_encryption(struct hostapd_data *hapd) - { - if (hapd->wpa_auth) ---- a/src/ap/hostapd.h -+++ b/src/ap/hostapd.h -@@ -714,6 +714,8 @@ struct hostapd_data * hostapd_get_iface( - void hostapd_event_sta_opmode_changed(struct hostapd_data *hapd, const u8 *addr, - enum smps_mode smps_mode, - enum chan_width chan_width, u8 rx_nss); -+struct hostapd_data * hostapd_mbssid_get_tx_bss(struct hostapd_data *hapd); -+int hostapd_mbssid_get_bss_index(struct hostapd_data *hapd); - - #ifdef CONFIG_FST - void fst_hostapd_fill_iface_obj(struct hostapd_data *hapd, ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -1627,6 +1627,21 @@ struct wpa_driver_ap_params { - * 2 = BURST beacon tx mode - */ - int beacon_tx_mode; -+ -+ /** -+ * mbssid_tx_iface - Transmitting interface of the set -+ */ -+ const char *mbssid_tx_iface; -+ -+ /** -+ * mbssid_index - The index of this BSS in the group -+ */ -+ unsigned int mbssid_index; -+ -+ /** -+ * mbssid_count - Total number of BSSs in the group -+ */ -+ unsigned int mbssid_count; - }; - - struct wpa_driver_mesh_bss_params { diff --git a/feeds/ipq95xx/hostapd/patches/q01-005-mbssid-add-multiple-BSSID-elements.patch b/feeds/ipq95xx/hostapd/patches/q01-005-mbssid-add-multiple-BSSID-elements.patch deleted file mode 100644 index 575f6cb5e..000000000 --- a/feeds/ipq95xx/hostapd/patches/q01-005-mbssid-add-multiple-BSSID-elements.patch +++ /dev/null @@ -1,450 +0,0 @@ -From 78dcbdbbf8a5ab304b72b7c967f6618642d4f78e Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Fri, 10 Sep 2021 14:56:37 -0700 -Subject: [PATCH 05/15] mbssid: add multiple BSSID elements - -Add data as per IEEE Std 802.11-2020 9.4.2.45 Multiple BSSID element. -Include this element in beacons and probe response frames when mbssid -is enabled. Split the BSSes into multiple elements if the data -does not fit in 255 bytes allowed for a single element. - -Add support for enhanced multiple BSSID advertisements (EMA) by -sending offsets to the start of each MBSSID element to nl80211. -Mac80211 generates different EMA beacons by including only one -multiple BSSID element in each beacon frame. - -Signed-off-by: John Crispin -Signed-off-by: Aloka Dixit ---- - src/ap/beacon.c | 67 ++++++++++- - src/ap/ieee802_11.c | 212 +++++++++++++++++++++++++++++++++++ - src/ap/ieee802_11.h | 5 +- - src/common/ieee802_11_defs.h | 2 + - src/drivers/driver.h | 27 +++++ - 5 files changed, 309 insertions(+), 4 deletions(-) - ---- a/src/ap/beacon.c -+++ b/src/ap/beacon.c -@@ -463,6 +463,9 @@ static int hostapd_set_mbssid_beacon(str - struct wpa_driver_ap_params *params) - { - struct hostapd_iface *iface = hapd->iface; -+ struct hostapd_data *tx_bss; -+ size_t len; -+ u8 num_mbssid = 0, *end; - - if (!iface->conf->mbssid || iface->num_bss == 1) - return 0; -@@ -478,10 +481,55 @@ static int hostapd_set_mbssid_beacon(str - return -1; - } - -- params->mbssid_tx_iface = hostapd_mbssid_get_tx_bss(hapd)->conf->iface; -+ tx_bss = hostapd_mbssid_get_tx_bss(hapd); -+ params->mbssid_tx_iface = tx_bss->conf->iface; - params->mbssid_index = hostapd_mbssid_get_bss_index(hapd); - params->mbssid_count = iface->num_bss; - -+ len = hostapd_eid_mbssid_len(tx_bss, WLAN_FC_STYPE_BEACON, &num_mbssid); -+ if (hapd->iconf->ema) { -+ if (!iface->ema_max_periodicity) { -+ wpa_printf(MSG_WARNING, "MBSSID: Driver doesn't support" -+ " enhanced multiple BSSID advertisements"); -+ return -1; -+ } -+ if (num_mbssid > iface->ema_max_periodicity) { -+ wpa_printf(MSG_WARNING, "MBSSID: Driver supports " -+ "maximum %u EMA profile periodicity", -+ iface->ema_max_periodicity); -+ return -1; -+ } -+ params->ema = 1; -+ } -+ -+ if (hapd != tx_bss || !num_mbssid) -+ return 0; -+ -+ params->mbssid_elem_count = num_mbssid; -+ params->mbssid_elem = os_zalloc(len); -+ if (!params->mbssid_elem) { -+ wpa_printf(MSG_ERROR, "Memory allocation failed for multiple " -+ "BSSID elements"); -+ return -1; -+ } -+ -+ params->mbssid_elem_offset = os_zalloc(params->mbssid_elem_count * -+ sizeof(u8 *)); -+ if (!params->mbssid_elem_offset) { -+ wpa_printf(MSG_ERROR, "MBSSID: Memory allocation failed for " -+ "multiple BSSID element offsets"); -+ os_free(params->mbssid_elem); -+ params->mbssid_elem = NULL; -+ return -1; -+ } -+ -+ end = hostapd_eid_mbssid(tx_bss, params->mbssid_elem, -+ params->mbssid_elem + len, -+ WLAN_FC_STYPE_BEACON, -+ params->mbssid_elem_count, -+ params->mbssid_elem_offset); -+ params->mbssid_elem_len = end - params->mbssid_elem; -+ - return 0; - } - -@@ -494,8 +542,11 @@ static u8 * hostapd_gen_probe_resp(struc - u8 *pos, *epos, *csa_pos; - size_t buflen; - -+ hapd = hostapd_mbssid_get_tx_bss(hapd); -+ - #define MAX_PROBERESP_LEN 768 - buflen = MAX_PROBERESP_LEN; -+ - #ifdef CONFIG_WPS - if (hapd->wps_probe_resp_ie) - buflen += wpabuf_len(hapd->wps_probe_resp_ie); -@@ -532,6 +583,7 @@ static u8 * hostapd_gen_probe_resp(struc - } - #endif /* CONFIG_IEEE80211AX */ - -+ buflen += hostapd_eid_mbssid_len(hapd, WLAN_FC_STYPE_PROBE_RESP, NULL); - buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP); - buflen += hostapd_mbo_ie_len(hapd); - buflen += hostapd_eid_owe_trans_len(hapd); -@@ -600,6 +652,8 @@ static u8 * hostapd_gen_probe_resp(struc - pos = hostapd_eid_supported_op_classes(hapd, pos); - pos = hostapd_eid_ht_capabilities(hapd, pos); - pos = hostapd_eid_ht_operation(hapd, pos); -+ pos = hostapd_eid_mbssid(hapd, pos, epos, WLAN_FC_STYPE_PROBE_RESP, 0, -+ NULL); - - pos = hostapd_eid_ext_capab(hapd, pos); - -@@ -1155,6 +1209,9 @@ void handle_probe_req(struct hostapd_dat - } - #endif /* CONFIG_TESTING_OPTIONS */ - -+ if (hapd != hostapd_mbssid_get_tx_bss(hapd) && res != EXACT_SSID_MATCH) -+ return; -+ - wpa_msg_ctrl(hapd->msg_ctx, MSG_INFO, RX_PROBE_REQUEST "sa=" MACSTR - " signal=%d", MAC2STR(mgmt->sa), ssi_signal); - -@@ -1181,7 +1238,8 @@ void handle_probe_req(struct hostapd_dat - hapd->cs_c_off_ecsa_proberesp; - } - -- ret = hostapd_drv_send_mlme(hapd, resp, resp_len, noack, -+ ret = hostapd_drv_send_mlme(hostapd_mbssid_get_tx_bss(hapd), resp, -+ resp_len, noack, - csa_offs_len ? csa_offs : NULL, - csa_offs_len, 0); - -@@ -1661,7 +1719,6 @@ int ieee802_11_build_ap_params(struct ho - tailpos = hostapd_eid_supported_op_classes(hapd, tailpos); - tailpos = hostapd_eid_ht_capabilities(hapd, tailpos); - tailpos = hostapd_eid_ht_operation(hapd, tailpos); -- - if (hostapd_set_mbssid_beacon(hapd, params)) - return -1; - -@@ -1880,6 +1937,10 @@ void ieee802_11_free_ap_params(struct wp - params->head = NULL; - os_free(params->proberesp); - params->proberesp = NULL; -+ os_free(params->mbssid_elem); -+ params->mbssid_elem = NULL; -+ os_free(params->mbssid_elem_offset); -+ params->mbssid_elem_offset = NULL; - #ifdef CONFIG_FILS - os_free(params->fd_frame_tmpl); - params->fd_frame_tmpl = NULL; ---- a/src/ap/ieee802_11.c -+++ b/src/ap/ieee802_11.c -@@ -3974,6 +3974,23 @@ static void handle_auth(struct hostapd_d - } - - -+u8 hostapd_max_bssid_indicator(struct hostapd_data *hapd) -+{ -+ size_t num_bss_nontx; -+ u8 max_bssid_ind = 0; -+ -+ if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1) -+ return 0; -+ -+ num_bss_nontx = hapd->iface->num_bss - 1; -+ while (num_bss_nontx > 0) { -+ max_bssid_ind++; -+ num_bss_nontx >>= 1; -+ } -+ return max_bssid_ind; -+} -+ -+ - int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta) - { - int i, j = 32, aid; -@@ -7667,4 +7684,199 @@ u8 * hostapd_eid_rnr(struct hostapd_data - return eid; - } - -+ -+static size_t hostapd_eid_mbssid_elem_len(struct hostapd_data *hapd, -+ u32 frame_type, size_t *bss_index) -+{ -+ size_t len = 3, i; -+ -+ for (i = *bss_index; i < hapd->iface->num_bss; i++) { -+ struct hostapd_data *bss = hapd->iface->bss[i]; -+ const u8 *auth, *rsn, *rsnx; -+ size_t nontx_profile_len, auth_len; -+ -+ if (!bss || !bss->conf || !bss->started) -+ continue; -+ -+ /* -+ * Sublement ID: 1 byte -+ * Length: 1 byte -+ * Nontransmitted capabilities: 4 bytes -+ * SSID element: 2 + variable -+ * Multiple BSSID Index Element: 3 bytes (+2 bytes in beacons) -+ * Fixed length = 1 + 1 + 4 + 2 + 3 = 11 -+ */ -+ nontx_profile_len = 11 + bss->conf->ssid.ssid_len; -+ -+ if (frame_type == WLAN_FC_STYPE_BEACON) -+ nontx_profile_len += 2; -+ -+ auth = wpa_auth_get_wpa_ie(bss->wpa_auth, &auth_len); -+ if (auth) { -+ rsn = get_ie(auth, auth_len, WLAN_EID_RSN); -+ if (rsn) -+ nontx_profile_len += (2 + rsn[1]); -+ -+ rsnx = get_ie(auth, auth_len, WLAN_EID_RSNX); -+ if (rsnx) -+ nontx_profile_len += (2 + rsnx[1]); -+ } -+ -+ if ((len + nontx_profile_len) > 255) -+ goto mbssid_too_big; -+ -+ len += nontx_profile_len; -+ } -+ -+mbssid_too_big: -+ *bss_index = i; -+ return len; -+} -+ -+ -+size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type, -+ u8 *elem_count) -+{ -+ size_t len = 0, bss_index = 1; -+ -+ if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 || -+ (frame_type != WLAN_FC_STYPE_BEACON && -+ frame_type != WLAN_FC_STYPE_PROBE_RESP)) -+ return 0; -+ -+ if (frame_type == WLAN_FC_STYPE_BEACON) { -+ if (!elem_count) { -+ wpa_printf(MSG_ERROR, "MBSSID: Insufficient data for " -+ "beacons"); -+ return 0; -+ } -+ *elem_count = 0; -+ } -+ -+ while (bss_index < hapd->iface->num_bss) { -+ len += hostapd_eid_mbssid_elem_len(hapd, frame_type, -+ &bss_index); -+ -+ if (frame_type == WLAN_FC_STYPE_BEACON) -+ *elem_count += 1; -+ } -+ return len; -+} -+ -+ -+static u8 * hostapd_eid_mbssid_elem(struct hostapd_data *hapd, u8 *eid, u8 *end, -+ u32 frame_type, u8 max_bssid_indicator, -+ size_t *bss_index) -+{ -+ size_t i; -+ u8 *eid_len_offset, *max_bssid_indicator_offset; -+ -+ *eid++ = WLAN_EID_MULTIPLE_BSSID; -+ eid_len_offset = eid++; -+ max_bssid_indicator_offset = eid++; -+ -+ for (i = *bss_index; i < hapd->iface->num_bss; i++) { -+ struct hostapd_data *bss = hapd->iface->bss[i]; -+ struct hostapd_bss_config *conf; -+ u8 *eid_len_pos, *nontx_bss_start = eid; -+ const u8 *auth, *rsn, *rsnx; -+ size_t auth_len = 0; -+ u16 capab_info; -+ -+ if (!bss || !bss->conf || !bss->started) -+ continue; -+ conf = bss->conf; -+ -+ *eid++ = WLAN_EID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE; -+ eid_len_pos = eid++; -+ -+ *eid++ = WLAN_EID_NONTRANSMITTED_BSSID_CAPA; -+ *eid++ = sizeof(capab_info); -+ capab_info = host_to_le16(hostapd_own_capab_info(bss)); -+ os_memcpy(eid, (const void *)&capab_info, sizeof(capab_info)); -+ eid += sizeof(capab_info); -+ -+ *eid++ = WLAN_EID_SSID; -+ *eid++ = conf->ssid.ssid_len; -+ os_memcpy(eid, conf->ssid.ssid, conf->ssid.ssid_len); -+ eid += conf->ssid.ssid_len; -+ -+ *eid++ = WLAN_EID_MULTIPLE_BSSID_INDEX; -+ if (frame_type == WLAN_FC_STYPE_BEACON) { -+ *eid++ = 3; -+ *eid++ = i; -+ *eid++ = conf->dtim_period; -+ *eid++ = 0xFF; -+ } else { -+ *eid++ = 1; -+ *eid++ = i; -+ } -+ -+ auth = wpa_auth_get_wpa_ie(bss->wpa_auth, &auth_len); -+ if (auth) { -+ rsn = get_ie(auth, auth_len, WLAN_EID_RSN); -+ if (rsn) { -+ os_memcpy(eid, rsn, 2 + rsn[1]); -+ eid += (2 + rsn[1]); -+ } -+ -+ rsnx = get_ie(auth, auth_len, WLAN_EID_RSNX); -+ if (rsnx) { -+ os_memcpy(eid, rsnx, 2 + rsnx[1]); -+ eid += (2 + rsnx[1]); -+ } -+ } -+ -+ *eid_len_pos = (eid - eid_len_pos) - 1; -+ -+ if (((eid - eid_len_offset) - 1) > 255) { -+ eid = nontx_bss_start; -+ goto mbssid_too_big; -+ } -+ } -+ -+mbssid_too_big: -+ *bss_index = i; -+ *max_bssid_indicator_offset = max_bssid_indicator; -+ if (*max_bssid_indicator_offset < 1) -+ *max_bssid_indicator_offset = 1; -+ *eid_len_offset = (eid - eid_len_offset) - 1; -+ return eid; -+} -+ -+ -+u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end, -+ u32 frame_type, u8 elem_count, u8 **elem_offset) -+{ -+ size_t bss_index = 1; -+ u8 elem_index = 0; -+ -+ if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 || -+ (frame_type != WLAN_FC_STYPE_BEACON && -+ frame_type != WLAN_FC_STYPE_PROBE_RESP)) -+ return eid; -+ -+ if (frame_type == WLAN_FC_STYPE_BEACON && !elem_offset) { -+ wpa_printf(MSG_ERROR, "MBSSID: Insufficient data for beacons"); -+ return eid; -+ } -+ -+ while (bss_index < hapd->iface->num_bss) { -+ if (frame_type == WLAN_FC_STYPE_BEACON) { -+ if (elem_index == elem_count) { -+ wpa_printf(MSG_WARNING, "MBSSID: More number of" -+ " elements than provided array"); -+ break; -+ } -+ -+ elem_offset[elem_index] = eid; -+ elem_index = elem_index + 1; -+ } -+ eid = hostapd_eid_mbssid_elem(hapd, eid, end, frame_type, -+ hostapd_max_bssid_indicator(hapd), -+ &bss_index); -+ } -+ return eid; -+} -+ - #endif /* CONFIG_NATIVE_WINDOWS */ ---- a/src/ap/ieee802_11.h -+++ b/src/ap/ieee802_11.h -@@ -129,8 +129,11 @@ u8 * hostapd_eid_time_zone(struct hostap - int hostapd_update_time_adv(struct hostapd_data *hapd); - void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr); - u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid); -- - int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta); -+size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type, -+ u8 *elem_count); -+u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end, -+ u32 frame_type, u8 elem_count, u8 **elem_offset); - #ifdef CONFIG_SAE - void sae_clear_retransmit_timer(struct hostapd_data *hapd, - struct sta_info *sta); ---- a/src/common/ieee802_11_defs.h -+++ b/src/common/ieee802_11_defs.h -@@ -491,6 +491,8 @@ - #define WLAN_EID_EXT_ANTI_CLOGGING_TOKEN 93 - #define WLAN_EID_EXT_PASN_PARAMS 100 - -+#define WLAN_EID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE 0 -+ - /* Operating Triplet can be any integer >= 201 - * From IEEE P802.11-REVmd/D4.0: The first octet in each Subband - * Triplet field or Operating Triplet field contains an unsigned ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -1642,6 +1642,33 @@ struct wpa_driver_ap_params { - * mbssid_count - Total number of BSSs in the group - */ - unsigned int mbssid_count; -+ -+ /** -+ * mbssid_elem - Buffer containing all multiple BSSID elements -+ */ -+ u8 *mbssid_elem; -+ -+ /** -+ * mbssid_elem_len - Total length of all multiple BSSID elements -+ */ -+ size_t mbssid_elem_len; -+ -+ /** -+ * mbssid_elem_count - The number of multiple bssid elements -+ */ -+ u8 mbssid_elem_count; -+ -+ /** -+ * mbssid_elem_offset - Offsets to elements in mbssid_elem. -+ * Kernel will use these offsets to generate multiple BSSID beacons. -+ */ -+ u8 **mbssid_elem_offset; -+ -+ /** -+ * ema - Enhanced multi-bssid advertisements support. -+ */ -+ u8 ema; -+ - }; - - struct wpa_driver_mesh_bss_params { diff --git a/feeds/ipq95xx/hostapd/patches/q01-006-mbssid-add-MBSSID-configuration-element.patch b/feeds/ipq95xx/hostapd/patches/q01-006-mbssid-add-MBSSID-configuration-element.patch deleted file mode 100644 index 8bf854169..000000000 --- a/feeds/ipq95xx/hostapd/patches/q01-006-mbssid-add-MBSSID-configuration-element.patch +++ /dev/null @@ -1,139 +0,0 @@ -From 23a89229c9aa2b833d9aa2db163f0b56d913b9bb Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Fri, 10 Sep 2021 16:31:14 -0700 -Subject: [PATCH 06/15] mbssid: add MBSSID configuration element - -Add data as per IEEE Std 802.11ax-2021 9.4.2.260 Multiple BSSID -Configuration element when enhanced multiple BSSID -advertisements (EMA) are enabled. -This element informs the clients about the EMA profile periodicity of -the multiple BSSID set. - -Co-developed-by: John Crispin -Signed-off-by: John Crispin -Signed-off-by: Aloka Dixit ---- - src/ap/beacon.c | 35 ++++++++++++++++++++++------------- - src/common/ieee802_11_defs.h | 1 + - 2 files changed, 23 insertions(+), 13 deletions(-) - ---- a/src/ap/beacon.c -+++ b/src/ap/beacon.c -@@ -459,8 +459,9 @@ static u8 * hostapd_eid_supported_op_cla - } - - --static int hostapd_set_mbssid_beacon(struct hostapd_data *hapd, -- struct wpa_driver_ap_params *params) -+static u8 * hostapd_set_mbssid_beacon(struct hostapd_data *hapd, -+ struct wpa_driver_ap_params *params, -+ u8 *eid) - { - struct hostapd_iface *iface = hapd->iface; - struct hostapd_data *tx_bss; -@@ -468,17 +469,17 @@ static int hostapd_set_mbssid_beacon(str - u8 num_mbssid = 0, *end; - - if (!iface->conf->mbssid || iface->num_bss == 1) -- return 0; -+ return eid; - - if (!iface->mbssid_max_interfaces) { - wpa_printf(MSG_ERROR, "MBSSID: Driver doesn't support " - "multi-BSSID advertisements"); -- return -1; -+ return eid; - } else if (iface->num_bss > iface->mbssid_max_interfaces) { - wpa_printf(MSG_ERROR, "MBSSID: Driver supports maximum %u " - "interfaces for multi-BSSID advertisements", - iface->mbssid_max_interfaces); -- return -1; -+ return eid; - } - - tx_bss = hostapd_mbssid_get_tx_bss(hapd); -@@ -491,26 +492,26 @@ static int hostapd_set_mbssid_beacon(str - if (!iface->ema_max_periodicity) { - wpa_printf(MSG_WARNING, "MBSSID: Driver doesn't support" - " enhanced multiple BSSID advertisements"); -- return -1; -+ return eid; - } - if (num_mbssid > iface->ema_max_periodicity) { - wpa_printf(MSG_WARNING, "MBSSID: Driver supports " - "maximum %u EMA profile periodicity", - iface->ema_max_periodicity); -- return -1; -+ return eid; - } - params->ema = 1; - } - - if (hapd != tx_bss || !num_mbssid) -- return 0; -+ return eid; - - params->mbssid_elem_count = num_mbssid; - params->mbssid_elem = os_zalloc(len); - if (!params->mbssid_elem) { - wpa_printf(MSG_ERROR, "Memory allocation failed for multiple " - "BSSID elements"); -- return -1; -+ return eid; - } - - params->mbssid_elem_offset = os_zalloc(params->mbssid_elem_count * -@@ -520,7 +521,7 @@ static int hostapd_set_mbssid_beacon(str - "multiple BSSID element offsets"); - os_free(params->mbssid_elem); - params->mbssid_elem = NULL; -- return -1; -+ return eid; - } - - end = hostapd_eid_mbssid(tx_bss, params->mbssid_elem, -@@ -530,7 +531,14 @@ static int hostapd_set_mbssid_beacon(str - params->mbssid_elem_offset); - params->mbssid_elem_len = end - params->mbssid_elem; - -- return 0; -+ if (hapd->iconf->ema) { -+ *eid++ = WLAN_EID_EXTENSION; -+ *eid++ = 3; -+ *eid++ = WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION; -+ *eid++ = iface->num_bss; -+ *eid++ = params->mbssid_elem_count; -+ } -+ return eid; - } - - -@@ -1634,6 +1642,8 @@ int ieee802_11_build_ap_params(struct ho - } - #endif /* CONFIG_IEEE80211AX */ - -+ if (hapd->iconf->ema) -+ tail_len += 5; /* Multiple BSSID Configuration element */ - tail_len += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_BEACON); - tail_len += hostapd_mbo_ie_len(hapd); - tail_len += hostapd_eid_owe_trans_len(hapd); -@@ -1719,8 +1729,7 @@ int ieee802_11_build_ap_params(struct ho - tailpos = hostapd_eid_supported_op_classes(hapd, tailpos); - tailpos = hostapd_eid_ht_capabilities(hapd, tailpos); - tailpos = hostapd_eid_ht_operation(hapd, tailpos); -- if (hostapd_set_mbssid_beacon(hapd, params)) -- return -1; -+ tailpos = hostapd_set_mbssid_beacon(hapd, params, tailpos); - - tailpos = hostapd_eid_ext_capab(hapd, tailpos); - ---- a/src/common/ieee802_11_defs.h -+++ b/src/common/ieee802_11_defs.h -@@ -481,6 +481,7 @@ - #define WLAN_EID_EXT_SPATIAL_REUSE 39 - #define WLAN_EID_EXT_COLOR_CHANGE_ANNOUNCEMENT 42 - #define WLAN_EID_EXT_OCV_OCI 54 -+#define WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION 55 - #define WLAN_EID_EXT_SHORT_SSID_LIST 58 - #define WLAN_EID_EXT_HE_6GHZ_BAND_CAP 59 - #define WLAN_EID_EXT_EDMG_CAPABILITIES 61 diff --git a/feeds/ipq95xx/hostapd/patches/q01-007-mbssid-add-non-inheritance-element.patch b/feeds/ipq95xx/hostapd/patches/q01-007-mbssid-add-non-inheritance-element.patch deleted file mode 100644 index 7a1294879..000000000 --- a/feeds/ipq95xx/hostapd/patches/q01-007-mbssid-add-non-inheritance-element.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 20bb093c1a0555c365afabb1809c8edb7bde4178 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Fri, 10 Sep 2021 14:58:04 -0700 -Subject: [PATCH 07/15] mbssid: add non-inheritance element - -Add data as per IEEE Std 802.11-2020 9.4.2.240 Non-Inheritance element -if the transmitted profile is secured but non-transmitted profiles -use open security. - -Signed-off-by: John Crispin -Signed-off-by: Sowmiya Sree Elavalagan -Signed-off-by: Aloka Dixit ---- - src/ap/ieee802_11.c | 30 ++++++++++++++++++++++++++++-- - src/common/ieee802_11_defs.h | 1 + - 2 files changed, 29 insertions(+), 2 deletions(-) - ---- a/src/ap/ieee802_11.c -+++ b/src/ap/ieee802_11.c -@@ -7688,12 +7688,14 @@ u8 * hostapd_eid_rnr(struct hostapd_data - static size_t hostapd_eid_mbssid_elem_len(struct hostapd_data *hapd, - u32 frame_type, size_t *bss_index) - { -+ struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd); - size_t len = 3, i; - - for (i = *bss_index; i < hapd->iface->num_bss; i++) { - struct hostapd_data *bss = hapd->iface->bss[i]; -- const u8 *auth, *rsn, *rsnx; -+ const u8 *auth, *rsn = NULL, *rsnx = NULL; - size_t nontx_profile_len, auth_len; -+ u8 ie_count = 0; - - if (!bss || !bss->conf || !bss->started) - continue; -@@ -7721,6 +7723,12 @@ static size_t hostapd_eid_mbssid_elem_le - if (rsnx) - nontx_profile_len += (2 + rsnx[1]); - } -+ if (!rsn && hostapd_wpa_ie(tx_bss, WLAN_EID_RSN)) -+ ie_count++; -+ if (!rsnx && hostapd_wpa_ie(tx_bss, WLAN_EID_RSNX)) -+ ie_count++; -+ if (ie_count) -+ nontx_profile_len += (4 + ie_count); - - if ((len + nontx_profile_len) > 255) - goto mbssid_too_big; -@@ -7768,6 +7776,7 @@ static u8 * hostapd_eid_mbssid_elem(stru - u32 frame_type, u8 max_bssid_indicator, - size_t *bss_index) - { -+ struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd); - size_t i; - u8 *eid_len_offset, *max_bssid_indicator_offset; - -@@ -7779,7 +7788,8 @@ static u8 * hostapd_eid_mbssid_elem(stru - struct hostapd_data *bss = hapd->iface->bss[i]; - struct hostapd_bss_config *conf; - u8 *eid_len_pos, *nontx_bss_start = eid; -- const u8 *auth, *rsn, *rsnx; -+ const u8 *auth, *rsn = NULL, *rsnx = NULL; -+ u8 ie_count = 0, non_inherit_ie[2]; - size_t auth_len = 0; - u16 capab_info; - -@@ -7826,6 +7836,22 @@ static u8 * hostapd_eid_mbssid_elem(stru - eid += (2 + rsnx[1]); - } - } -+ if (!rsn && hostapd_wpa_ie(tx_bss, WLAN_EID_RSN)) { -+ non_inherit_ie[ie_count] = WLAN_EID_RSN; -+ ie_count++; -+ } -+ if (!rsnx && hostapd_wpa_ie(tx_bss, WLAN_EID_RSNX)) { -+ non_inherit_ie[ie_count] = WLAN_EID_RSNX; -+ ie_count++; -+ } -+ if (ie_count) { -+ *eid++ = WLAN_EID_EXTENSION; -+ *eid++ = 2 + ie_count; -+ *eid++ = WLAN_EID_EXT_NON_INHERITANCE; -+ *eid++ = ie_count; -+ os_memcpy(eid, non_inherit_ie, ie_count); -+ eid += ie_count; -+ } - - *eid_len_pos = (eid - eid_len_pos) - 1; - ---- a/src/common/ieee802_11_defs.h -+++ b/src/common/ieee802_11_defs.h -@@ -482,6 +482,7 @@ - #define WLAN_EID_EXT_COLOR_CHANGE_ANNOUNCEMENT 42 - #define WLAN_EID_EXT_OCV_OCI 54 - #define WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION 55 -+#define WLAN_EID_EXT_NON_INHERITANCE 56 - #define WLAN_EID_EXT_SHORT_SSID_LIST 58 - #define WLAN_EID_EXT_HE_6GHZ_BAND_CAP 59 - #define WLAN_EID_EXT_EDMG_CAPABILITIES 61 diff --git a/feeds/ipq95xx/hostapd/patches/q01-008-mbssid-make-the-AID-space-shared.patch b/feeds/ipq95xx/hostapd/patches/q01-008-mbssid-make-the-AID-space-shared.patch deleted file mode 100644 index 761efcb06..000000000 --- a/feeds/ipq95xx/hostapd/patches/q01-008-mbssid-make-the-AID-space-shared.patch +++ /dev/null @@ -1,29 +0,0 @@ -From efb94ba16134dd58b51a920c9a8a145459ee38ef Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Fri, 10 Sep 2021 14:58:14 -0700 -Subject: [PATCH 08/15] mbssid: make the AID space shared - -As described in IEEE Std 802.11-2020 11.1.3.8 Multiple BSSID procedure, -set the lowest AID value assigned to any client equal to 2^n, -where n is the maximum BSSID indicator of the MBSSID set. - -Signed-off-by: John Crispin -Signed-off-by: Aloka Dixit ---- - src/ap/ieee802_11.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - ---- a/src/ap/ieee802_11.c -+++ b/src/ap/ieee802_11.c -@@ -4016,7 +4016,10 @@ int hostapd_get_aid(struct hostapd_data - } - if (j == 32) - return -1; -- aid = i * 32 + j + 1; -+ aid = i * 32 + j; -+ -+ aid += (1 << hostapd_max_bssid_indicator(hapd)); -+ - if (aid > 2007) - return -1; - diff --git a/feeds/ipq95xx/hostapd/patches/q01-009-mbssid-set-extended-capabilities.patch b/feeds/ipq95xx/hostapd/patches/q01-009-mbssid-set-extended-capabilities.patch deleted file mode 100644 index ee4b58f21..000000000 --- a/feeds/ipq95xx/hostapd/patches/q01-009-mbssid-set-extended-capabilities.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 6167dad7647fca057215110b0f371a949f952fd0 Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Fri, 10 Sep 2021 15:12:06 -0700 -Subject: [PATCH 09/15] mbssid: set extended capabilities - -Set extended capabilities as described in IEEE Std 802.11-2020 -section 9.4.2.26 Extended Capabilities element. - -Co-developed-by: John Crispin -Signed-off-by: John Crispin -Signed-off-by: Aloka Dixit ---- - src/ap/beacon.c | 38 ++++++++++++++++++++++++++++++++++++-- - 1 file changed, 36 insertions(+), 2 deletions(-) - -Index: b/src/ap/beacon.c -=================================================================== ---- a/src/ap/beacon.c 2022-10-17 02:00:55.052754218 +0530 -+++ b/src/ap/beacon.c 2022-10-17 02:02:21.956146621 +0530 -@@ -542,12 +542,41 @@ static u8 * hostapd_set_mbssid_beacon(st - } - - -+static u8 * hostapd_ext_capab_mbssid(struct hostapd_data *hapd, u8 *eid, -+ u8 *eid_ext_cap, u8 ema_periodicity) -+{ -+ size_t len; -+ -+ if (eid == eid_ext_cap) -+ return eid; -+ -+ len = eid_ext_cap[1]; -+ eid_ext_cap += 2; -+ -+ if (!hapd->iconf->mbssid && len >= 3) -+ eid_ext_cap[2] &= ~0x40; -+ -+ if (!hapd->iconf->ema && len >= 11) -+ eid_ext_cap[10] &= ~0x08; -+ -+ if (hapd->iconf->mbssid && ema_periodicity <= 1) { -+ while (len < 11) { -+ *eid++ = 0x00; -+ len++; -+ } -+ eid_ext_cap[10] |= 0x01; -+ } -+ -+ return eid; -+} -+ -+ - static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, - const struct ieee80211_mgmt *req, - int is_p2p, size_t *resp_len) - { - struct ieee80211_mgmt *resp; -- u8 *pos, *epos, *csa_pos; -+ u8 *pos, *epos, *csa_pos, *ext_cap_pos; - size_t buflen; - - hapd = hostapd_mbssid_get_tx_bss(hapd); -@@ -663,7 +692,10 @@ static u8 * hostapd_gen_probe_resp(struc - pos = hostapd_eid_mbssid(hapd, pos, epos, WLAN_FC_STYPE_PROBE_RESP, 0, - NULL); - -+ ext_cap_pos = pos; - pos = hostapd_eid_ext_capab(hapd, pos); -+ if (!is_6ghz_op_class(hapd->iconf->op_class)) -+ pos = hostapd_ext_capab_mbssid(hapd, pos, ext_cap_pos, 1); - - pos = hostapd_eid_time_adv(hapd, pos); - pos = hostapd_eid_time_zone(hapd, pos); -@@ -1589,7 +1621,7 @@ int ieee802_11_build_ap_params(struct ho - size_t resp_len = 0; - #ifdef NEED_AP_MLME - u16 capab_info; -- u8 *pos, *tailpos, *tailend, *csa_pos; -+ u8 *pos, *tailpos, *tailend, *csa_pos, *ext_cap_pos; - #endif /* NEED_AP_MLME */ - - os_memset(params, 0, sizeof(*params)); -@@ -1731,7 +1763,11 @@ int ieee802_11_build_ap_params(struct ho - tailpos = hostapd_eid_ht_operation(hapd, tailpos); - tailpos = hostapd_set_mbssid_beacon(hapd, params, tailpos); - -+ ext_cap_pos = tailpos; - tailpos = hostapd_eid_ext_capab(hapd, tailpos); -+ if (!is_6ghz_op_class(hapd->iconf->op_class)) -+ tailpos = hostapd_ext_capab_mbssid(hapd, tailpos, ext_cap_pos, -+ params->mbssid_elem_count); - - /* - * TODO: Time Advertisement element should only be included in some diff --git a/feeds/ipq95xx/hostapd/patches/q01-010-mbssid-DTIM-period-configuration-for-EMA-AP.patch b/feeds/ipq95xx/hostapd/patches/q01-010-mbssid-DTIM-period-configuration-for-EMA-AP.patch deleted file mode 100644 index dc360af39..000000000 --- a/feeds/ipq95xx/hostapd/patches/q01-010-mbssid-DTIM-period-configuration-for-EMA-AP.patch +++ /dev/null @@ -1,45 +0,0 @@ -From d8d604c6e7dcfae8aa51d16d1d0033b2d9e132e9 Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Fri, 10 Sep 2021 14:59:32 -0700 -Subject: [PATCH 10/15] mbssid: DTIM period configuration for EMA AP - -Set the DTIM periods of non-transmitted profiles equal to the EMA -profile periodicity if those are not a multiple of the latter -already as recommended in IEEE P802.11ax/D8.0, October 2020, -Multiple BSSID configuration examples, AA.1 Introduction. - -Signed-off-by: Aloka Dixit ---- - src/ap/ieee802_11.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - ---- a/src/ap/ieee802_11.c -+++ b/src/ap/ieee802_11.c -@@ -7777,7 +7777,7 @@ size_t hostapd_eid_mbssid_len(struct hos - - static u8 * hostapd_eid_mbssid_elem(struct hostapd_data *hapd, u8 *eid, u8 *end, - u32 frame_type, u8 max_bssid_indicator, -- size_t *bss_index) -+ size_t *bss_index, u8 elem_count) - { - struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd); - size_t i; -@@ -7818,6 +7818,9 @@ static u8 * hostapd_eid_mbssid_elem(stru - if (frame_type == WLAN_FC_STYPE_BEACON) { - *eid++ = 3; - *eid++ = i; -+ if (hapd->iconf->ema && -+ (conf->dtim_period % elem_count)) -+ conf->dtim_period = elem_count; - *eid++ = conf->dtim_period; - *eid++ = 0xFF; - } else { -@@ -7903,7 +7906,7 @@ u8 * hostapd_eid_mbssid(struct hostapd_d - } - eid = hostapd_eid_mbssid_elem(hapd, eid, end, frame_type, - hostapd_max_bssid_indicator(hapd), -- &bss_index); -+ &bss_index, elem_count); - } - return eid; - } diff --git a/feeds/ipq95xx/hostapd/patches/q01-011-mbssid-hidden-SSID-support.patch b/feeds/ipq95xx/hostapd/patches/q01-011-mbssid-hidden-SSID-support.patch deleted file mode 100644 index 11d5a3fdb..000000000 --- a/feeds/ipq95xx/hostapd/patches/q01-011-mbssid-hidden-SSID-support.patch +++ /dev/null @@ -1,118 +0,0 @@ -From e6ae627eb7370cbdbdf31a7d9a1b30d5586292c9 Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Fri, 10 Sep 2021 15:04:43 -0700 -Subject: [PATCH 11/15] mbssid: hidden SSID support - -Hidden nontransmitted BSSID profiles will be included in the beacons -and probe responses but SSID value will be removed or set to all -zeros depending on the configured value of 'ignore_broadcast_ssid'. -If complete profiles are omitted, clients cannot stay connected to -the AP. -For unicast probe requests with SSID set to a hidden nontransmitted -BSS, complete SSID should be included in the response. - -Signed-off-by: Aloka Dixit -Signed-off-by: Sowmiya Sree Elavalagan ---- - src/ap/beacon.c | 25 +++++++++++++++++++------ - src/ap/ieee802_11.c | 24 +++++++++++++++++++----- - 2 files changed, 38 insertions(+), 11 deletions(-) - ---- a/src/ap/beacon.c -+++ b/src/ap/beacon.c -@@ -578,6 +578,7 @@ static u8 * hostapd_gen_probe_resp(struc - struct ieee80211_mgmt *resp; - u8 *pos, *epos, *csa_pos, *ext_cap_pos; - size_t buflen; -+ struct hostapd_data *hapd_probed = hapd; - - hapd = hostapd_mbssid_get_tx_bss(hapd); - -@@ -620,7 +621,8 @@ static u8 * hostapd_gen_probe_resp(struc - } - #endif /* CONFIG_IEEE80211AX */ - -- buflen += hostapd_eid_mbssid_len(hapd, WLAN_FC_STYPE_PROBE_RESP, NULL); -+ buflen += hostapd_eid_mbssid_len(hapd_probed, WLAN_FC_STYPE_PROBE_RESP, -+ NULL); - buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP); - buflen += hostapd_mbo_ie_len(hapd); - buflen += hostapd_eid_owe_trans_len(hapd); -@@ -648,9 +650,20 @@ static u8 * hostapd_gen_probe_resp(struc - - pos = resp->u.probe_resp.variable; - *pos++ = WLAN_EID_SSID; -- *pos++ = hapd->conf->ssid.ssid_len; -- os_memcpy(pos, hapd->conf->ssid.ssid, hapd->conf->ssid.ssid_len); -- pos += hapd->conf->ssid.ssid_len; -+ if (hapd->conf->ignore_broadcast_ssid && hapd != hapd_probed) { -+ if (hapd->conf->ignore_broadcast_ssid == 2) { -+ *pos++ = hapd->conf->ssid.ssid_len; -+ os_memset(pos, 0, hapd->conf->ssid.ssid_len); -+ pos += hapd->conf->ssid.ssid_len; -+ } else { -+ *pos++ = 0; /* empty SSID */ -+ } -+ } else { -+ *pos++ = hapd->conf->ssid.ssid_len; -+ os_memcpy(pos, hapd->conf->ssid.ssid, -+ hapd->conf->ssid.ssid_len); -+ pos += hapd->conf->ssid.ssid_len; -+ } - - /* Supported rates */ - pos = hostapd_eid_supp_rates(hapd, pos); -@@ -689,8 +702,8 @@ static u8 * hostapd_gen_probe_resp(struc - pos = hostapd_eid_supported_op_classes(hapd, pos); - pos = hostapd_eid_ht_capabilities(hapd, pos); - pos = hostapd_eid_ht_operation(hapd, pos); -- pos = hostapd_eid_mbssid(hapd, pos, epos, WLAN_FC_STYPE_PROBE_RESP, 0, -- NULL); -+ pos = hostapd_eid_mbssid(hapd_probed, pos, epos, -+ WLAN_FC_STYPE_PROBE_RESP, 0, NULL); - - ext_cap_pos = pos; - pos = hostapd_eid_ext_capab(hapd, pos); ---- a/src/ap/ieee802_11.c -+++ b/src/ap/ieee802_11.c -@@ -7707,11 +7707,16 @@ static size_t hostapd_eid_mbssid_elem_le - * Sublement ID: 1 byte - * Length: 1 byte - * Nontransmitted capabilities: 4 bytes -- * SSID element: 2 + variable -+ * SSID element: 2 + variable (except for hidden BSS) - * Multiple BSSID Index Element: 3 bytes (+2 bytes in beacons) - * Fixed length = 1 + 1 + 4 + 2 + 3 = 11 - */ -- nontx_profile_len = 11 + bss->conf->ssid.ssid_len; -+ nontx_profile_len = 11; -+ -+ if (!bss->conf->ignore_broadcast_ssid || -+ bss->conf->ignore_broadcast_ssid == 2 || -+ (frame_type == WLAN_FC_STYPE_PROBE_RESP && bss == hapd)) -+ nontx_profile_len += bss->conf->ssid.ssid_len; - - if (frame_type == WLAN_FC_STYPE_BEACON) - nontx_profile_len += 2; -@@ -7810,9 +7815,18 @@ static u8 * hostapd_eid_mbssid_elem(stru - eid += sizeof(capab_info); - - *eid++ = WLAN_EID_SSID; -- *eid++ = conf->ssid.ssid_len; -- os_memcpy(eid, conf->ssid.ssid, conf->ssid.ssid_len); -- eid += conf->ssid.ssid_len; -+ if (!conf->ignore_broadcast_ssid || -+ (frame_type == WLAN_FC_STYPE_PROBE_RESP && bss == hapd)) { -+ *eid++ = conf->ssid.ssid_len; -+ os_memcpy(eid, conf->ssid.ssid, conf->ssid.ssid_len); -+ eid += conf->ssid.ssid_len; -+ } else if (conf->ignore_broadcast_ssid == 2) { -+ *eid++ = conf->ssid.ssid_len; -+ os_memset(eid, 0, conf->ssid.ssid_len); -+ eid += conf->ssid.ssid_len; -+ } else { -+ *eid++ = 0; -+ } - - *eid++ = WLAN_EID_MULTIPLE_BSSID_INDEX; - if (frame_type == WLAN_FC_STYPE_BEACON) { diff --git a/feeds/ipq95xx/hostapd/patches/q01-012-mbssid-process-known-BSSID-element.patch b/feeds/ipq95xx/hostapd/patches/q01-012-mbssid-process-known-BSSID-element.patch deleted file mode 100644 index d2d44253d..000000000 --- a/feeds/ipq95xx/hostapd/patches/q01-012-mbssid-process-known-BSSID-element.patch +++ /dev/null @@ -1,253 +0,0 @@ -From 7f24d44812413a9f05c1ed0fd4059f7461789d4a Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Fri, 10 Sep 2021 15:24:49 -0700 -Subject: [PATCH 12/15] mbssid: process known BSSID element - -Process the known BSSID elements if included by non-AP stations. -The format is described in IEEE Std 802.11ax-2021 9.4.2.261. - -Non-AP stations may include this element in directed probe requests -to indicate which of the multiple BSSIDs they have already discovered. -AP should exclude these profiles from the probe response. - -Signed-off-by: Aloka Dixit ---- - src/ap/beacon.c | 21 ++++++++++------- - src/ap/ieee802_11.c | 42 ++++++++++++++++++++++++++++------ - src/ap/ieee802_11.h | 6 +++-- - src/common/ieee802_11_common.c | 4 ++++ - src/common/ieee802_11_common.h | 2 ++ - src/common/ieee802_11_defs.h | 1 + - 6 files changed, 59 insertions(+), 17 deletions(-) - ---- a/src/ap/beacon.c -+++ b/src/ap/beacon.c -@@ -487,7 +487,8 @@ static u8 * hostapd_set_mbssid_beacon(st - params->mbssid_index = hostapd_mbssid_get_bss_index(hapd); - params->mbssid_count = iface->num_bss; - -- len = hostapd_eid_mbssid_len(tx_bss, WLAN_FC_STYPE_BEACON, &num_mbssid); -+ len = hostapd_eid_mbssid_len(tx_bss, WLAN_FC_STYPE_BEACON, &num_mbssid, -+ NULL, 0); - if (hapd->iconf->ema) { - if (!iface->ema_max_periodicity) { - wpa_printf(MSG_WARNING, "MBSSID: Driver doesn't support" -@@ -528,7 +529,7 @@ static u8 * hostapd_set_mbssid_beacon(st - params->mbssid_elem + len, - WLAN_FC_STYPE_BEACON, - params->mbssid_elem_count, -- params->mbssid_elem_offset); -+ params->mbssid_elem_offset, NULL, 0); - params->mbssid_elem_len = end - params->mbssid_elem; - - if (hapd->iconf->ema) { -@@ -573,7 +574,8 @@ static u8 * hostapd_ext_capab_mbssid(str - - static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, - const struct ieee80211_mgmt *req, -- int is_p2p, size_t *resp_len) -+ int is_p2p, size_t *resp_len, -+ const u8 *known_bss, u8 known_bss_len) - { - struct ieee80211_mgmt *resp; - u8 *pos, *epos, *csa_pos, *ext_cap_pos; -@@ -622,7 +624,7 @@ static u8 * hostapd_gen_probe_resp(struc - #endif /* CONFIG_IEEE80211AX */ - - buflen += hostapd_eid_mbssid_len(hapd_probed, WLAN_FC_STYPE_PROBE_RESP, -- NULL); -+ NULL, known_bss, known_bss_len); - buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP); - buflen += hostapd_mbo_ie_len(hapd); - buflen += hostapd_eid_owe_trans_len(hapd); -@@ -703,7 +705,8 @@ static u8 * hostapd_gen_probe_resp(struc - pos = hostapd_eid_ht_capabilities(hapd, pos); - pos = hostapd_eid_ht_operation(hapd, pos); - pos = hostapd_eid_mbssid(hapd_probed, pos, epos, -- WLAN_FC_STYPE_PROBE_RESP, 0, NULL); -+ WLAN_FC_STYPE_PROBE_RESP, 0, NULL, -+ known_bss, known_bss_len); - - ext_cap_pos = pos; - pos = hostapd_eid_ext_capab(hapd, pos); -@@ -1268,7 +1271,8 @@ void handle_probe_req(struct hostapd_dat - " signal=%d", MAC2STR(mgmt->sa), ssi_signal); - - resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL, -- &resp_len); -+ &resp_len, elems.mbssid_known_bss, -+ elems.mbssid_known_bss_len); - if (resp == NULL) - return; - -@@ -1338,7 +1342,7 @@ static u8 * hostapd_probe_resp_offloads( - "this"); - - /* Generate a Probe Response template for the non-P2P case */ -- return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len); -+ return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, NULL, 0); - } - #endif /* NEED_AP_MLME */ - -@@ -1355,7 +1359,8 @@ static u8 * hostapd_unsol_bcast_probe_re - hapd->conf->unsol_bcast_probe_resp_interval; - - return hostapd_gen_probe_resp(hapd, NULL, 0, -- ¶ms->unsol_bcast_probe_resp_tmpl_len); -+ ¶ms->unsol_bcast_probe_resp_tmpl_len, -+ NULL, 0); - } - #endif /* CONFIG_IEEE80211AX */ - ---- a/src/ap/ieee802_11.c -+++ b/src/ap/ieee802_11.c -@@ -7689,7 +7689,9 @@ u8 * hostapd_eid_rnr(struct hostapd_data - - - static size_t hostapd_eid_mbssid_elem_len(struct hostapd_data *hapd, -- u32 frame_type, size_t *bss_index) -+ u32 frame_type, size_t *bss_index, -+ const u8 *known_bss, -+ size_t known_bss_len) - { - struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd); - size_t len = 3, i; -@@ -7700,6 +7702,12 @@ static size_t hostapd_eid_mbssid_elem_le - size_t nontx_profile_len, auth_len; - u8 ie_count = 0; - -+ if (known_bss && (known_bss_len > (i / 8))) { -+ known_bss = &known_bss[i / 8]; -+ if (*known_bss & (u8)(BIT(i % 8))) -+ continue; -+ } -+ - if (!bss || !bss->conf || !bss->started) - continue; - -@@ -7751,7 +7759,8 @@ mbssid_too_big: - - - size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type, -- u8 *elem_count) -+ u8 *elem_count, const u8 *known_bss, -+ size_t known_bss_len) - { - size_t len = 0, bss_index = 1; - -@@ -7771,7 +7780,8 @@ size_t hostapd_eid_mbssid_len(struct hos - - while (bss_index < hapd->iface->num_bss) { - len += hostapd_eid_mbssid_elem_len(hapd, frame_type, -- &bss_index); -+ &bss_index, known_bss, -+ known_bss_len); - - if (frame_type == WLAN_FC_STYPE_BEACON) - *elem_count += 1; -@@ -7782,7 +7792,8 @@ size_t hostapd_eid_mbssid_len(struct hos - - static u8 * hostapd_eid_mbssid_elem(struct hostapd_data *hapd, u8 *eid, u8 *end, - u32 frame_type, u8 max_bssid_indicator, -- size_t *bss_index, u8 elem_count) -+ size_t *bss_index, u8 elem_count, -+ const u8 *known_bss, size_t known_bss_len) - { - struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd); - size_t i; -@@ -7801,6 +7812,12 @@ static u8 * hostapd_eid_mbssid_elem(stru - size_t auth_len = 0; - u16 capab_info; - -+ if (known_bss && (known_bss_len > (i / 8))) { -+ known_bss = &known_bss[i / 8]; -+ if (*known_bss & (u8)(BIT(i % 8))) -+ continue; -+ } -+ - if (!bss || !bss->conf || !bss->started) - continue; - conf = bss->conf; -@@ -7892,10 +7909,12 @@ mbssid_too_big: - - - u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end, -- u32 frame_type, u8 elem_count, u8 **elem_offset) -+ u32 frame_type, u8 elem_count, u8 **elem_offset, -+ const u8 *known_bss, size_t known_bss_len) - { - size_t bss_index = 1; - u8 elem_index = 0; -+ u8 max_bssid_indicator = hostapd_max_bssid_indicator(hapd); - - if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 || - (frame_type != WLAN_FC_STYPE_BEACON && -@@ -7919,8 +7938,9 @@ u8 * hostapd_eid_mbssid(struct hostapd_d - elem_index = elem_index + 1; - } - eid = hostapd_eid_mbssid_elem(hapd, eid, end, frame_type, -- hostapd_max_bssid_indicator(hapd), -- &bss_index, elem_count); -+ max_bssid_indicator, &bss_index, -+ elem_count, known_bss, -+ known_bss_len); - } - return eid; - } ---- a/src/ap/ieee802_11.h -+++ b/src/ap/ieee802_11.h -@@ -131,9 +131,11 @@ void hostapd_client_poll_ok(struct hosta - u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid); - int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta); - size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type, -- u8 *elem_count); -+ u8 *elem_count, const u8 *known_bss, -+ size_t known_bss_len); - u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end, -- u32 frame_type, u8 elem_count, u8 **elem_offset); -+ u32 frame_type, u8 elem_count, u8 **elem_offset, -+ const u8 *known_bss, size_t known_bss_len); - #ifdef CONFIG_SAE - void sae_clear_retransmit_timer(struct hostapd_data *hapd, - struct sta_info *sta); ---- a/src/common/ieee802_11_common.c -+++ b/src/common/ieee802_11_common.c -@@ -307,6 +307,10 @@ static int ieee802_11_parse_extension(co - elems->pasn_params = pos; - elems->pasn_params_len = elen; - break; -+ case WLAN_EID_EXT_KNOWN_BSSID: -+ elems->mbssid_known_bss = pos; -+ elems->mbssid_known_bss_len = elen; -+ break; - default: - if (show_errors) { - wpa_printf(MSG_MSGDUMP, ---- a/src/common/ieee802_11_common.h -+++ b/src/common/ieee802_11_common.h -@@ -118,6 +118,7 @@ struct ieee802_11_elems { - const u8 *sae_pk; - const u8 *s1g_capab; - const u8 *pasn_params; -+ const u8 *mbssid_known_bss; - - u8 ssid_len; - u8 supp_rates_len; -@@ -172,6 +173,7 @@ struct ieee802_11_elems { - u8 short_ssid_list_len; - u8 sae_pk_len; - u8 pasn_params_len; -+ u8 mbssid_known_bss_len; - - struct mb_ies_info mb_ies; - struct frag_ies_info frag_ies; ---- a/src/common/ieee802_11_defs.h -+++ b/src/common/ieee802_11_defs.h -@@ -483,6 +483,7 @@ - #define WLAN_EID_EXT_OCV_OCI 54 - #define WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION 55 - #define WLAN_EID_EXT_NON_INHERITANCE 56 -+#define WLAN_EID_EXT_KNOWN_BSSID 57 - #define WLAN_EID_EXT_SHORT_SSID_LIST 58 - #define WLAN_EID_EXT_HE_6GHZ_BAND_CAP 59 - #define WLAN_EID_EXT_EDMG_CAPABILITIES 61 diff --git a/feeds/ipq95xx/hostapd/patches/q01-013-mbssid-add-nl80211-support.patch b/feeds/ipq95xx/hostapd/patches/q01-013-mbssid-add-nl80211-support.patch deleted file mode 100644 index 9927ac500..000000000 --- a/feeds/ipq95xx/hostapd/patches/q01-013-mbssid-add-nl80211-support.patch +++ /dev/null @@ -1,195 +0,0 @@ -From eb4acfa2e5c146f7637f6abc78b672e885f8780d Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Fri, 10 Sep 2021 15:24:54 -0700 -Subject: [PATCH 13/15] mbssid: add nl80211 support - -Send MBSSID and EMA configuration parameters to kernel. - -Signed-off-by: John Crispin -Signed-off-by: Aloka Dixit ---- - src/drivers/driver_nl80211.c | 51 +++++++++++++++++++++++++++- - src/drivers/driver_nl80211_capa.c | 26 +++++++++++++++ - src/drivers/nl80211_copy.h | 55 +++++++++++++++++++++++++++++++ - 3 files changed, 131 insertions(+), 1 deletion(-) - ---- a/src/drivers/driver_nl80211.c -+++ b/src/drivers/driver_nl80211.c -@@ -4537,6 +4537,53 @@ static int nl80211_unsol_bcast_probe_res - #endif /* CONFIG_IEEE80211AX */ - - -+static int nl80211_mbssid(struct nl_msg *msg, -+ struct wpa_driver_ap_params *params) -+{ -+ struct nlattr *config, *elems; -+ int ifidx; -+ -+ config = nla_nest_start(msg, NL80211_ATTR_MBSSID_CONFIG); -+ if (!config) -+ goto fail; -+ -+ nla_put_u8(msg, NL80211_MBSSID_CONFIG_ATTR_INDEX, params->mbssid_index); -+ if (params->mbssid_tx_iface) { -+ ifidx = if_nametoindex(params->mbssid_tx_iface); -+ if (ifidx <= 0) -+ goto fail; -+ nla_put_u32(msg, -+ NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX, -+ ifidx); -+ } -+ -+ if (params->ema) -+ nla_put_flag(msg, NL80211_MBSSID_CONFIG_ATTR_EMA); -+ -+ nla_nest_end(msg, config); -+ -+ if (params->mbssid_elem_count && params->mbssid_elem_len && -+ params->mbssid_elem_offset && *params->mbssid_elem_offset) { -+ u8 i, **offs = params->mbssid_elem_offset; -+ -+ elems = nla_nest_start(msg, NL80211_ATTR_MBSSID_ELEMS); -+ if (!elems) -+ goto fail; -+ -+ for (i = 0; i < params->mbssid_elem_count - 1; i++) -+ nla_put(msg, i + 1, offs[i + 1] - offs[i], offs[i]); -+ nla_put(msg, i + 1, -+ *offs + params->mbssid_elem_len- offs[i], -+ offs[i]); -+ nla_nest_end(msg, elems); -+ } -+ return 0; -+ -+fail: -+ return -1; -+} -+ -+ - static int wpa_driver_nl80211_set_ap(void *priv, - struct wpa_driver_ap_params *params) - { -@@ -4834,6 +4881,9 @@ static int wpa_driver_nl80211_set_ap(voi - goto fail; - #endif /* CONFIG_FILS */ - -+ if (params->mbssid_count && nl80211_mbssid(msg, params) < 0) -+ goto fail; -+ - ret = send_and_recv_msgs_connect_handle(drv, msg, bss, 1); - if (ret) { - wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)", -@@ -5445,7 +5495,6 @@ const char * nl80211_iftype_str(enum nl8 - } - } - -- - static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv, - const char *ifname, - enum nl80211_iftype iftype, ---- a/src/drivers/driver_nl80211_capa.c -+++ b/src/drivers/driver_nl80211_capa.c -@@ -846,6 +846,29 @@ err: - } - - -+static void wiphy_info_mbssid(struct wpa_driver_capa *cap, struct nlattr *attr) -+{ -+ struct nlattr *config[NL80211_MBSSID_CONFIG_ATTR_MAX + 1]; -+ -+ if (nla_parse_nested(config, NL80211_MBSSID_CONFIG_ATTR_MAX, attr, -+ NULL)) -+ return; -+ -+ if (!config[NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES]) -+ return; -+ -+ cap->mbssid_max_interfaces = -+ nla_get_u8(config[NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES]); -+ -+ if (config[NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY]) -+ cap->ema_max_periodicity = -+ nla_get_u8(config[NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY]); -+ -+ wpa_printf(MSG_DEBUG, -+ "multiple_bssid: max interfaces %u, max profile periodicity %u\n", -+ cap->mbssid_max_interfaces, cap->ema_max_periodicity); -+} -+ - static int wiphy_info_handler(struct nl_msg *msg, void *arg) - { - struct nlattr *tb[NL80211_ATTR_MAX + 1]; -@@ -1070,6 +1093,9 @@ static int wiphy_info_handler(struct nl_ - if (tb[NL80211_ATTR_WIPHY_SELF_MANAGED_REG]) - capa->flags |= WPA_DRIVER_FLAGS_SELF_MANAGED_REGULATORY; - -+ if (tb[NL80211_ATTR_MBSSID_CONFIG]) -+ wiphy_info_mbssid(capa, tb[NL80211_ATTR_MBSSID_CONFIG]); -+ - return NL_SKIP; - } - ---- a/src/drivers/nl80211_copy.h -+++ b/src/drivers/nl80211_copy.h -@@ -7376,6 +7376,61 @@ enum nl80211_sar_specs_attrs { - NL80211_SAR_ATTR_SPECS_MAX = __NL80211_SAR_ATTR_SPECS_LAST - 1, - }; - -+/** -+ * enum nl80211_mbssid_config_attributes - multiple BSSID (MBSSID) and enhanced -+ * multi-BSSID advertisements (EMA) in AP mode. -+ * Kernel uses some of these attributes to advertise driver's support for -+ * MBSSID and EMA. -+ * Remaining attributes should be used by the userspace to configure the -+ * features. -+ * -+ * @__NL80211_MBSSID_CONFIG_ATTR_INVALID: Invalid -+ * -+ * @NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES: Used by the kernel to advertise -+ * the maximum number of MBSSID interfaces supported by the driver. -+ * Driver should indicate MBSSID support by setting -+ * wiphy->mbssid_max_interfaces to a value more than or equal to 2. -+ * -+ * @NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY: Used by the kernel -+ * to advertise the maximum profile periodicity supported by the driver -+ * if EMA is enabled. Driver should indicate EMA support to the userspace -+ * by setting wiphy->ema_max_profile_periodicity to -+ * a non-zero value. -+ * -+ * @NL80211_MBSSID_CONFIG_ATTR_INDEX: Mandatory parameter to pass the index of -+ * this BSS (u8) in the multiple BSSID set. -+ * Value must be set to 0 for the transmitting interface and non-zero for -+ * all non-transmitting interfaces. The userspace will be responsible -+ * for using unique indices for the interfaces. -+ * Range: 0 to wiphy->mbssid_max_interfaces-1. -+ * -+ * @NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX: Mandatory parameter for -+ * a non-transmitted profile which provides the interface index (u32) of -+ * the transmitted profile. The value must match one of the interface -+ * indices advertised by the kernel. Optional if the interface being set up -+ * is the transmitting one, however, if provided then the value must match -+ * the interface index of the same. -+ * -+ * @NL80211_MBSSID_CONFIG_ATTR_EMA: Flag used to enable EMA AP feature. -+ * Setting this flag is permitted only if the driver advertises EMA support -+ * by setting wiphy->ema_max_profile_periodicity to non-zero. -+ * -+ * @__NL80211_MBSSID_CONFIG_ATTR_LAST: Internal -+ * @NL80211_MBSSID_CONFIG_ATTR_MAX: highest attribute -+ */ -+enum nl80211_mbssid_config_attributes { -+ __NL80211_MBSSID_CONFIG_ATTR_INVALID, -+ -+ NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES, -+ NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY, -+ NL80211_MBSSID_CONFIG_ATTR_INDEX, -+ NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX, -+ NL80211_MBSSID_CONFIG_ATTR_EMA, -+ -+ /* keep last */ -+ __NL80211_MBSSID_CONFIG_ATTR_LAST, -+ NL80211_MBSSID_CONFIG_ATTR_MAX = __NL80211_MBSSID_CONFIG_ATTR_LAST - 1, -+}; - - /** - * enum nl80211_beacon_tx_mode - Beacon Tx Mode enum. diff --git a/feeds/ipq95xx/hostapd/patches/q01-014-mbssid-RNR-for-EMA-AP.patch b/feeds/ipq95xx/hostapd/patches/q01-014-mbssid-RNR-for-EMA-AP.patch deleted file mode 100644 index eb7aad3c6..000000000 --- a/feeds/ipq95xx/hostapd/patches/q01-014-mbssid-RNR-for-EMA-AP.patch +++ /dev/null @@ -1,412 +0,0 @@ -From 4a58da0a8bcb37f5ceac80fabb64c38ec2eedd94 Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Thu, 10 Dec 2020 15:13:11 -0800 -Subject: [PATCH 14/15] hostad: RNR for EMA AP - -(1) Enable RNR by default for EMA AP. -(2) Only for EMA AP, split reduced neighbor report in as many groups as - number of multiple BSSID offset groups. - Each RNR group skips the profiles already include in the corresponding - MBSSID groups. - The last additional group will have data common for all EMA beacons. -(3) Enable reduced neighbor report by default in 5GHz/2.4GHz beacons - and probe responses if one or more 6GHz APs are co-located. - -Signed-off-by: Aloka Dixit ---- - src/ap/beacon.c | 52 ++++++++++++++------- - src/ap/ieee802_11.c | 106 +++++++++++++++++++++++++++++++++++++------ - src/ap/ieee802_11.h | 5 +- - src/drivers/driver.h | 22 +++++++++ - 4 files changed, 152 insertions(+), 33 deletions(-) - ---- a/src/ap/beacon.c -+++ b/src/ap/beacon.c -@@ -488,7 +488,7 @@ static u8 * hostapd_set_mbssid_beacon(st - params->mbssid_count = iface->num_bss; - - len = hostapd_eid_mbssid_len(tx_bss, WLAN_FC_STYPE_BEACON, &num_mbssid, -- NULL, 0); -+ NULL, 0, ¶ms->rnr_elem_len); - if (hapd->iconf->ema) { - if (!iface->ema_max_periodicity) { - wpa_printf(MSG_WARNING, "MBSSID: Driver doesn't support" -@@ -509,27 +509,30 @@ static u8 * hostapd_set_mbssid_beacon(st - - params->mbssid_elem_count = num_mbssid; - params->mbssid_elem = os_zalloc(len); -- if (!params->mbssid_elem) { -- wpa_printf(MSG_ERROR, "Memory allocation failed for multiple " -- "BSSID elements"); -- return eid; -- } -+ if (!params->mbssid_elem) -+ goto error; - - params->mbssid_elem_offset = os_zalloc(params->mbssid_elem_count * - sizeof(u8 *)); -- if (!params->mbssid_elem_offset) { -- wpa_printf(MSG_ERROR, "MBSSID: Memory allocation failed for " -- "multiple BSSID element offsets"); -- os_free(params->mbssid_elem); -- params->mbssid_elem = NULL; -- return eid; -- } -+ if (!params->mbssid_elem_offset) -+ goto error; -+ -+ params->rnr_elem = os_zalloc(params->rnr_elem_len); -+ if (!params->rnr_elem) -+ goto error; -+ -+ params->rnr_elem_offset = os_zalloc((params->mbssid_elem_count + 1) * -+ sizeof(u8 *)); -+ if (!params->rnr_elem_offset) -+ goto error; - - end = hostapd_eid_mbssid(tx_bss, params->mbssid_elem, - params->mbssid_elem + len, - WLAN_FC_STYPE_BEACON, - params->mbssid_elem_count, -- params->mbssid_elem_offset, NULL, 0); -+ params->mbssid_elem_offset, NULL, 0, -+ params->rnr_elem, params->rnr_elem_offset, -+ ¶ms->rnr_elem_count, params->rnr_elem_len); - params->mbssid_elem_len = end - params->mbssid_elem; - - if (hapd->iconf->ema) { -@@ -540,6 +543,19 @@ static u8 * hostapd_set_mbssid_beacon(st - *eid++ = params->mbssid_elem_count; - } - return eid; -+ -+error: -+ os_free(params->mbssid_elem); -+ params->mbssid_elem = NULL; -+ os_free(params->mbssid_elem_offset); -+ params->mbssid_elem_offset = NULL; -+ os_free(params->rnr_elem); -+ params->rnr_elem = NULL; -+ os_free(params->rnr_elem_offset); -+ params->rnr_elem_offset = NULL; -+ wpa_printf(MSG_ERROR, -+ "Memory allocation failed for multiple BSSID elements"); -+ return eid; - } - - -@@ -624,7 +640,7 @@ static u8 * hostapd_gen_probe_resp(struc - #endif /* CONFIG_IEEE80211AX */ - - buflen += hostapd_eid_mbssid_len(hapd_probed, WLAN_FC_STYPE_PROBE_RESP, -- NULL, known_bss, known_bss_len); -+ NULL, known_bss, known_bss_len, NULL); - buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP); - buflen += hostapd_mbo_ie_len(hapd); - buflen += hostapd_eid_owe_trans_len(hapd); -@@ -706,7 +722,7 @@ static u8 * hostapd_gen_probe_resp(struc - pos = hostapd_eid_ht_operation(hapd, pos); - pos = hostapd_eid_mbssid(hapd_probed, pos, epos, - WLAN_FC_STYPE_PROBE_RESP, 0, NULL, -- known_bss, known_bss_len); -+ known_bss, known_bss_len, NULL, NULL, NULL, 0); - - ext_cap_pos = pos; - pos = hostapd_eid_ext_capab(hapd, pos); -@@ -2002,6 +2018,10 @@ void ieee802_11_free_ap_params(struct wp - params->mbssid_elem = NULL; - os_free(params->mbssid_elem_offset); - params->mbssid_elem_offset = NULL; -+ os_free(params->rnr_elem); -+ params->rnr_elem = NULL; -+ os_free(params->rnr_elem_offset); -+ params->rnr_elem_offset = NULL; - #ifdef CONFIG_FILS - os_free(params->fd_frame_tmpl); - params->fd_frame_tmpl = NULL; ---- a/src/ap/ieee802_11.c -+++ b/src/ap/ieee802_11.c -@@ -7336,9 +7336,12 @@ static size_t hostapd_eid_nr_db_len(stru - } - - -+const int ema_not_applicable = -1; - static size_t hostapd_eid_rnr_iface_len(struct hostapd_data *hapd, - struct hostapd_data *reporting_hapd, -- size_t *current_len) -+ size_t *current_len, -+ int ema_bss_index_1, -+ int ema_bss_index_2) - { - size_t total_len = 0, len = *current_len; - int tbtt_count = 0; -@@ -7364,6 +7367,10 @@ static size_t hostapd_eid_rnr_iface_len( - bss->conf->ignore_broadcast_ssid) - continue; - -+ if ((ema_bss_index_1 != -1) && (ema_bss_index_2 != -1) && -+ (i >= ema_bss_index_1) && (i < ema_bss_index_2)) -+ continue; -+ - if (len + RNR_TBTT_INFO_LEN > 255 || - tbtt_count >= RNR_TBTT_INFO_COUNT_MAX) - break; -@@ -7442,7 +7449,9 @@ static size_t hostapd_eid_rnr_colocation - continue; - - len += hostapd_eid_rnr_iface_len(iface->bss[0], hapd, -- current_len); -+ current_len, -+ ema_not_applicable, -+ ema_not_applicable); - } - - return len; -@@ -7465,15 +7474,20 @@ size_t hostapd_eid_rnr_len(struct hostap - total_len += hostapd_eid_rnr_colocation_len( - hapd, ¤t_len); - -- if (hapd->conf->rnr && hapd->iface->num_bss > 1) -+ if (hapd->conf->rnr && hapd->iface->num_bss > 1 && -+ !hapd->iconf->mbssid) - total_len += hostapd_eid_rnr_iface_len(hapd, hapd, -- ¤t_len); -+ ¤t_len, -+ ema_not_applicable, -+ ema_not_applicable); - break; - - case WLAN_FC_STYPE_ACTION: - if (hapd->iface->num_bss > 1 && mode == STANDALONE_6GHZ) - total_len += hostapd_eid_rnr_iface_len(hapd, hapd, -- ¤t_len); -+ ¤t_len, -+ ema_not_applicable, -+ ema_not_applicable); - break; - - default: -@@ -7541,7 +7555,8 @@ static u8 * hostapd_eid_nr_db(struct hos - - static u8 * hostapd_eid_rnr_iface(struct hostapd_data *hapd, - struct hostapd_data *reporting_hapd, -- u8 *eid, size_t *current_len) -+ u8 *eid, size_t *current_len, -+ int ema_bss_index_1, int ema_bss_index_2) - { - struct hostapd_data *bss; - struct hostapd_iface *iface = hapd->iface; -@@ -7586,6 +7601,10 @@ static u8 * hostapd_eid_rnr_iface(struct - bss->conf->ignore_broadcast_ssid) - continue; - -+ if ((ema_bss_index_1 != -1) && (ema_bss_index_2 != -1) && -+ (i >= ema_bss_index_1) && (i < ema_bss_index_2)) -+ continue; -+ - if (len + RNR_TBTT_INFO_LEN > 255 || - tbtt_count >= RNR_TBTT_INFO_COUNT_MAX) - break; -@@ -7599,6 +7618,12 @@ static u8 * hostapd_eid_rnr_iface(struct - reporting_hapd->conf->ssid.short_ssid) - bss_param |= RNR_BSS_PARAM_SAME_SSID; - -+ if (hapd->iconf->mbssid) { -+ bss_param |= RNR_BSS_PARAM_MULTIPLE_BSSID; -+ if (bss == hostapd_mbssid_get_tx_bss(hapd)) -+ bss_param |= RNR_BSS_PARAM_TRANSMITTED_BSSID; -+ } -+ - if (is_6ghz_op_class(hapd->iconf->op_class) && - bss->conf->unsol_bcast_probe_resp_interval) - bss_param |= -@@ -7642,7 +7667,8 @@ static u8 * hostapd_eid_rnr_colocation(s - continue; - - eid = hostapd_eid_rnr_iface(iface->bss[0], hapd, eid, -- current_len); -+ current_len, ema_not_applicable, -+ ema_not_applicable); - } - - return eid; -@@ -7666,15 +7692,20 @@ u8 * hostapd_eid_rnr(struct hostapd_data - eid = hostapd_eid_rnr_colocation(hapd, eid, - ¤t_len); - -- if (hapd->conf->rnr && hapd->iface->num_bss > 1) -+ if (hapd->conf->rnr && hapd->iface->num_bss > 1 && -+ !hapd->iconf->mbssid) - eid = hostapd_eid_rnr_iface(hapd, hapd, eid, -- ¤t_len); -+ ¤t_len, -+ ema_not_applicable, -+ ema_not_applicable); - break; - - case WLAN_FC_STYPE_ACTION: - if (hapd->iface->num_bss > 1 && mode == STANDALONE_6GHZ) - eid = hostapd_eid_rnr_iface(hapd, hapd, eid, -- ¤t_len); -+ ¤t_len, -+ ema_not_applicable, -+ ema_not_applicable); - break; - - default: -@@ -7760,9 +7791,9 @@ mbssid_too_big: - - size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type, - u8 *elem_count, const u8 *known_bss, -- size_t known_bss_len) -+ size_t known_bss_len, size_t *rnr_len) - { -- size_t len = 0, bss_index = 1; -+ size_t len = 0, bss_index = 1, rnr_cur_len = 0, rnr_count; - - if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 || - (frame_type != WLAN_FC_STYPE_BEACON && -@@ -7779,13 +7810,26 @@ size_t hostapd_eid_mbssid_len(struct hos - } - - while (bss_index < hapd->iface->num_bss) { -+ rnr_count = bss_index; - len += hostapd_eid_mbssid_elem_len(hapd, frame_type, - &bss_index, known_bss, - known_bss_len); - - if (frame_type == WLAN_FC_STYPE_BEACON) - *elem_count += 1; -+ if (hapd->iconf->ema && rnr_len) { -+ rnr_cur_len = 0; -+ (*rnr_len) += hostapd_eid_rnr_iface_len(hapd, -+ hostapd_mbssid_get_tx_bss(hapd), -+ &rnr_cur_len, -+ rnr_count, -+ bss_index); -+ } - } -+ -+ if (hapd->iconf->ema && rnr_len) -+ (*rnr_len) += hostapd_eid_rnr_len(hapd, frame_type); -+ - return len; - } - -@@ -7910,11 +7954,13 @@ mbssid_too_big: - - u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end, - u32 frame_type, u8 elem_count, u8 **elem_offset, -- const u8 *known_bss, size_t known_bss_len) -+ const u8 *known_bss, size_t known_bss_len, u8 *rnr_eid, -+ u8 **rnr_offsets, int *rnr_count, int rnr_len) - { -- size_t bss_index = 1; -- u8 elem_index = 0; -+ size_t bss_index = 1, cur_len = 0; -+ u8 elem_index = 0, *rnr_start_eid = rnr_eid; - u8 max_bssid_indicator = hostapd_max_bssid_indicator(hapd); -+ bool add_rnr = false; - - if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 || - (frame_type != WLAN_FC_STYPE_BEACON && -@@ -7926,7 +7972,12 @@ u8 * hostapd_eid_mbssid(struct hostapd_d - return eid; - } - -+ if (hapd->iconf->ema && frame_type == WLAN_FC_STYPE_BEACON && rnr_len) -+ add_rnr = true; -+ - while (bss_index < hapd->iface->num_bss) { -+ int rnr_start_count = bss_index; -+ - if (frame_type == WLAN_FC_STYPE_BEACON) { - if (elem_index == elem_count) { - wpa_printf(MSG_WARNING, "MBSSID: More number of" -@@ -7941,7 +7992,32 @@ u8 * hostapd_eid_mbssid(struct hostapd_d - max_bssid_indicator, &bss_index, - elem_count, known_bss, - known_bss_len); -+ -+ if (add_rnr == true) { -+ rnr_offsets[*rnr_count] = rnr_eid; -+ *rnr_count = *rnr_count + 1; -+ cur_len = 0; -+ -+ rnr_eid = hostapd_eid_rnr_iface(hapd, -+ hostapd_mbssid_get_tx_bss(hapd), -+ rnr_eid, &cur_len, -+ rnr_start_count, -+ bss_index); -+ } - } -+ -+ if ((add_rnr == true) && ((rnr_eid - rnr_start_eid) < rnr_len)) { -+ rnr_offsets[*rnr_count] = rnr_eid; -+ *rnr_count = *rnr_count + 1; -+ cur_len = 0; -+ -+ if (hapd->conf->rnr) -+ rnr_eid = hostapd_eid_nr_db(hapd, rnr_eid, &cur_len); -+ if (get_colocation_mode(hapd) == COLOCATED_LOWER_BAND) -+ rnr_eid = hostapd_eid_rnr_colocation(hapd, rnr_eid, -+ &cur_len); -+ } -+ - return eid; - } - ---- a/src/ap/ieee802_11.h -+++ b/src/ap/ieee802_11.h -@@ -132,10 +132,11 @@ u8 * hostapd_eid_bss_max_idle_period(str - int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta); - size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type, - u8 *elem_count, const u8 *known_bss, -- size_t known_bss_len); -+ size_t known_bss_len, size_t *rnr_len); - u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end, - u32 frame_type, u8 elem_count, u8 **elem_offset, -- const u8 *known_bss, size_t known_bss_len); -+ const u8 *known_bss, size_t known_bss_len, u8 *rnr_eid, -+ u8 **rnr_offsets, int *rnr_count, int rnr_len); - #ifdef CONFIG_SAE - void sae_clear_retransmit_timer(struct hostapd_data *hapd, - struct sta_info *sta); ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -1669,6 +1669,27 @@ struct wpa_driver_ap_params { - */ - u8 ema; - -+ /** -+ * rnr_elem - This buffer contains all of reduced neighbor report (RNR) -+ * elements -+ */ -+ u8 *rnr_elem; -+ -+ /** -+ * rnr_elem_len - Length of rnr_elem buffer -+ */ -+ size_t rnr_elem_len; -+ -+ /** -+ * rnr_elem_count - Number of RNR elements -+ */ -+ int rnr_elem_count; -+ -+ /** -+ * rnr_elem_offset - The offsets to the elements in rnr_elem. -+ * Kernel will use these to include RNR elements in EMA beacons. -+ */ -+ u8 **rnr_elem_offset; - }; - - struct wpa_driver_mesh_bss_params { -@@ -2340,6 +2361,7 @@ struct wpa_bss_params { - int wpa_key_mgmt; - int rsn_preauth; - enum mfp_options ieee80211w; -+ - }; - - #define WPA_STA_AUTHORIZED BIT(0) diff --git a/feeds/ipq95xx/hostapd/patches/q01-015-mbssid-Netlink-changes-for-RNR-offsets.patch b/feeds/ipq95xx/hostapd/patches/q01-015-mbssid-Netlink-changes-for-RNR-offsets.patch deleted file mode 100644 index 3debe29f5..000000000 --- a/feeds/ipq95xx/hostapd/patches/q01-015-mbssid-Netlink-changes-for-RNR-offsets.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 842ecae7678e62d97e7a9ca6efbe821444720e41 Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Mon, 14 Dec 2020 11:41:59 -0800 -Subject: [PATCH 15/15] hostapd: Netlink changes for RNR offsets - -This patch adds new nested netlink attribute NL80211_ATTR_EMA_RNR_ELEMS -used to send reduced neighbor report (RNR) elements to kernel when EMA -is enabled. -This attribute includes the count of RNR elements and data at each index. -While generating EMA beacons, kernel will include RNR group at a given -index along with MBSSID group. -Last element, if present, has RNR data common for all EMA beacons. - -Signed-off-by: Aloka Dixit ---- - src/drivers/driver_nl80211.c | 19 +++++++++++++++++++ - src/drivers/nl80211_copy.h | 2 ++ - 2 files changed, 21 insertions(+) - ---- a/src/drivers/driver_nl80211.c -+++ b/src/drivers/driver_nl80211.c -@@ -4577,6 +4577,25 @@ static int nl80211_mbssid(struct nl_msg - offs[i]); - nla_nest_end(msg, elems); - } -+ -+ if (!params->ema) -+ return 0; -+ -+ if (params->rnr_elem_count && params->rnr_elem_len && -+ params->rnr_elem_offset && *params->rnr_elem_offset) { -+ u8 i, **offs = params->rnr_elem_offset; -+ -+ elems = nla_nest_start(msg, NL80211_ATTR_EMA_RNR_ELEMS); -+ if (!elems) -+ goto fail; -+ -+ for (i = 0; i < params->rnr_elem_count - 1; i++) -+ nla_put(msg, i + 1, offs[i + 1] - offs[i], offs[i]); -+ nla_put(msg, i + 1, -+ *offs + params->rnr_elem_len- offs[i], -+ offs[i]); -+ nla_nest_end(msg, elems); -+ } - return 0; - - fail: ---- a/src/drivers/nl80211_copy.h -+++ b/src/drivers/nl80211_copy.h -@@ -3109,6 +3109,8 @@ enum nl80211_attrs { - - NL80211_ATTR_6G_REG_POWER_MODE, - -+ NL80211_ATTR_EMA_RNR_ELEMS, -+ - /* add attributes here, update the policy in nl80211.c */ - - __NL80211_ATTR_AFTER_LAST, diff --git a/feeds/ipq95xx/hostapd/patches/q01-016-mbssid-support-extended-rates-in-non-tx-profiles.patch b/feeds/ipq95xx/hostapd/patches/q01-016-mbssid-support-extended-rates-in-non-tx-profiles.patch deleted file mode 100644 index dfdbc1f24..000000000 --- a/feeds/ipq95xx/hostapd/patches/q01-016-mbssid-support-extended-rates-in-non-tx-profiles.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 96b57fdd283c3856f390e971d3acbe3f88107c0d Mon Sep 17 00:00:00 2001 -From: Sowmiya Sree Elavalagan -Date: Tue, 15 Mar 2022 13:49:02 -0700 -Subject: [PATCH] mbssid: support extended rates in non-tx profiles - -Add extended supported rates for non-transmitting interface if -applicable. If the transmitting interface supports it and -the non-transmitting interface does not then add it in the -non-inheritance element. - -Signed-off-by: Sowmiya Sree Elavalagan ---- - src/ap/ap_config.h | 1 + - src/ap/ieee802_11.c | 11 +++++++++++ - 2 files changed, 12 insertions(+) - ---- a/src/ap/ap_config.h -+++ b/src/ap/ap_config.h -@@ -911,6 +911,7 @@ struct hostapd_bss_config { - - u8 rnr; - int beacon_tx_mode; -+ bool xrates_supported; - }; - - /** ---- a/src/ap/ieee802_11.c -+++ b/src/ap/ieee802_11.c -@@ -166,6 +166,7 @@ u8 * hostapd_eid_ext_supp_rates(struct h - int i, num, count; - int h2e_required; - -+ hapd->conf->xrates_supported = 0; - if (hapd->iface->current_rates == NULL) - return eid; - -@@ -215,6 +216,7 @@ u8 * hostapd_eid_ext_supp_rates(struct h - *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY; - } - -+ hapd->conf->xrates_supported = 1; - return pos; - } - -@@ -7774,6 +7776,10 @@ static size_t hostapd_eid_mbssid_elem_le - ie_count++; - if (!rsnx && hostapd_wpa_ie(tx_bss, WLAN_EID_RSNX)) - ie_count++; -+ if (bss->conf->xrates_supported) -+ nontx_profile_len += 8; -+ else if (hapd->conf->xrates_supported) -+ ie_count++; - if (ie_count) - nontx_profile_len += (4 + ie_count); - -@@ -7852,7 +7858,7 @@ static u8 * hostapd_eid_mbssid_elem(stru - struct hostapd_bss_config *conf; - u8 *eid_len_pos, *nontx_bss_start = eid; - const u8 *auth, *rsn = NULL, *rsnx = NULL; -- u8 ie_count = 0, non_inherit_ie[2]; -+ u8 ie_count = 0, non_inherit_ie[3]; - size_t auth_len = 0; - u16 capab_info; - -@@ -7917,6 +7923,7 @@ static u8 * hostapd_eid_mbssid_elem(stru - eid += (2 + rsnx[1]); - } - } -+ eid = hostapd_eid_ext_supp_rates(bss, eid); - if (!rsn && hostapd_wpa_ie(tx_bss, WLAN_EID_RSN)) { - non_inherit_ie[ie_count] = WLAN_EID_RSN; - ie_count++; -@@ -7925,6 +7932,11 @@ static u8 * hostapd_eid_mbssid_elem(stru - non_inherit_ie[ie_count] = WLAN_EID_RSNX; - ie_count++; - } -+ if (hapd->conf->xrates_supported && -+ !bss->conf->xrates_supported) { -+ non_inherit_ie[ie_count] = WLAN_EID_EXT_SUPP_RATES; -+ ie_count++; -+ } - if (ie_count) { - *eid++ = WLAN_EID_EXTENSION; - *eid++ = 2 + ie_count; diff --git a/feeds/ipq95xx/hostapd/patches/q02-001-hostapd-fix-unsol-config.patch b/feeds/ipq95xx/hostapd/patches/q02-001-hostapd-fix-unsol-config.patch deleted file mode 100644 index a6486f49b..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-001-hostapd-fix-unsol-config.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 2adeba3ef1f8cf283b0d3c3b9c4a0e009fc85f65 Mon Sep 17 00:00:00 2001 -From: Karthikeyan Kathirvel -Date: Fri, 25 Mar 2022 14:36:33 +0530 -Subject: [PATCH] hostapd: unable to config unsolicited broadcast Probe - Response - -Unsolicited broadcast Probe Response config is not working in hostapd, -this is because fils_discovery_min_int was used by mistake where -fils_discovery_max_int should have been used, latter is the one used to -decide whether FILS discovery is enabled or not. - -Signed-off-by: Karthikeyan Kathirvel ---- - src/ap/ap_config.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c -index e91c042..4ceb480 100644 ---- a/src/ap/ap_config.c -+++ b/src/ap/ap_config.c -@@ -1427,7 +1427,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, - #endif /* CONFIG_SAE_PK */ - - #ifdef CONFIG_FILS -- if (full_config && bss->fils_discovery_min_int && -+ if (full_config && bss->fils_discovery_max_int && - bss->unsol_bcast_probe_resp_interval) { - wpa_printf(MSG_ERROR, - "Cannot enable both FILS discovery and unsolicited broadcast Probe Response at the same time"); --- -2.7.4 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-001-nl80211-sync-kernel-definitions.patch b/feeds/ipq95xx/hostapd/patches/q02-001-nl80211-sync-kernel-definitions.patch deleted file mode 100644 index fd2642948..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-001-nl80211-sync-kernel-definitions.patch +++ /dev/null @@ -1,147 +0,0 @@ -From 3c5da4abf9298e72e89b012ef9a1cc9a4b53975e Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Tue, 20 Jul 2021 13:47:09 -0700 -Subject: [PATCH 01/23] nl80211: sync kernel definitions - -Signed-off-by: Aloka Dixit ---- - src/drivers/nl80211_copy.h | 39 +++++++++++++++++++++++++++++++++++++- - 1 file changed, 38 insertions(+), 1 deletion(-) - ---- a/src/drivers/nl80211_copy.h -+++ b/src/drivers/nl80211_copy.h -@@ -1784,7 +1784,8 @@ enum nl80211_commands { - * features NL80211_EXT_FEATURE_BEACON_RATE_LEGACY, - * NL80211_EXT_FEATURE_BEACON_RATE_HT, - * NL80211_EXT_FEATURE_BEACON_RATE_VHT and -- * NL80211_EXT_FEATURE_BEACON_RATE_HE. -+ * NL80211_EXT_FEATURE_BEACON_RATE_HE and -+ * NL80211_EXT_FEATURE_BEACON_RATE_EHT. - * - * @NL80211_ATTR_FRAME_MATCH: A binary attribute which typically must contain - * at least one byte, currently used with @NL80211_CMD_REGISTER_FRAME. -@@ -2592,6 +2593,10 @@ enum nl80211_commands { - * @NL80211_ATTR_AWGN_INTERFERENCE_BITMAP: u32 attribute specifying the - * interference bitmap of operating bandwidth for %NL80211_CMD_AWGN_DETECT - * -+ * @NL80211_ATTR_EHT_CAPABILITY: EHT Capability information element (from -+ * association request when used with NL80211_CMD_NEW_STATION). Can be set -+ * only if %NL80211_STA_FLAG_WME is set. -+ * - * @NUM_NL80211_ATTR: total number of nl80211_attrs available - * @NL80211_ATTR_MAX: highest attribute number currently defined - * @__NL80211_ATTR_AFTER_LAST: internal use -@@ -3099,6 +3104,10 @@ enum nl80211_attrs { - NL80211_ATTR_MBSSID_CONFIG, - NL80211_ATTR_MBSSID_ELEMS, - -+ NL80211_ATTR_RADAR_BACKGROUND, -+ -+ NL80211_ATTR_AP_SETTINGS_FLAGS, -+ - NL80211_ATTR_BEACON_TX_MODE, - - NL80211_ATTR_WIPHY_ANTENNA_GAIN, -@@ -3111,6 +3120,10 @@ enum nl80211_attrs { - - NL80211_ATTR_EMA_RNR_ELEMS, - -+ NL80211_ATTR_EHT_CAPABILITY = NL80211_ATTR_MBSSID_ELEMS + 15, -+ -+ NL80211_ATTR_DISABLE_EHT, -+ - /* add attributes here, update the policy in nl80211.c */ - - __NL80211_ATTR_AFTER_LAST, -@@ -3690,6 +3703,8 @@ enum nl80211_mpath_info { - NL80211_MPATH_INFO_MAX = __NL80211_MPATH_INFO_AFTER_LAST - 1 - }; - -+#define NL80211_EHT_NSS_MAX 16 -+ - /** - * enum nl80211_band_iftype_attr - Interface type data attributes - * -@@ -3708,6 +3723,16 @@ enum nl80211_mpath_info { - * defined - * @NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA: HE 6GHz band capabilities (__le16), - * given for all 6 GHz band channels -+ * @NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS: vendor element capabilities that are -+ * advertised on this band/for this iftype (binary) -+ * @NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC: EHT MAC capabilities as in EHT -+ * capabilities element -+ * @NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY: EHT PHY capabilities as in EHT -+ * capabilities element -+ * @NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET: EHT supported NSS/MCS as in EHT -+ * capabilities element -+ * @NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE: EHT PPE thresholds information as -+ * defined in EHT capabilities element - * @__NL80211_BAND_IFTYPE_ATTR_AFTER_LAST: internal use - */ - enum nl80211_band_iftype_attr { -@@ -3719,6 +3744,11 @@ enum nl80211_band_iftype_attr { - NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET, - NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE, - NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA, -+ NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS, -+ NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC, -+ NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY, -+ NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET, -+ NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE, - - /* keep last */ - __NL80211_BAND_IFTYPE_ATTR_AFTER_LAST, -@@ -4915,6 +4945,9 @@ enum nl80211_key_attributes { - * see &struct nl80211_txrate_he - * @NL80211_TXRATE_HE_GI: configure HE GI, 0.8us, 1.6us and 3.2us. - * @NL80211_TXRATE_HE_LTF: configure HE LTF, 1XLTF, 2XLTF and 4XLTF. -+ * @NL80211_TXRATE_EHT: EHT rates allowed for TX rate selection, -+ * see &struct nl80211_txrate_eht -+ * - * @__NL80211_TXRATE_AFTER_LAST: internal - * @NL80211_TXRATE_MAX: highest TX rate attribute - */ -@@ -4927,6 +4960,7 @@ enum nl80211_tx_rate_attributes { - NL80211_TXRATE_HE, - NL80211_TXRATE_HE_GI, - NL80211_TXRATE_HE_LTF, -+ NL80211_TXRATE_EHT, - - /* keep last */ - __NL80211_TXRATE_AFTER_LAST, -@@ -4960,6 +4994,14 @@ enum nl80211_txrate_gi { - }; - - /** -+ * struct nl80211_txrate_eht - EHT MCS/NSS txrate bitmap -+ * @mcs: MCS bitmap table for each NSS (array index 0 for 1 stream, etc.) -+ */ -+struct nl80211_txrate_eht { -+ __u16 mcs[NL80211_EHT_NSS_MAX]; -+}; -+ -+/** - * enum nl80211_band - Frequency band - * @NL80211_BAND_2GHZ: 2.4 GHz ISM band - * @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz) -@@ -6029,6 +6071,9 @@ enum nl80211_feature_flags { - * frame protection for all management frames exchanged during the - * negotiation and range measurement procedure. - * -+ * @NL80211_EXT_FEATURE_BEACON_RATE_EHT: Driver supports beacon rate -+ * configuration (AP/mesh) with EHT rates. -+ * - * @NUM_NL80211_EXT_FEATURES: number of extended features. - * @MAX_NL80211_EXT_FEATURES: highest extended feature index. - */ -@@ -6093,6 +6138,10 @@ enum nl80211_ext_feature_index { - NL80211_EXT_FEATURE_SECURE_LTF, - NL80211_EXT_FEATURE_SECURE_RTT, - NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE, -+ NL80211_EXT_FEATURE_BSS_COLOR, -+ NL80211_EXT_FEATURE_FILS_CRYPTO_OFFLOAD, -+ NL80211_EXT_FEATURE_RADAR_BACKGROUND, -+ NL80211_EXT_FEATURE_BEACON_RATE_EHT, - - /* add new features before the definition below */ - NUM_NL80211_EXT_FEATURES, diff --git a/feeds/ipq95xx/hostapd/patches/q02-002-eht-define-EHT-elements.patch b/feeds/ipq95xx/hostapd/patches/q02-002-eht-define-EHT-elements.patch deleted file mode 100644 index 98e432b65..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-002-eht-define-EHT-elements.patch +++ /dev/null @@ -1,107 +0,0 @@ -From a39239c62e4d86cbd0afacbcf2f286341cb4695f Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Mon, 28 Jun 2021 13:27:48 -0700 -Subject: [PATCH 02/23] eht: define EHT elements - -Define following fields described in IEEE P802.11be/D1.4, January 2022, -- 9.4.2.313 EHT Capabilities element -- 9.4.2.311 EHT Operation element - -Signed-off-by: Aloka Dixit ---- - src/common/ieee802_11_defs.h | 77 ++++++++++++++++++++++++++++++++++++ - 1 file changed, 77 insertions(+) - ---- a/src/common/ieee802_11_defs.h -+++ b/src/common/ieee802_11_defs.h -@@ -493,6 +493,9 @@ - #define WLAN_EID_EXT_REJECTED_GROUPS 92 - #define WLAN_EID_EXT_ANTI_CLOGGING_TOKEN 93 - #define WLAN_EID_EXT_PASN_PARAMS 100 -+#define WLAN_EID_EXT_EHT_OPERATION 106 -+#define WLAN_EID_EXT_EHT_MULTI_LINK 107 -+#define WLAN_EID_EXT_EHT_CAPABILITY 108 - - /* Operating Triplet can be any integer >= 201 - * From IEEE P802.11-REVmd/D4.0: The first octet in each Subband -@@ -2404,6 +2407,80 @@ struct ieee80211_he_mu_edca_parameter_se - /* B7: Reserved if sent by an AP; More Data Ack if sent by a non-AP STA */ - #define HE_QOS_INFO_MORE_DATA_ACK ((u8) (BIT(7))) - -+#define EHT_MAC_CAPAB_MAX_LEN 2 -+#define EHT_PHY_CAPAB_MAX_LEN 9 -+#define EHT_MCS_NSS_CAPAB_MAX_LEN 9 -+/* -+ * Maximum PPE threshold length: 62 bytes -+ * NSS: 4 bits (maximum NSS: 16), RU index: 5 bits, each pair: 6 bits -+ * 9 + (5 * 16 * 6) = 489 bits, Padding: 7 bits -+ */ -+#define EHT_PPE_THRESH_CAPAB_MAX_LEN 62 -+ -+/* IEEE P802.11be/D1.4, January 2022, section 9.4.2.313 */ -+struct ieee80211_eht_capabilities { -+ u8 mac_cap[EHT_MAC_CAPAB_MAX_LEN]; -+ u8 phy_cap[EHT_PHY_CAPAB_MAX_LEN]; -+ u8 optional[71]; -+} STRUCT_PACKED; -+ -+/* -+ * struct ieee80211_eht_operation - eht operation element -+ * -+ * This structure is the "EHT Operation Element" fields as -+ * described in P802.11be_D1.4 section 9.4.2.311 -+ * -+ * FIXME: The spec is unclear how big the fields are, and doesn't -+ * indicate the "Disabled Subchannel Bitmap Present" in the -+ * structure (Figure 9-1002a) at all ... -+ */ -+struct ieee80211_eht_operation { -+ u8 chan_width; -+ u8 ccfs; -+ u8 present_bm; -+ /* contains disabled subchannel bitmap */ -+ u8 optional[]; -+} STRUCT_PACKED; -+ -+/* IEEE P802.11be/D1.4, January 2022, section 9.4.2.313.3 */ -+#define EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_IDX 0 -+#define EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_MASK ((u8) BIT(1)) -+ -+#define EHT_PHYCAP_SU_BEAMFORMER_IDX 0 -+#define EHT_PHYCAP_SU_BEAMFORMER ((u8) BIT(5)) -+#define EHT_PHYCAP_SU_BEAMFORMEE_IDX 0 -+#define EHT_PHYCAP_SU_BEAMFORMEE ((u8) BIT(6)) -+ -+#define EHT_PHYCAP_PPE_THRESHOLD_PRESENT_IDX 5 -+#define EHT_PHYCAP_PPE_THRESHOLD_PRESENT ((u8) BIT(3)) -+ -+#define EHT_PHYCAP_PPE_THRESHOLD_PRESENT_IDX 5 -+ -+#define EHT_PHYCAP_MU_BEAMFORMER_IDX 7 -+#define EHT_PHYCAP_MU_BEAMFORMER_80MHZ ((u8) BIT(4)) -+#define EHT_PHYCAP_MU_BEAMFORMER_160MHZ ((u8) BIT(5)) -+#define EHT_PHYCAP_MU_BEAMFORMER_320MHZ ((u8) BIT(6)) -+#define EHT_PHYCAP_MU_BEAMFORMER_MASK (EHT_PHYCAP_MU_BEAMFORMER_80MHZ | \ -+ EHT_PHYCAP_MU_BEAMFORMER_160MHZ | \ -+ EHT_PHYCAP_MU_BEAMFORMER_320MHZ) -+ -+/* -+ * IEEE P802.11be/D1.0, May 2021, -+ * section 9.4.2.295c.4 Supported EHT-MCS And NSS Set field -+ */ -+#define EHT_NSS_MAX_STREAMS 8 -+#define EHT_PHYCAP_MCS_NSS_LEN_20MHZ_ONLY 4 -+#define EHT_PHYCAP_MCS_NSS_LEN_20MHZ_PLUS 3 -+ -+/* IEEE P802.11be/D1.0, May 2021, 9.4.2.295c.5 EHT PPE Thresholds field */ -+#define EHT_PPE_THRES_NSS_SHIFT 0 -+#define EHT_PPE_THRES_NSS_MASK ((u8) (BIT(0) | BIT(1) | \ -+ BIT(2) | BIT(3))) -+#define EHT_PPE_THRES_RU_INDEX_SHIFT 4 -+#define EHT_PPE_THRES_RU_INDEX_MASK ((u8) (BIT(0) | BIT(1) | \ -+ BIT(2) | BIT(3) | \ -+ BIT(4))) -+ - /* IEEE P802.11ay/D4.0, 9.4.2.251 - EDMG Operation element */ - #define EDMG_BSS_OPERATING_CHANNELS_OFFSET 6 - #define EDMG_OPERATING_CHANNEL_WIDTH_OFFSET 7 diff --git a/feeds/ipq95xx/hostapd/patches/q02-003-eht-configuration-options-to-enable-disable-the-supp.patch b/feeds/ipq95xx/hostapd/patches/q02-003-eht-configuration-options-to-enable-disable-the-supp.patch deleted file mode 100644 index 785f0cc08..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-003-eht-configuration-options-to-enable-disable-the-supp.patch +++ /dev/null @@ -1,580 +0,0 @@ -From 1194cfc2d5835f2cb64b94eaae4431f3995fdc60 Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Mon, 28 Jun 2021 13:30:29 -0700 -Subject: [PATCH] eht: configuration options to enable/disable the support - -Add compilation for flag 802.11be along with options to enable -EHT support per radio and disable_per interface. - -Enabling HE is mandatory to enable EHT mode. - -Tested-by: Pradeep Kumar Chitrapu -Signed-off-by: Aloka Dixit ---- - hostapd/Makefile | 4 ++++ - hostapd/config_file.c | 6 ++++++ - hostapd/hostapd.conf | 10 ++++++++++ - src/ap/ap_config.c | 17 +++++++++++++++++ - src/ap/ap_config.h | 2 ++ - src/ap/ctrl_iface_ap.c | 5 ++++- - src/ap/sta_info.c | 7 ++++--- - src/ap/sta_info.h | 2 +- - src/common/hw_features_common.c | 2 ++ - src/drivers/driver.h | 7 +++++++ - src/drivers/driver_nl80211.c | 14 ++++++++++++-- - wpa_supplicant/Makefile | 11 +++++++++++ - wpa_supplicant/ap.c | 5 +++++ - wpa_supplicant/config.c | 4 ++++ - wpa_supplicant/config_file.c | 3 +++ - wpa_supplicant/config_ssid.h | 12 ++++++++++++ - wpa_supplicant/ctrl_iface.c | 7 ++++--- - wpa_supplicant/events.c | 2 ++ - wpa_supplicant/sme.c | 3 +++ - wpa_supplicant/wpa_cli.c | 3 +++ - wpa_supplicant/wpa_supplicant.c | 39 +++++++++++++++++++++++++++++++++++++-- - wpa_supplicant/wpa_supplicant_i.h | 4 ++++ - 22 files changed, 157 insertions(+), 12 deletions(-) - -diff --git a/hostapd/Makefile b/hostapd/Makefile -index 002d68833c46..bf7d250fe6c6 100644 ---- a/hostapd/Makefile -+++ b/hostapd/Makefile -@@ -349,6 +349,10 @@ CFLAGS += -DCONFIG_IEEE80211AX - OBJS += ../src/ap/ieee802_11_he.o - endif - -+ifdef CONFIG_IEEE80211BE -+CFLAGS += -DCONFIG_IEEE80211BE -+endif -+ - ifdef CONFIG_MBO - CFLAGS += -DCONFIG_MBO - OBJS += ../src/ap/mbo_ap.o -diff --git a/hostapd/config_file.c b/hostapd/config_file.c -index 340eb4874f70..a928beb6dfe8 100644 ---- a/hostapd/config_file.c -+++ b/hostapd/config_file.c -@@ -4622,6 +4622,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, - bss->disable_11ac = !!atoi(pos); - } else if (os_strcmp(buf, "disable_11ax") == 0) { - bss->disable_11ax = !!atoi(pos); -+ } else if (os_strcmp(buf, "disable_11be") == 0) { -+ bss->disable_11be = !!atoi(pos); - } else if (os_strcmp(buf, "beacon_tx_mode") == 0) { - int val = atoi(pos); - -@@ -4662,6 +4664,10 @@ static int hostapd_config_fill(struct hostapd_config *conf, - conf->mbssid = atoi(pos); - } else if (os_strcmp(buf, "ema") == 0) { - conf->ema = atoi(pos); -+#ifdef CONFIG_IEEE80211BE -+ } else if (os_strcmp(buf, "ieee80211be") == 0) { -+ conf->ieee80211be = atoi(pos); -+#endif /* CONFIG_IEEE80211BE */ - } else { - wpa_printf(MSG_ERROR, - "Line %d: unknown configuration item '%s'", -diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf -index 3303679211f5..9d35e0bcd49f 100644 ---- a/hostapd/hostapd.conf -+++ b/hostapd/hostapd.conf -@@ -996,6 +996,16 @@ wmm_ac_vo_acm=0 - # 1 = Enabled - #ema=0 - -+##### IEEE 802.11be related configuration ##################################### -+ -+#ieee80211be: Whether IEEE 802.11be (EHT) is enabled -+# 0 = disabled (default) -+# 1 = enabled -+#ieee80211be=1 -+ -+#disable_11be: Boolean (0/1) to disable EHT for a specific BSS -+#disable_11be=0 -+ - ##### IEEE 802.1X-2004 related configuration ################################## - - # Require IEEE 802.1X authorization -diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c -index 4ceb4803af5e..f036eb663c99 100644 ---- a/src/ap/ap_config.c -+++ b/src/ap/ap_config.c -@@ -1435,6 +1435,15 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, - } - #endif /* CONFIG_FILS */ - -+#ifdef CONFIG_IEEE80211BE -+ if (full_config && bss->disable_11be == false && -+ bss->disable_11ax == true) { -+ bss->disable_11be = true; -+ wpa_printf(MSG_ERROR, -+ "Disabling IEEE 802.11be as IEEE 802.11ax is disabled for this BSS"); -+ } -+#endif /* CONFIG_IEEE80211BE */ -+ - return 0; - } - -@@ -1508,6 +1517,14 @@ int hostapd_config_check(struct hostapd_config *conf, int full_config) - return -1; - } - -+#ifdef CONFIG_IEEE80211BE -+ if (full_config && conf->ieee80211be && !conf->ieee80211ax) { -+ wpa_printf(MSG_ERROR, -+ "Cannot set ieee80211be without ieee80211ax"); -+ return -1; -+ } -+#endif /* CONFIG_IEEE80211BE */ -+ - for (i = 0; i < conf->num_bss; i++) { - if (hostapd_config_check_bss(conf->bss[i], conf, full_config)) - return -1; -diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h -index ebcca548d8cd..0bf8ca345172 100644 ---- a/src/ap/ap_config.h -+++ b/src/ap/ap_config.h -@@ -537,6 +537,7 @@ struct hostapd_bss_config { - bool disable_11n; - bool disable_11ac; - bool disable_11ax; -+ bool disable_11be; - - /* IEEE 802.11v */ - int time_advertisement; -@@ -1127,6 +1128,7 @@ struct hostapd_config { - #endif /* CONFIG_AIRTIME_POLICY */ - u8 mbssid; - u8 ema; -+ int ieee80211be; - }; - - static inline u8 hostapd_get_he_6ghz_reg_pwr_type(struct hostapd_config *conf) -diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c -index e63cbf72dc54..c58715e8b765 100644 ---- a/src/ap/ctrl_iface_ap.c -+++ b/src/ap/ctrl_iface_ap.c -@@ -331,7 +331,7 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd, - return len; - len += ret; - -- ret = ap_sta_flags_txt(sta->flags, buf + len, buflen - len); -+ ret = ap_sta_flags_txt(sta->flags, sta->flags_ext, buf + len, buflen - len); - if (ret < 0) - return len; - len += ret; -@@ -1040,6 +1040,7 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf, - "ieee80211n=%d\n" - "ieee80211ac=%d\n" - "ieee80211ax=%d\n" -+ "ieee80211be=%d\n" - "beacon_int=%u\n" - "dtim_period=%d\n", - iface->conf->channel, -@@ -1052,6 +1053,8 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf, - !hapd->conf->disable_11ac, - iface->conf->ieee80211ax && - !hapd->conf->disable_11ax, -+ iface->conf->ieee80211be && -+ !hapd->conf->disable_11be, - iface->conf->beacon_int, - hapd->conf->dtim_period); - if (os_snprintf_error(buflen - len, ret)) -diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c -index 33ba7b8c5e66..0d446a7498e0 100644 ---- a/src/ap/sta_info.c -+++ b/src/ap/sta_info.c -@@ -1454,13 +1454,13 @@ void ap_sta_clear_disconnect_timeouts(struct hostapd_data *hapd, - } - - --int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen) -+int ap_sta_flags_txt(u32 flags, u32 flags_ext, char *buf, size_t buflen) - { - int res; - - buf[0] = '\0'; - res = os_snprintf(buf, buflen, -- "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", -+ "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", - (flags & WLAN_STA_AUTH ? "[AUTH]" : ""), - (flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""), - (flags & WLAN_STA_AUTHORIZED ? "[AUTHORIZED]" : ""), -@@ -1483,7 +1483,8 @@ int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen) - (flags & WLAN_STA_6GHZ ? "[6GHZ]" : ""), - (flags & WLAN_STA_VENDOR_VHT ? "[VENDOR_VHT]" : ""), - (flags & WLAN_STA_WNM_SLEEP_MODE ? -- "[WNM_SLEEP_MODE]" : "")); -+ "[WNM_SLEEP_MODE]" : ""), -+ (flags_ext & WLAN_STA_EXT_EHT ? "[EHT]" : "")); - if (os_snprintf_error(buflen, res)) - res = -1; - -diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h -index cac4318acafe..ec898bd15e1b 100644 ---- a/src/ap/sta_info.h -+++ b/src/ap/sta_info.h -@@ -401,7 +401,7 @@ void ap_sta_disassoc_cb(struct hostapd_data *hapd, struct sta_info *sta); - void ap_sta_clear_disconnect_timeouts(struct hostapd_data *hapd, - struct sta_info *sta); - --int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen); -+int ap_sta_flags_txt(u32 flags, u32 flags_ext, char *buf, size_t buflen); - void ap_sta_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd, - struct sta_info *sta); - int ap_sta_pending_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd, -diff --git a/src/common/hw_features_common.c b/src/common/hw_features_common.c -index 539b40555ca9..d99cf606911c 100644 ---- a/src/common/hw_features_common.c -+++ b/src/common/hw_features_common.c -@@ -390,6 +390,8 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, - { - if (!he_cap || !he_cap->he_supported) - he_enabled = 0; -+ if (!eht_cap || !eht_cap->eht_supported) -+ eht_enabled = 0; - os_memset(data, 0, sizeof(*data)); - data->mode = mode; - data->freq = freq; -diff --git a/src/drivers/driver.h b/src/drivers/driver.h -index ef86419fa5c9..01dab4dfdb78 100644 ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -1133,6 +1133,13 @@ struct wpa_driver_associate_params { - int disable_he; - #endif /* CONFIG_HE_OVERRIDES */ - -+#ifdef CONFIG_EHT_OVERRIDES -+ /** -+ * disable_eht - Disable EHT for this connection -+ */ -+ int disable_eht; -+#endif /* CONFIG_EHT_OVERRIDES */ -+ - /** - * req_key_mgmt_offload - Request key management offload for connection - * -diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c -index a8faf5193287..c79594399ce6 100644 ---- a/src/drivers/driver_nl80211.c -+++ b/src/drivers/driver_nl80211.c -@@ -4969,6 +4969,7 @@ static int nl80211_put_freq_params(struct nl_msg *msg, - if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq->freq)) - return -ENOBUFS; - -+ wpa_printf(MSG_DEBUG, " * eht_enabled=%d", freq->eht_enabled); - wpa_printf(MSG_DEBUG, " * he_enabled=%d", freq->he_enabled); - wpa_printf(MSG_DEBUG, " * vht_enabled=%d", freq->vht_enabled); - wpa_printf(MSG_DEBUG, " * ht_enabled=%d", freq->ht_enabled); -@@ -5061,9 +5062,10 @@ static int nl80211_set_channel(struct i802_bss *bss, - int ret; - - wpa_printf(MSG_DEBUG, -- "nl80211: Set freq %d (ht_enabled=%d, vht_enabled=%d, he_enabled=%d, bandwidth=%d MHz, cf1=%d MHz, cf2=%d MHz)", -+ "nl80211: Set freq %d (ht_enabled=%d, vht_enabled=%d, he_enabled=%d, eht_enabled=%d, bandwidth=%d MHz, cf1=%d MHz, cf2=%d MHz)", - freq->freq, freq->ht_enabled, freq->vht_enabled, freq->he_enabled, -- freq->bandwidth, freq->center_freq1, freq->center_freq2); -+ freq->eht_enabled, freq->bandwidth, freq->center_freq1, -+ freq->center_freq2); - - msg = nl80211_bss_msg(bss, 0, set_chan ? NL80211_CMD_SET_CHANNEL : - NL80211_CMD_SET_WIPHY); -@@ -6042,6 +6044,14 @@ static int nl80211_ht_vht_overrides(struct nl_msg *msg, - } - #endif /* CONFIG_HE_OVERRIDES */ - -+#ifdef CONFIG_EHT_OVERRIDES -+ if (params->disable_eht) { -+ wpa_printf(MSG_DEBUG, " * EHT disabled"); -+ if (nla_put_flag(msg, NL80211_ATTR_DISABLE_EHT)) -+ return -1; -+ } -+#endif /* CONFIG_EHT_OVERRIDES */ -+ - return 0; - } - -diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile -index 4c6592b62f5b..b5015c3f4019 100644 ---- a/wpa_supplicant/Makefile -+++ b/wpa_supplicant/Makefile -@@ -193,6 +193,10 @@ ifdef CONFIG_HE_OVERRIDES - CFLAGS += -DCONFIG_HE_OVERRIDES - endif - -+ifdef CONFIG_EHT_OVERRIDES -+CFLAGS += -DCONFIG_EHT_OVERRIDES -+endif -+ - ifndef CONFIG_BACKEND - CONFIG_BACKEND=file - endif -@@ -942,6 +946,9 @@ endif - ifdef CONFIG_IEEE80211AX - OBJS += ../src/ap/ieee802_11_he.o - endif -+ifdef CONFIG_IEEE80211BE -+OBJS += ../src/ap/ieee802_11_eht.o -+endif - ifdef CONFIG_WNM_AP - CFLAGS += -DCONFIG_WNM_AP - OBJS += ../src/ap/wnm_ap.o -@@ -971,6 +978,10 @@ ifdef CONFIG_IEEE80211AX - CFLAGS += -DCONFIG_IEEE80211AX - endif - -+ifdef CONFIG_IEEE80211BE -+CFLAGS += -DCONFIG_IEEE80211BE -+endif -+ - ifdef NEED_AP_MLME - OBJS += ../src/ap/wmm.o - OBJS += ../src/ap/ap_list.o -diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c -index 5c65d2dd68cc..a9d995af7719 100644 ---- a/wpa_supplicant/ap.c -+++ b/wpa_supplicant/ap.c -@@ -395,6 +395,11 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s, - HT_CAP_INFO_TX_STBC | - HT_CAP_INFO_MAX_AMSDU_SIZE); - -+ if (mode->eht_capab[wpas_mode_to_ieee80211_mode( -+ ssid->mode)].eht_supported && -+ ssid->eht) -+ conf->ieee80211be = 1; -+ - /* check this before VHT, because setting oper chan - * width and friends is the same call for HE and VHT - * and checks if conf->ieee8021ax == 1 */ -diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c -index 8274ec9e53d4..c2e24125ae5a 100644 ---- a/wpa_supplicant/config.c -+++ b/wpa_supplicant/config.c -@@ -2764,6 +2764,9 @@ static const struct parse_data ssid_fields[] = { - #ifdef CONFIG_HE_OVERRIDES - { INT_RANGE(disable_he, 0, 1)}, - #endif /* CONFIG_HE_OVERRIDES */ -+#ifdef CONFIG_EHT_OVERRIDES -+ { INT_RANGE(disable_eht, 0, 1)}, -+#endif /* CONFIG_EHT_OVERRIDES */ - { INT(ap_max_inactivity) }, - { INT(dtim_period) }, - { INT(beacon_int) }, -@@ -3273,6 +3276,7 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid) - ssid->ht = 1; - ssid->vht = 1; - ssid->he = 1; -+ ssid->eht = 1; - #ifdef IEEE8021X_EAPOL - ssid->eapol_flags = DEFAULT_EAPOL_FLAGS; - ssid->eap_workaround = DEFAULT_EAP_WORKAROUND; -diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c -index d5187c95aabb..58346e02ffc3 100644 ---- a/wpa_supplicant/config_file.c -+++ b/wpa_supplicant/config_file.c -@@ -887,6 +887,9 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) - #ifdef CONFIG_HE_OVERRIDES - INT(disable_he); - #endif /* CONFIG_HE_OVERRIDES */ -+#ifdef CONFIG_EHT_OVERRIDES -+ INT(disable_eht); -+#endif /* CONFIG_EHT_OVERRIDES */ - INT(disable_40mhz_scan); - INT(beacon_tx_mode); - INT(enable_160mhz_bw); -diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h -index 395b7e517fd0..4ac5324aea8e 100644 ---- a/wpa_supplicant/config_ssid.h -+++ b/wpa_supplicant/config_ssid.h -@@ -567,6 +567,8 @@ struct wpa_ssid { - - int he; - -+ int eht; -+ - int max_oper_chwidth; - - unsigned int vht_center_freq1; -@@ -814,6 +816,16 @@ struct wpa_ssid { - int disable_he; - #endif /* CONFIG_HE_OVERRIDES */ - -+#ifdef CONFIG_EHT_OVERRIDES -+ /** -+ * disable_eht - Disable EHT (IEEE 802.11be) for this network -+ * -+ * By default, use it if it is available, but this can be configured -+ * to 1 to have it disabled. -+ */ -+ int disable_eht; -+#endif /* CONFIG_EHT_OVERRIDES */ -+ - /** - * ap_max_inactivity - Timeout in seconds to detect STA's inactivity - * -diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c -index b53a538bec54..45befc9f1dc0 100644 ---- a/wpa_supplicant/ctrl_iface.c -+++ b/wpa_supplicant/ctrl_iface.c -@@ -2306,11 +2306,12 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, - - if (wpa_s->connection_set && - (wpa_s->connection_ht || wpa_s->connection_vht || -- wpa_s->connection_he)) { -+ wpa_s->connection_he || wpa_s->connection_eht)) { - ret = os_snprintf(pos, end - pos, - "wifi_generation=%u\n", -- wpa_s->connection_he ? 6 : -- (wpa_s->connection_vht ? 5 : 4)); -+ wpa_s->connection_eht ? 7 : -+ (wpa_s->connection_he ? 6 : -+ (wpa_s->connection_vht ? 5 : 4))); - if (os_snprintf_error(end - pos, ret)) - return pos - buf; - pos += ret; -diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c -index 13929de49c97..d53e54e65408 100644 ---- a/wpa_supplicant/events.c -+++ b/wpa_supplicant/events.c -@@ -2952,6 +2952,8 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s, - BAND_2_4_GHZ); - wpa_s->connection_he = req_elems.he_capabilities && - resp_elems.he_capabilities; -+ wpa_s->connection_eht = req_elems.eht_capabilities && -+ resp_elems.eht_capabilities; - } - } - -diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c -index 1dc7001a7305..9f37e64fe85c 100644 ---- a/wpa_supplicant/sme.c -+++ b/wpa_supplicant/sme.c -@@ -1980,6 +1980,9 @@ mscs_fail: - #ifdef CONFIG_HE_OVERRIDES - wpa_supplicant_apply_he_overrides(wpa_s, ssid, ¶ms); - #endif /* CONFIG_HE_OVERRIDES */ -+#ifdef CONFIG_EHT_OVERRIDES -+ wpa_supplicant_apply_eht_overrides(wpa_s, ssid, ¶ms); -+#endif /* CONFIG_EHT_OVERRIDES */ - #ifdef CONFIG_IEEE80211R - if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies && - get_ie(wpa_s->sme.ft_ies, wpa_s->sme.ft_ies_len, -diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c -index 23e09a66e259..8e5a8ff2d1e5 100644 ---- a/wpa_supplicant/wpa_cli.c -+++ b/wpa_supplicant/wpa_cli.c -@@ -1471,6 +1471,9 @@ static const char *network_fields[] = { - #ifdef CONFIG_HE_OVERRIDES - "disable_he", - #endif /* CONFIG_HE_OVERRIDES */ -+#ifdef CONFIG_EHT_OVERRIDES -+ "disable_eht", -+#endif /* CONFIG_EHT_OVERRIDES */ - "ap_max_inactivity", "dtim_period", "beacon_int", - #ifdef CONFIG_MACSEC - "macsec_policy", -diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c -index 07cd01c65776..593e5b851616 100644 ---- a/wpa_supplicant/wpa_supplicant.c -+++ b/wpa_supplicant/wpa_supplicant.c -@@ -2584,10 +2584,18 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s, - - /* Allow HE on 2.4 GHz without VHT: see nl80211_put_freq_params() */ - if (is_24ghz) { -+#ifdef CONFIG_EHT_OVERRIDES -+ if (is_24ghz && ssid->disable_eht) -+ freq->eht_enabled = 0; -+ else -+#endif /* CONFIG_EHT_OVERRIDES */ -+ freq->eht_enabled = mode->eht_capab[ieee80211_mode].eht_supported; -+ - #ifdef CONFIG_HE_OVERRIDES -- if (ssid->disable_he) -+ if (ssid->disable_he) { - freq->he_enabled = 0; -- else -+ freq->eht_enabled = 0; -+ } else - #endif /* CONFIG_HE_OVERRIDES */ - freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported; - -@@ -2691,6 +2699,13 @@ skip_vht80: - vht_freq.he_enabled = 0; - #endif /* CONFIG_HE_OVERRIDES */ - -+#ifdef CONFIG_EHT_OVERRIDES -+skip_vht80: -+ if (ssid->disable_eht) -+ vht_freq.eht_enabled = 0; -+#endif /* CONFIG_EHT_OVERRIDES */ -+ -+ - #ifdef CONFIG_HT_OVERRIDES - skip_ht40: - #endif /* CONFIG_HT_OVERRIDES */ -@@ -2845,6 +2860,12 @@ skip_to_6ghz: - freq->he_enabled = 0; - } - #endif /* CONFIG_HE_OVERRIDES */ -+#ifdef CONFIG_EHT_OVERRIDES -+ if (ssid->disable_eht) { -+ vht_freq.eht_enabled = 0; -+ freq->eht_enabled = 0; -+ } -+#endif /* CONFIG_EHT_OVERRIDES */ - if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq, - freq->channel, ssid->enable_edmg, - ssid->edmg_channel, freq->ht_enabled, -@@ -4061,6 +4082,9 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) - #ifdef CONFIG_HE_OVERRIDES - wpa_supplicant_apply_he_overrides(wpa_s, ssid, ¶ms); - #endif /* CONFIG_HE_OVERRIDES */ -+#ifdef CONFIG_EHT_OVERRIDES -+ wpa_supplicant_apply_eht_overrides(wpa_s, ssid, ¶ms); -+#endif /* CONFIG_EHT_OVERRIDES */ - - #ifdef CONFIG_P2P - /* -@@ -5857,6 +5881,17 @@ void wpa_supplicant_apply_he_overrides( - } - #endif /* CONFIG_HE_OVERRIDES */ - -+#ifdef CONFIG_EHT_OVERRIDES -+void wpa_supplicant_apply_eht_overrides( -+ struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, -+ struct wpa_driver_associate_params *params) -+{ -+ if (!ssid) -+ return; -+ -+ params->disable_eht = ssid->disable_eht; -+} -+#endif /* CONFIG_EHT_OVERRIDES */ - - static int pcsc_reader_init(struct wpa_supplicant *wpa_s) - { -diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h -index 5fa765fda25c..fd75d1bfe813 100644 ---- a/wpa_supplicant/wpa_supplicant_i.h -+++ b/wpa_supplicant/wpa_supplicant_i.h -@@ -958,6 +958,7 @@ struct wpa_supplicant { - unsigned int connection_ht:1; - unsigned int connection_vht:1; - unsigned int connection_he:1; -+ unsigned int connection_eht:1; - unsigned int disable_mbo_oce:1; - - struct os_reltime last_mac_addr_change; -@@ -1532,6 +1533,9 @@ void wpa_supplicant_apply_vht_overrides( - void wpa_supplicant_apply_he_overrides( - struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, - struct wpa_driver_associate_params *params); -+void wpa_supplicant_apply_eht_overrides( -+ struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, -+ struct wpa_driver_associate_params *params); - - int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); - int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s, --- -2.7.4 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-004-eht-operating-channel-width-configuration.patch b/feeds/ipq95xx/hostapd/patches/q02-004-eht-operating-channel-width-configuration.patch deleted file mode 100644 index be9802bc7..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-004-eht-operating-channel-width-configuration.patch +++ /dev/null @@ -1,126 +0,0 @@ -From 69e25643c80531592bd048ba08ff66d14aee4ca5 Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Mon, 20 Sep 2021 13:53:40 -0700 -Subject: [PATCH 04/23] eht: operating channel width configuration - -Add new configuration options to configure EHT operating channel width -and center frequency. - -Signed-off-by: Aloka Dixit ---- - hostapd/config_file.c | 4 ++++ - hostapd/hostapd.conf | 9 +++++++++ - src/ap/ap_config.h | 20 ++++++++++++++++++++ - src/ap/ctrl_iface_ap.c | 13 +++++++++++++ - 4 files changed, 46 insertions(+) - ---- a/hostapd/config_file.c -+++ b/hostapd/config_file.c -@@ -4626,6 +4626,10 @@ static int hostapd_config_fill(struct ho - #ifdef CONFIG_IEEE80211BE - } else if (os_strcmp(buf, "ieee80211be") == 0) { - conf->ieee80211be = atoi(pos); -+ } else if (os_strcmp(buf, "eht_oper_chwidth") == 0) { -+ conf->eht_oper_chwidth = atoi(pos); -+ } else if (os_strcmp(buf, "eht_oper_centr_freq_seg0_idx") == 0) { -+ conf->eht_oper_centr_freq_seg0_idx = atoi(pos); - #endif /* CONFIG_IEEE80211BE */ - } else { - wpa_printf(MSG_ERROR, ---- a/hostapd/hostapd.conf -+++ b/hostapd/hostapd.conf -@@ -973,6 +973,15 @@ wmm_ac_vo_acm=0 - #disable_11be: Boolean (0/1) to disable EHT for a specific BSS - #disable_11be=0 - -+# EHT operating channel information; see matching he_* parameters for details. -+# The field eht_oper_centr_freq_seg0_idx field is used to indicate center -+# frequency of 40, 80 and 160 MHz bandwidth operation. -+# In 6 GHz band, eht_oper_chwidth is ignored and the channel width is -+# derived from the configured operating class (IEEE P802.11be/D1.1, July 2021, -+# Annex E, E.1 Country information and operating classes). -+#eht_oper_chwidth -+#eht_oper_centr_freq_seg0_idx -+ - ##### IEEE 802.1X-2004 related configuration ################################## - - # Require IEEE 802.1X authorization ---- a/src/ap/ap_config.h -+++ b/src/ap/ap_config.h -@@ -1113,6 +1113,10 @@ struct hostapd_config { - #endif /* CONFIG_AIRTIME_POLICY */ - - int ieee80211be; -+#ifdef CONFIG_IEEE80211BE -+ u8 eht_oper_chwidth; -+ u8 eht_oper_centr_freq_seg0_idx; -+#endif /* CONFIG_IEEE80211BE */ - }; - - static inline u8 hostapd_get_he_6ghz_reg_pwr_type(struct hostapd_config *conf) -@@ -1127,6 +1131,10 @@ static inline u8 hostapd_get_he_6ghz_reg - - static inline u8 hostapd_get_oper_chwidth(struct hostapd_config *conf) - { -+#ifdef CONFIG_IEEE80211BE -+ if (conf->ieee80211be) -+ return conf->eht_oper_chwidth; -+#endif /* CONFIG_IEEE80211BE */ - #ifdef CONFIG_IEEE80211AX - if (conf->ieee80211ax) - return conf->he_oper_chwidth; -@@ -1137,6 +1145,10 @@ static inline u8 hostapd_get_oper_chwidt - static inline void - hostapd_set_oper_chwidth(struct hostapd_config *conf, u8 oper_chwidth) - { -+#ifdef CONFIG_IEEE80211BE -+ if (conf->ieee80211be) -+ conf->eht_oper_chwidth = oper_chwidth; -+#endif /* CONFIG_IEEE80211BE */ - #ifdef CONFIG_IEEE80211AX - if (conf->ieee80211ax) - conf->he_oper_chwidth = oper_chwidth; -@@ -1147,6 +1159,10 @@ hostapd_set_oper_chwidth(struct hostapd_ - static inline u8 - hostapd_get_oper_centr_freq_seg0_idx(struct hostapd_config *conf) - { -+#ifdef CONFIG_IEEE80211BE -+ if (conf->ieee80211be) -+ return conf->eht_oper_centr_freq_seg0_idx; -+#endif /* CONFIG_IEEE80211BE */ - #ifdef CONFIG_IEEE80211AX - if (conf->ieee80211ax) - return conf->he_oper_centr_freq_seg0_idx; -@@ -1158,6 +1174,10 @@ static inline void - hostapd_set_oper_centr_freq_seg0_idx(struct hostapd_config *conf, - u8 oper_centr_freq_seg0_idx) - { -+#ifdef CONFIG_IEEE80211BE -+ if (conf->ieee80211be) -+ conf->eht_oper_centr_freq_seg0_idx = oper_centr_freq_seg0_idx; -+#endif /* CONFIG_IEEE80211BE */ - #ifdef CONFIG_IEEE80211AX - if (conf->ieee80211ax) - conf->he_oper_centr_freq_seg0_idx = oper_centr_freq_seg0_idx; ---- a/src/ap/ctrl_iface_ap.c -+++ b/src/ap/ctrl_iface_ap.c -@@ -1050,6 +1050,19 @@ int hostapd_ctrl_iface_status(struct hos - return len; - len += ret; - -+#ifdef CONFIG_IEEE80211BE -+ if (iface->conf->ieee80211be && !hapd->conf->disable_11be) { -+ ret = os_snprintf(buf + len, buflen - len, -+ "eht_oper_chwidth=%d\n" -+ "eht_oper_centr_freq_seg0_idx=%d\n", -+ iface->conf->eht_oper_chwidth, -+ iface->conf->eht_oper_centr_freq_seg0_idx); -+ if (os_snprintf_error(buflen - len, ret)) -+ return len; -+ len += ret; -+ } -+#endif /* CONFIG_IEEE80211BE */ -+ - #ifdef CONFIG_IEEE80211AX - if (iface->conf->ieee80211ax && !hapd->conf->disable_11ax) { - ret = os_snprintf(buf + len, buflen - len, diff --git a/feeds/ipq95xx/hostapd/patches/q02-005-eht-beamforming-capabilities-configuration.patch b/feeds/ipq95xx/hostapd/patches/q02-005-eht-beamforming-capabilities-configuration.patch deleted file mode 100644 index 716e741b3..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-005-eht-beamforming-capabilities-configuration.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 23a71230cec01409bc535e110a52e70ba2511319 Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Tue, 29 Jun 2021 17:20:42 -0700 -Subject: [PATCH 05/23] eht: beamforming capabilities configuration - -Add configuration options to set SU/MU beamforming capabilities. - -Signed-off-by: Aloka Dixit ---- - hostapd/config_file.c | 6 ++++++ - src/ap/ap_config.h | 10 ++++++++++ - 2 files changed, 16 insertions(+) - -diff --git a/hostapd/config_file.c b/hostapd/config_file.c -index b15f94889f16..dada06c365b2 100644 ---- a/hostapd/config_file.c -+++ b/hostapd/config_file.c -@@ -4733,6 +4733,12 @@ static int hostapd_config_fill(struct hostapd_config *conf, - conf->eht_oper_chwidth = atoi(pos); - } else if (os_strcmp(buf, "eht_oper_centr_freq_seg0_idx") == 0) { - conf->eht_oper_centr_freq_seg0_idx = atoi(pos); -+ } else if (os_strcmp(buf, "eht_su_beamformer") == 0) { -+ conf->eht_phy_capab.su_beamformer = atoi(pos); -+ } else if (os_strcmp(buf, "eht_su_beamformee") == 0) { -+ conf->eht_phy_capab.su_beamformee = atoi(pos); -+ } else if (os_strcmp(buf, "eht_mu_beamformer") == 0) { -+ conf->eht_phy_capab.mu_beamformer = atoi(pos); - #endif /* CONFIG_IEEE80211BE */ - } else { - wpa_printf(MSG_ERROR, -diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h -index 0670a7c3380c..69f8ddac0396 100644 ---- a/src/ap/ap_config.h -+++ b/src/ap/ap_config.h -@@ -937,6 +937,15 @@ struct spatial_reuse { - u8 srg_partial_bssid_bitmap[8]; - }; - -+/** -+ * struct eht_phy_capabilities_info - EHT PHY capabilities -+ */ -+struct eht_phy_capabilities_info { -+ bool su_beamformer; -+ bool su_beamformee; -+ bool mu_beamformer; -+}; -+ - /** - * struct hostapd_config - Per-radio interface configuration - */ -@@ -1106,6 +1115,7 @@ struct hostapd_config { - #ifdef CONFIG_IEEE80211BE - u8 eht_oper_chwidth; - u8 eht_oper_centr_freq_seg0_idx; -+ struct eht_phy_capabilities_info eht_phy_capab; - #endif /* CONFIG_IEEE80211BE */ - }; - --- -2.31.1 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-006-eht-macro-for-320-MHZ-channel-width.patch b/feeds/ipq95xx/hostapd/patches/q02-006-eht-macro-for-320-MHZ-channel-width.patch deleted file mode 100644 index 2395ecfe8..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-006-eht-macro-for-320-MHZ-channel-width.patch +++ /dev/null @@ -1,33 +0,0 @@ -From d8b4c1a635e5aecf9afed3861cfad92bf75c823c Mon Sep 17 00:00:00 2001 -From: Muna Sinada -Date: Thu, 15 Jul 2021 10:26:21 -0700 -Subject: [PATCH 06/23] eht: macro for 320 MHZ channel width - -Add CHANWIDTH_320MHZ macro for 320 MHz bandwidth. - -Signed-off-by: Muna Sinada -Signed-off-by: Aloka Dixit ---- - src/common/ieee802_11_defs.h | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/src/common/ieee802_11_defs.h -+++ b/src/common/ieee802_11_defs.h -@@ -1348,7 +1348,7 @@ struct ieee80211_ampe_ie { - - #define VHT_RX_NSS_MAX_STREAMS 8 - --/* VHT/EDMG channel widths */ -+/* EHT/HE/VHT/EDMG channel widths */ - #define CHANWIDTH_USE_HT 0 - #define CHANWIDTH_80MHZ 1 - #define CHANWIDTH_160MHZ 2 -@@ -1358,7 +1358,7 @@ struct ieee80211_ampe_ie { - #define CHANWIDTH_6480MHZ 6 - #define CHANWIDTH_8640MHZ 7 - #define CHANWIDTH_40MHZ_6GHZ 8 -- -+#define CHANWIDTH_320MHZ 9 - #define HE_NSS_MAX_STREAMS 8 - - #define OUI_MICROSOFT 0x0050f2 /* Microsoft (also used in Wi-Fi specs) diff --git a/feeds/ipq95xx/hostapd/patches/q02-007-eht-support-for-operating-class-137.patch b/feeds/ipq95xx/hostapd/patches/q02-007-eht-support-for-operating-class-137.patch deleted file mode 100644 index 6c2ed1757..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-007-eht-support-for-operating-class-137.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 0e520bc273ba6cb91137a19bb86c4b1ef8be43fe Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Mon, 20 Sep 2021 13:57:58 -0700 -Subject: [PATCH 07/23] eht: support for operating class 137 - -IEEE P802.11be/D1.4, January 2022, Annex E, section E.1 adds a new -value 137 to be used for 320 Mhz bandwidth in 6GHz band. -Modify existing functions related to operating class to include this -value. - -Signed-off-by: Aloka Dixit ---- - src/common/ieee802_11_common.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c -index 5b74ddcdf62b..d7f8914e35bf 100644 ---- a/src/common/ieee802_11_common.c -+++ b/src/common/ieee802_11_common.c -@@ -1052,6 +1052,9 @@ enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq, - case CHANWIDTH_80P80MHZ: - *op_class = 135; - break; -+ case CHANWIDTH_320MHZ: -+ *op_class = 137; -+ break; - default: - if (sec_channel) - *op_class = 132; -@@ -1444,6 +1447,7 @@ static int ieee80211_chan_to_freq_global(u8 op_class, u8 chan) - case 133: /* UHB channels, 80 MHz: 7, 23, 39.. */ - case 134: /* UHB channels, 160 MHz: 15, 47, 79.. */ - case 135: /* UHB channels, 80+80 MHz: 7, 23, 39.. */ -+ case 137: /* UHB channels, 320 MHz: 31, 63, 95, 127, 159, 191 */ - if (chan < 1 || chan > 233) - return -1; - return 5950 + chan * 5; -@@ -2279,7 +2283,11 @@ bool is_6ghz_freq(int freq) - - bool is_6ghz_op_class(u8 op_class) - { -+#ifdef CONFIG_IEEE80211BE -+ return op_class >= 131 && op_class <= 137; -+#else - return op_class >= 131 && op_class <= 136; -+#endif /* CONFIG_IEEE80211BE */ - } - - -@@ -2585,6 +2593,8 @@ int op_class_to_bandwidth(u8 op_class) - return 160; - case 136: /* UHB channels, 20 MHz: 2 */ - return 20; -+ case 137: /* UHB channels, 320 MHz: 31 63 95 127 159 191 */ -+ return 320; - case 180: /* 60 GHz band, channels 1..8 */ - return 2160; - case 181: /* 60 GHz band, EDMG CB2, channels 9..15 */ -@@ -2647,6 +2657,8 @@ int op_class_to_ch_width(u8 op_class) - return CHANWIDTH_80P80MHZ; - case 136: /* UHB channels, 20 MHz: 2 */ - return CHANWIDTH_USE_HT; -+ case 137: /* 320 MHz: 31 63 95 127 159 191 */ -+ return CHANWIDTH_320MHZ; - case 180: /* 60 GHz band, channels 1..8 */ - return CHANWIDTH_2160MHZ; - case 181: /* 60 GHz band, EDMG CB2, channels 9..15 */ --- -2.31.1 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-008-eht-add-capabilities-element-in-management-frames.patch b/feeds/ipq95xx/hostapd/patches/q02-008-eht-add-capabilities-element-in-management-frames.patch deleted file mode 100644 index 435d601e2..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-008-eht-add-capabilities-element-in-management-frames.patch +++ /dev/null @@ -1,316 +0,0 @@ -From add539d6f28cce4519abad790fd4e423078b4ab7 Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Tue, 29 Jun 2021 16:46:36 -0700 -Subject: [PATCH 08/23] eht: add capabilities element in management frames. - -Add EHT capabilities IE in beacons, probe responses and association -response frames. - -Signed-off-by: Aloka Dixit -Signed-off-by: Pradeep Kumar Chitrapu ---- - hostapd/Makefile | 1 + - src/ap/beacon.c | 22 ++++++ - src/ap/ieee802_11.c | 10 +++ - src/ap/ieee802_11.h | 4 ++ - src/ap/ieee802_11_eht.c | 154 ++++++++++++++++++++++++++++++++++++++++ - src/drivers/driver.h | 14 ++++ - 6 files changed, 205 insertions(+) - create mode 100644 src/ap/ieee802_11_eht.c - ---- a/hostapd/Makefile -+++ b/hostapd/Makefile -@@ -351,6 +351,7 @@ endif - - ifdef CONFIG_IEEE80211BE - CFLAGS += -DCONFIG_IEEE80211BE -+OBJS += ../src/ap/ieee802_11_eht.o - endif - - ifdef CONFIG_MBO ---- a/src/ap/beacon.c -+++ b/src/ap/beacon.c -@@ -639,6 +639,11 @@ static u8 * hostapd_gen_probe_resp(struc - } - #endif /* CONFIG_IEEE80211AX */ - -+#ifdef CONFIG_IEEE80211BE -+ if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) -+ buflen += hostapd_eid_eht_capab_len(hapd, IEEE80211_MODE_AP); -+#endif /* CONFIG_IEEE80211BE */ -+ - buflen += hostapd_eid_mbssid_len(hapd_probed, WLAN_FC_STYPE_PROBE_RESP, - NULL, known_bss, known_bss_len, NULL); - buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP); -@@ -780,6 +785,11 @@ static u8 * hostapd_gen_probe_resp(struc - } - #endif /* CONFIG_IEEE80211AX */ - -+#ifdef CONFIG_IEEE80211BE -+ if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) -+ pos = hostapd_eid_eht_capab(hapd, pos, IEEE80211_MODE_AP); -+#endif /* CONFIG_IEEE80211BE */ -+ - #ifdef CONFIG_IEEE80211AC - if (hapd->conf->vendor_vht) - pos = hostapd_eid_vendor_vht(hapd, pos); -@@ -1707,6 +1717,11 @@ int ieee802_11_build_ap_params(struct ho - } - #endif /* CONFIG_IEEE80211AX */ - -+#ifdef CONFIG_IEEE80211BE -+ if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) -+ tail_len += hostapd_eid_eht_capab_len(hapd, IEEE80211_MODE_AP); -+#endif /* CONFIG_IEEE80211BE */ -+ - if (hapd->iconf->ema) - tail_len += 5; /* Multiple BSSID Configuration element */ - tail_len += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_BEACON); -@@ -1857,6 +1872,12 @@ int ieee802_11_build_ap_params(struct ho - } - #endif /* CONFIG_IEEE80211AX */ - -+#ifdef CONFIG_IEEE80211BE -+ if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) -+ tailpos = hostapd_eid_eht_capab(hapd, tailpos, -+ IEEE80211_MODE_AP); -+#endif /* CONFIG_IEEE80211BE */ -+ - #ifdef CONFIG_IEEE80211AC - if (hapd->conf->vendor_vht) - tailpos = hostapd_eid_vendor_vht(hapd, tailpos); ---- a/src/ap/ieee802_11.c -+++ b/src/ap/ieee802_11.c -@@ -5083,6 +5083,11 @@ static u16 send_assoc_resp(struct hostap - if (sta && sta->dpp_pfs) - buflen += 5 + sta->dpp_pfs->curve->prime_len; - #endif /* CONFIG_DPP2 */ -+#ifdef CONFIG_IEEE80211BE -+ if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) -+ buflen += hostapd_eid_eht_capab_len(hapd, IEEE80211_MODE_AP); -+#endif /* CONFIG_IEEE80211BE */ -+ - buf = os_zalloc(buflen); - if (!buf) { - res = WLAN_STATUS_UNSPECIFIED_FAILURE; -@@ -5197,6 +5202,11 @@ static u16 send_assoc_resp(struct hostap - } - #endif /* CONFIG_IEEE80211AX */ - -+#ifdef CONFIG_IEEE80211BE -+ if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) -+ p = hostapd_eid_eht_capab(hapd, p, IEEE80211_MODE_AP); -+#endif /* CONFIG_IEEE80211BE */ -+ - p = hostapd_eid_ext_capab(hapd, p); - p = hostapd_eid_bss_max_idle_period(hapd, p); - if (sta && sta->qos_map_enabled) ---- a/src/ap/ieee802_11.h -+++ b/src/ap/ieee802_11.h -@@ -215,5 +215,8 @@ void auth_sae_process_commit(void *eloop - u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len); - size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type); - u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type); -- -+size_t hostapd_eid_eht_capab_len(struct hostapd_data *hapd, -+ enum ieee80211_op_mode opmode); -+u8 * hostapd_eid_eht_capab(struct hostapd_data *hapd, u8 *eid, -+ enum ieee80211_op_mode opmode); - #endif /* IEEE802_11_H */ ---- /dev/null -+++ b/src/ap/ieee802_11_eht.c -@@ -0,0 +1,164 @@ -+/* -+ * hostapd / IEEE 802.11be EHT -+ * -+ * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. -+ * -+ * 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. -+ */ -+ -+#include "utils/includes.h" -+#include "utils/common.h" -+#include "hostapd.h" -+#include "ieee802_11.h" -+ -+static u8 ieee80211_eht_ppet_size(const u8 *ppe_thres, const u8 *phy_cap_info) -+{ -+ u8 sz = 0, ru; -+ -+ if ((phy_cap_info[EHT_PHYCAP_PPE_THRESHOLD_PRESENT_IDX] & -+ EHT_PHYCAP_PPE_THRESHOLD_PRESENT) == 0) -+ return 0; -+ -+ ru = (ppe_thres[0] & -+ (EHT_PPE_THRES_RU_INDEX_MASK << EHT_PPE_THRES_RU_INDEX_SHIFT)); -+ while (ru) { -+ if (ru & 0x1) -+ sz++; -+ ru >>= 1; -+ } -+ -+ ru = (ppe_thres[1] & (EHT_PPE_THRES_RU_INDEX_MASK >> -+ (8 - EHT_PPE_THRES_RU_INDEX_SHIFT))); -+ while (ru) { -+ if (ru & 0x1) -+ sz++; -+ ru >>= 1; -+ } -+ -+ sz *= (1 + (ppe_thres[0] & EHT_PPE_THRES_NSS_MASK)); -+ sz = (sz * 6) + 9; -+ if (sz % 8) -+ sz += 8; -+ sz /= 8; -+ -+ return sz; -+} -+ -+ -+static u8 ieee80211_eht_mcs_set_size(const u8 *he_phy_cap, -+ const u8 *eht_phy_cap) -+{ -+ u8 sz = EHT_PHYCAP_MCS_NSS_LEN_20MHZ_PLUS; -+ -+ if ((he_phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] & -+ (HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G | -+ HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G | -+ HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G | -+ HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G)) == 0) -+ return EHT_PHYCAP_MCS_NSS_LEN_20MHZ_ONLY; -+ -+ if (he_phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] & -+ (HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G | -+ HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G)) -+ sz += EHT_PHYCAP_MCS_NSS_LEN_20MHZ_PLUS; -+ -+ if (eht_phy_cap[EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_IDX] & -+ EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_MASK) -+ sz += EHT_PHYCAP_MCS_NSS_LEN_20MHZ_PLUS; -+ -+ return sz; -+} -+ -+ -+size_t hostapd_eid_eht_capab_len(struct hostapd_data *hapd, -+ enum ieee80211_op_mode opmode) -+{ -+ struct hostapd_hw_modes *mode; -+ struct eht_capabilities *eht_cap; -+ size_t len = 3 + EHT_MAC_CAPAB_MAX_LEN + EHT_PHY_CAPAB_MAX_LEN; -+ -+ mode = hapd->iface->current_mode; -+ if (!mode) -+ return 0; -+ -+ eht_cap = &mode->eht_capab[opmode]; -+ if (!eht_cap->eht_supported) -+ return 0; -+ -+ len += ieee80211_eht_mcs_set_size(mode->he_capab[opmode].phy_cap, -+ eht_cap->phy_cap); -+ len += ieee80211_eht_ppet_size(eht_cap->ppet, eht_cap->phy_cap); -+ -+ return len; -+} -+ -+u8 * hostapd_eid_eht_capab(struct hostapd_data *hapd, u8 *eid, -+ enum ieee80211_op_mode opmode) -+{ -+ struct hostapd_hw_modes *mode; -+ struct eht_capabilities *eht_cap; -+ struct ieee80211_eht_capabilities *cap; -+ size_t mcs_nss_len, ppe_thresh_len; -+ u8 *pos = eid, *length_pos; -+ -+ mode = hapd->iface->current_mode; -+ if (!mode) -+ return eid; -+ -+ eht_cap = &mode->eht_capab[opmode]; -+ if (!eht_cap->eht_supported) -+ return eid; -+ -+ *pos++ = WLAN_EID_EXTENSION; -+ length_pos = pos++; -+ *pos++ = WLAN_EID_EXT_EHT_CAPABILITY; -+ -+ cap = (struct ieee80211_eht_capabilities *) pos; -+ os_memset(cap, 0, sizeof(*cap)); -+ os_memcpy(cap->mac_cap, eht_cap->mac_cap, EHT_MAC_CAPAB_MAX_LEN); -+ os_memcpy(cap->phy_cap, eht_cap->phy_cap, EHT_PHY_CAPAB_MAX_LEN); -+ -+ if (!is_6ghz_op_class(hapd->iconf->op_class)) -+ cap->phy_cap[EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_IDX] &= -+ ~EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_MASK; -+ if (!hapd->iface->conf->eht_phy_capab.su_beamformer) -+ cap->phy_cap[EHT_PHYCAP_SU_BEAMFORMER_IDX] &= -+ ~EHT_PHYCAP_SU_BEAMFORMER; -+ -+ if (!hapd->iface->conf->eht_phy_capab.su_beamformee) -+ cap->phy_cap[EHT_PHYCAP_SU_BEAMFORMEE_IDX] &= -+ ~EHT_PHYCAP_SU_BEAMFORMEE; -+ -+ if (!hapd->iface->conf->eht_phy_capab.mu_beamformer) -+ cap->phy_cap[EHT_PHYCAP_MU_BEAMFORMER_IDX] &= -+ ~EHT_PHYCAP_MU_BEAMFORMER_MASK; -+ -+ pos = cap->optional; -+ -+ mcs_nss_len = ieee80211_eht_mcs_set_size(mode->he_capab[opmode].phy_cap, -+ eht_cap->phy_cap); -+ if (mcs_nss_len) { -+ os_memcpy(pos, eht_cap->mcs, mcs_nss_len); -+ pos += mcs_nss_len; -+ } -+ -+ ppe_thresh_len = ieee80211_eht_ppet_size(eht_cap->ppet, -+ eht_cap->phy_cap); -+ if (ppe_thresh_len) { -+ os_memcpy(pos, eht_cap->ppet, ppe_thresh_len); -+ pos += ppe_thresh_len; -+ } -+ -+ *length_pos = pos - (eid + 2); -+ return pos; -+} ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -201,6 +201,15 @@ struct he_capabilities { - u16 he_6ghz_capa; - }; - -+/* struct eht_capabilities - IEEE 802.11be EHT capabilities */ -+struct eht_capabilities { -+ u8 eht_supported; -+ u8 mac_cap[EHT_MAC_CAPAB_MAX_LEN]; -+ u8 phy_cap[EHT_PHY_CAPAB_MAX_LEN]; -+ u8 mcs[EHT_MCS_NSS_CAPAB_MAX_LEN]; -+ u8 ppet[EHT_PPE_THRESH_CAPAB_MAX_LEN]; -+}; -+ - #define HOSTAPD_MODE_FLAG_HT_INFO_KNOWN BIT(0) - #define HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN BIT(1) - -@@ -305,6 +314,11 @@ struct hostapd_hw_modes { - * supported in 6G band. - */ - s8 psd_values[NL80211_REG_NUM_POWER_MODES]; -+ -+ /** -+ * eht_capab - EHT (IEEE 802.11be) capabilities -+ */ -+ struct eht_capabilities eht_capab[IEEE80211_MODE_NUM]; - }; - - diff --git a/feeds/ipq95xx/hostapd/patches/q02-009-eht-add-operation-element-in-management-frames.patch b/feeds/ipq95xx/hostapd/patches/q02-009-eht-add-operation-element-in-management-frames.patch deleted file mode 100644 index 112591f98..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-009-eht-add-operation-element-in-management-frames.patch +++ /dev/null @@ -1,198 +0,0 @@ -From d0022739c2d8ae04151a1537d960daef280ca732 Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Tue, 15 Feb 2022 00:51:19 -0800 -Subject: [PATCH 09/23] eht: add operation element in management frames - -Add EHT operation element in beacon, probe response and association -response frames using the format described in IEEE P802.11be/D1.4, -January 2022, section 9.4.2.311. - -Length of this field is not yet provided in this version of the -specification, assume 1 byte for each field. - -Signed-off-by: Aloka Dixit -Signed-off-by: Muna Sinada ---- - src/ap/beacon.c | 16 ++++++++--- - src/ap/ieee802_11.c | 5 +++- - src/ap/ieee802_11.h | 1 + - src/ap/ieee802_11_eht.c | 51 ++++++++++++++++++++++++++++++++++++ - src/common/ieee802_11_defs.h | 10 +++++++ - 5 files changed, 78 insertions(+), 5 deletions(-) - ---- a/src/ap/beacon.c -+++ b/src/ap/beacon.c -@@ -640,8 +640,10 @@ static u8 * hostapd_gen_probe_resp(struc - #endif /* CONFIG_IEEE80211AX */ - - #ifdef CONFIG_IEEE80211BE -- if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) -+ if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) { - buflen += hostapd_eid_eht_capab_len(hapd, IEEE80211_MODE_AP); -+ buflen += (3 + sizeof(struct ieee80211_eht_operation)); -+ } - #endif /* CONFIG_IEEE80211BE */ - - buflen += hostapd_eid_mbssid_len(hapd_probed, WLAN_FC_STYPE_PROBE_RESP, -@@ -786,8 +788,10 @@ static u8 * hostapd_gen_probe_resp(struc - #endif /* CONFIG_IEEE80211AX */ - - #ifdef CONFIG_IEEE80211BE -- if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) -+ if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) { - pos = hostapd_eid_eht_capab(hapd, pos, IEEE80211_MODE_AP); -+ pos = hostapd_eid_eht_operation(hapd, pos, IEEE80211_MODE_AP); -+ } - #endif /* CONFIG_IEEE80211BE */ - - #ifdef CONFIG_IEEE80211AC -@@ -1718,8 +1722,10 @@ int ieee802_11_build_ap_params(struct ho - #endif /* CONFIG_IEEE80211AX */ - - #ifdef CONFIG_IEEE80211BE -- if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) -+ if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) { - tail_len += hostapd_eid_eht_capab_len(hapd, IEEE80211_MODE_AP); -+ tail_len += (3 + sizeof(struct ieee80211_eht_operation)); -+ } - #endif /* CONFIG_IEEE80211BE */ - - if (hapd->iconf->ema) -@@ -1873,9 +1879,12 @@ int ieee802_11_build_ap_params(struct ho - #endif /* CONFIG_IEEE80211AX */ - - #ifdef CONFIG_IEEE80211BE -- if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) -+ if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) { - tailpos = hostapd_eid_eht_capab(hapd, tailpos, - IEEE80211_MODE_AP); -+ tailpos = hostapd_eid_eht_operation(hapd, tailpos, -+ IEEE80211_MODE_AP); -+ } - #endif /* CONFIG_IEEE80211BE */ - - #ifdef CONFIG_IEEE80211AC ---- a/src/ap/ieee802_11.c -+++ b/src/ap/ieee802_11.c -@@ -5084,8 +5084,10 @@ static u16 send_assoc_resp(struct hostap - buflen += 5 + sta->dpp_pfs->curve->prime_len; - #endif /* CONFIG_DPP2 */ - #ifdef CONFIG_IEEE80211BE -- if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) -+ if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) { - buflen += hostapd_eid_eht_capab_len(hapd, IEEE80211_MODE_AP); -+ buflen += (3 + sizeof(struct ieee80211_eht_operation)); -+ } - #endif /* CONFIG_IEEE80211BE */ - - buf = os_zalloc(buflen); -@@ -5203,8 +5205,10 @@ static u16 send_assoc_resp(struct hostap - #endif /* CONFIG_IEEE80211AX */ - - #ifdef CONFIG_IEEE80211BE -- if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) -+ if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) { - p = hostapd_eid_eht_capab(hapd, p, IEEE80211_MODE_AP); -+ p = hostapd_eid_eht_operation(hapd, p, IEEE80211_MODE_AP); -+ } - #endif /* CONFIG_IEEE80211BE */ - - p = hostapd_eid_ext_capab(hapd, p); ---- a/src/ap/ieee802_11.h -+++ b/src/ap/ieee802_11.h -@@ -219,4 +219,6 @@ size_t hostapd_eid_eht_capab_len(struct - enum ieee80211_op_mode opmode); - u8 * hostapd_eid_eht_capab(struct hostapd_data *hapd, u8 *eid, - enum ieee80211_op_mode opmode); -+u8 * hostapd_eid_eht_operation(struct hostapd_data *hapd, u8 *eid, -+ enum ieee80211_op_mode opmode); - #endif /* IEEE802_11_H */ ---- a/src/ap/ieee802_11_eht.c -+++ b/src/ap/ieee802_11_eht.c -@@ -162,3 +162,60 @@ u8 * hostapd_eid_eht_capab(struct hostap - *length_pos = pos - (eid + 2); - return pos; - } -+ -+ -+u8 * hostapd_eid_eht_operation(struct hostapd_data *hapd, u8 *eid, -+ enum ieee80211_op_mode opmode) -+{ -+ struct hostapd_hw_modes *mode; -+ struct ieee80211_eht_operation *oper; -+ u8 *pos = eid, *length_pos, chwidth, seg0 = 0; -+ -+ mode = hapd->iface->current_mode; -+ if (!mode) -+ return eid; -+ -+ if (!mode->eht_capab[opmode].eht_supported) -+ return eid; -+ -+ *pos++ = WLAN_EID_EXTENSION; -+ length_pos = pos++; -+ *pos++ = WLAN_EID_EXT_EHT_OPERATION; -+ -+ oper = (struct ieee80211_eht_operation *) pos; -+ os_memset(oper, 0, sizeof(*oper)); -+ -+ if (is_6ghz_op_class(hapd->iconf->op_class)) -+ chwidth = op_class_to_ch_width(hapd->iconf->op_class); -+ else -+ chwidth = hapd->iconf->eht_oper_chwidth; -+ -+ seg0 = hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf); -+ -+ switch (chwidth) { -+ case CHANWIDTH_320MHZ: -+ *pos++ = EHT_OPERATION_CHANNEL_WIDTH_320MHZ; -+ break; -+ case CHANWIDTH_160MHZ: -+ *pos++ = EHT_OPERATION_CHANNEL_WIDTH_160MHZ; -+ break; -+ case CHANWIDTH_80MHZ: -+ *pos++ = EHT_OPERATION_CHANNEL_WIDTH_80MHZ; -+ break; -+ case CHANWIDTH_USE_HT: -+ if (seg0) -+ *pos++ = EHT_OPERATION_CHANNEL_WIDTH_40MHZ; -+ else -+ pos++; -+ break; -+ default: -+ return eid; -+ } -+ -+ if (!seg0) -+ seg0 = hapd->iconf->channel; -+ *pos++ = seg0; -+ -+ *length_pos = pos - (eid + 2); -+ return pos; -+} ---- a/src/common/ieee802_11_defs.h -+++ b/src/common/ieee802_11_defs.h -@@ -2476,6 +2476,11 @@ struct ieee80211_eht_operation { - u8 optional[]; - } STRUCT_PACKED; - -+#define EHT_OPERATION_CHANNEL_WIDTH_40MHZ 1 -+#define EHT_OPERATION_CHANNEL_WIDTH_80MHZ 2 -+#define EHT_OPERATION_CHANNEL_WIDTH_160MHZ 3 -+#define EHT_OPERATION_CHANNEL_WIDTH_320MHZ 4 -+ - /* IEEE P802.11be/D1.4, January 2022, section 9.4.2.313.3 */ - #define EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_IDX 0 - #define EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_MASK ((u8) BIT(1)) -@@ -2515,6 +2520,11 @@ struct ieee80211_eht_operation { - BIT(2) | BIT(3) | \ - BIT(4))) - -+#define EHT_OPERATION_CHANNEL_WIDTH_40MHZ 1 -+#define EHT_OPERATION_CHANNEL_WIDTH_80MHZ 2 -+#define EHT_OPERATION_CHANNEL_WIDTH_160MHZ 3 -+#define EHT_OPERATION_CHANNEL_WIDTH_320MHZ 4 -+ - /* IEEE P802.11ay/D4.0, 9.4.2.251 - EDMG Operation element */ - #define EDMG_BSS_OPERATING_CHANNELS_OFFSET 6 - #define EDMG_OPERATING_CHANNEL_WIDTH_OFFSET 7 diff --git a/feeds/ipq95xx/hostapd/patches/q02-010-nl80211-parse-EHT-capabilities-passed-by-kernel.patch b/feeds/ipq95xx/hostapd/patches/q02-010-nl80211-parse-EHT-capabilities-passed-by-kernel.patch deleted file mode 100644 index 9553c53a1..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-010-nl80211-parse-EHT-capabilities-passed-by-kernel.patch +++ /dev/null @@ -1,94 +0,0 @@ -From fe0a0d3556de5caa1498b8a406cd1c6496c5ad1e Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Tue, 29 Jun 2021 17:03:50 -0700 -Subject: [PATCH 10/23] nl80211: parse EHT capabilities passed by kernel - -Add nl80211 support to parse the EHT capabilities passed by the -kernel using new attributes added in NL80211_BAND_ATTR_IFTYPE_DATA. - -Signed-off-by: Aloka Dixit ---- - src/drivers/driver_nl80211_capa.c | 48 +++++++++++++++++++++++++++++-- - 1 file changed, 46 insertions(+), 2 deletions(-) - -diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c -index 200c545c2b70..b37167cc2075 100644 ---- a/src/drivers/driver_nl80211_capa.c -+++ b/src/drivers/driver_nl80211_capa.c -@@ -1774,12 +1774,14 @@ static int phy_info_rates(struct hostapd_hw_modes *mode, struct nlattr *tb) - } - - --static void phy_info_iftype_copy(struct he_capabilities *he_capab, -+static void phy_info_iftype_copy(struct hostapd_hw_modes *mode, - enum ieee80211_op_mode opmode, - struct nlattr **tb, struct nlattr **tb_flags) - { - enum nl80211_iftype iftype; - size_t len; -+ struct he_capabilities *he_capab = &mode->he_capab[opmode]; -+ struct eht_capabilities *eht_capab = &mode->eht_capab[opmode]; - - switch (opmode) { - case IEEE80211_MODE_INFRA: -@@ -1849,6 +1851,48 @@ static void phy_info_iftype_copy(struct he_capabilities *he_capab, - capa = nla_get_u16(tb[NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA]); - he_capab->he_6ghz_capa = le_to_host16(capa); - } -+ -+ if (!tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC] || -+ !tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY]) -+ return; -+ -+ eht_capab->eht_supported = 1; -+ -+ if (tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC]) { -+ len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC]); -+ if (len > sizeof(eht_capab->mac_cap)) -+ len = sizeof(eht_capab->mac_cap); -+ os_memcpy(eht_capab->mac_cap, -+ nla_data(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC]), -+ len); -+ } -+ -+ if (tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY]) { -+ len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY]); -+ if (len > sizeof(eht_capab->phy_cap)) -+ len = sizeof(eht_capab->phy_cap); -+ os_memcpy(eht_capab->phy_cap, -+ nla_data(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY]), -+ len); -+ } -+ -+ if (tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET]) { -+ len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET]); -+ if (len > sizeof(eht_capab->mcs)) -+ len = sizeof(eht_capab->mcs); -+ os_memcpy(eht_capab->mcs, -+ nla_data(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET]), -+ len); -+ } -+ -+ if (tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE]) { -+ len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE]); -+ if (len > sizeof(eht_capab->ppet)) -+ len = sizeof(eht_capab->ppet); -+ os_memcpy(&eht_capab->ppet, -+ nla_data(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE]), -+ len); -+ } - } - - -@@ -1870,7 +1914,7 @@ static int phy_info_iftype(struct hostapd_hw_modes *mode, - return NL_STOP; - - for (i = 0; i < IEEE80211_MODE_NUM; i++) -- phy_info_iftype_copy(&mode->he_capab[i], i, tb, tb_flags); -+ phy_info_iftype_copy(mode, i, tb, tb_flags); - - return NL_OK; - } --- -2.31.1 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-011-eht-parse-elements-received-in-management-frames.patch b/feeds/ipq95xx/hostapd/patches/q02-011-eht-parse-elements-received-in-management-frames.patch deleted file mode 100644 index 44829cf8a..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-011-eht-parse-elements-received-in-management-frames.patch +++ /dev/null @@ -1,51 +0,0 @@ -From a6480aca3e0e8c0509c852dae89d2016b616c486 Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Fri, 2 Jul 2021 12:21:11 -0700 -Subject: [PATCH 11/23] eht: parse elements received in management frames - -Parse and store pointers to EHT capabilities and operation elements -received in management frames. - -Signed-off-by: Aloka Dixit ---- - src/common/ieee802_11_common.c | 8 ++++++++ - src/common/ieee802_11_common.h | 4 ++++ - 2 files changed, 12 insertions(+) - ---- a/src/common/ieee802_11_common.c -+++ b/src/common/ieee802_11_common.c -@@ -311,6 +311,14 @@ static int ieee802_11_parse_extension(co - elems->mbssid_known_bss = pos; - elems->mbssid_known_bss_len = elen; - break; -+ case WLAN_EID_EXT_EHT_CAPABILITY: -+ elems->eht_capabilities = pos; -+ elems->eht_capabilities_len = elen; -+ break; -+ case WLAN_EID_EXT_EHT_OPERATION: -+ elems->eht_operation = pos; -+ elems->eht_operation_len = elen; -+ break; - default: - if (show_errors) { - wpa_printf(MSG_MSGDUMP, ---- a/src/common/ieee802_11_common.h -+++ b/src/common/ieee802_11_common.h -@@ -119,6 +119,8 @@ struct ieee802_11_elems { - const u8 *s1g_capab; - const u8 *pasn_params; - const u8 *mbssid_known_bss; -+ const u8 *eht_capabilities; -+ const u8 *eht_operation; - - u8 ssid_len; - u8 supp_rates_len; -@@ -174,6 +176,8 @@ struct ieee802_11_elems { - u8 sae_pk_len; - u8 pasn_params_len; - u8 mbssid_known_bss_len; -+ u8 eht_capabilities_len; -+ u8 eht_operation_len; - - struct mb_ies_info mb_ies; - struct frag_ies_info frag_ies; diff --git a/feeds/ipq95xx/hostapd/patches/q02-012-eht-process-association-request.patch b/feeds/ipq95xx/hostapd/patches/q02-012-eht-process-association-request.patch deleted file mode 100644 index 06e3c7c92..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-012-eht-process-association-request.patch +++ /dev/null @@ -1,216 +0,0 @@ -From a181193ed7b1d7ec37d6fe58d1e7c0f8c1ad15d7 Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Fri, 2 Jul 2021 12:22:20 -0700 -Subject: [PATCH 12/23] eht: process association request - -Parse EHT capabilities sent by a non-AP STA in association requests. -Validate the IE length, matching MCS rates between AP tx and STA rx. -Store the capabilities in the station info structure. - -Signed-off-by: Aloka Dixit ---- - src/ap/ieee802_11.c | 10 ++++ - src/ap/ieee802_11.h | 3 ++ - src/ap/ieee802_11_eht.c | 117 ++++++++++++++++++++++++++++++++++++++++ - src/ap/sta_info.c | 1 + - src/ap/sta_info.h | 6 +++ - 5 files changed, 137 insertions(+) - ---- a/src/ap/ieee802_11.c -+++ b/src/ap/ieee802_11.c -@@ -4593,6 +4593,16 @@ static int check_assoc_ies(struct hostap - } - } - #endif /* CONFIG_IEEE80211AX */ -+#ifdef CONFIG_IEEE80211BE -+ if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) { -+ resp = copy_sta_eht_capab(hapd, sta, IEEE80211_MODE_AP, -+ elems.he_capabilities, -+ elems.eht_capabilities, -+ elems.eht_capabilities_len); -+ if (resp != WLAN_STATUS_SUCCESS) -+ return resp; -+ } -+#endif /* CONFIG_IEEE80211BE */ - - #ifdef CONFIG_P2P - if (elems.p2p) { ---- a/src/ap/ieee802_11.h -+++ b/src/ap/ieee802_11.h -@@ -221,4 +221,7 @@ u8 * hostapd_eid_eht_capab(struct hostap - enum ieee80211_op_mode opmode); - u8 * hostapd_eid_eht_operation(struct hostapd_data *hapd, u8 *eid, - enum ieee80211_op_mode opmode); -+u16 copy_sta_eht_capab(struct hostapd_data *hapd, struct sta_info *sta, -+ enum ieee80211_op_mode opmode, const u8 *he_capab, -+ const u8 *eht_capab, size_t eht_capab_len); - #endif /* IEEE802_11_H */ ---- a/src/ap/ieee802_11_eht.c -+++ b/src/ap/ieee802_11_eht.c -@@ -20,6 +20,7 @@ - #include "utils/common.h" - #include "hostapd.h" - #include "ieee802_11.h" -+#include "sta_info.h" - - static u8 ieee80211_eht_ppet_size(const u8 *ppe_thres, const u8 *phy_cap_info) - { -@@ -219,3 +220,119 @@ u8 * hostapd_eid_eht_operation(struct ho - *length_pos = pos - (eid + 2); - return pos; - } -+ -+ -+static int check_valid_eht_mcs_nss(struct hostapd_data *hapd, const u8 *ap_mcs, -+ const u8 *sta_mcs, u8 mcs_count, u8 map_len) -+{ -+ u8 i, j; -+ -+ for (i = 0; i < mcs_count; i++) { -+ ap_mcs += (i * 3); -+ sta_mcs += (i * 3); -+ -+ for (j = 0; j < map_len; j++) { -+ if (((ap_mcs[j] >> 4) & 0xFF) == 0) -+ continue; -+ -+ if ((sta_mcs[j] & 0xFF) == 0) -+ continue; -+ -+ return 1; -+ } -+ } -+ -+ wpa_printf(MSG_DEBUG, -+ "No matching EHT MCS found between AP TX and STA RX"); -+ return 0; -+} -+ -+static int check_valid_eht_mcs(struct hostapd_data *hapd, const u8 *sta_eht_capab, -+ enum ieee80211_op_mode opmode) -+{ -+ struct hostapd_hw_modes *mode; -+ const u8 *ap_mcs, *sta_mcs; -+ -+ mode = hapd->iface->current_mode; -+ if (!mode) -+ return 1; -+ -+ ap_mcs = mode->eht_capab[opmode].mcs; -+ sta_mcs = ((const struct ieee80211_eht_capabilities *) sta_eht_capab)->optional; -+ -+ if (ieee80211_eht_mcs_set_size(mode->he_capab[opmode].phy_cap, -+ mode->eht_capab[opmode].phy_cap) == -+ EHT_PHYCAP_MCS_NSS_LEN_20MHZ_ONLY) { -+ return check_valid_eht_mcs_nss(hapd, ap_mcs, sta_mcs, 1, -+ EHT_PHYCAP_MCS_NSS_LEN_20MHZ_ONLY); -+ -+ } else { -+ u8 mcs_count = 1; -+ -+ switch (hapd->iface->conf->eht_oper_chwidth) { -+ /* TODO CHANWIDTH_320MHZ */ -+ case CHANWIDTH_80P80MHZ: -+ case CHANWIDTH_160MHZ: -+ mcs_count = 2; -+ break; -+ default: -+ break; -+ } -+ -+ return check_valid_eht_mcs_nss(hapd, ap_mcs, sta_mcs, mcs_count, -+ EHT_PHYCAP_MCS_NSS_LEN_20MHZ_PLUS); -+ } -+ -+ return 0; -+} -+ -+ -+static int ieee80211_invalid_eht_cap_size(const u8 *he_cap, const u8 *eht_cap, -+ size_t len) -+{ -+ struct ieee80211_eht_capabilities *cap; -+ const u8 *he_phy_cap; -+ size_t cap_len; -+ -+ he_phy_cap = ((struct ieee80211_he_capabilities *)he_cap)->he_phy_capab_info; -+ cap = (struct ieee80211_eht_capabilities *) eht_cap; -+ cap_len = sizeof(*cap); -+ if (len < cap_len) -+ return 1; -+ -+ cap_len += ieee80211_eht_mcs_set_size(he_phy_cap, cap->phy_cap); -+ if (len < cap_len) -+ return 1; -+ -+ cap_len += ieee80211_eht_ppet_size(&eht_cap[cap_len], cap->phy_cap); -+ -+ return (len != cap_len); -+} -+ -+ -+u16 copy_sta_eht_capab(struct hostapd_data *hapd, struct sta_info *sta, -+ enum ieee80211_op_mode opmode, const u8 *he_capab, -+ const u8 *eht_capab, size_t eht_capab_len) -+{ -+ if (!eht_capab || !hapd->iconf->ieee80211be || -+ hapd->conf->disable_11be || -+ ieee80211_invalid_eht_cap_size(he_capab, eht_capab, eht_capab_len) || -+ !check_valid_eht_mcs(hapd, eht_capab, opmode)) { -+ sta->flags_ext &= ~WLAN_STA_EXT_EHT; -+ os_free(sta->eht_capab); -+ sta->eht_capab = NULL; -+ return WLAN_STATUS_SUCCESS; -+ } -+ -+ if (!sta->eht_capab) { -+ sta->eht_capab = os_zalloc(eht_capab_len); -+ if (!sta->eht_capab) -+ return WLAN_STATUS_UNSPECIFIED_FAILURE; -+ } -+ -+ sta->flags_ext |= WLAN_STA_EXT_EHT; -+ os_memcpy(sta->eht_capab, eht_capab, eht_capab_len); -+ sta->eht_capab_len = eht_capab_len; -+ -+ return WLAN_STATUS_SUCCESS; -+} ---- a/src/ap/sta_info.c -+++ b/src/ap/sta_info.c -@@ -358,6 +358,7 @@ void ap_free_sta(struct hostapd_data *ha - os_free(sta->vht_operation); - os_free(sta->he_capab); - os_free(sta->he_6ghz_capab); -+ os_free(sta->eht_capab); - hostapd_free_psk_list(sta->psk); - os_free(sta->identity); - os_free(sta->radius_cui); ---- a/src/ap/sta_info.h -+++ b/src/ap/sta_info.h -@@ -46,6 +46,9 @@ - #define WLAN_STA_PENDING_DEAUTH_CB BIT(30) - #define WLAN_STA_NONERP BIT(31) - -+/* STA flags_ext */ -+#define WLAN_STA_EXT_EHT BIT(0) -+ - /* Maximum number of supported rates (from both Supported Rates and Extended - * Supported Rates IEs). */ - #define WLAN_SUPP_RATES_MAX 32 -@@ -113,6 +116,7 @@ struct sta_info { - u16 aid; /* STA's unique AID (1 .. 2007) or 0 if not yet assigned */ - u16 disconnect_reason_code; /* RADIUS server override */ - u32 flags; /* Bitfield of WLAN_STA_* */ -+ u32 flags_ext; /* Bitfield of WLAN_STA_EXT_* */ - u16 capability; - u16 listen_interval; /* or beacon_int for APs */ - u8 supported_rates[WLAN_SUPP_RATES_MAX]; -@@ -214,6 +218,8 @@ struct sta_info { - struct ieee80211_he_capabilities *he_capab; - size_t he_capab_len; - struct ieee80211_he_6ghz_band_cap *he_6ghz_capab; -+ struct ieee80211_eht_capabilities *eht_capab; -+ size_t eht_capab_len; - - int sa_query_count; /* number of pending SA Query requests; - * 0 = no SA Query in progress */ diff --git a/feeds/ipq95xx/hostapd/patches/q02-013-eht-changes-in-STA-addition-path.patch b/feeds/ipq95xx/hostapd/patches/q02-013-eht-changes-in-STA-addition-path.patch deleted file mode 100644 index 7790939cc..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-013-eht-changes-in-STA-addition-path.patch +++ /dev/null @@ -1,159 +0,0 @@ -From 4278083ffec33d4f5c74530326eeab62255b140e Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Tue, 6 Jul 2021 11:18:27 -0700 -Subject: [PATCH 13/23] eht: changes in STA addition path - -Add support for EHT capabilities in the during the addition of -a new station. - -Signed-off-by: Aloka Dixit ---- - src/ap/ap_drv_ops.c | 5 ++++- - src/ap/ap_drv_ops.h | 3 ++- - src/ap/ieee802_11.c | 9 +++++++++ - src/ap/ieee802_11.h | 4 ++++ - src/ap/ieee802_11_eht.c | 16 ++++++++++++++++ - src/ap/sta_info.c | 2 +- - src/drivers/driver.h | 2 ++ - 7 files changed, 38 insertions(+), 3 deletions(-) - -diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c -index e917736664bd..09378eac72d2 100644 ---- a/src/ap/ap_drv_ops.c -+++ b/src/ap/ap_drv_ops.c -@@ -417,7 +417,8 @@ int hostapd_sta_add(struct hostapd_data *hapd, - const struct ieee80211_ht_capabilities *ht_capab, - const struct ieee80211_vht_capabilities *vht_capab, - const struct ieee80211_he_capabilities *he_capab, -- size_t he_capab_len, -+ const struct ieee80211_eht_capabilities *eht_capab, -+ size_t he_capab_len, size_t eht_capab_len, - const struct ieee80211_he_6ghz_band_cap *he_6ghz_capab, - u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps, - int set) -@@ -440,6 +441,8 @@ int hostapd_sta_add(struct hostapd_data *hapd, - params.vht_capabilities = vht_capab; - params.he_capab = he_capab; - params.he_capab_len = he_capab_len; -+ params.eht_capab = eht_capab; -+ params.eht_capab_len = eht_capab_len; - params.he_6ghz_capab = he_6ghz_capab; - params.vht_opmode_enabled = !!(flags & WLAN_STA_VHT_OPMODE_ENABLED); - params.vht_opmode = vht_opmode; -diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h -index 61c8f64eb471..08f52dfa7390 100644 ---- a/src/ap/ap_drv_ops.h -+++ b/src/ap/ap_drv_ops.h -@@ -42,7 +42,8 @@ int hostapd_sta_add(struct hostapd_data *hapd, - const struct ieee80211_ht_capabilities *ht_capab, - const struct ieee80211_vht_capabilities *vht_capab, - const struct ieee80211_he_capabilities *he_capab, -- size_t he_capab_len, -+ const struct ieee80211_eht_capabilities *eht_capab, -+ size_t he_capab_len, size_t eht_capab_len, - const struct ieee80211_he_6ghz_band_cap *he_6ghz_capab, - u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps, - int set); -diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c -index 18eca78f3c84..c8f308b80f67 100644 ---- a/src/ap/ieee802_11.c -+++ b/src/ap/ieee802_11.c -@@ -4934,6 +4934,7 @@ static int add_associated_sta(struct hostapd_data *hapd, - struct ieee80211_ht_capabilities ht_cap; - struct ieee80211_vht_capabilities vht_cap; - struct ieee80211_he_capabilities he_cap; -+ struct ieee80211_eht_capabilities eht_cap; - int set = 1; - - /* -@@ -4990,6 +4991,12 @@ static int add_associated_sta(struct hostapd_data *hapd, - sta->he_capab_len); - } - #endif /* CONFIG_IEEE80211AX */ -+#ifdef CONFIG_IEEE80211BE -+ if (sta->flags & WLAN_STA_EXT_EHT) { -+ hostapd_get_eht_capab(hapd, sta->eht_capab, &eht_cap, -+ sta->eht_capab_len); -+ } -+#endif /* CONFIG_IEEE80211BE */ - - /* - * Add the station with forced WLAN_STA_ASSOC flag. The sta->flags -@@ -5002,7 +5009,9 @@ static int add_associated_sta(struct hostapd_data *hapd, - sta->flags & WLAN_STA_HT ? &ht_cap : NULL, - sta->flags & WLAN_STA_VHT ? &vht_cap : NULL, - sta->flags & WLAN_STA_HE ? &he_cap : NULL, -+ sta->flags_ext & WLAN_STA_EXT_EHT ? &eht_cap : NULL, - sta->flags & WLAN_STA_HE ? sta->he_capab_len : 0, -+ sta->flags_ext & WLAN_STA_EXT_EHT ? sta->eht_capab_len : 0, - sta->he_6ghz_capab, - sta->flags | WLAN_STA_ASSOC, sta->qosinfo, - sta->vht_opmode, sta->p2p_ie ? 1 : 0, -diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h -index a9be10238afa..338599f7c71c 100644 ---- a/src/ap/ieee802_11.h -+++ b/src/ap/ieee802_11.h -@@ -78,6 +78,10 @@ void hostapd_get_he_capab(struct hostapd_data *hapd, - const struct ieee80211_he_capabilities *he_cap, - struct ieee80211_he_capabilities *neg_he_cap, - size_t he_capab_len); -+void hostapd_get_eht_capab(struct hostapd_data *hapd, -+ const struct ieee80211_eht_capabilities *src, -+ struct ieee80211_eht_capabilities *dest, -+ size_t len); - int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta); - u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta, - const u8 *ht_capab); -diff --git a/src/ap/ieee802_11_eht.c b/src/ap/ieee802_11_eht.c -index dc3dedeffac6..f19af1114005 100644 ---- a/src/ap/ieee802_11_eht.c -+++ b/src/ap/ieee802_11_eht.c -@@ -320,3 +320,19 @@ u16 copy_sta_eht_capab(struct hostapd_data *hapd, struct sta_info *sta, - - return WLAN_STATUS_SUCCESS; - } -+ -+ -+void hostapd_get_eht_capab(struct hostapd_data *hapd, -+ const struct ieee80211_eht_capabilities *src, -+ struct ieee80211_eht_capabilities *dest, -+ size_t len) -+{ -+ if (!src || !dest) -+ return; -+ -+ if (len > sizeof(*dest)) -+ len = sizeof(*dest); -+ /* TODO: mask out unsupported features */ -+ -+ os_memcpy(dest, src, len); -+} -diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c -index 8d880403f347..711680bb8950 100644 ---- a/src/ap/sta_info.c -+++ b/src/ap/sta_info.c -@@ -1554,7 +1554,7 @@ int ap_sta_re_add(struct hostapd_data *hapd, struct sta_info *sta) - if (hostapd_sta_add(hapd, sta->addr, 0, 0, - sta->supported_rates, - sta->supported_rates_len, -- 0, NULL, NULL, NULL, 0, NULL, -+ 0, NULL, NULL, NULL, NULL, 0, 0, NULL, - sta->flags, 0, 0, 0, 0)) { - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_IEEE80211, -diff --git a/src/drivers/driver.h b/src/drivers/driver.h -index 7dcdd2140f18..34e73b739d25 100644 ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -2210,6 +2210,8 @@ struct hostapd_sta_add_params { - const struct ieee80211_he_capabilities *he_capab; - size_t he_capab_len; - const struct ieee80211_he_6ghz_band_cap *he_6ghz_capab; -+ const struct ieee80211_eht_capabilities *eht_capab; -+ size_t eht_capab_len; - u32 flags; /* bitmask of WPA_STA_* flags */ - u32 flags_mask; /* unset bits in flags */ - #ifdef CONFIG_MESH --- -2.31.1 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-014-nl80211-pass-station-s-EHT-capabilities-to-kernel.patch b/feeds/ipq95xx/hostapd/patches/q02-014-nl80211-pass-station-s-EHT-capabilities-to-kernel.patch deleted file mode 100644 index 8e518f8b7..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-014-nl80211-pass-station-s-EHT-capabilities-to-kernel.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 650c1ad30199e90a02a70da54e37c6ef4c780c4b Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Tue, 6 Jul 2021 11:19:43 -0700 -Subject: [PATCH 14/23] nl80211: pass station's EHT capabilities to kernel - -Pass non-AP station's EHT capabilities to the kernel using new -attribute NL80211_ATTR_EHT_CAPABILITY. - -Signed-off-by: Aloka Dixit ---- - src/drivers/driver_nl80211.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c -index 40b3e1b5c5ed..a7807d6a9a08 100644 ---- a/src/drivers/driver_nl80211.c -+++ b/src/drivers/driver_nl80211.c -@@ -5150,6 +5150,14 @@ static int wpa_driver_nl80211_sta_add(void *priv, - goto fail; - } - -+ if (params->eht_capab) { -+ wpa_hexdump(MSG_DEBUG, " * eht_capab", -+ (u8 *) params->eht_capab, params->eht_capab_len); -+ if (nla_put(msg, NL80211_ATTR_EHT_CAPABILITY, -+ params->eht_capab_len, params->eht_capab)) -+ goto fail; -+ } -+ - if (params->ext_capab) { - wpa_hexdump(MSG_DEBUG, " * ext_capab", - params->ext_capab, params->ext_capab_len); --- -2.31.1 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-015-eht-changes-to-the-neighbor-report-element.patch b/feeds/ipq95xx/hostapd/patches/q02-015-eht-changes-to-the-neighbor-report-element.patch deleted file mode 100644 index eae128c16..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-015-eht-changes-to-the-neighbor-report-element.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 740d243df39b5df9c59cc6131d9b4da2b213a8d9 Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Tue, 17 Aug 2021 16:11:22 -0700 -Subject: [PATCH 15/23] eht: changes to the neighbor report element - -Set bit 21 in the neighbor report for an EHT AP as described in -IEEE P802.11be/D1.4, January 2022, section 9.4.2.36. -Also move the check for 'he' outside the check for 'ht' as ht and vht -are not enabled for 6GHz band. - -Signed-off-by: Aloka Dixit ---- - src/ap/neighbor_db.c | 8 ++++++-- - src/common/ieee802_11_defs.h | 1 + - 2 files changed, 7 insertions(+), 2 deletions(-) - ---- a/src/ap/neighbor_db.c -+++ b/src/ap/neighbor_db.c -@@ -243,6 +243,7 @@ void hostapd_neighbor_set_own_report(str - int ht = hapd->iconf->ieee80211n && !hapd->conf->disable_11n; - int vht = hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac; - int he = hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax; -+ int eht = he && hapd->iconf->ieee80211be && !hapd->conf->disable_11be; - struct wpa_ssid_value ssid; - u8 channel, op_class; - u8 center_freq1_idx = 0, center_freq2_idx = 0; -@@ -278,8 +279,12 @@ void hostapd_neighbor_set_own_report(str - /* VHT bit added in IEEE P802.11-REVmc/D4.3 */ - if (vht) - bssid_info |= NEI_REP_BSSID_INFO_VHT; -- if (he) -- bssid_info |= NEI_REP_BSSID_INFO_HE; -+ } -+ -+ if (he) { -+ bssid_info |= NEI_REP_BSSID_INFO_HE; -+ if (eht) -+ bssid_info |= NEI_REP_BSSID_INFO_EHT; - } - - /* TODO: Set NEI_REP_BSSID_INFO_MOBILITY_DOMAIN if MDE is set */ ---- a/src/common/ieee802_11_defs.h -+++ b/src/common/ieee802_11_defs.h -@@ -2237,7 +2237,7 @@ enum phy_type { - #define NEI_REP_BSSID_INFO_VHT BIT(12) - #define NEI_REP_BSSID_INFO_FTM BIT(13) - #define NEI_REP_BSSID_INFO_HE BIT(14) -- -+#define NEI_REP_BSSID_INFO_EHT BIT(21) - /* - * IEEE P802.11-REVmc/D5.0 Table 9-152 - HT/VHT Operation Information - * subfields. diff --git a/feeds/ipq95xx/hostapd/patches/q02-016-eht-additions-in-FILS-discovery-frames.patch b/feeds/ipq95xx/hostapd/patches/q02-016-eht-additions-in-FILS-discovery-frames.patch deleted file mode 100644 index 799777e5e..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-016-eht-additions-in-FILS-discovery-frames.patch +++ /dev/null @@ -1,160 +0,0 @@ -From 1405e5078b42f9af4e7caed2803a7ffeecc81f29 Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Mon, 19 Jul 2021 11:21:46 -0700 -Subject: [PATCH 16/23] eht: additions in FILS discovery frames - -Add support for following as per IEEE P802.11be/D1.4, January 2022, -section 9.6.7.36, -- new EHT phy index -- EHT MCS rates -- support for 320 MHZ - -Signed-off-by: Aloka Dixit ---- - src/ap/beacon.c | 85 ++++++++++++++++++++++++------------ - src/common/ieee802_11_defs.h | 2 + - 2 files changed, 60 insertions(+), 27 deletions(-) - -diff --git a/src/ap/beacon.c b/src/ap/beacon.c -index 72b80f768d93..0a62ef7a1687 100644 ---- a/src/ap/beacon.c -+++ b/src/ap/beacon.c -@@ -1196,6 +1196,45 @@ void sta_track_del(struct hostapd_sta_info *info) - - #ifdef CONFIG_FILS - -+static u16 hostapd_fils_discovery_cap_nss(struct hostapd_hw_modes *mode, -+ u16 phy_index, u8 len) -+{ -+ u16 nss = 0; -+ -+ if (phy_index == FD_CAP_PHY_INDEX_EHT) { -+ u8 rx_nss = 0, tx_nss = 0; -+ u8 *mcs = mode->eht_capab[IEEE80211_MODE_AP].mcs; -+ -+ rx_nss = mcs[0] & 0x0F; -+ tx_nss = (mcs[0] & 0xF0) >> 4; -+ nss = (tx_nss < rx_nss ? tx_nss : rx_nss); -+ } else if (phy_index == FD_CAP_PHY_INDEX_HE) { -+ u8 i; -+ u16 *mcs = (u16 *) mode->he_capab[IEEE80211_MODE_AP].mcs; -+ -+ for (i = 0; i < HE_NSS_MAX_STREAMS; i++) { -+ u16 mask = 0x3 << (i * 2); -+ -+ if (len == 4 && (((mcs[0] & mask) == mask) || -+ ((mcs[1] & mask) == mask))) -+ continue; -+ -+ if (len == 8 && (((mcs[2] & mask) == mask) || -+ ((mcs[3] & mask) == mask))) -+ continue; -+ -+ if (len == 12 && (((mcs[4] & mask) == mask) || -+ ((mcs[5] & mask) == mask))) -+ continue; -+ -+ nss++; -+ } -+ } -+ -+ return nss; -+} -+ -+ - static u16 hostapd_fils_discovery_cap(struct hostapd_data *hapd) - { - u16 cap_info, phy_index = 0; -@@ -1207,9 +1246,19 @@ static u16 hostapd_fils_discovery_cap(struct hostapd_data *hapd) - cap_info |= FD_CAP_PRIVACY; - - if (is_6ghz_op_class(hapd->iconf->op_class)) { -- phy_index = FD_CAP_PHY_INDEX_HE; -+#ifdef CONFIG_IEEE80211BE -+ if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) -+ phy_index = FD_CAP_PHY_INDEX_EHT; -+#endif /* CONFIG_IEEE80211BE */ -+#ifdef CONFIG_IEEE80211AX -+ if (!phy_index && -+ hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) -+ phy_index = FD_CAP_PHY_INDEX_HE; -+#endif /* CONFIG_IEEE80211AX */ - - switch (hapd->iconf->op_class) { -+ case 137: -+ chwidth = FD_CAP_BSS_CHWIDTH_320; - case 135: - mcs_nss_size += 4; - /* fallthrough */ -@@ -1244,8 +1293,13 @@ static u16 hostapd_fils_discovery_cap(struct hostapd_data *hapd) - break; - } - -+#ifdef CONFIG_IEEE80211BE -+ if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) -+ phy_index = FD_CAP_PHY_INDEX_EHT; -+#endif /* CONFIG_IEEE80211BE */ - #ifdef CONFIG_IEEE80211AX -- if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) -+ if (!phy_index && -+ hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) - phy_index = FD_CAP_PHY_INDEX_HE; - #endif /* CONFIG_IEEE80211AX */ - #ifdef CONFIG_IEEE80211AC -@@ -1262,31 +1316,8 @@ static u16 hostapd_fils_discovery_cap(struct hostapd_data *hapd) - cap_info |= chwidth << FD_CAP_BSS_CHWIDTH_SHIFT; - - if (mode) { -- u16 *mcs = (u16 *) mode->he_capab[IEEE80211_MODE_AP].mcs; -- int i; -- u16 nss = 0; -- -- for (i = 0; i < HE_NSS_MAX_STREAMS; i++) { -- u16 nss_mask = 0x3 << (i * 2); -- -- if (mcs_nss_size == 4 && -- (((mcs[0] & nss_mask) == nss_mask) || -- ((mcs[1] & nss_mask) == nss_mask))) -- continue; -- -- if (mcs_nss_size == 8 && -- (((mcs[2] & nss_mask) == nss_mask) || -- ((mcs[3] & nss_mask) == nss_mask))) -- continue; -- -- if (mcs_nss_size == 12 && -- (((mcs[4] & nss_mask) == nss_mask) || -- ((mcs[5] & nss_mask) == nss_mask))) -- continue; -- -- nss++; -- } -- -+ u16 nss = hostapd_fils_discovery_cap_nss(mode, phy_index, -+ mcs_nss_size); - if (nss > 4) - cap_info |= FD_CAP_NSS_5_8 << FD_CAP_NSS_SHIFT; - else if (nss) -diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h -index 79e14cc90403..b5cb680737d6 100644 ---- a/src/common/ieee802_11_defs.h -+++ b/src/common/ieee802_11_defs.h -@@ -2538,6 +2538,7 @@ enum mscs_description_subelem { - #define FD_CAP_BSS_CHWIDTH_40 1 - #define FD_CAP_BSS_CHWIDTH_80 2 - #define FD_CAP_BSS_CHWIDTH_160_80_80 3 -+#define FD_CAP_BSS_CHWIDTH_320 4 - #define FD_CAP_BSS_CHWIDTH_SHIFT 2 - - #define FD_CAP_NSS_1 0 -@@ -2552,6 +2553,7 @@ enum mscs_description_subelem { - #define FD_CAP_PHY_INDEX_HT 2 - #define FD_CAP_PHY_INDEX_VHT 3 - #define FD_CAP_PHY_INDEX_HE 4 /* P802.11ax */ -+#define FD_CAP_PHY_INDEX_EHT 5 /* P802.11be */ - #define FD_CAP_PHY_INDEX_SHIFT 10 - - /* --- -2.31.1 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-017-eht-additions-to-hostapd_set_freq_params.patch b/feeds/ipq95xx/hostapd/patches/q02-017-eht-additions-to-hostapd_set_freq_params.patch deleted file mode 100644 index bf8bedf3d..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-017-eht-additions-to-hostapd_set_freq_params.patch +++ /dev/null @@ -1,308 +0,0 @@ -From bcbde623ce398a9f3503db3756c2c5acaafcad91 Mon Sep 17 00:00:00 2001 -From: Muna Sinada -Date: Thu, 15 Jul 2021 09:35:12 -0700 -Subject: [PATCH 17/23] eht: additions to hostapd_set_freq_params() - -Modify hostapd_set_freq_params to include EHT parameters and the calling -functions. - -Signed-off-by: Muna Sinada -Signed-off-by: Aloka Dixit ---- - src/ap/ap_drv_ops.c | 14 +++++++++----- - src/ap/ap_drv_ops.h | 6 +++--- - src/ap/beacon.c | 2 ++ - src/ap/dfs.c | 6 +++++- - src/ap/hostapd.c | 5 ++++- - src/common/hw_features_common.c | 24 ++++++++++++++++++------ - src/common/hw_features_common.h | 6 ++++-- - src/drivers/driver.h | 5 +++++ - wpa_supplicant/mesh.c | 8 ++++++-- - wpa_supplicant/wpa_supplicant.c | 6 ++++-- - 10 files changed, 60 insertions(+), 22 deletions(-) - ---- a/src/ap/ap_drv_ops.c -+++ b/src/ap/ap_drv_ops.c -@@ -550,7 +550,7 @@ int hostapd_flush(struct hostapd_data *h - int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode, - int freq, int channel, int edmg, u8 edmg_channel, - int ht_enabled, int vht_enabled, -- int he_enabled, -+ int he_enabled, int eht_enabled, - int sec_channel_offset, int oper_chwidth, - int center_segment0, int center_segment1) - { -@@ -559,12 +559,14 @@ int hostapd_set_freq(struct hostapd_data - - if (hostapd_set_freq_params(&data, mode, freq, channel, edmg, - edmg_channel, ht_enabled, -- vht_enabled, he_enabled, sec_channel_offset, -- oper_chwidth, -+ vht_enabled, he_enabled, eht_enabled, -+ sec_channel_offset, oper_chwidth, - center_segment0, center_segment1, - cmode ? cmode->vht_capab : 0, - cmode ? - &cmode->he_capab[IEEE80211_MODE_AP] : NULL, -+ cmode ? -+ &cmode->eht_capab[IEEE80211_MODE_AP] : NULL, - hapd->iconf->he_6ghz_reg_pwr_type)) - return -1; - -@@ -815,7 +817,7 @@ int hostapd_drv_send_action_addr3_ap(str - int hostapd_start_dfs_cac(struct hostapd_iface *iface, - enum hostapd_hw_mode mode, int freq, - int channel, int ht_enabled, int vht_enabled, -- int he_enabled, -+ int he_enabled, int eht_enabled, - int sec_channel_offset, int oper_chwidth, - int center_segment0, int center_segment1) - { -@@ -835,11 +837,13 @@ int hostapd_start_dfs_cac(struct hostapd - - if (hostapd_set_freq_params(&data, mode, freq, channel, 0, 0, - ht_enabled, -- vht_enabled, he_enabled, sec_channel_offset, -+ vht_enabled, he_enabled, eht_enabled, -+ sec_channel_offset, - oper_chwidth, center_segment0, - center_segment1, - cmode->vht_capab, - &cmode->he_capab[IEEE80211_MODE_AP], -+ &cmode->eht_capab[IEEE80211_MODE_AP], - hapd->iconf->he_6ghz_reg_pwr_type)) { - wpa_printf(MSG_ERROR, "Can't set freq params"); - return -1; ---- a/src/ap/ap_drv_ops.h -+++ b/src/ap/ap_drv_ops.h -@@ -65,8 +65,8 @@ int hostapd_get_seqnum(const char *ifnam - int hostapd_flush(struct hostapd_data *hapd); - int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode, - int freq, int channel, int edmg, u8 edmg_channel, -- int ht_enabled, int vht_enabled, -- int he_enabled, int sec_channel_offset, int oper_chwidth, -+ int ht_enabled, int vht_enabled, int he_enabled, -+ int eht_enabled, int sec_channel_offset, int oper_chwidth, - int center_segment0, int center_segment1); - int hostapd_set_rts(struct hostapd_data *hapd, int rts); - int hostapd_set_frag(struct hostapd_data *hapd, int frag); -@@ -129,7 +129,7 @@ int hostapd_add_tspec(struct hostapd_dat - int hostapd_start_dfs_cac(struct hostapd_iface *iface, - enum hostapd_hw_mode mode, int freq, - int channel, int ht_enabled, int vht_enabled, -- int he_enabled, -+ int he_enabled, int eht_enabled, - int sec_channel_offset, int oper_chwidth, - int center_segment0, int center_segment1); - int hostapd_drv_do_acs(struct hostapd_data *hapd); ---- a/src/ap/beacon.c -+++ b/src/ap/beacon.c -@@ -2162,12 +2162,14 @@ static int __ieee802_11_set_beacon(struc - iconf->channel, iconf->enable_edmg, - iconf->edmg_channel, iconf->ieee80211n, - iconf->ieee80211ac, iconf->ieee80211ax, -+ iconf->ieee80211be, - iconf->secondary_channel, - hostapd_get_oper_chwidth(iconf), - hostapd_get_oper_centr_freq_seg0_idx(iconf), - hostapd_get_oper_centr_freq_seg1_idx(iconf), - cmode->vht_capab, - &cmode->he_capab[IEEE80211_MODE_AP], -+ &cmode->eht_capab[IEEE80211_MODE_AP], - iconf->he_6ghz_reg_pwr_type) == 0) - params.freq = &freq; - ---- a/src/ap/dfs.c -+++ b/src/ap/dfs.c -@@ -871,7 +871,7 @@ int hostapd_handle_dfs(struct hostapd_if - res = hostapd_start_dfs_cac( - iface, iface->conf->hw_mode, iface->freq, iface->conf->channel, - iface->conf->ieee80211n, iface->conf->ieee80211ac, -- iface->conf->ieee80211ax, -+ iface->conf->ieee80211ax, iface->conf->ieee80211be, - iface->conf->secondary_channel, - hostapd_get_oper_chwidth(iface->conf), - hostapd_get_oper_centr_freq_seg0_idx(iface->conf), -@@ -1084,12 +1084,14 @@ static int hostapd_dfs_testmode_set_beac - iface->conf->ieee80211n, - iface->conf->ieee80211ac, - iface->conf->ieee80211ax, -+ iface->conf->ieee80211be, - secondary_channel, - hostapd_get_oper_chwidth(iface->conf), - vht_oper_centr_freq_seg0_idx, - vht_oper_centr_freq_seg1_idx, - iface->current_mode->vht_capab, - &iface->current_mode->he_capab[IEEE80211_MODE_AP], -+ &iface->current_mode->eht_capab[IEEE80211_MODE_AP], - hapd->iconf->he_6ghz_reg_pwr_type); - - if (err) { -@@ -1226,12 +1228,14 @@ static int hostapd_dfs_start_channel_swi - iface->conf->ieee80211n, - iface->conf->ieee80211ac, - iface->conf->ieee80211ax, -+ iface->conf->ieee80211be, - secondary_channel, - new_vht_oper_chwidth, - oper_centr_freq_seg0_idx, - oper_centr_freq_seg1_idx, - cmode->vht_capab, - &cmode->he_capab[ieee80211_mode], -+ &cmode->eht_capab[ieee80211_mode], - iface->conf->he_6ghz_reg_pwr_type); - - if (err) { ---- a/src/ap/hostapd.c -+++ b/src/ap/hostapd.c -@@ -2117,6 +2117,7 @@ static int hostapd_setup_interface_compl - hapd->iconf->ieee80211n, - hapd->iconf->ieee80211ac, - hapd->iconf->ieee80211ax, -+ hapd->iconf->ieee80211be, - hapd->iconf->secondary_channel, - hostapd_get_oper_chwidth(hapd->iconf), - hostapd_get_oper_centr_freq_seg0_idx( -@@ -3524,12 +3525,14 @@ static int hostapd_change_config_freq(st - conf->channel, conf->enable_edmg, - conf->edmg_channel, conf->ieee80211n, - conf->ieee80211ac, conf->ieee80211ax, -- conf->secondary_channel, -+ conf->ieee80211be, conf->secondary_channel, - hostapd_get_oper_chwidth(conf), - hostapd_get_oper_centr_freq_seg0_idx(conf), - hostapd_get_oper_centr_freq_seg1_idx(conf), - conf->vht_capab, - mode ? &mode->he_capab[IEEE80211_MODE_AP] : -+ NULL, -+ mode ? &mode->eht_capab[IEEE80211_MODE_AP] : - NULL, hapd->iconf->he_6ghz_reg_pwr_type)) - return -1; - ---- a/src/common/hw_features_common.c -+++ b/src/common/hw_features_common.c -@@ -383,10 +383,12 @@ int hostapd_set_freq_params(struct hosta - int freq, int channel, int enable_edmg, - u8 edmg_channel, int ht_enabled, - int vht_enabled, int he_enabled, -- int sec_channel_offset, -+ int eht_enabled, int sec_channel_offset, - int oper_chwidth, int center_segment0, - int center_segment1, u32 vht_caps, -- struct he_capabilities *he_cap, u8 reg_6g_pwr_mode) -+ struct he_capabilities *he_cap, -+ struct eht_capabilities *eht_cap, -+ u8 reg_6g_pwr_mode) - { - if (!he_cap || !he_cap->he_supported) - he_enabled = 0; -@@ -397,6 +399,7 @@ int hostapd_set_freq_params(struct hosta - data->ht_enabled = ht_enabled; - data->vht_enabled = vht_enabled; - data->he_enabled = he_enabled; -+ data->eht_enabled = eht_enabled; - data->sec_channel_offset = sec_channel_offset; - data->center_freq1 = freq + sec_channel_offset * 10; - data->center_freq2 = 0; -@@ -415,9 +418,9 @@ int hostapd_set_freq_params(struct hosta - &data->edmg); - - if (is_6ghz_freq(freq)) { -- if (!data->he_enabled) { -+ if (!data->he_enabled && !data->eht_enabled) { - wpa_printf(MSG_ERROR, -- "Can't set 6 GHz mode - HE isn't enabled"); -+ "Can't set 6 GHz mode - HE and EHT aren't enabled"); - return -1; - } - -@@ -482,7 +485,16 @@ int hostapd_set_freq_params(struct hosta - return 0; - } - -- if (data->he_enabled) switch (oper_chwidth) { -+ if (data->eht_enabled) switch (oper_chwidth) { -+ case CHANWIDTH_320MHZ: -+ if (!(eht_cap->phy_cap[EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_IDX] & -+ EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_MASK)) { -+ wpa_printf(MSG_ERROR, -+ "320 MHz channel width is not supported in 5 / 6GHz"); -+ return -1; -+ } -+ break; -+ } else if (data->he_enabled) switch (oper_chwidth) { - case CHANWIDTH_USE_HT: - if (sec_channel_offset == 0) - break; -@@ -545,7 +557,7 @@ int hostapd_set_freq_params(struct hosta - break; - } - -- if (data->he_enabled || data->vht_enabled) switch (oper_chwidth) { -+ if (data->eht_enabled || data->he_enabled || data->vht_enabled) switch (oper_chwidth) { - case CHANWIDTH_USE_HT: - if (center_segment1 || - (center_segment0 != 0 && ---- a/src/common/hw_features_common.h -+++ b/src/common/hw_features_common.h -@@ -40,10 +40,12 @@ int hostapd_set_freq_params(struct hosta - int freq, int channel, int edmg, u8 edmg_channel, - int ht_enabled, - int vht_enabled, int he_enabled, -- int sec_channel_offset, -+ int eht_enabled, int sec_channel_offset, - int oper_chwidth, int center_segment0, - int center_segment1, u32 vht_caps, -- struct he_capabilities *he_caps, u8 reg_6g_pwr_mode); -+ struct he_capabilities *he_caps, -+ struct eht_capabilities *eht_cap, -+ u8 reg_6g_pwr_mode); - void set_disable_ht40(struct ieee80211_ht_capabilities *htcaps, - int disabled); - int ieee80211ac_cap_check(u32 hw, u32 conf); ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -814,6 +814,11 @@ struct hostapd_freq_params { - * 2 - VLP_AP - */ - u8 he_6ghz_reg_pwr_type; -+ -+ /** -+ * eht_enabled - Whether EHT is enabled -+ */ -+ int eht_enabled; - }; - - /** ---- a/wpa_supplicant/mesh.c -+++ b/wpa_supplicant/mesh.c -@@ -227,12 +227,13 @@ static int wpas_mesh_update_freq_params( - ifmsh->conf->ieee80211n, - ifmsh->conf->ieee80211ac, - ifmsh->conf->ieee80211ax, -+ 0, - ifmsh->conf->secondary_channel, - hostapd_get_oper_chwidth(ifmsh->conf), - hostapd_get_oper_centr_freq_seg0_idx(ifmsh->conf), - hostapd_get_oper_centr_freq_seg1_idx(ifmsh->conf), - ifmsh->conf->vht_capab, -- he_capab, ifmsh->conf->he_6ghz_reg_pwr_type)) { -+ he_capab, NULL, ifmsh->conf->he_6ghz_reg_pwr_type)) { - wpa_printf(MSG_ERROR, "Error updating mesh frequency params"); - wpa_supplicant_mesh_deinit(wpa_s, true); - return -1; ---- a/wpa_supplicant/wpa_supplicant.c -+++ b/wpa_supplicant/wpa_supplicant.c -@@ -2849,9 +2849,10 @@ skip_to_6ghz: - freq->channel, ssid->enable_edmg, - ssid->edmg_channel, freq->ht_enabled, - vht_freq.vht_enabled, vht_freq.he_enabled, -- freq->sec_channel_offset, -+ 0, freq->sec_channel_offset, - chwidth, seg0, seg1, vht_caps, -- &mode->he_capab[ieee80211_mode], 0) != 0) -+ &mode->he_capab[ieee80211_mode], NULL, -+ 0) != 0) - return; - - *freq = vht_freq; diff --git a/feeds/ipq95xx/hostapd/patches/q02-018-eht-support-for-channel-switch-command.patch b/feeds/ipq95xx/hostapd/patches/q02-018-eht-support-for-channel-switch-command.patch deleted file mode 100644 index 930ef44a3..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-018-eht-support-for-channel-switch-command.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 15f8ed3e8f3226654aecf17800854486ab1356bf Mon Sep 17 00:00:00 2001 -From: Muna Sinada -Date: Wed, 21 Jul 2021 10:12:52 -0700 -Subject: [PATCH 18/23] eht: support for channel switch command - -Add option to hostapd client command to allow switch in EHT mode. - -Signed-off-by: Muna Sinada -Signed-off-by: Aloka Dixit ---- - hostapd/ctrl_iface.c | 2 +- - hostapd/hostapd_cli.c | 2 +- - src/ap/ap_config.h | 5 +++++ - src/ap/ctrl_iface_ap.c | 1 + - src/ap/hostapd.c | 14 +++++++++++--- - 5 files changed, 19 insertions(+), 5 deletions(-) - ---- a/hostapd/ctrl_iface.c -+++ b/hostapd/ctrl_iface.c -@@ -2771,7 +2771,7 @@ static int hostapd_ctrl_iface_chan_switc - - for (i = 0; i < iface->num_bss; i++) { - -- /* Save CHAN_SWITCH VHT and HE config */ -+ /* Save CHAN_SWITCH VHT, HE and EHT config */ - hostapd_chan_switch_config(iface->bss[i], - &settings.freq_params); - ---- a/hostapd/hostapd_cli.c -+++ b/hostapd/hostapd_cli.c -@@ -1188,7 +1188,7 @@ static int hostapd_cli_cmd_chan_switch(s - "arguments (count and freq)\n" - "usage: [sec_channel_offset=] " - "[center_freq1=] [center_freq2=] [bandwidth=] " -- "[blocktx] [ht|vht]\n"); -+ "[blocktx] [ht|vht|he|eht]\n"); - return -1; - } - ---- a/src/ap/ap_config.h -+++ b/src/ap/ap_config.h -@@ -1127,6 +1127,11 @@ struct hostapd_config { - u8 eht_oper_centr_freq_seg0_idx; - struct eht_phy_capabilities_info eht_phy_capab; - #endif /* CONFIG_IEEE80211BE */ -+ -+ /* EHT enable/disable config from CHAN_SWITCH */ -+#define CH_SWITCH_EHT_ENABLED BIT(0) -+#define CH_SWITCH_EHT_DISABLED BIT(1) -+ unsigned int ch_switch_eht_config; - }; - - static inline u8 hostapd_get_he_6ghz_reg_pwr_type(struct hostapd_config *conf) ---- a/src/ap/ctrl_iface_ap.c -+++ b/src/ap/ctrl_iface_ap.c -@@ -1258,6 +1258,7 @@ int hostapd_parse_csa_settings(const cha - settings->freq_params.ht_enabled = !!os_strstr(pos, " ht"); - settings->freq_params.vht_enabled = !!os_strstr(pos, " vht"); - settings->freq_params.he_enabled = !!os_strstr(pos, " he"); -+ settings->freq_params.eht_enabled = !!os_strstr(pos, " eht"); - settings->block_tx = !!os_strstr(pos, " blocktx"); - #undef SET_CSA_SETTING - ---- a/src/ap/hostapd.c -+++ b/src/ap/hostapd.c -@@ -3581,11 +3581,12 @@ static int hostapd_fill_csa_settings(str - &hapd->iface->cs_oper_class, - &chan) == NUM_HOSTAPD_MODES) { - wpa_printf(MSG_DEBUG, -- "invalid frequency for channel switch (freq=%d, sec_channel_offset=%d, vht_enabled=%d, he_enabled=%d)", -+ "invalid frequency for channel switch (freq=%d, sec_channel_offset=%d, vht_enabled=%d, he_enabled=%d, eht_enabled=%d)", - settings->freq_params.freq, - settings->freq_params.sec_channel_offset, - settings->freq_params.vht_enabled, -- settings->freq_params.he_enabled); -+ settings->freq_params.he_enabled, -+ settings->freq_params.eht_enabled); - return -1; - } - -@@ -3646,6 +3647,11 @@ void hostapd_cleanup_cs_params(struct ho - void hostapd_chan_switch_config(struct hostapd_data *hapd, - struct hostapd_freq_params *freq_params) - { -+ if (freq_params->eht_enabled) -+ hapd->iconf->ch_switch_eht_config |= CH_SWITCH_EHT_ENABLED; -+ else -+ hapd->iconf->ch_switch_eht_config |= CH_SWITCH_EHT_DISABLED; -+ - if (freq_params->he_enabled) - hapd->iconf->ch_switch_he_config |= CH_SWITCH_HE_ENABLED; - else -@@ -3658,7 +3664,8 @@ void hostapd_chan_switch_config(struct h - - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, -- "CHAN_SWITCH HE config 0x%x VHT config 0x%x", -+ "CHAN_SWITCH EHT config 0x%x HE config 0x%x VHT config 0x%x", -+ hapd->iconf->ch_switch_eht_config, - hapd->iconf->ch_switch_he_config, - hapd->iconf->ch_switch_vht_config); - } -@@ -3733,6 +3740,7 @@ hostapd_switch_channel_fallback(struct h - iface->conf->ieee80211n = freq_params->ht_enabled; - iface->conf->ieee80211ac = freq_params->vht_enabled; - iface->conf->ieee80211ax = freq_params->he_enabled; -+ iface->conf->ieee80211be = freq_params->eht_enabled; - hostapd_set_oper_centr_freq_seg0_idx(iface->conf, seg0_idx); - hostapd_set_oper_centr_freq_seg1_idx(iface->conf, seg1_idx); - hostapd_set_oper_chwidth(iface->conf, bw); diff --git a/feeds/ipq95xx/hostapd/patches/q02-019-eht-add-checks-for-channel-switch-announcement.patch b/feeds/ipq95xx/hostapd/patches/q02-019-eht-add-checks-for-channel-switch-announcement.patch deleted file mode 100644 index 4a3768572..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-019-eht-add-checks-for-channel-switch-announcement.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 6ea74653334ab1ab9d347e40bc0ef64960526c05 Mon Sep 17 00:00:00 2001 -From: Muna Sinada -Date: Wed, 21 Jul 2021 10:17:40 -0700 -Subject: [PATCH 19/23] eht: add checks for channel switch announcement - -Add checks to confirm that respective modes VHT/HE/EHT are not disabled -for the interface before adding the CSA related fields in the management -frames. - -Signed-off-by: Muna Sinada -Signed-off-by: Aloka Dixit ---- - src/ap/beacon.c | 10 ++++++++-- - src/ap/ieee802_11.c | 3 ++- - 2 files changed, 10 insertions(+), 3 deletions(-) - ---- a/src/ap/beacon.c -+++ b/src/ap/beacon.c -@@ -643,7 +643,10 @@ static u8 * hostapd_gen_probe_resp(struc - pos = hostapd_eid_txpower_envelope(hapd, pos); - #endif /* CONFIG_IEEE80211AX */ - -- pos = hostapd_eid_wb_chsw_wrapper(hapd, pos); -+ if ((hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) || -+ (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) || -+ (hapd->iconf->ieee80211be && !hapd->conf->disable_11be)) -+ pos = hostapd_eid_wb_chsw_wrapper(hapd, pos); - - pos = hostapd_eid_rnr(hapd, pos, WLAN_FC_STYPE_PROBE_RESP); - pos = hostapd_eid_fils_indic(hapd, pos, 0); -@@ -1757,7 +1760,10 @@ int ieee802_11_build_ap_params(struct ho - tailpos = hostapd_eid_txpower_envelope(hapd, tailpos); - #endif /* CONFIG_IEEE80211AX */ - -- tailpos = hostapd_eid_wb_chsw_wrapper(hapd, tailpos); -+ if ((hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) || -+ (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) || -+ (hapd->iconf->ieee80211be && !hapd->conf->disable_11be)) -+ tailpos = hostapd_eid_wb_chsw_wrapper(hapd, tailpos); - - tailpos = hostapd_eid_rnr(hapd, tailpos, WLAN_FC_STYPE_BEACON); - tailpos = hostapd_eid_fils_indic(hapd, tailpos, 0); ---- a/src/ap/ieee802_11.c -+++ b/src/ap/ieee802_11.c -@@ -7198,7 +7198,8 @@ u8 * hostapd_eid_wb_chsw_wrapper(struct - - if (!hapd->cs_freq_params.channel || - (!hapd->cs_freq_params.vht_enabled && -- !hapd->cs_freq_params.he_enabled)) -+ !hapd->cs_freq_params.he_enabled && -+ !hapd->cs_freq_params.eht_enabled)) - return eid; - - /* bandwidth: 0: 40, 1: 80, 2: 160, 3: 80+80 */ diff --git a/feeds/ipq95xx/hostapd/patches/q02-020-eht-changes-to-channel-switch-exchange-with-driver.patch b/feeds/ipq95xx/hostapd/patches/q02-020-eht-changes-to-channel-switch-exchange-with-driver.patch deleted file mode 100644 index 780ec2a19..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-020-eht-changes-to-channel-switch-exchange-with-driver.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 34237060f4970c887152e705ea15353996309e21 Mon Sep 17 00:00:00 2001 -From: Muna Sinada -Date: Wed, 21 Jul 2021 10:29:16 -0700 -Subject: [PATCH 20/23] eht: changes to channel switch exchange with driver - -Add EHT mode to channel switch related settings exchanged between -the userspace and the driver. - -Signed-off-by: Muna Sinada -Signed-off-by: Aloka Dixit ---- - src/ap/drv_callbacks.c | 40 +++++++++++++++++++++++++++--------- - src/drivers/driver_nl80211.c | 5 +++-- - 2 files changed, 33 insertions(+), 12 deletions(-) - ---- a/src/ap/drv_callbacks.c -+++ b/src/ap/drv_callbacks.c -@@ -881,10 +881,11 @@ void hostapd_event_ch_switch(struct host - - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, -- "driver %s channel switch: freq=%d, ht=%d, vht_ch=0x%x, he_ch=0x%x, offset=%d, width=%d (%s), cf1=%d, cf2=%d", -+ "driver %s channel switch: freq=%d, ht=%d, vht_ch=0x%x, he_ch=0x%x, eht_ch=0x%x, offset=%d, width=%d (%s), cf1=%d, cf2=%d", - finished ? "had" : "starting", - freq, ht, hapd->iconf->ch_switch_vht_config, -- hapd->iconf->ch_switch_he_config, offset, -+ hapd->iconf->ch_switch_he_config, -+ hapd->iconf->ch_switch_eht_config, offset, - width, channel_width_to_string(width), cf1, cf2); - - if (!hapd->iface->current_mode) { -@@ -929,22 +930,24 @@ void hostapd_event_ch_switch(struct host - hapd->iconf->ieee80211n = ht; - if (!ht) { - hapd->iconf->ieee80211ac = 0; -- if (!is_6ghz_freq(hapd->iface->freq)) -+ if (!is_6ghz_freq(hapd->iface->freq)) { - hapd->iconf->ieee80211ax = 0; -+ hapd->iconf->ieee80211be = 0; -+ } - } else { - if (hapd->iconf->ch_switch_vht_config) { - /* CHAN_SWITCH VHT config */ - if (hapd->iconf->ch_switch_vht_config & -- CH_SWITCH_VHT_ENABLED) -+ CH_SWITCH_VHT_ENABLED) - hapd->iconf->ieee80211ac = 1; - else if (hapd->iconf->ch_switch_vht_config & -- CH_SWITCH_VHT_DISABLED) -+ CH_SWITCH_VHT_DISABLED) - hapd->iconf->ieee80211ac = 0; - } - if (hapd->iconf->ch_switch_he_config) { - /* CHAN_SWITCH HE config */ - if (hapd->iconf->ch_switch_he_config & -- CH_SWITCH_HE_ENABLED) { -+ CH_SWITCH_HE_ENABLED) { - hapd->iconf->ieee80211ax = 1; - if (!is_6ghz_freq(hapd->iface->freq)) - hapd->iconf->ieee80211ac = 1; -@@ -953,9 +956,23 @@ void hostapd_event_ch_switch(struct host - CH_SWITCH_HE_DISABLED) - hapd->iconf->ieee80211ax = 0; - } -+ if (hapd->iconf->ch_switch_eht_config) { -+ /* CHAN_SWITCH EHT config */ -+ if (hapd->iconf->ch_switch_eht_config & -+ CH_SWITCH_EHT_ENABLED) { -+ hapd->iconf->ieee80211be = 1; -+ hapd->iconf->ieee80211ax = 1; -+ if (!is_6ghz_freq(hapd->iface->freq)) -+ hapd->iconf->ieee80211ac = 1; -+ } else if (hapd->iconf->ch_switch_eht_config & -+ CH_SWITCH_EHT_DISABLED) -+ hapd->iconf->ieee80211be = 0; -+ } - } -+ - hapd->iconf->ch_switch_vht_config = 0; - hapd->iconf->ch_switch_he_config = 0; -+ hapd->iconf->ch_switch_eht_config = 0; - - hapd->iconf->secondary_channel = offset; - hostapd_set_oper_chwidth(hapd->iconf, chwidth); diff --git a/feeds/ipq95xx/hostapd/patches/q02-021-nl80211-check-driver-capabilities-for-beacon-rates.patch b/feeds/ipq95xx/hostapd/patches/q02-021-nl80211-check-driver-capabilities-for-beacon-rates.patch deleted file mode 100644 index 16f703c65..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-021-nl80211-check-driver-capabilities-for-beacon-rates.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 6a26c187beb14ccdee95d95ab0194410ba9e0ded Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Tue, 20 Jul 2021 13:50:06 -0700 -Subject: [PATCH 21/23] nl80211: check driver capabilities for beacon rates - -Set flag WPA_DRIVER_FLAGS2_BEACON_RATE_EHT if the driver advertises -support for EHT rates for beacon transmission. - -Signed-off-by: Aloka Dixit ---- - src/drivers/driver.h | 2 ++ - src/drivers/driver_nl80211_capa.c | 4 ++++ - 2 files changed, 6 insertions(+) - ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -2149,6 +2149,8 @@ struct wpa_driver_capa { - #define WPA_DRIVER_FLAGS2_OCV 0x0000000000000080ULL - /** Driver expects user space implementation of SME in AP mode */ - #define WPA_DRIVER_FLAGS2_AP_SME 0x0000000000000100ULL -+/** Driver supports Beacon frame TX rate configuration (EHT rates) */ -+#define WPA_DRIVER_FLAGS2_BEACON_RATE_EHT 0x0000000000000400ULL - u64 flags2; - - #define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \ ---- a/src/drivers/driver_nl80211_capa.c -+++ b/src/drivers/driver_nl80211_capa.c -@@ -563,6 +563,10 @@ static void wiphy_info_ext_feature_flags - capa->flags2 |= WPA_DRIVER_FLAGS2_BEACON_RATE_HE; - - if (ext_feature_isset(ext_features, len, -+ NL80211_EXT_FEATURE_BEACON_RATE_EHT)) -+ capa->flags2 |= WPA_DRIVER_FLAGS2_BEACON_RATE_EHT; -+ -+ if (ext_feature_isset(ext_features, len, - NL80211_EXT_FEATURE_SET_SCAN_DWELL)) - capa->rrm_flags |= WPA_DRIVER_FLAGS_SUPPORT_SET_SCAN_DWELL; - diff --git a/feeds/ipq95xx/hostapd/patches/q02-022-eht-configuration-option-for-beacon-rates.patch b/feeds/ipq95xx/hostapd/patches/q02-022-eht-configuration-option-for-beacon-rates.patch deleted file mode 100644 index ef2590dc9..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-022-eht-configuration-option-for-beacon-rates.patch +++ /dev/null @@ -1,83 +0,0 @@ -From ed2488e7b721ca430ddbe1245f7b40396b4685c9 Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Thu, 22 Jul 2021 13:07:26 -0700 -Subject: [PATCH 22/23] eht: configuration option for beacon rates - -Add a new option 'eht' under 'beacon_rate' to configure EHT MCS rates. -Valid values for this option will be 0-15. - -Signed-off-by: Aloka Dixit ---- - hostapd/config_file.c | 10 ++++++++++ - hostapd/hostapd.conf | 2 ++ - src/common/defs.h | 3 ++- - src/drivers/driver.h | 5 +++-- - 4 files changed, 17 insertions(+), 3 deletions(-) - -diff --git a/hostapd/config_file.c b/hostapd/config_file.c -index dada06c365b2..a5c1efb20b2d 100644 ---- a/hostapd/config_file.c -+++ b/hostapd/config_file.c -@@ -3334,6 +3334,16 @@ static int hostapd_config_fill(struct hostapd_config *conf, - } - conf->rate_type = BEACON_RATE_HE; - conf->beacon_rate = val; -+ } else if (os_strncmp(pos, "eht:", 3) == 0) { -+ val = atoi(pos + 3); -+ if (val < 0 || val > 15) { -+ wpa_printf(MSG_ERROR, -+ "Line %d: invalid beacon_rate EHT-MCS %d", -+ line, val); -+ return 1; -+ } -+ conf->rate_type = BEACON_RATE_EHT; -+ conf->beacon_rate = val; - } else { - val = atoi(pos); - if (val < 10 || val > 10000) { -diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf -index b84d3d9fa677..e03bea2b3541 100644 ---- a/hostapd/hostapd.conf -+++ b/hostapd/hostapd.conf -@@ -285,6 +285,8 @@ fragm_threshold=-1 - # beacon_rate=vht: - # HE: - # beacon_rate=he: -+# EHT: -+# beacon_rate=eht: - # - # For example, beacon_rate=10 for 1 Mbps or beacon_rate=60 for 6 Mbps (OFDM). - #beacon_rate=10 -diff --git a/src/common/defs.h b/src/common/defs.h -index f43bdb5d1b15..ad66eb244715 100644 ---- a/src/common/defs.h -+++ b/src/common/defs.h -@@ -406,7 +406,8 @@ enum beacon_rate_type { - BEACON_RATE_LEGACY, - BEACON_RATE_HT, - BEACON_RATE_VHT, -- BEACON_RATE_HE -+ BEACON_RATE_HE, -+ BEACON_RATE_EHT, - }; - - enum eap_proxy_sim_state { -diff --git a/src/drivers/driver.h b/src/drivers/driver.h -index cc09eddfd168..076f290b28a4 100644 ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -1290,8 +1290,9 @@ struct wpa_driver_ap_params { - * This parameter can be used to set a specific Beacon frame data rate - * for the BSS. The interpretation of this value depends on the - * rate_type (legacy: in 100 kbps units, HT: HT-MCS, VHT: VHT-MCS, -- * HE: HE-MCS). If beacon_rate == 0 and rate_type == 0 -- * (BEACON_RATE_LEGACY), the default Beacon frame data rate is used. -+ * HE: HE-MCS, EHT: EHT-MCS). -+ * If beacon_rate == 0 and rate_type == 0 (BEACON_RATE_LEGACY), -+ * the default Beacon frame data rate is used. - */ - unsigned int beacon_rate; - --- -2.31.1 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-023-nl80211-pass-EHT-beacon-rate-configuration-to-kernel.patch b/feeds/ipq95xx/hostapd/patches/q02-023-nl80211-pass-EHT-beacon-rate-configuration-to-kernel.patch deleted file mode 100644 index d1bea9aea..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-023-nl80211-pass-EHT-beacon-rate-configuration-to-kernel.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 49de97b9da238db0af0fbbd89408c87cf9c7e139 Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Thu, 22 Jul 2021 13:13:08 -0700 -Subject: [PATCH 23/23] nl80211: pass EHT beacon rate configuration to kernel - -Propagate EHT beacon rate to kernel if the driver has advertised -support for this configuration. Legacy, HT, VHT and HE rates will be -set to NULL. - -Signed-off-by: Aloka Dixit ---- - src/drivers/driver_nl80211.c | 22 ++++++++++++++++++++++ - 1 file changed, 22 insertions(+) - -diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c -index b5e336be826b..088e58edf2a7 100644 ---- a/src/drivers/driver_nl80211.c -+++ b/src/drivers/driver_nl80211.c -@@ -4290,6 +4290,7 @@ static int nl80211_put_beacon_rate(struct nl_msg *msg, u64 flags, u64 flags2, - struct nlattr *bands, *band; - struct nl80211_txrate_vht vht_rate; - struct nl80211_txrate_he he_rate; -+ struct nl80211_txrate_eht eht_rate; - - if (!params->freq || - (params->beacon_rate == 0 && -@@ -4323,6 +4324,7 @@ static int nl80211_put_beacon_rate(struct nl_msg *msg, u64 flags, u64 flags2, - - os_memset(&vht_rate, 0, sizeof(vht_rate)); - os_memset(&he_rate, 0, sizeof(he_rate)); -+ os_memset(&eht_rate, 0, sizeof(eht_rate)); - - switch (params->rate_type) { - case BEACON_RATE_LEGACY: -@@ -4391,6 +4393,26 @@ static int nl80211_put_beacon_rate(struct nl_msg *msg, u64 flags, u64 flags2, - wpa_printf(MSG_DEBUG, " * beacon_rate = HE-MCS %u", - params->beacon_rate); - break; -+ -+ case BEACON_RATE_EHT: -+ if (!(flags2 & WPA_DRIVER_FLAGS2_BEACON_RATE_EHT)) { -+ wpa_printf(MSG_INFO, -+ "nl80211: Driver does not support setting Beacon frame rate (EHT)"); -+ return -1; -+ } -+ eht_rate.mcs[0] = BIT(params->beacon_rate); -+ if (nla_put(msg, NL80211_TXRATE_LEGACY, 0, NULL) || -+ nla_put(msg, NL80211_TXRATE_HT, 0, NULL) || -+ nla_put(msg, NL80211_TXRATE_VHT, sizeof(vht_rate), -+ &vht_rate) || -+ nla_put(msg, NL80211_TXRATE_HE, sizeof(he_rate), -+ &he_rate) || -+ nla_put(msg, NL80211_TXRATE_EHT, sizeof(eht_rate), -+ &eht_rate)) -+ return -1; -+ wpa_printf(MSG_DEBUG, " * beacon_rate = EHT-MCS %u", -+ params->beacon_rate); -+ break; - } - - nla_nest_end(msg, band); --- -2.31.1 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-024-hostapd-11BE-bringup-Fixes.patch b/feeds/ipq95xx/hostapd/patches/q02-024-hostapd-11BE-bringup-Fixes.patch deleted file mode 100644 index 4fdc025d6..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-024-hostapd-11BE-bringup-Fixes.patch +++ /dev/null @@ -1,125 +0,0 @@ -From 4009d6184a38cbc6a7c5bd842913c169b139da7c Mon Sep 17 00:00:00 2001 -From: Pradeep Kumar Chitrapu -Date: Wed, 23 Feb 2022 11:58:52 -0800 -Subject: [PATCH] hostapd: 11BE bringup Fixes - - - Fix EHT MCS rates length calculation. - - Process PPE Thresholds only if there are additional bytes - available in EHT Caps after MAC CAPS. PHY CAPS and - MCS rates. This is temporary workaround to ignore - other driversnot adding PPE thresholds in EHT CAP - inspite of setting eht_ppe_threshlds_present bit in - EHT PHY CAPS. - - Fix ppe threshold size computation - -Signed-off-by: Pradeep Kumar Chitrapu ---- - src/ap/ieee802_11_eht.c | 33 ++++++++++++++++++--------------- - src/common/ieee802_11_defs.h | 13 +++++++------ - 2 files changed, 25 insertions(+), 21 deletions(-) - ---- a/src/ap/ieee802_11_eht.c -+++ b/src/ap/ieee802_11_eht.c -@@ -24,29 +24,29 @@ - - static u8 ieee80211_eht_ppet_size(const u8 *ppe_thres, const u8 *phy_cap_info) - { -- u8 sz = 0, ru; -+ u8 sz = 0, nss, num_nss = 0; -+ u32 ru; - - if ((phy_cap_info[EHT_PHYCAP_PPE_THRESHOLD_PRESENT_IDX] & - EHT_PHYCAP_PPE_THRESHOLD_PRESENT) == 0) - return 0; - -- ru = (ppe_thres[0] & -- (EHT_PPE_THRES_RU_INDEX_MASK << EHT_PPE_THRES_RU_INDEX_SHIFT)); -+ ru = (u32) ppe_thres[0]; -+ ru = (ru & EHT_PPE_THRES_RU_INDEX_MASK) >> EHT_PPE_THRES_RU_INDEX_SHIFT; - while (ru) { - if (ru & 0x1) - sz++; - ru >>= 1; - } - -- ru = (ppe_thres[1] & (EHT_PPE_THRES_RU_INDEX_MASK >> -- (8 - EHT_PPE_THRES_RU_INDEX_SHIFT))); -- while (ru) { -- if (ru & 0x1) -- sz++; -- ru >>= 1; -+ nss = (ppe_thres[0] & EHT_PPE_THRES_NSS_MASK) >> EHT_PPE_THRES_NSS_SHIFT; -+ while (nss) { -+ if (nss & 0x1) -+ num_nss++; -+ nss >>= 1; - } - -- sz *= (1 + (ppe_thres[0] & EHT_PPE_THRES_NSS_MASK)); -+ sz = sz * (1 + num_nss); - sz = (sz * 6) + 9; - if (sz % 8) - sz += 8; -@@ -246,6 +246,7 @@ static int check_valid_eht_mcs(struct ho - { - struct hostapd_hw_modes *mode; - const u8 *ap_mcs, *sta_mcs; -+ u8 len; - - mode = hapd->iface->current_mode; - if (!mode) -@@ -254,9 +255,9 @@ static int check_valid_eht_mcs(struct ho - ap_mcs = mode->eht_capab[opmode].mcs; - sta_mcs = ((const struct ieee80211_eht_capabilities *) sta_eht_capab)->optional; - -- if (ieee80211_eht_mcs_set_size(mode->he_capab[opmode].phy_cap, -- mode->eht_capab[opmode].phy_cap) == -- EHT_PHYCAP_MCS_NSS_LEN_20MHZ_ONLY) { -+ len = ieee80211_eht_mcs_set_size(mode->he_capab[opmode].phy_cap, -+ mode->eht_capab[opmode].phy_cap); -+ if (len == EHT_PHYCAP_MCS_NSS_LEN_20MHZ_ONLY) { - return check_valid_eht_mcs_nss(hapd, ap_mcs, sta_mcs, 1, - EHT_PHYCAP_MCS_NSS_LEN_20MHZ_ONLY); - -@@ -274,7 +275,7 @@ static int check_valid_eht_mcs(struct ho - } - - return check_valid_eht_mcs_nss(hapd, ap_mcs, sta_mcs, mcs_count, -- EHT_PHYCAP_MCS_NSS_LEN_20MHZ_PLUS); -+ len); - } - - return 0; -@@ -298,7 +299,9 @@ static int ieee80211_invalid_eht_cap_siz - if (len < cap_len) - return 1; - -- cap_len += ieee80211_eht_ppet_size(&eht_cap[cap_len], cap->phy_cap); -+ if ((cap->phy_cap[EHT_PHYCAP_PPE_THRESHOLD_PRESENT_IDX] & -+ EHT_PHYCAP_PPE_THRESHOLD_PRESENT) == 0 && len > cap_len) -+ cap_len += ieee80211_eht_ppet_size(&eht_cap[cap_len], cap->phy_cap); - - return (len != cap_len); - } ---- a/src/common/ieee802_11_defs.h -+++ b/src/common/ieee802_11_defs.h -@@ -2511,14 +2511,14 @@ struct ieee80211_eht_operation { - #define EHT_PHYCAP_MCS_NSS_LEN_20MHZ_ONLY 4 - #define EHT_PHYCAP_MCS_NSS_LEN_20MHZ_PLUS 3 - --/* IEEE P802.11be/D1.0, May 2021, 9.4.2.295c.5 EHT PPE Thresholds field */ -+/* IEEE P802.11be/D1.4, May 2021, 9.4.2.295c.5 EHT PPE Thresholds field */ - #define EHT_PPE_THRES_NSS_SHIFT 0 - #define EHT_PPE_THRES_NSS_MASK ((u8) (BIT(0) | BIT(1) | \ -- BIT(2) | BIT(3))) -+ BIT(2) | BIT(3))) - #define EHT_PPE_THRES_RU_INDEX_SHIFT 4 --#define EHT_PPE_THRES_RU_INDEX_MASK ((u8) (BIT(0) | BIT(1) | \ -- BIT(2) | BIT(3) | \ -- BIT(4))) -+#define EHT_PPE_THRES_RU_INDEX_MASK ((u8) (BIT(4) | BIT(5) | \ -+ BIT(6) | BIT(7) | \ -+ BIT(8))) - - #define EHT_OPERATION_CHANNEL_WIDTH_40MHZ 1 - #define EHT_OPERATION_CHANNEL_WIDTH_80MHZ 2 diff --git a/feeds/ipq95xx/hostapd/patches/q02-025-hostapd-WAR-patch-for-prop-issue.patch b/feeds/ipq95xx/hostapd/patches/q02-025-hostapd-WAR-patch-for-prop-issue.patch deleted file mode 100644 index e710bc7bd..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-025-hostapd-WAR-patch-for-prop-issue.patch +++ /dev/null @@ -1,131 +0,0 @@ -From c47c9c66e37ecff2519ce17f22db1b542ec4436c Mon Sep 17 00:00:00 2001 -From: Pradeep Kumar Chitrapu -Date: Wed, 9 Mar 2022 09:47:40 -0800 -Subject: [PATCH] hostapd: workaround to match EHT client - -Current AP code is using IEEE P802.11be/D1.4 whereas client devices -are designed as per IEEE P802.11be/D1.3. -Roll-back the AP code to match client temporarily. - -Signed-off-by: Pradeep Kumar Chitrapu -Signed-off-by: Aloka Dixit ---- - src/ap/ieee802_11_eht.c | 33 +++++++++++++++++---------------- - src/common/ieee802_11_defs.h | 17 ++++++++++++----- - 2 files changed, 29 insertions(+), 21 deletions(-) - ---- a/src/ap/ieee802_11_eht.c -+++ b/src/ap/ieee802_11_eht.c -@@ -170,7 +170,7 @@ u8 * hostapd_eid_eht_operation(struct ho - { - struct hostapd_hw_modes *mode; - struct ieee80211_eht_operation *oper; -- u8 *pos = eid, *length_pos, chwidth, seg0 = 0; -+ u8 *pos = eid, oper_size = 0, chwidth; - - mode = hapd->iface->current_mode; - if (!mode) -@@ -179,45 +179,49 @@ u8 * hostapd_eid_eht_operation(struct ho - if (!mode->eht_capab[opmode].eht_supported) - return eid; - -+ oper_size = sizeof(struct ieee80211_eht_operation); - *pos++ = WLAN_EID_EXTENSION; -- length_pos = pos++; -+ *pos++ = 1 + oper_size; - *pos++ = WLAN_EID_EXT_EHT_OPERATION; - - oper = (struct ieee80211_eht_operation *) pos; - os_memset(oper, 0, sizeof(*oper)); - -+ oper->ccfs = hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf); -+ if (!oper->ccfs) -+ oper->ccfs = hapd->iconf->channel; -+ - if (is_6ghz_op_class(hapd->iconf->op_class)) - chwidth = op_class_to_ch_width(hapd->iconf->op_class); - else - chwidth = hapd->iconf->eht_oper_chwidth; - -- seg0 = hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf); -- - switch (chwidth) { - case CHANWIDTH_320MHZ: -- *pos++ = EHT_OPERATION_CHANNEL_WIDTH_320MHZ; -+ oper->width = EHT_OPERATION_CHANNEL_WIDTH_320MHZ; - break; - case CHANWIDTH_160MHZ: -- *pos++ = EHT_OPERATION_CHANNEL_WIDTH_160MHZ; -+ oper->width = EHT_OPERATION_CHANNEL_WIDTH_160MHZ; - break; - case CHANWIDTH_80MHZ: -- *pos++ = EHT_OPERATION_CHANNEL_WIDTH_80MHZ; -+ oper->width = EHT_OPERATION_CHANNEL_WIDTH_80MHZ; - break; - case CHANWIDTH_USE_HT: -- if (seg0) -- *pos++ = EHT_OPERATION_CHANNEL_WIDTH_40MHZ; -+ if ((is_6ghz_op_class(hapd->iconf->op_class) && -+ op_class_to_bandwidth(hapd->iconf->op_class) == 40) || -+ hapd->iconf->secondary_channel) -+ oper->width = EHT_OPERATION_CHANNEL_WIDTH_40MHZ; - else -- pos++; -+ oper->width = EHT_OPERATION_CHANNEL_WIDTH_20MHZ; -+ - break; - default: -- return eid; -+ oper->width = EHT_OPERATION_CHANNEL_WIDTH_20MHZ; -+ break; - } - -- if (!seg0) -- seg0 = hapd->iconf->channel; -- *pos++ = seg0; -+ pos += oper_size; - -- *length_pos = pos - (eid + 2); - return pos; - } - -@@ -295,6 +299,7 @@ static int ieee80211_invalid_eht_cap_siz - const u8 *he_phy_cap; - size_t cap_len; - -+ return 0; - he_phy_cap = ((struct ieee80211_he_capabilities *)he_cap)->he_phy_capab_info; - cap = (struct ieee80211_eht_capabilities *) eht_cap; - cap_len = sizeof(*cap); ---- a/src/common/ieee802_11_defs.h -+++ b/src/common/ieee802_11_defs.h -@@ -2458,6 +2458,7 @@ struct ieee80211_eht_capabilities { - u8 optional[71]; - } STRUCT_PACKED; - -+#define EHT_OPERATION_CCFS_SHIFT 4 - /* - * struct ieee80211_eht_operation - eht operation element - * -@@ -2469,13 +2470,17 @@ struct ieee80211_eht_capabilities { - * structure (Figure 9-1002a) at all ... - */ - struct ieee80211_eht_operation { -- u8 chan_width; -+ u8 width:3, -+ reserved:5; - u8 ccfs; -- u8 present_bm; -- /* contains disabled subchannel bitmap */ -- u8 optional[]; -+ u8 disable_sub_chan_bitmap_present:1, -+ reserved2:7; -+ le16 disabled_subchannel_bitmap; -+ -+ /* Add puncture pattern here when supported */ - } STRUCT_PACKED; - -+#define EHT_OPERATION_CHANNEL_WIDTH_20MHZ 0 - #define EHT_OPERATION_CHANNEL_WIDTH_40MHZ 1 - #define EHT_OPERATION_CHANNEL_WIDTH_80MHZ 2 - #define EHT_OPERATION_CHANNEL_WIDTH_160MHZ 3 diff --git a/feeds/ipq95xx/hostapd/patches/q02-031-ru_puncturing-retrieve-driver-support.patch b/feeds/ipq95xx/hostapd/patches/q02-031-ru_puncturing-retrieve-driver-support.patch deleted file mode 100644 index 41e985127..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-031-ru_puncturing-retrieve-driver-support.patch +++ /dev/null @@ -1,123 +0,0 @@ -From 74cd6b31e4300bd70dd67ecfeab07231fb3436d2 Mon Sep 17 00:00:00 2001 -From: Muna Sinada -Date: Wed, 8 Dec 2021 23:11:27 -0800 -Subject: [PATCH 1/6] ru_puncturing: retrieve driver support - -Retrieve the driver support for RU puncturing which is advertised -using the attribute NL80211_ATTR_RU_PUNCT_SUPP_BW. -Value indicates the bandwidths in which puncturing is supported - -80 MHz, 160 MHz or 320 MHz. - -Absence of the attribute or the value 0 means the driver does not -support this feature. - -Signed-off-by: Muna Sinada -Signed-off-by: Aloka Dixit ---- - hostapd/main.c | 1 + - src/ap/hostapd.h | 3 +++ - src/drivers/driver.h | 3 +++ - src/drivers/driver_nl80211_capa.c | 18 ++++++++++++++++++ - src/drivers/nl80211_copy.h | 12 ++++++++++++ - 5 files changed, 37 insertions(+) - -diff --git a/hostapd/main.c b/hostapd/main.c -index 6e54e9d66fd6..aeef81146306 100644 ---- a/hostapd/main.c -+++ b/hostapd/main.c -@@ -240,6 +240,7 @@ static int hostapd_driver_init(struct hostapd_iface *iface) - iface->extended_capa_mask = capa.extended_capa_mask; - iface->extended_capa_len = capa.extended_capa_len; - iface->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs; -+ iface->ru_punct_supp_bw = capa.ru_punct_supp_bw; - - /* - * Override extended capa with per-interface type (AP), if -diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h -index ccc1c8514878..6cdd2c4e77d5 100644 ---- a/src/ap/hostapd.h -+++ b/src/ap/hostapd.h -@@ -617,6 +617,9 @@ struct hostapd_iface { - /* Maximum profile periodicity for enhanced MBSSID advertisements */ - u8 ema_max_periodicity; - -+ /* Minimum bandwidth the driver supports RU puncturing */ -+ u8 ru_punct_supp_bw; -+ - int (*enable_iface_cb)(struct hostapd_iface *iface); - int (*disable_iface_cb)(struct hostapd_iface *iface); - }; -diff --git a/src/drivers/driver.h b/src/drivers/driver.h -index 4a60239be32f..2252a651c6ab 100644 ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -2275,6 +2275,9 @@ struct wpa_driver_capa { - u8 mbssid_max_interfaces; - /* Maximum profile periodicity for enhanced MBSSID advertisements */ - u8 ema_max_periodicity; -+ -+ /* Minimum bandwidth the driver supports RU Puncturing */ -+ u8 ru_punct_supp_bw; - }; - - -diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c -index dc85e21290ae..593fa47fe854 100644 ---- a/src/drivers/driver_nl80211_capa.c -+++ b/src/drivers/driver_nl80211_capa.c -@@ -1100,6 +1100,24 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg) - if (tb[NL80211_ATTR_MBSSID_CONFIG]) - wiphy_info_mbssid(capa, tb[NL80211_ATTR_MBSSID_CONFIG]); - -+ if (tb[NL80211_ATTR_RU_PUNCT_SUPP_BW]) { -+ u8 supp_bw = nla_get_u8(tb[NL80211_ATTR_RU_PUNCT_SUPP_BW]); -+ -+ switch (supp_bw) { -+ case NL80211_RU_PUNCT_SUPP_BW_80: -+ capa->ru_punct_supp_bw = CHANWIDTH_80MHZ; -+ break; -+ case NL80211_RU_PUNCT_SUPP_BW_160: -+ capa->ru_punct_supp_bw = CHANWIDTH_160MHZ; -+ break; -+ case NL80211_RU_PUNCT_SUPP_BW_320: -+ capa->ru_punct_supp_bw = CHANWIDTH_320MHZ; -+ break; -+ default: -+ break; -+ } -+ } -+ - return NL_SKIP; - } - -diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h -index 7666f18f3e95..77c7a8445e97 100644 ---- a/src/drivers/nl80211_copy.h -+++ b/src/drivers/nl80211_copy.h -@@ -3120,6 +3120,10 @@ enum nl80211_attrs { - - NL80211_ATTR_DISABLE_EHT, - -+ NL80211_ATTR_RU_PUNCT_SUPP_BW, -+ NL80211_ATTR_RU_PUNCT_SUPP_HE, -+ NL80211_ATTR_RU_PUNCT_BITMAP, -+ - /* add attributes here, update the policy in nl80211.c */ - - __NL80211_ATTR_AFTER_LAST, -@@ -7487,4 +7491,12 @@ enum nl80211_beacon_tx_mode { - NL80211_BEACON_STAGGERED_MODE = 1, - NL80211_BEACON_BURST_MODE = 2, - }; -+ -+enum nl80211_ru_punct_supp_bw { -+ NL80211_RU_PUNCT_NOT_SUPP, -+ NL80211_RU_PUNCT_SUPP_BW_80, -+ NL80211_RU_PUNCT_SUPP_BW_160, -+ NL80211_RU_PUNCT_SUPP_BW_320, -+}; -+ - #endif /* __LINUX_NL80211_H */ --- -2.31.1 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-032-ru_puncturing-add-configuration-option.patch b/feeds/ipq95xx/hostapd/patches/q02-032-ru_puncturing-add-configuration-option.patch deleted file mode 100644 index d32fccb0d..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-032-ru_puncturing-add-configuration-option.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 6a39866dcfc65fb44cfea13f9455b71a516b0f4f Mon Sep 17 00:00:00 2001 -From: Muna Sinada -Date: Wed, 2 Mar 2022 15:29:58 -0800 -Subject: [PATCH 2/6] ru_puncturing: add configuration option - -- New option 'ru_punct_bitmap' to configure RU puncturing bitmap. -- New option 'ru_punct_ofdma' which indicates if kernel should - consider OFDMA pattern. - -Signed-off-by: Muna Sinada -Signed-off-by: Aloka Dixit ---- - hostapd/config_file.c | 4 ++++ - hostapd/hostapd.conf | 11 +++++++++++ - src/ap/ap_config.h | 2 ++ - 3 files changed, 17 insertions(+) - -diff --git a/hostapd/config_file.c b/hostapd/config_file.c -index 72e00c337e07..80f3fc020f2a 100644 ---- a/hostapd/config_file.c -+++ b/hostapd/config_file.c -@@ -4687,6 +4687,10 @@ static int hostapd_config_fill(struct hostapd_config *conf, - conf->eht_phy_capab.su_beamformee = atoi(pos); - } else if (os_strcmp(buf, "eht_mu_beamformer") == 0) { - conf->eht_phy_capab.mu_beamformer = atoi(pos); -+ } else if (os_strcmp(buf, "ru_punct_bitmap") == 0) { -+ conf->ru_punct_bitmap = atoi(pos); -+ } else if (os_strcmp(buf, "ru_punct_ofdma") == 0) { -+ conf->ru_punct_ofdma = atoi(pos); - #endif /* CONFIG_IEEE80211BE */ - } else { - wpa_printf(MSG_ERROR, -diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf -index 481911784f46..5fda6c614c80 100644 ---- a/hostapd/hostapd.conf -+++ b/hostapd/hostapd.conf -@@ -1017,6 +1017,17 @@ wmm_ac_vo_acm=0 - #eht_oper_chwidth - #eht_oper_centr_freq_seg0_idx - -+# RU puncturing bitmap (16 bits) where each bit corresponds to -+# a 20 MHz channel in the given bandwidth, bit 0 corresponding to the channel -+# with lowest frequency. -+# Bit set to 1 indicates that the channel is punctured, otherwise active. -+# Default value is 0 indicating that no channel is punctured. -+#ru_punct_bitmap=4 -+ -+# If the kernel should consider OFDMA patterns while validating the provided -+# RU puncturing bitmap. Default value is 0. -+#ru_punct_ofdma=1 -+ - ##### IEEE 802.1X-2004 related configuration ################################## - - # Require IEEE 802.1X authorization -diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h -index 884809388d18..19955beaefba 100644 ---- a/src/ap/ap_config.h -+++ b/src/ap/ap_config.h -@@ -1148,6 +1148,8 @@ struct hostapd_config { - #define CH_SWITCH_EHT_ENABLED BIT(0) - #define CH_SWITCH_EHT_DISABLED BIT(1) - unsigned int ch_switch_eht_config; -+ u16 ru_punct_bitmap; -+ u8 ru_punct_ofdma; - }; - - static inline u8 hostapd_get_he_6ghz_reg_pwr_type(struct hostapd_config *conf) --- -2.31.1 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-033-ru_puncturing-add-bitmap-to-frequency-parameters.patch b/feeds/ipq95xx/hostapd/patches/q02-033-ru_puncturing-add-bitmap-to-frequency-parameters.patch deleted file mode 100644 index c8eb166bc..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-033-ru_puncturing-add-bitmap-to-frequency-parameters.patch +++ /dev/null @@ -1,263 +0,0 @@ -From c68ba759850c7e1e35c017884b417b670998b820 Mon Sep 17 00:00:00 2001 -From: Muna Sinada -Date: Wed, 1 Dec 2021 15:53:47 -0800 -Subject: [PATCH 3/6] ru_puncturing: add bitmap to frequency parameters - -Add ru_punct_bitmap and ru_punct_ofdma in frequency settings so -that all commands using this code path will be able to configure -the bitmap as well. - -Signed-off-by: Muna Sinada -Signed-off-by: Aloka Dixit ---- - src/ap/ap_drv_ops.c | 12 ++++++++---- - src/ap/ap_drv_ops.h | 6 ++++-- - src/ap/beacon.c | 4 +++- - src/ap/dfs.c | 11 ++++++++--- - src/ap/hostapd.c | 8 ++++++-- - src/common/hw_features_common.c | 5 ++++- - src/common/hw_features_common.h | 3 ++- - src/drivers/driver.h | 14 ++++++++++++++ - wpa_supplicant/mesh.c | 4 +++- - wpa_supplicant/wpa_supplicant.c | 3 ++- - 10 files changed, 54 insertions(+), 16 deletions(-) - -diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c -index cc2ee5e2edcc..2ba885898cd6 100644 ---- a/src/ap/ap_drv_ops.c -+++ b/src/ap/ap_drv_ops.c -@@ -552,7 +552,8 @@ int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode, - int ht_enabled, int vht_enabled, - int he_enabled, int eht_enabled, - int sec_channel_offset, int oper_chwidth, -- int center_segment0, int center_segment1) -+ int center_segment0, int center_segment1, -+ u16 ru_punct_bitmap, u8 ru_punct_ofdma) - { - struct hostapd_freq_params data; - struct hostapd_hw_modes *cmode = hapd->iface->current_mode; -@@ -567,7 +568,8 @@ int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode, - &cmode->he_capab[IEEE80211_MODE_AP] : NULL, - cmode ? - &cmode->eht_capab[IEEE80211_MODE_AP] : NULL, -- hapd->iconf->he_6ghz_reg_pwr_type)) -+ hapd->iconf->he_6ghz_reg_pwr_type, -+ ru_punct_bitmap, ru_punct_ofdma)) - return -1; - - if (hapd->driver == NULL) -@@ -819,7 +821,8 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface, - int channel, int ht_enabled, int vht_enabled, - int he_enabled, int eht_enabled, - int sec_channel_offset, int oper_chwidth, -- int center_segment0, int center_segment1) -+ int center_segment0, int center_segment1, -+ u16 ru_punct_bitmap, u8 ru_punct_ofdma) - { - struct hostapd_data *hapd = iface->bss[0]; - struct hostapd_freq_params data; -@@ -844,7 +847,8 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface, - cmode->vht_capab, - &cmode->he_capab[IEEE80211_MODE_AP], - &cmode->eht_capab[IEEE80211_MODE_AP], -- hapd->iconf->he_6ghz_reg_pwr_type)) { -+ hapd->iconf->he_6ghz_reg_pwr_type, -+ ru_punct_bitmap, ru_punct_ofdma)) { - wpa_printf(MSG_ERROR, "Can't set freq params"); - return -1; - } -diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h -index fcac1eeee6dc..9155f1abca9e 100644 ---- a/src/ap/ap_drv_ops.h -+++ b/src/ap/ap_drv_ops.h -@@ -67,7 +67,8 @@ int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode, - int freq, int channel, int edmg, u8 edmg_channel, - int ht_enabled, int vht_enabled, int he_enabled, - int eht_enabled, int sec_channel_offset, int oper_chwidth, -- int center_segment0, int center_segment1); -+ int center_segment0, int center_segment1, -+ u16 ru_punct_bitmap, u8 ru_punct_ofdma); - int hostapd_set_rts(struct hostapd_data *hapd, int rts); - int hostapd_set_frag(struct hostapd_data *hapd, int frag); - int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr, -@@ -131,7 +132,8 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface, - int channel, int ht_enabled, int vht_enabled, - int he_enabled, int eht_enabled, - int sec_channel_offset, int oper_chwidth, -- int center_segment0, int center_segment1); -+ int center_segment0, int center_segment1, -+ u16 ru_punct_bitmap, u8 ru_punct_ofdma); - int hostapd_drv_do_acs(struct hostapd_data *hapd); - int hostapd_drv_update_dh_ie(struct hostapd_data *hapd, const u8 *peer, - u16 reason_code, const u8 *ie, size_t ielen); -diff --git a/src/ap/beacon.c b/src/ap/beacon.c -index 9db8cf12e943..e331f9c95b12 100644 ---- a/src/ap/beacon.c -+++ b/src/ap/beacon.c -@@ -2176,7 +2176,9 @@ static int __ieee802_11_set_beacon(struct hostapd_data *hapd) - cmode->vht_capab, - &cmode->he_capab[IEEE80211_MODE_AP], - &cmode->eht_capab[IEEE80211_MODE_AP], -- iconf->he_6ghz_reg_pwr_type) == 0) -+ iconf->he_6ghz_reg_pwr_type, -+ iconf->ru_punct_bitmap, -+ iconf->ru_punct_ofdma) == 0) - params.freq = &freq; - - res = hostapd_drv_set_ap(hapd, ¶ms); -diff --git a/src/ap/dfs.c b/src/ap/dfs.c -index 29d2a8991256..c206eb713629 100644 ---- a/src/ap/dfs.c -+++ b/src/ap/dfs.c -@@ -875,7 +875,8 @@ int hostapd_handle_dfs(struct hostapd_iface *iface) - iface->conf->secondary_channel, - hostapd_get_oper_chwidth(iface->conf), - hostapd_get_oper_centr_freq_seg0_idx(iface->conf), -- hostapd_get_oper_centr_freq_seg1_idx(iface->conf)); -+ hostapd_get_oper_centr_freq_seg1_idx(iface->conf), -+ iface->conf->ru_punct_bitmap, iface->conf->ru_punct_ofdma); - - if (res) { - wpa_printf(MSG_ERROR, "DFS start_dfs_cac() failed, %d", res); -@@ -1092,7 +1093,9 @@ static int hostapd_dfs_testmode_set_beacon_csa(struct hostapd_iface *iface) - iface->current_mode->vht_capab, - &iface->current_mode->he_capab[IEEE80211_MODE_AP], - &iface->current_mode->eht_capab[IEEE80211_MODE_AP], -- hapd->iconf->he_6ghz_reg_pwr_type); -+ hapd->iconf->he_6ghz_reg_pwr_type, -+ iface->conf->ru_punct_bitmap, -+ iface->conf->ru_punct_ofdma); - - if (err) { - wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params"); -@@ -1236,7 +1239,9 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface) - cmode->vht_capab, - &cmode->he_capab[ieee80211_mode], - &cmode->eht_capab[ieee80211_mode], -- iface->conf->he_6ghz_reg_pwr_type); -+ iface->conf->he_6ghz_reg_pwr_type, -+ iface->conf->ru_punct_bitmap, -+ iface->conf->ru_punct_ofdma); - - if (err) { - wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params"); -diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c -index 0b623a2fcdf1..becb726c760b 100644 ---- a/src/ap/hostapd.c -+++ b/src/ap/hostapd.c -@@ -2123,7 +2123,9 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface, - hostapd_get_oper_centr_freq_seg0_idx( - hapd->iconf), - hostapd_get_oper_centr_freq_seg1_idx( -- hapd->iconf))) { -+ hapd->iconf), -+ hapd->iconf->ru_punct_bitmap, -+ hapd->iconf->ru_punct_ofdma)) { - wpa_printf(MSG_ERROR, "Could not set channel for " - "kernel driver"); - goto fail; -@@ -3533,7 +3535,9 @@ static int hostapd_change_config_freq(struct hostapd_data *hapd, - mode ? &mode->he_capab[IEEE80211_MODE_AP] : - NULL, - mode ? &mode->eht_capab[IEEE80211_MODE_AP] : -- NULL, hapd->iconf->he_6ghz_reg_pwr_type)) -+ NULL, hapd->iconf->he_6ghz_reg_pwr_type, -+ conf->ru_punct_bitmap, -+ conf->ru_punct_ofdma)) - return -1; - - switch (params->bandwidth) { -diff --git a/src/common/hw_features_common.c b/src/common/hw_features_common.c -index 2e03265a2e72..786568b7d970 100644 ---- a/src/common/hw_features_common.c -+++ b/src/common/hw_features_common.c -@@ -388,7 +388,8 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, - int center_segment1, u32 vht_caps, - struct he_capabilities *he_cap, - struct eht_capabilities *eht_cap, -- u8 reg_6g_pwr_mode) -+ u8 reg_6g_pwr_mode, u16 ru_punct_bitmap, -+ u8 ru_punct_ofdma) - { - if (!he_cap || !he_cap->he_supported) - he_enabled = 0; -@@ -403,6 +404,8 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, - data->sec_channel_offset = sec_channel_offset; - data->center_freq1 = freq + sec_channel_offset * 10; - data->center_freq2 = 0; -+ data->ru_punct_bitmap = ru_punct_bitmap; -+ data->ru_punct_ofdma = ru_punct_ofdma; - if (oper_chwidth == CHANWIDTH_80MHZ) - data->bandwidth = 80; - else if (oper_chwidth == CHANWIDTH_160MHZ || -diff --git a/src/common/hw_features_common.h b/src/common/hw_features_common.h -index 2971b719aaae..1efe293c9939 100644 ---- a/src/common/hw_features_common.h -+++ b/src/common/hw_features_common.h -@@ -45,7 +45,8 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, - int center_segment1, u32 vht_caps, - struct he_capabilities *he_caps, - struct eht_capabilities *eht_cap, -- u8 reg_6g_pwr_mode); -+ u8 reg_6g_pwr_mode, u16 ru_punct_bitmap, -+ u8 ru_punct_ofdma); - void set_disable_ht40(struct ieee80211_ht_capabilities *htcaps, - int disabled); - int ieee80211ac_cap_check(u32 hw, u32 conf); -diff --git a/src/drivers/driver.h b/src/drivers/driver.h -index 2252a651c6ab..baf05489be8e 100644 ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -819,6 +819,20 @@ struct hostapd_freq_params { - * eht_enabled - Whether EHT is enabled - */ - int eht_enabled; -+ -+ /** -+ * ru_punct_bitmap - RU puncturing bitmap -+ * Each bit corresponds to a 20 MHz subchannel, lowest bit for the -+ * channel with the lowest frequency. Bit set to 1 indicates that the -+ * subchannel is punctured, otherwise active. -+ */ -+ u16 ru_punct_bitmap; -+ -+ /** -+ * ru_punct_ofdma - If ru_punct_bitmap could be one of -+ * the OFDMA patterns -+ */ -+ u8 ru_punct_ofdma; - }; - - /** -diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c -index 15fe87b7e507..97116e049797 100644 ---- a/wpa_supplicant/mesh.c -+++ b/wpa_supplicant/mesh.c -@@ -233,7 +233,9 @@ static int wpas_mesh_update_freq_params(struct wpa_supplicant *wpa_s) - hostapd_get_oper_centr_freq_seg0_idx(ifmsh->conf), - hostapd_get_oper_centr_freq_seg1_idx(ifmsh->conf), - ifmsh->conf->vht_capab, -- he_capab, NULL, ifmsh->conf->he_6ghz_reg_pwr_type)) { -+ he_capab, NULL, ifmsh->conf->he_6ghz_reg_pwr_type, -+ ifmsh->conf->ru_punct_bitmap, -+ ifmsh->conf->ru_punct_ofdma)) { - wpa_printf(MSG_ERROR, "Error updating mesh frequency params"); - wpa_supplicant_mesh_deinit(wpa_s, true); - return -1; -diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c -index 07fc3d7ed8ec..cdaf23cf06fe 100644 ---- a/wpa_supplicant/wpa_supplicant.c -+++ b/wpa_supplicant/wpa_supplicant.c -@@ -2852,7 +2852,8 @@ skip_to_6ghz: - 0, freq->sec_channel_offset, - chwidth, seg0, seg1, vht_caps, - &mode->he_capab[ieee80211_mode], NULL, -- 0) != 0) -+ 0, freq->ru_punct_bitmap, -+ freq->ru_punct_ofdma) != 0) - return; - - *freq = vht_freq; --- -2.31.1 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-034-ru_puncturing-add-bitmap-to-EHT-operation-element.patch b/feeds/ipq95xx/hostapd/patches/q02-034-ru_puncturing-add-bitmap-to-EHT-operation-element.patch deleted file mode 100644 index 9a8034f74..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-034-ru_puncturing-add-bitmap-to-EHT-operation-element.patch +++ /dev/null @@ -1,394 +0,0 @@ -From 765ef9735ee87ccb8e58df2d7e3cba53851ac8ef Mon Sep 17 00:00:00 2001 -From: Muna Sinada -Date: Wed, 2 Mar 2022 15:32:49 -0800 -Subject: [PATCH] ru_puncturing: add bitmap to EHT operation element - -Add RU puncturing bitmap to the EHT operation element. -Bits set to 1 indicate that the subchannel is punctured, otherwise -active. - -Signed-off-by: Muna Sinada -Signed-off-by: Aloka Dixit ---- - hostapd/ctrl_iface.c | 36 +++++++++++++ - src/ap/hw_features.c | 64 +++++++++++++++++++++++ - src/ap/ieee802_11.c | 73 ++++++++++++++++++++++++++ - src/ap/ieee802_11.h | 1 + - src/ap/ieee802_11_eht.c | 27 +++++++++- - src/ap/ieee802_11_he.c | 16 ++++++ - src/ap/ieee802_11_vht.c | 7 +++ - src/common/hw_features_common.c | 92 +++++++++++++++++++++++++++++++++ - src/common/hw_features_common.h | 2 + - src/common/ieee802_11_defs.h | 1 + - 10 files changed, 318 insertions(+), 1 deletion(-) - ---- a/src/ap/hw_features.c -+++ b/src/ap/hw_features.c -@@ -898,6 +898,63 @@ static int hostapd_is_usable_edmg(struct - } - - -+static int hostapd_is_usable_ru_punct_bitmap(struct hostapd_iface *iface) -+{ -+ struct hostapd_config *conf = iface->conf; -+ u8 bw, start_chan; -+ -+ if (!conf->ru_punct_bitmap) { -+ conf->ru_punct_ofdma = 0; -+ return 1; -+ } -+ -+#ifdef CONFIG_IEEE80211BE -+ if (!conf->ieee80211be) { -+ wpa_printf(MSG_ERROR, -+ "Currently RU puncturing is supported only if ieee80211be is enabled"); -+ return 0; -+ } -+ -+ if (iface->freq >= 2412 && iface->freq <= 2484) { -+ wpa_printf(MSG_ERROR, -+ "RU puncturing not supported in 2.4 GHz"); -+ return 0; -+ } -+ -+ switch (conf->eht_oper_chwidth) { -+ case 0: -+ wpa_printf(MSG_ERROR, -+ "RU puncturing is supported only in 80 MHz and 160 MHz"); -+ return 0; -+ case 1: -+ bw = 80; -+ start_chan = conf->eht_oper_centr_freq_seg0_idx - 6; -+ break; -+ case 2: -+ bw = 160; -+ start_chan = conf->eht_oper_centr_freq_seg0_idx - 14; -+ break; -+ default: -+ return 0; -+ } -+ -+ if (is_ru_punct_bitmap_valid(bw, -+ (conf->channel - start_chan) / 4, -+ conf->ru_punct_bitmap, -+ conf->ru_punct_ofdma) == false) { -+ wpa_printf(MSG_ERROR, "Invalid RU puncturing bitmap"); -+ return 0; -+ } -+ -+ return 1; -+#else -+ wpa_printf(MSG_ERROR, -+ "Currently RU puncturing is supported only if ieee80211be is enabled"); -+ return 0; -+#endif /* CONFIG_IEEE80211BE */ -+} -+ -+ - static int hostapd_is_usable_chans(struct hostapd_iface *iface) - { - int secondary_freq; -@@ -920,6 +977,9 @@ static int hostapd_is_usable_chans(struc - if (!hostapd_is_usable_edmg(iface)) - return 0; - -+ if (!hostapd_is_usable_ru_punct_bitmap(iface)) -+ return 0; -+ - if (!iface->conf->secondary_channel) - return 1; - ---- a/src/ap/ieee802_11.c -+++ b/src/ap/ieee802_11.c -@@ -8066,4 +8066,77 @@ u8 * hostapd_eid_mbssid(struct hostapd_d - return eid; - } - -+ -+static void ru_punct_update_bw_80(u8 bitmap, u8 pri_chan, u8 *seg0) -+{ -+ u8 first_chan = *seg0 - 6, sec_chan; -+ -+ switch (bitmap) { -+ case 0x6: -+ *seg0 = 0; -+ return; -+ case 0x8: -+ case 0x4: -+ case 0x2: -+ case 0x1: -+ case 0xC: -+ case 0x3: -+ if (pri_chan < *seg0) -+ *seg0 -= 4; -+ else -+ *seg0 += 4; -+ break; -+ } -+ -+ if (pri_chan < *seg0) -+ sec_chan = pri_chan + 4; -+ else -+ sec_chan = pri_chan - 4; -+ -+ if (bitmap & BIT((sec_chan - first_chan) / 4)) -+ *seg0 = 0; -+} -+ -+ -+static void ru_punct_update_bw_160(u8 bitmap, u8 pri_chan, u8 *width, u8 *seg0) -+{ -+ if (pri_chan < *seg0) { -+ *seg0 -= 8; -+ if (bitmap & 0x0F) { -+ *width = 0; -+ ru_punct_update_bw_80(bitmap & 0xF, -+ pri_chan, -+ seg0); -+ } -+ } else { -+ *seg0 += 8; -+ if (bitmap & 0xF0) { -+ *width = 0; -+ ru_punct_update_bw_80((bitmap & 0xF0) >> 4, -+ pri_chan, -+ seg0); -+ } -+ } -+} -+ -+ -+void ru_punct_update_bw(u16 bitmap, u8 pri_chan, u8 *width, u8 *seg0, u8 *seg1) -+{ -+ if (!bitmap || !(*width) || ((*width) == 3)) -+ return; -+ -+ if (((*width) == 1) && (bitmap & 0xF)) { -+ *width = 0; -+ ru_punct_update_bw_80(bitmap & 0xF, pri_chan, seg0); -+ } -+ -+ if ((*width) == 2 && (bitmap & 0xFF)) { -+ *width = 1; -+ *seg1 = 0; -+ ru_punct_update_bw_160(bitmap & 0xFF, pri_chan, width, seg0); -+ } -+ -+ /* Add for 320 MHz */ -+} -+ - #endif /* CONFIG_NATIVE_WINDOWS */ ---- a/src/ap/ieee802_11.h -+++ b/src/ap/ieee802_11.h -@@ -228,4 +228,5 @@ u8 * hostapd_eid_eht_operation(struct ho - u16 copy_sta_eht_capab(struct hostapd_data *hapd, struct sta_info *sta, - enum ieee80211_op_mode opmode, const u8 *he_capab, - const u8 *eht_capab, size_t eht_capab_len); -+void ru_punct_update_bw(u16 bitmap, u8 pri_chan, u8 *width, u8 *seg0, u8 *seg1); - #endif /* IEEE802_11_H */ ---- a/src/ap/ieee802_11_eht.c -+++ b/src/ap/ieee802_11_eht.c -@@ -196,17 +196,37 @@ u8 * hostapd_eid_eht_operation(struct ho - else - chwidth = hapd->iconf->eht_oper_chwidth; - -+ if (hapd->iconf->ru_punct_bitmap && !hapd->iface->ru_punct_supp_bw) { -+ hapd->iconf->ru_punct_bitmap = 0; -+ wpa_printf(MSG_ERROR, -+ "Driver does not support RU puncturing. Setting bitmap to 0"); -+ } -+ - switch (chwidth) { - case CHANWIDTH_320MHZ: - oper->width = EHT_OPERATION_CHANNEL_WIDTH_320MHZ; - break; - case CHANWIDTH_160MHZ: - oper->width = EHT_OPERATION_CHANNEL_WIDTH_160MHZ; -+ if (hapd->iconf->ru_punct_bitmap && -+ hapd->iface->ru_punct_supp_bw == CHANWIDTH_320MHZ) { -+ hapd->iconf->ru_punct_bitmap = 0; -+ wpa_printf(MSG_ERROR, -+ "Driver does not support RU puncturing for bandwidths less than 320 MHz. Setting bitmap to 0"); -+ } - break; - case CHANWIDTH_80MHZ: - oper->width = EHT_OPERATION_CHANNEL_WIDTH_80MHZ; -+ if (hapd->iconf->ru_punct_bitmap && -+ ((hapd->iface->ru_punct_supp_bw == CHANWIDTH_160MHZ) || -+ (hapd->iface->ru_punct_supp_bw == CHANWIDTH_320MHZ))) { -+ hapd->iconf->ru_punct_bitmap = 0; -+ wpa_printf(MSG_ERROR, -+ "Driver does not support RU puncturing for bandwidths less than 160 MHz. Setting bitmap to 0"); -+ } - break; - case CHANWIDTH_USE_HT: -+ hapd->iconf->ru_punct_bitmap = 0; - if ((is_6ghz_op_class(hapd->iconf->op_class) && - op_class_to_bandwidth(hapd->iconf->op_class) == 40) || - hapd->iconf->secondary_channel) -@@ -216,10 +236,16 @@ u8 * hostapd_eid_eht_operation(struct ho - - break; - default: -+ hapd->iconf->ru_punct_bitmap = 0; - oper->width = EHT_OPERATION_CHANNEL_WIDTH_20MHZ; - break; - } - -+ if (hapd->iconf->ru_punct_bitmap) { -+ oper->disable_sub_chan_bitmap_present = 1; -+ oper->disabled_subchannel_bitmap = host_to_le16(hapd->iconf->ru_punct_bitmap); -+ } -+ - pos += oper_size; - - return pos; ---- a/src/ap/ieee802_11_he.c -+++ b/src/ap/ieee802_11_he.c -@@ -215,6 +215,22 @@ u8 * hostapd_eid_he_operation(struct hos - u8 seg0 = hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf); - u8 seg1 = hostapd_get_oper_centr_freq_seg1_idx(hapd->iconf); - -+ if (hapd->iconf->ru_punct_bitmap) { -+ hapd->iconf->he_oper_chwidth = -+ hostapd_get_oper_chwidth(hapd->iconf); -+ hapd->iconf->he_oper_centr_freq_seg0_idx = seg0; -+ hapd->iconf->he_oper_centr_freq_seg1_idx = seg1; -+ -+ ru_punct_update_bw(hapd->iconf->ru_punct_bitmap, -+ hapd->iconf->channel, -+ &hapd->iconf->he_oper_chwidth, -+ &hapd->iconf->he_oper_centr_freq_seg0_idx, -+ &hapd->iconf->he_oper_centr_freq_seg1_idx); -+ -+ seg0 = hapd->iconf->he_oper_centr_freq_seg0_idx; -+ seg1 = hapd->iconf->he_oper_centr_freq_seg1_idx; -+ } -+ - if (!seg0) - seg0 = hapd->iconf->channel; - ---- a/src/ap/ieee802_11_vht.c -+++ b/src/ap/ieee802_11_vht.c -@@ -98,6 +98,13 @@ u8 * hostapd_eid_vht_operation(struct ho - oper = (struct ieee80211_vht_operation *) pos; - os_memset(oper, 0, sizeof(*oper)); - -+ if (hapd->iconf->ru_punct_bitmap) -+ ru_punct_update_bw(hapd->iconf->ru_punct_bitmap, -+ hapd->iconf->channel, -+ &hapd->iconf->vht_oper_chwidth, -+ &hapd->iconf->vht_oper_centr_freq_seg0_idx, -+ &hapd->iconf->vht_oper_centr_freq_seg1_idx); -+ - /* - * center freq = 5 GHz + (5 * index) - * So index 42 gives center freq 5.210 GHz ---- a/src/common/hw_features_common.c -+++ b/src/common/hw_features_common.c -@@ -824,3 +824,95 @@ int chan_pri_allowed(const struct hostap - return !(chan->flag & HOSTAPD_CHAN_DISABLED) && - (chan->allowed_bw & HOSTAPD_CHAN_WIDTH_20); - } -+ -+ -+/* IEEE P802.11be/D1.31, December 2021, Table 36-30 5-bit punctured channel -+ * indication for the non-OFDMA case in an EHT MU PPDU -+ */ -+static const u16 ru_punct_bitmap_80[] = {0xF, 0xE, 0xD, 0xB, 0x7}; -+static const u16 ru_punct_bitmap_160[] = {0xFF, 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, -+ 0xDF, 0xBF, 0x7F, 0xFC, 0xF3, 0xCF, -+ 0x3F}; -+static const u16 ru_punct_bitmap_320[] = {0xFFFF, 0xFFFC, 0xFFF3, 0xFFCF, -+ 0xFF3F, 0xFCFF, 0xF3FF, 0xCFFF, -+ 0x3FFF, 0xFFF0, 0xFF0F, 0xF0FF, -+ 0x0FFF, 0xFFC0, 0xFF30, 0xFCF0, -+ 0xF3F0, 0xCFF0, 0x3FF0, 0x0FFC, -+ 0x0FF3, 0x0FCF, 0x0F3F, 0x0CFF, -+ 0x03FF}; -+ -+ -+bool is_ru_punct_bitmap_valid(u16 bw, u16 pri_ch_bit_pos, u16 ru_punct_bitmap, -+ u8 ru_punct_ofdma) -+{ -+ u8 i, non_ofdma_bitmap_count, ofdma_block_count = 1; -+ u16 bitmap; -+ const u16 *non_ofdma_bitmap; -+ -+ if (!ru_punct_bitmap) /* All channels active */ -+ return true; -+ -+ bitmap = ~ru_punct_bitmap; -+ -+ switch (bw) { -+ case 80: -+ bitmap &= 0xF; -+ non_ofdma_bitmap = &ru_punct_bitmap_80[0]; -+ non_ofdma_bitmap_count = ARRAY_SIZE(ru_punct_bitmap_80); -+ break; -+ -+ case 160: -+ bitmap &= 0xFF; -+ non_ofdma_bitmap = &ru_punct_bitmap_160[0]; -+ non_ofdma_bitmap_count = ARRAY_SIZE(ru_punct_bitmap_160); -+ break; -+ -+ case 320: -+ bitmap &= 0xFFFF; -+ non_ofdma_bitmap = &ru_punct_bitmap_320[0]; -+ non_ofdma_bitmap_count = ARRAY_SIZE(ru_punct_bitmap_320); -+ break; -+ -+ default: -+ return false; -+ } -+ -+ if (!bitmap) /* No channel active */ -+ return false; -+ -+ if (!(bitmap & BIT(pri_ch_bit_pos))) { -+ wpa_printf(MSG_DEBUG, "Primary channel cannot be punctured"); -+ return false; -+ } -+ -+ /* Check for non-OFDMA puncturing patterns */ -+ for (i = 0; i < non_ofdma_bitmap_count; i++) -+ if (non_ofdma_bitmap[i] == bitmap) -+ return true; -+ -+ if (!ru_punct_ofdma) -+ return false; -+ -+ /* Check for OFDMA puncturing patterns */ -+ for (i = 0; i < ofdma_block_count; i++) { -+ switch ((bitmap >> (i * 4)) & 0xF) { -+ /* IEEE P802.11be/D1.31, December 2021, 36.3.12.11.2 Preamble -+ * puncturing for PPDUs in an OFDMA transmission -+ */ -+ case 0xF: -+ case 0x7: -+ case 0xB: -+ case 0xD: -+ case 0xE: -+ case 0x3: -+ case 0xC: -+ case 0x9: -+ case 0x0: -+ break; -+ default: -+ return false; -+ } -+ } -+ -+ return true; -+} ---- a/src/common/hw_features_common.h -+++ b/src/common/hw_features_common.h -@@ -55,5 +55,7 @@ u32 num_chan_to_bw(int num_chans); - int chan_bw_allowed(const struct hostapd_channel_data *chan, u32 bw, - int ht40_plus, int pri); - int chan_pri_allowed(const struct hostapd_channel_data *chan); -+bool is_ru_punct_bitmap_valid(u16 bw, u16 pri_ch_bit_pos, u16 ru_punct_bitmap, -+ u8 ru_punct_ofdma); - - #endif /* HW_FEATURES_COMMON_H */ diff --git a/feeds/ipq95xx/hostapd/patches/q02-035-ru_puncturing-additions-to-channel-switch-command.patch b/feeds/ipq95xx/hostapd/patches/q02-035-ru_puncturing-additions-to-channel-switch-command.patch deleted file mode 100644 index 959418626..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-035-ru_puncturing-additions-to-channel-switch-command.patch +++ /dev/null @@ -1,307 +0,0 @@ -From 710e19ab3a32cb29f833de594b07c7a2639b88b9 Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Wed, 22 Dec 2021 14:16:01 -0800 -Subject: [PATCH] ru_puncturing: additions to channel switch command - -Parse the command to retrive the RU puncturing bitmap and if OFDMA -patterns shouldbe considered. - -Signed-off-by: Aloka Dixit ---- - hostapd/ctrl_iface.c | 37 ++++++++++++++++++++++++++++++ - src/ap/ctrl_iface_ap.c | 3 +++ - src/ap/drv_callbacks.c | 14 +++++++---- - src/ap/hostapd.c | 4 ++++ - src/ap/hostapd.h | 1 + - src/drivers/driver.h | 2 ++ - src/drivers/driver_nl80211.c | 6 +++-- - src/drivers/driver_nl80211_event.c | 11 +++++++++ - wpa_supplicant/ap.c | 2 +- - 9 files changed, 73 insertions(+), 7 deletions(-) - -Index: hostapd-2021-12-13-b26f5c0f/hostapd/ctrl_iface.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/hostapd/ctrl_iface.c -+++ hostapd-2021-12-13-b26f5c0f/hostapd/ctrl_iface.c -@@ -33,6 +33,7 @@ - #include "common/version.h" - #include "common/ieee802_11_defs.h" - #include "common/ctrl_iface_common.h" -+#include "common/hw_features_common.h" - #ifdef CONFIG_DPP - #include "common/dpp.h" - #endif /* CONFIG_DPP */ -@@ -2637,6 +2638,7 @@ static int hostapd_ctrl_register_frame(s - static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params) - { - int idx, bw, bw_idx[] = { 20, 40, 80, 160 }; -+ u32 start_freq; - - if (is_6ghz_freq(params->freq)) { - /* Verify if HE was enabled by user or not. 6 GHz does not -@@ -2669,11 +2671,17 @@ static int hostapd_ctrl_check_freq_param - - if (params->center_freq2 || params->sec_channel_offset) - return -1; -+ -+ if (params->ru_punct_bitmap) -+ return -1; - break; - case 40: - if (params->center_freq2 || !params->sec_channel_offset) - return -1; - -+ if (params->ru_punct_bitmap) -+ return -1; -+ - if (!params->center_freq1) - break; - switch (params->sec_channel_offset) { -@@ -2708,6 +2716,9 @@ static int hostapd_ctrl_check_freq_param - return -1; - } - -+ if (params->center_freq2 && params->ru_punct_bitmap) -+ return -1; -+ - /* Adjacent and overlapped are not allowed for 80+80 */ - if (params->center_freq2 && - params->center_freq1 - params->center_freq2 <= 80 && -@@ -2742,6 +2753,32 @@ static int hostapd_ctrl_check_freq_param - return -1; - } - -+ if (!params->ru_punct_bitmap) { -+ params->ru_punct_ofdma = 0; -+ return 0; -+ } -+ -+ if (!params->eht_enabled) { -+ wpa_printf(MSG_ERROR, -+ "Currently RU puncturing is supported only if EHT is enabled"); -+ return -1; -+ } -+ -+ if (params->freq >= 2412 && params->freq <= 2484) { -+ wpa_printf(MSG_ERROR, -+ "RU puncturing not supported in 2.4 GHz"); -+ return -1; -+ } -+ -+ start_freq = params->center_freq1 - (params->bandwidth / 2); -+ if (is_ru_punct_bitmap_valid(params->bandwidth, -+ (params->freq - start_freq) / 20, -+ params->ru_punct_bitmap, -+ params->ru_punct_ofdma) == false) { -+ wpa_printf(MSG_ERROR, "Invalid RU puncturing bitmap"); -+ return -1; -+ } -+ - return 0; - } - #endif /* NEED_AP_MLME */ -Index: hostapd-2021-12-13-b26f5c0f/src/ap/ctrl_iface_ap.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/ap/ctrl_iface_ap.c -+++ hostapd-2021-12-13-b26f5c0f/src/ap/ctrl_iface_ap.c -@@ -1266,10 +1266,13 @@ int hostapd_parse_csa_settings(const cha - SET_CSA_SETTING(center_freq2); - SET_CSA_SETTING(bandwidth); - SET_CSA_SETTING(sec_channel_offset); -+ SET_CSA_SETTING(ru_punct_bitmap); - settings->freq_params.ht_enabled = !!os_strstr(pos, " ht"); - settings->freq_params.vht_enabled = !!os_strstr(pos, " vht"); - settings->freq_params.he_enabled = !!os_strstr(pos, " he"); - settings->freq_params.eht_enabled = !!os_strstr(pos, " eht"); -+ settings->freq_params.ru_punct_ofdma = !!os_strstr(pos, -+ " ru_punct_ofdma"); - settings->block_tx = !!os_strstr(pos, " blocktx"); - #undef SET_CSA_SETTING - -Index: hostapd-2021-12-13-b26f5c0f/src/ap/drv_callbacks.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/ap/drv_callbacks.c -+++ hostapd-2021-12-13-b26f5c0f/src/ap/drv_callbacks.c -@@ -872,6 +872,7 @@ void hostapd_event_sta_opmode_changed(st - - void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, - int offset, int width, int cf1, int cf2, -+ u16 ru_punct_bitmap, u8 ru_punct_ofdma, - int finished) - { - #ifdef NEED_AP_MLME -@@ -881,12 +882,13 @@ void hostapd_event_ch_switch(struct host - - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, -- "driver %s channel switch: freq=%d, ht=%d, vht_ch=0x%x, he_ch=0x%x, eht_ch=0x%x, offset=%d, width=%d (%s), cf1=%d, cf2=%d", -+ "driver %s channel switch: freq=%d, ht=%d, vht_ch=0x%x, he_ch=0x%x, eht_ch=0x%x, offset=%d, width=%d (%s), cf1=%d, cf2=%d, ru_punct_bitmap=0x%x, ru_punct_ofdma=%u", - finished ? "had" : "starting", - freq, ht, hapd->iconf->ch_switch_vht_config, - hapd->iconf->ch_switch_he_config, - hapd->iconf->ch_switch_eht_config, offset, -- width, channel_width_to_string(width), cf1, cf2); -+ width, channel_width_to_string(width), cf1, cf2, -+ ru_punct_bitmap, ru_punct_ofdma); - - if (!hapd->iface->current_mode) { - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, -@@ -985,6 +987,8 @@ void hostapd_event_ch_switch(struct host - hostapd_set_oper_centr_freq_seg0_idx(hapd->iconf, seg0_idx); - hostapd_set_oper_centr_freq_seg1_idx(hapd->iconf, seg1_idx); - hapd->iconf->op_class = op_class; -+ hapd->iconf->ru_punct_bitmap = ru_punct_bitmap; -+ hapd->iconf->ru_punct_ofdma = ru_punct_ofdma; - if (hapd->iconf->ieee80211ac) { - hapd->iconf->vht_capab &= ~VHT_CAP_SUPP_CHAN_WIDTH_MASK; - if (chwidth == CHANWIDTH_160MHZ) -@@ -999,11 +1003,11 @@ void hostapd_event_ch_switch(struct host - hapd->iface->num_hw_features); - - wpa_msg(hapd->msg_ctx, MSG_INFO, -- "%sfreq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d dfs=%d", -+ "%sfreq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d dfs=%d ru_punct_bitmap=0x%x ru_punct_ofdma=%u", - finished ? WPA_EVENT_CHANNEL_SWITCH : - WPA_EVENT_CHANNEL_SWITCH_STARTED, - freq, ht, offset, channel_width_to_string(width), -- cf1, cf2, is_dfs); -+ cf1, cf2, is_dfs, ru_punct_bitmap, ru_punct_ofdma); - if (!finished) - return; - -@@ -2090,6 +2094,8 @@ void hostapd_wpa_event(void *ctx, enum w - data->ch_switch.ch_width, - data->ch_switch.cf1, - data->ch_switch.cf2, -+ data->ch_switch.ru_punct_bitmap, -+ data->ch_switch.ru_punct_ofdma, - event == EVENT_CH_SWITCH); - break; - case EVENT_CONNECT_FAILED_REASON: -Index: hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/ap/hostapd.c -+++ hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.c -@@ -3624,6 +3624,8 @@ static int hostapd_change_config_freq(st - conf->ieee80211n = params->ht_enabled; - conf->ieee80211ac = params->vht_enabled; - conf->secondary_channel = params->sec_channel_offset; -+ conf->ru_punct_bitmap = params->ru_punct_bitmap; -+ conf->ru_punct_ofdma= params->ru_punct_ofdma; - ieee80211_freq_to_chan(params->center_freq1, - &seg0); - ieee80211_freq_to_chan(params->center_freq2, -@@ -3837,6 +3839,8 @@ hostapd_switch_channel_fallback(struct h - hostapd_set_oper_centr_freq_seg0_idx(iface->conf, seg0_idx); - hostapd_set_oper_centr_freq_seg1_idx(iface->conf, seg1_idx); - hostapd_set_oper_chwidth(iface->conf, bw); -+ iface->conf->ru_punct_bitmap = freq_params->ru_punct_bitmap; -+ iface->conf->ru_punct_ofdma = freq_params->ru_punct_ofdma; - - /* - * Resetting operating class to avoid referring previous values -Index: hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.h -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/ap/hostapd.h -+++ hostapd-2021-12-13-b26f5c0f/src/ap/hostapd.h -@@ -730,6 +730,7 @@ int hostapd_probe_req_rx(struct hostapd_ - int ssi_signal); - void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, - int offset, int width, int cf1, int cf2, -+ u16 ru_punct_bitmap, u8 ru_punct_ofdma, - int finished); - struct survey_results; - void hostapd_event_get_survey(struct hostapd_iface *iface, -Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver.h -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/drivers/driver.h -+++ hostapd-2021-12-13-b26f5c0f/src/drivers/driver.h -@@ -6111,6 +6111,8 @@ union wpa_event_data { - enum chan_width ch_width; - int cf1; - int cf2; -+ u16 ru_punct_bitmap; -+ u8 ru_punct_ofdma; - } ch_switch; - - /** -Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/drivers/driver_nl80211.c -+++ hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211.c -@@ -10064,7 +10064,7 @@ static int nl80211_switch_channel(void * - int i; - - wpa_printf(MSG_DEBUG, -- "nl80211: Channel switch request (cs_count=%u block_tx=%u freq=%d channel=%d sec_channel_offset=%d width=%d cf1=%d cf2=%d%s%s%s)", -+ "nl80211: Channel switch request (cs_count=%u block_tx=%u freq=%d channel=%d sec_channel_offset=%d width=%d cf1=%d cf2=%d%s%s%s puncturing bitmap=0x%04x, ru_punct_ofdma=%u)", - settings->cs_count, settings->block_tx, - settings->freq_params.freq, - settings->freq_params.channel, -@@ -10074,7 +10074,9 @@ static int nl80211_switch_channel(void * - settings->freq_params.center_freq2, - settings->freq_params.ht_enabled ? " ht" : "", - settings->freq_params.vht_enabled ? " vht" : "", -- settings->freq_params.he_enabled ? " he" : ""); -+ settings->freq_params.he_enabled ? " he" : "", -+ settings->freq_params.ru_punct_bitmap, -+ settings->freq_params.ru_punct_ofdma); - - if (!(drv->capa.flags & WPA_DRIVER_FLAGS_AP_CSA)) { - wpa_printf(MSG_DEBUG, "nl80211: Driver does not support channel switch command"); -Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211_event.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/drivers/driver_nl80211_event.c -+++ hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211_event.c -@@ -692,6 +692,8 @@ static void mlme_event_ch_switch(struct - struct nlattr *ifindex, struct nlattr *freq, - struct nlattr *type, struct nlattr *bw, - struct nlattr *cf1, struct nlattr *cf2, -+ struct nlattr *ru_punct_bitmap, -+ struct nlattr *ru_punct_ofdma, - struct nlattr *count, - int finished) - { -@@ -754,6 +756,11 @@ static void mlme_event_ch_switch(struct - data.ch_switch.cf1 = nla_get_u32(cf1); - if (cf2) - data.ch_switch.cf2 = nla_get_u32(cf2); -+ if (ru_punct_bitmap) { -+ data.ch_switch.ru_punct_bitmap = nla_get_u16(ru_punct_bitmap); -+ if (ru_punct_ofdma) -+ data.ch_switch.ru_punct_ofdma = nla_get_flag(ru_punct_ofdma); -+ } - if (count) - data.ch_switch.count = nla_get_u32(count); - -@@ -3113,6 +3120,8 @@ static void do_process_drv_event(struct - tb[NL80211_ATTR_CHANNEL_WIDTH], - tb[NL80211_ATTR_CENTER_FREQ1], - tb[NL80211_ATTR_CENTER_FREQ2], -+ tb[NL80211_ATTR_RU_PUNCT_BITMAP], -+ tb[NL80211_ATTR_RU_PUNCT_SUPP_HE], - tb[NL80211_ATTR_CH_SWITCH_COUNT], - 0); - break; -@@ -3124,6 +3133,8 @@ static void do_process_drv_event(struct - tb[NL80211_ATTR_CHANNEL_WIDTH], - tb[NL80211_ATTR_CENTER_FREQ1], - tb[NL80211_ATTR_CENTER_FREQ2], -+ tb[NL80211_ATTR_RU_PUNCT_BITMAP], -+ tb[NL80211_ATTR_RU_PUNCT_SUPP_HE], - NULL, - 1); - break; -Index: hostapd-2021-12-13-b26f5c0f/wpa_supplicant/ap.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/wpa_supplicant/ap.c -+++ hostapd-2021-12-13-b26f5c0f/wpa_supplicant/ap.c -@@ -1663,7 +1663,7 @@ void wpas_ap_ch_switch(struct wpa_suppli - if (wpa_s->current_ssid) - wpa_s->current_ssid->frequency = freq; - hostapd_event_ch_switch(iface->bss[0], freq, ht, -- offset, width, cf1, cf2, finished); -+ offset, width, cf1, cf2, 0, 0, finished); - } - - diff --git a/feeds/ipq95xx/hostapd/patches/q02-036-ru_puncturing-send-bitmap-to-kernel.patch b/feeds/ipq95xx/hostapd/patches/q02-036-ru_puncturing-send-bitmap-to-kernel.patch deleted file mode 100644 index 1ac6b1c47..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-036-ru_puncturing-send-bitmap-to-kernel.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0abd3e6f6353d6cc2fec8a3d6bab6c895db5c678 Mon Sep 17 00:00:00 2001 -From: Muna Sinada -Date: Wed, 2 Mar 2022 15:47:45 -0800 -Subject: [PATCH 6/6] ru_puncturing: send bitmap to kernel - -Send the user configured bitmap to the kernel. - -Signed-off-by: Muna Sinada -Signed-off-by: Aloka Dixit ---- - src/drivers/driver_nl80211.c | 13 +++++++++++-- - 1 file changed, 11 insertions(+), 2 deletions(-) - ---- a/src/drivers/driver_nl80211.c -+++ b/src/drivers/driver_nl80211.c -@@ -5036,6 +5036,14 @@ static int nl80211_put_freq_params(struc - nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ2, - freq->center_freq2))) - return -ENOBUFS; -+ if (freq->ru_punct_bitmap) { -+ if (freq->ru_punct_ofdma && -+ nla_put_flag(msg, NL80211_ATTR_RU_PUNCT_SUPP_HE)) -+ return -ENOBUFS; -+ if (nla_put_u16(msg, NL80211_ATTR_RU_PUNCT_BITMAP, -+ freq->ru_punct_bitmap)) -+ return -ENOBUFS; -+ } - } else if (freq->ht_enabled || (freq->he_enabled && is_24ghz)) { - enum nl80211_channel_type ct; - -@@ -5084,10 +5092,10 @@ static int nl80211_set_channel(struct i8 - int ret; - - wpa_printf(MSG_DEBUG, -- "nl80211: Set freq %d (ht_enabled=%d, vht_enabled=%d, he_enabled=%d, eht_enabled=%d, bandwidth=%d MHz, cf1=%d MHz, cf2=%d MHz)", -+ "nl80211: Set freq %d (ht_enabled=%d, vht_enabled=%d, he_enabled=%d, eht_enabled=%d, bandwidth=%d MHz, cf1=%d MHz, cf2=%d MHz, puncturing bitmap=0x%04x)", - freq->freq, freq->ht_enabled, freq->vht_enabled, freq->he_enabled, - freq->eht_enabled, freq->bandwidth, freq->center_freq1, -- freq->center_freq2); -+ freq->center_freq2, freq->ru_punct_bitmap); - - msg = nl80211_bss_msg(bss, 0, set_chan ? NL80211_CMD_SET_CHANNEL : - NL80211_CMD_SET_WIPHY); diff --git a/feeds/ipq95xx/hostapd/patches/q02-037-ulmumimo-parameter-support.patch b/feeds/ipq95xx/hostapd/patches/q02-037-ulmumimo-parameter-support.patch deleted file mode 100644 index 38700c767..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-037-ulmumimo-parameter-support.patch +++ /dev/null @@ -1,221 +0,0 @@ -From 02645e533ed703233f8084232ee333d7148cb8e8 Mon Sep 17 00:00:00 2001 -From: Nagarajan Maran -Date: Thu, 21 Apr 2022 15:00:52 +0530 -Subject: [PATCH] hostapd: UL-MUMIMO param support - -Adding new params for he and eht to enable/disable ul mumimo. -Set 0 to disable or 1 to enable. If param isn't specified, -the driver/underlying hardware decides its default behaviour. -Following param fields are supported in hostapd conf file, -HE: "he_ul_mumimo" -EHT: "eht_ulmumimo_80mhz", "eht_ulmumimo_160mhz", "eht_ulmumimo_320mhz" - -Signed-off-by: Pradeep Kumar Chitrapu -Signed-off-by: Nagarajan Maran -Signed-off-by: Sidhanta Sahu ---- - hostapd/config_file.c | 10 ++++++++++ - hostapd/hostapd.conf | 5 +++++ - src/ap/ap_config.c | 2 ++ - src/ap/ap_config.h | 5 +++++ - src/ap/hw_features.c | 28 ++++++++++++++++++++++++++++ - src/ap/ieee802_11_eht.c | 14 +++++++++++++- - src/ap/ieee802_11_he.c | 7 +++++++ - src/common/ieee802_11_defs.h | 8 +++++++- - 8 files changed, 77 insertions(+), 2 deletions(-) - -diff --git a/hostapd/config_file.c b/hostapd/config_file.c -index 9ac681d..4f2e01c 100644 ---- a/hostapd/config_file.c -+++ b/hostapd/config_file.c -@@ -3422,6 +3422,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, - conf->he_phy_capab.he_su_beamformee = atoi(pos); - } else if (os_strcmp(buf, "he_mu_beamformer") == 0) { - conf->he_phy_capab.he_mu_beamformer = atoi(pos); -+ } else if (os_strcmp(buf, "he_ul_mumimo") == 0) { -+ conf->he_phy_capab.he_ul_mumimo = atoi(pos); - } else if (os_strcmp(buf, "he_bss_color") == 0) { - conf->he_op.he_bss_color = atoi(pos); - if (conf->he_op.he_bss_color > 63) -@@ -4689,6 +4691,14 @@ static int hostapd_config_fill(struct hostapd_config *conf, - conf->eht_phy_capab.su_beamformee = atoi(pos); - } else if (os_strcmp(buf, "eht_mu_beamformer") == 0) { - conf->eht_phy_capab.mu_beamformer = atoi(pos); -+ } else if (os_strcmp(buf, "eht_part_dl_mu_mimo") == 0) { -+ conf->eht_phy_capab.partial_bw_dl_mu_mimo = atoi(pos); -+ } else if (os_strcmp(buf, "eht_ulmumimo_80mhz") == 0) { -+ conf->eht_phy_capab.non_ofdma_ulmumimo_80mhz = atoi(pos); -+ } else if (os_strcmp(buf, "eht_ulmumimo_160mhz") == 0) { -+ conf->eht_phy_capab.non_ofdma_ulmumimo_160mhz = atoi(pos); -+ } else if (os_strcmp(buf, "eht_ulmumimo_320mhz") == 0) { -+ conf->eht_phy_capab.non_ofdma_ulmumimo_320mhz = atoi(pos); - } else if (os_strcmp(buf, "ru_punct_bitmap") == 0) { - conf->ru_punct_bitmap = atoi(pos); - } else if (os_strcmp(buf, "ru_punct_ofdma") == 0) { -diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf -index 5fda6c6..2502767 100644 ---- a/hostapd/hostapd.conf -+++ b/hostapd/hostapd.conf -@@ -832,6 +832,11 @@ wmm_ac_vo_acm=0 - # 1 = supported - #he_mu_beamformer=1 - -+#he_ul_mumimo: HE Uplink multiple user MIMO support -+# -1 or unspecified = Decided by firmware or underlying hardware(Default) -+# 0 = not supported -+# 1 = supported -+ - # he_bss_color: - # 0 = disable - # 1-63 = pre-defined color -diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c -index f036eb6..a237e72 100644 ---- a/src/ap/ap_config.c -+++ b/src/ap/ap_config.c -@@ -273,6 +273,8 @@ struct hostapd_config * hostapd_config_defaults(void) - HE_OPERATION_RTS_THRESHOLD_OFFSET; - /* Set default basic MCS/NSS set to single stream MCS 0-7 */ - conf->he_op.he_basic_mcs_nss_set = 0xfffc; -+ /* Set default to be decided by Driver/underlying HW */ -+ conf->he_phy_capab.he_ul_mumimo = -1; - conf->he_op.he_bss_color_disabled = 1; - conf->he_op.he_bss_color_partial = 0; - conf->he_op.he_bss_color = os_random() % 63 + 1; -diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h -index f082f14..04cd6fb 100644 ---- a/src/ap/ap_config.h -+++ b/src/ap/ap_config.h -@@ -922,6 +922,7 @@ struct he_phy_capabilities_info { - bool he_su_beamformer; - bool he_su_beamformee; - bool he_mu_beamformer; -+ int he_ul_mumimo; - }; - - /** -@@ -958,6 +959,10 @@ struct eht_phy_capabilities_info { - bool su_beamformer; - bool su_beamformee; - bool mu_beamformer; -+ bool partial_bw_dl_mu_mimo; -+ bool non_ofdma_ulmumimo_80mhz; -+ bool non_ofdma_ulmumimo_160mhz; -+ bool non_ofdma_ulmumimo_320mhz; - }; - - /** -diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c -index d24672c..1dcd0d0 100644 ---- a/src/ap/hw_features.c -+++ b/src/ap/hw_features.c -@@ -677,8 +677,36 @@ static int ieee80211ac_supported_vht_capab(struct hostapd_iface *iface) - - - #ifdef CONFIG_IEEE80211AX -+ -+static int _ieee80211he_cap_check(u8 *hw, u32 offset, u8 bits) -+{ -+ if (bits & hw[offset]) -+ return 1; -+ -+ return 0; -+} -+ - static int ieee80211ax_supported_he_capab(struct hostapd_iface *iface) - { -+ -+ struct hostapd_hw_modes *mode = iface->current_mode; -+ struct he_capabilities *hw = &mode->he_capab[IEEE80211_MODE_AP]; -+ struct hostapd_config *conf = iface->conf; -+ -+#define HE_CAP_CHECK(hw_cap, cap, bytes, conf) \ -+ do { \ -+ if (conf && !_ieee80211he_cap_check(hw_cap, bytes, cap)) { \ -+ wpa_printf(MSG_ERROR, "Driver does not support configured" \ -+ " HE capability [%s]", #cap); \ -+ return 0; \ -+ } \ -+ } while (0) -+ -+ if (conf->he_phy_capab.he_ul_mumimo != -1) -+ HE_CAP_CHECK(hw->phy_cap, HE_PHYCAP_UL_MUMIMO_CAPB, -+ HE_PHYCAP_UL_MUMIMO_CAPB_IDX, -+ conf->he_phy_capab.he_ul_mumimo); -+ - return 1; - } - #endif /* CONFIG_IEEE80211AX */ -diff --git a/src/ap/ieee802_11_eht.c b/src/ap/ieee802_11_eht.c -index 1fcd5de..8973cfd 100644 ---- a/src/ap/ieee802_11_eht.c -+++ b/src/ap/ieee802_11_eht.c -@@ -141,9 +141,21 @@ u8 * hostapd_eid_eht_capab(struct hostapd_data *hapd, u8 *eid, - ~EHT_PHYCAP_SU_BEAMFORMEE; - - if (!hapd->iface->conf->eht_phy_capab.mu_beamformer) -- cap->phy_cap[EHT_PHYCAP_MU_BEAMFORMER_IDX] &= -+ cap->phy_cap[EHT_PHYCAP_MU_CAPABILITY_IDX] &= - ~EHT_PHYCAP_MU_BEAMFORMER_MASK; - -+ if (!hapd->iface->conf->eht_phy_capab.non_ofdma_ulmumimo_80mhz) -+ cap->phy_cap[EHT_PHYCAP_MU_CAPABILITY_IDX] &= -+ ~EHT_PHYCAP_NON_OFDMA_UL_MU_MIMO_80MHZ; -+ -+ if (!hapd->iface->conf->eht_phy_capab.non_ofdma_ulmumimo_160mhz) -+ cap->phy_cap[EHT_PHYCAP_MU_CAPABILITY_IDX] &= -+ ~EHT_PHYCAP_NON_OFDMA_UL_MU_MIMO_160MHZ; -+ -+ if (!hapd->iface->conf->eht_phy_capab.non_ofdma_ulmumimo_320mhz) -+ cap->phy_cap[EHT_PHYCAP_MU_CAPABILITY_IDX] &= -+ ~EHT_PHYCAP_NON_OFDMA_UL_MU_MIMO_320MHZ; -+ - pos = cap->optional; - - mcs_nss_len = ieee80211_eht_mcs_set_size(mode->he_capab[opmode].phy_cap, -diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c -index 03b8711..6751526 100644 ---- a/src/ap/ieee802_11_he.c -+++ b/src/ap/ieee802_11_he.c -@@ -153,6 +153,13 @@ u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid, - cap->he_phy_capab_info[HE_PHYCAP_MU_BEAMFORMER_CAPAB_IDX] &= - ~HE_PHYCAP_MU_BEAMFORMER_CAPAB; - -+ if (hapd->iface->conf->he_phy_capab.he_ul_mumimo == 1) -+ cap->he_phy_capab_info[HE_PHYCAP_UL_MUMIMO_CAPB_IDX] |= -+ HE_PHYCAP_UL_MUMIMO_CAPB; -+ else if (hapd->iface->conf->he_phy_capab.he_ul_mumimo == 0) -+ cap->he_phy_capab_info[HE_PHYCAP_UL_MUMIMO_CAPB_IDX] &= -+ ~HE_PHYCAP_UL_MUMIMO_CAPB; -+ - cap->he_phy_capab_info[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &= - he_oper_chwidth; - -diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h -index cfe25c8..e4b891c 100644 ---- a/src/common/ieee802_11_defs.h -+++ b/src/common/ieee802_11_defs.h -@@ -2346,6 +2346,9 @@ struct ieee80211_spatial_reuse { - #define HE_PHYCAP_MU_BEAMFORMER_CAPAB_IDX 4 - #define HE_PHYCAP_MU_BEAMFORMER_CAPAB ((u8) BIT(1)) - -+#define HE_PHYCAP_UL_MUMIMO_CAPB_IDX 2 -+#define HE_PHYCAP_UL_MUMIMO_CAPB ((u8) BIT(6)) -+ - #define HE_PHYCAP_PPE_THRESHOLD_PRESENT_IDX 6 - #define HE_PHYCAP_PPE_THRESHOLD_PRESENT ((u8) BIT(7)) - -@@ -2500,7 +2503,10 @@ struct ieee80211_eht_operation { - - #define EHT_PHYCAP_PPE_THRESHOLD_PRESENT_IDX 5 - --#define EHT_PHYCAP_MU_BEAMFORMER_IDX 7 -+#define EHT_PHYCAP_MU_CAPABILITY_IDX 7 -+#define EHT_PHYCAP_NON_OFDMA_UL_MU_MIMO_80MHZ ((u8) BIT(1)) -+#define EHT_PHYCAP_NON_OFDMA_UL_MU_MIMO_160MHZ ((u8) BIT(2)) -+#define EHT_PHYCAP_NON_OFDMA_UL_MU_MIMO_320MHZ ((u8) BIT(3)) - #define EHT_PHYCAP_MU_BEAMFORMER_80MHZ ((u8) BIT(4)) - #define EHT_PHYCAP_MU_BEAMFORMER_160MHZ ((u8) BIT(5)) - #define EHT_PHYCAP_MU_BEAMFORMER_320MHZ ((u8) BIT(6)) --- -2.17.1 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-041-acs-configuration-option-for-RU-puncturing-threshold.patch b/feeds/ipq95xx/hostapd/patches/q02-041-acs-configuration-option-for-RU-puncturing-threshold.patch deleted file mode 100644 index fc0d2c647..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-041-acs-configuration-option-for-RU-puncturing-threshold.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 08ea6492e671b121c5aabc272bde9b56db81a09d Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Thu, 31 Mar 2022 17:37:51 -0700 -Subject: [PATCH 1/3] acs: configuration option for RU puncturing threshold - -Add new option 'ru_punct_acs_threshold' where the value indicates -the percentage of ideal channel average interference factor above -which a channel should be punctured. Default is set to 75. - -Signed-off-by: Aloka Dixit ---- - hostapd/config_file.c | 2 ++ - hostapd/hostapd.conf | 5 +++++ - src/ap/ap_config.c | 1 + - src/ap/ap_config.h | 1 + - 4 files changed, 9 insertions(+) - ---- a/hostapd/config_file.c -+++ b/hostapd/config_file.c -@@ -4691,6 +4691,14 @@ static int hostapd_config_fill(struct ho - conf->ru_punct_bitmap = atoi(pos); - } else if (os_strcmp(buf, "ru_punct_ofdma") == 0) { - conf->ru_punct_ofdma = atoi(pos); -+ } else if (os_strcmp(buf, "ru_punct_acs_threshold") == 0) { -+ conf->ru_punct_acs_threshold = atoi(pos); -+ if (conf->ru_punct_acs_threshold > 100) { -+ wpa_printf(MSG_ERROR, -+ "Line %d: ru_punct_acs_threshold must be between 0 and 100", -+ line); -+ return 1; -+ } - #endif /* CONFIG_IEEE80211BE */ - } else { - wpa_printf(MSG_ERROR, ---- a/hostapd/hostapd.conf -+++ b/hostapd/hostapd.conf -@@ -1028,6 +1028,12 @@ wmm_ac_vo_acm=0 - # RU puncturing bitmap. Default value is 0. - #ru_punct_ofdma=1 - -+# RU puncturing threshold in automatic channel selection (ACS), where the -+# value indicates the percentage of ideal channel average interference factor -+# above which a channel should be punctured. -+# Default is 0, indicates that ACS algorithm should not puncture any channel. -+#ru_punct_acs_threshold=75 -+ - ##### IEEE 802.1X-2004 related configuration ################################## - - # Require IEEE 802.1X authorization ---- a/src/ap/ap_config.h -+++ b/src/ap/ap_config.h -@@ -1150,6 +1150,7 @@ struct hostapd_config { - unsigned int ch_switch_eht_config; - u16 ru_punct_bitmap; - u8 ru_punct_ofdma; -+ u8 ru_punct_acs_threshold; - }; - - static inline u8 hostapd_get_he_6ghz_reg_pwr_type(struct hostapd_config *conf) diff --git a/feeds/ipq95xx/hostapd/patches/q02-042-acs-generate-puncturing-bitmap.patch b/feeds/ipq95xx/hostapd/patches/q02-042-acs-generate-puncturing-bitmap.patch deleted file mode 100644 index 22fc42dbf..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-042-acs-generate-puncturing-bitmap.patch +++ /dev/null @@ -1,165 +0,0 @@ -From 3975ed290f4d1dd7340595296fc8d39be6a41486 Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Thu, 31 Mar 2022 15:17:47 -0700 -Subject: [PATCH 2/3] acs: generate puncturing bitmap - -Generate puncturing bitmap after the ideal channel selection using -the threshold. - -Signed-off-by: Aloka Dixit ---- - src/ap/acs.c | 72 +++++++++++++++++++++++++++++++++++++++++--- - src/drivers/driver.h | 5 +++ - 2 files changed, 73 insertions(+), 4 deletions(-) - ---- a/src/ap/acs.c -+++ b/src/ap/acs.c -@@ -275,6 +275,7 @@ static void acs_cleanup_mode(struct host - dl_list_init(&chan->survey_list); - chan->flag |= HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED; - chan->min_nf = 0; -+ chan->ru_punct_bitmap = 0; - } - } - -@@ -644,6 +645,49 @@ static int is_common_24ghz_chan(int chan - #define ACS_24GHZ_PREFER_1_6_11 0.8 - #endif /* ACS_24GHZ_PREFER_1_6_11 */ - -+static void acs_update_puncturing_bitmap(struct hostapd_iface *iface, -+ struct hostapd_hw_modes *mode, u32 bw, -+ int n_chans, -+ struct hostapd_channel_data *chan, -+ long double factor, -+ int index_primary) -+{ -+ struct hostapd_channel_data *adj_chan = NULL; -+ int i; -+ struct hostapd_config *conf = iface->conf; -+ long double threshold = factor * conf->ru_punct_acs_threshold / 100; -+ -+ /* -+ * If threshold is 0 or user configured puncturing pattern is -+ * available then don't add additional puncturing. -+ */ -+ if (!conf->ru_punct_acs_threshold || conf->ru_punct_bitmap) -+ return; -+ -+ if (is_24ghz_mode(mode->mode) || (bw < 80)) -+ return; -+ -+ for (i = 0; i < n_chans; i++) { -+ if (i == index_primary) -+ continue; /* cannot puncture primary channel */ -+ -+ if (i > index_primary) -+ adj_chan = acs_find_chan(iface, -+ chan->freq + -+ ((i - index_primary) * 20)); -+ else -+ adj_chan = acs_find_chan(iface, -+ chan->freq - -+ ((index_primary - i) * 20)); -+ -+ if (!adj_chan) -+ break; -+ -+ if (adj_chan->interference_factor > threshold) -+ chan->ru_punct_bitmap |= BIT(i); -+ } -+} -+ - static void - acs_find_6g_psc_chan_mode(struct hostapd_iface *iface, - struct hostapd_hw_modes *mode, -@@ -740,8 +784,17 @@ acs_find_6g_psc_chan_mode(struct hostapd - - if (acs_usable_chan(chan) && - (!*ideal_chan || factor < *ideal_factor)) { -- *ideal_factor = factor; -+ /* reset puncturing bitmap for the previous ideal channel */ -+ if (*ideal_chan) -+ (*ideal_chan)->ru_punct_bitmap = 0; -+ -+ *ideal_factor = factor; - *ideal_chan = chan; -+ -+ if (iface->conf->ieee80211ax) -+ acs_update_puncturing_bitmap(iface, mode, bw, -+ n_chans, chan, -+ factor, 0); - } - - /* This channel would at least be usable */ -@@ -772,7 +825,11 @@ acs_find_ideal_chan_mode(struct hostapd_ - /* Since in the current ACS implementation the first channel is - * always a primary channel, skip channels not available as - * primary until more sophisticated channel selection is -- * implemented. */ -+ * implemented. -+ * If this implementation is changed to allow any channel in -+ * the bandwidth to be the primary one, the last parameter to -+ * acs_update_puncturing_bitmap() should be changed to the index -+ * of the primary channel */ - if (!chan_pri_allowed(chan)) - continue; - -@@ -923,8 +980,17 @@ acs_find_ideal_chan_mode(struct hostapd_ - - if (acs_usable_chan(chan) && - (!*ideal_chan || factor < *ideal_factor)) { -+ /* reset puncturing bitmap for the previous ideal channel */ -+ if (*ideal_chan) -+ (*ideal_chan)->ru_punct_bitmap = 0; -+ - *ideal_factor = factor; - *ideal_chan = chan; -+ -+ if (iface->conf->ieee80211ax) -+ acs_update_puncturing_bitmap(iface, mode, bw, -+ n_chans, chan, -+ factor, 0); - } - - /* This channel would at least be usable */ -@@ -1006,9 +1072,18 @@ bw_selected: - if (ideal_chan) { - wpa_printf(MSG_DEBUG, "ACS: Ideal channel is %d (%d MHz) with total interference factor of %Lg", - ideal_chan->chan, ideal_chan->freq, ideal_factor); -+ -+ if (iface->conf->ru_punct_acs_threshold) -+ wpa_printf(MSG_DEBUG, "ACS: RU puncturing bitmap 0x%x", -+ ideal_chan->ru_punct_bitmap); -+ - return ideal_chan; - } - -+ if (iface->conf->ru_punct_acs_threshold) -+ wpa_printf(MSG_DEBUG, "ACS: RU puncturing bitmap 0x%x", -+ ideal_chan->ru_punct_bitmap); -+ - return rand_chan; - } - -@@ -1116,6 +1191,7 @@ static void acs_study(struct hostapd_ifa - - iface->conf->channel = ideal_chan->chan; - iface->freq = ideal_chan->freq; -+ iface->conf->ru_punct_bitmap = ideal_chan->ru_punct_bitmap; - - if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) - acs_adjust_center_freq(iface); ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -181,6 +181,11 @@ struct hostapd_channel_data { - * wmm_rules - WMM regulatory rules - */ - struct hostapd_wmm_rule wmm_rules[WMM_AC_NUM]; -+ -+ /** -+ * ru_punct_bitmap - RU puncturing bitmap -+ */ -+ u16 ru_punct_bitmap; - }; - - #define HE_MAC_CAPAB_0 0 diff --git a/feeds/ipq95xx/hostapd/patches/q02-043-acs-validate-the-RU-puncturing-bitmap.patch b/feeds/ipq95xx/hostapd/patches/q02-043-acs-validate-the-RU-puncturing-bitmap.patch deleted file mode 100644 index 6cf8f9737..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-043-acs-validate-the-RU-puncturing-bitmap.patch +++ /dev/null @@ -1,45 +0,0 @@ -From f99354a45a72e124252e96b1f746fa8c83a8f597 Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Thu, 31 Mar 2022 17:19:22 -0700 -Subject: [PATCH 3/3] acs: validate the RU puncturing bitmap - -Validate generated RU puncturing bitmap against non-OFDMA patterns. -Also consider OFDMA patterns if ru_punct_ofdma option is set. - -Signed-off-by: Aloka Dixit ---- - src/ap/acs.c | 22 ++++++++-- - src/common/hw_features_common.c | 75 +++++++++++++++++++++++++++++++++ - src/common/hw_features_common.h | 2 +- - 3 files changed, 94 insertions(+), 5 deletions(-) - ---- a/src/ap/acs.c -+++ b/src/ap/acs.c -@@ -652,7 +652,7 @@ static void acs_update_puncturing_bitmap - long double factor, - int index_primary) - { -- struct hostapd_channel_data *adj_chan = NULL; -+ struct hostapd_channel_data *adj_chan = NULL, *first_chan = chan; - int i; - struct hostapd_config *conf = iface->conf; - long double threshold = factor * conf->ru_punct_acs_threshold / 100; -@@ -682,10 +682,18 @@ static void acs_update_puncturing_bitmap - - if (!adj_chan) - break; -+ else if (i == 0) -+ first_chan = adj_chan; - - if (adj_chan->interference_factor > threshold) - chan->ru_punct_bitmap |= BIT(i); - } -+ -+ if (!is_ru_punct_bitmap_valid(bw, -+ (chan->freq - first_chan->freq) / 20, -+ chan->ru_punct_bitmap, -+ conf->ru_punct_ofdma)) -+ chan->ru_punct_bitmap = 0; - } - - static void diff --git a/feeds/ipq95xx/hostapd/patches/q02-044-01-hostapd-Add-320-MHz-support.patch b/feeds/ipq95xx/hostapd/patches/q02-044-01-hostapd-Add-320-MHz-support.patch deleted file mode 100644 index 014d088b0..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-044-01-hostapd-Add-320-MHz-support.patch +++ /dev/null @@ -1,412 +0,0 @@ -From 387b308a6af81ada3643cc1c1658a7756f359b5a Mon Sep 17 00:00:00 2001 -From: Karthikeyan Periyasamy -Date: Tue, 21 Sep 2021 17:20:23 +0530 -Subject: [PATCH] hostapd: Add 320 MHz support - -Added 320 MHz channel support in 6GHz band (EHT) -as define by IEEE P802.11be/D1.1, July 2021 -section 36.3.23.2. It covers channel bringup, -frequency validation, channel switch and also -across all channel width and frequency manipulation. - -Signed-off-by: Karthikeyan Periyasamy -Signed-off-by: Ramya Gnanasekar ---- - hostapd/ctrl_iface.c | 31 +++++++++++++++++++++++++++++++ - src/ap/drv_callbacks.c | 6 ++++++ - src/ap/hostapd.c | 9 +++++++++ - src/ap/ieee802_11.c | 4 ++++ - src/ap/ieee802_11_eht.c | 4 +++- - src/ap/neighbor_db.c | 9 ++++++--- - src/common/defs.h | 1 + - src/common/hw_features_common.c | 3 +++ - src/common/ieee802_11_common.c | 6 ++++++ - src/common/ieee802_11_defs.h | 6 ++++++ - src/drivers/driver.h | 1 + - src/drivers/driver_common.c | 4 ++++ - src/drivers/driver_nl80211.c | 5 +++++ - src/drivers/driver_nl80211_capa.c | 3 +++ - src/drivers/driver_nl80211_event.c | 6 ++++++ - src/drivers/nl80211_copy.h | 2 ++ - wpa_supplicant/ctrl_iface.c | 2 ++ - 17 files changed, 98 insertions(+), 4 deletions(-) - -Index: b/hostapd/ctrl_iface.c -=================================================================== ---- a/hostapd/ctrl_iface.c 2022-08-30 18:41:54.749138965 +0530 -+++ b/hostapd/ctrl_iface.c 2022-08-30 18:41:54.717139244 +0530 -@@ -2637,7 +2637,7 @@ static int hostapd_ctrl_register_frame(s - #ifdef NEED_AP_MLME - static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params) - { -- int idx, bw, bw_idx[] = { 20, 40, 80, 160 }; -+ int idx, bw, bw_idx[] = { 20, 40, 80, 160, 320 }; - u32 start_freq; - - if (is_6ghz_freq(params->freq)) { -@@ -2749,6 +2749,34 @@ static int hostapd_ctrl_check_freq_param - return -1; - } - break; -+ case 320: -+ if (!params->center_freq1 || params->center_freq2 || -+ !params->sec_channel_offset) -+ return -1; -+ -+ switch (params->sec_channel_offset) { -+ case 1: -+ if (params->freq + 150 != params->center_freq1 && -+ params->freq + 70 != params->center_freq1 && -+ params->freq + 30 != params->center_freq1 && -+ params->freq - 10 != params->center_freq1 && -+ params->freq - 50 != params->center_freq1 && -+ params->freq - 130 != params->center_freq1) -+ return -1; -+ break; -+ case -1: -+ if (params->freq + 130 != params->center_freq1 && -+ params->freq + 50 != params->center_freq1 && -+ params->freq + 10 != params->center_freq1 && -+ params->freq - 30 != params->center_freq1 && -+ params->freq - 70 != params->center_freq1 && -+ params->freq - 150 != params->center_freq1) -+ return -1; -+ break; -+ default: -+ return -1; -+ } -+ break; - default: - return -1; - } -@@ -2872,6 +2900,9 @@ static int hostapd_ctrl_iface_chan_switc - case 160: - bandwidth = CHAN_WIDTH_160; - break; -+ case 320: -+ bandwidth = CHAN_WIDTH_320; -+ break; - default: - bandwidth = CHAN_WIDTH_20; - break; -Index: b/src/ap/drv_callbacks.c -=================================================================== ---- a/src/ap/drv_callbacks.c 2022-08-30 18:41:54.749138965 +0530 -+++ b/src/ap/drv_callbacks.c 2022-08-30 18:41:54.721139209 +0530 -@@ -854,6 +854,9 @@ void hostapd_event_sta_opmode_changed(st - case CHAN_WIDTH_160: - txt = "160"; - break; -+ case CHAN_WIDTH_320: -+ txt = "320"; -+ break; - default: - txt = NULL; - break; -@@ -917,6 +920,9 @@ void hostapd_event_ch_switch(struct host - case CHAN_WIDTH_160: - chwidth = CHANWIDTH_160MHZ; - break; -+ case CHAN_WIDTH_320: -+ chwidth = CHANWIDTH_320MHZ; -+ break; - case CHAN_WIDTH_20_NOHT: - case CHAN_WIDTH_20: - case CHAN_WIDTH_40: -@@ -977,7 +983,8 @@ void hostapd_event_ch_switch(struct host - hapd->iconf->ch_switch_eht_config = 0; - - if (width == CHAN_WIDTH_40 || width == CHAN_WIDTH_80 || -- width == CHAN_WIDTH_80P80 || width == CHAN_WIDTH_160) -+ width == CHAN_WIDTH_80P80 || width == CHAN_WIDTH_160 || -+ width == CHAN_WIDTH_320) - hapd->iconf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; - else if (width == CHAN_WIDTH_20 || width == CHAN_WIDTH_20_NOHT) - hapd->iconf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; -Index: b/src/ap/hostapd.c -=================================================================== ---- a/src/ap/hostapd.c 2022-08-30 18:41:54.749138965 +0530 -+++ b/src/ap/hostapd.c 2022-08-30 18:41:54.725139174 +0530 -@@ -3548,6 +3548,7 @@ static int hostapd_change_config_freq(st - case 40: - case 80: - case 160: -+ case 320: - conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; - break; - default: -@@ -3569,6 +3570,9 @@ static int hostapd_change_config_freq(st - case 160: - hostapd_set_oper_chwidth(conf, CHANWIDTH_160MHZ); - break; -+ case 320: -+ hostapd_set_oper_chwidth(conf, CHANWIDTH_320MHZ); -+ break; - default: - return -1; - } -@@ -3617,6 +3621,9 @@ static int hostapd_fill_csa_settings(str - case 160: - bandwidth = CHANWIDTH_160MHZ; - break; -+ case 320: -+ bandwidth = CHANWIDTH_320MHZ; -+ break; - default: - bandwidth = CHANWIDTH_USE_HT; - break; -@@ -3776,6 +3783,9 @@ hostapd_switch_channel_fallback(struct h - case 160: - bw = CHANWIDTH_160MHZ; - break; -+ case 320: -+ bw = CHANWIDTH_320MHZ; -+ break; - default: - wpa_printf(MSG_WARNING, "Unknown CSA bandwidth: %d", - freq_params->bandwidth); -Index: b/src/ap/ieee802_11_eht.c -=================================================================== ---- a/src/ap/ieee802_11_eht.c 2022-08-30 18:41:54.749138965 +0530 -+++ b/src/ap/ieee802_11_eht.c 2022-08-30 18:41:54.725139174 +0530 -@@ -301,7 +301,9 @@ static int check_valid_eht_mcs(struct ho - u8 mcs_count = 1; - - switch (hapd->iface->conf->eht_oper_chwidth) { -- /* TODO CHANWIDTH_320MHZ */ -+ case CHANWIDTH_320MHZ: -+ mcs_count = 3; -+ break; - case CHANWIDTH_80P80MHZ: - case CHANWIDTH_160MHZ: - mcs_count = 2; -Index: b/src/common/defs.h -=================================================================== ---- a/src/common/defs.h 2022-08-30 18:41:54.749138965 +0530 -+++ b/src/common/defs.h 2022-08-30 18:41:54.725139174 +0530 -@@ -430,6 +430,7 @@ enum chan_width { - CHAN_WIDTH_4320, - CHAN_WIDTH_6480, - CHAN_WIDTH_8640, -+ CHAN_WIDTH_320, - CHAN_WIDTH_UNKNOWN - }; - -Index: b/src/common/hw_features_common.c -=================================================================== ---- a/src/common/hw_features_common.c 2022-08-30 18:41:54.749138965 +0530 -+++ b/src/common/hw_features_common.c 2022-08-30 18:41:54.729139140 +0530 -@@ -413,6 +413,8 @@ int hostapd_set_freq_params(struct hosta - else if (oper_chwidth == CHANWIDTH_160MHZ || - oper_chwidth == CHANWIDTH_80P80MHZ) - data->bandwidth = 160; -+ else if (oper_chwidth == CHANWIDTH_320MHZ) -+ data->bandwidth = 320; - else if (sec_channel_offset) - data->bandwidth = 40; - else -@@ -809,6 +811,9 @@ int chan_bw_allowed(const struct hostapd - case 160: - bw_mask = HOSTAPD_CHAN_WIDTH_160; - break; -+ case 320: -+ bw_mask = HOSTAPD_CHAN_WIDTH_320; -+ break; - default: - bw_mask = 0; - break; -Index: b/src/common/ieee802_11_common.c -=================================================================== ---- a/src/common/ieee802_11_common.c 2022-08-30 18:41:54.749138965 +0530 -+++ b/src/common/ieee802_11_common.c 2022-08-30 18:41:54.729139140 +0530 -@@ -1164,6 +1164,9 @@ int ieee80211_chaninfo_to_channel(unsign - case CHAN_WIDTH_8640: - cw = CHANWIDTH_8640MHZ; - break; -+ case CHAN_WIDTH_320: -+ cw = CHANWIDTH_320MHZ; -+ break; - } - - if (ieee80211_freq_to_channel_ext(freq, sec_channel, cw, op_class, -@@ -2273,6 +2276,9 @@ int center_idx_to_bw_6ghz(u8 idx) - /* channels 15, 47, 79...*/ - if ((idx & 0x1f) == 0xf) - return 3; /* 160 MHz */ -+ /* channels 31, 63, 95, 127, 159, 191. */ -+ if ((idx & 0x1f) == 0x1f) -+ return 4; /* 320 MHz */ - - return -1; - } -Index: b/src/common/ieee802_11_defs.h -=================================================================== ---- a/src/common/ieee802_11_defs.h 2022-08-30 18:41:54.749138965 +0530 -+++ b/src/common/ieee802_11_defs.h 2022-08-30 18:41:54.729139140 +0530 -@@ -2241,6 +2241,7 @@ enum phy_type { - /* - * IEEE P802.11-REVmc/D5.0 Table 9-152 - HT/VHT Operation Information - * subfields. -+ * IEEE P802.11be/D1.1 Table 9-322al - EHT Operation Information subfields. - * Note: These definitions are not the same as other CHANWIDTH_*. - */ - enum nr_chan_width { -Index: b/src/drivers/driver.h -=================================================================== ---- a/src/drivers/driver.h 2022-08-30 18:41:54.749138965 +0530 -+++ b/src/drivers/driver.h 2022-08-30 18:41:54.729139140 +0530 -@@ -67,6 +67,7 @@ enum hostapd_chan_width_attr { - HOSTAPD_CHAN_WIDTH_40M = BIT(3), - HOSTAPD_CHAN_WIDTH_80 = BIT(4), - HOSTAPD_CHAN_WIDTH_160 = BIT(5), -+ HOSTAPD_CHAN_WIDTH_320 = BIT(6), - }; - - /* Filter gratuitous ARP */ -Index: b/src/drivers/driver_common.c -=================================================================== ---- a/src/drivers/driver_common.c 2022-08-30 18:41:54.749138965 +0530 -+++ b/src/drivers/driver_common.c 2022-08-30 18:41:54.733139105 +0530 -@@ -118,6 +118,8 @@ const char * channel_width_to_string(enu - return "80+80 MHz"; - case CHAN_WIDTH_160: - return "160 MHz"; -+ case CHAN_WIDTH_320: -+ return "320 MHz"; - default: - return "unknown"; - } -@@ -137,6 +139,8 @@ int channel_width_to_int(enum chan_width - case CHAN_WIDTH_80P80: - case CHAN_WIDTH_160: - return 160; -+ case CHAN_WIDTH_320: -+ return 320; - default: - return 0; - } -Index: b/src/drivers/driver_nl80211.c -=================================================================== ---- a/src/drivers/driver_nl80211.c 2022-08-30 18:41:54.749138965 +0530 -+++ b/src/drivers/driver_nl80211.c 2022-08-30 18:41:54.737139070 +0530 -@@ -215,6 +215,8 @@ enum chan_width convert2width(int width) - return CHAN_WIDTH_80P80; - case NL80211_CHAN_WIDTH_160: - return CHAN_WIDTH_160; -+ case NL80211_CHAN_WIDTH_320: -+ return CHAN_WIDTH_320; - } - return CHAN_WIDTH_UNKNOWN; - } -@@ -5020,6 +5022,9 @@ static int nl80211_put_freq_params(struc - case 160: - cw = NL80211_CHAN_WIDTH_160; - break; -+ case 320: -+ cw = NL80211_CHAN_WIDTH_320; -+ break; - default: - return -EINVAL; - } -Index: b/src/drivers/driver_nl80211_capa.c -=================================================================== ---- a/src/drivers/driver_nl80211_capa.c 2022-08-30 18:41:54.749138965 +0530 -+++ b/src/drivers/driver_nl80211_capa.c 2022-08-30 18:41:54.737139070 +0530 -@@ -1628,6 +1628,9 @@ static void phy_info_freq(struct hostapd - chan->allowed_bw &= ~HOSTAPD_CHAN_WIDTH_80; - if (tb_freq[NL80211_FREQUENCY_ATTR_NO_160MHZ]) - chan->allowed_bw &= ~HOSTAPD_CHAN_WIDTH_160; -+ if (tb_freq[NL80211_FREQUENCY_ATTR_NO_320MHZ]) -+ chan->allowed_bw &= ~HOSTAPD_CHAN_WIDTH_320; -+ - - if (tb_freq[NL80211_FREQUENCY_ATTR_DFS_STATE]) { - enum nl80211_dfs_state state = -Index: b/src/drivers/driver_nl80211_event.c -=================================================================== ---- a/src/drivers/driver_nl80211_event.c 2022-08-30 18:41:54.749138965 +0530 -+++ b/src/drivers/driver_nl80211_event.c 2022-08-30 18:41:54.741139036 +0530 -@@ -675,6 +675,9 @@ static int calculate_chan_offset(int wid - case CHAN_WIDTH_80P80: - freq1 = cf1 - 30; - break; -+ case CHAN_WIDTH_320: -+ freq1 = cf1 - 150; -+ break; - case CHAN_WIDTH_UNKNOWN: - case CHAN_WIDTH_2160: - case CHAN_WIDTH_4320: -@@ -2825,6 +2828,9 @@ static void nl80211_sta_opmode_change_ev - case NL80211_CHAN_WIDTH_160: - ed.sta_opmode.chan_width = CHAN_WIDTH_160; - break; -+ case NL80211_CHAN_WIDTH_320: -+ ed.sta_opmode.chan_width = CHAN_WIDTH_320; -+ break; - default: - ed.sta_opmode.chan_width = CHAN_WIDTH_UNKNOWN; - break; -Index: b/src/drivers/nl80211_copy.h -=================================================================== ---- a/src/drivers/nl80211_copy.h 2022-08-30 18:41:54.749138965 +0530 -+++ b/src/drivers/nl80211_copy.h 2022-08-30 18:42:13.980971726 +0530 -@@ -3947,6 +3947,9 @@ enum nl80211_frequency_attr { - NL80211_FREQUENCY_ATTR_4MHZ, - NL80211_FREQUENCY_ATTR_8MHZ, - NL80211_FREQUENCY_ATTR_16MHZ, -+ NL80211_FREQUENCY_ATTR_PSD, -+ NL80211_FREQUENCY_ATTR_NO_320MHZ, -+ NL80211_FREQUENCY_ATTR_NO_EHT, - - /* keep last */ - __NL80211_FREQUENCY_ATTR_AFTER_LAST, -@@ -4682,6 +4685,7 @@ enum nl80211_chan_width { - NL80211_CHAN_WIDTH_4, - NL80211_CHAN_WIDTH_8, - NL80211_CHAN_WIDTH_16, -+ NL80211_CHAN_WIDTH_320, - - /* keep last */ - __NL80211_CHAN_WIDTH_NUM, -Index: b/wpa_supplicant/ctrl_iface.c -=================================================================== ---- a/wpa_supplicant/ctrl_iface.c 2022-08-30 18:41:54.749138965 +0530 -+++ b/wpa_supplicant/ctrl_iface.c 2022-08-30 18:41:54.745139000 +0530 -@@ -5993,6 +5993,8 @@ static int parse_freq(int chwidth, int f - return CHANWIDTH_80MHZ; - case 160: - return CHANWIDTH_160MHZ; -+ case 320: -+ return CHANWIDTH_320MHZ; - default: - wpa_printf(MSG_DEBUG, "Unknown max oper bandwidth: %d", - chwidth); -Index: b/src/ap/ap_config.h -=================================================================== ---- a/src/ap/ap_config.h 2022-08-30 18:41:54.749138965 +0530 -+++ b/src/ap/ap_config.h 2022-08-30 18:41:54.745139000 +0530 -@@ -1186,7 +1186,8 @@ hostapd_set_oper_chwidth(struct hostapd_ - conf->eht_oper_chwidth = oper_chwidth; - #endif /* CONFIG_IEEE80211BE */ - #ifdef CONFIG_IEEE80211AX -- if (conf->ieee80211ax) -+ if (conf->ieee80211ax && -+ oper_chwidth < CHANWIDTH_320MHZ) - conf->he_oper_chwidth = oper_chwidth; - #endif /* CONFIG_IEEE80211AX */ - conf->vht_oper_chwidth = oper_chwidth; -Index: b/src/ap/ieee802_11_he.c -=================================================================== ---- a/src/ap/ieee802_11_he.c 2022-08-30 18:41:54.749138965 +0530 -+++ b/src/ap/ieee802_11_he.c 2022-08-30 18:41:54.749138965 +0530 -@@ -219,8 +219,8 @@ u8 * hostapd_eid_he_operation(struct hos - pos += 6; /* skip the fixed part */ - - if (is_6ghz_op_class(hapd->iconf->op_class)) { -- u8 seg0 = hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf); -- u8 seg1 = hostapd_get_oper_centr_freq_seg1_idx(hapd->iconf); -+ u8 seg0 = hapd->iface->conf->he_oper_centr_freq_seg0_idx; -+ u8 seg1 = hapd->iface->conf->he_oper_centr_freq_seg1_idx; - - if (hapd->iconf->ru_punct_bitmap) { - hapd->iconf->he_oper_chwidth = diff --git a/feeds/ipq95xx/hostapd/patches/q02-044-02-ACS-Add-ACS-support-for-11be-mode.patch b/feeds/ipq95xx/hostapd/patches/q02-044-02-ACS-Add-ACS-support-for-11be-mode.patch deleted file mode 100644 index 4636abf10..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-044-02-ACS-Add-ACS-support-for-11be-mode.patch +++ /dev/null @@ -1,169 +0,0 @@ -From 6017023786ba26149c18d3f73b3f0b829bab4a61 Mon Sep 17 00:00:00 2001 -From: Sriram R -Date: Mon, 20 Sep 2021 18:49:42 +0530 -Subject: [PATCH] ACS: Add ACS support for 11be mode - -Add ACS support for channels in 11be mode including -320MHz bw support for 6GHz. - -Signed-off-by: Sriram R -Signed-off-by: Ramya Gnanasekar ---- - src/ap/acs.c | 37 +++++++++++++++++++++++++++++++++---- - 1 file changed, 33 insertions(+), 4 deletions(-) - -Index: b/src/ap/acs.c -=================================================================== ---- a/src/ap/acs.c 2022-10-18 16:25:59.609149848 +0530 -+++ b/src/ap/acs.c 2022-10-18 16:26:17.653035183 +0530 -@@ -417,6 +417,18 @@ static int acs_usable_bw160_chan(const s - return 0; - } - -+static int acs_usable_bw320_chan(const struct hostapd_channel_data *chan) -+{ -+ /* Allow start of overlapping 320MHz channels */ -+ const int allowed[] = { 5955, 6115, 6275, 6435, 6595, 6755 }; -+ unsigned int i; -+ -+ for (i = 0; i < ARRAY_SIZE(allowed); i++) -+ if (chan->freq == allowed[i]) -+ return 1; -+ -+ return 0; -+} - - static int acs_survey_is_sufficient(struct freq_survey *survey) - { -@@ -871,7 +883,8 @@ acs_find_ideal_chan_mode(struct hostapd_ - } - - if (mode->mode == HOSTAPD_MODE_IEEE80211A && -- (iface->conf->ieee80211ac || iface->conf->ieee80211ax)) { -+ (iface->conf->ieee80211ac || iface->conf->ieee80211ax || -+ iface->conf->ieee80211be)) { - if (hostapd_get_oper_chwidth(iface->conf) == - CHANWIDTH_80MHZ && - !acs_usable_bw80_chan(chan)) { -@@ -889,6 +902,16 @@ acs_find_ideal_chan_mode(struct hostapd_ - chan->chan); - continue; - } -+ -+ if (iface->conf->ieee80211be && -+ hostapd_get_oper_chwidth(iface->conf) == -+ CHANWIDTH_320MHZ && -+ !acs_usable_bw320_chan(chan)) { -+ wpa_printf(MSG_DEBUG, -+ "ACS: Channel %d: not allowed as primary channel for 320 MHz bandwidth", -+ chan->chan); -+ continue; -+ } - } - - factor = 0; -@@ -1043,7 +1066,8 @@ acs_find_ideal_chan(struct hostapd_iface - iface->conf->secondary_channel) - n_chans = 2; - -- if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) { -+ if (iface->conf->ieee80211ac || iface->conf->ieee80211ax || -+ iface->conf->ieee80211be) { - switch (hostapd_get_oper_chwidth(iface->conf)) { - case CHANWIDTH_80MHZ: - n_chans = 4; -@@ -1051,6 +1075,7 @@ acs_find_ideal_chan(struct hostapd_iface - case CHANWIDTH_160MHZ: - n_chans = 8; - break; -+ /* 320 is supported only in 6GHz 11be mode */ - } - } - -@@ -1095,12 +1120,29 @@ bw_selected: - return rand_chan; - } - -+static int acs_get_center_freq_320mhz(int channel) -+{ -+ if (channel >= 1 && channel <= 45) -+ return 31; -+ else if (channel >= 49 && channel <= 77) -+ return 63; -+ else if (channel >= 81 && channel <= 109) -+ return 95; -+ else if (channel >= 113 && channel <= 141) -+ return 127; -+ else if (channel >= 145 && channel <= 173) -+ return 159; -+ else -+ return 191; -+} - - static void acs_adjust_center_freq(struct hostapd_iface *iface) - { - int psc_chan[] = {37, 53, 69, 85, 101, 117, - 133, 149, 165, 181, 197, 213} ; -- int offset, i; -+ int psc_chan_320_1[] = {69, 85, 133, 149, 197, 213}; -+ int psc_chan_320_2[] = {37, 53, 101, 117, 165, 181, 219}; -+ int offset = 0, i, seg0 = 0; - u8 bw = hostapd_get_oper_chwidth(iface->conf); - bool acs_exclude_6ghz_non_psc = iface->conf->acs_exclude_6ghz_non_psc; - bool is_sec_psc_chan = false; -@@ -1126,6 +1168,27 @@ static void acs_adjust_center_freq(struc - else - offset = 6; - break; -+ case CHANWIDTH_320MHZ: -+ if (acs_exclude_6ghz_non_psc) { -+ for (i = 0; i < ARRAY_SIZE(psc_chan_320_1); i++) { -+ if (psc_chan_320_1[i] == iface->conf->channel) { -+ is_sec_psc_chan = (i%2) ? true : false; -+ offset = is_sec_psc_chan ? 10 : 26; -+ break; -+ } -+ } -+ for (i = 0; i < ARRAY_SIZE(psc_chan_320_2); i++) { -+ if (psc_chan_320_2[i] == iface->conf->channel) { -+ is_sec_psc_chan = (i%2) ? true : false; -+ offset = is_sec_psc_chan ? -22 : -6; -+ break; -+ } -+ } -+ seg0 = iface->conf->channel + offset; -+ } else { -+ seg0 = acs_get_center_freq_320mhz(iface->conf->channel); -+ } -+ /* fallthrough */ - case CHANWIDTH_160MHZ: - /* In 160MHz, if primary 20MHz present in secondary 80MHz, then - * subtract with -6 to find the center frequency of the 160MHz -@@ -1139,12 +1202,16 @@ static void acs_adjust_center_freq(struc - /* TODO: How can this be calculated? Adjust - * acs_find_ideal_chan() */ - wpa_printf(MSG_INFO, -- "ACS: Only VHT20/40/80/160 is supported now"); -+ "ACS: Only VHT20/40/80/160 EHT320 is supported now"); - return; - } - - hostapd_set_oper_centr_freq_seg0_idx(iface->conf, - iface->conf->channel + offset); -+#ifdef CONFIG_IEEE80211BE -+ if (bw == CHANWIDTH_320MHZ) -+ iface->conf->eht_oper_centr_freq_seg0_idx = seg0; -+#endif - } - - -@@ -1201,7 +1268,8 @@ static void acs_study(struct hostapd_ifa - iface->freq = ideal_chan->freq; - iface->conf->ru_punct_bitmap = ideal_chan->ru_punct_bitmap; - -- if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) -+ if (iface->conf->ieee80211ac || iface->conf->ieee80211ax || -+ iface->conf->ieee80211be) - acs_adjust_center_freq(iface); - - err = 0; diff --git a/feeds/ipq95xx/hostapd/patches/q02-044-nl80211-sync-green-ap-changes.patch b/feeds/ipq95xx/hostapd/patches/q02-044-nl80211-sync-green-ap-changes.patch deleted file mode 100644 index 0cd89d9c9..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-044-nl80211-sync-green-ap-changes.patch +++ /dev/null @@ -1,68 +0,0 @@ -From d486b8c3149bcaa5dc40182f0d640fe1edec2672 Mon Sep 17 00:00:00 2001 -From: Sivashankari Madhavan -Date: Wed, 4 May 2022 15:09:09 +0530 -Subject: [PATCH] Sync the NL green AP changes to hostapd - -Sync the nl80211 Green ap changes into hostapd nl80211_copy - -Signed-off-by: Sivashankari Madhavan ---- - src/drivers/nl80211_copy.h | 19 ++++++++++++++----- - 1 file changed, 14 insertions(+), 5 deletions(-) - -diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h -index 77c7a84..7c51646 100644 ---- a/src/drivers/nl80211_copy.h -+++ b/src/drivers/nl80211_copy.h -@@ -350,11 +350,13 @@ - * or %NL80211_ATTR_MAC. - * - * @NL80211_CMD_GET_BEACON: (not used) -- * @NL80211_CMD_SET_BEACON: change the beacon on an access point interface -+ * @NL80211_CMD_UPDATE_AP: Update AP parameters which can vary at the -+ * runtime of BSS. change the beacon on an access point interface - * using the %NL80211_ATTR_BEACON_HEAD and %NL80211_ATTR_BEACON_TAIL - * attributes. For drivers that generate the beacon and probe responses -- * internally, the following attributes must be provided: %NL80211_ATTR_IE, -- * %NL80211_ATTR_IE_PROBE_RESP and %NL80211_ATTR_IE_ASSOC_RESP. -+ * internally, the following attributes must be provided for the -+ * beacon update: %NL80211_ATTR_IE, %NL80211_ATTR_IE_PROBE_RESP and -+ * %NL80211_ATTR_IE_ASSOC_RESP. - * @NL80211_CMD_START_AP: Start AP operation on an AP interface, parameters - * are like for %NL80211_CMD_SET_BEACON, and additionally parameters that - * do not change are used, these include %NL80211_ATTR_BEACON_INTERVAL, -@@ -1217,7 +1219,8 @@ enum nl80211_commands { - NL80211_CMD_DEL_KEY, - - NL80211_CMD_GET_BEACON, -- NL80211_CMD_SET_BEACON, -+ NL80211_CMD_UPDATE_AP, -+ NL80211_CMD_SET_BEACON = NL80211_CMD_UPDATE_AP, - NL80211_CMD_START_AP, - NL80211_CMD_NEW_BEACON = NL80211_CMD_START_AP, - NL80211_CMD_STOP_AP, -@@ -2597,6 +2600,11 @@ enum nl80211_commands { - * association request when used with NL80211_CMD_NEW_STATION). Can be set - * only if %NL80211_STA_FLAG_WME is set. - * -+ * @NL80211_ATTR_AP_PS: enable/disable AP power save. -+ * This attribute type is u8 and valid range is 0 to 1. -+ * 0 for disable AP power save mode. -+ * 1 for enable AP power save mode. -+ * - * @NUM_NL80211_ATTR: total number of nl80211_attrs available - * @NL80211_ATTR_MAX: highest attribute number currently defined - * @__NL80211_ATTR_AFTER_LAST: internal use -@@ -3123,7 +3131,8 @@ enum nl80211_attrs { - NL80211_ATTR_RU_PUNCT_SUPP_BW, - NL80211_ATTR_RU_PUNCT_SUPP_HE, - NL80211_ATTR_RU_PUNCT_BITMAP, -- -+ -+ NL80211_ATTR_AP_PS, - /* add attributes here, update the policy in nl80211.c */ - - __NL80211_ATTR_AFTER_LAST, --- -2.17.1 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-045-mesh_add_EHT_support.patch b/feeds/ipq95xx/hostapd/patches/q02-045-mesh_add_EHT_support.patch deleted file mode 100644 index ec5232e98..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-045-mesh_add_EHT_support.patch +++ /dev/null @@ -1,345 +0,0 @@ -From d7713b5ca78966dd7ea6a3bdd35511503dc59537 Mon Sep 17 00:00:00 2001 -From: Ramya Gnanasekar -Date: Thu, 14 Apr 2022 12:14:03 +0530 -Subject: [PATCH] mesh: add EHT support - -Add mesh_eht_enabled and eht ssid config to include EHT capability -and EHT operation IEs in mesh PLINK action frames. -Update mesh_eht_enabled from EHT capability advertised for mesh mode. -Support for mesh channelization in 320MHz. - -Signed-off-by: Ramya Gnanasekar -Signed-off-by: Sathishkumar Muruganandam ---- -Index: b/wpa_supplicant/ap.c -=================================================================== ---- a/wpa_supplicant/ap.c 2022-07-08 10:12:42.614954957 +0530 -+++ b/wpa_supplicant/ap.c 2022-07-08 10:12:42.586955263 +0530 -@@ -324,6 +324,14 @@ int wpa_supplicant_conf_ap_ht(struct wpa - - if (mode && is_6ghz_freq(ssid->frequency) && - conf->hw_mode == HOSTAPD_MODE_IEEE80211A) { -+ if (mode->eht_capab[wpas_mode_to_ieee80211_mode( -+ ssid->mode)].eht_supported && -+ ssid->eht) -+ conf->ieee80211be = 1; -+ if (mode->he_capab[wpas_mode_to_ieee80211_mode( -+ ssid->mode)].he_supported && -+ ssid->he) -+ conf->ieee80211ax = 1; - #ifdef CONFIG_P2P - wpas_conf_ap_he_6ghz(wpa_s, mode, ssid, conf); - #endif /* CONFIG_P2P */ -@@ -407,6 +415,10 @@ int wpa_supplicant_conf_ap_ht(struct wpa - ssid->mode)].he_supported && - ssid->he) - conf->ieee80211ax = 1; -+ if (mode->eht_capab[wpas_mode_to_ieee80211_mode( -+ ssid->mode)].eht_supported && -+ ssid->eht) -+ conf->ieee80211be = 1; - - if (mode->vht_capab && ssid->vht) { - conf->ieee80211ac = 1; -Index: b/wpa_supplicant/config.c -=================================================================== ---- a/wpa_supplicant/config.c 2022-07-08 10:12:42.614954957 +0530 -+++ b/wpa_supplicant/config.c 2022-07-08 10:12:42.586955263 +0530 -@@ -2812,6 +2812,7 @@ static const struct parse_data ssid_fiel - { INT_RANGE(disable_40mhz_scan, 0, 1)}, - { INT_RANGE(beacon_tx_mode, 1, 2)}, - { INT_RANGE(enable_160mhz_bw, 0, 1)}, -+ { INT_RANGE(enable_320mhz_bw, 0, 1)}, - }; - - #undef OFFSET -Index: b/wpa_supplicant/mesh.c -=================================================================== ---- a/wpa_supplicant/mesh.c 2022-07-08 10:12:42.614954957 +0530 -+++ b/wpa_supplicant/mesh.c 2022-07-08 10:12:42.586955263 +0530 -@@ -227,7 +227,7 @@ static int wpas_mesh_update_freq_params( - ifmsh->conf->ieee80211n, - ifmsh->conf->ieee80211ac, - ifmsh->conf->ieee80211ax, -- 0, -+ ifmsh->conf->ieee80211be, - ifmsh->conf->secondary_channel, - hostapd_get_oper_chwidth(ifmsh->conf), - hostapd_get_oper_centr_freq_seg0_idx(ifmsh->conf), -@@ -468,6 +468,9 @@ static int wpa_supplicant_mesh_init(stru - case 160: - conf->op_class = 134; - break; -+ case 320: -+ conf->op_class = 137; -+ break; - default: - conf->op_class = 131; - break; -@@ -659,6 +662,7 @@ int wpa_supplicant_join_mesh(struct wpa_ - wpa_s->mesh_ht_enabled = !!params->freq.ht_enabled; - wpa_s->mesh_vht_enabled = !!params->freq.vht_enabled; - wpa_s->mesh_he_enabled = !!params->freq.he_enabled; -+ wpa_s->mesh_eht_enabled = !!params->freq.eht_enabled; - if (params->freq.ht_enabled && params->freq.sec_channel_offset) - ssid->ht40 = params->freq.sec_channel_offset; - -@@ -678,6 +682,9 @@ int wpa_supplicant_join_mesh(struct wpa_ - case 160: - ssid->max_oper_chwidth = CHANWIDTH_160MHZ; - break; -+ case 320: -+ ssid->max_oper_chwidth = CHANWIDTH_320MHZ; -+ break; - default: - ssid->max_oper_chwidth = CHANWIDTH_USE_HT; - break; -@@ -685,6 +692,8 @@ int wpa_supplicant_join_mesh(struct wpa_ - } - if (wpa_s->mesh_he_enabled) - ssid->he = 1; -+ if (wpa_s->mesh_eht_enabled) -+ ssid->eht = 1; - if (ssid->beacon_int > 0) - params->beacon_int = ssid->beacon_int; - else if (wpa_s->conf->beacon_int > 0) -Index: b/wpa_supplicant/mesh_mpm.c -=================================================================== ---- a/wpa_supplicant/mesh_mpm.c 2022-07-08 10:12:42.614954957 +0530 -+++ b/wpa_supplicant/mesh_mpm.c 2022-07-08 10:12:42.586955263 +0530 -@@ -257,6 +257,16 @@ static void mesh_mpm_send_plink_action(s - 3 + sizeof(struct ieee80211_he_6ghz_band_cap); - } - #endif /* CONFIG_IEEE80211AX */ -+#ifdef CONFIG_IEEE80211BE -+ if (type != PLINK_CLOSE && wpa_s->mesh_eht_enabled) { -+ buf_len += 3 + -+ EHT_MAC_CAPAB_MAX_LEN + -+ EHT_PHY_CAPAB_MAX_LEN + -+ EHT_MCS_NSS_CAPAB_MAX_LEN + -+ EHT_PPE_THRESH_CAPAB_MAX_LEN; -+ buf_len += 3 + sizeof(struct ieee80211_eht_operation); -+ } -+#endif /* CONFIG_IEEE80211BE */ - if (type != PLINK_CLOSE) - buf_len += conf->rsn_ie_len; /* RSN IE */ - #ifdef CONFIG_OCV -@@ -391,6 +401,20 @@ static void mesh_mpm_send_plink_action(s - wpabuf_put_data(buf, he_capa_oper, pos - he_capa_oper); - } - #endif /* CONFIG_IEEE80211AX */ -+#ifdef CONFIG_IEEE80211BE -+ if (type != PLINK_CLOSE && wpa_s->mesh_eht_enabled) { -+ u8 eht_capa_oper[3 + -+ EHT_MAC_CAPAB_MAX_LEN + -+ EHT_PHY_CAPAB_MAX_LEN + -+ EHT_MCS_NSS_CAPAB_MAX_LEN + -+ EHT_PPE_THRESH_CAPAB_MAX_LEN + -+ 3 + sizeof(struct ieee80211_eht_operation)]; -+ pos = hostapd_eid_eht_capab(bss, eht_capa_oper, -+ IEEE80211_MODE_MESH); -+ pos = hostapd_eid_eht_operation(bss, pos, IEEE80211_MODE_MESH); -+ wpabuf_put_data(buf, eht_capa_oper, pos - eht_capa_oper); -+ } -+#endif /* CONFIG_IEEE80211BE */ - - #ifdef CONFIG_OCV - if (type != PLINK_CLOSE && conf->ocv) { -@@ -760,6 +784,11 @@ static struct sta_info * mesh_mpm_add_pe - copy_sta_he_6ghz_capab(data, sta, elems->he_6ghz_band_cap); - #endif /* CONFIG_IEEE80211AX */ - -+#ifdef CONFIG_IEEE80211BE -+ copy_sta_eht_capab(data, sta, IEEE80211_MODE_MESH, elems->he_capabilities, -+ elems->eht_capabilities, elems->eht_capabilities_len); -+#endif /* CONFIG_IEEE80211BE */ -+ - if (hostapd_get_aid(data, sta) < 0) { - wpa_msg(wpa_s, MSG_ERROR, "No AIDs available"); - ap_free_sta(data, sta); -@@ -780,6 +809,8 @@ static struct sta_info * mesh_mpm_add_pe - params.he_capab = sta->he_capab; - params.he_capab_len = sta->he_capab_len; - params.he_6ghz_capab = sta->he_6ghz_capab; -+ params.eht_capab = sta->eht_capab; -+ params.eht_capab_len = sta->eht_capab_len; - params.flags |= WPA_STA_WMM; - params.flags_mask |= WPA_STA_AUTHENTICATED; - if (conf->security == MESH_CONF_SEC_NONE) { -Index: b/wpa_supplicant/wpa_supplicant.c -=================================================================== ---- a/wpa_supplicant/wpa_supplicant.c 2022-07-08 10:12:42.614954957 +0530 -+++ b/wpa_supplicant/wpa_supplicant.c 2022-07-08 10:14:31.153768442 +0530 -@@ -2478,7 +2478,25 @@ static bool ibss_mesh_is_80mhz_avail(int - return true; - } - -+static int ibss_get_center_320mhz(int channel) -+{ -+ int seg0; -+ -+ if (channel >= 1 && channel <= 45) -+ seg0 = 31; -+ else if (channel >= 49 && channel <= 77) -+ seg0 = 63; -+ else if (channel >= 81 && channel <= 109) -+ seg0 = 95; -+ else if (channel >= 113 && channel <= 141) -+ seg0 = 127; -+ else if (channel >= 145 && channel <= 173) -+ seg0 = 159; -+ else -+ seg0 = 191; - -+ return seg0; -+} - void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s, - const struct wpa_ssid *ssid, - struct hostapd_freq_params *freq) -@@ -2500,6 +2518,9 @@ void ibss_mesh_setup_freq(struct wpa_sup - 6595, 6655, 6675, 6735, - 6755, 6815, 6835, 6895, - 6915, 6975, 6995, 7055 }; -+ unsigned int bw_320[] = { 5500, 5720, 5955, 6255, 6115, -+ 6415, 6275, 6575, 6435, 6735, -+ 6595, 6895, 6755, 7055}; - struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL; - u8 channel, chan_80mhz; - int i, chan_idx, ht40 = -1, res, obss_scan = 1; -@@ -2736,8 +2757,9 @@ skip_to_6ghz: - if (!vht_freq.vht_enabled && !is_6ghz) - return; - -- /* Enable HE with VHT for 5 GHz */ -+ /* Enable HE, EHT with VHT for 5 GHz */ - vht_freq.he_enabled = mode->he_capab[ieee80211_mode].he_supported; -+ vht_freq.eht_enabled = mode->eht_capab[ieee80211_mode].eht_supported; - - #ifdef CONFIG_HE_OVERRIDES - if (is_24ghz) -@@ -2801,6 +2823,19 @@ skip_to_6ghz: - } - } - -+ if ((ssid->enable_320mhz_bw) && (mode->eht_capab[ieee80211_mode].phy_cap[EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_IDX] & -+ EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_MASK) && is_6ghz) { -+ -+ for (i = 0; i < ARRAY_SIZE(bw_320); i+=2) { -+ if (freq->freq >= bw_320[i] && -+ freq->freq <= bw_320[i+1]) -+ break; -+ } -+ -+ seg0 = ibss_get_center_320mhz(freq->channel); -+ chwidth = CHANWIDTH_320MHZ; -+ } -+ - if (ssid->max_oper_chwidth == CHANWIDTH_80P80MHZ) { - /* setup center_freq2, bandwidth */ - for (k = 0; k < ARRAY_SIZE(bw_80_160); k++) { -@@ -2870,9 +2905,10 @@ skip_to_6ghz: - freq->channel, ssid->enable_edmg, - ssid->edmg_channel, freq->ht_enabled, - vht_freq.vht_enabled, vht_freq.he_enabled, -- 0, freq->sec_channel_offset, -+ vht_freq.eht_enabled, freq->sec_channel_offset, - chwidth, seg0, seg1, vht_caps, -- &mode->he_capab[ieee80211_mode], NULL, -+ &mode->he_capab[ieee80211_mode], -+ &mode->eht_capab[ieee80211_mode], - 0, freq->ru_punct_bitmap, - freq->ru_punct_ofdma) != 0) - return; -Index: b/wpa_supplicant/wpa_supplicant_i.h -=================================================================== ---- a/wpa_supplicant/wpa_supplicant_i.h 2022-07-08 10:12:42.614954957 +0530 -+++ b/wpa_supplicant/wpa_supplicant_i.h 2022-07-08 10:12:42.598955132 +0530 -@@ -1033,6 +1033,7 @@ struct wpa_supplicant { - unsigned int mesh_ht_enabled:1; - unsigned int mesh_vht_enabled:1; - unsigned int mesh_he_enabled:1; -+ unsigned int mesh_eht_enabled:1; - struct wpa_driver_mesh_join_params *mesh_params; - #ifdef CONFIG_PMKSA_CACHE_EXTERNAL - /* struct external_pmksa_cache::list */ -Index: b/hostapd/config_file.c -=================================================================== ---- a/hostapd/config_file.c 2022-07-08 10:12:42.614954957 +0530 -+++ b/hostapd/config_file.c 2022-07-08 10:12:42.598955132 +0530 -@@ -4266,6 +4266,8 @@ static int hostapd_config_fill(struct ho - } else if (os_strcmp(buf, "wowlan_triggers") == 0) { - os_free(bss->wowlan_triggers); - bss->wowlan_triggers = os_strdup(pos); -+ } else if (os_strcmp(buf, "enable_320mhz_bw") == 0) { -+ conf->enable_320mhz_bw = atoi(pos); - } else if (os_strcmp(buf, "enable_160mhz_bw") == 0) { - conf->enable_160mhz_bw = atoi(pos); - } else if (os_strcmp(buf, "disable_40mhz_scan") == 0) { -Index: b/src/ap/ap_config.h -=================================================================== ---- a/src/ap/ap_config.h 2022-07-08 10:12:42.614954957 +0530 -+++ b/src/ap/ap_config.h 2022-07-08 10:12:42.598955132 +0530 -@@ -1152,6 +1152,7 @@ struct hostapd_config { - u16 ru_punct_bitmap; - u8 ru_punct_ofdma; - u8 ru_punct_acs_threshold; -+ int enable_320mhz_bw; - }; - - static inline u8 hostapd_get_he_6ghz_reg_pwr_type(struct hostapd_config *conf) -Index: b/src/drivers/driver.h -=================================================================== ---- a/src/drivers/driver.h 2022-07-08 10:12:42.614954957 +0530 -+++ b/src/drivers/driver.h 2022-07-08 10:12:42.598955132 +0530 -@@ -1287,6 +1287,10 @@ struct wpa_driver_associate_params { - * Enable 160MHz BW - set it 1 to enable mesh 160MHz 6G - */ - int enable_160mhz_bw; -+ /** -+ * Enable 320MHz BW - set it 1 to enable mesh 320MHz 6G -+ */ -+ int enable_320mhz_bw; - }; - - enum hide_ssid { -Index: b/wpa_supplicant/config_file.c -=================================================================== ---- a/wpa_supplicant/config_file.c 2022-07-08 10:12:42.614954957 +0530 -+++ b/wpa_supplicant/config_file.c 2022-07-08 10:12:42.606955044 +0530 -@@ -893,6 +893,7 @@ static void wpa_config_write_network(FIL - INT(disable_40mhz_scan); - INT(beacon_tx_mode); - INT(enable_160mhz_bw); -+ INT(enable_320mhz_bw); - #undef STR - #undef INT - #undef INT_DEF -Index: b/wpa_supplicant/config_ssid.h -=================================================================== ---- a/wpa_supplicant/config_ssid.h 2022-07-08 10:12:42.614954957 +0530 -+++ b/wpa_supplicant/config_ssid.h 2022-07-08 10:12:42.610955000 +0530 -@@ -1223,6 +1223,10 @@ struct wpa_ssid { - * Enable 160MHz BW - set it 1 to enable mesh 160MHz 6G - */ - int enable_160mhz_bw; -+ /** -+ * Enable 320MHz BW - set it 1 to enable mesh 320MHz 6G -+ */ -+ int enable_320mhz_bw; - }; - - #endif /* CONFIG_SSID_H */ -Index: b/src/drivers/driver_nl80211.c -=================================================================== ---- a/src/drivers/driver_nl80211.c 2022-07-08 10:12:42.614954957 +0530 -+++ b/src/drivers/driver_nl80211.c 2022-07-08 10:12:42.610955000 +0530 -@@ -5002,7 +5002,8 @@ static int nl80211_put_freq_params(struc - is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G || - hw_mode == HOSTAPD_MODE_IEEE80211B; - -- if (freq->vht_enabled || (freq->he_enabled && !is_24ghz)) { -+ if (freq->vht_enabled || ((freq->he_enabled || freq->eht_enabled) && -+ !is_24ghz)) { - enum nl80211_chan_width cw; - - wpa_printf(MSG_DEBUG, " * bandwidth=%d", freq->bandwidth); diff --git a/feeds/ipq95xx/hostapd/patches/q02-046-hostapd-Add-5GHz-240MHz-support.patch b/feeds/ipq95xx/hostapd/patches/q02-046-hostapd-Add-5GHz-240MHz-support.patch deleted file mode 100644 index 93f4508e7..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-046-hostapd-Add-5GHz-240MHz-support.patch +++ /dev/null @@ -1,253 +0,0 @@ -From 5205496c33b432d7621ffff86df6540d6854fff2 Mon Sep 17 00:00:00 2001 -From: Hari Chandrakanthan -Date: Thu, 8 Sep 2022 21:10:01 +0530 -Subject: [PATCH] hostapd: Add 5GHz 240MHz support - -240MHz is supported in 5GHz for single band from channel -100 - 144 with right hand 80MHz puncturing in 320MHz bandwidth. - -EHT phy capability for advertising 320MHz support in 6GHz is -reused for 5GHz as well if 320MHz is configured. EHT opertional -IE is also used to advertise the bandwidth and the center frequency -of the AP. - -Signed-off-by: Karthik M -Signed-off-by: Ramya Gnanasekar -Signed-off-by: Hari Chandrakanthan ---- - src/ap/beacon.c | 8 +++++++- - src/ap/dfs.c | 19 ++++++++++++++++--- - src/ap/hw_features.c | 6 +++++- - src/ap/ieee802_11_eht.c | 10 +++++++--- - src/common/hw_features_common.c | 16 ++++++++++++++++ - src/common/ieee802_11_common.c | 7 +++++++ - src/common/ieee802_11_common.h | 1 + - src/common/ieee802_11_defs.h | 1 + - 8 files changed, 60 insertions(+), 8 deletions(-) - -diff --git a/src/ap/beacon.c b/src/ap/beacon.c -index 9536e76..e03f343 100644 ---- a/src/ap/beacon.c -+++ b/src/ap/beacon.c -@@ -434,18 +434,24 @@ static u8 * hostapd_eid_ecsa(struct hostapd_data *hapd, u8 *eid) - static u8 * hostapd_eid_supported_op_classes(struct hostapd_data *hapd, u8 *eid) - { - u8 op_class, channel; -+ int ch_width; - - if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA) || - !hapd->iface->freq) - return eid; - -+ ch_width = hostapd_get_oper_chwidth(hapd->iconf); - if (ieee80211_freq_to_channel_ext(hapd->iface->freq, - hapd->iconf->secondary_channel, -- hostapd_get_oper_chwidth(hapd->iconf), -+ ch_width, - &op_class, &channel) == - NUM_HOSTAPD_MODES) - return eid; - -+ /*op_class for 5GHz 320MHz bw is not defined in spec. So use op_class of 160MHz*/ -+ if (is_5ghz_freq(hapd->iface->freq) && ch_width == CHANWIDTH_320MHZ) -+ op_class = 129; -+ - *eid++ = WLAN_EID_SUPPORTED_OPERATING_CLASSES; - *eid++ = 2; - -diff --git a/src/ap/dfs.c b/src/ap/dfs.c -index f8de1c2..12e47a7 100644 ---- a/src/ap/dfs.c -+++ b/src/ap/dfs.c -@@ -411,7 +411,8 @@ static int dfs_get_start_chan_idx(struct hostapd_iface *iface, int *seg1_start) - channel_no -= 4; - - /* VHT/HE */ -- if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) { -+ if (iface->conf->ieee80211ac || iface->conf->ieee80211ax || -+ iface->conf->ieee80211be) { - switch (hostapd_get_oper_chwidth(iface->conf)) { - case CHANWIDTH_USE_HT: - break; -@@ -429,6 +430,10 @@ static int dfs_get_start_chan_idx(struct hostapd_iface *iface, int *seg1_start) - chan_seg1 = hostapd_get_oper_centr_freq_seg1_idx( - iface->conf) - 6; - break; -+ case CHANWIDTH_320MHZ: -+ channel_no = hostapd_get_oper_centr_freq_seg0_idx( -+ iface->conf) - 30; -+ break; - default: - wpa_printf(MSG_INFO, - "DFS only VHT20/40/80/160/80+80 is supported now"); -@@ -722,6 +727,10 @@ static int set_dfs_state(struct hostapd_iface *iface, int freq, int ht_enabled, - n_chans = 8; - frequency = cf1 - 70; - break; -+ case CHAN_WIDTH_320: -+ n_chans = 16; -+ frequency = cf1 - 150; -+ break; - default: - wpa_printf(MSG_INFO, "DFS chan_width %d not supported", - chan_width); -@@ -921,13 +930,14 @@ int hostapd_handle_dfs(struct hostapd_iface *iface) - hostapd_set_state(iface, HAPD_IFACE_DFS); - wpa_printf(MSG_DEBUG, "DFS start CAC on %d MHz", iface->freq); - wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START -- "freq=%d chan=%d sec_chan=%d, width=%d, seg0=%d, seg1=%d, cac_time=%ds", -+ "freq=%d chan=%d sec_chan=%d, width=%d, seg0=%d, seg1=%d, cac_time=%ds bitmap:0x%04x", - iface->freq, - iface->conf->channel, iface->conf->secondary_channel, - hostapd_get_oper_chwidth(iface->conf), - hostapd_get_oper_centr_freq_seg0_idx(iface->conf), - hostapd_get_oper_centr_freq_seg1_idx(iface->conf), -- iface->dfs_cac_ms / 1000); -+ iface->dfs_cac_ms / 1000, -+ iface->conf->ru_punct_bitmap); - - res = hostapd_start_dfs_cac( - iface, iface->conf->hw_mode, iface->freq, iface->conf->channel, -@@ -1552,6 +1562,9 @@ int hostapd_is_dfs_overlap(struct hostapd_iface *iface, enum chan_width width, - case CHAN_WIDTH_160: - half_width = 80; - break; -+ case CHAN_WIDTH_320: -+ half_width = 160; -+ break; - default: - wpa_printf(MSG_WARNING, "DFS chanwidth %d not supported", - width); -diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c -index f66c649..6a7a655 100644 ---- a/src/ap/hw_features.c -+++ b/src/ap/hw_features.c -@@ -929,7 +929,7 @@ static int hostapd_is_usable_edmg(struct hostapd_iface *iface) - static int hostapd_is_usable_ru_punct_bitmap(struct hostapd_iface *iface) - { - struct hostapd_config *conf = iface->conf; -- u8 bw, start_chan; -+ int bw, start_chan; - - if (!conf->ru_punct_bitmap) { - conf->ru_punct_ofdma = 0; -@@ -971,6 +971,10 @@ static int hostapd_is_usable_ru_punct_bitmap(struct hostapd_iface *iface) - bw = 160; - start_chan = conf->eht_oper_centr_freq_seg0_idx - 14; - break; -+ case 9: -+ bw = 320; -+ start_chan = conf->eht_oper_centr_freq_seg0_idx - 30; -+ break; - default: - return 0; - } -diff --git a/src/ap/ieee802_11_eht.c b/src/ap/ieee802_11_eht.c -index 8aca0de..f54fee3 100644 ---- a/src/ap/ieee802_11_eht.c -+++ b/src/ap/ieee802_11_eht.c -@@ -74,8 +74,10 @@ static u8 ieee80211_eht_mcs_set_size(const u8 *he_phy_cap, - sz += EHT_PHYCAP_MCS_NSS_LEN_20MHZ_PLUS; - - if (eht_phy_cap[EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_IDX] & -- EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_MASK) -+ EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_MASK) { - sz += EHT_PHYCAP_MCS_NSS_LEN_20MHZ_PLUS; -+ sz += EHT_PHYCAP_MCS_NSS_LEN_160MHZ; -+ } - - return sz; - } -@@ -110,7 +112,7 @@ u8 * hostapd_eid_eht_capab(struct hostapd_data *hapd, u8 *eid, - struct eht_capabilities *eht_cap; - struct ieee80211_eht_capabilities *cap; - size_t mcs_nss_len, ppe_thresh_len; -- u8 *pos = eid, *length_pos; -+ u8 *pos = eid, *length_pos, chwidth; - - mode = hapd->iface->current_mode; - if (!mode) -@@ -128,8 +130,10 @@ u8 * hostapd_eid_eht_capab(struct hostapd_data *hapd, u8 *eid, - os_memset(cap, 0, sizeof(*cap)); - os_memcpy(cap->mac_cap, eht_cap->mac_cap, EHT_MAC_CAPAB_MAX_LEN); - os_memcpy(cap->phy_cap, eht_cap->phy_cap, EHT_PHY_CAPAB_MAX_LEN); -+ chwidth = hapd->iconf->eht_oper_chwidth; - -- if (!is_6ghz_op_class(hapd->iconf->op_class)) -+ if (!is_6ghz_op_class(hapd->iconf->op_class) && -+ (chwidth != CHANWIDTH_320MHZ)) - cap->phy_cap[EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_IDX] &= - ~EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_MASK; - if (!hapd->iface->conf->eht_phy_capab.su_beamformer) -diff --git a/src/common/hw_features_common.c b/src/common/hw_features_common.c -index 0c7607d..3381d8f 100644 ---- a/src/common/hw_features_common.c -+++ b/src/common/hw_features_common.c -@@ -667,6 +667,22 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, - return -1; - } - break; -+ case CHANWIDTH_320MHZ: -+ data->bandwidth = 320; -+ if (center_segment1) { -+ wpa_printf(MSG_ERROR, -+ "320 MHz: center segment 1 should not be set"); -+ return -1; -+ } -+ if (channel >= 100 && channel <= 144) { -+ center_segment0 = 130; -+ data->center_freq1 = 5650; -+ } else { -+ wpa_printf(MSG_ERROR, -+ "320 MHz: Configured Channel is not supported"); -+ return -1; -+ } -+ break; - } - - return 0; -diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c -index 1e5c641..e68dca6 100644 ---- a/src/common/ieee802_11_common.c -+++ b/src/common/ieee802_11_common.c -@@ -2284,6 +2284,13 @@ int center_idx_to_bw_6ghz(u8 idx) - return -1; - } - -+bool is_5ghz_freq(int freq) -+{ -+ if ((freq >= 5180 && freq < 5600) || -+ (freq >= 5660 && freq < 5825)) -+ return true; -+ return false; -+} - - bool is_6ghz_freq(int freq) - { -diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h -index 48d66d8..e60afb3 100644 ---- a/src/common/ieee802_11_common.h -+++ b/src/common/ieee802_11_common.h -@@ -268,6 +268,7 @@ u8 country_to_global_op_class(const char *country, u8 op_class); - - const struct oper_class_map * get_oper_class(const char *country, u8 op_class); - int oper_class_bw_to_int(const struct oper_class_map *map); -+bool is_5ghz_freq(int freq); - int center_idx_to_bw_6ghz(u8 idx); - bool is_6ghz_freq(int freq); - bool is_6ghz_op_class(u8 op_class); -diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h -index dad1435..766ec1d 100644 ---- a/src/common/ieee802_11_defs.h -+++ b/src/common/ieee802_11_defs.h -@@ -2530,6 +2530,7 @@ struct ieee80211_eht_operation { - #define EHT_NSS_MAX_STREAMS 8 - #define EHT_PHYCAP_MCS_NSS_LEN_20MHZ_ONLY 4 - #define EHT_PHYCAP_MCS_NSS_LEN_20MHZ_PLUS 3 -+#define EHT_PHYCAP_MCS_NSS_LEN_160MHZ 3 - - /* IEEE P802.11be/D1.4, May 2021, 9.4.2.295c.5 EHT PPE Thresholds field */ - #define EHT_PPE_THRES_NSS_SHIFT 0 --- -2.7.4 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-046-hostapd-DFS-ACS-5GHz-240MHz-support.patch b/feeds/ipq95xx/hostapd/patches/q02-046-hostapd-DFS-ACS-5GHz-240MHz-support.patch deleted file mode 100644 index 1ae178568..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-046-hostapd-DFS-ACS-5GHz-240MHz-support.patch +++ /dev/null @@ -1,260 +0,0 @@ -From 19cb10a62d2cd4507cbe28bf36a1522fd8d5870a Mon Sep 17 00:00:00 2001 -From: Karthik M -Date: Fri, 24 Jun 2022 10:28:31 +0530 -Subject: [PATCH] hostapd: Add ACS and DFS support for 5GHz BW240MHZ - -ACS dynamically punctures the channels based on the -noise levels. Incase of 5G 240MHZ bandwidth, we need -to use static punturing bitmap. - -In case of radar, We have only one channel in 240MHz. -The bandwidth should downgrade to 160MHz -and choose a channel. - -Signed-off-by: Karthik M ---- - src/ap/acs.c | 19 +++++++++++++++---- - src/ap/dfs.c | 34 ++++++++++++++++++++++++++++++---- - 2 files changed, 45 insertions(+), 8 deletions(-) - -Index: b/src/ap/acs.c -=================================================================== ---- a/src/ap/acs.c 2022-09-19 10:33:57.084303028 +0530 -+++ b/src/ap/acs.c 2022-09-19 10:33:57.076303097 +0530 -@@ -420,7 +420,7 @@ static int acs_usable_bw160_chan(const s - static int acs_usable_bw320_chan(const struct hostapd_channel_data *chan) - { - /* Allow start of overlapping 320MHz channels */ -- const int allowed[] = { 5955, 6115, 6275, 6435, 6595, 6755 }; -+ const int allowed[] = { 5500, 5955, 6115, 6275, 6435, 6595, 6755 }; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(allowed); i++) -@@ -657,6 +657,8 @@ static int is_common_24ghz_chan(int chan - #define ACS_24GHZ_PREFER_1_6_11 0.8 - #endif /* ACS_24GHZ_PREFER_1_6_11 */ - -+#define PUNCTURING_PATTERN_5G_320MHZ 0XF000 -+ - static void acs_update_puncturing_bitmap(struct hostapd_iface *iface, - struct hostapd_hw_modes *mode, u32 bw, - int n_chans, -@@ -669,14 +671,32 @@ static void acs_update_puncturing_bitmap - struct hostapd_config *conf = iface->conf; - long double threshold = factor * conf->ru_punct_acs_threshold / 100; - -+ if (is_24ghz_mode(mode->mode) || (bw < 80)) -+ return; -+ -+ /* -+ * 5GHz 320Mhz operates with static punturing bitmap. Overiding the dynammic -+ * bitmap calculation -+ */ -+ -+ if (!is_6ghz_op_class(iface->conf->op_class) && bw == 320) { -+ if ((conf->ru_punct_bitmap & PUNCTURING_PATTERN_5G_320MHZ) == -+ PUNCTURING_PATTERN_5G_320MHZ) { -+ chan->ru_punct_bitmap = conf->ru_punct_bitmap; -+ goto bitmap_selected; -+ } else { -+ wpa_printf(MSG_DEBUG, "ACS : Invalid ru_punct_bitmap for 5G %X", -+ conf->ru_punct_bitmap); -+ return; -+ } -+ } -+ - /* - * If threshold is 0 or user configured puncturing pattern is - * available then don't add additional puncturing. - */ -- if (!conf->ru_punct_acs_threshold || conf->ru_punct_bitmap) -- return; - -- if (is_24ghz_mode(mode->mode) || (bw < 80)) -+ if (!conf->ru_punct_acs_threshold || conf->ru_punct_bitmap) - return; - - for (i = 0; i < n_chans; i++) { -@@ -701,6 +721,11 @@ static void acs_update_puncturing_bitmap - chan->ru_punct_bitmap |= BIT(i); - } - -+bitmap_selected: -+ wpa_printf(MSG_DEBUG, -+ "ACS: Calculated ru_punct_bitmap is %X and ru_punct_ofdma is %X", -+ chan->ru_punct_bitmap,conf->ru_punct_ofdma); -+ - if (!is_ru_punct_bitmap_valid(bw, - (chan->freq - first_chan->freq) / 20, - chan->ru_punct_bitmap, -@@ -919,6 +944,11 @@ acs_find_ideal_chan_mode(struct hostapd_ - factor = chan->interference_factor; - total_weight = 1; - -+ /* 5GHz is supported for 240Mhz and so reducing number of channels*/ -+ if(!is_6ghz_op_class(iface->conf->op_class) && -+ hostapd_get_oper_chwidth(iface->conf) == CHANWIDTH_320MHZ) -+ n_chans = n_chans - 4; -+ - for (j = 1; j < n_chans; j++) { - adj_chan = acs_find_chan(iface, chan->freq + (j * 20)); - if (!adj_chan) -@@ -1018,7 +1048,7 @@ acs_find_ideal_chan_mode(struct hostapd_ - *ideal_factor = factor; - *ideal_chan = chan; - -- if (iface->conf->ieee80211ax) -+ if (iface->conf->ieee80211ax || iface->conf->ieee80211be) - acs_update_puncturing_bitmap(iface, mode, bw, - n_chans, chan, - factor, 0); -@@ -1075,7 +1105,9 @@ acs_find_ideal_chan(struct hostapd_iface - case CHANWIDTH_160MHZ: - n_chans = 8; - break; -- /* 320 is supported only in 6GHz 11be mode */ -+ case CHANWIDTH_320MHZ: -+ n_chans = 16; -+ break; - } - } - -Index: b/src/ap/dfs.c -=================================================================== ---- a/src/ap/dfs.c 2022-09-19 10:33:57.084303028 +0530 -+++ b/src/ap/dfs.c 2022-09-19 10:42:06.192255486 +0530 -@@ -20,7 +20,6 @@ - #include "beacon.h" - #include "eloop.h" - -- - static int dfs_get_used_n_chans(struct hostapd_iface *iface, int *seg1) - { - int n_chans = 1; -@@ -30,7 +29,8 @@ static int dfs_get_used_n_chans(struct h - if (iface->conf->ieee80211n && iface->conf->secondary_channel) - n_chans = 2; - -- if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) { -+ if (iface->conf->ieee80211ac || iface->conf->ieee80211ax || -+ iface->conf->ieee80211be) { - switch (hostapd_get_oper_chwidth(iface->conf)) { - case CHANWIDTH_USE_HT: - break; -@@ -44,6 +44,9 @@ static int dfs_get_used_n_chans(struct h - n_chans = 4; - *seg1 = 4; - break; -+ case CHANWIDTH_320MHZ: -+ n_chans = 12; -+ break; - default: - break; - } -@@ -94,6 +97,12 @@ static int dfs_is_chan_allowed(struct ho - * 50, 114, 163 - */ - int allowed_160[] = { 36, 100, 149 }; -+ /* -+ * EHT320 valid channels based on center frequency: -+ * 100 -+ */ -+ int allowed_320[] = {100}; -+ - int *allowed = allowed_40; - unsigned int i, allowed_no = 0; - -@@ -110,6 +119,10 @@ static int dfs_is_chan_allowed(struct ho - allowed = allowed_160; - allowed_no = ARRAY_SIZE(allowed_160); - break; -+ case 16: -+ allowed = allowed_320; -+ allowed_no = ARRAY_SIZE(allowed_320); -+ break; - default: - wpa_printf(MSG_DEBUG, "Unknown width for %d channels", n_chans); - break; -@@ -337,7 +350,8 @@ static void dfs_adjust_center_freq(struc - u8 *oper_centr_freq_seg0_idx, - u8 *oper_centr_freq_seg1_idx) - { -- if (!iface->conf->ieee80211ac && !iface->conf->ieee80211ax) -+ if (!iface->conf->ieee80211ac && !iface->conf->ieee80211ax && -+ !iface->conf->ieee80211be) - return; - - if (!chan) -@@ -364,6 +378,9 @@ static void dfs_adjust_center_freq(struc - *oper_centr_freq_seg0_idx = chan->chan + 6; - *oper_centr_freq_seg1_idx = sec_chan_idx_80p80 + 6; - break; -+ case CHANWIDTH_320MHZ: -+ *oper_centr_freq_seg0_idx = chan->chan + 30; -+ break; - - default: - wpa_printf(MSG_INFO, -@@ -711,7 +728,7 @@ static int set_dfs_state(struct hostapd_ - frequency = cf1 - 70; - break; - case CHAN_WIDTH_320: -- n_chans = 16; -+ n_chans = 12; - frequency = cf1 - 150; - break; - default: -@@ -775,6 +792,10 @@ static int dfs_are_channels_overlapped(s - radar_n_chans = 8; - frequency = cf1 - 70; - break; -+ case CHAN_WIDTH_320: -+ radar_n_chans = 12; -+ frequency = cf1 - 150; -+ break; - default: - wpa_printf(MSG_INFO, "DFS chan_width %d not supported", - chan_width); -@@ -1021,6 +1042,7 @@ dfs_downgrade_bandwidth(struct hostapd_i - u8 *oper_centr_freq_seg1_idx, int *skip_radar) - { - struct hostapd_channel_data *channel; -+ int oper_chwidth; - - for (;;) { - channel = dfs_get_valid_channel(iface, secondary_channel, -@@ -1036,7 +1058,6 @@ dfs_downgrade_bandwidth(struct hostapd_i - if (*skip_radar) { - *skip_radar = 0; - } else { -- int oper_chwidth; - - oper_chwidth = hostapd_get_oper_chwidth(iface->conf); - if (oper_chwidth == CHANWIDTH_USE_HT) { -@@ -1047,9 +1068,13 @@ dfs_downgrade_bandwidth(struct hostapd_i - iface->conf->secondary_channel = 0; - *skip_radar = 1; - continue; -+ } else if (oper_chwidth == CHANWIDTH_320MHZ) { -+ oper_chwidth = oper_chwidth - 7; -+ } else { -+ oper_chwidth = oper_chwidth - 1; - } - *skip_radar = 1; -- hostapd_set_oper_chwidth(iface->conf, oper_chwidth - 1); -+ hostapd_set_oper_chwidth(iface->conf, oper_chwidth); - } - } - -Index: b/src/common/hw_features_common.c -=================================================================== ---- a/src/common/hw_features_common.c 2022-09-19 10:33:57.084303028 +0530 -+++ b/src/common/hw_features_common.c 2022-09-19 10:33:57.080303063 +0530 -@@ -794,6 +794,7 @@ u32 num_chan_to_bw(int num_chans) - case 2: - case 4: - case 8: -+ case 16: - return num_chans * 20; - default: - return 20; diff --git a/feeds/ipq95xx/hostapd/patches/q02-046-hostapd-add-support-to-disable-channel-switch-during.patch b/feeds/ipq95xx/hostapd/patches/q02-046-hostapd-add-support-to-disable-channel-switch-during.patch deleted file mode 100644 index 7258227b0..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-046-hostapd-add-support-to-disable-channel-switch-during.patch +++ /dev/null @@ -1,283 +0,0 @@ -From 00cada639346750210160441c00b5e953aa57d40 Mon Sep 17 00:00:00 2001 -From: Hari Chandrakanthan -Date: Mon, 11 Jul 2022 22:30:27 +0530 -Subject: [PATCH] hostapd : add support to disable channel switch during radar - detection - -A new config disable_csa_dfs is added. -When the above config is enabled, the usual channel switch during -radar detection is skipped. - -Rather hostapd/wpa_supplicant waits for 500ms for the user to do -the manual channel switch using hostapd_cli/wpa_cli. - -If no channel switch or channel set is issued within 500ms, -the interface is disabled. - -sample channel switch that disables the radar handling timer : -wpa_cli -i wlan2 chan_switch 5 5745 center_freq1=5775 sec_channel_offset=1 -bandwidth=80 vht ht he -hostapd_cli -i wlan3 chan_switch 5 5745 center_freq1=5775 sec_channel_offset=1 -bandwidth=80 vht ht he - -sample set channel cmd that disables the radar handling timer: -hostapd_cli -i wlan0 set channel 100 -wpa_cli -i wlan1 set_network 0 frequency 5500 - -Signed-off-by: Hari Chandrakanthan ---- - hostapd/config_file.c | 2 ++ - hostapd/ctrl_iface.c | 14 ++++++++++++++ - hostapd/hostapd.conf | 4 ++++ - src/ap/ap_config.h | 1 + - src/ap/dfs.c | 22 ++++++++++++++++++++-- - src/ap/dfs.h | 4 +++- - wpa_supplicant/ap.c | 12 +++++++++++- - wpa_supplicant/config.c | 2 ++ - wpa_supplicant/config.h | 1 + - wpa_supplicant/ctrl_iface.c | 12 +++++++++++- - wpa_supplicant/mesh.c | 2 ++ - wpa_supplicant/wpa_supplicant.conf | 4 ++++ - 12 files changed, 75 insertions(+), 5 deletions(-) - -diff --git a/hostapd/config_file.c b/hostapd/config_file.c -index 2aae477..2e4440b 100644 ---- a/hostapd/config_file.c -+++ b/hostapd/config_file.c -@@ -4704,6 +4704,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, - return 1; - } - #endif /* CONFIG_IEEE80211BE */ -+ } else if (os_strcmp(buf, "disable_csa_dfs") == 0) { -+ conf->disable_csa_dfs = atoi(pos); - } else { - wpa_printf(MSG_ERROR, - "Line %d: unknown configuration item '%s'", -diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c -index 1060c48..c053bf3 100644 ---- a/hostapd/ctrl_iface.c -+++ b/hostapd/ctrl_iface.c -@@ -1499,6 +1499,13 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd) - } else if (os_strcasecmp(cmd, "setband") == 0) { - ret = hostapd_ctrl_iface_set_band(hapd, value); - } else { -+ if (hapd->iface->conf->disable_csa_dfs && -+ ((os_strcmp(cmd, "channel") == 0) && -+ ((os_strcmp(value, "acs_survey") != 0) && -+ (atoi(value) != 0)))) { -+ eloop_cancel_timeout(hostapd_dfs_radar_handling_timeout, -+ hapd->iface, NULL); -+ } - ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value); - if (ret) - return ret; -@@ -2876,6 +2883,13 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface, - int bandwidth; - u8 chan; - -+ if (iface->conf->disable_csa_dfs == 1) { -+ wpa_printf(MSG_DEBUG, "chanswitch interface %s : cancel radar" -+ " handling timer", iface->conf->bss[0]->iface); -+ eloop_cancel_timeout(hostapd_dfs_radar_handling_timeout, -+ iface, NULL); -+ } -+ - ret = hostapd_parse_csa_settings(pos, &settings); - if (ret) - return ret; -diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf -index e4328d3..944acd5 100644 ---- a/hostapd/hostapd.conf -+++ b/hostapd/hostapd.conf -@@ -229,6 +229,10 @@ channel=1 - # (default 0, i.e., not constraint) - #min_tx_power=20 - -+# disable_csa_dfs option can be used to skip the channel switch in hostapd -+# during radar detection -+#disable_csa_dfs=1 -+ - # Beacon interval in kus (1.024 ms) (default: 100; range 15..65535) - beacon_int=100 - -diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h -index e16b123..e63b11a 100644 ---- a/src/ap/ap_config.h -+++ b/src/ap/ap_config.h -@@ -1153,6 +1153,7 @@ struct hostapd_config { - u8 ru_punct_ofdma; - u8 ru_punct_acs_threshold; - int enable_320mhz_bw; -+ int disable_csa_dfs; - }; - - static inline u8 hostapd_get_he_6ghz_reg_pwr_type(struct hostapd_config *conf) -diff --git a/src/ap/dfs.c b/src/ap/dfs.c -index 11bdd38..ea65cb4 100644 ---- a/src/ap/dfs.c -+++ b/src/ap/dfs.c -@@ -1105,6 +1105,17 @@ void hostapd_dfs_test_mode_csa_timeout(void *eloop_data, void *user_data) - ieee802_11_set_beacon(hapd); - } - -+void hostapd_dfs_radar_handling_timeout(void *eloop_data, void *user_data) -+{ -+ struct hostapd_iface *iface = eloop_data; -+ -+ wpa_printf(MSG_INFO, "Disabling interface %s since no channel" -+ " switch is initiated within radar handling timeout", -+ iface->conf->bss[0]->iface); -+ -+ hostapd_disable_iface(iface); -+} -+ - static int hostapd_dfs_testmode_set_beacon_csa(struct hostapd_iface *iface) - { - struct hostapd_data *hapd = iface->bss[0]; -@@ -1361,8 +1372,15 @@ int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq, - if (!res) - return 0; - -- /* radar detected while operating, switch the channel. */ -- res = hostapd_dfs_start_channel_switch(iface); -+ if (!iface->conf->disable_csa_dfs) { -+ /* radar detected while operating, switch the channel. */ -+ res = hostapd_dfs_start_channel_switch(iface); -+ } else if (!eloop_is_timeout_registered(hostapd_dfs_radar_handling_timeout, -+ iface, NULL)) { -+ eloop_register_timeout(0, HAPD_DFS_RADAR_CH_SWITCH_WAIT_DUR, -+ hostapd_dfs_radar_handling_timeout, -+ iface, NULL); -+ } - - return res; - } -diff --git a/src/ap/dfs.h b/src/ap/dfs.h -index 3a7c3e4..0cd0ced 100644 ---- a/src/ap/dfs.h -+++ b/src/ap/dfs.h -@@ -11,6 +11,8 @@ - - /* CSA beacon duration in seconds for dfs testing mode */ - #define HOSTAPD_DFS_TEST_MODE_CSA_DUR 1 -+/* Wait duration between radar detection and channel switch*/ -+#define HAPD_DFS_RADAR_CH_SWITCH_WAIT_DUR 500000 - - void hostapd_dfs_test_mode_csa_timeout(void *eloop_data, void *user_data); - -@@ -37,5 +39,5 @@ int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq, - int hostapd_handle_dfs_offload(struct hostapd_iface *iface); - int hostapd_is_dfs_overlap(struct hostapd_iface *iface, enum chan_width width, - int center_freq); -- -+void hostapd_dfs_radar_handling_timeout(void *eloop_data, void *user_data); - #endif /* DFS_H */ -diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c -index 2b90019..884a0e2 100644 ---- a/wpa_supplicant/ap.c -+++ b/wpa_supplicant/ap.c -@@ -1624,7 +1624,17 @@ int ap_switch_channel(struct wpa_supplicant *wpa_s, - int ap_ctrl_iface_chanswitch(struct wpa_supplicant *wpa_s, const char *pos) - { - struct csa_settings settings; -- int ret = hostapd_parse_csa_settings(pos, &settings); -+ int ret; -+ -+ if (wpa_s->ifmsh && wpa_s->ifmsh->conf->disable_csa_dfs == 1) { -+ wpa_printf(MSG_DEBUG, "wpa chanswitch interface %s :" -+ " cancelling radar handling timeout", -+ wpa_s->ifmsh->conf->bss[0]->iface); -+ eloop_cancel_timeout(hostapd_dfs_radar_handling_timeout, -+ wpa_s->ifmsh, NULL); -+ } -+ -+ ret = hostapd_parse_csa_settings(pos, &settings); - - if (ret) - return ret; -diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c -index 502d3d6..dcc3868 100644 ---- a/wpa_supplicant/config.c -+++ b/wpa_supplicant/config.c -@@ -5456,6 +5456,8 @@ static const struct global_parse_data global_fields[] = { - #endif /* CONFIG_PASN */ - { INT_RANGE(he_6ghz_reg_client_type, 1, 2), - CFG_CHANGED_HE_6GHZ_CLIENT_TYPE}, -+ { INT_RANGE(disable_csa_dfs, 0, 1), 0 }, -+ - }; - - #undef FUNC -diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h -index 7479583..89be860 100644 ---- a/wpa_supplicant/config.h -+++ b/wpa_supplicant/config.h -@@ -1710,6 +1710,7 @@ struct wpa_config { - * 2 = SUBORDINATE CLIENT - */ - u8 he_6ghz_reg_client_type; -+ int disable_csa_dfs; - }; - - -diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c -index 1aff200..61aeea7 100644 ---- a/wpa_supplicant/ctrl_iface.c -+++ b/wpa_supplicant/ctrl_iface.c -@@ -60,6 +60,7 @@ - #include "dpp_supplicant.h" - #include "sme.h" - #include "ap/ieee802_11.h" -+#include "ap/dfs.h" - - #ifdef __NetBSD__ - #include -@@ -3628,7 +3629,16 @@ static int wpa_supplicant_ctrl_iface_set_network( - id, name); - wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", - (u8 *) value, os_strlen(value)); -- -+#ifdef NEED_AP_MLME -+ if ((os_strcmp(name, "frequency") == 0) && -+ (wpa_s->ifmsh && wpa_s->ifmsh->conf->disable_csa_dfs == 1)) { -+ wpa_printf(MSG_DEBUG, "wpa interface %s :" -+ " cancelling radar handling timeout", -+ wpa_s->ifmsh->conf->bss[0]->iface); -+ eloop_cancel_timeout(hostapd_dfs_radar_handling_timeout, -+ wpa_s->ifmsh, NULL); -+ } -+#endif - ssid = wpa_config_get_network(wpa_s->conf, id); - if (ssid == NULL) { - wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " -diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c -index 0372c08..948f365 100644 ---- a/wpa_supplicant/mesh.c -+++ b/wpa_supplicant/mesh.c -@@ -554,6 +554,8 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, - conf->basic_rates[rate_len] = -1; - } - -+ ifmsh->conf->disable_csa_dfs = wpa_s->conf->disable_csa_dfs; -+ - /* While it can enhance performance to switch the primary channel, which - * is also the secondary channel of another network at the same time), - * to the other primary channel, problems exist with this in mesh -diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf -index 162e81d..29a0fe1 100644 ---- a/wpa_supplicant/wpa_supplicant.conf -+++ b/wpa_supplicant/wpa_supplicant.conf -@@ -1704,6 +1704,10 @@ fast_reauth=1 - #Set 1 to enable 160MHz in Mesh mode - #enable_160mhz_bw=1 - -+# disable_csa_dfs option can be used to skip the channel switch in wpa_supplicant -+# during radar detection -+#disable_csa_dfs=1 -+ - # Example blocks: - - # Simple case: WPA-PSK, PSK as an ASCII passphrase, allow all valid ciphers --- -2.7.4 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-046-wpa_supplicant-add-RU-puncturing-support.patch b/feeds/ipq95xx/hostapd/patches/q02-046-wpa_supplicant-add-RU-puncturing-support.patch deleted file mode 100644 index ff3dd08d6..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-046-wpa_supplicant-add-RU-puncturing-support.patch +++ /dev/null @@ -1,333 +0,0 @@ -From 340c9ab10eabb7a962f16cbb0a3abd492942ef57 Mon Sep 17 00:00:00 2001 -From: Rameshkumar Sundaram -Date: Wed, 25 May 2022 11:32:01 +0530 -Subject: [PATCH] wpa_supplicant: add RU puncturing support - -Retrieve the driver support for RU puncturing which is advertised -using the attribute NL80211_ATTR_RU_PUNCT_SUPP_BW. -Value indicates the bandwidths in which puncturing is supported - -80 MHz, 160 MHz or 320 MHz. -Absence of the attribute or the value 0 means the driver does not -support this feature. - -Add New option 'ru_punct_bitmap' to configure RU puncturing bitmap -and pass the configured bitmap to kernel via frequency params -during join mesh if driver supports puncturing pattern for configured -Bandwidth. -Kernel will validate the pattern against spec allowed patterns -(IEEE P802.11be/D1.5, Table 36-30) - -Parse EHT Operational IE of received mesh beacons and validate & -and send Peer mesh node's RU puncturing pattern as part of station -add command (NL80211_CMD_NEW_STATION). - -Signed-off-by: Rameshkumar Sundaram ---- - src/ap/hw_features.c | 9 +++++++++ - src/drivers/driver.h | 7 +++++++ - src/drivers/driver_nl80211.c | 6 ++++++ - wpa_supplicant/ap.c | 5 +++-- - wpa_supplicant/config.c | 2 ++ - wpa_supplicant/config_file.c | 1 + - wpa_supplicant/config_ssid.h | 6 ++++++ - wpa_supplicant/mesh.c | 4 ++++ - wpa_supplicant/mesh_mpm.c | 41 ++++++++++++++++++++++++++++++++++++++ - wpa_supplicant/wpa_supplicant.c | 26 ++++++++++++++++++++++-- - wpa_supplicant/wpa_supplicant.conf | 7 +++++++ - wpa_supplicant/wpa_supplicant_i.h | 2 ++ - 12 files changed, 112 insertions(+), 4 deletions(-) - -diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c -index 1dcd0d0..f66c649 100644 ---- a/src/ap/hw_features.c -+++ b/src/ap/hw_features.c -@@ -949,6 +949,15 @@ static int hostapd_is_usable_ru_punct_bitmap(struct hostapd_iface *iface) - return 0; - } - -+#ifdef CONFIG_MESH -+ if (iface->mconf != NULL) { -+ wpa_printf(MSG_DEBUG, -+ "%s: Mesh RU bitmap will be validated in kernel while joining the mesh network", -+ iface->bss[0]->conf->iface); -+ return 1; -+ } -+#endif -+ - switch (conf->eht_oper_chwidth) { - case 0: - wpa_printf(MSG_ERROR, -diff --git a/src/drivers/driver.h b/src/drivers/driver.h -index 038379b..3c73e68 100644 ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -1291,6 +1291,12 @@ struct wpa_driver_associate_params { - * Enable 320MHz BW - set it 1 to enable mesh 320MHz 6G - */ - int enable_320mhz_bw; -+ -+ /** -+ * RU puncturing bitmap - Each bit corresponds to a 20 MHz subchannel, -+ * lowest bit for the channel with the lowest frequency. -+ * Bit set to 1 indicates that the subchannel is punctured, otherwise active.*/ -+ u16 ru_punct_bitmap; - }; - - enum hide_ssid { -@@ -2381,6 +2387,7 @@ struct hostapd_sta_add_params { - const u8 *supp_oper_classes; - size_t supp_oper_classes_len; - int support_p2p_ps; -+ u16 ru_punct_bitmap; - }; - - struct mac_address { -diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c -index a89097d..44b4330 100644 ---- a/src/drivers/driver_nl80211.c -+++ b/src/drivers/driver_nl80211.c -@@ -5419,6 +5419,12 @@ static int wpa_driver_nl80211_sta_add(void *priv, - nla_nest_end(msg, wme); - } - -+ if (params->ru_punct_bitmap) { -+ wpa_printf(MSG_DEBUG, " * eht ru puncturing bitmap=0x%x", params->ru_punct_bitmap); -+ if (nla_put_u16(msg, NL80211_ATTR_RU_PUNCT_BITMAP, params->ru_punct_bitmap)) -+ goto fail; -+ } -+ - ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); - msg = NULL; - if (ret) -diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c -index 30f33c4..2c55e95 100644 ---- a/wpa_supplicant/ap.c -+++ b/wpa_supplicant/ap.c -@@ -417,9 +417,10 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s, - conf->ieee80211ax = 1; - if (mode->eht_capab[wpas_mode_to_ieee80211_mode( - ssid->mode)].eht_supported && -- ssid->eht) -+ ssid->eht) { - conf->ieee80211be = 1; -- -+ conf->ru_punct_bitmap = ssid->ru_punct_bitmap; -+ } - if (mode->vht_capab && ssid->vht) { - conf->ieee80211ac = 1; - conf->vht_capab |= mode->vht_capab; -diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c -index 502d3d6..f8945ee 100644 ---- a/wpa_supplicant/config.c -+++ b/wpa_supplicant/config.c -@@ -2813,6 +2813,7 @@ static const struct parse_data ssid_fields[] = { - { INT_RANGE(beacon_tx_mode, 1, 2)}, - { INT_RANGE(enable_160mhz_bw, 0, 1)}, - { INT_RANGE(enable_320mhz_bw, 0, 1)}, -+ { INT(ru_punct_bitmap) }, - }; - - #undef OFFSET -@@ -3330,6 +3331,7 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid) - ssid->mac_addr = -1; - ssid->max_oper_chwidth = DEFAULT_MAX_OPER_CHWIDTH; - ssid->beacon_tx_mode = DEFAULT_BEACON_TX_MODE; -+ ssid->ru_punct_bitmap = 0; - } - - -diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c -index f47973b..f8a519b 100644 ---- a/wpa_supplicant/config_file.c -+++ b/wpa_supplicant/config_file.c -@@ -894,6 +894,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) - INT(beacon_tx_mode); - INT(enable_160mhz_bw); - INT(enable_320mhz_bw); -+ INT(ru_punct_bitmap); - #undef STR - #undef INT - #undef INT_DEF -diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h -index 1704e0d..fdd40f9 100644 ---- a/wpa_supplicant/config_ssid.h -+++ b/wpa_supplicant/config_ssid.h -@@ -1227,6 +1227,12 @@ struct wpa_ssid { - * Enable 320MHz BW - set it 1 to enable mesh 320MHz 6G - */ - int enable_320mhz_bw; -+ -+ /** -+ * RU puncturing bitmap - Each bit corresponds to a 20 MHz subchannel, -+ * lowest bit for the channel with the lowest frequency. -+ * Bit set to 1 indicates that the subchannel is punctured, otherwise active.*/ -+ u16 ru_punct_bitmap; - }; - - #endif /* CONFIG_SSID_H */ -diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c -index 0372c08..231065d 100644 ---- a/wpa_supplicant/mesh.c -+++ b/wpa_supplicant/mesh.c -@@ -411,6 +411,7 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, - ifmsh->num_bss = 1; - ifmsh->enable_iface_cb = wpa_supplicant_mesh_enable_iface_cb; - ifmsh->disable_iface_cb = wpa_supplicant_mesh_disable_iface_cb; -+ ifmsh->ru_punct_supp_bw = wpa_s->ru_punct_supp_bw; - ifmsh->bss = os_calloc(wpa_s->ifmsh->num_bss, - sizeof(struct hostapd_data *)); - if (!ifmsh->bss) -@@ -493,6 +494,9 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, - wpa_s->mesh_params->handle_dfs = true; - } - -+ if (ssid->eht) -+ conf->ru_punct_bitmap = freq->ru_punct_bitmap; -+ - bss->iconf = conf; - ifmsh->conf = conf; - -diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c -index d69af3f..8899434 100644 ---- a/wpa_supplicant/mesh_mpm.c -+++ b/wpa_supplicant/mesh_mpm.c -@@ -728,6 +728,7 @@ static struct sta_info * mesh_mpm_add_peer(struct wpa_supplicant *wpa_s, - struct hostapd_data *data = wpa_s->ifmsh->bss[0]; - struct sta_info *sta; - struct ieee80211_ht_operation *oper; -+ struct ieee80211_eht_operation *eht_oper_ie; - int ret; - - if (elems->mesh_config_len >= 7 && -@@ -811,6 +812,46 @@ static struct sta_info * mesh_mpm_add_peer(struct wpa_supplicant *wpa_s, - params.he_6ghz_capab = sta->he_6ghz_capab; - params.eht_capab = sta->eht_capab; - params.eht_capab_len = sta->eht_capab_len; -+#ifdef CONFIG_IEEE80211BE -+ if (elems->eht_operation && elems->eht_operation_len >= sizeof(*eht_oper_ie)) { -+ u16 bw = 0; -+ u16 start_chan = 0; -+ u16 pri_chan = wpa_s->ifmsh->conf->channel; -+ -+ eht_oper_ie = (struct ieee80211_eht_operation *)elems->eht_operation; -+ if (eht_oper_ie->width >= EHT_OPERATION_CHANNEL_WIDTH_80MHZ && -+ eht_oper_ie->disable_sub_chan_bitmap_present && -+ eht_oper_ie->disabled_subchannel_bitmap) { -+ params.ru_punct_bitmap = eht_oper_ie->disabled_subchannel_bitmap; -+ /* Validate Peer's puncture bitmap and reset if invalid */ -+ switch (eht_oper_ie->width) { -+ case EHT_OPERATION_CHANNEL_WIDTH_80MHZ: -+ bw = 80; -+ start_chan = eht_oper_ie->ccfs - 6; -+ if (!is_ru_punct_bitmap_valid(bw, (pri_chan - start_chan) / 4, -+ params.ru_punct_bitmap, 0)) -+ params.ru_punct_bitmap = 0; -+ break; -+ case EHT_OPERATION_CHANNEL_WIDTH_160MHZ: -+ bw = 160; -+ start_chan = eht_oper_ie->ccfs - 14; -+ if (!is_ru_punct_bitmap_valid(bw, (pri_chan - start_chan) / 4, -+ params.ru_punct_bitmap, 0)) -+ params.ru_punct_bitmap = 0; -+ break; -+ case EHT_OPERATION_CHANNEL_WIDTH_320MHZ: -+ bw = 320; -+ start_chan = eht_oper_ie->ccfs - 30; -+ if (!is_ru_punct_bitmap_valid(bw, (pri_chan - start_chan) / 4, -+ params.ru_punct_bitmap, 0)) -+ params.ru_punct_bitmap = 0; -+ break; -+ default: -+ params.ru_punct_bitmap = 0; -+ } -+ } -+ } -+#endif /* CONFIG_IEEE80211BE */ - params.flags |= WPA_STA_WMM; - params.flags_mask |= WPA_STA_AUTHENTICATED; - if (conf->security == MESH_CONF_SEC_NONE) { -diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c -index 226b1c9..e030f79 100644 ---- a/wpa_supplicant/wpa_supplicant.c -+++ b/wpa_supplicant/wpa_supplicant.c -@@ -2904,6 +2904,27 @@ skip_to_6ghz: - freq->eht_enabled = 0; - } - #endif /* CONFIG_EHT_OVERRIDES */ -+ freq->ru_punct_bitmap = ssid->ru_punct_bitmap; -+ freq->ru_punct_ofdma = 0; /* Default to disabled for mesh. */ -+ -+ if (ssid->ru_punct_bitmap && wpa_s->drv_capa_known) { -+ switch (chwidth) { -+ case CHANWIDTH_320MHZ: -+ break; -+ case CHANWIDTH_160MHZ: -+ if (wpa_s->ru_punct_supp_bw == CHANWIDTH_320MHZ) -+ freq->ru_punct_bitmap = 0; -+ break; -+ case CHANWIDTH_80MHZ: -+ if ((wpa_s->ru_punct_supp_bw == CHANWIDTH_160MHZ) || -+ (wpa_s->ru_punct_supp_bw == CHANWIDTH_320MHZ)) -+ freq->ru_punct_bitmap = 0; -+ break; -+ default: -+ freq->ru_punct_bitmap = 0; -+ } -+ } -+ - if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq, - freq->channel, ssid->enable_edmg, - ssid->edmg_channel, freq->ht_enabled, -@@ -2918,8 +2939,8 @@ skip_to_6ghz: - - *freq = vht_freq; - -- wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d", -- freq->center_freq1, freq->center_freq2, freq->bandwidth); -+ wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d ru_punct_bitmap 0x%x", -+ freq->center_freq1, freq->center_freq2, freq->bandwidth, freq->ru_punct_bitmap); - } - - -@@ -6913,6 +6934,7 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, - wpa_s->num_multichan_concurrent = - capa.num_multichan_concurrent; - wpa_s->wmm_ac_supported = capa.wmm_ac_supported; -+ wpa_s->ru_punct_supp_bw = capa.ru_punct_supp_bw; - - if (capa.mac_addr_rand_scan_supported) - wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN; -diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf -index 162e81d..325a19d 100644 ---- a/wpa_supplicant/wpa_supplicant.conf -+++ b/wpa_supplicant/wpa_supplicant.conf -@@ -1704,6 +1704,13 @@ fast_reauth=1 - #Set 1 to enable 160MHz in Mesh mode - #enable_160mhz_bw=1 - -+# RU puncturing bitmap (16 bits) where each bit corresponds to -+# a 20 MHz channel in the given bandwidth, bit 0 corresponding to the channel -+# with lowest frequency. -+# Bit set to 1 indicates that the channel is punctured, otherwise active. -+# Default value is 0 indicating that no channel is punctured. -+#ru_punct_bitmap=4 -+ - # Example blocks: - - # Simple case: WPA-PSK, PSK as an ASCII passphrase, allow all valid ciphers -diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h -index 7888c3f..f642c68 100644 ---- a/wpa_supplicant/wpa_supplicant_i.h -+++ b/wpa_supplicant/wpa_supplicant_i.h -@@ -1521,6 +1521,8 @@ struct wpa_supplicant { - unsigned int enable_dscp_policy_capa:1; - unsigned int connection_dscp:1; - unsigned int wait_for_dscp_req:1; -+ /* Minimum bandwidth the driver supports RU puncturing */ -+ u8 ru_punct_supp_bw; - }; - - --- -2.7.4 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-047-hostapd-Fix-tx-power-envelope-for-non-PSD-countries.patch b/feeds/ipq95xx/hostapd/patches/q02-047-hostapd-Fix-tx-power-envelope-for-non-PSD-countries.patch deleted file mode 100644 index 73d51b507..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-047-hostapd-Fix-tx-power-envelope-for-non-PSD-countries.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 11873ac90db3f8c73088a1d7b4bd44509b832348 Mon Sep 17 00:00:00 2001 -From: Ramya Gnanasekar -Date: Fri, 21 Oct 2022 19:20:46 +0530 -Subject: [PATCH] hostapd: Fix tx power envelope for non PSD countries - -TX power envelope will contain PSD value for countries. -In case of non PSD countries, it is expected to carry -max EIRP for the channel received from FW through reg -rules. -Updated the power value in IE with max EIRP power for -other non PSD countries - -Signed-off-by: Ramya Gnanasekar - -diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c -index b7c55ca..2563a26 100644 ---- a/src/ap/ieee802_11.c -+++ b/src/ap/ieee802_11.c -@@ -7084,6 +7084,7 @@ u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid) - if (i == mode->num_channels) - return eid; - -+ chan = &mode->channels[i]; - /* For now, 6GHz has only support for Indoor AP type - * From IEEE P802.11ax/D7.0: An AP that is an - * Indoor Access Point per regulatory rules shall send at least -@@ -7105,9 +7106,12 @@ u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid) - */ - if (ap_type == AP_TYPE_6GHZ_INDOOR_AP) { - tx_pwr_cat = REG_SUBORDINATE_CLIENT; -- psd = mode->psd_values[NL80211_REG_SUBORDINATE_CLIENT_LPI + ap_type]; -+ psd = mode->psd_values[NL80211_REG_AP_LPI + ap_type]; - #ifdef REG_DOM_SUPPORT_TX_POWER -- tx_pwr = psd * 2; -+ if (psd) -+ tx_pwr = psd * 2; -+ else -+ tx_pwr = chan->max_tx_power; - #else - tx_pwr = (hostapd_get_6g_tx_power(hapd, ap_type, tx_pwr_cat) * 2); - #endif /* REG_DOM_SUPPORT_TX_POWER */ -@@ -7119,7 +7123,10 @@ u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid) - tx_pwr_cat = REG_DEFAULT_CLIENT; - psd = mode->psd_values[NL80211_REG_REGULAR_CLIENT_LPI + ap_type]; - #ifdef REG_DOM_SUPPORT_TX_POWER -- tx_pwr = psd * 2; -+ if (psd) -+ tx_pwr = psd * 2; -+ else -+ tx_pwr = chan->max_tx_power; - #else - tx_pwr = (hostapd_get_6g_tx_power(hapd, ap_type, tx_pwr_cat) * 2); - #endif /* REG_DOM_SUPPORT_TX_POWER */ -@@ -7181,7 +7188,6 @@ u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid) - * channel in Country element and local pwr constraint is specified - * for channel in this Power Constraint element. - */ -- chan = &mode->channels[i]; - max_tx_power = chan->max_tx_power - local_pwr_constraint; - - /* --- -2.17.1 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-047-wpa_supplicant-Add-5GHz-240MHz-support-for-mesh.patch b/feeds/ipq95xx/hostapd/patches/q02-047-wpa_supplicant-Add-5GHz-240MHz-support-for-mesh.patch deleted file mode 100644 index 5f6503d17..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-047-wpa_supplicant-Add-5GHz-240MHz-support-for-mesh.patch +++ /dev/null @@ -1,112 +0,0 @@ -From 3951d8e0aa5100b8cc7c94f39a67d743f69f2a8b Mon Sep 17 00:00:00 2001 -From: Rameshkumar Sundaram -Date: Wed, 15 Jun 2022 08:29:43 +0530 -Subject: [PATCH] wpa_supplicant: Add 5GHz 240MHz support for mesh - -240MHz can be supported in 5 GHz for from channel -#100 - 144 with right hand 80MHz punctured in 320MHz bandwidth. -Add support to bring up mesh in 5 GHz 320MHz (240+80 Punctrued). -When 320MHz is configured for channel 100-144, static puncturing -pattern bits for higher 80MHz should be set (i.e. pattern & 0xF000) -should result in 0xF000). -EHT phy capability for advertising 320MHz support in 6GHz is reused -for 5GHz as well if 320MHz is configured. -Add the missing 80MHz channels to bw_80_160 array of -ibss_mesh_setup_freq(). - -Signed-off-by: Rameshkumar Sundaram ---- - src/common/ieee802_11_common.c | 3 ++- - wpa_supplicant/ap.c | 5 ++-- - wpa_supplicant/wpa_supplicant.c | 51 ++++++++++++++++++++++++++++------------- - 3 files changed, 40 insertions(+), 19 deletions(-) - -Index: b/src/common/ieee802_11_common.c -=================================================================== ---- a/src/common/ieee802_11_common.c 2022-07-14 14:31:03.057966186 +0530 -+++ b/src/common/ieee802_11_common.c 2022-07-14 14:31:03.049966278 +0530 -@@ -1028,7 +1028,8 @@ enum hostapd_hw_mode ieee80211_freq_to_c - if ((freq - 5000) % 5) - return NUM_HOSTAPD_MODES; - -- if (vht_opclass) -+ /* There is no op class defined for 5 GHz 320MHz, let it be unset */ -+ if (vht_opclass || chanwidth == CHANWIDTH_320MHZ) - *op_class = vht_opclass; - else if (sec_channel == 1) - *op_class = 122; -Index: b/wpa_supplicant/ap.c -=================================================================== ---- a/wpa_supplicant/ap.c 2022-07-14 14:31:03.057966186 +0530 -+++ b/wpa_supplicant/ap.c 2022-07-14 14:31:03.049966278 +0530 -@@ -105,9 +105,10 @@ static void wpas_conf_ap_vht(struct wpa_ - hostapd_set_oper_centr_freq_seg0_idx(conf, freq_seg_idx); - - wpa_printf(MSG_DEBUG, -- "VHT seg0 index %d and seg1 index %d for AP", -+ "VHT seg0 index %d and seg1 index %d BW %d for AP", - hostapd_get_oper_centr_freq_seg0_idx(conf), -- hostapd_get_oper_centr_freq_seg1_idx(conf)); -+ hostapd_get_oper_centr_freq_seg1_idx(conf), -+ hostapd_get_oper_chwidth(conf)); - return; - } - -Index: b/wpa_supplicant/wpa_supplicant.c -=================================================================== ---- a/wpa_supplicant/wpa_supplicant.c 2022-07-14 14:31:03.057966186 +0530 -+++ b/wpa_supplicant/wpa_supplicant.c 2022-07-14 14:33:12.080479343 +0530 -@@ -2509,7 +2509,9 @@ void ibss_mesh_setup_freq(struct wpa_sup - /* bw_80_160 array members are 80MHz start freq, 80MHz end freq and so on - */ - unsigned int bw_80_160[] = { 5180, 5240, 5260, 5320, -- 5500, 5560, 5580, 5660, -+ 5500, 5560, 5580, 5640, -+ 5660, 5720, 0, 0, -+ /* Adding dummy sec80 after channel #144 to keep remining 160MHz array intact */ - 5745, 5805, 5825, 5885, - 5955, 6015, 6035, 6095, - 6115, 6175, 6195, 6255, -@@ -2824,16 +2826,33 @@ skip_to_6ghz: - } - - if ((ssid->enable_320mhz_bw) && (mode->eht_capab[ieee80211_mode].phy_cap[EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_IDX] & -- EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_MASK) && is_6ghz) { -- -- for (i = 0; i < ARRAY_SIZE(bw_320); i+=2) { -- if (freq->freq >= bw_320[i] && -- freq->freq <= bw_320[i+1]) -- break; -+ EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_MASK)) { -+ if (is_6ghz) { -+ for (i = 0; i < ARRAY_SIZE(bw_320); i+=2) { -+ if (freq->freq >= bw_320[i] && -+ freq->freq <= bw_320[i+1]) -+ break; -+ } -+ -+ seg0 = ibss_get_center_320mhz(freq->channel); -+ chwidth = CHANWIDTH_320MHZ; -+ } else { -+ /* There is only one 320MHz(240+80 Punctured) in 5 GHz Band */ -+ u8 start_chan_idx = 100; -+ if (freq->channel >= 100 && freq->channel <= 144 && (ssid->ru_punct_bitmap & 0xF000) == 0xF000) { -+ for (i = start_chan_idx; i <= start_chan_idx + 44; i += 4) { -+ struct hostapd_channel_data *chan; -+ chan = hw_get_channel_chan(mode, i, NULL); -+ if (!chan) -+ return; -+ if (chan->flag & (HOSTAPD_CHAN_DISABLED| -+ HOSTAPD_CHAN_NO_IR)) -+ return; -+ } -+ seg0 = 130; -+ chwidth = CHANWIDTH_320MHZ; -+ } - } -- -- seg0 = ibss_get_center_320mhz(freq->channel); -- chwidth = CHANWIDTH_320MHZ; - } - - if (ssid->max_oper_chwidth == CHANWIDTH_80P80MHZ) { diff --git a/feeds/ipq95xx/hostapd/patches/q02-048-hostapd-Update-11be-EHT-elements-to-Draft-2.0-versio.patch b/feeds/ipq95xx/hostapd/patches/q02-048-hostapd-Update-11be-EHT-elements-to-Draft-2.0-versio.patch deleted file mode 100644 index 56f1fcb2b..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-048-hostapd-Update-11be-EHT-elements-to-Draft-2.0-versio.patch +++ /dev/null @@ -1,289 +0,0 @@ -From 7377742385c93887bc125cecc21204387112517d Mon Sep 17 00:00:00 2001 -From: Balamurugan Mahalingam -Date: Tue, 16 Aug 2022 17:53:38 -0700 -Subject: [PATCH] hostapd: Update 11be EHT elements to Draft 2.0 version - -Update the EHT operations elements to Draft 2.0 and fix interop -issues with stations - -Signed-off-by: Balamurugan Mahalingam ---- - hostapd/config_file.c | 2 ++ - src/ap/ap_config.h | 9 +++++++++ - src/ap/beacon.c | 5 +++++ - src/ap/ctrl_iface_ap.c | 6 ++++-- - src/ap/ieee802_11.c | 2 ++ - src/ap/ieee802_11_eht.c | 34 ++++++++++++++++++++++++++++------ - src/common/ieee802_11_defs.h | 35 +++++++++++++++++++++++------------ - wpa_supplicant/mesh_mpm.c | 10 +++++----- - 8 files changed, 78 insertions(+), 25 deletions(-) - -diff --git a/hostapd/config_file.c b/hostapd/config_file.c -index 501d30c..d896d67 100644 ---- a/hostapd/config_file.c -+++ b/hostapd/config_file.c -@@ -4689,6 +4689,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, - conf->eht_oper_chwidth = atoi(pos); - } else if (os_strcmp(buf, "eht_oper_centr_freq_seg0_idx") == 0) { - conf->eht_oper_centr_freq_seg0_idx = atoi(pos); -+ } else if (os_strcmp(buf, "eht_oper_centr_freq_seg1_idx") == 0) { -+ conf->eht_oper_centr_freq_seg1_idx = atoi(pos); - } else if (os_strcmp(buf, "eht_su_beamformer") == 0) { - conf->eht_phy_capab.su_beamformer = atoi(pos); - } else if (os_strcmp(buf, "eht_su_beamformee") == 0) { -diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h -index f6d1d56..83ba76c 100644 ---- a/src/ap/ap_config.h -+++ b/src/ap/ap_config.h -@@ -1144,6 +1144,7 @@ struct hostapd_config { - #ifdef CONFIG_IEEE80211BE - u8 eht_oper_chwidth; - u8 eht_oper_centr_freq_seg0_idx; -+ u8 eht_oper_centr_freq_seg1_idx; - struct eht_phy_capabilities_info eht_phy_capab; - #endif /* CONFIG_IEEE80211BE */ - -@@ -1227,6 +1228,10 @@ hostapd_set_oper_centr_freq_seg0_idx(struct hostapd_config *conf, - static inline u8 - hostapd_get_oper_centr_freq_seg1_idx(struct hostapd_config *conf) - { -+#ifdef CONFIG_IEEE80211BE -+ if (conf->ieee80211be) -+ return conf->eht_oper_centr_freq_seg1_idx; -+#endif /* CONFIG_IEEE80211BE */ - #ifdef CONFIG_IEEE80211AX - if (conf->ieee80211ax) - return conf->he_oper_centr_freq_seg1_idx; -@@ -1238,6 +1243,10 @@ static inline void - hostapd_set_oper_centr_freq_seg1_idx(struct hostapd_config *conf, - u8 oper_centr_freq_seg1_idx) - { -+#ifdef CONFIG_IEEE80211BE -+ if (conf->ieee80211be) -+ conf->eht_oper_centr_freq_seg1_idx = oper_centr_freq_seg1_idx; -+#endif /* CONFIG_IEEE80211BE */ - #ifdef CONFIG_IEEE80211AX - if (conf->ieee80211ax) - conf->he_oper_centr_freq_seg1_idx = oper_centr_freq_seg1_idx; -diff --git a/src/ap/beacon.c b/src/ap/beacon.c -index 023729c..9536e76 100644 ---- a/src/ap/beacon.c -+++ b/src/ap/beacon.c -@@ -643,6 +643,9 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, - if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) { - buflen += hostapd_eid_eht_capab_len(hapd, IEEE80211_MODE_AP); - buflen += (3 + sizeof(struct ieee80211_eht_operation)); -+ if (hapd->iconf->ru_punct_bitmap) -+ buflen += DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE; -+ - } - #endif /* CONFIG_IEEE80211BE */ - -@@ -1759,6 +1762,8 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, - if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) { - tail_len += hostapd_eid_eht_capab_len(hapd, IEEE80211_MODE_AP); - tail_len += (3 + sizeof(struct ieee80211_eht_operation)); -+ if (hapd->iconf->ru_punct_bitmap) -+ tail_len += DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE; - } - #endif /* CONFIG_IEEE80211BE */ - -diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c -index 62db273..b697ad2 100644 ---- a/src/ap/ctrl_iface_ap.c -+++ b/src/ap/ctrl_iface_ap.c -@@ -1065,9 +1065,11 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf, - if (iface->conf->ieee80211be && !hapd->conf->disable_11be) { - ret = os_snprintf(buf + len, buflen - len, - "eht_oper_chwidth=%d\n" -- "eht_oper_centr_freq_seg0_idx=%d\n", -+ "eht_oper_centr_freq_seg0_idx=%d\n" -+ "eht_oper_centr_freq_seg1_idx=%d\n", - iface->conf->eht_oper_chwidth, -- iface->conf->eht_oper_centr_freq_seg0_idx); -+ iface->conf->eht_oper_centr_freq_seg0_idx, -+ iface->conf->eht_oper_centr_freq_seg1_idx); - if (os_snprintf_error(buflen - len, ret)) - return len; - len += ret; -diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c -index b4efc17..8a6fed8 100644 ---- a/src/ap/ieee802_11.c -+++ b/src/ap/ieee802_11.c -@@ -5106,6 +5106,8 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta, - if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) { - buflen += hostapd_eid_eht_capab_len(hapd, IEEE80211_MODE_AP); - buflen += (3 + sizeof(struct ieee80211_eht_operation)); -+ if (hapd->iconf->ru_punct_bitmap) -+ buflen += DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE; - } - #endif /* CONFIG_IEEE80211BE */ - -diff --git a/src/ap/ieee802_11_eht.c b/src/ap/ieee802_11_eht.c -index c7586ec..f54fee3 100644 ---- a/src/ap/ieee802_11_eht.c -+++ b/src/ap/ieee802_11_eht.c -@@ -174,6 +174,7 @@ u8 * hostapd_eid_eht_operation(struct hostapd_data *hapd, u8 *eid, - { - struct hostapd_hw_modes *mode; - struct ieee80211_eht_operation *oper; -+ struct eht_capabilities *eht_cap; - u8 *pos = eid, oper_size = 0, chwidth; - - mode = hapd->iface->current_mode; -@@ -185,15 +186,26 @@ u8 * hostapd_eid_eht_operation(struct hostapd_data *hapd, u8 *eid, - - oper_size = sizeof(struct ieee80211_eht_operation); - *pos++ = WLAN_EID_EXTENSION; -- *pos++ = 1 + oper_size; -+ -+ if (hapd->iconf->ru_punct_bitmap) -+ *pos++ = 1 + oper_size + DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE; -+ else -+ *pos++ = 1 + oper_size; -+ - *pos++ = WLAN_EID_EXT_EHT_OPERATION; - - oper = (struct ieee80211_eht_operation *) pos; - os_memset(oper, 0, sizeof(*oper)); - -- oper->ccfs = hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf); -- if (!oper->ccfs) -- oper->ccfs = hapd->iconf->channel; -+ eht_cap = &mode->eht_capab[opmode]; -+ oper->ehtop_params |= EHTOP_PARAMS_EHTOP_INFORMATION_PRESENT; -+ oper->ccfs0 = hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf); -+ oper->ccfs1 = hostapd_get_oper_centr_freq_seg1_idx(hapd->iconf); -+ memcpy(&oper->mcs_nss_supported, &eht_cap->mcs, -+ EHT_PHYCAP_MCS_NSS_LEN_20MHZ_ONLY); -+ -+ if (!oper->ccfs0) -+ oper->ccfs0 = hapd->iconf->channel; - - if (is_6ghz_op_class(hapd->iconf->op_class)) - chwidth = op_class_to_ch_width(hapd->iconf->op_class); -@@ -209,6 +221,14 @@ u8 * hostapd_eid_eht_operation(struct hostapd_data *hapd, u8 *eid, - switch (chwidth) { - case CHANWIDTH_320MHZ: - oper->width = EHT_OPERATION_CHANNEL_WIDTH_320MHZ; -+ if (!oper->ccfs1) { -+ /* CCFS0 points to center channel frequency in config */ -+ oper->ccfs1 = oper->ccfs0; -+ if (hapd->iconf->channel < oper->ccfs0) -+ oper->ccfs0 = oper->ccfs1 - 16; -+ else -+ oper->ccfs0 = oper->ccfs1 + 16; -+ } - break; - case CHANWIDTH_160MHZ: - oper->width = EHT_OPERATION_CHANNEL_WIDTH_160MHZ; -@@ -246,8 +266,10 @@ u8 * hostapd_eid_eht_operation(struct hostapd_data *hapd, u8 *eid, - } - - if (hapd->iconf->ru_punct_bitmap) { -- oper->disable_sub_chan_bitmap_present = 1; -- oper->disabled_subchannel_bitmap = host_to_le16(hapd->iconf->ru_punct_bitmap); -+ oper->ehtop_params |= EHTOP_PARAMS_DISABLED_SUBCHANNEL_BITMAP_PRESENT; -+ oper->disabled_subchannel_bitmap[0] = -+ host_to_le16(hapd->iconf->ru_punct_bitmap); -+ pos += DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE; - } - - pos += oper_size; -diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h -index 752f65f..766ec1d 100644 ---- a/src/common/ieee802_11_defs.h -+++ b/src/common/ieee802_11_defs.h -@@ -2462,28 +2462,39 @@ struct ieee80211_eht_capabilities { - u8 optional[71]; - } STRUCT_PACKED; - --#define EHT_OPERATION_CCFS_SHIFT 4 - /* - * struct ieee80211_eht_operation - eht operation element - * - * This structure is the "EHT Operation Element" fields as -- * described in P802.11be_D1.4 section 9.4.2.311 -- * -- * FIXME: The spec is unclear how big the fields are, and doesn't -- * indicate the "Disabled Subchannel Bitmap Present" in the -- * structure (Figure 9-1002a) at all ... -+ * described in P802.11be_D2.0 section 9.4.2.311 - */ -+ -+#define EHTOP_PARAMS_EHTOP_INFORMATION_PRESENT BIT(0) -+#define EHTOP_PARAMS_DISABLED_SUBCHANNEL_BITMAP_PRESENT BIT(1) -+#define EHTOP_PARAMS_EHT_DEFAULT_PE_DURATION BIT(2) -+#define EHTOP_PARAMS_GROUP_ADDRESSED_BU_INDICATION_LIMIT BIT(3) -+#define EHTOP_PARAMS_GROUP_ADDRESSED_BU_INDICATION_EXPONENT BIT(4) -+ -+#define DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE 2 -+ -+struct ieee80211_eht_mcs_nss_set { -+ u8 max_tx_mcs_nss_0_7; -+ u8 max_tx_mcs_nss_8_9; -+ u8 max_tx_mcs_nss_10_11; -+ u8 max_tx_mcs_nss_12_13; -+} STRUCT_PACKED; -+ - struct ieee80211_eht_operation { -+ u8 ehtop_params; -+ struct ieee80211_eht_mcs_nss_set mcs_nss_supported; - u8 width:3, - reserved:5; -- u8 ccfs; -- u8 disable_sub_chan_bitmap_present:1, -- reserved2:7; -- le16 disabled_subchannel_bitmap; -- -- /* Add puncture pattern here when supported */ -+ u8 ccfs0; -+ u8 ccfs1; -+ le16 disabled_subchannel_bitmap[0]; - } STRUCT_PACKED; - -+ - #define EHT_OPERATION_CHANNEL_WIDTH_20MHZ 0 - #define EHT_OPERATION_CHANNEL_WIDTH_40MHZ 1 - #define EHT_OPERATION_CHANNEL_WIDTH_80MHZ 2 -diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c -index b527a77..c56801f 100644 ---- a/wpa_supplicant/mesh_mpm.c -+++ b/wpa_supplicant/mesh_mpm.c -@@ -820,28 +820,28 @@ static struct sta_info * mesh_mpm_add_peer(struct wpa_supplicant *wpa_s, - - eht_oper_ie = (struct ieee80211_eht_operation *)elems->eht_operation; - if (eht_oper_ie->width >= EHT_OPERATION_CHANNEL_WIDTH_80MHZ && -- eht_oper_ie->disable_sub_chan_bitmap_present && -+ eht_oper_ie->ehtop_params & EHTOP_PARAMS_DISABLED_SUBCHANNEL_BITMAP_PRESENT && - eht_oper_ie->disabled_subchannel_bitmap) { -- params.ru_punct_bitmap = eht_oper_ie->disabled_subchannel_bitmap; -+ params.ru_punct_bitmap = eht_oper_ie->disabled_subchannel_bitmap[0]; - /* Validate Peer's puncture bitmap and reset if invalid */ - switch (eht_oper_ie->width) { - case EHT_OPERATION_CHANNEL_WIDTH_80MHZ: - bw = 80; -- start_chan = eht_oper_ie->ccfs - 6; -+ start_chan = eht_oper_ie->ccfs0 - 6; - if (!is_ru_punct_bitmap_valid(bw, (pri_chan - start_chan) / 4, - params.ru_punct_bitmap, 0)) - params.ru_punct_bitmap = 0; - break; - case EHT_OPERATION_CHANNEL_WIDTH_160MHZ: - bw = 160; -- start_chan = eht_oper_ie->ccfs - 14; -+ start_chan = eht_oper_ie->ccfs0 - 14; - if (!is_ru_punct_bitmap_valid(bw, (pri_chan - start_chan) / 4, - params.ru_punct_bitmap, 0)) - params.ru_punct_bitmap = 0; - break; - case EHT_OPERATION_CHANNEL_WIDTH_320MHZ: - bw = 320; -- start_chan = eht_oper_ie->ccfs - 30; -+ start_chan = eht_oper_ie->ccfs0 - 30; - if (!is_ru_punct_bitmap_valid(bw, (pri_chan - start_chan) / 4, - params.ru_punct_bitmap, 0)) - params.ru_punct_bitmap = 0; --- -2.17.1 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-048-mesh-Enable-80-160MHz-Mesh-DFS-channels.patch b/feeds/ipq95xx/hostapd/patches/q02-048-mesh-Enable-80-160MHz-Mesh-DFS-channels.patch deleted file mode 100644 index 5fe63c5a5..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-048-mesh-Enable-80-160MHz-Mesh-DFS-channels.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 6a7437a8bf48538e26924ca0cb3646fdff698883 Mon Sep 17 00:00:00 2001 -From: Hari Chandrakanthan -Date: Sun, 17 Jul 2022 12:26:36 +0530 -Subject: [PATCH] mesh: Enable 80-160MHz Mesh DFS channels - -There are two 80MHz and 160MHz 5G channels are present -in DFS occupied channel list. CAC needs to be performed -before the start of transmission for the DFS channels. -Hostapd CAC check is based on hapd->conf structures. -Hence the center frequency segment index and bandwidth -are added to perform CAC. - -Current implementation of DFS channel validatation for -mesh performs DFS check for only primary 80MHz of 160MHz -has DFS channels present or not. But this approach will -fail for channels having Non DFS channel as primary and -DFS channel for secondary 80MHz of 160MHz Eg: channel 36. -To avoid this issue, added DFS check for both primary 80MHz -and secondary 80MHz channels of 160MHz. - -Signed-off-by: Hari Chandrakanthan -Signed-off-by: P Praneesh ---- - wpa_supplicant/mesh.c | 29 +++++++++++++++++++++++++++-- - 1 file changed, 27 insertions(+), 2 deletions(-) - -diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c -index bb356a4..951a26c 100644 ---- a/wpa_supplicant/mesh.c -+++ b/wpa_supplicant/mesh.c -@@ -393,6 +393,7 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, - int basic_rates_erp[] = { 10, 20, 55, 60, 110, 120, 240, -1 }; - int rate_len; - int frequency; -+ bool is_dfs; - - if (!wpa_s->conf->user_mpm) { - /* not much for us to do here */ -@@ -484,8 +485,32 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, - bss->conf->ap_max_inactivity = wpa_s->conf->mesh_max_inactivity; - bss->conf->mesh_fwding = wpa_s->conf->mesh_fwding; - -- if (ieee80211_is_dfs(ssid->frequency, wpa_s->hw.modes, -- wpa_s->hw.num_modes) && wpa_s->conf->country[0]) { -+#define WPAS_GET_SEG_IDX(freq) ((freq - 5000)/5) -+ if (wpa_s->mesh_vht_enabled) { -+ if (freq->bandwidth == 80) -+ conf->vht_oper_chwidth = CHANWIDTH_80MHZ; -+ else if (freq->bandwidth == 160) -+ conf->vht_oper_chwidth = CHANWIDTH_160MHZ; -+ conf->vht_oper_centr_freq_seg0_idx = WPAS_GET_SEG_IDX(freq->center_freq1); -+ } -+ -+ if (wpa_s->mesh_he_enabled) { -+ if (freq->bandwidth == 80) -+ conf->he_oper_chwidth = CHANWIDTH_80MHZ; -+ else if (freq->bandwidth == 160) -+ conf->he_oper_chwidth = CHANWIDTH_160MHZ; -+ conf->he_oper_centr_freq_seg0_idx = WPAS_GET_SEG_IDX(freq->center_freq1); -+ } -+ -+ is_dfs = ieee80211_is_dfs(ssid->frequency, wpa_s->hw.modes, -+ wpa_s->hw.num_modes); -+ -+ /* Check secondary 80MHz of 160Mhz has DFS channels */ -+ if (!is_dfs && freq->bandwidth == 160) -+ is_dfs = ieee80211_is_dfs((ssid->frequency+80), wpa_s->hw.modes, -+ wpa_s->hw.num_modes); -+ -+ if (is_dfs && wpa_s->conf->country[0]) { - conf->ieee80211h = 1; - conf->ieee80211d = 1; - conf->country[0] = wpa_s->conf->country[0]; --- -2.7.4 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-049-hostapd-fix-channel-switch-in-eht-40mhz-bandwidth-fa.patch b/feeds/ipq95xx/hostapd/patches/q02-049-hostapd-fix-channel-switch-in-eht-40mhz-bandwidth-fa.patch deleted file mode 100644 index 151b561b3..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-049-hostapd-fix-channel-switch-in-eht-40mhz-bandwidth-fa.patch +++ /dev/null @@ -1,30 +0,0 @@ -From e845f59b9ef7b098b3082b7b608ef93f72aff4d6 Mon Sep 17 00:00:00 2001 -From: Pradeep Kumar Chitrapu -Date: Thu, 4 Aug 2022 10:45:58 -0700 -Subject: [PATCH] hostapd: fix channel switch in eht 40mhz bandwidth falling - back to 20mhz - -When EHT is enabled in 2 GHz band with 40MHz bandwidth, channel switch -in 40 MHz is falling back to 20 MHz. so fix that. - -Signed-off-by: Pradeep Kumar Chitrapu ---- - src/drivers/driver_nl80211.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c -index a34012376979..ec8b4b5f8627 100644 ---- a/src/drivers/driver_nl80211.c -+++ b/src/drivers/driver_nl80211.c -@@ -5053,7 +5053,7 @@ static int nl80211_put_freq_params(struct nl_msg *msg, - freq->ru_punct_bitmap)) - return -ENOBUFS; - } -- } else if (freq->ht_enabled || (freq->he_enabled && is_24ghz)) { -+ } else if (freq->ht_enabled || ((freq->he_enabled || freq->eht_enabled) && is_24ghz)) { - enum nl80211_channel_type ct; - - wpa_printf(MSG_DEBUG, " * sec_channel_offset=%d", --- -2.17.1 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-049-hostapd-fix-he40-eht40-bringup-with-acs.patch b/feeds/ipq95xx/hostapd/patches/q02-049-hostapd-fix-he40-eht40-bringup-with-acs.patch deleted file mode 100644 index eca21a43f..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-049-hostapd-fix-he40-eht40-bringup-with-acs.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 1aef02a7dcf4206fd231097a4d0b7704b6c95111 Mon Sep 17 00:00:00 2001 -From: Hari Chandrakanthan -Date: Tue, 9 Aug 2022 00:17:18 +0530 -Subject: [PATCH] hostapd : fix he40/eht40 bringup with acs - -when ap is brought up in he40/eht40 with acs, -the ap comes up with 20 Mhz bandwidth. It is expected to -come up with 40 Mhz bandwidth. - -conf->secondary_channel doesnot hold the correct value and it leads -to choosing 20 Mhz in the api hostapd_set_freq_params. - -when the config acs is chosen, the hostapd config -he_oper_centr_freq_seg0_idx is not filled with correct value -as the channel is not known during bring up. - -So using the config he_oper_centr_freq_seg0_idx to fill the -conf->secondary_channel doesnot work with acs. - -So use op_class to determine the bandwidth and based -on the bandwidth fill the conf->secondary_channel. - -Signed-off-by: Hari Chandrakanthan ---- - src/ap/hostapd.c | 7 ++----- - 1 file changed, 2 insertions(+), 5 deletions(-) - -diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c -index d9c0f09..86e094a 100644 ---- a/src/ap/hostapd.c -+++ b/src/ap/hostapd.c -@@ -1725,16 +1725,13 @@ static int configured_fixed_chan_to_freq(struct hostapd_iface *iface) - - static void hostapd_set_6ghz_sec_chan(struct hostapd_iface *iface) - { -- int bw, seg0; -- - if (!is_6ghz_op_class(iface->conf->op_class)) - return; - -- seg0 = hostapd_get_oper_centr_freq_seg0_idx(iface->conf); -- bw = center_idx_to_bw_6ghz(seg0); - /* Assign the secondary channel if absent in config for - * bandwidths > 20 MHz */ -- if (bw > 20 && !iface->conf->secondary_channel) { -+ if (op_class_to_bandwidth(iface->conf->op_class) >= 40 && -+ !iface->conf->secondary_channel) { - if (((iface->conf->channel - 1) / 4) % 2) - iface->conf->secondary_channel = -1; - else --- -2.7.4 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-050-hostapd-Add-freq-info-in-start-ap.patch b/feeds/ipq95xx/hostapd/patches/q02-050-hostapd-Add-freq-info-in-start-ap.patch deleted file mode 100644 index cd5e901f6..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-050-hostapd-Add-freq-info-in-start-ap.patch +++ /dev/null @@ -1,43 +0,0 @@ -From b21976225f55be31bde21b06a6511e12092376c1 Mon Sep 17 00:00:00 2001 -From: Harshitha Prem -Date: Tue, 23 Aug 2022 14:15:08 +0530 -Subject: [PATCH] hostapd: Add frequency info in start ap - -In case of single hw multiple band scenario, when we -bring up multiple virtual interface in various bands -simultaneously then the driver maps a random channel -to the virtual interface when start ap command is sent -as freq info is not present. - -Hence, add the frequency information in start ap netlink -command so that the driver maps the appropriate channel -context by parsing it. - -Signed-off-by: Harshitha Prem - ---- - src/drivers/driver_nl80211.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - ---- a/src/drivers/driver_nl80211.c -+++ b/src/drivers/driver_nl80211.c -@@ -171,7 +171,8 @@ static int nl80211_send_frame_cmd(struct - const u16 *csa_offs, size_t csa_offs_len); - static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss, - int report); -- -+static int nl80211_put_freq_params(struct nl_msg *msg, -+ const struct hostapd_freq_params *freq); - #define IFIDX_ANY -1 - - static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx, -@@ -4885,6 +4886,9 @@ static int wpa_driver_nl80211_set_ap(voi - nla_nest_end(msg, spr); - } - -+ if (params->freq && nl80211_put_freq_params(msg, params->freq) < 0) -+ goto fail; -+ - if (params->freq && params->freq->he_enabled) { - struct nlattr *bss_color; - diff --git a/feeds/ipq95xx/hostapd/patches/q02-050-wpa_supplicant-add-wpa_cli-support-for-cac.patch b/feeds/ipq95xx/hostapd/patches/q02-050-wpa_supplicant-add-wpa_cli-support-for-cac.patch deleted file mode 100644 index 9268c6473..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-050-wpa_supplicant-add-wpa_cli-support-for-cac.patch +++ /dev/null @@ -1,57 +0,0 @@ -From cea226f19df8cb78086374698d52f30485c2df43 Mon Sep 17 00:00:00 2001 -From: Hari Chandrakanthan -Date: Thu, 11 Aug 2022 10:35:15 +0530 -Subject: [PATCH] wpa_supplicant : add wpa_cli support for cac - -support to display cac inprogress state is added -as part of 'wpa_cli -i wlanx status' command - -Signed-off-by: Hari Chandrakanthan ---- - wpa_supplicant/ctrl_iface.c | 17 ++++++++++++++++- - 1 file changed, 16 insertions(+), 1 deletion(-) - -diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c -index 61aeea7..b96a996 100644 ---- a/wpa_supplicant/ctrl_iface.c -+++ b/wpa_supplicant/ctrl_iface.c -@@ -2205,7 +2205,7 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, - const char *params, - char *buf, size_t buflen) - { -- char *pos, *end, tmp[30]; -+ char *pos, *end, tmp[30], *tmp_buf; - int res, verbose, wps, ret; - #ifdef CONFIG_HS20 - const u8 *hs20; -@@ -2346,12 +2346,27 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, - } - #endif /* CONFIG_SAE */ - #endif /* CONFIG_SME */ -+ if (wpa_s->ifmsh) { -+ if(wpa_s->wpa_state == WPA_SCANNING && wpa_s->ifmsh->cac_started) -+ tmp_buf = "inprogress"; -+ else -+ tmp_buf = "N/A"; -+ } else { -+ tmp_buf = "N/A"; -+ } - ret = os_snprintf(pos, end - pos, "wpa_state=%s\n", - wpa_supplicant_state_txt(wpa_s->wpa_state)); - if (os_snprintf_error(end - pos, ret)) - return pos - buf; - pos += ret; - -+ ret = os_snprintf(pos, end - pos, "cac=%s\n", -+ tmp_buf); -+ if (os_snprintf_error(end - pos, ret)) -+ return pos - buf; -+ pos += ret; -+ -+ - if (wpa_s->l2 && - l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) { - ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp); --- -2.7.4 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-051-hostapd-Add-element-ID-extension-as-part-of-non-inhe.patch b/feeds/ipq95xx/hostapd/patches/q02-051-hostapd-Add-element-ID-extension-as-part-of-non-inhe.patch deleted file mode 100644 index 1bbdca6e4..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-051-hostapd-Add-element-ID-extension-as-part-of-non-inhe.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 1adb9ef3ff48623365196c59a98b9a5ac03e012c Mon Sep 17 00:00:00 2001 -Author: Sowmiya Sree Elavalagan -Date: Mon Mar 21 22:02:03 2022 +0530 -Subject: [PATCH] hostapd: Add element ID extension as part of non-inheritance - IE for mbssid. - -Certain clients do not scan all non tx profiles due to absence of -element ID extension list which is mandatory field in non inheritance -IE. Non inheritance Element ID is followed by extension element ID. -Length is expected to be mentioned. Currently we do not support any -extension element and hence filling length as 0. - -Signed-off-by: Sowmiya Sree Elavalagan -Signed-off-by: Ramya Gnanasekar - -diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c -index 8a6fed8..5b814ba 100644 ---- a/src/ap/ieee802_11.c -+++ b/src/ap/ieee802_11.c -@@ -7819,6 +7819,8 @@ static size_t hostapd_eid_mbssid_elem_len(struct hostapd_data *hapd, - if (ie_count) - nontx_profile_len += (4 + ie_count); - -+ nontx_profile_len += 1; /*Extension element ID length */ -+ - if ((len + nontx_profile_len) > 255) - goto mbssid_too_big; - -@@ -7974,11 +7976,16 @@ static u8 * hostapd_eid_mbssid_elem(struct hostapd_data *hapd, u8 *eid, u8 *end, - } - if (ie_count) { - *eid++ = WLAN_EID_EXTENSION; -- *eid++ = 2 + ie_count; -+ *eid++ = 3 + ie_count; - *eid++ = WLAN_EID_EXT_NON_INHERITANCE; - *eid++ = ie_count; - os_memcpy(eid, non_inherit_ie, ie_count); - eid += ie_count; -+ /* Element ID extension list is mandatory part of non inheritance IE. -+ * It has a length field followed by extension IEs. Currently no -+ * extension IEs are supported so filling length as 0. -+ */ -+ *eid++ = 0; - } - - *eid_len_pos = (eid - eid_len_pos) - 1; --- -2.17.1 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-051-hostapd-add-awgn-support-for-320MHz-bw-in-6GHz-band.patch b/feeds/ipq95xx/hostapd/patches/q02-051-hostapd-add-awgn-support-for-320MHz-bw-in-6GHz-band.patch deleted file mode 100644 index 1439eb067..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-051-hostapd-add-awgn-support-for-320MHz-bw-in-6GHz-band.patch +++ /dev/null @@ -1,263 +0,0 @@ -From 856937cfab895f6a20e1fd9d919ad5710077745c Mon Sep 17 00:00:00 2001 -From: Hari Chandrakanthan -Date: Wed, 28 Sep 2022 17:48:40 +0530 -Subject: [PATCH] hostapd : add awgn support for 320MHz bw in 6GHz band - -Add support for awgn handling of 320MHz bw in 6GHz band. - -Signed-off-by: Hari Chandrakanthan ---- - src/ap/interference.c | 147 ++++++++++++++++++++++++++++++++++---------------- - 1 file changed, 100 insertions(+), 47 deletions(-) - -diff --git a/src/ap/interference.c b/src/ap/interference.c -index c51a4bf..4148489 100644 ---- a/src/ap/interference.c -+++ b/src/ap/interference.c -@@ -62,6 +62,7 @@ static int intf_awgn_chan_range_available(struct hostapd_hw_modes *mode, - int allowed_80_6g[] = {1, 17, 33, 49, 65, 81, 97, 113, 129, 145, 161, 177, - 193, 209}; - int allowed_160_6g[] = {1, 33, 65, 97, 129, 161, 193}; -+ int allowed_320_6g[] = {1, 65, 129, 33, 97, 161}; - int chan_idx_match = 0; - int i; - -@@ -97,6 +98,13 @@ static int intf_awgn_chan_range_available(struct hostapd_hw_modes *mode, - break; - } - } -+ } else if (num_chans == 16) { /* 320Mhz channel */ -+ for (i = 0; i < ARRAY_SIZE(allowed_320_6g); i++) { -+ if (first_chan->chan == allowed_320_6g[i]) { -+ chan_idx_match = 1; -+ break; -+ } -+ } - } - - if (chan_idx_match == 1) -@@ -114,6 +122,42 @@ static int is_in_chanlist(struct hostapd_iface *iface, - return freq_range_list_includes(&iface->conf->acs_ch_list, chan->chan); - } - -+#define BASE_6G_FREQ 5950 -+ -+int get_centre_freq_6g(int chan_idx, int chan_width, int *centre_freq) -+{ -+ if (!centre_freq) -+ return -1; -+ -+ *centre_freq = 0; -+ -+ switch (chan_width) { -+ case CHAN_WIDTH_40: -+ if (chan_idx >= 1 && chan_idx <= 229) -+ *centre_freq = ((chan_idx / 8) * 8 + 3) * 5 + BASE_6G_FREQ; -+ break; -+ case CHAN_WIDTH_80: -+ if (chan_idx >= 1 && chan_idx <= 221) -+ *centre_freq = ((chan_idx / 16) * 16 + 7) * 5 + BASE_6G_FREQ; -+ break; -+ case CHAN_WIDTH_160: -+ if (chan_idx >= 1 && chan_idx <= 221) -+ *centre_freq = ((chan_idx / 32) * 32 + 15) * 5 + BASE_6G_FREQ; -+ break; -+ case CHAN_WIDTH_320: -+ if (chan_idx >= 1 && chan_idx <= 221) -+ *centre_freq = ((chan_idx /64) * 64 + 31) * 5 + BASE_6G_FREQ; -+ default: -+ break; -+ } -+ -+ if (*centre_freq == 0) -+ return -1; -+ -+ return 0; -+} -+ -+ - /* - *intf_awgn_find_channel - find the channel that can operate with bandwidth chan_width. - If idx doesn't match with index of any of the existing channel, then the api -@@ -123,11 +167,13 @@ static int is_in_chanlist(struct hostapd_iface *iface, - */ - static int intf_awgn_find_channel(struct hostapd_iface *iface, - struct hostapd_channel_data **ret_chan, -- int idx, int chan_width) -+ int idx, int chan_width, int cs1) - { - struct hostapd_hw_modes *mode = iface->current_mode; - struct hostapd_channel_data *chan; - int i, channel_idx = 0, n_chans; -+ int temp_centre_freq; -+ int ret; - - switch (chan_width) { - case CHAN_WIDTH_20_NOHT: -@@ -144,6 +190,9 @@ static int intf_awgn_find_channel(struct hostapd_iface *iface, - case CHAN_WIDTH_160: - n_chans = 8; - break; -+ case CHAN_WIDTH_320: -+ n_chans = 16; -+ break; - default: - n_chans = 1; - break; -@@ -167,6 +216,24 @@ static int intf_awgn_find_channel(struct hostapd_iface *iface, - continue; - } - -+ if (chan_width == CHAN_WIDTH_320) { -+ ret = get_centre_freq_6g(chan->chan, CHAN_WIDTH_320, -+ &temp_centre_freq); -+ if (ret) { -+ wpa_printf(MSG_ERROR, -+ "AWGN : couldn't find centre freq for chan : %d" -+ " chan_width : %d", chan->chan, CHAN_WIDTH_320); -+ return 0; -+ } -+ -+ if (abs(temp_centre_freq - cs1) < 320) { -+ wpa_printf(MSG_DEBUG, -+ "AWGN: channel %d is a overlapping channel so skipping", -+ chan->freq); -+ continue; -+ } -+ } -+ - if (ret_chan && idx == channel_idx) { - wpa_printf(MSG_DEBUG, "AWGN: Selected channel %d (%d)", - chan->freq, chan->chan); -@@ -182,50 +249,27 @@ static int intf_awgn_find_channel(struct hostapd_iface *iface, - } - - enum chan_seg { -- SEG_PRI20 = 0x1, -- SEG_SEC20 = 0x2, -- SEG_SEC40_LOWER = 0x4, -- SEG_SEC40_UPPER = 0x8, -- SEG_SEC40 = 0xC, -- SEG_SEC80_LOWER = 0x10, -- SEG_SEC80_LOWER_UPPER = 0x20, -- SEG_SEC80_UPPER_LOWER = 0x40, -- SEG_SEC80_UPPER = 0x80, -- SEG_SEC80 = 0xF0, -+ SEG_PRI20 = 0x1, -+ SEG_SEC20 = 0x2, -+ SEG_SEC40_LOW = 0x4, -+ SEG_SEC40_UP = 0x8, -+ SEG_SEC40 = 0xC, -+ SEG_SEC80_LOW = 0x10, -+ SEG_SEC80_LOW_UP = 0x20, -+ SEG_SEC80_UP_LOW = 0x40, -+ SEG_SEC80_UP = 0x80, -+ SEG_SEC80 = 0xF0, -+ SEG_SEC160_LOW = 0x0100, -+ SEG_SEC160_LOW_UP = 0x0200, -+ SEG_SEC160_LOW_UP_UP = 0x0400, -+ SEG_SEC160_LOW_UP_UP_UP = 0x0800, -+ SEG_SEC160_UP_LOW_LOW_LOW = 0x1000, -+ SEG_SEC160_UP_LOW_LOW = 0x2000, -+ SEG_SEC160_UP_LOW = 0x4000, -+ SEG_SEC160_UP = 0x8000, -+ SEG_SEC160 = 0xFF00, - }; - --#define BASE_6G_FREQ 5950 -- --int get_centre_freq_6g(int chan_idx, int chan_width, int *centre_freq) --{ -- if (!centre_freq) -- return -1; -- -- *centre_freq = 0; -- -- switch (chan_width) { -- case CHAN_WIDTH_40: -- if (chan_idx >= 1 && chan_idx <= 229) -- *centre_freq = ((chan_idx / 8) * 8 + 3) * 5 + BASE_6G_FREQ; -- break; -- case CHAN_WIDTH_80: -- if (chan_idx >= 1 && chan_idx <= 221) -- *centre_freq = ((chan_idx / 16) * 16 + 7) * 5 + BASE_6G_FREQ; -- break; -- case CHAN_WIDTH_160: -- if (chan_idx >= 1 && chan_idx <= 221) -- *centre_freq = ((chan_idx / 32) * 32 + 15) * 5 + BASE_6G_FREQ; -- break; -- default: -- break; -- } -- -- if (*centre_freq == 0) -- return -1; -- -- return 0; --} -- - /* - * hostapd_intf_awgn_detected - awgn interference is detected in the operating channel. - * The interference channel information is available as a -@@ -269,7 +313,7 @@ int hostapd_intf_awgn_detected(struct hostapd_iface *iface, int freq, int chan_w - if (channel_switch) { - /* Find a random channel to be switched */ - num_available_chandefs = intf_awgn_find_channel(iface, NULL, 0, -- chan_width); -+ chan_width, cf1); - if (num_available_chandefs == 0) { - wpa_printf(MSG_ERROR, "AWGN: no available_chandefs"); - return 0; -@@ -281,7 +325,7 @@ int hostapd_intf_awgn_detected(struct hostapd_iface *iface, int freq, int chan_w - } - - chan_idx = _rand % num_available_chandefs; -- intf_awgn_find_channel(iface, &chan_data, chan_idx, chan_width); -+ intf_awgn_find_channel(iface, &chan_data, chan_idx, chan_width, cf1); - - if (!chan_data) { - wpa_printf(MSG_ERROR, "AWGN: no random channel found, chan idx : %d", -@@ -295,7 +339,7 @@ int hostapd_intf_awgn_detected(struct hostapd_iface *iface, int freq, int chan_w - */ - chan_data = NULL; - chan_idx = (chan_idx + 1) % num_available_chandefs; -- intf_awgn_find_channel(iface, &chan_data, chan_idx, chan_width); -+ intf_awgn_find_channel(iface, &chan_data, chan_idx, chan_width, cf1); - if (!chan_data) { - wpa_printf(MSG_ERROR, - "AWGN: random channel not found, chan idx : %d", -@@ -319,7 +363,12 @@ int hostapd_intf_awgn_detected(struct hostapd_iface *iface, int freq, int chan_w - return 0; - } - -- if ((chan_width > CHAN_WIDTH_80) && -+ if ((chan_width > CHAN_WIDTH_160) && -+ !(chan_bw_interference_bitmap & SEG_SEC80) && -+ !(chan_bw_interference_bitmap & SEG_SEC40) && -+ !(chan_bw_interference_bitmap & SEG_SEC20)) -+ new_chan_width = CHAN_WIDTH_160; -+ else if ((chan_width > CHAN_WIDTH_80) && - !(chan_bw_interference_bitmap & SEG_SEC40) && - !(chan_bw_interference_bitmap & SEG_SEC20)) - new_chan_width = CHAN_WIDTH_80; -@@ -358,6 +407,9 @@ int hostapd_intf_awgn_detected(struct hostapd_iface *iface, int freq, int chan_w - case CHAN_WIDTH_160: - settings.freq_params.bandwidth = 160; - break; -+ case CHAN_WIDTH_320: -+ settings.freq_params.bandwidth = 320; -+ break; - default: - settings.freq_params.bandwidth = 20; - break; -@@ -367,6 +419,7 @@ int hostapd_intf_awgn_detected(struct hostapd_iface *iface, int freq, int chan_w - settings.freq_params.ht_enabled = iface->conf->ieee80211n; - settings.freq_params.vht_enabled = iface->conf->ieee80211ac; - settings.freq_params.he_enabled = iface->conf->ieee80211ax; -+ settings.freq_params.eht_enabled= iface->conf->ieee80211be; - - for (i = 0; i < iface->num_bss; i++) { - /* Save CHAN_SWITCH VHT and HE config */ --- -2.7.4 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-051-hostapd-fix-channel-switch-frequency-check.patch b/feeds/ipq95xx/hostapd/patches/q02-051-hostapd-fix-channel-switch-frequency-check.patch deleted file mode 100644 index 4aa9fb1de..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-051-hostapd-fix-channel-switch-frequency-check.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 03ad17e6281ebfd25a9747cea468be428f5af990 Mon Sep 17 00:00:00 2001 -From: Karthik M -Date: Fri, 7 Oct 2022 23:52:15 +0530 -Subject: [PATCH] hostapd: Frequency check during channel switch across BW - -Add the check for verifying the frequency for different BW -received during channel switch. - -Check makes sure that the channel frequency is appropriate -and lies within the center frequency. - -Signed-off-by: Karthik M ---- - hostapd/ctrl_iface.c | 145 +++++++++++++++++++++++-------------------- - 1 file changed, 76 insertions(+), 69 deletions(-) - ---- a/hostapd/ctrl_iface.c -+++ b/hostapd/ctrl_iface.c -@@ -2764,19 +2764,23 @@ static int hostapd_ctrl_check_freq_param - switch (params->sec_channel_offset) { - case 1: - if (params->freq + 150 != params->center_freq1 && -- params->freq + 70 != params->center_freq1 && -- params->freq + 30 != params->center_freq1 && -- params->freq - 10 != params->center_freq1 && -- params->freq - 50 != params->center_freq1 && -+ params->freq + 110 != params->center_freq1 && -+ params->freq + 70 != params->center_freq1 && -+ params->freq + 30 != params->center_freq1 && -+ params->freq - 10 != params->center_freq1 && -+ params->freq - 50 != params->center_freq1 && -+ params->freq - 90 != params->center_freq1 && - params->freq - 130 != params->center_freq1) - return -1; - break; - case -1: - if (params->freq + 130 != params->center_freq1 && -- params->freq + 50 != params->center_freq1 && -- params->freq + 10 != params->center_freq1 && -- params->freq - 30 != params->center_freq1 && -- params->freq - 70 != params->center_freq1 && -+ params->freq + 90 != params->center_freq1 && -+ params->freq + 50 != params->center_freq1 && -+ params->freq + 10 != params->center_freq1 && -+ params->freq - 30 != params->center_freq1 && -+ params->freq - 70 != params->center_freq1 && -+ params->freq - 110 != params->center_freq1 && - params->freq - 150 != params->center_freq1) - return -1; - break; diff --git a/feeds/ipq95xx/hostapd/patches/q02-052-hostapd-make-probe-response-as-broadcast-for-6GHz-ba.patch b/feeds/ipq95xx/hostapd/patches/q02-052-hostapd-make-probe-response-as-broadcast-for-6GHz-ba.patch deleted file mode 100644 index fb3a92292..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-052-hostapd-make-probe-response-as-broadcast-for-6GHz-ba.patch +++ /dev/null @@ -1,42 +0,0 @@ -From ec78b0e8a7ebd3d705b4119a795e044e3437670b Mon Sep 17 00:00:00 2001 -From: Hari Chandrakanthan -Date: Tue, 11 Oct 2022 23:57:00 +0530 -Subject: [PATCH] hostapd : make probe response as broadcast for 6GHz band - -Make probe response as broadcast for 6GHz band as mentioned -in the spec IEEE Std 802.11ax‐2021 section 26.17.2.3.2, -"If a 6 GHz AP receives a Probe Request frame and responds with a Probe -Response frame (per 11.1.4.3.4), the Address 1 field of the Probe -Response frame shall be set to the broadcast address, unless -the AP is not indicating its actual SSID in the SSID element -of its Beacon frames." - -Fixes: I6af7154bddf ("hostapd: Package Upgrade to b26f5c0fe3") - -Signed-off-by: Hari Chandrakanthan ---- - src/ap/beacon.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/src/ap/beacon.c b/src/ap/beacon.c -index 9536e76..011c0fc 100644 ---- a/src/ap/beacon.c -+++ b/src/ap/beacon.c -@@ -664,8 +664,13 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, - - resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_PROBE_RESP); -- if (req) -+ -+ if (req && (!is_6ghz_op_class(hapd->iconf->op_class) || -+ hapd->conf->ignore_broadcast_ssid)) - os_memcpy(resp->da, req->sa, ETH_ALEN); -+ else -+ os_memset(resp->da, 0xff, ETH_ALEN); -+ - os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN); - - os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN); --- -2.7.4 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-053-hostapd-awgn-fix-new-channel-selection-logic.patch b/feeds/ipq95xx/hostapd/patches/q02-053-hostapd-awgn-fix-new-channel-selection-logic.patch deleted file mode 100644 index dd8fc94ef..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-053-hostapd-awgn-fix-new-channel-selection-logic.patch +++ /dev/null @@ -1,421 +0,0 @@ -From 0fffe1c539734f9dc26a80fb80eddb7ea1f1af46 Mon Sep 17 00:00:00 2001 -From: Hari Chandrakanthan -Date: Mon, 31 Oct 2022 19:51:32 +0530 -Subject: [PATCH] hostapd : awgn - fix new channel selection logic - -From the list of channels allowed by Australia, -only one 320 MHz operable channel is available. - -So if awgn is detected when operating in 320 MHz, the ap -needs to reduce its bandwidth to next max available bw 160 MHz. - -But with current design if no other 320 Mhz channel is available, -hostapd bails out with a log saying that no channel with 320 MHz is available. -we don't check for next max available bandwidth in our current design and -this leads to ap to remain in the same channel even if awgn is detected. - -So the channel selection logic is changed in a way that the next max -available bandwidth is searched if no new channel is available for current -bandwidth. The search continues till 20 MHz bandwidth. - -This generic logic will help to fix similar issues in future. - -Also optimized the channel selection logic by looping over the list of all -the channels only once. - -Signed-off-by: Hari Chandrakanthan ---- - src/ap/interference.c | 249 ++++++++++++++++++++++++++++++++------------------ - 1 file changed, 160 insertions(+), 89 deletions(-) - -diff --git a/src/ap/interference.c b/src/ap/interference.c -index 4148489..1d66d6f 100644 ---- a/src/ap/interference.c -+++ b/src/ap/interference.c -@@ -46,6 +46,23 @@ - #include "eloop.h" - #include "hw_features.h" - -+static bool is_chan_disabled(struct hostapd_hw_modes *mode, int chan_num) -+{ -+ int chan_disabled = 1; -+ int i; -+ struct hostapd_channel_data *temp_chan; -+ -+ for (i = 0; i < mode->num_channels; i++) { -+ temp_chan = &mode->channels[i]; -+ if (temp_chan->chan == chan_num && -+ (!(temp_chan->flag & HOSTAPD_CHAN_DISABLED))) { -+ chan_disabled = 0; -+ break; -+ } -+ } -+ return chan_disabled; -+} -+ - /* - * intf_awgn_chan_range_available - check whether the channel can operate - * in the given bandwidth in 6Ghz -@@ -63,8 +80,11 @@ static int intf_awgn_chan_range_available(struct hostapd_hw_modes *mode, - 193, 209}; - int allowed_160_6g[] = {1, 33, 65, 97, 129, 161, 193}; - int allowed_320_6g[] = {1, 65, 129, 33, 97, 161}; -+ int allowed_arr_size = 0; -+ int *allowed_arr = NULL; - int chan_idx_match = 0; -- int i; -+ int chan_disabled = 0; -+ int i, j; - - first_chan = &mode->channels[first_chan_idx]; - -@@ -77,33 +97,40 @@ static int intf_awgn_chan_range_available(struct hostapd_hw_modes *mode, - if (num_chans == 1) - return 1; - -- if (num_chans == 2) { /* 40Mhz channel */ -- for (i = 0; i < ARRAY_SIZE(allowed_40_6g); i++) { -- if (first_chan->chan == allowed_40_6g[i]) { -- chan_idx_match = 1; -- break; -- } -- } -- } else if (num_chans == 4) { /* 80Mhz channel */ -- for (i = 0; i < ARRAY_SIZE(allowed_80_6g); i++) { -- if (first_chan->chan == allowed_80_6g[i]) { -- chan_idx_match = 1; -- break; -- } -- } -- } else if (num_chans == 8) { /* 160Mhz channel */ -- for (i = 0; i < ARRAY_SIZE(allowed_160_6g); i++) { -- if (first_chan->chan == allowed_160_6g[i]) { -- chan_idx_match = 1; -- break; -+ switch (num_chans) { -+ case 2: -+ allowed_arr_size = ARRAY_SIZE(allowed_40_6g); -+ allowed_arr = allowed_40_6g; -+ break; -+ case 4: -+ allowed_arr_size = ARRAY_SIZE(allowed_80_6g); -+ allowed_arr = allowed_80_6g; -+ break; -+ case 8: -+ allowed_arr_size = ARRAY_SIZE(allowed_160_6g); -+ allowed_arr = allowed_160_6g; -+ break; -+ case 16: -+ allowed_arr_size = ARRAY_SIZE(allowed_320_6g); -+ allowed_arr = allowed_320_6g; -+ break; -+ default: -+ allowed_arr_size = 0; -+ break; -+ } -+ -+ /* check whether all the 20 MHz channels in the given operating range is enabled */ -+ for (i = 0; i < allowed_arr_size; i++) { -+ if (first_chan->chan == allowed_arr[i]) { -+ for (j = 1; j <= num_chans - 1; j++) { -+ if (is_chan_disabled(mode, first_chan->chan + j * 4)) { -+ chan_disabled = 1; -+ break; -+ } - } -- } -- } else if (num_chans == 16) { /* 320Mhz channel */ -- for (i = 0; i < ARRAY_SIZE(allowed_320_6g); i++) { -- if (first_chan->chan == allowed_320_6g[i]) { -+ if (!chan_disabled) - chan_idx_match = 1; -- break; -- } -+ break; - } - } - -@@ -159,21 +186,28 @@ int get_centre_freq_6g(int chan_idx, int chan_width, int *centre_freq) - - - /* -- *intf_awgn_find_channel - find the channel that can operate with bandwidth chan_width. -- If idx doesn't match with index of any of the existing channel, then the api -- returns the total number of available chandefs that supports the provided bandwidth -- * @idx - index of the channel -- * @chan_width - bandwidth of the channel -+ * intf_awgn_find_channel_list - find the list of channels that can operate with -+ channel width chan_width and not present within the range of current operating range. -+ returns the total number of available chandefs that supports the provided bandwidth -+ * @chan_width - channel width to be checked -+ * @curr_centre_freq - current centre frequency -+ * @curr_chan_width - current channel width -+ * @chandef_list - pointer array to hold the list of valid available chandef - */ --static int intf_awgn_find_channel(struct hostapd_iface *iface, -- struct hostapd_channel_data **ret_chan, -- int idx, int chan_width, int cs1) -+static int intf_awgn_find_channel_list(struct hostapd_iface *iface, -+ int chan_width, int curr_centre_freq, -+ int curr_chan_width, -+ struct hostapd_channel_data ***chandef_list) - { - struct hostapd_hw_modes *mode = iface->current_mode; - struct hostapd_channel_data *chan; - int i, channel_idx = 0, n_chans; -- int temp_centre_freq; -+ int new_centre_freq; - int ret; -+ int curr_start_freq; -+ int curr_end_freq; -+ int new_start_freq; -+ int new_end_freq; - - switch (chan_width) { - case CHAN_WIDTH_20_NOHT: -@@ -198,6 +232,9 @@ static int intf_awgn_find_channel(struct hostapd_iface *iface, - break; - } - -+ curr_start_freq = curr_centre_freq - channel_width_to_int(curr_chan_width) / 2; -+ curr_end_freq = curr_centre_freq + channel_width_to_int(curr_chan_width) / 2; -+ - for (i = 0; i < mode->num_channels; i++) { - chan = &mode->channels[i]; - -@@ -216,44 +253,49 @@ static int intf_awgn_find_channel(struct hostapd_iface *iface, - continue; - } - -- if (chan_width == CHAN_WIDTH_320) { -- ret = get_centre_freq_6g(chan->chan, CHAN_WIDTH_320, -- &temp_centre_freq); -- if (ret) { -- wpa_printf(MSG_ERROR, -- "AWGN : couldn't find centre freq for chan : %d" -- " chan_width : %d", chan->chan, CHAN_WIDTH_320); -- return 0; -- } -- -- if (abs(temp_centre_freq - cs1) < 320) { -- wpa_printf(MSG_DEBUG, -- "AWGN: channel %d is a overlapping channel so skipping", -- chan->freq); -- continue; -- } -+ ret = get_centre_freq_6g(chan->chan, chan_width, -+ &new_centre_freq); -+ if (ret) { -+ wpa_printf(MSG_ERROR, -+ "AWGN : couldn't find centre freq for chan : %d" -+ " chan_width : %d", chan->chan, chan_width); -+ return 0; - } - -- if (ret_chan && idx == channel_idx) { -- wpa_printf(MSG_DEBUG, "AWGN: Selected channel %d (%d)", -- chan->freq, chan->chan); -- *ret_chan = chan; -- return idx; -+ new_start_freq = new_centre_freq - channel_width_to_int(chan_width) / 2; -+ new_end_freq = new_centre_freq + channel_width_to_int(chan_width) / 2; -+ -+ /* check whether new operating range is outside the current -+ * operating range since current operating range contains awgn -+ * interference -+ */ -+ if (((new_start_freq > curr_start_freq) && (new_start_freq < curr_end_freq)) || -+ ((new_end_freq > curr_start_freq) && (new_end_freq < curr_end_freq)) || -+ ((new_centre_freq > curr_start_freq && new_centre_freq < curr_end_freq))) { -+ wpa_printf(MSG_DEBUG, -+ "AWGN : freq range overlap new_start_freq : %d" -+ " new_end_freq : %d curr_start_freq : %d" -+ " curr_end_freq : %d centre_freq : %d", -+ new_start_freq, new_end_freq, curr_start_freq, -+ curr_end_freq, new_centre_freq); -+ continue; - } - -- wpa_printf(MSG_DEBUG, "AWGN: Adding channel %d (%d)", -+ wpa_printf(MSG_DEBUG, "AWGN: Adding channel %d (%d) to valid chandef list", - chan->freq, chan->chan); -+ (*chandef_list)[channel_idx] = chan; - channel_idx++; - } -+ - return channel_idx; - } - - enum chan_seg { -- SEG_PRI20 = 0x1, -- SEG_SEC20 = 0x2, -- SEG_SEC40_LOW = 0x4, -- SEG_SEC40_UP = 0x8, -- SEG_SEC40 = 0xC, -+ SEG_PRI20 = 0x1, -+ SEG_SEC20 = 0x2, -+ SEG_SEC40_LOW = 0x4, -+ SEG_SEC40_UP = 0x8, -+ SEG_SEC40 = 0xC, - SEG_SEC80_LOW = 0x10, - SEG_SEC80_LOW_UP = 0x20, - SEG_SEC80_UP_LOW = 0x40, -@@ -270,6 +312,31 @@ enum chan_seg { - SEG_SEC160 = 0xFF00, - }; - -+int get_next_max_width(int chan_width) -+{ -+ int next_max_width; -+ -+ switch (chan_width) { -+ case CHAN_WIDTH_320: -+ next_max_width = CHAN_WIDTH_160; -+ break; -+ case CHAN_WIDTH_160: -+ next_max_width = CHAN_WIDTH_80; -+ break; -+ case CHAN_WIDTH_80: -+ next_max_width = CHAN_WIDTH_40; -+ break; -+ case CHAN_WIDTH_40: -+ next_max_width = CHAN_WIDTH_20; -+ break; -+ default: -+ next_max_width = CHAN_WIDTH_20_NOHT; -+ break; -+ } -+ -+ return next_max_width; -+} -+ - /* - * hostapd_intf_awgn_detected - awgn interference is detected in the operating channel. - * The interference channel information is available as a -@@ -283,14 +350,16 @@ int hostapd_intf_awgn_detected(struct hostapd_iface *iface, int freq, int chan_w - struct csa_settings settings; - struct hostapd_channel_data *chan_data = NULL; - struct hostapd_channel_data *chan_temp = NULL; -+ struct hostapd_channel_data **available_chandef_list = NULL; - int ret; - unsigned int i; - u32 _rand; - u32 chan_idx; -- int num_available_chandefs; -+ int num_available_chandefs = 0; - u8 channel_switch = 0; - int new_chan_width; - int new_centre_freq; -+ int temp_width; - struct hostapd_hw_modes *mode = iface->current_mode; - - wpa_printf(MSG_DEBUG, -@@ -302,7 +371,7 @@ int hostapd_intf_awgn_detected(struct hostapd_iface *iface, int freq, int chan_w - - if (iface->conf->discard_6g_awgn_event) { - wpa_printf(MSG_DEBUG, "discard_6g_awgn_event set ignoring" -- "AWGN DETECT event from driver"); -+ " AWGN DETECT event from driver"); - return 0; - } - -@@ -310,47 +379,47 @@ int hostapd_intf_awgn_detected(struct hostapd_iface *iface, int freq, int chan_w - if (!chan_bw_interference_bitmap || (chan_bw_interference_bitmap & SEG_PRI20)) - channel_switch = 1; - -+ available_chandef_list = os_zalloc(sizeof(struct hostapd_channel_data *) * -+ mode->num_channels); - if (channel_switch) { -- /* Find a random channel to be switched */ -- num_available_chandefs = intf_awgn_find_channel(iface, NULL, 0, -- chan_width, cf1); -+ /* find a random channel to be switched */ -+ temp_width = chan_width; -+ -+ while (temp_width > CHAN_WIDTH_20_NOHT) { -+ num_available_chandefs = intf_awgn_find_channel_list(iface, -+ temp_width, -+ cf1, chan_width, -+ &available_chandef_list); -+ if (num_available_chandefs == 0) -+ temp_width = get_next_max_width(temp_width); -+ else -+ break; -+ } -+ - if (num_available_chandefs == 0) { - wpa_printf(MSG_ERROR, "AWGN: no available_chandefs"); -- return 0; -+ goto exit; - } - - if (os_get_random((u8 *)&_rand, sizeof(_rand)) < 0) { - wpa_printf(MSG_ERROR, "AWGN: couldn't get random number"); -- return 0; -+ goto exit; - } - - chan_idx = _rand % num_available_chandefs; -- intf_awgn_find_channel(iface, &chan_data, chan_idx, chan_width, cf1); -+ -+ chan_data = available_chandef_list[chan_idx]; - - if (!chan_data) { -- wpa_printf(MSG_ERROR, "AWGN: no random channel found, chan idx : %d", -+ wpa_printf(MSG_ERROR, "AWGN: channel info not available for chan_idx : %d", - chan_idx); -- return 0; -+ goto exit; - } - -- if(chan_data->freq == freq) { -- /* New random channel is same as operating channel -- * so choose another channel -- */ -- chan_data = NULL; -- chan_idx = (chan_idx + 1) % num_available_chandefs; -- intf_awgn_find_channel(iface, &chan_data, chan_idx, chan_width, cf1); -- if (!chan_data) { -- wpa_printf(MSG_ERROR, -- "AWGN: random channel not found, chan idx : %d", -- chan_idx); -- return 0; -- } -- } -+ new_chan_width = temp_width; - - wpa_printf(MSG_DEBUG, "AWGN: got random channel %d (%d)", - chan_data->freq, chan_data->chan); -- new_chan_width = chan_width; - } else { - /* interference is not present in the primary 20Mhz, so reduce bandwidth*/ - for (i = 0; i < mode->num_channels; i++) { -@@ -360,7 +429,7 @@ int hostapd_intf_awgn_detected(struct hostapd_iface *iface, int freq, int chan_w - } - if (!chan_data) { - wpa_printf(MSG_ERROR, "AWGN : no channel found"); -- return 0; -+ goto exit; - } - - if ((chan_width > CHAN_WIDTH_160) && -@@ -386,7 +455,7 @@ int hostapd_intf_awgn_detected(struct hostapd_iface *iface, int freq, int chan_w - wpa_printf(MSG_ERROR, - "AWGN : couldn't find centre freq for chan : %d" - " chan_width : %d", chan_data->chan, new_chan_width); -- return 0; -+ goto exit; - } - } else { - new_centre_freq = chan_data->freq; -@@ -442,5 +511,7 @@ int hostapd_intf_awgn_detected(struct hostapd_iface *iface, int freq, int chan_w - } - } - -+exit: -+ os_free(available_chandef_list); - return 0; - } --- -2.7.4 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-053-wpa_supplicant-set-interface-state-as-inactive-if-me.patch b/feeds/ipq95xx/hostapd/patches/q02-053-wpa_supplicant-set-interface-state-as-inactive-if-me.patch deleted file mode 100644 index 604d28962..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-053-wpa_supplicant-set-interface-state-as-inactive-if-me.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 462d1e11d742a496d169e4724f6925794f0d7e03 Mon Sep 17 00:00:00 2001 -From: Hari Chandrakanthan -Date: Thu, 13 Oct 2022 03:35:10 +0530 -Subject: [PATCH] wpa_supplicant : set interface state as inactive if mesh - bringup fails - -In the current design, when mesh + ap is brought up, -mesh is brought up first and then ap is brought up. - -There are cases where mesh bring up can fail. -Eg : mesh configured with acs. - -wpa_supplicant doesn't support acs with mesh. -So mesh bring up fails which is expected. - -The interface state is still maintained -as SCANNING even if mesh bring bring-up fails. - -Since ap bringup depends on mesh bringup and mesh interface state -doesnot reflect the correct state during bringup failure, the ap bring -up is not initiated and that leads to the issue where ap interface remains -disabled. - -So make the interface state as INACTIVE if the mesh bring up fails. - -Signed-off-by: Hari Chandrakanthan ---- - wpa_supplicant/wpa_supplicant.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c -index b9b5bdf..c19ec33 100644 ---- a/wpa_supplicant/wpa_supplicant.c -+++ b/wpa_supplicant/wpa_supplicant.c -@@ -2307,6 +2307,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, - ssid->frequency = bss->freq; - if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) { - wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh"); -+ wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); - return; - } - wpa_s->current_bss = bss; --- -2.7.4 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-054-hostapd-Disable-6GHz-FILS-and-UBPR-for-mutli-band-AP.patch b/feeds/ipq95xx/hostapd/patches/q02-054-hostapd-Disable-6GHz-FILS-and-UBPR-for-mutli-band-AP.patch deleted file mode 100644 index 652a53e97..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-054-hostapd-Disable-6GHz-FILS-and-UBPR-for-mutli-band-AP.patch +++ /dev/null @@ -1,325 +0,0 @@ -From 10ba7b35020ba6882436483a3b1cd74887ff3b36 Mon Sep 17 00:00:00 2001 -From: Hari Chandrakanthan -Date: Mon, 14 Nov 2022 20:53:31 +0530 -Subject: [PATCH] hostapd: Disable 6GHz FILS and UBPR for multi-band AP - -WFA test plan 2.0 has specification below: -3.3.2.1 Out of Box requirements: -FILS Discovery and Unsolicited Probe Response frames disabled -in the 6 GHz band if the AP simultaneously operates -on multiple bands in its out of box configuration. - -Also Channel access latency in 6GHz gets impacted by 20-33% -when there is FILS/UBPR in-band discovery frames. - -Extra transmissions (FILS, UBPRs) are polluting the spectrum -and increasing the potential to cause interference to the -incumbent systems operating in the 6GHz band. - -Keeping these in-band advertisement frames disabled helps -to optimize this latency. So, the aim to is to keep -FILS/UBPR disabled without impacting discoverability. - -Having OOB advertisement in lower band helps to avoid any -impact in AP discoverability even if FILS/UBPR is -disabled in 6GHz. So, keep them disabled if OOB is -ongoing. - -Re-enable in-band discovery with FILS/20 TU PRBR frames -if OOB gets disabled. - -Signed-off-by: Hari Chandrakanthan -Signed-off-by: Rameshkumar Sundaram ---- - src/ap/ap_config.h | 6 ++++ - src/ap/beacon.c | 30 +++++++++++++++++-- - src/ap/hostapd.c | 70 ++++++++++++++++++++++++++++++++++++++++++-- - src/ap/ieee802_11.c | 13 +++----- - src/ap/ieee802_11.h | 8 ++++- - src/drivers/driver_nl80211.c | 20 ++++++++----- - 6 files changed, 125 insertions(+), 22 deletions(-) - -diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h -index 80721ae..ab81568 100644 ---- a/src/ap/ap_config.h -+++ b/src/ap/ap_config.h -@@ -913,6 +913,12 @@ struct hostapd_bss_config { - u8 rnr; - int beacon_tx_mode; - bool xrates_supported; -+ enum { -+ FILS_UBPR_USER_DISABLED, -+ FILS_UBPR_FORCE_DISABLED, -+ FILS_UBPR_ENABLED -+ } fils_state, ubpr_state; -+ - }; - - /** -diff --git a/src/ap/beacon.c b/src/ap/beacon.c -index 450f4b4..7d18473 100644 ---- a/src/ap/beacon.c -+++ b/src/ap/beacon.c -@@ -1401,16 +1401,27 @@ static u8 * hostapd_probe_resp_offloads(struct hostapd_data *hapd, - - - #ifdef CONFIG_IEEE80211AX --/* Unsolicited broadcast Probe Response transmission, 6 GHz only */ -+/* Unsolicited broadcast Probe Response(UBPR) transmission, 6 GHz only */ - static u8 * hostapd_unsol_bcast_probe_resp(struct hostapd_data *hapd, - struct wpa_driver_ap_params *params) - { -+ /* Do not enable UBPR in 6GHz AP if colocated with lower band APs */ -+ hapd->conf->ubpr_state = FILS_UBPR_USER_DISABLED; - if (!is_6ghz_op_class(hapd->iconf->op_class)) - return NULL; - -+ if (hapd->conf->unsol_bcast_probe_resp_interval && -+ (get_colocation_mode(hapd) == COLOCATED_6GHZ)) { -+ hapd->conf->ubpr_state = FILS_UBPR_FORCE_DISABLED; -+ return NULL; -+ } -+ - params->unsol_bcast_probe_resp_interval = - hapd->conf->unsol_bcast_probe_resp_interval; - -+ if (params->unsol_bcast_probe_resp_interval) -+ hapd->conf->ubpr_state = FILS_UBPR_ENABLED; -+ - return hostapd_gen_probe_resp(hapd, NULL, 0, - ¶ms->unsol_bcast_probe_resp_tmpl_len, - NULL, 0); -@@ -1693,6 +1704,17 @@ static u8 * hostapd_gen_fils_discovery(struct hostapd_data *hapd, size_t *len) - static u8 * hostapd_fils_discovery(struct hostapd_data *hapd, - struct wpa_driver_ap_params *params) - { -+ /* Do not enable Fils discovery for 6GHz AP if its colocated -+ * with lower band APs. -+ */ -+ -+ if (is_6ghz_op_class(hapd->iconf->op_class) && -+ get_colocation_mode(hapd) == COLOCATED_6GHZ && -+ hapd->conf->fils_discovery_max_int) { -+ hapd->conf->fils_state = FILS_UBPR_FORCE_DISABLED; -+ return NULL; -+ } -+ - params->fd_max_int = hapd->conf->fils_discovery_max_int; - if (is_6ghz_op_class(hapd->iconf->op_class) && - params->fd_max_int > FD_MAX_INTERVAL_6GHZ) -@@ -1702,10 +1724,12 @@ static u8 * hostapd_fils_discovery(struct hostapd_data *hapd, - if (params->fd_min_int > params->fd_max_int) - params->fd_min_int = params->fd_max_int; - -- if (params->fd_max_int) -+ if (params->fd_max_int) { -+ hapd->conf->fils_state = FILS_UBPR_ENABLED; - return hostapd_gen_fils_discovery(hapd, - ¶ms->fd_frame_tmpl_len); -- -+ } -+ hapd->conf->fils_state = FILS_UBPR_USER_DISABLED; - return NULL; - } - -diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c -index 86e094a..44e2f4b 100644 ---- a/src/ap/hostapd.c -+++ b/src/ap/hostapd.c -@@ -68,7 +68,8 @@ static void hostapd_interface_setup_failure_handler(void *eloop_ctx, - void *timeout_ctx); - static void - hostapd_switch_color_timeout_handler(void *eloop_data, void *user_ctx); -- -+static void -+hostapd_interface_update_fils_ubpr(struct hostapd_iface *iface, bool iface_enabled); - - int hostapd_for_each_interface(struct hapd_interfaces *interfaces, - int (*cb)(struct hostapd_iface *iface, -@@ -2271,6 +2272,8 @@ dfs_offload: - for (j = 0; j < iface->num_bss; j++) - hostapd_neighbor_set_own_report(iface->bss[j]); - -+ hostapd_interface_update_fils_ubpr(iface, true); -+ - return 0; - - fail: -@@ -2504,7 +2507,7 @@ void hostapd_interface_deinit(struct hostapd_iface *iface) - break; - hostapd_bss_deinit(iface->bss[j]); - } -- -+ hostapd_interface_update_fils_ubpr(iface, false); - #ifdef NEED_AP_MLME - hostapd_stop_setup_timers(iface); - eloop_cancel_timeout(ap_ht2040_timeout, iface, NULL); -@@ -2620,6 +2623,68 @@ static int ifname_in_use(struct hapd_interfaces *interfaces, const char *ifname) - return 0; - } - -+/** -+ * hostapd_interface_update_fils_ubpr - Update 6GHz In-band discovery -+ * frames (FILS/UBPR) based on lower band interface state change. -+ * @iface_enabled: Whether lower band AP is enabled or disabled -+ * -+ * This function iterates through interfaces list and updates all 6GHz -+ * APs In-band discovery frames (enable/disable) based on state of lower -+ * band interfaces. -+ * Lower band interfaces going down: Enable FILS/UBPR for all 6GHz APs if config -+ * has it enabled. -+ * Lower band interfaces coming up: Disable FILS/UBPR for all 6GHz APs if not done -+ * already. -+ */ -+ -+static void -+hostapd_interface_update_fils_ubpr(struct hostapd_iface *iface, bool iface_enabled) -+{ -+ int i, j; -+ -+ if (!iface || (iface->interfaces == NULL)) -+ return; -+ -+#ifdef CONFIG_MESH -+ if (iface->mconf != NULL) -+ return; -+#endif -+ -+ if (is_6ghz_op_class(iface->conf->op_class)) -+ return; -+ -+ for (i = 0; i < iface->interfaces->count; i++) { -+ struct hostapd_iface *iface_6g = iface->interfaces->iface[i]; -+ if (iface == iface_6g || !iface_6g || !iface_6g->conf) -+ continue; -+ -+ if (!is_6ghz_op_class(iface_6g->conf->op_class)) -+ continue; -+ -+ for (j = 0; j < iface_6g->num_bss; j++) { -+ if (!iface_6g->bss[j] || !iface_6g->bss[j]->started) -+ continue; -+ -+ /* Lower band interface coming up but fils/ubpr is already disabled */ -+ if (iface_enabled && -+ (iface_6g->bss[j]->conf->fils_state != FILS_UBPR_ENABLED && -+ iface_6g->bss[j]->conf->ubpr_state != FILS_UBPR_ENABLED)) { -+ continue; -+ } -+ /* Lower band interface going down but fils/ubpr is not force disabled */ -+ if (!iface_enabled && -+ (iface_6g->bss[j]->conf->fils_state != FILS_UBPR_FORCE_DISABLED && -+ iface_6g->bss[j]->conf->ubpr_state != FILS_UBPR_FORCE_DISABLED)) { -+ continue; -+ } -+ wpa_printf(MSG_DEBUG, "%s Interface getting %s, check and set 6GHz Interface(%s)" -+ "In-band discovery frames", iface->bss[0]->conf->iface, -+ iface_enabled ? "enabled" : "disabled", iface_6g->bss[j]->conf->iface); -+ ieee802_11_set_beacon(iface_6g->bss[j]); -+ } -+ } -+ return; -+} - - /** - * hostapd_interface_init_bss - Read configuration file and init BSS data -@@ -2899,6 +2964,7 @@ int hostapd_disable_iface(struct hostapd_iface *hapd_iface) - wpa_printf(MSG_DEBUG, "Interface %s disabled", - hapd_iface->bss[0]->conf->iface); - hostapd_set_state(hapd_iface, HAPD_IFACE_DISABLED); -+ hostapd_interface_update_fils_ubpr(hapd_iface, false); - return 0; - } - -diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c -index 0502587..fea45da 100644 ---- a/src/ap/ieee802_11.c -+++ b/src/ap/ieee802_11.c -@@ -7446,15 +7446,7 @@ static size_t hostapd_eid_rnr_iface_len(struct hostapd_data *hapd, - return total_len; - } - -- --enum colocation_mode { -- NO_COLOCATED_6GHZ, -- STANDALONE_6GHZ, -- COLOCATED_6GHZ, -- COLOCATED_LOWER_BAND, --}; -- --static enum colocation_mode get_colocation_mode(struct hostapd_data *hapd) -+enum colocation_mode get_colocation_mode(struct hostapd_data *hapd) - { - u8 i; - bool is_6ghz = is_6ghz_op_class(hapd->iconf->op_class); -@@ -7473,6 +7465,9 @@ static enum colocation_mode get_colocation_mode(struct hostapd_data *hapd) - if (iface == hapd->iface || !iface || !iface->conf) - continue; - -+ if (iface->state == HAPD_IFACE_DISABLED) -+ continue; -+ - is_colocated_6ghz = is_6ghz_op_class(iface->conf->op_class); - if (!is_6ghz && is_colocated_6ghz) - return COLOCATED_LOWER_BAND; -diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h -index 79b0e54..7cdcf81 100644 ---- a/src/ap/ieee802_11.h -+++ b/src/ap/ieee802_11.h -@@ -19,7 +19,13 @@ struct ieee80211_mgmt; - struct radius_sta; - enum ieee80211_op_mode; - struct mac_acl_entry; -- -+enum colocation_mode { -+ NO_COLOCATED_6GHZ, -+ STANDALONE_6GHZ, -+ COLOCATED_6GHZ, -+ COLOCATED_LOWER_BAND, -+}; -+enum colocation_mode get_colocation_mode(struct hostapd_data *hapd); - int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len, - struct hostapd_frame_info *fi); - void ieee802_11_mgmt_cb(struct hostapd_data *hapd, const u8 *buf, size_t len, -diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c -index 7687a72..d7b9508 100644 ---- a/src/drivers/driver_nl80211.c -+++ b/src/drivers/driver_nl80211.c -@@ -4506,10 +4506,13 @@ static int nl80211_fils_discovery(struct i802_bss *bss, struct nl_msg *msg, - struct nlattr *attr; - - if (!bss->drv->fils_discovery) { -- wpa_printf(MSG_ERROR, -- "nl80211: Driver does not support FILS Discovery frame transmission for %s", -- bss->ifname); -- return -1; -+ if (params->fd_max_int) { -+ wpa_printf(MSG_ERROR, -+ "nl80211: Driver does not support FILS Discovery frame transmission for %s", -+ bss->ifname); -+ return -1; -+ } -+ return 0; - } - - attr = nla_nest_start(msg, NL80211_ATTR_FILS_DISCOVERY); -@@ -4537,10 +4540,13 @@ static int nl80211_unsol_bcast_probe_resp(struct i802_bss *bss, - struct nlattr *attr; - - if (!bss->drv->unsol_bcast_probe_resp) { -- wpa_printf(MSG_ERROR, -- "nl80211: Driver does not support unsolicited broadcast Probe Response frame transmission for %s", -+ if (params->unsol_bcast_probe_resp_interval) { -+ wpa_printf(MSG_ERROR, -+ "nl80211: Driver does not support unsolicited broadcast Probe Response frame transmission for %s", - bss->ifname); -- return -1; -+ return -1; -+ } -+ return 0; - } - - wpa_printf(MSG_DEBUG, --- -2.7.4 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-46-hostapd-Add-support-to-enable-disable-bss-color-coll.patch b/feeds/ipq95xx/hostapd/patches/q02-46-hostapd-Add-support-to-enable-disable-bss-color-coll.patch deleted file mode 100644 index 11a30ddd7..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-46-hostapd-Add-support-to-enable-disable-bss-color-coll.patch +++ /dev/null @@ -1,143 +0,0 @@ -From f0ec4fbe637b87e21ae5443318be5e322cc6f895 Mon Sep 17 00:00:00 2001 -From: Dinesh Karthikeyan -Date: Thu, 9 Jun 2022 11:42:34 +0530 -Subject: [PATCH] hostapd: Add support to enable/disable bss color collision - detection - -Add color collision detection parameters to provide user config -option to enable or disable it. - -Signed-off-by: Dinesh Karthikeyan ---- - hostapd/config_file.c | 2 ++ - hostapd/hostapd.conf | 4 ++++ - src/ap/ap_config.c | 1 + - src/ap/ap_config.h | 1 + - src/ap/beacon.c | 2 ++ - src/drivers/driver.h | 6 ++++++ - src/drivers/driver_nl80211.c | 5 ++++- - src/drivers/nl80211_copy.h | 3 +++ - 8 files changed, 23 insertions(+), 1 deletion(-) - -diff --git a/hostapd/config_file.c b/hostapd/config_file.c -index 2aae477..ede28a7 100644 ---- a/hostapd/config_file.c -+++ b/hostapd/config_file.c -@@ -3430,6 +3430,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, - conf->he_op.he_bss_color_disabled = 0; - } else if (os_strcmp(buf, "he_bss_color_partial") == 0) { - conf->he_op.he_bss_color_partial = atoi(pos); -+ } else if (os_strcmp(buf, "he_bss_color_collision_detection") == 0) { -+ conf->he_op.he_bss_color_collision_detection = atoi(pos); - } else if (os_strcmp(buf, "he_default_pe_duration") == 0) { - conf->he_op.he_default_pe_duration = atoi(pos); - } else if (os_strcmp(buf, "he_twt_required") == 0) { -diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf -index e4328d3..426ff97 100644 ---- a/hostapd/hostapd.conf -+++ b/hostapd/hostapd.conf -@@ -846,6 +846,10 @@ wmm_ac_vo_acm=0 - # he_bss_color_partial: BSS color AID equation - #he_bss_color_partial=0 - -+# he_bss_color_collision_detection: disable/enable BSS color collision -+#detection # 0 = disabled # 1 = enabled (default) -+#he_bss_color_collision_detection=1 -+ - #he_default_pe_duration: The duration of PE field in an HE PPDU in us - # Possible values are 0 us (default), 4 us, 8 us, 12 us, and 16 us - #he_default_pe_duration=0 -diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c -index a237e72..aca3420 100644 ---- a/src/ap/ap_config.c -+++ b/src/ap/ap_config.c -@@ -278,6 +278,7 @@ struct hostapd_config * hostapd_config_defaults(void) - conf->he_op.he_bss_color_disabled = 1; - conf->he_op.he_bss_color_partial = 0; - conf->he_op.he_bss_color = os_random() % 63 + 1; -+ conf->he_op.he_bss_color_collision_detection = 1; - conf->he_op.he_twt_responder = 1; - conf->he_6ghz_max_mpdu = 2; - conf->he_6ghz_max_ampdu_len_exp = 7; -diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h -index e16b123..5d12cf5 100644 ---- a/src/ap/ap_config.h -+++ b/src/ap/ap_config.h -@@ -932,6 +932,7 @@ struct he_operation { - u8 he_bss_color; - u8 he_bss_color_disabled; - u8 he_bss_color_partial; -+ u8 he_bss_color_collision_detection; - u8 he_default_pe_duration; - u8 he_twt_required; - u8 he_twt_responder; -diff --git a/src/ap/beacon.c b/src/ap/beacon.c -index e331f9c..ed4444b 100644 ---- a/src/ap/beacon.c -+++ b/src/ap/beacon.c -@@ -2149,6 +2149,8 @@ static int __ieee802_11_set_beacon(struct hostapd_data *hapd) - params.he_bss_color_partial = - hapd->iface->conf->he_op.he_bss_color_partial; - params.he_bss_color = hapd->iface->conf->he_op.he_bss_color; -+ params.he_bss_color_collision_detection = -+ hapd->iface->conf->he_op.he_bss_color_collision_detection; - params.twt_responder = hostapd_get_he_twt_responder(hapd, - IEEE80211_MODE_AP); - params.unsol_bcast_probe_resp_tmpl = -diff --git a/src/drivers/driver.h b/src/drivers/driver.h -index 038379b..70ec0fc 100644 ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -1625,6 +1625,12 @@ struct wpa_driver_ap_params { - int he_bss_color; - - /** -+ * he_bss_color_collision_detection - Whether the BSS Color collision -+ * detection is enabled -+ */ -+ int he_bss_color_collision_detection; -+ -+ /** - * twt_responder - Whether Target Wait Time responder is enabled - */ - int twt_responder; -diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c -index a89097d..c885489 100644 ---- a/src/drivers/driver_nl80211.c -+++ b/src/drivers/driver_nl80211.c -@@ -4895,7 +4895,10 @@ static int wpa_driver_nl80211_set_ap(void *priv, - (params->he_bss_color_partial && - nla_put_flag(msg, NL80211_HE_BSS_COLOR_ATTR_PARTIAL)) || - nla_put_u8(msg, NL80211_HE_BSS_COLOR_ATTR_COLOR, -- params->he_bss_color)) -+ params->he_bss_color) || -+ (!params->he_bss_color_collision_detection && -+ nla_put_flag(msg, -+ NL80211_HE_BSS_COLOR_ATTR_COLLISION_DETECTION_DISABLED))) - goto fail; - nla_nest_end(msg, bss_color); - } -diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h -index e14e3ac..2ba40ba 100644 ---- a/src/drivers/nl80211_copy.h -+++ b/src/drivers/nl80211_copy.h -@@ -7231,6 +7231,8 @@ enum nl80211_obss_pd_attributes { - * @NL80211_HE_BSS_COLOR_ATTR_COLOR: the current BSS Color. - * @NL80211_HE_BSS_COLOR_ATTR_DISABLED: is BSS coloring disabled. - * @NL80211_HE_BSS_COLOR_ATTR_PARTIAL: the AID equation to be used.. -+ * @NL80211_HE_BSS_COLOR_ATTR_COLLISION_DETECTION_DISABLED: is BSS -+ * color collision detection disabled. - * - * @__NL80211_HE_BSS_COLOR_ATTR_LAST: Internal - * @NL80211_HE_BSS_COLOR_ATTR_MAX: highest BSS Color attribute. -@@ -7241,6 +7243,7 @@ enum nl80211_bss_color_attributes { - NL80211_HE_BSS_COLOR_ATTR_COLOR, - NL80211_HE_BSS_COLOR_ATTR_DISABLED, - NL80211_HE_BSS_COLOR_ATTR_PARTIAL, -+ NL80211_HE_BSS_COLOR_ATTR_COLLISION_DETECTION_DISABLED, - - /* keep last */ - __NL80211_HE_BSS_COLOR_ATTR_LAST, --- -2.7.4 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-47-Changes-to-disable-compilation-errors-in-32-bit-arch.patch b/feeds/ipq95xx/hostapd/patches/q02-47-Changes-to-disable-compilation-errors-in-32-bit-arch.patch deleted file mode 100644 index 35cd92551..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-47-Changes-to-disable-compilation-errors-in-32-bit-arch.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 724e708744606d4b8e2a8e5732730e2ff368ff0c Mon Sep 17 00:00:00 2001 -From: Avula Sri Charan -Date: Thu, 27 Oct 2022 10:52:12 +0530 -Subject: [PATCH] Changes to disable compilation errors in 32 bit - -In yocto builds signcontext-32.h will be included for 32 -bit builds and signcontext-64.h for 64 bit builds because -of the absence of linux/types.h in signcontext-32.h we will -face the error __s8 undfined.So adding typedef of __s8 in -linux_wext.h. - -Signed-off-by: Avula Sri Charan ---- - src/drivers/linux_wext.h | 1 + - 1 file changed, 1 insertion(+) - -Index: hostapd-2021-12-13-b26f5c0f/src/drivers/linux_wext.h -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/drivers/linux_wext.h -+++ hostapd-2021-12-13-b26f5c0f/src/drivers/linux_wext.h -@@ -27,6 +27,7 @@ typedef uint16_t __u16; - typedef int16_t __s16; - typedef uint8_t __u8; - typedef int8_t __s8; -+typedef __signed__ char __s8; - #ifndef __user - #define __user - #endif /* __user */ diff --git a/feeds/ipq95xx/hostapd/patches/q02-50-hostapd-240MHz-Q-Q-vendor-IE-support.patch b/feeds/ipq95xx/hostapd/patches/q02-50-hostapd-240MHz-Q-Q-vendor-IE-support.patch deleted file mode 100644 index 54df819ee..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-50-hostapd-240MHz-Q-Q-vendor-IE-support.patch +++ /dev/null @@ -1,532 +0,0 @@ -From e4b73d7748efe3a6fe273a87897254ac9fcebbb1 Mon Sep 17 00:00:00 2001 -From: Ramya Gnanasekar -Date: Wed, 26 Oct 2022 15:19:47 +0530 -Subject: [PATCH] hostapd: 240MHz Q-Q vendor IE support - -240MHz is Q-Q feature and it should be advertised through -vendor IE in beacon, probe request/response and association. - -This patch has changes to add vendor IE to management frames, -parse the IE from STA and copy the capability which is later -advertised to mac80211 through NL attribute. - -Signed-off-by: Ramya Gnanasekar - -Index: hostapd-2021-12-13-b26f5c0f/src/ap/ap_drv_ops.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/ap/ap_drv_ops.c -+++ hostapd-2021-12-13-b26f5c0f/src/ap/ap_drv_ops.c -@@ -419,6 +419,8 @@ int hostapd_sta_add(struct hostapd_data - size_t he_capab_len, size_t eht_capab_len, - const struct ieee80211_he_6ghz_band_cap *he_6ghz_capab, - u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps, -+ const struct ieee80211_240mhz_vendor_oper *eht_240mhz_capab, -+ size_t eht_240mhz_len, - int set) - { - struct hostapd_sta_add_params params; -@@ -448,6 +450,8 @@ int hostapd_sta_add(struct hostapd_data - params.qosinfo = qosinfo; - params.support_p2p_ps = supp_p2p_ps; - params.set = set; -+ params.eht_240mhz_capab = eht_240mhz_capab; -+ params.eht_240mhz_len = eht_240mhz_len; - return hapd->driver->sta_add(hapd->drv_priv, ¶ms); - } - -Index: hostapd-2021-12-13-b26f5c0f/src/ap/ap_drv_ops.h -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/ap/ap_drv_ops.h -+++ hostapd-2021-12-13-b26f5c0f/src/ap/ap_drv_ops.h -@@ -46,6 +46,8 @@ int hostapd_sta_add(struct hostapd_data - size_t he_capab_len, size_t eht_capab_len, - const struct ieee80211_he_6ghz_band_cap *he_6ghz_capab, - u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps, -+ const struct ieee80211_240mhz_vendor_oper *eht_240mhz_capab, -+ size_t eht_240mhz_len, - int set); - int hostapd_set_privacy(struct hostapd_data *hapd, int enabled); - int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem, -Index: hostapd-2021-12-13-b26f5c0f/src/ap/beacon.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/ap/beacon.c -+++ hostapd-2021-12-13-b26f5c0f/src/ap/beacon.c -@@ -651,6 +651,10 @@ static u8 * hostapd_gen_probe_resp(struc - buflen += (3 + sizeof(struct ieee80211_eht_operation)); - if (hapd->iconf->ru_punct_bitmap) - buflen += DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE; -+ /* QCN Vendor IE for 240MHz */ -+ if (is_5ghz_freq(hapd->iface->freq)) -+ buflen += (6 + 2 + 4 + -+ sizeof(struct ieee80211_240mhz_vendor_oper)); - - } - #endif /* CONFIG_IEEE80211BE */ -@@ -809,6 +813,7 @@ static u8 * hostapd_gen_probe_resp(struc - if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) { - pos = hostapd_eid_eht_capab(hapd, pos, IEEE80211_MODE_AP); - pos = hostapd_eid_eht_operation(hapd, pos, IEEE80211_MODE_AP); -+ pos = hostapd_eid_vendor_240mhz(hapd, pos, IEEE80211_MODE_AP); - } - #endif /* CONFIG_IEEE80211BE */ - -@@ -1802,6 +1807,9 @@ int ieee802_11_build_ap_params(struct ho - tail_len += (3 + sizeof(struct ieee80211_eht_operation)); - if (hapd->iconf->ru_punct_bitmap) - tail_len += DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE; -+ if (is_5ghz_freq(hapd->iface->freq)) -+ tail_len += (6 + 2 + 4 + -+ sizeof(struct ieee80211_240mhz_vendor_oper)); - } - #endif /* CONFIG_IEEE80211BE */ - -@@ -1965,6 +1973,8 @@ int ieee802_11_build_ap_params(struct ho - IEEE80211_MODE_AP); - tailpos = hostapd_eid_eht_operation(hapd, tailpos, - IEEE80211_MODE_AP); -+ tailpos = hostapd_eid_vendor_240mhz(hapd, tailpos, -+ IEEE80211_MODE_AP); - } - #endif /* CONFIG_IEEE80211BE */ - -Index: hostapd-2021-12-13-b26f5c0f/src/ap/ieee802_11.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/ap/ieee802_11.c -+++ hostapd-2021-12-13-b26f5c0f/src/ap/ieee802_11.c -@@ -4607,6 +4607,9 @@ static int check_assoc_ies(struct hostap - elems.he_capabilities, - elems.eht_capabilities, - elems.eht_capabilities_len); -+ resp = copy_sta_eht_240mhz_capab(hapd, sta, IEEE80211_MODE_AP, -+ elems.eht_240mhz_capab, -+ elems.eht_240mhz_len); - if (resp != WLAN_STATUS_SUCCESS) - return resp; - } -@@ -4983,6 +4986,7 @@ static int add_associated_sta(struct hos - struct ieee80211_vht_capabilities vht_cap; - struct ieee80211_he_capabilities he_cap; - struct ieee80211_eht_capabilities eht_cap; -+ struct ieee80211_240mhz_vendor_oper eht_240mhz_cap; - int set = 1; - - /* -@@ -5043,6 +5047,8 @@ static int add_associated_sta(struct hos - if (sta->flags & WLAN_STA_EXT_EHT) { - hostapd_get_eht_capab(hapd, sta->eht_capab, &eht_cap, - sta->eht_capab_len); -+ hostapd_get_eht_240mhz_capab(hapd, sta->eht_240mhz_capab, &eht_240mhz_cap, -+ sta->eht_240mhz_len); - } - #endif /* CONFIG_IEEE80211BE */ - -@@ -5063,6 +5069,8 @@ static int add_associated_sta(struct hos - sta->he_6ghz_capab, - sta->flags | WLAN_STA_ASSOC, sta->qosinfo, - sta->vht_opmode, sta->p2p_ie ? 1 : 0, -+ sta->flags_ext & WLAN_STA_EXT_EHT? sta->eht_240mhz_capab : NULL, -+ sta->flags_ext & WLAN_STA_EXT_EHT? sta->eht_240mhz_len : 0, - set)) { - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_NOTICE, -@@ -5116,6 +5124,9 @@ static u16 send_assoc_resp(struct hostap - buflen += (3 + sizeof(struct ieee80211_eht_operation)); - if (hapd->iconf->ru_punct_bitmap) - buflen += DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE; -+ if (is_5ghz_freq(hapd->iface->freq)) -+ buflen += (6 + 2 + 4 + -+ sizeof(struct ieee80211_240mhz_vendor_oper)); - } - #endif /* CONFIG_IEEE80211BE */ - -@@ -5237,6 +5248,7 @@ static u16 send_assoc_resp(struct hostap - if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) { - p = hostapd_eid_eht_capab(hapd, p, IEEE80211_MODE_AP); - p = hostapd_eid_eht_operation(hapd, p, IEEE80211_MODE_AP); -+ p = hostapd_eid_vendor_240mhz(hapd, p, IEEE80211_MODE_AP); - } - #endif /* CONFIG_IEEE80211BE */ - -Index: hostapd-2021-12-13-b26f5c0f/src/ap/ieee802_11.h -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/ap/ieee802_11.h -+++ hostapd-2021-12-13-b26f5c0f/src/ap/ieee802_11.h -@@ -97,6 +97,10 @@ void hostapd_get_eht_capab(struct hostap - const struct ieee80211_eht_capabilities *src, - struct ieee80211_eht_capabilities *dest, - size_t len); -+void hostapd_get_eht_240mhz_capab(struct hostapd_data *hapd, -+ const struct ieee80211_240mhz_vendor_oper *src, -+ struct ieee80211_240mhz_vendor_oper *dest, -+ size_t len); - int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta); - u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta, - const u8 *ht_capab); -@@ -231,8 +235,13 @@ u8 * hostapd_eid_eht_capab(struct hostap - enum ieee80211_op_mode opmode); - u8 * hostapd_eid_eht_operation(struct hostapd_data *hapd, u8 *eid, - enum ieee80211_op_mode opmode); -+u8 * hostapd_eid_vendor_240mhz(struct hostapd_data *hapd, u8 *eid, -+ enum ieee80211_op_mode opmode); - u16 copy_sta_eht_capab(struct hostapd_data *hapd, struct sta_info *sta, - enum ieee80211_op_mode opmode, const u8 *he_capab, - const u8 *eht_capab, size_t eht_capab_len); -+u16 copy_sta_eht_240mhz_capab(struct hostapd_data *hapd, struct sta_info *sta, -+ enum ieee80211_op_mode opmode, -+ const u8 *eht_240mhz_capab, size_t eht_240mhz_len); - void ru_punct_update_bw(u16 bitmap, u8 pri_chan, u8 *width, u8 *seg0, u8 *seg1); - #endif /* IEEE802_11_H */ -Index: hostapd-2021-12-13-b26f5c0f/src/ap/ieee802_11_eht.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/ap/ieee802_11_eht.c -+++ hostapd-2021-12-13-b26f5c0f/src/ap/ieee802_11_eht.c -@@ -18,6 +18,7 @@ - - #include "utils/includes.h" - #include "utils/common.h" -+#include "common/qca-vendor.h" - #include "hostapd.h" - #include "ieee802_11.h" - #include "sta_info.h" -@@ -112,7 +113,7 @@ u8 * hostapd_eid_eht_capab(struct hostap - struct eht_capabilities *eht_cap; - struct ieee80211_eht_capabilities *cap; - size_t mcs_nss_len, ppe_thresh_len; -- u8 *pos = eid, *length_pos, chwidth; -+ u8 *pos = eid, *length_pos; - - mode = hapd->iface->current_mode; - if (!mode) -@@ -130,10 +131,8 @@ u8 * hostapd_eid_eht_capab(struct hostap - os_memset(cap, 0, sizeof(*cap)); - os_memcpy(cap->mac_cap, eht_cap->mac_cap, EHT_MAC_CAPAB_MAX_LEN); - os_memcpy(cap->phy_cap, eht_cap->phy_cap, EHT_PHY_CAPAB_MAX_LEN); -- chwidth = hapd->iconf->eht_oper_chwidth; - -- if (!is_6ghz_op_class(hapd->iconf->op_class) && -- (chwidth != CHANWIDTH_320MHZ)) -+ if (!is_6ghz_op_class(hapd->iconf->op_class)) - cap->phy_cap[EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_IDX] &= - ~EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_MASK; - if (!hapd->iface->conf->eht_phy_capab.su_beamformer) -@@ -289,6 +288,70 @@ u8 * hostapd_eid_eht_operation(struct ho - return pos; - } - -+u8 * hostapd_eid_vendor_240mhz(struct hostapd_data *hapd, u8 *eid, -+ enum ieee80211_op_mode opmode) -+{ -+ struct hostapd_hw_modes *mode; -+ u8 *pos = eid; -+ struct eht_capabilities *eht_cap; -+ struct ieee80211_240mhz_vendor_oper *eht_240_cap; -+ u8 ccfs0,ccfs1; -+ -+ mode = hapd->iface->current_mode; -+ if (!mode || is_6ghz_op_class(hapd->iconf->op_class) || -+ hapd->iconf->eht_oper_chwidth != CHANWIDTH_320MHZ) -+ return eid; -+ -+ eht_cap = &mode->eht_capab[opmode]; -+ -+ if (!eht_cap->eht_supported) -+ return eid; -+ ccfs0 = hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf); -+ ccfs1 = ccfs0 - 16; -+ -+ *pos++ = WLAN_EID_VENDOR_SPECIFIC; -+ *pos++ = 6 + /* Element ID, Length, OUI, OUI Type */ -+ 4 + /* QCN version Attribute size */ -+ sizeof(struct ieee80211_240mhz_vendor_oper); -+ WPA_PUT_BE24(pos, OUI_QCN); -+ pos += 3; -+ *pos++ = 1; /* QCN_OUI_TYPE */ -+ -+ /* QCN Version Attribute*/ -+ *pos++ = 1; /* QCN_ATTRIB_VERSION */ -+ *pos++ = 2; /* Length */ -+ *pos++ = 1; /* QCN_VER_ATTR_VER */ -+ *pos++ = 0; /* QCN_VER_ATTR_SUBVERSION */ -+ -+ /* QCN Attirbute */ -+ *pos++ = QCN_ATTRIB_HE_240_MHZ_SUPP; /*QCN_ATTRIB_HE_240_MHZ_SUPP*/ -+ *pos++ = sizeof(struct ieee80211_240mhz_vendor_oper); -+ -+ /* 240Mhz fields */ -+ eht_240_cap = (struct ieee80211_240mhz_vendor_oper*)pos; -+ os_memset(eht_240_cap, 0, sizeof(struct ieee80211_240mhz_vendor_oper)); -+ -+ eht_240_cap->ccfs1 = ccfs1; -+ eht_240_cap->ccfs0 = hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf); -+ eht_240_cap->ru_punct_bitmap = hapd->iconf->ru_punct_bitmap; -+ eht_240_cap->phy_cap_320mhz = eht_cap->phy_cap[EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_IDX] & -+ EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_MASK; -+ eht_240_cap->phy_cap_320mhz |= eht_cap->phy_cap[EHT_PHYCAP_BEAMFORMEE_SS_320MHZ_IDX] & -+ EHT_PHYCAP_BEAMFORMEE_SS_320MHZ_MASK; -+ eht_240_cap->phy_cap_320mhz |= (eht_cap->phy_cap[EHT_PHYCAP_NUM_SOUND_DIM_320MHZ_IDX] & -+ EHT_PHYCAP_NUM_SOUND_DIM_320MHZ_MASK) | -+ (eht_cap->phy_cap[EHT_PHYCAP_NUM_SOUND_DIM_320MHZ_IDX_1] & -+ EHT_PHYCAP_NUM_SOUND_DIM_320MHZ_MASK); -+ eht_240_cap->phy_cap_320mhz |= eht_cap->phy_cap[EHT_PHYCAP_NON_OFDMA_UL_MUMIMO_320MHZ_IDX] & -+ EHT_PHYCAP_NON_OFDMA_UL_MUMIMO_320MHZ_MASK; -+ eht_240_cap->phy_cap_320mhz |= eht_cap->phy_cap[EHT_PHYCAP_MU_CAPABILITY_IDX] & -+ EHT_PHYCAP_MU_BEAMFORMER_MASK; -+ -+ memcpy(&eht_240_cap->mcs_map_320mhz, &eht_cap->mcs, EHT_PHYCAP_MCS_NSS_LEN_160MHZ); -+ pos += sizeof(struct ieee80211_240mhz_vendor_oper); -+ -+ return pos; -+} - - static int check_valid_eht_mcs_nss(struct hostapd_data *hapd, const u8 *ap_mcs, - const u8 *sta_mcs, u8 mcs_count, u8 map_len) -@@ -426,3 +489,41 @@ void hostapd_get_eht_capab(struct hostap - - os_memcpy(dest, src, len); - } -+ -+u16 copy_sta_eht_240mhz_capab(struct hostapd_data *hapd, struct sta_info *sta, -+ enum ieee80211_op_mode opmode, -+ const u8 *eht_240mhz_capab, size_t eht_240mhz_capab_len) -+{ -+ if (!eht_240mhz_capab || !hapd->iconf->ieee80211be || -+ hapd->conf->disable_11be) { -+ os_free(sta->eht_240mhz_capab); -+ sta->eht_240mhz_capab = NULL; -+ return WLAN_STATUS_SUCCESS; -+ } -+ -+ if (!sta->eht_240mhz_capab) { -+ sta->eht_240mhz_capab = os_zalloc(eht_240mhz_capab_len); -+ if (!sta->eht_240mhz_capab) -+ return WLAN_STATUS_UNSPECIFIED_FAILURE; -+ } -+ -+ os_memcpy(sta->eht_240mhz_capab, eht_240mhz_capab, eht_240mhz_capab_len); -+ sta->eht_240mhz_len = eht_240mhz_capab_len; -+ -+ return WLAN_STATUS_SUCCESS; -+} -+ -+ -+void hostapd_get_eht_240mhz_capab(struct hostapd_data *hapd, -+ const struct ieee80211_240mhz_vendor_oper *src, -+ struct ieee80211_240mhz_vendor_oper *dest, -+ size_t len) -+{ -+ if (!src || !dest) -+ return; -+ -+ if (len > sizeof(*dest)) -+ len = sizeof(*dest); -+ -+ os_memcpy(dest, src, len); -+} -Index: hostapd-2021-12-13-b26f5c0f/src/ap/sta_info.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/ap/sta_info.c -+++ hostapd-2021-12-13-b26f5c0f/src/ap/sta_info.c -@@ -359,6 +359,7 @@ void ap_free_sta(struct hostapd_data *ha - os_free(sta->he_capab); - os_free(sta->he_6ghz_capab); - os_free(sta->eht_capab); -+ os_free(sta->eht_240mhz_capab); - hostapd_free_psk_list(sta->psk); - os_free(sta->identity); - os_free(sta->radius_cui); -@@ -1579,7 +1580,7 @@ int ap_sta_re_add(struct hostapd_data *h - sta->supported_rates, - sta->supported_rates_len, - 0, NULL, NULL, NULL, NULL, 0, 0, NULL, -- sta->flags, 0, 0, 0, 0)) { -+ sta->flags, 0, 0, 0, NULL, 0, 0)) { - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_NOTICE, -Index: hostapd-2021-12-13-b26f5c0f/src/ap/sta_info.h -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/ap/sta_info.h -+++ hostapd-2021-12-13-b26f5c0f/src/ap/sta_info.h -@@ -340,6 +340,8 @@ struct sta_info { - struct pasn_data *pasn; - #endif /* CONFIG_PASN */ - int signal_mgmt; -+ struct ieee80211_240mhz_vendor_oper *eht_240mhz_capab; -+ size_t eht_240mhz_len; - }; - - -Index: hostapd-2021-12-13-b26f5c0f/src/common/ieee802_11_common.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/common/ieee802_11_common.c -+++ hostapd-2021-12-13-b26f5c0f/src/common/ieee802_11_common.c -@@ -22,6 +22,7 @@ static int ieee802_11_parse_vendor_speci - int show_errors) - { - unsigned int oui; -+ u8 len, updated_len; - - /* first 3 bytes in vendor specific information element are the IEEE - * OUI of the vendor. The following byte is used a vendor specific -@@ -187,6 +188,36 @@ static int ieee802_11_parse_vendor_speci - } - break; - -+ case OUI_QCN: -+ len = updated_len = 0; -+ if (pos[3] == 0x1 ) { /* QCN_OUI_TYPE */ -+ updated_len += 4; -+ pos = pos + 4; /* Move OUI(3) and OUI_TYPE (1) */ -+ while (elen > updated_len) { -+ switch(pos[0]) { -+ case QCN_ATTRIB_HE_240_MHZ_SUPP: -+ elems->eht_240mhz_len = pos[1]; -+ if (elems->eht_240mhz_len > QCN_HE_240_MHZ_MAX_ELEM_LEN) { -+ wpa_printf(MSG_DEBUG, "Length %d for 240MHz Vendor IE exceeded", -+ elems->eht_240mhz_len); -+ elems->eht_240mhz_len = 0; -+ continue; -+ } -+ len = elems->eht_240mhz_len; -+ pos = pos + 2; -+ elems->eht_240mhz_capab = pos; -+ pos += len; -+ updated_len += len + 2; -+ break; -+ default: -+ len = pos[1]; -+ updated_len += len + 2; -+ pos += len + 2; -+ break; -+ } -+ } -+ } -+ break; - default: - wpa_printf(MSG_EXCESSIVE, "unknown vendor specific " - "information element ignored (vendor OUI " -@@ -427,6 +458,7 @@ ParseRes ieee802_11_parse_elems(const u8 - elems->ext_supp_rates_len = elen; - break; - case WLAN_EID_VENDOR_SPECIFIC: -+ - if (ieee802_11_parse_vendor_specific(pos, elen, - elems, - show_errors)) -Index: hostapd-2021-12-13-b26f5c0f/src/common/ieee802_11_common.h -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/common/ieee802_11_common.h -+++ hostapd-2021-12-13-b26f5c0f/src/common/ieee802_11_common.h -@@ -121,6 +121,7 @@ struct ieee802_11_elems { - const u8 *mbssid_known_bss; - const u8 *eht_capabilities; - const u8 *eht_operation; -+ const u8 *eht_240mhz_capab; - - u8 ssid_len; - u8 supp_rates_len; -@@ -178,6 +179,7 @@ struct ieee802_11_elems { - u8 mbssid_known_bss_len; - u8 eht_capabilities_len; - u8 eht_operation_len; -+ u8 eht_240mhz_len; - - struct mb_ies_info mb_ies; - struct frag_ies_info frag_ies; -Index: hostapd-2021-12-13-b26f5c0f/src/common/ieee802_11_defs.h -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/common/ieee802_11_defs.h -+++ hostapd-2021-12-13-b26f5c0f/src/common/ieee802_11_defs.h -@@ -2494,6 +2494,13 @@ struct ieee80211_eht_operation { - le16 disabled_subchannel_bitmap[0]; - } STRUCT_PACKED; - -+struct ieee80211_240mhz_vendor_oper { -+ u8 ccfs1; -+ u8 ccfs0; -+ u16 ru_punct_bitmap; -+ u16 phy_cap_320mhz; -+ u8 mcs_map_320mhz[3]; -+} STRUCT_PACKED; - - #define EHT_OPERATION_CHANNEL_WIDTH_20MHZ 0 - #define EHT_OPERATION_CHANNEL_WIDTH_40MHZ 1 -@@ -2526,6 +2533,19 @@ struct ieee80211_eht_operation { - EHT_PHYCAP_MU_BEAMFORMER_160MHZ | \ - EHT_PHYCAP_MU_BEAMFORMER_320MHZ) - -+#define EHT_PHYCAP_BEAMFORMEE_SS_320MHZ_IDX 3 -+#define EHT_PHYCAP_BEAMFORMEE_SS_320MHZ_MASK ((u8) (BIT(0) | BIT(1) | \ -+ BIT(2) | BIT(3))) -+ -+#define EHT_PHYCAP_NUM_SOUND_DIM_320MHZ_IDX 1 -+#define EHT_PHYCAP_NUM_SOUND_DIM_320MHZ_MASK ((u8) (BIT(0) | BIT(2) | \ -+ BIT(3))) -+#define EHT_PHYCAP_NUM_SOUND_DIM_320MHZ_IDX_1 2 -+#define EHT_PHYCAP_NUM_SOUND_DIM_320MHZ_MASK_1 ((u8) (BIT(0)) -+ -+#define EHT_PHYCAP_NON_OFDMA_UL_MUMIMO_320MHZ_IDX 6 -+#define EHT_PHYCAP_NON_OFDMA_UL_MUMIMO_320MHZ_MASK ((u8) BIT(3)) -+ - /* - * IEEE P802.11be/D1.0, May 2021, - * section 9.4.2.295c.4 Supported EHT-MCS And NSS Set field -Index: hostapd-2021-12-13-b26f5c0f/src/common/qca-vendor.h -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/common/qca-vendor.h -+++ hostapd-2021-12-13-b26f5c0f/src/common/qca-vendor.h -@@ -18,6 +18,10 @@ - */ - - #define OUI_QCA 0x001374 -+#define OUI_QCN 0x8cfdf0 -+ -+#define QCN_ATTRIB_HE_240_MHZ_SUPP 0X0B -+#define QCN_HE_240_MHZ_MAX_ELEM_LEN 9 - - #ifndef BIT - #define BIT(x) (1U << (x)) -Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver.h -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/drivers/driver.h -+++ hostapd-2021-12-13-b26f5c0f/src/drivers/driver.h -@@ -2398,6 +2398,8 @@ struct hostapd_sta_add_params { - size_t supp_oper_classes_len; - int support_p2p_ps; - u16 ru_punct_bitmap; -+ const struct ieee80211_240mhz_vendor_oper *eht_240mhz_capab; -+ size_t eht_240mhz_len; - }; - - struct mac_address { -Index: hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211.c -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/drivers/driver_nl80211.c -+++ hostapd-2021-12-13-b26f5c0f/src/drivers/driver_nl80211.c -@@ -5285,6 +5285,14 @@ static int wpa_driver_nl80211_sta_add(vo - goto fail; - } - -+ if (params->eht_240mhz_capab) { -+ wpa_hexdump(MSG_DEBUG, " * 240mhz_capab", -+ (u8 *)params->eht_240mhz_capab, params->eht_240mhz_len); -+ if (nla_put(msg, NL80211_ATTR_EHT_240MHZ_CAPABILITY, -+ params->eht_240mhz_len, params->eht_240mhz_capab)) -+ goto fail; -+ } -+ - if (params->ext_capab) { - wpa_hexdump(MSG_DEBUG, " * ext_capab", - params->ext_capab, params->ext_capab_len); -Index: hostapd-2021-12-13-b26f5c0f/src/drivers/nl80211_copy.h -=================================================================== ---- hostapd-2021-12-13-b26f5c0f.orig/src/drivers/nl80211_copy.h -+++ hostapd-2021-12-13-b26f5c0f/src/drivers/nl80211_copy.h -@@ -3137,6 +3137,7 @@ enum nl80211_attrs { - NL80211_ATTR_RU_PUNCT_BITMAP, - - NL80211_ATTR_AP_PS, -+ NL80211_ATTR_EHT_240MHZ_CAPABILITY, - /* add attributes here, update the policy in nl80211.c */ - - __NL80211_ATTR_AFTER_LAST, diff --git a/feeds/ipq95xx/hostapd/patches/q02-51-hostapd-Fix-WDS-Repeater-assoc-fail-on-6G-with-160MH.patch b/feeds/ipq95xx/hostapd/patches/q02-51-hostapd-Fix-WDS-Repeater-assoc-fail-on-6G-with-160MH.patch deleted file mode 100644 index a2030b70b..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-51-hostapd-Fix-WDS-Repeater-assoc-fail-on-6G-with-160MH.patch +++ /dev/null @@ -1,47 +0,0 @@ -From abec20dcfc7e4f38c6b9a90d95914d11a27d114c Mon Sep 17 00:00:00 2001 -From: Sivashankari Madhavan -Date: Sat, 26 Nov 2022 11:26:37 +0530 -Subject: [PATCH] hostapd: Fix WDS Repeater assoc fail on 6G with 160MHz - -While trying to connect the STA with WDS AP, filling the chandef info -in the driver. In the Problematic case, receiving the EHT160 center -frequency is invalid. Due to this chandef validation getting fail and -returns a failure message. - -[ 6340.667455] wlan1: authenticate with 00:03:7f:01:58:33 -[ 6340.667502] wlan1: HE 6GHz operation resulted in invalid chandef: 6195 MHz/5/0 MHz/0 MHz -[ 6340.671605] wlan1: Rejecting non-HE 6/7 GHz connection -[ 6343.937592] wlan1: authenticate with 00:03:7f:01:58:33 - -From the analysis, didn't update the EHT160 center frequency information -in hostapd. - -Fix it by updating the EHT160 center frequency information. - -Signed-off-by: Sivashankari Madhavan ---- - src/ap/ieee802_11_eht.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/src/ap/ieee802_11_eht.c b/src/ap/ieee802_11_eht.c -index e208352..ac88c2a 100644 ---- a/src/ap/ieee802_11_eht.c -+++ b/src/ap/ieee802_11_eht.c -@@ -243,6 +243,14 @@ u8 * hostapd_eid_eht_operation(struct hostapd_data *hapd, u8 *eid, - break; - case CHANWIDTH_160MHZ: - oper->width = EHT_OPERATION_CHANNEL_WIDTH_160MHZ; -+ if (!oper->ccfs1) { -+ /* CCFS0 points to center channel frequency in config */ -+ oper->ccfs1 = oper->ccfs0; -+ if (hapd->iconf->channel < oper->ccfs0) -+ oper->ccfs0 = oper->ccfs1 - 8; -+ else -+ oper->ccfs0 = oper->ccfs1 + 8; -+ } - if (hapd->iconf->ru_punct_bitmap && - hapd->iface->ru_punct_supp_bw == CHANWIDTH_320MHZ) { - hapd->iconf->ru_punct_bitmap = 0; --- -2.17.1 - diff --git a/feeds/ipq95xx/hostapd/patches/q02-51-hostapd-Set-duplicate-beacon-bit-in-HE-oper-IE.patch b/feeds/ipq95xx/hostapd/patches/q02-51-hostapd-Set-duplicate-beacon-bit-in-HE-oper-IE.patch deleted file mode 100644 index e0a687f29..000000000 --- a/feeds/ipq95xx/hostapd/patches/q02-51-hostapd-Set-duplicate-beacon-bit-in-HE-oper-IE.patch +++ /dev/null @@ -1,65 +0,0 @@ -From b14445ec68225d41ee4176ec0ed9f22f9e627498 Mon Sep 17 00:00:00 2001 -From: Ramya Gnanasekar -Date: Tue, 22 Nov 2022 13:26:22 +0530 -Subject: [PATCH] hostapd: Set duplicate beacon bit in HE oper IE - -When APUT operates in non-psc channels, duplicate beacons -will be sent in psc channels. Hence duplicate beacon field -to be updated in the same scenario. - -Signed-off-by: Ramya Gnanasekar - -Index: b/src/ap/ieee802_11_he.c -=================================================================== ---- a/src/ap/ieee802_11_he.c 2022-11-23 09:22:12.722659415 +0530 -+++ b/src/ap/ieee802_11_he.c 2022-11-23 09:23:10.334202383 +0530 -@@ -168,12 +168,26 @@ u8 * hostapd_eid_he_capab(struct hostapd - return pos; - } - -+bool is_psc_channel(int channel) -+{ -+ int psc_chan[] = {37, 53, 69, 85, 101, 117, -+ 133, 149, 165, 181, 197, 213} ; -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(psc_chan); i++) { -+ if (psc_chan[i] == channel) { -+ return true; -+ break; -+ } -+ } -+ return false; -+} - - u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid) - { - struct ieee80211_he_operation *oper; - u8 *pos = eid; -- int oper_size = 6; -+ int oper_size = 6, he_control; - u32 params = 0; - - if (!hapd->iface->current_mode) -@@ -261,13 +275,19 @@ u8 * hostapd_eid_he_operation(struct hos - u8 ap_type = hostapd_get_he_6ghz_reg_pwr_type(hapd->iconf); - - if (seg1) -- *pos++ = 3 | (IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO & -+ he_control = 3 | (IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO & - (ap_type << IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO_LSB)); - else -- *pos++ = center_idx_to_bw_6ghz(seg0) | -+ he_control = center_idx_to_bw_6ghz(seg0) | - (IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO & - (ap_type << IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO_LSB)); - -+ if (center_idx_to_bw_6ghz(seg0) && -+ !is_psc_channel(hapd->iconf->channel)) -+ he_control |= HE_6GHZ_OPER_INFO_CTRL_DUP_BEACON; -+ -+ *pos++ = he_control; -+ - /* Channel Center Freq Seg0/Seg1 */ - if (hapd->iconf->he_oper_chwidth == 2) { - /* diff --git a/feeds/ipq95xx/hostapd/src/hostapd/radius.c b/feeds/ipq95xx/hostapd/src/hostapd/radius.c new file mode 100644 index 000000000..362a22c27 --- /dev/null +++ b/feeds/ipq95xx/hostapd/src/hostapd/radius.c @@ -0,0 +1,715 @@ +#include "utils/includes.h" +#include "utils/common.h" +#include "utils/eloop.h" +#include "crypto/crypto.h" +#include "crypto/tls.h" + +#include "ap/ap_config.h" +#include "eap_server/eap.h" +#include "radius/radius.h" +#include "radius/radius_server.h" +#include "eap_register.h" + +#include +#include +#include +#include +#include + +#include +#include + +#define VENDOR_ID_WISPR 14122 +#define VENDOR_ATTR_SIZE 6 + +struct radius_parse_attr_data { + unsigned int vendor; + u8 type; + int size; + char format; + const char *data; +}; + +struct radius_parse_attr_state { + struct hostapd_radius_attr *prev; + struct hostapd_radius_attr *attr; + struct wpabuf *buf; + void *attrdata; +}; + +struct radius_user_state { + struct avl_node node; + struct eap_user data; +}; + +struct radius_user_data { + struct kvlist users; + struct avl_tree user_state; + struct blob_attr *wildcard; +}; + +struct radius_state { + struct radius_server_data *radius; + struct eap_config eap; + + struct radius_user_data phase1, phase2; + const char *user_file; + time_t user_file_ts; + + int n_attrs; + struct hostapd_radius_attr *attrs; +}; + +struct radius_config { + struct tls_connection_params tls; + struct radius_server_conf radius; +}; + +enum { + USER_ATTR_PASSWORD, + USER_ATTR_HASH, + USER_ATTR_SALT, + USER_ATTR_METHODS, + USER_ATTR_RADIUS, + USER_ATTR_VLAN, + USER_ATTR_MAX_RATE_UP, + USER_ATTR_MAX_RATE_DOWN, + __USER_ATTR_MAX +}; + +static void radius_tls_event(void *ctx, enum tls_event ev, + union tls_event_data *data) +{ + switch (ev) { + case TLS_CERT_CHAIN_SUCCESS: + wpa_printf(MSG_DEBUG, "radius: remote certificate verification success"); + break; + case TLS_CERT_CHAIN_FAILURE: + wpa_printf(MSG_INFO, "radius: certificate chain failure: reason=%d depth=%d subject='%s' err='%s'", + data->cert_fail.reason, + data->cert_fail.depth, + data->cert_fail.subject, + data->cert_fail.reason_txt); + break; + case TLS_PEER_CERTIFICATE: + wpa_printf(MSG_DEBUG, "radius: peer certificate: depth=%d serial_num=%s subject=%s", + data->peer_cert.depth, + data->peer_cert.serial_num ? data->peer_cert.serial_num : "N/A", + data->peer_cert.subject); + break; + case TLS_ALERT: + if (data->alert.is_local) + wpa_printf(MSG_DEBUG, "radius: local TLS alert: %s", + data->alert.description); + else + wpa_printf(MSG_DEBUG, "radius: remote TLS alert: %s", + data->alert.description); + break; + case TLS_UNSAFE_RENEGOTIATION_DISABLED: + /* Not applicable to TLS server */ + break; + } +} + +static void radius_userdata_init(struct radius_user_data *u) +{ + kvlist_init(&u->users, kvlist_blob_len); + avl_init(&u->user_state, avl_strcmp, false, NULL); +} + +static void radius_userdata_free(struct radius_user_data *u) +{ + struct radius_user_state *s, *tmp; + + kvlist_free(&u->users); + free(u->wildcard); + u->wildcard = NULL; + avl_remove_all_elements(&u->user_state, s, node, tmp) + free(s); +} + +static void +radius_userdata_load(struct radius_user_data *u, struct blob_attr *data) +{ + enum { + USERSTATE_USERS, + USERSTATE_WILDCARD, + __USERSTATE_MAX, + }; + static const struct blobmsg_policy policy[__USERSTATE_MAX] = { + [USERSTATE_USERS] = { "users", BLOBMSG_TYPE_TABLE }, + [USERSTATE_WILDCARD] = { "wildcard", BLOBMSG_TYPE_ARRAY }, + }; + struct blob_attr *tb[__USERSTATE_MAX], *cur; + int rem; + + if (!data) + return; + + blobmsg_parse(policy, __USERSTATE_MAX, tb, blobmsg_data(data), blobmsg_len(data)); + + blobmsg_for_each_attr(cur, tb[USERSTATE_USERS], rem) + kvlist_set(&u->users, blobmsg_name(cur), cur); + + if (tb[USERSTATE_WILDCARD]) + u->wildcard = blob_memdup(tb[USERSTATE_WILDCARD]); +} + +static void +load_userfile(struct radius_state *s) +{ + enum { + USERDATA_PHASE1, + USERDATA_PHASE2, + __USERDATA_MAX + }; + static const struct blobmsg_policy policy[__USERDATA_MAX] = { + [USERDATA_PHASE1] = { "phase1", BLOBMSG_TYPE_TABLE }, + [USERDATA_PHASE2] = { "phase2", BLOBMSG_TYPE_TABLE }, + }; + struct blob_attr *tb[__USERDATA_MAX], *cur; + static struct blob_buf b; + struct stat st; + int rem; + + if (stat(s->user_file, &st)) + return; + + if (s->user_file_ts == st.st_mtime) + return; + + s->user_file_ts = st.st_mtime; + radius_userdata_free(&s->phase1); + radius_userdata_free(&s->phase2); + + blob_buf_init(&b, 0); + blobmsg_add_json_from_file(&b, s->user_file); + blobmsg_parse(policy, __USERDATA_MAX, tb, blob_data(b.head), blob_len(b.head)); + radius_userdata_load(&s->phase1, tb[USERDATA_PHASE1]); + radius_userdata_load(&s->phase2, tb[USERDATA_PHASE2]); + + blob_buf_free(&b); +} + +static struct blob_attr * +radius_user_get(struct radius_user_data *s, const char *name) +{ + struct blob_attr *cur; + int rem; + + cur = kvlist_get(&s->users, name); + if (cur) + return cur; + + blobmsg_for_each_attr(cur, s->wildcard, rem) { + static const struct blobmsg_policy policy = { + "name", BLOBMSG_TYPE_STRING + }; + struct blob_attr *pattern; + + if (blobmsg_type(cur) != BLOBMSG_TYPE_TABLE) + continue; + + blobmsg_parse(&policy, 1, &pattern, blobmsg_data(cur), blobmsg_len(cur)); + if (!name) + continue; + + if (!fnmatch(blobmsg_get_string(pattern), name, 0)) + return cur; + } + + return NULL; +} + +static struct radius_parse_attr_data * +radius_parse_attr(struct blob_attr *attr) +{ + static const struct blobmsg_policy policy[4] = { + { .type = BLOBMSG_TYPE_INT32 }, + { .type = BLOBMSG_TYPE_INT32 }, + { .type = BLOBMSG_TYPE_STRING }, + { .type = BLOBMSG_TYPE_STRING }, + }; + static struct radius_parse_attr_data data; + struct blob_attr *tb[4]; + const char *format; + + blobmsg_parse_array(policy, ARRAY_SIZE(policy), tb, blobmsg_data(attr), blobmsg_len(attr)); + + if (!tb[0] || !tb[1] || !tb[2] || !tb[3]) + return NULL; + + format = blobmsg_get_string(tb[2]); + if (strlen(format) != 1) + return NULL; + + data.vendor = blobmsg_get_u32(tb[0]); + data.type = blobmsg_get_u32(tb[1]); + data.format = format[0]; + data.data = blobmsg_get_string(tb[3]); + data.size = strlen(data.data); + + switch (data.format) { + case 's': + break; + case 'x': + if (data.size & 1) + return NULL; + data.size /= 2; + break; + case 'd': + data.size = 4; + break; + default: + return NULL; + } + + return &data; +} + +static void +radius_count_attrs(struct blob_attr **tb, int *n_attr, size_t *attr_size) +{ + struct blob_attr *data = tb[USER_ATTR_RADIUS]; + struct blob_attr *cur; + int rem; + + blobmsg_for_each_attr(cur, data, rem) { + struct radius_parse_attr_data *data; + size_t prev = *attr_size; + + data = radius_parse_attr(cur); + if (!data) + continue; + + *attr_size += data->size; + if (data->vendor) + *attr_size += VENDOR_ATTR_SIZE; + + (*n_attr)++; + } + + *n_attr += !!tb[USER_ATTR_VLAN] * 3 + + !!tb[USER_ATTR_MAX_RATE_UP] + + !!tb[USER_ATTR_MAX_RATE_DOWN]; + *attr_size += !!tb[USER_ATTR_VLAN] * (4 + 4 + 5) + + !!tb[USER_ATTR_MAX_RATE_UP] * (4 + VENDOR_ATTR_SIZE) + + !!tb[USER_ATTR_MAX_RATE_DOWN] * (4 + VENDOR_ATTR_SIZE); +} + +static void * +radius_add_attr(struct radius_parse_attr_state *state, + u32 vendor, u8 type, u8 len) +{ + struct hostapd_radius_attr *attr; + struct wpabuf *buf; + void *val; + + val = state->attrdata; + + buf = state->buf++; + buf->buf = val; + + attr = state->attr++; + attr->val = buf; + attr->type = type; + + if (state->prev) + state->prev->next = attr; + state->prev = attr; + + if (vendor) { + u8 *vendor_hdr = val + 4; + + WPA_PUT_BE32(val, vendor); + vendor_hdr[0] = type; + vendor_hdr[1] = len + 2; + + len += VENDOR_ATTR_SIZE; + val += VENDOR_ATTR_SIZE; + attr->type = RADIUS_ATTR_VENDOR_SPECIFIC; + } + + buf->size = buf->used = len; + state->attrdata += len; + + return val; +} + +static void +radius_parse_attrs(struct blob_attr **tb, struct radius_parse_attr_state *state) +{ + struct blob_attr *data = tb[USER_ATTR_RADIUS]; + struct hostapd_radius_attr *prev = NULL; + struct blob_attr *cur; + int len, rem; + void *val; + + if ((cur = tb[USER_ATTR_VLAN]) != NULL && blobmsg_get_u32(cur) < 4096) { + char buf[5]; + + val = radius_add_attr(state, 0, RADIUS_ATTR_TUNNEL_TYPE, 4); + WPA_PUT_BE32(val, RADIUS_TUNNEL_TYPE_VLAN); + + val = radius_add_attr(state, 0, RADIUS_ATTR_TUNNEL_MEDIUM_TYPE, 4); + WPA_PUT_BE32(val, RADIUS_TUNNEL_MEDIUM_TYPE_802); + + len = snprintf(buf, sizeof(buf), "%d", blobmsg_get_u32(cur)); + val = radius_add_attr(state, 0, RADIUS_ATTR_TUNNEL_PRIVATE_GROUP_ID, len); + memcpy(val, buf, len); + } + + if ((cur = tb[USER_ATTR_MAX_RATE_UP]) != NULL) { + val = radius_add_attr(state, VENDOR_ID_WISPR, 7, 4); + WPA_PUT_BE32(val, blobmsg_get_u32(cur)); + } + + if ((cur = tb[USER_ATTR_MAX_RATE_DOWN]) != NULL) { + val = radius_add_attr(state, VENDOR_ID_WISPR, 8, 4); + WPA_PUT_BE32(val, blobmsg_get_u32(cur)); + } + + blobmsg_for_each_attr(cur, data, rem) { + struct radius_parse_attr_data *data; + void *val; + int size; + + data = radius_parse_attr(cur); + if (!data) + continue; + + val = radius_add_attr(state, data->vendor, data->type, data->size); + switch (data->format) { + case 's': + memcpy(val, data->data, data->size); + break; + case 'x': + hexstr2bin(data->data, val, data->size); + break; + case 'd': + WPA_PUT_BE32(val, atoi(data->data)); + break; + } + } +} + +static void +radius_user_parse_methods(struct eap_user *eap, struct blob_attr *data) +{ + struct blob_attr *cur; + int rem, n = 0; + + if (!data) + return; + + blobmsg_for_each_attr(cur, data, rem) { + const char *method; + + if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING) + continue; + + if (n == EAP_MAX_METHODS) + break; + + method = blobmsg_get_string(cur); + eap->methods[n].method = eap_server_get_type(method, &eap->methods[n].vendor); + if (eap->methods[n].vendor == EAP_VENDOR_IETF && + eap->methods[n].method == EAP_TYPE_NONE) { + if (!strcmp(method, "TTLS-PAP")) { + eap->ttls_auth |= EAP_TTLS_AUTH_PAP; + continue; + } + if (!strcmp(method, "TTLS-CHAP")) { + eap->ttls_auth |= EAP_TTLS_AUTH_CHAP; + continue; + } + if (!strcmp(method, "TTLS-MSCHAP")) { + eap->ttls_auth |= EAP_TTLS_AUTH_MSCHAP; + continue; + } + if (!strcmp(method, "TTLS-MSCHAPV2")) { + eap->ttls_auth |= EAP_TTLS_AUTH_MSCHAPV2; + continue; + } + } + n++; + } +} + +static struct eap_user * +radius_user_get_state(struct radius_user_data *u, struct blob_attr *data, + const char *id) +{ + static const struct blobmsg_policy policy[__USER_ATTR_MAX] = { + [USER_ATTR_PASSWORD] = { "password", BLOBMSG_TYPE_STRING }, + [USER_ATTR_HASH] = { "hash", BLOBMSG_TYPE_STRING }, + [USER_ATTR_SALT] = { "salt", BLOBMSG_TYPE_STRING }, + [USER_ATTR_METHODS] = { "methods", BLOBMSG_TYPE_ARRAY }, + [USER_ATTR_RADIUS] = { "radius", BLOBMSG_TYPE_ARRAY }, + [USER_ATTR_VLAN] = { "vlan-id", BLOBMSG_TYPE_INT32 }, + [USER_ATTR_MAX_RATE_UP] = { "max-rate-up", BLOBMSG_TYPE_INT32 }, + [USER_ATTR_MAX_RATE_DOWN] = { "max-rate-down", BLOBMSG_TYPE_INT32 }, + }; + struct blob_attr *tb[__USER_ATTR_MAX], *cur; + char *password_buf, *salt_buf, *name_buf; + struct radius_parse_attr_state astate = {}; + struct hostapd_radius_attr *attr; + struct radius_user_state *state; + int pw_len = 0, salt_len = 0; + struct eap_user *eap; + struct wpabuf *val; + size_t attrsize = 0; + void *attrdata; + int n_attr = 0; + + state = avl_find_element(&u->user_state, id, state, node); + if (state) + return &state->data; + + blobmsg_parse(policy, __USER_ATTR_MAX, tb, blobmsg_data(data), blobmsg_len(data)); + + if ((cur = tb[USER_ATTR_SALT]) != NULL) + salt_len = strlen(blobmsg_get_string(cur)) / 2; + if ((cur = tb[USER_ATTR_HASH]) != NULL) + pw_len = strlen(blobmsg_get_string(cur)) / 2; + else if ((cur = tb[USER_ATTR_PASSWORD]) != NULL) + pw_len = blobmsg_len(cur) - 1; + radius_count_attrs(tb, &n_attr, &attrsize); + + state = calloc_a(sizeof(*state), &name_buf, strlen(id) + 1, + &password_buf, pw_len, + &salt_buf, salt_len, + &astate.attr, n_attr * sizeof(*astate.attr), + &astate.buf, n_attr * sizeof(*astate.buf), + &astate.attrdata, attrsize); + eap = &state->data; + eap->salt = salt_len ? salt_buf : NULL; + eap->salt_len = salt_len; + eap->password = pw_len ? password_buf : NULL; + eap->password_len = pw_len; + eap->force_version = -1; + + if ((cur = tb[USER_ATTR_SALT]) != NULL) + hexstr2bin(blobmsg_get_string(cur), salt_buf, salt_len); + if ((cur = tb[USER_ATTR_PASSWORD]) != NULL) + memcpy(password_buf, blobmsg_get_string(cur), pw_len); + else if ((cur = tb[USER_ATTR_HASH]) != NULL) { + hexstr2bin(blobmsg_get_string(cur), password_buf, pw_len); + eap->password_hash = 1; + } + radius_user_parse_methods(eap, tb[USER_ATTR_METHODS]); + + if (n_attr > 0) { + cur = tb[USER_ATTR_RADIUS]; + eap->accept_attr = astate.attr; + radius_parse_attrs(tb, &astate); + } + + state->node.key = strcpy(name_buf, id); + avl_insert(&u->user_state, &state->node); + + return &state->data; + +free: + free(state); + return NULL; +} + +static int radius_get_eap_user(void *ctx, const u8 *identity, + size_t identity_len, int phase2, + struct eap_user *user) +{ + struct radius_state *s = ctx; + struct radius_user_data *u = phase2 ? &s->phase2 : &s->phase1; + struct blob_attr *entry; + struct eap_user *data; + char *id; + + if (identity_len > 512) + return -1; + + load_userfile(s); + + id = alloca(identity_len + 1); + memcpy(id, identity, identity_len); + id[identity_len] = 0; + + entry = radius_user_get(u, id); + if (!entry) + return -1; + + if (!user) + return 0; + + data = radius_user_get_state(u, entry, id); + if (!data) + return -1; + + *user = *data; + if (user->password_len > 0) + user->password = os_memdup(user->password, user->password_len); + if (user->salt_len > 0) + user->salt = os_memdup(user->salt, user->salt_len); + user->phase2 = phase2; + + return 0; +} + +static int radius_setup(struct radius_state *s, struct radius_config *c) +{ + struct eap_config *eap = &s->eap; + struct tls_config conf = { + .event_cb = radius_tls_event, + .tls_flags = TLS_CONN_DISABLE_TLSv1_3, + .cb_ctx = s, + }; + + eap->eap_server = 1; + eap->max_auth_rounds = 100; + eap->max_auth_rounds_short = 50; + eap->ssl_ctx = tls_init(&conf); + if (!eap->ssl_ctx) { + wpa_printf(MSG_INFO, "TLS init failed\n"); + return 1; + } + + if (tls_global_set_params(eap->ssl_ctx, &c->tls)) { + wpa_printf(MSG_INFO, "failed to set TLS parameters\n"); + return 1; + } + + c->radius.eap_cfg = eap; + c->radius.conf_ctx = s; + c->radius.get_eap_user = radius_get_eap_user; + s->radius = radius_server_init(&c->radius); + if (!s->radius) { + wpa_printf(MSG_INFO, "failed to initialize radius server\n"); + return 1; + } + + return 0; +} + +static int radius_init(struct radius_state *s) +{ + memset(s, 0, sizeof(*s)); + radius_userdata_init(&s->phase1); + radius_userdata_init(&s->phase2); +} + +static void radius_deinit(struct radius_state *s) +{ + if (s->radius) + radius_server_deinit(s->radius); + + if (s->eap.ssl_ctx) + tls_deinit(s->eap.ssl_ctx); + + radius_userdata_free(&s->phase1); + radius_userdata_free(&s->phase2); +} + +static int usage(const char *progname) +{ + fprintf(stderr, "Usage: %s \n", + progname); +} + +int radius_main(int argc, char **argv) +{ + static struct radius_state state = {}; + static struct radius_config config = {}; + const char *progname = argv[0]; + int ret = 0; + int ch; + + wpa_debug_setup_stdout(); + wpa_debug_level = 0; + + if (eloop_init()) { + wpa_printf(MSG_ERROR, "Failed to initialize event loop"); + return 1; + } + + eap_server_register_methods(); + radius_init(&state); + + while ((ch = getopt(argc, argv, "6C:c:d:i:k:K:p:P:s:u:")) != -1) { + switch (ch) { + case '6': + config.radius.ipv6 = 1; + break; + case 'C': + config.tls.ca_cert = optarg; + break; + case 'c': + if (config.tls.client_cert2) + return usage(progname); + + if (config.tls.client_cert) + config.tls.client_cert2 = optarg; + else + config.tls.client_cert = optarg; + break; + case 'd': + config.tls.dh_file = optarg; + break; + case 'i': + state.eap.server_id = optarg; + state.eap.server_id_len = strlen(optarg); + break; + case 'k': + if (config.tls.private_key2) + return usage(progname); + + if (config.tls.private_key) + config.tls.private_key2 = optarg; + else + config.tls.private_key = optarg; + break; + case 'K': + if (config.tls.private_key_passwd2) + return usage(progname); + + if (config.tls.private_key_passwd) + config.tls.private_key_passwd2 = optarg; + else + config.tls.private_key_passwd = optarg; + break; + case 'p': + config.radius.auth_port = atoi(optarg); + break; + case 'P': + config.radius.acct_port = atoi(optarg); + break; + case 's': + config.radius.client_file = optarg; + break; + case 'u': + state.user_file = optarg; + break; + default: + return usage(progname); + } + } + + if (!config.tls.client_cert || !config.tls.private_key || + !config.radius.client_file || !state.eap.server_id || + !state.user_file) { + wpa_printf(MSG_INFO, "missing options\n"); + goto out; + } + + ret = radius_setup(&state, &config); + if (ret) + goto out; + + load_userfile(&state); + eloop_run(); + +out: + radius_deinit(&state); + os_program_deinit(); + + return ret; +} diff --git a/feeds/ipq95xx/hostapd/src/src/ap/ubus.c b/feeds/ipq95xx/hostapd/src/src/ap/ubus.c index 3ef443d43..ae6209883 100644 --- a/feeds/ipq95xx/hostapd/src/src/ap/ubus.c +++ b/feeds/ipq95xx/hostapd/src/src/ap/ubus.c @@ -153,7 +153,7 @@ hostapd_bss_ban_client(struct hostapd_data *hapd, u8 *addr, int time) } } - eloop_register_timeout(time, 0, hostapd_bss_del_ban, ban, hapd); + eloop_register_timeout(0, time * 1000, hostapd_bss_del_ban, ban, hapd); } static int @@ -275,10 +275,24 @@ hostapd_bss_get_clients(struct ubus_context *ctx, struct ubus_object *obj, blobmsg_add_u8(&b, sta_flags[i].name, !!(sta->flags & sta_flags[i].flag)); +#ifdef CONFIG_MBO + blobmsg_add_u8(&b, "mbo", !!(sta->cell_capa)); +#endif + r = blobmsg_open_array(&b, "rrm"); for (i = 0; i < ARRAY_SIZE(sta->rrm_enabled_capa); i++) blobmsg_add_u32(&b, "", sta->rrm_enabled_capa[i]); blobmsg_close_array(&b, r); + + r = blobmsg_open_array(&b, "extended_capabilities"); + /* Check if client advertises extended capabilities */ + if (sta->ext_capability && sta->ext_capability[0] > 0) { + for (i = 0; i < sta->ext_capability[0]; i++) { + blobmsg_add_u32(&b, "", sta->ext_capability[1 + i]); + } + } + blobmsg_close_array(&b, r); + blobmsg_add_u32(&b, "aid", sta->aid); #ifdef CONFIG_TAXONOMY r = blobmsg_alloc_string_buffer(&b, "signature", 1024); @@ -305,42 +319,7 @@ hostapd_bss_get_clients(struct ubus_context *ctx, struct ubus_object *obj, blobmsg_add_u32(&b, "rx", sta_driver_data.current_rx_rate * 100); blobmsg_add_u32(&b, "tx", sta_driver_data.current_tx_rate * 100); blobmsg_close_table(&b, r); - blobmsg_add_u32(&b, "retries", sta_driver_data.tx_retry_count); - blobmsg_add_u32(&b, "failed", sta_driver_data.tx_retry_failed); blobmsg_add_u32(&b, "signal", sta_driver_data.signal); - - r = blobmsg_open_table(&b, "mcs"); - if (sta_driver_data.rx_hemcs) { - blobmsg_add_u32(&b, "he", 1); - blobmsg_add_u32(&b, "rx", sta_driver_data.rx_hemcs); - blobmsg_add_u32(&b, "tx", sta_driver_data.tx_hemcs); - } else if (sta_driver_data.rx_vhtmcs) { - blobmsg_add_u32(&b, "vht", 1); - blobmsg_add_u32(&b, "rx", sta_driver_data.rx_vhtmcs); - blobmsg_add_u32(&b, "tx", sta_driver_data.tx_vhtmcs); - } else { - blobmsg_add_u32(&b, "rx", sta_driver_data.rx_mcs); - blobmsg_add_u32(&b, "tx", sta_driver_data.tx_mcs); - } - blobmsg_close_table(&b, r); - - r = blobmsg_open_table(&b, "nss"); - if (sta_driver_data.rx_he_nss) { - blobmsg_add_u32(&b, "he", 1); - blobmsg_add_u32(&b, "rx", sta_driver_data.rx_he_nss); - blobmsg_add_u32(&b, "tx", sta_driver_data.tx_he_nss); - } else if (sta_driver_data.rx_vht_nss) { - blobmsg_add_u32(&b, "vht", 1); - blobmsg_add_u32(&b, "rx", sta_driver_data.rx_vht_nss); - blobmsg_add_u32(&b, "tx", sta_driver_data.tx_vht_nss); - } else { - blobmsg_add_u32(&b, "rx", sta_driver_data.rx_mcs); - blobmsg_add_u32(&b, "tx", sta_driver_data.tx_mcs); - } - blobmsg_close_table(&b, r); - - if (sta->signal_mgmt) - blobmsg_add_u32(&b, "signal_mgmt", sta->signal_mgmt); } hostapd_parse_capab_blobmsg(sta); @@ -368,32 +347,6 @@ hostapd_bss_get_features(struct ubus_context *ctx, struct ubus_object *obj, return 0; } -/* Imported from iw/util.c - * https://git.kernel.org/pub/scm/linux/kernel/git/jberg/iw.git/tree/util.c?id=4b25ae3537af48dbf9d0abf94132e5ba01b32c18#n200 - */ -int ieee80211_frequency_to_channel(int freq) -{ - /* see 802.11-2007 17.3.8.3.2 and Annex J */ - if (freq == 2484) - return 14; - /* see 802.11ax D6.1 27.3.23.2 and Annex E */ - else if (freq == 5935) - return 2; - else if (freq < 2484) - return (freq - 2407) / 5; - else if (freq >= 4910 && freq <= 4980) - return (freq - 4000) / 5; - else if (freq < 5950) - return (freq - 5000) / 5; - else if (freq <= 45000) /* DMG band lower limit */ - /* see 802.11ax D6.1 27.3.23.2 */ - return (freq - 5950) / 5; - else if (freq >= 58320 && freq <= 70200) - return (freq - 56160) / 2160; - else - return 0; -} - static int hostapd_bss_get_status(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, @@ -416,7 +369,6 @@ hostapd_bss_get_status(struct ubus_context *ctx, struct ubus_object *obj, &op_class, &channel); blob_buf_init(&b, 0); - blobmsg_add_string(&b, "driver", hapd->driver->name); blobmsg_add_string(&b, "status", hostapd_state_text(hapd->iface->state)); blobmsg_printf(&b, "bssid", MACSTR, MAC2STR(hapd->conf->bssid)); @@ -428,6 +380,12 @@ hostapd_bss_get_status(struct ubus_context *ctx, struct ubus_object *obj, blobmsg_add_u32(&b, "channel", channel); blobmsg_add_u32(&b, "op_class", op_class); blobmsg_add_u32(&b, "beacon_interval", hapd->iconf->beacon_int); +#ifdef CONFIG_IEEE80211AX + blobmsg_add_u32(&b, "bss_color", hapd->iface->conf->he_op.he_bss_color_disabled ? -1 : + hapd->iface->conf->he_op.he_bss_color); +#else + blobmsg_add_u32(&b, "bss_color", -1); +#endif snprintf(phy_name, 17, "%s", hapd->iface->phy); blobmsg_add_string(&b, "phy", phy_name); @@ -460,12 +418,6 @@ hostapd_bss_get_status(struct ubus_context *ctx, struct ubus_object *obj, hapd->iface->cac_started ? hapd->iface->dfs_cac_ms / 1000 - now.sec : 0); blobmsg_close_table(&b, dfs_table); - if (hapd->conf->uci_section) - blobmsg_add_string(&b, "uci_section", hapd->conf->uci_section); - - if (hapd->signal_mgmt) - blobmsg_add_u32(&b, "signal_mgmt", hapd->signal_mgmt); - ubus_send_reply(ctx, req, b.head); return 0; @@ -815,12 +767,17 @@ hostapd_switch_chan(struct ubus_context *ctx, struct ubus_object *obj, css.freq_params.ht_enabled, css.freq_params.vht_enabled, css.freq_params.he_enabled, - 0, + css.freq_params.eht_enabled, css.freq_params.sec_channel_offset, chwidth, seg0, seg1, iconf->vht_capab, - mode ? &mode->he_capab[IEEE80211_MODE_AP] : 0, - 0, 0, 0, 0); + mode ? &mode->he_capab[IEEE80211_MODE_AP] : + NULL, + mode ? &mode->eht_capab[IEEE80211_MODE_AP] : + NULL, + iconf->he_6ghz_reg_pwr_type, + iconf->ru_punct_bitmap, + iconf->ru_punct_ofdma); for (i = 0; i < hapd->iface->num_bss; i++) { struct hostapd_data *bss = hapd->iface->bss[i]; @@ -923,6 +880,7 @@ hostapd_rrm_print_nr(struct hostapd_neighbor_entry *nr) enum { BSS_MGMT_EN_NEIGHBOR, BSS_MGMT_EN_BEACON, + BSS_MGMT_EN_LINK_MEASUREMENT, #ifdef CONFIG_WNM_AP BSS_MGMT_EN_BSS_TRANSITION, #endif @@ -950,6 +908,14 @@ __hostapd_bss_mgmt_enable_f(struct hostapd_data *hapd, int flag) WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE | WLAN_RRM_CAPS_BEACON_REPORT_TABLE; + if (bss->radio_measurements[0] & flags == flags) + return false; + + bss->radio_measurements[0] |= (u8) flags; + return true; + case BSS_MGMT_EN_LINK_MEASUREMENT: + flags = WLAN_RRM_CAPS_LINK_MEASUREMENT; + if (bss->radio_measurements[0] & flags == flags) return false; @@ -987,6 +953,7 @@ __hostapd_bss_mgmt_enable(struct hostapd_data *hapd, uint32_t flags) static const struct blobmsg_policy bss_mgmt_enable_policy[__BSS_MGMT_EN_MAX] = { [BSS_MGMT_EN_NEIGHBOR] = { "neighbor_report", BLOBMSG_TYPE_BOOL }, [BSS_MGMT_EN_BEACON] = { "beacon_report", BLOBMSG_TYPE_BOOL }, + [BSS_MGMT_EN_LINK_MEASUREMENT] = { "link_measurement", BLOBMSG_TYPE_BOOL }, #ifdef CONFIG_WNM_AP [BSS_MGMT_EN_BSS_TRANSITION] = { "bss_transition", BLOBMSG_TYPE_BOOL }, #endif @@ -1015,6 +982,8 @@ hostapd_bss_mgmt_enable(struct ubus_context *ctx, struct ubus_object *obj, } __hostapd_bss_mgmt_enable(hapd, flags); + + return 0; } @@ -1265,13 +1234,105 @@ hostapd_rrm_beacon_req(struct ubus_context *ctx, struct ubus_object *obj, return 0; } +enum { + LM_REQ_ADDR, + LM_REQ_TX_POWER_USED, + LM_REQ_TX_POWER_MAX, + __LM_REQ_MAX, +}; + +static const struct blobmsg_policy lm_req_policy[__LM_REQ_MAX] = { + [LM_REQ_ADDR] = { "addr", BLOBMSG_TYPE_STRING }, + [LM_REQ_TX_POWER_USED] = { "tx-power-used", BLOBMSG_TYPE_INT32 }, + [LM_REQ_TX_POWER_MAX] = { "tx-power-max", BLOBMSG_TYPE_INT32 }, +}; + +static int +hostapd_rrm_lm_req(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *ureq, const char *method, + struct blob_attr *msg) +{ + struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); + struct blob_attr *tb[__LM_REQ_MAX]; + struct wpabuf *buf; + u8 addr[ETH_ALEN]; + int ret; + int8_t txp_used, txp_max; + + txp_used = 0; + txp_max = 0; + + blobmsg_parse(lm_req_policy, __LM_REQ_MAX, tb, blob_data(msg), blob_len(msg)); + + if (!tb[LM_REQ_ADDR]) + return UBUS_STATUS_INVALID_ARGUMENT; + + if (tb[LM_REQ_TX_POWER_USED]) + txp_used = (int8_t) blobmsg_get_u32(tb[LM_REQ_TX_POWER_USED]); + + if (tb[LM_REQ_TX_POWER_MAX]) + txp_max = (int8_t) blobmsg_get_u32(tb[LM_REQ_TX_POWER_MAX]); + + if (hwaddr_aton(blobmsg_data(tb[LM_REQ_ADDR]), addr)) + return UBUS_STATUS_INVALID_ARGUMENT; + + buf = wpabuf_alloc(5); + if (!buf) + return UBUS_STATUS_UNKNOWN_ERROR; + + wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT); + wpabuf_put_u8(buf, WLAN_RRM_LINK_MEASUREMENT_REQUEST); + wpabuf_put_u8(buf, 1); + /* TX-Power used */ + wpabuf_put_u8(buf, txp_used); + /* Max TX Power */ + wpabuf_put_u8(buf, txp_max); + + ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr, + wpabuf_head(buf), wpabuf_len(buf)); + + wpabuf_free(buf); + if (ret < 0) + return -ret; + + return 0; +} + + +void hostapd_ubus_handle_link_measurement(struct hostapd_data *hapd, const u8 *data, size_t len) +{ + const struct ieee80211_mgmt *mgmt = (const struct ieee80211_mgmt *) data; + const u8 *pos, *end; + u8 token; + + end = data + len; + token = mgmt->u.action.u.rrm.dialog_token; + pos = mgmt->u.action.u.rrm.variable; + + if (end - pos < 8) + return; + + if (!hapd->ubus.obj.has_subscribers) + return; + + blob_buf_init(&b, 0); + blobmsg_add_macaddr(&b, "address", mgmt->sa); + blobmsg_add_u16(&b, "dialog-token", token); + blobmsg_add_u16(&b, "rx-antenna-id", pos[4]); + blobmsg_add_u16(&b, "tx-antenna-id", pos[5]); + blobmsg_add_u16(&b, "rcpi", pos[6]); + blobmsg_add_u16(&b, "rsni", pos[7]); + + ubus_notify(ctx, &hapd->ubus.obj, "link-measurement-report", b.head, -1); +} + #ifdef CONFIG_WNM_AP static int hostapd_bss_tr_send(struct hostapd_data *hapd, u8 *addr, bool disassoc_imminent, bool abridged, u16 disassoc_timer, u8 validity_period, u8 dialog_token, - struct blob_attr *neighbors) + struct blob_attr *neighbors, u8 mbo_reason, u8 cell_pref, u8 reassoc_delay) { struct blob_attr *cur; struct sta_info *sta; @@ -1279,6 +1340,8 @@ hostapd_bss_tr_send(struct hostapd_data *hapd, u8 *addr, bool disassoc_imminent, int rem; u8 *nr = NULL; u8 req_mode = 0; + u8 mbo[10]; + size_t mbo_len = 0; sta = ap_get_sta(hapd, addr); if (!sta) @@ -1330,8 +1393,37 @@ hostapd_bss_tr_send(struct hostapd_data *hapd, u8 *addr, bool disassoc_imminent, if (disassoc_imminent) req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT; +#ifdef CONFIG_MBO + u8 *mbo_pos = mbo; + + if (mbo_reason > MBO_TRANSITION_REASON_PREMIUM_AP) + return UBUS_STATUS_INVALID_ARGUMENT; + + if (cell_pref != 0 && cell_pref != 1 && cell_pref != 255) + return UBUS_STATUS_INVALID_ARGUMENT; + + if (reassoc_delay > 65535 || (reassoc_delay && !disassoc_imminent)) + return UBUS_STATUS_INVALID_ARGUMENT; + + *mbo_pos++ = MBO_ATTR_ID_TRANSITION_REASON; + *mbo_pos++ = 1; + *mbo_pos++ = mbo_reason; + *mbo_pos++ = MBO_ATTR_ID_CELL_DATA_PREF; + *mbo_pos++ = 1; + *mbo_pos++ = cell_pref; + + if (reassoc_delay) { + *mbo_pos++ = MBO_ATTR_ID_ASSOC_RETRY_DELAY; + *mbo_pos++ = 2; + WPA_PUT_LE16(mbo_pos, reassoc_delay); + mbo_pos += 2; + } + + mbo_len = mbo_pos - mbo; +#endif + if (wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer, validity_period, NULL, - dialog_token, NULL, nr, nr_len, NULL, 0)) + dialog_token, NULL, nr, nr_len, mbo_len ? mbo : NULL, mbo_len)) return UBUS_STATUS_UNKNOWN_ERROR; return 0; @@ -1345,6 +1437,11 @@ enum { BSS_TR_NEIGHBORS, BSS_TR_ABRIDGED, BSS_TR_DIALOG_TOKEN, +#ifdef CONFIG_MBO + BSS_TR_MBO_REASON, + BSS_TR_CELL_PREF, + BSS_TR_REASSOC_DELAY, +#endif __BSS_TR_DISASSOC_MAX }; @@ -1356,6 +1453,11 @@ static const struct blobmsg_policy bss_tr_policy[__BSS_TR_DISASSOC_MAX] = { [BSS_TR_NEIGHBORS] = { "neighbors", BLOBMSG_TYPE_ARRAY }, [BSS_TR_ABRIDGED] = { "abridged", BLOBMSG_TYPE_BOOL }, [BSS_TR_DIALOG_TOKEN] = { "dialog_token", BLOBMSG_TYPE_INT32 }, +#ifdef CONFIG_MBO + [BSS_TR_MBO_REASON] = { "mbo_reason", BLOBMSG_TYPE_INT32 }, + [BSS_TR_CELL_PREF] = { "cell_pref", BLOBMSG_TYPE_INT32 }, + [BSS_TR_REASSOC_DELAY] = { "reassoc_delay", BLOBMSG_TYPE_INT32 }, +#endif }; static int @@ -1372,6 +1474,9 @@ hostapd_bss_transition_request(struct ubus_context *ctx, struct ubus_object *obj u32 dialog_token = 1; bool abridged; bool da_imminent; + u8 mbo_reason; + u8 cell_pref; + u8 reassoc_delay; blobmsg_parse(bss_tr_policy, __BSS_TR_DISASSOC_MAX, tb, blob_data(msg), blob_len(msg)); @@ -1393,52 +1498,19 @@ hostapd_bss_transition_request(struct ubus_context *ctx, struct ubus_object *obj da_imminent = !!(tb[BSS_TR_DA_IMMINENT] && blobmsg_get_bool(tb[BSS_TR_DA_IMMINENT])); abridged = !!(tb[BSS_TR_ABRIDGED] && blobmsg_get_bool(tb[BSS_TR_ABRIDGED])); +#ifdef CONFIG_MBO + if (tb[BSS_TR_MBO_REASON]) + mbo_reason = blobmsg_get_u32(tb[BSS_TR_MBO_REASON]); + + if (tb[BSS_TR_CELL_PREF]) + cell_pref = blobmsg_get_u32(tb[BSS_TR_CELL_PREF]); + + if (tb[BSS_TR_REASSOC_DELAY]) + reassoc_delay = blobmsg_get_u32(tb[BSS_TR_REASSOC_DELAY]); +#endif + return hostapd_bss_tr_send(hapd, addr, da_imminent, abridged, da_timer, valid_period, - dialog_token, tb[BSS_TR_NEIGHBORS]); -} - -enum { - WNM_DISASSOC_ADDR, - WNM_DISASSOC_DURATION, - WNM_DISASSOC_NEIGHBORS, - WNM_DISASSOC_ABRIDGED, - __WNM_DISASSOC_MAX, -}; - -static const struct blobmsg_policy wnm_disassoc_policy[__WNM_DISASSOC_MAX] = { - [WNM_DISASSOC_ADDR] = { "addr", BLOBMSG_TYPE_STRING }, - [WNM_DISASSOC_DURATION] { "duration", BLOBMSG_TYPE_INT32 }, - [WNM_DISASSOC_NEIGHBORS] { "neighbors", BLOBMSG_TYPE_ARRAY }, - [WNM_DISASSOC_ABRIDGED] { "abridged", BLOBMSG_TYPE_BOOL }, -}; - -static int -hostapd_wnm_disassoc_imminent(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *ureq, const char *method, - struct blob_attr *msg) -{ - struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); - struct blob_attr *tb[__WNM_DISASSOC_MAX]; - struct sta_info *sta; - int duration = 10; - u8 addr[ETH_ALEN]; - bool abridged; - - blobmsg_parse(wnm_disassoc_policy, __WNM_DISASSOC_MAX, tb, blob_data(msg), blob_len(msg)); - - if (!tb[WNM_DISASSOC_ADDR]) - return UBUS_STATUS_INVALID_ARGUMENT; - - if (hwaddr_aton(blobmsg_data(tb[WNM_DISASSOC_ADDR]), addr)) - return UBUS_STATUS_INVALID_ARGUMENT; - - if (tb[WNM_DISASSOC_DURATION]) - duration = blobmsg_get_u32(tb[WNM_DISASSOC_DURATION]); - - abridged = !!(tb[WNM_DISASSOC_ABRIDGED] && blobmsg_get_bool(tb[WNM_DISASSOC_ABRIDGED])); - - return hostapd_bss_tr_send(hapd, addr, true, abridged, duration, duration, - 1, tb[WNM_DISASSOC_NEIGHBORS]); + dialog_token, tb[BSS_TR_NEIGHBORS], mbo_reason, cell_pref, reassoc_delay); } #endif @@ -1495,10 +1567,61 @@ hostapd_bss_update_airtime(struct ubus_context *ctx, struct ubus_object *obj, } #endif +#ifdef CONFIG_TAXONOMY +static const struct blobmsg_policy addr_policy[] = { + { "address", BLOBMSG_TYPE_STRING } +}; + +static bool +hostapd_add_b64_data(const char *name, const struct wpabuf *buf) +{ + char *str; + + if (!buf) + return false; + + str = blobmsg_alloc_string_buffer(&b, name, B64_ENCODE_LEN(wpabuf_len(buf))); + b64_encode(wpabuf_head(buf), wpabuf_len(buf), str, B64_ENCODE_LEN(wpabuf_len(buf))); + blobmsg_add_string_buffer(&b); + + return true; +} + +static int +hostapd_bss_get_sta_ies(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); + struct blob_attr *tb; + struct sta_info *sta; + u8 addr[ETH_ALEN]; + + blobmsg_parse(addr_policy, 1, &tb, blobmsg_data(msg), blobmsg_len(msg)); + + if (!tb || hwaddr_aton(blobmsg_data(tb), addr)) + return UBUS_STATUS_INVALID_ARGUMENT; + + sta = ap_get_sta(hapd, addr); + if (!sta || (!sta->probe_ie_taxonomy && !sta->assoc_ie_taxonomy)) + return UBUS_STATUS_NOT_FOUND; + + blob_buf_init(&b, 0); + hostapd_add_b64_data("probe_ie", sta->probe_ie_taxonomy); + hostapd_add_b64_data("assoc_ie", sta->assoc_ie_taxonomy); + ubus_send_reply(ctx, req, b.head); + + return 0; +} +#endif + static const struct ubus_method bss_methods[] = { UBUS_METHOD_NOARG("reload", hostapd_bss_reload), UBUS_METHOD_NOARG("get_clients", hostapd_bss_get_clients), +#ifdef CONFIG_TAXONOMY + UBUS_METHOD("get_sta_ies", hostapd_bss_get_sta_ies, addr_policy), +#endif UBUS_METHOD_NOARG("get_status", hostapd_bss_get_status), UBUS_METHOD("del_client", hostapd_bss_del_client, del_policy), #ifdef CONFIG_AIRTIME_POLICY @@ -1522,8 +1645,8 @@ static const struct ubus_method bss_methods[] = { UBUS_METHOD_NOARG("rrm_nr_list", hostapd_rrm_nr_list), UBUS_METHOD("rrm_nr_set", hostapd_rrm_nr_set, nr_set_policy), UBUS_METHOD("rrm_beacon_req", hostapd_rrm_beacon_req, beacon_req_policy), + UBUS_METHOD("link_measurement_req", hostapd_rrm_lm_req, lm_req_policy), #ifdef CONFIG_WNM_AP - UBUS_METHOD("wnm_disassoc_imminent", hostapd_wnm_disassoc_imminent, wnm_disassoc_policy), UBUS_METHOD("bss_transition_request", hostapd_bss_transition_request, bss_tr_policy), #endif }; @@ -1536,85 +1659,6 @@ static int avl_compare_macaddr(const void *k1, const void *k2, void *ptr) return memcmp(k1, k2, ETH_ALEN); } -static int -hostapd_wired_get_clients(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) -{ - struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); - struct hostap_sta_driver_data sta_driver_data; - struct sta_info *sta; - void *list, *c; - char mac_buf[20]; - static const struct { - const char *name; - uint32_t flag; - } sta_flags[] = { - { "authorized", WLAN_STA_AUTHORIZED }, - }; - - blob_buf_init(&b, 0); - list = blobmsg_open_table(&b, "clients"); - for (sta = hapd->sta_list; sta; sta = sta->next) { - void *r; - int i; - - sprintf(mac_buf, MACSTR, MAC2STR(sta->addr)); - c = blobmsg_open_table(&b, mac_buf); - for (i = 0; i < ARRAY_SIZE(sta_flags); i++) - blobmsg_add_u8(&b, sta_flags[i].name, - !!(sta->flags & sta_flags[i].flag)); - - blobmsg_close_table(&b, c); - } - blobmsg_close_array(&b, list); - ubus_send_reply(ctx, req, b.head); - - return 0; -} - -static int -hostapd_wired_get_status(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) -{ - struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); - char iface_name[17]; - - blob_buf_init(&b, 0); - blobmsg_add_string(&b, "driver", hapd->driver->name); - blobmsg_add_string(&b, "status", hostapd_state_text(hapd->iface->state)); - - snprintf(iface_name, 17, "%s", hapd->iface->phy); - blobmsg_add_string(&b, "iface", iface_name); - - ubus_send_reply(ctx, req, b.head); - - return 0; -} - -static int -hostapd_wired_del_clients(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) -{ - struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); - - hostapd_free_stas(hapd); - - return 0; -} - -static const struct ubus_method wired_methods[] = { - UBUS_METHOD_NOARG("reload", hostapd_bss_reload), - UBUS_METHOD_NOARG("get_clients", hostapd_wired_get_clients), - UBUS_METHOD_NOARG("del_clients", hostapd_wired_del_clients), - UBUS_METHOD_NOARG("get_status", hostapd_wired_get_status), -}; - -static struct ubus_object_type wired_object_type = - UBUS_OBJECT_TYPE("hostapd_wired", wired_methods); - void hostapd_ubus_add_bss(struct hostapd_data *hapd) { struct ubus_object *obj = &hapd->ubus.obj; @@ -1634,15 +1678,9 @@ void hostapd_ubus_add_bss(struct hostapd_data *hapd) avl_init(&hapd->ubus.banned, avl_compare_macaddr, false, NULL); obj->name = name; - if (!strcmp(hapd->driver->name, "wired")) { - obj->type = &wired_object_type; - obj->methods = wired_object_type.methods; - obj->n_methods = wired_object_type.n_methods; - } else { - obj->type = &bss_object_type; - obj->methods = bss_object_type.methods; - obj->n_methods = bss_object_type.n_methods; - } + obj->type = &bss_object_type; + obj->methods = bss_object_type.methods; + obj->n_methods = bss_object_type.n_methods; ret = ubus_add_object(ctx, obj); hostapd_ubus_ref_inc(); } @@ -1725,7 +1763,6 @@ int hostapd_ubus_handle_event(struct hostapd_data *hapd, struct hostapd_ubus_req [HOSTAPD_UBUS_PROBE_REQ] = "probe", [HOSTAPD_UBUS_AUTH_REQ] = "auth", [HOSTAPD_UBUS_ASSOC_REQ] = "assoc", - [HOSTAPD_UBUS_COA] = "coa", }; const char *type = "mgmt"; struct ubus_event_req ureq = {}; @@ -1795,7 +1832,7 @@ int hostapd_ubus_handle_event(struct hostapd_data *hapd, struct hostapd_ubus_req } } - if (!hapd->ubus.notify_response && req->type != HOSTAPD_UBUS_COA) { + if (!hapd->ubus.notify_response) { ubus_notify(ctx, &hapd->ubus.obj, type, b.head, -1); return WLAN_STATUS_SUCCESS; } @@ -1822,40 +1859,20 @@ void hostapd_ubus_notify(struct hostapd_data *hapd, const char *type, const u8 * blob_buf_init(&b, 0); blobmsg_add_macaddr(&b, "address", addr); - blobmsg_add_string(&b, "ifname", hapd->conf->iface); ubus_notify(ctx, &hapd->ubus.obj, type, b.head, -1); } -void hostapd_ubus_notify_csa(struct hostapd_data *hapd, int freq) -{ - if (!hapd->ubus.obj.has_subscribers) - return; - - blob_buf_init(&b, 0); - blobmsg_add_string(&b, "ifname", hapd->conf->iface); - blobmsg_add_u32(&b, "freq", freq); - blobmsg_printf(&b, "bssid", MACSTR, MAC2STR(hapd->conf->bssid)); - - ubus_notify(ctx, &hapd->ubus.obj, "channel-switch", b.head, -1); -} - - -void hostapd_ubus_notify_authorized(struct hostapd_data *hapd, struct sta_info *sta) +void hostapd_ubus_notify_authorized(struct hostapd_data *hapd, struct sta_info *sta, + const char *auth_alg) { if (!hapd->ubus.obj.has_subscribers) return; blob_buf_init(&b, 0); blobmsg_add_macaddr(&b, "address", sta->addr); - blobmsg_add_string(&b, "ifname", hapd->conf->iface); - if (sta->bandwidth[0] || sta->bandwidth[1]) { - void *r = blobmsg_open_array(&b, "rate-limit"); - - blobmsg_add_u32(&b, "", sta->bandwidth[0]); - blobmsg_add_u32(&b, "", sta->bandwidth[1]); - blobmsg_close_array(&b, r); - } + if (auth_alg) + blobmsg_add_string(&b, "auth-alg", auth_alg); ubus_notify(ctx, &hapd->ubus.obj, "sta-authorized", b.head, -1); } @@ -1882,6 +1899,7 @@ void hostapd_ubus_notify_beacon_report( blobmsg_add_macaddr(&b, "bssid", rep->bssid); blobmsg_add_u16(&b, "antenna-id", rep->antenna_id); blobmsg_add_u16(&b, "parent-tsf", rep->parent_tsf); + blobmsg_add_u16(&b, "rep-mode", rep_mode); ubus_notify(ctx, &hapd->ubus.obj, "beacon-report", b.head, -1); } diff --git a/feeds/ipq95xx/hostapd/src/src/ap/ubus.c.orig b/feeds/ipq95xx/hostapd/src/src/ap/ubus.c.orig deleted file mode 100644 index befa3bc84..000000000 --- a/feeds/ipq95xx/hostapd/src/src/ap/ubus.c.orig +++ /dev/null @@ -1,1845 +0,0 @@ -/* - * hostapd / ubus support - * Copyright (c) 2013, Felix Fietkau - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" -#include "utils/common.h" -#include "utils/eloop.h" -#include "utils/wpabuf.h" -#include "common/ieee802_11_defs.h" -#include "common/hw_features_common.h" -#include "hostapd.h" -#include "neighbor_db.h" -#include "wps_hostapd.h" -#include "sta_info.h" -#include "ubus.h" -#include "ap_drv_ops.h" -#include "beacon.h" -#include "rrm.h" -#include "wnm_ap.h" -#include "taxonomy.h" -#include "airtime_policy.h" -#include "hw_features.h" - -static struct ubus_context *ctx; -static struct blob_buf b; -static int ctx_ref; - -static inline struct hostapd_data *get_hapd_from_object(struct ubus_object *obj) -{ - return container_of(obj, struct hostapd_data, ubus.obj); -} - -struct ubus_banned_client { - struct avl_node avl; - u8 addr[ETH_ALEN]; -}; - -static void ubus_reconnect_timeout(void *eloop_data, void *user_ctx) -{ - if (ubus_reconnect(ctx, NULL)) { - eloop_register_timeout(1, 0, ubus_reconnect_timeout, ctx, NULL); - return; - } - - ubus_add_uloop(ctx); -} - -static void hostapd_ubus_connection_lost(struct ubus_context *ctx) -{ - uloop_fd_delete(&ctx->sock); - eloop_register_timeout(1, 0, ubus_reconnect_timeout, ctx, NULL); -} - -static bool hostapd_ubus_init(void) -{ - if (ctx) - return true; - - eloop_add_uloop(); - ctx = ubus_connect(NULL); - if (!ctx) - return false; - - ctx->connection_lost = hostapd_ubus_connection_lost; - ubus_add_uloop(ctx); - - return true; -} - -static void hostapd_ubus_ref_inc(void) -{ - ctx_ref++; -} - -static void hostapd_ubus_ref_dec(void) -{ - ctx_ref--; - if (!ctx) - return; - - if (ctx_ref) - return; - - uloop_fd_delete(&ctx->sock); - ubus_free(ctx); - ctx = NULL; -} - -void hostapd_ubus_add_iface(struct hostapd_iface *iface) -{ - if (!hostapd_ubus_init()) - return; -} - -void hostapd_ubus_free_iface(struct hostapd_iface *iface) -{ - if (!ctx) - return; -} - -static void hostapd_notify_ubus(struct ubus_object *obj, char *bssname, char *event) -{ - char *event_type; - - if (!ctx || !obj) - return; - - if (asprintf(&event_type, "bss.%s", event) < 0) - return; - - blob_buf_init(&b, 0); - blobmsg_add_string(&b, "name", bssname); - ubus_notify(ctx, obj, event_type, b.head, -1); - free(event_type); -} - -static void -hostapd_bss_del_ban(void *eloop_data, void *user_ctx) -{ - struct ubus_banned_client *ban = eloop_data; - struct hostapd_data *hapd = user_ctx; - - avl_delete(&hapd->ubus.banned, &ban->avl); - free(ban); -} - -static void -hostapd_bss_ban_client(struct hostapd_data *hapd, u8 *addr, int time) -{ - struct ubus_banned_client *ban; - - if (time < 0) - time = 0; - - ban = avl_find_element(&hapd->ubus.banned, addr, ban, avl); - if (!ban) { - if (!time) - return; - - ban = os_zalloc(sizeof(*ban)); - memcpy(ban->addr, addr, sizeof(ban->addr)); - ban->avl.key = ban->addr; - avl_insert(&hapd->ubus.banned, &ban->avl); - } else { - eloop_cancel_timeout(hostapd_bss_del_ban, ban, hapd); - if (!time) { - hostapd_bss_del_ban(ban, hapd); - return; - } - } - - eloop_register_timeout(0, time * 1000, hostapd_bss_del_ban, ban, hapd); -} - -static int -hostapd_bss_reload(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) -{ - struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); - - return hostapd_reload_config(hapd->iface); -} - - -static void -hostapd_parse_vht_map_blobmsg(uint16_t map) -{ - char label[4]; - int16_t val; - int i; - - for (i = 0; i < 8; i++) { - snprintf(label, 4, "%dss", i + 1); - - val = (map & (BIT(1) | BIT(0))) + 7; - blobmsg_add_u16(&b, label, val == 10 ? -1 : val); - map = map >> 2; - } -} - -static void -hostapd_parse_vht_capab_blobmsg(struct ieee80211_vht_capabilities *vhtc) -{ - void *supported_mcs; - void *map; - int i; - - static const struct { - const char *name; - uint32_t flag; - } vht_capas[] = { - { "su_beamformee", VHT_CAP_SU_BEAMFORMEE_CAPABLE }, - { "mu_beamformee", VHT_CAP_MU_BEAMFORMEE_CAPABLE }, - }; - - for (i = 0; i < ARRAY_SIZE(vht_capas); i++) - blobmsg_add_u8(&b, vht_capas[i].name, - !!(vhtc->vht_capabilities_info & vht_capas[i].flag)); - - supported_mcs = blobmsg_open_table(&b, "mcs_map"); - - /* RX map */ - map = blobmsg_open_table(&b, "rx"); - hostapd_parse_vht_map_blobmsg(le_to_host16(vhtc->vht_supported_mcs_set.rx_map)); - blobmsg_close_table(&b, map); - - /* TX map */ - map = blobmsg_open_table(&b, "tx"); - hostapd_parse_vht_map_blobmsg(le_to_host16(vhtc->vht_supported_mcs_set.tx_map)); - blobmsg_close_table(&b, map); - - blobmsg_close_table(&b, supported_mcs); -} - -static void -hostapd_parse_capab_blobmsg(struct sta_info *sta) -{ - void *r, *v; - - v = blobmsg_open_table(&b, "capabilities"); - - if (sta->vht_capabilities) { - r = blobmsg_open_table(&b, "vht"); - hostapd_parse_vht_capab_blobmsg(sta->vht_capabilities); - blobmsg_close_table(&b, r); - } - - /* ToDo: Add HT / HE capability parsing */ - - blobmsg_close_table(&b, v); -} - -static int -hostapd_bss_get_clients(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) -{ - struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); - struct hostap_sta_driver_data sta_driver_data; - struct sta_info *sta; - void *list, *c; - char mac_buf[20]; - static const struct { - const char *name; - uint32_t flag; - } sta_flags[] = { - { "auth", WLAN_STA_AUTH }, - { "assoc", WLAN_STA_ASSOC }, - { "authorized", WLAN_STA_AUTHORIZED }, - { "preauth", WLAN_STA_PREAUTH }, - { "wds", WLAN_STA_WDS }, - { "wmm", WLAN_STA_WMM }, - { "ht", WLAN_STA_HT }, - { "vht", WLAN_STA_VHT }, - { "he", WLAN_STA_HE }, - { "wps", WLAN_STA_WPS }, - { "mfp", WLAN_STA_MFP }, - }; - - blob_buf_init(&b, 0); - blobmsg_add_u32(&b, "freq", hapd->iface->freq); - list = blobmsg_open_table(&b, "clients"); - for (sta = hapd->sta_list; sta; sta = sta->next) { - void *r; - int i; - - sprintf(mac_buf, MACSTR, MAC2STR(sta->addr)); - c = blobmsg_open_table(&b, mac_buf); - for (i = 0; i < ARRAY_SIZE(sta_flags); i++) - blobmsg_add_u8(&b, sta_flags[i].name, - !!(sta->flags & sta_flags[i].flag)); - - r = blobmsg_open_array(&b, "rrm"); - for (i = 0; i < ARRAY_SIZE(sta->rrm_enabled_capa); i++) - blobmsg_add_u32(&b, "", sta->rrm_enabled_capa[i]); - blobmsg_close_array(&b, r); - blobmsg_add_u32(&b, "aid", sta->aid); -#ifdef CONFIG_TAXONOMY - r = blobmsg_alloc_string_buffer(&b, "signature", 1024); - if (retrieve_sta_taxonomy(hapd, sta, r, 1024) > 0) - blobmsg_add_string_buffer(&b); -#endif - - /* Driver information */ - if (hostapd_drv_read_sta_data(hapd, &sta_driver_data, sta->addr) >= 0) { - r = blobmsg_open_table(&b, "bytes"); - blobmsg_add_u64(&b, "rx", sta_driver_data.rx_bytes); - blobmsg_add_u64(&b, "tx", sta_driver_data.tx_bytes); - blobmsg_close_table(&b, r); - r = blobmsg_open_table(&b, "airtime"); - blobmsg_add_u64(&b, "rx", sta_driver_data.rx_airtime); - blobmsg_add_u64(&b, "tx", sta_driver_data.tx_airtime); - blobmsg_close_table(&b, r); - r = blobmsg_open_table(&b, "packets"); - blobmsg_add_u32(&b, "rx", sta_driver_data.rx_packets); - blobmsg_add_u32(&b, "tx", sta_driver_data.tx_packets); - blobmsg_close_table(&b, r); - r = blobmsg_open_table(&b, "rate"); - /* Rate in kbits */ - blobmsg_add_u32(&b, "rx", sta_driver_data.current_rx_rate * 100); - blobmsg_add_u32(&b, "tx", sta_driver_data.current_tx_rate * 100); - blobmsg_close_table(&b, r); - blobmsg_add_u32(&b, "signal", sta_driver_data.signal); - } - - hostapd_parse_capab_blobmsg(sta); - - blobmsg_close_table(&b, c); - } - blobmsg_close_array(&b, list); - ubus_send_reply(ctx, req, b.head); - - return 0; -} - -static int -hostapd_bss_get_features(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) -{ - struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); - - blob_buf_init(&b, 0); - blobmsg_add_u8(&b, "ht_supported", ht_supported(hapd->iface->hw_features)); - blobmsg_add_u8(&b, "vht_supported", vht_supported(hapd->iface->hw_features)); - ubus_send_reply(ctx, req, b.head); - - return 0; -} - -/* Imported from iw/util.c - * https://git.kernel.org/pub/scm/linux/kernel/git/jberg/iw.git/tree/util.c?id=4b25ae3537af48dbf9d0abf94132e5ba01b32c18#n200 - */ -int ieee80211_frequency_to_channel(int freq) -{ - /* see 802.11-2007 17.3.8.3.2 and Annex J */ - if (freq == 2484) - return 14; - /* see 802.11ax D6.1 27.3.23.2 and Annex E */ - else if (freq == 5935) - return 2; - else if (freq < 2484) - return (freq - 2407) / 5; - else if (freq >= 4910 && freq <= 4980) - return (freq - 4000) / 5; - else if (freq < 5950) - return (freq - 5000) / 5; - else if (freq <= 45000) /* DMG band lower limit */ - /* see 802.11ax D6.1 27.3.23.2 */ - return (freq - 5950) / 5; - else if (freq >= 58320 && freq <= 70200) - return (freq - 56160) / 2160; - else - return 0; -} - -static int -hostapd_bss_get_status(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) -{ - struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); - void *airtime_table, *dfs_table, *rrm_table, *wnm_table; - struct os_reltime now; - char ssid[SSID_MAX_LEN + 1]; - char phy_name[17]; - size_t ssid_len = SSID_MAX_LEN; - u8 channel = 0, op_class = 0; - - if (hapd->conf->ssid.ssid_len < SSID_MAX_LEN) - ssid_len = hapd->conf->ssid.ssid_len; - - ieee80211_freq_to_channel_ext(hapd->iface->freq, - hapd->iconf->secondary_channel, - hostapd_get_oper_chwidth(hapd->iconf), - &op_class, &channel); - - blob_buf_init(&b, 0); - blobmsg_add_string(&b, "status", hostapd_state_text(hapd->iface->state)); - blobmsg_printf(&b, "bssid", MACSTR, MAC2STR(hapd->conf->bssid)); - - memset(ssid, 0, SSID_MAX_LEN + 1); - memcpy(ssid, hapd->conf->ssid.ssid, ssid_len); - blobmsg_add_string(&b, "ssid", ssid); - - blobmsg_add_u32(&b, "freq", hapd->iface->freq); - blobmsg_add_u32(&b, "channel", channel); - blobmsg_add_u32(&b, "op_class", op_class); - blobmsg_add_u32(&b, "beacon_interval", hapd->iconf->beacon_int); - - snprintf(phy_name, 17, "%s", hapd->iface->phy); - blobmsg_add_string(&b, "phy", phy_name); - - /* RRM */ - rrm_table = blobmsg_open_table(&b, "rrm"); - blobmsg_add_u64(&b, "neighbor_report_tx", hapd->openwrt_stats.rrm.neighbor_report_tx); - blobmsg_close_table(&b, rrm_table); - - /* WNM */ - wnm_table = blobmsg_open_table(&b, "wnm"); - blobmsg_add_u64(&b, "bss_transition_query_rx", hapd->openwrt_stats.wnm.bss_transition_query_rx); - blobmsg_add_u64(&b, "bss_transition_request_tx", hapd->openwrt_stats.wnm.bss_transition_request_tx); - blobmsg_add_u64(&b, "bss_transition_response_rx", hapd->openwrt_stats.wnm.bss_transition_response_rx); - blobmsg_close_table(&b, wnm_table); - - /* Airtime */ - airtime_table = blobmsg_open_table(&b, "airtime"); - blobmsg_add_u64(&b, "time", hapd->iface->last_channel_time); - blobmsg_add_u64(&b, "time_busy", hapd->iface->last_channel_time_busy); - blobmsg_add_u16(&b, "utilization", hapd->iface->channel_utilization); - blobmsg_close_table(&b, airtime_table); - - /* DFS */ - dfs_table = blobmsg_open_table(&b, "dfs"); - blobmsg_add_u32(&b, "cac_seconds", hapd->iface->dfs_cac_ms / 1000); - blobmsg_add_u8(&b, "cac_active", !!(hapd->iface->cac_started)); - os_reltime_age(&hapd->iface->dfs_cac_start, &now); - blobmsg_add_u32(&b, "cac_seconds_left", - hapd->iface->cac_started ? hapd->iface->dfs_cac_ms / 1000 - now.sec : 0); - blobmsg_close_table(&b, dfs_table); - - ubus_send_reply(ctx, req, b.head); - - return 0; -} - -enum { - NOTIFY_RESPONSE, - __NOTIFY_MAX -}; - -static const struct blobmsg_policy notify_policy[__NOTIFY_MAX] = { - [NOTIFY_RESPONSE] = { "notify_response", BLOBMSG_TYPE_INT32 }, -}; - -static int -hostapd_notify_response(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) -{ - struct blob_attr *tb[__NOTIFY_MAX]; - struct hostapd_data *hapd = get_hapd_from_object(obj); - struct wpabuf *elems; - const char *pos; - size_t len; - - blobmsg_parse(notify_policy, __NOTIFY_MAX, tb, - blob_data(msg), blob_len(msg)); - - if (!tb[NOTIFY_RESPONSE]) - return UBUS_STATUS_INVALID_ARGUMENT; - - hapd->ubus.notify_response = blobmsg_get_u32(tb[NOTIFY_RESPONSE]); - - return UBUS_STATUS_OK; -} - -enum { - DEL_CLIENT_ADDR, - DEL_CLIENT_REASON, - DEL_CLIENT_DEAUTH, - DEL_CLIENT_BAN_TIME, - __DEL_CLIENT_MAX -}; - -static const struct blobmsg_policy del_policy[__DEL_CLIENT_MAX] = { - [DEL_CLIENT_ADDR] = { "addr", BLOBMSG_TYPE_STRING }, - [DEL_CLIENT_REASON] = { "reason", BLOBMSG_TYPE_INT32 }, - [DEL_CLIENT_DEAUTH] = { "deauth", BLOBMSG_TYPE_INT8 }, - [DEL_CLIENT_BAN_TIME] = { "ban_time", BLOBMSG_TYPE_INT32 }, -}; - -static int -hostapd_bss_del_client(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) -{ - struct blob_attr *tb[__DEL_CLIENT_MAX]; - struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); - struct sta_info *sta; - bool deauth = false; - int reason; - u8 addr[ETH_ALEN]; - - blobmsg_parse(del_policy, __DEL_CLIENT_MAX, tb, blob_data(msg), blob_len(msg)); - - if (!tb[DEL_CLIENT_ADDR]) - return UBUS_STATUS_INVALID_ARGUMENT; - - if (hwaddr_aton(blobmsg_data(tb[DEL_CLIENT_ADDR]), addr)) - return UBUS_STATUS_INVALID_ARGUMENT; - - if (tb[DEL_CLIENT_REASON]) - reason = blobmsg_get_u32(tb[DEL_CLIENT_REASON]); - - if (tb[DEL_CLIENT_DEAUTH]) - deauth = blobmsg_get_bool(tb[DEL_CLIENT_DEAUTH]); - - sta = ap_get_sta(hapd, addr); - if (sta) { - if (deauth) { - hostapd_drv_sta_deauth(hapd, addr, reason); - ap_sta_deauthenticate(hapd, sta, reason); - } else { - hostapd_drv_sta_disassoc(hapd, addr, reason); - ap_sta_disassociate(hapd, sta, reason); - } - } - - if (tb[DEL_CLIENT_BAN_TIME]) - hostapd_bss_ban_client(hapd, addr, blobmsg_get_u32(tb[DEL_CLIENT_BAN_TIME])); - - return 0; -} - -static void -blobmsg_add_macaddr(struct blob_buf *buf, const char *name, const u8 *addr) -{ - char *s; - - s = blobmsg_alloc_string_buffer(buf, name, 20); - sprintf(s, MACSTR, MAC2STR(addr)); - blobmsg_add_string_buffer(buf); -} - -static int -hostapd_bss_list_bans(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) -{ - struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); - struct ubus_banned_client *ban; - void *c; - - blob_buf_init(&b, 0); - c = blobmsg_open_array(&b, "clients"); - avl_for_each_element(&hapd->ubus.banned, ban, avl) - blobmsg_add_macaddr(&b, NULL, ban->addr); - blobmsg_close_array(&b, c); - ubus_send_reply(ctx, req, b.head); - - return 0; -} - -#ifdef CONFIG_WPS -static int -hostapd_bss_wps_start(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) -{ - int rc; - struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); - - rc = hostapd_wps_button_pushed(hapd, NULL); - - if (rc != 0) - return UBUS_STATUS_NOT_SUPPORTED; - - return 0; -} - - -static const char * pbc_status_enum_str(enum pbc_status status) -{ - switch (status) { - case WPS_PBC_STATUS_DISABLE: - return "Disabled"; - case WPS_PBC_STATUS_ACTIVE: - return "Active"; - case WPS_PBC_STATUS_TIMEOUT: - return "Timed-out"; - case WPS_PBC_STATUS_OVERLAP: - return "Overlap"; - default: - return "Unknown"; - } -} - -static int -hostapd_bss_wps_status(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) -{ - int rc; - struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); - - blob_buf_init(&b, 0); - - blobmsg_add_string(&b, "pbc_status", pbc_status_enum_str(hapd->wps_stats.pbc_status)); - blobmsg_add_string(&b, "last_wps_result", - (hapd->wps_stats.status == WPS_STATUS_SUCCESS ? - "Success": - (hapd->wps_stats.status == WPS_STATUS_FAILURE ? - "Failed" : "None"))); - - /* If status == Failure - Add possible Reasons */ - if(hapd->wps_stats.status == WPS_STATUS_FAILURE && - hapd->wps_stats.failure_reason > 0) - blobmsg_add_string(&b, "reason", wps_ei_str(hapd->wps_stats.failure_reason)); - - if (hapd->wps_stats.status) - blobmsg_printf(&b, "peer_address", MACSTR, MAC2STR(hapd->wps_stats.peer_addr)); - - ubus_send_reply(ctx, req, b.head); - - return 0; -} - -static int -hostapd_bss_wps_cancel(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) -{ - int rc; - struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); - - rc = hostapd_wps_cancel(hapd); - - if (rc != 0) - return UBUS_STATUS_NOT_SUPPORTED; - - return 0; -} -#endif /* CONFIG_WPS */ - -static int -hostapd_bss_update_beacon(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) -{ - int rc; - struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); - - rc = ieee802_11_set_beacon(hapd); - - if (rc != 0) - return UBUS_STATUS_NOT_SUPPORTED; - - return 0; -} - -enum { - CONFIG_IFACE, - CONFIG_FILE, - __CONFIG_MAX -}; - -enum { - CSA_FREQ, - CSA_BCN_COUNT, - CSA_CENTER_FREQ1, - CSA_CENTER_FREQ2, - CSA_BANDWIDTH, - CSA_SEC_CHANNEL_OFFSET, - CSA_HT, - CSA_VHT, - CSA_HE, - CSA_BLOCK_TX, - CSA_FORCE, - __CSA_MAX -}; - -static const struct blobmsg_policy csa_policy[__CSA_MAX] = { - [CSA_FREQ] = { "freq", BLOBMSG_TYPE_INT32 }, - [CSA_BCN_COUNT] = { "bcn_count", BLOBMSG_TYPE_INT32 }, - [CSA_CENTER_FREQ1] = { "center_freq1", BLOBMSG_TYPE_INT32 }, - [CSA_CENTER_FREQ2] = { "center_freq2", BLOBMSG_TYPE_INT32 }, - [CSA_BANDWIDTH] = { "bandwidth", BLOBMSG_TYPE_INT32 }, - [CSA_SEC_CHANNEL_OFFSET] = { "sec_channel_offset", BLOBMSG_TYPE_INT32 }, - [CSA_HT] = { "ht", BLOBMSG_TYPE_BOOL }, - [CSA_VHT] = { "vht", BLOBMSG_TYPE_BOOL }, - [CSA_HE] = { "he", BLOBMSG_TYPE_BOOL }, - [CSA_BLOCK_TX] = { "block_tx", BLOBMSG_TYPE_BOOL }, - [CSA_FORCE] = { "force", BLOBMSG_TYPE_BOOL }, -}; - - -static void switch_chan_fallback_cb(void *eloop_data, void *user_ctx) -{ - struct hostapd_iface *iface = eloop_data; - struct hostapd_freq_params *freq_params = user_ctx; - - hostapd_switch_channel_fallback(iface, freq_params); -} - -#ifdef NEED_AP_MLME -static int -hostapd_switch_chan(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) -{ - struct blob_attr *tb[__CSA_MAX]; - struct hostapd_data *hapd = get_hapd_from_object(obj); - struct hostapd_config *iconf = hapd->iface->conf; - struct hostapd_freq_params *freq_params; - struct hostapd_hw_modes *mode = hapd->iface->current_mode; - struct csa_settings css = { - .freq_params = { - .ht_enabled = iconf->ieee80211n, - .vht_enabled = iconf->ieee80211ac, - .he_enabled = iconf->ieee80211ax, - .sec_channel_offset = iconf->secondary_channel, - } - }; - u8 chwidth = hostapd_get_oper_chwidth(iconf); - u8 seg0 = 0, seg1 = 0; - int ret = UBUS_STATUS_OK; - int i; - - blobmsg_parse(csa_policy, __CSA_MAX, tb, blob_data(msg), blob_len(msg)); - - if (!tb[CSA_FREQ]) - return UBUS_STATUS_INVALID_ARGUMENT; - - switch (iconf->vht_oper_chwidth) { - case CHANWIDTH_USE_HT: - if (iconf->secondary_channel) - css.freq_params.bandwidth = 40; - else - css.freq_params.bandwidth = 20; - break; - case CHANWIDTH_160MHZ: - css.freq_params.bandwidth = 160; - break; - default: - css.freq_params.bandwidth = 80; - break; - } - - css.freq_params.freq = blobmsg_get_u32(tb[CSA_FREQ]); - -#define SET_CSA_SETTING(name, field, type) \ - do { \ - if (tb[name]) \ - css.field = blobmsg_get_ ## type(tb[name]); \ - } while(0) - - SET_CSA_SETTING(CSA_BCN_COUNT, cs_count, u32); - SET_CSA_SETTING(CSA_CENTER_FREQ1, freq_params.center_freq1, u32); - SET_CSA_SETTING(CSA_CENTER_FREQ2, freq_params.center_freq2, u32); - SET_CSA_SETTING(CSA_BANDWIDTH, freq_params.bandwidth, u32); - SET_CSA_SETTING(CSA_SEC_CHANNEL_OFFSET, freq_params.sec_channel_offset, u32); - SET_CSA_SETTING(CSA_HT, freq_params.ht_enabled, bool); - SET_CSA_SETTING(CSA_VHT, freq_params.vht_enabled, bool); - SET_CSA_SETTING(CSA_HE, freq_params.he_enabled, bool); - SET_CSA_SETTING(CSA_BLOCK_TX, block_tx, bool); - - css.freq_params.channel = hostapd_hw_get_channel(hapd, css.freq_params.freq); - if (!css.freq_params.channel) - return UBUS_STATUS_NOT_SUPPORTED; - - switch (css.freq_params.bandwidth) { - case 160: - chwidth = CHANWIDTH_160MHZ; - break; - case 80: - chwidth = css.freq_params.center_freq2 ? CHANWIDTH_80P80MHZ : CHANWIDTH_80MHZ; - break; - default: - chwidth = CHANWIDTH_USE_HT; - break; - } - - hostapd_set_freq_params(&css.freq_params, iconf->hw_mode, - css.freq_params.freq, - css.freq_params.channel, iconf->enable_edmg, - iconf->edmg_channel, - css.freq_params.ht_enabled, - css.freq_params.vht_enabled, - css.freq_params.he_enabled, - css.freq_params.sec_channel_offset, - chwidth, seg0, seg1, - iconf->vht_capab, - mode ? &mode->he_capab[IEEE80211_MODE_AP] : - NULL); - - for (i = 0; i < hapd->iface->num_bss; i++) { - struct hostapd_data *bss = hapd->iface->bss[i]; - - if (hostapd_switch_channel(bss, &css) != 0) - ret = UBUS_STATUS_NOT_SUPPORTED; - } - - if (!ret || !tb[CSA_FORCE] || !blobmsg_get_bool(tb[CSA_FORCE])) - return ret; - - freq_params = malloc(sizeof(*freq_params)); - memcpy(freq_params, &css.freq_params, sizeof(*freq_params)); - eloop_register_timeout(0, 1, switch_chan_fallback_cb, - hapd->iface, freq_params); - - return 0; -#undef SET_CSA_SETTING -} -#endif - -enum { - VENDOR_ELEMENTS, - __VENDOR_ELEMENTS_MAX -}; - -static const struct blobmsg_policy ve_policy[__VENDOR_ELEMENTS_MAX] = { - /* vendor elements are provided as hex-string */ - [VENDOR_ELEMENTS] = { "vendor_elements", BLOBMSG_TYPE_STRING }, -}; - -static int -hostapd_vendor_elements(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) -{ - struct blob_attr *tb[__VENDOR_ELEMENTS_MAX]; - struct hostapd_data *hapd = get_hapd_from_object(obj); - struct hostapd_bss_config *bss = hapd->conf; - struct wpabuf *elems; - const char *pos; - size_t len; - - blobmsg_parse(ve_policy, __VENDOR_ELEMENTS_MAX, tb, - blob_data(msg), blob_len(msg)); - - if (!tb[VENDOR_ELEMENTS]) - return UBUS_STATUS_INVALID_ARGUMENT; - - pos = blobmsg_data(tb[VENDOR_ELEMENTS]); - len = os_strlen(pos); - if (len & 0x01) - return UBUS_STATUS_INVALID_ARGUMENT; - - len /= 2; - if (len == 0) { - wpabuf_free(bss->vendor_elements); - bss->vendor_elements = NULL; - return 0; - } - - elems = wpabuf_alloc(len); - if (elems == NULL) - return 1; - - if (hexstr2bin(pos, wpabuf_put(elems, len), len)) { - wpabuf_free(elems); - return UBUS_STATUS_INVALID_ARGUMENT; - } - - wpabuf_free(bss->vendor_elements); - bss->vendor_elements = elems; - - /* update beacons if vendor elements were set successfully */ - if (ieee802_11_update_beacons(hapd->iface) != 0) - return UBUS_STATUS_NOT_SUPPORTED; - return UBUS_STATUS_OK; -} - -static void -hostapd_rrm_print_nr(struct hostapd_neighbor_entry *nr) -{ - const u8 *data; - char *str; - int len; - - blobmsg_printf(&b, "", MACSTR, MAC2STR(nr->bssid)); - - str = blobmsg_alloc_string_buffer(&b, "", nr->ssid.ssid_len + 1); - memcpy(str, nr->ssid.ssid, nr->ssid.ssid_len); - str[nr->ssid.ssid_len] = 0; - blobmsg_add_string_buffer(&b); - - len = wpabuf_len(nr->nr); - str = blobmsg_alloc_string_buffer(&b, "", 2 * len + 1); - wpa_snprintf_hex(str, 2 * len + 1, wpabuf_head_u8(nr->nr), len); - blobmsg_add_string_buffer(&b); -} - -enum { - BSS_MGMT_EN_NEIGHBOR, - BSS_MGMT_EN_BEACON, -#ifdef CONFIG_WNM_AP - BSS_MGMT_EN_BSS_TRANSITION, -#endif - __BSS_MGMT_EN_MAX -}; - -static bool -__hostapd_bss_mgmt_enable_f(struct hostapd_data *hapd, int flag) -{ - struct hostapd_bss_config *bss = hapd->conf; - uint32_t flags; - - switch (flag) { - case BSS_MGMT_EN_NEIGHBOR: - if (bss->radio_measurements[0] & - WLAN_RRM_CAPS_NEIGHBOR_REPORT) - return false; - - bss->radio_measurements[0] |= - WLAN_RRM_CAPS_NEIGHBOR_REPORT; - hostapd_neighbor_set_own_report(hapd); - return true; - case BSS_MGMT_EN_BEACON: - flags = WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE | - WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE | - WLAN_RRM_CAPS_BEACON_REPORT_TABLE; - - if (bss->radio_measurements[0] & flags == flags) - return false; - - bss->radio_measurements[0] |= (u8) flags; - return true; -#ifdef CONFIG_WNM_AP - case BSS_MGMT_EN_BSS_TRANSITION: - if (bss->bss_transition) - return false; - - bss->bss_transition = 1; - return true; -#endif - } -} - -static void -__hostapd_bss_mgmt_enable(struct hostapd_data *hapd, uint32_t flags) -{ - bool update = false; - int i; - - for (i = 0; i < __BSS_MGMT_EN_MAX; i++) { - if (!(flags & (1 << i))) - continue; - - update |= __hostapd_bss_mgmt_enable_f(hapd, i); - } - - if (update) - ieee802_11_update_beacons(hapd->iface); -} - - -static const struct blobmsg_policy bss_mgmt_enable_policy[__BSS_MGMT_EN_MAX] = { - [BSS_MGMT_EN_NEIGHBOR] = { "neighbor_report", BLOBMSG_TYPE_BOOL }, - [BSS_MGMT_EN_BEACON] = { "beacon_report", BLOBMSG_TYPE_BOOL }, -#ifdef CONFIG_WNM_AP - [BSS_MGMT_EN_BSS_TRANSITION] = { "bss_transition", BLOBMSG_TYPE_BOOL }, -#endif -}; - -static int -hostapd_bss_mgmt_enable(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) - -{ - struct hostapd_data *hapd = get_hapd_from_object(obj); - struct blob_attr *tb[__BSS_MGMT_EN_MAX]; - struct blob_attr *cur; - uint32_t flags = 0; - int i; - bool neigh = false, beacon = false; - - blobmsg_parse(bss_mgmt_enable_policy, __BSS_MGMT_EN_MAX, tb, blob_data(msg), blob_len(msg)); - - for (i = 0; i < ARRAY_SIZE(tb); i++) { - if (!tb[i] || !blobmsg_get_bool(tb[i])) - continue; - - flags |= (1 << i); - } - - __hostapd_bss_mgmt_enable(hapd, flags); -} - - -static void -hostapd_rrm_nr_enable(struct hostapd_data *hapd) -{ - __hostapd_bss_mgmt_enable(hapd, 1 << BSS_MGMT_EN_NEIGHBOR); -} - -static int -hostapd_rrm_nr_get_own(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) -{ - struct hostapd_data *hapd = get_hapd_from_object(obj); - struct hostapd_neighbor_entry *nr; - void *c; - - hostapd_rrm_nr_enable(hapd); - - nr = hostapd_neighbor_get(hapd, hapd->own_addr, NULL); - if (!nr) - return UBUS_STATUS_NOT_FOUND; - - blob_buf_init(&b, 0); - - c = blobmsg_open_array(&b, "value"); - hostapd_rrm_print_nr(nr); - blobmsg_close_array(&b, c); - - ubus_send_reply(ctx, req, b.head); - - return 0; -} - -static int -hostapd_rrm_nr_list(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) -{ - struct hostapd_data *hapd = get_hapd_from_object(obj); - struct hostapd_neighbor_entry *nr; - void *c; - - hostapd_rrm_nr_enable(hapd); - blob_buf_init(&b, 0); - - c = blobmsg_open_array(&b, "list"); - dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry, list) { - void *cur; - - if (!memcmp(nr->bssid, hapd->own_addr, ETH_ALEN)) - continue; - - cur = blobmsg_open_array(&b, NULL); - hostapd_rrm_print_nr(nr); - blobmsg_close_array(&b, cur); - } - blobmsg_close_array(&b, c); - - ubus_send_reply(ctx, req, b.head); - - return 0; -} - -enum { - NR_SET_LIST, - __NR_SET_LIST_MAX -}; - -static const struct blobmsg_policy nr_set_policy[__NR_SET_LIST_MAX] = { - [NR_SET_LIST] = { "list", BLOBMSG_TYPE_ARRAY }, -}; - - -static void -hostapd_rrm_nr_clear(struct hostapd_data *hapd) -{ - struct hostapd_neighbor_entry *nr; - -restart: - dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry, list) { - if (!memcmp(nr->bssid, hapd->own_addr, ETH_ALEN)) - continue; - - hostapd_neighbor_remove(hapd, nr->bssid, &nr->ssid); - goto restart; - } -} - -static int -hostapd_rrm_nr_set(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) -{ - static const struct blobmsg_policy nr_e_policy[] = { - { .type = BLOBMSG_TYPE_STRING }, - { .type = BLOBMSG_TYPE_STRING }, - { .type = BLOBMSG_TYPE_STRING }, - }; - struct hostapd_data *hapd = get_hapd_from_object(obj); - struct blob_attr *tb_l[__NR_SET_LIST_MAX]; - struct blob_attr *tb[ARRAY_SIZE(nr_e_policy)]; - struct blob_attr *cur; - int rem; - - hostapd_rrm_nr_enable(hapd); - - blobmsg_parse(nr_set_policy, __NR_SET_LIST_MAX, tb_l, blob_data(msg), blob_len(msg)); - if (!tb_l[NR_SET_LIST]) - return UBUS_STATUS_INVALID_ARGUMENT; - - hostapd_rrm_nr_clear(hapd); - blobmsg_for_each_attr(cur, tb_l[NR_SET_LIST], rem) { - struct wpa_ssid_value ssid; - struct wpabuf *data; - u8 bssid[ETH_ALEN]; - char *s, *nr_s; - - blobmsg_parse_array(nr_e_policy, ARRAY_SIZE(nr_e_policy), tb, blobmsg_data(cur), blobmsg_data_len(cur)); - if (!tb[0] || !tb[1] || !tb[2]) - goto invalid; - - /* Neighbor Report binary */ - nr_s = blobmsg_get_string(tb[2]); - data = wpabuf_parse_bin(nr_s); - if (!data) - goto invalid; - - /* BSSID */ - s = blobmsg_get_string(tb[0]); - if (strlen(s) == 0) { - /* Copy BSSID from neighbor report */ - if (hwaddr_compact_aton(nr_s, bssid)) - goto invalid; - } else if (hwaddr_aton(s, bssid)) { - goto invalid; - } - - /* SSID */ - s = blobmsg_get_string(tb[1]); - if (strlen(s) == 0) { - /* Copy SSID from hostapd BSS conf */ - memcpy(&ssid, &hapd->conf->ssid, sizeof(ssid)); - } else { - ssid.ssid_len = strlen(s); - if (ssid.ssid_len > sizeof(ssid.ssid)) - goto invalid; - - memcpy(&ssid, s, ssid.ssid_len); - } - - hostapd_neighbor_set(hapd, bssid, &ssid, data, NULL, NULL, 0, 0); - wpabuf_free(data); - continue; - -invalid: - return UBUS_STATUS_INVALID_ARGUMENT; - } - - return 0; -} - -enum { - BEACON_REQ_ADDR, - BEACON_REQ_MODE, - BEACON_REQ_OP_CLASS, - BEACON_REQ_CHANNEL, - BEACON_REQ_DURATION, - BEACON_REQ_BSSID, - BEACON_REQ_SSID, - __BEACON_REQ_MAX, -}; - -static const struct blobmsg_policy beacon_req_policy[__BEACON_REQ_MAX] = { - [BEACON_REQ_ADDR] = { "addr", BLOBMSG_TYPE_STRING }, - [BEACON_REQ_OP_CLASS] { "op_class", BLOBMSG_TYPE_INT32 }, - [BEACON_REQ_CHANNEL] { "channel", BLOBMSG_TYPE_INT32 }, - [BEACON_REQ_DURATION] { "duration", BLOBMSG_TYPE_INT32 }, - [BEACON_REQ_MODE] { "mode", BLOBMSG_TYPE_INT32 }, - [BEACON_REQ_BSSID] { "bssid", BLOBMSG_TYPE_STRING }, - [BEACON_REQ_SSID] { "ssid", BLOBMSG_TYPE_STRING }, -}; - -static int -hostapd_rrm_beacon_req(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *ureq, const char *method, - struct blob_attr *msg) -{ - struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); - struct blob_attr *tb[__BEACON_REQ_MAX]; - struct blob_attr *cur; - struct wpabuf *req; - u8 bssid[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - u8 addr[ETH_ALEN]; - int mode, rem, ret; - int buf_len = 13; - - blobmsg_parse(beacon_req_policy, __BEACON_REQ_MAX, tb, blob_data(msg), blob_len(msg)); - - if (!tb[BEACON_REQ_ADDR] || !tb[BEACON_REQ_MODE] || !tb[BEACON_REQ_DURATION] || - !tb[BEACON_REQ_OP_CLASS] || !tb[BEACON_REQ_CHANNEL]) - return UBUS_STATUS_INVALID_ARGUMENT; - - if (tb[BEACON_REQ_SSID]) - buf_len += blobmsg_data_len(tb[BEACON_REQ_SSID]) + 2 - 1; - - mode = blobmsg_get_u32(tb[BEACON_REQ_MODE]); - if (hwaddr_aton(blobmsg_data(tb[BEACON_REQ_ADDR]), addr)) - return UBUS_STATUS_INVALID_ARGUMENT; - - if (tb[BEACON_REQ_BSSID] && - hwaddr_aton(blobmsg_data(tb[BEACON_REQ_BSSID]), bssid)) - return UBUS_STATUS_INVALID_ARGUMENT; - - req = wpabuf_alloc(buf_len); - if (!req) - return UBUS_STATUS_UNKNOWN_ERROR; - - /* 1: regulatory class */ - wpabuf_put_u8(req, blobmsg_get_u32(tb[BEACON_REQ_OP_CLASS])); - - /* 2: channel number */ - wpabuf_put_u8(req, blobmsg_get_u32(tb[BEACON_REQ_CHANNEL])); - - /* 3-4: randomization interval */ - wpabuf_put_le16(req, 0); - - /* 5-6: duration */ - wpabuf_put_le16(req, blobmsg_get_u32(tb[BEACON_REQ_DURATION])); - - /* 7: mode */ - wpabuf_put_u8(req, blobmsg_get_u32(tb[BEACON_REQ_MODE])); - - /* 8-13: BSSID */ - wpabuf_put_data(req, bssid, ETH_ALEN); - - if ((cur = tb[BEACON_REQ_SSID]) != NULL) { - wpabuf_put_u8(req, WLAN_EID_SSID); - wpabuf_put_u8(req, blobmsg_data_len(cur) - 1); - wpabuf_put_data(req, blobmsg_data(cur), blobmsg_data_len(cur) - 1); - } - - ret = hostapd_send_beacon_req(hapd, addr, 0, req); - if (ret < 0) - return -ret; - - return 0; -} - - -#ifdef CONFIG_WNM_AP - -static int -hostapd_bss_tr_send(struct hostapd_data *hapd, u8 *addr, bool disassoc_imminent, bool abridged, - u16 disassoc_timer, u8 validity_period, u8 dialog_token, - struct blob_attr *neighbors) -{ - struct blob_attr *cur; - struct sta_info *sta; - int nr_len = 0; - int rem; - u8 *nr = NULL; - u8 req_mode = 0; - - sta = ap_get_sta(hapd, addr); - if (!sta) - return UBUS_STATUS_NOT_FOUND; - - if (neighbors) { - u8 *nr_cur; - - if (blobmsg_check_array(neighbors, - BLOBMSG_TYPE_STRING) < 0) - return UBUS_STATUS_INVALID_ARGUMENT; - - blobmsg_for_each_attr(cur, neighbors, rem) { - int len = strlen(blobmsg_get_string(cur)); - - if (len % 2) - return UBUS_STATUS_INVALID_ARGUMENT; - - nr_len += (len / 2) + 2; - } - - if (nr_len) { - nr = os_zalloc(nr_len); - if (!nr) - return UBUS_STATUS_UNKNOWN_ERROR; - } - - nr_cur = nr; - blobmsg_for_each_attr(cur, neighbors, rem) { - int len = strlen(blobmsg_get_string(cur)) / 2; - - *nr_cur++ = WLAN_EID_NEIGHBOR_REPORT; - *nr_cur++ = (u8) len; - if (hexstr2bin(blobmsg_data(cur), nr_cur, len)) { - free(nr); - return UBUS_STATUS_INVALID_ARGUMENT; - } - - nr_cur += len; - } - } - - if (nr) - req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED; - - if (abridged) - req_mode |= WNM_BSS_TM_REQ_ABRIDGED; - - if (disassoc_imminent) - req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT; - - if (wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer, validity_period, NULL, - dialog_token, NULL, nr, nr_len, NULL, 0)) - return UBUS_STATUS_UNKNOWN_ERROR; - - return 0; -} - -enum { - BSS_TR_ADDR, - BSS_TR_DA_IMMINENT, - BSS_TR_DA_TIMER, - BSS_TR_VALID_PERIOD, - BSS_TR_NEIGHBORS, - BSS_TR_ABRIDGED, - BSS_TR_DIALOG_TOKEN, - __BSS_TR_DISASSOC_MAX -}; - -static const struct blobmsg_policy bss_tr_policy[__BSS_TR_DISASSOC_MAX] = { - [BSS_TR_ADDR] = { "addr", BLOBMSG_TYPE_STRING }, - [BSS_TR_DA_IMMINENT] = { "disassociation_imminent", BLOBMSG_TYPE_BOOL }, - [BSS_TR_DA_TIMER] = { "disassociation_timer", BLOBMSG_TYPE_INT32 }, - [BSS_TR_VALID_PERIOD] = { "validity_period", BLOBMSG_TYPE_INT32 }, - [BSS_TR_NEIGHBORS] = { "neighbors", BLOBMSG_TYPE_ARRAY }, - [BSS_TR_ABRIDGED] = { "abridged", BLOBMSG_TYPE_BOOL }, - [BSS_TR_DIALOG_TOKEN] = { "dialog_token", BLOBMSG_TYPE_INT32 }, -}; - -static int -hostapd_bss_transition_request(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *ureq, const char *method, - struct blob_attr *msg) -{ - struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); - struct blob_attr *tb[__BSS_TR_DISASSOC_MAX]; - struct sta_info *sta; - u32 da_timer = 0; - u32 valid_period = 0; - u8 addr[ETH_ALEN]; - u32 dialog_token = 1; - bool abridged; - bool da_imminent; - - blobmsg_parse(bss_tr_policy, __BSS_TR_DISASSOC_MAX, tb, blob_data(msg), blob_len(msg)); - - if (!tb[BSS_TR_ADDR]) - return UBUS_STATUS_INVALID_ARGUMENT; - - if (hwaddr_aton(blobmsg_data(tb[BSS_TR_ADDR]), addr)) - return UBUS_STATUS_INVALID_ARGUMENT; - - if (tb[BSS_TR_DA_TIMER]) - da_timer = blobmsg_get_u32(tb[BSS_TR_DA_TIMER]); - - if (tb[BSS_TR_VALID_PERIOD]) - valid_period = blobmsg_get_u32(tb[BSS_TR_VALID_PERIOD]); - - if (tb[BSS_TR_DIALOG_TOKEN]) - dialog_token = blobmsg_get_u32(tb[BSS_TR_DIALOG_TOKEN]); - - da_imminent = !!(tb[BSS_TR_DA_IMMINENT] && blobmsg_get_bool(tb[BSS_TR_DA_IMMINENT])); - abridged = !!(tb[BSS_TR_ABRIDGED] && blobmsg_get_bool(tb[BSS_TR_ABRIDGED])); - - return hostapd_bss_tr_send(hapd, addr, da_imminent, abridged, da_timer, valid_period, - dialog_token, tb[BSS_TR_NEIGHBORS]); -} - -enum { - WNM_DISASSOC_ADDR, - WNM_DISASSOC_DURATION, - WNM_DISASSOC_NEIGHBORS, - WNM_DISASSOC_ABRIDGED, - __WNM_DISASSOC_MAX, -}; - -static const struct blobmsg_policy wnm_disassoc_policy[__WNM_DISASSOC_MAX] = { - [WNM_DISASSOC_ADDR] = { "addr", BLOBMSG_TYPE_STRING }, - [WNM_DISASSOC_DURATION] { "duration", BLOBMSG_TYPE_INT32 }, - [WNM_DISASSOC_NEIGHBORS] { "neighbors", BLOBMSG_TYPE_ARRAY }, - [WNM_DISASSOC_ABRIDGED] { "abridged", BLOBMSG_TYPE_BOOL }, -}; - -static int -hostapd_wnm_disassoc_imminent(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *ureq, const char *method, - struct blob_attr *msg) -{ - struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); - struct blob_attr *tb[__WNM_DISASSOC_MAX]; - struct sta_info *sta; - int duration = 10; - u8 addr[ETH_ALEN]; - bool abridged; - - blobmsg_parse(wnm_disassoc_policy, __WNM_DISASSOC_MAX, tb, blob_data(msg), blob_len(msg)); - - if (!tb[WNM_DISASSOC_ADDR]) - return UBUS_STATUS_INVALID_ARGUMENT; - - if (hwaddr_aton(blobmsg_data(tb[WNM_DISASSOC_ADDR]), addr)) - return UBUS_STATUS_INVALID_ARGUMENT; - - if (tb[WNM_DISASSOC_DURATION]) - duration = blobmsg_get_u32(tb[WNM_DISASSOC_DURATION]); - - abridged = !!(tb[WNM_DISASSOC_ABRIDGED] && blobmsg_get_bool(tb[WNM_DISASSOC_ABRIDGED])); - - return hostapd_bss_tr_send(hapd, addr, true, abridged, duration, duration, - 1, tb[WNM_DISASSOC_NEIGHBORS]); -} -#endif - -#ifdef CONFIG_AIRTIME_POLICY -enum { - UPDATE_AIRTIME_STA, - UPDATE_AIRTIME_WEIGHT, - __UPDATE_AIRTIME_MAX, -}; - - -static const struct blobmsg_policy airtime_policy[__UPDATE_AIRTIME_MAX] = { - [UPDATE_AIRTIME_STA] = { "sta", BLOBMSG_TYPE_STRING }, - [UPDATE_AIRTIME_WEIGHT] = { "weight", BLOBMSG_TYPE_INT32 }, -}; - -static int -hostapd_bss_update_airtime(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *ureq, const char *method, - struct blob_attr *msg) -{ - struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); - struct blob_attr *tb[__UPDATE_AIRTIME_MAX]; - struct sta_info *sta = NULL; - u8 addr[ETH_ALEN]; - int weight; - - blobmsg_parse(airtime_policy, __UPDATE_AIRTIME_MAX, tb, blob_data(msg), blob_len(msg)); - - if (!tb[UPDATE_AIRTIME_WEIGHT]) - return UBUS_STATUS_INVALID_ARGUMENT; - - weight = blobmsg_get_u32(tb[UPDATE_AIRTIME_WEIGHT]); - - if (!tb[UPDATE_AIRTIME_STA]) { - if (!weight) - return UBUS_STATUS_INVALID_ARGUMENT; - - hapd->conf->airtime_weight = weight; - return 0; - } - - if (hwaddr_aton(blobmsg_data(tb[UPDATE_AIRTIME_STA]), addr)) - return UBUS_STATUS_INVALID_ARGUMENT; - - sta = ap_get_sta(hapd, addr); - if (!sta) - return UBUS_STATUS_NOT_FOUND; - - sta->dyn_airtime_weight = weight; - airtime_policy_new_sta(hapd, sta); - - return 0; -} -#endif - - -static const struct ubus_method bss_methods[] = { - UBUS_METHOD_NOARG("reload", hostapd_bss_reload), - UBUS_METHOD_NOARG("get_clients", hostapd_bss_get_clients), - UBUS_METHOD_NOARG("get_status", hostapd_bss_get_status), - UBUS_METHOD("del_client", hostapd_bss_del_client, del_policy), -#ifdef CONFIG_AIRTIME_POLICY - UBUS_METHOD("update_airtime", hostapd_bss_update_airtime, airtime_policy), -#endif - UBUS_METHOD_NOARG("list_bans", hostapd_bss_list_bans), -#ifdef CONFIG_WPS - UBUS_METHOD_NOARG("wps_start", hostapd_bss_wps_start), - UBUS_METHOD_NOARG("wps_status", hostapd_bss_wps_status), - UBUS_METHOD_NOARG("wps_cancel", hostapd_bss_wps_cancel), -#endif - UBUS_METHOD_NOARG("update_beacon", hostapd_bss_update_beacon), - UBUS_METHOD_NOARG("get_features", hostapd_bss_get_features), -#ifdef NEED_AP_MLME - UBUS_METHOD("switch_chan", hostapd_switch_chan, csa_policy), -#endif - UBUS_METHOD("set_vendor_elements", hostapd_vendor_elements, ve_policy), - UBUS_METHOD("notify_response", hostapd_notify_response, notify_policy), - UBUS_METHOD("bss_mgmt_enable", hostapd_bss_mgmt_enable, bss_mgmt_enable_policy), - UBUS_METHOD_NOARG("rrm_nr_get_own", hostapd_rrm_nr_get_own), - UBUS_METHOD_NOARG("rrm_nr_list", hostapd_rrm_nr_list), - UBUS_METHOD("rrm_nr_set", hostapd_rrm_nr_set, nr_set_policy), - UBUS_METHOD("rrm_beacon_req", hostapd_rrm_beacon_req, beacon_req_policy), -#ifdef CONFIG_WNM_AP - UBUS_METHOD("wnm_disassoc_imminent", hostapd_wnm_disassoc_imminent, wnm_disassoc_policy), - UBUS_METHOD("bss_transition_request", hostapd_bss_transition_request, bss_tr_policy), -#endif -}; - -static struct ubus_object_type bss_object_type = - UBUS_OBJECT_TYPE("hostapd_bss", bss_methods); - -static int avl_compare_macaddr(const void *k1, const void *k2, void *ptr) -{ - return memcmp(k1, k2, ETH_ALEN); -} - -void hostapd_ubus_add_bss(struct hostapd_data *hapd) -{ - struct ubus_object *obj = &hapd->ubus.obj; - char *name; - int ret; - -#ifdef CONFIG_MESH - if (hapd->conf->mesh & MESH_ENABLED) - return; -#endif - - if (!hostapd_ubus_init()) - return; - - if (asprintf(&name, "hostapd.%s", hapd->conf->iface) < 0) - return; - - avl_init(&hapd->ubus.banned, avl_compare_macaddr, false, NULL); - obj->name = name; - obj->type = &bss_object_type; - obj->methods = bss_object_type.methods; - obj->n_methods = bss_object_type.n_methods; - ret = ubus_add_object(ctx, obj); - hostapd_ubus_ref_inc(); -} - -void hostapd_ubus_free_bss(struct hostapd_data *hapd) -{ - struct ubus_object *obj = &hapd->ubus.obj; - char *name = (char *) obj->name; - -#ifdef CONFIG_MESH - if (hapd->conf->mesh & MESH_ENABLED) - return; -#endif - - if (!ctx) - return; - - if (obj->id) { - ubus_remove_object(ctx, obj); - hostapd_ubus_ref_dec(); - } - - free(name); -} - -static void -hostapd_ubus_vlan_action(struct hostapd_data *hapd, struct hostapd_vlan *vlan, - const char *action) -{ - struct vlan_description *desc = &vlan->vlan_desc; - void *c; - int i; - - if (!hapd->ubus.obj.has_subscribers) - return; - - blob_buf_init(&b, 0); - blobmsg_add_string(&b, "ifname", vlan->ifname); - blobmsg_add_string(&b, "bridge", vlan->bridge); - blobmsg_add_u32(&b, "vlan_id", vlan->vlan_id); - - if (desc->notempty) { - blobmsg_add_u32(&b, "untagged", desc->untagged); - c = blobmsg_open_array(&b, "tagged"); - for (i = 0; i < ARRAY_SIZE(desc->tagged) && desc->tagged[i]; i++) - blobmsg_add_u32(&b, "", desc->tagged[i]); - blobmsg_close_array(&b, c); - } - - ubus_notify(ctx, &hapd->ubus.obj, action, b.head, -1); -} - -void hostapd_ubus_add_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vlan) -{ - hostapd_ubus_vlan_action(hapd, vlan, "vlan_add"); -} - -void hostapd_ubus_remove_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vlan) -{ - hostapd_ubus_vlan_action(hapd, vlan, "vlan_remove"); -} - -struct ubus_event_req { - struct ubus_notify_request nreq; - int resp; -}; - -static void -ubus_event_cb(struct ubus_notify_request *req, int idx, int ret) -{ - struct ubus_event_req *ureq = container_of(req, struct ubus_event_req, nreq); - - ureq->resp = ret; -} - -int hostapd_ubus_handle_event(struct hostapd_data *hapd, struct hostapd_ubus_request *req) -{ - struct ubus_banned_client *ban; - const char *types[HOSTAPD_UBUS_TYPE_MAX] = { - [HOSTAPD_UBUS_PROBE_REQ] = "probe", - [HOSTAPD_UBUS_AUTH_REQ] = "auth", - [HOSTAPD_UBUS_ASSOC_REQ] = "assoc", - }; - const char *type = "mgmt"; - struct ubus_event_req ureq = {}; - const u8 *addr; - - if (req->mgmt_frame) - addr = req->mgmt_frame->sa; - else - addr = req->addr; - - ban = avl_find_element(&hapd->ubus.banned, addr, ban, avl); - if (ban) - return WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; - - if (!hapd->ubus.obj.has_subscribers) - return WLAN_STATUS_SUCCESS; - - if (req->type < ARRAY_SIZE(types)) - type = types[req->type]; - - blob_buf_init(&b, 0); - blobmsg_add_macaddr(&b, "address", addr); - if (req->mgmt_frame) - blobmsg_add_macaddr(&b, "target", req->mgmt_frame->da); - if (req->ssi_signal) - blobmsg_add_u32(&b, "signal", req->ssi_signal); - blobmsg_add_u32(&b, "freq", hapd->iface->freq); - - if (req->elems) { - if(req->elems->ht_capabilities) - { - struct ieee80211_ht_capabilities *ht_capabilities; - void *ht_cap, *ht_cap_mcs_set, *mcs_set; - - - ht_capabilities = (struct ieee80211_ht_capabilities*) req->elems->ht_capabilities; - ht_cap = blobmsg_open_table(&b, "ht_capabilities"); - blobmsg_add_u16(&b, "ht_capabilities_info", ht_capabilities->ht_capabilities_info); - ht_cap_mcs_set = blobmsg_open_table(&b, "supported_mcs_set"); - blobmsg_add_u16(&b, "a_mpdu_params", ht_capabilities->a_mpdu_params); - blobmsg_add_u16(&b, "ht_extended_capabilities", ht_capabilities->ht_extended_capabilities); - blobmsg_add_u32(&b, "tx_bf_capability_info", ht_capabilities->tx_bf_capability_info); - blobmsg_add_u16(&b, "asel_capabilities", ht_capabilities->asel_capabilities); - mcs_set = blobmsg_open_array(&b, "supported_mcs_set"); - for (int i = 0; i < 16; i++) { - blobmsg_add_u16(&b, NULL, (u16) ht_capabilities->supported_mcs_set[i]); - } - blobmsg_close_array(&b, mcs_set); - blobmsg_close_table(&b, ht_cap_mcs_set); - blobmsg_close_table(&b, ht_cap); - } - if(req->elems->vht_capabilities) - { - struct ieee80211_vht_capabilities *vht_capabilities; - void *vht_cap, *vht_cap_mcs_set; - - vht_capabilities = (struct ieee80211_vht_capabilities*) req->elems->vht_capabilities; - vht_cap = blobmsg_open_table(&b, "vht_capabilities"); - blobmsg_add_u32(&b, "vht_capabilities_info", vht_capabilities->vht_capabilities_info); - vht_cap_mcs_set = blobmsg_open_table(&b, "vht_supported_mcs_set"); - blobmsg_add_u16(&b, "rx_map", vht_capabilities->vht_supported_mcs_set.rx_map); - blobmsg_add_u16(&b, "rx_highest", vht_capabilities->vht_supported_mcs_set.rx_highest); - blobmsg_add_u16(&b, "tx_map", vht_capabilities->vht_supported_mcs_set.tx_map); - blobmsg_add_u16(&b, "tx_highest", vht_capabilities->vht_supported_mcs_set.tx_highest); - blobmsg_close_table(&b, vht_cap_mcs_set); - blobmsg_close_table(&b, vht_cap); - } - } - - if (!hapd->ubus.notify_response) { - ubus_notify(ctx, &hapd->ubus.obj, type, b.head, -1); - return WLAN_STATUS_SUCCESS; - } - - if (ubus_notify_async(ctx, &hapd->ubus.obj, type, b.head, &ureq.nreq)) - return WLAN_STATUS_SUCCESS; - - ureq.nreq.status_cb = ubus_event_cb; - ubus_complete_request(ctx, &ureq.nreq.req, 100); - - if (ureq.resp) - return ureq.resp; - - return WLAN_STATUS_SUCCESS; -} - -void hostapd_ubus_notify(struct hostapd_data *hapd, const char *type, const u8 *addr) -{ - if (!hapd->ubus.obj.has_subscribers) - return; - - if (!addr) - return; - - blob_buf_init(&b, 0); - blobmsg_add_macaddr(&b, "address", addr); - blobmsg_add_string(&b, "ifname", hapd->conf->iface); - - ubus_notify(ctx, &hapd->ubus.obj, type, b.head, -1); -} - - -void hostapd_ubus_notify_authorized(struct hostapd_data *hapd, struct sta_info *sta) -{ - if (!hapd->ubus.obj.has_subscribers) - return; - - blob_buf_init(&b, 0); - blobmsg_add_macaddr(&b, "address", sta->addr); - blobmsg_add_string(&b, "ifname", hapd->conf->iface); - if (sta->bandwidth[0] || sta->bandwidth[1]) { - void *r = blobmsg_open_array(&b, "rate-limit"); - - blobmsg_add_u32(&b, "", sta->bandwidth[0]); - blobmsg_add_u32(&b, "", sta->bandwidth[1]); - blobmsg_close_array(&b, r); - } - - ubus_notify(ctx, &hapd->ubus.obj, "sta-authorized", b.head, -1); -} - -void hostapd_ubus_notify_beacon_report( - struct hostapd_data *hapd, const u8 *addr, u8 token, u8 rep_mode, - struct rrm_measurement_beacon_report *rep, size_t len) -{ - if (!hapd->ubus.obj.has_subscribers) - return; - - if (!addr || !rep) - return; - - blob_buf_init(&b, 0); - blobmsg_add_macaddr(&b, "address", addr); - blobmsg_add_u16(&b, "op-class", rep->op_class); - blobmsg_add_u16(&b, "channel", rep->channel); - blobmsg_add_u64(&b, "start-time", rep->start_time); - blobmsg_add_u16(&b, "duration", rep->duration); - blobmsg_add_u16(&b, "report-info", rep->report_info); - blobmsg_add_u16(&b, "rcpi", rep->rcpi); - blobmsg_add_u16(&b, "rsni", rep->rsni); - blobmsg_add_macaddr(&b, "bssid", rep->bssid); - blobmsg_add_u16(&b, "antenna-id", rep->antenna_id); - blobmsg_add_u16(&b, "parent-tsf", rep->parent_tsf); - - ubus_notify(ctx, &hapd->ubus.obj, "beacon-report", b.head, -1); -} - -void hostapd_ubus_notify_radar_detected(struct hostapd_iface *iface, int frequency, - int chan_width, int cf1, int cf2) -{ - struct hostapd_data *hapd; - int i; - - blob_buf_init(&b, 0); - blobmsg_add_u16(&b, "frequency", frequency); - blobmsg_add_u16(&b, "width", chan_width); - blobmsg_add_u16(&b, "center1", cf1); - blobmsg_add_u16(&b, "center2", cf2); - - for (i = 0; i < iface->num_bss; i++) { - hapd = iface->bss[i]; - ubus_notify(ctx, &hapd->ubus.obj, "radar-detected", b.head, -1); - } -} - -#ifdef CONFIG_WNM_AP -static void hostapd_ubus_notify_bss_transition_add_candidate_list( - const u8 *candidate_list, u16 candidate_list_len) -{ - char *cl_str; - int i; - - if (candidate_list_len == 0) - return; - - cl_str = blobmsg_alloc_string_buffer(&b, "candidate-list", candidate_list_len * 2 + 1); - for (i = 0; i < candidate_list_len; i++) - snprintf(&cl_str[i*2], 3, "%02X", candidate_list[i]); - blobmsg_add_string_buffer(&b); - -} -#endif - -void hostapd_ubus_notify_bss_transition_response( - struct hostapd_data *hapd, const u8 *addr, u8 dialog_token, u8 status_code, - u8 bss_termination_delay, const u8 *target_bssid, - const u8 *candidate_list, u16 candidate_list_len) -{ -#ifdef CONFIG_WNM_AP - u16 i; - - if (!hapd->ubus.obj.has_subscribers) - return; - - if (!addr) - return; - - blob_buf_init(&b, 0); - blobmsg_add_macaddr(&b, "address", addr); - blobmsg_add_u8(&b, "dialog-token", dialog_token); - blobmsg_add_u8(&b, "status-code", status_code); - blobmsg_add_u8(&b, "bss-termination-delay", bss_termination_delay); - if (target_bssid) - blobmsg_add_macaddr(&b, "target-bssid", target_bssid); - - hostapd_ubus_notify_bss_transition_add_candidate_list(candidate_list, candidate_list_len); - - ubus_notify(ctx, &hapd->ubus.obj, "bss-transition-response", b.head, -1); -#endif -} - -int hostapd_ubus_notify_bss_transition_query( - struct hostapd_data *hapd, const u8 *addr, u8 dialog_token, u8 reason, - const u8 *candidate_list, u16 candidate_list_len) -{ -#ifdef CONFIG_WNM_AP - struct ubus_event_req ureq = {}; - char *cl_str; - u16 i; - - if (!hapd->ubus.obj.has_subscribers) - return 0; - - if (!addr) - return 0; - - blob_buf_init(&b, 0); - blobmsg_add_macaddr(&b, "address", addr); - blobmsg_add_u8(&b, "dialog-token", dialog_token); - blobmsg_add_u8(&b, "reason", reason); - hostapd_ubus_notify_bss_transition_add_candidate_list(candidate_list, candidate_list_len); - - if (!hapd->ubus.notify_response) { - ubus_notify(ctx, &hapd->ubus.obj, "bss-transition-query", b.head, -1); - return 0; - } - - if (ubus_notify_async(ctx, &hapd->ubus.obj, "bss-transition-query", b.head, &ureq.nreq)) - return 0; - - ureq.nreq.status_cb = ubus_event_cb; - ubus_complete_request(ctx, &ureq.nreq.req, 100); - - return ureq.resp; -#endif -} diff --git a/feeds/ipq95xx/hostapd/src/src/ap/ubus.h b/feeds/ipq95xx/hostapd/src/src/ap/ubus.h index ce23ee3a5..b0f7c44ab 100644 --- a/feeds/ipq95xx/hostapd/src/src/ap/ubus.h +++ b/feeds/ipq95xx/hostapd/src/src/ap/ubus.h @@ -47,8 +47,8 @@ void hostapd_ubus_add_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vlan) void hostapd_ubus_remove_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vlan); int hostapd_ubus_handle_event(struct hostapd_data *hapd, struct hostapd_ubus_request *req); +void hostapd_ubus_handle_link_measurement(struct hostapd_data *hapd, const u8 *data, size_t len); void hostapd_ubus_notify(struct hostapd_data *hapd, const char *type, const u8 *mac); -void hostapd_ubus_notify_authorized(struct hostapd_data *hapd, struct sta_info *sta); void hostapd_ubus_notify_beacon_report(struct hostapd_data *hapd, const u8 *addr, u8 token, u8 rep_mode, struct rrm_measurement_beacon_report *rep, @@ -65,7 +65,8 @@ void hostapd_ubus_free(struct hapd_interfaces *interfaces); int hostapd_ubus_notify_bss_transition_query( struct hostapd_data *hapd, const u8 *addr, u8 dialog_token, u8 reason, const u8 *candidate_list, u16 candidate_list_len); -void hostapd_ubus_notify_csa(struct hostapd_data *hapd, int freq); +void hostapd_ubus_notify_authorized(struct hostapd_data *hapd, struct sta_info *sta, + const char *auth_alg); #else @@ -100,6 +101,10 @@ static inline int hostapd_ubus_handle_event(struct hostapd_data *hapd, struct ho return 0; } +static inline void hostapd_ubus_handle_link_measurement(struct hostapd_data *hapd, const u8 *data, size_t len) +{ +} + static inline void hostapd_ubus_notify(struct hostapd_data *hapd, const char *type, const u8 *mac) { } @@ -137,6 +142,13 @@ static inline int hostapd_ubus_notify_bss_transition_query( { return 0; } + +static inline void +hostapd_ubus_notify_authorized(struct hostapd_data *hapd, struct sta_info *sta, + const char *auth_alg) +{ +} + #endif #endif diff --git a/feeds/ipq95xx/hostapd/src/src/ap/ucode.c b/feeds/ipq95xx/hostapd/src/src/ap/ucode.c index 25219b64a..6c6cdf7a3 100644 --- a/feeds/ipq95xx/hostapd/src/src/ap/ucode.c +++ b/feeds/ipq95xx/hostapd/src/src/ap/ucode.c @@ -509,6 +509,7 @@ static uc_value_t * uc_hostapd_iface_start(uc_vm_t *vm, size_t nargs) { struct hostapd_iface *iface = uc_fn_thisval("hostapd.iface"); + struct hostapd_hw_modes *cmode = iface->current_mode; uc_value_t *info = uc_fn_arg(0); struct hostapd_config *conf; bool changed = false; diff --git a/feeds/ipq95xx/hostapd/src/src/utils/ucode.c b/feeds/ipq95xx/hostapd/src/src/utils/ucode.c index 998cf5574..2beeb9a7f 100644 --- a/feeds/ipq95xx/hostapd/src/src/utils/ucode.c +++ b/feeds/ipq95xx/hostapd/src/src/utils/ucode.c @@ -52,12 +52,12 @@ uc_value_t *uc_wpa_freq_info(uc_vm_t *vm, size_t nargs) uc_value_t *sec = uc_fn_arg(1); int width = ucv_uint64_get(uc_fn_arg(2)); int freq_val, center_idx, center_ofs; + enum oper_chan_width chanwidth; enum hostapd_hw_mode hw_mode; u8 op_class, channel, tmp_channel; const char *modestr; int sec_channel = 0; uc_value_t *ret; - int chanwidth; if (ucv_type(freq) != UC_INTEGER) return NULL; @@ -77,13 +77,13 @@ uc_value_t *uc_wpa_freq_info(uc_vm_t *vm, size_t nargs) switch (width) { case 0: - chanwidth = CHANWIDTH_USE_HT; + chanwidth = CONF_OPER_CHWIDTH_USE_HT; break; case 1: - chanwidth = CHANWIDTH_80MHZ; + chanwidth = CONF_OPER_CHWIDTH_80MHZ; break; case 2: - chanwidth = CHANWIDTH_160MHZ; + chanwidth = CONF_OPER_CHWIDTH_160MHZ; break; default: return NULL; diff --git a/feeds/ipq95xx/hostapd/src/wpa_supplicant/ucode.c b/feeds/ipq95xx/hostapd/src/wpa_supplicant/ucode.c index 55d22584f..6cba73dcd 100644 --- a/feeds/ipq95xx/hostapd/src/wpa_supplicant/ucode.c +++ b/feeds/ipq95xx/hostapd/src/wpa_supplicant/ucode.c @@ -136,6 +136,7 @@ static uc_value_t * uc_wpas_add_iface(uc_vm_t *vm, size_t nargs) { uc_value_t *info = uc_fn_arg(0); + uc_value_t *driver = ucv_object_get(info, "driver", NULL); uc_value_t *ifname = ucv_object_get(info, "iface", NULL); uc_value_t *bridge = ucv_object_get(info, "bridge", NULL); uc_value_t *config = ucv_object_get(info, "config", NULL); @@ -154,6 +155,22 @@ uc_wpas_add_iface(uc_vm_t *vm, size_t nargs) .ctrl_interface = ucv_string_get(ctrl), }; + if (driver) { + const char *drvname; + if (ucv_type(driver) != UC_STRING) + goto out; + + iface.driver = NULL; + drvname = ucv_string_get(driver); + for (int i = 0; wpa_drivers[i]; i++) { + if (!strcmp(drvname, wpa_drivers[i]->name)) + iface.driver = wpa_drivers[i]->name; + } + + if (!iface.driver) + goto out; + } + if (!iface.ifname || !iface.confname) goto out; diff --git a/feeds/ipq95xx/ipq53xx/Makefile b/feeds/ipq95xx/ipq53xx/Makefile new file mode 100644 index 000000000..84f5a5356 --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/Makefile @@ -0,0 +1,27 @@ +include $(TOPDIR)/rules.mk + +ARCH:=aarch64 +BOARD:=ipq53xx +BOARDNAME:=Qualcomm Technologies, Inc IPQ53xx +FEATURES:=ubifs squashfs fpu ramdisk nand pcie usbgadget +CPU_TYPE:=cortex-a73 +CPU_SUBTYPE:=neon-vfpv4 +MAINTAINER:=John Crispin +SUBTARGETS:=generic + +KERNELNAME:=zImage Image dtbs + +KERNEL_PATCHVER:=5.4 +KERNEL_NAME_SUFFIX=-qsdk-b2d40c94fad765a48c03f492d669aeecbbb9b617 + +include $(INCLUDE_DIR)/target.mk +DEFAULT_PACKAGES += \ + uboot-envtools kmod-leds-gpio kmod-gpio-button-hotplug kmod-button-hotplug \ + kmod-usb3 swconfig kmod-qca-nss-dp \ + kmod-usb-phy-ipq5018 kmod-usb-dwc3-qcom-internal \ + kmod-qca-nss-ppe kmod-qca-ssdk-nohnat kmod-qca-psdk \ + kmod-gpio-button-hotplug iwinfo uboot-envtools swconfig \ + kmod-ath12k wpad-openssl \ + -procd-ujail + +$(eval $(call BuildTarget)) diff --git a/feeds/ipq95xx/ipq53xx/base-files/etc/board.d/01_leds b/feeds/ipq95xx/ipq53xx/base-files/etc/board.d/01_leds new file mode 100755 index 000000000..d245c44be --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/base-files/etc/board.d/01_leds @@ -0,0 +1,18 @@ +#!/bin/sh + +. /lib/functions/uci-defaults.sh + +board_config_update + +board=$(board_name) + +case "$board" in +sercomm,ap72tip) + ucidef_set_led_netdev "wan_link" "wan_link" "green:phy" "eth0" "link" + ucidef_set_led_netdev "wan_act" "wan_act" "yellow:phy" "eth0" "rx tx" + ;; +esac + +board_config_flush + +exit 0 diff --git a/feeds/ipq95xx/ipq53xx/base-files/etc/board.d/02_network b/feeds/ipq95xx/ipq53xx/base-files/etc/board.d/02_network new file mode 100755 index 000000000..1f838c8a6 --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/base-files/etc/board.d/02_network @@ -0,0 +1,24 @@ +#!/bin/sh + +. /lib/functions/uci-defaults.sh + +ipq53xx_setup_interfaces() +{ + local board="$1" + + case "$board" in + qcom,ipq9574-ap-al02-c4) + ucidef_set_interfaces_lan_wan "eth1 eth2 eth3 eth4 eth5" "eth0" + ;; + sercomm,ap72tip) + ucidef_set_interfaces_lan_wan "eth1" "eth0" + ;; + esac +} + +board_config_update +board=$(board_name) +ipq53xx_setup_interfaces $board +board_config_flush + +exit 0 diff --git a/feeds/ipq95xx/ipq53xx/base-files/etc/hotplug.d/firmware/10-ath11k-caldata b/feeds/ipq95xx/ipq53xx/base-files/etc/hotplug.d/firmware/10-ath11k-caldata new file mode 100755 index 000000000..dbbae10ba --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/base-files/etc/hotplug.d/firmware/10-ath11k-caldata @@ -0,0 +1,41 @@ +#!/bin/sh +export >> /tmp/foo + +[ -e /lib/firmware/$FIRMWARE ] && exit 0 + + +. /lib/functions.sh +. /lib/functions/system.sh + +caldata_die() { + echo "caldata: " "$*" + exit 1 +} + +caldata_extract() { + local part=$1 + local offset=$(($2)) + local count=$(($3)) + local mtd + + mtd=$(find_mtd_chardev $part) + [ -n "$mtd" ] || caldata_die "no mtd device found for partition $part" + + dd if=$mtd of=/lib/firmware/$FIRMWARE iflag=skip_bytes bs=$count skip=$offset count=1 2>/dev/null || \ + caldata_die "failed to extract calibration data from $mtd" +} + +board=$(board_name) + +case "$FIRMWARE" in +ath11k/IPQ9574/hw1.0/caldata.bin) + case "$board" in + qcom,ipq9574-ap-al02-c15) + caldata_extract "0:ART" 0x1000 0x20000 + ;; + esac + ;; +*) + exit 1 + ;; +esac diff --git a/feeds/ipq95xx/ipq53xx/base-files/etc/hotplug.d/firmware/10-ath12k-caldata b/feeds/ipq95xx/ipq53xx/base-files/etc/hotplug.d/firmware/10-ath12k-caldata new file mode 100755 index 000000000..776ae9436 --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/base-files/etc/hotplug.d/firmware/10-ath12k-caldata @@ -0,0 +1,53 @@ +#!/bin/sh +export >> /tmp/foo + +[ -e /lib/firmware/$FIRMWARE ] && exit 0 + + +. /lib/functions.sh +. /lib/functions/system.sh + +caldata_die() { + echo "caldata: " "$*" + exit 1 +} + +caldata_extract() { + local part=$1 + local offset=$(($2)) + local count=$(($3)) + local mtd + + mtd=$(find_mtd_chardev $part) + [ -n "$mtd" ] || caldata_die "no mtd device found for partition $part" + + dd if=$mtd of=/lib/firmware/$FIRMWARE iflag=skip_bytes bs=$count skip=$offset count=1 2>/dev/null || \ + caldata_die "failed to extract calibration data from $mtd" +} + +board=$(board_name) + +case "$FIRMWARE" in +ath12k/IPQ5332/hw1.0/caldata.bin) + case "$board" in + cig,wf189|\ + sercomm,ap72tip) + caldata_extract "0:ART" 0x1000 0x20000 + ;; + esac + ;; +ath12k/QCN92XX/hw1.0/cal-pci-0001:01:00.0.bin) + case "$board" in + cig,wf189) + caldata_extract "0:ART" 0x58800 0x2d000 + ;; + sercomm,ap72tip) + caldata_extract "0:ART" 0x58800 0x2d000 + #caldata_extract "0:ART" 0x26800 0x2d000 + ;; + esac + ;; +*) + exit 1 + ;; +esac diff --git a/feeds/ipq95xx/ipq53xx/base-files/etc/init.d/ath12k b/feeds/ipq95xx/ipq53xx/base-files/etc/init.d/ath12k new file mode 100755 index 000000000..07cb2142a --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/base-files/etc/init.d/ath12k @@ -0,0 +1,9 @@ +#!/bin/sh /etc/rc.common + +START=98 + +boot() { + rm /etc/config/wireless + wifi config + cp /etc/config/wireless /etc/config-shadow +} diff --git a/feeds/ipq95xx/ipq53xx/base-files/lib/upgrade/nand.sh b/feeds/ipq95xx/ipq53xx/base-files/lib/upgrade/nand.sh new file mode 100644 index 000000000..539f535c4 --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/base-files/lib/upgrade/nand.sh @@ -0,0 +1,392 @@ +# Copyright (C) 2014 OpenWrt.org +# + +. /lib/functions.sh + +# 'kernel' partition or UBI volume on NAND contains the kernel +CI_KERNPART="${CI_KERNPART:-kernel}" + +# 'ubi' partition on NAND contains UBI +CI_UBIPART="${CI_UBIPART:-ubi}" + +# 'rootfs' UBI volume on NAND contains the rootfs +CI_ROOTPART="${CI_ROOTPART:-rootfs}" + +# ipq807x qsdk kernel misbehaves +CI_IPQ807X=0 + +# update BOOTCONFIG partitions (rotate rootfs/rootfs_1) +CI_BOOTCFG=0 + +# update uboot-env if upgrade suceeded +CI_FWSETENV= + +ubi_mknod() { + local dir="$1" + local dev="/dev/$(basename $dir)" + + [ -e "$dev" ] && return 0 + + local devid="$(cat $dir/dev)" + local major="${devid%%:*}" + local minor="${devid##*:}" + mknod "$dev" c $major $minor +} + +nand_find_volume() { + local ubidevdir ubivoldir + ubidevdir="/sys/devices/virtual/ubi/$1" + [ ! -d "$ubidevdir" ] && return 1 + for ubivoldir in $ubidevdir/${1}_*; do + [ ! -d "$ubivoldir" ] && continue + if [ "$( cat $ubivoldir/name )" = "$2" ]; then + basename $ubivoldir + ubi_mknod "$ubivoldir" + return 0 + fi + done +} + +nand_find_ubi() { + local ubidevdir ubidev mtdnum + mtdnum="$( find_mtd_index $1 )" + [ ! "$mtdnum" ] && return 1 + for ubidevdir in /sys/devices/virtual/ubi/ubi*; do + [ ! -d "$ubidevdir" ] && continue + cmtdnum="$( cat $ubidevdir/mtd_num )" + [ ! "$mtdnum" ] && continue + if [ "$mtdnum" = "$cmtdnum" ]; then + ubidev=$( basename $ubidevdir ) + ubi_mknod "$ubidevdir" + echo $ubidev + return 0 + fi + done +} + +nand_get_magic_long() { + dd if="$1" skip=$2 bs=4 count=1 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"' +} + +get_magic_long_tar() { + ( tar xf $1 $2 -O | dd bs=4 count=1 | hexdump -v -n 4 -e '1/1 "%02x"') 2> /dev/null +} + +identify_magic() { + local magic=$1 + case "$magic" in + "55424923") + echo "ubi" + ;; + "31181006") + echo "ubifs" + ;; + "68737173") + echo "squashfs" + ;; + "d00dfeed") + echo "fit" + ;; + "4349"*) + echo "combined" + ;; + *) + echo "unknown $magic" + ;; + esac +} + + +identify() { + identify_magic $(nand_get_magic_long "$1" "${2:-0}") +} + +identify_tar() { + identify_magic $(get_magic_long_tar "$1" "$2") +} + +nand_restore_config() { + sync + local ubidev=$( nand_find_ubi $CI_UBIPART ) + local ubivol="$( nand_find_volume $ubidev rootfs_data )" + [ ! "$ubivol" ] && + ubivol="$( nand_find_volume $ubidev $CI_ROOTPART )" + mkdir /tmp/new_root + if ! mount -t ubifs /dev/$ubivol /tmp/new_root; then + echo "mounting ubifs $ubivol failed" + rmdir /tmp/new_root + return 1 + fi + mv "$1" "/tmp/new_root/$BACKUP_FILE" + umount /tmp/new_root + sync + rmdir /tmp/new_root +} + +nand_upgrade_prepare_ubi() { + local rootfs_length="$1" + local rootfs_type="$2" + local rootfs_data_max="$(fw_printenv -n rootfs_data_max 2>/dev/null)" + [ -n "$rootfs_data_max" ] && rootfs_data_max=$(printf %d "$rootfs_data_max") + + local kernel_length="$3" + local has_env="${4:-0}" + + [ -n "$rootfs_length" -o -n "$kernel_length" ] || return 1 + + local mtdnum="$( find_mtd_index "$CI_UBIPART" )" + if [ ! "$mtdnum" ]; then + echo "cannot find ubi mtd partition $CI_UBIPART" + return 1 + fi + + [ "$CI_IPQ807X" = 1 ] && ubidetach -f -m $mtdnum + + local ubidev="$( nand_find_ubi "$CI_UBIPART" )" + if [ ! "$ubidev" ]; then + ubiattach -m "$mtdnum" + sync + ubidev="$( nand_find_ubi "$CI_UBIPART" )" + fi + + if [ ! "$ubidev" ]; then + ubiformat /dev/mtd$mtdnum -y + ubiattach -m "$mtdnum" + sync + ubidev="$( nand_find_ubi "$CI_UBIPART" )" + [ "$has_env" -gt 0 ] && { + ubimkvol /dev/$ubidev -n 0 -N ubootenv -s 1MiB + ubimkvol /dev/$ubidev -n 1 -N ubootenv2 -s 1MiB + } + fi + + local kern_ubivol="$( nand_find_volume $ubidev $CI_KERNPART )" + local root_ubivol="$( nand_find_volume $ubidev $CI_ROOTPART )" + local data_ubivol="$( nand_find_volume $ubidev rootfs_data )" + + local ubiblk ubiblkvol + for ubiblk in /dev/ubiblock*_? ; do + [ -e "$ubiblk" ] || continue + echo "removing ubiblock${ubiblk:13}" + ubiblkvol=ubi${ubiblk:13} + if ! ubiblock -r /dev/$ubiblkvol; then + echo "cannot remove $ubiblk" + return 1 + fi + done + + # kill volumes + [ "$kern_ubivol" ] && ubirmvol /dev/$ubidev -N $CI_KERNPART || true + [ "$root_ubivol" -a "$root_ubivol" != "$kern_ubivol" ] && ubirmvol /dev/$ubidev -N $CI_ROOTPART || true + [ "$data_ubivol" ] && ubirmvol /dev/$ubidev -N rootfs_data || true + + # update kernel + if [ -n "$kernel_length" ]; then + if ! ubimkvol /dev/$ubidev -N $CI_KERNPART -s $kernel_length; then + echo "cannot create kernel volume" + return 1; + fi + fi + + # update rootfs + if [ -n "$rootfs_length" ]; then + local rootfs_size_param + if [ "$rootfs_type" = "ubifs" ]; then + rootfs_size_param="-m" + else + rootfs_size_param="-s $rootfs_length" + fi + if ! ubimkvol /dev/$ubidev -N $CI_ROOTPART $rootfs_size_param; then + echo "cannot create rootfs volume" + return 1; + fi + fi + + # create rootfs_data for non-ubifs rootfs + if [ "$rootfs_type" != "ubifs" ]; then + local availeb=$(cat /sys/devices/virtual/ubi/$ubidev/avail_eraseblocks) + local ebsize=$(cat /sys/devices/virtual/ubi/$ubidev/eraseblock_size) + local avail_size=$(( $availeb * $ebsize )) + local rootfs_data_size_param="-m" + if [ -n "$rootfs_data_max" ] && + [ "$rootfs_data_max" != "0" ] && + [ "$rootfs_data_max" -le "$avail_size" ]; then + rootfs_data_size_param="-s $rootfs_data_max" + fi + if ! ubimkvol /dev/$ubidev -N rootfs_data $rootfs_data_size_param; then + echo "cannot initialize rootfs_data volume" + return 1 + fi + fi + sync + return 0 +} + +nand_qca_update_bootconfig() { + local primary="0" + local mtdnum + local part + + [ -f /proc/boot_info/rootfs/primaryboot ] || return + [ -f /proc/boot_info/getbinary_bootconfig ] || return + + [ "$(cat /proc/boot_info/rootfs/primaryboot)" = "0" ] && primary="1" + echo "$primary" > /proc/boot_info/rootfs/primaryboot 2>/dev/null + + for part in "0:BOOTCONFIG" "0:BOOTCONFIG1"; do + mtdnum="$(find_mtd_index "$part")" + [ -c "/dev/mtd${mtdnum}" ] && { + mtd -qq write /proc/boot_info/getbinary_bootconfig \ + "/dev/mtd${mtdnum}" 2>/dev/null &&\ + echo "partition '$part' updated" + } + done +} + +nand_do_upgrade_success() { + local conf_tar="/tmp/sysupgrade.tgz" + sync + [ "$CI_BOOTCFG" = 1 ] && nand_qca_update_bootconfig + [ -n "$CI_FWSETENV" ] && fw_setenv $CI_FWSETENV + [ -f "$conf_tar" ] && nand_restore_config "$conf_tar" + echo "sysupgrade successful" + umount -a + sleep 5 + reboot -f +} + +# Flash the UBI image to MTD partition +nand_upgrade_ubinized() { + local ubi_file="$1" + local mtdnum="$(find_mtd_index "$CI_UBIPART")" + + [ ! "$mtdnum" ] && { + CI_UBIPART="rootfs" + mtdnum="$(find_mtd_index "$CI_UBIPART")" + } + + if [ ! "$mtdnum" ]; then + echo "cannot find mtd device $CI_UBIPART" + umount -a + reboot -f + fi + + local mtddev="/dev/mtd${mtdnum}" + ubidetach -p "${mtddev}" || true + sync + ubiformat "${mtddev}" -y -f "${ubi_file}" + ubiattach -p "${mtddev}" + nand_do_upgrade_success +} + +# Write the UBIFS image to UBI volume +nand_upgrade_ubifs() { + local rootfs_length=$( (cat $1 | wc -c) 2> /dev/null) + + nand_upgrade_prepare_ubi "$rootfs_length" "ubifs" "" "" + + local ubidev="$( nand_find_ubi "$CI_UBIPART" )" + local root_ubivol="$(nand_find_volume $ubidev $CI_ROOTPART)" + ubiupdatevol /dev/$root_ubivol -s $rootfs_length $1 + + nand_do_upgrade_success +} + +nand_upgrade_fit() { + local fit_file="$1" + local fit_length="$(wc -c < "$fit_file")" + + nand_upgrade_prepare_ubi "" "" "$fit_length" "1" + + local fit_ubidev="$(nand_find_ubi "$CI_UBIPART")" + local fit_ubivol="$(nand_find_volume $fit_ubidev "$CI_KERNPART")" + ubiupdatevol /dev/$fit_ubivol -s $fit_length $fit_file + + nand_do_upgrade_success +} + +nand_upgrade_tar() { + local tar_file="$1" + local kernel_mtd="$(find_mtd_index $CI_KERNPART)" + + local board_dir=$(tar tf "$tar_file" | grep -m 1 '^sysupgrade-.*/$') + board_dir=${board_dir%/} + + kernel_length=$( (tar xf "$tar_file" ${board_dir}/kernel -O | wc -c) 2> /dev/null) + local has_rootfs=0 + local rootfs_length + local rootfs_type + + tar tf "$tar_file" ${board_dir}/root 1>/dev/null 2>/dev/null && has_rootfs=1 + [ "$has_rootfs" = "1" ] && { + rootfs_length=$( (tar xf "$tar_file" ${board_dir}/root -O | wc -c) 2> /dev/null) + rootfs_type="$(identify_tar "$tar_file" ${board_dir}/root)" + } + + local has_kernel=1 + local has_env=0 + + [ "$CI_IPQ807X" = 0 -a "$kernel_length" != 0 -a -n "$kernel_mtd" ] && { + tar xf $tar_file ${board_dir}/kernel -O | mtd write - $CI_KERNPART + } + [ "$CI_IPQ807X" = 0 ] && { + [ "$kernel_length" = 0 -o ! -z "$kernel_mtd" ] && has_kernel= + } + + nand_upgrade_prepare_ubi "$rootfs_length" "$rootfs_type" "${has_kernel:+$kernel_length}" "$has_env" + + local ubidev="$( nand_find_ubi "$CI_UBIPART" )" + [ "$has_kernel" = "1" ] && { + local kern_ubivol="$( nand_find_volume $ubidev $CI_KERNPART )" + tar xf "$tar_file" ${board_dir}/kernel -O | \ + ubiupdatevol /dev/$kern_ubivol -s $kernel_length - + } + + [ "$has_rootfs" = "1" ] && { + local root_ubivol="$( nand_find_volume $ubidev $CI_ROOTPART )" + tar xf "$tar_file" ${board_dir}/root -O | \ + ubiupdatevol /dev/$root_ubivol -s $rootfs_length - + } + nand_do_upgrade_success +} + +# Recognize type of passed file and start the upgrade process +nand_do_upgrade() { + local file_type=$(identify $1) + + [ ! "$( find_mtd_index "$CI_UBIPART" )" ] && CI_UBIPART="rootfs" + + case "$file_type" in + "fit") nand_upgrade_fit $1;; + "ubi") nand_upgrade_ubinized $1;; + "ubifs") nand_upgrade_ubifs $1;; + *) nand_upgrade_tar $1;; + esac +} + +# Check if passed file is a valid one for NAND sysupgrade. Currently it accepts +# 3 types of files: +# 1) UBI - should contain an ubinized image, header is checked for the proper +# MAGIC +# 2) UBIFS - should contain UBIFS partition that will replace "rootfs" volume, +# header is checked for the proper MAGIC +# 3) TAR - archive has to include "sysupgrade-BOARD" directory with a non-empty +# "CONTROL" file (at this point its content isn't verified) +# +# You usually want to call this function in platform_check_image. +# +# $(1): board name, used in case of passing TAR file +# $(2): file to be checked +nand_do_platform_check() { + local board_name="$1" + local tar_file="$2" + local control_length=$( (tar xf $tar_file sysupgrade-$board_name/CONTROL -O | wc -c) 2> /dev/null) + local file_type="$(identify $2)" + + [ "$control_length" = 0 -a "$file_type" != "ubi" -a "$file_type" != "ubifs" -a "$file_type" != "fit" ] && { + echo "Invalid sysupgrade file." + return 1 + } + + return 0 +} diff --git a/feeds/ipq95xx/ipq53xx/base-files/lib/upgrade/platform.sh b/feeds/ipq95xx/ipq53xx/base-files/lib/upgrade/platform.sh new file mode 100644 index 000000000..a8e8388b8 --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/base-files/lib/upgrade/platform.sh @@ -0,0 +1,26 @@ +. /lib/functions/system.sh + +RAMFS_COPY_BIN='fw_printenv fw_setenv' +RAMFS_COPY_DATA='/etc/fw_env.config /var/lock/fw_printenv.lock' + +platform_check_image() { + local magic_long="$(get_magic_long "$1")" + [ "$magic_long" = "73797375" ] && return 0 + return 1 +} + +platform_do_upgrade() { + CI_UBIPART="rootfs" + CI_ROOTPART="ubi_rootfs" + CI_IPQ807X=1 + + board=$(board_name) + case $board in + cig,wf189|\ + sercomm,ap72tip|\ + qcom,ipq9574-ap-al02-c4|\ + qcom,ipq9574-ap-al02-c15) + nand_upgrade_tar "$1" + ;; + esac +} diff --git a/feeds/ipq95xx/ipq53xx/config-5.4 b/feeds/ipq95xx/ipq53xx/config-5.4 new file mode 100644 index 000000000..82db85839 --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/config-5.4 @@ -0,0 +1,1324 @@ +# CONFIG_AC97_BUS is not set +# CONFIG_AC97_BUS_NEW is not set +# CONFIG_AD7124 is not set +# CONFIG_AD7606_IFACE_PARALLEL is not set +# CONFIG_AD7606_IFACE_SPI is not set +# CONFIG_AD7768_1 is not set +# CONFIG_AD7949 is not set +# CONFIG_ADF4371 is not set +# CONFIG_ADIN_PHY is not set +# CONFIG_ADIS16460 is not set +# CONFIG_ADXL345_I2C is not set +# CONFIG_ADXL345_SPI is not set +# CONFIG_ADXL372_I2C is not set +# CONFIG_ADXL372_SPI is not set +# CONFIG_AHCI_IPQ is not set +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_ALLOC_BUFFERS_IN_4K_CHUNKS is not set +# CONFIG_ALLOC_SKB_PAGE_FRAG_DISABLE is not set +# CONFIG_AL_FIC is not set +# CONFIG_AMBA_PL08X is not set +# CONFIG_ANDROID is not set +# CONFIG_ANDROID_LOW_MEMORY_KILLER is not set +# CONFIG_ANDROID_TIMED_OUTPUT is not set +# CONFIG_APM_EMULATION is not set +# CONFIG_APQ_GCC_8084 is not set +# CONFIG_APQ_MMCC_8084 is not set +CONFIG_AQUANTIA_PHY=y +# CONFIG_AR8216_PHY is not set +# CONFIG_ARCHES is not set +CONFIG_ARCH_32BIT_OFF_T=y +# CONFIG_ARCH_AGILEX is not set +# CONFIG_ARCH_BITMAIN is not set +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y +CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y +CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y +CONFIG_ARCH_HAS_DMA_COHERENT_TO_PFN=y +CONFIG_ARCH_HAS_DMA_PREP_COHERENT=y +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y +CONFIG_ARCH_HAS_FORTIFY_SOURCE=y +CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y +# CONFIG_ARCH_HAS_KCOV is not set +CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y +CONFIG_ARCH_HAS_PHYS_TO_DMA=y +CONFIG_ARCH_HAS_SET_MEMORY=y +CONFIG_ARCH_HAS_SG_CHAIN=y +CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y +CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y +CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU=y +CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE=y +CONFIG_ARCH_HAS_TICK_BROADCAST=y +CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE=y +CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y +CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +# CONFIG_ARCH_IPQ6018 is not set +# CONFIG_ARCH_IPQ9574 is not set +CONFIG_ARCH_KEEP_MEMBLOCK=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +# CONFIG_ARCH_MDM9615 is not set +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +# CONFIG_ARCH_MILBEAUT is not set +CONFIG_ARCH_MMAP_RND_BITS=18 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS=11 +# CONFIG_ARCH_MSM8960 is not set +# CONFIG_ARCH_MSM8974 is not set +# CONFIG_ARCH_MSM8X60 is not set +CONFIG_ARCH_MULTIPLATFORM=y +# CONFIG_ARCH_MULTI_CPU_AUTO is not set +CONFIG_ARCH_MULTI_V6_V7=y +CONFIG_ARCH_MULTI_V7=y +CONFIG_ARCH_NR_GPIO=0 +CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y +CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y +CONFIG_ARCH_QCOM=y +# CONFIG_ARCH_RDA is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y +CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y +CONFIG_ARCH_SUPPORTS_UPROBES=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_USE_BUILTIN_BSWAP=y +CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y +CONFIG_ARCH_WANT_GENERAL_HUGETLB=y +CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_ARM=y +# CONFIG_ARM64_CNP is not set +# CONFIG_ARM64_ERRATUM_1165522 is not set +# CONFIG_ARM64_ERRATUM_1286807 is not set +# CONFIG_ARM64_ERRATUM_1418040 is not set +# CONFIG_ARM64_ERRATUM_1542419 is not set +# CONFIG_ARM64_MODULE_PLTS is not set +# CONFIG_ARM64_PMEM is not set +# CONFIG_ARM64_PSEUDO_NMI is not set +# CONFIG_ARM64_PTDUMP_DEBUGFS is not set +# CONFIG_ARM64_PTR_AUTH is not set +# CONFIG_ARM64_SSBD is not set +# CONFIG_ARM64_SVE is not set +# CONFIG_ARM64_TAGGED_ADDR_ABI is not set +# CONFIG_ARM64_UAO is not set +# CONFIG_ARM64_VHE is not set +CONFIG_ARM_AMBA=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +# CONFIG_ARM_ATAG_DTB_COMPAT is not set +# CONFIG_ARM_CCI is not set +# CONFIG_ARM_CCI400_COMMON is not set +# CONFIG_ARM_CCI400_PMU is not set +# CONFIG_ARM_CCI_PMU is not set +CONFIG_ARM_CPUIDLE=y +CONFIG_ARM_CPU_SUSPEND=y +# CONFIG_ARM_ERRATA_814220 is not set +# CONFIG_ARM_ERRATA_857272 is not set +CONFIG_ARM_GIC=y +CONFIG_ARM_HAS_SG_CHAIN=y +# CONFIG_ARM_HIGHBANK_CPUIDLE is not set +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ARM_L1_CACHE_SHIFT_6=y +# CONFIG_ARM_LPAE is not set +CONFIG_ARM_MODULE_PLTS=y +CONFIG_ARM_PATCH_IDIV=y +CONFIG_ARM_PATCH_PHYS_VIRT=y +CONFIG_ARM_PMU=y +CONFIG_ARM_PSCI=y +# CONFIG_ARM_PSCI_CPUIDLE is not set +CONFIG_ARM_PSCI_FW=y +CONFIG_ARM_QCOM_CPUFREQ=y +# CONFIG_ARM_QCOM_CPUFREQ_HW is not set +CONFIG_ARM_QCOM_CPUFREQ_NVMEM=y +# CONFIG_ARM_SCMI_PROTOCOL is not set +# CONFIG_ARM_SMMU is not set +# CONFIG_ARM_SP805_WATCHDOG is not set +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +CONFIG_ARM_UNWIND=y +CONFIG_ARM_VIRT_EXT=y +# CONFIG_ASHMEM is not set +CONFIG_ASYMMETRIC_KEY_TYPE=y +CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y +CONFIG_AT803X_PHY=y +# CONFIG_ATA is not set +# CONFIG_BACKLIGHT_CLASS_DEVICE is not set +# CONFIG_BATTERY_RT5033 is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_NVME=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BMP280 is not set +# CONFIG_BMP280_I2C is not set +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_BOUNCE=y +# CONFIG_BPF_KPROBE_OVERRIDE is not set +# CONFIG_BPFILTER is not set +CONFIG_BRIDGE_VLAN_FILTERING=y +# CONFIG_BT_HCIBTUSB_MTK is not set +# CONFIG_BT_MTKSDIO is not set +CONFIG_BUILD_BIN2C=y +# CONFIG_BUS_TOPOLOGY_ADHOC is not set +# CONFIG_CACHE_L2X0 is not set +# CONFIG_CAVIUM_TX2_ERRATUM_219 is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_CC_STACKPROTECTOR=y +# CONFIG_CC_STACKPROTECTOR_NONE is not set +CONFIG_CC_STACKPROTECTOR_REGULAR=y +# CONFIG_CHARGER_LT3651 is not set +# CONFIG_CHARGER_QCOM_SMBB is not set +# CONFIG_CHARGER_UCS1002 is not set +CONFIG_CLEANCACHE=y +CONFIG_CLKDEV_LOOKUP=y +CONFIG_CLKSRC_OF=y +CONFIG_CLKSRC_PROBE=y +CONFIG_CLKSRC_QCOM=y +CONFIG_CLONE_BACKWARDS=y +# CONFIG_CMA is not set +# CONFIG_CMA_ALIGNMENT is not set +# CONFIG_CMA_AREAS is not set +# CONFIG_CMA_DEBUG is not set +# CONFIG_CMA_DEBUGFS is not set +# CONFIG_CMA_SIZE_MBYTES is not set +# CONFIG_CMA_SIZE_SEL_MAX is not set +# CONFIG_CMA_SIZE_SEL_MBYTES is not set +# CONFIG_CMA_SIZE_SEL_MIN is not set +# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set +CONFIG_CNSS2=y +# CONFIG_CNSS2_QCA9574_SUPPORT is not set +# CONFIG_CNSS2_CALIBRATION_SUPPORT is not set +# CONFIG_CNSS2_DEBUG is not set +CONFIG_CNSS2_GENL=y +# CONFIG_CNSS2_PCI_DRIVER is not set +# CONFIG_CNSS2_PM is not set +# CONFIG_CNSS2_RAMDUMP is not set +# CONFIG_CNSS2_SMMU is not set +CONFIG_CNSS_QCN9000=y +CONFIG_COMMON_CLK=y +# CONFIG_COMMON_CLK_FIXED_MMIO is not set +CONFIG_COMMON_CLK_QCOM=y +# CONFIG_COMMON_CLK_SI5341 is not set +CONFIG_CONFIGFS_FS=y +CONFIG_COREDUMP=y +CONFIG_CORESIGHT=y +# CONFIG_CORESIGHT_BYTE_CNTR is not set +# CONFIG_CORESIGHT_CATU is not set +# CONFIG_CORESIGHT_CPU_DEBUG is not set +CONFIG_CORESIGHT_CSR=y +CONFIG_CORESIGHT_CTI=y +# CONFIG_CORESIGHT_CTI_SAVE_DISABLE is not set +# CONFIG_CORESIGHT_DUMMY is not set +CONFIG_CORESIGHT_HWEVENT=y +CONFIG_CORESIGHT_LINKS_AND_SINKS=y +CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y +# CONFIG_CORESIGHT_REMOTE_ETM is not set +# CONFIG_CORESIGHT_SINK_ETBV10 is not set +# CONFIG_CORESIGHT_SINK_TPIU is not set +# CONFIG_CORESIGHT_SOURCE_ETM3X is not set +CONFIG_CORESIGHT_SOURCE_ETM4X=y +CONFIG_CORESIGHT_STM=y +CONFIG_CORESIGHT_TPDA=y +CONFIG_CORESIGHT_TPDM=y +# CONFIG_CORESIGHT_TPDM_DEFAULT_ENABLE is not set +# CONFIG_COUNTER is not set +CONFIG_CPUFREQ_DT=y +CONFIG_CPUFREQ_DT_PLATDEV=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +# CONFIG_CPU_BIG_ENDIAN is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_HAS_ASID=y +# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_ICACHE_MISMATCH_WORKAROUND is not set +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y +# CONFIG_CPU_IDLE_GOV_TEO is not set +CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_PM=y +CONFIG_CPU_RMAP=y +# CONFIG_CPU_SW_DOMAIN_PAN is not set +# CONFIG_CPU_THERMAL is not set +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_V7=y +CONFIG_CRC16=y +# CONFIG_CRC32_SARWATE is not set +CONFIG_CRC32_SLICEBY8=y +CONFIG_CROSS_MEMORY_ATTACH=y +# CONFIG_CRYPTO_ADIANTUM is not set +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_DISABLE_AES192_TEST is not set +CONFIG_CRYPTO_AES_586=y +# CONFIG_CRYPTO_ALL_CASES is not set +CONFIG_CRYPTO_ARC4=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CCM=y +CONFIG_CRYPTO_CMAC=y +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_DEV_ATMEL_SHA204A is not set +# CONFIG_CRYPTO_DEV_HISI_ZIP is not set +# CONFIG_CRYPTO_DEV_OTA_CRYPTO is not set +CONFIG_CRYPTO_DEV_QCOM_ICE=y +# CONFIG_CRYPTO_DEV_QCOM_MSM_QCE is not set +# CONFIG_CRYPTO_DEV_QCOM_RNG is not set +CONFIG_CRYPTO_DISABLE_AHASH_LARGE_KEY_TEST=y +CONFIG_CRYPTO_DISABLE_AHASH_TYPE1_TESTS=y +CONFIG_CRYPTO_DISABLE_AHASH_TYPE2_TESTS=y +CONFIG_CRYPTO_DISABLE_AHASH_TYPE3_TESTS=y +CONFIG_CRYPTO_DISABLE_AUTH_SPLIT_TESTS=y +CONFIG_CRYPTO_DISABLE_HW_UNSUPPORTED_TESTS=y +CONFIG_CRYPTO_DISABLE_OUTOFPLACE_TESTS=y +CONFIG_CRYPTO_DRBG_HMAC=y +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_ECHAINIV=y +# CONFIG_CRYPTO_ECRDSA is not set +# CONFIG_CRYPTO_ESSIV is not set +CONFIG_CRYPTO_GCM=y +CONFIG_CRYPTO_GF128MUL=y +CONFIG_CRYPTO_GHASH=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_KPP2=y +CONFIG_CRYPTO_LIB_AES=y +CONFIG_CRYPTO_LIB_SHA256=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set +# CONFIG_CRYPTO_MANAGER_EXTRA_TESTS is not set +CONFIG_CRYPTO_MD5_PPC=y +CONFIG_CRYPTO_MICHAEL_MIC=y +CONFIG_CRYPTO_NO_AES_XTS_ZERO_KEY_SUPPORT=y +CONFIG_CRYPTO_NO_AES_CTR_UNEVEN_DATA_LEN_SUPPORT=y +# CONFIG_CRYPTO_NO_ZERO_LEN_HASH is not set +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_NULL2=y +CONFIG_CRYPTO_OFB=y +# CONFIG_CRYPTO_PCRYPT is not set +CONFIG_CRYPTO_RMD160=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_SEQIV=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA1_PPC=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +# CONFIG_CRYPTO_STREEBOG is not set +CONFIG_CRYPTO_WORKQUEUE=y +CONFIG_CRYPTO_XTS=y +# CONFIG_CRYPTO_XXHASH is not set +CONFIG_CRYPTO_XZ=y +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_EFI is not set +CONFIG_DEBUG_GPIO=y +# CONFIG_DEBUG_INFO_REDUCED is not set +CONFIG_DEBUG_KMEMLEAK_AUTO_SCAN=y +CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" +# CONFIG_DEBUG_MISC is not set +# CONFIG_DEBUG_PLIST is not set +# CONFIG_DEBUG_UART_8250 is not set +# CONFIG_DEBUG_USER is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEVMEM=y +# CONFIG_DIAGFWD_BRIDGE_CODE is not set +# CONFIG_DIAG_MHI is not set +CONFIG_DIAG_OVER_QRTR=y +# CONFIG_DIAG_OVER_USB is not set +CONFIG_DMADEVICES=y +# CONFIG_DMA_CMA is not set +CONFIG_DMA_ENGINE=y +CONFIG_DMA_OF=y +# CONFIG_DMA_SOUND is not set +CONFIG_DMA_VIRTUAL_CHANNELS=y +# CONFIG_DMI is not set +# CONFIG_DMIID is not set +# CONFIG_DMI_SYSFS is not set +# CONFIG_DM_REQ_CRYPT is not set +CONFIG_DM_CRYPT=y +CONFIG_DM_INIT=y +# CONFIG_DM_INLINE_CRYPT is not set +# CONFIG_DP83640_PHY is not set +# CONFIG_DPS310 is not set +CONFIG_DTC=y +# CONFIG_DWMAC_GENERIC is not set +# CONFIG_DWMAC_IPQ806X is not set +# CONFIG_DWMAC_SUNXI is not set +# CONFIG_DW_DMAC_PCI is not set +CONFIG_DYNAMIC_DEBUG=y +CONFIG_EDAC_ATOMIC_SCRUB=y +CONFIG_EDAC_SUPPORT=y +# CONFIG_EEPROM_EE1004 is not set +# CONFIG_EFI_ARMSTUB_DTB_LOADER is not set +# CONFIG_EFI_CAPSULE_LOADER is not set +# CONFIG_EFI_TEST is not set +# CONFIG_ENERGY_MODEL is not set +# CONFIG_EP_PCIE is not set +CONFIG_ETHERNET_PACKET_MANGLE=y +# CONFIG_EXPORTFS_BLOCK_OPS is not set +CONFIG_EXT4_ENCRYPTION=y +CONFIG_EXT4_FS=y +# CONFIG_EXT4_USE_FOR_EXT2 is not set +# CONFIG_EXTCON_FSA9480 is not set +CONFIG_FB=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_IMAGEBLIT=y +CONFIG_FB_CMDLINE=y +# CONFIG_FB_EFI is not set +CONFIG_FB_QTI_QPIC=y +CONFIG_FB_QTI_QPIC_ER_SSD1963_PANEL=y +CONFIG_FB_SYS_FOPS=y +# CONFIG_FIPS_ENABLE is not set +CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=y +# CONFIG_FSL_MC_BUS is not set +# CONFIG_FSL_QDMA is not set +CONFIG_FS_ENCRYPTION=y +CONFIG_FS_MBCACHE=y +# CONFIG_FS_VERITY is not set +# CONFIG_FUJITSU_ERRATUM_010001 is not set +CONFIG_FW_AUTH=y +CONFIG_FW_AUTH_TEST=m +# CONFIG_FW_LOADER_COMPRESS is not set +# CONFIG_FXAS21002C is not set +# CONFIG_FXOS8700_I2C is not set +# CONFIG_FXOS8700_SPI is not set +# CONFIG_GCC_PLUGINS is not set +# CONFIG_GCC_PLUGIN_CYC_COMPLEXITY is not set +# CONFIG_GCC_PLUGIN_LATENT_ENTROPY is not set +# CONFIG_GCC_PLUGIN_RANDSTRUCT is not set +# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF is not set +# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL is not set +# CONFIG_GCC_PLUGIN_STRUCTLEAK_USER is not set +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +# CONFIG_GENERIC_CPUFREQ_KRAIT is not set +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IO=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_MSI_IRQ_DOMAIN=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_PINCONF=y +CONFIG_GENERIC_PINCTRL_GROUPS=y +CONFIG_GENERIC_PINMUX_FUNCTIONS=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_TIME_VSYSCALL=y +# CONFIG_GEN_RTC is not set +# CONFIG_GLACIER is not set +# CONFIG_GLINK_DEBUG_FS is not set +CONFIG_GPIOLIB=y +CONFIG_GPIOLIB_IRQCHIP=y +# CONFIG_GPIO_AMD_FCH is not set +# CONFIG_GPIO_CADENCE is not set +CONFIG_GPIO_DEVRES=y +# CONFIG_GPIO_GW_PLD is not set +# CONFIG_GPIO_LATCH is not set +# CONFIG_GPIO_NXP_74HC153 is not set +CONFIG_GPIO_PCA953X=y +# CONFIG_GPIO_PCA953X_IRQ is not set +# CONFIG_GPIO_SAMA5D2_PIOBU is not set +CONFIG_GPIO_SYSFS=y +# CONFIG_GPIO_USB_DETECT is not set +# CONFIG_GSI is not set +# CONFIG_HABANA_AI is not set +CONFIG_HANDLE_DOMAIN_IRQ=y +CONFIG_HARDEN_BRANCH_PREDICTOR=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_ARCH_AUDITSYSCALL=y +CONFIG_HAVE_ARCH_BITREVERSE=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_ARCH_KGDB=y +CONFIG_HAVE_ARCH_PFN_VALID=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_ARM_ARCH_TIMER=y +# CONFIG_HAVE_ARM_SMCCC is not set +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_HAVE_BPF_JIT=y +CONFIG_HAVE_CC_STACKPROTECTOR=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_CLK_PREPARE=y +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_HAVE_DEBUG_KMEMLEAK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_HAVE_HW_BREAKPOINT=y +CONFIG_HAVE_IDE=y +CONFIG_HAVE_IOREMAP_PROT=y +CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZ4=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_HAVE_KERNEL_XZ=y +# CONFIG_HAVE_KPROBES is not set +# CONFIG_HAVE_KRETPROBES is not set +CONFIG_HAVE_MEMBLOCK=y +CONFIG_HAVE_MOD_ARCH_SPECIFIC=y +CONFIG_HAVE_NET_DSA=y +CONFIG_HAVE_OPROFILE=y +# CONFIG_HAVE_OPTPROBES is not set +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_HAVE_PERF_REGS=y +CONFIG_HAVE_PERF_USER_STACK_DUMP=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_RSEQ=y +CONFIG_HAVE_SMP=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_UID16=y +CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +# CONFIG_HEADERS_INSTALL is not set +# CONFIG_HID_MACALLY is not set +# CONFIG_HID_MALTRON is not set +# CONFIG_HID_VIEWSONIC is not set +CONFIG_HIGHMEM=y +CONFIG_HIGHPTE=y +# CONFIG_HIST_TRIGGERS is not set +CONFIG_HOTPLUG_CPU=y +CONFIG_HWSPINLOCK=y +CONFIG_HWSPINLOCK_QCOM=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_MSM_LEGACY=y +CONFIG_HZ_FIXED=0 +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_HELPER_AUTO=y +# CONFIG_I2C_NVIDIA_GPU is not set +CONFIG_I2C_QUP=y +# CONFIG_I3C is not set +# CONFIG_IGC is not set +CONFIG_IIO=y +# CONFIG_IIO_BUFFER is not set +# CONFIG_IIO_TRIGGER is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +# CONFIG_IKHEADERS is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_DM_INLINE_CRYPT is not set +# CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set +# CONFIG_INIT_ON_FREE_DEFAULT_ON is not set +# CONFIG_INPUT_GPIO_VIBRA is not set +# CONFIG_INPUT_MSM_VIBRATOR is not set +# CONFIG_INPUT_PM8941_PWRKEY is not set +# CONFIG_INPUT_PM8XXX_VIBRATOR is not set +# CONFIG_INTERCONNECT is not set +CONFIG_IOMMU_HELPER=y +# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set +# CONFIG_ION is not set +# CONFIG_ION_DUMMY is not set +# CONFIG_ION_MSM is not set +# CONFIG_ION_TEST is not set +# CONFIG_IO_URING is not set +# CONFIG_IPA is not set +# CONFIG_IPA3 is not set +# CONFIG_IPC_LOGGING is not set +CONFIG_IPC_LOG_MINIDUMP_BUFFERS=0 +# CONFIG_IPC_ROUTER is not set +# CONFIG_IPC_ROUTER_SECURITY is not set +# CONFIG_IPQ807X_REMOTEPROC is not set +# CONFIG_IPQ_ADCC_4019 is not set +# CONFIG_IPQ_ADSS_8074 is not set +# CONFIG_IPQ_APSS_PLL is not set +# CONFIG_IPQ_APSS_5018 is not set +# CONFIG_IPQ_APSS_6018 is not set +# CONFIG_IPQ_APSS_8074 is not set +# CONFIG_IPQ_APSS_9574 is not set +# CONFIG_IPQ_DWC3_QTI_EXTCON is not set +# CONFIG_IPQ_FLASH_16M_PROFILE is not set +# CONFIG_IPQ_GCC_4019 is not set +# CONFIG_IPQ_GCC_5018 is not set +# CONFIG_IPQ_GCC_6018 is not set +# CONFIG_IPQ_GCC_806X is not set +# CONFIG_IPQ_GCC_8074 is not set +# CONFIG_IPQ_GCC_9574 is not set +CONFIG_IPQ_GCC_IPQ5332=y +CONFIG_IPQ_NSSCC_IPQ5332=y +CONFIG_IPQ_APSS_IPQ5332=y +# CONFIG_IPQ_NSSCC_9574 is not set +# CONFIG_IPQ_LCC_806X is not set +# CONFIG_IPQ_REG_UPDATE is not set +# CONFIG_IPQ_REMOTEPROC_ADSP is not set +CONFIG_IPQ_SUBSYSTEM_DUMP=y +CONFIG_IPQ_SUBSYSTEM_RAMDUMP=y +# CONFIG_IPQ_SUBSYSTEM_RESTART is not set +# CONFIG_IPQ_SUBSYSTEM_RESTART_TEST is not set +CONFIG_IPQ_TCSR=y +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_TIME_ACCOUNTING=y +CONFIG_IRQ_WORK=y +CONFIG_JBD2=y +# CONFIG_KCOV is not set +CONFIG_KEYS=y +# CONFIG_KEYS_REQUEST_CACHE is not set +# CONFIG_PERSISTENT_KEYRINGS is not set +# CONFIG_BIG_KEYS is not set +# CONFIG_ENCRYPTED_KEYS is not set +CONFIG_KPSS_XCC=y +# CONFIG_KPROBE_EVENTS_ON_NOTRACE is not set +# CONFIG_KRAITCC is not set +# CONFIG_KRAIT_CLOCKS is not set +# CONFIG_KRAIT_L2_ACCESSORS is not set +# CONFIG_LCD_CLASS_DEVICE is not set +# CONFIG_LEDS_AN30259A is not set +CONFIG_LEDS_IPQ=y +# CONFIG_LEDS_LM3532 is not set +# CONFIG_LEDS_PCA9956B is not set +CONFIG_LEDS_TLC591XX=y +# CONFIG_LEDS_TRIGGER_AUDIO is not set +# CONFIG_LEDS_TRIGGER_PATTERN is not set +CONFIG_LIBFDT=y +CONFIG_LOCKUP_DETECTOR=y +# CONFIG_LOCK_EVENT_COUNTS is not set +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_LSM="lockdown,yama,loadpin,safesetid,integrity" +# CONFIG_LTC1660 is not set +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_MAILBOX=y +# CONFIG_MAILBOX_TEST is not set +# CONFIG_MAP_E_SUPPORT is not set +# CONFIG_MAX31856 is not set +# CONFIG_MAX44009 is not set +# CONFIG_MAX5432 is not set +# CONFIG_MB1232 is not set +# CONFIG_MCP3911 is not set +# CONFIG_MCP41010 is not set +CONFIG_MDIO=y +CONFIG_MDIO_BITBANG=y +CONFIG_MDIO_BOARDINFO=y +# CONFIG_MDIO_BUS_MUX_MULTIPLEXER is not set +CONFIG_MDIO_GPIO=y +CONFIG_MDIO_QCA=y +# CONFIG_MDM_GCC_9615 is not set +# CONFIG_MDM_LCC_9615 is not set +# CONFIG_MEMORY_HOTPLUG is not set +# CONFIG_MFD_LOCHNAGAR is not set +# CONFIG_MFD_MAX77650 is not set +# CONFIG_MFD_QCOM_RPM is not set +# CONFIG_MFD_ROHM_BD70528 is not set +# CONFIG_MFD_SPMI_PMIC is not set +# CONFIG_MFD_STMFX is not set +# CONFIG_MFD_STPMIC1 is not set +CONFIG_MFD_SYSCON=y +# CONFIG_MFD_TQMX86 is not set +CONFIG_MHI_BUS=y +CONFIG_MHI_BUS_DEBUG=y +CONFIG_MHI_NETDEV=y +CONFIG_MHI_QTI=y +# CONFIG_MHI_SATELLITE is not set +CONFIG_MHI_UCI=y +CONFIG_MHI_WWAN_CTRL=y +CONFIG_MIGHT_HAVE_CACHE_L2X0=y +CONFIG_MIGHT_HAVE_PCI=y +CONFIG_MIGRATION=y +# CONFIG_MIKROTIK is not set +# CONFIG_MISC_ALCOR_PCI is not set +# CONFIG_MMAP_ALLOW_UNINITIALIZED is not set +CONFIG_MMC=y +CONFIG_MMC_ARMMMCI=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_QCOM_DML=y +CONFIG_MMC_SDHCI=y +# CONFIG_MMC_SDHCI_AM654 is not set +CONFIG_MMC_SDHCI_IO_ACCESSORS=y +CONFIG_MMC_SDHCI_MSM=y +CONFIG_MMC_SDHCI_MSM_ICE=y +# CONFIG_MMC_SDHCI_MSM_ICE_PER_PART_DUN is not set +# CONFIG_MMC_SDHCI_OF_ARASAN is not set +# CONFIG_MMC_SDHCI_OF_ASPEED is not set +# CONFIG_MMC_SDHCI_PCI is not set +CONFIG_MMC_SDHCI_PLTFM=y +# CONFIG_MMC_STM32_SDMMC is not set +# CONFIG_MMC_TIFM_SD is not set +CONFIG_MODULES_TREE_LOOKUP=y +CONFIG_MODULES_USE_ELF_REL=y +# CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS is not set +# CONFIG_MPLS_ROUTING is not set +# CONFIG_MSM_ADSPRPC is not set +# CONFIG_MSM_BUS_SCALING is not set +# CONFIG_MSM_GCC_8660 is not set +# CONFIG_MSM_GCC_8916 is not set +# CONFIG_MSM_GCC_8960 is not set +# CONFIG_MSM_GCC_8974 is not set +# CONFIG_MSM_GCC_8994 is not set +# CONFIG_MSM_GCC_8996 is not set +# CONFIG_MSM_GCC_8998 is not set +# CONFIG_MSM_GLINK is not set +# CONFIG_MSM_GLINK_LOOPBACK_SERVER is not set +# CONFIG_MSM_GLINK_PKT is not set +# CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT is not set +# CONFIG_MSM_IPC_ROUTER_GLINK_XPRT is not set +# CONFIG_MSM_IPC_ROUTER_MHI_XPRT is not set +# CONFIG_MSM_LCC_8960 is not set +# CONFIG_MSM_MHI is not set +# CONFIG_MSM_MHI_DEBUG is not set +# CONFIG_MSM_MHI_DEV is not set +# CONFIG_MSM_MHI_UCI is not set +# CONFIG_MSM_MMCC_8960 is not set +# CONFIG_MSM_MMCC_8974 is not set +# CONFIG_MSM_MMCC_8996 is not set +# CONFIG_MSM_QMI_INTERFACE is not set +# CONFIG_MSM_RPM_GLINK is not set +# CONFIG_MSM_RPM_LOG is not set +# CONFIG_MSM_RPM_RPMSG is not set +# CONFIG_MSM_RPM_SMD is not set +# CONFIG_MSM_SECURE_BUFFER is not set +# CONFIG_MSM_SMEM is not set +# CONFIG_MSM_TEST_QMI_CLIENT is not set +# CONFIG_MTD_SPLIT_BCM_WFI_FW is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_HYPERBUS is not set +CONFIG_MTD_M25P80=y +# CONFIG_MTD_NAND_ECC_SW_BCH is not set +# CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC is not set +CONFIG_MTD_NAND_QCOM=y +# CONFIG_MTD_NAND_QCOM_SERIAL is not set +CONFIG_MTD_RAW_NAND=y +# CONFIG_MTD_ROUTERBOOT_PARTS is not set +CONFIG_MTD_SPINAND_GIGADEVICE=y +CONFIG_MTD_SPINAND_MT29F=y +CONFIG_MTD_SPINAND_ONDIEECC=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y +CONFIG_MTD_SPI_NOR_USE_4K_SECTORS_LIMIT=65536 +# CONFIG_MTD_SPLIT_ELF_FW is not set +CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MTD_SPLIT_FIT_FW=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_BEB_LIMIT=20 +CONFIG_MTD_UBI_BLOCK=y +# CONFIG_MTD_UBI_FASTMAP is not set +CONFIG_MTD_UBI_GLUEBI=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MULTI_IRQ_HANDLER=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEON=y +CONFIG_NET=y +# CONFIG_NET_DSA_MV88E6063 is not set +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_L3_MASTER_DEV=y +CONFIG_NET_PTP_CLASSIFY=y +# CONFIG_NET_SCH_TAPRIO is not set +CONFIG_NET_SWITCHDEV=y +# CONFIG_NET_VENDOR_GOOGLE is not set +# CONFIG_NET_VENDOR_PENSANDO is not set +# CONFIG_NF_CONNTRACK_DSCPREMARK_EXT is not set +# CONFIG_NF_IPV6_DUMMY_HEADER is not set +# CONFIG_NI_XGE_MANAGEMENT_ENET is not set +# CONFIG_NOA1305 is not set +CONFIG_NO_BOOTMEM=y +CONFIG_NO_HZ=y +CONFIG_NO_HZ_COMMON=y +CONFIG_NO_HZ_IDLE=y +CONFIG_NR_CPUS=4 +# CONFIG_NULL_TTY is not set +# CONFIG_NUMA is not set +CONFIG_NUM_ALT_PARTITION=16 +CONFIG_NVMEM=y +# CONFIG_NVMEM_REBOOT_MODE is not set +# CONFIG_NVMEM_SYSFS is not set +# CONFIG_NVME_MULTIPATH is not set +# CONFIG_NVME_TCP is not set +# CONFIG_OCTEONTX2_AF is not set +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_ADDRESS_PCI=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_KOBJ=y +CONFIG_OF_MDIO=y +CONFIG_OF_MTD=y +CONFIG_OF_NET=y +CONFIG_OF_PCI=y +CONFIG_OF_PCI_IRQ=y +CONFIG_OF_RESERVED_MEM=y +# CONFIG_OF_SLIMBUS is not set +CONFIG_OLD_SIGACTION=y +CONFIG_OLD_SIGSUSPEND3=y +# CONFIG_OPTIMIZE_INLINING is not set +# CONFIG_PACKING is not set +CONFIG_PADATA=y +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_ON_OOPS_VALUE=1 +CONFIG_PANIC_TIMEOUT=5 +CONFIG_PCI=y +# CONFIG_PCIEAER is not set +# CONFIG_PCIE_AL is not set +# CONFIG_PCIE_CADENCE_EP is not set +CONFIG_PCIE_DW=y +CONFIG_PCIE_DW_DEBUGFS=y +# CONFIG_PCIE_DW_PLAT is not set +# CONFIG_PCIE_PME is not set +CONFIG_PCIE_QCOM=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +# CONFIG_PCI_MESON is not set +CONFIG_PCI_MSI=y +CONFIG_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y +# CONFIG_PFT is not set +CONFIG_PGTABLE_LEVELS=2 +CONFIG_PHYLIB=y +# CONFIG_PHY_CADENCE_DP is not set +# CONFIG_PHY_CADENCE_DPHY is not set +# CONFIG_PHY_CADENCE_SIERRA is not set +# CONFIG_PHY_FSL_IMX8MQ_USB is not set +# CONFIG_PHY_IPQ_BALDUR_USB is not set +CONFIG_PHY_IPQ_UNIPHY_PCIE=y +# CONFIG_PHY_IPQ_UNIPHY_USB is not set +# CONFIG_PHY_MIXEL_MIPI_DPHY is not set +# CONFIG_PHY_OCELOT_SERDES is not set +# CONFIG_PHY_QCA_PCIE_QMP is not set +# CONFIG_PHY_QCOM_APQ8064_SATA is not set +# CONFIG_PHY_QCOM_IPQ806X_SATA is not set +# CONFIG_PHY_QCOM_PCIE2 is not set +# CONFIG_PHY_QCOM_QMP is not set +# CONFIG_PHY_QCOM_QUSB2 is not set +# CONFIG_PHY_QCOM_UFS is not set +CONFIG_PINCTRL=y +# CONFIG_PINCTRL_APQ8064 is not set +# CONFIG_PINCTRL_APQ8084 is not set +CONFIG_PINCTRL_IPQ5332=y +# CONFIG_PINCTRL_IPQ4019 is not set +# CONFIG_PINCTRL_IPQ5018 is not set +# CONFIG_PINCTRL_IPQ6018 is not set +# CONFIG_PINCTRL_IPQ8064 is not set +# CONFIG_PINCTRL_IPQ8074 is not set +# CONFIG_PINCTRL_IPQ9574 is not set +# CONFIG_PINCTRL_MDM9615 is not set +CONFIG_PINCTRL_MSM=y +# CONFIG_PINCTRL_MSM8660 is not set +# CONFIG_PINCTRL_MSM8916 is not set +# CONFIG_PINCTRL_MSM8960 is not set +# CONFIG_PINCTRL_MSM8994 is not set +# CONFIG_PINCTRL_MSM8996 is not set +# CONFIG_PINCTRL_MSM8998 is not set +# CONFIG_PINCTRL_OCELOT is not set +# CONFIG_PINCTRL_QCOM_SPMI_PMIC is not set +# CONFIG_PINCTRL_QCOM_SSBI_PMIC is not set +# CONFIG_PINCTRL_QCS404 is not set +# CONFIG_PINCTRL_SC7180 is not set +# CONFIG_PINCTRL_SDM660 is not set +# CONFIG_PINCTRL_SDM845 is not set +# CONFIG_PINCTRL_SINGLE is not set +# CONFIG_PINCTRL_SM8150 is not set +# CONFIG_PINCTRL_STMFX is not set +# CONFIG_PKCS7_TEST_KEY is not set +# CONFIG_PKCS7_MESSAGE_PARSER is not set +# CONFIG_PKCS8_PRIVATE_KEY_PARSER is not set +# CONFIG_PL330_DMA is not set +CONFIG_PM=y +# CONFIG_PM8916_WATCHDOG is not set +CONFIG_PM_CLK=y +# CONFIG_PM_DEBUG is not set +CONFIG_PM_GENERIC_DOMAINS=y +CONFIG_PM_GENERIC_DOMAINS_OF=y +CONFIG_PM_GENERIC_DOMAINS_SLEEP=y +CONFIG_PM_OPP=y +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_MSM=y +# CONFIG_POWER_RESET_QCOM_PON is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_HWMON is not set +CONFIG_PPS=y +CONFIG_PREEMPT=y +CONFIG_PREEMPT_COUNT=y +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_RCU=y +# CONFIG_PRINTK_CALLER is not set +CONFIG_PRINTK_TIME=y +CONFIG_PROC_PAGE_MONITOR=y +# CONFIG_PROC_STRIPPED is not set +# CONFIG_PSI is not set +CONFIG_PTP_1588_CLOCK=y +CONFIG_PUBLIC_KEY_ALGO_RSA=y +# CONFIG_PVPANIC is not set +CONFIG_PWM=y +CONFIG_PWM_IPQ=y +# CONFIG_PWM_PCA9685 is not set +CONFIG_PWM_SYSFS=y +# CONFIG_PWRSEQ_EMMC is not set +CONFIG_PWRSEQ_IPQ=y +# CONFIG_PWRSEQ_SIMPLE is not set +CONFIG_QCA_MINIDUMP=y +# CONFIG_QCA_MINIDUMP_DEBUG is not set +# CONFIG_QCOM_A53PLL is not set +CONFIG_QCOM_ADM=y +# CONFIG_QCOM_AOSS_QMP is not set +CONFIG_QCOM_APCS_IPC=y +CONFIG_QCOM_APM=y +# CONFIG_QCOM_APR is not set +CONFIG_QCOM_BAM_DMA=y +CONFIG_QCOM_CACHE_DUMP=y +CONFIG_QCOM_CACHE_DUMP_ON_PANIC=y +# CONFIG_QCOM_CLK_APCS_MSM8916 is not set +# CONFIG_QCOM_CLK_RPM is not set +# CONFIG_QCOM_CLK_SMD_RPM is not set +# CONFIG_QCOM_COINCELL is not set +# CONFIG_QCOM_COMMAND_DB is not set +CONFIG_QCOM_DLOAD_MODE=y +CONFIG_QCOM_DLOAD_MODE_APPSBL=y +# CONFIG_QCOM_EBI2 is not set +# CONFIG_QCOM_FASTRPC is not set +CONFIG_QCOM_GDSC=y +# CONFIG_QCOM_GENI_SE is not set +CONFIG_QCOM_GLINK_SSR=y +# CONFIG_QCOM_GSBI is not set +# CONFIG_QCOM_HFPLL is not set +# CONFIG_QCOM_LLCC is not set +CONFIG_QCOM_Q6V5_MPD=y +# CONFIG_QCOM_PDC is not set +# CONFIG_QCOM_PM is not set +# CONFIG_QCOM_Q6V5_ADSP is not set +# CONFIG_QCOM_Q6V5_MSS is not set +# CONFIG_QCOM_Q6V5_PAS is not set +# CONFIG_QCOM_Q6V5_WCSS is not set +CONFIG_QCOM_QFPROM=y +CONFIG_QCOM_QMI_HELPERS=y +CONFIG_QCOM_RESTART_REASON=y +# CONFIG_QCOM_RMTFS_MEM is not set +# CONFIG_QCOM_RPMH is not set +# CONFIG_QCOM_RPMPD is not set +# CONFIG_QCOM_RPM_CLK is not set +# CONFIG_QCOM_RTB is not set +CONFIG_QCOM_SCM=y +CONFIG_QCOM_SCM_32=y +# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set +# CONFIG_QCOM_SMD is not set +# CONFIG_QCOM_SMD_RPM is not set +CONFIG_QCOM_SMEM=y +CONFIG_QCOM_SMEM_STATE=y +CONFIG_QCOM_SMP2P=y +# CONFIG_QCOM_SMSM is not set +CONFIG_QCOM_SOCINFO=y +# CONFIG_QCOM_SPMI_ADC5 is not set +# CONFIG_QCOM_SPMI_TEMP_ALARM is not set +# CONFIG_QCOM_SPMI_VADC is not set +CONFIG_QCOM_SYSMON=y +CONFIG_QCOM_TSENS=y +# CONFIG_QCOM_WCNSS_CTRL is not set +# CONFIG_QCOM_WCNSS_PIL is not set +# CONFIG_QTI_BT_PIL is not set +# CONFIG_QTI_BT_INTERFACE is not set +CONFIG_QTI_HW_KEY=y +CONFIG_QTI_LICENSE_MANAGER=y +CONFIG_QCOM_WDT=y +# CONFIG_QCS_GCC_404 is not set +# CONFIG_QCS_TURING_404 is not set +CONFIG_QMI_ENCDEC=y +# CONFIG_QPNP_REVID is not set +CONFIG_QRTR=y +# CONFIG_QRTR_FIFO is not set +CONFIG_QRTR_MHI=y +CONFIG_QRTR_SMD=y +# CONFIG_QRTR_TUN is not set +# CONFIG_QRTR_USB is not set +CONFIG_QSEECOM=m +CONFIG_QTI_APSS_ACC=y +CONFIG_QTI_CTXT_SAVE=y +# CONFIG_QTI_DCC is not set +CONFIG_QTI_DCC_V2=y +CONFIG_QTI_EUD=y +# CONFIG_EUD_EXTCON_SUPPORT is not set +CONFIG_QTI_MEMORY_DUMP_V2=y +CONFIG_QTI_SCM_RESTART_REASON=y +CONFIG_QTI_TZ_LOG=y +# CONFIG_RANDOMIZE_BASE is not set +# CONFIG_RANDOM_TRUST_BOOTLOADER is not set +CONFIG_RATIONAL=y +# CONFIG_RCU_BOOST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=21 +# CONFIG_RCU_EXPERT is not set +CONFIG_RCU_STALL_COMMON=y +CONFIG_RD_GZIP=y +# CONFIG_REED_SOLOMON_TEST is not set +CONFIG_REGMAP=y +CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_CPR3=y +CONFIG_REGULATOR_CPR3_NPU=y +CONFIG_REGULATOR_CPR4_APSS=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_GPIO=y +# CONFIG_REGULATOR_IPQ40XX is not set +# CONFIG_REGULATOR_QCOM_RPM is not set +# CONFIG_REGULATOR_QCOM_SMD_RPM is not set +# CONFIG_REGULATOR_QCOM_SPMI is not set +# CONFIG_REGULATOR_QTI_GPIO is not set +# CONFIG_REGULATOR_RPM_GLINK is not set +# CONFIG_REGULATOR_RPM_SMD is not set +CONFIG_RELAY=y +CONFIG_REMOTEPROC=y +# CONFIG_RESET_ATTACK_MITIGATION is not set +CONFIG_RESET_CONTROLLER=y +# CONFIG_RESET_QCOM_AOSS is not set +# CONFIG_RESET_QCOM_PDC is not set +CONFIG_RFS_ACCEL=y +# CONFIG_RODATA_FULL_DEFAULT_ENABLED is not set +CONFIG_RPMSG=y +CONFIG_RPMSG_CHAR=y +# CONFIG_RPMSG_QCOM_GLINK_RPM is not set +CONFIG_RPMSG_QCOM_GLINK_SMEM=y +CONFIG_RPMSG_QCOM_SMD=y +# CONFIG_RPMSG_VIRTIO is not set +CONFIG_RPS=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_PM8XXX is not set +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_SAMPLES=y +# CONFIG_SAMPLE_CONFIGFS is not set +# CONFIG_SAMPLE_HW_BREAKPOINT is not set +# CONFIG_SAMPLE_KFIFO is not set +# CONFIG_SAMPLE_KOBJECT is not set +# CONFIG_SAMPLE_KPROBES is not set +# CONFIG_SAMPLE_KRETPROBES is not set +CONFIG_SAMPLE_QMI_CLIENT=m +# CONFIG_SAMPLE_RPMSG_CLIENT is not set +CONFIG_SAMPLE_TRACE_EVENTS=y +# CONFIG_SAMPLE_TRACE_PRINTK is not set +# CONFIG_SAMPLE_VFIO_MDEV_MDPY_FB is not set +# CONFIG_SATA_AHCI is not set +CONFIG_SCHED_HRTICK=y +# CONFIG_SCHED_INFO is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_MYRS is not set +CONFIG_SCSI_SCAN_ASYNC=y +# CONFIG_SDM_CAMCC_845 is not set +# CONFIG_SDM_DISPCC_845 is not set +# CONFIG_SDM_GCC_660 is not set +# CONFIG_SDM_GCC_845 is not set +# CONFIG_SDM_GPUCC_845 is not set +# CONFIG_SDM_LPASSCC_845 is not set +# CONFIG_SDM_VIDEOCC_845 is not set +# CONFIG_SEEMP_CORE is not set +# CONFIG_SENSIRION_SGP30 is not set +# CONFIG_SENSORS_DRIVETEMP is not set +# CONFIG_SENSORS_OCC_P8_I2C is not set +# CONFIG_SENSORS_RM3100_I2C is not set +# CONFIG_SENSORS_RM3100_SPI is not set +# CONFIG_SERIAL_8250 is not set +# CONFIG_SERIAL_8250_CONSOLE is not set +# CONFIG_SERIAL_8250_DMA is not set +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +# CONFIG_SERIAL_FSL_LINFLEXUART is not set +CONFIG_SERIAL_MSM=y +CONFIG_SERIAL_MSM_CONSOLE=y +# CONFIG_SERIAL_SIFIVE is not set +# CONFIG_SHUFFLE_PAGE_ALLOCATOR is not set +CONFIG_SKB_RECYCLER=y +CONFIG_SKB_RECYCLER_MULTI_CPU=y +# CONFIG_SKB_RECYCLER_PREALLOC is not set +# CONFIG_SLIMBUS is not set +# CONFIG_SLIMBUS_MSM_CTRL is not set +# CONFIG_SLIMBUS_MSM_NGD is not set +CONFIG_SMP=y +CONFIG_SMP_ON_UP=y +# CONFIG_SM_GCC_8150 is not set +CONFIG_SND=y +# CONFIG_SND_AOA is not set +# CONFIG_SND_COMPRESS_OFFLOAD is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +# CONFIG_SND_PCM is not set +# CONFIG_SND_PROC_FS is not set +CONFIG_SND_SOC=y +# CONFIG_SND_SOC_AK4118 is not set +# CONFIG_SND_SOC_APQ8016_SBC is not set +# CONFIG_SND_SOC_CS35L36 is not set +# CONFIG_SND_SOC_CS4341 is not set +# CONFIG_SND_SOC_CX2072X is not set +# CONFIG_SND_SOC_DMIC is not set +# CONFIG_SND_SOC_FSL_AUDMIX is not set +# CONFIG_SND_SOC_FSL_MICFIL is not set +# CONFIG_SND_SOC_I2C_AND_SPI is not set +CONFIG_SND_SOC_IPQ=y +# CONFIG_SND_SOC_IPQ_ADSS is not set +# CONFIG_SND_SOC_IPQ_CODEC is not set +# CONFIG_SND_SOC_IPQ_CPU_DAI is not set +# CONFIG_SND_SOC_IPQ_MBOX is not set +CONFIG_SND_SOC_IPQ_LPASS=y +# CONFIG_SND_SOC_IPQ_LPASS_PCM_RAW is not set +CONFIG_SND_SOC_IPQ9574_LPASS_PCM_RAW=y +# CONFIG_SND_SOC_IPQ_PCM_I2S is not set +# CONFIG_SND_SOC_IPQ_PCM_TDM is not set +# CONFIG_SND_SOC_IPQ_PCM_RAW is not set +# CONFIG_SND_SOC_IPQ_STEREO is not set +# CONFIG_SND_SOC_MAX98088 is not set +# CONFIG_SND_SOC_MAX98357A is not set +# CONFIG_SND_SOC_MT6358 is not set +# CONFIG_SND_SOC_MTK_BTCVSD is not set +# CONFIG_SND_SOC_NAU8822 is not set +# CONFIG_SND_SOC_PCM3060_I2C is not set +# CONFIG_SND_SOC_PCM3060_SPI is not set +CONFIG_SND_SOC_QCOM=y +# CONFIG_SND_SOC_RK3328 is not set +# CONFIG_SND_SOC_SOF_TOPLEVEL is not set +# CONFIG_SND_SOC_STORM is not set +# CONFIG_SND_SOC_UDA1334 is not set +# CONFIG_SND_SOC_WM8904 is not set +# CONFIG_SND_SOC_XILINX_AUDIO_FORMATTER is not set +# CONFIG_SND_SOC_XILINX_I2S is not set +# CONFIG_SND_SOC_XILINX_SPDIF is not set +CONFIG_SOUND=y +# CONFIG_SOUND_OSS_CORE_PRECLAIM is not set +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +# CONFIG_SPI_MTK_QUADSPI is not set +# CONFIG_SPI_QCOM_QSPI is not set +CONFIG_SPI_QUP=y +CONFIG_SPI_SPIDEV=y +# CONFIG_SPI_VSC7385 is not set +# CONFIG_SPMI is not set +# CONFIG_SPMI_MSM_PMIC_ARB is not set +# CONFIG_SPMI_PMIC_CLKDIV is not set +CONFIG_SPS=y +# CONFIG_SPS30 is not set +# CONFIG_SPS_SUPPORT_BAMDMA is not set +CONFIG_SPS_SUPPORT_NDP_BAM=y +CONFIG_SRCU=y +# CONFIG_SRD_TRACE is not set +# CONFIG_STAGING is not set +# CONFIG_STM_PROTO_BASIC is not set +# CONFIG_STM_PROTO_SYS_T is not set +# CONFIG_STM_SOURCE_FTRACE is not set +# CONFIG_STM_SOURCE_HEARTBEAT is not set +# CONFIG_STOPWATCH is not set +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_SYSTEM_EXTRA_CERTIFICATE is not set +# CONFIG_SECONDARY_TRUSTED_KEYRING is not set +CONFIG_SUSPEND=y +# CONFIG_SWAP is not set +CONFIG_SWCONFIG=y +CONFIG_SWIOTLB=y +CONFIG_SWP_EMULATE=y +# CONFIG_SW_SYNC is not set +# CONFIG_SYNC is not set +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +# CONFIG_TEST_BLACKHOLE_DEV is not set +# CONFIG_TEST_MEMCAT_P is not set +# CONFIG_TEST_MEMINIT is not set +# CONFIG_TEST_STACKINIT is not set +# CONFIG_TEST_STRSCPY is not set +# CONFIG_TEST_VMALLOC is not set +# CONFIG_TEST_XARRAY is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_THERMAL_GOV_USER_SPACE=y +CONFIG_THERMAL_HWMON=y +CONFIG_THERMAL_OF=y +CONFIG_THERMAL_WRITABLE_TRIPS=y +# CONFIG_THUMB2_KERNEL is not set +# CONFIG_TICK_CPU_ACCOUNTING is not set +# CONFIG_TI_ADS124S08 is not set +# CONFIG_TI_ADS8344 is not set +# CONFIG_TI_CPSW_PHY_SEL is not set +# CONFIG_TI_DAC7311 is not set +# CONFIG_TI_DAC7612 is not set +CONFIG_TRACING_EVENTS_GPIO=y +# CONFIG_TRUSTED_FOUNDATIONS is not set +CONFIG_UBIFS_FS=y +CONFIG_UBIFS_FS_ADVANCED_COMPR=y +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_XATTR=y +CONFIG_UBIFS_FS_XZ=y +CONFIG_UBIFS_FS_ZLIB=y +# CONFIG_UBIFS_FS_ZSTD is not set +CONFIG_UEVENT_HELPER_PATH="" +CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" +# CONFIG_UNICODE is not set +CONFIG_UNINLINE_SPIN_UNLOCK=y +# CONFIG_UNMAP_KERNEL_AT_EL0 is not set +CONFIG_UNWINDER_ARM=y +# CONFIG_UNWINDER_FRAME_POINTER is not set +# CONFIG_USB_BAM is not set +CONFIG_USB_CONFIGFS=y +# CONFIG_USB_CONFIGFS_ACM is not set +# CONFIG_USB_CONFIGFS_ECM is not set +# CONFIG_USB_CONFIGFS_ECM_SUBSET is not set +# CONFIG_USB_CONFIGFS_EEM is not set +# CONFIG_USB_CONFIGFS_F_DIAG is not set +# CONFIG_USB_CONFIGFS_F_FS is not set +# CONFIG_USB_CONFIGFS_F_HID is not set +# CONFIG_USB_CONFIGFS_F_LB_SS is not set +# CONFIG_USB_CONFIGFS_F_MIDI is not set +# CONFIG_USB_CONFIGFS_F_PRINTER is not set +# CONFIG_USB_CONFIGFS_F_QDSS is not set +# CONFIG_USB_CONFIGFS_F_UAC1 is not set +# CONFIG_USB_CONFIGFS_F_UAC1_LEGACY is not set +# CONFIG_USB_CONFIGFS_F_UAC2 is not set +# CONFIG_USB_CONFIGFS_MASS_STORAGE is not set +# CONFIG_USB_CONFIGFS_NCM is not set +# CONFIG_USB_CONFIGFS_OBEX is not set +# CONFIG_USB_CONFIGFS_RNDIS is not set +# CONFIG_USB_CONFIGFS_SERIAL is not set +# CONFIG_USB_CONN_GPIO is not set +# CONFIG_USB_DWC3_OF_SIMPLE is not set +# CONFIG_USB_EHCI_FSL is not set +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +# CONFIG_USB_GADGET is not set +# CONFIG_USB_NET_AQC111 is not set +# CONFIG_USB_OHCI_LITTLE_ENDIAN is not set +# CONFIG_USB_QCA_M31_PHY is not set +# CONFIG_USB_QCOM_8X16_PHY is not set +# CONFIG_USB_QCOM_QMP_PHY is not set +# CONFIG_USB_QCOM_QUSB_PHY is not set +CONFIG_USB_SUPPORT=y +CONFIG_USE_OF=y +# CONFIG_U_SERIAL_CONSOLE is not set +# CONFIG_VALIDATE_FS_PARSER is not set +# CONFIG_VCNL4035 is not set +CONFIG_VDSO=y +CONFIG_VECTORS_BASE=0xffff0000 +# CONFIG_VFIO is not set +CONFIG_VFP=y +CONFIG_VFPv3=y +# CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set +# CONFIG_VHOST_NET is not set +# CONFIG_VIRT_WIFI is not set +# CONFIG_VIRTIO_BLK is not set +# CONFIG_VIRTIO_CONSOLE is not set +# CONFIG_VIRTIO_FS is not set +# CONFIG_VIRTIO_NET is not set +# CONFIG_VL53L0X_I2C is not set +# CONFIG_VMAP_STACK is not set +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_WATCHDOG_CORE=y +CONFIG_WATCHDOG_OPEN_TIMEOUT=0 +# CONFIG_WL_TI is not set +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set +CONFIG_WWAN=y +CONFIG_WWAN_CORE=y +CONFIG_X509_CERTIFICATE_PARSER=y +# CONFIG_XILINX_SDFEC is not set +# CONFIG_XILINX_XADC is not set +CONFIG_XPS=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_BCJ=y +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZONE_DMA_FLAG=0 +# CONFIG_DEBUG_MEM_USAGE is not set +# CONFIG_BPF_UNPRIV_DEFAULT_OFF is not set +# CONFIG_HARDEN_BRANCH_HISTORY is not set +# CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY is not set +CONFIG_SECCRYPT=m +# CONFIG_CRYPTO_SHA1_ARM is not set +# CONFIG_CRYPTO_SHA1_ARM_NEON is not set +# CONFIG_CRYPTO_SHA1_ARM_CE is not set +# CONFIG_CRYPTO_SHA2_ARM_CE is not set +# CONFIG_CRYPTO_SHA256_ARM is not set +# CONFIG_CRYPTO_SHA512_ARM is not set +# CONFIG_CRYPTO_AES_ARM is not set +# CONFIG_CRYPTO_AES_ARM_BS is not set +# CONFIG_CRYPTO_GHASH_ARM_CE is not set +# CONFIG_CRYPTO_CRC32_ARM_CE is not set +# CONFIG_CRYPTO_CHACHA20_NEON is not set +# CONFIG_CRYPTO_NHPOLY1305_NEON is not set +# CONFIG_CRYPTO_SHA256_ARM64 is not set +# CONFIG_CRYPTO_SHA512_ARM64 is not set +# CONFIG_CRYPTO_SHA1_ARM64_CE is not set +# CONFIG_CRYPTO_SHA2_ARM64_CE is not set +# CONFIG_CRYPTO_SHA512_ARM64_CE is not set +# CONFIG_CRYPTO_SHA3_ARM64 is not set +# CONFIG_CRYPTO_SM3_ARM64_CE is not set +# CONFIG_CRYPTO_SM4_ARM64_CE is not set  +# CONFIG_CRYPTO_GHASH_ARM64_CE is not set +# CONFIG_CRYPTO_AES_ARM64 is not set +# CONFIG_CRYPTO_AES_ARM64_CE_CCM is not set +# CONFIG_CRYPTO_AES_ARM64_CE_BLK is not set +# CONFIG_CRYPTO_AES_ARM64_NEON_BLK is not set +# CONFIG_CRYPTO_AES_ARM64_BS is not set +CONFIG_BPF_JIT_ALWAYS_ON=y +CONFIG_NET_SCH_INGRESS=y +CONFIG_NET_CLS_ACT=y +CONFIG_NET_CLS_BPF=y +# CONFIG_MMC_SDHCI_MSM_ICE_PER_PART_DUN is not set +# CONFIG_NF_CONNTRACK_RTCACHE is not set +# CONFIG_PCIE_DW_DEBUGFS is not set +CONFIG_INIT_STACK_NONE=y +# CONFIG_INIT_STACK_ALL is not set +# CONFIG_SECCRYPT is not set +CONFIG_HWMON=y +# CONFIG_CORESIGHT_STREAM is not set +# CONFIG_DIAG_CHAR is not set +CONFIG_LEDS_PWM=y diff --git a/feeds/ipq95xx/ipq53xx/files/arch/arm64/boot/dts/qcom/ipq5332-cig-wf189.dts b/feeds/ipq95xx/ipq53xx/files/arch/arm64/boot/dts/qcom/ipq5332-cig-wf189.dts new file mode 100644 index 000000000..f9c8e53de --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/files/arch/arm64/boot/dts/qcom/ipq5332-cig-wf189.dts @@ -0,0 +1,437 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * IPQ5332 AP-MI01.6 board device tree source + * + * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +/dts-v1/; + +#include "ipq5332.dtsi" + +#ifdef __IPQ_MEM_PROFILE_512_MB__ +#include "ipq5332-512MB-memory.dtsi" +#else +#include "ipq5332-default-memory.dtsi" +#endif + +/ { + #address-cells = <0x2>; + #size-cells = <0x2>; + model = "CIG WF189"; + compatible = "cig,wf189", "qcom,ipq5332-ap-mi01.6", "qcom,ipq5332"; + interrupt-parent = <&intc>; + + aliases { + serial0 = &blsp1_uart0; + serial1 = &blsp1_uart1; + ethernet0 = "/soc/dp1"; + ethernet1 = "/soc/dp2"; + led-boot = &led_power; + led-failsafe = &led_power; + led-running = &led_power; + led-upgrade = &led_power; + }; + + chosen { + stdout-path = "serial0"; + }; + + soc { + pinctrl@1000000 { + serial_0_pins: serial0-pinmux { + pins = "gpio18", "gpio19"; + function = "blsp0_uart0"; + drive-strength = <8>; + bias-pull-up; + }; + + serial_1_pins: serial1-pinmux { + pins = "gpio33", "gpio34", "gpio35", "gpio36"; + function = "blsp1_uart2"; + drive-strength = <8>; + bias-pull-up; + }; + + i2c_1_pins: i2c-1-pinmux { + pins = "gpio29", "gpio30"; + function = "blsp1_i2c0"; + drive-strength = <8>; + bias-pull-up; + }; + + mdio1_pins: mdio1_pinmux { + mux_0 { + pins = "gpio27"; + function = "mdc1"; + drive-strength = <8>; + bias-disable; + }; + mux_1 { + pins = "gpio28"; + function = "mdio1"; + drive-strength = <8>; + bias-pull-up; + }; + }; + + pwm_pins: pwm_pinmux { + mux_1 { + pins = "gpio26"; + function = "pwm2"; + drive-strength = <8>; + }; + mux_2 { + pins = "gpio30"; + function = "pwm1"; + drive-strength = <8>; + }; + mux_3 { + pins = "gpio45"; + function = "pwm0"; + drive-strength = <8>; + }; + }; + + /*audio_pins_pri: audio_pinmux_pri { + mux_1 { + pins = "gpio29"; + function = "audio_pri"; + drive-strength = <8>; + bias-pull-down; + }; + + mux_2 { + pins = "gpio30"; + function = "audio_pri"; + drive-strength = <8>; + bias-pull-down; + }; + + mux_3 { + pins = "gpio31"; + function = "audio_pri"; + drive-strength = <4>; + bias-pull-down; + }; + + mux_4 { + pins = "gpio32"; + function = "audio_pri"; + drive-strength = <4>; + bias-pull-down; + }; + };*/ + + spi_2_pins: spi-2-pins { + pins = "gpio33", "gpio34", "gpio35", "gpio36"; + function = "blsp2_spi0"; + drive-strength = <8>; + bias-pull-down; + }; + + button_pins: button_pins { + rst_button { + pins = "gpio17"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + }; + }; + + dp1 { + device_type = "network"; + compatible = "qcom,nss-dp"; + qcom,id = <2>; + reg = <0x3a504000 0x4000>; + qcom,mactype = <1>; + local-mac-address = [000000000000]; + mdio-bus = <&mdio>; + qcom,phy-mdio-addr = <12>; + qcom,link-poll = <1>; + phy-mode = "sgmii"; + }; + + dp2 { + device_type = "network"; + compatible = "qcom,nss-dp"; + qcom,id = <1>; + reg = <0x3a500000 0x4000>; + qcom,mactype = <1>; + local-mac-address = [000000000000]; + mdio-bus = <&mdio>; + qcom,phy-mdio-addr = <8>; + qcom,link-poll = <1>; + phy-mode = "sgmii"; + qcom,ppe-offload-disabled = <1>; + qcom,is_switch_connected = <1>; + }; + + pwm: pwm { + pinctrl-0 = <&pwm_pins>; + pinctrl-names = "default"; + used-pwm-indices = <1>, <1>, <1>, <1>; + #pwm-cells = <2>; + status = "ok"; + }; + + mdio:mdio@90000 { + status = "ok"; + pinctrl-0 = <&mdio1_pins>; + pinctrl-names = "default"; + /*gpio51 for manhattan reset*/ + phy-reset-gpio = <&tlmm 14 0 &tlmm 20 0>; + phyaddr_fixup = <0xC90F018>; + uniphyaddr_fixup = <0xC90F014>; + mdio_clk_fixup; /* MDIO clock sequence fix up flag */ + + phy0: ethernet-phy@0 { + reg = <8>; + reset-gpios = <&tlmm 14 GPIO_ACTIVE_LOW>; + compatible ="ethernet-phy-ieee802.3-c45"; + }; + phy1: ethernet-phy@1 { + reg = <12>; + reset-gpios = <&tlmm 20 GPIO_ACTIVE_LOW>; + }; + }; + + + /*pcm: pcm@0xA3C0000{ + pinctrl-0 = <&audio_pins_pri>; + pinctrl-names = "primary"; + status = "disabled"; + };*/ + + ess-instance { + num_devices = <0x1>; + ess-switch@3a000000 { + switch_cpu_bmp = <0x1>; /* cpu port bitmap */ + switch_lan_bmp = <0x2>; /* lan port bitmap */ + switch_wan_bmp = <0x4>; /* wan port bitmap */ + switch_mac_mode = <0xd>; /* mac mode for uniphy instance0*/ + switch_mac_mode1 = <0xf>; /* mac mode for uniphy instance1*/ + switch_mac_mode2 = <0xff>; /* mac mode for uniphy instance2*/ + + qcom,port_phyinfo { + port@0 { + port_id = <1>; + phy_address = <8>; + mdiobus = <&mdio>; + ethernet-phy-ieee802.3-c45; + }; + port@1 { + port_id = <2>; + phy_address = <12>; + mdiobus = <&mdio>; + }; + }; + + }; + + }; + + /* EDMA host driver configuration for the board */ + edma@3ab00000 { + qcom,txdesc-ring-start = <4>; /* Tx desc ring start ID */ + qcom,txdesc-rings = <12>; /* Total number of Tx desc rings to be provisioned */ + qcom,txcmpl-ring-start = <4>; /* Tx complete ring start ID */ + qcom,txcmpl-rings = <12>; /* Total number of Tx complete rings to be provisioned */ + qcom,rxfill-ring-start = <4>; /* Rx fill ring start ID */ + qcom,rxfill-rings = <4>; /* Total number of Rx fill rings to be provisioned */ + qcom,rxdesc-ring-start = <12>; /* Rx desc ring start ID */ + qcom,rxdesc-rings = <4>; /* Total number of Rx desc rings to be provisioned */ + qcom,rx-page-mode = <0>; /* Rx fill ring page mode */ + qcom,tx-map-priority-level = <1>; /* Tx priority level per port */ + qcom,rx-map-priority-level = <1>; /* Rx priority level per core */ + qcom,ppeds-num = <2>; /* Number of PPEDS nodes */ + /* PPE-DS node format: */ + qcom,ppeds-map = <1 1 1 1 32 8>, /* PPEDS Node#0 ring and queue map */ + <2 2 2 2 40 8>; /* PPEDS Node#1 ring and queue map */ + qcom,txdesc-map = <8 9 10 11>, /* Port0 per-core Tx ring map */ + <12 13 14 15>, /* Port1 per-core Tx ring map */ + <4 5 6 7>; /* used only for packets from vp*/ + qcom,txdesc-fc-grp-map = <1 2>; /* Per GMAC flow control group map */ + qcom,rxfill-map = <4 5 6 7>; /* Per-core Rx fill ring map */ + qcom,rxdesc-map = <12 13 14 15>; /* Per-core Rx desc ring map */ + qcom,rx-queue-start = <0>; /* Rx queue start */ + qcom,rx-ring-queue-map = <0 8 16 24>, /* Priority 0 queues per-core Rx ring map */ + <1 9 17 25>, /* Priority 1 queues per-core Rx ring map */ + <2 10 18 26>, /* Priority 2 queues per-core Rx ring map */ + <3 11 19 27>, /* Priority 3 queues per-core Rx ring map */ + <4 12 20 28>, /* Priority 4 queues per-core Rx ring map */ + <5 13 21 29>, /* Priority 5 queues per-core Rx ring map */ + <6 14 22 30>, /* Priority 6 queues per-core Rx ring map */ + <7 15 23 31>; /* Priority 7 queues per-core Rx ring map */ + interrupts = <0 163 4>, /* Tx complete ring id #4 IRQ info */ + <0 164 4>, /* Tx complete ring id #5 IRQ info */ + <0 165 4>, /* Tx complete ring id #6 IRQ info */ + <0 166 4>, /* Tx complete ring id #7 IRQ info */ + <0 167 4>, /* Tx complete ring id #8 IRQ info */ + <0 168 4>, /* Tx complete ring id #9 IRQ info */ + <0 169 4>, /* Tx complete ring id #10 IRQ info */ + <0 170 4>, /* Tx complete ring id #11 IRQ info */ + <0 171 4>, /* Tx complete ring id #12 IRQ info */ + <0 172 4>, /* Tx complete ring id #13 IRQ info */ + <0 173 4>, /* Tx complete ring id #14 IRQ info */ + <0 174 4>, /* Tx complete ring id #15 IRQ info */ + <0 139 4>, /* Rx desc ring id #12 IRQ info */ + <0 140 4>, /* Rx desc ring id #13 IRQ info */ + <0 141 4>, /* Rx desc ring id #14 IRQ info */ + <0 142 4>, /* Rx desc ring id #15 IRQ info */ + <0 191 4>, /* Misc error IRQ info */ + <0 160 4>, /* PPEDS Node #1(TxComp ring id #1) TxComplete IRQ info */ + <0 128 4>, /* PPEDS Node #1(Rx Desc ring id #1) Rx Desc IRQ info */ + <0 152 4>, /* PPEDS Node #1(RxFill Desc ring id #1) Rx Fill IRQ info */ + <0 161 4>, /* PPEDS Node #2(TxComp ring id #2) TxComplete IRQ info */ + <0 129 4>, /* PPEDS Node #2(Rx Desc ring id #2) Rx Desc IRQ info */ + <0 153 4>; /* PPEDS Node #2(RxFill Desc ring id #2) Rx Fill IRQ info */ + }; + + serial@78af000 { + pinctrl-0 = <&serial_0_pins>; + pinctrl-names = "default"; + status = "ok"; + }; + + serial@78b0000 { + pinctrl-0 = <&serial_1_pins>; + pinctrl-names = "default"; + status = "ok"; + }; + + spi_2: spi@78b7000 { + pinctrl-0 = <&spi_2_pins>; + pinctrl-names = "default"; + cs-select = <0>; + status = "disabled"; + }; + + i2c_1: i2c@78b6000 { + pinctrl-0 = <&i2c_1_pins>; + pinctrl-names = "default"; + }; + + dma@7984000 { + status = "ok"; + }; + + nand: nand@79b0000 { + pinctrl-0 = <&qspi_nand_pins>; + pinctrl-names = "default"; + status = "ok"; + }; + + usb3@8A00000 { + status = "ok"; + qcom,multiplexed-phy; + }; + + ssuniphy_0: ssuniphy@4b0000 { + status = "ok"; + }; + + hs_m31phy_0: hs_m31phy@7b000 { + status = "ok"; + }; + + pcie1_phy_x2: phy_x2@4b1000 { + status = "ok"; + }; + + gpio_keys { + compatible = "gpio-keys"; + pinctrl-0 = <&button_pins>; + pinctrl-names = "default"; + button@1 { + label = "rst"; + linux,code = ; + gpios = <&tlmm 17 GPIO_ACTIVE_LOW>; + linux,input-type = <1>; + debounce-interval = <60>; + }; + }; + + pwmleds { + compatible = "pwm-leds"; + led1 { + label = "led1"; + pwms = <&pwm 0 10000>; + max-brightness = <255>; + }; + led_power: led2 { + label = "green:status"; + pwms = <&pwm 1 10000>; + max-brightness = <255>; + }; + led3 { + label = "led3"; + pwms = <&pwm 2 10000>; + max-brightness = <255>; + }; + led4 { + label = "led4"; + pwms = <&pwm 3 10000>; + max-brightness = <255>; + }; + }; + + wsi: wsi { + id = <0>; + num_chip = <2>; + }; + + pcie1: pcie@18000000 { + status = "ok"; + pcie1_rp { + reg = <0 0 0 0 0>; + + qcom,mhi@1 { + reg = <0 0 0 0 0>; + qti,disable-rddm-prealloc; + qti,rddm-seg-len = <0x1000>; +#if defined(__CNSS2__) + qrtr_node_id = <0x31>; + memory-region = <0>, <&mhi_region1>; +#else + memory-region = <&qcn9224_pcie1>; + qcom,board_id = <0x1019>; + qcom,wsi = <&wsi>; +#endif + }; + }; + }; + }; +}; + +&wifi0 { + qcom,rproc = <&q6_wcss_pd1>; + qcom,rproc_rpd = <&q6v5_wcss>; + qcom,multipd_arch; + qcom,userpd-subsys-name = "q6v5_wcss_userpd1"; +#if defined(__CNSS2__) + mem-region = <&q6_region>; +#else + memory-region = <&q6_region>; + qcom,wsi = <&wsi>; +#endif + qcom,board_id = <0x16>; + status = "ok"; +}; + +&mhi_region1 { + status = "ok"; +}; + +&qcn9224_pcie1 { + status = "ok"; +}; + +/* QCN9224 5G+6G */ +&wifi2 { + hremote_node = <&qcn9224_pcie1>; + board_id = <0x1019>; + status = "ok"; +}; diff --git a/feeds/ipq95xx/ipq53xx/files/arch/arm64/boot/dts/qcom/ipq5332-mi01.2.dtsi.20231011 b/feeds/ipq95xx/ipq53xx/files/arch/arm64/boot/dts/qcom/ipq5332-mi01.2.dtsi.20231011 new file mode 100644 index 000000000..fac09a225 --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/files/arch/arm64/boot/dts/qcom/ipq5332-mi01.2.dtsi.20231011 @@ -0,0 +1,396 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * IPQ5332 AP-MI01.2 board device tree source + * + * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + +#include "ipq5332.dtsi" + +/ { + aliases { + serial0 = &blsp1_uart0; /*console*/ + serial1 = &blsp1_uart1; /*ble*/ + ethernet0 = "/soc/dp1"; + ethernet1 = "/soc/dp2"; + }; + + chosen { + stdout-path = "serial0"; + }; + + soc { + pinctrl@1000000 { + serial_0_pins: serial0-pinmux { /*console*/ + pins = "gpio18", "gpio19"; + function = "blsp0_uart0"; + drive-strength = <8>; + bias-pull-up; + }; + + serial_1_pins: serial1-pinmux { /*ble*/ +// pins = "gpio33", "gpio34", "gpio35", "gpio36"; + pins = "gpio33", "gpio35"; + function = "blsp1_uart2"; + drive-strength = <8>; + bias-pull-up; + }; + + //serial_2_pins: serial2-pinmux { /*gps*/ + /* pins = "gpio33", "gpio34", "gpio35", "gpio36"; + function = "blsp1_uart1"; + drive-strength = <8>; + bias-pull-up; + };*/ + + i2c_2_pins: i2c-2-pinmux { + pins = "gpio43", "gpio45"; + function = "blsp2_i2c0"; + drive-strength = <8>; + bias-pull-up; + }; + + + spi_0_pins: spi0-pinmux { + spi_clock { + pins = "gpio14"; + function = "blsp0_spi"; + drive-strength = <8>; + bias-pull-down; + }; + + spi_mosi { + pins = "gpio15"; + function = "blsp0_spi"; + drive-strength = <8>; + bias-pull-down; + }; + + spi_miso { + pins = "gpio16"; + function = "blsp0_spi"; + drive-strength = <8>; + bias-pull-down; + }; + + spi_cs { + pins = "gpio17"; + function = "blsp0_spi"; + drive-strength = <8>; + bias-pull-up; + }; + }; + + spi_1_pins: spi_1_pins { /* tpm */ + mux { + pins = "gpio29", "gpio30", "gpio31", "gpio32"; + function = "blsp1_spi0"; + drive-strength = <8>; +// bias-disable; + bias-pull-up; + }; + }; + + mdio0_pins: mdio_pinmux { + mux_0 { + pins = "gpio25"; + function = "mdc0"; + drive-strength = <8>; + bias-disable; + }; + mux_1 { + pins = "gpio26"; + function = "mdio0"; + drive-strength = <8>; + bias-pull-up; + }; + }; + + mdio1_pins: mdio_pinmux { + mux_0 { + pins = "gpio27"; + function = "mdc1"; + drive-strength = <8>; + bias-disable; + }; + mux_1 { + pins = "gpio28"; + function = "mdio1"; + drive-strength = <8>; + bias-pull-up; + }; + }; +/* + sfp_pins: sfp_pinmux { + sfp_rx { + pins = "gpio45"; + function = "rx1"; + bias-disable; + }; + sfp_tx { + pins = "gpio24"; + function = "gpio"; + drive-strength = <8>; + bias-pull-down; + output-low; + }; + };*/ + }; + + + dp1 { + device_type = "network"; + compatible = "qcom,nss-dp"; + qcom,id = <1>; + reg = <0x3a500000 0x4000>; + qcom,mactype = <1>; + local-mac-address = [000000000000]; + mdio-bus = <&mdio>; + qcom,phy-mdio-addr = <24>; + qcom,link-poll = <1>; + phy-mode = "sgmii"; + }; + + dp2 { + device_type = "network"; + compatible = "qcom,nss-dp"; + qcom,id = <2>; + reg = <0x3a504000 0x4000>; + qcom,mactype = <1>; + local-mac-address = [000000000000]; + qcom,phy-mdio-addr = <0>; + qcom,link-poll = <1>; + phy-mode = "sgmii"; + }; + +/* dp2 { + device_type = "network"; + compatible = "qcom,nss-dp"; + qcom,id = <2>; + reg = <0x3a504000 0x4000>; + qcom,mactype = <1>; + local-mac-address = [000000000000]; + mdio-bus = <&mdio>; + qcom,phy-mdio-addr = <30>; + qcom,link-poll = <1>; + phy-mode = "sgmii"; + }; +*/ + + mdio:mdio@90000 { + status = "ok"; + pinctrl-0 = <&mdio1_pins>; + pinctrl-names = "default"; + /*gpio0 for napa, gpio3 for AQR114C*/ + phy-reset-gpio = <&tlmm 0 0 &tlmm 3 0>; + + phy0: ethernet-phy@0 { + reg = <24>; + }; + phy1: ethernet-phy@1 { //aqr114c + reg = <0>; + compatible ="ethernet-phy-ieee802.3-c45"; + }; + + }; + + ess-instance { + ess-switch@3a000000 { + pinctrl-names = "default"; + switch_cpu_bmp = <0x1>; /* cpu port bitmap */ + switch_lan_bmp = <0x0>; /* lan port bitmap */ + switch_wan_bmp = <0x6>; /* wan port bitmap */ + switch_mac_mode = <0xf>; /* mac mode for uniphy instance0*/ + switch_mac_mode1 = <0xf>; /* mac mode for uniphy instance1*/ +// switch_mac_mode1 = <0xe>; /* mac mode for uniphy instance1*/ + switch_mac_mode2 = <0xff>; /* mac mode for uniphy instance2*/ + qcom,port_phyinfo { + port@0 { + port_id = <1>; + phy_address = <24>; + }; + port@1 { //aqr114c + port_id = <2>; + phy_address = <0>; + ethernet-phy-ieee802.3-c45; + }; +/* port@1 { + port_id = <2>; + phy_address = <30>; + media-type = "sfp"; + };*/ + + }; + }; + }; + + eud@78000 { + status = "disabled"; + }; + + /* EDMA host driver configuration for the board */ + edma@3ab00000 { + qcom,txdesc-ring-start = <4>; /* Tx desc ring start ID */ + qcom,txdesc-rings = <12>; /* Total number of Tx desc rings to be provisioned */ + qcom,txcmpl-ring-start = <4>; /* Tx complete ring start ID */ + qcom,txcmpl-rings = <12>; /* Total number of Tx complete rings to be provisioned */ + qcom,rxfill-ring-start = <4>; /* Rx fill ring start ID */ + qcom,rxfill-rings = <4>; /* Total number of Rx fill rings to be provisioned */ + qcom,rxdesc-ring-start = <12>; /* Rx desc ring start ID */ + qcom,rxdesc-rings = <4>; /* Total number of Rx desc rings to be provisioned */ + qcom,rx-page-mode = <0>; /* Rx fill ring page mode */ + qcom,tx-map-priority-level = <1>; /* Tx priority level per port */ + qcom,rx-map-priority-level = <1>; /* Rx priority level per core */ + qcom,ppeds-num = <2>; /* Number of PPEDS nodes */ + /* PPE-DS node format: */ + qcom,ppeds-map = <1 1 1 1 32 8>, /* PPEDS Node#0 ring and queue map */ + <2 2 2 2 40 8>; /* PPEDS Node#1 ring and queue map */ + qcom,txdesc-map = <8 9 10 11>, /* Port0 per-core Tx ring map */ + <12 13 14 15>, /* Port1 per-core Tx ring map */ + <4 5 6 7>; /* used only for packets from vp*/ + qcom,txdesc-fc-grp-map = <1 2>; /* Per GMAC flow control group map */ + qcom,rxfill-map = <4 5 6 7>; /* Per-core Rx fill ring map */ + qcom,rxdesc-map = <12 13 14 15>; /* Per-core Rx desc ring map */ + qcom,rx-queue-start = <0>; /* Rx queue start */ + qcom,rx-ring-queue-map = <0 8 16 24>, /* Priority 0 queues per-core Rx ring map */ + <1 9 17 25>, /* Priority 1 queues per-core Rx ring map */ + <2 10 18 26>, /* Priority 2 queues per-core Rx ring map */ + <3 11 19 27>, /* Priority 3 queues per-core Rx ring map */ + <4 12 20 28>, /* Priority 4 queues per-core Rx ring map */ + <5 13 21 29>, /* Priority 5 queues per-core Rx ring map */ + <6 14 22 30>, /* Priority 6 queues per-core Rx ring map */ + <7 15 23 31>; /* Priority 7 queues per-core Rx ring map */ + interrupts = <0 163 4>, /* Tx complete ring id #4 IRQ info */ + <0 164 4>, /* Tx complete ring id #5 IRQ info */ + <0 165 4>, /* Tx complete ring id #6 IRQ info */ + <0 166 4>, /* Tx complete ring id #7 IRQ info */ + <0 167 4>, /* Tx complete ring id #8 IRQ info */ + <0 168 4>, /* Tx complete ring id #9 IRQ info */ + <0 169 4>, /* Tx complete ring id #10 IRQ info */ + <0 170 4>, /* Tx complete ring id #11 IRQ info */ + <0 171 4>, /* Tx complete ring id #12 IRQ info */ + <0 172 4>, /* Tx complete ring id #13 IRQ info */ + <0 173 4>, /* Tx complete ring id #14 IRQ info */ + <0 174 4>, /* Tx complete ring id #15 IRQ info */ + <0 139 4>, /* Rx desc ring id #12 IRQ info */ + <0 140 4>, /* Rx desc ring id #13 IRQ info */ + <0 141 4>, /* Rx desc ring id #14 IRQ info */ + <0 142 4>, /* Rx desc ring id #15 IRQ info */ + <0 191 4>, /* Misc error IRQ info */ + <0 160 4>, /* PPEDS Node #1(TxComp ring id #1) TxComplete IRQ info */ + <0 128 4>, /* PPEDS Node #1(Rx Desc ring id #1) Rx Desc IRQ info */ + <0 152 4>, /* PPEDS Node #1(RxFill Desc ring id #1) Rx Fill IRQ info */ + <0 161 4>, /* PPEDS Node #2(TxComp ring id #2) TxComplete IRQ info */ + <0 129 4>, /* PPEDS Node #2(Rx Desc ring id #2) Rx Desc IRQ info */ + <0 153 4>; /* PPEDS Node #2(RxFill Desc ring id #2) Rx Fill IRQ info */ + }; + + serial@78af000 { + pinctrl-0 = <&serial_0_pins>; + pinctrl-names = "default"; + status = "ok"; + }; + + serial@78b0000 { + pinctrl-0 = <&serial_1_pins>; + pinctrl-names = "default"; + status = "ok"; + }; + + i2c_2: i2c@78b7000 { + status = "ok"; + pinctrl-0 = <&i2c_2_pins>; + pinctrl-names = "default"; + }; + + + spi@78b5000 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + cs-select = <0>; + status = "ok"; + + m25p80@0 { + compatible = "n25q128a11"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + spi-max-frequency = <50000000>; + }; + }; + + /*tpm*/ + spi@78b6000 { + pinctrl-0 = <&spi_1_pins>; + pinctrl-names = "default"; + cs-select = <0>; + status = "ok"; + + tpm: spi-tpm@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,st33htpm-spi"; + reg = <0>; + spi-max-frequency = <20000000>; + status = "okay"; + }; + }; + + dma@7984000 { + status = "ok"; + }; + + nand@79b0000 { + pinctrl-0 = <&qspi_nand_pins>; + pinctrl-names = "default"; + status = "ok"; + }; + + usb3@8A00000 { + status = "ok"; + qcom,select-utmi-as-pipe-clk; + dwc3@8A00000 { + /delete-property/ #phy-cells; + /delete-property/ phys; + /delete-property/ phy-names; + }; + }; + + hs_m31phy@7b000 { + status = "ok"; + }; + + phy_x2@4b1000 { + status = "ok"; + }; + + wsi: wsi { + id = <0>; + num_chip = <3>; + }; + + pcie@18000000 { + status = "ok"; + pcie1_rp { + reg = <0 0 0 0 0>; + + qcom,mhi@1 { + reg = <0 0 0 0 0>; + qti,disable-rddm-prealloc; + qti,rddm-seg-len = <0x1000>; +#if defined(__CNSS2__) + qrtr_node_id = <0x31>; + memory-region = <0>, <&mhi_region1>; +#else + memory-region = <&qcn9224_pcie1>; + qcom,board_id = <0x16>; + qcom,wsi = <&wsi>; +#endif + }; + }; + }; + + }; +}; diff --git a/feeds/ipq95xx/ipq53xx/files/arch/arm64/boot/dts/qcom/ipq5332-sercomm-ap72tip.dts b/feeds/ipq95xx/ipq53xx/files/arch/arm64/boot/dts/qcom/ipq5332-sercomm-ap72tip.dts new file mode 100644 index 000000000..6e2bd7cc6 --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/files/arch/arm64/boot/dts/qcom/ipq5332-sercomm-ap72tip.dts @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * IPQ5332 AP-MI01.2 board device tree source + * + * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +/dts-v1/; + + +#ifdef __IPQ_MEM_PROFILE_512_MB__ +#include "ipq5332-512MB-memory.dtsi" +#else +#include "ipq5332-default-memory.dtsi" +#endif + +#include "ipq5332-sercomm-mi01.2.dtsi" + +/ { + #address-cells = <0x2>; + #size-cells = <0x2>; + model = "Sercomm WiFi-7"; + compatible = "sercomm,ap72tip", "qcom,ipq5332"; + interrupt-parent = <&intc>; + + aliases { + led-boot = &led_power; + led-failsafe = &led_power; + led-running = &led_power; + led-upgrade = &led_power; + }; + + soc { + phy@4b0000 { + status = "disabled"; + }; + + + pcie@20000000 { + status = "disabled"; + pcie0_rp { + reg = <0 0 0 0 0>; + qcom,mhi@2 { + reg = <0 0 0 0 0>; + qti,disable-rddm-prealloc; + qti,rddm-seg-len = <0x1000>; +#if defined(__CNSS2__) + qrtr_node_id = <0x30>; + memory-region = <0>, <&mhi_region0>; +#else + memory-region = <&qcn9224_pcie0>; + qcom,board_id = <0x15>; + qcom,wsi = <&wsi>; +#endif + }; + }; + }; + + pinctrl@1000000 { + button_pins: button_pins { + rst_button { + pins = "gpio1"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + pinctrl-0 = <&button_pins>; + pinctrl-names = "default"; + button@1 { + label = "rst"; + linux,code = ; + gpios = <&tlmm 1 GPIO_ACTIVE_LOW>; + linux,input-type = <1>; + debounce-interval = <60>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led@25 { + label = "blue:status"; + gpios = <&tca6416 9 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + led@24 { + label = "red:status"; + gpios = <&tca6416 10 GPIO_ACTIVE_HIGH>; + }; + led_power: led@16 { + label = "green:status"; + gpios = <&tca6416 11 GPIO_ACTIVE_HIGH>; + }; + led@61 { + label = "green:phy"; + gpios = <&tca6416 13 GPIO_ACTIVE_HIGH>; + }; + led@62 { + label = "yellow:phy"; + gpios = <&tca6416 14 GPIO_ACTIVE_HIGH>; + }; + }; + }; +}; + +&wifi0 { + qcom,rproc = <&q6_wcss_pd1>; + qcom,rproc_rpd = <&q6v5_wcss>; + qcom,multipd_arch; + qcom,userpd-subsys-name = "q6v5_wcss_userpd1"; +#if defined(__CNSS2__) + mem-region = <&q6_region>; +#else + memory-region = <&q6_region>; + qcom,wsi = <&wsi>; +#endif + qcom,board_id = <0x16>; //orig:0x12->0x16 + status = "ok"; +}; + +&qcn9224_pcie0 { + status = "disabled"; +}; + +&qcn9224_pcie1 { + status = "ok"; +}; + +&mhi_region0 { + status = "disabled"; +}; + +&mhi_region1 { + status = "ok"; +}; + +&wifi1 { + /* QCN9224 radio 5G */ + hremote_node = <&qcn9224_pcie0>; + board_id = <0x15>; + status = "disabled"; +}; + +&wifi2 { + /* QCN9224 5G+6G */ + hremote_node = <&qcn9224_pcie1>; + qcom,board_id = <0x100f>; //0x16->0x1019 + status = "ok"; +}; + +&i2c_0 { + tca6416: gpio@20 { + compatible = "ti,tca6416"; + reg = <0x20>; + gpio-controller; + #gpio-cells = <2>; + }; +}; diff --git a/feeds/ipq95xx/ipq53xx/files/arch/arm64/boot/dts/qcom/ipq5332-sercomm-mi01.2.dtsi b/feeds/ipq95xx/ipq53xx/files/arch/arm64/boot/dts/qcom/ipq5332-sercomm-mi01.2.dtsi new file mode 100644 index 000000000..b60d367a4 --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/files/arch/arm64/boot/dts/qcom/ipq5332-sercomm-mi01.2.dtsi @@ -0,0 +1,445 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * IPQ5332 AP-MI01.2 board device tree source + * + * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + +#include "ipq5332-sercomm.dtsi" + +/ { + aliases { + serial0 = &blsp1_uart0; /*console*/ + serial1 = &blsp1_uart1; /*ble*/ + ethernet0 = "/soc/dp1"; + ethernet1 = "/soc/dp2"; + }; + + chosen { + stdout-path = "serial0"; + }; + + soc { + pinctrl@1000000 { + serial_0_pins: serial0-pinmux { /*console*/ + pins = "gpio18", "gpio19"; + function = "blsp0_uart0"; + drive-strength = <8>; + bias-pull-up; + }; + + serial_1_pins: serial1-pinmux { /*ble*/ +// pins = "gpio33", "gpio34", "gpio35", "gpio36"; + pins = "gpio33", "gpio35"; + function = "blsp1_uart2"; + drive-strength = <8>; + bias-pull-up; + }; + + //serial_2_pins: serial2-pinmux { /*gps*/ + /* pins = "gpio33", "gpio34", "gpio35", "gpio36"; + function = "blsp1_uart1"; + drive-strength = <8>; + bias-pull-up; + };*/ + + i2c_0_pins: i2c-0-pinmux { + pins = "gpio43", "gpio45"; + function = "blsp2_i2c0"; + drive-strength = <8>; + bias-pull-up; + }; + + + spi_0_pins: spi0-pinmux { + spi_clock { + pins = "gpio14"; + function = "blsp0_spi"; + drive-strength = <8>; + bias-pull-down; + }; + + spi_mosi { + pins = "gpio15"; + function = "blsp0_spi"; + drive-strength = <8>; + bias-pull-down; + }; + + spi_miso { + pins = "gpio16"; + function = "blsp0_spi"; + drive-strength = <8>; + bias-pull-down; + }; + + spi_cs { + pins = "gpio17"; + function = "blsp0_spi"; + drive-strength = <8>; + bias-pull-up; + }; + }; + + spi_1_pins: spi_1_pins { /* tpm */ + mux { + pins = "gpio29", "gpio30", "gpio31", "gpio32"; + function = "blsp1_spi0"; + drive-strength = <8>; +// bias-disable; + bias-pull-up; + }; + }; + + mdio0_pins: mdio_pinmux { + mux_0 { + pins = "gpio25"; + function = "mdc0"; + drive-strength = <8>; + bias-disable; + }; + mux_1 { + pins = "gpio26"; + function = "mdio0"; + drive-strength = <8>; + bias-pull-up; + }; + }; + + mdio1_pins: mdio_pinmux { + mux_0 { + pins = "gpio27"; + function = "mdc1"; + drive-strength = <8>; + bias-disable; + }; + mux_1 { + pins = "gpio28"; + function = "mdio1"; + drive-strength = <8>; + bias-pull-up; + }; + }; +/* + sfp_pins: sfp_pinmux { + sfp_rx { + pins = "gpio45"; + function = "rx1"; + bias-disable; + }; + sfp_tx { + pins = "gpio24"; + function = "gpio"; + drive-strength = <8>; + bias-pull-down; + output-low; + }; + };*/ + }; + + +#if 1 //AQR114C + dp1 { + device_type = "network"; + compatible = "qcom,nss-dp"; + qcom,id = <1>; + reg = <0x3a500000 0x4000>; + qcom,mactype = <1>; + local-mac-address = [000000000000]; + mdio-bus = <&mdio>; + qcom,phy-mdio-addr = <24>; + qcom,link-poll = <1>; + phy-mode = "sgmii"; + }; + dp2 { + device_type = "network"; + compatible = "qcom,nss-dp"; + qcom,id = <2>; + reg = <0x3a504000 0x4000>; + qcom,mactype = <1>; + local-mac-address = [000000000000]; + qcom,phy-mdio-addr = <0>; + qcom,link-poll = <1>; + phy-mode = "sgmii"; + }; + + mdio:mdio@90000 { + status = "ok"; + pinctrl-0 = <&mdio1_pins>; + pinctrl-names = "default"; + /*gpio0 for napa, gpio3 for AQR114C*/ + //phy-reset-gpio = <&tlmm 0 0 &tlmm 3 0>; + phy-reset-gpio = <&tlmm 0 0>; + + phy0: ethernet-phy@0 { + reg = <24>; + }; + phy1: ethernet-phy@1 { //aqr114c + reg = <0>; + compatible ="ethernet-phy-ieee802.3-c45"; + }; + }; + + ess-instance { + ess-switch@3a000000 { + switch_cpu_bmp = <0x1>; /* cpu port bitmap */ + switch_lan_bmp = <0x0>; /* lan port bitmap */ + switch_wan_bmp = <0x6>; /* wan port bitmap */ + switch_mac_mode = <0xc>; /* mac mode for uniphy instance0*/ + switch_mac_mode1 = <0xf>; /* mac mode for uniphy instance1 114c*/ + switch_mac_mode2 = <0xff>; /* mac mode for uniphy instance2*/ + qcom,port_phyinfo { + port@0 { + port_id = <1>; + phy_address = <24>; + }; + port@1 { //aqr114c + port_id = <2>; + phy_address = <0>; + ethernet-phy-ieee802.3-c45; + }; + }; + }; + }; + +#else //SFP + + dp1 { + device_type = "network"; + compatible = "qcom,nss-dp"; + qcom,id = <1>; + reg = <0x3a500000 0x4000>; + qcom,mactype = <1>; + local-mac-address = [000000000000]; + mdio-bus = <&mdio>; + qcom,phy-mdio-addr = <24>; + qcom,link-poll = <1>; + phy-mode = "sgmii"; + }; + dp2 { + device_type = "network"; + compatible = "qcom,nss-dp"; + qcom,id = <2>; + reg = <0x3a504000 0x4000>; + qcom,mactype = <1>; + local-mac-address = [000000000000]; + mdio-bus = <&mdio>; + qcom,phy-mdio-addr = <30>; + qcom,link-poll = <1>; + phy-mode = "sgmii"; + }; + + mdio:mdio@90000 { + status = "ok"; + pinctrl-0 = <&mdio1_pins>; + pinctrl-names = "default"; + /*gpio0 for napa, gpio3 for AQR114C*/ + //phy-reset-gpio = <&tlmm 0 0 &tlmm 3 0>; + phy-reset-gpio = <&tlmm 0 0>; + + phy0: ethernet-phy@0 { + reg = <24>; + }; + }; + + ess-instance { + ess-switch@3a000000 { + switch_cpu_bmp = <0x1>; /* cpu port bitmap */ + switch_lan_bmp = <0x0>; /* lan port bitmap */ + switch_wan_bmp = <0x6>; /* wan port bitmap */ + switch_mac_mode = <0xc>; /* mac mode for uniphy instance0*/ + switch_mac_mode1 = <0xe>; /* mac mode for uniphy instance1 sfp PORT_WRAPPER_10GBASE_R*/ +// switch_mac_mode1 = <0xc>; /* mac mode for uniphy instance1 sfp PORT_WRAPPER_SGMII_PLUS*/ + switch_mac_mode2 = <0xff>; /* mac mode for uniphy instance2*/ + qcom,port_phyinfo { + port@0 { + port_id = <1>; + phy_address = <24>; + }; + port@1 { + port_id = <2>; + phy_address = <30>; + media-type = "sfp"; + }; + }; + }; + }; +#endif + + nss-macsec0 { + compatible = "qcom,nss-macsec"; + phy_addr = <24>; + mdiobus = <&mdio>; + }; + + + eud@78000 { + status = "disabled"; + }; + + /* EDMA host driver configuration for the board */ + edma@3ab00000 { + qcom,txdesc-ring-start = <4>; /* Tx desc ring start ID */ + qcom,txdesc-rings = <12>; /* Total number of Tx desc rings to be provisioned */ + qcom,txcmpl-ring-start = <4>; /* Tx complete ring start ID */ + qcom,txcmpl-rings = <12>; /* Total number of Tx complete rings to be provisioned */ + qcom,rxfill-ring-start = <4>; /* Rx fill ring start ID */ + qcom,rxfill-rings = <4>; /* Total number of Rx fill rings to be provisioned */ + qcom,rxdesc-ring-start = <12>; /* Rx desc ring start ID */ + qcom,rxdesc-rings = <4>; /* Total number of Rx desc rings to be provisioned */ + qcom,rx-page-mode = <0>; /* Rx fill ring page mode */ + qcom,tx-map-priority-level = <1>; /* Tx priority level per port */ + qcom,rx-map-priority-level = <1>; /* Rx priority level per core */ + qcom,ppeds-num = <2>; /* Number of PPEDS nodes */ + /* PPE-DS node format: */ + qcom,ppeds-map = <1 1 1 1 32 8>, /* PPEDS Node#0 ring and queue map */ + <2 2 2 2 40 8>; /* PPEDS Node#1 ring and queue map */ + qcom,txdesc-map = <8 9 10 11>, /* Port0 per-core Tx ring map */ + <12 13 14 15>, /* Port1 per-core Tx ring map */ + <4 5 6 7>; /* used only for packets from vp*/ + qcom,txdesc-fc-grp-map = <1 2>; /* Per GMAC flow control group map */ + qcom,rxfill-map = <4 5 6 7>; /* Per-core Rx fill ring map */ + qcom,rxdesc-map = <12 13 14 15>; /* Per-core Rx desc ring map */ + qcom,rx-queue-start = <0>; /* Rx queue start */ + qcom,rx-ring-queue-map = <0 8 16 24>, /* Priority 0 queues per-core Rx ring map */ + <1 9 17 25>, /* Priority 1 queues per-core Rx ring map */ + <2 10 18 26>, /* Priority 2 queues per-core Rx ring map */ + <3 11 19 27>, /* Priority 3 queues per-core Rx ring map */ + <4 12 20 28>, /* Priority 4 queues per-core Rx ring map */ + <5 13 21 29>, /* Priority 5 queues per-core Rx ring map */ + <6 14 22 30>, /* Priority 6 queues per-core Rx ring map */ + <7 15 23 31>; /* Priority 7 queues per-core Rx ring map */ + interrupts = <0 163 4>, /* Tx complete ring id #4 IRQ info */ + <0 164 4>, /* Tx complete ring id #5 IRQ info */ + <0 165 4>, /* Tx complete ring id #6 IRQ info */ + <0 166 4>, /* Tx complete ring id #7 IRQ info */ + <0 167 4>, /* Tx complete ring id #8 IRQ info */ + <0 168 4>, /* Tx complete ring id #9 IRQ info */ + <0 169 4>, /* Tx complete ring id #10 IRQ info */ + <0 170 4>, /* Tx complete ring id #11 IRQ info */ + <0 171 4>, /* Tx complete ring id #12 IRQ info */ + <0 172 4>, /* Tx complete ring id #13 IRQ info */ + <0 173 4>, /* Tx complete ring id #14 IRQ info */ + <0 174 4>, /* Tx complete ring id #15 IRQ info */ + <0 139 4>, /* Rx desc ring id #12 IRQ info */ + <0 140 4>, /* Rx desc ring id #13 IRQ info */ + <0 141 4>, /* Rx desc ring id #14 IRQ info */ + <0 142 4>, /* Rx desc ring id #15 IRQ info */ + <0 191 4>, /* Misc error IRQ info */ + <0 160 4>, /* PPEDS Node #1(TxComp ring id #1) TxComplete IRQ info */ + <0 128 4>, /* PPEDS Node #1(Rx Desc ring id #1) Rx Desc IRQ info */ + <0 152 4>, /* PPEDS Node #1(RxFill Desc ring id #1) Rx Fill IRQ info */ + <0 161 4>, /* PPEDS Node #2(TxComp ring id #2) TxComplete IRQ info */ + <0 129 4>, /* PPEDS Node #2(Rx Desc ring id #2) Rx Desc IRQ info */ + <0 153 4>; /* PPEDS Node #2(RxFill Desc ring id #2) Rx Fill IRQ info */ + }; + + serial@78af000 { + pinctrl-0 = <&serial_0_pins>; + pinctrl-names = "default"; + status = "ok"; + }; + + serial@78b0000 { + pinctrl-0 = <&serial_1_pins>; + pinctrl-names = "default"; + status = "ok"; + }; + + i2c_0: i2c@78b7000 { + status = "ok"; + pinctrl-0 = <&i2c_0_pins>; + pinctrl-names = "default"; + }; + + + spi@78b5000 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + cs-select = <0>; + status = "ok"; + + m25p80@0 { + compatible = "n25q128a11"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + spi-max-frequency = <50000000>; + }; + }; + + /*tpm*/ + spi@78b6000 { + pinctrl-0 = <&spi_1_pins>; + pinctrl-names = "default"; + cs-select = <0>; + status = "ok"; + + tpm: spi-tpm@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,st33htpm-spi"; + reg = <0>; + spi-max-frequency = <20000000>; + status = "okay"; + }; + }; + + dma@7984000 { + status = "ok"; + }; + + nand@79b0000 { + pinctrl-0 = <&qspi_nand_pins>; + pinctrl-names = "default"; + status = "ok"; + }; + + usb3@8A00000 { + status = "ok"; + qcom,select-utmi-as-pipe-clk; + dwc3@8A00000 { + /delete-property/ #phy-cells; + /delete-property/ phys; + /delete-property/ phy-names; + }; + }; + + hs_m31phy@7b000 { + status = "ok"; + }; + + phy_x2@4b1000 { + status = "ok"; + }; + + wsi: wsi { + id = <0>; + num_chip = <2>; + }; + + pcie@18000000 { + status = "ok"; + pcie1_rp { + reg = <0 0 0 0 0>; + + qcom,mhi@1 { + reg = <0 0 0 0 0>; + qti,disable-rddm-prealloc; + qti,rddm-seg-len = <0x1000>; +#if defined(__CNSS2__) + qrtr_node_id = <0x31>; + memory-region = <0>, <&mhi_region1>; +#else + memory-region = <&qcn9224_pcie1>; + qcom,board_id = <0x100f>; + qcom,wsi = <&wsi>; +#endif + }; + }; + }; + + }; +}; diff --git a/feeds/ipq95xx/ipq53xx/files/arch/arm64/boot/dts/qcom/ipq5332-sercomm.dtsi b/feeds/ipq95xx/ipq53xx/files/arch/arm64/boot/dts/qcom/ipq5332-sercomm.dtsi new file mode 100644 index 000000000..9b4a33e6f --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/files/arch/arm64/boot/dts/qcom/ipq5332-sercomm.dtsi @@ -0,0 +1,2701 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * IPQ5332 device tree source + * + * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/ { + #address-cells = <2>; + #size-cells = <2>; + interrupt-parent = <&intc>; + + clocks { + sleep_clk: sleep-clk { + compatible = "fixed-clock"; + clock-frequency = <32000>; + #clock-cells = <0>; + }; + + xo: xo { + compatible = "fixed-clock"; + clock-frequency = <24000000>; + #clock-cells = <0>; + }; + + usb3phy_0_cc_pipe_clk: usb3phy_0_cc_pipe_clk { + compatible = "fixed-clock"; + clock-frequency = <250000000>; + #clock-cells = <0>; + }; + + pcie3x2_phy_pipe_clk: pcie3x2_phy_pipe_clk { + compatible = "fixed-clock"; + clock-frequency = <250000000>; + #clock-cells = <0>; + }; + + pcie3x1_0_phy_pipe_clk: pcie3x1_0_phy_pipe_clk { + compatible = "fixed-clock"; + clock-frequency = <250000000>; + #clock-cells = <0>; + }; + + pcie3x1_1_phy_pipe_clk: pcie3x1_1_phy_pipe_clk { + compatible = "fixed-clock"; + clock-frequency = <250000000>; + #clock-cells = <0>; + }; + + cmn_pll_nss_clk_200m: cmn_pll_nss_clk_200m { + compatible = "fixed-clock"; + clock-frequency = <200000000>; + #clock-cells = <0>; + }; + + cmn_pll_nss_clk_300m: cmn_pll_nss_clk_300m { + compatible = "fixed-clock"; + clock-frequency = <300000000>; + #clock-cells = <0>; + }; + + gcc_gpll0_out_aux: gcc_gpll0_out_aux { + compatible = "fixed-clock"; + clock-frequency = <800000000>; + #clock-cells = <0>; + }; + }; + + cpus: cpus { + #address-cells = <1>; + #size-cells = <0>; + + CPU0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x0>; + enable-method = "psci"; + next-level-cache = <&L2_0>; + clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; + operating-points-v2 = <&cpu_opp_table>; + }; + + CPU1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + enable-method = "psci"; + reg = <0x1>; + next-level-cache = <&L2_0>; + clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; + operating-points-v2 = <&cpu_opp_table>; + }; + + CPU2: cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + enable-method = "psci"; + reg = <0x2>; + next-level-cache = <&L2_0>; + clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; + operating-points-v2 = <&cpu_opp_table>; + }; + + CPU3: cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + enable-method = "psci"; + reg = <0x3>; + next-level-cache = <&L2_0>; + clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; + operating-points-v2 = <&cpu_opp_table>; + }; + + L2_0: l2-cache { + compatible = "cache"; + cache-level = <0x2>; + }; + + cpu_opp_table: cpu_opp_table { + compatible = "operating-points-v2-ipq5332"; + opp-shared; + nvmem-cells = <&cpu_speed_bin>; + nvmem-cell-names = "speed_bin"; + + /* + * Listed all supported CPU frequencies and opp-supported-hw + * values to select CPU frequencies based on the limits fused. + * ------------------------------------------------------------ + * Frequency BIT3 BIT2 BIT1 BIT0 opp-supported-hw + * 1.0GHz 1.2GHz 1.5GHz No Limit + * ------------------------------------------------------------ + * 1100000000 1 1 1 1 0xF + * 1500000000 0 0 1 1 0x3 + * ----------------------------------------------------------- + */ + + opp-1100000000 { + opp-hz = /bits/ 64 <1100000000>; + opp-microvolt = <850000>; + opp-supported-hw = <0xF>; + clock-latency-ns = <200000>; + }; + + opp-1500000000 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <950000>; + opp-supported-hw = <0x3>; + clock-latency-ns = <200000>; + }; + }; + }; + + firmware { + qfprom { + compatible = "qcom,qfprom-sec"; + img-addr = <0x4A100000>; + img-size = <0x00500000>; + scm-cmd-id = <0x1F>; + }; + }; + + qcn9224_legacy_irq0: qcn9224_legacy_irq0 { + compatible = "qcom,qcn9224_legacy_irq"; + status = "ok"; + qrtr_node_id = <0x30>; + qcn9224_in0: legacy_interrupt { + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + qcn9224_legacy_irq1: qcn9224_legacy_irq1 { + compatible = "qcom,qcn9224_legacy_irq"; + status = "ok"; + qrtr_node_id = <0x31>; + qcn9224_in1: legacy_interrupt { + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + soc: soc { + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0 0xffffffff>; + dma-ranges; + compatible = "simple-bus"; + + eud@78000 { + compatible = "qcom,msm-eud"; + reg = <0x78000 0x1000>, + <0x79000 0x2000>, + <0x7a000 0x1000>; + reg-names = "eud_base", + "eud_mode_mgr", + "eud_mode_mgr2"; + interrupts = ; + interrupt-names = "eud_irq"; + qcom,eud-clock-vote-req = <1>; + clocks = <&gcc GCC_USB0_PHY_CFG_AHB_CLK>; + clock-names = "eud_ahb2phy_clk"; + status = "disabled"; + }; + + hs_m31phy_0: hs_m31phy@7b000 { + compatible = "qca,ipq5332-m31-usb-hsphy"; + reg = <0x07b000 0x12C>, + <0x08af8800 0x400>; + reg-names = "m31usb_phy_base", + "qscratch_base"; + phy_type= "utmi"; + + resets = <&gcc GCC_QUSB2_0_PHY_BCR>; + reset-names = "usb2_phy_reset"; + + status = "disabled"; + }; + + ssuniphy_0: ssuniphy@4b0000 { + compatible = "qca,ipq5332-uni-ssphy"; + reg = <0x4b0000 0x800>; + clocks = <&gcc GCC_USB0_PIPE_CLK>, + <&gcc GCC_USB0_PHY_CFG_AHB_CLK>, + <&gcc GCC_PCIE3X1_PHY_AHB_CLK>; + + clock-names = "pipe_clk", "phy_cfg_ahb_clk", + "phy_ahb_clk"; + + resets = <&gcc GCC_USB0_PHY_BCR>; + reset-names = "por_rst"; + #phy-cells = <0>; + status = "disabled"; + }; + + prng: prng@e3000 { + compatible = "qcom,msm-rng"; + reg = <0xe3000 0x1000>; + clocks = <&gcc GCC_PRNG_AHB_CLK>; + clock-names = "km_clk_src"; + qcom,no-qrng-config; + }; + + pcie0_phy: phy@4b0000{ + compatible = "qca,uni-pcie-phy-gen3"; + reg = <0x4b0000 0x800>; + phy-type = "gen3"; + #phy-cells = <0>; + clocks = <&gcc GCC_PCIE3X1_0_PIPE_CLK>, + <&gcc GCC_SNOC_PCIE3_1LANE_M_CLK>, + <&gcc GCC_SNOC_PCIE3_1LANE_S_CLK>, + <&gcc GCC_PCIE3X1_PHY_AHB_CLK>; + + clock-names = "pipe_clk", + "lane_m_clk", + "lane_s_clk", + "phy_ahb_clk"; + + resets = <&gcc GCC_PCIE3X1_0_PHY_BCR>, + <&gcc GCC_PCIE3X1_0_PHY_PHY_BCR>, + <&gcc GCC_PCIE3X1_PHY_AHB_CLK_ARES>; + reset-names = "phy", + "phy_phy", + "phy_ahb"; + mode-fixed = <2>; /* TBD */ + status = "disabled"; + }; + + /* PHY for PCIE1 single lane mode */ + pcie1_phy: phy@4b1000 { + compatible = "qca,uni-pcie-phy-gen3"; + reg = <0x4b1000 0x800>; + phy-type = "gen3"; + #phy-cells = <0>; + qti,multiplexed-phy; + qti,phy-mux-regs = <&tcsr_q6_block 0x2544>; + phy-ahb-shared-reset; + clocks = <&gcc GCC_PCIE3X2_PIPE_CLK>, + <&gcc GCC_SNOC_PCIE3_2LANE_M_CLK>, + <&gcc GCC_SNOC_PCIE3_2LANE_S_CLK>, + <&gcc GCC_PCIE3X2_PHY_AHB_CLK>; + + clock-names = "pipe_clk", + "lane_m_clk", + "lane_s_clk", + "phy_ahb_clk"; + + resets = <&gcc GCC_PCIE3X2_PHY_BCR>, + <&gcc GCC_PCIE3X2_PHY_AHB_CLK_ARES>; + reset-names = "phy", + "phy_ahb"; + mode-fixed = <2>; /* TBD */ + status = "disabled"; + }; + + /* PHY for PCIE2 single lane mode */ + pcie2_phy: phy@4b1800 { + compatible = "qca,uni-pcie-phy-gen3"; + reg = <0x4b1800 0x800>; + phy-type = "gen3"; + #phy-cells = <0>; + phy-ahb-shared-reset; + + qti,multiplexed-phy; + qti,phy-mux-regs = <&tcsr_q6_block 0x2544>; + + clocks = <&gcc GCC_PCIE3X1_1_PIPE_CLK>, + <&gcc GCC_SNOC_PCIE3_1LANE_1_M_CLK>, + <&gcc GCC_SNOC_PCIE3_1LANE_1_S_CLK>, + <&gcc GCC_PCIE3X2_PHY_AHB_CLK>; + + clock-names = "pipe_clk", + "lane_m_clk", + "lane_s_clk", + "phy_ahb_clk"; + + resets = <&gcc GCC_PCIE3X1_1_PHY_BCR>, + <&gcc GCC_PCIE3X2_PHY_AHB_CLK_ARES>; + reset-names = "phy", + "phy_ahb"; + mode-fixed = <2>; /* TBD */ + status = "disabled"; + }; + + + /* PHY for PCIE1 dual lane mode */ + pcie1_phy_x2: phy_x2@4b1000 { + compatible = "qca,uni-pcie-phy-gen3"; + reg = <0x4b1000 0x1000>; + phy-type = "gen3"; + #phy-cells = <0>; + clocks = <&gcc GCC_PCIE3X2_PIPE_CLK>, + <&gcc GCC_SNOC_PCIE3_2LANE_M_CLK>, + <&gcc GCC_SNOC_PCIE3_2LANE_S_CLK>, + <&gcc GCC_PCIE3X2_PHY_AHB_CLK>; + + clock-names = "pipe_clk", + "lane_m_clk", + "lane_s_clk", + "phy_ahb_clk"; + + resets = <&gcc GCC_PCIE3X2_PHY_BCR>, + <&gcc GCC_PCIE3X2_PHY_AHB_CLK_ARES>; + reset-names = "phy", + "phy_ahb"; + mode-fixed = <2>; /* TBD */ + x2 = <1>; + status = "disabled"; + }; + + seccrypt: qcom,seccrypt { + compatible = "qcom,seccrypt"; + status = "ok"; + }; + + intc: interrupt-controller@b000000 { + compatible = "qcom,msm-qgic2"; + interrupt-controller; + #interrupt-cells = <0x3>; + reg = <0x0b000000 0x1000>, /*GICD*/ + <0x0b002000 0x1000>, /*GICC*/ + <0x0b001000 0x1000>, /*GICH*/ + <0x0b004000 0x1000>; /*GICV*/ + interrupts = ; + ranges = <0 0x0b00c000 0x3000>; + + v2m0: v2m@0 { + compatible = "arm,gic-v2m-frame"; + msi-controller; + reg = <0x0 0xffd>; + }; + + v2m1: v2m@1 { + compatible = "arm,gic-v2m-frame"; + msi-controller; + reg = <0x1000 0xffd>; + }; + + v2m2: v2m@2 { + compatible = "arm,gic-v2m-frame"; + msi-controller; + reg = <0x2000 0xffd>; + }; + }; + + lpass: lpass@0xA000000{ + compatible = "qca,lpass-ipq5332"; + reg = <0xA000000 0x3BFFFF>; + clocks = <&gcc GCC_LPASS_SWAY_CLK>, + <&gcc GCC_LPASS_CORE_AXIM_CLK>, + <&gcc GCC_SNOC_LPASS_CFG_CLK>, + <&gcc GCC_PCNOC_LPASS_CLK>; + clock-names = "sway", "axim", "snoc_cfg", "pcnoc"; + resets = <&gcc GCC_LPASS_BCR>; + reset-names = "lpass"; + status = "disabled"; + }; + + pcm: pcm@0xA3C0000{ + compatible = "qca,ipq5332-lpass-pcm"; + reg = <0xA3C0000 0x23014>; + status = "disabled"; + + pcm0: pcm0@0 { + interrupts = <0 370 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "out0"; + capture_memory = "lpm"; + playback_memory = "lpm"; + voice_loopback = <0>; + slave = <0>; + status = "disabled"; + }; + + pcm1: pcm1@1 { + interrupts = <0 371 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "out1"; + capture_memory = "lpm"; + playback_memory = "lpm"; + voice_loopback = <0>; + slave = <0>; + status = "disabled"; + }; + + }; + + pcm_lb: pcm_lb@0 { + compatible = "qca,ipq5332-pcm-lb"; + status = "disabled"; + }; + + mdio@90000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "qcom,qca-mdio", "qcom,ipq40xx-mdio"; + reg = <0x90000 0x64>; + clocks = <&gcc GCC_MDIO_AHB_CLK>, + <&gcc GCC_UNIPHY0_AHB_CLK>, + <&gcc GCC_UNIPHY0_SYS_CLK>, + <&gcc GCC_UNIPHY1_AHB_CLK>, + <&gcc GCC_UNIPHY1_SYS_CLK>; + clock-names = "gcc_mdio_ahb_clk", + "uniphy0_ahb_clk", + "uniphy0_sys_clk", + "uniphy1_ahb_clk", + "uniphy1_sys_clk"; + status = "disabled"; + }; + + ess-instance { + compatible = "qcom,ess-instance"; + ess-switch@3a000000 { + compatible = "qcom,ess-switch-ipq53xx"; + switch_access_mode = "local bus"; + reg = <0x3a000000 0x1000000>; + bm_tick_mode = <0>; /* bm tick mode */ + tm_tick_mode = <0>; /* tm tick mode */ + clocks = <&gcc GCC_CMN_12GPLL_AHB_CLK>, + <&gcc GCC_CMN_12GPLL_SYS_CLK>, + <&gcc GCC_UNIPHY0_AHB_CLK>, + <&gcc GCC_UNIPHY0_SYS_CLK>, + <&gcc GCC_UNIPHY1_AHB_CLK>, + <&gcc GCC_UNIPHY1_SYS_CLK>, + <&gcc GCC_NSSNOC_NSSCC_CLK>, + <&gcc GCC_NSSCC_CLK>, + <&gcc GCC_NSSNOC_SNOC_1_CLK>, + <&gcc GCC_NSSNOC_SNOC_CLK>, + <&gcc GCC_IM_SLEEP_CLK>, + <&nsscc NSS_CC_PORT1_MAC_CLK>, + <&nsscc NSS_CC_PORT2_MAC_CLK>, + <&nsscc NSS_CC_PPE_SWITCH_CLK>, + <&nsscc NSS_CC_PPE_SWITCH_CFG_CLK>, + <&nsscc NSS_CC_NSSNOC_PPE_CLK>, + <&nsscc NSS_CC_NSSNOC_PPE_CFG_CLK>, + <&nsscc NSS_CC_PPE_EDMA_CLK>, + <&nsscc NSS_CC_PPE_EDMA_CFG_CLK>, + <&nsscc NSS_CC_PPE_SWITCH_IPE_CLK>, + <&nsscc NSS_CC_PPE_SWITCH_BTQ_CLK>, + <&nsscc NSS_CC_PORT1_RX_CLK>, + <&nsscc NSS_CC_PORT1_TX_CLK>, + <&nsscc NSS_CC_PORT2_RX_CLK>, + <&nsscc NSS_CC_PORT2_TX_CLK>, + <&nsscc NSS_CC_UNIPHY_PORT1_RX_CLK>, + <&nsscc NSS_CC_UNIPHY_PORT1_TX_CLK>, + <&nsscc NSS_CC_UNIPHY_PORT2_RX_CLK>, + <&nsscc NSS_CC_UNIPHY_PORT2_TX_CLK>; + clock-names = "cmn_ahb_clk", + "cmn_sys_clk", + "uniphy0_ahb_clk", + "uniphy0_sys_clk", + "uniphy1_ahb_clk", + "uniphy1_sys_clk", + "gcc_nssnoc_nsscc_clk", + "gcc_nsscc_clk", + "gcc_nssnoc_snoc_1_clk", + "gcc_nssnoc_snoc_clk", + "gcc_im_sleep_clk", + "port1_mac_clk", + "port2_mac_clk", + "nss_ppe_clk", + "nss_ppe_cfg_clk", + "nssnoc_ppe_clk", + "nssnoc_ppe_cfg_clk", + "nss_edma_clk", + "nss_edma_cfg_clk", + "nss_ppe_ipe_clk", + "nss_ppe_btq_clk", + "nss_port1_rx_clk", + "nss_port1_tx_clk", + "nss_port2_rx_clk", + "nss_port2_tx_clk", + "uniphy0_port1_rx_clk", + "uniphy0_port1_tx_clk", + "uniphy1_port5_rx_clk", + "uniphy1_port5_tx_clk"; + resets = <&nsscc NSS_CC_PPE_BCR>, + <&gcc GCC_UNIPHY0_BCR>, + <&gcc GCC_UNIPHY1_BCR>, + <&gcc GCC_UNIPHY0_AHB_CLK_ARES>, + <&gcc GCC_UNIPHY1_AHB_CLK_ARES>, + <&gcc GCC_UNIPHY0_SYS_CLK_ARES>, + <&gcc GCC_UNIPHY1_SYS_CLK_ARES>, + <&gcc GCC_UNIPHY0_XPCS_ARES>, + <&gcc GCC_UNIPHY1_XPCS_ARES>, + <&nsscc NSS_CC_UNIPHY_PORT1_RX_CLK_ARES>, + <&nsscc NSS_CC_UNIPHY_PORT1_TX_CLK_ARES>, + <&nsscc NSS_CC_UNIPHY_PORT2_RX_CLK_ARES>, + <&nsscc NSS_CC_UNIPHY_PORT2_TX_CLK_ARES>, + <&nsscc NSS_CC_PORT1_RX_CLK_ARES>, + <&nsscc NSS_CC_PORT1_TX_CLK_ARES>, + <&nsscc NSS_CC_PORT2_RX_CLK_ARES>, + <&nsscc NSS_CC_PORT2_TX_CLK_ARES>, + <&nsscc NSS_CC_PORT1_MAC_CLK_ARES>, + <&nsscc NSS_CC_PORT2_MAC_CLK_ARES>; + reset-names = "ppe_rst", + "uniphy0_soft_rst", + "uniphy1_soft_rst", + "uniphy0_ahb_rst", + "uniphy1_ahb_rst", + "uniphy0_sys_rst", + "uniphy1_sys_rst", + "uniphy0_xpcs_rst", + "uniphy1_xpcs_rst", + "uniphy_port1_rx_rst", + "uniphy_port1_tx_rst", + "uniphy_port2_rx_rst", + "uniphy_port2_tx_rst", + "nss_port1_rx_rst", + "nss_port1_tx_rst", + "nss_port2_rx_rst", + "nss_port2_tx_rst", + "nss_port1_mac_rst", + "nss_port2_mac_rst"; + + port_scheduler_resource { + port@0 { + port_id = <0>; + ucast_queue = <0 43>; + mcast_queue = <256 262>; + l0sp = <0 6>; + l0cdrr = <0 27>; + l0edrr = <0 27>; + l1cdrr = <0 0>; + l1edrr = <0 0>; + }; + port@1 { + port_id = <1>; + ucast_queue = <204 211>; + mcast_queue = <272 275>; + l0sp = <51 52>; + l0cdrr = <108 115>; + l0edrr = <108 115>; + l1cdrr = <23 24>; + l1edrr = <23 24>; + }; + port@2 { + port_id = <2>; + ucast_queue = <212 219>; + mcast_queue = <276 279>; + l0sp = <53 54>; + l0cdrr = <116 123>; + l0edrr = <116 123>; + l1cdrr = <25 26>; + l1edrr = <25 26>; + }; + reserved { + ucast_queue = <44 203>; + mcast_queue = <263 271>; + l0sp = <7 50>; + l0cdrr = <28 107>; + l0edrr = <28 107>; + l1cdrr = <1 22>; + l1edrr = <1 22>; + }; + }; + + port_scheduler_config { + port@0 { + port_id = <0>; + l1scheduler { + group@0 { + /* L0 SP */ + sp = <0 1 2 3 4 5 6>; + /* cpri cdrr epri edrr */ + cfg = <0 0 0 0>; + }; + }; + l0scheduler { + group@0 { + /* unicast queue */ + ucast_queue = <0>; + ucast_loop_pri = <4>; + /* multicast queue */ + mcast_queue = <256>; + /* sp cpri cdrr epri edrr */ + cfg = <0 0 0 0 0>; + }; + group@1 { + ucast_queue = <4>; + ucast_loop_pri = <4>; + cfg = <0 0 0 0 0>; + }; + group@2 { + ucast_queue = <8>; + ucast_loop_pri = <4>; + mcast_queue = <257>; + cfg = <1 0 4 0 4>; + }; + group@3 { + ucast_queue = <12>; + ucast_loop_pri = <4>; + cfg = <1 0 4 0 4>; + }; + group@4 { + ucast_queue = <16>; + ucast_loop_pri = <4>; + mcast_queue = <258>; + cfg = <2 0 8 0 8>; + }; + group@5 { + ucast_queue = <20>; + ucast_loop_pri = <4>; + cfg = <2 0 8 0 8>; + }; + group@6 { + ucast_queue = <24>; + ucast_loop_pri = <4>; + mcast_queue = <259>; + cfg = <3 0 12 0 12>; + }; + group@7 { + ucast_queue = <28>; + ucast_loop_pri = <4>; + cfg = <3 0 12 0 12>; + }; + group@8 { + ucast_queue = <32>; + ucast_loop_pri = <4>; + mcast_queue = <260>; + cfg = <4 0 16 0 16>; + }; + group@9 { + ucast_queue = <36>; + ucast_loop_pri = <4>; + mcast_queue = <261>; + cfg = <5 0 20 0 20>; + }; + group@10 { + ucast_queue = <40>; + ucast_loop_pri = <4>; + mcast_queue = <262>; + cfg = <6 0 24 0 24>; + }; + }; + }; + port@1 { + port_id = <1>; + l1scheduler { + group@0 { + sp = <51>; + cfg = <0 23 0 23>; + }; + group@1 { + sp = <52>; + cfg = <1 24 1 24>; + }; + }; + l0scheduler { + group@0 { + ucast_queue = <204>; + ucast_loop_pri = <8>; + /* max priority per SP */ + ucast_max_pri = <4>; + mcast_queue = <272>; + mcast_loop_pri = <4>; + cfg = <51 0 108 0 108>; + }; + }; + }; + port@2 { + port_id = <2>; + l1scheduler { + group@0 { + sp = <53>; + cfg = <0 25 0 25>; + }; + group@1 { + sp = <54>; + cfg = <1 26 1 26>; + }; + }; + l0scheduler { + group@0 { + ucast_queue = <212>; + ucast_loop_pri = <8>; + ucast_max_pri = <4>; + mcast_queue = <276>; + mcast_loop_pri = <4>; + cfg = <53 0 116 0 116>; + }; + }; + }; + }; + }; + }; + + edma@3ab00000 { + compatible = "qcom,edma"; + reg = <0x3ab00000 0xed000>; + reg-names = "edma-reg-base"; + reset-names = "edma_rst"; + clocks = <&nsscc NSS_CC_NSS_CSR_CLK>, + <&nsscc NSS_CC_NSSNOC_NSS_CSR_CLK>, + <&nsscc NSS_CC_CE_APB_CLK>, + <&nsscc NSS_CC_CE_AXI_CLK>, + <&nsscc NSS_CC_NSSNOC_CE_APB_CLK>, + <&nsscc NSS_CC_NSSNOC_CE_AXI_CLK>, + <&gcc GCC_NSS_TS_CLK>, + <&gcc GCC_NSSCC_CLK>, + <&gcc GCC_NSSCFG_CLK>, + <&gcc GCC_NSSNOC_ATB_CLK>, + <&gcc GCC_NSSNOC_NSSCC_CLK>, + <&gcc GCC_NSSNOC_PCNOC_1_CLK>, + <&gcc GCC_NSSNOC_QOSGEN_REF_CLK>, + <&gcc GCC_NSSNOC_SNOC_1_CLK>, + <&gcc GCC_NSSNOC_SNOC_CLK>, + <&gcc GCC_NSSNOC_TIMEOUT_REF_CLK>, + <&gcc GCC_NSSNOC_XO_DCD_CLK>, + <&gcc GCC_SNOC_NSSNOC_CLK>, + <&gcc GCC_SNOC_NSSNOC_1_CLK>, + <&gcc GCC_MEM_NOC_AHB_CLK>, + <&gcc GCC_MEM_NOC_SNOC_AXI_CLK>, + <&gcc GCC_MEM_NOC_APSS_AXI_CLK>, + <&gcc GCC_MEM_NOC_QOSGEN_EXTREF_CLK>, + <&gcc GCC_MEM_NOC_TS_CLK>; + clock-names = "nss-csr-clk", "nss-nssnoc-csr-clk", "nss-ce-ahb-clk", + "nss-ce-axi-clk", "nss-nssnoc-ce-ahb-clk", "nss-nssnoc-ce-axi-clk", + "nss-ts-clk", "nss-nsscc-clk", "nss-nsscfg-clk", "nss-nssnoc-atb-clk", + "nss-nssnoc-nsscc-clk", "nss-nssnoc-pcnoc-1-clk", "nss-nssnoc-qosgen-ref-clk", + "nss-nssnoc-snoc-1-clk", "nss-nssnoc-snoc-clk", "nss-nssnoc-timeout-ref-clk", + "nss-nssnoc-xo-dcd-clk", "nss-snoc-nssnoc-clk", "nss-snoc-nssnoc-1-clk", + "nss-mem-noc-ahb-clk", "nss-mem-noc-snoc-axi-clk", "nss-mem-noc-apss-axi-clk", + "nss-mem-noc-qosgen-extref-clk","nss-mem-noc-ts-clk"; + }; + + ess-uniphy@7a00000 { + compatible = "qcom,ess-uniphy"; + reg = <0x7a00000 0x20000>; + uniphy_access_mode = "local bus"; + }; + + nss-ppe { + compatible = "qcom,nss-ppe"; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + clock-frequency = <24000000>; + }; + + watchdog: watchdog@b017000 { + compatible = "qcom,kpss-wdt"; + reg = <0xb017000 0x1000>; + interrupts = ; + clocks = <&sleep_clk>; + }; + + timer@b120000 { + #address-cells = <1>; + #size-cells = <1>; + ranges; + compatible = "arm,armv7-timer-mem"; + reg = <0xb120000 0x1000>; + clock-frequency = <24000000>; + + frame@b120000 { + frame-number = <0>; + interrupts = , + ; + reg = <0xb121000 0x1000>, + <0xb122000 0x1000>; + }; + + frame@b123000 { + frame-number = <1>; + interrupts = ; + reg = <0xb123000 0x1000>; + status = "disabled"; + }; + + frame@b124000 { + frame-number = <2>; + interrupts = ; + reg = <0xb124000 0x1000>; + status = "disabled"; + }; + + frame@b125000 { + frame-number = <3>; + interrupts = ; + reg = <0xb125000 0x1000>; + status = "disabled"; + }; + + frame@b126000 { + frame-number = <4>; + interrupts = ; + reg = <0xb126000 0x1000>; + status = "disabled"; + }; + + frame@b127000 { + frame-number = <5>; + interrupts = ; + reg = <0xb127000 0x1000>; + status = "disabled"; + }; + + frame@b128000 { + frame-number = <6>; + interrupts = ; + reg = <0xb128000 0x1000>; + status = "disabled"; + }; + }; + + tlmm: pinctrl@1000000 { + compatible = "qcom,ipq5332-pinctrl"; + reg = <0x01000000 0x300000>; + interrupts = ; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&tlmm 0 0 53>; + interrupt-controller; + #interrupt-cells = <2>; + emmc_pins: emmc_pins { + emmc_clk { + pins = "gpio13"; + function = "sdc_clk"; + drive-strength = <8>; + bias-disable; + }; + emmc_cmd { + pins = "gpio12"; + function = "sdc_cmd"; + drive-strength = <8>; + bias-pull-up; + }; + emmc_data { + pins = "gpio8", "gpio9", "gpio10", + "gpio11"; + function = "sdc_data"; + drive-strength = <8>; + bias-pull-up; + }; + }; + + pci0_pin: pci0-pinmux { + pins = "gpio38"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + output-low; + }; + + pci1_pin: pci1-pinmux { + pins = "gpio47"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + output-low; + }; + + pci2_pin: pci2-pinmux { + pins = "gpio44"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + output-low; + }; + + qspi_nand_pins: qspi_nand_pins { + qspi_clock { + pins = "gpio13"; + function = "qspi_clk"; + drive-strength = <8>; + bias-pull-down; + }; + + qspi_cs { + pins = "gpio12"; + function = "qspi_cs"; + drive-strength = <8>; + bias-pull-up; + }; + + qspi_data { + pins = "gpio8", "gpio9", "gpio10", "gpio11"; + function = "qspi_data"; + drive-strength = <8>; + bias-pull-down; + }; + }; + +/* button_pins: button_pins { + wps_button { + pins = "gpio35"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + };*/ + + bt_pins: bt_pins { + PTA_0 { + pins = "gpio49"; + function = "PTA_0"; + drive-strength = <8>; + bias-disable; + }; + PTA_1 { + pins = "gpio50"; + function = "PTA_1"; + drive-strength = <8>; + bias-disable; + }; + PTA_2 { + pins = "gpio51"; + function = "PTA_2"; + drive-strength = <8>; + bias-disable; + }; +/* bt_reset { + pins = "gpio32"; + function = "gpio"; + drive-strength = <8>; + bias-pull-down; + };*/ + + }; + }; + + gcc: gcc@1800000 { + compatible = "qcom,gcc-ipq5332"; + reg = <0x1800000 0x80000>; + clocks = <&xo>, + <&sleep_clk>, + <&usb3phy_0_cc_pipe_clk>, + <&pcie3x2_phy_pipe_clk>, + <&pcie3x1_0_phy_pipe_clk>, + <&pcie3x1_1_phy_pipe_clk>; + clock-names = "xo", + "sleep_clk", + "usb3phy_0_cc_pipe_clk", + "pcie3x2_phy_pipe_clk", + "pcie3x1_0_phy_pipe_clk", + "pcie3x1_1_phy_pipe_clk"; + #clock-cells = <0x1>; + #reset-cells = <0x1>; + }; + + nsscc: nsscc@39b00000{ + compatible = "qcom,nsscc-ipq5332"; + reg = <0x39b00000 0x80000>; + clocks = <&xo>, + <&cmn_pll_nss_clk_200m>, + <&cmn_pll_nss_clk_300m>, + <&gcc_gpll0_out_aux>; + clock-names = "xo", + "cmn_pll_nss_clk_200m", + "cmn_pll_nss_clk_300m", + "gcc_gpll0_out_aux"; + #clock-cells = <0x1>; + #reset-cells = <0x1>; + }; + + dcc@797f000 { + compatible = "qcom,dcc-v2-ipq5332"; + reg = <0x40ff000 0x1000>, + <0x4080000 0x800>; + reg-names = "dcc-base", "dcc-ram-base"; + dcc-ram-offset = <0x0>; + status = "disabled"; + }; + + pwm { + compatible = "qti,ipq5332-pwm"; + reg = <0x1941010 0x20>; + clocks = <&gcc GCC_ADSS_PWM_CLK>; + clock-names = "core"; + src-freq = <100000000>; + pwm-base-index = <0>; + used-pwm-indices = <1>, <1>, <1>, <1>; + status = "disabled"; + }; + + blsp_dma: dma@7884000 { + compatible = "qcom,bam-v1.7.0"; + reg = <0x07884000 0x1d000>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "bam_clk"; + #dma-cells = <1>; + qcom,ee = <0>; + }; + + blsp1_uart0: serial@78af000 { + compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; + reg = <0x078af000 0x200>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_UART1_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + status = "disabled"; + }; + + blsp1_uart1: serial@78b0000 { + compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; + reg = <0x078b0000 0x200>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_UART2_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 2>, <&blsp_dma 3>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + + sdhc_1: sdhci@7804000 { + compatible = "qcom,sdhci-msm-v5"; + reg = <0x7804000 0x1000>, <0x7805000 0x1000>; + reg-names = "hc_mem", "cmdq_mem"; + + interrupts = , + ; + interrupt-names = "hc_irq", "pwr_irq"; + + clocks = <&xo>, + <&gcc GCC_SDCC1_AHB_CLK>, + <&gcc GCC_SDCC1_APPS_CLK>; + clock-names = "xo", "iface", "core"; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + max-frequency = <192000000>; + bus-width = <4>; + non-removable; + status = "disabled"; + }; + + spi0: spi@78b5000 { + compatible = "qcom,spi-qup-v2.2.1"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x078b5000 0x600>; + interrupts = ; + spi-max-frequency = <50000000>; + clocks = <&gcc GCC_BLSP1_QUP1_SPI_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 4>, <&blsp_dma 5>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + +/* spi2: spi@78b7000 { + compatible = "qcom,spi-qup-v2.2.1"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x078b7000 0x600>; + interrupts = ; + spi-max-frequency = <50000000>; + clocks = <&gcc GCC_BLSP1_QUP3_SPI_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 8>, <&blsp_dma 9>; + dma-names = "tx", "rx"; + status = "disabled"; + };*/ + + spi1: spi@78b6000 { + compatible = "qcom,spi-qup-v2.2.1"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x078b6000 0x600>; + interrupts = ; + spi-max-frequency = <50000000>; + clocks = <&gcc GCC_BLSP1_QUP2_SPI_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 6>, <&blsp_dma 7>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + +/* i2c_0: i2c@78b5000 { + compatible = "qcom,i2c-qup-v2.2.1"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x078b5000 0x600>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_QUP1_I2C_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + clock-frequency = <400000>; + dmas = <&blsp_dma 4>, <&blsp_dma 5>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + + i2c_1: i2c@78b6000 { + compatible = "qcom,i2c-qup-v2.2.1"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x78b6000 0x600>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_AHB_CLK>, + <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>; + clock-names = "iface", "core"; + clock-frequency = <400000>; + dmas = <&blsp_dma 7>, <&blsp_dma 6>; + dma-names = "rx", "tx"; + status = "disabled"; + };*/ + + + i2c_2: i2c@78b7000 { + compatible = "qcom,i2c-qup-v2.2.1"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x78b7000 0x600>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_AHB_CLK>, + <&gcc GCC_BLSP1_QUP3_I2C_APPS_CLK>; + clock-names = "iface", "core"; + clock-frequency = <400000>; + dmas = <&blsp_dma 8>, <&blsp_dma 9>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + + qpic_bam: dma@7984000 { + compatible = "qcom,bam-v1.7.0"; + reg = <0x7984000 0x1c000>; + interrupts = ; + clocks = <&gcc GCC_QPIC_AHB_CLK>; + clock-names = "bam_clk"; + #dma-cells = <1>; + qcom,ee = <0>; + status = "disabled"; + }; + + nand: nand@79b0000 { + compatible = "qcom,ipq5332-nand"; + reg = <0x79b0000 0x10000>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&gcc GCC_QPIC_CLK>, + <&gcc GCC_QPIC_AHB_CLK>, + <&gcc GCC_QPIC_IO_MACRO_CLK>; + clock-names = "core", "aon", "io_macro"; + + dmas = <&qpic_bam 0>, + <&qpic_bam 1>, + <&qpic_bam 2>, + <&qpic_bam 3>; + dma-names = "tx", "rx", "cmd", "sts"; + qcom,io_macro_max_clk = <320000000>; + qcom,io_macro_clk_rates = <24000000 100000000 200000000 \ + 320000000>; + status = "disabled"; + + nandcs@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + + nand-ecc-strength = <4>; + nand-ecc-step-size = <512>; + nand-bus-width = <8>; + }; + }; + + tcsr_boot_misc: syscon@193d100 { + compatible = "syscon"; + reg = <0x0193d100 0x4>; + }; + + tcsr_mutex_regs: syscon@1905000 { + compatible = "syscon"; + reg = <0x01905000 0x8000>; + }; + + tcsr_mutex: hwlock { + compatible = "qcom,tcsr-mutex"; + syscon = <&tcsr_mutex_regs 0 0x80>; + #hwlock-cells = <1>; + }; + + smem { + compatible = "qcom,smem"; + memory-region = <&smem_region>; + hwlocks = <&tcsr_mutex 0>; + }; + + scm { + compatible = "qcom,scm"; + qcom,dload-mode = <&tcsr_boot_misc 0>; + }; + + usb3: usb3@8A00000 { + compatible = "qcom,ipq5018-dwc3"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + reg = <0x8AF8800 0x100>, + <0x8A00000 0xe000>; + reg-names = "qscratch_base", "dwc3_base"; + + clocks = <&gcc GCC_USB0_MASTER_CLK>, + <&gcc GCC_USB0_SLEEP_CLK>, + <&gcc GCC_USB0_MOCK_UTMI_CLK>, + <&gcc GCC_USB0_PHY_CFG_AHB_CLK>, + <&gcc GCC_USB0_AUX_CLK>, + <&gcc GCC_USB0_LFPS_CLK>, + <&gcc GCC_USB0_PIPE_CLK>; + + clock-names = "master", + "sleep", + "mock_utmi", + "cfg_ahb_clk", + "aux_clk", + "lfps_clk", + "pipe_clk"; + + assigned-clocks = <&gcc GCC_USB0_MASTER_CLK>, + <&gcc GCC_USB0_MOCK_UTMI_CLK>, + <&gcc GCC_USB0_AUX_CLK>, + <&gcc GCC_USB0_LFPS_CLK>; + + assigned-clock-rates = <133330000>, + <60000000>, + <2000000>, + <25000000>; + + resets = <&gcc GCC_USB_BCR>; + + qca,host = <1>; + qcom,phy-mux-regs = <&tcsr_q6_block 0x2540>; + status = "disabled"; + + dwc_0: dwc3@8A00000 { + compatible = "snps,dwc3"; + reg = <0x8A00000 0xe000>; + interrupts = ; + usb-phy = <&hs_m31phy_0>; + #phy-cells = <0>; + phys = <&ssuniphy_0>; + phy-names = "usb3-phy"; + snps,dis_ep_cache_eviction; + tx-fifo-resize; + snps,usb3-u1u2-disable; + snps,nominal-elastic-buffer; + snps,is-utmi-l1-suspend; + snps,hird-threshold = /bits/ 8 <0x0>; + snps,dis_u2_susphy_quirk; + snps,dis_u3_susphy_quirk; + snps,quirk-ref-clock-adjustment = <0x49459>; + snps,quirk-ref-clock-period = <0x10>; + snps,quirk-30m-sb-sel = <0x0>; + dr_mode = "host"; + }; + }; + + + eip: eip196@39800000 { + compatible = "qcom,eip"; + reg-names = "eip_pbase"; + reg = <0x39800000 0x7ffff>; + reg_offset = <0x80000>; + ranges; + clocks = <&nsscc NSS_CC_EIP_CLK>, + <&nsscc NSS_CC_NSSNOC_EIP_CLK>; + clock-names = "eip_clk", "eip_nocclk"; + clock-frequency = /bits/ 64 <300000000 300000000>; + status = "ok"; + interrupts = , + , + , + ; + + dma0 { + tx_cpu = /bits/ 8 <0>; + rx_cpu = /bits/ 8 <0>; + ring-name = "lookaside"; + ring-id = /bits/ 8 <0>; + }; + + dma1 { + tx_cpu = /bits/ 8 <1>; + rx_cpu = /bits/ 8 <1>; + ring-name = "lookaside"; + ring-id = /bits/ 8 <1>; + }; + + dma2 { + tx_cpu = /bits/ 8 <2>; + rx_cpu = /bits/ 8 <2>; + ring-name = "lookaside"; + ring-id = /bits/ 8 <2>; + }; + + dma3 { + tx_cpu = /bits/ 8 <3>; + rx_cpu = /bits/ 8 <3>; + ring-name = "lookaside"; + ring-id = /bits/ 8 <3>; + }; + }; + + eip_crypto: eip_crypto { + compatible = "qcom,eip_crypto"; + status = "ok"; + }; + + /* 1L controller with 2L/2x1L Flexible PHY 2nd lane */ + pcie2: pcie@10000000 { + pinctrl-0 = <&pci2_pin>; + pinctrl-names = "default"; + compatible = "qti,pcie-ipq5332"; + reg = <0x10000000 0xf1d + 0x10000F20 0xa8 + 0x10001000 0x1000 + 0xf0000 0x3000 + 0x10100000 0x1000>; + reg-names = "dbi", "elbi", "atu", "parf", "config"; + device_type = "pci"; + linux,pci-domain = <2>; + bus-range = <0x00 0xff>; + num-lanes = <1>; + #address-cells = <3>; + #size-cells = <2>; + axi-halt-val = <0x1e>; /* increase halt window size to 1GB */ + + ranges = <0x81000000 0 0x10200000 0x10200000 + 0 0x00100000 /* downstream I/O */ + 0x82000000 0 0x10300000 0x10300000 + 0 0x7d00000>; /* non-prefetchable memory */ + + phys = <&pcie2_phy>; + phy-names = "pciephy"; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0x7>; + interrupt-map = <0 0 0 1 &intc 0 399 + IRQ_TYPE_LEVEL_HIGH>, /* int_a */ + <0 0 0 2 &intc 0 400 + IRQ_TYPE_LEVEL_HIGH>, /* int_b */ + <0 0 0 3 &intc 0 401 + IRQ_TYPE_LEVEL_HIGH>, /* int_c */ + <0 0 0 4 &intc 0 402 + IRQ_TYPE_LEVEL_HIGH>; /* int_d */ + + interrupts = ; + interrupt-names = "global_irq"; + + clocks = <&gcc GCC_PCIE3X1_1_AXI_M_CLK>, + <&gcc GCC_PCIE3X1_1_AXI_S_CLK>, + <&gcc GCC_PCIE3X1_1_AHB_CLK>, + <&gcc GCC_PCIE3X2_AUX_CLK>, + <&gcc GCC_PCIE3X1_1_AXI_S_BRIDGE_CLK>, + <&gcc GCC_PCIE3X1_1_RCHG_CLK>; + + clock-names = "axi_m", + "axi_s", + "ahb", + "aux", + "axi_bridge", + "rchng"; + + axi-m-clk-rate = <240000000>; + axi-s-clk-rate = <240000000>; + aux-clk-rate = <2000000>; + + resets = <&gcc GCC_PCIE3X1_1_PIPE_ARES>, + <&gcc GCC_PCIE3X1_1_CORE_STICKY_ARES>, + <&gcc GCC_PCIE3X1_1_AXI_M_CLK_ARES>, + <&gcc GCC_PCIE3X1_1_AXI_S_CLK_ARES>, + <&gcc GCC_PCIE3X1_1_AXI_M_STICKY_ARES>, + <&gcc GCC_PCIE3X1_1_AXI_S_STICKY_ARES>, + <&gcc GCC_PCIE3X1_1_AHB_CLK_ARES>, + <&gcc GCC_PCIE3X1_1_AUX_CLK_ARES>; + + reset-names = "pipe", + "sticky", + "axi_m", + "axi_s", + "axi_m_sticky", + "axi_s_sticky", + "ahb", + "aux"; + + msi-parent = <&v2m0>; + max-payload-size = <1>; + perst-gpio = <&tlmm 44 GPIO_ACTIVE_LOW>; + status = "disabled"; + nvmem-cells = <&pcie2_disable>; + + pcie2_rp: pcie2_rp { + reg = <0 0 0 0 0>; + }; + }; + + /* 2L controller with 2L/2x1L Flexible PHY. + * Connected to the 1st lane of the Flexible PHY in 1L mode + */ + pcie1: pcie@18000000 { + pinctrl-0 = <&pci1_pin>; + pinctrl-names = "default"; + compatible = "qti,pcie-ipq5332"; + reg = <0x18000000 0xf1d + 0x18000F20 0xa8 + 0x18001000 0x1000 + 0x88000 0x3000 + 0x18100000 0x1000>; + reg-names = "dbi", "elbi", "atu", "parf", "config"; + device_type = "pci"; + linux,pci-domain = <1>; + bus-range = <0x00 0xff>; + num-lanes = <2>; + #address-cells = <3>; + #size-cells = <2>; + slv-addr-space-sz = <0x8000000>; + axi-halt-val = <0x1e>; /* increase halt window size to 1GB */ + + phys = <&pcie1_phy_x2>; + phy-names = "pciephy"; + + ranges = <0x81000000 0 0x18200000 0x18200000 + 0 0x00100000 /* downstream I/O */ + 0x82000000 0 0x18300000 0x18300000 + 0 0x7d00000>; /* non-prefetchable memory */ + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0x7>; + interrupt-map = <0 0 0 1 &intc 0 412 + IRQ_TYPE_LEVEL_HIGH>, /* int_a */ + <0 0 0 2 &intc 0 413 + IRQ_TYPE_LEVEL_HIGH>, /* int_b */ + <0 0 0 3 &intc 0 414 + IRQ_TYPE_LEVEL_HIGH>, /* int_c */ + <0 0 0 4 &intc 0 415 + IRQ_TYPE_LEVEL_HIGH>; /* int_d */ + + interrupts = ; + interrupt-names = "global_irq"; + + clocks = <&gcc GCC_PCIE3X2_AXI_M_CLK>, + <&gcc GCC_PCIE3X2_AXI_S_CLK>, + <&gcc GCC_PCIE3X2_AHB_CLK>, + <&gcc GCC_PCIE3X2_AUX_CLK>, + <&gcc GCC_PCIE3X2_AXI_S_BRIDGE_CLK>, + <&gcc GCC_PCIE3X2_RCHG_CLK>; + + clock-names = "axi_m", + "axi_s", + "ahb", + "aux", + "axi_bridge", + "rchng"; + + axi-m-clk-rate = <266666667>; + axi-s-clk-rate = <240000000>; + aux-clk-rate = <2000000>; + + resets = <&gcc GCC_PCIE3X2_PIPE_ARES>, + <&gcc GCC_PCIE3X2_CORE_STICKY_ARES>, + <&gcc GCC_PCIE3X2_AXI_M_CLK_ARES>, + <&gcc GCC_PCIE3X2_AXI_S_CLK_ARES>, + <&gcc GCC_PCIE3X2_AXI_M_STICKY_ARES>, + <&gcc GCC_PCIE3X2_AXI_S_STICKY_ARES>, + <&gcc GCC_PCIE3X2_AHB_CLK_ARES>, + <&gcc GCC_PCIE3X2_AUX_CLK_ARES>; + + reset-names = "pipe", + "sticky", + "axi_m", + "axi_s", + "axi_m_sticky", + "axi_s_sticky", + "ahb", + "aux"; + + msi-parent = <&v2m0>; + max-payload-size = <1>; + perst-gpio = <&tlmm 47 GPIO_ACTIVE_LOW>; + status = "disabled"; + nvmem-cells = <&pcie1_disable>; + + pcie1_rp: pcie1_rp { + reg = <0 0 0 0 0>; + }; + }; + + /* 1L controller with USB/PCIe combo PHY */ + pcie0: pcie@20000000 { + pinctrl-0 = <&pci0_pin>; + pinctrl-names = "default"; + compatible = "qti,pcie-ipq5332"; + reg = <0x20000000 0xf1d + 0x20000F20 0xa8 + 0x20001000 0x1000 + 0x80000 0x3000 + 0x20100000 0x1000>; + reg-names = "dbi", "elbi", "atu", "parf", "config"; + device_type = "pci"; + linux,pci-domain = <0>; + bus-range = <0x00 0xff>; + num-lanes = <1>; + #address-cells = <3>; + #size-cells = <2>; + axi-halt-val = <0x1e>; /* increase halt window size to 1GB */ + + phys = <&pcie0_phy>; + phy-names = "pciephy"; + + ranges = <0x81000000 0 0x20200000 0x20200000 + 0 0x00100000 /* downstream I/O */ + 0x82000000 0 0x20300000 0x20300000 + 0 0xfd00000>; /* non-prefetchable memory */ + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0x7>; + interrupt-map = <0 0 0 1 &intc 0 35 + IRQ_TYPE_LEVEL_HIGH>, /* int_a */ + <0 0 0 2 &intc 0 36 + IRQ_TYPE_LEVEL_HIGH>, /* int_b */ + <0 0 0 3 &intc 0 37 + IRQ_TYPE_LEVEL_HIGH>, /* int_c */ + <0 0 0 4 &intc 0 38 + IRQ_TYPE_LEVEL_HIGH>; /* int_d */ + + interrupts = ; + interrupt-names = "global_irq"; + + clocks = <&gcc GCC_PCIE3X1_0_AXI_M_CLK>, + <&gcc GCC_PCIE3X1_0_AXI_S_CLK>, + <&gcc GCC_PCIE3X1_0_AHB_CLK>, + <&gcc GCC_PCIE3X1_0_AUX_CLK>, + <&gcc GCC_PCIE3X1_0_AXI_S_BRIDGE_CLK>, + <&gcc GCC_PCIE3X1_0_RCHG_CLK>; + + clock-names = "axi_m", + "axi_s", + "ahb", + "aux", + "axi_bridge", + "rchng"; + + axi-m-clk-rate = <240000000>; + axi-s-clk-rate = <240000000>; + aux-clk-rate = <2000000>; + + resets = <&gcc GCC_PCIE3X1_0_PIPE_ARES>, + <&gcc GCC_PCIE3X1_0_CORE_STICKY_ARES>, + <&gcc GCC_PCIE3X1_0_AXI_M_CLK_ARES>, + <&gcc GCC_PCIE3X1_0_AXI_S_CLK_ARES>, + <&gcc GCC_PCIE3X1_0_AXI_M_STICKY_ARES>, + <&gcc GCC_PCIE3X1_0_AXI_S_STICKY_ARES>, + <&gcc GCC_PCIE3X1_0_AHB_CLK_ARES>, + <&gcc GCC_PCIE3X1_0_AUX_CLK_ARES>; + + reset-names = "pipe", + "sticky", + "axi_m", + "axi_s", + "axi_m_sticky", + "axi_s_sticky", + "ahb", + "aux"; + + msi-parent = <&v2m0>; + max-payload-size = <1>; + perst-gpio = <&tlmm 38 GPIO_ACTIVE_LOW>; + status = "disabled"; + nvmem-cells = <&pcie0_disable>; + + pcie0_rp: pcie0_rp { + reg = <0 0 0 0 0>; + }; + }; + + apcs_glb: mailbox@b111000 { + compatible = "qcom,ipq5332-apcs-apps-global"; + reg = <0x0b111000 0x6000>; + #clock-cells = <1>; + #mbox-cells = <1>; + }; + + wifi0: wifi@c0000000 { + compatible = "qcom,cnss-qca5332", "qcom,ipq5332-wifi"; + reg = <0xc000000 0x1000000>; + #ifdef __IPQ_MEM_PROFILE_256_MB__ + qcom,tgt-mem-mode = <2>; + #elif __IPQ_MEM_PROFILE_512_MB__ + qcom,tgt-mem-mode = <1>; + #else + qcom,tgt-mem-mode = <0>; + #endif + qcom,rproc = <&q6v5_wcss>; + qcom,bdf-addr = <0x4B500000 0x4B500000 0x4B500000 + 0x0 0x0 0x0>; + qcom,caldb-addr = <0x4CE00000 0x4CE00000 0x0 + 0x0 0x0 0x0>; + qcom,caldb-size = <0x500000>; + interrupts = <0 559 1>, /* misc-pulse1 */ + <0 560 1>, /* misc-latch */ + <0 561 1>, /* sw-exception */ + <0 422 1>, /* ce0 */ + <0 423 1>, /* ce1 */ + <0 424 1>, /* ce2 */ + <0 425 1>, /* ce3 */ + <0 426 1>, /* ce4 */ + <0 427 1>, /* ce5 */ + <0 428 1>, /* ce6 */ + <0 429 1>, /* ce7 */ + <0 430 1>, /* ce8 */ + <0 431 1>, /* ce9 */ + <0 432 1>, /* ce10 */ + <0 433 1>, /* ce11 */ + <0 491 1>, /* host2wbm-desc-feed */ + <0 495 1>, /* host2reo-re-injection */ + <0 493 1>, /* host2reo-command */ + <0 544 1>, /* host2rxdma-monitor-ring1 */ + <0 457 1>, /* reo2ost-exception */ + <0 466 1>, /* wbm2host-rx-release */ + <0 497 1>, /* reo2host-status */ + <0 454 1>, /* reo2host-destination-ring4 */ + <0 453 1>, /* reo2host-destination-ring3 */ + <0 452 1>, /* reo2host-destination-ring2 */ + <0 451 1>, /* reo2host-destination-ring1 */ + <0 488 1>, /* rxdma2host-monitor-destination-mac3 */ + <0 488 1>, /* rxdma2host-monitor-destination-mac2 */ + <0 484 1>, /* rxdma2host-monitor-destination-mac1 */ + <0 554 1>, /* host2rxdma-host-buf-ring-mac3 */ + <0 554 1>, /* host2rxdma-host-buf-ring-mac2 */ + <0 549 1>, /* host2rxdma-host-buf-ring-mac1 */ + <0 507 1>, /* host2tcl-input-ring4 */ + <0 500 1>, /* host2tcl-input-ring3 */ + <0 499 1>, /* host2tcl-input-ring2 */ + <0 498 1>, /* host2tcl-input-ring1 */ + <0 450 1>, /* wbm2host-tx-completions-ring4 */ + <0 449 1>, /* wbm2host-tx-completions-ring3 */ + <0 448 1>, /* wbm2host-tx-completions-ring2 */ + <0 447 1>, /* wbm2host-tx-completions-ring1 */ + <0 543 1>, /* host2tx-monitor-ring1 */ + <0 486 1>, /* txmon2host-monitor-destination-mac3 */ + <0 486 1>, /* txmon2host-monitor-destination-mac2 */ + <0 482 1>, /* txmon2host-monitor-destination-mac1 */ + <0 419 1>, /* umac_reset */ + /* Unused Interrupts */ + <0 558 1>, /* host2rxdma-monitor-ring3 */ + <0 558 1>, /* host2rxdma-monitor-ring2 */ + <0 558 1>, /* ppdu-end-interrupts-mac3 */ + <0 558 1>, /* ppdu-end-interrupts-mac2 */ + <0 558 1>, /* ppdu-end-interrupts-mac1 */ + <0 558 1>, /* rxdma2host-monitor-status-ring-mac3 */ + <0 558 1>, /* rxdma2host-monitor-status-ring-mac2 */ + <0 558 1>, /* rxdma2host-monitor-status-ring-mac1 */ + <0 558 1>, /* rxdma2host-destination-ring-mac3 */ + <0 558 1>, /* rxdma2host-destination-ring-mac2 */ + <0 558 1>; /* rxdma2host-destination-ring-mac1 */ + + interrupt-names = "misc-pulse1", + "misc-latch", + "sw-exception", + "ce0", + "ce1", + "ce2", + "ce3", + "ce4", + "ce5", + "ce6", + "ce7", + "ce8", + "ce9", + "ce10", + "ce11", + "host2wbm-desc-feed", + "host2reo-re-injection", + "host2reo-command", + "host2rxdma-monitor-ring1", + "reo2ost-exception", + "wbm2host-rx-release", + "reo2host-status", + "reo2host-destination-ring4", + "reo2host-destination-ring3", + "reo2host-destination-ring2", + "reo2host-destination-ring1", + "rxdma2host-monitor-destination-mac3", + "rxdma2host-monitor-destination-mac2", + "rxdma2host-monitor-destination-mac1", + "host2rxdma-host-buf-ring-mac3", + "host2rxdma-host-buf-ring-mac2", + "host2rxdma-host-buf-ring-mac1", + "host2tcl-input-ring4", + "host2tcl-input-ring3", + "host2tcl-input-ring2", + "host2tcl-input-ring1", + "wbm2host-tx-completions-ring4", + "wbm2host-tx-completions-ring3", + "wbm2host-tx-completions-ring2", + "wbm2host-tx-completions-ring1", + "host2tx-monitor-ring1", + "txmon2host-monitor-destination-mac3", + "txmon2host-monitor-destination-mac2", + "txmon2host-monitor-destination-mac1", + "umac_reset", + /* Unused Interrupts */ + "host2rxdma-monitor-ring3", + "host2rxdma-monitor-ring2", + "ppdu-end-interrupts-mac3", + "ppdu-end-interrupts-mac2", + "ppdu-end-interrupts-mac1", + "rxdma2host-monitor-status-ring-mac3", + "rxdma2host-monitor-status-ring-mac2", + "rxdma2host-monitor-status-ring-mac1", + "rxdma2host-destination-ring-mac3", + "rxdma2host-destination-ring-mac2", + "rxdma2host-destination-ring-mac1"; + /* 36 indicates GPIO number for LED_2G. + * 0 indicates that the GPIO is active high. + */ + led-gpio = <&tlmm 36 0>; + status = "disabled"; + qcom,pta-num = <0>; + qcom,coex-mode = <0x2>; + qcom,bt-active-time = <0x18>; + qcom,bt-priority-time = <0x12>; + qcom,coex-algo = <0x2>; + qcom,pta-priority = <0x80800505>; + }; + + wifi1: wifi1@f00000 { + compatible = "qcom,cnss-qcn9224"; + qcom,wlan-ramdump-dynamic = <0x600000>; + qrtr_node_id = <0x30>; + qca,auto-restart; + status = "disabled"; + interrupt-bmap = <0x100512>; +#ifdef __IPQ_MEM_PROFILE_512_MB__ + /* qcn9224 tgt-mem-mode=1 layout - 37MB + * +=========+==============+=========+ + * | Region | Start Offset | Size | + * +---------+--------------+---------+ + * | HREMOTE | 0x4EC00000 | 20MB | + * +---------+--------------+---------+ + * | M3 Dump | 0x50000000 | 1MB | + * +---------+--------------+---------+ + * | ETR | 0x50100000 | 1MB | + * +---------+--------------+---------+ + * | Caldb | 0x50200000 | 8MB | + * +---------+--------------+---------+ + * |Pageable | 0x50A00000 | 7MB | + * +==================================+ + */ + base-addr = <0x4EC00000>; + m3-dump-addr = <0x50000000>; + etr-addr = <0x50100000>; + caldb-addr = <0x50200000>; + pageable-addr = <0x50A00000>; + hremote-size = <0x1400000>; + pageable-size = <0x700000>; + tgt-mem-mode = <0x1>; +#else + /* qcn9224 tgt-mem-mode=0 layout - 50MB + * +=========+==============+=========+ + * | Region | Start Offset | Size | + * +---------+--------------+---------+ + * | HREMOTE | 0x4EC00000 | 28MB | + * +---------+--------------+---------+ + * | M3 Dump | 0x50800000 | 1MB | + * +---------+--------------+---------+ + * | ETR | 0x50900000 | 1MB | + * +---------+--------------+---------+ + * | Caldb | 0x50A00000 | 8MB | + * +---------+--------------+---------+ + * |Pageable | 0x51200000 | 12MB | + * +==================================+ + */ + base-addr = <0x4EC00000>; + m3-dump-addr = <0x50800000>; + etr-addr = <0x50900000>; + caldb-addr = <0x50A00000>; + pageable-addr = <0x51200000>; + hremote-size = <0x1C00000>; + pageable-size = <0xC00000>; + tgt-mem-mode = <0x0>; +#endif + caldb-size = <0x800000>; + qca,extended-intc; + interrupts-extended = + <&qcn9224_in0 5 0>, + <&qcn9224_in0 6 0>, + <&qcn9224_in0 7 0>, + <&qcn9224_in0 8 0>, + <&qcn9224_in0 9 0>, + <&qcn9224_in0 10 0>, + <&qcn9224_in0 11 0>, + <&qcn9224_in0 12 0>, + <&qcn9224_in0 13 0>, + <&qcn9224_in0 14 0>, + <&qcn9224_in0 15 0>, + <&qcn9224_in0 16 0>, + <&qcn9224_in0 17 0>, + <&qcn9224_in0 18 0>, + <&qcn9224_in0 19 0>, + <&qcn9224_in0 20 0>, + <&qcn9224_in0 49 0>, + <&qcn9224_in0 48 0>, + <&qcn9224_in0 47 0>, + <&qcn9224_in0 46 0>, + <&qcn9224_in0 45 0>, + <&qcn9224_in0 44 0>, + <&qcn9224_in0 43 0>, + <&qcn9224_in0 42 0>, + <&qcn9224_in0 50 0>, + <&qcn9224_in0 52 0>, + <&qcn9224_in0 51 0>, + <&qcn9224_in0 30 0>, + <&qcn9224_in0 29 0>, + <&qcn9224_in0 28 0>, + <&qcn9224_in0 27 0>, + <&qcn9224_in0 26 0>, + <&qcn9224_in0 25 0>, + <&qcn9224_in0 31 0>, + <&qcn9224_in0 80 0>, + <&qcn9224_in0 71 0>, + <&qcn9224_in0 96 0>, + <&qcn9224_in0 97 0>, + <&qcn9224_in0 67 0>, + <&qcn9224_in0 100 0>, + <&qcn9224_in0 99 0>, + <&qcn9224_in0 68 0>, + <&qcn9224_in0 69 0>, + <&qcn9224_in0 121 0>, + <&qcn9224_in0 119 0>, + <&qcn9224_in0 122 0>, + <&qcn9224_in0 120 0>, + <&qcn9224_in0 116 0>, + <&qcn9224_in0 113 0>, + <&qcn9224_in0 115 0>, + <&qcn9224_in0 112 0>, + <&qcn9224_in0 114 0>, + <&qcn9224_in0 111 0>, + <&qcn9224_in0 110 0>, + <&qcn9224_in0 109 0>, + <&qcn9224_in0 108 0>, + <&qcn9224_in0 39 0>, + <&qcn9224_in0 38 0>, + <&qcn9224_in0 37 0>, + <&qcn9224_in0 36 0>, + <&qcn9224_in0 35 0>, + <&qcn9224_in0 34 0>, + <&qcn9224_in0 33 0>, + <&qcn9224_in0 41 0>, + <&qcn9224_in0 40 0>, + <&qcn9224_in0 32 0>, + <&qcn9224_in0 24 0>, + <&qcn9224_in0 23 0>, + <&qcn9224_in0 22 0>, + <&qcn9224_in0 21 0>, + <&qcn9224_in0 66 0>, + <&qcn9224_in0 78 0>, + <&qcn9224_in0 117 0>, + <&qcn9224_in0 118 0>, + <&qcn9224_in0 61 0>, + <&qcn9224_in0 60 0>, + <&qcn9224_in0 57 0>, + <&qcn9224_in0 56 0>, + <&qcn9224_in0 63 0>, + <&qcn9224_in0 62 0>, + <&qcn9224_in0 59 0>, + <&qcn9224_in0 58 0>, + <&qcn9224_in0 65 0>, + <&qcn9224_in0 83 0>, + <&qcn9224_in0 75 0>, + <&qcn9224_in0 82 0>, + <&qcn9224_in0 81 0>, + <&qcn9224_in0 74 0>, + <&qcn9224_in0 73 0>, + <&qcn9224_in0 72 0>, + <&qcn9224_in0 98 0>, + <&qcn9224_in0 107 0>, + <&qcn9224_in0 106 0>, + <&qcn9224_in0 105 0>, + <&qcn9224_in0 104 0>, + <&qcn9224_in0 103 0>, + <&qcn9224_in0 102 0>, + <&qcn9224_in0 101 0>, + <&qcn9224_in0 76 0>, + <&qcn9224_in0 77 0>, + <&qcn9224_in0 143 0>, + <&qcn9224_in0 142 0>, + <&qcn9224_in0 141 0>, + <&intc GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>; + + interrupt-names = "ce0", + "ce1", + "ce2", + "ce3", + "ce4", + "ce5", + "ce6", + "ce7", + "ce8", + "ce9", + "ce10", + "ce11", + "ce12", + "ce13", + "ce14", + "ce15", + "reo2sw8_intr2", + "reo2sw7_intr2", + "reo2sw6_intr2", + "reo2sw5_intr2", + "reo2sw4_intr2", + "reo2sw3_intr2", + "reo2sw2_intr2", + "reo2sw1_intr2", + "reo2sw0_intr2", + "reo2sw8_intr", + "reo2sw7_intr", + "reo2sw6_inrr", + "reo2sw5_intr", + "reo2sw4_intr", + "reo2sw3_intr", + "reo2sw2_intr", + "reo2sw1_intr", + "reo2sw0_intr", + "reo2status_intr2", + "reo_status", + "reo2rxdma_out_2", + "reo2rxdma_out_1", + "reo_cmd", + "sw2reo6", + "sw2reo5", + "sw2reo1", + "sw2reo", + "rxdma2reo_mlo_0_dst_ring1", + "rxdma2reo_mlo_0_dst_ring0", + "rxdma2reo_mlo_1_dst_ring1", + "rxdma2reo_mlo_1_dst_ring0", + "rxdma2reo_dst_ring1", + "rxdma2reo_dst_ring0", + "rxdma2sw_dst_ring1", + "rxdma2sw_dst_ring0", + "rxdma2release_dst_ring1", + "rxdma2release_dst_ring0", + "sw2rxdma_2_src_ring", + "sw2rxdma_1_src_ring", + "sw2rxdma_0", + "wbm2sw6_release2", + "wbm2sw5_release2", + "wbm2sw4_release2", + "wbm2sw3_release2", + "wbm2sw2_release2", + "wbm2sw1_release2", + "wbm2sw0_release2", + "wbm2sw6_release", + "wbm2sw5_release", + "wbm2sw4_release", + "wbm2sw3_release", + "wbm2sw2_release", + "wbm2sw1_release", + "wbm2sw0_release", + "wbm2sw_link", + "wbm_error_release", + "sw2txmon_src_ring", + "sw2rxmon_src_ring", + "txmon2sw_p1_intr1", + "txmon2sw_p1_intr0", + "txmon2sw_p0_dest1", + "txmon2sw_p0_dest0", + "rxmon2sw_p1_intr1", + "rxmon2sw_p1_intr0", + "rxmon2sw_p0_dest1", + "rxmon2sw_p0_dest0", + "sw_release", + "sw2tcl_credit2", + "sw2tcl_credit", + "sw2tcl4", + "sw2tcl5", + "sw2tcl3", + "sw2tcl2", + "sw2tcl1", + "sw2wbm1", + "misc_8", + "misc_7", + "misc_6", + "misc_5", + "misc_4", + "misc_3", + "misc_2", + "misc_1", + "misc_0", + "mhi2", + "mhi1", + "mhi0", + "inta"; + }; + + + wifi2: wifi2@f00000 { + compatible = "qcom,cnss-qcn9224"; + qcom,wlan-ramdump-dynamic = <0x600000>; + qrtr_node_id = <0x31>; + qca,auto-restart; + status = "disabled"; + interrupt-bmap = <0x100512>; +#ifdef __IPQ_MEM_PROFILE_512_MB__ + /* qcn9224 tgt-mem-mode=1 layout - 37MB + * +=========+==============+=========+ + * | Region | Start Offset | Size | + * +---------+--------------+---------+ + * | HREMOTE | 0x51100000 | 20MB | + * +---------+--------------+---------+ + * | M3 Dump | 0x52500000 | 1MB | + * +---------+--------------+---------+ + * | ETR | 0x52600000 | 1MB | + * +---------+--------------+---------+ + * | Caldb | 0x52700000 | 8MB | + * +---------+--------------+---------+ + * |Pageable | 0x52F00000 | 7MB | + * +==================================+ + */ + base-addr = <0x51100000>; + m3-dump-addr = <0x52500000>; + etr-addr = <0x52600000>; + caldb-addr = <0x52700000>; + pageable-addr = <0x52F00000>; + hremote-size = <0x1400000>; + pageable-size = <0x700000>; + tgt-mem-mode = <0x1>; +#else + /* qcn9224 tgt-mem-mode=0 layout - 50MB + * +=========+==============+=========+ + * | Region | Start Offset | Size | + * +---------+--------------+---------+ + * | HREMOTE | 0x51E00000 | 28MB | + * +---------+--------------+---------+ + * | M3 Dump | 0x53A00000 | 1MB | + * +---------+--------------+---------+ + * | ETR | 0x53B00000 | 1MB | + * +---------+--------------+---------+ + * | Caldb | 0x53C00000 | 8MB | + * +---------+--------------+---------+ + * |Pageable | 0x54400000 | 12MB | + * +==================================+ + */ + base-addr = <0x51E00000>; + m3-dump-addr = <0x53A00000>; + etr-addr = <0x53B00000>; + caldb-addr = <0x53C00000>; + pageable-addr = <0x54400000>; + hremote-size = <0x1C00000>; + pageable-size = <0xC00000>; + tgt-mem-mode = <0x0>; +#endif + caldb-size = <0x800000>; + qca,extended-intc; + interrupts-extended = + <&qcn9224_in1 5 0>, + <&qcn9224_in1 6 0>, + <&qcn9224_in1 7 0>, + <&qcn9224_in1 8 0>, + <&qcn9224_in1 9 0>, + <&qcn9224_in1 10 0>, + <&qcn9224_in1 11 0>, + <&qcn9224_in1 12 0>, + <&qcn9224_in1 13 0>, + <&qcn9224_in1 14 0>, + <&qcn9224_in1 15 0>, + <&qcn9224_in1 16 0>, + <&qcn9224_in1 17 0>, + <&qcn9224_in1 18 0>, + <&qcn9224_in1 19 0>, + <&qcn9224_in1 20 0>, + <&qcn9224_in1 49 0>, + <&qcn9224_in1 48 0>, + <&qcn9224_in1 47 0>, + <&qcn9224_in1 46 0>, + <&qcn9224_in1 45 0>, + <&qcn9224_in1 44 0>, + <&qcn9224_in1 43 0>, + <&qcn9224_in1 42 0>, + <&qcn9224_in1 50 0>, + <&qcn9224_in1 52 0>, + <&qcn9224_in1 51 0>, + <&qcn9224_in1 30 0>, + <&qcn9224_in1 29 0>, + <&qcn9224_in1 28 0>, + <&qcn9224_in1 27 0>, + <&qcn9224_in1 26 0>, + <&qcn9224_in1 25 0>, + <&qcn9224_in1 31 0>, + <&qcn9224_in1 80 0>, + <&qcn9224_in1 71 0>, + <&qcn9224_in1 96 0>, + <&qcn9224_in1 97 0>, + <&qcn9224_in1 67 0>, + <&qcn9224_in1 100 0>, + <&qcn9224_in1 99 0>, + <&qcn9224_in1 68 0>, + <&qcn9224_in1 69 0>, + <&qcn9224_in1 121 0>, + <&qcn9224_in1 119 0>, + <&qcn9224_in1 122 0>, + <&qcn9224_in1 120 0>, + <&qcn9224_in1 116 0>, + <&qcn9224_in1 113 0>, + <&qcn9224_in1 115 0>, + <&qcn9224_in1 112 0>, + <&qcn9224_in1 114 0>, + <&qcn9224_in1 111 0>, + <&qcn9224_in1 110 0>, + <&qcn9224_in1 109 0>, + <&qcn9224_in1 108 0>, + <&qcn9224_in1 39 0>, + <&qcn9224_in1 38 0>, + <&qcn9224_in1 37 0>, + <&qcn9224_in1 36 0>, + <&qcn9224_in1 35 0>, + <&qcn9224_in1 34 0>, + <&qcn9224_in1 33 0>, + <&qcn9224_in1 41 0>, + <&qcn9224_in1 40 0>, + <&qcn9224_in1 32 0>, + <&qcn9224_in1 24 0>, + <&qcn9224_in1 23 0>, + <&qcn9224_in1 22 0>, + <&qcn9224_in1 21 0>, + <&qcn9224_in1 66 0>, + <&qcn9224_in1 78 0>, + <&qcn9224_in1 117 0>, + <&qcn9224_in1 118 0>, + <&qcn9224_in1 61 0>, + <&qcn9224_in1 60 0>, + <&qcn9224_in1 57 0>, + <&qcn9224_in1 56 0>, + <&qcn9224_in1 63 0>, + <&qcn9224_in1 62 0>, + <&qcn9224_in1 59 0>, + <&qcn9224_in1 58 0>, + <&qcn9224_in1 65 0>, + <&qcn9224_in1 83 0>, + <&qcn9224_in1 75 0>, + <&qcn9224_in1 82 0>, + <&qcn9224_in1 81 0>, + <&qcn9224_in1 74 0>, + <&qcn9224_in1 73 0>, + <&qcn9224_in1 72 0>, + <&qcn9224_in1 98 0>, + <&qcn9224_in1 107 0>, + <&qcn9224_in1 106 0>, + <&qcn9224_in1 105 0>, + <&qcn9224_in1 104 0>, + <&qcn9224_in1 103 0>, + <&qcn9224_in1 102 0>, + <&qcn9224_in1 101 0>, + <&qcn9224_in1 76 0>, + <&qcn9224_in1 77 0>, + <&qcn9224_in1 143 0>, + <&qcn9224_in1 142 0>, + <&qcn9224_in1 141 0>, + <&intc GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>; + + interrupt-names = "ce0", + "ce1", + "ce2", + "ce3", + "ce4", + "ce5", + "ce6", + "ce7", + "ce8", + "ce9", + "ce10", + "ce11", + "ce12", + "ce13", + "ce14", + "ce15", + "reo2sw8_intr2", + "reo2sw7_intr2", + "reo2sw6_intr2", + "reo2sw5_intr2", + "reo2sw4_intr2", + "reo2sw3_intr2", + "reo2sw2_intr2", + "reo2sw1_intr2", + "reo2sw0_intr2", + "reo2sw8_intr", + "reo2sw7_intr", + "reo2sw6_inrr", + "reo2sw5_intr", + "reo2sw4_intr", + "reo2sw3_intr", + "reo2sw2_intr", + "reo2sw1_intr", + "reo2sw0_intr", + "reo2status_intr2", + "reo_status", + "reo2rxdma_out_2", + "reo2rxdma_out_1", + "reo_cmd", + "sw2reo6", + "sw2reo5", + "sw2reo1", + "sw2reo", + "rxdma2reo_mlo_0_dst_ring1", + "rxdma2reo_mlo_0_dst_ring0", + "rxdma2reo_mlo_1_dst_ring1", + "rxdma2reo_mlo_1_dst_ring0", + "rxdma2reo_dst_ring1", + "rxdma2reo_dst_ring0", + "rxdma2sw_dst_ring1", + "rxdma2sw_dst_ring0", + "rxdma2release_dst_ring1", + "rxdma2release_dst_ring0", + "sw2rxdma_2_src_ring", + "sw2rxdma_1_src_ring", + "sw2rxdma_0", + "wbm2sw6_release2", + "wbm2sw5_release2", + "wbm2sw4_release2", + "wbm2sw3_release2", + "wbm2sw2_release2", + "wbm2sw1_release2", + "wbm2sw0_release2", + "wbm2sw6_release", + "wbm2sw5_release", + "wbm2sw4_release", + "wbm2sw3_release", + "wbm2sw2_release", + "wbm2sw1_release", + "wbm2sw0_release", + "wbm2sw_link", + "wbm_error_release", + "sw2txmon_src_ring", + "sw2rxmon_src_ring", + "txmon2sw_p1_intr1", + "txmon2sw_p1_intr0", + "txmon2sw_p0_dest1", + "txmon2sw_p0_dest0", + "rxmon2sw_p1_intr1", + "rxmon2sw_p1_intr0", + "rxmon2sw_p0_dest1", + "rxmon2sw_p0_dest0", + "sw_release", + "sw2tcl_credit2", + "sw2tcl_credit", + "sw2tcl4", + "sw2tcl5", + "sw2tcl3", + "sw2tcl2", + "sw2tcl1", + "sw2wbm1", + "misc_8", + "misc_7", + "misc_6", + "misc_5", + "misc_4", + "misc_3", + "misc_2", + "misc_1", + "misc_0", + "mhi2", + "mhi1", + "mhi0", + "inta"; + }; + + wifi3: wifi3@f00000 { + compatible = "qcom,cnss-qcn9160"; + msi-parent = <&v2m0>; + status = "disabled"; + }; + + wcss: wcss-smp2p { + compatible = "qcom,smp2p"; + qcom,smem = <435>, <428>; + + interrupt-parent = <&intc>; + interrupts = ; + + mboxes = <&apcs_glb 9>; + + qcom,local-pid = <0>; + qcom,remote-pid = <1>; + global_timer = <0x4A5000>; + + wcss_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + qcom,smp2p-feature-ssr-ack; + #qcom,smem-state-cells = <1>; + }; + + wcss_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + tcsr_q6_block: syscon@1945000 { + compatible = "syscon"; + reg = <0x1945000 0xE000>; + }; + + q6v5_wcss: remoteproc@d100000 { + compatible = "qcom,ipq5332-q6-mpd"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + firmware = "IPQ5332/q6_fw0.mdt"; + reg = <0x0d100000 0x4040>, + <0x193d21c 0x8>, + <0x193d204 0x4>, + <0x1825000 0x90b8>, + <0x4a1000 0x4>, + <0xD190488 0x4>; + reg-names = "qdsp6", + "tcsr-msip", + "tcsr-q6", + "ce_ahb", + "qtimer", + "l2vic_int"; + + interrupts-extended = <&intc GIC_SPI 421 IRQ_TYPE_EDGE_RISING>, + <&wcss_smp2p_in 0 0>, + <&wcss_smp2p_in 1 0>, + <&wcss_smp2p_in 2 0>, + <&wcss_smp2p_in 3 0>; + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack"; + + resets = <&gcc GCC_WCSS_BCR>, + <&gcc GCC_WCSS_Q6_BCR>; + + reset-names = "wcss_reset", + "wcss_q6_reset"; + + clocks = <&gcc GCC_Q6_TSCTR_1TO2_CLK>, + <&gcc GCC_Q6SS_TRIG_CLK>, + <&gcc GCC_Q6_AXIS_CLK>, + <&gcc GCC_Q6_AHB_S_CLK>, + <&gcc GCC_Q6SS_ATBM_CLK>, + <&gcc GCC_Q6_AHB_CLK>, + <&gcc GCC_Q6_AXIM_CLK>, + <&gcc GCC_Q6SS_PCLKDBG_CLK>, + <&gcc GCC_WCSS_ECAHB_CLK>, + <&gcc GCC_SYS_NOC_WCSS_AHB_CLK>, + <&gcc GCC_MEM_NOC_Q6_AXI_CLK>; + + clock-names = "q6_tsctr_1to2", + "q6ss_trig", + "q6_axis", + "q6_ahb_s", + "q6ss_atbm", + "q6_ahb", + "q6_axim", + "q6ss_pclkdbg", + "wcss_ecahb", + "sys_noc_wcss_ahb", + "mem_noc_q6_axi"; + + assigned-clocks = <&gcc GCC_Q6_TSCTR_1TO2_CLK>, + <&gcc GCC_Q6SS_TRIG_CLK>, + <&gcc GCC_Q6_AXIS_CLK>, + <&gcc GCC_Q6_AHB_S_CLK>, + <&gcc GCC_Q6SS_ATBM_CLK>, + <&gcc GCC_Q6_AHB_CLK>, + <&gcc GCC_Q6_AXIM_CLK>, + <&gcc GCC_Q6SS_PCLKDBG_CLK>, + <&gcc GCC_WCSS_ECAHB_CLK>, + <&gcc GCC_SYS_NOC_WCSS_AHB_CLK>, + <&gcc GCC_MEM_NOC_Q6_AXI_CLK>; + + assigned-clock-rates = <300000000>, + <120000000>, + <266666667>, + <133333333>, + <240000000>, + <133333333>, + <533333333>, + <120000000>, + <133333333>, + <133333333>, + <533333333>; + + qcom,halt-regs = <&tcsr_q6_block 0xa000 0xd000 0x0>; + + qcom,smem-states = <&wcss_smp2p_out 0>, + <&wcss_smp2p_out 1>; + qcom,smem-state-names = "shutdown", + "stop"; + memory-region = <&q6_region>, + <&m3_dump>, + <&q6_etr_region>, + <&q6_caldb_region>; + qcom,rproc = <&q6v5_wcss>; + qcom,bootargs_smem = <507>; + qcom,bootargs_version = <2>; + qcom,userpd-bootargs; + license-file = ""; + qcom,heartbeat_smem = <508>; + glink-edge { + interrupts = ; + qcom,remote-pid = <1>; + mboxes = <&apcs_glb 8>; + global_timer = <0x4A5000>; + + qrtr_requests { + qcom,glink-channels = "IPCRTR"; + }; + }; + + q6_wcss_pd1: remoteproc_pd1 { + compatible = "qcom,ipq5332-wcss-ahb-mpd"; + reg = <0x004ab000 0x20>; + reg-names = "rmb"; + firmware = "IPQ5332/q6_fw1.mdt"; + iu_firmware = "IPQ5332/iu_fw.mdt"; + qcom,halt-regs = <&tcsr_q6_block 0xa000 0x18 0x0>; + interrupts-extended = <&wcss_smp2p_in 8 0>, + <&wcss_smp2p_in 9 0>, + <&wcss_smp2p_in 12 0>, + <&wcss_smp2p_in 11 0>; + interrupt-names = "fatal", + "ready", + "spawn-ack", + "stop-ack"; + + resets = <&gcc GCC_WCSSAON_ARES>, + <&gcc GCC_WCSS_BCR>, + <&gcc GCC_CE_BCR>; + reset-names = "wcss_aon_reset", + "wcss_reset", + "ce_reset"; + + clocks = <&gcc GCC_WCSS_DBG_IFC_APB_BDG_CLK>, + <&gcc GCC_WCSS_DBG_IFC_NTS_CLK>, + <&gcc GCC_WCSS_AXIS_CLK>, + <&gcc GCC_WCSS_DBG_IFC_ATB_CLK>, + <&gcc GCC_WCSS_DBG_IFC_ATB_BDG_CLK>, + <&gcc GCC_WCSS_DBG_IFC_APB_CLK>, + <&gcc GCC_WCSS_AXIM_CLK>, + <&gcc GCC_WCSS_DBG_IFC_NTS_BDG_CLK>, + <&gcc GCC_CE_AXI_CLK>, + <&gcc GCC_CE_PCNOC_AHB_CLK>, + <&gcc GCC_CE_AHB_CLK>; + + clock-names = "dbg-apb-bdg", + "dbg-nts", + "wcss_axi_s_clk", + "dbg-atb", + "dbg-atb-bdg", + "dbg-apb", + "wcss_axi_m_clk", + "dbg-nts-bdg", + "ce-axi", + "ce-pcnoc-ahb", + "ce-ahb"; + qcom,smem-states = <&wcss_smp2p_out 8>, + <&wcss_smp2p_out 9>, + <&wcss_smp2p_out 10>; + qcom,smem-state-names = "shutdown", + "stop", + "spawn"; + qcom,offloaded_to_q6; + }; + + q6_wcss_pd2: remoteproc_pd2 { + compatible = "qcom,ipq5332-wcss-pcie-mpd"; + firmware = "IPQ5332/q6_fw2.mdt"; + qcom,halt-regs = <&tcsr_q6_block 0xa000 0x18 0x0>; + interrupts-extended = <&wcss_smp2p_in 16 0>, + <&wcss_smp2p_in 17 0>, + <&wcss_smp2p_in 20 0>, + <&wcss_smp2p_in 19 0>; + interrupt-names = "fatal", + "ready", + "spawn-ack", + "stop-ack"; + + qcom,smem-states = <&wcss_smp2p_out 16>, + <&wcss_smp2p_out 17>, + <&wcss_smp2p_out 18>; + qcom,smem-state-names = "shutdown", + "stop", + "spawn"; + status = "disabled"; + }; + + q6_wcss_pd3: remoteproc_pd3 { + compatible = "qcom,ipq5332-wcss-pcie-mpd"; + firmware = "IPQ5332/q6_fw3.mdt"; + qcom,halt-regs = <&tcsr_q6_block 0xa000 0x18 0x0>; + interrupts-extended = <&wcss_smp2p_in 24 0>, + <&wcss_smp2p_in 25 0>, + <&wcss_smp2p_in 28 0>, + <&wcss_smp2p_in 27 0>; + interrupt-names = "fatal", + "ready", + "spawn-ack", + "stop-ack"; + + qcom,smem-states = <&wcss_smp2p_out 24>, + <&wcss_smp2p_out 25>, + <&wcss_smp2p_out 26>; + qcom,smem-state-names = "shutdown", + "stop", + "spawn"; + status = "disabled"; + }; + }; + + apss_clk: qcom,apss_clk@b111000 { + compatible = "qcom,apss-ipq5332"; + reg = <0xb111000 0x6000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + msm_imem: qcom,msm-imem@8600000 { + compatible = "qcom,msm-imem"; + reg = <0x08600000 0x1000>; + ranges = <0x0 0x08600000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + + tz-log-buf-addr@720 { + compatible = "qcom,msm-imem-tz-log-buf-addr"; + reg = <0x720 4>; + }; + + restart-reason-buf-addr@7a4 { + compatible = "qcom,msm-imem-restart-reason-buf-addr"; + reg = <0x7a4 4>; + }; + }; + + qfprom_nvmem: qfprom_nvmem@a4000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "qcom,qfprom"; + reg = <0xa4000 0x721>; + + cpu_speed_bin: cpu_speed_bin@1d { + reg = <0x1d 0x2>; + bits = <7 2>; + }; + + tsens_calib_sel: calib@3E0 { + reg = <0x3E0 0x4>; + }; + + tsens_calib_offset: calib@3A4 { + reg = <0x3A4 0xC>; + }; + + pcie0_disable: pcie0_disable@25 { + reg = <0x25 0x1>; + bits = <3 1>; + }; + + pcie1_disable: pcie1_disable@25 { + reg = <0x25 0x1>; + bits = <4 1>; + }; + + pcie2_disable: pcie2_disable@25 { + reg = <0x25 0x1>; + bits = <2 1>; + }; + }; + }; + + license_manager { + compatible = "qti,license-manager-service"; + device-license-termination; + }; + +/* gpio_keys { + compatible = "gpio-keys"; + pinctrl-0 = <&button_pins>; + pinctrl-names = "default"; + status = "ok"; + + button@1 { + label = "wps"; + linux,code = ; + gpios = <&tlmm 35 GPIO_ACTIVE_LOW>; + linux,input-type = <1>; + debounce-interval = <60>; + }; + };*/ + + pmu { + compatible = "arm,cortex-a53-pmu"; + interrupts = ; + }; + + pmu-v7 { + compatible = "arm,cortex-a7-pmu"; + interrupts = ; + }; + + qti,tzlog { + compatible = "qti,tzlog-ipq5332"; + interrupts = ; + qti,tz-diag-buf-size = <0x3000>; + qti,tz-ring-off = <7>; + qti,tz-log-pos-info-off = <810>; + }; + + qti,scm_restart_reason { + compatible = "qti_ipq5332,scm_restart_reason"; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + qti,sps { + compatible = "qti,msm-sps-4k"; + qti,pipe-attr-ee; + }; + + + qcom,test@0 { + compatible = "qcom,testmhi"; + qcom,wlan-ramdump-dynamic = <0x600000>; + }; + + qti,gadget_diag@0 { + compatible = "qti,gadget-diag"; + status = "disabled"; + }; + + ctx_save: ctx-save { + compatible = "qti,ctxt-save-ipq5332"; + }; + + qseecom: qseecom { + compatible = "ipq9574-qseecom"; + memory-region = <&tzapp>; + status = "ok"; + }; +}; + +#include "ipq5332-coresight.dtsi" +#include "ipq5332-thermal.dtsi" diff --git a/feeds/ipq95xx/ipq53xx/generic/config-default b/feeds/ipq95xx/ipq53xx/generic/config-default new file mode 100644 index 000000000..559bf95ba --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/generic/config-default @@ -0,0 +1,72 @@ +# CONFIG_32BIT is not set +CONFIG_64BIT=y +# CONFIG_ACPI is not set +# CONFIG_ARCH_BCM_IPROC is not set +# CONFIG_ARCH_EXYNOS7 is not set +CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y +CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y +# CONFIG_ARCH_LAYERSCAPE is not set +CONFIG_ARCH_PHYS_ADDR_T_64BIT=y +# CONFIG_ARCH_SEATTLE is not set +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +# CONFIG_ARCH_SPRD is not set +# CONFIG_ARCH_STRATIX10 is not set +# CONFIG_ARCH_THUNDER is not set +CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y +CONFIG_ARCH_WANT_FRAME_POINTERS=y +CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y +# CONFIG_ARCH_XGENE is not set +# CONFIG_ARCH_ZYNQMP is not set +CONFIG_ARM64=y +# CONFIG_ARM64_16K_PAGES is not set +CONFIG_ARM64_4K_PAGES=y +# CONFIG_ARM64_64K_PAGES is not set +# CONFIG_ARM64_CRYPTO is not set +# CONFIG_ARM64_ERRATUM_819472 is not set +# CONFIG_ARM64_ERRATUM_824069 is not set +# CONFIG_ARM64_ERRATUM_826319 is not set +# CONFIG_ARM64_ERRATUM_827319 is not set +# CONFIG_ARM64_ERRATUM_832075 is not set +# CONFIG_ARM64_ERRATUM_843419 is not set +# CONFIG_ARM64_ERRATUM_845719 is not set +CONFIG_ARM64_HW_AFDBM=y +# CONFIG_ARM64_LSE_ATOMICS is not set +CONFIG_ARM64_PAN=y +# CONFIG_ARM64_PTDUMP is not set +# CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set +CONFIG_ARM64_VA_BITS=39 +CONFIG_ARM64_VA_BITS_39=y +# CONFIG_ARM64_VA_BITS_48 is not set +# CONFIG_ARMV8_DEPRECATED is not set +# CONFIG_CAVIUM_ERRATUM_22375 is not set +# CONFIG_CAVIUM_ERRATUM_23154 is not set +# CONFIG_CAVIUM_ERRATUM_27456 is not set +# CONFIG_COMMON_CLK_VERSATILE is not set +CONFIG_COMMON_CLK_XGENE=y +CONFIG_COMPAT=y +CONFIG_COMPAT_BINFMT_ELF=y +# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set +# CONFIG_DEBUG_ALIGN_RODATA is not set +CONFIG_FRAME_WARN=2048 +# CONFIG_GPIO_XGENE is not set +# CONFIG_HUGETLBFS is not set +# CONFIG_I2C_CADENCE is not set +# CONFIG_KASAN is not set +# CONFIG_KVM is not set +# CONFIG_NET_VENDOR_CAVIUM is not set +# CONFIG_PCI_HISI is not set +CONFIG_PHYS_ADDR_T_64BIT=y +# CONFIG_PHY_XGENE is not set +# CONFIG_POWER_RESET_XGENE is not set +CONFIG_QCOM_SCM_64=y +# CONFIG_RTC_DRV_EFI is not set +CONFIG_SPARSEMEM=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_VIRTUALIZATION=y +CONFIG_ARM64_CRYPTO=y +CONFIG_CRYPTO_AES_ARM64_CE=y diff --git a/feeds/ipq95xx/ipq53xx/generic/target.mk b/feeds/ipq95xx/ipq53xx/generic/target.mk new file mode 100644 index 000000000..36dffc459 --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/generic/target.mk @@ -0,0 +1,12 @@ + +SUBTARGET:=generic +BOARDNAME:=QTI IPQ53xx(64bit) based boards +CPU_TYPE:=cortex-a53 +KERNELNAME:=Image dtbs + +DEFAULT_PACKAGES += \ + sysupgrade-helper + +define Target/Description + Build images for IPQ53xx 64 bit system. +endef diff --git a/feeds/ipq95xx/ipq53xx/image/Makefile b/feeds/ipq95xx/ipq53xx/image/Makefile new file mode 100644 index 000000000..810322cec --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/image/Makefile @@ -0,0 +1,26 @@ +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/image.mk + +IMG_PREFIX:=$(VERSION_DIST_SANITIZED)-$(IMG_PREFIX_VERNUM)$(IMG_PREFIX_VERCODE)$(IMG_PREFIX_EXTRA)$(BOARD) + +# default all platform image(fit) build +define Device/Default + PROFILES = Default $$(DEVICE_NAME) + FILESYSTEMS := squashfs + DEVICE_DTS_DIR := $(DTS_DIR)/qcom + KERNEL_IN_UBI := 1 + ROOTFSNAME_IN_UBI := ubi_rootfs + BLOCKSIZE := 128k + PAGESIZE := 2048 + IMAGES := sysupgrade.tar nand-factory.bin + IMAGE/sysupgrade.tar := sysupgrade-tar | append-metadata + IMAGE/nand-factory.bin := append-ubi | qsdk-ipq-factory-nand + KERNEL_NAME := Image + KERNEL = kernel-bin | gzip | fit gzip $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb + #KERNEL_INITRAMFS = kernel-bin | gzip | fit gzip $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb + KERNEL_INITRAMFS = kernel-bin | fit none $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb +endef + +include ipq53xx.mk + +$(eval $(call BuildImage)) diff --git a/feeds/ipq95xx/ipq53xx/image/ipq53xx.mk b/feeds/ipq95xx/ipq53xx/image/ipq53xx.mk new file mode 100644 index 000000000..3d693c0c7 --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/image/ipq53xx.mk @@ -0,0 +1,25 @@ +KERNEL_LOADADDR := 0x40080000 + +define Device/cig_wf189 + DEVICE_TITLE := CIG WF189 + DEVICE_DTS := ipq5332-cig-wf189 + DEVICE_DTS_CONFIG := config@mi01.6 + IMAGES := sysupgrade.tar nand-factory.bin nand-factory.ubi + IMAGE/sysupgrade.tar := sysupgrade-tar | append-metadata + IMAGE/nand-factory.bin := append-ubi | qsdk-ipq-factory-nand + IMAGE/nand-factory.ubi := append-ubi + DEVICE_PACKAGES := ath12k-wifi-cig-wf189 ath12k-firmware-qcn92xx-split-phy ath12k-firmware-ipq53xx +endef +TARGET_DEVICES += cig_wf189 + +define Device/sercomm_ap72tip + DEVICE_TITLE := Sercomm AP72 TIP + DEVICE_DTS := ipq5332-sercomm-ap72tip + DEVICE_DTS_CONFIG := config@mi01.2-qcn9160-c1 + IMAGES := sysupgrade.tar nand-factory.bin nand-factory.ubi + IMAGE/sysupgrade.tar := sysupgrade-tar | append-metadata + IMAGE/nand-factory.bin := append-ubi | qsdk-ipq-factory-nand + IMAGE/nand-factory.ubi := append-ubi + DEVICE_PACKAGES := ath12k-wifi-sercomm-ap72tip ath12k-firmware-qcn92xx-split-phy ath12k-firmware-ipq53xx +endef +TARGET_DEVICES += sercomm_ap72tip diff --git a/feeds/ipq95xx/ipq53xx/ipq95xx_32/config-default b/feeds/ipq95xx/ipq53xx/ipq95xx_32/config-default new file mode 100644 index 000000000..9e7800137 --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/ipq95xx_32/config-default @@ -0,0 +1,6 @@ +CONFIG_ARCH_IPQ9574=y +CONFIG_ARCH_MMAP_RND_BITS=8 +CONFIG_PCIE_DW_PLAT=y +# CONFIG_USB_QCOM_DIAG_BRIDGE is not set +CONFIG_VMSPLIT_1G=y +# CONFIG_VMSPLIT_3G is not set diff --git a/feeds/ipq95xx/ipq53xx/ipq95xx_32/target.mk b/feeds/ipq95xx/ipq53xx/ipq95xx_32/target.mk new file mode 100644 index 000000000..04d4fa53c --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/ipq95xx_32/target.mk @@ -0,0 +1,13 @@ + +ARCH:=arm +SUBTARGET:=ipq95xx_32 +BOARDNAME:=QTI IPQ95xx(32bit) based boards +CPU_TYPE:=cortex-a7 + +DEFAULT_PACKAGES += \ + uboot-2016-ipq9574 -uboot-2016-ipq95xx_tiny -lk-ipq95xx \ + fwupgrade-tools + +define Target/Description + Build firmware image for IPQ95xx SoC devices. +endef diff --git a/feeds/ipq95xx/ipq53xx/modules.mk b/feeds/ipq95xx/ipq53xx/modules.mk new file mode 100644 index 000000000..405d8e104 --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/modules.mk @@ -0,0 +1,61 @@ +define KernelPackage/usb-dwc3-internal + TITLE:=DWC3 USB controller driver + DEPENDS:=+USB_GADGET_SUPPORT:kmod-usb-gadget + KCONFIG:= \ + CONFIG_USB_DWC3 \ + CONFIG_USB_DWC3_HOST=n \ + CONFIG_USB_DWC3_GADGET=n \ + CONFIG_USB_DWC3_DUAL_ROLE=y \ + CONFIG_EXTCON=y \ + CONFIG_USB_DWC3_DEBUG=n \ + CONFIG_USB_DWC3_VERBOSE=n + FILES:= $(LINUX_DIR)/drivers/usb/dwc3/dwc3.ko + AUTOLOAD:=$(call AutoLoad,84,dwc3) + $(call AddPlatformDepends/usb) +endef + +define KernelPackage/usb-dwc3-internal/description + This driver provides support for the Dual Role SuperSpeed + USB Controller based on the Synopsys DesignWare USB3 IP Core +endef + +$(eval $(call KernelPackage,usb-dwc3-internal)) + +define KernelPackage/usb-dwc3-qcom-internal + TITLE:=DWC3 QTI USB driver + DEPENDS:=@!LINUX_4_14 @(TARGET_ipq40xx||TARGET_ipq806x||TARGET_ipq807x||TARGET_ipq60xx||TARGET_ipq95xx||TARGET_ipq50xx||TARGET_ipq53xx) +kmod-usb-dwc3-internal + KCONFIG:= CONFIG_USB_DWC3_QCOM + FILES:= $(LINUX_DIR)/drivers/usb/dwc3/dwc3-qcom.ko + AUTOLOAD:=$(call AutoLoad,83,dwc3-qcom) + $(call AddPlatformDepends/usb) +endef + +define KernelPackage/usb-dwc3-qcom-internal/description + Some QTI SoCs use DesignWare Core IP for USB2/3 functionality. + This driver also handles Qscratch wrapper which is needed for + peripheral mode support. +endef + +$(eval $(call KernelPackage,usb-dwc3-qcom-internal)) + +define KernelPackage/usb-phy-ipq807x + TITLE:=DWC3 USB QTI PHY drivers for IPQ807x based targets + DEPENDS:=@TARGET_ipq||TARGET_ipq807x||TARGET_ipq95xx||TARGET_ipq60xx + KCONFIG:= \ + CONFIG_PHY_QCOM_QUSB2 \ + CONFIG_PHY_QCOM_QMP=y \ + CONFIG_USB_QCOM_QUSB_PHY \ + CONFIG_USB_QCOM_QMP_PHY + FILES:= \ + $(LINUX_DIR)/drivers/phy/qualcomm/phy-qcom-qusb2.ko@ge5.4 \ + $(LINUX_DIR)/drivers/usb/phy/phy-msm-qusb.ko@le4.4 \ + $(LINUX_DIR)/drivers/usb/phy/phy-msm-ssusb-qmp.ko@le4.4 + AUTOLOAD:=$(call AutoLoad,85,phy-qcom-qusb2 phy-msm-qusb phy-msm-ssusb-qmp) + $(call AddPlatformDepends/usb) +endef + +define KernelPackage/usb-phy-ipq807x/description + Support for USB PHY drivers in IPQ807x based SoCs. +endef + +$(eval $(call KernelPackage,usb-phy-ipq807x)) diff --git a/feeds/ipq95xx/ipq53xx/patches/001-ip6mr.patch b/feeds/ipq95xx/ipq53xx/patches/001-ip6mr.patch new file mode 100644 index 000000000..fa06c0092 --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/patches/001-ip6mr.patch @@ -0,0 +1,13 @@ +Index: linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/net/ipv6/ip6mr.c +=================================================================== +--- linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d.orig/net/ipv6/ip6mr.c ++++ linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/net/ipv6/ip6mr.c +@@ -105,7 +105,7 @@ static ip6mr_mfc_event_offload_callback_ + + #ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES + #define ip6mr_for_each_table(mrt, net) \ +- list_for_each_entry_rcu(mrt, &net->ipv6.mr_tables, list) ++ list_for_each_entry_rcu(mrt, &net->ipv6.mr6_tables, list) + + static struct mr_table *ip6mr_mr_table_iter(struct net *net, + struct mr_table *mrt) diff --git a/feeds/ipq95xx/ipq53xx/patches/002-dload_dis.patch b/feeds/ipq95xx/ipq53xx/patches/002-dload_dis.patch new file mode 100644 index 000000000..9ed342008 --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/patches/002-dload_dis.patch @@ -0,0 +1,24 @@ +Index: linux-5.4.213-qsdk-f2ee796db820cd8261889849f043c9c816196452/arch/arm64/boot/dts/qcom/ipq6018.dtsi +=================================================================== +--- linux-5.4.213-qsdk-f2ee796db820cd8261889849f043c9c816196452.orig/arch/arm64/boot/dts/qcom/ipq6018.dtsi ++++ linux-5.4.213-qsdk-f2ee796db820cd8261889849f043c9c816196452/arch/arm64/boot/dts/qcom/ipq6018.dtsi +@@ -1882,6 +1882,7 @@ + + qti,scm_restart_reason { + compatible = "qti_ipq6018,scm_restart_reason"; ++ dload_status = <1>; + }; + + ctx_save: ctx-save { +Index: linux-5.4.213-qsdk-f2ee796db820cd8261889849f043c9c816196452/arch/arm64/boot/dts/qcom/ipq9574.dtsi +=================================================================== +--- linux-5.4.213-qsdk-f2ee796db820cd8261889849f043c9c816196452.orig/arch/arm64/boot/dts/qcom/ipq9574.dtsi ++++ linux-5.4.213-qsdk-f2ee796db820cd8261889849f043c9c816196452/arch/arm64/boot/dts/qcom/ipq9574.dtsi +@@ -3678,6 +3678,7 @@ + + qti,scm_restart_reason { + compatible = "qti_ipq9574,scm_restart_reason"; ++ dload_status = <1>; + }; + + qti,gadget_diag@0 { diff --git a/feeds/ipq95xx/ipq53xx/patches/100-GPIO-add-named-gpio-exports.patch b/feeds/ipq95xx/ipq53xx/patches/100-GPIO-add-named-gpio-exports.patch new file mode 100644 index 000000000..0bc92b6b5 --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/patches/100-GPIO-add-named-gpio-exports.patch @@ -0,0 +1,173 @@ +From 4267880319bc1a2270d352e0ded6d6386242a7ef Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Tue, 12 Aug 2014 20:49:27 +0200 +Subject: [PATCH 24/53] GPIO: add named gpio exports + +Signed-off-by: John Crispin +--- + drivers/gpio/gpiolib-of.c | 68 +++++++++++++++++++++++++++++++++++++++++ + drivers/gpio/gpiolib-sysfs.c | 10 +++++- + include/asm-generic/gpio.h | 6 ++++ + include/linux/gpio/consumer.h | 8 +++++ + 4 files changed, 91 insertions(+), 1 deletion(-) + +Index: linux-5.4.213-qsdk-f2ee796db820cd8261889849f043c9c816196452/drivers/gpio/gpiolib-of.c +=================================================================== +--- linux-5.4.213-qsdk-f2ee796db820cd8261889849f043c9c816196452.orig/drivers/gpio/gpiolib-of.c ++++ linux-5.4.213-qsdk-f2ee796db820cd8261889849f043c9c816196452/drivers/gpio/gpiolib-of.c +@@ -19,6 +19,8 @@ + #include + #include + #include ++#include ++#include + + #include "gpiolib.h" + #include "gpiolib-of.h" +@@ -917,3 +919,68 @@ void of_gpiochip_remove(struct gpio_chip + { + of_node_put(chip->of_node); + } ++ ++static struct of_device_id gpio_export_ids[] = { ++ { .compatible = "gpio-export" }, ++ { /* sentinel */ } ++}; ++ ++static int of_gpio_export_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct device_node *cnp; ++ u32 val; ++ int nb = 0; ++ ++ for_each_child_of_node(np, cnp) { ++ const char *name = NULL; ++ int gpio; ++ bool dmc; ++ int max_gpio = 1; ++ int i; ++ ++ of_property_read_string(cnp, "gpio-export,name", &name); ++ ++ if (!name) ++ max_gpio = of_gpio_count(cnp); ++ ++ for (i = 0; i < max_gpio; i++) { ++ unsigned flags = 0; ++ enum of_gpio_flags of_flags; ++ ++ gpio = of_get_gpio_flags(cnp, i, &of_flags); ++ if (!gpio_is_valid(gpio)) ++ return gpio; ++ ++ if (of_flags == OF_GPIO_ACTIVE_LOW) ++ flags |= GPIOF_ACTIVE_LOW; ++ ++ if (!of_property_read_u32(cnp, "gpio-export,output", &val)) ++ flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; ++ else ++ flags |= GPIOF_IN; ++ ++ if (devm_gpio_request_one(&pdev->dev, gpio, flags, name ? name : of_node_full_name(np))) ++ continue; ++ ++ dmc = of_property_read_bool(cnp, "gpio-export,direction_may_change"); ++ gpio_export_with_name(gpio, dmc, name); ++ nb++; ++ } ++ } ++ ++ dev_info(&pdev->dev, "%d gpio(s) exported\n", nb); ++ ++ return 0; ++} ++ ++static struct platform_driver gpio_export_driver = { ++ .driver = { ++ .name = "gpio-export", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(gpio_export_ids), ++ }, ++ .probe = of_gpio_export_probe, ++}; ++ ++module_platform_driver(gpio_export_driver); +Index: linux-5.4.213-qsdk-f2ee796db820cd8261889849f043c9c816196452/drivers/gpio/gpiolib-sysfs.c +=================================================================== +--- linux-5.4.213-qsdk-f2ee796db820cd8261889849f043c9c816196452.orig/drivers/gpio/gpiolib-sysfs.c ++++ linux-5.4.213-qsdk-f2ee796db820cd8261889849f043c9c816196452/drivers/gpio/gpiolib-sysfs.c +@@ -571,7 +571,7 @@ static struct class gpio_class = { + * + * Returns zero on success, else an error. + */ +-int gpiod_export(struct gpio_desc *desc, bool direction_may_change) ++int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name) + { + struct gpio_chip *chip; + struct gpio_device *gdev; +@@ -633,6 +633,8 @@ int gpiod_export(struct gpio_desc *desc, + offset = gpio_chip_hwgpio(desc); + if (chip->names && chip->names[offset]) + ioname = chip->names[offset]; ++ if (name) ++ ioname = name; + + dev = device_create_with_groups(&gpio_class, &gdev->dev, + MKDEV(0, 0), data, gpio_groups, +@@ -654,6 +656,12 @@ err_unlock: + gpiod_dbg(desc, "%s: status %d\n", __func__, status); + return status; + } ++EXPORT_SYMBOL_GPL(__gpiod_export); ++ ++int gpiod_export(struct gpio_desc *desc, bool direction_may_change) ++{ ++ return __gpiod_export(desc, direction_may_change, NULL); ++} + EXPORT_SYMBOL_GPL(gpiod_export); + + static int match_export(struct device *dev, const void *desc) +Index: linux-5.4.213-qsdk-f2ee796db820cd8261889849f043c9c816196452/include/asm-generic/gpio.h +=================================================================== +--- linux-5.4.213-qsdk-f2ee796db820cd8261889849f043c9c816196452.orig/include/asm-generic/gpio.h ++++ linux-5.4.213-qsdk-f2ee796db820cd8261889849f043c9c816196452/include/asm-generic/gpio.h +@@ -127,6 +127,12 @@ static inline int gpio_export(unsigned g + return gpiod_export(gpio_to_desc(gpio), direction_may_change); + } + ++int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name); ++static inline int gpio_export_with_name(unsigned gpio, bool direction_may_change, const char *name) ++{ ++ return __gpiod_export(gpio_to_desc(gpio), direction_may_change, name); ++} ++ + static inline int gpio_export_link(struct device *dev, const char *name, + unsigned gpio) + { +Index: linux-5.4.213-qsdk-f2ee796db820cd8261889849f043c9c816196452/include/linux/gpio/consumer.h +=================================================================== +--- linux-5.4.213-qsdk-f2ee796db820cd8261889849f043c9c816196452.orig/include/linux/gpio/consumer.h ++++ linux-5.4.213-qsdk-f2ee796db820cd8261889849f043c9c816196452/include/linux/gpio/consumer.h +@@ -668,6 +668,7 @@ static inline void devm_acpi_dev_remove_ + + #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS) + ++int _gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name); + int gpiod_export(struct gpio_desc *desc, bool direction_may_change); + int gpiod_export_link(struct device *dev, const char *name, + struct gpio_desc *desc); +@@ -675,6 +676,13 @@ void gpiod_unexport(struct gpio_desc *de + + #else /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */ + ++static inline int _gpiod_export(struct gpio_desc *desc, ++ bool direction_may_change, ++ const char *name) ++{ ++ return -ENOSYS; ++} ++ + static inline int gpiod_export(struct gpio_desc *desc, + bool direction_may_change) + { diff --git a/feeds/ipq95xx/ipq53xx/patches/100-bpf-Fix-the-off-by-two-error-in-range-markings.patch b/feeds/ipq95xx/ipq53xx/patches/100-bpf-Fix-the-off-by-two-error-in-range-markings.patch new file mode 100644 index 000000000..f0f318992 --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/patches/100-bpf-Fix-the-off-by-two-error-in-range-markings.patch @@ -0,0 +1,151 @@ +From: Maxim Mikityanskiy +Date: Tue, 30 Nov 2021 20:16:07 +0200 +Subject: [PATCH] bpf: Fix the off-by-two error in range markings + +commit 2fa7d94afc1afbb4d702760c058dc2d7ed30f226 upstream. + +The first commit cited below attempts to fix the off-by-one error that +appeared in some comparisons with an open range. Due to this error, +arithmetically equivalent pieces of code could get different verdicts +from the verifier, for example (pseudocode): + + // 1. Passes the verifier: + if (data + 8 > data_end) + return early + read *(u64 *)data, i.e. [data; data+7] + + // 2. Rejected by the verifier (should still pass): + if (data + 7 >= data_end) + return early + read *(u64 *)data, i.e. [data; data+7] + +The attempted fix, however, shifts the range by one in a wrong +direction, so the bug not only remains, but also such piece of code +starts failing in the verifier: + + // 3. Rejected by the verifier, but the check is stricter than in #1. + if (data + 8 >= data_end) + return early + read *(u64 *)data, i.e. [data; data+7] + +The change performed by that fix converted an off-by-one bug into +off-by-two. The second commit cited below added the BPF selftests +written to ensure than code chunks like #3 are rejected, however, +they should be accepted. + +This commit fixes the off-by-two error by adjusting new_range in the +right direction and fixes the tests by changing the range into the +one that should actually fail. + +Fixes: fb2a311a31d3 ("bpf: fix off by one for range markings with L{T, E} patterns") +Fixes: b37242c773b2 ("bpf: add test cases to bpf selftests to cover all access tests") +Signed-off-by: Maxim Mikityanskiy +Signed-off-by: Daniel Borkmann +Link: https://lore.kernel.org/bpf/20211130181607.593149-1-maximmi@nvidia.com +Signed-off-by: Greg Kroah-Hartman +--- + +Index: linux-5.4.213-qsdk-f2ee796db820cd8261889849f043c9c816196452/tools/testing/selftests/bpf/verifier/xdp_direct_packet_access.c +=================================================================== +--- linux-5.4.213-qsdk-f2ee796db820cd8261889849f043c9c816196452.orig/tools/testing/selftests/bpf/verifier/xdp_direct_packet_access.c ++++ linux-5.4.213-qsdk-f2ee796db820cd8261889849f043c9c816196452/tools/testing/selftests/bpf/verifier/xdp_direct_packet_access.c +@@ -202,10 +202,10 @@ + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, + offsetof(struct xdp_md, data_end)), + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), +- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), + BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1), + BPF_JMP_IMM(BPF_JA, 0, 0, 1), +- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, +@@ -293,10 +293,10 @@ + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, + offsetof(struct xdp_md, data_end)), + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), +- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), + BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1), + BPF_JMP_IMM(BPF_JA, 0, 0, 1), +- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, +@@ -469,9 +469,9 @@ + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, + offsetof(struct xdp_md, data_end)), + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), +- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), + BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1), +- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, +@@ -740,9 +740,9 @@ + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, + offsetof(struct xdp_md, data_end)), + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), +- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), + BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1), +- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, +@@ -918,10 +918,10 @@ + offsetof(struct xdp_md, data_meta)), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), +- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), + BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1), + BPF_JMP_IMM(BPF_JA, 0, 0, 1), +- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, +@@ -1009,10 +1009,10 @@ + offsetof(struct xdp_md, data_meta)), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), +- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), + BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1), + BPF_JMP_IMM(BPF_JA, 0, 0, 1), +- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, +@@ -1185,9 +1185,9 @@ + offsetof(struct xdp_md, data_meta)), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), +- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), + BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1), +- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, +@@ -1456,9 +1456,9 @@ + offsetof(struct xdp_md, data_meta)), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), +- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), + BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1), +- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, diff --git a/feeds/ipq95xx/ipq53xx/patches/102-kernel-extable.c-use-address-of-operator-on-section-.patch b/feeds/ipq95xx/ipq53xx/patches/102-kernel-extable.c-use-address-of-operator-on-section-.patch new file mode 100644 index 000000000..ef1683103 --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/patches/102-kernel-extable.c-use-address-of-operator-on-section-.patch @@ -0,0 +1,38 @@ +From: Nathan Chancellor +Date: Mon, 6 Apr 2020 20:09:27 -0700 +Subject: [PATCH] kernel/extable.c: use address-of operator on section symbols + +Clang warns: + +../kernel/extable.c:37:52: warning: array comparison always evaluates to +a constant [-Wtautological-compare] + if (main_extable_sort_needed && __stop___ex_table > __start___ex_table) { + ^ +1 warning generated. + +These are not true arrays, they are linker defined symbols, which are just +addresses. Using the address of operator silences the warning and does +not change the resulting assembly with either clang/ld.lld or gcc/ld +(tested with diff + objdump -Dr). + +Suggested-by: Nick Desaulniers +Signed-off-by: Nathan Chancellor +Signed-off-by: Andrew Morton +Reviewed-by: Andrew Morton +Link: https://github.com/ClangBuiltLinux/linux/issues/892 +Link: http://lkml.kernel.org/r/20200219202036.45702-1-natechancellor@gmail.com +Signed-off-by: Linus Torvalds +--- + +--- a/kernel/extable.c ++++ b/kernel/extable.c +@@ -34,7 +34,8 @@ u32 __initdata __visible main_extable_so + /* Sort the kernel's built-in exception table */ + void __init sort_main_extable(void) + { +- if (main_extable_sort_needed && __stop___ex_table > __start___ex_table) { ++ if (main_extable_sort_needed && ++ &__stop___ex_table > &__start___ex_table) { + pr_notice("Sorting __ex_table...\n"); + sort_extable(__start___ex_table, __stop___ex_table); + } diff --git a/feeds/ipq95xx/ipq53xx/patches/103-fix_mhi_bus_test.patch b/feeds/ipq95xx/ipq53xx/patches/103-fix_mhi_bus_test.patch new file mode 100644 index 000000000..6b8af0796 --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/patches/103-fix_mhi_bus_test.patch @@ -0,0 +1,14 @@ +--- a/drivers/bus/mhi/test/mhitest_pci.c ++++ b/drivers/bus/mhi/test/mhitest_pci.c +@@ -547,11 +547,6 @@ int mhitest_pci_register_mhi(struct mhit + mplat->mhi_ctrl = mhi_ctrl; + dev_set_drvdata(&pci_dev->dev, mplat); + mhi_ctrl->cntrl_dev = &pci_dev->dev; +- +- if (!mplat->fw_name) { +- MHITEST_ERR("fw_name is NULLL\n"); +- return -EINVAL; +- } + mhi_ctrl->fw_image = mplat->fw_name; + + mhi_ctrl->regs = mplat->bar; diff --git a/feeds/ipq95xx/ipq53xx/patches/130-proxy-arp.patch b/feeds/ipq95xx/ipq53xx/patches/130-proxy-arp.patch new file mode 100644 index 000000000..323ad56c2 --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/patches/130-proxy-arp.patch @@ -0,0 +1,14 @@ +Index: linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/net/bridge/br_arp_nd_proxy.c +=================================================================== +--- linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d.orig/net/bridge/br_arp_nd_proxy.c ++++ linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/net/bridge/br_arp_nd_proxy.c +@@ -198,7 +198,8 @@ void br_do_proxy_suppress_arp(struct sk_ + + if ((p && (p->flags & BR_PROXYARP)) || + (f->dst && (f->dst->flags & (BR_PROXYARP_WIFI | +- BR_NEIGH_SUPPRESS)))) { ++ BR_NEIGH_SUPPRESS)) ++ && memcmp(sha, n->ha, 6))) { + if (!vid) + br_arp_send(br, p, skb->dev, sip, tip, + sha, n->ha, sha, 0, 0); diff --git a/feeds/ipq95xx/ipq53xx/patches/140-gcc12-fixes.patch b/feeds/ipq95xx/ipq53xx/patches/140-gcc12-fixes.patch new file mode 100644 index 000000000..c232d2f62 --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/patches/140-gcc12-fixes.patch @@ -0,0 +1,15 @@ +Index: linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/drivers/soc/qcom/ctx-save.c +=================================================================== +--- linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d.orig/drivers/soc/qcom/ctx-save.c ++++ linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/drivers/soc/qcom/ctx-save.c +@@ -1509,8 +1509,8 @@ static int ctx_save_probe(struct platfor + + #ifdef CONFIG_QCA_MINIDUMP + ret = register_module_notifier(&wlan_module_exit_nb); +- if (ret) +- dev_err(&pdev->dev, "Failed to register WLAN module exit notifier\n"); ++ if (ret) ++ dev_err(&pdev->dev, "Failed to register WLAN module exit notifier\n"); + + ret = atomic_notifier_chain_register(&panic_notifier_list, + &wlan_panic_nb); diff --git a/feeds/ipq95xx/ipq53xx/patches/200-pstore.patch b/feeds/ipq95xx/ipq53xx/patches/200-pstore.patch new file mode 100644 index 000000000..4af18c41f --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/patches/200-pstore.patch @@ -0,0 +1,49 @@ +Index: linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/arch/arm64/boot/dts/qcom/ipq6018-memory.dtsi +=================================================================== +--- linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d.orig/arch/arm64/boot/dts/qcom/ipq6018-memory.dtsi ++++ linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/arch/arm64/boot/dts/qcom/ipq6018-memory.dtsi +@@ -132,6 +132,14 @@ + reg = <0x0 0x4d400000 0x0 0x100000>; + }; + ++ ramoops@4d500000 { ++ compatible = "ramoops"; ++ reg = <0x0 0x4d500000 0x0 0x100000>; ++ record-size = <0x1000>; ++ console-size = <0x1000>; ++ pmsg-size = <0x1000>; ++ }; ++ + rpm_msg_ram: rpm_msg_ram@0x60000 { + no-map; + reg = <0x0 0x60000 0x0 0x6000>; +@@ -256,6 +264,14 @@ + reg = <0x0 0x4e300000 0x0 0x100000>; + }; + ++ ramoops@4e400000 { ++ compatible = "ramoops"; ++ reg = <0x0 0x4e400000 0x0 0x100000>; ++ record-size = <0x1000>; ++ console-size = <0x1000>; ++ pmsg-size = <0x1000>; ++ }; ++ + rpm_msg_ram: rpm_msg_ram@0x60000 { + no-map; + reg = <0x0 0x60000 0x0 0x6000>; +@@ -383,6 +399,14 @@ + reg = <0x0 0x50100000 0x0 0x100000>; + }; + ++ ramoops@50200000 { ++ compatible = "ramoops"; ++ reg = <0x0 0x50200000 0x0 0x100000>; ++ record-size = <0x1000>; ++ console-size = <0x1000>; ++ pmsg-size = <0x1000>; ++ }; ++ + rpm_msg_ram: rpm_msg_ram@0x60000 { + no-map; + reg = <0x0 0x60000 0x0 0x6000>; diff --git a/feeds/ipq95xx/ipq53xx/patches/238-net-core-Allow-live-renaming-when-an-interface-is-up.patch b/feeds/ipq95xx/ipq53xx/patches/238-net-core-Allow-live-renaming-when-an-interface-is-up.patch new file mode 100644 index 000000000..316060898 --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/patches/238-net-core-Allow-live-renaming-when-an-interface-is-up.patch @@ -0,0 +1,136 @@ +From: Andy Ren +Date: Mon, 7 Nov 2022 09:42:42 -0800 +Subject: [PATCH] net/core: Allow live renaming when an interface is up + +Allow a network interface to be renamed when the interface +is up. + +As described in the netconsole documentation [1], when netconsole is +used as a built-in, it will bring up the specified interface as soon as +possible. As a result, user space will not be able to rename the +interface since the kernel disallows renaming of interfaces that are +administratively up unless the 'IFF_LIVE_RENAME_OK' private flag was set +by the kernel. + +The original solution [2] to this problem was to add a new parameter to +the netconsole configuration parameters that allows renaming of +the interface used by netconsole while it is administratively up. +However, during the discussion that followed, it became apparent that we +have no reason to keep the current restriction and instead we should +allow user space to rename interfaces regardless of their administrative +state: + +1. The restriction was put in place over 20 years ago when renaming was +only possible via IOCTL and before rtnetlink started notifying user +space about such changes like it does today. + +2. The 'IFF_LIVE_RENAME_OK' flag was added over 3 years ago in version +5.2 and no regressions were reported. + +3. In-kernel listeners to 'NETDEV_CHANGENAME' do not seem to care about +the administrative state of interface. + +Therefore, allow user space to rename running interfaces by removing the +restriction and the associated 'IFF_LIVE_RENAME_OK' flag. Help in +possible triage by emitting a message to the kernel log that an +interface was renamed while UP. + +[1] https://www.kernel.org/doc/Documentation/networking/netconsole.rst +[2] https://lore.kernel.org/netdev/20221102002420.2613004-1-andy.ren@getcruise.com/ + +Signed-off-by: Andy Ren +Reviewed-by: Ido Schimmel +Reviewed-by: David Ahern +Signed-off-by: David S. Miller +--- + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -1503,7 +1503,6 @@ struct net_device_ops { + * @IFF_FAILOVER: device is a failover master device + * @IFF_FAILOVER_SLAVE: device is lower dev of a failover master device + * @IFF_L3MDEV_RX_HANDLER: only invoke the rx handler of L3 master device +- * @IFF_LIVE_RENAME_OK: rename is allowed while device is up and running + */ + enum netdev_priv_flags { + IFF_802_1Q_VLAN = 1<<0, +@@ -1536,7 +1535,7 @@ enum netdev_priv_flags { + IFF_FAILOVER = 1<<27, + IFF_FAILOVER_SLAVE = 1<<28, + IFF_L3MDEV_RX_HANDLER = 1<<29, +- IFF_LIVE_RENAME_OK = 1<<30, ++ /* was IFF_LIVE_RENAME_OK */ + IFF_NO_IP_ALIGN = 1<<31, + }; + +@@ -1595,7 +1594,6 @@ enum netdev_priv_flags_ext { + #define IFF_FAILOVER IFF_FAILOVER + #define IFF_FAILOVER_SLAVE IFF_FAILOVER_SLAVE + #define IFF_L3MDEV_RX_HANDLER IFF_L3MDEV_RX_HANDLER +-#define IFF_LIVE_RENAME_OK IFF_LIVE_RENAME_OK + #define IFF_NO_IP_ALIGN IFF_NO_IP_ALIGN + + /* Specifies the type of the struct net_device::ml_priv pointer */ +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -1093,22 +1093,6 @@ int dev_change_name(struct net_device *d + + net = dev_net(dev); + +- /* Some auto-enslaved devices e.g. failover slaves are +- * special, as userspace might rename the device after +- * the interface had been brought up and running since +- * the point kernel initiated auto-enslavement. Allow +- * live name change even when these slave devices are +- * up and running. +- * +- * Typically, users of these auto-enslaving devices +- * don't actually care about slave name change, as +- * they are supposed to operate on master interface +- * directly. +- */ +- if (dev->flags & IFF_UP && +- likely(!(dev->priv_flags & IFF_LIVE_RENAME_OK))) +- return -EBUSY; +- + down_write(&devnet_rename_sem); + + if (strncmp(newname, dev->name, IFNAMSIZ) == 0) { +@@ -1125,7 +1109,8 @@ int dev_change_name(struct net_device *d + } + + if (oldname[0] && !strchr(oldname, '%')) +- netdev_info(dev, "renamed from %s\n", oldname); ++ netdev_info(dev, "renamed from %s%s\n", oldname, ++ dev->flags & IFF_UP ? " (while UP)" : ""); + + old_assign_type = dev->name_assign_type; + dev->name_assign_type = NET_NAME_RENAMED; +--- a/net/core/failover.c ++++ b/net/core/failover.c +@@ -80,14 +80,14 @@ static int failover_slave_register(struc + goto err_upper_link; + } + +- slave_dev->priv_flags |= (IFF_FAILOVER_SLAVE | IFF_LIVE_RENAME_OK); ++ slave_dev->priv_flags |= IFF_FAILOVER_SLAVE; + + if (fops && fops->slave_register && + !fops->slave_register(slave_dev, failover_dev)) + return NOTIFY_OK; + + netdev_upper_dev_unlink(slave_dev, failover_dev); +- slave_dev->priv_flags &= ~(IFF_FAILOVER_SLAVE | IFF_LIVE_RENAME_OK); ++ slave_dev->priv_flags &= ~IFF_FAILOVER_SLAVE; + err_upper_link: + netdev_rx_handler_unregister(slave_dev); + done: +@@ -121,7 +121,7 @@ int failover_slave_unregister(struct net + + netdev_rx_handler_unregister(slave_dev); + netdev_upper_dev_unlink(slave_dev, failover_dev); +- slave_dev->priv_flags &= ~(IFF_FAILOVER_SLAVE | IFF_LIVE_RENAME_OK); ++ slave_dev->priv_flags &= ~IFF_FAILOVER_SLAVE; + + if (fops && fops->slave_unregister && + !fops->slave_unregister(slave_dev, failover_dev)) diff --git a/feeds/ipq95xx/ipq53xx/patches/300-pwm.patch b/feeds/ipq95xx/ipq53xx/patches/300-pwm.patch new file mode 100644 index 000000000..b283d159c --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/patches/300-pwm.patch @@ -0,0 +1,40 @@ +Index: linux-5.4.213-qsdk-b2d40c94fad765a48c03f492d669aeecbbb9b617/drivers/pwm/pwm-ipq.c +=================================================================== +--- linux-5.4.213-qsdk-b2d40c94fad765a48c03f492d669aeecbbb9b617.orig/drivers/pwm/pwm-ipq.c ++++ linux-5.4.213-qsdk-b2d40c94fad765a48c03f492d669aeecbbb9b617/drivers/pwm/pwm-ipq.c +@@ -110,6 +110,7 @@ struct ipq_pwm_chip { + + static ssize_t count; + static uint32_t used_pwm[MAX_PWM_DEVICES]; ++//static uint32_t dft_pwm[MAX_PWM_DEVICES]; + + static const uint32_t pwm_ctrl_register[] = { + ADSS_GLB_PWM0_CTRL_REG, +@@ -330,6 +331,7 @@ static int ipq_pwm_probe(struct platform + struct device *dev; + unsigned int base_index; + int ret; ++ //unsigned int i; + const void *dev_data; + unsigned long src_freq = SRC_FREQ; + struct resource *res = NULL; +@@ -387,6 +389,19 @@ static int ipq_pwm_probe(struct platform + dev_err(dev, "pwmchip_add() failed: %d\n", ret); + return ret; + } ++ ++ /*count = of_property_count_u32_elems(dev->of_node, "dft-pwm-status"); ++ if (!of_property_read_u32_array(dev->of_node, "dft-pwm-status", ++ dft_pwm, count)) { ++ for(i = 0; i < count; i++) { ++ if(dft_pwm[i] > 0) { ++ ipq_pwm_request(&(pwm->chip), &(pwm->chip.pwms[i])); ++ ipq_pwm_config(&(pwm->chip), &(pwm->chip.pwms[i]), 500000000, 1000000000); ++ } ++ } ++ }*/ ++ ipq_pwm_request(&(pwm->chip), &(pwm->chip.pwms[1])); ++ ipq_pwm_config(&(pwm->chip), &(pwm->chip.pwms[1]), 500000000, 1000000000); + + return 0; + } diff --git a/feeds/ipq95xx/ipq53xx/patches/301-button.patch b/feeds/ipq95xx/ipq53xx/patches/301-button.patch new file mode 100644 index 000000000..ad5e24709 --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/patches/301-button.patch @@ -0,0 +1,42 @@ +Index: linux-5.4.213-qsdk-b2d40c94fad765a48c03f492d669aeecbbb9b617/arch/arm64/boot/dts/qcom/ipq5332.dtsi +=================================================================== +--- linux-5.4.213-qsdk-b2d40c94fad765a48c03f492d669aeecbbb9b617.orig/arch/arm64/boot/dts/qcom/ipq5332.dtsi ++++ linux-5.4.213-qsdk-b2d40c94fad765a48c03f492d669aeecbbb9b617/arch/arm64/boot/dts/qcom/ipq5332.dtsi +@@ -918,15 +918,6 @@ + }; + }; + +- button_pins: button_pins { +- wps_button { +- pins = "gpio35"; +- function = "gpio"; +- drive-strength = <8>; +- bias-pull-up; +- }; +- }; +- + bt_pins: bt_pins { + PTA_0 { + pins = "gpio49"; +@@ -2577,21 +2568,6 @@ + device-license-termination; + }; + +- gpio_keys { +- compatible = "gpio-keys"; +- pinctrl-0 = <&button_pins>; +- pinctrl-names = "default"; +- status = "ok"; +- +- button@1 { +- label = "wps"; +- linux,code = ; +- gpios = <&tlmm 35 GPIO_ACTIVE_LOW>; +- linux,input-type = <1>; +- debounce-interval = <60>; +- }; +- }; +- + pmu { + compatible = "arm,cortex-a53-pmu"; + interrupts = ; diff --git a/feeds/ipq95xx/ipq53xx/patches/302-aq-phy.patch b/feeds/ipq95xx/ipq53xx/patches/302-aq-phy.patch new file mode 100644 index 000000000..ff3f1b518 --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/patches/302-aq-phy.patch @@ -0,0 +1,66 @@ +Index: linux-5.4.213-qsdk-b2d40c94fad765a48c03f492d669aeecbbb9b617/drivers/net/phy/aquantia_main.c +=================================================================== +--- linux-5.4.213-qsdk-b2d40c94fad765a48c03f492d669aeecbbb9b617.orig/drivers/net/phy/aquantia_main.c ++++ linux-5.4.213-qsdk-b2d40c94fad765a48c03f492d669aeecbbb9b617/drivers/net/phy/aquantia_main.c +@@ -31,6 +31,9 @@ + #define PHY_ID_AQCS109 0x03a1b5c2 + #define PHY_ID_AQR405 0x03a1b4b0 + ++#define PHY_ID_AQR114C 0x31c31c22 ++#define PHY_ID_AQR114C_B1 0x31c31c23 ++ + #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 + #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) + #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR 0 +@@ -1101,6 +1104,42 @@ static struct phy_driver aqr_driver[] = + .ack_interrupt = aqr_ack_interrupt, + .read_status = aqr_read_status, + }, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR114C), ++ .name = "Aquantia AQR114C", ++ .probe = aqr107_probe, ++ .config_init = aqr107_config_init, ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .ack_interrupt = aqr_ack_interrupt, ++ .read_status = aqr107_read_status, ++ .get_tunable = aqr107_get_tunable, ++ .set_tunable = aqr107_set_tunable, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++ .link_change_notify = aqr107_link_change_notify, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR114C_B1), ++ .name = "Aquantia AQR114C_B1", ++ .probe = aqr107_probe, ++ .config_init = aqr107_config_init, ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .ack_interrupt = aqr_ack_interrupt, ++ .read_status = aqr107_read_status, ++ .get_tunable = aqr107_get_tunable, ++ .set_tunable = aqr107_set_tunable, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++ .link_change_notify = aqr107_link_change_notify, ++}, + }; + + module_phy_driver(aqr_driver); +@@ -1120,6 +1159,8 @@ static struct mdio_device_id __maybe_unu + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR114C) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR114C_B1) }, + { } + }; + diff --git a/feeds/ipq95xx/ipq53xx/profiles/00-default.mk b/feeds/ipq95xx/ipq53xx/profiles/00-default.mk new file mode 100644 index 000000000..aab8678ed --- /dev/null +++ b/feeds/ipq95xx/ipq53xx/profiles/00-default.mk @@ -0,0 +1,10 @@ + +define Profile/Default + NAME:=Default Profile (minimum package set) + PACKAGES:= +endef + +define Profile/Default/Description + Default package set compatible with most boards. +endef +$(eval $(call Profile,Default)) diff --git a/feeds/ipq95xx/ipq95xx/Makefile b/feeds/ipq95xx/ipq95xx/Makefile index 082591d4b..5ed46a30e 100644 --- a/feeds/ipq95xx/ipq95xx/Makefile +++ b/feeds/ipq95xx/ipq95xx/Makefile @@ -12,7 +12,7 @@ SUBTARGETS:=generic ipq95xx_32 KERNELNAME:=zImage Image dtbs KERNEL_PATCHVER:=5.4 -KERNEL_NAME_SUFFIX=-qsdk-f2ee796db820cd8261889849f043c9c816196452 +KERNEL_NAME_SUFFIX=-qsdk-b2d40c94fad765a48c03f492d669aeecbbb9b617 include $(INCLUDE_DIR)/target.mk DEFAULT_PACKAGES += \ diff --git a/feeds/ipq95xx/ipq95xx/base-files/lib/upgrade/nand.sh b/feeds/ipq95xx/ipq95xx/base-files/lib/upgrade/nand.sh index 539f535c4..659892b81 100644 --- a/feeds/ipq95xx/ipq95xx/base-files/lib/upgrade/nand.sh +++ b/feeds/ipq95xx/ipq95xx/base-files/lib/upgrade/nand.sh @@ -247,8 +247,8 @@ nand_do_upgrade_success() { local conf_tar="/tmp/sysupgrade.tgz" sync [ "$CI_BOOTCFG" = 1 ] && nand_qca_update_bootconfig + [ -f "$conf_tar" ] && nand_restore_config "$conf_tar" && sync [ -n "$CI_FWSETENV" ] && fw_setenv $CI_FWSETENV - [ -f "$conf_tar" ] && nand_restore_config "$conf_tar" echo "sysupgrade successful" umount -a sleep 5 diff --git a/feeds/ipq95xx/ipq95xx/config-5.4 b/feeds/ipq95xx/ipq95xx/config-5.4 index 99d1fc633..d67ca01ed 100644 --- a/feeds/ipq95xx/ipq95xx/config-5.4 +++ b/feeds/ipq95xx/ipq95xx/config-5.4 @@ -1274,3 +1274,4 @@ CONFIG_INIT_STACK_NONE=y # CONFIG_SECCRYPT is not set CONFIG_HWMON=y # CONFIG_CORESIGHT_STREAM is not set +# CONFIG_QTI_HW_KEY is not set diff --git a/feeds/ipq95xx/iw/Makefile b/feeds/ipq95xx/iw/Makefile index 8f99cb747..ff527dbb2 100644 --- a/feeds/ipq95xx/iw/Makefile +++ b/feeds/ipq95xx/iw/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=iw -PKG_VERSION:=5.16 +PKG_VERSION:=5.19 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=https://www.kernel.org/pub/software/network/iw -PKG_HASH:=4c44e42762f903f9094ba5a598998c800a97a62afd6fd31ec1e0a799e308659c +PKG_HASH:=f167bbe947dd53bb9ebc0c1dcef5db6ad73ac1d6084f2c6f9376c5c360cc4d4e PKG_MAINTAINER:=Felix Fietkau PKG_LICENSE:=GPL-2.0 diff --git a/feeds/ipq95xx/iw/patches/001-nl80211_h_sync.patch b/feeds/ipq95xx/iw/patches/001-nl80211_h_sync.patch index eadddf5cd..ee9a72607 100644 --- a/feeds/ipq95xx/iw/patches/001-nl80211_h_sync.patch +++ b/feeds/ipq95xx/iw/patches/001-nl80211_h_sync.patch @@ -1,8 +1,8 @@ --- a/nl80211.h +++ b/nl80211.h -@@ -2639,6 +2639,9 @@ enum nl80211_commands { - * Mandatory parameter for the transmitting interface to enable MBSSID. - * Optional for the non-transmitting interfaces. +@@ -2663,6 +2663,9 @@ enum nl80211_commands { + * association request when used with NL80211_CMD_NEW_STATION). Can be set + * only if %NL80211_STA_FLAG_WME is set. * + * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce + * transmit power to stay within regulatory limits. u32, dBi. @@ -10,20 +10,26 @@ * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use -@@ -3145,6 +3148,20 @@ enum nl80211_attrs { - NL80211_ATTR_MBSSID_CONFIG, - NL80211_ATTR_MBSSID_ELEMS, +@@ -3177,6 +3180,26 @@ enum nl80211_attrs { + NL80211_ATTR_DISABLE_EHT, + ++ NL80211_ATTR_MLO_LINKS, ++ NL80211_ATTR_MLO_LINK_ID, ++ NL80211_ATTR_MLD_ADDR, ++ ++ NL80211_ATTR_MLO_SUPPORT, ++ ++ NL80211_ATTR_MAX_NUM_AKM_SUITES, ++ ++ NL80211_ATTR_EML_CAPABILITY, ++ NL80211_ATTR_MLD_CAPA_AND_OPS, ++ ++ NL80211_ATTR_TX_HW_TIMESTAMP, ++ NL80211_ATTR_RX_HW_TIMESTAMP, ++ + NL80211_ATTR_HE_MUEDCA_PARAMS, + -+ NL80211_ATTR_MULTIPLE_BSSID_PARENT, -+ NL80211_ATTR_MULTIPLE_BSSID_INDEX, -+ NL80211_ATTR_MULTIPLE_BSSID_COUNT, -+ NL80211_ATTR_MULTIPLE_BSSID_IES, -+ NL80211_ATTR_MULTIPLE_BSSID_EMA, -+ -+ NL80211_ATTR_RNR_OFFSETS, -+ + NL80211_ATTR_BEACON_TX_MODE, + + NL80211_ATTR_WIPHY_ANTENNA_GAIN, diff --git a/feeds/ipq95xx/iw/patches/502-Add-channel-attribure-support-for-nl80211-message.patch b/feeds/ipq95xx/iw/patches/502-Add-channel-attribure-support-for-nl80211-message.patch deleted file mode 100644 index 21dd5f4b9..000000000 --- a/feeds/ipq95xx/iw/patches/502-Add-channel-attribure-support-for-nl80211-message.patch +++ /dev/null @@ -1,40 +0,0 @@ -Add channel attribure support for nl80211 message - ---- - info.c | 9 +++++++-- - nl80211.h | 1 + - 2 files changed, 8 insertions(+), 2 deletions(-) - ---- a/info.c -+++ b/info.c -@@ -183,13 +183,18 @@ static int print_phy_handler(struct nl_m - band_had_freq = true; - } - nla_for_each_nested(nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) { -- uint32_t freq; -+ uint32_t freq,channel; - nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, nla_data(nl_freq), - nla_len(nl_freq), freq_policy); - if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ]) - continue; - freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]); -- printf("\t\t\t* %d MHz [%d]", freq, ieee80211_frequency_to_channel(freq)); -+ if (tb_freq[NL80211_FREQUENCY_ATTR_CHANNEL]) -+ channel = nla_get_u16(tb_freq[NL80211_FREQUENCY_ATTR_CHANNEL]); -+ else -+ channel = ieee80211_frequency_to_channel(freq); -+ printf("\t\t\t* %d MHz [%d]", freq, channel); -+ - - if (tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER] && - !tb_freq[NL80211_FREQUENCY_ATTR_DISABLED]) ---- a/nl80211.h -+++ b/nl80211.h -@@ -3802,6 +3802,7 @@ enum nl80211_frequency_attr { - NL80211_FREQUENCY_ATTR_NO_20MHZ, - NL80211_FREQUENCY_ATTR_NO_10MHZ, - NL80211_FREQUENCY_ATTR_WMM, -+ NL80211_FREQUENCY_ATTR_CHANNEL, - NL80211_FREQUENCY_ATTR_NO_HE, - NL80211_FREQUENCY_ATTR_OFFSET, - NL80211_FREQUENCY_ATTR_1MHZ, diff --git a/feeds/ipq95xx/iw/patches/522-iw-Add-MLO-support-in-interface-creation.patch b/feeds/ipq95xx/iw/patches/522-iw-Add-MLO-support-in-interface-creation.patch deleted file mode 100644 index 66e744d05..000000000 --- a/feeds/ipq95xx/iw/patches/522-iw-Add-MLO-support-in-interface-creation.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 72be4bb967e8081d4864619ff2afaad77e1956e2 Mon Sep 17 00:00:00 2001 -From: Vikram Kandukuri -Date: Wed, 20 Oct 2021 23:10:53 +0530 -Subject: [PATCH] iw: Add MLO support in interface creation - -Add MLO support in interface creation and add support to get -MLD mac address in dev info. - -Signed-off-by: Vikram Kandukuri ---- - interface.c | 27 ++++++++++++++++++++++++++- - nl80211.h | 3 +++ - 2 files changed, 29 insertions(+), 1 deletion(-) - -diff --git a/interface.c b/interface.c -index 57e2fe4..88b30e9 100644 ---- a/interface.c -+++ b/interface.c -@@ -236,7 +236,9 @@ static int handle_interface_add(struct nl80211_state *state, - enum nl80211_iftype type; - int tpset; - unsigned char mac_addr[ETH_ALEN]; -- int found_mac = 0; -+ unsigned char mld_mac_addr[ETH_ALEN]; -+ int found_mac = 0, found_mld_mac = 0; -+ char mac_temp[20]; - - if (argc < 1) - return 1; -@@ -287,6 +289,18 @@ try_another: - fprintf(stderr, "flags error\n"); - return 2; - } -+ } else if (strcmp(argv[0], "mld_addr") == 0) { -+ argc--; -+ argv++; -+ if (mac_addr_a2n(mld_mac_addr, argv[0])) { -+ fprintf(stderr, "Invalid MAC address\n"); -+ return 2; -+ } -+ argc--; -+ argv++; -+ found_mld_mac = 1; -+ mac_addr_n2a(mac_temp, mld_mac_addr); -+ goto try_another; - } else { - return 1; - } -@@ -302,6 +316,10 @@ try_another: - if (found_mac) - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); - -+ if (found_mld_mac) -+ NLA_PUT(msg, NL80211_ATTR_MLD_MAC, ETH_ALEN, mld_mac_addr); -+ -+ - return 0; - nla_put_failure: - return -ENOBUFS; -@@ -399,6 +417,13 @@ static int print_iface_handler(struct nl_msg *msg, void *arg) - mac_addr_n2a(mac_addr, nla_data(tb_msg[NL80211_ATTR_MAC])); - printf("%s\taddr %s\n", indent, mac_addr); - } -+ -+ if (tb_msg[NL80211_ATTR_MLD_MAC]) { -+ char mld_mac_addr[20]; -+ mac_addr_n2a(mld_mac_addr, nla_data(tb_msg[NL80211_ATTR_MLD_MAC])); -+ printf("%s\tmld_addr %s\n", indent, mld_mac_addr); -+ } -+ - if (tb_msg[NL80211_ATTR_SSID]) { - printf("%s\tssid ", indent); - print_ssid_escaped(nla_len(tb_msg[NL80211_ATTR_SSID]), -diff --git a/nl80211.h b/nl80211.h -index 174851b..5654aca 100644 ---- a/nl80211.h -+++ b/nl80211.h -@@ -3047,6 +3047,9 @@ enum nl80211_attrs { - - NL80211_ATTR_WIPHY_ANTENNA_GAIN, - -+ NL80211_ATTR_MLD_MAC=352, -+ NL80211_ATTR_MLD_REFERENCE=353, -+ - /* add attributes here, update the policy in nl80211.c */ - - __NL80211_ATTR_AFTER_LAST, --- -2.7.4 - diff --git a/feeds/ipq95xx/iw/patches/601-iw-update-nl80211.h.patch b/feeds/ipq95xx/iw/patches/601-iw-update-nl80211.h.patch index d256fa10b..b844de701 100644 --- a/feeds/ipq95xx/iw/patches/601-iw-update-nl80211.h.patch +++ b/feeds/ipq95xx/iw/patches/601-iw-update-nl80211.h.patch @@ -13,34 +13,33 @@ Signed-off-by: Muna Sinada --- a/nl80211.h +++ b/nl80211.h -@@ -3139,6 +3139,8 @@ enum nl80211_attrs { +@@ -1481,6 +1481,17 @@ enum nl80211_commands { - NL80211_ATTR_DISABLE_HE, + NL80211_CMD_ASSOC_COMEBACK, -+ NL80211_ATTR_HE_MUEDCA_PARAMS, ++ NL80211_CMD_ADD_LINK, ++ NL80211_CMD_REMOVE_LINK, + - NL80211_ATTR_OBSS_COLOR_BITMAP, ++ NL80211_CMD_ADD_LINK_STA, ++ NL80211_CMD_MODIFY_LINK_STA, ++ NL80211_CMD_REMOVE_LINK_STA, ++ ++ NL80211_CMD_UPDATE_HE_MUEDCA_PARAMS, ++ ++ NL80211_CMD_AWGN_DETECT, ++ + /* add new commands above here */ - NL80211_ATTR_COLOR_CHANGE_COUNT, -@@ -3148,15 +3150,9 @@ enum nl80211_attrs { - NL80211_ATTR_MBSSID_CONFIG, - NL80211_ATTR_MBSSID_ELEMS, + /* used to define NL80211_CMD_MAX below */ +@@ -3193,6 +3204,7 @@ enum nl80211_attrs { -- NL80211_ATTR_HE_MUEDCA_PARAMS, -- -- NL80211_ATTR_MULTIPLE_BSSID_PARENT, -- NL80211_ATTR_MULTIPLE_BSSID_INDEX, -- NL80211_ATTR_MULTIPLE_BSSID_COUNT, -- NL80211_ATTR_MULTIPLE_BSSID_IES, -- NL80211_ATTR_MULTIPLE_BSSID_EMA, -+ NL80211_ATTR_RADAR_BACKGROUND, + NL80211_ATTR_TX_HW_TIMESTAMP, + NL80211_ATTR_RX_HW_TIMESTAMP, ++ NL80211_ATTR_TD_BITMAP, -- NL80211_ATTR_RNR_OFFSETS, -+ NL80211_ATTR_AP_SETTINGS_FLAGS, + NL80211_ATTR_HE_MUEDCA_PARAMS, - NL80211_ATTR_BEACON_TX_MODE, - -@@ -3164,6 +3160,20 @@ enum nl80211_attrs { +@@ -3202,6 +3214,18 @@ enum nl80211_attrs { NL80211_ATTR_STA_MGMT_RTS_CTS_CONFIG, @@ -50,44 +49,16 @@ Signed-off-by: Muna Sinada + + NL80211_ATTR_EMA_RNR_ELEMS, + -+ NL80211_ATTR_EHT_CAPABILITY = NL80211_ATTR_MBSSID_ELEMS + 15, -+ -+ NL80211_ATTR_DISABLE_EHT, -+ + NL80211_ATTR_RU_PUNCT_SUPP_BW, ++ + NL80211_ATTR_RU_PUNCT_SUPP_HE, ++ + NL80211_ATTR_RU_PUNCT_BITMAP, + - NL80211_ATTR_MLD_MAC=352, - NL80211_ATTR_MLD_REFERENCE=353, + /* add attributes here, update the policy in nl80211.c */ -@@ -3429,6 +3439,13 @@ enum nl80211_he_ru_alloc { - * @NL80211_RATE_INFO_HE_DCM: HE DCM value (u8, 0/1) - * @NL80211_RATE_INFO_RU_ALLOC: HE RU allocation, if not present then - * non-OFDMA was used (u8, see &enum nl80211_he_ru_alloc) -+ * @NL80211_RATE_INFO_320_MHZ_WIDTH: 320 MHz bitrate -+ * @NL80211_RATE_INFO_EHT_MCS: EHT MCS index (u8, 0-15) -+ * @NL80211_RATE_INFO_EHT_NSS: EHT NSS value (u8, 1-8) -+ * @NL80211_RATE_INFO_EHT_GI: EHT guard interval identifier -+ * (u8, see &enum nl80211_eht_gi) -+ * @NL80211_RATE_INFO_EHT_RU_ALLOC: EHT RU allocation, if not present then -+ * non-OFDMA was used (u8, see &enum nl80211_eht_ru_alloc) - * @__NL80211_RATE_INFO_AFTER_LAST: internal use - */ - enum nl80211_rate_info { -@@ -3450,6 +3467,11 @@ enum nl80211_rate_info { - NL80211_RATE_INFO_HE_GI, - NL80211_RATE_INFO_HE_DCM, - NL80211_RATE_INFO_HE_RU_ALLOC, -+ NL80211_RATE_INFO_320_MHZ_WIDTH, -+ NL80211_RATE_INFO_EHT_MCS, -+ NL80211_RATE_INFO_EHT_NSS, -+ NL80211_RATE_INFO_EHT_GI, -+ NL80211_RATE_INFO_EHT_RU_ALLOC, - - /* keep last */ - __NL80211_RATE_INFO_AFTER_LAST, -@@ -3746,6 +3768,8 @@ enum nl80211_mpath_info { + __NL80211_ATTR_AFTER_LAST, +@@ -3845,6 +3869,8 @@ enum nl80211_mpath_info { NL80211_MPATH_INFO_MAX = __NL80211_MPATH_INFO_AFTER_LAST - 1 }; @@ -96,7 +67,7 @@ Signed-off-by: Muna Sinada /** * enum nl80211_band_iftype_attr - Interface type data attributes * -@@ -4954,6 +4978,11 @@ enum nl80211_key_attributes { +@@ -5074,6 +5100,11 @@ enum nl80211_key_attributes { * see &struct nl80211_txrate_he * @NL80211_TXRATE_HE_GI: configure HE GI, 0.8us, 1.6us and 3.2us. * @NL80211_TXRATE_HE_LTF: configure HE LTF, 1XLTF, 2XLTF and 4XLTF. @@ -108,7 +79,7 @@ Signed-off-by: Muna Sinada * @__NL80211_TXRATE_AFTER_LAST: internal * @NL80211_TXRATE_MAX: highest TX rate attribute */ -@@ -4967,6 +4996,9 @@ enum nl80211_tx_rate_attributes { +@@ -5087,6 +5118,9 @@ enum nl80211_tx_rate_attributes { NL80211_TXRATE_HE_GI, NL80211_TXRATE_HE_LTF, NL80211_TXRATE_HE_UL, @@ -118,7 +89,7 @@ Signed-off-by: Muna Sinada /* keep last */ __NL80211_TXRATE_AFTER_LAST, -@@ -5000,6 +5032,38 @@ enum nl80211_txrate_gi { +@@ -5120,6 +5154,26 @@ enum nl80211_txrate_gi { }; /** @@ -130,18 +101,6 @@ Signed-off-by: Muna Sinada +}; + +/** -+ * enum nl80211_eht_gi - EHT guard interval -+ * @NL80211_RATE_INFO_EHT_GI_0_8: 0.8 usec -+ * @NL80211_RATE_INFO_EHT_GI_1_6: 1.6 usec -+ * @NL80211_RATE_INFO_EHT_GI_3_2: 3.2 usec -+ */ -+enum nl80211_eht_gi { -+ NL80211_RATE_INFO_EHT_GI_0_8, -+ NL80211_RATE_INFO_EHT_GI_1_6, -+ NL80211_RATE_INFO_EHT_GI_3_2, -+}; -+ -+/** + * enum nl80211_eht_ltf - EHT long training field + * @NL80211_RATE_INFO_EHT_1xLTF: 3.2 usec + * @NL80211_RATE_INFO_EHT_2xLTF: 6.4 usec diff --git a/feeds/ipq95xx/iw/patches/602-iw-Support-EHT-rate-configuration.patch b/feeds/ipq95xx/iw/patches/602-iw-Support-EHT-rate-configuration.patch index cbba910f4..2acf45a9a 100644 --- a/feeds/ipq95xx/iw/patches/602-iw-Support-EHT-rate-configuration.patch +++ b/feeds/ipq95xx/iw/patches/602-iw-Support-EHT-rate-configuration.patch @@ -356,25 +356,3 @@ Signed-off-by: Muna Sinada NL80211_CMD_SET_TX_BITRATE_MASK, 0, CIB_NETDEV, handle_bitrates, "Sets up the specified rate masks.\n" "Not passing any arguments would clear the existing mask (if any)."); ---- a/station.c -+++ b/station.c -@@ -259,6 +259,19 @@ void parse_bitrate(struct nlattr *bitrat - if (rinfo[NL80211_RATE_INFO_HE_RU_ALLOC]) - pos += snprintf(pos, buflen - (pos - buf), - " HE-RU-ALLOC %d", nla_get_u8(rinfo[NL80211_RATE_INFO_HE_RU_ALLOC])); -+ if (rinfo[NL80211_RATE_INFO_EHT_MCS]) -+ pos += snprintf(pos, buflen - (pos - buf), -+ " EHT-MCS %d", nla_get_u8(rinfo[NL80211_RATE_INFO_EHT_MCS])); -+ if (rinfo[NL80211_RATE_INFO_EHT_NSS]) -+ pos += snprintf(pos, buflen - (pos - buf), -+ " EHT-NSS %d", nla_get_u8(rinfo[NL80211_RATE_INFO_EHT_NSS])); -+ if (rinfo[NL80211_RATE_INFO_EHT_GI]) -+ pos += snprintf(pos, buflen - (pos - buf), -+ " EHT-GI %d", nla_get_u8(rinfo[NL80211_RATE_INFO_EHT_GI])); -+ if (rinfo[NL80211_RATE_INFO_EHT_RU_ALLOC]) -+ pos += snprintf(pos, buflen - (pos - buf), -+ " EHT-RU-ALLOC %d", nla_get_u8(rinfo[NL80211_RATE_INFO_EHT_RU_ALLOC])); -+ - } - - static char *get_chain_signal(struct nlattr *attr_list) diff --git a/feeds/ipq95xx/iw/patches/603-iw-Add-320-MHz-support.patch b/feeds/ipq95xx/iw/patches/603-iw-Add-320-MHz-support.patch index 521bdbcb5..ed2e66b1d 100644 --- a/feeds/ipq95xx/iw/patches/603-iw-Add-320-MHz-support.patch +++ b/feeds/ipq95xx/iw/patches/603-iw-Add-320-MHz-support.patch @@ -15,10 +15,8 @@ Signed-off-by: Karthikeyan Periyasamy util.c | 36 +++++++++++++++++++++++++++++++++++- 5 files changed, 47 insertions(+), 4 deletions(-) -Index: iw-5.16/event.c -=================================================================== ---- iw-5.16.orig/event.c -+++ iw-5.16/event.c +--- a/event.c ++++ b/event.c @@ -856,6 +856,9 @@ static void parse_ch_switch_notify(struc case NL80211_CHAN_WIDTH_160: printf("\"160 MHz\""); @@ -29,20 +27,9 @@ Index: iw-5.16/event.c case NL80211_CHAN_WIDTH_5: printf("\"5 MHz\""); break; -Index: iw-5.16/interface.c -=================================================================== ---- iw-5.16.orig/interface.c -+++ iw-5.16/interface.c -@@ -376,6 +376,8 @@ char *channel_width_name(enum nl80211_ch - return "80+80 MHz"; - case NL80211_CHAN_WIDTH_160: - return "160 MHz"; -+ case NL80211_CHAN_WIDTH_320: -+ return "320 MHz"; - case NL80211_CHAN_WIDTH_5: - return "5 MHz"; - case NL80211_CHAN_WIDTH_10: -@@ -766,11 +768,11 @@ static int handle_chan(struct nl80211_st +--- a/interface.c ++++ b/interface.c +@@ -743,11 +743,11 @@ static int handle_chan(struct nl80211_st SECTION(switch); COMMAND(switch, freq, @@ -57,10 +44,8 @@ Index: iw-5.16/interface.c NL80211_CMD_CHANNEL_SWITCH, 0, CIB_NETDEV, handle_chan, "Switch the operating channel by sending a channel switch announcement (CSA)." "6GHz channels expects '6G' in argument. Defaults to 5GHz or 2GHz channels"); -Index: iw-5.16/measurements.c -=================================================================== ---- iw-5.16.orig/measurements.c -+++ iw-5.16/measurements.c +--- a/measurements.c ++++ b/measurements.c @@ -189,6 +189,7 @@ static int parse_ftm_target(struct nl_ms case NL80211_CHAN_WIDTH_160: preamble = NL80211_PREAMBLE_VHT; @@ -69,31 +54,8 @@ Index: iw-5.16/measurements.c default: return HANDLER_RET_USAGE; } -Index: iw-5.16/nl80211.h -=================================================================== ---- iw-5.16.orig/nl80211.h -+++ iw-5.16/nl80211.h -@@ -4677,6 +4677,8 @@ enum nl80211_key_mode { - * and %NL80211_ATTR_CENTER_FREQ2 attributes must be provided as well - * @NL80211_CHAN_WIDTH_160: 160 MHz channel, the %NL80211_ATTR_CENTER_FREQ1 - * attribute must be provided as well -+ * @NL80211_CHAN_WIDTH_320: 320 MHz channel, the %NL80211_ATTR_CENTER_FREQ1 -+ * attribute must be provided as well - * @NL80211_CHAN_WIDTH_5: 5 MHz OFDM channel - * @NL80211_CHAN_WIDTH_10: 10 MHz OFDM channel - * @NL80211_CHAN_WIDTH_1: 1 MHz OFDM channel -@@ -4699,6 +4701,7 @@ enum nl80211_chan_width { - NL80211_CHAN_WIDTH_4, - NL80211_CHAN_WIDTH_8, - NL80211_CHAN_WIDTH_16, -+ NL80211_CHAN_WIDTH_320, - }; - - /** -Index: iw-5.16/util.c -=================================================================== ---- iw-5.16.orig/util.c -+++ iw-5.16/util.c +--- a/util.c ++++ b/util.c @@ -473,6 +473,7 @@ enum nl80211_chan_width str_to_bw(const { .name = "80", .val = NL80211_CHAN_WIDTH_80, }, { .name = "80+80", .val = NL80211_CHAN_WIDTH_80P80, }, @@ -102,15 +64,7 @@ Index: iw-5.16/util.c }; unsigned int i; -@@ -510,6 +511,7 @@ static int parse_freqs(struct chandef *c - case NL80211_CHAN_WIDTH_40: - case NL80211_CHAN_WIDTH_80: - case NL80211_CHAN_WIDTH_160: -+ case NL80211_CHAN_WIDTH_320: - need_cf1 = true; - break; - case NL80211_CHAN_WIDTH_1: -@@ -580,12 +582,12 @@ static int parse_freqs(struct chandef *c +@@ -581,12 +582,12 @@ static int parse_freqs(struct chandef *c * user by giving "NOHT" instead. * * The working specifier if chan is set are: @@ -126,8 +80,8 @@ Index: iw-5.16/util.c * * If the mode/channel width is not given the NOHT is assumed. * -@@ -628,6 +630,10 @@ int parse_freqchan(struct chandef *chand - .width = NL80211_CHAN_WIDTH_160, +@@ -633,6 +634,10 @@ int parse_freqchan(struct chandef *chand + .width = NL80211_CHAN_WIDTH_320, .freq1_diff = 0, .chantype = -1 }, + { .name = "320MHz", @@ -137,7 +91,7 @@ Index: iw-5.16/util.c }; const struct chanmode *chanmode_selected = NULL; unsigned int freq; -@@ -1308,12 +1314,16 @@ void iw_hexdump(const char *prefix, cons +@@ -1697,13 +1702,16 @@ void iw_hexdump(const char *prefix, cons int get_cf1(const struct chanmode *chanmode, unsigned long freq) { @@ -147,17 +101,17 @@ Index: iw-5.16/util.c 5955, 6035, 6115, 6195, 6275, 6355, 6435, 6515, 6595, 6675, 6755, 6835, 6195, 6995 }; - unsigned int vht160[] = { 5180, 5500 }; -+ unsigned int eht320_1[] = { 5955, 6275, 6595 }; -+ unsigned int eht320_2[] = { 6115, 6435, 6755 }; -+ unsigned int eht320_1diff, eht320_2diff; -+ + unsigned int bw160[] = { 5180, 5500, 5955, 6115, 6275, 6435, + 6595, 6755, 6915 }; ++ unsigned int eht320_1[] = { 5955, 6275, 6595 }; ++ unsigned int eht320_2[] = { 6115, 6435, 6755 }; ++ unsigned int eht320_1diff, eht320_2diff; switch (chanmode->width) { case NL80211_CHAN_WIDTH_80: -@@ -1340,6 +1350,31 @@ int get_cf1(const struct chanmode *chanm +@@ -1730,6 +1738,31 @@ int get_cf1(const struct chanmode *chanm - cf1 = vht160[j] + 70; + cf1 = bw160[j] + 70; break; + case NL80211_CHAN_WIDTH_320: + /* setup center_freq1 */ @@ -187,10 +141,8 @@ Index: iw-5.16/util.c default: cf1 = freq + chanmode->freq1_diff; break; -Index: iw-5.16/phy.c -=================================================================== ---- iw-5.16.orig/phy.c -+++ iw-5.16/phy.c +--- a/phy.c ++++ b/phy.c @@ -199,14 +199,14 @@ static int handle_freq(struct nl80211_st } diff --git a/feeds/ipq95xx/iw/patches/603-iw-Add-EHT-Capability-Information.patch b/feeds/ipq95xx/iw/patches/603-iw-Add-EHT-Capability-Information.patch deleted file mode 100644 index 93791ae0c..000000000 --- a/feeds/ipq95xx/iw/patches/603-iw-Add-EHT-Capability-Information.patch +++ /dev/null @@ -1,279 +0,0 @@ -From 9acc984a8790de84105011c2cf98bf5b5a0164f7 Mon Sep 17 00:00:00 2001 -From: Muna Sinada -Date: Wed, 26 Jan 2022 14:23:01 -0800 -Subject: [PATCH] iw: Add EHT Capability Information - -Add EHT capability information that is printed out in "iw phy" -commands. - -Signed-off-by: Muna Sinada ---- - info.c | 4 +- - iw.h | 3 + - scan.c | 8 +++ - util.c | 206 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 220 insertions(+), 1 deletion(-) - ---- a/info.c -+++ b/info.c -@@ -174,8 +174,10 @@ static int print_phy_handler(struct nl_m - struct nlattr *nl_iftype; - int rem_band; - -- nla_for_each_nested(nl_iftype, tb_band[NL80211_BAND_ATTR_IFTYPE_DATA], rem_band) -+ nla_for_each_nested(nl_iftype, tb_band[NL80211_BAND_ATTR_IFTYPE_DATA], rem_band) { - print_he_info(nl_iftype); -+ print_eht_info(nl_iftype); -+ } - } - if (tb_band[NL80211_BAND_ATTR_FREQS]) { - if (!band_had_freq) { ---- a/iw.h -+++ b/iw.h -@@ -233,6 +233,9 @@ void print_ht_capability(__u16 cap); - void print_vht_info(__u32 capa, const __u8 *mcs); - void print_he_capability(const uint8_t *ie, int len); - void print_he_info(struct nlattr *nl_iftype); -+void print_eht_capability(const uint8_t *ie, int len); -+void print_eht_info(struct nlattr *nl_iftype); -+ - - char *channel_width_name(enum nl80211_chan_width width); - const char *iftype_name(enum nl80211_iftype iftype); ---- a/scan.c -+++ b/scan.c -@@ -2322,8 +2322,16 @@ static void print_he_capa(const uint8_t - print_he_capability(data, len); - } - -+static void print_eht_capa(const uint8_t type, uint8_t len, const uint8_t *data, -+ const struct print_ies_data *ie_buffer) -+{ -+ printf("\n"); -+ print_eht_capability(data, len); -+} -+ - static const struct ie_print ext_printers[] = { - [35] = { "HE capabilities", print_he_capa, 21, 54, BIT(PRINT_SCAN), }, -+ [108] = { "EHT capabilities", print_eht_capa, 13, 62, BIT(PRINT_SCAN), }, - }; - - static void print_extension(unsigned char len, unsigned char *ie, ---- a/util.c -+++ b/util.c -@@ -1187,6 +1187,121 @@ static void __print_he_capa(const __u16 - } - } - -+static void __print_eht_capa(const __u16 *mac_cap, -+ const __u16 *phy_cap, -+ const __u8 *mcs_set, size_t mcs_len, -+ const __u8 *ppet, int ppet_len, -+ bool indent) -+{ -+ int i; -+ const char *pre = indent ? "\t" : ""; -+ -+ #define PRINT_EHT_CAP(_var, _idx, _bit, _str) \ -+ do { \ -+ if (_var[_idx] & BIT(_bit)) \ -+ printf("%s\t\t\t" _str "\n", pre); \ -+ } while (0) -+ -+ #define PRINT_EHT_CAP_MASK(_var, _idx, _shift, _mask, _str) \ -+ do { \ -+ if ((_var[_idx] >> _shift) & _mask) \ -+ printf("%s\t\t\t" _str ": %d\n", pre, (_var[_idx] >> _shift) & _mask); \ -+ } while (0) -+ -+ #define PRINT_EHT_MAC_CAP(...) PRINT_EHT_CAP(mac_cap, __VA_ARGS__) -+ #define PRINT_EHT_MAC_CAP_MASK(...) PRINT_EHT_CAP_MASK(mac_cap, __VA_ARGS__) -+ #define PRINT_EHT_PHY_CAP(...) PRINT_EHT_CAP(phy_cap, __VA_ARGS__) -+ #define PRINT_EHT_PHY_CAP0(_idx, _bit, ...) PRINT_EHT_CAP(phy_cap, _idx, _bit + 8, __VA_ARGS__) -+ #define PRINT_EHT_PHY_CAP_MASK(...) PRINT_EHT_CAP_MASK(phy_cap, __VA_ARGS__) -+ -+ printf("%s\t\tEHT MAC Capabilities (0x", pre); -+ for (i = 0; i < 2; i++) -+ printf("%04x", mac_cap[i]); -+ printf("):\n"); -+ -+ PRINT_EHT_MAC_CAP(0, 0, "NSEP Priority Access Support"); -+ PRINT_EHT_MAC_CAP(0, 1, "EHT OM Control Support"); -+ PRINT_EHT_MAC_CAP(0, 2, "Triggered TXOP Sharing Mode 1 Support"); -+ PRINT_EHT_MAC_CAP(0, 3, "Triggered TXOP Sharing Mode 2 Support"); -+ PRINT_EHT_MAC_CAP(0, 4, "Restrived TWT Support"); -+ PRINT_EHT_MAC_CAP(0, 5, "SCS Traffic Description Support"); -+ PRINT_EHT_MAC_CAP_MASK(0, 6, 0x7, "Maximum MPDU Length"); -+ -+ printf("%s\t\tEHT PHY Capabilities: (0x", pre); -+ for (i = 0; i < 8; i++) -+ printf("%02x", ((__u8 *)phy_cap)[i + 1]); -+ printf("):\n"); -+ -+ PRINT_EHT_PHY_CAP0(0, 1, "320 MHz in 6 GHz Support"); -+ PRINT_EHT_PHY_CAP0(0, 2, "242-tone RU in BW Wider Than 20 MHz Support"); -+ PRINT_EHT_PHY_CAP0(0, 3, "NDP With 4x EHT-LTF and 3.2us GI"); -+ PRINT_EHT_PHY_CAP0(0, 4, "Partial Bandwidth UL MU-MIMO"); -+ PRINT_EHT_PHY_CAP0(0, 5, "SU Beamformer"); -+ PRINT_EHT_PHY_CAP0(0, 6, "SU Beamformee"); -+ PRINT_EHT_PHY_CAP_MASK(0, 7, 0x7, "Beamformee STS <= 80Mhz"); -+ PRINT_EHT_PHY_CAP_MASK(0, 10, 0x7, "Beamformee STS = 160Mhz"); -+ PRINT_EHT_PHY_CAP_MASK(0, 13, 0x7, "Beamformee STS = 320Mhz"); -+ PRINT_EHT_PHY_CAP_MASK(1, 0, 0x7, "Sounding Dimensions <= 80Mhz"); -+ PRINT_EHT_PHY_CAP_MASK(1, 3, 0x7, "Sounding Dimensions = 160Mhz"); -+ PRINT_EHT_PHY_CAP_MASK(1, 6, 0x7, "Sounding Dimensions = 320Mhz"); -+ PRINT_EHT_PHY_CAP(1, 9, "Ng = 16 SU Feedback"); -+ PRINT_EHT_PHY_CAP(1, 10, "Ng = 16 MU Feedback"); -+ PRINT_EHT_PHY_CAP(1, 11, "Codebook Size SU Feedback"); -+ PRINT_EHT_PHY_CAP(1, 12, "Codebook Size MU Feedback"); -+ PRINT_EHT_PHY_CAP(1, 13, "Triggered SU Beamforming Feedback"); -+ PRINT_EHT_PHY_CAP(1, 14, "Triggered MU Beamforming Partial BW Feedback"); -+ PRINT_EHT_PHY_CAP(1, 15, "Triggered CQI Feedback"); -+ PRINT_EHT_PHY_CAP(2, 0, "Partial Bandwidth DL MU-MIMO"); -+ PRINT_EHT_PHY_CAP(2, 1, "EHT PSR-based SR Support"); -+ PRINT_EHT_PHY_CAP(2, 2, "Power Boost Factor Support"); -+ PRINT_EHT_PHY_CAP(2, 3, "EHT MU PPDU With 4x EHT-LTF and 0.8us GI"); -+ PRINT_EHT_PHY_CAP_MASK(2, 4, 0xf, "Max Nc"); -+ PRINT_EHT_PHY_CAP(2, 8, "Non-Triggered CQI Feedback"); -+ PRINT_EHT_PHY_CAP(2, 9, "TX 1024-QAM and 4096-QAM"); -+ PRINT_EHT_PHY_CAP(2, 10, "RX 1024-QAM and 4096-QAM"); -+ PRINT_EHT_PHY_CAP(2, 11, "PPE Thresholds Present"); -+ PRINT_EHT_PHY_CAP_MASK(2, 12, 0x3, "Common Nominal Packet Padding"); -+ PRINT_EHT_PHY_CAP(2, 14, "Extra EHT-LTFs Rx Support"); -+ PRINT_EHT_PHY_CAP_MASK(2, 0, 0x7, "Max Number of Supported EHT-LTFs"); -+ PRINT_EHT_PHY_CAP_MASK(3, 3, 0xf, "MCS 15 Support"); -+ PRINT_EHT_PHY_CAP(3, 7, "EHT DUP (MCS 14) in 6 GHz Support"); -+ PRINT_EHT_PHY_CAP(3, 8, "20 MHz Operating STA Recieving NDP With Wider BW"); -+ PRINT_EHT_PHY_CAP(3, 9, "Non-OFDMA UL MU-MIMO <= 80Mhz"); -+ PRINT_EHT_PHY_CAP(3, 10, "Non-OFDMA UL MU-MIMO = 160Mhz"); -+ PRINT_EHT_PHY_CAP(3, 11, "Non-OFDMA UL MU-MIMO = 320Mhz"); -+ PRINT_EHT_PHY_CAP(3, 12, "MU Beamformer <= 80Mhz"); -+ PRINT_EHT_PHY_CAP(3, 13, "MU Beamformer = 160Mhz"); -+ PRINT_EHT_PHY_CAP(3, 14, "MU Beamformer <= 320Mhz"); -+ PRINT_EHT_PHY_CAP(3, 15, "TB Sounding Feedback Rate Limit"); -+ -+ char *bw[] = { "<= 80", "160", "360" }; -+ for (i = 0; i < 3; i++) { -+ int j; -+ -+ printf("%s\t\tEHT TX/RX MCS and NSS set %s MHz\n", pre, bw[i]); -+ -+ for(j = 7; j >= 0; j--) { -+ printf("%s\t\t\t%d streams: ", pre, j + 1); -+ if (mcs_set[i * 3] >= j) -+ printf("MCS 0-13\n"); -+ else if (mcs_set[(i * 3) + 1] >= j) -+ printf("MCS 0-11\n"); -+ else if (mcs_set[(i * 3) + 2] >= j) -+ printf("MCS 0-9\n"); -+ else -+ printf("not supported\n"); -+ } -+ } -+ -+ if (ppet_len) { -+ printf("%s\t\tEHT PPE Threshold ", pre); -+ for (i = 0; i < ppet_len; i++) -+ if (ppet[i]) -+ printf("0x%02x ", ppet[i]); -+ printf("\n"); -+ } -+} -+ - void print_iftype_list(const char *name, const char *pfx, struct nlattr *attr) - { - struct nlattr *ift; -@@ -1293,6 +1408,80 @@ void print_he_capability(const uint8_t * - __print_he_capa(mac_cap, phy_cap - 1, mcs_set, mcs_len, NULL, 0, false); - } - -+void print_eht_info(struct nlattr *nl_iftype) -+{ -+ struct nlattr *tb[NL80211_BAND_IFTYPE_ATTR_MAX + 1]; -+ __u16 mac_cap[1] = { 0 }; -+ __u16 phy_cap[4] = { 0 }; -+ __u8 mcs_set[9] = { 0 }; -+ __u8 ppet[62] = { 0 }; -+ size_t len; -+ int mcs_len = 0, ppet_len = 0; -+ -+ nla_parse(tb, NL80211_BAND_IFTYPE_ATTR_MAX, -+ nla_data(nl_iftype), nla_len(nl_iftype), NULL); -+ -+ if (tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC]) { -+ len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC]); -+ if (len > sizeof(mac_cap)) -+ len = sizeof(mac_cap); -+ memcpy(mac_cap, -+ nla_data(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC]), -+ len); -+ } -+ -+ if (tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY]) { -+ len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY]); -+ -+ if (len > sizeof(phy_cap) - 1) -+ len = sizeof(phy_cap) - 1; -+ memcpy(&((__u8 *)phy_cap)[1], -+ nla_data(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY]), -+ len); -+ } -+ -+ if (tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET]) { -+ len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET]); -+ if (len > sizeof(mcs_set)) -+ len = sizeof(mcs_set); -+ memcpy(mcs_set, -+ nla_data(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET]), -+ len); -+ mcs_len = len; -+ } -+ -+ if (tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE]) { -+ len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE]); -+ if (len > sizeof(ppet)) -+ len = sizeof(ppet); -+ memcpy(ppet, -+ nla_data(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE]), -+ len); -+ ppet_len = len; -+ } -+ -+ __print_eht_capa(mac_cap, phy_cap, mcs_set, mcs_len, ppet, ppet_len, -+ true); -+} -+ -+void print_eht_capability(const uint8_t *ie, int len) -+{ -+ const void *mac_cap, *phy_cap, *mcs_set; -+ int mcs_len; -+ int i = 0; -+ -+ mac_cap = &ie[i]; -+ i += 2; -+ -+ phy_cap = &ie[i]; -+ i += 8; -+ -+ mcs_set = &ie[i]; -+ mcs_len = len - i; -+ -+ __print_eht_capa(mac_cap, phy_cap - 1, mcs_set, mcs_len, NULL, 0, false); -+} -+ - void iw_hexdump(const char *prefix, const __u8 *buf, size_t size) - { - size_t i; ---- a/nl80211.h -+++ b/nl80211.h -@@ -3786,6 +3786,10 @@ enum nl80211_band_iftype_attr { - NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE, - NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA, - NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS, -+ NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC, -+ NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY, -+ NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET, -+ NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE, - - /* keep last */ - __NL80211_BAND_IFTYPE_ATTR_AFTER_LAST, diff --git a/feeds/ipq95xx/iw/patches/604-iw-Add-the-support-for-green-ap.patch b/feeds/ipq95xx/iw/patches/604-iw-Add-the-support-for-green-ap.patch index c2e431ef9..60e894bbe 100644 --- a/feeds/ipq95xx/iw/patches/604-iw-Add-the-support-for-green-ap.patch +++ b/feeds/ipq95xx/iw/patches/604-iw-Add-the-support-for-green-ap.patch @@ -13,11 +13,9 @@ Signed-off-by: Sivashankari Madhavan nl80211.h | 5 ++++- 2 files changed, 36 insertions(+), 1 deletion(-) -Index: iw-5.16/interface.c -=================================================================== ---- iw-5.16.orig/interface.c -+++ iw-5.16/interface.c -@@ -1220,3 +1220,34 @@ COMMAND(set, tidconf, "[peer 1) -+ return 1; ++ if (argc == 3) { ++ if (!strcmp(argv[0], "-l")) { ++ unsigned int link_id; + -+ ap_ps = strtol(argv[0], &end, 10); ++ link_id = strtol(argv[1], &end, 10); ++ if (*end) ++ return 1; ++ if (link_id < MAX_MLD_LINK) { ++ NLA_PUT_U8(msg, NL80211_ATTR_MLO_LINK_ID, ++ link_id); ++ i = 2; ++ } ++ } else { ++ printf("Invalid parameter: %s\n", argv[0]); ++ return 1; ++ } ++ } else { ++ if (argc != 1) ++ return 1; ++ } + -+ if (*end){ -+ return 2; -+ } ++ ap_ps = strtol(argv[i], &end, 10); + -+ if (ap_ps > 1) ++ if (*end) ++ return 2; ++ ++ if (ap_ps > 1) + return -EINVAL; + -+ NLA_PUT_U8(msg, NL80211_ATTR_AP_PS, ap_ps); ++ NLA_PUT_U8(msg, NL80211_ATTR_AP_PS, ap_ps); + -+ return 0; ++ return 0; + +nla_put_failure: -+ return -ENOBUFS; ++ return -ENOBUFS; +} + -+COMMAND(set, ap_ps, "", ++COMMAND(set, ap_ps, "[-l] ", + NL80211_CMD_UPDATE_AP, 0, CIB_NETDEV, handle_interface_ap_ps, NULL); -Index: iw-5.16/nl80211.h -=================================================================== ---- iw-5.16.orig/nl80211.h -+++ iw-5.16/nl80211.h -@@ -1255,7 +1255,8 @@ enum nl80211_commands { +--- a/nl80211.h ++++ b/nl80211.h +@@ -1260,7 +1260,8 @@ enum nl80211_commands { NL80211_CMD_DEL_KEY, NL80211_CMD_GET_BEACON, @@ -66,12 +80,22 @@ Index: iw-5.16/nl80211.h NL80211_CMD_START_AP, NL80211_CMD_NEW_BEACON = NL80211_CMD_START_AP, NL80211_CMD_STOP_AP, -@@ -3170,6 +3171,8 @@ enum nl80211_attrs { - NL80211_ATTR_RU_PUNCT_SUPP_HE, +@@ -3225,6 +3226,8 @@ enum nl80211_attrs { + NL80211_ATTR_RU_PUNCT_BITMAP, + NL80211_ATTR_AP_PS, + - NL80211_ATTR_MLD_MAC=352, - NL80211_ATTR_MLD_REFERENCE=353, + /* add attributes here, update the policy in nl80211.c */ + __NL80211_ATTR_AFTER_LAST, +--- a/iw.h ++++ b/iw.h +@@ -41,6 +41,7 @@ enum nlmsgerr_attrs { + + #define ETH_ALEN 6 + #define VHT_MUMIMO_GROUP_LEN 24 ++#define MAX_MLD_LINK 15 + + /* libnl 1.x compatibility code */ + #if !defined(CONFIG_LIBNL20) && !defined(CONFIG_LIBNL30) diff --git a/feeds/ipq95xx/iw/patches/605-iw-add-support-for-6-GHz-in-iw-reg-get-command.patch b/feeds/ipq95xx/iw/patches/605-iw-add-support-for-6-GHz-in-iw-reg-get-command.patch index 808087f05..156f7a98c 100644 --- a/feeds/ipq95xx/iw/patches/605-iw-add-support-for-6-GHz-in-iw-reg-get-command.patch +++ b/feeds/ipq95xx/iw/patches/605-iw-add-support-for-6-GHz-in-iw-reg-get-command.patch @@ -32,11 +32,9 @@ Signed-off-by: Aditya Kumar Singh reg.c | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) -diff --git a/nl80211.h b/nl80211.h -index 95d2121..9bc5122 100644 --- a/nl80211.h +++ b/nl80211.h -@@ -3858,6 +3858,20 @@ enum nl80211_band_attr { +@@ -3935,6 +3935,20 @@ enum nl80211_band_attr { #define NL80211_BAND_ATTR_HT_CAPA NL80211_BAND_ATTR_HT_CAPA @@ -57,7 +55,7 @@ index 95d2121..9bc5122 100644 /** * enum nl80211_wmm_rule - regulatory wmm rule * -@@ -4083,6 +4097,10 @@ enum nl80211_reg_type { +@@ -4165,6 +4179,10 @@ enum nl80211_reg_type { * a given frequency range. The value is in mBm (100 * dBm). * @NL80211_ATTR_DFS_CAC_TIME: DFS CAC time in milliseconds. * If not present or 0 default CAC time will be used. @@ -68,7 +66,7 @@ index 95d2121..9bc5122 100644 * @NL80211_REG_RULE_ATTR_MAX: highest regulatory rule attribute number * currently defined * @__NL80211_REG_RULE_ATTR_AFTER_LAST: internal use -@@ -4100,6 +4118,10 @@ enum nl80211_reg_rule_attr { +@@ -4182,6 +4200,10 @@ enum nl80211_reg_rule_attr { NL80211_ATTR_DFS_CAC_TIME, @@ -79,27 +77,25 @@ index 95d2121..9bc5122 100644 /* keep last */ __NL80211_REG_RULE_ATTR_AFTER_LAST, NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1 -@@ -4181,6 +4203,7 @@ enum nl80211_sched_scan_match_attr { - * @NL80211_RRF_NO_80MHZ: 80MHz operation not allowed +@@ -4264,6 +4286,7 @@ enum nl80211_sched_scan_match_attr { * @NL80211_RRF_NO_160MHZ: 160MHz operation not allowed * @NL80211_RRF_NO_HE: HE operation not allowed + * @NL80211_RRF_NO_320MHZ: 320MHz operation not allowed + * @NL80211_RRF_PSD: channels has power spectral density value */ enum nl80211_reg_rule_flags { NL80211_RRF_NO_OFDM = 1<<0, -@@ -4199,6 +4222,7 @@ enum nl80211_reg_rule_flags { - NL80211_RRF_NO_80MHZ = 1<<15, +@@ -4283,6 +4306,7 @@ enum nl80211_reg_rule_flags { NL80211_RRF_NO_160MHZ = 1<<16, NL80211_RRF_NO_HE = 1<<17, -+ NL80211_RRF_PSD = 1<<18, + NL80211_RRF_NO_320MHZ = 1<<18, ++ NL80211_RRF_PSD = 1<<19, }; #define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR -diff --git a/reg.c b/reg.c -index feb347a..36f8192 100644 --- a/reg.c +++ b/reg.c -@@ -111,6 +111,34 @@ COMMAND(reg, set, "", +@@ -111,6 +111,34 @@ COMMAND(reg, set, " -Date: Mon, 29 Aug 2022 10:12:16 +0530 -Subject: [PATCH] iw: fix wrong information display for EHT PHY CAPABILITY in iw phy# info - -Currently, EHT PHY capability information that is received from kernel -is stored from 9th bit of phy_cap and first 8 bit is zero, -when we are printing information, then first 8 bit of phy_cap -is checking with 8 bit of actual information. - -Hence EHT PHY capability display wrong information in iw phy# info - -Fix it by storing kernel information from index zero of phy_cap. - -Fixes: a6de65ec ("iw: Add EHT Capability Information") - -Signed-off-by: Aaradhana Sahu ---- - util.c | 20 ++++++++++---------- - 1 file changed, 10 insertions(+), 10 deletions(-) - ---- a/util.c -+++ b/util.c -@@ -1226,7 +1226,6 @@ static void __print_eht_capa(const __u16 - #define PRINT_EHT_MAC_CAP(...) PRINT_EHT_CAP(mac_cap, __VA_ARGS__) - #define PRINT_EHT_MAC_CAP_MASK(...) PRINT_EHT_CAP_MASK(mac_cap, __VA_ARGS__) - #define PRINT_EHT_PHY_CAP(...) PRINT_EHT_CAP(phy_cap, __VA_ARGS__) -- #define PRINT_EHT_PHY_CAP0(_idx, _bit, ...) PRINT_EHT_CAP(phy_cap, _idx, _bit + 8, __VA_ARGS__) - #define PRINT_EHT_PHY_CAP_MASK(...) PRINT_EHT_CAP_MASK(phy_cap, __VA_ARGS__) - - printf("%s\t\tEHT MAC Capabilities (0x", pre); -@@ -1243,16 +1242,16 @@ static void __print_eht_capa(const __u16 - PRINT_EHT_MAC_CAP_MASK(0, 6, 0x7, "Maximum MPDU Length"); - - printf("%s\t\tEHT PHY Capabilities: (0x", pre); -- for (i = 0; i < 8; i++) -- printf("%02x", ((__u8 *)phy_cap)[i + 1]); -+ for (i = 0; i < 9; i++) -+ printf("%02x", ((__u8 *)phy_cap)[i]); - printf("):\n"); - -- PRINT_EHT_PHY_CAP0(0, 1, "320 MHz in 6 GHz Support"); -- PRINT_EHT_PHY_CAP0(0, 2, "242-tone RU in BW Wider Than 20 MHz Support"); -- PRINT_EHT_PHY_CAP0(0, 3, "NDP With 4x EHT-LTF and 3.2us GI"); -- PRINT_EHT_PHY_CAP0(0, 4, "Partial Bandwidth UL MU-MIMO"); -- PRINT_EHT_PHY_CAP0(0, 5, "SU Beamformer"); -- PRINT_EHT_PHY_CAP0(0, 6, "SU Beamformee"); -+ PRINT_EHT_PHY_CAP(0, 1, "320 MHz in 6 GHz Support"); -+ PRINT_EHT_PHY_CAP(0, 2, "242-tone RU in BW Wider Than 20 MHz Support"); -+ PRINT_EHT_PHY_CAP(0, 3, "NDP With 4x EHT-LTF and 3.2us GI"); -+ PRINT_EHT_PHY_CAP(0, 4, "Partial Bandwidth UL MU-MIMO"); -+ PRINT_EHT_PHY_CAP(0, 5, "SU Beamformer"); -+ PRINT_EHT_PHY_CAP(0, 6, "SU Beamformee"); - PRINT_EHT_PHY_CAP_MASK(0, 7, 0x7, "Beamformee STS <= 80Mhz"); - PRINT_EHT_PHY_CAP_MASK(0, 10, 0x7, "Beamformee STS = 160Mhz"); - PRINT_EHT_PHY_CAP_MASK(0, 13, 0x7, "Beamformee STS = 320Mhz"); -@@ -1427,7 +1426,7 @@ void print_eht_info(struct nlattr *nl_if - { - struct nlattr *tb[NL80211_BAND_IFTYPE_ATTR_MAX + 1]; - __u16 mac_cap[1] = { 0 }; -- __u16 phy_cap[4] = { 0 }; -+ __u16 phy_cap[5] = { 0 }; - __u8 mcs_set[9] = { 0 }; - __u8 ppet[62] = { 0 }; - size_t len; -@@ -1450,7 +1449,7 @@ void print_eht_info(struct nlattr *nl_if - - if (len > sizeof(phy_cap) - 1) - len = sizeof(phy_cap) - 1; -- memcpy(&((__u8 *)phy_cap)[1], -+ memcpy(&((__u8 *)phy_cap)[0], - nla_data(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY]), - len); - } diff --git a/feeds/ipq95xx/iw/patches/607-Changes-needed-for-yocto.patch b/feeds/ipq95xx/iw/patches/607-Changes-needed-for-yocto.patch index f9a2ee4da..1c98b3a69 100644 --- a/feeds/ipq95xx/iw/patches/607-Changes-needed-for-yocto.patch +++ b/feeds/ipq95xx/iw/patches/607-Changes-needed-for-yocto.patch @@ -18,8 +18,6 @@ Signed-off-by: Avula Sri Charan util.c | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) -diff --git a/sar.c b/sar.c -index 95e36e4..e7f8a9f 100644 --- a/sar.c +++ b/sar.c @@ -14,9 +14,10 @@ @@ -34,28 +32,3 @@ index 95e36e4..e7f8a9f 100644 static int set_sar_specs(struct nl80211_state *state, struct nl_msg *msg, int argc, char **argv, -diff --git a/util.c b/util.c -index 48735ab..036f162 100644 ---- a/util.c -+++ b/util.c -@@ -1210,7 +1210,8 @@ static void __print_eht_capa(const __u16 *mac_cap, - { - int i; - const char *pre = indent ? "\t" : ""; -- -+ char *bw[] = { "<= 80", "160", "360" }; -+ - #define PRINT_EHT_CAP(_var, _idx, _bit, _str) \ - do { \ - if (_var[_idx] & BIT(_bit)) \ -@@ -1288,7 +1289,6 @@ static void __print_eht_capa(const __u16 *mac_cap, - PRINT_EHT_PHY_CAP(3, 14, "MU Beamformer <= 320Mhz"); - PRINT_EHT_PHY_CAP(3, 15, "TB Sounding Feedback Rate Limit"); - -- char *bw[] = { "<= 80", "160", "360" }; - for (i = 0; i < 3; i++) { - int j; - --- -2.17.1 - diff --git a/feeds/ipq95xx/iw/patches/608-iw-Add-support-for-background-CAC.patch b/feeds/ipq95xx/iw/patches/608-iw-Add-support-for-background-CAC.patch new file mode 100644 index 000000000..c1848ca11 --- /dev/null +++ b/feeds/ipq95xx/iw/patches/608-iw-Add-support-for-background-CAC.patch @@ -0,0 +1,132 @@ +From 953c7b5bcaaafa711833d3592c5ec8bd8e72fa68 Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Wed, 12 Oct 2022 16:39:33 +0530 +Subject: [PATCH] iw: Add support for background CAC + +Changes are made to support following CLIs: + iw dev cac trigger channel [6G] [width] [bgcac] + iw dev cac stop +--- + nl80211.h | 1 + + phy.c | 28 +++++++++++++++++++++++----- + 2 files changed, 24 insertions(+), 5 deletions(-) + +--- a/nl80211.h ++++ b/nl80211.h +@@ -1493,6 +1493,7 @@ enum nl80211_commands { + + NL80211_CMD_AWGN_DETECT, + ++ NL80211_CMD_STOP_BGRADAR_DETECT, + /* add new commands above here */ + + /* used to define NL80211_CMD_MAX below */ +--- a/phy.c ++++ b/phy.c +@@ -282,15 +282,37 @@ static int handle_cac_trigger(struct nl8 + enum id_input id) + { + struct chandef chandef; +- int res; ++ int res, count, index = 0; + + if (argc < 2) + return 1; + +- if (strcmp(argv[0], "channel") == 0) { +- res = parse_freqchan(&chandef, true, argc - 1, argv + 1, NULL); +- } else if (strcmp(argv[0], "freq") == 0) { +- res = parse_freqchan(&chandef, false, argc - 1, argv + 1, NULL); ++ if (!strcmp(argv[0], "-l")) { ++ unsigned int link_id; ++ char *endptr; ++ ++ link_id = strtol(argv[1], &endptr, 10); ++ ++ if (*endptr) ++ return 1; ++ ++ if (link_id <= MAX_MLD_LINK) { ++ NLA_PUT_U8(msg, NL80211_ATTR_MLO_LINK_ID, ++ link_id); ++ index = 2; ++ } ++ } ++ ++ if (strcmp(argv[argc - 1], "bgcac") == 0) { ++ NLA_PUT_FLAG(msg, NL80211_ATTR_RADAR_BACKGROUND); ++ count = argc - index - 2; ++ } else ++ count = argc - index - 1; ++ ++ if (strcmp(argv[index], "channel") == 0) { ++ res = parse_freqchan(&chandef, true, count, argv + index + 1, NULL); ++ } else if (strcmp(argv[index], "freq") == 0) { ++ res = parse_freqchan(&chandef, false, count, argv + index + 1, NULL); + } else { + return 1; + } +@@ -299,6 +321,10 @@ static int handle_cac_trigger(struct nl8 + return res; + + return put_chandef(msg, &chandef); ++ ++nla_put_failure: ++ return -ENOBUFS; ++ + } + + static int no_seq_check(struct nl_msg *msg, void *arg) +@@ -374,9 +400,9 @@ TOPLEVEL(cac, "channel [6G] [N + "freq [5|10|20|40|80|80+80|160] [ []]", + 0, 0, CIB_NETDEV, handle_cac, NULL); + COMMAND(cac, trigger, +- "channel [6G] [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n" +- "freq [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n" +- "freq [5|10|20|40|80|80+80|160] [ []]", ++ "[-l] channel [6G] [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz] [bgcac]\n" ++ "freq [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz] [bgcac]\n" ++ "freq [5|10|20|40|80|80+80|160] [ []] [bgcac]", + NL80211_CMD_RADAR_DETECT, 0, CIB_NETDEV, handle_cac_trigger, + "Start or trigger a channel availability check (CAC) looking to look for\n" + "radars on the given channel."); +@@ -882,3 +908,39 @@ static int handle_get_txq(struct nl80211 + COMMAND(get, txq, "", + NL80211_CMD_GET_WIPHY, 0, CIB_PHY, handle_get_txq, + "Get TXQ parameters."); ++ ++static int handle_cac_stop(struct nl80211_state *state, ++ struct nl_msg *msg, ++ int argc, char **argv, ++ enum id_input id) ++{ ++ if (argc > 0) { ++ if (!strcmp(argv[0], "-l")) { ++ unsigned int link_id; ++ char *endptr; ++ ++ if (argc != 2) ++ return 1; ++ ++ link_id = strtol(argv[1], &endptr, 10); ++ ++ if (*endptr) ++ return 1; ++ ++ if (link_id <= MAX_MLD_LINK) { ++ NLA_PUT_U8(msg, NL80211_ATTR_MLO_LINK_ID, ++ link_id); ++ } ++ } ++ } ++ ++ return 0; ++ ++nla_put_failure: ++ return -ENOBUFS; ++} ++ ++COMMAND(cac, stop, "[-l] ", ++ NL80211_CMD_STOP_BGRADAR_DETECT, 0, CIB_NETDEV, handle_cac_stop, ++ "Stop the ongoing background CAC"); ++ diff --git a/feeds/ipq95xx/iw/patches/608-iw-print-handler-to-display-320MHz-bitrate.patch b/feeds/ipq95xx/iw/patches/608-iw-print-handler-to-display-320MHz-bitrate.patch deleted file mode 100644 index d55096922..000000000 --- a/feeds/ipq95xx/iw/patches/608-iw-print-handler-to-display-320MHz-bitrate.patch +++ /dev/null @@ -1,26 +0,0 @@ -From dd072e8e639554298b9d1205540cc4555efef1dd Mon Sep 17 00:00:00 2001 -From: Ramya Gnanasekar -Date: Fri, 4 Nov 2022 00:22:17 +0530 -Subject: [PATCH] iw: print handler to display 320MHz bitrate - -This patch adds handler to print tx/rx bitrates -for 320MHz - -Signed-off-by: Ramya Gnanasekar - -diff --git a/station.c b/station.c -index 970e8a5..5618200 100644 ---- a/station.c -+++ b/station.c -@@ -239,6 +239,8 @@ void parse_bitrate(struct nlattr *bitrate_attr, char *buf, int buflen) - pos += snprintf(pos, buflen - (pos - buf), " 80P80MHz"); - if (rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH]) - pos += snprintf(pos, buflen - (pos - buf), " 160MHz"); -+ if (rinfo[NL80211_RATE_INFO_320_MHZ_WIDTH]) -+ pos += snprintf(pos, buflen - (pos - buf), " 320MHz"); - if (rinfo[NL80211_RATE_INFO_SHORT_GI]) - pos += snprintf(pos, buflen - (pos - buf), " short GI"); - if (rinfo[NL80211_RATE_INFO_VHT_NSS]) --- -2.17.1 - diff --git a/feeds/ipq95xx/iw/patches/609-02-iw-add-link-id-information-for-iw-dev.patch b/feeds/ipq95xx/iw/patches/609-02-iw-add-link-id-information-for-iw-dev.patch new file mode 100644 index 000000000..064da75c8 --- /dev/null +++ b/feeds/ipq95xx/iw/patches/609-02-iw-add-link-id-information-for-iw-dev.patch @@ -0,0 +1,128 @@ +From acf2137f1b10a7ab8613258e420c74770c72f6cd Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Fri, 18 Nov 2022 17:52:41 +0530 +Subject: [PATCH] iw: add link information for iw dev + +print link address, channel, and tx power information for each link. + +for MLO iw dev will display +phy#3 + Interface wlan0 + ifindex 34 + wdev 0x30000000a + addr 00:03:7f:12:dc:dc + ssid OpenWrt + type AP + link 0: + addr 00:03:7f:12:dc:dc + channel 11 (2462 MHz), width: 20 MHz, center1: 2462 MHz + txpower 28.00 dBm + link 1: + addr 00:03:7f:12:dd:dd + channel 36 (5180 MHz), width: 80 MHz, center1: 5210 MHz + txpower 28.00 dBm + +Signed-off-by: Aaradhana Sahu +--- + interface.c | 103 ++++++++++++++++++++++++++++++++++++++-------------- + 1 file changed, 75 insertions(+), 28 deletions(-) + +--- a/interface.c ++++ b/interface.c +@@ -387,10 +387,40 @@ char *channel_width_name(enum nl80211_ch + } + } + ++static void print_channel_txpower(struct nlattr *tb_msg[], const char *space) ++{ ++ if (tb_msg[NL80211_ATTR_WIPHY_FREQ]) { ++ uint32_t freq = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_FREQ]); ++ printf("\t\t%schannel %d (%d MHz)", space, ++ ieee80211_frequency_to_channel(freq), freq); ++ if (tb_msg[NL80211_ATTR_CHANNEL_WIDTH]) { ++ printf(", width: %s", ++ channel_width_name(nla_get_u32(tb_msg[NL80211_ATTR_CHANNEL_WIDTH]))); ++ if (tb_msg[NL80211_ATTR_CENTER_FREQ1]) ++ printf(", center1: %d MHz", ++ nla_get_u32(tb_msg[NL80211_ATTR_CENTER_FREQ1])); ++ if (tb_msg[NL80211_ATTR_CENTER_FREQ2]) ++ printf(", center2: %d MHz", ++ nla_get_u32(tb_msg[NL80211_ATTR_CENTER_FREQ2])); ++ } else if (tb_msg[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { ++ enum nl80211_channel_type channel_type; ++ channel_type = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_CHANNEL_TYPE]); ++ printf(" %s", channel_type_name(channel_type)); ++ } ++ printf("\n"); ++ } ++ if (tb_msg[NL80211_ATTR_WIPHY_TX_POWER_LEVEL]) { ++ int32_t txp = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_TX_POWER_LEVEL]); ++ printf("\t\t%stxpower %d.%.2d dBm\n", space, ++ txp / 100, txp % 100); ++ } ++} ++ + static int print_iface_handler(struct nl_msg *msg, void *arg) + { + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); + struct nlattr *tb_msg[NL80211_ATTR_MAX + 1]; ++ struct nlattr *attrs, *link[NL80211_ATTR_MAX + 1]; + unsigned int *wiphy = arg; + const char *indent = ""; + +@@ -436,38 +466,24 @@ static int print_iface_handler(struct nl + printf("%s\ttype %s\n", indent, iftype_name(nla_get_u32(tb_msg[NL80211_ATTR_IFTYPE]))); + if (!wiphy && tb_msg[NL80211_ATTR_WIPHY]) + printf("%s\twiphy %d\n", indent, nla_get_u32(tb_msg[NL80211_ATTR_WIPHY])); +- if (tb_msg[NL80211_ATTR_WIPHY_FREQ]) { +- uint32_t freq = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_FREQ]); +- +- printf("%s\tchannel %d (%d MHz)", indent, +- ieee80211_frequency_to_channel(freq), freq); +- +- if (tb_msg[NL80211_ATTR_CHANNEL_WIDTH]) { +- printf(", width: %s", +- channel_width_name(nla_get_u32(tb_msg[NL80211_ATTR_CHANNEL_WIDTH]))); +- if (tb_msg[NL80211_ATTR_CENTER_FREQ1]) +- printf(", center1: %d MHz", +- nla_get_u32(tb_msg[NL80211_ATTR_CENTER_FREQ1])); +- if (tb_msg[NL80211_ATTR_CENTER_FREQ2]) +- printf(", center2: %d MHz", +- nla_get_u32(tb_msg[NL80211_ATTR_CENTER_FREQ2])); +- } else if (tb_msg[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { +- enum nl80211_channel_type channel_type; +- +- channel_type = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_CHANNEL_TYPE]); +- printf(" %s", channel_type_name(channel_type)); +- } +- +- printf("\n"); ++ if (tb_msg[NL80211_ATTR_MLO_LINKS]) { ++ int ret = 0; ++ nla_for_each_nested(attrs, tb_msg[NL80211_ATTR_MLO_LINKS], ret) { ++ nla_parse_nested(link, NL80211_ATTR_MAX, attrs, NULL); ++ if (link[NL80211_ATTR_MLO_LINK_ID]) { ++ printf("%s\tlink %d:\n", indent, ++ nla_get_u8(link[NL80211_ATTR_MLO_LINK_ID])); ++ if (link[NL80211_ATTR_MAC]) { ++ char link_addr[20]; ++ mac_addr_n2a(link_addr, nla_data(link[NL80211_ATTR_MAC])); ++ printf("%s\t addr %s\n", indent, link_addr); ++ } ++ print_channel_txpower(link, " "); ++ } ++ } ++ } else { ++ print_channel_txpower(tb_msg, ""); + } +- +- if (tb_msg[NL80211_ATTR_WIPHY_TX_POWER_LEVEL]) { +- int32_t txp = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_TX_POWER_LEVEL]); +- +- printf("%s\ttxpower %d.%.2d dBm\n", +- indent, txp / 100, txp % 100); +- } +- + if (tb_msg[NL80211_ATTR_TXQ_STATS]) { + char buf[150]; + parse_txq_stats(buf, sizeof(buf), tb_msg[NL80211_ATTR_TXQ_STATS], 1, -1, indent); diff --git a/feeds/ipq95xx/iw/patches/609-03-iw-add-link-id-for-iw-wlan-station-dump.patch b/feeds/ipq95xx/iw/patches/609-03-iw-add-link-id-for-iw-wlan-station-dump.patch new file mode 100644 index 000000000..db03c8a22 --- /dev/null +++ b/feeds/ipq95xx/iw/patches/609-03-iw-add-link-id-for-iw-wlan-station-dump.patch @@ -0,0 +1,85 @@ +From 21b83739d21aa8d995f004b35a8b14a26598ac47 Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Thu, 24 Nov 2022 10:35:40 +0530 +Subject: [PATCH] iw: display link id for iw wlan# station dump + +print associated link id for each interface. + +for MLO iw wlan# station dump will display +Station 00:7a:f6:22:12:3e (on wlan0 - link0, link1) + inactive time: 16160 ms + rx bytes: 2984 + rx packets: 5 + tx bytes: 858 + tx packets: 0 + tx retries: 0 + tx failed: 0 + rx drop misc: 0 + signal: -43 dBm + tx bitrate: 6.0 MBit/s + tx duration: 1366 us + rx duration: 0 us + authorized: no + authenticated: no + associated: no + WMM/WME: no + DTIM period: 0 + beacon interval:0 + short preamble: yes + short slot time:yes + connected time: 294 seconds + associated at [boottime]: 18411.885s + associated at: 1668599688499 ms + current time: 1668599982613 ms + +Signed-off-by: Aaradhana Sahu +--- + station.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/station.c ++++ b/station.c +@@ -307,6 +307,7 @@ static int print_sta_handler(struct nl_m + struct nlattr *tb[NL80211_ATTR_MAX + 1]; + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); + struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1]; ++ struct nlattr *attrs, *link[NL80211_ATTR_MAX + 1]; + char mac_addr[20], state_name[10], dev[20]; + struct nl80211_sta_flag_update *sta_flags; + static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = { +@@ -376,7 +377,24 @@ static int print_sta_handler(struct nl_m + + mac_addr_n2a(mac_addr, nla_data(tb[NL80211_ATTR_MAC])); + if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev); +- printf("Station %s (on %s)", mac_addr, dev); ++ if (tb[NL80211_ATTR_MLO_LINKS]) { ++ int ret = 0, offset = 0; ++ const char *indent = ""; ++ char link_buf[MLD_MAX_LINK_BUF_SIZE]; ++ nla_for_each_nested(attrs, tb[NL80211_ATTR_MLO_LINKS], ret) { ++ nla_parse_nested(link, NL80211_ATTR_MAX, attrs, NULL); ++ if (link[NL80211_ATTR_MLO_LINK_ID]) { ++ offset += snprintf(link_buf + offset, ++ MLD_MAX_LINK_BUF_SIZE - offset, ++ "%slink%d", indent, ++ nla_get_u8(link[NL80211_ATTR_MLO_LINK_ID])); ++ indent = ", "; ++ } ++ } ++ printf("Station %s (on %s - %s)", mac_addr, dev, link_buf); ++ } else { ++ printf("Station %s (on %s)", mac_addr, dev); ++ } + + if (sinfo[NL80211_STA_INFO_INACTIVE_TIME]) + printf("\n\tinactive time:\t%u ms", +--- a/iw.h ++++ b/iw.h +@@ -41,6 +41,7 @@ enum nlmsgerr_attrs { + + #define ETH_ALEN 6 + #define VHT_MUMIMO_GROUP_LEN 24 ++#define MLD_MAX_LINK_BUF_SIZE 100 + #define MAX_MLD_LINK 15 + + /* libnl 1.x compatibility code */ diff --git a/feeds/ipq95xx/iw/patches/609-04-iw-add-support-set-txpower-command-for-each-link.patch b/feeds/ipq95xx/iw/patches/609-04-iw-add-support-set-txpower-command-for-each-link.patch new file mode 100644 index 000000000..84cb86730 --- /dev/null +++ b/feeds/ipq95xx/iw/patches/609-04-iw-add-support-set-txpower-command-for-each-link.patch @@ -0,0 +1,97 @@ +From ae070708333cb4a08fde17590523d2adff401852 Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Tue, 17 Jan 2023 11:44:47 +0530 +Subject: [PATCH] iw: add support set txpower command for each link + +Add support for set tx power by link id in multi-link operation. + +Command: +iw wlan0 set txpower -l [] + +Signed-off-by: Aaradhana Sahu +--- + phy.c | 43 +++++++++++++++++++++++++++++++++---------- + 1 files changed, 34 insertions(+), 10 deletions(-) + +--- a/phy.c ++++ b/phy.c +@@ -666,20 +666,43 @@ static int handle_txpower(struct nl80211 + enum id_input id) + { + enum nl80211_tx_power_setting type; +- int mbm; ++ int mbm, i, max_argc; + + /* get the required args */ +- if (argc != 1 && argc != 2) +- return 1; ++ if (argc == 3 || argc == 4) { ++ max_argc = 4; + +- if (!strcmp(argv[0], "auto")) ++ if (!strcmp(argv[0], "-l")) { ++ unsigned int link_id; ++ char *endptr; ++ ++ link_id = strtol(argv[1], &endptr, 10); ++ if (*endptr) ++ return 1; ++ if (link_id <= MAX_MLD_LINK) { ++ NLA_PUT_U8(msg, NL80211_ATTR_MLO_LINK_ID, ++ link_id); ++ i = 2; ++ } ++ } else { ++ printf("Invalid parameter: %s\n", argv[0]); ++ return 1; ++ } ++ } else { ++ if (argc != 1 && argc != 2) ++ return 1; ++ max_argc = 2; ++ i = 0; ++ } ++ ++ if (!strcmp(argv[i], "auto")) + type = NL80211_TX_POWER_AUTOMATIC; +- else if (!strcmp(argv[0], "fixed")) ++ else if (!strcmp(argv[i], "fixed")) + type = NL80211_TX_POWER_FIXED; +- else if (!strcmp(argv[0], "limit")) ++ else if (!strcmp(argv[i], "limit")) + type = NL80211_TX_POWER_LIMITED; + else { +- printf("Invalid parameter: %s\n", argv[0]); ++ printf("Invalid parameter: %s\n", argv[i]); + return 2; + } + +@@ -687,16 +710,16 @@ static int handle_txpower(struct nl80211 + + if (type != NL80211_TX_POWER_AUTOMATIC) { + char *endptr; +- if (argc != 2) { ++ if (argc != max_argc) { + printf("Missing TX power level argument.\n"); + return 2; + } + +- mbm = strtol(argv[1], &endptr, 10); ++ mbm = strtol(argv[++i], &endptr, 10); + if (*endptr) + return 2; + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL, mbm); +- } else if (argc != 1) ++ } else if (argc != max_argc-1) + return 1; + + return 0; +@@ -707,7 +730,7 @@ static int handle_txpower(struct nl80211 + COMMAND(set, txpower, " []", + NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_txpower, + "Specify transmit power level and setting type."); +-COMMAND(set, txpower, " []", ++COMMAND(set, txpower, "[-l] []", + NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_txpower, + "Specify transmit power level and setting type."); + diff --git a/feeds/ipq95xx/iw/patches/609-05-iw-add-support-set-bitrate-command-for-each-link.patch b/feeds/ipq95xx/iw/patches/609-05-iw-add-support-set-bitrate-command-for-each-link.patch new file mode 100644 index 000000000..dd92c178f --- /dev/null +++ b/feeds/ipq95xx/iw/patches/609-05-iw-add-support-set-bitrate-command-for-each-link.patch @@ -0,0 +1,57 @@ +From 07d07d8f7f6c2b7f648d22d06db772e0ad006cf6 Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Thu, 12 Jan 2023 16:36:37 +0530 +Subject: [PATCH] iw: add support set bitrate command for each link + +Add support for set bit rate by link id in multi-link operation. + +command: +iw dev wlanX set bitrates -l eht-mcs-<6/5/2.4> + + +Signed-off-by: Aaradhana Sahu +--- + bitrate.c | 20 ++++++++++++++++++-- + 1 file changed, 18 insertions(+), 2 deletions(-) + +diff --git a/bitrate.c b/bitrate.c +index 571ebb4..24752be 100644 +--- a/bitrate.c ++++ b/bitrate.c +@@ -199,7 +199,7 @@ int set_bitrates(struct nl_msg *msg, + enum nl80211_attrs attr) + { + struct nlattr *nl_rates, *nl_band; +- int i, ret = 0; ++ int i, index, ret = 0; + bool have_legacy_24 = false, have_legacy_5 = false; + uint8_t legacy_24[32], legacy_5[32]; + int n_legacy_24 = 0, n_legacy_5 = 0; +@@ -266,7 +266,23 @@ int set_bitrates(struct nl_msg *msg, + S_EHT_LTF, + } parser_state = S_NONE; + +- for (i = 0; i < argc; i++) { ++ if (!strcmp(argv[0], "-l")) { ++ unsigned int link_id; ++ char *endptr; ++ ++ link_id = strtol(argv[1], &endptr, 10); ++ if (*endptr) ++ return 1; ++ if (link_id <= MAX_MLD_LINK) { ++ NLA_PUT_U8(msg, NL80211_ATTR_MLO_LINK_ID, ++ link_id); ++ index = 2; ++ } ++ } else { ++ index = 0; ++ } ++ ++ for (i = index; i < argc; i++) { + char *end; + double tmpd; + long tmpl; +-- +2.17.1 + diff --git a/feeds/ipq95xx/iw/patches/609-06-iw-add-support-for-rts-threshold-command-for-MLO.patch b/feeds/ipq95xx/iw/patches/609-06-iw-add-support-for-rts-threshold-command-for-MLO.patch new file mode 100644 index 000000000..251993be9 --- /dev/null +++ b/feeds/ipq95xx/iw/patches/609-06-iw-add-support-for-rts-threshold-command-for-MLO.patch @@ -0,0 +1,75 @@ +From f253847b35ea0d11526f27d7f4d931beab87d59f Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Fri, 10 Feb 2023 15:47:48 +0530 +Subject: [PATCH] iw: add support for rts threshold command for MLO + +Add support for set rts threshold command according to +each link id for multi-link operation. + +command: +iw dev wlan# set rts -l + +Signed-off-by: Aaradhana Sahu +--- + phy.c | 36 ++++++++++++++++++++++++++++++------ + 1 file changed, 30 insertions(+), 6 deletions(-) + +--- a/phy.c ++++ b/phy.c +@@ -444,19 +444,40 @@ static int handle_rts(struct nl80211_sta + int argc, char **argv, + enum id_input id) + { +- unsigned int rts; ++ unsigned int rts, link_id; ++ int index = 0; ++ char *endptr; + +- if (argc != 1) ++ if (!argc) { + return 1; ++ } else if (argc == 3) { ++ if (!strcmp(argv[0], "-l")) { ++ link_id = strtol(argv[1], &endptr, 10); ++ ++ if (*endptr) ++ return 1; ++ ++ if (link_id <= MAX_MLD_LINK) { ++ NLA_PUT_U8(msg, NL80211_ATTR_MLO_LINK_ID, ++ link_id); ++ index = 2; ++ } ++ } else { ++ printf("Invalid parameter: %s\n", argv[0]); ++ return 1; ++ } ++ } + +- if (strcmp("off", argv[0]) == 0) ++ if (strcmp("off", argv[index]) == 0) { + rts = -1; +- else { ++ } else { + char *end; + +- if (!*argv[0]) ++ if (!*argv[index]) + return 1; +- rts = strtoul(argv[0], &end, 10); ++ ++ rts = strtoul(argv[index], &end, 10); ++ + if (*end != '\0') + return 1; + } +@@ -470,6 +491,9 @@ static int handle_rts(struct nl80211_sta + COMMAND(set, rts, "", + NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_rts, + "Set rts threshold."); ++COMMAND(set, rts, "[-l] ", ++ NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_rts, ++ "Set rts threshold."); + + static int handle_retry(struct nl80211_state *state, + struct nl_msg *msg, diff --git a/feeds/ipq95xx/iw/patches/609-iw-interface-combination-changes.patch b/feeds/ipq95xx/iw/patches/609-iw-interface-combination-changes.patch new file mode 100644 index 000000000..74a592f88 --- /dev/null +++ b/feeds/ipq95xx/iw/patches/609-iw-interface-combination-changes.patch @@ -0,0 +1,281 @@ +From 9c263bc61d802fab30b3529ebdaace86f564e8f0 Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Fri, 4 Nov 2022 18:51:54 +0530 +Subject: [PATCH] iw: interface combination changes + +print multi_hw channels +print multi_hw interface combinations + +Signed-off-by: Harshitha Prem +--- + info.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++- + nl80211.h | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 170 insertions(+), 2 deletions(-) + +--- a/info.c ++++ b/info.c +@@ -390,7 +390,6 @@ next: + + if (tb_msg[NL80211_ATTR_WIPHY_COVERAGE_CLASS]) { + unsigned char coverage; +- + coverage = nla_get_u8(tb_msg[NL80211_ATTR_WIPHY_COVERAGE_CLASS]); + /* See handle_distance() for an explanation where the '450' comes from */ + printf("\tCoverage class: %d (up to %dm)\n", coverage, 450 * coverage); +@@ -436,6 +435,7 @@ next: + struct nlattr *nl_combi; + int rem_combi; + bool have_combinations = false; ++ bool have_combinations_per_hw = false; + + nla_for_each_nested(nl_combi, tb_msg[NL80211_ATTR_INTERFACE_COMBINATIONS], rem_combi) { + static struct nla_policy iface_combination_policy[NUM_NL80211_IFACE_COMB] = { +@@ -444,6 +444,7 @@ next: + [NL80211_IFACE_COMB_STA_AP_BI_MATCH] = { .type = NLA_FLAG }, + [NL80211_IFACE_COMB_NUM_CHANNELS] = { .type = NLA_U32 }, + [NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS] = { .type = NLA_U32 }, ++ [NL80211_IFACE_COMB_PER_HW_COMB] = { .type = NLA_NESTED }, + }; + struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB]; + static struct nla_policy iface_limit_policy[NUM_NL80211_IFACE_LIMIT] = { +@@ -452,7 +453,15 @@ next: + }; + struct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT]; + struct nlattr *nl_limit; +- int err, rem_limit; ++ static struct nla_policy iface_comb_per_hw_policy[NUM_NL80211_IFACE_COMB_PER_HW_COMB] = { ++ [NL80211_IFACE_COMB_PER_HW_COMB_HW_IDX] = { .type = NLA_U8 }, ++ [NL80211_IFACE_COMB_PER_HW_COMB_LIMITS] = { .type = NLA_NESTED }, ++ [NL80211_IFACE_COMB_PER_HW_COMB_MAXIMUM] = { .type = NLA_U16 }, ++ [NL80211_IFACE_COMB_PER_HW_COMB_NUM_CHANNELS] = { .type = NLA_U32 }, ++ }; ++ struct nlattr *tb_per_hw[NUM_NL80211_IFACE_COMB_PER_HW_COMB]; ++ struct nlattr *nl_per_hw; ++ int err, rem_limit, rem_per_hw; + bool comma = false; + + if (!have_combinations) { +@@ -512,6 +521,43 @@ next: + } + } + printf("\n"); ++ ++ if (!tb_comb[NL80211_IFACE_COMB_PER_HW_COMB]) ++ goto broken_combination; ++ ++ nla_for_each_nested(nl_per_hw, tb_comb[NL80211_IFACE_COMB_PER_HW_COMB], rem_per_hw) { ++ comma = false; ++ if (!have_combinations_per_hw) { ++ printf("\tvalid interface combo per hw:"); ++ have_combinations_per_hw = true; ++ } ++ ++ err = nla_parse_nested(tb_per_hw, MAX_NL80211_IFACE_COMB_PER_HW_COMB, ++ nl_per_hw, iface_comb_per_hw_policy); ++ if (err || !tb_per_hw[NL80211_IFACE_COMB_PER_HW_COMB_HW_IDX]) { ++ printf(" at %d %d\n", __LINE__, err); ++ goto broken_combination; ++ } ++ printf("\n\t\thw_idx %d:\n\t\t\t max num of iface: %d, #channels <= %d,", ++ nla_get_u8(tb_per_hw[NL80211_IFACE_COMB_PER_HW_COMB_HW_IDX]), ++ nla_get_u32(tb_per_hw[NL80211_IFACE_COMB_PER_HW_COMB_MAXIMUM]), ++ nla_get_u16(tb_per_hw[NL80211_IFACE_COMB_NUM_CHANNELS])); ++ nla_for_each_nested(nl_limit, tb_comb[NL80211_IFACE_COMB_LIMITS], rem_limit) { ++ err = nla_parse_nested(tb_limit, MAX_NL80211_IFACE_LIMIT, ++ nl_limit, iface_limit_policy); ++ if (err || !tb_limit[NL80211_IFACE_LIMIT_TYPES]) { ++ printf(" at %d %d\n", __LINE__, err); ++ goto broken_combination; ++ } ++ if (comma) ++ printf(", "); ++ comma = true; ++ printf("#{ "); ++ print_iftype_line(tb_limit[NL80211_IFACE_LIMIT_TYPES]); ++ printf(" } <= %u", nla_get_u32(tb_limit[NL80211_IFACE_LIMIT_MAX])); ++ } ++ } ++ printf("\n"); + broken_combination: + ; + } +@@ -762,6 +808,49 @@ broken_combination: + printf("\tMaximum associated stations in AP mode: %u\n", + nla_get_u16(tb_msg[NL80211_ATTR_MAX_AP_ASSOC_STA])); + ++ if (tb_msg[NL80211_ATTR_MULTI_HW_MACS]) { ++ struct nlattr *tb_hw[NL80211_MULTI_HW_MAC_ATTR_MAX + 1]; ++ struct nlattr *tb_freq[NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_MAX + 1]; ++ struct nlattr *nl_hw_macs; ++ struct nlattr *nl_freq_list; ++ int rem_hw_macs, rem_freq_list; ++ ++ nla_for_each_nested(nl_hw_macs, tb_msg[NL80211_ATTR_MULTI_HW_MACS], ++ rem_hw_macs) { ++ nla_parse(tb_hw, NL80211_MULTI_HW_MAC_ATTR_MAX, ++ nla_data(nl_hw_macs), nla_len(nl_hw_macs), ++ NULL); ++ ++ if (tb_hw[NL80211_MULTI_HW_MAC_ATTR_IDX]) { ++ uint8_t hw_idx; ++ hw_idx = nla_get_u8(tb_hw[NL80211_MULTI_HW_MAC_ATTR_IDX]); ++ printf("\n\thw_idx %d channel list:\n", hw_idx); ++ } ++ if (tb_hw[NL80211_MULTI_HW_MAC_ATTR_CHAN_LIST]) { ++ uint8_t count = 0; ++ printf("\t\t"); ++ nla_for_each_nested(nl_freq_list, ++ tb_hw[NL80211_MULTI_HW_MAC_ATTR_CHAN_LIST], ++ rem_freq_list) { ++ if (count == 20) { ++ printf("\n\t\t"); ++ count = 0; ++ } ++ nla_parse(tb_freq, NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_MAX, ++ nla_data(nl_freq_list), nla_len(nl_freq_list), ++ NULL); ++ if (tb_freq[NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_FREQ]) { ++ uint32_t freq; ++ freq = nla_get_u32(tb_freq[NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_FREQ]); ++ printf("%d ",ieee80211_frequency_to_channel(freq)); ++ count++; ++ } ++ } ++ } ++ } ++ printf("\n"); ++ } ++ + return NL_SKIP; + } + +--- a/nl80211.h ++++ b/nl80211.h +@@ -3217,6 +3217,8 @@ enum nl80211_attrs { + + NL80211_ATTR_AP_PS, + ++ NL80211_ATTR_MULTI_HW_MACS, ++ + /* add attributes here, update the policy in nl80211.c */ + + __NL80211_ATTR_AFTER_LAST, +@@ -5826,6 +5828,10 @@ enum nl80211_iface_limit_attrs { + * @NL80211_IFACE_COMB_BI_MIN_GCD: u32 attribute specifying the minimum GCD of + * different beacon intervals supported by all the interface combinations + * in this group (if not present, all beacon intervals be identical). ++ * @NL80211_IFACE_COMB_PER_HW_COMB: nested attribute specifying the interface ++ * combination for each underlying hardware when multiple hardware are ++ * registered under a single wiphy, ++ * see &enum nl80211_if_combination_per_hw_comb_attrs. + * @NUM_NL80211_IFACE_COMB: number of attributes + * @MAX_NL80211_IFACE_COMB: highest attribute number + * +@@ -5841,6 +5847,16 @@ enum nl80211_iface_limit_attrs { + * + * numbers = [ #{STA} <= 1, #{P2P-client,P2P-GO} <= 3 ], max = 4 + * => allows a STA plus three P2P interfaces ++ * When describing per-hw combinations, the first possibility can ++ * further include the finer capabilities like below ++ * hw_chan_idx = 0, numbers = [ #{STA} <= 1, #{AP} <= 1 ], ++ * channels = 1, max = 2 ++ * => allows a STA plus an AP interface on the underlying hw mac ++ * advertised at index 0 in wiphy @hw_chans array. ++ * hw_chan_idx = 1, numbers = [ #{STA} <= 1, #{AP} <= 2 ], ++ * channels = 1, max = 3 ++ * => allows a STA plus two AP interfaces on the underlying hw mac ++ * advertised at index 1 in wiphy @hw_chans array. + * + * The list of these four possibilities could completely be contained + * within the %NL80211_ATTR_INTERFACE_COMBINATIONS attribute to indicate +@@ -5861,12 +5877,43 @@ enum nl80211_if_combination_attrs { + NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, + NL80211_IFACE_COMB_RADAR_DETECT_REGIONS, + NL80211_IFACE_COMB_BI_MIN_GCD, +- ++ NL80211_IFACE_COMB_PER_HW_COMB, + /* keep last */ + NUM_NL80211_IFACE_COMB, + MAX_NL80211_IFACE_COMB = NUM_NL80211_IFACE_COMB - 1 + }; + ++/** ++ * enum nl80211_if_combination_per_hw_comb_attrs - per-hw iface combination ++ * attributes with multi-hw radios ++ * ++ * @NL80211_IFACE_COMB_PER_HW_COMB_UNSPEC: (reserved) ++ * @NL80211_IFACE_COMB_PER_HW_COMB_HW_IDX: u8 attribute specifying the index ++ * to the wiphy @hw_chans list for which the iface combination is being ++ * described. ++ * @NL80211_IFACE_COMB_PER_HW_COMB_LIMITS: nested attribute containing the ++ * limits for the given interface types, see ++ * &enum nl80211_iface_limit_attrs. ++ * @NL80211_IFACE_COMB_PER_HW_COMB_MAXIMUM: u32 attribute giving the maximum ++ * number of interfaces that can be created in this group. This number ++ * does not apply to the interfaces purely managed in software. ++ * @NL80211_IFACE_COMB_PER_HW_COMB_NUM_CHANNELS: u32 attribute specifying the ++ * number of different channels that can be used in this group. ++ * @NUM_NL80211_IFACE_COMB_PER_HW_COMB: number of attributes ++ * @MAX_NL80211_IFACE_COMB_PER_HW_COMB: highest attribute number ++ */ ++enum nl80211_if_combination_per_hw_comb_attrs { ++ NL80211_IFACE_COMB_PER_HW_COMB_UNSPEC, ++ NL80211_IFACE_COMB_PER_HW_COMB_HW_IDX, ++ NL80211_IFACE_COMB_PER_HW_COMB_LIMITS, ++ NL80211_IFACE_COMB_PER_HW_COMB_MAXIMUM, ++ NL80211_IFACE_COMB_PER_HW_COMB_NUM_CHANNELS, ++ ++ /* keep last */ ++ NUM_NL80211_IFACE_COMB_PER_HW_COMB, ++ MAX_NL80211_IFACE_COMB_PER_HW_COMB = ++ NUM_NL80211_IFACE_COMB_PER_HW_COMB - 1 ++}; + + /** + * enum nl80211_plink_state - state of a mesh peer link finite state machine +@@ -7766,4 +7813,45 @@ enum nl80211_ap_settings_flags { + NL80211_AP_SETTINGS_SA_QUERY_OFFLOAD_SUPPORT = 1 << 1, + }; + ++/** ++ * nl80211_multi_hw_mac_attrs - multi-hw mac attributes ++ * ++ * @NL80211_MULTI_HW_MAC_ATTR_INVALID: invalid ++ * @NL80211_MULTI_HW_MAC_ATTR_IDX: (u8) array index in wiphy @hw_chans to refer an ++ * underlying hw mac for which the supported channel list is advertised. ++ * @NL80211_MULTI_HW_MAC_ATTR_CHAN_LIST: nested attribute specifying list of ++ * supported channels, see &enum nl80211_multi_hw_mac_chan_list_attrs ++ * @__NL80211_MULTI_HW_MAC_ATTR_LAST: internal use ++ * @NL80211_MULTI_HW_MAC_ATTR_MAX: maximum multi-hw mac attribute ++ */ ++enum nl80211_multi_hw_mac_attrs { ++ __NL80211_MULTI_HW_MAC_ATTR_INVALID, ++ ++ NL80211_MULTI_HW_MAC_ATTR_IDX, ++ NL80211_MULTI_HW_MAC_ATTR_CHAN_LIST, ++ ++ /* keep last */ ++ __NL80211_MULTI_HW_MAC_ATTR_LAST, ++ NL80211_MULTI_HW_MAC_ATTR_MAX = ++ __NL80211_MULTI_HW_MAC_ATTR_LAST - 1 ++}; ++ ++/** ++ * nl80211_multi_hw_mac_chan_list_attrs - channel attributes for multi-hw ++ * ++ * @__NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_INVALID: invalid ++ * @NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_FREQ: channel center frequency in MHz ++ * @__NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_LAST: internal use ++ * @NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_MAX: maximum channel attribute ++ */ ++enum nl80211_multi_hw_mac_chan_list_attrs { ++ __NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_INVALID, ++ ++ NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_FREQ, ++ ++ /* keep last */ ++ __NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_LAST, ++ NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_MAX = ++ __NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_LAST - 1 ++}; + #endif /* __LINUX_NL80211_H */ diff --git a/feeds/ipq95xx/iw/patches/610-iw-sync-NL-Attribute-and-Ext-Feature-with-RRM-change.patch b/feeds/ipq95xx/iw/patches/610-iw-sync-NL-Attribute-and-Ext-Feature-with-RRM-change.patch new file mode 100644 index 000000000..ef10b3724 --- /dev/null +++ b/feeds/ipq95xx/iw/patches/610-iw-sync-NL-Attribute-and-Ext-Feature-with-RRM-change.patch @@ -0,0 +1,61 @@ +From c9d3ed710064b8db1757ccc5fac03d3eb9a1a97a Mon Sep 17 00:00:00 2001 +From: Raj Kumar Bhagat +Date: Thu, 26 Jan 2023 17:59:07 +0530 +Subject: [PATCH] iw: sync NL Attribute and Ext Feature with RRM changes + +Due to RRM link measurement changes new NL Attribute and NL extended +feature are added in kernel. The NL attributes and extended feature +are: + NL80211_ATTR_WIPHY_MAX_TX_POWER_LEVEL + NL80211_EXT_FEATURE_TX_POWER_REPORTING + +Add this NL changes in iw to sync NL attribute and NL extended +feature with kernel changes. + +The below NL Attributes are used in iw. Thus sync will make the +below attributes not impacted after the RRM chnages. + + NL80211_ATTR_RU_PUNCT_BITMAP + NL80211_ATTR_AP_PS + NL80211_ATTR_MULTI_HW_MACS + +Signed-off-by: Raj Kumar Bhagat +--- + info.c | 3 +++ + nl80211.h | 15 +++++++++++++++ + 2 files changed, 18 insertions(+) + +--- a/info.c ++++ b/info.c +@@ -167,7 +167,9 @@ static void ext_feat_print(enum nl80211_ + "support for MFP in range measurement negotiation/procedure"); + ext_feat_case(BSS_COLOR, "BSS coloring support"); + ext_feat_case(FILS_CRYPTO_OFFLOAD, "FILS crypto offload"); ++ ext_feat_case(WIDE_BAND_SCAN, "wide band scan support"); + ext_feat_case(RADAR_BACKGROUND, "Radar background support"); ++ ext_feat_case(STA_MGMT_RTS_CTS, "station management RTS CTS support"); + } + } + +--- a/nl80211.h ++++ b/nl80211.h +@@ -6397,6 +6397,9 @@ enum nl80211_feature_flags { + * @NL80211_EXT_FEATURE_RADAR_BACKGROUND: Device supports background radar/CAC + * detection. + * ++ * @NL80211_EXT_FEATURE_WIDE_BAND_SCAN: Driver/device supports wide band scan ++ * on a frequency along with its corresponding phymode (40Mhz, 80Mhz) ++ * + * @NUM_NL80211_EXT_FEATURES: number of extended features. + * @MAX_NL80211_EXT_FEATURES: highest extended feature index. + */ +@@ -6463,7 +6466,9 @@ enum nl80211_ext_feature_index { + NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE, + NL80211_EXT_FEATURE_BSS_COLOR, + NL80211_EXT_FEATURE_FILS_CRYPTO_OFFLOAD, ++ NL80211_EXT_FEATURE_WIDE_BAND_SCAN, + NL80211_EXT_FEATURE_RADAR_BACKGROUND, ++ NL80211_EXT_FEATURE_STA_MGMT_RTS_CTS, + + /* add new features before the definition below */ + NUM_NL80211_EXT_FEATURES, diff --git a/feeds/ipq95xx/iw/patches/611-add-sawf-support.patch b/feeds/ipq95xx/iw/patches/611-add-sawf-support.patch new file mode 100644 index 000000000..d36c78894 --- /dev/null +++ b/feeds/ipq95xx/iw/patches/611-add-sawf-support.patch @@ -0,0 +1,395 @@ +From 8fea084fa76f76159bcc110699eb5a91854e6f19 Mon Sep 17 00:00:00 2001 +From: Nagarajan Maran +Date: Thu, 10 Nov 2022 18:52:12 +0530 +Subject: [PATCH] iw: add support for sawf + +Add configure, disable and view support for SAWF service classes. + +Below is the command to configure a service class + - iw phy service_class create + [min_tput ] [max_tput ] + [burst_size ] [service_interval ] + [delay_bound ] [msdu_ttl ] [priority ] + [tid ] [msdu_loss ] + +Below is the command to disable a service class + - iw phy service_class delete + +Below is the command to view a specific service class + - iw phy service_class view + +Below is the command to view all service classes + - iw phy service_class view + +Signed-off-by: Karthikeyan Kathirvel +Co-Developed-by: Nagarajan Maran +Signed-off-by: Nagarajan Maran +--- + iw.h | 17 +++++ + sawf.c | 215 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 232 insertions(+) + create mode 100644 sawf.c + +--- a/iw.h ++++ b/iw.h +@@ -69,6 +69,12 @@ enum id_input { + II_WDEV, + }; + ++enum qca_nl80211_vendor_subcmds { ++ QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS = 203, ++ QCA_NL80211_VENDOR_SUBCMD_SVC_CREATE = 204, ++ QCA_NL80211_VENDOR_SUBCMD_SVC_DISABLE = 205, ++ QCA_NL80211_VENDOR_SUBCMD_SVC_VIEW = 206, ++}; + /* Attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION and + * QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION subcommands. +@@ -82,6 +88,26 @@ enum qca_wlan_vendor_attr_config { + QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST - 1, + }; + ++enum qca_wlan_vendor_sawf_attr_config { ++ QCA_WLAN_VENDOR_ATTR_SAWF_SERVICE_CLASSES = 1, ++ QCA_WLAN_VENDOR_ATTR_SAWF_SVC_ID, ++ QCA_WLAN_VENDOR_ATTR_SAWF_SVC_APP_NAME, ++ QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MIN_TP, ++ QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MAX_TP, ++ QCA_WLAN_VENDOR_ATTR_SAWF_SVC_BURST_SIZE, ++ QCA_WLAN_VENDOR_ATTR_SAWF_SVC_INTERVAL, ++ QCA_WLAN_VENDOR_ATTR_SAWF_SVC_DELAY_BOUND, ++ QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_TTL, ++ QCA_WLAN_VENDOR_ATTR_SAWF_SVC_PRIO, ++ QCA_WLAN_VENDOR_ATTR_SAWF_SVC_TID, ++ QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_RATE_LOSS, ++ ++ /* keep last */ ++ QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_AFTER_LAST, ++ QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX = ++ QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_AFTER_LAST - 1, ++}; ++ + #define HANDLER_RET_USAGE 1 + #define HANDLER_RET_DONE 3 + +--- /dev/null ++++ b/sawf.c +@@ -0,0 +1,318 @@ ++/* ++ * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. ++ ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "nl80211.h" ++#include "iw.h" ++ ++#define OUI_QCA 0x001374 ++#define MAX_OPTIONAL_STRINGS 9 ++#define MAX_STRING_SIZE 60 ++#define MAX_RANGE(type) pow(2, 8 * sizeof(type)) - 1 ++#define SVC_CREATE_MIN_ARGUMENTS 2 ++#define SVC_CREATE_MAX_ARGUMENTS 20 ++#define SVC_DISABLE_MAX_ARGUMENTS 1 ++#define SVC_VIEW_MAX_ARGUMENTS 1 ++#define APP_NAME_MAX_BYTES 64 ++ ++struct sawf_disable_param { ++ uint8_t svc_id; ++}; ++ ++SECTION(service_class); ++ ++static int handle_service_class_create(struct nl80211_state *state, ++ struct nl_msg *msg, int argc, ++ char **argv, enum id_input id) ++{ ++ struct nlattr *service_class; ++ char app_name[APP_NAME_MAX_BYTES]; ++ int parsed = 0, param_count; ++ char *end; ++ unsigned long value; ++ char service_check[MAX_OPTIONAL_STRINGS][MAX_STRING_SIZE] = {"min_tput", ++ "max_tput", ++ "burst_size", ++ "service_interval", ++ "delay_bound", ++ "msdu_ttl", ++ "priority", ++ "tid", ++ "msdu_loss"}; ++ ++ if (argc < SVC_CREATE_MIN_ARGUMENTS || argc > SVC_CREATE_MAX_ARGUMENTS || ++ (argc % SVC_CREATE_MIN_ARGUMENTS) != 0) ++ goto err; ++ ++ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA); ++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, ++ QCA_NL80211_VENDOR_SUBCMD_SVC_CREATE); ++ ++ service_class = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA); ++ if (!service_class) ++ return -ENOBUFS; ++ ++ errno = 0; ++ value = strtoul(argv[0], &end, 10); ++ if (*end != '\0' || value > MAX_RANGE(uint8_t) || errno == ERANGE) ++ goto err; ++ ++ strlcpy(app_name, argv[1], APP_NAME_MAX_BYTES); ++ ++ nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_SAWF_SVC_ID, value); ++ nla_put(msg, QCA_WLAN_VENDOR_ATTR_SAWF_SVC_APP_NAME, sizeof(app_name), app_name); ++ ++ parsed += 2; ++ ++ for (errno = 0; parsed < argc; parsed += 2, errno = 0) { ++ value = strtoul(argv[parsed + 1], &end, 10); ++ if (*end != '\0' || value > MAX_RANGE(uint32_t) || errno == ERANGE) ++ goto err; ++ ++ for (param_count = 0; param_count < MAX_OPTIONAL_STRINGS; ++ param_count++) { ++ if (!strcmp(argv[parsed], service_check[param_count])) ++ break; ++ } ++ ++ if (param_count == MAX_OPTIONAL_STRINGS) ++ goto err; ++ ++ switch (param_count + QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MIN_TP) { ++ case QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MIN_TP: ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MIN_TP, value); ++ break; ++ case QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MAX_TP: ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MAX_TP, value); ++ break; ++ case QCA_WLAN_VENDOR_ATTR_SAWF_SVC_BURST_SIZE: ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SAWF_SVC_BURST_SIZE, value); ++ break; ++ case QCA_WLAN_VENDOR_ATTR_SAWF_SVC_INTERVAL: ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SAWF_SVC_INTERVAL, value); ++ break; ++ case QCA_WLAN_VENDOR_ATTR_SAWF_SVC_DELAY_BOUND: ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SAWF_SVC_DELAY_BOUND, ++ value); ++ break; ++ case QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_TTL: ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_TTL, value); ++ break; ++ case QCA_WLAN_VENDOR_ATTR_SAWF_SVC_PRIO: ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SAWF_SVC_PRIO, value); ++ break; ++ case QCA_WLAN_VENDOR_ATTR_SAWF_SVC_TID: ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SAWF_SVC_TID, value); ++ break; ++ case QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_RATE_LOSS: ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_RATE_LOSS, ++ value); ++ break; ++ } ++ } ++ ++ nla_nest_end(msg, service_class); ++ return 0; ++err: ++ printf("Invalid SAWF service class command format: Usage\n"); ++ printf("\t iw phy service_class create "); ++ printf("[min_tput ] [max_tput ] "); ++ printf("[burst_size ] [service_interval ] "); ++ printf("[delay_bound ] [msdu_ttl ] "); ++ printf("[priority ] [tid ] [msdu_loss ]\n"); ++ ++ return -EINVAL; ++} ++ ++COMMAND(service_class, create, " [min_tput ]" ++ " [max_tput ] [burst_size ]" ++ " [service_interval ] [delay_bound ]" ++ " [msdu_ttl ] [priority ] [tid ]" ++ " [msdu_loss ]", NL80211_CMD_VENDOR, 0, CIB_PHY, ++ handle_service_class_create, "."); ++ ++static int handle_service_class_disable(struct nl80211_state *state, ++ struct nl_msg *msg, int argc, ++ char **argv, enum id_input id) ++{ ++ struct nlattr *service_class; ++ unsigned long value; ++ char *end; ++ ++ if (argc != SVC_DISABLE_MAX_ARGUMENTS) ++ goto err; ++ ++ errno = 0; ++ value = strtoul(argv[0], &end, 10); ++ if (*end != '\0' || value > MAX_RANGE(uint8_t) || errno == ERANGE) ++ goto err; ++ ++ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA); ++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, ++ QCA_NL80211_VENDOR_SUBCMD_SVC_DISABLE); ++ ++ service_class = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA); ++ if (!service_class) ++ return -ENOBUFS; ++ ++ nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_SAWF_SVC_ID, value); ++ ++ nla_nest_end(msg, service_class); ++ return 0; ++ ++err: ++ printf("Invalid SAWF service class command format: Usage\n"); ++ printf("\t iw phy service_class disable \n"); ++ return -EINVAL; ++} ++ ++COMMAND(service_class, disable, "", NL80211_CMD_VENDOR, 0, CIB_PHY, ++ handle_service_class_disable, "."); ++ ++static int print_sawf_service_classes(struct nl_msg *msg, void *arg) ++{ ++ struct nlattr *tb_msg[NL80211_ATTR_MAX + 1]; ++ struct nlattr *sawf_service_classes; ++ struct nlattr *sawf_service_class; ++ struct nlattr *attrs[QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX + 1]; ++ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); ++ int sawf_service_classes_len = 0; ++ char *app_name = NULL; ++ static struct nla_policy sawf_policy[QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX + 1] = { ++ [QCA_WLAN_VENDOR_ATTR_SAWF_SVC_ID] = {.type = NLA_U8}, ++ [QCA_WLAN_VENDOR_ATTR_SAWF_SVC_APP_NAME] = {.type = NLA_STRING}, ++ [QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MIN_TP] = {.type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MAX_TP] = {.type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_SAWF_SVC_BURST_SIZE] = {.type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_SAWF_SVC_INTERVAL] = {.type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_SAWF_SVC_DELAY_BOUND] = {.type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_TTL] = {.type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_SAWF_SVC_PRIO] = {.type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_SAWF_SVC_TID] = {.type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_RATE_LOSS] = {.type = NLA_U32}, ++ }; ++ ++ nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), ++ genlmsg_attrlen(gnlh, 0), NULL); ++ ++ if (tb_msg[NL80211_ATTR_VENDOR_DATA]) { ++ sawf_service_classes = nla_data(tb_msg[NL80211_ATTR_VENDOR_DATA]); ++ sawf_service_classes_len = nla_len(tb_msg[NL80211_ATTR_VENDOR_DATA]); ++ } ++ else ++ return NL_SKIP; ++ ++ if (nla_type(sawf_service_classes) != QCA_WLAN_VENDOR_ATTR_SAWF_SERVICE_CLASSES ) ++ return NL_SKIP; ++ ++ nla_for_each_nested(sawf_service_class, sawf_service_classes, ++ sawf_service_classes_len) { ++ nla_parse_nested(attrs, ++ QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX, ++ sawf_service_class, sawf_policy); ++ ++ printf("***********************************\n"); ++ if (attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_ID]) ++ printf("Service ID\t: %u\n", ++ nla_get_u8(attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_ID])); ++ if (attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_APP_NAME]) { ++ app_name = nla_data(attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_APP_NAME]); ++ printf("App Name\t: %s\n", app_name); ++ } ++ if (attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MIN_TP]) ++ printf("Min throughput\t: %u\n", ++ nla_get_u32(attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MIN_TP])); ++ if (attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MAX_TP]) ++ printf("Max throughput\t: %u\n", ++ nla_get_u32(attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MAX_TP])); ++ if (attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_BURST_SIZE]) ++ printf("Burst Size\t: %u\n", ++ nla_get_u32(attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_BURST_SIZE])); ++ if (attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_INTERVAL]) ++ printf("Service Interval: %u\n", ++ nla_get_u32(attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_INTERVAL])); ++ if (attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_DELAY_BOUND]) ++ printf("Delay Bound\t: %u\n", ++ nla_get_u32(attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_DELAY_BOUND])); ++ if (attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_TTL]) ++ printf("MSDU TTL\t: %u\n", ++ nla_get_u32(attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_TTL])); ++ if (attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_PRIO]) ++ printf("Priority\t: %u\n", ++ nla_get_u32(attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_PRIO])); ++ if (attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_TID]) ++ printf("TID\t\t: %u\n", ++ nla_get_u32(attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_TID])); ++ if (attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_RATE_LOSS]) ++ printf("MSDU Loss Rate\t: %u\n", ++ nla_get_u32(attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_RATE_LOSS])); ++ } ++ return NL_SKIP; ++} ++ ++static int handle_service_class_dump(struct nl80211_state *state, ++ struct nl_msg *msg, int argc, ++ char **argv, enum id_input id) ++{ ++ struct nlattr *service_class; ++ unsigned long value = 0; ++ char *end; ++ ++ if (argc > SVC_VIEW_MAX_ARGUMENTS) { ++ goto err; ++ } ++ else if (argc == SVC_VIEW_MAX_ARGUMENTS) { ++ errno = 0; ++ value = strtoul(argv[0], &end, 10); ++ if (*end != '\0' || value > MAX_RANGE(uint8_t) || errno == ERANGE) ++ goto err; ++ } ++ ++ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA); ++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, ++ QCA_NL80211_VENDOR_SUBCMD_SVC_VIEW); ++ ++ service_class = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA); ++ if (!service_class) ++ return -ENOBUFS; ++ ++ if (argc) ++ nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_SAWF_SVC_ID, value); ++ ++ nla_nest_end(msg, service_class); ++ ++ register_handler(print_sawf_service_classes, NULL); ++ return 0; ++err: ++ printf("Invalid SAWF service class command format: Usage\n"); ++ printf("\t iw phy service_class view []\n"); ++ return -EINVAL; ++} ++ ++COMMAND(service_class, view, "[]", NL80211_CMD_VENDOR, NLM_F_DUMP, CIB_PHY, ++ handle_service_class_dump, "."); diff --git a/feeds/ipq95xx/iw/patches/611-iw-add-support-to-add-del-multi-chan-support-for-mon.patch b/feeds/ipq95xx/iw/patches/611-iw-add-support-to-add-del-multi-chan-support-for-mon.patch new file mode 100644 index 000000000..7557fd9f6 --- /dev/null +++ b/feeds/ipq95xx/iw/patches/611-iw-add-support-to-add-del-multi-chan-support-for-mon.patch @@ -0,0 +1,197 @@ +From 98e3c7c11e335d9f63bdf7377ba2ebfa6cc251b0 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Kathirvel +Date: Mon, 20 Mar 2023 14:00:30 +0530 +Subject: [PATCH] iw: add support to add/del multi chan support for monitor + +The below command helps to add multiple channels to monitor interface +iw dev mon0 add channel 11 +iw dev mon0 add channel 36 +iw dev mon0 add channel 49 6G + +Similarly channel can be deleted from the monitor interface +iw dev mon0 del channel 36 + +The same is done for set freq command and added add freq and del freq + +Signed-off-by: Karthikeyan Kathirvel +--- + iw.h | 1 + + nl80211.h | 16 +++++++++ + phy.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- + 3 files changed, 119 insertions(+), 2 deletions(-) + +diff --git a/iw.h b/iw.h +index d01b85b70df8..972df0c32fc8 100644 +--- a/iw.h ++++ b/iw.h +@@ -324,6 +324,7 @@ DECLARE_SECTION(reg); + DECLARE_SECTION(roc); + DECLARE_SECTION(scan); + DECLARE_SECTION(set); ++DECLARE_SECTION(add); + DECLARE_SECTION(station); + DECLARE_SECTION(survey); + DECLARE_SECTION(switch); +diff --git a/nl80211.h b/nl80211.h +index 2d9a3d65afe8..f336ff4139dc 100644 +--- a/nl80211.h ++++ b/nl80211.h +@@ -2683,6 +2683,16 @@ enum nl80211_commands { + * the operating channel as per device capability, policy and regulatory + * authority in signed mBm units. + * ++ * @NL80211_ATTR_RADAR_BITMAP: (u16) RADAR bitmap where the lowest bit ++ * corresponds to the lowest 20MHZ channel. Each bit set to 1 ++ * indicates that radar is detected in that sub-channel. ++ * ++ * @NL80211_ATTR_ADD_MULTI_CHAN: Add channel to the radio, this is used ++ * for monitor interface (u32). ++ * ++ * @NL80211_ATTR_DEL_MULTI_CHAN: Delete channel from the radio, this is used ++ * for monitor interface (u32). ++ * + * @NUM_NL80211_ATTR: total number of nl80211_attrs available + * @NL80211_ATTR_MAX: highest attribute number currently defined + * @__NL80211_ATTR_AFTER_LAST: internal use +@@ -3237,6 +3247,12 @@ enum nl80211_attrs { + + NL80211_ATTR_MULTI_HW_MACS, + ++ NL80211_ATTR_RADAR_BITMAP, ++ ++ NL80211_ATTR_EHT_240MHZ_CAPABILITY, ++ ++ NL80211_ATTR_ADD_MULTI_CHAN, ++ NL80211_ATTR_DEL_MULTI_CHAN, + /* add attributes here, update the policy in nl80211.c */ + + __NL80211_ATTR_AFTER_LAST, +diff --git a/phy.c b/phy.c +index e935c27af2ee..23cd45318dbd 100644 +--- a/phy.c ++++ b/phy.c +@@ -15,6 +15,8 @@ + #include "nl80211.h" + #include "iw.h" + ++SECTION(add); ++ + struct channels_ctx { + int last_band; + bool width_40; +@@ -209,6 +211,59 @@ COMMAND(set, freq, + " [5|10|20|40|80|80+80|160|320] [ []] [ru-puncturing-bitmap ]", + NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_freq, NULL); + ++static int handle_add_freq(struct nl80211_state *state, struct nl_msg *msg, ++ int argc, char **argv, ++ enum id_input id) ++{ ++ struct chandef chandef; ++ int res; ++ ++ res = parse_freqchan(&chandef, false, argc, argv, NULL); ++ if (res) ++ return res; ++ ++ NLA_PUT_U32(msg, NL80211_ATTR_ADD_MULTI_CHAN, true); ++ ++ return put_chandef(msg, &chandef); ++ nla_put_failure: ++ return -ENOBUFS; ++} ++ ++COMMAND(add, freq, ++ " [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz|160MHz|320MHz]\n" ++ " [5|10|20|40|80|80+80|160|320] [ []]", ++ NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_add_freq, ++ "Set frequency/channel the hardware is using, including HT\n" ++ "configuration."); ++COMMAND(add, freq, ++ " [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz|160MHz|320MHz]\n" ++ " [5|10|20|40|80|80+80|160|320] [ []]", ++ NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_add_freq, NULL); ++ ++static int handle_del_freq(struct nl80211_state *state, struct nl_msg *msg, ++ int argc, char **argv, ++ enum id_input id) ++{ ++ struct chandef chandef; ++ int res; ++ ++ res = parse_freqchan(&chandef, false, argc, argv, NULL); ++ if (res) ++ return res; ++ ++ NLA_PUT_U32(msg, NL80211_ATTR_DEL_MULTI_CHAN, true); ++ ++ return put_chandef(msg, &chandef); ++ nla_put_failure: ++ return -ENOBUFS; ++} ++ ++COMMAND(del, freq, "\n", ++ NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_del_freq, ++ "del frequency/channel the hardware is using\n"); ++COMMAND(del, freq, "\n", ++ NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_del_freq, NULL); ++ + static int handle_chan(struct nl80211_state *state, struct nl_msg *msg, + int argc, char **argv, + enum id_input id) +@@ -227,6 +282,52 @@ COMMAND(set, channel, " [6G] [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz|16 + COMMAND(set, channel, " [6G] [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz|160MHz|320MHz] [6G] [ru-puncturing-bitmap ]", + NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_chan, NULL); + ++static int handle_add_chan(struct nl80211_state *state, struct nl_msg *msg, ++ int argc, char **argv, ++ enum id_input id) ++{ ++ struct chandef chandef; ++ int res; ++ ++ res = parse_freqchan(&chandef, true, argc, argv, NULL); ++ if (res) ++ return res; ++ ++ NLA_PUT_U32(msg, NL80211_ATTR_ADD_MULTI_CHAN, true); ++ ++ return put_chandef(msg, &chandef); ++ ++ nla_put_failure: ++ return -ENOBUFS; ++} ++COMMAND(add, channel, " [6G] [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz|160MHz|320MHz]", ++ NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_add_chan, NULL); ++COMMAND(add, channel, " [6G] [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz|160MHz|320MHz] [6G]", ++ NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_add_chan, NULL); ++ ++static int handle_del_chan(struct nl80211_state *state, struct nl_msg *msg, ++ int argc, char **argv, ++ enum id_input id) ++{ ++ struct chandef chandef; ++ int res; ++ ++ res = parse_freqchan(&chandef, true, argc, argv, NULL); ++ if (res) ++ return res; ++ ++ NLA_PUT_U32(msg, NL80211_ATTR_DEL_MULTI_CHAN, true); ++ ++ return put_chandef(msg, &chandef); ++ ++ nla_put_failure: ++ return -ENOBUFS; ++} ++COMMAND(del, channel, " [6G]", ++ NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_del_chan, NULL); ++COMMAND(del, channel, " [6G]", ++ NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_del_chan, NULL); ++ + + struct cac_event { + int ret; +-- +2.38.0 + diff --git a/feeds/ipq95xx/iw/patches/612-iw-Add-support-for-link-specific-station-dump-fields.patch b/feeds/ipq95xx/iw/patches/612-iw-Add-support-for-link-specific-station-dump-fields.patch new file mode 100644 index 000000000..937971ecb --- /dev/null +++ b/feeds/ipq95xx/iw/patches/612-iw-Add-support-for-link-specific-station-dump-fields.patch @@ -0,0 +1,115 @@ +From 1898807476c589bf140d7cf9690f172e9c97ab18 Mon Sep 17 00:00:00 2001 +From: Sivashankari Madhavan +Date: Fri, 5 May 2023 10:34:40 +0530 +Subject: [PATCH] iw: Add support for link specific station dump fields display + +While connecting the AP with a station in SLO/MLO mode observe +the Dtim period and Beacon Interval as 0 in the station dump. + +During the start AP, these fields are updated in the specific +link config. But when setting the station info, it's referring +to the sdata bss config. Due to this, observing the issue. + +Fix it by updating these fields with corresponding link config data +per active link. + +Signed-off-by: Sivashankari Madhavan +--- + nl80211.h | 8 ++++++++ + station.c | 51 +++++++++++++++++++++++++++++++++++++++++++-------- + 2 files changed, 51 insertions(+), 8 deletions(-) + +Index: iw-5.19/station.c +=================================================================== +--- iw-5.19.orig/station.c ++++ iw-5.19/station.c +@@ -148,9 +148,11 @@ static void parse_tid_stats(struct nlatt + printf("\n\tTXQs:%s", txqbuf); + } + +-static void parse_bss_param(struct nlattr *bss_param_attr) ++static void parse_bss_param(struct nlattr *bss_param_attr, ++ struct nlattr *tb[NL80211_ATTR_MAX + 1]) + { + struct nlattr *bss_param_info[NL80211_STA_BSS_PARAM_MAX + 1], *info; ++ struct nlattr *attrs; + static struct nla_policy bss_poilcy[NL80211_STA_BSS_PARAM_MAX + 1] = { + [NL80211_STA_BSS_PARAM_CTS_PROT] = { .type = NLA_FLAG }, + [NL80211_STA_BSS_PARAM_SHORT_PREAMBLE] = { .type = NLA_FLAG }, +@@ -159,17 +161,58 @@ static void parse_bss_param(struct nlatt + [NL80211_STA_BSS_PARAM_BEACON_INTERVAL] = { .type = NLA_U16 }, + }; + +- if (nla_parse_nested(bss_param_info, NL80211_STA_BSS_PARAM_MAX, +- bss_param_attr, bss_poilcy)) { +- printf("failed to parse nested bss param attributes!"); ++ if (tb[NL80211_ATTR_MLO_LINKS]) { ++ int ret = 0, dtim_offset = 0, beacon_int_offset = 0; ++ const char *dtim_indent = "", *beacon_int_indent = ""; ++ char dtim_buf[MLD_MAX_LINK_BUF_SIZE], ++ beacon_int_buf[MLD_MAX_LINK_BUF_SIZE]; ++ ++ nla_for_each_nested(attrs, bss_param_attr, ret) { ++ if (nla_parse_nested(bss_param_info, ++ NL80211_STA_BSS_PARAM_MAX, ++ attrs, bss_poilcy)) { ++ printf("\nFailed to parse nested bss param attributes!\n"); ++ } ++ ++ info = bss_param_info[NL80211_STA_BSS_PARAM_DTIM_PERIOD]; ++ ++ if (info) { ++ dtim_offset += snprintf(dtim_buf + dtim_offset, ++ MLD_MAX_LINK_BUF_SIZE - dtim_offset, ++ "%s%u", dtim_indent, ++ nla_get_u8(info)); ++ dtim_indent = ", "; ++ } ++ ++ info = bss_param_info[NL80211_STA_BSS_PARAM_BEACON_INTERVAL]; ++ ++ if (info) { ++ beacon_int_offset += snprintf(beacon_int_buf + beacon_int_offset, ++ MLD_MAX_LINK_BUF_SIZE - beacon_int_offset, ++ "%s%u", beacon_int_indent, ++ nla_get_u16(info)); ++ beacon_int_indent = ", "; ++ } ++ } ++ ++ printf("\n\tDTIM period:\t%s",dtim_buf); ++ ++ printf("\n\tbeacon interval:%s",beacon_int_buf); ++ } else { ++ if (nla_parse_nested(bss_param_info, ++ NL80211_STA_BSS_PARAM_MAX, ++ bss_param_attr, bss_poilcy)) { ++ printf("\nFailed to parse nested bss param attributes!\n"); ++ } ++ ++ info = bss_param_info[NL80211_STA_BSS_PARAM_DTIM_PERIOD]; ++ if (info) ++ printf("\n\tDTIM period:\t%u", nla_get_u8(info)); ++ info = bss_param_info[NL80211_STA_BSS_PARAM_BEACON_INTERVAL]; ++ if (info) ++ printf("\n\tbeacon interval:%u", nla_get_u16(info)); + } + +- info = bss_param_info[NL80211_STA_BSS_PARAM_DTIM_PERIOD]; +- if (info) +- printf("\n\tDTIM period:\t%u", nla_get_u8(info)); +- info = bss_param_info[NL80211_STA_BSS_PARAM_BEACON_INTERVAL]; +- if (info) +- printf("\n\tbeacon interval:%u", nla_get_u16(info)); + info = bss_param_info[NL80211_STA_BSS_PARAM_CTS_PROT]; + if (info) { + printf("\n\tCTS protection:"); +@@ -622,7 +665,7 @@ static int print_sta_handler(struct nl_m + !strcmp((char *)arg, "-v")) + parse_tid_stats(sinfo[NL80211_STA_INFO_TID_STATS]); + if (sinfo[NL80211_STA_INFO_BSS_PARAM]) +- parse_bss_param(sinfo[NL80211_STA_INFO_BSS_PARAM]); ++ parse_bss_param(sinfo[NL80211_STA_INFO_BSS_PARAM], tb); + if (sinfo[NL80211_STA_INFO_CONNECTED_TIME]) + printf("\n\tconnected time:\t%u seconds", + nla_get_u32(sinfo[NL80211_STA_INFO_CONNECTED_TIME])); diff --git a/feeds/ipq95xx/iw/patches/612-iw-default-q-map-support.patch b/feeds/ipq95xx/iw/patches/612-iw-default-q-map-support.patch new file mode 100644 index 000000000..bdf88e3c7 --- /dev/null +++ b/feeds/ipq95xx/iw/patches/612-iw-default-q-map-support.patch @@ -0,0 +1,210 @@ +From 5ea22f07b7cac4ac9776151476fa8906ce7b10a8 Mon Sep 17 00:00:00 2001 +From: Ganesh Babu Jothiram +Date: Mon, 3 Apr 2023 02:12:30 +0530 +Subject: [PATCH] iw: add support for default msduq map + +Below is the command for default msduq map. + - iw dev defqmap map + +Below is the command for default msduq unmap and reports. + - iw dev defqmap unmap + +Below is the command for default msduq map reports. + - iw dev defqmap report o + +The above commands will map/unmap the specificed service class ID to use +default MSDUQ of TID. +The TID value is obtaied from the service class parameter. + +Signed-off-by: Ganesh Babu Jothiram +--- + defqmap.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + iw.h | 13 +++++ + 2 files changed, 167 insertions(+) + create mode 100644 defqmap.c + +diff --git a/defqmap.c b/defqmap.c +new file mode 100644 +index 0000000..d8964b3 +--- /dev/null ++++ b/defqmap.c +@@ -0,0 +1,145 @@ ++/* ++ * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. ++ ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "nl80211.h" ++#include "iw.h" ++#define MAC_ADDR_LEN 18 ++#define SAWF_SVC_ID_INVALID 0xFF ++#define MAX_RANGE(type) (pow(2, 8 * sizeof(type)) - 1) ++#define OUI_QCA 0x001374 ++ ++SECTION(defqmap); ++ ++static int handle_default_q_map_req(struct nl80211_state *state, ++ struct nl_msg *msg, int argc, char **argv, ++ enum id_input id) ++{ ++ struct nlattr *defqmap_attr; ++ char *end; ++ unsigned long value; ++ char macaddr[MAC_ADDR_LEN] = {0}; ++ ++ if (argc < 2 || argc > 2 || (argc%2) != 0) ++ goto err; ++ ++ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA); ++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, ++ QCA_NL80211_VENDOR_SUBCMD_SAWF_DEF_Q_MAP); ++ ++ defqmap_attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA); ++ if (!defqmap_attr) ++ return -ENOBUFS; ++ ++ errno = 0; ++ value = strtoul(argv[0], &end, 10); ++ if (*end != '\0' || value > MAX_RANGE(uint8_t) || errno == ERANGE) ++ goto err; ++ ++ strlcpy(macaddr, argv[1], MAC_ADDR_LEN); ++ ++ nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_SVC_ID, value); ++ nla_put(msg, QCA_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_MAC_ADDR, MAC_ADDR_LEN, macaddr); ++ ++ nla_nest_end(msg, defqmap_attr); ++ return 0; ++err: ++ return -EINVAL; ++} ++ ++COMMAND(defqmap, map, " ", NL80211_CMD_VENDOR, 0, CIB_NETDEV, handle_default_q_map_req, "."); ++ ++static int handle_default_q_unmap_req(struct nl80211_state *state, ++ struct nl_msg *msg, int argc, char **argv, ++ enum id_input id) ++{ ++ struct nlattr *defqmap_attr; ++ char *end; ++ unsigned long value; ++ char macaddr[MAC_ADDR_LEN] = {0}; ++ ++ if (argc < 2 || argc > 2 || (argc%2) != 0) ++ goto err; ++ ++ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA); ++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, ++ QCA_NL80211_VENDOR_SUBCMD_SAWF_DEF_Q_UNMAP); ++ ++ defqmap_attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA); ++ if (!defqmap_attr) ++ return -ENOBUFS; ++ ++ errno = 0; ++ value = strtoul(argv[0], &end, 10); ++ if (*end != '\0' || value > MAX_RANGE(uint8_t) || errno == ERANGE) ++ goto err; ++ ++ strlcpy(macaddr, argv[1], MAC_ADDR_LEN); ++ ++ nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_SVC_ID, value); ++ nla_put(msg, QCA_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_MAC_ADDR, MAC_ADDR_LEN, macaddr); ++ ++ nla_nest_end(msg, defqmap_attr); ++ return 0; ++err: ++ return -EINVAL; ++} ++ ++COMMAND(defqmap, unmap, " ", NL80211_CMD_VENDOR, 0, CIB_NETDEV, handle_default_q_unmap_req, "."); ++ ++ ++static int handle_default_q_map_report(struct nl80211_state *state, ++ struct nl_msg *msg, int argc, char **argv, ++ enum id_input id) ++{ ++ struct nlattr *defqmap_attr; ++ char macaddr[MAC_ADDR_LEN] = {0}; ++ ++ if (argc < 1 || argc > 1) ++ goto err; ++ ++ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA); ++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, ++ QCA_NL80211_VENDOR_SUBCMD_SAWF_DEF_Q_MAP_REP); ++ ++ defqmap_attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA); ++ if (!defqmap_attr) ++ return -ENOBUFS; ++ ++ errno = 0; ++ strlcpy(macaddr, argv[0], MAC_ADDR_LEN); ++ ++ nla_put(msg, QCA_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_MAC_ADDR, MAC_ADDR_LEN, macaddr); ++ ++ nla_nest_end(msg, defqmap_attr); ++ return 0; ++err: ++ return -EINVAL; ++} ++ ++COMMAND(defqmap, report, "", NL80211_CMD_VENDOR, 0, CIB_NETDEV, handle_default_q_map_report, "."); +diff --git a/iw.h b/iw.h +index 494919f..1b327c3 100644 +--- a/iw.h ++++ b/iw.h +@@ -74,6 +74,9 @@ enum qca_nl80211_vendor_subcmds { + QCA_NL80211_VENDOR_SUBCMD_SVC_CREATE = 204, + QCA_NL80211_VENDOR_SUBCMD_SVC_DISABLE = 205, + QCA_NL80211_VENDOR_SUBCMD_SVC_VIEW = 206, ++ QCA_NL80211_VENDOR_SUBCMD_SAWF_DEF_Q_MAP = 207, ++ QCA_NL80211_VENDOR_SUBCMD_SAWF_DEF_Q_UNMAP = 208, ++ QCA_NL80211_VENDOR_SUBCMD_SAWF_DEF_Q_MAP_REP = 209 + }; + /* Attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION and +@@ -88,6 +91,16 @@ enum qca_wlan_vendor_attr_config { + QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST - 1, + }; + ++enum ath12k_vendor_attr_sawf_def_q_map { ++ QCA_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_INVALID = 0, ++ QCA_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_SVC_ID = 1, ++ QCA_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_MAC_ADDR = 2, ++ ++ QCA_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_AFTER_LAST, ++ QCA_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_MAX = ++ QCA_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_AFTER_LAST - 1, ++}; ++ + enum qca_wlan_vendor_sawf_attr_config { + QCA_WLAN_VENDOR_ATTR_SAWF_SERVICE_CLASSES = 1, + QCA_WLAN_VENDOR_ATTR_SAWF_SVC_ID, +-- +2.17.1 + diff --git a/feeds/ipq95xx/iw/patches/613-iw-add-sawf-uplink-configuration-paramters-support.patch b/feeds/ipq95xx/iw/patches/613-iw-add-sawf-uplink-configuration-paramters-support.patch new file mode 100644 index 000000000..7c717a608 --- /dev/null +++ b/feeds/ipq95xx/iw/patches/613-iw-add-sawf-uplink-configuration-paramters-support.patch @@ -0,0 +1,184 @@ +From d5b3cb26d97cca6bbd816087aa292d5ed46b6b7f Mon Sep 17 00:00:00 2001 +From: Ganesh Babu Jothiram +Date: Mon, 3 Apr 2023 16:33:24 +0530 +Subject: [PATCH] iw: sawf: add uplink configuration parameters in the service + class + +configuration structure. + +add uplink configuration related parameters into service class structure and +update service class configure, and view to extend support for uplink configuration. + +Below is the command to configure a service class + - iw phy service_class create + [min_tput ] [max_tput ] + [burst_size ] [service_interval ] + [delay_bound ] [msdu_ttl ] [priority ] + [tid ] [msdu_loss ] [ul_service_interval ] + [ul_min_tput ] [ul_max_latency ] + [ul_burst_size ] [ul_ofdma_disable ] + [ul_mu_mimo_disable ] + +Below is the command to disable a service class + - iw phy service_class delete + +Below is the command to view a specific service class + - iw phy service_class view + +Below is the command to view all service classes + - iw phy service_class view + +Signed-off-by: Ganesh Babu Jothiram +--- + iw.h | 6 +++++ + sawf.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---- + 2 files changed, 74 insertions(+), 4 deletions(-) + +diff --git a/iw.h b/iw.h +index 1b327c3..64769d7 100644 +--- a/iw.h ++++ b/iw.h +@@ -114,6 +114,12 @@ enum qca_wlan_vendor_sawf_attr_config { + QCA_WLAN_VENDOR_ATTR_SAWF_SVC_PRIO, + QCA_WLAN_VENDOR_ATTR_SAWF_SVC_TID, + QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_RATE_LOSS, ++ QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_SVC_INTERVAL, ++ QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MIN_TPUT, ++ QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MAX_LATENCY, ++ QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_BURST_SIZE, ++ QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_OFDMA_DISABLE, ++ QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MU_MIMO_DISABLE, + + /* keep last */ + QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_AFTER_LAST, +diff --git a/sawf.c b/sawf.c +index da88e52..2fe2be0 100644 +--- a/sawf.c ++++ b/sawf.c +@@ -31,11 +31,11 @@ + #include "iw.h" + + #define OUI_QCA 0x001374 +-#define MAX_OPTIONAL_STRINGS 9 ++#define MAX_OPTIONAL_STRINGS 15 + #define MAX_STRING_SIZE 60 + #define MAX_RANGE(type) pow(2, 8 * sizeof(type)) - 1 + #define SVC_CREATE_MIN_ARGUMENTS 2 +-#define SVC_CREATE_MAX_ARGUMENTS 20 ++#define SVC_CREATE_MAX_ARGUMENTS 32 + #define SVC_DISABLE_MAX_ARGUMENTS 1 + #define SVC_VIEW_MAX_ARGUMENTS 1 + #define APP_NAME_MAX_BYTES 64 +@@ -63,7 +63,13 @@ static int handle_service_class_create(struct nl80211_state *state, + "msdu_ttl", + "priority", + "tid", +- "msdu_loss"}; ++ "msdu_loss", ++ "ul_service_interval", ++ "ul_min_tput", ++ "ul_max_latency", ++ "ul_burst_size", ++ "ul_ofdma_disable", ++ "ul_mu_mimo_disable"}; + + if (argc < SVC_CREATE_MIN_ARGUMENTS || argc > SVC_CREATE_MAX_ARGUMENTS || + (argc % SVC_CREATE_MIN_ARGUMENTS) != 0) +@@ -133,6 +139,30 @@ static int handle_service_class_create(struct nl80211_state *state, + nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_RATE_LOSS, + value); + break; ++ case QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_SVC_INTERVAL: ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_SVC_INTERVAL, ++ value); ++ break; ++ case QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MIN_TPUT: ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MIN_TPUT, ++ value); ++ break; ++ case QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MAX_LATENCY: ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MAX_LATENCY, ++ value); ++ break; ++ case QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_BURST_SIZE: ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_BURST_SIZE, ++ value); ++ break; ++ case QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_OFDMA_DISABLE: ++ nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_OFDMA_DISABLE, ++ value); ++ break; ++ case QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MU_MIMO_DISABLE: ++ nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MU_MIMO_DISABLE, ++ value); ++ break; + } + } + +@@ -145,6 +175,12 @@ err: + printf("[burst_size ] [service_interval ] "); + printf("[delay_bound ] [msdu_ttl ] "); + printf("[priority ] [tid ] [msdu_loss ]\n"); ++ printf("[ul_service_interval ]\n"); ++ printf("[ul_min_tput ]\n"); ++ printf("[ul_max_latency ]\n"); ++ printf("[ul_burst_size ]\n"); ++ printf("[ul_ofdma_disable ]\n"); ++ printf("[ul_mu_mimo_disable ]\n"); + + return -EINVAL; + } +@@ -153,7 +189,11 @@ COMMAND(service_class, create, " [min_tput ] [burst_size ]" + " [service_interval ] [delay_bound ]" + " [msdu_ttl ] [priority ] [tid ]" +- " [msdu_loss ]", NL80211_CMD_VENDOR, 0, CIB_PHY, ++ " [msdu_loss ] [ul_service_interval ]" ++ " [ul_min_tput ] [ul_max_latency ]" ++ " [ul_burst_size ] [ul_ofdma_disable ]" ++ " [ul_mu_mimo_disable ]", NL80211_CMD_VENDOR, 0, CIB_PHY, ++ + handle_service_class_create, "."); + + static int handle_service_class_disable(struct nl80211_state *state, +@@ -215,6 +255,12 @@ static int print_sawf_service_classes(struct nl_msg *msg, void *arg) + [QCA_WLAN_VENDOR_ATTR_SAWF_SVC_PRIO] = {.type = NLA_U32}, + [QCA_WLAN_VENDOR_ATTR_SAWF_SVC_TID] = {.type = NLA_U32}, + [QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_RATE_LOSS] = {.type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_SVC_INTERVAL] = {.type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MIN_TPUT] = {.type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MAX_LATENCY] = {.type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_BURST_SIZE] = {.type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_OFDMA_DISABLE] = {.type = NLA_U8}, ++ [QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MU_MIMO_DISABLE] = {.type = NLA_U8}, + }; + + nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), +@@ -271,6 +317,24 @@ static int print_sawf_service_classes(struct nl_msg *msg, void *arg) + if (attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_RATE_LOSS]) + printf("MSDU Loss Rate\t: %u\n", + nla_get_u32(attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_RATE_LOSS])); ++ if (attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_SVC_INTERVAL]) ++ printf("UL service interval\t: %u\n", ++ nla_get_u32(attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_SVC_INTERVAL])); ++ if (attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MIN_TPUT]) ++ printf("UL min throughput\t: %u\n", ++ nla_get_u32(attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MIN_TPUT])); ++ if (attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MAX_LATENCY]) ++ printf("UL max latency\t: %u\n", ++ nla_get_u32(attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MAX_LATENCY])); ++ if (attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_BURST_SIZE]) ++ printf("UL burst size\t: %u\n", ++ nla_get_u32(attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_BURST_SIZE])); ++ if (attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_OFDMA_DISABLE]) ++ printf("UL ofdma disable\t: %u\n", ++ nla_get_u8(attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_OFDMA_DISABLE])); ++ if (attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MU_MIMO_DISABLE]) ++ printf("UL mu mimo disable\t: %u\n", ++ nla_get_u8(attrs[QCA_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MU_MIMO_DISABLE])); + } + return NL_SKIP; + } +-- +2.17.1 + diff --git a/feeds/ipq95xx/iw/patches/614-iw-add-support-to-configure-telemetry.patch b/feeds/ipq95xx/iw/patches/614-iw-add-support-to-configure-telemetry.patch new file mode 100644 index 000000000..1ed5fec49 --- /dev/null +++ b/feeds/ipq95xx/iw/patches/614-iw-add-support-to-configure-telemetry.patch @@ -0,0 +1,428 @@ +From 6dd3cb94e051d1ebe923ff854aa666dea719a30f Mon Sep 17 00:00:00 2001 +From: Mahendran P +Date: Mon, 29 May 2023 10:34:24 +0530 +Subject: [PATCH] iw: add support to configure telemetry + +Add sla samples configuration, sla thershold configuration and sla detection configuration +Below is the command to configure sla samples configuration + - iw phy telemetry sla_samples_cfg + +Below is the command to configure sla thershold + - iw phy telemetry sla_thershold + +Below is the command to configure sla detection + - iw phy telemetry sla_detection_cfg + +Signed-off-by: Mahendran P +--- + iw.h | 52 +++++++++- + telemetry.c | 272 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 323 insertions(+), 1 deletion(-) + create mode 100644 telemetry.c + +--- a/iw.h ++++ b/iw.h +@@ -76,7 +76,11 @@ enum qca_nl80211_vendor_subcmds { + QCA_NL80211_VENDOR_SUBCMD_SVC_VIEW = 206, + QCA_NL80211_VENDOR_SUBCMD_SAWF_DEF_Q_MAP = 207, + QCA_NL80211_VENDOR_SUBCMD_SAWF_DEF_Q_UNMAP = 208, +- QCA_NL80211_VENDOR_SUBCMD_SAWF_DEF_Q_MAP_REP = 209 ++ QCA_NL80211_VENDOR_SUBCMD_SAWF_DEF_Q_MAP_REP = 209, ++ QCA_NL80211_VENDOR_SUBCMD_TELEMETRY_SLA_THERSHOLD_CFG = 210, ++ QCA_NL80211_VENDOR_SUBCMD_TELEMETRY_SLA_SAMPLES_COLLECTION_CFG = 211, ++ QCA_NL80211_VENDOR_SUBCMD_TELEMETRY_SLA_BREACH_DETECTION_CFG = 212 ++ QCA_NL80211_VENDOR_SUBCMD_SAWF_SLA_BREACH = 214, + }; + /* Attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION and +@@ -127,6 +131,82 @@ enum qca_wlan_vendor_sawf_attr_config { + QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_AFTER_LAST - 1, + }; + ++enum qca_wlan_vendor_attr_telemetry_sawf_sla_samples_config { ++ QCA_WLAN_VENDOR_ATTR_TELEMETRY_MOVING_AVG_PKT = 1, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRY_MOVING_AVG_WIN, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_NUM_PKT, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_TIME_SEC, ++ ++ /* keep last */ ++ QCA_WLAN_VENDOR_TELEMETRY_SLA_SAMPLES_CFG_ATTR_AFTER_LAST, ++ QCA_WLAN_VENDOR_TELEMETRY_SLA_SAMPLES_CFG_ATTR_CONFIG_MAX = ++ QCA_WLAN_VENDOR_TELEMETRY_SLA_SAMPLES_CFG_ATTR_AFTER_LAST - 1, ++}; ++ ++enum qca_wlan_vendor_attr_telemetry_sawf_sla_detect_config { ++ QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECTION_PARAM = 1, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_MIN_TP, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_MAX_TP, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_BURST_SIZE, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_INTERVAL, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_DELAY_BOUND, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_MSDU_TTL, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_MSDU_RATE_LOSS, ++ ++ /* keep last */ ++ QCA_WLAN_VENDOR_TELEMETRY_SLA_DETECT_AFTER_LAST, ++ QCA_WLAN_VENDOR_TELEMETRY_SLA_DETECT_ATTR_CONFIG_MAX = ++ QCA_WLAN_VENDOR_TELEMETRY_SLA_DETECT_AFTER_LAST - 1, ++ ++}; ++ ++enum qca_wlan_vendor_attr_telemetry_sawf_sla_thershold_config { ++ QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_SVC_ID = 1, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_MIN_TP, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_MAX_TP, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_BURST_SIZE, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_INTERVAL, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_DELAY_BOUND, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_MSDU_TTL, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_MSDU_RATE_LOSS, ++ ++ /* keep last */ ++ QCA_WLAN_VENDOR_TELEMETRY_SLA_THERSHOLD_CFG_AFTER_LAST, ++ QCA_WLAN_VENDOR_TELEMETRY_SLA_THERSHOLD_CFG_ATTR_CONFIG_MAX = ++ QCA_WLAN_VENDOR_TELEMETRY_SLA_THERSHOLD_CFG_AFTER_LAST - 1, ++}; ++ ++/** ++ * enum qca_wlan_vendor_attr_sawf_sla_params - This enum defines ++ * attributes required for QCA_NL80211_VENDOR_SUBCMD_SAWF_SLA_BREACH ++ * Used to send sla clear event to driver. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_SLA_PEER_MAC: Unsigned 8-bit array ++ * of size 6, representing peer mac address. ++ * @QCA_WLAN_VENDOR_ATTR_SLA_SVC_ID: Unsigned 8-bit representing service ID ++ * @QCA_WLAN_VENDOR_ATTR_SLA_PARAM: Unsigned 8-bit indicaing service class ++ * from qca_vendor_attr_sla_param_type ++ * @QCA_WLAN_VENDOR_ATTR_SLA_PEER_MLD_MAC: Unsigned 8-bit array ++ * of size 6, representing peer mld mac address. Filled only for ML capable ++ * peers ++ * @QCA_WLAN_VENDOR_ATTR_SLA_AC: Unsigned 8-bit representing AC for breach ++ * ++ */ ++enum qca_wlan_vendor_attr_sawf_sla_params { ++ QCA_WLAN_VENDOR_ATTR_SLA_INVALID = 0, ++ QCA_WLAN_VENDOR_ATTR_SLA_PEER_MAC = 1, ++ QCA_WLAN_VENDOR_ATTR_SLA_SVC_ID = 2, ++ QCA_WLAN_VENDOR_ATTR_SLA_PARAM = 3, ++ QCA_WLAN_VENDOR_ATTR_SLA_SET_CLEAR = 4, ++ QCA_WLAN_VENDOR_ATTR_SLA_PEER_MLD_MAC = 5, ++ QCA_WLAN_VENDOR_ATTR_SLA_AC = 6, ++ ++ /* Keep last */ ++ QCA_WLAN_VENDOR_ATTR_SLA_AFTER_LAST, ++ QCA_WLAN_VENDOR_ATTR_SLA_MAX = ++ QCA_WLAN_VENDOR_ATTR_SLA_AFTER_LAST - 1 ++}; ++ + #define HANDLER_RET_USAGE 1 + #define HANDLER_RET_DONE 3 + +--- /dev/null ++++ b/telemetry.c +@@ -0,0 +1,305 @@ ++/* ++ * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. ++ ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "nl80211.h" ++#include "iw.h" ++ ++#define OUI_QCA 0x001374 ++#define MAX_OPTIONAL_STRINGS 15 ++#define MAX_STRING_SIZE 60 ++#define MAX_RANGE(type) pow(2, 8 * sizeof(type)) - 1 ++#define SVC_CREATE_MIN_ARGUMENTS 2 ++#define SVC_CREATE_MAX_ARGUMENTS 32 ++#define SVC_DISABLE_MAX_ARGUMENTS 1 ++#define SVC_VIEW_MAX_ARGUMENTS 1 ++#define APP_NAME_MAX_BYTES 64 ++#define streq(a, b) (strcmp((a), (b)) == 0) ++ ++#define TELEMETRY_SLA_SAMPLES_CONFIG_NUM_OF_PARAMS 4 ++#define TELEMETRY_SLA_THERSHOLD_CONFIG_NUM_OF_PARAMS 8 ++#define TELEMETRY_SLA_DETECTION_CONFIG_NUM_OF_PARAMS 8 ++ ++struct telemetry_sawf_generic_param { ++ uint32_t moving_avg_pkt; ++ uint32_t moving_avg_win; ++ uint32_t sla_num_pkt; ++ uint32_t sla_time_sec; ++}; ++ ++struct telemetry_sawf_sla_thershold { ++ uint8_t svc_id; ++ uint32_t min_throughput_rate; ++ uint32_t max_throughput_rate; ++ uint32_t burst_size; ++ uint32_t service_interval; ++ uint32_t delay_bound; ++ uint32_t msdu_ttl; ++ uint32_t msdu_rate_loss; ++}; ++ ++enum telemetry_sawf_sla_detect { ++ SLA_DETECT_NUM_PACKET, ++ SLA_DETECT_PER_SECOND, ++ SLA_DETECT_MOV_AVG, ++ SLA_DETECT_NUM_SECOND, ++ SLA_DETECT_MAX, ++}; ++ ++struct telemetry_sawf_sla_detect_param { ++ enum telemetry_sawf_sla_detect sla_detect; ++ uint32_t min_throughput_rate; ++ uint32_t max_throughput_rate; ++ uint32_t burst_size; ++ uint32_t service_interval; ++ uint32_t delay_bound; ++ uint32_t msdu_ttl; ++ uint32_t msdu_rate_loss; ++}; ++ ++ ++SECTION(telemetry); ++ ++static int handle_telemetry_sawf_sla_samples_colletion_cfg ++ (struct nl80211_state *state, struct nl_msg *msg, ++ int argc, char **argv, enum id_input id) ++{ ++ struct nlattr *telemetry_cfg; ++ char *end; ++ struct telemetry_sawf_generic_param telemetry_param; ++ ++ if (argc != TELEMETRY_SLA_SAMPLES_CONFIG_NUM_OF_PARAMS) ++ goto err; ++ ++ telemetry_param.moving_avg_pkt = strtoul(argv[0], &end, 10); ++ telemetry_param.moving_avg_win = strtoul(argv[1], &end, 10); ++ telemetry_param.sla_num_pkt = strtoul(argv[2], &end, 10); ++ telemetry_param.sla_time_sec = strtoul(argv[3], &end, 10); ++ ++ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA); ++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, ++ QCA_NL80211_VENDOR_SUBCMD_TELEMETRY_SLA_SAMPLES_COLLECTION_CFG); ++ ++ telemetry_cfg = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA); ++ if (!telemetry_cfg) ++ return -ENOBUFS; ++ ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TELEMETRY_MOVING_AVG_PKT, ++ telemetry_param.moving_avg_pkt); ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TELEMETRY_MOVING_AVG_WIN, ++ telemetry_param.moving_avg_win); ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_NUM_PKT, ++ telemetry_param.sla_num_pkt); ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_TIME_SEC, ++ telemetry_param.sla_time_sec); ++ ++ nla_nest_end(msg, telemetry_cfg); ++ ++ return 0; ++ ++err: ++ printf("invalid telemetry sla samples configuration command format: Usage\n"); ++ printf("\t iw phy telemetry sla_samples_cfg \n"); ++ return -EINVAL; ++} ++ ++COMMAND(telemetry, sla_samples_cfg, " " ++" ", NL80211_CMD_VENDOR, 0, CIB_PHY, ++handle_telemetry_sawf_sla_samples_colletion_cfg, "."); ++ ++static int handle_telemetry_sawf_sla_thershold_cfg(struct nl80211_state *state, ++ struct nl_msg *msg, int argc, char **argv, ++ enum id_input id) ++{ ++ struct nlattr *telemetry_cfg; ++ char *end; ++ struct telemetry_sawf_sla_thershold sla_thershold_cfg; ++ ++ if (argc != TELEMETRY_SLA_THERSHOLD_CONFIG_NUM_OF_PARAMS) ++ goto err; ++ ++ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA); ++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, ++ QCA_NL80211_VENDOR_SUBCMD_TELEMETRY_SLA_THERSHOLD_CFG); ++ ++ telemetry_cfg = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA); ++ if (!telemetry_cfg) ++ return -ENOBUFS; ++ ++ sla_thershold_cfg.svc_id = strtoul(argv[0], &end, 10); ++ sla_thershold_cfg.min_throughput_rate = strtoul(argv[1], &end, 10); ++ sla_thershold_cfg.max_throughput_rate = strtoul(argv[2], &end, 10); ++ sla_thershold_cfg.burst_size = strtoul(argv[3], &end, 10); ++ sla_thershold_cfg.service_interval = strtoul(argv[4], &end, 10); ++ sla_thershold_cfg.delay_bound = strtoul(argv[5], &end, 10); ++ sla_thershold_cfg.msdu_ttl = strtoul(argv[6], &end, 10); ++ sla_thershold_cfg.msdu_rate_loss = strtoul(argv[7], &end, 10); ++ ++ ++ nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_SVC_ID, ++ sla_thershold_cfg.svc_id); ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_MIN_TP, ++ sla_thershold_cfg.min_throughput_rate); ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_MAX_TP, ++ sla_thershold_cfg.max_throughput_rate); ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_BURST_SIZE, ++ sla_thershold_cfg.burst_size); ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_INTERVAL, ++ sla_thershold_cfg.service_interval); ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_DELAY_BOUND, ++ sla_thershold_cfg.delay_bound); ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_MSDU_TTL, ++ sla_thershold_cfg.msdu_ttl); ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_MSDU_RATE_LOSS, ++ sla_thershold_cfg.msdu_rate_loss); ++ nla_nest_end(msg, telemetry_cfg); ++ return 0; ++ ++err: ++ printf("invalid telemetry sla thershold configuration command format: Usage\n"); ++ printf("\t iw phy telemetry sla_thershold "); ++ printf(" "); ++ printf(" \n"); ++ return -EINVAL; ++} ++ ++COMMAND(telemetry, sla_thershold, " " ++" ", NL80211_CMD_VENDOR, 0, ++CIB_PHY, handle_telemetry_sawf_sla_thershold_cfg, "."); ++ ++ ++static int handle_telemetry_sawf_sla_detection_cfg(struct nl80211_state *state, ++ struct nl_msg *msg, int argc, char **argv, ++ enum id_input id) ++{ ++ struct nlattr *telemetry_cfg; ++ char *end; ++ struct telemetry_sawf_sla_detect_param telemetry_param; ++ ++ if (argc != TELEMETRY_SLA_DETECTION_CONFIG_NUM_OF_PARAMS) ++ goto err; ++ ++ if (streq(argv[0], "num_packet")) ++ telemetry_param.sla_detect = SLA_DETECT_NUM_PACKET; ++ ++ if (streq(argv[0], "per_second")) ++ telemetry_param.sla_detect = SLA_DETECT_PER_SECOND; ++ ++ if (streq(argv[0], "moving_avg")) ++ telemetry_param.sla_detect = SLA_DETECT_MOV_AVG; ++ ++ if (streq(argv[0], "num_second")) ++ telemetry_param.sla_detect = SLA_DETECT_NUM_SECOND; ++ ++ telemetry_param.min_throughput_rate = strtoul(argv[1], &end, 10); ++ telemetry_param.max_throughput_rate = strtoul(argv[2], &end, 10); ++ telemetry_param.burst_size = strtoul(argv[3], &end, 10); ++ telemetry_param.service_interval = strtoul(argv[4], &end, 10); ++ telemetry_param.delay_bound = strtoul(argv[5], &end, 10); ++ telemetry_param.msdu_ttl = strtoul(argv[6], &end, 10); ++ telemetry_param.msdu_rate_loss = strtoul(argv[7], &end, 10); ++ ++ ++ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA); ++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, ++ QCA_NL80211_VENDOR_SUBCMD_TELEMETRY_SLA_BREACH_DETECTION_CFG); ++ ++ telemetry_cfg = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA); ++ if (!telemetry_cfg) ++ return -ENOBUFS; ++ ++ nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECTION_PARAM, ++ telemetry_param.sla_detect); ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_MIN_TP, ++ telemetry_param.min_throughput_rate); ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_MAX_TP, ++ telemetry_param.max_throughput_rate); ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_BURST_SIZE, ++ telemetry_param.burst_size); ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_INTERVAL, ++ telemetry_param.service_interval); ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_DELAY_BOUND, ++ telemetry_param.delay_bound); ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_MSDU_TTL, ++ telemetry_param.msdu_ttl); ++ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_MSDU_RATE_LOSS, ++ telemetry_param.msdu_rate_loss); ++ nla_nest_end(msg, telemetry_cfg); ++ ++ return 0; ++ ++err: ++ printf("invalid telemetry sla breach detection configuration command format: Usage\n"); ++ printf("\t iw phy telemetry sla_detection_cfg \n"); ++ return -EINVAL; ++} ++ ++COMMAND(telemetry, sla_detection_cfg, " " ++" " ++"", NL80211_CMD_VENDOR, 0, CIB_PHY, ++handle_telemetry_sawf_sla_detection_cfg, "."); ++ ++#define TELEMETRY_SLA_CLEAR_STATS_MAX_ARG 1 ++#define MAC_ADDR_LEN 18 ++ ++static int handle_telemetry_sla_clear_stats(struct nl80211_state *state, ++ struct nl_msg *msg, int argc, char **argv, ++ enum id_input id) ++{ ++ struct nlattr *sla_clear; ++ unsigned char mac_addr[MAC_ADDR_LEN]; ++ ++ if (argc != TELEMETRY_SLA_CLEAR_STATS_MAX_ARG) ++ goto err; ++ ++ if (mac_addr_a2n(mac_addr, argv[0])) { ++ printf("Invalid MAC address\n"); ++ return -EINVAL; ++ } ++ ++ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA); ++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, ++ QCA_NL80211_VENDOR_SUBCMD_SAWF_SLA_BREACH); ++ ++ sla_clear = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA); ++ if (!sla_clear) ++ return -ENOBUFS; ++ ++ if (nla_put(msg, QCA_WLAN_VENDOR_ATTR_SLA_PEER_MAC, ++ ETH_ALEN, mac_addr)) ++ return -ENOBUFS; ++ ++ nla_nest_end(msg, sla_clear); ++ return NL_OK; ++err: ++ printf("Invalid telemetry sla clear stats, command format: Usage\n"); ++ printf("\t iw dev telemetry sla_clear_stats \n"); ++ return NL_STOP; ++} ++COMMAND(telemetry, sla_clear_stats, "", NL80211_CMD_VENDOR, 0, CIB_NETDEV, ++ handle_telemetry_sla_clear_stats, "."); diff --git a/feeds/ipq95xx/iw/patches/615-01-iw-Add-support-to-handle-streaming-stats-in-target.patch b/feeds/ipq95xx/iw/patches/615-01-iw-Add-support-to-handle-streaming-stats-in-target.patch new file mode 100644 index 000000000..6433e06ea --- /dev/null +++ b/feeds/ipq95xx/iw/patches/615-01-iw-Add-support-to-handle-streaming-stats-in-target.patch @@ -0,0 +1,147 @@ +From 741fa523d6dd195195a9b7514a9583699f43ba3a Mon Sep 17 00:00:00 2001 +From: Nagarajan Maran +Date: Wed, 7 Jun 2023 12:26:25 +0530 +Subject: [PATCH] iw: Add support to handle streaming stats in target. + +Signed-off-by: Nagarajan Maran +--- + iw.h | 13 +++++++- + sawf_stats.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 99 insertions(+), 1 deletion(-) + create mode 100644 sawf_stats.c + +--- a/iw.h ++++ b/iw.h +@@ -79,7 +79,8 @@ enum qca_nl80211_vendor_subcmds { + QCA_NL80211_VENDOR_SUBCMD_SAWF_DEF_Q_MAP_REP = 209, + QCA_NL80211_VENDOR_SUBCMD_TELEMETRY_SLA_THERSHOLD_CFG = 210, + QCA_NL80211_VENDOR_SUBCMD_TELEMETRY_SLA_SAMPLES_COLLECTION_CFG = 211, +- QCA_NL80211_VENDOR_SUBCMD_TELEMETRY_SLA_BREACH_DETECTION_CFG = 212 ++ QCA_NL80211_VENDOR_SUBCMD_TELEMETRY_SLA_BREACH_DETECTION_CFG = 212, ++ QCA_NL80211_VENDOR_SUBCMD_SAWF_STREAMING_STATS = 213, + QCA_NL80211_VENDOR_SUBCMD_SAWF_SLA_BREACH = 214, + }; + /* Attributes for data used by +@@ -95,6 +96,17 @@ enum qca_wlan_vendor_attr_config { + QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST - 1, + }; + ++enum ath12k_vendor_attr_sawf_streaming { ++ QCA_WLAN_VENDOR_ATTR_SAWF_STREAMING_INVALID = 0, ++ QCA_WLAN_VENDOR_ATTR_SAWF_STREAMING_BASIC_STATS = 1, ++ QCA_WLAN_VENDOR_ATTR_SAWF_STREAMING_EXTND_STATS = 2, ++ QCA_WLAN_VENDOR_ATTR_MLO_LINK_ID = 3, ++ /* keep last */ ++ QCA_WLAN_VENDOR_ATTR_SAWF_STREAMING_AFTER_LAST, ++ QCA_WLAN_VENDOR_ATTR_SAWF_STREAMING_MAX = ++ QCA_WLAN_VENDOR_ATTR_SAWF_STREAMING_AFTER_LAST - 1, ++}; ++ + enum ath12k_vendor_attr_sawf_def_q_map { + QCA_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_SVC_ID = 1, +--- /dev/null ++++ b/sawf_stats.c +@@ -0,0 +1,102 @@ ++/* ++ * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. ++ ++ * 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. ++ */ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "nl80211.h" ++#include "iw.h" ++ ++#define OUI_QCA 0x001374 ++#define STREAMING_STATS_MIN_ARGUMENTS 1 ++#define STREAMING_STATS_MAX_ARGUMENTS 3 ++#define STREAMING_STATS_MAX_VALUE 3 ++#define STREAMING_STATS_BASIC_EN_EXTND_DIS 1 ++#define STREAMING_STATS_BASIC_DIS_EXTND_EN 2 ++ ++ ++SECTION(streaming_stats); ++ ++static int handle_streaming_stats(struct nl80211_state *state, ++ struct nl_msg *msg, int argc, char **argv, ++ enum id_input id) ++{ ++ struct nlattr *stats; ++ unsigned long value; ++ uint8_t basic_stats = 0, extnd_stats = 0, link_id; ++ char *end; ++ ++ if (argc < STREAMING_STATS_MIN_ARGUMENTS || ++ argc > STREAMING_STATS_MAX_ARGUMENTS) ++ goto err; ++ ++ errno = 0; ++ value = strtoul(argv[0], &end, 10); ++ if (*end != '\0' || value > STREAMING_STATS_MAX_VALUE || errno == ERANGE) ++ goto err; ++ argc--; ++ ++ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA); ++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, ++ QCA_NL80211_VENDOR_SUBCMD_SAWF_STREAMING_STATS); ++ ++ stats = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA); ++ if (!stats) ++ return -ENOBUFS; ++ ++ if (value & STREAMING_STATS_BASIC_EN_EXTND_DIS) ++ basic_stats = 1; ++ if (value & STREAMING_STATS_BASIC_DIS_EXTND_EN) ++ extnd_stats = 1; ++ ++ nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_SAWF_STREAMING_BASIC_STATS, basic_stats); ++ nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_SAWF_STREAMING_EXTND_STATS, extnd_stats); ++ ++ if (argc) { ++ argc--; ++ if (!strcmp(argv[1], "-l") || !argc) ++ goto err; ++ errno = 0; ++ link_id = strtoul(argv[2], &end, 10); ++ if (*end != '\0' || value > MAX_MLD_LINK || errno == ERANGE) { ++ goto err; ++ } ++ nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_MLO_LINK_ID, link_id); ++ } ++ ++ nla_nest_end(msg, stats); ++ return 0; ++ ++err: ++ printf("Invalid SAWF streaming stats command format: Usage\n"); ++ printf("iw dev streaming_stats configure [-l ]\n"); ++ printf("\t value: 0 - Disable both Basic and Extended stats\n"); ++ printf("\t value: 1 - Enable Basic and Disable Extended stats\n"); ++ printf("\t value: 2 - Disable Basic and Enable Extended stats\n"); ++ printf("\t value: 3 - Enable both Basic and Extended stats\n"); ++ return -EINVAL; ++} ++ ++COMMAND(streaming_stats, handle, " [-l ]", NL80211_CMD_VENDOR, 0, CIB_NETDEV, handle_streaming_stats, "."); diff --git a/feeds/ipq95xx/iw/patches/615-02-iw-Add-support-to-get-SAWF-stats.patch b/feeds/ipq95xx/iw/patches/615-02-iw-Add-support-to-get-SAWF-stats.patch new file mode 100644 index 000000000..30b2ee155 --- /dev/null +++ b/feeds/ipq95xx/iw/patches/615-02-iw-Add-support-to-get-SAWF-stats.patch @@ -0,0 +1,815 @@ +From 581b7eb9fb63e21a277e71799756f6f629581ebf Mon Sep 17 00:00:00 2001 +From: Nagarajan Maran +Date: Thu, 8 Jun 2023 18:30:49 +0530 +Subject: [PATCH] iw: Add support to get SAWF stats + +Signed-off-by: Nagarajan Maran +--- + iw.h | 1 + + sawf_stats.c | 398 ++++++++++++++++++++++++++++++++++++++++++++++++++- + sawf_stats.h | 367 +++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 764 insertions(+), 2 deletions(-) + create mode 100644 sawf_stats.h + +--- a/sawf_stats.c ++++ b/sawf_stats.c +@@ -28,6 +28,7 @@ + + #include "nl80211.h" + #include "iw.h" ++#include "sawf_stats.h" + + #define OUI_QCA 0x001374 + #define STREAMING_STATS_MIN_ARGUMENTS 1 +@@ -35,7 +36,7 @@ + #define STREAMING_STATS_MAX_VALUE 3 + #define STREAMING_STATS_BASIC_EN_EXTND_DIS 1 + #define STREAMING_STATS_BASIC_DIS_EXTND_EN 2 +- ++#define MAX_RANGE(type) pow(2, 8 * sizeof(type)) - 1 + + SECTION(streaming_stats); + +@@ -100,3 +101,401 @@ err: + } + + COMMAND(streaming_stats, handle, " [-l ]", NL80211_CMD_VENDOR, 0, CIB_NETDEV, handle_streaming_stats, "."); ++ ++SECTION(sawf_stats); ++#define MAC_ADDR_LEN 18 ++#define TELEMETRY_GET_STATS_MIN_ARG 3 ++#define TELEMETRY_GET_STATS_MAX_ARG 4 ++#define SAWFDELAY_STATS 0x00400000 ++#define SAWFTX_STATS 0x00800000 ++ ++const char *stats_if_hw_tx_comp_delay_bucket[DELAY_BUCKET_MAX + 1] = { ++ "0 to 250 us", "250 to 500 us", ++ "500 to 750 us", "750 to 1000 us", ++ "1000 to 1500 us", "1500 to 2000 us", ++ "2000 to 2500 us", "2500 to 5000 us", ++ "5000 to 6000 us", "6000 to 7000 ms", ++ "7000 to 8000 us", "8000 to 9000 us", "9000+ us" ++}; ++ ++static void print_hist_stats(struct delay_hist_stats *hstats, ++ enum hist_types hist_type) ++{ ++ uint8_t index = 0; ++ uint64_t count = 0; ++ ++ for (index = 0; index < HIST_BUCKET_MAX; index++) { ++ count = hstats->hist.freq[index]; ++ if (!count) ++ continue; ++ if (index > DELAY_BUCKET_MAX) { ++ printf("%s: Packets = %" PRIu64 "\n", ++ "Invalid index", count); ++ continue; ++ } ++ switch (hist_type) { ++ case HIST_TYPE_HW_TX_COMP_DELAY: ++ printf("%s: Packets = %" PRIu64 "\n", ++ stats_if_hw_tx_comp_delay_bucket[index], ++ count); ++ break; ++ default: ++ break; ++ } ++ } ++ ++ printf("Min = %d\n", hstats->min); ++ printf("Max = %d\n", hstats->max); ++ printf("Avg = %d\n", hstats->avg); ++} ++ ++static void print_telemetry_delay_stats(struct telemetry_sawf_delay_stat *delay_stats) ++{ ++ printf("\nDelay Bins\n"); ++ ++ print_hist_stats(&delay_stats->delay_hist, ++ HIST_TYPE_HW_TX_COMP_DELAY); ++ ++ printf("NwDelay Moving average = %u\n", ++ delay_stats->nwdelay_avg); ++ printf("SwDelay Moving average = %u\n", ++ delay_stats->swdelay_avg); ++ printf("HwDelay Moving average = %u\n", ++ delay_stats->hwdelay_avg); ++ printf("Delay bound success = %" PRIu64 "\n", ++ delay_stats->delay_bound_success); ++ printf("Delay bound failure = %" PRIu64 "\n", ++ delay_stats->delay_bound_failure); ++ ++ return; ++} ++ ++static void print_telemetry_tx_stats(struct telemetry_sawf_tx_stat *tx_stats) ++{ ++ printf("Tx_info_success_num = %u\n", ++ tx_stats->tx_success.num_pkts); ++ printf("Tx_info_success_bytes = %" PRIu64 "\n", ++ tx_stats->tx_success.bytes); ++ printf("Tx_info_ingress_num = %u\n", ++ tx_stats->tx_ingress.num_pkts); ++ printf("Tx_info_ingress_bytes = %" PRIu64 "\n", ++ tx_stats->tx_ingress.bytes); ++ printf("Tx_info_Throughput = %u\n", ++ tx_stats->throughput); ++ printf("Tx_info_ingress_rate = %u\n", ++ tx_stats->ingress_rate); ++ ++ printf("Tx_info_drop_num = %u\n", ++ tx_stats->dropped.fw_rem.num_pkts); ++ printf("Tx_info_drop_bytes = %" PRIu64 "\n", ++ tx_stats->dropped.fw_rem.bytes); ++ printf("Tx_info_drop_fw_rem_notx = %u\n", ++ tx_stats->dropped.fw_rem_notx); ++ printf("Tx_info_drop_Tx_fw_rem_tx = %u\n", ++ tx_stats->dropped.fw_rem_tx); ++ printf("Tx_info_drop_Tx_age_out = %u\n", ++ tx_stats->dropped.age_out); ++ ++ printf("Tx_info_drop_fw_reason1 = %u\n", ++ tx_stats->dropped.fw_reason1); ++ printf("Tx_info_drop_fw_reason2 = %u\n", ++ tx_stats->dropped.fw_reason2); ++ printf("Tx_info_drop_fw_reason3 = %u\n", ++ tx_stats->dropped.fw_reason3); ++ printf("Tx_info_tx_failed = %u\n", ++ tx_stats->tx_failed); ++ printf("Tx_info_queue_depth = %u\n", ++ tx_stats->queue_depth); ++ printf("Service_intvl_success_cnt = %" PRIu64 "\n", ++ tx_stats->svc_intval_stats.success_cnt); ++ printf("Service_intvl_failure_cnt = %" PRIu64 "\n", ++ tx_stats->svc_intval_stats.failure_cnt); ++ printf("Burst_size_success_cnt = %" PRIu64 "\n", ++ tx_stats->burst_size_stats.success_cnt); ++ printf("Burst_size_failure_cnt = %" PRIu64 "\n", ++ tx_stats->burst_size_stats.failure_cnt); ++} ++ ++static int error_stats_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, ++ void *arg) ++{ ++ struct unified_stats *telemetry_stats = (struct unified_stats*)arg; ++ ++ telemetry_stats->err = EINVAL; ++ return NL_STOP; ++} ++ ++static void print_sawf_stats(struct unified_stats *telemetry_stats, ++ uint8_t svc_id) ++{ ++ int tid, q_id; ++ struct telemetry_sawfdelay_stats *delay_stats = telemetry_stats->feat[STATS_FEAT_SAWFDELAY]; ++ struct telemetry_sawftx_stats *tx_stats = telemetry_stats->feat[STATS_FEAT_SAWFTX]; ++ struct telemetry_sawf_tx_stat *sawftx_stats; ++ struct telemetry_sawf_delay_stat *sawfdelay_stats; ++ ++ if(tx_stats) { ++ if (!svc_id) { ++ for (tid = 0; tid < MAX_TID; tid++) { ++ for (q_id = 0; q_id < MAX_SAWF_Q; q_id++) { ++ sawftx_stats = &tx_stats->tx[tid][q_id]; ++ printf("----TIDX: %d---- ", tid); ++ printf("----QUEUE: %d----\n", q_id); ++ print_telemetry_tx_stats(sawftx_stats); ++ } ++ } ++ } else { ++ sawftx_stats = &tx_stats->tx[0][0]; ++ printf("----TIDX: %d---- ", tx_stats->tid); ++ printf("----QUEUE: %d----\n", tx_stats->msduq); ++ print_telemetry_tx_stats(sawftx_stats); ++ } ++ } ++ ++ if(delay_stats) { ++ if (!svc_id) { ++ for (tid = 0; tid < MAX_TID; tid++) { ++ for (q_id = 0; q_id < MAX_SAWF_Q; q_id++) { ++ sawfdelay_stats = &delay_stats->delay[tid][q_id]; ++ printf("----TIDX: %d---- ", tid); ++ printf("----QUEUE: %d----\n", q_id); ++ print_telemetry_delay_stats(sawfdelay_stats); ++ } ++ } ++ } else { ++ sawfdelay_stats = &delay_stats->delay[0][0]; ++ printf("----TIDX: %d---- ", delay_stats->tid); ++ printf("----QUEUE: %d----\n", delay_stats->msduq); ++ print_telemetry_delay_stats(sawfdelay_stats); ++ } ++ } ++} ++ ++static int complete_telemetry_stats(struct nl_msg *msg, void *arg) ++{ ++ struct unified_stats *telemetry_stats = (struct unified_stats*)arg; ++ ++ telemetry_stats->err = 0; ++ return NL_OK; ++} ++ ++static int print_telemetry_stats(struct nl_msg *msg, void *arg) ++{ ++ struct nlattr *tb_msg[NL80211_ATTR_MAX + 1]; ++ struct nlattr *stats[QCA_WLAN_VENDOR_ATTR_TELEMETRIC_MAX + 1]; ++ struct nlattr *feat[QCA_WLAN_VENDOR_ATTR_FEAT_MAX + 1]; ++ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); ++ static struct nla_policy stats_policy[QCA_WLAN_VENDOR_ATTR_STATS_MAX + 1] = { ++ [QCA_WLAN_VENDOR_ATTR_STATS_LEVEL] = { .type = NLA_U8 }, ++ [QCA_WLAN_VENDOR_ATTR_STATS_OBJECT] = { .type = NLA_U8 }, ++ [QCA_WLAN_VENDOR_ATTR_STATS_OBJ_ID] = { .type = NLA_UNSPEC }, ++ [QCA_WLAN_VENDOR_ATTR_STATS_PARENT_IF] = { .type = NLA_UNSPEC }, ++ [QCA_WLAN_VENDOR_ATTR_STATS_TYPE] = { .type = NLA_U8 }, ++ [QCA_WLAN_VENDOR_ATTR_STATS_RECURSIVE] = { .type = NLA_NESTED }, ++ [QCA_WLAN_VENDOR_ATTR_STATS_MULTI_REPLY] = { .type = NLA_FLAG }, ++ [QCA_WLAN_VENDOR_ATTR_STATS_SERVICEID] = { .type = NLA_U8 }, ++ }; ++ struct telemetry_sawfdelay_stats *delay_stats; ++ struct telemetry_sawftx_stats *tx_stats; ++ static int filled_buf_len_delay, filled_buf_len_tx; ++ struct unified_stats *telemetry_stats = (struct unified_stats*)arg; ++ size_t len; ++ ++ nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), ++ genlmsg_attrlen(gnlh, 0), NULL); ++ ++ if (tb_msg[NL80211_ATTR_VENDOR_DATA]) ++ nla_parse_nested(stats, QCA_WLAN_VENDOR_ATTR_STATS_MAX, ++ tb_msg[NL80211_ATTR_VENDOR_DATA], stats_policy); ++ else ++ return NL_STOP; ++ ++ if (!stats[QCA_WLAN_VENDOR_ATTR_STATS_LEVEL] || ++ !stats[QCA_WLAN_VENDOR_ATTR_STATS_OBJECT] || ++ !stats[QCA_WLAN_VENDOR_ATTR_STATS_OBJ_ID] || ++ !stats[QCA_WLAN_VENDOR_ATTR_STATS_TYPE] || ++ !stats[QCA_WLAN_VENDOR_ATTR_STATS_RECURSIVE] || ++ !stats[QCA_WLAN_VENDOR_ATTR_STATS_SERVICEID]) { ++ printf("SAWF STATS: Invalid data received\n"); ++ return NL_SKIP; ++ } ++ ++ if (stats[QCA_WLAN_VENDOR_ATTR_STATS_MULTI_REPLY]) { ++ delay_stats = telemetry_stats->feat[STATS_FEAT_SAWFDELAY]; ++ tx_stats = telemetry_stats->feat[STATS_FEAT_SAWFTX]; ++ } else { ++ filled_buf_len_delay = 0; ++ filled_buf_len_tx = 0; ++ delay_stats = NULL; ++ tx_stats = NULL; ++ } ++ ++ nla_parse_nested(feat, QCA_WLAN_VENDOR_ATTR_FEAT_MAX, ++ stats[QCA_WLAN_VENDOR_ATTR_STATS_RECURSIVE], NULL); ++ ++ if (feat[QCA_WLAN_VENDOR_ATTR_FEAT_SAWFDELAY]) { ++ if (!delay_stats) { ++ void *temp_delay; ++ temp_delay = malloc(sizeof(struct telemetry_sawfdelay_stats)); ++ if (!temp_delay) ++ return NL_STOP; ++ len = nla_len(feat[QCA_WLAN_VENDOR_ATTR_FEAT_SAWFDELAY]); ++ memcpy((uint8_t *)temp_delay, nla_data(feat[QCA_WLAN_VENDOR_ATTR_FEAT_SAWFDELAY]), ++ len); ++ delay_stats = temp_delay; ++ filled_buf_len_delay += len; ++ } else { ++ len = nla_len(feat[QCA_WLAN_VENDOR_ATTR_FEAT_SAWFDELAY]); ++ memcpy((uint8_t *)delay_stats + filled_buf_len_delay, ++ nla_data(feat[QCA_WLAN_VENDOR_ATTR_FEAT_SAWFDELAY]), ++ len); ++ filled_buf_len_delay += len; ++ } ++ telemetry_stats->feat[STATS_FEAT_SAWFDELAY] = delay_stats; ++ } ++ ++ if (feat[QCA_WLAN_VENDOR_ATTR_FEAT_SAWFTX]) { ++ if (!tx_stats) { ++ void *temp_tx; ++ temp_tx = malloc(sizeof(struct telemetry_sawftx_stats)); ++ if (!temp_tx) ++ return NL_STOP; ++ len = nla_len(feat[QCA_WLAN_VENDOR_ATTR_FEAT_SAWFTX]); ++ memcpy((uint8_t *)temp_tx, nla_data(feat[QCA_WLAN_VENDOR_ATTR_FEAT_SAWFTX]), ++ len); ++ tx_stats = temp_tx; ++ filled_buf_len_tx += len; ++ } else { ++ len = nla_len(feat[QCA_WLAN_VENDOR_ATTR_FEAT_SAWFTX]); ++ memcpy((uint8_t *)tx_stats + filled_buf_len_tx, ++ nla_data(feat[QCA_WLAN_VENDOR_ATTR_FEAT_SAWFTX]), ++ len); ++ filled_buf_len_tx += len; ++ } ++ telemetry_stats->feat[STATS_FEAT_SAWFTX] = tx_stats; ++ } ++ ++ return NL_OK; ++} ++ ++static void free_unified_stats(struct unified_stats *telemetry_stats) ++{ ++ int i; ++ ++ for (i = 0; i < STATS_FEAT_MAX; i++) { ++ if (telemetry_stats->feat[i]) ++ free(telemetry_stats->feat[i]); ++ telemetry_stats->feat[i] = NULL; ++ } ++ free(telemetry_stats); ++} ++ ++static int handle_sawf_stats(struct nl80211_state *state, ++ struct nl_msg *msg, int argc, char **argv, ++ enum id_input id) ++{ ++ struct nlattr *telemetry; ++ unsigned char mac_addr[MAC_ADDR_LEN]; ++ unsigned long stats = 0; ++ uint8_t value; ++ int ret; ++ struct nl_cb *cb; ++ struct unified_stats *telemetry_stats; ++ char *end; ++ ++ if (argc < TELEMETRY_GET_STATS_MIN_ARG || argc > TELEMETRY_GET_STATS_MAX_ARG) ++ goto err; ++ ++ if (mac_addr_a2n(mac_addr, argv[0])) { ++ printf("Invalid MAC address\n"); ++ return -EINVAL; ++ } ++ argc--; ++ argv++; ++ ++ if (!strcmp("svc_id", argv[0])) { ++ argc--; ++ argv++; ++ errno = 0; ++ value = strtoul(argv[0], &end, 10); ++ if (*end != '\0' || value > MAX_RANGE(uint8_t) || errno == ERANGE) ++ goto err; ++ ++ argc--; ++ argv++; ++ } else { ++ goto err; ++ } ++ ++ if (!argc) ++ goto err; ++ ++ while (argc) { ++ if (!strcmp("sawfdelay",argv[0])) ++ stats |= SAWFDELAY_STATS; ++ else if (!strcmp("sawftx",argv[0])) ++ stats |= SAWFTX_STATS; ++ else ++ goto err; ++ argc--; ++ argv++; ++ } ++ ++ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA); ++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, ++ QCA_NL80211_VENDOR_SUBCMD_TELEMETRY_GETSTATS); ++ ++ telemetry = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA); ++ if (!telemetry) ++ return -ENOBUFS; ++ ++ if (nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_TELEMETRIC_LEVEL, ++ STATS_LVL_ADVANCE) || ++ nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_TELEMETRIC_OBJECT, ++ STATS_OBJ_STA) || ++ nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_TELEMETRIC_TYPE, ++ STATS_TYPE_DATA) || ++ nla_put_u64(msg, QCA_WLAN_VENDOR_ATTR_TELEMETRIC_FEATURE_FLAG, ++ stats) || ++ nla_put(msg, QCA_WLAN_VENDOR_ATTR_TELEMETRIC_STA_MAC, ++ ETH_ALEN, mac_addr) || ++ nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_TELEMETRIC_SERVICEID, ++ value) || ++ nla_put_flag(msg, QCA_WLAN_VENDOR_ATTR_TELEMETRIC_AGGREGATE)) ++ return -ENOBUFS; ++ ++ nla_nest_end(msg, telemetry); ++ telemetry_stats = malloc(sizeof(struct unified_stats)); ++ if (!telemetry_stats) ++ return NL_SKIP; ++ ++ memset(telemetry_stats, 0, sizeof(struct unified_stats)); ++ ++ ret = nl_send_auto_complete(state->nl_sock, msg); ++ if (ret < 0) ++ goto unified_stats_free; ++ ++ telemetry_stats->err = -1; ++ ++ cb = nl_cb_alloc(iw_debug ? NL_CB_DEBUG : NL_CB_DEFAULT); ++ nl_cb_err(cb, NL_CB_CUSTOM, error_stats_handler, telemetry_stats); ++ nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_telemetry_stats, telemetry_stats); ++ nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, complete_telemetry_stats, telemetry_stats); ++ ++ while (telemetry_stats->err < 0) ++ nl_recvmsgs(state->nl_sock, cb); ++ ++ if (telemetry_stats->err != EINVAL) ++ print_sawf_stats(telemetry_stats, value); ++ nl_cb_put(cb); // free the cb ++ ++unified_stats_free: ++ free_unified_stats(telemetry_stats); ++ return HANDLER_RET_DONE; ++err: ++ printf("Invalid SAWF stats get command, format: Usage\n"); ++ printf("iw dev sawf_stats get [svc_id ] "); ++ printf("<[sawftx] [sawfdelay]>\n"); ++ return HANDLER_RET_DONE; ++} ++COMMAND(sawf_stats, get, " svc_id <[sawftx] [sawfdelay]>", NL80211_CMD_VENDOR, 0, CIB_NETDEV, handle_sawf_stats, "."); +--- /dev/null ++++ b/sawf_stats.h +@@ -0,0 +1,368 @@ ++/* ++ * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. ++ ++ * 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. ++ */ ++ ++/** ++ * enum qca_wlan_vendor_attr_telemetric: Defines attributes to be used in ++ * request message of QCA_NL80211_VENDOR_SUBCMD_TELEMETRIC_DATA vendor command. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_TELEMETRIC_LEVEL: Defines stats levels like Basic or ++ * Advance or Debug. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_TELEMETRIC_OBJECT: Defines stats objects like STA or ++ * VAP or Radio or SoC. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_TELEMETRIC_TYPE: Defines stats types like Data or ++ * control. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_TELEMETRIC_AGGREGATE: Defines aggregation flag for ++ * driver agrregation. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_TELEMETRIC_FEATURE_FLAG: Defines feature flags for ++ * which stats is requested. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_TELEMETRIC_STA_MAC: Defines STA MAC Address if the ++ * request is for particular STA object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_TELEMETRIC_SERVICEID: Defines serviceid for sawf stats. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_TELEMETRIC_MAX: Defines maximum attribute counts to be ++ * used in QCA_NL80211_VENDOR_SUBCMD_TELEMETRIC_DATA vendor command request. ++ */ ++enum qca_wlan_vendor_attr_telemetric { ++ QCA_WLAN_VENDOR_TELEMETRY_INVALID = 0, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRIC_LEVEL, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRIC_OBJECT, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRIC_TYPE, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRIC_AGGREGATE, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRIC_FEATURE_FLAG, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRIC_STA_MAC, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRIC_SERVICEID, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRIC_MLD_LINK, ++ ++ QCA_WLAN_VENDOR_ATTR_TELEMETRIC_AFTER_LAST, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRIC_MAX = ++ QCA_WLAN_VENDOR_ATTR_TELEMETRIC_AFTER_LAST -1, ++}; ++ ++/** ++ * enum qca_wlan_vendor_attr_stats: Defines attributes to be used in response of ++ * QCA_NL80211_VENDOR_SUBCMD_TELEMETRIC_DATA vendor command. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_STATS_LEVEL: Used for stats levels like Basic or ++ * Advance or Debug. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_STATS_OBJECT: Required (u8) ++ * Used with the command, carrying stats, to specify for which stats_object_e. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_STATS_OBJ_ID: Used for Object ID like for STA MAC ++ * address or for VAP or Radio or SoC respective interface name. ++ * ++ * QCA_WLAN_VENDOR_ATTR_STATS_SERVICEID: Used for sawf levels stats like per ++ * peer or per peer per serviceclass. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_STATS_PARENT_IF: Used for Parent Object interface name ++ * like for STA VAP name, for VAP Radio interface name and for Radio SoC ++ * interface name. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_STATS_TYPE: Used for stats types like Data or ++ * control. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_STATS_RECURSIVE: Required (NESTED Flag) ++ * Used with the command to specify the nested stats. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_STATS_MULTI_REPLY: Set this flag if current reply ++ * messageis holding data from previous reply. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_STATS_MAX: Defines maximum attriutes can be used in ++ * QCA_NL80211_VENDOR_SUBCMD_TELEMETRIC_DATA vendor command response. ++ */ ++ ++enum qca_wlan_vendor_attr_stats { ++ QCA_WLAN_VENDOR_ATTR_STATS_LEVEL = 1, ++ QCA_WLAN_VENDOR_ATTR_STATS_OBJECT, ++ QCA_WLAN_VENDOR_ATTR_STATS_OBJ_ID, ++ QCA_WLAN_VENDOR_ATTR_STATS_SERVICEID, ++ QCA_WLAN_VENDOR_ATTR_STATS_PARENT_IF, ++ QCA_WLAN_VENDOR_ATTR_STATS_TYPE, ++ QCA_WLAN_VENDOR_ATTR_STATS_RECURSIVE, ++ QCA_WLAN_VENDOR_ATTR_STATS_MULTI_REPLY, ++ QCA_WLAN_VENDOR_ATTR_STATS_MAX, ++}; ++ ++/** ++ * enum qca_wlan_vendor_attr_feat: Defines nested attributes to be used in ++ * response of QCA_NL80211_VENDOR_SUBCMD_TELEMETRIC_DATA vendor command. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_ME: Used for Multicast Enhancement stats for a ++ * particular stats object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_RX: Used for Rx stats for a particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_TX: Used for Tx stats for a particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_AST: Used for AST stats for a particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_CFR: Used for CFR stats for a particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_FWD: Used for BSS stats for a particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_RAW: Used for RAW mode stats for a particular ++ * object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_TSO: Used for TSO stats for a particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_TWT: Used for TWT stats for a particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_VOW: Used for VOW stats for a particular object. ++* ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_WDI: Used for WDI stats for a particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_WMI: Used for WMI stats for a particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_IGMP: Used for IGMP stats for a particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_LINK: Used for Link related stats for a particular ++ * object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_MESH: Used for Mesh related stats for a particular ++ * object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_RATE: Used for Rate stats for a particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_NAWDS: Used for NAWDS related stats for a ++ * particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_DELAY: Used for DELAY related stats for a ++ * particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_JITTER: Used for JITTER related stats for a ++ * particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_TXCAP: Used for TXCAP realted stats for a ++ * particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_MONITOR: Used for MONITOR realted stats for a ++ * particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_SAWFDELAY: Used for SAWFDELAY related stats for a ++ * particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_SAWFTX: Used for SAWFTX related stats for a ++ * particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_DETER: Used for DETERMINISTIC related stats for a ++ * particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_MAX: Defines Maximum count of feature attributes. ++ */ ++enum qca_wlan_vendor_attr_feat { ++ QCA_WLAN_VENDOR_ATTR_FEAT_ME = 1, ++ QCA_WLAN_VENDOR_ATTR_FEAT_RX, ++ QCA_WLAN_VENDOR_ATTR_FEAT_TX, ++ QCA_WLAN_VENDOR_ATTR_FEAT_AST, ++ QCA_WLAN_VENDOR_ATTR_FEAT_CFR, ++ QCA_WLAN_VENDOR_ATTR_FEAT_FWD, ++ QCA_WLAN_VENDOR_ATTR_FEAT_RAW, ++ QCA_WLAN_VENDOR_ATTR_FEAT_TSO, ++ QCA_WLAN_VENDOR_ATTR_FEAT_TWT, ++ QCA_WLAN_VENDOR_ATTR_FEAT_VOW, ++ QCA_WLAN_VENDOR_ATTR_FEAT_WDI, ++ QCA_WLAN_VENDOR_ATTR_FEAT_WMI, ++ QCA_WLAN_VENDOR_ATTR_FEAT_IGMP, ++ QCA_WLAN_VENDOR_ATTR_FEAT_LINK, ++ QCA_WLAN_VENDOR_ATTR_FEAT_MESH, ++ QCA_WLAN_VENDOR_ATTR_FEAT_RATE, ++ QCA_WLAN_VENDOR_ATTR_FEAT_NAWDS, ++ QCA_WLAN_VENDOR_ATTR_FEAT_DELAY, ++ QCA_WLAN_VENDOR_ATTR_FEAT_JITTER, ++ QCA_WLAN_VENDOR_ATTR_FEAT_TXCAP, ++ QCA_WLAN_VENDOR_ATTR_FEAT_MONITOR, ++ QCA_WLAN_VENDOR_ATTR_FEAT_SAWFDELAY, ++ QCA_WLAN_VENDOR_ATTR_FEAT_SAWFTX, ++ QCA_WLAN_VENDOR_ATTR_FEAT_DETER, ++ /** ++ * New attribute must be add before this. ++ * Also define the corresponding feature ++ * index in stats_feat_index_e. ++ */ ++ QCA_WLAN_VENDOR_ATTR_FEAT_MAX, ++}; ++ ++/** ++ * enum stats_level: Defines detailing levels ++ * @STATS_LVL_BASIC: Very minimal stats data ++ * @STATS_LVL_ADVANCE: Mostly feature specific stats data ++ * @STATS_LVL_DEBUG: Stats data for debug purpose ++ * @STATS_LVL_MAX: Max supported Stats levels ++ */ ++enum stats_level { ++ STATS_LVL_BASIC, ++ STATS_LVL_ADVANCE, ++ STATS_LVL_DEBUG, ++ STATS_LVL_MAX = STATS_LVL_DEBUG, ++}; ++ ++/** ++ * enum stats_object: Defines the Stats specific to object ++ * @STATS_OBJ_STA: Stats for station/peer associated to AP ++ * @STATS_OBJ_VAP: Stats for VAP ++ * @STATS_OBJ_MLD: Stats for MLD group ++ * @STATS_OBJ_RADIO: Stats for particular Radio ++ * @STATS_OBJ_AP: Stats for SoC ++ * @STATS_OBJ_MAX: Max supported objects ++ */ ++enum stats_object { ++ STATS_OBJ_STA, ++ STATS_OBJ_VAP, ++ STATS_OBJ_MLD, ++ STATS_OBJ_RADIO, ++ STATS_OBJ_AP, ++ STATS_OBJ_MAX = STATS_OBJ_AP, ++}; ++ ++/** ++ * enum stats_type: Defines the Stats for specific category ++ * @STATS_TYPE_DATA: Stats for Data frames ++ * @STATS_TYPE_CTRL: Stats for Control/Management frames ++ * @STATS_TYPE_MAX: Max supported types ++ */ ++enum stats_type { ++ STATS_TYPE_DATA, ++ STATS_TYPE_CTRL, ++ STATS_TYPE_MAX = STATS_TYPE_CTRL, ++}; ++ ++#define MAX_TID 8 ++#define MAX_Q 8 ++#define MAX_SAWF_Q 2 ++ ++struct sawf_fw_mpdu_stats { ++ uint64_t success_cnt; ++ uint64_t failure_cnt; ++}; ++ ++struct dp_pkt_info { ++ uint32_t num_pkts; ++ uint64_t bytes; ++}; ++ ++struct telemetry_sawf_tx_stat { ++ struct dp_pkt_info tx_success; ++ struct dp_pkt_info tx_ingress; ++ struct { ++ struct dp_pkt_info fw_rem; ++ uint32_t fw_rem_notx; ++ uint32_t fw_rem_tx; ++ uint32_t age_out; ++ uint32_t fw_reason1; ++ uint32_t fw_reason2; ++ uint32_t fw_reason3; ++ } dropped; ++ struct sawf_fw_mpdu_stats svc_intval_stats; ++ struct sawf_fw_mpdu_stats burst_size_stats; ++ uint32_t tx_failed; ++ uint32_t queue_depth; ++ uint32_t throughput; ++ uint32_t ingress_rate; ++}; ++ ++struct telemetry_sawftx_stats { ++ struct telemetry_sawf_tx_stat tx[MAX_TID][MAX_Q]; ++ uint8_t tid; ++ uint8_t msduq; ++}; ++ ++enum stats_if_hist_bucket_index { ++ HIST_BUCKET_0, ++ HIST_BUCKET_1, ++ HIST_BUCKET_2, ++ HIST_BUCKET_3, ++ HIST_BUCKET_4, ++ HIST_BUCKET_5, ++ HIST_BUCKET_6, ++ HIST_BUCKET_7, ++ HIST_BUCKET_8, ++ HIST_BUCKET_9, ++ HIST_BUCKET_10, ++ HIST_BUCKET_11, ++ HIST_BUCKET_12, ++ HIST_BUCKET_MAX, ++}; ++ ++enum stats_if_delay_bucket_index { ++ DELAY_BUCKET_0, ++ DELAY_BUCKET_1, ++ DELAY_BUCKET_2, ++ DELAY_BUCKET_3, ++ DELAY_BUCKET_4, ++ DELAY_BUCKET_5, ++ DELAY_BUCKET_6, ++ DELAY_BUCKET_7, ++ DELAY_BUCKET_8, ++ DELAY_BUCKET_9, ++ DELAY_BUCKET_10, ++ DELAY_BUCKET_11, ++ DELAY_BUCKET_12, ++ DELAY_BUCKET_MAX, ++}; ++ ++enum hist_types { ++ HIST_TYPE_SW_ENQEUE_DELAY, ++ HIST_TYPE_HW_COMP_DELAY, ++ HIST_TYPE_REAP_STACK, ++ HIST_TYPE_HW_TX_COMP_DELAY, ++ HIST_TYPE_MAX, ++}; ++ ++struct hist_bucket { ++ enum hist_types hist_type; ++ uint64_t freq[HIST_BUCKET_MAX]; ++}; ++ ++struct delay_hist_stats { ++ struct hist_bucket hist; ++ int32_t max; ++ int32_t min; ++ int32_t avg; ++}; ++ ++struct telemetry_sawf_delay_stat { ++ struct delay_hist_stats delay_hist; ++ uint8_t cur_win; ++ uint32_t nwdelay_avg; ++ uint32_t swdelay_avg; ++ uint32_t hwdelay_avg; ++ uint64_t delay_bound_success; ++ uint64_t delay_bound_failure; ++}; ++ ++struct telemetry_sawfdelay_stats { ++ struct telemetry_sawf_delay_stat delay[MAX_TID][MAX_Q]; ++ uint8_t tid; ++ uint8_t msduq; ++}; ++ ++enum stats_feat { ++ STATS_FEAT_SAWFDELAY = 0, ++ STATS_FEAT_SAWFTX = 1, ++ STATS_FEAT_MAX = 2, ++}; ++ ++struct unified_stats { ++ void *feat[STATS_FEAT_MAX]; ++ int err; ++}; ++ +--- a/iw.h ++++ b/iw.h +@@ -82,6 +82,7 @@ enum qca_nl80211_vendor_subcmds { + QCA_NL80211_VENDOR_SUBCMD_TELEMETRY_SLA_BREACH_DETECTION_CFG = 212, + QCA_NL80211_VENDOR_SUBCMD_SAWF_STREAMING_STATS = 213, + QCA_NL80211_VENDOR_SUBCMD_SAWF_SLA_BREACH = 214, ++ QCA_NL80211_VENDOR_SUBCMD_TELEMETRY_GETSTATS = 334, + }; + /* Attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION and diff --git a/feeds/ipq95xx/iw/patches/616-01-iw-32-bit-compilation-fixes.patch b/feeds/ipq95xx/iw/patches/616-01-iw-32-bit-compilation-fixes.patch new file mode 100644 index 000000000..1c8b089db --- /dev/null +++ b/feeds/ipq95xx/iw/patches/616-01-iw-32-bit-compilation-fixes.patch @@ -0,0 +1,35 @@ +From 465bf0b889b8718318b636763464d0dd78c088c8 Mon Sep 17 00:00:00 2001 +From: Arulanbu Balusamy +Date: Sat, 8 Jul 2023 23:13:36 +0530 +Subject: [PATCH] event.c: format specifier modify in printf statement + +The variable declares in long long int but exist format specifier is unsigned +long int. So modify the format specifier by declaring local variable. + + +Signed-off-by: Arulanbu Balusamy +--- + event.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/event.c ++++ b/event.c +@@ -929,7 +929,7 @@ + #endif + + if (args->time || args->reltime || args->ctime) { +- unsigned long long usecs, previous; ++ unsigned long long usecs, previous, tvusec; + + previous = 1000000ULL * args->ts.tv_sec + args->ts.tv_usec; + gettimeofday(&args->ts, NULL); +@@ -949,7 +949,8 @@ + + memset(buf, 0, 255); + strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm); +- printf("[%s.%06lu]: ", buf, args->ts.tv_usec); ++ tvusec=args->ts.tv_usec; ++ printf("[%s.%06llu]: ", buf, tvusec); + } else { + printf("%llu.%06llu: ", usecs/1000000, usecs % 1000000); + } diff --git a/feeds/ipq95xx/iw/patches/617-iw-print-NO-EHT-flags-for-reg-get-command.patch b/feeds/ipq95xx/iw/patches/617-iw-print-NO-EHT-flags-for-reg-get-command.patch new file mode 100644 index 000000000..7d5a29517 --- /dev/null +++ b/feeds/ipq95xx/iw/patches/617-iw-print-NO-EHT-flags-for-reg-get-command.patch @@ -0,0 +1,49 @@ +From 2f37eaa39c6fb845c181281d5708b3413cf29b79 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Wed, 6 Sep 2023 11:10:35 +0530 +Subject: [PATCH] iw: print NO-EHT flags for reg get command + +If a reg rule is marked with NO-EHT flag, print "NO-EHT" while +displaying the reg rules via reg get command. + +Signed-off-by: Aditya Kumar Singh +--- + nl80211.h | 2 ++ + reg.c | 1 + + 2 files changed, 3 insertions(+) + +diff --git a/nl80211.h b/nl80211.h +index f3f456094989..db431b13776d 100644 +--- a/nl80211.h ++++ b/nl80211.h +@@ -4344,6 +4344,7 @@ enum nl80211_sched_scan_match_attr { + * @NL80211_RRF_NO_HE: HE operation not allowed + * @NL80211_RRF_NO_320MHZ: 320MHz operation not allowed + * @NL80211_RRF_PSD: channels has power spectral density value ++ * @NL80211_RRF_NO_EHT: EHT operation not allowed + */ + enum nl80211_reg_rule_flags { + NL80211_RRF_NO_OFDM = 1<<0, +@@ -4364,6 +4365,7 @@ enum nl80211_reg_rule_flags { + NL80211_RRF_NO_HE = 1<<17, + NL80211_RRF_NO_320MHZ = 1<<18, + NL80211_RRF_PSD = 1<<19, ++ NL80211_RRF_NO_EHT = 1<<20, + }; + + #define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR +diff --git a/reg.c b/reg.c +index 1ff4fe998a18..2c3bffb95486 100644 +--- a/reg.c ++++ b/reg.c +@@ -251,6 +251,7 @@ static int print_reg_handler(struct nl_msg *msg, void *arg) + PARSE_FLAG(NL80211_RRF_NO_160MHZ, "NO-160MHZ"); + PARSE_FLAG(NL80211_RRF_NO_HE, "NO-HE"); + PARSE_FLAG(NL80211_RRF_NO_320MHZ, "NO-320MHZ"); ++ PARSE_FLAG(NL80211_RRF_NO_EHT, "NO-EHT"); + + /* Kernels that support NO_IR always turn on both flags */ + if ((flags & NL80211_RRF_NO_IR) && (flags & __NL80211_RRF_NO_IBSS)) { +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/Makefile b/feeds/ipq95xx/mac80211/Makefile index 2aab06f65..54a0c8928 100644 --- a/feeds/ipq95xx/mac80211/Makefile +++ b/feeds/ipq95xx/mac80211/Makefile @@ -2,11 +2,11 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=mac80211 -PKG_VERSION:=20220404-5.4.164-f40abb4788 +PKG_VERSION:=20220822-5.4.213-ef7197996efe PKG_RELEASE:=1 PKG_SOURCE_URL:=https://mirror2.openwrt.org/sources/ -PKG_HASH:=be7781729017385f2a1d0b388c9fca22468dbbc442138f80e3932ad04ed59f0c PKG_SOURCE:=backports-$(PKG_VERSION).tar.bz2 +PKG_HASH:=80cbf7738d08dc43683c8df0a4334b8220fb153116e8a13e408e854ad2c4950b PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/backports-$(PKG_VERSION) PKG_BUILD_PARALLEL:=1 @@ -89,7 +89,7 @@ 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 +hostapd-common + DEPENDS+= +kmod-cfg80211 KCONFIG:=\ CONFIG_AVERAGE=y FILES:= $(PKG_BUILD_DIR)/net/mac80211/mac80211.ko @@ -179,7 +179,7 @@ config-$(call config_package,mac80211-hwsim) += MAC80211_HWSIM MAKE_OPTS:= -C "$(PKG_BUILD_DIR)" \ CROSS_COMPILE="$(KERNEL_CROSS)" \ ARCH="$(LINUX_KARCH)" \ - EXTRA_CFLAGS="-I$(PKG_BUILD_DIR)/include $(IREMAP_CFLAGS) -I$(STAGING_DIR)/usr/include/qca-nss-drv -I$(STAGING_DIR)/usr/include/qca-nss-clients -Wno-incompatible-pointer-types -Wno-discarded-qualifiers -Wno-int-conversion -Wno-unused-function -Wno-implicit-fallthrough -Wno-error=array-parameter -Wno-stringop-overread -Wno-address -Wno-array-parameter" \ + EXTRA_CFLAGS="-I$(PKG_BUILD_DIR)/include $(IREMAP_CFLAGS) -I$(STAGING_DIR)/usr/include/qca-nss-drv -I$(STAGING_DIR)/usr/include/qca-nss-clients -Wno-incompatible-pointer-types -Wno-discarded-qualifiers -Wno-int-conversion -Wno-unused-function -Wno-implicit-fallthrough -Wno-error=array-parameter -Wno-stringop-overread -Wno-address -Wno-array-parameter -Wno-error=unused-variable" \ KLIB_BUILD="$(LINUX_DIR)" \ MODPROBE=true \ KLIB=$(TARGET_MODULES_DIR) \ @@ -262,8 +262,6 @@ define KernelPackage/cfg80211/install $(INSTALL_DIR) $(1)/lib/wifi $(1)/lib/netifd/wireless $(INSTALL_DATA) ./files/lib/wifi/mac80211.sh $(1)/lib/wifi $(INSTALL_BIN) ./files/lib/netifd/wireless/mac80211.sh $(1)/lib/netifd/wireless - $(INSTALL_DIR) $(1)/etc/hotplug.d/ieee80211 - $(INSTALL_DATA) ./files/mac80211.hotplug $(1)/etc/hotplug.d/ieee80211/10-wifi-detect endef $(eval $(foreach drv,$(PKG_DRIVERS),$(call KernelPackage,$(drv)))) diff --git a/feeds/ipq95xx/mac80211/ath.mk b/feeds/ipq95xx/mac80211/ath.mk index c27f73a3b..a226a280c 100644 --- a/feeds/ipq95xx/mac80211/ath.mk +++ b/feeds/ipq95xx/mac80211/ath.mk @@ -64,6 +64,7 @@ config-$(call config_package,ath10k) += ATH10K ATH10K_PCI config-$(call config_package,ath11k) += ATH11K ATH11K_AHB ATH11K_SPECTRAL ATH11K_DEBUG ATH11K_CFR config-$(call config_package,ath11k-pci) += ATH11K_PCI config-$(call config_package,ath12k) += ATH12K +config-y += ATH12K_SPECTRAL ATH12K_AHB #ifeq ($(CONFIG_KERNEL_IPQ_MEM_PROFILE),512) config-y += ATH11K_MEM_PROFILE_512M @@ -288,7 +289,7 @@ define KernelPackage/ath11k $(call KernelPackage/mac80211/Default) TITLE:=Atheros 802.11ax wireless cards support URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath11k - DEPENDS+= @TARGET_ipq95xx +kmod-ath +@DRIVER_11N_SUPPORT +@DRIVER_11AC_SUPPORT +@DRIVER_11W_SUPPORT \ + DEPENDS+= @(TARGET_ipq95xx||TARGET_ipq53xx) +kmod-ath +@DRIVER_11N_SUPPORT +@DRIVER_11AC_SUPPORT +@DRIVER_11W_SUPPORT \ +@DRIVER_11AX_SUPPORT FILES:= \ $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath11k/ath11k.ko @@ -323,7 +324,7 @@ define KernelPackage/ath12k $(call KernelPackage/mac80211/Default) TITLE:=Atheros 802.11be wireless cards support URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath12k - DEPENDS+= @TARGET_ipq95xx +kmod-ath +@DRIVER_11N_SUPPORT +@DRIVER_11AC_SUPPORT +@DRIVER_11W_SUPPORT \ + DEPENDS+= @(TARGET_ipq95xx||TARGET_ipq53xx) +kmod-ath +@DRIVER_11N_SUPPORT +@DRIVER_11AC_SUPPORT +@DRIVER_11W_SUPPORT \ +@DRIVER_11AX_SUPPORT FILES:= \ $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath12k/ath12k.ko diff --git a/feeds/ipq95xx/mac80211/files/lib/netifd/wireless/mac80211.sh b/feeds/ipq95xx/mac80211/files/lib/netifd/wireless/mac80211.sh index 681289529..690fc37d1 100644 --- a/feeds/ipq95xx/mac80211/files/lib/netifd/wireless/mac80211.sh +++ b/feeds/ipq95xx/mac80211/files/lib/netifd/wireless/mac80211.sh @@ -536,22 +536,13 @@ mac80211_hostapd_setup_base() { eht_ulmumimo_80mhz \ eht_ulmumimo_160mhz \ eht_ulmumimo_320mhz \ - disable_eml_cap + disable_eml_cap:1 append base_cfg "ieee80211be=1" "$N" append base_cfg "eht_su_beamformer=$eht_su_beamformer" "$N" append base_cfg "eht_mu_beamformer=$eht_mu_beamformer" "$N" append base_cfg "eht_su_beamformee=$eht_su_beamformee" "$N" - drv_mlo_capable=$(cat /sys/module/ath12k/parameters/mlo_capable) - if [ -n "$drv_mlo_capable" ] && [ $drv_mlo_capable -eq 1 ]; then - append base_cfg "mlo=1" "$N" - fi - config_get bonded $2 bonded - if [ -n "$bonded" ] && [ $bonded -eq 1 ]; then - append base_cfg "bonded=1" "$N" - fi - [ -n "$disable_eml_cap" ] && append base_cfg "disable_eml_cap=$disable_eml_cap" "$N" if [ -n "$eht_ulmumimo_80mhz" ]; then @@ -1151,9 +1142,9 @@ drv_mac80211_setup() { [ "$rxantenna" = "$prev_rxantenna" -a "$txantenna" = "$prev_txantenna" ] || mac80211_reset_config "$phy" wireless_set_data phy="$phy" txantenna="$txantenna" rxantenna="$rxantenna" - iw phy "$phy" set antenna $txantenna $rxantenna >/dev/null 2>&1 - iw phy "$phy" set antenna_gain $antenna_gain >/dev/null 2>&1 - iw phy "$phy" set distance "$distance" >/dev/null 2>&1 +# iw phy "$phy" set antenna $txantenna $rxantenna >/dev/null 2>&1 +# iw phy "$phy" set antenna_gain $antenna_gain >/dev/null 2>&1 +# iw phy "$phy" set distance "$distance" >/dev/null 2>&1 if [ -n "$txpower" ]; then iw phy "$phy" set txpower fixed "${txpower%%.*}00" diff --git a/feeds/ipq95xx/mac80211/files/lib/wifi/mac80211.sh b/feeds/ipq95xx/mac80211/files/lib/wifi/mac80211.sh index 115e5b796..c256c105f 100644 --- a/feeds/ipq95xx/mac80211/files/lib/wifi/mac80211.sh +++ b/feeds/ipq95xx/mac80211/files/lib/wifi/mac80211.sh @@ -72,6 +72,8 @@ BEGIN { if (vht && band != "1:") mode="VHT80" if (he) mode="HE80" if (he && band == "1:") mode="HE20" + if (be) mode="EHT80" + if (be && band == "1:") mode="EHT20" sub("\\[", "", channel) sub("\\]", "", channel) bands = bands band channel ":" mode " " @@ -85,6 +87,7 @@ $1 == "Band" { vht = "" ht = "" he = "" + be = "" } $0 ~ "Capabilities:" { @@ -99,6 +102,10 @@ $0 ~ "HE Iftypes" { he=1 } +$0 ~ "EHT Iftypes" { + be=1 +} + $1 == "*" && $3 == "MHz" && $0 !~ /disabled/ && band && !channel { channel = $4 } @@ -181,12 +188,12 @@ detect_mac80211() { ${scanning} set wireless.radio${devidx}.disabled=1 - set wireless.default_radio${devidx}=wifi-iface - set wireless.default_radio${devidx}.device=radio${devidx} - set wireless.default_radio${devidx}.network=lan - set wireless.default_radio${devidx}.mode=ap - set wireless.default_radio${devidx}.ssid=OpenWrt - set wireless.default_radio${devidx}.encryption=none + #set wireless.default_radio${devidx}=wifi-iface + #set wireless.default_radio${devidx}.device=radio${devidx} + #set wireless.default_radio${devidx}.network=lan + #set wireless.default_radio${devidx}.mode=ap + #set wireless.default_radio${devidx}.ssid=OpenWrt + #set wireless.default_radio${devidx}.encryption=none EOF uci -q commit wireless diff --git a/feeds/ipq95xx/mac80211/files/mac80211.hotplug b/feeds/ipq95xx/mac80211/files/mac80211.hotplug deleted file mode 100644 index b86555266..000000000 --- a/feeds/ipq95xx/mac80211/files/mac80211.hotplug +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -[ "${ACTION}" = "add" ] && { - /sbin/wifi config -} diff --git a/feeds/ipq95xx/mac80211/patches/pending/200-coldboot-cal.patch b/feeds/ipq95xx/mac80211/patches/pending/200-coldboot-cal.patch new file mode 100644 index 000000000..9a7c4c3f9 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/pending/200-coldboot-cal.patch @@ -0,0 +1,13 @@ +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/qmi.c +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/qmi.c ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/qmi.c +@@ -24,7 +24,7 @@ + #define PLATFORM_CAP_PCIE_GLOBAL_RESET 0x08 + #define ATH12K_QMI_MAX_CHUNK_SIZE 2097152 + +-bool ath12k_cold_boot_cal = 1; ++bool ath12k_cold_boot_cal = 0; + module_param_named(cold_boot_cal, ath12k_cold_boot_cal, bool, 0644); + MODULE_PARM_DESC(cold_boot_cal, + "Decrease the channel switch time but increase the driver load time (Default: true)"); diff --git a/feeds/ipq95xx/mac80211/patches/pending/201-firmware-load.patch b/feeds/ipq95xx/mac80211/patches/pending/201-firmware-load.patch new file mode 100644 index 000000000..e6df72c28 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/pending/201-firmware-load.patch @@ -0,0 +1,31 @@ +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/core.c +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/core.c ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/core.c +@@ -48,7 +48,7 @@ unsigned int ath12k_ftm_mode; + module_param_named(ftm_mode, ath12k_ftm_mode, uint, 0444); + MODULE_PARM_DESC(ftm_mode, "Boots up in factory test mode"); + +-unsigned int ath12k_mlo_capable = true; ++unsigned int ath12k_mlo_capable = false; + module_param_named(mlo_capable, ath12k_mlo_capable, uint, 0644); + MODULE_PARM_DESC(mlo_capable, "mlo capable: 0-disable, 1-enable"); + +@@ -474,7 +474,7 @@ const struct firmware *ath12k_core_firmw + + ath12k_core_create_firmware_path(ab, file, path, sizeof(path)); + +- ret = request_firmware_direct(&fw, path, ab->dev); ++ ret = request_firmware(&fw, path, ab->dev); + if (ret) + return ERR_PTR(ret); + +@@ -734,6 +734,8 @@ int ath12k_core_fetch_bdf(struct ath12k_ + + ab->bd_api = 1; + ret = ath12k_core_fetch_board_data_api_1(ab, bd, ATH12K_DEFAULT_BOARD_FILE); ++ if (!ret) ++ goto success; + if (ret) { + ath12k_err(ab, "failed to fetch board-2.bin from %s\n", + ab->hw_params->fw.dir); diff --git a/feeds/ipq95xx/mac80211/patches/qca/000-a-Revert-mac80211-allow_AP_VLAN_operation_on_crypto_controlled_devices.patch b/feeds/ipq95xx/mac80211/patches/qca/000-a-Revert-mac80211-allow_AP_VLAN_operation_on_crypto_controlled_devices.patch new file mode 100644 index 000000000..6aba65d0d --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/000-a-Revert-mac80211-allow_AP_VLAN_operation_on_crypto_controlled_devices.patch @@ -0,0 +1,57 @@ +From db3bdcb9c3ffc628c5284d7ed03a704295ba1214 Mon Sep 17 00:00:00 2001 +From: quic_nikhgurr +Date: Wed, 28 Mar 2018 18:34:19 +0530 +Subject: Revert: "mac80211: allow AP_VLAN operation on crypto controlled devices" + +This reverts commit: https://git.codelinaro.org/clo/qsdk/kvalo/ath/-/commit/db3bdcb9c3ffc628c5284d7ed03a704295ba1214 + +Signed-off-by: quic_nikhgurr + +--- + net/mac80211/key.c | 8 +++----- + net/mac80211/main.c | 8 ++------ + 2 files changed, 5 insertions(+), 11 deletions(-) + +diff --git b/net/mac80211/key.c a/net/mac80211/key.c +index ee0d0cc8dc3b..aee05ec3f7ea 100644 +--- b/net/mac80211/key.c ++++ a/net/mac80211/key.c +@@ -126,7 +126,7 @@ static void decrease_tailroom_need_count(struct ieee80211_sub_if_data *sdata, + + static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) + { +- struct ieee80211_sub_if_data *sdata = key->sdata; ++ struct ieee80211_sub_if_data *sdata; + struct sta_info *sta; + int ret = -EOPNOTSUPP; + +@@ -162,6 +162,7 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) + if (sta && !sta->uploaded) + goto out_unsupported; + ++ sdata = key->sdata; + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { + /* + * The driver doesn't know anything about VLAN interfaces. +diff --git b/net/mac80211/main.c a/net/mac80211/main.c +index 8d0333b5355b..0785d04a80bc 100644 +--- b/net/mac80211/main.c ++++ a/net/mac80211/main.c +@@ -930,12 +930,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) + IEEE80211_HT_CAP_SM_PS_SHIFT; + } + +- /* if low-level driver supports AP, we also support VLAN. +- * drivers advertising SW_CRYPTO_CONTROL should enable AP_VLAN +- * based on their support to transmit SW encrypted packets. +- */ +- if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP) && +- !ieee80211_hw_check(&local->hw, SW_CRYPTO_CONTROL)) { ++ /* if low-level driver supports AP, we also support VLAN */ ++ if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) { + hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); + hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN); + } +-- +2.25.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/000-b-Revert-net-fq_impl-use-skb_get_hash-instead-of-skb_get_hash_perturb.patch b/feeds/ipq95xx/mac80211/patches/qca/000-b-Revert-net-fq_impl-use-skb_get_hash-instead-of-skb_get_hash_perturb.patch new file mode 100644 index 000000000..f25751ce1 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/000-b-Revert-net-fq_impl-use-skb_get_hash-instead-of-skb_get_hash_perturb.patch @@ -0,0 +1,50 @@ +From 48a54f6bc456859dabbd1fbd805e233d260754cf Mon Sep 17 00:00:00 2001 +From: quic_nikhgurr +Date: Sun, 26 Jul 2020 15:09:46 +0200 +Subject: Revert: "net/fq_impl: use skb_get_hash instead of skb_get_hash_perturb" + +This reverts commit: https://git.codelinaro.org/clo/qsdk/kvalo/ath/-/commit/48a54f6bc456859dabbd1fbd805e233d260754cf + +Signed-off-by: quic_nikhgurr + +--- + include/net/fq.h | 1 + + include/net/fq_impl.h | 3 ++- + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git b/include/net/fq.h a/include/net/fq.h +index e39f3f8d5f8a..2ad85e683041 100644 +--- b/include/net/fq.h ++++ a/include/net/fq.h +@@ -69,6 +69,7 @@ struct fq { + struct list_head tin_backlog; + spinlock_t lock; + u32 flows_cnt; ++ siphash_key_t perturbation; + u32 limit; + u32 memory_limit; + u32 memory_usage; +diff --git b/include/net/fq_impl.h a/include/net/fq_impl.h +index e73d74d2fabf..38a9a3d1222b 100644 +--- b/include/net/fq_impl.h ++++ a/include/net/fq_impl.h +@@ -108,7 +108,7 @@ static struct sk_buff *fq_tin_dequeue(struct fq *fq, + + static u32 fq_flow_idx(struct fq *fq, struct sk_buff *skb) + { +- u32 hash = skb_get_hash(skb); ++ u32 hash = skb_get_hash_perturb(skb, &fq->perturbation); + + return reciprocal_scale(hash, fq->flows_cnt); + } +@@ -308,6 +308,7 @@ static int fq_init(struct fq *fq, int flows_cnt) + INIT_LIST_HEAD(&fq->backlogs); + spin_lock_init(&fq->lock); + fq->flows_cnt = max_t(u32, flows_cnt, 1); ++ get_random_bytes(&fq->perturbation, sizeof(fq->perturbation)); + fq->quantum = 300; + fq->limit = 8192; + fq->memory_limit = 16 << 20; /* 16 MBytes */ +-- +2.25.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/000-c-Revert-ath10k-fix-wmi-mgmt-tx-queue-full-due-to-race-condition.patch b/feeds/ipq95xx/mac80211/patches/qca/000-c-Revert-ath10k-fix-wmi-mgmt-tx-queue-full-due-to-race-condition.patch new file mode 100644 index 000000000..95a04a1e7 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/000-c-Revert-ath10k-fix-wmi-mgmt-tx-queue-full-due-to-race-condition.patch @@ -0,0 +1,48 @@ +From b55379e343a3472c35f4a1245906db5158cab453 Mon Sep 17 00:00:00 2001 +From: quic_nikhgurr +Date: Tue, 22 Dec 2020 14:34:47 +0800 +Subject: Revert: "ath10k: fix wmi mgmt tx queue full due to race condition" + +This reverts commit: https://git.codelinaro.org/clo/qsdk/kvalo/ath/-/commit/b55379e343a3472c35f4a1245906db5158cab453 + +Signed-off-by: quic_nikhgurr + +--- + drivers/net/wireless/ath/ath10k/mac.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +diff --git b/drivers/net/wireless/ath/ath10k/mac.c a/drivers/net/wireless/ath/ath10k/mac.c +index 84db56729cba..8809950afb69 100644 +--- b/drivers/net/wireless/ath/ath10k/mac.c ++++ a/drivers/net/wireless/ath/ath10k/mac.c +@@ -3931,16 +3931,23 @@ bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar) + static int ath10k_mac_tx_wmi_mgmt(struct ath10k *ar, struct sk_buff *skb) + { + struct sk_buff_head *q = &ar->wmi_mgmt_tx_queue; ++ int ret = 0; ++ ++ spin_lock_bh(&ar->data_lock); + +- if (skb_queue_len_lockless(q) >= ATH10K_MAX_NUM_MGMT_PENDING) { ++ if (skb_queue_len(q) == ATH10K_MAX_NUM_MGMT_PENDING) { + ath10k_warn(ar, "wmi mgmt tx queue is full\n"); +- return -ENOSPC; ++ ret = -ENOSPC; ++ goto unlock; + } + +- skb_queue_tail(q, skb); ++ __skb_queue_tail(q, skb); + ieee80211_queue_work(ar->hw, &ar->wmi_mgmt_tx_work); + +- return 0; ++unlock: ++ spin_unlock_bh(&ar->data_lock); ++ ++ return ret; + } + + static enum ath10k_mac_tx_path +-- +2.25.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/000-d-Revert-treewide-Replace-0-element-memcpy-destinations-with-flexible-arrays.patch b/feeds/ipq95xx/mac80211/patches/qca/000-d-Revert-treewide-Replace-0-element-memcpy-destinations-with-flexible-arrays.patch new file mode 100644 index 000000000..7a6ba160c --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/000-d-Revert-treewide-Replace-0-element-memcpy-destinations-with-flexible-arrays.patch @@ -0,0 +1,185 @@ +From 47c662486cccf03e7062139d069b07ab0126ef59 Mon Sep 17 00:00:00 2001 +From: quic_nikhgurr +Date: Fri, 13 Aug 2021 12:19:24 -0700 +Subject: Revert: "treewide: Replace 0-element memcpy() destinations with flexible arrays" + +This reverts commit: https://git.codelinaro.org/clo/qsdk/kvalo/ath/-/commit/47c662486cccf03e7062139d069b07ab0126ef59 + +Signed-off-by: quic_nikhgurr + +--- + drivers/net/wireless/ath/ath10k/bmi.h | 10 +++---- + drivers/scsi/qla4xxx/ql4_def.h | 4 +-- + drivers/staging/r8188eu/include/ieee80211.h | 6 ++-- + drivers/staging/rtl8712/ieee80211.h | 4 +-- + drivers/staging/rtl8723bs/include/ieee80211.h | 6 ++-- + include/linux/ieee80211.h | 30 +++++++++---------- + include/uapi/linux/dlm_device.h | 4 +-- + 7 files changed, 32 insertions(+), 32 deletions(-) + +diff --git b/drivers/net/wireless/ath/ath10k/bmi.h a/drivers/net/wireless/ath/ath10k/bmi.h +index 0685c0d2d4ea..f6fadcbdd86e 100644 +--- b/drivers/net/wireless/ath/ath10k/bmi.h ++++ a/drivers/net/wireless/ath/ath10k/bmi.h +@@ -109,7 +109,7 @@ struct bmi_cmd { + struct { + __le32 addr; + __le32 len; +- u8 payload[]; ++ u8 payload[0]; + } write_mem; + struct { + __le32 addr; +@@ -138,18 +138,18 @@ struct bmi_cmd { + } rompatch_uninstall; + struct { + __le32 count; +- __le32 patch_ids[]; /* length of @count */ ++ __le32 patch_ids[0]; /* length of @count */ + } rompatch_activate; + struct { + __le32 count; +- __le32 patch_ids[]; /* length of @count */ ++ __le32 patch_ids[0]; /* length of @count */ + } rompatch_deactivate; + struct { + __le32 addr; + } lz_start; + struct { + __le32 len; /* max BMI_MAX_DATA_SIZE */ +- u8 payload[]; /* length of @len */ ++ u8 payload[0]; /* length of @len */ + } lz_data; + struct { + u8 name[BMI_NVRAM_SEG_NAME_SZ]; +@@ -160,7 +160,7 @@ struct bmi_cmd { + + union bmi_resp { + struct { +- DECLARE_FLEX_ARRAY(u8, payload); ++ u8 payload[0]; + } read_mem; + struct { + __le32 result; +diff --git b/include/linux/ieee80211.h a/include/linux/ieee80211.h +index ada3dd79cd08..694264503119 100644 +--- b/include/linux/ieee80211.h ++++ a/include/linux/ieee80211.h +@@ -1143,7 +1143,7 @@ struct ieee80211_mgmt { + __le16 auth_transaction; + __le16 status_code; + /* possibly followed by Challenge text */ +- u8 variable[]; ++ u8 variable[0]; + } __packed auth; + struct { + __le16 reason_code; +@@ -1152,26 +1152,26 @@ struct ieee80211_mgmt { + __le16 capab_info; + __le16 listen_interval; + /* followed by SSID and Supported rates */ +- u8 variable[]; ++ u8 variable[0]; + } __packed assoc_req; + struct { + __le16 capab_info; + __le16 status_code; + __le16 aid; + /* followed by Supported rates */ +- u8 variable[]; ++ u8 variable[0]; + } __packed assoc_resp, reassoc_resp; + struct { + __le16 capab_info; + __le16 status_code; +- u8 variable[]; ++ u8 variable[0]; + } __packed s1g_assoc_resp, s1g_reassoc_resp; + struct { + __le16 capab_info; + __le16 listen_interval; + u8 current_ap[ETH_ALEN]; + /* followed by SSID and Supported rates */ +- u8 variable[]; ++ u8 variable[0]; + } __packed reassoc_req; + struct { + __le16 reason_code; +@@ -1182,11 +1182,11 @@ struct ieee80211_mgmt { + __le16 capab_info; + /* followed by some of SSID, Supported rates, + * FH Params, DS Params, CF Params, IBSS Params, TIM */ +- u8 variable[]; ++ u8 variable[0]; + } __packed beacon; + struct { + /* only variable items: SSID, Supported rates */ +- DECLARE_FLEX_ARRAY(u8, variable); ++ u8 variable[0]; + } __packed probe_req; + struct { + __le64 timestamp; +@@ -1194,7 +1194,7 @@ struct ieee80211_mgmt { + __le16 capab_info; + /* followed by some of SSID, Supported rates, + * FH Params, DS Params, CF Params, IBSS Params */ +- u8 variable[]; ++ u8 variable[0]; + } __packed probe_resp; + struct { + u8 category; +@@ -1203,16 +1203,16 @@ struct ieee80211_mgmt { + u8 action_code; + u8 dialog_token; + u8 status_code; +- u8 variable[]; ++ u8 variable[0]; + } __packed wme_action; + struct{ + u8 action_code; +- u8 variable[]; ++ u8 variable[0]; + } __packed chan_switch; + struct{ + u8 action_code; + struct ieee80211_ext_chansw_ie data; +- u8 variable[]; ++ u8 variable[0]; + } __packed ext_chan_switch; + struct{ + u8 action_code; +@@ -1228,7 +1228,7 @@ struct ieee80211_mgmt { + __le16 timeout; + __le16 start_seq_num; + /* followed by BA Extension */ +- u8 variable[]; ++ u8 variable[0]; + } __packed addba_req; + struct{ + u8 action_code; +@@ -1244,11 +1244,11 @@ struct ieee80211_mgmt { + } __packed delba; + struct { + u8 action_code; +- u8 variable[]; ++ u8 variable[0]; + } __packed self_prot; + struct{ + u8 action_code; +- u8 variable[]; ++ u8 variable[0]; + } __packed mesh_action; + struct { + u8 action; +@@ -1292,7 +1292,7 @@ struct ieee80211_mgmt { + u8 toa[6]; + __le16 tod_error; + __le16 toa_error; +- u8 variable[]; ++ u8 variable[0]; + } __packed ftm; + struct { + u8 action_code; +-- +2.25.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/000-e-Revert-ath11k-make-relay-callbacks-const.patch b/feeds/ipq95xx/mac80211/patches/qca/000-e-Revert-ath11k-make-relay-callbacks-const.patch new file mode 100644 index 000000000..49f335e0a --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/000-e-Revert-ath11k-make-relay-callbacks-const.patch @@ -0,0 +1,29 @@ +From 36b0cefe901a06aab1d488c12c38b8076054bc12 Mon Sep 17 00:00:00 2001 +From: quic_nikhgurr +Date: Tue, 15 Dec 2020 20:46:06 -0800 +Subject: Revert: "ath11k: make relay callbacks const" + +This reverts commit: https://git.codelinaro.org/clo/qsdk/kvalo/ath/-/commit/36b0cefe901a06aab1d488c12c38b8076054bc12 + +Signed-off-by: quic_nikhgurr + +--- + drivers/net/wireless/ath/ath11k/spectral.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git b/drivers/net/wireless/ath/ath11k/spectral.c a/drivers/net/wireless/ath/ath11k/spectral.c +index 1afe67759659..ac2a8cfdc1c0 100644 +--- b/drivers/net/wireless/ath/ath11k/spectral.c ++++ a/drivers/net/wireless/ath/ath11k/spectral.c +@@ -148,7 +148,7 @@ static int remove_buf_file_handler(struct dentry *dentry) + return 0; + } + +-static const struct rchan_callbacks rfs_scan_cb = { ++static struct rchan_callbacks rfs_scan_cb = { + .create_buf_file = create_buf_file_handler, + .remove_buf_file = remove_buf_file_handler, + }; +-- +2.25.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/000-f-Revert-fq_codel-generalise-ce_threshold-marking-for-subset-of-traffic.patch b/feeds/ipq95xx/mac80211/patches/qca/000-f-Revert-fq_codel-generalise-ce_threshold-marking-for-subset-of-traffic.patch new file mode 100644 index 000000000..27ae73c60 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/000-f-Revert-fq_codel-generalise-ce_threshold-marking-for-subset-of-traffic.patch @@ -0,0 +1,93 @@ +From dfcb63ce1de6b10ba98dee928f9463f37e5a5512 Mon Sep 17 00:00:00 2001 +From: quic_nikhgurr +Date: Tue, 19 Oct 2021 19:47:09 +0200 +Subject: Revert: "fq_codel: generalise ce_threshold marking for subset of traffic" + +This reverts commit: https://git.codelinaro.org/clo/qsdk/kvalo/ath/-/commit/dfcb63ce1de6b10ba98dee928f9463f37e5a5512 + +Signed-off-by: quic_nikhgurr + +--- + include/net/codel.h | 7 ++----- + include/net/codel_impl.h | 14 +++++++------- + include/uapi/linux/pkt_sched.h | 3 +-- + net/mac80211/sta_info.c | 3 +-- + net/sched/sch_fq_codel.c | 13 ++++--------- + 5 files changed, 15 insertions(+), 25 deletions(-) + +diff --git b/include/net/codel.h a/include/net/codel.h +index a6c9e34e62b8..5e8b181b76b8 100644 +--- b/include/net/codel.h ++++ a/include/net/codel.h +@@ -102,9 +102,7 @@ static inline u32 codel_time_to_us(codel_time_t val) + * @interval: width of moving time window + * @mtu: device mtu, or minimal queue backlog in bytes. + * @ecn: is Explicit Congestion Notification enabled +- * @ce_threshold_selector: apply ce_threshold to packets matching this value +- * in the diffserv/ECN byte of the IP header +- * @ce_threshold_mask: mask to apply to ce_threshold_selector comparison ++ * @ce_threshold_ect1: if ce_threshold only marks ECT(1) packets + */ + struct codel_params { + codel_time_t target; +@@ -112,8 +110,7 @@ struct codel_params { + codel_time_t interval; + u32 mtu; + bool ecn; +- u8 ce_threshold_selector; +- u8 ce_threshold_mask; ++ bool ce_threshold_ect1; + }; + + /** +diff --git b/include/net/codel_impl.h a/include/net/codel_impl.h +index 137d40d8cbeb..7af2c3eb3c43 100644 +--- b/include/net/codel_impl.h ++++ a/include/net/codel_impl.h +@@ -54,8 +54,7 @@ static void codel_params_init(struct codel_params *params) + params->interval = MS2TIME(100); + params->target = MS2TIME(5); + params->ce_threshold = CODEL_DISABLED_THRESHOLD; +- params->ce_threshold_mask = 0; +- params->ce_threshold_selector = 0; ++ params->ce_threshold_ect1 = false; + params->ecn = false; + } + +@@ -251,12 +250,13 @@ static struct sk_buff *codel_dequeue(void *ctx, + if (skb && codel_time_after(vars->ldelay, params->ce_threshold)) { + bool set_ce = true; + +- if (params->ce_threshold_mask) { +- int dsfield = skb_get_dsfield(skb); ++ if (params->ce_threshold_ect1) { ++ /* Note: if skb_get_dsfield() returns -1, following ++ * gives INET_ECN_MASK, which is != INET_ECN_ECT_1. ++ */ ++ u8 ecn = skb_get_dsfield(skb) & INET_ECN_MASK; + +- set_ce = (dsfield >= 0 && +- (((u8)dsfield & params->ce_threshold_mask) == +- params->ce_threshold_selector)); ++ set_ce = (ecn == INET_ECN_ECT_1); + } + if (set_ce && INET_ECN_set_ce(skb)) + stats->ce_mark++; + +diff --git b/net/mac80211/sta_info.c a/net/mac80211/sta_info.c +index bd52ac3bee90..a39830418434 100644 +--- b/net/mac80211/sta_info.c ++++ a/net/mac80211/sta_info.c +@@ -513,8 +513,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, + sta->cparams.target = MS2TIME(20); + sta->cparams.interval = MS2TIME(100); + sta->cparams.ecn = true; +- sta->cparams.ce_threshold_selector = 0; +- sta->cparams.ce_threshold_mask = 0; ++ sta->cparams.ce_threshold_ect1 = false; + + sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr); + +-- +2.25.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/000-g-Revert-fq_codel-implement-L4S-style-ce_threshold_ect1-marking.patch b/feeds/ipq95xx/mac80211/patches/qca/000-g-Revert-fq_codel-implement-L4S-style-ce_threshold_ect1-marking.patch new file mode 100644 index 000000000..1bca7d0f2 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/000-g-Revert-fq_codel-implement-L4S-style-ce_threshold_ect1-marking.patch @@ -0,0 +1,88 @@ +From e72aeb9ee0e34c57dc90793d0bf82cab9624d64e Mon Sep 17 00:00:00 2001 +From: quic_nikhgurr +Date: Thu, 14 Oct 2021 10:59:18 -0700 +Subject: Revert: "fq_codel: implement L4S style ce_threshold_ect1 marking" + +This reverts commit: https://git.codelinaro.org/clo/qsdk/kvalo/ath/-/commit/e72aeb9ee0e34c57dc90793d0bf82cab9624d64e + +Signed-off-by: quic_nikhgurr + +--- + include/net/codel.h | 2 -- + include/net/codel_impl.h | 18 +++--------------- + include/uapi/linux/pkt_sched.h | 1 - + net/mac80211/sta_info.c | 1 - + net/sched/sch_fq_codel.c | 15 ++++----------- + 5 files changed, 7 insertions(+), 30 deletions(-) + +diff --git b/include/net/codel.h a/include/net/codel.h +index 5e8b181b76b8..a6e428f80135 100644 +--- b/include/net/codel.h ++++ a/include/net/codel.h +@@ -102,7 +102,6 @@ static inline u32 codel_time_to_us(codel_time_t val) + * @interval: width of moving time window + * @mtu: device mtu, or minimal queue backlog in bytes. + * @ecn: is Explicit Congestion Notification enabled +- * @ce_threshold_ect1: if ce_threshold only marks ECT(1) packets + */ + struct codel_params { + codel_time_t target; +@@ -110,7 +109,6 @@ struct codel_params { + codel_time_t interval; + u32 mtu; + bool ecn; +- bool ce_threshold_ect1; + }; + + /** +diff --git b/include/net/codel_impl.h a/include/net/codel_impl.h +index 7af2c3eb3c43..d289b91dcd65 100644 +--- b/include/net/codel_impl.h ++++ a/include/net/codel_impl.h +@@ -54,7 +54,6 @@ static void codel_params_init(struct codel_params *params) + params->interval = MS2TIME(100); + params->target = MS2TIME(5); + params->ce_threshold = CODEL_DISABLED_THRESHOLD; +- params->ce_threshold_ect1 = false; + params->ecn = false; + } + +@@ -247,20 +246,9 @@ static struct sk_buff *codel_dequeue(void *ctx, + vars->rec_inv_sqrt); + } + end: +- if (skb && codel_time_after(vars->ldelay, params->ce_threshold)) { +- bool set_ce = true; +- +- if (params->ce_threshold_ect1) { +- /* Note: if skb_get_dsfield() returns -1, following +- * gives INET_ECN_MASK, which is != INET_ECN_ECT_1. +- */ +- u8 ecn = skb_get_dsfield(skb) & INET_ECN_MASK; +- +- set_ce = (ecn == INET_ECN_ECT_1); +- } +- if (set_ce && INET_ECN_set_ce(skb)) +- stats->ce_mark++; +- } ++ if (skb && codel_time_after(vars->ldelay, params->ce_threshold) && ++ INET_ECN_set_ce(skb)) ++ stats->ce_mark++; + return skb; + } + +diff --git b/net/mac80211/sta_info.c a/net/mac80211/sta_info.c +index a39830418434..2b5acb37587f 100644 +--- b/net/mac80211/sta_info.c ++++ a/net/mac80211/sta_info.c +@@ -513,7 +513,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, + sta->cparams.target = MS2TIME(20); + sta->cparams.interval = MS2TIME(100); + sta->cparams.ecn = true; +- sta->cparams.ce_threshold_ect1 = false; + + sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr); + +-- +2.25.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/000-h-Revert-mac80211-use-eth_hw_addr_set.patch b/feeds/ipq95xx/mac80211/patches/qca/000-h-Revert-mac80211-use-eth_hw_addr_set.patch new file mode 100644 index 000000000..b42b4e6e4 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/000-h-Revert-mac80211-use-eth_hw_addr_set.patch @@ -0,0 +1,43 @@ +From de1352ead8a8cb4367a19ac23d9deaaa23befc3e Mon Sep 17 00:00:00 2001 +From: quic_nikhgurr +Date: Tue, 19 Oct 2021 09:28:15 -0700 +Subject: Revert: "mac80211: use eth_hw_addr_set()" + +This reverts commit: https://git.codelinaro.org/clo/qsdk/kvalo/ath/-/commit/de1352ead8a8cb4367a19ac23d9deaaa23befc3e + +Signed-off-by: quic_nikhgurr + +--- + net/mac80211/iface.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git b/net/mac80211/iface.c a/net/mac80211/iface.c +index 9a2145c8192b..691b983b762e 100644 +--- b/net/mac80211/iface.c ++++ a/net/mac80211/iface.c +@@ -1137,7 +1137,9 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) + * this interface, if it has the special null one. + */ + if (dev && is_zero_ether_addr(dev->dev_addr)) { +- eth_hw_addr_set(dev, local->hw.wiphy->perm_addr); ++ memcpy(dev->dev_addr, ++ local->hw.wiphy->perm_addr, ++ ETH_ALEN); + memcpy(dev->perm_addr, dev->dev_addr, ETH_ALEN); + + if (!is_valid_ether_addr(dev->dev_addr)) { +@@ -1991,9 +1993,9 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, + + ieee80211_assign_perm_addr(local, ndev->perm_addr, type); + if (is_valid_ether_addr(params->macaddr)) +- eth_hw_addr_set(ndev, params->macaddr); ++ memcpy(ndev->dev_addr, params->macaddr, ETH_ALEN); + else +- eth_hw_addr_set(ndev, ndev->perm_addr); ++ memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN); + SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); + + /* don't use IEEE80211_DEV_TO_SUB_IF -- it checks too much */ +-- +2.25.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/000-i-Revert-mac80211-Use-memset_after-to-clear-tx-status.patch b/feeds/ipq95xx/mac80211/patches/qca/000-i-Revert-mac80211-Use-memset_after-to-clear-tx-status.patch new file mode 100644 index 000000000..e7d771c35 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/000-i-Revert-mac80211-Use-memset_after-to-clear-tx-status.patch @@ -0,0 +1,36 @@ +From fb5f6a0e8063b7a84d6d44ef353846ccd7708d2e Mon Sep 17 00:00:00 2001 +From: quic_nikhgurr +Date: Thu, 18 Nov 2021 12:38:39 -0800 +Subject: Revert: "mac80211: Use memset_after() to clear tx status" + +This reverts commit: https://git.codelinaro.org/clo/qsdk/kvalo/ath/-/commit/fb5f6a0e8063b7a84d6d44ef353846ccd7708d2e + +Signed-off-by: quic_nikhgurr + +--- + drivers/net/wireless/ath/carl9170/tx.c | 12 ++++++------ + drivers/net/wireless/intersil/p54/txrx.c | 6 +++++- + include/net/mac80211.h | 7 ++++++- + 3 files changed, 17 insertions(+), 8 deletions(-) + +diff --git b/include/net/mac80211.h a/include/net/mac80211.h +index e349f57d19ae..10e6fe215f0f 100644 +--- b/include/net/mac80211.h ++++ a/include/net/mac80211.h +@@ -1205,7 +1205,12 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) + /* clear the rate counts */ + for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) + info->status.rates[i].count = 0; +- memset_after(&info->status, 0, rates); ++ ++ BUILD_BUG_ON( ++ offsetof(struct ieee80211_tx_info, status.ack_signal) != 20); ++ memset(&info->status.ampdu_ack_len, 0, ++ sizeof(struct ieee80211_tx_info) - ++ offsetof(struct ieee80211_tx_info, status.ampdu_ack_len)); + } + + +-- +2.25.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/000-j-Revert-ethtool-extend-ringparam-setting-getting-API-with-rx_buf_len.patch b/feeds/ipq95xx/mac80211/patches/qca/000-j-Revert-ethtool-extend-ringparam-setting-getting-API-with-rx_buf_len.patch new file mode 100644 index 000000000..2ad44e213 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/000-j-Revert-ethtool-extend-ringparam-setting-getting-API-with-rx_buf_len.patch @@ -0,0 +1,38 @@ +From 7462494408cd3de8b0bc1e79670bf213288501d0 Mon Sep 17 00:00:00 2001 +From: quic_nikhgurr +Date: Thu, 18 Nov 2021 20:12:43 +0800 +Subject: Revert: "ethtool: extend ringparam setting/getting API with rx_buf_len" + +This reverts commit: https://git.codelinaro.org/clo/qsdk/kvalo/ath/-/commit/7462494408cd3de8b0bc1e79670bf213288501d0 + +Signed-off-by: quic_nikhgurr + +diff --git b/net/mac80211/ethtool.c a/net/mac80211/ethtool.c +index b2253df54413..99a2e30b3833 100644 +--- b/net/mac80211/ethtool.c ++++ a/net/mac80211/ethtool.c +@@ -14,9 +14,7 @@ + #include "driver-ops.h" + + static int ieee80211_set_ringparam(struct net_device *dev, +- struct ethtool_ringparam *rp, +- struct kernel_ethtool_ringparam *kernel_rp, +- struct netlink_ext_ack *extack) ++ struct ethtool_ringparam *rp) + { + struct ieee80211_local *local = wiphy_priv(dev->ieee80211_ptr->wiphy); + +@@ -27,9 +25,7 @@ static int ieee80211_set_ringparam(struct net_device *dev, + } + + static void ieee80211_get_ringparam(struct net_device *dev, +- struct ethtool_ringparam *rp, +- struct kernel_ethtool_ringparam *kernel_rp, +- struct netlink_ext_ack *extack) ++ struct ethtool_ringparam *rp) + { + struct ieee80211_local *local = wiphy_priv(dev->ieee80211_ptr->wiphy); + +-- +2.25.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/000-k-Revert-headers-Add-MHI-stuff-to-mod_devicetable.patch b/feeds/ipq95xx/mac80211/patches/qca/000-k-Revert-headers-Add-MHI-stuff-to-mod_devicetable.patch new file mode 100644 index 000000000..ca16554f7 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/000-k-Revert-headers-Add-MHI-stuff-to-mod_devicetable.patch @@ -0,0 +1,40 @@ +From 8afac3a8ddf832c33b4a7acff5687bae657c8c38 Mon Sep 17 00:00:00 2001 +From: quic_nikhgurr +Date: Mon, 7 Feb 2022 11:33:32 +0000 +Subject: Revert: "headers: Add MHI stuff to mod_devicetable" + +This reverts commit: https://git.kernel.org/pub/scm/linux/kernel/git/backports/backports.git/commit/?id=8afac3a8ddf832c33b4a7acff5687bae657c8c38 + +Signed-off-by: quic_nikhgurr + +--- + backport/backport-include/linux/mod_devicetable.h | 15 --------------- + 1 file changed, 15 deletions(-) + +diff --git b/backport/backport-include/linux/mod_devicetable.h a/backport/backport-include/linux/mod_devicetable.h +index fc9beedb..ec0a3e62 100644 +--- b/backport-include/linux/mod_devicetable.h ++++ a/backport-include/linux/mod_devicetable.h +@@ -14,19 +14,4 @@ + #define HID_ANY_ID (~0) + #endif + +-#if LINUX_VERSION_IS_LESS(5,7,0) +-#define MHI_DEVICE_MODALIAS_FMT "mhi:%s" +-#define MHI_NAME_SIZE 32 +- +-/** +- * struct mhi_device_id - MHI device identification +- * @chan: MHI channel name +- * @driver_data: driver data; +- */ +-struct mhi_device_id { +- const char chan[MHI_NAME_SIZE]; +- kernel_ulong_t driver_data; +-}; +-#endif +- + #endif /* __BACKPORT_MOD_DEVICETABLE_H */ +-- +2.25.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/007-fix_compilation_issue.patch b/feeds/ipq95xx/mac80211/patches/qca/007-fix_compilation_issue.patch index b1cf418a9..41aa50286 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/007-fix_compilation_issue.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/007-fix_compilation_issue.patch @@ -48,7 +48,7 @@ PTR_ERR(ar_ahb->cpu_init_rst)); --- a/drivers/net/wireless/ath/ath11k/Kconfig +++ b/drivers/net/wireless/ath/ath11k/Kconfig -@@ -5,7 +5,6 @@ config ATH11K +@@ -6,7 +6,6 @@ config ATH11K depends on MAC80211 && HAS_DMA depends on CRYPTO_MICHAEL_MIC select ATH_COMMON @@ -58,7 +58,7 @@ chipsets. --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -46,7 +46,7 @@ struct wmi_tlv { +@@ -48,7 +48,7 @@ struct wmi_tlv { #define WMI_TLV_LEN GENMASK(15, 0) #define WMI_TLV_TAG GENMASK(31, 16) @@ -218,7 +218,7 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, struct genl_info *info, struct cfg80211_crypto_settings *settings, -@@ -14010,7 +14012,7 @@ static int nl80211_vendor_check_policy(c +@@ -14593,7 +14595,7 @@ static int nl80211_vendor_check_policy(c return -EINVAL; } @@ -280,16 +280,16 @@ #endif /* _BP_LINUX_VERSION_H */ --- a/include/net/mac80211.h +++ b/include/net/mac80211.h -@@ -3956,8 +3956,6 @@ struct ieee80211_prep_tx_info { +@@ -4108,8 +4108,6 @@ struct ieee80211_prep_tx_info { * radar channel. * The caller is expected to set chandef pointer to NULL in order to * disable background CAC/radar detection. - * @net_fill_forward_path: Called from .ndo_fill_forward_path in order to - * resolve a path for hardware flow offloading - */ - struct ieee80211_ops { - void (*tx)(struct ieee80211_hw *hw, -@@ -4288,11 +4286,6 @@ struct ieee80211_ops { + * @change_vif_links: Change the valid links on an interface, note that while + * removing the old link information is still valid (link_conf pointer), + * but may immediately disappear after the function returns. The old or +@@ -4464,11 +4462,6 @@ struct ieee80211_ops { struct ieee80211_sta *sta, u8 flowid); int (*set_radar_background)(struct ieee80211_hw *hw, struct cfg80211_chan_def *chandef); @@ -298,16 +298,15 @@ - struct ieee80211_sta *sta, - struct net_device_path_ctx *ctx, - struct net_device_path *path); - }; - - /** + int (*change_vif_links)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + u16 old_links, u16 new_links, --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h -@@ -1485,27 +1485,4 @@ static inline void drv_twt_teardown_requ - local->ops->twt_teardown_request(&local->hw, sta, flowid); +@@ -1530,28 +1530,6 @@ static inline void drv_twt_teardown_requ trace_drv_return_void(local); } -- + -static inline int drv_net_fill_forward_path(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata, - struct ieee80211_sta *sta, @@ -330,11 +329,13 @@ - return ret; -} - - #endif /* __MAC80211_DRIVER_OPS */ + static inline int drv_change_vif_links(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + u16 old_links, u16 new_links, --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c -@@ -851,64 +851,6 @@ static const struct net_device_ops ieee8 - +@@ -1065,64 +1065,6 @@ static const struct net_device_ops ieee8 + .ndo_get_stats64 = ieee80211_get_stats64, }; -static int ieee80211_netdev_fill_forward_path(struct net_device_path_ctx *ctx, @@ -379,7 +380,7 @@ - } - } - -- sta = sta_info_get(sdata, sdata->u.mgd.bssid); +- sta = sta_info_get(sdata, sdata->deflink.u.mgd.bssid); - break; - default: - goto out; @@ -396,20 +397,19 @@ -} - static const struct net_device_ops ieee80211_dataif_8023_ops = { - #if LINUX_VERSION_IS_LESS(4,10,0) - .ndo_change_mtu = __change_mtu, -@@ -926,8 +868,6 @@ static const struct net_device_ops ieee8 - #else - .ndo_get_stats64 = bp_ieee80211_get_stats64, - #endif -- + .ndo_open = ieee80211_open, + .ndo_stop = ieee80211_stop, +@@ -1132,7 +1074,6 @@ static const struct net_device_ops ieee8 + .ndo_set_mac_address = ieee80211_change_mac, + .ndo_select_queue = ieee80211_netdev_select_queue, + .ndo_get_stats64 = ieee80211_get_stats64, - .ndo_fill_forward_path = ieee80211_netdev_fill_forward_path, }; static bool ieee80211_iftype_supports_hdr_offload(enum nl80211_iftype iftype) --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h -@@ -2892,13 +2892,6 @@ TRACE_EVENT(drv_twt_teardown_request, +@@ -2471,13 +2471,6 @@ TRACE_EVENT(drv_twt_teardown_request, ) ); @@ -420,12 +420,12 @@ - TP_ARGS(local, sdata, sta) -); - - #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ - - #undef TRACE_INCLUDE_PATH + TRACE_EVENT(drv_change_vif_links, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, --- a/backport-include/linux/lockdep.h +++ b/backport-include/linux/lockdep.h -@@ -20,4 +20,16 @@ struct lockdep_map { }; +@@ -23,4 +23,16 @@ struct lockdep_map { }; #endif /* CONFIG_LOCKDEP */ #endif /* lockdep_assert_not_held */ diff --git a/feeds/ipq95xx/mac80211/patches/qca/008-Enabling_vht_capability_for_2G.patch b/feeds/ipq95xx/mac80211/patches/qca/008-Enabling_vht_capability_for_2G.patch index 5765424f9..170220a6f 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/008-Enabling_vht_capability_for_2G.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/008-Enabling_vht_capability_for_2G.patch @@ -1,16 +1,15 @@ --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c -@@ -5028,8 +5028,6 @@ static int ieee80211_prep_channel(struct - struct ieee802_11_elems *elems; +@@ -4577,7 +4577,6 @@ static int ieee80211_prep_channel(struct const struct cfg80211_bss_ies *ies; int ret; -- u32 i; + u32 i; - bool have_80mhz; rcu_read_lock(); -@@ -5127,22 +5125,6 @@ static int ieee80211_prep_channel(struct - ifmgd->flags |= IEEE80211_STA_DISABLE_HE; +@@ -4709,22 +4708,6 @@ static int ieee80211_prep_channel(struct + eht_oper = NULL; } - /* Allow VHT if at least one channel on the sband supports 80 MHz */ @@ -26,7 +25,7 @@ - - if (!have_80mhz) { - sdata_info(sdata, "80 MHz not supported, disabling VHT\n"); -- ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; +- *conn_flags |= IEEE80211_CONN_DISABLE_VHT; - } - if (sband->band == NL80211_BAND_S1GHZ) { @@ -35,7 +34,7 @@ --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c @@ -121,7 +121,6 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(stru - struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.vht_cap; + struct ieee80211_sta_vht_cap *vht_cap = &link_sta->pub->vht_cap; struct ieee80211_sta_vht_cap own_cap; u32 cap_info, i; - bool have_80mhz; @@ -63,14 +62,14 @@ /* * A VHT STA must support 40 MHz, but if we verify that here * then we break a few things - some APs (e.g. Netgear R6300v2 -@@ -361,6 +346,12 @@ enum ieee80211_sta_rx_bandwidth ieee8021 +@@ -392,6 +377,12 @@ out: IEEE80211_STA_RX_BW_40 : IEEE80211_STA_RX_BW_20; + /* If 40MHz support is not indicated in HT cap, we need not check other + * vht caps for 80 & 160MHz. STA bandwidth can be set to 20MHz. + */ -+ if (!(sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) ++ if (!(link_sta->pub->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) + return IEEE80211_STA_RX_BW_20; + cap_width = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK; diff --git a/feeds/ipq95xx/mac80211/patches/qca/009-ath11k-Enable-VHT-for-2G.patch b/feeds/ipq95xx/mac80211/patches/qca/009-ath11k-Enable-VHT-for-2G.patch index 26b3119aa..c3b699005 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/009-ath11k-Enable-VHT-for-2G.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/009-ath11k-Enable-VHT-for-2G.patch @@ -1,18 +1,18 @@ --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -2580,9 +2580,9 @@ static void ath11k_peer_assoc_h_phymode( - } else if (sta->vht_cap.vht_supported && - !ath11k_peer_assoc_h_vht_masked(vht_mcs_mask)) { - if (sta->bandwidth == IEEE80211_STA_RX_BW_40) +@@ -2591,9 +2591,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->ht_cap.ht_supported && + } else if (sta->deflink.ht_cap.ht_supported && !ath11k_peer_assoc_h_ht_masked(ht_mcs_mask)) { - if (sta->bandwidth == IEEE80211_STA_RX_BW_40) -@@ -5066,6 +5066,9 @@ static void ath11k_mac_setup_ht_vht_cap( + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40) +@@ -5092,6 +5092,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); @@ -24,7 +24,7 @@ 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 -@@ -393,6 +393,8 @@ ath11k_pull_mac_phy_cap_svc_ready_ext(st +@@ -398,6 +398,8 @@ ath11k_pull_mac_phy_cap_svc_ready_ext(st * handled. */ if (mac_phy_caps->supported_bands & WMI_HOST_WLAN_2G_CAP) { @@ -32,4 +32,4 @@ + 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; - } else if (mac_phy_caps->supported_bands & WMI_HOST_WLAN_5G_CAP) { + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/012-ath11k-add-pktlog-debugfs-support.patch b/feeds/ipq95xx/mac80211/patches/qca/012-ath11k-add-pktlog-debugfs-support.patch index 3659ae137..f1a9fa0ab 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/012-ath11k-add-pktlog-debugfs-support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/012-ath11k-add-pktlog-debugfs-support.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath11k/Kconfig +++ b/drivers/net/wireless/ath/ath11k/Kconfig -@@ -59,3 +59,12 @@ config ATH11K_SPECTRAL +@@ -60,3 +60,12 @@ config ATH11K_SPECTRAL Enable ath11k spectral scan support Say Y to enable access to the FFT/spectral data via debugfs. @@ -15,25 +15,25 @@ + frame filters can be alterted by debugfs entries. --- a/drivers/net/wireless/ath/ath11k/Makefile +++ b/drivers/net/wireless/ath/ath11k/Makefile -@@ -24,6 +24,7 @@ ath11k-$(CPTCFG_NL80211_TESTMODE) += tes - ath11k-$(CPTCFG_ATH11K_TRACING) += trace.o +@@ -25,6 +25,7 @@ ath11k-$(CPTCFG_ATH11K_TRACING) += trace ath11k-$(CONFIG_THERMAL) += thermal.o ath11k-$(CPTCFG_ATH11K_SPECTRAL) += spectral.o + ath11k-$(CONFIG_PM) += wow.o +ath11k-$(CPTCFG_ATH11K_PKTLOG) += pktlog.o obj-$(CPTCFG_ATH11K_AHB) += ath11k_ahb.o ath11k_ahb-y += ahb.o --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -12,6 +12,7 @@ - #include +@@ -17,6 +17,7 @@ + #include #include "qmi.h" #include "htc.h" +#include "pktlog.h" #include "wmi.h" #include "hal.h" #include "dp.h" -@@ -453,6 +454,11 @@ struct ath11k_debug { +@@ -553,6 +554,11 @@ struct ath11k_debug { u32 pktlog_mode; u32 pktlog_peer_valid; u8 pktlog_peer_addr[ETH_ALEN]; @@ -43,8 +43,8 @@ + bool is_pkt_logging; +#endif u32 rx_filter; - }; - + u32 mem_offset; + u32 module_id_bitmap[MAX_MODULE_ID_BITMAP_WORDS]; --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c @@ -14,6 +14,7 @@ @@ -55,7 +55,7 @@ static const char *htt_bp_umac_ring[HTT_SW_UMAC_RING_IDX_MAX] = { "REO2SW1_RING", -@@ -1132,6 +1133,7 @@ int ath11k_debugfs_register(struct ath11 +@@ -1401,6 +1402,7 @@ int ath11k_debugfs_register(struct ath11 ath11k_debugfs_htt_stats_init(ar); ath11k_debugfs_fw_stats_init(ar); @@ -63,17 +63,20 @@ debugfs_create_file("ext_tx_stats", 0644, ar->debug.debugfs_pdev, ar, -@@ -1157,4 +1159,5 @@ int ath11k_debugfs_register(struct ath11 - - void ath11k_debugfs_unregister(struct ath11k *ar) - { +@@ -1448,6 +1450,8 @@ void ath11k_debugfs_unregister(struct at + kfree(dbr_debug); + ar->debug.dbr_debug[i] = NULL; + } ++ + ath11k_deinit_pktlog(ar); } + + static ssize_t ath11k_write_twt_add_dialog(struct file *file, --- a/drivers/net/wireless/ath/ath11k/debugfs.h +++ b/drivers/net/wireless/ath/ath11k/debugfs.h -@@ -226,4 +226,38 @@ static inline int ath11k_debugfs_get_fw_ - - #endif /* CPTCFG_MAC80211_DEBUGFS*/ +@@ -404,4 +404,38 @@ ath11k_debugfs_add_dbring_entry(struct a + } + #endif /* CPTCFG_ATH11K_DEBUGFS*/ +#ifdef CPTCFG_ATH11K_PKTLOG +void ath11k_init_pktlog(struct ath11k *ar); @@ -112,7 +115,7 @@ #endif /* _ATH11K_DEBUGFS_H_ */ --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -1588,8 +1588,10 @@ static int ath11k_htt_pull_ppdu_stats(st +@@ -1589,8 +1589,10 @@ static int ath11k_htt_pull_ppdu_stats(st goto exit; } @@ -124,7 +127,7 @@ ppdu_info = ath11k_dp_htt_get_ppdu_desc(ar, ppdu_id); if (!ppdu_info) { -@@ -1628,6 +1630,7 @@ static void ath11k_htt_pktlog(struct ath +@@ -1629,6 +1631,7 @@ static void ath11k_htt_pktlog(struct ath trace_ath11k_htt_pktlog(ar, data->payload, hdr->size, ar->ab->pktlog_defs_checksum); @@ -132,16 +135,16 @@ } static void ath11k_htt_backpressure_event_handler(struct ath11k_base *ab, -@@ -5076,6 +5079,8 @@ int ath11k_dp_rx_process_mon_status(stru +@@ -5189,6 +5192,8 @@ int ath11k_dp_rx_process_mon_status(stru } else if (ath11k_debugfs_is_pktlog_rx_stats_enabled(ar)) { log_type = ATH11K_PKTLOG_TYPE_RX_STATBUF; rx_buf_sz = DP_RX_BUFFER_SIZE; + ath11k_rx_stats_buf_pktlog_process(ar, skb->data, + log_type, rx_buf_sz); - } - - if (log_type) -@@ -5112,8 +5117,11 @@ int ath11k_dp_rx_process_mon_status(stru + } else { + log_type = ATH11K_PKTLOG_TYPE_INVALID; + rx_buf_sz = 0; +@@ -5229,8 +5234,11 @@ int ath11k_dp_rx_process_mon_status(stru arsta = (struct ath11k_sta *)peer->sta->drv_priv; ath11k_dp_rx_update_peer_stats(arsta, ppdu_info); @@ -762,4 +765,4 @@ +ATH11K_PKTLOG= ATH12K= ATH12K_DEBUG= - ATH12K_DEBUGFS= + ATH12K_TRACING= diff --git a/feeds/ipq95xx/mac80211/patches/qca/017-ath11k-factory-test-mode-support.patch b/feeds/ipq95xx/mac80211/patches/qca/017-ath11k-factory-test-mode-support.patch index 75c96e647..5cb4266fe 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/017-ath11k-factory-test-mode-support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/017-ath11k-factory-test-mode-support.patch @@ -1,25 +1,78 @@ +From 35a3aff175b3367684823712efa89fb7dfc46f4c Mon Sep 17 00:00:00 2001 +From: Sowmiya Sree Elavalagan +Date: Thu, 15 Oct 2020 12:43:43 +0530 +Subject: [PATCH] ath11k: factory test mode support + +Add factory test mode support. + +Device was switched to ftm mode on receiving start command from +ftm userspace add, now module param has been added to start +device in ftm mode directly.Device needs to be rebooted or +ath11k module has to be reinserted with ftm_mode unset to +bring it back to machine mode. Booting in ftm mode would +prevent loading of cal data and vap from starting. + +Command: insmod ath11k ftm_mode=1 + +Signed-off-by: Sowmiya Sree Elavalagan +--- + drivers/net/wireless/ath/ath11k/core.c | 11 +- + drivers/net/wireless/ath/ath11k/core.h | 2 + + drivers/net/wireless/ath/ath11k/debug.h | 1 + + drivers/net/wireless/ath/ath11k/mac.c | 5 + + drivers/net/wireless/ath/ath11k/qmi.c | 5 + + drivers/net/wireless/ath/ath11k/testmode.c | 276 +++++++++++++++------------ + drivers/net/wireless/ath/ath11k/testmode.h | 21 +- + drivers/net/wireless/ath/ath11k/testmode_i.h | 2 +- + drivers/net/wireless/ath/ath11k/wmi.c | 36 +++- + drivers/net/wireless/ath/ath11k/wmi.h | 20 ++ + 10 files changed, 247 insertions(+), 132 deletions(-) + --- a/drivers/net/wireless/ath/ath11k/ahb.c +++ b/drivers/net/wireless/ath/ath11k/ahb.c -@@ -699,6 +699,7 @@ static int ath11k_ahb_probe(struct platf - ab->hif.ops = &ath11k_ahb_hif_ops; +@@ -1018,6 +1018,7 @@ static int ath11k_ahb_probe(struct platf + ab->hif.ops = hif_ops; ab->pdev = pdev; - ab->hw_rev = (enum ath11k_hw_rev)of_id->data; + ab->hw_rev = hw_rev; + ab->fw_mode = ATH11K_FIRMWARE_MODE_NORMAL; - ab->mem = mem; - ab->mem_len = resource_size(mem_res); platform_set_drvdata(pdev, ab); + + ret = ath11k_pcic_register_pci_ops(ab, pci_ops); --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -1121,7 +1121,7 @@ int ath11k_core_qmi_firmware_ready(struc - set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags); +@@ -32,6 +32,10 @@ module_param_named(frame_mode, ath11k_fr + MODULE_PARM_DESC(frame_mode, + "Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)"); - mutex_lock(&ab->core_lock); -- ret = ath11k_core_start(ab, ATH11K_FIRMWARE_MODE_NORMAL); -+ ret = ath11k_core_start(ab, ab->fw_mode); ++unsigned int ath11k_ftm_mode; ++module_param_named(ftm_mode, ath11k_ftm_mode, uint, 0644); ++MODULE_PARM_DESC(ftm_mode, "Boots up in factory test mode"); ++ + static const struct ath11k_hw_params ath11k_hw_params[] = { + { + .hw_rev = ATH11K_HW_IPQ8074, +@@ -1145,6 +1149,11 @@ static int ath11k_core_soc_create(struct + { + int ret; + ++ if (ath11k_ftm_mode) { ++ ab->fw_mode = ATH11K_FIRMWARE_MODE_FTM; ++ ath11k_info(ab, "Booting in ftm mode - %d\n", ab->fw_mode); ++ } ++ + ret = ath11k_qmi_init_service(ab); if (ret) { - ath11k_err(ab, "failed to start core: %d\n", ret); - goto err_dp_free; -@@ -1277,7 +1277,8 @@ static void ath11k_core_restart(struct w + ath11k_err(ab, "failed to initialize qmi :%d\n", ret); +@@ -1371,7 +1380,7 @@ int ath11k_core_qmi_firmware_ready(struc + { + int ret; + +- ret = ath11k_core_start_firmware(ab, ATH11K_FIRMWARE_MODE_NORMAL); ++ ret = ath11k_core_start_firmware(ab, ab->fw_mode); + if (ret) { + ath11k_err(ab, "failed to start firmware: %d\n", ret); + return ret; +@@ -1536,7 +1545,8 @@ static void ath11k_core_pre_reconfigure_ for (i = 0; i < ab->num_radios; i++) { pdev = &ab->pdevs[i]; ar = pdev->ar; @@ -29,30 +82,27 @@ continue; ieee80211_stop_queues(ar->hw); -@@ -1336,6 +1337,12 @@ static void ath11k_core_restart(struct w +@@ -1599,6 +1609,9 @@ static void ath11k_core_post_reconfigure ath11k_warn(ab, "device is wedged, will not restart radio %d\n", i); break; + case ATH11K_STATE_TM: + ath11k_warn(ab, "fw mode reset done radio %d\n", i); -+ if (test_bit(ATH11K_FLAG_FW_RESTART_FOR_HOST, &ar->ab->dev_flags)) { -+ complete(&ar->fw_mode_reset); -+ } + break; } mutex_unlock(&ar->conf_mutex); } --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -204,6 +204,7 @@ enum ath11k_dev_flags { +@@ -267,6 +267,7 @@ enum ath11k_dev_flags { ATH11K_FLAG_HTC_SUSPEND_COMPLETE, ATH11K_FLAG_CE_IRQ_ENABLED, ATH11K_FLAG_EXT_IRQ_ENABLED, + ATH11K_FLAG_FW_RESTART_FOR_HOST, ATH11K_FLAG_FIXED_MEM_RGN, - }; - -@@ -415,6 +416,7 @@ enum ath11k_state { + ATH11K_FLAG_DEVICE_INIT_DONE, + ATH11K_FLAG_MULTI_MSI_VECTORS, +@@ -513,6 +514,7 @@ enum ath11k_state { ATH11K_STATE_RESTARTING, ATH11K_STATE_RESTARTED, ATH11K_STATE_WEDGED, @@ -60,7 +110,7 @@ /* Add other states as required */ }; -@@ -425,6 +427,12 @@ enum ath11k_state { +@@ -523,6 +525,12 @@ enum ath11k_state { #define ATH11K_INVALID_RSSI_EMPTY -128 @@ -73,15 +123,16 @@ struct ath11k_fw_stats { struct dentry *debugfs_fwstats; u32 pdev_id; -@@ -604,6 +612,7 @@ struct ath11k { +@@ -708,6 +716,8 @@ struct ath11k { #endif bool dfs_block_radar_events; struct ath11k_thermal thermal; + struct completion fw_mode_reset; ++ u8 ftm_msgref; u32 vdev_id_11d_scan; - struct completion finish_11d_scan; - struct completion finish_11d_ch_list; -@@ -703,6 +712,7 @@ struct ath11k_soc_dp_stats { + struct completion completed_11d_scan; + enum ath11k_11d_state state_11d; +@@ -822,6 +832,7 @@ struct ath11k_msi_config { /* Master structure to hold the hw data which may be used in core module */ struct ath11k_base { enum ath11k_hw_rev hw_rev; @@ -89,17 +140,18 @@ struct platform_device *pdev; struct device *dev; struct ath11k_qmi qmi; -@@ -789,6 +799,7 @@ struct ath11k_base { +@@ -931,6 +942,8 @@ struct ath11k_base { /* protected by data_lock */ u32 fw_crash_counter; } stats; ++ bool ftm_segment_handler; + struct ath11k_ftm_event_obj ftm_event_obj; u32 pktlog_defs_checksum; struct ath11k_dbring_cap *db_caps; --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -632,7 +632,10 @@ struct ath11k *ath11k_mac_get_ar_by_pdev +@@ -639,7 +639,10 @@ struct ath11k *ath11k_mac_get_ar_by_pdev return NULL; for (i = 0; i < ab->num_radios; i++) { @@ -111,7 +163,19 @@ if (pdev && pdev->pdev_id == pdev_id) return (pdev->ar ? pdev->ar : NULL); -@@ -5749,6 +5752,7 @@ static int ath11k_mac_op_start(struct ie +@@ -5727,6 +5730,11 @@ static int ath11k_mac_op_start(struct ie + struct ath11k_pdev *pdev = ar->pdev; + int ret; + ++ if (ath11k_ftm_mode) { ++ ath11k_err(ab, "fail to start mac operations in ftm mode\n"); ++ return -EWOULDBLOCK; ++ } ++ + ath11k_mac_drain_tx(ar); + mutex_lock(&ar->conf_mutex); + +@@ -5741,6 +5749,7 @@ static int ath11k_mac_op_start(struct ie case ATH11K_STATE_RESTARTED: case ATH11K_STATE_WEDGED: case ATH11K_STATE_ON: @@ -121,33 +185,35 @@ goto err; --- a/drivers/net/wireless/ath/ath11k/testmode.c +++ b/drivers/net/wireless/ath/ath11k/testmode.c -@@ -9,6 +9,7 @@ +@@ -9,8 +9,12 @@ #include "wmi.h" #include "hw.h" #include "core.h" +#include "hif.h" #include "testmode_i.h" ++#define FTM_SEGHDR_CURRENT_SEQ GENMASK(3, 0) ++#define FTM_SEGHDR_TOTAL_SEGMENTS GENMASK(7, 4) ++ static const struct nla_policy ath11k_tm_policy[ATH11K_TM_ATTR_MAX + 1] = { -@@ -23,34 +24,89 @@ static const struct nla_policy ath11k_tm + [ATH11K_TM_ATTR_CMD] = { .type = NLA_U32 }, + [ATH11K_TM_ATTR_DATA] = { .type = NLA_BINARY, +@@ -22,35 +26,61 @@ static const struct nla_policy ath11k_tm + /* Returns true if callee consumes the skb and the skb should be discarded. * Returns false if skb is not used. Does not sleep. ++ * Unsegmented events are handled here. Segments are aggregated in appln layer */ -bool ath11k_tm_event_wmi(struct ath11k *ar, u32 cmd_id, struct sk_buff *skb) -+bool ath11k_tm_event_wmi(struct ath11k_base *ab, u32 cmd_id, -+ struct sk_buff *skb) ++bool ath11k_wmi_tm_event_unsegmented(struct ath11k_base *ab, u32 cmd_id, ++ struct sk_buff *skb) { struct sk_buff *nl_skb; ++ struct ath11k *ar; bool consumed; - int ret; + int ret, i; -+ struct ath11k *ar; + struct ath11k_pdev *pdev; -+ u8 *buf_pos; -+ u16 datalen; -+ struct seg_hdr_info *seghdr_info; -+ u8 total_segments, current_seq; -+ u32 data_pos; - ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE, + ath11k_dbg(ab, ATH11K_DBG_TESTMODE, @@ -160,30 +226,124 @@ + for (i = 0; i < ab->num_radios; i++) { + pdev = &ab->pdevs[i]; + ar = pdev->ar; -+ if (ar && ar->state == ATH11K_STATE_TM) -+ break; ++ if (ar) { ++ mutex_lock(&ar->conf_mutex); ++ if (ar->state == ATH11K_STATE_TM) { ++ mutex_unlock(&ar->conf_mutex); ++ break; ++ } ++ mutex_unlock(&ar->conf_mutex); ++ } + } + + if (i >= ab->num_radios) { -+ ath11k_dbg(ab, ATH11K_DBG_TESTMODE, "testmode event not handled\n"); ++ ath11k_warn(ab, "testmode event not handled due to invalid pdev\n"); + return false; + } spin_lock_bh(&ar->data_lock); ++ /* Only testmode.c should be handling events from utf firmware, ++ * otherwise all sort of problems will arise as mac80211 operations ++ * are not initialised. ++ */ consumed = true; -+ seghdr_info = (struct seg_hdr_info *)(skb->data + WMI_TLV_HDR_SIZE); -+ current_seq = (seghdr_info->segmentinfo & 0xF); -+ total_segments = (seghdr_info->segmentinfo >> 4) & 0xF; + nl_skb = cfg80211_testmode_alloc_event_skb(ar->hw->wiphy, + 2 * sizeof(u32) + skb->len, + GFP_ATOMIC); + if (!nl_skb) { +- ath11k_warn(ar->ab, ++ ath11k_warn(ab, + "failed to allocate skb for testmode wmi event\n"); + goto out; + } + + ret = nla_put_u32(nl_skb, ATH11K_TM_ATTR_CMD, ATH11K_TM_CMD_WMI); + if (ret) { +- ath11k_warn(ar->ab, ++ ath11k_warn(ab, + "failed to put testmode wmi event cmd attribute: %d\n", + ret); + kfree_skb(nl_skb); +@@ -59,8 +89,8 @@ bool ath11k_tm_event_wmi(struct ath11k * + + ret = nla_put_u32(nl_skb, ATH11K_TM_ATTR_WMI_CMDID, cmd_id); + if (ret) { +- ath11k_warn(ar->ab, +- "failed to put testmode wmi even cmd_id: %d\n", ++ ath11k_warn(ab, ++ "failed to put testmode wmi event cmd_id: %d\n", + ret); + kfree_skb(nl_skb); + goto out; +@@ -68,7 +98,7 @@ bool ath11k_tm_event_wmi(struct ath11k * + + ret = nla_put(nl_skb, ATH11K_TM_ATTR_DATA, skb->len, skb->data); + if (ret) { +- ath11k_warn(ar->ab, ++ ath11k_warn(ab, + "failed to copy skb to testmode wmi event: %d\n", + ret); + kfree_skb(nl_skb); +@@ -79,7 +109,125 @@ bool ath11k_tm_event_wmi(struct ath11k * + + out: + spin_unlock_bh(&ar->data_lock); ++ return consumed; ++} + -+ datalen = skb->len - (sizeof(struct seg_hdr_info) + WMI_TLV_HDR_SIZE); -+ buf_pos = skb->data + (sizeof(struct seg_hdr_info) + WMI_TLV_HDR_SIZE); ++/* Returns true if callee consumes the skb and the skb should be discarded. ++ * Returns false if skb is not used. Does not sleep. ++ * Segmented events are hangled here. ++ * Data of various events received from fw is aggregated and ++ * sent to application layer ++ */ ++bool ath11k_process_tm_event(struct ath11k_base *ab, u32 cmd_id, ++ const struct wmi_ftm_event_msg *ftm_msg, ++ u16 length) ++{ ++ struct sk_buff *nl_skb; ++ bool consumed; ++ int ret; ++ struct ath11k *ar; ++ u8 *buf_pos; ++ u16 datalen; ++ u8 total_segments, current_seq; ++ u32 data_pos; ++ u32 pdev_id; ++ ++ ath11k_dbg(ab, ATH11K_DBG_TESTMODE, ++ "testmode event wmi cmd_id %d ftm event msg %pK datalen %d\n", ++ cmd_id, ftm_msg, length); ++ ath11k_dbg_dump(ab, ATH11K_DBG_TESTMODE, NULL, "", ftm_msg, length); ++ pdev_id = DP_HW2SW_MACID(ftm_msg->seg_hdr.pdev_id); ++ ++ if (pdev_id >= ab->num_radios) { ++ ath11k_warn(ab, "testmode event not handled due to invalid pdev id\n"); ++ return false; ++ } ++ ++ ar = ab->pdevs[pdev_id].ar; ++ if (!ar) { ++ ath11k_warn(ab, "testmode event not handled due to absence of pdev\n"); ++ return false; ++ } ++ ++ spin_lock_bh(&ar->data_lock); ++ consumed = true; ++ current_seq = FIELD_GET(FTM_SEGHDR_CURRENT_SEQ, ++ ftm_msg->seg_hdr.segmentinfo); ++ total_segments = FIELD_GET(FTM_SEGHDR_TOTAL_SEGMENTS, ++ ftm_msg->seg_hdr.segmentinfo); ++ datalen = length - (sizeof(struct wmi_ftm_seg_hdr)); ++ buf_pos = (u8 *)ftm_msg->data; + + if (current_seq == 0) { + ab->ftm_event_obj.expected_seq = 0; + ab->ftm_event_obj.data_pos = 0; + } ++ + data_pos = ab->ftm_event_obj.data_pos; + + if ((data_pos + datalen) > ATH11K_FTM_EVENT_MAX_BUF_LENGTH) { @@ -198,57 +358,61 @@ + + if (++ab->ftm_event_obj.expected_seq != total_segments) { + ab->ftm_event_obj.data_pos = data_pos; -+ ath11k_warn(ab, -+ "parial data received current_seq[%d], total_seg[%d]\n", ++ ath11k_dbg(ab, ATH11K_DBG_TESTMODE, ++ "partial data received current_seq[%d], total_seg[%d]\n", + current_seq, total_segments); + goto out; + } + -+ ath11k_warn(ab, -+ "total data length[%d] = [%d]\n", -+ data_pos, seghdr_info->len); -+ - nl_skb = cfg80211_testmode_alloc_event_skb(ar->hw->wiphy, -- 2 * sizeof(u32) + skb->len, ++ ath11k_dbg(ab, ATH11K_DBG_TESTMODE, ++ "total data length[%d] = [%d]\n", ++ data_pos, ftm_msg->seg_hdr.len); ++ nl_skb = cfg80211_testmode_alloc_event_skb(ar->hw->wiphy, + 2 * sizeof(u32) + data_pos, - GFP_ATOMIC); - if (!nl_skb) { -- ath11k_warn(ar->ab, ++ GFP_ATOMIC); ++ if (!nl_skb) { + ath11k_warn(ab, - "failed to allocate skb for testmode wmi event\n"); - goto out; - } - -- ret = nla_put_u32(nl_skb, ATH11K_TM_ATTR_CMD, ATH11K_TM_CMD_WMI); -+ ret = nla_put_u32(nl_skb, ATH11K_TM_ATTR_CMD, ATH11K_TM_CMD_WMI_FTM); - if (ret) { -- ath11k_warn(ar->ab, ++ "failed to allocate skb for testmode wmi event\n"); ++ goto out; ++ } ++ ++ ret = nla_put_u32(nl_skb, ATH11K_TM_ATTR_CMD, ++ ATH11K_TM_CMD_WMI_FTM); ++ if (ret) { + ath11k_warn(ab, - "failed to put testmode wmi event cmd attribute: %d\n", - ret); - kfree_skb(nl_skb); -@@ -59,16 +115,17 @@ bool ath11k_tm_event_wmi(struct ath11k * - - ret = nla_put_u32(nl_skb, ATH11K_TM_ATTR_WMI_CMDID, cmd_id); - if (ret) { -- ath11k_warn(ar->ab, ++ "failed to put testmode wmi event cmd attribute: %d\n", ++ ret); ++ kfree_skb(nl_skb); ++ goto out; ++ } ++ ++ ret = nla_put_u32(nl_skb, ATH11K_TM_ATTR_WMI_CMDID, cmd_id); ++ if (ret) { + ath11k_warn(ab, - "failed to put testmode wmi even cmd_id: %d\n", - ret); - kfree_skb(nl_skb); - goto out; - } - -- ret = nla_put(nl_skb, ATH11K_TM_ATTR_DATA, skb->len, skb->data); ++ "failed to put testmode wmi even cmd_id: %d\n", ++ ret); ++ kfree_skb(nl_skb); ++ goto out; ++ } ++ + ret = nla_put(nl_skb, ATH11K_TM_ATTR_DATA, data_pos, + &ab->ftm_event_obj.eventdata[0]); - if (ret) { -- ath11k_warn(ar->ab, ++ if (ret) { + ath11k_warn(ab, - "failed to copy skb to testmode wmi event: %d\n", - ret); - kfree_skb(nl_skb); -@@ -115,6 +172,107 @@ static int ath11k_tm_cmd_get_version(str ++ "failed to copy skb to testmode wmi event: %d\n", ++ ret); ++ kfree_skb(nl_skb); ++ goto out; ++ } ++ ++ cfg80211_testmode_event(nl_skb, GFP_ATOMIC); + ++out: ++ spin_unlock_bh(&ar->data_lock); + return consumed; + } + +@@ -115,6 +263,41 @@ static int ath11k_tm_cmd_get_version(str return cfg80211_testmode_reply(skb); } @@ -257,7 +421,6 @@ + int ret; + + ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE, " enter testmode cmd fw start\n"); -+ + mutex_lock(&ar->conf_mutex); + + if (ar->state == ATH11K_STATE_TM) { @@ -271,92 +434,47 @@ + goto err; + } + -+ /* Firmware already running in FTM mode */ -+ if (ar->ab->fw_mode == ATH11K_FIRMWARE_MODE_FTM) { -+ ar->state = ATH11K_STATE_TM; -+ ret = 0; -+ goto err; -+ } -+ ar->ab->ftm_event_obj.eventdata = kzalloc(ATH11K_FTM_EVENT_MAX_BUF_LENGTH, -+ GFP_KERNEL); ++ ar->ab->ftm_event_obj.eventdata = ++ kzalloc(ATH11K_FTM_EVENT_MAX_BUF_LENGTH, GFP_KERNEL); + if (!ar->ab->ftm_event_obj.eventdata) { + ret = -ENOMEM; + goto err; + } + -+ ar->ab->fw_mode = ATH11K_FIRMWARE_MODE_FTM; + ar->state = ATH11K_STATE_TM; ++ ar->ftm_msgref = 0; + mutex_unlock(&ar->conf_mutex); -+ init_completion(&ar->fw_mode_reset); -+ -+ set_bit(ATH11K_FLAG_FW_RESTART_FOR_HOST, &ar->ab->dev_flags); -+ ath11k_hif_power_down(ar->ab); -+ ath11k_hif_power_up(ar->ab); -+ -+ if (!wait_for_completion_timeout(&ar->fw_mode_reset, -+ FTM_MODE_RESET_TIMEOUT_HZ)) { -+ clear_bit(ATH11K_FLAG_FW_RESTART_FOR_HOST, &ar->ab->dev_flags); -+ ath11k_warn(ar->ab, "failed to restat the core in ftm mode\n"); -+ return 0; -+ } -+ clear_bit(ATH11K_FLAG_FW_RESTART_FOR_HOST, &ar->ab->dev_flags); + ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE, " enter testmode cmd started\n"); -+ + return 0; +err: + mutex_unlock(&ar->conf_mutex); + return ret; +} -+ -+static int ath11k_tm_cmd_testmode_stop(struct ath11k *ar, struct nlattr *tb[]) -+{ -+ int ret; -+ -+ ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE, "Enter testmode cmd fw stop\n"); -+ -+ mutex_lock(&ar->conf_mutex); -+ -+ if (ar->state != ATH11K_STATE_TM) { -+ ret = -ENETDOWN; -+ goto out; -+ } -+ -+ /* Firmware not running in FTM mode */ -+ if (ar->ab->fw_mode != ATH11K_FIRMWARE_MODE_FTM) { -+ ar->state = ATH11K_STATE_OFF; -+ ret = 0; -+ goto out; -+ } -+ -+ ar->ab->fw_mode = ATH11K_FIRMWARE_MODE_NORMAL; -+ mutex_unlock(&ar->conf_mutex); -+ init_completion(&ar->fw_mode_reset); -+ -+ set_bit(ATH11K_FLAG_FW_RESTART_FOR_HOST, &ar->ab->dev_flags); -+ ath11k_hif_power_down(ar->ab); -+ ath11k_hif_power_up(ar->ab); -+ -+ if (!wait_for_completion_timeout(&ar->fw_mode_reset, -+ FTM_MODE_RESET_TIMEOUT_HZ)) { -+ clear_bit(ATH11K_FLAG_FW_RESTART_FOR_HOST, &ar->ab->dev_flags); -+ ath11k_warn(ar->ab, "failed to restat the core in ftm mode\n"); -+ return 0; -+ } -+ -+ ar->state = ATH11K_STATE_OFF; -+ clear_bit(ATH11K_FLAG_FW_RESTART_FOR_HOST, &ar->ab->dev_flags); -+ kfree(ar->ab->ftm_event_obj.eventdata); -+ ath11k_info(ar->ab, "UTF firmware stopped\n"); -+ return 0; -+out: -+ mutex_unlock(&ar->conf_mutex); -+ return ret; -+} + static int ath11k_tm_cmd_wmi(struct ath11k *ar, struct nlattr *tb[]) { struct ath11k_pdev_wmi *wmi = ar->wmi; -@@ -173,8 +331,95 @@ out: +@@ -125,11 +308,6 @@ static int ath11k_tm_cmd_wmi(struct ath1 + + mutex_lock(&ar->conf_mutex); + +- if (ar->state != ATH11K_STATE_ON) { +- ret = -ENETDOWN; +- goto out; +- } +- + if (!tb[ATH11K_TM_ATTR_DATA]) { + ret = -EINVAL; + goto out; +@@ -165,7 +343,6 @@ static int ath11k_tm_cmd_wmi(struct ath1 + ret); + goto out; + } +- + ret = 0; + + out: +@@ -173,10 +350,92 @@ out: return ret; } @@ -364,19 +482,16 @@ +{ + struct ath11k_pdev_wmi *wmi = ar->wmi; + struct sk_buff *skb; -+ u32 cmd_id, buf_len; ++ u32 cmd_id, buf_len, hdr_info; + int ret; + void *buf; -+ u8 *cmd; + /* if buf_len is 0 no data is sent, return error */ -+ static u8 msgref = 1; + u8 segnumber = 0, seginfo; + u16 chunk_len, total_bytes, num_segments; + u8 *bufpos; -+ struct seg_hdr_info seg_hdr; ++ struct wmi_ftm_cmd *ftm_cmd; + + mutex_lock(&ar->conf_mutex); -+ + ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE, "ar->state %d\n", ar->state); + + if (ar->state != ATH11K_STATE_TM) { @@ -392,12 +507,10 @@ + buf = nla_data(tb[ATH11K_TM_ATTR_DATA]); + buf_len = nla_len(tb[ATH11K_TM_ATTR_DATA]); + cmd_id = WMI_PDEV_UTF_CMDID; -+ + ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE, + "testmode cmd wmi cmd_id %d buf %pK buf_len %d\n", + cmd_id, buf, buf_len); + ath11k_dbg_dump(ar->ab, ATH11K_DBG_TESTMODE, NULL, "", buf, buf_len); -+ + bufpos = buf; + total_bytes = buf_len; + num_segments = total_bytes / MAX_WMI_UTF_LEN; @@ -411,27 +524,25 @@ + else + chunk_len = buf_len; + -+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, -+ (chunk_len + sizeof(seg_hdr) + -+ WMI_TLV_HDR_SIZE)); ++ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, (chunk_len + ++ sizeof(struct wmi_ftm_cmd))); + if (!skb) { + ret = -ENOMEM; + goto out; + } + -+ seg_hdr.len = total_bytes; -+ seg_hdr.msgref = msgref; -+ seginfo = ((num_segments << 4) & 0xF0) | (segnumber & 0xF); -+ seg_hdr.segmentinfo = seginfo; -+ seg_hdr.pad = 0; ++ ftm_cmd = (struct wmi_ftm_cmd *)skb->data; ++ hdr_info = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_BYTE) | ++ FIELD_PREP(WMI_TLV_LEN, (chunk_len + ++ sizeof(struct wmi_ftm_seg_hdr))); ++ ftm_cmd->tlv_header = hdr_info; ++ ftm_cmd->seg_hdr.len = total_bytes; ++ ftm_cmd->seg_hdr.msgref = ar->ftm_msgref; ++ seginfo = FIELD_PREP(FTM_SEGHDR_TOTAL_SEGMENTS, num_segments) | ++ FIELD_PREP(FTM_SEGHDR_CURRENT_SEQ, segnumber); ++ ftm_cmd->seg_hdr.segmentinfo = seginfo; + segnumber++; -+ -+ cmd = (uint8_t *)skb->data; -+ WMITLV_SET_HDR(cmd, WMITLV_TAG_BYTE, (chunk_len + sizeof(seg_hdr))); -+ cmd += WMI_TLV_HDR_SIZE; -+ memcpy(cmd, &seg_hdr, sizeof(seg_hdr)); -+ memcpy(&cmd[sizeof(seg_hdr)], bufpos, chunk_len); -+ ++ memcpy(&ftm_cmd->data, bufpos, chunk_len); + ret = ath11k_wmi_cmd_send(wmi, skb, cmd_id); + if (ret) { + ath11k_warn(ar->ab, "ftm wmi command fail: %d\n", ret); @@ -441,6 +552,7 @@ + buf_len -= chunk_len; + bufpos += chunk_len; + } ++ ++ar->ftm_msgref; + ret = 0; +out: + mutex_unlock(&ar->conf_mutex); @@ -452,31 +564,38 @@ + void *data, int len) { struct ath11k *ar = hw->priv; ++ struct ath11k_base *ab = ar->ab; struct nlattr *tb[ATH11K_TM_ATTR_MAX + 1]; -@@ -189,9 +434,15 @@ int ath11k_tm_cmd(struct ieee80211_hw *h + int ret; + +@@ -189,10 +448,18 @@ int ath11k_tm_cmd(struct ieee80211_hw *h return -EINVAL; switch (nla_get_u32(tb[ATH11K_TM_ATTR_CMD])) { -+ case ATH11K_TM_CMD_WMI_FTM: -+ return ath11k_tm_cmd_process_ftm(ar, tb); ++ case ATH11K_TM_CMD_WMI: ++ ab->ftm_segment_handler = 0; ++ return ath11k_tm_cmd_wmi(ar, tb, vif); + case ATH11K_TM_CMD_TESTMODE_START: + return ath11k_tm_cmd_testmode_start(ar, tb); -+ case ATH11K_TM_CMD_TESTMODE_STOP: -+ return ath11k_tm_cmd_testmode_stop(ar, tb); case ATH11K_TM_CMD_GET_VERSION: return ath11k_tm_cmd_get_version(ar, tb); - case ATH11K_TM_CMD_WMI: -+ case ATH11K_TM_CMD_WMI_FW_TEST: - return ath11k_tm_cmd_wmi(ar, tb); +- return ath11k_tm_cmd_wmi(ar, tb); ++ case ATH11K_TM_CMD_WMI_FTM: ++ ab->ftm_segment_handler = 1; ++ return ath11k_tm_cmd_process_ftm(ar, tb); ++ case ATH11K_TM_CMD_TESTMODE_STOP: ++ return 0; default: return -EOPNOTSUPP; + } --- a/drivers/net/wireless/ath/ath11k/testmode.h +++ b/drivers/net/wireless/ath/ath11k/testmode.h -@@ -4,16 +4,33 @@ +@@ -4,17 +4,46 @@ */ #include "core.h" -+#include "ahb.h" ++#include "hif.h" + +#define MAX_WMI_UTF_LEN 252 +#define WMI_TLV_HDR_SIZE 4 @@ -496,18 +615,32 @@ #ifdef CPTCFG_NL80211_TESTMODE -bool ath11k_tm_event_wmi(struct ath11k *ar, u32 cmd_id, struct sk_buff *skb); -+bool ath11k_tm_event_wmi(struct ath11k_base *ab, u32 cmd_id, -+ struct sk_buff *skb); ++bool ath11k_wmi_tm_event_unsegmented(struct ath11k_base *ab, u32 cmd_id, ++ struct sk_buff *skb); ++ ++bool ath11k_process_tm_event(struct ath11k_base *ab, u32 cmd_id, ++ const struct wmi_ftm_event_msg *ftm_msg, ++ u16 length); ++ int ath11k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void *data, int len); #else ++static inline bool ath11k_wmi_tm_event_unsegmented(struct ath11k_base *ab, ++ u32 cmd_id, ++ struct sk_buff *skb) ++{ ++ return false; ++} -static inline bool ath11k_tm_event_wmi(struct ath11k *ar, u32 cmd_id, -+static inline bool ath11k_tm_event_wmi(struct ath11k_base *ab, u32 cmd_id, - struct sk_buff *skb) +- struct sk_buff *skb) ++static inline bool ath11k_process_tm_event(struct ath11k_base *ab, u32 cmd_id, ++ const struct wmi_ftm_event_msg *msg, ++ u16 length) { return false; + } --- a/drivers/net/wireless/ath/ath11k/testmode_i.h +++ b/drivers/net/wireless/ath/ath11k/testmode_i.h @@ -14,6 +14,7 @@ @@ -541,7 +674,7 @@ * ATH11K_TM_ATTR_DATA. */ - ATH11K_TM_CMD_WMI = 1, -+ ATH11K_TM_CMD_WMI_FW_TEST = 3, ++ ATH11K_TM_CMD_WMI = 3, + + /* The command used to transmit a FTM WMI command to the firmware + * and the event to receive WMI events from the firmware.The data @@ -553,7 +686,7 @@ }; --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -18,6 +18,7 @@ +@@ -19,6 +19,7 @@ #include "mac.h" #include "hw.h" #include "peer.h" @@ -561,19 +694,60 @@ struct wmi_tlv_policy { size_t min_len; -@@ -7631,6 +7632,9 @@ static void ath11k_wmi_tlv_op_rx(struct - case WMI_OBSS_COLOR_COLLISION_DETECTION_EVENTID: - ath11k_wmi_obss_color_collision_event(ab, skb); +@@ -7564,6 +7565,37 @@ exit: + kfree(tb); + } + ++static void ath11k_wmi_tm_event_segmented(struct ath11k_base *ab, u32 cmd_id, ++ struct sk_buff *skb) ++{ ++ const void **tb; ++ const struct wmi_ftm_event_msg *ev; ++ u16 length; ++ int ret; ++ bool consumed; ++ ++ tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); ++ if (IS_ERR(tb)) { ++ ret = PTR_ERR(tb); ++ ath11k_warn(ab, "failed to parse ftm event tlv: %d\n", ret); ++ return; ++ } ++ ++ ev = tb[WMI_TAG_ARRAY_BYTE]; ++ if (!ev) { ++ ath11k_warn(ab, "failed to fetch ftm msg\n"); ++ kfree(tb); ++ return; ++ } ++ ++ length = skb->len - TLV_HDR_SIZE; ++ consumed = ath11k_process_tm_event(ab, cmd_id, ev, length); ++ if (!consumed) ++ ath11k_warn(ab, "Failed to process ftm event\n"); ++ ++ kfree(tb); ++} ++ + static void + ath11k_wmi_pdev_temperature_event(struct ath11k_base *ab, + struct sk_buff *skb) +@@ -7934,6 +7966,12 @@ static void ath11k_wmi_tlv_op_rx(struct + case WMI_TWT_ADD_DIALOG_EVENTID: + ath11k_wmi_twt_add_dialog_event(ab, skb); break; + case WMI_PDEV_UTF_EVENTID: -+ ath11k_tm_event_wmi(ab, id, skb); ++ if (ab->ftm_segment_handler) ++ ath11k_wmi_tm_event_segmented(ab, id, skb); ++ else ++ ath11k_wmi_tm_event_unsegmented(ab, id, skb); + break; /* add Unsupported events here */ case WMI_TBTTOFFSET_EXT_UPDATE_EVENTID: case WMI_PEER_OPER_MODE_CHANGE_EVENTID: --- a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c +++ b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c -@@ -4563,7 +4563,8 @@ static int ath11k_open_htt_stats(struct +@@ -4649,7 +4649,8 @@ static int ath11k_open_htt_stats(struct mutex_lock(&ar->conf_mutex); @@ -583,3 +757,64 @@ ret = -ENETDOWN; goto err_unlock; } +--- a/drivers/net/wireless/ath/ath11k/wow.c ++++ b/drivers/net/wireless/ath/ath11k/wow.c +@@ -831,6 +831,7 @@ exit: + case ATH11K_STATE_RESTARTING: + case ATH11K_STATE_RESTARTED: + case ATH11K_STATE_WEDGED: ++ case ATH11K_STATE_TM: + ath11k_warn(ar->ab, "encountered unexpected device state %d on resume, cannot recover\n", + ar->state); + ret = -EIO; +--- a/drivers/net/wireless/ath/ath11k/debug.h ++++ b/drivers/net/wireless/ath/ath11k/debug.h +@@ -33,6 +33,7 @@ __printf(2, 3) void ath11k_err(struct at + __printf(2, 3) void ath11k_warn(struct ath11k_base *ab, const char *fmt, ...); + + extern unsigned int ath11k_debug_mask; ++extern unsigned int ath11k_ftm_mode; + + #ifdef CPTCFG_ATH11K_DEBUG + __printf(3, 4) void __ath11k_dbg(struct ath11k_base *ab, +--- a/drivers/net/wireless/ath/ath11k/thermal.c ++++ b/drivers/net/wireless/ath/ath11k/thermal.c +@@ -70,7 +70,8 @@ static ssize_t ath11k_thermal_show_temp( + mutex_lock(&ar->conf_mutex); + + /* Can't get temperature when the card is off */ +- if (ar->state != ATH11K_STATE_ON) { ++ if (ar->state != ATH11K_STATE_ON && ++ ar->ab->fw_mode != ATH11K_FIRMWARE_MODE_FTM) { + ret = -ENETDOWN; + goto out; + } +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -3508,6 +3508,26 @@ struct wmi_get_pdev_temperature_cmd { + u32 pdev_id; + } __packed; + ++#define MAX_WMI_UTF_LEN 252 ++ ++struct wmi_ftm_seg_hdr { ++ u32 len; ++ u32 msgref; ++ u32 segmentinfo; ++ u32 pdev_id; ++} __packed; ++ ++struct wmi_ftm_cmd { ++ u32 tlv_header; ++ struct wmi_ftm_seg_hdr seg_hdr; ++ u8 data[]; ++}; ++ ++struct wmi_ftm_event_msg { ++ struct wmi_ftm_seg_hdr seg_hdr; ++ u8 data[]; ++}; ++ + #define WMI_BEACON_TX_BUFFER_SIZE 512 + + struct wmi_bcn_tmpl_cmd { diff --git a/feeds/ipq95xx/mac80211/patches/qca/020-ath11k-add-btcoex-config.patch b/feeds/ipq95xx/mac80211/patches/qca/020-ath11k-add-btcoex-config.patch index 7bb0fab6e..7fe99d70d 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/020-ath11k-add-btcoex-config.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/020-ath11k-add-btcoex-config.patch @@ -4,15 +4,15 @@ peer.o \ dbring.o \ hw.o \ -- wow.o -+ wow.o \ +- pcic.o ++ pcic.o \ + vendor.o ath11k-$(CPTCFG_ATH11K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o ath11k-$(CPTCFG_NL80211_TESTMODE) += testmode.o --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -476,6 +476,16 @@ struct ath11k_per_peer_tx_stats { +@@ -588,6 +588,16 @@ struct ath11k_per_peer_tx_stats { #define ATH11K_FLUSH_TIMEOUT (5 * HZ) #define ATH11K_VDEV_DELETE_TIMEOUT_HZ (5 * HZ) @@ -29,7 +29,7 @@ struct ath11k { struct ath11k_base *ab; struct ath11k_pdev *pdev; -@@ -593,6 +603,8 @@ struct ath11k { +@@ -707,6 +717,8 @@ struct ath11k { struct ath11k_per_peer_tx_stats cached_stats; u32 last_ppdu_id; u32 cached_ppdu_id; @@ -40,24 +40,24 @@ struct ath11k_debug debug; --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -6,6 +6,7 @@ - - #include +@@ -8,6 +8,7 @@ #include + #include + #include +#include - #include "mac.h" - #include "core.h" - #include "debug.h" -@@ -16,6 +17,7 @@ - #include "testmode.h" - #include "peer.h" + #include + #include + +@@ -23,6 +24,7 @@ #include "debugfs_sta.h" + #include "hif.h" + #include "wow.h" +#include "vendor.h" #define CHAN2G(_channel, _freq, _flags) { \ .band = NL80211_BAND_2GHZ, \ -@@ -7602,6 +7604,91 @@ static void ath11k_mac_op_sta_statistics - sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL); +@@ -8428,6 +8430,91 @@ exit: + return ret; } +#define ATH11K_WLAN_PRIO_MAX 0x63 @@ -148,7 +148,7 @@ static const struct ieee80211_ops ath11k_ops = { .tx = ath11k_mac_op_tx, .start = ath11k_mac_op_start, -@@ -7822,6 +7909,56 @@ static int ath11k_mac_setup_iface_combin +@@ -8664,6 +8751,56 @@ static int ath11k_mac_setup_iface_combin return 0; } @@ -205,7 +205,7 @@ static const u8 ath11k_if_types_ext_capa[] = { [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING, [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF, -@@ -8027,6 +8164,7 @@ static int __ath11k_mac_register(struct +@@ -8900,6 +9037,7 @@ static int __ath11k_mac_register(struct } ath11k_reg_init(ar); @@ -213,7 +213,7 @@ if (!test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) { ar->hw->netdev_features = NETIF_F_HW_CSUM; -@@ -8157,6 +8295,7 @@ int ath11k_mac_allocate(struct ath11k_ba +@@ -9053,6 +9191,7 @@ int ath11k_mac_allocate(struct ath11k_ba */ ath11k_wmi_pdev_attach(ab, i); @@ -223,7 +223,7 @@ ar->num_tx_chains = get_num_chains(pdev->cap.tx_chain_mask); --- a/drivers/net/wireless/ath/ath11k/mac.h +++ b/drivers/net/wireless/ath/ath11k/mac.h -@@ -142,8 +142,9 @@ void __ath11k_mac_scan_finish(struct ath +@@ -150,8 +150,9 @@ void __ath11k_mac_scan_finish(struct ath void ath11k_mac_scan_finish(struct ath11k *ar); struct ath11k_vif *ath11k_mac_get_arvif(struct ath11k *ar, u32 vdev_id); @@ -447,7 +447,7 @@ +#endif /* QCA_VENDOR_H */ --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -1536,6 +1536,71 @@ int ath11k_wmi_vdev_set_param_cmd(struct +@@ -1570,6 +1570,71 @@ int ath11k_wmi_vdev_set_param_cmd(struct return ret; } @@ -521,7 +521,7 @@ { --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -4839,6 +4839,79 @@ struct wmi_wmm_params_arg { +@@ -4903,6 +4903,79 @@ struct wmi_wmm_params_arg { u8 no_ack; }; @@ -601,7 +601,7 @@ struct wmi_vdev_set_wmm_params_cmd { u32 tlv_header; u32 vdev_id; -@@ -5469,6 +5542,8 @@ int ath11k_wmi_pdev_non_srg_obss_color_e +@@ -6061,6 +6134,8 @@ int ath11k_wmi_pdev_non_srg_obss_color_e u32 *bitmap); int ath11k_wmi_pdev_non_srg_obss_bssid_enable_bitmap(struct ath11k *ar, u32 *bitmap); diff --git a/feeds/ipq95xx/mac80211/patches/qca/022-ath11k-add-ap-ps-support.patch b/feeds/ipq95xx/mac80211/patches/qca/022-ath11k-add-ap-ps-support.patch index c884cd224..38f381ab5 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/022-ath11k-add-ap-ps-support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/022-ath11k-add-ap-ps-support.patch @@ -1,14 +1,14 @@ --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -24,6 +24,7 @@ - #include "thermal.h" +@@ -30,6 +30,7 @@ #include "dbring.h" #include "spectral.h" + #include "wow.h" +#include "vendor.h" #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK) -@@ -495,6 +496,11 @@ struct ath11k_coex_info { +@@ -598,6 +599,11 @@ struct ath11k_coex_info { u32 pta_priority; }; @@ -20,18 +20,18 @@ struct ath11k { struct ath11k_base *ab; struct ath11k_pdev *pdev; -@@ -625,6 +631,8 @@ struct ath11k { - bool dfs_block_radar_events; +@@ -730,6 +736,8 @@ struct ath11k { struct ath11k_thermal thermal; struct completion fw_mode_reset; + u8 ftm_msgref; + int ap_ps_enabled; + enum ath11k_ap_ps_state ap_ps_state; u32 vdev_id_11d_scan; - struct completion finish_11d_scan; - struct completion finish_11d_ch_list; + struct completion completed_11d_scan; + enum ath11k_11d_state state_11d; --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -4390,6 +4390,33 @@ static void ath11k_mac_dec_num_stations( +@@ -4410,6 +4410,33 @@ static void ath11k_mac_dec_num_stations( ar->num_stations--; } @@ -65,7 +65,7 @@ static int ath11k_mac_station_add(struct ath11k *ar, struct ieee80211_vif *vif, struct ieee80211_sta *sta) -@@ -4429,6 +4456,12 @@ static int ath11k_mac_station_add(struct +@@ -4449,6 +4476,12 @@ static int ath11k_mac_station_add(struct ath11k_dbg(ab, ATH11K_DBG_MAC, "Added peer: %pM for VDEV: %d\n", sta->addr, arvif->vdev_id); @@ -78,7 +78,7 @@ if (ath11k_debugfs_is_extd_tx_stats_enabled(ar)) { arsta->tx_stats = kzalloc(sizeof(*arsta->tx_stats), GFP_KERNEL); if (!arsta->tx_stats) { -@@ -4552,6 +4585,9 @@ static int ath11k_mac_op_sta_state(struc +@@ -4576,6 +4609,9 @@ static int ath11k_mac_op_sta_state(struc kfree(arsta->tx_stats); arsta->tx_stats = NULL; @@ -88,7 +88,7 @@ kfree(arsta->rx_stats); arsta->rx_stats = NULL; -@@ -5877,6 +5913,7 @@ static void ath11k_mac_op_stop(struct ie +@@ -5874,6 +5910,7 @@ static void ath11k_mac_op_stop(struct ie clear_bit(ATH11K_CAC_RUNNING, &ar->dev_flags); ar->state = ATH11K_STATE_OFF; @@ -96,7 +96,7 @@ mutex_unlock(&ar->conf_mutex); cancel_delayed_work_sync(&ar->scan.timeout); -@@ -6245,7 +6282,6 @@ static int ath11k_mac_op_add_interface(s +@@ -6248,7 +6285,6 @@ static int ath11k_mac_op_add_interface(s arvif->vdev_id, ret); goto err; } @@ -104,9 +104,9 @@ ar->num_created_vdevs++; ath11k_dbg(ab, ATH11K_DBG_MAC, "vdev %pM created, vdev_id %d\n", vif->addr, arvif->vdev_id); -@@ -6363,6 +6399,10 @@ static int ath11k_mac_op_add_interface(s - } - } +@@ -6372,6 +6408,10 @@ static int ath11k_mac_op_add_interface(s + if (ret) + goto err_peer_del; + ret = ath11k_mac_ap_ps_recalc(ar); + if (ret) @@ -121,11 +121,11 @@ ath11k_mac_txpower_recalc(ar); + ath11k_mac_ap_ps_recalc(ar); - /* TODO: recal traffic pause state based on the available vdevs */ + ath11k_debugfs_remove_interface(arvif); --- a/drivers/net/wireless/ath/ath11k/mac.h +++ b/drivers/net/wireless/ath/ath11k/mac.h -@@ -134,6 +134,7 @@ void ath11k_mac_11d_scan_start(struct at +@@ -135,6 +135,7 @@ void ath11k_mac_11d_scan_start(struct at void ath11k_mac_11d_scan_stop(struct ath11k *ar); void ath11k_mac_11d_scan_stop_all(struct ath11k_base *ab); @@ -260,7 +260,7 @@ * enum qca_wlan_vendor_attr_btcoex_config - Used by the vendor command --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -1258,6 +1258,38 @@ ath11k_wmi_rx_reord_queue_remove(struct +@@ -1276,6 +1276,38 @@ ath11k_wmi_rx_reord_queue_remove(struct return ret; } @@ -301,7 +301,7 @@ { --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -2990,6 +2990,12 @@ struct set_fwtest_params { +@@ -3005,6 +3005,12 @@ struct set_fwtest_params { u32 value; }; @@ -314,7 +314,7 @@ struct wmi_fwtest_set_param_cmd_param { u32 tlv_header; u32 param_id; -@@ -5633,6 +5639,7 @@ int ath11k_wmi_pdev_non_srg_obss_bssid_e +@@ -6156,6 +6162,7 @@ int ath11k_wmi_pdev_non_srg_obss_bssid_e u32 *bitmap); int ath11k_send_coex_config_cmd(struct ath11k *ar, struct coex_config_arg *coex_config); diff --git a/feeds/ipq95xx/mac80211/patches/qca/031-ath11k-print-stats-on-crash.patch b/feeds/ipq95xx/mac80211/patches/qca/031-ath11k-print-stats-on-crash.patch index b38116d3b..770df7e57 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/031-ath11k-print-stats-on-crash.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/031-ath11k-print-stats-on-crash.patch @@ -5,10 +5,10 @@ #include #include +#include + #include "core.h" #include "dp_tx.h" - #include "dp_rx.h" -@@ -31,6 +32,16 @@ module_param_named(frame_mode, ath11k_fr +@@ -32,6 +33,16 @@ module_param_named(frame_mode, ath11k_fr MODULE_PARM_DESC(frame_mode, "Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)"); @@ -25,7 +25,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { { .hw_rev = ATH11K_HW_IPQ8074, -@@ -1087,6 +1098,127 @@ static int ath11k_core_rfkill_config(str +@@ -1367,6 +1378,127 @@ static int ath11k_core_start_firmware(st return ret; } @@ -153,15 +153,15 @@ int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab) { int ret; -@@ -1132,6 +1264,7 @@ int ath11k_core_qmi_firmware_ready(struc +@@ -1418,6 +1550,7 @@ int ath11k_core_qmi_firmware_ready(struc ath11k_err(ab, "failed to create pdev core: %d\n", ret); goto err_core_stop; } + ath11k_hif_irq_enable(ab); + mutex_unlock(&ab->core_lock); - ret = ath11k_core_rfkill_config(ab); -@@ -1391,6 +1524,14 @@ int ath11k_core_init(struct ath11k_base +@@ -1745,6 +1878,14 @@ int ath11k_core_init(struct ath11k_base { int ret; @@ -176,7 +176,7 @@ ret = ath11k_core_soc_create(ab); if (ret) { ath11k_err(ab, "failed to create soc core: %d\n", ret); -@@ -1413,6 +1554,14 @@ void ath11k_core_deinit(struct ath11k_ba +@@ -1767,6 +1908,14 @@ void ath11k_core_deinit(struct ath11k_ba ath11k_hif_power_down(ab); ath11k_mac_destroy(ab); ath11k_core_soc_destroy(ab); @@ -191,8 +191,8 @@ } EXPORT_SYMBOL(ath11k_core_deinit); -@@ -1430,6 +1579,8 @@ struct ath11k_base *ath11k_core_alloc(st - const struct ath11k_bus_params *bus_params) +@@ -1783,6 +1932,8 @@ struct ath11k_base *ath11k_core_alloc(st + enum ath11k_bus bus) { struct ath11k_base *ab; + static atomic_t num_soc = ATOMIC_INIT(0); @@ -200,7 +200,7 @@ ab = kzalloc(sizeof(*ab) + priv_size, GFP_KERNEL); if (!ab) -@@ -1449,6 +1600,9 @@ struct ath11k_base *ath11k_core_alloc(st +@@ -1810,6 +1961,9 @@ struct ath11k_base *ath11k_core_alloc(st init_waitqueue_head(&ab->peer_mapping_wq); init_waitqueue_head(&ab->wmi_ab.tx_credits_wq); init_waitqueue_head(&ab->qmi.cold_boot_waitq); @@ -209,10 +209,10 @@ +#endif INIT_WORK(&ab->restart_work, ath11k_core_restart); INIT_WORK(&ab->update_11d_work, ath11k_update_11d); - INIT_WORK(&ab->rfkill_work, ath11k_rfkill_work); -@@ -1459,6 +1613,10 @@ struct ath11k_base *ath11k_core_alloc(st + INIT_WORK(&ab->reset_work, ath11k_core_reset); +@@ -1819,6 +1973,10 @@ struct ath11k_base *ath11k_core_alloc(st + ab->dev = dev; - ab->bus_params = *bus_params; ab->hif.bus = bus; + soc_idx = atomic_inc_return(&num_soc); + /* dec soc_idx to start from 0 */ @@ -223,7 +223,7 @@ --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -751,8 +751,8 @@ static int ath11k_fill_bp_stats(struct a +@@ -794,8 +794,8 @@ static int ath11k_fill_bp_stats(struct a return len; } @@ -236,7 +236,7 @@ bool stats_rxd = false; --- a/drivers/net/wireless/ath/ath11k/debugfs.h +++ b/drivers/net/wireless/ath/ath11k/debugfs.h -@@ -117,6 +117,8 @@ void ath11k_debugfs_unregister(struct at +@@ -272,6 +272,8 @@ void ath11k_debugfs_unregister(struct at void ath11k_debugfs_fw_stats_process(struct ath11k_base *ab, struct sk_buff *skb); void ath11k_debugfs_fw_stats_init(struct ath11k *ar); @@ -245,8 +245,8 @@ int ath11k_debugfs_get_fw_stats(struct ath11k *ar, u32 pdev_id, u32 vdev_id, u32 stats_id); -@@ -152,6 +154,12 @@ static inline int ath11k_debugfs_rx_filt - } +@@ -314,6 +316,12 @@ void ath11k_debugfs_add_dbring_entry(str + struct hal_srng *srng); #else +ssize_t ath11k_debugfs_dump_soc_ring_bp_stats(struct ath11k_base *ab, @@ -260,7 +260,7 @@ return 0; --- a/drivers/net/wireless/ath/ath11k/qmi.h +++ b/drivers/net/wireless/ath/ath11k/qmi.h -@@ -7,7 +7,9 @@ +@@ -8,7 +8,9 @@ #define ATH11K_QMI_H #include @@ -270,7 +270,7 @@ #define ATH11K_HOST_VERSION_STRING "WIN" #define ATH11K_QMI_WLANFW_TIMEOUT_MS 10000 -@@ -124,6 +126,7 @@ struct ath11k_qmi { +@@ -130,6 +132,7 @@ struct ath11k_qmi { struct workqueue_struct *event_wq; struct list_head event_list; spinlock_t event_lock; /* spinlock for qmi event list */ @@ -280,8 +280,8 @@ u32 mem_seg_count; --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -26,6 +26,11 @@ - #include "spectral.h" +@@ -32,6 +32,11 @@ + #include "wow.h" #include "vendor.h" +#ifdef CONFIG_QCOM_QMI_HELPERS @@ -292,16 +292,16 @@ #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK) #define ATH11K_TX_MGMT_NUM_PENDING_MAX 512 -@@ -42,6 +47,8 @@ extern unsigned int ath11k_frame_mode; - - #define ATH11K_MON_TIMER_INTERVAL 10 +@@ -65,6 +70,8 @@ extern unsigned int ath11k_frame_mode; + #define ATH11K_RECONFIGURE_TIMEOUT_HZ (10 * HZ) + #define ATH11K_RECOVER_START_TIMEOUT_HZ (20 * HZ) +#define MAX_SOCS 3 + enum ath11k_supported_bw { ATH11K_BW_20 = 0, ATH11K_BW_40 = 1, -@@ -1031,6 +1038,7 @@ int ath11k_core_suspend(struct ath11k_ba +@@ -1180,6 +1187,7 @@ int ath11k_core_suspend(struct ath11k_ba const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab, const char *filename); @@ -311,7 +311,7 @@ { --- a/drivers/net/wireless/ath/ath11k/ahb.c +++ b/drivers/net/wireless/ath/ath11k/ahb.c -@@ -332,6 +332,7 @@ static int ath11k_ahb_power_up(struct at +@@ -387,6 +387,7 @@ static int ath11k_ahb_power_up(struct at struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab); int ret; @@ -319,7 +319,7 @@ ret = rproc_boot(ab_ahb->tgt_rproc); if (ret) ath11k_err(ab, "failed to boot the remote processor Q6\n"); -@@ -343,6 +344,7 @@ static void ath11k_ahb_power_down(struct +@@ -398,6 +399,7 @@ static void ath11k_ahb_power_down(struct { struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab); @@ -327,7 +327,7 @@ rproc_shutdown(ab_ahb->tgt_rproc); } -@@ -622,6 +624,31 @@ static int ath11k_ahb_map_service_to_pip +@@ -685,6 +687,31 @@ static int ath11k_ahb_map_service_to_pip return 0; } @@ -356,10 +356,10 @@ +} +#endif + - static const struct ath11k_hif_ops ath11k_ahb_hif_ops = { + static const struct ath11k_hif_ops ath11k_ahb_hif_ops_ipq8074 = { .start = ath11k_ahb_start, .stop = ath11k_ahb_stop, -@@ -632,6 +659,10 @@ static const struct ath11k_hif_ops ath11 +@@ -695,6 +722,10 @@ static const struct ath11k_hif_ops ath11 .map_service_to_pipe = ath11k_ahb_map_service_to_pipe, .power_down = ath11k_ahb_power_down, .power_up = ath11k_ahb_power_up, @@ -369,7 +369,7 @@ +#endif }; - static int ath11k_core_get_rproc(struct ath11k_base *ab) + static const struct ath11k_hif_ops ath11k_ahb_hif_ops_wcn6750 = { --- a/drivers/net/wireless/ath/ath11k/hif.h +++ b/drivers/net/wireless/ath/ath11k/hif.h @@ -29,6 +29,10 @@ struct ath11k_hif_ops { diff --git a/feeds/ipq95xx/mac80211/patches/qca/036-nl80211-add-wide-band-scan-support.patch b/feeds/ipq95xx/mac80211/patches/qca/036-nl80211-add-wide-band-scan-support.patch index 782b5f8d4..e2cdc240b 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/036-nl80211-add-wide-band-scan-support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/036-nl80211-add-wide-band-scan-support.patch @@ -1,6 +1,6 @@ --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h -@@ -2261,6 +2261,7 @@ struct cfg80211_scan_6ghz_params { +@@ -2407,6 +2407,7 @@ struct cfg80211_scan_6ghz_params { * @channels: channels to scan on. * @n_channels: total number of channels to scan * @scan_width: channel width for scanning @@ -8,7 +8,7 @@ * @ie: optional information element(s) to add into Probe Request or %NULL * @ie_len: length of ie in octets * @duration: how long to listen on each channel, in TUs. If -@@ -2291,6 +2292,7 @@ struct cfg80211_scan_request { +@@ -2437,6 +2438,7 @@ struct cfg80211_scan_request { int n_ssids; u32 n_channels; enum nl80211_bss_scan_width scan_width; @@ -18,7 +18,7 @@ u16 duration; --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h -@@ -6079,6 +6079,9 @@ enum nl80211_feature_flags { +@@ -6273,6 +6273,9 @@ enum nl80211_feature_flags { * @NL80211_EXT_FEATURE_RADAR_BACKGROUND: Device supports background radar/CAC * detection. * @@ -28,7 +28,7 @@ * @NUM_NL80211_EXT_FEATURES: number of extended features. * @MAX_NL80211_EXT_FEATURES: highest extended feature index. */ -@@ -6145,6 +6148,7 @@ enum nl80211_ext_feature_index { +@@ -6339,6 +6342,7 @@ enum nl80211_ext_feature_index { NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE, NL80211_EXT_FEATURE_BSS_COLOR, NL80211_EXT_FEATURE_FILS_CRYPTO_OFFLOAD, @@ -36,7 +36,7 @@ NL80211_EXT_FEATURE_RADAR_BACKGROUND, /* add new features before the definition below */ -@@ -6262,6 +6266,8 @@ enum nl80211_timeout_reason { +@@ -6456,6 +6460,8 @@ enum nl80211_timeout_reason { * %NL80211_ATTR_SCAN_FREQUENCIES will not be included. * @NL80211_SCAN_FLAG_COLOCATED_6GHZ: scan for colocated APs reported by * 2.4/5 GHz APs @@ -45,7 +45,7 @@ */ enum nl80211_scan_flags { NL80211_SCAN_FLAG_LOW_PRIORITY = 1<<0, -@@ -6279,6 +6285,7 @@ enum nl80211_scan_flags { +@@ -6473,6 +6479,7 @@ enum nl80211_scan_flags { NL80211_SCAN_FLAG_MIN_PREQ_CONTENT = 1<<12, NL80211_SCAN_FLAG_FREQ_KHZ = 1<<13, NL80211_SCAN_FLAG_COLOCATED_6GHZ = 1<<14, @@ -55,7 +55,7 @@ /** --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c -@@ -718,11 +718,13 @@ static int __ieee80211_start_scan(struct +@@ -732,11 +732,13 @@ static int __ieee80211_start_scan(struct local->hw_scan_req = kmalloc( sizeof(*local->hw_scan_req) + @@ -71,7 +71,7 @@ ies = (u8 *)local->hw_scan_req + --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c -@@ -8462,7 +8462,10 @@ nl80211_check_scan_flags(struct wiphy *w +@@ -8833,7 +8833,10 @@ nl80211_check_scan_flags(struct wiphy *w NL80211_EXT_FEATURE_SCAN_RANDOM_SN) || !nl80211_check_scan_feat(wiphy, *flags, NL80211_SCAN_FLAG_MIN_PREQ_CONTENT, @@ -83,7 +83,7 @@ return -EOPNOTSUPP; if (*flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { -@@ -8487,10 +8490,12 @@ static int nl80211_trigger_scan(struct s +@@ -8858,10 +8861,12 @@ static int nl80211_trigger_scan(struct s struct cfg80211_scan_request *request; struct nlattr *scan_freqs = NULL; bool scan_freqs_khz = false; @@ -97,7 +97,7 @@ wiphy = &rdev->wiphy; -@@ -8503,7 +8508,12 @@ static int nl80211_trigger_scan(struct s +@@ -8874,7 +8879,12 @@ static int nl80211_trigger_scan(struct s if (rdev->scan_req || rdev->scan_msg) return -EBUSY; @@ -111,7 +111,7 @@ if (!wiphy_ext_feature_isset(wiphy, NL80211_EXT_FEATURE_SCAN_FREQ_KHZ)) return -EOPNOTSUPP; -@@ -8516,6 +8526,8 @@ static int nl80211_trigger_scan(struct s +@@ -8887,6 +8897,8 @@ static int nl80211_trigger_scan(struct s n_channels = validate_scan_freqs(scan_freqs); if (!n_channels) return -EINVAL; @@ -120,7 +120,7 @@ } else { n_channels = ieee80211_get_num_supported_channels(wiphy); } -@@ -8536,12 +8548,19 @@ static int nl80211_trigger_scan(struct s +@@ -8907,12 +8919,19 @@ static int nl80211_trigger_scan(struct s return -EINVAL; request = kzalloc(sizeof(*request) @@ -140,7 +140,7 @@ if (n_ssids) request->ssids = (void *)&request->channels[n_channels]; request->n_ssids = n_ssids; -@@ -8575,7 +8594,7 @@ static int nl80211_trigger_scan(struct s +@@ -8946,7 +8965,7 @@ static int nl80211_trigger_scan(struct s request->channels[i] = chan; i++; } @@ -149,56 +149,3 @@ enum nl80211_band band; /* all channels */ -@@ -8598,31 +8617,32 @@ static int nl80211_trigger_scan(struct s - } - } - -- if (!i) { -- err = -EINVAL; -- goto out_free; -- } -- -- request->n_channels = i; -- -- wdev_lock(wdev); -- if (!cfg80211_off_channel_oper_allowed(wdev)) { -- struct ieee80211_channel *chan; -- -- if (request->n_channels != 1) { -- wdev_unlock(wdev); -- err = -EBUSY; -+ if (!chandef_found) { -+ if (!i) { -+ err = -EINVAL; - goto out_free; - } -+ request->n_channels = i; - -- chan = request->channels[0]; -- if (chan->center_freq != wdev->chandef.chan->center_freq) { -- wdev_unlock(wdev); -- err = -EBUSY; -- goto out_free; -+ wdev_lock(wdev); -+ if (!cfg80211_off_channel_oper_allowed(wdev)) { -+ struct ieee80211_channel *chan; -+ -+ if (request->n_channels != 1) { -+ wdev_unlock(wdev); -+ err = -EBUSY; -+ goto out_free; -+ } -+ -+ chan = request->channels[0]; -+ if (chan->center_freq != wdev->chandef.chan->center_freq) { -+ wdev_unlock(wdev); -+ err = -EBUSY; -+ goto out_free; -+ } - } -+ wdev_unlock(wdev); - } -- wdev_unlock(wdev); - - i = 0; - if (n_ssids) { diff --git a/feeds/ipq95xx/mac80211/patches/qca/037-ath11k-add-wide-band-scan-support.patch b/feeds/ipq95xx/mac80211/patches/qca/037-ath11k-add-wide-band-scan-support.patch index d85743aaa..c06ee77b4 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/037-ath11k-add-wide-band-scan-support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/037-ath11k-add-wide-band-scan-support.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -3566,6 +3566,28 @@ static int ath11k_start_scan(struct ath1 +@@ -3601,6 +3601,28 @@ static int ath11k_start_scan(struct ath1 return 0; } @@ -29,7 +29,7 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_scan_request *hw_req) -@@ -3645,18 +3667,16 @@ static int ath11k_mac_op_hw_scan(struct +@@ -3660,18 +3682,16 @@ static int ath11k_mac_op_hw_scan(struct arg.scan_flags |= WMI_SCAN_FLAG_PASSIVE; } @@ -56,7 +56,7 @@ } if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { -@@ -3679,7 +3699,6 @@ static int ath11k_mac_op_hw_scan(struct +@@ -3694,7 +3714,6 @@ static int ath11k_mac_op_hw_scan(struct ATH11K_MAC_SCAN_TIMEOUT_MSECS)); exit: @@ -64,9 +64,79 @@ if (req->ie_len) kfree(arg.extraie.ptr); -@@ -8646,6 +8665,11 @@ static int __ath11k_mac_register(struct - wiphy_ext_feature_set(ar->hw->wiphy, - NL80211_EXT_FEATURE_BSS_COLOR); +@@ -8381,6 +8400,8 @@ static int ath11k_mac_op_cancel_remain_o + return 0; + } + ++//TODO Author has to correct the below api as per wide band scan ++#if 0 + static int ath11k_mac_op_remain_on_channel(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_channel *chan, +@@ -8423,17 +8444,11 @@ static int ath11k_mac_op_remain_on_chann + + memset(&arg, 0, sizeof(arg)); + ath11k_wmi_start_scan_init(ar, &arg); +- arg.num_chan = 1; +- arg.chan_list = kcalloc(arg.num_chan, sizeof(*arg.chan_list), +- GFP_KERNEL); +- if (!arg.chan_list) { +- ret = -ENOMEM; +- goto exit; +- } ++ arg.chan_list.num_chan = 1; + + arg.vdev_id = arvif->vdev_id; + arg.scan_id = ATH11K_SCAN_ID; +- arg.chan_list[0] = chan->center_freq; ++ arg.chan_list = chan->center_freq; + arg.dwell_time_active = scan_time_msec; + arg.dwell_time_passive = scan_time_msec; + arg.max_scan_time = scan_time_msec; +@@ -8448,7 +8463,7 @@ static int ath11k_mac_op_remain_on_chann + spin_lock_bh(&ar->data_lock); + ar->scan.state = ATH11K_SCAN_IDLE; + spin_unlock_bh(&ar->data_lock); +- goto free_chan_list; ++ goto exit; + } + + ret = wait_for_completion_timeout(&ar->scan.on_channel, 3 * HZ); +@@ -8458,7 +8473,7 @@ static int ath11k_mac_op_remain_on_chann + if (ret) + ath11k_warn(ar->ab, "failed to stop scan: %d\n", ret); + ret = -ETIMEDOUT; +- goto free_chan_list; ++ goto exit; + } + + ieee80211_queue_delayed_work(ar->hw, &ar->scan.timeout, +@@ -8466,12 +8481,11 @@ static int ath11k_mac_op_remain_on_chann + + ret = 0; + +-free_chan_list: +- kfree(arg.chan_list); + exit: + mutex_unlock(&ar->conf_mutex); + return ret; + } ++#endif + + #define ATH11K_WLAN_PRIO_MAX 0x63 + #define ATH11K_WLAN_PRIO_WEIGHT 0xff +@@ -8610,7 +8624,7 @@ static const struct ieee80211_ops ath11k + #endif + + .set_sar_specs = ath11k_mac_op_set_bios_sar_specs, +- .remain_on_channel = ath11k_mac_op_remain_on_channel, ++// .remain_on_channel = ath11k_mac_op_remain_on_channel, + .cancel_remain_on_channel = ath11k_mac_op_cancel_remain_on_channel, + }; + +@@ -9065,6 +9079,11 @@ static int __ath11k_mac_register(struct + ieee80211_hw_set(ar->hw, DETECTS_COLOR_COLLISION); + } + if (test_bit(WMI_TLV_SERVICE_SCAN_PHYMODE_SUPPORT, + ar->ab->wmi_ab.svc_map)) @@ -78,7 +148,7 @@ --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -2108,6 +2108,110 @@ int ath11k_wmi_send_peer_assoc_cmd(struc +@@ -2126,6 +2126,110 @@ int ath11k_wmi_send_peer_assoc_cmd(struc return ret; } @@ -189,7 +259,7 @@ void ath11k_wmi_start_scan_init(struct ath11k *ar, struct scan_req_params *arg) { -@@ -2227,15 +2331,17 @@ int ath11k_wmi_send_scan_start_cmd(struc +@@ -2248,15 +2352,17 @@ int ath11k_wmi_send_scan_start_cmd(struc void *ptr; int i, ret, len; u32 *tmp_ptr; @@ -209,7 +279,7 @@ len += TLV_HDR_SIZE; if (params->num_ssids) -@@ -2259,6 +2365,19 @@ int ath11k_wmi_send_scan_start_cmd(struc +@@ -2280,6 +2386,19 @@ int ath11k_wmi_send_scan_start_cmd(struc len += TLV_HDR_SIZE + params->num_hint_s_ssid * sizeof(struct hint_short_ssid); @@ -229,7 +299,7 @@ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len); if (!skb) return -ENOMEM; -@@ -2290,7 +2409,7 @@ int ath11k_wmi_send_scan_start_cmd(struc +@@ -2311,7 +2430,7 @@ int ath11k_wmi_send_scan_start_cmd(struc cmd->max_scan_time = params->max_scan_time; cmd->probe_delay = params->probe_delay; cmd->burst_duration = params->burst_duration; @@ -238,7 +308,7 @@ cmd->num_bssid = params->num_bssid; cmd->num_ssids = params->num_ssids; cmd->ie_len = params->extraie.len; -@@ -2300,7 +2419,7 @@ int ath11k_wmi_send_scan_start_cmd(struc +@@ -2321,7 +2440,7 @@ int ath11k_wmi_send_scan_start_cmd(struc ptr += sizeof(*cmd); @@ -247,7 +317,7 @@ tlv = ptr; tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_UINT32) | -@@ -2308,8 +2427,8 @@ int ath11k_wmi_send_scan_start_cmd(struc +@@ -2329,8 +2448,8 @@ int ath11k_wmi_send_scan_start_cmd(struc ptr += TLV_HDR_SIZE; tmp_ptr = (u32 *)ptr; @@ -258,7 +328,7 @@ ptr += len; -@@ -2350,6 +2469,7 @@ int ath11k_wmi_send_scan_start_cmd(struc +@@ -2371,6 +2490,7 @@ int ath11k_wmi_send_scan_start_cmd(struc ptr += params->num_bssid * sizeof(*bssid); len = extraie_len_with_pad; @@ -266,7 +336,7 @@ tlv = ptr; tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_BYTE) | FIELD_PREP(WMI_TLV_LEN, len); -@@ -2361,6 +2481,36 @@ int ath11k_wmi_send_scan_start_cmd(struc +@@ -2382,6 +2502,36 @@ int ath11k_wmi_send_scan_start_cmd(struc ptr += extraie_len_with_pad; @@ -303,7 +373,7 @@ if (params->num_hint_s_ssid) { len = params->num_hint_s_ssid * sizeof(struct hint_short_ssid); tlv = ptr; -@@ -2487,7 +2637,7 @@ int ath11k_wmi_send_scan_chan_list_cmd(s +@@ -2508,7 +2658,7 @@ int ath11k_wmi_send_scan_chan_list_cmd(s FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); cmd->pdev_id = chan_list->pdev_id; cmd->num_scan_chans = num_send_chans; @@ -314,7 +384,7 @@ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -64,8 +64,6 @@ struct wmi_tlv { +@@ -66,8 +66,6 @@ struct wmi_tlv { #define WLAN_SCAN_PARAMS_MAX_BSSID 4 #define WLAN_SCAN_PARAMS_MAX_IE_LEN 256 @@ -323,16 +393,16 @@ #define WMI_BA_MODE_BUFFER_SIZE_256 3 /* * HW mode config type replicated from FW header -@@ -3096,6 +3094,8 @@ enum scan_dwelltime_adaptive_mode { - #define WLAN_SCAN_MAX_NUM_SSID 10 - #define WLAN_SCAN_MAX_NUM_BSSID 10 +@@ -3108,6 +3106,8 @@ enum scan_dwelltime_adaptive_mode { + SCAN_DWELL_MODE_STATIC = 4 + }; +#define WLAN_SCAN_MAX_NUM_CHANNELS 60 + #define WLAN_SSID_MAX_LEN 32 struct element_info { -@@ -3109,6 +3109,12 @@ struct wlan_ssid { +@@ -3121,6 +3121,12 @@ struct wlan_ssid { }; #define WMI_IE_BITMAP_SIZE 8 @@ -343,9 +413,9 @@ + u32 oui_type_subtype; /* vendor OUI type and subtype */ +}; - #define WMI_SCAN_MAX_NUM_SSID 0x0A /* prefix used by scan requestor ids on the host */ -@@ -3243,6 +3249,22 @@ struct hint_bssid { + #define WMI_HOST_SCAN_REQUESTOR_ID_PREFIX 0xA000 +@@ -3250,6 +3256,22 @@ struct hint_bssid { struct wmi_mac_addr bssid; }; @@ -368,7 +438,7 @@ struct scan_req_params { u32 scan_id; u32 scan_req_id; -@@ -3305,17 +3327,17 @@ struct scan_req_params { +@@ -3312,17 +3334,17 @@ struct scan_req_params { scan_f_forced:1, scan_f_2ghz:1, scan_f_5ghz:1, @@ -387,9 +457,9 @@ + struct chan_list chan_list; + struct cfg80211_chan_def *chandef; u32 notify_scan_events; - struct wlan_ssid ssid[WLAN_SCAN_MAX_NUM_SSID]; - struct wmi_mac_addr bssid_list[WLAN_SCAN_MAX_NUM_BSSID]; -@@ -3326,6 +3348,7 @@ struct scan_req_params { + struct wlan_ssid ssid[WLAN_SCAN_PARAMS_MAX_SSID]; + struct wmi_mac_addr bssid_list[WLAN_SCAN_PARAMS_MAX_BSSID]; +@@ -3333,6 +3355,7 @@ struct scan_req_params { u32 num_hint_bssid; struct hint_short_ssid hint_s_ssid[WLAN_SCAN_MAX_HINT_S_SSID]; struct hint_bssid hint_bssid[WLAN_SCAN_MAX_HINT_BSSID]; @@ -397,7 +467,7 @@ struct wmi_mac_addr mac_addr; struct wmi_mac_addr mac_mask; }; -@@ -3681,9 +3704,12 @@ struct wmi_stop_scan_cmd { +@@ -3688,9 +3711,12 @@ struct wmi_stop_scan_cmd { struct scan_chan_list_params { u32 pdev_id; u16 nallchans; @@ -410,7 +480,7 @@ struct wmi_scan_chan_list_cmd { u32 tlv_header; u32 num_scan_chans; -@@ -5558,6 +5584,8 @@ int ath11k_wmi_vdev_delete(struct ath11k +@@ -6053,6 +6079,8 @@ int ath11k_wmi_vdev_delete(struct ath11k void ath11k_wmi_start_scan_init(struct ath11k *ar, struct scan_req_params *arg); int ath11k_wmi_send_scan_start_cmd(struct ath11k *ar, struct scan_req_params *params); @@ -421,9 +491,9 @@ int ath11k_wmi_send_wmm_update_cmd_tlv(struct ath11k *ar, u32 vdev_id, --- a/drivers/net/wireless/ath/ath11k/reg.c +++ b/drivers/net/wireless/ath/ath11k/reg.c -@@ -104,101 +104,7 @@ ath11k_reg_notifier(struct wiphy *wiphy, +@@ -105,14 +105,7 @@ ath11k_reg_notifier(struct wiphy *wiphy, - int ath11k_reg_update_chan_list(struct ath11k *ar) + int ath11k_reg_update_chan_list(struct ath11k *ar, bool wait) { - struct ieee80211_supported_band **bands; - struct scan_chan_list_params *params; @@ -432,8 +502,15 @@ - struct channel_param *ch; - enum nl80211_band band; - int num_channels = 0; -- int i, ret; -- +- int i, ret, left; ++ int left; + + if (wait && ar->state_11d != ATH11K_11D_IDLE) { + left = wait_for_completion_timeout(&ar->completed_11d_scan, +@@ -142,87 +135,7 @@ int ath11k_reg_update_chan_list(struct a + if (ar->state == ATH11K_STATE_RESTARTING) + return 0; + - bands = hw->wiphy->bands; - for (band = 0; band < NUM_NL80211_BANDS; band++) { - if (!bands[band]) @@ -514,11 +591,6 @@ - ret = ath11k_wmi_send_scan_chan_list_cmd(ar, params); - kfree(params); - -- if (ar->pending_11d) { -- complete(&ar->finish_11d_ch_list); -- ar->pending_11d = false; -- } -- - return ret; + return ath11k_wmi_update_scan_chan_list(ar, NULL); } diff --git a/feeds/ipq95xx/mac80211/patches/qca/038-ath11k-Adding-support-for-QDSS.patch b/feeds/ipq95xx/mac80211/patches/qca/038-ath11k-Adding-support-for-QDSS.patch index 98b87f782..9245a4bc3 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/038-ath11k-Adding-support-for-QDSS.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/038-ath11k-Adding-support-for-QDSS.patch @@ -1,17 +1,18 @@ --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -1267,6 +1267,8 @@ int ath11k_core_qmi_firmware_ready(struc +@@ -1552,6 +1552,9 @@ int ath11k_core_qmi_firmware_ready(struc + } ath11k_hif_irq_enable(ab); - ++ + ath11k_config_qdss(ab); + - ret = ath11k_core_rfkill_config(ab); - if (ret && ret != -EOPNOTSUPP) { - ath11k_err(ab, "failed to config rfkill: %d\n", ret); + mutex_unlock(&ab->core_lock); + + return 0; --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -1025,6 +1025,7 @@ struct ath11k_base *ath11k_core_alloc(st +@@ -1174,6 +1174,7 @@ struct ath11k_base *ath11k_core_alloc(st void ath11k_core_free(struct ath11k_base *ath11k); int ath11k_core_fetch_bdf(struct ath11k_base *ath11k, struct ath11k_board_data *bd); @@ -21,7 +22,7 @@ struct ath11k_board_data *bd, --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c -@@ -22,6 +22,194 @@ module_param_named(cold_boot_cal, ath11k +@@ -28,6 +28,194 @@ module_param_named(cold_boot_cal, ath11k MODULE_PARM_DESC(cold_boot_cal, "Decrease the channel switch time but increase the driver load time (Default: true)"); @@ -216,7 +217,7 @@ static struct qmi_elem_info qmi_wlanfw_host_cap_req_msg_v01_ei[] = { { .data_type = QMI_OPT_FLAG, -@@ -1628,6 +1816,156 @@ static struct qmi_elem_info qmi_wlanfw_w +@@ -1696,6 +1884,156 @@ static struct qmi_elem_info qmi_wlanfw_w }, }; @@ -373,7 +374,7 @@ static int ath11k_qmi_host_cap_send(struct ath11k_base *ab) { struct qmi_wlanfw_host_cap_req_msg_v01 req; -@@ -1736,7 +2074,12 @@ static int ath11k_qmi_fw_ind_register_se +@@ -1803,7 +2141,12 @@ static int ath11k_qmi_fw_ind_register_se req->cal_done_enable = 1; req->fw_init_done_enable_valid = 1; req->fw_init_done_enable = 1; @@ -387,7 +388,7 @@ req->pin_connect_result_enable_valid = 0; req->pin_connect_result_enable = 0; -@@ -2609,6 +2952,31 @@ void ath11k_qmi_firmware_stop(struct ath +@@ -2791,6 +3134,31 @@ void ath11k_qmi_firmware_stop(struct ath } } @@ -421,7 +422,7 @@ { --- a/drivers/net/wireless/ath/ath11k/qmi.h +++ b/drivers/net/wireless/ath/ath11k/qmi.h -@@ -28,6 +28,8 @@ +@@ -30,6 +30,8 @@ #define ATH11K_QMI_CALDB_SIZE 0x480000 #define ATH11K_QMI_BDF_EXT_STR_LENGTH 0x20 #define ATH11K_QMI_FW_MEM_REQ_SEGMENT_CNT 3 @@ -430,7 +431,7 @@ #define QMI_WLFW_REQUEST_MEM_IND_V01 0x0035 #define QMI_WLFW_FW_MEM_READY_IND_V01 0x0037 -@@ -139,7 +141,51 @@ struct ath11k_qmi { +@@ -145,7 +147,51 @@ struct ath11k_qmi { wait_queue_head_t cold_boot_waitq; }; @@ -483,7 +484,7 @@ #define QMI_WLANFW_HOST_CAP_REQ_V01 0x0034 #define QMI_WLANFW_HOST_CAP_RESP_MSG_V01_MAX_LEN 7 #define QMI_WLFW_HOST_CAP_RESP_V01 0x0034 -@@ -178,13 +224,15 @@ struct qmi_wlanfw_host_cap_req_msg_v01 { +@@ -184,13 +230,15 @@ struct qmi_wlanfw_host_cap_req_msg_v01 { u32 mem_bucket; u8 mem_cfg_mode_valid; u8 mem_cfg_mode; @@ -500,7 +501,7 @@ #define QMI_WLANFW_IND_REGISTER_REQ_V01 0x0020 #define QMI_WLANFW_IND_REGISTER_RESP_MSG_V01_MAX_LEN 18 #define QMI_WLANFW_IND_REGISTER_RESP_V01 0x0020 -@@ -215,6 +263,12 @@ struct qmi_wlanfw_ind_register_req_msg_v +@@ -221,6 +269,12 @@ struct qmi_wlanfw_ind_register_req_msg_v u8 xo_cal_enable; u8 cal_done_enable_valid; u8 cal_done_enable; @@ -513,15 +514,13 @@ }; struct qmi_wlanfw_ind_register_resp_msg_v01 { -@@ -495,5 +549,11 @@ void ath11k_qmi_event_work(struct work_s - void ath11k_qmi_msg_recv_work(struct work_struct *work); +@@ -516,5 +570,8 @@ void ath11k_qmi_msg_recv_work(struct wor void ath11k_qmi_deinit_service(struct ath11k_base *ab); int ath11k_qmi_init_service(struct ath11k_base *ab); + void ath11k_qmi_free_resource(struct ath11k_base *ab); +- +int wlfw_send_qdss_trace_config_download_req(struct ath11k_base *ab, -+ const u8 *buffer, unsigned int len); -+ ++ const u8 *buffer, unsigned int len); +int ath11k_send_qdss_trace_mode_req(struct ath11k_base *ab, -+ enum wlfw_qdss_trace_mode_enum_v01 mode); -+ - ++ enum wlfw_qdss_trace_mode_enum_v01 mode); #endif diff --git a/feeds/ipq95xx/mac80211/patches/qca/039-mac80211-ath11k-add-HE-TX-rate-reporting-to-radiotap.patch b/feeds/ipq95xx/mac80211/patches/qca/039-mac80211-ath11k-add-HE-TX-rate-reporting-to-radiotap.patch deleted file mode 100644 index fa2c8d3b6..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/039-mac80211-ath11k-add-HE-TX-rate-reporting-to-radiotap.patch +++ /dev/null @@ -1,55 +0,0 @@ -From c4401adb2f0188add0dc2194849f4baacf31ce49 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Wed, 17 Jul 2019 16:22:12 -0700 -Subject: [PATCH 1/6] mac80211: add xmit rate to struct ieee80211_tx_status - -Right now struct ieee80211_tx_rate cannot hold HE rates. Lets use -struct ieee80211_tx_status instead. This will also make the code -future-proof for when we have EHT. - -Signed-off-by: John Crispin ---- - include/net/mac80211.h | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/net/wireless/ath/ath11k/dp_tx.c -+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c -@@ -419,9 +419,12 @@ static void ath11k_dp_tx_complete_msdu(s - struct sk_buff *msdu, - struct hal_tx_status *ts) - { -+ struct ieee80211_tx_status status = { 0 }; - struct ath11k_base *ab = ar->ab; - struct ieee80211_tx_info *info; - struct ath11k_skb_cb *skb_cb; -+ struct ath11k_peer *peer; -+ struct ath11k_sta *arsta; - - if (WARN_ON_ONCE(ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM)) { - /* Must not happen */ -@@ -488,7 +491,24 @@ static void ath11k_dp_tx_complete_msdu(s - * Might end up reporting it out-of-band from HTT stats. - */ - -- ieee80211_tx_status(ar->hw, msdu); -+ spin_lock_bh(&ab->base_lock); -+ peer = ath11k_peer_find_by_id(ab, ts->peer_id); -+ if (!peer || !peer->sta) { -+ ath11k_dbg(ab, ATH11K_DBG_DATA, -+ "dp_tx: failed to find the peer with peer_id %d\n", -+ ts->peer_id); -+ spin_unlock_bh(&ab->base_lock); -+ dev_kfree_skb_any(msdu); -+ goto exit; -+ } -+ arsta = (struct ath11k_sta *)peer->sta->drv_priv; -+ status.sta = peer->sta; -+ status.skb = msdu; -+ status.info = info; -+ status.rate = &arsta->last_txrate; -+ ieee80211_tx_status_ext(ar->hw, &status); -+ spin_unlock_bh(&ab->base_lock); -+ return; - } - - static inline void ath11k_dp_tx_status_parse(struct ath11k_base *ab, diff --git a/feeds/ipq95xx/mac80211/patches/qca/056-ath11k-mac80211-twt-support.patch b/feeds/ipq95xx/mac80211/patches/qca/056-ath11k-mac80211-twt-support.patch deleted file mode 100644 index 27df01d8d..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/056-ath11k-mac80211-twt-support.patch +++ /dev/null @@ -1,642 +0,0 @@ -From bb865d8d08eb703ec016a503bf8a4cf8e8e8070b Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Tue, 1 Oct 2019 16:48:51 -0700 -Subject: [PATCH 1/5] [PATCH V3] ath11k: add TWT support - -Signed-off-by: Shashidhar Lakkavalli -Signed-off-by: John Crispin ---- - drivers/net/wireless/ath/ath11k/mac.c | 12 +++++ - drivers/net/wireless/ath/ath11k/wmi.c | 91 +++++++++++++++++++++++++++++++++++ - drivers/net/wireless/ath/ath11k/wmi.h | 71 +++++++++++++++++++++++++++ - 3 files changed, 174 insertions(+) - ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -3337,6 +3337,8 @@ static void ath11k_mac_op_bss_info_chang - ath11k_wmi_send_twt_enable_cmd(ar, ar->pdev->pdev_id); - else - ath11k_wmi_send_twt_disable_cmd(ar, ar->pdev->pdev_id); -+ if (vif->type == NL80211_IFTYPE_AP) -+ ath11k_debugfs_twt(arvif, info->twt_requester); - } - - if (changed & BSS_CHANGED_HE_OBSS_PD) -@@ -6559,6 +6561,10 @@ err_vdev_del: - - /* TODO: recal traffic pause state based on the available vdevs */ - -+ /* Remove TWT related files and directory */ -+ debugfs_remove_recursive(arvif->debugfs_twt); -+ arvif->debugfs_twt = NULL; -+ - mutex_unlock(&ar->conf_mutex); - } - ---- a/drivers/net/wireless/ath/ath11k/wmi.c -+++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -141,6 +141,8 @@ static const struct wmi_tlv_policy wmi_t - .min_len = sizeof(struct wmi_vdev_delete_resp_event) }, - [WMI_TAG_OBSS_COLOR_COLLISION_EVT] = { - .min_len = sizeof(struct wmi_obss_color_collision_event) }, -+ [WMI_TAG_TWT_ADD_DIALOG_COMPLETE_EVENT] -+ = { .min_len = sizeof(struct wmi_twt_add_dialog_event) }, - [WMI_TAG_11D_NEW_COUNTRY_EVENT] = { - .min_len = sizeof(struct wmi_11d_new_cc_ev) }, - [WMI_TAG_PER_CHAIN_RSSI_STATS] = { -@@ -2860,7 +2862,162 @@ int ath11k_wmi_delba_send(struct ath11k - return ret; - } - --int ath11k_wmi_addba_set_resp(struct ath11k *ar, u32 vdev_id, const u8 *mac, -+int -+ath11k_wmi_send_twt_add_dialog_cmd(struct ath11k *ar, -+ struct wmi_twt_add_dialog_params *params) -+{ -+ struct ath11k_pdev_wmi *wmi = ar->wmi; -+ struct ath11k_base *ab = wmi->wmi_ab->ab; -+ struct wmi_twt_add_dialog_params_cmd *cmd; -+ struct sk_buff *skb; -+ int ret, len; -+ -+ len = sizeof(*cmd); -+ -+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len); -+ if (!skb) -+ return -ENOMEM; -+ -+ cmd = (void *)skb->data; -+ cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, -+ WMI_TAG_TWT_ADD_DIALOG_CMD) | -+ FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE); -+ -+ cmd->vdev_id = params->vdev_id; -+ ether_addr_copy(cmd->peer_macaddr.addr, params->peer_macaddr); -+ cmd->dialog_id = params->dialog_id; -+ cmd->wake_intvl_us = params->wake_intvl_us; -+ cmd->wake_intvl_mantis = params->wake_intvl_mantis; -+ cmd->wake_dura_us = params->wake_dura_us; -+ cmd->sp_offset_us = params->sp_offset_us; -+ cmd->flags = params->twt_cmd; -+ if (params->flag_bcast) -+ cmd->flags |= WMI_TWT_ADD_DIALOG_FLAG_BCAST; -+ if (params->flag_trigger) -+ cmd->flags |= WMI_TWT_ADD_DIALOG_FLAG_TRIGGER; -+ if (params->flag_flow_type) -+ cmd->flags |= WMI_TWT_ADD_DIALOG_FLAG_FLOW_TYPE; -+ if (params->flag_protection) -+ cmd->flags |= WMI_TWT_ADD_DIALOG_FLAG_PROTECTION; -+ -+ ret = ath11k_wmi_cmd_send(wmi, skb, -+ WMI_TWT_ADD_DIALOG_CMDID); -+ -+ if (ret) { -+ ath11k_warn(ab, "Failed to send WMI_TWT_ADD_DIALOG_CMDID"); -+ dev_kfree_skb(skb); -+ } -+ return ret; -+} -+ -+int -+ath11k_wmi_send_twt_del_dialog_cmd(struct ath11k *ar, -+ struct wmi_twt_del_dialog_params *params) -+{ -+ struct ath11k_pdev_wmi *wmi = ar->wmi; -+ struct ath11k_base *ab = wmi->wmi_ab->ab; -+ struct wmi_twt_del_dialog_params_cmd *cmd; -+ struct sk_buff *skb; -+ int ret, len; -+ -+ len = sizeof(*cmd); -+ -+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len); -+ if (!skb) -+ return -ENOMEM; -+ -+ cmd = (void *)skb->data; -+ cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, -+ WMI_TAG_TWT_DEL_DIALOG_CMD) | -+ FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE); -+ -+ cmd->vdev_id = params->vdev_id; -+ ether_addr_copy(cmd->peer_macaddr.addr, params->peer_macaddr); -+ cmd->dialog_id = params->dialog_id; -+ -+ ret = ath11k_wmi_cmd_send(wmi, skb, -+ WMI_TWT_DEL_DIALOG_CMDID); -+ if (ret) { -+ ath11k_warn(ab, "Failed to send WMI_TWT_DEL_DIALOG_CMDID"); -+ dev_kfree_skb(skb); -+ } -+ return ret; -+} -+ -+int -+ath11k_wmi_send_twt_pause_dialog_cmd(struct ath11k *ar, -+ struct wmi_twt_pause_dialog_params *params) -+{ -+ struct ath11k_pdev_wmi *wmi = ar->wmi; -+ struct ath11k_base *ab = wmi->wmi_ab->ab; -+ struct wmi_twt_pause_dialog_params_cmd *cmd; -+ struct sk_buff *skb; -+ int ret, len; -+ -+ len = sizeof(*cmd); -+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len); -+ if (!skb) -+ return -ENOMEM; -+ -+ cmd = (void *)skb->data; -+ cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, -+ WMI_TAG_TWT_PAUSE_DIALOG_CMD) | -+ FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE); -+ -+ cmd->vdev_id = params->vdev_id; -+ ether_addr_copy(cmd->peer_macaddr.addr, params->peer_macaddr); -+ cmd->dialog_id = params->dialog_id; -+ -+ ret = ath11k_wmi_cmd_send(wmi, skb, -+ WMI_TWT_PAUSE_DIALOG_CMDID); -+ if (ret) { -+ ath11k_warn(ab, "Failed to send WMI_TWT_PAUSE_DIALOG_CMDID"); -+ dev_kfree_skb(skb); -+ } -+ return ret; -+} -+ -+int -+ath11k_wmi_send_twt_resume_dialog_cmd(struct ath11k *ar, -+ struct wmi_twt_resume_dialog_params *params) -+{ -+ struct ath11k_pdev_wmi *wmi = ar->wmi; -+ struct ath11k_base *ab = wmi->wmi_ab->ab; -+ struct wmi_twt_resume_dialog_params_cmd *cmd; -+ struct sk_buff *skb; -+ int ret, len; -+ -+ len = sizeof(*cmd); -+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len); -+ if (!skb) -+ return -ENOMEM; -+ -+ cmd = (void *)skb->data; -+ cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, -+ WMI_TAG_TWT_RESUME_DIALOG_CMD) | -+ FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE); -+ -+ cmd->vdev_id = params->vdev_id; -+ ether_addr_copy(cmd->peer_macaddr.addr, params->peer_macaddr); -+ cmd->dialog_id = params->dialog_id; -+ cmd->sp_offset_us = params->sp_offset_us; -+ cmd->next_twt_size = params->next_twt_size; -+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "%s:%s[%d]%x %x %x %x %x\n", -+ __FILE__, __func__, __LINE__, cmd->peer_macaddr.word0, -+ cmd->peer_macaddr.word1, cmd->dialog_id, -+ params->sp_offset_us, params->next_twt_size); -+ -+ ret = ath11k_wmi_cmd_send(wmi, skb, -+ WMI_TWT_RESUME_DIALOG_CMDID); -+ if (ret) { -+ ath11k_warn(ab, "Failed to send WMI_TWT_RESUME_DIALOG_CMDID"); -+ dev_kfree_skb(skb); -+ } -+ return ret; -+} -+ -+int -+ath11k_wmi_addba_set_resp(struct ath11k *ar, u32 vdev_id, const u8 *mac, - u32 tid, u32 status) - { - struct ath11k_pdev_wmi *wmi = ar->wmi; -@@ -7782,6 +7939,37 @@ ath11k_wmi_diag_event(struct ath11k_base - trace_ath11k_wmi_diag(ab, skb->data, skb->len); - } - -+static void ath11k_wmi_twt_add_dialog_event(struct ath11k_base *ab, struct sk_buff *skb) -+{ -+ const char *status[] = { -+ "OK", "TWT_NOT_ENABLED", "USED_DIALOG_ID", "INVALID_PARAM", -+ "NOT_READY", "NO_RESOURCE", "NO_ACK", "NO_RESPONSE", -+ "DENIED", "UNKNOWN_ERROR" -+ }; -+ const void **tb; -+ const struct wmi_twt_add_dialog_event *ev; -+ int ret; -+ -+ tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); -+ if (IS_ERR(tb)) { -+ ret = PTR_ERR(tb); -+ ath11k_warn(ab, "failed to parse tlv: %d\n", ret); -+ return; -+ } -+ -+ ev = tb[WMI_TAG_TWT_ADD_DIALOG_COMPLETE_EVENT]; -+ if (!ev) { -+ ath11k_warn(ab, "failed to fetch twt add dialog ev"); -+ goto exit; -+ } -+ -+ ath11k_info(ab, "TWT Add Dialog Event - Status: %s, DialogId: %d, VdevId: %d\n", -+ status[ev->status], ev->vdev_id, ev->dialog_id); -+ -+exit: -+ kfree(tb); -+} -+ - static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb) - { - struct wmi_cmd_hdr *cmd_hdr; -@@ -7882,11 +8070,17 @@ static void ath11k_wmi_tlv_op_rx(struct - case WMI_PDEV_UTF_EVENTID: - ath11k_tm_event_wmi(ab, id, skb); - break; -+ case WMI_TWT_ADD_DIALOG_EVENTID: -+ ath11k_wmi_twt_add_dialog_event(ab, skb); -+ break; - /* add Unsupported events here */ - case WMI_TBTTOFFSET_EXT_UPDATE_EVENTID: - case WMI_PEER_OPER_MODE_CHANGE_EVENTID: - case WMI_TWT_ENABLE_EVENTID: - case WMI_TWT_DISABLE_EVENTID: -+ case WMI_TWT_DEL_DIALOG_EVENTID: -+ case WMI_TWT_PAUSE_DIALOG_EVENTID: -+ case WMI_TWT_RESUME_DIALOG_EVENTID: - case WMI_PDEV_DMA_RING_CFG_RSP_EVENTID: - case WMI_PEER_CREATE_CONF_EVENTID: - ath11k_dbg(ab, ATH11K_DBG_WMI, ---- a/drivers/net/wireless/ath/ath11k/wmi.h -+++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -5057,6 +5057,112 @@ struct wmi_twt_disable_params_cmd { - u32 pdev_id; - } __packed; - -+enum WMI_HOST_TWT_COMMAND { -+ WMI_HOST_TWT_COMMAND_REQUEST_TWT = 0, -+ WMI_HOST_TWT_COMMAND_SUGGEST_TWT, -+ WMI_HOST_TWT_COMMAND_DEMAND_TWT, -+ WMI_HOST_TWT_COMMAND_TWT_GROUPING, -+ WMI_HOST_TWT_COMMAND_ACCEPT_TWT, -+ WMI_HOST_TWT_COMMAND_ALTERNATE_TWT, -+ WMI_HOST_TWT_COMMAND_DICTATE_TWT, -+ WMI_HOST_TWT_COMMAND_REJECT_TWT, -+}; -+ -+#define WMI_TWT_ADD_DIALOG_FLAG_BCAST BIT(8) -+#define WMI_TWT_ADD_DIALOG_FLAG_TRIGGER BIT(9) -+#define WMI_TWT_ADD_DIALOG_FLAG_FLOW_TYPE BIT(10) -+#define WMI_TWT_ADD_DIALOG_FLAG_PROTECTION BIT(11) -+ -+struct wmi_twt_add_dialog_params_cmd { -+ u32 tlv_header; -+ u32 vdev_id; -+ struct wmi_mac_addr peer_macaddr; -+ u32 dialog_id; -+ u32 wake_intvl_us; -+ u32 wake_intvl_mantis; -+ u32 wake_dura_us; -+ u32 sp_offset_us; -+ u32 flags; -+}; -+ -+struct wmi_twt_add_dialog_params { -+ u32 vdev_id; -+ u8 peer_macaddr[ETH_ALEN]; -+ u32 dialog_id; -+ u32 wake_intvl_us; -+ u32 wake_intvl_mantis; -+ u32 wake_dura_us; -+ u32 sp_offset_us; -+ u8 twt_cmd; -+ u8 flag_bcast; -+ u8 flag_trigger; -+ u8 flag_flow_type; -+ u8 flag_protection; -+}; -+ -+enum wmi_twt_add_dialog_status { -+ WMI_ADD_TWT_STATUS_OK, /* adding TWT dialog successfully completed */ -+ WMI_ADD_TWT_STATUS_TWT_NOT_ENABLED, /* TWT not enabled */ -+ WMI_ADD_TWT_STATUS_USED_DIALOG_ID, /* TWT dialog ID is already used */ -+ WMI_ADD_TWT_STATUS_INVALID_PARAM, /* invalid parameters */ -+ WMI_ADD_TWT_STATUS_NOT_READY, /* FW not ready */ -+ WMI_ADD_TWT_STATUS_NO_RESOURCE, /* FW resource exhausted */ -+ WMI_ADD_TWT_STATUS_NO_ACK, /* peer AP/STA did not ACK the request/response frame */ -+ WMI_ADD_TWT_STATUS_NO_RESPONSE, /* peer AP did not send the response frame */ -+ WMI_ADD_TWT_STATUS_DENIED, /* AP did not accept the request */ -+ WMI_ADD_TWT_STATUS_UNKNOWN_ERROR, /* adding TWT dialog failed with an unknown reason */ -+}; -+ -+struct wmi_twt_add_dialog_event { -+ u32 vdev_id; -+ struct wmi_mac_addr peer_macaddr; -+ u32 dialog_id; -+ u32 status; -+}; -+ -+struct wmi_twt_del_dialog_params { -+ u32 vdev_id; -+ u8 peer_macaddr[ETH_ALEN]; -+ u32 dialog_id; -+}; -+ -+struct wmi_twt_del_dialog_params_cmd { -+ u32 tlv_header; -+ u32 vdev_id; -+ struct wmi_mac_addr peer_macaddr; -+ u32 dialog_id; -+}; -+ -+struct wmi_twt_pause_dialog_params { -+ u32 vdev_id; -+ u8 peer_macaddr[ETH_ALEN]; -+ u32 dialog_id; -+}; -+ -+struct wmi_twt_pause_dialog_params_cmd { -+ u32 tlv_header; -+ u32 vdev_id; -+ struct wmi_mac_addr peer_macaddr; -+ u32 dialog_id; -+}; -+ -+struct wmi_twt_resume_dialog_params { -+ u32 vdev_id; -+ u8 peer_macaddr[ETH_ALEN]; -+ u32 dialog_id; -+ u32 sp_offset_us; -+ u32 next_twt_size; -+}; -+ -+struct wmi_twt_resume_dialog_params_cmd { -+ u32 tlv_header; -+ u32 vdev_id; -+ struct wmi_mac_addr peer_macaddr; -+ u32 dialog_id; -+ u32 sp_offset_us; -+ u32 next_twt_size; -+}; -+ - struct wmi_obss_spatial_reuse_params_cmd { - u32 tlv_header; - u32 pdev_id; -@@ -5653,6 +5759,14 @@ void ath11k_wmi_fw_stats_fill(struct ath - int ath11k_wmi_simulate_radar(struct ath11k *ar); - int ath11k_wmi_send_twt_enable_cmd(struct ath11k *ar, u32 pdev_id); - int ath11k_wmi_send_twt_disable_cmd(struct ath11k *ar, u32 pdev_id); -+int ath11k_wmi_send_twt_add_dialog_cmd(struct ath11k *ar, -+ struct wmi_twt_add_dialog_params *params); -+int ath11k_wmi_send_twt_del_dialog_cmd(struct ath11k *ar, -+ struct wmi_twt_del_dialog_params *params); -+int ath11k_wmi_send_twt_pause_dialog_cmd(struct ath11k *ar, -+ struct wmi_twt_pause_dialog_params *params); -+int ath11k_wmi_send_twt_resume_dialog_cmd(struct ath11k *ar, -+ struct wmi_twt_resume_dialog_params *params); - int ath11k_wmi_send_obss_spr_cmd(struct ath11k *ar, u32 vdev_id, - struct ieee80211_he_obss_pd *he_obss_pd); - int ath11k_wmi_pdev_set_srg_bss_color_bitmap(struct ath11k *ar, u32 *bitmap); ---- a/drivers/net/wireless/ath/ath11k/core.h -+++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -273,6 +273,7 @@ struct ath11k_vif { - bool bcca_zero_sent; - bool do_not_send_tmpl; - struct ieee80211_chanctx_conf chanctx; -+ struct dentry *debugfs_twt; - }; - - struct ath11k_vif_iter { ---- a/drivers/net/wireless/ath/ath11k/debugfs.c -+++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -53,6 +53,203 @@ static const char *htt_bp_lmac_ring[HTT_ - "MONITOR_DEST_RING", - }; - -+#ifdef CPTCFG_MAC80211_DEBUGFS -+static ssize_t ath11k_write_twt_add_dialog(struct file *file, -+ const char __user *ubuf, -+ size_t count, loff_t *ppos) -+{ -+ struct ath11k_vif *arvif = file->private_data; -+ struct wmi_twt_add_dialog_params params = { 0 }; -+ u8 buf[128] = {0}; -+ int ret; -+ -+ ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count); -+ if (ret < 0) { -+ return ret; -+ } -+ buf[ret] = '\0'; -+ ret = sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx %u %u %u %u %u %hhu %hhu %hhu %hhu %hhu", -+ ¶ms.peer_macaddr[0], -+ ¶ms.peer_macaddr[1], -+ ¶ms.peer_macaddr[2], -+ ¶ms.peer_macaddr[3], -+ ¶ms.peer_macaddr[4], -+ ¶ms.peer_macaddr[5], -+ ¶ms.dialog_id, -+ ¶ms.wake_intvl_us, -+ ¶ms.wake_intvl_mantis, -+ ¶ms.wake_dura_us, -+ ¶ms.sp_offset_us, -+ ¶ms.twt_cmd, -+ ¶ms.flag_bcast, -+ ¶ms.flag_trigger, -+ ¶ms.flag_flow_type, -+ ¶ms.flag_protection); -+ if (ret != 16) -+ return -EINVAL; -+ -+ params.vdev_id = arvif->vdev_id; -+ -+ ret = ath11k_wmi_send_twt_add_dialog_cmd(arvif->ar, ¶ms); -+ -+ return ret ? ret : count; -+} -+ -+static ssize_t ath11k_write_twt_del_dialog(struct file *file, -+ const char __user *ubuf, -+ size_t count, loff_t *ppos) -+{ -+ struct ath11k_vif *arvif = file->private_data; -+ struct wmi_twt_del_dialog_params params = { 0 }; -+ u8 buf[64] = {0}; -+ int ret; -+ -+ ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count); -+ if (ret < 0) { -+ return ret; -+ } -+ buf[ret] = '\0'; -+ ret = sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx %u", -+ ¶ms.peer_macaddr[0], -+ ¶ms.peer_macaddr[1], -+ ¶ms.peer_macaddr[2], -+ ¶ms.peer_macaddr[3], -+ ¶ms.peer_macaddr[4], -+ ¶ms.peer_macaddr[5], -+ ¶ms.dialog_id); -+ if (ret != 7) -+ return -EINVAL; -+ -+ params.vdev_id = arvif->vdev_id; -+ -+ ret = ath11k_wmi_send_twt_del_dialog_cmd(arvif->ar, ¶ms); -+ -+ return ret ? ret : count; -+} -+ -+static ssize_t ath11k_write_twt_pause_dialog(struct file *file, -+ const char __user *ubuf, -+ size_t count, loff_t *ppos) -+{ -+ struct ath11k_vif *arvif = file->private_data; -+ struct wmi_twt_pause_dialog_params params = { 0 }; -+ u8 buf[64] = {0}; -+ int ret; -+ -+ ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count); -+ if (ret < 0) { -+ return ret; -+ } -+ buf[ret] = '\0'; -+ ret = sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx %u", -+ ¶ms.peer_macaddr[0], -+ ¶ms.peer_macaddr[1], -+ ¶ms.peer_macaddr[2], -+ ¶ms.peer_macaddr[3], -+ ¶ms.peer_macaddr[4], -+ ¶ms.peer_macaddr[5], -+ ¶ms.dialog_id); -+ if (ret != 7) -+ return -EINVAL; -+ -+ params.vdev_id = arvif->vdev_id; -+ -+ ret = ath11k_wmi_send_twt_pause_dialog_cmd(arvif->ar, ¶ms); -+ -+ return ret ? ret : count; -+} -+ -+ -+static ssize_t ath11k_write_twt_resume_dialog(struct file *file, -+ const char __user *ubuf, -+ size_t count, loff_t *ppos) -+{ -+ struct ath11k_vif *arvif = file->private_data; -+ struct wmi_twt_resume_dialog_params params = { 0 }; -+ u8 buf[64] = {0}; -+ int ret; -+ -+ ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count); -+ if (ret < 0) { -+ return ret; -+ } -+ buf[ret] = '\0'; -+ ret = sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx %u %u %u", -+ ¶ms.peer_macaddr[0], -+ ¶ms.peer_macaddr[1], -+ ¶ms.peer_macaddr[2], -+ ¶ms.peer_macaddr[3], -+ ¶ms.peer_macaddr[4], -+ ¶ms.peer_macaddr[5], -+ ¶ms.dialog_id, -+ ¶ms.sp_offset_us, -+ ¶ms.next_twt_size); -+ if (ret != 9) -+ return -EINVAL; -+ -+ params.vdev_id = arvif->vdev_id; -+ -+ ret = ath11k_wmi_send_twt_resume_dialog_cmd(arvif->ar, ¶ms); -+ -+ return ret ? ret : count; -+} -+ -+static const struct file_operations ath11k_fops_twt_add_dialog = { -+ .write = ath11k_write_twt_add_dialog, -+ .open = simple_open -+}; -+ -+static const struct file_operations ath11k_fops_twt_del_dialog = { -+ .write = ath11k_write_twt_del_dialog, -+ .open = simple_open -+}; -+ -+static const struct file_operations ath11k_fops_twt_pause_dialog = { -+ .write = ath11k_write_twt_pause_dialog, -+ .open = simple_open -+}; -+ -+static const struct file_operations ath11k_fops_twt_resume_dialog = { -+ .write = ath11k_write_twt_resume_dialog, -+ .open = simple_open -+}; -+ -+void ath11k_debugfs_twt(struct ath11k_vif *arvif, bool enable) -+{ -+ if (!enable && arvif->debugfs_twt) { -+ debugfs_remove_recursive(arvif->debugfs_twt); -+ arvif->debugfs_twt = NULL; -+ return; -+ } -+ -+ if (arvif->debugfs_twt) -+ return; -+ -+ arvif->debugfs_twt = debugfs_create_dir("twt", arvif->vif->debugfs_dir); -+ if (IS_ERR_OR_NULL(arvif->debugfs_twt)) { -+ ath11k_warn(arvif->ar->ab, "failed to create twt debugfs: %p\n", arvif->debugfs_twt); -+ arvif->debugfs_twt = NULL; -+ return; -+ } -+ -+ debugfs_create_file("add_dialog", 0200, -+ arvif->debugfs_twt, arvif, -+ &ath11k_fops_twt_add_dialog); -+ -+ debugfs_create_file("del_dialog", 0200, -+ arvif->debugfs_twt, arvif, -+ &ath11k_fops_twt_del_dialog); -+ -+ debugfs_create_file("pause_dialog", 0200, -+ arvif->debugfs_twt, arvif, -+ &ath11k_fops_twt_pause_dialog); -+ -+ debugfs_create_file("resume_dialog", 0200, -+ arvif->debugfs_twt, arvif, -+ &ath11k_fops_twt_resume_dialog); -+} -+#endif -+ - static void ath11k_fw_stats_pdevs_free(struct list_head *head) - { - struct ath11k_fw_stats_pdev *i, *tmp; ---- a/drivers/net/wireless/ath/ath11k/debugfs.h -+++ b/drivers/net/wireless/ath/ath11k/debugfs.h -@@ -107,6 +107,15 @@ enum ath11k_dbg_aggr_mode { - ATH11K_DBG_AGGR_MODE_MAX, - }; - -+#ifdef CPTCFG_MAC80211_DEBUGFS -+void ath11k_debugfs_twt(struct ath11k_vif *arvif, bool enable); -+#else -+static inline void ath11k_debugfs_twt(struct ath11k_vif *arvif, bool enable) -+{ -+ -+} -+#endif -+ - #ifdef CPTCFG_ATH11K_DEBUGFS - int ath11k_debugfs_soc_create(struct ath11k_base *ab); - void ath11k_debugfs_soc_destroy(struct ath11k_base *ab); ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -5686,7 +5686,8 @@ static int nl80211_start_ap(struct sk_bu - } - } - -- params->twt_responder = -+ if (info->attrs[NL80211_ATTR_TWT_RESPONDER]) -+ params->twt_responder = - nla_get_flag(info->attrs[NL80211_ATTR_TWT_RESPONDER]); - - if (info->attrs[NL80211_ATTR_HE_OBSS_PD]) { diff --git a/feeds/ipq95xx/mac80211/patches/qca/059-ath11k-add-he-fields-into-radiotap-header.patch b/feeds/ipq95xx/mac80211/patches/qca/059-ath11k-add-he-fields-into-radiotap-header.patch deleted file mode 100644 index 666944d09..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/059-ath11k-add-he-fields-into-radiotap-header.patch +++ /dev/null @@ -1,1107 +0,0 @@ -From 9afeb9b40161e74565f3e7ea7ee665d87901c7f6 Mon Sep 17 00:00:00 2001 -From: Miles Hu -Date: Mon, 21 Oct 2019 17:47:10 -0700 -Subject: [PATCH] ath11k: add he fields into radiotap header parse he fields in - ppdu tlv and enable he & he_mu in radiotap. fix qos tag missing in native - wifi mode. add rssi and tsf in radiotap. - -todo: -add he_mu_other after bringup branch rebasing mac80211. -add vht coding, mimo group id and partial aid. - -Signed-off-by: Miles Hu ---- - drivers/net/wireless/ath/ath11k/dp_rx.c | 109 +++++-- - drivers/net/wireless/ath/ath11k/hal_desc.h | 1 + - drivers/net/wireless/ath/ath11k/hal_rx.c | 437 ++++++++++++++++++++++++++--- - drivers/net/wireless/ath/ath11k/hal_rx.h | 229 ++++++++++++++- - net/mac80211/util.c | 7 + - 5 files changed, 717 insertions(+), 66 deletions(-) - ---- a/drivers/net/wireless/ath/ath11k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -4809,14 +4809,15 @@ ath11k_dp_rx_mon_merg_msdus(struct ath11 - { - struct ath11k_base *ab = ar->ab; - struct sk_buff *msdu, *prev_buf; -- u32 wifi_hdr_len; - struct hal_rx_desc *rx_desc; - char *hdr_desc; - u8 *dest, decap_format; - struct ieee80211_hdr_3addr *wh; - struct rx_attention *rx_attention; - u32 err_bitmap; -+ static u32 pkt_type = 0; - -+ pkt_type++; - if (!head_msdu) - goto err_merge_fail; - -@@ -4851,38 +4852,28 @@ ath11k_dp_rx_mon_merg_msdus(struct ath11 - - skb_trim(prev_buf, prev_buf->len - HAL_RX_FCS_LEN); - } else if (decap_format == DP_RX_DECAP_TYPE_NATIVE_WIFI) { -- __le16 qos_field; - u8 qos_pkt = 0; - - rx_desc = (struct hal_rx_desc *)head_msdu->data; - hdr_desc = ath11k_dp_rxdesc_get_80211hdr(ab, rx_desc); - - /* Base size */ -- wifi_hdr_len = sizeof(struct ieee80211_hdr_3addr); - wh = (struct ieee80211_hdr_3addr *)hdr_desc; - - if (ieee80211_is_data_qos(wh->frame_control)) { -- struct ieee80211_qos_hdr *qwh = -- (struct ieee80211_qos_hdr *)hdr_desc; -- -- qos_field = qwh->qos_ctrl; - qos_pkt = 1; - } - msdu = head_msdu; - - while (msdu) { -- rx_desc = (struct hal_rx_desc *)msdu->data; -- hdr_desc = ath11k_dp_rxdesc_get_80211hdr(ab, rx_desc); - -+ ath11k_dp_rx_msdus_set_payload(ar, msdu); - if (qos_pkt) { - dest = skb_push(msdu, sizeof(__le16)); - if (!dest) - goto err_merge_fail; -- memcpy(dest, hdr_desc, wifi_hdr_len); -- memcpy(dest + wifi_hdr_len, -- (u8 *)&qos_field, sizeof(__le16)); -+ memcpy(dest, hdr_desc, sizeof(struct ieee80211_qos_hdr)); - } -- ath11k_dp_rx_msdus_set_payload(ar, msdu); - prev_buf = msdu; - msdu = msdu->next; - } -@@ -4906,8 +4897,85 @@ err_merge_fail: - return NULL; - } - -+static void -+ath11k_dp_rx_update_radiotap_he(struct hal_rx_mon_ppdu_info *rx_status, -+ u8 *rtap_buf) -+{ -+ u32 rtap_len = 0; -+ -+ put_unaligned_le16(rx_status->he_data1, &rtap_buf[rtap_len]); -+ rtap_len += 2; -+ -+ put_unaligned_le16(rx_status->he_data2, &rtap_buf[rtap_len]); -+ rtap_len += 2; -+ -+ put_unaligned_le16(rx_status->he_data3, &rtap_buf[rtap_len]); -+ rtap_len += 2; -+ -+ put_unaligned_le16(rx_status->he_data4, &rtap_buf[rtap_len]); -+ rtap_len += 2; -+ -+ put_unaligned_le16(rx_status->he_data5, &rtap_buf[rtap_len]); -+ rtap_len += 2; -+ -+ put_unaligned_le16(rx_status->he_data6, &rtap_buf[rtap_len]); -+} -+ -+static void -+ath11k_dp_rx_update_radiotap_he_mu(struct hal_rx_mon_ppdu_info *rx_status, -+ u8 *rtap_buf) -+{ -+ u32 rtap_len = 0; -+ -+ put_unaligned_le16(rx_status->he_flags1, &rtap_buf[rtap_len]); -+ rtap_len += 2; -+ -+ put_unaligned_le16(rx_status->he_flags2, &rtap_buf[rtap_len]); -+ rtap_len += 2; -+ -+ rtap_buf[rtap_len] = rx_status->he_RU[0]; -+ rtap_len += 1; -+ -+ rtap_buf[rtap_len] = rx_status->he_RU[1]; -+ rtap_len += 1; -+ -+ rtap_buf[rtap_len] = rx_status->he_RU[2]; -+ rtap_len += 1; -+ -+ rtap_buf[rtap_len] = rx_status->he_RU[3]; -+} -+ -+static void ath11k_update_radiotap(struct hal_rx_mon_ppdu_info *ppduinfo, -+ struct sk_buff *mon_skb, -+ struct ieee80211_rx_status *rxs) -+{ -+ u8 *ptr = NULL; -+ -+ if (ppduinfo->he_mu_flags) { -+ rxs->flag |= RX_FLAG_RADIOTAP_HE_MU; -+ rxs->encoding = RX_ENC_HE; -+ ptr = skb_push(mon_skb, sizeof(struct ieee80211_radiotap_he_mu)); -+ ath11k_dp_rx_update_radiotap_he_mu(ppduinfo, ptr); -+ } -+ if (ppduinfo->he_flags) { -+ rxs->flag |= RX_FLAG_RADIOTAP_HE; -+ rxs->encoding = RX_ENC_HE; -+ ptr = skb_push(mon_skb, sizeof(struct ieee80211_radiotap_he)); -+ ath11k_dp_rx_update_radiotap_he(ppduinfo, ptr); -+ } -+ -+ rxs->flag |= RX_FLAG_MACTIME_START; -+ rxs->signal = ppduinfo->rssi_comb + ATH11K_DEFAULT_NOISE_FLOOR; -+ -+ if (ppduinfo->nss) -+ rxs->nss = ppduinfo->nss; -+ -+ rxs->mactime = ppduinfo->tsft; -+} -+ - static int ath11k_dp_rx_mon_deliver(struct ath11k *ar, u32 mac_id, - struct sk_buff *head_msdu, -+ struct hal_rx_mon_ppdu_info *ppduinfo, - struct sk_buff *tail_msdu, - struct napi_struct *napi) - { -@@ -4943,7 +5011,7 @@ static int ath11k_dp_rx_mon_deliver(stru - rxs->flag |= RX_FLAG_ALLOW_SAME_PN; - } - rxs->flag |= RX_FLAG_ONLY_MONITOR; -- -+ ath11k_update_radiotap(ppduinfo, mon_skb, rxs); - ath11k_dp_rx_deliver_msdu(ar, napi, mon_skb, rxs); - mon_skb = skb_next; - } while (mon_skb); -@@ -5017,6 +5085,7 @@ static void ath11k_dp_rx_mon_dest_proces - } - if (head_msdu && tail_msdu) { - ath11k_dp_rx_mon_deliver(ar, dp->mac_id, head_msdu, -+ &pmon->mon_ppdu_info, - tail_msdu, napi); - rx_mon_stats->dest_mpdu_done++; - } ---- a/drivers/net/wireless/ath/ath11k/hal_desc.h -+++ b/drivers/net/wireless/ath/ath11k/hal_desc.h -@@ -474,6 +474,7 @@ enum hal_tlv_tag { - - #define HAL_TLV_HDR_TAG GENMASK(9, 1) - #define HAL_TLV_HDR_LEN GENMASK(25, 10) -+#define HAL_TLV_USR_ID GENMASK(31, 26) - - #define HAL_TLV_ALIGN 4 - ---- a/drivers/net/wireless/ath/ath11k/hal_rx.c -+++ b/drivers/net/wireless/ath/ath11k/hal_rx.c -@@ -802,12 +802,75 @@ void ath11k_hal_reo_init_cmd_ring(struct - } - } - -+#define HAL_MAX_UL_MU_USERS 37 -+static inline void -+ath11k_hal_rx_handle_ofdma_info(void *rx_tlv, -+ struct hal_rx_user_status *rx_user_status) -+{ -+ struct hal_rx_ppdu_end_user_stats *ppdu_end_user = -+ (struct hal_rx_ppdu_end_user_stats *)rx_tlv; -+ -+ rx_user_status->ul_ofdma_user_v0_word0 = ppdu_end_user->info6; -+ -+ rx_user_status->ul_ofdma_user_v0_word1 = ppdu_end_user->rsvd2[10]; -+} -+ -+static inline void -+ath11k_hal_rx_populate_byte_count(void *rx_tlv, void *ppduinfo, -+ struct hal_rx_user_status *rx_user_status) -+{ -+ struct hal_rx_ppdu_end_user_stats *ppdu_end_user = -+ (struct hal_rx_ppdu_end_user_stats *)rx_tlv; -+ -+ rx_user_status->mpdu_ok_byte_count = -+ FIELD_GET(HAL_RX_PPDU_END_USER_STATS_RSVD2_6_MPDU_OK_BYTE_COUNT, -+ ppdu_end_user->rsvd2[6]); -+ rx_user_status->mpdu_err_byte_count = -+ FIELD_GET(HAL_RX_PPDU_END_USER_STATS_RSVD2_8_MPDU_ERR_BYTE_COUNT, -+ ppdu_end_user->rsvd2[8]); -+} -+ -+static inline void -+ath11k_hal_rx_populate_mu_user_info(void *rx_tlv, struct hal_rx_mon_ppdu_info *ppdu_info, -+ struct hal_rx_user_status *rx_user_status) -+{ -+ rx_user_status->ast_index = ppdu_info->ast_index; -+ rx_user_status->tid = ppdu_info->tid; -+ rx_user_status->tcp_msdu_count = -+ ppdu_info->tcp_msdu_count; -+ rx_user_status->udp_msdu_count = -+ ppdu_info->udp_msdu_count; -+ rx_user_status->other_msdu_count = -+ ppdu_info->other_msdu_count; -+ rx_user_status->frame_control = ppdu_info->frame_control; -+ rx_user_status->frame_control_info_valid = -+ ppdu_info->frame_control_info_valid; -+ rx_user_status->data_sequence_control_info_valid = -+ ppdu_info->data_sequence_control_info_valid; -+ rx_user_status->first_data_seq_ctrl = -+ ppdu_info->first_data_seq_ctrl; -+ rx_user_status->preamble_type = ppdu_info->preamble_type; -+ rx_user_status->ht_flags = ppdu_info->ht_flags; -+ rx_user_status->vht_flags = ppdu_info->vht_flags; -+ rx_user_status->he_flags = ppdu_info->he_flags; -+ rx_user_status->rs_flags = ppdu_info->rs_flags; -+ -+ rx_user_status->mpdu_cnt_fcs_ok = -+ ppdu_info->num_mpdu_fcs_ok; -+ rx_user_status->mpdu_cnt_fcs_err = -+ ppdu_info->num_mpdu_fcs_err; -+ -+ ath11k_hal_rx_populate_byte_count(rx_tlv, ppdu_info, rx_user_status); -+} -+ - static enum hal_rx_mon_status - ath11k_hal_rx_parse_mon_status_tlv(struct ath11k_base *ab, - struct hal_rx_mon_ppdu_info *ppdu_info, -- u32 tlv_tag, u8 *tlv_data) -+ u32 tlv_tag, u8 *tlv_data, u32 userid) - { -- u32 info0, info1; -+ u32 info0, info1, value; -+ u8 he_dcm = 0, he_stbc = 0; -+ u16 he_gi = 0, he_ltf = 0; - - switch (tlv_tag) { - case HAL_RX_PPDU_START: { -@@ -828,6 +891,9 @@ ath11k_hal_rx_parse_mon_status_tlv(struc - info0 = __le32_to_cpu(eu_stats->info0); - info1 = __le32_to_cpu(eu_stats->info1); - -+ ppdu_info->ast_index = -+ FIELD_GET(HAL_RX_PPDU_END_USER_STATS_INFO2_AST_INDEX, -+ __le32_to_cpu(eu_stats->info2)); - ppdu_info->tid = - ffs(FIELD_GET(HAL_RX_PPDU_END_USER_STATS_INFO6_TID_BITMAP, - __le32_to_cpu(eu_stats->info6))) - 1; -@@ -851,6 +917,42 @@ ath11k_hal_rx_parse_mon_status_tlv(struc - ppdu_info->num_mpdu_fcs_err = - FIELD_GET(HAL_RX_PPDU_END_USER_STATS_INFO0_MPDU_CNT_FCS_ERR, - info0); -+ switch (ppdu_info->preamble_type) { -+ case HAL_RX_PREAMBLE_11N: -+ ppdu_info->ht_flags = 1; -+ break; -+ case HAL_RX_PREAMBLE_11AC: -+ ppdu_info->vht_flags = 1; -+ break; -+ case HAL_RX_PREAMBLE_11AX: -+ ppdu_info->he_flags = 1; -+ break; -+ default: -+ break; -+ } -+ -+ if(userid < HAL_MAX_UL_MU_USERS) { -+ struct hal_rx_user_status *rxuser_stats = -+ &ppdu_info->userstats; -+ -+ ath11k_hal_rx_handle_ofdma_info(tlv_data, rxuser_stats); -+ ath11k_hal_rx_populate_mu_user_info(tlv_data, ppdu_info, -+ rxuser_stats); -+ } -+ ppdu_info->userstats.mpdu_fcs_ok_bitmap[0] = eu_stats->rsvd1[0]; -+ ppdu_info->userstats.mpdu_fcs_ok_bitmap[1] = eu_stats->rsvd1[1]; -+ -+ break; -+ } -+ case HAL_RX_PPDU_END_USER_STATS_EXT: { -+ struct hal_rx_ppdu_end_user_stats_ext *eu_stats = -+ (struct hal_rx_ppdu_end_user_stats_ext *)tlv_data; -+ ppdu_info->userstats.mpdu_fcs_ok_bitmap[2] = eu_stats->info1; -+ ppdu_info->userstats.mpdu_fcs_ok_bitmap[3] = eu_stats->info2; -+ ppdu_info->userstats.mpdu_fcs_ok_bitmap[4] = eu_stats->info3; -+ ppdu_info->userstats.mpdu_fcs_ok_bitmap[5] = eu_stats->info4; -+ ppdu_info->userstats.mpdu_fcs_ok_bitmap[6] = eu_stats->info5; -+ ppdu_info->userstats.mpdu_fcs_ok_bitmap[7] = eu_stats->info6; - break; - } - case HAL_PHYRX_HT_SIG: { -@@ -917,7 +1019,7 @@ ath11k_hal_rx_parse_mon_status_tlv(struc - info1 = __le32_to_cpu(vht_sig->info1); - - ppdu_info->ldpc = FIELD_GET(HAL_RX_VHT_SIG_A_INFO_INFO1_SU_MU_CODING, -- info0); -+ info1); - ppdu_info->mcs = FIELD_GET(HAL_RX_VHT_SIG_A_INFO_INFO1_MCS, - info1); - gi_setting = FIELD_GET(HAL_RX_VHT_SIG_A_INFO_INFO1_GI_SETTING, -@@ -949,23 +1051,153 @@ ath11k_hal_rx_parse_mon_status_tlv(struc - else - ppdu_info->reception_type = - HAL_RX_RECEPTION_TYPE_MU_MIMO; -+ ppdu_info->vht_flag_values5 = group_id; -+ ppdu_info->vht_flag_values3[0] = (((ppdu_info->mcs) << 4) | -+ ppdu_info->nss); -+ ppdu_info->vht_flag_values2 = ppdu_info->bw; -+ ppdu_info->vht_flag_values4 = -+ FIELD_GET(HAL_RX_VHT_SIG_A_INFO_INFO1_SU_MU_CODING, info1); - break; - } - case HAL_PHYRX_HE_SIG_A_SU: { - struct hal_rx_he_sig_a_su_info *he_sig_a = - (struct hal_rx_he_sig_a_su_info *)tlv_data; -- u32 nsts, cp_ltf, dcm; -+ u32 nsts, cp_ltf, dcm, value; -+ ppdu_info->he_flags = 1; - - info0 = __le32_to_cpu(he_sig_a->info0); - info1 = __le32_to_cpu(he_sig_a->info1); - -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO0_FORMAT_IND, info0); -+ -+ if (value == 0) { -+ ppdu_info->he_data1 = HE_TRIG_FORMAT_TYPE; -+ } else { -+ ppdu_info->he_data1 = HE_SU_FORMAT_TYPE; -+ } -+ ppdu_info->he_data1 |= -+ HE_BSS_COLOR_KNOWN | -+ HE_BEAM_CHANGE_KNOWN | -+ HE_DL_UL_KNOWN | -+ HE_MCS_KNOWN | -+ HE_DCM_KNOWN | -+ HE_CODING_KNOWN | -+ HE_LDPC_EXTRA_SYMBOL_KNOWN | -+ HE_STBC_KNOWN | -+ HE_DATA_BW_RU_KNOWN | -+ HE_DOPPLER_KNOWN; -+ -+ ppdu_info->he_data2 |= -+ HE_GI_KNOWN | -+ HE_TXBF_KNOWN | -+ HE_PE_DISAMBIGUITY_KNOWN | -+ HE_TXOP_KNOWN | -+ HE_LTF_SYMBOLS_KNOWN | -+ HE_PRE_FEC_PADDING_KNOWN | -+ HE_MIDABLE_PERIODICITY_KNOWN; -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO0_BSS_COLOR, info0); -+ ppdu_info->he_data3 = value; -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO0_BEAM_CHANGE, info0); -+ value = value << HE_BEAM_CHANGE_SHIFT; -+ ppdu_info->he_data3 |= value; -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO0_DL_UL_FLAG, info0); -+ value = value << HE_DL_UL_SHIFT; -+ ppdu_info->he_data3 |= value; -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO0_TRANSMIT_MCS, info0); -+ ppdu_info->mcs = value; -+ value = value << HE_TRANSMIT_MCS_SHIFT; -+ ppdu_info->he_data3 |= value; -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO0_DCM, info0); -+ he_dcm = value; -+ value = value << HE_DCM_SHIFT; -+ ppdu_info->he_data3 |= value; -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO1_CODING, info1); -+ value = value << HE_CODING_SHIFT; -+ ppdu_info->he_data3 |= value; -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO1_LDPC_EXTRA, info1); -+ value = value << HE_LDPC_EXTRA_SYMBOL_SHIFT; -+ ppdu_info->he_data3 |= value; -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO1_STBC, info1); -+ he_stbc = value; -+ value = value << HE_STBC_SHIFT; -+ ppdu_info->he_data3 |= value; -+ -+ /* data4 */ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO0_SPATIAL_REUSE, info0); -+ ppdu_info->he_data4 = value; -+ -+ /* data5 */ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO0_TRANSMIT_BW, info0); -+ ppdu_info->he_data5 = value; -+ ppdu_info->bw = value; -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO0_CP_LTF_SIZE, info0); -+ switch (value) { -+ case 0: -+ he_gi = HE_GI_0_8; -+ he_ltf = HE_LTF_1_X; -+ break; -+ case 1: -+ he_gi = HE_GI_0_8; -+ he_ltf = HE_LTF_2_X; -+ break; -+ case 2: -+ he_gi = HE_GI_1_6; -+ he_ltf = HE_LTF_2_X; -+ break; -+ case 3: -+ if (he_dcm && he_stbc) { -+ he_gi = HE_GI_0_8; -+ he_ltf = HE_LTF_4_X; -+ } else { -+ he_gi = HE_GI_3_2; -+ he_ltf = HE_LTF_4_X; -+ } -+ break; -+ } -+ ppdu_info->gi = he_gi; -+ value = he_gi << HE_GI_SHIFT; -+ ppdu_info->he_data5 |= value; -+ value = he_ltf << HE_LTF_SIZE_SHIFT; -+ ppdu_info->ltf_size = he_ltf; -+ ppdu_info->he_data5 |= value; -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO0_NSTS, info0); -+ value = (value << HE_LTF_SYM_SHIFT); -+ ppdu_info->he_data5 |= value; -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO1_PKT_EXT_FACTOR, info1); -+ value = value << HE_PRE_FEC_PAD_SHIFT; -+ ppdu_info->he_data5 |= value; -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO1_TXBF, info1); -+ value = value << HE_TXBF_SHIFT; -+ ppdu_info->he_data5 |= value; -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO1_PKT_EXT_PE_DISAM, info1); -+ value = value << HE_PE_DISAMBIGUITY_SHIFT; -+ ppdu_info->he_data5 |= value; -+ -+ /* data6 */ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO0_NSTS, info0); -+ value++; -+ ppdu_info->nss = value; -+ ppdu_info->he_data6 = value; -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO1_DOPPLER_IND, info1); -+ value = value << HE_DOPPLER_SHIFT; -+ ppdu_info->he_data6 |= value; -+ value = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO1_TXOP_DURATION, info1); -+ value = value << HE_TXOP_SHIFT; -+ ppdu_info->he_data6 |= value; -+ - ppdu_info->mcs = - FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO0_TRANSMIT_MCS, - info0); - ppdu_info->bw = - FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO0_TRANSMIT_BW, - info0); -- ppdu_info->ldpc = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO1_CODING, info0); -+ ppdu_info->ldpc = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO1_CODING, info1); - ppdu_info->is_stbc = info1 & - HAL_RX_HE_SIG_A_SU_INFO_INFO1_STBC; - ppdu_info->beamformed = info1 & -@@ -975,22 +1207,6 @@ ath11k_hal_rx_parse_mon_status_tlv(struc - info0); - nsts = FIELD_GET(HAL_RX_HE_SIG_A_SU_INFO_INFO0_NSTS, info0); - -- switch (cp_ltf) { -- case 0: -- case 1: -- ppdu_info->gi = HAL_RX_GI_0_8_US; -- break; -- case 2: -- ppdu_info->gi = HAL_RX_GI_1_6_US; -- break; -- case 3: -- if (dcm && ppdu_info->is_stbc) -- ppdu_info->gi = HAL_RX_GI_0_8_US; -- else -- ppdu_info->gi = HAL_RX_GI_3_2_US; -- break; -- } -- - ppdu_info->nss = nsts + 1; - ppdu_info->dcm = dcm; - ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_SU; -@@ -1000,32 +1216,133 @@ ath11k_hal_rx_parse_mon_status_tlv(struc - struct hal_rx_he_sig_a_mu_dl_info *he_sig_a_mu_dl = - (struct hal_rx_he_sig_a_mu_dl_info *)tlv_data; - -- u32 cp_ltf; -- - info0 = __le32_to_cpu(he_sig_a_mu_dl->info0); - info1 = __le32_to_cpu(he_sig_a_mu_dl->info1); - -- ppdu_info->bw = -- FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO_INFO0_TRANSMIT_BW, -- info0); -- cp_ltf = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO_INFO0_CP_LTF_SIZE, -- info0); -+ ppdu_info->he_mu_flags = 1; -+ -+ ppdu_info->he_data1 = HE_MU_FORMAT_TYPE; -+ ppdu_info->he_data1 |= -+ HE_BSS_COLOR_KNOWN | -+ HE_DL_UL_KNOWN | -+ HE_LDPC_EXTRA_SYMBOL_KNOWN | -+ HE_STBC_KNOWN | -+ HE_DATA_BW_RU_KNOWN | -+ HE_DOPPLER_KNOWN; -+ -+ ppdu_info->he_data2 = -+ HE_GI_KNOWN | -+ HE_LTF_SYMBOLS_KNOWN | -+ HE_PRE_FEC_PADDING_KNOWN | -+ HE_PE_DISAMBIGUITY_KNOWN | -+ HE_TXOP_KNOWN | -+ HE_MIDABLE_PERIODICITY_KNOWN; -+ -+ /*data3*/ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO0_BSS_COLOR, info0); -+ ppdu_info->he_data3 = value; -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO0_UL_FLAG, info0); -+ value = value << HE_DL_UL_SHIFT; -+ ppdu_info->he_data3 |= value; -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO1_LDPC_EXTRA, info1); -+ value = value << HE_LDPC_EXTRA_SYMBOL_SHIFT; -+ ppdu_info->he_data3 |= value; -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO1_STBC, info1); -+ he_stbc = value; -+ value = value << HE_STBC_SHIFT; -+ ppdu_info->he_data3 |= value; -+ -+ /*data4*/ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO0_SPATIAL_REUSE, info0); -+ ppdu_info->he_data4 = value; -+ -+ /*data5*/ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO0_TRANSMIT_BW, info0); -+ ppdu_info->he_data5 = value; -+ ppdu_info->bw = value; - -- switch (cp_ltf) { -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO0_CP_LTF_SIZE, info0); -+ switch (value) { - case 0: -+ he_gi = HE_GI_0_8; -+ he_ltf = HE_LTF_4_X; -+ break; - case 1: -- ppdu_info->gi = HAL_RX_GI_0_8_US; -+ he_gi = HE_GI_0_8; -+ he_ltf = HE_LTF_2_X; - break; - case 2: -- ppdu_info->gi = HAL_RX_GI_1_6_US; -+ he_gi = HE_GI_1_6; -+ he_ltf = HE_LTF_2_X; - break; - case 3: -- ppdu_info->gi = HAL_RX_GI_3_2_US; -+ he_gi = HE_GI_3_2; -+ he_ltf = HE_LTF_4_X; - break; - } -+ ppdu_info->gi = he_gi; -+ value = he_gi << HE_GI_SHIFT; -+ ppdu_info->he_data5 |= value; -+ -+ value = he_ltf << HE_LTF_SIZE_SHIFT; -+ ppdu_info->he_data5 |= value; -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO1_NUM_LTF_SYMB, info1); -+ value = (value << HE_LTF_SYM_SHIFT); -+ ppdu_info->he_data5 |= value; -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO1_PKT_EXT_FACTOR, info1); -+ value = value << HE_PRE_FEC_PAD_SHIFT; -+ ppdu_info->he_data5 |= value; -+ -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO1_PKT_EXT_PE_DISAM, info1); -+ value = value << HE_PE_DISAMBIGUITY_SHIFT; -+ ppdu_info->he_data5 |= value; -+ -+ /*data6*/ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO0_DOPPLER_INDICATION, info0); -+ value = value << HE_DOPPLER_SHIFT; -+ ppdu_info->he_data6 |= value; -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO1_TXOP_DURATION, info1); -+ value = value << HE_TXOP_SHIFT; -+ ppdu_info->he_data6 |= value; -+ -+ /* HE-MU Flags */ -+ /* HE-MU-flags1 */ -+ ppdu_info->he_flags1 = -+ HE_SIG_B_MCS_KNOWN | -+ HE_SIG_B_DCM_KNOWN | -+ HE_SIG_B_COMPRESSION_FLAG_1_KNOWN | -+ HE_SIG_B_SYM_NUM_KNOWN | -+ HE_RU_0_KNOWN; -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO0_MCS_OF_SIGB, info0); -+ ppdu_info->he_flags1 |= value; -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO0_DCM_OF_SIGB, info0); -+ value = value << HE_DCM_FLAG_1_SHIFT; -+ ppdu_info->he_flags1 |= value; -+ -+ /* HE-MU-flags2 */ -+ ppdu_info->he_flags2 = -+ HE_BW_KNOWN; -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO0_TRANSMIT_BW, info0); -+ ppdu_info->he_flags2 |= value; -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO0_COMP_MODE_SIGB, info0); -+ value = value << HE_SIG_B_COMPRESSION_FLAG_2_SHIFT; -+ ppdu_info->he_flags2 |= value; -+ value = FIELD_GET(HAL_RX_HE_SIG_A_MU_DL_INFO0_NUM_SIGB_SYMB, info0); -+ value = value - 1; -+ value = value << HE_NUM_SIG_B_SYMBOLS_SHIFT; -+ ppdu_info->he_flags2 |= value; - - ppdu_info->is_stbc = info1 & -- HAL_RX_HE_SIG_A_MU_DL_INFO_INFO1_STBC; -+ HAL_RX_HE_SIG_A_MU_DL_INFO1_STBC; - ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_MU_MIMO; - break; - } -@@ -1040,7 +1357,7 @@ ath11k_hal_rx_parse_mon_status_tlv(struc - info0); - ppdu_info->ru_alloc = - ath11k_mac_phy_he_ru_to_nl80211_he_ru_alloc(ru_tones); -- -+ ppdu_info->he_RU[0] = ru_tones; - ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_MU_MIMO; - break; - } -@@ -1050,14 +1367,25 @@ ath11k_hal_rx_parse_mon_status_tlv(struc - - info0 = __le32_to_cpu(he_sig_b2_mu->info0); - -+ ppdu_info->he_data1 |= HE_MCS_KNOWN | HE_CODING_KNOWN; -+ - ppdu_info->mcs = -- FIELD_GET(HAL_RX_HE_SIG_B2_MU_INFO_INFO0_STA_MCS, -- info0); -+ FIELD_GET(HAL_RX_HE_SIG_B2_MU_INFO_INFO0_STA_MCS, info0); -+ value = ppdu_info->mcs << HE_TRANSMIT_MCS_SHIFT; -+ ppdu_info->he_data3 |= value; -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_B2_MU_INFO_INFO0_STA_CODING, info0); -+ ppdu_info->ldpc = value; -+ value = value << HE_CODING_SHIFT; -+ ppdu_info->he_data3 |= value; -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_B2_MU_INFO_INFO0_STA_ID, info0); -+ value = value << HE_STA_ID_SHIFT; -+ ppdu_info->he_data4 |= value; -+ - ppdu_info->nss = - FIELD_GET(HAL_RX_HE_SIG_B2_MU_INFO_INFO0_STA_NSTS, - info0) + 1; -- ppdu_info->ldpc = FIELD_GET(HAL_RX_HE_SIG_B2_MU_INFO_INFO0_STA_CODING, -- info0); - break; - } - case HAL_PHYRX_HE_SIG_B2_OFDMA: { -@@ -1066,17 +1394,38 @@ ath11k_hal_rx_parse_mon_status_tlv(struc - - info0 = __le32_to_cpu(he_sig_b2_ofdma->info0); - -+ ppdu_info->he_data1 |= -+ HE_MCS_KNOWN | HE_DCM_KNOWN | HE_CODING_KNOWN; -+ -+ /* HE-data2 */ -+ ppdu_info->he_data2 |= HE_TXBF_KNOWN; -+ - ppdu_info->mcs = - FIELD_GET(HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_MCS, - info0); -+ value = ppdu_info->mcs << HE_TRANSMIT_MCS_SHIFT; -+ ppdu_info->he_data3 |= value; -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_DCM, info0); -+ he_dcm = value; -+ value = value << HE_DCM_SHIFT; -+ ppdu_info->he_data3 |= value; -+ -+ value = FIELD_GET(HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_CODING, info0); -+ ppdu_info->ldpc = value; -+ value = value << HE_CODING_SHIFT; -+ ppdu_info->he_data3 |= value; -+ -+ /* HE-data4 */ -+ value = FIELD_GET(HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_ID, info0); -+ value = value << HE_STA_ID_SHIFT; -+ ppdu_info->he_data4 |= value; -+ - ppdu_info->nss = - FIELD_GET(HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_NSTS, - info0) + 1; - ppdu_info->beamformed = -- info0 & -- HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_TXBF; -- ppdu_info->ldpc = FIELD_GET(HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_CODING, -- info0); -+ info0 & HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_TXBF; - ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_MU_OFDMA; - break; - } -@@ -1092,7 +1441,7 @@ ath11k_hal_rx_parse_mon_status_tlv(struc - * PHYRX_OTHER_RECEIVE_INFO TLV. - */ - ppdu_info->rssi_comb = -- FIELD_GET(HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO1_RSSI_COMB, -+ FIELD_GET(HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO0_RSSI_COMB, - __le32_to_cpu(rssi->info0)); - - if (db2dbm) { -@@ -1118,6 +1467,8 @@ ath11k_hal_rx_parse_mon_status_tlv(struc - ppdu_info->rx_duration = - FIELD_GET(HAL_RX_PPDU_END_DURATION, - __le32_to_cpu(ppdu_rx_duration->info0)); -+ ppdu_info->tsft =ppdu_rx_duration->rsvd0[1]; -+ ppdu_info->tsft = (ppdu_info->tsft << 32) | ppdu_rx_duration->rsvd0[0]; - break; - } - case HAL_DUMMY: -@@ -1141,12 +1492,14 @@ ath11k_hal_rx_parse_mon_status(struct at - enum hal_rx_mon_status hal_status = HAL_RX_MON_STATUS_BUF_DONE; - u16 tlv_tag; - u16 tlv_len; -+ u32 tlv_userid = 0; - u8 *ptr = skb->data; - - do { - tlv = (struct hal_tlv_hdr *)ptr; - tlv_tag = FIELD_GET(HAL_TLV_HDR_TAG, tlv->tl); - tlv_len = FIELD_GET(HAL_TLV_HDR_LEN, tlv->tl); -+ tlv_userid = FIELD_GET(HAL_TLV_USR_ID, tlv->tl); - ptr += sizeof(*tlv); - - /* The actual length of PPDU_END is the combined length of many PHY -@@ -1158,7 +1511,7 @@ ath11k_hal_rx_parse_mon_status(struct at - tlv_len = sizeof(struct hal_rx_rxpcu_classification_overview); - - hal_status = ath11k_hal_rx_parse_mon_status_tlv(ab, ppdu_info, -- tlv_tag, ptr); -+ tlv_tag, ptr, tlv_userid); - ptr += tlv_len; - ptr = PTR_ALIGN(ptr, HAL_TLV_ALIGN); - ---- a/drivers/net/wireless/ath/ath11k/hal_rx.h -+++ b/drivers/net/wireless/ath/ath11k/hal_rx.h -@@ -91,6 +91,36 @@ struct hal_sw_mon_ring_entries { - bool drop_ppdu; - }; - -+struct hal_rx_user_status { -+ u32 mcs:4, -+ nss:3, -+ ofdma_info_valid:1, -+ dl_ofdma_ru_start_index:7, -+ dl_ofdma_ru_width:7, -+ dl_ofdma_ru_size:8; -+ u32 ul_ofdma_user_v0_word0; -+ u32 ul_ofdma_user_v0_word1; -+ u32 ast_index; -+ u32 tid; -+ u16 tcp_msdu_count; -+ u16 udp_msdu_count; -+ u16 other_msdu_count; -+ u16 frame_control; -+ u8 frame_control_info_valid; -+ u8 data_sequence_control_info_valid; -+ u16 first_data_seq_ctrl; -+ u32 preamble_type; -+ u16 ht_flags; -+ u16 vht_flags; -+ u16 he_flags; -+ u8 rs_flags; -+ u32 mpdu_cnt_fcs_ok; -+ u32 mpdu_cnt_fcs_err; -+ u32 mpdu_fcs_ok_bitmap[8]; -+ u32 mpdu_ok_byte_count; -+ u32 mpdu_err_byte_count; -+}; -+ - struct hal_rx_mon_ppdu_info { - u32 ppdu_id; - u32 ppdu_ts; -@@ -107,17 +137,60 @@ struct hal_rx_mon_ppdu_info { - u8 mcs; - u8 nss; - u8 bw; -+ u8 vht_flag_values1; -+ u8 vht_flag_values2; -+ u8 vht_flag_values3[4]; -+ u8 vht_flag_values4; -+ u8 vht_flag_values5; -+ u16 vht_flag_values6; - u8 is_stbc; - u8 gi; -+ u8 sgi; - u8 ldpc; - u8 beamformed; - u8 rssi_comb; - u8 rssi_chain_pri20[HAL_RX_MAX_NSS]; - u8 tid; -+ u16 ht_flags; -+ u16 vht_flags; -+ u16 he_flags; -+ u16 he_mu_flags; - u8 dcm; - u8 ru_alloc; - u8 reception_type; -+ u64 tsft; - u64 rx_duration; -+ u16 frame_control; -+ u32 ast_index; -+ u8 rs_fcs_err; -+ u8 rs_flags; -+ u8 cck_flag; -+ u8 ofdm_flag; -+ u8 ulofdma_flag; -+ u8 frame_control_info_valid; -+ u16 he_per_user_1; -+ u16 he_per_user_2; -+ u8 he_per_user_position; -+ u8 he_per_user_known; -+ u16 he_flags1; -+ u16 he_flags2; -+ u8 he_RU[4]; -+ u16 he_data1; -+ u16 he_data2; -+ u16 he_data3; -+ u16 he_data4; -+ u16 he_data5; -+ u16 he_data6; -+ u32 ppdu_len; -+ u32 prev_ppdu_id; -+ u32 device_id; -+ u16 first_data_seq_ctrl; -+ u8 monitor_direct_used; -+ u8 data_sequence_control_info_valid; -+ u8 ltf_size; -+ u8 rxpcu_filter_pass; -+ char rssi_chain[8][8]; -+ struct hal_rx_user_status userstats; - }; - - #define HAL_RX_PPDU_START_INFO0_PPDU_ID GENMASK(15, 0) -@@ -150,6 +223,9 @@ struct hal_rx_ppdu_start { - #define HAL_RX_PPDU_END_USER_STATS_INFO6_TID_BITMAP GENMASK(15, 0) - #define HAL_RX_PPDU_END_USER_STATS_INFO6_TID_EOSP_BITMAP GENMASK(31, 16) - -+#define HAL_RX_PPDU_END_USER_STATS_RSVD2_6_MPDU_OK_BYTE_COUNT GENMASK(24, 0) -+#define HAL_RX_PPDU_END_USER_STATS_RSVD2_8_MPDU_ERR_BYTE_COUNT GENMASK(24, 0) -+ - struct hal_rx_ppdu_end_user_stats { - __le32 rsvd0[2]; - __le32 info0; -@@ -160,10 +236,21 @@ struct hal_rx_ppdu_end_user_stats { - __le32 rsvd1[2]; - __le32 info4; - __le32 info5; -- __le32 info6; -+ __le32 info6; //byte 11 - __le32 rsvd2[11]; - } __packed; - -+struct hal_rx_ppdu_end_user_stats_ext { -+ u32 info0; -+ u32 info1; -+ u32 info2; -+ u32 info3; -+ u32 info4; -+ u32 info5; -+ u32 info6; -+} __packed; -+ -+ - #define HAL_RX_HT_SIG_INFO_INFO0_MCS GENMASK(6, 0) - #define HAL_RX_HT_SIG_INFO_INFO0_BW BIT(7) - -@@ -212,25 +299,63 @@ enum hal_rx_vht_sig_a_gi_setting { - HAL_RX_VHT_SIG_A_SHORT_GI_AMBIGUITY = 3, - }; - -+#define HAL_RX_SU_MU_CODING_LDPC 0x01 -+ -+#define HE_GI_0_8 0 -+#define HE_GI_0_4 1 -+#define HE_GI_1_6 2 -+#define HE_GI_3_2 3 -+ -+#define HE_LTF_1_X 0 -+#define HE_LTF_2_X 1 -+#define HE_LTF_4_X 2 -+#define HE_LTF_UNKNOWN 3 -+ - #define HAL_RX_HE_SIG_A_SU_INFO_INFO0_TRANSMIT_MCS GENMASK(6, 3) - #define HAL_RX_HE_SIG_A_SU_INFO_INFO0_DCM BIT(7) - #define HAL_RX_HE_SIG_A_SU_INFO_INFO0_TRANSMIT_BW GENMASK(20, 19) - #define HAL_RX_HE_SIG_A_SU_INFO_INFO0_CP_LTF_SIZE GENMASK(22, 21) - #define HAL_RX_HE_SIG_A_SU_INFO_INFO0_NSTS GENMASK(25, 23) -+#define HAL_RX_HE_SIG_A_SU_INFO_INFO0_BSS_COLOR GENMASK(13, 8) -+#define HAL_RX_HE_SIG_A_SU_INFO_INFO0_SPATIAL_REUSE GENMASK(18, 15) -+#define HAL_RX_HE_SIG_A_SU_INFO_INFO0_FORMAT_IND BIT(0) -+#define HAL_RX_HE_SIG_A_SU_INFO_INFO0_BEAM_CHANGE BIT(1) -+#define HAL_RX_HE_SIG_A_SU_INFO_INFO0_DL_UL_FLAG BIT(2) -+ - -+#define HAL_RX_HE_SIG_A_SU_INFO_INFO1_TXOP_DURATION GENMASK(6, 0) - #define HAL_RX_HE_SIG_A_SU_INFO_INFO1_CODING BIT(7) -+#define HAL_RX_HE_SIG_A_SU_INFO_INFO1_LDPC_EXTRA BIT(8) - #define HAL_RX_HE_SIG_A_SU_INFO_INFO1_STBC BIT(9) - #define HAL_RX_HE_SIG_A_SU_INFO_INFO1_TXBF BIT(10) -+#define HAL_RX_HE_SIG_A_SU_INFO_INFO1_PKT_EXT_FACTOR GENMASK(12, 11) -+#define HAL_RX_HE_SIG_A_SU_INFO_INFO1_PKT_EXT_PE_DISAM BIT(13) -+#define HAL_RX_HE_SIG_A_SU_INFO_INFO1_DOPPLER_IND BIT(15) - - struct hal_rx_he_sig_a_su_info { - __le32 info0; - __le32 info1; - } __packed; - --#define HAL_RX_HE_SIG_A_MU_DL_INFO_INFO0_TRANSMIT_BW GENMASK(17, 15) --#define HAL_RX_HE_SIG_A_MU_DL_INFO_INFO0_CP_LTF_SIZE GENMASK(24, 23) -- --#define HAL_RX_HE_SIG_A_MU_DL_INFO_INFO1_STBC BIT(12) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO0_UL_FLAG BIT(1) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO0_MCS_OF_SIGB GENMASK(3, 1) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO0_DCM_OF_SIGB BIT(4) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO0_BSS_COLOR GENMASK(10, 5) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO0_SPATIAL_REUSE GENMASK(14, 11) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO0_TRANSMIT_BW GENMASK(17, 15) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO0_NUM_SIGB_SYMB GENMASK(21, 18) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO0_COMP_MODE_SIGB BIT(22) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO0_CP_LTF_SIZE GENMASK(24, 23) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO0_DOPPLER_INDICATION BIT(25) -+ -+#define HAL_RX_HE_SIG_A_MU_DL_INFO1_TXOP_DURATION GENMASK(6, 0) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO1_CODING BIT(7) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO1_NUM_LTF_SYMB GENMASK(10, 8) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO1_LDPC_EXTRA BIT(11) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO1_STBC BIT(12) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO1_TXBF BIT(10) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO1_PKT_EXT_FACTOR GENMASK(14,13) -+#define HAL_RX_HE_SIG_A_MU_DL_INFO1_PKT_EXT_PE_DISAM BIT(15) - - struct hal_rx_he_sig_a_mu_dl_info { - __le32 info0; -@@ -243,6 +368,7 @@ struct hal_rx_he_sig_b1_mu_info { - __le32 info0; - } __packed; - -+#define HAL_RX_HE_SIG_B2_MU_INFO_INFO0_STA_ID GENMASK(10, 0) - #define HAL_RX_HE_SIG_B2_MU_INFO_INFO0_STA_MCS GENMASK(18, 15) - #define HAL_RX_HE_SIG_B2_MU_INFO_INFO0_STA_CODING BIT(20) - #define HAL_RX_HE_SIG_B2_MU_INFO_INFO0_STA_NSTS GENMASK(31, 29) -@@ -251,6 +377,7 @@ struct hal_rx_he_sig_b2_mu_info { - __le32 info0; - } __packed; - -+#define HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_ID GENMASK(10, 0) - #define HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_NSTS GENMASK(13, 11) - #define HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_TXBF BIT(19) - #define HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_MCS GENMASK(18, 15) -@@ -261,7 +388,7 @@ struct hal_rx_he_sig_b2_ofdma_info { - __le32 info0; - } __packed; - --#define HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO1_RSSI_COMB GENMASK(15, 8) -+#define HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO0_RSSI_COMB GENMASK(15, 8) - - #define HAL_RX_PHYRX_RSSI_PREAMBLE_PRI20 GENMASK(7, 0) - -@@ -367,4 +494,96 @@ ath11k_hal_rx_parse_mon_status(struct at - #define REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_1 0xADBEEF - #define REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_2 0xBDBEEF - #define REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_3 0xCDBEEF -+ -+ -+/* HE Radiotap data1 Mask */ -+#define HE_SU_FORMAT_TYPE 0x0000 -+#define HE_EXT_SU_FORMAT_TYPE 0x0001 -+#define HE_MU_FORMAT_TYPE 0x0002 -+#define HE_TRIG_FORMAT_TYPE 0x0003 -+#define HE_BEAM_CHANGE_KNOWN 0x0008 -+#define HE_DL_UL_KNOWN 0x0010 -+#define HE_MCS_KNOWN 0x0020 -+#define HE_DCM_KNOWN 0x0040 -+#define HE_CODING_KNOWN 0x0080 -+#define HE_LDPC_EXTRA_SYMBOL_KNOWN 0x0100 -+#define HE_STBC_KNOWN 0x0200 -+#define HE_DATA_BW_RU_KNOWN 0x4000 -+#define HE_DOPPLER_KNOWN 0x8000 -+#define HE_BSS_COLOR_KNOWN 0x0004 -+ -+/* HE Radiotap data2 Mask */ -+#define HE_GI_KNOWN 0x0002 -+#define HE_TXBF_KNOWN 0x0010 -+#define HE_PE_DISAMBIGUITY_KNOWN 0x0020 -+#define HE_TXOP_KNOWN 0x0040 -+#define HE_LTF_SYMBOLS_KNOWN 0x0004 -+#define HE_PRE_FEC_PADDING_KNOWN 0x0008 -+#define HE_MIDABLE_PERIODICITY_KNOWN 0x0080 -+ -+/* HE radiotap data3 shift values */ -+#define HE_BEAM_CHANGE_SHIFT 6 -+#define HE_DL_UL_SHIFT 7 -+#define HE_TRANSMIT_MCS_SHIFT 8 -+#define HE_DCM_SHIFT 12 -+#define HE_CODING_SHIFT 13 -+#define HE_LDPC_EXTRA_SYMBOL_SHIFT 14 -+#define HE_STBC_SHIFT 15 -+ -+/* HE radiotap data4 shift values */ -+#define HE_STA_ID_SHIFT 4 -+ -+/* HE radiotap data5 */ -+#define HE_GI_SHIFT 4 -+#define HE_LTF_SIZE_SHIFT 6 -+#define HE_LTF_SYM_SHIFT 8 -+#define HE_TXBF_SHIFT 14 -+#define HE_PE_DISAMBIGUITY_SHIFT 15 -+#define HE_PRE_FEC_PAD_SHIFT 12 -+ -+/* HE radiotap data6 */ -+#define HE_DOPPLER_SHIFT 4 -+#define HE_TXOP_SHIFT 8 -+ -+/* HE radiotap HE-MU flags1 */ -+#define HE_SIG_B_MCS_KNOWN 0x0010 -+#define HE_SIG_B_DCM_KNOWN 0x0040 -+#define HE_SIG_B_SYM_NUM_KNOWN 0x8000 -+#define HE_RU_0_KNOWN 0x0100 -+#define HE_RU_1_KNOWN 0x0200 -+#define HE_RU_2_KNOWN 0x0400 -+#define HE_RU_3_KNOWN 0x0800 -+#define HE_DCM_FLAG_1_SHIFT 5 -+#define HE_SPATIAL_REUSE_MU_KNOWN 0x0100 -+#define HE_SIG_B_COMPRESSION_FLAG_1_KNOWN 0x4000 -+ -+/* HE radiotap HE-MU flags2 */ -+#define HE_SIG_B_COMPRESSION_FLAG_2_SHIFT 3 -+#define HE_BW_KNOWN 0x0004 -+#define HE_NUM_SIG_B_SYMBOLS_SHIFT 4 -+#define HE_SIG_B_COMPRESSION_FLAG_2_KNOWN 0x0100 -+#define HE_NUM_SIG_B_FLAG_2_SHIFT 9 -+#define HE_LTF_FLAG_2_SYMBOLS_SHIFT 12 -+#define HE_LTF_KNOWN 0x8000 -+ -+/* HE radiotap per_user_1 */ -+#define HE_STA_SPATIAL_SHIFT 11 -+#define HE_TXBF_SHIFT 14 -+#define HE_RESERVED_SET_TO_1_SHIFT 19 -+#define HE_STA_CODING_SHIFT 20 -+ -+/* HE radiotap per_user_2 */ -+#define HE_STA_MCS_SHIFT 4 -+#define HE_STA_DCM_SHIFT 5 -+ -+/* HE radiotap per user known */ -+#define HE_USER_FIELD_POSITION_KNOWN 0x01 -+#define HE_STA_ID_PER_USER_KNOWN 0x02 -+#define HE_STA_NSTS_KNOWN 0x04 -+#define HE_STA_TX_BF_KNOWN 0x08 -+#define HE_STA_SPATIAL_CONFIG_KNOWN 0x10 -+#define HE_STA_MCS_KNOWN 0x20 -+#define HE_STA_DCM_KNOWN 0x40 -+#define HE_STA_CODING_KNOWN 0x80 -+ - #endif diff --git a/feeds/ipq95xx/mac80211/patches/qca/068-ath11k-add-rx-histogram-stats.patch b/feeds/ipq95xx/mac80211/patches/qca/068-ath11k-add-rx-histogram-stats.patch index e6b88f0d1..62d17b0a0 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/068-ath11k-add-rx-histogram-stats.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/068-ath11k-add-rx-histogram-stats.patch @@ -17,16 +17,16 @@ Signed-off-by: Manikanta Pubbisetty --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -42,6 +42,8 @@ extern bool ath11k_collect_dump; +@@ -48,6 +48,8 @@ extern bool ath11k_collect_dump; #define ATH11K_INVALID_HW_MAC_ID 0xFF #define ATH11K_CONNECTION_LOSS_HZ (3 * HZ) +#define ATH11K_RX_RATE_TABLE_NUM 320 +#define ATH11K_RX_RATE_TABLE_11AX_NUM 576 - extern unsigned int ath11k_frame_mode; - -@@ -281,6 +283,17 @@ struct ath11k_vif_iter { + /* SMBIOS type containing Board Data File Name Extension */ + #define ATH11K_SMBIOS_BDF_EXT_TYPE 0xF8 +@@ -375,6 +377,17 @@ struct ath11k_vif_iter { struct ath11k_vif *arvif; }; @@ -44,7 +44,7 @@ Signed-off-by: Manikanta Pubbisetty struct ath11k_rx_peer_stats { u64 num_msdu; u64 num_mpdu_fcs_ok; -@@ -292,10 +305,6 @@ struct ath11k_rx_peer_stats { +@@ -386,10 +399,6 @@ struct ath11k_rx_peer_stats { u64 non_ampdu_msdu_count; u64 stbc_count; u64 beamformed_count; @@ -55,7 +55,7 @@ Signed-off-by: Manikanta Pubbisetty u64 coding_count[HAL_RX_SU_MU_CODING_MAX]; u64 tid_count[IEEE80211_NUM_TIDS + 1]; u64 pream_cnt[HAL_RX_PREAMBLE_MAX]; -@@ -303,6 +312,8 @@ struct ath11k_rx_peer_stats { +@@ -397,6 +406,8 @@ struct ath11k_rx_peer_stats { u64 rx_duration; u64 dcm_count; u64 ru_alloc_cnt[HAL_RX_RU_ALLOC_TYPE_MAX]; @@ -266,7 +266,7 @@ Signed-off-by: Manikanta Pubbisetty &fops_htt_peer_stats); --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -2757,16 +2757,53 @@ exit: +@@ -2758,10 +2758,43 @@ exit: return total_msdu_reaped; } @@ -294,7 +294,7 @@ Signed-off-by: Manikanta Pubbisetty + gi_idx = ath11k_he_gi_to_nl80211_he_gi(ppdu_info->gi); + rate_idx = mcs_idx * 12 + 12 * 12 * nss_idx; + rate_idx += bw_idx * 3 + gi_idx; -+ } else { ++ } else { + return; + } + @@ -310,17 +310,16 @@ Signed-off-by: Manikanta Pubbisetty u32 num_msdu; int i; - if (!rx_stats) - return; +@@ -2771,6 +2804,8 @@ static void ath11k_dp_rx_update_peer_sta + arsta->rssi_comb = ppdu_info->rssi_comb; + ewma_avg_rssi_add(&arsta->avg_rssi, ppdu_info->rssi_comb); -+ arsta->rssi_comb = ppdu_info->rssi_comb; -+ + if (!ath11k_debugfs_is_extd_rx_stats_enabled(ar)) + return; num_msdu = ppdu_info->tcp_msdu_count + ppdu_info->tcp_ack_msdu_count + ppdu_info->udp_msdu_count + ppdu_info->other_msdu_count; -@@ -2783,18 +2820,6 @@ static void ath11k_dp_rx_update_peer_sta +@@ -2787,18 +2822,6 @@ static void ath11k_dp_rx_update_peer_sta ppdu_info->tid = IEEE80211_NUM_TIDS; } @@ -339,7 +338,7 @@ Signed-off-by: Manikanta Pubbisetty if (ppdu_info->ldpc < HAL_RX_SU_MU_CODING_MAX) rx_stats->coding_count[ppdu_info->ldpc] += num_msdu; -@@ -2823,8 +2848,6 @@ static void ath11k_dp_rx_update_peer_sta +@@ -2827,8 +2850,6 @@ static void ath11k_dp_rx_update_peer_sta rx_stats->dcm_count += ppdu_info->dcm; rx_stats->ru_alloc_cnt[ppdu_info->ru_alloc] += num_msdu; @@ -348,7 +347,7 @@ Signed-off-by: Manikanta Pubbisetty BUILD_BUG_ON(ARRAY_SIZE(arsta->chain_signal) > ARRAY_SIZE(ppdu_info->rssi_chain_pri20)); -@@ -2833,6 +2856,52 @@ static void ath11k_dp_rx_update_peer_sta +@@ -2837,6 +2858,52 @@ static void ath11k_dp_rx_update_peer_sta rx_stats->rx_duration += ppdu_info->rx_duration; arsta->rx_duration = rx_stats->rx_duration; @@ -403,7 +402,7 @@ Signed-off-by: Manikanta Pubbisetty static struct sk_buff *ath11k_dp_rx_alloc_mon_status_buf(struct ath11k_base *ab, --- a/drivers/net/wireless/ath/ath11k/hal_rx.c +++ b/drivers/net/wireless/ath/ath11k/hal_rx.c -@@ -967,44 +967,78 @@ ath11k_hal_rx_parse_mon_status_tlv(struc +@@ -971,44 +971,78 @@ ath11k_hal_rx_parse_mon_status_tlv(struc ppdu_info->is_stbc = FIELD_GET(HAL_RX_HT_SIG_INFO_INFO1_STBC, info1); ppdu_info->ldpc = FIELD_GET(HAL_RX_HT_SIG_INFO_INFO1_FEC_CODING, info1); @@ -506,7 +505,7 @@ Signed-off-by: Manikanta Pubbisetty ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_SU; break; } -@@ -1454,11 +1488,16 @@ ath11k_hal_rx_parse_mon_status_tlv(struc +@@ -1459,11 +1493,16 @@ ath11k_hal_rx_parse_mon_status_tlv(struc break; } case HAL_RX_MPDU_START: { @@ -537,8 +536,8 @@ Signed-off-by: Manikanta Pubbisetty struct hal_rx_mon_status_tlv_hdr { u32 hdr; -@@ -73,6 +77,22 @@ enum hal_rx_mon_status { - HAL_RX_MON_STATUS_BUF_DONE, +@@ -103,6 +107,22 @@ struct hal_rx_user_status { + u32 mpdu_err_byte_count; }; +enum hal_rx_legacy_rate { @@ -560,7 +559,7 @@ Signed-off-by: Manikanta Pubbisetty #define HAL_TLV_STATUS_PPDU_NOT_DONE HAL_RX_MON_STATUS_PPDU_NOT_DONE #define HAL_TLV_STATUS_PPDU_DONE HAL_RX_MON_STATUS_PPDU_DONE #define HAL_TLV_STATUS_BUF_DONE HAL_RX_MON_STATUS_BUF_DONE -@@ -127,6 +147,7 @@ struct hal_rx_mon_ppdu_info { +@@ -157,6 +177,7 @@ struct hal_rx_mon_ppdu_info { u32 num_mpdu_fcs_ok; u32 num_mpdu_fcs_err; u32 preamble_type; @@ -568,22 +567,6 @@ Signed-off-by: Manikanta Pubbisetty u16 chan_num; u16 tcp_msdu_count; u16 tcp_ack_msdu_count; -@@ -406,11 +427,14 @@ struct hal_rx_phyrx_rssi_legacy_info { - - #define HAL_RX_MPDU_INFO_INFO0_PEERID GENMASK(31, 16) - #define HAL_RX_MPDU_INFO_INFO0_PEERID_WCN6855 GENMASK(15, 0) -+#define HAL_RX_MPDU_INFO_INFO1_MPDU_LEN GENMASK(13, 0) - - struct hal_rx_mpdu_info { - __le32 rsvd0; - __le32 info0; -- __le32 rsvd1[21]; -+ __le32 rsvd1[11]; -+ __le32 info1; -+ __le32 rsvd2[9]; - } __packed; - - struct hal_rx_mpdu_info_wcn6855 { --- a/drivers/net/wireless/ath/ath11k/dp_rx.h +++ b/drivers/net/wireless/ath/ath11k/dp_rx.h @@ -41,6 +41,25 @@ struct ath11k_dp_rfc1042_hdr { diff --git a/feeds/ipq95xx/mac80211/patches/qca/072-ath11k-support-hostapd-config-to-enable-disable-he-m.patch b/feeds/ipq95xx/mac80211/patches/qca/072-ath11k-support-hostapd-config-to-enable-disable-he-m.patch index d99f85b93..ae16f9e10 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/072-ath11k-support-hostapd-config-to-enable-disable-he-m.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/072-ath11k-support-hostapd-config-to-enable-disable-he-m.patch @@ -13,11 +13,9 @@ Signed-off-by: Miles Hu net/mac80211/cfg.c | 5 +- 4 files changed, 138 insertions(+), 11 deletions(-) -Index: backports-20210222-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/mac.c -=================================================================== ---- backports-20210222-4.4.60-b157d2276.orig/drivers/net/wireless/ath/ath11k/mac.c -+++ backports-20210222-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/mac.c -@@ -2061,6 +2061,131 @@ static int ath11k_setup_peer_smps(struct +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -2699,6 +2699,131 @@ static int ath11k_setup_peer_smps(struct ath11k_smps_map[smps]); } @@ -149,24 +147,24 @@ Index: backports-20210222-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/mac.c static void ath11k_bss_assoc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf) -@@ -2069,6 +2194,7 @@ static void ath11k_bss_assoc(struct ieee - struct ieee80211_sta *ap_sta; - struct ath11k_peer *peer; - bool is_auth = false; +@@ -2709,6 +2834,7 @@ static void ath11k_bss_assoc(struct ieee + struct ieee80211_sta *ap_sta; + struct ath11k_peer *peer; + bool is_auth = false; + struct ieee80211_sta_he_cap he_cap; int ret; lockdep_assert_held(&ar->conf_mutex); -@@ -2085,6 +2211,8 @@ static void ath11k_bss_assoc(struct ieee +@@ -2725,6 +2851,8 @@ static void ath11k_bss_assoc(struct ieee rcu_read_unlock(); return; } + /* he_cap here is updated at assoc success for sta mode only */ -+ he_cap = ap_sta->he_cap; ++ he_cap = ap_sta->deflink.he_cap; ath11k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg, false); -@@ -2111,6 +2239,12 @@ static void ath11k_bss_assoc(struct ieee +@@ -2753,6 +2881,12 @@ static void ath11k_bss_assoc(struct ieee return; } @@ -178,8 +176,8 @@ Index: backports-20210222-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/mac.c + WARN_ON(arvif->is_up); - arvif->aid = bss_conf->aid; -@@ -2511,6 +2645,8 @@ static void ath11k_mac_op_bss_info_chang + arvif->aid = vif->cfg.aid; +@@ -3202,6 +3336,8 @@ static void ath11k_mac_op_bss_info_chang ether_addr_copy(arvif->bssid, info->bssid); if (changed & BSS_CHANGED_BEACON_ENABLED) { @@ -188,7 +186,7 @@ Index: backports-20210222-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/mac.c ath11k_control_beaconing(arvif, info); if (arvif->is_up && vif->bss_conf.he_support && -@@ -4426,6 +4562,39 @@ static __le16 ath11k_mac_setup_he_6ghz_c +@@ -5313,6 +5449,39 @@ static __le16 ath11k_mac_setup_he_6ghz_c return cpu_to_le16(bcap->he_6ghz_capa); } @@ -228,7 +226,7 @@ Index: backports-20210222-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/mac.c static int ath11k_mac_copy_he_cap(struct ath11k *ar, struct ath11k_pdev_cap *cap, struct ieee80211_sband_iftype_data *data, -@@ -4483,18 +4652,7 @@ static int ath11k_mac_copy_he_cap(struct +@@ -5370,18 +5539,7 @@ static int ath11k_mac_copy_he_cap(struct break; } @@ -248,7 +246,7 @@ Index: backports-20210222-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/mac.c memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres)); if (he_cap_elem->phy_cap_info[6] & -@@ -5027,69 +5185,6 @@ ath11k_mac_setup_vdev_create_params(stru +@@ -5981,69 +6139,6 @@ ath11k_mac_setup_vdev_create_params(stru } } @@ -318,15 +316,15 @@ Index: backports-20210222-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/mac.c static void ath11k_mac_op_update_vif_offload(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { -@@ -5604,7 +5699,6 @@ ath11k_mac_vdev_start_restart(struct ath - struct ath11k *ar = arvif->ar; +@@ -6704,7 +6799,6 @@ ath11k_mac_vdev_start_restart(struct ath struct ath11k_base *ab = ar->ab; struct wmi_vdev_start_req_arg arg = {}; + const struct cfg80211_chan_def *chandef = &ctx->def; - int he_support = arvif->vif->bss_conf.he_support; int ret = 0; lockdep_assert_held(&ar->conf_mutex); -@@ -5646,15 +5740,6 @@ ath11k_mac_vdev_start_restart(struct ath +@@ -6745,15 +6839,6 @@ ath11k_mac_vdev_start_restart(struct ath spin_lock_bh(&ab->base_lock); arg.regdomain = ar->ab->dfs_region; spin_unlock_bh(&ab->base_lock); @@ -342,11 +340,9 @@ Index: backports-20210222-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/mac.c } arg.channel.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR); -Index: backports-20210222-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/wmi.h -=================================================================== ---- backports-20210222-4.4.60-b157d2276.orig/drivers/net/wireless/ath/ath11k/wmi.h -+++ backports-20210222-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/wmi.h -@@ -2779,6 +2779,8 @@ struct rx_reorder_queue_remove_params { +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -2857,6 +2857,8 @@ struct rx_reorder_queue_remove_params { #define HECAP_PHYDWORD_0 0 #define HECAP_PHYDWORD_1 1 #define HECAP_PHYDWORD_2 2 @@ -355,7 +351,7 @@ Index: backports-20210222-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/wmi.h #define HECAP_PHY_SU_BFER BIT(31) #define HECAP_PHY_SU_BFEE BIT(0) -@@ -2812,8 +2814,11 @@ struct rx_reorder_queue_remove_params { +@@ -2890,8 +2892,11 @@ struct rx_reorder_queue_remove_params { #define HE_DL_MUOFDMA_ENABLE 1 #define HE_UL_MUOFDMA_ENABLE 1 #define HE_DL_MUMIMO_ENABLE 1 @@ -367,11 +363,9 @@ Index: backports-20210222-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/wmi.h #define HE_VHT_SOUNDING_MODE_ENABLE 1 #define HE_SU_MU_SOUNDING_MODE_ENABLE 1 -Index: backports-20210222-4.4.60-b157d2276/include/net/mac80211.h -=================================================================== ---- backports-20210222-4.4.60-b157d2276.orig/include/net/mac80211.h -+++ backports-20210222-4.4.60-b157d2276/include/net/mac80211.h -@@ -695,6 +695,7 @@ struct ieee80211_bss_conf { +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -708,6 +708,7 @@ struct ieee80211_bss_conf { u16 nss_set; } he_oper; struct ieee80211_he_obss_pd he_obss_pd; @@ -379,12 +373,10 @@ Index: backports-20210222-4.4.60-b157d2276/include/net/mac80211.h struct cfg80211_he_bss_color he_bss_color; struct ieee80211_fils_discovery fils_discovery; u32 unsol_bcast_probe_resp_interval; -Index: backports-20210222-4.4.60-b157d2276/net/mac80211/cfg.c -=================================================================== ---- backports-20210222-4.4.60-b157d2276.orig/net/mac80211/cfg.c -+++ backports-20210222-4.4.60-b157d2276/net/mac80211/cfg.c -@@ -1078,6 +1078,11 @@ static int ieee80211_start_ap(struct wip - changed |= BSS_CHANGED_HE_BSS_COLOR; +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1202,6 +1202,11 @@ static int ieee80211_start_ap(struct wip + return err; } + if (params->he_cap) { @@ -393,5 +385,5 @@ Index: backports-20210222-4.4.60-b157d2276/net/mac80211/cfg.c + } + mutex_lock(&local->mtx); - err = ieee80211_vif_use_channel(sdata, ¶ms->chandef, - IEEE80211_CHANCTX_SHARED); + err = ieee80211_link_use_channel(link, ¶ms->chandef, + IEEE80211_CHANCTX_SHARED); diff --git a/feeds/ipq95xx/mac80211/patches/qca/084-ath11k-fix-ul-ofdma-counter-always-zero-in-peer-stat.patch b/feeds/ipq95xx/mac80211/patches/qca/084-ath11k-fix-ul-ofdma-counter-always-zero-in-peer-stat.patch index 61dc0fd1c..027195781 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/084-ath11k-fix-ul-ofdma-counter-always-zero-in-peer-stat.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/084-ath11k-fix-ul-ofdma-counter-always-zero-in-peer-stat.patch @@ -31,7 +31,7 @@ Signed-off-by: Miles Hu spin_unlock_bh(&ar->ab->base_lock); --- a/drivers/net/wireless/ath/ath11k/hal_rx.c +++ b/drivers/net/wireless/ath/ath11k/hal_rx.c -@@ -1469,6 +1469,7 @@ ath11k_hal_rx_parse_mon_status_tlv(struc +@@ -1474,6 +1474,7 @@ ath11k_hal_rx_parse_mon_status_tlv(struc ab->wmi_ab.svc_map); struct hal_rx_phyrx_rssi_legacy_info *rssi = (struct hal_rx_phyrx_rssi_legacy_info *)tlv_data; @@ -39,8 +39,8 @@ Signed-off-by: Miles Hu /* TODO: Please note that the combined rssi will not be accurate * in MU case. Rssi in MU needs to be retrieved from -@@ -1478,6 +1479,22 @@ ath11k_hal_rx_parse_mon_status_tlv(struc - FIELD_GET(HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO0_RSSI_COMB, +@@ -1483,6 +1484,22 @@ ath11k_hal_rx_parse_mon_status_tlv(struc + FIELD_GET(HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO1_RSSI_COMB, __le32_to_cpu(rssi->info0)); + reception_type = @@ -64,10 +64,10 @@ Signed-off-by: Miles Hu ppdu_info->rssi_chain_pri20[i] = --- a/drivers/net/wireless/ath/ath11k/hal_rx.h +++ b/drivers/net/wireless/ath/ath11k/hal_rx.h -@@ -410,6 +410,14 @@ struct hal_rx_he_sig_b2_ofdma_info { +@@ -407,6 +407,14 @@ struct hal_rx_he_sig_b2_ofdma_info { } __packed; - #define HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO0_RSSI_COMB GENMASK(15, 8) + #define HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO1_RSSI_COMB GENMASK(15, 8) +#define HAL_RX_PHYRX_RSSI_LEGACY_INFO_RSVD1_RECEPTION GENMASK(3, 0) + +enum hal_rx_ul_reception_type { diff --git a/feeds/ipq95xx/mac80211/patches/qca/087-ath11k-fix-ul-ofdma-counter-increamenting-improperly.patch b/feeds/ipq95xx/mac80211/patches/qca/087-ath11k-fix-ul-ofdma-counter-increamenting-improperly.patch index 17d99e742..ad3798775 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/087-ath11k-fix-ul-ofdma-counter-increamenting-improperly.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/087-ath11k-fix-ul-ofdma-counter-increamenting-improperly.patch @@ -5,7 +5,7 @@ --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -5385,8 +5385,11 @@ int ath11k_dp_rx_process_mon_status(stru +@@ -5431,8 +5431,11 @@ int ath11k_dp_rx_process_mon_status(stru goto next_skb; } @@ -21,13 +21,13 @@ trace_ath11k_htt_rxdesc(ar, skb->data, log_type, rx_buf_sz); --- a/drivers/net/wireless/ath/ath11k/hal_rx.c +++ b/drivers/net/wireless/ath/ath11k/hal_rx.c -@@ -894,6 +894,9 @@ ath11k_hal_rx_parse_mon_status_tlv(struc +@@ -896,6 +896,9 @@ ath11k_hal_rx_parse_mon_status_tlv(struc ppdu_info->ast_index = FIELD_GET(HAL_RX_PPDU_END_USER_STATS_INFO2_AST_INDEX, - __le32_to_cpu(eu_stats->info2)); + __le32_to_cpu(eu_stats->info2)); + ppdu_info->fc_valid = + FIELD_GET(HAL_RX_PPDU_END_USER_STATS_INFO1_FC_VALID, -+ __le32_to_cpu(eu_stats->info1)); ++ __le32_to_cpu(eu_stats->info1)); ppdu_info->tid = ffs(FIELD_GET(HAL_RX_PPDU_END_USER_STATS_INFO6_TID_BITMAP, __le32_to_cpu(eu_stats->info6))) - 1; @@ -41,7 +41,7 @@ enum hal_rx_mon_status { HAL_RX_MON_STATUS_PPDU_NOT_DONE, -@@ -172,6 +173,7 @@ struct hal_rx_mon_ppdu_info { +@@ -201,6 +202,7 @@ struct hal_rx_mon_ppdu_info { u8 rssi_comb; u8 rssi_chain_pri20[HAL_RX_MAX_NSS]; u8 tid; diff --git a/feeds/ipq95xx/mac80211/patches/qca/088-ath11k-add-htt-stats.patch b/feeds/ipq95xx/mac80211/patches/qca/088-ath11k-add-htt-stats.patch index 0a9d979ed..f4c65828c 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/088-ath11k-add-htt-stats.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/088-ath11k-add-htt-stats.patch @@ -13,7 +13,7 @@ ATH11K_DBG_HTT_EXT_STATS_TXBF_OFDMA = 32, --- a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c +++ b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c -@@ -3639,6 +3639,370 @@ static inline void htt_print_backpressur +@@ -3725,6 +3725,370 @@ static inline void htt_print_backpressur } } @@ -384,7 +384,7 @@ static inline void htt_print_pdev_tx_rate_txbf_stats_tlv(const void *tag_buf, struct debug_htt_stats_req *stats_req) -@@ -4318,6 +4682,30 @@ static int ath11k_dbg_htt_ext_stats_pars +@@ -4404,6 +4768,30 @@ static int ath11k_dbg_htt_ext_stats_pars case HTT_STATS_RING_BACKPRESSURE_STATS_TAG: htt_print_backpressure_stats_tlv_v(tag_buf, user_data); break; @@ -417,7 +417,7 @@ break; --- a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h +++ b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h -@@ -102,6 +102,14 @@ enum htt_tlv_tag_t { +@@ -103,6 +103,14 @@ enum htt_tlv_tag_t { HTT_STATS_PDEV_OBSS_PD_TAG = 88, HTT_STATS_HW_WAR_TAG = 89, HTT_STATS_RING_BACKPRESSURE_STATS_TAG = 90, @@ -432,26 +432,25 @@ HTT_STATS_PEER_CTRL_PATH_TXRX_STATS_TAG = 101, HTT_STATS_PDEV_TX_RATE_TXBF_STATS_TAG = 108, HTT_STATS_TXBF_OFDMA_NDPA_STATS_TAG = 113, -@@ -1290,13 +1298,18 @@ struct htt_tx_pdev_rate_stats_tlv { +@@ -1312,13 +1320,17 @@ struct htt_tx_pdev_rate_stats_tlv { #define HTT_RX_PDEV_STATS_NUM_LEGACY_CCK_STATS 4 #define HTT_RX_PDEV_STATS_NUM_LEGACY_OFDM_STATS 8 #define HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS 12 -+#define HTT_RX_PDEV_STATS_NUM_EMCS_COUNTERS 2 ++#define HTT_RX_PDEV_STATS_NUM_EMCS_COUNTERS 2 #define HTT_RX_PDEV_STATS_NUM_GI_COUNTERS 4 #define HTT_RX_PDEV_STATS_NUM_DCM_COUNTERS 5 #define HTT_RX_PDEV_STATS_NUM_BW_COUNTERS 4 #define HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS 8 -+#define HTT_RX_PDEV_STATS_ULNUM_SPATIAL_STREAMS 8 ++#define HTT_RX_PDEV_STATS_ULNUM_SPATIAL_STREAMS 8 #define HTT_RX_PDEV_STATS_NUM_PREAMBLE_TYPES HTT_STATS_PREAM_COUNT #define HTT_RX_PDEV_MAX_OFDMA_NUM_USER 8 -+#define HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER 8 ++#define HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER 8 #define HTT_RX_PDEV_STATS_RXEVM_MAX_PILOTS_PER_NSS 16 +#define HTT_RX_PDEV_STATS_NUM_RU_SIZE_160MHZ_CNTRS 7 -+#define HTT_RX_PDEV_STATS_NUM_RU_SIZE_COUNTERS 6 + #define HTT_RX_PDEV_STATS_NUM_RU_SIZE_COUNTERS 6 + #define HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER 8 - struct htt_rx_pdev_rate_stats_tlv { - u32 mac_id__word; -@@ -1758,6 +1771,105 @@ struct htt_ring_backpressure_stats_tlv { +@@ -1797,6 +1809,105 @@ struct htt_ring_backpressure_stats_tlv { u32 backpressure_hist[5]; }; diff --git a/feeds/ipq95xx/mac80211/patches/qca/090-ath11k-fix-fixrate-issue.patch b/feeds/ipq95xx/mac80211/patches/qca/090-ath11k-fix-fixrate-issue.patch index d050d1ce7..e28dee3c7 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/090-ath11k-fix-fixrate-issue.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/090-ath11k-fix-fixrate-issue.patch @@ -54,7 +54,7 @@ + } + + /* Avoid updating invalid nss as fixed rate*/ -+ if (nss > sta->rx_nss) ++ if (nss > sta->deflink.rx_nss) + return -EINVAL; + + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, @@ -99,7 +99,7 @@ band); if (ret) return ret; -+ } else if (sta->ht_cap.ht_supported && num_ht_rates == 1) { ++ } else if (sta->deflink.ht_cap.ht_supported && num_ht_rates == 1) { + ret = ath11k_mac_set_peer_ht_fixed_rate(arvif, sta, mask, + band); + if (ret) @@ -126,10 +126,10 @@ mask); num_he_rates = ath11k_mac_bitrate_mask_num_he_rates(ar, band, @@ -4312,6 +4384,9 @@ static void ath11k_sta_rc_update_wk(stru - } else if (sta->he_cap.has_he && num_he_rates == 1) { + } else if (sta->deflink.he_cap.has_he && num_he_rates == 1) { ath11k_mac_set_peer_he_fixed_rate(arvif, sta, mask, band); -+ } else if (sta->ht_cap.ht_supported && num_ht_rates == 1) { ++ } else if (sta->deflink.ht_cap.ht_supported && num_ht_rates == 1) { + ath11k_mac_set_peer_ht_fixed_rate(arvif, sta, mask, + band); } else { diff --git a/feeds/ipq95xx/mac80211/patches/qca/105-ath11k-fix-monitor-crash-if-tx-offload-is-enabled.patch b/feeds/ipq95xx/mac80211/patches/qca/105-ath11k-fix-monitor-crash-if-tx-offload-is-enabled.patch index 085665627..76701682c 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/105-ath11k-fix-monitor-crash-if-tx-offload-is-enabled.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/105-ath11k-fix-monitor-crash-if-tx-offload-is-enabled.patch @@ -3,16 +3,16 @@ --- a/drivers/net/wireless/ath/ath11k/dp_tx.c +++ b/drivers/net/wireless/ath/ath11k/dp_tx.c -@@ -319,6 +319,8 @@ ath11k_dp_tx_htt_tx_complete_buf(struct +@@ -323,6 +323,8 @@ ath11k_dp_tx_htt_tx_complete_buf(struct struct ieee80211_tx_info *info; struct ath11k_skb_cb *skb_cb; struct ath11k *ar; + struct ieee80211_vif *vif; + u8 flags = 0; - spin_lock_bh(&tx_ring->tx_idr_lock); - msdu = idr_find(&tx_ring->txbuf_idr, ts->msdu_id); -@@ -342,6 +344,14 @@ ath11k_dp_tx_htt_tx_complete_buf(struct + spin_lock(&tx_ring->tx_idr_lock); + msdu = idr_remove(&tx_ring->txbuf_idr, ts->msdu_id); +@@ -344,6 +346,14 @@ ath11k_dp_tx_htt_tx_complete_buf(struct dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); @@ -27,7 +27,7 @@ memset(&info->status, 0, sizeof(info->status)); if (ts->acked) { -@@ -354,8 +364,10 @@ ath11k_dp_tx_htt_tx_complete_buf(struct +@@ -357,8 +367,10 @@ ath11k_dp_tx_htt_tx_complete_buf(struct info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; } } @@ -40,17 +40,17 @@ } static void -@@ -423,6 +435,8 @@ static void ath11k_dp_tx_complete_msdu(s - struct ath11k_skb_cb *skb_cb; +@@ -527,6 +539,8 @@ static void ath11k_dp_tx_complete_msdu(s struct ath11k_peer *peer; struct ath11k_sta *arsta; + struct rate_info rate; + struct ieee80211_vif *vif; + u8 flags = 0; if (WARN_ON_ONCE(ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM)) { /* Must not happen */ -@@ -445,6 +459,9 @@ static void ath11k_dp_tx_complete_msdu(s - goto exit; +@@ -547,6 +561,9 @@ static void ath11k_dp_tx_complete_msdu(s + return; } + flags = skb_cb->flags; @@ -59,13 +59,15 @@ info = IEEE80211_SKB_CB(msdu); memset(&info->status, 0, sizeof(info->status)); -@@ -506,5 +523,8 @@ static void ath11k_dp_tx_complete_msdu(s - status.info = info; - status.rate = &arsta->last_txrate; +@@ -613,7 +630,10 @@ static void ath11k_dp_tx_complete_msdu(s + + spin_unlock_bh(&ab->base_lock); + - ieee80211_tx_status_ext(ar->hw, &status); + if (flags & ATH11K_SKB_HW_80211_ENCAP) + ieee80211_tx_status_8023(ar->hw, vif, msdu); + else + ieee80211_tx_status_ext(ar->hw, &status); - spin_unlock_bh(&ab->base_lock); - return; + } + + static inline void ath11k_dp_tx_status_parse(struct ath11k_base *ab, diff --git a/feeds/ipq95xx/mac80211/patches/qca/108-ath11k-enable-ul-ofdma-ru-allocation-in-peer-stats.patch b/feeds/ipq95xx/mac80211/patches/qca/108-ath11k-enable-ul-ofdma-ru-allocation-in-peer-stats.patch index fd844dfa6..80eb7cc9c 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/108-ath11k-enable-ul-ofdma-ru-allocation-in-peer-stats.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/108-ath11k-enable-ul-ofdma-ru-allocation-in-peer-stats.patch @@ -15,7 +15,7 @@ --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -2894,11 +2894,12 @@ exit: +@@ -2895,11 +2895,12 @@ exit: static void ath11k_dp_rx_update_peer_rate_table_stats(struct ath11k_rx_peer_stats *rx_stats, struct hal_rx_mon_ppdu_info *ppdu_info, @@ -30,7 +30,7 @@ u32 bw_idx = ppdu_info->bw; u32 gi_idx = ppdu_info->gi; -@@ -2920,10 +2921,13 @@ ath11k_dp_rx_update_peer_rate_table_stat +@@ -2921,10 +2922,13 @@ ath11k_dp_rx_update_peer_rate_table_stat } rx_stats->pkt_stats.rx_rate[rate_idx] += num_msdu; @@ -46,7 +46,7 @@ struct hal_rx_mon_ppdu_info *ppdu_info) { struct ath11k_rx_peer_stats *rx_stats = arsta->rx_stats; -@@ -2980,7 +2984,6 @@ static void ath11k_dp_rx_update_peer_sta +@@ -2982,7 +2986,6 @@ static void ath11k_dp_rx_update_peer_sta rx_stats->num_mpdu_fcs_ok += ppdu_info->num_mpdu_fcs_ok; rx_stats->num_mpdu_fcs_err += ppdu_info->num_mpdu_fcs_err; rx_stats->dcm_count += ppdu_info->dcm; @@ -54,7 +54,7 @@ BUILD_BUG_ON(ARRAY_SIZE(arsta->chain_signal) > ARRAY_SIZE(ppdu_info->rssi_chain_pri20)); -@@ -2998,10 +3001,10 @@ static void ath11k_dp_rx_update_peer_sta +@@ -3000,10 +3003,10 @@ static void ath11k_dp_rx_update_peer_sta if (ppdu_info->preamble_type == HAL_RX_PREAMBLE_11N && ppdu_info->mcs <= HAL_RX_MAX_MCS_HT) { @@ -69,7 +69,7 @@ } if (ppdu_info->preamble_type == HAL_RX_PREAMBLE_11AC && -@@ -3034,7 +3037,120 @@ static void ath11k_dp_rx_update_peer_sta +@@ -3036,7 +3039,120 @@ static void ath11k_dp_rx_update_peer_sta rx_stats->byte_stats.bw_count[ppdu_info->bw] += ppdu_info->mpdu_len; } @@ -191,7 +191,7 @@ } -@@ -5317,6 +5433,55 @@ static void ath11k_dp_rx_mon_dest_proces +@@ -5359,6 +5475,55 @@ static void ath11k_dp_rx_mon_dest_proces } } @@ -247,7 +247,7 @@ int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id, struct napi_struct *napi, int budget) { -@@ -5387,8 +5552,13 @@ int ath11k_dp_rx_process_mon_status(stru +@@ -5433,8 +5598,13 @@ int ath11k_dp_rx_process_mon_status(stru if ((ppdu_info.fc_valid) && (ppdu_info.ast_index != HAL_AST_IDX_INVALID)) { @@ -265,15 +265,15 @@ if (ath11k_debugfs_is_pktlog_peer_valid(ar, peer->addr)) { --- a/drivers/net/wireless/ath/ath11k/hal_rx.c +++ b/drivers/net/wireless/ath/ath11k/hal_rx.c -@@ -802,7 +802,6 @@ void ath11k_hal_reo_init_cmd_ring(struct +@@ -804,7 +804,6 @@ void ath11k_hal_reo_init_cmd_ring(struct } } -#define HAL_MAX_UL_MU_USERS 37 static inline void ath11k_hal_rx_handle_ofdma_info(void *rx_tlv, - struct hal_rx_user_status *rx_user_status) -@@ -836,6 +835,8 @@ ath11k_hal_rx_populate_mu_user_info(void + struct hal_rx_user_status *rx_user_status) +@@ -838,6 +837,8 @@ ath11k_hal_rx_populate_mu_user_info(void { rx_user_status->ast_index = ppdu_info->ast_index; rx_user_status->tid = ppdu_info->tid; @@ -282,7 +282,7 @@ rx_user_status->tcp_msdu_count = ppdu_info->tcp_msdu_count; rx_user_status->udp_msdu_count = -@@ -859,6 +860,9 @@ ath11k_hal_rx_populate_mu_user_info(void +@@ -861,6 +862,9 @@ ath11k_hal_rx_populate_mu_user_info(void ppdu_info->num_mpdu_fcs_ok; rx_user_status->mpdu_cnt_fcs_err = ppdu_info->num_mpdu_fcs_err; @@ -292,7 +292,7 @@ ath11k_hal_rx_populate_byte_count(rx_tlv, ppdu_info, rx_user_status); } -@@ -882,6 +886,14 @@ ath11k_hal_rx_parse_mon_status_tlv(struc +@@ -884,6 +888,14 @@ ath11k_hal_rx_parse_mon_status_tlv(struc __le32_to_cpu(ppdu_start->info0)); ppdu_info->chan_num = __le32_to_cpu(ppdu_start->chan_num); ppdu_info->ppdu_ts = __le32_to_cpu(ppdu_start->ppdu_start_ts); @@ -307,9 +307,9 @@ break; } case HAL_RX_PPDU_END_USER_STATS: { -@@ -936,26 +948,26 @@ ath11k_hal_rx_parse_mon_status_tlv(struc +@@ -938,15 +950,16 @@ ath11k_hal_rx_parse_mon_status_tlv(struc - if(userid < HAL_MAX_UL_MU_USERS) { + if (userid < HAL_MAX_UL_MU_USERS) { struct hal_rx_user_status *rxuser_stats = - &ppdu_info->userstats; + &ppdu_info->userstats[userid]; @@ -317,15 +317,17 @@ ath11k_hal_rx_handle_ofdma_info(tlv_data, rxuser_stats); ath11k_hal_rx_populate_mu_user_info(tlv_data, ppdu_info, - rxuser_stats); + rxuser_stats); } -- ppdu_info->userstats.mpdu_fcs_ok_bitmap[0] = eu_stats->rsvd1[0]; -- ppdu_info->userstats.mpdu_fcs_ok_bitmap[1] = eu_stats->rsvd1[1]; -- -+ ppdu_info->mpdu_fcs_ok_bitmap[0] = eu_stats->rsvd1[0]; -+ ppdu_info->mpdu_fcs_ok_bitmap[1] = eu_stats->rsvd1[1]; +- ppdu_info->userstats.mpdu_fcs_ok_bitmap[0] = ++ ppdu_info->mpdu_fcs_ok_bitmap[0] = + __le32_to_cpu(eu_stats->rsvd1[0]); +- ppdu_info->userstats.mpdu_fcs_ok_bitmap[1] = ++ ppdu_info->mpdu_fcs_ok_bitmap[1] = + __le32_to_cpu(eu_stats->rsvd1[1]); + break; - } +@@ -954,12 +967,12 @@ ath11k_hal_rx_parse_mon_status_tlv(struc case HAL_RX_PPDU_END_USER_STATS_EXT: { struct hal_rx_ppdu_end_user_stats_ext *eu_stats = (struct hal_rx_ppdu_end_user_stats_ext *)tlv_data; @@ -357,7 +359,7 @@ enum hal_rx_mon_status { HAL_RX_MON_STATUS_PPDU_NOT_DONE, HAL_RX_MON_STATUS_PPDU_DONE, -@@ -116,14 +120,15 @@ struct hal_rx_user_status { +@@ -82,14 +86,15 @@ struct hal_rx_user_status { u32 mcs:4, nss:3, ofdma_info_valid:1, @@ -376,7 +378,7 @@ u16 udp_msdu_count; u16 other_msdu_count; u16 frame_control; -@@ -137,13 +142,14 @@ struct hal_rx_user_status { +@@ -103,7 +108,7 @@ struct hal_rx_user_status { u8 rs_flags; u32 mpdu_cnt_fcs_ok; u32 mpdu_cnt_fcs_err; @@ -385,6 +387,7 @@ u32 mpdu_ok_byte_count; u32 mpdu_err_byte_count; }; +@@ -144,6 +149,7 @@ struct hal_sw_mon_ring_entries { struct hal_rx_mon_ppdu_info { u32 ppdu_id; @@ -392,7 +395,7 @@ u32 ppdu_ts; u32 num_mpdu_fcs_ok; u32 num_mpdu_fcs_err; -@@ -213,9 +219,20 @@ struct hal_rx_mon_ppdu_info { +@@ -212,9 +218,20 @@ struct hal_rx_mon_ppdu_info { u8 ltf_size; u8 rxpcu_filter_pass; char rssi_chain[8][8]; @@ -439,7 +442,7 @@ struct ath11k_peer *peer; --- a/drivers/net/wireless/ath/ath11k/peer.h +++ b/drivers/net/wireless/ath/ath11k/peer.h -@@ -53,6 +53,7 @@ struct ath11k_peer *ath11k_peer_find(str +@@ -59,6 +59,7 @@ struct ath11k_peer *ath11k_peer_find(str struct ath11k_peer *ath11k_peer_find_by_addr(struct ath11k_base *ab, const u8 *addr); struct ath11k_peer *ath11k_peer_find_by_id(struct ath11k_base *ab, int peer_id); diff --git a/feeds/ipq95xx/mac80211/patches/qca/112-ath11k-add-btcoex-debugfs-support.patch b/feeds/ipq95xx/mac80211/patches/qca/112-ath11k-add-btcoex-debugfs-support.patch index dcd7a5fe9..e38c71514 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/112-ath11k-add-btcoex-debugfs-support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/112-ath11k-add-btcoex-debugfs-support.patch @@ -1,7 +1,7 @@ --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -1249,6 +1249,247 @@ static const struct file_operations fops - .open = simple_open +@@ -1580,6 +1580,247 @@ static const struct file_operations fops + .llseek = default_llseek, }; +static ssize_t ath11k_write_btcoex(struct file *file, @@ -248,16 +248,16 @@ int ath11k_debugfs_register(struct ath11k *ar) { struct ath11k_base *ab = ar->ab; -@@ -1279,6 +1520,15 @@ int ath11k_debugfs_register(struct ath11 - debugfs_create_file("pktlog_filter", 0644, +@@ -1613,6 +1854,15 @@ int ath11k_debugfs_register(struct ath11 + debugfs_create_file("fw_dbglog_config", 0600, ar->debug.debugfs_pdev, ar, - &fops_pktlog_filter); + &fops_fw_dbglog); + debugfs_create_file("btcoex", 0644, -+ ar->debug.debugfs_pdev, ar, -+ &fops__btcoex); ++ ar->debug.debugfs_pdev, ar, ++ &fops__btcoex); + debugfs_create_file("btcoex_duty_cycle", 0644, -+ ar->debug.debugfs_pdev, ar, -+ &fops__btcoex_duty_cycle); ++ ar->debug.debugfs_pdev, ar, ++ &fops__btcoex_duty_cycle); + debugfs_create_file("btcoex_algorithm", 0644, + ar->debug.debugfs_pdev, ar, + &fops_btcoex_algo); @@ -266,7 +266,7 @@ debugfs_create_file("dfs_simulate_radar", 0200, --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -1558,6 +1558,26 @@ static void ath11k_wmi_copy_coex_config( +@@ -1638,6 +1638,26 @@ static void ath11k_wmi_copy_coex_config( coex_config->bt_txrx_time, coex_config->bt_priority_time, coex_config->pta_algorithm, coex_config->pta_priority); } @@ -295,7 +295,7 @@ int ath11k_send_coex_config_cmd(struct ath11k *ar, --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -4792,6 +4792,11 @@ enum wmi_coex_config_type { +@@ -4958,6 +4958,11 @@ enum wmi_coex_config_type { WMI_COEX_CONFIG_WLAN_SCAN_PRIORITY = 15, WMI_COEX_CONFIG_WLAN_PKT_PRIORITY = 16, WMI_COEX_CONFIG_PTA_INTERFACE = 17, @@ -307,7 +307,7 @@ }; struct coex_config_arg { -@@ -4817,6 +4822,13 @@ struct coex_config_arg { +@@ -4983,6 +4988,13 @@ struct coex_config_arg { u32 wlan_pkt_weight; u32 bt_pkt_weight; }; @@ -321,7 +321,7 @@ }; }; -@@ -4844,6 +4856,15 @@ struct wmi_coex_config_cmd { +@@ -5010,6 +5022,15 @@ struct wmi_coex_config_cmd { u32 wlan_pkt_weight; u32 bt_pkt_weight; } __packed; @@ -460,7 +460,7 @@ WIPHY_VENDOR_CMD_NEED_RUNNING, --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -487,6 +487,10 @@ struct ath11k_coex_info { +@@ -626,6 +626,10 @@ struct ath11k_coex_info { u32 bt_priority_time_slot; u32 coex_algo_type; u32 pta_priority; @@ -471,7 +471,7 @@ }; enum ath11k_ap_ps_state { -@@ -494,6 +498,13 @@ enum ath11k_ap_ps_state { +@@ -633,6 +637,13 @@ enum ath11k_ap_ps_state { ATH11K_AP_PS_STATE_ON, }; @@ -487,7 +487,7 @@ struct ath11k_pdev *pdev; --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -7276,6 +7276,11 @@ static void ath11k_mac_fetch_coex_info(s +@@ -9009,6 +9009,11 @@ static void ath11k_mac_fetch_coex_info(s ath11k_err(ab, "No qcom,pta-priority entry in dev-tree.\n"); } diff --git a/feeds/ipq95xx/mac80211/patches/qca/138-ath11k-fill-vdev-pdev-id-for-fwtest-cmd.patch b/feeds/ipq95xx/mac80211/patches/qca/138-ath11k-fill-vdev-pdev-id-for-fwtest-cmd.patch index e7a093197..4d82f55ca 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/138-ath11k-fill-vdev-pdev-id-for-fwtest-cmd.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/138-ath11k-fill-vdev-pdev-id-for-fwtest-cmd.patch @@ -1,6 +1,22 @@ +From d4342be9786373d76303dae06bb7b560d7b8f864 Mon Sep 17 00:00:00 2001 +From: Lavanya Suresh +Date: Thu, 21 Jan 2021 21:27:14 +0530 +Subject: [PATCH] ath11k: fill vdev pdev id for fwtest cmd + +Update proper vdev pdev id for fwtest command. + +Add null checks for vif ptr of vdev, to avoid sending fwtest +cmd when vdev is not up. + +Signed-off-by: Venkateswara Naralasetty +Signed-off-by: Lavanya Suresh +--- + drivers/net/wireless/ath/ath11k/testmode.c | 37 +++++++++++++++++------------- + 1 file changed, 21 insertions(+), 16 deletions(-) + --- a/drivers/net/wireless/ath/ath11k/testmode.c +++ b/drivers/net/wireless/ath/ath11k/testmode.c -@@ -273,13 +273,16 @@ out: +@@ -298,13 +298,16 @@ err: return ret; } @@ -19,7 +35,7 @@ mutex_lock(&ar->conf_mutex); -@@ -302,6 +305,18 @@ static int ath11k_tm_cmd_wmi(struct ath1 +@@ -322,6 +325,27 @@ static int ath11k_tm_cmd_wmi(struct ath1 buf_len = nla_len(tb[ATH11K_TM_ATTR_DATA]); cmd_id = nla_get_u32(tb[ATH11K_TM_ATTR_WMI_CMDID]); @@ -30,20 +46,20 @@ + if (tag == WMI_TAG_PDEV_SET_PARAM_CMD) + *ptr = ar->pdev->pdev_id; + -+ if (vif && (tag == WMI_TAG_VDEV_SET_PARAM_CMD || tag == WMI_TAG_UNIT_TEST_CMD)) { -+ arvif = (struct ath11k_vif *)vif->drv_priv; -+ *ptr = arvif->vdev_id; ++ if (ar->ab->fw_mode != ATH11K_FIRMWARE_MODE_FTM && ++ (tag == WMI_TAG_VDEV_SET_PARAM_CMD || tag == WMI_TAG_UNIT_TEST_CMD)) { ++ if (vif) { ++ arvif = (struct ath11k_vif *)vif->drv_priv; ++ *ptr = arvif->vdev_id; ++ } ++ else { ++ ret = -EINVAL; ++ ath11k_warn(ar->ab, "vdev is not up for given vdev id, so failed to send wmi command (testmode): %d\n", ++ ret); ++ goto out; ++ } + } + ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE, "testmode cmd wmi cmd_id %d buf %pK buf_len %d\n", cmd_id, buf, buf_len); -@@ -443,7 +458,7 @@ int ath11k_tm_cmd(struct ieee80211_hw *h - case ATH11K_TM_CMD_GET_VERSION: - return ath11k_tm_cmd_get_version(ar, tb); - case ATH11K_TM_CMD_WMI_FW_TEST: -- return ath11k_tm_cmd_wmi(ar, tb); -+ return ath11k_tm_cmd_wmi(ar, tb, vif); - default: - return -EOPNOTSUPP; - } diff --git a/feeds/ipq95xx/mac80211/patches/qca/142-ath11k-adding-support-for-mgmt-frame-stats.patch b/feeds/ipq95xx/mac80211/patches/qca/142-ath11k-adding-support-for-mgmt-frame-stats.patch index 691d4c9f7..db9e00fed 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/142-ath11k-adding-support-for-mgmt-frame-stats.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/142-ath11k-adding-support-for-mgmt-frame-stats.patch @@ -1,7 +1,7 @@ --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -225,6 +225,16 @@ enum ath11k_monitor_flags { - ATH11K_FLAG_MONITOR_VDEV_CREATED, +@@ -314,6 +314,16 @@ struct ath11k_rekey_data { + bool enable_offload; }; +#define ATH11K_STATS_MGMT_FRM_TYPE_MAX 16 @@ -17,17 +17,18 @@ struct ath11k_vif { u32 vdev_id; enum wmi_vdev_type vdev_type; -@@ -277,6 +287,7 @@ struct ath11k_vif { - bool do_not_send_tmpl; - struct ieee80211_chanctx_conf chanctx; +@@ -371,6 +381,8 @@ struct ath11k_vif { + #ifdef CPTCFG_ATH11K_DEBUGFS struct dentry *debugfs_twt; + #endif /* CPTCFG_ATH11K_DEBUGFS */ ++ + struct ath11k_mgmt_frame_stats mgmt_stats; }; struct ath11k_vif_iter { --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -1558,6 +1558,87 @@ static const struct file_operations fops +@@ -1827,6 +1827,87 @@ static const struct file_operations fops .open = simple_open }; @@ -115,7 +116,7 @@ int ath11k_debugfs_register(struct ath11k *ar) { struct ath11k_base *ab = ar->ab; -@@ -1597,6 +1678,9 @@ int ath11k_debugfs_register(struct ath11 +@@ -1869,6 +1950,9 @@ int ath11k_debugfs_register(struct ath11 debugfs_create_file("btcoex_algorithm", 0644, ar->debug.debugfs_pdev, ar, &fops_btcoex_algo); @@ -127,7 +128,7 @@ debugfs_create_file("dfs_simulate_radar", 0200, --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -5870,9 +5870,9 @@ static int ath11k_mac_mgmt_tx(struct ath +@@ -5897,9 +5897,9 @@ static int ath11k_mac_mgmt_tx(struct ath */ if (is_prb_rsp && atomic_read(&ar->num_pending_mgmt_tx) > ATH11K_PRB_RSP_DROP_THRESHOLD) { @@ -139,7 +140,7 @@ } if (skb_queue_len_lockless(q) >= ATH11K_TX_MGMT_NUM_PENDING_MAX) { -@@ -5955,9 +5955,11 @@ static void ath11k_mac_op_tx(struct ieee +@@ -5925,9 +5925,11 @@ static void ath11k_mac_op_tx(struct ieee struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_key_conf *key = info->control.hw_key; @@ -151,7 +152,7 @@ int ret; memset(skb_cb, 0, sizeof(*skb_cb)); -@@ -5971,12 +5973,21 @@ static void ath11k_mac_op_tx(struct ieee +@@ -5941,12 +5943,21 @@ static void ath11k_mac_op_tx(struct ieee if (info_flags & IEEE80211_TX_CTL_HW_80211_ENCAP) { skb_cb->flags |= ATH11K_SKB_HW_80211_ENCAP; } else if (ieee80211_is_mgmt(hdr->frame_control)) { @@ -177,7 +178,7 @@ } --- a/drivers/net/wireless/ath/ath11k/peer.c +++ b/drivers/net/wireless/ath/ath11k/peer.c -@@ -319,6 +319,7 @@ int ath11k_peer_create(struct ath11k *ar +@@ -435,6 +435,7 @@ int ath11k_peer_create(struct ath11k *ar peer->sec_type = HAL_ENCRYPT_TYPE_OPEN; peer->sec_type_grp = HAL_ENCRYPT_TYPE_OPEN; @@ -187,7 +188,7 @@ arsta = (struct ath11k_sta *)sta->drv_priv; --- a/drivers/net/wireless/ath/ath11k/peer.h +++ b/drivers/net/wireless/ath/ath11k/peer.h -@@ -20,6 +20,7 @@ struct ppdu_user_delayba { +@@ -21,6 +21,7 @@ struct ppdu_user_delayba { struct ath11k_peer { struct list_head list; struct ieee80211_sta *sta; @@ -197,7 +198,7 @@ int peer_id; --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -5426,6 +5426,12 @@ static int wmi_process_mgmt_tx_comp(stru +@@ -5619,6 +5619,12 @@ static int wmi_process_mgmt_tx_comp(stru struct sk_buff *msdu; struct ieee80211_tx_info *info; struct ath11k_skb_cb *skb_cb; @@ -210,7 +211,7 @@ int num_mgmt; spin_lock_bh(&ar->txmgmt_idr_lock); -@@ -5448,6 +5454,31 @@ static int wmi_process_mgmt_tx_comp(stru +@@ -5641,6 +5647,31 @@ static int wmi_process_mgmt_tx_comp(stru if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) && !status) info->flags |= IEEE80211_TX_STAT_ACK; @@ -242,7 +243,7 @@ ieee80211_tx_status_irqsafe(ar->hw, msdu); num_mgmt = atomic_dec_if_positive(&ar->num_pending_mgmt_tx); -@@ -7021,6 +7052,11 @@ static void ath11k_mgmt_rx_event(struct +@@ -7228,6 +7259,11 @@ static void ath11k_mgmt_rx_event(struct struct ieee80211_hdr *hdr; u16 fc; struct ieee80211_supported_band *sband; @@ -254,7 +255,7 @@ if (ath11k_pull_mgmt_rx_params_tlv(ab, skb, &rx_ev) != 0) { ath11k_warn(ab, "failed to extract mgmt rx event"); -@@ -7086,7 +7122,34 @@ static void ath11k_mgmt_rx_event(struct +@@ -7293,7 +7329,34 @@ static void ath11k_mgmt_rx_event(struct hdr = (struct ieee80211_hdr *)skb->data; fc = le16_to_cpu(hdr->frame_control); diff --git a/feeds/ipq95xx/mac80211/patches/qca/164-ath11k-add-qcn9000-support.patch b/feeds/ipq95xx/mac80211/patches/qca/164-ath11k-add-qcn9000-support.patch index 242f06aa6..90a470cac 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/164-ath11k-add-qcn9000-support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/164-ath11k-add-qcn9000-support.patch @@ -14,15 +14,7 @@ Signed-off-by: Anilkumar Kolli --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c -@@ -13,6 +13,7 @@ - #include "hif.h" - #include "mhi.h" - #include "debug.h" -+#include - - #define ATH11K_PCI_BAR_NUM 0 - #define ATH11K_PCI_DMA_MASK 32 -@@ -923,6 +924,7 @@ err_irq_affinity_cleanup: +@@ -370,6 +370,7 @@ 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; @@ -30,7 +22,7 @@ Signed-off-by: Anilkumar Kolli cfg->tgt_ce = ab->hw_params.target_ce_config; cfg->tgt_ce_len = ab->hw_params.target_ce_count; -@@ -931,6 +933,9 @@ static void ath11k_pci_init_qmi_ce_confi +@@ -378,6 +379,9 @@ static void ath11k_pci_init_qmi_ce_confi 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; @@ -40,24 +32,24 @@ Signed-off-by: Anilkumar Kolli ath11k_ce_get_shadow_config(ab, &cfg->shadow_reg_v2, &cfg->shadow_reg_v2_len); } -@@ -984,7 +989,7 @@ static int ath11k_pci_alloc_msi(struct a - num_vectors = pci_alloc_irq_vectors(ab_pci->pdev, +@@ -419,7 +423,7 @@ static int ath11k_pci_alloc_msi(struct a + num_vectors = pci_alloc_irq_vectors(pci_dev, msi_config->total_vectors, msi_config->total_vectors, - PCI_IRQ_MSI); + PCI_IRQ_NOMSIX); if (num_vectors == msi_config->total_vectors) { - set_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags); - ab_pci->irq_flags = IRQF_SHARED; -@@ -1158,6 +1163,7 @@ static int ath11k_pci_power_up(struct at + set_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags); + } else { +@@ -599,6 +603,7 @@ static int ath11k_pci_power_up(struct at { struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); int ret; + u32 addr; ab_pci->register_window = 0; - clear_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags); -@@ -1382,6 +1388,14 @@ static int ath11k_pci_probe(struct pci_d + clear_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags); +@@ -756,6 +761,14 @@ static int ath11k_pci_probe(struct pci_d if (!ret) set_bit(ATH11K_FLAG_FIXED_MEM_RGN, &ab->dev_flags); @@ -67,14 +59,14 @@ Signed-off-by: Anilkumar Kolli + */ + ret = of_property_read_u32(ab->dev->of_node, "base-addr", &addr); + if (ret == 0) -+ ab->bus_params.fixed_mem_region = true; ++ ab->hw_params.fixed_mem_region = true; + ret = ath11k_pci_claim(ab_pci, pdev); if (ret) { ath11k_err(ab, "failed to claim device: %d\n", ret); --- a/drivers/net/wireless/ath/ath11k/mhi.c +++ b/drivers/net/wireless/ath/ath11k/mhi.c -@@ -28,6 +28,7 @@ static struct mhi_channel_config ath11k_ +@@ -33,6 +33,7 @@ static struct mhi_channel_config ath11k_ .offload_channel = false, .doorbell_mode_switch = false, .auto_queue = false, @@ -82,7 +74,7 @@ Signed-off-by: Anilkumar Kolli }, { .num = 1, -@@ -42,6 +43,7 @@ static struct mhi_channel_config ath11k_ +@@ -47,6 +48,7 @@ static struct mhi_channel_config ath11k_ .offload_channel = false, .doorbell_mode_switch = false, .auto_queue = false, @@ -90,7 +82,7 @@ Signed-off-by: Anilkumar Kolli }, { .num = 20, -@@ -56,6 +58,7 @@ static struct mhi_channel_config ath11k_ +@@ -61,6 +63,7 @@ static struct mhi_channel_config ath11k_ .offload_channel = false, .doorbell_mode_switch = false, .auto_queue = false, @@ -98,7 +90,7 @@ Signed-off-by: Anilkumar Kolli }, { .num = 21, -@@ -70,6 +73,7 @@ static struct mhi_channel_config ath11k_ +@@ -75,6 +78,7 @@ static struct mhi_channel_config ath11k_ .offload_channel = false, .doorbell_mode_switch = false, .auto_queue = true, @@ -106,7 +98,7 @@ Signed-off-by: Anilkumar Kolli }, }; -@@ -121,6 +125,7 @@ static struct mhi_channel_config ath11k_ +@@ -126,6 +130,7 @@ static struct mhi_channel_config ath11k_ .offload_channel = false, .doorbell_mode_switch = false, .auto_queue = false, @@ -114,7 +106,7 @@ Signed-off-by: Anilkumar Kolli }, { .num = 1, -@@ -135,6 +140,7 @@ static struct mhi_channel_config ath11k_ +@@ -140,6 +145,7 @@ static struct mhi_channel_config ath11k_ .offload_channel = false, .doorbell_mode_switch = false, .auto_queue = false, @@ -122,7 +114,7 @@ Signed-off-by: Anilkumar Kolli }, { .num = 20, -@@ -149,6 +155,7 @@ static struct mhi_channel_config ath11k_ +@@ -154,6 +160,7 @@ static struct mhi_channel_config ath11k_ .offload_channel = false, .doorbell_mode_switch = false, .auto_queue = false, @@ -130,7 +122,7 @@ Signed-off-by: Anilkumar Kolli }, { .num = 21, -@@ -163,6 +170,7 @@ static struct mhi_channel_config ath11k_ +@@ -168,6 +175,7 @@ static struct mhi_channel_config ath11k_ .offload_channel = false, .doorbell_mode_switch = false, .auto_queue = true, @@ -138,20 +130,19 @@ Signed-off-by: Anilkumar Kolli }, }; -@@ -384,6 +392,10 @@ int ath11k_mhi_register(struct ath11k_pc +@@ -420,6 +428,9 @@ int ath11k_mhi_register(struct ath11k_pc mhi_ctrl->iova_stop = 0xFFFFFFFF; } + ath11k_info(ab, "mhi_ctrl start addr %llx end addr %llx\n", -+ (u64)mhi_ctrl->iova_start, (u64)mhi_ctrl->iova_stop); -+ ++ (u64)mhi_ctrl->iova_start, (u64)mhi_ctrl->iova_stop); + + mhi_ctrl->rddm_size = RDDM_DUMP_SIZE; mhi_ctrl->sbl_size = SZ_512K; mhi_ctrl->seg_len = SZ_512K; - mhi_ctrl->fbc_download = true; --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c -@@ -3154,7 +3154,7 @@ static void ath11k_qmi_msg_mem_request_c +@@ -3345,7 +3345,7 @@ static void ath11k_qmi_msg_mem_request_c ret); return; } @@ -160,7 +151,7 @@ Signed-off-by: Anilkumar Kolli ret = ath11k_qmi_alloc_target_mem_chunk(ab); if (ret) { ath11k_warn(ab, "failed to allocate qmi target memory: %d\n", -@@ -3324,7 +3324,7 @@ static void ath11k_qmi_driver_event_work +@@ -3525,7 +3525,7 @@ static void ath11k_qmi_driver_event_work break; } diff --git a/feeds/ipq95xx/mac80211/patches/qca/188-ath11k-m3-ssr-dump-collection.patch b/feeds/ipq95xx/mac80211/patches/qca/188-ath11k-m3-ssr-dump-collection.patch index 3583a24cc..ca6580b2d 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/188-ath11k-m3-ssr-dump-collection.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/188-ath11k-m3-ssr-dump-collection.patch @@ -1,14 +1,14 @@ --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c -@@ -12,6 +12,7 @@ - #include - #include +@@ -15,6 +15,7 @@ #include + #include + #include +#include #define SLEEP_CLOCK_SELECT_INTERNAL_BIT 0x02 #define HOST_CSTATE_BIT 0x04 -@@ -472,6 +473,24 @@ static struct qmi_elem_info qmi_wlanfw_h +@@ -478,6 +479,24 @@ static struct qmi_elem_info qmi_wlanfw_h .ei_array = qmi_response_type_v01_ei, }, { @@ -33,7 +33,7 @@ .data_type = QMI_EOTI, .array_type = NO_ARRAY, .tlv_type = QMI_COMMON_TLV_TYPE, -@@ -697,6 +716,24 @@ static struct qmi_elem_info qmi_wlanfw_i +@@ -703,6 +722,24 @@ static struct qmi_elem_info qmi_wlanfw_i cal_done_enable), }, { @@ -58,7 +58,7 @@ .data_type = QMI_EOTI, .array_type = NO_ARRAY, .tlv_type = QMI_COMMON_TLV_TYPE, -@@ -1816,6 +1853,87 @@ static struct qmi_elem_info qmi_wlanfw_w +@@ -1884,6 +1921,87 @@ static struct qmi_elem_info qmi_wlanfw_w }, }; @@ -146,16 +146,16 @@ int wlfw_send_qdss_trace_config_download_req(struct ath11k_base *ab, const u8 *buffer, unsigned int file_len) { -@@ -2082,6 +2200,8 @@ static int ath11k_qmi_fw_ind_register_se +@@ -2149,6 +2267,8 @@ static int ath11k_qmi_fw_ind_register_se req->qdss_trace_free_enable = 1; req->pin_connect_result_enable_valid = 0; req->pin_connect_result_enable = 0; + req->m3_dump_upload_req_enable_valid = 1; + req->m3_dump_upload_req_enable = 1; - ret = qmi_txn_init(handle, &txn, - qmi_wlanfw_ind_register_resp_msg_v01_ei, resp); -@@ -2333,6 +2453,33 @@ static int ath11k_qmi_assign_target_mem_ + /* WCN6750 doesn't request for DDR memory via QMI, + * instead it uses a fixed 12MB reserved memory +@@ -2428,6 +2548,33 @@ static int ath11k_qmi_assign_target_mem_ ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type; idx++; break; @@ -189,7 +189,7 @@ default: ath11k_warn(ab, "qmi ignore invalid mem req type %d\n", ab->qmi.target_mem[i].type); -@@ -3032,6 +3179,114 @@ static int ath11k_qmi_process_coldboot_c +@@ -3214,6 +3361,114 @@ static int ath11k_qmi_process_coldboot_c return 0; } @@ -304,7 +304,7 @@ static int ath11k_qmi_driver_event_post(struct ath11k_qmi *qmi, enum ath11k_qmi_event_type type, -@@ -3204,6 +3459,30 @@ static void ath11k_qmi_msg_cold_boot_cal +@@ -3395,6 +3650,30 @@ static void ath11k_qmi_msg_cold_boot_cal ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi cold boot calibration done\n"); } @@ -335,7 +335,7 @@ static const struct qmi_msg_handler ath11k_qmi_msg_handlers[] = { { .type = QMI_INDICATION, -@@ -3234,6 +3513,14 @@ static const struct qmi_msg_handler ath1 +@@ -3425,6 +3704,14 @@ static const struct qmi_msg_handler ath1 sizeof(struct qmi_wlanfw_fw_cold_cal_done_ind_msg_v01), .fn = ath11k_qmi_msg_cold_boot_cal_done_cb, }, @@ -350,7 +350,7 @@ }; static int ath11k_qmi_ops_new_server(struct qmi_handle *qmi_hdl, -@@ -3338,6 +3625,9 @@ static void ath11k_qmi_driver_event_work +@@ -3543,6 +3830,9 @@ static void ath11k_qmi_driver_event_work break; case ATH11K_QMI_EVENT_COLD_BOOT_CAL_DONE: break; @@ -362,31 +362,33 @@ break; --- a/drivers/net/wireless/ath/ath11k/qmi.h +++ b/drivers/net/wireless/ath/ath11k/qmi.h -@@ -30,16 +30,23 @@ +@@ -32,11 +32,16 @@ #define ATH11K_QMI_FW_MEM_REQ_SEGMENT_CNT 3 #define ATH11K_QMI_MAX_QDSS_CONFIG_FILE_NAME_SIZE 64 #define ATH11K_QMI_DEFAULT_QDSS_CONFIG_FILE_NAME "qdss_trace_config.bin" -+#define ATH11K_QMI_IPQ8074_M3_DUMP_ADDRESS 0x51000000 -+#define ATH11K_QMI_IPQ6018_M3_DUMP_ADDRESS 0x50100000 -+#define ATH11K_QMI_M3_DUMP_SIZE 0x100000 ++#define ATH11K_QMI_IPQ8074_M3_DUMP_ADDRESS 0x51000000 ++#define ATH11K_QMI_IPQ6018_M3_DUMP_ADDRESS 0x50100000 ++#define ATH11K_QMI_M3_DUMP_SIZE 0x100000 #define QMI_WLFW_REQUEST_MEM_IND_V01 0x0035 #define QMI_WLFW_FW_MEM_READY_IND_V01 0x0037 #define QMI_WLFW_COLD_BOOT_CAL_DONE_IND_V01 0x0021 #define QMI_WLFW_FW_READY_IND_V01 0x0038 -+#define QMI_WLFW_M3_DUMP_UPLOAD_DONE_REQ_V01 0x004E -+#define QMI_WLFW_M3_DUMP_UPLOAD_REQ_IND_V01 0x004D ++#define QMI_WLFW_M3_DUMP_UPLOAD_DONE_REQ_V01 0x004E ++#define QMI_WLFW_M3_DUMP_UPLOAD_REQ_IND_V01 0x004D #define QMI_WLANFW_MAX_DATA_SIZE_V01 6144 #define ATH11K_FIRMWARE_MODE_OFF 4 - #define ATH11K_COLD_BOOT_FW_RESET_DELAY (40 * HZ) +@@ -44,6 +49,8 @@ -+#define ATH11K_HOST_DDR_M3_OFFSET 0x2300000 + #define ATH11K_QMI_DEVICE_BAR_SIZE 0x200000 + ++#define ATH11K_HOST_DDR_M3_OFFSET 0x2300000 + struct ath11k_base; enum ath11k_qmi_file_type { -@@ -69,6 +76,7 @@ enum ath11k_qmi_event_type { +@@ -73,6 +80,7 @@ enum ath11k_qmi_event_type { ATH11K_QMI_EVENT_FORCE_FW_ASSERT, ATH11K_QMI_EVENT_POWER_UP, ATH11K_QMI_EVENT_POWER_DOWN, @@ -394,7 +396,7 @@ ATH11K_QMI_EVENT_MAX, }; -@@ -78,6 +86,13 @@ struct ath11k_qmi_driver_event { +@@ -82,6 +90,13 @@ struct ath11k_qmi_driver_event { void *data; }; @@ -408,7 +410,7 @@ struct ath11k_qmi_ce_cfg { const struct ce_pipe_config *tgt_ce; int tgt_ce_len; -@@ -141,6 +156,12 @@ struct ath11k_qmi { +@@ -147,6 +162,12 @@ struct ath11k_qmi { wait_queue_head_t cold_boot_waitq; }; @@ -421,7 +423,7 @@ #define QMI_WLANFW_QDSS_TRACE_CONFIG_DOWNLOAD_REQ_MSG_V01_MAX_LEN 6167 #define QMI_WLANFW_QDSS_TRACE_CONFIG_DOWNLOAD_RESP_MSG_V01_MAX_LEN 7 #define QMI_WLANFW_QDSS_TRACE_CONFIG_DOWNLOAD_REQ_V01 0x0044 -@@ -162,6 +183,15 @@ struct qmi_wlanfw_qdss_trace_config_down +@@ -168,6 +189,15 @@ struct qmi_wlanfw_qdss_trace_config_down struct qmi_response_type_v01 resp; }; @@ -437,7 +439,7 @@ #define QMI_WLANFW_QDSS_TRACE_MODE_REQ_V01 0x0045 #define QMI_WLANFW_QDSS_TRACE_MODE_REQ_MSG_V01_MAX_LEN 18 #define QMI_WLANFW_QDSS_TRACE_MODE_RESP_MSG_V01_MAX_LEN 7 -@@ -269,6 +299,10 @@ struct qmi_wlanfw_ind_register_req_msg_v +@@ -275,6 +305,10 @@ struct qmi_wlanfw_ind_register_req_msg_v u8 qdss_trace_save_enable; u8 qdss_trace_free_enable_valid; u8 qdss_trace_free_enable; @@ -448,7 +450,7 @@ }; struct qmi_wlanfw_ind_register_resp_msg_v01 { -@@ -342,6 +376,12 @@ struct qmi_wlanfw_fw_cold_cal_done_ind_m +@@ -348,6 +382,12 @@ struct qmi_wlanfw_fw_cold_cal_done_ind_m char placeholder; }; @@ -458,10 +460,10 @@ + u64 size; +}; + - #define QMI_WLANFW_CAP_REQ_MSG_V01_MAX_LEN 0 - #define QMI_WLANFW_CAP_RESP_MSG_V01_MAX_LEN 235 - #define QMI_WLANFW_CAP_REQ_V01 0x0024 -@@ -472,6 +512,8 @@ struct qmi_wlanfw_bdf_download_resp_msg_ + #define QMI_WLANFW_CAP_REQ_MSG_V01_MAX_LEN 0 + #define QMI_WLANFW_CAP_RESP_MSG_V01_MAX_LEN 235 + #define QMI_WLANFW_CAP_REQ_V01 0x0024 +@@ -492,6 +532,8 @@ struct qmi_wlanfw_bdf_download_resp_msg_ #define QMI_WLANFW_M3_INFO_RESP_V01 0x003C #define QMI_WLANFW_M3_INFO_REQ_V01 0x003C @@ -472,17 +474,17 @@ u32 size; --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -505,6 +505,7 @@ struct ath11k_debug { - bool is_pkt_logging; - #endif - u32 rx_filter; +@@ -608,6 +608,7 @@ struct ath11k_debug { + u32 mem_offset; + u32 module_id_bitmap[MAX_MODULE_ID_BITMAP_WORDS]; + struct ath11k_debug_dbr *dbr_debug[WMI_DIRECT_BUF_MAX]; + bool enable_m3_dump; }; struct ath11k_per_peer_tx_stats { --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -1671,6 +1671,68 @@ static const struct file_operations fops +@@ -1940,6 +1940,68 @@ static const struct file_operations fops .open = simple_open }; @@ -551,9 +553,9 @@ int ath11k_debugfs_register(struct ath11k *ar) { struct ath11k_base *ab = ar->ab; -@@ -1726,6 +1788,10 @@ int ath11k_debugfs_register(struct ath11 - &ar->dfs_block_radar_events); - } +@@ -2002,6 +2064,10 @@ int ath11k_debugfs_register(struct ath11 + debugfs_create_file("enable_dbr_debug", 0200, ar->debug.debugfs_pdev, + ar, &fops_dbr_debug); + debugfs_create_file("enable_m3_dump", 0644, + ar->debug.debugfs_pdev, ar, @@ -564,8 +566,8 @@ --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -8328,6 +8328,36 @@ int ath11k_wmi_simulate_radar(struct ath - return ath11k_wmi_send_unit_test_cmd(ar, wmi_ut, dfs_args); +@@ -8681,6 +8681,36 @@ int ath11k_wmi_fw_dbglog_cfg(struct ath1 + return ret; } +int ath11k_wmi_pdev_m3_dump_enable(struct ath11k *ar, u32 enable) { @@ -603,8 +605,8 @@ u32 i; --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -2083,6 +2083,11 @@ enum wmi_tlv_service { - WMI_MAX_EXT_SERVICE +@@ -2098,6 +2098,11 @@ enum wmi_tlv_service { + WMI_MAX_EXT2_SERVICE = 384 }; +enum wmi_unit_test_cmdid { @@ -615,7 +617,7 @@ enum { WMI_SMPS_FORCED_MODE_NONE = 0, WMI_SMPS_FORCED_MODE_DISABLED, -@@ -3996,6 +4001,15 @@ struct wmi_dfs_unit_test_arg { +@@ -4003,6 +4008,15 @@ struct wmi_dfs_unit_test_arg { u32 radar_param; }; @@ -631,17 +633,17 @@ struct wmi_unit_test_cmd { u32 tlv_header; u32 vdev_id; -@@ -5830,6 +5844,7 @@ int ath11k_wmi_set_hw_mode(struct ath11k +@@ -6325,6 +6339,7 @@ int ath11k_wmi_set_hw_mode(struct ath11k enum wmi_host_hw_mode_config_type mode); int ath11k_wmi_wow_host_wakeup_ind(struct ath11k *ar); int ath11k_wmi_wow_enable(struct ath11k *ar); +int ath11k_wmi_pdev_m3_dump_enable(struct ath11k *ar, u32 enable); int ath11k_wmi_scan_prob_req_oui(struct ath11k *ar, const u8 mac_addr[ETH_ALEN]); - #endif + int ath11k_wmi_fw_dbglog_cfg(struct ath11k *ar, u32 *module_id_bitmap, --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -54,6 +54,7 @@ static const struct ath11k_hw_params ath +@@ -55,6 +55,7 @@ static const struct ath11k_hw_params ath .max_radios = 3, .bdf_addr = 0x4B0C0000, .hw_ops = &ipq8074_ops, @@ -649,7 +651,7 @@ .ring_mask = &ath11k_hw_ring_mask_ipq8074, .internal_sleep_clock = false, .regs = &ipq8074_regs, -@@ -122,6 +123,7 @@ static const struct ath11k_hw_params ath +@@ -129,6 +130,7 @@ static const struct ath11k_hw_params ath .max_radios = 2, .bdf_addr = 0x4ABC0000, .hw_ops = &ipq6018_ops, @@ -657,7 +659,7 @@ .ring_mask = &ath11k_hw_ring_mask_ipq8074, .internal_sleep_clock = false, .regs = &ipq8074_regs, -@@ -286,7 +288,7 @@ static const struct ath11k_hw_params ath +@@ -302,7 +304,7 @@ static const struct ath11k_hw_params ath .supports_shadow_regs = false, .idle_ps = false, .supports_sta_ps = false, @@ -668,10 +670,10 @@ .num_peers = 128, --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h -@@ -190,6 +190,7 @@ struct ath11k_hw_params { +@@ -187,6 +187,7 @@ struct ath11k_hw_params { + const struct ath11k_hw_hal_params *hal_params; bool supports_dynamic_smps_6ghz; bool alloc_cacheable_memory; - bool wakeup_mhi; + u32 m3_addr; bool supports_rssi_stats; bool fw_wmi_diag_event; diff --git a/feeds/ipq95xx/mac80211/patches/qca/189-ath11k-add-support-for-device-recovery.patch b/feeds/ipq95xx/mac80211/patches/qca/189-ath11k-add-support-for-device-recovery.patch deleted file mode 100644 index d825d4da4..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/189-ath11k-add-support-for-device-recovery.patch +++ /dev/null @@ -1,200 +0,0 @@ -From 07ce203ddee206785244a083ba030ed99af07392 Mon Sep 17 00:00:00 2001 -From: Anilkumar Kolli -Date: Wed, 9 Sep 2020 19:53:01 +0530 -Subject: [PATCH 13/15] ath11k: ath11k: add support for device recovery - -Test command: -echo assert > /sys/kernel/debug/ath11k/qca6390/simulate_fw_crash - -Then ath11k_mhi_notify_status receive MHI_CB_EE_RDDM notify and start -to do recovery process. - -It need add workqueue_aux, because ab->workqueue is used when receive -ATH11K_QMI_EVENT_FW_READY in recovery process(queue_work(ab->workqueue, -&ab->restart_work;)), and ath11k_core_reset will wait for max -ATH11K_RESET_TIMEOUT_HZ for the previous restart_work finished, if -ath11k_core_reset also queued in ab->workqueue, then it will delay -restart_work of previous recovery and lead previous recovery fail. - -With this patch, ath11k recovery success - -Signed-off-by: Wen Gong ---- - drivers/net/wireless/ath/ath11k/core.c | 48 ++++++++++++++++++++++++++++++++++ - drivers/net/wireless/ath/ath11k/core.h | 6 +++++ - drivers/net/wireless/ath/ath11k/mhi.c | 31 ++++++++++++++++++++++ - drivers/net/wireless/ath/ath11k/pci.c | 1 + - 4 files changed, 86 insertions(+) - ---- a/drivers/net/wireless/ath/ath11k/core.c -+++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -1483,9 +1483,49 @@ static void ath11k_core_restart(struct w - } - mutex_unlock(&ar->conf_mutex); - } -+ -+ if (ab->is_reset) { -+ atomic_dec(&ab->reset_count); -+ complete(&ab->reset_complete); -+ ab->is_reset = false; -+ } -+ - complete(&ab->driver_recovery); - } - -+static void ath11k_core_reset(struct work_struct *work) -+{ -+ struct ath11k_base *ab = container_of(work, struct ath11k_base, reset_work); -+ int reset_count; -+ long time_left; -+ -+ reset_count = atomic_add_return(1, &ab->reset_count); -+ -+ if (reset_count > 1) { -+ ath11k_warn(ab, "already reseting count %d\n", reset_count); -+ -+ reinit_completion(&ab->reset_complete); -+ time_left = wait_for_completion_timeout(&ab->reset_complete, -+ ATH11K_RESET_TIMEOUT_HZ); -+ ath11k_info(ab, "reset wait time left %ld\n", time_left); -+ -+ if (time_left) { -+ ath11k_info(ab, "to skip reset\n"); -+ atomic_dec(&ab->reset_count); -+ return; -+ } -+ } -+ -+ ath11k_info(ab, "reset starting\n"); -+ -+ ab->is_reset = true; -+ -+ ath11k_hif_power_down(ab); -+ ath11k_hif_power_up(ab); -+ -+ ath11k_info(ab, "reset started\n"); -+} -+ - static int ath11k_init_hw_params(struct ath11k_base *ab) - { - const struct ath11k_hw_params *hw_params = NULL; -@@ -1596,8 +1636,13 @@ struct ath11k_base *ath11k_core_alloc(st - if (!ab->workqueue) - goto err_sc_free; - -+ ab->workqueue_aux = create_singlethread_workqueue("ath11k_aux_wq"); -+ if (!ab->workqueue_aux) -+ goto err_free_wq; -+ - mutex_init(&ab->core_lock); - spin_lock_init(&ab->base_lock); -+ init_completion(&ab->reset_complete); - mutex_init(&ab->vdev_id_11d_lock); - - INIT_LIST_HEAD(&ab->peers); -@@ -1608,6 +1653,7 @@ struct ath11k_base *ath11k_core_alloc(st - init_waitqueue_head(&ath11k_ssr_dump_wq); - #endif - INIT_WORK(&ab->restart_work, ath11k_core_restart); -+ INIT_WORK(&ab->reset_work, ath11k_core_reset); - INIT_WORK(&ab->update_11d_work, ath11k_update_11d); - INIT_WORK(&ab->rfkill_work, ath11k_rfkill_work); - timer_setup(&ab->rx_replenish_retry, ath11k_ce_rx_replenish_retry, 0); -@@ -1624,6 +1670,8 @@ struct ath11k_base *ath11k_core_alloc(st - - return ab; - -+err_free_wq: -+ destroy_workqueue(ab->workqueue); - err_sc_free: - kfree(ab); - return NULL; ---- a/drivers/net/wireless/ath/ath11k/core.h -+++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -41,6 +41,7 @@ extern bool ath11k_collect_dump; - /* Pending management packets threshold for dropping probe responses */ - #define ATH11K_PRB_RSP_DROP_THRESHOLD ((ATH11K_TX_MGMT_TARGET_MAX_SUPPORT_WMI * 3) / 4) - -+#define ATH11K_RESET_TIMEOUT_HZ (10 * HZ) - #define ATH11K_INVALID_HW_MAC_ID 0xFF - #define ATH11K_CONNECTION_LOSS_HZ (3 * HZ) - #define ATH11K_RX_RATE_TABLE_NUM 320 -@@ -865,6 +866,11 @@ struct ath11k_base { - struct completion driver_recovery; - struct workqueue_struct *workqueue; - struct work_struct restart_work; -+ struct workqueue_struct *workqueue_aux; -+ struct work_struct reset_work; -+ atomic_t reset_count; -+ bool is_reset; -+ struct completion reset_complete; - struct work_struct update_11d_work; - u8 new_alpha2[3]; - struct { ---- a/drivers/net/wireless/ath/ath11k/mhi.c -+++ b/drivers/net/wireless/ath/ath11k/mhi.c -@@ -290,6 +290,29 @@ static int ath11k_mhi_get_msi(struct ath - return 0; - } - -+static char *ath11k_mhi_callback_to_str(int reason) -+{ -+ switch (reason) { -+ case MHI_CB_IDLE: -+ return "MHI_CB_IDLE"; -+ case MHI_CB_PENDING_DATA: -+ return "MHI_CB_PENDING_DATA"; -+ case MHI_CB_LPM_ENTER: -+ return "MHI_CB_LPM_ENTER"; -+ case MHI_CB_LPM_EXIT: -+ return "MHI_CB_LPM_EXIT"; -+ case MHI_CB_EE_RDDM: -+ return "MHI_CB_EE_RDDM"; -+ case MHI_CB_SYS_ERROR: -+ return "MHI_CB_SYS_ERROR"; -+ case MHI_CB_FATAL_ERROR: -+ return "MHI_CB_FATAL_ERROR"; -+ default: -+ return "UNKNOWN"; -+ } -+}; -+ -+ - static int ath11k_mhi_op_runtime_get(struct mhi_controller *mhi_cntrl) - { - return 0; -@@ -297,6 +320,7 @@ static int ath11k_mhi_op_runtime_get(str - - static void ath11k_mhi_op_runtime_put(struct mhi_controller *mhi_cntrl) - { -+ - } - - static void ath11k_mhi_op_status_cb(struct mhi_controller *mhi_cntrl, -@@ -304,10 +328,16 @@ static void ath11k_mhi_op_status_cb(stru - { - struct ath11k_base *ab = dev_get_drvdata(mhi_cntrl->cntrl_dev); - -+ ath11k_info(ab, "mhi notify status reason %s\n", -+ ath11k_mhi_callback_to_str(cb)); -+ - switch (cb) { - case MHI_CB_SYS_ERROR: - ath11k_warn(ab, "firmware crashed: MHI_CB_SYS_ERROR\n"); - break; -+ case MHI_CB_EE_RDDM: -+ queue_work(ab->workqueue_aux, &ab->reset_work); -+ break; - default: - break; - } ---- a/drivers/net/wireless/ath/ath11k/pci.c -+++ b/drivers/net/wireless/ath/ath11k/pci.c -@@ -1558,6 +1558,7 @@ static void ath11k_pci_remove(struct pci - } - - set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags); -+ cancel_work_sync(&ab->reset_work); - - ath11k_core_deinit(ab); - diff --git a/feeds/ipq95xx/mac80211/patches/qca/191-ath11k-add-mgmt-and-data-ack-rssi.patch b/feeds/ipq95xx/mac80211/patches/qca/191-ath11k-add-mgmt-and-data-ack-rssi.patch index d71450dd2..89f49512b 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/191-ath11k-add-mgmt-and-data-ack-rssi.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/191-ath11k-add-mgmt-and-data-ack-rssi.patch @@ -57,7 +57,7 @@ + { info->flags |= IEEE80211_TX_STAT_ACK; + info->status.ack_signal = tx_compl_param->ack_rssi; -+ info->status.is_valid_ack_signal = true; ++ info->status.flags |= IEEE80211_TX_STATUS_ACK_SIGNAL_VALID; + } hdr = (struct ieee80211_hdr *)msdu->data; diff --git a/feeds/ipq95xx/mac80211/patches/qca/191-ath11k-update-ulmumimo-ofdma-htt-stats.patch b/feeds/ipq95xx/mac80211/patches/qca/191-ath11k-update-ulmumimo-ofdma-htt-stats.patch deleted file mode 100644 index ee17b8913..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/191-ath11k-update-ulmumimo-ofdma-htt-stats.patch +++ /dev/null @@ -1,195 +0,0 @@ ---- a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c -+++ b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c -@@ -1403,6 +1403,8 @@ htt_print_tx_selfgen_ax_stats_tlv(const - htt_stats_buf->ax_mu_mimo_brpoll_7); - len += scnprintf(buf + len, buf_len - len, "ax_basic_trigger = %u\n", - htt_stats_buf->ax_basic_trigger); -+ len += scnprintf(buf + len, buf_len - len, "ax_ulmumimo_trigger = %u\n", -+ htt_stats_buf->ax_ulmumimo_trigger); - len += scnprintf(buf + len, buf_len - len, "ax_bsr_trigger = %u\n", - htt_stats_buf->ax_bsr_trigger); - len += scnprintf(buf + len, buf_len - len, "ax_mu_bar_trigger = %u\n", -@@ -1485,6 +1487,8 @@ htt_print_tx_selfgen_ax_err_stats_tlv(co - htt_stats_buf->ax_mu_mimo_brp7_err); - len += scnprintf(buf + len, buf_len - len, "ax_basic_trigger_err = %u\n", - htt_stats_buf->ax_basic_trigger_err); -+ len += scnprintf(buf + len, buf_len - len, "ax_ulmumimo_trigger_err = %u\n", -+ htt_stats_buf->ax_ulmumimo_trigger_err); - len += scnprintf(buf + len, buf_len - len, "ax_bsr_trigger_err = %u\n", - htt_stats_buf->ax_bsr_trigger_err); - len += scnprintf(buf + len, buf_len - len, "ax_mu_bar_trigger_err = %u\n", -@@ -1519,6 +1523,16 @@ htt_print_tx_pdev_mu_mimo_sch_stats_tlv( - len += scnprintf(buf + len, buf_len - len, "mu_mimo_ppdu_posted = %u\n\n", - htt_stats_buf->mu_mimo_ppdu_posted); - -+ for (i = 0; i < HTT_TX_PDEV_STATS_NUM_AC_MUMIMO_USER_STATS; i++) -+ len += scnprintf(buf + len, buf_len - len, -+ "ac_mu_mimo_sch_posted_per_group_index %u = %u\n", -+ i, htt_stats_buf->ac_mu_mimo_sch_posted_per_grp_sz[i]); -+ -+ for (i = 0; i < HTT_TX_PDEV_STATS_NUM_AX_MUMIMO_USER_STATS; i++) -+ len += scnprintf(buf + len, buf_len - len, -+ "ax_mu_mimo_sch_posted_per_group_index %u = %u\n", -+ i, htt_stats_buf->ax_mu_mimo_sch_posted_per_grp_sz[i]); -+ - len += scnprintf(buf + len, buf_len - len, "11ac MU_MIMO SCH STATS:\n"); - - for (i = 0; i < HTT_TX_PDEV_STATS_NUM_AC_MUMIMO_USER_STATS; i++) -@@ -1535,10 +1549,34 @@ htt_print_tx_pdev_mu_mimo_sch_stats_tlv( - - len += scnprintf(buf + len, buf_len - len, "\n11ax OFDMA SCH STATS:\n"); - -- for (i = 0; i < HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS; i++) -+ for (i = 0; i < HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS; i++) { - len += scnprintf(buf + len, buf_len - len, - "ax_ofdma_sch_nusers_%u = %u\n", - i, htt_stats_buf->ax_ofdma_sch_nusers[i]); -+ len += scnprintf(buf + len, buf_len - len, -+ "ax_ul_ofdma_basic_sch_nusers_%u = %u\n", -+ i, htt_stats_buf->ax_ul_ofdma_basic_sch_nusers[i]); -+ len += scnprintf(buf + len, buf_len - len, -+ "ax_ul_ofdma_bsr_sch_nusers_%u = %u\n", -+ i, htt_stats_buf->ax_ul_ofdma_bsr_sch_nusers[i]); -+ len += scnprintf(buf + len, buf_len - len, -+ "ax_ul_ofdma_sch_bar_nusers_%u = %u\n", -+ i, htt_stats_buf->ax_ul_ofdma_bar_sch_nusers[i]); -+ len += scnprintf(buf + len, buf_len - len, -+ "ax_ul_ofdma_brp_sch_nusers_%u = %u\n", -+ i, htt_stats_buf->ax_ul_ofdma_brp_sch_nusers[i]); -+ } -+ -+ len += scnprintf(buf + len, buf_len - len, "\n11ax UL MUMIO SCH STATS:\n"); -+ -+ for (i = 0; i < HTT_TX_PDEV_STATS_NUM_UL_MUMIMO_USER_STATS; i++) { -+ len += scnprintf(buf + len, buf_len - len, -+ "ax_ul_mumimo_basic_sch_nusers_%u = %u\n", -+ i, htt_stats_buf->ax_ul_mumimo_basic_sch_nusers[i]); -+ len += scnprintf(buf + len, buf_len - len, -+ "ax_ul_mumimo_brp_sch_nusers_%u = %u\n", -+ i, htt_stats_buf->ax_ul_mumimo_brp_sch_nusers[i]); -+ } - - if (len >= buf_len) - buf[buf_len - 1] = 0; -@@ -2933,6 +2971,19 @@ static inline void htt_print_rx_pdev_rat - len += scnprintf(buf + len, buf_len - len, "txbf = %u\n", - htt_stats_buf->txbf); - -+ len += scnprintf(buf + len, buf_len - len, "\nrx_su_ndpa = %u", -+ htt_stats_buf->rx_su_ndpa); -+ PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_11ax_su_txbf_mcs, -+ "rx_11ax_su_txbf_mcs", HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS, "\n"); -+ -+ len += scnprintf(buf + len, buf_len - len, "\nrx_mu_ndpa = %u", -+ htt_stats_buf->rx_mu_ndpa); -+ PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_11ax_mu_txbf_mcs, -+ "rx_11ax_mu_txbf_mcs", HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS, "\n"); -+ -+ len += scnprintf(buf + len, buf_len - len, "\nrx_br_poll = %u", -+ htt_stats_buf->rx_br_poll); -+ - PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_legacy_cck_rate, - "rx_legacy_cck_rate", - HTT_RX_PDEV_STATS_NUM_LEGACY_CCK_STATS, "\n"); -@@ -2995,6 +3046,30 @@ static inline void htt_print_rx_pdev_rat - len += scnprintf(buf + len, buf_len - len, "\n"); - } - -+ PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_ulofdma_non_data_nusers, -+ "rx_ulofdma_non_data_nusers", HTT_RX_PDEV_MAX_OFDMA_NUM_USER, "\n"); -+ -+ PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_ulofdma_data_nusers, -+ "rx_ulofdma_data_nusers", HTT_RX_PDEV_MAX_OFDMA_NUM_USER, "\n"); -+ -+ PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_11ax_dl_ofdma_mcs, -+ "rx_11ax_dl_ofdma_mcs", HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS, "\n"); -+ -+ PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_11ax_dl_ofdma_ru, -+ "rx_11ax_dl_ofdma_ru", HTT_RX_PDEV_STATS_NUM_RU_SIZE_COUNTERS, "\n"); -+ -+ PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_ulmumimo_non_data_ppdu, -+ "rx_ulmumimo_non_data_ppdu", HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER, "\n"); -+ -+ PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_ulmumimo_data_ppdu, -+ "rx_ulmumimo_data_ppdu", HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER, "\n"); -+ -+ PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_ulmumimo_mpdu_ok, -+ "rx_ulmumimo_mpdu_ok", HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER, "\n"); -+ -+ PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_ulmumimo_mpdu_fail, -+ "rx_ulmumimo_mpdu_fail", HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER, "\n"); -+ - len += scnprintf(buf + len, buf_len - len, "per_chain_rssi_pkt_type = %#x\n", - htt_stats_buf->per_chain_rssi_pkt_type); - ---- a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h -+++ b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h -@@ -682,6 +682,7 @@ struct htt_tx_selfgen_ax_stats_tlv { - u32 ax_bsr_trigger; - u32 ax_mu_bar_trigger; - u32 ax_mu_rts_trigger; -+ u32 ax_ulmumimo_trigger; - }; - - struct htt_tx_selfgen_ac_err_stats_tlv { -@@ -712,12 +713,14 @@ struct htt_tx_selfgen_ax_err_stats_tlv { - u32 ax_bsr_trigger_err; - u32 ax_mu_bar_trigger_err; - u32 ax_mu_rts_trigger_err; -+ u32 ax_ulmumimo_trigger_err; - }; - - /* == TX MU STATS == */ - #define HTT_TX_PDEV_STATS_NUM_AC_MUMIMO_USER_STATS 4 - #define HTT_TX_PDEV_STATS_NUM_AX_MUMIMO_USER_STATS 8 - #define HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS 74 -+#define HTT_TX_PDEV_STATS_NUM_UL_MUMIMO_USER_STATS 8 - - struct htt_tx_pdev_mu_mimo_sch_stats_tlv { - /* mu-mimo sw sched cmd stats */ -@@ -734,6 +737,23 @@ struct htt_tx_pdev_mu_mimo_sch_stats_tlv - u32 ac_mu_mimo_sch_nusers[HTT_TX_PDEV_STATS_NUM_AC_MUMIMO_USER_STATS]; - u32 ax_mu_mimo_sch_nusers[HTT_TX_PDEV_STATS_NUM_AX_MUMIMO_USER_STATS]; - u32 ax_ofdma_sch_nusers[HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS]; -+ u32 ax_ul_ofdma_basic_sch_nusers[HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS]; -+ u32 ax_ul_ofdma_bsr_sch_nusers[HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS]; -+ u32 ax_ul_ofdma_bar_sch_nusers[HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS]; -+ u32 ax_ul_ofdma_brp_sch_nusers[HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS]; -+ /* UL MUMIMO */ -+ /* -+ * ax_ul_mumimo_basic_sch_nusers[i] is the number of basic triggers sent -+ * for (i+1) users -+ */ -+ u32 ax_ul_mumimo_basic_sch_nusers[HTT_TX_PDEV_STATS_NUM_UL_MUMIMO_USER_STATS]; -+ /* -+ * ax_ul_mumimo_brp_sch_nusers[i] is the number of brp triggers sent -+ * for (i+1) users -+ */ -+ u32 ax_ul_mumimo_brp_sch_nusers[HTT_TX_PDEV_STATS_NUM_UL_MUMIMO_USER_STATS]; -+ u32 ac_mu_mimo_sch_posted_per_grp_sz[HTT_TX_PDEV_STATS_NUM_AC_MUMIMO_USER_STATS]; -+ u32 ax_mu_mimo_sch_posted_per_grp_sz[HTT_TX_PDEV_STATS_NUM_AX_MUMIMO_USER_STATS]; - }; - - struct htt_tx_pdev_mu_mimo_mpdu_stats_tlv { -@@ -1375,6 +1398,21 @@ struct htt_rx_pdev_rate_stats_tlv { - u32 per_chain_rssi_pkt_type; - s8 rx_per_chain_rssi_in_dbm[HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS] - [HTT_RX_PDEV_STATS_NUM_BW_COUNTERS]; -+ -+ u32 rx_su_ndpa; -+ u32 rx_11ax_su_txbf_mcs[HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS]; -+ u32 rx_mu_ndpa; -+ u32 rx_11ax_mu_txbf_mcs[HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS]; -+ u32 rx_br_poll; -+ u32 rx_11ax_dl_ofdma_mcs[HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS]; -+ u32 rx_11ax_dl_ofdma_ru[HTT_RX_PDEV_STATS_NUM_RU_SIZE_COUNTERS]; -+ -+ u32 rx_ulmumimo_non_data_ppdu[HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER]; /* ppdu level */ -+ u32 rx_ulmumimo_data_ppdu[HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER]; /* ppdu level */ -+ u32 rx_ulmumimo_mpdu_ok[HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER]; /* mpdu level */ -+ u32 rx_ulmumimo_mpdu_fail[HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER]; /* mpdu level */ -+ u32 rx_ulofdma_non_data_nusers[HTT_RX_PDEV_MAX_OFDMA_NUM_USER]; -+ u32 rx_ulofdma_data_nusers[HTT_RX_PDEV_MAX_OFDMA_NUM_USER]; - }; - - /* == RX PDEV/SOC STATS == */ diff --git a/feeds/ipq95xx/mac80211/patches/qca/192-ath11k-fix-rx-bytes-value-not-updated-on-mesh.patch b/feeds/ipq95xx/mac80211/patches/qca/192-ath11k-fix-rx-bytes-value-not-updated-on-mesh.patch deleted file mode 100644 index aa77b7a39..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/192-ath11k-fix-rx-bytes-value-not-updated-on-mesh.patch +++ /dev/null @@ -1,218 +0,0 @@ -From 7f711a26742fffdcf10cda6089b2442f1da4db60 Mon Sep 17 00:00:00 2001 -From: Thiraviyam Mariyappan -Date: Wed, 17 Jun 2020 11:19:32 +0530 -Subject: [PATCH] mac80211: fix rx bytes values not updated on mesh link - -Previously, for mesh link the rx stats from pcpu is not -updating. Due to this, rx bytes are not updated. Fixing -that by updating the rx stats from pcpu rx stats - -Signed-off-by: Thiraviyam Mariyappan ---- - net/mac80211/rx.c | 27 ++++++++++++++++----------- - 1 file changed, 16 insertions(+), 11 deletions(-) - ---- a/net/mac80211/rx.c -+++ b/net/mac80211/rx.c -@@ -218,10 +218,16 @@ static void __ieee80211_queue_skb_to_ifa - struct sta_info *sta, - struct sk_buff *skb) - { -+ struct ieee80211_sta_rx_stats *stats; -+ - skb_queue_tail(&sdata->skb_queue, skb); - ieee80211_queue_work(&sdata->local->hw, &sdata->work); -- if (sta) -- sta->rx_stats.packets++; -+ if (sta) { -+ stats = &sta->rx_stats; -+ if (ieee80211_hw_check(&sdata->local->hw, USES_RSS)) -+ stats = this_cpu_ptr(sta->pcpu_rx_stats); -+ stats->packets++; -+ } - } - - static void ieee80211_queue_skb_to_iface(struct ieee80211_sub_if_data *sdata, -@@ -1738,11 +1744,18 @@ ieee80211_rx_h_sta_process(struct ieee80 - struct sk_buff *skb = rx->skb; - struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; -+ struct ieee80211_local *local = rx->sdata->local; -+ struct ieee80211_sta_rx_stats *stats; - int i; - - if (!sta) - return RX_CONTINUE; - -+ stats = &sta->rx_stats; -+ -+ if (ieee80211_hw_check(&local->hw, USES_RSS)) -+ stats = this_cpu_ptr(sta->pcpu_rx_stats); -+ - /* - * Update last_rx only for IBSS packets which are for the current - * BSSID and for station already AUTHORIZED to avoid keeping the -@@ -1752,49 +1765,49 @@ ieee80211_rx_h_sta_process(struct ieee80 - * something went wrong the first time. - */ - if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) { -- u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len, -+ u8 *bssid = ieee80211_get_bssid(hdr, skb->len, - NL80211_IFTYPE_ADHOC); - if (ether_addr_equal(bssid, rx->sdata->u.ibss.bssid) && - test_sta_flag(sta, WLAN_STA_AUTHORIZED)) { -- sta->rx_stats.last_rx = jiffies; -+ stats->last_rx = jiffies; - if (ieee80211_is_data(hdr->frame_control) && - !is_multicast_ether_addr(hdr->addr1)) - sta->rx_stats.last_rate = - sta_stats_encode_rate(status); - } - } else if (rx->sdata->vif.type == NL80211_IFTYPE_OCB) { -- sta->rx_stats.last_rx = jiffies; -+ stats->last_rx = jiffies; - } else if (!ieee80211_is_s1g_beacon(hdr->frame_control) && - !is_multicast_ether_addr(hdr->addr1)) { - /* - * Mesh beacons will update last_rx when if they are found to - * match the current local configuration when processed. - */ -- sta->rx_stats.last_rx = jiffies; -+ stats->last_rx = jiffies; - if (ieee80211_is_data(hdr->frame_control)) -- sta->rx_stats.last_rate = sta_stats_encode_rate(status); -+ stats->last_rate = sta_stats_encode_rate(status); - } - -- sta->rx_stats.fragments++; -+ stats->fragments++; - -- u64_stats_update_begin(&rx->sta->rx_stats.syncp); -- sta->rx_stats.bytes += rx->skb->len; -- u64_stats_update_end(&rx->sta->rx_stats.syncp); -+ u64_stats_update_begin(&stats->syncp); -+ stats->bytes += skb->len; -+ u64_stats_update_end(&stats->syncp); - - if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) { -- sta->rx_stats.last_signal = status->signal; -+ stats->last_signal = status->signal; - ewma_signal_add(&sta->rx_stats_avg.signal, -status->signal); - } - - if (status->chains) { -- sta->rx_stats.chains = status->chains; -+ stats->chains = status->chains; - for (i = 0; i < ARRAY_SIZE(status->chain_signal); i++) { - int signal = status->chain_signal[i]; - - if (!(status->chains & BIT(i))) - continue; - -- sta->rx_stats.chain_signal_last[i] = signal; -+ stats->chain_signal_last[i] = signal; - ewma_signal_add(&sta->rx_stats_avg.chain_signal[i], - -signal); - } -@@ -1856,8 +1869,8 @@ ieee80211_rx_h_sta_process(struct ieee80 - * Update counter and free packet here to avoid - * counting this as a dropped packed. - */ -- sta->rx_stats.packets++; -- dev_kfree_skb(rx->skb); -+ stats->packets++; -+ dev_kfree_skb(skb); - return RX_QUEUED; - } - -@@ -2248,6 +2261,7 @@ ieee80211_rx_h_defragment(struct ieee802 - struct ieee80211_fragment_entry *entry; - struct sk_buff *skb; - struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); -+ struct ieee80211_sta_rx_stats *stats; - - hdr = (struct ieee80211_hdr *)rx->skb->data; - fc = hdr->frame_control; -@@ -2392,8 +2406,12 @@ ieee80211_rx_h_defragment(struct ieee802 - - out: - ieee80211_led_rx(rx->local); -- if (rx->sta) -- rx->sta->rx_stats.packets++; -+ if (rx->sta) { -+ stats = &rx->sta->rx_stats; -+ if (ieee80211_hw_check(&rx->sdata->local->hw, USES_RSS)) -+ stats = this_cpu_ptr(rx->sta->pcpu_rx_stats); -+ stats->packets++; -+ } - return RX_CONTINUE; - } - -@@ -3277,6 +3295,7 @@ ieee80211_rx_h_action(struct ieee80211_r - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; - struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); - int len = rx->skb->len; -+ struct ieee80211_sta_rx_stats *stats; - - if (!ieee80211_is_action(mgmt->frame_control)) - return RX_CONTINUE; -@@ -3569,8 +3588,12 @@ ieee80211_rx_h_action(struct ieee80211_r - return RX_CONTINUE; - - handled: -- if (rx->sta) -- rx->sta->rx_stats.packets++; -+ if (rx->sta) { -+ stats = &rx->sta->rx_stats; -+ if (ieee80211_hw_check(&local->hw, USES_RSS)) -+ stats = this_cpu_ptr(rx->sta->pcpu_rx_stats); -+ stats->packets++; -+ } - dev_kfree_skb(rx->skb); - return RX_QUEUED; - -@@ -3618,6 +3641,7 @@ ieee80211_rx_h_action_post_userspace(str - struct ieee80211_sub_if_data *sdata = rx->sdata; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; - int len = rx->skb->len; -+ struct ieee80211_sta_rx_stats *stats; - - if (!ieee80211_is_action(mgmt->frame_control)) - return RX_CONTINUE; -@@ -3641,8 +3665,12 @@ ieee80211_rx_h_action_post_userspace(str - return RX_CONTINUE; - - handled: -- if (rx->sta) -- rx->sta->rx_stats.packets++; -+ if (rx->sta) { -+ stats = &rx->sta->rx_stats; -+ if (ieee80211_hw_check(&rx->sdata->local->hw, USES_RSS)) -+ stats = this_cpu_ptr(rx->sta->pcpu_rx_stats); -+ stats->packets++; -+ } - dev_kfree_skb(rx->skb); - return RX_QUEUED; - } ---- a/net/mac80211/mesh_plink.c -+++ b/net/mac80211/mesh_plink.c -@@ -416,6 +416,7 @@ static void mesh_sta_info_init(struct ie - struct ieee80211_supported_band *sband; - u32 rates, basic_rates = 0, changed = 0; - enum ieee80211_sta_rx_bandwidth bw = sta->sta.bandwidth; -+ struct ieee80211_sta_rx_stats *stats; - - sband = ieee80211_get_sband(sdata); - if (!sband) -@@ -425,7 +426,10 @@ static void mesh_sta_info_init(struct ie - &basic_rates); - - spin_lock_bh(&sta->mesh->plink_lock); -- sta->rx_stats.last_rx = jiffies; -+ stats = &sta->rx_stats; -+ if (ieee80211_hw_check(&local->hw, USES_RSS)) -+ stats = this_cpu_ptr(sta->pcpu_rx_stats); -+ stats->last_rx = jiffies; - - /* rates and capabilities don't change during peering */ - if (sta->mesh->plink_state == NL80211_PLINK_ESTAB && diff --git a/feeds/ipq95xx/mac80211/patches/qca/194-ath11k-use-dev_coredumpm-API-to-collect-rddm.patch b/feeds/ipq95xx/mac80211/patches/qca/194-ath11k-use-dev_coredumpm-API-to-collect-rddm.patch index 88549c4c5..6945015f0 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/194-ath11k-use-dev_coredumpm-API-to-collect-rddm.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/194-ath11k-use-dev_coredumpm-API-to-collect-rddm.patch @@ -29,21 +29,21 @@ Signed-off-by: Anilkumar Kolli ath11k-$(CONFIG_THERMAL) += thermal.o +ath11k-$(CONFIG_WANT_DEV_COREDUMP) += coredump.o ath11k-$(CPTCFG_ATH11K_SPECTRAL) += spectral.o + ath11k-$(CONFIG_PM) += wow.o ath11k-$(CPTCFG_ATH11K_PKTLOG) += pktlog.o - --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -9,6 +9,7 @@ - #include - #include +@@ -12,6 +12,7 @@ + #include + #include "core.h" +#include "coredump.h" #include "dp_tx.h" #include "dp_rx.h" #include "debug.h" -@@ -1112,6 +1113,9 @@ static void ath11k_core_reset(struct wor - - ab->is_reset = true; +@@ -1835,6 +1836,9 @@ static void ath11k_core_reset(struct wor + time_left = wait_for_completion_timeout(&ab->recovery_start, + ATH11K_RECOVER_START_TIMEOUT_HZ); + /* prepare coredump */ + ath11k_coredump_download_rddm(ab); @@ -451,16 +451,16 @@ Signed-off-by: Anilkumar Kolli + u32 num_seg; + struct ath11k_dump_segment *seg; + u8 bus_id; -+}; ++}; + +void ath11k_coredump_download_rddm(struct ath11k_base *ab); + +#endif --- a/drivers/net/wireless/ath/ath11k/mhi.c +++ b/drivers/net/wireless/ath/ath11k/mhi.c -@@ -374,6 +374,7 @@ int ath11k_mhi_register(struct ath11k_pc +@@ -432,6 +432,7 @@ int ath11k_mhi_register(struct ath11k_pc #if LINUX_VERSION_IS_GEQ(5,15,0) - mhi_ctrl->reg_len = ab->mem_len; + mhi_ctrl->reg_len = ab->mem_len; #endif + mhi_ctrl->rddm_size = ATH11K_PCI_FW_RDDM_SZ; @@ -474,12 +474,12 @@ Signed-off-by: Anilkumar Kolli +#define ATH11K_PCI_FW_RDDM_SZ (4 * 1024 *1024) + - enum ath11k_mhi_state { - ATH11K_MHI_INIT, - ATH11K_MHI_DEINIT, + int ath11k_mhi_start(struct ath11k_pci *ar_pci); + void ath11k_mhi_stop(struct ath11k_pci *ar_pci); + int ath11k_mhi_register(struct ath11k_pci *ar_pci); --- a/drivers/net/wireless/ath/ath11k/pci.h +++ b/drivers/net/wireless/ath/ath11k/pci.h -@@ -23,6 +23,7 @@ +@@ -24,6 +24,7 @@ /* register used for handshake mechanism to validate UMAC is awake */ #define PCIE_SOC_WAKE_PCIE_LOCAL_REG 0x3004 diff --git a/feeds/ipq95xx/mac80211/patches/qca/195-ath11k-add-coldboot-calibration-for-qcn9000.patch b/feeds/ipq95xx/mac80211/patches/qca/195-ath11k-add-coldboot-calibration-for-qcn9000.patch index 758c45eb5..5314febc7 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/195-ath11k-add-coldboot-calibration-for-qcn9000.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/195-ath11k-add-coldboot-calibration-for-qcn9000.patch @@ -17,15 +17,15 @@ Signed-off-by: Jaya Surya Mathavan --- a/drivers/net/wireless/ath/ath11k/ahb.c +++ b/drivers/net/wireless/ath/ath11k/ahb.c -@@ -11,6 +11,7 @@ +@@ -14,6 +14,7 @@ #include "ahb.h" #include "debug.h" #include "hif.h" +#include "qmi.h" #include + #include "pcic.h" - static const struct of_device_id ath11k_ahb_of_match[] = { -@@ -348,31 +349,6 @@ static void ath11k_ahb_power_down(struct +@@ -403,31 +404,6 @@ static void ath11k_ahb_power_down(struct rproc_shutdown(ab_ahb->tgt_rproc); } @@ -57,28 +57,29 @@ Signed-off-by: Jaya Surya Mathavan static void ath11k_ahb_init_qmi_ce_config(struct ath11k_base *ab) { struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg; -@@ -690,10 +666,12 @@ static int ath11k_core_get_rproc(struct +@@ -1004,11 +980,13 @@ static int ath11k_ahb_fw_resource_deinit static int ath11k_ahb_probe(struct platform_device *pdev) { struct ath11k_base *ab; + struct device *dev = &pdev->dev; const struct of_device_id *of_id; - struct resource *mem_res; - void __iomem *mem; + const struct ath11k_hif_ops *hif_ops; + const struct ath11k_pci_ops *pci_ops; + enum ath11k_hw_rev hw_rev; int ret; + u32 hw_mode_id; of_id = of_match_device(ath11k_ahb_of_match, &pdev->dev); if (!of_id) { -@@ -733,6 +711,7 @@ static int ath11k_ahb_probe(struct platf +@@ -1050,6 +1028,7 @@ static int ath11k_ahb_probe(struct platf + ab->pdev = pdev; + ab->hw_rev = hw_rev; ab->fw_mode = ATH11K_FIRMWARE_MODE_NORMAL; - ab->mem = mem; - ab->mem_len = resource_size(mem_res); + ab->enable_cold_boot_cal = ath11k_cold_boot_cal; platform_set_drvdata(pdev, ab); - ret = ath11k_core_pre_init(ab); -@@ -769,7 +748,13 @@ static int ath11k_ahb_probe(struct platf + ret = ath11k_pcic_register_pci_ops(ab, pci_ops); +@@ -1100,7 +1079,13 @@ static int ath11k_ahb_probe(struct platf goto err_ce_free; } @@ -95,7 +96,7 @@ Signed-off-by: Jaya Surya Mathavan --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -838,6 +838,7 @@ struct ath11k_base { +@@ -969,6 +969,7 @@ struct ath11k_base { struct ath11k_targ_cap target_caps; u32 ext_service_bitmap[WMI_SERVICE_EXT_BM_SIZE]; bool pdevs_macaddr_valid; @@ -105,33 +106,33 @@ Signed-off-by: Jaya Surya Mathavan struct ath11k_hw_params hw_params; --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c -@@ -13,6 +13,7 @@ - #include "hif.h" +@@ -15,6 +15,7 @@ #include "mhi.h" #include "debug.h" + #include "pcic.h" +#include "qmi.h" - #include #define ATH11K_PCI_BAR_NUM 0 -@@ -1431,6 +1432,7 @@ static int ath11k_pci_probe(struct pci_d - ab_pci->msi_config = &ath11k_msi_config[1]; - ab->bus_params.static_window_map = true; + #define ATH11K_PCI_DMA_MASK 32 +@@ -804,6 +805,7 @@ static int ath11k_pci_probe(struct pci_d + case QCN9074_DEVICE_ID: + pci_ops = &ath11k_pci_ops_qcn9074; ab->hw_rev = ATH11K_HW_QCN9074_HW10; + ab->enable_cold_boot_cal = ath11k_cold_boot_cal; break; case WCN6855_DEVICE_ID: ab->id.bdf_search = ATH11K_BDF_SEARCH_BUS_AND_BOARD; -@@ -1517,6 +1519,7 @@ unsupported_wcn6855_soc: +@@ -909,6 +911,7 @@ unsupported_wcn6855_soc: ath11k_err(ab, "failed to init core: %d\n", ret); - goto err_free_irq; + goto err_irq_affinity_cleanup; } + ath11k_qmi_fwreset_from_cold_boot(ab); return 0; - err_free_irq: + err_irq_affinity_cleanup: --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c -@@ -8,6 +8,7 @@ +@@ -9,6 +9,7 @@ #include "qmi.h" #include "core.h" #include "debug.h" @@ -139,43 +140,7 @@ Signed-off-by: Jaya Surya Mathavan #include #include #include -@@ -2355,6 +2356,25 @@ static int ath11k_qmi_alloc_target_mem_c - - for (i = 0; i < ab->qmi.mem_seg_count; i++) { - chunk = &ab->qmi.target_mem[i]; -+ -+ /* -+ * FW reloads in coldboot/FWrecovery. -+ * in such case, no need to allocate memory for FW again. -+ */ -+ if (chunk->vaddr) { -+ if (chunk->prev_type != chunk->type || -+ chunk->prev_size != chunk->size) { -+ dma_free_coherent(ab->dev, -+ ab->qmi.target_mem[i].size, -+ ab->qmi.target_mem[i].vaddr, -+ ab->qmi.target_mem[i].paddr); -+ -+ ab->qmi.target_mem[i].vaddr = NULL; -+ } else { -+ continue; -+ } -+ } -+ - chunk->vaddr = dma_alloc_coherent(ab->dev, - chunk->size, - &chunk->paddr, -@@ -2375,6 +2395,9 @@ static int ath11k_qmi_alloc_target_mem_c - chunk->type); - return -EINVAL; - } -+ -+ chunk->prev_type = chunk->type; -+ chunk->prev_size = chunk->size; - } - - return 0; -@@ -3144,6 +3167,33 @@ int ath11k_qmi_firmware_start(struct ath +@@ -3335,6 +3339,33 @@ int ath11k_qmi_firmware_start(struct ath return 0; } @@ -209,7 +174,7 @@ Signed-off-by: Jaya Surya Mathavan static int ath11k_qmi_process_coldboot_calibration(struct ath11k_base *ab) { int timeout; -@@ -3400,7 +3450,7 @@ static void ath11k_qmi_msg_mem_request_c +@@ -3600,7 +3631,7 @@ static void ath11k_qmi_msg_mem_request_c ret); return; } @@ -220,29 +185,18 @@ Signed-off-by: Jaya Surya Mathavan ath11k_warn(ab, "failed to allocate qmi target memory: %d\n", --- a/drivers/net/wireless/ath/ath11k/qmi.h +++ b/drivers/net/wireless/ath/ath11k/qmi.h -@@ -43,7 +43,7 @@ +@@ -45,7 +45,7 @@ #define QMI_WLANFW_MAX_DATA_SIZE_V01 6144 #define ATH11K_FIRMWARE_MODE_OFF 4 -#define ATH11K_COLD_BOOT_FW_RESET_DELAY (40 * HZ) +#define ATH11K_COLD_BOOT_FW_RESET_DELAY (60 * HZ) - struct ath11k_base; - -@@ -110,6 +110,8 @@ struct ath11k_qmi_event_msg { - struct target_mem_chunk { - u32 size; - u32 type; -+ u32 prev_size; -+ u32 prev_type; - dma_addr_t paddr; - u32 *vaddr; - void __iomem *iaddr; -@@ -594,6 +596,7 @@ int wlfw_send_qdss_trace_config_download + #define ATH11K_QMI_DEVICE_BAR_SIZE 0x200000 +@@ -616,4 +616,5 @@ int wlfw_send_qdss_trace_config_download + const u8 *buffer, unsigned int len); int ath11k_send_qdss_trace_mode_req(struct ath11k_base *ab, - enum wlfw_qdss_trace_mode_enum_v01 mode); + enum wlfw_qdss_trace_mode_enum_v01 mode); +int ath11k_qmi_fwreset_from_cold_boot(struct ath11k_base *ab); - - #endif diff --git a/feeds/ipq95xx/mac80211/patches/qca/196-ath11k-add-qdss-support-for-qcn9000.patch b/feeds/ipq95xx/mac80211/patches/qca/196-ath11k-add-qdss-support-for-qcn9000.patch index ba41edb60..5319788f6 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/196-ath11k-add-qdss-support-for-qcn9000.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/196-ath11k-add-qdss-support-for-qcn9000.patch @@ -42,15 +42,15 @@ Signed-off-by: Jaya Surya Mathavan --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -843,6 +843,7 @@ struct ath11k_base { +@@ -972,6 +972,7 @@ struct ath11k_base { + int bd_api; struct ath11k_hw_params hw_params; - struct ath11k_bus_params bus_params; + bool is_qdss_tracing; const struct firmware *cal_file; -@@ -1089,6 +1090,8 @@ void ath11k_core_halt(struct ath11k *ar) +@@ -1232,6 +1233,8 @@ void ath11k_core_halt(struct ath11k *ar) int ath11k_core_resume(struct ath11k_base *ab); int ath11k_core_suspend(struct ath11k_base *ab); @@ -61,7 +61,7 @@ Signed-off-by: Jaya Surya Mathavan void ath11k_core_wait_dump_collect(struct ath11k_base *ab); --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -781,6 +781,79 @@ static const struct file_operations fops +@@ -824,6 +824,79 @@ static const struct file_operations fops .llseek = default_llseek, }; @@ -115,7 +115,7 @@ Signed-off-by: Jaya Surya Mathavan + ret = count; + goto exit; + } -+ if (!ab->bus_params.fixed_bdf_addr) { ++ if (!ab->hw_params.fixed_bdf_addr) { + ret = ath11k_send_qdss_trace_mode_req(ab, + QMI_WLANFW_QDSS_TRACE_OFF_V01); + if (ret < 0) @@ -141,7 +141,7 @@ Signed-off-by: Jaya Surya Mathavan static ssize_t ath11k_write_enable_extd_tx_stats(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) -@@ -1090,6 +1163,10 @@ int ath11k_debugfs_pdev_create(struct at +@@ -1196,6 +1269,10 @@ int ath11k_debugfs_pdev_create(struct at debugfs_create_file("simulate_fw_crash", 0600, ab->debugfs_soc, ab, &fops_simulate_fw_crash); @@ -154,15 +154,15 @@ Signed-off-by: Jaya Surya Mathavan --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c -@@ -14,6 +14,7 @@ - #include - #include +@@ -17,6 +17,7 @@ + #include + #include #include +#include #define SLEEP_CLOCK_SELECT_INTERNAL_BIT 0x02 #define HOST_CSTATE_BIT 0x04 -@@ -24,10 +25,6 @@ module_param_named(cold_boot_cal, ath11k +@@ -30,10 +31,6 @@ module_param_named(cold_boot_cal, ath11k MODULE_PARM_DESC(cold_boot_cal, "Decrease the channel switch time but increase the driver load time (Default: true)"); @@ -173,7 +173,7 @@ Signed-off-by: Jaya Surya Mathavan static struct qmi_elem_info qmi_wlanfw_qdss_trace_config_download_req_msg_v01_ei[] = { { .data_type = QMI_OPT_FLAG, -@@ -457,6 +454,24 @@ static struct qmi_elem_info qmi_wlanfw_h +@@ -463,6 +460,24 @@ static struct qmi_elem_info qmi_wlanfw_h mem_cfg_mode), }, { @@ -198,7 +198,7 @@ Signed-off-by: Jaya Surya Mathavan .data_type = QMI_EOTI, .array_type = NO_ARRAY, .tlv_type = QMI_COMMON_TLV_TYPE, -@@ -721,20 +736,92 @@ static struct qmi_elem_info qmi_wlanfw_i +@@ -727,20 +742,92 @@ static struct qmi_elem_info qmi_wlanfw_i .elem_len = 1, .elem_size = sizeof(u8), .array_type = NO_ARRAY, @@ -295,7 +295,7 @@ Signed-off-by: Jaya Surya Mathavan .data_type = QMI_EOTI, .array_type = NO_ARRAY, .tlv_type = QMI_COMMON_TLV_TYPE, -@@ -1935,6 +2022,85 @@ static struct qmi_elem_info qmi_wlanfw_m +@@ -2003,6 +2090,85 @@ static struct qmi_elem_info qmi_wlanfw_m }, }; @@ -381,7 +381,7 @@ Signed-off-by: Jaya Surya Mathavan int wlfw_send_qdss_trace_config_download_req(struct ath11k_base *ab, const u8 *buffer, unsigned int file_len) { -@@ -2016,19 +2182,19 @@ int ath11k_send_qdss_trace_mode_req(stru +@@ -2084,19 +2250,19 @@ int ath11k_send_qdss_trace_mode_req(stru req.mode_valid = 1; req.mode = mode; req.option_valid = 1; @@ -405,7 +405,7 @@ Signed-off-by: Jaya Surya Mathavan goto out; } -@@ -2046,12 +2212,6 @@ out: +@@ -2114,12 +2280,6 @@ out: return ret; } @@ -418,15 +418,7 @@ Signed-off-by: Jaya Surya Mathavan static int ath11k_qmi_send_qdss_config(struct ath11k_base *ab) { struct device *dev = ab->dev; -@@ -2331,20 +2491,27 @@ static void ath11k_qmi_free_target_mem_c - int i; - - for (i = 0; i < ab->qmi.mem_seg_count; i++) { -- if ((ab->bus_params.fixed_mem_region || -- test_bit(ATH11K_FLAG_FIXED_MEM_RGN, &ab->dev_flags)) && -- ab->qmi.target_mem[i].iaddr) -- iounmap(ab->qmi.target_mem[i].iaddr); - +@@ -2420,12 +2580,23 @@ static void ath11k_qmi_free_target_mem_c if (!ab->qmi.target_mem[i].vaddr) continue; @@ -434,8 +426,8 @@ Signed-off-by: Jaya Surya Mathavan - ab->qmi.target_mem[i].size, - ab->qmi.target_mem[i].vaddr, - ab->qmi.target_mem[i].paddr); -+ if (ab->bus_params.fixed_mem_region || -+ test_bit(ATH11K_FLAG_FIXED_MEM_RGN, &ab->dev_flags)){ ++ if ((ab->hw_params.fixed_mem_region || ++ test_bit(ATH11K_FLAG_FIXED_MEM_RGN, &ab->dev_flags))) { + iounmap(ab->qmi.target_mem[i].vaddr); + } else { + dma_free_coherent(ab->dev, @@ -447,14 +439,14 @@ Signed-off-by: Jaya Surya Mathavan ab->qmi.target_mem[i].vaddr = NULL; } + -+ if (ab->bus_params.fixed_mem_region && ab->qmi.qdss_mem[0].vaddr) { ++ if (ab->hw_params.fixed_mem_region && ab->qmi.qdss_mem[0].vaddr) { + iounmap(ab->qmi.qdss_mem[0].vaddr); + ab->qmi.qdss_mem[0].vaddr = NULL; + } } static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab) -@@ -3129,21 +3296,12 @@ int ath11k_config_qdss(struct ath11k_bas +@@ -3292,21 +3463,12 @@ int ath11k_config_qdss(struct ath11k_bas if (ab->fw_mode == ATH11K_FIRMWARE_MODE_FTM) return 0; @@ -482,7 +474,7 @@ Signed-off-by: Jaya Surya Mathavan } int ath11k_qmi_firmware_start(struct ath11k_base *ab, -@@ -3337,6 +3495,23 @@ send_resp: +@@ -3500,6 +3662,23 @@ send_resp: return; } @@ -506,7 +498,7 @@ Signed-off-by: Jaya Surya Mathavan static int ath11k_qmi_driver_event_post(struct ath11k_qmi *qmi, enum ath11k_qmi_event_type type, -@@ -3395,6 +3570,173 @@ static int ath11k_qmi_event_mem_request( +@@ -3537,6 +3716,173 @@ static int ath11k_qmi_event_mem_request( return ret; } @@ -562,7 +554,7 @@ Signed-off-by: Jaya Surya Mathavan + struct device_node *dev_node = NULL; + struct resource q6_etr; + -+ if (ab->bus_params.fixed_bdf_addr) { ++ if (ab->hw_params.fixed_bdf_addr) { + dev_node = of_find_node_by_name(NULL, "q6_etr_dump"); + if (!dev_node) { + ath11k_err(ab, "No q6_etr_dump available in dts\n"); @@ -680,7 +672,7 @@ Signed-off-by: Jaya Surya Mathavan static int ath11k_qmi_event_load_bdf(struct ath11k_qmi *qmi) { struct ath11k_base *ab = qmi->ab; -@@ -3533,6 +3875,83 @@ static void ath11k_qmi_m3_dump_upload_re +@@ -3705,6 +4051,83 @@ static void ath11k_qmi_m3_dump_upload_re event_data); } @@ -764,7 +756,7 @@ Signed-off-by: Jaya Surya Mathavan static const struct qmi_msg_handler ath11k_qmi_msg_handlers[] = { { .type = QMI_INDICATION, -@@ -3571,6 +3990,23 @@ static const struct qmi_msg_handler ath1 +@@ -3743,6 +4166,23 @@ static const struct qmi_msg_handler ath1 sizeof(struct qmi_wlanfw_m3_dump_upload_req_ind_msg_v01), .fn = ath11k_qmi_m3_dump_upload_req_ind_cb, }, @@ -788,7 +780,7 @@ Signed-off-by: Jaya Surya Mathavan }; static int ath11k_qmi_ops_new_server(struct qmi_handle *qmi_hdl, -@@ -3678,6 +4114,12 @@ static void ath11k_qmi_driver_event_work +@@ -3864,6 +4304,12 @@ static void ath11k_qmi_driver_event_work case ATH11K_QMI_EVENT_M3_DUMP_UPLOAD_REQ: ath11k_qmi_event_m3_dump_upload_req(qmi, event->data); break; @@ -803,17 +795,17 @@ Signed-off-by: Jaya Surya Mathavan break; --- a/drivers/net/wireless/ath/ath11k/qmi.h +++ b/drivers/net/wireless/ath/ath11k/qmi.h -@@ -40,6 +40,9 @@ +@@ -42,6 +42,9 @@ #define QMI_WLFW_FW_READY_IND_V01 0x0038 - #define QMI_WLFW_M3_DUMP_UPLOAD_DONE_REQ_V01 0x004E - #define QMI_WLFW_M3_DUMP_UPLOAD_REQ_IND_V01 0x004D + #define QMI_WLFW_M3_DUMP_UPLOAD_DONE_REQ_V01 0x004E + #define QMI_WLFW_M3_DUMP_UPLOAD_REQ_IND_V01 0x004D +#define QMI_WLFW_QDSS_TRACE_REQ_MEM_IND_V01 0x003F -+#define QMI_Q6_QDSS_ETR_SIZE_QCN9074 0x100000 ++#define QMI_Q6_QDSS_ETR_SIZE_QCN9074 0x100000 +#define QMI_WLFW_QDSS_TRACE_SAVE_IND_V01 0x0041 #define QMI_WLANFW_MAX_DATA_SIZE_V01 6144 #define ATH11K_FIRMWARE_MODE_OFF 4 -@@ -77,6 +80,8 @@ enum ath11k_qmi_event_type { +@@ -81,6 +84,8 @@ enum ath11k_qmi_event_type { ATH11K_QMI_EVENT_POWER_UP, ATH11K_QMI_EVENT_POWER_DOWN, ATH11K_QMI_EVENT_M3_DUMP_UPLOAD_REQ, @@ -822,7 +814,7 @@ Signed-off-by: Jaya Surya Mathavan ATH11K_QMI_EVENT_MAX, }; -@@ -149,6 +154,8 @@ struct ath11k_qmi { +@@ -153,6 +158,8 @@ struct ath11k_qmi { struct ath11k_qmi_ce_cfg ce_cfg; struct target_mem_chunk target_mem[ATH11K_QMI_WLANFW_MAX_NUM_MEM_SEG_V01]; u32 mem_seg_count; @@ -831,7 +823,7 @@ Signed-off-by: Jaya Surya Mathavan u32 target_mem_mode; bool target_mem_delayed; u8 cal_done; -@@ -198,6 +205,7 @@ struct qmi_wlanfw_m3_dump_upload_done_re +@@ -202,6 +209,7 @@ struct qmi_wlanfw_m3_dump_upload_done_re #define QMI_WLANFW_QDSS_TRACE_MODE_REQ_MSG_V01_MAX_LEN 18 #define QMI_WLANFW_QDSS_TRACE_MODE_RESP_MSG_V01_MAX_LEN 7 #define QMI_WLANFW_QDSS_TRACE_MODE_RESP_V01 0x0045 @@ -839,7 +831,7 @@ Signed-off-by: Jaya Surya Mathavan enum wlfw_qdss_trace_mode_enum_v01 { WLFW_QDSS_TRACE_MODE_ENUM_MIN_VAL_V01 = INT_MIN, -@@ -227,6 +235,7 @@ struct qmi_wlanfw_qdss_trace_mode_resp_m +@@ -231,6 +239,7 @@ struct qmi_wlanfw_qdss_trace_mode_resp_m #define BDF_MEM_REGION_TYPE 0x2 #define M3_DUMP_REGION_TYPE 0x3 #define CALDB_MEM_REGION_TYPE 0x4 @@ -847,7 +839,7 @@ Signed-off-by: Jaya Surya Mathavan struct qmi_wlanfw_host_cap_req_msg_v01 { u8 num_clients_valid; -@@ -319,7 +328,9 @@ struct qmi_wlanfw_ind_register_resp_msg_ +@@ -323,7 +332,9 @@ struct qmi_wlanfw_ind_register_resp_msg_ #define QMI_WLANFW_REQUEST_MEM_IND_V01 0x0035 #define QMI_WLANFW_RESPOND_MEM_REQ_V01 0x0036 #define QMI_WLANFW_RESPOND_MEM_RESP_V01 0x0036 @@ -857,7 +849,7 @@ Signed-off-by: Jaya Surya Mathavan struct qmi_wlanfw_mem_cfg_s_v01 { u64 offset; -@@ -384,6 +395,29 @@ struct qmi_wlanfw_m3_dump_upload_req_ind +@@ -388,6 +399,29 @@ struct qmi_wlanfw_m3_dump_upload_req_ind u64 size; }; @@ -884,10 +876,10 @@ Signed-off-by: Jaya Surya Mathavan + struct qdss_trace_mem_seg mem_seg[QDSS_TRACE_SEG_LEN_MAX]; +}; + - #define QMI_WLANFW_CAP_REQ_MSG_V01_MAX_LEN 0 - #define QMI_WLANFW_CAP_RESP_MSG_V01_MAX_LEN 235 - #define QMI_WLANFW_CAP_REQ_V01 0x0024 -@@ -535,7 +569,6 @@ struct qmi_wlanfw_m3_info_resp_msg_v01 { + #define QMI_WLANFW_CAP_REQ_MSG_V01_MAX_LEN 0 + #define QMI_WLANFW_CAP_RESP_MSG_V01_MAX_LEN 235 + #define QMI_WLANFW_CAP_REQ_V01 0x0024 +@@ -553,7 +587,6 @@ struct qmi_wlanfw_m3_info_resp_msg_v01 { #define QMI_WLANFW_WLAN_CFG_REQ_V01 0x0023 #define QMI_WLANFW_WLAN_CFG_RESP_V01 0x0023 #define QMI_WLANFW_WLAN_INI_REQ_V01 0x002F @@ -895,12 +887,3 @@ Signed-off-by: Jaya Surya Mathavan #define QMI_WLANFW_MAX_NUM_CE_V01 12 #define QMI_WLANFW_MAX_NUM_SVC_V01 24 #define QMI_WLANFW_MAX_NUM_SHADOW_REG_V01 24 -@@ -597,7 +630,7 @@ int wlfw_send_qdss_trace_config_download - const u8 *buffer, unsigned int len); - - int ath11k_send_qdss_trace_mode_req(struct ath11k_base *ab, -- enum wlfw_qdss_trace_mode_enum_v01 mode); -+ enum wlfw_qdss_trace_mode_enum_v01 mode); - int ath11k_qmi_fwreset_from_cold_boot(struct ath11k_base *ab); - - diff --git a/feeds/ipq95xx/mac80211/patches/qca/196-ath11k-tpc-stats-support.patch b/feeds/ipq95xx/mac80211/patches/qca/196-ath11k-tpc-stats-support.patch index b7a9bc03b..250fde738 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/196-ath11k-tpc-stats-support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/196-ath11k-tpc-stats-support.patch @@ -44,7 +44,7 @@ Signed-off-by: Sriram R --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -676,6 +676,11 @@ struct ath11k { +@@ -780,6 +780,11 @@ struct ath11k { struct ath11k_coex_info coex; int monitor_vdev_id; @@ -58,7 +58,7 @@ Signed-off-by: Sriram R #endif --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -1810,6 +1810,588 @@ static const struct file_operations fops +@@ -2079,6 +2079,588 @@ static const struct file_operations fops .open = simple_open }; @@ -647,7 +647,7 @@ Signed-off-by: Sriram R int ath11k_debugfs_register(struct ath11k *ar) { struct ath11k_base *ab = ar->ab; -@@ -1833,6 +2415,7 @@ int ath11k_debugfs_register(struct ath11 +@@ -2102,6 +2684,7 @@ int ath11k_debugfs_register(struct ath11 ath11k_debugfs_fw_stats_init(ar); ath11k_init_pktlog(ar); @@ -655,7 +655,7 @@ Signed-off-by: Sriram R debugfs_create_file("ext_tx_stats", 0644, ar->debug.debugfs_pdev, ar, -@@ -1868,6 +2451,10 @@ int ath11k_debugfs_register(struct ath11 +@@ -2144,6 +2727,10 @@ int ath11k_debugfs_register(struct ath11 debugfs_create_file("enable_m3_dump", 0644, ar->debug.debugfs_pdev, ar, &fops_enable_m3_dump); @@ -668,8 +668,8 @@ Signed-off-by: Sriram R } --- a/drivers/net/wireless/ath/ath11k/debugfs.h +++ b/drivers/net/wireless/ath/ath11k/debugfs.h -@@ -52,6 +52,43 @@ enum ath11k_dbg_htt_ext_stats_type { - ATH11K_DBG_HTT_NUM_EXT_STATS, +@@ -82,6 +82,43 @@ struct ath11k_debug_dbr { + bool dbr_debug_enabled; }; +#define ATH11K_CCK_RATES 4 @@ -714,7 +714,7 @@ Signed-off-by: Sriram R u8 pdev_id; --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -87,6 +87,10 @@ static const struct wmi_tlv_policy wmi_t +@@ -88,6 +88,10 @@ static const struct wmi_tlv_policy wmi_t = { .min_len = 0 }, [WMI_TAG_ARRAY_UINT32] = { .min_len = 0 }, @@ -725,17 +725,17 @@ Signed-off-by: Sriram R [WMI_TAG_SERVICE_READY_EVENT] = { .min_len = sizeof(struct wmi_service_ready_event) }, [WMI_TAG_SERVICE_READY_EXT_EVENT] -@@ -143,6 +147,8 @@ static const struct wmi_tlv_policy wmi_t - .min_len = sizeof(struct wmi_obss_color_collision_event) }, - [WMI_TAG_TWT_ADD_DIALOG_COMPLETE_EVENT] - = { .min_len = sizeof(struct wmi_twt_add_dialog_event) }, +@@ -142,6 +146,8 @@ static const struct wmi_tlv_policy wmi_t + .min_len = sizeof(struct wmi_per_chain_rssi_stats) }, + [WMI_TAG_TWT_ADD_DIALOG_COMPLETE_EVENT] = { + .min_len = sizeof(struct wmi_twt_add_dialog_event) }, + [WMI_TAG_TPC_STATS_EVENT_FIXED_PARAM] + = { .min_len = sizeof(struct wmi_tpc_stats_event_fixed_param) }, - [WMI_TAG_11D_NEW_COUNTRY_EVENT] = { - .min_len = sizeof(struct wmi_11d_new_cc_ev) }, - [WMI_TAG_PER_CHAIN_RSSI_STATS] = { -@@ -8026,6 +8032,444 @@ ath11k_wmi_diag_event(struct ath11k_base - trace_ath11k_wmi_diag(ab, skb->data, skb->len); + }; + + #define PRIMAP(_hw_mode_) \ +@@ -8326,6 +8332,444 @@ static void ath11k_wmi_gtk_offload_statu + kfree(tb); } +static int ath11k_tpc_get_reg_pwr(struct ath11k_base *ab, @@ -1176,12 +1176,12 @@ Signed-off-by: Sriram R + return ret; +} + - static void ath11k_wmi_twt_add_dialog_event(struct ath11k_base *ab, struct sk_buff *skb) + static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb) { - const char *status[] = { -@@ -8191,6 +8635,9 @@ static void ath11k_wmi_tlv_op_rx(struct - case WMI_DIAG_EVENTID: - ath11k_wmi_diag_event(ab, skb); + struct wmi_cmd_hdr *cmd_hdr; +@@ -8491,6 +8935,9 @@ static void ath11k_wmi_tlv_op_rx(struct + case WMI_GTK_OFFLOAD_STATUS_EVENTID: + ath11k_wmi_gtk_offload_status_event(ab, skb); break; + case WMI_PDEV_GET_TPC_STATS_EVENTID: + ath11k_process_tpc_stats(ab, skb); @@ -1191,15 +1191,7 @@ Signed-off-by: Sriram R ath11k_dbg(ab, ATH11K_DBG_WMI, "Unknown eventid: 0x%x\n", id); --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -281,6 +281,7 @@ enum wmi_tlv_cmd_id { - WMI_PDEV_SET_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID, - WMI_PDEV_SET_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID, - WMI_PDEV_SET_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID, -+ WMI_PDEV_GET_TPC_STATS_CMDID, - WMI_VDEV_CREATE_CMDID = WMI_TLV_CMD(WMI_GRP_VDEV), - WMI_VDEV_DELETE_CMDID, - WMI_VDEV_START_REQUEST_CMDID, -@@ -630,6 +631,8 @@ enum wmi_tlv_event_id { +@@ -637,6 +637,8 @@ enum wmi_tlv_event_id { WMI_PDEV_RAP_INFO_EVENTID, WMI_CHAN_RF_CHARACTERIZATION_INFO_EVENTID, WMI_SERVICE_READY_EXT2_EVENTID, @@ -1208,7 +1200,7 @@ Signed-off-by: Sriram R WMI_VDEV_START_RESP_EVENTID = WMI_TLV_CMD(WMI_GRP_VDEV), WMI_VDEV_STOPPED_EVENTID, WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID, -@@ -1104,6 +1107,7 @@ enum wmi_tlv_tag { +@@ -1111,6 +1113,7 @@ enum wmi_tlv_tag { WMI_TAG_ARRAY_BYTE, WMI_TAG_ARRAY_STRUCT, WMI_TAG_ARRAY_FIXED_STRUCT, @@ -1216,7 +1208,7 @@ Signed-off-by: Sriram R WMI_TAG_LAST_ARRAY_ENUM = 31, WMI_TAG_SERVICE_READY_EVENT, WMI_TAG_HAL_REG_CAPABILITIES, -@@ -1855,6 +1859,13 @@ enum wmi_tlv_tag { +@@ -1862,6 +1865,12 @@ enum wmi_tlv_tag { WMI_TAG_PDEV_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD, WMI_TAG_PDEV_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMD, WMI_TAG_PDEV_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD, @@ -1226,12 +1218,11 @@ Signed-off-by: Sriram R + WMI_TAG_TPC_STATS_REG_PWR_ALLOWED, + WMI_TAG_TPC_STATS_RATES_ARRAY, + WMI_TAG_TPC_STATS_CTL_PWR_TABLE_EVENT, -+ + WMI_TAG_PDEV_SET_BIOS_SAR_TABLE_CMD = 0x3D8, + WMI_TAG_PDEV_SET_BIOS_GEO_TABLE_CMD, WMI_TAG_MAX - }; - -@@ -5494,6 +5505,183 @@ struct wmi_rfkill_state_change_ev { - u32 radio_state; +@@ -5597,6 +5606,183 @@ struct wmi_debug_log_config_cmd_fixed_pa + u32 value; } __packed; +enum wmi_tpc_pream_bw { @@ -1414,10 +1405,11 @@ Signed-off-by: Sriram R #define WMI_MAX_MEM_REQS 32 #define MAX_RADIOS 3 -@@ -5850,4 +6038,6 @@ int ath11k_wmi_wow_enable(struct ath11k - int ath11k_wmi_pdev_m3_dump_enable(struct ath11k *ar, u32 enable); - int ath11k_wmi_scan_prob_req_oui(struct ath11k *ar, - const u8 mac_addr[ETH_ALEN]); +@@ -6368,5 +6554,7 @@ int ath11k_wmi_pdev_set_bios_sar_table_p + int ath11k_wmi_pdev_set_bios_geo_table_param(struct ath11k *ar); + int ath11k_wmi_sta_keepalive(struct ath11k *ar, + const struct wmi_sta_keepalive_arg *arg); +int ath11k_wmi_pdev_get_tpc_table_cmdid(struct ath11k *ar); +void ath11k_wmi_free_tpc_stats_mem(struct ath11k *ar); + #endif diff --git a/feeds/ipq95xx/mac80211/patches/qca/199-001-mac80211-add-nss-support.patch b/feeds/ipq95xx/mac80211/patches/qca/199-001-mac80211-add-nss-support.patch index 775d8eae2..7c6124ce1 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/199-001-mac80211-add-nss-support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/199-001-mac80211-add-nss-support.patch @@ -16,7 +16,7 @@ Signed-off-by: Sriram R --- a/include/net/mac80211.h +++ b/include/net/mac80211.h -@@ -359,6 +359,20 @@ enum ieee80211_bss_change { +@@ -377,6 +377,20 @@ enum ieee80211_bss_change { /* when adding here, make sure to change ieee80211_reconfig */ }; @@ -37,23 +37,24 @@ Signed-off-by: Sriram R /* * The maximum number of IPv4 addresses listed for ARP filtering. If the number * of addresses for an interface increase beyond this value, hardware ARP -@@ -631,6 +645,7 @@ struct ieee80211_fils_discovery { - * @tx_pwr_env: transmit power envelope array of BSS. - * @tx_pwr_env_num: number of @tx_pwr_env. - * @pwr_reduction: power constraint of BSS. +@@ -651,6 +665,7 @@ struct ieee80211_fils_discovery { + * write-protected by sdata_lock and local->mtx so holding either is fine + * for read access. + * @color_change_color: the bss color that will be used after the change. + * @nss_ap_isolate: Used for notifying the NSS host about AP isolate feature */ struct ieee80211_bss_conf { const u8 *bssid; -@@ -701,6 +716,7 @@ struct ieee80211_bss_conf { - struct ieee80211_tx_pwr_env tx_pwr_env[IEEE80211_TPE_MAX_IE_COUNT]; - u8 tx_pwr_env_num; - u8 pwr_reduction; +@@ -725,6 +740,8 @@ struct ieee80211_bss_conf { + + bool color_change_active; + u8 color_change_color; ++ + bool nss_ap_isolate; }; /** -@@ -1781,6 +1797,16 @@ struct ieee80211_vif *wdev_to_ieee80211_ +@@ -1905,6 +1922,16 @@ struct ieee80211_vif *wdev_to_ieee80211_ struct wireless_dev *ieee80211_vif_to_wdev(struct ieee80211_vif *vif); /** @@ -70,26 +71,26 @@ Signed-off-by: Sriram R * enum ieee80211_key_flags - key flags * * These flags are used for communication about keys between the driver -@@ -2407,6 +2433,8 @@ struct ieee80211_txq { - * @IEEE80211_HW_SUPPORTS_CONC_MON_RX_DECAP: Hardware supports concurrent rx - * decapsulation offload and passing raw 802.11 frames for monitor iface. +@@ -2558,6 +2585,8 @@ struct ieee80211_txq { + * @IEEE80211_HW_MLO_MCAST_MULTI_LINK_TX: Hardware/driver handles transmitting + * multicast frames on all links, mac80211 should not do that. * + * @IEEE80211_HW_SUPPORTS_NSS_OFFLOAD: Hardware/driver supports NSS offload + * * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays */ enum ieee80211_hw_flags { -@@ -2462,6 +2490,7 @@ enum ieee80211_hw_flags { - IEEE80211_HW_SUPPORTS_TX_ENCAP_OFFLOAD, - IEEE80211_HW_SUPPORTS_RX_DECAP_OFFLOAD, +@@ -2615,6 +2644,7 @@ enum ieee80211_hw_flags { IEEE80211_HW_SUPPORTS_CONC_MON_RX_DECAP, + IEEE80211_HW_DETECTS_COLOR_COLLISION, + IEEE80211_HW_MLO_MCAST_MULTI_LINK_TX, + IEEE80211_HW_SUPPORTS_NSS_OFFLOAD, /* keep last, obviously */ NUM_IEEE80211_HW_FLAGS -@@ -3440,6 +3469,10 @@ enum ieee80211_reconfig_type { - * of the bss parameters has changed when a call is made. The callback - * can sleep. +@@ -3627,6 +3657,10 @@ struct ieee80211_prep_tx_info { + * non-MLO connections. + * The callback can sleep. * + * @nss_bss_info_changed: Handler for configuration requests related to NSS BSS + * parameters that may vary during BSS's lifespan, and may affect low level @@ -98,29 +99,30 @@ Signed-off-by: Sriram R * @prepare_multicast: Prepare for multicast filter configuration. * This callback is optional, and its return value is passed * to configure_filter(). This callback must be atomic. -@@ -3927,6 +3960,9 @@ struct ieee80211_ops { - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, - u32 changed); +@@ -4152,7 +4186,9 @@ struct ieee80211_ops { + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, + u64 changed); +- + void (*nss_bss_info_changed)(struct ieee80211_hw *hw, -+ struct ieee80211_vif *vif, -+ u32 changed); - - int (*start_ap)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); - void (*stop_ap)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); ++ struct ieee80211_vif *vif, ++ u64 changed); + int (*start_ap)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf); + void (*stop_ap)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c -@@ -407,6 +407,7 @@ static const char *hw_flag_names[] = { - FLAG(SUPPORTS_TX_ENCAP_OFFLOAD), - FLAG(SUPPORTS_RX_DECAP_OFFLOAD), +@@ -496,6 +496,7 @@ static const char *hw_flag_names[] = { FLAG(SUPPORTS_CONC_MON_RX_DECAP), + FLAG(DETECTS_COLOR_COLLISION), + FLAG(MLO_MCAST_MULTI_LINK_TX), + FLAG(SUPPORTS_NSS_OFFLOAD), #undef FLAG }; --- a/net/mac80211/util.c +++ b/net/mac80211/util.c -@@ -881,6 +881,22 @@ struct wireless_dev *ieee80211_vif_to_wd +@@ -889,6 +889,22 @@ struct wireless_dev *ieee80211_vif_to_wd } EXPORT_SYMBOL_GPL(ieee80211_vif_to_wdev); @@ -145,12 +147,12 @@ Signed-off-by: Sriram R * the suspend->resume cycle. Since we can't check each caller --- a/net/mac80211/main.c +++ b/net/mac80211/main.c -@@ -210,6 +210,17 @@ void ieee80211_bss_info_change_notify(st - drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed); +@@ -290,6 +290,17 @@ void ieee80211_link_info_change_notify(s + drv_link_info_changed(local, sdata, link->conf, link->link_id, changed); } +void ieee80211_nss_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, -+ u32 changed) ++ u64 changed) +{ + struct ieee80211_local *local = sdata->local; + @@ -163,9 +165,9 @@ Signed-off-by: Sriram R u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) { sdata->vif.bss_conf.use_cts_prot = false; -@@ -598,12 +609,6 @@ struct ieee80211_hw *ieee80211_alloc_hw_ +@@ -692,12 +703,6 @@ struct ieee80211_hw *ieee80211_alloc_hw_ + NL80211_FEATURE_FULL_AP_CLIENT_STATE; wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_STA); - #endif wiphy_ext_feature_set(wiphy, - NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211); - wiphy_ext_feature_set(wiphy, @@ -176,9 +178,9 @@ Signed-off-by: Sriram R NL80211_EXT_FEATURE_SCAN_FREQ_KHZ); if (!ops->hw_scan) { -@@ -921,6 +926,18 @@ int ieee80211_register_hw(struct ieee802 - (!local->ops->start_nan || !local->ops->stop_nan))) - return -EINVAL; +@@ -1006,6 +1011,18 @@ int ieee80211_register_hw(struct ieee802 + return -EINVAL; + } + /* Control port over nl80211 is disabled for nss offload as + * sending per packet tx status is not supported and only @@ -197,21 +199,19 @@ Signed-off-by: Sriram R return -EINVAL; --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c -@@ -2092,7 +2092,10 @@ sta_get_last_rx_stats(struct sta_info *s - struct ieee80211_sta_rx_stats *stats = &sta->rx_stats; - int cpu; - -- if (!sta->pcpu_rx_stats) +@@ -2229,6 +2229,9 @@ sta_get_last_rx_stats(struct sta_info *s + struct ieee80211_sta_rx_stats *stats = &sta->deflink.rx_stats; + int cpu; + + if (ieee80211_hw_check(&sta->local->hw, SUPPORTS_NSS_OFFLOAD)) + return stats; + -+ if (!sta->pcpu_rx_stats) + if (!sta->deflink.pcpu_rx_stats) return stats; - for_each_possible_cpu(cpu) { --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c -@@ -994,11 +994,23 @@ ieee80211_tx_h_stats(struct ieee80211_tx +@@ -1007,11 +1007,23 @@ ieee80211_tx_h_stats(struct ieee80211_tx { struct sk_buff *skb; int ac = -1; @@ -233,9 +233,9 @@ Signed-off-by: Sriram R + continue; + } ac = skb_get_queue_mapping(skb); - tx->sta->tx_stats.bytes[ac] += skb->len; + tx->sta->deflink.tx_stats.bytes[ac] += skb->len; } -@@ -2751,7 +2763,9 @@ static struct sk_buff *ieee80211_build_h +@@ -2830,7 +2842,9 @@ static struct sk_buff *ieee80211_build_h if (unlikely(!multicast && ((skb->sk && skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS) || @@ -246,7 +246,7 @@ Signed-off-by: Sriram R info_id = ieee80211_store_ack_skb(local, skb, &info_flags, cookie); -@@ -4210,7 +4224,8 @@ static void ieee80211_8023_xmit(struct i +@@ -4492,7 +4506,8 @@ static void ieee80211_8023_xmit(struct i } if (unlikely(skb->sk && @@ -256,22 +256,22 @@ Signed-off-by: Sriram R info->ack_frame_id = ieee80211_store_ack_skb(local, skb, &info->flags, NULL); -@@ -4218,8 +4233,10 @@ static void ieee80211_8023_xmit(struct i +@@ -4500,8 +4515,10 @@ static void ieee80211_8023_xmit(struct i dev_sw_netstats_tx_add(dev, 1, skb->len); -- sta->tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len; -- sta->tx_stats.packets[skb_get_queue_mapping(skb)]++; +- sta->deflink.tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len; +- sta->deflink.tx_stats.packets[skb_get_queue_mapping(skb)]++; + if (!ieee80211_hw_check(&local->hw, SUPPORTS_NSS_OFFLOAD)) { -+ sta->tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len; -+ sta->tx_stats.packets[skb_get_queue_mapping(skb)]++; ++ sta->deflink.tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len; ++ sta->deflink.tx_stats.packets[skb_get_queue_mapping(skb)]++; + } if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) sdata = container_of(sdata->bss, --- a/net/wireless/util.c +++ b/net/wireless/util.c -@@ -2084,6 +2084,9 @@ bool cfg80211_does_bw_fit_range(const st +@@ -2252,6 +2252,9 @@ bool cfg80211_does_bw_fit_range(const st int cfg80211_sinfo_alloc_tid_stats(struct station_info *sinfo, gfp_t gfp) { @@ -283,16 +283,16 @@ Signed-off-by: Sriram R gfp); --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -2280,7 +2280,7 @@ static int ieee80211_change_bss(struct w +@@ -2474,7 +2474,7 @@ static int ieee80211_change_bss(struct w { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_supported_band *sband; - u32 changed = 0; + u32 changed = 0, nss_changed = 0;; - if (!sdata_dereference(sdata->u.ap.beacon, sdata)) + if (!sdata_dereference(sdata->deflink.u.ap.beacon, sdata)) return -ENOENT; -@@ -2327,6 +2327,8 @@ static int ieee80211_change_bss(struct w +@@ -2521,6 +2521,8 @@ static int ieee80211_change_bss(struct w sdata->flags |= IEEE80211_SDATA_DONT_BRIDGE_PACKETS; else sdata->flags &= ~IEEE80211_SDATA_DONT_BRIDGE_PACKETS; @@ -301,9 +301,9 @@ Signed-off-by: Sriram R ieee80211_check_fast_rx_iface(sdata); } -@@ -2356,6 +2358,8 @@ static int ieee80211_change_bss(struct w +@@ -2550,6 +2552,8 @@ static int ieee80211_change_bss(struct w - ieee80211_bss_info_change_notify(sdata, changed); + ieee80211_link_info_change_notify(sdata, &sdata->deflink, changed); + ieee80211_nss_bss_info_change_notify(sdata, nss_changed); + @@ -312,7 +312,7 @@ Signed-off-by: Sriram R --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h -@@ -178,6 +178,23 @@ static inline void drv_bss_info_changed( +@@ -200,6 +200,23 @@ static inline void drv_link_info_changed trace_drv_return_void(local); } @@ -338,12 +338,12 @@ Signed-off-by: Sriram R { --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h -@@ -1626,6 +1626,8 @@ int ieee80211_hw_config(struct ieee80211 - void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); - void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, - u32 changed); +@@ -1767,6 +1767,8 @@ void ieee80211_vif_cfg_change_notify(str + void ieee80211_link_info_change_notify(struct ieee80211_sub_if_data *sdata, + struct ieee80211_link_data *link, + u64 changed); +void ieee80211_nss_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, -+ u32 changed); ++ u64 changed); void ieee80211_configure_filter(struct ieee80211_local *local); u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); @@ -386,11 +386,11 @@ Signed-off-by: Sriram R + TP_ARGS(local) +); - TRACE_EVENT(drv_bss_info_changed, + TRACE_EVENT(drv_vif_cfg_changed, TP_PROTO(struct ieee80211_local *local, --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c -@@ -863,7 +863,8 @@ static bool ieee80211_set_sdata_offload_ +@@ -1151,7 +1151,8 @@ static bool ieee80211_set_sdata_offload_ local->hw.wiphy->frag_threshold != (u32)-1) flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED; @@ -420,7 +420,7 @@ Signed-off-by: Sriram R depends on MAC80211_DEBUG_MENU --- a/local-symbols +++ b/local-symbols -@@ -73,6 +73,7 @@ MAC80211_MESH_PS_DEBUG= +@@ -65,6 +65,7 @@ MAC80211_MESH_PS_DEBUG= MAC80211_TDLS_DEBUG= MAC80211_DEBUG_COUNTERS= MAC80211_STA_HASH_MAX_SIZE= diff --git a/feeds/ipq95xx/mac80211/patches/qca/199-002-ath11k_nss-add-nss-driver-interface.patch b/feeds/ipq95xx/mac80211/patches/qca/199-002-ath11k_nss-add-nss-driver-interface.patch index a8f691ebe..41a5cb11d 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/199-002-ath11k_nss-add-nss-driver-interface.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/199-002-ath11k_nss-add-nss-driver-interface.patch @@ -19,7 +19,7 @@ Signed-off-by: Sriram R --- a/drivers/net/wireless/ath/ath11k/Kconfig +++ b/drivers/net/wireless/ath/ath11k/Kconfig -@@ -11,6 +11,16 @@ config ATH11K +@@ -12,6 +12,16 @@ config ATH11K If you choose to build a module, it'll be called ath11k. @@ -38,9 +38,9 @@ Signed-off-by: Sriram R depends on m --- a/drivers/net/wireless/ath/ath11k/Makefile +++ b/drivers/net/wireless/ath/ath11k/Makefile -@@ -27,6 +27,7 @@ ath11k-$(CONFIG_THERMAL) += thermal.o - ath11k-$(CONFIG_WANT_DEV_COREDUMP) += coredump.o +@@ -28,6 +28,7 @@ ath11k-$(CONFIG_WANT_DEV_COREDUMP) += co ath11k-$(CPTCFG_ATH11K_SPECTRAL) += spectral.o + ath11k-$(CONFIG_PM) += wow.o ath11k-$(CPTCFG_ATH11K_PKTLOG) += pktlog.o +ath11k-$(CPTCFG_ATH11K_NSS_SUPPORT) += nss.o @@ -1207,42 +1207,42 @@ Signed-off-by: Sriram R + + stainfo = container_of(sta, struct sta_info, sta); + if (peer->nss.nss_stats->last_rx && -+ time_after((unsigned long)peer->nss.nss_stats->last_rx, stainfo->rx_stats.last_rx)) -+ stainfo->rx_stats.last_rx = peer->nss.nss_stats->last_rx; ++ time_after((unsigned long)peer->nss.nss_stats->last_rx, stainfo->deflink.rx_stats.last_rx)) ++ stainfo->deflink.rx_stats.last_rx = peer->nss.nss_stats->last_rx; + + if (peer->nss.nss_stats->last_ack && -+ time_after((unsigned long)peer->nss.nss_stats->last_ack, stainfo->status_stats.last_ack)) -+ stainfo->status_stats.last_ack = peer->nss.nss_stats->last_ack; ++ time_after((unsigned long)peer->nss.nss_stats->last_ack, stainfo->deflink.status_stats.last_ack)) ++ stainfo->deflink.status_stats.last_ack = peer->nss.nss_stats->last_ack; + -+ stainfo->rx_stats.dropped += peer->nss.nss_stats->rx_dropped - ++ stainfo->deflink.rx_stats.dropped += peer->nss.nss_stats->rx_dropped - + peer->nss.nss_stats->last_rxdrop; + peer->nss.nss_stats->last_rxdrop = peer->nss.nss_stats->rx_dropped; + + sinfo->tx_packets = 0; + /* Add only ac-0 count as mgmt packets uses WME_AC_BE */ -+ sinfo->tx_packets += stainfo->tx_stats.packets[WME_AC_BE]; ++ sinfo->tx_packets += stainfo->deflink.tx_stats.packets[WME_AC_BE]; + sinfo->tx_packets += peer->nss.nss_stats->tx_packets; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS); + sinfo->tx_bytes = 0; + + /* Add only ac-0 count as mgmt packets uses WME_AC_BE */ -+ sinfo->tx_bytes += stainfo->tx_stats.bytes[WME_AC_BE]; ++ sinfo->tx_bytes += stainfo->deflink.tx_stats.bytes[WME_AC_BE]; + sinfo->tx_bytes += peer->nss.nss_stats->tx_bytes; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES); + -+ sinfo->tx_failed = stainfo->status_stats.retry_failed + ++ sinfo->tx_failed = stainfo->deflink.status_stats.retry_failed + + peer->nss.nss_stats->tx_failed; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED); + -+ sinfo->tx_retries = stainfo->status_stats.retry_count + ++ sinfo->tx_retries = stainfo->deflink.status_stats.retry_count + + peer->nss.nss_stats->tx_retries; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES); + -+ sinfo->rx_packets = stainfo->rx_stats.packets + ++ sinfo->rx_packets = stainfo->deflink.rx_stats.packets + + peer->nss.nss_stats->rx_packets; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS); + -+ sinfo->rx_bytes = stainfo->rx_stats.bytes + ++ sinfo->rx_bytes = stainfo->deflink.rx_stats.bytes + + peer->nss.nss_stats->rx_bytes; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES); + @@ -2778,38 +2778,38 @@ Signed-off-by: Sriram R { --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c -@@ -188,6 +188,20 @@ static inline u32 ath11k_pci_get_window_ - return window_start; +@@ -67,6 +67,20 @@ static u32 ath11k_pci_get_window_start(s + return ATH11K_PCI_WINDOW_START; } +static inline u32 ath11k_pci_get_window_offset(struct ath11k_base *ab, -+ u32 offset) ++ u32 offset) +{ -+ u32 window_start; ++ u32 window_start; + -+ if (ab->bus_params.static_window_map) { -+ window_start = ath11k_pci_get_window_start(ab, offset); ++ if (ab->hw_params.static_window_map) { ++ window_start = ath11k_pci_get_window_start(ab, offset); + -+ if (window_start) -+ offset = window_start + (offset & WINDOW_RANGE_MASK); -+ } -+ return offset; ++ if (window_start) ++ offset = window_start + (offset & ATH11K_PCI_WINDOW_RANGE_MASK); ++ } ++ return offset; +} + - void ath11k_pci_write32(struct ath11k_base *ab, u32 offset, u32 value) + static inline void ath11k_pci_select_window(struct ath11k_pci *ab_pci, u32 offset) { - struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); -@@ -1332,6 +1346,7 @@ static const struct ath11k_hif_ops ath11 - .map_service_to_pipe = ath11k_pci_map_service_to_pipe, + struct ath11k_base *ab = ab_pci->ab; +@@ -702,6 +716,7 @@ static const struct ath11k_hif_ops ath11 + .map_service_to_pipe = ath11k_pcic_map_service_to_pipe, .ce_irq_enable = ath11k_pci_hif_ce_irq_enable, .ce_irq_disable = ath11k_pci_hif_ce_irq_disable, + .get_window_offset = ath11k_pci_get_window_offset, - .get_ce_msi_idx = ath11k_pci_get_ce_msi_idx, + .get_ce_msi_idx = ath11k_pcic_get_ce_msi_idx, }; --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -989,6 +989,29 @@ unlock_exit: +@@ -997,6 +997,29 @@ unlock_exit: spin_unlock_bh(&ab->base_lock); } @@ -2841,7 +2841,7 @@ Signed-off-by: Sriram R enum hal_pn_type pn_type) --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -1103,6 +1103,44 @@ int ath11k_wmi_send_pdev_set_regdomain(s +@@ -1134,6 +1134,44 @@ int ath11k_wmi_send_pdev_set_regdomain(s return ret; } @@ -2888,7 +2888,7 @@ Signed-off-by: Sriram R { --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -2823,6 +2823,27 @@ struct pdev_set_regdomain_params { +@@ -2841,6 +2841,27 @@ struct pdev_set_regdomain_params { u32 pdev_id; }; @@ -2916,7 +2916,7 @@ Signed-off-by: Sriram R struct rx_reorder_queue_remove_params { u8 *peer_macaddr; u16 vdev_id; -@@ -3075,6 +3096,16 @@ struct wmi_pdev_set_regdomain_cmd { +@@ -3093,6 +3114,16 @@ struct wmi_pdev_set_regdomain_cmd { u32 dfs_domain; } __packed; @@ -2933,7 +2933,7 @@ Signed-off-by: Sriram R struct wmi_peer_set_param_cmd { u32 tlv_header; u32 vdev_id; -@@ -5833,6 +5864,8 @@ int ath11k_wmi_send_peer_create_cmd(stru +@@ -6300,6 +6331,8 @@ int ath11k_wmi_send_peer_create_cmd(stru int ath11k_wmi_vdev_set_param_cmd(struct ath11k *ar, u32 vdev_id, u32 param_id, u32 param_value); @@ -2991,7 +2991,7 @@ Signed-off-by: Sriram R int ath11k_dp_pdev_reo_setup(struct ath11k_base *ab); --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -5823,6 +5823,16 @@ static int ath11k_mac_op_start(struct ie +@@ -6121,6 +6121,16 @@ static int ath11k_mac_op_start(struct ie } } diff --git a/feeds/ipq95xx/mac80211/patches/qca/199-003-ath11k-add-nss-support.patch b/feeds/ipq95xx/mac80211/patches/qca/199-003-ath11k-add-nss-support.patch index 4b591b92b..e84040aa8 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/199-003-ath11k-add-nss-support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/199-003-ath11k-add-nss-support.patch @@ -24,7 +24,7 @@ Signed-off-by: Sriram R --- a/drivers/net/wireless/ath/ath11k/ahb.c +++ b/drivers/net/wireless/ath/ath11k/ahb.c -@@ -450,6 +450,12 @@ static int ath11k_ahb_ext_irq_config(str +@@ -510,6 +510,12 @@ static int ath11k_ahb_config_ext_irq(str int i, j; int irq; int ret; @@ -37,7 +37,7 @@ Signed-off-by: Sriram R for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; -@@ -462,20 +468,20 @@ static int ath11k_ahb_ext_irq_config(str +@@ -522,20 +528,20 @@ static int ath11k_ahb_config_ext_irq(str ath11k_ahb_ext_grp_napi_poll, NAPI_POLL_WEIGHT); for (j = 0; j < ATH11K_EXT_IRQ_NUM_MAX; j++) { @@ -62,7 +62,7 @@ Signed-off-by: Sriram R irq_grp->irqs[num_irq++] = wbm2host_rx_release; if (ab->hw_params.ring_mask->reo_status[i] & BIT(j)) -@@ -488,7 +494,7 @@ static int ath11k_ahb_ext_irq_config(str +@@ -548,7 +554,7 @@ static int ath11k_ahb_config_ext_irq(str ath11k_hw_get_mac_from_pdev_id(hw, j); } @@ -71,17 +71,17 @@ Signed-off-by: Sriram R irq_grp->irqs[num_irq++] = host2rxdma_host_buf_ring_mac1 - ath11k_hw_get_mac_from_pdev_id(hw, j); -@@ -710,6 +716,7 @@ static int ath11k_ahb_probe(struct platf - ab->hw_rev = (enum ath11k_hw_rev)of_id->data; - ab->fw_mode = ATH11K_FIRMWARE_MODE_NORMAL; +@@ -806,6 +812,7 @@ static int ath11k_ahb_setup_resources(st + } + ab->mem = mem; + ab->mem_pa = mem_res->start; ab->mem_len = resource_size(mem_res); - ab->enable_cold_boot_cal = ath11k_cold_boot_cal; - platform_set_drvdata(pdev, ab); + + return 0; --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -18,6 +18,12 @@ +@@ -19,6 +19,12 @@ #include "hif.h" #include "wow.h" @@ -94,59 +94,34 @@ Signed-off-by: Sriram R unsigned int ath11k_debug_mask; EXPORT_SYMBOL(ath11k_debug_mask); module_param_named(debug_mask, ath11k_debug_mask, uint, 0644); -@@ -911,23 +917,30 @@ static int ath11k_core_pdev_create(struc - return ret; - } - -- ret = ath11k_mac_register(ab); -+ ret = ath11k_dp_pdev_alloc(ab); - if (ret) { -- ath11k_err(ab, "failed register the radio with mac80211: %d\n", ret); -+ ath11k_err(ab, "failed to attach DP pdev: %d\n", ret); +@@ -1210,10 +1216,16 @@ static int ath11k_core_pdev_create(struc goto err_pdev_debug; } -- ret = ath11k_dp_pdev_alloc(ab); + ret = ath11k_nss_setup(ab); - if (ret) { -- ath11k_err(ab, "failed to attach DP pdev: %d\n", ret); -- goto err_mac_unregister; -+ ath11k_err(ab, "failed to setup nss driver interface%d", -+ ret); ++ if (ret) { ++ ath11k_err(ab, "failed to setup nss driver interface%d", ret); + goto err_dp_pdev_free; + } + -+ ret = ath11k_mac_register(ab); -+ if (ret) { -+ ath11k_err(ab, "failed register the radio with mac80211: %d\n", ret); + ret = ath11k_mac_register(ab); + if (ret) { + ath11k_err(ab, "failed register the radio with mac80211: %d\n", ret); +- goto err_dp_pdev_free; + goto err_nss_tear; } ret = ath11k_thermal_register(ab); - if (ret) { - ath11k_err(ab, "could not register thermal device: %d\n", - ret); -- goto err_dp_pdev_free; -+ goto err_mac_unregister; - } - - ret = ath11k_spectral_init(ab); -@@ -940,10 +953,12 @@ static int ath11k_core_pdev_create(struc - - err_thermal_unregister: +@@ -1235,6 +1247,8 @@ err_thermal_unregister: ath11k_thermal_unregister(ab); --err_dp_pdev_free: -- ath11k_dp_pdev_free(ab); err_mac_unregister: ath11k_mac_unregister(ab); +err_nss_tear: + ath11k_nss_teardown(ab); -+err_dp_pdev_free: -+ ath11k_dp_pdev_free(ab); + err_dp_pdev_free: + ath11k_dp_pdev_free(ab); err_pdev_debug: - ath11k_debugfs_pdev_destroy(ab); - -@@ -955,6 +970,10 @@ static void ath11k_core_pdev_destroy(str +@@ -1248,6 +1262,10 @@ static void ath11k_core_pdev_destroy(str ath11k_spectral_deinit(ab); ath11k_thermal_unregister(ab); ath11k_mac_unregister(ab); @@ -157,7 +132,7 @@ Signed-off-by: Sriram R ath11k_hif_irq_disable(ab); ath11k_dp_pdev_free(ab); ath11k_debugfs_pdev_destroy(ab); -@@ -1297,6 +1316,10 @@ static int ath11k_core_reconfigure_on_cr +@@ -1580,6 +1598,10 @@ static int ath11k_core_reconfigure_on_cr int ret; mutex_lock(&ab->core_lock); @@ -168,7 +143,7 @@ Signed-off-by: Sriram R ath11k_thermal_unregister(ab); ath11k_hif_irq_disable(ab); ath11k_dp_pdev_free(ab); -@@ -1564,6 +1587,10 @@ int ath11k_core_pre_init(struct ath11k_b +@@ -1879,6 +1901,10 @@ int ath11k_core_pre_init(struct ath11k_b ath11k_err(ab, "failed to get hw params: %d\n", ret); return ret; } @@ -181,17 +156,17 @@ Signed-off-by: Sriram R } --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -26,6 +26,7 @@ - #include "spectral.h" +@@ -32,6 +32,7 @@ + #include "wow.h" #include "vendor.h" #include "rx_desc.h" +#include "nss.h" #ifdef CONFIG_QCOM_QMI_HELPERS extern wait_queue_head_t ath11k_ssr_dump_wq; -@@ -289,6 +290,9 @@ struct ath11k_vif { - struct ieee80211_chanctx_conf chanctx; - struct dentry *debugfs_twt; +@@ -383,6 +384,9 @@ struct ath11k_vif { + #endif /* CPTCFG_ATH11K_DEBUGFS */ + struct ath11k_mgmt_frame_stats mgmt_stats; +#ifdef CPTCFG_ATH11K_NSS_SUPPORT + struct arvif_nss nss; @@ -199,7 +174,7 @@ Signed-off-by: Sriram R }; struct ath11k_vif_iter { -@@ -439,6 +443,9 @@ struct ath11k_sta { +@@ -536,6 +540,9 @@ struct ath11k_sta { #endif bool use_4addr_set; @@ -209,7 +184,7 @@ Signed-off-by: Sriram R u16 tcl_metadata; }; -@@ -561,6 +568,9 @@ struct ath11k { +@@ -663,6 +670,9 @@ struct ath11k { struct ieee80211_hw *hw; struct ieee80211_ops *ops; struct ath11k_pdev_wmi *wmi; @@ -218,8 +193,8 @@ Signed-off-by: Sriram R +#endif struct ath11k_pdev_dp dp; u8 mac_addr[ETH_ALEN]; - u32 ht_cap_info; -@@ -804,8 +814,10 @@ struct ath11k_base { + struct ath11k_he ar_he; +@@ -922,8 +932,10 @@ struct ath11k_base { struct ath11k_htc htc; struct ath11k_dp dp; @@ -319,7 +294,7 @@ Signed-off-by: Sriram R --- a/drivers/net/wireless/ath/ath11k/dp.h +++ b/drivers/net/wireless/ath/ath11k/dp.h -@@ -190,6 +190,7 @@ struct ath11k_pdev_dp { +@@ -193,6 +193,7 @@ struct ath11k_pdev_dp { #define DP_AVG_MSDUS_PER_MPDU 4 #define DP_RX_HASH_ENABLE 1 /* Enable hash based Rx steering */ @@ -379,7 +354,7 @@ Signed-off-by: Sriram R if (ar->ab->hw_params.rxdma1_enable) { rx_ring = &dp->rxdma_mon_buf_ring; -@@ -2031,7 +2034,7 @@ static void ath11k_dp_rx_h_csum_offload( +@@ -2032,7 +2035,7 @@ static void ath11k_dp_rx_h_csum_offload( CHECKSUM_NONE : CHECKSUM_UNNECESSARY; } @@ -388,7 +363,7 @@ Signed-off-by: Sriram R enum hal_encrypt_type enctype) { switch (enctype) { -@@ -2058,7 +2061,7 @@ static int ath11k_dp_rx_crypto_mic_len(s +@@ -2059,7 +2062,7 @@ static int ath11k_dp_rx_crypto_mic_len(s return 0; } @@ -397,7 +372,7 @@ Signed-off-by: Sriram R enum hal_encrypt_type enctype) { switch (enctype) { -@@ -2086,7 +2089,7 @@ static int ath11k_dp_rx_crypto_param_len +@@ -2087,7 +2090,7 @@ static int ath11k_dp_rx_crypto_param_len return 0; } @@ -406,7 +381,7 @@ Signed-off-by: Sriram R enum hal_encrypt_type enctype) { switch (enctype) { -@@ -3125,6 +3128,13 @@ static void ath11k_dp_rx_update_user_sta +@@ -3127,6 +3130,13 @@ static void ath11k_dp_rx_update_user_sta arsta = (struct ath11k_sta *)peer->sta->drv_priv; rx_stats = arsta->rx_stats; @@ -420,7 +395,7 @@ Signed-off-by: Sriram R if (!rx_stats) return; -@@ -3201,8 +3211,10 @@ static void ath11k_dp_rx_update_peer_mu_ +@@ -3203,8 +3213,10 @@ static void ath11k_dp_rx_update_peer_mu_ { u32 num_users, i; @@ -432,7 +407,7 @@ Signed-off-by: Sriram R num_users = ppdu_info->num_users; if (num_users > HAL_MAX_UL_MU_USERS) -@@ -5555,7 +5567,7 @@ int ath11k_dp_rx_process_mon_status(stru +@@ -5597,7 +5609,7 @@ int ath11k_dp_rx_process_mon_status(stru struct sk_buff_head skb_list; struct hal_rx_mon_ppdu_info *ppdu_info; struct ath11k_peer *peer; @@ -440,8 +415,8 @@ Signed-off-by: Sriram R + struct ath11k_sta *arsta = NULL; int num_buffs_reaped = 0; u32 rx_buf_sz; - u16 log_type = 0; -@@ -5618,6 +5630,7 @@ int ath11k_dp_rx_process_mon_status(stru + u16 log_type; +@@ -5664,6 +5676,7 @@ int ath11k_dp_rx_process_mon_status(stru if (ppdu_info->reception_type == HAL_RX_RECEPTION_TYPE_SU) { arsta = (struct ath11k_sta *)peer->sta->drv_priv; ath11k_dp_rx_update_peer_su_stats(arsta, ppdu_info); @@ -470,7 +445,7 @@ Signed-off-by: Sriram R #endif /* ATH11K_DP_RX_H */ --- a/drivers/net/wireless/ath/ath11k/hal.h +++ b/drivers/net/wireless/ath/ath11k/hal.h -@@ -416,6 +416,8 @@ enum hal_srng_ring_id { +@@ -419,6 +419,8 @@ enum hal_srng_ring_id { #define HAL_SRNG_RING_ID_MAX (HAL_SRNG_RING_ID_UMAC_ID_END + \ HAL_SRNG_NUM_LMAC_RINGS) @@ -481,7 +456,7 @@ Signed-off-by: Sriram R HAL_REO_EXCEPTION, --- a/drivers/net/wireless/ath/ath11k/hal_rx.c +++ b/drivers/net/wireless/ath/ath11k/hal_rx.c -@@ -932,6 +932,12 @@ ath11k_hal_rx_parse_mon_status_tlv(struc +@@ -934,6 +934,12 @@ ath11k_hal_rx_parse_mon_status_tlv(struc ppdu_info->num_mpdu_fcs_err = FIELD_GET(HAL_RX_PPDU_END_USER_STATS_INFO0_MPDU_CNT_FCS_ERR, info0); @@ -496,15 +471,15 @@ Signed-off-by: Sriram R ppdu_info->ht_flags = 1; --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -18,6 +18,7 @@ - #include "peer.h" - #include "debugfs_sta.h" +@@ -25,6 +25,7 @@ + #include "hif.h" + #include "wow.h" #include "vendor.h" +#include "nss.h" #define CHAN2G(_channel, _freq, _flags) { \ .band = NL80211_BAND_2GHZ, \ -@@ -1418,6 +1419,11 @@ static void ath11k_control_beaconing(str +@@ -1429,6 +1430,11 @@ static void ath11k_control_beaconing(str lockdep_assert_held(&arvif->ar->conf_mutex); if (!info->enable_beacon) { @@ -516,7 +491,7 @@ Signed-off-by: Sriram R ret = ath11k_wmi_vdev_down(ar, arvif->vdev_id); if (ret) ath11k_warn(ar->ab, "failed to down vdev_id %i: %d\n", -@@ -1451,6 +1457,12 @@ static void ath11k_control_beaconing(str +@@ -1462,6 +1468,12 @@ static void ath11k_control_beaconing(str arvif->is_up = true; @@ -529,9 +504,9 @@ Signed-off-by: Sriram R ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev %d up\n", arvif->vdev_id); } -@@ -2894,6 +2906,12 @@ static void ath11k_bss_assoc(struct ieee +@@ -2906,6 +2918,12 @@ static void ath11k_bss_assoc(struct ieee "mac vdev %d up (associated) bssid %pM aid %d\n", - arvif->vdev_id, bss_conf->bssid, bss_conf->aid); + arvif->vdev_id, bss_conf->bssid, vif->cfg.aid); + ret = ath11k_nss_vdev_up(arvif); + if(ret) { @@ -542,7 +517,7 @@ Signed-off-by: Sriram R spin_lock_bh(&ar->ab->base_lock); peer = ath11k_peer_find(ar->ab, arvif->vdev_id, arvif->bssid); -@@ -2936,6 +2954,10 @@ static void ath11k_bss_disassoc(struct i +@@ -2948,6 +2966,10 @@ static void ath11k_bss_disassoc(struct i lockdep_assert_held(&ar->conf_mutex); @@ -553,7 +528,7 @@ Signed-off-by: Sriram R ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev %i disassoc bssid %pM\n", arvif->vdev_id, arvif->bssid); -@@ -3214,6 +3236,28 @@ static int ath11k_mac_config_obss_pd(str +@@ -3228,6 +3250,28 @@ static int ath11k_mac_config_obss_pd(str return 0; } @@ -582,7 +557,7 @@ Signed-off-by: Sriram R static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, -@@ -4052,6 +4096,26 @@ static int ath11k_mac_op_set_key(struct +@@ -4069,6 +4113,26 @@ static int ath11k_mac_op_set_key(struct spin_lock_bh(&ab->base_lock); peer = ath11k_peer_find(ab, arvif->vdev_id, peer_addr); @@ -609,7 +584,7 @@ Signed-off-by: Sriram R if (peer && cmd == SET_KEY) { peer->keys[key->keyidx] = key; if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { -@@ -4090,9 +4154,8 @@ static int ath11k_mac_op_set_key(struct +@@ -4107,9 +4171,8 @@ static int ath11k_mac_op_set_key(struct break; } } @@ -620,7 +595,7 @@ Signed-off-by: Sriram R exit: mutex_unlock(&ar->conf_mutex); return ret; -@@ -5995,10 +6058,14 @@ static void ath11k_mac_op_tx(struct ieee +@@ -5963,10 +6026,14 @@ static void ath11k_mac_op_tx(struct ieee if (control->sta) arsta = (struct ath11k_sta *)control->sta->drv_priv; @@ -636,7 +611,7 @@ Signed-off-by: Sriram R } } -@@ -6020,6 +6087,8 @@ static int ath11k_mac_config_mon_status_ +@@ -5988,6 +6055,8 @@ static int ath11k_mac_config_mon_status_ if (enable) { tlv_filter = ath11k_mac_mon_status_filter_default; @@ -645,7 +620,7 @@ Signed-off-by: Sriram R if (ath11k_debugfs_rx_filter(ar)) tlv_filter.rx_filter = ath11k_debugfs_rx_filter(ar); } -@@ -6254,7 +6323,7 @@ ath11k_mac_setup_vdev_create_params(stru +@@ -6248,7 +6317,7 @@ ath11k_mac_setup_vdev_create_params(stru } } @@ -654,7 +629,7 @@ Signed-off-by: Sriram R struct ieee80211_vif *vif) { struct ath11k *ar = hw->priv; -@@ -6300,6 +6369,8 @@ static void ath11k_mac_op_update_vif_off +@@ -6294,6 +6363,8 @@ static void ath11k_mac_op_update_vif_off arvif->vdev_id, ret); vif->offload_flags &= ~IEEE80211_OFFLOAD_DECAP_ENABLED; } @@ -663,7 +638,7 @@ Signed-off-by: Sriram R } static bool ath11k_mac_vif_ap_active_any(struct ath11k_base *ab) -@@ -6521,7 +6592,34 @@ static int ath11k_mac_op_add_interface(s +@@ -6517,7 +6588,34 @@ static int ath11k_mac_op_add_interface(s list_add(&arvif->list, &ar->arvifs); spin_unlock_bh(&ar->data_lock); @@ -699,7 +674,7 @@ Signed-off-by: Sriram R nss = get_num_chains(ar->cfg_tx_chainmask) ? : 1; ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, -@@ -6651,6 +6749,7 @@ err_peer_del: +@@ -6643,6 +6741,7 @@ err_peer_del: } err_vdev_del: @@ -707,7 +682,7 @@ Signed-off-by: Sriram R ath11k_wmi_vdev_delete(ar, arvif->vdev_id); ar->num_created_vdevs--; ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id); -@@ -6705,6 +6804,8 @@ static void ath11k_mac_op_remove_interfa +@@ -6698,6 +6797,8 @@ static void ath11k_mac_op_remove_interfa reinit_completion(&ar->vdev_delete_done); @@ -716,7 +691,7 @@ Signed-off-by: Sriram R ret = ath11k_wmi_vdev_delete(ar, arvif->vdev_id); if (ret) { ath11k_warn(ab, "failed to delete WMI vdev %d: %d\n", -@@ -7138,6 +7239,10 @@ ath11k_mac_update_vif_chan(struct ath11k +@@ -7149,6 +7250,10 @@ ath11k_mac_update_vif_chan(struct ath11k arvif->vdev_id, ret); continue; } @@ -727,16 +702,16 @@ Signed-off-by: Sriram R } /* Restart the internal monitor vdev on new channel */ -@@ -8292,6 +8397,8 @@ static void ath11k_mac_op_sta_statistics - sinfo->signal = db2dbm ? signal : signal + ATH11K_DEFAULT_NOISE_FLOOR; - sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL); - } +@@ -8363,6 +8468,8 @@ static void ath11k_mac_op_sta_statistics + sinfo->signal_avg = ewma_avg_rssi_read(&arsta->avg_rssi) + + ATH11K_DEFAULT_NOISE_FLOOR; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG); + + ath11k_nss_update_sta_stats(sinfo, sta, arsta); } - #define ATH11K_WLAN_PRIO_MAX 0x63 -@@ -8389,6 +8496,7 @@ static const struct ieee80211_ops ath11k + #if IS_ENABLED(CONFIG_IPV6) +@@ -8758,6 +8865,7 @@ static const struct ieee80211_ops ath11k .update_vif_offload = ath11k_mac_op_update_vif_offload, .config = ath11k_mac_op_config, .bss_info_changed = ath11k_mac_op_bss_info_changed, @@ -744,7 +719,7 @@ Signed-off-by: Sriram R .configure_filter = ath11k_mac_op_configure_filter, .hw_scan = ath11k_mac_op_hw_scan, .cancel_hw_scan = ath11k_mac_op_cancel_hw_scan, -@@ -8801,7 +8909,8 @@ static int __ath11k_mac_register(struct +@@ -9188,7 +9296,8 @@ static int __ath11k_mac_register(struct ieee80211_hw_set(ar->hw, TX_AMPDU_SETUP_IN_HW); ieee80211_hw_set(ar->hw, SUPPORTS_REORDERING_BUFFER); ieee80211_hw_set(ar->hw, SUPPORTS_AMSDU_IN_AMPDU); @@ -754,9 +729,9 @@ Signed-off-by: Sriram R } ar->hw->wiphy->features |= NL80211_FEATURE_STATIC_SMPS; -@@ -8882,6 +8991,9 @@ static int __ath11k_mac_register(struct - ieee80211_hw_set(ar->hw, SUPPORT_FAST_XMIT); - } +@@ -9294,6 +9403,9 @@ static int __ath11k_mac_register(struct + ab->hw_params.bios_sar_capa) + ar->hw->wiphy->sar_capa = ab->hw_params.bios_sar_capa; + if (ab->nss.enabled) + ieee80211_hw_set(ar->hw, SUPPORTS_NSS_OFFLOAD); @@ -766,14 +741,14 @@ Signed-off-by: Sriram R ath11k_err(ar->ab, "ieee80211 registration failed: %d\n", ret); --- a/drivers/net/wireless/ath/ath11k/peer.c +++ b/drivers/net/wireless/ath/ath11k/peer.c -@@ -6,6 +6,7 @@ +@@ -7,6 +7,7 @@ #include "core.h" #include "peer.h" #include "debug.h" +#include "nss.h" - struct ath11k_peer *ath11k_peer_find(struct ath11k_base *ab, int vdev_id, - const u8 *addr) + static struct ath11k_peer *ath11k_peer_find_list_by_id(struct ath11k_base *ab, + int peer_id) @@ -150,6 +151,8 @@ void ath11k_peer_map_event(struct ath11k ether_addr_copy(peer->addr, mac_addr); list_add(&peer->list, &ab->peers); @@ -783,7 +758,7 @@ Signed-off-by: Sriram R } ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "htt peer map vdev %d peer %pM id %d\n", -@@ -239,6 +242,8 @@ int ath11k_peer_delete(struct ath11k *ar +@@ -333,6 +336,8 @@ static int __ath11k_peer_delete(struct a reinit_completion(&ar->peer_delete_done); @@ -791,10 +766,10 @@ Signed-off-by: Sriram R + ret = ath11k_wmi_send_peer_delete_cmd(ar, addr, vdev_id); if (ret) { - ath11k_warn(ar->ab, + ath11k_warn(ab, --- a/drivers/net/wireless/ath/ath11k/peer.h +++ b/drivers/net/wireless/ath/ath11k/peer.h -@@ -27,6 +27,7 @@ struct ath11k_peer { +@@ -28,6 +28,7 @@ struct ath11k_peer { u16 ast_hash; u8 pdev_idx; u16 hw_peer_id; @@ -804,19 +779,7 @@ Signed-off-by: Sriram R struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1]; --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c -@@ -826,6 +826,11 @@ static int ath11k_pci_ext_irq_config(str - netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi, - ath11k_pci_ext_grp_napi_poll, NAPI_POLL_WEIGHT); - -+ /* tcl, reo, rx_err, wbm release, rxdma rings are offloaded to nss. */ -+ if (ab->nss.enabled && !(ab->hw_params.ring_mask->reo_status[i] || -+ ab->hw_params.ring_mask->rx_mon_status[i])) -+ continue; -+ - if (ab->hw_params.ring_mask->tx[i] || - ab->hw_params.ring_mask->rx[i] || - ab->hw_params.ring_mask->rx_err[i] || -@@ -1122,6 +1127,7 @@ static int ath11k_pci_claim(struct ath11 +@@ -562,6 +562,7 @@ static int ath11k_pci_claim(struct ath11 goto clear_master; } @@ -826,7 +789,7 @@ Signed-off-by: Sriram R --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -968,6 +968,7 @@ static ssize_t ath11k_write_extd_rx_stat +@@ -814,6 +814,7 @@ static ssize_t ath11k_write_extd_rx_stat HTT_RX_FP_DATA_FILTER_FLASG3; } else { tlv_filter = ath11k_mac_mon_status_filter_default; @@ -834,7 +797,7 @@ Signed-off-by: Sriram R } ar->debug.rx_filter = tlv_filter.rx_filter; -@@ -1882,6 +1883,75 @@ static const struct file_operations fops +@@ -1954,6 +1955,75 @@ static const struct file_operations fops .open = simple_open }; @@ -910,7 +873,7 @@ Signed-off-by: Sriram R static int ath11k_get_tpc_ctl_mode(struct wmi_tpc_stats_event *tpc_stats, u32 pream_idx, int *mode) { -@@ -2528,6 +2598,10 @@ int ath11k_debugfs_register(struct ath11 +@@ -2607,6 +2677,10 @@ int ath11k_debugfs_register(struct ath11 debugfs_create_file("tpc_stats_type", 0600, ar->debug.debugfs_pdev, ar, &fops_tpc_stats_type); @@ -943,16 +906,6 @@ Signed-off-by: Sriram R int ath11k_dp_tx_htt_rx_full_mon_setup(struct ath11k_base *ab, int mac_id, bool config); ---- a/local-symbols -+++ b/local-symbols -@@ -126,6 +126,7 @@ ATH10K_DFS_CERTIFIED= - ATH11K= - ATH11K_AHB= - ATH11K_PCI= -+ATH11K_NSS_SUPPORT= - ATH11K_DEBUG= - ATH11K_DEBUGFS= - ATH11K_TRACING= --- a/drivers/net/wireless/ath/ath11k/nss.c +++ b/drivers/net/wireless/ath/ath11k/nss.c @@ -657,12 +657,14 @@ drop: @@ -1042,7 +995,7 @@ Signed-off-by: Sriram R } --- a/drivers/net/wireless/ath/ath11k/hw.c +++ b/drivers/net/wireless/ath/ath11k/hw.c -@@ -103,8 +103,10 @@ static void ath11k_init_wmi_config_qca63 +@@ -104,8 +104,10 @@ static void ath11k_init_wmi_config_qca63 static void ath11k_hw_ipq8074_reo_setup(struct ath11k_base *ab) { @@ -1053,7 +1006,7 @@ Signed-off-by: Sriram R /* Each hash entry uses three bits to map to a particular ring. */ u32 ring_hash_map = HAL_HASH_ROUTING_RING_SW1 << 0 | HAL_HASH_ROUTING_RING_SW2 << 3 | -@@ -115,11 +117,14 @@ static void ath11k_hw_ipq8074_reo_setup( +@@ -116,11 +118,14 @@ static void ath11k_hw_ipq8074_reo_setup( HAL_HASH_ROUTING_RING_SW3 << 18 | HAL_HASH_ROUTING_RING_SW4 << 21; @@ -1069,7 +1022,7 @@ Signed-off-by: Sriram R FIELD_PREP(HAL_REO1_GEN_ENABLE_AGING_LIST_ENABLE, 1) | FIELD_PREP(HAL_REO1_GEN_ENABLE_AGING_FLUSH_ENABLE, 1); ath11k_hif_write32(ab, reo_base + HAL_REO1_GEN_ENABLE, val); -@@ -133,6 +138,10 @@ static void ath11k_hw_ipq8074_reo_setup( +@@ -134,6 +139,10 @@ static void ath11k_hw_ipq8074_reo_setup( ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_3(ab), HAL_DEFAULT_REO_TIMEOUT_USEC); @@ -1080,7 +1033,7 @@ Signed-off-by: Sriram R ath11k_hif_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_0, FIELD_PREP(HAL_REO_DEST_RING_CTRL_HASH_RING_MAP, ring_hash_map)); -@@ -753,8 +762,10 @@ static u8 *ath11k_hw_wcn6855_rx_desc_mpd +@@ -754,8 +763,10 @@ static u8 *ath11k_hw_wcn6855_rx_desc_mpd static void ath11k_hw_wcn6855_reo_setup(struct ath11k_base *ab) { @@ -1091,7 +1044,7 @@ Signed-off-by: Sriram R /* Each hash entry uses four bits to map to a particular ring. */ u32 ring_hash_map = HAL_HASH_ROUTING_RING_SW1 << 0 | HAL_HASH_ROUTING_RING_SW2 << 4 | -@@ -765,6 +776,9 @@ static void ath11k_hw_wcn6855_reo_setup( +@@ -766,6 +777,9 @@ static void ath11k_hw_wcn6855_reo_setup( HAL_HASH_ROUTING_RING_SW3 << 24 | HAL_HASH_ROUTING_RING_SW4 << 28; @@ -1101,16 +1054,16 @@ Signed-off-by: Sriram R val = ath11k_hif_read32(ab, reo_base + HAL_REO1_GEN_ENABLE); val |= FIELD_PREP(HAL_REO1_GEN_ENABLE_AGING_LIST_ENABLE, 1) | FIELD_PREP(HAL_REO1_GEN_ENABLE_AGING_FLUSH_ENABLE, 1); -@@ -772,7 +786,7 @@ static void ath11k_hw_wcn6855_reo_setup( +@@ -773,7 +787,7 @@ static void ath11k_hw_wcn6855_reo_setup( - val = ath11k_hif_read32(ab, reo_base + HAL_REO1_MISC_CTL); + val = ath11k_hif_read32(ab, reo_base + HAL_REO1_MISC_CTL(ab)); val &= ~HAL_REO1_MISC_CTL_FRAGMENT_DST_RING; - val |= FIELD_PREP(HAL_REO1_MISC_CTL_FRAGMENT_DST_RING, HAL_SRNG_RING_ID_REO2SW1); + val |= FIELD_PREP(HAL_REO1_MISC_CTL_FRAGMENT_DST_RING, frag_dest_ring); - ath11k_hif_write32(ab, reo_base + HAL_REO1_MISC_CTL, val); + ath11k_hif_write32(ab, reo_base + HAL_REO1_MISC_CTL(ab), val); ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_0(ab), -@@ -784,6 +798,10 @@ static void ath11k_hw_wcn6855_reo_setup( +@@ -785,6 +799,10 @@ static void ath11k_hw_wcn6855_reo_setup( ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_3(ab), HAL_DEFAULT_REO_TIMEOUT_USEC); @@ -1121,3 +1074,28 @@ Signed-off-by: Sriram R ath11k_hif_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_2, ring_hash_map); ath11k_hif_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_3, +--- a/drivers/net/wireless/ath/ath11k/pcic.c ++++ b/drivers/net/wireless/ath/ath11k/pcic.c +@@ -519,6 +519,12 @@ static int ath11k_pcic_ext_irq_config(st + netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi, + ath11k_pcic_ext_grp_napi_poll, NAPI_POLL_WEIGHT); + ++ /* tcl, reo, rx_err, wbm release, rxdma rings are offloaded to nss. */ ++ if (ab->nss.enabled && ++ !(ab->hw_params.ring_mask->reo_status[i] || ++ ab->hw_params.ring_mask->rx_mon_status[i])) ++ continue; ++ + if (ab->hw_params.ring_mask->tx[i] || + ab->hw_params.ring_mask->rx[i] || + ab->hw_params.ring_mask->rx_err[i] || +--- a/local-symbols ++++ b/local-symbols +@@ -126,6 +126,7 @@ ATH10K_DFS_CERTIFIED= + ATH11K= + ATH11K_AHB= + ATH11K_PCI= ++ATH11K_NSS_SUPPORT= + ATH11K_DEBUG= + ATH11K_DEBUGFS= + ATH11K_TRACING= diff --git a/feeds/ipq95xx/mac80211/patches/qca/201-ath11k-ipq5018-support.patch b/feeds/ipq95xx/mac80211/patches/qca/201-ath11k-ipq5018-support.patch index 165d942f1..5b87cd7d4 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/201-ath11k-ipq5018-support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/201-ath11k-ipq5018-support.patch @@ -17,9 +17,9 @@ Signed-off-by: Sriram R --- a/drivers/net/wireless/ath/ath11k/ahb.c +++ b/drivers/net/wireless/ath/ath11k/ahb.c -@@ -24,6 +24,9 @@ static const struct of_device_id ath11k_ - { .compatible = "qcom,ipq6018-wifi", - .data = (void *)ATH11K_HW_IPQ6018_HW10, +@@ -31,6 +31,9 @@ static const struct of_device_id ath11k_ + { .compatible = "qcom,wcn6750-wifi", + .data = (void *)ATH11K_HW_WCN6750_HW10, }, + { .compatible = "qcom,ipq5018-wifi", + .data = (void *)ATH11K_HW_IPQ5018, @@ -27,7 +27,7 @@ Signed-off-by: Sriram R { } }; -@@ -137,12 +140,22 @@ enum ext_irq_num { +@@ -192,12 +195,22 @@ static const struct ath11k_pci_ops ath11 static inline u32 ath11k_ahb_read32(struct ath11k_base *ab, u32 offset) { @@ -52,7 +52,7 @@ Signed-off-by: Sriram R } static void ath11k_ahb_kill_tasklets(struct ath11k_base *ab) -@@ -211,30 +224,53 @@ static void ath11k_ahb_clearbit32(struct +@@ -266,30 +279,53 @@ static void ath11k_ahb_clearbit32(struct static void ath11k_ahb_ce_irq_enable(struct ath11k_base *ab, u16 ce_id) { const struct ce_attr *ce_attr; @@ -112,9 +112,17 @@ Signed-off-by: Sriram R } } -@@ -721,6 +757,21 @@ static int ath11k_ahb_probe(struct platf - ab->enable_cold_boot_cal = ath11k_cold_boot_cal; - platform_set_drvdata(pdev, ab); +@@ -1006,6 +1042,7 @@ static int ath11k_ahb_probe(struct platf + switch (hw_rev) { + case ATH11K_HW_IPQ8074: + case ATH11K_HW_IPQ6018_HW10: ++ case ATH11K_HW_IPQ5018: + hif_ops = &ath11k_ahb_hif_ops_ipq8074; + pci_ops = NULL; + break; +@@ -1052,6 +1089,21 @@ static int ath11k_ahb_probe(struct platf + if (ret) + goto err_core_free; + ab->mem_ce = ab->mem; + if (ab->hw_rev == ATH11K_HW_IPQ5018) { @@ -131,12 +139,12 @@ Signed-off-by: Sriram R + ab->ce_remap_base_addr = HAL_IPQ5018_CE_WFSS_REG_BASE; + } + - ret = ath11k_core_pre_init(ab); + ret = ath11k_ahb_fw_resources_init(ab); if (ret) goto err_core_free; -@@ -807,6 +858,10 @@ qmi_fail: - ath11k_ahb_free_irq(ab); +@@ -1142,6 +1194,10 @@ qmi_fail: ath11k_hal_srng_deinit(ab); + ath11k_ahb_fw_resource_deinit(ab); ath11k_ce_free_pipes(ab); + + if (ab->ce_remap) @@ -147,7 +155,7 @@ Signed-off-by: Sriram R --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -54,6 +54,10 @@ extern unsigned int ath11k_frame_mode; +@@ -76,6 +76,10 @@ extern unsigned int ath11k_frame_mode; #define MAX_SOCS 3 @@ -158,15 +166,15 @@ Signed-off-by: Sriram R enum ath11k_supported_bw { ATH11K_BW_20 = 0, ATH11K_BW_40 = 1, -@@ -132,6 +136,7 @@ enum ath11k_hw_rev { - ATH11K_HW_QCN9074_HW10, +@@ -155,6 +159,7 @@ enum ath11k_hw_rev { ATH11K_HW_WCN6855_HW20, ATH11K_HW_WCN6855_HW21, + ATH11K_HW_WCN6750_HW10, + ATH11K_HW_IPQ5018, }; enum ath11k_firmware_mode { -@@ -818,6 +823,7 @@ struct ath11k_base { +@@ -936,6 +941,7 @@ struct ath11k_base { struct ath11k_soc_nss nss; void __iomem *mem; @@ -174,16 +182,16 @@ Signed-off-by: Sriram R dma_addr_t mem_pa; unsigned long mem_len; -@@ -922,6 +928,8 @@ struct ath11k_base { - } id; +@@ -1066,6 +1072,8 @@ struct ath11k_base { + } pci; bool fw_recovery_support; + bool ce_remap; + u32 ce_remap_base_addr; /* must be last */ - u8 drv_priv[0] __aligned(sizeof(void *)); -@@ -1096,6 +1104,9 @@ extern const struct service_to_pipe ath1 + u8 drv_priv[] __aligned(sizeof(void *)); +@@ -1240,6 +1248,9 @@ extern const struct service_to_pipe ath1 extern const struct ce_pipe_config ath11k_target_ce_config_wlan_qcn9074[]; extern const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_qcn9074[]; @@ -195,7 +203,7 @@ Signed-off-by: Sriram R int ath11k_core_init(struct ath11k_base *ath11k); --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h -@@ -161,6 +161,7 @@ struct ath11k_hw_params { +@@ -159,6 +159,7 @@ struct ath11k_hw_params { bool rx_mac_buf_ring; bool vdev_start_delay; bool htt_peer_map_v2; @@ -203,15 +211,15 @@ Signed-off-by: Sriram R struct { u8 fft_sz; -@@ -191,6 +192,7 @@ struct ath11k_hw_params { +@@ -188,6 +189,7 @@ struct ath11k_hw_params { + bool supports_dynamic_smps_6ghz; bool alloc_cacheable_memory; - bool wakeup_mhi; u32 m3_addr; + u8 reo_dest_ring_map_shift; bool supports_rssi_stats; bool fw_wmi_diag_event; bool current_cc_support; -@@ -236,6 +238,8 @@ struct ath11k_hw_ops { +@@ -243,6 +245,8 @@ struct ath11k_hw_ops { u16 (*mpdu_info_get_peerid)(u8 *tlv_data); bool (*rx_desc_mac_addr2_valid)(struct hal_rx_desc *desc); u8* (*rx_desc_mpdu_start_addr2)(struct hal_rx_desc *desc); @@ -220,37 +228,25 @@ Signed-off-by: Sriram R }; extern const struct ath11k_hw_ops ipq8074_ops; -@@ -243,6 +247,7 @@ extern const struct ath11k_hw_ops ipq601 - extern const struct ath11k_hw_ops qca6390_ops; +@@ -251,6 +255,7 @@ extern const struct ath11k_hw_ops qca639 extern const struct ath11k_hw_ops qcn9074_ops; extern const struct ath11k_hw_ops wcn6855_ops; + extern const struct ath11k_hw_ops wcn6750_ops; +extern const struct ath11k_hw_ops ipq5018_ops; extern const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_ipq8074; extern const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_qca6390; -@@ -336,6 +341,12 @@ struct ath11k_hw_regs { - u32 hal_reo_tcl_ring_base_lsb; - u32 hal_reo_tcl_ring_hp; - -+ u32 hal_sw2reo_ring_base_lsb; -+ u32 hal_sw2reo_ring_hp; -+ -+ u32 hal_reo_cmd_ring_base_lsb; -+ u32 hal_reo_cmd_ring_hp; -+ - u32 hal_reo_status_ring_base_lsb; - u32 hal_reo_status_hp; - -@@ -360,5 +371,6 @@ extern const struct ath11k_hw_regs ipq80 - extern const struct ath11k_hw_regs qca6390_regs; +@@ -384,6 +389,7 @@ extern const struct ath11k_hw_regs qca63 extern const struct ath11k_hw_regs qcn9074_regs; extern const struct ath11k_hw_regs wcn6855_regs; + extern const struct ath11k_hw_regs wcn6750_regs; +extern const struct ath11k_hw_regs ipq5018_regs; - #endif + static inline const char *ath11k_bd_ie_type_str(enum ath11k_bd_ie_type type) + { --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -92,6 +92,7 @@ static const struct ath11k_hw_params ath +@@ -90,6 +90,7 @@ static const struct ath11k_hw_params ath .fft_hdr_len = 16, .max_fft_bins = 512, }, @@ -258,7 +254,7 @@ Signed-off-by: Sriram R .interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | -@@ -107,6 +108,7 @@ static const struct ath11k_hw_params ath +@@ -105,6 +106,7 @@ static const struct ath11k_hw_params ath .num_peers = 512, .supports_suspend = false, .hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074), @@ -266,7 +262,7 @@ Signed-off-by: Sriram R .supports_regdb = false, .fix_l1ss = true, .credit_flow = false, -@@ -150,6 +152,7 @@ static const struct ath11k_hw_params ath +@@ -154,6 +156,7 @@ static const struct ath11k_hw_params ath .rx_mac_buf_ring = false, .vdev_start_delay = false, .htt_peer_map_v2 = true, @@ -274,7 +270,7 @@ Signed-off-by: Sriram R .spectral = { .fft_sz = 4, -@@ -173,6 +176,7 @@ static const struct ath11k_hw_params ath +@@ -177,6 +180,7 @@ static const struct ath11k_hw_params ath .num_peers = 512, .supports_suspend = false, .hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074), @@ -282,7 +278,7 @@ Signed-off-by: Sriram R .supports_regdb = false, .fix_l1ss = true, .credit_flow = false, -@@ -215,6 +219,7 @@ static const struct ath11k_hw_params ath +@@ -225,6 +229,7 @@ static const struct ath11k_hw_params ath .rx_mac_buf_ring = true, .vdev_start_delay = true, .htt_peer_map_v2 = false, @@ -290,15 +286,15 @@ Signed-off-by: Sriram R .spectral = { .fft_sz = 0, -@@ -237,6 +242,7 @@ static const struct ath11k_hw_params ath +@@ -247,6 +252,7 @@ static const struct ath11k_hw_params ath .num_peers = 512, .supports_suspend = true, .hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074), + .reo_dest_ring_map_shift = HAL_REO_DEST_RING_CTRL_HASH_RING_SHIFT, - .supports_regdb = true, + .supports_regdb = false, .fix_l1ss = true, .credit_flow = true, -@@ -278,6 +284,7 @@ static const struct ath11k_hw_params ath +@@ -294,6 +300,7 @@ static const struct ath11k_hw_params ath .rx_mac_buf_ring = false, .vdev_start_delay = false, .htt_peer_map_v2 = true, @@ -306,7 +302,7 @@ Signed-off-by: Sriram R .spectral = { .fft_sz = 2, -@@ -301,6 +308,7 @@ static const struct ath11k_hw_params ath +@@ -317,6 +324,7 @@ static const struct ath11k_hw_params ath .num_peers = 128, .supports_suspend = false, .hal_desc_sz = sizeof(struct hal_rx_desc_qcn9074), @@ -314,7 +310,7 @@ Signed-off-by: Sriram R .supports_regdb = false, .fix_l1ss = true, .credit_flow = false, -@@ -343,6 +351,7 @@ static const struct ath11k_hw_params ath +@@ -365,6 +373,7 @@ static const struct ath11k_hw_params ath .rx_mac_buf_ring = true, .vdev_start_delay = true, .htt_peer_map_v2 = false, @@ -322,7 +318,7 @@ Signed-off-by: Sriram R .spectral = { .fft_sz = 0, -@@ -365,6 +374,7 @@ static const struct ath11k_hw_params ath +@@ -387,6 +396,7 @@ static const struct ath11k_hw_params ath .num_peers = 512, .supports_suspend = true, .hal_desc_sz = sizeof(struct hal_rx_desc_wcn6855), @@ -330,7 +326,7 @@ Signed-off-by: Sriram R .supports_regdb = true, .fix_l1ss = false, .credit_flow = true, -@@ -407,6 +417,7 @@ static const struct ath11k_hw_params ath +@@ -435,6 +445,7 @@ static const struct ath11k_hw_params ath .rx_mac_buf_ring = true, .vdev_start_delay = true, .htt_peer_map_v2 = false, @@ -338,7 +334,7 @@ Signed-off-by: Sriram R .spectral = { .fft_sz = 0, -@@ -428,6 +439,7 @@ static const struct ath11k_hw_params ath +@@ -456,6 +467,7 @@ static const struct ath11k_hw_params ath .num_peers = 512, .supports_suspend = true, .hal_desc_sz = sizeof(struct hal_rx_desc_wcn6855), @@ -346,9 +342,9 @@ Signed-off-by: Sriram R .supports_regdb = true, .fix_l1ss = false, .credit_flow = true, -@@ -440,6 +452,61 @@ static const struct ath11k_hw_params ath - .fw_wmi_diag_event = true, - .current_cc_support = true, +@@ -546,6 +558,70 @@ static const struct ath11k_hw_params ath + .fixed_fw_mem = true, + .support_off_channel_tx = false, }, + { + .hw_rev = ATH11K_HW_IPQ5018, @@ -387,7 +383,7 @@ Signed-off-by: Sriram R + .supports_suspend = false, + .hal_params = &ath11k_hw_hal_params_ipq8074, + .host_ce_config = ath11k_host_ce_config_qcn9074, -+ .reo_dest_ring_map_shift = HAL_REO_DEST_RING_CTRL_HASH_RING_SHIFT, ++ .reo_dest_ring_map_shift = HAL_IPQ5018_REO_DEST_RING_CTRL_HASH_RING_SHIFT, + .ce_count = 6, + .target_ce_config = ath11k_target_ce_config_wlan_ipq5018, + .target_ce_count = 9, @@ -403,14 +399,23 @@ Signed-off-by: Sriram R + .rx_mac_buf_ring = false, + .vdev_start_delay = false, + .htt_peer_map_v2 = true, -+ .reo_dest_ring_map_shift = HAL_IPQ5018_REO_DEST_RING_CTRL_HASH_RING_SHIFT, -+ } ++ .supports_sta_ps = false, ++ .dbr_debug_support = true, ++ .bios_sar_capa = NULL, ++ .m3_fw_support = false, ++ .fixed_bdf_addr = true, ++ .fixed_mem_region = true, ++ .static_window_map = false, ++ .hybrid_bus_type = false, ++ .fixed_fw_mem = false, ++ .support_off_channel_tx = false, ++ }, }; - int ath11k_core_suspend(struct ath11k_base *ab) + static inline struct ath11k_pdev *ath11k_core_get_single_pdev(struct ath11k_base *ab) --- a/drivers/net/wireless/ath/ath11k/hw.c +++ b/drivers/net/wireless/ath/ath11k/hw.c -@@ -12,6 +12,7 @@ +@@ -13,6 +13,7 @@ #include "hif.h" #include "hal.h" #include "hw.h" @@ -418,7 +423,7 @@ Signed-off-by: Sriram R /* Map from pdev index to hw mac index */ static u8 ath11k_hw_ipq8074_mac_from_pdev_id(int pdev_idx) -@@ -103,9 +104,7 @@ static void ath11k_init_wmi_config_qca63 +@@ -104,9 +105,7 @@ static void ath11k_init_wmi_config_qca63 static void ath11k_hw_ipq8074_reo_setup(struct ath11k_base *ab) { @@ -428,7 +433,7 @@ Signed-off-by: Sriram R /* Each hash entry uses three bits to map to a particular ring. */ u32 ring_hash_map = HAL_HASH_ROUTING_RING_SW1 << 0 | -@@ -116,18 +115,9 @@ static void ath11k_hw_ipq8074_reo_setup( +@@ -117,18 +116,9 @@ static void ath11k_hw_ipq8074_reo_setup( HAL_HASH_ROUTING_RING_SW2 << 15 | HAL_HASH_ROUTING_RING_SW3 << 18 | HAL_HASH_ROUTING_RING_SW4 << 21; @@ -449,7 +454,7 @@ Signed-off-by: Sriram R ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_0(ab), HAL_DEFAULT_REO_TIMEOUT_USEC); -@@ -142,18 +132,18 @@ static void ath11k_hw_ipq8074_reo_setup( +@@ -143,18 +133,18 @@ static void ath11k_hw_ipq8074_reo_setup( if (ab->nss.enabled) return; @@ -476,7 +481,7 @@ Signed-off-by: Sriram R } static void ath11k_init_wmi_config_ipq8074(struct ath11k_base *ab, -@@ -407,6 +397,50 @@ struct rx_attention *ath11k_hw_ipq8074_r +@@ -408,6 +398,50 @@ struct rx_attention *ath11k_hw_ipq8074_r return &desc->u.ipq8074.attention; } @@ -517,17 +522,17 @@ Signed-off-by: Sriram R + FIELD_PREP(HAL_REO1_GEN_ENABLE_AGING_FLUSH_ENABLE, 1); + ath11k_hif_write32(ab, reo_base + HAL_REO1_GEN_ENABLE, val); + -+ val = ath11k_hif_read32(ab, reo_base + HAL_REO1_MISC_CTL); ++ val = ath11k_hif_read32(ab, reo_base + HAL_REO1_MISC_CTL(ab)); + val &= ~HAL_REO1_MISC_CTL_FRAGMENT_DST_RING; + val |= FIELD_PREP(HAL_REO1_MISC_CTL_FRAGMENT_DST_RING, frag_dst_ring); -+ ath11k_hif_write32(ab, reo_base + HAL_REO1_MISC_CTL, val); ++ ath11k_hif_write32(ab, reo_base + HAL_REO1_MISC_CTL(ab), val); + +} + static u8 *ath11k_hw_ipq8074_rx_desc_get_msdu_payload(struct hal_rx_desc *desc) { return &desc->u.ipq8074.msdu_payload[0]; -@@ -762,9 +796,7 @@ static u8 *ath11k_hw_wcn6855_rx_desc_mpd +@@ -763,9 +797,7 @@ static u8 *ath11k_hw_wcn6855_rx_desc_mpd static void ath11k_hw_wcn6855_reo_setup(struct ath11k_base *ab) { @@ -537,14 +542,12 @@ Signed-off-by: Sriram R /* Each hash entry uses four bits to map to a particular ring. */ u32 ring_hash_map = HAL_HASH_ROUTING_RING_SW1 << 0 | -@@ -775,19 +807,46 @@ static void ath11k_hw_wcn6855_reo_setup( - HAL_HASH_ROUTING_RING_SW2 << 20 | +@@ -777,18 +809,44 @@ static void ath11k_hw_wcn6855_reo_setup( HAL_HASH_ROUTING_RING_SW3 << 24 | HAL_HASH_ROUTING_RING_SW4 << 28; -+ u8 reo_dest_hash_shift = ab->hw_params.reo_dest_ring_map_shift; -+ -+ ab->hw_params.hw_ops->set_rx_fragmentation_dst_ring(ab); ++ u8 reo_dest_hash_shift = ab->hw_params.reo_dest_ring_map_shift; ++ ab->hw_params.hw_ops->set_rx_fragmentation_dst_ring(ab); + + ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_0(ab), + HAL_DEFAULT_REO_TIMEOUT_USEC); @@ -570,10 +573,10 @@ Signed-off-by: Sriram R + ring_hash_map << reo_dest_hash_shift); +} -- val = ath11k_hif_read32(ab, reo_base + HAL_REO1_MISC_CTL); +- val = ath11k_hif_read32(ab, reo_base + HAL_REO1_MISC_CTL(ab)); - val &= ~HAL_REO1_MISC_CTL_FRAGMENT_DST_RING; - val |= FIELD_PREP(HAL_REO1_MISC_CTL_FRAGMENT_DST_RING, frag_dest_ring); -- ath11k_hif_write32(ab, reo_base + HAL_REO1_MISC_CTL, val); +- ath11k_hif_write32(ab, reo_base + HAL_REO1_MISC_CTL(ab), val); +static void ath11k_hw_ipq5018_reo_setup(struct ath11k_base *ab) +{ + u32 reo_base = HAL_SEQ_WCSS_UMAC_REO_REG; @@ -593,7 +596,7 @@ Signed-off-by: Sriram R ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_0(ab), HAL_DEFAULT_REO_TIMEOUT_USEC); -@@ -802,10 +861,14 @@ static void ath11k_hw_wcn6855_reo_setup( +@@ -803,10 +861,14 @@ static void ath11k_hw_wcn6855_reo_setup( if (ab->nss.enabled) return; @@ -610,8 +613,8 @@ Signed-off-by: Sriram R } static u16 ath11k_hw_ipq8074_mpdu_info_get_peerid(u8 *tlv_data) -@@ -831,6 +894,70 @@ static u16 ath11k_hw_wcn6855_mpdu_info_g - return peer_id; +@@ -838,6 +900,70 @@ static bool ath11k_hw_wcn6855_rx_desc_ge + __le32_to_cpu(desc->u.wcn6855.msdu_start.info2)); } +static void ath11k_hw_ipq5018_set_rx_fragmentation_dst_ring(struct ath11k_base *ab) @@ -681,7 +684,7 @@ Signed-off-by: Sriram R const struct ath11k_hw_ops ipq8074_ops = { .get_hw_mac_from_pdev_id = ath11k_hw_ipq8074_mac_from_pdev_id, .wmi_init_config = ath11k_init_wmi_config_ipq8074, -@@ -868,6 +995,8 @@ const struct ath11k_hw_ops ipq8074_ops = +@@ -875,6 +1001,8 @@ const struct ath11k_hw_ops ipq8074_ops = .mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid, .rx_desc_mac_addr2_valid = ath11k_hw_ipq8074_rx_desc_mac_addr2_valid, .rx_desc_mpdu_start_addr2 = ath11k_hw_ipq8074_rx_desc_mpdu_start_addr2, @@ -690,7 +693,7 @@ Signed-off-by: Sriram R }; const struct ath11k_hw_ops ipq6018_ops = { -@@ -907,6 +1036,8 @@ const struct ath11k_hw_ops ipq6018_ops = +@@ -914,6 +1042,8 @@ const struct ath11k_hw_ops ipq6018_ops = .mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid, .rx_desc_mac_addr2_valid = ath11k_hw_ipq8074_rx_desc_mac_addr2_valid, .rx_desc_mpdu_start_addr2 = ath11k_hw_ipq8074_rx_desc_mpdu_start_addr2, @@ -699,7 +702,7 @@ Signed-off-by: Sriram R }; const struct ath11k_hw_ops qca6390_ops = { -@@ -946,6 +1077,8 @@ const struct ath11k_hw_ops qca6390_ops = +@@ -953,6 +1083,8 @@ const struct ath11k_hw_ops qca6390_ops = .mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid, .rx_desc_mac_addr2_valid = ath11k_hw_ipq8074_rx_desc_mac_addr2_valid, .rx_desc_mpdu_start_addr2 = ath11k_hw_ipq8074_rx_desc_mpdu_start_addr2, @@ -708,7 +711,7 @@ Signed-off-by: Sriram R }; const struct ath11k_hw_ops qcn9074_ops = { -@@ -985,6 +1118,8 @@ const struct ath11k_hw_ops qcn9074_ops = +@@ -992,6 +1124,8 @@ const struct ath11k_hw_ops qcn9074_ops = .mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid, .rx_desc_mac_addr2_valid = ath11k_hw_ipq9074_rx_desc_mac_addr2_valid, .rx_desc_mpdu_start_addr2 = ath11k_hw_ipq9074_rx_desc_mpdu_start_addr2, @@ -717,7 +720,7 @@ Signed-off-by: Sriram R }; const struct ath11k_hw_ops wcn6855_ops = { -@@ -1023,8 +1158,51 @@ const struct ath11k_hw_ops wcn6855_ops = +@@ -1031,6 +1165,8 @@ const struct ath11k_hw_ops wcn6855_ops = .mpdu_info_get_peerid = ath11k_hw_wcn6855_mpdu_info_get_peerid, .rx_desc_mac_addr2_valid = ath11k_hw_wcn6855_rx_desc_mac_addr2_valid, .rx_desc_mpdu_start_addr2 = ath11k_hw_wcn6855_rx_desc_mpdu_start_addr2, @@ -725,6 +728,11 @@ Signed-off-by: Sriram R + .get_reo_dest_remap_config = ath11k_get_reo_dest_remap_config_default, }; + const struct ath11k_hw_ops wcn6750_ops = { +@@ -1072,6 +1208,47 @@ const struct ath11k_hw_ops wcn6750_ops = + .rx_desc_mpdu_start_addr2 = ath11k_hw_ipq9074_rx_desc_mpdu_start_addr2, + }; + +/* IPQ5018 hw ops is similar to QCN9074 except for the dest ring remap */ +const struct ath11k_hw_ops ipq5018_ops = { + .get_hw_mac_from_pdev_id = ath11k_hw_ipq6018_mac_from_pdev_id, @@ -764,12 +772,12 @@ Signed-off-by: Sriram R + .reo_setup = ath11k_hw_ipq5018_reo_setup, + .set_rx_fragmentation_dst_ring = ath11k_hw_ipq5018_set_rx_fragmentation_dst_ring, + .get_reo_dest_remap_config = ath11k_get_reo_dest_remap_config_5018, -+ }; ++}; + #define ATH11K_TX_RING_MASK_0 0x1 #define ATH11K_TX_RING_MASK_1 0x2 #define ATH11K_TX_RING_MASK_2 0x4 -@@ -1833,6 +2011,197 @@ const struct service_to_pipe ath11k_targ +@@ -1880,6 +2057,197 @@ const struct service_to_pipe ath11k_targ }, }; @@ -967,9 +975,9 @@ Signed-off-by: Sriram R const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_qcn9074 = { .tx = { ATH11K_TX_RING_MASK_0, -@@ -1919,6 +2288,14 @@ const struct ath11k_hw_regs ipq8074_regs - .hal_reo_tcl_ring_base_lsb = 0x000003fc, - .hal_reo_tcl_ring_hp = 0x00003058, +@@ -1970,6 +2338,14 @@ const struct ath11k_hw_regs ipq8074_regs + .hal_reo_cmd_ring_base_lsb = 0x00000194, + .hal_reo_cmd_ring_hp = 0x00003020, + /* SW2REO ring address */ + .hal_sw2reo_ring_base_lsb = 0x000001ec, @@ -982,9 +990,9 @@ Signed-off-by: Sriram R /* REO status address */ .hal_reo_status_ring_base_lsb = 0x00000504, .hal_reo_status_hp = 0x00003070, -@@ -1990,6 +2367,14 @@ const struct ath11k_hw_regs qca6390_regs - .hal_reo_tcl_ring_base_lsb = 0x000003a4, - .hal_reo_tcl_ring_hp = 0x00003050, +@@ -2055,6 +2431,14 @@ const struct ath11k_hw_regs qca6390_regs + .hal_reo_cmd_ring_base_lsb = 0x00000194, + .hal_reo_cmd_ring_hp = 0x00003020, + /* SW2REO ring address */ + .hal_sw2reo_ring_base_lsb = 0x000001ec, @@ -997,9 +1005,9 @@ Signed-off-by: Sriram R /* REO status address */ .hal_reo_status_ring_base_lsb = 0x000004ac, .hal_reo_status_hp = 0x00003068, -@@ -2061,6 +2446,14 @@ const struct ath11k_hw_regs qcn9074_regs - .hal_reo_tcl_ring_base_lsb = 0x000003fc, - .hal_reo_tcl_ring_hp = 0x00003058, +@@ -2140,6 +2524,14 @@ const struct ath11k_hw_regs qcn9074_regs + .hal_reo_cmd_ring_base_lsb = 0x00000194, + .hal_reo_cmd_ring_hp = 0x00003020, + /* SW2REO ring address */ + .hal_sw2reo_ring_base_lsb = 0x000001ec, @@ -1012,7 +1020,7 @@ Signed-off-by: Sriram R /* REO status address */ .hal_reo_status_ring_base_lsb = 0x00000504, .hal_reo_status_hp = 0x00003070, -@@ -2073,6 +2466,81 @@ const struct ath11k_hw_regs qcn9074_regs +@@ -2156,6 +2548,81 @@ const struct ath11k_hw_regs qcn9074_regs /* WBM Idle address */ .hal_wbm_idle_link_ring_base_lsb = 0x00000874, @@ -1121,7 +1129,7 @@ Signed-off-by: Sriram R #define CE_RING_IDX_INCR(nentries_mask, idx) (((idx) + 1) & (nentries_mask)) --- a/drivers/net/wireless/ath/ath11k/hal.c +++ b/drivers/net/wireless/ath/ath11k/hal.c -@@ -814,8 +814,16 @@ void ath11k_hal_srng_access_begin(struct +@@ -815,8 +815,16 @@ void ath11k_hal_srng_access_begin(struct */ void ath11k_hal_srng_access_end(struct ath11k_base *ab, struct hal_srng *srng) { @@ -1138,7 +1146,7 @@ Signed-off-by: Sriram R /* 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 -@@ -835,13 +843,13 @@ void ath11k_hal_srng_access_end(struct a +@@ -836,13 +844,13 @@ void ath11k_hal_srng_access_end(struct a *(volatile u32 *)srng->u.src_ring.tp_addr; ath11k_hif_write32(ab, (unsigned long)srng->u.src_ring.hp_addr - @@ -1154,7 +1162,7 @@ Signed-off-by: Sriram R srng->u.dst_ring.tp); } } -@@ -952,6 +960,7 @@ int ath11k_hal_srng_setup(struct ath11k_ +@@ -953,6 +961,7 @@ int ath11k_hal_srng_setup(struct ath11k_ u32 lmac_idx; int i; u32 reg_base; @@ -1162,7 +1170,7 @@ Signed-off-by: Sriram R ring_id = ath11k_hal_srng_get_ring_id(ab, type, ring_num, mac_id); if (ring_id < 0) -@@ -981,6 +990,13 @@ int ath11k_hal_srng_setup(struct ath11k_ +@@ -982,6 +991,13 @@ int ath11k_hal_srng_setup(struct ath11k_ (ring_num * srng_config->reg_size[i]); } @@ -1176,7 +1184,7 @@ Signed-off-by: Sriram R memset(srng->ring_base_vaddr, 0, (srng->entry_size * srng->num_entries) << 2); -@@ -1006,7 +1022,7 @@ int ath11k_hal_srng_setup(struct ath11k_ +@@ -1007,7 +1023,7 @@ int ath11k_hal_srng_setup(struct ath11k_ } else { if (!ab->hw_params.supports_shadow_regs) srng->u.src_ring.hp_addr = @@ -1185,7 +1193,7 @@ Signed-off-by: Sriram R else ath11k_dbg(ab, ATH11k_DBG_HAL, "hal type %d ring_num %d reg_base 0x%x shadow 0x%lx\n", -@@ -1039,7 +1055,7 @@ int ath11k_hal_srng_setup(struct ath11k_ +@@ -1040,7 +1056,7 @@ int ath11k_hal_srng_setup(struct ath11k_ } else { if (!ab->hw_params.supports_shadow_regs) srng->u.dst_ring.tp_addr = @@ -1194,26 +1202,9 @@ Signed-off-by: Sriram R (HAL_REO1_RING_TP(ab) - HAL_REO1_RING_HP(ab))); else ath11k_dbg(ab, ATH11k_DBG_HAL, -@@ -1193,12 +1209,12 @@ static int ath11k_hal_srng_create_config - s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_TCL_RING_HP(ab); - - s = &hal->srng_config[HAL_REO_REINJECT]; -- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_SW2REO_RING_BASE_LSB; -- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_SW2REO_RING_HP; -+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_SW2REO_RING_BASE_LSB(ab); -+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_SW2REO_RING_HP(ab); - - s = &hal->srng_config[HAL_REO_CMD]; -- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_CMD_RING_BASE_LSB; -- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_CMD_HP; -+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_CMD_RING_BASE_LSB(ab); -+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_CMD_HP(ab); - - s = &hal->srng_config[HAL_REO_STATUS]; - s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_STATUS_RING_BASE_LSB(ab); --- a/drivers/net/wireless/ath/ath11k/hal.h +++ b/drivers/net/wireless/ath/ath11k/hal.h -@@ -11,6 +11,8 @@ +@@ -12,6 +12,8 @@ struct ath11k_base; @@ -1222,7 +1213,7 @@ Signed-off-by: Sriram R #define HAL_LINK_DESC_SIZE (32 << 2) #define HAL_LINK_DESC_ALIGN 128 #define HAL_NUM_MPDUS_PER_LINK_DESC 6 -@@ -27,6 +29,7 @@ struct ath11k_base; +@@ -28,6 +30,7 @@ struct ath11k_base; #define HAL_WBM_IDLE_SCATTER_BUF_SIZE (HAL_WBM_IDLE_SCATTER_BUF_SIZE_MAX - \ HAL_WBM_IDLE_SCATTER_NEXT_PTR_SIZE) @@ -1230,36 +1221,15 @@ Signed-off-by: Sriram R #define HAL_DSCP_TID_MAP_TBL_NUM_ENTRIES_MAX 48 #define HAL_DSCP_TID_TBL_SIZE 24 -@@ -120,6 +123,7 @@ struct ath11k_base; +@@ -121,6 +124,7 @@ struct ath11k_base; #define HAL_REO1_DEST_RING_CTRL_IX_1 0x00000008 #define HAL_REO1_DEST_RING_CTRL_IX_2 0x0000000c #define HAL_REO1_DEST_RING_CTRL_IX_3 0x00000010 -+#define HAL_REO1_R0_MISC_CTL 0x000005d8 - #define HAL_REO1_MISC_CTL 0x00000630 ++#define HAL_REO1_R0_MISC_CTL 0x000005d8 + #define HAL_REO1_MISC_CTL(ab) ab->hw_params.regs->hal_reo1_misc_ctl #define HAL_REO1_RING_BASE_LSB(ab) ab->hw_params.regs->hal_reo1_ring_base_lsb #define HAL_REO1_RING_BASE_MSB(ab) ab->hw_params.regs->hal_reo1_ring_base_msb -@@ -180,16 +184,16 @@ struct ath11k_base; - #define HAL_REO_TCL_RING_HP(ab) ab->hw_params.regs->hal_reo_tcl_ring_hp - - /* REO CMD R0 address */ --#define HAL_REO_CMD_RING_BASE_LSB 0x00000194 -+#define HAL_REO_CMD_RING_BASE_LSB(ab) ab->hw_params.regs->hal_reo_cmd_ring_base_lsb - - /* REO CMD R2 address */ --#define HAL_REO_CMD_HP 0x00003020 -+#define HAL_REO_CMD_HP(ab) ab->hw_params.regs->hal_reo_cmd_ring_hp - - /* SW2REO R0 address */ --#define HAL_SW2REO_RING_BASE_LSB 0x000001ec -+#define HAL_SW2REO_RING_BASE_LSB(ab) ab->hw_params.regs->hal_sw2reo_ring_base_lsb - - /* SW2REO R2 address */ --#define HAL_SW2REO_RING_HP 0x00003028 -+#define HAL_SW2REO_RING_HP(ab) ab->hw_params.regs->hal_sw2reo_ring_hp - - /* CE ring R0 address */ - #define HAL_CE_DST_RING_BASE_LSB 0x00000000 -@@ -282,6 +286,7 @@ struct ath11k_base; +@@ -285,6 +289,7 @@ struct ath11k_base; #define HAL_REO1_GEN_ENABLE_AGING_LIST_ENABLE BIT(2) #define HAL_REO1_GEN_ENABLE_AGING_FLUSH_ENABLE BIT(3) #define HAL_REO1_MISC_CTL_FRAGMENT_DST_RING GENMASK(20, 17) @@ -1267,7 +1237,7 @@ Signed-off-by: Sriram R /* CE ring bit field mask and shift */ #define HAL_CE_DST_R0_DEST_CTRL_MAX_LEN GENMASK(15, 0) -@@ -318,6 +323,10 @@ struct ath11k_base; +@@ -321,6 +326,10 @@ struct ath11k_base; #define HAL_WBM2SW_RELEASE_RING_BASE_MSB_RING_SIZE 0x000fffff #define HAL_RXDMA_RING_MAX_SIZE 0x0000ffff @@ -1278,7 +1248,7 @@ Signed-off-by: Sriram R /* Add any other errors here and return them in * ath11k_hal_rx_desc_get_err(). */ -@@ -517,6 +526,7 @@ enum hal_srng_dir { +@@ -520,6 +529,7 @@ enum hal_srng_dir { #define HAL_SRNG_FLAGS_MSI_INTR 0x00020000 #define HAL_SRNG_FLAGS_CACHED 0x20000000 #define HAL_SRNG_FLAGS_LMAC_RING 0x80000000 @@ -1288,11 +1258,11 @@ Signed-off-by: Sriram R #define HAL_SRNG_TLV_HDR_LEN GENMASK(25, 10) --- a/drivers/net/wireless/ath/ath11k/qmi.h +++ b/drivers/net/wireless/ath/ath11k/qmi.h -@@ -32,6 +32,7 @@ +@@ -34,6 +34,7 @@ #define ATH11K_QMI_DEFAULT_QDSS_CONFIG_FILE_NAME "qdss_trace_config.bin" - #define ATH11K_QMI_IPQ8074_M3_DUMP_ADDRESS 0x51000000 - #define ATH11K_QMI_IPQ6018_M3_DUMP_ADDRESS 0x50100000 -+#define ATH11K_QMI_IPQ5018_M3_DUMP_ADDRESS 0x4C800000 - #define ATH11K_QMI_M3_DUMP_SIZE 0x100000 + #define ATH11K_QMI_IPQ8074_M3_DUMP_ADDRESS 0x51000000 + #define ATH11K_QMI_IPQ6018_M3_DUMP_ADDRESS 0x50100000 ++#define ATH11K_QMI_IPQ5018_M3_DUMP_ADDRESS 0x4C800000 + #define ATH11K_QMI_M3_DUMP_SIZE 0x100000 #define QMI_WLFW_REQUEST_MEM_IND_V01 0x0035 diff --git a/feeds/ipq95xx/mac80211/patches/qca/203-mac80211-ath11k-fw-dynamic-muedca.patch b/feeds/ipq95xx/mac80211/patches/qca/203-mac80211-ath11k-fw-dynamic-muedca.patch index a2219770c..efe2e4b9d 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/203-mac80211-ath11k-fw-dynamic-muedca.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/203-mac80211-ath11k-fw-dynamic-muedca.patch @@ -31,17 +31,17 @@ Signed-off-by: Muna Sinada --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -149,6 +149,8 @@ static const struct wmi_tlv_policy wmi_t - = { .min_len = sizeof(struct wmi_twt_add_dialog_event) }, +@@ -152,6 +152,8 @@ static const struct wmi_tlv_policy wmi_t + .min_len = sizeof(struct wmi_twt_add_dialog_event) }, [WMI_TAG_TPC_STATS_EVENT_FIXED_PARAM] = { .min_len = sizeof(struct wmi_tpc_stats_event_fixed_param) }, + [WMI_TAG_MUEDCA_PARAMS_CONFIG_EVENT] + = { .min_len = sizeof(struct wmi_pdev_update_muedca_event) }, - [WMI_TAG_11D_NEW_COUNTRY_EVENT] = { - .min_len = sizeof(struct wmi_11d_new_cc_ev) }, - [WMI_TAG_PER_CHAIN_RSSI_STATS] = { -@@ -8539,6 +8541,74 @@ exit: - kfree(tb); + }; + + #define PRIMAP(_hw_mode_) \ +@@ -8651,6 +8653,74 @@ int ath11k_wmi_pdev_get_tpc_table_cmdid( + return ret; } +static void @@ -115,7 +115,7 @@ Signed-off-by: Muna Sinada static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb) { struct wmi_cmd_hdr *cmd_hdr; -@@ -8676,6 +8746,9 @@ static void ath11k_wmi_tlv_op_rx(struct +@@ -8788,6 +8858,9 @@ static void ath11k_wmi_tlv_op_rx(struct case WMI_PDEV_GET_TPC_STATS_EVENTID: ath11k_process_tpc_stats(ab, skb); break; @@ -127,7 +127,7 @@ Signed-off-by: Muna Sinada ath11k_dbg(ab, ATH11K_DBG_WMI, "Unknown eventid: 0x%x\n", id); --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -743,6 +743,7 @@ enum wmi_tlv_event_id { +@@ -749,6 +749,7 @@ enum wmi_tlv_event_id { WMI_READ_DATA_FROM_FLASH_EVENTID, WMI_REPORT_RX_AGGR_FAILURE_EVENTID, WMI_PKGID_EVENTID, @@ -135,7 +135,7 @@ Signed-off-by: Muna Sinada WMI_GPIO_INPUT_EVENTID = WMI_TLV_CMD(WMI_GRP_GPIO), WMI_UPLOADH_EVENTID, WMI_CAPTUREH_EVENTID, -@@ -1853,6 +1854,7 @@ enum wmi_tlv_tag { +@@ -1859,6 +1860,7 @@ enum wmi_tlv_tag { WMI_TAG_NDP_EVENT, WMI_TAG_PDEV_PEER_PKTLOG_FILTER_CMD = 0x301, WMI_TAG_PDEV_PEER_PKTLOG_FILTER_INFO, @@ -143,7 +143,7 @@ Signed-off-by: Muna Sinada WMI_TAG_FILS_DISCOVERY_TMPL_CMD = 0x344, WMI_TAG_PDEV_SRG_BSS_COLOR_BITMAP_CMD = 0x37b, WMI_TAG_PDEV_SRG_PARTIAL_BSSID_BITMAP_CMD, -@@ -4575,6 +4577,16 @@ struct wmi_pdev_temperature_event { +@@ -4580,6 +4582,16 @@ struct wmi_pdev_temperature_event { u32 pdev_id; } __packed; @@ -162,7 +162,7 @@ Signed-off-by: Muna Sinada #define WMI_RX_STATUS_ERR_DECRYPT 0x08 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h -@@ -8435,4 +8435,15 @@ static inline int cfg80211_color_change_ +@@ -8896,4 +8896,15 @@ static inline int cfg80211_color_change_ 0, 0); } @@ -180,7 +180,7 @@ Signed-off-by: Muna Sinada #endif /* __NET_CFG80211_H */ --- a/include/net/mac80211.h +++ b/include/net/mac80211.h -@@ -6851,6 +6851,20 @@ u32 ieee80211_calc_rx_airtime(struct iee +@@ -7064,6 +7064,20 @@ u32 ieee80211_calc_rx_airtime(struct iee int len); /** @@ -203,9 +203,9 @@ Signed-off-by: Muna Sinada * This function calculates the estimated airtime usage of a frame based on the --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h -@@ -1237,6 +1237,10 @@ - * to describe the BSSID address of the AP and %NL80211_ATTR_TIMEOUT to - * specify the timeout value. +@@ -1273,6 +1273,10 @@ + * @NL80211_CMD_MODIFY_LINK_STA: Modify a link of an MLD station + * @NL80211_CMD_REMOVE_LINK_STA: Remove a link of an MLD station * + * @NL80211_CMD_UPDATE_HE_MUEDCA_PARAMS: Updated MU-EDCA parameters from driver. + * This event is used to update dynamic MU-EDCA parameters in Beacon frame, @@ -214,40 +214,38 @@ Signed-off-by: Muna Sinada * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ -@@ -1469,6 +1473,8 @@ enum nl80211_commands { - - NL80211_CMD_SET_SAR_SPECS, +@@ -1524,6 +1528,7 @@ enum nl80211_commands { + NL80211_CMD_MODIFY_LINK_STA, + NL80211_CMD_REMOVE_LINK_STA, + NL80211_CMD_UPDATE_HE_MUEDCA_PARAMS, -+ - NL80211_CMD_OBSS_COLOR_COLLISION, + /* add new commands above here */ - NL80211_CMD_COLOR_CHANGE_REQUEST, -@@ -2659,6 +2665,9 @@ enum nl80211_commands { - * enumerated in &enum nl80211_ap_settings_flags. This attribute shall be - * used with %NL80211_CMD_START_AP request. - * + /* used to define NL80211_CMD_MAX below */ +@@ -2741,6 +2746,8 @@ enum nl80211_commands { + * When used with %NL80211_CMD_FRAME_TX_STATUS, indicates the ack RX + * timestamp. When used with %NL80211_CMD_FRAME RX notification, indicates + * the incoming frame RX timestamp. + * @NL80211_ATTR_HE_MUEDCA_PARAMS: MU-EDCA AC parameters for the -+ * %NL80211_CMD_UPDATE_HE_MUEDCA_PARAMS command. -+ * ++ * %NL80211_CMD_UPDATE_HE_MUEDCA_PARAMS command. * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use -@@ -3156,6 +3165,8 @@ enum nl80211_attrs { - - NL80211_ATTR_DISABLE_HE, +@@ -3269,6 +3276,8 @@ enum nl80211_attrs { + NL80211_ATTR_TX_HW_TIMESTAMP, + NL80211_ATTR_RX_HW_TIMESTAMP, + NL80211_ATTR_HE_MUEDCA_PARAMS, + - NL80211_ATTR_OBSS_COLOR_BITMAP, + /* add attributes here, update the policy in nl80211.c */ - NL80211_ATTR_COLOR_CHANGE_COUNT, + __NL80211_ATTR_AFTER_LAST, --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c -@@ -6034,3 +6034,15 @@ void ieee80211_cqm_beacon_loss_notify(st - cfg80211_cqm_beacon_loss_notify(sdata->dev, gfp); +@@ -7331,3 +7331,15 @@ void ieee80211_disable_rssi_reports(stru + _ieee80211_enable_rssi_reports(sdata, 0, 0); } - EXPORT_SYMBOL(ieee80211_cqm_beacon_loss_notify); + EXPORT_SYMBOL(ieee80211_disable_rssi_reports); + +void ieee80211_update_muedca_params(struct ieee80211_hw *hw, + struct ieee80211_mu_edca_param_set @@ -262,8 +260,8 @@ Signed-off-by: Muna Sinada +EXPORT_SYMBOL(ieee80211_update_muedca_params); --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h -@@ -2931,6 +2931,26 @@ DEFINE_EVENT(sta_event, drv_net_fill_for - TP_ARGS(local, sdata, sta) +@@ -3051,6 +3051,26 @@ TRACE_EVENT(stop_queue, + ) ); +TRACE_EVENT(api_update_muedca_params, @@ -291,7 +289,7 @@ Signed-off-by: Muna Sinada #undef TRACE_INCLUDE_PATH --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c -@@ -18601,6 +18601,42 @@ nla_put_failure: +@@ -19695,6 +19695,42 @@ nla_put_failure: } EXPORT_SYMBOL(cfg80211_update_owe_info_event); diff --git a/feeds/ipq95xx/mac80211/patches/qca/205-monitor-ring-stuck-fix.patch b/feeds/ipq95xx/mac80211/patches/qca/205-monitor-ring-stuck-fix.patch deleted file mode 100644 index 55572d2cb..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/205-monitor-ring-stuck-fix.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 1746f5b5b62c72131a7d909592c8444594d9726e Mon Sep 17 00:00:00 2001 -From: Karthikeyan Kathirvel -Date: Mon, 10 Aug 2020 21:41:47 +0530 -Subject: [PATCH] ath11k: monitor ring stuck - -More than 20000 ppdu id jumping can cause status ring and destination -ring processing not sync. The status ring is processed and the -destination ring is not processed. Since destination is not reaped for -so long, backpressure is occured at destination ring. - -Added a workaround to update the ppdu id with the latest ppdu, this will -reap the destination ring and will avoid stuck. Increased monitor ring -sizes to avoid the early backpressure. - -Signed-off-by: Karthikeyan Kathirvel ---- - drivers/net/wireless/ath/ath11k/dp.h | 10 +++++++++ - drivers/net/wireless/ath/ath11k/dp_rx.c | 36 +++++++++++++++++++++++++++------ - 2 files changed, 40 insertions(+), 6 deletions(-) - ---- a/drivers/net/wireless/ath/ath11k/dp.h -+++ b/drivers/net/wireless/ath/ath11k/dp.h -@@ -101,6 +101,8 @@ struct ath11k_pdev_mon_stats { - u32 dest_mpdu_drop; - u32 dup_mon_linkdesc_cnt; - u32 dup_mon_buf_cnt; -+ u32 dest_mon_stuck; -+ u32 dest_mon_not_reaped; - }; - - struct dp_link_desc_bank { -@@ -121,6 +123,13 @@ struct dp_link_desc_bank { - (DP_RX_DESC_COOKIE_INDEX_MAX | DP_RX_DESC_COOKIE_POOL_ID_MAX) - #define DP_NOT_PPDU_ID_WRAP_AROUND 20000 - -+/* -+ * The destination ring processing is stuck if the destination is not -+ * moving while status ring moves 16 ppdu. the destination ring processing -+ * skips this destination ring ppdu as walkaround -+ */ -+#define MON_DEST_RING_STUCK_MAX_CNT 16 -+ - enum ath11k_dp_ppdu_state { - DP_PPDU_STATUS_START, - DP_PPDU_STATUS_DONE, -@@ -143,6 +152,7 @@ struct ath11k_mon_data { - - struct ath11k_pdev_dp { - u32 mac_id; -+ u32 mon_dest_ring_stuck_cnt; - atomic_t num_tx_pending; - wait_queue_head_t tx_empty_waitq; - struct dp_rxdma_ring rx_refill_buf_ring; ---- a/drivers/net/wireless/ath/ath11k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -5426,6 +5426,7 @@ void ath11k_dp_rx_mon_dest_process(struc - u32 ring_id; - struct ath11k_pdev_mon_stats *rx_mon_stats; - u32 npackets = 0; -+ u32 mpdu_rx_bufs_used; - - if (ar->ab->hw_params.rxdma1_enable) - ring_id = dp->rxdma_mon_dst_ring.ring_id; -@@ -5455,10 +5456,29 @@ void ath11k_dp_rx_mon_dest_process(struc - head_msdu = NULL; - tail_msdu = NULL; - -- rx_bufs_used += ath11k_dp_rx_mon_mpdu_pop(ar, mac_id, ring_entry, -+ mpdu_rx_bufs_used = ath11k_dp_rx_mon_mpdu_pop(ar, mac_id, ring_entry, - &head_msdu, - &tail_msdu, - &npackets, &ppdu_id); -+ rx_bufs_used += mpdu_rx_bufs_used; -+ -+ if (mpdu_rx_bufs_used) -+ dp->mon_dest_ring_stuck_cnt = 0; -+ else { -+ dp->mon_dest_ring_stuck_cnt++; -+ rx_mon_stats->dest_mon_not_reaped++; -+ } -+ -+ if (dp->mon_dest_ring_stuck_cnt > MON_DEST_RING_STUCK_MAX_CNT) { -+ rx_mon_stats->dest_mon_stuck++; -+ ath11k_dbg(ar->ab, ATH11K_DBG_DATA, -+ "status ring ppdu_id=%d dest ring ppdu_id=%d mon_dest_ring_stuck_cnt=%d\n" \ -+ "dest_mon_not_reaped=%u dest_mon_stuck=%u", -+ pmon->mon_ppdu_info.ppdu_id, ppdu_id,dp->mon_dest_ring_stuck_cnt, -+ rx_mon_stats->dest_mon_not_reaped, rx_mon_stats->dest_mon_stuck); -+ pmon->mon_ppdu_info.ppdu_id = ppdu_id; -+ continue; -+ } - - if (ppdu_id != pmon->mon_ppdu_info.ppdu_id) { - pmon->mon_ppdu_status = DP_PPDU_STATUS_START; diff --git a/feeds/ipq95xx/mac80211/patches/qca/207-ath11k-Add-support-for-dynamic-vlan.patch b/feeds/ipq95xx/mac80211/patches/qca/207-ath11k-Add-support-for-dynamic-vlan.patch index 4130d030a..ecf4d6b5f 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/207-ath11k-Add-support-for-dynamic-vlan.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/207-ath11k-Add-support-for-dynamic-vlan.patch @@ -150,15 +150,6 @@ Signed-off-by: Seevalamuthu Mariappan memset(&info->status, 0, sizeof(info->status)); if (ts->acked) { -@@ -616,7 +690,7 @@ static void ath11k_dp_tx_complete_msdu(s - ts->peer_id); - spin_unlock_bh(&ab->base_lock); - dev_kfree_skb_any(msdu); -- goto exit; -+ return; - } - arsta = (struct ath11k_sta *)peer->sta->drv_priv; - status.sta = peer->sta; --- a/drivers/net/wireless/ath/ath11k/dp_tx.h +++ b/drivers/net/wireless/ath/ath11k/dp_tx.h @@ -15,6 +15,204 @@ struct ath11k_dp_htt_wbm_tx_status { @@ -368,7 +359,7 @@ Signed-off-by: Seevalamuthu Mariappan int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif, --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -9092,6 +9092,9 @@ static int __ath11k_mac_register(struct +@@ -9515,6 +9515,9 @@ static int __ath11k_mac_register(struct */ ar->hw->wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MONITOR); @@ -380,7 +371,7 @@ Signed-off-by: Seevalamuthu Mariappan if (ret) { --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c -@@ -37,6 +37,9 @@ +@@ -36,6 +36,9 @@ #include "wme.h" #include "rate.h" @@ -390,7 +381,7 @@ Signed-off-by: Seevalamuthu Mariappan /* misc utils */ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, -@@ -4183,6 +4186,8 @@ void __ieee80211_subif_start_xmit(struct +@@ -4145,6 +4148,8 @@ void __ieee80211_subif_start_xmit(struct struct sta_info *sta; struct sk_buff *next; int len = skb->len; @@ -399,7 +390,7 @@ Signed-off-by: Seevalamuthu Mariappan if (unlikely(skb->len < ETH_HLEN)) { kfree_skb(skb); -@@ -4197,6 +4202,19 @@ void __ieee80211_subif_start_xmit(struct +@@ -4159,6 +4164,19 @@ void __ieee80211_subif_start_xmit(struct if (IS_ERR(sta)) sta = NULL; diff --git a/feeds/ipq95xx/mac80211/patches/qca/207-ath11k-Enable-512MB-profile-in-ath11k.patch b/feeds/ipq95xx/mac80211/patches/qca/207-ath11k-Enable-512MB-profile-in-ath11k.patch index 51597920a..73ab06e6d 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/207-ath11k-Enable-512MB-profile-in-ath11k.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/207-ath11k-Enable-512MB-profile-in-ath11k.patch @@ -22,7 +22,7 @@ Signed-off-by: Ramya Gnanasekar --- a/drivers/net/wireless/ath/ath11k/Kconfig +++ b/drivers/net/wireless/ath/ath11k/Kconfig -@@ -78,3 +78,10 @@ config ATH11K_PKTLOG +@@ -79,3 +79,10 @@ config ATH11K_PKTLOG and reception, rate information and ani state. The packet log uses ring buffer to dump the data. The buffer size, frame filters can be alterted by debugfs entries. @@ -35,7 +35,7 @@ Signed-off-by: Ramya Gnanasekar + Enables 512MB memory profile for ath11k --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h -@@ -10,11 +10,30 @@ +@@ -11,11 +11,30 @@ #include "wmi.h" /* Target configuration defines */ @@ -56,7 +56,7 @@ Signed-off-by: Ramya Gnanasekar #define TARGET_NUM_PEERS_PDEV(ab) (ab->hw_params.num_peers + TARGET_NUM_VDEVS(ab)) +/* Max num of stations (per radio) */ -+#define TARGET_NUM_STATIONS(ab) (ab->hw_params.num_peers) ++#define TARGET_NUM_STATIONS(ab) (ab->hw_params.num_peers) +#define ATH11K_QMI_TARGET_MEM_MODE ATH11K_QMI_TARGET_MEM_MODE_DEFAULT +#define ATH11K_DP_TX_COMP_RING_SIZE 32768 +#define ATH11K_DP_RXDMA_MON_STATUS_RING_SIZE 1024 @@ -66,7 +66,7 @@ Signed-off-by: Ramya Gnanasekar /* Num of peers for Single Radio mode */ #define TARGET_NUM_PEERS_SINGLE(ab) (TARGET_NUM_PEERS_PDEV(ab)) -@@ -25,9 +44,6 @@ +@@ -26,9 +45,6 @@ /* Num of peers for DBS_SBS */ #define TARGET_NUM_PEERS_DBS_SBS(ab) (3 * TARGET_NUM_PEERS_PDEV(ab)) @@ -78,21 +78,21 @@ Signed-off-by: Ramya Gnanasekar #define TARGET_NUM_TIDS(ab, x) (2 * TARGET_NUM_PEERS(ab, x) + \ --- a/drivers/net/wireless/ath/ath11k/qmi.h +++ b/drivers/net/wireless/ath/ath11k/qmi.h -@@ -30,8 +30,15 @@ +@@ -32,8 +32,15 @@ #define ATH11K_QMI_FW_MEM_REQ_SEGMENT_CNT 3 #define ATH11K_QMI_MAX_QDSS_CONFIG_FILE_NAME_SIZE 64 #define ATH11K_QMI_DEFAULT_QDSS_CONFIG_FILE_NAME "qdss_trace_config.bin" + +#ifdef CPTCFG_ATH11K_MEM_PROFILE_512M -+#define ATH11K_QMI_IPQ8074_M3_DUMP_ADDRESS 0x4E800000 -+#define ATH11K_QMI_IPQ6018_M3_DUMP_ADDRESS 0x4E300000 ++#define ATH11K_QMI_IPQ8074_M3_DUMP_ADDRESS 0x4E800000 ++#define ATH11K_QMI_IPQ6018_M3_DUMP_ADDRESS 0x4E300000 +#else - #define ATH11K_QMI_IPQ8074_M3_DUMP_ADDRESS 0x51000000 - #define ATH11K_QMI_IPQ6018_M3_DUMP_ADDRESS 0x50100000 + #define ATH11K_QMI_IPQ8074_M3_DUMP_ADDRESS 0x51000000 + #define ATH11K_QMI_IPQ6018_M3_DUMP_ADDRESS 0x50100000 +#endif + - #define ATH11K_QMI_IPQ5018_M3_DUMP_ADDRESS 0x4C800000 - #define ATH11K_QMI_M3_DUMP_SIZE 0x100000 + #define ATH11K_QMI_IPQ5018_M3_DUMP_ADDRESS 0x4C800000 + #define ATH11K_QMI_M3_DUMP_SIZE 0x100000 --- a/local-symbols +++ b/local-symbols @@ -106,17 +106,17 @@ Signed-off-by: Ramya Gnanasekar ATH11K_TRACING= --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -930,6 +930,7 @@ struct ath11k_base { +@@ -1080,6 +1080,7 @@ struct ath11k_base { bool fw_recovery_support; bool ce_remap; u32 ce_remap_base_addr; + atomic_t num_max_allowed; /* must be last */ - u8 drv_priv[0] __aligned(sizeof(void *)); + u8 drv_priv[] __aligned(sizeof(void *)); --- a/drivers/net/wireless/ath/ath11k/dp.h +++ b/drivers/net/wireless/ath/ath11k/dp.h -@@ -211,8 +211,9 @@ struct ath11k_pdev_dp { +@@ -204,8 +204,9 @@ struct ath11k_pdev_dp { #define DP_WBM_RELEASE_RING_SIZE 64 #define DP_TCL_DATA_RING_SIZE 512 @@ -127,7 +127,7 @@ Signed-off-by: Ramya Gnanasekar #define DP_TCL_CMD_RING_SIZE 32 #define DP_TCL_STATUS_RING_SIZE 32 #define DP_REO_DST_RING_MAX 4 -@@ -225,9 +226,9 @@ struct ath11k_pdev_dp { +@@ -218,9 +219,9 @@ struct ath11k_pdev_dp { #define DP_RXDMA_BUF_RING_SIZE 4096 #define DP_RXDMA_REFILL_RING_SIZE 2048 #define DP_RXDMA_ERR_DST_RING_SIZE 1024 @@ -166,7 +166,7 @@ Signed-off-by: Ramya Gnanasekar dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); -@@ -803,6 +806,7 @@ void ath11k_dp_tx_completion_handler(str +@@ -808,6 +811,7 @@ void ath11k_dp_tx_completion_handler(str wake_up(&ar->dp.tx_empty_waitq); ath11k_dp_tx_complete_msdu(ar, msdu, &ts); @@ -176,7 +176,7 @@ Signed-off-by: Ramya Gnanasekar --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -103,7 +103,7 @@ static const struct ath11k_hw_params ath +@@ -101,7 +101,7 @@ static const struct ath11k_hw_params ath .idle_ps = false, .supports_sta_ps = false, .cold_boot_calib = true, @@ -185,7 +185,7 @@ Signed-off-by: Ramya Gnanasekar .num_vdevs = 16 + 1, .num_peers = 512, .supports_suspend = false, -@@ -171,7 +171,7 @@ static const struct ath11k_hw_params ath +@@ -175,7 +175,7 @@ static const struct ath11k_hw_params ath .idle_ps = false, .supports_sta_ps = false, .cold_boot_calib = true, @@ -194,7 +194,7 @@ Signed-off-by: Ramya Gnanasekar .num_vdevs = 16 + 1, .num_peers = 512, .supports_suspend = false, -@@ -237,7 +237,7 @@ static const struct ath11k_hw_params ath +@@ -247,7 +247,7 @@ static const struct ath11k_hw_params ath .idle_ps = true, .supports_sta_ps = true, .cold_boot_calib = false, @@ -203,7 +203,7 @@ Signed-off-by: Ramya Gnanasekar .num_vdevs = 16 + 1, .num_peers = 512, .supports_suspend = true, -@@ -303,7 +303,7 @@ static const struct ath11k_hw_params ath +@@ -319,7 +319,7 @@ static const struct ath11k_hw_params ath .idle_ps = false, .supports_sta_ps = false, .cold_boot_calib = true, @@ -212,7 +212,7 @@ Signed-off-by: Ramya Gnanasekar .num_vdevs = 8, .num_peers = 128, .supports_suspend = false, -@@ -369,7 +369,7 @@ static const struct ath11k_hw_params ath +@@ -391,7 +391,7 @@ static const struct ath11k_hw_params ath .idle_ps = true, .supports_sta_ps = true, .cold_boot_calib = false, @@ -221,7 +221,7 @@ Signed-off-by: Ramya Gnanasekar .num_vdevs = 16 + 1, .num_peers = 512, .supports_suspend = true, -@@ -434,7 +434,7 @@ static const struct ath11k_hw_params ath +@@ -462,7 +462,7 @@ static const struct ath11k_hw_params ath .idle_ps = true, .supports_sta_ps = true, .cold_boot_calib = false, diff --git a/feeds/ipq95xx/mac80211/patches/qca/207-mac80211-add-nss-redirect-support.patch b/feeds/ipq95xx/mac80211/patches/qca/207-mac80211-add-nss-redirect-support.patch index af547543c..8fb94a708 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/207-mac80211-add-nss-redirect-support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/207-mac80211-add-nss-redirect-support.patch @@ -30,7 +30,7 @@ Signed-off-by: Sowmiya Sree Elavalagan --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h -@@ -32,6 +32,9 @@ +@@ -33,6 +33,9 @@ #include "key.h" #include "sta_info.h" #include "debug.h" @@ -40,7 +40,7 @@ Signed-off-by: Sowmiya Sree Elavalagan extern const struct cfg80211_ops mac80211_config_ops; -@@ -1008,6 +1011,9 @@ struct ieee80211_sub_if_data { +@@ -1093,6 +1096,9 @@ struct ieee80211_sub_if_data { struct dentry *default_beacon_key; } debugfs; #endif @@ -52,7 +52,7 @@ Signed-off-by: Sowmiya Sree Elavalagan struct ieee80211_vif vif; --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c -@@ -26,6 +26,12 @@ +@@ -27,6 +27,12 @@ #include "wme.h" #include "rate.h" @@ -65,9 +65,9 @@ Signed-off-by: Sowmiya Sree Elavalagan /** * DOC: Interface list locking * -@@ -647,6 +653,13 @@ static int ieee80211_stop(struct net_dev - { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); +@@ -923,6 +929,13 @@ static int ieee80211_stop(struct net_dev + ieee80211_stop_mbssid(sdata); + } +#ifdef CPTCFG_MAC80211_NSS_SUPPORT + if (sdata->nssctx) { @@ -79,7 +79,7 @@ Signed-off-by: Sowmiya Sree Elavalagan wiphy_lock(sdata->local->hw.wiphy); ieee80211_do_stop(sdata, true); wiphy_unlock(sdata->local->hw.wiphy); -@@ -1095,6 +1108,34 @@ void ieee80211_del_virtual_monitor(struc +@@ -1394,6 +1407,34 @@ void ieee80211_del_virtual_monitor(struc kfree(sdata); } @@ -114,7 +114,7 @@ Signed-off-by: Sowmiya Sree Elavalagan /* * NOTE: Be very careful when changing this function, it must NOT return * an error on interface type changes that have been pre-checked, so most -@@ -1326,6 +1367,19 @@ int ieee80211_do_open(struct wireless_de +@@ -1626,6 +1667,19 @@ int ieee80211_do_open(struct wireless_de ieee80211_recalc_ps(local); @@ -136,7 +136,7 @@ Signed-off-by: Sowmiya Sree Elavalagan local->ops->wake_tx_queue) { --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c -@@ -2520,6 +2520,54 @@ static bool ieee80211_frame_allowed(stru +@@ -2604,6 +2604,54 @@ static bool ieee80211_frame_allowed(stru return true; } @@ -191,9 +191,9 @@ Signed-off-by: Sowmiya Sree Elavalagan static void ieee80211_deliver_skb_to_local_stack(struct sk_buff *skb, struct ieee80211_rx_data *rx) { -@@ -2538,6 +2586,9 @@ static void ieee80211_deliver_skb_to_loc - } else { - memset(skb->cb, 0, sizeof(skb->cb)); +@@ -2643,6 +2691,9 @@ static void ieee80211_deliver_skb_to_loc + !ether_addr_equal(ehdr->h_dest, sdata->vif.addr))) + ether_addr_copy(ehdr->h_dest, sdata->vif.addr); +#ifdef CPTCFG_MAC80211_NSS_SUPPORT + netif_rx_nss(rx, skb); @@ -201,7 +201,7 @@ Signed-off-by: Sowmiya Sree Elavalagan /* deliver to local stack */ if (rx->list) #if LINUX_VERSION_IS_GEQ(4,19,0) -@@ -2547,6 +2598,7 @@ static void ieee80211_deliver_skb_to_loc +@@ -2652,6 +2703,7 @@ static void ieee80211_deliver_skb_to_loc #endif else netif_receive_skb(skb); @@ -211,8 +211,8 @@ Signed-off-by: Sowmiya Sree Elavalagan --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c -@@ -4140,6 +4140,35 @@ out: - rcu_read_unlock(); +@@ -4395,6 +4395,35 @@ static void ieee80211_mlo_multicast_tx(s + kfree_skb(skb); } +#ifdef CPTCFG_MAC80211_NSS_SUPPORT @@ -247,18 +247,18 @@ Signed-off-by: Sowmiya Sree Elavalagan /** * ieee80211_subif_start_xmit - netif start_xmit function for 802.3 vifs * @skb: packet to be sent -@@ -4150,6 +4179,10 @@ out: - netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, - struct net_device *dev) - { +@@ -4408,6 +4437,10 @@ netdev_tx_t ieee80211_subif_start_xmit(s + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + const struct ethhdr *eth = (void *)skb->data; + +#ifdef CPTCFG_MAC80211_NSS_SUPPORT + ieee80211_xmit_nss_fixup(skb, dev); +#endif + - if (unlikely(ieee80211_multicast_to_unicast(skb, dev))) { - struct sk_buff_head queue; + if (likely(!is_multicast_ether_addr(eth->h_dest))) + goto normal; -@@ -4281,6 +4314,9 @@ netdev_tx_t ieee80211_subif_start_xmit_8 +@@ -4564,6 +4597,9 @@ netdev_tx_t ieee80211_subif_start_xmit_8 struct ieee80211_key *key; struct sta_info *sta; diff --git a/feeds/ipq95xx/mac80211/patches/qca/210-ath11k-full-mon-support-for-qcn9000.patch b/feeds/ipq95xx/mac80211/patches/qca/210-ath11k-full-mon-support-for-qcn9000.patch index e5de43324..b9e0dff05 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/210-ath11k-full-mon-support-for-qcn9000.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/210-ath11k-full-mon-support-for-qcn9000.patch @@ -33,32 +33,6 @@ Signed-off-by: Anilkumar Kolli drivers/net/wireless/ath/ath11k/mac.c | 11 + 14 files changed, 677 insertions(+), 24 deletions(-) ---- a/drivers/net/wireless/ath/ath11k/core.c -+++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -60,6 +60,7 @@ static const struct ath11k_hw_params ath - }, - .max_radios = 3, - .bdf_addr = 0x4B0C0000, -+ .full_monitor_mode = false, - .hw_ops = &ipq8074_ops, - .m3_addr = ATH11K_QMI_IPQ8074_M3_DUMP_ADDRESS, - .ring_mask = &ath11k_hw_ring_mask_ipq8074, -@@ -131,6 +132,7 @@ static const struct ath11k_hw_params ath - }, - .max_radios = 2, - .bdf_addr = 0x4ABC0000, -+ .full_monitor_mode = false, - .hw_ops = &ipq6018_ops, - .m3_addr = ATH11K_QMI_IPQ6018_M3_DUMP_ADDRESS, - .ring_mask = &ath11k_hw_ring_mask_ipq8074, -@@ -266,6 +268,7 @@ static const struct ath11k_hw_params ath - .max_radios = 1, - .single_pdev_only = false, - .qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCN9074, -+ .full_monitor_mode = true, - .hw_ops = &qcn9074_ops, - .ring_mask = &ath11k_hw_ring_mask_qcn9074, - .internal_sleep_clock = false, --- a/drivers/net/wireless/ath/ath11k/dp.c +++ b/drivers/net/wireless/ath/ath11k/dp.c @@ -837,9 +837,10 @@ int ath11k_dp_service_srng(struct ath11k @@ -86,7 +60,7 @@ Signed-off-by: Anilkumar Kolli } void ath11k_dp_pdev_reo_cleanup(struct ath11k_base *ab) -@@ -5585,7 +5587,6 @@ int ath11k_dp_rx_process_mon_status(stru +@@ -5607,7 +5609,6 @@ int ath11k_dp_rx_process_mon_status(stru enum hal_rx_mon_status hal_status; struct sk_buff *skb; struct sk_buff_head skb_list; @@ -94,8 +68,8 @@ Signed-off-by: Anilkumar Kolli struct ath11k_peer *peer; struct ath11k_sta *arsta = NULL; int num_buffs_reaped = 0; -@@ -5621,15 +5622,6 @@ int ath11k_dp_rx_process_mon_status(stru - +@@ -5647,15 +5648,6 @@ int ath11k_dp_rx_process_mon_status(stru + memset(ppdu_info, 0, sizeof(struct hal_rx_mon_ppdu_info)); hal_status = ath11k_hal_rx_parse_mon_status(ab, ppdu_info, skb); - if (test_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags) && @@ -110,7 +84,7 @@ Signed-off-by: Anilkumar Kolli if (ppdu_info->peer_id == HAL_INVALID_PEERID || hal_status != HAL_RX_MON_STATUS_PPDU_DONE) { dev_kfree_skb_any(skb); -@@ -5666,7 +5658,6 @@ int ath11k_dp_rx_process_mon_status(stru +@@ -5692,7 +5684,6 @@ int ath11k_dp_rx_process_mon_status(stru next_skb: spin_unlock_bh(&ab->base_lock); rcu_read_unlock(); @@ -118,15 +92,7 @@ Signed-off-by: Anilkumar Kolli dev_kfree_skb_any(skb); memset(ppdu_info, 0, sizeof(*ppdu_info)); ppdu_info->peer_id = HAL_INVALID_PEERID; -@@ -5889,6 +5880,7 @@ static int ath11k_dp_rx_full_mon_deliver - tail_msdu = mon_mpdu->tail; - if (head_msdu && tail_msdu) { - ret = ath11k_dp_rx_mon_deliver(ar, mac_id, head_msdu, -+ &pmon->mon_ppdu_info, - tail_msdu, napi); - rx_mon_stats->dest_mpdu_done++; - ath11k_dbg(ar->ab, ATH11K_DBG_DATA, "full mon: deliver ppdu\n"); -@@ -6032,12 +6024,10 @@ int ath11k_dp_rx_process_mon_rings(struc +@@ -6059,12 +6050,10 @@ int ath11k_dp_rx_process_mon_rings(struc struct ath11k *ar = ath11k_ab_to_ar(ab, mac_id); int ret = 0; @@ -165,7 +131,7 @@ Signed-off-by: Anilkumar Kolli int ath11k_peer_rx_frag_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id); --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h -@@ -125,6 +125,7 @@ enum ath11k_bus { +@@ -126,6 +126,7 @@ enum ath11k_bus { struct hal_rx_desc; struct hal_tcl_data_cmd; diff --git a/feeds/ipq95xx/mac80211/patches/qca/211-002-ath11k-add-WDS-offload-support-on-NSS-offload-for-STA-mode.patch b/feeds/ipq95xx/mac80211/patches/qca/211-002-ath11k-add-WDS-offload-support-on-NSS-offload-for-STA-mode.patch index fcb605b76..54ad59737 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/211-002-ath11k-add-WDS-offload-support-on-NSS-offload-for-STA-mode.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/211-002-ath11k-add-WDS-offload-support-on-NSS-offload-for-STA-mode.patch @@ -26,7 +26,7 @@ Signed-off-by: Sathishkumar Muruganandam --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -576,6 +576,7 @@ struct ath11k { +@@ -679,6 +679,7 @@ struct ath11k { struct ath11k_pdev_wmi *wmi; #ifdef CPTCFG_ATH11K_NSS_SUPPORT struct ath11k_nss nss; @@ -34,7 +34,7 @@ Signed-off-by: Sathishkumar Muruganandam #endif struct ath11k_pdev_dp dp; u8 mac_addr[ETH_ALEN]; -@@ -904,8 +905,12 @@ struct ath11k_base { +@@ -1041,8 +1042,12 @@ struct ath11k_base { u32 fw_crash_counter; } stats; struct ath11k_ftm_event_obj ftm_event_obj; @@ -46,10 +46,10 @@ Signed-off-by: Sathishkumar Muruganandam + struct ath11k_dbring_cap *db_caps; u32 num_db_cap; - struct work_struct rfkill_work; + --- a/drivers/net/wireless/ath/ath11k/dp.h +++ b/drivers/net/wireless/ath/ath11k/dp.h -@@ -1197,13 +1197,16 @@ struct htt_t2h_peer_map_event { +@@ -1098,13 +1098,16 @@ struct htt_t2h_peer_map_event { #define HTT_T2H_PEER_UNMAP_INFO_PEER_ID HTT_T2H_PEER_MAP_INFO_PEER_ID #define HTT_T2H_PEER_UNMAP_INFO1_MAC_ADDR_H16 \ HTT_T2H_PEER_MAP_INFO1_MAC_ADDR_H16 @@ -70,7 +70,7 @@ Signed-off-by: Sathishkumar Muruganandam struct htt_resp_msg { --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -1855,6 +1855,8 @@ void ath11k_dp_htt_htc_t2h_msg_handler(s +@@ -1856,6 +1856,8 @@ void ath11k_dp_htt_htc_t2h_msg_handler(s u16 peer_mac_h16; u16 ast_hash; u16 hw_peer_id; @@ -79,7 +79,7 @@ Signed-off-by: Sathishkumar Muruganandam ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "dp_htt rx msg type :0x%0x\n", type); -@@ -1890,15 +1892,29 @@ void ath11k_dp_htt_htc_t2h_msg_handler(s +@@ -1891,15 +1893,29 @@ void ath11k_dp_htt_htc_t2h_msg_handler(s resp->peer_map_ev.info2); hw_peer_id = FIELD_GET(HTT_T2H_PEER_MAP_INFO1_HW_PEER_ID, resp->peer_map_ev.info1); @@ -114,7 +114,7 @@ Signed-off-by: Sathishkumar Muruganandam break; --- a/drivers/net/wireless/ath/ath11k/dp_tx.c +++ b/drivers/net/wireless/ath/ath11k/dp_tx.c -@@ -469,7 +469,7 @@ ath11k_dp_tx_process_htt_tx_complete(str +@@ -479,7 +479,7 @@ ath11k_dp_tx_process_htt_tx_complete(str break; case HAL_WBM_REL_HTT_TX_COMP_STATUS_MEC_NOTIFY: /* This event is to be handled only when the driver decides to @@ -425,7 +425,7 @@ Signed-off-by: Sathishkumar Muruganandam + + spin_lock_bh(&ab->base_lock); + -+ peer = ath11k_peer_find_by_id(ab, peer_id); ++ peer = ath11k_peer_find_list_by_id(ab, peer_id); + if (!peer) { + ath11k_warn(ab, "peer-unmap-event: unknown peer id %d\n", + peer_id); @@ -562,19 +562,20 @@ Signed-off-by: Sathishkumar Muruganandam } static int ath11k_wait_for_peer_common(struct ath11k_base *ab, int vdev_id, -@@ -186,19 +586,33 @@ static int ath11k_wait_for_peer_common(s +@@ -256,20 +656,34 @@ err_clean: void ath11k_peer_cleanup(struct ath11k *ar, u32 vdev_id) { - struct ath11k_peer *peer, *tmp; + struct ath11k_peer *peer, *tmp_peer; + struct ath11k_base *ab = ar->ab; +#ifdef CPTCFG_ATH11K_NSS_SUPPORT + struct ath11k_ast_entry *ast_entry, *tmp_ast; +#endif - struct ath11k_base *ab = ar->ab; lockdep_assert_held(&ar->conf_mutex); + mutex_lock(&ab->tbl_mtx_lock); spin_lock_bh(&ab->base_lock); - list_for_each_entry_safe(peer, tmp, &ab->peers, list) { + list_for_each_entry_safe(peer, tmp_peer, &ab->peers, list) { @@ -595,10 +596,10 @@ Signed-off-by: Sathishkumar Muruganandam + ath11k_peer_del_ast(ar, ast_entry); +#endif + + ath11k_peer_rhash_delete(ab, peer); list_del(&peer->list); kfree(peer); - ar->num_peers--; -@@ -242,7 +656,7 @@ int ath11k_peer_delete(struct ath11k *ar +@@ -336,7 +750,7 @@ static int __ath11k_peer_delete(struct a reinit_completion(&ar->peer_delete_done); @@ -607,7 +608,7 @@ Signed-off-by: Sathishkumar Muruganandam ret = ath11k_wmi_send_peer_delete_cmd(ar, addr, vdev_id); if (ret) { -@@ -270,6 +684,7 @@ int ath11k_peer_create(struct ath11k *ar +@@ -377,6 +791,7 @@ int ath11k_peer_create(struct ath11k *ar struct ieee80211_sta *sta, struct peer_create_params *param) { struct ath11k_peer *peer; @@ -615,7 +616,7 @@ Signed-off-by: Sathishkumar Muruganandam struct ath11k_sta *arsta; int ret, fbret; -@@ -324,7 +739,14 @@ int ath11k_peer_create(struct ath11k *ar +@@ -440,7 +855,14 @@ int ath11k_peer_create(struct ath11k *ar peer->sec_type = HAL_ENCRYPT_TYPE_OPEN; peer->sec_type_grp = HAL_ENCRYPT_TYPE_OPEN; @@ -633,7 +634,7 @@ Signed-off-by: Sathishkumar Muruganandam arsta = (struct ath11k_sta *)sta->drv_priv; --- a/drivers/net/wireless/ath/ath11k/peer.h +++ b/drivers/net/wireless/ath/ath11k/peer.h -@@ -17,6 +17,47 @@ struct ppdu_user_delayba { +@@ -18,6 +18,47 @@ struct ppdu_user_delayba { u32 resp_rate_flags; }; @@ -681,7 +682,7 @@ Signed-off-by: Sathishkumar Muruganandam struct ath11k_peer { struct list_head list; struct ieee80211_sta *sta; -@@ -28,6 +69,10 @@ struct ath11k_peer { +@@ -29,6 +70,10 @@ struct ath11k_peer { u8 pdev_idx; u16 hw_peer_id; struct ath11k_nss_peer nss; @@ -692,7 +693,7 @@ Signed-off-by: Sathishkumar Muruganandam /* protected by ab->data_lock */ struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1]; -@@ -48,8 +93,13 @@ struct ath11k_peer { +@@ -54,8 +99,13 @@ struct ath11k_peer { }; void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id); @@ -706,10 +707,11 @@ Signed-off-by: Sathishkumar Muruganandam struct ath11k_peer *ath11k_peer_find(struct ath11k_base *ab, int vdev_id, const u8 *addr); struct ath11k_peer *ath11k_peer_find_by_addr(struct ath11k_base *ab, -@@ -65,4 +115,72 @@ int ath11k_wait_for_peer_delete_done(str - struct ath11k_peer *ath11k_peer_find_by_vdev_id(struct ath11k_base *ab, - int vdev_id); - +@@ -73,4 +123,71 @@ struct ath11k_peer *ath11k_peer_find_by_ + int ath11k_peer_rhash_tbl_init(struct ath11k_base *ab); + void ath11k_peer_rhash_tbl_destroy(struct ath11k_base *ab); + int ath11k_peer_rhash_delete(struct ath11k_base *ab, struct ath11k_peer *peer); ++ +#ifdef CPTCFG_ATH11K_NSS_SUPPORT +struct ath11k_ast_entry *ath11k_peer_ast_find_by_addr(struct ath11k_base *ab, + u8* addr); @@ -742,7 +744,6 @@ Signed-off-by: Sathishkumar Muruganandam +static inline int ath11k_peer_update_ast(struct ath11k *ar, struct ath11k_peer *peer, + struct ath11k_ast_entry *ast_entry) +{ -+ + return 0; +} + @@ -776,21 +777,20 @@ Signed-off-by: Sathishkumar Muruganandam +{ + return NULL; +} -+ +#endif /* CPTCFG_ATH11K_NSS_SUPPORT */ #endif /* _PEER_H_ */ --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -151,6 +151,8 @@ static const struct wmi_tlv_policy wmi_t +@@ -154,6 +154,8 @@ static const struct wmi_tlv_policy wmi_t = { .min_len = sizeof(struct wmi_tpc_stats_event_fixed_param) }, [WMI_TAG_MUEDCA_PARAMS_CONFIG_EVENT] = { .min_len = sizeof(struct wmi_pdev_update_muedca_event) }, + [WMI_TAG_WDS_ADDR_EVENT] + = { .min_len = sizeof(struct wmi_wds_addr_event) }, - [WMI_TAG_11D_NEW_COUNTRY_EVENT] = { - .min_len = sizeof(struct wmi_11d_new_cc_ev) }, - [WMI_TAG_PER_CHAIN_RSSI_STATS] = { -@@ -1080,6 +1082,51 @@ int ath11k_wmi_send_peer_delete_cmd(stru + }; + + #define PRIMAP(_hw_mode_) \ +@@ -1096,6 +1098,51 @@ int ath11k_wmi_send_peer_delete_cmd(stru return ret; } @@ -842,7 +842,7 @@ Signed-off-by: Sathishkumar Muruganandam int ath11k_wmi_send_pdev_set_regdomain(struct ath11k *ar, struct pdev_set_regdomain_params *param) { -@@ -5966,6 +6013,36 @@ static int ath11k_pull_peer_assoc_conf_e +@@ -6006,6 +6053,36 @@ static int ath11k_pull_peer_assoc_conf_e return 0; } @@ -879,7 +879,7 @@ Signed-off-by: Sathishkumar Muruganandam static void ath11k_wmi_pull_pdev_stats_base(const struct wmi_pdev_stats_base *src, struct ath11k_fw_stats_pdev *dst) { -@@ -6900,6 +6977,7 @@ static int ath11k_wmi_tlv_rdy_parse(stru +@@ -6950,6 +7027,7 @@ static int ath11k_wmi_tlv_rdy_parse(stru ether_addr_copy(ab->mac_addr, fixed_param.ready_event_min.mac_addr.addr); @@ -887,7 +887,7 @@ Signed-off-by: Sathishkumar Muruganandam ab->pktlog_defs_checksum = fixed_param.pktlog_defs_checksum; ab->wmi_ready = true; break; -@@ -8609,6 +8687,22 @@ exit: +@@ -8721,6 +8799,22 @@ exit: kfree(tb); } @@ -910,9 +910,9 @@ Signed-off-by: Sathishkumar Muruganandam static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb) { struct wmi_cmd_hdr *cmd_hdr; -@@ -8712,6 +8806,9 @@ static void ath11k_wmi_tlv_op_rx(struct - case WMI_TWT_ADD_DIALOG_EVENTID: - ath11k_wmi_twt_add_dialog_event(ab, skb); +@@ -8824,6 +8918,9 @@ static void ath11k_wmi_tlv_op_rx(struct + case WMI_PDEV_UTF_EVENTID: + ath11k_tm_event_wmi(ab, id, skb); break; + case WMI_WDS_PEER_EVENTID: + ath11k_wmi_wds_peer_event(ab, skb); @@ -922,7 +922,7 @@ Signed-off-by: Sathishkumar Muruganandam case WMI_PEER_OPER_MODE_CHANGE_EVENTID: --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -2964,6 +2964,21 @@ struct wmi_peer_delete_cmd { +@@ -2977,6 +2977,21 @@ struct wmi_peer_delete_cmd { struct wmi_mac_addr peer_macaddr; } __packed; @@ -944,7 +944,7 @@ Signed-off-by: Sathishkumar Muruganandam struct wmi_peer_reorder_queue_setup_cmd { u32 tlv_header; u32 vdev_id; -@@ -4320,6 +4335,21 @@ struct wmi_probe_resp_tx_status_event { +@@ -4325,6 +4340,21 @@ struct wmi_probe_resp_tx_status_event { u32 tx_status; } __packed; @@ -966,7 +966,7 @@ Signed-off-by: Sathishkumar Muruganandam /* * PDEV statistics */ -@@ -5963,6 +5993,9 @@ int ath11k_wmi_set_sta_ps_param(struct a +@@ -6350,6 +6380,9 @@ int ath11k_wmi_set_sta_ps_param(struct a int ath11k_wmi_force_fw_hang_cmd(struct ath11k *ar, u32 type, u32 delay_time_ms); int ath11k_wmi_send_peer_delete_cmd(struct ath11k *ar, const u8 *peer_addr, u8 vdev_id); diff --git a/feeds/ipq95xx/mac80211/patches/qca/211-ath11k-custom-aggregation-size-support-over-WMI.patch b/feeds/ipq95xx/mac80211/patches/qca/211-ath11k-custom-aggregation-size-support-over-WMI.patch index aa41eb941..132537506 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/211-ath11k-custom-aggregation-size-support-over-WMI.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/211-ath11k-custom-aggregation-size-support-over-WMI.patch @@ -26,7 +26,7 @@ Signed-off-by: Ramya Gnanasekar --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -253,6 +253,94 @@ void ath11k_debugfs_twt(struct ath11k_vi +@@ -292,6 +292,94 @@ void ath11k_debugfs_twt(struct ath11k_vi } #endif @@ -123,7 +123,7 @@ Signed-off-by: Ramya Gnanasekar struct ath11k_fw_stats_pdev *i, *tmp; --- a/drivers/net/wireless/ath/ath11k/debugfs.h +++ b/drivers/net/wireless/ath/ath11k/debugfs.h -@@ -158,6 +158,8 @@ static inline void ath11k_debugfs_twt(st +@@ -313,6 +313,8 @@ static inline void ath11k_debugfs_twt(st } #endif @@ -136,14 +136,14 @@ Signed-off-by: Ramya Gnanasekar +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -6758,6 +6758,8 @@ static int ath11k_mac_op_add_interface(s if (ret) - ath11k_warn(ar->ab, "failed to set ap ps ret %d\n", ret); + goto err_peer_del; + ath11k_debug_aggr_size_config_init(arvif); + mutex_unlock(&ar->conf_mutex); return 0; -@@ -6900,6 +6902,13 @@ err_vdev_del: +@@ -6893,6 +6895,13 @@ err_vdev_del: debugfs_remove_recursive(arvif->debugfs_twt); arvif->debugfs_twt = NULL; @@ -159,7 +159,7 @@ Signed-off-by: Ramya Gnanasekar --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -3983,6 +3983,58 @@ int ath11k_wmi_send_bss_color_change_ena +@@ -4021,6 +4021,58 @@ int ath11k_wmi_send_bss_color_change_ena return ret; } @@ -220,7 +220,7 @@ Signed-off-by: Ramya Gnanasekar { --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -5306,6 +5306,56 @@ struct wmi_pdev_obss_pd_bitmap_cmd { +@@ -5311,6 +5311,56 @@ struct wmi_pdev_obss_pd_bitmap_cmd { u32 bitmap[2]; } __packed; @@ -277,21 +277,22 @@ Signed-off-by: Ramya Gnanasekar #define ATH11K_BSS_COLOR_COLLISION_SCAN_PERIOD_MS 200 #define ATH11K_OBSS_COLOR_COLLISION_DETECTION_DISABLE 0 #define ATH11K_OBSS_COLOR_COLLISION_DETECTION 1 -@@ -6119,4 +6169,6 @@ int ath11k_wmi_scan_prob_req_oui(struct - const u8 mac_addr[ETH_ALEN]); +@@ -6529,5 +6579,7 @@ int ath11k_wmi_sta_keepalive(struct ath1 + const struct wmi_sta_keepalive_arg *arg); int ath11k_wmi_pdev_get_tpc_table_cmdid(struct ath11k *ar); void ath11k_wmi_free_tpc_stats_mem(struct ath11k *ar); +int ath11k_wmi_send_aggr_size_cmd(struct ath11k *ar, + struct set_custom_aggr_size_params *params); + #endif --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -295,6 +295,8 @@ struct ath11k_vif { - u32 vht_cap; - struct ieee80211_chanctx_conf chanctx; +@@ -388,6 +388,8 @@ struct ath11k_vif { + + #ifdef CPTCFG_ATH11K_DEBUGFS struct dentry *debugfs_twt; + struct dentry *ampdu_aggr_size; + struct dentry *amsdu_aggr_size; + #endif /* CPTCFG_ATH11K_DEBUGFS */ + struct ath11k_mgmt_frame_stats mgmt_stats; - #ifdef CPTCFG_ATH11K_NSS_SUPPORT - struct arvif_nss nss; diff --git a/feeds/ipq95xx/mac80211/patches/qca/211-ath11k-use-reserved-memory-from-bootargs.patch b/feeds/ipq95xx/mac80211/patches/qca/211-ath11k-use-reserved-memory-from-bootargs.patch index 39ca5b1e3..112baecb1 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/211-ath11k-use-reserved-memory-from-bootargs.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/211-ath11k-use-reserved-memory-from-bootargs.patch @@ -21,7 +21,7 @@ Signed-off-by: Anilkumar Kolli --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -47,6 +47,11 @@ bool ath11k_collect_dump = false; +@@ -48,6 +48,11 @@ bool ath11k_collect_dump = false; EXPORT_SYMBOL(ath11k_collect_dump); #endif @@ -35,7 +35,7 @@ Signed-off-by: Anilkumar Kolli static const struct ath11k_hw_params ath11k_hw_params[] = { --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c -@@ -2573,7 +2573,7 @@ static int ath11k_qmi_assign_target_mem_ +@@ -2655,7 +2655,7 @@ static int ath11k_qmi_assign_target_mem_ struct device *dev = ab->dev; struct device_node *hremote_node = NULL; struct resource res; @@ -44,7 +44,7 @@ Signed-off-by: Anilkumar Kolli int i, idx, ret; for (i = 0, idx = 0; i < ab->qmi.mem_seg_count; i++) { -@@ -2600,7 +2600,17 @@ static int ath11k_qmi_assign_target_mem_ +@@ -2682,7 +2682,17 @@ static int ath11k_qmi_assign_target_mem_ return -EINVAL; } @@ -63,7 +63,7 @@ Signed-off-by: Anilkumar Kolli ab->qmi.target_mem[idx].iaddr = ioremap(ab->qmi.target_mem[idx].paddr, ab->qmi.target_mem[i].size); -@@ -2626,13 +2636,17 @@ static int ath11k_qmi_assign_target_mem_ +@@ -2708,13 +2718,17 @@ static int ath11k_qmi_assign_target_mem_ if (hremote_node) { ab->qmi.target_mem[idx].paddr = res.start + host_ddr_sz; @@ -84,7 +84,7 @@ Signed-off-by: Anilkumar Kolli } else { ab->qmi.target_mem[idx].paddr = 0; ab->qmi.target_mem[idx].vaddr = NULL; -@@ -3572,7 +3586,9 @@ int ath11k_qmi_pci_alloc_qdss_mem(struct +@@ -3720,7 +3734,9 @@ int ath11k_qmi_pci_alloc_qdss_mem(struct { struct ath11k_base *ab = qmi->ab; struct device *dev = ab->dev; @@ -95,7 +95,7 @@ Signed-off-by: Anilkumar Kolli u32 addr = 0; if (ab->qmi.qdss_mem_seg_len > 1) { -@@ -3590,11 +3606,33 @@ int ath11k_qmi_pci_alloc_qdss_mem(struct +@@ -3738,11 +3754,33 @@ int ath11k_qmi_pci_alloc_qdss_mem(struct return -ENOMEM; } @@ -135,29 +135,29 @@ Signed-off-by: Anilkumar Kolli ioremap(ab->qmi.qdss_mem[i].paddr, --- a/drivers/net/wireless/ath/ath11k/qmi.h +++ b/drivers/net/wireless/ath/ath11k/qmi.h -@@ -32,9 +32,17 @@ +@@ -34,9 +34,17 @@ #define ATH11K_QMI_DEFAULT_QDSS_CONFIG_FILE_NAME "qdss_trace_config.bin" #ifdef CPTCFG_ATH11K_MEM_PROFILE_512M -+#define ATH11K_HOST_DDR_M3_OFFSET 0xC00000 -+#define ATH11K_HOST_DDR_QDSS_OFFSET 0xD00000 -+#define ATH11K_HOST_DDR_CALDB_OFFSET 0xE00000 -+#define ATH11K_HOST_DDR_PAGEABLE_OFFSET 0x1600000 - #define ATH11K_QMI_IPQ8074_M3_DUMP_ADDRESS 0x4E800000 - #define ATH11K_QMI_IPQ6018_M3_DUMP_ADDRESS 0x4E300000 ++#define ATH11K_HOST_DDR_M3_OFFSET 0xC00000 ++#define ATH11K_HOST_DDR_QDSS_OFFSET 0xD00000 ++#define ATH11K_HOST_DDR_CALDB_OFFSET 0xE00000 ++#define ATH11K_HOST_DDR_PAGEABLE_OFFSET 0x1600000 + #define ATH11K_QMI_IPQ8074_M3_DUMP_ADDRESS 0x4E800000 + #define ATH11K_QMI_IPQ6018_M3_DUMP_ADDRESS 0x4E300000 #else -+#define ATH11K_HOST_DDR_M3_OFFSET 0x2300000 -+#define ATH11K_HOST_DDR_QDSS_OFFSET 0x2400000 -+#define ATH11K_HOST_DDR_CALDB_OFFSET 0x2500000 -+#define ATH11K_HOST_DDR_PAGEABLE_OFFSET 0x2D00000 - #define ATH11K_QMI_IPQ8074_M3_DUMP_ADDRESS 0x51000000 - #define ATH11K_QMI_IPQ6018_M3_DUMP_ADDRESS 0x50100000 ++#define ATH11K_HOST_DDR_M3_OFFSET 0x2300000 ++#define ATH11K_HOST_DDR_QDSS_OFFSET 0x2400000 ++#define ATH11K_HOST_DDR_CALDB_OFFSET 0x2500000 ++#define ATH11K_HOST_DDR_PAGEABLE_OFFSET 0x2D00000 + #define ATH11K_QMI_IPQ8074_M3_DUMP_ADDRESS 0x51000000 + #define ATH11K_QMI_IPQ6018_M3_DUMP_ADDRESS 0x50100000 #endif -@@ -56,9 +64,8 @@ - #define ATH11K_FIRMWARE_MODE_OFF 4 - #define ATH11K_COLD_BOOT_FW_RESET_DELAY (60 * HZ) +@@ -60,9 +68,8 @@ --#define ATH11K_HOST_DDR_M3_OFFSET 0x2300000 + #define ATH11K_QMI_DEVICE_BAR_SIZE 0x200000 + +-#define ATH11K_HOST_DDR_M3_OFFSET 0x2300000 - struct ath11k_base; +extern unsigned int ath11k_host_ddr_addr; @@ -166,13 +166,13 @@ Signed-off-by: Anilkumar Kolli ATH11K_QMI_FILE_TYPE_BDF_GOLDEN, --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c -@@ -1416,8 +1416,7 @@ static int ath11k_pci_probe(struct pci_d +@@ -784,8 +784,7 @@ static int ath11k_pci_probe(struct pci_d * allocate memory for FW in DDR, set fixed_mem_region to true for * these pltforms supports reserved memory. */ - ret = of_property_read_u32(ab->dev->of_node, "base-addr", &addr); - if (ret == 0) + if (ath11k_host_ddr_addr || !ret) - ab->bus_params.fixed_mem_region = true; + ab->hw_params.fixed_mem_region = true; ret = ath11k_pci_claim(ab_pci, pdev); diff --git a/feeds/ipq95xx/mac80211/patches/qca/213-mac80211-ath11k-Add-HE-UL-MU-fixed-rate-setting.patch b/feeds/ipq95xx/mac80211/patches/qca/213-mac80211-ath11k-Add-HE-UL-MU-fixed-rate-setting.patch index 4134977da..31d5b9238 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/213-mac80211-ath11k-Add-HE-UL-MU-fixed-rate-setting.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/213-mac80211-ath11k-Add-HE-UL-MU-fixed-rate-setting.patch @@ -19,7 +19,7 @@ Signed-off-by: Muna Sinada --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -4098,6 +4098,20 @@ ath11k_mac_bitrate_mask_num_he_rates(str +@@ -4238,6 +4238,20 @@ ath11k_mac_bitrate_mask_num_he_rates(str } static int @@ -40,7 +40,7 @@ Signed-off-by: Muna Sinada ath11k_mac_set_peer_vht_fixed_rate(struct ath11k_vif *arvif, struct ieee80211_sta *sta, const struct cfg80211_bitrate_mask *mask, -@@ -7512,10 +7526,11 @@ ath11k_mac_set_auto_rate_gi_ltf(struct a +@@ -7935,10 +7949,11 @@ ath11k_mac_set_auto_rate_gi_ltf(struct a static int ath11k_mac_set_rate_params(struct ath11k_vif *arvif, u32 rate, u8 nss, u8 sgi, u8 ldpc, @@ -54,7 +54,7 @@ Signed-off-by: Muna Sinada int ret; lockdep_assert_held(&ar->conf_mutex); -@@ -7583,6 +7598,20 @@ static int ath11k_mac_set_rate_params(st +@@ -8006,6 +8021,20 @@ static int ath11k_mac_set_rate_params(st } } @@ -75,7 +75,7 @@ Signed-off-by: Muna Sinada return 0; } -@@ -7636,6 +7665,21 @@ ath11k_mac_he_mcs_range_present(struct a +@@ -8059,6 +8088,21 @@ ath11k_mac_he_mcs_range_present(struct a return true; } @@ -97,15 +97,16 @@ Signed-off-by: Muna Sinada static void ath11k_mac_set_bitrate_mask_iter(void *data, struct ieee80211_sta *sta) { -@@ -7672,13 +7716,15 @@ ath11k_mac_validate_vht_he_fixed_rate_se +@@ -8095,14 +8139,16 @@ ath11k_mac_validate_vht_he_fixed_rate_se const struct cfg80211_bitrate_mask *mask) { bool he_fixed_rate = false, vht_fixed_rate = false; + bool he_ul_fixed_rate = false; struct ath11k_peer *peer, *tmp; - const u16 *vht_mcs_mask, *he_mcs_mask; -- u8 vht_nss, he_nss; + const u16 *vht_mcs_mask, *he_mcs_mask, *he_ul_mcs_mask; + struct ieee80211_link_sta *deflink; +- u8 vht_nss, he_nss; + u8 vht_nss, he_nss, he_ul_nss; bool ret = true; @@ -115,7 +116,7 @@ Signed-off-by: Muna Sinada if (ath11k_mac_bitrate_mask_num_vht_rates(ar, band, mask) == 1) vht_fixed_rate = true; -@@ -7686,11 +7732,15 @@ ath11k_mac_validate_vht_he_fixed_rate_se +@@ -8110,11 +8156,15 @@ ath11k_mac_validate_vht_he_fixed_rate_se if (ath11k_mac_bitrate_mask_num_he_rates(ar, band, mask) == 1) he_fixed_rate = true; @@ -132,22 +133,22 @@ Signed-off-by: Muna Sinada rcu_read_lock(); spin_lock_bh(&ar->ab->base_lock); -@@ -7706,6 +7756,14 @@ ath11k_mac_validate_vht_he_fixed_rate_se +@@ -8133,6 +8183,14 @@ ath11k_mac_validate_vht_he_fixed_rate_se ret = false; goto out; } + /* TODO: + check when UL is valid + */ -+ if (he_ul_fixed_rate && (!peer->sta->he_cap.has_he || -+ peer->sta->rx_nss < he_ul_nss)) { ++ if (he_ul_fixed_rate && (!peer->sta->deflink.he_cap.has_he || ++ peer->sta->deflink.rx_nss < he_ul_nss)) { + ret = false; + goto out; + } } } -@@ -7774,15 +7832,17 @@ ath11k_mac_op_set_bitrate_mask(struct ie +@@ -8202,15 +8260,17 @@ ath11k_mac_op_set_bitrate_mask(struct ie const u8 *ht_mcs_mask; const u16 *vht_mcs_mask; const u16 *he_mcs_mask; @@ -167,15 +168,15 @@ Signed-off-by: Muna Sinada bool he_fixed_rate = false; if (ath11k_mac_vif_chan(vif, &def)) -@@ -7792,6 +7852,7 @@ ath11k_mac_op_set_bitrate_mask(struct ie +@@ -8221,6 +8281,7 @@ ath11k_mac_op_set_bitrate_mask(struct ie ht_mcs_mask = mask->control[band].ht_mcs; vht_mcs_mask = mask->control[band].vht_mcs; he_mcs_mask = mask->control[band].he_mcs; + he_ul_mcs_mask = mask->control[band].he_ul_mcs; - ldpc = !!(ar->ht_cap_info & WMI_HT_CAP_LDPC); + ldpc = !!(cap->band[band].ht_cap_info & WMI_HT_CAP_TX_LDPC); sgi = mask->control[band].gi; -@@ -7801,6 +7862,23 @@ ath11k_mac_op_set_bitrate_mask(struct ie +@@ -8230,6 +8291,23 @@ ath11k_mac_op_set_bitrate_mask(struct ie he_gi = mask->control[band].he_gi; he_ltf = mask->control[band].he_ltf; @@ -197,9 +198,9 @@ Signed-off-by: Muna Sinada + } + /* mac80211 doesn't support sending a fixed HT/VHT MCS alone, rather it - * requires passing atleast one of used basic rates along with them. + * requires passing at least one of used basic rates along with them. * Fixed rate setting across different preambles(legacy, HT, VHT) is -@@ -7906,9 +7984,10 @@ ath11k_mac_op_set_bitrate_mask(struct ie +@@ -8335,9 +8413,10 @@ ath11k_mac_op_set_bitrate_mask(struct ie mutex_lock(&ar->conf_mutex); ret = ath11k_mac_set_rate_params(arvif, rate, nss, sgi, ldpc, he_gi, @@ -214,7 +215,7 @@ Signed-off-by: Muna Sinada --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -1080,6 +1080,7 @@ enum wmi_tlv_vdev_param { +@@ -1078,6 +1078,7 @@ enum wmi_tlv_vdev_param { WMI_VDEV_PARAM_BA_MODE = 0x7e, WMI_VDEV_PARAM_AUTORATE_MISC_CFG = 0x80, WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE = 0x87, @@ -224,7 +225,7 @@ Signed-off-by: Muna Sinada WMI_VDEV_PARAM_BSS_COLOR, --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h -@@ -716,6 +716,7 @@ struct cfg80211_bitrate_mask { +@@ -771,6 +771,7 @@ struct cfg80211_bitrate_mask { enum nl80211_txrate_gi gi; enum nl80211_he_gi he_gi; enum nl80211_he_ltf he_ltf; @@ -234,7 +235,7 @@ Signed-off-by: Muna Sinada --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h -@@ -4971,6 +4971,7 @@ enum nl80211_key_attributes { +@@ -5154,6 +5154,7 @@ enum nl80211_key_attributes { * see &struct nl80211_txrate_he * @NL80211_TXRATE_HE_GI: configure HE GI, 0.8us, 1.6us and 3.2us. * @NL80211_TXRATE_HE_LTF: configure HE LTF, 1XLTF, 2XLTF and 4XLTF. @@ -242,7 +243,7 @@ Signed-off-by: Muna Sinada * @__NL80211_TXRATE_AFTER_LAST: internal * @NL80211_TXRATE_MAX: highest TX rate attribute */ -@@ -4983,6 +4984,7 @@ enum nl80211_tx_rate_attributes { +@@ -5166,6 +5167,7 @@ enum nl80211_tx_rate_attributes { NL80211_TXRATE_HE, NL80211_TXRATE_HE_GI, NL80211_TXRATE_HE_LTF, @@ -252,7 +253,7 @@ Signed-off-by: Muna Sinada __NL80211_TXRATE_AFTER_LAST, --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c -@@ -386,6 +386,10 @@ static const struct nla_policy nl80211_t +@@ -395,6 +395,10 @@ static const struct nla_policy nl80211_t [NL80211_TXRATE_HE_LTF] = NLA_POLICY_RANGE(NLA_U8, NL80211_RATE_INFO_HE_1XLTF, NL80211_RATE_INFO_HE_4XLTF), @@ -263,7 +264,7 @@ Signed-off-by: Muna Sinada }; static const struct nla_policy -@@ -4962,6 +4966,14 @@ static int nl80211_parse_tx_bitrate_mask +@@ -5130,6 +5134,15 @@ static int nl80211_parse_tx_bitrate_mask mask->control[band].he_ltf = nla_get_u8(tb[NL80211_TXRATE_HE_LTF]); @@ -271,7 +272,8 @@ Signed-off-by: Muna Sinada + if (!he_set_mcs_mask( + info, wdev, sband, + nla_data(tb[NL80211_TXRATE_HE_UL]), -+ mask->control[band].he_ul_mcs)) ++ mask->control[band].he_ul_mcs, ++ link_id)) + return -EINVAL; + } + diff --git a/feeds/ipq95xx/mac80211/patches/qca/214-ath11k-Enable-WMI-based-FW-Logging.patch b/feeds/ipq95xx/mac80211/patches/qca/214-ath11k-Enable-WMI-based-FW-Logging.patch index 4c3add6ca..011c12e99 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/214-ath11k-Enable-WMI-based-FW-Logging.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/214-ath11k-Enable-WMI-based-FW-Logging.patch @@ -24,70 +24,71 @@ Signed-off-by: Sriram R --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -123,6 +123,7 @@ static const struct ath11k_hw_params ath +@@ -120,6 +120,7 @@ static const struct ath11k_hw_params ath + .hal_params = &ath11k_hw_hal_params_ipq8074, .supports_dynamic_smps_6ghz = false, .alloc_cacheable_memory = true, - .wakeup_mhi = false, + .ce_fwlog_enable = false, .supports_rssi_stats = false, .fw_wmi_diag_event = false, .current_cc_support = false, -@@ -192,6 +193,7 @@ static const struct ath11k_hw_params ath +@@ -195,6 +196,7 @@ static const struct ath11k_hw_params ath + .hal_params = &ath11k_hw_hal_params_ipq8074, .supports_dynamic_smps_6ghz = false, .alloc_cacheable_memory = true, - .wakeup_mhi = false, + .ce_fwlog_enable = false, .supports_rssi_stats = false, .fw_wmi_diag_event = false, .current_cc_support = false, -@@ -258,6 +260,7 @@ static const struct ath11k_hw_params ath +@@ -267,6 +269,7 @@ static const struct ath11k_hw_params ath + .hal_params = &ath11k_hw_hal_params_qca6390, .supports_dynamic_smps_6ghz = false, .alloc_cacheable_memory = false, - .wakeup_mhi = true, + .ce_fwlog_enable = false, .supports_rssi_stats = true, .fw_wmi_diag_event = true, .current_cc_support = true, -@@ -325,6 +328,7 @@ static const struct ath11k_hw_params ath +@@ -340,6 +343,7 @@ static const struct ath11k_hw_params ath + .hal_params = &ath11k_hw_hal_params_ipq8074, .supports_dynamic_smps_6ghz = true, .alloc_cacheable_memory = true, - .wakeup_mhi = false, + .ce_fwlog_enable = true, .supports_rssi_stats = false, .fw_wmi_diag_event = false, .current_cc_support = false, -@@ -391,6 +395,7 @@ static const struct ath11k_hw_params ath +@@ -412,6 +416,7 @@ static const struct ath11k_hw_params ath + .hal_params = &ath11k_hw_hal_params_qca6390, .supports_dynamic_smps_6ghz = false, .alloc_cacheable_memory = false, - .wakeup_mhi = true, -+ .ce_fwlog_enable = true, - .supports_rssi_stats = true, - .fw_wmi_diag_event = true, - .current_cc_support = true, -@@ -456,6 +461,7 @@ static const struct ath11k_hw_params ath - .supports_dynamic_smps_6ghz = false, - .alloc_cacheable_memory = false, - .wakeup_mhi = true, + .ce_fwlog_enable = false, .supports_rssi_stats = true, .fw_wmi_diag_event = true, .current_cc_support = true, -@@ -507,12 +513,14 @@ static const struct ath11k_hw_params ath +@@ -483,6 +488,7 @@ static const struct ath11k_hw_params ath + .hal_params = &ath11k_hw_hal_params_qca6390, + .supports_dynamic_smps_6ghz = false, + .alloc_cacheable_memory = false, ++ .ce_fwlog_enable = false, + .supports_rssi_stats = true, + .fw_wmi_diag_event = true, + .current_cc_support = true, +@@ -552,6 +558,7 @@ static const struct ath11k_hw_params ath + .hal_params = &ath11k_hw_hal_params_qca6390, + .supports_dynamic_smps_6ghz = false, + .alloc_cacheable_memory = false, ++ .ce_fwlog_enable = false, + .supports_rssi_stats = true, + .fw_wmi_diag_event = false, + .current_cc_support = true, +@@ -614,6 +621,7 @@ static const struct ath11k_hw_params ath .cold_boot_calib = true, .fix_l1ss = true, .alloc_cacheable_memory = true, -+ .ce_fwlog_enable = false, ++ .ce_fwlog_enable = true, .rxdma1_enable = true, .num_rxmda_per_pdev = 1, .rx_mac_buf_ring = false, - .vdev_start_delay = false, - .htt_peer_map_v2 = true, - .reo_dest_ring_map_shift = HAL_IPQ5018_REO_DEST_RING_CTRL_HASH_RING_SHIFT, -+ .ce_fwlog_enable = true, - } - }; - -@@ -1247,7 +1255,6 @@ int ath11k_core_ssr_notifier_cb(struct n +@@ -1527,7 +1535,6 @@ int ath11k_core_ssr_notifier_cb(struct n struct platform_device *pdev = NULL; struct platform_device *ssr_pdev = (struct platform_device *)data; #endif @@ -95,7 +96,7 @@ Signed-off-by: Sriram R if (test_bit(ATH11K_FLAG_FW_RESTART_FOR_HOST, &qmi->ab->dev_flags)) { return 0; } -@@ -1316,6 +1323,10 @@ void ath11k_core_wait_dump_collect(struc +@@ -1596,6 +1603,10 @@ void ath11k_core_wait_dump_collect(struc #endif EXPORT_SYMBOL(ath11k_core_wait_dump_collect); @@ -106,9 +107,9 @@ Signed-off-by: Sriram R int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab) { int ret; -@@ -1372,6 +1383,14 @@ int ath11k_core_qmi_firmware_ready(struc - goto err_core_stop; - } +@@ -1652,6 +1663,14 @@ int ath11k_core_qmi_firmware_ready(struc + + ath11k_config_qdss(ab); + if (ab->hw_params.ce_fwlog_enable && ce_fwlog) { + ret = ath11k_enable_fwlog(ab); @@ -123,8 +124,8 @@ Signed-off-by: Sriram R return 0; --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h -@@ -210,6 +210,7 @@ struct ath11k_hw_params { - bool wakeup_mhi; +@@ -207,6 +207,7 @@ struct ath11k_hw_params { + bool alloc_cacheable_memory; u32 m3_addr; u8 reo_dest_ring_map_shift; + bool ce_fwlog_enable; @@ -133,7 +134,7 @@ Signed-off-by: Sriram R bool current_cc_support; --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c -@@ -2101,6 +2101,50 @@ struct qmi_elem_info qmi_wlanfw_qdss_tra +@@ -2169,6 +2169,50 @@ struct qmi_elem_info qmi_wlanfw_qdss_tra }, }; @@ -184,7 +185,7 @@ Signed-off-by: Sriram R int wlfw_send_qdss_trace_config_download_req(struct ath11k_base *ab, const u8 *buffer, unsigned int file_len) { -@@ -4148,6 +4192,55 @@ static void ath11k_qmi_driver_event_work +@@ -4355,6 +4399,55 @@ static void ath11k_qmi_driver_event_work spin_unlock(&qmi->event_lock); } @@ -242,7 +243,7 @@ Signed-off-by: Sriram R int ret; --- a/drivers/net/wireless/ath/ath11k/qmi.h +++ b/drivers/net/wireless/ath/ath11k/qmi.h -@@ -208,6 +208,18 @@ struct qmi_wlanfw_m3_dump_upload_done_re +@@ -220,6 +220,18 @@ struct qmi_wlanfw_m3_dump_upload_done_re struct qmi_response_type_v01 resp; }; @@ -261,13 +262,11 @@ Signed-off-by: Sriram R #define QMI_WLANFW_QDSS_TRACE_MODE_REQ_V01 0x0045 #define QMI_WLANFW_QDSS_TRACE_MODE_REQ_MSG_V01_MAX_LEN 18 #define QMI_WLANFW_QDSS_TRACE_MODE_RESP_MSG_V01_MAX_LEN 7 -@@ -639,6 +651,7 @@ int wlfw_send_qdss_trace_config_download +@@ -665,4 +677,5 @@ int wlfw_send_qdss_trace_config_download int ath11k_send_qdss_trace_mode_req(struct ath11k_base *ab, enum wlfw_qdss_trace_mode_enum_v01 mode); int ath11k_qmi_fwreset_from_cold_boot(struct ath11k_base *ab); +int ath11k_enable_fwlog(struct ath11k_base *ab); - - #endif --- a/drivers/net/wireless/ath/ath11k/testmode.c +++ b/drivers/net/wireless/ath/ath11k/testmode.c @@ -361,7 +360,7 @@ Signed-off-by: Sriram R __ATH11K_TM_ATTR_AFTER_LAST, --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -8195,13 +8195,6 @@ static void ath11k_wmi_event_wow_wakeup_ +@@ -8228,13 +8228,6 @@ static void ath11k_wmi_event_wow_wakeup_ complete(&ab->wow.wakeup_completed); } @@ -372,10 +371,10 @@ Signed-off-by: Sriram R - trace_ath11k_wmi_diag(ab, skb->data, skb->len); -} - - static int ath11k_tpc_get_reg_pwr(struct ath11k_base *ab, - struct wmi_tpc_stats_event *tpc_stats, - struct wmi_max_reg_power_allowed *ev) -@@ -8755,6 +8748,29 @@ static void ath11k_wmi_wds_peer_event(st + static const char *ath11k_wmi_twt_add_dialog_event_status(u32 status) + { + switch (status) { +@@ -8867,6 +8860,29 @@ static void ath11k_wmi_wds_peer_event(st wds_addr_arg.dst_macaddr); } diff --git a/feeds/ipq95xx/mac80211/patches/qca/214-ath11k-qos-null-frame-tx-over-wmi.patch b/feeds/ipq95xx/mac80211/patches/qca/214-ath11k-qos-null-frame-tx-over-wmi.patch index 13cb7caa4..c35541aa4 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/214-ath11k-qos-null-frame-tx-over-wmi.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/214-ath11k-qos-null-frame-tx-over-wmi.patch @@ -22,7 +22,7 @@ Signed-off-by: Sowmiya Sree Elavalagan --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -5900,6 +5900,16 @@ static int ath11k_mac_mgmt_tx_wmi(struct +@@ -5926,6 +5926,16 @@ static int ath11k_mac_mgmt_tx_wmi(struct ATH11K_SKB_CB(skb)->paddr = paddr; @@ -39,7 +39,7 @@ Signed-off-by: Sowmiya Sree Elavalagan ret = ath11k_wmi_mgmt_send(ar, arvif->vdev_id, buf_id, skb); if (ret) { ath11k_warn(ar->ab, "failed to send mgmt frame: %d\n", ret); -@@ -5966,8 +5976,8 @@ static void ath11k_mgmt_over_wmi_tx_work +@@ -5993,8 +6003,8 @@ static void ath11k_mgmt_over_wmi_tx_work } } @@ -50,7 +50,7 @@ Signed-off-by: Sowmiya Sree Elavalagan { struct sk_buff_head *q = &ar->wmi_mgmt_tx_queue; -@@ -6086,7 +6096,7 @@ static void ath11k_mac_op_tx(struct ieee +@@ -6056,7 +6066,7 @@ static void ath11k_mac_op_tx(struct ieee } else if (ieee80211_is_mgmt(hdr->frame_control)) { frm_type = FIELD_GET(IEEE80211_FCTL_STYPE, hdr->frame_control); is_prb_rsp = ieee80211_is_probe_resp(hdr->frame_control); @@ -59,7 +59,7 @@ Signed-off-by: Sowmiya Sree Elavalagan if (ret) { if (ret != -EBUSY) ath11k_warn(ar->ab, "failed to queue management frame %d\n", -@@ -6101,6 +6111,20 @@ static void ath11k_mac_op_tx(struct ieee +@@ -6071,6 +6081,20 @@ static void ath11k_mac_op_tx(struct ieee spin_unlock_bh(&ar->data_lock); } return; @@ -82,7 +82,7 @@ Signed-off-by: Sowmiya Sree Elavalagan if (control->sta) --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -112,7 +112,7 @@ static const struct wmi_tlv_policy wmi_t +@@ -113,7 +113,7 @@ static const struct wmi_tlv_policy wmi_t [WMI_TAG_MGMT_RX_HDR] = { .min_len = sizeof(struct wmi_mgmt_rx_hdr) }, [WMI_TAG_MGMT_TX_COMPL_EVENT] @@ -91,7 +91,7 @@ Signed-off-by: Sowmiya Sree Elavalagan [WMI_TAG_SCAN_EVENT] = { .min_len = sizeof(struct wmi_scan_event) }, [WMI_TAG_PEER_STA_KICKOUT_EVENT] -@@ -682,6 +682,55 @@ int ath11k_wmi_mgmt_send(struct ath11k * +@@ -700,6 +700,55 @@ int ath11k_wmi_mgmt_send(struct ath11k * return ret; } @@ -147,7 +147,7 @@ Signed-off-by: Sowmiya Sree Elavalagan int ath11k_wmi_vdev_create(struct ath11k *ar, u8 *macaddr, struct vdev_create_params *param) { -@@ -5566,7 +5615,7 @@ static int ath11k_pull_mgmt_rx_params_tl +@@ -5759,7 +5808,7 @@ static int ath11k_pull_mgmt_rx_params_tl return 0; } @@ -156,7 +156,7 @@ Signed-off-by: Sowmiya Sree Elavalagan { struct sk_buff *msdu; struct ieee80211_tx_info *info; -@@ -5603,6 +5652,11 @@ static int wmi_process_mgmt_tx_comp(stru +@@ -5796,6 +5845,11 @@ static int wmi_process_mgmt_tx_comp(stru info->status.is_valid_ack_signal = true; } @@ -168,7 +168,7 @@ Signed-off-by: Sowmiya Sree Elavalagan hdr = (struct ieee80211_hdr *)msdu->data; frm_type = FIELD_GET(IEEE80211_FCTL_STYPE, hdr->frame_control); -@@ -5621,10 +5675,13 @@ static int wmi_process_mgmt_tx_comp(stru +@@ -5814,10 +5868,13 @@ static int wmi_process_mgmt_tx_comp(stru arvif = ath11k_vif_to_arvif(vif); mgmt_stats = &arvif->mgmt_stats; @@ -186,7 +186,7 @@ Signed-off-by: Sowmiya Sree Elavalagan spin_unlock_bh(&ar->data_lock); skip_mgmt_stats: -@@ -5638,7 +5695,7 @@ skip_mgmt_stats: +@@ -5831,7 +5888,7 @@ skip_mgmt_stats: ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi mgmt tx comp pending %d desc id %d\n", @@ -195,7 +195,7 @@ Signed-off-by: Sowmiya Sree Elavalagan if (!num_mgmt) wake_up(&ar->txmgmt_empty_waitq); -@@ -5646,12 +5703,13 @@ skip_mgmt_stats: +@@ -5839,12 +5896,13 @@ skip_mgmt_stats: return 0; } @@ -213,7 +213,7 @@ Signed-off-by: Sowmiya Sree Elavalagan int ret; tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); -@@ -5661,7 +5719,7 @@ static int ath11k_pull_mgmt_tx_compl_par +@@ -5854,7 +5912,7 @@ static int ath11k_pull_mgmt_tx_compl_par return ret; } @@ -222,7 +222,7 @@ Signed-off-by: Sowmiya Sree Elavalagan if (!ev) { ath11k_warn(ab, "failed to fetch mgmt tx compl ev"); kfree(tb); -@@ -7374,10 +7432,11 @@ exit: +@@ -7581,10 +7639,11 @@ exit: static void ath11k_mgmt_tx_compl_event(struct ath11k_base *ab, struct sk_buff *skb) { @@ -236,7 +236,7 @@ Signed-off-by: Sowmiya Sree Elavalagan ath11k_warn(ab, "failed to extract mgmt tx compl event"); return; } -@@ -7390,7 +7449,7 @@ static void ath11k_mgmt_tx_compl_event(s +@@ -7597,7 +7656,7 @@ static void ath11k_mgmt_tx_compl_event(s goto exit; } @@ -245,7 +245,7 @@ Signed-off-by: Sowmiya Sree Elavalagan ath11k_dbg(ab, ATH11K_DBG_MGMT, "mgmt tx compl ev pdev_id %d, desc_id %d, status %d", -@@ -7401,6 +7460,36 @@ exit: +@@ -7608,6 +7667,36 @@ exit: rcu_read_unlock(); } @@ -282,107 +282,7 @@ Signed-off-by: Sowmiya Sree Elavalagan static struct ath11k *ath11k_get_ar_on_scan_state(struct ath11k_base *ab, u32 vdev_id, enum ath11k_scan_state state) -@@ -7782,47 +7871,67 @@ static void ath11k_vdev_install_key_comp - rcu_read_unlock(); - } - --static void ath11k_service_available_event(struct ath11k_base *ab, struct sk_buff *skb) -+static int ath11k_wmi_tlv_services_parser(struct ath11k_base *ab, -+ u16 tag, u16 len, -+ const void *ptr, void *data) - { -- const void **tb; - const struct wmi_service_available_event *ev; -- int ret; -+ u32 *wmi_ext2_service_bitmap; - int i, j; - -- tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); -- if (IS_ERR(tb)) { -- ret = PTR_ERR(tb); -- ath11k_warn(ab, "failed to parse tlv: %d\n", ret); -- return; -- } -+ switch (tag) { -+ case WMI_TAG_SERVICE_AVAILABLE_EVENT: -+ ev = (struct wmi_service_available_event *)ptr; -+ for (i = 0, j = WMI_MAX_SERVICE; -+ i < WMI_SERVICE_SEGMENT_BM_SIZE32 && j < WMI_MAX_EXT_SERVICE; -+ i++) { -+ do { -+ if (ev->wmi_service_segment_bitmap[i] & -+ BIT(j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32)) -+ set_bit(j, ab->wmi_ab.svc_map); -+ } while (++j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32); -+ } - -- ev = tb[WMI_TAG_SERVICE_AVAILABLE_EVENT]; -- if (!ev) { -- ath11k_warn(ab, "failed to fetch svc available ev"); -- kfree(tb); -- return; -- } -+ ath11k_dbg(ab, ATH11K_DBG_WMI, -+ "wmi_ext_service_bitmap 0:0x%x, 1:0x%x, 2:0x%x, 3:0x%x", -+ ev->wmi_service_segment_bitmap[0], -+ ev->wmi_service_segment_bitmap[1], -+ ev->wmi_service_segment_bitmap[2], -+ ev->wmi_service_segment_bitmap[3]); - -- /* TODO: Use wmi_service_segment_offset information to get the service -- * especially when more services are advertised in multiple sevice -- * available events. -- */ -- for (i = 0, j = WMI_MAX_SERVICE; -- i < WMI_SERVICE_SEGMENT_BM_SIZE32 && j < WMI_MAX_EXT_SERVICE; -- i++) { -- do { -- if (ev->wmi_service_segment_bitmap[i] & -- BIT(j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32)) -- set_bit(j, ab->wmi_ab.svc_map); -- } while (++j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32); -+ break; -+ -+ case WMI_TAG_ARRAY_UINT32: -+ wmi_ext2_service_bitmap = (u32 *)ptr; -+ for (i = 0, j = WMI_MAX_EXT_SERVICE; -+ i < WMI_SERVICE_SEGMENT_BM_SIZE32 && j < WMI_MAX_EXT2_SERVICE; -+ i++) { -+ do { -+ if (wmi_ext2_service_bitmap[i] & -+ BIT(j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32)) -+ set_bit(j, ab->wmi_ab.svc_map); -+ } while (++j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32); -+ } -+ -+ ath11k_dbg(ab, ATH11K_DBG_WMI, -+ "wmi_ext2_service__bitmap 0:0x%x, 1:0x%x, 2:0x%x, 3:0x%x", -+ wmi_ext2_service_bitmap[0], wmi_ext2_service_bitmap[1], -+ wmi_ext2_service_bitmap[2], wmi_ext2_service_bitmap[3]); -+ -+ break; - } -+ return 0; -+} - -- ath11k_dbg(ab, ATH11K_DBG_WMI, -- "wmi_ext_service_bitmap 0:0x%x, 1:0x%x, 2:0x%x, 3:0x%x", -- ev->wmi_service_segment_bitmap[0], ev->wmi_service_segment_bitmap[1], -- ev->wmi_service_segment_bitmap[2], ev->wmi_service_segment_bitmap[3]); -+static void ath11k_service_available_event(struct ath11k_base *ab, struct sk_buff *skb) -+{ -+ int ret = 0; - -- kfree(tb); -+ ret = ath11k_wmi_tlv_iter(ab, skb->data, skb->len, -+ ath11k_wmi_tlv_services_parser, -+ NULL); -+ if (ret) -+ ath11k_warn(ab, "failed to parse services available tlv %d\n", ret); - } - - static void ath11k_peer_assoc_conf_event(struct ath11k_base *ab, struct sk_buff *skb) -@@ -8921,6 +9030,9 @@ static void ath11k_wmi_tlv_op_rx(struct +@@ -9214,6 +9303,9 @@ static void ath11k_wmi_tlv_op_rx(struct case WMI_MUEDCA_PARAMS_CONFIG_EVENTID: ath11k_wmi_pdev_update_muedca_params_status_event(ab, skb); break; @@ -394,7 +294,7 @@ Signed-off-by: Sowmiya Sree Elavalagan ath11k_dbg(ab, ATH11K_DBG_WMI, "Unknown eventid: 0x%x\n", id); --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -345,6 +345,7 @@ enum wmi_tlv_cmd_id { +@@ -351,6 +351,7 @@ enum wmi_tlv_cmd_id { WMI_BSS_COLOR_CHANGE_ENABLE_CMDID, WMI_VDEV_BCN_OFFLOAD_QUIET_CONFIG_CMDID, WMI_FILS_DISCOVERY_TMPL_CMDID, @@ -402,7 +302,7 @@ Signed-off-by: Sowmiya Sree Elavalagan WMI_ADDBA_CLEAR_RESP_CMDID = WMI_TLV_CMD(WMI_GRP_BA_NEG), WMI_ADDBA_SEND_CMDID, WMI_ADDBA_STATUS_CMDID, -@@ -677,6 +678,8 @@ enum wmi_tlv_event_id { +@@ -683,6 +684,8 @@ enum wmi_tlv_event_id { WMI_TBTTOFFSET_EXT_UPDATE_EVENTID, WMI_OFFCHAN_DATA_TX_COMPLETION_EVENTID, WMI_HOST_FILS_DISCOVERY_EVENTID, @@ -411,23 +311,25 @@ Signed-off-by: Sowmiya Sree Elavalagan WMI_TX_DELBA_COMPLETE_EVENTID = WMI_TLV_CMD(WMI_GRP_BA_NEG), WMI_TX_ADDBA_COMPLETE_EVENTID, WMI_BA_RSP_SSN_EVENTID, -@@ -1869,6 +1872,9 @@ enum wmi_tlv_tag { +@@ -1875,6 +1878,9 @@ enum wmi_tlv_tag { WMI_TAG_TPC_STATS_REG_PWR_ALLOWED, WMI_TAG_TPC_STATS_RATES_ARRAY, WMI_TAG_TPC_STATS_CTL_PWR_TABLE_EVENT, + /* TODO add all the missing cmds */ + WMI_TAG_QOS_NULL_FRAME_TX_SEND = 0x3A6, + WMI_TAG_QOS_NULL_FRAME_TX_STATUS, - + WMI_TAG_PDEV_SET_BIOS_SAR_TABLE_CMD = 0x3D8, + WMI_TAG_PDEV_SET_BIOS_GEO_TABLE_CMD, WMI_TAG_MAX - }; -@@ -2094,8 +2100,21 @@ enum wmi_tlv_service { +@@ -2102,9 +2108,22 @@ enum wmi_tlv_service { WMI_TLV_SERVICE_FREQINFO_IN_METADATA = 219, WMI_TLV_SERVICE_EXT2_MSG = 220, WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT = 249, + WMI_TLV_SERVICE_CONFIGURE_ROAM_TRIGGER_PARAM_SUPPORT = 254, + WMI_TLV_SERVICE_CFR_TA_RA_AS_FP_SUPPORT = 255, -+ WMI_MAX_EXT_SERVICE = 256, + + /* The second 128 bits */ + WMI_MAX_EXT_SERVICE = 256, + + WMI_TLV_SERVICE_CFR_CAPTURE_COUNT_SUPPORT = 256, + WMI_TLV_SERVICE_OCV_SUPPORT = 257, @@ -438,13 +340,11 @@ Signed-off-by: Sowmiya Sree Elavalagan + WMI_TLV_SERVICE_FSE_CMEM_ALLOC_SUPPORT = 262, + WMI_TLV_SERVICE_PASSIVE_SCAN_START_TIME_ENHANCE = 263, + WMI_TLV_SERVICE_QOS_NULL_FRAME_TX_OVER_WMI = 264, ++ + WMI_TLV_SERVICE_BIOS_SAR_SUPPORT = 326, -- WMI_MAX_EXT_SERVICE -+ WMI_MAX_EXT2_SERVICE - }; - - enum wmi_unit_test_cmdid { -@@ -3795,6 +3814,7 @@ struct wmi_scan_prob_req_oui_cmd { + /* The third 128 bits */ +@@ -3800,6 +3819,7 @@ struct wmi_scan_prob_req_oui_cmd { } __packed; #define WMI_MGMT_SEND_DOWNLD_LEN 64 @@ -452,7 +352,7 @@ Signed-off-by: Sowmiya Sree Elavalagan #define WMI_TX_PARAMS_DWORD0_POWER GENMASK(7, 0) #define WMI_TX_PARAMS_DWORD0_MCS_MASK GENMASK(19, 8) -@@ -3805,9 +3825,10 @@ struct wmi_scan_prob_req_oui_cmd { +@@ -3810,9 +3830,10 @@ struct wmi_scan_prob_req_oui_cmd { #define WMI_TX_PARAMS_DWORD1_BW_MASK GENMASK(14, 8) #define WMI_TX_PARAMS_DWORD1_PREAMBLE_TYPE GENMASK(19, 15) #define WMI_TX_PARAMS_DWORD1_FRAME_TYPE BIT(20) @@ -465,7 +365,7 @@ Signed-off-by: Sowmiya Sree Elavalagan u32 tlv_header; u32 tx_params_dword0; u32 tx_params_dword1; -@@ -4667,7 +4688,7 @@ struct wmi_rssi_ctl_ext { +@@ -4672,7 +4693,7 @@ struct wmi_rssi_ctl_ext { u32 rssi_ctl_ext[MAX_ANTENNA_EIGHT - ATH_MAX_ANTENNA]; }; @@ -474,7 +374,7 @@ Signed-off-by: Sowmiya Sree Elavalagan u32 desc_id; u32 status; u32 pdev_id; -@@ -5807,6 +5828,17 @@ enum ath11k_wmi_tpc_stats_ctl_array { +@@ -5908,6 +5929,17 @@ enum ath11k_wmi_tpc_stats_ctl_array { ATH11K_TPC_STATS_CTL_160ARRAY, }; @@ -492,16 +392,7 @@ Signed-off-by: Sowmiya Sree Elavalagan #define WMI_MAX_MEM_REQS 32 #define MAX_RADIOS 3 -@@ -5822,7 +5854,7 @@ struct ath11k_wmi_base { - - struct completion service_ready; - struct completion unified_ready; -- DECLARE_BITMAP(svc_map, WMI_MAX_EXT_SERVICE); -+ DECLARE_BITMAP(svc_map, WMI_MAX_EXT2_SERVICE); - wait_queue_head_t tx_credits_wq; - const struct wmi_peer_flags_map *peer_flags; - u32 num_mem_chunks; -@@ -6003,6 +6035,8 @@ int ath11k_wmi_cmd_send(struct ath11k_pd +@@ -6496,6 +6528,8 @@ int ath11k_wmi_cmd_send(struct ath11k_pd struct sk_buff *ath11k_wmi_alloc_skb(struct ath11k_wmi_base *wmi_sc, u32 len); int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id, struct sk_buff *frame); diff --git a/feeds/ipq95xx/mac80211/patches/qca/218-ath11k-add-support-to-enable-disable-color-collision.patch b/feeds/ipq95xx/mac80211/patches/qca/218-ath11k-add-support-to-enable-disable-color-collision.patch index 400d4ec37..817537247 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/218-ath11k-add-support-to-enable-disable-color-collision.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/218-ath11k-add-support-to-enable-disable-color-collision.patch @@ -16,15 +16,15 @@ Signed-off-by: Lavanya Suresh --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -6,6 +6,7 @@ - - #include - #include -+#include +@@ -9,6 +9,7 @@ + #include + #include #include - #include "mac.h" - #include "core.h" -@@ -47,6 +48,10 @@ ++#include + #include + #include + +@@ -54,6 +55,10 @@ .max_power = 30, \ } @@ -35,7 +35,7 @@ Signed-off-by: Lavanya Suresh static const struct ieee80211_channel ath11k_2ghz_channels[] = { CHAN2G(1, 2412, 0), CHAN2G(2, 2417, 0), -@@ -3537,7 +3542,7 @@ static void ath11k_mac_op_bss_info_chang +@@ -3559,7 +3564,7 @@ static void ath11k_mac_op_bss_info_chang ret = ath11k_wmi_send_obss_color_collision_cfg_cmd( ar, arvif->vdev_id, info->he_bss_color.color, ATH11K_BSS_COLOR_COLLISION_DETECTION_AP_PERIOD_MS, diff --git a/feeds/ipq95xx/mac80211/patches/qca/220-mac80211-disable-color-collision-detection-in-case-of-no-free-colors.patch b/feeds/ipq95xx/mac80211/patches/qca/220-mac80211-disable-color-collision-detection-in-case-of-no-free-colors.patch deleted file mode 100644 index ded1e97be..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/220-mac80211-disable-color-collision-detection-in-case-of-no-free-colors.patch +++ /dev/null @@ -1,111 +0,0 @@ -From eb1ad9bd9d72ca6fd8810890bf10def06fdcf632 Mon Sep 17 00:00:00 2001 -From: Lavanya Suresh -Date: Wed, 7 Oct 2020 13:45:16 +0530 -Subject: [PATCH] mac80211: disable color collision detection in case of no - free colors - -Send disable event in wmi collision detection cfg command to FW, -when there are no free colors available to select. - -It can be reenabled once new color is available. Send wmi collision -cfg command only if any value is changed. - -Signed-off-by: Lavanya Suresh ---- - include/linux/ieee80211.h | 1 + - include/net/cfg80211.h | 1 + - net/mac80211/cfg.c | 33 ++++++++++++++++++++++++++++++--- - net/wireless/nl80211.c | 5 +++++ - 4 files changed, 37 insertions(+), 3 deletions(-) - ---- a/include/linux/ieee80211.h -+++ b/include/linux/ieee80211.h -@@ -1874,6 +1874,7 @@ struct ieee80211_he_mcs_nss_supp { - __le16 tx_mcs_80p80; - } __packed; - -+#define HE_OPERATION_BSS_COLOR_DISABLED ((u32) BIT(31)) - /** - * struct ieee80211_he_operation - HE capabilities element - * ---- a/include/net/cfg80211.h -+++ b/include/net/cfg80211.h -@@ -1130,6 +1130,7 @@ struct cfg80211_beacon_data { - const u8 *civicloc; - struct cfg80211_mbssid_elems *mbssid_ies; - s8 ftm_responder; -+ u8 bss_color_info; - - size_t head_len, tail_len; - size_t beacon_ies_len; ---- a/net/mac80211/cfg.c -+++ b/net/mac80211/cfg.c -@@ -996,6 +996,8 @@ static int ieee80211_assign_beacon(struc - { - struct beacon_data *new, *old; - int new_head_len, new_tail_len; -+ const u8 *cap; -+ struct ieee80211_he_operation *he_oper = NULL; - int size, err; - u32 changed = BSS_CHANGED_BEACON; - -@@ -1084,6 +1086,26 @@ static int ieee80211_assign_beacon(struc - changed |= BSS_CHANGED_FTM_RESPONDER; - } - -+ if (params->bss_color_info == 1) { -+ cap = cfg80211_find_ext_ie(WLAN_EID_EXT_HE_OPERATION, params->tail, params->tail_len); -+ if (cap && cap[1] >= sizeof(*he_oper) + 1) -+ he_oper = (void *)(cap + 3); -+ -+ if (he_oper && -+ he_oper->he_oper_params & HE_OPERATION_BSS_COLOR_DISABLED) { -+ if (sdata->vif.bss_conf.he_bss_color.enabled) { -+ sdata->vif.bss_conf.he_bss_color.enabled = 0; -+ changed |= BSS_CHANGED_HE_BSS_COLOR; -+ } -+ } -+ else { -+ if(!sdata->vif.bss_conf.he_bss_color.enabled) { -+ sdata->vif.bss_conf.he_bss_color.enabled = 1; -+ changed |= BSS_CHANGED_HE_BSS_COLOR; -+ } -+ } -+ } -+ - rcu_assign_pointer(sdata->u.ap.beacon, new); - - if (old) -@@ -4272,9 +4294,15 @@ static void - ieee80211_color_change_bss_config_notify(struct ieee80211_sub_if_data *sdata, - u8 color, int enable, u32 changed) - { -- sdata->vif.bss_conf.he_bss_color.color = color; -- sdata->vif.bss_conf.he_bss_color.enabled = enable; -- changed |= BSS_CHANGED_HE_BSS_COLOR; -+ if (sdata->vif.bss_conf.he_bss_color.color != color) { -+ sdata->vif.bss_conf.he_bss_color.color = color; -+ changed |= BSS_CHANGED_HE_BSS_COLOR; -+ } -+ -+ if (sdata->vif.bss_conf.he_bss_color.enabled != enable) { -+ sdata->vif.bss_conf.he_bss_color.enabled = enable; -+ changed |= BSS_CHANGED_HE_BSS_COLOR; -+ } - - ieee80211_bss_info_change_notify(sdata, changed); - } ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -5243,6 +5243,11 @@ static int nl80211_parse_beacon(struct c - bcn->mbssid_ies = mbssid; - } - -+ if (attrs[NL80211_ATTR_HE_BSS_COLOR]) -+ bcn->bss_color_info = 1; -+ else -+ bcn->bss_color_info = 0; -+ - return 0; - } - diff --git a/feeds/ipq95xx/mac80211/patches/qca/221-ath11k-add-debugfs-interface-to-read-write-from-memo.patch b/feeds/ipq95xx/mac80211/patches/qca/221-ath11k-add-debugfs-interface-to-read-write-from-memo.patch index 2e81c1841..5add5fe95 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/221-ath11k-add-debugfs-interface-to-read-write-from-memo.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/221-ath11k-add-debugfs-interface-to-read-write-from-memo.patch @@ -19,9 +19,9 @@ Signed-off-by: Lavanya Suresh --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -488,6 +488,7 @@ struct ath11k_debug { - #endif - u32 rx_filter; +@@ -627,6 +627,7 @@ struct ath11k_debug { + u32 module_id_bitmap[MAX_MODULE_ID_BITMAP_WORDS]; + struct ath11k_debug_dbr *dbr_debug[WMI_DIRECT_BUF_MAX]; bool enable_m3_dump; + u32 mem_addr; }; @@ -29,7 +29,7 @@ Signed-off-by: Lavanya Suresh struct ath11k_per_peer_tx_stats { --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -13,6 +13,7 @@ +@@ -16,6 +16,7 @@ #include "debugfs_htt_stats.h" #include "peer.h" #include "pktlog.h" @@ -37,8 +37,8 @@ Signed-off-by: Lavanya Suresh struct dentry *debugfs_ath11k; -@@ -1924,6 +1925,103 @@ static const struct file_operations fops - .open = simple_open +@@ -2309,6 +2310,103 @@ static const struct file_operations fops + .llseek = default_llseek, }; +static ssize_t ath11k_athdiag_read(struct file *file, @@ -141,9 +141,9 @@ Signed-off-by: Lavanya Suresh static int ath11k_get_tpc_ctl_mode(struct wmi_tpc_stats_event *tpc_stats, u32 pream_idx, int *mode) { -@@ -2570,6 +2668,10 @@ int ath11k_debugfs_register(struct ath11 - debugfs_create_file("tpc_stats_type", 0600, ar->debug.debugfs_pdev, - ar, &fops_tpc_stats_type); +@@ -2966,6 +3064,10 @@ int ath11k_debugfs_register(struct ath11 + debugfs_create_file("nss_peer_stats_config", 0644, + ar->debug.debugfs_pdev, ar, &fops_nss_stats); + debugfs_create_file("athdiag", S_IRUSR | S_IWUSR, + ar->debug.debugfs_pdev, ar, @@ -154,7 +154,7 @@ Signed-off-by: Lavanya Suresh --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c -@@ -2100,6 +2100,157 @@ struct qmi_elem_info wlfw_ini_resp_msg_v +@@ -2213,6 +2213,157 @@ struct qmi_elem_info wlfw_ini_resp_msg_v }, }; @@ -312,7 +312,7 @@ Signed-off-by: Lavanya Suresh int wlfw_send_qdss_trace_config_download_req(struct ath11k_base *ab, const u8 *buffer, unsigned int file_len) { -@@ -3839,6 +3990,130 @@ free_event_data: +@@ -4210,6 +4361,130 @@ free_event_data: kfree(event_data); } @@ -445,7 +445,7 @@ Signed-off-by: Lavanya Suresh .type = QMI_INDICATION, --- a/drivers/net/wireless/ath/ath11k/qmi.h +++ b/drivers/net/wireless/ath/ath11k/qmi.h -@@ -260,6 +260,7 @@ struct qmi_wlanfw_qdss_trace_mode_resp_m +@@ -267,6 +267,7 @@ struct qmi_wlanfw_qdss_trace_mode_resp_m #define M3_DUMP_REGION_TYPE 0x3 #define CALDB_MEM_REGION_TYPE 0x4 #define QDSS_ETR_MEM_REGION_TYPE 0x6 @@ -453,7 +453,7 @@ Signed-off-by: Lavanya Suresh struct qmi_wlanfw_host_cap_req_msg_v01 { u8 num_clients_valid; -@@ -355,6 +356,10 @@ struct qmi_wlanfw_ind_register_resp_msg_ +@@ -362,6 +363,10 @@ struct qmi_wlanfw_ind_register_resp_msg_ #define QMI_WLFW_QDSS_TRACE_MEM_INFO_REQ_V01 0x0040 #define QMI_WLANFW_MAX_NUM_MEM_CFG_V01 2 #define QMI_WLANFW_MAX_STR_LEN_V01 16 @@ -464,7 +464,7 @@ Signed-off-by: Lavanya Suresh struct qmi_wlanfw_mem_cfg_s_v01 { u64 offset; -@@ -631,6 +636,30 @@ struct qmi_wlanfw_wlan_cfg_resp_msg_v01 +@@ -662,6 +667,30 @@ struct qmi_wlanfw_wlan_ini_resp_msg_v01 struct qmi_response_type_v01 resp; }; @@ -495,12 +495,10 @@ Signed-off-by: Lavanya Suresh int ath11k_qmi_firmware_start(struct ath11k_base *ab, u32 mode); void ath11k_qmi_firmware_stop(struct ath11k_base *ab); -@@ -645,6 +674,8 @@ int ath11k_send_qdss_trace_mode_req(stru +@@ -676,4 +705,6 @@ int ath11k_send_qdss_trace_mode_req(stru enum wlfw_qdss_trace_mode_enum_v01 mode); int ath11k_qmi_fwreset_from_cold_boot(struct ath11k_base *ab); int ath11k_enable_fwlog(struct ath11k_base *ab); +int ath11k_qmi_mem_read(struct ath11k_base *ab, u32 mem_addr, void *mem_value, size_t count); +int ath11k_qmi_mem_write(struct ath11k_base *ab, u32 mem_addr, void* mem_value, size_t count); - - #endif diff --git a/feeds/ipq95xx/mac80211/patches/qca/222-ath11k-add-module-param-for-ftm.patch b/feeds/ipq95xx/mac80211/patches/qca/222-ath11k-add-module-param-for-ftm.patch deleted file mode 100644 index 462d7e2a7..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/222-ath11k-add-module-param-for-ftm.patch +++ /dev/null @@ -1,699 +0,0 @@ -From 35a3aff175b3367684823712efa89fb7dfc46f4c Mon Sep 17 00:00:00 2001 -From: Sowmiya Sree Elavalagan -Date: Thu, 15 Oct 2020 12:43:43 +0530 -Subject: [PATCH] ath11k: add module param for ftm - -Device was switched to ftm mode on receiving start command from -ftm userspace add, now module param has been added to start -device in ftm mode directly.Device needs to be rebooted or -ath11k module has to be reinserted with ftm_mode unset to -bring it back to machine mode. Booting in ftm mode would -prevent loading of cal data and vap from starting. - -Command: insmod ath11k ftm_mode=1 - -Signed-off-by: Sowmiya Sree Elavalagan ---- - drivers/net/wireless/ath/ath11k/core.c | 11 +- - drivers/net/wireless/ath/ath11k/core.h | 2 + - drivers/net/wireless/ath/ath11k/debug.h | 1 + - drivers/net/wireless/ath/ath11k/mac.c | 5 + - drivers/net/wireless/ath/ath11k/qmi.c | 5 + - drivers/net/wireless/ath/ath11k/testmode.c | 276 +++++++++++++++------------ - drivers/net/wireless/ath/ath11k/testmode.h | 21 +- - drivers/net/wireless/ath/ath11k/testmode_i.h | 2 +- - drivers/net/wireless/ath/ath11k/wmi.c | 36 +++- - drivers/net/wireless/ath/ath11k/wmi.h | 20 ++ - 10 files changed, 247 insertions(+), 132 deletions(-) - ---- a/drivers/net/wireless/ath/ath11k/core.c -+++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -42,6 +42,10 @@ EXPORT_SYMBOL(ath11k_host_ddr_addr); - module_param_named(host_ddr_addr, ath11k_host_ddr_addr, uint, 0644); - MODULE_PARM_DESC(host_ddr_addr, "host ddr addr for FW"); - -+unsigned int ath11k_ftm_mode; -+module_param_named(ftm_mode, ath11k_ftm_mode, uint, 0644); -+MODULE_PARM_DESC(ftm_mode, "Boots up in factory test mode"); -+ - struct ath11k_base *ath11k_soc[MAX_SOCS]; - - static const struct ath11k_hw_params ath11k_hw_params[] = { -@@ -680,6 +684,11 @@ static int ath11k_core_soc_create(struct - { - int ret; - -+ if (ath11k_ftm_mode) { -+ ab->fw_mode = ATH11K_FIRMWARE_MODE_FTM; -+ ath11k_info(ab, "Booting in ftm mode - %d\n", ab->fw_mode); -+ } -+ - ret = ath11k_qmi_init_service(ab); - if (ret) { - ath11k_err(ab, "failed to initialize qmi :%d\n", ret); -@@ -1191,9 +1200,6 @@ static void ath11k_core_restart(struct w - break; - case ATH11K_STATE_TM: - ath11k_warn(ab, "fw mode reset done radio %d\n", i); -- if (test_bit(ATH11K_FLAG_FW_RESTART_FOR_HOST, &ar->ab->dev_flags)) { -- complete(&ar->fw_mode_reset); -- } - break; - } - mutex_unlock(&ar->conf_mutex); ---- a/drivers/net/wireless/ath/ath11k/core.h -+++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -678,6 +678,7 @@ struct ath11k { - bool dfs_block_radar_events; - struct ath11k_thermal thermal; - struct completion fw_mode_reset; -+ u8 ftm_msgref; - int ap_ps_enabled; - enum ath11k_ap_ps_state ap_ps_state; - -@@ -865,6 +866,7 @@ struct ath11k_base { - /* protected by data_lock */ - u32 fw_crash_counter; - } stats; -+ bool ftm_segment_handler; - struct ath11k_ftm_event_obj ftm_event_obj; - - u32 max_ast_index; ---- a/drivers/net/wireless/ath/ath11k/debug.h -+++ b/drivers/net/wireless/ath/ath11k/debug.h -@@ -33,6 +33,7 @@ __printf(2, 3) void ath11k_err(struct at - __printf(2, 3) void ath11k_warn(struct ath11k_base *ab, const char *fmt, ...); - - extern unsigned int ath11k_debug_mask; -+extern unsigned int ath11k_ftm_mode; - - #ifdef CPTCFG_ATH11K_DEBUG - __printf(3, 4) void __ath11k_dbg(struct ath11k_base *ab, ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -5560,6 +5560,11 @@ static int ath11k_mac_op_start(struct ie - struct device *dev = ab->dev; - int ret; - -+ if (ath11k_ftm_mode) { -+ ath11k_err(ab, "fail to start mac operations in ftm mode\n"); -+ return -EWOULDBLOCK; -+ } -+ - ath11k_mac_drain_tx(ar); - mutex_lock(&ar->conf_mutex); - ---- a/drivers/net/wireless/ath/ath11k/testmode.c -+++ b/drivers/net/wireless/ath/ath11k/testmode.c -@@ -12,6 +12,9 @@ - #include "hif.h" - #include "testmode_i.h" - -+#define FTM_SEGHDR_CURRENT_SEQ GENMASK(3, 0) -+#define FTM_SEGHDR_TOTAL_SEGMENTS GENMASK(7, 4) -+ - static const struct nla_policy ath11k_tm_policy[ATH11K_TM_ATTR_MAX + 1] = { - [ATH11K_TM_ATTR_CMD] = { .type = NLA_U32 }, - [ATH11K_TM_ATTR_DATA] = { .type = NLA_BINARY, -@@ -63,20 +66,16 @@ void ath11k_fwlog_write(struct ath11k_ba - - /* Returns true if callee consumes the skb and the skb should be discarded. - * Returns false if skb is not used. Does not sleep. -+ * Unsegmented events are handled here. Segments are aggregated in appln layer - */ --bool ath11k_tm_event_wmi(struct ath11k_base *ab, u32 cmd_id, -- struct sk_buff *skb) -+bool ath11k_wmi_tm_event_unsegmented(struct ath11k_base *ab, u32 cmd_id, -+ struct sk_buff *skb) - { - struct sk_buff *nl_skb; -+ struct ath11k *ar; - bool consumed; - int ret, i; -- struct ath11k *ar; - struct ath11k_pdev *pdev; -- u8 *buf_pos; -- u16 datalen; -- struct seg_hdr_info *seghdr_info; -- u8 total_segments, current_seq; -- u32 data_pos; - - ath11k_dbg(ab, ATH11K_DBG_TESTMODE, - "testmode event wmi cmd_id %d skb %pK skb->len %d\n", -@@ -87,30 +86,123 @@ bool ath11k_tm_event_wmi(struct ath11k_b - for (i = 0; i < ab->num_radios; i++) { - pdev = &ab->pdevs[i]; - ar = pdev->ar; -- if (ar && ar->state == ATH11K_STATE_TM) -- break; -+ if (ar) { -+ mutex_lock(&ar->conf_mutex); -+ if (ar->state == ATH11K_STATE_TM) { -+ mutex_unlock(&ar->conf_mutex); -+ break; -+ } -+ mutex_unlock(&ar->conf_mutex); -+ } - } - - if (i >= ab->num_radios) { -- ath11k_dbg(ab, ATH11K_DBG_TESTMODE, "testmode event not handled\n"); -+ ath11k_warn(ab, "testmode event not handled due to invalid pdev\n"); - return false; - } - - spin_lock_bh(&ar->data_lock); - -+ /* Only testmode.c should be handling events from utf firmware, -+ * otherwise all sort of problems will arise as mac80211 operations -+ * are not initialised. -+ */ - consumed = true; - -- seghdr_info = (struct seg_hdr_info *)(skb->data + WMI_TLV_HDR_SIZE); -- current_seq = (seghdr_info->segmentinfo & 0xF); -- total_segments = (seghdr_info->segmentinfo >> 4) & 0xF; -+ nl_skb = cfg80211_testmode_alloc_event_skb(ar->hw->wiphy, -+ 2 * sizeof(u32) + skb->len, -+ GFP_ATOMIC); -+ if (!nl_skb) { -+ ath11k_warn(ab, -+ "failed to allocate skb for testmode wmi event\n"); -+ goto out; -+ } -+ -+ ret = nla_put_u32(nl_skb, ATH11K_TM_ATTR_CMD, ATH11K_TM_CMD_WMI); -+ if (ret) { -+ ath11k_warn(ab, -+ "failed to put testmode wmi event cmd attribute: %d\n", -+ ret); -+ kfree_skb(nl_skb); -+ goto out; -+ } -+ -+ ret = nla_put_u32(nl_skb, ATH11K_TM_ATTR_WMI_CMDID, cmd_id); -+ if (ret) { -+ ath11k_warn(ab, -+ "failed to put testmode wmi event cmd_id: %d\n", -+ ret); -+ kfree_skb(nl_skb); -+ goto out; -+ } -+ -+ ret = nla_put(nl_skb, ATH11K_TM_ATTR_DATA, skb->len, skb->data); -+ if (ret) { -+ ath11k_warn(ab, -+ "failed to copy skb to testmode wmi event: %d\n", -+ ret); -+ kfree_skb(nl_skb); -+ goto out; -+ } -+ -+ cfg80211_testmode_event(nl_skb, GFP_ATOMIC); -+ -+out: -+ spin_unlock_bh(&ar->data_lock); -+ return consumed; -+} -+ -+/* Returns true if callee consumes the skb and the skb should be discarded. -+ * Returns false if skb is not used. Does not sleep. -+ * Segmented events are hangled here. -+ * Data of various events received from fw is aggregated and -+ * sent to application layer -+ */ -+bool ath11k_process_tm_event(struct ath11k_base *ab, u32 cmd_id, -+ const struct wmi_ftm_event_msg *ftm_msg, -+ u16 length) -+{ -+ struct sk_buff *nl_skb; -+ bool consumed; -+ int ret; -+ struct ath11k *ar; -+ u8 *buf_pos; -+ u16 datalen; -+ u8 total_segments, current_seq; -+ u32 data_pos; -+ u32 pdev_id; - -- datalen = skb->len - (sizeof(struct seg_hdr_info) + WMI_TLV_HDR_SIZE); -- buf_pos = skb->data + (sizeof(struct seg_hdr_info) + WMI_TLV_HDR_SIZE); -+ ath11k_dbg(ab, ATH11K_DBG_TESTMODE, -+ "testmode event wmi cmd_id %d ftm event msg %pK datalen %d\n", -+ cmd_id, ftm_msg, length); -+ ath11k_dbg_dump(ab, ATH11K_DBG_TESTMODE, NULL, "", ftm_msg, length); -+ pdev_id = DP_HW2SW_MACID(ftm_msg->seg_hdr.pdev_id); -+ -+ if (pdev_id >= ab->num_radios) { -+ ath11k_warn(ab, "testmode event not handled due to invalid pdev id\n"); -+ return false; -+ } -+ -+ ar = ab->pdevs[pdev_id].ar; -+ if (!ar) { -+ ath11k_warn(ab, "testmode event not handled due to absence of pdev\n"); -+ return false; -+ } -+ -+ spin_lock_bh(&ar->data_lock); -+ consumed = true; -+ current_seq = FIELD_GET(FTM_SEGHDR_CURRENT_SEQ, -+ ftm_msg->seg_hdr.segmentinfo); -+ total_segments = FIELD_GET(FTM_SEGHDR_TOTAL_SEGMENTS, -+ ftm_msg->seg_hdr.segmentinfo); -+ datalen = length - (sizeof(struct wmi_ftm_seg_hdr)); -+ buf_pos = (u8 *)ftm_msg->data; - - if (current_seq == 0) { - ab->ftm_event_obj.expected_seq = 0; - ab->ftm_event_obj.data_pos = 0; - } -+ - data_pos = ab->ftm_event_obj.data_pos; - - if ((data_pos + datalen) > ATH11K_FTM_EVENT_MAX_BUF_LENGTH) { -@@ -125,16 +217,15 @@ bool ath11k_tm_event_wmi(struct ath11k_b - - if (++ab->ftm_event_obj.expected_seq != total_segments) { - ab->ftm_event_obj.data_pos = data_pos; -- ath11k_warn(ab, -- "parial data received current_seq[%d], total_seg[%d]\n", -+ ath11k_dbg(ab, ATH11K_DBG_TESTMODE, -+ "partial data received current_seq[%d], total_seg[%d]\n", - current_seq, total_segments); - goto out; - } - -- ath11k_warn(ab, -- "total data length[%d] = [%d]\n", -- data_pos, seghdr_info->len); -- -+ ath11k_dbg(ab, ATH11K_DBG_TESTMODE, -+ "total data length[%d] = [%d]\n", -+ data_pos, ftm_msg->seg_hdr.len); - nl_skb = cfg80211_testmode_alloc_event_skb(ar->hw->wiphy, - 2 * sizeof(u32) + data_pos, - GFP_ATOMIC); -@@ -144,7 +235,8 @@ bool ath11k_tm_event_wmi(struct ath11k_b - goto out; - } - -- ret = nla_put_u32(nl_skb, ATH11K_TM_ATTR_CMD, ATH11K_TM_CMD_WMI_FTM); -+ ret = nla_put_u32(nl_skb, ATH11K_TM_ATTR_CMD, -+ ATH11K_TM_CMD_WMI_FTM); - if (ret) { - ath11k_warn(ab, - "failed to put testmode wmi event cmd attribute: %d\n", -@@ -176,7 +268,6 @@ bool ath11k_tm_event_wmi(struct ath11k_b - - out: - spin_unlock_bh(&ar->data_lock); -- - return consumed; - } - -@@ -217,7 +308,6 @@ static int ath11k_tm_cmd_testmode_start( - int ret; - - ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE, " enter testmode cmd fw start\n"); -- - mutex_lock(&ar->conf_mutex); - - if (ar->state == ATH11K_STATE_TM) { -@@ -231,88 +321,23 @@ static int ath11k_tm_cmd_testmode_start( - goto err; - } - -- /* Firmware already running in FTM mode */ -- if (ar->ab->fw_mode == ATH11K_FIRMWARE_MODE_FTM) { -- ar->state = ATH11K_STATE_TM; -- ret = 0; -- goto err; -- } -- ar->ab->ftm_event_obj.eventdata = kzalloc(ATH11K_FTM_EVENT_MAX_BUF_LENGTH, -- GFP_KERNEL); -+ ar->ab->ftm_event_obj.eventdata = -+ kzalloc(ATH11K_FTM_EVENT_MAX_BUF_LENGTH, GFP_KERNEL); - if (!ar->ab->ftm_event_obj.eventdata) { - ret = -ENOMEM; - goto err; - } - -- ar->ab->fw_mode = ATH11K_FIRMWARE_MODE_FTM; - ar->state = ATH11K_STATE_TM; -+ ar->ftm_msgref = 0; - mutex_unlock(&ar->conf_mutex); -- init_completion(&ar->fw_mode_reset); -- -- set_bit(ATH11K_FLAG_FW_RESTART_FOR_HOST, &ar->ab->dev_flags); -- ath11k_hif_power_down(ar->ab); -- ath11k_hif_power_up(ar->ab); -- -- if (!wait_for_completion_timeout(&ar->fw_mode_reset, -- FTM_MODE_RESET_TIMEOUT_HZ)) { -- clear_bit(ATH11K_FLAG_FW_RESTART_FOR_HOST, &ar->ab->dev_flags); -- ath11k_warn(ar->ab, "failed to restat the core in ftm mode\n"); -- return 0; -- } -- clear_bit(ATH11K_FLAG_FW_RESTART_FOR_HOST, &ar->ab->dev_flags); - ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE, " enter testmode cmd started\n"); -- - return 0; - err: - mutex_unlock(&ar->conf_mutex); - return ret; - } - --static int ath11k_tm_cmd_testmode_stop(struct ath11k *ar, struct nlattr *tb[]) --{ -- int ret; -- -- ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE, "Enter testmode cmd fw stop\n"); -- -- mutex_lock(&ar->conf_mutex); -- -- if (ar->state != ATH11K_STATE_TM) { -- ret = -ENETDOWN; -- goto out; -- } -- -- /* Firmware not running in FTM mode */ -- if (ar->ab->fw_mode != ATH11K_FIRMWARE_MODE_FTM) { -- ar->state = ATH11K_STATE_OFF; -- ret = 0; -- goto out; -- } -- -- ar->ab->fw_mode = ATH11K_FIRMWARE_MODE_NORMAL; -- mutex_unlock(&ar->conf_mutex); -- init_completion(&ar->fw_mode_reset); -- -- set_bit(ATH11K_FLAG_FW_RESTART_FOR_HOST, &ar->ab->dev_flags); -- ath11k_hif_power_down(ar->ab); -- ath11k_hif_power_up(ar->ab); -- -- if (!wait_for_completion_timeout(&ar->fw_mode_reset, -- FTM_MODE_RESET_TIMEOUT_HZ)) { -- clear_bit(ATH11K_FLAG_FW_RESTART_FOR_HOST, &ar->ab->dev_flags); -- ath11k_warn(ar->ab, "failed to restat the core in ftm mode\n"); -- return 0; -- } -- -- ar->state = ATH11K_STATE_OFF; -- clear_bit(ATH11K_FLAG_FW_RESTART_FOR_HOST, &ar->ab->dev_flags); -- kfree(ar->ab->ftm_event_obj.eventdata); -- ath11k_info(ar->ab, "UTF firmware stopped\n"); -- return 0; --out: -- mutex_unlock(&ar->conf_mutex); -- return ret; --} -- - static int ath11k_tm_cmd_wmi(struct ath11k *ar, struct nlattr *tb[], - struct ieee80211_vif *vif) - { -@@ -326,11 +351,6 @@ static int ath11k_tm_cmd_wmi(struct ath1 - - mutex_lock(&ar->conf_mutex); - -- if (ar->state != ATH11K_STATE_ON) { -- ret = -ENETDOWN; -- goto out; -- } -- - if (!tb[ATH11K_TM_ATTR_DATA]) { - ret = -EINVAL; - goto out; -@@ -378,7 +398,6 @@ static int ath11k_tm_cmd_wmi(struct ath1 - ret); - goto out; - } -- - ret = 0; - - out: -@@ -390,19 +409,16 @@ static int ath11k_tm_cmd_process_ftm(str - { - struct ath11k_pdev_wmi *wmi = ar->wmi; - struct sk_buff *skb; -- u32 cmd_id, buf_len; -+ u32 cmd_id, buf_len, hdr_info; - int ret; - void *buf; -- u8 *cmd; - /* if buf_len is 0 no data is sent, return error */ -- static u8 msgref = 1; - u8 segnumber = 0, seginfo; - u16 chunk_len, total_bytes, num_segments; - u8 *bufpos; -- struct seg_hdr_info seg_hdr; -+ struct wmi_ftm_cmd *ftm_cmd; - - mutex_lock(&ar->conf_mutex); -- - ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE, "ar->state %d\n", ar->state); - - if (ar->state != ATH11K_STATE_TM) { -@@ -418,12 +434,10 @@ static int ath11k_tm_cmd_process_ftm(str - buf = nla_data(tb[ATH11K_TM_ATTR_DATA]); - buf_len = nla_len(tb[ATH11K_TM_ATTR_DATA]); - cmd_id = WMI_PDEV_UTF_CMDID; -- - ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE, - "testmode cmd wmi cmd_id %d buf %pK buf_len %d\n", - cmd_id, buf, buf_len); - ath11k_dbg_dump(ar->ab, ATH11K_DBG_TESTMODE, NULL, "", buf, buf_len); -- - bufpos = buf; - total_bytes = buf_len; - num_segments = total_bytes / MAX_WMI_UTF_LEN; -@@ -437,27 +451,25 @@ static int ath11k_tm_cmd_process_ftm(str - else - chunk_len = buf_len; - -- skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, -- (chunk_len + sizeof(seg_hdr) + -- WMI_TLV_HDR_SIZE)); -+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, (chunk_len + -+ sizeof(struct wmi_ftm_cmd))); - if (!skb) { - ret = -ENOMEM; - goto out; - } - -- seg_hdr.len = total_bytes; -- seg_hdr.msgref = msgref; -- seginfo = ((num_segments << 4) & 0xF0) | (segnumber & 0xF); -- seg_hdr.segmentinfo = seginfo; -- seg_hdr.pad = 0; -+ ftm_cmd = (struct wmi_ftm_cmd *)skb->data; -+ hdr_info = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_BYTE) | -+ FIELD_PREP(WMI_TLV_LEN, (chunk_len + -+ sizeof(struct wmi_ftm_seg_hdr))); -+ ftm_cmd->tlv_header = hdr_info; -+ ftm_cmd->seg_hdr.len = total_bytes; -+ ftm_cmd->seg_hdr.msgref = ar->ftm_msgref; -+ seginfo = FIELD_PREP(FTM_SEGHDR_TOTAL_SEGMENTS, num_segments) | -+ FIELD_PREP(FTM_SEGHDR_CURRENT_SEQ, segnumber); -+ ftm_cmd->seg_hdr.segmentinfo = seginfo; - segnumber++; -- -- cmd = (uint8_t *)skb->data; -- WMITLV_SET_HDR(cmd, WMITLV_TAG_BYTE, (chunk_len + sizeof(seg_hdr))); -- cmd += WMI_TLV_HDR_SIZE; -- memcpy(cmd, &seg_hdr, sizeof(seg_hdr)); -- memcpy(&cmd[sizeof(seg_hdr)], bufpos, chunk_len); -- -+ memcpy(&ftm_cmd->data, bufpos, chunk_len); - ret = ath11k_wmi_cmd_send(wmi, skb, cmd_id); - if (ret) { - ath11k_warn(ar->ab, "ftm wmi command fail: %d\n", ret); -@@ -467,6 +479,7 @@ static int ath11k_tm_cmd_process_ftm(str - buf_len -= chunk_len; - bufpos += chunk_len; - } -+ ++ar->ftm_msgref; - ret = 0; - out: - mutex_unlock(&ar->conf_mutex); -@@ -477,6 +490,7 @@ int ath11k_tm_cmd(struct ieee80211_hw *h - void *data, int len) - { - struct ath11k *ar = hw->priv; -+ struct ath11k_base *ab = ar->ab; - struct nlattr *tb[ATH11K_TM_ATTR_MAX + 1]; - int ret; - -@@ -489,16 +503,18 @@ int ath11k_tm_cmd(struct ieee80211_hw *h - return -EINVAL; - - switch (nla_get_u32(tb[ATH11K_TM_ATTR_CMD])) { -- case ATH11K_TM_CMD_WMI_FTM: -- return ath11k_tm_cmd_process_ftm(ar, tb); -+ case ATH11K_TM_CMD_WMI: -+ ab->ftm_segment_handler = 0; -+ return ath11k_tm_cmd_wmi(ar, tb, vif); - case ATH11K_TM_CMD_TESTMODE_START: - return ath11k_tm_cmd_testmode_start(ar, tb); -- case ATH11K_TM_CMD_TESTMODE_STOP: -- return ath11k_tm_cmd_testmode_stop(ar, tb); - case ATH11K_TM_CMD_GET_VERSION: - return ath11k_tm_cmd_get_version(ar, tb); -- case ATH11K_TM_CMD_WMI_FW_TEST: -- return ath11k_tm_cmd_wmi(ar, tb, vif); -+ case ATH11K_TM_CMD_WMI_FTM: -+ ab->ftm_segment_handler = 1; -+ return ath11k_tm_cmd_process_ftm(ar, tb); -+ case ATH11K_TM_CMD_TESTMODE_STOP: -+ return 0; - default: - return -EOPNOTSUPP; - } ---- a/drivers/net/wireless/ath/ath11k/testmode.h -+++ b/drivers/net/wireless/ath/ath11k/testmode.h -@@ -4,7 +4,7 @@ - */ - - #include "core.h" --#include "ahb.h" -+#include "hif.h" - - #define MAX_WMI_UTF_LEN 252 - #define WMI_TLV_HDR_SIZE 4 -@@ -23,16 +23,28 @@ struct seg_hdr_info { - - #ifdef CPTCFG_NL80211_TESTMODE - --bool ath11k_tm_event_wmi(struct ath11k_base *ab, u32 cmd_id, -- struct sk_buff *skb); -+bool ath11k_wmi_tm_event_unsegmented(struct ath11k_base *ab, u32 cmd_id, -+ struct sk_buff *skb); -+ -+bool ath11k_process_tm_event(struct ath11k_base *ab, u32 cmd_id, -+ const struct wmi_ftm_event_msg *ftm_msg, -+ u16 length); -+ - int ath11k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - void *data, int len); - - void ath11k_fwlog_write(struct ath11k_base *ab, u8 *data, int len); - #else -+static inline bool ath11k_wmi_tm_event_unsegmented(struct ath11k_base *ab, -+ u32 cmd_id, -+ struct sk_buff *skb) -+{ -+ return false; -+} - --static inline bool ath11k_tm_event_wmi(struct ath11k_base *ab, u32 cmd_id, -- struct sk_buff *skb) -+static inline bool ath11k_process_tm_event(struct ath11k_base *ab, u32 cmd_id, -+ const struct wmi_ftm_event_msg *msg, -+ u16 length) - { - return false; - } ---- a/drivers/net/wireless/ath/ath11k/testmode_i.h -+++ b/drivers/net/wireless/ath/ath11k/testmode_i.h -@@ -60,7 +60,7 @@ enum ath11k_tm_cmd { - * provided with ATH11K_TM_ATTR_WMI_CMDID and payload in - * ATH11K_TM_ATTR_DATA. - */ -- ATH11K_TM_CMD_WMI_FW_TEST = 3, -+ ATH11K_TM_CMD_WMI = 3, - - /* The command used to transmit a FTM WMI command to the firmware - * and the event to receive WMI events from the firmware.The data ---- a/drivers/net/wireless/ath/ath11k/wmi.c -+++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -7716,6 +7716,37 @@ exit: - kfree(tb); - } - -+static void ath11k_wmi_tm_event_segmented(struct ath11k_base *ab, u32 cmd_id, -+ struct sk_buff *skb) -+{ -+ const void **tb; -+ const struct wmi_ftm_event_msg *ev; -+ u16 length; -+ int ret; -+ bool consumed; -+ -+ tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); -+ if (IS_ERR(tb)) { -+ ret = PTR_ERR(tb); -+ ath11k_warn(ab, "failed to parse ftm event tlv: %d\n", ret); -+ return; -+ } -+ -+ ev = tb[WMI_TAG_ARRAY_BYTE]; -+ if (!ev) { -+ ath11k_warn(ab, "failed to fetch ftm msg\n"); -+ kfree(tb); -+ return; -+ } -+ -+ length = skb->len - TLV_HDR_SIZE; -+ consumed = ath11k_process_tm_event(ab, cmd_id, ev, length); -+ if (!consumed) -+ ath11k_warn(ab, "Failed to process ftm event\n"); -+ -+ kfree(tb); -+} -+ - static void - ath11k_wmi_pdev_temperature_event(struct ath11k_base *ab, - struct sk_buff *skb) -@@ -8558,7 +8589,10 @@ static void ath11k_wmi_tlv_op_rx(struct - ath11k_probe_resp_tx_status_event(ab, skb); - break; - case WMI_PDEV_UTF_EVENTID: -- ath11k_tm_event_wmi(ab, id, skb); -+ if (ab->ftm_segment_handler) -+ ath11k_wmi_tm_event_segmented(ab, id, skb); -+ else -+ ath11k_wmi_tm_event_unsegmented(ab, id, skb); - break; - case WMI_TWT_ADD_DIALOG_EVENTID: - ath11k_wmi_twt_add_dialog_event(ab, skb); ---- a/drivers/net/wireless/ath/ath11k/wmi.h -+++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -3668,6 +3668,26 @@ struct wmi_get_pdev_temperature_cmd { - u32 pdev_id; - } __packed; - -+#define MAX_WMI_UTF_LEN 252 -+ -+struct wmi_ftm_seg_hdr { -+ u32 len; -+ u32 msgref; -+ u32 segmentinfo; -+ u32 pdev_id; -+} __packed; -+ -+struct wmi_ftm_cmd { -+ u32 tlv_header; -+ struct wmi_ftm_seg_hdr seg_hdr; -+ u8 data[]; -+}; -+ -+struct wmi_ftm_event_msg { -+ struct wmi_ftm_seg_hdr seg_hdr; -+ u8 data[]; -+}; -+ - #define WMI_BEACON_TX_BUFFER_SIZE 512 - - struct wmi_bcn_tmpl_cmd { ---- a/drivers/net/wireless/ath/ath11k/thermal.c -+++ b/drivers/net/wireless/ath/ath11k/thermal.c -@@ -70,7 +70,8 @@ static ssize_t ath11k_thermal_show_temp( - mutex_lock(&ar->conf_mutex); - - /* Can't get temperature when the card is off */ -- if (ar->state != ATH11K_STATE_ON) { -+ if (ar->state != ATH11K_STATE_ON && -+ ar->ab->fw_mode != ATH11K_FIRMWARE_MODE_FTM) { - ret = -ENETDOWN; - goto out; - } diff --git a/feeds/ipq95xx/mac80211/patches/qca/226-th11k-Update-CE-DP-irq-names-during-registration-fo.patch b/feeds/ipq95xx/mac80211/patches/qca/226-th11k-Update-CE-DP-irq-names-during-registration-fo.patch index 10e0cff64..f0613cce7 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/226-th11k-Update-CE-DP-irq-names-during-registration-fo.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/226-th11k-Update-CE-DP-irq-names-during-registration-fo.patch @@ -22,11 +22,11 @@ Signed-off-by: P Praneesh drivers/net/wireless/ath/ath11k/pci.h | 30 ++++++++++++ 2 files changed, 64 insertions(+), 54 deletions(-) ---- a/drivers/net/wireless/ath/ath11k/pci.c -+++ b/drivers/net/wireless/ath/ath11k/pci.c -@@ -76,58 +76,16 @@ static const struct ath11k_msi_config at - }, - }; +--- a/drivers/net/wireless/ath/ath11k/pcic.c ++++ b/drivers/net/wireless/ath/ath11k/pcic.c +@@ -8,58 +8,28 @@ + #include "pcic.h" + #include "debug.h" -static const char *irq_name[ATH11K_IRQ_NUM_MAX] = { - "bhi", @@ -90,13 +90,8 @@ Signed-off-by: P Praneesh + { + ATH11K_PCI_CE_IRQS_NAME() + }, - }; - - static inline void ath11k_pci_select_window(struct ath11k_pci *ab_pci, u32 offset) -@@ -537,6 +495,18 @@ static int ath11k_get_user_msi_assignmen - base_vector); - } - ++}; ++ +const char *dp_irq_name[ATH11K_MAX_PCI_DOMAINS + 1][ATH11K_EXT_IRQ_GRP_NUM_MAX] = { + { + ATH11K_PCI_DP_IRQS_NAME(0) @@ -107,58 +102,57 @@ Signed-off-by: P Praneesh + { + ATH11K_PCI_DP_IRQS_NAME() + }, -+}; -+ - static void ath11k_pci_free_ext_irq(struct ath11k_base *ab) - { - int i, j; -@@ -730,6 +700,11 @@ static int ath11k_pci_ext_irq_config(str - struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); - int i, j, ret, num_vectors = 0; - u32 user_base_data = 0, base_vector = 0; + }; + + static const struct ath11k_msi_config ath11k_msi_config[] = { +@@ -498,6 +468,11 @@ static int ath11k_pcic_ext_irq_config(st + int i, j, ret, num_vectors = 0; + u32 user_base_data = 0, base_vector = 0; + unsigned long irq_flags; + struct ath11k_pci *ar_pci = ath11k_pci_priv(ab); + u8 domain_id = pci_domain_nr(ar_pci->pdev->bus); + + if (domain_id > ATH11K_MAX_PCI_DOMAINS) + domain_id = ATH11K_MAX_PCI_DOMAINS; - - ret = ath11k_pci_get_user_msi_assignment(ath11k_pci_priv(ab), "DP", - &num_vectors, -@@ -781,7 +756,7 @@ static int ath11k_pci_ext_irq_config(str + + ret = ath11k_pcic_get_user_msi_assignment(ab, "DP", &num_vectors, + &user_base_data, +@@ -554,7 +529,8 @@ static int ath11k_pcic_ext_irq_config(st + irq_set_status_flags(irq, IRQ_DISABLE_UNLAZY); - ret = request_irq(irq, ath11k_pci_ext_interrupt_handler, - ab_pci->irq_flags, -- "DP_EXT_IRQ", irq_grp); + ret = request_irq(irq, ath11k_pcic_ext_interrupt_handler, +- irq_flags, "DP_EXT_IRQ", irq_grp); ++ irq_flags, + dp_irq_name[domain_id][i], irq_grp); if (ret) { ath11k_err(ab, "failed request irq %d: %d\n", vector, ret); -@@ -803,6 +778,11 @@ static int ath11k_pci_config_irq(struct - u32 msi_irq_start; +@@ -576,6 +552,11 @@ int ath11k_pcic_config_irq(struct ath11k unsigned int msi_data; int irq, i, ret, irq_idx; + unsigned long irq_flags; + struct ath11k_pci *ar_pci = ath11k_pci_priv(ab); + u8 domain_id = pci_domain_nr(ar_pci->pdev->bus); + + if (domain_id > ATH11K_MAX_PCI_DOMAINS) + domain_id = ATH11K_MAX_PCI_DOMAINS; - ret = ath11k_pci_get_user_msi_assignment(ath11k_pci_priv(ab), - "CE", &msi_data_count, -@@ -824,7 +804,7 @@ static int ath11k_pci_config_irq(struct - tasklet_setup(&ce_pipe->intr_tq, ath11k_pci_ce_tasklet); + ret = ath11k_pcic_get_user_msi_assignment(ab, "CE", &msi_data_count, + &msi_data_start, &msi_irq_start); +@@ -603,7 +584,7 @@ int ath11k_pcic_config_irq(struct ath11k + tasklet_setup(&ce_pipe->intr_tq, ath11k_pcic_ce_tasklet); - ret = request_irq(irq, ath11k_pci_ce_interrupt_handler, -- ab_pci->irq_flags, irq_name[irq_idx], -+ ab_pci->irq_flags, ce_irq_name[domain_id][i], - ce_pipe); + ret = request_irq(irq, ath11k_pcic_ce_interrupt_handler, +- irq_flags, irq_name[irq_idx], ce_pipe); ++ irq_flags, ce_irq_name[domain_id][i], ce_pipe); if (ret) { ath11k_err(ab, "failed to request irq %d: %d\n", ---- a/drivers/net/wireless/ath/ath11k/pci.h -+++ b/drivers/net/wireless/ath/ath11k/pci.h -@@ -53,6 +53,36 @@ - #define WLAON_QFPROM_PWR_CTRL_REG 0x01f8031c - #define QFPROM_PWR_CTRL_VDD4BLOW_MASK 0x4 + irq_idx, ret); +--- a/drivers/net/wireless/ath/ath11k/pcic.h ++++ b/drivers/net/wireless/ath/ath11k/pcic.h +@@ -24,6 +24,36 @@ + */ + #define ATH11K_PCI_ACCESS_ALWAYS_OFF 0xFE0 +#define STR_CONV(str) #str + @@ -190,6 +184,6 @@ Signed-off-by: P Praneesh + STR_CONV(pci##x##_ce10),\ + STR_CONV(pci##x##_ce11),\ + - struct ath11k_msi_user { - char *name; - int num_vectors; + int ath11k_pcic_get_user_msi_assignment(struct ath11k_base *ab, char *user_name, + int *num_vectors, u32 *user_base_data, + u32 *base_vector); diff --git a/feeds/ipq95xx/mac80211/patches/qca/228-ath11k-fix-rssi-station-dump-not-updated-in-qcn9000.patch b/feeds/ipq95xx/mac80211/patches/qca/228-ath11k-fix-rssi-station-dump-not-updated-in-qcn9000.patch index e3b7dc0db..51b24341b 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/228-ath11k-fix-rssi-station-dump-not-updated-in-qcn9000.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/228-ath11k-fix-rssi-station-dump-not-updated-in-qcn9000.patch @@ -20,7 +20,7 @@ Signed-off-by: P Praneesh --- a/drivers/net/wireless/ath/ath11k/hal_rx.c +++ b/drivers/net/wireless/ath/ath11k/hal_rx.c -@@ -1522,8 +1522,7 @@ ath11k_hal_rx_parse_mon_status_tlv(struc +@@ -1540,8 +1540,7 @@ ath11k_hal_rx_parse_mon_status_tlv(struc if (peer_id) ppdu_info->peer_id = peer_id; @@ -32,7 +32,7 @@ Signed-off-by: P Praneesh case HAL_RXPCU_PPDU_END_INFO: { --- a/drivers/net/wireless/ath/ath11k/hal_rx.h +++ b/drivers/net/wireless/ath/ath11k/hal_rx.h -@@ -461,6 +461,14 @@ struct hal_rx_mpdu_info_wcn6855 { +@@ -501,6 +501,14 @@ struct hal_rx_mpdu_info_wcn6855 { __le32 rsvd1[14]; } __packed; @@ -49,7 +49,7 @@ Signed-off-by: P Praneesh __le32 rsvd0[9]; --- a/drivers/net/wireless/ath/ath11k/hw.c +++ b/drivers/net/wireless/ath/ath11k/hw.c -@@ -872,6 +872,16 @@ static u16 ath11k_hw_ipq8074_mpdu_info_g +@@ -883,6 +883,16 @@ static u16 ath11k_hw_ipq8074_mpdu_info_g return peer_id; } @@ -66,8 +66,8 @@ Signed-off-by: P Praneesh static u16 ath11k_hw_wcn6855_mpdu_info_get_peerid(u8 *tlv_data) { u16 peer_id = 0; -@@ -883,6 +893,26 @@ static u16 ath11k_hw_wcn6855_mpdu_info_g - return peer_id; +@@ -900,6 +910,26 @@ static bool ath11k_hw_wcn6855_rx_desc_ge + __le32_to_cpu(desc->u.wcn6855.msdu_start.info2)); } +static u16 ath11k_hw_qcn9074_mpdu_info_get_peerid(u8 *tlv_data) @@ -93,7 +93,7 @@ Signed-off-by: P Praneesh static void ath11k_hw_ipq5018_set_rx_fragmentation_dst_ring(struct ath11k_base *ab) { u8 frag_dst_ring = HAL_SRNG_RING_ID_REO2SW1; -@@ -985,6 +1015,7 @@ const struct ath11k_hw_ops ipq8074_ops = +@@ -1003,6 +1033,7 @@ const struct ath11k_hw_ops ipq8074_ops = .rx_desc_mpdu_start_addr2 = ath11k_hw_ipq8074_rx_desc_mpdu_start_addr2, .set_rx_fragmentation_dst_ring = ath11k_hw_ipq8074_set_rx_fragmentation_dst_ring, .get_reo_dest_remap_config = ath11k_get_reo_dest_remap_config_default, @@ -101,7 +101,7 @@ Signed-off-by: P Praneesh }; const struct ath11k_hw_ops ipq6018_ops = { -@@ -1025,6 +1056,7 @@ const struct ath11k_hw_ops ipq6018_ops = +@@ -1044,6 +1075,7 @@ const struct ath11k_hw_ops ipq6018_ops = .rx_desc_mpdu_start_addr2 = ath11k_hw_ipq8074_rx_desc_mpdu_start_addr2, .set_rx_fragmentation_dst_ring = ath11k_hw_ipq8074_set_rx_fragmentation_dst_ring, .get_reo_dest_remap_config = ath11k_get_reo_dest_remap_config_default, @@ -109,7 +109,7 @@ Signed-off-by: P Praneesh }; const struct ath11k_hw_ops qca6390_ops = { -@@ -1065,6 +1097,7 @@ const struct ath11k_hw_ops qca6390_ops = +@@ -1085,6 +1117,7 @@ const struct ath11k_hw_ops qca6390_ops = .rx_desc_mpdu_start_addr2 = ath11k_hw_ipq8074_rx_desc_mpdu_start_addr2, .set_rx_fragmentation_dst_ring = ath11k_hw_ipq8074_set_rx_fragmentation_dst_ring, .get_reo_dest_remap_config = ath11k_get_reo_dest_remap_config_default, @@ -117,7 +117,7 @@ Signed-off-by: P Praneesh }; const struct ath11k_hw_ops qcn9074_ops = { -@@ -1105,6 +1138,8 @@ const struct ath11k_hw_ops qcn9074_ops = +@@ -1126,6 +1159,8 @@ const struct ath11k_hw_ops qcn9074_ops = .rx_desc_mpdu_start_addr2 = ath11k_hw_ipq9074_rx_desc_mpdu_start_addr2, .set_rx_fragmentation_dst_ring = ath11k_hw_ipq8074_set_rx_fragmentation_dst_ring, .get_reo_dest_remap_config = ath11k_get_reo_dest_remap_config_default, @@ -126,26 +126,26 @@ Signed-off-by: P Praneesh }; const struct ath11k_hw_ops wcn6855_ops = { -@@ -1145,6 +1180,7 @@ const struct ath11k_hw_ops wcn6855_ops = +@@ -1167,6 +1202,7 @@ const struct ath11k_hw_ops wcn6855_ops = .rx_desc_mpdu_start_addr2 = ath11k_hw_wcn6855_rx_desc_mpdu_start_addr2, .set_rx_fragmentation_dst_ring = ath11k_hw_wcn6855_set_rx_fragmentation_dst_ring, .get_reo_dest_remap_config = ath11k_get_reo_dest_remap_config_default, + .rx_desc_get_hal_mpdu_len = ath11k_hw_ipq8074_rx_desc_get_hal_mpdu_len, }; - /* IPQ5018 hw ops is similar to QCN9074 except for the dest ring remap */ -@@ -1185,6 +1221,8 @@ const struct ath11k_hw_ops ipq5018_ops = + const struct ath11k_hw_ops wcn6750_ops = { +@@ -1247,6 +1283,8 @@ const struct ath11k_hw_ops ipq5018_ops = .reo_setup = ath11k_hw_ipq5018_reo_setup, .set_rx_fragmentation_dst_ring = ath11k_hw_ipq5018_set_rx_fragmentation_dst_ring, .get_reo_dest_remap_config = ath11k_get_reo_dest_remap_config_5018, + .mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid, + .rx_desc_get_hal_mpdu_len = ath11k_hw_qcn9074_rx_desc_get_hal_mpdu_len, - }; + }; #define ATH11K_TX_RING_MASK_0 0x1 --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h -@@ -246,6 +246,7 @@ struct ath11k_hw_ops { +@@ -265,6 +265,7 @@ struct ath11k_hw_ops { u8* (*rx_desc_mpdu_start_addr2)(struct hal_rx_desc *desc); void (*set_rx_fragmentation_dst_ring)(struct ath11k_base *ab); u32 (*get_reo_dest_remap_config)(void); diff --git a/feeds/ipq95xx/mac80211/patches/qca/231-ath11k-add-ATH11K_QMI_TARGET_MEM_MODE_256M-support-f.patch b/feeds/ipq95xx/mac80211/patches/qca/231-ath11k-add-ATH11K_QMI_TARGET_MEM_MODE_256M-support-f.patch index 695fe3b92..db569f8bf 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/231-ath11k-add-ATH11K_QMI_TARGET_MEM_MODE_256M-support-f.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/231-ath11k-add-ATH11K_QMI_TARGET_MEM_MODE_256M-support-f.patch @@ -21,64 +21,74 @@ Signed-off-by: P Praneesh --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -128,6 +128,7 @@ static const struct ath11k_hw_params ath +@@ -125,6 +125,7 @@ static const struct ath11k_hw_params ath + .supports_dynamic_smps_6ghz = false, .alloc_cacheable_memory = true, - .wakeup_mhi = false, .ce_fwlog_enable = false, + .fwmem_mode_change = false, .supports_rssi_stats = false, .fw_wmi_diag_event = false, .current_cc_support = false, -@@ -198,6 +199,7 @@ static const struct ath11k_hw_params ath +@@ -201,6 +202,7 @@ static const struct ath11k_hw_params ath + .supports_dynamic_smps_6ghz = false, .alloc_cacheable_memory = true, - .wakeup_mhi = false, .ce_fwlog_enable = false, + .fwmem_mode_change = false, .supports_rssi_stats = false, .fw_wmi_diag_event = false, .current_cc_support = false, -@@ -265,6 +267,7 @@ static const struct ath11k_hw_params ath +@@ -274,6 +276,7 @@ static const struct ath11k_hw_params ath + .supports_dynamic_smps_6ghz = false, .alloc_cacheable_memory = false, - .wakeup_mhi = true, .ce_fwlog_enable = false, + .fwmem_mode_change = false, .supports_rssi_stats = true, .fw_wmi_diag_event = true, .current_cc_support = true, -@@ -333,6 +336,7 @@ static const struct ath11k_hw_params ath +@@ -348,6 +351,7 @@ static const struct ath11k_hw_params ath + .supports_dynamic_smps_6ghz = true, .alloc_cacheable_memory = true, - .wakeup_mhi = false, .ce_fwlog_enable = true, + .fwmem_mode_change = true, .supports_rssi_stats = false, .fw_wmi_diag_event = false, .current_cc_support = false, -@@ -399,7 +403,8 @@ static const struct ath11k_hw_params ath +@@ -421,6 +425,7 @@ static const struct ath11k_hw_params ath .supports_dynamic_smps_6ghz = false, .alloc_cacheable_memory = false, - .wakeup_mhi = true, -- .ce_fwlog_enable = true, -+ .ce_fwlog_enable = false, -+ .fwmem_mode_change = false, - .supports_rssi_stats = true, - .fw_wmi_diag_event = true, - .current_cc_support = true, -@@ -466,6 +471,7 @@ static const struct ath11k_hw_params ath - .alloc_cacheable_memory = false, - .wakeup_mhi = true, .ce_fwlog_enable = false, + .fwmem_mode_change = false, .supports_rssi_stats = true, .fw_wmi_diag_event = true, .current_cc_support = true, -@@ -525,6 +531,22 @@ static const struct ath11k_hw_params ath - .htt_peer_map_v2 = true, - .reo_dest_ring_map_shift = HAL_IPQ5018_REO_DEST_RING_CTRL_HASH_RING_SHIFT, +@@ -493,6 +498,7 @@ static const struct ath11k_hw_params ath + .supports_dynamic_smps_6ghz = false, + .alloc_cacheable_memory = false, + .ce_fwlog_enable = false, ++ .fwmem_mode_change = false, + .supports_rssi_stats = true, + .fw_wmi_diag_event = true, + .current_cc_support = true, +@@ -563,6 +569,7 @@ static const struct ath11k_hw_params ath + .supports_dynamic_smps_6ghz = false, + .alloc_cacheable_memory = false, + .ce_fwlog_enable = false, ++ .fwmem_mode_change = false, + .supports_rssi_stats = true, + .fw_wmi_diag_event = false, + .current_cc_support = true, +@@ -626,6 +633,7 @@ static const struct ath11k_hw_params ath + .fix_l1ss = true, + .alloc_cacheable_memory = true, .ce_fwlog_enable = true, + .fwmem_mode_change = false, -+ }, -+}; -+ + .rxdma1_enable = true, + .num_rxmda_per_pdev = 1, + .rx_mac_buf_ring = false, +@@ -644,6 +652,21 @@ static const struct ath11k_hw_params ath + }, + }; + +static const struct ath11k_num_vdevs_peers ath11k_vdevs_peers[] = { + { + .num_vdevs = (16 + 1), @@ -91,10 +101,13 @@ Signed-off-by: P Praneesh + { + .num_vdevs = 8, + .num_peers = 128, - } - }; - -@@ -963,6 +985,8 @@ static int ath11k_core_soc_create(struct ++ }, ++}; ++ + static inline struct ath11k_pdev *ath11k_core_get_single_pdev(struct ath11k_base *ab) + { + WARN_ON(!ab->hw_params.single_pdev_only); +@@ -1266,6 +1289,8 @@ static int ath11k_core_soc_create(struct ath11k_info(ab, "Booting in ftm mode - %d\n", ab->fw_mode); } @@ -105,7 +118,7 @@ Signed-off-by: P Praneesh ath11k_err(ab, "failed to initialize qmi :%d\n", ret); --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h -@@ -211,6 +211,7 @@ struct ath11k_hw_params { +@@ -208,6 +208,7 @@ struct ath11k_hw_params { u32 m3_addr; u8 reo_dest_ring_map_shift; bool ce_fwlog_enable; @@ -115,7 +128,7 @@ Signed-off-by: P Praneesh bool current_cc_support; --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c -@@ -25,6 +25,10 @@ module_param_named(cold_boot_cal, ath11k +@@ -31,6 +31,10 @@ module_param_named(cold_boot_cal, ath11k MODULE_PARM_DESC(cold_boot_cal, "Decrease the channel switch time but increase the driver load time (Default: true)"); @@ -126,7 +139,7 @@ Signed-off-by: P Praneesh static struct qmi_elem_info qmi_wlanfw_qdss_trace_config_download_req_msg_v01_ei[] = { { .data_type = QMI_OPT_FLAG, -@@ -2829,7 +2833,8 @@ static int ath11k_qmi_assign_target_mem_ +@@ -2906,7 +2910,8 @@ static int ath11k_qmi_assign_target_mem_ return -EINVAL; } @@ -136,7 +149,7 @@ Signed-off-by: P Praneesh if (hremote_node) { ab->qmi.target_mem[idx].paddr = res.start + host_ddr_sz; -@@ -4545,6 +4550,17 @@ int ath11k_qmi_init_service(struct ath11 +@@ -4732,6 +4737,17 @@ int ath11k_qmi_init_service(struct ath11 ab->qmi.ab = ab; ab->qmi.target_mem_mode = ab->hw_params.fw_mem_mode; @@ -156,7 +169,7 @@ Signed-off-by: P Praneesh if (ret < 0) { --- a/drivers/net/wireless/ath/ath11k/qmi.h +++ b/drivers/net/wireless/ath/ath11k/qmi.h -@@ -67,6 +67,12 @@ +@@ -71,6 +71,12 @@ struct ath11k_base; extern unsigned int ath11k_host_ddr_addr; @@ -171,8 +184,8 @@ Signed-off-by: P Praneesh ATH11K_QMI_FILE_TYPE_CALDATA = 2, --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -821,6 +821,11 @@ struct ath11k_soc_dp_stats { - struct ath11k_dp_ring_bp_stats bp_stats; +@@ -940,6 +940,11 @@ struct ath11k_msi_config { + u16 hw_rev; }; +struct ath11k_num_vdevs_peers { @@ -183,17 +196,17 @@ Signed-off-by: P Praneesh /* Master structure to hold the hw data which may be used in core module */ struct ath11k_base { enum ath11k_hw_rev hw_rev; -@@ -953,6 +958,7 @@ struct ath11k_base { +@@ -1098,6 +1103,7 @@ struct ath11k_base { bool ce_remap; u32 ce_remap_base_addr; atomic_t num_max_allowed; + struct ath11k_num_vdevs_peers *num_vdevs_peers; /* must be last */ - u8 drv_priv[0] __aligned(sizeof(void *)); + u8 drv_priv[] __aligned(sizeof(void *)); --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -2034,6 +2034,9 @@ static ssize_t ath11k_dump_mgmt_stats(st +@@ -2106,6 +2106,9 @@ static ssize_t ath11k_dump_mgmt_stats(st size_t count, loff_t *ppos) { struct ath11k *ar = file->private_data; diff --git a/feeds/ipq95xx/mac80211/patches/qca/231-ath11k-add-wmi-ctrl-path-stats.patch b/feeds/ipq95xx/mac80211/patches/qca/231-ath11k-add-wmi-ctrl-path-stats.patch index 18be6f80c..b8ce89dcc 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/231-ath11k-add-wmi-ctrl-path-stats.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/231-ath11k-add-wmi-ctrl-path-stats.patch @@ -36,16 +36,16 @@ Signed-off-by: Thiraviyam Mariyappan --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -299,6 +299,7 @@ struct ath11k_vif { +@@ -392,6 +392,7 @@ struct ath11k_vif { struct dentry *debugfs_twt; struct dentry *ampdu_aggr_size; struct dentry *amsdu_aggr_size; + struct dentry *wmi_ctrl_stat; + #endif /* CPTCFG_ATH11K_DEBUGFS */ + struct ath11k_mgmt_frame_stats mgmt_stats; - #ifdef CPTCFG_ATH11K_NSS_SUPPORT - struct arvif_nss nss; -@@ -531,6 +532,9 @@ struct ath11k_debug { - u32 rx_filter; +@@ -634,6 +635,9 @@ struct ath11k_debug { + struct ath11k_debug_dbr *dbr_debug[WMI_DIRECT_BUF_MAX]; bool enable_m3_dump; u32 mem_addr; + struct list_head wmi_list; @@ -56,7 +56,7 @@ Signed-off-by: Thiraviyam Mariyappan struct ath11k_per_peer_tx_stats { --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -254,6 +254,218 @@ void ath11k_debugfs_twt(struct ath11k_vi +@@ -293,6 +293,218 @@ void ath11k_debugfs_twt(struct ath11k_vi } #endif @@ -277,7 +277,7 @@ Signed-off-by: Thiraviyam Mariyappan size_t count, loff_t *ppos) --- a/drivers/net/wireless/ath/ath11k/debugfs.h +++ b/drivers/net/wireless/ath/ath11k/debugfs.h -@@ -159,6 +159,8 @@ static inline void ath11k_debugfs_twt(st +@@ -314,6 +314,8 @@ static inline void ath11k_debugfs_twt(st #endif void ath11k_debug_aggr_size_config_init(struct ath11k_vif *arvif); @@ -288,15 +288,15 @@ Signed-off-by: Thiraviyam Mariyappan int ath11k_debugfs_create(void); --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -6821,6 +6821,7 @@ static int ath11k_mac_op_add_interface(s - ath11k_warn(ar->ab, "failed to set ap ps ret %d\n", ret); +@@ -6822,6 +6822,7 @@ static int ath11k_mac_op_add_interface(s + goto err_peer_del; ath11k_debug_aggr_size_config_init(arvif); + ath11k_debugfs_wmi_ctrl_stats(arvif); mutex_unlock(&ar->conf_mutex); -@@ -6971,6 +6972,10 @@ err_vdev_del: +@@ -6965,6 +6966,10 @@ err_vdev_del: debugfs_remove(arvif->amsdu_aggr_size); arvif->amsdu_aggr_size = NULL; @@ -309,7 +309,7 @@ Signed-off-by: Thiraviyam Mariyappan --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -3076,6 +3076,102 @@ ath11k_wmi_send_twt_add_dialog_cmd(struc +@@ -3734,6 +3734,102 @@ int ath11k_wmi_send_twt_resume_dialog_cm } int @@ -409,10 +409,10 @@ Signed-off-by: Thiraviyam Mariyappan +} + +int - ath11k_wmi_send_twt_del_dialog_cmd(struct ath11k *ar, - struct wmi_twt_del_dialog_params *params) + ath11k_wmi_send_obss_spr_cmd(struct ath11k *ar, u32 vdev_id, + struct ieee80211_he_obss_pd *he_obss_pd) { -@@ -7463,6 +7559,195 @@ exit: +@@ -7516,6 +7612,195 @@ exit: rcu_read_unlock(); } @@ -608,7 +608,7 @@ Signed-off-by: Thiraviyam Mariyappan static void ath11k_qos_null_compl_event(struct ath11k_base *ab, struct sk_buff *skb) { struct wmi_tx_compl_event tx_compl_param = {0}; -@@ -9166,6 +9451,9 @@ static void ath11k_wmi_tlv_op_rx(struct +@@ -9282,6 +9567,9 @@ static void ath11k_wmi_tlv_op_rx(struct case WMI_QOS_NULL_FRAME_TX_COMPLETION_EVENTID: ath11k_qos_null_compl_event(ab, skb); break; @@ -620,7 +620,7 @@ Signed-off-by: Thiraviyam Mariyappan ath11k_dbg(ab, ATH11K_DBG_WMI, "Unknown eventid: 0x%x\n", id); --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -441,6 +441,8 @@ enum wmi_tlv_cmd_id { +@@ -447,6 +447,8 @@ enum wmi_tlv_cmd_id { WMI_REQUEST_RCPI_CMDID, WMI_REQUEST_PEER_STATS_INFO_CMDID, WMI_REQUEST_RADIO_CHAN_STATS_CMDID, @@ -629,7 +629,7 @@ Signed-off-by: Thiraviyam Mariyappan WMI_SET_ARP_NS_OFFLOAD_CMDID = WMI_TLV_CMD(WMI_GRP_ARP_NS_OFL), WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMDID, WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMDID, -@@ -710,6 +712,8 @@ enum wmi_tlv_event_id { +@@ -716,6 +718,8 @@ enum wmi_tlv_event_id { WMI_UPDATE_RCPI_EVENTID, WMI_PEER_STATS_INFO_EVENTID, WMI_RADIO_CHAN_STATS_EVENTID, @@ -638,7 +638,7 @@ Signed-off-by: Thiraviyam Mariyappan WMI_NLO_MATCH_EVENTID = WMI_TLV_CMD(WMI_GRP_NLO_OFL), WMI_NLO_SCAN_COMPLETE_EVENTID, WMI_APFIND_EVENTID, -@@ -1866,6 +1870,11 @@ enum wmi_tlv_tag { +@@ -1872,6 +1876,11 @@ enum wmi_tlv_tag { WMI_TAG_PDEV_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD, WMI_TAG_PDEV_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMD, WMI_TAG_PDEV_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD, @@ -650,17 +650,17 @@ Signed-off-by: Thiraviyam Mariyappan WMI_TAG_TPC_STATS_GET_CMD = 0x38B, WMI_TAG_TPC_STATS_EVENT_FIXED_PARAM, WMI_TAG_TPC_STATS_CONFIG_EVENT, -@@ -1875,6 +1884,7 @@ enum wmi_tlv_tag { +@@ -1881,6 +1890,7 @@ enum wmi_tlv_tag { /* TODO add all the missing cmds */ WMI_TAG_QOS_NULL_FRAME_TX_SEND = 0x3A6, WMI_TAG_QOS_NULL_FRAME_TX_STATUS, + WMI_CTRL_PATH_CAL_STATS = 0x3BC, - + WMI_TAG_PDEV_SET_BIOS_SAR_TABLE_CMD = 0x3D8, + WMI_TAG_PDEV_SET_BIOS_GEO_TABLE_CMD, WMI_TAG_MAX - }; -@@ -5364,6 +5374,257 @@ struct wmi_twt_resume_dialog_params_cmd +@@ -5369,6 +5379,257 @@ struct wmi_twt_resume_dialog_params_cmd u32 next_twt_size; - }; + } __packed; +/** + * WMI arrays of length WMI_MGMT_FRAME_SUBTYPE_MAX use the @@ -916,7 +916,7 @@ Signed-off-by: Thiraviyam Mariyappan struct wmi_obss_spatial_reuse_params_cmd { u32 tlv_header; u32 pdev_id; -@@ -5896,6 +6157,7 @@ struct wmi_qos_null_tx_cmd { +@@ -5891,6 +6152,7 @@ struct wmi_qos_null_tx_cmd { #define WMI_SERVICE_READY_TIMEOUT_HZ (5 * HZ) #define WMI_SEND_TIMEOUT_HZ (3 * HZ) @@ -924,10 +924,11 @@ Signed-off-by: Thiraviyam Mariyappan enum ath11k_wmi_peer_ps_param { WMI_PEER_STA_WAKEUP_MODE = 0, -@@ -6284,4 +6546,6 @@ int ath11k_wmi_pdev_get_tpc_table_cmdid( +@@ -6694,5 +6956,6 @@ int ath11k_wmi_pdev_get_tpc_table_cmdid( void ath11k_wmi_free_tpc_stats_mem(struct ath11k *ar); int ath11k_wmi_send_aggr_size_cmd(struct ath11k *ar, struct set_custom_aggr_size_params *params); +- +int ath11k_wmi_send_wmi_ctrl_stats_cmd(struct ath11k *ar, + struct wmi_ctrl_path_stats_cmd_param *param); #endif diff --git a/feeds/ipq95xx/mac80211/patches/qca/232-ath11k-qcn6122-support.patch b/feeds/ipq95xx/mac80211/patches/qca/232-ath11k-qcn6122-support.patch index b4e404106..a3cdea705 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/232-ath11k-qcn6122-support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/232-ath11k-qcn6122-support.patch @@ -33,32 +33,9 @@ Signed-off-by: Sowmiya Sree Elavalagan drivers/net/wireless/ath/ath11k/qmi.h | 23 ++- 16 files changed, 828 insertions(+), 132 deletions(-) ---- a/drivers/net/wireless/ath/ath11k/Makefile -+++ b/drivers/net/wireless/ath/ath11k/Makefile -@@ -30,10 +30,10 @@ ath11k-$(CPTCFG_ATH11K_PKTLOG) += pktlog - ath11k-$(CPTCFG_ATH11K_NSS_SUPPORT) += nss.o - - obj-$(CPTCFG_ATH11K_AHB) += ath11k_ahb.o --ath11k_ahb-y += ahb.o -+ath11k_ahb-y += ahb.o pci_cmn.o - - obj-$(CPTCFG_ATH11K_PCI) += ath11k_pci.o --ath11k_pci-y += mhi.o pci.o -+ath11k_pci-y += mhi.o pci.o pci_cmn.o - - # for tracing framework to find trace.h - CFLAGS_trace.o := -I$(src) --- a/drivers/net/wireless/ath/ath11k/ahb.c +++ b/drivers/net/wireless/ath/ath11k/ahb.c -@@ -11,6 +11,7 @@ - #include "ahb.h" - #include "debug.h" - #include "hif.h" -+#include "pci_cmn.h" - #include "qmi.h" - #include - -@@ -27,6 +28,9 @@ static const struct of_device_id ath11k_ +@@ -34,6 +34,9 @@ static const struct of_device_id ath11k_ { .compatible = "qcom,ipq5018-wifi", .data = (void *)ATH11K_HW_IPQ5018, }, @@ -68,22 +45,85 @@ Signed-off-by: Sowmiya Sree Elavalagan { } }; -@@ -39,6 +43,14 @@ static const struct ath11k_bus_params at - .fixed_mem_region = true, +@@ -139,46 +142,35 @@ enum ext_irq_num { }; -+static const struct ath11k_bus_params ath11k_internal_pci_bus_params = { -+ .mhi_support = false, -+ .m3_fw_support = false, -+ .fixed_bdf_addr = true, -+ .fixed_mem_region = true, -+ .static_window_map = true, + static int +-ath11k_ahb_get_msi_irq_wcn6750(struct ath11k_base *ab, unsigned int vector) ++ath11k_ahb_get_msi_irq(struct ath11k_base *ab, unsigned int vector) + { + return ab->pci.msi.irqs[vector]; + } + +-static inline u32 +-ath11k_ahb_get_window_start_wcn6750(struct ath11k_base *ab, u32 offset) ++static u32 ath11k_ahb_get_window_start(struct ath11k_base *ab, u32 offset) + { +- u32 window_start = 0; +- +- /* If offset lies within DP register range, use 1st window */ +- if ((offset ^ HAL_SEQ_WCSS_UMAC_OFFSET) < ATH11K_PCI_WINDOW_RANGE_MASK) +- window_start = ATH11K_PCI_WINDOW_START; +- /* If offset lies within CE register range, use 2nd window */ +- else if ((offset ^ HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab)) < +- ATH11K_PCI_WINDOW_RANGE_MASK) +- window_start = 2 * ATH11K_PCI_WINDOW_START; +- +- return window_start; ++ return ath11k_pcic_get_window_start(ab, offset, ATH11K_BUS_AHB); + } + + static void +-ath11k_ahb_window_write32_wcn6750(struct ath11k_base *ab, u32 offset, u32 value) ++ath11k_ahb_window_write32(struct ath11k_base *ab, u32 offset, u32 value) + { + u32 window_start; + + /* WCN6750 uses static window based register access*/ +- window_start = ath11k_ahb_get_window_start_wcn6750(ab, offset); ++ window_start = ath11k_ahb_get_window_start(ab, offset); + + iowrite32(value, ab->mem + window_start + + (offset & ATH11K_PCI_WINDOW_RANGE_MASK)); + } + +-static u32 ath11k_ahb_window_read32_wcn6750(struct ath11k_base *ab, u32 offset) ++static u32 ath11k_ahb_window_read32(struct ath11k_base *ab, u32 offset) + { + u32 window_start; + u32 val; + + /* WCN6750 uses static window based register access */ +- window_start = ath11k_ahb_get_window_start_wcn6750(ab, offset); ++ window_start = ath11k_ahb_get_window_start(ab, offset); + + val = ioread32(ab->mem + window_start + + (offset & ATH11K_PCI_WINDOW_RANGE_MASK)); +@@ -188,11 +180,20 @@ static u32 ath11k_ahb_window_read32_wcn6 + static const struct ath11k_pci_ops ath11k_ahb_pci_ops_wcn6750 = { + .wakeup = NULL, + .release = NULL, +- .get_msi_irq = ath11k_ahb_get_msi_irq_wcn6750, +- .window_write32 = ath11k_ahb_window_write32_wcn6750, +- .window_read32 = ath11k_ahb_window_read32_wcn6750, ++ .get_msi_irq = ath11k_ahb_get_msi_irq, ++ .window_write32 = ath11k_ahb_window_write32, ++ .window_read32 = ath11k_ahb_window_read32, + }; + ++static const struct ath11k_pci_ops ath11k_ahb_pci_ops_qcn6122 = { ++ .wakeup = NULL, ++ .release = NULL, ++ .get_msi_irq = ath11k_ahb_get_msi_irq, ++ .window_write32 = ath11k_ahb_window_write32, ++ .window_read32 = ath11k_ahb_window_read32, +}; + - #define ATH11K_IRQ_CE0_OFFSET 4 - - static const char *irq_name[ATH11K_IRQ_NUM_MAX] = { -@@ -394,6 +406,7 @@ static void ath11k_ahb_init_qmi_ce_confi ++ + static inline u32 ath11k_ahb_read32(struct ath11k_base *ab, u32 offset) + { + if (ab->ce_remap && (offset & HAL_CE_REMAP_REG_BASE)) { +@@ -449,6 +450,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; @@ -91,44 +131,67 @@ Signed-off-by: Sowmiya Sree Elavalagan } static void ath11k_ahb_free_ext_irq(struct ath11k_base *ab) -@@ -681,6 +694,36 @@ static const struct ath11k_hif_ops ath11 - .ssr_notifier_reg = ath11k_ahb_ssr_notifier_reg, - .ssr_notifier_unreg = ath11k_ahb_ssr_notifier_unreg, - #endif -+ .free_irq = ath11k_ahb_free_irq, -+ .config_irq = ath11k_ahb_config_irq, -+}; +@@ -470,6 +472,9 @@ static void ath11k_ahb_free_irq(struct a + int irq_idx; + int i; + ++ if (ab->hw_params.internal_pci) ++ return ath11k_pcic_ipci_free_irq(ab); + -+static const struct ath11k_hif_ops ath11k_internal_pci_hif_ops = { -+ .start = ath11k_ipci_start, -+ .stop = ath11k_pci_stop, -+ .read32 = ath11k_ipci_read32, -+ .write32 = ath11k_ipci_write32, + if (ab->hw_params.hybrid_bus_type) + return ath11k_pcic_free_irq(ab); + +@@ -633,6 +638,9 @@ static int ath11k_ahb_config_irq(struct + int irq, irq_idx, i; + int ret; + ++ if (ab->hw_params.internal_pci) ++ return ath11k_pcic_ipci_config_irq(ab); ++ + if (ab->hw_params.hybrid_bus_type) + return ath11k_pcic_config_irq(ab); + +@@ -760,6 +768,27 @@ static const struct ath11k_hif_ops ath11 + .power_up = ath11k_ahb_power_up, + }; + ++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, + .power_down = ath11k_ahb_power_down, + .power_up = ath11k_ahb_power_up, -+ .irq_enable = ath11k_pci_ext_irq_enable, -+ .irq_disable = ath11k_pci_ext_irq_disable, -+ .get_msi_address = ath11k_pci_get_qgic_msi_address, -+ .get_user_msi_vector = ath11k_ipci_get_user_msi_assignment, -+ .map_service_to_pipe = ath11k_pci_map_service_to_pipe, ++ .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, ++ .get_ce_msi_idx = ath11k_pcic_get_ce_msi_idx, ++ .config_static_window = ath11k_pcic_config_static_window, + .get_window_offset = ath11k_pci_get_window_offset, -+ .get_ce_msi_idx = ath11k_pci_get_ce_msi_idx, -+ /* TODO: Additional hif ops has been brought in to remove -+ * platform checks. QCN6122 is a hybrid bus which is a -+ * combination of pic and ahb. This addition ops needs -+ * to be removed in future -+ */ -+ .config_static_window = ath11k_pci_config_static_window, +#ifdef CONFIG_QCOM_QMI_HELPERS + .ssr_notifier_reg = ath11k_ahb_ssr_notifier_reg, + .ssr_notifier_unreg = ath11k_ahb_ssr_notifier_unreg, +#endif -+ .free_irq = ath11k_internal_pci_free_irq, -+ .config_irq = ath11k_config_irq_internal_pci, - }; - ++}; ++ static int ath11k_core_get_rproc(struct ath11k_base *ab) -@@ -705,6 +748,29 @@ static int ath11k_core_get_rproc(struct + { + struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab); +@@ -838,6 +867,11 @@ static int ath11k_ahb_setup_resources(st + struct resource *mem_res; + void __iomem *mem; + ++ if (ab->hw_params.internal_pci) { ++ set_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags); ++ return 0; ++ } ++ + if (ab->hw_params.hybrid_bus_type) + return ath11k_ahb_setup_msi_resources(ab); + +@@ -1020,6 +1054,28 @@ static int ath11k_ahb_fw_resource_deinit return 0; } @@ -146,11 +209,10 @@ Signed-off-by: Sowmiya Sree Elavalagan + return 0; + } + -+ if (strcmp(subsys_name, "q6v5_wcss_userpd2") == 0) { ++ if (strcmp(subsys_name, "q6v5_wcss_userpd2") == 0) + userpd_id = QCN6122_USERPD_0; -+ } else if (strcmp(subsys_name, "q6v5_wcss_userpd3") == 0) { ++ else if (strcmp(subsys_name, "q6v5_wcss_userpd3") == 0) + userpd_id = QCN6122_USERPD_1; -+ } + + return userpd_id; +} @@ -158,92 +220,43 @@ Signed-off-by: Sowmiya Sree Elavalagan static int ath11k_ahb_probe(struct platform_device *pdev) { struct ath11k_base *ab; -@@ -712,7 +778,7 @@ static int ath11k_ahb_probe(struct platf - const struct of_device_id *of_id; - struct resource *mem_res; - void __iomem *mem; +@@ -1028,7 +1084,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 userpd_id, ret; ++ int ret, userpd_id; u32 hw_mode_id; of_id = of_match_device(ath11k_ahb_of_match, &pdev->dev); -@@ -721,17 +787,7 @@ static int ath11k_ahb_probe(struct platf - return -EINVAL; +@@ -1050,11 +1106,16 @@ 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: ++ hif_ops = &ath11k_ahb_hif_ops_qcn6122; ++ pci_ops = &ath11k_ahb_pci_ops_qcn6122; ++ break; + default: + dev_err(&pdev->dev, "unsupported device type %d\n", hw_rev); + return -EOPNOTSUPP; } -- mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- if (!mem_res) { -- dev_err(&pdev->dev, "failed to get IO memory resource\n"); -- return -ENXIO; -- } -- -- mem = devm_ioremap_resource(&pdev->dev, mem_res); -- if (IS_ERR(mem)) { -- dev_err(&pdev->dev, "ioremap error\n"); -- return PTR_ERR(mem); -- } + userpd_id = ath11k_get_userpd_id(dev); - ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); if (ret) { -@@ -751,13 +807,32 @@ static int ath11k_ahb_probe(struct platf + dev_err(&pdev->dev, "failed to set 32-bit consistent dma\n"); +@@ -1071,6 +1132,7 @@ static int ath11k_ahb_probe(struct platf + ab->hif.ops = hif_ops; ab->pdev = pdev; - ab->hw_rev = (enum ath11k_hw_rev)of_id->data; - ab->fw_mode = ATH11K_FIRMWARE_MODE_NORMAL; -- ab->mem = mem; -- ab->mem_pa = mem_res->start; -- ab->mem_len = resource_size(mem_res); + ab->hw_rev = hw_rev; + ab->userpd_id = userpd_id; + ab->fw_mode = ATH11K_FIRMWARE_MODE_NORMAL; ab->enable_cold_boot_cal = ath11k_cold_boot_cal; platform_set_drvdata(pdev, ab); - -- ab->mem_ce = ab->mem; -+ if (ab->hw_rev != ATH11K_HW_QCN6122) { -+ mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!mem_res) { -+ dev_err(&pdev->dev, "failed to get IO memory resource\n"); -+ return -ENXIO; -+ } -+ -+ mem = devm_ioremap_resource(&pdev->dev, mem_res); -+ if (IS_ERR(mem)) { -+ dev_err(&pdev->dev, "ioremap error\n"); -+ return PTR_ERR(mem); -+ } -+ -+ ab->mem = mem; -+ ab->mem_len = resource_size(mem_res); -+ ab->mem_ce = ab->mem; -+ ab->mem_pa = mem_res->start; -+ } else { -+ ab->hif.ops = &ath11k_internal_pci_hif_ops; -+ ab->bus_params = ath11k_internal_pci_bus_params; -+ } -+ - if (ab->hw_rev == ATH11K_HW_IPQ5018) { - /* ce register space is moved out of wcss unlike ipq8074 or ipq6018 - * and the space is not contiguous, hence remapping the CE registers -@@ -800,7 +875,7 @@ static int ath11k_ahb_probe(struct platf - goto err_ce_free; - } - -- ret = ath11k_ahb_config_irq(ab); -+ ret = ath11k_hif_config_irq(ab); - if (ret) { - ath11k_err(ab, "failed to configure irq: %d\n", ret); - goto err_ce_free; -@@ -855,7 +930,7 @@ static int ath11k_ahb_remove(struct plat - - ath11k_core_deinit(ab); - qmi_fail: -- ath11k_ahb_free_irq(ab); -+ ath11k_hif_free_irq(ab); - ath11k_hal_srng_deinit(ab); - ath11k_ce_free_pipes(ab); - --- a/drivers/net/wireless/ath/ath11k/ce.c +++ b/drivers/net/wireless/ath/ath11k/ce.c -@@ -216,7 +216,7 @@ const struct ce_attr ath11k_host_ce_conf +@@ -217,7 +217,7 @@ const struct ce_attr ath11k_host_ce_conf .flags = CE_ATTR_FLAGS, .src_nentries = 0, .src_sz_max = 2048, @@ -252,11 +265,52 @@ Signed-off-by: Sowmiya Sree Elavalagan .recv_cb = ath11k_htc_rx_completion_handler, }, +@@ -548,7 +548,11 @@ static void ath11k_ce_srng_msi_ring_para + + ring_params->msi_addr = addr_lo; + ring_params->msi_addr |= (dma_addr_t)(((uint64_t)addr_hi) << 32); +- ring_params->msi_data = (msi_data_idx % msi_data_count) + msi_data_start; ++ if (ab->hw_params.internal_pci) ++ ring_params->msi_data = ab->ipci.ce_msi_data[ce_id]; ++ else ++ ring_params->msi_data = (msi_data_idx % msi_data_count) + msi_data_start; ++ + ring_params->flags |= HAL_SRNG_FLAGS_MSI_INTR; + } + +--- a/drivers/net/wireless/ath/ath11k/ce.h ++++ b/drivers/net/wireless/ath/ath11k/ce.h +@@ -7,6 +7,7 @@ + #define ATH11K_CE_H + + #define CE_COUNT_MAX 12 ++#define ATH11K_QCN6122_CE_COUNT 6 + + /* Byte swap data words */ + #define CE_ATTR_BYTE_SWAP_DATA 2 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -534,6 +534,59 @@ static const struct ath11k_hw_params ath - .ce_fwlog_enable = true, - .fwmem_mode_change = false, +@@ -580,6 +580,8 @@ static const struct ath11k_hw_params ath + .hybrid_bus_type = true, + .fixed_fw_mem = true, + .support_off_channel_tx = false, ++ .ce_window = 2, ++ .dp_window = 1, + }, + { + .hw_rev = ATH11K_HW_IPQ5018, +@@ -595,7 +597,7 @@ static const struct ath11k_hw_params ath + .hal_desc_sz = sizeof(struct hal_rx_desc_qcn9074), + .hw_ops = &ipq5018_ops, + .qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ8074, +- .ring_mask = &ath11k_hw_ring_mask_ipq8074, ++ .ring_mask = &ath11k_hw_ring_mask_qcn6122, + .regs = &ipq5018_regs, + .m3_addr = ATH11K_QMI_IPQ5018_M3_DUMP_ADDRESS, + .credit_flow = false, +@@ -647,6 +649,76 @@ static const struct ath11k_hw_params ath + .fixed_fw_mem = false, + .support_off_channel_tx = false, }, + { + .hw_rev = ATH11K_HW_QCN6122, @@ -266,17 +320,20 @@ Signed-off-by: Sowmiya Sree Elavalagan + .board_size = 256 * 1024, + .cal_offset = 128 * 1024, + }, ++ .hal_params = &ath11k_hw_hal_params_ipq8074, + .max_radios = 1, + .bdf_addr = 0x4D200000, + /* hal_desc_sz is similar to qcn9074 */ + .hal_desc_sz = sizeof(struct hal_rx_desc_qcn9074), + .hw_ops = &qcn6122_ops, + .qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCN6122, -+ .hal_params = &ath11k_hw_hal_params_ipq8074, -+ .fix_l1ss = true, -+ .alloc_cacheable_memory = true, + .ring_mask = &ath11k_hw_ring_mask_qcn6122, + .regs = &qcn6122_regs, ++ .num_dscp_tid_map_tbl = HAL_IPQ5018_DSCP_TID_MAP_TBL_NUM_ENTRIES_MAX, ++ ++ .interface_modes = BIT(NL80211_IFTYPE_STATION) | ++ BIT(NL80211_IFTYPE_AP) | ++ BIT(NL80211_IFTYPE_MESH_POINT), + .m3_addr = ATH11K_QMI_QCN6122_M3_DUMP_ADDRESS, + .spectral = { + .fft_sz = 2, @@ -286,10 +343,6 @@ Signed-off-by: Sowmiya Sree Elavalagan + .max_fft_bins = 1024, + }, + .credit_flow = false, -+ .num_dscp_tid_map_tbl = HAL_IPQ5018_DSCP_TID_MAP_TBL_NUM_ENTRIES_MAX, -+ .interface_modes = BIT(NL80211_IFTYPE_STATION) | -+ BIT(NL80211_IFTYPE_AP) | -+ BIT(NL80211_IFTYPE_MESH_POINT), + .supports_monitor = true, + .supports_shadow_regs = false, + .idle_ps = false, @@ -300,7 +353,6 @@ Signed-off-by: Sowmiya Sree Elavalagan + .target_ce_count = 9, + .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq5018, + .svc_to_ce_map_len = 17, -+ .fw_mem_mode = ATH11K_QMI_TARGET_MEM_MODE_512M, + .single_pdev_only = false, + .rxdma1_enable = true, + .num_rxmda_per_pdev = 1, @@ -308,126 +360,118 @@ Signed-off-by: Sowmiya Sree Elavalagan + .vdev_start_delay = false, + .htt_peer_map_v2 = true, + .cold_boot_calib = 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 = false, ++ .internal_pci = true, ++ .ce_window = 2, ++ .dp_window = 3, ++ .fw_mem_mode = ATH11K_QMI_TARGET_MEM_MODE_512M, + .ce_fwlog_enable = false, -+ .fwmem_mode_change = false, ++ .fwmem_mode_change = false, ++ .supports_sta_ps = false, ++ .dbr_debug_support = true, ++ .bios_sar_capa = NULL, ++ .fixed_fw_mem = false, ++ .support_off_channel_tx = false, ++ .m3_offset = ATH11K_QMI_QCN6122_M3_OFFSET, ++ .qdss_offset = ATH11K_QMI_QCN6122_QDSS_OFFSET, ++ .caldb_offset = ATH11K_QMI_QCN6122_CALDB_OFFSET, + }, }; static const struct ath11k_num_vdevs_peers ath11k_vdevs_peers[] = { --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -46,6 +46,8 @@ extern bool ath11k_collect_dump; - - #define ATH11K_RESET_TIMEOUT_HZ (10 * HZ) - #define ATH11K_INVALID_HW_MAC_ID 0xFF -+#define QCN6122_USERPD_0 1 -+#define QCN6122_USERPD_1 2 - #define ATH11K_CONNECTION_LOSS_HZ (3 * HZ) +@@ -55,6 +55,9 @@ extern bool ath11k_collect_dump; #define ATH11K_RX_RATE_TABLE_NUM 320 #define ATH11K_RX_RATE_TABLE_11AX_NUM 576 -@@ -139,6 +141,7 @@ enum ath11k_hw_rev { - ATH11K_HW_WCN6855_HW20, + ++#define QCN6122_USERPD_0 1 ++#define QCN6122_USERPD_1 2 ++ + /* SMBIOS type containing Board Data File Name Extension */ + #define ATH11K_SMBIOS_BDF_EXT_TYPE 0xF8 + +@@ -163,6 +166,7 @@ enum ath11k_hw_rev { ATH11K_HW_WCN6855_HW21, + ATH11K_HW_WCN6750_HW10, ATH11K_HW_IPQ5018, + ATH11K_HW_QCN6122, }; enum ath11k_firmware_mode { -@@ -830,6 +833,12 @@ struct ath11k_num_vdevs_peers { +@@ -949,6 +953,14 @@ struct ath11k_num_vdevs_peers { u32 num_peers; }; +struct ath11k_internal_pci { -+ const struct ath11k_msi_config *msi_cfg; + bool gic_enabled; + wait_queue_head_t gic_msi_waitq; ++ u32 dp_msi_data[ATH11K_EXT_IRQ_GRP_NUM_MAX]; ++ u32 ce_msi_data[ATH11K_QCN6122_CE_COUNT]; ++ u32 dp_irq_num[8]; +}; + /* Master structure to hold the hw data which may be used in core module */ struct ath11k_base { enum ath11k_hw_rev hw_rev; -@@ -963,6 +972,8 @@ struct ath11k_base { - u32 ce_remap_base_addr; - atomic_t num_max_allowed; - struct ath11k_num_vdevs_peers *num_vdevs_peers; +@@ -1013,6 +1025,8 @@ struct ath11k_base { + wait_queue_head_t peer_mapping_wq; + u8 mac_addr[ETH_ALEN]; + bool wmi_ready; + int userpd_id; + struct ath11k_internal_pci ipci; - - /* must be last */ - u8 drv_priv[0] __aligned(sizeof(void *)); + u32 wlan_init_status; + int irq_num[ATH11K_IRQ_NUM_MAX]; + struct ath11k_ext_irq_grp ext_irq_grp[ATH11K_EXT_IRQ_GRP_NUM_MAX]; --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -20,6 +20,8 @@ - - struct dentry *debugfs_ath11k; - -+struct dentry *debugfs_ath11k; -+ - static const char *htt_bp_umac_ring[HTT_SW_UMAC_RING_IDX_MAX] = { - "REO2SW1_RING", - "REO2SW2_RING", -@@ -1560,7 +1562,12 @@ int ath11k_debugfs_soc_create(struct ath +@@ -1469,7 +1469,12 @@ int ath11k_debugfs_soc_create(struct ath return 0; if (ab->hif.bus == ATH11K_BUS_AHB) { - snprintf(soc_name, sizeof(soc_name), "%s", ab->hw_params.name); -+ if (ab->userpd_id) { ++ if (ab->userpd_id) + snprintf(soc_name, sizeof(soc_name), "%s_%d", + ab->hw_params.name, ab->userpd_id); -+ } else { -+ snprintf(soc_name, sizeof(soc_name), "%s", ab->hw_params.name); -+ } ++ else ++ snprintf(soc_name, sizeof(soc_name), "%s", ++ ab->hw_params.name); } else { snprintf(soc_name, sizeof(soc_name), "%s_%s", ab->hw_params.name, dev_name(dev)); --- a/drivers/net/wireless/ath/ath11k/dp.c +++ b/drivers/net/wireless/ath/ath11k/dp.c -@@ -231,6 +231,7 @@ static void ath11k_dp_srng_msi_setup(str +@@ -229,8 +229,12 @@ static void ath11k_dp_srng_msi_setup(str + + ring_params->msi_addr = addr_lo; ring_params->msi_addr |= (dma_addr_t)(((uint64_t)addr_hi) << 32); - ring_params->msi_data = (msi_group_number % msi_data_count) +- ring_params->msi_data = (msi_group_number % msi_data_count) ++ if (ab->hw_params.internal_pci) { ++ ring_params->msi_data = ab->ipci.dp_msi_data[msi_group_number]; ++ } else { ++ ring_params->msi_data = (msi_group_number % msi_data_count) + msi_data_start; -+ ++ } ring_params->flags |= HAL_SRNG_FLAGS_MSI_INTR; } ---- a/drivers/net/wireless/ath/ath11k/hal.h -+++ b/drivers/net/wireless/ath/ath11k/hal.h -@@ -55,7 +55,6 @@ struct ath11k_base; - (ab->hw_params.regs->hal_seq_wcss_umac_ce1_dst_reg) - #define HAL_SEQ_WCSS_UMAC_WBM_REG 0x00a34000 - --#define HAL_CE_WFSS_CE_REG_BASE 0x01b80000 - #define HAL_WLAON_REG_BASE 0x01f80000 - - /* SW2TCL(x) R0 ring configuration address */ --- a/drivers/net/wireless/ath/ath11k/hif.h +++ b/drivers/net/wireless/ath/ath11k/hif.h -@@ -33,6 +33,9 @@ struct ath11k_hif_ops { - void (*ssr_notifier_reg)(struct ath11k_base *ab); +@@ -34,6 +34,7 @@ struct ath11k_hif_ops { void (*ssr_notifier_unreg)(struct ath11k_base *ab); #endif -+ void (*config_static_window)(struct ath11k_base *ab); -+ int (*config_irq)(struct ath11k_base *ab); -+ void (*free_irq)(struct ath11k_base *ab); u32 (*get_window_offset)(struct ath11k_base *ab, u32 offset); ++ void (*config_static_window)(struct ath11k_base *ab); }; -@@ -131,14 +134,6 @@ static inline void ath11k_get_msi_addres - ab->hif.ops->get_msi_address(ab, msi_addr_lo, msi_addr_hi); - } - --static inline u32 ath11k_hif_get_window_offset(struct ath11k_base *ab, u32 offset) --{ -- if (ab->hif.ops->get_window_offset) -- return ab->hif.ops->get_window_offset(ab, offset); -- -- return offset; --} -- - static inline void ath11k_get_ce_msi_idx(struct ath11k_base *ab, u32 ce_id, - u32 *msi_data_idx) - { -@@ -165,4 +160,33 @@ static inline void ath11k_hif_ssr_notifi + static inline void ath11k_hif_ce_irq_enable(struct ath11k_base *ab) +@@ -165,4 +166,12 @@ static inline void ath11k_hif_ssr_notifi ab->hif.ops->ssr_notifier_unreg(ab); } #endif @@ -438,52 +482,31 @@ Signed-off-by: Sowmiya Sree Elavalagan + return; + + ab->hif.ops->config_static_window(ab); -+} -+ -+static inline void ath11k_hif_free_irq(struct ath11k_base *ab) -+{ -+ if (!ab->hif.ops->free_irq) -+ return; -+ -+ return ab->hif.ops->free_irq(ab); -+} -+ -+static inline int ath11k_hif_config_irq(struct ath11k_base *ab) -+{ -+ return ab->hif.ops->config_irq(ab); -+} -+ -+static inline u32 ath11k_hif_get_window_offset(struct ath11k_base *ab, u32 offset) -+{ -+ if (ab->hif.ops->get_window_offset) -+ return ab->hif.ops->get_window_offset(ab, offset); -+ -+ return offset; +} #endif /* _HIF_H_ */ --- a/drivers/net/wireless/ath/ath11k/hw.c +++ b/drivers/net/wireless/ath/ath11k/hw.c -@@ -1241,6 +1241,51 @@ const struct ath11k_hw_ops ipq5018_ops = +@@ -1287,6 +1287,49 @@ const struct ath11k_hw_ops ipq5018_ops = .rx_desc_get_hal_mpdu_len = ath11k_hw_qcn9074_rx_desc_get_hal_mpdu_len, - }; + }; +const struct ath11k_hw_ops qcn6122_ops = { + .get_hw_mac_from_pdev_id = ath11k_hw_ipq6018_mac_from_pdev_id, + .wmi_init_config = ath11k_init_wmi_config_ipq8074, + .mac_id_to_pdev_id = ath11k_hw_mac_id_to_pdev_id_ipq8074, + .mac_id_to_srng_id = ath11k_hw_mac_id_to_srng_id_ipq8074, -+ .rx_desc_mac_addr2_valid = ath11k_hw_qcn9074_rx_desc_mac_addr2_valid, -+ .rx_desc_mpdu_start_addr2 = ath11k_hw_qcn9074_rx_desc_mpdu_start_addr2, ++ .rx_desc_mac_addr2_valid = ath11k_hw_ipq9074_rx_desc_mac_addr2_valid, ++ .rx_desc_mpdu_start_addr2 = ath11k_hw_ipq9074_rx_desc_mpdu_start_addr2, + .tx_mesh_enable = ath11k_hw_qcn9074_tx_mesh_enable, + .rx_desc_get_first_msdu = ath11k_hw_qcn9074_rx_desc_get_first_msdu, + .rx_desc_get_last_msdu = ath11k_hw_qcn9074_rx_desc_get_last_msdu, + .rx_desc_get_l3_pad_bytes = ath11k_hw_qcn9074_rx_desc_get_l3_pad_bytes, + .rx_desc_get_hdr_status = ath11k_hw_qcn9074_rx_desc_get_hdr_status, + .rx_desc_encrypt_valid = ath11k_hw_qcn9074_rx_desc_encrypt_valid, -+ .rx_desc_get_ldpc_support = ath11k_hw_qcn9074_rx_desc_get_ldpc_support, + .rx_desc_get_encrypt_type = ath11k_hw_qcn9074_rx_desc_get_encrypt_type, + .rx_desc_get_decap_type = ath11k_hw_qcn9074_rx_desc_get_decap_type, + .rx_desc_get_mesh_ctl = ath11k_hw_qcn9074_rx_desc_get_mesh_ctl, ++ .rx_desc_get_ldpc_support = ath11k_hw_qcn9074_rx_desc_get_ldpc_support, + .rx_desc_get_mpdu_seq_ctl_vld = ath11k_hw_qcn9074_rx_desc_get_mpdu_seq_ctl_vld, + .rx_desc_get_mpdu_fc_valid = ath11k_hw_qcn9074_rx_desc_get_mpdu_fc_valid, + .rx_desc_get_mpdu_start_seq_no = ath11k_hw_qcn9074_rx_desc_get_mpdu_start_seq_no, @@ -498,24 +521,22 @@ Signed-off-by: Sowmiya Sree Elavalagan + .rx_desc_get_mpdu_peer_id = ath11k_hw_qcn9074_rx_desc_get_mpdu_peer_id, + .rx_desc_copy_attn_end_tlv = ath11k_hw_qcn9074_rx_desc_copy_attn_end, + .rx_desc_get_mpdu_start_tag = ath11k_hw_qcn9074_rx_desc_get_mpdu_start_tag, -+ .reo_setup = ath11k_hw_ipq5018_reo_setup, -+ .set_rx_fragmentation_dst_ring = ath11k_hw_ipq5018_set_rx_fragmentation_dst_ring, + .rx_desc_get_mpdu_ppdu_id = ath11k_hw_qcn9074_rx_desc_get_mpdu_ppdu_id, + .rx_desc_set_msdu_len = ath11k_hw_qcn9074_rx_desc_set_msdu_len, ++ .reo_setup = ath11k_hw_ipq5018_reo_setup, + .rx_desc_get_attention = ath11k_hw_qcn9074_rx_desc_get_attention, + .rx_desc_get_msdu_payload = ath11k_hw_qcn9074_rx_desc_get_msdu_payload, -+ .mpdu_info_get_peerid = ath11k_hw_qcn9074_mpdu_info_get_peerid, -+ .rx_desc_get_hal_mpdu_len = ath11k_hw_qcn9074_rx_desc_get_hal_mpdu_len, ++ .mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid, ++ .set_rx_fragmentation_dst_ring = ath11k_hw_ipq5018_set_rx_fragmentation_dst_ring, + .get_reo_dest_remap_config = ath11k_get_reo_dest_remap_config_5018, -+#ifdef CPTCFG_ATH11K_MEM_PROFILE_512M -+#endif ++ .rx_desc_get_hal_mpdu_len = ath11k_hw_qcn9074_rx_desc_get_hal_mpdu_len, ++ .rx_desc_get_hal_ppdu_id = ath11k_hw_qcn9074_rx_desc_get_hal_mpdu_ppdu_id, +}; -+ + #define ATH11K_TX_RING_MASK_0 0x1 #define ATH11K_TX_RING_MASK_1 0x2 #define ATH11K_TX_RING_MASK_2 0x4 -@@ -2049,6 +2094,41 @@ const struct service_to_pipe ath11k_targ +@@ -2095,6 +2138,43 @@ const struct service_to_pipe ath11k_targ }, }; @@ -537,12 +558,14 @@ Signed-off-by: Sowmiya Sree Elavalagan + 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 = { ++ .reo_status = { + 0, 0, 0, + ATH11K_REO_STATUS_RING_MASK_0, + }, @@ -557,11 +580,10 @@ Signed-off-by: Sowmiya Sree Elavalagan /* 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 */ -@@ -2671,3 +2751,79 @@ const struct ath11k_hw_hal_params ath11k - const struct ath11k_hw_hal_params ath11k_hw_hal_params_qca6390 = { - .rx_buf_rbm = HAL_RX_BUF_RBM_SW1_BM, +@@ -2855,6 +2935,81 @@ const struct ath11k_hw_regs wcn6750_regs + .hal_reo1_misc_ctl = 0x000005d8, }; -+ + +const struct ath11k_hw_regs qcn6122_regs = { + /* SW2TCL(x) R0 ring configuration address */ + .hal_tcl1_ring_base_lsb = 0x00000694, @@ -637,9 +659,12 @@ Signed-off-by: Sowmiya Sree Elavalagan + .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, + }; --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h -@@ -91,9 +91,12 @@ +@@ -92,9 +92,12 @@ #define ATH11K_BOARD_API2_FILE "board-2.bin" #define ATH11K_DEFAULT_BOARD_FILE "board.bin" #define ATH11K_DEFAULT_CAL_FILE "caldata.bin" @@ -648,13 +673,31 @@ Signed-off-by: Sowmiya Sree Elavalagan #define ATH11K_AMSS_FILE "amss.bin" #define ATH11K_M3_FILE "m3.bin" #define ATH11K_REGDB_FILE_NAME "regdb.bin" -+#define NODE_ID_BASE 0x27 ++#define NODE_ID_BASE 0x27 enum ath11k_hw_rate_cck { ATH11K_HW_RATE_CCK_LP_11M = 0, -@@ -268,10 +271,12 @@ extern const struct ath11k_hw_ops qca639 - extern const struct ath11k_hw_ops qcn9074_ops; +@@ -123,6 +126,7 @@ enum ath11k_bus { + }; + + #define ATH11K_EXT_IRQ_GRP_NUM_MAX 11 ++#define ATH11K_EXT_MSI_IRQ_GRP_MAX 8 + + struct hal_rx_desc; + struct hal_tcl_data_cmd; +@@ -222,6 +226,9 @@ struct ath11k_hw_params { + bool hybrid_bus_type; + bool fixed_fw_mem; + bool support_off_channel_tx; ++ bool internal_pci; ++ u8 ce_window; ++ u8 dp_window; + }; + + struct ath11k_hw_ops { +@@ -276,10 +283,12 @@ extern const struct ath11k_hw_ops qcn907 extern const struct ath11k_hw_ops wcn6855_ops; + extern const struct ath11k_hw_ops wcn6750_ops; extern const struct ath11k_hw_ops ipq5018_ops; +extern const struct ath11k_hw_ops qcn6122_ops; @@ -665,718 +708,105 @@ Signed-off-by: Sowmiya Sree Elavalagan extern const struct ath11k_hw_hal_params ath11k_hw_hal_params_ipq8074; extern const struct ath11k_hw_hal_params ath11k_hw_hal_params_qca6390; -@@ -392,5 +397,6 @@ extern const struct ath11k_hw_regs qca63 - extern const struct ath11k_hw_regs qcn9074_regs; +@@ -410,6 +419,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; - #endif ---- a/drivers/net/wireless/ath/ath11k/mhi.c -+++ b/drivers/net/wireless/ath/ath11k/mhi.c -@@ -11,6 +11,7 @@ - #include "debug.h" - #include "mhi.h" - #include "pci.h" -+#include "pci_cmn.h" - - #define MHI_TIMEOUT_DEFAULT_MS 90000 - -@@ -261,7 +262,8 @@ static int ath11k_mhi_get_msi(struct ath - int *irq; - unsigned int msi_data; - -- ret = ath11k_pci_get_user_msi_assignment(ab_pci, -+ ret = ath11k_pci_get_user_msi_assignment(ab, ab_pci->msi_config, -+ ab_pci->msi_ep_base_data, - "MHI", &num_vectors, - &user_base_data, &base_vector); - if (ret) + static inline const char *ath11k_bd_ie_type_str(enum ath11k_bd_ie_type type) + { --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c -@@ -14,20 +14,14 @@ - #include "mhi.h" - #include "debug.h" - #include "qmi.h" -+#include "pci_cmn.h" - #include +@@ -53,32 +53,7 @@ static void ath11k_pci_bus_release(struc - #define ATH11K_PCI_BAR_NUM 0 - #define ATH11K_PCI_DMA_MASK 32 - --#define ATH11K_PCI_IRQ_CE0_OFFSET 3 - #define ATH11K_PCI_IRQ_DP_OFFSET 14 - --#define WINDOW_ENABLE_BIT 0x40000000 --#define WINDOW_REG_ADDRESS 0x310c --#define WINDOW_VALUE_MASK GENMASK(24, 19) --#define WINDOW_START 0x80000 --#define WINDOW_RANGE_MASK GENMASK(18, 0) -- - #define TCSR_SOC_HW_VERSION 0x0224 - #define TCSR_SOC_HW_VERSION_MAJOR_MASK GENMASK(11, 8) - #define TCSR_SOC_HW_VERSION_MINOR_MASK GENMASK(7, 0) -@@ -58,28 +52,6 @@ static const struct ath11k_bus_params at - .fixed_mem_region = false, - }; - --static const struct ath11k_msi_config ath11k_msi_config[] = { -- { -- .total_vectors = 32, -- .total_users = 4, -- .users = (struct ath11k_msi_user[]) { -- { .name = "MHI", .num_vectors = 3, .base_vector = 0 }, -- { .name = "CE", .num_vectors = 10, .base_vector = 3 }, -- { .name = "WAKE", .num_vectors = 1, .base_vector = 13 }, -- { .name = "DP", .num_vectors = 18, .base_vector = 14 }, -- }, -- }, -- { -- .total_vectors = 16, -- .total_users = 3, -- .users = (struct ath11k_msi_user[]) { -- { .name = "MHI", .num_vectors = 3, .base_vector = 0 }, -- { .name = "CE", .num_vectors = 5, .base_vector = 3 }, -- { .name = "DP", .num_vectors = 8, .base_vector = 8 }, -- }, -- }, --}; -- - static const struct ath11k_msi_config msi_config_one_msi = { - .total_vectors = 1, - .total_users = 4, -@@ -91,18 +63,6 @@ static const struct ath11k_msi_config ms - }, - }; - --const char *ce_irq_name[ATH11K_MAX_PCI_DOMAINS + 1][CE_COUNT_MAX] = { -- { -- ATH11K_PCI_CE_IRQS_NAME(0) -- }, -- { -- ATH11K_PCI_CE_IRQS_NAME(1) -- }, -- { -- ATH11K_PCI_CE_IRQS_NAME() -- }, --}; -- - static inline void ath11k_pci_select_window(struct ath11k_pci *ab_pci, u32 offset) + static u32 ath11k_pci_get_window_start(struct ath11k_base *ab, u32 offset) { - struct ath11k_base *ab = ab_pci->ab; -@@ -119,48 +79,6 @@ static inline void ath11k_pci_select_win - } - } - --static inline void ath11k_pci_select_static_window(struct ath11k_pci *ab_pci) --{ -- u32 umac_window = FIELD_GET(WINDOW_VALUE_MASK, HAL_SEQ_WCSS_UMAC_OFFSET); -- u32 ce_window = FIELD_GET(WINDOW_VALUE_MASK, HAL_CE_WFSS_CE_REG_BASE); -- u32 window; +- if (!ab->hw_params.static_window_map) +- return ATH11K_PCI_WINDOW_START; - -- window = (umac_window << 12) | (ce_window << 6); -- -- iowrite32(WINDOW_ENABLE_BIT | window, ab_pci->ab->mem + WINDOW_REG_ADDRESS); --} -- --static inline u32 ath11k_pci_get_window_start(struct ath11k_base *ab, -- u32 offset) --{ -- u32 window_start; -- -- /* If offset lies within DP register range, use 3rd window */ -- if ((offset ^ HAL_SEQ_WCSS_UMAC_OFFSET) < WINDOW_RANGE_MASK) -- window_start = 3 * WINDOW_START; -- /* If offset lies within CE register range, use 2nd window */ -- else if ((offset ^ HAL_CE_WFSS_CE_REG_BASE) < WINDOW_RANGE_MASK) -- window_start = 2 * WINDOW_START; +- if ((offset ^ HAL_SEQ_WCSS_UMAC_OFFSET) < ATH11K_PCI_WINDOW_RANGE_MASK) +- /* if offset lies within DP register range, use 3rd window */ +- return 3 * ATH11K_PCI_WINDOW_START; +- else if ((offset ^ HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab)) < +- ATH11K_PCI_WINDOW_RANGE_MASK) +- /* if offset lies within CE register range, use 2nd window */ +- return 2 * ATH11K_PCI_WINDOW_START; - else -- window_start = WINDOW_START; -- -- return window_start; +- return ATH11K_PCI_WINDOW_START; -} - -static inline u32 ath11k_pci_get_window_offset(struct ath11k_base *ab, -- u32 offset) +- u32 offset) -{ -- u32 window_start; +- u32 window_start; - -- if (ab->bus_params.static_window_map) { -- window_start = ath11k_pci_get_window_start(ab, offset); +- if (ab->hw_params.static_window_map) { +- window_start = ath11k_pci_get_window_start(ab, offset); - -- if (window_start) -- offset = window_start + (offset & WINDOW_RANGE_MASK); -- } -- return offset; --} -- - void ath11k_pci_write32(struct ath11k_base *ab, u32 offset, u32 value) - { - struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); -@@ -461,318 +379,18 @@ static void ath11k_pci_get_msi_address(s - } +- if (window_start) +- offset = window_start + (offset & ATH11K_PCI_WINDOW_RANGE_MASK); +- } +- return offset; ++ return ath11k_pcic_get_window_start(ab, offset, ATH11K_BUS_PCI); } --int ath11k_pci_get_user_msi_assignment(struct ath11k_pci *ab_pci, char *user_name, -- int *num_vectors, u32 *user_base_data, -- u32 *base_vector) + static inline void ath11k_pci_select_window(struct ath11k_pci *ab_pci, u32 offset) +@@ -172,20 +147,6 @@ static const struct ath11k_msi_config ms + }, + }; + +-static inline void ath11k_pci_select_static_window(struct ath11k_pci *ab_pci) -{ -- struct ath11k_base *ab = ab_pci->ab; -- const struct ath11k_msi_config *msi_config = ab_pci->msi_config; -- int idx; +- u32 umac_window; +- u32 ce_window; +- u32 window; - -- for (idx = 0; idx < msi_config->total_users; idx++) { -- if (strcmp(user_name, msi_config->users[idx].name) == 0) { -- *num_vectors = msi_config->users[idx].num_vectors; -- *base_vector = msi_config->users[idx].base_vector; -- *user_base_data = *base_vector + ab_pci->msi_ep_base_data; +- umac_window = FIELD_GET(ATH11K_PCI_WINDOW_VALUE_MASK, HAL_SEQ_WCSS_UMAC_OFFSET); +- ce_window = FIELD_GET(ATH11K_PCI_WINDOW_VALUE_MASK, HAL_CE_WFSS_CE_REG_BASE); +- window = (umac_window << 12) | (ce_window << 6); - -- ath11k_dbg(ab, ATH11K_DBG_PCI, -- "Assign MSI to user: %s, num_vectors: %d, user_base_data: %u, base_vector: %u\n", -- user_name, *num_vectors, *user_base_data, -- *base_vector); -- -- return 0; -- } -- } -- -- ath11k_err(ab, "Failed to find MSI assignment for %s!\n", user_name); -- -- return -EINVAL; +- iowrite32(ATH11K_PCI_WINDOW_ENABLE_BIT | window, +- ab_pci->ab->mem + ATH11K_PCI_WINDOW_REG_ADDRESS); -} - --static void ath11k_pci_get_ce_msi_idx(struct ath11k_base *ab, u32 ce_id, -- u32 *msi_idx) --{ -- u32 i, msi_data_idx; -- -- for (i = 0, msi_data_idx = 0; i < ab->hw_params.ce_count; i++) { -- if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) -- continue; -- -- if (ce_id == i) -- break; -- -- msi_data_idx++; -- } -- *msi_idx = msi_data_idx; --} -- - static int ath11k_get_user_msi_assignment(struct ath11k_base *ab, char *user_name, - int *num_vectors, u32 *user_base_data, - u32 *base_vector) + static void ath11k_pci_soc_global_reset(struct ath11k_base *ab) { - struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); + u32 val, delay; +@@ -393,6 +354,7 @@ static void ath11k_pci_init_qmi_ce_confi + 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; ++ ab->qmi.service_ins_id += ab->userpd_id; -- return ath11k_pci_get_user_msi_assignment(ab_pci, user_name, -+ return ath11k_pci_get_user_msi_assignment(ab, ab_pci->msi_config, -+ ab_pci->msi_ep_base_data, user_name, - num_vectors, user_base_data, - base_vector); - } - --const char *dp_irq_name[ATH11K_MAX_PCI_DOMAINS + 1][ATH11K_EXT_IRQ_GRP_NUM_MAX] = { -- { -- ATH11K_PCI_DP_IRQS_NAME(0) -- }, -- { -- ATH11K_PCI_DP_IRQS_NAME(1) -- }, -- { -- ATH11K_PCI_DP_IRQS_NAME() -- }, --}; -- --static void ath11k_pci_free_ext_irq(struct ath11k_base *ab) --{ -- int i, j; -- -- for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { -- struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; -- -- for (j = 0; j < irq_grp->num_irq; j++) -- free_irq(ab->irq_num[irq_grp->irqs[j]], irq_grp); -- -- netif_napi_del(&irq_grp->napi); -- } --} -- --static void ath11k_pci_free_irq(struct ath11k_base *ab) --{ -- int i, irq_idx; -- -- for (i = 0; i < ab->hw_params.ce_count; i++) { -- if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) -- continue; -- irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i; -- free_irq(ab->irq_num[irq_idx], &ab->ce.ce_pipe[i]); -- } -- -- ath11k_pci_free_ext_irq(ab); --} -- --static void ath11k_pci_ce_irq_enable(struct ath11k_base *ab, u16 ce_id) --{ -- struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); -- u32 irq_idx; -- -- /* In case of one MSI vector, we handle irq enable/disable in a -- * uniform way since we only have one irq -- */ -- if (!test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags)) -- return; -- -- irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id; -- enable_irq(ab->irq_num[irq_idx]); --} -- --static void ath11k_pci_ce_irq_disable(struct ath11k_base *ab, u16 ce_id) --{ -- struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); -- u32 irq_idx; -- -- /* In case of one MSI vector, we handle irq enable/disable in a -- * uniform way since we only have one irq -- */ -- if (!test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags)) -- return; -- -- irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id; -- disable_irq_nosync(ab->irq_num[irq_idx]); --} -- --static void ath11k_pci_ce_irqs_disable(struct ath11k_base *ab) --{ -- int i; -- -- clear_bit(ATH11K_FLAG_CE_IRQ_ENABLED, &ab->dev_flags); -- -- for (i = 0; i < ab->hw_params.ce_count; i++) { -- if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) -- continue; -- ath11k_pci_ce_irq_disable(ab, i); -- } --} -- --static void ath11k_pci_sync_ce_irqs(struct ath11k_base *ab) --{ -- int i; -- int irq_idx; -- -- for (i = 0; i < ab->hw_params.ce_count; i++) { -- if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) -- continue; -- -- irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i; -- synchronize_irq(ab->irq_num[irq_idx]); -- } --} -- --static void ath11k_pci_ce_tasklet(struct tasklet_struct *t) --{ -- struct ath11k_ce_pipe *ce_pipe = from_tasklet(ce_pipe, t, intr_tq); -- int irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_pipe->pipe_num; -- -- ath11k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num); -- -- enable_irq(ce_pipe->ab->irq_num[irq_idx]); --} -- --static irqreturn_t ath11k_pci_ce_interrupt_handler(int irq, void *arg) --{ -- struct ath11k_ce_pipe *ce_pipe = arg; -- struct ath11k_base *ab = ce_pipe->ab; -- int irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_pipe->pipe_num; -- -- if (!test_bit(ATH11K_FLAG_CE_IRQ_ENABLED, &ab->dev_flags)) -- return IRQ_HANDLED; -- -- /* last interrupt received for this CE */ -- ce_pipe->timestamp = jiffies; -- -- disable_irq_nosync(ab->irq_num[irq_idx]); -- -- tasklet_schedule(&ce_pipe->intr_tq); -- -- return IRQ_HANDLED; --} -- --static void ath11k_pci_ext_grp_disable(struct ath11k_ext_irq_grp *irq_grp) --{ -- struct ath11k_pci *ab_pci = ath11k_pci_priv(irq_grp->ab); -- int i; -- -- /* In case of one MSI vector, we handle irq enable/disable -- * in a uniform way since we only have one irq -- */ -- if (!test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags)) -- return; -- -- for (i = 0; i < irq_grp->num_irq; i++) -- disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]); --} -- --static void __ath11k_pci_ext_irq_disable(struct ath11k_base *sc) --{ -- int i; -- -- clear_bit(ATH11K_FLAG_EXT_IRQ_ENABLED, &sc->dev_flags); -- -- for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { -- struct ath11k_ext_irq_grp *irq_grp = &sc->ext_irq_grp[i]; -- -- ath11k_pci_ext_grp_disable(irq_grp); -- -- if (irq_grp->napi_enabled) { -- napi_synchronize(&irq_grp->napi); -- napi_disable(&irq_grp->napi); -- irq_grp->napi_enabled = false; -- } -- } --} -- --static void ath11k_pci_ext_grp_enable(struct ath11k_ext_irq_grp *irq_grp) --{ -- struct ath11k_pci *ab_pci = ath11k_pci_priv(irq_grp->ab); -- int i; -- -- /* In case of one MSI vector, we handle irq enable/disable in a -- * uniform way since we only have one irq -- */ -- if (!test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags)) -- return; -- -- for (i = 0; i < irq_grp->num_irq; i++) -- enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]); --} -- --static void ath11k_pci_ext_irq_enable(struct ath11k_base *ab) --{ -- int i; -- -- set_bit(ATH11K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags); -- -- for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { -- struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; -- -- if (!irq_grp->napi_enabled) { -- napi_enable(&irq_grp->napi); -- irq_grp->napi_enabled = true; -- } -- ath11k_pci_ext_grp_enable(irq_grp); -- } --} -- --static void ath11k_pci_sync_ext_irqs(struct ath11k_base *ab) --{ -- int i, j, irq_idx; -- -- for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { -- struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; -- -- for (j = 0; j < irq_grp->num_irq; j++) { -- irq_idx = irq_grp->irqs[j]; -- synchronize_irq(ab->irq_num[irq_idx]); -- } -- } --} -- --static void ath11k_pci_ext_irq_disable(struct ath11k_base *ab) --{ -- __ath11k_pci_ext_irq_disable(ab); -- ath11k_pci_sync_ext_irqs(ab); --} -- --static int ath11k_pci_ext_grp_napi_poll(struct napi_struct *napi, int budget) --{ -- struct ath11k_ext_irq_grp *irq_grp = container_of(napi, -- struct ath11k_ext_irq_grp, -- napi); -- struct ath11k_base *ab = irq_grp->ab; -- int work_done; -- int i; -- -- work_done = ath11k_dp_service_srng(ab, irq_grp, budget); -- if (work_done < budget) { -- napi_complete_done(napi, work_done); -- for (i = 0; i < irq_grp->num_irq; i++) -- enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]); -- } -- -- if (work_done > budget) -- work_done = budget; -- -- return work_done; --} -- --static irqreturn_t ath11k_pci_ext_interrupt_handler(int irq, void *arg) --{ -- struct ath11k_ext_irq_grp *irq_grp = arg; -- struct ath11k_base *ab = irq_grp->ab; -- int i; -- -- if (!test_bit(ATH11K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags)) -- return IRQ_HANDLED; -- -- ath11k_dbg(irq_grp->ab, ATH11K_DBG_PCI, "ext irq:%d\n", irq); -- -- /* last interrupt received for this group */ -- irq_grp->timestamp = jiffies; -- -- for (i = 0; i < irq_grp->num_irq; i++) -- disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]); -- -- napi_schedule(&irq_grp->napi); -- -- return IRQ_HANDLED; --} -- - static int ath11k_pci_ext_irq_config(struct ath11k_base *ab) - { - struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); -@@ -784,7 +402,8 @@ static int ath11k_pci_ext_irq_config(str - if (domain_id > ATH11K_MAX_PCI_DOMAINS) - domain_id = ATH11K_MAX_PCI_DOMAINS; - -- ret = ath11k_pci_get_user_msi_assignment(ath11k_pci_priv(ab), "DP", -+ ret = ath11k_pci_get_user_msi_assignment(ab, ar_pci->msi_config, -+ ar_pci->msi_ep_base_data, "DP", - &num_vectors, - &user_base_data, - &base_vector); -@@ -870,7 +489,8 @@ static int ath11k_pci_config_irq(struct - if (domain_id > ATH11K_MAX_PCI_DOMAINS) - domain_id = ATH11K_MAX_PCI_DOMAINS; - -- ret = ath11k_pci_get_user_msi_assignment(ath11k_pci_priv(ab), -+ ret = ath11k_pci_get_user_msi_assignment(ab, ar_pci->msi_config, -+ ar_pci->msi_ep_base_data, - "CE", &msi_data_count, - &msi_data_start, &msi_irq_start); - if (ret) -@@ -940,19 +560,6 @@ static void ath11k_pci_init_qmi_ce_confi - &cfg->shadow_reg_v2_len); - } - --static void ath11k_pci_ce_irqs_enable(struct ath11k_base *ab) --{ -- int i; -- -- set_bit(ATH11K_FLAG_CE_IRQ_ENABLED, &ab->dev_flags); -- -- for (i = 0; i < ab->hw_params.ce_count; i++) { -- if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) -- continue; -- ath11k_pci_ce_irq_enable(ab, i); -- } --} -- - static void ath11k_pci_msi_config(struct ath11k_pci *ab_pci, bool enable) - { - struct pci_dev *dev = ab_pci->pdev; -@@ -1153,13 +760,6 @@ static void ath11k_pci_aspm_disable(stru - set_bit(ATH11K_PCI_ASPM_RESTORE, &ab_pci->flags); - } - --static void ath11k_pci_aspm_restore(struct ath11k_pci *ab_pci) --{ -- if (test_and_clear_bit(ATH11K_PCI_ASPM_RESTORE, &ab_pci->flags)) -- pcie_capability_write_word(ab_pci->pdev, PCI_EXP_LNKCTL, -- ab_pci->link_ctl); --} -- - static int ath11k_pci_power_up(struct ath11k_base *ab) - { - struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); -@@ -1184,7 +784,7 @@ static int ath11k_pci_power_up(struct at + ret = of_property_read_u32(ab->dev->of_node, "qrtr_instance_id", &node_id); + if (!ret) +@@ -639,7 +601,7 @@ static int ath11k_pci_power_up(struct at } - if (ab->bus_params.static_window_map) + if (ab->hw_params.static_window_map) - ath11k_pci_select_static_window(ab_pci); -+ ath11k_pci_select_static_window(ab); ++ ath11k_pcic_config_static_window(ab); return 0; } -@@ -1223,53 +823,6 @@ static int ath11k_pci_hif_resume(struct - return 0; - } - --static void ath11k_pci_kill_tasklets(struct ath11k_base *ab) --{ -- int i; -- -- for (i = 0; i < ab->hw_params.ce_count; i++) { -- struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i]; -- -- if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) -- continue; -- -- tasklet_kill(&ce_pipe->intr_tq); -- } --} -- --static void ath11k_pci_ce_irq_disable_sync(struct ath11k_base *ab) --{ -- ath11k_pci_ce_irqs_disable(ab); -- ath11k_pci_sync_ce_irqs(ab); -- ath11k_pci_kill_tasklets(ab); --} -- --static void ath11k_pci_stop(struct ath11k_base *ab) --{ -- ath11k_pci_ce_irq_disable_sync(ab); -- ath11k_ce_cleanup_pipes(ab); --} -- --static int ath11k_pci_start(struct ath11k_base *ab) --{ -- struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); -- -- set_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags); -- -- /* TODO: for now don't restore ASPM in case of single MSI -- * vector as MHI register reading in M2 causes system hang. -- */ -- if (test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags)) -- ath11k_pci_aspm_restore(ab_pci); -- else -- ath11k_info(ab, "leaving PCI ASPM disabled to avoid MHI M2 problems\n"); -- -- ath11k_pci_ce_irqs_enable(ab); -- ath11k_ce_rx_post_buf(ab); -- -- return 0; --} -- - static void ath11k_pci_hif_ce_irq_enable(struct ath11k_base *ab) - { - ath11k_pci_ce_irqs_enable(ab); -@@ -1280,49 +833,6 @@ static void ath11k_pci_hif_ce_irq_disabl - ath11k_pci_ce_irq_disable_sync(ab); - } - --static int ath11k_pci_map_service_to_pipe(struct ath11k_base *ab, u16 service_id, -- u8 *ul_pipe, u8 *dl_pipe) --{ -- const struct service_to_pipe *entry; -- bool ul_set = false, dl_set = false; -- int i; -- -- for (i = 0; i < ab->hw_params.svc_to_ce_map_len; i++) { -- entry = &ab->hw_params.svc_to_ce_map[i]; -- -- if (__le32_to_cpu(entry->service_id) != service_id) -- continue; -- -- switch (__le32_to_cpu(entry->pipedir)) { -- case PIPEDIR_NONE: -- break; -- case PIPEDIR_IN: -- WARN_ON(dl_set); -- *dl_pipe = __le32_to_cpu(entry->pipenum); -- dl_set = true; -- break; -- case PIPEDIR_OUT: -- WARN_ON(ul_set); -- *ul_pipe = __le32_to_cpu(entry->pipenum); -- ul_set = true; -- break; -- case PIPEDIR_INOUT: -- WARN_ON(dl_set); -- WARN_ON(ul_set); -- *dl_pipe = __le32_to_cpu(entry->pipenum); -- *ul_pipe = __le32_to_cpu(entry->pipenum); -- dl_set = true; -- ul_set = true; -- break; -- } -- } -- -- if (WARN_ON(!ul_set || !dl_set)) -- return -ENOENT; -- -- return 0; --} -- - static const struct ath11k_hif_ops ath11k_pci_hif_ops = { - .start = ath11k_pci_start, - .stop = ath11k_pci_stop, ---- a/drivers/net/wireless/ath/ath11k/pci.h -+++ b/drivers/net/wireless/ath/ath11k/pci.h -@@ -128,9 +128,6 @@ static inline struct ath11k_pci *ath11k_ - return (struct ath11k_pci *)ab->drv_priv; - } - --int ath11k_pci_get_user_msi_assignment(struct ath11k_pci *ar_pci, char *user_name, -- int *num_vectors, u32 *user_base_data, -- u32 *base_vector); - int ath11k_pci_get_msi_irq(struct device *dev, unsigned int vector); - void ath11k_pci_write32(struct ath11k_base *ab, u32 offset, u32 value); - u32 ath11k_pci_read32(struct ath11k_base *ab, u32 offset); ---- /dev/null -+++ b/drivers/net/wireless/ath/ath11k/pci_cmn.c -@@ -0,0 +1,593 @@ -+// SPDX-License-Identifier: BSD-3-Clause-Clear -+/* -+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#include +--- a/drivers/net/wireless/ath/ath11k/pcic.c ++++ b/drivers/net/wireless/ath/ath11k/pcic.c +@@ -7,6 +7,10 @@ + #include "core.h" + #include "pcic.h" + #include "debug.h" ++#include "pci.h" +#include -+#include "core.h" -+#include "pci_cmn.h" -+#include "debug.h" -+ -+const char *dp_irq_name[ATH11K_MAX_PCI_DOMAINS + 1][ATH11K_EXT_IRQ_GRP_NUM_MAX] = { -+ { -+ ATH11K_PCI_DP_IRQS_NAME(0) -+ }, -+ { -+ ATH11K_PCI_DP_IRQS_NAME(1) -+ }, -+ { -+ ATH11K_PCI_DP_IRQS_NAME() -+ }, -+}; -+ -+const char *ce_irq_name[ATH11K_MAX_PCI_DOMAINS + 1][CE_COUNT_MAX] = { -+ { -+ ATH11K_PCI_CE_IRQS_NAME(0) -+ }, -+ { -+ ATH11K_PCI_CE_IRQS_NAME(1) -+ }, -+ { -+ ATH11K_PCI_CE_IRQS_NAME() -+ }, -+}; -+ -+enum ath11k_msi_supported_hw { -+ ATH11K_MSI_CONFIG_QCA6390, -+ ATH11K_MSI_CONFIG_QCN9074, -+ ATH11K_MSI_CONFIG_QCN6122, -+}; -+ -+const struct ath11k_msi_config ath11k_msi_config[] = { -+ { -+ .total_vectors = 32, -+ .total_users = 4, -+ .users = (struct ath11k_msi_user[]) { -+ { .name = "MHI", .num_vectors = 3, .base_vector = 0 }, -+ { .name = "CE", .num_vectors = 10, .base_vector = 3 }, -+ { .name = "WAKE", .num_vectors = 1, .base_vector = 13 }, -+ { .name = "DP", .num_vectors = 18, .base_vector = 14 }, -+ }, -+ }, -+ { -+ .total_vectors = 16, -+ .total_users = 3, -+ .users = (struct ath11k_msi_user[]) { -+ { .name = "MHI", .num_vectors = 3, .base_vector = 0 }, -+ { .name = "CE", .num_vectors = 5, .base_vector = 3 }, -+ { .name = "DP", .num_vectors = 8, .base_vector = 8 }, -+ }, -+ }, ++#include ++#include + + const char *ce_irq_name[ATH11K_MAX_PCI_DOMAINS + 1][CE_COUNT_MAX] = { + { +@@ -85,6 +89,15 @@ static const struct ath11k_msi_config at + }, + .hw_rev = ATH11K_HW_WCN6750_HW10, + }, + { + .total_vectors = 13, + .total_users = 2, @@ -1384,516 +814,166 @@ Signed-off-by: Sowmiya Sree Elavalagan + { .name = "CE", .num_vectors = 5, .base_vector = 0 }, + { .name = "DP", .num_vectors = 8, .base_vector = 5 }, + }, ++ .hw_rev = ATH11K_HW_QCN6122, + }, -+}; -+ -+inline void ath11k_pci_select_static_window(struct ath11k_base *ab) + }; + + int ath11k_pcic_init_msi_config(struct ath11k_base *ab) +@@ -241,6 +254,15 @@ void ath11k_pcic_free_irq(struct ath11k_ + } + EXPORT_SYMBOL(ath11k_pcic_free_irq); + ++void ath11k_pcic_ipci_free_irq(struct ath11k_base *ab) +{ -+ u32 umac_window = FIELD_GET(WINDOW_VALUE_MASK, HAL_SEQ_WCSS_UMAC_OFFSET); -+ u32 ce_window = FIELD_GET(WINDOW_VALUE_MASK, HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab)); ++ struct platform_device *pdev = ab->pdev; ++ ++ ath11k_pcic_free_irq(ab); ++ platform_msi_domain_free_irqs(&pdev->dev); ++} ++EXPORT_SYMBOL(ath11k_pcic_ipci_free_irq); ++ + static void ath11k_pcic_ce_irq_enable(struct ath11k_base *ab, u16 ce_id) + { + u32 irq_idx; +@@ -650,7 +672,8 @@ EXPORT_SYMBOL(ath11k_pcic_stop); + + int ath11k_pcic_start(struct ath11k_base *ab) + { +- set_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags); ++ if (!ab->hw_params.internal_pci) ++ set_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags); + + ath11k_pcic_ce_irqs_enable(ab); + ath11k_ce_rx_post_buf(ab); +@@ -710,7 +733,7 @@ int ath11k_pcic_register_pci_ops(struct + return 0; + + /* Return error if mandatory pci_ops callbacks are missing */ +- if (!pci_ops->get_msi_irq || !pci_ops->window_write32 || ++ if (!pci_ops->window_write32 || + !pci_ops->window_read32) + return -EINVAL; + +@@ -718,3 +741,258 @@ int ath11k_pcic_register_pci_ops(struct + return 0; + } + EXPORT_SYMBOL(ath11k_pcic_register_pci_ops); ++ ++void ath11k_pcic_select_static_window(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 << 12) | (ce_window << 6); + -+ iowrite32(WINDOW_ENABLE_BIT | window, ab->mem + WINDOW_REG_ADDRESS); ++ iowrite32(ATH11K_PCI_WINDOW_ENABLE_BIT | window, ++ ab->mem + ATH11K_PCI_WINDOW_REG_ADDRESS); +} + -+u32 ath11k_pci_get_window_start(struct ath11k_base *ab, u32 offset) ++void ath11k_pcic_config_static_window(struct ath11k_base *ab) +{ -+ u32 window_start; -+ -+ /* If offset lies within DP register range, use 3rd window */ -+ if ((offset ^ HAL_SEQ_WCSS_UMAC_OFFSET) < WINDOW_RANGE_MASK) -+ window_start = 3 * WINDOW_START; -+ /* If offset lies within CE register range, use 2nd window */ -+ else if ((offset ^ HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab)) < WINDOW_RANGE_MASK) -+ window_start = 2 * WINDOW_START; -+ else -+ window_start = WINDOW_START; -+ -+ return window_start; ++ if (ab->hw_params.static_window_map) ++ ath11k_pcic_select_static_window(ab); +} ++EXPORT_SYMBOL(ath11k_pcic_config_static_window); + -+u32 ath11k_pci_get_window_offset(struct ath11k_base *ab, u32 offset) ++int ath11k_pcic_ext_config_gic_msi_irq(struct ath11k_base *ab, struct platform_device *pdev, ++ struct msi_desc *msi_desc, int i) +{ -+ u32 window_start; ++ u32 user_base_data = 0, base_vector = 0, base_idx; ++ struct ath11k_ext_irq_grp *irq_grp; ++ int j, ret = 0, num_vectors = 0; ++ u32 num_irq = 0; + -+ if (ab->bus_params.static_window_map) { -+ window_start = ath11k_pci_get_window_start(ab, offset); ++ base_idx = ATH11K_PCI_IRQ_CE0_OFFSET + CE_COUNT_MAX; ++ ret = ath11k_pcic_get_user_msi_assignment(ab, "DP", &num_vectors, ++ &user_base_data, &base_vector); ++ if (ret < 0) ++ return ret; + -+ if (window_start) -+ offset = window_start + (offset & WINDOW_RANGE_MASK); -+ } -+ return offset; -+} ++ irq_grp = &ab->ext_irq_grp[i]; ++ irq_grp->ab = ab; ++ irq_grp->grp_id = i; ++ init_dummy_netdev(&irq_grp->napi_ndev); ++ netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi, ++ ath11k_pcic_ext_grp_napi_poll, NAPI_POLL_WEIGHT); + -+void ath11k_ipci_write32(struct ath11k_base *ab, u32 offset, u32 value) -+{ -+ u32 window_start; -+ -+ if (offset < WINDOW_START) { -+ iowrite32(value, ab->mem + offset); -+ } else { -+ window_start = ath11k_pci_get_window_start(ab, offset); -+ iowrite32(value, ab->mem + window_start + -+ (offset & WINDOW_RANGE_MASK)); -+ } -+} -+ -+u32 ath11k_ipci_read32(struct ath11k_base *ab, u32 offset) -+{ -+ u32 val, window_start; -+ -+ if (offset < WINDOW_START) { -+ val = ioread32(ab->mem + offset); -+ } else { -+ window_start = ath11k_pci_get_window_start(ab, offset); -+ val = ioread32(ab->mem + window_start + -+ (offset & WINDOW_RANGE_MASK)); ++ if (ab->hw_params.ring_mask->tx[i] || ++ ab->hw_params.ring_mask->rx[i] || ++ ab->hw_params.ring_mask->rx_err[i] || ++ ab->hw_params.ring_mask->rx_wbm_rel[i] || ++ ab->hw_params.ring_mask->reo_status[i] || ++ ab->hw_params.ring_mask->rxdma2host[i] || ++ ab->hw_params.ring_mask->host2rxdma[i] || ++ ab->hw_params.ring_mask->rx_mon_status[i]) { ++ num_irq = 1; + } + -+ return val; -+} ++ irq_grp->num_irq = num_irq; ++ irq_grp->irqs[0] = base_idx + i; + -+static void ath11k_pci_ce_irq_enable(struct ath11k_base *ab, u16 ce_id) -+{ -+ struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); -+ u32 irq_idx; ++ for (j = 0; j < irq_grp->num_irq; j++) { ++ int irq_idx = irq_grp->irqs[j]; ++ int vector = (i % num_vectors); + -+ /* In case of one MSI vector, we handle irq enable/disable in a -+ * uniform way since we only have one irq -+ */ -+ if (!test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags)) -+ return; -+ -+ irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id; -+ enable_irq(ab->irq_num[irq_idx]); -+} -+ -+void ath11k_pci_ce_irqs_enable(struct ath11k_base *ab) -+{ -+ int i; -+ -+ set_bit(ATH11K_FLAG_CE_IRQ_ENABLED, &ab->dev_flags); -+ -+ for (i = 0; i < ab->hw_params.ce_count; i++) { -+ if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) -+ continue; -+ ath11k_pci_ce_irq_enable(ab, i); -+ } -+} -+ -+int ath11k_ipci_start(struct ath11k_base *ab) -+{ -+ ath11k_pci_ce_irqs_enable(ab); -+ ath11k_ce_rx_post_buf(ab); -+ -+ return 0; -+} -+ -+void ath11k_pci_aspm_restore(struct ath11k_pci *ab_pci) -+{ -+ if (test_and_clear_bit(ATH11K_PCI_ASPM_RESTORE, &ab_pci->flags)) -+ pcie_capability_write_word(ab_pci->pdev, PCI_EXP_LNKCTL, -+ ab_pci->link_ctl); -+} -+ -+int ath11k_pci_start(struct ath11k_base *ab) -+{ -+ struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); -+ -+ set_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags); -+ -+ /* TODO: for now don't restore ASPM in case of single MSI -+ * vector as MHI register reading in M2 causes system hang. -+ */ -+ if (test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags)) -+ ath11k_pci_aspm_restore(ab_pci); -+ else -+ ath11k_info(ab, "leaving PCI ASPM disabled to avoid MHI M2 problems\n"); -+ -+ ath11k_pci_ce_irqs_enable(ab); -+ ath11k_ce_rx_post_buf(ab); -+ -+ return 0; -+} -+ -+void ath11k_pci_config_static_window(struct ath11k_base *ab) -+{ -+ if (ab->bus_params.static_window_map) -+ ath11k_pci_select_static_window(ab); -+} -+ -+void ath11k_internal_pci_free_irq(struct ath11k_base *ab) -+{ -+ ath11k_pci_free_irq(ab); -+} -+ -+static void ath11k_pci_free_ext_irq(struct ath11k_base *ab) -+{ -+ int i, j; -+ -+ for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { -+ struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; -+ -+ for (j = 0; j < irq_grp->num_irq; j++) -+ free_irq(ab->irq_num[irq_grp->irqs[j]], irq_grp); -+ -+ netif_napi_del(&irq_grp->napi); -+ } -+} -+ -+void ath11k_pci_free_irq(struct ath11k_base *ab) -+{ -+ int i, irq_idx; -+ -+ for (i = 0; i < ab->hw_params.ce_count; i++) { -+ if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) -+ continue; -+ irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i; -+ free_irq(ab->irq_num[irq_idx], &ab->ce.ce_pipe[i]); -+ } -+ -+ ath11k_pci_free_ext_irq(ab); -+} -+ -+int ath11k_pci_get_user_msi_assignment(struct ath11k_base *ab, -+ struct ath11k_msi_config *msi_config, -+ u32 msi_ep_base_data, char *user_name, -+ int *num_vectors, u32 *user_base_data, -+ u32 *base_vector) -+{ -+ int idx; -+ -+ for (idx = 0; idx < msi_config->total_users; idx++) { -+ if (strcmp(user_name, msi_config->users[idx].name) == 0) { -+ *num_vectors = msi_config->users[idx].num_vectors; -+ *user_base_data = msi_config->users[idx].base_vector -+ + msi_ep_base_data; -+ *base_vector = msi_config->users[idx].base_vector; -+ -+ ath11k_dbg(ab, ATH11K_DBG_PCI, "Assign MSI to user: %s, num_vectors: %d, user_base_data: %u, base_vector: %u\n", -+ user_name, *num_vectors, *user_base_data, -+ *base_vector); -+ -+ return 0; ++ irq_set_status_flags(msi_desc->irq, IRQ_DISABLE_UNLAZY); ++ ret = devm_request_irq(&pdev->dev, msi_desc->irq, ++ ath11k_pcic_ext_interrupt_handler, ++ IRQF_SHARED, dp_irq_name[ab->userpd_id][i], ++ irq_grp); ++ if (ret) { ++ ath11k_err(ab, "failed request irq %d: %d\n", ++ irq_idx, ret); ++ return ret; + } ++ ab->irq_num[irq_idx] = msi_desc->irq; ++ ab->ipci.dp_irq_num[vector] = msi_desc->irq; ++ ab->ipci.dp_msi_data[i] = msi_desc->msg.data; ++ disable_irq_nosync(ab->irq_num[irq_idx]); + } -+ -+ ath11k_err(ab, "Failed to find MSI assignment for %s!\n", user_name); -+ -+ return -EINVAL; ++ return ret; +} + -+int ath11k_pci_get_domain_id(struct ath11k_base *ab) ++int ath11k_pcic_config_gic_msi_irq(struct ath11k_base *ab, struct platform_device *pdev, ++ struct msi_desc *msi_desc, int i) +{ -+ u8 domain_id; -+ struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); ++ struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i]; ++ int irq_idx, ret; + -+ if (ab->userpd_id) -+ domain_id = ab->userpd_id; -+ else -+ domain_id = pci_domain_nr(ab_pci->pdev->bus); ++ tasklet_setup(&ce_pipe->intr_tq, ath11k_pcic_ce_tasklet); ++ irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i; + -+ if (domain_id > ATH11K_MAX_PCI_DOMAINS) -+ domain_id = ATH11K_MAX_PCI_DOMAINS; -+ -+ return domain_id; -+} -+ -+void ath11k_pci_ce_irq_disable(struct ath11k_base *ab, u16 ce_id) -+{ -+ struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); -+ u32 irq_idx; -+ -+ /* In case of one MSI vector, we handle irq enable/disable in a -+ * uniform way since we only have one irq -+ */ -+ if (!test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags)) -+ return; -+ -+ irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id; -+ disable_irq_nosync(ab->irq_num[irq_idx]); -+} -+ -+static void ath11k_pci_ce_irqs_disable(struct ath11k_base *ab) -+{ -+ int i; -+ -+ clear_bit(ATH11K_FLAG_CE_IRQ_ENABLED, &ab->dev_flags); -+ -+ for (i = 0; i < ab->hw_params.ce_count; i++) { -+ if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) -+ continue; -+ ath11k_pci_ce_irq_disable(ab, i); ++ ret = devm_request_irq(&pdev->dev, msi_desc->irq, ++ ath11k_pcic_ce_interrupt_handler, ++ IRQF_SHARED, ce_irq_name[ab->userpd_id][i], ++ ce_pipe); ++ if (ret) { ++ ath11k_warn(ab, "failed to request irq %d: %d\n", ++ irq_idx, ret); ++ return ret; + } ++ ab->irq_num[irq_idx] = msi_desc->irq; ++ ab->ipci.ce_msi_data[i] = msi_desc->msg.data; ++ ath11k_pcic_ce_irq_disable(ab, i); ++ ++ return ret; +} + -+static void ath11k_pci_sync_ce_irqs(struct ath11k_base *ab) ++static void ath11k_msi_msg_handler(struct msi_desc *desc, struct msi_msg *msg) +{ -+ int i; -+ int irq_idx; -+ -+ for (i = 0; i < ab->hw_params.ce_count; i++) { -+ if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) -+ continue; -+ -+ irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i; -+ synchronize_irq(ab->irq_num[irq_idx]); -+ } ++ desc->msg.address_lo = msg->address_lo; ++ desc->msg.address_hi = msg->address_hi; ++ desc->msg.data = msg->data; +} + -+void ath11k_pci_ce_tasklet(struct tasklet_struct *t) -+{ -+ struct ath11k_ce_pipe *ce_pipe = from_tasklet(ce_pipe, t, intr_tq); -+ int irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_pipe->pipe_num; -+ -+ ath11k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num); -+ -+ enable_irq(ce_pipe->ab->irq_num[irq_idx]); -+} -+ -+irqreturn_t ath11k_pci_ce_interrupt_handler(int irq, void *arg) -+{ -+ struct ath11k_ce_pipe *ce_pipe = arg; -+ struct ath11k_base *ab = ce_pipe->ab; -+ int irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_pipe->pipe_num; -+ -+ if (!test_bit(ATH11K_FLAG_CE_IRQ_ENABLED, &ab->dev_flags)) -+ return IRQ_HANDLED; -+ -+ /* last interrupt received for this CE */ -+ ce_pipe->timestamp = jiffies; -+ -+ disable_irq_nosync(ab->irq_num[irq_idx]); -+ -+ tasklet_schedule(&ce_pipe->intr_tq); -+ -+ return IRQ_HANDLED; -+} -+ -+static void ath11k_pci_kill_tasklets(struct ath11k_base *ab) -+{ -+ int i; -+ -+ for (i = 0; i < ab->hw_params.ce_count; i++) { -+ struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i]; -+ -+ if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) -+ continue; -+ -+ tasklet_kill(&ce_pipe->intr_tq); -+ } -+} -+ -+void ath11k_pci_ce_irq_disable_sync(struct ath11k_base *ab) -+{ -+ ath11k_pci_ce_irqs_disable(ab); -+ ath11k_pci_sync_ce_irqs(ab); -+ ath11k_pci_kill_tasklets(ab); -+} -+ -+ -+void ath11k_pci_stop(struct ath11k_base *ab) -+{ -+ ath11k_pci_ce_irq_disable_sync(ab); -+ ath11k_ce_cleanup_pipes(ab); -+} -+ -+static void ath11k_pci_ext_grp_enable(struct ath11k_ext_irq_grp *irq_grp) -+{ -+ int i; -+ -+ for (i = 0; i < irq_grp->num_irq; i++) -+ enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]); -+} -+ -+int ath11k_pci_ext_grp_napi_poll(struct napi_struct *napi, int budget) -+{ -+ struct ath11k_ext_irq_grp *irq_grp = container_of(napi, -+ struct ath11k_ext_irq_grp, -+ napi); -+ struct ath11k_base *ab = irq_grp->ab; -+ int work_done; -+ int i; -+ -+ work_done = ath11k_dp_service_srng(ab, irq_grp, budget); -+ if (work_done < budget) { -+ napi_complete_done(napi, work_done); -+ for (i = 0; i < irq_grp->num_irq; i++) -+ enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]); -+ } -+ -+ if (work_done > budget) -+ work_done = budget; -+ -+ return work_done; -+} -+ -+void ath11k_pci_ext_grp_disable(struct ath11k_ext_irq_grp *irq_grp) -+{ -+ struct ath11k_pci *ab_pci = ath11k_pci_priv(irq_grp->ab); -+ int i; -+ -+ /* In case of one MSI vector, we handle irq enable/disable -+ * in a uniform way since we only have one irq -+ */ -+ if (!test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags)) -+ return; -+ -+ for (i = 0; i < irq_grp->num_irq; i++) -+ disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]); -+} -+ -+irqreturn_t ath11k_pci_ext_interrupt_handler(int irq, void *arg) -+{ -+ struct ath11k_ext_irq_grp *irq_grp = arg; -+ struct ath11k_base *ab = irq_grp->ab; -+ int i; -+ -+ if (!test_bit(ATH11K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags)) -+ return IRQ_HANDLED; -+ -+ ath11k_dbg(irq_grp->ab, ATH11K_DBG_PCI, "ext irq:%d\n", irq); -+ -+ /* last interrupt received for this group */ -+ irq_grp->timestamp = jiffies; -+ -+ for (i = 0; i < irq_grp->num_irq; i++) -+ disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]); -+ -+ napi_schedule(&irq_grp->napi); -+ -+ return IRQ_HANDLED; -+} -+ -+static void __ath11k_pci_ext_irq_disable(struct ath11k_base *sc) -+{ -+ int i; -+ -+ clear_bit(ATH11K_FLAG_EXT_IRQ_ENABLED, &sc->dev_flags); -+ -+ for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { -+ struct ath11k_ext_irq_grp *irq_grp = &sc->ext_irq_grp[i]; -+ -+ ath11k_pci_ext_grp_disable(irq_grp); -+ -+ napi_synchronize(&irq_grp->napi); -+ napi_disable(&irq_grp->napi); -+ } -+} -+ -+void ath11k_pci_ext_irq_enable(struct ath11k_base *ab) -+{ -+ int i; -+ -+ set_bit(ATH11K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags); -+ -+ for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { -+ struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; -+ -+ napi_enable(&irq_grp->napi); -+ ath11k_pci_ext_grp_enable(irq_grp); -+ } -+} -+ -+static void ath11k_pci_sync_ext_irqs(struct ath11k_base *ab) -+{ -+ int i, j, irq_idx; -+ -+ for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { -+ struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; -+ -+ for (j = 0; j < irq_grp->num_irq; j++) { -+ irq_idx = irq_grp->irqs[j]; -+ synchronize_irq(ab->irq_num[irq_idx]); -+ } -+ } -+} -+ -+void ath11k_pci_ext_irq_disable(struct ath11k_base *ab) -+{ -+ __ath11k_pci_ext_irq_disable(ab); -+ ath11k_pci_sync_ext_irqs(ab); -+} -+ -+void ath11k_pci_get_qgic_msi_address(struct ath11k_base *ab, u32 *msi_addr_lo, -+ u32 *msi_addr_hi) -+{ -+ *msi_addr_lo = 0; -+ *msi_addr_hi = 0; -+} -+ -+int ath11k_ipci_get_user_msi_assignment(struct ath11k_base *ab, char *user_name, -+ int *num_vectors, u32 *user_base_data, -+ u32 *base_vector) -+{ -+ return 0; -+} -+ -+int ath11k_pci_map_service_to_pipe(struct ath11k_base *ab, u16 service_id, -+ u8 *ul_pipe, u8 *dl_pipe) -+{ -+ const struct service_to_pipe *entry; -+ bool ul_set = false, dl_set = false; -+ int i; -+ -+ for (i = 0; i < ab->hw_params.svc_to_ce_map_len; i++) { -+ entry = &ab->hw_params.svc_to_ce_map[i]; -+ -+ if (__le32_to_cpu(entry->service_id) != service_id) -+ continue; -+ -+ switch (__le32_to_cpu(entry->pipedir)) { -+ case PIPEDIR_NONE: -+ break; -+ case PIPEDIR_IN: -+ WARN_ON(dl_set); -+ *dl_pipe = __le32_to_cpu(entry->pipenum); -+ dl_set = true; -+ break; -+ case PIPEDIR_OUT: -+ WARN_ON(ul_set); -+ *ul_pipe = __le32_to_cpu(entry->pipenum); -+ ul_set = true; -+ break; -+ case PIPEDIR_INOUT: -+ WARN_ON(dl_set); -+ WARN_ON(ul_set); -+ *dl_pipe = __le32_to_cpu(entry->pipenum); -+ *ul_pipe = __le32_to_cpu(entry->pipenum); -+ dl_set = true; -+ ul_set = true; -+ break; -+ } -+ } -+ -+ if (WARN_ON(!ul_set || !dl_set)) -+ return -ENOENT; -+ -+ return 0; -+} -+ -+void ath11k_pci_get_ce_msi_idx(struct ath11k_base *ab, u32 ce_id, -+ u32 *msi_idx) -+{ -+ u32 i, msi_data_idx; -+ -+ for (i = 0, msi_data_idx = 0; i < ab->hw_params.ce_count; i++) { -+ if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) -+ continue; -+ -+ if (ce_id == i) -+ break; -+ -+ msi_data_idx++; -+ } -+ *msi_idx = msi_data_idx; -+} -+ -+int ath11k_config_irq_internal_pci(struct ath11k_base *ab) ++int ath11k_pcic_ipci_config_irq(struct ath11k_base *ab) +{ + int ret; ++ struct platform_device *pdev = ab->pdev; ++ struct msi_desc *msi_desc; ++ bool ce_done = false; ++ int i = 0; + + if (ab->userpd_id != QCN6122_USERPD_0 && + ab->userpd_id != QCN6122_USERPD_1) { @@ -1901,280 +981,240 @@ Signed-off-by: Sowmiya Sree Elavalagan + return -ENODEV; + } + -+ ab->ipci.msi_cfg = &ath11k_msi_config[ATH11K_MSI_CONFIG_QCN6122]; ++ ret = ath11k_pcic_init_msi_config(ab); ++ if (ret) { ++ ath11k_err(ab, "failed to fetch msi config: %d\n", ret); ++ return ret; ++ } ++ ++ ret = platform_msi_domain_alloc_irqs(&pdev->dev, ab->pci.msi.config->total_vectors, ++ ath11k_msi_msg_handler); ++ if (ret) { ++ ath11k_warn(ab, "failed to alloc irqs %d ab %pM\n", ret, ab); ++ return ret; ++ } ++ ++ for_each_msi_entry(msi_desc, &pdev->dev) { ++ if (!ce_done && i == ab->hw_params.ce_count) { ++ i = 0; ++ ce_done = true; ++ } ++ ++ if (!ce_done && i < ab->hw_params.ce_count) { ++ if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) ++ i++; ++ ++ ret = ath11k_pcic_config_gic_msi_irq(ab, pdev, msi_desc, i); ++ if (ret) { ++ ath11k_warn(ab, "failed to request irq %d\n", ret); ++ return ret; ++ } ++ } else { ++ ret = ath11k_pcic_ext_config_gic_msi_irq(ab, pdev, msi_desc, i); ++ if (ret) { ++ ath11k_warn(ab, "failed to config ext msi irq %d\n", ret); ++ return ret; ++ } ++ } ++ ++ i++; ++ ab->pci.msi.addr_lo = msi_desc->msg.address_lo; ++ ab->pci.msi.addr_hi = msi_desc->msg.address_hi; ++ ++ if (i == 0 && !ce_done) ++ ab->pci.msi.ep_base_data = msi_desc->msg.data; ++ } ++ ++ for_each_msi_entry(msi_desc, &pdev->dev) { ++ u32 user_base_data = 0, base_vector = 0; ++ int vector, num_vectors = 0; ++ ++ ret = ath11k_pcic_get_user_msi_assignment(ab, "DP", &num_vectors, ++ &user_base_data, &base_vector); ++ if (ret < 0) ++ return ret; ++ ++ vector = (i % num_vectors); ++ ++ if (i >= ATH11K_EXT_IRQ_GRP_NUM_MAX) ++ break; ++ ++ if (ab->ipci.dp_irq_num[vector] != msi_desc->irq) ++ continue; ++ ++ ret = ath11k_pcic_ext_config_gic_msi_irq(ab, pdev, msi_desc, i); ++ if (ret) { ++ ath11k_warn(ab, "failed to config ext msi irq %d\n", ret); ++ return ret; ++ } ++ ++ i++; ++ } + + ab->ipci.gic_enabled = 1; + wake_up(&ab->ipci.gic_msi_waitq); -+ + return ret; +} ++EXPORT_SYMBOL(ath11k_pcic_ipci_config_irq); + ---- /dev/null -+++ b/drivers/net/wireless/ath/ath11k/pci_cmn.h -@@ -0,0 +1,65 @@ -+// SPDX-License-Identifier: BSD-3-Clause-Clear -+/* -+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ ++u32 ath11k_pcic_get_window_start(struct ath11k_base *ab, u32 offset, ++ enum ath11k_bus bus) ++{ ++ u32 window_start = 0; + -+#ifndef _ATH11K_PCI_CMN_H -+#define _ATH11K_PCI_CMN_H ++ if (bus == ATH11K_BUS_PCI) { ++ if (!ab->hw_params.static_window_map) ++ return ATH11K_PCI_WINDOW_START; + -+#include "core.h" -+#include "pci.h" ++ /* if offset lies within DP register range, use 3rd window */ ++ if ((offset ^ HAL_SEQ_WCSS_UMAC_OFFSET) < ++ ATH11K_PCI_WINDOW_RANGE_MASK) ++ window_start = 3 * ATH11K_PCI_WINDOW_START; ++ /* if offset lies within CE register range, use 2nd window */ ++ else if ((offset ^ HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab)) < ++ ATH11K_PCI_WINDOW_RANGE_MASK) ++ window_start = 2 * ATH11K_PCI_WINDOW_START; ++ else ++ window_start = ATH11K_PCI_WINDOW_START; ++ } else if (bus == ATH11K_BUS_AHB) { ++ /* If offset lies within DP register range, use 1st window */ ++ if ((offset ^ HAL_SEQ_WCSS_UMAC_OFFSET) < ++ ATH11K_PCI_WINDOW_RANGE_MASK) ++ window_start = ++ ab->hw_params.dp_window * ATH11K_PCI_WINDOW_START; ++ /* If offset lies within CE register range, use 2nd window */ ++ else if ((offset ^ HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab)) < ++ ATH11K_PCI_WINDOW_RANGE_MASK) ++ window_start = ++ ab->hw_params.ce_window * ATH11K_PCI_WINDOW_START; ++ else ++ window_start = ATH11K_PCI_WINDOW_START; ++ } ++ else { ++ /* Must not come here */ ++ WARN_ON(1); ++ } + -+#define WINDOW_ENABLE_BIT 0x40000000 -+#define WINDOW_REG_ADDRESS 0x310c -+#define WINDOW_VALUE_MASK GENMASK(24, 19) -+#define WINDOW_START 0x80000 -+#define WINDOW_RANGE_MASK GENMASK(18, 0) ++ return window_start; ++} ++EXPORT_SYMBOL(ath11k_pcic_get_window_start); + -+#define ATH11K_PCI_IRQ_CE0_OFFSET 3 -+#define ATH11K_MAX_PCI_DOMAINS 2 ++u32 ath11k_pci_get_window_offset(struct ath11k_base *ab, u32 offset) ++{ ++ u32 window_start; + -+extern const struct ath11k_msi_config ath11k_msi_config[]; ++ if (ab->hw_params.static_window_map) { ++ window_start = ath11k_pcic_get_window_start(ab, offset, ++ ATH11K_BUS_PCI); + -+extern const char *dp_irq_name[ATH11K_MAX_PCI_DOMAINS + 1][ATH11K_EXT_IRQ_GRP_NUM_MAX]; -+extern const char *ce_irq_name[ATH11K_MAX_PCI_DOMAINS + 1][CE_COUNT_MAX]; -+int ath11k_pci_get_user_msi_assignment(struct ath11k_base *ab, -+ struct ath11k_msi_config *msi_config, -+ u32 msi_ep_base_data, char *user_name, -+ int *num_vectors, u32 *user_base_data, -+ u32 *base_vector); -+void ath11k_ipci_write32(struct ath11k_base *ab, u32 offset, u32 value); -+u32 ath11k_ipci_read32(struct ath11k_base *ab, u32 offset); -+void ath11k_pci_get_ce_msi_idx(struct ath11k_base *ab, u32 ce_id, u32 *msi_idx); -+void ath11k_pci_free_irq(struct ath11k_base *ab); -+void ath11k_pci_ext_irq_enable(struct ath11k_base *ab); -+void ath11k_pci_ext_irq_disable(struct ath11k_base *ab); -+void ath11k_pci_stop(struct ath11k_base *ab); -+int ath11k_pci_core_start(struct ath11k_base *ab); -+int ath11k_pci_map_service_to_pipe(struct ath11k_base *ab, u16 service_id, -+ u8 *ul_pipe, u8 *dl_pipe); -+int ath11k_ipci_get_user_msi_assignment(struct ath11k_base *ab, char *user_name, -+ int *num_vectors, u32 *user_base_data, -+ u32 *base_vector); -+void ath11k_pci_ce_irqs_enable(struct ath11k_base *ab); -+void ath11k_pci_ce_irq_disable_sync(struct ath11k_base *ab); -+int ath11k_pci_get_msi_config(struct ath11k_base *ab); -+void ath11k_pci_config_static_window(struct ath11k_base *ab); -+void ath11k_pci_select_static_window(struct ath11k_base *ab); -+void ath11k_internal_pci_free_irq(struct ath11k_base *ab); -+int ath11k_internal_pci_config_irq(struct ath11k_base *ab); -+int ath11k_ipci_start(struct ath11k_base *ab); -+int ath11k_pci_start(struct ath11k_base *ab); -+u32 ath11k_pci_get_window_start(struct ath11k_base *ab, u32 offset); -+int ath11k_pci_ext_grp_napi_poll(struct napi_struct *napi, int budget); -+void ath11k_pci_ce_tasklet(struct tasklet_struct *t); -+irqreturn_t ath11k_pci_ce_interrupt_handler(int irq, void *arg); -+void ath11k_pci_ce_irq_disable(struct ath11k_base *ab, u16 ce_id); -+irqreturn_t ath11k_pci_ext_interrupt_handler(int irq, void *arg); -+void ath11k_pci_aspm_restore(struct ath11k_pci *ab_pci); -+void ath11k_pci_get_qgic_msi_address(struct ath11k_base *ab, u32 *msi_addr_lo, -+ u32 *msi_addr_hi); ++ if (window_start) ++ offset = window_start + (offset & ATH11K_PCI_WINDOW_RANGE_MASK); ++ } ++ return offset; ++} ++EXPORT_SYMBOL(ath11k_pci_get_window_offset); +--- a/drivers/net/wireless/ath/ath11k/pcic.h ++++ b/drivers/net/wireless/ath/ath11k/pcic.h +@@ -75,4 +75,11 @@ void ath11k_pcic_ce_irq_disable_sync(str + int ath11k_pcic_init_msi_config(struct ath11k_base *ab); + int ath11k_pcic_register_pci_ops(struct ath11k_base *ab, + const struct ath11k_pci_ops *pci_ops); ++void ath11k_pcic_select_static_window(struct ath11k_base *ab); ++void ath11k_pcic_ipci_free_irq(struct ath11k_base *ab); ++int ath11k_pcic_ipci_config_irq(struct ath11k_base *ab); ++void ath11k_pcic_config_static_window(struct ath11k_base *ab); ++u32 ath11k_pcic_get_window_start(struct ath11k_base *ab, u32 offset, ++ enum ath11k_bus bus); +u32 ath11k_pci_get_window_offset(struct ath11k_base *ab, u32 offset); -+int ath11k_config_irq_internal_pci(struct ath11k_base *ab); -+void ath11k_pci_ext_grp_disable(struct ath11k_ext_irq_grp *irq_grp); -+int ath11k_pci_get_domain_id(struct ath11k_base *ab); -+#endif + #endif --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c -@@ -7,6 +7,7 @@ +@@ -7,7 +7,7 @@ + #include #include "qmi.h" - #include "core.h" +-#include "core.h" +#include "hif.h" #include "debug.h" #include "hif.h" #include -@@ -1062,6 +1063,68 @@ static struct qmi_elem_info qmi_wlanfw_c - }, - }; +@@ -2898,6 +2898,10 @@ static int ath11k_qmi_assign_target_mem_ + idx++; + break; + case BDF_MEM_REGION_TYPE: ++ if (!of_property_read_u32(ab->dev->of_node, "qcom,bdf-addr", ++ &addr)) ++ ab->hw_params.bdf_addr = (u32)addr; ++ + ab->qmi.target_mem[idx].paddr = ab->hw_params.bdf_addr; + ab->qmi.target_mem[idx].vaddr = NULL; + ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size; +@@ -2918,6 +2922,10 @@ static int ath11k_qmi_assign_target_mem_ + } else if (ath11k_host_ddr_addr) { + ab->qmi.target_mem[idx].paddr = ath11k_host_ddr_addr + + ATH11K_HOST_DDR_CALDB_OFFSET; ++ } else if (of_property_read_u32(ab->dev->of_node, ++ "qcom,caldb-addr", ++ &addr)) { ++ ab->qmi.target_mem[idx].paddr = (u32)addr; + } else { + ab->qmi.target_mem[idx].paddr = + ATH11K_QMI_CALDB_ADDRESS; +@@ -2981,7 +2989,7 @@ static int ath11k_qmi_request_device_inf + int ret; -+static struct qmi_elem_info qmi_wlanfw_device_info_req_msg_v01_ei[] = { -+ { -+ .data_type = QMI_EOTI, -+ .array_type = NO_ARRAY, -+ .tlv_type = QMI_COMMON_TLV_TYPE, -+ }, -+}; -+ -+struct qmi_elem_info qmi_wlanfw_device_info_resp_msg_v01_ei[] = { -+ { -+ .data_type = QMI_STRUCT, -+ .elem_len = 1, -+ .elem_size = sizeof(struct qmi_response_type_v01), -+ .array_type = NO_ARRAY, -+ .tlv_type = 0x02, -+ .offset = offsetof(struct qmi_wlanfw_device_info_resp_msg_v01, -+ resp), -+ .ei_array = qmi_response_type_v01_ei, -+ }, -+ { -+ .data_type = QMI_OPT_FLAG, -+ .elem_len = 1, -+ .elem_size = sizeof(u8), -+ .array_type = NO_ARRAY, -+ .tlv_type = 0x10, -+ .offset = offsetof(struct qmi_wlanfw_device_info_resp_msg_v01, -+ bar_addr_valid), -+ }, -+ { -+ .data_type = QMI_UNSIGNED_8_BYTE, -+ .elem_len = 1, -+ .elem_size = sizeof(u64), -+ .array_type = NO_ARRAY, -+ .tlv_type = 0x10, -+ .offset = offsetof(struct qmi_wlanfw_device_info_resp_msg_v01, -+ bar_addr), -+ }, -+ { -+ .data_type = QMI_OPT_FLAG, -+ .elem_len = 1, -+ .elem_size = sizeof(u8), -+ .array_type = NO_ARRAY, -+ .tlv_type = 0x11, -+ .offset = offsetof(struct qmi_wlanfw_device_info_resp_msg_v01, -+ bar_size_valid), -+ }, -+ { -+ .data_type = QMI_UNSIGNED_4_BYTE, -+ .elem_len = 1, -+ .elem_size = sizeof(u32), -+ .array_type = NO_ARRAY, -+ .tlv_type = 0x11, -+ .offset = offsetof(struct qmi_wlanfw_device_info_resp_msg_v01, -+ bar_size), -+ }, -+ { -+ .data_type = QMI_EOTI, -+ .array_type = NO_ARRAY, -+ .tlv_type = QMI_COMMON_TLV_TYPE, -+ }, -+}; -+ - static struct qmi_elem_info qmi_wlanfw_rf_chip_info_s_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_4_BYTE, -@@ -2895,6 +2958,85 @@ static int ath11k_qmi_assign_target_mem_ - return 0; - } + /* device info message req is only sent for hybrid bus devices */ +- if (!ab->hw_params.hybrid_bus_type) ++ if (!ab->hw_params.hybrid_bus_type && !ab->hw_params.internal_pci) + return 0; -+static int ath11k_qmi_request_device_info(struct ath11k_base *ab) -+{ -+ struct qmi_wlanfw_device_info_req_msg_v01 req; -+ struct qmi_wlanfw_device_info_resp_msg_v01 resp; -+ struct qmi_txn txn = {}; -+ void *bar_addr_va = NULL; -+ int ret = 0; -+ -+ /*device info message only supported for internal-PCI devices */ -+ if (ab->hw_rev != ATH11K_HW_QCN6122) -+ return 0; -+ -+ memset(&req, 0, sizeof(req)); -+ memset(&resp, 0, sizeof(resp)); -+ -+ ret = qmi_txn_init(&ab->qmi.handle, &txn, -+ qmi_wlanfw_device_info_resp_msg_v01_ei, &resp); -+ if (ret < 0) -+ goto out; -+ -+ ret = qmi_send_request(&ab->qmi.handle, NULL, &txn, -+ QMI_WLANFW_DEVICE_INFO_REQ_V01, -+ QMI_WLANFW_DEVICE_INFO_REQ_MSG_V01, -+ qmi_wlanfw_device_info_req_msg_v01_ei, &req); -+ if (ret < 0) { -+ ath11k_warn(ab, "qmi failed to send target device info request, err = %d\n", -+ ret); -+ goto out; -+ } -+ -+ ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH11K_QMI_WLANFW_TIMEOUT_MS)); -+ if (ret < 0) { -+ ath11k_warn(ab, "qmi failed target device info request %d\n", ret); -+ goto out; -+ } -+ -+ if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { -+ ath11k_warn(ab, "qmi device info req failed, result: %d, err: %d\n", -+ resp.resp.result, resp.resp.error); -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ if (!resp.bar_addr_valid || !resp.bar_size_valid) { -+ ath11k_warn(ab, "qmi device info response invalid, result: %d, err: %d\n", -+ resp.resp.result, resp.resp.error); -+ ret = -EINVAL; -+ goto out; -+ } -+ if (!resp.bar_addr || -+ resp.bar_size != QCN6122_DEVICE_BAR_SIZE) { -+ ath11k_warn(ab, "qmi device info invalid addr and size, result: %d, err: %d\n", -+ resp.resp.result, resp.resp.error); -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ bar_addr_va = ioremap_nocache(resp.bar_addr, resp.bar_size); -+ -+ if (!bar_addr_va) { -+ ath11k_warn(ab, "qmi device info ioremap failed\n"); -+ ab->mem_len = 0; -+ ret = -EIO; -+ goto out; -+ } -+ -+ ab->mem = bar_addr_va; + ret = qmi_txn_init(&ab->qmi.handle, &txn, +@@ -3039,8 +3047,15 @@ static int ath11k_qmi_request_device_inf + } + + ab->mem = bar_addr_va; + ab->mem_pa = resp.bar_addr; -+ ab->mem_len = resp.bar_size; + ab->mem_len = resp.bar_size; + ++ if (ab->hw_params.internal_pci) ++ ath11k_hif_config_static_window(ab); + -+ ath11k_dbg(ab, ATH11K_DBG_QMI, "Device BAR Info va: 0x%p, size: 0x%lx\n", -+ ab->mem, ab->mem_len); ++ ath11k_dbg(ab, ATH11K_DBG_QMI, "Device BAR Info pa: %pad, size: 0x%lx\n", ++ &ab->mem_pa, ab->mem_len); + -+ ath11k_hif_config_static_window(ab); -+ return 0; -+out: -+ return ret; -+} -+ - static int ath11k_qmi_request_target_cap(struct ath11k_base *ab) - { - struct device *dev = ab->dev; -@@ -3160,6 +3302,31 @@ static int ath11k_qmi_load_bdf_qmi(struc + return 0; + out: + return ret; +@@ -3318,10 +3333,27 @@ static int ath11k_qmi_load_bdf_qmi(struc + fw_size = ATH11K_QMI_MAX_BDF_FILE_NAME_SIZE; + } else { + file_type = ATH11K_QMI_FILE_TYPE_CALDATA; +- /* cal--.bin */ snprintf(filename, sizeof(filename), "cal-%s-%s.bin", ath11k_bus_str(ab->hif.bus), dev_name(dev)); + -+ if(ab->bus_params.fixed_bdf_addr) { -+ snprintf(filename, sizeof(filename), -+ "%s", ATH11K_DEFAULT_CAL_FILE); -+ if (ab->userpd_id) { ++ if (ab->hw_params.fixed_bdf_addr) { ++ snprintf(filename, sizeof(filename), "%s", ++ ATH11K_DEFAULT_CAL_FILE); ++ ++ if (ab->hw_params.internal_pci) { + snprintf(filename, sizeof(filename), "%s%d%s", -+ ATH11K_QMI_DEF_CAL_FILE_PREFIX, -+ ab->userpd_id, -+ ATH11K_QMI_DEF_CAL_FILE_SUFFIX); ++ ATH11K_QMI_DEF_CAL_FILE_PREFIX, ++ ab->userpd_id, ++ ATH11K_QMI_DEF_CAL_FILE_SUFFIX); + } + } else { -+ snprintf(filename, sizeof(filename), -+ "%s%d%s", -+ ATH11K_QMI_DEF_CAL_FILE_PREFIX, -+ ab->qmi.service_ins_id - (NODE_ID_BASE - 1), -+ ATH11K_QMI_DEF_CAL_FILE_SUFFIX); -+ } -+ -+ if (ab->bus_params.fixed_bdf_addr && ab->userpd_id) { + snprintf(filename, sizeof(filename), "%s%d%s", + ATH11K_QMI_DEF_CAL_FILE_PREFIX, -+ ab->userpd_id, ++ ab->qmi.service_ins_id - (NODE_ID_BASE - 1), + ATH11K_QMI_DEF_CAL_FILE_SUFFIX); + } + fw_entry = ath11k_core_firmware_request(ab, filename); if (!IS_ERR(fw_entry)) goto success; -@@ -3853,6 +4020,26 @@ int ath11k_qmi_pci_alloc_qdss_mem(struct +@@ -3996,6 +4028,25 @@ int ath11k_qmi_pci_alloc_qdss_mem(struct return 0; } @@ -2196,21 +1236,20 @@ Signed-off-by: Sowmiya Sree Elavalagan + + return dev_node; +} -+ + int ath11k_qmi_qdss_mem_alloc(struct ath11k_qmi *qmi) { int ret, i; -@@ -3861,7 +4048,7 @@ int ath11k_qmi_qdss_mem_alloc(struct ath +@@ -4004,7 +4055,7 @@ int ath11k_qmi_qdss_mem_alloc(struct ath struct resource q6_etr; - if (ab->bus_params.fixed_bdf_addr) { + if (ab->hw_params.fixed_bdf_addr) { - dev_node = of_find_node_by_name(NULL, "q6_etr_dump"); + dev_node = ath11k_get_etr_dev_node(ab); if (!dev_node) { ath11k_err(ab, "No q6_etr_dump available in dts\n"); return -ENOMEM; -@@ -3876,6 +4063,19 @@ int ath11k_qmi_qdss_mem_alloc(struct ath +@@ -4019,6 +4070,19 @@ int ath11k_qmi_qdss_mem_alloc(struct ath ab->qmi.qdss_mem[i].paddr = q6_etr.start; ab->qmi.qdss_mem[i].size = resource_size(&q6_etr); ab->qmi.qdss_mem[i].type = QDSS_ETR_MEM_REGION_TYPE; @@ -2230,20 +1269,7 @@ Signed-off-by: Sowmiya Sree Elavalagan } } else { ret = ath11k_qmi_pci_alloc_qdss_mem(qmi); -@@ -3990,6 +4190,12 @@ static int ath11k_qmi_event_load_bdf(str - if (ab->hw_params.supports_regdb) - ath11k_qmi_load_bdf_qmi(ab, true); - -+ ret = ath11k_qmi_request_device_info(ab); -+ if (ret < 0) { -+ ath11k_warn(ab, "qmi failed to req device info %d\n", ret); -+ return ret; -+ } -+ - ret = ath11k_qmi_load_bdf_qmi(ab, false); - if (ret < 0) { - ath11k_warn(ab, "failed to load board data file: %d\n", ret); -@@ -4411,6 +4617,23 @@ static const struct qmi_ops ath11k_qmi_o +@@ -4584,6 +4648,23 @@ static const struct qmi_ops ath11k_qmi_o .del_server = ath11k_qmi_ops_del_server, }; @@ -2267,7 +1293,7 @@ Signed-off-by: Sowmiya Sree Elavalagan static void ath11k_qmi_driver_event_work(struct work_struct *work) { struct ath11k_qmi *qmi = container_of(work, struct ath11k_qmi, -@@ -4466,6 +4689,14 @@ static void ath11k_qmi_driver_event_work +@@ -4649,6 +4730,14 @@ static void ath11k_qmi_driver_event_work clear_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags); clear_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags); @@ -2275,14 +1301,14 @@ Signed-off-by: Sowmiya Sree Elavalagan + if (ret) { + ath11k_warn(ab, + "Failed to get qgic handler for dev %d ret: %d\n", -+ ab->hw_rev, ret); ++ ab->hw_rev, ret); + break; + } + - ath11k_core_qmi_firmware_ready(ab); - set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags); - } -@@ -4588,6 +4819,7 @@ int ath11k_qmi_init_service(struct ath11 + ret = ath11k_core_qmi_firmware_ready(ab); + if (ret) { + set_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags); +@@ -4775,6 +4864,7 @@ int ath11k_qmi_init_service(struct ath11 return ret; } @@ -2292,56 +1318,23 @@ Signed-off-by: Sowmiya Sree Elavalagan --- a/drivers/net/wireless/ath/ath11k/qmi.h +++ b/drivers/net/wireless/ath/ath11k/qmi.h -@@ -22,6 +22,7 @@ - #define ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCA6390 0x01 +@@ -24,6 +24,7 @@ #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 -@@ -63,6 +64,13 @@ - #define QMI_WLANFW_MAX_DATA_SIZE_V01 6144 - #define ATH11K_FIRMWARE_MODE_OFF 4 +@@ -67,6 +68,8 @@ #define ATH11K_COLD_BOOT_FW_RESET_DELAY (60 * HZ) -+#define ATH11K_QMI_DEF_CAL_FILE_PREFIX "caldata_" -+#define ATH11K_QMI_DEF_CAL_FILE_SUFFIX ".bin" -+#define ATH11K_RCV_GIC_MSI_HDLR_DELAY (3 * HZ) -+ -+#define QCN6122_DEVICE_BAR_SIZE 0x200000 -+#define ATH11K_RCV_GIC_MSI_HDLR_DELAY (3 * HZ) + + #define ATH11K_QMI_DEVICE_BAR_SIZE 0x200000 ++#define ATH11K_RCV_GIC_MSI_HDLR_DELAY (3 * HZ) +#define ATH11K_QMI_QCN6122_M3_DUMP_ADDRESS 0x4E200000 struct ath11k_base; extern unsigned int ath11k_host_ddr_addr; -@@ -460,6 +468,8 @@ struct ath11k_qmi_event_qdss_trace_save_ - #define QMI_WLANFW_CAP_RESP_MSG_V01_MAX_LEN 235 - #define QMI_WLANFW_CAP_REQ_V01 0x0024 - #define QMI_WLANFW_CAP_RESP_V01 0x0024 -+#define QMI_WLANFW_DEVICE_INFO_REQ_V01 0x004C -+#define QMI_WLANFW_DEVICE_INFO_REQ_MSG_V01 0 - - enum qmi_wlanfw_pipedir_enum_v01 { - QMI_WLFW_PIPEDIR_NONE_V01 = 0, -@@ -552,6 +562,18 @@ struct qmi_wlanfw_cap_req_msg_v01 { - char placeholder; - }; - -+struct qmi_wlanfw_device_info_req_msg_v01 { -+ char placeholder; -+}; -+ -+struct qmi_wlanfw_device_info_resp_msg_v01 { -+ struct qmi_response_type_v01 resp; -+ u8 bar_addr_valid; -+ u64 bar_addr; -+ u8 bar_size_valid; -+ u32 bar_size; -+}; -+ - #define QMI_WLANFW_BDF_DOWNLOAD_REQ_MSG_V01_MAX_LEN 6182 - #define QMI_WLANFW_BDF_DOWNLOAD_RESP_MSG_V01_MAX_LEN 7 - #define QMI_WLANFW_BDF_DOWNLOAD_RESP_V01 0x0025 --- a/drivers/net/wireless/ath/ath11k/nss.c +++ b/drivers/net/wireless/ath/ath11k/nss.c @@ -2164,6 +2164,8 @@ static int ath11k_nss_get_target_type(st diff --git a/feeds/ipq95xx/mac80211/patches/qca/233-001-ath11k-add-support-memory-stats.patch b/feeds/ipq95xx/mac80211/patches/qca/233-001-ath11k-add-support-memory-stats.patch index b3c5cc6df..208403aa9 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/233-001-ath11k-add-support-memory-stats.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/233-001-ath11k-add-support-memory-stats.patch @@ -60,7 +60,7 @@ Signed-off-by: Maharaja Kennadyrajan --- a/drivers/net/wireless/ath/ath11k/ce.c +++ b/drivers/net/wireless/ath/ath11k/ce.c -@@ -358,6 +358,9 @@ static int ath11k_ce_rx_post_pipe(struct +@@ -359,6 +359,9 @@ static int ath11k_ce_rx_post_pipe(struct dev_kfree_skb_any(skb); goto exit; } @@ -70,7 +70,7 @@ Signed-off-by: Maharaja Kennadyrajan } exit: -@@ -426,6 +429,9 @@ static void ath11k_ce_recv_process_cb(st +@@ -427,6 +430,9 @@ static void ath11k_ce_recv_process_cb(st __skb_queue_head_init(&list); while (ath11k_ce_completed_recv_next(pipe, &skb, &nbytes) == 0) { max_nbytes = skb->len + skb_tailroom(skb); @@ -80,7 +80,7 @@ Signed-off-by: Maharaja Kennadyrajan dma_unmap_single(ab->dev, ATH11K_SKB_RXCB(skb)->paddr, max_nbytes, DMA_FROM_DEVICE); -@@ -619,6 +625,9 @@ ath11k_ce_alloc_ring(struct ath11k_base +@@ -620,6 +626,9 @@ ath11k_ce_alloc_ring(struct ath11k_base if (ce_ring == NULL) return ERR_PTR(-ENOMEM); @@ -90,7 +90,7 @@ Signed-off-by: Maharaja Kennadyrajan ce_ring->nentries = nentries; ce_ring->nentries_mask = nentries - 1; -@@ -634,6 +643,9 @@ ath11k_ce_alloc_ring(struct ath11k_base +@@ -635,6 +644,9 @@ ath11k_ce_alloc_ring(struct ath11k_base return ERR_PTR(-ENOMEM); } @@ -100,7 +100,7 @@ Signed-off-by: Maharaja Kennadyrajan ce_ring->base_addr_ce_space_unaligned = base_addr; ce_ring->base_addr_owner_space = PTR_ALIGN( -@@ -813,6 +825,9 @@ static void ath11k_ce_rx_pipe_cleanup(st +@@ -814,6 +826,9 @@ static void ath11k_ce_rx_pipe_cleanup(st continue; ring->skb[i] = NULL; @@ -110,7 +110,7 @@ Signed-off-by: Maharaja Kennadyrajan dma_unmap_single(ab->dev, ATH11K_SKB_RXCB(skb)->paddr, skb->len + skb_tailroom(skb), DMA_FROM_DEVICE); dev_kfree_skb_any(skb); -@@ -994,6 +1009,9 @@ void ath11k_ce_free_pipes(struct ath11k_ +@@ -992,6 +1007,9 @@ void ath11k_ce_free_pipes(struct ath11k_ CE_DESC_RING_ALIGN, ce_ring->base_addr_owner_space_unaligned, ce_ring->base_addr_ce_space_unaligned); @@ -120,7 +120,7 @@ Signed-off-by: Maharaja Kennadyrajan kfree(pipe->src_ring); pipe->src_ring = NULL; } -@@ -1006,6 +1024,9 @@ void ath11k_ce_free_pipes(struct ath11k_ +@@ -1004,6 +1022,9 @@ void ath11k_ce_free_pipes(struct ath11k_ CE_DESC_RING_ALIGN, ce_ring->base_addr_owner_space_unaligned, ce_ring->base_addr_ce_space_unaligned); @@ -130,7 +130,7 @@ Signed-off-by: Maharaja Kennadyrajan kfree(pipe->dest_ring); pipe->dest_ring = NULL; } -@@ -1019,6 +1040,9 @@ void ath11k_ce_free_pipes(struct ath11k_ +@@ -1017,6 +1038,9 @@ void ath11k_ce_free_pipes(struct ath11k_ CE_DESC_RING_ALIGN, ce_ring->base_addr_owner_space_unaligned, ce_ring->base_addr_ce_space_unaligned); @@ -142,7 +142,7 @@ Signed-off-by: Maharaja Kennadyrajan } --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -1769,6 +1769,8 @@ int ath11k_core_pre_init(struct ath11k_b +@@ -2031,6 +2031,8 @@ int ath11k_core_pre_init(struct ath11k_b if (nss_offload) ab->nss.stats_enabled = 1; @@ -153,8 +153,8 @@ Signed-off-by: Maharaja Kennadyrajan EXPORT_SYMBOL(ath11k_core_pre_init); --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -839,6 +839,23 @@ struct ath11k_internal_pci { - wait_queue_head_t gic_msi_waitq; +@@ -949,6 +949,23 @@ struct ath11k_num_vdevs_peers { + u32 num_peers; }; +struct ath11k_memory_stats { @@ -177,7 +177,7 @@ Signed-off-by: Maharaja Kennadyrajan /* Master structure to hold the hw data which may be used in core module */ struct ath11k_base { enum ath11k_hw_rev hw_rev; -@@ -920,6 +937,7 @@ struct ath11k_base { +@@ -1041,6 +1058,7 @@ struct ath11k_base { enum ath11k_dfs_region dfs_region; #ifdef CPTCFG_ATH11K_DEBUGFS struct dentry *debugfs_soc; @@ -185,14 +185,14 @@ Signed-off-by: Maharaja Kennadyrajan #endif struct ath11k_soc_dp_stats soc_stats; -@@ -974,6 +992,7 @@ struct ath11k_base { +@@ -1108,6 +1126,7 @@ struct ath11k_base { + u32 ce_remap_base_addr; + atomic_t num_max_allowed; struct ath11k_num_vdevs_peers *num_vdevs_peers; - int userpd_id; - struct ath11k_internal_pci ipci; + bool enable_memory_stats; /* must be last */ - u8 drv_priv[0] __aligned(sizeof(void *)); + u8 drv_priv[] __aligned(sizeof(void *)); --- a/drivers/net/wireless/ath/ath11k/coredump.c +++ b/drivers/net/wireless/ath/ath11k/coredump.c @@ -109,6 +109,8 @@ void ath11k_coredump_build_inline(struct @@ -256,7 +256,7 @@ Signed-off-by: Maharaja Kennadyrajan } --- a/drivers/net/wireless/ath/ath11k/dbring.c +++ b/drivers/net/wireless/ath/ath11k/dbring.c -@@ -138,6 +138,7 @@ static int ath11k_dbring_fill_bufs(struc +@@ -141,6 +141,7 @@ static int ath11k_dbring_fill_bufs(struc break; } num_remain--; @@ -264,7 +264,7 @@ Signed-off-by: Maharaja Kennadyrajan } spin_unlock_bh(&srng->lock); -@@ -383,6 +384,8 @@ void ath11k_dbring_buf_cleanup(struct at +@@ -390,6 +391,8 @@ void ath11k_dbring_buf_cleanup(struct at idr_remove(&ring->bufs_idr, buf_id); dma_unmap_single(ar->ab->dev, buff->paddr, ring->buf_sz, DMA_FROM_DEVICE); @@ -275,7 +275,7 @@ Signed-off-by: Maharaja Kennadyrajan } --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -1409,6 +1409,8 @@ static ssize_t ath11k_debugfs_dump_soc_d +@@ -1450,6 +1450,8 @@ static ssize_t ath11k_debugfs_dump_soc_d if (!buf) return -ENOMEM; @@ -284,7 +284,7 @@ Signed-off-by: Maharaja Kennadyrajan len += scnprintf(buf + len, size - len, "SOC RX STATS:\n\n"); len += scnprintf(buf + len, size - len, "err ring pkts: %u\n", soc_stats->err_ring_pkts); -@@ -1450,6 +1452,8 @@ static ssize_t ath11k_debugfs_dump_soc_d +@@ -1491,6 +1493,8 @@ static ssize_t ath11k_debugfs_dump_soc_d retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); kfree(buf); @@ -293,7 +293,7 @@ Signed-off-by: Maharaja Kennadyrajan return retval; } -@@ -1527,6 +1531,106 @@ static const struct file_operations fops +@@ -1631,6 +1635,106 @@ static const struct file_operations fops .open = simple_open, }; @@ -400,7 +400,7 @@ Signed-off-by: Maharaja Kennadyrajan int ath11k_debugfs_pdev_create(struct ath11k_base *ab) { if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)) -@@ -1545,6 +1649,12 @@ int ath11k_debugfs_pdev_create(struct at +@@ -1649,6 +1753,12 @@ int ath11k_debugfs_pdev_create(struct at debugfs_create_file("set_fw_recovery", 0600, ab->debugfs_soc, ab, &fops_fw_recovery); @@ -413,7 +413,7 @@ Signed-off-by: Maharaja Kennadyrajan return 0; } -@@ -2275,6 +2385,8 @@ static ssize_t ath11k_dump_mgmt_stats(st +@@ -2537,6 +2647,8 @@ static ssize_t ath11k_dump_mgmt_stats(st if (!buf) return -ENOMEM; @@ -422,7 +422,7 @@ Signed-off-by: Maharaja Kennadyrajan mutex_lock(&ar->conf_mutex); spin_lock_bh(&ar->data_lock); -@@ -2325,6 +2437,9 @@ static ssize_t ath11k_dump_mgmt_stats(st +@@ -2587,6 +2699,9 @@ static ssize_t ath11k_dump_mgmt_stats(st ret = simple_read_from_buffer(ubuf, count, ppos, buf, len); mutex_unlock(&ar->conf_mutex); kfree(buf); @@ -442,7 +442,7 @@ Signed-off-by: Maharaja Kennadyrajan /* htt_dbg_ext_stats_type */ enum ath11k_dbg_htt_ext_stats_type { -@@ -163,6 +164,24 @@ void ath11k_debugfs_wmi_ctrl_stats(struc +@@ -318,6 +319,24 @@ void ath11k_debugfs_wmi_ctrl_stats(struc void ath11k_wmi_crl_path_stats_list_free(struct list_head *head); #ifdef CPTCFG_ATH11K_DEBUGFS @@ -467,9 +467,9 @@ Signed-off-by: Maharaja Kennadyrajan int ath11k_debugfs_create(void); void ath11k_debugfs_destroy(void); int ath11k_debugfs_soc_create(struct ath11k_base *ab); -@@ -210,6 +229,11 @@ static inline int ath11k_debugfs_rx_filt - return ar->debug.rx_filter; - } +@@ -372,6 +391,11 @@ void ath11k_debugfs_add_dbring_entry(str + enum ath11k_dbg_dbr_event event, + struct hal_srng *srng); +static inline int ath11k_debug_is_memory_stats_enabled(struct ath11k_base *ab) +{ @@ -479,7 +479,7 @@ Signed-off-by: Maharaja Kennadyrajan #else static inline int ath11k_debugfs_create(void) { -@@ -287,6 +311,11 @@ static inline bool ath11k_debugfs_is_pkt +@@ -449,6 +473,11 @@ static inline bool ath11k_debugfs_is_pkt return false; } @@ -522,7 +522,7 @@ Signed-off-by: Maharaja Kennadyrajan ring->vaddr_unaligned = NULL; } -@@ -278,6 +280,8 @@ int ath11k_dp_srng_setup(struct ath11k_b +@@ -277,6 +279,8 @@ int ath11k_dp_srng_setup(struct ath11k_b if (!ring->vaddr_unaligned) return -ENOMEM; @@ -531,7 +531,7 @@ Signed-off-by: Maharaja Kennadyrajan ring->vaddr = PTR_ALIGN(ring->vaddr_unaligned, HAL_RING_BASE_ALIGN); ring->paddr = ring->paddr_unaligned + ((unsigned long)ring->vaddr - (unsigned long)ring->vaddr_unaligned); -@@ -510,6 +514,7 @@ static void ath11k_dp_scatter_idle_link_ +@@ -509,6 +513,7 @@ static void ath11k_dp_scatter_idle_link_ dma_free_coherent(ab->dev, HAL_WBM_IDLE_SCATTER_BUF_SIZE_MAX, slist[i].vaddr, slist[i].paddr); slist[i].vaddr = NULL; @@ -539,7 +539,7 @@ Signed-off-by: Maharaja Kennadyrajan } } -@@ -547,6 +552,7 @@ static int ath11k_dp_scatter_idle_link_d +@@ -546,6 +551,7 @@ static int ath11k_dp_scatter_idle_link_d ret = -ENOMEM; goto err; } @@ -547,7 +547,7 @@ Signed-off-by: Maharaja Kennadyrajan } scatter_idx = 0; -@@ -601,6 +607,7 @@ ath11k_dp_link_desc_bank_free(struct ath +@@ -600,6 +606,7 @@ ath11k_dp_link_desc_bank_free(struct ath link_desc_banks[i].vaddr_unaligned, link_desc_banks[i].paddr_unaligned); link_desc_banks[i].vaddr_unaligned = NULL; @@ -555,7 +555,7 @@ Signed-off-by: Maharaja Kennadyrajan } } } -@@ -634,6 +641,7 @@ static int ath11k_dp_link_desc_bank_allo +@@ -633,6 +640,7 @@ static int ath11k_dp_link_desc_bank_allo ((unsigned long)desc_bank[i].vaddr - (unsigned long)desc_bank[i].vaddr_unaligned); desc_bank[i].size = desc_sz; @@ -563,7 +563,7 @@ Signed-off-by: Maharaja Kennadyrajan } return 0; -@@ -1040,8 +1048,11 @@ static int ath11k_dp_tx_pending_cleanup( +@@ -1039,8 +1047,11 @@ static int ath11k_dp_tx_pending_cleanup( void ath11k_dp_free(struct ath11k_base *ab) { struct ath11k_dp *dp = &ab->dp; @@ -575,7 +575,7 @@ Signed-off-by: Maharaja Kennadyrajan ath11k_dp_link_desc_cleanup(ab, dp->link_desc_banks, HAL_WBM_IDLE_LINK, &dp->wbm_idle_ring); -@@ -1055,6 +1066,7 @@ void ath11k_dp_free(struct ath11k_base * +@@ -1054,6 +1065,7 @@ void ath11k_dp_free(struct ath11k_base * ath11k_dp_tx_pending_cleanup, ab); idr_destroy(&dp->tx_ring[i].txbuf_idr); spin_unlock_bh(&dp->tx_ring[i].tx_idr_lock); @@ -583,7 +583,7 @@ Signed-off-by: Maharaja Kennadyrajan kfree(dp->tx_ring[i].tx_status); } -@@ -1112,6 +1124,7 @@ int ath11k_dp_alloc(struct ath11k_base * +@@ -1111,6 +1123,7 @@ int ath11k_dp_alloc(struct ath11k_base * ret = -ENOMEM; goto fail_cmn_srng_cleanup; } @@ -593,7 +593,7 @@ Signed-off-by: Maharaja Kennadyrajan for (i = 0; i < ab->hw_params.num_dscp_tid_map_tbl; i++) --- a/drivers/net/wireless/ath/ath11k/hal.c +++ b/drivers/net/wireless/ath/ath11k/hal.c -@@ -200,6 +200,8 @@ static int ath11k_hal_alloc_cont_rdp(str +@@ -201,6 +201,8 @@ static int ath11k_hal_alloc_cont_rdp(str if (!hal->rdp.vaddr) return -ENOMEM; @@ -602,7 +602,7 @@ Signed-off-by: Maharaja Kennadyrajan return 0; } -@@ -214,6 +216,7 @@ static void ath11k_hal_free_cont_rdp(str +@@ -215,6 +217,7 @@ static void ath11k_hal_free_cont_rdp(str size = sizeof(u32) * HAL_SRNG_RING_ID_MAX; dma_free_coherent(ab->dev, size, hal->rdp.vaddr, hal->rdp.paddr); @@ -610,7 +610,7 @@ Signed-off-by: Maharaja Kennadyrajan hal->rdp.vaddr = NULL; } -@@ -228,6 +231,8 @@ static int ath11k_hal_alloc_cont_wrp(str +@@ -229,6 +232,8 @@ static int ath11k_hal_alloc_cont_wrp(str if (!hal->wrp.vaddr) return -ENOMEM; @@ -619,7 +619,7 @@ Signed-off-by: Maharaja Kennadyrajan return 0; } -@@ -242,6 +247,7 @@ static void ath11k_hal_free_cont_wrp(str +@@ -243,6 +248,7 @@ static void ath11k_hal_free_cont_wrp(str size = sizeof(u32) * HAL_SRNG_NUM_LMAC_RINGS; dma_free_coherent(ab->dev, size, hal->wrp.vaddr, hal->wrp.paddr); @@ -637,7 +637,7 @@ Signed-off-by: Maharaja Kennadyrajan kfree_skb(skb); } -@@ -593,6 +594,7 @@ int ath11k_htc_connect_service(struct at +@@ -601,6 +602,7 @@ int ath11k_htc_connect_service(struct at bool disable_credit_flow_ctrl = false; u16 message_id, service_id, flags = 0; u8 tx_alloc = 0; @@ -645,7 +645,7 @@ Signed-off-by: Maharaja Kennadyrajan /* special case for HTC pseudo control service */ if (conn_req->service_id == ATH11K_HTC_SVC_ID_RSVD_CTRL) { -@@ -616,6 +618,7 @@ int ath11k_htc_connect_service(struct at +@@ -624,6 +626,7 @@ int ath11k_htc_connect_service(struct at return -ENOMEM; } @@ -653,7 +653,7 @@ Signed-off-by: Maharaja Kennadyrajan length = sizeof(*req_msg); skb_put(skb, length); memset(skb->data, 0, length); -@@ -651,6 +654,8 @@ int ath11k_htc_connect_service(struct at +@@ -659,6 +662,8 @@ int ath11k_htc_connect_service(struct at return status; } @@ -662,7 +662,7 @@ Signed-off-by: Maharaja Kennadyrajan /* wait for response */ time_left = wait_for_completion_timeout(&htc->ctl_resp, ATH11K_HTC_CONN_SVC_TIMEOUT_HZ); -@@ -752,11 +757,13 @@ int ath11k_htc_start(struct ath11k_htc * +@@ -760,11 +765,13 @@ int ath11k_htc_start(struct ath11k_htc * int status = 0; struct ath11k_base *ab = htc->ab; struct ath11k_htc_setup_complete_extended *msg; @@ -676,7 +676,7 @@ Signed-off-by: Maharaja Kennadyrajan skb_put(skb, sizeof(*msg)); memset(skb->data, 0, skb->len); -@@ -775,6 +782,8 @@ int ath11k_htc_start(struct ath11k_htc * +@@ -783,6 +790,8 @@ int ath11k_htc_start(struct ath11k_htc * return status; } @@ -687,7 +687,7 @@ Signed-off-by: Maharaja Kennadyrajan --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -3844,6 +3844,8 @@ static int ath11k_mac_op_hw_scan(struct +@@ -3859,6 +3859,8 @@ static int ath11k_mac_op_hw_scan(struct goto exit; } @@ -696,7 +696,7 @@ Signed-off-by: Maharaja Kennadyrajan ath11k_wmi_start_scan_init(ar, arg); arg->vdev_id = arvif->vdev_id; arg->scan_id = ATH11K_SCAN_ID; -@@ -3857,6 +3859,8 @@ static int ath11k_mac_op_hw_scan(struct +@@ -3872,6 +3874,8 @@ static int ath11k_mac_op_hw_scan(struct arg->extraie.len = req->ie_len; } @@ -705,7 +705,7 @@ Signed-off-by: Maharaja Kennadyrajan if (req->n_ssids) { arg->num_ssids = req->n_ssids; for (i = 0; i < arg->num_ssids; i++) { -@@ -3914,8 +3918,13 @@ static int ath11k_mac_op_hw_scan(struct +@@ -3929,8 +3933,13 @@ static int ath11k_mac_op_hw_scan(struct exit: if (arg) { @@ -720,7 +720,7 @@ Signed-off-by: Maharaja Kennadyrajan kfree(arg); } -@@ -7394,6 +7403,8 @@ ath11k_mac_update_active_vif_chan(struct +@@ -7411,6 +7420,8 @@ ath11k_mac_update_active_vif_chan(struct if (!arg.vifs) return; @@ -729,7 +729,7 @@ Signed-off-by: Maharaja Kennadyrajan ieee80211_iterate_active_interfaces_atomic(ar->hw, IEEE80211_IFACE_ITER_NORMAL, ath11k_mac_change_chanctx_fill_iter, -@@ -7401,6 +7412,8 @@ ath11k_mac_update_active_vif_chan(struct +@@ -7418,6 +7429,8 @@ ath11k_mac_update_active_vif_chan(struct ath11k_mac_update_vif_chan(ar, arg.vifs, arg.n_vifs); @@ -850,7 +850,7 @@ Signed-off-by: Maharaja Kennadyrajan ath11k_dbg(ab, ATH11K_DBG_NSS, "curr page %d, allocated %d, total allocated %d\n", curr_page_idx, alloc_size, i + alloc_size); -@@ -2227,6 +2253,8 @@ static int ath11k_nss_init(struct ath11k +@@ -2224,6 +2250,8 @@ static int ath11k_nss_init(struct ath11k if (!wlmsg) return -ENOMEM; @@ -859,7 +859,7 @@ Signed-off-by: Maharaja Kennadyrajan wim = &wlmsg->msg.init; wim->target_type = target_type; -@@ -2344,6 +2372,7 @@ unregister: +@@ -2341,6 +2369,7 @@ unregister: nss_unregister_wifili_if(ab->nss.if_num); free: ath11k_nss_tx_desc_mem_free(ab); @@ -867,7 +867,7 @@ Signed-off-by: Maharaja Kennadyrajan kfree(wlmsg); return -EINVAL; } -@@ -2450,6 +2479,8 @@ int ath11k_nss_pdev_init(struct ath11k_b +@@ -2447,6 +2476,8 @@ int ath11k_nss_pdev_init(struct ath11k_b goto unregister; } @@ -876,7 +876,7 @@ Signed-off-by: Maharaja Kennadyrajan pdevmsg = &wlmsg->msg.pdevmsg; pdevmsg->radio_id = radio_id; -@@ -2495,6 +2526,8 @@ int ath11k_nss_pdev_init(struct ath11k_b +@@ -2492,6 +2523,8 @@ int ath11k_nss_pdev_init(struct ath11k_b goto free; } @@ -885,7 +885,7 @@ Signed-off-by: Maharaja Kennadyrajan kfree(wlmsg); /* Disable nss sojourn stats by default */ -@@ -2513,6 +2546,7 @@ int ath11k_nss_pdev_init(struct ath11k_b +@@ -2510,6 +2543,7 @@ int ath11k_nss_pdev_init(struct ath11k_b return 0; free: @@ -893,7 +893,7 @@ Signed-off-by: Maharaja Kennadyrajan kfree(wlmsg); unregister: nss_unregister_wifili_radio_if(ar->nss.if_num); -@@ -2535,6 +2569,8 @@ int ath11k_nss_start(struct ath11k_base +@@ -2532,6 +2566,8 @@ int ath11k_nss_start(struct ath11k_base if (!wlmsg) return -ENOMEM; @@ -902,7 +902,7 @@ Signed-off-by: Maharaja Kennadyrajan msg_cb = (nss_wifili_msg_callback_t)ath11k_nss_wifili_event_receive; /* Empty message for NSS Start message */ -@@ -2575,6 +2611,7 @@ int ath11k_nss_start(struct ath11k_base +@@ -2572,6 +2608,7 @@ int ath11k_nss_start(struct ath11k_base ath11k_dbg(ab, ATH11K_DBG_NSS, "nss start success\n"); free: @@ -910,7 +910,7 @@ Signed-off-by: Maharaja Kennadyrajan kfree(wlmsg); return ret; } -@@ -2593,6 +2630,8 @@ static void ath11k_nss_reset(struct ath1 +@@ -2590,6 +2627,8 @@ static void ath11k_nss_reset(struct ath1 return; } @@ -919,7 +919,7 @@ Signed-off-by: Maharaja Kennadyrajan msg_cb = (nss_wifili_msg_callback_t)ath11k_nss_wifili_event_receive; /* Empty message for NSS Reset message */ -@@ -2631,6 +2670,7 @@ static void ath11k_nss_reset(struct ath1 +@@ -2628,6 +2667,7 @@ static void ath11k_nss_reset(struct ath1 nss_unregister_wifili_if(ab->nss.if_num); free: @@ -927,7 +927,7 @@ Signed-off-by: Maharaja Kennadyrajan kfree(wlmsg); } -@@ -2646,6 +2686,8 @@ static int ath11k_nss_stop(struct ath11k +@@ -2643,6 +2683,8 @@ static int ath11k_nss_stop(struct ath11k if (!wlmsg) return -ENOMEM; @@ -936,7 +936,7 @@ Signed-off-by: Maharaja Kennadyrajan msg_cb = (nss_wifili_msg_callback_t)ath11k_nss_wifili_event_receive; /* Empty message for Stop command */ -@@ -2685,6 +2727,8 @@ static int ath11k_nss_stop(struct ath11k +@@ -2682,6 +2724,8 @@ static int ath11k_nss_stop(struct ath11k /* NSS Stop success */ ret = 0; free: @@ -945,7 +945,7 @@ Signed-off-by: Maharaja Kennadyrajan kfree(wlmsg); return ret; } -@@ -2710,6 +2754,8 @@ int ath11k_nss_pdev_deinit(struct ath11k +@@ -2707,6 +2751,8 @@ int ath11k_nss_pdev_deinit(struct ath11k if (!wlmsg) return -ENOMEM; @@ -954,7 +954,7 @@ Signed-off-by: Maharaja Kennadyrajan deinit = &wlmsg->msg.pdevdeinit; deinit->ifnum = radio_id; -@@ -2752,6 +2798,7 @@ int ath11k_nss_pdev_deinit(struct ath11k +@@ -2749,6 +2795,7 @@ int ath11k_nss_pdev_deinit(struct ath11k nss_dynamic_interface_dealloc_node(ar->nss.if_num, dyn_if_type); nss_unregister_wifili_radio_if(ar->nss.if_num); free: @@ -964,7 +964,7 @@ Signed-off-by: Maharaja Kennadyrajan } --- a/drivers/net/wireless/ath/ath11k/peer.c +++ b/drivers/net/wireless/ath/ath11k/peer.c -@@ -670,6 +670,9 @@ int ath11k_peer_delete(struct ath11k *ar +@@ -777,6 +777,9 @@ int ath11k_peer_delete(struct ath11k *ar if (ret) return ret; @@ -974,7 +974,7 @@ Signed-off-by: Maharaja Kennadyrajan ar->num_peers--; return 0; -@@ -758,6 +761,8 @@ int ath11k_peer_create(struct ath11k *ar +@@ -874,6 +877,8 @@ int ath11k_peer_create(struct ath11k *ar arsta->tcl_metadata &= ~HTT_TCL_META_DATA_VALID_HTT; } @@ -985,7 +985,7 @@ Signed-off-by: Maharaja Kennadyrajan spin_unlock_bh(&ar->ab->base_lock); --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -623,6 +623,8 @@ struct sk_buff *ath11k_wmi_alloc_skb(str +@@ -626,6 +626,8 @@ struct sk_buff *ath11k_wmi_alloc_skb(str if (!skb) return NULL; @@ -994,7 +994,7 @@ Signed-off-by: Maharaja Kennadyrajan skb_reserve(skb, WMI_SKB_HEADROOM); if (!IS_ALIGNED((unsigned long)skb->data, 4)) ath11k_warn(ab, "unaligned WMI skb data\n"); -@@ -7013,6 +7015,7 @@ static void ath11k_wmi_htc_tx_complete(s +@@ -7066,6 +7068,7 @@ static void ath11k_wmi_htc_tx_complete(s u8 eid; eid = ATH11K_SKB_CB(skb)->eid; @@ -1002,7 +1002,7 @@ Signed-off-by: Maharaja Kennadyrajan dev_kfree_skb(skb); if (eid >= ATH11K_HTC_EP_COUNT) -@@ -9451,6 +9454,7 @@ static void ath11k_wmi_tlv_op_rx(struct +@@ -9385,6 +9388,7 @@ static void ath11k_wmi_tlv_op_rx(struct } out: diff --git a/feeds/ipq95xx/mac80211/patches/qca/233-002-mac80211-add-support-memory-stats.patch b/feeds/ipq95xx/mac80211/patches/qca/233-002-mac80211-add-support-memory-stats.patch index b8472761b..cdf925c50 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/233-002-mac80211-add-support-memory-stats.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/233-002-mac80211-add-support-memory-stats.patch @@ -54,17 +54,17 @@ Signed-off-by: Maharaja Kennadyrajan --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c -@@ -556,6 +556,9 @@ ieee80211_alloc_chanctx(struct ieee80211 +@@ -631,6 +631,9 @@ ieee80211_alloc_chanctx(struct ieee80211 if (!ctx) return NULL; + atomic_add(sizeof(*ctx) + local->hw.chanctx_data_size, + &local->memory_stats.malloc_size); + - INIT_LIST_HEAD(&ctx->assigned_vifs); - INIT_LIST_HEAD(&ctx->reserved_vifs); + INIT_LIST_HEAD(&ctx->assigned_links); + INIT_LIST_HEAD(&ctx->reserved_links); ctx->conf.def = *chandef; -@@ -616,6 +619,8 @@ ieee80211_new_chanctx(struct ieee80211_l +@@ -691,6 +694,8 @@ ieee80211_new_chanctx(struct ieee80211_l err = ieee80211_add_chanctx(local, ctx); if (err) { @@ -73,7 +73,7 @@ Signed-off-by: Maharaja Kennadyrajan kfree(ctx); return ERR_PTR(err); } -@@ -668,6 +673,8 @@ static void ieee80211_free_chanctx(struc +@@ -743,6 +748,8 @@ static void ieee80211_free_chanctx(struc list_del_rcu(&ctx->list); ieee80211_del_chanctx(local, ctx); @@ -82,7 +82,7 @@ Signed-off-by: Maharaja Kennadyrajan kfree_rcu(ctx, rcu_head); } -@@ -1298,6 +1305,9 @@ static int ieee80211_chsw_switch_vifs(st +@@ -1420,6 +1427,9 @@ static int ieee80211_chsw_switch_vifs(st if (!vif_chsw) return -ENOMEM; @@ -92,7 +92,7 @@ Signed-off-by: Maharaja Kennadyrajan i = 0; list_for_each_entry(ctx, &local->chanctx_list, list) { if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER) -@@ -1327,6 +1337,8 @@ static int ieee80211_chsw_switch_vifs(st +@@ -1449,6 +1459,8 @@ static int ieee80211_chsw_switch_vifs(st CHANCTX_SWMODE_SWAP_CONTEXTS); out: @@ -112,7 +112,7 @@ Signed-off-by: Maharaja Kennadyrajan static ssize_t aqm_read(struct file *file, char __user *user_buf, -@@ -689,6 +691,8 @@ void debugfs_hw_add(struct ieee80211_loc +@@ -680,6 +682,8 @@ void debugfs_hw_add(struct ieee80211_loc if (!statsd) return; @@ -123,8 +123,8 @@ Signed-off-by: Maharaja Kennadyrajan DEBUGFS_STATS_ADD(dot11MulticastTransmittedFrameCount); --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h -@@ -1210,6 +1210,10 @@ struct airtime_sched_info { - }; +@@ -1270,6 +1270,10 @@ enum mac80211_scan_state { + DECLARE_STATIC_KEY_FALSE(aql_disable); +struct mac80211_memory_stats { @@ -134,7 +134,7 @@ Signed-off-by: Maharaja Kennadyrajan struct ieee80211_local { /* embed the driver visible part. * don't cast (use the static inlines below), but we keep -@@ -1488,6 +1492,8 @@ struct ieee80211_local { +@@ -1555,6 +1559,8 @@ struct ieee80211_local { struct ieee80211_sub_if_data __rcu *monitor_sdata; struct cfg80211_chan_def monitor_chandef; @@ -145,7 +145,7 @@ Signed-off-by: Maharaja Kennadyrajan }; --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c -@@ -1158,6 +1158,9 @@ int ieee80211_add_virtual_monitor(struct +@@ -1365,6 +1365,9 @@ int ieee80211_add_virtual_monitor(struct return ret; } @@ -155,7 +155,7 @@ Signed-off-by: Maharaja Kennadyrajan skb_queue_head_init(&sdata->skb_queue); skb_queue_head_init(&sdata->status_queue); INIT_WORK(&sdata->work, ieee80211_iface_work); -@@ -1195,6 +1198,8 @@ void ieee80211_del_virtual_monitor(struc +@@ -1402,6 +1405,8 @@ void ieee80211_del_virtual_monitor(struc drv_remove_interface(local, sdata); @@ -166,7 +166,7 @@ Signed-off-by: Maharaja Kennadyrajan --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c -@@ -173,6 +173,8 @@ int mesh_rmc_init(struct ieee80211_sub_i +@@ -174,6 +174,8 @@ int mesh_rmc_init(struct ieee80211_sub_i sdata->u.mesh.rmc = kmalloc(sizeof(struct mesh_rmc), GFP_KERNEL); if (!sdata->u.mesh.rmc) return -ENOMEM; @@ -175,7 +175,7 @@ Signed-off-by: Maharaja Kennadyrajan sdata->u.mesh.rmc->idx_mask = RMC_BUCKETS - 1; for (i = 0; i < RMC_BUCKETS; i++) INIT_HLIST_HEAD(&sdata->u.mesh.rmc->bucket[i]); -@@ -196,6 +198,8 @@ void mesh_rmc_free(struct ieee80211_sub_ +@@ -197,6 +199,8 @@ void mesh_rmc_free(struct ieee80211_sub_ } } @@ -186,7 +186,7 @@ Signed-off-by: Maharaja Kennadyrajan } --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c -@@ -1001,6 +1001,9 @@ static void mesh_queue_preq(struct mesh_ +@@ -1006,6 +1006,9 @@ static void mesh_queue_preq(struct mesh_ return; } @@ -196,7 +196,7 @@ Signed-off-by: Maharaja Kennadyrajan memcpy(preq_node->dst, mpath->dst, ETH_ALEN); preq_node->flags = flags; -@@ -1115,6 +1118,8 @@ void mesh_path_start_discovery(struct ie +@@ -1120,6 +1123,8 @@ void mesh_path_start_discovery(struct ie enddiscovery: rcu_read_unlock(); @@ -207,7 +207,7 @@ Signed-off-by: Maharaja Kennadyrajan --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c -@@ -168,6 +168,7 @@ void ieee80211_offchannel_return(struct +@@ -170,6 +170,7 @@ void ieee80211_offchannel_return(struct static void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc) { @@ -215,7 +215,7 @@ Signed-off-by: Maharaja Kennadyrajan /* was never transmitted */ if (roc->frame) { cfg80211_mgmt_tx_status(&roc->sdata->wdev, roc->mgmt_tx_cookie, -@@ -186,6 +187,8 @@ static void ieee80211_roc_notify_destroy +@@ -188,6 +189,8 @@ static void ieee80211_roc_notify_destroy roc->chan, GFP_KERNEL); list_del(&roc->list); @@ -224,7 +224,7 @@ Signed-off-by: Maharaja Kennadyrajan kfree(roc); } -@@ -548,6 +551,8 @@ static int ieee80211_start_roc_work(stru +@@ -550,6 +553,8 @@ static int ieee80211_start_roc_work(stru if (!roc) return -ENOMEM; @@ -233,7 +233,7 @@ Signed-off-by: Maharaja Kennadyrajan /* * If the duration is zero, then the driver * wouldn't actually do anything. Set it to -@@ -593,6 +598,8 @@ static int ieee80211_start_roc_work(stru +@@ -595,6 +600,8 @@ static int ieee80211_start_roc_work(stru ret = drv_remain_on_channel(local, sdata, channel, duration, type); if (ret) { @@ -244,7 +244,7 @@ Signed-off-by: Maharaja Kennadyrajan } --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c -@@ -455,6 +455,12 @@ static void __ieee80211_scan_completed(s +@@ -469,6 +469,12 @@ static void __ieee80211_scan_completed(s scan_req = rcu_dereference_protected(local->scan_req, lockdep_is_held(&local->mtx)); @@ -257,7 +257,7 @@ Signed-off-by: Maharaja Kennadyrajan if (scan_req != local->int_scan_req) { local->scan_info.aborted = aborted; cfg80211_scan_done(scan_req, &local->scan_info); -@@ -724,6 +730,12 @@ static int __ieee80211_start_scan(struct +@@ -738,6 +744,12 @@ static int __ieee80211_start_scan(struct if (!local->hw_scan_req) return -ENOMEM; @@ -270,7 +270,7 @@ Signed-off-by: Maharaja Kennadyrajan local->hw_scan_req->req.chandef = req->chandef; local->hw_scan_req->req.ssids = req->ssids; local->hw_scan_req->req.n_ssids = req->n_ssids; -@@ -813,6 +825,12 @@ static int __ieee80211_start_scan(struct +@@ -829,6 +841,12 @@ static int __ieee80211_start_scan(struct } if (rc) { @@ -285,15 +285,15 @@ Signed-off-by: Maharaja Kennadyrajan local->scanning = 0; --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c -@@ -258,6 +258,7 @@ struct sta_info *sta_info_get_by_idx(str +@@ -354,6 +354,7 @@ static void sta_remove_link(struct sta_i */ void sta_info_free(struct ieee80211_local *local, struct sta_info *sta) { + struct ieee80211_hw *hw = &local->hw; - /* - * If we had used sta_info_pre_move_state() then we might not - * have gone through the state transitions down again, so do -@@ -285,8 +286,13 @@ void sta_info_free(struct ieee80211_loca + int i; + + for (i = 0; i < ARRAY_SIZE(sta->link); i++) { +@@ -390,9 +391,13 @@ void sta_info_free(struct ieee80211_loca kfree(to_txq_info(sta->sta.txq[0])); kfree(rcu_dereference_raw(sta->sta.rates)); #ifdef CPTCFG_MAC80211_MESH @@ -302,22 +302,23 @@ Signed-off-by: Maharaja Kennadyrajan + &local->memory_stats.malloc_size); kfree(sta->mesh); #endif +- + atomic_sub(sizeof(*sta) + hw->sta_data_size, + &local->memory_stats.malloc_size); - free_percpu(sta->pcpu_rx_stats); + sta_info_free_link(&sta->deflink); kfree(sta); } -@@ -345,6 +351,9 @@ struct sta_info *sta_info_alloc(struct i - if (!sta) - return NULL; +@@ -493,6 +498,9 @@ __sta_info_alloc(struct ieee80211_sub_if + sta->local = local; + sta->sdata = sdata; + atomic_add(sizeof(*sta) + hw->sta_data_size, + &local->memory_stats.malloc_size); + - if (ieee80211_hw_check(hw, USES_RSS)) { - sta->pcpu_rx_stats = - alloc_percpu_gfp(struct ieee80211_sta_rx_stats, gfp); -@@ -362,6 +371,8 @@ struct sta_info *sta_info_alloc(struct i + if (sta_info_alloc_link(local, &sta->deflink, gfp)) + return NULL; + +@@ -514,6 +522,8 @@ __sta_info_alloc(struct ieee80211_sub_if sta->mesh = kzalloc(sizeof(*sta->mesh), gfp); if (!sta->mesh) goto free; @@ -325,10 +326,10 @@ Signed-off-by: Maharaja Kennadyrajan + &local->memory_stats.malloc_size); sta->mesh->plink_sta = sta; spin_lock_init(&sta->mesh->plink_lock); - if (ieee80211_vif_is_mesh(&sdata->vif) && -@@ -525,8 +536,12 @@ free_txq: + if (!sdata->u.mesh.user_mpm) +@@ -645,8 +655,12 @@ free_txq: free: - free_percpu(sta->pcpu_rx_stats); + sta_info_free_link(&sta->deflink); #ifdef CPTCFG_MAC80211_MESH + atomic_sub(sizeof(*sta->mesh), + &local->memory_stats.malloc_size); diff --git a/feeds/ipq95xx/mac80211/patches/qca/233-ath11k-Disable-rx_header-tlv-for-2K-SKB.patch b/feeds/ipq95xx/mac80211/patches/qca/233-ath11k-Disable-rx_header-tlv-for-2K-SKB.patch index 6d27b7f23..5c22c6f30 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/233-ath11k-Disable-rx_header-tlv-for-2K-SKB.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/233-ath11k-Disable-rx_header-tlv-for-2K-SKB.patch @@ -10,11 +10,9 @@ to unsubscribe rx_pkt_header tlv for rxdma ring. Signed-off-by: Ramya Gnanasekar -Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k/debugfs.c -=================================================================== ---- backports-20211207_001-5.4.164-b7ab87182e.orig/drivers/net/wireless/ath/ath11k/debugfs.c -+++ backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -1230,6 +1230,7 @@ static ssize_t ath11k_write_extd_rx_stat +--- a/drivers/net/wireless/ath/ath11k/debugfs.c ++++ b/drivers/net/wireless/ath/ath11k/debugfs.c +@@ -1316,6 +1316,7 @@ static ssize_t ath11k_write_extd_rx_stat } ar->debug.rx_filter = tlv_filter.rx_filter; @@ -22,7 +20,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) { ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id; -@@ -1745,6 +1746,7 @@ static ssize_t ath11k_write_pktlog_filte +@@ -1889,6 +1890,7 @@ static ssize_t ath11k_write_pktlog_filte } /* Clear rx filter set for monitor mode and rx status */ @@ -30,11 +28,9 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) { ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id; ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id, -Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k/dp.h -=================================================================== ---- backports-20211207_001-5.4.164-b7ab87182e.orig/drivers/net/wireless/ath/ath11k/dp.h -+++ backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k/dp.h -@@ -225,7 +225,8 @@ struct ath11k_pdev_dp { +--- a/drivers/net/wireless/ath/ath11k/dp.h ++++ b/drivers/net/wireless/ath/ath11k/dp.h +@@ -217,7 +217,8 @@ struct ath11k_pdev_dp { #define DP_REO_CMD_RING_SIZE 128 #define DP_REO_STATUS_RING_SIZE 2048 #define DP_RXDMA_BUF_RING_SIZE 4096 @@ -44,7 +40,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k #define DP_RXDMA_ERR_DST_RING_SIZE 1024 #define DP_RXDMA_MON_STATUS_RING_SIZE ATH11K_DP_RXDMA_MON_STATUS_RING_SIZE #define DP_RXDMA_MONITOR_BUF_RING_SIZE ATH11K_DP_RXDMA_MONITOR_BUF_RING_SIZE -@@ -648,7 +649,7 @@ enum htt_stats_internal_ppdu_frametype { +@@ -640,7 +641,7 @@ enum htt_stats_internal_ppdu_frametype { * * |31 26|25|24|23 16|15 8|7 0| * |-----------------+----------------+----------------+---------------| @@ -53,7 +49,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k * |-------------------------------------------------------------------| * | rsvd2 | ring_buffer_size | * |-------------------------------------------------------------------| -@@ -662,6 +663,14 @@ enum htt_stats_internal_ppdu_frametype { +@@ -654,6 +655,14 @@ enum htt_stats_internal_ppdu_frametype { * |-------------------------------------------------------------------| * | tlv_filter_in_flags | * |-------------------------------------------------------------------| @@ -68,7 +64,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k * Where: * PS = pkt_swap * SS = status_swap -@@ -675,7 +684,10 @@ enum htt_stats_internal_ppdu_frametype { +@@ -667,7 +676,10 @@ enum htt_stats_internal_ppdu_frametype { * More details can be got from enum htt_srng_ring_id * b'24 - status_swap: 1 is to swap status TLV * b'25 - pkt_swap: 1 is to swap packet TLV @@ -80,7 +76,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k * dword1 - b'0:16 - ring_buffer_size: size of bufferes referenced by rx ring, * in byte units. * Valid only for HW_TO_SW_RING and SW_TO_HW_RING -@@ -704,6 +716,42 @@ enum htt_stats_internal_ppdu_frametype { +@@ -696,6 +708,42 @@ enum htt_stats_internal_ppdu_frametype { * dword6 - b'0:31 - tlv_filter_in_flags: * Filter in Attention/MPDU/PPDU/Header/User tlvs * Refer to CFG_TLV_FILTER_IN_FLAG defs @@ -123,7 +119,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k */ #define HTT_RX_RING_SELECTION_CFG_CMD_INFO0_MSG_TYPE GENMASK(7, 0) -@@ -711,8 +759,16 @@ enum htt_stats_internal_ppdu_frametype { +@@ -703,8 +751,16 @@ enum htt_stats_internal_ppdu_frametype { #define HTT_RX_RING_SELECTION_CFG_CMD_INFO0_RING_ID GENMASK(23, 16) #define HTT_RX_RING_SELECTION_CFG_CMD_INFO0_SS BIT(24) #define HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PS BIT(25) @@ -140,7 +136,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k enum htt_rx_filter_tlv_flags { HTT_RX_FILTER_TLV_FLAGS_MPDU_START = BIT(0), -@@ -1016,6 +1072,14 @@ enum htt_rx_data_pkt_filter_tlv_flasg3 { +@@ -1008,6 +1064,14 @@ enum htt_rx_data_pkt_filter_tlv_flasg3 { HTT_RX_FILTER_TLV_FLAGS_PER_MSDU_HEADER | \ HTT_RX_FILTER_TLV_FLAGS_ATTENTION) @@ -155,7 +151,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k struct htt_rx_ring_selection_cfg_cmd { u32 info0; u32 info1; -@@ -1024,6 +1088,10 @@ struct htt_rx_ring_selection_cfg_cmd { +@@ -1016,6 +1080,10 @@ struct htt_rx_ring_selection_cfg_cmd { u32 pkt_type_en_flags2; u32 pkt_type_en_flags3; u32 rx_filter_tlv; @@ -166,7 +162,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k } __packed; struct htt_rx_ring_tlv_filter { -@@ -1032,6 +1100,14 @@ struct htt_rx_ring_tlv_filter { +@@ -1024,6 +1092,14 @@ struct htt_rx_ring_tlv_filter { u32 pkt_filter_flags1; /* MGMT */ u32 pkt_filter_flags2; /* CTRL */ u32 pkt_filter_flags3; /* DATA */ @@ -180,12 +176,10 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k + u16 rx_attn_offset; }; - /** -Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k/dp_rx.c -=================================================================== ---- backports-20211207_001-5.4.164-b7ab87182e.orig/drivers/net/wireless/ath/ath11k/dp_rx.c -+++ backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -63,6 +63,12 @@ static inline bool ath11k_dp_rx_h_mpdu_s + #define HTT_RX_FULL_MON_MODE_CFG_CMD_INFO0_MSG_TYPE GENMASK(7, 0) +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -70,6 +70,12 @@ static inline bool ath11k_dp_rx_h_mpdu_s return ab->hw_params.hw_ops->rx_desc_get_mpdu_fc_valid(desc); } @@ -198,7 +192,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k static inline bool ath11k_dp_rx_h_mpdu_start_more_frags(struct ath11k_base *ab, struct sk_buff *skb) { -@@ -299,6 +305,35 @@ static u8 *ath11k_dp_rxdesc_mpdu_start_a +@@ -306,6 +312,35 @@ static u8 *ath11k_dp_rxdesc_mpdu_start_a return ab->hw_params.hw_ops->rx_desc_mpdu_start_addr2(desc); } @@ -234,7 +228,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k static void ath11k_dp_service_mon_ring(struct timer_list *t) { struct ath11k_base *ab = from_timer(ab, t, mon_reap_timer); -@@ -2124,6 +2159,49 @@ int ath11k_dp_rx_crypto_icv_len(struct a +@@ -2133,6 +2168,49 @@ int ath11k_dp_rx_crypto_icv_len(struct a return 0; } @@ -284,7 +278,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k static void ath11k_dp_rx_h_undecap_nwifi(struct ath11k *ar, struct sk_buff *msdu, u8 *first_hdr, -@@ -2137,7 +2215,8 @@ static void ath11k_dp_rx_h_undecap_nwifi +@@ -2146,7 +2224,8 @@ static void ath11k_dp_rx_h_undecap_nwifi u8 da[ETH_ALEN]; u8 sa[ETH_ALEN]; u16 qos_ctl = 0; @@ -294,7 +288,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k /* copy SA & DA and pull decapped header */ hdr = (struct ieee80211_hdr *)msdu->data; -@@ -2146,7 +2225,7 @@ static void ath11k_dp_rx_h_undecap_nwifi +@@ -2155,7 +2234,7 @@ static void ath11k_dp_rx_h_undecap_nwifi ether_addr_copy(sa, ieee80211_get_SA(hdr)); skb_pull(msdu, ieee80211_hdrlen(hdr->frame_control)); @@ -303,7 +297,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k /* original 802.11 header is valid for the first msdu * hence we can reuse the same header */ -@@ -2176,16 +2255,23 @@ static void ath11k_dp_rx_h_undecap_nwifi +@@ -2185,16 +2264,23 @@ static void ath11k_dp_rx_h_undecap_nwifi /* copy decap header before overwriting for reuse below */ memcpy(decap_hdr, (uint8_t *)hdr, hdr_len); @@ -332,7 +326,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k memcpy(skb_push(msdu, IEEE80211_QOS_CTL_LEN), &qos_ctl, IEEE80211_QOS_CTL_LEN); -@@ -2301,6 +2387,20 @@ static void ath11k_dp_rx_h_undecap_eth(s +@@ -2310,6 +2396,20 @@ static void ath11k_dp_rx_h_undecap_eth(s u8 da[ETH_ALEN]; u8 sa[ETH_ALEN]; void *rfc1042; @@ -353,7 +347,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k rfc1042 = ath11k_dp_rx_h_find_rfc1042(ar, msdu, enctype); if (WARN_ON_ONCE(!rfc1042)) -@@ -2329,6 +2429,7 @@ static void ath11k_dp_rx_h_undecap_eth(s +@@ -2338,6 +2438,7 @@ static void ath11k_dp_rx_h_undecap_eth(s memcpy(skb_push(msdu, hdr_len), hdr, hdr_len); @@ -361,7 +355,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k /* original 802.11 header has a different DA and in * case of 4addr it may also have different SA */ -@@ -2347,6 +2448,7 @@ static void ath11k_dp_rx_h_undecap_snap( +@@ -2356,6 +2457,7 @@ static void ath11k_dp_rx_h_undecap_snap( size_t hdr_len; u8 l3_pad_bytes; struct hal_rx_desc *rx_desc; @@ -369,7 +363,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k /* Delivered decapped frame: * [amsdu header] <-- replaced with 802.11 hdr -@@ -2360,6 +2462,11 @@ static void ath11k_dp_rx_h_undecap_snap( +@@ -2369,6 +2471,11 @@ static void ath11k_dp_rx_h_undecap_snap( skb_put(msdu, l3_pad_bytes); skb_pull(msdu, sizeof(struct ath11k_dp_amsdu_subframe_hdr) + l3_pad_bytes); @@ -381,7 +375,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k hdr = (struct ieee80211_hdr *)first_hdr; hdr_len = ieee80211_hdrlen(hdr->frame_control); -@@ -2753,6 +2860,20 @@ static int ath11k_dp_rx_process_msdu(str +@@ -2765,6 +2872,20 @@ static int ath11k_dp_rx_process_msdu(str goto free_out; } @@ -402,7 +396,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k rxcb = ATH11K_SKB_RXCB(msdu); rxcb->rx_desc = rx_desc; msdu_len = ath11k_dp_rx_h_msdu_start_msdu_len(ab, rx_desc); -@@ -2765,8 +2886,9 @@ static int ath11k_dp_rx_process_msdu(str +@@ -2777,8 +2898,9 @@ static int ath11k_dp_rx_process_msdu(str hdr_status = ath11k_dp_rx_h_80211_hdr(ab, rx_desc); ret = -EINVAL; ath11k_warn(ab, "invalid msdu len %u\n", msdu_len); @@ -414,7 +408,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k ath11k_dbg_dump(ab, ATH11K_DBG_DATA, NULL, "", rx_desc, sizeof(struct hal_rx_desc)); goto free_out; -@@ -3733,6 +3855,7 @@ static int ath11k_dp_rx_h_verify_tkip_mi +@@ -3612,6 +3734,7 @@ static int ath11k_dp_rx_h_verify_tkip_mi hdr = (struct ieee80211_hdr *)(msdu->data + hal_rx_desc_sz); hdr_len = ieee80211_hdrlen(hdr->frame_control); @@ -422,7 +416,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k head_len = hdr_len + hal_rx_desc_sz + IEEE80211_TKIP_IV_LEN; tail_len = IEEE80211_CCMP_MIC_LEN + IEEE80211_TKIP_ICV_LEN + FCS_LEN; -@@ -4013,8 +4136,8 @@ static void ath11k_dp_rx_h_sort_frags(st +@@ -3892,8 +4015,8 @@ static void ath11k_dp_rx_h_sort_frags(st static u64 ath11k_dp_rx_h_get_pn(struct ath11k *ar, struct sk_buff *skb) { @@ -432,7 +426,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k u8 *ehdr; u32 hal_rx_desc_sz = ar->ab->hw_params.hal_desc_sz; -@@ -4237,8 +4360,9 @@ ath11k_dp_process_rx_err_buf(struct ath1 +@@ -4116,8 +4239,9 @@ ath11k_dp_process_rx_err_buf(struct ath1 if ((msdu_len + hal_rx_desc_sz) > DP_RX_BUFFER_SIZE) { hdr_status = ath11k_dp_rx_h_80211_hdr(ar->ab, rx_desc); ath11k_warn(ar->ab, "invalid msdu leng %u", msdu_len); @@ -444,7 +438,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k ath11k_dbg_dump(ar->ab, ATH11K_DBG_DATA, NULL, "", rx_desc, sizeof(struct hal_rx_desc)); dev_kfree_skb_any(msdu); -@@ -4861,6 +4985,47 @@ void ath11k_dp_rx_pdev_free(struct ath11 +@@ -4740,6 +4864,47 @@ void ath11k_dp_rx_pdev_free(struct ath11 ath11k_dp_rxdma_pdev_buf_free(ar); } @@ -492,7 +486,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k int ath11k_dp_rx_pdev_alloc(struct ath11k_base *ab, int mac_id) { struct ath11k *ar = ab->pdevs[mac_id].ar; -@@ -4954,6 +5119,12 @@ config_refill_ring: +@@ -4833,6 +4998,12 @@ config_refill_ring: } } @@ -505,11 +499,9 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k return 0; } -Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k/dp_tx.c -=================================================================== ---- backports-20211207_001-5.4.164-b7ab87182e.orig/drivers/net/wireless/ath/ath11k/dp_tx.c -+++ backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k/dp_tx.c -@@ -1108,6 +1108,8 @@ int ath11k_dp_tx_htt_rx_filter_setup(str +--- a/drivers/net/wireless/ath/ath11k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_tx.c +@@ -1179,6 +1179,8 @@ int ath11k_dp_tx_htt_rx_filter_setup(str !!(params.flags & HAL_SRNG_FLAGS_MSI_SWAP)); cmd->info0 |= FIELD_PREP(HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PS, !!(params.flags & HAL_SRNG_FLAGS_DATA_TLV_SWAP)); @@ -518,7 +510,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k cmd->info1 = FIELD_PREP(HTT_RX_RING_SELECTION_CFG_CMD_INFO1_BUF_SIZE, rx_buf_size); -@@ -1117,6 +1119,26 @@ int ath11k_dp_tx_htt_rx_filter_setup(str +@@ -1188,6 +1190,26 @@ int ath11k_dp_tx_htt_rx_filter_setup(str cmd->pkt_type_en_flags3 = tlv_filter->pkt_filter_flags3; cmd->rx_filter_tlv = tlv_filter->rx_filter; @@ -545,7 +537,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k ret = ath11k_htc_send(&ab->htc, ab->dp.eid, skb); if (ret) goto err_free; -@@ -1195,6 +1217,7 @@ int ath11k_dp_tx_htt_monitor_mode_ring_c +@@ -1266,6 +1288,7 @@ int ath11k_dp_tx_htt_monitor_mode_ring_c } ring_id = dp->rxdma_mon_buf_ring.refill_buf_ring.ring_id; @@ -553,11 +545,9 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k if (!reset) { tlv_filter.rx_filter = HTT_RX_MON_FILTER_TLV_FLAGS_MON_BUF_RING; -Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k/hw.c -=================================================================== ---- backports-20211207_001-5.4.164-b7ab87182e.orig/drivers/net/wireless/ath/ath11k/hw.c -+++ backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k/hw.c -@@ -245,7 +245,11 @@ static u8 ath11k_hw_ipq8074_rx_desc_get_ +--- a/drivers/net/wireless/ath/ath11k/hw.c ++++ b/drivers/net/wireless/ath/ath11k/hw.c +@@ -246,7 +246,11 @@ static u8 ath11k_hw_ipq8074_rx_desc_get_ static u8 *ath11k_hw_ipq8074_rx_desc_get_hdr_status(struct hal_rx_desc *desc) { @@ -569,7 +559,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k } static bool ath11k_hw_ipq8074_rx_desc_encrypt_valid(struct hal_rx_desc *desc) -@@ -374,17 +378,6 @@ static void ath11k_hw_ipq8074_rx_desc_se +@@ -381,17 +385,6 @@ static void ath11k_hw_ipq8074_rx_desc_se desc->u.ipq8074.msdu_start.info1 = __cpu_to_le32(info); } @@ -587,7 +577,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k static struct rx_attention *ath11k_hw_ipq8074_rx_desc_get_attention(struct hal_rx_desc *desc) { -@@ -440,6 +433,123 @@ static u8 *ath11k_hw_ipq8074_rx_desc_get +@@ -447,6 +440,123 @@ static u8 *ath11k_hw_ipq8074_rx_desc_get return &desc->u.ipq8074.msdu_payload[0]; } @@ -711,7 +701,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k static bool ath11k_hw_qcn9074_rx_desc_get_first_msdu(struct hal_rx_desc *desc) { return !!FIELD_GET(RX_MSDU_END_INFO4_FIRST_MSDU, -@@ -460,7 +570,11 @@ static u8 ath11k_hw_qcn9074_rx_desc_get_ +@@ -467,7 +577,11 @@ static u8 ath11k_hw_qcn9074_rx_desc_get_ static u8 *ath11k_hw_qcn9074_rx_desc_get_hdr_status(struct hal_rx_desc *desc) { @@ -723,7 +713,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k } static bool ath11k_hw_qcn9074_rx_desc_encrypt_valid(struct hal_rx_desc *desc) -@@ -631,7 +745,11 @@ static u8 ath11k_hw_wcn6855_rx_desc_get_ +@@ -644,7 +758,11 @@ static u8 ath11k_hw_wcn6855_rx_desc_get_ static u8 *ath11k_hw_wcn6855_rx_desc_get_hdr_status(struct hal_rx_desc *desc) { @@ -735,7 +725,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k } static bool ath11k_hw_wcn6855_rx_desc_encrypt_valid(struct hal_rx_desc *desc) -@@ -935,6 +1053,97 @@ static void ath11k_hw_ipq5018_set_rx_fra +@@ -953,6 +1071,97 @@ static void ath11k_hw_ipq5018_set_rx_fra ath11k_hif_write32(ab, reo_base + HAL_REO1_R0_MISC_CTL, val); } @@ -833,7 +823,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k static u32 ath11k_get_reo_dest_remap_config_default(void) { u32 ring_hash_map; -@@ -1015,6 +1224,13 @@ const struct ath11k_hw_ops ipq8074_ops = +@@ -1034,6 +1243,13 @@ const struct ath11k_hw_ops ipq8074_ops = .set_rx_fragmentation_dst_ring = ath11k_hw_ipq8074_set_rx_fragmentation_dst_ring, .get_reo_dest_remap_config = ath11k_get_reo_dest_remap_config_default, .rx_desc_get_hal_mpdu_len = ath11k_hw_ipq8074_rx_desc_get_hal_mpdu_len, @@ -847,7 +837,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k }; const struct ath11k_hw_ops ipq6018_ops = { -@@ -1056,6 +1272,13 @@ const struct ath11k_hw_ops ipq6018_ops = +@@ -1076,6 +1292,13 @@ const struct ath11k_hw_ops ipq6018_ops = .set_rx_fragmentation_dst_ring = ath11k_hw_ipq8074_set_rx_fragmentation_dst_ring, .get_reo_dest_remap_config = ath11k_get_reo_dest_remap_config_default, .rx_desc_get_hal_mpdu_len = ath11k_hw_ipq8074_rx_desc_get_hal_mpdu_len, @@ -861,7 +851,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k }; const struct ath11k_hw_ops qca6390_ops = { -@@ -1097,6 +1320,13 @@ const struct ath11k_hw_ops qca6390_ops = +@@ -1118,6 +1341,13 @@ const struct ath11k_hw_ops qca6390_ops = .set_rx_fragmentation_dst_ring = ath11k_hw_ipq8074_set_rx_fragmentation_dst_ring, .get_reo_dest_remap_config = ath11k_get_reo_dest_remap_config_default, .rx_desc_get_hal_mpdu_len = ath11k_hw_ipq8074_rx_desc_get_hal_mpdu_len, @@ -875,7 +865,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k }; const struct ath11k_hw_ops qcn9074_ops = { -@@ -1104,6 +1334,8 @@ const struct ath11k_hw_ops qcn9074_ops = +@@ -1125,6 +1355,8 @@ const struct ath11k_hw_ops qcn9074_ops = .wmi_init_config = ath11k_init_wmi_config_ipq8074, .mac_id_to_pdev_id = ath11k_hw_mac_id_to_pdev_id_ipq8074, .mac_id_to_srng_id = ath11k_hw_mac_id_to_srng_id_ipq8074, @@ -884,7 +874,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k .tx_mesh_enable = ath11k_hw_qcn9074_tx_mesh_enable, .rx_desc_get_first_msdu = ath11k_hw_qcn9074_rx_desc_get_first_msdu, .rx_desc_get_last_msdu = ath11k_hw_qcn9074_rx_desc_get_last_msdu, -@@ -1139,6 +1371,13 @@ const struct ath11k_hw_ops qcn9074_ops = +@@ -1161,6 +1393,13 @@ const struct ath11k_hw_ops qcn9074_ops = .get_reo_dest_remap_config = ath11k_get_reo_dest_remap_config_default, .mpdu_info_get_peerid = ath11k_hw_qcn9074_mpdu_info_get_peerid, .rx_desc_get_hal_mpdu_len = ath11k_hw_qcn9074_rx_desc_get_hal_mpdu_len, @@ -898,7 +888,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k }; const struct ath11k_hw_ops wcn6855_ops = { -@@ -1188,8 +1427,8 @@ const struct ath11k_hw_ops ipq5018_ops = +@@ -1250,8 +1489,8 @@ const struct ath11k_hw_ops ipq5018_ops = .wmi_init_config = ath11k_init_wmi_config_ipq8074, .mac_id_to_pdev_id = ath11k_hw_mac_id_to_pdev_id_ipq8074, .mac_id_to_srng_id = ath11k_hw_mac_id_to_srng_id_ipq8074, @@ -909,7 +899,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k .tx_mesh_enable = ath11k_hw_qcn9074_tx_mesh_enable, .rx_desc_get_first_msdu = ath11k_hw_qcn9074_rx_desc_get_first_msdu, .rx_desc_get_last_msdu = ath11k_hw_qcn9074_rx_desc_get_last_msdu, -@@ -1217,6 +1456,13 @@ const struct ath11k_hw_ops ipq5018_ops = +@@ -1280,6 +1519,13 @@ const struct ath11k_hw_ops ipq5018_ops = .rx_desc_set_msdu_len = ath11k_hw_qcn9074_rx_desc_set_msdu_len, .rx_desc_get_attention = ath11k_hw_qcn9074_rx_desc_get_attention, .rx_desc_get_msdu_payload = ath11k_hw_qcn9074_rx_desc_get_msdu_payload, @@ -923,27 +913,9 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k .reo_setup = ath11k_hw_ipq5018_reo_setup, .set_rx_fragmentation_dst_ring = ath11k_hw_ipq5018_set_rx_fragmentation_dst_ring, .get_reo_dest_remap_config = ath11k_get_reo_dest_remap_config_5018, -@@ -1264,10 +1510,14 @@ const struct ath11k_hw_ops qcn6122_ops = - .rx_desc_get_hal_mpdu_len = ath11k_hw_qcn9074_rx_desc_get_hal_mpdu_len, - .get_reo_dest_remap_config = ath11k_get_reo_dest_remap_config_5018, - #ifdef CPTCFG_ATH11K_MEM_PROFILE_512M -+ .rx_desc_get_offset = ath11k_hw_qcn9074_rx_desc_get_offset, - #endif -+ .rx_desc_get_mpdu_frame_ctl = ath11k_hw_qcn9074_rx_desc_get_mpdu_frame_ctl, -+ .rx_desc_dot11_hdr_fields_valid = ath11k_hw_qcn9074_rx_desc_dot11_hdr_fields_valid, -+ .rx_desc_get_dot11_hdr = ath11k_hw_qcn9074_rx_desc_get_dot11_hdr, -+ .rx_desc_get_crypto_header = ath11k_hw_qcn9074_rx_desc_get_crypto_hdr, - }; - -- - #define ATH11K_TX_RING_MASK_0 0x1 - #define ATH11K_TX_RING_MASK_1 0x2 - #define ATH11K_TX_RING_MASK_2 0x4 -Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k/hw.h -=================================================================== ---- backports-20211207_001-5.4.164-b7ab87182e.orig/drivers/net/wireless/ath/ath11k/hw.h -+++ backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k/hw.h -@@ -21,6 +21,11 @@ +--- a/drivers/net/wireless/ath/ath11k/hw.h ++++ b/drivers/net/wireless/ath/ath11k/hw.h +@@ -22,6 +22,11 @@ #define ATH11K_DP_RXDMA_MON_STATUS_RING_SIZE 512 #define ATH11K_DP_RXDMA_MONITOR_BUF_RING_SIZE 128 #define ATH11K_DP_RXDMA_MONITOR_DST_RING_SIZE 128 @@ -954,8 +926,8 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k +#define ATH11K_DP_RXDMA_NSS_REFILL_RING_SIZE 1816 #else /* Num VDEVS per radio */ - #define TARGET_NUM_VDEVS (ab->num_vdevs_peers[ab->qmi.target_mem_mode].num_vdevs) -@@ -32,6 +37,8 @@ + #define TARGET_NUM_VDEVS(ab) (ab->hw_params.num_vdevs) +@@ -34,6 +39,8 @@ #define ATH11K_DP_RXDMA_MON_STATUS_RING_SIZE 1024 #define ATH11K_DP_RXDMA_MONITOR_BUF_RING_SIZE 4096 #define ATH11K_DP_RXDMA_MONITOR_DST_RING_SIZE 2048 @@ -973,7 +945,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k struct ath11k_hw_ring_mask { u8 tx[ATH11K_EXT_IRQ_GRP_NUM_MAX]; -@@ -250,6 +259,16 @@ struct ath11k_hw_ops { +@@ -267,6 +276,16 @@ struct ath11k_hw_ops { void (*set_rx_fragmentation_dst_ring)(struct ath11k_base *ab); u32 (*get_reo_dest_remap_config)(void); u32 (*rx_desc_get_hal_mpdu_len) (u8 *tlv_data); @@ -990,11 +962,9 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k }; extern const struct ath11k_hw_ops ipq8074_ops; -Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k/mac.c -=================================================================== ---- backports-20211207_001-5.4.164-b7ab87182e.orig/drivers/net/wireless/ath/ath11k/mac.c -+++ backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k/mac.c -@@ -5969,6 +5969,7 @@ static int ath11k_mac_config_mon_status_ +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -6164,6 +6164,7 @@ static int ath11k_mac_config_mon_status_ tlv_filter.rx_filter = ath11k_debugfs_rx_filter(ar); } @@ -1002,10 +972,8 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) { ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id; ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, -Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k/rx_desc.h -=================================================================== ---- backports-20211207_001-5.4.164-b7ab87182e.orig/drivers/net/wireless/ath/ath11k/rx_desc.h -+++ backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k/rx_desc.h +--- a/drivers/net/wireless/ath/ath11k/rx_desc.h ++++ b/drivers/net/wireless/ath/ath11k/rx_desc.h @@ -1442,9 +1442,11 @@ struct hal_rx_desc_ipq8074 { __le32 mpdu_end_tag; struct rx_mpdu_end mpdu_end; @@ -1015,7 +983,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k __le32 phy_ppdu_id; u8 hdr_status[HAL_RX_DESC_HDR_STATUS_LEN]; +#endif - u8 msdu_payload[0]; + u8 msdu_payload[]; } __packed; @@ -1461,9 +1463,11 @@ struct hal_rx_desc_qcn9074 { @@ -1027,7 +995,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k __le32 phy_ppdu_id; u8 hdr_status[HAL_RX_DESC_HDR_STATUS_LEN]; +#endif - u8 msdu_payload[0]; + u8 msdu_payload[]; } __packed; @@ -1480,9 +1484,11 @@ struct hal_rx_desc_wcn6855 { @@ -1039,7 +1007,7 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k __le32 phy_ppdu_id; u8 hdr_status[HAL_RX_DESC_HDR_STATUS_LEN]; +#endif - u8 msdu_payload[0]; + u8 msdu_payload[]; } __packed; @@ -1507,4 +1513,17 @@ struct hal_rx_desc { @@ -1060,11 +1028,9 @@ Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k + + #endif /* ATH11K_RX_DESC_H */ -Index: backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k/nss.c -=================================================================== ---- backports-20211207_001-5.4.164-b7ab87182e.orig/drivers/net/wireless/ath/ath11k/nss.c -+++ backports-20211207_001-5.4.164-b7ab87182e/drivers/net/wireless/ath/ath11k/nss.c -@@ -2261,7 +2261,7 @@ static int ath11k_nss_init(struct ath11k +--- a/drivers/net/wireless/ath/ath11k/nss.c ++++ b/drivers/net/wireless/ath/ath11k/nss.c +@@ -2258,7 +2258,7 @@ static int ath11k_nss_init(struct ath11k /* fill rx parameters to initialize rx context */ wim->wrip.tlv_size = ab->hw_params.hal_desc_sz; diff --git a/feeds/ipq95xx/mac80211/patches/qca/233-ath11k-QDSS-support-for-qcn6122.patch b/feeds/ipq95xx/mac80211/patches/qca/233-ath11k-QDSS-support-for-qcn6122.patch index acbed6ea8..b23566af1 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/233-ath11k-QDSS-support-for-qcn6122.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/233-ath11k-QDSS-support-for-qcn6122.patch @@ -19,70 +19,70 @@ Signed-off-by: Ramya Gnanasekar --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -129,6 +129,7 @@ static const struct ath11k_hw_params ath - .wakeup_mhi = false, +@@ -126,6 +126,7 @@ static const struct ath11k_hw_params ath + .alloc_cacheable_memory = true, .ce_fwlog_enable = false, .fwmem_mode_change = false, + .is_qdss_support = false, .supports_rssi_stats = false, .fw_wmi_diag_event = false, .current_cc_support = false, -@@ -200,6 +201,7 @@ static const struct ath11k_hw_params ath - .wakeup_mhi = false, +@@ -203,6 +204,7 @@ static const struct ath11k_hw_params ath + .alloc_cacheable_memory = true, .ce_fwlog_enable = false, .fwmem_mode_change = false, + .is_qdss_support = false, .supports_rssi_stats = false, .fw_wmi_diag_event = false, .current_cc_support = false, -@@ -268,6 +270,7 @@ static const struct ath11k_hw_params ath - .wakeup_mhi = true, +@@ -277,6 +279,7 @@ static const struct ath11k_hw_params ath + .alloc_cacheable_memory = false, .ce_fwlog_enable = false, .fwmem_mode_change = false, + .is_qdss_support = false, .supports_rssi_stats = true, .fw_wmi_diag_event = true, .current_cc_support = true, -@@ -337,6 +340,7 @@ static const struct ath11k_hw_params ath - .wakeup_mhi = false, +@@ -352,6 +355,7 @@ static const struct ath11k_hw_params ath + .alloc_cacheable_memory = true, .ce_fwlog_enable = true, .fwmem_mode_change = true, + .is_qdss_support = true, .supports_rssi_stats = false, .fw_wmi_diag_event = false, .current_cc_support = false, -@@ -405,6 +409,7 @@ static const struct ath11k_hw_params ath - .wakeup_mhi = true, +@@ -426,6 +430,7 @@ static const struct ath11k_hw_params ath + .alloc_cacheable_memory = false, .ce_fwlog_enable = false, .fwmem_mode_change = false, + .is_qdss_support = false, .supports_rssi_stats = true, .fw_wmi_diag_event = true, .current_cc_support = true, -@@ -472,6 +477,7 @@ static const struct ath11k_hw_params ath - .wakeup_mhi = true, +@@ -499,6 +504,7 @@ static const struct ath11k_hw_params ath + .alloc_cacheable_memory = false, .ce_fwlog_enable = false, .fwmem_mode_change = false, + .is_qdss_support = false, .supports_rssi_stats = true, .fw_wmi_diag_event = true, .current_cc_support = true, -@@ -532,6 +538,7 @@ static const struct ath11k_hw_params ath - .reo_dest_ring_map_shift = HAL_IPQ5018_REO_DEST_RING_CTRL_HASH_RING_SHIFT, - .ce_fwlog_enable = true, - .fwmem_mode_change = false, +@@ -651,6 +657,7 @@ static const struct ath11k_hw_params ath + .hybrid_bus_type = false, + .fixed_fw_mem = false, + .support_off_channel_tx = false, + .is_qdss_support = false, }, { .hw_rev = ATH11K_HW_QCN6122, -@@ -584,6 +591,7 @@ static const struct ath11k_hw_params ath - .cold_boot_calib = true, +@@ -713,6 +720,7 @@ static const struct ath11k_hw_params ath + .fw_mem_mode = ATH11K_QMI_TARGET_MEM_MODE_512M, .ce_fwlog_enable = false, - .fwmem_mode_change = false, -+ .is_qdss_support = false, - }, - }; - + .fwmem_mode_change = false, ++ .is_qdss_support = false, + .supports_sta_ps = false, + .dbr_debug_support = true, + .bios_sar_capa = NULL, --- a/drivers/net/wireless/ath/ath11k/coredump.c +++ b/drivers/net/wireless/ath/ath11k/coredump.c @@ -4,6 +4,7 @@ @@ -166,20 +166,9 @@ Signed-off-by: Ramya Gnanasekar out: ATH11K_MEMORY_STATS_DEC(ab, malloc_size, event_data->total_size); ATH11K_MEMORY_STATS_DEC(ab, malloc_size, len); ---- a/drivers/net/wireless/ath/ath11k/debugfs.c -+++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -1135,7 +1135,7 @@ ath11k_write_trace_qdss(struct file *fil - ret = count; - goto exit; - } -- if (!ab->bus_params.fixed_bdf_addr) { -+ if (ab->hw_params.is_qdss_support) { - ret = ath11k_send_qdss_trace_mode_req(ab, - QMI_WLANFW_QDSS_TRACE_OFF_V01); - if (ret < 0) --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h -@@ -225,6 +225,7 @@ struct ath11k_hw_params { +@@ -222,6 +222,7 @@ struct ath11k_hw_params { u8 reo_dest_ring_map_shift; bool ce_fwlog_enable; bool fwmem_mode_change; diff --git a/feeds/ipq95xx/mac80211/patches/qca/233-ath11k-add-ce-latency-stats.patch b/feeds/ipq95xx/mac80211/patches/qca/233-ath11k-add-ce-latency-stats.patch index 1a7c42576..913fb16dd 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/233-ath11k-add-ce-latency-stats.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/233-ath11k-add-ce-latency-stats.patch @@ -29,7 +29,7 @@ Signed-off-by: Thiraviyam Mariyappan --- a/drivers/net/wireless/ath/ath11k/ahb.c +++ b/drivers/net/wireless/ath/ath11k/ahb.c -@@ -455,8 +455,16 @@ static void ath11k_ahb_ce_tasklet(struct +@@ -487,8 +487,16 @@ static void ath11k_ahb_ce_tasklet(struct { struct ath11k_ce_pipe *ce_pipe = from_tasklet(ce_pipe, t, intr_tq); @@ -46,7 +46,7 @@ Signed-off-by: Thiraviyam Mariyappan ath11k_ahb_ce_irq_enable(ce_pipe->ab, ce_pipe->pipe_num); } -@@ -471,6 +479,9 @@ static irqreturn_t ath11k_ahb_ce_interru +@@ -503,6 +511,9 @@ static irqreturn_t ath11k_ahb_ce_interru tasklet_schedule(&ce_pipe->intr_tq); @@ -58,7 +58,7 @@ Signed-off-by: Thiraviyam Mariyappan --- a/drivers/net/wireless/ath/ath11k/ce.c +++ b/drivers/net/wireless/ath/ath11k/ce.c -@@ -1049,6 +1049,8 @@ int ath11k_ce_alloc_pipes(struct ath11k_ +@@ -1055,6 +1055,8 @@ int ath11k_ce_alloc_pipes(struct ath11k_ int ret; const struct ce_attr *attr; @@ -67,7 +67,7 @@ Signed-off-by: Thiraviyam Mariyappan spin_lock_init(&ab->ce.ce_lock); for (i = 0; i < ab->hw_params.ce_count; i++) { -@@ -1097,3 +1099,30 @@ int ath11k_ce_get_attr_flags(struct ath1 +@@ -1103,3 +1105,30 @@ int ath11k_ce_get_attr_flags(struct ath1 return ab->hw_params.host_ce_config[ce_id].flags; } EXPORT_SYMBOL(ath11k_ce_get_attr_flags); @@ -114,7 +114,7 @@ Signed-off-by: Thiraviyam Mariyappan /* @@ -153,6 +159,19 @@ struct ath11k_ce_ring { - struct sk_buff *skb[0]; + struct sk_buff *skb[]; }; +struct ce_tasklet_time { @@ -154,7 +154,7 @@ Signed-off-by: Thiraviyam Mariyappan #endif --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -929,6 +929,7 @@ struct ath11k_base { +@@ -1123,6 +1123,7 @@ struct ath11k_base { bool fw_recovery_support; bool ce_remap; @@ -164,7 +164,7 @@ Signed-off-by: Thiraviyam Mariyappan struct ath11k_num_vdevs_peers *num_vdevs_peers; --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -1581,6 +1581,93 @@ static const struct file_operations fops +@@ -1736,6 +1736,93 @@ static const struct file_operations fops .llseek = default_llseek, }; @@ -258,9 +258,9 @@ Signed-off-by: Thiraviyam Mariyappan int ath11k_debugfs_pdev_create(struct ath11k_base *ab) { if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)) -@@ -1598,6 +1685,8 @@ int ath11k_debugfs_pdev_create(struct at - debugfs_create_file("set_fw_recovery", 0600, ab->debugfs_soc, ab, - &fops_fw_recovery); +@@ -1760,6 +1847,8 @@ int ath11k_debugfs_pdev_create(struct at + debugfs_create_file("memory_stats", 0600, ab->debugfs_soc, ab, + &fops_memory_stats); + debugfs_create_file("ce_latency_stats", 0600, ab->debugfs_soc, ab, + &fops_ce_latency_stats); @@ -269,7 +269,7 @@ Signed-off-by: Thiraviyam Mariyappan } --- a/drivers/net/wireless/ath/ath11k/hal.c +++ b/drivers/net/wireless/ath/ath11k/hal.c -@@ -1289,7 +1289,11 @@ void ath11k_hal_dump_srng_stats(struct a +@@ -1349,7 +1349,11 @@ void ath11k_hal_dump_srng_stats(struct a struct hal_srng *srng; struct ath11k_ext_irq_grp *irq_grp; struct ath11k_ce_pipe *ce_pipe; @@ -282,7 +282,7 @@ Signed-off-by: Thiraviyam Mariyappan ath11k_err(ab, "Last interrupt received for each CE:\n"); for (i = 0; i < ab->hw_params.ce_count; i++) { -@@ -1298,9 +1302,23 @@ void ath11k_hal_dump_srng_stats(struct a +@@ -1358,9 +1362,23 @@ void ath11k_hal_dump_srng_stats(struct a if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) continue; @@ -308,32 +308,3 @@ Signed-off-by: Thiraviyam Mariyappan } ath11k_err(ab, "\nLast interrupt received for each group:\n"); ---- a/drivers/net/wireless/ath/ath11k/pci_cmn.c -+++ b/drivers/net/wireless/ath/ath11k/pci_cmn.c -@@ -644,8 +644,16 @@ static void ath11k_pci_ce_tasklet(struct - struct ath11k_ce_pipe *ce_pipe = from_tasklet(ce_pipe, t, intr_tq); - int irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_pipe->pipe_num; - -+ if (ce_pipe->ab->ce_latency_stats_enable) -+ ce_pipe->tasklet_ts.exec_entry_ts = ktime_get_boottime(); -+ - ath11k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num); - -+ if (ce_pipe->ab->ce_latency_stats_enable) { -+ ce_pipe->tasklet_ts.exec_complete_ts = ktime_get_boottime(); -+ ce_update_tasklet_time_duration_stats(ce_pipe); -+ } -+ - enable_irq(ce_pipe->ab->irq_num[irq_idx]); - } - -@@ -657,6 +665,9 @@ static irqreturn_t ath11k_pci_ce_interru - - tasklet_schedule(&ce_pipe->intr_tq); - -+ if (ce_pipe->ab->ce_latency_stats_enable) -+ ce_pipe->tasklet_ts.sched_entry_ts = ktime_get_boottime(); -+ - return IRQ_HANDLED; - } - diff --git a/feeds/ipq95xx/mac80211/patches/qca/234-001-ath11k-account-tx-rx-packets-flow.patch b/feeds/ipq95xx/mac80211/patches/qca/234-001-ath11k-account-tx-rx-packets-flow.patch index 27a4af96d..2d552fbde 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/234-001-ath11k-account-tx-rx-packets-flow.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/234-001-ath11k-account-tx-rx-packets-flow.patch @@ -79,9 +79,9 @@ Signed-off-by: Maharaja Kennadyrajan --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -421,6 +421,17 @@ struct ath11k_per_ppdu_tx_stats { - u32 retry_bytes; - }; +@@ -526,6 +526,17 @@ struct ath11k_per_ppdu_tx_stats { + + DECLARE_EWMA(avg_rssi, 10, 8) +struct ath11k_driver_tx_pkts_flow { + atomic_t pkts_in; @@ -97,7 +97,7 @@ Signed-off-by: Maharaja Kennadyrajan struct ath11k_sta { struct ath11k_vif *arvif; -@@ -450,6 +461,8 @@ struct ath11k_sta { +@@ -559,6 +570,8 @@ struct ath11k_sta { #ifdef CPTCFG_ATH11K_NSS_SUPPORT struct ath11k_nss_sta_stats *nss_stats; #endif @@ -108,7 +108,7 @@ Signed-off-by: Maharaja Kennadyrajan u32 peer_ps_state; --- a/drivers/net/wireless/ath/ath11k/debugfs.h +++ b/drivers/net/wireless/ath/ath11k/debugfs.h -@@ -72,6 +72,8 @@ enum ath11k_dbg_htt_ext_stats_type { +@@ -102,6 +102,8 @@ struct ath11k_debug_dbr { #define TPC_STATS_TOT_COLUMN 100 #define ATH11K_TPC_STATS_BUF_SIZE (TPC_STATS_TOT_ROW * TPC_STATS_TOT_COLUMN) @@ -119,7 +119,42 @@ Signed-off-by: Maharaja Kennadyrajan ATH11K_DBG_TPC_STATS_SU_WITH_TXBF, --- a/drivers/net/wireless/ath/ath11k/debugfs_sta.c +++ b/drivers/net/wireless/ath/ath11k/debugfs_sta.c -@@ -1087,6 +1087,9 @@ static ssize_t ath11k_dbg_sta_reset_rx_s +@@ -222,9 +222,6 @@ static ssize_t ath11k_dbg_sta_dump_tx_st + char *buf, mu_group_id[MAX_MU_GROUP_LENGTH] = {0}; + u32 index; + +- if (!arsta->tx_stats) +- return -ENOENT; +- + buf = kzalloc(size, GFP_KERNEL); + if (!buf) + return -ENOMEM; +@@ -232,6 +229,12 @@ static ssize_t ath11k_dbg_sta_dump_tx_st + mutex_lock(&ar->conf_mutex); + + spin_lock_bh(&ar->data_lock); ++ ++ if (!arsta->tx_stats) { ++ retval = -ENOENT; ++ goto end; ++ } ++ + for (k = 0; k < ATH11K_STATS_TYPE_MAX; k++) { + for (j = 0; j < ATH11K_COUNTER_TYPE_MAX; j++) { + stats = &arsta->tx_stats->stats[k]; +@@ -365,6 +368,11 @@ static ssize_t ath11k_dbg_sta_dump_tx_st + + mutex_unlock(&ar->conf_mutex); + return retval; ++end: ++ spin_unlock_bh(&ar->data_lock); ++ mutex_unlock(&ar->conf_mutex); ++ kfree(buf); ++ return retval; + } + + static const struct file_operations fops_tx_stats = { +@@ -992,6 +1000,9 @@ static ssize_t ath11k_dbg_sta_reset_rx_s spin_lock_bh(&ar->ab->base_lock); memset(arsta->rx_stats, 0, sizeof(*arsta->rx_stats)); @@ -129,7 +164,7 @@ Signed-off-by: Maharaja Kennadyrajan spin_unlock_bh(&ar->ab->base_lock); ret = count; -@@ -1196,6 +1199,142 @@ static const struct file_operations fops +@@ -1101,6 +1112,153 @@ static const struct file_operations fops .llseek = default_llseek, }; @@ -145,15 +180,18 @@ Signed-off-by: Maharaja Kennadyrajan + const int size = ATH11K_DRV_TX_STATS_SIZE; + char *buf; + -+ if (!arsta->tx_stats) -+ return -ENOENT; -+ + buf = kzalloc(ATH11K_DRV_TX_STATS_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + mutex_lock(&ar->conf_mutex); + spin_lock_bh(&ar->ab->base_lock); ++ ++ if (!arsta->tx_stats) { ++ ret_val = -ENOENT; ++ goto end; ++ } ++ + len += scnprintf(buf + len, size - len, + "Tx packets inflow from mac80211: %u\n", + atomic_read(&arsta->drv_tx_pkts.pkts_in)); @@ -170,6 +208,11 @@ Signed-off-by: Maharaja Kennadyrajan + + mutex_unlock(&ar->conf_mutex); + return ret_val; ++end: ++ spin_unlock_bh(&ar->ab->base_lock); ++ mutex_unlock(&ar->conf_mutex); ++ kfree(buf); ++ return ret_val; +} + +static const struct file_operations fops_driver_tx_pkts_flow = { @@ -188,9 +231,6 @@ Signed-off-by: Maharaja Kennadyrajan + struct ath11k *ar = arsta->arvif->ar; + int ret, reset; + -+ if (!arsta->tx_stats) -+ return -ENOENT; -+ + ret = kstrtoint_from_user(buf, count, 0, &reset); + if (ret) + return ret; @@ -199,6 +239,12 @@ Signed-off-by: Maharaja Kennadyrajan + return -EINVAL; + + spin_lock_bh(&ar->ab->base_lock); ++ ++ if (!arsta->tx_stats) { ++ spin_unlock_bh(&ar->ab->base_lock); ++ return -ENOENT; ++ } ++ + memset(arsta->tx_stats, 0, sizeof(*arsta->tx_stats)); + atomic_set(&arsta->drv_tx_pkts.pkts_in, 0); + atomic_set(&arsta->drv_tx_pkts.pkts_out, 0); @@ -272,7 +318,7 @@ Signed-off-by: Maharaja Kennadyrajan void ath11k_debugfs_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct dentry *dir) { -@@ -1211,14 +1350,21 @@ void ath11k_debugfs_sta_op_add(struct ie +@@ -1116,14 +1274,21 @@ void ath11k_debugfs_sta_op_add(struct ie debugfs_create_file("total_ps_duration", 0440, dir, sta, &fops_total_ps_duration); } @@ -297,7 +343,7 @@ Signed-off-by: Maharaja Kennadyrajan debugfs_create_file("htt_peer_stats", 0400, dir, sta, --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -2564,6 +2564,7 @@ static void ath11k_dp_rx_h_mpdu(struct a +@@ -2573,6 +2573,7 @@ static void ath11k_dp_rx_h_mpdu(struct a struct rx_attention *rx_attention; u32 err_bitmap; @@ -305,7 +351,7 @@ Signed-off-by: Maharaja Kennadyrajan /* PN for multicast packets will be checked in mac80211 */ rxcb = ATH11K_SKB_RXCB(msdu); fill_crypto_hdr = ath11k_dp_rx_h_attn_is_mcbc(ar->ab, rx_desc); -@@ -2754,6 +2755,7 @@ static void ath11k_dp_rx_deliver_msdu(st +@@ -2766,6 +2767,7 @@ static void ath11k_dp_rx_deliver_msdu(st struct ieee80211_rx_status *rx_status; struct ieee80211_radiotap_he *he = NULL; struct ieee80211_sta *pubsta = NULL; @@ -313,7 +359,7 @@ Signed-off-by: Maharaja Kennadyrajan struct ath11k_peer *peer; struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(msdu); u8 decap = DP_RX_DECAP_TYPE_RAW; -@@ -2819,6 +2821,18 @@ static void ath11k_dp_rx_deliver_msdu(st +@@ -2831,6 +2833,18 @@ static void ath11k_dp_rx_deliver_msdu(st rx_status->flag |= RX_FLAG_8023; ieee80211_rx_napi(ar->hw, pubsta, msdu, napi); @@ -332,7 +378,7 @@ Signed-off-by: Maharaja Kennadyrajan } static int ath11k_dp_rx_process_msdu(struct ath11k *ar, -@@ -2965,6 +2979,8 @@ int ath11k_dp_process_rx(struct ath11k_b +@@ -2977,6 +2991,8 @@ int ath11k_dp_process_rx(struct ath11k_b int total_msdu_reaped = 0; struct hal_srng *srng; struct sk_buff *msdu; @@ -341,7 +387,7 @@ Signed-off-by: Maharaja Kennadyrajan bool done = false; int buf_id, mac_id; struct ath11k *ar; -@@ -3035,6 +3051,19 @@ try_again: +@@ -3047,6 +3063,19 @@ try_again: rxcb->tid = FIELD_GET(HAL_REO_DEST_RING_INFO0_RX_QUEUE_NUM, desc->info0); @@ -361,7 +407,7 @@ Signed-off-by: Maharaja Kennadyrajan rxcb->mac_id = mac_id; __skb_queue_tail(&msdu_list[mac_id], msdu); -@@ -4527,7 +4556,10 @@ static int ath11k_dp_rx_h_null_q_desc(st +@@ -4406,7 +4435,10 @@ static int ath11k_dp_rx_h_null_q_desc(st struct rx_attention *rx_attention; u8 l3pad_bytes; struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(msdu); @@ -372,7 +418,7 @@ Signed-off-by: Maharaja Kennadyrajan msdu_len = ath11k_dp_rx_h_msdu_start_msdu_len(ar->ab, desc); -@@ -4579,6 +4611,18 @@ static int ath11k_dp_rx_h_null_q_desc(st +@@ -4458,6 +4490,18 @@ static int ath11k_dp_rx_h_null_q_desc(st * rx with mac80211. Need not worry about cleaning up amsdu_list. */ @@ -393,7 +439,7 @@ Signed-off-by: Maharaja Kennadyrajan --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -5898,6 +5898,7 @@ static void ath11k_mac_op_tx(struct ieee +@@ -6076,6 +6076,7 @@ static void ath11k_mac_op_tx(struct ieee struct ath11k_mgmt_frame_stats *mgmt_stats = &arvif->mgmt_stats; struct ath11k_sta *arsta = NULL; u32 info_flags = info->flags; @@ -401,7 +447,7 @@ Signed-off-by: Maharaja Kennadyrajan bool is_prb_rsp; u16 frm_type = 0; int ret; -@@ -5958,6 +5959,15 @@ static void ath11k_mac_op_tx(struct ieee +@@ -6136,6 +6137,15 @@ static void ath11k_mac_op_tx(struct ieee ieee80211_free_txskb(ar->hw, skb); return; } diff --git a/feeds/ipq95xx/mac80211/patches/qca/234-002-mac80211-account-tx-rx-packets-flow.patch b/feeds/ipq95xx/mac80211/patches/qca/234-002-mac80211-account-tx-rx-packets-flow.patch index d8ea8973e..ac291c100 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/234-002-mac80211-account-tx-rx-packets-flow.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/234-002-mac80211-account-tx-rx-packets-flow.patch @@ -78,7 +78,7 @@ Signed-off-by: Maharaja Kennadyrajan --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c -@@ -1012,6 +1012,176 @@ out: +@@ -1013,6 +1013,176 @@ out: } STA_OPS(he_capa); @@ -255,7 +255,7 @@ Signed-off-by: Maharaja Kennadyrajan #define DEBUGFS_ADD(name) \ debugfs_create_file(#name, 0400, \ sta->debugfs_dir, sta, &sta_ ##name## _ops) -@@ -1050,6 +1220,10 @@ void ieee80211_sta_debugfs_add(struct st +@@ -1051,6 +1221,10 @@ void ieee80211_sta_debugfs_add(struct st DEBUGFS_ADD(ht_capa); DEBUGFS_ADD(vht_capa); DEBUGFS_ADD(he_capa); @@ -264,11 +264,11 @@ Signed-off-by: Maharaja Kennadyrajan + DEBUGFS_ADD(mac80211_tx_pkts_flow); + DEBUGFS_ADD(mac80211_rx_pkts_flow); - DEBUGFS_ADD_COUNTER(rx_duplicates, rx_stats.num_duplicates); - DEBUGFS_ADD_COUNTER(rx_fragments, rx_stats.fragments); + DEBUGFS_ADD_COUNTER(rx_duplicates, deflink.rx_stats.num_duplicates); + DEBUGFS_ADD_COUNTER(rx_fragments, deflink.rx_stats.fragments); --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c -@@ -2641,6 +2641,7 @@ static void ieee80211_deliver_skb_to_loc +@@ -2657,6 +2657,7 @@ static void ieee80211_deliver_skb_to_loc { struct ieee80211_sub_if_data *sdata = rx->sdata; struct net_device *dev = sdata->dev; @@ -276,7 +276,7 @@ Signed-off-by: Maharaja Kennadyrajan if (unlikely((skb->protocol == sdata->control_port_protocol || (skb->protocol == cpu_to_be16(ETH_P_PREAUTH) && -@@ -2687,6 +2688,7 @@ static void ieee80211_deliver_skb_to_loc +@@ -2704,6 +2705,7 @@ static void ieee80211_deliver_skb_to_loc else netif_receive_skb(skb); #endif @@ -284,7 +284,7 @@ Signed-off-by: Maharaja Kennadyrajan } } -@@ -2745,6 +2747,7 @@ ieee80211_deliver_skb(struct ieee80211_r +@@ -2762,6 +2764,7 @@ ieee80211_deliver_skb(struct ieee80211_r */ xmit_skb = skb; skb = NULL; @@ -292,7 +292,7 @@ Signed-off-by: Maharaja Kennadyrajan } } } -@@ -4584,6 +4587,7 @@ static void ieee80211_rx_8023(struct iee +@@ -4674,6 +4677,7 @@ static void ieee80211_rx_8023(struct iee skb_reset_network_header(xmit_skb); skb_reset_mac_header(xmit_skb); dev_queue_xmit(xmit_skb); @@ -300,15 +300,7 @@ Signed-off-by: Maharaja Kennadyrajan } if (!skb) -@@ -4602,6 +4606,7 @@ static void ieee80211_rx_8023(struct iee - else - netif_receive_skb(skb); - -+ atomic_inc(&sta->rx_netif_pkts); - } - - static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx, -@@ -4965,9 +4970,18 @@ void ieee80211_rx_list(struct ieee80211_ +@@ -5117,9 +5121,18 @@ void ieee80211_rx_list(struct ieee80211_ struct ieee80211_supported_band *sband; struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; @@ -329,9 +321,9 @@ Signed-off-by: Maharaja Kennadyrajan --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h -@@ -675,6 +675,13 @@ struct sta_info { - - struct ieee80211_fragment_cache frags; +@@ -708,6 +708,13 @@ struct sta_info { + struct link_sta_info deflink; + struct link_sta_info __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS]; + atomic_t tx_drv_pkts; + atomic_t tx_netif_pkts; @@ -345,7 +337,7 @@ Signed-off-by: Maharaja Kennadyrajan }; --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c -@@ -4202,6 +4202,9 @@ void __ieee80211_subif_start_xmit(struct +@@ -4164,6 +4164,9 @@ void __ieee80211_subif_start_xmit(struct if (IS_ERR(sta)) sta = NULL; @@ -355,7 +347,7 @@ Signed-off-by: Maharaja Kennadyrajan if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { ap_sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap); -@@ -4497,6 +4500,9 @@ static bool ieee80211_tx_8023(struct iee +@@ -4509,6 +4512,9 @@ static bool ieee80211_tx_8023(struct iee drv_tx(local, &control, skb); @@ -365,7 +357,7 @@ Signed-off-by: Maharaja Kennadyrajan return true; } -@@ -4564,6 +4570,9 @@ static void ieee80211_8023_xmit(struct i +@@ -4583,6 +4589,9 @@ static void ieee80211_8023_xmit(struct i ieee80211_tx_8023(sdata, skb, sta, false); diff --git a/feeds/ipq95xx/mac80211/patches/qca/234-ath11k-add-dbring-debug-and-buffer-validation-suppor.patch b/feeds/ipq95xx/mac80211/patches/qca/234-ath11k-add-dbring-debug-and-buffer-validation-suppor.patch deleted file mode 100644 index 42b989510..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/234-ath11k-add-dbring-debug-and-buffer-validation-suppor.patch +++ /dev/null @@ -1,462 +0,0 @@ -From 475f5c31d6c28a5fbb53aa9779af61214613cde9 Mon Sep 17 00:00:00 2001 -From: Venkateswara Naralasetty -Date: Wed, 23 Dec 2020 10:53:49 +0530 -Subject: [PATCH] ath11k: add dbring debug and buffer validation support - -Target copy spectral report through dbring to host for further -processing. This mechanism involves ring and buffer management -in the Host, FW, and uCode, where improper tail pointer update -issues are seen. This dbring debug support help to debug such -issues by tracking head and tail pointer movement along with -the timestamp at which each buffer is received and replenished. - -Currently there is no validation on the spectral report over the -db ring buffers from the hardware. Improper/incomplete DMA by -the target can result in invalid data received by host. -Due to this we may populate incorrect data to user space. - -This buffer validation support fix this issues by filling some -magic value in the buffer during buffer replenish and check for -the magic value in the buffer received by the target. -If host detect magic value in the received buffer it will -drop the buffer. - -Signed-off-by: Venkateswara Naralasetty ---- - drivers/net/wireless/ath/ath11k/core.h | 1 + - drivers/net/wireless/ath/ath11k/dbring.c | 54 ++++++- - drivers/net/wireless/ath/ath11k/dbring.h | 4 +- - drivers/net/wireless/ath/ath11k/debugfs.c | 218 +++++++++++++++++++++++++++++ - drivers/net/wireless/ath/ath11k/debugfs.h | 40 +++++- - drivers/net/wireless/ath/ath11k/spectral.c | 29 ++-- - 6 files changed, 331 insertions(+), 15 deletions(-) - ---- a/drivers/net/wireless/ath/ath11k/core.h -+++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -551,6 +551,7 @@ struct ath11k_debug { - struct list_head wmi_list; - struct completion wmi_ctrl_path_stats_rcvd; - u32 wmi_ctrl_path_stats_tagid; -+ struct ath11k_db_module_debug *module_debug[WMI_DIRECT_BUF_MAX]; - }; - - struct ath11k_per_peer_tx_stats { ---- a/drivers/net/wireless/ath/ath11k/dbring.c -+++ b/drivers/net/wireless/ath/ath11k/dbring.c -@@ -37,7 +37,8 @@ static void ath11k_dbring_fill_magic_val - - static int ath11k_dbring_bufs_replenish(struct ath11k *ar, - struct ath11k_dbring *ring, -- struct ath11k_dbring_element *buff) -+ struct ath11k_dbring_element *buff, -+ enum wmi_direct_buffer_module id) - { - struct ath11k_base *ab = ar->ab; - struct hal_srng *srng; -@@ -84,6 +85,7 @@ static int ath11k_dbring_bufs_replenish( - - ath11k_hal_rx_buf_addr_info_set(desc, paddr, cookie, 0); - -+ ath11k_dbring_add_debug_entry(ar, id, DBR_RING_DEBUG_EVENT_REPLENISH, srng); - ath11k_hal_srng_access_end(ab, srng); - - return 0; -@@ -101,7 +103,8 @@ err: - } - - static int ath11k_dbring_fill_bufs(struct ath11k *ar, -- struct ath11k_dbring *ring) -+ struct ath11k_dbring *ring, -+ enum wmi_direct_buffer_module id) - { - struct ath11k_dbring_element *buff; - struct hal_srng *srng; -@@ -129,7 +132,7 @@ static int ath11k_dbring_fill_bufs(struc - kfree(buff); - break; - } -- ret = ath11k_dbring_bufs_replenish(ar, ring, buff); -+ ret = ath11k_dbring_bufs_replenish(ar, ring, buff, id); - if (ret) { - ath11k_warn(ar->ab, "failed to replenish db ring num_remain %d req_ent %d\n", - num_remain, req_entries); -@@ -195,7 +198,8 @@ int ath11k_dbring_set_cfg(struct ath11k - - int ath11k_dbring_buf_setup(struct ath11k *ar, - struct ath11k_dbring *ring, -- struct ath11k_dbring_cap *db_cap) -+ struct ath11k_dbring_cap *db_cap, -+ enum wmi_direct_buffer_module id) - { - struct ath11k_base *ab = ar->ab; - struct hal_srng *srng; -@@ -211,7 +215,7 @@ int ath11k_dbring_buf_setup(struct ath11 - ring->hp_addr = ath11k_hal_srng_get_hp_addr(ar->ab, srng); - ring->tp_addr = ath11k_hal_srng_get_tp_addr(ar->ab, srng); - -- ret = ath11k_dbring_fill_bufs(ar, ring); -+ ret = ath11k_dbring_fill_bufs(ar, ring, id); - - return ret; - } -@@ -271,7 +275,7 @@ int ath11k_dbring_buffer_release_event(s - struct ath11k_buffer_addr desc; - u8 *vaddr_unalign; - u32 num_entry, num_buff_reaped; -- u8 pdev_idx, rbm; -+ u8 pdev_idx, rbm, module_id; - u32 cookie; - int buf_id; - int size; -@@ -279,6 +283,7 @@ int ath11k_dbring_buffer_release_event(s - int ret = 0; - - pdev_idx = ev->fixed.pdev_id; -+ module_id = ev->fixed.module_id; - - if (pdev_idx >= ab->num_radios) { - ath11k_warn(ab, "Invalid pdev id %d\n", pdev_idx); -@@ -347,6 +352,9 @@ int ath11k_dbring_buffer_release_event(s - dma_unmap_single(ab->dev, buff->paddr, ring->buf_sz, - DMA_FROM_DEVICE); - -+ ath11k_dbring_add_debug_entry(ar, module_id, -+ DBR_RING_DEBUG_EVENT_RX, srng); -+ - if (ring->handler) { - vaddr_unalign = buff->payload; - handler_data.data = PTR_ALIGN(vaddr_unalign, -@@ -358,7 +366,7 @@ int ath11k_dbring_buffer_release_event(s - - buff->paddr = 0; - memset(buff->payload, 0, size); -- ath11k_dbring_bufs_replenish(ar, ring, buff); -+ ath11k_dbring_bufs_replenish(ar, ring, buff, module_id); - } - - spin_unlock_bh(&srng->lock); ---- a/drivers/net/wireless/ath/ath11k/dbring.h -+++ b/drivers/net/wireless/ath/ath11k/dbring.h -@@ -65,7 +65,8 @@ int ath11k_dbring_wmi_cfg_setup(struct a - enum wmi_direct_buffer_module id); - int ath11k_dbring_buf_setup(struct ath11k *ar, - struct ath11k_dbring *ring, -- struct ath11k_dbring_cap *db_cap); -+ struct ath11k_dbring_cap *db_cap, -+ enum wmi_direct_buffer_module id); - int ath11k_dbring_srng_setup(struct ath11k *ar, struct ath11k_dbring *ring, - int ring_num, int num_entries); - int ath11k_dbring_buffer_release_event(struct ath11k_base *ab, ---- a/drivers/net/wireless/ath/ath11k/debugfs.c -+++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -3349,6 +3349,203 @@ static const struct file_operations fops - .llseek = default_llseek, - }; - -+void ath11k_dbring_add_debug_entry(struct ath11k *ar, -+ enum wmi_direct_buffer_module id, -+ enum ath11k_db_ring_dbg_event event, -+ struct hal_srng *srng) -+{ -+ struct ath11k_db_module_debug *db_module_debug; -+ struct ath11k_db_ring_debug *db_ring_debug; -+ struct ath11k_db_ring_debug_entry *entry; -+ -+ if (id > WMI_DIRECT_BUF_MAX || event > DBR_RING_DEBUG_EVENT_MAX) -+ return; -+ -+ db_module_debug = ar->debug.module_debug[id]; -+ if (!db_module_debug) -+ return; -+ -+ db_ring_debug = &db_module_debug->db_ring_debug; -+ -+ if (!db_module_debug->db_ring_debug_enabled) -+ return; -+ -+ if (db_ring_debug->entries) { -+ entry = &db_ring_debug->entries[db_ring_debug->db_ring_debug_idx]; -+ entry->hp = srng->u.src_ring.hp; -+ entry->tp = *srng->u.src_ring.tp_addr; -+ entry->timestamp = jiffies; -+ entry->event = event; -+ -+ db_ring_debug->db_ring_debug_idx++; -+ if (db_ring_debug->db_ring_debug_idx == -+ db_ring_debug->num_ring_debug_entries) -+ db_ring_debug->db_ring_debug_idx = 0; -+ } -+} -+ -+static ssize_t ath11k_dbr_dump_debug_entries(struct file *file, -+ char __user *user_buf, -+ size_t count, loff_t *ppos) -+{ -+ struct ath11k_db_ring_debug *db_ring_debug = file->private_data; -+ static const char * const event_id_to_string[] = {"empty", "Rx", "Replenish"}; -+ int size = 25 * 1024; -+ char *buf; -+ int i, ret; -+ int len = 0; -+ -+ buf = kzalloc(size, GFP_KERNEL); -+ if (!buf) -+ return -ENOMEM; -+ -+ len += scnprintf(buf + len, size - len, "-------------------------------------\n"); -+ len += scnprintf(buf + len, size - len, "| idx | hp | tp | timestamp | event |\n"); -+ len += scnprintf(buf + len, size - len, "-------------------------------------\n"); -+ -+ for (i = 0; i < db_ring_debug->num_ring_debug_entries; i++) { -+ len += scnprintf(buf + len, size - len, -+ "|%4u|%8u|%8u|%11llu|%8s|\n", i, -+ db_ring_debug->entries[i].hp, -+ db_ring_debug->entries[i].tp, -+ db_ring_debug->entries[i].timestamp, -+ event_id_to_string[db_ring_debug->entries[i].event]); -+ } -+ -+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); -+ kfree(buf); -+ -+ return ret; -+} -+ -+static const struct file_operations fops_dump_dbr_debug_entries = { -+ .read = ath11k_dbr_dump_debug_entries, -+ .open = simple_open, -+ .owner = THIS_MODULE, -+ .llseek = default_llseek, -+}; -+ -+static void ath11k_db_module_debugfs_destroy(struct ath11k *ar, int module_id) -+{ -+ struct ath11k_db_module_debug *module_debug; -+ struct ath11k_db_ring_debug *db_ring_debug; -+ -+ module_debug = ar->debug.module_debug[module_id]; -+ db_ring_debug = &module_debug->db_ring_debug; -+ -+ if (!module_debug || !module_debug->module_debugfs) -+ return; -+ -+ debugfs_remove_recursive(module_debug->module_debugfs); -+ module_debug->module_debugfs = NULL; -+ module_debug->db_ring_debug_enabled = false; -+ kfree(db_ring_debug->entries); -+ db_ring_debug->entries = NULL; -+ kfree(module_debug); -+ ar->debug.module_debug[module_id] = NULL; -+} -+ -+static int ath11k_db_module_debugfs_init(struct ath11k *ar, int module_id) -+{ -+ struct ath11k_db_module_debug *module_debug; -+ struct ath11k_db_ring_debug *db_ring_debug; -+ static const char * const module_id_to_str[] = {"spectral", "CFR"}; -+ u32 size; -+ -+ if (!ar->debug.module_debug[module_id]) -+ ar->debug.module_debug[module_id] = kzalloc(sizeof(*module_debug), -+ GFP_KERNEL); -+ -+ module_debug = ar->debug.module_debug[module_id]; -+ db_ring_debug = &module_debug->db_ring_debug; -+ -+ if (module_debug->module_debugfs) -+ return 0; -+ -+ module_debug->module_debugfs = debugfs_create_dir(module_id_to_str[module_id], -+ ar->debug.debugfs_pdev); -+ if (IS_ERR_OR_NULL(module_debug->module_debugfs)) { -+ if (IS_ERR(module_debug->module_debugfs)) -+ return PTR_ERR(module_debug->module_debugfs); -+ return -ENOMEM; -+ } -+ -+ size = ATH11K_DBR_DEUBG_ENTRIES_MAX * -+ sizeof(struct ath11k_db_ring_debug_entry); -+ -+ module_debug->db_ring_debug_enabled = true; -+ db_ring_debug->num_ring_debug_entries = ATH11K_DBR_DEUBG_ENTRIES_MAX; -+ db_ring_debug->db_ring_debug_idx = 0; -+ db_ring_debug->entries = kzalloc(size, GFP_KERNEL); -+ if (!db_ring_debug->entries) -+ return -ENOMEM; -+ -+ debugfs_create_file("dump_db_ring_debug", 0444, module_debug->module_debugfs, -+ db_ring_debug, &fops_dump_dbr_debug_entries); -+ -+ return 0; -+} -+ -+static ssize_t ath11k_write_enable_dbr_debug(struct file *file, -+ const char __user *ubuf, -+ size_t count, loff_t *ppos) -+{ -+ struct ath11k *ar = file->private_data; -+ char buf[32] = {0}; -+ u32 module_id, enable; -+ int ret; -+ static const char usage[] = "usage: echo " -+ "module_id:0-Spectral 1-CFR val:0-disable 1-enable"; -+ -+ mutex_lock(&ar->conf_mutex); -+ -+ if (ar->state != ATH11K_STATE_ON) { -+ ret = -ENETDOWN; -+ goto out; -+ } -+ -+ ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count); -+ if (ret < 0) -+ goto out; -+ -+ buf[ret] = '\0'; -+ ret = sscanf(buf, "%u %u", &module_id, &enable); -+ if (ret != 2) { -+ ath11k_warn(ar->ab, "%s\n", usage); -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ if (module_id > 1 || enable > 1) { -+ ath11k_warn(ar->ab, "%s\n", usage); -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ if (enable) { -+ ret = ath11k_db_module_debugfs_init(ar, module_id); -+ if (ret) { -+ ath11k_warn(ar->ab, "db ring module debgfs init failed: %d\n", -+ ret); -+ goto out; -+ } -+ } else { -+ ath11k_db_module_debugfs_destroy(ar, module_id); -+ } -+ -+ ret = count; -+out: -+ mutex_unlock(&ar->conf_mutex); -+ return ret; -+} -+ -+static const struct file_operations fops_dbr_debug = { -+ .write = ath11k_write_enable_dbr_debug, -+ .open = simple_open, -+ .owner = THIS_MODULE, -+ .llseek = default_llseek, -+}; -+ - int ath11k_debugfs_register(struct ath11k *ar) - { - struct ath11k_base *ab = ar->ab; -@@ -3435,11 +3632,32 @@ int ath11k_debugfs_register(struct ath11 - ar->debug.debugfs_pdev, ar, - &fops_athdiag); - -+ debugfs_create_file("enable_dbr_debug", 0200, ar->debug.debugfs_pdev, -+ ar, &fops_dbr_debug); -+ - return 0; - } - - void ath11k_debugfs_unregister(struct ath11k *ar) - { -+ struct ath11k_db_module_debug *module_debug; -+ struct ath11k_db_ring_debug *db_ring_debug; -+ int i; -+ -+ for (i = 0; i < WMI_DIRECT_BUF_MAX; i++) { -+ module_debug = ar->debug.module_debug[i]; -+ if (!module_debug) -+ continue; -+ -+ db_ring_debug = &module_debug->db_ring_debug; -+ module_debug->db_ring_debug_enabled = false; -+ kfree(db_ring_debug->entries); -+ db_ring_debug->entries = NULL; -+ debugfs_remove_recursive(module_debug->module_debugfs); -+ kfree(module_debug); -+ ar->debug.module_debug[i] = NULL; -+ } -+ - ath11k_deinit_pktlog(ar); - debugfs_remove_recursive(ar->debug.debugfs_pdev); - ar->debug.debugfs_pdev = NULL; ---- a/drivers/net/wireless/ath/ath11k/debugfs.h -+++ b/drivers/net/wireless/ath/ath11k/debugfs.h -@@ -92,6 +92,34 @@ enum ath11k_debug_tpc_stats_ctl_mode { - ATH11K_TPC_STATS_CTL_MODE_BW_160, - }; - -+#define ATH11K_DBR_DEUBG_ENTRIES_MAX 512 -+ -+enum ath11k_db_ring_dbg_event { -+ DBR_RING_DEBUG_EVENT_INVALID, -+ DBR_RING_DEBUG_EVENT_RX, -+ DBR_RING_DEBUG_EVENT_REPLENISH, -+ DBR_RING_DEBUG_EVENT_MAX, -+}; -+ -+struct ath11k_db_ring_debug_entry { -+ u32 hp; -+ u32 tp; -+ u64 timestamp; -+ enum ath11k_db_ring_dbg_event event; -+}; -+ -+struct ath11k_db_ring_debug { -+ struct ath11k_db_ring_debug_entry *entries; -+ u32 db_ring_debug_idx; -+ u32 num_ring_debug_entries; -+}; -+ -+struct ath11k_db_module_debug { -+ struct ath11k_db_ring_debug db_ring_debug; -+ struct dentry *module_debugfs; -+ bool db_ring_debug_enabled; -+}; -+ - struct debug_htt_stats_req { - bool done; - u8 pdev_id; -@@ -197,6 +225,10 @@ void ath11k_debugfs_fw_stats_process(str - void ath11k_debugfs_fw_stats_init(struct ath11k *ar); - ssize_t ath11k_debugfs_dump_soc_ring_bp_stats(struct ath11k_base *ab, - char *buf, int size); -+void ath11k_dbring_add_debug_entry(struct ath11k *ar, -+ enum wmi_direct_buffer_module id, -+ enum ath11k_db_ring_dbg_event event, -+ struct hal_srng *srng); - int ath11k_debugfs_get_fw_stats(struct ath11k *ar, u32 pdev_id, - u32 vdev_id, u32 stats_id); - -@@ -328,7 +360,13 @@ static inline int ath11k_debugfs_get_fw_ - { - return 0; - } -- -+static inline void -+ath11k_dbring_add_debug_entry(struct ath11k *ar, -+ enum wmi_direct_buffer_module id, -+ enum ath11k_db_ring_dbg_event event, -+ struct hal_srng *srng) -+{ -+} - #endif /* CPTCFG_MAC80211_DEBUGFS*/ - - #ifdef CPTCFG_ATH11K_PKTLOG ---- a/drivers/net/wireless/ath/ath11k/spectral.c -+++ b/drivers/net/wireless/ath/ath11k/spectral.c -@@ -817,7 +817,7 @@ static int ath11k_spectral_ring_alloc(st - ATH11K_SPECTRAL_EVENT_TIMEOUT_MS, - ath11k_spectral_process_data); - -- ret = ath11k_dbring_buf_setup(ar, &sp->rx_ring, db_cap); -+ ret = ath11k_dbring_buf_setup(ar, &sp->rx_ring, db_cap, WMI_DIRECT_BUF_SPECTRAL); - if (ret) { - ath11k_warn(ar->ab, "failed to setup db ring buffer\n"); - goto srng_cleanup; diff --git a/feeds/ipq95xx/mac80211/patches/qca/235-001-mac80211-add-AP_VLAN-iftype-support-on-NSS-offload-case.patch b/feeds/ipq95xx/mac80211/patches/qca/235-001-mac80211-add-AP_VLAN-iftype-support-on-NSS-offload-case.patch index eb5f35e6f..8f1c0ae50 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/235-001-mac80211-add-AP_VLAN-iftype-support-on-NSS-offload-case.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/235-001-mac80211-add-AP_VLAN-iftype-support-on-NSS-offload-case.patch @@ -21,7 +21,7 @@ Signed-off-by: Sathishkumar Muruganandam --- a/include/net/mac80211.h +++ b/include/net/mac80211.h -@@ -4748,6 +4748,17 @@ void ieee80211_sta_pspoll(struct ieee802 +@@ -4932,6 +4932,17 @@ void ieee80211_sta_pspoll(struct ieee802 */ void ieee80211_sta_uapsd_trigger(struct ieee80211_sta *sta, u8 tid); @@ -41,7 +41,7 @@ Signed-off-by: Sathishkumar Muruganandam * This is enough for the radiotap header. --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -1906,7 +1906,13 @@ static int ieee80211_change_station(stru +@@ -1997,7 +1997,13 @@ static int ieee80211_change_station(stru rcu_assign_pointer(vlansdata->u.vlan.sta, sta); __ieee80211_check_fast_rx_iface(vlansdata); @@ -58,7 +58,7 @@ Signed-off-by: Sathishkumar Muruganandam if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && --- a/net/mac80211/driver-ops.c +++ b/net/mac80211/driver-ops.c -@@ -56,10 +56,9 @@ int drv_add_interface(struct ieee80211_l +@@ -57,10 +57,9 @@ int drv_add_interface(struct ieee80211_l might_sleep(); @@ -73,7 +73,7 @@ Signed-off-by: Sathishkumar Muruganandam trace_drv_add_interface(local, sdata); --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c -@@ -600,6 +600,9 @@ static void ieee80211_do_stop(struct iee +@@ -849,6 +849,9 @@ static void ieee80211_do_stop(struct iee switch (sdata->vif.type) { case NL80211_IFTYPE_AP_VLAN: @@ -83,7 +83,7 @@ Signed-off-by: Sathishkumar Muruganandam break; case NL80211_IFTYPE_MONITOR: if (local->monitors == 0) -@@ -888,6 +891,7 @@ static bool ieee80211_iftype_supports_hd +@@ -1140,6 +1143,7 @@ static bool ieee80211_iftype_supports_hd switch (iftype) { /* P2P GO and client are mapped to AP/STATION types */ case NL80211_IFTYPE_AP: @@ -91,7 +91,7 @@ Signed-off-by: Sathishkumar Muruganandam case NL80211_IFTYPE_STATION: return true; default: -@@ -942,7 +946,8 @@ static void ieee80211_set_vif_encap_ops( +@@ -1194,7 +1198,8 @@ static void ieee80211_set_vif_encap_ops( struct ieee80211_sub_if_data *bss = sdata; bool enabled; @@ -101,13 +101,13 @@ Signed-off-by: Sathishkumar Muruganandam if (!sdata->bss) return; -@@ -1269,10 +1274,17 @@ int ieee80211_do_open(struct wireless_de +@@ -1536,10 +1541,17 @@ int ieee80211_do_open(struct wireless_de switch (sdata->vif.type) { case NL80211_IFTYPE_AP_VLAN: - /* no need to tell driver, but set carrier and chanctx */ - if (rtnl_dereference(sdata->bss->beacon)) { - ieee80211_vif_vlan_copy_chanctx(sdata); + if (sdata->bss->active) { + ieee80211_link_vlan_copy_chanctx(&sdata->deflink); netif_carrier_on(dev); + + if (ieee80211_hw_check(&local->hw, SUPPORTS_NSS_OFFLOAD)) { @@ -122,7 +122,7 @@ Signed-off-by: Sathishkumar Muruganandam netif_carrier_off(dev); --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c -@@ -1691,6 +1691,12 @@ void ieee80211_sta_uapsd_trigger(struct +@@ -1671,6 +1671,12 @@ void ieee80211_sta_uapsd_trigger(struct } EXPORT_SYMBOL(ieee80211_sta_uapsd_trigger); @@ -137,7 +137,7 @@ Signed-off-by: Sathishkumar Muruganandam { --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c -@@ -4206,8 +4206,13 @@ void __ieee80211_subif_start_xmit(struct +@@ -4168,8 +4168,13 @@ void __ieee80211_subif_start_xmit(struct atomic_inc(&sta->tx_netif_pkts); if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { @@ -153,8 +153,8 @@ Signed-off-by: Sathishkumar Muruganandam if (ap_sdata->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED && !is_multicast_ether_addr(skb->data)) { if (sta) -@@ -4558,7 +4563,8 @@ static void ieee80211_8023_xmit(struct i - sta->tx_stats.packets[skb_get_queue_mapping(skb)]++; +@@ -4577,7 +4582,8 @@ static void ieee80211_8023_xmit(struct i + sta->deflink.tx_stats.packets[skb_get_queue_mapping(skb)]++; } - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) @@ -165,7 +165,7 @@ Signed-off-by: Sathishkumar Muruganandam --- a/net/mac80211/util.c +++ b/net/mac80211/util.c -@@ -2231,6 +2231,9 @@ static void ieee80211_assign_chanctx(str +@@ -2283,6 +2283,9 @@ static void ieee80211_assign_chanctx(str if (!local->use_chanctx) return; @@ -173,9 +173,9 @@ Signed-off-by: Sathishkumar Muruganandam + return; + mutex_lock(&local->chanctx_mtx); - conf = rcu_dereference_protected(sdata->vif.chanctx_conf, + conf = rcu_dereference_protected(link->conf->chanctx_conf, lockdep_is_held(&local->chanctx_mtx)); -@@ -2406,7 +2409,8 @@ int ieee80211_reconfig(struct ieee80211_ +@@ -2459,7 +2462,8 @@ int ieee80211_reconfig(struct ieee80211_ } list_for_each_entry(sdata, &local->interfaces, list) { @@ -185,7 +185,7 @@ Signed-off-by: Sathishkumar Muruganandam sdata->vif.type != NL80211_IFTYPE_MONITOR && ieee80211_sdata_running(sdata)) { res = drv_add_interface(local, sdata); -@@ -2421,7 +2425,8 @@ int ieee80211_reconfig(struct ieee80211_ +@@ -2474,7 +2478,8 @@ int ieee80211_reconfig(struct ieee80211_ if (res) { list_for_each_entry_continue_reverse(sdata, &local->interfaces, list) @@ -197,7 +197,7 @@ Signed-off-by: Sathishkumar Muruganandam drv_remove_interface(local, sdata); --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c -@@ -3653,7 +3653,8 @@ static bool ieee80211_assoc_success(stru +@@ -4896,7 +4896,8 @@ static bool ieee80211_assoc_success(stru * If we're using 4-addr mode, let the AP know that we're * doing so, so that it can create the STA VLAN on its side */ @@ -209,7 +209,7 @@ Signed-off-by: Sathishkumar Muruganandam /* --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h -@@ -1441,7 +1441,9 @@ static inline void drv_sta_set_4addr(str +@@ -1485,7 +1485,9 @@ static inline void drv_sta_set_4addr(str struct ieee80211_sub_if_data *sdata, struct ieee80211_sta *sta, bool enabled) { diff --git a/feeds/ipq95xx/mac80211/patches/qca/235-002-mac80211-Add-support-for-beacon-tx-mode.patch b/feeds/ipq95xx/mac80211/patches/qca/235-002-mac80211-Add-support-for-beacon-tx-mode.patch index 9b00123bd..13877d5b0 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/235-002-mac80211-Add-support-for-beacon-tx-mode.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/235-002-mac80211-Add-support-for-beacon-tx-mode.patch @@ -23,7 +23,7 @@ Signed-off-by: Maharaja Kennadyrajan --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h -@@ -1234,6 +1234,7 @@ struct cfg80211_unsol_bcast_probe_resp { +@@ -1329,6 +1329,7 @@ struct cfg80211_unsol_bcast_probe_resp { * @fils_discovery: FILS discovery transmission parameters * @unsol_bcast_probe_resp: Unsolicited broadcast probe response parameters * @mbssid_config: AP settings for multiple bssid @@ -31,7 +31,7 @@ Signed-off-by: Maharaja Kennadyrajan */ struct cfg80211_ap_settings { struct cfg80211_chan_def chandef; -@@ -1267,6 +1268,7 @@ struct cfg80211_ap_settings { +@@ -1363,6 +1364,7 @@ struct cfg80211_ap_settings { struct cfg80211_fils_discovery fils_discovery; struct cfg80211_unsol_bcast_probe_resp unsol_bcast_probe_resp; struct cfg80211_mbssid_config mbssid_config; @@ -39,7 +39,7 @@ Signed-off-by: Maharaja Kennadyrajan }; /** -@@ -2133,6 +2135,7 @@ struct mesh_config { +@@ -2279,6 +2281,7 @@ struct mesh_config { * to operate on DFS channels. * @control_port_over_nl80211: TRUE if userspace expects to exchange control * port frames over NL80211 instead of the network interface. @@ -47,7 +47,7 @@ Signed-off-by: Maharaja Kennadyrajan * * These parameters are fixed when the mesh is created. */ -@@ -2156,6 +2159,7 @@ struct mesh_setup { +@@ -2302,6 +2305,7 @@ struct mesh_setup { struct cfg80211_bitrate_mask beacon_rate; bool userspace_handles_dfs; bool control_port_over_nl80211; @@ -57,17 +57,17 @@ Signed-off-by: Maharaja Kennadyrajan /** --- a/include/net/mac80211.h +++ b/include/net/mac80211.h -@@ -651,6 +651,7 @@ struct ieee80211_fils_discovery { - * @tx_pwr_env_num: number of @tx_pwr_env. - * @pwr_reduction: power constraint of BSS. +@@ -666,6 +666,7 @@ struct ieee80211_fils_discovery { + * for read access. + * @color_change_color: the bss color that will be used after the change. * @nss_ap_isolate: Used for notifying the NSS host about AP isolate feature + * @beacon_tx_mode: Beacon Tx Mode setting. */ struct ieee80211_bss_conf { const u8 *bssid; -@@ -727,6 +728,7 @@ struct ieee80211_bss_conf { - u8 tx_pwr_env_num; - u8 pwr_reduction; +@@ -742,6 +743,7 @@ struct ieee80211_bss_conf { + u8 color_change_color; + bool nss_ap_isolate; + enum nl80211_beacon_tx_mode beacon_tx_mode; }; @@ -75,27 +75,26 @@ Signed-off-by: Maharaja Kennadyrajan /** --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h -@@ -2667,7 +2667,9 @@ enum nl80211_commands { - * +@@ -2749,6 +2749,9 @@ enum nl80211_commands { + * the incoming frame RX timestamp. * @NL80211_ATTR_HE_MUEDCA_PARAMS: MU-EDCA AC parameters for the - * %NL80211_CMD_UPDATE_HE_MUEDCA_PARAMS command. -- * + * %NL80211_CMD_UPDATE_HE_MUEDCA_PARAMS command. + * @NL80211_ATTR_BEACON_TX_MODE: used to configure the beacon tx mode as -+ * staggered mode = 1 or burst mode = 2 in %NL80211_CMD_START_AP or -+ * %NL80211_CMD_JOIN_MESH from user-space. ++ * staggered mode = 1 or burst mode = 2 in %NL80211_CMD_START_AP or ++ * %NL80211_CMD_JOIN_MESH from user-space. * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use -@@ -3180,6 +3182,8 @@ enum nl80211_attrs { +@@ -3279,6 +3282,8 @@ enum nl80211_attrs { - NL80211_ATTR_AP_SETTINGS_FLAGS, + NL80211_ATTR_HE_MUEDCA_PARAMS, + NL80211_ATTR_BEACON_TX_MODE, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, -@@ -7527,4 +7531,12 @@ enum nl80211_ap_settings_flags { +@@ -7720,4 +7725,12 @@ enum nl80211_ap_settings_flags { NL80211_AP_SETTINGS_SA_QUERY_OFFLOAD_SUPPORT = 1 << 1, }; @@ -110,15 +109,15 @@ Signed-off-by: Maharaja Kennadyrajan #endif /* __LINUX_NL80211_H */ --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -1144,6 +1144,7 @@ static int ieee80211_start_ap(struct wip +@@ -1199,6 +1199,7 @@ static int ieee80211_start_ap(struct wip - prev_beacon_int = sdata->vif.bss_conf.beacon_int; - sdata->vif.bss_conf.beacon_int = params->beacon_interval; -+ sdata->vif.bss_conf.beacon_tx_mode = params->beacon_tx_mode; + prev_beacon_int = link_conf->beacon_int; + link_conf->beacon_int = params->beacon_interval; ++ link_conf->beacon_tx_mode = params->beacon_tx_mode; if (params->he_cap && params->he_oper) { - sdata->vif.bss_conf.he_support = true; -@@ -2222,6 +2223,7 @@ static int copy_mesh_setup(struct ieee80 + link_conf->he_support = true; +@@ -2317,6 +2318,7 @@ static int copy_mesh_setup(struct ieee80 sdata->vif.bss_conf.beacon_int = setup->beacon_interval; sdata->vif.bss_conf.dtim_period = setup->dtim_period; @@ -128,15 +127,15 @@ Signed-off-by: Maharaja Kennadyrajan if (wiphy_ext_feature_isset(sdata->local->hw.wiphy, --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c -@@ -801,6 +801,7 @@ static const struct nla_policy nl80211_p - [NL80211_ATTR_MBSSID_ELEMS] = { .type = NLA_NESTED }, - [NL80211_ATTR_RADAR_BACKGROUND] = { .type = NLA_FLAG }, - [NL80211_ATTR_AP_SETTINGS_FLAGS] = { .type = NLA_U32 }, +@@ -830,6 +830,7 @@ static const struct nla_policy nl80211_p + [NL80211_ATTR_MLD_ADDR] = NLA_POLICY_EXACT_LEN(ETH_ALEN), + [NL80211_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG }, + [NL80211_ATTR_MAX_NUM_AKM_SUITES] = { .type = NLA_REJECT }, + [NL80211_ATTR_BEACON_TX_MODE] = NLA_POLICY_RANGE(NLA_U32, 1, 2), }; /* policy for the key attributes */ -@@ -5545,6 +5546,9 @@ static int nl80211_start_ap(struct sk_bu +@@ -5750,6 +5751,9 @@ static int nl80211_start_ap(struct sk_bu nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]); params->dtim_period = nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]); @@ -146,7 +145,7 @@ Signed-off-by: Maharaja Kennadyrajan err = cfg80211_validate_beacon_int(rdev, dev->ieee80211_ptr->iftype, params->beacon_interval); -@@ -12200,6 +12204,10 @@ static int nl80211_join_mesh(struct sk_b +@@ -12771,6 +12775,10 @@ static int nl80211_join_mesh(struct sk_b return -EINVAL; } diff --git a/feeds/ipq95xx/mac80211/patches/qca/235-003-ath11k-add-AP_VLAN-vif-support-for-WDS-offload-in-NSS-offload.patch b/feeds/ipq95xx/mac80211/patches/qca/235-003-ath11k-add-AP_VLAN-vif-support-for-WDS-offload-in-NSS-offload.patch index f50a54851..6819a0838 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/235-003-ath11k-add-AP_VLAN-vif-support-for-WDS-offload-in-NSS-offload.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/235-003-ath11k-add-AP_VLAN-vif-support-for-WDS-offload-in-NSS-offload.patch @@ -33,9 +33,9 @@ Signed-off-by: Sathishkumar Muruganandam --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -304,9 +304,8 @@ struct ath11k_vif { - struct dentry *amsdu_aggr_size; - struct dentry *wmi_ctrl_stat; +@@ -400,9 +400,8 @@ struct ath11k_vif { + #endif /* CPTCFG_ATH11K_DEBUGFS */ + struct ath11k_mgmt_frame_stats mgmt_stats; -#ifdef CPTCFG_ATH11K_NSS_SUPPORT struct arvif_nss nss; @@ -46,7 +46,7 @@ Signed-off-by: Sathishkumar Muruganandam struct ath11k_vif_iter { --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -4556,6 +4556,11 @@ static void ath11k_sta_rc_update_wk(stru +@@ -4575,6 +4575,11 @@ static void ath11k_sta_rc_update_wk(stru arvif = arsta->arvif; ar = arvif->ar; @@ -58,7 +58,7 @@ Signed-off-by: Sathishkumar Muruganandam if (WARN_ON(ath11k_mac_vif_chan(arvif->vif, &def))) return; -@@ -4694,17 +4699,28 @@ static void ath11k_sta_rc_update_wk(stru +@@ -4713,17 +4718,28 @@ static void ath11k_sta_rc_update_wk(stru static void ath11k_sta_set_4addr_wk(struct work_struct *wk) { struct ath11k *ar; @@ -89,7 +89,7 @@ Signed-off-by: Sathishkumar Muruganandam "setting USE_4ADDR for peer %pM\n", sta->addr); ret = ath11k_wmi_set_peer_param(ar, sta->addr, -@@ -4712,8 +4728,92 @@ static void ath11k_sta_set_4addr_wk(stru +@@ -4731,8 +4747,93 @@ static void ath11k_sta_set_4addr_wk(stru WMI_PEER_USE_4ADDR, 1); if (ret) @@ -155,6 +155,7 @@ Signed-off-by: Sathishkumar Muruganandam + + spin_lock_bh(&ab->base_lock); + wds_peer->nss.ext_vdev_up = true; ++ wds_peer->nss.ext_vif = vif; + spin_unlock_bh(&ab->base_lock); + + /* NAWDS and CFG_WDS_BACKHAUL configs should be done on corresponding @@ -183,7 +184,7 @@ Signed-off-by: Sathishkumar Muruganandam } static int ath11k_mac_inc_num_stations(struct ath11k_vif *arvif, -@@ -5041,9 +5141,32 @@ static void ath11k_mac_op_sta_set_4addr( +@@ -5064,9 +5165,32 @@ static void ath11k_mac_op_sta_set_4addr( struct ieee80211_sta *sta, bool enabled) { struct ath11k *ar = hw->priv; @@ -216,7 +217,7 @@ Signed-off-by: Sathishkumar Muruganandam ieee80211_queue_work(ar->hw, &arsta->set_4addr_wk); arsta->use_4addr_set = true; } -@@ -6452,6 +6575,9 @@ static int ath11k_mac_op_update_vif_offl +@@ -6447,6 +6571,9 @@ static int ath11k_mac_op_update_vif_offl u32 param_id, param_value; int ret; @@ -226,7 +227,7 @@ Signed-off-by: Sathishkumar Muruganandam param_id = WMI_VDEV_PARAM_TX_ENCAP_TYPE; if (ath11k_frame_mode != ATH11K_HW_TXRX_ETHERNET || (vif->type != NL80211_IFTYPE_STATION && -@@ -6634,7 +6760,8 @@ static int ath11k_mac_op_add_interface(s +@@ -6631,7 +6758,8 @@ static int ath11k_mac_op_add_interface(s goto err; } @@ -236,7 +237,7 @@ Signed-off-by: Sathishkumar Muruganandam ath11k_warn(ab, "failed to create vdev %u, reached max vdev limit %d\n", ar->num_created_vdevs, TARGET_NUM_VDEVS(ab)); ret = -EBUSY; -@@ -6647,6 +6774,28 @@ static int ath11k_mac_op_add_interface(s +@@ -6644,6 +6772,28 @@ static int ath11k_mac_op_add_interface(s arvif->vif = vif; INIT_LIST_HEAD(&arvif->list); @@ -265,7 +266,7 @@ Signed-off-by: Sathishkumar Muruganandam INIT_DELAYED_WORK(&arvif->connection_loss_work, ath11k_mac_vif_sta_connection_loss_work); -@@ -6676,6 +6825,7 @@ static int ath11k_mac_op_add_interface(s +@@ -6673,6 +6823,7 @@ static int ath11k_mac_op_add_interface(s fallthrough; case NL80211_IFTYPE_AP: arvif->vdev_type = WMI_VDEV_TYPE_AP; @@ -273,7 +274,7 @@ Signed-off-by: Sathishkumar Muruganandam break; case NL80211_IFTYPE_MONITOR: arvif->vdev_type = WMI_VDEV_TYPE_MONITOR; -@@ -6903,15 +7053,32 @@ static void ath11k_mac_op_remove_interfa +@@ -6897,15 +7048,32 @@ static void ath11k_mac_op_remove_interfa { struct ath11k *ar = hw->priv; struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); @@ -308,7 +309,7 @@ Signed-off-by: Sathishkumar Muruganandam ath11k_dbg(ab, ATH11K_DBG_MAC, "mac remove interface (vdev %d)\n", arvif->vdev_id); -@@ -6923,6 +7090,14 @@ static void ath11k_mac_op_remove_interfa +@@ -6917,6 +7085,14 @@ static void ath11k_mac_op_remove_interfa if (ret) ath11k_warn(ab, "failed to submit AP self-peer removal on vdev %d: %d\n", arvif->vdev_id, ret); @@ -323,7 +324,7 @@ Signed-off-by: Sathishkumar Muruganandam } reinit_completion(&ar->vdev_delete_done); -@@ -7000,6 +7175,7 @@ err_vdev_del: +@@ -6992,6 +7168,7 @@ err_vdev_del: debugfs_remove(arvif->wmi_ctrl_stat); arvif->wmi_ctrl_stat = NULL; @@ -331,7 +332,7 @@ Signed-off-by: Sathishkumar Muruganandam mutex_unlock(&ar->conf_mutex); } -@@ -7059,16 +7235,17 @@ static int ath11k_mac_op_ampdu_action(st +@@ -7051,16 +7228,17 @@ static int ath11k_mac_op_ampdu_action(st struct ieee80211_ampdu_params *params) { struct ath11k *ar = hw->priv; @@ -351,7 +352,7 @@ Signed-off-by: Sathishkumar Muruganandam break; case IEEE80211_AMPDU_TX_START: case IEEE80211_AMPDU_TX_STOP_CONT: -@@ -8599,6 +8776,7 @@ static void ath11k_mac_op_sta_statistics +@@ -8667,6 +8845,7 @@ static void ath11k_mac_op_sta_statistics { struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv; struct ath11k *ar = arsta->arvif->ar; @@ -359,19 +360,19 @@ Signed-off-by: Sathishkumar Muruganandam s8 signal; bool db2dbm = test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT, ar->ab->wmi_ab.svc_map); -@@ -8651,7 +8829,8 @@ static void ath11k_mac_op_sta_statistics - sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL); - } +@@ -8723,7 +8902,8 @@ static void ath11k_mac_op_sta_statistics + ATH11K_DEFAULT_NOISE_FLOOR; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG); - ath11k_nss_update_sta_stats(sinfo, sta, arsta); + if (arvif->ar->ab->nss.enabled) + ath11k_nss_update_sta_stats(arvif, sinfo, sta); } - #define ATH11K_WLAN_PRIO_MAX 0x63 + #if IS_ENABLED(CONFIG_IPV6) --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -4854,6 +4854,8 @@ enum wmi_vdev_subtype { +@@ -4859,6 +4859,8 @@ enum wmi_vdev_subtype { WMI_VDEV_SUBTYPE_MESH_11S, }; @@ -382,7 +383,7 @@ Signed-off-by: Sathishkumar Muruganandam WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD = 1, --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -1157,12 +1157,13 @@ err_mem_free: +@@ -1158,12 +1158,13 @@ err_mem_free: return ret; } @@ -398,7 +399,7 @@ Signed-off-by: Sathishkumar Muruganandam int ret; ret = ath11k_peer_rx_tid_setup(ar, params->sta->addr, vdev_id, -@@ -1174,13 +1175,13 @@ int ath11k_dp_rx_ampdu_start(struct ath1 +@@ -1175,13 +1176,13 @@ int ath11k_dp_rx_ampdu_start(struct ath1 return ret; } @@ -415,7 +416,7 @@ Signed-off-by: Sathishkumar Muruganandam dma_addr_t paddr; bool active; int ret; -@@ -3159,11 +3160,11 @@ ath11k_dp_rx_update_peer_rate_table_stat +@@ -3160,11 +3161,11 @@ ath11k_dp_rx_update_peer_rate_table_stat rx_stats->byte_stats.rx_rate[rate_idx] += ppdu_info->mpdu_len; } @@ -430,7 +431,7 @@ Signed-off-by: Sathishkumar Muruganandam u32 num_msdu; int i; -@@ -5908,7 +5909,7 @@ int ath11k_dp_rx_process_mon_status(stru +@@ -5898,7 +5899,7 @@ int ath11k_dp_rx_process_mon_status(stru if (ppdu_info->reception_type == HAL_RX_RECEPTION_TYPE_SU) { arsta = (struct ath11k_sta *)peer->sta->drv_priv; @@ -512,7 +513,7 @@ Signed-off-by: Sathishkumar Muruganandam list_del(&ast_entry->ase_list); --- a/drivers/net/wireless/ath/ath11k/peer.h +++ b/drivers/net/wireless/ath/ath11k/peer.h -@@ -33,6 +33,7 @@ enum ath11k_ast_entry_type { +@@ -34,6 +34,7 @@ enum ath11k_ast_entry_type { enum ath11k_wds_wmi_action { ATH11K_WDS_WMI_ADD = 1, ATH11K_WDS_WMI_UPDATE, @@ -520,7 +521,7 @@ Signed-off-by: Sathishkumar Muruganandam ATH11K_WDS_WMI_MAX }; -@@ -118,6 +119,8 @@ struct ath11k_peer *ath11k_peer_find_by_ +@@ -127,6 +128,8 @@ int ath11k_peer_rhash_delete(struct ath1 #ifdef CPTCFG_ATH11K_NSS_SUPPORT struct ath11k_ast_entry *ath11k_peer_ast_find_by_addr(struct ath11k_base *ab, u8* addr); @@ -529,7 +530,7 @@ Signed-off-by: Sathishkumar Muruganandam int ath11k_peer_add_ast(struct ath11k *ar, struct ath11k_peer *peer, u8* mac_addr, enum ath11k_ast_entry_type type); int ath11k_peer_update_ast(struct ath11k *ar, struct ath11k_peer *peer, -@@ -137,6 +140,12 @@ static inline struct ath11k_ast_entry *a +@@ -146,6 +149,12 @@ static inline struct ath11k_ast_entry *a { return NULL; } @@ -544,7 +545,31 @@ Signed-off-by: Sathishkumar Muruganandam u8* mac_addr, enum ath11k_ast_entry_type type) --- a/drivers/net/wireless/ath/ath11k/nss.c +++ b/drivers/net/wireless/ath/ath11k/nss.c -@@ -996,6 +996,9 @@ int ath11k_nss_vdev_set_cmd(struct ath11 +@@ -124,7 +124,10 @@ static void ath11k_nss_get_peer_stats(st + + peer->nss.nss_stats->tx_failed += tx_dropped; + +- ATH11K_NSS_TXRX_NETDEV_STATS(tx, peer->vif, tx_bytes, tx_packets); ++ if (peer->nss.ext_vdev_up) ++ ATH11K_NSS_TXRX_NETDEV_STATS(tx, peer->nss.ext_vif, tx_bytes, tx_packets); ++ else ++ ATH11K_NSS_TXRX_NETDEV_STATS(tx, peer->vif, tx_bytes, tx_packets); + + rx_packets = pstats->rx.rx_recvd; + peer->nss.nss_stats->rx_packets += rx_packets; +@@ -134,7 +137,10 @@ static void ath11k_nss_get_peer_stats(st + pstats->rx.err.decrypt_err; + peer->nss.nss_stats->rx_dropped += rx_dropped; + +- ATH11K_NSS_TXRX_NETDEV_STATS(rx, peer->vif, rx_bytes, rx_packets); ++ if (peer->nss.ext_vdev_up) ++ ATH11K_NSS_TXRX_NETDEV_STATS(tx, peer->nss.ext_vif, tx_bytes, tx_packets); ++ else ++ ATH11K_NSS_TXRX_NETDEV_STATS(rx, peer->vif, rx_bytes, rx_packets); + + spin_unlock_bh(&ab->base_lock); + rcu_read_unlock(); +@@ -996,6 +1002,9 @@ int ath11k_nss_vdev_set_cmd(struct ath11 case ATH11K_NSS_WIFI_VDEV_DECAP_TYPE_CMD: cmd = NSS_WIFI_VDEV_DECAP_TYPE_CMD; break; @@ -564,3 +589,11 @@ Signed-off-by: Sathishkumar Muruganandam }; enum ath11k_nss_opmode { +@@ -152,6 +153,7 @@ struct ath11k_nss_peer { + uint32_t *vaddr; + dma_addr_t paddr; + bool ext_vdev_up; ++ struct ieee80211_vif *ext_vif; + struct peer_stats *nss_stats; + struct completion complete; + }; diff --git a/feeds/ipq95xx/mac80211/patches/qca/235-ath11k-add-mod-param-support-to-skip-radio.patch b/feeds/ipq95xx/mac80211/patches/qca/235-ath11k-add-mod-param-support-to-skip-radio.patch index 3ef708c5e..3809621f1 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/235-ath11k-add-mod-param-support-to-skip-radio.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/235-ath11k-add-mod-param-support-to-skip-radio.patch @@ -15,7 +15,7 @@ Signed-off-by: Sowmiya Sree Elavalagan --- a/drivers/net/wireless/ath/ath11k/ahb.c +++ b/drivers/net/wireless/ath/ath11k/ahb.c -@@ -741,6 +741,22 @@ static int ath11k_get_userpd_id(struct d +@@ -1091,6 +1091,23 @@ static int ath11k_get_userpd_id(struct d return userpd_id; } @@ -32,31 +32,33 @@ Signed-off-by: Sowmiya Sree Elavalagan + userpd_id == QCN6122_USERPD_1) + return true; + } -+ return false; ++ ++ return false; +} + static int ath11k_ahb_probe(struct platform_device *pdev) { struct ath11k_base *ab; -@@ -748,7 +764,7 @@ static int ath11k_ahb_probe(struct platf - const struct of_device_id *of_id; - struct resource *mem_res; - void __iomem *mem; -- int userpd_id, ret; -+ int userpd_id, ret = 0; +@@ -1099,7 +1116,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, userpd_id; ++ int ret = 0, userpd_id; u32 hw_mode_id; of_id = of_match_device(ath11k_ahb_of_match, &pdev->dev); -@@ -758,6 +774,8 @@ static int ath11k_ahb_probe(struct platf +@@ -1131,6 +1148,9 @@ static int ath11k_ahb_probe(struct platf } userpd_id = ath11k_get_userpd_id(dev); + if (ath11k_skip_target_probe(userpd_id, of_id)) + goto end; - ++ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); if (ret) { -@@ -869,8 +887,8 @@ err_hal_srng_deinit: + dev_err(&pdev->dev, "failed to set 32-bit consistent dma\n"); +@@ -1236,8 +1256,8 @@ err_fw_deinit: err_core_free: ath11k_core_free(ab); @@ -66,7 +68,7 @@ Signed-off-by: Sowmiya Sree Elavalagan return ret; } -@@ -879,6 +897,9 @@ static int ath11k_ahb_remove(struct plat +@@ -1246,6 +1266,9 @@ static int ath11k_ahb_remove(struct plat struct ath11k_base *ab = platform_get_drvdata(pdev); unsigned long left; @@ -89,7 +91,7 @@ Signed-off-by: Sowmiya Sree Elavalagan struct ath11k_ahb { --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -47,6 +47,12 @@ unsigned int ath11k_ftm_mode; +@@ -57,6 +57,12 @@ unsigned int ath11k_ftm_mode; module_param_named(ftm_mode, ath11k_ftm_mode, uint, 0644); MODULE_PARM_DESC(ftm_mode, "Boots up in factory test mode"); @@ -104,9 +106,9 @@ Signed-off-by: Sowmiya Sree Elavalagan static const struct ath11k_hw_params ath11k_hw_params[] = { --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -28,6 +28,8 @@ - #include "rx_desc.h" - #include "nss.h" +@@ -39,6 +39,8 @@ extern wait_queue_head_t ath11k_ssr_dump + extern bool ath11k_collect_dump; + #endif +extern unsigned int ath11k_skip_radio; + diff --git a/feeds/ipq95xx/mac80211/patches/qca/235-ath11k-add-provison-to-use-segmentted-memory-on-hk10.patch b/feeds/ipq95xx/mac80211/patches/qca/235-ath11k-add-provison-to-use-segmentted-memory-on-hk10.patch index b0e7bf373..8fbb5f836 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/235-ath11k-add-provison-to-use-segmentted-memory-on-hk10.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/235-ath11k-add-provison-to-use-segmentted-memory-on-hk10.patch @@ -17,9 +17,9 @@ Signed-off-by: Anilkumar Kolli --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c -@@ -41,6 +41,11 @@ - #define QCA6390_DEVICE_ID 0x1101 +@@ -28,6 +28,11 @@ #define QCN9074_DEVICE_ID 0x1104 + #define WCN6855_DEVICE_ID 0x1103 +unsigned int ath11k_fw_mem_seg; +EXPORT_SYMBOL(ath11k_fw_mem_seg); @@ -28,24 +28,25 @@ Signed-off-by: Anilkumar Kolli + static const struct pci_device_id ath11k_pci_id_table[] = { { PCI_VDEVICE(QCOM, QCA6390_DEVICE_ID) }, - { PCI_VDEVICE(QCOM, QCN9074_DEVICE_ID) }, -@@ -1352,6 +1357,10 @@ static int ath11k_pci_probe(struct pci_d - !of_property_read_u32(ab->dev->of_node, "base-addr", &addr)) - ab->bus_params.fixed_mem_region = true; + { PCI_VDEVICE(QCOM, WCN6855_DEVICE_ID) }, +@@ -787,6 +792,10 @@ static int ath11k_pci_probe(struct pci_d + if (ath11k_host_ddr_addr || !ret) + ab->hw_params.fixed_mem_region = true; + /* This is HACK to bring up the QCN9074 with segemnted memory */ + if (ath11k_fw_mem_seg) -+ ab->bus_params.fixed_mem_region = false; ++ ab->hw_params.fixed_mem_region = false; + ret = ath11k_pci_claim(ab_pci, pdev); if (ret) { ath11k_err(ab, "failed to claim device: %d\n", ret); --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c -@@ -2726,6 +2726,16 @@ static int ath11k_qmi_alloc_target_mem_c +@@ -2808,6 +2808,16 @@ static int ath11k_qmi_alloc_target_mem_c + for (i = 0; i < ab->qmi.mem_seg_count; i++) { chunk = &ab->qmi.target_mem[i]; - /* ++ /* + * Ignore the memory request from FW if size is more than 2MB + * if host sends failure, FW reqesut for 2MB segments in mode-0 + * and 1MB segments in mode-1 and mode-2 @@ -55,7 +56,6 @@ Signed-off-by: Anilkumar Kolli + return 0; + } + -+ /* - * FW reloads in coldboot/FWrecovery. + /* Firmware reloads in coldboot/firmware recovery. * in such case, no need to allocate memory for FW again. */ diff --git a/feeds/ipq95xx/mac80211/patches/qca/235-ath11k-update-arvif-band-info.patch b/feeds/ipq95xx/mac80211/patches/qca/235-ath11k-update-arvif-band-info.patch index d4a59b022..05495ba47 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/235-ath11k-update-arvif-band-info.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/235-ath11k-update-arvif-band-info.patch @@ -5,7 +5,7 @@ Signed-off-by: Karthikeyan Periyasamy --- --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -2714,6 +2714,7 @@ static void ath11k_dp_rx_h_ppdu(struct a +@@ -2715,6 +2715,7 @@ static void ath11k_dp_rx_h_ppdu(struct a u8 channel_num; u32 center_freq, meta_data; struct ieee80211_channel *channel; @@ -13,7 +13,7 @@ Signed-off-by: Karthikeyan Periyasamy rx_status->freq = 0; rx_status->rate_idx = 0; -@@ -2731,20 +2732,40 @@ static void ath11k_dp_rx_h_ppdu(struct a +@@ -2732,20 +2733,40 @@ static void ath11k_dp_rx_h_ppdu(struct a center_freq <= ATH11K_MAX_6G_FREQ) { rx_status->band = NL80211_BAND_6GHZ; rx_status->freq = center_freq; @@ -55,7 +55,7 @@ Signed-off-by: Karthikeyan Periyasamy rx_desc, sizeof(struct hal_rx_desc)); } -@@ -3585,6 +3606,12 @@ static int ath11k_dp_rx_reap_mon_status_ +@@ -3587,6 +3608,12 @@ static int ath11k_dp_rx_reap_mon_status_ &cookie, &rbm); if (paddr) { buf_id = FIELD_GET(DP_RXDMA_BUF_COOKIE_BUF_ID, cookie); @@ -68,7 +68,7 @@ Signed-off-by: Karthikeyan Periyasamy spin_lock_bh(&rx_ring->idr_lock); skb = idr_find(&rx_ring->bufs_idr, buf_id); -@@ -5743,6 +5770,11 @@ void ath11k_dp_rx_mon_dest_process(struc +@@ -5765,6 +5792,11 @@ void ath11k_dp_rx_mon_dest_process(struc spin_unlock_bh(&pmon->mon_lock); if (rx_bufs_used) { @@ -82,7 +82,7 @@ Signed-off-by: Karthikeyan Periyasamy --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -3911,7 +3911,8 @@ static int ath11k_mac_op_hw_scan(struct +@@ -3926,7 +3926,8 @@ static int ath11k_mac_op_hw_scan(struct ret = ath11k_start_scan(ar, arg); if (ret) { @@ -92,7 +92,7 @@ Signed-off-by: Karthikeyan Periyasamy spin_lock_bh(&ar->data_lock); ar->scan.state = ATH11K_SCAN_IDLE; spin_unlock_bh(&ar->data_lock); -@@ -7295,7 +7296,7 @@ static void ath11k_mac_op_remove_chanctx +@@ -7292,7 +7293,7 @@ static void ath11k_mac_op_remove_chanctx struct ath11k *ar = hw->priv; struct ath11k_base *ab = ar->ab; @@ -103,7 +103,7 @@ Signed-off-by: Karthikeyan Periyasamy --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c -@@ -4994,12 +4994,16 @@ void ieee80211_rx_list(struct ieee80211_ +@@ -5139,12 +5139,16 @@ void ieee80211_rx_list(struct ieee80211_ } } @@ -124,7 +124,7 @@ Signed-off-by: Karthikeyan Periyasamy * If we're suspending, it is possible although not too likely --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c -@@ -647,9 +647,15 @@ static void ieee80211_scan_state_send_pr +@@ -661,9 +661,15 @@ static void ieee80211_scan_state_send_pr int i; struct ieee80211_sub_if_data *sdata; struct cfg80211_scan_request *scan_req; @@ -143,7 +143,7 @@ Signed-off-by: Karthikeyan Periyasamy --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -743,6 +743,7 @@ struct ath11k { +@@ -842,6 +842,7 @@ struct ath11k { u8 ftm_msgref; int ap_ps_enabled; enum ath11k_ap_ps_state ap_ps_state; @@ -153,7 +153,7 @@ Signed-off-by: Karthikeyan Periyasamy u8 ps_timekeeper_enable; --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -3671,6 +3671,7 @@ int ieee80211_attach_ack_skb(struct ieee +@@ -3832,6 +3832,7 @@ int ieee80211_attach_ack_skb(struct ieee if (id < 0) { kfree_skb(ack_skb); @@ -163,7 +163,7 @@ Signed-off-by: Karthikeyan Periyasamy --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c -@@ -2537,6 +2537,7 @@ static u16 ieee80211_store_ack_skb(struc +@@ -2546,6 +2546,7 @@ static u16 ieee80211_store_ack_skb(struc } } else { kfree_skb(ack_skb); @@ -173,7 +173,7 @@ Signed-off-by: Karthikeyan Periyasamy --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -24,7 +24,7 @@ module_param_named(nss_offload, nss_offl +@@ -25,7 +25,7 @@ module_param_named(nss_offload, nss_offl MODULE_PARM_DESC(nss_offload, "Enable NSS Offload support"); #endif @@ -186,9 +186,9 @@ Signed-off-by: Karthikeyan Periyasamy +++ b/drivers/net/wireless/ath/ath11k/debug.h @@ -25,6 +25,7 @@ enum ath11k_debug_mask { ATH11K_DBG_PCI = 0x00001000, - ATH11K_DBG_DP_TX = 0x00001000, - ATH11K_DBG_DP_RX = 0x00002000, -+ ATH11K_DBG_TEST = 0x00080000, + ATH11K_DBG_DP_TX = 0x00002000, + ATH11K_DBG_DP_RX = 0x00004000, ++ ATH11K_DBG_TEST = 0x00080000, ATH11K_DBG_ANY = 0xffffffff, }; diff --git a/feeds/ipq95xx/mac80211/patches/qca/236-001-mac80211-add-dynamic-VLAN-support-on-NSS-offload.patch b/feeds/ipq95xx/mac80211/patches/qca/236-001-mac80211-add-dynamic-VLAN-support-on-NSS-offload.patch index d3636812f..47583dd77 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/236-001-mac80211-add-dynamic-VLAN-support-on-NSS-offload.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/236-001-mac80211-add-dynamic-VLAN-support-on-NSS-offload.patch @@ -24,7 +24,7 @@ Signed-off-by: Sathishkumar Muruganandam --- a/include/net/mac80211.h +++ b/include/net/mac80211.h -@@ -1910,6 +1910,8 @@ enum ieee80211_key_flags { +@@ -2005,6 +2005,8 @@ enum ieee80211_key_flags { * @tx_pn: PN used for TX keys, may be used by the driver as well if it * needs to do software PN assignment by itself (e.g. due to TSO) * @flags: key flags, see &enum ieee80211_key_flags. @@ -33,7 +33,7 @@ Signed-off-by: Sathishkumar Muruganandam * @keyidx: the key index (0-3) * @keylen: key material length * @key: key material. For ALG_TKIP the key is encoded as a 256-bit (32 byte) -@@ -1928,6 +1930,7 @@ struct ieee80211_key_conf { +@@ -2023,6 +2025,7 @@ struct ieee80211_key_conf { u8 hw_key_idx; s8 keyidx; u16 flags; @@ -43,7 +43,7 @@ Signed-off-by: Sathishkumar Muruganandam }; --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -510,6 +510,7 @@ static int ieee80211_add_key(struct wiph +@@ -500,6 +500,7 @@ static int ieee80211_add_key(struct wiph break; case NL80211_IFTYPE_AP: case NL80211_IFTYPE_AP_VLAN: @@ -53,7 +53,7 @@ Signed-off-by: Sathishkumar Muruganandam key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT; --- a/net/mac80211/driver-ops.c +++ b/net/mac80211/driver-ops.c -@@ -113,7 +113,11 @@ int drv_sta_state(struct ieee80211_local +@@ -114,7 +114,11 @@ int drv_sta_state(struct ieee80211_local might_sleep(); @@ -68,7 +68,7 @@ Signed-off-by: Sathishkumar Muruganandam --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h -@@ -261,7 +261,9 @@ static inline int drv_set_key(struct iee +@@ -283,7 +283,9 @@ static inline int drv_set_key(struct iee might_sleep(); @@ -91,7 +91,7 @@ Signed-off-by: Sathishkumar Muruganandam /* * The driver doesn't know anything about VLAN interfaces. * Hence, don't send GTKs for VLAN interfaces to the driver. -@@ -553,6 +554,8 @@ ieee80211_key_alloc(u32 cipher, int idx, +@@ -569,6 +570,8 @@ ieee80211_key_alloc(u32 cipher, int idx, */ key->conf.flags = 0; key->flags = 0; @@ -102,10 +102,10 @@ Signed-off-by: Sathishkumar Muruganandam key->conf.keyidx = idx; --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c -@@ -4248,8 +4248,11 @@ static void ieee80211_8023_xmit(struct i +@@ -4529,8 +4529,11 @@ static void ieee80211_8023_xmit(struct i struct ieee80211_key *key, struct sk_buff *skb) { - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_tx_info *info; + struct ethhdr *ehdr = (struct ethhdr *)skb->data; struct ieee80211_local *local = sdata->local; struct tid_ampdu_tx *tid_tx; @@ -114,7 +114,7 @@ Signed-off-by: Sathishkumar Muruganandam u8 tid; if (local->ops->wake_tx_queue) { -@@ -4258,6 +4261,12 @@ static void ieee80211_8023_xmit(struct i +@@ -4539,6 +4542,12 @@ static void ieee80211_8023_xmit(struct i skb_get_hash(skb); } diff --git a/feeds/ipq95xx/mac80211/patches/qca/236-003-ath11k-add-dynamic-VLAN-support-in-NSS-offload.patch b/feeds/ipq95xx/mac80211/patches/qca/236-003-ath11k-add-dynamic-VLAN-support-in-NSS-offload.patch index 10c4a80a9..5d6a07b15 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/236-003-ath11k-add-dynamic-VLAN-support-in-NSS-offload.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/236-003-ath11k-add-dynamic-VLAN-support-in-NSS-offload.patch @@ -34,21 +34,23 @@ Signed-off-by: Sathishkumar Muruganandam drivers/net/wireless/ath/ath11k/wmi.h | 2 + 4 files changed, 233 insertions(+), 19 deletions(-) ---- a/drivers/net/wireless/ath/ath11k/core.h -+++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -95,6 +95,11 @@ enum ath11k_crypt_mode { +Index: b/drivers/net/wireless/ath/ath11k/core.h +=================================================================== +--- a/drivers/net/wireless/ath/ath11k/core.h 2023-02-14 20:04:55.694489869 +0530 ++++ b/drivers/net/wireless/ath/ath11k/core.h 2023-02-14 20:05:50.254053130 +0530 +@@ -118,6 +118,11 @@ enum ath11k_crypt_mode { ATH11K_CRYPT_MODE_SW, }; +#define ATH11K_GROUP_KEYS_NUM_MAX 128 -+#define ATH11K_FREE_GROUP_IDX_MAP_BITS 32 ++#define ATH11K_FREE_GROUP_IDX_MAP_BITS (BITS_PER_BYTE * (sizeof(long))) +#define ATH11K_FREE_GROUP_IDX_MAP_MAX (ATH11K_GROUP_KEYS_NUM_MAX / \ + ATH11K_FREE_GROUP_IDX_MAP_BITS) + static inline enum wme_ac ath11k_tid_to_ac(u32 tid) { return (((tid == 0) || (tid == 3)) ? WME_AC_BE : -@@ -249,6 +254,20 @@ struct ath11k_mgmt_frame_stats { +@@ -339,6 +344,20 @@ struct ath11k_mgmt_frame_stats { u32 tx_compl_fail[ATH11K_STATS_MGMT_FRM_TYPE_MAX]; }; @@ -69,7 +71,7 @@ Signed-off-by: Sathishkumar Muruganandam struct ath11k_vif { u32 vdev_id; enum wmi_vdev_type vdev_type; -@@ -308,6 +327,11 @@ struct ath11k_vif { +@@ -404,6 +423,11 @@ struct ath11k_vif { struct ath11k_mgmt_frame_stats mgmt_stats; struct arvif_nss nss; struct list_head ap_vlan_arvifs; @@ -81,9 +83,11 @@ Signed-off-by: Sathishkumar Muruganandam }; struct ath11k_vif_iter { ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -340,6 +340,10 @@ enum nl80211_he_gi ath11k_mac_he_gi_to_n +Index: b/drivers/net/wireless/ath/ath11k/mac.c +=================================================================== +--- a/drivers/net/wireless/ath/ath11k/mac.c 2023-02-14 20:04:55.694489869 +0530 ++++ b/drivers/net/wireless/ath/ath11k/mac.c 2023-02-14 20:04:55.690489901 +0530 +@@ -348,6 +348,10 @@ enum nl80211_he_gi ath11k_mac_he_gi_to_n return ret; } @@ -94,7 +98,7 @@ Signed-off-by: Sathishkumar Muruganandam u8 ath11k_mac_bw_to_mac80211_bw(u8 bw) { u8 ret = 0; -@@ -712,6 +716,33 @@ u8 ath11k_mac_get_target_pdev_id(struct +@@ -720,6 +724,33 @@ u8 ath11k_mac_get_target_pdev_id(struct return ar->ab->target_pdev_ids[0].pdev_id; } @@ -128,7 +132,7 @@ Signed-off-by: Sathishkumar Muruganandam static void ath11k_pdev_caps_update(struct ath11k *ar) { struct ath11k_base *ab = ar->ab; -@@ -3971,6 +4002,9 @@ static int ath11k_install_key(struct ath +@@ -3989,6 +4020,9 @@ static int ath11k_install_key(struct ath if (test_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags)) return 0; @@ -138,7 +142,7 @@ Signed-off-by: Sathishkumar Muruganandam if (cmd == DISABLE_KEY) { arg.key_cipher = WMI_CIPHER_NONE; arg.key_data = NULL; -@@ -4060,15 +4094,40 @@ static int ath11k_clear_peer_keys(struct +@@ -4078,15 +4112,40 @@ static int ath11k_clear_peer_keys(struct return first_errno; } @@ -181,7 +185,7 @@ Signed-off-by: Sathishkumar Muruganandam const u8 *peer_addr; int ret = 0; u32 flags = 0; -@@ -4086,17 +4145,38 @@ static int ath11k_mac_op_set_key(struct +@@ -4104,17 +4163,38 @@ static int ath11k_mac_op_set_key(struct if (key->keyidx > WMI_MAX_KEY_INDEX) return -ENOSPC; @@ -224,7 +228,7 @@ Signed-off-by: Sathishkumar Muruganandam /* the peer should not disappear in mid-way (unless FW goes awry) since * we already hold conf_mutex. we just make sure its there now. */ -@@ -4141,6 +4221,74 @@ static int ath11k_mac_op_set_key(struct +@@ -4159,6 +4239,74 @@ static int ath11k_mac_op_set_key(struct goto exit; } @@ -299,7 +303,7 @@ Signed-off-by: Sathishkumar Muruganandam spin_lock_bh(&ab->base_lock); peer = ath11k_peer_find(ab, arvif->vdev_id, peer_addr); -@@ -4163,6 +4311,27 @@ static int ath11k_mac_op_set_key(struct +@@ -4181,6 +4329,27 @@ static int ath11k_mac_op_set_key(struct goto unlock; } @@ -327,7 +331,7 @@ Signed-off-by: Sathishkumar Muruganandam if (peer && cmd == SET_KEY) { peer->keys[key->keyidx] = key; if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { -@@ -4172,18 +4341,23 @@ static int ath11k_mac_op_set_key(struct +@@ -4190,18 +4359,23 @@ static int ath11k_mac_op_set_key(struct peer->mcast_keyidx = key->keyidx; peer->sec_type_grp = ath11k_dp_tx_get_encrypt_type(key->cipher); } @@ -354,7 +358,7 @@ Signed-off-by: Sathishkumar Muruganandam switch (key->cipher) { case WLAN_CIPHER_SUITE_TKIP: -@@ -4974,6 +5148,33 @@ exit: +@@ -4995,6 +5169,33 @@ exit: return ret; } @@ -388,7 +392,7 @@ Signed-off-by: Sathishkumar Muruganandam static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, -@@ -5077,6 +5278,34 @@ static int ath11k_mac_op_sta_state(struc +@@ -5101,6 +5302,34 @@ static int ath11k_mac_op_sta_state(struc if (ret) ath11k_warn(ar->ab, "Unable to authorize peer %pM vdev %d: %d\n", sta->addr, arvif->vdev_id, ret); @@ -423,7 +427,7 @@ Signed-off-by: Sathishkumar Muruganandam } } else if (old_state == IEEE80211_STA_AUTHORIZED && new_state == IEEE80211_STA_ASSOC) { -@@ -6792,6 +7021,7 @@ static int ath11k_mac_op_add_interface(s +@@ -6790,6 +7019,7 @@ static int ath11k_mac_op_add_interface(s vif->addr, ret); goto err; } @@ -431,7 +435,7 @@ Signed-off-by: Sathishkumar Muruganandam mutex_unlock(&ar->conf_mutex); return ret; } -@@ -6816,6 +7046,20 @@ static int ath11k_mac_op_add_interface(s +@@ -6814,6 +7044,20 @@ static int ath11k_mac_op_add_interface(s arvif->vdev_id = bit; arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE; @@ -452,7 +456,7 @@ Signed-off-by: Sathishkumar Muruganandam switch (vif->type) { case NL80211_IFTYPE_UNSPECIFIED: case NL80211_IFTYPE_STATION: -@@ -6851,7 +7095,7 @@ static int ath11k_mac_op_add_interface(s +@@ -6849,7 +7093,7 @@ static int ath11k_mac_op_add_interface(s if (ret) { ath11k_warn(ab, "failed to create WMI vdev %d: %d\n", arvif->vdev_id, ret); @@ -461,32 +465,25 @@ Signed-off-by: Sathishkumar Muruganandam } ar->num_created_vdevs++; ath11k_dbg(ab, ATH11K_DBG_MAC, "vdev %pM created, vdev_id %d\n", -@@ -7011,13 +7255,13 @@ err_peer_del: +@@ -7012,7 +7256,7 @@ err_peer_del: if (fbret) { - ath11k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n", - arvif->vdev_id, vif->addr); + ath11k_warn(ar->ab, "fallback fail to delete peer addr %pM vdev_id %d ret %d\n", + vif->addr, arvif->vdev_id, fbret); - goto err; + goto err_keyid; } - - fbret = ath11k_wait_for_peer_delete_done(ar, arvif->vdev_id, - vif->addr); - if (fbret) -- goto err; -+ goto err_keyid; - - ar->num_peers--; } -@@ -7032,6 +7276,8 @@ err_vdev_del: + +@@ -7026,6 +7270,8 @@ err_vdev_del: list_del(&arvif->list); spin_unlock_bh(&ar->data_lock); +err_keyid: + kfree(arvif->vlan_keyid_map); err: + ath11k_debugfs_remove_interface(arvif); mutex_unlock(&ar->conf_mutex); - -@@ -7143,6 +7389,7 @@ err_vdev_del: +@@ -7138,6 +7384,7 @@ err_vdev_del: list_del(&arvif->list); spin_unlock_bh(&ar->data_lock); @@ -494,9 +491,9 @@ Signed-off-by: Sathishkumar Muruganandam ath11k_peer_cleanup(ar, arvif->vdev_id); idr_for_each(&ar->txmgmt_idr, -@@ -9453,8 +9700,11 @@ static int __ath11k_mac_register(struct - ieee80211_hw_set(ar->hw, SUPPORT_FAST_XMIT); - } +@@ -9867,8 +10114,11 @@ static int __ath11k_mac_register(struct + ab->hw_params.bios_sar_capa) + ar->hw->wiphy->sar_capa = ab->hw_params.bios_sar_capa; - if (ab->nss.enabled) + if (ab->nss.enabled) { @@ -507,9 +504,11 @@ Signed-off-by: Sathishkumar Muruganandam ret = ieee80211_register_hw(ar->hw); if (ret) { ---- a/drivers/net/wireless/ath/ath11k/wmi.c -+++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -2004,6 +2004,7 @@ int ath11k_wmi_vdev_install_key(struct a +Index: b/drivers/net/wireless/ath/ath11k/wmi.c +=================================================================== +--- a/drivers/net/wireless/ath/ath11k/wmi.c 2023-02-14 20:04:55.694489869 +0530 ++++ b/drivers/net/wireless/ath/ath11k/wmi.c 2023-02-14 20:04:55.690489901 +0530 +@@ -2020,6 +2020,7 @@ int ath11k_wmi_vdev_install_key(struct a cmd->key_len = arg->key_len; cmd->key_txmic_len = arg->key_txmic_len; cmd->key_rxmic_len = arg->key_rxmic_len; @@ -517,7 +516,7 @@ Signed-off-by: Sathishkumar Muruganandam if (arg->key_rsc_counter) memcpy(&cmd->key_rsc_counter, &arg->key_rsc_counter, -@@ -4461,6 +4462,7 @@ ath11k_wmi_copy_resource_config(struct w +@@ -4497,6 +4498,7 @@ ath11k_wmi_copy_resource_config(struct w wmi_cfg->sched_params = tg_cfg->sched_params; wmi_cfg->twt_ap_pdev_count = tg_cfg->twt_ap_pdev_count; wmi_cfg->twt_ap_sta_count = tg_cfg->twt_ap_sta_count; @@ -525,7 +524,7 @@ Signed-off-by: Sathishkumar Muruganandam } static int ath11k_init_cmd_send(struct ath11k_pdev_wmi *wmi, -@@ -4677,6 +4679,9 @@ int ath11k_wmi_cmd_init(struct ath11k_ba +@@ -4713,6 +4715,9 @@ int ath11k_wmi_cmd_init(struct ath11k_ba memset(&init_param, 0, sizeof(init_param)); memset(&config, 0, sizeof(config)); @@ -535,9 +534,11 @@ Signed-off-by: Sathishkumar Muruganandam ab->hw_params.hw_ops->wmi_init_config(ab, &config); memcpy(&wmi_sc->wlan_resource_config, &config, sizeof(config)); ---- a/drivers/net/wireless/ath/ath11k/wmi.h -+++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -3728,6 +3728,7 @@ struct wmi_vdev_install_key_arg { +Index: b/drivers/net/wireless/ath/ath11k/wmi.h +=================================================================== +--- a/drivers/net/wireless/ath/ath11k/wmi.h 2023-02-14 20:04:55.694489869 +0530 ++++ b/drivers/net/wireless/ath/ath11k/wmi.h 2023-02-14 20:04:55.690489901 +0530 +@@ -3733,6 +3733,7 @@ struct wmi_vdev_install_key_arg { u32 vdev_id; const u8 *macaddr; u32 key_idx; @@ -545,7 +546,7 @@ Signed-off-by: Sathishkumar Muruganandam u32 key_flags; u32 key_cipher; u32 key_len; -@@ -5934,6 +5935,7 @@ struct target_resource_config { +@@ -5939,6 +5940,7 @@ struct target_resource_config { u32 bpf_instruction_size; u32 max_bssid_rx_filters; u32 use_pdev_id; diff --git a/feeds/ipq95xx/mac80211/patches/qca/236-ath11k-Add-checks-for-vdev-id-in-fwtest-command.patch b/feeds/ipq95xx/mac80211/patches/qca/236-ath11k-Add-checks-for-vdev-id-in-fwtest-command.patch deleted file mode 100644 index 1b224cf7a..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/236-ath11k-Add-checks-for-vdev-id-in-fwtest-command.patch +++ /dev/null @@ -1,37 +0,0 @@ -From d4342be9786373d76303dae06bb7b560d7b8f864 Mon Sep 17 00:00:00 2001 -From: Lavanya Suresh -Date: Thu, 21 Jan 2021 21:27:14 +0530 -Subject: [PATCH] ath11k: Add vdev null checks for fwtest command - -Added null checks for vif ptr of vdev, to avoid sending fwtest -cmd when vdev is not up. - -Signed-off-by: Lavanya Suresh ---- - drivers/net/wireless/ath/ath11k/testmode.c | 37 +++++++++++++++++------------- - 1 file changed, 21 insertions(+), 16 deletions(-) - ---- a/drivers/net/wireless/ath/ath11k/testmode.c -+++ b/drivers/net/wireless/ath/ath11k/testmode.c -@@ -381,9 +381,18 @@ static int ath11k_tm_cmd_wmi(struct ath1 - if (tag == WMI_TAG_PDEV_SET_PARAM_CMD) - *ptr = ar->pdev->pdev_id; - -- if (vif && (tag == WMI_TAG_VDEV_SET_PARAM_CMD || tag == WMI_TAG_UNIT_TEST_CMD)) { -- arvif = (struct ath11k_vif *)vif->drv_priv; -- *ptr = arvif->vdev_id; -+ if (ar->ab->fw_mode != ATH11K_FIRMWARE_MODE_FTM && -+ (tag == WMI_TAG_VDEV_SET_PARAM_CMD || tag == WMI_TAG_UNIT_TEST_CMD)) { -+ if (vif) { -+ arvif = (struct ath11k_vif *)vif->drv_priv; -+ *ptr = arvif->vdev_id; -+ } -+ else { -+ ret = -EINVAL; -+ ath11k_warn(ar->ab, "vdev is not up for given vdev id, so failed to send wmi command (testmode): %d\n", -+ ret); -+ goto out; -+ } - } - - ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE, diff --git a/feeds/ipq95xx/mac80211/patches/qca/236-ath11k-add-debugfs-to-disable-dynamic-bandwidth-oper.patch b/feeds/ipq95xx/mac80211/patches/qca/236-ath11k-add-debugfs-to-disable-dynamic-bandwidth-oper.patch index 9f7fb468c..d55969e18 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/236-ath11k-add-debugfs-to-disable-dynamic-bandwidth-oper.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/236-ath11k-add-debugfs-to-disable-dynamic-bandwidth-oper.patch @@ -14,17 +14,17 @@ Signed-off-by: Pradeep Kumar Chitrapu --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -524,6 +524,7 @@ struct ath11k_debug { +@@ -680,6 +680,7 @@ struct ath11k_debug { + struct list_head wmi_list; struct completion wmi_ctrl_path_stats_rcvd; u32 wmi_ctrl_path_stats_tagid; - struct ath11k_db_module_debug *module_debug[WMI_DIRECT_BUF_MAX]; + bool disable_dynamic_bw; }; struct ath11k_per_peer_tx_stats { --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -3478,6 +3478,68 @@ static const struct file_operations fops +@@ -3419,6 +3419,68 @@ static const struct file_operations fops .llseek = default_llseek, }; @@ -93,7 +93,7 @@ Signed-off-by: Pradeep Kumar Chitrapu int ath11k_debugfs_register(struct ath11k *ar) { struct ath11k_base *ab = ar->ab; -@@ -3527,6 +3589,9 @@ int ath11k_debugfs_register(struct ath11 +@@ -3468,6 +3530,9 @@ int ath11k_debugfs_register(struct ath11 debugfs_create_file("dump_mgmt_stats", 0644, ar->debug.debugfs_pdev, ar, &fops_dump_mgmt_stats); diff --git a/feeds/ipq95xx/mac80211/patches/qca/237-002-ath11k-Add-provision-to-configure-rx-hashmap.patch b/feeds/ipq95xx/mac80211/patches/qca/237-002-ath11k-Add-provision-to-configure-rx-hashmap.patch index 816d717be..728a71e38 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/237-002-ath11k-Add-provision-to-configure-rx-hashmap.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/237-002-ath11k-Add-provision-to-configure-rx-hashmap.patch @@ -25,18 +25,18 @@ Signed-off-by: P Praneesh --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -993,6 +993,8 @@ struct ath11k_base { - struct ath11k_internal_pci ipci; +@@ -1168,6 +1168,8 @@ struct ath11k_base { + struct ath11k_num_vdevs_peers *num_vdevs_peers; bool enable_memory_stats; + u32 rx_hash; + /* must be last */ - u8 drv_priv[0] __aligned(sizeof(void *)); + u8 drv_priv[] __aligned(sizeof(void *)); }; --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -1418,6 +1418,55 @@ static const struct file_operations fops +@@ -1569,6 +1569,55 @@ static const struct file_operations fops .llseek = default_llseek, }; @@ -92,7 +92,7 @@ Signed-off-by: P Praneesh static ssize_t ath11k_debug_write_fw_recovery(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -@@ -1698,6 +1747,9 @@ int ath11k_debugfs_pdev_create(struct at +@@ -1850,6 +1899,9 @@ int ath11k_debugfs_pdev_create(struct at debugfs_create_file("ce_latency_stats", 0600, ab->debugfs_soc, ab, &fops_ce_latency_stats); @@ -115,7 +115,7 @@ Signed-off-by: P Praneesh /* NOTE: reo_dest ring id starts from 1 unlike mac_id which starts from 0 */ --- a/drivers/net/wireless/ath/ath11k/hal.h +++ b/drivers/net/wireless/ath/ath11k/hal.h -@@ -920,6 +920,7 @@ void ath11k_hal_reo_qdesc_setup(void *va +@@ -926,6 +926,7 @@ void ath11k_hal_reo_qdesc_setup(void *va u32 start_seq, enum hal_pn_type type); void ath11k_hal_reo_init_cmd_ring(struct ath11k_base *ab, struct hal_srng *srng); @@ -125,7 +125,7 @@ Signed-off-by: P Praneesh u32 nsbufs, u32 tot_link_desc, --- a/drivers/net/wireless/ath/ath11k/hw.c +++ b/drivers/net/wireless/ath/ath11k/hw.c -@@ -102,6 +102,23 @@ static void ath11k_init_wmi_config_qca63 +@@ -103,6 +103,23 @@ static void ath11k_init_wmi_config_qca63 config->flag1 |= WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64; } @@ -149,7 +149,7 @@ Signed-off-by: P Praneesh static void ath11k_hw_ipq8074_reo_setup(struct ath11k_base *ab) { u32 reo_base = HAL_SEQ_WCSS_UMAC_REO_REG; -@@ -115,7 +132,6 @@ static void ath11k_hw_ipq8074_reo_setup( +@@ -116,7 +133,6 @@ static void ath11k_hw_ipq8074_reo_setup( HAL_HASH_ROUTING_RING_SW2 << 15 | HAL_HASH_ROUTING_RING_SW3 << 18 | HAL_HASH_ROUTING_RING_SW4 << 21; @@ -157,7 +157,7 @@ Signed-off-by: P Praneesh ab->hw_params.hw_ops->set_rx_fragmentation_dst_ring(ab); -@@ -132,18 +148,7 @@ static void ath11k_hw_ipq8074_reo_setup( +@@ -133,18 +149,7 @@ static void ath11k_hw_ipq8074_reo_setup( if (ab->nss.enabled) return; @@ -177,15 +177,15 @@ Signed-off-by: P Praneesh } static void ath11k_init_wmi_config_ipq8074(struct ath11k_base *ab, -@@ -909,7 +914,6 @@ static void ath11k_hw_wcn6855_reo_setup( - HAL_HASH_ROUTING_RING_SW2 << 20 | +@@ -927,7 +932,6 @@ static void ath11k_hw_wcn6855_reo_setup( HAL_HASH_ROUTING_RING_SW3 << 24 | HAL_HASH_ROUTING_RING_SW4 << 28; -- u8 reo_dest_hash_shift = ab->hw_params.reo_dest_ring_map_shift; +- u8 reo_dest_hash_shift = ab->hw_params.reo_dest_ring_map_shift; ab->hw_params.hw_ops->set_rx_fragmentation_dst_ring(ab); -@@ -927,16 +931,12 @@ static void ath11k_hw_wcn6855_reo_setup( + ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_0(ab), +@@ -943,16 +947,12 @@ static void ath11k_hw_wcn6855_reo_setup( if (ab->nss.enabled) return; @@ -203,7 +203,7 @@ Signed-off-by: P Praneesh /* Each hash entry uses three bits to map to a particular ring. */ u32 ring_hash_map = HAL_HASH_ROUTING_RING_SW1 << 0 | -@@ -963,14 +963,7 @@ static void ath11k_hw_ipq5018_reo_setup( +@@ -979,14 +979,7 @@ static void ath11k_hw_ipq5018_reo_setup( if (ab->nss.enabled) return; diff --git a/feeds/ipq95xx/mac80211/patches/qca/237-003-ath11k-allocate-dst-ring-descriptors-from-cacheable-.patch b/feeds/ipq95xx/mac80211/patches/qca/237-003-ath11k-allocate-dst-ring-descriptors-from-cacheable-.patch index b45e26021..b749dba39 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/237-003-ath11k-allocate-dst-ring-descriptors-from-cacheable-.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/237-003-ath11k-allocate-dst-ring-descriptors-from-cacheable-.patch @@ -22,31 +22,9 @@ Signed-off-by: P Praneesh drivers/net/wireless/ath/ath11k/hal.h | 1 + 4 files changed, 66 insertions(+), 8 deletions(-) ---- a/drivers/net/wireless/ath/ath11k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -2998,9 +2998,9 @@ int ath11k_dp_process_rx(struct ath11k_b - - spin_lock_bh(&srng->lock); - -+try_again: - ath11k_hal_srng_access_begin(ab, srng); - --try_again: - while (likely(desc = - (struct hal_reo_dest_ring *)ath11k_hal_srng_dst_get_next_entry(ab, - srng))) { -@@ -3086,7 +3086,7 @@ try_again: - * head pointer so that we can reap complete MPDU in the current - * rx processing. - */ -- if (unlikely(!done && ath11k_hal_srng_dst_num_free(ab, srng, true))) { -+ if (!done && ath11k_hal_srng_dst_num_free(ab, srng, true)) { - ath11k_hal_srng_access_end(ab, srng); - goto try_again; - } --- a/drivers/net/wireless/ath/ath11k/dp_tx.c +++ b/drivers/net/wireless/ath/ath11k/dp_tx.c -@@ -639,6 +639,7 @@ void ath11k_dp_tx_completion_handler(str +@@ -753,6 +753,7 @@ void ath11k_dp_tx_completion_handler(str struct sk_buff *msdu; struct hal_tx_status ts = { 0 }; struct dp_tx_ring *tx_ring = &dp->tx_ring[ring_id]; @@ -54,7 +32,7 @@ Signed-off-by: P Praneesh u32 *desc; u32 msdu_id; u8 mac_id; -@@ -647,9 +648,18 @@ void ath11k_dp_tx_completion_handler(str +@@ -761,9 +762,18 @@ void ath11k_dp_tx_completion_handler(str ath11k_hal_srng_access_begin(ab, status_ring); @@ -76,7 +54,7 @@ Signed-off-by: P Praneesh tx_ring->tx_status_head = --- a/drivers/net/wireless/ath/ath11k/hal.c +++ b/drivers/net/wireless/ath/ath11k/hal.c -@@ -660,7 +660,8 @@ u32 *ath11k_hal_srng_dst_get_next_entry( +@@ -661,7 +661,8 @@ u32 *ath11k_hal_srng_dst_get_next_entry( desc = srng->ring_base_vaddr + srng->u.dst_ring.tp; @@ -86,7 +64,7 @@ Signed-off-by: P Praneesh /* wrap around to start of ring*/ if (srng->u.dst_ring.tp == srng->ring_size) -@@ -673,8 +674,63 @@ u32 *ath11k_hal_srng_dst_get_next_entry( +@@ -674,8 +675,63 @@ u32 *ath11k_hal_srng_dst_get_next_entry( return desc; } @@ -153,7 +131,7 @@ Signed-off-by: P Praneesh --- a/drivers/net/wireless/ath/ath11k/hal.h +++ b/drivers/net/wireless/ath/ath11k/hal.h -@@ -944,8 +944,12 @@ void ath11k_hal_srng_get_params(struct a +@@ -950,8 +950,12 @@ void ath11k_hal_srng_get_params(struct a u32 *ath11k_hal_srng_dst_get_next_entry(struct ath11k_base *ab, struct hal_srng *srng); u32 *ath11k_hal_srng_dst_peek(struct ath11k_base *ab, struct hal_srng *srng); diff --git a/feeds/ipq95xx/mac80211/patches/qca/237-006-ath11k-Allow-fast-rx-by-bypassing-stats-update.patch b/feeds/ipq95xx/mac80211/patches/qca/237-006-ath11k-Allow-fast-rx-by-bypassing-stats-update.patch index be11228b3..30e3d6446 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/237-006-ath11k-Allow-fast-rx-by-bypassing-stats-update.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/237-006-ath11k-Allow-fast-rx-by-bypassing-stats-update.patch @@ -21,11 +21,9 @@ Signed-off-by: P Praneesh drivers/net/wireless/ath/ath11k/peer.h | 1 + 8 files changed, 201 insertions(+), 6 deletions(-) -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/core.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath11k/core.h -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/core.h -@@ -138,6 +138,7 @@ struct ath11k_skb_rxcb { +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -157,6 +157,7 @@ struct ath11k_skb_rxcb { u8 tid; u16 peer_id; u16 seq_no; @@ -33,19 +31,17 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/cor }; enum ath11k_hw_rev { -@@ -1037,6 +1038,7 @@ struct ath11k_base { +@@ -1169,6 +1170,7 @@ struct ath11k_base { bool enable_memory_stats; u32 rx_hash; + bool stats_disable; /* must be last */ - u8 drv_priv[0] __aligned(sizeof(void *)); -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/debugfs.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath11k/debugfs.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -1514,6 +1514,79 @@ static const struct file_operations fops + u8 drv_priv[] __aligned(sizeof(void *)); +--- a/drivers/net/wireless/ath/ath11k/debugfs.c ++++ b/drivers/net/wireless/ath/ath11k/debugfs.c +@@ -1618,6 +1618,79 @@ static const struct file_operations fops .write = ath11k_write_rx_hash, }; @@ -125,7 +121,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/deb static ssize_t ath11k_debug_write_fw_recovery(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -@@ -1832,6 +1905,9 @@ int ath11k_debugfs_soc_create(struct ath +@@ -1931,6 +2004,9 @@ int ath11k_debugfs_soc_create(struct ath return -ENOMEM; } @@ -135,10 +131,8 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/deb return 0; } -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/dp_rx.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath11k/dp_rx.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/dp_rx.c +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c @@ -375,6 +375,12 @@ static int ath11k_dp_purge_mon_ring(stru return -ETIMEDOUT; } @@ -152,7 +146,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/dp_ /* Returns number of Rx buffers replenished */ int ath11k_dp_rxbufs_replenish(struct ath11k_base *ab, int mac_id, struct dp_rxdma_ring *rx_ring, -@@ -2559,10 +2565,60 @@ ath11k_dp_rx_h_find_peer(struct ath11k_b +@@ -2560,10 +2566,60 @@ ath11k_dp_rx_h_find_peer(struct ath11k_b return peer; } @@ -214,7 +208,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/dp_ { bool fill_crypto_hdr; enum hal_encrypt_type enctype; -@@ -2572,7 +2628,8 @@ static void ath11k_dp_rx_h_mpdu(struct a +@@ -2573,7 +2629,8 @@ static void ath11k_dp_rx_h_mpdu(struct a struct ath11k_peer *peer; struct rx_attention *rx_attention; u32 err_bitmap; @@ -224,7 +218,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/dp_ /* PN for multicast packets will be checked in mac80211 */ rxcb = ATH11K_SKB_RXCB(msdu); -@@ -2587,6 +2644,30 @@ static void ath11k_dp_rx_h_mpdu(struct a +@@ -2588,6 +2645,30 @@ static void ath11k_dp_rx_h_mpdu(struct a spin_lock_bh(&ar->ab->base_lock); peer = ath11k_dp_rx_h_find_peer(ar->ab, msdu); if (peer) { @@ -255,7 +249,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/dp_ if (rxcb->is_mcbc) enctype = peer->sec_type_grp; else -@@ -2852,7 +2933,8 @@ static void ath11k_dp_rx_deliver_msdu(st +@@ -2872,7 +2953,8 @@ static void ath11k_dp_rx_deliver_msdu(st static int ath11k_dp_rx_process_msdu(struct ath11k *ar, struct sk_buff *msdu, struct sk_buff_head *msdu_list, @@ -265,7 +259,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/dp_ { struct ath11k_base *ab = ar->ab; struct hal_rx_desc *rx_desc, *lrx_desc; -@@ -2934,8 +3016,13 @@ static int ath11k_dp_rx_process_msdu(str +@@ -2954,8 +3036,13 @@ static int ath11k_dp_rx_process_msdu(str } } @@ -280,7 +274,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/dp_ rx_status->flag |= RX_FLAG_SKIP_MONITOR | RX_FLAG_DUP_VALIDATED; -@@ -2950,10 +3037,12 @@ static void ath11k_dp_rx_process_receive +@@ -2970,10 +3057,12 @@ static void ath11k_dp_rx_process_receive struct sk_buff_head *msdu_list, int mac_id) { @@ -293,7 +287,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/dp_ if (skb_queue_empty(msdu_list)) return; -@@ -2970,7 +3059,12 @@ static void ath11k_dp_rx_process_receive +@@ -2990,7 +3079,12 @@ static void ath11k_dp_rx_process_receive } while ((msdu = __skb_dequeue(msdu_list))) { @@ -307,7 +301,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/dp_ if (unlikely(ret)) { ath11k_dbg(ab, ATH11K_DBG_DATA, "Unable to process msdu %d", ret); -@@ -2978,7 +3072,10 @@ static void ath11k_dp_rx_process_receive +@@ -2998,7 +3092,10 @@ static void ath11k_dp_rx_process_receive continue; } @@ -319,7 +313,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/dp_ } } -@@ -4446,6 +4543,7 @@ static int ath11k_dp_rx_h_null_q_desc(st +@@ -4467,6 +4564,7 @@ static int ath11k_dp_rx_h_null_q_desc(st struct ath11k_sta *arsta = NULL; u32 hal_rx_desc_sz = ar->ab->hw_params.hal_desc_sz; u32 peer_id; @@ -327,7 +321,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/dp_ msdu_len = ath11k_dp_rx_h_msdu_start_msdu_len(ar->ab, desc); -@@ -4489,7 +4587,8 @@ static int ath11k_dp_rx_h_null_q_desc(st +@@ -4510,7 +4608,8 @@ static int ath11k_dp_rx_h_null_q_desc(st } ath11k_dp_rx_h_ppdu(ar, desc, status); @@ -337,11 +331,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/dp_ rxcb->tid = ath11k_dp_rx_h_mpdu_start_tid(ar->ab, desc); -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/hw.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath11k/hw.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/hw.c -@@ -287,6 +287,16 @@ static bool ath11k_hw_ipq8074_rx_desc_ge +--- a/drivers/net/wireless/ath/ath11k/hw.c ++++ b/drivers/net/wireless/ath/ath11k/hw.c +@@ -288,6 +288,16 @@ static bool ath11k_hw_ipq8074_rx_desc_ge __le32_to_cpu(desc->u.ipq8074.msdu_start.info2)); } @@ -358,7 +350,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/hw. static bool ath11k_hw_ipq8074_rx_desc_get_mpdu_seq_ctl_vld(struct hal_rx_desc *desc) { return !!FIELD_GET(RX_MPDU_START_INFO1_MPDU_SEQ_CTRL_VALID, -@@ -618,6 +628,16 @@ static bool ath11k_hw_qcn9074_rx_desc_ge +@@ -619,6 +629,16 @@ static bool ath11k_hw_qcn9074_rx_desc_ge __le32_to_cpu(desc->u.qcn9074.msdu_start.info2)); } @@ -375,7 +367,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/hw. static bool ath11k_hw_qcn9074_rx_desc_get_mpdu_seq_ctl_vld(struct hal_rx_desc *desc) { return !!FIELD_GET(RX_MPDU_START_INFO11_MPDU_SEQ_CTRL_VALID, -@@ -1204,6 +1224,7 @@ const struct ath11k_hw_ops ipq8074_ops = +@@ -1210,6 +1230,7 @@ const struct ath11k_hw_ops ipq8074_ops = .rx_desc_get_encrypt_type = ath11k_hw_ipq8074_rx_desc_get_encrypt_type, .rx_desc_get_decap_type = ath11k_hw_ipq8074_rx_desc_get_decap_type, .rx_desc_get_mesh_ctl = ath11k_hw_ipq8074_rx_desc_get_mesh_ctl, @@ -383,7 +375,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/hw. .rx_desc_get_ldpc_support = ath11k_hw_ipq8074_rx_desc_get_ldpc_support, .rx_desc_get_mpdu_seq_ctl_vld = ath11k_hw_ipq8074_rx_desc_get_mpdu_seq_ctl_vld, .rx_desc_get_mpdu_fc_valid = ath11k_hw_ipq8074_rx_desc_get_mpdu_fc_valid, -@@ -1253,6 +1274,7 @@ const struct ath11k_hw_ops ipq6018_ops = +@@ -1259,6 +1280,7 @@ const struct ath11k_hw_ops ipq6018_ops = .rx_desc_get_encrypt_type = ath11k_hw_ipq8074_rx_desc_get_encrypt_type, .rx_desc_get_decap_type = ath11k_hw_ipq8074_rx_desc_get_decap_type, .rx_desc_get_mesh_ctl = ath11k_hw_ipq8074_rx_desc_get_mesh_ctl, @@ -391,7 +383,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/hw. .rx_desc_get_ldpc_support = ath11k_hw_ipq8074_rx_desc_get_ldpc_support, .rx_desc_get_mpdu_seq_ctl_vld = ath11k_hw_ipq8074_rx_desc_get_mpdu_seq_ctl_vld, .rx_desc_get_mpdu_fc_valid = ath11k_hw_ipq8074_rx_desc_get_mpdu_fc_valid, -@@ -1302,6 +1324,7 @@ const struct ath11k_hw_ops qca6390_ops = +@@ -1308,6 +1330,7 @@ const struct ath11k_hw_ops qca6390_ops = .rx_desc_get_encrypt_type = ath11k_hw_ipq8074_rx_desc_get_encrypt_type, .rx_desc_get_decap_type = ath11k_hw_ipq8074_rx_desc_get_decap_type, .rx_desc_get_mesh_ctl = ath11k_hw_ipq8074_rx_desc_get_mesh_ctl, @@ -399,7 +391,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/hw. .rx_desc_get_ldpc_support = ath11k_hw_ipq8074_rx_desc_get_ldpc_support, .rx_desc_get_mpdu_seq_ctl_vld = ath11k_hw_ipq8074_rx_desc_get_mpdu_seq_ctl_vld, .rx_desc_get_mpdu_fc_valid = ath11k_hw_ipq8074_rx_desc_get_mpdu_fc_valid, -@@ -1353,6 +1376,7 @@ const struct ath11k_hw_ops qcn9074_ops = +@@ -1359,6 +1382,7 @@ const struct ath11k_hw_ops qcn9074_ops = .rx_desc_get_encrypt_type = ath11k_hw_qcn9074_rx_desc_get_encrypt_type, .rx_desc_get_decap_type = ath11k_hw_qcn9074_rx_desc_get_decap_type, .rx_desc_get_mesh_ctl = ath11k_hw_qcn9074_rx_desc_get_mesh_ctl, @@ -407,19 +399,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/hw. .rx_desc_get_ldpc_support = ath11k_hw_qcn9074_rx_desc_get_ldpc_support, .rx_desc_get_mpdu_seq_ctl_vld = ath11k_hw_qcn9074_rx_desc_get_mpdu_seq_ctl_vld, .rx_desc_get_mpdu_fc_valid = ath11k_hw_qcn9074_rx_desc_get_mpdu_fc_valid, -@@ -1497,6 +1521,7 @@ const struct ath11k_hw_ops qcn6122_ops = - .rx_desc_get_encrypt_type = ath11k_hw_qcn9074_rx_desc_get_encrypt_type, - .rx_desc_get_decap_type = ath11k_hw_qcn9074_rx_desc_get_decap_type, - .rx_desc_get_mesh_ctl = ath11k_hw_qcn9074_rx_desc_get_mesh_ctl, -+ .rx_desc_get_ip_valid = ath11k_hw_qcn9074_rx_desc_get_ip_valid, - .rx_desc_get_mpdu_seq_ctl_vld = ath11k_hw_qcn9074_rx_desc_get_mpdu_seq_ctl_vld, - .rx_desc_get_mpdu_fc_valid = ath11k_hw_qcn9074_rx_desc_get_mpdu_fc_valid, - .rx_desc_get_mpdu_start_seq_no = ath11k_hw_qcn9074_rx_desc_get_mpdu_start_seq_no, -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/hw.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath11k/hw.h -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/hw.h -@@ -246,6 +246,7 @@ struct ath11k_hw_ops { +--- a/drivers/net/wireless/ath/ath11k/hw.h ++++ b/drivers/net/wireless/ath/ath11k/hw.h +@@ -250,6 +250,7 @@ struct ath11k_hw_ops { u32 (*rx_desc_get_encrypt_type)(struct hal_rx_desc *desc); u8 (*rx_desc_get_decap_type)(struct hal_rx_desc *desc); u8 (*rx_desc_get_mesh_ctl)(struct hal_rx_desc *desc); @@ -427,11 +409,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/hw. bool (*rx_desc_get_ldpc_support)(struct hal_rx_desc *desc); bool (*rx_desc_get_mpdu_seq_ctl_vld)(struct hal_rx_desc *desc); bool (*rx_desc_get_mpdu_fc_valid)(struct hal_rx_desc *desc); -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/mac.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath11k/mac.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/mac.c -@@ -5310,6 +5310,14 @@ static int ath11k_mac_op_sta_state(struc +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -5334,6 +5334,14 @@ static int ath11k_mac_op_sta_state(struc } } else if (old_state == IEEE80211_STA_AUTHORIZED && new_state == IEEE80211_STA_ASSOC) { diff --git a/feeds/ipq95xx/mac80211/patches/qca/237-007-ath11k-optimizations-in-ath11k_dp_process_rx.patch b/feeds/ipq95xx/mac80211/patches/qca/237-007-ath11k-optimizations-in-ath11k_dp_process_rx.patch deleted file mode 100644 index 2801eccbc..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/237-007-ath11k-optimizations-in-ath11k_dp_process_rx.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0fe4a7f57a44a0aaad6fb1d6861c9fb9597358a2 Mon Sep 17 00:00:00 2001 -From: P Praneesh -Date: Tue, 15 Dec 2020 11:27:48 +0530 -Subject: [PATCH] ath11k: optimizations in ath11k_dp_process_rx() - -Incaludes below changes, - 1. Increment total_msdu_reaped only when continuation is not set and update - drop flag correspondingly. This is to avoid additional access to ath11k_hal_srng_dst_num_free() - 2. Avoid descriptor memcpy as the data is prefetched already - 3. The Active Pdev and CAC check are done for each msdu in ath11k_dp_rx_process_received_packets - Rather, collect all msdu's in a per mac msdu list, and pass to the function. - 4. Add branch predictors where required in the process rx() - 5. Remove usage of quota variable since we add only max napi budget msdus to the list - 6. Prefetch the initial descriptor part which is used by all the hw ops for msdu info collection. - - About 3-4% improvement on single radio UDP UL on single core was seen. - More validation/confirmation on perf stats required. - -Signed-off-by: Sriram R -Signed-off-by: P Praneesh ---- - drivers/net/wireless/ath/ath11k/dp_rx.c | 107 ++++++++++++++++---------------- - 1 file changed, 55 insertions(+), 52 deletions(-) - ---- a/drivers/net/wireless/ath/ath11k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -3184,7 +3184,7 @@ try_again: - * head pointer so that we can reap complete MPDU in the current - * rx processing. - */ -- if (!done && ath11k_hal_srng_dst_num_free(ab, srng, true)) { -+ if (unlikely(!done && ath11k_hal_srng_dst_num_free(ab, srng, true))) { - ath11k_hal_srng_access_end(ab, srng); - goto try_again; - } diff --git a/feeds/ipq95xx/mac80211/patches/qca/237-ath11k-add-debugfs-interface-to-configure-firmware-d.patch b/feeds/ipq95xx/mac80211/patches/qca/237-ath11k-add-debugfs-interface-to-configure-firmware-d.patch deleted file mode 100644 index db8465b1c..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/237-ath11k-add-debugfs-interface-to-configure-firmware-d.patch +++ /dev/null @@ -1,233 +0,0 @@ -From c7a64ef56edcc32c18431ec7aba345b20eda5e8f Mon Sep 17 00:00:00 2001 -From: Seevalamuthu Mariappan -Date: Mon, 25 Jan 2021 10:10:30 +0530 -Subject: [PATCH] ath11k: add debugfs interface to configure firmware dbg log - level - -Added debugfs interface "fw_dbglog_config" to configure firmware log levels. -Configuration is done via WMI command WMI_DBGLOG_CFG_CMDID. - -Command to configure, -echo " " > /sys/kernel/debug/ath11k//fw_dbglog_config - -where dbglog_param can be, - 1) WMI_DEBUG_LOG_PARAM_LOG_LEVEL - configure log level for a given module - here, = <0xaaaa00bb>, 'aaaa' - module id and 'bb' - loglevel - 2) WMI_DEBUG_LOG_PARAM_VDEV_ENABLE - enable the debug log for a given vdev - here, = vdev_id - 3) WMI_DEBUG_LOG_PARAM_VDEV_DISABLE - disable debug log for a given vdev - except ERROR logs - here, = vdev_id - 4) WMI_DEBUG_LOG_PARAM_VDEV_ENABLE_BITMAP - set vdev enable bitmap - here, = vdev_enable_bitmap - 5) WMI_DEBUG_LOG_PARAM_MOD_ENABLE_BITMAP - set a given log level to all the - modules specified in the module bitmap - here, = <0xaaaaaaaa000000bb>, 'aaaaaaaa' - module bitmap and - 'bb' - loglevel - 6) WMI_DEBUG_LOG_PARAM_WOW_MOD_ENABLE_BITMAP - Wow mode specific logging enable - here, = <0xaaaaaaaa000000bb>, 'aaaaaaaa' - module bitmap and - 'bb' - loglevel - -Sample command usage, -echo "1 0xffff0001" > /sys/kernel/debug/ath11k/qcn9000\ hw1.0_0000 -\:01\:00.0/fw_dbglog_config - -Signed-off-by: Seevalamuthu Mariappan ---- - drivers/net/wireless/ath/ath11k/core.h | 2 + - drivers/net/wireless/ath/ath11k/debugfs.c | 66 ++++++++++++++++++++++++++++++++- - drivers/net/wireless/ath/ath11k/wmi.c | 48 ++++++++++++++++++++++++ - drivers/net/wireless/ath/ath11k/wmi.h | 16 ++++++++ - 4 files changed, 131 insertions(+), 1 deletion(-) - ---- a/drivers/net/wireless/ath/ath11k/core.h -+++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -1036,6 +1036,8 @@ struct ath11k_base { - int userpd_id; - struct ath11k_internal_pci ipci; - bool enable_memory_stats; -+ u32 fw_dbglog_param; -+ u64 fw_dbglog_val; - - u32 rx_hash; - bool stats_disable; ---- a/drivers/net/wireless/ath/ath11k/debugfs.c -+++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -1841,6 +1841,71 @@ static const struct file_operations fops - .read = ath11k_read_ce_latency_stats, - }; - -+static ssize_t ath11k_read_fw_dbglog(struct file *file, -+ char __user *user_buf, -+ size_t count, loff_t *ppos) -+{ -+ struct ath11k_base *ab = file->private_data; -+ size_t len; -+ char buf[128]; -+ -+ len = scnprintf(buf, sizeof(buf), "%u 0x%016llx\n", -+ ab->fw_dbglog_param, ab->fw_dbglog_val); -+ -+ return simple_read_from_buffer(user_buf, count, ppos, buf, len); -+} -+ -+static ssize_t ath11k_write_fw_dbglog(struct file *file, -+ const char __user *user_buf, -+ size_t count, loff_t *ppos) -+{ -+ struct ath11k_base *ab = file->private_data; -+ struct ath11k *ar = ab->pdevs[0].ar; -+ char buf[128] = {0}; -+ unsigned int param; -+ u64 value; -+ int ret; -+ -+ if (!ar) -+ return -EINVAL; -+ -+ mutex_lock(&ar->conf_mutex); -+ ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, -+ user_buf, count); -+ if (ret <= 0) -+ goto out; -+ -+ ret = sscanf(buf, "%u %llx", ¶m, &value); -+ -+ if (ret != 2) { -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ ab->fw_dbglog_param = param; -+ ab->fw_dbglog_val = value; -+ ret = ath11k_wmi_dbglog_cfg(ar, param, value); -+ if (ret) { -+ ath11k_warn(ar, "dbglog cfg failed from debugfs: %d\n", -+ ret); -+ goto out; -+ } -+ -+ ret = count; -+ -+out: -+ mutex_unlock(&ar->conf_mutex); -+ return ret; -+} -+ -+static const struct file_operations fops_fw_dbglog = { -+ .read = ath11k_read_fw_dbglog, -+ .write = ath11k_write_fw_dbglog, -+ .open = simple_open, -+ .owner = THIS_MODULE, -+ .llseek = default_llseek, -+}; -+ - int ath11k_debugfs_pdev_create(struct ath11k_base *ab) - { - if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)) -@@ -1867,6 +1932,9 @@ int ath11k_debugfs_pdev_create(struct at - - debugfs_create_file("ce_latency_stats", 0600, ab->debugfs_soc, ab, - &fops_ce_latency_stats); -+ debugfs_create_file("fw_dbglog_config", 0600, ab->debugfs_soc, ab, -+ &fops_fw_dbglog); -+ - - debugfs_create_file("rx_hash", 0600, ab->debugfs_soc, ab, - &fops_soc_rx_hash); -@@ -3827,7 +3895,6 @@ int ath11k_debugfs_register(struct ath11 - - debugfs_create_file("enable_dbr_debug", 0200, ar->debug.debugfs_pdev, - ar, &fops_dbr_debug); -- - return 0; - } - ---- a/drivers/net/wireless/ath/ath11k/wmi.c -+++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -9076,6 +9076,55 @@ int ath11k_wmi_pdev_get_tpc_table_cmdid( - return ret; - } - -+int ath11k_wmi_dbglog_cfg(struct ath11k *ar, u32 param, u64 value) -+{ -+ struct ath11k_pdev_wmi *wmi = ar->wmi; -+ struct wmi_dbglog_config_cmd_fixed_param *cmd; -+ struct sk_buff *skb; -+ struct wmi_tlv *tlv; -+ u32 module_id_bitmap; -+ int ret, len; -+ -+ len = sizeof(*cmd) + TLV_HDR_SIZE + sizeof(module_id_bitmap); -+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len); -+ if (!skb) -+ return -ENOMEM; -+ cmd = (struct wmi_dbglog_config_cmd_fixed_param *)skb->data; -+ cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_DEBUG_LOG_CONFIG_CMD) | -+ FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); -+ cmd->dbg_log_param = param; -+ -+ tlv = (u8 *) cmd + sizeof(*cmd); -+ tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_UINT32) | -+ FIELD_PREP(WMI_TLV_LEN, sizeof(u32)); -+ -+ switch (param) { -+ case WMI_DEBUG_LOG_PARAM_LOG_LEVEL: -+ case WMI_DEBUG_LOG_PARAM_VDEV_ENABLE: -+ case WMI_DEBUG_LOG_PARAM_VDEV_DISABLE: -+ case WMI_DEBUG_LOG_PARAM_VDEV_ENABLE_BITMAP: -+ cmd->value = value; -+ break; -+ case WMI_DEBUG_LOG_PARAM_MOD_ENABLE_BITMAP: -+ case WMI_DEBUG_LOG_PARAM_WOW_MOD_ENABLE_BITMAP: -+ cmd->value = value; -+ module_id_bitmap = value >> 32; -+ memcpy(tlv->value, &module_id_bitmap, sizeof(module_id_bitmap)); -+ break; -+ default: -+ dev_kfree_skb(skb); -+ return -EINVAL; -+ } -+ -+ ret = ath11k_wmi_cmd_send(wmi, skb, WMI_DBGLOG_CFG_CMDID); -+ if (ret) { -+ ath11k_warn(ar->ab, -+ "failed to send WMI_DBGLOG_CFG_CMDID\n"); -+ dev_kfree_skb(skb); -+ } -+ return ret; -+} -+ - static void ath11k_wmi_twt_add_dialog_event(struct ath11k_base *ab, struct sk_buff *skb) - { - const char *status[] = { ---- a/drivers/net/wireless/ath/ath11k/wmi.h -+++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -6155,6 +6155,21 @@ struct wmi_qos_null_tx_cmd { - u32 tx_params_valid; - } __packed; - -+enum wmi_dblog_param { -+ WMI_DEBUG_LOG_PARAM_LOG_LEVEL = 0x1, -+ WMI_DEBUG_LOG_PARAM_VDEV_ENABLE, -+ WMI_DEBUG_LOG_PARAM_VDEV_DISABLE, -+ WMI_DEBUG_LOG_PARAM_VDEV_ENABLE_BITMAP, -+ WMI_DEBUG_LOG_PARAM_MOD_ENABLE_BITMAP, -+ WMI_DEBUG_LOG_PARAM_WOW_MOD_ENABLE_BITMAP, -+}; -+ -+struct wmi_dbglog_config_cmd_fixed_param { -+ u32 tlv_header; -+ u32 dbg_log_param; -+ u32 value; -+} __packed; -+ - #define WMI_MAX_MEM_REQS 32 - - #define MAX_RADIOS 3 -@@ -6552,4 +6567,5 @@ int ath11k_wmi_send_aggr_size_cmd(struct - struct set_custom_aggr_size_params *params); - int ath11k_wmi_send_wmi_ctrl_stats_cmd(struct ath11k *ar, - struct wmi_ctrl_path_stats_cmd_param *param); -+int ath11k_wmi_dbglog_cfg(struct ath11k *ar, u32 param, u64 value); - #endif diff --git a/feeds/ipq95xx/mac80211/patches/qca/237-ath11k-fix-radiotap-rate-info.patch b/feeds/ipq95xx/mac80211/patches/qca/237-ath11k-fix-radiotap-rate-info.patch deleted file mode 100644 index e321b075c..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/237-ath11k-fix-radiotap-rate-info.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 3a74003841f04a5daac160e26c51d81c1dd99fd7 Mon Sep 17 00:00:00 2001 -From: Anilkumar Kolli -Date: Mon, 25 Jan 2021 19:54:00 +0530 -Subject: ath11k: Fix rate in monior mode radiotap header - -Packet Rate info is not part of msdu in mon_dst_ring, -rate is updated from monitor status ring. - -Signed-off-by: Anilkumar Kolli ---- - drivers/net/wireless/ath/ath11k/dp_rx.c | 20 ++++++++++++++++---- - drivers/net/wireless/ath/ath11k/hal_rx.c | 1 + - 2 files changed, 17 insertions(+), 4 deletions(-) - ---- a/drivers/net/wireless/ath/ath11k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -5751,31 +5751,47 @@ ath11k_dp_rx_update_radiotap_he_mu(struc - rtap_buf[rtap_len] = rx_status->he_RU[3]; - } - --static void ath11k_update_radiotap(struct hal_rx_mon_ppdu_info *ppduinfo, -- struct sk_buff *mon_skb, -- struct ieee80211_rx_status *rxs) -+static void ath11k_update_radiotap(struct ath11k *ar, -+ struct hal_rx_mon_ppdu_info *ppduinfo, -+ struct sk_buff *mon_skb, -+ struct ieee80211_rx_status *rxs) - { -+ struct ieee80211_supported_band *sband; - u8 *ptr = NULL; - -+ rxs->flag |= RX_FLAG_MACTIME_START; -+ rxs->signal = ppduinfo->rssi_comb + ATH11K_DEFAULT_NOISE_FLOOR; -+ /* Incase if ppduinfo->nss is 0 TLVs are not processed in -+ * ath11k_hal_rx_parse_mon_status_tlv, 0 nss cause warning -+ * in mac80211 so to avoid that issue filling it with -+ * minimum nss -+ */ -+ rxs->nss = ppduinfo->nss ? ppduinfo->nss : ppduinfo->nss + 1; -+ - if (ppduinfo->he_mu_flags) { - rxs->flag |= RX_FLAG_RADIOTAP_HE_MU; - rxs->encoding = RX_ENC_HE; - ptr = skb_push(mon_skb, sizeof(struct ieee80211_radiotap_he_mu)); - ath11k_dp_rx_update_radiotap_he_mu(ppduinfo, ptr); -- } -- if (ppduinfo->he_flags) { -+ } else if (ppduinfo->he_flags) { - rxs->flag |= RX_FLAG_RADIOTAP_HE; - rxs->encoding = RX_ENC_HE; - ptr = skb_push(mon_skb, sizeof(struct ieee80211_radiotap_he)); - ath11k_dp_rx_update_radiotap_he(ppduinfo, ptr); -+ rxs->rate_idx = ppduinfo->rate; -+ } else if (ppduinfo->vht_flags) { -+ rxs->encoding = RX_ENC_VHT; -+ rxs->rate_idx = ppduinfo->rate; -+ } else if (ppduinfo->ht_flags) { -+ rxs->encoding = RX_ENC_HT; -+ rxs->rate_idx = ppduinfo->rate; -+ } else { -+ rxs->encoding = RX_ENC_LEGACY; -+ sband = &ar->mac.sbands[rxs->band]; -+ rxs->rate_idx = ath11k_mac_hw_rate_to_idx(sband, ppduinfo->rate, -+ ppduinfo->cck_flag); - } - -- rxs->flag |= RX_FLAG_MACTIME_START; -- rxs->signal = ppduinfo->rssi_comb + ATH11K_DEFAULT_NOISE_FLOOR; -- -- if (ppduinfo->nss) -- rxs->nss = ppduinfo->nss; -- - rxs->mactime = ppduinfo->tsft; - } - -@@ -5810,7 +5826,7 @@ static int ath11k_dp_rx_mon_deliver(stru - rxs->flag |= RX_FLAG_ALLOW_SAME_PN; - } - rxs->flag |= RX_FLAG_ONLY_MONITOR; -- ath11k_update_radiotap(ppduinfo, mon_skb, rxs); -+ ath11k_update_radiotap(ar, ppduinfo, mon_skb, rxs); - ath11k_dp_rx_deliver_msdu(ar, napi, mon_skb, rxs); - mon_skb = skb_next; - } while (mon_skb); diff --git a/feeds/ipq95xx/mac80211/patches/qca/238-ath11k-add-cfr-support-for-ipq8074.patch b/feeds/ipq95xx/mac80211/patches/qca/238-ath11k-add-cfr-support-for-ipq8074.patch index 3e9bb0b3b..5072830ff 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/238-ath11k-add-cfr-support-for-ipq8074.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/238-ath11k-add-cfr-support-for-ipq8074.patch @@ -66,7 +66,7 @@ Signed-off-by: Venkateswara Naralasetty --- a/drivers/net/wireless/ath/ath11k/Kconfig +++ b/drivers/net/wireless/ath/ath11k/Kconfig -@@ -85,3 +85,12 @@ config ATH11K_MEM_PROFILE_512M +@@ -86,3 +86,12 @@ config ATH11K_MEM_PROFILE_512M default n ---help--- Enables 512MB memory profile for ath11k @@ -81,14 +81,14 @@ Signed-off-by: Venkateswara Naralasetty + Say Y to enable access to collect cfr data dump via debugfs. --- a/drivers/net/wireless/ath/ath11k/Makefile +++ b/drivers/net/wireless/ath/ath11k/Makefile -@@ -28,6 +28,7 @@ ath11k-$(CONFIG_WANT_DEV_COREDUMP) += co - ath11k-$(CPTCFG_ATH11K_SPECTRAL) += spectral.o +@@ -29,6 +29,7 @@ ath11k-$(CPTCFG_ATH11K_SPECTRAL) += spec + ath11k-$(CONFIG_PM) += wow.o ath11k-$(CPTCFG_ATH11K_PKTLOG) += pktlog.o ath11k-$(CPTCFG_ATH11K_NSS_SUPPORT) += nss.o +ath11k-$(CPTCFG_ATH11K_CFR) += cfr.o obj-$(CPTCFG_ATH11K_AHB) += ath11k_ahb.o - ath11k_ahb-y += ahb.o pci_cmn.o + ath11k_ahb-y += ahb.o --- /dev/null +++ b/drivers/net/wireless/ath/ath11k/cfr.c @@ -0,0 +1,878 @@ @@ -1257,9 +1257,9 @@ Signed-off-by: Venkateswara Naralasetty +#endif /* ATH11K_CFR_H */ --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -545,6 +545,11 @@ static const struct ath11k_hw_params ath - .ce_fwlog_enable = true, - .fwmem_mode_change = false, +@@ -664,6 +664,11 @@ static const struct ath11k_hw_params ath + .fixed_fw_mem = false, + .support_off_channel_tx = false, .is_qdss_support = false, + .cfr_support = true, + .cfr_dma_hdr_size = sizeof(struct ath11k_cfir_dma_hdr), @@ -1269,7 +1269,7 @@ Signed-off-by: Venkateswara Naralasetty }, { .hw_rev = ATH11K_HW_QCN6122, -@@ -1130,8 +1135,16 @@ static int ath11k_core_pdev_create(struc +@@ -1453,8 +1458,16 @@ static int ath11k_core_pdev_create(struc goto err_thermal_unregister; } @@ -1286,7 +1286,7 @@ Signed-off-by: Venkateswara Naralasetty err_thermal_unregister: ath11k_thermal_unregister(ab); err_mac_unregister: -@@ -1148,6 +1161,7 @@ err_pdev_debug: +@@ -1471,6 +1484,7 @@ err_pdev_debug: static void ath11k_core_pdev_destroy(struct ath11k_base *ab) { @@ -1294,7 +1294,7 @@ Signed-off-by: Venkateswara Naralasetty ath11k_spectral_deinit(ab); ath11k_thermal_unregister(ab); ath11k_mac_unregister(ab); -@@ -1516,6 +1530,7 @@ static int ath11k_core_reconfigure_on_cr +@@ -1829,6 +1843,7 @@ static int ath11k_core_reconfigure_on_cr ath11k_hif_irq_disable(ab); ath11k_dp_pdev_free(ab); ath11k_spectral_deinit(ab); @@ -1304,7 +1304,7 @@ Signed-off-by: Venkateswara Naralasetty ath11k_dp_pdev_reo_cleanup(ab); --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -27,6 +27,7 @@ +@@ -33,6 +33,7 @@ #include "vendor.h" #include "rx_desc.h" #include "nss.h" @@ -1312,7 +1312,7 @@ Signed-off-by: Venkateswara Naralasetty #ifdef CONFIG_QCOM_QMI_HELPERS extern wait_queue_head_t ath11k_ssr_dump_wq; -@@ -445,6 +446,13 @@ struct ath11k_htt_tx_stats { +@@ -541,6 +542,13 @@ struct ath11k_htt_tx_stats { u32 mu_group[MAX_MU_GROUP_ID]; }; @@ -1326,7 +1326,7 @@ Signed-off-by: Venkateswara Naralasetty struct ath11k_per_ppdu_tx_stats { u16 succ_pkts; u16 failed_pkts; -@@ -506,6 +514,9 @@ struct ath11k_sta { +@@ -605,6 +613,9 @@ struct ath11k_sta { u32 ps_start_jiffies; u8 peer_current_ps_valid; u32 ps_total_duration; @@ -1336,7 +1336,7 @@ Signed-off-by: Venkateswara Naralasetty }; #define ATH11K_MIN_5G_FREQ 4150 -@@ -774,6 +785,10 @@ struct ath11k { +@@ -878,6 +889,10 @@ struct ath11k { u8 ps_state_enable; u8 ps_timekeeper_enable; u8 reset_ps_duration; @@ -1345,8 +1345,8 @@ Signed-off-by: Venkateswara Naralasetty +#endif + u8 cfr_enabled; u32 vdev_id_11d_scan; - struct completion finish_11d_scan; - struct completion finish_11d_ch_list; + struct completion completed_11d_scan; + enum ath11k_11d_state state_11d; --- a/drivers/net/wireless/ath/ath11k/dbring.c +++ b/drivers/net/wireless/ath/ath11k/dbring.c @@ -35,7 +35,7 @@ static void ath11k_dbring_fill_magic_val @@ -1356,7 +1356,7 @@ Signed-off-by: Venkateswara Naralasetty -static int ath11k_dbring_bufs_replenish(struct ath11k *ar, +int ath11k_dbring_bufs_replenish(struct ath11k *ar, struct ath11k_dbring *ring, - struct ath11k_dbring_element *buff, + struct ath11k_dbring_element *buff, enum wmi_direct_buffer_module id) @@ -78,6 +78,9 @@ static int ath11k_dbring_bufs_replenish( goto err_idr_remove; @@ -1368,26 +1368,7 @@ Signed-off-by: Venkateswara Naralasetty buff->paddr = paddr; cookie = FIELD_PREP(DP_RXDMA_BUF_COOKIE_PDEV_ID, ar->pdev_idx) | -@@ -198,8 +201,7 @@ int ath11k_dbring_set_cfg(struct ath11k - - int ath11k_dbring_buf_setup(struct ath11k *ar, - struct ath11k_dbring *ring, -- struct ath11k_dbring_cap *db_cap, -- enum wmi_direct_buffer_module id) -+ struct ath11k_dbring_cap *db_cap) - { - struct ath11k_base *ab = ar->ab; - struct hal_srng *srng; -@@ -215,7 +217,7 @@ int ath11k_dbring_buf_setup(struct ath11 - ring->hp_addr = ath11k_hal_srng_get_hp_addr(ar->ab, srng); - ring->tp_addr = ath11k_hal_srng_get_tp_addr(ar->ab, srng); - -- ret = ath11k_dbring_fill_bufs(ar, ring, id); -+ ret = ath11k_dbring_fill_bufs(ar, ring, db_cap->id); - - return ret; - } -@@ -281,6 +283,7 @@ int ath11k_dbring_buffer_release_event(s +@@ -280,6 +283,7 @@ int ath11k_dbring_buffer_release_event(s int size; dma_addr_t paddr; int ret = 0; @@ -1395,7 +1376,7 @@ Signed-off-by: Venkateswara Naralasetty pdev_idx = ev->fixed.pdev_id; module_id = ev->fixed.module_id; -@@ -310,6 +313,9 @@ int ath11k_dbring_buffer_release_event(s +@@ -309,6 +313,9 @@ int ath11k_dbring_buffer_release_event(s case WMI_DIRECT_BUF_SPECTRAL: ring = ath11k_spectral_get_dbring(ar); break; @@ -1405,7 +1386,7 @@ Signed-off-by: Venkateswara Naralasetty default: ring = NULL; ath11k_warn(ab, "Recv dma buffer release ev on unsupp module %d\n", -@@ -360,8 +366,12 @@ int ath11k_dbring_buffer_release_event(s +@@ -359,8 +366,12 @@ int ath11k_dbring_buffer_release_event(s handler_data.data = PTR_ALIGN(vaddr_unalign, ring->buf_align); handler_data.data_sz = ring->buf_sz; @@ -1430,7 +1411,7 @@ Signed-off-by: Venkateswara Naralasetty }; struct ath11k_dbring_buf_release_event { -@@ -60,13 +62,17 @@ int ath11k_dbring_set_cfg(struct ath11k +@@ -60,6 +62,11 @@ int ath11k_dbring_set_cfg(struct ath11k u32 event_timeout_ms, int (*handler)(struct ath11k *, struct ath11k_dbring_data *)); @@ -1442,14 +1423,6 @@ Signed-off-by: Venkateswara Naralasetty int ath11k_dbring_wmi_cfg_setup(struct ath11k *ar, struct ath11k_dbring *ring, enum wmi_direct_buffer_module id); - int ath11k_dbring_buf_setup(struct ath11k *ar, - struct ath11k_dbring *ring, -- struct ath11k_dbring_cap *db_cap, -- enum wmi_direct_buffer_module id); -+ struct ath11k_dbring_cap *db_cap); - int ath11k_dbring_srng_setup(struct ath11k *ar, struct ath11k_dbring *ring, - int ring_num, int num_entries); - int ath11k_dbring_buffer_release_event(struct ath11k_base *ab, --- a/drivers/net/wireless/ath/ath11k/debugfs_sta.c +++ b/drivers/net/wireless/ath/ath11k/debugfs_sta.c @@ -1240,6 +1240,157 @@ static const struct file_operations fops @@ -1510,7 +1483,7 @@ Signed-off-by: Venkateswara Naralasetty + + if (cfr_capture_enable > WMI_PEER_CFR_CAPTURE_ENABLE || + cfr_capture_bw > WMI_PEER_CFR_CAPTURE_BW_80MHZ || -+ cfr_capture_bw > sta->bandwidth || ++ cfr_capture_bw > sta->deflink.bandwidth || + cfr_capture_method > CFR_CAPURE_METHOD_NULL_FRAME_WITH_PHASE || + cfr_capture_period > WMI_PEER_CFR_PERIODICITY_MAX) { + ret = -EINVAL; @@ -1623,7 +1596,7 @@ Signed-off-by: Venkateswara Naralasetty } --- a/drivers/net/wireless/ath/ath11k/hal.c +++ b/drivers/net/wireless/ath/ath11k/hal.c -@@ -181,7 +181,7 @@ static const struct hal_srng_config hw_s +@@ -182,7 +182,7 @@ static const struct hal_srng_config hw_s }, { /* RXDMA DIR BUF */ .start_ring_id = HAL_SRNG_RING_ID_RXDMA_DIR_BUF, @@ -1634,7 +1607,7 @@ Signed-off-by: Venkateswara Naralasetty .ring_dir = HAL_SRNG_DIR_SRC, --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h -@@ -225,6 +225,10 @@ struct ath11k_hw_params { +@@ -223,6 +223,10 @@ struct ath11k_hw_params { bool ce_fwlog_enable; bool fwmem_mode_change; bool is_qdss_support; @@ -1647,7 +1620,7 @@ Signed-off-by: Venkateswara Naralasetty bool current_cc_support; --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -5252,6 +5252,8 @@ static int ath11k_mac_op_sta_state(struc +@@ -5274,6 +5274,8 @@ static int ath11k_mac_op_sta_state(struc kfree(arsta->rx_stats); arsta->rx_stats = NULL; @@ -1656,7 +1629,7 @@ Signed-off-by: Venkateswara Naralasetty } else if (old_state == IEEE80211_STA_AUTH && new_state == IEEE80211_STA_ASSOC && (vif->type == NL80211_IFTYPE_AP || -@@ -6259,6 +6261,7 @@ static int ath11k_mac_mgmt_tx_wmi(struct +@@ -6283,6 +6285,7 @@ static int ath11k_mac_mgmt_tx_wmi(struct struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_tx_info *info; dma_addr_t paddr; @@ -1664,7 +1637,7 @@ Signed-off-by: Venkateswara Naralasetty int buf_id; int ret; -@@ -6304,7 +6307,13 @@ static int ath11k_mac_mgmt_tx_wmi(struct +@@ -6328,7 +6331,13 @@ static int ath11k_mac_mgmt_tx_wmi(struct return 0; } @@ -1679,20 +1652,9 @@ Signed-off-by: Venkateswara Naralasetty if (ret) { ath11k_warn(ar->ab, "failed to send mgmt frame: %d\n", ret); goto err_unmap_buf; ---- a/drivers/net/wireless/ath/ath11k/spectral.c -+++ b/drivers/net/wireless/ath/ath11k/spectral.c -@@ -817,7 +817,7 @@ static int ath11k_spectral_ring_alloc(st - ATH11K_SPECTRAL_EVENT_TIMEOUT_MS, - ath11k_spectral_process_data); - -- ret = ath11k_dbring_buf_setup(ar, &sp->rx_ring, db_cap, WMI_DIRECT_BUF_SPECTRAL); -+ ret = ath11k_dbring_buf_setup(ar, &sp->rx_ring, db_cap); - if (ret) { - ath11k_warn(ar->ab, "failed to setup db ring buffer\n"); - goto srng_cleanup; --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -636,10 +636,11 @@ struct sk_buff *ath11k_wmi_alloc_skb(str +@@ -651,11 +651,12 @@ static u32 ath11k_wmi_mgmt_get_freq(stru } int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id, @@ -1700,12 +1662,13 @@ Signed-off-by: Venkateswara Naralasetty + struct sk_buff *frame, bool tx_params_valid) { struct ath11k_pdev_wmi *wmi = ar->wmi; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(frame); struct wmi_mgmt_send_cmd *cmd; + struct wmi_tx_send_params *params; struct wmi_tlv *frame_tlv; struct sk_buff *skb; u32 buf_len; -@@ -650,6 +651,9 @@ int ath11k_wmi_mgmt_send(struct ath11k * +@@ -666,6 +667,9 @@ int ath11k_wmi_mgmt_send(struct ath11k * len = sizeof(*cmd) + sizeof(*frame_tlv) + roundup(buf_len, 4); @@ -1715,7 +1678,7 @@ Signed-off-by: Venkateswara Naralasetty skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len); if (!skb) return -ENOMEM; -@@ -664,7 +668,7 @@ int ath11k_wmi_mgmt_send(struct ath11k * +@@ -680,7 +684,7 @@ int ath11k_wmi_mgmt_send(struct ath11k * cmd->paddr_hi = upper_32_bits(ATH11K_SKB_CB(frame)->paddr); cmd->frame_len = frame->len; cmd->buf_len = buf_len; @@ -1724,7 +1687,7 @@ Signed-off-by: Venkateswara Naralasetty frame_tlv = (struct wmi_tlv *)(skb->data + sizeof(*cmd)); frame_tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_BYTE) | -@@ -674,6 +678,13 @@ int ath11k_wmi_mgmt_send(struct ath11k * +@@ -690,6 +694,13 @@ int ath11k_wmi_mgmt_send(struct ath11k * ath11k_ce_byte_swap(frame_tlv->value, buf_len); @@ -1738,7 +1701,7 @@ Signed-off-by: Venkateswara Naralasetty ret = ath11k_wmi_cmd_send(wmi, skb, WMI_MGMT_TX_SEND_CMDID); if (ret) { ath11k_warn(ar->ab, -@@ -4229,6 +4240,42 @@ int ath11k_wmi_fils_discovery_tmpl(struc +@@ -4264,6 +4275,42 @@ int ath11k_wmi_fils_discovery_tmpl(struc return ret; } @@ -1781,7 +1744,7 @@ Signed-off-by: Venkateswara Naralasetty int ath11k_wmi_probe_resp_tmpl(struct ath11k *ar, u32 vdev_id, struct sk_buff *tmpl) { -@@ -9346,6 +9393,89 @@ static void ath11k_wmi_diag_event(struct +@@ -9389,6 +9436,89 @@ static void ath11k_wmi_diag_event(struct ath11k_fwlog_write(ab,data, tlv_len); } @@ -1871,7 +1834,7 @@ Signed-off-by: Venkateswara Naralasetty static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb) { struct wmi_cmd_hdr *cmd_hdr; -@@ -9501,6 +9631,9 @@ static void ath11k_wmi_tlv_op_rx(struct +@@ -9544,6 +9674,9 @@ static void ath11k_wmi_tlv_op_rx(struct case WMI_CTRL_PATH_STATS_EVENTID: ath11k_wmi_ctrl_path_stats_event(ab, skb); break; @@ -1883,7 +1846,7 @@ Signed-off-by: Venkateswara Naralasetty ath11k_dbg(ab, ATH11K_DBG_WMI, "Unknown eventid: 0x%x\n", id); --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -331,6 +331,10 @@ enum wmi_tlv_cmd_id { +@@ -337,6 +337,10 @@ enum wmi_tlv_cmd_id { WMI_PEER_REORDER_QUEUE_REMOVE_CMDID, WMI_PEER_SET_RX_BLOCKSIZE_CMDID, WMI_PEER_ANTDIV_INFO_REQ_CMDID, @@ -1894,7 +1857,7 @@ Signed-off-by: Venkateswara Naralasetty WMI_BCN_TX_CMDID = WMI_TLV_CMD(WMI_GRP_MGMT), WMI_PDEV_SEND_BCN_CMDID, WMI_BCN_TMPL_CMDID, -@@ -959,6 +963,7 @@ enum wmi_tlv_pdev_param { +@@ -965,6 +969,7 @@ enum wmi_tlv_pdev_param { WMI_PDEV_PARAM_RADIO_CHAN_STATS_ENABLE, WMI_PDEV_PARAM_RADIO_DIAGNOSIS_ENABLE, WMI_PDEV_PARAM_MESH_MCAST_ENABLE, @@ -1902,7 +1865,7 @@ Signed-off-by: Venkateswara Naralasetty WMI_PDEV_PARAM_SET_CMD_OBSS_PD_THRESHOLD = 0xbc, WMI_PDEV_PARAM_SET_CMD_OBSS_PD_PER_AC = 0xbe, WMI_PDEV_PARAM_ENABLE_SR_PROHIBIT = 0xc6, -@@ -1862,7 +1867,9 @@ enum wmi_tlv_tag { +@@ -1868,7 +1873,9 @@ enum wmi_tlv_tag { WMI_TAG_NDP_EVENT, WMI_TAG_PDEV_PEER_PKTLOG_FILTER_CMD = 0x301, WMI_TAG_PDEV_PEER_PKTLOG_FILTER_INFO, @@ -1912,7 +1875,7 @@ Signed-off-by: Venkateswara Naralasetty WMI_TAG_FILS_DISCOVERY_TMPL_CMD = 0x344, WMI_TAG_PDEV_SRG_BSS_COLOR_BITMAP_CMD = 0x37b, WMI_TAG_PDEV_SRG_PARTIAL_BSSID_BITMAP_CMD, -@@ -3494,6 +3501,85 @@ struct wmi_bssid_arg { +@@ -3499,6 +3506,85 @@ struct wmi_bssid_arg { const u8 *bssid; }; @@ -1998,7 +1961,7 @@ Signed-off-by: Venkateswara Naralasetty struct wmi_start_scan_arg { u32 scan_id; u32 scan_req_id; -@@ -6393,7 +6479,7 @@ int ath11k_wmi_cmd_send(struct ath11k_pd +@@ -6765,7 +6851,7 @@ int ath11k_wmi_cmd_send(struct ath11k_pd u32 cmd_id); struct sk_buff *ath11k_wmi_alloc_skb(struct ath11k_wmi_base *wmi_sc, u32 len); int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id, @@ -2007,10 +1970,10 @@ Signed-off-by: Venkateswara Naralasetty int ath11k_wmi_qos_null_send(struct ath11k *ar, u32 vdev_id, u32 buf_id, struct sk_buff *frame); int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id, -@@ -6568,4 +6654,7 @@ int ath11k_wmi_send_aggr_size_cmd(struct +@@ -6962,4 +7048,7 @@ int ath11k_wmi_send_aggr_size_cmd(struct + struct set_custom_aggr_size_params *params); int ath11k_wmi_send_wmi_ctrl_stats_cmd(struct ath11k *ar, struct wmi_ctrl_path_stats_cmd_param *param); - int ath11k_wmi_dbglog_cfg(struct ath11k *ar, u32 param, u64 value); +int ath11k_wmi_peer_set_cfr_capture_conf(struct ath11k *ar, + u32 vdev_id, const u8 *mac, + struct wmi_peer_cfr_capture_conf_arg *arg); @@ -2019,11 +1982,11 @@ Signed-off-by: Venkateswara Naralasetty +++ b/drivers/net/wireless/ath/ath11k/debug.h @@ -25,6 +25,8 @@ enum ath11k_debug_mask { ATH11K_DBG_PCI = 0x00001000, - ATH11K_DBG_DP_TX = 0x00001000, - ATH11K_DBG_DP_RX = 0x00002000, -+ ATH11K_DBG_CFR = 0x00008000, -+ ATH11K_DBG_CFR_DUMP = 0x00010000, - ATH11K_DBG_TEST = 0x00080000, + ATH11K_DBG_DP_TX = 0x00002000, + ATH11K_DBG_DP_RX = 0x00004000, ++ ATH11K_DBG_CFR = 0x00008000, ++ ATH11K_DBG_CFR_DUMP = 0x00010000, + ATH11K_DBG_TEST = 0x00080000, ATH11K_DBG_ANY = 0xffffffff, }; --- a/local-symbols @@ -2035,4 +1998,4 @@ Signed-off-by: Venkateswara Naralasetty +ATH11K_CFR= ATH12K= ATH12K_DEBUG= - ATH12K_DEBUGFS= + ATH12K_TRACING= diff --git a/feeds/ipq95xx/mac80211/patches/qca/239-ath11k-Increment-pending_mgmt_tx-before-tx-send.patch b/feeds/ipq95xx/mac80211/patches/qca/239-ath11k-Increment-pending_mgmt_tx-before-tx-send.patch deleted file mode 100644 index 781d6aab8..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/239-ath11k-Increment-pending_mgmt_tx-before-tx-send.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 2e78fb74a8521a73d072a7732ce7e71370475898 Mon Sep 17 00:00:00 2001 -From: Lavanya Suresh -Date: Mon, 8 Feb 2021 15:41:49 +0530 -Subject: [PATCH] ath11k: Increment pending_mgmt_tx before tx send - -Updated to increment 'num_pending_mgmt_tx' count before invoking -send, to avoid 0 value while decrementing in tx completion handler. - - -Signed-off-by: Lavanya Suresh ---- - drivers/net/wireless/ath/ath11k/mac.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -6076,6 +6076,7 @@ static void ath11k_mgmt_over_wmi_tx_work - } - - arvif = ath11k_vif_to_arvif(skb_cb->vif); -+ mutex_lock(&ar->conf_mutex); - if (ar->allocated_vdev_map & (1LL << arvif->vdev_id) && - arvif->is_started) { - atomic_inc(&ar->num_pending_mgmt_tx); -@@ -6095,6 +6096,7 @@ static void ath11k_mgmt_over_wmi_tx_work - arvif->is_started); - ieee80211_free_txskb(ar->hw, skb); - } -+ mutex_unlock(&ar->conf_mutex); - } - } - diff --git a/feeds/ipq95xx/mac80211/patches/qca/239-ath11k-cfr-for-qcn9000.patch b/feeds/ipq95xx/mac80211/patches/qca/239-ath11k-cfr-for-qcn9000.patch index 96efdca42..3189c0cce 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/239-ath11k-cfr-for-qcn9000.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/239-ath11k-cfr-for-qcn9000.patch @@ -517,7 +517,7 @@ Signed-off-by: Venkateswara Naralasetty if (cfr_capture_enable > WMI_PEER_CFR_CAPTURE_ENABLE || - cfr_capture_bw > WMI_PEER_CFR_CAPTURE_BW_80MHZ || - cfr_capture_bw > sta->bandwidth || + cfr_capture_bw > sta->deflink.bandwidth || cfr_capture_method > CFR_CAPURE_METHOD_NULL_FRAME_WITH_PHASE || cfr_capture_period > WMI_PEER_CFR_PERIODICITY_MAX) { --- a/drivers/net/wireless/ath/ath11k/hw.c diff --git a/feeds/ipq95xx/mac80211/patches/qca/244-ath11k-dp-tx-perf.patch b/feeds/ipq95xx/mac80211/patches/qca/244-ath11k-dp-tx-perf.patch index 8a20fe228..1c1f60e2c 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/244-ath11k-dp-tx-perf.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/244-ath11k-dp-tx-perf.patch @@ -26,7 +26,7 @@ Signed-off-by: P Praneesh --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -112,6 +112,7 @@ static inline enum wme_ac ath11k_tid_to_ +@@ -135,6 +135,7 @@ static inline enum wme_ac ath11k_tid_to_ enum ath11k_skb_flags { ATH11K_SKB_HW_80211_ENCAP = BIT(0), ATH11K_SKB_CIPHER_SET = BIT(1), @@ -34,7 +34,7 @@ Signed-off-by: P Praneesh }; struct ath11k_skb_cb { -@@ -870,10 +871,16 @@ struct ath11k_dp_ring_bp_stats { +@@ -976,10 +977,16 @@ struct ath11k_dp_ring_bp_stats { struct ath11k_soc_dp_tx_err_stats { /* TCL Ring Descriptor unavailable */ u32 desc_na[DP_TCL_NUM_RING_MAX]; @@ -53,7 +53,7 @@ Signed-off-by: P Praneesh struct ath11k_soc_dp_stats { --- a/drivers/net/wireless/ath/ath11k/dp.c +++ b/drivers/net/wireless/ath/ath11k/dp.c -@@ -362,7 +362,7 @@ void ath11k_dp_stop_shadow_timers(struct +@@ -365,7 +365,7 @@ void ath11k_dp_stop_shadow_timers(struct if (!ab->hw_params.supports_shadow_regs) return; @@ -62,7 +62,7 @@ Signed-off-by: P Praneesh ath11k_dp_shadow_stop_timer(ab, &ab->dp.tx_ring_timer[i]); ath11k_dp_shadow_stop_timer(ab, &ab->dp.reo_cmd_timer); -@@ -377,7 +377,7 @@ static void ath11k_dp_srng_common_cleanu +@@ -380,7 +380,7 @@ static void ath11k_dp_srng_common_cleanu 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); @@ -71,7 +71,7 @@ Signed-off-by: P Praneesh ath11k_dp_srng_cleanup(ab, &dp->tx_ring[i].tcl_data_ring); ath11k_dp_srng_cleanup(ab, &dp->tx_ring[i].tcl_comp_ring); } -@@ -410,6 +410,11 @@ static int ath11k_dp_srng_common_setup(s +@@ -413,6 +413,11 @@ static int ath11k_dp_srng_common_setup(s goto err; } @@ -83,7 +83,7 @@ Signed-off-by: P Praneesh ret = ath11k_dp_srng_setup(ab, &dp->tcl_status_ring, HAL_TCL_STATUS, 0, 0, DP_TCL_STATUS_RING_SIZE); if (ret) { -@@ -417,7 +422,7 @@ static int ath11k_dp_srng_common_setup(s +@@ -420,7 +425,7 @@ static int ath11k_dp_srng_common_setup(s goto err; } @@ -92,7 +92,7 @@ Signed-off-by: P Praneesh ret = ath11k_dp_srng_setup(ab, &dp->tx_ring[i].tcl_data_ring, HAL_TCL_DATA, i, 0, DP_TCL_DATA_RING_SIZE); -@@ -437,7 +442,7 @@ static int ath11k_dp_srng_common_setup(s +@@ -440,7 +445,7 @@ static int ath11k_dp_srng_common_setup(s } srng = &ab->hal.srng_list[dp->tx_ring[i].tcl_data_ring.ring_id]; @@ -101,7 +101,7 @@ Signed-off-by: P Praneesh ath11k_dp_shadow_init_timer(ab, &dp->tx_ring_timer[i], ATH11K_SHADOW_DP_TIMER_INTERVAL, -@@ -1060,7 +1065,7 @@ void ath11k_dp_free(struct ath11k_base * +@@ -1063,7 +1068,7 @@ void ath11k_dp_free(struct ath11k_base * ath11k_dp_reo_cmd_list_cleanup(ab); @@ -110,7 +110,7 @@ Signed-off-by: P Praneesh spin_lock_bh(&dp->tx_ring[i].tx_idr_lock); idr_for_each(&dp->tx_ring[i].txbuf_idr, ath11k_dp_tx_pending_cleanup, ab); -@@ -1112,7 +1117,7 @@ int ath11k_dp_alloc(struct ath11k_base * +@@ -1115,7 +1120,7 @@ int ath11k_dp_alloc(struct ath11k_base * size = sizeof(struct hal_wbm_release_ring) * DP_TX_COMP_RING_SIZE; @@ -121,7 +121,7 @@ Signed-off-by: P Praneesh dp->tx_ring[i].tcl_data_ring_id = i; --- a/drivers/net/wireless/ath/ath11k/dp_tx.c +++ b/drivers/net/wireless/ath/ath11k/dp_tx.c -@@ -123,7 +123,7 @@ int ath11k_dp_tx(struct ath11k *ar, stru +@@ -132,7 +132,7 @@ int ath11k_dp_tx(struct ath11k *ar, stru int ret; u8 ring_selector = 0, ring_map = 0; bool tcl_ring_retry, is_diff_encap = false; @@ -130,7 +130,7 @@ Signed-off-by: P Praneesh if (unlikely(test_bit(ATH11K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))) return -ESHUTDOWN; -@@ -132,6 +132,7 @@ int ath11k_dp_tx(struct ath11k *ar, stru +@@ -141,6 +141,7 @@ int ath11k_dp_tx(struct ath11k *ar, stru !ieee80211_is_data(hdr->frame_control))) return -ENOTSUPP; @@ -138,7 +138,7 @@ Signed-off-by: P Praneesh pool_id = skb_get_queue_mapping(skb) & (ATH11K_HW_MAX_QUEUES - 1); /* Let the default ring selection be based on current processor -@@ -141,16 +142,25 @@ int ath11k_dp_tx(struct ath11k *ar, stru +@@ -150,16 +151,25 @@ int ath11k_dp_tx(struct ath11k *ar, stru * If all rings are full, we drop the packet. * //TODO Add throttling logic when all rings are full */ @@ -167,7 +167,7 @@ Signed-off-by: P Praneesh spin_lock_bh(&tx_ring->tx_idr_lock); ret = idr_alloc(&tx_ring->txbuf_idr, skb, 0, -@@ -158,8 +168,8 @@ tcl_ring_sel: +@@ -167,8 +177,8 @@ tcl_ring_sel: spin_unlock_bh(&tx_ring->tx_idr_lock); if (unlikely(ret < 0)) { @@ -178,7 +178,7 @@ Signed-off-by: P Praneesh return -ENOSPC; } -@@ -274,6 +284,11 @@ tcl_ring_sel: +@@ -279,6 +289,11 @@ tcl_ring_sel: ti.encrypt_type = HAL_ENCRYPT_TYPE_OPEN; } @@ -190,7 +190,7 @@ Signed-off-by: P Praneesh ti.paddr = dma_map_single(ab->dev, skb->data, skb->len, DMA_TO_DEVICE); if (unlikely(dma_mapping_error(ab->dev, ti.paddr))) { atomic_inc(&ab->soc_stats.tx_err.misc_fail); -@@ -282,13 +297,13 @@ tcl_ring_sel: +@@ -287,13 +302,13 @@ tcl_ring_sel: goto fail_remove_idr; } @@ -209,7 +209,7 @@ Signed-off-by: P Praneesh tcl_ring = &ab->hal.srng_list[hal_ring_id]; spin_lock_bh(&tcl_ring->lock); -@@ -301,7 +316,7 @@ tcl_ring_sel: +@@ -306,7 +321,7 @@ tcl_ring_sel: * desc because the desc is directly enqueued onto hw queue. */ ath11k_hal_srng_access_end(ab, tcl_ring); @@ -218,7 +218,7 @@ Signed-off-by: P Praneesh spin_unlock_bh(&tcl_ring->lock); ret = -ENOMEM; -@@ -310,8 +325,8 @@ tcl_ring_sel: +@@ -315,8 +330,8 @@ tcl_ring_sel: * checking this ring earlier for each pkt tx. * Restart ring selection if some rings are not checked yet. */ @@ -229,7 +229,7 @@ Signed-off-by: P Praneesh tcl_ring_retry = true; ring_selector++; } -@@ -322,17 +337,17 @@ tcl_ring_sel: +@@ -327,17 +342,17 @@ tcl_ring_sel: ath11k_hal_tx_cmd_desc_setup(ab, hal_tcl_desc + sizeof(struct hal_tlv_hdr), &ti); @@ -250,7 +250,7 @@ Signed-off-by: P Praneesh return 0; -@@ -379,7 +394,6 @@ static void ath11k_dp_tx_free_txbuf(stru +@@ -384,7 +399,6 @@ static void ath11k_dp_tx_free_txbuf(stru ar = ab->pdevs[mac_id].ar; if (atomic_dec_and_test(&ar->dp.num_tx_pending)) wake_up(&ar->dp.tx_empty_waitq); @@ -258,7 +258,7 @@ Signed-off-by: P Praneesh } static void -@@ -411,16 +425,30 @@ ath11k_dp_tx_htt_tx_complete_buf(struct +@@ -416,16 +430,30 @@ ath11k_dp_tx_htt_tx_complete_buf(struct if (atomic_dec_and_test(&ar->dp.num_tx_pending)) wake_up(&ar->dp.tx_empty_waitq); @@ -291,20 +291,8 @@ Signed-off-by: P Praneesh - flags = skb_cb->flags; vif = skb_cb->vif; - if ( skb_cb->pkt_offset > 0 ) -@@ -609,9 +637,10 @@ static void ath11k_dp_tx_complete_msdu(s - struct ath11k_peer *peer; - struct ath11k_sta *arsta; - struct ieee80211_vif *vif; -+ struct rate_info rate; - u8 flags = 0; - -- if (WARN_ON_ONCE(ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM)) { -+ if (unlikely(WARN_ON_ONCE(ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM))) { - /* Must not happen */ - return; - } -@@ -620,6 +649,22 @@ static void ath11k_dp_tx_complete_msdu(s + if (skb_cb->pkt_offset) +@@ -628,6 +656,22 @@ static void ath11k_dp_tx_complete_msdu(s dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); @@ -327,7 +315,7 @@ Signed-off-by: P Praneesh if (unlikely(!rcu_access_pointer(ab->pdevs_active[ar->pdev_idx]))) { dev_kfree_skb_any(msdu); return; -@@ -630,7 +675,6 @@ static void ath11k_dp_tx_complete_msdu(s +@@ -638,7 +682,6 @@ static void ath11k_dp_tx_complete_msdu(s return; } @@ -335,7 +323,7 @@ Signed-off-by: P Praneesh vif = skb_cb->vif; info = IEEE80211_SKB_CB(msdu); -@@ -682,7 +726,7 @@ static void ath11k_dp_tx_complete_msdu(s +@@ -685,7 +728,7 @@ static void ath11k_dp_tx_complete_msdu(s spin_lock_bh(&ab->base_lock); peer = ath11k_peer_find_by_id(ab, ts->peer_id); @@ -344,24 +332,7 @@ Signed-off-by: P Praneesh ath11k_dbg(ab, ATH11K_DBG_DATA, "dp_tx: failed to find the peer with peer_id %d\n", ts->peer_id); -@@ -694,12 +738,14 @@ static void ath11k_dp_tx_complete_msdu(s - status.sta = peer->sta; - status.skb = msdu; - status.info = info; -- status.rate = &arsta->last_txrate; -+ rate = arsta->last_txrate; -+ status.rate = &rate; -+ -+ spin_unlock_bh(&ab->base_lock); - if (flags & ATH11K_SKB_HW_80211_ENCAP) - ieee80211_tx_status_8023(ar->hw, vif, msdu); - else - ieee80211_tx_status_ext(ar->hw, &status); -- spin_unlock_bh(&ab->base_lock); - return; - } - -@@ -734,19 +780,36 @@ static inline void ath11k_dp_tx_status_p +@@ -744,19 +787,36 @@ static inline void ath11k_dp_tx_status_p ts->rate_stats = 0; } @@ -400,7 +371,7 @@ Signed-off-by: P Praneesh spin_lock_bh(&status_ring->lock); -@@ -761,33 +824,27 @@ void ath11k_dp_tx_completion_handler(str +@@ -771,33 +831,27 @@ void ath11k_dp_tx_completion_handler(str ath11k_hal_srng_dst_invalidate_entry(ab, status_ring, valid_entries); @@ -448,7 +419,7 @@ Signed-off-by: P Praneesh ath11k_dp_tx_status_parse(ab, tx_status, &ts); desc_id = FIELD_GET(BUFFER_ADDR_INFO1_SW_COOKIE, -@@ -820,7 +877,6 @@ void ath11k_dp_tx_completion_handler(str +@@ -830,7 +884,6 @@ void ath11k_dp_tx_completion_handler(str wake_up(&ar->dp.tx_empty_waitq); ath11k_dp_tx_complete_msdu(ar, msdu, &ts); @@ -458,7 +429,7 @@ Signed-off-by: P Praneesh --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -6536,12 +6536,22 @@ static void ath11k_mac_op_tx(struct ieee +@@ -6502,12 +6502,22 @@ static void ath11k_mac_op_tx(struct ieee if (control->sta) arsta = (struct ath11k_sta *)control->sta->drv_priv; @@ -482,7 +453,7 @@ Signed-off-by: P Praneesh ieee80211_free_txskb(ar->hw, skb); return; } -@@ -7415,7 +7425,7 @@ err_vdev_del: +@@ -7406,7 +7416,7 @@ err_vdev_del: idr_for_each(&ar->txmgmt_idr, ath11k_mac_vif_txmgmt_idr_remove, vif); @@ -493,7 +464,7 @@ Signed-off-by: P Praneesh ath11k_mac_vif_unref, vif); --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -1442,10 +1442,22 @@ static ssize_t ath11k_debugfs_dump_soc_d +@@ -1286,10 +1286,22 @@ static ssize_t ath11k_debugfs_dump_soc_d len += scnprintf(buf + len, size - len, "ring%d: %u\n", i, soc_stats->tx_err.desc_na[i]); @@ -518,7 +489,7 @@ Signed-off-by: P Praneesh if (len > size) --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -128,7 +128,6 @@ static const struct ath11k_hw_params ath +@@ -126,22 +126,12 @@ static const struct ath11k_hw_params ath .supports_regdb = false, .fix_l1ss = true, .credit_flow = false, @@ -526,7 +497,6 @@ Signed-off-by: P Praneesh .hal_params = &ath11k_hw_hal_params_ipq8074, .supports_dynamic_smps_6ghz = false, .alloc_cacheable_memory = true, -@@ -136,18 +135,11 @@ static const struct ath11k_hw_params ath .ce_fwlog_enable = false, .fwmem_mode_change = false, .is_qdss_support = false, @@ -542,21 +512,25 @@ Signed-off-by: P Praneesh .supports_rssi_stats = false, .fw_wmi_diag_event = false, .current_cc_support = false, +@@ -155,6 +145,8 @@ static const struct ath11k_hw_params ath + .hybrid_bus_type = false, + .fixed_fw_mem = false, + .support_off_channel_tx = false, + /* In addition to TCL ring use TCL_CMD ring also for tx */ + .max_tx_ring = DP_TCL_NUM_RING_MAX + 1, }, { .hw_rev = ATH11K_HW_IPQ6018_HW10, -@@ -220,6 +212,8 @@ static const struct ath11k_hw_params ath - .supports_rssi_stats = false, - .fw_wmi_diag_event = false, - .current_cc_support = false, +@@ -233,6 +225,8 @@ static const struct ath11k_hw_params ath + .hybrid_bus_type = false, + .fixed_fw_mem = false, + .support_off_channel_tx = false, + /* In addition to TCL ring use TCL_CMD ring also for tx */ + .max_tx_ring = DP_TCL_NUM_RING_MAX + 1, }, { .name = "qca6390 hw2.0", -@@ -348,7 +342,6 @@ static const struct ath11k_hw_params ath +@@ -364,7 +358,6 @@ static const struct ath11k_hw_params ath .supports_regdb = false, .fix_l1ss = true, .credit_flow = false, @@ -564,10 +538,10 @@ Signed-off-by: P Praneesh .hal_params = &ath11k_hw_hal_params_ipq8074, .supports_dynamic_smps_6ghz = true, .alloc_cacheable_memory = true, -@@ -359,6 +352,18 @@ static const struct ath11k_hw_params ath - .supports_rssi_stats = false, - .fw_wmi_diag_event = false, - .current_cc_support = false, +@@ -384,6 +377,17 @@ static const struct ath11k_hw_params ath + .hybrid_bus_type = false, + .fixed_fw_mem = false, + .support_off_channel_tx = false, + .cfr_support = true, + .cfr_dma_hdr_size = sizeof(struct ath11k_cfir_enh_dma_hdr), + .cfr_num_stream_bufs = 255, @@ -575,15 +549,14 @@ Signed-off-by: P Praneesh + * max cfr payload(16384 bytes) + */ + .cfr_stream_buf_size = sizeof(struct ath11k_csi_cfr_header) + -+ (CFR_HDR_MAX_LEN_WORDS_QCN9074 *4) + -+ CFR_DATA_MAX_LEN_QCN9074, -+ ++ (CFR_HDR_MAX_LEN_WORDS_QCN9074 *4) + ++ CFR_DATA_MAX_LEN_QCN9074, + /* In addition to TCL ring use TCL_CMD ring also for tx */ + .max_tx_ring = DP_TCL_NUM_RING_MAX + 1, }, { .name = "wcn6855 hw2.0", -@@ -560,6 +565,8 @@ static const struct ath11k_hw_params ath +@@ -678,6 +682,8 @@ static const struct ath11k_hw_params ath .cfr_num_stream_bufs = 255, /* csi_cfr_header + cfr header + max cfr payload */ .cfr_stream_buf_size = 8500, @@ -592,15 +565,15 @@ Signed-off-by: P Praneesh }, { .hw_rev = ATH11K_HW_QCN6122, -@@ -614,6 +621,7 @@ static const struct ath11k_hw_params ath - .ce_fwlog_enable = false, - .fwmem_mode_change = false, - .is_qdss_support = false, +@@ -749,6 +755,7 @@ static const struct ath11k_hw_params ath + .m3_offset = ATH11K_QMI_QCN6122_M3_OFFSET, + .qdss_offset = ATH11K_QMI_QCN6122_QDSS_OFFSET, + .caldb_offset = ATH11K_QMI_QCN6122_CALDB_OFFSET, + .max_tx_ring = DP_TCL_NUM_RING_MAX, }, }; -@@ -1809,6 +1817,9 @@ int ath11k_core_pre_init(struct ath11k_b +@@ -2152,6 +2159,9 @@ int ath11k_core_pre_init(struct ath11k_b ab->enable_memory_stats = ATH11K_DEBUG_ENABLE_MEMORY_STATS; diff --git a/feeds/ipq95xx/mac80211/patches/qca/245-compilation_fix.patch b/feeds/ipq95xx/mac80211/patches/qca/245-compilation_fix.patch index aa4c4929a..ef51acceb 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/245-compilation_fix.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/245-compilation_fix.patch @@ -63,36 +63,13 @@ Signed-off-by: Tamizh Chelvam ath11k_hal_rx_buf_addr_info_set(desc, paddr, cookie, 0); -- ath11k_dbring_add_debug_entry(ar, id, DBR_RING_DEBUG_EVENT_REPLENISH, srng); +- ath11k_debugfs_add_dbring_entry(ar, id, ATH11K_DBG_DBR_EVENT_REPLENISH, srng); ath11k_hal_srng_access_end(ab, srng); return 0; -@@ -358,9 +357,6 @@ int ath11k_dbring_buffer_release_event(s - dma_unmap_single(ab->dev, buff->paddr, ring->buf_sz, - DMA_FROM_DEVICE); - -- ath11k_dbring_add_debug_entry(ar, module_id, -- DBR_RING_DEBUG_EVENT_RX, srng); -- - if (ring->handler) { - vaddr_unalign = buff->payload; - handler_data.data = PTR_ALIGN(vaddr_unalign, ---- a/drivers/net/wireless/ath/ath11k/debug.h -+++ b/drivers/net/wireless/ath/ath11k/debug.h -@@ -23,8 +23,8 @@ enum ath11k_debug_mask { - ATH11K_DBG_TESTMODE = 0x00000400, - ATH11k_DBG_HAL = 0x00000800, - ATH11K_DBG_PCI = 0x00001000, -- ATH11K_DBG_DP_TX = 0x00001000, -- ATH11K_DBG_DP_RX = 0x00002000, -+ ATH11K_DBG_DP_TX = 0x00002000, -+ ATH11K_DBG_DP_RX = 0x00004000, - ATH11K_DBG_CFR = 0x00008000, - ATH11K_DBG_CFR_DUMP = 0x00010000, - ATH11K_DBG_ANY = 0xffffffff, --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -2875,7 +2875,7 @@ static void ath11k_dp_rx_deliver_msdu(st +@@ -2895,7 +2895,7 @@ static void ath11k_dp_rx_deliver_msdu(st spin_unlock_bh(&ar->ab->base_lock); ath11k_dbg(ar->ab, ATH11K_DBG_DATA, @@ -103,9 +80,9 @@ Signed-off-by: Tamizh Chelvam peer ? peer->addr : NULL, --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -2188,6 +2188,12 @@ static void ath11k_peer_assoc_h_he(struc +@@ -2199,6 +2199,12 @@ static void ath11k_peer_assoc_h_he(struc - arg->peer_nss = min(sta->rx_nss, max_nss); + arg->peer_nss = min(sta->deflink.rx_nss, max_nss); +#if LINUX_VERSION_IS_LESS(5,16,0) + memcpy(&arg->peer_he_cap_macinfo, he_cap->he_cap_elem.mac_cap_info, @@ -116,7 +93,7 @@ Signed-off-by: Tamizh Chelvam memcpy_and_pad(&arg->peer_he_cap_macinfo, sizeof(arg->peer_he_cap_macinfo), he_cap->he_cap_elem.mac_cap_info, -@@ -2198,6 +2204,7 @@ static void ath11k_peer_assoc_h_he(struc +@@ -2209,6 +2215,7 @@ static void ath11k_peer_assoc_h_he(struc he_cap->he_cap_elem.phy_cap_info, sizeof(he_cap->he_cap_elem.phy_cap_info), 0); @@ -124,7 +101,7 @@ Signed-off-by: Tamizh Chelvam arg->peer_he_ops = vif->bss_conf.he_oper.params; /* the top most byte is used to indicate BSS color info */ -@@ -7038,7 +7045,7 @@ static int ath11k_mac_op_add_interface(s +@@ -7032,7 +7039,7 @@ static int ath11k_mac_op_add_interface(s if ((vif->type == NL80211_IFTYPE_AP_VLAN || vif->type == NL80211_IFTYPE_STATION) && ab->nss.enabled) { if (ath11k_frame_mode == ATH11K_HW_TXRX_ETHERNET && @@ -133,7 +110,7 @@ Signed-off-by: Tamizh Chelvam vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR; arvif->nss.encap = ATH11K_HW_TXRX_ETHERNET; arvif->nss.decap = ATH11K_HW_TXRX_ETHERNET; -@@ -9251,6 +9258,8 @@ static void ath11k_mac_update_ch_list(st +@@ -9634,6 +9641,8 @@ static void ath11k_mac_update_ch_list(st band->channels[i].center_freq > freq_high) band->channels[i].flags |= IEEE80211_CHAN_DISABLED; } @@ -144,7 +121,7 @@ Signed-off-by: Tamizh Chelvam #define ATH11k_5_DOT_9_MIN_FREQ 5845 --- a/drivers/net/wireless/ath/ath11k/mhi.c +++ b/drivers/net/wireless/ath/ath11k/mhi.c -@@ -389,7 +389,7 @@ int ath11k_mhi_register(struct ath11k_pc +@@ -393,7 +393,7 @@ int ath11k_mhi_register(struct ath11k_pc struct mhi_controller_config *ath11k_mhi_config; int ret; @@ -153,7 +130,7 @@ Signed-off-by: Tamizh Chelvam if (!mhi_ctrl) return -ENOMEM; -@@ -409,7 +409,7 @@ int ath11k_mhi_register(struct ath11k_pc +@@ -413,7 +413,7 @@ int ath11k_mhi_register(struct ath11k_pc ret = ath11k_mhi_get_msi(ab_pci); if (ret) { ath11k_err(ab, "failed to get msi for mhi\n"); @@ -162,7 +139,7 @@ Signed-off-by: Tamizh Chelvam return ret; } -@@ -457,7 +457,7 @@ int ath11k_mhi_register(struct ath11k_pc +@@ -461,7 +461,7 @@ int ath11k_mhi_register(struct ath11k_pc ret = mhi_register_controller(mhi_ctrl, ath11k_mhi_config); if (ret) { ath11k_err(ab, "failed to register to mhi bus, err = %d\n", ret); @@ -171,28 +148,29 @@ Signed-off-by: Tamizh Chelvam return ret; } -@@ -626,7 +626,7 @@ static int ath11k_mhi_set_state(struct a - * are not in M3 state but they are functional. So just ignore - * the MHI state while resuming. - */ -- ret = mhi_pm_resume_force(ab_pci->mhi_ctrl); -+ // ret = mhi_pm_resume_force(ab_pci->mhi_ctrl); - break; - case ATH11K_MHI_TRIGGER_RDDM: - ret = mhi_force_rddm_mode(ab_pci->mhi_ctrl); +@@ -528,7 +528,8 @@ int ath11k_mhi_resume(struct ath11k_pci + * are not in M3 state but they are functional. So just ignore + * the MHI state while resuming. + */ +- ret = mhi_pm_resume_force(ab_pci->mhi_ctrl); ++ //ret = mhi_pm_resume_force(ab_pci->mhi_ctrl); ++ ret = 0; + if (ret) { + ath11k_warn(ab, "failed to resume mhi: %d", ret); + return ret; --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c -@@ -769,7 +769,6 @@ static int ath11k_pci_power_up(struct at +@@ -586,7 +586,6 @@ static int ath11k_pci_power_up(struct at { struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); int ret; - u32 addr; ab_pci->register_window = 0; - clear_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags); + clear_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags); --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c -@@ -2901,11 +2901,6 @@ static int ath11k_qmi_assign_target_mem_ +@@ -2919,11 +2919,6 @@ static int ath11k_qmi_assign_target_mem_ idx++; break; case CALDB_MEM_REGION_TYPE: @@ -245,7 +223,7 @@ Signed-off-by: Tamizh Chelvam u32 memory_usage; --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h -@@ -203,6 +203,7 @@ enum ieee80211_rx_flags { +@@ -210,6 +210,7 @@ enum ieee80211_rx_flags { }; struct ieee80211_rx_data { @@ -253,7 +231,7 @@ Signed-off-by: Tamizh Chelvam #if LINUX_VERSION_IS_GEQ(4,19,0) struct list_head *list; #else -@@ -286,6 +287,7 @@ struct unsol_bcast_probe_resp_data { +@@ -297,6 +298,7 @@ struct unsol_bcast_probe_resp_data { u8 data[]; }; @@ -263,7 +241,7 @@ Signed-off-by: Tamizh Chelvam * bitmap_empty :) --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c -@@ -1664,7 +1664,6 @@ static void ieee80211_iface_work(struct +@@ -1934,7 +1934,6 @@ static void ieee80211_iface_work(struct /* first process frames */ while ((skb = skb_dequeue(&sdata->skb_queue))) { @@ -271,7 +249,7 @@ Signed-off-by: Tamizh Chelvam if (skb->protocol == cpu_to_be16(ETH_P_TDLS)) ieee80211_process_tdls_channel_switch(sdata, skb); -@@ -1672,17 +1671,14 @@ static void ieee80211_iface_work(struct +@@ -1942,17 +1941,14 @@ static void ieee80211_iface_work(struct ieee80211_iface_process_skb(local, sdata, skb); kfree_skb(skb); @@ -291,23 +269,29 @@ Signed-off-by: Tamizh Chelvam /* then other type-dependent work */ --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c -@@ -4545,19 +4545,20 @@ static void ieee80211_8023_xmit(struct i +@@ -4561,20 +4561,22 @@ static void ieee80211_8023_xmit(struct i + ieee80211_aggr_check(sdata, sta, skb); - tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; +- tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; - tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]); - if (tid_tx) { - if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) { - /* fall back to non-offload slow path */ -- __ieee80211_subif_start_xmit(skb, dev, 0, 0, NULL); +- __ieee80211_subif_start_xmit(skb, dev, 0, +- IEEE80211_TX_CTRL_MLO_LINK_UNSPEC, +- NULL); - return; - } + if (!ieee80211_hw_check(&local->hw, SUPPORTS_NSS_OFFLOAD)) { ++ tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; + tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]); + if (tid_tx) { + if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) { + /* fall back to non-offload slow path */ -+ __ieee80211_subif_start_xmit(skb, dev, 0, 0, NULL); ++ __ieee80211_subif_start_xmit(skb, dev, 0, ++ IEEE80211_TX_CTRL_MLO_LINK_UNSPEC, ++ NULL); + return; + } @@ -319,11 +303,9 @@ Signed-off-by: Tamizh Chelvam + tid_tx->last_tx = jiffies; + } } -- + if (unlikely(skb->sk && - skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS && - !ieee80211_hw_check(&local->hw, SUPPORTS_NSS_OFFLOAD))) -@@ -4600,7 +4601,7 @@ netdev_tx_t ieee80211_subif_start_xmit_8 +@@ -4619,7 +4621,7 @@ netdev_tx_t ieee80211_subif_start_xmit_8 { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ethhdr *ehdr = (struct ethhdr *)skb->data; @@ -332,7 +314,7 @@ Signed-off-by: Tamizh Chelvam struct sta_info *sta; #ifdef CPTCFG_MAC80211_NSS_SUPPORT -@@ -4618,9 +4619,13 @@ netdev_tx_t ieee80211_subif_start_xmit_8 +@@ -4637,9 +4639,13 @@ netdev_tx_t ieee80211_subif_start_xmit_8 goto out; } @@ -349,7 +331,7 @@ Signed-off-by: Tamizh Chelvam goto skip_offload; key = rcu_dereference(sta->ptk[sta->ptk_idx]); -@@ -4630,6 +4635,7 @@ netdev_tx_t ieee80211_subif_start_xmit_8 +@@ -4649,6 +4655,7 @@ netdev_tx_t ieee80211_subif_start_xmit_8 if (key && (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))) goto skip_offload; @@ -357,7 +339,7 @@ Signed-off-by: Tamizh Chelvam ieee80211_8023_xmit(sdata, dev, sta, key, skb); goto out; -@@ -5867,13 +5873,7 @@ int ieee80211_tx_control_port(struct wip +@@ -6003,13 +6010,7 @@ int ieee80211_tx_control_port(struct wip mutex_lock(&local->mtx); local_bh_disable(); @@ -374,7 +356,7 @@ Signed-off-by: Tamizh Chelvam mutex_unlock(&local->mtx); --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c -@@ -4988,7 +4988,7 @@ void ieee80211_rx_list(struct ieee80211_ +@@ -5105,7 +5105,7 @@ void ieee80211_rx_list(struct ieee80211_ if (pubsta) { sta = container_of(pubsta, struct sta_info, sta); @@ -383,7 +365,7 @@ Signed-off-by: Tamizh Chelvam if (!(status->flag & RX_FLAG_ONLY_MONITOR)) atomic_inc(&sta->rx_drv_pkts); } -@@ -5080,8 +5080,6 @@ void ieee80211_rx_list(struct ieee80211_ +@@ -5197,8 +5197,6 @@ void ieee80211_rx_list(struct ieee80211_ status->rx_flags = 0; @@ -392,7 +374,7 @@ Signed-off-by: Tamizh Chelvam /* * Frames with failed FCS/PLCP checksum are not returned, * all other frames are returned without radiotap header -@@ -5101,7 +5099,6 @@ void ieee80211_rx_list(struct ieee80211_ +@@ -5218,7 +5216,6 @@ void ieee80211_rx_list(struct ieee80211_ __ieee80211_rx_handle_packet(hw, pubsta, skb, list); } diff --git a/feeds/ipq95xx/mac80211/patches/qca/300-ath11k-nss-mesh-offload-support.patch b/feeds/ipq95xx/mac80211/patches/qca/300-ath11k-nss-mesh-offload-support.patch index 96030e43a..53153e4f0 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/300-ath11k-nss-mesh-offload-support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/300-ath11k-nss-mesh-offload-support.patch @@ -47,7 +47,7 @@ Signed-off-by: Vasanthakumar Thiagarajan --- a/drivers/net/wireless/ath/ath11k/Makefile +++ b/drivers/net/wireless/ath/ath11k/Makefile @@ -20,7 +20,7 @@ ath11k-y += core.o \ - wow.o \ + pcic.o \ vendor.o -ath11k-$(CPTCFG_ATH11K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o @@ -1022,8 +1022,8 @@ Signed-off-by: Vasanthakumar Thiagarajan +#endif --- a/drivers/net/wireless/ath/ath11k/dp.h +++ b/drivers/net/wireless/ath/ath11k/dp.h -@@ -1529,15 +1529,29 @@ struct htt_ppdu_stats_usr_cmn_array { - struct htt_tx_ppdu_stats_info tx_ppdu_info[0]; +@@ -1522,15 +1522,29 @@ struct htt_ppdu_stats_usr_cmn_array { + struct htt_tx_ppdu_stats_info tx_ppdu_info[]; } __packed; +#define HTT_PPDU_STATS_CMPLTN_FLUSH_INFO_FLOW_TYPE GENMASK(7, 0) @@ -1054,7 +1054,7 @@ Signed-off-by: Vasanthakumar Thiagarajan #define HTT_PPDU_STATS_MAX_USERS 37 --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -1445,6 +1445,68 @@ static int ath11k_htt_tlv_ppdu_stats_par +@@ -1446,6 +1446,68 @@ static int ath11k_htt_tlv_ppdu_stats_par return 0; } @@ -1089,7 +1089,7 @@ Signed-off-by: Vasanthakumar Thiagarajan + memset(&status, 0, sizeof(status)); + + status.sta = sta; -+ status.rate = &arsta->last_txrate; ++ status.rates = &arsta->last_txrate; + status.mpdu_fail = FIELD_GET(HTT_PPDU_STATS_CMPLTN_FLUSH_INFO_NUM_MPDU, + msg->info); + ar = arsta->arvif->ar; @@ -1123,7 +1123,7 @@ Signed-off-by: Vasanthakumar Thiagarajan static void ath11k_update_per_peer_tx_stats(struct ath11k *ar, struct htt_ppdu_stats *ppdu_stats, u8 user) -@@ -1471,6 +1533,9 @@ ath11k_update_per_peer_tx_stats(struct a +@@ -1472,6 +1534,9 @@ ath11k_update_per_peer_tx_stats(struct a if (!(usr_stats->tlv_flags & BIT(HTT_PPDU_STATS_TAG_USR_RATE))) return; @@ -1133,7 +1133,7 @@ Signed-off-by: Vasanthakumar Thiagarajan if (usr_stats->tlv_flags & BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_COMMON)) is_ampdu = HTT_USR_CMPLTN_IS_AMPDU(usr_stats->cmpltn_cmn.flags); -@@ -1604,6 +1669,8 @@ ath11k_update_per_peer_tx_stats(struct a +@@ -1605,6 +1670,8 @@ ath11k_update_per_peer_tx_stats(struct a ath11k_debugfs_sta_add_tx_stats(arsta, peer_stats, rate_idx); } @@ -1142,7 +1142,7 @@ Signed-off-by: Vasanthakumar Thiagarajan spin_unlock_bh(&ab->base_lock); rcu_read_unlock(); } -@@ -1691,8 +1758,10 @@ int ath11k_dp_htt_tlv_iter(struct ath11k +@@ -1692,8 +1759,10 @@ int ath11k_dp_htt_tlv_iter(struct ath11k int ret = -EINVAL; struct htt_ppdu_stats_info * ppdu_info = NULL; @@ -1155,7 +1155,7 @@ Signed-off-by: Vasanthakumar Thiagarajan while (len > 0) { if (len < sizeof(*tlv)) { ath11k_err(ab, "htt tlv parse failure at byte %zd (%zu bytes left, %zu expected)\n", -@@ -1721,6 +1790,66 @@ int ath11k_dp_htt_tlv_iter(struct ath11k +@@ -1722,6 +1791,66 @@ int ath11k_dp_htt_tlv_iter(struct ath11k return 0; } @@ -1207,7 +1207,7 @@ Signed-off-by: Vasanthakumar Thiagarajan + memset(&status, 0, sizeof(status)); + + status.sta = sta; -+ status.rate = &arsta->last_txrate; ++ status.rates = &arsta->last_txrate; + status.mpdu_succ = usr_stats->cmpltn_cmn.mpdu_success; + + ieee80211s_update_metric_ppdu(ar->hw, &status); @@ -1222,7 +1222,7 @@ Signed-off-by: Vasanthakumar Thiagarajan static int ath11k_htt_pull_ppdu_stats(struct ath11k_base *ab, struct sk_buff *skb) { -@@ -1739,6 +1868,15 @@ static int ath11k_htt_pull_ppdu_stats(st +@@ -1740,6 +1869,15 @@ static int ath11k_htt_pull_ppdu_stats(st pdev_id = FIELD_GET(HTT_T2H_PPDU_STATS_INFO_PDEV_ID, msg->info); ppdu_id = msg->ppdu_id; @@ -1238,7 +1238,7 @@ Signed-off-by: Vasanthakumar Thiagarajan rcu_read_lock(); ar = ath11k_mac_get_ar_by_pdev_id(ab, pdev_id); if (!ar) { -@@ -1810,6 +1948,12 @@ static int ath11k_htt_pull_ppdu_stats(st +@@ -1811,6 +1949,12 @@ static int ath11k_htt_pull_ppdu_stats(st } } @@ -1251,7 +1251,7 @@ Signed-off-by: Vasanthakumar Thiagarajan spin_unlock_bh(&ar->data_lock); exit: rcu_read_unlock(); -@@ -3098,6 +3242,23 @@ static void ath11k_dp_rx_process_receive +@@ -3099,6 +3243,23 @@ static void ath11k_dp_rx_process_receive } } @@ -1286,7 +1286,7 @@ Signed-off-by: Vasanthakumar Thiagarajan #endif /* ATH11K_DP_RX_H */ --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -3306,6 +3306,16 @@ static void ath11k_mac_op_nss_bss_info_c +@@ -3320,6 +3320,16 @@ static void ath11k_mac_op_nss_bss_info_c ath11k_warn(ar->ab, "failed to set ap_isolate in nss %d\n", ret); } @@ -1303,7 +1303,7 @@ Signed-off-by: Vasanthakumar Thiagarajan mutex_unlock(&ar->conf_mutex); } -@@ -6552,7 +6562,7 @@ static void ath11k_mac_op_tx(struct ieee +@@ -6521,7 +6531,7 @@ static void ath11k_mac_op_tx(struct ieee skb_cb->flags |= ATH11K_SKB_TX_STATUS; if (ar->ab->nss.enabled) @@ -1312,8 +1312,8 @@ Signed-off-by: Vasanthakumar Thiagarajan else ret = ath11k_dp_tx(ar, arvif, arsta, skb); -@@ -9118,6 +9128,28 @@ static void ath11k_mac_op_sta_statistics - ath11k_nss_update_sta_stats(arvif, sinfo, sta); +@@ -9496,6 +9506,28 @@ exit: + return ret; } +#ifdef CPTCFG_MAC80211_MESH @@ -1341,17 +1341,17 @@ Signed-off-by: Vasanthakumar Thiagarajan #define ATH11K_WLAN_PRIO_MAX 0x63 #define ATH11K_WLAN_PRIO_WEIGHT 0xff -@@ -9242,6 +9274,9 @@ static const struct ieee80211_ops ath11k - #ifdef CPTCFG_ATH11K_DEBUGFS - .sta_add_debugfs = ath11k_debugfs_sta_op_add, - #endif +@@ -9636,6 +9668,9 @@ static const struct ieee80211_ops ath11k + .set_sar_specs = ath11k_mac_op_set_bios_sar_specs, + .remain_on_channel = ath11k_mac_op_remain_on_channel, + .cancel_remain_on_channel = ath11k_mac_op_cancel_remain_on_channel, +#ifdef CPTCFG_MAC80211_MESH -+ .config_mesh_offload_path = ath11k_mac_op_config_mesh_offload_path, ++ .config_mesh_offload_path = ath11k_mac_op_config_mesh_offload_path, +#endif }; static void ath11k_mac_update_ch_list(struct ath11k *ar, -@@ -9743,6 +9778,8 @@ static int __ath11k_mac_register(struct +@@ -10164,6 +10199,8 @@ static int __ath11k_mac_register(struct ieee80211_hw_set(ar->hw, SUPPORTS_NSS_OFFLOAD); wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_VLAN_OFFLOAD); @@ -1489,53 +1489,10 @@ Signed-off-by: Vasanthakumar Thiagarajan if (!arvif) { dev_kfree_skb_any(skb); return; -@@ -875,17 +895,1075 @@ ath11k_nss_ext_vdev_data_receive(struct - int data_offs = 0; - int ret; +@@ -917,14 +937,1098 @@ ath11k_nss_ext_vdev_data_receive(struct + ath11k_nss_deliver_rx(arvif->vif, skb, eth_decap, data_offs, napi); + } -- if (!dev) { -+ if (!dev) { -+ dev_kfree_skb_any(skb); -+ return; -+ } -+ -+ wdev = dev->ieee80211_ptr; -+ if (!wdev) { -+ dev_kfree_skb_any(skb); -+ return; -+ } -+ -+ vif = wdev_to_ieee80211_vif(wdev); -+ if (!vif) { -+ dev_kfree_skb_any(skb); -+ return; -+ } -+ -+ arvif = (struct ath11k_vif *)vif->drv_priv; -+ if (!arvif) { -+ dev_kfree_skb_any(skb); -+ return; -+ } -+ -+ ab = arvif->ar->ab; -+ -+ skb->dev = dev; -+ -+ /* log the original skb received from nss */ -+ ath11k_dbg_dump(ab, ATH11K_DBG_DP_RX, "", "dp rx msdu from nss ext : ", -+ skb->data, skb->len); -+ -+ ret = ath11k_nss_undecap(arvif, skb, &data_offs, ð_decap); -+ if (ret) { -+ ath11k_warn(ab, "error in nss ext rx undecap, type %d err %d\n", -+ arvif->nss.decap, ret); -+ dev_kfree_skb_any(skb); -+ return; -+ } -+ -+ ath11k_nss_deliver_rx(arvif->vif, skb, eth_decap, data_offs, napi); -+} -+ +/*------Mesh offload------*/ + +void ath11k_nss_mesh_wifili_event_receive(void *app_data, @@ -2534,18 +2491,16 @@ Signed-off-by: Vasanthakumar Thiagarajan + + vif = wdev_to_ieee80211_vif(wdev); + if (!vif) { - dev_kfree_skb_any(skb); - return; - } - -- wdev = dev->ieee80211_ptr; -- if (!wdev) { ++ dev_kfree_skb_any(skb); ++ return; ++ } ++ + arvif = (struct ath11k_vif *)vif->drv_priv; + if (!arvif) { - dev_kfree_skb_any(skb); - return; - } - ++ dev_kfree_skb_any(skb); ++ return; ++ } ++ + ab = arvif->ar->ab; + ath11k_dbg_dump(ab, ATH11K_DBG_DP_RX, "", "msdu from nss data_receive_cb on mesh link vdev: ", + skb->data, skb->len); @@ -2565,28 +2520,27 @@ Signed-off-by: Vasanthakumar Thiagarajan + struct ath11k_vif *arvif; + struct wireless_dev *wdev = (struct wireless_dev *)dev; + - vif = wdev_to_ieee80211_vif(wdev); - if (!vif) { - dev_kfree_skb_any(skb); -@@ -900,21 +1978,46 @@ ath11k_nss_ext_vdev_data_receive(struct - - ab = arvif->ar->ab; - -- skb->dev = dev; ++ vif = wdev_to_ieee80211_vif(wdev); ++ if (!vif) { ++ dev_kfree_skb_any(skb); ++ return; ++ } ++ ++ arvif = (struct ath11k_vif *)vif->drv_priv; ++ if (!arvif) { ++ dev_kfree_skb_any(skb); ++ return; ++ } ++ ++ ab = arvif->ar->ab; ++ + wifi_metadata = (struct nss_wifi_vdev_per_packet_metadata *)(skb->head + + NSS_WIFI_VDEV_PER_PACKET_METADATA_OFFSET); - -- /* log the original skb received from nss */ -- ath11k_dbg_dump(ab, ATH11K_DBG_DP_RX, "", "dp rx msdu from nss ext : ", -- skb->data, skb->len); ++ + ath11k_dbg(ab, ATH11K_DBG_NSS_MESH, + "dp special data from nss on mesh link vap: pkt_type %d\n", + wifi_metadata->pkt_type); - -- ret = ath11k_nss_undecap(arvif, skb, &data_offs, ð_decap); -- if (ret) { -- ath11k_warn(ab, "error in nss ext rx undecap, type %d err %d\n", -- arvif->nss.decap, ret); ++ + switch (wifi_metadata->pkt_type) { + case NSS_WIFI_VDEV_MESH_EXT_DATA_PKT_TYPE_RX_SPL_PACKET: + ath11k_dbg_dump(ab, ATH11K_DBG_DP_RX, "", @@ -2596,8 +2550,7 @@ Signed-off-by: Vasanthakumar Thiagarajan + ath11k_dbg_dump(ab, ATH11K_DBG_DP_RX, "", + "special packet payload from nss on mesh link vdev: ", + skb->data, skb->len); - dev_kfree_skb_any(skb); -- return; ++ dev_kfree_skb_any(skb); + break; + case NSS_WIFI_VDEV_EXT_DATA_PKT_TYPE_MCBC_RX: + ath11k_dbg_dump(ab, ATH11K_DBG_DP_RX, "", @@ -2620,13 +2573,12 @@ Signed-off-by: Vasanthakumar Thiagarajan + wifi_metadata->pkt_type); + dev_kfree_skb_any(skb); + break; - } -- -- ath11k_nss_deliver_rx(arvif->vif, skb, eth_decap, data_offs, napi); - } - ++ } ++} ++ int ath11k_nss_tx(struct ath11k_vif *arvif, struct sk_buff *skb) -@@ -923,8 +2026,9 @@ int ath11k_nss_tx(struct ath11k_vif *arv + { + struct ath11k *ar = arvif->ar; nss_tx_status_t status; int encap_type = ath11k_dp_tx_get_encap_type(arvif, skb); struct ath11k_soc_dp_stats *soc_stats = &ar->ab->soc_stats; @@ -3102,7 +3054,7 @@ Signed-off-by: Vasanthakumar Thiagarajan vdev_msg = kzalloc(sizeof(struct nss_wifi_vdev_msg), GFP_ATOMIC); if (!vdev_msg) return -ENOMEM; -@@ -2753,6 +4198,49 @@ static int ath11k_nss_get_dynamic_interf +@@ -2750,6 +4195,49 @@ static int ath11k_nss_get_dynamic_interf } } @@ -3152,7 +3104,7 @@ Signed-off-by: Vasanthakumar Thiagarajan static int ath11k_nss_init(struct ath11k_base *ab) { struct nss_wifili_init_msg *wim = NULL; -@@ -2887,6 +4375,15 @@ static int ath11k_nss_init(struct ath11k +@@ -2884,6 +4372,15 @@ static int ath11k_nss_init(struct ath11k kfree(wlmsg); @@ -3194,7 +3146,7 @@ Signed-off-by: Vasanthakumar Thiagarajan /* WIFILI Supported Target Types */ #define ATH11K_WIFILI_TARGET_TYPE_UNKNOWN 0xFF -@@ -60,6 +63,7 @@ struct hal_rx_user_status; +@@ -59,6 +62,7 @@ struct hal_rx_user_status; /* Timeout for waiting for response from NSS on TX msg */ #define ATH11K_NSS_MSG_TIMEOUT_MS 5000 @@ -3202,7 +3154,7 @@ Signed-off-by: Vasanthakumar Thiagarajan /* Init Flags */ #define WIFILI_NSS_CCE_DISABLED 0x1 #define WIFILI_ADDTL_MEM_SEG_SET 0x000000002 -@@ -111,6 +115,8 @@ enum ath11k_nss_vdev_cmd { +@@ -110,6 +114,8 @@ enum ath11k_nss_vdev_cmd { ATH11K_NSS_WIFI_VDEV_CFG_WDS_BACKHAUL_CMD, }; @@ -3211,7 +3163,7 @@ Signed-off-by: Vasanthakumar Thiagarajan enum ath11k_nss_opmode { ATH11K_NSS_OPMODE_UNKNOWN, ATH11K_NSS_OPMODE_AP, -@@ -157,10 +163,30 @@ struct ath11k_nss_peer { +@@ -156,10 +162,30 @@ struct ath11k_nss_peer { struct completion complete; }; @@ -3242,7 +3194,7 @@ Signed-off-by: Vasanthakumar Thiagarajan /* Used for completion status for vdev config nss messages */ struct completion complete; /* Keep the copy of encap type for nss */ -@@ -182,6 +208,25 @@ struct arvif_nss { +@@ -181,6 +207,25 @@ struct arvif_nss { /* WDS cfg should be done only once for ext vdev */ bool wds_cfg_done; bool created; @@ -3268,7 +3220,7 @@ Signed-off-by: Vasanthakumar Thiagarajan }; /* Structure to hold the pdev/radio related info for nss offload support */ -@@ -190,6 +235,8 @@ struct ath11k_nss { +@@ -189,6 +234,8 @@ struct ath11k_nss { int if_num; /* Radio/pdev Context obtained on pdev register */ void* ctx; @@ -3277,7 +3229,7 @@ Signed-off-by: Vasanthakumar Thiagarajan }; /* Structure to hold the soc related info for nss offload support */ -@@ -198,10 +245,14 @@ struct ath11k_soc_nss { +@@ -197,10 +244,14 @@ struct ath11k_soc_nss { bool enabled; /* turn on/off nss stats support in ath11k */ bool stats_enabled; @@ -3292,7 +3244,7 @@ Signed-off-by: Vasanthakumar Thiagarajan /* Completion to nss message response */ struct completion complete; /* Response to nss messages are stored here on msg callback -@@ -258,6 +309,19 @@ void ath11k_nss_update_sta_rxrate(struct +@@ -257,6 +308,19 @@ void ath11k_nss_update_sta_rxrate(struct int ath11k_nss_setup(struct ath11k_base *ab); int ath11k_nss_teardown(struct ath11k_base *ab); void ath11k_nss_ext_rx_stats(struct ath11k_base *ab, struct htt_rx_ring_tlv_filter *tlv_filter); @@ -3312,7 +3264,7 @@ Signed-off-by: Vasanthakumar Thiagarajan #else static inline int ath11k_nss_tx(struct ath11k_vif *arvif, struct sk_buff *skb) { -@@ -428,5 +492,38 @@ static inline void ath11k_nss_ext_rx_sta +@@ -427,5 +491,38 @@ static inline void ath11k_nss_ext_rx_sta { return; } @@ -3353,8 +3305,8 @@ Signed-off-by: Vasanthakumar Thiagarajan #endif --- a/include/net/mac80211.h +++ b/include/net/mac80211.h -@@ -127,6 +127,9 @@ - +@@ -143,6 +143,9 @@ + */ struct device; +struct ieee80211_mesh_path_offld; @@ -3363,7 +3315,7 @@ Signed-off-by: Vasanthakumar Thiagarajan /** * enum ieee80211_max_queues - maximum number of queues * -@@ -366,11 +369,17 @@ enum ieee80211_bss_change { +@@ -384,11 +387,17 @@ enum ieee80211_bss_change { * to indicate which NSS BSS parameter changed. * * @BSS_CHANGED_NSS_AP_ISOLATE: AP Isolate feature in NSS mode @@ -3381,8 +3333,8 @@ Signed-off-by: Vasanthakumar Thiagarajan }; /* -@@ -729,6 +738,11 @@ struct ieee80211_bss_conf { - u8 pwr_reduction; +@@ -744,6 +753,11 @@ struct ieee80211_bss_conf { + bool nss_ap_isolate; enum nl80211_beacon_tx_mode beacon_tx_mode; + @@ -3393,16 +3345,16 @@ Signed-off-by: Vasanthakumar Thiagarajan }; /** -@@ -1158,6 +1172,8 @@ ieee80211_info_get_tx_time_est(struct ie - * @skb: Packet skb (can be NULL if not provided by the driver) - * @rate: The TX rate that was used when sending the packet - * @free_list: list where processed skbs are stored to be free'd by the driver +@@ -1223,6 +1237,8 @@ struct ieee80211_rate_status { + * @ack_hwtstamp: Hardware timestamp of the received ack in nanoseconds + * Only needed for Timing measurement and Fine timing measurement action + * frames. Only reported by devices that have timestamping enabled. + * @mpdu_succ: Number of mpdus successfully transmitted + * @mpdu_fail: Number of mpdus failed */ struct ieee80211_tx_status { struct ieee80211_sta *sta; -@@ -1169,6 +1185,8 @@ struct ieee80211_tx_status { +@@ -1237,6 +1253,8 @@ struct ieee80211_tx_status { #else struct sk_buff_head *free_list; #endif @@ -3411,7 +3363,7 @@ Signed-off-by: Vasanthakumar Thiagarajan }; /** -@@ -1669,12 +1687,14 @@ struct ieee80211_channel_switch { +@@ -1743,12 +1761,14 @@ struct ieee80211_channel_switch { * @IEEE80211_VIF_GET_NOA_UPDATE: request to handle NOA attributes * and send P2P_PS notification to the driver if NOA changed, even * this is not pure P2P vif. @@ -3426,15 +3378,15 @@ Signed-off-by: Vasanthakumar Thiagarajan }; -@@ -2516,6 +2536,7 @@ enum ieee80211_hw_flags { - IEEE80211_HW_SUPPORTS_RX_DECAP_OFFLOAD, - IEEE80211_HW_SUPPORTS_CONC_MON_RX_DECAP, +@@ -2650,6 +2670,7 @@ enum ieee80211_hw_flags { + IEEE80211_HW_DETECTS_COLOR_COLLISION, + IEEE80211_HW_MLO_MCAST_MULTI_LINK_TX, IEEE80211_HW_SUPPORTS_NSS_OFFLOAD, + IEEE80211_HW_SUPPORTS_MESH_NSS_OFFLOAD, /* keep last, obviously */ NUM_IEEE80211_HW_FLAGS -@@ -3980,6 +4001,8 @@ struct ieee80211_prep_tx_info { +@@ -4133,6 +4154,8 @@ struct ieee80211_prep_tx_info { * @set_sar_specs: Update the SAR (TX power) settings. * @sta_set_decap_offload: Called to notify the driver when a station is allowed * to use rx decapsulation offload @@ -3443,7 +3395,7 @@ Signed-off-by: Vasanthakumar Thiagarajan * @add_twt_setup: Update hw with TWT agreement parameters received from the peer. * This callback allows the hw to check if requested parameters * are supported and if there is enough room for a new agreement. -@@ -4321,6 +4344,12 @@ struct ieee80211_ops { +@@ -4497,6 +4520,12 @@ struct ieee80211_ops { void (*sta_set_decap_offload)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool enabled); @@ -3456,7 +3408,7 @@ Signed-off-by: Vasanthakumar Thiagarajan void (*add_twt_setup)(struct ieee80211_hw *hw, struct ieee80211_sta *sta, struct ieee80211_twt_setup *twt); -@@ -6958,4 +6987,100 @@ static inline bool ieee80211_is_tx_data( +@@ -7174,4 +7203,100 @@ static inline bool ieee80211_is_tx_data( ieee80211_is_data(hdr->frame_control); } @@ -3559,7 +3511,7 @@ Signed-off-by: Vasanthakumar Thiagarajan #endif /* MAC80211_H */ --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -2247,6 +2247,7 @@ static int ieee80211_update_mesh_config( +@@ -2342,6 +2342,7 @@ static int ieee80211_update_mesh_config( struct mesh_config *conf; struct ieee80211_sub_if_data *sdata; struct ieee80211_if_mesh *ifmsh; @@ -3567,7 +3519,7 @@ Signed-off-by: Vasanthakumar Thiagarajan sdata = IEEE80211_DEV_TO_SUB_IF(dev); ifmsh = &sdata->u.mesh; -@@ -2263,8 +2264,11 @@ static int ieee80211_update_mesh_config( +@@ -2358,8 +2359,11 @@ static int ieee80211_update_mesh_config( conf->dot11MeshMaxPeerLinks = nconf->dot11MeshMaxPeerLinks; if (_chg_mesh_attr(NL80211_MESHCONF_MAX_RETRIES, mask)) conf->dot11MeshMaxRetries = nconf->dot11MeshMaxRetries; @@ -3580,7 +3532,7 @@ Signed-off-by: Vasanthakumar Thiagarajan if (_chg_mesh_attr(NL80211_MESHCONF_ELEMENT_TTL, mask)) conf->element_ttl = nconf->element_ttl; if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask)) { -@@ -2278,8 +2282,12 @@ static int ieee80211_update_mesh_config( +@@ -2373,8 +2377,12 @@ static int ieee80211_update_mesh_config( if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, mask)) conf->dot11MeshHWMPmaxPREQretries = nconf->dot11MeshHWMPmaxPREQretries; @@ -3594,7 +3546,7 @@ Signed-off-by: Vasanthakumar Thiagarajan if (_chg_mesh_attr(NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, mask)) conf->min_discovery_timeout = nconf->min_discovery_timeout; if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, mask)) -@@ -2314,8 +2322,12 @@ static int ieee80211_update_mesh_config( +@@ -2409,8 +2417,12 @@ static int ieee80211_update_mesh_config( if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_RANN_INTERVAL, mask)) conf->dot11MeshHWMPRannInterval = nconf->dot11MeshHWMPRannInterval; @@ -3608,7 +3560,7 @@ Signed-off-by: Vasanthakumar Thiagarajan if (_chg_mesh_attr(NL80211_MESHCONF_RSSI_THRESHOLD, mask)) { /* our RSSI threshold implementation is supported only for * devices that report signal in dBm. -@@ -2356,6 +2368,7 @@ static int ieee80211_update_mesh_config( +@@ -2452,6 +2464,7 @@ static int ieee80211_update_mesh_config( conf->dot11MeshConnectedToAuthServer = nconf->dot11MeshConnectedToAuthServer; ieee80211_mbss_info_change_notify(sdata, BSS_CHANGED_BEACON); @@ -3618,7 +3570,7 @@ Signed-off-by: Vasanthakumar Thiagarajan --- a/net/mac80211/debug.h +++ b/net/mac80211/debug.h -@@ -63,6 +63,12 @@ +@@ -67,6 +67,12 @@ #define MAC80211_MESH_PS_DEBUG 0 #endif @@ -3631,7 +3583,7 @@ Signed-off-by: Vasanthakumar Thiagarajan #ifdef CPTCFG_MAC80211_TDLS_DEBUG #define MAC80211_TDLS_DEBUG 1 #else -@@ -182,6 +188,10 @@ do { \ +@@ -215,6 +221,10 @@ do { \ _sdata_dbg(MAC80211_MESH_PS_DEBUG, \ sdata, fmt, ##__VA_ARGS__) @@ -3644,9 +3596,9 @@ Signed-off-by: Vasanthakumar Thiagarajan sdata, fmt, ##__VA_ARGS__) --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c -@@ -507,6 +507,7 @@ static const char *hw_flag_names[] = { - FLAG(SUPPORTS_RX_DECAP_OFFLOAD), - FLAG(SUPPORTS_CONC_MON_RX_DECAP), +@@ -499,6 +499,7 @@ static const char *hw_flag_names[] = { + FLAG(DETECTS_COLOR_COLLISION), + FLAG(MLO_MCAST_MULTI_LINK_TX), FLAG(SUPPORTS_NSS_OFFLOAD), + FLAG(SUPPORTS_MESH_NSS_OFFLOAD), #undef FLAG @@ -3654,7 +3606,7 @@ Signed-off-by: Vasanthakumar Thiagarajan --- a/net/mac80211/driver-ops.c +++ b/net/mac80211/driver-ops.c -@@ -347,3 +347,23 @@ int drv_ampdu_action(struct ieee80211_lo +@@ -349,3 +349,23 @@ int drv_ampdu_action(struct ieee80211_lo return ret; } @@ -3680,17 +3632,16 @@ Signed-off-by: Vasanthakumar Thiagarajan +#endif --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h -@@ -1506,4 +1506,11 @@ static inline void drv_twt_teardown_requ - local->ops->twt_teardown_request(&local->hw, sta, flowid); - trace_drv_return_void(local); +@@ -1593,4 +1593,10 @@ static inline int drv_change_sta_links(s + return ret; } -+ + +#ifdef CPTCFG_MAC80211_MESH +void drv_config_mesh_offload_path(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + enum ieee80211_mesh_path_offld_cmd cmd, + struct ieee80211_mesh_path_offld *path); -+#endif ++#endif /* CPTCFG_MAC80211_MESH */ #endif /* __MAC80211_DRIVER_OPS */ --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -3715,7 +3666,7 @@ Signed-off-by: Vasanthakumar Thiagarajan static inline --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c -@@ -360,6 +360,13 @@ u32 airtime_link_metric_get(struct ieee8 +@@ -365,6 +365,13 @@ u32 airtime_link_metric_get(struct ieee8 return (u32)result; } @@ -3729,7 +3680,7 @@ Signed-off-by: Vasanthakumar Thiagarajan /** * hwmp_route_info_get - Update routing info to originator and transmitter * -@@ -383,9 +390,10 @@ static u32 hwmp_route_info_get(struct ie +@@ -388,9 +395,10 @@ static u32 hwmp_route_info_get(struct ie { struct ieee80211_local *local = sdata->local; struct mesh_path *mpath; @@ -3741,7 +3692,7 @@ Signed-off-by: Vasanthakumar Thiagarajan u32 orig_sn, orig_metric; unsigned long orig_lifetime, exp_time; u32 last_hop_metric, new_metric; -@@ -486,7 +494,10 @@ static u32 hwmp_route_info_get(struct ie +@@ -491,7 +499,10 @@ static u32 hwmp_route_info_get(struct ie } if (fresh_info) { @@ -3753,7 +3704,7 @@ Signed-off-by: Vasanthakumar Thiagarajan mpath->path_change_count++; mesh_path_assign_nexthop(mpath, sta); mpath->flags |= MESH_PATH_SN_VALID; -@@ -504,6 +515,8 @@ static u32 hwmp_route_info_get(struct ie +@@ -509,6 +520,8 @@ static u32 hwmp_route_info_get(struct ie /* draft says preq_id should be saved to, but there does * not seem to be any use for it, skipping by now */ @@ -3762,7 +3713,7 @@ Signed-off-by: Vasanthakumar Thiagarajan } else spin_unlock_bh(&mpath->state_lock); } -@@ -534,7 +547,14 @@ static u32 hwmp_route_info_get(struct ie +@@ -539,7 +552,14 @@ static u32 hwmp_route_info_get(struct ie } if (fresh_info) { @@ -3778,7 +3729,7 @@ Signed-off-by: Vasanthakumar Thiagarajan mpath->path_change_count++; mesh_path_assign_nexthop(mpath, sta); mpath->metric = last_hop_metric; -@@ -547,6 +567,8 @@ static u32 hwmp_route_info_get(struct ie +@@ -552,6 +572,8 @@ static u32 hwmp_route_info_get(struct ie /* init it at a low value - 0 start is tricky */ ewma_mesh_fail_avg_add(&sta->mesh->fail_avg, 1); mesh_path_tx_pending(mpath); @@ -3787,7 +3738,7 @@ Signed-off-by: Vasanthakumar Thiagarajan } else spin_unlock_bh(&mpath->state_lock); } -@@ -683,15 +705,6 @@ static void hwmp_preq_frame_process(stru +@@ -688,15 +710,6 @@ static void hwmp_preq_frame_process(stru } } @@ -3803,7 +3754,7 @@ Signed-off-by: Vasanthakumar Thiagarajan static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, const u8 *prep_elem, u32 metric) -@@ -1330,3 +1343,272 @@ void mesh_path_tx_root_frame(struct ieee +@@ -1335,3 +1348,272 @@ void mesh_path_tx_root_frame(struct ieee return; } } @@ -4027,11 +3978,11 @@ Signed-off-by: Vasanthakumar Thiagarajan + LINK_FAIL_THRESH) + mesh_plink_broken(sta); + -+ if (!st->rate) ++ if (!st->rates) + continue; + + ewma_mesh_tx_rate_avg_add(&sta->mesh->tx_rate_avg, -+ cfg80211_calculate_bitrate(st->rate)); ++ cfg80211_calculate_bitrate(st->rates)); + } +} +EXPORT_SYMBOL(ieee80211s_update_metric_ppdu); @@ -4482,7 +4433,7 @@ Signed-off-by: Vasanthakumar Thiagarajan void mesh_pathtbl_unregister(struct ieee80211_sub_if_data *sdata) --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c -@@ -2983,6 +2983,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80 +@@ -2995,6 +2995,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80 struct mesh_path *mppath; char *proxied_addr; char *mpp_addr; @@ -4490,7 +4441,7 @@ Signed-off-by: Vasanthakumar Thiagarajan if (is_multicast_ether_addr(hdr->addr1)) { mpp_addr = hdr->addr3; -@@ -3002,10 +3003,15 @@ ieee80211_rx_h_mesh_fwding(struct ieee80 +@@ -3014,10 +3015,15 @@ ieee80211_rx_h_mesh_fwding(struct ieee80 mpp_path_add(sdata, proxied_addr, mpp_addr); } else { spin_lock_bh(&mppath->state_lock); @@ -4519,7 +4470,7 @@ Signed-off-by: Vasanthakumar Thiagarajan ATH11K_DBG_WMI = 0x00000002, --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c -@@ -2607,6 +2607,9 @@ static struct sk_buff *ieee80211_build_h +@@ -2616,6 +2616,9 @@ static struct sk_buff *ieee80211_build_h info_flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; #endif @@ -4529,7 +4480,7 @@ Signed-off-by: Vasanthakumar Thiagarajan /* convert Ethernet header to proper 802.11 header (based on * operation mode) */ ethertype = (skb->data[12] << 8) | skb->data[13]; -@@ -2653,6 +2656,13 @@ static struct sk_buff *ieee80211_build_h +@@ -2685,6 +2688,13 @@ static struct sk_buff *ieee80211_build_h break; #ifdef CPTCFG_MAC80211_MESH case NL80211_IFTYPE_MESH_POINT: @@ -4543,7 +4494,7 @@ Signed-off-by: Vasanthakumar Thiagarajan if (!is_multicast_ether_addr(skb->data)) { struct sta_info *next_hop; bool mpp_lookup = true; -@@ -2928,10 +2938,10 @@ static struct sk_buff *ieee80211_build_h +@@ -2938,10 +2948,10 @@ static struct sk_buff *ieee80211_build_h skb_reset_mac_header(skb); @@ -4557,8 +4508,8 @@ Signed-off-by: Vasanthakumar Thiagarajan + info->flags |= info_flags; info->ack_frame_id = info_id; info->band = band; - info->control.flags = ctrl_flags; -@@ -4198,6 +4208,7 @@ void __ieee80211_subif_start_xmit(struct + +@@ -4160,6 +4170,7 @@ void __ieee80211_subif_start_xmit(struct struct sk_buff *next; int len = skb->len; struct ieee80211_key *key = NULL; @@ -4566,7 +4517,7 @@ Signed-off-by: Vasanthakumar Thiagarajan struct ieee80211_sub_if_data *ap_sdata; if (unlikely(skb->len < ETH_HLEN)) { -@@ -4294,9 +4305,15 @@ void __ieee80211_subif_start_xmit(struct +@@ -4256,9 +4267,15 @@ void __ieee80211_subif_start_xmit(struct goto out; } diff --git a/feeds/ipq95xx/mac80211/patches/qca/301-debugfs-support-for-ani-parameters.patch b/feeds/ipq95xx/mac80211/patches/qca/301-debugfs-support-for-ani-parameters.patch index 05050b1a2..d81ee3614 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/301-debugfs-support-for-ani-parameters.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/301-debugfs-support-for-ani-parameters.patch @@ -15,15 +15,15 @@ Signed-off-by: Hari Chandrakanthan --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -790,6 +790,7 @@ struct ath11k { +@@ -889,6 +889,7 @@ struct ath11k { struct ath11k_cfr cfr; #endif u8 cfr_enabled; + bool ani_enabled; u32 vdev_id_11d_scan; - struct completion finish_11d_scan; - struct completion finish_11d_ch_list; -@@ -1064,6 +1065,13 @@ struct ath11k_base { + struct completion completed_11d_scan; + enum ath11k_11d_state state_11d; +@@ -1196,6 +1197,13 @@ struct ath11k_base { u32 rx_hash; bool stats_disable; @@ -35,11 +35,11 @@ Signed-off-by: Hari Chandrakanthan + struct completion ani_cck_event; + /* must be last */ - u8 drv_priv[0] __aligned(sizeof(void *)); + u8 drv_priv[] __aligned(sizeof(void *)); }; --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -3816,6 +3816,302 @@ static const struct file_operations fops +@@ -4078,6 +4078,302 @@ static const struct file_operations fops .open = simple_open }; @@ -342,7 +342,7 @@ Signed-off-by: Hari Chandrakanthan int ath11k_debugfs_register(struct ath11k *ar) { struct ath11k_base *ab = ar->ab; -@@ -3840,6 +4136,8 @@ int ath11k_debugfs_register(struct ath11 +@@ -4102,6 +4398,8 @@ int ath11k_debugfs_register(struct ath11 ath11k_debugfs_fw_stats_init(ar); ath11k_init_pktlog(ar); init_completion(&ar->tpc_complete); @@ -351,11 +351,10 @@ Signed-off-by: Hari Chandrakanthan debugfs_create_file("ext_tx_stats", 0644, ar->debug.debugfs_pdev, ar, -@@ -3907,6 +4205,16 @@ int ath11k_debugfs_register(struct ath11 +@@ -4174,6 +4472,14 @@ int ath11k_debugfs_register(struct ath11 + ar->debug.debugfs_pdev, ar, + &fops_athdiag); - debugfs_create_file("enable_dbr_debug", 0200, ar->debug.debugfs_pdev, - ar, &fops_dbr_debug); -+ + debugfs_create_file("ani_enable", S_IRUSR | S_IWUSR, + ar->debug.debugfs_pdev, ar, &fops_ani_enable); + debugfs_create_file("ani_level", S_IRUSR | S_IWUSR, @@ -364,13 +363,12 @@ Signed-off-by: Hari Chandrakanthan + ar->debug.debugfs_pdev, ar, &fops_ani_poll_period); + debugfs_create_file("ani_listen_period", S_IRUSR | S_IWUSR, + ar->debug.debugfs_pdev, ar, &fops_ani_listen_period); -+ return 0; } --- a/drivers/net/wireless/ath/ath11k/debugfs.h +++ b/drivers/net/wireless/ath/ath11k/debugfs.h -@@ -211,6 +211,12 @@ do { \ +@@ -366,6 +366,12 @@ do { \ #define ATH11K_MEMORY_STATS_DEC(_struct, _field, _size) #endif @@ -385,7 +383,7 @@ Signed-off-by: Hari Chandrakanthan void ath11k_debugfs_destroy(void); --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -6768,6 +6768,9 @@ static int ath11k_mac_op_start(struct ie +@@ -6760,6 +6760,9 @@ static int ath11k_mac_op_start(struct ie rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], &ab->pdevs[ar->pdev_idx]); @@ -397,7 +395,7 @@ Signed-off-by: Hari Chandrakanthan err: --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -8411,6 +8411,74 @@ ath11k_wmi_pdev_csa_switch_count_status_ +@@ -8272,6 +8272,74 @@ ath11k_wmi_pdev_csa_switch_count_status_ kfree(tb); } @@ -472,7 +470,7 @@ Signed-off-by: Hari Chandrakanthan static void ath11k_wmi_pdev_dfs_radar_detected_event(struct ath11k_base *ab, struct sk_buff *skb) { -@@ -9655,6 +9723,12 @@ static void ath11k_wmi_tlv_op_rx(struct +@@ -9579,6 +9647,12 @@ static void ath11k_wmi_tlv_op_rx(struct case WMI_PEER_CFR_CAPTURE_EVENTID: ath11k_wmi_parse_cfr_capture_event(ab, skb); break; @@ -487,7 +485,7 @@ Signed-off-by: Hari Chandrakanthan ath11k_dbg(ab, ATH11K_DBG_WMI, "Unknown eventid: 0x%x\n", id); --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -117,6 +117,12 @@ enum WMI_HOST_WLAN_BAND { +@@ -119,6 +119,12 @@ enum WMI_HOST_WLAN_BAND { WMI_HOST_WLAN_2G_5G_CAP = WMI_HOST_WLAN_2G_CAP | WMI_HOST_WLAN_5G_CAP, }; @@ -500,7 +498,7 @@ Signed-off-by: Hari Chandrakanthan /* Parameters used for WMI_VDEV_PARAM_AUTORATE_MISC_CFG command. * Used only for HE auto rate mode. */ -@@ -2716,6 +2722,11 @@ struct wmi_p2p_noa_descriptor { +@@ -2729,6 +2735,11 @@ struct wmi_p2p_noa_descriptor { u32 start_time; }; @@ -512,7 +510,7 @@ Signed-off-by: Hari Chandrakanthan struct channel_param { u8 chan_id; u8 pwr; -@@ -3127,6 +3138,12 @@ struct wmi_fwtest_set_param_cmd_param { +@@ -3140,6 +3151,12 @@ struct wmi_fwtest_set_param_cmd_param { u32 param_value; }; @@ -525,7 +523,7 @@ Signed-off-by: Hari Chandrakanthan struct wmi_pdev_set_param_cmd { u32 tlv_header; u32 pdev_id; -@@ -6660,4 +6677,5 @@ int ath11k_wmi_dbglog_cfg(struct ath11k +@@ -7070,4 +7087,5 @@ int ath11k_wmi_dbglog_cfg(struct ath11k int ath11k_wmi_peer_set_cfr_capture_conf(struct ath11k *ar, u32 vdev_id, const u8 *mac, struct wmi_peer_cfr_capture_conf_arg *arg); diff --git a/feeds/ipq95xx/mac80211/patches/qca/303-mac80211-support-to-track-mesh-beacon-miss-event.patch b/feeds/ipq95xx/mac80211/patches/qca/303-mac80211-support-to-track-mesh-beacon-miss-event.patch index 700f4f591..ec990c034 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/303-mac80211-support-to-track-mesh-beacon-miss-event.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/303-mac80211-support-to-track-mesh-beacon-miss-event.patch @@ -17,15 +17,15 @@ Signed-off-by: Hari Chandrakanthan --- a/include/net/mac80211.h +++ b/include/net/mac80211.h -@@ -1807,6 +1807,7 @@ struct ieee80211_vif { +@@ -750,6 +750,7 @@ struct ieee80211_bss_conf { bool color_change_active; u8 color_change_color; + u8 bmiss_threshold; - struct ieee80211_vif *mbssid_tx_vif; - -@@ -2555,6 +2556,12 @@ enum ieee80211_hw_flags { + bool nss_ap_isolate; + enum nl80211_beacon_tx_mode beacon_tx_mode; +@@ -2676,6 +2677,12 @@ enum ieee80211_hw_flags { NUM_IEEE80211_HW_FLAGS }; @@ -38,17 +38,17 @@ Signed-off-by: Hari Chandrakanthan /** * struct ieee80211_hw - hardware information and state * -@@ -2717,6 +2724,7 @@ struct ieee80211_hw { - u8 tx_sk_pacing_shift; - u8 weight_multiplier; +@@ -2841,6 +2848,7 @@ struct ieee80211_hw { u32 max_mtu; + const s8 *tx_power_levels; + u8 max_txpwr_levels_idx; + u32 dbg_mask; }; static inline bool _ieee80211_hw_check(struct ieee80211_hw *hw, --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c -@@ -424,6 +424,41 @@ static const struct file_operations airt +@@ -414,6 +414,41 @@ static const struct file_operations forc .llseek = default_llseek, }; @@ -90,24 +90,24 @@ Signed-off-by: Hari Chandrakanthan #ifdef CONFIG_PM static ssize_t reset_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) -@@ -673,6 +708,7 @@ void debugfs_hw_add(struct ieee80211_loc - DEBUGFS_ADD(hw_conf); +@@ -667,6 +702,7 @@ void debugfs_hw_add(struct ieee80211_loc DEBUGFS_ADD_MODE(force_tx_status, 0600); DEBUGFS_ADD_MODE(aql_enable, 0600); + DEBUGFS_ADD(aql_pending); + DEBUGFS_ADD(dbg_mask); if (local->ops->wake_tx_queue) DEBUGFS_ADD_MODE(aqm, 0600); --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c -@@ -299,6 +299,32 @@ static ssize_t ieee80211_if_parse_smps(s +@@ -297,6 +297,32 @@ static ssize_t ieee80211_if_parse_smps(s } IEEE80211_IF_FILE_RW(smps); +int ieee80211_if_fmt_bmiss_threshold(const struct ieee80211_sub_if_data *sdata, + char *buf, int buflen) +{ -+ return snprintf(buf, buflen, "%u\n", sdata->vif.bmiss_threshold); ++ return snprintf(buf, buflen, "%u\n", sdata->vif.bss_conf.bmiss_threshold); +} + +static ssize_t ieee80211_if_parse_bmiss_threshold(struct ieee80211_sub_if_data *sdata, @@ -123,7 +123,7 @@ Signed-off-by: Hari Chandrakanthan + if (!val) + return -EINVAL; + -+ sdata->vif.bmiss_threshold = val; ++ sdata->vif.bss_conf.bmiss_threshold = val; + + return buflen; +} @@ -133,7 +133,7 @@ Signed-off-by: Hari Chandrakanthan static ssize_t ieee80211_if_parse_tkip_mic_test( struct ieee80211_sub_if_data *sdata, const char *buf, int buflen) { -@@ -713,6 +739,7 @@ static void add_ap_files(struct ieee8021 +@@ -681,6 +707,7 @@ static void add_ap_files(struct ieee8021 DEBUGFS_ADD(num_buffered_multicast); DEBUGFS_ADD_MODE(tkip_mic_test, 0200); DEBUGFS_ADD_MODE(multicast_to_unicast, 0600); @@ -141,7 +141,7 @@ Signed-off-by: Hari Chandrakanthan } static void add_vlan_files(struct ieee80211_sub_if_data *sdata) -@@ -733,6 +760,7 @@ static void add_mesh_files(struct ieee80 +@@ -701,6 +728,7 @@ static void add_mesh_files(struct ieee80 { DEBUGFS_ADD_MODE(tsf, 0600); DEBUGFS_ADD_MODE(estab_plinks, 0400); @@ -151,7 +151,7 @@ Signed-off-by: Hari Chandrakanthan static void add_mesh_stats(struct ieee80211_sub_if_data *sdata) --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c -@@ -162,6 +162,8 @@ void mesh_sta_cleanup(struct sta_info *s +@@ -163,6 +163,8 @@ void mesh_sta_cleanup(struct sta_info *s struct ieee80211_sub_if_data *sdata = sta->sdata; u32 changed = mesh_plink_deactivate(sta); @@ -160,9 +160,9 @@ Signed-off-by: Hari Chandrakanthan if (changed) ieee80211_mbss_info_change_notify(sdata, changed); } -@@ -1362,6 +1364,9 @@ static void ieee80211_mesh_rx_bcn_presp( +@@ -1361,6 +1363,9 @@ static void ieee80211_mesh_rx_bcn_presp( if (ifmsh->csa_role != IEEE80211_MESH_CSA_ROLE_INIT && - !sdata->vif.csa_active) + !sdata->vif.bss_conf.csa_active) ieee80211_mesh_process_chnswitch(sdata, elems, true); + + if (stype != IEEE80211_STYPE_PROBE_RESP) @@ -172,7 +172,7 @@ Signed-off-by: Hari Chandrakanthan if (ifmsh->sync_ops) --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h -@@ -287,7 +287,9 @@ int mesh_path_send_to_gates(struct mesh_ +@@ -267,7 +267,9 @@ int mesh_path_send_to_gates(struct mesh_ int mesh_gate_num(struct ieee80211_sub_if_data *sdata); u32 airtime_link_metric_get(struct ieee80211_local *local, struct sta_info *sta); @@ -183,7 +183,7 @@ Signed-off-by: Hari Chandrakanthan /* Mesh plinks */ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata, u8 *hw_addr, struct ieee802_11_elems *ie, -@@ -322,6 +324,7 @@ void mesh_path_discard_frame(struct ieee +@@ -302,6 +304,7 @@ void mesh_path_discard_frame(struct ieee void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata); bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt); @@ -193,7 +193,7 @@ Signed-off-by: Hari Chandrakanthan #ifdef CPTCFG_MAC80211_MESH --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c -@@ -597,6 +597,58 @@ mesh_sta_info_get(struct ieee80211_sub_i +@@ -598,6 +598,58 @@ mesh_sta_info_get(struct ieee80211_sub_i return sta; } @@ -211,12 +211,12 @@ Signed-off-by: Hari Chandrakanthan + goto unlock_rcu; + + if (!(sta->local->hw.dbg_mask & IEEE80211_HW_DBG_BMISS_LOG) || -+ !sta->sdata->vif.bmiss_threshold) ++ !sta->sdata->vif.bss_conf.bmiss_threshold) + goto unlock_rcu; + + sta->mesh->bmiss_count = 0; + sta->mesh->beacon_int = mgmt->u.beacon.beacon_int; -+ timeout = sta->mesh->beacon_int * sta->sdata->vif.bmiss_threshold; ++ timeout = sta->mesh->beacon_int * sta->sdata->vif.bss_conf.bmiss_threshold; + + mod_timer(&sta->mesh->bmiss_timer, (jiffies + msecs_to_jiffies(timeout))); + @@ -234,14 +234,14 @@ Signed-off-by: Hari Chandrakanthan + sta = mesh->plink_sta; + + if (!(sta->local->hw.dbg_mask & IEEE80211_HW_DBG_BMISS_LOG) || -+ !sta->sdata->vif.bmiss_threshold) ++ !sta->sdata->vif.bss_conf.bmiss_threshold) + goto unlock_rcu; + + mesh->bmiss_count++; + sdata_info(sta->sdata, "Beacon miss count %u from %pM\n", + mesh->bmiss_count, sta->sta.addr); + -+ timeout = sta->mesh->beacon_int * sta->sdata->vif.bmiss_threshold; ++ timeout = sta->mesh->beacon_int * sta->sdata->vif.bss_conf.bmiss_threshold; + + mod_timer(&sta->mesh->bmiss_timer, (jiffies + msecs_to_jiffies(timeout))); + @@ -254,8 +254,8 @@ Signed-off-by: Hari Chandrakanthan * --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c -@@ -379,6 +379,7 @@ struct sta_info *sta_info_alloc(struct i - !sdata->u.mesh.user_mpm) +@@ -529,6 +529,7 @@ __sta_info_alloc(struct ieee80211_sub_if + if (!sdata->u.mesh.user_mpm) timer_setup(&sta->mesh->plink_timer, mesh_plink_timer, 0); + timer_setup(&sta->mesh->bmiss_timer, mesh_bmiss_event, 0); @@ -264,7 +264,7 @@ Signed-off-by: Hari Chandrakanthan #endif --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h -@@ -422,6 +422,10 @@ struct mesh_sta { +@@ -418,6 +418,10 @@ struct mesh_sta { enum nl80211_mesh_power_mode peer_pm; enum nl80211_mesh_power_mode nonpeer_pm; diff --git a/feeds/ipq95xx/mac80211/patches/qca/305-001-mac80211-Add-support-to-handle-AWGN-interference-for-6G.patch b/feeds/ipq95xx/mac80211/patches/qca/305-001-mac80211-Add-support-to-handle-AWGN-interference-for-6G.patch index 32b64c8a0..e74a5afa8 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/305-001-mac80211-Add-support-to-handle-AWGN-interference-for-6G.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/305-001-mac80211-Add-support-to-handle-AWGN-interference-for-6G.patch @@ -16,12 +16,10 @@ Signed-off-by: Lavanya Suresh net/mac80211/util.c | 26 ++++++++++++++++++++++++++ 4 files changed, 39 insertions(+) -diff --git a/include/net/mac80211.h b/include/net/mac80211.h -index df3c728..a91a7f9 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h -@@ -6245,6 +6245,13 @@ void ieee80211_radar_detected(struct ieee80211_hw *hw); - void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success); +@@ -6407,6 +6407,13 @@ void ieee80211_channel_switch_disconnect + bool block_tx); /** + * ieee80211_awgn_detected - inform that awgn interference is detected @@ -33,21 +31,19 @@ index df3c728..a91a7f9 100644 +/** * ieee80211_request_smps - request SM PS transition * @vif: &struct ieee80211_vif pointer from the add_interface callback. - * @smps_mode: new SM PS mode -diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h -index 448e8bd..200d325 100644 + * @link_id: link ID for MLO, or 0 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h -@@ -952,6 +952,8 @@ struct ieee80211_sub_if_data { - bool csa_block_tx; /* write-protected by sdata_lock and local->mtx */ +@@ -978,6 +978,8 @@ struct ieee80211_link_data { + struct cfg80211_chan_def csa_chandef; + struct work_struct awgn_detected_work; + struct work_struct color_change_finalize_work; - struct list_head assigned_chanctx_list; /* protected by chanctx_mtx */ -@@ -1778,6 +1780,8 @@ int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, + /* context reservation -- protected with chanctx_mtx */ +@@ -1918,6 +1920,8 @@ int ieee80211_mgmt_tx_cancel_wait(struct void ieee80211_csa_finalize_work(struct work_struct *work); int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_csa_settings *params); @@ -56,31 +52,28 @@ index 448e8bd..200d325 100644 /* color change handling */ void ieee80211_color_change_finalize_work(struct work_struct *work); -diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c -index 1169a1c..7d441ac 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c -@@ -471,6 +471,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do +@@ -400,6 +400,8 @@ static void ieee80211_link_init(struct i + + INIT_WORK(&link->csa_finalize_work, + ieee80211_csa_finalize_work); ++ INIT_WORK(&sdata->awgn_detected_work, ++ ieee80211_awgn_interference_detected_work); + INIT_WORK(&link->color_change_finalize_work, + ieee80211_color_change_finalize_work); + INIT_LIST_HEAD(&link->assigned_chanctx_list); +@@ -717,6 +719,7 @@ static void ieee80211_do_stop(struct iee sdata_unlock(sdata); - cancel_work_sync(&sdata->csa_finalize_work); + cancel_work_sync(&sdata->deflink.csa_finalize_work); + cancel_work_sync(&sdata->awgn_detected_work); - cancel_work_sync(&sdata->color_change_finalize_work); - - cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); -@@ -1660,6 +1661,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, - INIT_WORK(&sdata->work, ieee80211_iface_work); - INIT_WORK(&sdata->recalc_smps, ieee80211_recalc_smps_work); - INIT_WORK(&sdata->csa_finalize_work, ieee80211_csa_finalize_work); -+ INIT_WORK(&sdata->awgn_detected_work, ieee80211_awgn_interference_detected_work); - INIT_WORK(&sdata->color_change_finalize_work, ieee80211_color_change_finalize_work); - INIT_LIST_HEAD(&sdata->assigned_chanctx_list); - INIT_LIST_HEAD(&sdata->reserved_chanctx_list); -diff --git a/net/mac80211/util.c b/net/mac80211/util.c -index a00ed23..56f490b 100644 + cancel_work_sync(&sdata->deflink.color_change_finalize_work); + + cancel_delayed_work_sync(&sdata->deflink.dfs_cac_timer_work); --- a/net/mac80211/util.c +++ b/net/mac80211/util.c -@@ -3929,6 +3929,32 @@ u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c) +@@ -4187,6 +4187,32 @@ ieee80211_conn_flags_t ieee80211_chandef return ret; } @@ -113,6 +106,3 @@ index a00ed23..56f490b 100644 /* * Returns true if smps_mode_new is strictly more restrictive than * smps_mode_old. --- -2.7.4 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/305-002-ath11k-Add-support-to-handle-AWGN-interference-for-6G.patch b/feeds/ipq95xx/mac80211/patches/qca/305-002-ath11k-Add-support-to-handle-AWGN-interference-for-6G.patch index e55be161f..31f9bb4aa 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/305-002-ath11k-Add-support-to-handle-AWGN-interference-for-6G.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/305-002-ath11k-Add-support-to-handle-AWGN-interference-for-6G.patch @@ -27,8 +27,8 @@ Signed-off-by: Lavanya Suresh --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -2165,6 +2165,35 @@ static const struct file_operations fops - .open = simple_open +@@ -2478,6 +2478,35 @@ static const struct file_operations fops + .llseek = default_llseek, }; +static ssize_t ath11k_write_simulate_awgn(struct file *file, @@ -63,9 +63,9 @@ Signed-off-by: Lavanya Suresh static ssize_t ath11k_write_btcoex(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) -@@ -4136,6 +4165,12 @@ int ath11k_debugfs_register(struct ath11 - &ar->dfs_block_radar_events); - } +@@ -4456,6 +4485,12 @@ int ath11k_debugfs_register(struct ath11 + debugfs_create_file("enable_dbr_debug", 0200, ar->debug.debugfs_pdev, + ar, &fops_dbr_debug); + if (ar->hw->wiphy->bands[NL80211_BAND_6GHZ]) { + debugfs_create_file("simulate_awgn", 0200, @@ -78,7 +78,7 @@ Signed-off-by: Lavanya Suresh &fops_enable_m3_dump); --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -8531,6 +8531,209 @@ exit: +@@ -8752,6 +8752,209 @@ exit: kfree(tb); } @@ -288,9 +288,9 @@ Signed-off-by: Lavanya Suresh static void ath11k_wmi_tm_event_segmented(struct ath11k_base *ab, u32 cmd_id, struct sk_buff *skb) { -@@ -9678,6 +9881,9 @@ static void ath11k_wmi_tlv_op_rx(struct - case WMI_WOW_WAKEUP_HOST_EVENTID: - ath11k_wmi_event_wow_wakeup_host(ab, skb); +@@ -10001,6 +10204,9 @@ static void ath11k_wmi_tlv_op_rx(struct + case WMI_GTK_OFFLOAD_STATUS_EVENTID: + ath11k_wmi_gtk_offload_status_event(ab, skb); break; + case WMI_DCS_INTERFERENCE_EVENTID: + ath11k_wmi_dcs_awgn_interference_event(ab, skb); @@ -298,8 +298,8 @@ Signed-off-by: Lavanya Suresh case WMI_PDEV_GET_TPC_STATS_EVENTID: ath11k_process_tpc_stats(ab, skb); break; -@@ -9846,6 +10052,42 @@ int ath11k_wmi_simulate_radar(struct ath - return ath11k_wmi_send_unit_test_cmd(ar, wmi_ut, dfs_args); +@@ -10214,6 +10420,42 @@ int ath11k_wmi_fw_dbglog_cfg(struct ath1 + return ret; } + @@ -343,23 +343,23 @@ Signed-off-by: Lavanya Suresh u32 m3_args[WMI_M3_MAX_TEST_ARGS]; --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -1909,6 +1909,7 @@ enum wmi_tlv_tag { +@@ -1908,6 +1908,7 @@ enum wmi_tlv_tag { WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT, WMI_CTRL_PATH_CAL_STATS = 0x3BC, + WMI_TAG_DCS_AWGN_INT_TYPE = 0x3C5, - + WMI_TAG_PDEV_SET_BIOS_SAR_TABLE_CMD = 0x3D8, + WMI_TAG_PDEV_SET_BIOS_GEO_TABLE_CMD, WMI_TAG_MAX - }; -@@ -2181,6 +2182,7 @@ enum wmi_tlv_service { +@@ -2180,6 +2181,7 @@ enum wmi_tlv_service { WMI_TLV_SERVICE_PASSIVE_SCAN_START_TIME_ENHANCE = 263, WMI_TLV_SERVICE_QOS_NULL_FRAME_TX_OVER_WMI = 264, WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281, + WMI_TLV_SERVICE_DCS_AWGN_INT_SUPPORT = 286, - WMI_MAX_EXT2_SERVICE - }; -@@ -4264,6 +4266,17 @@ struct wmi_dfs_unit_test_arg { + WMI_TLV_SERVICE_BIOS_SAR_SUPPORT = 326, + +@@ -4277,6 +4279,17 @@ struct wmi_dfs_unit_test_arg { u32 radar_param; }; @@ -377,7 +377,7 @@ Signed-off-by: Lavanya Suresh #define WMI_M3_UNIT_TEST_MODULE 0x22 #define WMI_M3_UNIT_TEST_TOKEN 0 -@@ -4891,6 +4904,42 @@ struct wmi_pdev_radar_ev { +@@ -4913,6 +4926,42 @@ struct wmi_pdev_radar_ev { s32 sidx; } __packed; @@ -420,7 +420,7 @@ Signed-off-by: Lavanya Suresh struct wmi_pdev_temperature_event { /* temperature value in Celcius degree */ s32 temp; -@@ -6686,6 +6735,7 @@ void ath11k_wmi_fw_stats_fill(struct ath +@@ -7122,6 +7171,7 @@ void ath11k_wmi_fw_stats_fill(struct ath struct ath11k_fw_stats *fw_stats, u32 stats_id, char *buf); int ath11k_wmi_simulate_radar(struct ath11k *ar); diff --git a/feeds/ipq95xx/mac80211/patches/qca/305-ath11k-fix-radar-detection-issue-in-160mhz.patch b/feeds/ipq95xx/mac80211/patches/qca/305-ath11k-fix-radar-detection-issue-in-160mhz.patch deleted file mode 100644 index a96c5c792..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/305-ath11k-fix-radar-detection-issue-in-160mhz.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 2e25abb2008e0eed96ad6fe8f58881f31e1bf486 Mon Sep 17 00:00:00 2001 -From: Venkateswara Naralasetty -Date: Mon, 19 Apr 2021 11:11:06 +0530 -Subject: [PATCH] ath11k: fix radar detection issue in 160mhz - -Failed to detect RADAR pulses in the secondary 80mhz when the -the AP's primary 80mzh is in non-dfs region in 160mhz. - -This is due to host is not setting WMI channel flags WMI_CHAN_INFO_DFS -and WMI_CHAN_INFO_DFS_FREQ2 in case of primary 80 is in non-dfs region. -HALPHY detects the RADAR pulses only when thse channel flags are set. - -Fix this issue by setting WMI channel flags WMI_CHAN_INFO_DFS and -WMI_CHAN_INFO_DFS_FREQ2 based on the radar_enabled flag from channel -context. - -Signed-off-by: Venkateswara Naralasetty ---- - drivers/net/wireless/ath/ath11k/mac.c | 15 +++++++++++---- - 1 file changed, 11 insertions(+), 4 deletions(-) - ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -7252,7 +7252,7 @@ static void ath11k_mac_op_remove_chanctx - static int - ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif, - const struct cfg80211_chan_def *chandef, -- bool restart) -+ bool restart, bool radar_enabled) - { - struct ath11k *ar = arvif->ar; - struct ath11k_base *ab = ar->ab; -@@ -7291,8 +7291,7 @@ ath11k_mac_vdev_start_restart(struct ath - arg.channel.chan_radar = - !!(chandef->chan->flags & IEEE80211_CHAN_RADAR); - -- arg.channel.freq2_radar = -- !!(chandef->chan->flags & IEEE80211_CHAN_RADAR); -+ arg.channel.freq2_radar = radar_enabled; - - arg.channel.passive = arg.channel.chan_radar; - -@@ -7405,15 +7404,19 @@ err: - } - - static int ath11k_mac_vdev_start(struct ath11k_vif *arvif, -- const struct cfg80211_chan_def *chandef) -+ const struct cfg80211_chan_def *chandef, -+ bool radar_enabled) - { -- return ath11k_mac_vdev_start_restart(arvif, chandef, false); -+ return ath11k_mac_vdev_start_restart(arvif, chandef, false, -+ radar_enabled); - } - - static int ath11k_mac_vdev_restart(struct ath11k_vif *arvif, -- const struct cfg80211_chan_def *chandef) -+ const struct cfg80211_chan_def *chandef, -+ bool radar_enabled) - { -- return ath11k_mac_vdev_start_restart(arvif, chandef, true); -+ return ath11k_mac_vdev_start_restart(arvif, chandef, true, -+ radar_enabled); - } - - struct ath11k_mac_change_chanctx_arg { -@@ -7482,16 +7485,17 @@ ath11k_mac_update_vif_chan(struct ath11k - if (WARN_ON(!arvif->is_started)) - continue; - -- if (WARN_ON(!arvif->is_up)) -- continue; -- -- ret = ath11k_mac_vdev_restart(arvif, &vifs[i].new_ctx->def); -+ ret = ath11k_mac_vdev_restart(arvif, &vifs[i].new_ctx->def, -+ vifs[i].new_ctx->radar_enabled); - if (ret) { - ath11k_warn(ab, "failed to restart vdev %d: %d\n", - arvif->vdev_id, ret); - continue; - } - -+ if (!arvif->is_up) -+ continue; -+ - ret = ath11k_mac_setup_bcn_tmpl(arvif); - if (ret) - ath11k_warn(ab, "failed to update bcn tmpl during csa: %d\n", -@@ -7583,7 +7587,8 @@ static void ath11k_mac_op_change_chanctx - if (WARN_ON(changed & IEEE80211_CHANCTX_CHANGE_CHANNEL)) - goto unlock; - -- if (changed & IEEE80211_CHANCTX_CHANGE_WIDTH) -+ if (changed & IEEE80211_CHANCTX_CHANGE_WIDTH || -+ changed & IEEE80211_CHANCTX_CHANGE_RADAR) - ath11k_mac_update_active_vif_chan(ar, ctx); - - /* TODO: Recalc radar detection */ -@@ -7603,7 +7608,8 @@ static int ath11k_start_vdev_delay(struc - if (WARN_ON(arvif->is_started)) - return -EBUSY; - -- ret = ath11k_mac_vdev_start(arvif, &arvif->chanctx.def); -+ ret = ath11k_mac_vdev_start(arvif, &arvif->chanctx.def, -+ arvif->chanctx.radar_enabled); - if (ret) { - ath11k_warn(ab, "failed to start vdev %i addr %pM on freq %d: %d\n", - arvif->vdev_id, vif->addr, -@@ -7689,7 +7695,7 @@ ath11k_mac_op_assign_vif_chanctx(struct - goto out; - } - -- ret = ath11k_mac_vdev_start(arvif, &ctx->def); -+ ret = ath11k_mac_vdev_start(arvif, &ctx->def, ctx->radar_enabled); - if (ret) { - ath11k_warn(ab, "failed to start vdev %i addr %pM on freq %d: %d\n", - arvif->vdev_id, vif->addr, diff --git a/feeds/ipq95xx/mac80211/patches/qca/306-ath11k-sta-dbg-level-log.patch b/feeds/ipq95xx/mac80211/patches/qca/306-ath11k-sta-dbg-level-log.patch index ce96e4444..41144ac55 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/306-ath11k-sta-dbg-level-log.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/306-ath11k-sta-dbg-level-log.patch @@ -17,7 +17,7 @@ Signed-off-by: Tamizh Chelvam --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -271,6 +271,11 @@ struct ath11k_dyn_vlan_cfg { +@@ -355,6 +355,11 @@ struct ath11k_dyn_vlan_cfg { struct list_head cfg_list; }; @@ -29,11 +29,13 @@ Signed-off-by: Tamizh Chelvam struct ath11k_vif { u32 vdev_id; enum wmi_vdev_type vdev_type; -@@ -327,7 +332,11 @@ struct ath11k_vif { +@@ -415,9 +420,13 @@ struct ath11k_vif { struct dentry *ampdu_aggr_size; struct dentry *amsdu_aggr_size; struct dentry *wmi_ctrl_stat; + struct dentry *mac_filter; + #endif /* CPTCFG_ATH11K_DEBUGFS */ + struct ath11k_mgmt_frame_stats mgmt_stats; + /* protected by conf_mutex */ + struct list_head mac_filters; @@ -45,15 +47,15 @@ Signed-off-by: Tamizh Chelvam +++ b/drivers/net/wireless/ath/ath11k/debug.h @@ -28,6 +28,7 @@ enum ath11k_debug_mask { ATH11K_DBG_DP_RX = 0x00004000, - ATH11K_DBG_CFR = 0x00008000, - ATH11K_DBG_CFR_DUMP = 0x00010000, -+ ATH11K_DBG_PEER = 0x00020000, - ATH11K_DBG_TEST = 0x00080000, + ATH11K_DBG_CFR = 0x00008000, + ATH11K_DBG_CFR_DUMP = 0x00010000, ++ ATH11K_DBG_PEER = 0x00020000, + ATH11K_DBG_TEST = 0x00080000, ATH11K_DBG_ANY = 0xffffffff, }; --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -458,6 +458,117 @@ static const struct file_operations ath1 +@@ -298,6 +298,117 @@ static const struct file_operations ath1 .read = ath11k_read_wmi_ctrl_path_stats, }; @@ -171,28 +173,9 @@ Signed-off-by: Tamizh Chelvam void ath11k_debugfs_wmi_ctrl_stats(struct ath11k_vif *arvif) { arvif->wmi_ctrl_stat = debugfs_create_file("wmi_ctrl_stats", 0644, ---- a/drivers/net/wireless/ath/ath11k/debugfs.h -+++ b/drivers/net/wireless/ath/ath11k/debugfs.h -@@ -182,11 +182,16 @@ enum ath11k_dbg_aggr_mode { - - #ifdef CPTCFG_MAC80211_DEBUGFS - void ath11k_debugfs_twt(struct ath11k_vif *arvif, bool enable); -+void ath11k_debugfs_dbg_mac_filter(struct ath11k_vif *arvif); - #else - static inline void ath11k_debugfs_twt(struct ath11k_vif *arvif, bool enable) - { - - } -+ -+static void ath11k_debugfs_dbg_mac_filter(struct ath11k_vif *arvif) -+{ -+} - #endif - - void ath11k_debug_aggr_size_config_init(struct ath11k_vif *arvif); --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -4548,6 +4548,25 @@ ath11k_mac_bitrate_mask_num_vht_rates(st +@@ -4565,6 +4565,25 @@ ath11k_mac_bitrate_mask_num_vht_rates(st return num_rates; } @@ -218,7 +201,7 @@ Signed-off-by: Tamizh Chelvam static int ath11k_mac_bitrate_mask_num_he_rates(struct ath11k *ar, enum nl80211_band band, -@@ -4739,9 +4758,15 @@ static int ath11k_station_assoc(struct a +@@ -4756,9 +4775,15 @@ static int ath11k_station_assoc(struct a enum nl80211_band band; struct cfg80211_bitrate_mask *mask; u8 num_vht_rates, num_he_rates, num_ht_rates; @@ -234,7 +217,7 @@ Signed-off-by: Tamizh Chelvam if (WARN_ON(ath11k_mac_vif_chan(vif, &def))) return -EPERM; -@@ -4828,10 +4853,16 @@ static int ath11k_station_disassoc(struc +@@ -4846,10 +4871,16 @@ static int ath11k_station_disassoc(struc struct ieee80211_sta *sta) { struct ath11k_vif *arvif = (void *)vif->drv_priv; @@ -251,7 +234,7 @@ Signed-off-by: Tamizh Chelvam if (!sta->wme) { arvif->num_legacy_stations--; ret = ath11k_recalc_rtscts_prot(arvif); -@@ -4863,6 +4894,7 @@ static void ath11k_sta_rc_update_wk(stru +@@ -4881,6 +4912,7 @@ static void ath11k_sta_rc_update_wk(stru int err, num_ht_rates, num_vht_rates, num_he_rates; const struct cfg80211_bitrate_mask *mask; struct peer_assoc_params peer_arg; @@ -259,7 +242,7 @@ Signed-off-by: Tamizh Chelvam arsta = container_of(wk, struct ath11k_sta, update_wk); sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv); -@@ -4895,6 +4927,8 @@ static void ath11k_sta_rc_update_wk(stru +@@ -4913,6 +4945,8 @@ static void ath11k_sta_rc_update_wk(stru mutex_lock(&ar->conf_mutex); @@ -268,7 +251,7 @@ Signed-off-by: Tamizh Chelvam nss = max_t(u32, 1, nss); nss = min(nss, max(max(ath11k_mac_max_ht_nss(ht_mcs_mask), ath11k_mac_max_vht_nss(vht_mcs_mask)), -@@ -4925,8 +4959,9 @@ static void ath11k_sta_rc_update_wk(stru +@@ -4943,8 +4977,9 @@ static void ath11k_sta_rc_update_wk(stru } if (changed & IEEE80211_RC_NSS_CHANGED) { @@ -280,7 +263,7 @@ Signed-off-by: Tamizh Chelvam err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, WMI_PEER_NSS, nss); -@@ -4936,8 +4971,9 @@ static void ath11k_sta_rc_update_wk(stru +@@ -4954,8 +4989,9 @@ static void ath11k_sta_rc_update_wk(stru } if (changed & IEEE80211_RC_SMPS_CHANGED) { @@ -292,7 +275,7 @@ Signed-off-by: Tamizh Chelvam err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, WMI_PEER_MIMO_PS_STATE, smps); -@@ -4947,6 +4983,10 @@ static void ath11k_sta_rc_update_wk(stru +@@ -4965,6 +5001,10 @@ static void ath11k_sta_rc_update_wk(stru } if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) { @@ -303,7 +286,7 @@ Signed-off-by: Tamizh Chelvam mask = &arvif->bitrate_mask; num_ht_rates = ath11k_mac_bitrate_mask_num_ht_rates(ar, band, mask); -@@ -5019,6 +5059,7 @@ static void ath11k_sta_set_4addr_wk(stru +@@ -5037,6 +5077,7 @@ static void ath11k_sta_set_4addr_wk(stru struct ath11k_base *ab; struct ath11k_peer *wds_peer; u8 wds_addr[ETH_ALEN]; @@ -311,7 +294,7 @@ Signed-off-by: Tamizh Chelvam u32 wds_peer_id; int ret = 0; -@@ -5028,13 +5069,18 @@ static void ath11k_sta_set_4addr_wk(stru +@@ -5046,13 +5087,18 @@ static void ath11k_sta_set_4addr_wk(stru ar = arvif->ar; ab = ar->ab; @@ -332,7 +315,7 @@ Signed-off-by: Tamizh Chelvam ret = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, -@@ -5195,6 +5241,7 @@ static int ath11k_mac_station_add(struct +@@ -5213,6 +5259,7 @@ static int ath11k_mac_station_add(struct struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv; struct peer_create_params peer_param; @@ -340,7 +323,7 @@ Signed-off-by: Tamizh Chelvam int ret; lockdep_assert_held(&ar->conf_mutex); -@@ -5206,6 +5253,7 @@ static int ath11k_mac_station_add(struct +@@ -5224,6 +5271,7 @@ static int ath11k_mac_station_add(struct goto exit; } @@ -348,7 +331,7 @@ Signed-off-by: Tamizh Chelvam arsta->rx_stats = kzalloc(sizeof(*arsta->rx_stats), GFP_KERNEL); if (!arsta->rx_stats) { ret = -ENOMEM; -@@ -5223,8 +5271,9 @@ static int ath11k_mac_station_add(struct +@@ -5241,8 +5289,9 @@ static int ath11k_mac_station_add(struct goto free_rx_stats; } @@ -360,7 +343,7 @@ Signed-off-by: Tamizh Chelvam ret = ath11k_mac_ap_ps_recalc(ar); if (ret) { -@@ -5241,8 +5290,9 @@ static int ath11k_mac_station_add(struct +@@ -5259,8 +5308,9 @@ static int ath11k_mac_station_add(struct } if (ieee80211_vif_is_mesh(vif)) { @@ -372,7 +355,7 @@ Signed-off-by: Tamizh Chelvam ret = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, WMI_PEER_USE_4ADDR, 1); -@@ -5361,7 +5411,7 @@ static int ath11k_mac_op_sta_state(struc +@@ -5380,7 +5430,7 @@ static int ath11k_mac_op_sta_state(struc sta->addr, arvif->vdev_id); else ath11k_dbg(ar->ab, @@ -381,7 +364,7 @@ Signed-off-by: Tamizh Chelvam "Removed peer: %pM for VDEV: %d\n", sta->addr, arvif->vdev_id); } -@@ -5475,6 +5525,10 @@ static int ath11k_mac_op_sta_state(struc +@@ -5497,6 +5547,10 @@ static int ath11k_mac_op_sta_state(struc sta->addr); } @@ -392,7 +375,7 @@ Signed-off-by: Tamizh Chelvam mutex_unlock(&ar->conf_mutex); return ret; } -@@ -7230,6 +7284,8 @@ static int ath11k_mac_op_add_interface(s +@@ -7225,6 +7279,8 @@ static int ath11k_mac_op_add_interface(s goto err; } @@ -401,7 +384,7 @@ Signed-off-by: Tamizh Chelvam switch (vif->type) { case NL80211_IFTYPE_UNSPECIFIED: case NL80211_IFTYPE_STATION: -@@ -7593,6 +7649,10 @@ err_vdev_del: +@@ -7579,6 +7635,10 @@ err_vdev_del: debugfs_remove(arvif->wmi_ctrl_stat); arvif->wmi_ctrl_stat = NULL; @@ -414,10 +397,10 @@ Signed-off-by: Tamizh Chelvam } --- a/drivers/net/wireless/ath/ath11k/mac.h +++ b/drivers/net/wireless/ath/ath11k/mac.h -@@ -174,4 +174,5 @@ enum hal_encrypt_type ath11k_dp_tx_get_e - void ath11k_mac_handle_beacon(struct ath11k *ar, struct sk_buff *skb); - void ath11k_mac_handle_beacon_miss(struct ath11k *ar, u32 vdev_id); - void ath11k_mac_bcn_tx_event(struct ath11k_vif *arvif); +@@ -177,4 +177,5 @@ int ath11k_mac_wait_tx_complete(struct a + int ath11k_mac_vif_set_keepalive(struct ath11k_vif *arvif, + enum wmi_sta_keepalive_method method, + u32 interval); +bool ath11k_mac_sta_level_info(struct ath11k_vif *arvif, struct ieee80211_sta *sta); #endif --- a/drivers/net/wireless/ath/ath11k/peer.c @@ -458,7 +441,7 @@ Signed-off-by: Tamizh Chelvam spin_unlock_bh(&ab->base_lock); goto exit; -@@ -782,6 +785,11 @@ int ath11k_peer_create(struct ath11k *ar +@@ -898,6 +901,11 @@ int ath11k_peer_create(struct ath11k *ar ar->num_peers++; @@ -468,11 +451,11 @@ Signed-off-by: Tamizh Chelvam + } + spin_unlock_bh(&ar->ab->base_lock); + mutex_unlock(&ar->ab->tbl_mtx_lock); - return 0; --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -8342,9 +8342,9 @@ static void ath11k_peer_sta_kickout_even +@@ -8392,9 +8392,9 @@ static void ath11k_peer_sta_kickout_even goto exit; } @@ -487,7 +470,7 @@ Signed-off-by: Tamizh Chelvam exit: --- a/drivers/net/wireless/ath/ath11k/peer.h +++ b/drivers/net/wireless/ath/ath11k/peer.h -@@ -91,6 +91,7 @@ struct ath11k_peer { +@@ -97,6 +97,7 @@ struct ath11k_peer { struct ppdu_user_delayba ppdu_stats_delayba; bool delayba_flag; @@ -495,3 +478,18 @@ Signed-off-by: Tamizh Chelvam }; void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id); +--- a/drivers/net/wireless/ath/ath11k/debugfs.h ++++ b/drivers/net/wireless/ath/ath11k/debugfs.h +@@ -427,7 +427,12 @@ static inline int ath11k_debug_is_memory + return ab->enable_memory_stats; + } + ++void ath11k_debugfs_dbg_mac_filter(struct ath11k_vif *arvif); + #else ++ ++static void ath11k_debugfs_dbg_mac_filter(struct ath11k_vif *arvif) ++{ ++} + static inline int ath11k_debugfs_create(void) + { + return 0; diff --git a/feeds/ipq95xx/mac80211/patches/qca/307-ath11k-fix-256-BA-mode.patch b/feeds/ipq95xx/mac80211/patches/qca/307-ath11k-fix-256-BA-mode.patch deleted file mode 100644 index c303bfb0a..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/307-ath11k-fix-256-BA-mode.patch +++ /dev/null @@ -1,41 +0,0 @@ -diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c -index cbd48137a3c5..7290175ceaf3 100644 ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -3104,6 +3104,21 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw, - arvif->do_not_send_tmpl = true; - else - arvif->do_not_send_tmpl = false; -+ -+ if (vif->bss_conf.he_support) { -+ ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, -+ WMI_VDEV_PARAM_BA_MODE, -+ WMI_BA_MODE_BUFFER_SIZE_256); -+ if (ret) { -+ ath11k_warn(ar->ab, -+ "failed to set BA BUFFER SIZE 256 for vdev: %d\n", -+ arvif->vdev_id); -+ } else { -+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, -+ "Set BA BUFFER SIZE 256 for VDEV: %d\n", -+ arvif->vdev_id); -+ } -+ } - } - - if (changed & (BSS_CHANGED_BEACON_INFO | BSS_CHANGED_BEACON)) { -@@ -3141,14 +3156,6 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw, - - if (arvif->is_up && vif->bss_conf.he_support && - vif->bss_conf.he_oper.params) { -- ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, -- WMI_VDEV_PARAM_BA_MODE, -- WMI_BA_MODE_BUFFER_SIZE_256); -- if (ret) -- ath11k_warn(ar->ab, -- "failed to set BA BUFFER SIZE 256 for vdev: %d\n", -- arvif->vdev_id); -- - param_id = WMI_VDEV_PARAM_HEOPS_0_31; - param_value = vif->bss_conf.he_oper.params; - ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, diff --git a/feeds/ipq95xx/mac80211/patches/qca/307-mac80211-support-to-dump-cont-tx-fail-count-in-mesh.patch b/feeds/ipq95xx/mac80211/patches/qca/307-mac80211-support-to-dump-cont-tx-fail-count-in-mesh.patch index b84551f6f..d99b613b4 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/307-mac80211-support-to-dump-cont-tx-fail-count-in-mesh.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/307-mac80211-support-to-dump-cont-tx-fail-count-in-mesh.patch @@ -14,11 +14,9 @@ Signed-off-by: Hari Chandrakanthan net/wireless/nl80211.c | 22 ++++++++++++ 7 files changed, 185 insertions(+), 3 deletions(-) -diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h -index a815e49..6a21dd9 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h -@@ -7477,6 +7477,11 @@ void cfg80211_cqm_pktloss_notify(struct net_device *dev, +@@ -8057,6 +8057,11 @@ void cfg80211_cqm_pktloss_notify(struct void cfg80211_cqm_txe_notify(struct net_device *dev, const u8 *peer, u32 num_packets, u32 rate, u32 intvl, gfp_t gfp); @@ -30,11 +28,9 @@ index a815e49..6a21dd9 100644 /** * cfg80211_cqm_beacon_loss_notify - beacon loss event * @dev: network device -diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h -index 74ff51c..8f72ca3 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h -@@ -5012,6 +5012,11 @@ enum nl80211_ps_state { +@@ -5236,6 +5236,11 @@ enum nl80211_ps_state { NL80211_PS_ENABLED, }; @@ -46,7 +42,7 @@ index 74ff51c..8f72ca3 100644 /** * enum nl80211_attr_cqm - connection quality monitor attributes * @__NL80211_ATTR_CQM_INVALID: invalid -@@ -5056,6 +5061,7 @@ enum nl80211_attr_cqm { +@@ -5280,6 +5285,7 @@ enum nl80211_attr_cqm { NL80211_ATTR_CQM_TXE_INTVL, NL80211_ATTR_CQM_BEACON_LOSS_EVENT, NL80211_ATTR_CQM_RSSI_LEVEL, @@ -54,11 +50,9 @@ index 74ff51c..8f72ca3 100644 /* keep last */ __NL80211_ATTR_CQM_AFTER_LAST, -diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c -index 9da69aa..8e656ea 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c -@@ -508,6 +508,49 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, +@@ -526,6 +526,57 @@ static ssize_t sta_ht_capa_read(struct f } STA_OPS(ht_capa); @@ -66,7 +60,7 @@ index 9da69aa..8e656ea 100644 + size_t count, loff_t *ppos) +{ + struct sta_info *sta = file->private_data; -+ char buf[12 * MAX_TX_FAIL_CNT], *p = buf; ++ char buf[18 * MAX_TX_FAIL_CNT], *p = buf; + int i; + + if(!sta->mesh) { @@ -74,12 +68,18 @@ index 9da69aa..8e656ea 100644 + return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); + } + ++ p += scnprintf(p, sizeof(buf) + buf - p, "\nTx Cont fail cnt info : \n"); + for (i = 0; i < MAX_TX_FAIL_CNT; i++) { + if (!sta->mesh->tx_fail_cnt[i]) + continue; + p += scnprintf(p, sizeof(buf) + buf - p, "%d : %u\n",i, + sta->mesh->tx_fail_cnt[i]); + } ++ ++ p += scnprintf(p, sizeof(buf) + buf - p, "mgmt fail cnt : %u\n", sta->mesh->mgmt_fail_cnt); ++ p += scnprintf(p, sizeof(buf) + buf - p, "current fail avg : %lu\n", ++ ewma_mesh_fail_avg_read(&sta->mesh->fail_avg)); ++ + return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); +} + @@ -96,8 +96,10 @@ index 9da69aa..8e656ea 100644 + if (!sta->mesh || ret || val >= MESH_TX_FAILURE_LOG_CTRL_MAX) + return -EINVAL; + -+ if (val & MESH_RESET_TX_FAIL_COUNT) ++ if (val & MESH_RESET_TX_FAIL_COUNT) { + memset(sta->mesh->tx_fail_cnt, 0, sizeof(u32) * MAX_TX_FAIL_CNT); ++ return count; ++ } + + sta->mesh->tx_fail_log = val; + return count; @@ -108,7 +110,7 @@ index 9da69aa..8e656ea 100644 static ssize_t sta_vht_capa_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { -@@ -1196,6 +1239,9 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) +@@ -1225,6 +1276,9 @@ void ieee80211_sta_debugfs_add(struct st DEBUGFS_ADD(reset_mac80211_rx_pkts_flow); DEBUGFS_ADD(mac80211_tx_pkts_flow); DEBUGFS_ADD(mac80211_rx_pkts_flow); @@ -116,13 +118,11 @@ index 9da69aa..8e656ea 100644 + DEBUGFS_ADD(tx_fail_cnt); +#endif - DEBUGFS_ADD_COUNTER(rx_duplicates, rx_stats.num_duplicates); - DEBUGFS_ADD_COUNTER(rx_fragments, rx_stats.fragments); -diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c -index b670cac..3310cde 100644 + DEBUGFS_ADD_COUNTER(rx_duplicates, deflink.rx_stats.num_duplicates); + DEBUGFS_ADD_COUNTER(rx_fragments, deflink.rx_stats.fragments); --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c -@@ -71,6 +71,9 @@ static inline u16 u16_field_get(const u8 *preq_elem, int offset, bool ae) +@@ -71,6 +71,9 @@ static inline u16 u16_field_get(const u8 #define SN_LT(x, y) ((s32)(x - y) < 0) #define MAX_SANE_SN_DELTA 32 @@ -132,9 +132,11 @@ index b670cac..3310cde 100644 static inline u32 SN_DELTA(u32 x, u32 y) { return x >= y ? x - y : y - x; -@@ -297,11 +300,24 @@ void ieee80211s_update_metric(struct ieee80211_local *local, +@@ -296,12 +299,28 @@ void ieee80211s_update_metric(struct iee + struct sta_info *sta, struct ieee80211_tx_status *st) { ++ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) st->skb->data; struct ieee80211_tx_info *txinfo = st->info; - int failed; + int failed = 0; @@ -142,9 +144,11 @@ index b670cac..3310cde 100644 failed = !(txinfo->flags & IEEE80211_TX_STAT_ACK); -+ if (failed) ++ if (failed) { + sta->mesh->fail_cnt++; -+ else if (sta->mesh->fail_cnt) { ++ if (ieee80211_is_mgmt(hdr->frame_control)) ++ sta->mesh->mgmt_fail_cnt++; ++ } else if (sta->mesh->fail_cnt) { + if (sta->mesh->fail_cnt >= MAX_TX_FAIL_CNT && + (sta->mesh->tx_fail_log & MESH_ENABLE_MPL_LOG)) + sdata_info(sta->sdata, " MESH MPL HIGHER fail count %u for peer %pM\n", @@ -158,7 +162,7 @@ index b670cac..3310cde 100644 /* moving average, scaled to 100. * feed failure as 100 and success as 0 */ -@@ -367,6 +383,30 @@ next_hop_deref_protected(struct mesh_path *mpath) +@@ -372,6 +391,33 @@ next_hop_deref_protected(struct mesh_pat lockdep_is_held(&mpath->state_lock)); } @@ -173,7 +177,10 @@ index b670cac..3310cde 100644 + cfg80211_cqm_mpath_change_notify(sta->sdata->dev, sta->sta.addr, + event, GFP_ATOMIC); + -+ sdata_info(sta->sdata, "MESH MPL continuous fail count :\n"); ++ if (event == NL80211_MPATH_METRIC_CHANGE) ++ return; ++ ++ sdata_info(sta->sdata, "MESH MPL continuous fail count for mesh %pM :\n", sta->addr); + for (i = 0; i < MAX_TX_FAIL_CNT; i++) { + if (!sta->mesh->tx_fail_cnt[i]) + continue; @@ -182,14 +189,14 @@ index b670cac..3310cde 100644 + sta->mesh->tx_fail_cnt[i]); + } + -+ sdata_info(sta->sdata, "current continuous tx fail count %u\n", -+ sta->mesh->fail_cnt); ++ sdata_info(sta->sdata, "current continuous tx fail count %u mgmt fail cnt %u fail avg : %lu\n", ++ sta->mesh->fail_cnt, sta->mesh->mgmt_fail_cnt, ewma_mesh_fail_avg_read(&sta->mesh->fail_avg)); +} + /** * hwmp_route_info_get - Update routing info to originator and transmitter * -@@ -399,6 +439,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, +@@ -404,6 +450,8 @@ static u32 hwmp_route_info_get(struct ie u32 last_hop_metric, new_metric; bool process = true; u8 hopcount; @@ -198,7 +205,7 @@ index b670cac..3310cde 100644 rcu_read_lock(); sta = sta_info_get(sdata, mgmt->sa); -@@ -497,8 +539,23 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, +@@ -502,8 +550,23 @@ static u32 hwmp_route_info_get(struct ie next_hop = rcu_dereference(mpath->next_hop); if (next_hop) ether_addr_copy(old_next_hop_addr, next_hop->sta.addr); @@ -207,23 +214,23 @@ index b670cac..3310cde 100644 mpath->path_change_count++; + mpath_dbg(sdata, "MESH MPU dst %pM next hop %pM" + " metric %d ft 0x%x\n", -+ mpath->dst, sta->addr, last_hop_metric, action); ++ mpath->dst, sta->deflink.addr, last_hop_metric, action); + } else if (MP_DIFF(new_metric, mpath->metric) > + (mpath->metric*LOG_PERCENT_DIFF)/100) { -+ signal_avg = -ewma_signal_read(&sta->rx_stats_avg.signal); ++ signal_avg = -ewma_signal_read(&sta->deflink.rx_stats_avg.signal); + mpath_dbg(sdata, "MESH MPLMU DIRECT dst %pM next hop" + " %pM metric from %d to %d ft 0x%x signal %d" + "dbm signal_avg %d dbm\n", -+ mpath->dst, sta->addr, mpath->metric, ++ mpath->dst, sta->deflink.addr, mpath->metric, + new_metric, action, -+ sta->rx_stats.last_signal, ++ sta->deflink.rx_stats.last_signal, + signal_avg); + mpath_metric_change = 1; + } mesh_path_assign_nexthop(mpath, sta); mpath->flags |= MESH_PATH_SN_VALID; mpath->metric = new_metric; -@@ -550,8 +607,24 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, +@@ -559,8 +622,24 @@ static u32 hwmp_route_info_get(struct ie next_hop = rcu_dereference(mpath->next_hop); if (next_hop) ether_addr_copy(old_next_hop_addr, next_hop->sta.addr); @@ -232,16 +239,16 @@ index b670cac..3310cde 100644 mpath->path_change_count++; + mpath_dbg(sdata, "MESH MPU dst %pM next hop %pM" + " metric %d ft 0x%x\n", -+ mpath->dst, sta->addr, last_hop_metric, action); ++ mpath->dst, sta->deflink.addr, last_hop_metric, action); + } else if (MP_DIFF(last_hop_metric, mpath->metric) > + (mpath->metric*LOG_PERCENT_DIFF)/100) { -+ signal_avg = -ewma_signal_read(&sta->rx_stats_avg.signal); ++ signal_avg = -ewma_signal_read(&sta->deflink.rx_stats_avg.signal); + mpath_dbg(sdata, "MESH MPLMU DIRECT dst %pM next hop" + " %pM metric from %d to %d ft 0x%x signal" + " %d dbm signal_avg %d dbm\n", -+ mpath->dst, sta->addr, mpath->metric, ++ mpath->dst, sta->deflink.addr, mpath->metric, + last_hop_metric, action, -+ sta->rx_stats.last_signal, ++ sta->deflink.rx_stats.last_signal, + signal_avg); + mpath_metric_change = 1; + } @@ -249,7 +256,7 @@ index b670cac..3310cde 100644 mesh_path_assign_nexthop(mpath, sta); mpath->metric = last_hop_metric; mpath->exp_time = time_after(mpath->exp_time, exp_time) -@@ -569,6 +642,9 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, +@@ -578,6 +657,9 @@ static u32 hwmp_route_info_get(struct ie spin_unlock_bh(&mpath->state_lock); } @@ -259,19 +266,17 @@ index b670cac..3310cde 100644 rcu_read_unlock(); return process ? new_metric : 0; -diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c -index ce44ecc..80e6c87 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c -@@ -601,6 +601,7 @@ void mesh_plink_broken(struct sta_info *sta) - struct mesh_table *tbl = sdata->u.mesh.mesh_paths; +@@ -596,6 +596,7 @@ void mesh_plink_broken(struct sta_info * + struct mesh_table *tbl = &sdata->u.mesh.mesh_paths; static const u8 bcast[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; struct mesh_path *mpath; + int paths_deactivated = 0, signal_avg; rcu_read_lock(); hlist_for_each_entry_rcu(mpath, &tbl->walk_head, walk_list) { -@@ -615,9 +616,20 @@ void mesh_plink_broken(struct sta_info *sta) +@@ -610,9 +611,19 @@ void mesh_plink_broken(struct sta_info * sdata->u.mesh.mshcfg.element_ttl, mpath->dst, mpath->sn, WLAN_REASON_MESH_PATH_DEST_UNREACHABLE, bcast); @@ -280,20 +285,17 @@ index ce44ecc..80e6c87 100644 } rcu_read_unlock(); + if (paths_deactivated) { -+ signal_avg = -ewma_signal_read(&sta->rx_stats_avg.signal); -+ if(sta->mesh->tx_fail_log & MESH_ENABLE_MPL_LOG) -+ sdata_info(sta->sdata, " MESH MPL link to %pM is broken and" -+ " %d path deactivated signal %d dbm signal_avg %d dbm\n", -+ sta->addr, paths_deactivated, -+ sta->rx_stats.last_signal, -+ signal_avg); ++ signal_avg = -ewma_signal_read(&sta->deflink.rx_stats_avg.signal); ++ sdata_info(sta->sdata, " MESH MPL link to %pM is broken and" ++ " %d path deactivated signal %d dbm signal_avg %d dbm\n", ++ sta->deflink.addr, paths_deactivated, ++ sta->deflink.rx_stats.last_signal, ++ signal_avg); + mesh_continuous_tx_fail_cnt(sta, NL80211_MPATH_BROKEN_NOTIFY); + } } static void mesh_path_free_rcu(struct mesh_table *tbl, -diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h -index 2e2122e..03144ed 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -123,6 +123,15 @@ enum ieee80211_sta_info_flags { @@ -312,7 +314,7 @@ index 2e2122e..03144ed 100644 DECLARE_EWMA(avg_signal, 10, 8) enum ieee80211_agg_stop_reason { AGG_STOP_DECLINED, -@@ -423,6 +432,10 @@ struct mesh_sta { +@@ -426,6 +435,11 @@ struct mesh_sta { struct ewma_mesh_fail_avg fail_avg; /* moving average of tx bitrate */ struct ewma_mesh_tx_rate_avg tx_rate_avg; @@ -320,10 +322,11 @@ index 2e2122e..03144ed 100644 + u32 fail_cnt; + u32 tx_fail_cnt[MAX_TX_FAIL_CNT]; + u8 tx_fail_log; ++ u32 mgmt_fail_cnt; }; DECLARE_EWMA(signal, 10, 8) -@@ -834,6 +847,8 @@ u8 sta_info_tx_streams(struct sta_info *sta); +@@ -923,6 +937,8 @@ void ieee80211_sta_remove_link(struct st void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta); void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta); void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta); @@ -332,11 +335,9 @@ index 2e2122e..03144ed 100644 unsigned long ieee80211_sta_last_active(struct sta_info *sta); -diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c -index b62438d..5279a6b 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c -@@ -17380,6 +17380,28 @@ void cfg80211_cqm_txe_notify(struct net_device *dev, +@@ -18749,6 +18749,28 @@ void cfg80211_cqm_txe_notify(struct net_ } EXPORT_SYMBOL(cfg80211_cqm_txe_notify); @@ -365,6 +366,3 @@ index b62438d..5279a6b 100644 void cfg80211_cqm_pktloss_notify(struct net_device *dev, const u8 *peer, u32 num_packets, gfp_t gfp) { --- -2.7.4 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/308-ath11k-poll-reo-status-ipq5018.patch b/feeds/ipq95xx/mac80211/patches/qca/308-ath11k-poll-reo-status-ipq5018.patch deleted file mode 100644 index 5d83113a4..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/308-ath11k-poll-reo-status-ipq5018.patch +++ /dev/null @@ -1,228 +0,0 @@ -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 ---- - drivers/net/wireless/ath/ath11k/core.c | 8 ++++- - drivers/net/wireless/ath/ath11k/dp.c | 59 +++++++++++++++++++++++++++++++++ - drivers/net/wireless/ath/ath11k/dp.h | 8 +++++ - drivers/net/wireless/ath/ath11k/dp_tx.c | 4 +++ - drivers/net/wireless/ath/ath11k/hw.c | 31 +++++++++++++++++ - drivers/net/wireless/ath/ath11k/hw.h | 2 ++ - 6 files changed, 111 insertions(+), 1 deletion(-) - ---- a/drivers/net/wireless/ath/ath11k/core.c -+++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -140,6 +140,7 @@ static const struct ath11k_hw_params ath - .current_cc_support = false, - /* In addition to TCL ring use TCL_CMD ring also for tx */ - .max_tx_ring = DP_TCL_NUM_RING_MAX + 1, -+ .reo_status_poll = false, - }, - { - .hw_rev = ATH11K_HW_IPQ6018_HW10, -@@ -214,6 +215,7 @@ static const struct ath11k_hw_params ath - .current_cc_support = false, - /* In addition to TCL ring use TCL_CMD ring also for tx */ - .max_tx_ring = DP_TCL_NUM_RING_MAX + 1, -+ .reo_status_poll = false, - }, - { - .name = "qca6390 hw2.0", -@@ -283,6 +285,7 @@ static const struct ath11k_hw_params ath - .supports_rssi_stats = true, - .fw_wmi_diag_event = true, - .current_cc_support = true, -+ .reo_status_poll = false, - }, - { - .name = "qcn9074 hw1.0", -@@ -364,6 +367,7 @@ static const struct ath11k_hw_params ath - - /* In addition to TCL ring use TCL_CMD ring also for tx */ - .max_tx_ring = DP_TCL_NUM_RING_MAX + 1, -+ .reo_status_poll = false, - }, - { - .name = "wcn6855 hw2.0", -@@ -433,6 +437,7 @@ static const struct ath11k_hw_params ath - .supports_rssi_stats = true, - .fw_wmi_diag_event = true, - .current_cc_support = true, -+ .reo_status_poll = false, - }, - { - .name = "wcn6855 hw2.1", -@@ -501,6 +506,7 @@ static const struct ath11k_hw_params ath - .supports_rssi_stats = true, - .fw_wmi_diag_event = true, - .current_cc_support = true, -+ .reo_status_poll = false, - }, - { - .hw_rev = ATH11K_HW_IPQ5018, -@@ -567,6 +573,7 @@ static const struct ath11k_hw_params ath - .cfr_stream_buf_size = 8500, - /* In addition to TCL ring use TCL_CMD ring also for tx */ - .max_tx_ring = DP_TCL_NUM_RING_MAX, -+ .reo_status_poll = false, - }, - { - .hw_rev = ATH11K_HW_QCN6122, -@@ -622,6 +629,7 @@ static const struct ath11k_hw_params ath - .fwmem_mode_change = false, - .is_qdss_support = false, - .max_tx_ring = DP_TCL_NUM_RING_MAX, -+ .reo_status_poll = false, - }, - }; - ---- a/drivers/net/wireless/ath/ath11k/dp.c -+++ b/drivers/net/wireless/ath/ath11k/dp.c -@@ -368,12 +368,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); -@@ -394,6 +448,8 @@ static int ath11k_dp_srng_common_setup(s - struct hal_srng *srng; - int i, ret; - -+ 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 -@@ -43,6 +43,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; -@@ -292,6 +294,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 */ -@@ -1885,5 +1891,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 -@@ -901,6 +901,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 -@@ -232,6 +232,7 @@ struct ath11k_hw_params { - u32 cfr_dma_hdr_size; - u32 cfr_num_stream_bufs; - u32 cfr_stream_buf_size; -+ bool reo_status_poll; - bool supports_rssi_stats; - bool fw_wmi_diag_event; - bool current_cc_support; diff --git a/feeds/ipq95xx/mac80211/patches/qca/309-ath11k-support-to-calculate-medium-busy.patch b/feeds/ipq95xx/mac80211/patches/qca/309-ath11k-support-to-calculate-medium-busy.patch index 07f5d3f17..b32efa56c 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/309-ath11k-support-to-calculate-medium-busy.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/309-ath11k-support-to-calculate-medium-busy.patch @@ -14,7 +14,7 @@ Signed-off-by: Hari Chandrakanthan --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -4252,6 +4252,30 @@ static const struct file_operations fops +@@ -4057,6 +4057,30 @@ static const struct file_operations fops .llseek = default_llseek, }; @@ -45,18 +45,18 @@ Signed-off-by: Hari Chandrakanthan int ath11k_debugfs_register(struct ath11k *ar) { struct ath11k_base *ab = ar->ab; -@@ -4360,6 +4384,8 @@ int ath11k_debugfs_register(struct ath11 +@@ -4169,6 +4193,8 @@ int ath11k_debugfs_register(struct ath11 ar->debug.debugfs_pdev, ar, &fops_ani_poll_period); debugfs_create_file("ani_listen_period", S_IRUSR | S_IWUSR, ar->debug.debugfs_pdev, ar, &fops_ani_listen_period); + debugfs_create_file("medium_busy", S_IRUSR, ar->debug.debugfs_pdev, ar, + &fops_medium_busy); - return 0; } + --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -6852,6 +6852,7 @@ static int ath11k_wmi_tlv_fw_stats_data_ +@@ -6892,6 +6892,7 @@ static int ath11k_wmi_tlv_fw_stats_data_ struct ath11k_sta *arsta; int i, ret = 0; const void *data = ptr; @@ -64,7 +64,7 @@ Signed-off-by: Hari Chandrakanthan if (!ev) { ath11k_warn(ab, "failed to fetch update stats ev"); -@@ -6887,7 +6888,16 @@ static int ath11k_wmi_tlv_fw_stats_data_ +@@ -6927,7 +6928,16 @@ static int ath11k_wmi_tlv_fw_stats_data_ ath11k_wmi_pull_pdev_stats_tx(&src->tx, dst); ath11k_wmi_pull_pdev_stats_rx(&src->rx, dst); list_add_tail(&dst->list, &stats->pdevs); @@ -81,7 +81,7 @@ Signed-off-by: Hari Chandrakanthan for (i = 0; i < ev->num_vdev_stats; i++) { const struct wmi_vdev_stats *src; -@@ -8461,6 +8471,9 @@ static void ath11k_chan_info_event(struc +@@ -8511,6 +8521,9 @@ static void ath11k_chan_info_event(struc SURVEY_INFO_TIME_BUSY; survey->time = div_u64(ch_info_ev.cycle_count, cc_freq_hz); survey->time_busy = div_u64(ch_info_ev.rx_clear_count, cc_freq_hz); @@ -93,9 +93,9 @@ Signed-off-by: Hari Chandrakanthan spin_unlock_bh(&ar->data_lock); --- a/include/net/mac80211.h +++ b/include/net/mac80211.h -@@ -2712,6 +2712,7 @@ struct ieee80211_hw { - u8 weight_multiplier; - u32 max_mtu; +@@ -2849,6 +2849,7 @@ struct ieee80211_hw { + const s8 *tx_power_levels; + u8 max_txpwr_levels_idx; u32 dbg_mask; + u8 medium_busy; }; @@ -103,31 +103,30 @@ Signed-off-by: Hari Chandrakanthan static inline bool _ieee80211_hw_check(struct ieee80211_hw *hw, --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c -@@ -549,11 +549,12 @@ static u32 hwmp_route_info_get(struct ie - signal_avg = -ewma_signal_read(&sta->rx_stats_avg.signal); +@@ -560,11 +560,12 @@ static u32 hwmp_route_info_get(struct ie + signal_avg = -ewma_signal_read(&sta->deflink.rx_stats_avg.signal); mpath_dbg(sdata, "MESH MPLMU DIRECT dst %pM next hop" " %pM metric from %d to %d ft 0x%x signal %d" - "dbm signal_avg %d dbm\n", + "dbm signal_avg %d dbm medium_busy %u\n", - mpath->dst, sta->addr, mpath->metric, + mpath->dst, sta->deflink.addr, mpath->metric, new_metric, action, - sta->rx_stats.last_signal, + sta->deflink.rx_stats.last_signal, - signal_avg); + signal_avg, + sta->local->hw.medium_busy); mpath_metric_change = 1; } mesh_path_assign_nexthop(mpath, sta); -@@ -621,11 +622,13 @@ static u32 hwmp_route_info_get(struct ie - signal_avg = -ewma_signal_read(&sta->rx_stats_avg.signal); +@@ -632,11 +633,12 @@ static u32 hwmp_route_info_get(struct ie + signal_avg = -ewma_signal_read(&sta->deflink.rx_stats_avg.signal); mpath_dbg(sdata, "MESH MPLMU DIRECT dst %pM next hop" " %pM metric from %d to %d ft 0x%x signal" - " %d dbm signal_avg %d dbm\n", -+ " %d dbm signal_avg %d dbm" -+ " medium_busy %u\n", - mpath->dst, sta->addr, mpath->metric, ++ " %d dbm signal_avg %d dbm medium_busy %u\n", + mpath->dst, sta->deflink.addr, mpath->metric, last_hop_metric, action, - sta->rx_stats.last_signal, + sta->deflink.rx_stats.last_signal, - signal_avg); + signal_avg, + sta->local->hw.medium_busy); @@ -136,17 +135,17 @@ Signed-off-by: Hari Chandrakanthan --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c -@@ -619,10 +619,11 @@ void mesh_plink_broken(struct sta_info * - signal_avg = -ewma_signal_read(&sta->rx_stats_avg.signal); - if(sta->mesh->tx_fail_log & MESH_ENABLE_MPL_LOG) - sdata_info(sta->sdata, " MESH MPL link to %pM is broken and" -- " %d path deactivated signal %d dbm signal_avg %d dbm\n", -+ " %d path deactivated signal %d dbm signal_avg %d dbm" -+ " medium_busy : %d\n", - sta->addr, paths_deactivated, - sta->rx_stats.last_signal, -- signal_avg); -+ signal_avg, sta->local->hw.medium_busy); +@@ -618,10 +618,11 @@ void mesh_plink_broken(struct sta_info * + if (paths_deactivated) { + signal_avg = -ewma_signal_read(&sta->deflink.rx_stats_avg.signal); + sdata_info(sta->sdata, " MESH MPL link to %pM is broken and" +- " %d path deactivated signal %d dbm signal_avg %d dbm\n", ++ " %d path deactivated signal %d dbm signal_avg %d dbm" ++ " medium_busy : %d\n", + sta->deflink.addr, paths_deactivated, + sta->deflink.rx_stats.last_signal, +- signal_avg); ++ signal_avg, sta->local->hw.medium_busy); mesh_continuous_tx_fail_cnt(sta, NL80211_MPATH_BROKEN_NOTIFY); } } diff --git a/feeds/ipq95xx/mac80211/patches/qca/310-ath11k-fix-max-peer-count-in-ipq5018-and-qcn6122.patch b/feeds/ipq95xx/mac80211/patches/qca/310-ath11k-fix-max-peer-count-in-ipq5018-and-qcn6122.patch index 682da8308..5c7702cb3 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/310-ath11k-fix-max-peer-count-in-ipq5018-and-qcn6122.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/310-ath11k-fix-max-peer-count-in-ipq5018-and-qcn6122.patch @@ -21,7 +21,7 @@ Signed-off-by: Hari Chandrakanthan --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -64,6 +64,9 @@ EXPORT_SYMBOL(ath11k_skip_radio); +@@ -65,6 +65,9 @@ EXPORT_SYMBOL(ath11k_skip_radio); struct ath11k_base *ath11k_soc[MAX_SOCS]; @@ -31,50 +31,74 @@ Signed-off-by: Hari Chandrakanthan static const struct ath11k_hw_params ath11k_hw_params[] = { { .hw_rev = ATH11K_HW_IPQ8074, -@@ -141,6 +144,7 @@ static const struct ath11k_hw_params ath +@@ -147,6 +150,7 @@ static const struct ath11k_hw_params ath + .support_off_channel_tx = false, /* In addition to TCL ring use TCL_CMD ring also for tx */ .max_tx_ring = DP_TCL_NUM_RING_MAX + 1, - .reo_status_poll = false, + .num_vdevs_peers = ath11k_vdevs_peers, }, { .hw_rev = ATH11K_HW_IPQ6018_HW10, -@@ -216,6 +220,7 @@ static const struct ath11k_hw_params ath +@@ -227,6 +231,7 @@ static const struct ath11k_hw_params ath + .support_off_channel_tx = false, /* In addition to TCL ring use TCL_CMD ring also for tx */ .max_tx_ring = DP_TCL_NUM_RING_MAX + 1, - .reo_status_poll = false, + .num_vdevs_peers = ath11k_vdevs_peers, }, { .name = "qca6390 hw2.0", -@@ -286,6 +291,7 @@ static const struct ath11k_hw_params ath - .fw_wmi_diag_event = true, - .current_cc_support = true, - .reo_status_poll = false, +@@ -302,6 +307,7 @@ static const struct ath11k_hw_params ath + .hybrid_bus_type = false, + .fixed_fw_mem = false, + .support_off_channel_tx = true, + .num_vdevs_peers = ath11k_vdevs_peers, }, { .name = "qcn9074 hw1.0", -@@ -368,6 +374,7 @@ static const struct ath11k_hw_params ath +@@ -388,6 +394,7 @@ static const struct ath11k_hw_params ath + CFR_DATA_MAX_LEN_QCN9074, /* In addition to TCL ring use TCL_CMD ring also for tx */ .max_tx_ring = DP_TCL_NUM_RING_MAX + 1, - .reo_status_poll = false, + .num_vdevs_peers = ath11k_vdevs_peers, }, { .name = "wcn6855 hw2.0", -@@ -573,6 +580,7 @@ static const struct ath11k_hw_params ath +@@ -463,6 +470,7 @@ static const struct ath11k_hw_params ath + .hybrid_bus_type = false, + .fixed_fw_mem = false, + .support_off_channel_tx = true, ++ .num_vdevs_peers = ath11k_vdevs_peers, + }, + { + .name = "wcn6855 hw2.1", +@@ -537,6 +545,7 @@ static const struct ath11k_hw_params ath + .hybrid_bus_type = false, + .fixed_fw_mem = false, + .support_off_channel_tx = true, ++ .num_vdevs_peers = ath11k_vdevs_peers, + }, + { + .name = "wcn6750 hw1.0", +@@ -610,6 +619,7 @@ static const struct ath11k_hw_params ath + .support_off_channel_tx = false, + .ce_window = 2, + .dp_window = 1, ++ .num_vdevs_peers = ath11k_vdevs_peers, + }, + { + .hw_rev = ATH11K_HW_IPQ5018, +@@ -684,6 +694,7 @@ static const struct ath11k_hw_params ath + .cfr_stream_buf_size = 8500, /* In addition to TCL ring use TCL_CMD ring also for tx */ .max_tx_ring = DP_TCL_NUM_RING_MAX, - .reo_status_poll = false, + .num_vdevs_peers = ath11k_vdevs_peers_ipq5018, }, { .hw_rev = ATH11K_HW_QCN6122, -@@ -628,9 +636,25 @@ static const struct ath11k_hw_params ath - .is_qdss_support = false, +@@ -756,9 +767,25 @@ static const struct ath11k_hw_params ath + .qdss_offset = ATH11K_QMI_QCN6122_QDSS_OFFSET, + .caldb_offset = ATH11K_QMI_QCN6122_CALDB_OFFSET, .max_tx_ring = DP_TCL_NUM_RING_MAX, - .reo_status_poll = false, + .num_vdevs_peers = ath11k_vdevs_peers_ipq5018, }, }; @@ -91,13 +115,13 @@ Signed-off-by: Hari Chandrakanthan + { + .num_vdevs = 8, + .num_peers = 128, -+ }, ++ } +}; + static const struct ath11k_num_vdevs_peers ath11k_vdevs_peers[] = { { .num_vdevs = (16 + 1), -@@ -1081,8 +1105,6 @@ static int ath11k_core_soc_create(struct +@@ -1396,8 +1423,6 @@ static int ath11k_core_soc_create(struct ath11k_info(ab, "Booting in ftm mode - %d\n", ab->fw_mode); } @@ -108,17 +132,17 @@ Signed-off-by: Hari Chandrakanthan ath11k_err(ab, "failed to initialize qmi :%d\n", ret); --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -1079,7 +1079,6 @@ struct ath11k_base { +@@ -1228,7 +1228,6 @@ struct ath11k_base { bool ce_latency_stats_enable; u32 ce_remap_base_addr; atomic_t num_max_allowed; - struct ath11k_num_vdevs_peers *num_vdevs_peers; - int userpd_id; - struct ath11k_internal_pci ipci; bool enable_memory_stats; + + u32 rx_hash; --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h -@@ -15,10 +15,10 @@ struct ath11k_cfr_peer_tx_param; +@@ -16,10 +16,10 @@ struct ath11k_cfr_peer_tx_param; /* Target configuration defines */ #ifdef CPTCFG_ATH11K_MEM_PROFILE_512M @@ -132,32 +156,32 @@ Signed-off-by: Hari Chandrakanthan #define ATH11K_QMI_TARGET_MEM_MODE ATH11K_QMI_TARGET_MEM_MODE_512M #define ATH11K_DP_TX_COMP_RING_SIZE 8192 #define ATH11K_DP_RXDMA_MON_STATUS_RING_SIZE 512 -@@ -31,11 +31,10 @@ struct ath11k_cfr_peer_tx_param; +@@ -32,11 +32,10 @@ struct ath11k_cfr_peer_tx_param; #define ATH11K_DP_RXDMA_NSS_REFILL_RING_SIZE 1816 #else /* Num VDEVS per radio */ -#define TARGET_NUM_VDEVS(ab) (ab->hw_params.num_vdevs) - -#define TARGET_NUM_PEERS_PDEV(ab) (ab->hw_params.num_peers + TARGET_NUM_VDEVS(ab)) -+#define TARGET_NUM_VDEVS(ab) (ab->hw_params.num_vdevs_peers[ab->qmi.target_mem_mode].num_vdevs) -+#define TARGET_NUM_PEERS_PDEV(ab) (ab->hw_params.num_vdevs_peers[ab->qmi.target_mem_mode].num_peers + TARGET_NUM_VDEVS(ab)) ++#define TARGET_NUM_VDEVS(ab) (ab->hw_params.num_vdevs_peers[ab->qmi.target_mem_mode].num_vdevs) ++#define TARGET_NUM_PEERS_PDEV(ab) (ab->hw_params.num_vdevs_peers[ab->qmi.target_mem_mode].num_peers + TARGET_NUM_VDEVS(ab)) /* Max num of stations (per radio) */ --#define TARGET_NUM_STATIONS(ab) (ab->hw_params.num_peers) -+#define TARGET_NUM_STATIONS(ab) (ab->hw_params.num_vdevs_peers[ab->qmi.target_mem_mode].num_peers) +-#define TARGET_NUM_STATIONS(ab) (ab->hw_params.num_peers) ++#define TARGET_NUM_STATIONS(ab) (ab->hw_params.num_vdevs_peers[ab->qmi.target_mem_mode].num_peers) #define ATH11K_QMI_TARGET_MEM_MODE ATH11K_QMI_TARGET_MEM_MODE_DEFAULT #define ATH11K_DP_TX_COMP_RING_SIZE 32768 #define ATH11K_DP_RXDMA_MON_STATUS_RING_SIZE 1024 -@@ -234,6 +233,7 @@ struct ath11k_hw_params { +@@ -230,6 +229,7 @@ struct ath11k_hw_params { + u32 cfr_dma_hdr_size; u32 cfr_num_stream_bufs; u32 cfr_stream_buf_size; - bool reo_status_poll; + const struct ath11k_num_vdevs_peers *num_vdevs_peers; bool supports_rssi_stats; bool fw_wmi_diag_event; bool current_cc_support; --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -2808,7 +2808,7 @@ static ssize_t ath11k_dump_mgmt_stats(st +@@ -2810,7 +2810,7 @@ static ssize_t ath11k_dump_mgmt_stats(st struct ath11k_vif *arvif = NULL; struct ath11k_mgmt_frame_stats *mgmt_stats; int len = 0, ret, i; diff --git a/feeds/ipq95xx/mac80211/patches/qca/311-002-cfg80211-mitigate-A-MSDU-aggregation-attacks.patch b/feeds/ipq95xx/mac80211/patches/qca/311-002-cfg80211-mitigate-A-MSDU-aggregation-attacks.patch deleted file mode 100644 index 1b503f6af..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/311-002-cfg80211-mitigate-A-MSDU-aggregation-attacks.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 2b8a1fee3488c602aca8bea004a087e60806a5cf Mon Sep 17 00:00:00 2001 -From: Mathy Vanhoef -Date: Tue, 11 May 2021 20:02:45 +0200 -Subject: cfg80211: mitigate A-MSDU aggregation attacks - -Mitigate A-MSDU injection attacks (CVE-2020-24588) by detecting if the -destination address of a subframe equals an RFC1042 (i.e., LLC/SNAP) -header, and if so dropping the complete A-MSDU frame. This mitigates -known attacks, although new (unknown) aggregation-based attacks may -remain possible. - -This defense works because in A-MSDU aggregation injection attacks, a -normal encrypted Wi-Fi frame is turned into an A-MSDU frame. This means -the first 6 bytes of the first A-MSDU subframe correspond to an RFC1042 -header. In other words, the destination MAC address of the first A-MSDU -subframe contains the start of an RFC1042 header during an aggregation -attack. We can detect this and thereby prevent this specific attack. -For details, see Section 7.2 of "Fragment and Forge: Breaking Wi-Fi -Through Frame Aggregation and Fragmentation". - -Note that for kernel 4.9 and above this patch depends on "mac80211: -properly handle A-MSDUs that start with a rfc1042 header". Otherwise -this patch has no impact and attacks will remain possible. - -Cc: stable@vger.kernel.org -Signed-off-by: Mathy Vanhoef -Link: https://lore.kernel.org/r/20210511200110.25d93176ddaf.I9e265b597f2cd23eb44573f35b625947b386a9de@changeid -Signed-off-by: Johannes Berg ---- - net/wireless/util.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/net/wireless/util.c b/net/wireless/util.c -index 39966a873e40..7ec021a610ae 100644 ---- a/net/wireless/util.c -+++ b/net/wireless/util.c -@@ -771,6 +771,9 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, - remaining = skb->len - offset; - if (subframe_len > remaining) - goto purge; -+ /* mitigate A-MSDU aggregation injection attacks */ -+ if (ether_addr_equal(eth.h_dest, rfc1042_header)) -+ goto purge; - - offset += sizeof(struct ethhdr); - last = remaining <= subframe_len + padding; diff --git a/feeds/ipq95xx/mac80211/patches/qca/312-ath11k-add-ampdu-id-in-802.11-radiotap-header.patch b/feeds/ipq95xx/mac80211/patches/qca/312-ath11k-add-ampdu-id-in-802.11-radiotap-header.patch index 5e5a19976..811c5fc56 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/312-ath11k-add-ampdu-id-in-802.11-radiotap-header.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/312-ath11k-add-ampdu-id-in-802.11-radiotap-header.patch @@ -25,7 +25,7 @@ Signed-off-by: P Praneesh --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -5968,6 +5968,7 @@ static void ath11k_update_radiotap(struc +@@ -5865,6 +5865,7 @@ static void ath11k_update_radiotap(struc { struct ieee80211_supported_band *sband; u8 *ptr = NULL; @@ -33,9 +33,9 @@ Signed-off-by: P Praneesh rxs->flag |= RX_FLAG_MACTIME_START; rxs->signal = ppduinfo->rssi_comb + ATH11K_DEFAULT_NOISE_FLOOR; -@@ -5978,6 +5979,11 @@ static void ath11k_update_radiotap(struc - */ - rxs->nss = ppduinfo->nss ? ppduinfo->nss : ppduinfo->nss + 1; +@@ -5872,6 +5873,11 @@ static void ath11k_update_radiotap(struc + if (ppduinfo->nss) + rxs->nss = ppduinfo->nss; + if (ampdu_id) { + rxs->flag |= RX_FLAG_AMPDU_DETAILS; @@ -47,7 +47,7 @@ Signed-off-by: P Praneesh rxs->encoding = RX_ENC_HE; --- a/drivers/net/wireless/ath/ath11k/hal_rx.c +++ b/drivers/net/wireless/ath/ath11k/hal_rx.c -@@ -867,6 +867,13 @@ ath11k_hal_rx_populate_mu_user_info(void +@@ -884,6 +884,13 @@ ath11k_hal_rx_populate_mu_user_info(void ath11k_hal_rx_populate_byte_count(rx_tlv, ppdu_info, rx_user_status); } @@ -61,7 +61,7 @@ Signed-off-by: P Praneesh static enum hal_rx_mon_status ath11k_hal_rx_parse_mon_status_tlv(struct ath11k_base *ab, struct hal_rx_mon_ppdu_info *ppdu_info, -@@ -1521,6 +1530,12 @@ ath11k_hal_rx_parse_mon_status_tlv(struc +@@ -1556,6 +1563,12 @@ ath11k_hal_rx_parse_mon_status_tlv(struc ppdu_info->peer_id = peer_id; ppdu_info->mpdu_len += ab->hw_params.hw_ops->rx_desc_get_hal_mpdu_len(tlv_data); @@ -85,16 +85,16 @@ Signed-off-by: P Praneesh }; #define HAL_RX_UL_OFDMA_USER_INFO_V0_W0_VALID BIT(30) -@@ -443,15 +445,16 @@ struct hal_rx_phyrx_rssi_legacy_info { +@@ -453,15 +455,16 @@ struct hal_rx_phyrx_rssi_legacy_info { __le32 info0; } __packed; -#define HAL_RX_MPDU_INFO_INFO0_PEERID GENMASK(31, 16) #define HAL_RX_MPDU_INFO_INFO0_PEERID_WCN6855 GENMASK(15, 0) --#define HAL_RX_MPDU_INFO_INFO1_MPDU_LEN GENMASK(13, 0) -+#define HAL_RX_MPDU_INFO_INFO0_PPDU_ID GENMASK(31, 16) -+#define HAL_RX_MPDU_INFO_INFO1_PEERID GENMASK(31, 16) -+#define HAL_RX_MPDU_INFO_INFO2_MPDU_LEN GENMASK(13, 0) +-#define HAL_RX_MPDU_INFO_INFO1_MPDU_LEN GENMASK(13, 0) ++#define HAL_RX_MPDU_INFO_INFO0_PPDU_ID GENMASK(31, 16) ++#define HAL_RX_MPDU_INFO_INFO1_PEERID GENMASK(31, 16) ++#define HAL_RX_MPDU_INFO_INFO2_MPDU_LEN GENMASK(13, 0) struct hal_rx_mpdu_info { - __le32 rsvd0; @@ -106,7 +106,7 @@ Signed-off-by: P Praneesh __le32 rsvd2[9]; } __packed; -@@ -462,10 +465,11 @@ struct hal_rx_mpdu_info_wcn6855 { +@@ -472,10 +475,11 @@ struct hal_rx_mpdu_info_wcn6855 { } __packed; struct hal_rx_mpdu_info_qcn9074 { @@ -122,7 +122,7 @@ Signed-off-by: P Praneesh --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h -@@ -283,6 +283,7 @@ struct ath11k_hw_ops { +@@ -299,6 +299,7 @@ struct ath11k_hw_ops { void (*fill_cfr_hdr_info)(struct ath11k *ar, struct ath11k_csi_cfr_header *header, struct ath11k_cfr_peer_tx_param *params); @@ -132,7 +132,7 @@ Signed-off-by: P Praneesh extern const struct ath11k_hw_ops ipq8074_ops; --- a/drivers/net/wireless/ath/ath11k/hw.c +++ b/drivers/net/wireless/ath/ath11k/hw.c -@@ -13,6 +13,7 @@ +@@ -14,6 +14,7 @@ #include "hal.h" #include "hw.h" #include "hif.h" @@ -140,7 +140,7 @@ Signed-off-by: P Praneesh /* Map from pdev index to hw mac index */ static u8 ath11k_hw_ipq8074_mac_from_pdev_id(int pdev_idx) -@@ -986,16 +987,14 @@ static void ath11k_hw_ipq5018_reo_setup( +@@ -1002,16 +1003,14 @@ static void ath11k_hw_ipq5018_reo_setup( ath11k_hal_reo_hash_setup(ab, ring_hash_map); } @@ -161,7 +161,7 @@ Signed-off-by: P Praneesh } static -@@ -1004,8 +1003,40 @@ u32 ath11k_hw_ipq8074_rx_desc_get_hal_mp +@@ -1020,8 +1019,40 @@ u32 ath11k_hw_ipq8074_rx_desc_get_hal_mp struct hal_rx_mpdu_info *mpdu_info = (struct hal_rx_mpdu_info *)tlv_data; @@ -204,7 +204,7 @@ Signed-off-by: P Praneesh } static u16 ath11k_hw_wcn6855_mpdu_info_get_peerid(u8 *tlv_data) -@@ -1024,21 +1055,10 @@ static u16 ath11k_hw_qcn9074_mpdu_info_g +@@ -1046,21 +1077,10 @@ static u16 ath11k_hw_qcn9074_mpdu_info_g struct hal_rx_mpdu_info_qcn9074 *mpdu_info = (struct hal_rx_mpdu_info_qcn9074 *)tlv_data; @@ -228,7 +228,7 @@ Signed-off-by: P Praneesh static void ath11k_hw_ipq5018_set_rx_fragmentation_dst_ring(struct ath11k_base *ab) { u8 frag_dst_ring = HAL_SRNG_RING_ID_REO2SW1; -@@ -1312,6 +1332,7 @@ const struct ath11k_hw_ops ipq8074_ops = +@@ -1335,6 +1355,7 @@ const struct ath11k_hw_ops ipq8074_ops = .rx_desc_get_dot11_hdr = ath11k_hw_ipq8074_rx_desc_get_dot11_hdr, .rx_desc_get_crypto_header = ath11k_hw_ipq8074_rx_desc_get_crypto_hdr, .fill_cfr_hdr_info = ath11k_hw_ipq8074_fill_cfr_hdr_info, @@ -236,7 +236,7 @@ Signed-off-by: P Praneesh }; const struct ath11k_hw_ops ipq6018_ops = { -@@ -1361,6 +1382,7 @@ const struct ath11k_hw_ops ipq6018_ops = +@@ -1385,6 +1406,7 @@ const struct ath11k_hw_ops ipq6018_ops = .rx_desc_dot11_hdr_fields_valid = ath11k_hw_ipq8074_rx_desc_dot11_hdr_fields_valid, .rx_desc_get_dot11_hdr = ath11k_hw_ipq8074_rx_desc_get_dot11_hdr, .rx_desc_get_crypto_header = ath11k_hw_ipq8074_rx_desc_get_crypto_hdr, @@ -244,7 +244,7 @@ Signed-off-by: P Praneesh }; const struct ath11k_hw_ops qca6390_ops = { -@@ -1410,6 +1432,7 @@ const struct ath11k_hw_ops qca6390_ops = +@@ -1435,6 +1457,7 @@ const struct ath11k_hw_ops qca6390_ops = .rx_desc_dot11_hdr_fields_valid = ath11k_hw_ipq8074_rx_desc_dot11_hdr_fields_valid, .rx_desc_get_dot11_hdr = ath11k_hw_ipq8074_rx_desc_get_dot11_hdr, .rx_desc_get_crypto_header = ath11k_hw_ipq8074_rx_desc_get_crypto_hdr, @@ -252,7 +252,7 @@ Signed-off-by: P Praneesh }; const struct ath11k_hw_ops qcn9074_ops = { -@@ -1463,6 +1486,7 @@ const struct ath11k_hw_ops qcn9074_ops = +@@ -1489,6 +1512,7 @@ const struct ath11k_hw_ops qcn9074_ops = .rx_desc_get_dot11_hdr = ath11k_hw_qcn9074_rx_desc_get_dot11_hdr, .rx_desc_get_crypto_header = ath11k_hw_qcn9074_rx_desc_get_crypto_hdr, .fill_cfr_hdr_info = ath11k_hw_qcn9074_fill_cfr_hdr_info, @@ -260,26 +260,18 @@ Signed-off-by: P Praneesh }; const struct ath11k_hw_ops wcn6855_ops = { -@@ -1504,6 +1528,7 @@ const struct ath11k_hw_ops wcn6855_ops = +@@ -1531,6 +1555,7 @@ const struct ath11k_hw_ops wcn6855_ops = .set_rx_fragmentation_dst_ring = ath11k_hw_wcn6855_set_rx_fragmentation_dst_ring, .get_reo_dest_remap_config = ath11k_get_reo_dest_remap_config_default, .rx_desc_get_hal_mpdu_len = ath11k_hw_ipq8074_rx_desc_get_hal_mpdu_len, + .rx_desc_get_hal_ppdu_id = ath11k_hw_ipq8074_rx_desc_get_hal_mpdu_ppdu_id, }; - /* IPQ5018 hw ops is similar to QCN9074 except for the dest ring remap */ -@@ -1547,6 +1572,7 @@ const struct ath11k_hw_ops ipq5018_ops = + const struct ath11k_hw_ops wcn6750_ops = { +@@ -1620,6 +1645,7 @@ const struct ath11k_hw_ops ipq5018_ops = .get_reo_dest_remap_config = ath11k_get_reo_dest_remap_config_5018, .mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid, .rx_desc_get_hal_mpdu_len = ath11k_hw_qcn9074_rx_desc_get_hal_mpdu_len, -+ .rx_desc_get_hal_ppdu_id = ath11k_hw_qcn9074_rx_desc_get_hal_mpdu_ppdu_id, - }; - - const struct ath11k_hw_ops qcn6122_ops = { -@@ -1602,6 +1628,7 @@ const struct ath11k_hw_ops qcn6122_ops = - .rx_desc_dot11_hdr_fields_valid = ath11k_hw_qcn9074_rx_desc_dot11_hdr_fields_valid, - .rx_desc_get_dot11_hdr = ath11k_hw_qcn9074_rx_desc_get_dot11_hdr, - .rx_desc_get_crypto_header = ath11k_hw_qcn9074_rx_desc_get_crypto_hdr, + .rx_desc_get_hal_ppdu_id = ath11k_hw_qcn9074_rx_desc_get_hal_mpdu_ppdu_id, }; diff --git a/feeds/ipq95xx/mac80211/patches/qca/312-mac80211-fix-invalid-nss-config.patch b/feeds/ipq95xx/mac80211/patches/qca/312-mac80211-fix-invalid-nss-config.patch index f5082f3dd..c53311b09 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/312-mac80211-fix-invalid-nss-config.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/312-mac80211-fix-invalid-nss-config.patch @@ -23,7 +23,7 @@ Signed-off-by: Thiraviyam Mariyappan + if (he_cap->he_mcs_nss_supp.rx_mcs_80 == cpu_to_le16(0xFFFF)) { + he_cap->has_he = false; + sdata_info(sdata, "Ignoring HE IE from %pM due to invalid rx_mcs_80\n", -+ sta->addr); ++ link_sta->pub->addr); + return; + } + diff --git a/feeds/ipq95xx/mac80211/patches/qca/314-001-ath11k-add-peer-rhash-table-support.patch b/feeds/ipq95xx/mac80211/patches/qca/314-001-ath11k-add-peer-rhash-table-support.patch deleted file mode 100644 index baef37bc3..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/314-001-ath11k-add-peer-rhash-table-support.patch +++ /dev/null @@ -1,518 +0,0 @@ -From 985edaabe31628237a6771d091d3cda0d8e16065 Mon Sep 17 00:00:00 2001 -From: Karthikeyan Periyasamy -Date: Thu, 3 Jun 2021 15:07:12 +0530 -Subject: [PATCH] ath11k: add peer rhash table support - -peer lookup operation consume more CPU cycle when more clients -are connected. It leads to degrade in KPI measurement in UL data -traffic with 128 clients. In 64bit system not able to meet the -expected measurement for the TCP UL test case. To fix this -issue by reducing the peer lookup operation by introducing -rhash based lookup instead of linear based lookup. - -TCP UL 128 Clients test case Observation: -Before fix - ~480 Mbps -After fix - ~860 Mbps - -Signed-off-by: Karthikeyan Periyasamy ---- - drivers/net/wireless/ath/ath11k/core.h | 9 ++ - drivers/net/wireless/ath/ath11k/mac.c | 15 +++ - drivers/net/wireless/ath/ath11k/peer.c | 164 +++++++++++++++++++++++++++++++++ - drivers/net/wireless/ath/ath11k/peer.h | 8 ++ - 4 files changed, 196 insertions(+) - ---- a/drivers/net/wireless/ath/ath11k/core.h -+++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -990,6 +990,18 @@ struct ath11k_base { - struct ath11k_pdev __rcu *pdevs_active[MAX_RADIOS]; - struct ath11k_hal_reg_capabilities_ext hal_reg_cap[MAX_RADIOS]; - unsigned long long free_vdev_map; -+ -+ /* -+ * The rhashtable containing struct ath11k_peer keyed by mac addr -+ * protected under ab->base_lock spin lock -+ */ -+ struct rhashtable *rhead_peer_addr; -+ struct rhashtable_params rhash_peer_addr_param; -+ -+ /* The rhashtable containing struct ath11k_peer keyed by id */ -+ struct rhashtable *rhead_peer_id; -+ struct rhashtable_params rhash_peer_id_param; -+ - struct list_head peers; - wait_queue_head_t peer_mapping_wq; - u8 mac_addr[ETH_ALEN]; ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -1031,6 +1031,7 @@ void ath11k_mac_peer_cleanup_all(struct - spin_lock_bh(&ab->base_lock); - list_for_each_entry_safe(peer, tmp, &ab->peers, list) { - ath11k_peer_rx_tid_cleanup(ar, peer); -+ ath11k_peer_rhash_delete(ab, peer); - list_del(&peer->list); - kfree(peer); - } -@@ -5430,6 +5431,7 @@ static int ath11k_mac_op_sta_state(struc - } else if (peer && peer->sta == sta) { - ath11k_warn(ar->ab, "Found peer entry %pM n vdev %i after it was supposedly removed\n", - vif->addr, arvif->vdev_id); -+ ath11k_peer_rhash_delete(ar->ab, peer); - peer->sta = NULL; - list_del(&peer->list); - kfree(peer); -@@ -9825,6 +9827,8 @@ void ath11k_mac_unregister(struct ath11k - - __ath11k_mac_unregister(ar); - } -+ -+ ath11k_peer_rhash_tbl_destroy(ab); - } - - static int __ath11k_mac_register(struct ath11k *ar) -@@ -10060,6 +10064,10 @@ int ath11k_mac_register(struct ath11k_ba - ab->cc_freq_hz = IPQ8074_CC_FREQ_HERTZ; - ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS(ab))) - 1; - -+ ret = ath11k_peer_rhash_tbl_init(ab); -+ if (ret) -+ return ret; -+ - for (i = 0; i < ab->num_radios; i++) { - pdev = &ab->pdevs[i]; - ar = pdev->ar; -@@ -10089,6 +10097,8 @@ err_cleanup: - __ath11k_mac_unregister(ar); - } - -+ ath11k_peer_rhash_tbl_destroy(ab); -+ - return ret; - } - ---- a/drivers/net/wireless/ath/ath11k/peer.c -+++ b/drivers/net/wireless/ath/ath11k/peer.c -@@ -27,25 +27,6 @@ struct ath11k_peer *ath11k_peer_find(str - return NULL; - } - --static struct ath11k_peer *ath11k_peer_find_by_pdev_idx(struct ath11k_base *ab, -- u8 pdev_idx, const u8 *addr) --{ -- struct ath11k_peer *peer; -- -- lockdep_assert_held(&ab->base_lock); -- -- list_for_each_entry(peer, &ab->peers, list) { -- if (peer->pdev_idx != pdev_idx) -- continue; -- if (!ether_addr_equal(peer->addr, addr)) -- continue; -- -- return peer; -- } -- -- return NULL; --} -- - struct ath11k_peer *ath11k_peer_find_by_addr(struct ath11k_base *ab, - const u8 *addr) - { -@@ -53,14 +34,13 @@ struct ath11k_peer *ath11k_peer_find_by_ - - lockdep_assert_held(&ab->base_lock); - -- list_for_each_entry(peer, &ab->peers, list) { -- if (!ether_addr_equal(peer->addr, addr)) -- continue; -+ if (!ab->rhead_peer_addr) -+ return NULL; - -- return peer; -- } -+ peer = rhashtable_lookup_fast(ab->rhead_peer_addr, addr, -+ ab->rhash_peer_addr_param); - -- return NULL; -+ return peer; - } - - struct ath11k_peer *ath11k_peer_find_by_id(struct ath11k_base *ab, -@@ -70,11 +50,13 @@ struct ath11k_peer *ath11k_peer_find_by_ - - lockdep_assert_held(&ab->base_lock); - -- list_for_each_entry(peer, &ab->peers, list) -- if (peer_id == peer->peer_id) -- return peer; -+ if (!ab->rhead_peer_id) -+ return NULL; - -- return NULL; -+ peer = rhashtable_lookup_fast(ab->rhead_peer_id, &peer_id, -+ ab->rhash_peer_id_param); -+ -+ return peer; - } - - struct ath11k_peer *ath11k_peer_find_by_vdev_id(struct ath11k_base *ab, -@@ -423,6 +405,7 @@ void ath11k_peer_unmap_event(struct ath1 - ath11k_dbg(ab, ATH11K_DBG_PEER, "peer unmap vdev %d peer %pM id %d\n", - peer->vdev_id, peer->addr, peer_id); - -+ ath11k_peer_rhash_delete(ab, peer); - list_del(&peer->list); - kfree(peer); - wake_up(&ab->peer_mapping_wq); -@@ -476,6 +459,7 @@ void ath11k_peer_unmap_v2_event(struct a - #endif - free_peer: - rcu_read_unlock(); -+ ath11k_peer_rhash_delete(ab, peer); - list_del(&peer->list); - kfree(peer); - wake_up(&ab->peer_mapping_wq); -@@ -604,6 +588,69 @@ static int ath11k_wait_for_peer_common(s - return 0; - } - -+static inline int ath11k_peer_rhash_insert(struct ath11k_base *ab, -+ struct rhashtable *rtbl, -+ struct rhash_head *rhead, -+ struct rhashtable_params *params, -+ void *key) -+{ -+ struct ath11k_peer *tmp; -+ -+ lockdep_assert_held(&ab->base_lock); -+ -+ tmp = rhashtable_lookup_get_insert_fast(rtbl, rhead, *params); -+ -+ if (!tmp) -+ return 0; -+ else if (IS_ERR(tmp)) -+ return PTR_ERR(tmp); -+ else -+ return -EEXIST; -+} -+ -+static inline int ath11k_peer_rhash_remove(struct ath11k_base *ab, -+ struct rhashtable *rtbl, -+ struct rhash_head *rhead, -+ struct rhashtable_params *params) -+{ -+ lockdep_assert_held(&ab->base_lock); -+ -+ return rhashtable_remove_fast(rtbl, rhead, *params); -+} -+ -+static int ath11k_peer_rhash_add(struct ath11k_base *ab, struct ath11k_peer *peer) -+{ -+ int ret; -+ -+ lockdep_assert_held(&ab->base_lock); -+ -+ if (!ab->rhead_peer_id || !ab->rhead_peer_addr) -+ return -EPERM; -+ -+ ret = ath11k_peer_rhash_insert(ab, ab->rhead_peer_id, &peer->rhash_id, -+ &ab->rhash_peer_id_param, &peer->peer_id); -+ if (ret) { -+ ath11k_warn(ab, "failed to add peer %pM with id %d in rhash_id ret %d\n", -+ peer->addr, peer->peer_id, ret); -+ return ret; -+ } -+ -+ ret = ath11k_peer_rhash_insert(ab, ab->rhead_peer_addr, &peer->rhash_addr, -+ &ab->rhash_peer_addr_param, &peer->addr); -+ if (ret) { -+ ath11k_warn(ab, "failed to add peer %pM with id %d in rhash_addr ret %d\n", -+ peer->addr, peer->peer_id, ret); -+ goto err_clean; -+ } -+ -+ return 0; -+ -+err_clean: -+ ath11k_peer_rhash_remove(ab, ab->rhead_peer_id, &peer->rhash_id, -+ &ab->rhash_peer_id_param); -+ return ret; -+} -+ - void ath11k_peer_cleanup(struct ath11k *ar, u32 vdev_id) - { - struct ath11k_peer *peer, *tmp_peer; -@@ -633,6 +680,7 @@ void ath11k_peer_cleanup(struct ath11k * - ath11k_peer_del_ast(ar, ast_entry); - #endif - -+ ath11k_peer_rhash_delete(ab, peer); - list_del(&peer->list); - kfree(peer); - ar->num_peers--; -@@ -720,7 +768,7 @@ int ath11k_peer_create(struct ath11k *ar - } - - spin_lock_bh(&ar->ab->base_lock); -- peer = ath11k_peer_find_by_pdev_idx(ar->ab, ar->pdev_idx, param->peer_addr); -+ peer = ath11k_peer_find_by_addr(ar->ab, param->peer_addr); - if (peer) { - spin_unlock_bh(&ar->ab->base_lock); - return -EINVAL; -@@ -752,6 +800,12 @@ int ath11k_peer_create(struct ath11k *ar - goto cleanup; - } - -+ ret = ath11k_peer_rhash_add(ar->ab, peer); -+ if (ret) { -+ spin_unlock_bh(&ar->ab->base_lock); -+ goto cleanup; -+ } -+ - peer->pdev_idx = ar->pdev_idx; - peer->sta = sta; - -@@ -814,3 +868,190 @@ cleanup: - exit: - return ret; - } -+ -+int ath11k_peer_rhash_delete(struct ath11k_base *ab, struct ath11k_peer *peer) -+{ -+ int ret; -+ -+ lockdep_assert_held(&ab->base_lock); -+ -+ if (!ab->rhead_peer_id || !ab->rhead_peer_addr) -+ return -EPERM; -+ -+ ret = ath11k_peer_rhash_remove(ab, ab->rhead_peer_id, &peer->rhash_id, -+ &ab->rhash_peer_id_param); -+ if (ret) { -+ ath11k_warn(ab, "failed to remove peer %pM id %d in rhash_id ret %d\n", -+ peer->addr, peer->peer_id, ret); -+ return ret; -+ } -+ -+ ret = ath11k_peer_rhash_remove(ab, ab->rhead_peer_addr, &peer->rhash_addr, -+ &ab->rhash_peer_addr_param); -+ if (ret) { -+ ath11k_warn(ab, "failed to remove peer %pM id %d in rhash_addr ret %d\n", -+ peer->addr, peer->peer_id, ret); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int ath11k_peer_rhash_id_tbl_init(struct ath11k_base *ab) -+{ -+ struct rhashtable_params *param; -+ struct rhashtable *rhash_id_tbl; -+ int ret; -+ size_t size; -+ -+ if (ab->rhead_peer_id) -+ return 0; -+ -+ size = sizeof(*ab->rhead_peer_id); -+ rhash_id_tbl = kzalloc(size, GFP_KERNEL); -+ if (!rhash_id_tbl) { -+ ath11k_warn(ab, "failed to init rhash id table due to no mem (size %zu)\n", -+ size); -+ return -ENOMEM; -+ } -+ -+ param = &ab->rhash_peer_id_param; -+ -+ param->key_offset = offsetof(struct ath11k_peer, peer_id); -+ param->head_offset = offsetof(struct ath11k_peer, rhash_id); -+ param->key_len = sizeof_field(struct ath11k_peer, peer_id); -+ param->automatic_shrinking = true; -+ param->nelem_hint = ab->num_radios * TARGET_NUM_PEERS_PDEV(ab); -+ -+ ret = rhashtable_init(rhash_id_tbl, param); -+ if (ret) { -+ ath11k_warn(ab, "failed to init peer id rhash table %d\n", ret); -+ goto err_free; -+ } -+ -+ spin_lock_bh(&ab->base_lock); -+ -+ if (!ab->rhead_peer_id) { -+ ab->rhead_peer_id = rhash_id_tbl; -+ } else { -+ spin_unlock_bh(&ab->base_lock); -+ ath11k_warn(ab, "already peer rhash id init done id_tbl: %p\n", -+ ab->rhead_peer_id); -+ goto cleanup_tbl; -+ } -+ -+ spin_unlock_bh(&ab->base_lock); -+ -+ return 0; -+ -+cleanup_tbl: -+ rhashtable_destroy(rhash_id_tbl); -+err_free: -+ kfree(rhash_id_tbl); -+ -+ return ret; -+} -+ -+static int ath11k_peer_rhash_addr_tbl_init(struct ath11k_base *ab) -+{ -+ struct rhashtable_params *param; -+ struct rhashtable *rhash_addr_tbl; -+ int ret; -+ size_t size; -+ -+ if (ab->rhead_peer_addr) -+ return 0; -+ -+ size = sizeof(*ab->rhead_peer_addr); -+ rhash_addr_tbl = kzalloc(size, GFP_KERNEL); -+ if (!rhash_addr_tbl) { -+ ath11k_warn(ab, "failed to init rhash addr table due to no mem (size %zu)\n", -+ size); -+ return -ENOMEM; -+ } -+ -+ param = &ab->rhash_peer_addr_param; -+ -+ param->key_offset = offsetof(struct ath11k_peer, addr); -+ param->head_offset = offsetof(struct ath11k_peer, rhash_addr); -+ param->key_len = sizeof_field(struct ath11k_peer, addr); -+ param->automatic_shrinking = true; -+ param->nelem_hint = TARGET_NUM_PEERS_PDEV(ab); -+ -+ ret = rhashtable_init(rhash_addr_tbl, param); -+ if (ret) { -+ ath11k_warn(ab, "failed to init peer addr rhash table %d\n", ret); -+ goto err_free; -+ } -+ -+ spin_lock_bh(&ab->base_lock); -+ -+ if (!ab->rhead_peer_addr) { -+ ab->rhead_peer_addr = rhash_addr_tbl; -+ } else { -+ spin_unlock_bh(&ab->base_lock); -+ ath11k_warn(ab, "already peer rhash addr init done\n"); -+ goto cleanup_tbl; -+ } -+ -+ spin_unlock_bh(&ab->base_lock); -+ -+ return 0; -+ -+cleanup_tbl: -+ rhashtable_destroy(rhash_addr_tbl); -+err_free: -+ kfree(rhash_addr_tbl); -+ -+ return ret; -+} -+ -+static inline void ath11k_peer_rhash_id_tbl_destroy(struct ath11k_base *ab) -+{ -+ if (!ab->rhead_peer_id) -+ return; -+ -+ rhashtable_destroy(ab->rhead_peer_id); -+ kfree(ab->rhead_peer_id); -+ ab->rhead_peer_id = NULL; -+} -+ -+static inline void ath11k_peer_rhash_addr_tbl_destroy(struct ath11k_base *ab) -+{ -+ if (!ab->rhead_peer_addr) -+ return; -+ -+ rhashtable_destroy(ab->rhead_peer_addr); -+ kfree(ab->rhead_peer_addr); -+ ab->rhead_peer_addr = NULL; -+} -+ -+int ath11k_peer_rhash_tbl_init(struct ath11k_base *ab) -+{ -+ int ret; -+ -+ ret = ath11k_peer_rhash_id_tbl_init(ab); -+ if (ret) -+ return ret; -+ -+ ret = ath11k_peer_rhash_addr_tbl_init(ab); -+ if (ret) -+ goto cleanup_tbl; -+ -+ return 0; -+ -+cleanup_tbl: -+ ath11k_peer_rhash_id_tbl_destroy(ab); -+ -+ return ret; -+} -+ -+void ath11k_peer_rhash_tbl_destroy(struct ath11k_base *ab) -+{ -+ spin_lock_bh(&ab->base_lock); -+ -+ ath11k_peer_rhash_id_tbl_destroy(ab); -+ ath11k_peer_rhash_addr_tbl_destroy(ab); -+ -+ spin_unlock_bh(&ab->base_lock); -+} ---- a/drivers/net/wireless/ath/ath11k/peer.h -+++ b/drivers/net/wireless/ath/ath11k/peer.h -@@ -78,6 +78,10 @@ struct ath11k_peer { - /* protected by ab->data_lock */ - struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1]; - struct dp_rx_tid rx_tid[IEEE80211_NUM_TIDS + 1]; -+ /* peer id based rhashtable list pointer */ -+ struct rhash_head rhash_id; -+ /* peer addr based rhashtable list pointer */ -+ struct rhash_head rhash_addr; - - /* Info used in MMIC verification of - * RX fragments -@@ -116,6 +120,9 @@ int ath11k_wait_for_peer_delete_done(str - const u8 *addr); - struct ath11k_peer *ath11k_peer_find_by_vdev_id(struct ath11k_base *ab, - int vdev_id); -+int ath11k_peer_rhash_tbl_init(struct ath11k_base *ab); -+void ath11k_peer_rhash_tbl_destroy(struct ath11k_base *ab); -+int ath11k_peer_rhash_delete(struct ath11k_base *ab, struct ath11k_peer *peer); - - #ifdef CPTCFG_ATH11K_NSS_SUPPORT - struct ath11k_ast_entry *ath11k_peer_ast_find_by_addr(struct ath11k_base *ab, ---- a/drivers/net/wireless/ath/ath11k/wmi.c -+++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -8335,7 +8335,6 @@ static void ath11k_peer_sta_kickout_even - spin_lock_bh(&ab->base_lock); - - peer = ath11k_peer_find_by_addr(ab, arg.mac_addr); -- - if (!peer) { - ath11k_warn(ab, "peer not found %pM\n", - arg.mac_addr); -@@ -9947,7 +9946,6 @@ ath11k_wmi_event_peer_sta_ps_state_chg(s - spin_lock_bh(&ab->base_lock); - - peer = ath11k_peer_find_by_addr(ab, peer_addr); -- - if (!peer) { - ath11k_warn(ab, "peer not found %pM\n", - peer_addr); -@@ -9958,11 +9956,9 @@ ath11k_wmi_event_peer_sta_ps_state_chg(s - } - - ar = ath11k_mac_get_ar_by_vdev_id(ab, peer->vdev_id); -- - if (!ar) { - ath11k_warn(ab, "invalid vdev id in peer sta ps state change ev %d", - peer->vdev_id); -- - spin_unlock_bh(&ab->base_lock); - goto exit; - } diff --git a/feeds/ipq95xx/mac80211/patches/qca/318-ath11k-add-support-for-tx-completion-stats.patch b/feeds/ipq95xx/mac80211/patches/qca/318-ath11k-add-support-for-tx-completion-stats.patch index b8a72f957..18f1ef580 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/318-ath11k-add-support-for-tx-completion-stats.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/318-ath11k-add-support-for-tx-completion-stats.patch @@ -48,11 +48,13 @@ Signed-off-by: Hari Chandrakanthan --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -310,10 +310,12 @@ struct ath11k_vif { +@@ -427,12 +427,14 @@ struct ath11k_vif { struct dentry *amsdu_aggr_size; struct dentry *wmi_ctrl_stat; struct dentry *mac_filter; + struct dentry *wbm_tx_completion_stats; + #endif /* CPTCFG_ATH11K_DEBUGFS */ + struct ath11k_mgmt_frame_stats mgmt_stats; /* protected by conf_mutex */ struct list_head mac_filters; @@ -60,8 +62,8 @@ Signed-off-by: Hari Chandrakanthan + u64 wbm_tx_comp_stats[HAL_WBM_REL_HTT_TX_COMP_STATUS_MAX]; struct arvif_nss nss; struct list_head ap_vlan_arvifs; - /* VLAN keyidx map required for Dynamic VLAN */ -@@ -421,6 +423,10 @@ struct ath11k_htt_data_stats { + /* list required by Dynamic VLAN during fw_recovery */ +@@ -542,6 +544,10 @@ struct ath11k_htt_data_stats { u64 ru_loc[ATH11K_COUNTER_TYPE_MAX][HAL_RX_RU_ALLOC_TYPE_MAX]; }; @@ -72,7 +74,7 @@ Signed-off-by: Hari Chandrakanthan struct ath11k_htt_tx_stats { struct ath11k_htt_data_stats stats[ATH11K_STATS_TYPE_MAX]; u64 tx_duration; -@@ -495,6 +501,7 @@ struct ath11k_sta { +@@ -623,6 +629,7 @@ struct ath11k_sta { u32 ps_start_jiffies; u8 peer_current_ps_valid; u32 ps_total_duration; @@ -82,7 +84,7 @@ Signed-off-by: Hari Chandrakanthan #endif --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -575,6 +575,81 @@ void ath11k_debugfs_wmi_ctrl_stats(struc +@@ -419,6 +419,81 @@ void ath11k_debugfs_wmi_ctrl_stats(struc init_completion(&arvif->ar->debug.wmi_ctrl_path_stats_rcvd); } @@ -166,9 +168,9 @@ Signed-off-by: Hari Chandrakanthan size_t count, loff_t *ppos) --- a/drivers/net/wireless/ath/ath11k/debugfs.h +++ b/drivers/net/wireless/ath/ath11k/debugfs.h -@@ -194,6 +194,7 @@ static void ath11k_debugfs_dbg_mac_filte - } - #endif +@@ -307,6 +307,7 @@ struct ath11k_fw_dbglog { + }; + }; +void ath11k_debugfs_wbm_tx_comp_stats(struct ath11k_vif *arvif); void ath11k_debug_aggr_size_config_init(struct ath11k_vif *arvif); @@ -176,7 +178,7 @@ Signed-off-by: Hari Chandrakanthan void ath11k_wmi_crl_path_stats_list_free(struct list_head *head); --- a/drivers/net/wireless/ath/ath11k/debugfs_sta.c +++ b/drivers/net/wireless/ath/ath11k/debugfs_sta.c -@@ -316,8 +316,15 @@ static ssize_t ath11k_dbg_sta_dump_tx_st +@@ -221,6 +221,13 @@ static ssize_t ath11k_dbg_sta_dump_tx_st const int size = 2 * 4096; char *buf, mu_group_id[MAX_MU_GROUP_LENGTH] = {0}; u32 index; @@ -188,12 +190,18 @@ Signed-off-by: Hari Chandrakanthan + [HAL_WBM_REL_HTT_TX_COMP_STATUS_MEC_NOTIFY] = "MEC notify pkt count"}; + int idx; -- if (!arsta->tx_stats) -+ if (!arsta->tx_stats || !arsta->wbm_tx_stats) - return -ENOENT; - buf = kzalloc(size, GFP_KERNEL); -@@ -449,7 +456,15 @@ static ssize_t ath11k_dbg_sta_dump_tx_st + if (!buf) +@@ -230,7 +237,7 @@ static ssize_t ath11k_dbg_sta_dump_tx_st + + spin_lock_bh(&ar->data_lock); + +- if (!arsta->tx_stats) { ++ if (!arsta->tx_stats || !arsta->wbm_tx_stats) { + retval = -ENOENT; + goto end; + } +@@ -357,7 +364,15 @@ static ssize_t ath11k_dbg_sta_dump_tx_st len += scnprintf(buf + len, size - len, "BA fails\n %llu\n", arsta->tx_stats->ba_fails); len += scnprintf(buf + len, size - len, @@ -210,16 +218,16 @@ Signed-off-by: Hari Chandrakanthan spin_unlock_bh(&ar->data_lock); -@@ -1253,7 +1268,7 @@ static ssize_t ath11k_dbg_sta_reset_tx_s - struct ath11k *ar = arsta->arvif->ar; - int ret, reset; +@@ -1184,7 +1199,7 @@ static ssize_t ath11k_dbg_sta_reset_tx_s -- if (!arsta->tx_stats) -+ if (!arsta->tx_stats || !arsta->wbm_tx_stats) + spin_lock_bh(&ar->ab->base_lock); + +- if (!arsta->tx_stats) { ++ if (!arsta->tx_stats || !arsta->wbm_tx_stats) { + spin_unlock_bh(&ar->ab->base_lock); return -ENOENT; - - ret = kstrtoint_from_user(buf, count, 0, &reset); -@@ -1267,6 +1282,7 @@ static ssize_t ath11k_dbg_sta_reset_tx_s + } +@@ -1192,6 +1207,7 @@ static ssize_t ath11k_dbg_sta_reset_tx_s memset(arsta->tx_stats, 0, sizeof(*arsta->tx_stats)); atomic_set(&arsta->drv_tx_pkts.pkts_in, 0); atomic_set(&arsta->drv_tx_pkts.pkts_out, 0); @@ -227,7 +235,7 @@ Signed-off-by: Hari Chandrakanthan spin_unlock_bh(&ar->ab->base_lock); ret = count; -@@ -1527,4 +1543,5 @@ void ath11k_debugfs_sta_op_add(struct ie +@@ -1455,4 +1471,5 @@ void ath11k_debugfs_sta_op_add(struct ie debugfs_create_file("cfr_capture", 0400, dir, sta, &fops_peer_cfr_capture); #endif/* CPTCFG_ATH11K_CFR */ @@ -235,7 +243,7 @@ Signed-off-by: Hari Chandrakanthan } --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -1662,8 +1662,7 @@ ath11k_update_per_peer_tx_stats(struct a +@@ -1665,8 +1665,7 @@ ath11k_update_per_peer_tx_stats(struct a peer_stats->mu_grpid = mu_grpid; peer_stats->mu_pos = mu_pos; peer_stats->ru_tones = arsta->txrate.he_ru_alloc; @@ -247,7 +255,7 @@ Signed-off-by: Hari Chandrakanthan --- a/drivers/net/wireless/ath/ath11k/dp_tx.c +++ b/drivers/net/wireless/ath/ath11k/dp_tx.c -@@ -530,7 +530,8 @@ static void ath11k_dp_tx_cache_peer_stat +@@ -634,7 +634,8 @@ err_out: static void ath11k_dp_tx_complete_msdu(struct ath11k *ar, struct sk_buff *msdu, @@ -256,18 +264,18 @@ Signed-off-by: Hari Chandrakanthan + enum hal_wbm_htt_tx_comp_status wbm_status) { struct ieee80211_tx_status status = { 0 }; - struct ath11k_base *ab = ar->ab; -@@ -538,7 +539,8 @@ static void ath11k_dp_tx_complete_msdu(s - struct ath11k_skb_cb *skb_cb; + struct ieee80211_rate_status status_rate = { 0 }; +@@ -644,7 +645,8 @@ static void ath11k_dp_tx_complete_msdu(s struct ath11k_peer *peer; struct ath11k_sta *arsta; + struct rate_info rate; - struct ieee80211_vif *vif; + struct ieee80211_vif *vif = NULL; + struct ath11k_vif *arvif = NULL; - struct rate_info rate; u8 flags = 0; -@@ -578,6 +580,9 @@ static void ath11k_dp_tx_complete_msdu(s + if (WARN_ON_ONCE(ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM)) { +@@ -683,6 +685,9 @@ static void ath11k_dp_tx_complete_msdu(s } vif = skb_cb->vif; @@ -277,9 +285,9 @@ Signed-off-by: Hari Chandrakanthan info = IEEE80211_SKB_CB(msdu); memset(&info->status, 0, sizeof(info->status)); -@@ -642,11 +647,18 @@ static void ath11k_dp_tx_complete_msdu(s - rate = arsta->last_txrate; - status.rate = &rate; +@@ -748,6 +753,11 @@ static void ath11k_dp_tx_complete_msdu(s + status.rates = &status_rate; + status.n_rates = 1; + if (unlikely(ath11k_debugfs_is_extd_tx_stats_enabled(ar))) { + if(arsta->wbm_tx_stats && wbm_status < HAL_WBM_REL_HTT_TX_COMP_STATUS_MAX) @@ -287,24 +295,17 @@ Signed-off-by: Hari Chandrakanthan + } + spin_unlock_bh(&ab->base_lock); -+ - if (flags & ATH11K_SKB_HW_80211_ENCAP) - ieee80211_tx_status_8023(ar->hw, vif, msdu); - else - ieee80211_tx_status_ext(ar->hw, &status); -+ - return; - } -@@ -706,6 +718,7 @@ void ath11k_dp_tx_completion_handler(str + if (flags & ATH11K_SKB_HW_80211_ENCAP) +@@ -813,6 +823,7 @@ void ath11k_dp_tx_completion_handler(str struct hal_tx_status ts = { 0 }; struct dp_tx_ring *tx_ring = &dp->tx_ring[ring_id]; - int valid_entries; + int valid_entries; + enum hal_wbm_htt_tx_comp_status wbm_status; u32 *desc; u32 msdu_id, desc_id; u8 mac_id; -@@ -743,6 +756,9 @@ void ath11k_dp_tx_completion_handler(str +@@ -859,6 +870,9 @@ void ath11k_dp_tx_completion_handler(str mac_id = FIELD_GET(DP_TX_DESC_ID_MAC_ID, desc_id); msdu_id = FIELD_GET(DP_TX_DESC_ID_MSDU_ID, desc_id); @@ -314,7 +315,7 @@ Signed-off-by: Hari Chandrakanthan if (unlikely(ts.buf_rel_source == HAL_WBM_REL_SRC_MODULE_FW)) { ath11k_dp_tx_process_htt_tx_complete(ab, (void *)tx_status, -@@ -767,7 +783,7 @@ void ath11k_dp_tx_completion_handler(str +@@ -883,7 +897,7 @@ void ath11k_dp_tx_completion_handler(str if (atomic_dec_and_test(&ar->dp.num_tx_pending)) wake_up(&ar->dp.tx_empty_waitq); @@ -335,7 +336,7 @@ Signed-off-by: Hari Chandrakanthan struct hal_tcl_data_cmd { --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -5063,6 +5063,11 @@ static int ath11k_mac_station_add(struct +@@ -5306,6 +5306,11 @@ static int ath11k_mac_station_add(struct ret = -ENOMEM; goto free_peer; } @@ -347,7 +348,7 @@ Signed-off-by: Hari Chandrakanthan } if (ieee80211_vif_is_mesh(vif)) { -@@ -5101,6 +5106,8 @@ static int ath11k_mac_station_add(struct +@@ -5345,6 +5350,8 @@ static int ath11k_mac_station_add(struct free_tx_stats: kfree(arsta->tx_stats); arsta->tx_stats = NULL; @@ -356,8 +357,8 @@ Signed-off-by: Hari Chandrakanthan free_peer: ath11k_peer_delete(ar, arvif->vdev_id, sta->addr); free_rx_stats: -@@ -5205,6 +5212,8 @@ static int ath11k_mac_op_sta_state(struc - free: +@@ -5456,6 +5463,8 @@ static int ath11k_mac_op_sta_state(struc + kfree(arsta->tx_stats); arsta->tx_stats = NULL; + kfree(arsta->wbm_tx_stats); @@ -365,7 +366,7 @@ Signed-off-by: Hari Chandrakanthan ret = ath11k_mac_ap_ps_recalc(ar); if (ret) ath11k_warn(ar->ab, "failed to send ap ps ret %d\n", ret); -@@ -6864,6 +6873,7 @@ static int ath11k_mac_op_add_interface(s +@@ -7316,6 +7325,7 @@ static int ath11k_mac_op_add_interface(s } ath11k_debugfs_dbg_mac_filter(arvif); @@ -373,7 +374,7 @@ Signed-off-by: Hari Chandrakanthan switch (vif->type) { case NL80211_IFTYPE_UNSPECIFIED: -@@ -7214,6 +7224,10 @@ err_vdev_del: +@@ -7659,6 +7669,10 @@ err_vdev_del: debugfs_remove(arvif->mac_filter); arvif->mac_filter = NULL; diff --git a/feeds/ipq95xx/mac80211/patches/qca/320-ath11k-fix-sleep-function-called-from-invalid-contex.patch b/feeds/ipq95xx/mac80211/patches/qca/320-ath11k-fix-sleep-function-called-from-invalid-contex.patch deleted file mode 100644 index 221638315..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/320-ath11k-fix-sleep-function-called-from-invalid-contex.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 88327536d2c643dbabed84ad4e0e7e03c33035b3 Mon Sep 17 00:00:00 2001 -From: P Praneesh -Date: Fri, 9 Jul 2021 12:18:59 +0530 -Subject: [PATCH] ath11k: WAR for sleep function called from invalid context - -mhi_device_get_sync internally calls sleep from the interrupt context. -Since QCN9074 disable power save mode for all the platforms, no need -to call wake up MHI. As a WAR, removing these QCA6390 checks and needs to -be fix it with someother approach to avoid sleep in interrupt context. - -Signed-off-by: P Praneesh ---- - drivers/net/wireless/ath/ath11k/pci.c | 24 ++++++++++++------------ - 1 file changed, 12 insertions(+), 12 deletions(-) - ---- a/drivers/net/wireless/ath/ath11k/pci.c -+++ b/drivers/net/wireless/ath/ath11k/pci.c -@@ -88,14 +88,6 @@ void ath11k_pci_write32(struct ath11k_ba - struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); - u32 window_start; - -- /* for offset beyond BAR + 4K - 32, may -- * need to wakeup MHI to access. -- */ -- if (ab->hw_params.wakeup_mhi && -- test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && -- offset >= ACCESS_ALWAYS_OFF) -- mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev); -- - if (offset < WINDOW_START) { - iowrite32(value, ab->mem + offset); - } else { -@@ -115,11 +107,6 @@ void ath11k_pci_write32(struct ath11k_ba - (offset & WINDOW_RANGE_MASK)); - } - } -- -- if (ab->hw_params.wakeup_mhi && -- test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && -- offset >= ACCESS_ALWAYS_OFF) -- mhi_device_put(ab_pci->mhi_ctrl->mhi_dev); - } - - u32 ath11k_pci_read32(struct ath11k_base *ab, u32 offset) -@@ -127,14 +114,6 @@ u32 ath11k_pci_read32(struct ath11k_base - struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); - u32 val, window_start; - -- /* for offset beyond BAR + 4K - 32, may -- * need to wakeup MHI to access. -- */ -- if (ab->hw_params.wakeup_mhi && -- test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && -- offset >= ACCESS_ALWAYS_OFF) -- mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev); -- - if (offset < WINDOW_START) { - val = ioread32(ab->mem + offset); - } else { -@@ -155,11 +134,6 @@ u32 ath11k_pci_read32(struct ath11k_base - } - } - -- if (ab->hw_params.wakeup_mhi && -- test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && -- offset >= ACCESS_ALWAYS_OFF) -- mhi_device_put(ab_pci->mhi_ctrl->mhi_dev); -- - return val; - } - diff --git a/feeds/ipq95xx/mac80211/patches/qca/321-001-qgic-api-compile-fix.patch b/feeds/ipq95xx/mac80211/patches/qca/321-001-qgic-api-compile-fix.patch index d3d8f7a80..76fe6aa4a 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/321-001-qgic-api-compile-fix.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/321-001-qgic-api-compile-fix.patch @@ -18,7 +18,7 @@ Signed-off-by: Tamizh Chelvam --- a/drivers/net/wireless/ath/ath11k/ahb.c +++ b/drivers/net/wireless/ath/ath11k/ahb.c -@@ -702,17 +702,39 @@ static int ath11k_core_get_rproc(struct +@@ -777,17 +777,39 @@ static int ath11k_core_get_rproc(struct struct device *dev = ab->dev; struct rproc *prproc; phandle rproc_phandle; @@ -68,7 +68,7 @@ Signed-off-by: Tamizh Chelvam return 0; --- a/drivers/net/wireless/ath/ath11k/ce.c +++ b/drivers/net/wireless/ath/ath11k/ce.c -@@ -1112,10 +1112,17 @@ void ce_update_tasklet_time_duration_sta +@@ -1110,10 +1110,17 @@ void ce_update_tasklet_time_duration_sta { s64 sched_us, exec_us; @@ -102,8 +102,8 @@ Signed-off-by: Tamizh Chelvam fw_img = mhi_ctrl->fbc_image; --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c -@@ -574,7 +574,11 @@ static int ath11k_pci_alloc_msi(struct a - num_vectors = pci_alloc_irq_vectors(ab_pci->pdev, +@@ -443,7 +443,11 @@ static int ath11k_pci_alloc_msi(struct a + num_vectors = pci_alloc_irq_vectors(pci_dev, msi_config->total_vectors, msi_config->total_vectors, - PCI_IRQ_NOMSIX); @@ -113,8 +113,8 @@ Signed-off-by: Tamizh Chelvam + PCI_IRQ_LEGACY|PCI_IRQ_MSI); +#endif if (num_vectors == msi_config->total_vectors) { - set_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags); - ab_pci->irq_flags = IRQF_SHARED; + set_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags); + } else { --- a/drivers/net/wireless/ath/ath11k/pktlog.c +++ b/drivers/net/wireless/ath/ath11k/pktlog.c @@ -157,7 +157,11 @@ static char *ath_pktlog_getbuf(struct at @@ -143,14 +143,14 @@ Signed-off-by: Tamizh Chelvam static struct vm_operations_struct pktlog_vmops = { --- a/drivers/net/wireless/ath/ath11k/mhi.c +++ b/drivers/net/wireless/ath/ath11k/mhi.c -@@ -394,8 +394,10 @@ int ath11k_mhi_register(struct ath11k_pc +@@ -441,8 +441,10 @@ int ath11k_mhi_register(struct ath11k_pc return ret; } +#if LINUX_VERSION_IS_GEQ(5,15,0) - if (!test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags)) + if (!test_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags)) mhi_ctrl->irq_flags = IRQF_SHARED | IRQF_NOBALANCING; +#endif - np = of_find_node_by_type(NULL, "memory"); - if (!np) { + if (test_bit(ATH11K_FLAG_FIXED_MEM_RGN, &ab->dev_flags)) { + ret = ath11k_mhi_read_addr_from_dt(mhi_ctrl); diff --git a/feeds/ipq95xx/mac80211/patches/qca/321-002-ath11k-use-gic-api-irq-allocation.patch b/feeds/ipq95xx/mac80211/patches/qca/321-002-ath11k-use-gic-api-irq-allocation.patch index b6124eeb4..dd5cb2c7c 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/321-002-ath11k-use-gic-api-irq-allocation.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/321-002-ath11k-use-gic-api-irq-allocation.patch @@ -18,31 +18,9 @@ Signed-off-by: Tamizh Chelvam drivers/net/wireless/ath/ath11k/pci.h | 5 ++ 8 files changed, 218 insertions(+), 8 deletions(-) ---- a/drivers/net/wireless/ath/ath11k/ce.c -+++ b/drivers/net/wireless/ath/ath11k/ce.c -@@ -553,7 +553,10 @@ static void ath11k_ce_srng_msi_ring_para - - ring_params->msi_addr = addr_lo; - ring_params->msi_addr |= (dma_addr_t)(((uint64_t)addr_hi) << 32); -- ring_params->msi_data = (msi_data_idx % msi_data_count) + msi_data_start; -+ if (!ab->userpd_id) -+ ring_params->msi_data = (msi_data_idx % msi_data_count) + msi_data_start; -+ else -+ ring_params->msi_data = ab->ipci.ce_msi_data[ce_id]; - ring_params->flags |= HAL_SRNG_FLAGS_MSI_INTR; - } - --- a/drivers/net/wireless/ath/ath11k/ce.h +++ b/drivers/net/wireless/ath/ath11k/ce.h -@@ -7,6 +7,7 @@ - #define ATH11K_CE_H - - #define CE_COUNT_MAX 12 -+#define ATH11K_QCN6122_CE_COUNT 6 - - /* Byte swap data words */ - #define CE_ATTR_BYTE_SWAP_DATA 2 -@@ -192,6 +193,7 @@ struct ath11k_ce_pipe { +@@ -193,6 +193,7 @@ struct ath11k_ce_pipe { struct ce_tasklet_time tracker[CE_TIME_DURATION_MAX]; u32 sched_delay_gt_500US; u32 exec_delay_gt_500US; @@ -50,41 +28,9 @@ Signed-off-by: Tamizh Chelvam }; struct ath11k_ce { ---- a/drivers/net/wireless/ath/ath11k/core.h -+++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -925,6 +925,12 @@ struct ath11k_internal_pci { - const struct ath11k_msi_config *msi_cfg; - bool gic_enabled; - wait_queue_head_t gic_msi_waitq; -+ u32 address_lo; -+ u32 address_hi; -+ u32 dp_msi_data[ATH11K_EXT_IRQ_GRP_NUM_MAX]; -+ u32 ce_msi_data[ATH11K_QCN6122_CE_COUNT]; -+ u32 gic_ep_base_data; -+ u32 dp_irq_num[8]; - }; - - struct ath11k_memory_stats { ---- a/drivers/net/wireless/ath/ath11k/dp.c -+++ b/drivers/net/wireless/ath/ath11k/dp.c -@@ -231,8 +231,12 @@ static void ath11k_dp_srng_msi_setup(str - - ring_params->msi_addr = addr_lo; - ring_params->msi_addr |= (dma_addr_t)(((uint64_t)addr_hi) << 32); -- ring_params->msi_data = (msi_group_number % msi_data_count) -- + msi_data_start; -+ -+ if (!ab->userpd_id) -+ ring_params->msi_data = (msi_group_number % msi_data_count) -+ + msi_data_start; -+ else -+ ring_params->msi_data = ab->ipci.dp_msi_data[msi_group_number]; - - ring_params->flags |= HAL_SRNG_FLAGS_MSI_INTR; - } --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c -@@ -4,9 +4,9 @@ +@@ -5,9 +5,9 @@ */ #include @@ -95,250 +41,3 @@ Signed-off-by: Tamizh Chelvam #include "pci.h" #include "core.h" ---- a/drivers/net/wireless/ath/ath11k/pci_cmn.c -+++ b/drivers/net/wireless/ath/ath11k/pci_cmn.c -@@ -4,6 +4,7 @@ - */ - - #include -+#include - #include - #include "core.h" - #include "pci_cmn.h" -@@ -208,7 +209,10 @@ void ath11k_pci_config_static_window(str - - void ath11k_internal_pci_free_irq(struct ath11k_base *ab) - { -+ struct platform_device *pdev = ab->pdev; -+ - ath11k_pci_free_irq(ab); -+ platform_msi_domain_free_irqs(&pdev->dev); - } - - static void ath11k_pci_free_ext_irq(struct ath11k_base *ab) -@@ -330,16 +334,8 @@ void ath11k_pci_ce_tasklet(struct taskle - struct ath11k_ce_pipe *ce_pipe = from_tasklet(ce_pipe, t, intr_tq); - int irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_pipe->pipe_num; - -- if (ce_pipe->ab->ce_latency_stats_enable) -- ce_pipe->tasklet_ts.exec_entry_ts = ktime_get_boottime(); -- - ath11k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num); - -- if (ce_pipe->ab->ce_latency_stats_enable) { -- ce_pipe->tasklet_ts.exec_complete_ts = ktime_get_boottime(); -- ce_update_tasklet_time_duration_stats(ce_pipe); -- } -- - enable_irq(ce_pipe->ab->irq_num[irq_idx]); - } - -@@ -359,9 +355,6 @@ irqreturn_t ath11k_pci_ce_interrupt_hand - - tasklet_schedule(&ce_pipe->intr_tq); - -- if (ce_pipe->ab->ce_latency_stats_enable) -- ce_pipe->tasklet_ts.sched_entry_ts = ktime_get_boottime(); -- - return IRQ_HANDLED; - } - -@@ -460,6 +453,95 @@ irqreturn_t ath11k_pci_ext_interrupt_han - return IRQ_HANDLED; - } - -+ -+int ath11k_pci_ext_config_gic_msi_irq(struct ath11k_base *ab, struct platform_device *pdev, -+ struct msi_desc *msi_desc, int i) -+{ -+ u32 user_base_data = 0, base_vector = 0, base_idx; -+ struct ath11k_ext_irq_grp *irq_grp; -+ int j, ret = 0, num_vectors = 0; -+ u8 domain_id; -+ u32 num_irq = 0; -+ -+ domain_id = ath11k_pci_get_domain_id(ab); -+ base_idx = ATH11K_PCI_IRQ_CE0_OFFSET + CE_COUNT_MAX; -+ ret = ath11k_pci_get_user_msi_assignment(ab, ab->ipci.msi_cfg, 0, -+ "DP", &num_vectors, &user_base_data, -+ &base_vector); -+ if (ret < 0) -+ return ret; -+ -+ irq_grp = &ab->ext_irq_grp[i]; -+ irq_grp->ab = ab; -+ irq_grp->grp_id = i; -+ init_dummy_netdev(&irq_grp->napi_ndev); -+ netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi, -+ ath11k_pci_ext_grp_napi_poll, NAPI_POLL_WEIGHT); -+ -+ if (ab->hw_params.ring_mask->tx[i] || -+ ab->hw_params.ring_mask->rx[i] || -+ ab->hw_params.ring_mask->rx_err[i] || -+ ab->hw_params.ring_mask->rx_wbm_rel[i] || -+ ab->hw_params.ring_mask->reo_status[i] || -+ ab->hw_params.ring_mask->rxdma2host[i] || -+ ab->hw_params.ring_mask->host2rxdma[i] || -+ ab->hw_params.ring_mask->rx_mon_status[i]) { -+ num_irq = 1; -+ } -+ -+ irq_grp->num_irq = num_irq; -+ irq_grp->irqs[0] = base_idx + i; -+ -+ for (j = 0; j < irq_grp->num_irq; j++) { -+ -+ int irq_idx = irq_grp->irqs[j]; -+ int vector = (i % num_vectors) + base_vector; -+ -+ irq_set_status_flags(msi_desc->irq, IRQ_DISABLE_UNLAZY); -+ ret = devm_request_irq(&pdev->dev, msi_desc->irq, -+ ath11k_pci_ext_interrupt_handler, -+ IRQF_SHARED, dp_irq_name[domain_id][i], -+ irq_grp); -+ if (ret) { -+ ath11k_err(ab, "failed request irq %d: %d\n", -+ irq_idx, ret); -+ return ret; -+ } -+ ab->irq_num[irq_idx] = msi_desc->irq; -+ ab->ipci.dp_irq_num[vector] = msi_desc->irq; -+ ab->ipci.dp_msi_data[i] = msi_desc->msg.data; -+ disable_irq_nosync(ab->irq_num[irq_idx]); -+ } -+ return ret; -+} -+ -+int ath11k_pci_config_gic_msi_irq(struct ath11k_base *ab, struct platform_device *pdev, -+ struct msi_desc *msi_desc, int i) -+{ -+ struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i]; -+ int irq_idx, ret; -+ u8 domain_id; -+ -+ domain_id = ath11k_pci_get_domain_id(ab); -+ tasklet_setup(&ce_pipe->intr_tq, ath11k_pci_ce_tasklet); -+ irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i; -+ -+ ret = devm_request_irq(&pdev->dev, msi_desc->irq, -+ ath11k_pci_ce_interrupt_handler, -+ IRQF_SHARED, ce_irq_name[domain_id][i], -+ ce_pipe); -+ if (ret) { -+ ath11k_warn(ab, "failed to request irq %d: %d\n", -+ irq_idx, ret); -+ return ret; -+ } -+ ab->irq_num[irq_idx] = msi_desc->irq; -+ ab->ipci.ce_msi_data[i] = msi_desc->msg.data; -+ ath11k_pci_ce_irq_disable(ab, i); -+ -+ return ret; -+} -+ - static void __ath11k_pci_ext_irq_disable(struct ath11k_base *sc) - { - int i; -@@ -513,7 +595,7 @@ void ath11k_pci_ext_irq_disable(struct a - void ath11k_pci_get_qgic_msi_address(struct ath11k_base *ab, u32 *msi_addr_lo, - u32 *msi_addr_hi) - { -- *msi_addr_lo = 0; -+ *msi_addr_lo = ab->ipci.address_lo; - *msi_addr_hi = 0; - } - -@@ -584,9 +666,20 @@ void ath11k_pci_get_ce_msi_idx(struct at - *msi_idx = msi_data_idx; - } - -+void ath11k_gicv2m_msg_handler(struct msi_desc *desc, struct msi_msg *msg) -+{ -+ desc->msg.address_lo = msg->address_lo; -+ desc->msg.address_hi = msg->address_hi; -+ desc->msg.data = msg->data; -+} -+ - int ath11k_config_irq_internal_pci(struct ath11k_base *ab) - { - int ret; -+ struct platform_device *pdev = ab->pdev; -+ struct msi_desc *msi_desc; -+ bool ce_done = false; -+ int i = 0; - - if (ab->userpd_id != QCN6122_USERPD_0 && - ab->userpd_id != QCN6122_USERPD_1) { -@@ -596,6 +689,72 @@ int ath11k_config_irq_internal_pci(struc - - ab->ipci.msi_cfg = &ath11k_msi_config[ATH11K_MSI_CONFIG_QCN6122]; - -+ ret = platform_msi_domain_alloc_irqs(&pdev->dev, ab->ipci.msi_cfg->total_vectors, -+ ath11k_gicv2m_msg_handler); -+ if (ret) { -+ ath11k_warn(ab, "failed to alloc irqs %d ab %pM\n", ret, ab); -+ return ret; -+ } -+ -+ for_each_msi_entry(msi_desc, &pdev->dev) { -+ if (!ce_done && i == ab->hw_params.ce_count) { -+ i = 0; -+ ce_done = true; -+ } -+ -+ if (!ce_done && i < ab->hw_params.ce_count) { -+ if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) -+ i++; -+ -+ ret = ath11k_pci_config_gic_msi_irq(ab, pdev, msi_desc, i); -+ if (ret) { -+ ath11k_warn(ab, "failed to request irq %d\n", ret); -+ return ret; -+ } -+ } else { -+ ret = ath11k_pci_ext_config_gic_msi_irq(ab, pdev, msi_desc, i); -+ if (ret) { -+ ath11k_warn(ab, "failed to config ext msi irq %d\n", ret); -+ return ret; -+ } -+ } -+ -+ i++; -+ ab->ipci.address_lo = msi_desc->msg.address_lo; -+ ab->ipci.address_hi = msi_desc->msg.address_hi; -+ -+ if (i == 0 && !ce_done) -+ ab->ipci.gic_ep_base_data = msi_desc->msg.data; -+ -+ } -+ -+ for_each_msi_entry(msi_desc, &pdev->dev) { -+ u32 user_base_data = 0, base_vector = 0; -+ int vector, num_vectors = 0; -+ -+ ret = ath11k_pci_get_user_msi_assignment(ab, ab->ipci.msi_cfg, 0, -+ "DP", &num_vectors, &user_base_data, -+ &base_vector); -+ if (ret < 0) -+ return ret; -+ -+ vector = (i % num_vectors) + base_vector; -+ -+ if (i >= ATH11K_EXT_IRQ_GRP_NUM_MAX) -+ break; -+ -+ if (ab->ipci.dp_irq_num[vector] != msi_desc->irq) -+ continue; -+ -+ ret = ath11k_pci_ext_config_gic_msi_irq(ab, pdev, msi_desc, i); -+ if (ret) { -+ ath11k_warn(ab, "failed to config ext msi irq %d\n", ret); -+ return ret; -+ } -+ -+ i++; -+ } -+ - ab->ipci.gic_enabled = 1; - wake_up(&ab->ipci.gic_msi_waitq); - diff --git a/feeds/ipq95xx/mac80211/patches/qca/321-ath11k-add-spectral-160mhz.dump b/feeds/ipq95xx/mac80211/patches/qca/321-ath11k-add-spectral-160mhz.dump index 40681f31e..b8922586a 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/321-ath11k-add-spectral-160mhz.dump +++ b/feeds/ipq95xx/mac80211/patches/qca/321-ath11k-add-spectral-160mhz.dump @@ -35,7 +35,7 @@ Signed-off-by: Tamizh Chelvam --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -98,6 +98,7 @@ static const struct ath11k_hw_params ath +@@ -107,6 +107,7 @@ static const struct ath11k_hw_params ath .summary_pad_sz = 0, .fft_hdr_len = 16, .max_fft_bins = 512, @@ -43,7 +43,7 @@ Signed-off-by: Tamizh Chelvam }, .num_dscp_tid_map_tbl = HAL_DSCP_TID_MAP_TBL_NUM_ENTRIES_MAX, -@@ -167,6 +168,7 @@ static const struct ath11k_hw_params ath +@@ -187,6 +188,7 @@ static const struct ath11k_hw_params ath .summary_pad_sz = 0, .fft_hdr_len = 16, .max_fft_bins = 512, @@ -51,7 +51,7 @@ Signed-off-by: Tamizh Chelvam }, .interface_modes = BIT(NL80211_IFTYPE_STATION) | -@@ -228,6 +230,7 @@ static const struct ath11k_hw_params ath +@@ -266,6 +268,7 @@ static const struct ath11k_hw_params ath .summary_pad_sz = 0, .fft_hdr_len = 0, .max_fft_bins = 0, @@ -59,7 +59,7 @@ Signed-off-by: Tamizh Chelvam }, .interface_modes = BIT(NL80211_IFTYPE_STATION) | -@@ -287,6 +290,7 @@ static const struct ath11k_hw_params ath +@@ -341,6 +344,7 @@ static const struct ath11k_hw_params ath .summary_pad_sz = 16, .fft_hdr_len = 24, .max_fft_bins = 1024, @@ -67,7 +67,7 @@ Signed-off-by: Tamizh Chelvam }, .interface_modes = BIT(NL80211_IFTYPE_STATION) | -@@ -356,6 +360,7 @@ static const struct ath11k_hw_params ath +@@ -428,6 +432,7 @@ static const struct ath11k_hw_params ath .summary_pad_sz = 0, .fft_hdr_len = 0, .max_fft_bins = 0, @@ -75,7 +75,7 @@ Signed-off-by: Tamizh Chelvam }, .interface_modes = BIT(NL80211_IFTYPE_STATION) | -@@ -413,6 +418,7 @@ static const struct ath11k_hw_params ath +@@ -504,6 +509,7 @@ static const struct ath11k_hw_params ath .summary_pad_sz = 0, .fft_hdr_len = 0, .max_fft_bins = 0, @@ -83,7 +83,15 @@ Signed-off-by: Tamizh Chelvam }, .interface_modes = BIT(NL80211_IFTYPE_STATION) | -@@ -460,6 +466,7 @@ static const struct ath11k_hw_params ath +@@ -578,6 +584,7 @@ static const struct ath11k_hw_params ath + .summary_pad_sz = 0, + .fft_hdr_len = 0, + .max_fft_bins = 0, ++ .fragment_160mhz = false, + }, + + .interface_modes = BIT(NL80211_IFTYPE_STATION) | +@@ -644,6 +651,7 @@ static const struct ath11k_hw_params ath .summary_pad_sz = 16, .fft_hdr_len = 24, .max_fft_bins = 1024, @@ -91,17 +99,9 @@ Signed-off-by: Tamizh Chelvam }, .interface_modes = BIT(NL80211_IFTYPE_STATION) | -@@ -512,6 +519,7 @@ static const struct ath11k_hw_params ath - .summary_pad_sz = 16, - .fft_hdr_len = 24, - .max_fft_bins = 1024, -+ .fragment_160mhz = false, - }, - .credit_flow = false, - .num_dscp_tid_map_tbl = HAL_IPQ5018_DSCP_TID_MAP_TBL_NUM_ENTRIES_MAX, --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h -@@ -193,6 +193,7 @@ struct ath11k_hw_params { +@@ -199,6 +199,7 @@ struct ath11k_hw_params { u8 summary_pad_sz; u8 fft_hdr_len; u16 max_fft_bins; @@ -128,7 +128,7 @@ Signed-off-by: Tamizh Chelvam ret = ath11k_wmi_vdev_spectral_enable(ar, arvif->vdev_id, ATH11K_WMI_SPECTRAL_TRIGGER_CMD_CLEAR, ATH11K_WMI_SPECTRAL_ENABLE_CMD_ENABLE); -@@ -582,6 +585,7 @@ int ath11k_spectral_process_fft(struct a +@@ -585,6 +588,7 @@ int ath11k_spectral_process_fft(struct a u8 chan_width_mhz, bin_sz; int ret; u32 check_length; @@ -136,7 +136,7 @@ Signed-off-by: Tamizh Chelvam lockdep_assert_held(&ar->spectral.lock); -@@ -634,6 +638,11 @@ int ath11k_spectral_process_fft(struct a +@@ -639,6 +643,11 @@ int ath11k_spectral_process_fft(struct a case ATH11K_SPECTRAL_80MHZ: fft_sample->chan_width_mhz = chan_width_mhz; break; @@ -148,7 +148,7 @@ Signed-off-by: Tamizh Chelvam default: ath11k_warn(ab, "invalid channel width %d\n", chan_width_mhz); return -EINVAL; -@@ -658,6 +667,13 @@ int ath11k_spectral_process_fft(struct a +@@ -663,6 +672,13 @@ int ath11k_spectral_process_fft(struct a freq = summary->meta.freq2; fft_sample->freq2 = __cpu_to_be16(freq); @@ -174,7 +174,7 @@ Signed-off-by: Tamizh Chelvam #ifdef CPTCFG_ATH11K_SPECTRAL --- a/drivers/net/wireless/ath/spectral_common.h +++ b/drivers/net/wireless/ath/spectral_common.h -@@ -116,6 +116,7 @@ struct fft_sample_ath11k { +@@ -119,6 +119,7 @@ struct fft_sample_ath11k { u8 chan_width_mhz; s8 max_index; u8 max_exp; @@ -182,3 +182,13 @@ Signed-off-by: Tamizh Chelvam __be16 freq1; __be16 freq2; __be16 max_magnitude; +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -2255,6 +2255,7 @@ enum wmi_beacon_gen_mode { + enum wmi_direct_buffer_module { + WMI_DIRECT_BUF_SPECTRAL = 0, + WMI_DIRECT_BUF_CFR = 1, ++ WMI_CONFIG_MODULE_CV_UPLOAD = 2, + + /* keep it last */ + WMI_DIRECT_BUF_MAX diff --git a/feeds/ipq95xx/mac80211/patches/qca/321-ath11k-add-support-to-config-spatial-streams.patch b/feeds/ipq95xx/mac80211/patches/qca/321-ath11k-add-support-to-config-spatial-streams.patch index 8129e5ce0..1c6a46588 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/321-ath11k-add-support-to-config-spatial-streams.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/321-ath11k-add-support-to-config-spatial-streams.patch @@ -75,7 +75,7 @@ index 34f7227..d715ab9 100644 + u8 num_spatial_strm_mask; + + ret = kstrtou8_from_user(buf, count, 0, &num_spatial_strm_mask); -+ if (ret || num_spatial_strm_mask > GENMASK(sta->rx_nss - 1, 0)) ++ if (ret || num_spatial_strm_mask > GENMASK(sta->deflink.rx_nss - 1, 0)) + return -EINVAL; + + mutex_lock(&ar->conf_mutex); diff --git a/feeds/ipq95xx/mac80211/patches/qca/323-ath11k-add-debug-code-to-dump-peer-assoc-params.patch b/feeds/ipq95xx/mac80211/patches/qca/323-ath11k-add-debug-code-to-dump-peer-assoc-params.patch index c5916d9ba..1a23b1621 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/323-ath11k-add-debug-code-to-dump-peer-assoc-params.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/323-ath11k-add-debug-code-to-dump-peer-assoc-params.patch @@ -60,10 +60,10 @@ Signed-off-by: Rameshkumar Sundaram + arg->bw_40, arg->bw_80, arg->bw_160); + + ath11k_warn(ar->ab, "STA(%pM) Capabilities:\nhe %d vht %d ht %d bw %d", -+ sta->addr, sta->he_cap.has_he, sta->vht_cap.vht_supported, -+ sta->ht_cap.ht_supported, sta->bandwidth); -+ ath11k_warn(ar->ab, "ht cap = 0x%x vht cap = 0x%x", sta->ht_cap.cap, sta->vht_cap.cap); -+ he_cap = &sta->he_cap.he_cap_elem; ++ sta->addr, sta->deflink.he_cap.has_he, sta->deflink.vht_cap.vht_supported, ++ sta->deflink.ht_cap.ht_supported, sta->deflink.bandwidth); ++ ath11k_warn(ar->ab, "ht cap = 0x%x vht cap = 0x%x", sta->deflink.ht_cap.cap, sta->deflink.vht_cap.cap); ++ he_cap = &sta->deflink.he_cap.he_cap_elem; + print_hex_dump(KERN_ERR, "he_cap: ", DUMP_PREFIX_ADDRESS, 16, 1, + he_cap, sizeof(struct ieee80211_he_cap_elem), false); + @@ -90,7 +90,7 @@ Signed-off-by: Rameshkumar Sundaram @@ -3026,12 +3060,12 @@ static void ath11k_bss_assoc(struct ieee /* he_cap here is updated at assoc success for sta mode only */ - he_cap = ap_sta->he_cap; + he_cap = ap_sta->deflink.he_cap; - ath11k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg, false); + debug = ath11k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg, false); diff --git a/feeds/ipq95xx/mac80211/patches/qca/323-ath11k-radio-phy-probe-sequence.patch b/feeds/ipq95xx/mac80211/patches/qca/323-ath11k-radio-phy-probe-sequence.patch index bbd337fed..00041ad94 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/323-ath11k-radio-phy-probe-sequence.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/323-ath11k-radio-phy-probe-sequence.patch @@ -20,17 +20,17 @@ Signed-off-by: Karthikeyan Kathirvel --- a/drivers/net/wireless/ath/ath11k/ahb.c +++ b/drivers/net/wireless/ath/ath11k/ahb.c -@@ -829,6 +829,7 @@ static int ath11k_ahb_probe(struct platf - void __iomem *mem; - int userpd_id, ret = 0; +@@ -1063,6 +1063,7 @@ static int ath11k_ahb_probe(struct platf + enum ath11k_hw_rev hw_rev; + int ret; u32 hw_mode_id; + unsigned long left; of_id = of_match_device(ath11k_ahb_of_match, &pdev->dev); if (!of_id) { -@@ -860,6 +861,15 @@ static int ath11k_ahb_probe(struct platf +@@ -1105,6 +1106,15 @@ static int ath11k_ahb_probe(struct platf + ab->hw_rev = hw_rev; ab->fw_mode = ATH11K_FIRMWARE_MODE_NORMAL; - ab->userpd_id = userpd_id; ab->enable_cold_boot_cal = ath11k_cold_boot_cal; + mutex_lock(&dev_init_lock); + left = wait_event_timeout(ath11k_radio_prb_wq, dev_init_progress == false, @@ -43,12 +43,12 @@ Signed-off-by: Karthikeyan Kathirvel + platform_set_drvdata(pdev, ab); - if (ab->hw_rev != ATH11K_HW_QCN6122) { + ret = ath11k_pcic_register_pci_ops(ab, pci_ops); --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -61,6 +61,14 @@ MODULE_PARM_DESC(skip_radio_bmap, "Bitma - unsigned int ath11k_skip_radio; - EXPORT_SYMBOL(ath11k_skip_radio); +@@ -57,6 +57,15 @@ unsigned int ath11k_ftm_mode; + module_param_named(ftm_mode, ath11k_ftm_mode, uint, 0644); + MODULE_PARM_DESC(ftm_mode, "Boots up in factory test mode"); +wait_queue_head_t ath11k_radio_prb_wq; +EXPORT_SYMBOL(ath11k_radio_prb_wq); @@ -58,10 +58,11 @@ Signed-off-by: Karthikeyan Kathirvel + +struct mutex dev_init_lock; +EXPORT_SYMBOL(dev_init_lock); - ++ struct ath11k_base *ath11k_soc[MAX_SOCS]; -@@ -1976,6 +1984,9 @@ EXPORT_SYMBOL(ath11k_core_alloc); + static const struct ath11k_num_vdevs_peers ath11k_vdevs_peers[]; +@@ -2233,6 +2242,9 @@ EXPORT_SYMBOL(ath11k_core_alloc); int ath11k_init(void) { @@ -73,7 +74,7 @@ Signed-off-by: Karthikeyan Kathirvel module_init(ath11k_init); --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -10172,6 +10172,8 @@ int ath11k_mac_allocate(struct ath11k_ba +@@ -10587,6 +10587,8 @@ int ath11k_mac_allocate(struct ath11k_ba ret = -ENOMEM; goto err_free_mac; } @@ -84,15 +85,15 @@ Signed-off-by: Karthikeyan Kathirvel ar->hw = hw; --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c -@@ -856,6 +856,7 @@ static int ath11k_pci_probe(struct pci_d - struct ath11k_pci *ab_pci; +@@ -760,6 +760,7 @@ static int ath11k_pci_probe(struct pci_d u32 soc_hw_version_major, soc_hw_version_minor, addr; + const struct ath11k_pci_ops *pci_ops; int ret; + unsigned long left; - ab = ath11k_core_alloc(&pdev->dev, sizeof(*ab_pci), ATH11K_BUS_PCI, - &ath11k_pci_bus_params); -@@ -874,6 +875,15 @@ static int ath11k_pci_probe(struct pci_d + ab = ath11k_core_alloc(&pdev->dev, sizeof(*ab_pci), ATH11K_BUS_PCI); + +@@ -778,6 +779,15 @@ static int ath11k_pci_probe(struct pci_d pci_set_drvdata(pdev, ab); ab->fw_recovery_support = false; @@ -110,17 +111,18 @@ Signed-off-by: Karthikeyan Kathirvel /* Set fixed_mem_region to true for platforms support reserved memory --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -35,6 +35,9 @@ extern bool ath11k_collect_dump; +@@ -40,6 +40,10 @@ extern wait_queue_head_t ath11k_ssr_dump + extern bool ath11k_collect_dump; #endif - extern unsigned int ath11k_skip_radio; +extern wait_queue_head_t ath11k_radio_prb_wq; +extern bool dev_init_progress; +extern struct mutex dev_init_lock; - ++ #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK) -@@ -61,6 +64,8 @@ extern unsigned int ath11k_frame_mode; + #define ATH11K_TX_MGMT_NUM_PENDING_MAX 512 +@@ -79,6 +83,8 @@ extern unsigned int ath11k_frame_mode; #define MAX_SOCS 3 diff --git a/feeds/ipq95xx/mac80211/patches/qca/324-ath11k-Add-module-param-to-specific-caldata-file-loc.patch b/feeds/ipq95xx/mac80211/patches/qca/324-ath11k-Add-module-param-to-specific-caldata-file-loc.patch index e9cb5082e..8f6a95958 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/324-ath11k-Add-module-param-to-specific-caldata-file-loc.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/324-ath11k-Add-module-param-to-specific-caldata-file-loc.patch @@ -24,10 +24,10 @@ Signed-off-by: Tamizh Chelvam --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -61,6 +61,12 @@ MODULE_PARM_DESC(skip_radio_bmap, "Bitma - unsigned int ath11k_skip_radio; +@@ -63,6 +63,12 @@ unsigned int ath11k_skip_radio; EXPORT_SYMBOL(ath11k_skip_radio); + +char *ath11k_caldata_bin_path = NULL; +EXPORT_SYMBOL(ath11k_caldata_bin_path); +module_param(ath11k_caldata_bin_path, charp, 0644); @@ -39,7 +39,7 @@ Signed-off-by: Tamizh Chelvam --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c -@@ -3251,6 +3251,28 @@ err_free_req: +@@ -3287,6 +3287,28 @@ err_free_req: return ret; } @@ -68,7 +68,7 @@ Signed-off-by: Tamizh Chelvam static int ath11k_qmi_load_bdf_qmi(struct ath11k_base *ab, bool regdb) { -@@ -3331,7 +3353,10 @@ static int ath11k_qmi_load_bdf_qmi(struc +@@ -3359,7 +3381,10 @@ static int ath11k_qmi_load_bdf_qmi(struc ATH11K_QMI_DEF_CAL_FILE_SUFFIX); } @@ -82,7 +82,7 @@ Signed-off-by: Tamizh Chelvam --- a/drivers/net/wireless/ath/ath11k/qmi.h +++ b/drivers/net/wireless/ath/ath11k/qmi.h -@@ -66,6 +66,7 @@ +@@ -73,6 +73,7 @@ struct ath11k_base; extern unsigned int ath11k_host_ddr_addr; diff --git a/feeds/ipq95xx/mac80211/patches/qca/324-ath11k-add-CFR-capture-support-for-ipq5018-qcn6122.patch b/feeds/ipq95xx/mac80211/patches/qca/324-ath11k-add-CFR-capture-support-for-ipq5018-qcn6122.patch index adfa3e4f4..a62d8b56e 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/324-ath11k-add-CFR-capture-support-for-ipq5018-qcn6122.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/324-ath11k-add-CFR-capture-support-for-ipq5018-qcn6122.patch @@ -48,10 +48,8 @@ Signed-off-by: Abinaya Kalaiselvan drivers/net/wireless/ath/ath11k/hw.h | 2 + 5 files changed, 108 insertions(+), 11 deletions(-) -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/cfr.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath11k/cfr.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/cfr.c +--- a/drivers/net/wireless/ath/ath11k/cfr.c ++++ b/drivers/net/wireless/ath/ath11k/cfr.c @@ -190,10 +190,11 @@ static int ath11k_cfr_correlate_and_rela "dbr event -> txrx event delay = %u ms", jiffies_to_msecs(diff)); @@ -85,10 +83,8 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/cfr return -EINVAL; mutex_lock(&ar->conf_mutex); -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/cfr.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath11k/cfr.h -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/cfr.h +--- a/drivers/net/wireless/ath/ath11k/cfr.h ++++ b/drivers/net/wireless/ath/ath11k/cfr.h @@ -22,9 +22,8 @@ #define ATH11K_CFR_RADIO_IPQ8074 23 @@ -101,11 +97,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/cfr #define VENDOR_QCA 0x8cfdf0 #define PLATFORM_TYPE_ARM 2 -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/core.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath11k/core.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/core.c -@@ -382,13 +382,12 @@ static const struct ath11k_hw_params ath +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -405,12 +405,12 @@ static const struct ath11k_hw_params ath .cfr_support = true, .cfr_dma_hdr_size = sizeof(struct ath11k_cfir_enh_dma_hdr), .cfr_num_stream_bufs = 255, @@ -115,16 +109,23 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/cor * max cfr payload(16384 bytes) */ - .cfr_stream_buf_size = sizeof(struct ath11k_csi_cfr_header) + -- (CFR_HDR_MAX_LEN_WORDS_QCN9074 *4) + -- CFR_DATA_MAX_LEN_QCN9074, -- +- (CFR_HDR_MAX_LEN_WORDS_QCN9074 *4) + +- CFR_DATA_MAX_LEN_QCN9074, + .cfr_stream_buf_size = 16716, /* In addition to TCL ring use TCL_CMD ring also for tx */ .max_tx_ring = DP_TCL_NUM_RING_MAX + 1, - .reo_status_poll = false, -@@ -602,6 +601,15 @@ static const struct ath11k_hw_params ath + .num_vdevs_peers = ath11k_vdevs_peers, +@@ -710,14 +710,18 @@ static const struct ath11k_hw_params ath + .fixed_fw_mem = false, + .support_off_channel_tx = false, + .is_qdss_support = false, +- .cfr_support = true, +- .cfr_dma_hdr_size = sizeof(struct ath11k_cfir_dma_hdr), +- .cfr_num_stream_bufs = 255, +- /* csi_cfr_header + cfr header + max cfr payload */ +- .cfr_stream_buf_size = 8500, + /* In addition to TCL ring use TCL_CMD ring also for tx */ .max_tx_ring = DP_TCL_NUM_RING_MAX, - .reo_status_poll = true, .num_vdevs_peers = ath11k_vdevs_peers_ipq5018, + .cfr_support = true, + .cfr_dma_hdr_size = sizeof(struct ath11k_cfir_dma_hdr), @@ -138,9 +139,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/cor }, { .hw_rev = ATH11K_HW_QCN6122, -@@ -659,6 +667,15 @@ static const struct ath11k_hw_params ath +@@ -791,6 +795,15 @@ static const struct ath11k_hw_params ath + .caldb_offset = ATH11K_QMI_QCN6122_CALDB_OFFSET, .max_tx_ring = DP_TCL_NUM_RING_MAX, - .reo_status_poll = true, .num_vdevs_peers = ath11k_vdevs_peers_ipq5018, + .cfr_support = true, + .cfr_dma_hdr_size = sizeof(struct ath11k_cfir_enh_dma_hdr), @@ -154,11 +155,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/cor }, }; -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/hw.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath11k/hw.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/hw.c -@@ -1300,6 +1300,78 @@ void ath11k_hw_qcn9074_fill_cfr_hdr_info +--- a/drivers/net/wireless/ath/ath11k/hw.c ++++ b/drivers/net/wireless/ath/ath11k/hw.c +@@ -1306,6 +1306,78 @@ void ath11k_hw_qcn9074_fill_cfr_hdr_info sizeof(params->agc_gain)); } @@ -237,24 +236,30 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/hw. const struct ath11k_hw_ops ipq8074_ops = { .get_hw_mac_from_pdev_id = ath11k_hw_ipq8074_mac_from_pdev_id, .wmi_init_config = ath11k_init_wmi_config_ipq8074, -@@ -1620,6 +1692,7 @@ const struct ath11k_hw_ops qcn6122_ops = +@@ -1615,6 +1687,7 @@ const struct ath11k_hw_ops ipq5018_ops = .rx_desc_get_decap_type = ath11k_hw_qcn9074_rx_desc_get_decap_type, .rx_desc_get_mesh_ctl = ath11k_hw_qcn9074_rx_desc_get_mesh_ctl, - .rx_desc_get_ip_valid = ath11k_hw_qcn9074_rx_desc_get_ip_valid, + .rx_desc_get_ldpc_support = ath11k_hw_qcn9074_rx_desc_get_ldpc_support, ++ .fill_cfr_hdr_info = ath11k_hw_ipq5018_fill_cfr_hdr_info, + .rx_desc_get_mpdu_seq_ctl_vld = ath11k_hw_qcn9074_rx_desc_get_mpdu_seq_ctl_vld, + .rx_desc_get_mpdu_fc_valid = ath11k_hw_qcn9074_rx_desc_get_mpdu_fc_valid, + .rx_desc_get_mpdu_start_seq_no = ath11k_hw_qcn9074_rx_desc_get_mpdu_start_seq_no, +@@ -1665,6 +1738,7 @@ const struct ath11k_hw_ops qcn6122_ops = + .rx_desc_get_decap_type = ath11k_hw_qcn9074_rx_desc_get_decap_type, + .rx_desc_get_mesh_ctl = ath11k_hw_qcn9074_rx_desc_get_mesh_ctl, + .rx_desc_get_ldpc_support = ath11k_hw_qcn9074_rx_desc_get_ldpc_support, + .fill_cfr_hdr_info = ath11k_hw_qcn6122_fill_cfr_hdr_info, .rx_desc_get_mpdu_seq_ctl_vld = ath11k_hw_qcn9074_rx_desc_get_mpdu_seq_ctl_vld, .rx_desc_get_mpdu_fc_valid = ath11k_hw_qcn9074_rx_desc_get_mpdu_fc_valid, .rx_desc_get_mpdu_start_seq_no = ath11k_hw_qcn9074_rx_desc_get_mpdu_start_seq_no, -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/hw.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath11k/hw.h -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath11k/hw.h -@@ -231,6 +231,8 @@ struct ath11k_hw_params { +--- a/drivers/net/wireless/ath/ath11k/hw.h ++++ b/drivers/net/wireless/ath/ath11k/hw.h +@@ -229,6 +229,8 @@ struct ath11k_hw_params { bool cfr_support; u32 cfr_dma_hdr_size; u32 cfr_num_stream_bufs; + u32 cfr_max_header_len_words; + u32 cfr_max_data_len; u32 cfr_stream_buf_size; - bool reo_status_poll; const struct ath11k_num_vdevs_peers *num_vdevs_peers; + bool supports_rssi_stats; diff --git a/feeds/ipq95xx/mac80211/patches/qca/324-ath11k-ipq9574-support.patch b/feeds/ipq95xx/mac80211/patches/qca/324-ath11k-ipq9574-support.patch index 7b16f56ed..78f3130fa 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/324-ath11k-ipq9574-support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/324-ath11k-ipq9574-support.patch @@ -17,7 +17,7 @@ Signed-off-by: Karthikeyan Kathirvel --- a/drivers/net/wireless/ath/ath11k/ahb.c +++ b/drivers/net/wireless/ath/ath11k/ahb.c -@@ -31,6 +31,9 @@ static const struct of_device_id ath11k_ +@@ -37,6 +37,9 @@ static const struct of_device_id ath11k_ { .compatible = "qcom,qcn6122-wifi", .data = (void *)ATH11K_HW_QCN6122, }, @@ -27,9 +27,17 @@ Signed-off-by: Karthikeyan Kathirvel { } }; +@@ -1137,6 +1140,7 @@ static int ath11k_ahb_probe(struct platf + case ATH11K_HW_IPQ8074: + case ATH11K_HW_IPQ6018_HW10: + case ATH11K_HW_IPQ5018: ++ case ATH11K_HW_IPQ9574: + hif_ops = &ath11k_ahb_hif_ops_ipq8074; + pci_ops = NULL; + break; --- a/drivers/net/wireless/ath/ath11k/ce.c +++ b/drivers/net/wireless/ath/ath11k/ce.c -@@ -247,6 +247,96 @@ const struct ce_attr ath11k_host_ce_conf +@@ -248,6 +248,96 @@ const struct ce_attr ath11k_host_ce_conf }, }; @@ -138,9 +146,9 @@ Signed-off-by: Karthikeyan Kathirvel void ath11k_ce_rx_replenish_retry(struct timer_list *t); --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -679,6 +679,74 @@ static const struct ath11k_hw_params ath - */ - .cfr_stream_buf_size = 16580, +@@ -778,6 +778,82 @@ static const struct ath11k_hw_params ath + .reo_status_poll = false, + .num_vdevs_peers = ath11k_vdevs_peers_ipq5018, }, + { + .hw_rev = ATH11K_HW_IPQ9574, @@ -185,10 +193,9 @@ Signed-off-by: Karthikeyan Kathirvel + .fragment_160mhz = true, + }, + .num_dscp_tid_map_tbl = HAL_DSCP_TID_MAP_TBL_NUM_ENTRIES_MAX, -+ + .interface_modes = BIT(NL80211_IFTYPE_STATION) | -+ BIT(NL80211_IFTYPE_AP) | -+ BIT(NL80211_IFTYPE_MESH_POINT), ++ BIT(NL80211_IFTYPE_AP) | ++ BIT(NL80211_IFTYPE_MESH_POINT), + .supports_monitor = true, + .supports_shadow_regs = false, + .idle_ps = false, @@ -206,24 +213,33 @@ Signed-off-by: Karthikeyan Kathirvel + .cfr_stream_buf_size = 8500, + /* In addition to TCL ring use TCL_CMD ring also for tx */ + .max_tx_ring = DP_TCL_NUM_RING_MAX + 1, -+ .wakeup_mhi = false, -+ .reo_status_poll = false, ++ //.wakeup_mhi = false, + .num_vdevs_peers = ath11k_vdevs_peers, ++ .supports_sta_ps = false, ++ .dbr_debug_support = true, ++ .bios_sar_capa = NULL, ++ .m3_fw_support = false, ++ .fixed_bdf_addr = true, ++ .fixed_mem_region = true, ++ .static_window_map = false, ++ .hybrid_bus_type = false, ++ .fixed_fw_mem = false, ++ .support_off_channel_tx = false, + }, }; static const struct ath11k_num_vdevs_peers ath11k_vdevs_peers_ipq5018[] = { --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -157,6 +157,7 @@ enum ath11k_hw_rev { - ATH11K_HW_WCN6855_HW21, +@@ -181,6 +181,7 @@ enum ath11k_hw_rev { + ATH11K_HW_WCN6750_HW10, ATH11K_HW_IPQ5018, ATH11K_HW_QCN6122, + ATH11K_HW_IPQ9574, }; enum ath11k_firmware_mode { -@@ -1305,6 +1306,9 @@ extern const struct service_to_pipe ath1 +@@ -1432,6 +1433,9 @@ extern const struct service_to_pipe ath1 extern const struct ce_pipe_config ath11k_target_ce_config_wlan_ipq5018[]; extern const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_ipq5018[]; @@ -235,7 +251,7 @@ Signed-off-by: Karthikeyan Kathirvel int ath11k_core_init(struct ath11k_base *ath11k); --- a/drivers/net/wireless/ath/ath11k/hw.c +++ b/drivers/net/wireless/ath/ath11k/hw.c -@@ -35,6 +35,15 @@ static u8 ath11k_hw_ipq6018_mac_from_pde +@@ -36,6 +36,15 @@ static u8 ath11k_hw_ipq6018_mac_from_pde return pdev_idx; } @@ -251,8 +267,8 @@ Signed-off-by: Karthikeyan Kathirvel static void ath11k_hw_ipq8074_tx_mesh_enable(struct ath11k_base *ab, struct hal_tcl_data_cmd *tcl_cmd) { -@@ -1726,6 +1735,58 @@ const struct ath11k_hw_ops qcn6122_ops = - .rx_desc_get_hal_ppdu_id = ath11k_hw_qcn9074_rx_desc_get_hal_mpdu_ppdu_id, +@@ -1761,6 +1770,58 @@ const struct ath11k_hw_ops qcn6122_ops = + .get_reo_dest_remap_config = ath11k_get_reo_dest_remap_config_5018, }; +const struct ath11k_hw_ops ipq9574_ops = { @@ -310,7 +326,7 @@ Signed-off-by: Karthikeyan Kathirvel #define ATH11K_TX_RING_MASK_0 0x1 #define ATH11K_TX_RING_MASK_1 0x2 #define ATH11K_TX_RING_MASK_2 0x4 -@@ -2667,6 +2728,108 @@ const struct ce_pipe_config ath11k_targe +@@ -2706,6 +2767,108 @@ const struct ce_pipe_config ath11k_targe }, }; @@ -419,7 +435,7 @@ Signed-off-by: Karthikeyan Kathirvel /* Map from service/endpoint to Copy Engine for IPQ5018. * This table is derived from the CE TABLE, above. * It is passed to the Target at startup for use by firmware. -@@ -2764,6 +2927,108 @@ const struct service_to_pipe ath11k_targ +@@ -2803,6 +2966,108 @@ const struct service_to_pipe ath11k_targ { /* terminator entry */ } }; @@ -530,18 +546,19 @@ Signed-off-by: Karthikeyan Kathirvel .tx = { --- a/drivers/net/wireless/ath/ath11k/qmi.h +++ b/drivers/net/wireless/ath/ath11k/qmi.h -@@ -71,6 +71,7 @@ - #define QCN6122_DEVICE_BAR_SIZE 0x200000 - #define ATH11K_RCV_GIC_MSI_HDLR_DELAY (3 * HZ) +@@ -71,6 +71,8 @@ + #define ATH11K_RCV_GIC_MSI_HDLR_DELAY (3 * HZ) #define ATH11K_QMI_QCN6122_M3_DUMP_ADDRESS 0x4E200000 -+#define ATH11K_QMI_IPQ9574_M3_DUMP_ADDRESS 0x4D600000 ++#define ATH11K_QMI_IPQ9574_M3_DUMP_ADDRESS 0x4D600000 ++ struct ath11k_base; extern unsigned int ath11k_host_ddr_addr; + extern char *ath11k_caldata_bin_path; --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h -@@ -308,6 +308,7 @@ extern const struct ath11k_hw_ops qcn907 - extern const struct ath11k_hw_ops wcn6855_ops; +@@ -319,6 +319,7 @@ extern const struct ath11k_hw_ops wcn685 + extern const struct ath11k_hw_ops wcn6750_ops; extern const struct ath11k_hw_ops ipq5018_ops; extern const struct ath11k_hw_ops qcn6122_ops; +extern const struct ath11k_hw_ops ipq9574_ops; diff --git a/feeds/ipq95xx/mac80211/patches/qca/325-ath11k-Add-support-to-packet-error-rate.patch b/feeds/ipq95xx/mac80211/patches/qca/325-ath11k-Add-support-to-packet-error-rate.patch index 296316445..84e6c02fe 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/325-ath11k-Add-support-to-packet-error-rate.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/325-ath11k-Add-support-to-packet-error-rate.patch @@ -36,12 +36,10 @@ Signed-off-by: Hari Chandrakanthan drivers/net/wireless/ath/ath11k/mac.c | 2 ++ 6 files changed, 80 insertions(+), 2 deletions(-) -diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h -index 34074d5..89bee8e 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -448,6 +448,8 @@ struct ath11k_driver_rx_pkts_flow { - atomic_t pkts_out; +@@ -588,6 +588,8 @@ struct ath11k_driver_rx_pkts_flow { + atomic_t pkts_out_to_netif; }; +DECLARE_EWMA(sta_per, 8, 16) @@ -49,7 +47,7 @@ index 34074d5..89bee8e 100644 struct ath11k_sta { struct ath11k_vif *arvif; -@@ -492,6 +494,12 @@ struct ath11k_sta { +@@ -635,6 +637,12 @@ struct ath11k_sta { u8 tx_pwr_multiplier; u8 chain_enable_bits; u32 tx_pwr[HTT_PPDU_STATS_USER_CMN_TX_PWR_ARR_SIZE]; @@ -62,11 +60,9 @@ index 34074d5..89bee8e 100644 #ifdef CPTCFG_ATH11K_CFR struct ath11k_per_peer_cfr_capture cfr_capture; #endif -diff --git a/drivers/net/wireless/ath/ath11k/debugfs_sta.c b/drivers/net/wireless/ath/ath11k/debugfs_sta.c -index 3db4d60..5db8c6f 100644 --- a/drivers/net/wireless/ath/ath11k/debugfs_sta.c +++ b/drivers/net/wireless/ath/ath11k/debugfs_sta.c -@@ -1573,16 +1573,53 @@ static ssize_t ath11k_dbg_sta_read_htt_comm_stats(struct file *file, +@@ -1482,16 +1482,53 @@ static ssize_t ath11k_dbg_sta_read_htt_c } else tx_pwr = 0; len += scnprintf(buf + len, sizeof(buf) - len, @@ -121,18 +117,16 @@ index 3db4d60..5db8c6f 100644 .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, -@@ -1646,5 +1683,5 @@ void ath11k_debugfs_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vi +@@ -1555,5 +1592,5 @@ void ath11k_debugfs_sta_op_add(struct ie ar->ab->wmi_ab.svc_map)) debugfs_create_file("config_nss", 0600, dir, sta, &fops_config_num_spatial_strm); - debugfs_create_file("htt_comm_stats", 0400, dir, sta, &fops_htt_comm_stats); + debugfs_create_file("htt_comm_stats", 0600, dir, sta, &fops_htt_comm_stats); } -diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c -index 3c85b33..ae859ef 100644 --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -1672,6 +1672,12 @@ ath11k_update_per_peer_tx_stats(struct ath11k *ar, +@@ -1685,6 +1685,12 @@ ath11k_update_per_peer_tx_stats(struct a peer_stats->mu_grpid = mu_grpid; peer_stats->mu_pos = mu_pos; peer_stats->ru_tones = arsta->txrate.he_ru_alloc; @@ -145,13 +139,11 @@ index 3c85b33..ae859ef 100644 if (unlikely(ath11k_debugfs_is_extd_tx_stats_enabled(ar))) ath11k_debugfs_sta_add_tx_stats(arsta, peer_stats, rate_idx); } -diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c -index 7392284..03f5b26 100644 --- a/drivers/net/wireless/ath/ath11k/dp_tx.c +++ b/drivers/net/wireless/ath/ath11k/dp_tx.c -@@ -647,6 +647,14 @@ static void ath11k_dp_tx_complete_msdu(struct ath11k *ar, - rate = arsta->last_txrate; - status.rate = &rate; +@@ -754,6 +754,14 @@ static void ath11k_dp_tx_complete_msdu(s + status.rates = &status_rate; + status.n_rates = 1; + if (ts->status != HAL_WBM_TQM_REL_REASON_FRAME_ACKED) { + arsta->fail_pkts += 1; @@ -164,8 +156,6 @@ index 7392284..03f5b26 100644 if (unlikely(ath11k_debugfs_is_extd_tx_stats_enabled(ar))) { if(arsta->wbm_tx_stats && wbm_status < HAL_WBM_REL_HTT_TX_COMP_STATUS_MAX) arsta->wbm_tx_stats->wbm_tx_comp_stats[wbm_status]++; -diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.h b/drivers/net/wireless/ath/ath11k/dp_tx.h -index 9635a4a..c41898a 100644 --- a/drivers/net/wireless/ath/ath11k/dp_tx.h +++ b/drivers/net/wireless/ath/ath11k/dp_tx.h @@ -9,6 +9,9 @@ @@ -178,7 +168,7 @@ index 9635a4a..c41898a 100644 struct ath11k_dp_htt_wbm_tx_status { u32 msdu_id; bool acked; -@@ -239,4 +242,18 @@ ath11k_dp_tx_get_encap_type(struct ath11k_vif *arvif, struct sk_buff *skb); +@@ -240,4 +243,18 @@ ath11k_dp_tx_get_encap_type(struct ath11 int ath11k_dp_tx_htt_rx_full_mon_setup(struct ath11k_base *ab, int mac_id, bool config); @@ -197,19 +187,14 @@ index 9635a4a..c41898a 100644 +} + #endif -diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c -index 88dc960..a5f05ae 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -5029,6 +5029,8 @@ static int ath11k_mac_station_add(struct ath11k *ar, +@@ -5377,6 +5377,8 @@ static int ath11k_mac_station_add(struct } } + ewma_sta_per_init(&arsta->per); + ewma_sta_per_add(&arsta->per, 1); + ewma_avg_rssi_init(&arsta->avg_rssi); return 0; - free_tx_stats: --- -2.7.4 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/325-ath11k-Enhance-existing-htt-stats-tlv.patch b/feeds/ipq95xx/mac80211/patches/qca/325-ath11k-Enhance-existing-htt-stats-tlv.patch index 0085f4380..602413951 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/325-ath11k-Enhance-existing-htt-stats-tlv.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/325-ath11k-Enhance-existing-htt-stats-tlv.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c +++ b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c -@@ -17,6 +17,17 @@ +@@ -18,6 +18,17 @@ #define HTT_TLV_HDR_LEN 4 @@ -18,7 +18,25 @@ #define PRINT_ARRAY_TO_BUF(out, buflen, arr, str, len, newline) \ do { \ int index = 0; u8 i; const char *str_val = str; \ -@@ -80,6 +91,10 @@ static inline void htt_print_tx_pdev_sta +@@ -38,6 +49,17 @@ + buflen += index; \ + } while (0) + ++#define CHAIN_ARRAY_TO_BUF(out, buflen, arr, len) \ ++ do { \ ++ int index = 0; u8 i; \ ++ for (i = 0; i < len; i++) { \ ++ index += scnprintf((out + buflen) + index, \ ++ (ATH11K_HTT_STATS_BUF_SIZE - buflen) - index, \ ++ " %u:%d,", i, arr[i]); \ ++ } \ ++ buflen += index; \ ++ } while (0) ++ + static inline void htt_print_stats_string_tlv(const void *tag_buf, + u16 tag_len, + struct debug_htt_stats_req *stats_req) +@@ -81,6 +103,10 @@ static inline void htt_print_tx_pdev_sta len += scnprintf(buf + len, buf_len - len, "HTT_TX_PDEV_STATS_CMN_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "mac_id = %lu\n", FIELD_GET(HTT_STATS_MAC_ID, htt_stats_buf->mac_id__word)); @@ -29,7 +47,7 @@ len += scnprintf(buf + len, buf_len - len, "hw_queued = %u\n", htt_stats_buf->hw_queued); len += scnprintf(buf + len, buf_len - len, "hw_reaped = %u\n", -@@ -94,6 +109,8 @@ static inline void htt_print_tx_pdev_sta +@@ -95,6 +121,8 @@ static inline void htt_print_tx_pdev_sta htt_stats_buf->hw_filt); len += scnprintf(buf + len, buf_len - len, "tx_abort = %u\n", htt_stats_buf->tx_abort); @@ -38,7 +56,7 @@ len += scnprintf(buf + len, buf_len - len, "mpdu_requeued = %u\n", htt_stats_buf->mpdu_requeued); len += scnprintf(buf + len, buf_len - len, "tx_xretry = %u\n", -@@ -108,6 +125,8 @@ static inline void htt_print_tx_pdev_sta +@@ -109,6 +137,8 @@ static inline void htt_print_tx_pdev_sta htt_stats_buf->cont_xretry); len += scnprintf(buf + len, buf_len - len, "tx_timeout = %u\n", htt_stats_buf->tx_timeout); @@ -47,7 +65,7 @@ len += scnprintf(buf + len, buf_len - len, "pdev_resets = %u\n", htt_stats_buf->pdev_resets); len += scnprintf(buf + len, buf_len - len, "phy_underrun = %u\n", -@@ -122,8 +141,26 @@ static inline void htt_print_tx_pdev_sta +@@ -123,8 +153,26 @@ static inline void htt_print_tx_pdev_sta htt_stats_buf->seq_completed); len += scnprintf(buf + len, buf_len - len, "seq_restarted = %u\n", htt_stats_buf->seq_restarted); @@ -75,7 +93,7 @@ len += scnprintf(buf + len, buf_len - len, "seq_switch_hw_paused = %u\n", htt_stats_buf->seq_switch_hw_paused); len += scnprintf(buf + len, buf_len - len, "next_seq_posted_dsr = %u\n", -@@ -140,6 +177,8 @@ static inline void htt_print_tx_pdev_sta +@@ -141,6 +189,8 @@ static inline void htt_print_tx_pdev_sta htt_stats_buf->mpdu_removed_tqm); len += scnprintf(buf + len, buf_len - len, "msdu_removed_tqm = %u\n", htt_stats_buf->msdu_removed_tqm); @@ -84,7 +102,7 @@ len += scnprintf(buf + len, buf_len - len, "mpdus_sw_flush = %u\n", htt_stats_buf->mpdus_sw_flush); len += scnprintf(buf + len, buf_len - len, "mpdus_hw_filter = %u\n", -@@ -176,8 +215,10 @@ static inline void htt_print_tx_pdev_sta +@@ -177,8 +227,10 @@ static inline void htt_print_tx_pdev_sta htt_stats_buf->isr_wait_seq_posted); len += scnprintf(buf + len, buf_len - len, "tx_active_dur_us_low = %u\n", htt_stats_buf->tx_active_dur_us_low); @@ -96,7 +114,7 @@ if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -441,18 +482,90 @@ static inline void htt_print_hw_stats_pd +@@ -442,18 +494,90 @@ static inline void htt_print_hw_stats_pd htt_stats_buf->rx_abort); len += scnprintf(buf + len, buf_len - len, "rx_abort_fail_count = %u\n", htt_stats_buf->rx_abort_fail_count); @@ -188,7 +206,7 @@ if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -711,6 +824,8 @@ static inline void htt_print_peer_stats_ +@@ -712,6 +836,8 @@ static inline void htt_print_peer_stats_ len += scnprintf(buf + len, buf_len - len, "transmitted_ppdu_bytes = %llu\n", htt_stats_buf->ppdu_transmitted_bytes_low | ((u64)htt_stats_buf->ppdu_transmitted_bytes_high << 32)); @@ -197,7 +215,7 @@ len += scnprintf(buf + len, buf_len - len, "ttl_removed_count = %u\n", htt_stats_buf->peer_ttl_removed_count); len += scnprintf(buf + len, buf_len - len, "inactive_time = %u\n\n", -@@ -864,6 +979,13 @@ static inline void htt_print_rx_peer_rat +@@ -865,6 +991,13 @@ static inline void htt_print_rx_peer_rat HTT_RX_PEER_STATS_NUM_BW_COUNTERS, "\n"); } @@ -211,7 +229,7 @@ for (j = 0; j < HTT_RX_PEER_STATS_NUM_GI_COUNTERS; j++) { len += scnprintf(buf + len, (buf_len - len), "rx_gi[%u] = ", j); -@@ -874,6 +996,37 @@ static inline void htt_print_rx_peer_rat +@@ -875,6 +1008,38 @@ static inline void htt_print_rx_peer_rat PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_pream, "rx_pream", HTT_RX_PDEV_STATS_NUM_PREAMBLE_TYPES, "\n"); @@ -242,14 +260,15 @@ + for (j = 0; j < HTT_RX_PEER_STATS_NUM_SPATIAL_STREAMS; j++) { + len += HTT_DBG_OUT(buf + len, buf_len - len, + "\nrx_per_chain_rssi_in_dbm[%u] = ", j); -+ ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_per_chain_rssi_in_dbm[j], ++ CHAIN_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_per_chain_rssi_in_dbm[j], + HTT_RX_PEER_STATS_NUM_BW_COUNTERS); ++ len += scnprintf(buf + len, buf_len - len, "\n"); + } + if (len >= buf_len) buf[buf_len - 1] = 0; else -@@ -1330,6 +1483,20 @@ htt_print_tx_selfgen_cmn_stats_tlv(const +@@ -1331,6 +1496,20 @@ htt_print_tx_selfgen_cmn_stats_tlv(const htt_stats_buf->delayed_bar_6); len += scnprintf(buf + len, buf_len - len, "delayed_bar_7 = %u\n\n", htt_stats_buf->delayed_bar_7); @@ -270,7 +289,7 @@ if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -1349,19 +1516,33 @@ htt_print_tx_selfgen_ac_stats_tlv(const +@@ -1350,19 +1529,33 @@ htt_print_tx_selfgen_ac_stats_tlv(const u32 buf_len = ATH11K_HTT_STATS_BUF_SIZE; len += scnprintf(buf + len, buf_len - len, "HTT_TX_SELFGEN_AC_STATS_TLV:\n"); @@ -311,7 +330,7 @@ htt_stats_buf->ac_mu_mimo_brpoll_3); if (len >= buf_len) -@@ -1382,29 +1563,35 @@ htt_print_tx_selfgen_ax_stats_tlv(const +@@ -1383,29 +1576,35 @@ htt_print_tx_selfgen_ax_stats_tlv(const u32 buf_len = ATH11K_HTT_STATS_BUF_SIZE; len += scnprintf(buf + len, buf_len - len, "HTT_TX_SELFGEN_AX_STATS_TLV:\n"); @@ -365,8 +384,8 @@ + len += HTT_DBG_OUT(buf + len, buf_len - len, "\nax_basic_trigger = %u\n", htt_stats_buf->ax_basic_trigger); len += scnprintf(buf + len, buf_len - len, "ax_ulmumimo_trigger = %u\n", - htt_stats_buf->ax_ulmumimo_trigger); -@@ -1435,18 +1622,32 @@ htt_print_tx_selfgen_ac_err_stats_tlv(co + htt_stats_buf->ax_ulmumimo_trigger); +@@ -1436,18 +1635,32 @@ htt_print_tx_selfgen_ac_err_stats_tlv(co len += scnprintf(buf + len, buf_len - len, "HTT_TX_SELFGEN_AC_ERR_STATS_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "ac_su_ndp_err = %u\n", htt_stats_buf->ac_su_ndp_err); @@ -400,7 +419,7 @@ if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -1468,27 +1669,38 @@ htt_print_tx_selfgen_ax_err_stats_tlv(co +@@ -1469,27 +1682,38 @@ htt_print_tx_selfgen_ax_err_stats_tlv(co len += scnprintf(buf + len, buf_len - len, "HTT_TX_SELFGEN_AX_ERR_STATS_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "ax_su_ndp_err = %u\n", htt_stats_buf->ax_su_ndp_err); @@ -453,8 +472,8 @@ + len += HTT_DBG_OUT(buf + len, buf_len - len, "\nax_basic_trigger_err = %u\n", htt_stats_buf->ax_basic_trigger_err); len += scnprintf(buf + len, buf_len - len, "ax_ulmumimo_trigger_err = %u\n", - htt_stats_buf->ax_ulmumimo_trigger_err); -@@ -1880,6 +2092,22 @@ htt_print_tx_pdev_stats_sched_per_txq_tl + htt_stats_buf->ax_ulmumimo_trigger_err); +@@ -1881,6 +2105,22 @@ htt_print_tx_pdev_stats_sched_per_txq_tl htt_stats_buf->notify_sched); len += scnprintf(buf + len, buf_len - len, "dur_based_sendn_term = %u\n\n", htt_stats_buf->dur_based_sendn_term); @@ -477,7 +496,7 @@ if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -2067,8 +2295,9 @@ htt_print_tx_tqm_pdev_stats_tlv_v(const +@@ -2068,8 +2308,9 @@ htt_print_tx_tqm_pdev_stats_tlv_v(const stats_req->buf_len = len; } @@ -489,7 +508,7 @@ { const struct htt_tx_tqm_cmn_stats_tlv *htt_stats_buf = tag_buf; u8 *buf = stats_req->buf; -@@ -2092,6 +2321,21 @@ static inline void htt_print_tx_tqm_cmn_ +@@ -2093,6 +2334,21 @@ static inline void htt_print_tx_tqm_cmn_ htt_stats_buf->drop_notification); len += scnprintf(buf + len, buf_len - len, "desc_threshold = %u\n\n", htt_stats_buf->desc_threshold); @@ -511,7 +530,7 @@ if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -2114,8 +2358,56 @@ static inline void htt_print_tx_tqm_erro +@@ -2115,8 +2371,56 @@ static inline void htt_print_tx_tqm_erro htt_stats_buf->q_empty_failure); len += scnprintf(buf + len, buf_len - len, "q_not_empty_failure = %u\n", htt_stats_buf->q_not_empty_failure); @@ -569,7 +588,7 @@ if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -2194,6 +2486,16 @@ htt_print_tx_de_eapol_packets_stats_tlv( +@@ -2195,6 +2499,16 @@ htt_print_tx_de_eapol_packets_stats_tlv( htt_stats_buf->g1_packets); len += scnprintf(buf + len, buf_len - len, "g2_packets = %u\n\n", htt_stats_buf->g2_packets); @@ -586,7 +605,7 @@ if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -2240,6 +2542,18 @@ htt_print_tx_de_classify_failed_stats_tl +@@ -2241,6 +2555,18 @@ htt_print_tx_de_classify_failed_stats_tl htt_stats_buf->ipv6_jumbogram_zero_length); len += scnprintf(buf + len, buf_len - len, "qos_to_non_qos_in_prog = %u\n\n", htt_stats_buf->qos_to_non_qos_in_prog); @@ -605,7 +624,7 @@ if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -2498,6 +2812,12 @@ htt_print_tx_de_cmn_stats_tlv(const void +@@ -2499,6 +2825,12 @@ htt_print_tx_de_cmn_stats_tlv(const void htt_stats_buf->wbm2fw_entry_count); len += scnprintf(buf + len, buf_len - len, "invalid_pdev = %u\n\n", htt_stats_buf->invalid_pdev); @@ -618,7 +637,7 @@ if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -2781,6 +3101,8 @@ static inline void htt_print_tx_pdev_rat +@@ -2782,6 +3114,8 @@ static inline void htt_print_tx_pdev_rat htt_stats_buf->rts_success); len += scnprintf(buf + len, buf_len - len, "ack_rssi = %u\n", htt_stats_buf->ack_rssi); @@ -627,7 +646,7 @@ len += scnprintf(buf + len, buf_len - len, "Legacy CCK Rates: 1 Mbps: %u, 2 Mbps: %u, 5.5 Mbps: %u, 11 Mbps: %u\n", -@@ -2803,12 +3125,24 @@ static inline void htt_print_tx_pdev_rat +@@ -2804,12 +3138,24 @@ static inline void htt_print_tx_pdev_rat PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->tx_mcs, "tx_mcs", HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS, "\n"); @@ -652,7 +671,7 @@ PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->tx_nss, "tx_nss", HTT_TX_PDEV_STATS_NUM_SPATIAL_STREAMS, "\n"); PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->ac_mu_mimo_tx_nss, -@@ -2830,6 +3164,9 @@ static inline void htt_print_tx_pdev_rat +@@ -2831,6 +3177,9 @@ static inline void htt_print_tx_pdev_rat HTT_TX_PDEV_STATS_NUM_BW_COUNTERS, "\n"); PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->tx_stbc, "tx_stbc", HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS, "\n"); @@ -662,7 +681,7 @@ PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->tx_pream, "tx_pream", HTT_TX_PDEV_STATS_NUM_PREAMBLE_TYPES, "\n"); -@@ -2842,8 +3179,14 @@ static inline void htt_print_tx_pdev_rat +@@ -2843,8 +3192,14 @@ static inline void htt_print_tx_pdev_rat for (j = 0; j < HTT_TX_PDEV_STATS_NUM_GI_COUNTERS; j++) { len += scnprintf(buf + len, (buf_len - len), "tx_gi[%u] = ", j); @@ -677,7 +696,7 @@ } /* AC MU-MIMO GI Stats */ -@@ -2860,6 +3203,9 @@ static inline void htt_print_tx_pdev_rat +@@ -2861,6 +3216,9 @@ static inline void htt_print_tx_pdev_rat "ax_mu_mimo_tx_gi[%u] = ", j); PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->ax_mu_mimo_tx_gi[j], NULL, HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS, "\n"); @@ -687,7 +706,7 @@ } /* DL OFDMA GI Stats */ -@@ -2868,11 +3214,18 @@ static inline void htt_print_tx_pdev_rat +@@ -2869,11 +3227,18 @@ static inline void htt_print_tx_pdev_rat "ofdma_tx_gi[%u] = ", j); PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->ofdma_tx_gi[j], NULL, HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS, "\n"); @@ -706,7 +725,7 @@ if (len >= buf_len) buf[buf_len - 1] = 0; else -@@ -3038,29 +3391,6 @@ static inline void htt_print_rx_pdev_rat +@@ -3041,33 +3406,6 @@ static inline void htt_print_rx_pdev_rat PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_ulofdma_mpdu_fail, "rx_ulofdma_mpdu_fail", HTT_RX_PDEV_MAX_OFDMA_NUM_USER, "\n"); @@ -722,23 +741,27 @@ - } - - PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_ulofdma_non_data_nusers, -- "rx_ulofdma_non_data_nusers", HTT_RX_PDEV_MAX_OFDMA_NUM_USER, "\n"); +- "rx_ulofdma_non_data_nusers", HTT_RX_PDEV_MAX_OFDMA_NUM_USER, +- "\n"); - - PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_ulofdma_data_nusers, -- "rx_ulofdma_data_nusers", HTT_RX_PDEV_MAX_OFDMA_NUM_USER, "\n"); +- "rx_ulofdma_data_nusers", HTT_RX_PDEV_MAX_OFDMA_NUM_USER, +- "\n"); - - PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_11ax_dl_ofdma_mcs, -- "rx_11ax_dl_ofdma_mcs", HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS, "\n"); +- "rx_11ax_dl_ofdma_mcs", HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS, +- "\n"); - - PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_11ax_dl_ofdma_ru, -- "rx_11ax_dl_ofdma_ru", HTT_RX_PDEV_STATS_NUM_RU_SIZE_COUNTERS, "\n"); +- "rx_11ax_dl_ofdma_ru", HTT_RX_PDEV_STATS_NUM_RU_SIZE_COUNTERS, +- "\n"); - PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_ulmumimo_non_data_ppdu, - "rx_ulmumimo_non_data_ppdu", HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER, "\n"); - -@@ -3073,6 +3403,13 @@ static inline void htt_print_rx_pdev_rat - PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_ulmumimo_mpdu_fail, - "rx_ulmumimo_mpdu_fail", HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER, "\n"); + "rx_ulmumimo_non_data_ppdu", HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER, + "\n"); +@@ -3084,6 +3422,13 @@ static inline void htt_print_rx_pdev_rat + "rx_ulmumimo_mpdu_fail", HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER, + "\n"); + for (j = 0; j < HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS; j++) { + len += HTT_DBG_OUT(buf + len, buf_len - len, @@ -750,7 +773,7 @@ len += scnprintf(buf + len, buf_len - len, "per_chain_rssi_pkt_type = %#x\n", htt_stats_buf->per_chain_rssi_pkt_type); -@@ -3087,6 +3424,23 @@ static inline void htt_print_rx_pdev_rat +@@ -3098,6 +3443,23 @@ static inline void htt_print_rx_pdev_rat htt_stats_buf->rx_per_chain_rssi_in_dbm[j][i]); len += scnprintf(buf + len, buf_len - len, "\n"); } @@ -774,7 +797,7 @@ len += scnprintf(buf + len, buf_len - len, "\n"); if (len >= buf_len) -@@ -3651,22 +4005,27 @@ htt_print_pdev_obss_pd_stats_tlv_v(const +@@ -3662,22 +4024,27 @@ htt_print_pdev_obss_pd_stats_tlv_v(const u32 len = stats_req->buf_len; u32 buf_len = ATH11K_HTT_STATS_BUF_SIZE; @@ -815,7 +838,7 @@ if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -3683,30 +4042,33 @@ static inline void htt_print_backpressur +@@ -3694,30 +4061,33 @@ static inline void htt_print_backpressur (struct debug_htt_stats_req *)data; struct htt_ring_backpressure_stats_tlv *htt_stats_buf = (struct htt_ring_backpressure_stats_tlv *)tag_buf; @@ -859,7 +882,7 @@ if (len >= buf_len) { buf[buf_len - 1] = 0; -@@ -3839,9 +4201,6 @@ static inline void htt_print_ul_ofdma_tr +@@ -3850,9 +4220,6 @@ static inline void htt_print_ul_ofdma_tr PRINT_ARRAY_TO_BUF(buf, len, htt_trigger_stats_buf->ul_ofdma_rx_mcs, "ul_ofdma_rx_mcs", HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS, "\n"); @@ -869,7 +892,7 @@ for (j = 0; j < HTT_RX_PDEV_STATS_NUM_GI_COUNTERS; j++) { len += scnprintf(buf + len, buf_len - len, -@@ -3850,13 +4209,6 @@ static inline void htt_print_ul_ofdma_tr +@@ -3861,13 +4228,6 @@ static inline void htt_print_ul_ofdma_tr htt_trigger_stats_buf->ul_ofdma_rx_gi[j], NULL, HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS, "\n"); @@ -883,7 +906,7 @@ } PRINT_ARRAY_TO_BUF(buf, len, htt_trigger_stats_buf->ul_ofdma_rx_nss, -@@ -3866,6 +4218,12 @@ static inline void htt_print_ul_ofdma_tr +@@ -3877,6 +4237,12 @@ static inline void htt_print_ul_ofdma_tr PRINT_ARRAY_TO_BUF(buf, len, htt_trigger_stats_buf->ul_ofdma_rx_bw, "ul_ofdma_rx_bw", HTT_RX_PDEV_STATS_NUM_BW_COUNTERS, "\n"); @@ -896,7 +919,7 @@ len += scnprintf(buf + len, buf_len - len, "ul_ofdma_rx_stbc = %u\n", htt_trigger_stats_buf->ul_ofdma_rx_stbc); -@@ -3881,6 +4239,23 @@ static inline void htt_print_ul_ofdma_tr +@@ -3892,6 +4258,23 @@ static inline void htt_print_ul_ofdma_tr "rx_ulofdma_data_ru_size_ppdu", HTT_RX_PDEV_STATS_NUM_RU_SIZE_COUNTERS, "\n"); @@ -920,7 +943,7 @@ len += scnprintf(buf + len, buf_len - len, "\n\n"); stats_req->buf_len = len; -@@ -3913,7 +4288,7 @@ static inline void htt_print_ul_mumimo_t +@@ -3924,7 +4307,7 @@ static inline void htt_print_ul_mumimo_t PRINT_ARRAY_TO_BUF(buf, len, htt_ul_mumimo_trig_stats_buf->ul_mumimo_rx_mcs_ext, "ul_mumimo_ext_rx_mcs", @@ -929,7 +952,7 @@ for (j = 0; j < HTT_RX_PDEV_STATS_NUM_GI_COUNTERS; j++) { len += scnprintf(buf + len, buf_len - len, -@@ -3922,19 +4297,12 @@ static inline void htt_print_ul_mumimo_t +@@ -3933,19 +4316,12 @@ static inline void htt_print_ul_mumimo_t htt_ul_mumimo_trig_stats_buf->ul_mumimo_rx_gi[j], NULL, HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS, "\n"); @@ -950,7 +973,7 @@ PRINT_ARRAY_TO_BUF(buf, len, htt_ul_mumimo_trig_stats_buf->ul_mumimo_rx_bw, -@@ -3945,6 +4313,34 @@ static inline void htt_print_ul_mumimo_t +@@ -3956,6 +4332,34 @@ static inline void htt_print_ul_mumimo_t htt_ul_mumimo_trig_stats_buf->ul_mumimo_rx_stbc); len += scnprintf(buf + len, buf_len - len, "ul_mumimo_rx_ldpc = %u\n", htt_ul_mumimo_trig_stats_buf->ul_mumimo_rx_ldpc); @@ -985,7 +1008,7 @@ len += scnprintf(buf + len, buf_len - len, "\n\n"); stats_req->buf_len = len; -@@ -4081,18 +4477,28 @@ static inline void htt_print_rx_fse_stat +@@ -4092,18 +4496,28 @@ static inline void htt_print_rx_fse_stat stats_req->buf_len = len; } @@ -1018,7 +1041,7 @@ len += scnprintf(buf + len, buf_len - len, "tx_ol_mcs = "); for (i = 0; i < HTT_TX_TXBF_RATE_STATS_NUM_MCS_COUNTERS; i++) -@@ -4136,18 +4542,41 @@ void htt_print_pdev_tx_rate_txbf_stats_t +@@ -4147,18 +4561,41 @@ void htt_print_pdev_tx_rate_txbf_stats_t "%d:%u,", i, htt_stats_buf->tx_su_ol_bw[i]); len--; @@ -1060,7 +1083,7 @@ len += scnprintf(buf + len, buf_len - len, "\n"); stats_req->buf_len = len; -@@ -4359,14 +4788,15 @@ void htt_print_phy_stats_tlv(const void +@@ -4370,14 +4807,15 @@ void htt_print_phy_stats_tlv(const void len += HTT_DBG_OUT(buf + len, buf_len - len, "runtime_nf_chain[%d] = %d\n", i, htt_stats_buf->runtime_nf_chain[i]); @@ -1080,7 +1103,7 @@ stats_req->buf_len = len; } -@@ -4381,18 +4811,20 @@ static inline void htt_print_phy_reset_c +@@ -4392,18 +4830,20 @@ static inline void htt_print_phy_reset_c len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_PHY_RESET_COUNTERS_TLV:\n"); @@ -1107,7 +1130,7 @@ if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -4412,60 +4844,66 @@ static inline void htt_print_phy_reset_s +@@ -4423,60 +4863,66 @@ static inline void htt_print_phy_reset_s len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_PHY_RESET_STATS_TLV:\n"); @@ -1201,7 +1224,7 @@ if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -4484,13 +4922,12 @@ void htt_print_peer_ctrl_path_txrx_stats +@@ -4495,13 +4941,12 @@ void htt_print_peer_ctrl_path_txrx_stats u32 len = stats_req->buf_len; u32 buf_len = ATH11K_HTT_STATS_BUF_SIZE; int i; @@ -1221,7 +1244,7 @@ len += scnprintf(buf + len, buf_len - len, "HTT_STATS_PEER_CTRL_PATH_TXRX_STATS_TAG:\n"); -@@ -4500,16 +4937,16 @@ void htt_print_peer_ctrl_path_txrx_stats +@@ -4511,16 +4956,16 @@ void htt_print_peer_ctrl_path_txrx_stats htt_stat_buf->peer_mac_addr[2], htt_stat_buf->peer_mac_addr[3], htt_stat_buf->peer_mac_addr[4], htt_stat_buf->peer_mac_addr[5]); @@ -1246,10 +1269,20 @@ htt_stat_buf->peer_rx_mgmt_subtype[i]); len += scnprintf(buf + len, buf_len - len, "\n"); -@@ -4528,6 +4965,118 @@ void htt_print_peer_ctrl_path_txrx_stats - buflen += index; \ - } while (0) +@@ -4528,16 +4973,117 @@ void htt_print_peer_ctrl_path_txrx_stats + stats_req->buf_len = len; + } +-#define CHAIN_ARRAY_TO_BUF(out, buflen, arr, len) \ +- do { \ +- int index = 0; u8 i; \ +- for (i = 0; i < len; i++) { \ +- index += scnprintf((out + buflen) + index, \ +- (ATH11K_HTT_STATS_BUF_SIZE - buflen) - index, \ +- " %u:%d,", i, arr[i]); \ +- } \ +- buflen += index; \ +- } while (0) +static inline void htt_print_pdev_ctrl_path_tx_stats_tlv(const void *tag_buf, + struct debug_htt_stats_req *stats_req) +{ @@ -1361,11 +1394,10 @@ + + stats_req->buf_len = len; +} -+ + static inline void htt_print_rx_pdev_rate_ext_stats_tlv(const void *tag_buf, struct debug_htt_stats_req *stats_req) - { -@@ -4597,10 +5146,13 @@ static int ath11k_dbg_htt_ext_stats_pars +@@ -4608,10 +5154,13 @@ static int ath11k_dbg_htt_ext_stats_pars void *user_data) { struct debug_htt_stats_req *stats_req = user_data; @@ -1380,7 +1412,7 @@ break; case HTT_STATS_TX_PDEV_UNDERRUN_TAG: htt_print_tx_pdev_stats_urrn_tlv_v(tag_buf, len, stats_req); -@@ -4671,7 +5223,7 @@ static int ath11k_dbg_htt_ext_stats_pars +@@ -4682,7 +5231,7 @@ static int ath11k_dbg_htt_ext_stats_pars break; case HTT_STATS_TX_TQM_CMN_TAG: @@ -1389,7 +1421,7 @@ break; case HTT_STATS_TX_TQM_PDEV_TAG: -@@ -4940,6 +5492,9 @@ static int ath11k_dbg_htt_ext_stats_pars +@@ -4951,6 +5500,9 @@ static int ath11k_dbg_htt_ext_stats_pars case HTT_STATS_PDEV_OBSS_PD_TAG: htt_print_pdev_obss_pd_stats_tlv_v(tag_buf, stats_req); break; @@ -1399,7 +1431,7 @@ case HTT_STATS_RING_BACKPRESSURE_STATS_TAG: htt_print_backpressure_stats_tlv_v(tag_buf, user_data); break; -@@ -4997,6 +5552,15 @@ static int ath11k_dbg_htt_ext_stats_pars +@@ -5008,6 +5560,15 @@ static int ath11k_dbg_htt_ext_stats_pars case HTT_STATS_PEER_CTRL_PATH_TXRX_STATS_TAG: htt_print_peer_ctrl_path_txrx_stats_tlv(tag_buf, stats_req); break; @@ -1415,7 +1447,7 @@ case HTT_STATS_RX_PDEV_RATE_EXT_STATS_TAG: htt_print_rx_pdev_rate_ext_stats_tlv(tag_buf, stats_req); break; -@@ -5004,6 +5568,13 @@ static int ath11k_dbg_htt_ext_stats_pars +@@ -5015,6 +5576,13 @@ static int ath11k_dbg_htt_ext_stats_pars break; } @@ -1431,7 +1463,7 @@ --- a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h +++ b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h -@@ -110,6 +110,7 @@ enum htt_tlv_tag_t { +@@ -111,6 +111,7 @@ enum htt_tlv_tag_t { HTT_STATS_RX_PDEV_UL_MIMO_USER_STATS_TAG = 96, HTT_STATS_RX_PDEV_UL_MUMIMO_TRIG_STATS_TAG = 97, HTT_STATS_RX_FSE_STATS_TAG = 98, @@ -1439,7 +1471,7 @@ HTT_STATS_SCHED_TXQ_SUPERCYCLE_TRIGGER_TAG = 100, HTT_STATS_PEER_CTRL_PATH_TXRX_STATS_TAG = 101, HTT_STATS_PDEV_CTRL_PATH_TX_STATS_TAG = 102, -@@ -213,6 +214,27 @@ struct htt_tx_pdev_stats_cmn_tlv { +@@ -214,6 +215,27 @@ struct htt_tx_pdev_stats_cmn_tlv { u32 tx_active_dur_us_low; u32 tx_active_dur_us_high; @@ -1467,7 +1499,7 @@ }; /* NOTE: Variable length TLV, use length spec to infer array size */ -@@ -295,6 +317,33 @@ struct htt_hw_stats_pdev_errs_tlv { +@@ -296,6 +318,33 @@ struct htt_hw_stats_pdev_errs_tlv { u32 tx_glb_reset; u32 tx_txq_reset; u32 rx_timeout_reset; @@ -1501,7 +1533,7 @@ }; struct htt_hw_stats_whal_tx_tlv { -@@ -424,6 +473,7 @@ struct htt_peer_stats_cmn_tlv { +@@ -425,6 +474,7 @@ struct htt_peer_stats_cmn_tlv { u32 ppdu_transmitted_bytes_high; u32 peer_ttl_removed_count; u32 inactive_time; @@ -1509,7 +1541,7 @@ }; #define HTT_PEER_DETAILS_VDEV_ID GENMASK(7, 0) -@@ -452,6 +502,7 @@ enum htt_stats_param_type { +@@ -453,6 +503,7 @@ enum htt_stats_param_type { }; #define HTT_TX_PEER_STATS_NUM_MCS_COUNTERS 12 @@ -1517,7 +1549,7 @@ #define HTT_TX_PEER_STATS_NUM_GI_COUNTERS 4 #define HTT_TX_PEER_STATS_NUM_DCM_COUNTERS 5 /* HTT_TX_PEER_STATS_NUM_BW_COUNTERS: -@@ -461,6 +512,8 @@ enum htt_stats_param_type { +@@ -462,6 +513,8 @@ enum htt_stats_param_type { * bw index 3: rssi_ext40_high20_chain0 */ #define HTT_TX_PEER_STATS_NUM_BW_COUNTERS 4 @@ -1526,7 +1558,7 @@ #define HTT_TX_PEER_STATS_NUM_SPATIAL_STREAMS 8 #define HTT_TX_PEER_STATS_NUM_PREAMBLE_TYPES HTT_STATS_PREAM_COUNT -@@ -490,6 +543,7 @@ struct htt_tx_peer_rate_stats_tlv { +@@ -491,6 +544,7 @@ struct htt_tx_peer_rate_stats_tlv { }; #define HTT_RX_PEER_STATS_NUM_MCS_COUNTERS 12 @@ -1534,7 +1566,7 @@ #define HTT_RX_PEER_STATS_NUM_GI_COUNTERS 4 #define HTT_RX_PEER_STATS_NUM_DCM_COUNTERS 5 #define HTT_RX_PEER_STATS_NUM_BW_COUNTERS 4 -@@ -522,6 +576,27 @@ struct htt_rx_peer_rate_stats_tlv { +@@ -523,6 +577,27 @@ struct htt_rx_peer_rate_stats_tlv { /* Counters to track number of rx packets in each GI in each mcs (0-11) */ u32 rx_gi[HTT_RX_PEER_STATS_NUM_GI_COUNTERS] [HTT_RX_PEER_STATS_NUM_MCS_COUNTERS]; @@ -1562,7 +1594,7 @@ }; enum htt_peer_stats_req_mode { -@@ -538,6 +613,7 @@ enum htt_peer_stats_tlv_enum { +@@ -539,6 +614,7 @@ enum htt_peer_stats_tlv_enum { HTT_TX_TID_STATS_TLV = 4, HTT_RX_TID_STATS_TLV = 5, HTT_MSDU_FLOW_STATS_TLV = 6, @@ -1570,7 +1602,7 @@ HTT_PEER_STATS_MAX_TLV = 31, }; -@@ -658,6 +734,11 @@ struct htt_tx_hwq_txop_used_cnt_hist_tlv +@@ -659,6 +735,11 @@ struct htt_tx_hwq_txop_used_cnt_hist_tlv }; /* == TX SELFGEN STATS == */ @@ -1582,7 +1614,7 @@ struct htt_tx_selfgen_cmn_stats_tlv { u32 mac_id__word; u32 su_bar; -@@ -671,6 +752,13 @@ struct htt_tx_selfgen_cmn_stats_tlv { +@@ -672,6 +753,13 @@ struct htt_tx_selfgen_cmn_stats_tlv { u32 delayed_bar_5; /* MU user 5 */ u32 delayed_bar_6; /* MU user 6 */ u32 delayed_bar_7; /* MU user 7 */ @@ -1596,7 +1628,7 @@ }; struct htt_tx_selfgen_ac_stats_tlv { -@@ -679,9 +767,16 @@ struct htt_tx_selfgen_ac_stats_tlv { +@@ -680,9 +768,16 @@ struct htt_tx_selfgen_ac_stats_tlv { u32 ac_su_ndp; u32 ac_mu_mimo_ndpa; u32 ac_mu_mimo_ndp; @@ -1616,7 +1648,7 @@ }; struct htt_tx_selfgen_ax_stats_tlv { -@@ -690,18 +785,30 @@ struct htt_tx_selfgen_ax_stats_tlv { +@@ -691,18 +786,30 @@ struct htt_tx_selfgen_ax_stats_tlv { u32 ax_su_ndp; u32 ax_mu_mimo_ndpa; u32 ax_mu_mimo_ndp; @@ -1654,7 +1686,7 @@ }; struct htt_tx_selfgen_ac_err_stats_tlv { -@@ -713,6 +820,13 @@ struct htt_tx_selfgen_ac_err_stats_tlv { +@@ -714,6 +821,13 @@ struct htt_tx_selfgen_ac_err_stats_tlv { u32 ac_mu_mimo_brp1_err; u32 ac_mu_mimo_brp2_err; u32 ac_mu_mimo_brp3_err; @@ -1668,7 +1700,7 @@ }; struct htt_tx_selfgen_ax_err_stats_tlv { -@@ -721,18 +835,31 @@ struct htt_tx_selfgen_ax_err_stats_tlv { +@@ -722,18 +836,31 @@ struct htt_tx_selfgen_ax_err_stats_tlv { u32 ax_su_ndpa_err; u32 ax_mu_mimo_ndpa_err; u32 ax_mu_mimo_ndp_err; @@ -1707,7 +1739,7 @@ }; /* == TX MU STATS == */ -@@ -887,6 +1014,14 @@ struct htt_tx_pdev_stats_sched_per_txq_t +@@ -889,6 +1016,14 @@ struct htt_tx_pdev_stats_sched_per_txq_t u32 num_tqm_sched_algo_trigger; u32 notify_sched; u32 dur_based_sendn_term; @@ -1722,7 +1754,7 @@ }; struct htt_stats_tx_sched_cmn_tlv { -@@ -976,6 +1111,11 @@ struct htt_tx_tqm_cmn_stats_tlv { +@@ -978,6 +1113,11 @@ struct htt_tx_tqm_cmn_stats_tlv { u32 q_not_empty; u32 drop_notification; u32 desc_threshold; @@ -1734,7 +1766,7 @@ }; struct htt_tx_tqm_error_stats_tlv { -@@ -983,6 +1123,24 @@ struct htt_tx_tqm_error_stats_tlv { +@@ -985,6 +1125,24 @@ struct htt_tx_tqm_error_stats_tlv { u32 q_empty_failure; u32 q_not_empty_failure; u32 add_msdu_failure; @@ -1759,7 +1791,7 @@ }; /* == TQM CMDQ stats == */ -@@ -1013,6 +1171,11 @@ struct htt_tx_de_eapol_packets_stats_tlv +@@ -1015,6 +1173,11 @@ struct htt_tx_de_eapol_packets_stats_tlv u32 m4_packets; u32 g1_packets; u32 g2_packets; @@ -1771,7 +1803,7 @@ }; struct htt_tx_de_classify_failed_stats_tlv { -@@ -1029,6 +1192,12 @@ struct htt_tx_de_classify_failed_stats_t +@@ -1031,6 +1194,12 @@ struct htt_tx_de_classify_failed_stats_t u32 fse_tid_override; u32 ipv6_jumbogram_zero_length; u32 qos_to_non_qos_in_prog; @@ -1784,7 +1816,7 @@ }; struct htt_tx_de_classify_stats_tlv { -@@ -1128,6 +1297,9 @@ struct htt_tx_de_cmn_stats_tlv { +@@ -1130,6 +1299,9 @@ struct htt_tx_de_cmn_stats_tlv { u32 tcl_res_invalid_addrx; u32 wbm2fw_entry_count; u32 invalid_pdev; @@ -1794,7 +1826,7 @@ }; /* == RING-IF STATS == */ -@@ -1237,6 +1409,8 @@ struct htt_sring_cmn_tlv { +@@ -1239,6 +1411,8 @@ struct htt_sring_cmn_tlv { /* == PDEV TX RATE CTRL STATS == */ #define HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS 12 @@ -1803,7 +1835,7 @@ #define HTT_TX_PDEV_STATS_NUM_GI_COUNTERS 4 #define HTT_TX_PDEV_STATS_NUM_DCM_COUNTERS 5 #define HTT_TX_PDEV_STATS_NUM_BW_COUNTERS 4 -@@ -1245,11 +1419,21 @@ struct htt_sring_cmn_tlv { +@@ -1247,11 +1421,21 @@ struct htt_sring_cmn_tlv { #define HTT_TX_PDEV_STATS_NUM_LEGACY_CCK_STATS 4 #define HTT_TX_PDEV_STATS_NUM_LEGACY_OFDM_STATS 8 #define HTT_TX_PDEV_STATS_NUM_LTF 4 @@ -1825,7 +1857,7 @@ struct htt_tx_pdev_rate_stats_tlv { u32 mac_id__word; u32 tx_ldpc; -@@ -1323,24 +1507,51 @@ struct htt_tx_pdev_rate_stats_tlv { +@@ -1325,25 +1509,52 @@ struct htt_tx_pdev_rate_stats_tlv { [HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS]; u32 ofdma_tx_gi[HTT_TX_PDEV_STATS_NUM_GI_COUNTERS] [HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS]; @@ -1856,18 +1888,19 @@ -#define HTT_RX_PDEV_STATS_NUM_LEGACY_CCK_STATS 4 -#define HTT_RX_PDEV_STATS_NUM_LEGACY_OFDM_STATS 8 -#define HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS 12 --#define HTT_RX_PDEV_STATS_NUM_EMCS_COUNTERS 2 +-#define HTT_RX_PDEV_STATS_NUM_EMCS_COUNTERS 2 -#define HTT_RX_PDEV_STATS_NUM_GI_COUNTERS 4 -#define HTT_RX_PDEV_STATS_NUM_DCM_COUNTERS 5 -#define HTT_RX_PDEV_STATS_NUM_BW_COUNTERS 4 -#define HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS 8 --#define HTT_RX_PDEV_STATS_ULNUM_SPATIAL_STREAMS 8 +-#define HTT_RX_PDEV_STATS_ULNUM_SPATIAL_STREAMS 8 -#define HTT_RX_PDEV_STATS_NUM_PREAMBLE_TYPES HTT_STATS_PREAM_COUNT -#define HTT_RX_PDEV_MAX_OFDMA_NUM_USER 8 --#define HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER 8 +-#define HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER 8 -#define HTT_RX_PDEV_STATS_RXEVM_MAX_PILOTS_PER_NSS 16 -#define HTT_RX_PDEV_STATS_NUM_RU_SIZE_160MHZ_CNTRS 7 -#define HTT_RX_PDEV_STATS_NUM_RU_SIZE_COUNTERS 6 +-#define HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER 8 +#define HTT_RX_PDEV_STATS_NUM_LEGACY_CCK_STATS 4 +#define HTT_RX_PDEV_STATS_NUM_LEGACY_OFDM_STATS 8 +#define HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS 12 @@ -1889,25 +1922,11 @@ +#define HTT_RX_PDEV_STATS_NUM_RU_SIZE_160MHZ_CNTRS 7 +#define HTT_RX_PDEV_STATS_NUM_RU_SIZE_COUNTERS 6 +#define HTT_RX_PDEV_STATS_NUM_REDUCED_CHAN_TYPES 2 ++ struct htt_rx_pdev_rate_stats_tlv { u32 mac_id__word; -@@ -1428,10 +1639,10 @@ struct htt_rx_pdev_rate_stats_tlv { - u32 rx_11ax_dl_ofdma_mcs[HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS]; - u32 rx_11ax_dl_ofdma_ru[HTT_RX_PDEV_STATS_NUM_RU_SIZE_COUNTERS]; - -- u32 rx_ulmumimo_non_data_ppdu[HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER]; /* ppdu level */ -- u32 rx_ulmumimo_data_ppdu[HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER]; /* ppdu level */ -- u32 rx_ulmumimo_mpdu_ok[HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER]; /* mpdu level */ -- u32 rx_ulmumimo_mpdu_fail[HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER]; /* mpdu level */ -+ u32 rx_ulmumimo_non_data_ppdu[HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER]; -+ u32 rx_ulmumimo_data_ppdu[HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER]; -+ u32 rx_ulmumimo_mpdu_ok[HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER]; -+ u32 rx_ulmumimo_mpdu_fail[HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER]; - u32 rx_ulofdma_non_data_nusers[HTT_RX_PDEV_MAX_OFDMA_NUM_USER]; - u32 rx_ulofdma_data_nusers[HTT_RX_PDEV_MAX_OFDMA_NUM_USER]; - }; -@@ -1856,6 +2067,8 @@ struct htt_rx_pdev_ul_ofdma_user_stats_t +@@ -1859,6 +2070,8 @@ struct htt_rx_pdev_ul_ofdma_user_stats_t u32 rx_ulofdma_data_nusers; }; @@ -1916,7 +1935,7 @@ struct htt_rx_pdev_ul_trigger_stats_tlv { u32 mac_id__word; u32 rx_11ax_ul_ofdma; -@@ -1868,9 +2081,13 @@ struct htt_rx_pdev_ul_trigger_stats_tlv +@@ -1871,9 +2084,13 @@ struct htt_rx_pdev_ul_trigger_stats_tlv u32 ul_ofdma_rx_ldpc; u32 rx_ulofdma_data_ru_size_ppdu[HTT_RX_PDEV_STATS_NUM_RU_SIZE_160MHZ_CNTRS]; u32 rx_ulofdma_non_data_ru_size_ppdu[HTT_RX_PDEV_STATS_NUM_RU_SIZE_160MHZ_CNTRS]; @@ -1933,7 +1952,7 @@ }; struct htt_rx_pdev_ul_mumimo_trig_stats_tlv { -@@ -1878,14 +2095,24 @@ struct htt_rx_pdev_ul_mumimo_trig_stats_ +@@ -1881,14 +2098,24 @@ struct htt_rx_pdev_ul_mumimo_trig_stats_ u32 rx_11ax_ul_mumimo; u32 ul_mumimo_rx_mcs[HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS]; u32 ul_mumimo_rx_gi[HTT_RX_PDEV_STATS_NUM_GI_COUNTERS] @@ -1963,7 +1982,7 @@ }; struct htt_rx_pdev_ul_mimo_user_stats_tlv { -@@ -1918,7 +2145,8 @@ struct htt_rx_fse_stats_tlv { +@@ -1921,7 +2148,8 @@ struct htt_rx_fse_stats_tlv { #define HTT_TX_TXBF_RATE_STATS_NUM_MCS_COUNTERS 14 #define HTT_TX_TXBF_RATE_STATS_NUM_BW_COUNTERS 5 @@ -1973,7 +1992,7 @@ struct htt_pdev_txrate_txbf_stats_tlv { /* SU TxBF TX MCS stats */ -@@ -1939,6 +2167,13 @@ struct htt_pdev_txrate_txbf_stats_tlv { +@@ -1942,6 +2170,13 @@ struct htt_pdev_txrate_txbf_stats_tlv { u32 tx_su_ibf_bw[HTT_TX_TXBF_RATE_STATS_NUM_BW_COUNTERS]; /* Open loop TX BW stats */ u32 tx_su_ol_bw[HTT_TX_TXBF_RATE_STATS_NUM_BW_COUNTERS]; @@ -1987,7 +2006,7 @@ }; struct htt_txbf_ofdma_ndpa_stats_tlv { -@@ -2054,9 +2289,7 @@ struct htt_phy_counters_tlv { +@@ -2057,9 +2292,7 @@ struct htt_phy_counters_tlv { }; struct htt_phy_stats_tlv { @@ -1997,7 +2016,7 @@ /* number of false radars detected */ u32 false_radar_cnt; /* number of channel switches happened due to radar detection */ -@@ -2069,6 +2302,7 @@ struct htt_phy_stats_tlv { +@@ -2072,6 +2305,7 @@ struct htt_phy_stats_tlv { s32 ani_level; /* running time in minutes since FW boot */ u32 fw_run_time; @@ -2005,7 +2024,7 @@ }; struct htt_phy_reset_counters_tlv { -@@ -2108,6 +2342,8 @@ struct htt_phy_reset_stats_tlv { +@@ -2111,6 +2345,8 @@ struct htt_phy_reset_stats_tlv { u32 phy_dyn_pri_chan; u32 cca_thresh; u32 dyn_cca_status; @@ -2014,7 +2033,7 @@ }; struct htt_peer_ctrl_path_txrx_stats_tlv { -@@ -2120,6 +2356,45 @@ struct htt_peer_ctrl_path_txrx_stats_tlv +@@ -2123,6 +2359,45 @@ struct htt_peer_ctrl_path_txrx_stats_tlv u32 peer_rx_mgmt_subtype[ATH11K_STATS_MGMT_FRM_TYPE_MAX]; }; @@ -2062,7 +2081,7 @@ void ath11k_debugfs_htt_stats_init(struct ath11k *ar); --- a/drivers/net/wireless/ath/ath11k/dp.h +++ b/drivers/net/wireless/ath/ath11k/dp.h -@@ -1797,12 +1797,13 @@ struct htt_ext_stats_cfg_cmd { +@@ -1737,12 +1737,13 @@ struct htt_ext_stats_cfg_cmd { * 4 bit htt_tx_tid_stats_tlv/htt_tx_tid_stats_v1_tlv * 5 bit htt_rx_tid_stats_tlv * 6 bit htt_msdu_flow_stats_tlv diff --git a/feeds/ipq95xx/mac80211/patches/qca/326-ath11k-Add-support-to-bit-error-rate.patch b/feeds/ipq95xx/mac80211/patches/qca/326-ath11k-Add-support-to-bit-error-rate.patch index 28aab369b..1faf3b9d9 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/326-ath11k-Add-support-to-bit-error-rate.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/326-ath11k-Add-support-to-bit-error-rate.patch @@ -173,9 +173,9 @@ index a5f05ae..535f249 100644 ewma_sta_per_add(&arsta->per, 1); + ewma_sta_ber_init(&arsta->ber); + ewma_sta_ber_add(&arsta->ber, 1); - return 0; - - free_tx_stats: + ewma_avg_rssi_init(&arsta->avg_rssi); + return 0; + -- 2.7.4 diff --git a/feeds/ipq95xx/mac80211/patches/qca/326-ath11k-add-smart-antenna-APIs.patch b/feeds/ipq95xx/mac80211/patches/qca/326-ath11k-add-smart-antenna-APIs.patch index 13aeac4b0..a1d3242be 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/326-ath11k-add-smart-antenna-APIs.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/326-ath11k-add-smart-antenna-APIs.patch @@ -26,7 +26,7 @@ Signed-off-by: Maharaja Kennadyrajan --- a/drivers/net/wireless/ath/ath11k/Kconfig +++ b/drivers/net/wireless/ath/ath11k/Kconfig -@@ -94,3 +94,10 @@ config ATH11K_CFR +@@ -95,3 +95,10 @@ config ATH11K_CFR Enable ath11k cfr dump support Say Y to enable access to collect cfr data dump via debugfs. @@ -39,17 +39,17 @@ Signed-off-by: Maharaja Kennadyrajan + This option enables smart antenna algorithm. --- a/drivers/net/wireless/ath/ath11k/Makefile +++ b/drivers/net/wireless/ath/ath11k/Makefile -@@ -29,6 +29,7 @@ ath11k-$(CPTCFG_ATH11K_SPECTRAL) += spec +@@ -30,6 +30,7 @@ ath11k-$(CONFIG_PM) += wow.o ath11k-$(CPTCFG_ATH11K_PKTLOG) += pktlog.o ath11k-$(CPTCFG_ATH11K_NSS_SUPPORT) += nss.o ath11k-$(CPTCFG_ATH11K_CFR) += cfr.o +ath11k-$(CPTCFG_ATH11K_SMART_ANT_ALG) += smart_ant_api.o obj-$(CPTCFG_ATH11K_AHB) += ath11k_ahb.o - ath11k_ahb-y += ahb.o pci_cmn.o + ath11k_ahb-y += ahb.o --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -67,6 +67,12 @@ module_param(ath11k_caldata_bin_path, ch +@@ -63,6 +63,12 @@ module_param(ath11k_caldata_bin_path, ch MODULE_PARM_DESC(ath11k_caldata_bin_path, "Caldata bin path for loading"); @@ -64,7 +64,7 @@ Signed-off-by: Maharaja Kennadyrajan --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -28,6 +28,7 @@ +@@ -34,6 +34,7 @@ #include "rx_desc.h" #include "nss.h" #include "cfr.h" @@ -72,7 +72,7 @@ Signed-off-by: Maharaja Kennadyrajan #ifdef CONFIG_QCOM_QMI_HELPERS extern wait_queue_head_t ath11k_ssr_dump_wq; -@@ -521,6 +522,7 @@ struct ath11k_sta { +@@ -615,6 +616,7 @@ struct ath11k_sta { s8 chain_signal[IEEE80211_MAX_CHAINS]; struct ath11k_htt_tx_stats *tx_stats; struct ath11k_rx_peer_stats *rx_stats; @@ -80,16 +80,16 @@ Signed-off-by: Maharaja Kennadyrajan #ifdef CPTCFG_MAC80211_DEBUGFS /* protected by conf_mutex */ -@@ -840,6 +842,8 @@ struct ath11k { +@@ -940,6 +942,8 @@ struct ath11k { u8 cfr_enabled; bool ani_enabled; enum wmi_phy_mode cfr_phymode; + struct ath11k_smart_ant_info smart_ant_info; + u32 rx_antenna; u32 vdev_id_11d_scan; - struct completion finish_11d_scan; - struct completion finish_11d_ch_list; -@@ -1310,6 +1314,24 @@ enum ath11k_fw_recovery_option { + struct completion completed_11d_scan; + enum ath11k_11d_state state_11d; +@@ -1425,6 +1429,24 @@ enum ath11k_fw_recovery_option { ATH11K_FW_RECOVERY_ENABLE_SSR_ONLY, }; @@ -117,16 +117,16 @@ Signed-off-by: Maharaja Kennadyrajan --- a/drivers/net/wireless/ath/ath11k/debug.h +++ b/drivers/net/wireless/ath/ath11k/debug.h @@ -29,6 +29,7 @@ enum ath11k_debug_mask { - ATH11K_DBG_CFR = 0x00008000, - ATH11K_DBG_CFR_DUMP = 0x00010000, - ATH11K_DBG_PEER = 0x00020000, + ATH11K_DBG_CFR = 0x00008000, + ATH11K_DBG_CFR_DUMP = 0x00010000, + ATH11K_DBG_PEER = 0x00020000, + ATH11K_DBG_SMART_ANT = 0x00040000, - ATH11K_DBG_TEST = 0x00080000, + ATH11K_DBG_TEST = 0x00080000, ATH11K_DBG_ANY = 0xffffffff, }; --- a/drivers/net/wireless/ath/ath11k/hw.c +++ b/drivers/net/wireless/ath/ath11k/hw.c -@@ -214,6 +214,7 @@ static void ath11k_init_wmi_config_ipq80 +@@ -215,6 +215,7 @@ static void ath11k_init_wmi_config_ipq80 config->twt_ap_pdev_count = ab->num_radios; config->twt_ap_sta_count = 1000; config->flag1 |= WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64; @@ -136,7 +136,7 @@ Signed-off-by: Maharaja Kennadyrajan static int ath11k_hw_mac_id_to_pdev_id_ipq8074(struct ath11k_hw_params *hw, --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -409,7 +409,7 @@ int ath11k_mac_hw_ratecode_to_legacy_rat +@@ -416,7 +416,7 @@ int ath11k_mac_hw_ratecode_to_legacy_rat return -EINVAL; } @@ -145,7 +145,7 @@ Signed-off-by: Maharaja Kennadyrajan { int num_chains = 0; -@@ -5506,6 +5506,13 @@ static int ath11k_mac_op_sta_state(struc +@@ -5517,6 +5517,13 @@ static int ath11k_mac_op_sta_state(struc if (ret) ath11k_warn(ar->ab, "Failed to associate station: %pM\n", sta->addr); @@ -159,7 +159,7 @@ Signed-off-by: Maharaja Kennadyrajan } else if (old_state == IEEE80211_STA_ASSOC && new_state == IEEE80211_STA_AUTHORIZED) { spin_lock_bh(&ar->ab->base_lock); -@@ -5575,6 +5582,8 @@ static int ath11k_mac_op_sta_state(struc +@@ -5586,6 +5593,8 @@ static int ath11k_mac_op_sta_state(struc (vif->type == NL80211_IFTYPE_AP || vif->type == NL80211_IFTYPE_MESH_POINT || vif->type == NL80211_IFTYPE_ADHOC)) { @@ -168,16 +168,16 @@ Signed-off-by: Maharaja Kennadyrajan ret = ath11k_station_disassoc(ar, vif, sta); if (ret) ath11k_warn(ar->ab, "Failed to disassociate station: %pM\n", -@@ -8097,6 +8106,8 @@ ath11k_mac_update_vif_chan(struct ath11k - if (!arvif->is_up) +@@ -8100,6 +8109,8 @@ ath11k_mac_update_vif_chan(struct ath11k continue; + } + ath11k_smart_ant_disable(arvif); + ret = ath11k_mac_setup_bcn_tmpl(arvif); if (ret) ath11k_warn(ab, "failed to update bcn tmpl during csa: %d\n", -@@ -8312,6 +8323,21 @@ ath11k_mac_op_assign_vif_chanctx(struct +@@ -8315,6 +8326,21 @@ ath11k_mac_op_assign_vif_chanctx(struct arvif->is_started = true; @@ -201,7 +201,7 @@ Signed-off-by: Maharaja Kennadyrajan ret = ath11k_mac_monitor_start(ar); --- a/drivers/net/wireless/ath/ath11k/mac.h +++ b/drivers/net/wireless/ath/ath11k/mac.h -@@ -141,6 +141,7 @@ int ath11k_mac_register(struct ath11k_ba +@@ -142,6 +142,7 @@ int ath11k_mac_register(struct ath11k_ba int ath11k_mac_allocate(struct ath11k_base *ab); int ath11k_mac_hw_ratecode_to_legacy_rate(u8 hw_rc, u8 preamble, u8 *rateidx, u16 *rate); @@ -301,16 +301,16 @@ Signed-off-by: Maharaja Kennadyrajan +#endif --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -155,6 +155,8 @@ static const struct wmi_tlv_policy wmi_t - = { .min_len = sizeof(struct wmi_pdev_update_muedca_event) }, - [WMI_TAG_WDS_ADDR_EVENT] - = { .min_len = sizeof(struct wmi_wds_addr_event) }, +@@ -154,6 +154,8 @@ static const struct wmi_tlv_policy wmi_t + = { .min_len = sizeof(struct wmi_pdev_update_muedca_event) }, + [WMI_TAG_WDS_ADDR_EVENT] + = { .min_len = sizeof(struct wmi_wds_addr_event) }, + [WMI_TAG_PEER_RATECODE_LIST_EVENT] + = { .min_len = sizeof(struct wmi_peer_ratecode_list_fixed_param) }, - [WMI_TAG_11D_NEW_COUNTRY_EVENT] = { - .min_len = sizeof(struct wmi_11d_new_cc_ev) }, - [WMI_TAG_PER_CHAIN_RSSI_STATS] = { -@@ -4517,6 +4519,7 @@ ath11k_wmi_copy_resource_config(struct w + }; + + #define PRIMAP(_hw_mode_) \ +@@ -4556,6 +4558,7 @@ ath11k_wmi_copy_resource_config(struct w wmi_cfg->host_service_flags &= ~(1 << WMI_RSRC_CFG_HOST_SERVICE_FLAG_REG_CC_EXT_SUPPORT_BIT); wmi_cfg->host_service_flags |= tg_cfg->is_reg_cc_ext_event_supported << WMI_RSRC_CFG_HOST_SERVICE_FLAG_REG_CC_EXT_SUPPORT_BIT; @@ -318,7 +318,7 @@ Signed-off-by: Maharaja Kennadyrajan } static int ath11k_init_cmd_send(struct ath11k_pdev_wmi *wmi, -@@ -10127,6 +10130,165 @@ static void ath11k_wmi_parse_cfr_capture +@@ -10064,6 +10067,165 @@ static void ath11k_wmi_parse_cfr_capture "failed to process cfr cpature ret = %d\n", ret); } @@ -484,7 +484,7 @@ Signed-off-by: Maharaja Kennadyrajan static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb) { struct wmi_cmd_hdr *cmd_hdr; -@@ -10297,6 +10459,9 @@ static void ath11k_wmi_tlv_op_rx(struct +@@ -10231,6 +10393,9 @@ static void ath11k_wmi_tlv_op_rx(struct case WMI_PDEV_ANI_OFDM_LEVEL_EVENTID: ath11k_wmi_event_ani_ofdm_level(ab, skb); break; @@ -494,9 +494,9 @@ Signed-off-by: Maharaja Kennadyrajan /* TODO: Add remaining events */ default: ath11k_dbg(ab, ATH11K_DBG_WMI, "Unknown eventid: 0x%x\n", id); -@@ -10650,3 +10815,393 @@ int ath11k_wmi_scan_prob_req_oui(struct +@@ -11314,3 +11479,393 @@ int ath11k_wmi_sta_keepalive(struct ath1 - return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_SCAN_PROB_REQ_OUI_CMDID); + return ath11k_wmi_cmd_send(wmi, skb, WMI_STA_KEEPALIVE_CMDID); } + +void @@ -899,11 +899,11 @@ Signed-off-by: Maharaja Kennadyrajan +struct ath11k_smart_ant_node_config_params; +struct ath11k_smart_ant_train_info; struct ath11k_fw_stats; - - #define PSOC_HOST_MAX_NUM_SS (8) -@@ -6664,6 +6668,101 @@ struct wmi_wow_ev_arg { - u32 data_len; - }; + struct ath11k_fw_dbglog; + struct ath11k_vif; +@@ -7051,6 +7055,101 @@ enum wmi_sta_keepalive_method { + #define WMI_STA_KEEPALIVE_INTERVAL_DEFAULT 30 + #define WMI_STA_KEEPALIVE_INTERVAL_DISABLE 0 +/*Smart antenna related defs */ + @@ -1003,7 +1003,7 @@ Signed-off-by: Maharaja Kennadyrajan int ath11k_wmi_cmd_send(struct ath11k_pdev_wmi *wmi, struct sk_buff *skb, u32 cmd_id); struct sk_buff *ath11k_wmi_alloc_skb(struct ath11k_wmi_base *wmi_sc, u32 len); -@@ -6848,4 +6947,22 @@ int ath11k_wmi_peer_set_cfr_capture_conf +@@ -7258,4 +7357,22 @@ int ath11k_wmi_peer_set_cfr_capture_conf u32 vdev_id, const u8 *mac, struct wmi_peer_cfr_capture_conf_arg *arg); int ath11k_wmi_pdev_get_ani_level(struct ath11k *ar, u32 param_id, u8 pdev_id); @@ -1724,7 +1724,7 @@ Signed-off-by: Maharaja Kennadyrajan +#endif /* _SMART_ANT_ALG_ */ --- a/drivers/net/wireless/ath/ath11k/dp.h +++ b/drivers/net/wireless/ath/ath11k/dp.h -@@ -1482,6 +1482,9 @@ enum htt_ppdu_stats_usr_compln_status { +@@ -1475,6 +1475,9 @@ enum htt_ppdu_stats_usr_compln_status { #define HTT_USR_CMPLTN_SHORT_RETRY(_val) \ FIELD_GET(HTT_PPDU_STATS_USR_CMPLTN_CMN_FLAGS_SHORT_RETRY_M, _val) @@ -1734,7 +1734,7 @@ Signed-off-by: Maharaja Kennadyrajan struct htt_ppdu_stats_usr_cmpltn_cmn { u8 status; u8 tid_num; -@@ -1490,7 +1493,29 @@ struct htt_ppdu_stats_usr_cmpltn_cmn { +@@ -1483,7 +1486,29 @@ struct htt_ppdu_stats_usr_cmpltn_cmn { u32 ack_rssi; u16 mpdu_tried; u16 mpdu_success; @@ -1765,7 +1765,7 @@ Signed-off-by: Maharaja Kennadyrajan } __packed; #define HTT_PPDU_STATS_ACK_BA_INFO_NUM_MPDU_M GENMASK(8, 0) -@@ -1512,7 +1537,6 @@ struct htt_ppdu_stats_usr_cmpltn_ack_ba_ +@@ -1505,7 +1530,6 @@ struct htt_ppdu_stats_usr_cmpltn_ack_ba_ #define HTT_PPDU_STATS_USR_CMN_FLAG_DELAYBA BIT(14) #define HTT_PPDU_STATS_USR_CMN_HDR_SW_PEERID GENMASK(31, 16) #define HTT_PPDU_STATS_USR_CMN_CTL_FRM_CTRL GENMASK(15, 0) @@ -1783,7 +1783,7 @@ Signed-off-by: Maharaja Kennadyrajan #include "debugfs_htt_stats.h" #include "debugfs_sta.h" #include "hal_desc.h" -@@ -1404,6 +1405,7 @@ static int ath11k_htt_tlv_ppdu_stats_par +@@ -1405,6 +1406,7 @@ static int ath11k_htt_tlv_ppdu_stats_par memcpy((void *)&user_stats->cmpltn_cmn, ptr, sizeof(struct htt_ppdu_stats_usr_cmpltn_cmn)); user_stats->tlv_flags |= BIT(tag); @@ -1791,7 +1791,7 @@ Signed-off-by: Maharaja Kennadyrajan break; case HTT_PPDU_STATS_TAG_USR_COMPLTN_ACK_BA_STATUS: if (len < -@@ -6245,6 +6247,8 @@ int ath11k_dp_rx_process_mon_status(stru +@@ -6255,6 +6257,8 @@ int ath11k_dp_rx_process_mon_status(stru log_type, rx_buf_sz); } @@ -1802,7 +1802,7 @@ Signed-off-by: Maharaja Kennadyrajan rcu_read_unlock(); --- a/drivers/net/wireless/ath/ath11k/hal_rx.c +++ b/drivers/net/wireless/ath/ath11k/hal_rx.c -@@ -1568,9 +1568,12 @@ ath11k_hal_rx_parse_mon_status_tlv(struc +@@ -1574,9 +1574,12 @@ ath11k_hal_rx_parse_mon_status_tlv(struc case HAL_RXPCU_PPDU_END_INFO: { struct hal_rx_ppdu_end_duration *ppdu_rx_duration = (struct hal_rx_ppdu_end_duration *)tlv_data; @@ -1813,12 +1813,12 @@ Signed-off-by: Maharaja Kennadyrajan FIELD_GET(HAL_RX_PPDU_END_DURATION, - __le32_to_cpu(ppdu_rx_duration->info0)); + __le32_to_cpu(ppdu_rx_duration->info1)); - ppdu_info->tsft =ppdu_rx_duration->rsvd0[1]; - ppdu_info->tsft = (ppdu_info->tsft << 32) | ppdu_rx_duration->rsvd0[0]; - break; + ppdu_info->tsft = __le32_to_cpu(ppdu_rx_duration->rsvd0[1]); + ppdu_info->tsft = (ppdu_info->tsft << 32) | + __le32_to_cpu(ppdu_rx_duration->rsvd0[0]); --- a/drivers/net/wireless/ath/ath11k/hal_rx.h +++ b/drivers/net/wireless/ath/ath11k/hal_rx.h -@@ -225,6 +225,7 @@ struct hal_rx_mon_ppdu_info { +@@ -224,6 +224,7 @@ struct hal_rx_mon_ppdu_info { struct hal_rx_user_status userstats[HAL_MAX_UL_MU_USERS]; u8 userid; u16 ampdu_id[HAL_MAX_UL_MU_USERS]; @@ -1851,4 +1851,4 @@ Signed-off-by: Maharaja Kennadyrajan +ATH11K_SMART_ANT_ALG= ATH12K= ATH12K_DEBUG= - ATH12K_DEBUGFS= + ATH12K_TRACING= diff --git a/feeds/ipq95xx/mac80211/patches/qca/327-ath11k-add-smart-antenna-debugfs.patch b/feeds/ipq95xx/mac80211/patches/qca/327-ath11k-add-smart-antenna-debugfs.patch index 661119608..647c5bda3 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/327-ath11k-add-smart-antenna-debugfs.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/327-ath11k-add-smart-antenna-debugfs.patch @@ -16,7 +16,7 @@ Signed-off-by: Maharaja Kennadyrajan --- a/drivers/net/wireless/ath/ath11k/Makefile +++ b/drivers/net/wireless/ath/ath11k/Makefile @@ -20,7 +20,7 @@ ath11k-y += core.o \ - wow.o \ + pcic.o \ vendor.o -ath11k-$(CPTCFG_ATH11K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o debug_nss.o @@ -26,7 +26,7 @@ Signed-off-by: Maharaja Kennadyrajan ath11k-$(CONFIG_THERMAL) += thermal.o --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -592,6 +592,7 @@ struct ath11k_debug { +@@ -740,6 +740,7 @@ struct ath11k_debug { u32 wmi_ctrl_path_stats_tagid; struct ath11k_db_module_debug *module_debug[WMI_DIRECT_BUF_MAX]; bool disable_dynamic_bw; @@ -345,7 +345,7 @@ Signed-off-by: Maharaja Kennadyrajan + return -EINVAL; + } + -+ for (i = 0; i <= sta->bandwidth; i++) ++ for (i = 0; i <= sta->deflink.bandwidth; i++) + rate_mask |= (0xff << (8 * i)); + + if ((params.rate_array[0] & rate_mask) != params.rate_array[0]) { @@ -404,7 +404,7 @@ Signed-off-by: Maharaja Kennadyrajan +} --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -4327,6 +4327,7 @@ int ath11k_debugfs_register(struct ath11 +@@ -4636,6 +4636,7 @@ int ath11k_debugfs_register(struct ath11 ath11k_debugfs_fw_stats_init(ar); ath11k_init_pktlog(ar); @@ -414,21 +414,21 @@ Signed-off-by: Maharaja Kennadyrajan init_completion(&ab->ani_cck_event); --- a/drivers/net/wireless/ath/ath11k/debugfs.h +++ b/drivers/net/wireless/ath/ath11k/debugfs.h -@@ -239,6 +239,7 @@ void ath11k_debugfs_unregister(struct at +@@ -394,6 +394,7 @@ void ath11k_debugfs_unregister(struct at void ath11k_debugfs_fw_stats_process(struct ath11k_base *ab, struct sk_buff *skb); void ath11k_debugfs_fw_stats_init(struct ath11k *ar); +void ath11k_smart_ant_debugfs_init(struct ath11k *ar); ssize_t ath11k_debugfs_dump_soc_ring_bp_stats(struct ath11k_base *ab, - char *buf, int size); + char *buf, int size); void ath11k_dbring_add_debug_entry(struct ath11k *ar, -@@ -375,6 +376,9 @@ ath11k_dbring_add_debug_entry(struct ath - struct hal_srng *srng) +@@ -555,6 +556,9 @@ ath11k_debugfs_add_dbring_entry(struct a + struct hal_srng *srng) { } +static inline void ath11k_smart_ant_debugfs_init(struct ath11k *ar) +{ +} - #endif /* CPTCFG_MAC80211_DEBUGFS*/ + #endif /* CPTCFG_ATH11K_DEBUGFS*/ #ifdef CPTCFG_ATH11K_PKTLOG diff --git a/feeds/ipq95xx/mac80211/patches/qca/328-ath11k-fix-workqueue-not-getting-destroyed-after-rmmod.patch b/feeds/ipq95xx/mac80211/patches/qca/328-ath11k-fix-workqueue-not-getting-destroyed-after-rmmod.patch deleted file mode 100644 index e5306856e..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/328-ath11k-fix-workqueue-not-getting-destroyed-after-rmmod.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 856372c2e30917a1603d338992c9bc3c4fe2e6d0 Mon Sep 17 00:00:00 2001 -From: Aditya Kumar Singh -Date: Mon, 13 Sep 2021 09:32:32 +0530 -Subject: [PATCH] ath11k: fix workqueue not getting destroyed after rmmod - -This change is to destroy the workqueues after the modules -are removed from kernel. Earlier, the workqueues were -not destroyed and left as it is. - -If workqueues are not destroyed, it could lead to kernel -memory scarcity in a longer run. This could affect self and -other drivers workability as well. - -Signed-off-by: Aditya Kumar Singh ---- - drivers/net/wireless/ath/ath11k/core.c | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/drivers/net/wireless/ath/ath11k/core.c -+++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -2011,6 +2011,9 @@ EXPORT_SYMBOL(ath11k_core_deinit); - - void ath11k_core_free(struct ath11k_base *ab) - { -+ flush_workqueue(ab->workqueue_aux); -+ destroy_workqueue(ab->workqueue_aux); -+ - flush_workqueue(ab->workqueue); - destroy_workqueue(ab->workqueue); - diff --git a/feeds/ipq95xx/mac80211/patches/qca/329-ath11k-add-ftm-responder-support.patch b/feeds/ipq95xx/mac80211/patches/qca/329-ath11k-add-ftm-responder-support.patch index 6015366ce..60ef9b33c 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/329-ath11k-add-ftm-responder-support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/329-ath11k-add-ftm-responder-support.patch @@ -19,22 +19,23 @@ Signed-off-by: Sowmiya Sree Elavalagan --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -281,6 +281,7 @@ struct ath11k_vif { +@@ -405,6 +405,7 @@ struct ath11k_vif { bool is_started; bool is_up; + bool ftm_responder; bool spectral_enabled; + bool ps; u32 aid; - u8 bssid[ETH_ALEN]; --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -3293,10 +3293,23 @@ static void ath11k_mac_op_bss_info_chang +@@ -3504,11 +3504,24 @@ static void ath11k_mac_op_bss_info_chang u16 bitrate; int ret = 0; u8 rateidx; - u32 rate; + u32 rate, param; + u32 ipv4_cnt; mutex_lock(&ar->conf_mutex); @@ -54,7 +55,7 @@ Signed-off-by: Sowmiya Sree Elavalagan if (changed & BSS_CHANGED_BEACON_INT) { arvif->beacon_interval = info->beacon_int; -@@ -9442,6 +9455,9 @@ static int __ath11k_mac_register(struct +@@ -10465,6 +10478,9 @@ static int __ath11k_mac_register(struct NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP); } @@ -66,7 +67,7 @@ Signed-off-by: Sowmiya Sree Elavalagan --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -1099,6 +1099,7 @@ enum wmi_tlv_vdev_param { +@@ -1098,6 +1098,7 @@ enum wmi_tlv_vdev_param { WMI_VDEV_PARAM_ENABLE_BCAST_PROBE_RESPONSE, WMI_VDEV_PARAM_FILS_MAX_CHANNEL_GUARD_TIME, WMI_VDEV_PARAM_HE_LTF = 0x74, diff --git a/feeds/ipq95xx/mac80211/patches/qca/330-ath11k-sync-wds_ast_entry-updates.patch b/feeds/ipq95xx/mac80211/patches/qca/330-ath11k-sync-wds_ast_entry-updates.patch index c7b3b0d31..9b034adf1 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/330-ath11k-sync-wds_ast_entry-updates.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/330-ath11k-sync-wds_ast_entry-updates.patch @@ -46,7 +46,7 @@ Signed-off-by: Rameshkumar Sundaram --- a/drivers/net/wireless/ath/ath11k/ahb.c +++ b/drivers/net/wireless/ath/ath11k/ahb.c -@@ -994,6 +994,7 @@ static int ath11k_ahb_remove(struct plat +@@ -1319,6 +1319,7 @@ static int ath11k_ahb_remove(struct plat set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags); cancel_work_sync(&ab->restart_work); @@ -56,18 +56,18 @@ Signed-off-by: Rameshkumar Sundaram qmi_fail: --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -2041,6 +2041,7 @@ struct ath11k_base *ath11k_core_alloc(st - goto err_free_wq; +@@ -2386,6 +2386,7 @@ struct ath11k_base *ath11k_core_alloc(st mutex_init(&ab->core_lock); + mutex_init(&ab->tbl_mtx_lock); + mutex_init(&ab->base_ast_lock); spin_lock_init(&ab->base_lock); - init_completion(&ab->reset_complete); mutex_init(&ab->vdev_id_11d_lock); -@@ -2056,6 +2057,8 @@ struct ath11k_base *ath11k_core_alloc(st - INIT_WORK(&ab->reset_work, ath11k_core_reset); + init_completion(&ab->reset_complete); +@@ -2402,6 +2403,8 @@ struct ath11k_base *ath11k_core_alloc(st + INIT_WORK(&ab->restart_work, ath11k_core_restart); INIT_WORK(&ab->update_11d_work, ath11k_update_11d); - INIT_WORK(&ab->rfkill_work, ath11k_rfkill_work); + INIT_WORK(&ab->reset_work, ath11k_core_reset); + INIT_WORK(&ab->wmi_ast_work, ath11k_peer_ast_wds_wmi_wk); + INIT_LIST_HEAD(&ab->wmi_ast_list); timer_setup(&ab->rx_replenish_retry, ath11k_ce_rx_replenish_retry, 0); @@ -75,7 +75,7 @@ Signed-off-by: Rameshkumar Sundaram init_completion(&ab->wow.wakeup_completed); --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -29,6 +29,7 @@ +@@ -35,6 +35,7 @@ #include "nss.h" #include "cfr.h" #include "smart_ant.h" @@ -83,7 +83,7 @@ Signed-off-by: Rameshkumar Sundaram #ifdef CONFIG_QCOM_QMI_HELPERS extern wait_queue_head_t ath11k_ssr_dump_wq; -@@ -1151,6 +1152,9 @@ struct ath11k_base { +@@ -1279,6 +1280,9 @@ struct ath11k_base { int ani_cck_level; struct completion ani_ofdm_event; struct completion ani_cck_event; @@ -92,10 +92,10 @@ Signed-off-by: Rameshkumar Sundaram + struct list_head wmi_ast_list; /* must be last */ - u8 drv_priv[0] __aligned(sizeof(void *)); + u8 drv_priv[] __aligned(sizeof(void *)); --- a/drivers/net/wireless/ath/ath11k/nss.c +++ b/drivers/net/wireless/ath/ath11k/nss.c -@@ -641,8 +641,9 @@ static void ath11k_nss_wds_type_rx(struc +@@ -647,8 +647,9 @@ static void ath11k_nss_wds_type_rx(struc spin_unlock_bh(&ab->base_lock); } @@ -106,7 +106,7 @@ Signed-off-by: Rameshkumar Sundaram struct ath11k_base *ab = ar->ab; struct ath11k_peer *peer = ar->bss_peer; u8 mac_addr[ETH_ALEN]; -@@ -669,7 +670,7 @@ static void ath11k_nss_mec_handler(struc +@@ -675,7 +676,7 @@ static void ath11k_nss_mec_handler(struc memcpy(mac_addr, mac_addr_h16, ETH_ALEN - 4); memcpy(mac_addr + 2, mac_addr_l32, 4); @@ -115,7 +115,7 @@ Signed-off-by: Rameshkumar Sundaram spin_lock_bh(&ab->base_lock); ath11k_peer_add_ast(ar, peer, mac_addr, ATH11K_AST_TYPE_MEC); -@@ -704,7 +705,7 @@ static void ath11k_nss_vdev_spl_receive_ +@@ -710,7 +711,7 @@ static void ath11k_nss_vdev_spl_receive_ addr4_valid, peer_id); break; case NSS_WIFI_VDEV_WDS_TYPE_MEC: @@ -124,7 +124,7 @@ Signed-off-by: Rameshkumar Sundaram break; default: ath11k_warn(ab, "unsupported wds_type %d\n", wds_type); -@@ -3795,11 +3796,7 @@ int ath11k_nss_add_wds_peer(struct ath11 +@@ -3804,11 +3805,7 @@ int ath11k_nss_add_wds_peer(struct ath11 wds_peer_msg->ast_type = type; wds_peer_msg->peer_id = peer->peer_id; @@ -137,7 +137,7 @@ Signed-off-by: Rameshkumar Sundaram ether_addr_copy(wds_peer_msg->dest_mac, dest_mac); msg_cb = (nss_wifili_msg_callback_t)ath11k_nss_wifili_event_receive; -@@ -3922,7 +3919,7 @@ msg_free: +@@ -3931,7 +3928,7 @@ msg_free: return ret; } @@ -146,7 +146,7 @@ Signed-off-by: Rameshkumar Sundaram u8 *dest_mac) { struct ath11k_base *ab = ar->ab; -@@ -3940,8 +3937,8 @@ int ath11k_nss_del_wds_peer(struct ath11 +@@ -3949,8 +3946,8 @@ int ath11k_nss_del_wds_peer(struct ath11 wds_peer_msg->pdev_id = ar->pdev->pdev_id; wds_peer_msg->ast_type = ATH11K_AST_TYPE_NONE; @@ -159,7 +159,7 @@ Signed-off-by: Rameshkumar Sundaram msg_cb = (nss_wifili_msg_callback_t)ath11k_nss_wifili_event_receive; --- a/drivers/net/wireless/ath/ath11k/nss.h +++ b/drivers/net/wireless/ath/ath11k/nss.h -@@ -290,8 +290,8 @@ int ath11k_nss_update_wds_peer(struct at +@@ -291,8 +291,8 @@ int ath11k_nss_update_wds_peer(struct at u8 *dest_mac); int ath11k_nss_map_wds_peer(struct ath11k *ar, struct ath11k_peer *peer, u8 *dest_mac, enum ath11k_ast_entry_type type); @@ -170,7 +170,7 @@ Signed-off-by: Rameshkumar Sundaram int ath11k_nss_ext_vdev_cfg_wds_peer(struct ath11k_vif *arvif, u8 *wds_addr, u32 wds_peer_id); int ath11k_nss_ext_vdev_wds_4addr_allow(struct ath11k_vif *arvif, -@@ -403,8 +403,8 @@ static inline int ath11k_nss_map_wds_pee +@@ -404,8 +404,8 @@ static inline int ath11k_nss_map_wds_pee return 0; } @@ -183,17 +183,17 @@ Signed-off-by: Rameshkumar Sundaram } --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c -@@ -1072,6 +1072,7 @@ static void ath11k_pci_remove(struct pci +@@ -957,6 +957,7 @@ static void ath11k_pci_remove(struct pci + } set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags); - cancel_work_sync(&ab->reset_work); + cancel_work_sync(&ab->wmi_ast_work); ath11k_core_deinit(ab); --- a/drivers/net/wireless/ath/ath11k/peer.c +++ b/drivers/net/wireless/ath/ath11k/peer.c -@@ -142,49 +142,68 @@ struct ath11k_ast_entry *ath11k_peer_ast +@@ -160,49 +160,68 @@ struct ath11k_ast_entry *ath11k_peer_ast void ath11k_peer_ast_wds_wmi_wk(struct work_struct *wk) { @@ -217,10 +217,6 @@ Signed-off-by: Rameshkumar Sundaram - peer = ast_entry->peer; + mutex_lock(&ab->base_ast_lock); + spin_lock_bh(&ab->base_lock); -+ -+ while ((entry = list_first_entry_or_null(&ab->wmi_ast_list, -+ struct ath11k_ast_entry, wmi_list))) { -+ list_del_init(&entry->wmi_list); - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "ath11k_peer_ast_wds_wmi_wk action %d ast_entry %pM next_node %pM vdev %d\n", - ast_entry->action, ast_entry->addr, ast_entry->next_node_mac, @@ -239,6 +235,10 @@ Signed-off-by: Rameshkumar Sundaram - if (peer) - ath11k_nss_del_wds_peer(ar, peer, - ast_entry->addr); ++ while ((entry = list_first_entry_or_null(&ab->wmi_ast_list, ++ struct ath11k_ast_entry, wmi_list))) { ++ list_del_init(&entry->wmi_list); ++ + if (!entry->ar || (entry->peer && entry->peer->delete_in_progress)) { + continue; } @@ -297,7 +297,7 @@ Signed-off-by: Rameshkumar Sundaram } int ath11k_peer_add_ast(struct ath11k *ar, struct ath11k_peer *peer, -@@ -193,6 +212,8 @@ int ath11k_peer_add_ast(struct ath11k *a +@@ -211,6 +230,8 @@ int ath11k_peer_add_ast(struct ath11k *a struct ath11k_ast_entry *ast_entry = NULL; struct ath11k_base *ab = ar->ab; @@ -306,7 +306,7 @@ Signed-off-by: Rameshkumar Sundaram if (ab->num_ast_entries == ab->max_ast_index) { ath11k_warn(ab, "failed to add ast for %pM due to insufficient ast entry resource %d in target\n", mac_addr, ab->max_ast_index); -@@ -208,6 +229,9 @@ int ath11k_peer_add_ast(struct ath11k *a +@@ -226,6 +247,9 @@ int ath11k_peer_add_ast(struct ath11k *a } } @@ -316,7 +316,7 @@ Signed-off-by: Rameshkumar Sundaram ast_entry = kzalloc(sizeof(*ast_entry), GFP_ATOMIC); if (!ast_entry) { ath11k_warn(ab, "failed to alloc ast_entry for %pM\n", -@@ -239,7 +263,7 @@ int ath11k_peer_add_ast(struct ath11k *a +@@ -257,7 +281,7 @@ int ath11k_peer_add_ast(struct ath11k *a } INIT_LIST_HEAD(&ast_entry->ase_list); @@ -325,7 +325,7 @@ Signed-off-by: Rameshkumar Sundaram ast_entry->vdev_id = peer->vdev_id; ast_entry->pdev_idx = peer->pdev_idx; ast_entry->is_mapped = false; -@@ -253,16 +277,12 @@ int ath11k_peer_add_ast(struct ath11k *a +@@ -271,16 +295,12 @@ int ath11k_peer_add_ast(struct ath11k *a ath11k_dbg(ab, ATH11K_DBG_MAC, "ath11k_peer_add_ast peer %pM ast_entry %pM, ast_type %d\n", peer->addr, mac_addr, ast_entry->type); @@ -344,7 +344,7 @@ Signed-off-by: Rameshkumar Sundaram } ab->num_ast_entries++; -@@ -275,6 +295,8 @@ int ath11k_peer_update_ast(struct ath11k +@@ -293,6 +313,8 @@ int ath11k_peer_update_ast(struct ath11k struct ath11k_peer *old_peer = ast_entry->peer; struct ath11k_base *ab = ar->ab; @@ -353,7 +353,7 @@ Signed-off-by: Rameshkumar Sundaram if (!ast_entry->is_mapped) { ath11k_warn(ab, "ath11k_peer_update_ast: ast_entry %pM not mapped yet\n", ast_entry->addr); -@@ -287,6 +309,9 @@ int ath11k_peer_update_ast(struct ath11k +@@ -305,6 +327,9 @@ int ath11k_peer_update_ast(struct ath11k (ast_entry->is_active)) return 0; @@ -363,7 +363,7 @@ Signed-off-by: Rameshkumar Sundaram ast_entry->vdev_id = peer->vdev_id; ast_entry->pdev_idx = peer->pdev_idx; ast_entry->type = ATH11K_AST_TYPE_WDS; -@@ -299,7 +324,14 @@ int ath11k_peer_update_ast(struct ath11k +@@ -317,7 +342,14 @@ int ath11k_peer_update_ast(struct ath11k old_peer->addr, peer->addr, ast_entry->addr); ast_entry->action = ATH11K_WDS_WMI_UPDATE; @@ -379,7 +379,7 @@ Signed-off-by: Rameshkumar Sundaram return 0; } -@@ -345,16 +377,23 @@ void ath11k_peer_del_ast(struct ath11k * +@@ -363,16 +395,23 @@ void ath11k_peer_del_ast(struct ath11k * ath11k_dbg(ab, ATH11K_DBG_MAC, "ath11k_peer_del_ast pdev:%d peer %pM ast_entry %pM\n", ar->pdev->pdev_id, peer->addr, ast_entry->addr); @@ -408,47 +408,53 @@ Signed-off-by: Rameshkumar Sundaram ab->num_ast_entries--; } -@@ -660,7 +699,9 @@ void ath11k_peer_cleanup(struct ath11k * - struct ath11k_base *ab = ar->ab; +@@ -684,6 +723,10 @@ void ath11k_peer_cleanup(struct ath11k * lockdep_assert_held(&ar->conf_mutex); -- + +#ifdef CPTCFG_ATH11K_NSS_SUPPORT + mutex_lock(&ab->base_ast_lock); +#endif ++ + mutex_lock(&ab->tbl_mtx_lock); spin_lock_bh(&ab->base_lock); list_for_each_entry_safe(peer, tmp_peer, &ab->peers, list) { - if (peer->vdev_id != vdev_id) -@@ -687,6 +728,9 @@ void ath11k_peer_cleanup(struct ath11k * - } +@@ -712,6 +755,9 @@ void ath11k_peer_cleanup(struct ath11k * spin_unlock_bh(&ab->base_lock); + mutex_unlock(&ab->tbl_mtx_lock); +#ifdef CPTCFG_ATH11K_NSS_SUPPORT + mutex_unlock(&ab->base_ast_lock); +#endif } static int ath11k_wait_for_peer_deleted(struct ath11k *ar, int vdev_id, const u8 *addr) -@@ -719,13 +763,42 @@ int ath11k_wait_for_peer_delete_done(str - int ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, u8 *addr) - { +@@ -746,9 +792,18 @@ static int __ath11k_peer_delete(struct a int ret; -- + struct ath11k_peer *peer; + struct ath11k_base *ab = ar->ab; +#ifdef CPTCFG_ATH11K_NSS_SUPPORT -+ struct ath11k_peer *peer; + struct ath11k_ast_entry *ast_entry, *tmp_ast; +#endif + lockdep_assert_held(&ar->conf_mutex); - reinit_completion(&ar->peer_delete_done); - - ath11k_nss_peer_delete(ar->ab, vdev_id, addr); ++ reinit_completion(&ar->peer_delete_done); ++ ath11k_nss_peer_delete(ar->ab, vdev_id, addr); ++ +#ifdef CPTCFG_ATH11K_NSS_SUPPORT -+ mutex_lock(&ar->ab->base_ast_lock); -+ spin_lock_bh(&ar->ab->base_lock); ++ mutex_lock(&ab->base_ast_lock); ++#endif + mutex_lock(&ab->tbl_mtx_lock); + spin_lock_bh(&ab->base_lock); -+ peer = ath11k_peer_find_by_addr(ar->ab, addr); +@@ -763,14 +818,34 @@ static int __ath11k_peer_delete(struct a + return -EINVAL; + } + +- ath11k_peer_rhash_delete(ab, peer); + if (peer) { ++#ifdef CPTCFG_ATH11K_NSS_SUPPORT + peer->delete_in_progress = true; + if (peer->self_ast_entry) { + ath11k_peer_del_ast(ar, peer->self_ast_entry); @@ -462,20 +468,29 @@ Signed-off-by: Rameshkumar Sundaram + if (!list_empty(&ast_entry->wmi_list)) { + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, + "%s deleting unprocessed ast entry %pM of peer %pM from wmi list\n", -+ __func__, ast_entry->addr, addr); ++ __func__, ast_entry->addr, addr); + list_del_init(&ast_entry->wmi_list); + } + } -+ } -+ spin_unlock_bh(&ar->ab->base_lock); -+ mutex_unlock(&ar->ab->base_ast_lock); +#endif ++ ath11k_peer_rhash_delete(ab, peer); ++ } + + spin_unlock_bh(&ab->base_lock); + mutex_unlock(&ab->tbl_mtx_lock); +- +- reinit_completion(&ar->peer_delete_done); +- +- ath11k_nss_peer_delete(ar->ab, vdev_id, addr); ++#ifdef CPTCFG_ATH11K_NSS_SUPPORT ++ mutex_unlock(&ab->base_ast_lock); ++#endif + ret = ath11k_wmi_send_peer_delete_cmd(ar, addr, vdev_id); if (ret) { - ath11k_warn(ar->ab, --- a/drivers/net/wireless/ath/ath11k/peer.h +++ b/drivers/net/wireless/ath/ath11k/peer.h -@@ -41,9 +41,7 @@ enum ath11k_wds_wmi_action { +@@ -42,9 +42,7 @@ enum ath11k_wds_wmi_action { struct ath11k_ast_entry { u16 ast_idx; u8 addr[ETH_ALEN]; @@ -485,7 +500,7 @@ Signed-off-by: Rameshkumar Sundaram struct ath11k_peer *peer; struct ath11k *ar; bool next_hop; -@@ -57,6 +55,7 @@ struct ath11k_ast_entry { +@@ -58,6 +56,7 @@ struct ath11k_ast_entry { bool delete_in_progress; void *cookie; struct list_head ase_list; @@ -493,7 +508,7 @@ Signed-off-by: Rameshkumar Sundaram }; struct ath11k_peer { -@@ -96,6 +95,7 @@ struct ath11k_peer { +@@ -98,6 +97,7 @@ struct ath11k_peer { struct ppdu_user_delayba ppdu_stats_delayba; bool delayba_flag; bool peer_logging_enabled; diff --git a/feeds/ipq95xx/mac80211/patches/qca/331-cfg80211-hold-bss-lock-while-updating-nontrans-list.patch b/feeds/ipq95xx/mac80211/patches/qca/331-cfg80211-hold-bss-lock-while-updating-nontrans-list.patch deleted file mode 100644 index 589640e8c..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/331-cfg80211-hold-bss-lock-while-updating-nontrans-list.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 5085d00b2b14f9d8852ce6899deb628fa020c4f5 Mon Sep 17 00:00:00 2001 -From: Rameshkumar Sundaram -Date: Mon, 4 Oct 2021 15:58:29 +0530 -Subject: [PATCH] cfg80211: hold bss lock while updating nontrans list - -Synchronize additions to nontrans list of transmitting bss -with bss_lock to avoid races. -Also while cfg80211_add_nontrans_list fails -__cfg80211_unlink_bss needs bss lock to be held -(has lockdep assert on bss_lock). -so protect the whole block with bss_lock -to avoid races and warnings. - -Signed-off-by: Rameshkumar Sundaram ---- - net/wireless/scan.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/net/wireless/scan.c b/net/wireless/scan.c -index 272b1c5..c54a881 100644 ---- a/net/wireless/scan.c -+++ b/net/wireless/scan.c -@@ -1959,11 +1959,13 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy, - /* this is a nontransmitting bss, we need to add it to - * transmitting bss' list if it is not there - */ -+ spin_lock_bh(&rdev->bss_lock); - if (cfg80211_add_nontrans_list(non_tx_data->tx_bss, - &res->pub)) { - if (__cfg80211_unlink_bss(rdev, res)) - rdev->bss_generation++; - } -+ spin_unlock_bh(&rdev->bss_lock); - } - - trace_cfg80211_return_bss(&res->pub); --- -2.7.4 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/332-0001-mac80211-Add-qos-tid-configuration-support.patch b/feeds/ipq95xx/mac80211/patches/qca/332-0001-mac80211-Add-qos-tid-configuration-support.patch index 6be246954..d70e694e6 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/332-0001-mac80211-Add-qos-tid-configuration-support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/332-0001-mac80211-Add-qos-tid-configuration-support.patch @@ -23,7 +23,7 @@ Signed-off-by: Sowmiya Sree Elavalagan --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h -@@ -731,6 +731,8 @@ struct cfg80211_tid_cfg { +@@ -803,6 +803,8 @@ struct cfg80211_tid_cfg { enum nl80211_tid_config amsdu; enum nl80211_tx_rate_setting txrate_type; struct cfg80211_bitrate_mask txrate_mask; @@ -32,33 +32,33 @@ Signed-off-by: Sowmiya Sree Elavalagan }; /** -@@ -1359,6 +1361,7 @@ enum station_parameters_apply_mask { +@@ -1455,6 +1457,7 @@ enum station_parameters_apply_mask { + STATION_PARAM_APPLY_UAPSD = BIT(0), STATION_PARAM_APPLY_CAPABILITY = BIT(1), STATION_PARAM_APPLY_PLINK_STATE = BIT(2), - STATION_PARAM_APPLY_STA_TXPOWER = BIT(3), + STATION_PARAM_APPLY_MGMT_RTS_CTS = BIT(4), }; /** -@@ -1457,6 +1460,7 @@ struct station_parameters { - const struct ieee80211_he_cap_elem *he_capa; - u8 he_capa_len; +@@ -1590,6 +1593,7 @@ struct station_parameters { + u8 supported_oper_classes_len; + int support_p2p_ps; u16 airtime_weight; + enum nl80211_mgmt_rts_cts_conf mgmt_rts_cts; - struct sta_txpwr txpwr; - const struct ieee80211_he_6ghz_capa *he_6ghz_capa; + struct link_station_parameters link_sta_params; }; + --- a/include/net/mac80211.h +++ b/include/net/mac80211.h -@@ -2187,6 +2187,7 @@ struct ieee80211_sta { +@@ -2307,6 +2307,7 @@ struct ieee80211_sta { bool support_p2p_ps; u16 max_rc_amsdu_len; u16 max_tid_amsdu_len[IEEE80211_NUM_TIDS]; + enum nl80211_mgmt_rts_cts_conf mgmt_rts_cts; - struct ieee80211_sta_txpwr txpwr; struct ieee80211_txq *txq[IEEE80211_NUM_TIDS + 1]; -@@ -4117,6 +4118,9 @@ struct ieee80211_ops { + +@@ -4293,6 +4294,9 @@ struct ieee80211_ops { int (*sta_set_txpwr)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta); @@ -70,7 +70,7 @@ Signed-off-by: Sowmiya Sree Elavalagan enum ieee80211_sta_state old_state, --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h -@@ -3184,6 +3184,10 @@ enum nl80211_attrs { +@@ -3284,6 +3284,10 @@ enum nl80211_attrs { NL80211_ATTR_BEACON_TX_MODE, @@ -81,7 +81,7 @@ Signed-off-by: Sowmiya Sree Elavalagan /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, -@@ -4358,6 +4362,11 @@ enum nl80211_mesh_power_mode { +@@ -4547,6 +4551,11 @@ enum nl80211_mesh_power_mode { NL80211_MESH_POWER_MAX = __NL80211_MESH_POWER_AFTER_LAST - 1 }; @@ -93,7 +93,7 @@ Signed-off-by: Sowmiya Sree Elavalagan /** * enum nl80211_meshconf_params - mesh configuration parameters * -@@ -5206,6 +5215,8 @@ enum nl80211_tid_config_attr { +@@ -5400,6 +5409,8 @@ enum nl80211_tid_config_attr { NL80211_TID_CONFIG_ATTR_AMSDU_CTRL, NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE, NL80211_TID_CONFIG_ATTR_TX_RATE, @@ -102,7 +102,7 @@ Signed-off-by: Sowmiya Sree Elavalagan /* keep last */ __NL80211_TID_CONFIG_ATTR_AFTER_LAST, -@@ -6173,6 +6184,7 @@ enum nl80211_ext_feature_index { +@@ -6367,6 +6378,7 @@ enum nl80211_ext_feature_index { NL80211_EXT_FEATURE_FILS_CRYPTO_OFFLOAD, NL80211_EXT_FEATURE_WIDE_BAND_SCAN, NL80211_EXT_FEATURE_RADAR_BACKGROUND, @@ -112,9 +112,9 @@ Signed-off-by: Sowmiya Sree Elavalagan NUM_NL80211_EXT_FEATURES, --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -1722,6 +1722,13 @@ static int sta_apply_parameters(struct i - return ret; - } +@@ -1818,6 +1818,13 @@ static int sta_apply_parameters(struct i + if (params->listen_interval >= 0) + sta->listen_interval = params->listen_interval; + if (params->sta_modify_mask & STATION_PARAM_APPLY_MGMT_RTS_CTS) { + sta->sta.mgmt_rts_cts = params->mgmt_rts_cts; @@ -123,12 +123,12 @@ Signed-off-by: Sowmiya Sree Elavalagan + return ret; + } + - if (params->supported_rates && params->supported_rates_len) { - ieee80211_parse_bitrates(&sdata->vif.bss_conf.chandef, - sband, params->supported_rates, + ret = sta_link_apply_parameters(local, sta, false, + ¶ms->link_sta_params); + if (ret) --- a/net/mac80211/driver-ops.c +++ b/net/mac80211/driver-ops.c -@@ -162,6 +162,27 @@ int drv_sta_set_txpwr(struct ieee80211_l +@@ -163,6 +163,27 @@ int drv_sta_set_txpwr(struct ieee80211_l return ret; } @@ -158,7 +158,7 @@ Signed-off-by: Sowmiya Sree Elavalagan struct ieee80211_sta *sta, u32 changed) --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h -@@ -552,6 +552,11 @@ int drv_sta_set_txpwr(struct ieee80211_l +@@ -574,6 +574,11 @@ int drv_sta_set_txpwr(struct ieee80211_l struct ieee80211_sub_if_data *sdata, struct sta_info *sta); @@ -172,7 +172,7 @@ Signed-off-by: Sowmiya Sree Elavalagan struct ieee80211_sta *sta, u32 changed); --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h -@@ -903,6 +903,34 @@ TRACE_EVENT(drv_sta_set_txpwr, +@@ -937,6 +937,34 @@ TRACE_EVENT(drv_sta_set_txpwr, ) ); @@ -209,7 +209,7 @@ Signed-off-by: Sowmiya Sree Elavalagan struct ieee80211_sub_if_data *sdata, --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c -@@ -411,7 +411,9 @@ nl80211_tid_config_attr_policy[NL80211_T +@@ -420,7 +420,9 @@ nl80211_tid_config_attr_policy[NL80211_T [NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE] = NLA_POLICY_MAX(NLA_U8, NL80211_TX_RATE_FIXED), [NL80211_TID_CONFIG_ATTR_TX_RATE] = @@ -220,16 +220,16 @@ Signed-off-by: Sowmiya Sree Elavalagan }; static const struct nla_policy -@@ -802,6 +804,8 @@ static const struct nla_policy nl80211_p - [NL80211_ATTR_RADAR_BACKGROUND] = { .type = NLA_FLAG }, - [NL80211_ATTR_AP_SETTINGS_FLAGS] = { .type = NLA_U32 }, +@@ -831,6 +833,8 @@ static const struct nla_policy nl80211_p + [NL80211_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG }, + [NL80211_ATTR_MAX_NUM_AKM_SUITES] = { .type = NLA_REJECT }, [NL80211_ATTR_BEACON_TX_MODE] = NLA_POLICY_RANGE(NLA_U32, 1, 2), + [NL80211_ATTR_STA_MGMT_RTS_CTS_CONFIG] = + NLA_POLICY_MAX(NLA_U8, NL80211_MGMT_RTS_CTS_DISABLE), }; /* policy for the key attributes */ -@@ -6748,6 +6752,16 @@ static int nl80211_set_station(struct sk +@@ -7026,6 +7030,15 @@ static int nl80211_set_station(struct sk NL80211_EXT_FEATURE_AIRTIME_FAIRNESS)) return -EOPNOTSUPP; @@ -237,16 +237,15 @@ Signed-off-by: Sowmiya Sree Elavalagan + if (!wiphy_ext_feature_isset(&rdev->wiphy, + NL80211_EXT_FEATURE_STA_MGMT_RTS_CTS)) + return -EOPNOTSUPP; -+ + params.mgmt_rts_cts = + nla_get_u8(info->attrs[NL80211_ATTR_STA_MGMT_RTS_CTS_CONFIG]); + params.sta_modify_mask |= STATION_PARAM_APPLY_MGMT_RTS_CTS; + } + - err = nl80211_parse_sta_txpower_setting(info, ¶ms); - if (err) - return err; -@@ -15009,6 +15023,12 @@ static int parse_tid_conf(struct cfg8021 + err = nl80211_parse_sta_txpower_setting(info, + ¶ms.link_sta_params.txpwr, + ¶ms.link_sta_params.txpwr_set); +@@ -15602,6 +15615,12 @@ static int parse_tid_conf(struct cfg8021 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL); tid_conf->ampdu = nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_AMPDU_CTRL]); @@ -259,7 +258,7 @@ Signed-off-by: Sowmiya Sree Elavalagan } if (attrs[NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL]) { -@@ -15021,6 +15041,12 @@ static int parse_tid_conf(struct cfg8021 +@@ -15614,6 +15633,12 @@ static int parse_tid_conf(struct cfg8021 tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_AMSDU_CTRL); tid_conf->amsdu = nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_AMSDU_CTRL]); diff --git a/feeds/ipq95xx/mac80211/patches/qca/332-0002-ath11k-Add-tid-qos-configuration-support.patch b/feeds/ipq95xx/mac80211/patches/qca/332-0002-ath11k-Add-tid-qos-configuration-support.patch index c1a0f1ab7..be2eec23f 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/332-0002-ath11k-Add-tid-qos-configuration-support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/332-0002-ath11k-Add-tid-qos-configuration-support.patch @@ -34,7 +34,7 @@ Signed-off-by: Sowmiya Sree Elavalagan --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -95,6 +95,7 @@ enum wme_ac { +@@ -83,6 +83,7 @@ enum wme_ac { #define ATH11K_HT_MCS_MAX 7 #define ATH11K_VHT_MCS_MAX 9 #define ATH11K_HE_MCS_MAX 11 @@ -42,7 +42,7 @@ Signed-off-by: Sowmiya Sree Elavalagan enum ath11k_crypt_mode { /* Only use hardware crypto engine */ -@@ -107,6 +108,7 @@ enum ath11k_crypt_mode { +@@ -95,6 +96,7 @@ enum ath11k_crypt_mode { #define ATH11K_FREE_GROUP_IDX_MAP_BITS 32 #define ATH11K_FREE_GROUP_IDX_MAP_MAX (ATH11K_GROUP_KEYS_NUM_MAX / \ ATH11K_FREE_GROUP_IDX_MAP_BITS) @@ -50,15 +50,14 @@ Signed-off-by: Sowmiya Sree Elavalagan static inline enum wme_ac ath11k_tid_to_ac(u32 tid) { -@@ -120,6 +122,7 @@ enum ath11k_skb_flags { - ATH11K_SKB_HW_80211_ENCAP = BIT(0), +@@ -108,5 +110,6 @@ enum ath11k_skb_flags { ATH11K_SKB_CIPHER_SET = BIT(1), - ATH11K_SKB_TX_STATUS = BIT(2), + ATH11K_SKB_TX_STATUS = BIT(2), + ATH11K_SKB_F_NOACK_TID = BIT(3), }; struct ath11k_skb_cb { -@@ -285,6 +288,18 @@ struct ath11k_mac_filter { +@@ -246,6 +249,18 @@ struct ath11k_mac_filter { u8 peer_mac[ETH_ALEN]; }; @@ -77,8 +76,8 @@ Signed-off-by: Sowmiya Sree Elavalagan struct ath11k_vif { u32 vdev_id; enum wmi_vdev_type vdev_type; -@@ -355,6 +370,9 @@ struct ath11k_vif { - struct list_head dyn_vlan_cfg; +@@ -308,6 +323,9 @@ struct ath11k_vif { + struct list_head ap_vlan_arvifs; /* VLAN keyidx map required for Dynamic VLAN */ u16 *vlan_keyid_map; + u32 tid_conf_changed[ATH11K_TID_MAX]; @@ -87,7 +86,7 @@ Signed-off-by: Sowmiya Sree Elavalagan DECLARE_BITMAP(free_groupidx_map, ATH11K_GROUP_KEYS_NUM_MAX); }; -@@ -562,6 +580,8 @@ struct ath11k_sta { +@@ -511,6 +529,8 @@ struct ath11k_sta { /*bytes count for bit error rate computation*/ u32 ber_succ_bytes; u32 ber_fail_bytes; @@ -98,7 +97,7 @@ Signed-off-by: Sowmiya Sree Elavalagan #endif --- a/drivers/net/wireless/ath/ath11k/dp_tx.c +++ b/drivers/net/wireless/ath/ath11k/dp_tx.c -@@ -462,7 +462,8 @@ ath11k_dp_tx_htt_tx_complete_buf(struct +@@ -456,7 +456,8 @@ ath11k_dp_tx_htt_tx_complete_buf(struct memset(&info->status, 0, sizeof(info->status)); if (ts->acked) { @@ -108,7 +107,7 @@ Signed-off-by: Sowmiya Sree Elavalagan info->flags |= IEEE80211_TX_STAT_ACK; info->status.ack_signal = ATH11K_DEFAULT_NOISE_FLOOR + ts->ack_rssi; -@@ -694,7 +695,8 @@ static void ath11k_dp_tx_complete_msdu(s +@@ -591,7 +592,8 @@ static void ath11k_dp_tx_complete_msdu(s info->status.rates[0].idx = -1; if (ts->status == HAL_WBM_TQM_REL_REASON_FRAME_ACKED && @@ -118,7 +117,7 @@ Signed-off-by: Sowmiya Sree Elavalagan info->flags |= IEEE80211_TX_STAT_ACK; info->status.ack_signal = ATH11K_DEFAULT_NOISE_FLOOR + ts->ack_rssi; -@@ -702,7 +704,8 @@ static void ath11k_dp_tx_complete_msdu(s +@@ -599,7 +601,8 @@ static void ath11k_dp_tx_complete_msdu(s } if (ts->status == HAL_WBM_TQM_REL_REASON_CMD_REMOVE_TX && @@ -127,24 +126,24 @@ Signed-off-by: Sowmiya Sree Elavalagan + (flags & ATH11K_SKB_F_NOACK_TID)) info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; - if (unlikely(ath11k_debugfs_is_extd_tx_stats_enabled(ar)) || + if (unlikely(ath11k_debugfs_is_extd_tx_stats_enabled(ar))) { --- a/drivers/net/wireless/ath/ath11k/hw.c +++ b/drivers/net/wireless/ath/ath11k/hw.c -@@ -110,6 +110,10 @@ static void ath11k_init_wmi_config_qca63 - config->num_wow_filters = 0x16; - config->num_keep_alive_pattern = 0; - config->flag1 |= WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64; +@@ -157,6 +157,10 @@ static void ath11k_init_wmi_config_ipq80 + config->num_wow_filters = 0x16; + config->num_keep_alive_pattern = 0; + config->flag1 |= WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64; + if (test_bit(WMI_TLV_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT, + ab->wmi_ab.svc_map)) { + config->peer_tid_ext |= WMI_RSRC_CFG_FLAG_PEER_TID_EXT; + } } - void ath11k_hal_reo_hash_setup(struct ath11k_base *ab, u32 ring_hash_map) + static int ath11k_hw_mac_id_to_pdev_id_ipq8074(struct ath11k_hw_params *hw, --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -4589,6 +4589,180 @@ ath11k_mac_bitrate_mask_num_ht_rates(str - return num_rates; +@@ -4310,6 +4310,180 @@ exit: + return ret; } +static int ath11k_new_peer_tid_config(struct ath11k *ar, @@ -221,33 +220,33 @@ Signed-off-by: Sowmiya Sree Elavalagan + struct ieee80211_sta *sta, + u32 rate_ctrl_flag, u8 nss) +{ -+ if (nss > sta->rx_nss) { ++ if (nss > sta->deflink.rx_nss) { + ath11k_warn(ar->ab, "Invalid nss field, configured %u limit %u\n", -+ nss, sta->rx_nss); ++ nss, sta->deflink.rx_nss); + return -EINVAL; + } + + if (ATH11K_HW_PREAMBLE(rate_ctrl_flag) == WMI_RATE_PREAMBLE_HE) { -+ if (!sta->he_cap.has_he) { ++ if (!sta->deflink.he_cap.has_he) { + ath11k_warn(ar->ab, "Invalid HE rate for sta %pM\n", + sta->addr); + return -EINVAL; + } + } else if (ATH11K_HW_PREAMBLE(rate_ctrl_flag) == WMI_RATE_PREAMBLE_VHT) { -+ if (!sta->vht_cap.vht_supported || sta->he_cap.has_he) { ++ if (!sta->deflink.vht_cap.vht_supported || sta->deflink.he_cap.has_he) { + ath11k_warn(ar->ab, "Invalid VHT rate for sta %pM\n", + sta->addr); + return -EINVAL; + } + } else if (ATH11K_HW_PREAMBLE(rate_ctrl_flag) == WMI_RATE_PREAMBLE_HT) { -+ if (!sta->ht_cap.ht_supported || sta->vht_cap.vht_supported) { ++ if (!sta->deflink.ht_cap.ht_supported || sta->deflink.vht_cap.vht_supported) { + ath11k_warn(ar->ab, "Invalid HT rate for sta %pM\n", + sta->addr); + return -EINVAL; + } + } else { -+ if (sta->ht_cap.ht_supported || -+ sta->vht_cap.vht_supported || sta->he_cap.has_he) { ++ if (sta->deflink.ht_cap.ht_supported || ++ sta->deflink.vht_cap.vht_supported || sta->deflink.he_cap.has_he) { + ath11k_warn(ar->ab, "Invalid rate cap\n"); + return -EINVAL; + } @@ -324,7 +323,7 @@ Signed-off-by: Sowmiya Sree Elavalagan static int ath11k_mac_bitrate_mask_num_vht_rates(struct ath11k *ar, enum nl80211_band band, -@@ -4899,8 +5073,10 @@ static int ath11k_station_assoc(struct a +@@ -4564,8 +4738,10 @@ static int ath11k_station_assoc(struct a return ret; } } @@ -336,7 +335,7 @@ Signed-off-by: Sowmiya Sree Elavalagan } static int ath11k_station_disassoc(struct ath11k *ar, -@@ -5429,6 +5605,201 @@ static int ath11k_mac_cfg_dyn_vlan(struc +@@ -5091,6 +5267,201 @@ static int ath11k_mac_cfg_dyn_vlan(struc return ret; } @@ -538,15 +537,15 @@ Signed-off-by: Sowmiya Sree Elavalagan static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, -@@ -5446,6 +5817,7 @@ static int ath11k_mac_op_sta_state(struc +@@ -5108,6 +5479,7 @@ static int ath11k_mac_op_sta_state(struc new_state == IEEE80211_STA_NOTEXIST)) { cancel_work_sync(&arsta->update_wk); - cancel_work_sync(&arsta->set_4addr_wk); + cancel_work_sync(&arsta->set_4addr_wk); + cancel_work_sync(&arsta->tid_config_wk); } mutex_lock(&ar->conf_mutex); -@@ -5457,6 +5829,7 @@ static int ath11k_mac_op_sta_state(struc +@@ -5119,6 +5491,7 @@ static int ath11k_mac_op_sta_state(struc arsta->peer_ps_state = WMI_PEER_PS_STATE_DISABLED; INIT_WORK(&arsta->update_wk, ath11k_sta_rc_update_wk); INIT_WORK(&arsta->set_4addr_wk, ath11k_sta_set_4addr_wk); @@ -554,8 +553,8 @@ Signed-off-by: Sowmiya Sree Elavalagan ret = ath11k_mac_station_add(ar, vif, sta); if (ret) -@@ -6756,6 +7129,8 @@ static void ath11k_mac_op_tx(struct ieee - struct ieee80211_sta *sta = control->sta; +@@ -6302,6 +6675,8 @@ static void ath11k_mac_op_tx(struct ieee + struct ath11k_sta *arsta = NULL; bool is_prb_rsp; u16 frm_type = 0; + u8 tid, *qos_ctl; @@ -563,41 +562,37 @@ Signed-off-by: Sowmiya Sree Elavalagan int ret; memset(skb_cb, 0, sizeof(*skb_cb)); -@@ -6813,6 +7188,33 @@ static void ath11k_mac_op_tx(struct ieee - test_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags)) +@@ -6356,6 +6731,29 @@ static void ath11k_mac_op_tx(struct ieee + ar->monitor_vdev_created) skb_cb->flags |= ATH11K_SKB_TX_STATUS; + if (ieee80211_is_data_qos(hdr->frame_control)) { + qos_ctl = ieee80211_get_qos_ctl(hdr); + tid = (*qos_ctl) & IEEE80211_QOS_CTL_TID_MASK; + -+ if (tid < ATH11K_TID_MAX) { -+ if (arvif->tid_cfg[tid].noack == WMI_PEER_TID_CONFIG_NOACK) ++ if (arvif->tid_cfg[tid].noack == WMI_PEER_TID_CONFIG_NOACK) ++ noack = true; ++ ++ /* sta specific config has high precedence over vif specific config ++ * Hence overwrite sta specific config if it is present ++ */ ++ if (sta) { ++ arsta = (struct ath11k_sta *)sta->drv_priv; ++ if (arsta->tid_cfg[tid].noack == WMI_PEER_TID_CONFIG_NOACK) + noack = true; + -+ /* sta specific config has high precedence over vif specific config -+ * Hence overwrite sta specific config if it is present -+ */ -+ if (sta) { -+ arsta = (struct ath11k_sta *)sta->drv_priv; -+ if (arsta->tid_cfg[tid].noack == WMI_PEER_TID_CONFIG_NOACK) -+ noack = true; -+ -+ if (arsta->tid_cfg[tid].noack == WMI_PEER_TID_CONFIG_ACK) -+ noack = false; -+ } -+ -+ if (noack) -+ skb_cb->flags |= ATH11K_SKB_F_NOACK_TID; -+ } else { -+ ath11k_warn(ar->ab, "invalid tid %d in xmit\n", tid); ++ if (arsta->tid_cfg[tid].noack == WMI_PEER_TID_CONFIG_ACK) ++ noack = false; + } ++ ++ if (noack) ++ skb_cb->flags |= ATH11K_SKB_F_NOACK_TID; + } + if (ar->ab->nss.enabled) ret = ath11k_nss_tx(arvif, skb); else -@@ -8545,6 +8947,24 @@ static void ath11k_mac_op_flush(struct i +@@ -8041,6 +8439,24 @@ ath11k_mac_bitrate_mask_num_ht_rates(str } static bool @@ -622,7 +617,7 @@ Signed-off-by: Sowmiya Sree Elavalagan ath11k_mac_has_single_legacy_rate(struct ath11k *ar, enum nl80211_band band, const struct cfg80211_bitrate_mask *mask) -@@ -8678,6 +9098,533 @@ ath11k_mac_get_single_legacy_rate(struct +@@ -8172,6 +8588,533 @@ ath11k_mac_get_single_legacy_rate(struct } static int @@ -1156,7 +1151,7 @@ Signed-off-by: Sowmiya Sree Elavalagan ath11k_mac_set_fixed_rate_gi_ltf(struct ath11k_vif *arvif, u8 he_gi, u8 he_ltf) { struct ath11k *ar = arvif->ar; -@@ -9575,6 +10522,9 @@ static const struct ieee80211_ops ath11k +@@ -9005,6 +9948,9 @@ static const struct ieee80211_ops ath11k .get_survey = ath11k_mac_op_get_survey, .flush = ath11k_mac_op_flush, .sta_statistics = ath11k_mac_op_sta_statistics, @@ -1166,9 +1161,9 @@ Signed-off-by: Sowmiya Sree Elavalagan CFG80211_TESTMODE_CMD(ath11k_tm_cmd) #ifdef CPTCFG_ATH11K_DEBUGFS .sta_add_debugfs = ath11k_debugfs_sta_op_add, -@@ -10059,6 +11009,35 @@ static int __ath11k_mac_register(struct - wiphy_ext_feature_set(ar->hw->wiphy, - NL80211_EXT_FEATURE_BSS_COLOR); +@@ -9486,6 +10432,35 @@ static int __ath11k_mac_register(struct + wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_STA_TX_PWR); + wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_BSS_COLOR); + if (test_bit(WMI_TLV_SERVICE_PEER_TID_CONFIGS_SUPPORT, ar->ab->wmi_ab.svc_map)) { + ar->hw->wiphy->tid_config_support.vif |= @@ -1204,7 +1199,7 @@ Signed-off-by: Sowmiya Sree Elavalagan wiphy_ext_feature_set(ar->hw->wiphy, --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -748,6 +748,55 @@ int ath11k_wmi_qos_null_send(struct ath1 +@@ -724,6 +724,55 @@ int ath11k_wmi_qos_null_send(struct ath1 return ret; } @@ -1260,17 +1255,17 @@ Signed-off-by: Sowmiya Sree Elavalagan int ath11k_wmi_vdev_create(struct ath11k *ar, u8 *macaddr, struct vdev_create_params *param) { -@@ -4520,6 +4569,7 @@ ath11k_wmi_copy_resource_config(struct w +@@ -4380,6 +4429,7 @@ ath11k_wmi_copy_resource_config(struct w wmi_cfg->host_service_flags |= tg_cfg->is_reg_cc_ext_event_supported << WMI_RSRC_CFG_HOST_SERVICE_FLAG_REG_CC_EXT_SUPPORT_BIT; - wmi_cfg->smart_ant_cap = 1; + wmi_cfg->smart_ant_cap = 1; + wmi_cfg->flag1 |= tg_cfg->peer_tid_ext; } - + static int ath11k_init_cmd_send(struct ath11k_pdev_wmi *wmi, --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -2178,6 +2178,7 @@ enum wmi_tlv_service { +@@ -2189,6 +2189,7 @@ enum wmi_tlv_service { WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281, WMI_TLV_SERVICE_DCS_AWGN_INT_SUPPORT = 286, WMI_TLV_SERVICE_DYN_NSS_MASK_SUPPORT = 303, @@ -1278,7 +1273,7 @@ Signed-off-by: Sowmiya Sree Elavalagan WMI_MAX_EXT2_SERVICE }; -@@ -2218,6 +2219,7 @@ enum { +@@ -2229,6 +2230,7 @@ enum { #define WMI_PEER_SET_MIN_TX_RATE 0x12 #define WMI_PEER_SET_DEFAULT_ROUTING 0x13 #define WMI_PEER_PARAM_DYN_NSS_EN_MASK 0x24 @@ -1286,7 +1281,7 @@ Signed-off-by: Sowmiya Sree Elavalagan /* slot time long */ #define WMI_VDEV_SLOT_TIME_LONG 0x1 -@@ -2398,6 +2400,7 @@ struct wmi_init_cmd { +@@ -2410,6 +2412,7 @@ struct wmi_init_cmd { #define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5) #define WMI_RSRC_CFG_FLAG1_ACK_RSSI BIT(18) #define WMI_RSRC_CFG_HOST_SERVICE_FLAG_REG_CC_EXT_SUPPORT_BIT 4 @@ -1294,7 +1289,7 @@ Signed-off-by: Sowmiya Sree Elavalagan struct wmi_resource_config { u32 tlv_header; -@@ -6186,6 +6189,7 @@ struct target_resource_config { +@@ -6178,6 +6181,7 @@ struct target_resource_config { u32 num_msdu_desc; u32 max_frag_entries; u32 max_peer_ext_stats; @@ -1302,7 +1297,7 @@ Signed-off-by: Sowmiya Sree Elavalagan u32 smart_ant_cap; u32 bk_minfree; u32 be_minfree; -@@ -6435,6 +6439,78 @@ struct wmi_qos_null_tx_cmd { +@@ -6404,6 +6408,78 @@ struct wmi_qos_null_tx_cmd { u32 tx_params_valid; } __packed; @@ -1378,10 +1373,10 @@ Signed-off-by: Sowmiya Sree Elavalagan + u32 max_num_msdu_in_mpdu; +} __packed; + - enum wmi_dblog_param { - WMI_DEBUG_LOG_PARAM_LOG_LEVEL = 0x1, - WMI_DEBUG_LOG_PARAM_VDEV_ENABLE, -@@ -6771,6 +6847,8 @@ int ath11k_wmi_mgmt_send(struct ath11k * + #define WMI_MAX_MEM_REQS 32 + + #define MAX_RADIOS 3 +@@ -6740,6 +6816,8 @@ int ath11k_wmi_mgmt_send(struct ath11k * struct sk_buff *frame, bool tx_params_valid); int ath11k_wmi_qos_null_send(struct ath11k *ar, u32 vdev_id, u32 buf_id, struct sk_buff *frame); @@ -1389,4 +1384,4 @@ Signed-off-by: Sowmiya Sree Elavalagan + const struct wmi_per_peer_per_tid_cfg_arg *arg); int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id, struct ieee80211_mutable_offsets *offs, - struct sk_buff *bcn); + struct sk_buff *bcn, u32 ema_param); diff --git a/feeds/ipq95xx/mac80211/patches/qca/333-0008-cfg80211-save-power-spectral-density-psd-of-regulato.patch b/feeds/ipq95xx/mac80211/patches/qca/333-0008-cfg80211-save-power-spectral-density-psd-of-regulato.patch index e574c2b24..704190157 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/333-0008-cfg80211-save-power-spectral-density-psd-of-regulato.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/333-0008-cfg80211-save-power-spectral-density-psd-of-regulato.patch @@ -18,28 +18,26 @@ Signed-off-by: Aditya Kumar Singh net/wireless/reg.c | 17 +++++++++++++++++ 5 files changed, 50 insertions(+) -diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h -index 7b4c4b0..eebe8ba 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h -@@ -108,6 +108,8 @@ struct wiphy; - * on this channel. - * @IEEE80211_CHAN_16MHZ: 16 MHz bandwidth is permitted - * on this channel. +@@ -120,6 +120,8 @@ struct wiphy; + * This may be due to the driver or due to regulatory bandwidth + * restrictions. + * @IEEE80211_CHAN_NO_EHT: EHT operation is not permitted on this channel. + * @IEEE80211_CHAN_PSD: power spectral density (in dBm) -+ * on this channel. - * ++ * on this channel. */ enum ieee80211_channel_flags { -@@ -130,6 +132,7 @@ enum ieee80211_channel_flags { - IEEE80211_CHAN_4MHZ = 1<<16, - IEEE80211_CHAN_8MHZ = 1<<17, + IEEE80211_CHAN_DISABLED = 1<<0, +@@ -143,6 +145,7 @@ enum ieee80211_channel_flags { IEEE80211_CHAN_16MHZ = 1<<18, -+ IEEE80211_CHAN_PSD = 1<<19, + IEEE80211_CHAN_NO_320MHZ = 1<<19, + IEEE80211_CHAN_NO_EHT = 1<<20, ++ IEEE80211_CHAN_PSD = 1<<21, }; #define IEEE80211_CHAN_NO_HT40 \ -@@ -163,6 +166,7 @@ enum ieee80211_channel_flags { +@@ -176,6 +179,7 @@ enum ieee80211_channel_flags { * on this channel. * @dfs_state_entered: timestamp (jiffies) when the dfs state was entered. * @dfs_cac_ms: DFS CAC time in milliseconds, this is valid for DFS channels. @@ -47,7 +45,7 @@ index 7b4c4b0..eebe8ba 100644 */ struct ieee80211_channel { enum nl80211_band band; -@@ -179,6 +183,7 @@ struct ieee80211_channel { +@@ -192,6 +196,7 @@ struct ieee80211_channel { enum nl80211_dfs_state dfs_state; unsigned long dfs_state_entered; unsigned int dfs_cac_ms; @@ -55,8 +53,6 @@ index 7b4c4b0..eebe8ba 100644 }; /** -diff --git a/include/net/regulatory.h b/include/net/regulatory.h -index 47f06f6..ed20004 100644 --- a/include/net/regulatory.h +++ b/include/net/regulatory.h @@ -221,6 +221,7 @@ struct ieee80211_reg_rule { @@ -67,28 +63,26 @@ index 47f06f6..ed20004 100644 }; struct ieee80211_regdomain { -diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h -index e2393d0..f138647 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h -@@ -3913,6 +3913,8 @@ enum nl80211_wmm_rule { - * on this channel in current regulatory domain. - * @NL80211_FREQUENCY_ATTR_16MHZ: 16 MHz operation is allowed - * on this channel in current regulatory domain. +@@ -4127,6 +4127,8 @@ enum nl80211_wmm_rule { + * as the primary or any of the secondary channels isn't possible + * @NL80211_FREQUENCY_ATTR_NO_EHT: EHT operation is not allowed on this channel + * in current regulatory domain. + * @NL80211_FREQUENCY_ATTR_PSD: power spectral density (in dBm) + * is allowed on this channel in current regulatory domain. * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number * currently defined * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use -@@ -3949,6 +3951,7 @@ enum nl80211_frequency_attr { - NL80211_FREQUENCY_ATTR_4MHZ, - NL80211_FREQUENCY_ATTR_8MHZ, +@@ -4165,6 +4167,7 @@ enum nl80211_frequency_attr { NL80211_FREQUENCY_ATTR_16MHZ, + NL80211_FREQUENCY_ATTR_NO_320MHZ, + NL80211_FREQUENCY_ATTR_NO_EHT, + NL80211_FREQUENCY_ATTR_PSD, /* keep last */ __NL80211_FREQUENCY_ATTR_AFTER_LAST, -@@ -4049,6 +4052,8 @@ enum nl80211_reg_type { +@@ -4265,6 +4268,8 @@ enum nl80211_reg_type { * a given frequency range. The value is in mBm (100 * dBm). * @NL80211_ATTR_DFS_CAC_TIME: DFS CAC time in milliseconds. * If not present or 0 default CAC time will be used. @@ -97,7 +91,7 @@ index e2393d0..f138647 100644 * @NL80211_REG_RULE_ATTR_MAX: highest regulatory rule attribute number * currently defined * @__NL80211_REG_RULE_ATTR_AFTER_LAST: internal use -@@ -4066,6 +4071,8 @@ enum nl80211_reg_rule_attr { +@@ -4282,6 +4287,8 @@ enum nl80211_reg_rule_attr { NL80211_ATTR_DFS_CAC_TIME, @@ -106,27 +100,25 @@ index e2393d0..f138647 100644 /* keep last */ __NL80211_REG_RULE_ATTR_AFTER_LAST, NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1 -@@ -4147,6 +4154,7 @@ enum nl80211_sched_scan_match_attr { - * @NL80211_RRF_NO_80MHZ: 80MHz operation not allowed +@@ -4364,6 +4371,7 @@ enum nl80211_sched_scan_match_attr { * @NL80211_RRF_NO_160MHZ: 160MHz operation not allowed * @NL80211_RRF_NO_HE: HE operation not allowed + * @NL80211_RRF_NO_320MHZ: 320MHz operation not allowed + * @NL80211_RRF_PSD: channels has power spectral density value */ enum nl80211_reg_rule_flags { NL80211_RRF_NO_OFDM = 1<<0, -@@ -4165,6 +4173,7 @@ enum nl80211_reg_rule_flags { - NL80211_RRF_NO_80MHZ = 1<<15, +@@ -4383,6 +4391,7 @@ enum nl80211_reg_rule_flags { NL80211_RRF_NO_160MHZ = 1<<16, NL80211_RRF_NO_HE = 1<<17, -+ NL80211_RRF_PSD = 1<<18, + NL80211_RRF_NO_320MHZ = 1<<18, ++ NL80211_RRF_PSD = 1<<19, }; #define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR -diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c -index 958b6f9..bd93def 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c -@@ -1094,6 +1094,10 @@ static int nl80211_msg_put_channel(struct sk_buff *msg, struct wiphy *wiphy, +@@ -1132,6 +1132,10 @@ static int nl80211_msg_put_channel(struc if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_OFFSET, chan->freq_offset)) goto nla_put_failure; @@ -137,7 +129,7 @@ index 958b6f9..bd93def 100644 if ((chan->flags & IEEE80211_CHAN_DISABLED) && nla_put_flag(msg, NL80211_FREQUENCY_ATTR_DISABLED)) goto nla_put_failure; -@@ -7842,6 +7846,11 @@ static int nl80211_put_regdom(const struct ieee80211_regdomain *regdom, +@@ -8321,6 +8325,11 @@ static int nl80211_put_regdom(const stru reg_rule->dfs_cac_ms)) goto nla_put_failure; @@ -149,7 +141,7 @@ index 958b6f9..bd93def 100644 nla_nest_end(msg, nl_reg_rule); } -@@ -8015,6 +8024,7 @@ static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = +@@ -8494,6 +8503,7 @@ static const struct nla_policy reg_rule_ [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 }, [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 }, [NL80211_ATTR_DFS_CAC_TIME] = { .type = NLA_U32 }, @@ -157,7 +149,7 @@ index 958b6f9..bd93def 100644 }; static int parse_reg_rule(struct nlattr *tb[], -@@ -8036,6 +8046,14 @@ static int parse_reg_rule(struct nlattr *tb[], +@@ -8515,6 +8525,14 @@ static int parse_reg_rule(struct nlattr reg_rule->flags = nla_get_u32(tb[NL80211_ATTR_REG_RULE_FLAGS]); @@ -172,20 +164,18 @@ index 958b6f9..bd93def 100644 freq_range->start_freq_khz = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]); freq_range->end_freq_khz = -diff --git a/net/wireless/reg.c b/net/wireless/reg.c -index f3bf028..3104916 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c -@@ -1589,6 +1589,8 @@ static u32 map_regdom_flags(u32 rd_flags) - channel_flags |= IEEE80211_CHAN_NO_160MHZ; - if (rd_flags & NL80211_RRF_NO_HE) +@@ -1620,6 +1620,8 @@ static u32 map_regdom_flags(u32 rd_flags channel_flags |= IEEE80211_CHAN_NO_HE; + if (rd_flags & NL80211_RRF_NO_320MHZ) + channel_flags |= IEEE80211_CHAN_NO_320MHZ; + if (rd_flags & NL80211_RRF_PSD) + channel_flags |= IEEE80211_CHAN_PSD; return channel_flags; } -@@ -1793,6 +1795,9 @@ static void handle_channel_single_rule(struct wiphy *wiphy, +@@ -1826,6 +1828,9 @@ static void handle_channel_single_rule(s chan->dfs_cac_ms = reg_rule->dfs_cac_ms; } @@ -195,7 +185,7 @@ index f3bf028..3104916 100644 return; } -@@ -1813,6 +1818,9 @@ static void handle_channel_single_rule(struct wiphy *wiphy, +@@ -1846,6 +1851,9 @@ static void handle_channel_single_rule(s chan->dfs_cac_ms = IEEE80211_DFS_MIN_CAC_TIME_MS; } @@ -205,7 +195,7 @@ index f3bf028..3104916 100644 if (chan->orig_mpwr) { /* * Devices that use REGULATORY_COUNTRY_IE_FOLLOW_POWER -@@ -1882,6 +1890,12 @@ static void handle_channel_adjacent_rules(struct wiphy *wiphy, +@@ -1915,6 +1923,12 @@ static void handle_channel_adjacent_rule rrule2->dfs_cac_ms); } @@ -218,7 +208,7 @@ index f3bf028..3104916 100644 return; } -@@ -2539,6 +2553,9 @@ static void handle_channel_custom(struct wiphy *wiphy, +@@ -2601,6 +2615,9 @@ static void handle_channel_custom(struct chan->dfs_cac_ms = IEEE80211_DFS_MIN_CAC_TIME_MS; } @@ -228,6 +218,3 @@ index f3bf028..3104916 100644 chan->max_power = chan->max_reg_power; } --- -2.7.4 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/333-0013-ath11k-add-parse-of-transmit-power-envelope-element.patch b/feeds/ipq95xx/mac80211/patches/qca/333-0013-ath11k-add-parse-of-transmit-power-envelope-element.patch index 51f66c962..9f8a9f0f8 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/333-0013-ath11k-add-parse-of-transmit-power-envelope-element.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/333-0013-ath11k-add-parse-of-transmit-power-envelope-element.patch @@ -14,12 +14,10 @@ Signed-off-by: Aditya Kumar Singh drivers/net/wireless/ath/ath11k/mac.c | 196 +++++++++++++++++++++++++++++++++ 2 files changed, 234 insertions(+) -diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h -index 7bb27ef..47f885f 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -246,6 +246,43 @@ struct ath11k_mac_filter { - u8 peer_mac[ETH_ALEN]; +@@ -384,6 +384,43 @@ struct ath11k_tid_qos_config { + int ext_tid_cfg_bitmap; }; +/** @@ -62,19 +60,17 @@ index 7bb27ef..47f885f 100644 struct ath11k_vif { u32 vdev_id; enum wmi_vdev_type vdev_type; -@@ -298,6 +335,7 @@ struct ath11k_vif { - bool do_not_send_tmpl; - u32 vht_cap; +@@ -439,6 +476,7 @@ struct ath11k_vif { struct ieee80211_chanctx_conf chanctx; + struct ath11k_arp_ns_offload arp_ns_offload; + struct ath11k_rekey_data rekey_data; + struct ath11k_reg_tpc_power_info reg_tpc_info; + + #ifdef CPTCFG_ATH11K_DEBUGFS struct dentry *debugfs_twt; - struct ath11k_mgmt_frame_stats mgmt_stats; - /* protected by conf_mutex */ -diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c -index 3ef2615..2894b50 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -7805,6 +7805,199 @@ static int ath11k_start_vdev_delay(struct ieee80211_hw *hw, +@@ -8797,6 +8797,199 @@ static int ath11k_start_vdev_delay(struc return 0; } @@ -274,7 +270,7 @@ index 3ef2615..2894b50 100644 static int ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, -@@ -7831,6 +8024,9 @@ ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, +@@ -8824,6 +9017,9 @@ ath11k_mac_op_assign_vif_chanctx(struct power_type); if (power_type == IEEE80211_REG_UNSET_AP) power_type = IEEE80211_REG_LPI_AP; @@ -284,6 +280,3 @@ index 3ef2615..2894b50 100644 } /* for QCA6390 bss peer must be created before vdev_start */ --- -2.7.4 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/333-0016-ath11k-discard-BSS_CHANGED_TXPOWER-when-EXT_TPC_REG_.patch b/feeds/ipq95xx/mac80211/patches/qca/333-0016-ath11k-discard-BSS_CHANGED_TXPOWER-when-EXT_TPC_REG_.patch index da73ac5bf..91f1a336b 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/333-0016-ath11k-discard-BSS_CHANGED_TXPOWER-when-EXT_TPC_REG_.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/333-0016-ath11k-discard-BSS_CHANGED_TXPOWER-when-EXT_TPC_REG_.patch @@ -26,30 +26,42 @@ Signed-off-by: Aditya Kumar Singh --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -3503,8 +3503,18 @@ static void ath11k_mac_op_bss_info_chang - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev_id %i txpower %d\n", - arvif->vdev_id, info->txpower); +@@ -771,6 +771,7 @@ static void ath11k_pdev_caps_update(stru -- arvif->txpower = info->txpower; -- ath11k_mac_txpower_recalc(ar); -+ if (ar->supports_6ghz && info->chandef.chan && -+ info->chandef.chan->band == NL80211_BAND_6GHZ && -+ (arvif->vdev_type == WMI_VDEV_TYPE_STA || -+ arvif->vdev_type == WMI_VDEV_TYPE_AP) && -+ test_bit(WMI_TLV_SERVICE_EXT_TPC_REG_SUPPORT, -+ ar->ab->wmi_ab.svc_map)) { -+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, -+ "discard tx power, change to set TPC power\n"); -+ } else { -+ arvif->txpower = info->txpower; -+ ath11k_mac_txpower_recalc(ar); -+ } + ar->txpower_limit_2g = ar->max_tx_power; + ar->txpower_limit_5g = ar->max_tx_power; ++ ar->txpower_limit_6g = ar->max_tx_power; + ar->txpower_scale = WMI_HOST_TP_SCALE_MAX; + } + +@@ -941,6 +942,16 @@ static int ath11k_mac_txpower_recalc(str + ar->txpower_limit_5g = txpower; } - if (changed & BSS_CHANGED_MCAST_RATE && ++ if ((ar->hw->wiphy->bands[NL80211_BAND_6GHZ]) && ++ ar->txpower_limit_6g != txpower) { ++ param = WMI_PDEV_PARAM_TXPOWER_LIMIT5G; ++ ret = ath11k_wmi_pdev_set_param(ar, param, ++ txpower, ar->pdev->pdev_id); ++ if (ret) ++ goto fail; ++ ar->txpower_limit_6g = txpower; ++ } ++ + return 0; + + fail: +@@ -3700,7 +3711,6 @@ static void ath11k_mac_op_bss_info_chang + if (changed & BSS_CHANGED_TXPOWER) { + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev_id %i txpower %d\n", + arvif->vdev_id, info->txpower); +- + arvif->txpower = info->txpower; + ath11k_mac_txpower_recalc(ar); + } --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -2186,6 +2186,7 @@ enum wmi_tlv_service { +@@ -2175,6 +2175,7 @@ enum wmi_tlv_service { WMI_TLV_SERVICE_FSE_CMEM_ALLOC_SUPPORT = 262, WMI_TLV_SERVICE_PASSIVE_SCAN_START_TIME_ENHANCE = 263, WMI_TLV_SERVICE_QOS_NULL_FRAME_TX_OVER_WMI = 264, @@ -57,3 +69,13 @@ Signed-off-by: Aditya Kumar Singh WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281, WMI_TLV_SERVICE_DCS_AWGN_INT_SUPPORT = 286, WMI_TLV_SERVICE_DYN_NSS_MASK_SUPPORT = 303, +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -793,6 +793,7 @@ struct ath11k { + u32 max_tx_power; + u32 txpower_limit_2g; + u32 txpower_limit_5g; ++ u32 txpower_limit_6g; + u32 txpower_scale; + u32 power_scale; + u32 chan_tx_pwr; diff --git a/feeds/ipq95xx/mac80211/patches/qca/333-0017-ath11k-add-handler-for-WMI_VDEV_SET_TPC_POWER_CMDID.patch b/feeds/ipq95xx/mac80211/patches/qca/333-0017-ath11k-add-handler-for-WMI_VDEV_SET_TPC_POWER_CMDID.patch index 69d335d7f..62d49f133 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/333-0017-ath11k-add-handler-for-WMI_VDEV_SET_TPC_POWER_CMDID.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/333-0017-ath11k-add-handler-for-WMI_VDEV_SET_TPC_POWER_CMDID.patch @@ -13,11 +13,9 @@ Signed-off-by: Aditya Kumar Singh drivers/net/wireless/ath/ath11k/wmi.h | 61 +++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) -diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c -index 2ace82d..8584e7b 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -2712,6 +2712,69 @@ int ath11k_wmi_send_scan_start_cmd(struct ath11k *ar, +@@ -2809,6 +2809,69 @@ int ath11k_wmi_send_scan_start_cmd(struc return ret; } @@ -87,19 +85,17 @@ index 2ace82d..8584e7b 100644 int ath11k_wmi_send_scan_stop_cmd(struct ath11k *ar, struct scan_cancel_param *param) { -diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h -index e5ef378..e1ae11d 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -16,6 +16,7 @@ struct ath11k_smart_ant_info; - struct ath11k_smart_ant_node_config_params; - struct ath11k_smart_ant_train_info; +@@ -18,6 +18,7 @@ struct ath11k_smart_ant_train_info; struct ath11k_fw_stats; + struct ath11k_fw_dbglog; + struct ath11k_vif; +struct ath11k_reg_tpc_power_info; #define PSOC_HOST_MAX_NUM_SS (8) -@@ -327,6 +328,36 @@ enum wmi_tlv_cmd_id { +@@ -325,6 +326,36 @@ enum wmi_tlv_cmd_id { WMI_VDEV_SET_CUSTOM_AGGR_SIZE_CMDID, WMI_VDEV_ENCRYPT_DECRYPT_DATA_REQ_CMDID, WMI_VDEV_ADD_MAC_ADDR_TO_RX_FILTER_CMDID, @@ -136,7 +132,7 @@ index e5ef378..e1ae11d 100644 WMI_PEER_CREATE_CMDID = WMI_TLV_CMD(WMI_GRP_PEER), WMI_PEER_DELETE_CMDID, WMI_PEER_FLUSH_TIDS_CMDID, -@@ -1912,6 +1943,8 @@ enum wmi_tlv_tag { +@@ -1911,6 +1942,8 @@ enum wmi_tlv_tag { WMI_TAG_QOS_NULL_FRAME_TX_STATUS, WMI_TAG_REGULATORY_RULE_EXT_STRUCT = 0x3A9, WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT, @@ -145,7 +141,7 @@ index e5ef378..e1ae11d 100644 WMI_CTRL_PATH_CAL_STATS = 0x3BC, WMI_TAG_DCS_AWGN_INT_TYPE = 0x3C5, -@@ -3322,6 +3355,31 @@ struct wlan_ssid { +@@ -3305,6 +3338,31 @@ struct wlan_ssid { u8 ssid[WLAN_SSID_MAX_LEN]; }; @@ -177,14 +173,11 @@ index e5ef378..e1ae11d 100644 #define WMI_IE_BITMAP_SIZE 8 #define PROBE_REQ_MAX_OUIS 16 -@@ -6950,4 +7008,7 @@ int +@@ -7480,4 +7538,7 @@ int ath11k_wmi_peer_set_smart_ant_train_ant_param_cmd(struct ath11k *ar, - u32 vdev_id, const u8 *macaddr, - const struct wmi_peer_set_smart_ant_train_ant_fixed_param_cmd *arg); + u32 vdev_id, const u8 *macaddr, + const struct wmi_peer_set_smart_ant_train_ant_fixed_param_cmd *arg); +int ath11k_wmi_send_vdev_set_tpc_power(struct ath11k *ar, + u32 vdev_id, + struct ath11k_reg_tpc_power_info *param); #endif --- -2.7.4 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/333-002-mac80211-add-support-to-awgn-detection-and-mitigatio.patch b/feeds/ipq95xx/mac80211/patches/qca/333-002-mac80211-add-support-to-awgn-detection-and-mitigatio.patch index 1cdf5cb6b..81f7af58b 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/333-002-mac80211-add-support-to-awgn-detection-and-mitigatio.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/333-002-mac80211-add-support-to-awgn-detection-and-mitigatio.patch @@ -36,9 +36,9 @@ Signed-off-by: Hari Chandrakanthan Index: b/include/net/cfg80211.h =================================================================== ---- a/include/net/cfg80211.h 2022-11-26 12:57:21.206211895 +0530 -+++ b/include/net/cfg80211.h 2022-11-26 12:57:21.186212041 +0530 -@@ -7655,6 +7655,19 @@ cfg80211_background_radar_event(struct w +--- a/include/net/cfg80211.h 2022-11-28 20:29:10.512278346 +0530 ++++ b/include/net/cfg80211.h 2022-11-28 20:29:10.504278410 +0530 +@@ -8110,6 +8110,19 @@ cfg80211_background_radar_event(struct w } /** @@ -60,9 +60,9 @@ Index: b/include/net/cfg80211.h * @mac: MAC address of a station which opmode got modified Index: b/include/net/mac80211.h =================================================================== ---- a/include/net/mac80211.h 2022-11-26 12:57:21.206211895 +0530 -+++ b/include/net/mac80211.h 2022-11-26 12:57:21.194211983 +0530 -@@ -6212,9 +6212,10 @@ void ieee80211_channel_switch_disconnect +--- a/include/net/mac80211.h 2022-11-28 20:29:10.512278346 +0530 ++++ b/include/net/mac80211.h 2022-11-28 20:29:10.504278410 +0530 +@@ -6414,9 +6414,10 @@ void ieee80211_channel_switch_disconnect /** * ieee80211_awgn_detected - inform that awgn interference is detected * @@ -77,9 +77,9 @@ Index: b/include/net/mac80211.h * ieee80211_request_smps - request SM PS transition Index: b/include/uapi/linux/nl80211.h =================================================================== ---- a/include/uapi/linux/nl80211.h 2022-11-26 12:57:21.206211895 +0530 -+++ b/include/uapi/linux/nl80211.h 2022-11-26 12:57:21.194211983 +0530 -@@ -1241,6 +1241,11 @@ +--- a/include/uapi/linux/nl80211.h 2022-11-28 20:29:10.512278346 +0530 ++++ b/include/uapi/linux/nl80211.h 2022-11-28 20:29:10.508278378 +0530 +@@ -1277,6 +1277,11 @@ * This event is used to update dynamic MU-EDCA parameters in Beacon frame, * coming from driver and now need to be reflected in Beacon frame. * @@ -91,25 +91,25 @@ Index: b/include/uapi/linux/nl80211.h * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ -@@ -1483,6 +1488,8 @@ enum nl80211_commands { - NL80211_CMD_COLOR_CHANGE_ABORTED, - NL80211_CMD_COLOR_CHANGE_COMPLETED, +@@ -1529,6 +1534,8 @@ enum nl80211_commands { + NL80211_CMD_REMOVE_LINK_STA, -+ NL80211_CMD_AWGN_DETECT, + NL80211_CMD_UPDATE_HE_MUEDCA_PARAMS, + - NL80211_CMD_SET_FILS_AAD, ++ NL80211_CMD_AWGN_DETECT, + /* add new commands above here */ - NL80211_CMD_ASSOC_COMEBACK, -@@ -2670,6 +2677,8 @@ enum nl80211_commands { + /* used to define NL80211_CMD_MAX below */ +@@ -2751,6 +2758,8 @@ enum nl80211_commands { * @NL80211_ATTR_BEACON_TX_MODE: used to configure the beacon tx mode as - * staggered mode = 1 or burst mode = 2 in %NL80211_CMD_START_AP or - * %NL80211_CMD_JOIN_MESH from user-space. + * staggered mode = 1 or burst mode = 2 in %NL80211_CMD_START_AP or + * %NL80211_CMD_JOIN_MESH from user-space. + * @NL80211_ATTR_AWGN_INTERFERENCE_BITMAP: u32 attribute specifying the -+ * interference bitmap of operating bandwidth for %NL80211_CMD_AWGN_DETECT ++ * interference bitmap of operating bandwidth for %NL80211_CMD_AWGN_DETECT * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use -@@ -3188,6 +3197,8 @@ enum nl80211_attrs { +@@ -3287,6 +3296,8 @@ enum nl80211_attrs { NL80211_ATTR_STA_MGMT_RTS_CTS_CONFIG, @@ -120,18 +120,18 @@ Index: b/include/uapi/linux/nl80211.h __NL80211_ATTR_AFTER_LAST, Index: b/net/mac80211/ieee80211_i.h =================================================================== ---- a/net/mac80211/ieee80211_i.h 2022-11-26 12:57:21.206211895 +0530 -+++ b/net/mac80211/ieee80211_i.h 2022-11-26 12:57:21.194211983 +0530 -@@ -958,8 +958,6 @@ struct ieee80211_sub_if_data { - bool csa_block_tx; /* write-protected by sdata_lock and local->mtx */ +--- a/net/mac80211/ieee80211_i.h 2022-11-28 20:29:10.512278346 +0530 ++++ b/net/mac80211/ieee80211_i.h 2022-11-28 20:29:10.508278378 +0530 +@@ -978,8 +978,6 @@ struct ieee80211_link_data { + struct cfg80211_chan_def csa_chandef; - struct work_struct awgn_detected_work; - struct work_struct color_change_finalize_work; - struct list_head assigned_chanctx_list; /* protected by chanctx_mtx */ -@@ -1497,6 +1495,8 @@ struct ieee80211_local { + /* context reservation -- protected with chanctx_mtx */ +@@ -1564,6 +1562,8 @@ struct ieee80211_local { struct cfg80211_chan_def monitor_chandef; struct mac80211_memory_stats memory_stats; @@ -140,7 +140,7 @@ Index: b/net/mac80211/ieee80211_i.h /* extended capabilities provided by mac80211 */ u8 ext_capa[8]; -@@ -2474,6 +2474,7 @@ void ieee80211_dfs_cac_timer(unsigned lo +@@ -2477,6 +2477,7 @@ void ieee80211_dfs_cac_timer(unsigned lo void ieee80211_dfs_cac_timer_work(struct work_struct *work); void ieee80211_dfs_cac_cancel(struct ieee80211_local *local); void ieee80211_dfs_radar_detected_work(struct work_struct *work); @@ -150,29 +150,30 @@ Index: b/net/mac80211/ieee80211_i.h Index: b/net/mac80211/iface.c =================================================================== ---- a/net/mac80211/iface.c 2022-11-26 12:57:21.206211895 +0530 -+++ b/net/mac80211/iface.c 2022-11-26 12:57:21.202211924 +0530 -@@ -468,7 +468,6 @@ static void ieee80211_do_stop(struct iee +--- a/net/mac80211/iface.c 2022-11-28 20:29:10.512278346 +0530 ++++ b/net/mac80211/iface.c 2022-11-28 20:29:10.508278378 +0530 +@@ -400,8 +400,6 @@ static void ieee80211_link_init(struct i + + INIT_WORK(&link->csa_finalize_work, + ieee80211_csa_finalize_work); +- INIT_WORK(&sdata->awgn_detected_work, +- ieee80211_awgn_interference_detected_work); + INIT_WORK(&link->color_change_finalize_work, + ieee80211_color_change_finalize_work); + INIT_LIST_HEAD(&link->assigned_chanctx_list); +@@ -719,7 +717,6 @@ static void ieee80211_do_stop(struct iee sdata_unlock(sdata); - cancel_work_sync(&sdata->csa_finalize_work); + cancel_work_sync(&sdata->deflink.csa_finalize_work); - cancel_work_sync(&sdata->awgn_detected_work); - cancel_work_sync(&sdata->color_change_finalize_work); + cancel_work_sync(&sdata->deflink.color_change_finalize_work); - cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); -@@ -1749,7 +1748,6 @@ static void ieee80211_setup_sdata(struct - INIT_WORK(&sdata->work, ieee80211_iface_work); - INIT_WORK(&sdata->recalc_smps, ieee80211_recalc_smps_work); - INIT_WORK(&sdata->csa_finalize_work, ieee80211_csa_finalize_work); -- INIT_WORK(&sdata->awgn_detected_work, ieee80211_awgn_interference_detected_work); - INIT_WORK(&sdata->color_change_finalize_work, ieee80211_color_change_finalize_work); - INIT_LIST_HEAD(&sdata->assigned_chanctx_list); - INIT_LIST_HEAD(&sdata->reserved_chanctx_list); + cancel_delayed_work_sync(&sdata->deflink.dfs_cac_timer_work); Index: b/net/mac80211/main.c =================================================================== ---- a/net/mac80211/main.c 2022-11-26 12:57:21.206211895 +0530 -+++ b/net/mac80211/main.c 2022-11-26 12:57:21.202211924 +0530 -@@ -269,6 +269,7 @@ static void ieee80211_restart_work(struc +--- a/net/mac80211/main.c 2022-11-28 20:29:10.512278346 +0530 ++++ b/net/mac80211/main.c 2022-11-28 20:29:10.508278378 +0530 +@@ -349,6 +349,7 @@ static void ieee80211_restart_work(struc flush_workqueue(local->workqueue); flush_work(&local->sched_scan_stopped_work); flush_work(&local->radar_detected_work); @@ -180,7 +181,7 @@ Index: b/net/mac80211/main.c rtnl_lock(); /* we might do interface manipulations, so need both */ -@@ -735,6 +736,8 @@ struct ieee80211_hw *ieee80211_alloc_hw_ +@@ -816,6 +817,8 @@ struct ieee80211_hw *ieee80211_alloc_hw_ INIT_WORK(&local->radar_detected_work, ieee80211_dfs_radar_detected_work); @@ -189,7 +190,7 @@ Index: b/net/mac80211/main.c INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter); local->smps_mode = IEEE80211_SMPS_OFF; -@@ -1407,6 +1410,7 @@ void ieee80211_unregister_hw(struct ieee +@@ -1487,6 +1490,7 @@ void ieee80211_unregister_hw(struct ieee cancel_work_sync(&local->reconfig_filter); flush_work(&local->sched_scan_stopped_work); flush_work(&local->radar_detected_work); @@ -199,9 +200,9 @@ Index: b/net/mac80211/main.c rate_control_deinitialize(local); Index: b/net/mac80211/util.c =================================================================== ---- a/net/mac80211/util.c 2022-11-26 12:57:21.206211895 +0530 -+++ b/net/mac80211/util.c 2022-11-26 12:57:21.202211924 +0530 -@@ -3888,6 +3888,32 @@ void ieee80211_dfs_cac_cancel(struct iee +--- a/net/mac80211/util.c 2022-11-28 20:29:10.512278346 +0530 ++++ b/net/mac80211/util.c 2022-11-28 20:29:10.508278378 +0530 +@@ -4074,6 +4074,32 @@ void ieee80211_dfs_cac_cancel(struct iee mutex_unlock(&local->mtx); } @@ -234,7 +235,7 @@ Index: b/net/mac80211/util.c void ieee80211_dfs_radar_detected_work(struct work_struct *work) { struct ieee80211_local *local = -@@ -3927,6 +3953,15 @@ void ieee80211_radar_detected(struct iee +@@ -4113,6 +4139,15 @@ void ieee80211_radar_detected(struct iee } EXPORT_SYMBOL(ieee80211_radar_detected); @@ -247,10 +248,10 @@ Index: b/net/mac80211/util.c +} +EXPORT_SYMBOL(ieee80211_awgn_detected); + - u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c) + ieee80211_conn_flags_t ieee80211_chandef_downgrade(struct cfg80211_chan_def *c) { - u32 ret; -@@ -3992,32 +4027,6 @@ u32 ieee80211_chandef_downgrade(struct c + ieee80211_conn_flags_t ret; +@@ -4187,32 +4222,6 @@ ieee80211_conn_flags_t ieee80211_chandef return ret; } @@ -285,9 +286,9 @@ Index: b/net/mac80211/util.c * smps_mode_old. Index: b/net/wireless/mlme.c =================================================================== ---- a/net/wireless/mlme.c 2022-11-26 12:57:21.206211895 +0530 -+++ b/net/wireless/mlme.c 2022-11-26 12:57:21.202211924 +0530 -@@ -931,6 +931,15 @@ void __cfg80211_radar_event(struct wiphy +--- a/net/wireless/mlme.c 2022-11-28 20:29:10.512278346 +0530 ++++ b/net/wireless/mlme.c 2022-11-28 20:29:10.508278378 +0530 +@@ -962,6 +962,15 @@ void __cfg80211_radar_event(struct wiphy } EXPORT_SYMBOL(__cfg80211_radar_event); @@ -305,9 +306,9 @@ Index: b/net/wireless/mlme.c enum nl80211_radar_event event, gfp_t gfp) Index: b/net/wireless/nl80211.c =================================================================== ---- a/net/wireless/nl80211.c 2022-11-26 12:57:21.206211895 +0530 -+++ b/net/wireless/nl80211.c 2022-11-26 12:57:50.737997337 +0530 -@@ -806,6 +806,7 @@ static const struct nla_policy nl80211_p +--- a/net/wireless/nl80211.c 2022-11-28 20:29:10.512278346 +0530 ++++ b/net/wireless/nl80211.c 2022-11-28 20:36:33.216789284 +0530 +@@ -835,6 +835,7 @@ static const struct nla_policy nl80211_p [NL80211_ATTR_BEACON_TX_MODE] = NLA_POLICY_RANGE(NLA_U32, 1, 2), [NL80211_ATTR_STA_MGMT_RTS_CTS_CONFIG] = NLA_POLICY_MAX(NLA_U8, NL80211_MGMT_RTS_CTS_DISABLE), @@ -315,7 +316,7 @@ Index: b/net/wireless/nl80211.c }; /* policy for the key attributes */ -@@ -17965,6 +17966,55 @@ void cfg80211_ch_switch_notify(struct ne +@@ -19054,6 +19055,55 @@ void cfg80211_ch_switch_notify(struct ne } EXPORT_SYMBOL(cfg80211_ch_switch_notify); @@ -338,16 +339,16 @@ Index: b/net/wireless/nl80211.c + return; + } + -+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx)) -+ goto nla_put_failure; ++ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx)) ++ goto nla_put_failure; + + /* Radar and AWGN events don't need a netdev parameter */ + if (netdev) { + struct wireless_dev *wdev = netdev->ieee80211_ptr; + + if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || -+ nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev), -+ NL80211_ATTR_PAD)) ++ nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev), ++ NL80211_ATTR_PAD)) + goto nla_put_failure; + } + @@ -373,9 +374,9 @@ Index: b/net/wireless/nl80211.c u8 count, bool quiet) Index: b/net/wireless/nl80211.h =================================================================== ---- a/net/wireless/nl80211.h 2022-11-26 12:57:21.206211895 +0530 -+++ b/net/wireless/nl80211.h 2022-11-26 12:57:21.206211895 +0530 -@@ -116,6 +116,11 @@ nl80211_radar_notify(struct cfg80211_reg +--- a/net/wireless/nl80211.h 2022-11-28 20:29:10.512278346 +0530 ++++ b/net/wireless/nl80211.h 2022-11-28 20:29:10.512278346 +0530 +@@ -113,6 +113,11 @@ nl80211_radar_notify(struct cfg80211_reg enum nl80211_radar_event event, struct net_device *netdev, gfp_t gfp); diff --git a/feeds/ipq95xx/mac80211/patches/qca/333-0020-mac80211-add-support-for-6G-channels-and-regulatory.patch b/feeds/ipq95xx/mac80211/patches/qca/333-0020-mac80211-add-support-for-6G-channels-and-regulatory.patch index 245f7ea47..87ec27731 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/333-0020-mac80211-add-support-for-6G-channels-and-regulatory.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/333-0020-mac80211-add-support-for-6G-channels-and-regulatory.patch @@ -33,7 +33,7 @@ Signed-off-by: Aditya Kumar Singh --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h -@@ -2325,6 +2325,7 @@ struct ieee80211_he_6ghz_oper { +@@ -2569,6 +2569,7 @@ struct ieee80211_he_6ghz_oper { #define IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_160MHZ 3 #define IEEE80211_HE_6GHZ_OPER_CTRL_DUP_BEACON 0x4 #define IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO 0x38 @@ -43,7 +43,7 @@ Signed-off-by: Aditya Kumar Singh u8 ccfs1; --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h -@@ -453,6 +453,21 @@ struct ieee80211_sta_s1g_cap { +@@ -518,6 +518,21 @@ struct ieee80211_sta_s1g_cap { }; /** @@ -65,7 +65,7 @@ Signed-off-by: Aditya Kumar Singh * struct ieee80211_supported_band - frequency band definition * * This structure describes a frequency band a wiphy -@@ -460,6 +475,7 @@ struct ieee80211_sta_s1g_cap { +@@ -525,6 +540,7 @@ struct ieee80211_sta_s1g_cap { * * @channels: Array of channels the hardware can operate with * in this band. @@ -73,7 +73,7 @@ Signed-off-by: Aditya Kumar Singh * @band: the band this structure represents * @n_channels: Number of channels in @channels * @bitrates: Array of bitrates the hardware can operate with -@@ -479,6 +495,7 @@ struct ieee80211_sta_s1g_cap { +@@ -544,6 +560,7 @@ struct ieee80211_sta_s1g_cap { */ struct ieee80211_supported_band { struct ieee80211_channel *channels; @@ -81,15 +81,16 @@ Signed-off-by: Aditya Kumar Singh struct ieee80211_rate *bitrates; enum nl80211_band band; int n_channels; -@@ -5551,6 +5568,7 @@ struct wireless_dev { - struct work_struct pmsr_free_wk; - - unsigned long unprot_beacon_reported; +@@ -5848,6 +5865,8 @@ struct wireless_dev { + }; + } links[IEEE80211_MLD_MAX_NUM_LINKS]; + u16 valid_links; ++ + u8 reg_6g_power_mode; }; - static inline u8 *wdev_address(struct wireless_dev *wdev) -@@ -5683,6 +5701,19 @@ ieee80211_get_channel(struct wiphy *wiph + static inline const u8 *wdev_address(struct wireless_dev *wdev) +@@ -6006,6 +6025,19 @@ ieee80211_get_channel(struct wiphy *wiph } /** @@ -121,7 +122,7 @@ Signed-off-by: Aditya Kumar Singh bool has_wmm; --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h -@@ -3168,6 +3168,8 @@ enum nl80211_attrs { +@@ -3299,6 +3299,8 @@ enum nl80211_attrs { NL80211_ATTR_AWGN_INTERFERENCE_BITMAP, @@ -130,7 +131,7 @@ Signed-off-by: Aditya Kumar Singh /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, -@@ -3835,6 +3837,20 @@ enum nl80211_band_attr { +@@ -4046,6 +4048,20 @@ enum nl80211_band_attr { #define NL80211_BAND_ATTR_HT_CAPA NL80211_BAND_ATTR_HT_CAPA @@ -153,43 +154,46 @@ Signed-off-by: Aditya Kumar Singh * --- a/net/mac80211/util.c +++ b/net/mac80211/util.c -@@ -3375,10 +3375,13 @@ bool ieee80211_chandef_he_6ghz_oper(stru - const struct ieee80211_sta_he_cap *he_cap; +@@ -3571,9 +3571,12 @@ bool ieee80211_chandef_he_6ghz_oper(stru struct cfg80211_chan_def he_chandef = *chandef; const struct ieee80211_he_6ghz_oper *he_6ghz_oper; -+ enum nl80211_regulatory_power_modes mode; struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; - bool support_80_80, support_160; - u8 he_phy_cap; ++ enum nl80211_regulatory_power_modes mode; + bool support_80_80, support_160, support_320; + u8 he_phy_cap, eht_phy_cap; u32 freq; + u8 reg_info; + u8 reg_6g_power_mode; if (chandef->chan->band != NL80211_BAND_6GHZ) return true; -@@ -3415,9 +3418,29 @@ bool ieee80211_chandef_he_6ghz_oper(stru +@@ -3616,6 +3619,24 @@ bool ieee80211_chandef_he_6ghz_oper(stru return false; } + /* 6G Power mode present in the beacon */ + reg_info = (he_6ghz_oper->control & IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO) >> -+ IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO_LSB; ++ IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO_LSB; + + /* 6G Power mode configured by the user */ + reg_6g_power_mode = sdata->wdev.reg_6g_power_mode; + -+ /** ++ /* + * For AP/AP_VLAN/MESH_POINT interfaces, the 6G power mode depends on the + * mode configured by user (LPI/SP/VLP). For other interfaces (for ex STA) + * mode depends on the power mode present in beacon as well as power mode + * configured by the user for that interface + */ + if (iftype == NL80211_IFTYPE_AP || iftype == NL80211_IFTYPE_AP_VLAN || -+ iftype == NL80211_IFTYPE_MESH_POINT) { ++ iftype == NL80211_IFTYPE_MESH_POINT) + mode = reg_6g_power_mode; -+ } else ++ else + mode = 3 * (1 + reg_6g_power_mode) + reg_info; -+ + /* + * The EHT operation IE does not contain the primary channel so the + * primary channel frequency should be taken from the 6 GHz operation +@@ -3623,7 +3644,8 @@ bool ieee80211_chandef_he_6ghz_oper(stru + */ freq = ieee80211_channel_to_frequency(he_6ghz_oper->primary, NL80211_BAND_6GHZ); - he_chandef.chan = ieee80211_get_channel(sdata->local->hw.wiphy, freq); @@ -200,7 +204,7 @@ Signed-off-by: Aditya Kumar Singh IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO)) { --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c -@@ -803,6 +803,7 @@ static const struct nla_policy nl80211_p +@@ -836,6 +836,7 @@ static const struct nla_policy nl80211_p [NL80211_ATTR_STA_MGMT_RTS_CTS_CONFIG] = NLA_POLICY_MAX(NLA_U8, NL80211_MGMT_RTS_CTS_DISABLE), [NL80211_ATTR_AWGN_INTERFERENCE_BITMAP] = { .type = NLA_U32 }, @@ -208,7 +212,7 @@ Signed-off-by: Aditya Kumar Singh }; /* policy for the key attributes */ -@@ -3050,6 +3051,7 @@ int nl80211_parse_chandef(struct cfg8021 +@@ -3210,6 +3211,7 @@ int nl80211_parse_chandef(struct cfg8021 { struct netlink_ext_ack *extack = genl_info_extack(info); struct nlattr **attrs = info->attrs; @@ -216,7 +220,7 @@ Signed-off-by: Aditya Kumar Singh u32 control_freq; if (!attrs[NL80211_ATTR_WIPHY_FREQ]) -@@ -3061,8 +3063,19 @@ int nl80211_parse_chandef(struct cfg8021 +@@ -3221,8 +3223,19 @@ int nl80211_parse_chandef(struct cfg8021 control_freq += nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]); @@ -239,7 +243,7 @@ Signed-off-by: Aditya Kumar Singh chandef->freq1_offset = control_freq % 1000; --- a/net/wireless/reg.c +++ b/net/wireless/reg.c -@@ -1596,7 +1596,8 @@ static u32 map_regdom_flags(u32 rd_flags +@@ -1627,7 +1627,8 @@ static u32 map_regdom_flags(u32 rd_flags static const struct ieee80211_reg_rule * freq_reg_info_regd(u32 center_freq, @@ -249,7 +253,7 @@ Signed-off-by: Aditya Kumar Singh { int i; bool band_rule_found = false; -@@ -1610,7 +1611,12 @@ freq_reg_info_regd(u32 center_freq, +@@ -1641,7 +1642,12 @@ freq_reg_info_regd(u32 center_freq, const struct ieee80211_freq_range *fr = NULL; rr = ®d->reg_rules[i]; @@ -263,7 +267,7 @@ Signed-off-by: Aditya Kumar Singh /* * We only need to know if one frequency rule was -@@ -1642,7 +1648,7 @@ __freq_reg_info(struct wiphy *wiphy, u32 +@@ -1673,7 +1679,7 @@ __freq_reg_info(struct wiphy *wiphy, u32 u32 bw; for (bw = MHZ_TO_KHZ(bws[i]); bw >= min_bw; bw = MHZ_TO_KHZ(bws[i--])) { @@ -272,7 +276,7 @@ Signed-off-by: Aditya Kumar Singh if (!IS_ERR(reg_rule)) return reg_rule; } -@@ -2292,7 +2298,7 @@ static void reg_process_ht_flags_channel +@@ -2325,7 +2331,7 @@ static void reg_process_ht_flags_channel if (regd) { const struct ieee80211_reg_rule *reg_rule = freq_reg_info_regd(MHZ_TO_KHZ(channel->center_freq), @@ -281,7 +285,7 @@ Signed-off-by: Aditya Kumar Singh if (!IS_ERR(reg_rule)) flags = reg_rule->flags; -@@ -2502,7 +2508,8 @@ static void update_all_wiphy_regulatory( +@@ -2564,7 +2570,8 @@ static void update_all_wiphy_regulatory( static void handle_channel_custom(struct wiphy *wiphy, struct ieee80211_channel *chan, const struct ieee80211_regdomain *regd, @@ -291,7 +295,7 @@ Signed-off-by: Aditya Kumar Singh { u32 bw_flags = 0; const struct ieee80211_reg_rule *reg_rule = NULL; -@@ -2511,7 +2518,7 @@ static void handle_channel_custom(struct +@@ -2573,7 +2580,7 @@ static void handle_channel_custom(struct center_freq_khz = ieee80211_channel_to_khz(chan); for (bw = MHZ_TO_KHZ(20); bw >= min_bw; bw = bw / 2) { @@ -300,7 +304,7 @@ Signed-off-by: Aditya Kumar Singh if (!IS_ERR(reg_rule)) break; } -@@ -2564,10 +2571,20 @@ static void handle_band_custom(struct wi +@@ -2626,10 +2633,20 @@ static void handle_band_custom(struct wi const struct ieee80211_regdomain *regd) { unsigned int i; @@ -321,7 +325,7 @@ Signed-off-by: Aditya Kumar Singh /* * We currently assume that you always want at least 20 MHz, * otherwise channel 12 might get enabled if this rule is -@@ -2575,7 +2592,7 @@ static void handle_band_custom(struct wi +@@ -2637,7 +2654,7 @@ static void handle_band_custom(struct wi */ for (i = 0; i < sband->n_channels; i++) handle_channel_custom(wiphy, &sband->channels[i], regd, @@ -332,7 +336,7 @@ Signed-off-by: Aditya Kumar Singh /* Used by drivers prior to wiphy registration */ --- a/net/wireless/util.c +++ b/net/wireless/util.c -@@ -164,6 +164,30 @@ int ieee80211_freq_khz_to_channel(u32 fr +@@ -165,6 +165,30 @@ int ieee80211_freq_khz_to_channel(u32 fr } EXPORT_SYMBOL(ieee80211_freq_khz_to_channel); diff --git a/feeds/ipq95xx/mac80211/patches/qca/333-0022-cfg80211-add-6g-power-mode-advertisement-in-nl8.patch b/feeds/ipq95xx/mac80211/patches/qca/333-0022-cfg80211-add-6g-power-mode-advertisement-in-nl8.patch index 50bf2c347..2ba8e77cc 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/333-0022-cfg80211-add-6g-power-mode-advertisement-in-nl8.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/333-0022-cfg80211-add-6g-power-mode-advertisement-in-nl8.patch @@ -26,7 +26,7 @@ Signed-off-by: Aditya Kumar Singh --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h -@@ -4070,6 +4070,7 @@ enum nl80211_reg_type { +@@ -4297,6 +4297,7 @@ enum nl80211_reg_type { * If not present or 0 default CAC time will be used. * @NL80211_ATTR_POWER_RULE_PSD: power spectral density (in dBm). * This could be negative. @@ -34,7 +34,7 @@ Signed-off-by: Aditya Kumar Singh * @NL80211_REG_RULE_ATTR_MAX: highest regulatory rule attribute number * currently defined * @__NL80211_REG_RULE_ATTR_AFTER_LAST: internal use -@@ -4089,6 +4090,8 @@ enum nl80211_reg_rule_attr { +@@ -4316,6 +4317,8 @@ enum nl80211_reg_rule_attr { NL80211_ATTR_POWER_RULE_PSD, @@ -45,23 +45,21 @@ Signed-off-by: Aditya Kumar Singh NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c -@@ -3230,6 +3230,15 @@ static int __nl80211_set_channel(struct - result = -EINVAL; - } +@@ -3370,6 +3370,13 @@ static int __nl80211_set_channel(struct + if (result) + return result; + /* Userspace might advertise the 6G power mode (AP). Just parse and store + * it in wdev. No immediate action required. */ -+ if (info->attrs[NL80211_ATTR_6G_REG_POWER_MODE]) { -+ wdev_lock(wdev); ++ if (wdev && info->attrs[NL80211_ATTR_6G_REG_POWER_MODE]) { + wdev->reg_6g_power_mode = + nla_get_u8(info->attrs[NL80211_ATTR_6G_REG_POWER_MODE]); -+ wdev_unlock(wdev); + } + - return result; - } - -@@ -3970,6 +3979,17 @@ static int nl80211_set_interface(struct + switch (iftype) { + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_P2P_GO: +@@ -4180,6 +4187,17 @@ static int nl80211_set_interface(struct params.use_4addr = -1; } @@ -79,7 +77,7 @@ Signed-off-by: Aditya Kumar Singh err = nl80211_parse_mon_options(rdev, ntype, info, ¶ms); if (err < 0) return err; -@@ -7856,7 +7876,9 @@ static int nl80211_put_regdom(const stru +@@ -8335,7 +8353,9 @@ static int nl80211_put_regdom(const stru nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP, power_rule->max_eirp) || nla_put_u32(msg, NL80211_ATTR_DFS_CAC_TIME, diff --git a/feeds/ipq95xx/mac80211/patches/qca/334-ath11k-Add-support-to-threeway-coex.patch b/feeds/ipq95xx/mac80211/patches/qca/334-ath11k-Add-support-to-threeway-coex.patch index e755ac969..aea3cd49c 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/334-ath11k-Add-support-to-threeway-coex.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/334-ath11k-Add-support-to-threeway-coex.patch @@ -32,20 +32,18 @@ Signed-off-by: Hari Chandrakanthan drivers/net/wireless/ath/ath11k/wmi.h | 38 +++++++- 4 files changed, 253 insertions(+), 2 deletions(-) -diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h -index 5089c36..b9fafee 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -584,6 +584,8 @@ struct ath11k_dbg_htt_stats { - spinlock_t lock; - }; +@@ -772,6 +772,8 @@ struct ath11k_dbg_htt_stats { + + #define MAX_MODULE_ID_BITMAP_WORDS 16 +#define ATH11K_MAX_COEX_PRIORITY_LEVEL 3 + struct ath11k_debug { struct dentry *debugfs_pdev; struct ath11k_dbg_htt_stats htt_stats; -@@ -610,6 +612,7 @@ struct ath11k_debug { +@@ -801,6 +803,7 @@ struct ath11k_debug { struct ath11k_db_module_debug *module_debug[WMI_DIRECT_BUF_MAX]; bool disable_dynamic_bw; struct dentry *debugfs_smartant; @@ -53,11 +51,9 @@ index 5089c36..b9fafee 100644 }; struct ath11k_per_peer_tx_stats { -diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c -index 3cb3bda..69575f2 100644 --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -422,6 +422,68 @@ int wmi_ctrl_path_cal_stat(struct ath11k_vif *arvif, const char __user *ubuf, +@@ -463,6 +463,68 @@ int wmi_ctrl_path_cal_stat(struct ath11k return ret_val; } @@ -126,7 +122,7 @@ index 3cb3bda..69575f2 100644 static ssize_t ath11k_read_wmi_ctrl_path_stats(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) -@@ -439,6 +501,9 @@ static ssize_t ath11k_read_wmi_ctrl_path_stats(struct file *file, +@@ -480,6 +542,9 @@ static ssize_t ath11k_read_wmi_ctrl_path case WMI_CTRL_PATH_CAL_STATS: ret_val = wmi_ctrl_path_cal_stat(arvif, ubuf, count, ppos); break; @@ -136,7 +132,7 @@ index 3cb3bda..69575f2 100644 /* Add case for newly wmi ctrl path added stats here */ default : /* Unsupported tag */ -@@ -4335,6 +4400,93 @@ static const struct file_operations fops_medium_busy = { +@@ -4652,6 +4717,93 @@ static const struct file_operations fops .llseek = default_llseek, }; @@ -230,20 +226,18 @@ index 3cb3bda..69575f2 100644 int ath11k_debugfs_register(struct ath11k *ar) { struct ath11k_base *ab = ar->ab; -@@ -4446,6 +4598,8 @@ int ath11k_debugfs_register(struct ath11k *ar) +@@ -4767,6 +4919,8 @@ int ath11k_debugfs_register(struct ath11 ar->debug.debugfs_pdev, ar, &fops_ani_listen_period); debugfs_create_file("medium_busy", S_IRUSR, ar->debug.debugfs_pdev, ar, &fops_medium_busy); + debugfs_create_file("coex_priority", 0600, + ar->debug.debugfs_pdev, ar, &fops_coex_priority); - return 0; } -diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c -index d485bbe..a6ed07e 100644 + --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -1831,6 +1831,18 @@ static void ath11k_wmi_copy_coex_config(struct ath11k *ar, struct wmi_coex_confi +@@ -1866,6 +1866,18 @@ static void ath11k_wmi_copy_coex_config( coex_config->vdev_id, coex_config->coex_algo); } @@ -262,7 +256,7 @@ index d485bbe..a6ed07e 100644 } int ath11k_send_coex_config_cmd(struct ath11k *ar, -@@ -3140,6 +3152,7 @@ ath11k_wmi_send_wmi_ctrl_stats_cmd(struct ath11k *ar, +@@ -3890,6 +3902,7 @@ ath11k_wmi_send_wmi_ctrl_stats_cmd(struc num_pdev_idx++; break; case WMI_REQ_CTRL_PATH_CAL_STAT: @@ -270,7 +264,7 @@ index d485bbe..a6ed07e 100644 pdev_id_array[num_pdev_idx] = ar->pdev->pdev_id; stats_id = (1 << param->stats_id); num_pdev_idx++; -@@ -4444,7 +4457,9 @@ static int ath11k_init_cmd_send(struct ath11k_pdev_wmi *wmi, +@@ -4685,7 +4698,9 @@ static int ath11k_init_cmd_send(struct a struct wmi_pdev_band_to_mac *band_to_mac; struct wlan_host_mem_chunk *host_mem_chunks; struct wmi_tlv *tlv; @@ -280,7 +274,7 @@ index d485bbe..a6ed07e 100644 void *ptr; u32 hw_mode_len = 0; u16 idx; -@@ -4470,6 +4485,9 @@ static int ath11k_init_cmd_send(struct ath11k_pdev_wmi *wmi, +@@ -4711,6 +4726,9 @@ static int ath11k_init_cmd_send(struct a ath11k_wmi_copy_resource_config(cfg, param->res_cfg); @@ -290,7 +284,7 @@ index d485bbe..a6ed07e 100644 cfg->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_RESOURCE_CONFIG) | FIELD_PREP(WMI_TLV_LEN, sizeof(*cfg) - TLV_HDR_SIZE); -@@ -7815,6 +7833,42 @@ int wmi_print_ctrl_path_cal_stats_tlv(struct ath11k_base *ab, u16 len, +@@ -8470,6 +8488,42 @@ int wmi_print_ctrl_path_cal_stats_tlv(st return 0; } @@ -333,7 +327,7 @@ index d485bbe..a6ed07e 100644 static int ath11k_wmi_ctrl_stats_subtlv_parser(struct ath11k_base *ab, u16 tag, u16 len, const void *ptr, void *data) -@@ -7830,10 +7884,14 @@ static int ath11k_wmi_ctrl_stats_subtlv_parser(struct ath11k_base *ab, +@@ -8485,10 +8539,14 @@ static int ath11k_wmi_ctrl_stats_subtlv_ case WMI_CTRL_PATH_CAL_STATS: ret = wmi_print_ctrl_path_cal_stats_tlv(ab, len, ptr, data); break; @@ -349,19 +343,17 @@ index d485bbe..a6ed07e 100644 return -EINVAL; break; } -diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h -index e7101f0..0148b55 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -1915,6 +1915,7 @@ enum wmi_tlv_tag { - - WMI_CTRL_PATH_CAL_STATS = 0x3BC, +@@ -1949,6 +1949,7 @@ enum wmi_tlv_tag { WMI_TAG_DCS_AWGN_INT_TYPE = 0x3C5, + WMI_TAG_PDEV_SET_BIOS_SAR_TABLE_CMD = 0x3D8, + WMI_TAG_PDEV_SET_BIOS_GEO_TABLE_CMD, + WMI_CTRL_PATH_BTCOEX_STATS = 0x3FD, - WMI_TAG_MAX }; -@@ -2413,6 +2414,8 @@ struct wmi_init_cmd { + +@@ -2448,6 +2449,8 @@ struct wmi_init_cmd { #define WMI_RSRC_CFG_FLAG1_ACK_RSSI BIT(18) #define WMI_RSRC_CFG_HOST_SERVICE_FLAG_REG_CC_EXT_SUPPORT_BIT 4 #define WMI_RSRC_CFG_FLAG_PEER_TID_EXT BIT(22) @@ -370,7 +362,7 @@ index e7101f0..0148b55 100644 struct wmi_resource_config { u32 tlv_header; -@@ -5413,6 +5416,8 @@ enum wmi_coex_config_type { +@@ -5509,6 +5512,8 @@ enum wmi_coex_config_type { WMI_COEX_CONFIG_WLAN_SCAN_PRIORITY = 15, WMI_COEX_CONFIG_WLAN_PKT_PRIORITY = 16, WMI_COEX_CONFIG_PTA_INTERFACE = 17, @@ -379,7 +371,7 @@ index e7101f0..0148b55 100644 /* WMI_COEX_CONFIG_FORCED_ALGO * config to select coex algorithm * coex_algo: select fixed coex algorithm -@@ -5450,6 +5455,14 @@ struct coex_config_arg { +@@ -5546,6 +5551,14 @@ struct coex_config_arg { struct { u32 coex_algo; }; @@ -394,7 +386,7 @@ index e7101f0..0148b55 100644 }; }; -@@ -5486,6 +5499,15 @@ struct wmi_coex_config_cmd { +@@ -5582,6 +5595,15 @@ struct wmi_coex_config_cmd { struct { u32 coex_algo; } __packed; @@ -410,7 +402,7 @@ index e7101f0..0148b55 100644 } __packed; } __packed; -@@ -5866,7 +5888,6 @@ struct wmi_ctrl_path_stats_cmd_param { +@@ -5962,7 +5984,6 @@ struct wmi_ctrl_path_stats_cmd_param { u32 action; }; @@ -418,7 +410,7 @@ index e7101f0..0148b55 100644 struct wmi_ctrl_path_stats_ev_param { u32 req_id; /* more flag -@@ -5892,6 +5913,7 @@ enum wmi_ctrl_path_stats_id { +@@ -5988,6 +6009,7 @@ enum wmi_ctrl_path_stats_id { WMI_REQ_CTRL_PATH_VDEV_EXTD_STAT = 2, WMI_REQ_CTRL_PATH_MEM_STAT = 3, WMI_REQ_CTRL_PATH_CAL_STAT = 5, @@ -426,7 +418,7 @@ index e7101f0..0148b55 100644 }; enum wmi_ctrl_path_stats_action { -@@ -5902,6 +5924,20 @@ enum wmi_ctrl_path_stats_action { +@@ -5998,6 +6020,20 @@ enum wmi_ctrl_path_stats_action { WMI_REQ_CTRL_PATH_STAT_STOP = 4, }; @@ -447,6 +439,3 @@ index e7101f0..0148b55 100644 struct wmi_obss_spatial_reuse_params_cmd { u32 tlv_header; u32 pdev_id; --- -2.7.4 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/335-0001-ath11k-optimize-tx-completions.patch b/feeds/ipq95xx/mac80211/patches/qca/335-0001-ath11k-optimize-tx-completions.patch index e565555ca..9c74fea78 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/335-0001-ath11k-optimize-tx-completions.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/335-0001-ath11k-optimize-tx-completions.patch @@ -13,7 +13,7 @@ Signed-off-by: Venkateswara Naralasetty --- a/drivers/net/wireless/ath/ath11k/dp_tx.c +++ b/drivers/net/wireless/ath/ath11k/dp_tx.c -@@ -623,10 +623,41 @@ err_out: +@@ -633,10 +633,41 @@ err_out: spin_unlock_bh(&ab->base_lock); } @@ -56,22 +56,22 @@ Signed-off-by: Venkateswara Naralasetty + enum hal_wbm_rel_src_module buf_rel_source) { struct ieee80211_tx_status status = { 0 }; - struct ath11k_base *ab = ar->ab; -@@ -637,9 +668,12 @@ static void ath11k_dp_tx_complete_msdu(s + struct ieee80211_rate_status status_rate = { 0 }; +@@ -648,9 +679,12 @@ static void ath11k_dp_tx_complete_msdu(s + struct rate_info rate; struct ieee80211_vif *vif = NULL; struct ath11k_vif *arvif = NULL; - struct rate_info rate; + struct hal_tx_status ts = { 0 }; + enum hal_wbm_htt_tx_comp_status wbm_status; + enum hal_wbm_tqm_rel_reason rel_status; u8 flags = 0; -- if (unlikely(WARN_ON_ONCE(ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM))) { +- if (WARN_ON_ONCE(ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM)) { + if (unlikely(WARN_ON_ONCE(buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM))) { /* Must not happen */ return; } -@@ -650,11 +684,14 @@ static void ath11k_dp_tx_complete_msdu(s +@@ -661,11 +695,14 @@ static void ath11k_dp_tx_complete_msdu(s flags = skb_cb->flags; @@ -88,7 +88,7 @@ Signed-off-by: Venkateswara Naralasetty } if (skb_has_frag_list(msdu)) { kfree_skb_list(skb_shinfo(msdu)->frag_list); -@@ -664,6 +701,8 @@ static void ath11k_dp_tx_complete_msdu(s +@@ -675,6 +712,8 @@ static void ath11k_dp_tx_complete_msdu(s return; } @@ -97,7 +97,7 @@ Signed-off-by: Venkateswara Naralasetty if (unlikely(!rcu_access_pointer(ab->pdevs_active[ar->pdev_idx]))) { dev_kfree_skb_any(msdu); return; -@@ -674,6 +713,9 @@ static void ath11k_dp_tx_complete_msdu(s +@@ -685,6 +724,9 @@ static void ath11k_dp_tx_complete_msdu(s return; } @@ -107,7 +107,7 @@ Signed-off-by: Venkateswara Naralasetty vif = skb_cb->vif; arvif = (void *)vif->drv_priv; if(arvif && wbm_status < HAL_WBM_REL_HTT_TX_COMP_STATUS_MAX) -@@ -685,42 +727,42 @@ static void ath11k_dp_tx_complete_msdu(s +@@ -696,50 +738,50 @@ static void ath11k_dp_tx_complete_msdu(s /* skip tx rate update from ieee80211_status*/ info->status.rates[0].idx = -1; @@ -119,7 +119,7 @@ Signed-off-by: Venkateswara Naralasetty info->status.ack_signal = ATH11K_DEFAULT_NOISE_FLOOR + - ts->ack_rssi; + ts.ack_rssi; - info->status.is_valid_ack_signal = true; + info->status.flags |= IEEE80211_TX_STATUS_ACK_SIGNAL_VALID; } - if (ts->status == HAL_WBM_TQM_REL_REASON_CMD_REMOVE_TX && @@ -159,10 +159,6 @@ Signed-off-by: Venkateswara Naralasetty + ath11k_dp_tx_cache_peer_stats(ar, msdu, &ts); } - /* NOTE: Tx rate status reporting. Tx completion status does not have -@@ -729,11 +771,11 @@ static void ath11k_dp_tx_complete_msdu(s - */ - spin_lock_bh(&ab->base_lock); - peer = ath11k_peer_find_by_id(ab, ts->peer_id); + peer = ath11k_peer_find_by_id(ab, ts.peer_id); @@ -174,17 +170,17 @@ Signed-off-by: Venkateswara Naralasetty spin_unlock_bh(&ab->base_lock); dev_kfree_skb_any(msdu); return; -@@ -745,7 +787,7 @@ static void ath11k_dp_tx_complete_msdu(s - rate = arsta->last_txrate; - status.rate = &rate; +@@ -756,7 +798,7 @@ static void ath11k_dp_tx_complete_msdu(s + status.rates = &status_rate; + status.n_rates = 1; - if (ts->status != HAL_WBM_TQM_REL_REASON_FRAME_ACKED) { + if (ts.status != HAL_WBM_TQM_REL_REASON_FRAME_ACKED) { arsta->fail_pkts += 1; arsta->per_fail_pkts += 1; arsta->fail_bytes += msdu->len; -@@ -773,37 +815,6 @@ static void ath11k_dp_tx_complete_msdu(s - return; +@@ -782,37 +824,6 @@ static void ath11k_dp_tx_complete_msdu(s + ieee80211_tx_status_ext(ar->hw, &status); } -static inline void ath11k_dp_tx_status_parse(struct ath11k_base *ab, @@ -221,7 +217,7 @@ Signed-off-by: Venkateswara Naralasetty static inline bool ath11k_dp_tx_completion_valid(struct hal_wbm_release_ring *desc) { struct htt_tx_wbm_completion *status_desc; -@@ -827,10 +838,9 @@ void ath11k_dp_tx_completion_handler(str +@@ -836,10 +847,9 @@ void ath11k_dp_tx_completion_handler(str int hal_ring_id = dp->tx_ring[ring_id].tcl_comp_ring.ring_id, count = 0, i = 0; struct hal_srng *status_ring = &ab->hal.srng_list[hal_ring_id]; struct sk_buff *msdu; @@ -233,7 +229,7 @@ Signed-off-by: Venkateswara Naralasetty u32 *desc; u32 msdu_id, desc_id; u8 mac_id; -@@ -870,17 +880,16 @@ void ath11k_dp_tx_completion_handler(str +@@ -879,17 +889,16 @@ void ath11k_dp_tx_completion_handler(str while (count--) { tx_status = &tx_ring->tx_status[i++]; @@ -254,7 +250,7 @@ Signed-off-by: Venkateswara Naralasetty ath11k_dp_tx_process_htt_tx_complete(ab, (void *)tx_status, mac_id, msdu_id, -@@ -904,7 +913,7 @@ void ath11k_dp_tx_completion_handler(str +@@ -913,7 +922,7 @@ void ath11k_dp_tx_completion_handler(str if (atomic_dec_and_test(&ar->dp.num_tx_pending)) wake_up(&ar->dp.tx_empty_waitq); diff --git a/feeds/ipq95xx/mac80211/patches/qca/335-0004-ath11k-use-single-TCL-ring-for-tx.patch b/feeds/ipq95xx/mac80211/patches/qca/335-0004-ath11k-use-single-TCL-ring-for-tx.patch index ccafcdee5..686d08100 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/335-0004-ath11k-use-single-TCL-ring-for-tx.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/335-0004-ath11k-use-single-TCL-ring-for-tx.patch @@ -13,21 +13,21 @@ Signed-off-by: Venkateswara Naralasetty --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -604,7 +604,7 @@ static const struct ath11k_hw_params ath - /* csi_cfr_header + cfr header + max cfr payload */ - .cfr_stream_buf_size = 8500, +@@ -717,7 +717,7 @@ static const struct ath11k_hw_params ath + .support_off_channel_tx = false, + .is_qdss_support = false, /* In addition to TCL ring use TCL_CMD ring also for tx */ - .max_tx_ring = DP_TCL_NUM_RING_MAX, + .max_tx_ring = 1, - .reo_status_poll = false, .num_vdevs_peers = ath11k_vdevs_peers_ipq5018, .cfr_support = true, -@@ -670,7 +670,7 @@ static const struct ath11k_hw_params ath - .ce_fwlog_enable = false, - .fwmem_mode_change = false, - .is_qdss_support = false, + .cfr_dma_hdr_size = sizeof(struct ath11k_cfir_dma_hdr), +@@ -799,7 +799,7 @@ static const struct ath11k_hw_params ath + .m3_offset = ATH11K_QMI_QCN6122_M3_OFFSET, + .qdss_offset = ATH11K_QMI_QCN6122_QDSS_OFFSET, + .caldb_offset = ATH11K_QMI_QCN6122_CALDB_OFFSET, - .max_tx_ring = DP_TCL_NUM_RING_MAX, + .max_tx_ring = 1, - .reo_status_poll = false, .num_vdevs_peers = ath11k_vdevs_peers_ipq5018, .cfr_support = true, + .cfr_dma_hdr_size = sizeof(struct ath11k_cfir_enh_dma_hdr), diff --git a/feeds/ipq95xx/mac80211/patches/qca/335-0005-mac80211-simple-tx-for-AP-mode.patch b/feeds/ipq95xx/mac80211/patches/qca/335-0005-mac80211-simple-tx-for-AP-mode.patch index 5c8f6adb4..5f080e13d 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/335-0005-mac80211-simple-tx-for-AP-mode.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/335-0005-mac80211-simple-tx-for-AP-mode.patch @@ -7,13 +7,14 @@ Introduced new API ieee80211_8023_xmit_ap to make tx simple and to avoid unnecessary checks for AP mode. Signed-off-by: Venkateswara Naralasetty +Signed-off-by: Aloka Dixit --- net/mac80211/tx.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c -@@ -4360,6 +4360,61 @@ out_free: +@@ -4643,6 +4643,72 @@ out_free: kfree_skb(skb); } @@ -21,7 +22,7 @@ Signed-off-by: Venkateswara Naralasetty + struct net_device *dev, struct sta_info *sta, + struct ieee80211_key *key, struct sk_buff *skb) +{ -+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); ++ struct ieee80211_tx_info *info; + struct ieee80211_local *local = sdata->local; + struct ieee80211_sta *pubsta = NULL; + struct ieee80211_tx_control control = {}; @@ -29,6 +30,15 @@ Signed-off-by: Venkateswara Naralasetty + int q; + u16 q_map; + ++ /* ++ * If the skb is shared we need to obtain our own copy. ++ */ ++ skb = skb_share_check(skb, GFP_ATOMIC); ++ ++ if (unlikely(!skb)) ++ return; ++ ++ info = IEEE80211_SKB_CB(skb); + memset(info, 0, sizeof(*info)); + + if (unlikely(skb->sk && @@ -46,11 +56,13 @@ Signed-off-by: Venkateswara Naralasetty + q = sdata->vif.hw_queue[q_map]; + + if (sta) { -+ sta->tx_stats.bytes[q_map] += skb->len; -+ sta->tx_stats.packets[q_map]++; ++ sta->deflink.tx_stats.bytes[q_map] += skb->len; ++ sta->deflink.tx_stats.packets[q_map]++; + atomic_inc(&sta->tx_netif_pkts); + } + ++ ieee80211_tx_stats(dev, skb->len); ++ + spin_lock_irqsave(&local->queue_stop_reason_lock, flags); + + if (local->queue_stop_reasons[q] || !skb_queue_empty(&local->pending[q])) { @@ -60,7 +72,7 @@ Signed-off-by: Venkateswara Naralasetty + } + + spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); -+ ++ + if (sta && sta->uploaded) + pubsta = &sta->sta; + @@ -75,7 +87,7 @@ Signed-off-by: Venkateswara Naralasetty netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb, struct net_device *dev) { -@@ -4399,6 +4454,11 @@ netdev_tx_t ieee80211_subif_start_xmit_8 +@@ -4682,6 +4748,11 @@ netdev_tx_t ieee80211_subif_start_xmit_8 if (key && (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))) goto skip_offload; diff --git a/feeds/ipq95xx/mac80211/patches/qca/335-mac80211-Mesh-Fast-xmit-support.patch b/feeds/ipq95xx/mac80211/patches/qca/335-mac80211-Mesh-Fast-xmit-support.patch index 70b359ba0..5e6790871 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/335-mac80211-Mesh-Fast-xmit-support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/335-mac80211-Mesh-Fast-xmit-support.patch @@ -25,17 +25,17 @@ Signed-off-by: Sriram R --- a/include/net/mac80211.h +++ b/include/net/mac80211.h -@@ -914,6 +914,7 @@ enum mac80211_tx_control_flags { - IEEE80211_TX_INTCFL_NEED_TXPROCESSING = BIT(6), +@@ -939,6 +939,7 @@ enum mac80211_tx_control_flags { IEEE80211_TX_CTRL_NO_SEQNO = BIT(7), IEEE80211_TX_CTRL_DONT_REORDER = BIT(8), -+ IEEE80211_TX_CTRL_CHECK_FAST_MESH = BIT(9), + IEEE80211_TX_CTRL_MCAST_MLO_FIRST_TX = BIT(9), ++ IEEE80211_TX_CTRL_CHECK_FAST_MESH = BIT(10), + IEEE80211_TX_CTRL_MLO_LINK = 0xf0000000, }; - /* --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h -@@ -754,6 +754,7 @@ struct ieee80211_if_mesh { +@@ -740,6 +740,7 @@ struct ieee80211_if_mesh { struct mesh_table mpp_paths; /* Store paths for MPP&MAP */ int mesh_paths_generation; int mpp_paths_generation; @@ -45,7 +45,7 @@ Signed-off-by: Sriram R #ifdef CPTCFG_MAC80211_MESH --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c -@@ -787,6 +787,8 @@ static void ieee80211_mesh_housekeeping( +@@ -788,6 +788,8 @@ static void ieee80211_mesh_housekeeping( changed = mesh_accept_plinks_update(sdata); ieee80211_mbss_info_change_notify(sdata, changed); @@ -118,7 +118,7 @@ Signed-off-by: Sriram R static inline u32 u32_field_get(const u8 *preq_elem, int offset, bool ae) { if (ae) -@@ -1064,7 +1062,7 @@ free: +@@ -1074,7 +1072,7 @@ free: * Locking: the function must be called from within a rcu read lock block. * */ @@ -127,7 +127,7 @@ Signed-off-by: Sriram R { struct ieee80211_sub_if_data *sdata = mpath->sdata; struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; -@@ -1334,6 +1332,7 @@ int mesh_nexthop_lookup(struct ieee80211 +@@ -1344,6 +1342,7 @@ int mesh_nexthop_lookup(struct ieee80211 if (!mpath || !(mpath->flags & MESH_PATH_ACTIVE)) return -ENOENT; @@ -135,7 +135,7 @@ Signed-off-by: Sriram R if (time_after(jiffies, mpath->exp_time - msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) && -@@ -1347,6 +1346,10 @@ int mesh_nexthop_lookup(struct ieee80211 +@@ -1357,6 +1356,10 @@ int mesh_nexthop_lookup(struct ieee80211 memcpy(hdr->addr1, next_hop->sta.addr, ETH_ALEN); memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN); ieee80211_mps_set_frame_flags(sdata, next_hop, hdr); @@ -220,7 +220,7 @@ Signed-off-by: Sriram R static inline bool mpath_expired(struct mesh_path *mpath) { return (mpath->flags & MESH_PATH_ACTIVE) && -@@ -455,6 +513,348 @@ struct mesh_path *mesh_path_new(struct i +@@ -455,6 +513,335 @@ struct mesh_path *mesh_path_new(struct i return new_mpath; } @@ -276,19 +276,6 @@ Signed-off-by: Sriram R + if (mpath_expired(mpath)) + return NULL; + -+ /* -+ * If the skb is shared we need to obtain our own copy. -+ */ -+ if (skb_shared(skb)) { -+ struct sk_buff *tmp_skb = skb; -+ -+ skb = skb_clone(skb, GFP_ATOMIC); -+ kfree_skb(tmp_skb); -+ -+ if (!skb) -+ return NULL; -+ } -+ + /* In case there was a path refresh and update after we last used + * update the next hop addr. + */ @@ -569,7 +556,7 @@ Signed-off-by: Sriram R struct mesh_path *__mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst) { -@@ -482,6 +882,7 @@ struct mesh_path *__mesh_path_add(struct +@@ -482,6 +869,7 @@ struct mesh_path *__mesh_path_add(struct mesh_rht_params); if (!mpath) hlist_add_head(&new_mpath->walk_list, &tbl->walk_head); @@ -577,7 +564,7 @@ Signed-off-by: Sriram R spin_unlock_bh(&tbl->walk_lock); if (mpath) { -@@ -667,8 +1068,11 @@ static void __mesh_path_del(struct mesh_ +@@ -666,8 +1054,11 @@ static void __mesh_path_del(struct mesh_ if (next_hop) ether_addr_copy(path.next_hop, next_hop->addr); @@ -589,7 +576,7 @@ Signed-off-by: Sriram R mesh_path_free_rcu(tbl, mpath); drv_config_mesh_offload_path(sdata->local, sdata, -@@ -901,6 +1305,8 @@ void mesh_path_fix_nexthop(struct mesh_p +@@ -900,6 +1291,8 @@ void mesh_path_fix_nexthop(struct mesh_p mpath->exp_time = 0; mpath->flags = MESH_PATH_FIXED | MESH_PATH_SN_VALID; mesh_path_activate(mpath); @@ -598,7 +585,7 @@ Signed-off-by: Sriram R spin_unlock_bh(&mpath->state_lock); ewma_mesh_fail_avg_init(&next_hop->mesh->fail_avg); /* init it at a low value - 0 start is tricky */ -@@ -912,6 +1318,7 @@ void mesh_path_fix_nexthop(struct mesh_p +@@ -911,6 +1304,7 @@ void mesh_path_fix_nexthop(struct mesh_p void mesh_pathtbl_init(struct ieee80211_sub_if_data *sdata) { @@ -606,7 +593,7 @@ Signed-off-by: Sriram R mesh_table_init(&sdata->u.mesh.mesh_paths); mesh_table_init(&sdata->u.mesh.mpp_paths); } -@@ -943,4 +1350,5 @@ void mesh_pathtbl_unregister(struct ieee +@@ -942,4 +1336,5 @@ void mesh_pathtbl_unregister(struct ieee { mesh_table_free(&sdata->u.mesh.mesh_paths); mesh_table_free(&sdata->u.mesh.mpp_paths); @@ -614,7 +601,7 @@ Signed-off-by: Sriram R } --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c -@@ -3014,6 +3014,10 @@ ieee80211_rx_h_mesh_fwding(struct ieee80 +@@ -3008,6 +3008,10 @@ ieee80211_rx_h_mesh_fwding(struct ieee80 mesh_nss_offld_path_update(mppath, false, NULL); } rcu_read_unlock(); @@ -627,7 +614,7 @@ Signed-off-by: Sriram R /* Frame has reached destination. Don't forward */ --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c -@@ -2715,18 +2715,24 @@ static struct sk_buff *ieee80211_build_h +@@ -2747,16 +2747,20 @@ static struct sk_buff *ieee80211_build_h hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, mesh_da, sdata->vif.addr); @@ -643,18 +630,14 @@ Signed-off-by: Sriram R meshhdrlen = ieee80211_new_mesh_header( sdata, &mesh_hdr, skb->data, skb->data + ETH_ALEN); - + /* cache unicast proxy headers */ + if ((ethertype >= ETH_P_802_3_MIN)) + ctrl_flags |= IEEE80211_TX_CTRL_CHECK_FAST_MESH; + } -+ + } -+ - chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); - if (!chanctx_conf) { - ret = -ENOTCONN; -@@ -3537,6 +3543,82 @@ ieee80211_xmit_fast_finish(struct ieee80 + +@@ -3584,6 +3588,82 @@ ieee80211_xmit_fast_finish(struct ieee80 return TX_CONTINUE; } @@ -737,13 +720,21 @@ Signed-off-by: Sriram R static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata, struct sta_info *sta, struct ieee80211_fast_tx *fast_tx, -@@ -4218,6 +4300,10 @@ void __ieee80211_subif_start_xmit(struct +@@ -4180,6 +4260,18 @@ void __ieee80211_subif_start_xmit(struct rcu_read_lock(); -+ if (ieee80211_vif_is_mesh(&sdata->vif) && -+ ieee80211_mesh_xmit_fast(sdata, skb, ctrl_flags)) -+ goto out; ++ if (ieee80211_vif_is_mesh(&sdata->vif)) { ++ /* ++ * If the skb is shared we need to obtain our own copy. ++ */ ++ skb = skb_share_check(skb, GFP_ATOMIC); ++ if (unlikely(!skb)) ++ goto out; ++ ++ if (ieee80211_mesh_xmit_fast(sdata, skb, ctrl_flags)) ++ goto out; ++ } + if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) goto out_free; diff --git a/feeds/ipq95xx/mac80211/patches/qca/336-ath11k-fix-kernel-panic-during-unload-load-ath11k.patch b/feeds/ipq95xx/mac80211/patches/qca/336-ath11k-fix-kernel-panic-during-unload-load-ath11k.patch deleted file mode 100644 index b400e572d..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/336-ath11k-fix-kernel-panic-during-unload-load-ath11k.patch +++ /dev/null @@ -1,74 +0,0 @@ -From c66e156226b0964f0d19d8bcd56867134013e6e8 Mon Sep 17 00:00:00 2001 -From: Venkateswara Naralasetty -Date: Wed, 1 Dec 2021 21:11:17 +0530 -Subject: [PATCH] ath11k: fix kernel panic during unload/load ath11k - -netif_napi_del() is not called during ath11k_ahb_free_ext_irq() -causing kernel panic with unload/load ath11k modules for -few itterations. - -[ 1164.317442] Unable to handle kernel paging request at virtual address deadbeafdeadbebf -[ 1164.325256] Mem abort info: -[ 1164.333027] ESR = 0x96000004 -[ 1164.335655] EC = 0x25: DABT (current EL), IL = 32 bits -[ 1164.338828] SET = 0, FnV = 0 -[ 1164.344242] EA = 0, S1PTW = 0 -[ 1164.347166] Data abort info: -[ 1164.350147] ISV = 0, ISS = 0x00000004 -[ 1164.353269] CM = 0, WnR = 0 -[ 1164.356889] [deadbeafdeadbebf] address between user and kernel address ranges -[ 1164.359965] Internal error: Oops: 96000004 [#1] PREEMPT SMP -[ 1164.571239] CPU: 1 PID: 27721 Comm: insmod Not tainted 5.4.89 #0 -[ 1164.593462] Hardware name: Qualcomm Technologies, Inc. IPQ5018/AP-MP03.5-C2 (DT) -[ 1164.599543] pstate: a0400005 (NzCv daif +PAN -UAO) -[ 1164.606927] pc : napi_by_id+0x1c/0x44 -[ 1164.611520] lr : netif_napi_add+0x1b8/0x228 - -[ 1164.696933] Call trace: -[ 1164.702231] napi_by_id+0x1c/0x44 -[ 1164.704407] ath11k_pci_ext_config_gic_msi_irq+0xe8/0x314 [ath11k_pci] -[ 1164.707882] init_module+0xb3a5bc/0xb3b8d8 [ath11k_ahb] -[ 1164.714299] init_module+0xb3b618/0xb3b8d8 [ath11k_ahb] -[ 1164.719423] platform_drv_probe+0x50/0x9c -[ 1164.724625] really_probe+0x1c8/0x410 -[ 1164.728791] driver_probe_device+0xe8/0x12c -[ 1164.732437] device_driver_attach+0x40/0x68 -[ 1164.736430] __driver_attach+0x120/0x138 -[ 1164.740596] bus_for_each_dev+0x68/0xbc -[ 1164.744763] driver_attach+0x20/0x28 -[ 1164.748324] bus_add_driver+0x104/0x1f4 -[ 1164.752144] driver_register+0xa0/0xe4 -[ 1164.755701] __platform_driver_register+0x48/0x50 -[ 1164.759529] init_module+0x20/0x1000 [ath11k_ahb] -[ 1164.764299] do_one_initcall+0x74/0x190 -[ 1164.768987] do_init_module+0x54/0x1e0 -[ 1164.772631] load_module+0x1d8c/0x1f48 -[ 1164.776447] __se_sys_init_module+0x24c/0x2ac -[ 1164.780180] __arm64_sys_init_module+0x14/0x1c -[ 1164.784612] el0_svc_common.constprop.0+0x84/0x100 -[ 1164.788948] el0_svc_handler+0x18/0x20 -[ 1164.793722] el0_svc+0x8/0x1b4 -[ 1164.797461] Code: d37d1c40 91008021 f8606821 14000005 (b9417801) -[ 1164.800498] ---[ end trace 9da51c6caab45221 ]--- - -Signed-off-by: Venkateswara Naralasetty ---- - drivers/net/wireless/ath/ath11k/ahb.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c -index dad2502..94e6c48 100644 ---- a/drivers/net/wireless/ath/ath11k/ahb.c -+++ b/drivers/net/wireless/ath/ath11k/ahb.c -@@ -435,6 +435,8 @@ static void ath11k_ahb_free_ext_irq(struct ath11k_base *ab) - - for (j = 0; j < irq_grp->num_irq; j++) - free_irq(ab->irq_num[irq_grp->irqs[j]], irq_grp); -+ -+ netif_napi_del(&irq_grp->napi); - } - } - --- -2.7.4 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/336-ath11k-support-avg-signal-in-sta-dump.patch b/feeds/ipq95xx/mac80211/patches/qca/336-ath11k-support-avg-signal-in-sta-dump.patch deleted file mode 100644 index 0a4279521..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/336-ath11k-support-avg-signal-in-sta-dump.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 62d0aec59d1b4e3c7d029040f8a0efda1df80362 Mon Sep 17 00:00:00 2001 -From: Thiraviyam Mariyappan -Date: Wed, 8 Dec 2021 12:48:11 +0530 -Subject: [PATCH] ath11k: support avg signal in station dump - -mac80211 doesn't calculate avg signal since uses_rss enabled from driver. -so, avg signal doesn't print in station dump. This patch calculates -avg signal from the rssi and displayed in station dump. - -Signed-off-by: Thiraviyam Mariyappan ---- - drivers/net/wireless/ath/ath11k/core.h | 2 ++ - drivers/net/wireless/ath/ath11k/dp_rx.c | 1 + - drivers/net/wireless/ath/ath11k/mac.c | 4 ++++ - 3 files changed, 7 insertions(+) - ---- a/drivers/net/wireless/ath/ath11k/core.h -+++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -557,6 +557,7 @@ struct ath11k_driver_rx_pkts_flow { - }; - - DECLARE_EWMA(sta_per, 8, 16) -+DECLARE_EWMA(avg_rssi, 10, 8) - - struct ath11k_sta { - struct ath11k_vif *arvif; -@@ -578,6 +579,7 @@ struct ath11k_sta { - u8 rssi_comb; - s8 rssi_beacon; - s8 chain_signal[IEEE80211_MAX_CHAINS]; -+ struct ewma_avg_rssi avg_rssi; - struct ath11k_htt_tx_stats *tx_stats; - struct ath11k_rx_peer_stats *rx_stats; - struct ath11k_smart_ant_sta *smart_ant_sta; ---- a/drivers/net/wireless/ath/ath11k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -3504,6 +3504,7 @@ static void ath11k_dp_rx_update_peer_su_ - return; - - arsta->rssi_comb = ppdu_info->rssi_comb; -+ ewma_avg_rssi_add(&arsta->avg_rssi, ppdu_info->rssi_comb); - - if (!ath11k_debugfs_is_extd_rx_stats_enabled(ar)) - return; ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -5580,6 +5580,7 @@ static int ath11k_mac_station_add(struct - ewma_sta_per_add(&arsta->per, 1); - ewma_sta_ber_init(&arsta->ber); - ewma_sta_ber_add(&arsta->ber, 1); -+ ewma_avg_rssi_init(&arsta->avg_rssi); - return 0; - - free_tx_stats: -@@ -11047,6 +11048,9 @@ static void ath11k_mac_op_sta_statistics - sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL); - } - -+ sinfo->signal_avg = ewma_avg_rssi_read(&arsta->avg_rssi) + ATH11K_DEFAULT_NOISE_FLOOR; -+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG); -+ - if (arvif->ar->ab->nss.enabled) - ath11k_nss_update_sta_stats(arvif, sinfo, sta); - } diff --git a/feeds/ipq95xx/mac80211/patches/qca/336-mac80211-Mesh-Fast-rx-support.patch b/feeds/ipq95xx/mac80211/patches/qca/336-mac80211-Mesh-Fast-rx-support.patch index 3c3acf3a4..5c7e3ba21 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/336-mac80211-Mesh-Fast-rx-support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/336-mac80211-Mesh-Fast-rx-support.patch @@ -20,7 +20,7 @@ Signed-off-by: Sriram R --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -1500,6 +1500,8 @@ static void sta_apply_mesh_params(struct +@@ -1583,6 +1583,8 @@ static void sta_apply_mesh_params(struct /* init at low value */ ewma_mesh_tx_rate_avg_add(&sta->mesh->tx_rate_avg, 10); @@ -29,7 +29,7 @@ Signed-off-by: Sriram R break; case NL80211_PLINK_LISTEN: case NL80211_PLINK_BLOCKED: -@@ -1514,6 +1516,7 @@ static void sta_apply_mesh_params(struct +@@ -1597,6 +1599,7 @@ static void sta_apply_mesh_params(struct ieee80211_mps_sta_status_update(sta); changed |= ieee80211_mps_set_sta_local_pm(sta, NL80211_MESH_POWER_UNKNOWN); @@ -48,7 +48,7 @@ Signed-off-by: Sriram R return changed; } -@@ -888,6 +890,7 @@ static u32 mesh_plink_establish(struct i +@@ -889,6 +891,7 @@ static u32 mesh_plink_establish(struct i mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n", sta->sta.addr); ieee80211_mps_sta_status_update(sta); changed |= ieee80211_mps_set_sta_local_pm(sta, mshcfg->power_mode); @@ -56,7 +56,7 @@ Signed-off-by: Sriram R return changed; } -@@ -906,7 +909,7 @@ static u32 mesh_plink_fsm(struct ieee802 +@@ -907,7 +910,7 @@ static u32 mesh_plink_fsm(struct ieee802 struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg; enum ieee80211_self_protected_actioncode action = 0; u32 changed = 0; @@ -65,7 +65,7 @@ Signed-off-by: Sriram R mpl_dbg(sdata, "peer %pM in state %s got event %s\n", sta->sta.addr, mplstates[sta->mesh->plink_state], mplevents[event]); -@@ -966,6 +969,7 @@ static u32 mesh_plink_fsm(struct ieee802 +@@ -967,6 +970,7 @@ static u32 mesh_plink_fsm(struct ieee802 break; case CNF_ACPT: changed |= mesh_plink_establish(sdata, sta); @@ -73,7 +73,7 @@ Signed-off-by: Sriram R break; default: break; -@@ -981,6 +985,7 @@ static u32 mesh_plink_fsm(struct ieee802 +@@ -982,6 +986,7 @@ static u32 mesh_plink_fsm(struct ieee802 break; case OPN_ACPT: changed |= mesh_plink_establish(sdata, sta); @@ -81,7 +81,7 @@ Signed-off-by: Sriram R action = WLAN_SP_MESH_PEERING_CONFIRM; break; default: -@@ -1027,6 +1032,10 @@ static u32 mesh_plink_fsm(struct ieee802 +@@ -1028,6 +1033,10 @@ static u32 mesh_plink_fsm(struct ieee802 break; } spin_unlock_bh(&sta->mesh->plink_lock); @@ -94,7 +94,7 @@ Signed-off-by: Sriram R if (action) { --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c -@@ -4439,6 +4439,17 @@ void ieee80211_check_fast_rx(struct sta_ +@@ -4523,6 +4523,17 @@ void ieee80211_check_fast_rx(struct sta_ } break; @@ -112,7 +112,7 @@ Signed-off-by: Sriram R default: goto clear; } -@@ -4478,7 +4489,7 @@ void ieee80211_check_fast_rx(struct sta_ +@@ -4562,7 +4573,7 @@ void ieee80211_check_fast_rx(struct sta_ __release(check_fast_rx); if (assign) @@ -121,10 +121,10 @@ Signed-off-by: Sriram R offload = assign && (sdata->vif.offload_flags & IEEE80211_OFFLOAD_DECAP_ENABLED); -@@ -4660,6 +4671,10 @@ static bool ieee80211_invoke_fast_rx(str +@@ -4734,6 +4745,10 @@ static bool ieee80211_invoke_fast_rx(str u8 sa[ETH_ALEN]; } addrs __aligned(2); - struct ieee80211_sta_rx_stats *stats = &sta->rx_stats; + struct ieee80211_sta_rx_stats *stats = &sta->deflink.rx_stats; + struct ieee80211s_hdr *mesh_hdr; + struct mesh_path *mppath; + u8 da_offs = fast_rx->da_offs, sa_offs = fast_rx->sa_offs; @@ -132,7 +132,7 @@ Signed-off-by: Sriram R /* for parallel-rx, we need to have DUP_VALIDATED, otherwise we write * to a common data structure; drivers can implement that per queue -@@ -4709,6 +4724,37 @@ static bool ieee80211_invoke_fast_rx(str +@@ -4783,6 +4798,37 @@ static bool ieee80211_invoke_fast_rx(str snap_offs += IEEE80211_CCMP_HDR_LEN; } @@ -170,7 +170,7 @@ Signed-off-by: Sriram R if (!(status->rx_flags & IEEE80211_RX_AMSDU)) { if (!pskb_may_pull(skb, snap_offs + sizeof(*payload))) goto drop; -@@ -4745,9 +4791,34 @@ static bool ieee80211_invoke_fast_rx(str +@@ -4819,9 +4865,33 @@ static bool ieee80211_invoke_fast_rx(str return true; } @@ -193,7 +193,6 @@ Signed-off-by: Sriram R + ether_addr_copy(mppath->mpp, mpp_addr); + + mppath->exp_time = jiffies; -+ + spin_unlock_bh(&mppath->state_lock); + } + rcu_read_unlock(); @@ -204,6 +203,6 @@ Signed-off-by: Sriram R - ether_addr_copy(addrs.sa, skb->data + fast_rx->sa_offs); + ether_addr_copy(addrs.da, skb->data + da_offs); + ether_addr_copy(addrs.sa, skb->data + sa_offs); + skb_postpull_rcsum(skb, skb->data + snap_offs, + sizeof(rfc1042_header) + 2); /* remove the SNAP but leave the ethertype */ - skb_pull(skb, snap_offs + sizeof(rfc1042_header)); - /* push the addresses in front */ diff --git a/feeds/ipq95xx/mac80211/patches/qca/339-ath11k-Handle-failure-in-qmi-firmware-ready.patch b/feeds/ipq95xx/mac80211/patches/qca/339-ath11k-Handle-failure-in-qmi-firmware-ready.patch index 5445a2351..0151a07c1 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/339-ath11k-Handle-failure-in-qmi-firmware-ready.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/339-ath11k-Handle-failure-in-qmi-firmware-ready.patch @@ -29,25 +29,14 @@ Signed-off-by: Seevalamuthu Mariappan drivers/net/wireless/ath/ath11k/qmi.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) -diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c -index ee03b11..b1180e8 100644 --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c -@@ -4538,7 +4538,13 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work) +@@ -4713,6 +4713,8 @@ static void ath11k_qmi_driver_event_work + clear_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags); + ret = ath11k_core_qmi_firmware_ready(ab); + if (ret) { ++ ath11k_warn(ab, ++ "failed to init after firmware ready: %d\n", ret); + set_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags); break; } - -- ath11k_core_qmi_firmware_ready(ab); -+ ret = ath11k_core_qmi_firmware_ready(ab); -+ if (ret) { -+ ath11k_warn(ab, -+ "failed to init after firmware ready: %d\n", ret); -+ set_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags); -+ break; -+ } - set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags); - } - --- -2.7.4 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/339-ath11k-add-get_txpower-mac-ops.patch b/feeds/ipq95xx/mac80211/patches/qca/339-ath11k-add-get_txpower-mac-ops.patch index 0ccdcd548..622ccb89f 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/339-ath11k-add-get_txpower-mac-ops.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/339-ath11k-add-get_txpower-mac-ops.patch @@ -23,9 +23,9 @@ Signed-off-by: Aditya Kumar Singh --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -782,6 +782,55 @@ static const struct ath11k_num_vdevs_pee - } - }; +@@ -825,6 +825,55 @@ static inline struct ath11k_pdev *ath11k + return &ab->pdevs[0]; + } +void ath11k_fw_stats_pdevs_free(struct list_head *head) +{ @@ -81,7 +81,7 @@ Signed-off-by: Aditya Kumar Singh int ret; --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -685,8 +685,6 @@ struct ath11k_debug { +@@ -781,8 +781,6 @@ struct ath11k_debug { struct ath11k_dbg_htt_stats htt_stats; u32 extd_tx_stats; struct ath11k_fw_stats fw_stats; @@ -90,7 +90,7 @@ Signed-off-by: Aditya Kumar Singh u32 extd_rx_stats; u32 pktlog_filter; u32 pktlog_mode; -@@ -921,6 +919,10 @@ struct ath11k { +@@ -1021,6 +1019,10 @@ struct ath11k { struct cfg80211_chan_def awgn_chandef; u32 chan_bw_interference_bitmap; bool awgn_intf_handling_in_prog; @@ -99,9 +99,9 @@ Signed-off-by: Aditya Kumar Singh + struct completion fw_stats_complete; + bool fw_stats_done; u32 vdev_id_11d_scan; - struct completion finish_11d_scan; - struct completion finish_11d_ch_list; -@@ -1394,6 +1396,12 @@ enum ath11k_fw_recovery_option { + struct completion completed_11d_scan; + enum ath11k_11d_state state_11d; +@@ -1509,6 +1511,12 @@ enum ath11k_fw_recovery_option { ATH11K_FW_RECOVERY_ENABLE_SSR_ONLY, }; @@ -116,7 +116,7 @@ Signed-off-by: Aditya Kumar Singh static inline bool ath11k_smart_ant_enabled(struct ath11k *ar) --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -807,91 +807,28 @@ void ath11k_debug_aggr_size_config_init( +@@ -844,91 +844,28 @@ void ath11k_debug_aggr_size_config_init( &fops_amsdu_aggr_size); } @@ -217,7 +217,7 @@ Signed-off-by: Aditya Kumar Singh } /* FW sends all the active VDEV stats irrespective of PDEV, * hence limit until the count of all VDEVs started -@@ -904,43 +841,34 @@ void ath11k_debugfs_fw_stats_process(str +@@ -941,43 +878,34 @@ void ath11k_debugfs_fw_stats_process(str is_end = ((++num_vdev) == total_vdevs_started); @@ -269,7 +269,7 @@ Signed-off-by: Aditya Kumar Singh } static int ath11k_debugfs_fw_stats_request(struct ath11k *ar, -@@ -961,7 +889,7 @@ static int ath11k_debugfs_fw_stats_reque +@@ -998,7 +926,7 @@ static int ath11k_debugfs_fw_stats_reque ath11k_debugfs_fw_stats_reset(ar); @@ -278,7 +278,7 @@ Signed-off-by: Aditya Kumar Singh ret = ath11k_wmi_send_stats_request_cmd(ar, req_param); -@@ -972,7 +900,7 @@ static int ath11k_debugfs_fw_stats_reque +@@ -1009,7 +937,7 @@ static int ath11k_debugfs_fw_stats_reque } time_left = @@ -287,7 +287,7 @@ Signed-off-by: Aditya Kumar Singh 1 * HZ); if (!time_left) return -ETIMEDOUT; -@@ -982,7 +910,7 @@ static int ath11k_debugfs_fw_stats_reque +@@ -1019,7 +947,7 @@ static int ath11k_debugfs_fw_stats_reque break; spin_lock_bh(&ar->data_lock); @@ -296,7 +296,7 @@ Signed-off-by: Aditya Kumar Singh spin_unlock_bh(&ar->data_lock); break; } -@@ -2284,11 +2212,12 @@ void ath11k_debugfs_fw_stats_init(struct +@@ -2383,11 +2311,12 @@ void ath11k_debugfs_fw_stats_init(struct debugfs_create_file("beacon_stats", 0600, fwstats_dir, ar, &fops_bcn_stats); @@ -313,7 +313,7 @@ Signed-off-by: Aditya Kumar Singh static ssize_t ath11k_write_pktlog_filter(struct file *file, --- a/drivers/net/wireless/ath/ath11k/debugfs.h +++ b/drivers/net/wireless/ath/ath11k/debugfs.h -@@ -239,7 +239,7 @@ int ath11k_debugfs_pdev_create(struct at +@@ -394,7 +394,7 @@ int ath11k_debugfs_pdev_create(struct at void ath11k_debugfs_pdev_destroy(struct ath11k_base *ab); int ath11k_debugfs_register(struct ath11k *ar); void ath11k_debugfs_unregister(struct ath11k *ar); @@ -322,7 +322,7 @@ Signed-off-by: Aditya Kumar Singh void ath11k_debugfs_fw_stats_init(struct ath11k *ar); void ath11k_smart_ant_debugfs_init(struct ath11k *ar); -@@ -336,8 +336,8 @@ static inline void ath11k_debugfs_unregi +@@ -498,8 +498,8 @@ static inline void ath11k_debugfs_unregi { } @@ -335,7 +335,7 @@ Signed-off-by: Aditya Kumar Singh --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -11168,6 +11168,96 @@ out: +@@ -11525,6 +11525,96 @@ out: return ret; } @@ -432,18 +432,18 @@ Signed-off-by: Aditya Kumar Singh static const struct ieee80211_ops ath11k_ops = { .tx = ath11k_mac_op_tx, .start = ath11k_mac_op_start, -@@ -11213,6 +11303,7 @@ static const struct ieee80211_ops ath11k +@@ -11586,6 +11676,7 @@ static const struct ieee80211_ops ath11k #ifdef CPTCFG_MAC80211_MESH - .config_mesh_offload_path = ath11k_mac_op_config_mesh_offload_path, + .config_mesh_offload_path = ath11k_mac_op_config_mesh_offload_path, #endif + .get_txpower = ath11k_mac_op_get_txpower, }; static void ath11k_mac_update_ch_list(struct ath11k *ar, -@@ -11981,6 +12072,8 @@ int ath11k_mac_allocate(struct ath11k_ba +@@ -12390,6 +12481,8 @@ int ath11k_mac_allocate(struct ath11k_ba + clear_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags); ar->vdev_id_11d_scan = ATH11K_11D_INVALID_VDEV_ID; - init_completion(&ar->finish_11d_scan); - init_completion(&ar->finish_11d_ch_list); + init_completion(&ar->completed_11d_scan); + + ath11k_fw_stats_init(ar); } @@ -451,7 +451,7 @@ Signed-off-by: Aditya Kumar Singh return 0; --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -7683,7 +7683,7 @@ void ath11k_wmi_fw_stats_fill(struct ath +@@ -7727,7 +7727,7 @@ void ath11k_wmi_fw_stats_fill(struct ath spin_lock_bh(&ar->data_lock); if (stats_id == WMI_REQUEST_PDEV_STAT) { @@ -460,7 +460,7 @@ Signed-off-by: Aditya Kumar Singh struct ath11k_fw_stats_pdev, list); if (!pdev) { ath11k_warn(ar->ab, "failed to get pdev stats\n"); -@@ -9096,7 +9096,52 @@ static void ath11k_peer_assoc_conf_event +@@ -9146,7 +9146,52 @@ static void ath11k_peer_assoc_conf_event static void ath11k_update_stats_event(struct ath11k_base *ab, struct sk_buff *skb) { diff --git a/feeds/ipq95xx/mac80211/patches/qca/339-ath11k-disable-spectral-scan-during-spectral-deinit.patch b/feeds/ipq95xx/mac80211/patches/qca/339-ath11k-disable-spectral-scan-during-spectral-deinit.patch index a391adf13..da5bb8f25 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/339-ath11k-disable-spectral-scan-during-spectral-deinit.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/339-ath11k-disable-spectral-scan-during-spectral-deinit.patch @@ -13,54 +13,9 @@ Signed-off-by: Hari Chandrakanthan drivers/net/wireless/ath/ath11k/spectral.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) ---- a/drivers/net/wireless/ath/ath11k/spectral.c -+++ b/drivers/net/wireless/ath/ath11k/spectral.c -@@ -215,7 +215,10 @@ static int ath11k_spectral_scan_config(s - return -ENODEV; - - arvif->spectral_enabled = (mode != ATH11K_SPECTRAL_DISABLED); -+ -+ spin_lock_bh(&ar->spectral.lock); - ar->spectral.mode = mode; -+ spin_unlock_bh(&ar->spectral.lock); - - ret = ath11k_wmi_vdev_spectral_enable(ar, arvif->vdev_id, - ATH11K_WMI_SPECTRAL_TRIGGER_CMD_CLEAR, -@@ -859,9 +862,6 @@ static inline void ath11k_spectral_ring_ - { - struct ath11k_spectral *sp = &ar->spectral; - -- if (!sp->enabled) -- return; -- - ath11k_dbring_srng_cleanup(ar, &sp->rx_ring); - ath11k_dbring_buf_cleanup(ar, &sp->rx_ring); - } -@@ -913,15 +913,16 @@ void ath11k_spectral_deinit(struct ath11 - if (!sp->enabled) - continue; - -- ath11k_spectral_debug_unregister(ar); -- ath11k_spectral_ring_free(ar); -+ mutex_lock(&ar->conf_mutex); -+ ath11k_spectral_scan_config(ar, ATH11K_SPECTRAL_DISABLED); -+ mutex_unlock(&ar->conf_mutex); - - spin_lock_bh(&sp->lock); -- -- sp->mode = ATH11K_SPECTRAL_DISABLED; - sp->enabled = false; -- - spin_unlock_bh(&sp->lock); -+ -+ ath11k_spectral_debug_unregister(ar); -+ ath11k_spectral_ring_free(ar); - } - } - --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -7631,6 +7631,11 @@ static void ath11k_mac_op_remove_interfa +@@ -8068,6 +8068,11 @@ static void ath11k_mac_op_remove_interfa mutex_lock(&ar->conf_mutex); diff --git a/feeds/ipq95xx/mac80211/patches/qca/342-mac80211-fix-unconditional-sta-usage.patch b/feeds/ipq95xx/mac80211/patches/qca/342-mac80211-fix-unconditional-sta-usage.patch index 604b728fe..9b7138ab8 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/342-mac80211-fix-unconditional-sta-usage.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/342-mac80211-fix-unconditional-sta-usage.patch @@ -33,21 +33,21 @@ Signed-off-by: Tamizh Chelvam --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c -@@ -4394,7 +4394,7 @@ static void ieee80211_8023_xmit(struct i - memset(info, 0, sizeof(*info)); +@@ -4672,7 +4672,7 @@ static void ieee80211_8023_xmit(struct i + + ieee80211_aggr_check(sdata, sta, skb); - tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; - if (!ieee80211_hw_check(&local->hw, SUPPORTS_NSS_OFFLOAD)) { + if (!ieee80211_hw_check(&local->hw, SUPPORTS_NSS_OFFLOAD) && sta) { + tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]); if (tid_tx) { - if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) { -@@ -4418,7 +4418,7 @@ static void ieee80211_8023_xmit(struct i +@@ -4700,7 +4700,7 @@ static void ieee80211_8023_xmit(struct i ieee80211_tx_stats(dev, skb->len); - if (!ieee80211_hw_check(&local->hw, SUPPORTS_NSS_OFFLOAD)) { + if (!ieee80211_hw_check(&local->hw, SUPPORTS_NSS_OFFLOAD) && sta) { - sta->tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len; - sta->tx_stats.packets[skb_get_queue_mapping(skb)]++; + sta->deflink.tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len; + sta->deflink.tx_stats.packets[skb_get_queue_mapping(skb)]++; } diff --git a/feeds/ipq95xx/mac80211/patches/qca/346-ath11k-Add-debugfs-entry-to-configure-bss-survey-mod.patch b/feeds/ipq95xx/mac80211/patches/qca/346-ath11k-Add-debugfs-entry-to-configure-bss-survey-mod.patch index ed7c27d36..95a8e89e7 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/346-ath11k-Add-debugfs-entry-to-configure-bss-survey-mod.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/346-ath11k-Add-debugfs-entry-to-configure-bss-survey-mod.patch @@ -28,11 +28,9 @@ Signed-off-by: Seevalamuthu Mariappan drivers/net/wireless/ath/ath11k/mac.c | 7 ++++- 3 files changed, 57 insertions(+), 1 deletion(-) -diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h -index 833dc53..a51c970 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -670,6 +670,7 @@ struct ath11k_debug { +@@ -818,6 +818,7 @@ struct ath11k_debug { bool disable_dynamic_bw; struct dentry *debugfs_smartant; u32 coex_priority_level[ATH11K_MAX_COEX_PRIORITY_LEVEL]; @@ -40,11 +38,9 @@ index 833dc53..a51c970 100644 }; struct ath11k_per_peer_tx_stats { -diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c -index d62fca7..8018b22 100644 --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -4647,6 +4647,53 @@ static const struct file_operations fops_coex_priority = { +@@ -4951,6 +4951,53 @@ static const struct file_operations fops .llseek = default_llseek, }; @@ -98,21 +94,19 @@ index d62fca7..8018b22 100644 int ath11k_debugfs_register(struct ath11k *ar) { struct ath11k_base *ab = ar->ab; -@@ -4761,6 +4808,9 @@ int ath11k_debugfs_register(struct ath11k *ar) +@@ -5069,6 +5116,9 @@ int ath11k_debugfs_register(struct ath11 &fops_medium_busy); debugfs_create_file("coex_priority", 0600, ar->debug.debugfs_pdev, ar, &fops_coex_priority); + debugfs_create_file("bss_survey_mode", 0644, + ar->debug.debugfs_pdev, ar, + &fops_bss_survey_mode); - return 0; } -diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c -index af380a5..6ab8525 100644 + --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -10490,10 +10490,15 @@ ath11k_mac_update_bss_chan_survey(struct ath11k *ar, +@@ -10955,10 +10955,15 @@ ath11k_mac_update_bss_chan_survey(struct struct ieee80211_channel *channel) { int ret; @@ -129,6 +123,3 @@ index af380a5..6ab8525 100644 if (!test_bit(WMI_TLV_SERVICE_BSS_CHANNEL_INFO_64, ar->ab->wmi_ab.svc_map) || ar->rx_channel != channel) return; --- -2.7.4 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/346-ath11k-add-pci3-and-pci4-domain-names-to-dp-ce_.patch b/feeds/ipq95xx/mac80211/patches/qca/346-ath11k-add-pci3-and-pci4-domain-names-to-dp-ce_.patch index 7a261c8a8..da283d44c 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/346-ath11k-add-pci3-and-pci4-domain-names-to-dp-ce_.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/346-ath11k-add-pci3-and-pci4-domain-names-to-dp-ce_.patch @@ -32,11 +32,9 @@ Signed-off-by: Rameshkumar Sundaram drivers/net/wireless/ath/ath11k/pci_cmn.h | 1 - 3 files changed, 19 insertions(+), 2 deletions(-) -diff --git a/drivers/net/wireless/ath/ath11k/pci.h b/drivers/net/wireless/ath/ath11k/pci.h -index 2c5ef76..f8a68c1 100644 --- a/drivers/net/wireless/ath/ath11k/pci.h +++ b/drivers/net/wireless/ath/ath11k/pci.h -@@ -23,7 +23,7 @@ +@@ -24,7 +24,7 @@ /* register used for handshake mechanism to validate UMAC is awake */ #define PCIE_SOC_WAKE_PCIE_LOCAL_REG 0x3004 @@ -45,27 +43,9 @@ index 2c5ef76..f8a68c1 100644 #define PCIE_PCIE_PARF_LTSSM 0x1e081b0 #define PARM_LTSSM_VALUE 0x111 -diff --git a/drivers/net/wireless/ath/ath11k/pci_cmn.c b/drivers/net/wireless/ath/ath11k/pci_cmn.c -index aba8417..2c65ae5 100644 ---- a/drivers/net/wireless/ath/ath11k/pci_cmn.c -+++ b/drivers/net/wireless/ath/ath11k/pci_cmn.c -@@ -18,6 +18,15 @@ const char *dp_irq_name[ATH11K_MAX_PCI_DOMAINS + 1][ATH11K_EXT_IRQ_GRP_NUM_MAX] - ATH11K_PCI_DP_IRQS_NAME(1) - }, - { -+ ATH11K_PCI_DP_IRQS_NAME(2) -+ }, -+ { -+ ATH11K_PCI_DP_IRQS_NAME(3) -+ }, -+ { -+ ATH11K_PCI_DP_IRQS_NAME(4) -+ }, -+ { - ATH11K_PCI_DP_IRQS_NAME() - }, - }; -@@ -30,6 +39,15 @@ const char *ce_irq_name[ATH11K_MAX_PCI_DOMAINS + 1][CE_COUNT_MAX] = { +--- a/drivers/net/wireless/ath/ath11k/pcic.c ++++ b/drivers/net/wireless/ath/ath11k/pcic.c +@@ -16,6 +16,15 @@ const char *ce_irq_name[ATH11K_MAX_PCI_D ATH11K_PCI_CE_IRQS_NAME(1) }, { @@ -81,18 +61,19 @@ index aba8417..2c65ae5 100644 ATH11K_PCI_CE_IRQS_NAME() }, }; -diff --git a/drivers/net/wireless/ath/ath11k/pci_cmn.h b/drivers/net/wireless/ath/ath11k/pci_cmn.h -index 81099f2..7f1ce82 100644 ---- a/drivers/net/wireless/ath/ath11k/pci_cmn.h -+++ b/drivers/net/wireless/ath/ath11k/pci_cmn.h -@@ -16,7 +16,6 @@ - #define WINDOW_RANGE_MASK GENMASK(18, 0) - - #define ATH11K_PCI_IRQ_CE0_OFFSET 3 --#define ATH11K_MAX_PCI_DOMAINS 2 - - extern const struct ath11k_msi_config ath11k_msi_config[]; - --- -2.7.4 - +@@ -28,6 +37,15 @@ const char *dp_irq_name[ATH11K_MAX_PCI_D + ATH11K_PCI_DP_IRQS_NAME(1) + }, + { ++ ATH11K_PCI_DP_IRQS_NAME(2) ++ }, ++ { ++ ATH11K_PCI_DP_IRQS_NAME(3) ++ }, ++ { ++ ATH11K_PCI_DP_IRQS_NAME(4) ++ }, ++ { + ATH11K_PCI_DP_IRQS_NAME() + }, + }; diff --git a/feeds/ipq95xx/mac80211/patches/qca/347-ath11k-add-tbl-lock.patch b/feeds/ipq95xx/mac80211/patches/qca/347-ath11k-add-tbl-lock.patch deleted file mode 100644 index faa2d8b4f..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/347-ath11k-add-tbl-lock.patch +++ /dev/null @@ -1,323 +0,0 @@ -From a6d4a6e80806259ffb4eeabe046440d44423b99c Mon Sep 17 00:00:00 2001 -From: Karthikeyan Periyasamy -Date: Wed, 2 Feb 2022 08:47:50 +0530 -Subject: [PATCH] ath11k: add tbl lock - -Signed-off-by: Karthikeyan Periyasamy ---- - drivers/net/wireless/ath/ath11k/core.c | 1 + - drivers/net/wireless/ath/ath11k/core.h | 8 ++--- - drivers/net/wireless/ath/ath11k/mac.c | 4 +++ - drivers/net/wireless/ath/ath11k/peer.c | 60 ++++++++++++++++++++++++++++++---- - 4 files changed, 62 insertions(+), 11 deletions(-) - ---- a/drivers/net/wireless/ath/ath11k/core.c -+++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -1894,6 +1894,7 @@ struct ath11k_base *ath11k_core_alloc(st - goto err_free_wq; - - mutex_init(&ab->core_lock); -+ mutex_init(&ab->tbl_mtx_lock); - mutex_init(&ab->base_ast_lock); - spin_lock_init(&ab->base_lock); - init_completion(&ab->reset_complete); ---- a/drivers/net/wireless/ath/ath11k/core.h -+++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -1095,10 +1095,10 @@ struct ath11k_base { - struct ath11k_hal_reg_capabilities_ext hal_reg_cap[MAX_RADIOS]; - unsigned long long free_vdev_map; - -- /* -- * The rhashtable containing struct ath11k_peer keyed by mac addr -- * protected under ab->base_lock spin lock -- */ -+ /* To synchronize rhash tbl write operation */ -+ struct mutex tbl_mtx_lock; -+ -+ /* The rhashtable containing struct ath11k_peer keyed by mac addr */ - struct rhashtable *rhead_peer_addr; - struct rhashtable_params rhash_peer_addr_param; - ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -948,6 +948,7 @@ void ath11k_mac_peer_cleanup_all(struct - - lockdep_assert_held(&ar->conf_mutex); - -+ mutex_lock(&ab->tbl_mtx_lock); - spin_lock_bh(&ab->base_lock); - list_for_each_entry_safe(peer, tmp, &ab->peers, list) { - ath11k_peer_rx_tid_cleanup(ar, peer); -@@ -956,6 +957,7 @@ void ath11k_mac_peer_cleanup_all(struct - kfree(peer); - } - spin_unlock_bh(&ab->base_lock); -+ mutex_unlock(&ab->tbl_mtx_lock); - - ar->num_peers = 0; - ar->num_stations = 0; -@@ -5739,6 +5741,7 @@ static int ath11k_mac_op_sta_state(struc - sta->addr, arvif->vdev_id); - - ath11k_mac_dec_num_stations(arvif, sta); -+ mutex_lock(&ar->ab->tbl_mtx_lock); - spin_lock_bh(&ar->ab->base_lock); - peer = ath11k_peer_find(ar->ab, arvif->vdev_id, sta->addr); - if (peer && peer->sta == sta) { -@@ -5751,6 +5754,7 @@ static int ath11k_mac_op_sta_state(struc - ar->num_peers--; - } - spin_unlock_bh(&ar->ab->base_lock); -+ mutex_unlock(&ar->ab->tbl_mtx_lock); - - free: - kfree(arsta->tx_stats); ---- a/drivers/net/wireless/ath/ath11k/peer.c -+++ b/drivers/net/wireless/ath/ath11k/peer.c -@@ -8,6 +8,23 @@ - #include "debug.h" - #include "nss.h" - -+static struct ath11k_peer *ath11k_peer_find_list_by_id(struct ath11k_base *ab, -+ int peer_id) -+{ -+ struct ath11k_peer *peer; -+ -+ lockdep_assert_held(&ab->base_lock); -+ -+ list_for_each_entry(peer, &ab->peers, list) { -+ if (peer->peer_id != peer_id) -+ continue; -+ -+ return peer; -+ } -+ -+ return NULL; -+} -+ - struct ath11k_peer *ath11k_peer_find(struct ath11k_base *ab, int vdev_id, - const u8 *addr) - { -@@ -433,7 +450,7 @@ void ath11k_peer_unmap_event(struct ath1 - - spin_lock_bh(&ab->base_lock); - -- peer = ath11k_peer_find_by_id(ab, peer_id); -+ peer = ath11k_peer_find_list_by_id(ab, peer_id); - if (!peer) { - ath11k_warn(ab, "peer-unmap-event: unknown peer id %d\n", - peer_id); -@@ -444,7 +461,6 @@ void ath11k_peer_unmap_event(struct ath1 - ath11k_dbg(ab, ATH11K_DBG_PEER, "peer unmap vdev %d peer %pM id %d\n", - peer->vdev_id, peer->addr, peer_id); - -- ath11k_peer_rhash_delete(ab, peer); - list_del(&peer->list); - kfree(peer); - wake_up(&ab->peer_mapping_wq); -@@ -461,7 +477,7 @@ void ath11k_peer_unmap_v2_event(struct a - - spin_lock_bh(&ab->base_lock); - -- peer = ath11k_peer_find_by_id(ab, peer_id); -+ peer = ath11k_peer_find_list_by_id(ab, peer_id); - if (!peer) { - ath11k_warn(ab, "peer-unmap-event: unknown peer id %d\n", - peer_id); -@@ -498,7 +514,6 @@ void ath11k_peer_unmap_v2_event(struct a - #endif - free_peer: - rcu_read_unlock(); -- ath11k_peer_rhash_delete(ab, peer); - list_del(&peer->list); - kfree(peer); - wake_up(&ab->peer_mapping_wq); -@@ -636,6 +651,7 @@ static inline int ath11k_peer_rhash_inse - struct ath11k_peer *tmp; - - lockdep_assert_held(&ab->base_lock); -+ lockdep_assert_held(&ab->tbl_mtx_lock); - - tmp = rhashtable_lookup_get_insert_fast(rtbl, rhead, *params); - -@@ -653,6 +669,7 @@ static inline int ath11k_peer_rhash_remo - struct rhashtable_params *params) - { - lockdep_assert_held(&ab->base_lock); -+ lockdep_assert_held(&ab->tbl_mtx_lock); - - return rhashtable_remove_fast(rtbl, rhead, *params); - } -@@ -662,6 +679,7 @@ static int ath11k_peer_rhash_add(struct - int ret; - - lockdep_assert_held(&ab->base_lock); -+ lockdep_assert_held(&ab->tbl_mtx_lock); - - if (!ab->rhead_peer_id || !ab->rhead_peer_addr) - return -EPERM; -@@ -702,6 +720,7 @@ void ath11k_peer_cleanup(struct ath11k * - #ifdef CPTCFG_ATH11K_NSS_SUPPORT - mutex_lock(&ab->base_ast_lock); - #endif -+ mutex_lock(&ab->tbl_mtx_lock); - spin_lock_bh(&ab->base_lock); - list_for_each_entry_safe(peer, tmp_peer, &ab->peers, list) { - if (peer->vdev_id != vdev_id) -@@ -728,6 +747,7 @@ void ath11k_peer_cleanup(struct ath11k * - } - - spin_unlock_bh(&ab->base_lock); -+ mutex_unlock(&ab->tbl_mtx_lock); - #ifdef CPTCFG_ATH11K_NSS_SUPPORT - mutex_unlock(&ab->base_ast_lock); - #endif -@@ -763,8 +783,8 @@ int ath11k_wait_for_peer_delete_done(str - int ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, u8 *addr) - { - int ret; --#ifdef CPTCFG_ATH11K_NSS_SUPPORT - struct ath11k_peer *peer; -+#ifdef CPTCFG_ATH11K_NSS_SUPPORT - struct ath11k_ast_entry *ast_entry, *tmp_ast; - #endif - lockdep_assert_held(&ar->conf_mutex); -@@ -774,10 +794,13 @@ int ath11k_peer_delete(struct ath11k *ar - ath11k_nss_peer_delete(ar->ab, vdev_id, addr); - #ifdef CPTCFG_ATH11K_NSS_SUPPORT - mutex_lock(&ar->ab->base_ast_lock); -+#endif -+ mutex_lock(&ar->ab->tbl_mtx_lock); - spin_lock_bh(&ar->ab->base_lock); - - peer = ath11k_peer_find_by_addr(ar->ab, addr); - if (peer) { -+#ifdef CPTCFG_ATH11K_NSS_SUPPORT - peer->delete_in_progress = true; - if (peer->self_ast_entry) { - ath11k_peer_del_ast(ar, peer->self_ast_entry); -@@ -795,8 +818,12 @@ int ath11k_peer_delete(struct ath11k *ar - list_del_init(&ast_entry->wmi_list); - } - } -+#endif -+ ath11k_peer_rhash_delete(ar->ab, peer); - } - spin_unlock_bh(&ar->ab->base_lock); -+ mutex_unlock(&ar->ab->tbl_mtx_lock); -+#ifdef CPTCFG_ATH11K_NSS_SUPPORT - mutex_unlock(&ar->ab->base_ast_lock); - #endif - ret = ath11k_wmi_send_peer_delete_cmd(ar, addr, vdev_id); -@@ -861,11 +888,13 @@ int ath11k_peer_create(struct ath11k *ar - if (ret) - return ret; - -+ mutex_lock(&ar->ab->tbl_mtx_lock); - spin_lock_bh(&ar->ab->base_lock); - - peer = ath11k_peer_find(ar->ab, param->vdev_id, param->peer_addr); - if (!peer) { - spin_unlock_bh(&ar->ab->base_lock); -+ mutex_unlock(&ar->ab->tbl_mtx_lock); - ath11k_warn(ar->ab, "failed to find peer %pM on vdev %i after creation\n", - param->peer_addr, param->vdev_id); - -@@ -876,6 +905,7 @@ int ath11k_peer_create(struct ath11k *ar - ret = ath11k_peer_rhash_add(ar->ab, peer); - if (ret) { - spin_unlock_bh(&ar->ab->base_lock); -+ mutex_unlock(&ar->ab->tbl_mtx_lock); - goto cleanup; - } - -@@ -918,6 +948,7 @@ int ath11k_peer_create(struct ath11k *ar - } - - spin_unlock_bh(&ar->ab->base_lock); -+ mutex_unlock(&ar->ab->tbl_mtx_lock); - - return 0; - -@@ -947,6 +978,7 @@ int ath11k_peer_rhash_delete(struct ath1 - int ret; - - lockdep_assert_held(&ab->base_lock); -+ lockdep_assert_held(&ab->tbl_mtx_lock); - - if (!ab->rhead_peer_id || !ab->rhead_peer_addr) - return -EPERM; -@@ -977,6 +1009,8 @@ static int ath11k_peer_rhash_id_tbl_init - int ret; - size_t size; - -+ lockdep_assert_held(&ab->tbl_mtx_lock); -+ - if (ab->rhead_peer_id) - return 0; - -@@ -1032,6 +1066,8 @@ static int ath11k_peer_rhash_addr_tbl_in - int ret; - size_t size; - -+ lockdep_assert_held(&ab->tbl_mtx_lock); -+ - if (ab->rhead_peer_addr) - return 0; - -@@ -1081,6 +1117,8 @@ err_free: - - static inline void ath11k_peer_rhash_id_tbl_destroy(struct ath11k_base *ab) - { -+ lockdep_assert_held(&ab->tbl_mtx_lock); -+ - if (!ab->rhead_peer_id) - return; - -@@ -1091,6 +1129,8 @@ static inline void ath11k_peer_rhash_id_ - - static inline void ath11k_peer_rhash_addr_tbl_destroy(struct ath11k_base *ab) - { -+ lockdep_assert_held(&ab->tbl_mtx_lock); -+ - if (!ab->rhead_peer_addr) - return; - -@@ -1103,28 +1143,34 @@ int ath11k_peer_rhash_tbl_init(struct at - { - int ret; - -+ mutex_lock(&ab->tbl_mtx_lock); -+ - ret = ath11k_peer_rhash_id_tbl_init(ab); - if (ret) -- return ret; -+ goto out; - - ret = ath11k_peer_rhash_addr_tbl_init(ab); - if (ret) - goto cleanup_tbl; - -+ mutex_unlock(&ab->tbl_mtx_lock); -+ - return 0; - - cleanup_tbl: - ath11k_peer_rhash_id_tbl_destroy(ab); -+out: -+ mutex_unlock(&ab->tbl_mtx_lock); - - return ret; - } - - void ath11k_peer_rhash_tbl_destroy(struct ath11k_base *ab) - { -- spin_lock_bh(&ab->base_lock); -+ mutex_lock(&ab->tbl_mtx_lock); - - ath11k_peer_rhash_id_tbl_destroy(ab); - ath11k_peer_rhash_addr_tbl_destroy(ab); - -- spin_unlock_bh(&ab->base_lock); -+ mutex_unlock(&ab->tbl_mtx_lock); - } diff --git a/feeds/ipq95xx/mac80211/patches/qca/348-ath11k-increase-max-scan-param.patch b/feeds/ipq95xx/mac80211/patches/qca/348-ath11k-increase-max-scan-param.patch deleted file mode 100644 index e7b452903..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/348-ath11k-increase-max-scan-param.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 882ee68af56629ef21daea3c451709804e2a5f24 Mon Sep 17 00:00:00 2001 -From: Karthikeyan Kathirvel -Date: Thu, 24 Feb 2022 22:50:24 +0530 -Subject: [PATCH] ath11k: inceasing the max num of ssid/bssid for prb req - -The maximum number of SSIDs in a for active probe requests is currently -reported as 16 (WLAN_SCAN_PARAMS_MAX_SSID) when registering the driver. -The scan_req_params structure only has the capacity to hold 10 SSIDs. -This leads to a buffer overflow which can be triggered from -wpa_supplicant in userspace. When copying the SSIDs into the scan_req_params -structure in the ath11k_mac_op_hw_scan route, it can overwrite the -extraie pointer. - -Firmware supports 16 ssid * 16 bssid, for each ssid 16 bssid combo probe -request will be sent, so totally 256 probe requests supported. So -increasing both max ssid and bssid to 16. - -Signed-off-by: Karthikeyan Kathirvel ---- - drivers/net/wireless/ath/ath11k/wmi.h | 14 +++----------- - 1 file changed, 3 insertions(+), 11 deletions(-) - -diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h -index 3db838e..536b547 100644 ---- a/drivers/net/wireless/ath/ath11k/wmi.h -+++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -3338,9 +3338,6 @@ enum scan_dwelltime_adaptive_mode { - SCAN_DWELL_MODE_STATIC = 4 - }; - --#define WLAN_SCAN_MAX_NUM_SSID 10 --#define WLAN_SCAN_MAX_NUM_BSSID 10 -- - #define WLAN_SCAN_MAX_NUM_CHANNELS 60 - - #define WLAN_SSID_MAX_LEN 32 -@@ -3388,7 +3385,6 @@ struct wmi_vendor_oui { - u32 oui_type_subtype; /* vendor OUI type and subtype */ - }; - --#define WMI_SCAN_MAX_NUM_SSID 0x0A - /* prefix used by scan requestor ids on the host */ - #define WMI_HOST_SCAN_REQUESTOR_ID_PREFIX 0xA000 - -@@ -3396,10 +3392,6 @@ struct wmi_vendor_oui { - /* host cycles through the lower 12 bits to generate ids */ - #define WMI_HOST_SCAN_REQ_ID_PREFIX 0xA000 - --#define WLAN_SCAN_PARAMS_MAX_SSID 16 --#define WLAN_SCAN_PARAMS_MAX_BSSID 4 --#define WLAN_SCAN_PARAMS_MAX_IE_LEN 256 -- - /* Values lower than this may be refused by some firmware revisions with a scan - * completion with a timedout reason. - */ -@@ -3613,8 +3605,8 @@ struct scan_req_params { - struct chan_list chan_list; - struct cfg80211_chan_def *chandef; - u32 notify_scan_events; -- struct wlan_ssid ssid[WLAN_SCAN_MAX_NUM_SSID]; -- struct wmi_mac_addr bssid_list[WLAN_SCAN_MAX_NUM_BSSID]; -+ struct wlan_ssid ssid[WLAN_SCAN_PARAMS_MAX_SSID]; -+ struct wmi_mac_addr bssid_list[WLAN_SCAN_PARAMS_MAX_BSSID]; - struct element_info extraie; - struct element_info htcap; - struct element_info vhtcap; --- -2.7.4 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/349-ath11k-add-tx-delay-to-tsf.patch b/feeds/ipq95xx/mac80211/patches/qca/349-ath11k-add-tx-delay-to-tsf.patch index 5aab2b65c..ab49fe4d0 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/349-ath11k-add-tx-delay-to-tsf.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/349-ath11k-add-tx-delay-to-tsf.patch @@ -28,7 +28,7 @@ Signed-off-by: Hari Chandrakanthan --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -410,6 +410,7 @@ struct ath11k_vif { +@@ -501,6 +501,7 @@ struct ath11k_vif { u32 tid_conf_changed[ATH11K_TID_MAX]; struct ath11k_tid_qos_config tid_cfg[ATH11K_TID_MAX]; u32 tids_rst; @@ -38,7 +38,7 @@ Signed-off-by: Hari Chandrakanthan --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -1525,6 +1525,7 @@ static int ath11k_mac_setup_bcn_tmpl(str +@@ -1532,6 +1532,7 @@ static int ath11k_mac_setup_bcn_tmpl(str u8 *ies; int ret; const u8 *vht_cap_ie; @@ -46,7 +46,7 @@ Signed-off-by: Hari Chandrakanthan if (arvif->vdev_type != WMI_VDEV_TYPE_AP) return 0; -@@ -1557,6 +1558,14 @@ static int ath11k_mac_setup_bcn_tmpl(str +@@ -1564,6 +1565,14 @@ static int ath11k_mac_setup_bcn_tmpl(str else arvif->wpaie_present = false; @@ -61,7 +61,7 @@ Signed-off-by: Hari Chandrakanthan ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn); kfree_skb(bcn); -@@ -7181,6 +7190,7 @@ static void ath11k_mac_op_tx(struct ieee +@@ -7103,6 +7112,7 @@ static void ath11k_mac_op_tx(struct ieee struct ieee80211_key_conf *key = info->control.hw_key; struct ath11k_mgmt_frame_stats *mgmt_stats = &arvif->mgmt_stats; struct ath11k_sta *arsta = NULL; @@ -69,7 +69,7 @@ Signed-off-by: Hari Chandrakanthan u32 info_flags = info->flags; struct ieee80211_sta *sta = control->sta; bool is_prb_rsp; -@@ -7188,6 +7198,7 @@ static void ath11k_mac_op_tx(struct ieee +@@ -7110,6 +7120,7 @@ static void ath11k_mac_op_tx(struct ieee u8 tid, *qos_ctl; bool noack = false; int ret; @@ -77,7 +77,7 @@ Signed-off-by: Hari Chandrakanthan if (unlikely(test_bit(ATH11K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))) { ieee80211_free_txskb(ar->hw, skb); -@@ -7207,6 +7218,12 @@ static void ath11k_mac_op_tx(struct ieee +@@ -7129,6 +7140,12 @@ static void ath11k_mac_op_tx(struct ieee } else if (ieee80211_is_mgmt(hdr->frame_control)) { frm_type = FIELD_GET(IEEE80211_FCTL_STYPE, hdr->frame_control); is_prb_rsp = ieee80211_is_probe_resp(hdr->frame_control); @@ -92,7 +92,7 @@ Signed-off-by: Hari Chandrakanthan if (ret != -EBUSY) --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -10538,6 +10538,144 @@ static void ath11k_wmi_tlv_cfr_cpature_p +@@ -10585,6 +10585,144 @@ static void ath11k_wmi_tlv_cfr_cpature_p } } @@ -136,7 +136,7 @@ Signed-off-by: Hari Chandrakanthan + + arvif->tbtt_offset = tbtt_offset_info->tbtt_offset; + -+ conf = rcu_dereference(arvif->vif->chanctx_conf); ++ conf = rcu_dereference(arvif->vif->bss_conf.chanctx_conf); + if (conf && conf->def.chan->band == NL80211_BAND_2GHZ) { + /* 1Mbps Beacon: */ + /* 144 us ( LPREAMBLE) + 48 (PLCP Header) @@ -237,7 +237,7 @@ Signed-off-by: Hari Chandrakanthan static int ath11k_wmi_tlv_cfr_capture_evt_parse(struct ath11k_base *ab, u16 tag, u16 len, const void *ptr, void *data) -@@ -10582,6 +10720,16 @@ static void ath11k_wmi_parse_cfr_capture +@@ -10629,6 +10767,16 @@ static void ath11k_wmi_parse_cfr_capture "failed to process cfr cpature ret = %d\n", ret); } @@ -254,7 +254,7 @@ Signed-off-by: Hari Chandrakanthan static int ath11k_wmi_peer_ratecode_subtlv_parser(struct ath11k_base *ab, u16 tag, u16 len, const void *ptr, void *data) -@@ -10853,8 +11001,10 @@ static void ath11k_wmi_tlv_op_rx(struct +@@ -10900,8 +11048,10 @@ static void ath11k_wmi_tlv_op_rx(struct case WMI_WDS_PEER_EVENTID: ath11k_wmi_wds_peer_event(ab, skb); break; @@ -268,7 +268,7 @@ Signed-off-by: Hari Chandrakanthan case WMI_TWT_DISABLE_EVENTID: --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -4613,6 +4613,24 @@ struct wmi_vdev_delete_resp_event { +@@ -4626,6 +4626,24 @@ struct wmi_vdev_delete_resp_event { u32 vdev_id; } __packed; diff --git a/feeds/ipq95xx/mac80211/patches/qca/350-01-mac80211-MBSSID-and-EMA-beacon-handling-in-AP-mode.patch b/feeds/ipq95xx/mac80211/patches/qca/350-01-mac80211-MBSSID-and-EMA-beacon-handling-in-AP-mode.patch index 41a889708..30fe9a810 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/350-01-mac80211-MBSSID-and-EMA-beacon-handling-in-AP-mode.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/350-01-mac80211-MBSSID-and-EMA-beacon-handling-in-AP-mode.patch @@ -33,27 +33,10 @@ Signed-off-by: Aloka Dixit net/mac80211/tx.c | 149 ++++++++++++++++++++++++++++++-- 4 files changed, 377 insertions(+), 37 deletions(-) -Index: b/include/net/mac80211.h -=================================================================== ---- a/include/net/mac80211.h 2022-07-27 23:52:19.508575446 +0530 -+++ b/include/net/mac80211.h 2022-07-27 23:52:19.504575477 +0530 -@@ -5047,12 +5047,14 @@ void ieee80211_report_low_ack(struct iee - * @cntdwn_counter_offs: array of IEEE80211_MAX_CNTDWN_COUNTERS_NUM offsets - * to countdown counters. This array can contain zero values which - * should be ignored. -+ * @mbssid_off: position of the multiple bssid element - */ - struct ieee80211_mutable_offsets { - u16 tim_offset; - u16 tim_length; - - u16 cntdwn_counter_offs[IEEE80211_MAX_CNTDWN_COUNTERS_NUM]; -+ u16 mbssid_off; - }; - - /** -@@ -5080,6 +5082,96 @@ ieee80211_beacon_get_template(struct iee - struct ieee80211_mutable_offsets *offs); +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -5268,6 +5268,99 @@ ieee80211_beacon_get_template(struct iee + unsigned int link_id); /** + * enum ieee80211_bcn_tmpl_ema - EMA beacon generation type @@ -95,6 +78,7 @@ Index: b/include/net/mac80211.h +struct sk_buff * +ieee80211_beacon_get_template_ema_index(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, ++ unsigned int link_id, + struct ieee80211_mutable_offsets *offs, + u8 ema_index); + @@ -134,7 +118,8 @@ Index: b/include/net/mac80211.h + */ +struct ieee80211_ema_beacons * +ieee80211_beacon_get_template_ema_list(struct ieee80211_hw *hw, -+ struct ieee80211_vif *vif); ++ struct ieee80211_vif *vif, ++ unsigned int link_id); + +/** + * ieee80211_beacon_free_ema_list - free an EMA beacon template list @@ -146,396 +131,60 @@ Index: b/include/net/mac80211.h +void ieee80211_beacon_free_ema_list(struct ieee80211_ema_beacons *ema_beacons); + +/** ++ * ieee80211_beacon_get_tim - beacon generation function * @hw: pointer obtained from ieee80211_alloc_hw(). * @vif: &struct ieee80211_vif pointer from the add_interface callback. -Index: b/net/mac80211/cfg.c -=================================================================== ---- a/net/mac80211/cfg.c 2022-07-27 23:52:19.508575446 +0530 -+++ b/net/mac80211/cfg.c 2022-07-27 23:52:19.504575477 +0530 -@@ -990,14 +990,47 @@ static int ieee80211_set_ftm_responder_p - return 0; +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1171,13 +1171,19 @@ ieee80211_vif_get_shift(struct ieee80211 } -+static int ieee80211_get_mbssid_beacon_len(struct cfg80211_mbssid_elems *elems) -+{ -+ int i, len = 0; -+ -+ if (!elems) -+ return 0; -+ -+ for (i = 0; i < elems->cnt; i++) -+ len += elems->elem[i].len; -+ -+ return len; -+} -+ -+static u8 *ieee80211_copy_mbssid_beacon(u8 *pos, -+ struct cfg80211_mbssid_elems *dest, -+ struct cfg80211_mbssid_elems *src) -+{ -+ int i; -+ -+ if (!dest || !src) -+ return pos; -+ -+ dest->cnt = src->cnt; -+ for (i = 0; i < dest->cnt; i++) { -+ dest->elem[i].len = src->elem[i].len; -+ memcpy(pos, src->elem[i].data, dest->elem[i].len); -+ dest->elem[i].data = pos; -+ pos += dest->elem[i].len; -+ } -+ -+ return pos; -+} -+ - static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, - struct cfg80211_beacon_data *params, - const struct ieee80211_csa_settings *csa, - const struct ieee80211_color_change_settings *cca) + static inline int +-ieee80211_get_mbssid_beacon_len(struct cfg80211_mbssid_elems *elems) ++ieee80211_get_mbssid_beacon_len(struct cfg80211_mbssid_elems *elems, int index) { - struct beacon_data *new, *old; -- int new_head_len, new_tail_len; -- const u8 *cap; -+ int new_head_len, new_tail_len, new_mbssid_len = 0; -+ const u8 *cap, *pos; - struct ieee80211_he_operation *he_oper = NULL; - int size, err; - u32 changed = BSS_CHANGED_BEACON; -@@ -1022,12 +1055,35 @@ static int ieee80211_assign_beacon(struc - else - new_tail_len = old->tail_len; + int i, len = 0; -- size = sizeof(*new) + new_head_len + new_tail_len; -+ if (params->mbssid_ies) -+ new_mbssid_len = ieee80211_get_mbssid_beacon_len(params->mbssid_ies); -+ else if (old && old->mbssid_ies) -+ new_mbssid_len = ieee80211_get_mbssid_beacon_len(old->mbssid_ies); -+ -+ size = sizeof(*new) + new_head_len + new_tail_len + new_mbssid_len; +- if (!elems) ++ if (!elems || !elems->cnt) + return 0; - new = kzalloc(size, GFP_KERNEL); - if (!new) - return -ENOMEM; - -+ if (new_mbssid_len) { -+ if (params->mbssid_ies) -+ new->mbssid_ies = kzalloc(struct_size(new->mbssid_ies, -+ elem, -+ params->mbssid_ies->cnt), -+ GFP_KERNEL); -+ else if (old && old->mbssid_ies) -+ new->mbssid_ies = kzalloc(struct_size(new->mbssid_ies, -+ elem, -+ old->mbssid_ies->cnt), -+ GFP_KERNEL); -+ -+ if (!new->mbssid_ies) { -+ err = -ENOMEM; -+ goto error; -+ } -+ } -+ - /* start filling the new info now */ - - /* -@@ -1039,6 +1095,15 @@ static int ieee80211_assign_beacon(struc - new->head_len = new_head_len; - new->tail_len = new_tail_len; - -+ if (params->mbssid_ies) -+ pos = ieee80211_copy_mbssid_beacon(new->tail + new_tail_len, -+ new->mbssid_ies, -+ params->mbssid_ies); -+ else if (old) -+ pos = ieee80211_copy_mbssid_beacon(new->tail + new_tail_len, -+ new->mbssid_ies, -+ old->mbssid_ies); -+ - if (csa) { - new->cntdwn_current_counter = csa->count; - memcpy(new->cntdwn_counter_offsets, csa->counter_offsets_beacon, -@@ -1064,10 +1129,8 @@ static int ieee80211_assign_beacon(struc - - err = ieee80211_set_probe_resp(sdata, params->probe_resp, - params->probe_resp_len, csa, cca); -- if (err < 0) { -- kfree(new); -- return err; -- } -+ if (err < 0) -+ goto error; - if (err == 0) - changed |= BSS_CHANGED_AP_PROBE_RESP; - -@@ -1079,10 +1142,8 @@ static int ieee80211_assign_beacon(struc - params->civicloc, - params->civicloc_len); - -- if (err < 0) { -- kfree(new); -- return err; -- } -+ if (err < 0) -+ goto error; - - changed |= BSS_CHANGED_FTM_RESPONDER; - } -@@ -1109,10 +1170,19 @@ static int ieee80211_assign_beacon(struc - - rcu_assign_pointer(sdata->u.ap.beacon, new); - -- if (old) -+ if (old) { -+ kfree(old->mbssid_ies); - kfree_rcu(old, rcu_head); -+ } - - return changed; -+ -+error: -+ if (new) { -+ kfree(new->mbssid_ies); -+ kfree(new); -+ } -+ return err; - } - - static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, -@@ -1277,8 +1347,10 @@ static int ieee80211_start_ap(struct wip - if (err) { - old = sdata_dereference(sdata->u.ap.beacon, sdata); - -- if (old) -+ if (old) { -+ kfree(old->mbssid_ies); - kfree_rcu(old, rcu_head); -+ } - RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); - goto error; - } -@@ -1361,8 +1433,11 @@ static int ieee80211_stop_ap(struct wiph - - mutex_unlock(&local->mtx); - -- kfree(sdata->u.ap.next_beacon); -- sdata->u.ap.next_beacon = NULL; -+ if (sdata->u.ap.next_beacon) { -+ kfree(sdata->u.ap.next_beacon->mbssid_ies); -+ kfree(sdata->u.ap.next_beacon); -+ sdata->u.ap.next_beacon = NULL; -+ } - - /* turn off carrier for this interface and dependent VLANs */ - list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) -@@ -1374,6 +1449,7 @@ static int ieee80211_stop_ap(struct wiph - RCU_INIT_POINTER(sdata->u.ap.probe_resp, NULL); - RCU_INIT_POINTER(sdata->u.ap.fils_discovery, NULL); - RCU_INIT_POINTER(sdata->u.ap.unsol_bcast_probe_resp, NULL); -+ kfree(old_beacon->mbssid_ies); - kfree_rcu(old_beacon, rcu_head); - if (old_probe_resp) - kfree_rcu(old_probe_resp, rcu_head); -@@ -3190,16 +3266,30 @@ cfg80211_beacon_dup(struct cfg80211_beac - struct cfg80211_beacon_data *new_beacon; - u8 *pos; - int len; -+ int mbssid_len = ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies); - - len = beacon->head_len + beacon->tail_len + beacon->beacon_ies_len + - beacon->proberesp_ies_len + beacon->assocresp_ies_len + -- beacon->probe_resp_len + beacon->lci_len + beacon->civicloc_len; -+ beacon->probe_resp_len + beacon->lci_len + beacon->civicloc_len + -+ mbssid_len; - - new_beacon = kzalloc(sizeof(*new_beacon) + len, GFP_KERNEL); - if (!new_beacon) - return NULL; - -+ if (mbssid_len) { -+ new_beacon->mbssid_ies = kzalloc(struct_size(new_beacon->mbssid_ies, -+ elem, -+ beacon->mbssid_ies->cnt), -+ GFP_KERNEL); -+ if (!new_beacon->mbssid_ies) { -+ kfree(new_beacon); -+ return NULL; -+ } -+ } -+ - pos = (u8 *)(new_beacon + 1); -+ - if (beacon->head_len) { - new_beacon->head_len = beacon->head_len; - new_beacon->head = pos; -@@ -3236,6 +3326,9 @@ cfg80211_beacon_dup(struct cfg80211_beac - memcpy(pos, beacon->probe_resp, beacon->probe_resp_len); - pos += beacon->probe_resp_len; - } -+ if (mbssid_len) -+ pos = ieee80211_copy_mbssid_beacon(pos, new_beacon->mbssid_ies, -+ beacon->mbssid_ies); - - /* might copy -1, meaning no changes requested */ - new_beacon->ftm_responder = beacon->ftm_responder; -@@ -3285,8 +3378,11 @@ static int ieee80211_set_after_csa_beaco - case NL80211_IFTYPE_AP: - err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon, - NULL, NULL); -- kfree(sdata->u.ap.next_beacon); -- sdata->u.ap.next_beacon = NULL; -+ if (sdata->u.ap.next_beacon) { -+ kfree(sdata->u.ap.next_beacon->mbssid_ies); -+ kfree(sdata->u.ap.next_beacon); -+ sdata->u.ap.next_beacon = NULL; -+ } - - if (err < 0) - return err; -@@ -3441,8 +3537,10 @@ static int ieee80211_set_csa_beacon(stru - if ((params->n_counter_offsets_beacon > - IEEE80211_MAX_CNTDWN_COUNTERS_NUM) || - (params->n_counter_offsets_presp > -- IEEE80211_MAX_CNTDWN_COUNTERS_NUM)) -- return -EINVAL; -+ IEEE80211_MAX_CNTDWN_COUNTERS_NUM)) { -+ err = -EINVAL; -+ goto error; -+ } - - csa.counter_offsets_beacon = params->counter_offsets_beacon; - csa.counter_offsets_presp = params->counter_offsets_presp; -@@ -3451,10 +3549,8 @@ static int ieee80211_set_csa_beacon(stru - csa.count = params->count; - - err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa, &csa, NULL); -- if (err < 0) { -- kfree(sdata->u.ap.next_beacon); -- return err; -- } -+ if (err < 0) -+ goto error; - *changed |= err; - - break; -@@ -3537,13 +3633,24 @@ static int ieee80211_set_csa_beacon(stru - } - - return 0; -+ -+error: -+ if (sdata->vif.type == NL80211_IFTYPE_AP && sdata->u.ap.next_beacon) { -+ kfree(sdata->u.ap.next_beacon->mbssid_ies); -+ kfree(sdata->u.ap.next_beacon); -+ sdata->u.ap.next_beacon = NULL; -+ } -+ return err; - } - - static void ieee80211_color_change_abort(struct ieee80211_sub_if_data *sdata) - { - sdata->vif.color_change_active = false; -- kfree(sdata->u.ap.next_beacon); -- sdata->u.ap.next_beacon = NULL; -+ if (sdata->u.ap.next_beacon) { -+ kfree(sdata->u.ap.next_beacon->mbssid_ies); -+ kfree(sdata->u.ap.next_beacon); -+ sdata->u.ap.next_beacon = NULL; -+ } - - cfg80211_color_change_aborted_notify(sdata->dev); - } -@@ -4282,8 +4389,11 @@ ieee80211_set_after_color_change_beacon( - - ret = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon, - NULL, NULL); -- kfree(sdata->u.ap.next_beacon); -- sdata->u.ap.next_beacon = NULL; -+ if (sdata->u.ap.next_beacon) { -+ kfree(sdata->u.ap.next_beacon->mbssid_ies); -+ kfree(sdata->u.ap.next_beacon); -+ sdata->u.ap.next_beacon = NULL; -+ } - - if (ret < 0) - return ret; -@@ -4326,7 +4436,11 @@ ieee80211_set_color_change_beacon(struct - err = ieee80211_assign_beacon(sdata, ¶ms->beacon_color_change, - NULL, &color_change); - if (err < 0) { -- kfree(sdata->u.ap.next_beacon); -+ if (sdata->u.ap.next_beacon) { -+ kfree(sdata->u.ap.next_beacon->mbssid_ies); -+ kfree(sdata->u.ap.next_beacon); -+ sdata->u.ap.next_beacon = NULL; -+ } - return err; - } - *changed |= err; -Index: b/net/mac80211/ieee80211_i.h -=================================================================== ---- a/net/mac80211/ieee80211_i.h 2022-07-27 23:52:19.508575446 +0530 -+++ b/net/mac80211/ieee80211_i.h 2022-07-27 23:52:19.504575477 +0530 -@@ -265,6 +265,7 @@ struct beacon_data { - struct ieee80211_meshconf_ie *meshconf; - u16 cntdwn_counter_offsets[IEEE80211_MAX_CNTDWN_COUNTERS_NUM]; - u8 cntdwn_current_counter; -+ struct cfg80211_mbssid_elems *mbssid_ies; - struct rcu_head rcu_head; - }; - -Index: b/net/mac80211/tx.c -=================================================================== ---- a/net/mac80211/tx.c 2022-07-27 23:52:19.508575446 +0530 -+++ b/net/mac80211/tx.c 2022-07-27 23:54:02.027794403 +0530 -@@ -5338,33 +5338,72 @@ ieee80211_beacon_get_finish(struct ieee8 - IEEE80211_TX_CTL_FIRST_FRAGMENT; - } - -+static int ieee80211_beacon_mbssid_len(struct beacon_data *beacon, int index) -+{ -+ int len = 0; -+ -+ if (!beacon->mbssid_ies || !beacon->mbssid_ies->cnt) ++ if (index >= elems->cnt) + return 0; -+ else if (index >= beacon->mbssid_ies->cnt) -+ return -1; + + if (index >= IEEE80211_BCN_EMA_BASE) -+ return beacon->mbssid_ies->elem[index].len; ++ return elems->elem[index].len; + -+ /* IEEE80211_BCN_EMA_DISABLED */ -+ for (index = IEEE80211_BCN_EMA_BASE; index < beacon->mbssid_ies->cnt; -+ index++) -+ len += beacon->mbssid_ies->elem[index].len; -+ -+ return len; -+} -+ -+static void ieee80211_beacon_add_mbssid(struct beacon_data *beacon, int index, -+ struct sk_buff *skb) -+{ + for (i = 0; i < elems->cnt; i++) + len += elems->elem[i].len; + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -5379,13 +5379,20 @@ ieee80211_beacon_get_finish(struct ieee8 + } + + static void +-ieee80211_beacon_add_mbssid(struct sk_buff *skb, struct beacon_data *beacon) ++ieee80211_beacon_add_mbssid(struct sk_buff *skb, int index, struct beacon_data *beacon) + { + int i; + +- if (!beacon->mbssid_ies) + if (!beacon->mbssid_ies || !beacon->mbssid_ies->cnt || -+ index >= beacon->mbssid_ies->cnt) -+ return; -+ ++ index >= beacon->mbssid_ies->cnt) + return; + + if (index >= IEEE80211_BCN_EMA_BASE) { + skb_put_data(skb, beacon->mbssid_ies->elem[index].data, + beacon->mbssid_ies->elem[index].len); + return; + } + -+ /* IEEE80211_BCN_EMA_DISABLED */ -+ for (index = IEEE80211_BCN_EMA_BASE; index < beacon->mbssid_ies->cnt; -+ index++) -+ skb_put_data(skb, beacon->mbssid_ies->elem[index].data, -+ beacon->mbssid_ies->elem[index].len); -+} -+ - static struct sk_buff * - ieee80211_beacon_get_ap(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, + for (i = 0; i < beacon->mbssid_ies->cnt; i++) + skb_put_data(skb, beacon->mbssid_ies->elem[i].data, + beacon->mbssid_ies->elem[i].len); +@@ -5398,7 +5405,8 @@ ieee80211_beacon_get_ap(struct ieee80211 struct ieee80211_mutable_offsets *offs, bool is_template, struct beacon_data *beacon, @@ -545,54 +194,32 @@ Index: b/net/mac80211/tx.c { struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); - struct ieee80211_if_ap *ap = &sdata->u.ap; - struct sk_buff *skb = NULL; - u16 csa_off_base = 0; -+ int mbssid_len = 0; - -- if (beacon->cntdwn_counter_offsets[0]) { -- if (!is_template) -- ieee80211_beacon_update_cntdwn(vif); -- -- ieee80211_set_beacon_cntdwn(sdata, beacon); -- } -+ mbssid_len = ieee80211_beacon_mbssid_len(beacon, ema_index); -+ if (mbssid_len == -1) -+ return NULL; - +@@ -5417,7 +5425,7 @@ ieee80211_beacon_get_ap(struct ieee80211 /* headroom, head length, -- * tail length and maximum TIM length -+ * tail length, maximum TIM length and multiple BSSID length + * tail length, maximum TIM length and multiple BSSID length */ +- mbssid_len = ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies); ++ mbssid_len = ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies, ema_index); skb = dev_alloc_skb(local->tx_headroom + beacon->head_len + beacon->tail_len + 256 + -- local->hw.extra_beacon_tailroom); -+ local->hw.extra_beacon_tailroom + mbssid_len); - if (!skb) - return NULL; + local->hw.extra_beacon_tailroom + mbssid_len); +@@ -5435,7 +5443,7 @@ ieee80211_beacon_get_ap(struct ieee80211 + offs->cntdwn_counter_offs[0] = beacon->cntdwn_counter_offsets[0]; -@@ -5382,6 +5421,14 @@ ieee80211_beacon_get_ap(struct ieee80211 - csa_off_base = skb->len; - } + if (mbssid_len) { +- ieee80211_beacon_add_mbssid(skb, beacon); ++ ieee80211_beacon_add_mbssid(skb, ema_index, beacon); + offs->mbssid_off = skb->len - mbssid_len; + } -+ if (mbssid_len) { -+ ieee80211_beacon_add_mbssid(beacon, ema_index, skb); -+ if (offs) { -+ offs->mbssid_off = skb->len - mbssid_len; -+ csa_off_base = skb->len; -+ } -+ } -+ - if (beacon->tail) - skb_put_data(skb, beacon->tail, beacon->tail_len); - -@@ -5393,11 +5440,47 @@ ieee80211_beacon_get_ap(struct ieee80211 +@@ -5454,12 +5462,49 @@ ieee80211_beacon_get_ap(struct ieee80211 return skb; } +static void +ieee80211_beacon_get_ap_ema_list(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, ++ struct ieee80211_link_data *link, + struct ieee80211_mutable_offsets *offs, + bool is_template, struct beacon_data *beacon, + struct ieee80211_chanctx_conf *chanctx_conf, @@ -610,7 +237,7 @@ Index: b/net/mac80211/tx.c + beacons->cnt < beacon->mbssid_ies->cnt; + beacons->cnt++) { + beacons->bcn[beacons->cnt].skb = -+ ieee80211_beacon_get_ap(hw, vif, ++ ieee80211_beacon_get_ap(hw, vif, link, + &beacons->bcn[beacons->cnt].offs, + is_template, beacon, + chanctx_conf, beacons->cnt); @@ -628,56 +255,51 @@ Index: b/net/mac80211/tx.c __ieee80211_beacon_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_mutable_offsets *offs, -- bool is_template) -+ bool is_template, + bool is_template, +- unsigned int link_id) ++ unsigned int link_id, + int ema_index, + struct ieee80211_ema_beacons **ema_beacons) { struct ieee80211_local *local = hw_to_local(hw); struct beacon_data *beacon = NULL; -@@ -5423,8 +5506,23 @@ __ieee80211_beacon_get(struct ieee80211_ +@@ -5488,8 +5533,16 @@ __ieee80211_beacon_get(struct ieee80211_ if (!beacon) goto out; -- skb = ieee80211_beacon_get_ap(hw, vif, offs, is_template, +- skb = ieee80211_beacon_get_ap(hw, vif, link, offs, is_template, - beacon, chanctx_conf); -+ if (beacon->cntdwn_counter_offsets[0]) { -+ if (!is_template) -+ ieee80211_beacon_update_cntdwn(vif); -+ -+ ieee80211_set_beacon_cntdwn(sdata, beacon); -+ } -+ + if (ema_beacons) -+ (void)ieee80211_beacon_get_ap_ema_list(hw, vif, offs, ++ (void)ieee80211_beacon_get_ap_ema_list(hw, vif, link, offs, + is_template, + beacon, + chanctx_conf, + ema_beacons); + else -+ skb = ieee80211_beacon_get_ap(hw, vif, offs, ++ skb = ieee80211_beacon_get_ap(hw, vif, link, offs, + is_template, beacon, + chanctx_conf, ema_index); } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; struct ieee80211_hdr *hdr; -@@ -5510,16 +5608,51 @@ ieee80211_beacon_get_template(struct iee - struct ieee80211_vif *vif, - struct ieee80211_mutable_offsets *offs) +@@ -5577,10 +5630,45 @@ ieee80211_beacon_get_template(struct iee + struct ieee80211_mutable_offsets *offs, + unsigned int link_id) { -- return __ieee80211_beacon_get(hw, vif, offs, true); -+ return __ieee80211_beacon_get(hw, vif, offs, true, -+ IEEE80211_BCN_EMA_DISABLED, NULL); +- return __ieee80211_beacon_get(hw, vif, offs, true, link_id); ++ return __ieee80211_beacon_get(hw, vif, offs, true, link_id, ++ IEEE80211_BCN_EMA_DISABLED, NULL); } EXPORT_SYMBOL(ieee80211_beacon_get_template); +struct sk_buff * +ieee80211_beacon_get_template_ema_index(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, ++ unsigned int link_id, + struct ieee80211_mutable_offsets *offs, + u8 ema_index) +{ -+ return __ieee80211_beacon_get(hw, vif, offs, true, ema_index, NULL); ++ return __ieee80211_beacon_get(hw, vif, offs, true, link_id, ema_index, NULL); +} +EXPORT_SYMBOL(ieee80211_beacon_get_template_ema_index); + @@ -694,10 +316,11 @@ Index: b/net/mac80211/tx.c + +struct ieee80211_ema_beacons * +ieee80211_beacon_get_template_ema_list(struct ieee80211_hw *hw, -+ struct ieee80211_vif *vif) ++ struct ieee80211_vif *vif, ++ unsigned int link_id) +{ + struct ieee80211_ema_beacons *ema_beacons = NULL; -+ (void)__ieee80211_beacon_get(hw, vif, NULL, false, ++ (void)__ieee80211_beacon_get(hw, vif, NULL, true, link_id, + IEEE80211_BCN_EMA_BASE, &ema_beacons); + return ema_beacons; +} @@ -705,13 +328,47 @@ Index: b/net/mac80211/tx.c + struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u16 *tim_offset, u16 *tim_length) + u16 *tim_offset, u16 *tim_length, +@@ -5588,7 +5676,7 @@ struct sk_buff *ieee80211_beacon_get_tim { struct ieee80211_mutable_offsets offs = {}; -- struct sk_buff *bcn = __ieee80211_beacon_get(hw, vif, &offs, false); -+ struct sk_buff *bcn = __ieee80211_beacon_get(hw, vif, &offs, false, -+ IEEE80211_BCN_EMA_DISABLED, -+ NULL); + struct sk_buff *bcn = __ieee80211_beacon_get(hw, vif, &offs, false, +- link_id); ++ link_id, IEEE80211_BCN_EMA_DISABLED, NULL); struct sk_buff *copy; - struct ieee80211_supported_band *sband; int shift; + +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1050,11 +1050,11 @@ static int ieee80211_assign_beacon(struc + if (params->mbssid_ies) { + mbssid = params->mbssid_ies; + size += struct_size(new->mbssid_ies, elem, mbssid->cnt); +- size += ieee80211_get_mbssid_beacon_len(mbssid); ++ size += ieee80211_get_mbssid_beacon_len(mbssid, IEEE80211_BCN_EMA_DISABLED); + } else if (old && old->mbssid_ies) { + mbssid = old->mbssid_ies; + size += struct_size(new->mbssid_ies, elem, mbssid->cnt); +- size += ieee80211_get_mbssid_beacon_len(mbssid); ++ size += ieee80211_get_mbssid_beacon_len(mbssid, IEEE80211_BCN_EMA_DISABLED); + } + + new = kzalloc(size, GFP_KERNEL); +@@ -1077,7 +1077,7 @@ static int ieee80211_assign_beacon(struc + + new->mbssid_ies = (void *)pos; + pos += struct_size(new->mbssid_ies, elem, mbssid->cnt); +- ieee80211_copy_mbssid_beacon(pos, new->mbssid_ies, mbssid); ++ pos += ieee80211_copy_mbssid_beacon(pos, new->mbssid_ies, mbssid); + /* update bssid_indicator */ + link_conf->bssid_indicator = + ilog2(__roundup_pow_of_two(mbssid->cnt + 1)); +@@ -3287,7 +3287,7 @@ cfg80211_beacon_dup(struct cfg80211_beac + len = beacon->head_len + beacon->tail_len + beacon->beacon_ies_len + + beacon->proberesp_ies_len + beacon->assocresp_ies_len + + beacon->probe_resp_len + beacon->lci_len + beacon->civicloc_len + +- ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies); ++ ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies, IEEE80211_BCN_EMA_DISABLED); + + new_beacon = kzalloc(sizeof(*new_beacon) + len, GFP_KERNEL); + if (!new_beacon) diff --git a/feeds/ipq95xx/mac80211/patches/qca/350-02-mac80211-MBSSID-channel-switch.patch b/feeds/ipq95xx/mac80211/patches/qca/350-02-mac80211-MBSSID-channel-switch.patch deleted file mode 100644 index 837081db5..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/350-02-mac80211-MBSSID-channel-switch.patch +++ /dev/null @@ -1,52 +0,0 @@ -From c40df06d84d97f450b3524dc8ef5a4dd5ce5af61 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Tue, 5 Oct 2021 21:09:38 -0700 -Subject: [PATCH 02/14] mac80211: MBSSID channel switch - -Trigger ieee80211_csa_finish() on the non-transmitting interfaces -when channel switch concludes on the transmitting interface. - -Signed-off-by: John Crispin -Co-developed-by: Aloka Dixit -Signed-off-by: Aloka Dixit ---- - net/mac80211/cfg.c | 16 ++++++++++++++-- - 1 file changed, 14 insertions(+), 2 deletions(-) - ---- a/net/mac80211/cfg.c -+++ b/net/mac80211/cfg.c -@@ -3351,9 +3351,32 @@ cfg80211_beacon_dup(struct cfg80211_beac - void ieee80211_csa_finish(struct ieee80211_vif *vif) - { - struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); -+ struct ieee80211_local *local = sdata->local; - -- ieee80211_queue_work(&sdata->local->hw, -- &sdata->csa_finalize_work); -+ rcu_read_lock(); -+ -+ if (vif->mbssid_tx_vif == vif) { -+ /* Trigger ieee80211_csa_finish() on the non-transmitting -+ * interfaces when channel switch is received on -+ * transmitting interface -+ */ -+ struct ieee80211_sub_if_data *iter; -+ -+ list_for_each_entry_rcu(iter, &local->interfaces, list) { -+ if (!ieee80211_sdata_running(iter)) -+ continue; -+ -+ if (iter == sdata || iter->vif.mbssid_tx_vif != vif) -+ continue; -+ -+ ieee80211_queue_work(&iter->local->hw, -+ &iter->csa_finalize_work); -+ } -+ } -+ -+ ieee80211_queue_work(&local->hw, &sdata->csa_finalize_work); -+ -+ rcu_read_unlock(); - } - EXPORT_SYMBOL(ieee80211_csa_finish); - diff --git a/feeds/ipq95xx/mac80211/patches/qca/350-04-ath11k-set-MBSSID-and-EMA-driver-capabilities.patch b/feeds/ipq95xx/mac80211/patches/qca/350-04-ath11k-set-MBSSID-and-EMA-driver-capabilities.patch index c130bc5c8..11a1806c6 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/350-04-ath11k-set-MBSSID-and-EMA-driver-capabilities.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/350-04-ath11k-set-MBSSID-and-EMA-driver-capabilities.patch @@ -19,7 +19,7 @@ Signed-off-by: Aloka Dixit --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -11686,19 +11686,23 @@ static void ath11k_mac_fetch_coex_info(s +@@ -12015,19 +12015,23 @@ static void ath11k_mac_fetch_coex_info(s static const u8 ath11k_if_types_ext_capa[] = { [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING, @@ -43,7 +43,15 @@ Signed-off-by: Aloka Dixit }; static const struct wiphy_iftype_ext_capab ath11k_iftypes_ext_capa[] = { -@@ -11945,6 +11949,9 @@ static int __ath11k_mac_register(struct +@@ -12148,6 +12152,7 @@ static int __ath11k_mac_register(struct + ieee80211_hw_set(ar->hw, QUEUE_CONTROL); + ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG); + ieee80211_hw_set(ar->hw, REPORTS_LOW_ACK); ++ ieee80211_hw_set(ar->hw, SUPPORTS_MULTI_BSSID); + + if (ath11k_frame_mode == ATH11K_HW_TXRX_ETHERNET) { + ieee80211_hw_set(ar->hw, SUPPORTS_TX_ENCAP_OFFLOAD); +@@ -12295,6 +12300,9 @@ static int __ath11k_mac_register(struct wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER); diff --git a/feeds/ipq95xx/mac80211/patches/qca/350-08-ath11k-move-vif-parameter-setting-in-a-different-fun.patch b/feeds/ipq95xx/mac80211/patches/qca/350-08-ath11k-move-vif-parameter-setting-in-a-different-fun.patch index dfd590eaf..a779c99b6 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/350-08-ath11k-move-vif-parameter-setting-in-a-different-fun.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/350-08-ath11k-move-vif-parameter-setting-in-a-different-fun.patch @@ -14,10 +14,11 @@ Signed-off-by: Aloka Dixit --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -1423,31 +1423,16 @@ err_mon_del: +@@ -1521,32 +1521,16 @@ err_mon_del: + mutex_unlock(&ar->conf_mutex); return ret; } - +- -static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif) +static void ath11k_mac_setup_bcn_tmpl_vif_params(struct ath11k_vif *arvif, + struct sk_buff *bcn) @@ -38,7 +39,7 @@ Signed-off-by: Aloka Dixit - if (arvif->vdev_type != WMI_VDEV_TYPE_AP) - return 0; - -- bcn = ieee80211_beacon_get_template(hw, vif, &offs); +- bcn = ieee80211_beacon_get_template(hw, vif, &offs, 0); - if (!bcn) { - ath11k_warn(ab, "failed to get beacon template from mac80211\n"); - return -EPERM; @@ -49,7 +50,7 @@ Signed-off-by: Aloka Dixit ies += sizeof(mgmt->u.beacon); if (cfg80211_find_ie(WLAN_EID_RSN, ies, (skb_tail_pointer(bcn) - ies))) -@@ -1473,10 +1458,32 @@ static int ath11k_mac_setup_bcn_tmpl(str +@@ -1572,10 +1556,32 @@ static int ath11k_mac_setup_bcn_tmpl(str * staggered batch have the same TSF. */ if (arvif->tbtt_offset) { diff --git a/feeds/ipq95xx/mac80211/patches/qca/350-09-ath11k-EMA-beacon-support.patch b/feeds/ipq95xx/mac80211/patches/qca/350-09-ath11k-EMA-beacon-support.patch index e2c5d7504..a564a971b 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/350-09-ath11k-EMA-beacon-support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/350-09-ath11k-EMA-beacon-support.patch @@ -18,7 +18,7 @@ Signed-off-by: Aloka Dixit --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -1445,7 +1445,7 @@ static void ath11k_mac_setup_bcn_tmpl_vi +@@ -1543,7 +1543,7 @@ static void ath11k_mac_setup_bcn_tmpl_vi vht_cap = (void *)(vht_cap_ie + 2); arvif->vht_cap = vht_cap->vht_cap_info; } @@ -27,7 +27,7 @@ Signed-off-by: Aloka Dixit if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, WLAN_OUI_TYPE_MICROSOFT_WPA, -@@ -1464,37 +1464,116 @@ static void ath11k_mac_setup_bcn_tmpl_vi +@@ -1562,37 +1562,116 @@ static void ath11k_mac_setup_bcn_tmpl_vi } @@ -67,7 +67,7 @@ Signed-off-by: Aloka Dixit + + tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv; + beacons = ieee80211_beacon_get_template_ema_list(tx_arvif->ar->hw, -+ tx_arvif->vif); ++ tx_arvif->vif, 0); + if (!beacons || !beacons->cnt) { + ath11k_warn(arvif->ar->ab, + "failed to get ema beacon templates from mac80211\n"); @@ -107,7 +107,7 @@ Signed-off-by: Aloka Dixit + tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv; + + bcn = ieee80211_beacon_get_template(tx_arvif->ar->hw, tx_arvif->vif, -+ &offs); ++ &offs, 0); - bcn = ieee80211_beacon_get_template(hw, vif, &offs); if (!bcn) { @@ -158,7 +158,7 @@ Signed-off-by: Aloka Dixit struct ieee80211_vif *vif = arvif->vif; --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -1980,7 +1980,7 @@ int ath11k_wmi_send_bcn_offload_control_ +@@ -2012,7 +2012,7 @@ int ath11k_wmi_send_bcn_offload_control_ int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id, struct ieee80211_mutable_offsets *offs, @@ -167,7 +167,7 @@ Signed-off-by: Aloka Dixit { struct ath11k_pdev_wmi *wmi = ar->wmi; struct wmi_bcn_tmpl_cmd *cmd; -@@ -2018,6 +2018,8 @@ int ath11k_wmi_bcn_tmpl(struct ath11k *a +@@ -2050,6 +2050,8 @@ int ath11k_wmi_bcn_tmpl(struct ath11k *a } cmd->buf_len = bcn->len; @@ -176,7 +176,7 @@ Signed-off-by: Aloka Dixit ptr = skb->data + sizeof(*cmd); -@@ -10287,7 +10289,7 @@ static int ath11k_wmi_tbtt_offset_subtlv +@@ -10667,7 +10669,7 @@ static int ath11k_wmi_tbtt_offset_subtlv mgmt = (void *)bcn->data; memcpy(&mgmt->u.beacon.timestamp, &adjusted_tsf, sizeof(adjusted_tsf)); @@ -187,7 +187,7 @@ Signed-off-by: Aloka Dixit if (ret) --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -3898,6 +3898,11 @@ struct wmi_ftm_event_msg { +@@ -3920,6 +3920,11 @@ struct wmi_ftm_event_msg { #define WMI_BEACON_TX_BUFFER_SIZE 512 @@ -199,7 +199,7 @@ Signed-off-by: Aloka Dixit struct wmi_bcn_tmpl_cmd { u32 tlv_header; u32 vdev_id; -@@ -3908,6 +3913,11 @@ struct wmi_bcn_tmpl_cmd { +@@ -3930,6 +3935,11 @@ struct wmi_bcn_tmpl_cmd { u32 csa_event_bitmap; u32 mbssid_ie_offset; u32 esp_ie_offset; @@ -211,7 +211,7 @@ Signed-off-by: Aloka Dixit } __packed; struct wmi_key_seq_counter { -@@ -6931,7 +6941,7 @@ int ath11k_wmi_set_per_peer_per_tid_cfg( +@@ -7393,7 +7403,7 @@ int ath11k_wmi_set_per_peer_per_tid_cfg( const struct wmi_per_peer_per_tid_cfg_arg *arg); int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id, struct ieee80211_mutable_offsets *offs, diff --git a/feeds/ipq95xx/mac80211/patches/qca/350-11-nl80211-add-RNR-for-EMA-AP.patch b/feeds/ipq95xx/mac80211/patches/qca/350-11-nl80211-add-RNR-for-EMA-AP.patch index 7afc0782a..d25dd1431 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/350-11-nl80211-add-RNR-for-EMA-AP.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/350-11-nl80211-add-RNR-for-EMA-AP.patch @@ -21,15 +21,12 @@ Signed-off-by: Aloka Dixit net/wireless/nl80211.c | 50 ++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+) -diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h -index 0a1ad2903fa2..5ec7d35a77b7 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h -@@ -1116,6 +1116,25 @@ struct cfg80211_mbssid_elems { - } elem[]; +@@ -1203,6 +1203,25 @@ struct cfg80211_mbssid_elems { }; -+/** + /** + * struct cfg80211_rnr_elems - Reduced neighbor report (RNR) elements + * @ies: array of extra information element(s) to add into Beacon frames for + * RNR or %NULL. @@ -48,10 +45,11 @@ index 0a1ad2903fa2..5ec7d35a77b7 100644 + } elem[]; +}; + - /** ++/** * struct cfg80211_beacon_data - beacon data + * @link_id: the link ID for the AP MLD link sending this beacon * @head: head portion of beacon (before TIM IE) -@@ -1135,6 +1154,7 @@ struct cfg80211_mbssid_elems { +@@ -1222,6 +1241,7 @@ struct cfg80211_mbssid_elems { * @probe_resp_len: length of probe response template (@probe_resp) * @probe_resp: probe response template (AP mode only) * @mbssid_ies: multiple BSSID elements @@ -59,7 +57,7 @@ index 0a1ad2903fa2..5ec7d35a77b7 100644 * @ftm_responder: enable FTM responder functionality; -1 for no change * (which also implies no change in LCI/civic location data) * @lci: Measurement Report element content, starting with Measurement Token -@@ -1153,6 +1173,7 @@ struct cfg80211_beacon_data { +@@ -1245,6 +1265,7 @@ struct cfg80211_beacon_data { const u8 *lci; const u8 *civicloc; struct cfg80211_mbssid_elems *mbssid_ies; @@ -67,14 +65,12 @@ index 0a1ad2903fa2..5ec7d35a77b7 100644 s8 ftm_responder; u8 bss_color_info; -diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h -index f62c062d7c18..31ca813446c6 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h -@@ -2659,6 +2659,17 @@ enum nl80211_commands { - * %NL80211_CMD_JOIN_MESH from user-space. +@@ -2761,6 +2761,17 @@ enum nl80211_commands { + * %NL80211_CMD_JOIN_MESH from user-space. * @NL80211_ATTR_AWGN_INTERFERENCE_BITMAP: u32 attribute specifying the - * interference bitmap of operating bandwidth for %NL80211_CMD_AWGN_DETECT + * interference bitmap of operating bandwidth for %NL80211_CMD_AWGN_DETECT + * + * @NL80211_ATTR_EMA_RNR_ELEMS: Nested attribute for reduced neighbor elements. + * This attribute can be used only when NL80211_MBSSID_CONFIG_ATTR_EMA flag @@ -89,7 +85,7 @@ index f62c062d7c18..31ca813446c6 100644 * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use -@@ -3177,6 +3188,8 @@ enum nl80211_attrs { +@@ -3301,6 +3312,8 @@ enum nl80211_attrs { NL80211_ATTR_6G_REG_POWER_MODE, @@ -98,11 +94,9 @@ index f62c062d7c18..31ca813446c6 100644 /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, -diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c -index b96bf47ff206..7235f167e540 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c -@@ -809,6 +809,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { +@@ -837,6 +837,7 @@ static const struct nla_policy nl80211_p NLA_POLICY_MAX(NLA_U8, NL80211_MGMT_RTS_CTS_DISABLE), [NL80211_ATTR_AWGN_INTERFERENCE_BITMAP] = { .type = NLA_U32 }, [NL80211_ATTR_6G_REG_POWER_MODE] = NLA_POLICY_RANGE(NLA_U8, 0, 2), @@ -110,8 +104,8 @@ index b96bf47ff206..7235f167e540 100644 }; /* policy for the key attributes */ -@@ -5198,6 +5199,30 @@ nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs) - return elems; +@@ -5399,6 +5400,30 @@ static int nl80211_parse_he_bss_color(st + return 0; } +static struct cfg80211_rnr_elems * @@ -141,7 +135,7 @@ index b96bf47ff206..7235f167e540 100644 static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev, struct nlattr *attrs[], struct cfg80211_beacon_data *bcn) -@@ -5287,6 +5312,20 @@ static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev, +@@ -5498,6 +5523,20 @@ static int nl80211_parse_beacon(struct c return PTR_ERR(mbssid); bcn->mbssid_ies = mbssid; @@ -162,19 +156,19 @@ index b96bf47ff206..7235f167e540 100644 } if (attrs[NL80211_ATTR_HE_BSS_COLOR]) -@@ -5793,6 +5832,11 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) +@@ -6008,6 +6047,11 @@ static int nl80211_start_ap(struct sk_bu 0); if (err) - goto out; + goto out_unlock; + + if (!params->mbssid_config.ema && params->beacon.rnr_ies) { + err = -EINVAL; -+ goto out; ++ goto out_unlock; + } } - nl80211_calculate_ap_params(params); -@@ -5821,6 +5865,7 @@ out: + err = nl80211_calculate_ap_params(params); +@@ -6049,6 +6093,7 @@ out: params->mbssid_config.tx_wdev->netdev && params->mbssid_config.tx_wdev->netdev != dev) dev_put(params->mbssid_config.tx_wdev->netdev); @@ -182,7 +176,7 @@ index b96bf47ff206..7235f167e540 100644 kfree(params); return err; -@@ -5854,6 +5899,7 @@ static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info) +@@ -6083,6 +6128,7 @@ static int nl80211_set_beacon(struct sk_ out: kfree(params.mbssid_ies); @@ -190,7 +184,7 @@ index b96bf47ff206..7235f167e540 100644 return err; } -@@ -9704,6 +9750,8 @@ skip_beacons: +@@ -10095,6 +10141,8 @@ skip_beacons: free: kfree(params.beacon_after.mbssid_ies); kfree(params.beacon_csa.mbssid_ies); @@ -199,7 +193,7 @@ index b96bf47ff206..7235f167e540 100644 kfree(csa_attrs); return err; } -@@ -15259,6 +15307,8 @@ static int nl80211_color_change(struct sk_buff *skb, struct genl_info *info) +@@ -15883,6 +15931,8 @@ static int nl80211_color_change(struct s out: kfree(params.beacon_next.mbssid_ies); kfree(params.beacon_color_change.mbssid_ies); @@ -208,6 +202,3 @@ index b96bf47ff206..7235f167e540 100644 kfree(tb); return err; } --- -2.31.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/350-12-mac80211-add-RNR-for-EMA-AP.patch b/feeds/ipq95xx/mac80211/patches/qca/350-12-mac80211-add-RNR-for-EMA-AP.patch index 84b2bc957..6d7e10f4b 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/350-12-mac80211-add-RNR-for-EMA-AP.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/350-12-mac80211-add-RNR-for-EMA-AP.patch @@ -12,12 +12,10 @@ Signed-off-by: Aloka Dixit net/mac80211/tx.c | 48 ++++++++++++++- 3 files changed, 151 insertions(+), 16 deletions(-) -diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c -index 75f174111832..72a2a4b9fb26 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -1023,13 +1023,46 @@ static u8 *ieee80211_copy_mbssid_beacon(u8 *pos, - return pos; +@@ -1012,6 +1012,39 @@ ieee80211_copy_mbssid_beacon(u8 *pos, st + return offset; } +static int ieee80211_get_rnr_beacon_len(struct cfg80211_rnr_elems *elems) @@ -54,146 +52,138 @@ index 75f174111832..72a2a4b9fb26 100644 +} + static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, + struct ieee80211_link_data *link, struct cfg80211_beacon_data *params, - const struct ieee80211_csa_settings *csa, +@@ -1019,8 +1052,9 @@ static int ieee80211_assign_beacon(struc const struct ieee80211_color_change_settings *cca) { + struct cfg80211_mbssid_elems *mbssid = NULL; ++ struct cfg80211_rnr_elems *rnr = NULL; struct beacon_data *new, *old; -- int new_head_len, new_tail_len, new_mbssid_len = 0; -+ int new_head_len, new_tail_len, new_mbssid_len = 0, new_rnr_len = 0; - const u8 *cap, *pos; - struct ieee80211_he_operation *he_oper = NULL; +- int new_head_len, new_tail_len; ++ int new_head_len, new_tail_len, new_rnr_len = 0; int size, err; -@@ -1055,12 +1088,16 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, - else - new_tail_len = old->tail_len; - -- if (params->mbssid_ies) -+ if (params->mbssid_ies) { - new_mbssid_len = ieee80211_get_mbssid_beacon_len(params->mbssid_ies); -- else if (old && old->mbssid_ies) -+ new_rnr_len = ieee80211_get_rnr_beacon_len(params->rnr_ies); -+ } else if (old) { - new_mbssid_len = ieee80211_get_mbssid_beacon_len(old->mbssid_ies); -+ new_rnr_len = ieee80211_get_rnr_beacon_len(old->rnr_ies); -+ } - -- size = sizeof(*new) + new_head_len + new_tail_len + new_mbssid_len; -+ size = sizeof(*new) + new_head_len + new_tail_len + new_mbssid_len + -+ new_rnr_len; - - new = kzalloc(size, GFP_KERNEL); - if (!new) -@@ -1082,6 +1119,23 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, - err = -ENOMEM; - goto error; - } -+ -+ if (new_rnr_len) { -+ if (params->rnr_ies) -+ new->rnr_ies = kzalloc(struct_size(new->rnr_ies, -+ elem, -+ params->rnr_ies->cnt), -+ GFP_KERNEL); -+ else if (old && old->rnr_ies) -+ new->rnr_ies = kzalloc(struct_size(new->rnr_ies, -+ elem, -+ old->rnr_ies->cnt), -+ GFP_KERNEL); -+ if (!new->rnr_ies) { -+ err = -ENOMEM; -+ goto error; -+ } + u32 changed = BSS_CHANGED_BEACON; + struct ieee80211_bss_conf *link_conf = link->conf; +@@ -1051,16 +1085,43 @@ static int ieee80211_assign_beacon(struc + mbssid = params->mbssid_ies; + size += struct_size(new->mbssid_ies, elem, mbssid->cnt); + size += ieee80211_get_mbssid_beacon_len(mbssid, IEEE80211_BCN_EMA_DISABLED); ++ if (params->rnr_ies) { ++ rnr = params->rnr_ies; ++ new_rnr_len = ieee80211_get_rnr_beacon_len(rnr); ++ } + } else if (old && old->mbssid_ies) { + mbssid = old->mbssid_ies; + size += struct_size(new->mbssid_ies, elem, mbssid->cnt); + size += ieee80211_get_mbssid_beacon_len(mbssid, IEEE80211_BCN_EMA_DISABLED); ++ if (old->rnr_ies) { ++ rnr = old->rnr_ies; ++ new_rnr_len = ieee80211_get_rnr_beacon_len(rnr); + } } - /* start filling the new info now */ -@@ -1095,14 +1149,19 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, - new->head_len = new_head_len; - new->tail_len = new_tail_len; ++ size += new_rnr_len; ++ + new = kzalloc(size, GFP_KERNEL); + if (!new) + return -ENOMEM; -- if (params->mbssid_ies) -+ if (params->mbssid_ies) { - pos = ieee80211_copy_mbssid_beacon(new->tail + new_tail_len, - new->mbssid_ies, - params->mbssid_ies); -- else if (old) -+ pos = ieee80211_copy_rnr_beacon(pos, new->rnr_ies, -+ params->rnr_ies); -+ } else if (old) { - pos = ieee80211_copy_mbssid_beacon(new->tail + new_tail_len, - new->mbssid_ies, - old->mbssid_ies); -+ pos = ieee80211_copy_rnr_beacon(pos, new->rnr_ies, -+ old->rnr_ies); ++ if (new_rnr_len) { ++ if (params->rnr_ies) ++ new->rnr_ies = kzalloc(struct_size(new->rnr_ies, ++ elem, ++ params->rnr_ies->cnt), ++ GFP_KERNEL); ++ else if (old && old->rnr_ies) ++ new->rnr_ies = kzalloc(struct_size(new->rnr_ies, ++ elem, ++ old->rnr_ies->cnt), ++ GFP_KERNEL); ++ if (!new->rnr_ies) { ++ kfree(new); ++ return -ENOMEM; ++ } + } ++ + /* start filling the new info now */ - if (csa) { - new->cntdwn_current_counter = csa->count; -@@ -1172,6 +1231,7 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, - - if (old) { - kfree(old->mbssid_ies); -+ kfree(old->rnr_ies); - kfree_rcu(old, rcu_head); - } - -@@ -1180,6 +1240,7 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, - error: - if (new) { - kfree(new->mbssid_ies); + /* +@@ -1078,6 +1139,7 @@ static int ieee80211_assign_beacon(struc + new->mbssid_ies = (void *)pos; + pos += struct_size(new->mbssid_ies, elem, mbssid->cnt); + pos += ieee80211_copy_mbssid_beacon(pos, new->mbssid_ies, mbssid); ++ pos = ieee80211_copy_rnr_beacon(pos, new->rnr_ies, rnr); + /* update bssid_indicator */ + link_conf->bssid_indicator = + ilog2(__roundup_pow_of_two(mbssid->cnt + 1)); +@@ -1109,6 +1171,7 @@ static int ieee80211_assign_beacon(struc + err = ieee80211_set_probe_resp(sdata, params->probe_resp, + params->probe_resp_len, csa, cca, link); + if (err < 0) { + kfree(new->rnr_ies); kfree(new); + return err; } - return err; -@@ -1349,6 +1410,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, +@@ -1125,6 +1188,7 @@ static int ieee80211_assign_beacon(struc + link_conf); - if (old) { - kfree(old->mbssid_ies); -+ kfree(old->rnr_ies); - kfree_rcu(old, rcu_head); + if (err < 0) { ++ kfree(new->rnr_ies); + kfree(new); + return err; } - RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); -@@ -1432,6 +1494,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) +@@ -1135,8 +1199,10 @@ static int ieee80211_assign_beacon(struc + rcu_assign_pointer(link->u.ap.beacon, new); + sdata->u.ap.active = true; - if (sdata->u.ap.next_beacon) { - kfree(sdata->u.ap.next_beacon->mbssid_ies); -+ kfree(sdata->u.ap.next_beacon->rnr_ies); - kfree(sdata->u.ap.next_beacon); - sdata->u.ap.next_beacon = NULL; - } -@@ -1447,6 +1510,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) - RCU_INIT_POINTER(sdata->u.ap.fils_discovery, NULL); - RCU_INIT_POINTER(sdata->u.ap.unsol_bcast_probe_resp, NULL); - kfree(old_beacon->mbssid_ies); +- if (old) ++ if (old) { ++ kfree(old->rnr_ies); + kfree_rcu(old, rcu_head); ++ } + + return changed; + } +@@ -1379,6 +1445,7 @@ static void ieee80211_free_next_beacon(s + return; + + kfree(link->u.ap.next_beacon->mbssid_ies); ++ kfree(link->u.ap.next_beacon->rnr_ies); + kfree(link->u.ap.next_beacon); + link->u.ap.next_beacon = NULL; + } +@@ -1435,6 +1502,7 @@ static int ieee80211_stop_ap(struct wiph + RCU_INIT_POINTER(link->u.ap.probe_resp, NULL); + RCU_INIT_POINTER(link->u.ap.fils_discovery, NULL); + RCU_INIT_POINTER(link->u.ap.unsol_bcast_probe_resp, NULL); + kfree(old_beacon->rnr_ies); kfree_rcu(old_beacon, rcu_head); if (old_probe_resp) kfree_rcu(old_probe_resp, rcu_head); -@@ -3262,13 +3326,16 @@ cfg80211_beacon_dup(struct cfg80211_beacon_data *beacon) +@@ -3282,12 +3350,16 @@ cfg80211_beacon_dup(struct cfg80211_beac { struct cfg80211_beacon_data *new_beacon; u8 *pos; - int len; -- int mbssid_len = ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies); + int len, mbssid_len = 0, rnr_len = 0; + -+ mbssid_len = ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies); ++ mbssid_len = ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies, 0); + if (mbssid_len) + rnr_len = ieee80211_get_rnr_beacon_len(beacon->rnr_ies); len = beacon->head_len + beacon->tail_len + beacon->beacon_ies_len + beacon->proberesp_ies_len + beacon->assocresp_ies_len + beacon->probe_resp_len + beacon->lci_len + beacon->civicloc_len + -- mbssid_len; +- ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies, IEEE80211_BCN_EMA_DISABLED); + mbssid_len + rnr_len; new_beacon = kzalloc(sizeof(*new_beacon) + len, GFP_KERNEL); if (!new_beacon) -@@ -3279,9 +3346,16 @@ cfg80211_beacon_dup(struct cfg80211_beacon_data *beacon) - elem, - beacon->mbssid_ies->cnt), - GFP_KERNEL); +@@ -3298,9 +3370,16 @@ cfg80211_beacon_dup(struct cfg80211_beac + kzalloc(struct_size(new_beacon->mbssid_ies, + elem, beacon->mbssid_ies->cnt), + GFP_KERNEL); - if (!new_beacon->mbssid_ies) { - kfree(new_beacon); - return NULL; @@ -210,14 +200,15 @@ index 75f174111832..72a2a4b9fb26 100644 } } -@@ -3323,9 +3397,14 @@ cfg80211_beacon_dup(struct cfg80211_beacon_data *beacon) +@@ -3341,10 +3420,15 @@ cfg80211_beacon_dup(struct cfg80211_beac memcpy(pos, beacon->probe_resp, beacon->probe_resp_len); pos += beacon->probe_resp_len; } -- if (mbssid_len) -+ if (mbssid_len) { - pos = ieee80211_copy_mbssid_beacon(pos, new_beacon->mbssid_ies, - beacon->mbssid_ies); +- if (beacon->mbssid_ies && beacon->mbssid_ies->cnt) ++ if (beacon->mbssid_ies && beacon->mbssid_ies->cnt) { + pos += ieee80211_copy_mbssid_beacon(pos, + new_beacon->mbssid_ies, + beacon->mbssid_ies); + if (rnr_len) + pos = ieee80211_copy_rnr_beacon(pos, + new_beacon->rnr_ies, @@ -226,7 +217,7 @@ index 75f174111832..72a2a4b9fb26 100644 /* might copy -1, meaning no changes requested */ new_beacon->ftm_responder = beacon->ftm_responder; -@@ -3343,6 +3422,14 @@ cfg80211_beacon_dup(struct cfg80211_beacon_data *beacon) +@@ -3362,6 +3446,14 @@ cfg80211_beacon_dup(struct cfg80211_beac } return new_beacon; @@ -241,51 +232,9 @@ index 75f174111832..72a2a4b9fb26 100644 } void ieee80211_csa_finish(struct ieee80211_vif *vif) -@@ -3377,6 +3464,7 @@ static int ieee80211_set_after_csa_beacon(struct ieee80211_sub_if_data *sdata, - NULL, NULL); - if (sdata->u.ap.next_beacon) { - kfree(sdata->u.ap.next_beacon->mbssid_ies); -+ kfree(sdata->u.ap.next_beacon->rnr_ies); - kfree(sdata->u.ap.next_beacon); - sdata->u.ap.next_beacon = NULL; - } -@@ -3634,6 +3722,7 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata, - error: - if (sdata->vif.type == NL80211_IFTYPE_AP && sdata->u.ap.next_beacon) { - kfree(sdata->u.ap.next_beacon->mbssid_ies); -+ kfree(sdata->u.ap.next_beacon->rnr_ies); - kfree(sdata->u.ap.next_beacon); - sdata->u.ap.next_beacon = NULL; - } -@@ -3645,6 +3734,7 @@ static void ieee80211_color_change_abort(struct ieee80211_sub_if_data *sdata) - sdata->vif.color_change_active = false; - if (sdata->u.ap.next_beacon) { - kfree(sdata->u.ap.next_beacon->mbssid_ies); -+ kfree(sdata->u.ap.next_beacon->rnr_ies); - kfree(sdata->u.ap.next_beacon); - sdata->u.ap.next_beacon = NULL; - } -@@ -4388,6 +4478,7 @@ ieee80211_set_after_color_change_beacon(struct ieee80211_sub_if_data *sdata, - NULL, NULL); - if (sdata->u.ap.next_beacon) { - kfree(sdata->u.ap.next_beacon->mbssid_ies); -+ kfree(sdata->u.ap.next_beacon->rnr_ies); - kfree(sdata->u.ap.next_beacon); - sdata->u.ap.next_beacon = NULL; - } -@@ -4435,6 +4526,7 @@ ieee80211_set_color_change_beacon(struct ieee80211_sub_if_data *sdata, - if (err < 0) { - if (sdata->u.ap.next_beacon) { - kfree(sdata->u.ap.next_beacon->mbssid_ies); -+ kfree(sdata->u.ap.next_beacon->rnr_ies); - kfree(sdata->u.ap.next_beacon); - sdata->u.ap.next_beacon = NULL; - } -diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h -index 4d5728353b22..67c147363cb7 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h -@@ -266,6 +266,7 @@ struct beacon_data { +@@ -276,6 +276,7 @@ struct beacon_data { u16 cntdwn_counter_offsets[IEEE80211_MAX_CNTDWN_COUNTERS_NUM]; u8 cntdwn_current_counter; struct cfg80211_mbssid_elems *mbssid_ies; @@ -293,12 +242,10 @@ index 4d5728353b22..67c147363cb7 100644 struct rcu_head rcu_head; }; -diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c -index 13d7fc842ab2..6f51297f7fc6 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c -@@ -5378,6 +5378,41 @@ static void ieee80211_beacon_add_mbssid(struct beacon_data *beacon, int index, - beacon->mbssid_ies->elem[index].len); +@@ -5381,6 +5381,41 @@ ieee80211_beacon_add_mbssid(struct sk_bu + beacon->mbssid_ies->elem[i].len); } +static int ieee80211_beacon_rnr_len(struct beacon_data *beacon, int index) @@ -339,47 +286,39 @@ index 13d7fc842ab2..6f51297f7fc6 100644 static struct sk_buff * ieee80211_beacon_get_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, -@@ -5392,7 +5427,7 @@ ieee80211_beacon_get_ap(struct ieee80211_hw *hw, +@@ -5396,7 +5431,7 @@ ieee80211_beacon_get_ap(struct ieee80211 struct ieee80211_if_ap *ap = &sdata->u.ap; struct sk_buff *skb = NULL; u16 csa_off_base = 0; -- int mbssid_len = 0; -+ int mbssid_len = 0, rnr_len = 0; +- int mbssid_len; ++ int mbssid_len, rnr_len = 0; if (beacon->cntdwn_counter_offsets[0]) { if (!is_template) -@@ -5404,13 +5439,16 @@ ieee80211_beacon_get_ap(struct ieee80211_hw *hw, - mbssid_len = ieee80211_beacon_mbssid_len(beacon, ema_index); - if (mbssid_len == -1) - return NULL; -+ else if (mbssid_len > 0) -+ rnr_len = ieee80211_beacon_rnr_len(beacon, ema_index); - - /* headroom, head length, +@@ -5409,9 +5444,13 @@ ieee80211_beacon_get_ap(struct ieee80211 * tail length, maximum TIM length and multiple BSSID length */ + mbssid_len = ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies, ema_index); ++ if (mbssid_len > 0) ++ rnr_len = ieee80211_beacon_rnr_len(beacon, ema_index); ++ skb = dev_alloc_skb(local->tx_headroom + beacon->head_len + beacon->tail_len + 256 + - local->hw.extra_beacon_tailroom + mbssid_len); + local->hw.extra_beacon_tailroom + mbssid_len + -+ rnr_len); ++ rnr_len); if (!skb) return NULL; -@@ -5430,8 +5468,12 @@ ieee80211_beacon_get_ap(struct ieee80211_hw *hw, +@@ -5427,7 +5466,10 @@ ieee80211_beacon_get_ap(struct ieee80211 - if (mbssid_len) { - ieee80211_beacon_add_mbssid(beacon, ema_index, skb); -+ -+ if (rnr_len) -+ ieee80211_beacon_add_rnr(beacon, ema_index, skb); -+ - if (offs) { + if (mbssid_len) { + ieee80211_beacon_add_mbssid(skb, ema_index, beacon); - offs->mbssid_off = skb->len - mbssid_len; ++ if (rnr_len) ++ ieee80211_beacon_add_rnr(beacon, ema_index, skb); ++ + offs->mbssid_off = skb->len - (mbssid_len + rnr_len); - csa_off_base = skb->len; } - } --- -2.31.1 - + + /* for AP the csa offsets are from tail */ diff --git a/feeds/ipq95xx/mac80211/patches/qca/350-15-nl80211-FILS-discovery-template-definition.patch b/feeds/ipq95xx/mac80211/patches/qca/350-15-nl80211-FILS-discovery-template-definition.patch index e27e25fc7..8b0059f3f 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/350-15-nl80211-FILS-discovery-template-definition.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/350-15-nl80211-FILS-discovery-template-definition.patch @@ -23,45 +23,62 @@ Signed-off-by: Aloka Dixit --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h -@@ -4170,7 +4170,7 @@ struct cfg80211_ops { +@@ -4373,7 +4373,7 @@ struct cfg80211_ops { int (*start_ap)(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ap_settings *settings); int (*change_beacon)(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_beacon_data *info); + struct cfg80211_ap_settings *info); - int (*stop_ap)(struct wiphy *wiphy, struct net_device *dev); - + int (*stop_ap)(struct wiphy *wiphy, struct net_device *dev, + unsigned int link_id); --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -1435,11 +1435,12 @@ error: +@@ -1391,17 +1391,18 @@ error: } static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_beacon_data *params) + struct cfg80211_ap_settings *params) { - struct ieee80211_sub_if_data *sdata; + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_link_data *link; struct beacon_data *old; int err; + struct ieee80211_bss_conf *link_conf; + u32 changed; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); sdata_assert_lock(sdata); -@@ -1454,10 +1455,28 @@ static int ieee80211_change_beacon(struc + +- link = sdata_dereference(sdata->link[params->link_id], sdata); ++ link = sdata_dereference(sdata->link[params->beacon.link_id], sdata); + if (!link) + return -ENOLINK; + +@@ -1417,17 +1418,36 @@ static int ieee80211_change_beacon(struc if (!old) return -ENOENT; -- err = ieee80211_assign_beacon(sdata, params, NULL, NULL); -+ err = ieee80211_assign_beacon(sdata, ¶ms->beacon, NULL, NULL); +- err = ieee80211_assign_beacon(sdata, link, params, NULL, NULL); ++ err = ieee80211_assign_beacon(sdata, link, ¶ms->beacon, NULL, NULL); if (err < 0) return err; -- ieee80211_bss_info_change_notify(sdata, err); -+ + +- if (params->he_bss_color_valid && +- params->he_bss_color.enabled != link_conf->he_bss_color.enabled) { +- link_conf->he_bss_color.enabled = params->he_bss_color.enabled; ++ if (params->beacon.he_bss_color_valid && ++ params->beacon.he_bss_color.enabled != link_conf->he_bss_color.enabled) { ++ link_conf->he_bss_color.enabled = params->beacon.he_bss_color.enabled; + err |= BSS_CHANGED_HE_BSS_COLOR; + } + +- ieee80211_link_info_change_notify(sdata, link, err); + changed = err; + if (params->fils_discovery.max_interval) { + err = ieee80211_set_fils_discovery(sdata, -+ ¶ms->fils_discovery); ++ ¶ms->fils_discovery, ++ link, link_conf); + if (err < 0) + return err; + changed |= BSS_CHANGED_FILS_DISCOVERY; @@ -69,30 +86,21 @@ Signed-off-by: Aloka Dixit + + if (params->unsol_bcast_probe_resp.interval) { + err = ieee80211_set_unsol_bcast_probe_resp(sdata, -+ ¶ms->unsol_bcast_probe_resp); ++ ¶ms->unsol_bcast_probe_resp, ++ link, link_conf); + if (err < 0) + return err; + changed |= BSS_CHANGED_UNSOL_BCAST_PROBE_RESP; + } + -+ ieee80211_bss_info_change_notify(sdata, changed); ++ ieee80211_link_info_change_notify(sdata, link, changed); return 0; } --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c -@@ -425,6 +425,9 @@ nl80211_fils_discovery_policy[NL80211_FI - NLA_POLICY_RANGE(NLA_BINARY, - NL80211_FILS_DISCOVERY_TMPL_MIN_LEN, - IEEE80211_MAX_DATA_LEN), -+#else -+ [NL80211_FILS_DISCOVERY_ATTR_TMPL] = { .type = NLA_BINARY, -+ .len = IEEE80211_MAX_DATA_LEN }, - #endif - }; - -@@ -5880,7 +5883,7 @@ static int nl80211_set_beacon(struct sk_ - struct cfg80211_registered_device *rdev = info->user_ptr[0]; +@@ -6098,7 +6098,7 @@ static int nl80211_set_beacon(struct sk_ + unsigned int link_id = nl80211_link_id(info->attrs); struct net_device *dev = info->user_ptr[1]; struct wireless_dev *wdev = dev->ieee80211_ptr; - struct cfg80211_beacon_data params; @@ -100,8 +108,8 @@ Signed-off-by: Aloka Dixit int err; if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && -@@ -5893,17 +5896,39 @@ static int nl80211_set_beacon(struct sk_ - if (!wdev->beacon_interval) +@@ -6111,17 +6111,38 @@ static int nl80211_set_beacon(struct sk_ + if (!wdev->links[link_id].ap.beacon_interval) return -EINVAL; - err = nl80211_parse_beacon(rdev, info->attrs, ¶ms); @@ -122,10 +130,9 @@ Signed-off-by: Aloka Dixit + } + + if (info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP]) { -+ err = nl80211_parse_unsol_bcast_probe_resp( -+ rdev, -+ info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP], -+ params); ++ err = nl80211_parse_unsol_bcast_probe_resp(rdev, ++ info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP], ++ params); + if (err) + goto out; + } @@ -146,7 +153,7 @@ Signed-off-by: Aloka Dixit --- a/net/wireless/rdev-ops.h +++ b/net/wireless/rdev-ops.h -@@ -162,7 +162,7 @@ static inline int rdev_start_ap(struct c +@@ -167,7 +167,7 @@ static inline int rdev_start_ap(struct c static inline int rdev_change_beacon(struct cfg80211_registered_device *rdev, struct net_device *dev, @@ -157,7 +164,7 @@ Signed-off-by: Aloka Dixit trace_rdev_change_beacon(&rdev->wiphy, dev, info); --- a/net/wireless/trace.h +++ b/net/wireless/trace.h -@@ -597,44 +597,50 @@ TRACE_EVENT(rdev_start_ap, +@@ -599,46 +599,50 @@ TRACE_EVENT(rdev_start_ap, TRACE_EVENT(rdev_change_beacon, TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, @@ -167,13 +174,13 @@ Signed-off-by: Aloka Dixit TP_STRUCT__entry( WIPHY_ENTRY NETDEV_ENTRY + __field(int, link_id) - __dynamic_array(u8, head, info ? info->head_len : 0) - __dynamic_array(u8, tail, info ? info->tail_len : 0) - __dynamic_array(u8, beacon_ies, info ? info->beacon_ies_len : 0) + __dynamic_array(u8, head, info ? info->beacon.head_len : 0) + __dynamic_array(u8, tail, info ? info->beacon.tail_len : 0) -+ __dynamic_array(u8, beacon_ies, -+ info ? info->beacon.beacon_ies_len : 0) ++ __dynamic_array(u8, beacon_ies, info ? info->beacon.beacon_ies_len : 0) __dynamic_array(u8, proberesp_ies, - info ? info->proberesp_ies_len : 0) + info ? info->beacon.proberesp_ies_len : 0) @@ -181,13 +188,13 @@ Signed-off-by: Aloka Dixit - info ? info->assocresp_ies_len : 0) - __dynamic_array(u8, probe_resp, info ? info->probe_resp_len : 0) + info ? info->beacon.assocresp_ies_len : 0) -+ __dynamic_array(u8, probe_resp, -+ info ? info->beacon.probe_resp_len : 0) ++ __dynamic_array(u8, probe_resp, info ? info->beacon.probe_resp_len : 0) ), TP_fast_assign( WIPHY_ASSIGN; NETDEV_ASSIGN; if (info) { +- __entry->link_id = info->link_id; - if (info->head) - memcpy(__get_dynamic_array(head), info->head, - info->head_len); @@ -195,6 +202,7 @@ Signed-off-by: Aloka Dixit - memcpy(__get_dynamic_array(tail), info->tail, - info->tail_len); - if (info->beacon_ies) ++ __entry->link_id = info->beacon.link_id; + if (info->beacon.head) + memcpy(__get_dynamic_array(head), + info->beacon.head, @@ -228,6 +236,6 @@ Signed-off-by: Aloka Dixit - info->probe_resp, info->probe_resp_len); + info->beacon.probe_resp, + info->beacon.probe_resp_len); + } else { + __entry->link_id = -1; } - ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG) diff --git a/feeds/ipq95xx/mac80211/patches/qca/351-ath11k-add-qmi-changes-to-fetch-memory-region.patch b/feeds/ipq95xx/mac80211/patches/qca/351-ath11k-add-qmi-changes-to-fetch-memory-region.patch index 8fa8ad778..738be4310 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/351-ath11k-add-qmi-changes-to-fetch-memory-region.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/351-ath11k-add-qmi-changes-to-fetch-memory-region.patch @@ -16,7 +16,7 @@ Signed-off-by: P Praneesh --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -166,6 +166,9 @@ static const struct ath11k_hw_params ath +@@ -168,6 +168,9 @@ static const struct ath11k_hw_params ath .max_tx_ring = DP_TCL_NUM_RING_MAX + 1, .reo_status_poll = false, .num_vdevs_peers = ath11k_vdevs_peers, @@ -26,7 +26,7 @@ Signed-off-by: P Praneesh }, { .hw_rev = ATH11K_HW_IPQ6018_HW10, -@@ -243,6 +246,9 @@ static const struct ath11k_hw_params ath +@@ -251,6 +254,9 @@ static const struct ath11k_hw_params ath .max_tx_ring = DP_TCL_NUM_RING_MAX + 1, .reo_status_poll = false, .num_vdevs_peers = ath11k_vdevs_peers, @@ -36,7 +36,7 @@ Signed-off-by: P Praneesh }, { .name = "qca6390 hw2.0", -@@ -398,6 +404,10 @@ static const struct ath11k_hw_params ath +@@ -418,6 +424,10 @@ static const struct ath11k_hw_params ath .max_tx_ring = DP_TCL_NUM_RING_MAX + 1, .reo_status_poll = false, .num_vdevs_peers = ath11k_vdevs_peers, @@ -47,7 +47,7 @@ Signed-off-by: P Praneesh }, { .name = "wcn6855 hw2.0", -@@ -617,6 +627,9 @@ static const struct ath11k_hw_params ath +@@ -721,6 +731,9 @@ static const struct ath11k_hw_params ath * max cfr payload(4096 bytes) */ .cfr_stream_buf_size = 4292, @@ -57,22 +57,22 @@ Signed-off-by: P Praneesh }, { .hw_rev = ATH11K_HW_QCN6122, -@@ -684,6 +697,9 @@ static const struct ath11k_hw_params ath - * cfr payload(16384 bytes) - */ - .cfr_stream_buf_size = 16580, -+ .m3_offset = ATH11K_QMI_QCN6122_M3_OFFSET, -+ .qdss_offset = ATH11K_QMI_QCN6122_QDSS_OFFSET, -+ .caldb_offset = ATH11K_QMI_QCN6122_CALDB_OFFSET, - }, - { - .hw_rev = ATH11K_HW_IPQ9574, +@@ -860,6 +873,9 @@ static const struct ath11k_hw_params ath + .hybrid_bus_type = false, + .fixed_fw_mem = false, + .support_off_channel_tx = false, ++ .m3_offset = ATH11K_QMI_IPQ9574_M3_OFFSET, ++ .caldb_offset = ATH11K_QMI_IPQ9574_CALDB_OFFSET, ++ .bdf_offset = ATH11K_QMI_IPQ9574_BDF_OFFSET, + }, + }; + --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h -@@ -240,6 +240,11 @@ struct ath11k_hw_params { - bool supports_rssi_stats; - bool fw_wmi_diag_event; - bool current_cc_support; +@@ -250,6 +250,11 @@ struct ath11k_hw_params { + bool internal_pci; + u8 ce_window; + u8 dp_window; + u32 bdf_offset; + u32 m3_offset; + u32 caldb_offset; @@ -83,9 +83,9 @@ Signed-off-by: P Praneesh struct ath11k_hw_ops { --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c -@@ -2850,24 +2850,27 @@ static int ath11k_qmi_assign_target_mem_ - u32 host_ddr_sz, addr; +@@ -2865,24 +2865,27 @@ static int ath11k_qmi_assign_target_mem_ int i, idx, ret; + u32 addr = 0; + hremote_node = of_parse_phandle(dev->of_node, "memory-region", 0); + if (hremote_node) { @@ -120,30 +120,31 @@ Signed-off-by: P Praneesh if (res.end - res.start + 1 < ab->qmi.target_mem[i].size) { ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi fail to assign memory of sz\n"); -@@ -2894,6 +2897,10 @@ static int ath11k_qmi_assign_target_mem_ +@@ -2909,6 +2912,9 @@ static int ath11k_qmi_assign_target_mem_ idx++; break; case BDF_MEM_REGION_TYPE: + if (hremote_node) + ab->hw_params.bdf_addr = + res.start + ab->hw_params.bdf_offset; -+ - ab->qmi.target_mem[idx].paddr = ab->hw_params.bdf_addr; - ab->qmi.target_mem[idx].vaddr = NULL; - ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size; -@@ -2905,16 +2912,16 @@ static int ath11k_qmi_assign_target_mem_ + if (!of_property_read_u32(ab->dev->of_node, "qcom,bdf-addr", + &addr)) + ab->hw_params.bdf_addr = (u32)addr; +@@ -2924,10 +2930,10 @@ static int ath11k_qmi_assign_target_mem_ ab->enable_cold_boot_cal) { if (hremote_node) { ab->qmi.target_mem[idx].paddr = - res.start + host_ddr_sz; -+ res.start + ab->hw_params.caldb_offset; ++ res.start + ab->hw_params.caldb_offset; } else if (ath11k_host_ddr_addr) { - ab->qmi.target_mem[idx].paddr = ath11k_host_ddr_addr + - ATH11K_HOST_DDR_CALDB_OFFSET; + ab->qmi.target_mem[idx].paddr = -+ ath11k_host_ddr_addr + ab->hw_params.caldb_offset; - } else { - ab->qmi.target_mem[idx].paddr = ++ ath11k_host_ddr_addr + ab->hw_params.caldb_offset; + } else if (of_property_read_u32(ab->dev->of_node, + "qcom,caldb-addr", + &addr)) { +@@ -2937,7 +2943,7 @@ static int ath11k_qmi_assign_target_mem_ ATH11K_QMI_CALDB_ADDRESS; } @@ -152,7 +153,7 @@ Signed-off-by: P Praneesh ioremap(ab->qmi.target_mem[idx].paddr, ab->qmi.target_mem[i].size); } else { -@@ -2939,10 +2946,10 @@ static int ath11k_qmi_assign_target_mem_ +@@ -2962,10 +2968,10 @@ static int ath11k_qmi_assign_target_mem_ ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type; if (hremote_node) { ab->qmi.target_mem[idx].paddr = @@ -165,7 +166,7 @@ Signed-off-by: P Praneesh } else { ab->qmi.target_mem[idx].paddr = ab->hw_params.m3_addr; } -@@ -2954,10 +2961,10 @@ static int ath11k_qmi_assign_target_mem_ +@@ -2977,10 +2983,10 @@ static int ath11k_qmi_assign_target_mem_ break; case PAGEABLE_MEM_TYPE: if (hremote_node) { @@ -178,7 +179,7 @@ Signed-off-by: P Praneesh } else { ath11k_dbg(ab, ATH11K_DBG_QMI, "pageable-addr is not in dt\n"); -@@ -4056,10 +4063,9 @@ int ath11k_qmi_pci_alloc_qdss_mem(struct +@@ -4051,10 +4057,9 @@ int ath11k_qmi_pci_alloc_qdss_mem(struct } if (ath11k_host_ddr_addr) @@ -193,39 +194,39 @@ Signed-off-by: P Praneesh ab->qmi.qdss_mem[i].vaddr = --- a/drivers/net/wireless/ath/ath11k/qmi.h +++ b/drivers/net/wireless/ath/ath11k/qmi.h -@@ -33,24 +33,39 @@ +@@ -35,24 +35,42 @@ #define ATH11K_QMI_DEFAULT_QDSS_CONFIG_FILE_NAME "qdss_trace_config.bin" #ifdef CPTCFG_ATH11K_MEM_PROFILE_512M --#define ATH11K_HOST_DDR_M3_OFFSET 0xC00000 --#define ATH11K_HOST_DDR_QDSS_OFFSET 0xD00000 --#define ATH11K_HOST_DDR_CALDB_OFFSET 0xE00000 --#define ATH11K_HOST_DDR_PAGEABLE_OFFSET 0x1600000 -+#define ATH11K_QMI_QCN9074_M3_OFFSET 0xC00000 -+#define ATH11K_QMI_QCN9074_QDSS_OFFSET 0xD00000 -+#define ATH11K_QMI_QCN9074_CALDB_OFFSET 0xE00000 -+#define ATH11K_QMI_QCN9074_PAGEABLE_OFFSET 0x1600000 - #define ATH11K_QMI_IPQ8074_M3_DUMP_ADDRESS 0x4E800000 - #define ATH11K_QMI_IPQ6018_M3_DUMP_ADDRESS 0x4E300000 -+#define ATH11K_QMI_IPQ8074_M3_DUMP_OFFSET 0x3800000 -+#define ATH11K_QMI_IPQ6018_M3_DUMP_OFFSET 0x3800000 +-#define ATH11K_HOST_DDR_M3_OFFSET 0xC00000 +-#define ATH11K_HOST_DDR_QDSS_OFFSET 0xD00000 +-#define ATH11K_HOST_DDR_CALDB_OFFSET 0xE00000 +-#define ATH11K_HOST_DDR_PAGEABLE_OFFSET 0x1600000 ++#define ATH11K_QMI_QCN9074_M3_OFFSET 0xC00000 ++#define ATH11K_QMI_QCN9074_QDSS_OFFSET 0xD00000 ++#define ATH11K_QMI_QCN9074_CALDB_OFFSET 0xE00000 ++#define ATH11K_QMI_QCN9074_PAGEABLE_OFFSET 0x1600000 + #define ATH11K_QMI_IPQ8074_M3_DUMP_ADDRESS 0x4E800000 + #define ATH11K_QMI_IPQ6018_M3_DUMP_ADDRESS 0x4E300000 ++#define ATH11K_QMI_IPQ8074_M3_DUMP_OFFSET 0x3800000 ++#define ATH11K_QMI_IPQ6018_M3_DUMP_OFFSET 0x3800000 #else --#define ATH11K_HOST_DDR_M3_OFFSET 0x2300000 --#define ATH11K_HOST_DDR_QDSS_OFFSET 0x2400000 --#define ATH11K_HOST_DDR_CALDB_OFFSET 0x2500000 --#define ATH11K_HOST_DDR_PAGEABLE_OFFSET 0x2D00000 -+#define ATH11K_QMI_QCN9074_M3_OFFSET 0x2300000 -+#define ATH11K_QMI_QCN9074_QDSS_OFFSET 0x2400000 -+#define ATH11K_QMI_QCN9074_CALDB_OFFSET 0x2500000 -+#define ATH11K_QMI_QCN9074_PAGEABLE_OFFSET 0x2D00000 - #define ATH11K_QMI_IPQ8074_M3_DUMP_ADDRESS 0x51000000 - #define ATH11K_QMI_IPQ6018_M3_DUMP_ADDRESS 0x50100000 -+#define ATH11K_QMI_IPQ8074_M3_DUMP_OFFSET 0x6000000 -+#define ATH11K_QMI_IPQ6018_M3_DUMP_OFFSET 0x5600000 +-#define ATH11K_HOST_DDR_M3_OFFSET 0x2300000 +-#define ATH11K_HOST_DDR_QDSS_OFFSET 0x2400000 +-#define ATH11K_HOST_DDR_CALDB_OFFSET 0x2500000 +-#define ATH11K_HOST_DDR_PAGEABLE_OFFSET 0x2D00000 ++#define ATH11K_QMI_QCN9074_M3_OFFSET 0x2300000 ++#define ATH11K_QMI_QCN9074_QDSS_OFFSET 0x2400000 ++#define ATH11K_QMI_QCN9074_CALDB_OFFSET 0x2500000 ++#define ATH11K_QMI_QCN9074_PAGEABLE_OFFSET 0x2D00000 + #define ATH11K_QMI_IPQ8074_M3_DUMP_ADDRESS 0x51000000 + #define ATH11K_QMI_IPQ6018_M3_DUMP_ADDRESS 0x50100000 ++#define ATH11K_QMI_IPQ8074_M3_DUMP_OFFSET 0x6000000 ++#define ATH11K_QMI_IPQ6018_M3_DUMP_OFFSET 0x5600000 #endif - #define ATH11K_QMI_IPQ5018_M3_DUMP_ADDRESS 0x4C800000 - #define ATH11K_QMI_M3_DUMP_SIZE 0x100000 + #define ATH11K_QMI_IPQ5018_M3_DUMP_ADDRESS 0x4C800000 + #define ATH11K_QMI_M3_DUMP_SIZE 0x100000 +#define ATH11K_QMI_IPQ8074_CALDB_OFFSET 0xA00000 +#define ATH11K_QMI_IPQ8074_BDF_OFFSET 0xC0000 @@ -237,6 +238,9 @@ Signed-off-by: P Praneesh +#define ATH11K_QMI_QCN6122_M3_OFFSET 0xD00000 +#define ATH11K_QMI_QCN6122_QDSS_OFFSET 0xE00000 +#define ATH11K_QMI_QCN6122_CALDB_OFFSET 0xF00000 ++#define ATH11K_QMI_IPQ9574_CALDB_OFFSET 0xA00000 ++#define ATH11K_QMI_IPQ9574_BDF_OFFSET 0xC0000 ++#define ATH11K_QMI_IPQ9574_M3_OFFSET 0xD00000 + #define QMI_WLFW_REQUEST_MEM_IND_V01 0x0035 #define QMI_WLFW_FW_MEM_READY_IND_V01 0x0037 diff --git a/feeds/ipq95xx/mac80211/patches/qca/351-mac80211-fix-mesh-airtime-link-metric-estimating.patch b/feeds/ipq95xx/mac80211/patches/qca/351-mac80211-fix-mesh-airtime-link-metric-estimating.patch deleted file mode 100644 index 20fc01811..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/351-mac80211-fix-mesh-airtime-link-metric-estimating.patch +++ /dev/null @@ -1,40 +0,0 @@ -From fc9d9b3f367638505837a5815b1842bba2425993 Mon Sep 17 00:00:00 2001 -From: Aditya Kumar Singh -Date: Fri, 25 Mar 2022 11:04:37 +0530 -Subject: [PATCH] mac80211: fix mesh airtime link metric estimating - -ieee80211s_update_metric api uses sta_set_rate_info_tx api to -get struct rate_info data from struct ieee80211_tx_rate present -in ieee80211_sta->tx_stats. However, drivers can skip tx rate -calculation by setting rate idx as -1. Such drivers can provide -rate_info directly. - -Add fix to use rate_info directly if present instead of -sta_set_rate_info_tx. - -Signed-off-by: Aditya Kumar Singh ---- - net/mac80211/mesh_hwmp.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c -index 026798a..6d12053 100644 ---- a/net/mac80211/mesh_hwmp.c -+++ b/net/mac80211/mesh_hwmp.c -@@ -324,7 +324,12 @@ void ieee80211s_update_metric(struct ieee80211_local *local, - LINK_FAIL_THRESH) - mesh_plink_broken(sta); - -- sta_set_rate_info_tx(sta, &sta->tx_stats.last_rate, &rinfo); -+ /* use rate info set by the driver directly if present */ -+ if (st->rate) -+ rinfo = sta->tx_stats.last_rate_info; -+ else -+ sta_set_rate_info_tx(sta, &sta->tx_stats.last_rate, &rinfo); -+ - ewma_mesh_tx_rate_avg_add(&sta->mesh->tx_rate_avg, - cfg80211_calculate_bitrate(&rinfo)); - } --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/352-ath11k-Fix-non-removal-of-debugfs-post-firmware-reco.patch b/feeds/ipq95xx/mac80211/patches/qca/352-ath11k-Fix-non-removal-of-debugfs-post-firmware-reco.patch index 86d0b52e5..9f7609f9b 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/352-ath11k-Fix-non-removal-of-debugfs-post-firmware-reco.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/352-ath11k-Fix-non-removal-of-debugfs-post-firmware-reco.patch @@ -28,7 +28,7 @@ Signed-off-by: Nidhi Jain --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -7681,6 +7681,14 @@ static int ath11k_mac_vdev_delete(struct +@@ -8015,6 +8015,14 @@ static int ath11k_mac_vdev_delete(struct return ret; } @@ -43,7 +43,7 @@ Signed-off-by: Nidhi Jain static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { -@@ -7777,13 +7785,6 @@ static int ath11k_mac_op_add_interface(s +@@ -8111,13 +8119,6 @@ static int ath11k_mac_op_add_interface(s goto err; } @@ -57,7 +57,7 @@ Signed-off-by: Nidhi Jain switch (vif->type) { case NL80211_IFTYPE_UNSPECIFIED: case NL80211_IFTYPE_STATION: -@@ -7965,13 +7966,7 @@ static int ath11k_mac_op_add_interface(s +@@ -8310,13 +8311,8 @@ static int ath11k_mac_op_add_interface(s if (ret) ath11k_warn(ar->ab, "failed to set ap ps ret %d\n", ret); @@ -68,11 +68,12 @@ Signed-off-by: Nidhi Jain - INIT_LIST_HEAD(&arvif->ar->debug.wmi_list); - init_completion(&arvif->ar->debug.wmi_ctrl_path_stats_rcvd); - } -+ ath11k_debugfs_per_arvif(arvif); ++ if (arvif->vif->debugfs_dir) ++ ath11k_debugfs_per_arvif(arvif); mutex_unlock(&ar->conf_mutex); -@@ -8022,6 +8017,32 @@ static int ath11k_mac_vif_unref(int buf_ +@@ -8358,6 +8354,32 @@ static int ath11k_mac_vif_unref(int buf_ return 0; } @@ -105,14 +106,10 @@ Signed-off-by: Nidhi Jain static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { -@@ -8122,29 +8143,7 @@ err_vdev_del: +@@ -8463,24 +8485,8 @@ err_vdev_del: /* TODO: recal traffic pause state based on the available vdevs */ -- /* Remove TWT related files and directory */ -- debugfs_remove_recursive(arvif->debugfs_twt); -- arvif->debugfs_twt = NULL; -- - /* Remove A-MPDU, A-MSDU aggr size files */ - debugfs_remove(arvif->ampdu_aggr_size); - arvif->ampdu_aggr_size = NULL; @@ -131,36 +128,34 @@ Signed-off-by: Nidhi Jain - /* Remove the wbm tx compl stats file */ - debugfs_remove(arvif->wbm_tx_completion_stats); - arvif->wbm_tx_completion_stats = NULL; -- -+ ath11k_mac_debugfs_remove_stats_file(arvif); ++ if (arvif->vif->debugfs_dir) ++ ath11k_mac_debugfs_remove_stats_file(arvif); + unlock: mutex_unlock(&ar->conf_mutex); - } --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -1685,6 +1685,7 @@ static void ath11k_core_restart(struct w - struct ath11k_base *ab = container_of(work, struct ath11k_base, restart_work); +@@ -2156,6 +2156,7 @@ static void ath11k_core_pre_reconfigure_ + { struct ath11k *ar; struct ath11k_pdev *pdev; + struct ath11k_vif *arvif; - int i, ret = 0; + int i; spin_lock_bh(&ab->base_lock); -@@ -1698,6 +1699,11 @@ static void ath11k_core_restart(struct w +@@ -2169,6 +2170,9 @@ static void ath11k_core_pre_reconfigure_ ar->state == ATH11K_STATE_TM) continue; -+ list_for_each_entry(arvif, &ar->arvifs, list) { -+ if (arvif->is_started) -+ ath11k_mac_debugfs_remove_stats_file(arvif); -+ } ++ list_for_each_entry(arvif, &ar->arvifs, list) ++ ath11k_mac_debugfs_remove_stats_file(arvif); + ieee80211_stop_queues(ar->hw); ath11k_mac_drain_tx(ar); - complete(&ar->scan.started); + ar->state_11d = ATH11K_11D_IDLE; --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c -@@ -261,18 +261,9 @@ static ssize_t ath11k_write_wmi_ctrl_pat +@@ -103,18 +103,9 @@ static ssize_t ath11k_write_wmi_ctrl_pat { struct ath11k_vif *arvif = file->private_data; struct wmi_ctrl_path_stats_cmd_param param = {0}; @@ -179,7 +174,7 @@ Signed-off-by: Nidhi Jain ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count); if (ret < 0) { return ret; -@@ -733,19 +724,10 @@ static ssize_t ath11k_write_ampdu_aggr_s +@@ -575,19 +566,10 @@ static ssize_t ath11k_write_ampdu_aggr_s { struct ath11k_vif *arvif = file->private_data; struct ath11k_base *ab = arvif->ar->ab; @@ -201,7 +196,7 @@ Signed-off-by: Nidhi Jain --- a/drivers/net/wireless/ath/ath11k/mac.h +++ b/drivers/net/wireless/ath/ath11k/mac.h -@@ -170,4 +170,5 @@ bool ath11k_mac_sta_level_info(struct at +@@ -185,4 +185,5 @@ bool ath11k_mac_sta_level_info(struct at void ath11k_mac_get_any_chandef_iter(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *conf, void *data); diff --git a/feeds/ipq95xx/mac80211/patches/qca/352-mac80211-allow-nss-change-only-upto-max_nss.patch b/feeds/ipq95xx/mac80211/patches/qca/352-mac80211-allow-nss-change-only-upto-max_nss.patch index 67958421f..d4c3f240c 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/352-mac80211-allow-nss-change-only-upto-max_nss.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/352-mac80211-allow-nss-change-only-upto-max_nss.patch @@ -42,11 +42,9 @@ Signed-off-by: Rameshkumar Sundaram net/mac80211/vht.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) -diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c -index 52b9db6..ee60b37 100644 --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c -@@ -556,7 +556,7 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, +@@ -614,7 +614,7 @@ u32 __ieee80211_vht_handle_opmode(struct enum ieee80211_sta_rx_bandwidth new_bw; struct sta_opmode_info sta_opmode = {}; u32 changed = 0; @@ -55,34 +53,32 @@ index 52b9db6..ee60b37 100644 /* ignore - no support for BF yet */ if (opmode & IEEE80211_OPMODE_NOTIF_RX_NSS_TYPE_BF) -@@ -567,10 +567,23 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, +@@ -625,10 +625,24 @@ u32 __ieee80211_vht_handle_opmode(struct nss += 1; - if (sta->sta.rx_nss != nss) { -- sta->sta.rx_nss = nss; + if (link_sta->pub->rx_nss != nss) { +- link_sta->pub->rx_nss = nss; - sta_opmode.rx_nss = nss; - changed |= IEEE80211_RC_NSS_CHANGED; - sta_opmode.changed |= STA_OPMODE_N_SS_CHANGED; -+ cur_nss = sta->sta.rx_nss; -+ sta->sta.rx_nss = 0; -+ ieee80211_sta_set_rx_nss(sta); -+ /* Do not allow an nss change to rx_nss greater than max_nss negotiated during -+ * association. ++ cur_nss = link_sta->pub->rx_nss; ++ link_sta->pub->rx_nss = 0; ++ ieee80211_sta_set_rx_nss(link_sta); ++ /* ++ * Do not allow an nss change to rx_nss greater than max_nss ++ * negotiated during association. + */ -+ if (nss <= sta->sta.rx_nss) { -+ sta->sta.rx_nss = nss; ++ if (nss <= link_sta->pub->rx_nss) { ++ link_sta->pub->rx_nss = nss; + sta_opmode.rx_nss = nss; + changed |= IEEE80211_RC_NSS_CHANGED; + sta_opmode.changed |= STA_OPMODE_N_SS_CHANGED; -+ } -+ else { -+ sta->sta.rx_nss = cur_nss; ++ } else { ++ link_sta->pub->rx_nss = cur_nss; + pr_warn_ratelimited("Ignoring VHT Operating Mode Notification from STA" -+ " %pM with invalid nss %d", sta->sta.addr, nss); ++ " %pM with invalid nss %d", ++ link_sta->pub->addr, nss); + } } switch (opmode & IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK) { --- -2.7.4 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/353-ath11k-fix-bandwidth-change-issue-for-peer-sta.patch b/feeds/ipq95xx/mac80211/patches/qca/353-ath11k-fix-bandwidth-change-issue-for-peer-sta.patch index c60817e2f..8064e12d1 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/353-ath11k-fix-bandwidth-change-issue-for-peer-sta.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/353-ath11k-fix-bandwidth-change-issue-for-peer-sta.patch @@ -152,7 +152,7 @@ index 1dcfc43..b30c9a1 100644 + spin_lock_bh(&ar->data_lock); + + /* Set arsta bw and last bw */ -+ arsta->bw = arsta->bw_last = sta->bandwidth; ++ arsta->bw = arsta->bw_last = sta->deflink.bandwidth; + + spin_unlock_bh(&ar->data_lock); + diff --git a/feeds/ipq95xx/mac80211/patches/qca/353-ath11k-ignore-frags-from-uninitialized-peer-in-dp.patch b/feeds/ipq95xx/mac80211/patches/qca/353-ath11k-ignore-frags-from-uninitialized-peer-in-dp.patch index 0376ef9e2..a09e44860 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/353-ath11k-ignore-frags-from-uninitialized-peer-in-dp.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/353-ath11k-ignore-frags-from-uninitialized-peer-in-dp.patch @@ -74,7 +74,7 @@ Signed-off-by: Nagarajan Maran /* TODO: Setup other peer specific resource used in data path */ --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -4241,6 +4241,7 @@ int ath11k_peer_rx_frag_setup(struct ath +@@ -4123,6 +4123,7 @@ int ath11k_peer_rx_frag_setup(struct ath } peer->tfm_mmic = tfm; @@ -82,7 +82,7 @@ Signed-off-by: Nagarajan Maran spin_unlock_bh(&ab->base_lock); return 0; -@@ -4686,6 +4687,14 @@ static int ath11k_dp_rx_frag_h_mpdu(stru +@@ -4569,6 +4570,14 @@ static int ath11k_dp_rx_frag_h_mpdu(stru ret = -ENOENT; goto out_unlock; } @@ -97,7 +97,7 @@ Signed-off-by: Nagarajan Maran rx_tid = &peer->rx_tid[tid]; if ((!skb_queue_empty(&rx_tid->rx_frags) && seqno != rx_tid->cur_sn) || -@@ -4701,7 +4710,7 @@ static int ath11k_dp_rx_frag_h_mpdu(stru +@@ -4584,7 +4593,7 @@ static int ath11k_dp_rx_frag_h_mpdu(stru goto out_unlock; } @@ -108,8 +108,8 @@ Signed-off-by: Nagarajan Maran ath11k_dp_rx_h_sort_frags(ar, &rx_tid->rx_frags, msdu); --- a/drivers/net/wireless/ath/ath11k/peer.h +++ b/drivers/net/wireless/ath/ath11k/peer.h -@@ -96,6 +96,8 @@ struct ath11k_peer { - bool is_authorized; +@@ -98,6 +98,8 @@ struct ath11k_peer { + bool delayba_flag; bool peer_logging_enabled; bool delete_in_progress; + /* Peer's datapath set flag */ diff --git a/feeds/ipq95xx/mac80211/patches/qca/354-ath11k-Fix-unmapping-allocated-memory.patch b/feeds/ipq95xx/mac80211/patches/qca/354-ath11k-Fix-unmapping-allocated-memory.patch index de5666f8b..9770779d6 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/354-ath11k-Fix-unmapping-allocated-memory.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/354-ath11k-Fix-unmapping-allocated-memory.patch @@ -19,7 +19,7 @@ Signed-off-by: Rahul Bhattacharjee --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -1329,6 +1329,8 @@ int ath11k_core_ssr_notifier_cb(struct n +@@ -1852,6 +1852,8 @@ int ath11k_core_ssr_notifier_cb(struct n ath11k_hal_dump_srng_stats(qmi->ab); /* TODO Add more driver stats */ @@ -30,7 +30,7 @@ Signed-off-by: Rahul Bhattacharjee BUG_ON(1); --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c -@@ -2690,7 +2690,7 @@ out: +@@ -2770,7 +2770,7 @@ out: return ret; } @@ -39,7 +39,7 @@ Signed-off-by: Rahul Bhattacharjee { int i; -@@ -2713,6 +2713,13 @@ static void ath11k_qmi_free_target_mem_c +@@ -2800,6 +2800,13 @@ static void ath11k_qmi_free_target_mem_c iounmap(ab->qmi.qdss_mem[0].vaddr); ab->qmi.qdss_mem[0].vaddr = NULL; } @@ -55,10 +55,9 @@ Signed-off-by: Rahul Bhattacharjee static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab) --- a/drivers/net/wireless/ath/ath11k/qmi.h +++ b/drivers/net/wireless/ath/ath11k/qmi.h -@@ -726,5 +726,6 @@ int ath11k_enable_fwlog(struct ath11k_ba +@@ -734,4 +734,5 @@ int ath11k_qmi_fwreset_from_cold_boot(st + int ath11k_enable_fwlog(struct ath11k_base *ab); int ath11k_qmi_mem_read(struct ath11k_base *ab, u32 mem_addr, void *mem_value, size_t count); int ath11k_qmi_mem_write(struct ath11k_base *ab, u32 mem_addr, void* mem_value, size_t count); - +void ath11k_qmi_free_target_mem_chunk(struct ath11k_base *ab); - #endif diff --git a/feeds/ipq95xx/mac80211/patches/qca/354-ath11k-Update-the-Rate-Table-information-display.patch b/feeds/ipq95xx/mac80211/patches/qca/354-ath11k-Update-the-Rate-Table-information-display.patch index 240a77e51..4cc840125 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/354-ath11k-Update-the-Rate-Table-information-display.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/354-ath11k-Update-the-Rate-Table-information-display.patch @@ -15,11 +15,9 @@ Signed-off-by: Balamurugan Mahalingam drivers/net/wireless/ath/ath11k/dp_rx.c | 18 +-- 3 files changed, 101 insertions(+), 29 deletions(-) -diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h -index 019347b..5450397 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -429,7 +429,7 @@ struct ath11k_rx_peer_rate_stats { +@@ -520,7 +520,7 @@ struct ath11k_rx_peer_rate_stats { u64 bw_count[HAL_RX_BW_MAX]; u64 gi_count[HAL_RX_GI_MAX]; u64 legacy_count[HAL_RX_MAX_NUM_LEGACY_RATES]; @@ -28,11 +26,9 @@ index 019347b..5450397 100644 }; struct ath11k_rx_peer_stats { -diff --git a/drivers/net/wireless/ath/ath11k/debugfs_sta.c b/drivers/net/wireless/ath/ath11k/debugfs_sta.c -index b8eb09f..820552d 100644 --- a/drivers/net/wireless/ath/ath11k/debugfs_sta.c +++ b/drivers/net/wireless/ath/ath11k/debugfs_sta.c -@@ -400,8 +400,7 @@ static ssize_t ath11k_dbg_sta_dump_rx_stats(struct file *file, +@@ -400,8 +400,7 @@ static ssize_t ath11k_dbg_sta_dump_rx_st int len = 0, i, retval = 0; const int size = 4 * 4096; char *buf; @@ -42,7 +38,7 @@ index b8eb09f..820552d 100644 char *legacy_rate_str[] = {"1Mbps", "2Mbps", "5.5Mbps", "6Mbps", "9Mbps", "11Mbps", "12Mbps", "18Mbps", "24Mbps", "36 Mbps", "48Mbps", "54Mbps"}; -@@ -414,9 +413,6 @@ static ssize_t ath11k_dbg_sta_dump_rx_stats(struct file *file, +@@ -414,9 +413,6 @@ static ssize_t ath11k_dbg_sta_dump_rx_st ATH11K_MEMORY_STATS_INC(ar->ab, malloc_size, size); @@ -52,7 +48,7 @@ index b8eb09f..820552d 100644 mutex_lock(&ar->conf_mutex); spin_lock_bh(&ar->ab->base_lock); -@@ -494,12 +490,54 @@ static ssize_t ath11k_dbg_sta_dump_rx_stats(struct file *file, +@@ -494,12 +490,54 @@ static ssize_t ath11k_dbg_sta_dump_rx_st rx_stats->pkt_stats.bw_count[2], rx_stats->pkt_stats.bw_count[3]); len += scnprintf(buf + len, size - len, "\nRate Table (packets):\n"); @@ -61,7 +57,8 @@ index b8eb09f..820552d 100644 - rx_stats->pkt_stats.rx_rate[i], - (i + 1) % (he_rates_avail ? 12 : 8) ? "\t" : "\n"); + num_run = HAL_RX_BW_MAX * HAL_RX_GI_MAX * HAL_RX_MAX_NSS; -+ + +- len += scnprintf(buf + len, size - len, "\nRX success byte stats:\n"); + for (i = 0; i < num_run; i++) { + found = 0; + for (mcs = 0; mcs < (HAL_RX_MAX_MCS_HT + 1); mcs++) @@ -96,8 +93,7 @@ index b8eb09f..820552d 100644 + mcs, rx_stats->pkt_stats.rx_rate[bw][gi][nss][mcs]); + } + } - -- len += scnprintf(buf + len, size - len, "\nRX success byte stats:\n"); ++ + if (nss++ >= HAL_RX_MAX_NSS - 1) { + nss = 0; + if (gi++ >= HAL_RX_GI_MAX - 1) { @@ -112,7 +108,7 @@ index b8eb09f..820552d 100644 len += scnprintf(buf + len, size - len, "\nHE byte stats:\n"); for (i = 0; i <= HAL_RX_MAX_MCS_HE; i++) len += scnprintf(buf + len, size - len, "MCS %d: %llu%s", i, -@@ -538,10 +576,54 @@ static ssize_t ath11k_dbg_sta_dump_rx_stats(struct file *file, +@@ -538,10 +576,54 @@ static ssize_t ath11k_dbg_sta_dump_rx_st rx_stats->byte_stats.bw_count[2], rx_stats->byte_stats.bw_count[3]); len += scnprintf(buf + len, size - len, "\nRate Table (bytes):\n"); @@ -171,11 +167,9 @@ index b8eb09f..820552d 100644 len += scnprintf(buf + len, size - len, "\nDCM: %llu\nRU26: %llu \nRU52: %llu \nRU106: %llu \nRU242: %llu \nRU484: %llu \nRU996: %llu\n", rx_stats->dcm_count, rx_stats->ru_alloc_cnt[0], -diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c -index 9e05ddd..04946cb 100644 --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -3473,7 +3473,6 @@ ath11k_dp_rx_update_peer_rate_table_stats(struct ath11k_rx_peer_stats *rx_stats, +@@ -3474,7 +3474,6 @@ ath11k_dp_rx_update_peer_rate_table_stat struct hal_rx_user_status* user_stats, u32 num_msdu) { @@ -183,7 +177,7 @@ index 9e05ddd..04946cb 100644 u32 mcs_idx = (user_stats) ? user_stats->mcs : ppdu_info->mcs; u32 nss_idx = (user_stats) ? user_stats->nss - 1 : ppdu_info->nss - 1; u32 bw_idx = ppdu_info->bw; -@@ -3484,23 +3483,14 @@ ath11k_dp_rx_update_peer_rate_table_stats(struct ath11k_rx_peer_stats *rx_stats, +@@ -3485,23 +3484,15 @@ ath11k_dp_rx_update_peer_rate_table_stat return; } @@ -192,13 +186,13 @@ index 9e05ddd..04946cb 100644 - rate_idx = mcs_idx * 8 + 8 * 10 * nss_idx; - rate_idx += bw_idx * 2 + gi_idx; - } else if (ppdu_info->preamble_type == HAL_RX_PREAMBLE_11AX) { -+ if (ppdu_info->preamble_type == HAL_RX_PREAMBLE_11AX) ++ if (ppdu_info->preamble_type == HAL_RX_PREAMBLE_11AX) { gi_idx = ath11k_he_gi_to_nl80211_he_gi(ppdu_info->gi); - rate_idx = mcs_idx * 12 + 12 * 12 * nss_idx; - rate_idx += bw_idx * 3 + gi_idx; -- } else { +- } else { - return; -- } + } - rx_stats->pkt_stats.rx_rate[rate_idx] += num_msdu; + rx_stats->pkt_stats.rx_rate[bw_idx][gi_idx][nss_idx][mcs_idx] += num_msdu; @@ -211,6 +205,3 @@ index 9e05ddd..04946cb 100644 } static void ath11k_dp_rx_update_peer_su_stats(struct ath11k *ar, --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/358-ath11k-fix-tx-bitrate-retry-signal-in-station-dump.patch b/feeds/ipq95xx/mac80211/patches/qca/358-ath11k-fix-tx-bitrate-retry-signal-in-station-dump.patch new file mode 100644 index 000000000..c5312ce7d --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/358-ath11k-fix-tx-bitrate-retry-signal-in-station-dump.patch @@ -0,0 +1,398 @@ +From 7a29b2630ed3c71959b924674a0b39911140e7e1 Mon Sep 17 00:00:00 2001 +From: Sowmiya Sree Elavalagan +Date: Mon, 10 Oct 2022 22:43:46 +0530 +Subject: [PATCH] ath11k: Fix rssi and retry count in station dump and skip tx bitrate update + for mgmt frames + +Fix signal and signal average in station dump by using real +noise floor and appropriate bandwidth offset. In this way +signal strength in station matches the rssi_in_dbm in htt stats +Tx bitrate in station dump was dropping to legacy rate +randomly, this is because the tx rate was updated for +management packet as well. Skip tx bitrate update for +management packets based on the tid. +Tx retries in station dump is showing 0 always. +Fixed it by getting the retry count in tx completion path +from tx descriptors. And updated this to station info in +sta_statistics mac ops. + +Signed-off-by: Sowmiya Sree Elavalagan +--- + drivers/net/wireless/ath/ath11k/core.h | 2 + + drivers/net/wireless/ath/ath11k/dp_rx.c | 154 ++++++++++++------------ + drivers/net/wireless/ath/ath11k/mac.c | 30 +++-- + drivers/net/wireless/ath/ath11k/wmi.c | 6 +- + 4 files changed, 106 insertions(+), 86 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -680,6 +680,7 @@ struct ath11k_sta { + u8 rssi_comb; + struct ewma_avg_rssi avg_rssi; + s8 rssi_beacon; ++ u32 tx_retry_count; + s8 chain_signal[IEEE80211_MAX_CHAINS]; + struct ath11k_htt_tx_stats *tx_stats; + struct ath11k_rx_peer_stats *rx_stats; +@@ -720,6 +721,7 @@ struct ath11k_sta { + /*bytes count for bit error rate computation*/ + u32 ber_succ_bytes; + u32 ber_fail_bytes; ++ u32 last_tx_pkt_bw; + struct work_struct tid_config_wk; + struct ath11k_tid_qos_config tid_cfg[ATH11K_TID_MAX]; + #ifdef CPTCFG_ATH11K_CFR +@@ -923,6 +925,7 @@ struct ath11k { + u32 txpower_scale; + u32 power_scale; + u32 chan_tx_pwr; ++ s32 chan_noise_floor; + u32 num_stations; + u32 max_num_stations; + /* To synchronize concurrent synchronous mac80211 callback operations, +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -1607,91 +1607,92 @@ ath11k_update_per_peer_tx_stats(struct a + ru_start = user_rate->ru_start; + ru_tone = user_rate->ru_end; + +- /* Note: If host configured fixed rates and in some other special +- * cases, the broadcast/management frames are sent in different rates. +- * Firmware rate's control to be skipped for this? ++ /* PPDU stats reported for mgmt packet doesn't have valid tx bytes. ++ * So skip peer stats update for mgmt packets. + */ + +- if (flags == WMI_RATE_PREAMBLE_HE && mcs > ATH11K_HE_MCS_MAX) { +- ath11k_warn(ab, "Invalid HE mcs %d peer stats", mcs); +- return; +- } ++ if (tid < HTT_PPDU_STATS_NON_QOS_TID) { ++ /* Note: If host configured fixed rates and in some other special ++ * cases, the broadcast/management frames are sent in different rates. ++ * Firmware rate's control to be skipped for this? ++ */ + +- if (flags == WMI_RATE_PREAMBLE_VHT && mcs > ATH11K_VHT_MCS_MAX) { +- ath11k_warn(ab, "Invalid VHT mcs %d peer stats", mcs); +- return; +- } ++ if (flags == WMI_RATE_PREAMBLE_HE && mcs > ATH11K_HE_MCS_MAX) { ++ ath11k_warn(ab, "Invalid HE mcs %d peer stats", mcs); ++ return; ++ } + +- if (flags == WMI_RATE_PREAMBLE_HT && (mcs > ATH11K_HT_MCS_MAX || nss < 1)) { +- ath11k_warn(ab, "Invalid HT mcs %d nss %d peer stats", +- mcs, nss); +- return; +- } ++ if (flags == WMI_RATE_PREAMBLE_VHT && mcs > ATH11K_VHT_MCS_MAX) { ++ ath11k_warn(ab, "Invalid VHT mcs %d peer stats", mcs); ++ return; ++ } + +- if (flags == WMI_RATE_PREAMBLE_CCK || flags == WMI_RATE_PREAMBLE_OFDM) { +- ret = ath11k_mac_hw_ratecode_to_legacy_rate(mcs, +- flags, +- &rate_idx, +- &rate); +- if (ret < 0) ++ if (flags == WMI_RATE_PREAMBLE_HT && (mcs > ATH11K_HT_MCS_MAX || nss < 1)) { ++ ath11k_warn(ab, "Invalid HT mcs %d nss %d peer stats", ++ mcs, nss); + return; +- } ++ } + +- rcu_read_lock(); +- spin_lock_bh(&ab->base_lock); +- peer = ath11k_peer_find_by_id(ab, usr_stats->peer_id); ++ if (flags == WMI_RATE_PREAMBLE_CCK || flags == WMI_RATE_PREAMBLE_OFDM) { ++ ret = ath11k_mac_hw_ratecode_to_legacy_rate(mcs, ++ flags, ++ &rate_idx, ++ &rate); ++ if (ret < 0) ++ return; ++ } + +- if (!peer || !peer->sta) { +- spin_unlock_bh(&ab->base_lock); +- rcu_read_unlock(); +- return; +- } ++ rcu_read_lock(); ++ spin_lock_bh(&ab->base_lock); ++ peer = ath11k_peer_find_by_id(ab, usr_stats->peer_id); ++ ++ if (!peer || !peer->sta) { ++ spin_unlock_bh(&ab->base_lock); ++ rcu_read_unlock(); ++ return; ++ } + +- sta = peer->sta; +- arsta = (struct ath11k_sta *)sta->drv_priv; ++ sta = peer->sta; ++ arsta = (struct ath11k_sta *)sta->drv_priv; + +- memset(&arsta->txrate, 0, sizeof(arsta->txrate)); ++ memset(&arsta->txrate, 0, sizeof(arsta->txrate)); + +- switch (flags) { +- case WMI_RATE_PREAMBLE_OFDM: +- arsta->txrate.legacy = rate; +- break; +- case WMI_RATE_PREAMBLE_CCK: +- arsta->txrate.legacy = rate; +- break; +- case WMI_RATE_PREAMBLE_HT: +- arsta->txrate.mcs = mcs + 8 * (nss - 1); +- arsta->txrate.flags = RATE_INFO_FLAGS_MCS; +- if (sgi) +- arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; +- break; +- case WMI_RATE_PREAMBLE_VHT: +- arsta->txrate.mcs = mcs; +- arsta->txrate.flags = RATE_INFO_FLAGS_VHT_MCS; +- if (sgi) +- arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; +- break; +- case WMI_RATE_PREAMBLE_HE: +- arsta->txrate.mcs = mcs; +- arsta->txrate.flags = RATE_INFO_FLAGS_HE_MCS; +- arsta->txrate.he_dcm = dcm; +- arsta->txrate.he_gi = ath11k_mac_he_gi_to_nl80211_he_gi(sgi); +- arsta->txrate.he_ru_alloc = ath11k_mac_phy_he_ru_to_nl80211_he_ru_alloc +- ((user_rate->ru_end - +- user_rate->ru_start) + 1); +- break; +- } ++ switch (flags) { ++ case WMI_RATE_PREAMBLE_OFDM: ++ arsta->txrate.legacy = rate; ++ break; ++ case WMI_RATE_PREAMBLE_CCK: ++ arsta->txrate.legacy = rate; ++ break; ++ case WMI_RATE_PREAMBLE_HT: ++ arsta->txrate.mcs = mcs + 8 * (nss - 1); ++ arsta->txrate.flags = RATE_INFO_FLAGS_MCS; ++ if (sgi) ++ arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; ++ break; ++ case WMI_RATE_PREAMBLE_VHT: ++ arsta->txrate.mcs = mcs; ++ arsta->txrate.flags = RATE_INFO_FLAGS_VHT_MCS; ++ if (sgi) ++ arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; ++ break; ++ case WMI_RATE_PREAMBLE_HE: ++ arsta->txrate.mcs = mcs; ++ arsta->txrate.flags = RATE_INFO_FLAGS_HE_MCS; ++ arsta->txrate.he_dcm = dcm; ++ arsta->txrate.he_gi = ath11k_mac_he_gi_to_nl80211_he_gi(sgi); ++ arsta->txrate.he_ru_alloc = ath11k_mac_phy_he_ru_to_nl80211_he_ru_alloc ++ ((user_rate->ru_end - ++ user_rate->ru_start) + 1); ++ break; ++ } + +- arsta->txrate.nss = nss; ++ arsta->txrate.nss = nss; + +- arsta->txrate.bw = ath11k_mac_bw_to_mac80211_bw(bw); +- arsta->tx_duration += tx_duration; +- memcpy(&arsta->last_txrate, &arsta->txrate, sizeof(struct rate_info)); ++ arsta->txrate.bw = ath11k_mac_bw_to_mac80211_bw(bw); ++ arsta->tx_duration += tx_duration; ++ memcpy(&arsta->last_txrate, &arsta->txrate, sizeof(struct rate_info)); + +- /* PPDU stats reported for mgmt packet doesn't have valid tx bytes. +- * So skip peer stats update for mgmt packets. +- */ +- if (tid < HTT_PPDU_STATS_NON_QOS_TID) { + memset(peer_stats, 0, sizeof(*peer_stats)); + peer_stats->succ_pkts = succ_pkts; + peer_stats->succ_bytes = succ_bytes; +@@ -1719,12 +1720,12 @@ ath11k_update_per_peer_tx_stats(struct a + + if (unlikely(ath11k_debugfs_is_extd_tx_stats_enabled(ar))) + ath11k_debugfs_sta_add_tx_stats(arsta, peer_stats, rate_idx); ++ ++ spin_unlock_bh(&ab->base_lock); ++ rcu_read_unlock(); + } + + usr_stats->rate_stats_updated = true; +- +- spin_unlock_bh(&ab->base_lock); +- rcu_read_unlock(); + } + + static void ath11k_htt_update_ppdu_stats(struct ath11k *ar, +@@ -3509,13 +3510,16 @@ static void ath11k_dp_rx_update_peer_su_ + { + struct ath11k_rx_peer_stats *rx_stats = arsta->rx_stats; + u32 num_msdu; ++ u32 bw_offset; + int i; + + if (!rx_stats) + return; + ++ arsta->last_tx_pkt_bw = ppdu_info->bw; ++ bw_offset = arsta->last_tx_pkt_bw * 3; + arsta->rssi_comb = ppdu_info->rssi_comb; +- ewma_avg_rssi_add(&arsta->avg_rssi, ppdu_info->rssi_comb); ++ ewma_avg_rssi_add(&arsta->avg_rssi, ppdu_info->rssi_comb + bw_offset); + + if (!ath11k_debugfs_is_extd_rx_stats_enabled(ar)) + return; +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -11471,6 +11471,7 @@ static void ath11k_mac_op_sta_statistics + struct ath11k *ar = arsta->arvif->ar; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + s8 signal; ++ u32 bw_offset = 0; + bool db2dbm = test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT, + ar->ab->wmi_ab.svc_map); + +@@ -11480,6 +11481,11 @@ static void ath11k_mac_op_sta_statistics + sinfo->tx_duration = arsta->tx_duration; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_DURATION); + ++ if (arsta->tx_retry_count) { ++ sinfo->tx_retries = arsta->tx_retry_count; ++ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES); ++ } ++ + if (arsta->txrate.legacy || arsta->txrate.nss) { + if (arsta->txrate.legacy) { + sinfo->txrate.legacy = arsta->txrate.legacy; +@@ -11505,25 +11511,35 @@ static void ath11k_mac_op_sta_statistics + ath11k_mac_put_chain_rssi(sinfo, arsta, "fw stats", true); + } + +- signal = arsta->rssi_comb; +- if (!signal && ++ if (arsta->rssi_comb) { ++ bw_offset = arsta->last_tx_pkt_bw * 3; ++ signal = arsta->rssi_comb + ar->chan_noise_floor + bw_offset; ++ sinfo->signal = signal; ++ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL); ++ } else if (!signal && + arsta->arvif->vdev_type == WMI_VDEV_TYPE_STA && + ar->ab->hw_params.supports_rssi_stats && + !(ath11k_debugfs_get_fw_stats(ar, ar->pdev->pdev_id, 0, +- WMI_REQUEST_VDEV_STAT))) ++ WMI_REQUEST_VDEV_STAT))) { + signal = arsta->rssi_beacon; + ++ if (signal) { ++ sinfo->signal = db2dbm ? signal : signal + ATH11K_DEFAULT_NOISE_FLOOR; ++ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL); ++ } ++ } ++ + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, + "mac sta statistics db2dbm %u rssi comb %d rssi beacon %d\n", + db2dbm, arsta->rssi_comb, arsta->rssi_beacon); + +- if (signal) { +- sinfo->signal = db2dbm ? signal : signal + ATH11K_DEFAULT_NOISE_FLOOR; +- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL); ++ if (ar->chan_noise_floor) { ++ sinfo->signal_avg = ewma_avg_rssi_read(&arsta->avg_rssi) + ++ ar->chan_noise_floor; ++ } else { ++ sinfo->signal_avg = ewma_avg_rssi_read(&arsta->avg_rssi) + ++ ATH11K_DEFAULT_NOISE_FLOOR; + } +- +- sinfo->signal_avg = ewma_avg_rssi_read(&arsta->avg_rssi) + +- ATH11K_DEFAULT_NOISE_FLOOR; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG); + + if (arvif->ar->ab->nss.enabled) +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -7077,10 +7077,12 @@ static int ath11k_pull_wds_addr_ev(struc + return 0; + } + +-static void ath11k_wmi_pull_pdev_stats_base(const struct wmi_pdev_stats_base *src, ++static void ath11k_wmi_pull_pdev_stats_base(struct ath11k *ar, ++ const struct wmi_pdev_stats_base *src, + struct ath11k_fw_stats_pdev *dst) + { + dst->ch_noise_floor = src->chan_nf; ++ ar->chan_noise_floor = src->chan_nf; + dst->tx_frame_count = src->tx_frame_count; + dst->rx_frame_count = src->rx_frame_count; + dst->rx_clear_count = src->rx_clear_count; +@@ -7304,7 +7306,7 @@ static int ath11k_wmi_tlv_fw_stats_data_ + if (!dst) + continue; + +- ath11k_wmi_pull_pdev_stats_base(&src->base, dst); ++ ath11k_wmi_pull_pdev_stats_base(ar, &src->base, dst); + ath11k_wmi_pull_pdev_stats_tx(&src->tx, dst); + ath11k_wmi_pull_pdev_stats_rx(&src->rx, dst); + list_add_tail(&dst->list, &stats->pdevs); +--- a/drivers/net/wireless/ath/ath11k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_tx.c +@@ -795,6 +795,7 @@ static void ath11k_dp_tx_complete_msdu(s + struct hal_tx_status ts = { 0 }; + enum hal_wbm_htt_tx_comp_status wbm_status; + enum hal_wbm_tqm_rel_reason rel_status; ++ u32 bw_offset; + u8 flags = 0; + + if (unlikely(WARN_ON_ONCE(buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM))) { +@@ -851,15 +852,6 @@ static void ath11k_dp_tx_complete_msdu(s + /* skip tx rate update from ieee80211_status*/ + info->status.rates[0].idx = -1; + +- if (ts.status == HAL_WBM_TQM_REL_REASON_FRAME_ACKED && +- !(info->flags & IEEE80211_TX_CTL_NO_ACK) && +- !(flags & ATH11K_SKB_F_NOACK_TID)) { +- info->flags |= IEEE80211_TX_STAT_ACK; +- info->status.ack_signal = ATH11K_DEFAULT_NOISE_FLOOR + +- ts.ack_rssi; +- info->status.flags |= IEEE80211_TX_STATUS_ACK_SIGNAL_VALID; +- } +- + if (ts.status == HAL_WBM_TQM_REL_REASON_CMD_REMOVE_TX && + (info->flags & IEEE80211_TX_CTL_NO_ACK) && + (flags & ATH11K_SKB_F_NOACK_TID)) +@@ -911,6 +903,17 @@ static void ath11k_dp_tx_complete_msdu(s + status.rates = &status_rate; + status.n_rates = 1; + ++ arsta->tx_retry_count += ts.try_cnt > 1 ? (ts.try_cnt - 1) : 0; ++ ++ if (ts.status == HAL_WBM_TQM_REL_REASON_FRAME_ACKED && ++ !(info->flags & IEEE80211_TX_CTL_NO_ACK) && ++ !(flags & ATH11K_SKB_F_NOACK_TID)) { ++ info->flags |= IEEE80211_TX_STAT_ACK; ++ bw_offset = arsta->last_tx_pkt_bw * ATH11K_TX_PKTS_BW_OFFSET; ++ info->status.ack_signal = ts.ack_rssi + ar->chan_noise_floor + bw_offset; ++ info->status.flags |= IEEE80211_TX_STATUS_ACK_SIGNAL_VALID; ++ } ++ + if (ts.status != HAL_WBM_TQM_REL_REASON_FRAME_ACKED) { + arsta->fail_pkts += 1; + arsta->per_fail_pkts += 1; +--- a/drivers/net/wireless/ath/ath11k/dp_tx.h ++++ b/drivers/net/wireless/ath/ath11k/dp_tx.h +@@ -12,6 +12,7 @@ + #define ATH11K_NUM_PKTS_THRSHLD_FOR_PER 50 + #define ATH11K_GET_PERCENTAGE(value, total_value) (((value)*100)/(total_value)) + #define ATH11K_NUM_BYTES_THRSHLD_FOR_BER 25000 ++#define ATH11K_TX_PKTS_BW_OFFSET 3 + + struct ath11k_dp_htt_wbm_tx_status { + u32 msdu_id; diff --git a/feeds/ipq95xx/mac80211/patches/qca/358-ath11k-skip-caldb-alloc-in-seg-mode.patch b/feeds/ipq95xx/mac80211/patches/qca/358-ath11k-skip-caldb-alloc-in-seg-mode.patch new file mode 100644 index 000000000..8b7f01aba --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/358-ath11k-skip-caldb-alloc-in-seg-mode.patch @@ -0,0 +1,41 @@ +From 26988f50228b268b08361df4033f614fc2b17c30 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Kathirvel +Date: Fri, 30 Sep 2022 23:19:29 +0530 +Subject: [PATCH] ath11k: skip caldb alloc in seg mode when cold_boot_cal is + disabled + +In segmented approach, when cold boot calibration is disabled caldb +memory segments are allocated and responded to the firmware. This memory +will be unused. + +Skip allocating caldb memory when cold boot calibration is disabled. + +Signed-off-by: Karthikeyan Kathirvel +--- + drivers/net/wireless/ath/ath11k/qmi.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c +index 104df0cae14d..b40027550e8e 100644 +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -2797,6 +2797,16 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab) + for (i = 0; i < ab->qmi.mem_seg_count; i++) { + chunk = &ab->qmi.target_mem[i]; + ++ ++ if (chunk->type == CALDB_MEM_REGION_TYPE && (!ab->enable_cold_boot_cal ++ || !ab->hw_params.cold_boot_calib)) { ++ ath11k_info(ab, "Skipping caldb allocation chunk->size %u chunk->paddr %pad\n", ++ chunk->size, &chunk->paddr); ++ chunk->paddr = 0; ++ chunk->vaddr = NULL; ++ continue; ++ } ++ + /* + * Ignore the memory request from FW if size is more than 2MB + * if host sends failure, FW reqesut for 2MB segments in mode-0 +-- +2.37.3 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/358-mac80211-Don-t-stop-queue-when-qdisc-is-noqueue.patch b/feeds/ipq95xx/mac80211/patches/qca/358-mac80211-Don-t-stop-queue-when-qdisc-is-noqueue.patch new file mode 100644 index 000000000..dd85fc34f --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/358-mac80211-Don-t-stop-queue-when-qdisc-is-noqueue.patch @@ -0,0 +1,120 @@ +From f79327c3c3ef964c0d6d98643b5fd47acbe8e1dc Mon Sep 17 00:00:00 2001 +From: Tamizh Chelvam Raja +Date: Wed, 22 Jun 2022 12:48:05 +0530 +Subject: [PATCH] mac80211: Don't stop queue when qdisc is noqueue + +User can set noqueue for an interface and mac80211 +doesn't know about the qdisc configuration, so it +stop queues in some scenarios and that cause below +warning messages flood on the console. + +Example callbacks: + +* ieee80211_rx_napi->ieee80211_rx_list-> ieee80211_prepare_and_rx_handle + | +__ieee80211_stop_queue<-ieee80211_add_pending_skb <- ieee80211_rx_h_mesh_fwding + +* ieee80211_add_pending_skbs->__ieee80211_stop_queue + +Virtual device wlanX asks to queue packet! + +To avoid this warning, enable vif specific debugfs +entry to notify that qdisc is configured with +noqueue and do not stop the queue for the netdev. And +drop the pkt in mac80211 until the hw queue started again. + +Signed-off-by: Tamizh Chelvam Raja +--- + include/net/mac80211.h | 2 ++ + net/mac80211/debugfs_netdev.c | 28 ++++++++++++++++++++++++++++ + net/mac80211/tx.c | 8 ++++++++ + net/mac80211/util.c | 13 ++++++++++++- + 4 files changed, 50 insertions(+), 1 deletion(-) + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -1911,6 +1911,7 @@ struct ieee80211_vif { + bool rx_mcast_action_reg; + + bool txqs_stopped[IEEE80211_NUM_ACS]; ++ bool noqueue_enable; + + struct ieee80211_vif *mbssid_tx_vif; + +--- a/net/mac80211/debugfs_netdev.c ++++ b/net/mac80211/debugfs_netdev.c +@@ -323,6 +323,32 @@ static ssize_t ieee80211_if_parse_bmiss_ + + IEEE80211_IF_FILE_RW(bmiss_threshold); + ++static ssize_t ieee80211_if_fmt_noqueue_enable(const struct ieee80211_sub_if_data *sdata, ++ char *buf, int buflen) ++{ ++ return snprintf(buf, buflen, "%u\n", sdata->vif.noqueue_enable); ++} ++ ++static ssize_t ieee80211_if_parse_noqueue_enable(struct ieee80211_sub_if_data *sdata, ++ const char *buf, int buflen) ++{ ++ int ret; ++ u8 val; ++ ++ ret = kstrtou8(buf, 0, &val); ++ if (ret) ++ return ret; ++ ++ if (val > 1) ++ return -EINVAL; ++ ++ sdata->vif.noqueue_enable = val; ++ ++ return buflen; ++} ++ ++IEEE80211_IF_FILE_RW(noqueue_enable); ++ + static ssize_t ieee80211_if_parse_tkip_mic_test( + struct ieee80211_sub_if_data *sdata, const char *buf, int buflen) + { +@@ -708,6 +734,7 @@ static void add_ap_files(struct ieee8021 + DEBUGFS_ADD_MODE(tkip_mic_test, 0200); + DEBUGFS_ADD_MODE(multicast_to_unicast, 0600); + DEBUGFS_ADD_MODE(bmiss_threshold, 0600); ++ DEBUGFS_ADD_MODE(noqueue_enable, 0600); + } + + static void add_vlan_files(struct ieee80211_sub_if_data *sdata) +@@ -729,6 +756,7 @@ static void add_mesh_files(struct ieee80 + DEBUGFS_ADD_MODE(tsf, 0600); + DEBUGFS_ADD_MODE(estab_plinks, 0400); + DEBUGFS_ADD_MODE(bmiss_threshold, 0600); ++ DEBUGFS_ADD_MODE(noqueue_enable, 0600); + } + + static void add_mesh_stats(struct ieee80211_sub_if_data *sdata) +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -417,8 +417,12 @@ void ieee80211_propagate_queue_wake(stru + if (ac_queue == queue || + (sdata->vif.cab_queue == queue && + local->queue_stop_reasons[ac_queue] == 0 && +- skb_queue_empty(&local->pending[ac_queue]))) ++ skb_queue_empty(&local->pending[ac_queue]))) { ++ if (sdata->vif.noqueue_enable) ++ continue; ++ + netif_wake_subqueue(sdata->dev, ac); ++ } + } + } + } +@@ -517,6 +521,9 @@ static void __ieee80211_stop_queue(struc + for (ac = 0; ac < n_acs; ac++) { + if (sdata->vif.hw_queue[ac] == queue || + sdata->vif.cab_queue == queue) { ++ if (!local->ops->wake_tx_queue && sdata->vif.noqueue_enable) ++ continue; ++ + if (!local->ops->wake_tx_queue) { + netif_stop_subqueue(sdata->dev, ac); + continue; diff --git a/feeds/ipq95xx/mac80211/patches/qca/359-cfg80211-Fix-mcs-divisor-value.patch b/feeds/ipq95xx/mac80211/patches/qca/359-cfg80211-Fix-mcs-divisor-value.patch new file mode 100644 index 000000000..89d0771ae --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/359-cfg80211-Fix-mcs-divisor-value.patch @@ -0,0 +1,36 @@ +From eba63277b467c7a81962e51096c776dc8efb1b81 Mon Sep 17 00:00:00 2001 +From: Tamizh Chelvam Raja +Date: Fri, 2 Sep 2022 19:47:19 +0530 +Subject: [PATCH 1/4] cfg80211: Fix mcs divisor value + +mcs divisor for mcs6 is wrongly calculated, Fix it by proper value + +previous mcs_divisor value = (11769/6144) = 1.915527 + +fixed mcs_divisor value = (11377/6144) = 1.851725 + +With the previous mcs_divisor value, bitrate for mcs6 calculated +wrongly. + +Change-Id: I822bd2e690a6b00eb01c77060327f7e40a55f37b +Signed-off-by: Tamizh Chelvam Raja +--- + net/wireless/util.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/wireless/util.c b/net/wireless/util.c +index 6f6d806..ffdb1a7 100644 +--- a/net/wireless/util.c ++++ b/net/wireless/util.c +@@ -1377,7 +1377,7 @@ static u32 cfg80211_calculate_bitrate_he(struct rate_info *rate) + 25599, /* 4.166666... */ + 17067, /* 2.777777... */ + 12801, /* 2.083333... */ +- 11769, /* 1.851851... */ ++ 11377, /* 1.851725... */ + 10239, /* 1.666666... */ + 8532, /* 1.388888... */ + 7680, /* 1.250000... */ +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/360-ath11k-add-length-validation-before-skb_put-call.patch b/feeds/ipq95xx/mac80211/patches/qca/360-ath11k-add-length-validation-before-skb_put-call.patch new file mode 100644 index 000000000..42c85c41e --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/360-ath11k-add-length-validation-before-skb_put-call.patch @@ -0,0 +1,130 @@ +From d762e0422fc0636f1eec53ebbec23a2258058734 Mon Sep 17 00:00:00 2001 +From: P Praneesh +Date: Tue, 30 Aug 2022 22:04:01 +0530 +Subject: [PATCH 2/4] ath11k: add length validation before skb_put call + +In the wbm_err path, while processing tkip mic error msdu_len is fetched +from the hal_rx_desc's msdu_end. This msdu_len is directly passing to the +skb_put without the validation. + +In the stretch test scenario, some of the descriptors received under wbm_err +is invalid and carries junk values which leads to higher msdu_len compare to +actual msdu data size. + +Add a check to drop the skb when the calculation msdu length is greater than +the skb size and add provision to capture the dropped packet count in +soc_dp_stats. + +Change-Id: I83e3440492c23a98fc3b667a78a9cc0449101231 +Signed-off-by: Tamizh Chelvam Raja +Signed-off-by: P Praneesh +--- + drivers/net/wireless/ath/ath11k/core.h | 2 ++ + drivers/net/wireless/ath/ath11k/debugfs.c | 10 ++++++---- + drivers/net/wireless/ath/ath11k/dp_rx.c | 21 +++++++++++++++++---- + 3 files changed, 25 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h +index 0fb2e80..4b17c42 100644 +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -1007,7 +1007,9 @@ struct ath11k_soc_dp_stats { + u32 err_ring_pkts; + u32 invalid_rbm; + u32 rxdma_error[HAL_REO_ENTR_RING_RXDMA_ECODE_MAX]; ++ u32 rxdma_error_drop[HAL_REO_ENTR_RING_RXDMA_ECODE_MAX]; + u32 reo_error[HAL_REO_DEST_RING_ERROR_CODE_MAX]; ++ u32 reo_error_drop[HAL_REO_DEST_RING_ERROR_CODE_MAX]; + u32 hal_reo_error[DP_REO_DST_RING_MAX]; + struct ath11k_soc_dp_tx_err_stats tx_err; + struct ath11k_dp_ring_bp_stats bp_stats; +diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c +index d62fca7..0ae0ef5 100644 +--- a/drivers/net/wireless/ath/ath11k/debugfs.c ++++ b/drivers/net/wireless/ath/ath11k/debugfs.c +@@ -1576,13 +1576,15 @@ static ssize_t ath11k_debugfs_dump_soc_dp_stats(struct file *file, + soc_stats->invalid_rbm); + len += scnprintf(buf + len, size - len, "RXDMA errors:\n"); + for (i = 0; i < HAL_REO_ENTR_RING_RXDMA_ECODE_MAX; i++) +- len += scnprintf(buf + len, size - len, "%s: %u\n", +- rxdma_err[i], soc_stats->rxdma_error[i]); ++ len += scnprintf(buf + len, size - len, "%s: handled %u dropped %u\n", ++ rxdma_err[i], soc_stats->rxdma_error[i], ++ soc_stats->rxdma_error_drop[i]); + + len += scnprintf(buf + len, size - len, "\nREO errors:\n"); + for (i = 0; i < HAL_REO_DEST_RING_ERROR_CODE_MAX; i++) +- len += scnprintf(buf + len, size - len, "%s: %u\n", +- reo_err[i], soc_stats->reo_error[i]); ++ len += scnprintf(buf + len, size - len, "%s: handled %u dropped %u\n", ++ reo_err[i], soc_stats->reo_error[i], ++ soc_stats->reo_error_drop[i]); + + len += scnprintf(buf + len, size - len, "\nHAL REO errors:\n"); + len += scnprintf(buf + len, size - len, +diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c +index 5946c5d..aefea73 100644 +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -5054,8 +5054,6 @@ static bool ath11k_dp_rx_h_reo_err(struct ath11k *ar, struct sk_buff *msdu, + struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(msdu); + bool drop = false; + +- ar->ab->soc_stats.reo_error[rxcb->err_code]++; +- + switch (rxcb->err_code) { + case HAL_REO_DEST_RING_ERROR_CODE_DESC_ADDR_ZERO: + if (ath11k_dp_rx_h_null_q_desc(ar, msdu, status, msdu_list)) +@@ -5075,10 +5073,15 @@ static bool ath11k_dp_rx_h_reo_err(struct ath11k *ar, struct sk_buff *msdu, + break; + } + ++ if (drop) ++ ar->ab->soc_stats.reo_error_drop[rxcb->err_code]++; ++ else ++ ar->ab->soc_stats.reo_error[rxcb->err_code]++; ++ + return drop; + } + +-static void ath11k_dp_rx_h_tkip_mic_err(struct ath11k *ar, struct sk_buff *msdu, ++static bool ath11k_dp_rx_h_tkip_mic_err(struct ath11k *ar, struct sk_buff *msdu, + struct ieee80211_rx_status *status) + { + u16 msdu_len; +@@ -5092,6 +5095,14 @@ static void ath11k_dp_rx_h_tkip_mic_err(struct ath11k *ar, struct sk_buff *msdu, + + l3pad_bytes = ath11k_dp_rx_h_msdu_end_l3pad(ar->ab, desc); + msdu_len = ath11k_dp_rx_h_msdu_start_msdu_len(ar->ab, desc); ++ ++ if ((hal_rx_desc_sz + l3pad_bytes + msdu_len) > DP_RX_BUFFER_SIZE) { ++ ath11k_warn(ar->ab, "invalid msdu len in tkip mirc err %u\n", msdu_len); ++ ath11k_dbg_dump(ar->ab, ATH11K_DBG_DATA, NULL, "", desc, ++ sizeof(struct hal_rx_desc)); ++ return true; ++ } ++ + skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len); + skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes); + +@@ -5102,6 +5113,8 @@ static void ath11k_dp_rx_h_tkip_mic_err(struct ath11k *ar, struct sk_buff *msdu, + + ath11k_dp_rx_h_undecap(ar, msdu, desc, + HAL_ENCRYPT_TYPE_TKIP_MIC, status, false); ++ ++ return false; + } + + static bool ath11k_dp_rx_h_rxdma_err(struct ath11k *ar, struct sk_buff *msdu, +@@ -5114,7 +5127,7 @@ static bool ath11k_dp_rx_h_rxdma_err(struct ath11k *ar, struct sk_buff *msdu, + + switch (rxcb->err_code) { + case HAL_REO_ENTR_RING_RXDMA_ECODE_TKIP_MIC_ERR: +- ath11k_dp_rx_h_tkip_mic_err(ar, msdu, status); ++ drop = ath11k_dp_rx_h_tkip_mic_err(ar, msdu, status); + break; + default: + /* TODO: Review other rxdma error code to check if anything is +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/361-ath11k-Count-wbm_tx_status-reason-code-1-as-drop-pac.patch b/feeds/ipq95xx/mac80211/patches/qca/361-ath11k-Count-wbm_tx_status-reason-code-1-as-drop-pac.patch new file mode 100644 index 000000000..adcc56e8b --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/361-ath11k-Count-wbm_tx_status-reason-code-1-as-drop-pac.patch @@ -0,0 +1,94 @@ +From 7ecea313f69620c6040610f48ff8b1406295ca8a Mon Sep 17 00:00:00 2001 +From: Tamizh Chelvam Raja +Date: Thu, 6 Oct 2022 21:42:59 +0530 +Subject: [PATCH 3/4] ath11k: Count wbm_tx_status reason code 1 as drop packets + +Consider wbm_tx_status reason code 1 as drop packets +instead of fail_pkts and not report the tx status to mac80211. +Since the wbm status of reason code 1 for msdu is packet +which is not tried to transmit in the air and its been +dropped due to hw queue full scnearo. + +Signed-off-by: Tamizh Chelvam Raja +--- + drivers/net/wireless/ath/ath11k/core.h | 2 ++ + drivers/net/wireless/ath/ath11k/debugfs_sta.c | 4 ++++ + drivers/net/wireless/ath/ath11k/dp_tx.c | 19 +++++++++++++++---- + 3 files changed, 21 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -712,12 +712,14 @@ struct ath11k_sta { + struct ewma_sta_per per; + u64 fail_pkts; + u64 succ_pkts; ++ u64 drop_pkts; + /* pkt count for packet error rate computation*/ + u32 per_fail_pkts; + u32 per_succ_pkts; + struct ewma_sta_ber ber; + u64 succ_bytes; + u64 fail_bytes; ++ u64 drop_bytes; + /*bytes count for bit error rate computation*/ + u32 ber_succ_bytes; + u32 ber_fail_bytes; +--- a/drivers/net/wireless/ath/ath11k/debugfs_sta.c ++++ b/drivers/net/wireless/ath/ath11k/debugfs_sta.c +@@ -1589,12 +1589,16 @@ static ssize_t ath11k_dbg_sta_read_htt_c + arsta->fail_pkts); + len += scnprintf(buf + len, sizeof(buf) - len, "succ_pkts : %llu\n", + arsta->succ_pkts); ++ len += scnprintf(buf + len, sizeof(buf) - len, "drop_pkts : %llu\n", ++ arsta->drop_pkts); + len += scnprintf(buf + len, sizeof(buf) - len, "PER : %lu\n", + ewma_sta_per_read(&arsta->per)); + len += scnprintf(buf + len, sizeof(buf) - len, "fail_bytes : %llu\n", + arsta->fail_bytes); + len += scnprintf(buf + len, sizeof(buf) - len, "succ_bytes : %llu\n", + arsta->succ_bytes); ++ len += scnprintf(buf + len, sizeof(buf) - len, "drop_bytes : %llu\n", ++ arsta->drop_bytes); + len += scnprintf(buf + len, sizeof(buf) - len, + "BER : %lu\n", ewma_sta_ber_read(&arsta->ber)); + spin_unlock_bh(&ar->ab->base_lock); +--- a/drivers/net/wireless/ath/ath11k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_tx.c +@@ -366,6 +366,8 @@ tcl_ring_sel: + /* TODO: Take care of other encap modes as well */ + ret = -EINVAL; + atomic_inc(&ab->soc_stats.tx_err.misc_fail); ++ arsta->drop_pkts++; ++ arsta->drop_bytes += skb->len; + goto fail_remove_idr; + } + +@@ -915,10 +917,24 @@ static void ath11k_dp_tx_complete_msdu(s + } + + if (ts.status != HAL_WBM_TQM_REL_REASON_FRAME_ACKED) { +- arsta->fail_pkts += 1; +- arsta->per_fail_pkts += 1; +- arsta->fail_bytes += msdu->len; +- arsta->ber_fail_bytes += msdu->len; ++ switch (ts.status) { ++ case HAL_WBM_TQM_REL_REASON_CMD_REMOVE_MPDU: ++ case HAL_WBM_TQM_REL_REASON_CMD_REMOVE_AGED_FRAMES: ++ case HAL_WBM_TQM_REL_REASON_CMD_REMOVE_TX: ++ arsta->drop_pkts += 1; ++ arsta->drop_bytes += msdu->len; ++ spin_unlock_bh(&ab->base_lock); ++ dev_kfree_skb_any(msdu); ++ return; ++ default: ++ //TODO: Remove this print and add as a stats ++ ath11k_dbg(ab, ATH11K_DBG_DP_TX, "tx frame is not acked status %d\n", ts.status); ++ arsta->fail_pkts += 1; ++ arsta->per_fail_pkts += 1; ++ arsta->fail_bytes += msdu->len; ++ arsta->ber_fail_bytes += msdu->len; ++ } ++ + if(arsta->per_fail_pkts + arsta->per_succ_pkts >= + ATH11K_NUM_PKTS_THRSHLD_FOR_PER) + ath11k_sta_stats_update_per(arsta); diff --git a/feeds/ipq95xx/mac80211/patches/qca/362-ath11k-fix-incorrect-ast-index-assignment-for-wds-peer.patch b/feeds/ipq95xx/mac80211/patches/qca/362-ath11k-fix-incorrect-ast-index-assignment-for-wds-peer.patch new file mode 100644 index 000000000..468c652b6 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/362-ath11k-fix-incorrect-ast-index-assignment-for-wds-peer.patch @@ -0,0 +1,96 @@ +From 396176575be9767a79d451fba4fe2931305f0435 Mon Sep 17 00:00:00 2001 +From: Raj Kumar Bhagat +Date: Mon, 7 Nov 2022 21:49:20 +0530 +Subject: [PATCH] ath11k: fix incorrect ast index assignment for wds peer + +Currently, same ast index is assigned for different nss wds peer mac +addresses which is incorrect. However, firmware provides the correct +and different ast index for different mac addresses. + +Hence, fix this issue by assigning the correct ast index provided by +the firmware. + +Signed-off-by: Raj Kumar Bhagat +--- + drivers/net/wireless/ath/ath11k/nss.c | 5 +++-- + drivers/net/wireless/ath/ath11k/nss.h | 6 ++++-- + drivers/net/wireless/ath/ath11k/peer.c | 3 +-- + 3 files changed, 8 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/nss.c b/drivers/net/wireless/ath/ath11k/nss.c +index 21322e2..7392da8 100644 +--- a/drivers/net/wireless/ath/ath11k/nss.c ++++ b/drivers/net/wireless/ath/ath11k/nss.c +@@ -3879,13 +3879,14 @@ msg_free: + } + + int ath11k_nss_map_wds_peer(struct ath11k *ar, struct ath11k_peer *peer, +- u8 *dest_mac, enum ath11k_ast_entry_type type) ++ u8 *dest_mac, struct ath11k_ast_entry *ast_entry) + { + struct ath11k_base *ab = ar->ab; + struct nss_wifili_wds_peer_map_msg *wds_peer_map_msg; + struct nss_wifili_msg *wlmsg = NULL; + nss_wifili_msg_callback_t msg_cb; + nss_tx_status_t status; ++ enum ath11k_ast_entry_type type = ast_entry->type; + int ret = 0; + + wlmsg = kzalloc(sizeof(struct nss_wifili_msg), GFP_ATOMIC); +@@ -3895,7 +3896,7 @@ int ath11k_nss_map_wds_peer(struct ath11k *ar, struct ath11k_peer *peer, + wds_peer_map_msg = &wlmsg->msg.wdspeermapmsg; + + wds_peer_map_msg->vdev_id = peer->vdev_id; +- wds_peer_map_msg->ast_idx = peer->hw_peer_id; ++ wds_peer_map_msg->ast_idx = ast_entry->ast_idx; + + if (type == ATH11K_AST_TYPE_MEC) + wds_peer_map_msg->peer_id = NSS_WIFILI_MEC_PEER_ID; +diff --git a/drivers/net/wireless/ath/ath11k/nss.h b/drivers/net/wireless/ath/ath11k/nss.h +index 3504b61..87da646 100644 +--- a/drivers/net/wireless/ath/ath11k/nss.h ++++ b/drivers/net/wireless/ath/ath11k/nss.h +@@ -17,6 +17,7 @@ struct ath11k; + struct ath11k_base; + struct ath11k_vif; + struct ath11k_peer; ++struct ath11k_ast_entry; + struct ath11k_sta; + enum ath11k_ast_entry_type; + struct hal_rx_mon_ppdu_info; +@@ -290,7 +291,7 @@ int ath11k_nss_add_wds_peer(struct ath11k *ar, struct ath11k_peer *peer, + int ath11k_nss_update_wds_peer(struct ath11k *ar, struct ath11k_peer *peer, + u8 *dest_mac); + int ath11k_nss_map_wds_peer(struct ath11k *ar, struct ath11k_peer *peer, +- u8 *dest_mac, enum ath11k_ast_entry_type type); ++ u8 *dest_mac, struct ath11k_ast_entry *ast_entry); + int ath11k_nss_del_wds_peer(struct ath11k *ar, u8 *peer_addr, + int peer_id, u8 *dest_mac); + int ath11k_nss_ext_vdev_cfg_wds_peer(struct ath11k_vif *arvif, +@@ -399,7 +400,8 @@ static inline int ath11k_nss_update_wds_peer(struct ath11k *ar, struct ath11k_pe + } + + static inline int ath11k_nss_map_wds_peer(struct ath11k *ar, struct ath11k_peer *peer, +- u8 *dest_mac, int type) ++ u8 *dest_mac, ++ struct ath11k_ast_entry *ast_entry) + { + return 0; + } +diff --git a/drivers/net/wireless/ath/ath11k/peer.c b/drivers/net/wireless/ath/ath11k/peer.c +index 7892661..243c594 100644 +--- a/drivers/net/wireless/ath/ath11k/peer.c ++++ b/drivers/net/wireless/ath/ath11k/peer.c +@@ -373,8 +373,7 @@ void ath11k_peer_map_ast(struct ath11k *ar, struct ath11k_peer *peer, + + if ((ast_entry->type == ATH11K_AST_TYPE_WDS) || + (ast_entry->type == ATH11K_AST_TYPE_MEC)) +- ath11k_nss_map_wds_peer(ar, peer, mac_addr, +- ast_entry->type); ++ ath11k_nss_map_wds_peer(ar, peer, mac_addr, ast_entry); + + ath11k_dbg(ab, ATH11K_DBG_MAC, "ath11k_peer_map_ast peer %pM ast_entry %pM\n", + peer->addr, ast_entry->addr); +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/665-ath11k-Add-the-green-AP-enabling-set-command-support.patch b/feeds/ipq95xx/mac80211/patches/qca/363-ath11k-Add-the-green-AP-enabling-set-command-support.patch similarity index 100% rename from feeds/ipq95xx/mac80211/patches/qca/665-ath11k-Add-the-green-AP-enabling-set-command-support.patch rename to feeds/ipq95xx/mac80211/patches/qca/363-ath11k-Add-the-green-AP-enabling-set-command-support.patch diff --git a/feeds/ipq95xx/mac80211/patches/qca/364-ath11k-Encoding-regdb.bin-in-board-2.bin.patch b/feeds/ipq95xx/mac80211/patches/qca/364-ath11k-Encoding-regdb.bin-in-board-2.bin.patch new file mode 100644 index 000000000..1f6ae9e5e --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/364-ath11k-Encoding-regdb.bin-in-board-2.bin.patch @@ -0,0 +1,429 @@ +From 280215228b96d7a6a4000a5f65bd015d7c21ffac Mon Sep 17 00:00:00 2001 +From: Karthik M +Date: Fri, 14 Oct 2022 20:28:38 +0530 +Subject: [PATCH] ath11k: Encoding regdb.bin in board-2.bin + +Add support to encode regdb.bin in board-2.bin along with the bdf files. + +Signed-off-by: Karthik M +--- + drivers/net/wireless/ath/ath11k/core.c | 96 ++++++++++++-------------- + drivers/net/wireless/ath/ath11k/core.h | 6 +- + drivers/net/wireless/ath/ath11k/hw.h | 2 + + drivers/net/wireless/ath/ath11k/qmi.c | 56 ++++++++++----- + drivers/net/wireless/ath/ath11k/qmi.h | 3 + + 5 files changed, 96 insertions(+), 67 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c +index f7c3762..1db2334 100644 +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -148,7 +148,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { + .supports_suspend = false, + .hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074), + .reo_dest_ring_map_shift = HAL_REO_DEST_RING_CTRL_HASH_RING_SHIFT, +- .supports_regdb = false, ++ .supports_regdb = true, + .fix_l1ss = true, + .credit_flow = false, + .hal_params = &ath11k_hw_hal_params_ipq8074, +@@ -232,7 +232,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { + .supports_suspend = false, + .hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074), + .reo_dest_ring_map_shift = HAL_REO_DEST_RING_CTRL_HASH_RING_SHIFT, +- .supports_regdb = false, ++ .supports_regdb = true, + .fix_l1ss = true, + .credit_flow = false, + .max_tx_ring = DP_TCL_NUM_RING_MAX, +@@ -392,7 +392,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { + .supports_suspend = false, + .hal_desc_sz = sizeof(struct hal_rx_desc_qcn9074), + .reo_dest_ring_map_shift = HAL_REO_DEST_RING_CTRL_HASH_RING_SHIFT, +- .supports_regdb = false, ++ .supports_regdb = true, + .fix_l1ss = true, + .credit_flow = false, + .hal_params = &ath11k_hw_hal_params_ipq8074, +@@ -699,6 +699,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { + .hal_params = &ath11k_hw_hal_params_ipq8074, + .host_ce_config = ath11k_host_ce_config_qcn9074, + .reo_dest_ring_map_shift = HAL_IPQ5018_REO_DEST_RING_CTRL_HASH_RING_SHIFT, ++ .supports_regdb = true, + .ce_count = 6, + .target_ce_config = ath11k_target_ce_config_wlan_ipq5018, + .target_ce_count = 9, +@@ -779,6 +780,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { + .idle_ps = false, + .supports_suspend = false, + .host_ce_config = ath11k_host_ce_config_qcn9074, ++ .supports_regdb = true, + .ce_count = 6, + .target_ce_config = ath11k_target_ce_config_wlan_ipq5018, + .target_ce_count = 9, +@@ -844,6 +846,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { + .regs = &ipq8074_regs, + .qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ8074, + .host_ce_config = ath11k_host_ce_config_ipq9574, ++ .supports_regdb = true, + .ce_count = 10, + .target_ce_config = ath11k_target_ce_config_wlan_ipq9574, + .target_ce_count = 10, +@@ -1208,20 +1211,21 @@ int ath11k_core_check_dt(struct ath11k_base *ab) + return 0; + } + +-static int __ath11k_core_create_board_name(struct ath11k_base *ab, char *name, +- size_t name_len, bool with_variant) ++static int ath11k_core_create_board_name(struct ath11k_base *ab, char *name, ++ char *defaultname, size_t name_len) + { + /* strlen(',variant=') + strlen(ab->qmi.target.bdf_ext) */ + char variant[9 + ATH11K_QMI_BDF_EXT_STR_LENGTH] = { 0 }; + +- if (with_variant && ab->qmi.target.bdf_ext[0] != '\0') ++ if (ab->qmi.target.bdf_ext[0] != '\0') + scnprintf(variant, sizeof(variant), ",variant=%s", + ab->qmi.target.bdf_ext); + + switch (ab->id.bdf_search) { + case ATH11K_BDF_SEARCH_BUS_AND_BOARD: + scnprintf(name, name_len, +- "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x,qmi-chip-id=%d,qmi-board-id=%d%s", ++ "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x," ++ "subsystem-device=%04x,qmi-chip-id=%d,qmi-board-id=%d%s", + ath11k_bus_str(ab->hif.bus), + ab->id.vendor, ab->id.device, + ab->id.subsystem_vendor, +@@ -1236,6 +1240,12 @@ static int __ath11k_core_create_board_name(struct ath11k_base *ab, char *name, + ath11k_bus_str(ab->hif.bus), + ab->qmi.target.chip_id, + ab->qmi.target.board_id, variant); ++ ++ scnprintf(defaultname, name_len, ++ "bus=%s,qmi-chip-id=%d,qmi-board-id=%d%s", ++ ath11k_bus_str(ab->hif.bus), ++ ab->qmi.target.chip_id, ++ ATH11K_DEFAULT_ID, variant); + break; + } + +@@ -1244,18 +1254,6 @@ static int __ath11k_core_create_board_name(struct ath11k_base *ab, char *name, + return 0; + } + +-static int ath11k_core_create_board_name(struct ath11k_base *ab, char *name, +- size_t name_len) +-{ +- return __ath11k_core_create_board_name(ab, name, name_len, true); +-} +- +-static int ath11k_core_create_fallback_board_name(struct ath11k_base *ab, char *name, +- size_t name_len) +-{ +- return __ath11k_core_create_board_name(ab, name, name_len, false); +-} +- + const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab, + const char *file) + { +@@ -1457,6 +1455,7 @@ static int ath11k_core_fetch_board_data_api_n(struct ath11k_base *ab, + /* either found or error, so stop searching */ + goto out; + } ++ + next: + /* jump over the padding */ + ie_len = ALIGN(ie_len, 4); +@@ -1497,16 +1496,13 @@ int ath11k_core_fetch_board_data_api_1(struct ath11k_base *ab, + return 0; + } + +-#define BOARD_NAME_SIZE 200 + int ath11k_core_fetch_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd) + { + char boardname[BOARD_NAME_SIZE], fallback_boardname[BOARD_NAME_SIZE]; +- char *filename, filepath[100]; + int ret; + +- filename = ATH11K_BOARD_API2_FILE; +- +- ret = ath11k_core_create_board_name(ab, boardname, sizeof(boardname)); ++ ret = ath11k_core_create_board_name(ab, boardname, fallback_boardname, ++ BOARD_NAME_SIZE); + if (ret) { + ath11k_err(ab, "failed to create board name: %d", ret); + return ret; +@@ -1520,13 +1516,6 @@ int ath11k_core_fetch_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd) + if (!ret) + goto success; + +- ret = ath11k_core_create_fallback_board_name(ab, fallback_boardname, +- sizeof(fallback_boardname)); +- if (ret) { +- ath11k_err(ab, "failed to create fallback board name: %d", ret); +- return ret; +- } +- + ret = ath11k_core_fetch_board_data_api_n(ab, bd, fallback_boardname, + ATH11K_BD_IE_BOARD, + ATH11K_BD_IE_BOARD_NAME, +@@ -1537,16 +1526,13 @@ int ath11k_core_fetch_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd) + ab->bd_api = 1; + ret = ath11k_core_fetch_board_data_api_1(ab, bd, ATH11K_DEFAULT_BOARD_FILE); + if (ret) { +- ath11k_core_create_firmware_path(ab, filename, +- filepath, sizeof(filepath)); +- ath11k_err(ab, "failed to fetch board data for %s from %s\n", +- boardname, filepath); +- if (memcmp(boardname, fallback_boardname, strlen(boardname))) +- ath11k_err(ab, "failed to fetch board data for %s from %s\n", +- fallback_boardname, filepath); +- + ath11k_err(ab, "failed to fetch board.bin from %s\n", + ab->hw_params.fw.dir); ++ } else { ++ ret = ath11k_core_fetch_board_data_api_1(ab, bd, ATH11K_BOARD_API2_FILE); ++ if (ret) ++ ath11k_err(ab, "failed to fetch board-2.bin from %s\n", ++ ab->hw_params.fw.dir); + return ret; + } + +@@ -1557,33 +1543,43 @@ success: + + int ath11k_core_fetch_regdb(struct ath11k_base *ab, struct ath11k_board_data *bd) + { +- char boardname[BOARD_NAME_SIZE]; ++ char regdbname[REGDB_NAME_SIZE], fallback_regdbname[REGDB_NAME_SIZE]; + int ret; + +- ret = ath11k_core_create_board_name(ab, boardname, BOARD_NAME_SIZE); ++ ret = ath11k_core_create_board_name(ab, regdbname, fallback_regdbname, ++ REGDB_NAME_SIZE); + if (ret) { + ath11k_dbg(ab, ATH11K_DBG_BOOT, + "failed to create board name for regdb: %d", ret); +- goto exit; ++ return ret; + } + +- ret = ath11k_core_fetch_board_data_api_n(ab, bd, boardname, ++ ab->bd_api = 2; ++ ret = ath11k_core_fetch_board_data_api_n(ab, bd, regdbname, + ATH11K_BD_IE_REGDB, + ATH11K_BD_IE_REGDB_NAME, + ATH11K_BD_IE_REGDB_DATA); + if (!ret) +- goto exit; ++ goto success; + ++ ret = ath11k_core_fetch_board_data_api_n(ab, bd, fallback_regdbname, ++ ATH11K_BD_IE_REGDB, ++ ATH11K_BD_IE_REGDB_NAME, ++ ATH11K_BD_IE_REGDB_DATA); ++ if (!ret) ++ goto success; ++ ++ ab->bd_api = 1; + ret = ath11k_core_fetch_board_data_api_1(ab, bd, ATH11K_REGDB_FILE_NAME); +- if (ret) ++ if (ret) { + ath11k_dbg(ab, ATH11K_DBG_BOOT, "failed to fetch %s from %s\n", + ATH11K_REGDB_FILE_NAME, ab->hw_params.fw.dir); ++ return ret; ++ } + +-exit: +- if (!ret) +- ath11k_dbg(ab, ATH11K_DBG_BOOT, "fetched regdb\n"); +- +- return ret; ++success: ++ ath11k_dbg(ab, ATH11K_DBG_BOOT, "using board api %d\n", ab->bd_api); ++ return 0; + } + + static void ath11k_core_stop(struct ath11k_base *ab) +diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h +index 7fc20dd..9ce72c4 100644 +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -1089,6 +1089,9 @@ struct ath11k_pdev { + u8 mac_addr[ETH_ALEN]; + }; + ++#define BOARD_NAME_SIZE 100 ++#define REGDB_NAME_SIZE 100 ++ + struct ath11k_board_data { + const struct firmware *fw; + const void *data; +@@ -1591,7 +1594,8 @@ void ath11k_core_free(struct ath11k_base *ath11k); + int ath11k_core_fetch_bdf(struct ath11k_base *ath11k, + struct ath11k_board_data *bd); + int ath11k_config_qdss(struct ath11k_base *ab); +-int ath11k_core_fetch_regdb(struct ath11k_base *ab, struct ath11k_board_data *bd); ++int ath11k_core_fetch_regdb(struct ath11k_base *ab, ++ struct ath11k_board_data *bd); + int ath11k_core_fetch_board_data_api_1(struct ath11k_base *ab, + struct ath11k_board_data *bd, + const char *name); +diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/ath/ath11k/hw.h +index daa6cfb..b995f4b 100644 +--- a/drivers/net/wireless/ath/ath11k/hw.h ++++ b/drivers/net/wireless/ath/ath11k/hw.h +@@ -107,6 +107,8 @@ struct ath11k_cfr_peer_tx_param; + #define ATH11K_AMSS_FILE "amss.bin" + #define ATH11K_M3_FILE "m3.bin" + #define ATH11K_REGDB_FILE_NAME "regdb.bin" ++#define ATH11K_REGDB_BINARY "regdb" ++#define ATH11K_DEFAULT_ID 255 + #define NODE_ID_BASE 0x27 + + enum ath11k_hw_rate_cck { +diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c +index 05d5f9d..5509d00 100644 +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -1413,6 +1413,24 @@ static struct qmi_elem_info qmi_wlanfw_cap_resp_msg_v01_ei[] = { + .offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01, + eeprom_read_timeout), + }, ++ { ++ .data_type = QMI_OPT_FLAG, ++ .elem_len = 1, ++ .elem_size = sizeof(u8), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x24, ++ .offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01, ++ regdb_support_valid), ++ }, ++ { ++ .data_type = QMI_UNSIGNED_1_BYTE, ++ .elem_len = 1, ++ .elem_size = sizeof(u8), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x24, ++ .offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01, ++ regdb_support), ++ }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, +@@ -3190,6 +3208,11 @@ static int ath11k_qmi_request_target_cap(struct ath11k_base *ab) + ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi cal data supported from eeprom\n"); + } + ++ if (resp.regdb_support_valid) { ++ ab->qmi.target.regdb = resp.regdb_support; ++ ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi regdb download is supported\n"); ++ } ++ + fw_build_id = ab->qmi.target.fw_build_id; + fw_build_id_mask_len = strlen(FW_BUILD_ID_MASK); + if (!strncmp(fw_build_id, FW_BUILD_ID_MASK, fw_build_id_mask_len)) +@@ -3233,7 +3256,7 @@ static int ath11k_qmi_load_file_target_mem(struct ath11k_base *ab, + + memset(&resp, 0, sizeof(resp)); + +- if (ab->hw_params.fixed_bdf_addr) { ++ if (ab->hw_params.fixed_bdf_addr && !ab->qmi.target.regdb) { + bdf_addr = ioremap(ab->hw_params.bdf_addr, ab->hw_params.fw.board_size); + if (!bdf_addr) { + ath11k_warn(ab, "qmi ioremap error for bdf_addr\n"); +@@ -3262,7 +3285,7 @@ static int ath11k_qmi_load_file_target_mem(struct ath11k_base *ab, + req->end = 1; + } + +- if (ab->hw_params.fixed_bdf_addr || ++ if ((ab->hw_params.fixed_bdf_addr && !ab->qmi.target.regdb) || + type == ATH11K_QMI_FILE_TYPE_EEPROM) { + req->data_valid = 0; + req->end = 1; +@@ -3271,7 +3294,7 @@ static int ath11k_qmi_load_file_target_mem(struct ath11k_base *ab, + memcpy(req->data, temp, req->data_len); + } + +- if (ab->hw_params.fixed_bdf_addr) { ++ if (ab->hw_params.fixed_bdf_addr && !ab->qmi.target.regdb) { + if (type == ATH11K_QMI_FILE_TYPE_CALDATA) + bdf_addr += ab->hw_params.fw.cal_offset; + +@@ -3310,7 +3333,7 @@ static int ath11k_qmi_load_file_target_mem(struct ath11k_base *ab, + goto err_iounmap; + } + +- if (ab->hw_params.fixed_bdf_addr || ++ if ((ab->hw_params.fixed_bdf_addr && !ab->qmi.target.regdb) || + type == ATH11K_QMI_FILE_TYPE_EEPROM) { + remaining = 0; + } else { +@@ -3323,7 +3346,7 @@ static int ath11k_qmi_load_file_target_mem(struct ath11k_base *ab, + } + + err_iounmap: +- if (ab->hw_params.fixed_bdf_addr) ++ if (ab->hw_params.fixed_bdf_addr && !ab->qmi.target.regdb) + iounmap(bdf_addr); + + err_free_req: +@@ -3369,22 +3392,23 @@ static int ath11k_qmi_load_bdf_qmi(struct ath11k_base *ab, + + if (regdb) { + ret = ath11k_core_fetch_regdb(ab, &bd); ++ if (ret) { ++ ath11k_warn(ab, "qmi failed to fetch regdb file: %d\n", ret); ++ goto out; ++ } ++ bdf_type = ATH11K_QMI_BDF_TYPE_REGDB; + } else { + ret = ath11k_core_fetch_bdf(ab, &bd); +- if (ret) ++ if (ret) { + ath11k_warn(ab, "qmi failed to fetch board file: %d\n", ret); ++ goto out; ++ } ++ if (bd.len >= SELFMAG && memcmp(bd.data, ELFMAG, SELFMAG) == 0) ++ bdf_type = ATH11K_QMI_BDF_TYPE_ELF; ++ else ++ bdf_type = ATH11K_QMI_BDF_TYPE_BIN; + } + +- if (ret) +- goto out; +- +- if (regdb) +- bdf_type = ATH11K_QMI_BDF_TYPE_REGDB; +- else if (bd.len >= SELFMAG && memcmp(bd.data, ELFMAG, SELFMAG) == 0) +- bdf_type = ATH11K_QMI_BDF_TYPE_ELF; +- else +- bdf_type = ATH11K_QMI_BDF_TYPE_BIN; +- + ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi bdf_type %d\n", bdf_type); + + fw_size = min_t(u32, ab->hw_params.fw.board_size, bd.len); +diff --git a/drivers/net/wireless/ath/ath11k/qmi.h b/drivers/net/wireless/ath/ath11k/qmi.h +index ec72214..6855b67 100644 +--- a/drivers/net/wireless/ath/ath11k/qmi.h ++++ b/drivers/net/wireless/ath/ath11k/qmi.h +@@ -180,6 +180,7 @@ struct target_info { + u32 soc_id; + u32 fw_version; + u32 eeprom_caldata; ++ u8 regdb; + char fw_build_timestamp[ATH11K_QMI_WLANFW_MAX_TIMESTAMP_LEN_V01 + 1]; + char fw_build_id[ATH11K_QMI_WLANFW_MAX_BUILD_ID_LEN_V01 + 1]; + char bdf_ext[ATH11K_QMI_BDF_EXT_STR_LENGTH]; +@@ -577,6 +578,8 @@ struct qmi_wlanfw_cap_resp_msg_v01 { + u32 otp_version; + u8 eeprom_read_timeout_valid; + u32 eeprom_read_timeout; ++ u8 regdb_support_valid; ++ u8 regdb_support; + }; + + struct qmi_wlanfw_cap_req_msg_v01 { +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/365-01-ath11k-Add-support-for-ADFS.patch b/feeds/ipq95xx/mac80211/patches/qca/365-01-ath11k-Add-support-for-ADFS.patch new file mode 100644 index 000000000..c86aff554 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/365-01-ath11k-Add-support-for-ADFS.patch @@ -0,0 +1,717 @@ +From cae92de241180ae14eccbe18e7f76c48af64e003 Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Wed, 19 Oct 2022 23:56:08 +0530 +Subject: [PATCH 3/4] ath11k: Add support for ADFS + +The following changes are added to support background DFS +feature: + 1. add support for ADFS WMI command + 2. handle ADFS complete event from Firmware + 3. parse the firmware phy mac capabilties to + infer which chainmask supports ADFS + 4. During channel change abort ongoing CAC + 5. handle radar on agile detector + +Signed-off-by: Harshitha Prem +--- + drivers/net/wireless/ath/ath11k/core.h | 1 + + drivers/net/wireless/ath/ath11k/mac.c | 60 +++++++++++ + drivers/net/wireless/ath/ath11k/mac.h | 1 + + drivers/net/wireless/ath/ath11k/wmi.c | 142 +++++++++++++++++++++++++ + drivers/net/wireless/ath/ath11k/wmi.h | 64 +++++++++++ + 5 files changed, 268 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -1059,6 +1059,7 @@ struct ath11k { + u8 twt_enabled; + bool nlo_enabled; + u8 alpha2[REG_ALPHA2_LEN + 1]; ++ struct cfg80211_chan_def agile_chandef; + }; + + struct ath11k_band_cap { +@@ -1082,6 +1083,7 @@ struct ath11k_pdev_cap { + u32 rx_chain_mask; + u32 tx_chain_mask_shift; + u32 rx_chain_mask_shift; ++ u32 adfs_chain_mask; + struct ath11k_band_cap band[NUM_NL80211_BANDS]; + bool nss_ratio_enabled; + u8 nss_ratio_info; +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -8826,6 +8826,28 @@ ath11k_mac_vdev_start_restart(struct ath + if (ret) + ath11k_warn(ab, "failed to set 6G non-ht dup conf for vdev %d: %d\n", + arvif->vdev_id, ret); ++ ++ /* In case of ADFS, we have to abort ongoing backgrorund CAC */ ++ ++ if ((ar->pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP) && ++ test_bit(ar->cfg_rx_chainmask, &ar->pdev->cap.adfs_chain_mask) && ++ ar->agile_chandef.chan) { ++ ++ ath11k_dbg(ab, ATH11K_DBG_MAC, ++ "Aborting ongoing Agile DFS on freq %d", ++ ar->agile_chandef.chan->center_freq); ++ ++ ret = ath11k_wmi_vdev_adfs_ocac_abort_cmd_send(ar,arvif->vdev_id); ++ if (!ret) { ++ memset(&ar->agile_chandef, 0, sizeof(struct cfg80211_chan_def)); ++ ar->agile_chandef.chan = NULL; ++ ath11k_mac_background_dfs_event(ar, ATH11K_BGDFS_ABORT); ++ } else { ++ ath11k_warn(ab, "failed to abort agile CAC for vdev %d", ++ arvif->vdev_id); ++ } ++ } ++ + return 0; + } + +@@ -12046,6 +12068,80 @@ err_unlock: + return 0; + } + ++ ++static int ath11k_mac_op_set_radar_background(struct ieee80211_hw *hw, ++ struct cfg80211_chan_def *def) ++{ ++ struct ath11k *ar = hw->priv; ++ struct ath11k_vif *arvif; ++ bool arvif_found = false; ++ int ret; ++ struct ieee80211_chanctx_conf *conf; ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ if (ar->ab->dfs_region == ATH11K_DFS_REG_UNSET) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ if (!test_bit(ar->cfg_rx_chainmask, &ar->pdev->cap.adfs_chain_mask)) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ list_for_each_entry(arvif, &ar->arvifs, list) { ++ if (arvif->is_started && ++ arvif->vdev_type == WMI_VDEV_TYPE_AP) { ++ arvif_found = true; ++ break; ++ } ++ } ++ ++ if (!arvif_found) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ if (!def) { ++ ret = ath11k_wmi_vdev_adfs_ocac_abort_cmd_send(ar,arvif->vdev_id); ++ if (!ret) { ++ memset(&ar->agile_chandef, 0, ++ sizeof(struct cfg80211_chan_def)); ++ ar->agile_chandef.chan = NULL; ++ } ++ } else { ++ if (!cfg80211_chandef_valid(def) || ++ !(def->chan->flags & IEEE80211_CHAN_RADAR)) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ /* Note: currently, half and quater bandwidth agile DFS is not ++ supported */ ++ conf = rcu_dereference(arvif->vif->bss_conf.chanctx_conf); ++ if (conf && conf->def.width != def->width) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ret = ath11k_wmi_vdev_adfs_ch_cfg_cmd_send(ar, arvif->vdev_id, def); ++ if (!ret) { ++ memcpy(&ar->agile_chandef, def, ++ sizeof(struct cfg80211_chan_def)); ++ } else { ++ ath11k_warn(ar->ab, "Failed to start agile CAC"); ++ memset(&ar->agile_chandef, 0, ++ sizeof(struct cfg80211_chan_def)); ++ ar->agile_chandef.chan = NULL; ++ } ++ } ++ ++exit: ++ mutex_unlock(&ar->conf_mutex); ++ return ret; ++} ++ ++ + static const struct ieee80211_ops ath11k_ops = { + .tx = ath11k_mac_op_tx, + .start = ath11k_mac_op_start, +@@ -12108,6 +12204,7 @@ static const struct ieee80211_ops ath11k + .config_mesh_offload_path = ath11k_mac_op_config_mesh_offload_path, + #endif + .get_txpower = ath11k_mac_op_get_txpower, ++ .set_radar_background = ath11k_mac_op_set_radar_background, + }; + + static void ath11k_mac_update_ch_list(struct ath11k *ar, +@@ -12692,6 +12789,11 @@ static int __ath11k_mac_register(struct + wiphy_ext_feature_set(ar->hw->wiphy, + NL80211_EXT_FEATURE_WIDE_BAND_SCAN); + ++ if ((cap->supported_bands & WMI_HOST_WLAN_5G_CAP) && ++ test_bit(ar->cfg_rx_chainmask, &cap->adfs_chain_mask)) ++ wiphy_ext_feature_set(ar->hw->wiphy, ++ NL80211_EXT_FEATURE_RADAR_BACKGROUND); ++ + ar->hw->wiphy->cipher_suites = cipher_suites; + ar->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); + +@@ -12988,3 +13090,40 @@ int ath11k_mac_vif_set_keepalive(struct + + return 0; + } ++ ++void ath11k_mac_background_dfs_event(struct ath11k *ar, ++ enum ath11k_background_dfs_events ev) ++{ ++ struct ath11k_vif *arvif; ++ bool arvif_found = false; ++ int ret = 0; ++ ++ list_for_each_entry(arvif, &ar->arvifs, list) { ++ if (arvif->is_started && ++ arvif->vdev_type == WMI_VDEV_TYPE_AP) { ++ arvif_found = true; ++ break; ++ } ++ } ++ ++ if (!arvif_found) ++ return; ++ ++ if (ev == ATH11K_BGDFS_RADAR) { ++ cfg80211_background_radar_event(ar->hw->wiphy, &ar->agile_chandef, GFP_ATOMIC); ++ lockdep_assert_held(&ar->conf_mutex); ++ ret = ath11k_wmi_vdev_adfs_ocac_abort_cmd_send(ar,arvif->vdev_id); ++ } else if (ev == ATH11K_BGDFS_ABORT) { ++ cfg80211_background_cac_abort(ar->hw->wiphy); ++ } ++ ++ if (!ret) { ++ memset(&ar->agile_chandef, 0, sizeof(struct cfg80211_chan_def)); ++ ar->agile_chandef.chan = NULL; ++ } else { ++ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, ++ "ADFS state can't be reset (ret=%d)\n", ++ ret); ++ } ++} ++ +--- a/drivers/net/wireless/ath/ath11k/mac.h ++++ b/drivers/net/wireless/ath/ath11k/mac.h +@@ -131,6 +131,12 @@ extern const struct htt_rx_ring_tlv_filt + #define ATH11K_SCAN_11D_INTERVAL 600000 + #define ATH11K_11D_INVALID_VDEV_ID 0xFFFF + ++enum ath11k_background_dfs_events { ++ ATH11K_BGDFS_SUCCESS, ++ ATH11K_BGDFS_ABORT, ++ ATH11K_BGDFS_RADAR, ++}; ++ + void ath11k_mac_11d_scan_start(struct ath11k *ar, u32 vdev_id); + void ath11k_mac_11d_scan_stop(struct ath11k *ar); + void ath11k_mac_11d_scan_stop_all(struct ath11k_base *ab); +@@ -186,4 +192,5 @@ void ath11k_mac_get_any_chandef_iter(str + struct ieee80211_chanctx_conf *conf, + void *data); + void ath11k_mac_debugfs_remove_stats_file(struct ath11k_vif *arvif); ++void ath11k_mac_background_dfs_event(struct ath11k *ar, enum ath11k_background_dfs_events ev); + #endif +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -50,6 +50,7 @@ struct wmi_tlv_svc_rdy_ext_parse { + bool hw_mode_done; + bool mac_phy_done; + bool ext_hal_reg_done; ++ u32 n_mac_phy_chainmask_combo; + bool mac_phy_chainmask_combo_done; + bool mac_phy_chainmask_cap_done; + bool oem_dma_ring_cap_done; +@@ -176,6 +177,36 @@ static const int ath11k_hw_mode_pri_map[ + PRIMAP(WMI_HOST_HW_MODE_MAX), + }; + ++enum wmi_host_channel_width ++ath11k_wmi_get_host_chan_width(u32 width) ++{ ++ enum wmi_host_channel_width host_width; ++ ++ switch (width) { ++ case NL80211_CHAN_WIDTH_20_NOHT: ++ case NL80211_CHAN_WIDTH_20: ++ host_width = WMI_HOST_CHAN_WIDTH_20; ++ break; ++ case NL80211_CHAN_WIDTH_40: ++ host_width = WMI_HOST_CHAN_WIDTH_40; ++ break; ++ case NL80211_CHAN_WIDTH_80: ++ host_width = WMI_HOST_CHAN_WIDTH_80; ++ break; ++ case NL80211_CHAN_WIDTH_160: ++ host_width = WMI_HOST_CHAN_WIDTH_160; ++ break; ++ case NL80211_CHAN_WIDTH_80P80: ++ host_width = WMI_HOST_CHAN_WIDTH_80P80; ++ break; ++ default: ++ host_width = WMI_HOST_CHAN_WIDTH_MAX; ++ break; ++ } ++ ++ return host_width; ++} ++ + static int + ath11k_wmi_tlv_iter(struct ath11k_base *ab, const void *ptr, size_t len, + int (*iter)(struct ath11k_base *ab, u16 tag, u16 len, +@@ -5458,6 +5489,91 @@ free_dir_buff: + return ret; + } + ++static int ath11k_wmi_tlv_mac_phy_chainmask_caps(struct ath11k_base *soc, ++ u16 len, const void *ptr, void *data) ++{ ++ struct wmi_tlv_svc_rdy_ext_parse *svc_rdy_ext = data; ++ struct wmi_mac_phy_chainmask_caps *cmask_caps = (struct wmi_mac_phy_chainmask_caps *)ptr; ++ struct ath11k_chainmask_table *cmask_table; ++ struct ath11k_pdev_cap *pdev_cap; ++ u32 tag; ++ int i, j; ++ ++ if (!svc_rdy_ext->hw_mode_caps) ++ return -EINVAL; ++ ++ if ((!svc_rdy_ext->param.num_chainmask_tables) || ++ (svc_rdy_ext->param.num_chainmask_tables > ATH11K_MAX_CHAINMASK_TABLES)) ++ return -EINVAL; ++ ++ for (i = 0; i < svc_rdy_ext->param.num_chainmask_tables; i++) { ++ cmask_table = &svc_rdy_ext->param.chainmask_table[i]; ++ ++ for (j = 0; j < cmask_table->num_valid_chainmasks; j++) { ++ tag = FIELD_GET(WMI_TLV_TAG, cmask_caps->tlv_header); ++ ++ if (tag != WMI_TAG_MAC_PHY_CHAINMASK_CAPABILITY) ++ return -EPROTO; ++ ++ cmask_table->cap_list[j].chainmask = cmask_caps->chainmask; ++ cmask_table->cap_list[j].supported_caps = cmask_caps->supported_flags; ++ cmask_caps++; ++ } ++ } ++ for (i = 0; i < svc_rdy_ext->tot_phy_id; i++) { ++ pdev_cap = &soc->pdevs[i].cap; ++ cmask_table = &svc_rdy_ext->param.chainmask_table[i]; ++ for (j = 0; j < cmask_table->num_valid_chainmasks; j++) { ++ if (cmask_table->cap_list[j].supported_caps & WMI_SUPPORT_CHAIN_MASK_ADFS) ++ pdev_cap->adfs_chain_mask |= (1 << cmask_table->cap_list[j].chainmask); ++ } ++ } ++ return 0; ++} ++ ++static void ath11k_wmi_free_chainmask_caps(struct wmi_tlv_svc_rdy_ext_parse *svc_rdy_ext) ++{ ++ int i; ++ ++ if (!svc_rdy_ext->param.num_chainmask_tables) ++ return; ++ ++ for (i = 0; i < svc_rdy_ext->param.num_chainmask_tables; i++) { ++ if (!svc_rdy_ext->param.chainmask_table[i].cap_list) ++ continue; ++ kfree(svc_rdy_ext->param.chainmask_table[i].cap_list); ++ svc_rdy_ext->param.chainmask_table[i].cap_list = NULL; ++ } ++} ++ ++static int ath11k_wmi_tlv_mac_phy_chainmask_combo_parse(struct ath11k_base *soc, ++ u16 tag, u16 len, ++ const void *ptr, void *data) ++{ ++ struct wmi_tlv_svc_rdy_ext_parse *svc_rdy_ext = data; ++ struct wmi_mac_phy_chainmask_combo *cmask_combo = (struct wmi_mac_phy_chainmask_combo *)ptr; ++ u32 i = svc_rdy_ext->n_mac_phy_chainmask_combo; ++ struct ath11k_chainmask_table *cmask_table; ++ ++ if (tag != WMI_TAG_MAC_PHY_CHAINMASK_COMBO) ++ return -EPROTO; ++ ++ if (svc_rdy_ext->n_mac_phy_chainmask_combo >= svc_rdy_ext->param.num_chainmask_tables) ++ return -ENOBUFS; ++ ++ cmask_table = &svc_rdy_ext->param.chainmask_table[i]; ++ cmask_table->table_id = cmask_combo->chainmask_table_id; ++ cmask_table->num_valid_chainmasks = cmask_combo->num_valid_chainmask; ++ cmask_table->cap_list = kcalloc(cmask_combo->num_valid_chainmask, ++ sizeof(struct ath11k_chainmask_capabilities), ++ GFP_ATOMIC); ++ if (!cmask_table->cap_list) ++ return -ENOMEM; ++ ++ svc_rdy_ext->n_mac_phy_chainmask_combo++; ++ return 0; ++} ++ + static int ath11k_wmi_tlv_svc_rdy_ext_parse(struct ath11k_base *ab, + u16 tag, u16 len, + const void *ptr, void *data) +@@ -5479,6 +5595,7 @@ static int ath11k_wmi_tlv_svc_rdy_ext_pa + case WMI_TAG_SOC_MAC_PHY_HW_MODE_CAPS: + svc_rdy_ext->hw_caps = (struct wmi_soc_mac_phy_hw_mode_caps *)ptr; + svc_rdy_ext->param.num_hw_modes = svc_rdy_ext->hw_caps->num_hw_modes; ++ svc_rdy_ext->param.num_chainmask_tables = svc_rdy_ext->hw_caps->num_chainmask_tables; + break; + + case WMI_TAG_SOC_HAL_REG_CAPABILITIES: +@@ -5515,8 +5632,21 @@ static int ath11k_wmi_tlv_svc_rdy_ext_pa + + svc_rdy_ext->ext_hal_reg_done = true; + } else if (!svc_rdy_ext->mac_phy_chainmask_combo_done) { ++ svc_rdy_ext->n_mac_phy_chainmask_combo = 0; ++ ret = ath11k_wmi_tlv_iter(ab, ptr, len, ++ ath11k_wmi_tlv_mac_phy_chainmask_combo_parse, ++ svc_rdy_ext); ++ if (ret) { ++ ath11k_warn(ab, "failed to parse chainmask combo tlv %d\n", ret); ++ return ret; ++ } + svc_rdy_ext->mac_phy_chainmask_combo_done = true; + } else if (!svc_rdy_ext->mac_phy_chainmask_cap_done) { ++ ret = ath11k_wmi_tlv_mac_phy_chainmask_caps(ab, len, ptr, svc_rdy_ext); ++ if (ret) { ++ ath11k_warn(ab, "failed to parse chainmask caps tlv %d\n", ret); ++ return ret; ++ } + svc_rdy_ext->mac_phy_chainmask_cap_done = true; + } else if (!svc_rdy_ext->oem_dma_ring_cap_done) { + svc_rdy_ext->oem_dma_ring_cap_done = true; +@@ -5554,6 +5684,7 @@ static int ath11k_service_ready_ext_even + complete(&ab->wmi_ab.service_ready); + + kfree(svc_rdy_ext.mac_phy_caps); ++ ath11k_wmi_free_chainmask_caps(&svc_rdy_ext); + return 0; + + err: +@@ -9413,6 +9544,8 @@ ath11k_wmi_pdev_dfs_radar_detected_event + + if (ar->dfs_block_radar_events) + ath11k_info(ab, "DFS Radar detected, but ignored as requested\n"); ++ else if (ev->detector_id == 1) ++ ath11k_mac_background_dfs_event(ar, ATH11K_BGDFS_RADAR); + else + ieee80211_radar_detected(ar->hw); + +@@ -10946,6 +11079,56 @@ static void ath11k_wmi_event_peer_rateco + return; + } + ++static void ath11k_process_ocac_complete_event(struct ath11k_base *ab, ++ struct sk_buff *skb) ++{ ++ const void **tb; ++ const struct wmi_vdev_adfs_ocac_complete_event_fixed_param *ev; ++ struct ath11k *ar; ++ int ret; ++ ++ tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); ++ if (IS_ERR(tb)) { ++ ret = PTR_ERR(tb); ++ ath11k_warn(ab, "failed to parse tlv: %d\n", ret); ++ return; ++ } ++ ++ ev = tb[WMI_TAG_VDEV_ADFS_OCAC_COMPLETE_EVENT]; ++ ++ if (!ev) { ++ ath11k_warn(ab, "failed to fetch ocac completed ev"); ++ goto exit; ++ } ++ ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "pdev dfs ocac complete event on vdev %d, " ++ "chan freq %d, chan_width %d, status %d " ++ "freq %d, freq1 %d, freq2 %d ", ++ ev->vdev_id, ev->chan_freq, ev->chan_width, ++ ev->status, ev->center_freq, ev->center_freq1, ++ ev->center_freq2); ++ ++ ar = ath11k_mac_get_ar_by_vdev_id(ab, ev->vdev_id); ++ ++ if (!ar) { ++ ath11k_warn(ab, "OCAC complete event in invalid vdev %d\n", ++ ev->vdev_id); ++ goto exit; ++ } ++ ++ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "aDFS ocac complete event in vdev %d\n", ++ ev->vdev_id); ++ if (ev->status) { ++ ath11k_mac_background_dfs_event(ar, ATH11K_BGDFS_ABORT); ++ } else { ++ memset(&ar->agile_chandef, 0, sizeof(struct cfg80211_chan_def)); ++ ar->agile_chandef.chan = NULL; ++ } ++exit: ++ kfree(tb); ++} ++ + static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb) + { + struct wmi_cmd_hdr *cmd_hdr; +@@ -11121,6 +11304,9 @@ static void ath11k_wmi_tlv_op_rx(struct + case WMI_PEER_RATECODE_LIST_EVENTID: + ath11k_wmi_event_peer_ratecode_list(ab, skb); + break; ++ case WMI_VDEV_ADFS_OCAC_COMPLETE_EVENTID: ++ ath11k_process_ocac_complete_event(ab, skb); ++ break; + /* TODO: Add remaining events */ + default: + ath11k_dbg(ab, ATH11K_DBG_WMI, "Unknown eventid: 0x%x\n", id); +@@ -12596,3 +12782,100 @@ ath11k_wmi_pdev_enable_smart_ant(struct + kfree(params); + return ret; + } ++ ++ ++int ath11k_wmi_vdev_adfs_ch_cfg_cmd_send(struct ath11k *ar, u32 vdev_id, struct cfg80211_chan_def *def) ++{ ++ ++ struct ath11k_pdev_wmi *wmi = ar->wmi; ++ struct wmi_vdev_adfs_ch_cfg_cmd *cmd; ++ struct sk_buff *skb; ++ int ret = 0; ++ ++ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd)); ++ if (!skb) ++ return -ENOMEM; ++ ++ cmd = (struct wmi_vdev_adfs_ch_cfg_cmd *)skb->data; ++ cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_VDEV_ADFS_CH_CFG_CMD) | ++ FIELD_PREP(WMI_TLV_LEN, ++ sizeof(struct wmi_vdev_adfs_ch_cfg_cmd) - TLV_HDR_SIZE); ++ cmd->vdev_id = vdev_id; ++ ++ if (ar->ab->dfs_region == ATH11K_DFS_REG_ETSI) { ++ cmd->ocac_mode = WMI_ADFS_MODE_QUICK_OCAC; ++ ++ /* For ETSI, Agile CAC minimum time = 6 * CAC time */ ++ cmd->min_duration_ms = 6 * def->chan->dfs_cac_ms; ++ if (def->chan->dfs_cac_ms != IEEE80211_DFS_MIN_CAC_TIME_MS) ++ cmd->max_duration_ms = MAX_WEATHER_RADAR_CHAN_PRECAC_TIMEOUT; ++ else ++ cmd->max_duration_ms = MAX_PRECAC_TIMEOUT; ++ ++ } else if (ar->ab->dfs_region == ATH11K_DFS_REG_FCC) { ++ cmd->ocac_mode = WMI_ADFS_MODE_QUICK_RCAC; ++ cmd->min_duration_ms = MIN_RCAC_TIMEOUT; ++ cmd->max_duration_ms = MAX_RCAC_TIMEOUT; ++ } ++ ++ cmd->chan_freq = def->chan->center_freq; ++ cmd->chan_width = ath11k_wmi_get_host_chan_width(def->width); ++ cmd->center_freq1 = def->center_freq1; ++ cmd->center_freq2 = def->center_freq2; ++ ++ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, ++ "Send adfs channel cfg command for vdev id %d " ++ "mode as %d min duration %d chan_freq %d chan_width %d\n" ++ "center_freq1 %d center_freq2 %d", cmd->vdev_id, ++ cmd->ocac_mode, cmd->min_duration_ms, cmd->chan_freq, ++ cmd->chan_width, cmd->center_freq1, cmd->center_freq2); ++ ++ ret = ath11k_wmi_cmd_send(wmi, skb, WMI_VDEV_ADFS_CH_CFG_CMDID); ++ if (ret) { ++ ath11k_warn(ar->ab, ++ "failed to send WMI_VDEV_ADFS_CH_CFG_CMDID\n"); ++ dev_kfree_skb(skb); ++ } ++ ++ return ret; ++} ++ ++int ath11k_wmi_vdev_adfs_ocac_abort_cmd_send(struct ath11k *ar, u32 vdev_id) ++{ ++ struct ath11k_pdev_wmi *wmi = ar->wmi; ++ struct wmi_vdev_adfs_ocac_abort_cmd *cmd; ++ struct sk_buff *skb; ++ int ret = 0; ++ ++ if (!ar->agile_chandef.chan) { ++ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, ++ "Currently, agile CAC is not active on any channel." ++ "ignore abort"); ++ return ret; ++ } ++ ++ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd)); ++ if (!skb) ++ return -ENOMEM; ++ ++ cmd = (struct wmi_vdev_adfs_ocac_abort_cmd *)skb->data; ++ cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_VDEV_ADFS_OCAC_ABORT_CMD) | ++ FIELD_PREP(WMI_TLV_LEN, ++ sizeof(struct wmi_vdev_adfs_ocac_abort_cmd) - TLV_HDR_SIZE); ++ ++ cmd->vdev_id = vdev_id; ++ ret = ath11k_wmi_cmd_send(wmi, skb, WMI_VDEV_ADFS_OCAC_ABORT_CMDID); ++ ++ if (ret) { ++ ath11k_warn(ar->ab, ++ "failed to send WMI_VDEV_ADFS_CH_CFG_CMDID\n"); ++ dev_kfree_skb(skb); ++ return ret; ++ } ++ ++ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, ++ "Sent ADFS abort command to vdev %d", vdev_id); ++ ++ return ret; ++} ++ +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -2362,6 +2362,19 @@ struct ath11k_ppe_threshold { + u32 ppet16_ppet8_ru3_ru0[PSOC_HOST_MAX_NUM_SS]; + }; + ++struct ath11k_chainmask_capabilities { ++ u32 supported_caps; ++ u32 chainmask; ++}; ++ ++struct ath11k_chainmask_table { ++ u32 table_id; ++ u32 num_valid_chainmasks; ++ struct ath11k_chainmask_capabilities *cap_list; ++}; ++ ++#define ATH11K_MAX_CHAINMASK_TABLES 5 ++ + struct ath11k_service_ext_param { + u32 default_conc_scan_config_bits; + u32 default_fw_config_bits; +@@ -2371,6 +2384,9 @@ struct ath11k_service_ext_param { + u32 max_bssid_rx_filters; + u32 num_hw_modes; + u32 num_phy; ++ u32 num_chainmask_tables; ++ struct ath11k_chainmask_table ++ chainmask_table[ATH11K_MAX_CHAINMASK_TABLES]; + }; + + struct ath11k_hw_mode_caps { +@@ -2610,6 +2626,17 @@ struct wmi_hw_mode_capabilities { + u32 hw_mode_config_type; + } __packed; + ++struct wmi_mac_phy_chainmask_combo { ++ u32 chainmask_table_id; ++ u32 num_valid_chainmask; ++} __packed; ++ ++struct wmi_mac_phy_chainmask_caps { ++ u32 tlv_header; ++ u32 supported_flags; ++ u32 chainmask; ++} __packed; ++ + #define WMI_MAX_HECAP_PHY_SIZE (3) + #define WMI_NSS_RATIO_ENABLE_DISABLE_BITPOS BIT(0) + #define WMI_NSS_RATIO_ENABLE_DISABLE_GET(_val) \ +@@ -5110,6 +5137,9 @@ enum wmi_host_channel_width { + WMI_HOST_CHAN_WIDTH_80 = 2, + WMI_HOST_CHAN_WIDTH_160 = 3, + WMI_HOST_CHAN_WIDTH_80P80 = 4, ++ ++ /* keep last */ ++ WMI_HOST_CHAN_WIDTH_MAX = 0xF, + }; + + enum wmi_dcs_interference_chan_segment { +@@ -7407,6 +7437,60 @@ struct wmi_peer_set_smart_ant_node_confi + u32 args_count; + } __packed; + ++ ++ ++#define WMI_ADFS_MODE_QUICK_OCAC 0 /* Agile preCAC */ ++#define WMI_ADFS_MODE_QUICK_RCAC 2 /* Agile Rolling CAC */ ++#define WMI_SUPPORT_CHAIN_MASK_ADFS BIT(31) ++ ++#define MIN_PRECAC_TIMEOUT (6 * 60 * 1000) /* 6 minutes */ ++#define MIN_WEATHER_RADAR_CHAN_PRECAC_TIMEOUT (6 * 10 * 60 * 1000) /* 1 hour */ ++#define MAX_PRECAC_TIMEOUT (4 * 60 * 60 * 1000) /* 4 hours */ ++#define MAX_WEATHER_RADAR_CHAN_PRECAC_TIMEOUT (24 * 60 * 60 * 1000) /* 24 hours */ ++#define MIN_RCAC_TIMEOUT (62 * 1000) /* 62 seconds */ ++#define MAX_RCAC_TIMEOUT 0xffffffff ++ ++struct wmi_vdev_adfs_ch_cfg_cmd { ++ u32 tlv_header; ++ u32 vdev_id; ++ u32 ocac_mode; ++ u32 min_duration_ms; ++ u32 max_duration_ms; ++ u32 chan_freq; ++ u32 chan_width; ++ /* ++ * Two center frequencies are required since agile channel switch ++ * has to support 160/165 MHz for products like Pine. ++ * For agile which supports only up to 80MHz (HK), ++ * freq2 will be 0 and ignored. ++ */ ++ union { ++ u32 center_freq; ++ u32 center_freq1; ++ }; ++ u32 center_freq2; ++} __packed; ++ ++struct wmi_vdev_adfs_ocac_abort_cmd { ++ u32 tlv_header; ++ u32 vdev_id; ++} __packed; ++ ++#define WMI_DFS_RADAR_DETECTED_IN_SERVICE_CHAN 0 ++#define WMI_DFS_RADAR_DETECTED_IN_OCAC_CHAN 1 ++ ++struct wmi_vdev_adfs_ocac_complete_event_fixed_param { ++ u32 vdev_id; ++ u32 chan_freq; ++ u32 chan_width; ++ union { ++ u32 center_freq; ++ u32 center_freq1; ++ }; ++ u32 status; ++ u32 center_freq2; ++} __packed; ++ + int ath11k_wmi_cmd_send(struct ath11k_pdev_wmi *wmi, struct sk_buff *skb, + u32 cmd_id); + struct sk_buff *ath11k_wmi_alloc_skb(struct ath11k_wmi_base *wmi_sc, u32 len); +@@ -7635,4 +7719,6 @@ ath11k_wmi_peer_set_smart_ant_train_ant_ + int ath11k_wmi_send_vdev_set_tpc_power(struct ath11k *ar, + u32 vdev_id, + struct ath11k_reg_tpc_power_info *param); ++int ath11k_wmi_vdev_adfs_ch_cfg_cmd_send(struct ath11k *ar,u32 vdev_id, struct cfg80211_chan_def *chandef); ++int ath11k_wmi_vdev_adfs_ocac_abort_cmd_send(struct ath11k *ar,u32 vdev_id); + #endif diff --git a/feeds/ipq95xx/mac80211/patches/qca/365-02-ath11k-add-support-for-ADFS-radar.patch b/feeds/ipq95xx/mac80211/patches/qca/365-02-ath11k-add-support-for-ADFS-radar.patch new file mode 100644 index 000000000..323631a6a --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/365-02-ath11k-add-support-for-ADFS-radar.patch @@ -0,0 +1,147 @@ +From 03102d956de466582ca144d5e419423381b9150f Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Wed, 12 Oct 2022 17:32:27 +0530 +Subject: [PATCH 4/4] ath11k: add support for ADFS radar + +added support for simulating dfs with agile detector id +and offset values via debugfs command + +old command: +echo 1 > /sys/kernel/debug///dfs_simulate_radar + +Extension: + +echo A B C D > /sys/kernel/debug///dfs_simulate_radar + +where A - is segment id + B - chrip radar indication + C - offset value + D - agile detector id + +Signed-off-by: Harshitha Prem +--- + drivers/net/wireless/ath/ath11k/debugfs.c | 56 ++++++++++++++++++++++- + drivers/net/wireless/ath/ath11k/wmi.c | 4 +- + drivers/net/wireless/ath/ath11k/wmi.h | 2 +- + 3 files changed, 58 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/debugfs.c ++++ b/drivers/net/wireless/ath/ath11k/debugfs.c +@@ -2393,12 +2393,21 @@ static const struct file_operations fops + .open = simple_open + }; + ++#define SEGMENT_ID GENMASK(1,0) ++#define CHRIP_ID BIT(2) ++#define OFFSET GENMASK(10,3) ++#define DETECTOR_ID GENMASK(12,11) + static ssize_t ath11k_write_simulate_radar(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) + { + struct ath11k *ar = file->private_data; + int ret; ++ u32 radar_params; ++ u8 agile = 0, segment = 0, chrip = 0; ++ int offset = 0, len; ++ char buf[64], *token, *sptr; ++ + + if (ar->state != ATH11K_STATE_ON) { + ath11k_warn(ar->ab, "pdev %d not in ON state\n", ar->pdev->pdev_id); +@@ -2406,7 +2415,54 @@ static ssize_t ath11k_write_simulate_rad + return -ENETDOWN; + } + +- ret = ath11k_wmi_simulate_radar(ar); ++ len = min(count, sizeof(buf) - 1); ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ /* For backward compatibility */ ++ if (len <= 2) ++ goto send_cmd; ++ ++ buf[len] = '\0'; ++ sptr = buf; ++ token = strsep(&sptr, " "); ++ if (!token) ++ return -EINVAL; ++ ++ if (kstrtou8(token, 16, &segment)) ++ return -EINVAL; ++ ++ token = strsep(&sptr, " "); ++ if (!token) ++ return -EINVAL; ++ ++ if (kstrtou8(token, 16, &chrip)) ++ return -EINVAL; ++ ++ token = strsep(&sptr, " "); ++ if (!token) ++ return -EINVAL; ++ ++ if (kstrtoint(token, 16, &offset)) ++ return -EINVAL; ++ ++ token = strsep(&sptr, " "); ++ if (!token) ++ return -EINVAL; ++ ++ if (kstrtou8(token, 16, &agile)) ++ return -EINVAL; ++ ++ if ((segment > 1) || (chrip > 1) || (agile > 2)) ++ return -EINVAL; ++ ++send_cmd: ++ radar_params = FIELD_PREP(SEGMENT_ID, segment) | ++ FIELD_PREP(CHRIP_ID, chrip) | ++ FIELD_PREP(OFFSET, offset) | ++ FIELD_PREP(DETECTOR_ID, agile); ++ ++ ret = ath11k_wmi_simulate_radar(ar, radar_params); + if (ret) + return ret; + +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -11410,7 +11410,7 @@ ath11k_wmi_send_unit_test_cmd(struct ath + return ret; + } + +-int ath11k_wmi_simulate_radar(struct ath11k *ar) ++int ath11k_wmi_simulate_radar(struct ath11k *ar, u32 radar_params) + { + struct ath11k_vif *arvif; + u32 dfs_args[DFS_MAX_TEST_ARGS]; +@@ -11433,14 +11433,15 @@ int ath11k_wmi_simulate_radar(struct ath + * freq offset (b3 - b10) to unit test. For simulation + * purpose this can be set to 0 which is valid. + */ +- dfs_args[DFS_TEST_RADAR_PARAM] = 0; ++ dfs_args[DFS_TEST_RADAR_PARAM] = radar_params; + + wmi_ut.vdev_id = arvif->vdev_id; + wmi_ut.module_id = DFS_UNIT_TEST_MODULE; + wmi_ut.num_args = DFS_MAX_TEST_ARGS; + wmi_ut.diag_token = DFS_UNIT_TEST_TOKEN; + +- ath11k_dbg(ar->ab, ATH11K_DBG_REG, "Triggering Radar Simulation\n"); ++ ath11k_dbg(ar->ab, ATH11K_DBG_REG, ++ "Triggering Radar Simulation with param %d\n", radar_params); + + return ath11k_wmi_send_unit_test_cmd(ar, wmi_ut, dfs_args); + } +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -7612,7 +7612,7 @@ size_t ath11k_wmi_fw_stats_num_vdevs(str + void ath11k_wmi_fw_stats_fill(struct ath11k *ar, + struct ath11k_fw_stats *fw_stats, u32 stats_id, + char *buf); +-int ath11k_wmi_simulate_radar(struct ath11k *ar); ++int ath11k_wmi_simulate_radar(struct ath11k *ar, u32 radar_params); + int ath11k_wmi_simulate_awgn(struct ath11k *ar, u32 chan_bw_interference_bitmap); + int ath11k_wmi_send_twt_enable_cmd(struct ath11k *ar, u32 pdev_id); + int ath11k_wmi_send_twt_disable_cmd(struct ath11k *ar, u32 pdev_id); diff --git a/feeds/ipq95xx/mac80211/patches/qca/366-ath11k-wmm-sent-pkts.patch b/feeds/ipq95xx/mac80211/patches/qca/366-ath11k-wmm-sent-pkts.patch new file mode 100644 index 000000000..10fba22ad --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/366-ath11k-wmm-sent-pkts.patch @@ -0,0 +1,140 @@ +From 871856ed87e144a2ec67bb2fed85de2ebcda759b Mon Sep 17 00:00:00 2001 +From: saleemuddin shaik +Date: Sat, 4 Mar 2023 14:07:19 +0530 +Subject: ath11k: add statistic support for counting wmm sent packets. + +Segregated wmm types for rx path and tx path introduced to handle bidirectional + traffic flow. This will avoid misplaced piling of the wmm buckets. + +Signed-off-by: saleemuddin shaik +--- + drivers/net/wireless/ath/ath11k/core.h | 8 ++++ + drivers/net/wireless/ath/ath11k/debugfs.c | 51 +++++++++++++++++++++++ + drivers/net/wireless/ath/ath11k/dp_rx.c | 2 + + drivers/net/wireless/ath/ath11k/mac.c | 2 + + 4 files changed, 63 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h +index e83e1af..094d163 100644 +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -849,6 +849,13 @@ struct ath11k_per_peer_tx_stats { + bool is_ampdu; + }; + ++#define ATH11K_DSCP_PRIORITY 7 ++ ++struct ath11k_wmm_stats { ++ int tx_type; ++ u64 total_wmm_tx_pkts[WME_NUM_AC]; ++}; ++ + #define ATH11K_FLUSH_TIMEOUT (5 * HZ) + #define ATH11K_VDEV_DELETE_TIMEOUT_HZ (5 * HZ) + +@@ -1002,6 +1009,7 @@ struct ath11k { + struct ath11k_wow wow; + struct completion target_suspend; + bool target_suspend_ack; ++ struct ath11k_wmm_stats wmm_stats; + struct ath11k_per_peer_tx_stats peer_tx_stats; + struct list_head ppdu_stats_info; + u32 ppdu_stat_list_depth; +diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c +index c400643..e1fe71d 100644 +--- a/drivers/net/wireless/ath/ath11k/debugfs.c ++++ b/drivers/net/wireless/ath/ath11k/debugfs.c +@@ -864,6 +864,51 @@ static const struct file_operations fops_pdev_stats = { + .llseek = default_llseek, + }; + ++static ssize_t ath11k_read_wmm_stats(struct file *file, ++ char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath11k *ar = file->private_data; ++ int len = 0; ++ int size = 2048; ++ char *buf; ++ ssize_t retval; ++ u64 total_wmm_sent_pkts = 0; ++ ++ buf = kzalloc(size, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ mutex_lock(&ar->conf_mutex); ++ for (count = 0; count < WME_NUM_AC; count++) ++ total_wmm_sent_pkts += ar->wmm_stats.total_wmm_tx_pkts[count]; ++ ++ len += scnprintf(buf + len, size - len, "total number of wmm_sent: %llu\n", ++ total_wmm_sent_pkts); ++ len += scnprintf(buf + len, size - len, "num of be wmm_sent: %llu\n", ++ ar->wmm_stats.total_wmm_tx_pkts[WME_AC_BE]); ++ len += scnprintf(buf + len, size - len, "num of bk wmm_sent: %llu\n", ++ ar->wmm_stats.total_wmm_tx_pkts[WME_AC_BK]); ++ len += scnprintf(buf + len, size - len, "num of vi wmm_sent: %llu\n", ++ ar->wmm_stats.total_wmm_tx_pkts[WME_AC_VI]); ++ len += scnprintf(buf + len, size - len, "num of vo wmm_sent: %llu\n", ++ ar->wmm_stats.total_wmm_tx_pkts[WME_AC_VO]); ++ ++ mutex_unlock(&ar->conf_mutex); ++ ++ if (len > size) ++ len = size; ++ retval = simple_read_from_buffer(ubuf, count, ppos, buf, len); ++ kfree(buf); ++ ++ return retval; ++} ++ ++static const struct file_operations fops_wmm_stats = { ++ .read = ath11k_read_wmm_stats, ++ .open = simple_open, ++}; ++ + static int ath11k_open_vdev_stats(struct inode *inode, struct file *file) + { + struct ath11k *ar = inode->i_private; +@@ -4610,6 +4655,12 @@ int ath11k_debugfs_register(struct ath11k *ar) + init_completion(&ab->ani_ofdm_event); + init_completion(&ab->ani_cck_event); + ++ memset(&ar->wmm_stats, 0, sizeof(struct ath11k_wmm_stats)); ++ ++ debugfs_create_file("wmm_stats", 0644, ++ ar->debug.debugfs_pdev, ar, ++ &fops_wmm_stats); ++ + debugfs_create_file("ext_tx_stats", 0644, + ar->debug.debugfs_pdev, ar, + &fops_extd_tx_stats); +diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c +index 896d797..d47378f 100644 +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -1589,6 +1589,8 @@ ath11k_update_per_peer_tx_stats(struct ath11k *ar, + usr_stats->ack_ba.info); + tid = FIELD_GET(HTT_PPDU_STATS_ACK_BA_INFO_TID_NUM, + usr_stats->ack_ba.info); ++ ar->wmm_stats.tx_type = ath11k_tid_to_ac(tid > ATH11K_DSCP_PRIORITY ? 0: tid); ++ ar->wmm_stats.total_wmm_tx_pkts[ar->wmm_stats.tx_type]++; + } + + if (common->fes_duration_us) +diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c +index 6849f40..fb7e411 100644 +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -8860,6 +8860,8 @@ static int ath11k_mac_vdev_stop(struct ath11k_vif *arvif) + + reinit_completion(&ar->vdev_setup_done); + ++ memset(&ar->wmm_stats, 0, sizeof(struct ath11k_wmm_stats)); ++ + ret = ath11k_wmi_vdev_stop(ar, arvif->vdev_id); + if (ret) { + ath11k_warn(ar->ab, "failed to stop WMI vdev %i: %d\n", +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/367-ath11k-wmm-received-pkts.patch b/feeds/ipq95xx/mac80211/patches/qca/367-ath11k-wmm-received-pkts.patch new file mode 100644 index 000000000..9d9661142 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/367-ath11k-wmm-received-pkts.patch @@ -0,0 +1,118 @@ +From 04144dc7f370a94d8513c7d9624e49db87f54469 Mon Sep 17 00:00:00 2001 +From: saleemuddin shaik +Date: Sat, 4 Mar 2023 14:09:50 +0530 +Subject: ath11k: add statistic support for counting wmm received packets. + +ath11k wmm receive packets statistics through fast_rx path is covered. +If the peer is fast_rx peer, the tid of the packets are retrieved and +the statistical information for received packets are update +at the respective categories like, AC_BE, AC_BK, AC_VO and AC_VI. + +Signed-off-by: saleemuddin shaik +--- + drivers/net/wireless/ath/ath11k/core.h | 2 ++ + drivers/net/wireless/ath/ath11k/debugfs.c | 15 ++++++++++++++- + drivers/net/wireless/ath/ath11k/dp_rx.c | 8 ++++++++ + 3 files changed, 24 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h +index 094d163..a68eedf 100644 +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -853,7 +853,9 @@ struct ath11k_per_peer_tx_stats { + + struct ath11k_wmm_stats { + int tx_type; ++ int rx_type; + u64 total_wmm_tx_pkts[WME_NUM_AC]; ++ u64 total_wmm_rx_pkts[WME_NUM_AC]; + }; + + #define ATH11K_FLUSH_TIMEOUT (5 * HZ) +diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c +index e1fe71d..84e3bd9 100644 +--- a/drivers/net/wireless/ath/ath11k/debugfs.c ++++ b/drivers/net/wireless/ath/ath11k/debugfs.c +@@ -874,17 +874,22 @@ static ssize_t ath11k_read_wmm_stats(struct file *file, + char *buf; + ssize_t retval; + u64 total_wmm_sent_pkts = 0; ++ u64 total_wmm_received_pkts = 0; + + buf = kzalloc(size, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + mutex_lock(&ar->conf_mutex); +- for (count = 0; count < WME_NUM_AC; count++) ++ for (count = 0; count < WME_NUM_AC; count++) { + total_wmm_sent_pkts += ar->wmm_stats.total_wmm_tx_pkts[count]; ++ total_wmm_received_pkts += ar->wmm_stats.total_wmm_rx_pkts[count]; ++ } + + len += scnprintf(buf + len, size - len, "total number of wmm_sent: %llu\n", + total_wmm_sent_pkts); ++ len += scnprintf(buf + len, size - len, "total number of wmm_received: %llu\n", ++ total_wmm_received_pkts); + len += scnprintf(buf + len, size - len, "num of be wmm_sent: %llu\n", + ar->wmm_stats.total_wmm_tx_pkts[WME_AC_BE]); + len += scnprintf(buf + len, size - len, "num of bk wmm_sent: %llu\n", +@@ -893,6 +898,14 @@ static ssize_t ath11k_read_wmm_stats(struct file *file, + ar->wmm_stats.total_wmm_tx_pkts[WME_AC_VI]); + len += scnprintf(buf + len, size - len, "num of vo wmm_sent: %llu\n", + ar->wmm_stats.total_wmm_tx_pkts[WME_AC_VO]); ++ len += scnprintf(buf + len, size - len, "num of be wmm_received: %llu\n", ++ ar->wmm_stats.total_wmm_rx_pkts[WME_AC_BE]); ++ len += scnprintf(buf + len, size - len, "num of bk wmm_received: %llu\n", ++ ar->wmm_stats.total_wmm_rx_pkts[WME_AC_BK]); ++ len += scnprintf(buf + len, size - len, "num of vi wmm_received: %llu\n", ++ ar->wmm_stats.total_wmm_rx_pkts[WME_AC_VI]); ++ len += scnprintf(buf + len, size - len, "num of vo wmm_received: %llu\n", ++ ar->wmm_stats.total_wmm_rx_pkts[WME_AC_VO]); + + mutex_unlock(&ar->conf_mutex); + +diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c +index d47378f..2160dbb 100644 +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -2740,6 +2740,7 @@ static void ath11k_dp_rx_h_undecap(struct ath11k *ar, struct sk_buff *msdu, + enctype, status); + break; + } ++ ar->wmm_stats.total_wmm_rx_pkts[ar->wmm_stats.rx_type]++; + } + + static struct ath11k_peer * +@@ -2830,7 +2831,9 @@ static void ath11k_dp_rx_h_mpdu(struct ath11k *ar, + u32 err_bitmap; + struct wireless_dev *wdev = NULL; + struct ath11k_sta *arsta = NULL; ++ u8 tid; + ++ tid = ath11k_dp_rx_h_mpdu_start_tid(ar->ab, rx_desc); + /* PN for multicast packets will be checked in mac80211 */ + rxcb = ATH11K_SKB_RXCB(msdu); + if (!ar->ab->nss.enabled) +@@ -2851,6 +2854,9 @@ static void ath11k_dp_rx_h_mpdu(struct ath11k *ar, + * path, so its safe to skip checking errors here */ + if (*fast_rx && + ath11k_dp_rx_check_fast_rx(ar, msdu, rx_desc, peer)) { ++ ar->wmm_stats.rx_type = ++ ath11k_tid_to_ac(rxcb->tid > ATH11K_DSCP_PRIORITY ? 0: rxcb->tid); ++ ar->wmm_stats.total_wmm_rx_pkts[ar->wmm_stats.rx_type]++; + wdev = ieee80211_vif_to_wdev(peer->vif); + if (wdev) { + spin_unlock_bh(&ar->ab->base_lock); +@@ -3416,6 +3422,8 @@ try_again: + rxcb->tid = FIELD_GET(HAL_REO_DEST_RING_INFO0_RX_QUEUE_NUM, + desc->info0); + ++ ar->wmm_stats.rx_type = ath11k_tid_to_ac(rxcb->tid > ATH11K_DSCP_PRIORITY ? 0: rxcb->tid); ++ + if (ath11k_debugfs_is_extd_rx_stats_enabled(ar) && rxcb->peer_id) { + rcu_read_lock(); + spin_lock_bh(&ab->base_lock); +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/368-ath11k-fail-sent-pkts.patch b/feeds/ipq95xx/mac80211/patches/qca/368-ath11k-fail-sent-pkts.patch new file mode 100644 index 000000000..6a092404b --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/368-ath11k-fail-sent-pkts.patch @@ -0,0 +1,91 @@ +From fe3b72176e72b1b0ccfd969447ce8519f8274457 Mon Sep 17 00:00:00 2001 +From: saleemuddin shaik +Date: Sat, 4 Mar 2023 14:11:03 +0530 +Subject: ath11k: add statistic support for counting wmm failed sent + packets. + +if the acknowledgement is not received for the packets sent in the air, +then incrementing the drop packets are counted based on WMM categories. + +Signed-off-by: saleemuddin shaik +--- + drivers/net/wireless/ath/ath11k/core.h | 1 + + drivers/net/wireless/ath/ath11k/debugfs.c | 12 ++++++++++++ + drivers/net/wireless/ath/ath11k/dp_tx.c | 6 ++++++ + 3 files changed, 19 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h +index a68eedf..1b5d938 100644 +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -856,6 +856,7 @@ struct ath11k_wmm_stats { + int rx_type; + u64 total_wmm_tx_pkts[WME_NUM_AC]; + u64 total_wmm_rx_pkts[WME_NUM_AC]; ++ u64 total_wmm_tx_drop[WME_NUM_AC]; + }; + + #define ATH11K_FLUSH_TIMEOUT (5 * HZ) +diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c +index 84e3bd9..a0ca4b9 100644 +--- a/drivers/net/wireless/ath/ath11k/debugfs.c ++++ b/drivers/net/wireless/ath/ath11k/debugfs.c +@@ -875,6 +875,7 @@ static ssize_t ath11k_read_wmm_stats(struct file *file, + ssize_t retval; + u64 total_wmm_sent_pkts = 0; + u64 total_wmm_received_pkts = 0; ++ u64 total_wmm_fail_sent = 0; + + buf = kzalloc(size, GFP_KERNEL); + if (!buf) +@@ -884,12 +885,15 @@ static ssize_t ath11k_read_wmm_stats(struct file *file, + for (count = 0; count < WME_NUM_AC; count++) { + total_wmm_sent_pkts += ar->wmm_stats.total_wmm_tx_pkts[count]; + total_wmm_received_pkts += ar->wmm_stats.total_wmm_rx_pkts[count]; ++ total_wmm_fail_sent += ar->wmm_stats.total_wmm_tx_drop[count]; + } + + len += scnprintf(buf + len, size - len, "total number of wmm_sent: %llu\n", + total_wmm_sent_pkts); + len += scnprintf(buf + len, size - len, "total number of wmm_received: %llu\n", + total_wmm_received_pkts); ++ len += scnprintf(buf + len, size - len, "total number of wmm_fail_sent: %llu\n", ++ total_wmm_fail_sent); + len += scnprintf(buf + len, size - len, "num of be wmm_sent: %llu\n", + ar->wmm_stats.total_wmm_tx_pkts[WME_AC_BE]); + len += scnprintf(buf + len, size - len, "num of bk wmm_sent: %llu\n", +@@ -906,6 +910,14 @@ static ssize_t ath11k_read_wmm_stats(struct file *file, + ar->wmm_stats.total_wmm_rx_pkts[WME_AC_VI]); + len += scnprintf(buf + len, size - len, "num of vo wmm_received: %llu\n", + ar->wmm_stats.total_wmm_rx_pkts[WME_AC_VO]); ++ len += scnprintf(buf + len, size - len, "num of be wmm_tx_dropped: %llu\n", ++ ar->wmm_stats.total_wmm_tx_drop[WME_AC_BE]); ++ len += scnprintf(buf + len, size - len, "num of bk wmm_tx_dropped: %llu\n", ++ ar->wmm_stats.total_wmm_tx_drop[WME_AC_BK]); ++ len += scnprintf(buf + len, size - len, "num of vi wmm_tx_dropped: %llu\n", ++ ar->wmm_stats.total_wmm_tx_drop[WME_AC_VI]); ++ len += scnprintf(buf + len, size - len, "num of vo wmm_tx_dropped: %llu\n", ++ ar->wmm_stats.total_wmm_tx_drop[WME_AC_VO]); + + mutex_unlock(&ar->conf_mutex); + +diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c +index 15ed9d1..d939f42 100644 +--- a/drivers/net/wireless/ath/ath11k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_tx.c +@@ -829,6 +829,12 @@ static void ath11k_dp_tx_complete_msdu(struct ath11k *ar, + + ath11k_dp_tx_status_parse(ab, tx_status, &ts); + ++ ar->wmm_stats.tx_type = ath11k_tid_to_ac(ts.tid > ATH11K_DSCP_PRIORITY ? 0:ts.tid); ++ if (ar->wmm_stats.tx_type) { ++ if (ts.status != HAL_WBM_TQM_REL_REASON_FRAME_ACKED) ++ ar->wmm_stats.total_wmm_tx_drop[ar->wmm_stats.tx_type]++; ++ } ++ + if (unlikely(!rcu_access_pointer(ab->pdevs_active[ar->pdev_idx]))) { + dev_kfree_skb_any(msdu); + return; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/369-ath11k-fail-received-pkts.patch b/feeds/ipq95xx/mac80211/patches/qca/369-ath11k-fail-received-pkts.patch new file mode 100644 index 000000000..9d8808f58 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/369-ath11k-fail-received-pkts.patch @@ -0,0 +1,99 @@ +From 0763cf3a8987df6da4865afd663f06890ec5c8a3 Mon Sep 17 00:00:00 2001 +From: saleemuddin shaik +Date: Sat, 4 Mar 2023 14:12:52 +0530 +Subject: ath11k: add statistic support for counting wmm failed received + packets. + +if the desc bit is not set and num_msdu is greater then one, +then increment the drop packets are counted based on WMM categories. + +Signed-off-by: saleemuddin shaik +--- + drivers/net/wireless/ath/ath11k/core.h | 1 + + drivers/net/wireless/ath/ath11k/debugfs.c | 12 ++++++++++++ + drivers/net/wireless/ath/ath11k/dp_rx.c | 1 + + 3 files changed, 14 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -857,6 +857,7 @@ struct ath11k_wmm_stats { + u64 total_wmm_tx_pkts[WME_NUM_AC]; + u64 total_wmm_rx_pkts[WME_NUM_AC]; + u64 total_wmm_tx_drop[WME_NUM_AC]; ++ u64 total_wmm_rx_drop[WME_NUM_AC]; + }; + + #define ATH11K_FLUSH_TIMEOUT (5 * HZ) +--- a/drivers/net/wireless/ath/ath11k/debugfs.c ++++ b/drivers/net/wireless/ath/ath11k/debugfs.c +@@ -876,6 +876,7 @@ static ssize_t ath11k_read_wmm_stats(str + u64 total_wmm_sent_pkts = 0; + u64 total_wmm_received_pkts = 0; + u64 total_wmm_fail_sent = 0; ++ u64 total_wmm_fail_received = 0; + + buf = kzalloc(size, GFP_KERNEL); + if (!buf) +@@ -886,6 +887,7 @@ static ssize_t ath11k_read_wmm_stats(str + total_wmm_sent_pkts += ar->wmm_stats.total_wmm_tx_pkts[count]; + total_wmm_received_pkts += ar->wmm_stats.total_wmm_rx_pkts[count]; + total_wmm_fail_sent += ar->wmm_stats.total_wmm_tx_drop[count]; ++ total_wmm_fail_received += ar->wmm_stats.total_wmm_rx_drop[count]; + } + + len += scnprintf(buf + len, size - len, "total number of wmm_sent: %llu\n", +@@ -894,6 +896,8 @@ static ssize_t ath11k_read_wmm_stats(str + total_wmm_received_pkts); + len += scnprintf(buf + len, size - len, "total number of wmm_fail_sent: %llu\n", + total_wmm_fail_sent); ++ len += scnprintf(buf + len, size - len, "total number of wmm_fail_received: %llu\n", ++ total_wmm_fail_received); + len += scnprintf(buf + len, size - len, "num of be wmm_sent: %llu\n", + ar->wmm_stats.total_wmm_tx_pkts[WME_AC_BE]); + len += scnprintf(buf + len, size - len, "num of bk wmm_sent: %llu\n", +@@ -918,6 +922,14 @@ static ssize_t ath11k_read_wmm_stats(str + ar->wmm_stats.total_wmm_tx_drop[WME_AC_VI]); + len += scnprintf(buf + len, size - len, "num of vo wmm_tx_dropped: %llu\n", + ar->wmm_stats.total_wmm_tx_drop[WME_AC_VO]); ++ len += scnprintf(buf + len, size - len, "num of be wmm_rx_dropped: %llu\n", ++ ar->wmm_stats.total_wmm_rx_drop[WME_AC_BE]); ++ len += scnprintf(buf + len, size - len, "num of bk wmm_rx_dropped: %llu\n", ++ ar->wmm_stats.total_wmm_rx_drop[WME_AC_BK]); ++ len += scnprintf(buf + len, size - len, "num of vi wmm_rx_dropped: %llu\n", ++ ar->wmm_stats.total_wmm_rx_drop[WME_AC_VI]); ++ len += scnprintf(buf + len, size - len, "num of vo wmm_rx_dropped: %llu\n", ++ ar->wmm_stats.total_wmm_rx_drop[WME_AC_VO]); + + mutex_unlock(&ar->conf_mutex); + +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -4753,8 +4753,7 @@ int ath11k_dp_process_rx_err(struct ath1 + struct ath11k *ar; + dma_addr_t paddr; + u32 *desc; +- bool is_frag; +- u8 drop = 0; ++ bool is_frag, drop = false; + + tot_n_bufs_reaped = 0; + quota = budget; +@@ -4800,7 +4799,7 @@ int ath11k_dp_process_rx_err(struct ath1 + * msdu's indicated due to error reasons. + */ + if (!is_frag || num_msdus > 1) { +- drop = 1; ++ drop = true; + /* Return the link desc back to wbm idle list */ + ath11k_dp_rx_link_desc_return(ab, desc, + HAL_WBM_REL_BM_ACT_PUT_IN_IDLE); +@@ -4815,6 +4814,9 @@ int ath11k_dp_process_rx_err(struct ath1 + + ar = ab->pdevs[mac_id].ar; + ++ if (drop) ++ ar->wmm_stats.total_wmm_rx_drop[ar->wmm_stats.rx_type]++; ++ + if (!ath11k_dp_process_rx_err_buf(ar, desc, buf_id, drop)) { + n_bufs_reaped[mac_id]++; + tot_n_bufs_reaped++; diff --git a/feeds/ipq95xx/mac80211/patches/qca/370-ath11k-add-support-to-get-rssi-value-of-non-associat.patch b/feeds/ipq95xx/mac80211/patches/qca/370-ath11k-add-support-to-get-rssi-value-of-non-associat.patch new file mode 100644 index 000000000..6685a4eb0 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/370-ath11k-add-support-to-get-rssi-value-of-non-associat.patch @@ -0,0 +1,673 @@ +From dda25e914cf8f077d1ab8bcaa5600f483976cac5 Mon Sep 17 00:00:00 2001 +From: saleemuddin shaik +Date: Thu, 16 Mar 2023 13:56:43 +0530 +Subject: [PATCH] ath11k: add support to get rssi value of non-associated + client + +Monitor the surrounding network to get RSSI of non-associated +client(for example, if Neighbor-Peer associated to neighboring AP's). +Obtaining the RSSI it is useful for roaming between AP's in a +network and on deciding which AP the client should associate +with. +This is achieved through debugfs by providing the mac address +of a npr(neighbor peer) which creates a neighbor-peer object to store's the +data associated with the npr such as its mac, RSSI and timestamp. +Once the npr is added a file with the mac-address of npr as its +filename is created. +Each time the file is read a peer object is created for the +NPR and filter is set to get its ppdu_info for home channel +thereby obtaining the RSSI and a corresponding unix +timestamp is created, once the data collection is completed the +peer object is destroyed to free-up peer count. +Upto 6 NPR's can be created to keep the load and peer-count low. +Once the rssi and timestamp are obtained the peer object +created for NPR is deleted to free the peer id. +In case the NPR packets are unavailable during scan the +previous timestamped value is returned. + +Command to add a Neighbor-Peer: +echo "add," > +/sys/kernel/debug/ieee80211/phyX/ath11k/neighbor_peer + +Command to delete a Neighbor-Peer: +echo "del," > +/sys/kernel/debug/ieee80211/phyX/ath11k/neighbor_peer + +Command to display RSSI of Neighbor-Peer: +cat /sys/kernel/debug/ieee80211/phyX/ath11k/nrp_rssi/ + +Signed-off-by: saleemuddin shaik +--- + drivers/net/wireless/ath/ath11k/core.c | 5 + + drivers/net/wireless/ath/ath11k/core.h | 4 + + drivers/net/wireless/ath/ath11k/debugfs.c | 401 ++++++++++++++++++++++ + drivers/net/wireless/ath/ath11k/debugfs.h | 30 ++ + drivers/net/wireless/ath/ath11k/dp_rx.c | 14 + + drivers/net/wireless/ath/ath11k/mac.c | 32 ++ + 6 files changed, 486 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c +index 504e390..0bdee41 100644 +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -2177,6 +2177,10 @@ static void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab) + complete(&ar->scan.on_channel); + complete(&ar->peer_assoc_done); + complete(&ar->peer_delete_done); ++ ++ if (!list_empty(&ab->neighbor_peers)) ++ ath11k_debugfs_nrp_cleanup_all(ar); ++ + complete(&ar->install_key_done); + complete(&ar->vdev_setup_done); + complete(&ar->vdev_delete_done); +@@ -2467,6 +2471,7 @@ struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size, + init_completion(&ab->recovery_start); + + INIT_LIST_HEAD(&ab->peers); ++ INIT_LIST_HEAD(&ab->neighbor_peers); + init_waitqueue_head(&ab->peer_mapping_wq); + init_waitqueue_head(&ab->wmi_ab.tx_credits_wq); + init_waitqueue_head(&ab->qmi.cold_boot_waitq); +diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h +index e543442..2b8b4b8 100644 +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -830,6 +830,7 @@ struct ath11k_debug { + struct dentry *debugfs_smartant; + u32 coex_priority_level[ATH11K_MAX_COEX_PRIORITY_LEVEL]; + enum wmi_bss_chan_info_req_type bss_survey_mode; ++ struct dentry *debugfs_nrp; + }; + + struct ath11k_per_peer_tx_stats { +@@ -1323,6 +1324,9 @@ struct ath11k_base { + #endif + struct ath11k_soc_dp_stats soc_stats; + ++ struct list_head neighbor_peers; ++ int num_nrps; ++ + unsigned long dev_flags; + struct completion driver_recovery; + struct workqueue_struct *workqueue; +diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c +index 44a4e5a..a6b998c 100644 +--- a/drivers/net/wireless/ath/ath11k/debugfs.c ++++ b/drivers/net/wireless/ath/ath11k/debugfs.c +@@ -1424,6 +1424,404 @@ static const struct file_operations fops_extd_rx_stats = { + .open = simple_open, + }; + ++static int ath11k_reset_nrp_filter(struct ath11k *ar, ++ bool reset) ++{ ++ int i = 0; ++ int ret = 0; ++ u32 ring_id = 0; ++ struct htt_rx_ring_tlv_filter tlv_filter = {0}; ++ struct ath11k_pdev_dp *dp = &ar->dp; ++ struct ath11k_base *ab = ar->ab; ++ ++ if (ab->hw_params.full_monitor_mode) { ++ ret = ath11k_dp_tx_htt_rx_full_mon_setup(ab, ++ dp->mac_id, !reset); ++ if (ret < 0) { ++ ath11k_err(ab, "failed to setup full monitor %d\n", ret); ++ return ret; ++ } ++ } ++ ++ ring_id = dp->rxdma_mon_buf_ring.refill_buf_ring.ring_id; ++ tlv_filter.offset_valid = false; ++ if (!reset) { ++ tlv_filter.pkt_filter_flags0 = ++ HTT_RX_MON_MO_MGMT_FILTER_FLAGS0; ++ tlv_filter.pkt_filter_flags1 = ++ HTT_RX_MON_MO_MGMT_FILTER_FLAGS1; ++ tlv_filter.pkt_filter_flags2 = ++ HTT_RX_MON_MO_CTRL_FILTER_FLASG2; ++ tlv_filter.pkt_filter_flags3 = ++ HTT_RX_MON_MO_CTRL_FILTER_FLASG3 | ++ HTT_RX_MON_MO_DATA_FILTER_FLASG3; ++ } ++ ++ if (ar->ab->hw_params.rxdma1_enable) { ++ ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id, ++ HAL_RXDMA_MONITOR_BUF, ++ DP_RXDMA_REFILL_RING_SIZE, ++ &tlv_filter); ++ } else if (!reset) { ++ for (i = 0; i < ar->ab->hw_params.num_rxmda_per_pdev; i++) { ++ ring_id = ar->dp.rx_mac_buf_ring[i].ring_id; ++ ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ++ ar->dp.mac_id + i, ++ HAL_RXDMA_BUF, ++ 1024, ++ &tlv_filter); ++ } ++ } ++ ++ if (ret) ++ return ret; ++ ++ for (i = 0; i < ar->ab->hw_params.num_rxmda_per_pdev; i++) { ++ ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id; ++ if (!reset) { ++ tlv_filter.rx_filter = ++ HTT_RX_MON_FILTER_TLV_FLAGS_MON_STATUS_RING; ++ } else { ++ tlv_filter = ath11k_mac_mon_status_filter_default; ++ ++ if (ath11k_debugfs_is_extd_rx_stats_enabled(ar)) ++ tlv_filter.rx_filter = ath11k_debugfs_rx_filter(ar); ++ } ++ ++ ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ++ ar->dp.mac_id + i, ++ HAL_RXDMA_MONITOR_STATUS, ++ DP_RXDMA_REFILL_RING_SIZE, ++ &tlv_filter); ++ } ++ ++ if (!ar->ab->hw_params.rxdma1_enable) ++ mod_timer(&ar->ab->mon_reap_timer, jiffies + ++ msecs_to_jiffies(ATH11K_MON_TIMER_INTERVAL)); ++ ++ return ret; ++} ++ ++void ath11k_debugfs_nrp_cleanup_all(struct ath11k *ar) ++{ ++ struct ath11k_base *ab = ar->ab; ++ struct ath11k_neighbor_peer *nrp, *tmp; ++ ++ spin_lock_bh(&ab->base_lock); ++ list_for_each_entry_safe(nrp, tmp, &ab->neighbor_peers, list) { ++ if (nrp->is_filter_on) ++ complete(&nrp->filter_done); ++ list_del(&nrp->list); ++ kfree(nrp); ++ } ++ ++ ab->num_nrps = 0; ++ spin_unlock_bh(&ab->base_lock); ++ ++ debugfs_remove_recursive(ar->debug.debugfs_nrp); ++} ++ ++void ath11k_debugfs_nrp_clean(struct ath11k *ar, const u8 *addr) ++{ ++ int i, j; ++ char fname[MAC_UNIT_LEN * ETH_ALEN] = {0}; ++ ++ for (i = 0, j = 0; i < (MAC_UNIT_LEN * ETH_ALEN); i += MAC_UNIT_LEN, j++) { ++ if (j == ETH_ALEN - 1) { ++ snprintf(fname + i, sizeof(fname) - i, "%02x", *(addr + j)); ++ break; ++ } ++ snprintf(fname + i, sizeof(fname) - i, "%02x:", *(addr + j)); ++ } ++ ++ spin_lock_bh(&ar->ab->base_lock); ++ ar->ab->num_nrps--; ++ spin_unlock_bh(&ar->ab->base_lock); ++ ++ debugfs_lookup_and_remove(fname, ar->debug.debugfs_nrp); ++ if (!ar->ab->num_nrps) { ++ debugfs_remove_recursive(ar->debug.debugfs_nrp); ++ ath11k_reset_nrp_filter(ar, true); ++ } ++} ++ ++static ssize_t ath11k_read_nrp_rssi(struct file *file, ++ char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath11k *ar = file->private_data; ++ struct ath11k_base *ab = ar->ab; ++ struct ath11k_vif *arvif = NULL; ++ struct ath11k_neighbor_peer *nrp = NULL, *tmp; ++ struct peer_create_params peer_param = {0}; ++ u8 macaddr[ETH_ALEN] = {0}; ++ loff_t file_pos = *ppos; ++ struct path *fpath = &file->f_path; ++ char *fname = fpath->dentry->d_iname; ++ char buf[128] = {0}; ++ int i = 0; ++ int j = 0; ++ int len = 0; ++ int vdev_id = -1; ++ bool nrp_found = false; ++ int ret; ++ ++ mutex_lock(&ar->conf_mutex); ++ if (ar->state != ATH11K_STATE_ON) { ++ mutex_unlock(&ar->conf_mutex); ++ return -ENETDOWN; ++ } ++ mutex_unlock(&ar->conf_mutex); ++ ++ if (file_pos > 0) ++ return 0; ++ ++ mutex_lock(&ar->conf_mutex); ++ list_for_each_entry(arvif, &ar->arvifs, list) { ++ if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { ++ vdev_id = arvif->vdev_id; ++ break; ++ } ++ } ++ mutex_unlock(&ar->conf_mutex); ++ ++ if (vdev_id < 0) { ++ ath11k_warn(ab, "unable to get vdev for AP interface\n"); ++ return 0; ++ } ++ ++ for (i = 0, j = 0; i < MAC_UNIT_LEN * ETH_ALEN; i += MAC_UNIT_LEN, j++) { ++ if (sscanf(fname + i, "%hhX", &macaddr[j]) <= 0) ++ return -EINVAL; ++ } ++ ++ spin_lock_bh(&ab->base_lock); ++ list_for_each_entry(nrp, &ab->neighbor_peers, list) { ++ if (ether_addr_equal(macaddr, nrp->addr)) { ++ reinit_completion(&nrp->filter_done); ++ nrp->vdev_id = vdev_id; ++ nrp->is_filter_on = false; ++ break; ++ } ++ } ++ spin_unlock_bh(&ab->base_lock); ++ ++ peer_param.vdev_id = nrp->vdev_id; ++ peer_param.peer_addr = nrp->addr; ++ peer_param.peer_type = WMI_PEER_TYPE_DEFAULT; ++ ++ ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_SET_PROMISC_MODE_CMDID, ++ 1, ar->pdev->pdev_id); ++ if (ret) ++ ath11k_err(ar->ab, "failed to enable promisc mode: %d\n", ret); ++ ++ if (!ath11k_peer_create(ar, arvif, NULL, &peer_param)) { ++ spin_lock_bh(&ab->base_lock); ++ list_for_each_entry_safe(nrp, tmp, &ab->neighbor_peers, list) { ++ if (ether_addr_equal(nrp->addr, peer_param.peer_addr)) { ++ nrp_found = true; ++ break; ++ } ++ } ++ spin_unlock_bh(&ab->base_lock); ++ ++ if (nrp_found) { ++ spin_lock_bh(&ab->base_lock); ++ nrp->is_filter_on = true; ++ spin_unlock_bh(&ab->base_lock); ++ ++ wait_for_completion_interruptible_timeout(&nrp->filter_done, 15 * HZ); ++ ++ spin_lock_bh(&ab->base_lock); ++ nrp->is_filter_on = false; ++ spin_unlock_bh(&ab->base_lock); ++ ++ len = scnprintf(buf, sizeof(buf), ++ "Neighbor Peer MAC\t\tRSSI\t\tTime\n"); ++ len += scnprintf(buf + len, sizeof(buf) - len, "%pM\t\t%u\t\t%lld\n", ++ nrp->addr, nrp->rssi, nrp->timestamp); ++ } else { ++ ath11k_peer_delete(ar, vdev_id, macaddr); ++ ath11k_warn(ab, "%pM not found in nrp list\n", macaddr); ++ return -EINVAL; ++ } ++ ++ ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_SET_PROMISC_MODE_CMDID, ++ 0, ar->pdev->pdev_id); ++ if (ret) ++ ath11k_err(ar->ab, "failed to disable promisc mode: %d\n", ret); ++ ++ ath11k_peer_delete(ar, vdev_id, macaddr); ++ } else { ++ ath11k_warn(ab, "unable to create peer for nrp[%pM]\n", macaddr); ++ return -EINVAL; ++ } ++ ++ return simple_read_from_buffer(ubuf, count, ppos, buf, len); ++} ++ ++static const struct file_operations fops_read_nrp_rssi = { ++ .read = ath11k_read_nrp_rssi, ++ .open = simple_open, ++}; ++ ++static ssize_t ath11k_write_nrp_mac(struct file *file, ++ const char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath11k *ar = file->private_data; ++ struct ath11k_base *ab = ar->ab; ++ struct ath11k_peer *peer = NULL; ++ struct ath11k_neighbor_peer *nrp = NULL, *tmp = NULL; ++ u8 mac[ETH_ALEN] = {0}; ++ char fname[MAC_UNIT_LEN * ETH_ALEN] = {0}; ++ char *str = NULL; ++ char *buf = vmalloc(count); ++ char *ptr = buf; ++ int i = 0; ++ int j = 0; ++ int ret = count; ++ int action = 0; ++ ssize_t rc = 0; ++ bool del_nrp = false; ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ rc = simple_write_to_buffer(buf, count, ppos, ubuf, count); ++ if (rc <= 0) ++ goto exit; ++ ++ buf[count - 1] = '\0'; ++ ++ if (ar->state != ATH11K_STATE_ON) { ++ ret = -ENETDOWN; ++ goto exit; ++ } ++ ++ str = strsep(&buf, ","); ++ if (!strcmp(str, "add")) ++ action = NRP_ACTION_ADD; ++ else if (!strcmp(str, "del")) ++ action = NRP_ACTION_DEL; ++ else { ++ ath11k_err(ab, "error: invalid argument\n"); ++ goto exit; ++ } ++ ++ memset(mac, 0, sizeof(mac)); ++ while ((str = strsep(&buf, ":")) != NULL) { ++ if (i >= ETH_ALEN || kstrtou8(str, 16, mac + i)) { ++ ath11k_warn(ab, "error: invalid mac address\n"); ++ goto exit; ++ } ++ i++; ++ } ++ ++ if (i != ETH_ALEN) { ++ ath11k_warn(ab, "error: invalid mac address\n"); ++ goto exit; ++ } ++ ++ if (!is_valid_ether_addr(mac)) { ++ ath11k_err(ab, "error: invalid mac address\n"); ++ goto exit; ++ } ++ ++ for (i = 0, j = 0; i < (MAC_UNIT_LEN * ETH_ALEN); i += MAC_UNIT_LEN, j++) { ++ if (j == ETH_ALEN - 1) { ++ snprintf(fname + i, sizeof(fname) - i, "%02x", mac[j]); ++ break; ++ } ++ snprintf(fname + i, sizeof(fname) - i, "%02x:", mac[j]); ++ } ++ ++ switch (action) { ++ case NRP_ACTION_ADD: ++ if (ab->num_nrps == (ATH11K_MAX_NRPS - 1)) { ++ ath11k_warn(ab, "max nrp reached, cannot create more\n"); ++ goto exit; ++ } ++ ++ spin_lock_bh(&ab->base_lock); ++ list_for_each_entry(nrp, &ab->neighbor_peers, list) { ++ if (ether_addr_equal(nrp->addr, mac)) { ++ ath11k_warn(ab, "cannot add existing neighbor peer\n"); ++ goto exit; ++ } ++ } ++ spin_unlock_bh(&ab->base_lock); ++ ++ spin_lock_bh(&ab->base_lock); ++ peer = ath11k_peer_find_by_addr(ab, mac); ++ if (peer) { ++ ath11k_warn(ab, "cannot add exisitng peer [%pM] as nrp\n", mac); ++ spin_unlock_bh(&ab->base_lock); ++ goto exit; ++ } ++ spin_unlock_bh(&ab->base_lock); ++ ++ nrp = kzalloc(sizeof(*nrp), GFP_KERNEL); ++ if (!nrp) ++ goto exit; ++ ++ init_completion(&nrp->filter_done); ++ ether_addr_copy(nrp->addr, mac); ++ ++ spin_lock_bh(&ab->base_lock); ++ list_add_tail(&nrp->list, &ab->neighbor_peers); ++ spin_unlock_bh(&ab->base_lock); ++ ++ if (!ab->num_nrps) { ++ ar->debug.debugfs_nrp = debugfs_create_dir("nrp_rssi", ++ ar->debug.debugfs_pdev); ++ ath11k_reset_nrp_filter(ar, false); ++ } ++ spin_lock_bh(&ab->base_lock); ++ ab->num_nrps++; ++ spin_unlock_bh(&ab->base_lock); ++ ++ debugfs_create_file(fname, 0644, ++ ar->debug.debugfs_nrp, ar, ++ &fops_read_nrp_rssi); ++ break; ++ case NRP_ACTION_DEL: ++ if (!ar->ab->num_nrps) { ++ ath11k_err(ab, "error: no nac added\n"); ++ goto exit; ++ } ++ ++ spin_lock_bh(&ab->base_lock); ++ list_for_each_entry_safe(nrp, tmp, &ab->neighbor_peers, list) { ++ if (ether_addr_equal(nrp->addr, mac)) { ++ list_del(&nrp->list); ++ kfree(nrp); ++ del_nrp = true; ++ break; ++ } ++ ++ } ++ spin_unlock_bh(&ab->base_lock); ++ ++ if (!del_nrp) ++ ath11k_warn(ab, "cannot delete %pM not added to list\n", mac); ++ else ++ ath11k_debugfs_nrp_clean(ar, mac); ++ break; ++ default: ++ break; ++ } ++ exit: ++ mutex_unlock(&ar->conf_mutex); ++ ++ vfree(ptr); ++ return ret; ++} ++ ++static const struct file_operations fops_write_nrp_mac = { ++ .write = ath11k_write_nrp_mac, ++ .open = simple_open, ++}; ++ + static int ath11k_fill_bp_stats(struct ath11k_base *ab, + struct ath11k_bp_stats *bp_stats, + char *buf, int len, int size) +@@ -4698,6 +5096,9 @@ int ath11k_debugfs_register(struct ath11k *ar) + ar->debug.debugfs_pdev, ar, + &fops_wmm_stats); + ++ debugfs_create_file("neighbor_peer", 0644, ++ ar->debug.debugfs_pdev, ar, ++ &fops_write_nrp_mac); + debugfs_create_file("ext_tx_stats", 0644, + ar->debug.debugfs_pdev, ar, + &fops_extd_tx_stats); +diff --git a/drivers/net/wireless/ath/ath11k/debugfs.h b/drivers/net/wireless/ath/ath11k/debugfs.h +index 57c8255..72d446b 100644 +--- a/drivers/net/wireless/ath/ath11k/debugfs.h ++++ b/drivers/net/wireless/ath/ath11k/debugfs.h +@@ -12,6 +12,9 @@ + #define ATH11K_TX_POWER_MIN_VAL 0 + #define ATH11K_DEBUG_ENABLE_MEMORY_STATS 1 + ++#define ATH11K_MAX_NRPS 7 ++#define MAC_UNIT_LEN 3 ++ + /* htt_dbg_ext_stats_type */ + enum ath11k_dbg_htt_ext_stats_type { + ATH11K_DBG_HTT_EXT_STATS_RESET = 0, +@@ -190,6 +193,11 @@ enum ath11k_dbg_aggr_mode { + ATH11K_DBG_AGGR_MODE_MAX, + }; + ++enum ath11k_nrp_action { ++ NRP_ACTION_ADD, ++ NRP_ACTION_DEL, ++}; ++ + enum fw_dbglog_wlan_module_id { + WLAN_MODULE_ID_MIN = 0, + WLAN_MODULE_INF = WLAN_MODULE_ID_MIN, +@@ -298,6 +306,17 @@ enum fw_dbglog_log_level { + ATH11K_FW_DBGLOG_LVL_MAX + }; + ++struct ath11k_neighbor_peer { ++ struct list_head list; ++ struct completion filter_done; ++ bool is_filter_on; ++ int vdev_id; ++ u8 addr[ETH_ALEN]; ++ u8 rssi; ++ s64 timestamp; ++ bool rssi_valid; ++}; ++ + struct ath11k_fw_dbglog { + enum wmi_debug_log_param param; + union { +@@ -361,6 +380,8 @@ ssize_t ath11k_debugfs_dump_soc_ring_bp_stats(struct ath11k_base *ab, + char *buf, int size); + int ath11k_debugfs_get_fw_stats(struct ath11k *ar, u32 pdev_id, + u32 vdev_id, u32 stats_id); ++void ath11k_debugfs_nrp_clean(struct ath11k *ar, const u8 *addr); ++void ath11k_debugfs_nrp_cleanup_all(struct ath11k *ar); + + static inline bool ath11k_debugfs_is_pktlog_lite_mode_enabled(struct ath11k *ar) + { +@@ -536,6 +557,15 @@ ath11k_debugfs_add_dbring_entry(struct ath11k *ar, + static inline void ath11k_smart_ant_debugfs_init(struct ath11k *ar) + { + } ++ ++static inline void ath11k_debugfs_nrp_clean(struct ath11k *ar, const u8 *addr) ++{ ++} ++ ++static inline void ath11k_debugfs_nrp_cleanup_all(struct ath11k *ar) ++{ ++} ++ + #endif /* CPTCFG_ATH11K_DEBUGFS*/ + + #ifdef CPTCFG_ATH11K_PKTLOG +diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c +index 5e85a2e..4a3f6fa 100644 +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -6368,6 +6368,7 @@ int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id, + struct sk_buff *skb; + struct sk_buff_head skb_list; + struct ath11k_peer *peer; ++ struct ath11k_neighbor_peer *nrp, *tmp; + struct ath11k_sta *arsta = NULL; + int num_buffs_reaped = 0; + u32 rx_buf_sz; +@@ -6427,6 +6428,19 @@ int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id, + spin_lock_bh(&ab->base_lock); + peer = ath11k_peer_find_by_id(ab, ppdu_info->peer_id); + ++ if (!list_empty(&ab->neighbor_peers)) { ++ if (peer && !peer->sta) { ++ list_for_each_entry_safe(nrp, tmp, &ab->neighbor_peers, list) { ++ if (nrp->is_filter_on && ether_addr_equal(nrp->addr, peer->addr)) { ++ nrp->rssi = ppdu_info->rssi_comb; ++ nrp->timestamp = ktime_to_ms(ktime_get_real()); ++ complete(&nrp->filter_done); ++ } ++ } ++ goto next_skb; ++ } ++ } ++ + if (!peer || !peer->sta) { + ath11k_dbg(ab, ATH11K_DBG_DATA, + "failed to find the peer with peer_id %d\n", +diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c +index fb7e411..d97a309 100644 +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -1069,6 +1069,9 @@ void ath11k_mac_peer_cleanup_all(struct ath11k *ar) + spin_unlock_bh(&ab->base_lock); + mutex_unlock(&ab->tbl_mtx_lock); + ++ if (!list_empty(&ab->neighbor_peers)) ++ ath11k_debugfs_nrp_cleanup_all(ar); ++ + ar->num_peers = 0; + ar->num_stations = 0; + } +@@ -5755,6 +5758,9 @@ static int ath11k_mac_station_add(struct ath11k *ar, + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv; + struct peer_create_params peer_param; ++ struct ath11k_neighbor_peer *nrp, *tmp; ++ int nvdev_id; ++ bool del_nrp = false; + bool peer_dbg_info; + int ret; + +@@ -5778,6 +5784,32 @@ static int ath11k_mac_station_add(struct ath11k *ar, + peer_param.peer_addr = sta->addr; + peer_param.peer_type = WMI_PEER_TYPE_DEFAULT; + ++ /* ++ * When the neighbor peer associates with this AP and successfully ++ * becomes a station, check and clear the corresponding MAC from ++ * NRP list and failing to do so would inadvertently cause the ++ * STA association(peer creation for STA) to fail due to the NRP ++ * having created a peer already for the same MAC address ++ */ ++ if (!list_empty(&ab->neighbor_peers)) { ++ spin_lock_bh(&ab->base_lock); ++ list_for_each_entry_safe(nrp, tmp, &ab->neighbor_peers, list) { ++ if (ether_addr_equal(nrp->addr, sta->addr)) { ++ nvdev_id = nrp->vdev_id; ++ list_del(&nrp->list); ++ kfree(nrp); ++ del_nrp = true; ++ break; ++ } ++ } ++ spin_unlock_bh(&ab->base_lock); ++ ++ if (del_nrp) { ++ ath11k_peer_delete(ar, nvdev_id, sta->addr); ++ ath11k_debugfs_nrp_clean(ar, sta->addr); ++ } ++ } ++ + ret = ath11k_peer_create(ar, arvif, sta, &peer_param); + if (ret) { + ath11k_warn(ab, "Failed to add peer: %pM for VDEV: %d\n", +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/371-ath11k-Fix-ppdu_id-from-firmware-PPDU-stats.patch b/feeds/ipq95xx/mac80211/patches/qca/371-ath11k-Fix-ppdu_id-from-firmware-PPDU-stats.patch new file mode 100644 index 000000000..a4c956b98 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/371-ath11k-Fix-ppdu_id-from-firmware-PPDU-stats.patch @@ -0,0 +1,56 @@ +From 537a8f2292ba9052957e8284161bcee0635e4223 Mon Sep 17 00:00:00 2001 +From: Ramya Gnanasekar +Date: Tue, 11 Apr 2023 14:15:36 +0530 +Subject: [PATCH] ath11k: Fix ppdu_id from firmware PPDU stats + +ppdu_id in USR_COMPLTN_ACK_BA_STATUS TLV will have firmware meta data +last 7 bits. +When ppdu_id is taken as such, during parsing this is treated as different +ppdu_id which causes incorrect stats update. Since firmware will use +this MSB 7 bits for internal accounting and optimization, +it is recommended to use first 25 bits when fetching ppdu for USR_COMPLTN_ACK_BA_STATUS. + +Signed-off-by: Ramya Gnanasekar + +Index: b/drivers/net/wireless/ath/ath11k/dp.h +=================================================================== +--- a/drivers/net/wireless/ath/ath11k/dp.h 2023-04-20 13:02:45.902017567 +0530 ++++ b/drivers/net/wireless/ath/ath11k/dp.h 2023-04-20 13:03:27.529760148 +0530 +@@ -1520,6 +1520,7 @@ struct htt_ppdu_stats_usr_cmpltn_cmn { + #define HTT_PPDU_STATS_ACK_BA_INFO_TID_NUM GENMASK(31, 25) + + #define HTT_PPDU_STATS_NON_QOS_TID 16 ++#define HTT_PPDU_STATS_PPDU_ID GENMASK(24, 0) + + struct htt_ppdu_stats_usr_cmpltn_ack_ba_status { + u32 ppdu_id; +Index: b/drivers/net/wireless/ath/ath11k/dp_rx.c +=================================================================== +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c 2023-04-20 13:02:45.902017567 +0530 ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c 2023-04-20 13:02:45.890017641 +0530 +@@ -1352,7 +1352,7 @@ static int ath11k_htt_tlv_ppdu_stats_par + struct ath11k_peer *peer; + int cur_user; + u16 peer_id; +- u32 frame_type; ++ u32 frame_type, ppdu_id; + int i; + + ppdu_info = (struct htt_ppdu_stats_info *)data; +@@ -1435,6 +1435,8 @@ static int ath11k_htt_tlv_ppdu_stats_par + return -EINVAL; + } + ++ ppdu_id = ++ ((struct htt_ppdu_stats_usr_cmpltn_ack_ba_status *)ptr)->ppdu_id; + peer_id = + ((struct htt_ppdu_stats_usr_cmpltn_ack_ba_status *)ptr)->sw_peer_id; + cur_user = ath11k_get_ppdu_user_index(&ppdu_info->ppdu_stats, +@@ -1446,6 +1448,7 @@ static int ath11k_htt_tlv_ppdu_stats_par + user_stats->is_valid_peer_id = true; + memcpy((void *)&user_stats->ack_ba, ptr, + sizeof(struct htt_ppdu_stats_usr_cmpltn_ack_ba_status)); ++ ppdu_info->ppdu_id = FIELD_GET(HTT_PPDU_STATS_PPDU_ID, ppdu_id); + user_stats->tlv_flags |= BIT(tag); + break; + case HTT_PPDU_STATS_TAG_USR_COMMON: diff --git a/feeds/ipq95xx/mac80211/patches/qca/371-ath11k-Fix-the-wrong-regdomain-update-for-KR-country.patch b/feeds/ipq95xx/mac80211/patches/qca/371-ath11k-Fix-the-wrong-regdomain-update-for-KR-country.patch new file mode 100644 index 000000000..c38df51fb --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/371-ath11k-Fix-the-wrong-regdomain-update-for-KR-country.patch @@ -0,0 +1,36 @@ +From 328f8dd44fdadbd17d910705f105f7ecae6969bd Mon Sep 17 00:00:00 2001 +From: Karthik M +Date: Mon, 17 Apr 2023 17:22:39 +0530 +Subject: [PATCH] ath11k: Fix the wrong regdomain update for KR country + +KR country should follow JP regulatory domain instead it +was assigned ETSI domain wrongly. + +This issue got exposed after the change +5dbddc3d4ac ("cfg80211: precac check for self-managed wiphy") +got merged. + +Signed-off-by: Karthik M +--- + drivers/net/wireless/ath/ath11k/reg.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath11k/reg.c b/drivers/net/wireless/ath/ath11k/reg.c +index 2926553..0a3aaef 100644 +--- a/drivers/net/wireless/ath/ath11k/reg.c ++++ b/drivers/net/wireless/ath/ath11k/reg.c +@@ -231,10 +231,10 @@ ath11k_map_fw_dfs_region(enum ath11k_dfs_region dfs_region) + case ATH11K_DFS_REG_CN: + return NL80211_DFS_FCC; + case ATH11K_DFS_REG_ETSI: +- case ATH11K_DFS_REG_KR: + return NL80211_DFS_ETSI; + case ATH11K_DFS_REG_MKK: + case ATH11K_DFS_REG_MKK_N: ++ case ATH11K_DFS_REG_KR: + return NL80211_DFS_JP; + default: + return NL80211_DFS_UNSET; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/372-ath11k-Add-Rate-table-for-peer-tx-stats.patch b/feeds/ipq95xx/mac80211/patches/qca/372-ath11k-Add-Rate-table-for-peer-tx-stats.patch new file mode 100644 index 000000000..c5bc61d1a --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/372-ath11k-Add-Rate-table-for-peer-tx-stats.patch @@ -0,0 +1,174 @@ +From bdbbf6f502a02517510c433f318a34c176d6a560 Mon Sep 17 00:00:00 2001 +From: Maharaja Kennadyrajan +Date: Tue, 18 Apr 2023 23:10:32 +0530 +Subject: [PATCH 3/3] ath11k: Add Rate table for peer tx stats + +Add the rate table for peer tx stats which helps to +provide the number of packets transmitted in the +particular rate for success, failure, retry and ampdu +packets. +Also added the tx bytes in the rate table to get the +success, failure, retry and ampdu bytes in the +particular rate. + +Output: +Rate table packets : + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 4 0 0 4 + 0 0 4 0 0 0 0 0 + 5 0 0 5 0 0 5 0 + 0 0 0 0 5 0 0 17 + 0 0 200 0 0 0 0 0 + 5 0 0 12 0 0 1730 0 + 0 0 0 0 38 0 0 5 + 0 0 2428 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 + +Validated that total number of success packets in the rate code +table is matching with the total number of success packets in +NSS or BW or VHT MCS packets. + +Signed-off-by: Maharaja Kennadyrajan +Signed-off-by: Tamizh Chelvam Raja +--- + drivers/net/wireless/ath/ath11k/core.h | 2 ++ + drivers/net/wireless/ath/ath11k/debugfs_sta.c | 36 +++++++++++++++++-- + drivers/net/wireless/ath/ath11k/mac.c | 6 ++-- + 3 files changed, 40 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -63,6 +63,7 @@ extern struct mutex dev_init_lock; + #define ATH11K_CONNECTION_LOSS_HZ (3 * HZ) + #define ATH11K_RX_RATE_TABLE_NUM 320 + #define ATH11K_RX_RATE_TABLE_11AX_NUM 576 ++#define ATH11K_TX_RATE_TABLE_11AX_NUM 576 + + #define QCN6122_USERPD_0 1 + #define QCN6122_USERPD_1 2 +@@ -611,6 +612,7 @@ struct ath11k_htt_data_stats { + u64 gi[ATH11K_COUNTER_TYPE_MAX][ATH11K_GI_NUM]; + u64 transmit_type[ATH11K_COUNTER_TYPE_MAX][HAL_RX_RECEPTION_TYPE_MAX]; + u64 ru_loc[ATH11K_COUNTER_TYPE_MAX][HAL_RX_RU_ALLOC_TYPE_MAX]; ++ u64 rate_table[ATH11K_COUNTER_TYPE_MAX][ATH11K_TX_RATE_TABLE_11AX_NUM]; + }; + + struct ath11k_wbm_tx_stats { +--- a/drivers/net/wireless/ath/ath11k/debugfs_sta.c ++++ b/drivers/net/wireless/ath/ath11k/debugfs_sta.c +@@ -45,7 +45,8 @@ void ath11k_debugfs_sta_add_tx_stats(str + { + struct rate_info *txrate = &arsta->txrate; + struct ath11k_htt_tx_stats *tx_stats; +- int gi, mcs, bw, nss, ru_type, ppdu_type; ++ int gi, mcs, bw, nss, ru_type, ppdu_type, idx; ++ u8 he_gi; + + if (!arsta->tx_stats) + return; +@@ -56,6 +57,10 @@ void ath11k_debugfs_sta_add_tx_stats(str + bw = ath11k_mac_mac80211_bw_to_ath11k_bw(txrate->bw); + nss = txrate->nss - 1; + ++ he_gi = ath11k_he_gi_to_nl80211_he_gi(gi); ++ idx = mcs * 12 + 12 * 12 * nss; ++ idx += bw * 3 + he_gi; ++ + #define STATS_OP_FMT(name) tx_stats->stats[ATH11K_STATS_TYPE_##name] + + if (txrate->flags & RATE_INFO_FLAGS_HE_MCS) { +@@ -152,12 +157,16 @@ void ath11k_debugfs_sta_add_tx_stats(str + peer_stats->succ_bytes + peer_stats->retry_bytes; + STATS_OP_FMT(AMPDU).gi[0][gi] += + peer_stats->succ_bytes + peer_stats->retry_bytes; ++ STATS_OP_FMT(AMPDU).rate_table[0][idx] += ++ peer_stats->succ_bytes + peer_stats->retry_bytes; + STATS_OP_FMT(AMPDU).bw[1][bw] += + peer_stats->succ_pkts + peer_stats->retry_pkts; + STATS_OP_FMT(AMPDU).nss[1][nss] += + peer_stats->succ_pkts + peer_stats->retry_pkts; + STATS_OP_FMT(AMPDU).gi[1][gi] += + peer_stats->succ_pkts + peer_stats->retry_pkts; ++ STATS_OP_FMT(AMPDU).rate_table[1][idx] += ++ peer_stats->succ_pkts + peer_stats->retry_pkts; + } else { + tx_stats->ack_fails += peer_stats->ba_fails; + } +@@ -186,6 +195,15 @@ void ath11k_debugfs_sta_add_tx_stats(str + STATS_OP_FMT(RETRY).nss[1][nss] += peer_stats->retry_pkts; + STATS_OP_FMT(RETRY).gi[1][gi] += peer_stats->retry_pkts; + ++ if (txrate->flags >= RATE_INFO_FLAGS_MCS) { ++ STATS_OP_FMT(SUCC).rate_table[0][idx] += peer_stats->succ_bytes; ++ STATS_OP_FMT(SUCC).rate_table[1][idx] += peer_stats->succ_pkts; ++ STATS_OP_FMT(FAIL).rate_table[0][idx] += peer_stats->failed_bytes; ++ STATS_OP_FMT(FAIL).rate_table[1][idx] += peer_stats->failed_pkts; ++ STATS_OP_FMT(RETRY).rate_table[0][idx] += peer_stats->retry_bytes; ++ STATS_OP_FMT(RETRY).rate_table[1][idx] += peer_stats->retry_pkts; ++ } ++ + tx_stats->tx_duration += peer_stats->duration; + + tx_stats->ru_start = peer_stats->ru_start; +@@ -206,6 +224,8 @@ void ath11k_debugfs_sta_update_txcompl(s + ath11k_dp_tx_update_txcompl(ar, ts); + } + ++#define STR_PKTS_BYTES ((strstr(str[j], "packets")) ? "packets" : "bytes") ++ + static ssize_t ath11k_dbg_sta_dump_tx_stats(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +@@ -218,7 +238,7 @@ static ssize_t ath11k_dbg_sta_dump_tx_st + "retry", "ampdu"}; + static const char *str[ATH11K_COUNTER_TYPE_MAX] = {"bytes", "packets"}; + int len = 0, i, j, k, retval = 0; +- const int size = 2 * 4096; ++ const int size = 16 * 4096; + char *buf, mu_group_id[MAX_MU_GROUP_LENGTH] = {0}; + u32 index; + char *fields[] = {[HAL_WBM_REL_HTT_TX_COMP_STATUS_OK] = "Acked pkt count", +@@ -297,6 +317,18 @@ static ssize_t ath11k_dbg_sta_dump_tx_st + len += scnprintf(buf + len, size - len, "%llu ", + stats->legacy[j][i]); + ++ len += scnprintf(buf + len, size - len, ++ "\nRate table %s :\n", ++ STR_PKTS_BYTES); ++ for (i = 0; i < ATH11K_TX_RATE_TABLE_11AX_NUM; i++) { ++ len += scnprintf(buf + len, size - len, ++ "\t%llu", ++ stats->rate_table[j][i]); ++ if (!((i + 1) % 8)) ++ len += ++ scnprintf(buf + len, size - len, "\n"); ++ } ++ len += scnprintf(buf + len, size - len, "\n"); + len += scnprintf(buf + len, size - len, "\n ru %s: \n", str[j]); + len += scnprintf(buf + len, size - len, + "\tru 26: %llu\n", stats->ru_loc[j][0]); diff --git a/feeds/ipq95xx/mac80211/patches/qca/373-ath11k-Add-retry-mechanism-for-update_rx_qu.patch b/feeds/ipq95xx/mac80211/patches/qca/373-ath11k-Add-retry-mechanism-for-update_rx_qu.patch new file mode 100644 index 000000000..a7ccdb053 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/373-ath11k-Add-retry-mechanism-for-update_rx_qu.patch @@ -0,0 +1,398 @@ +From 17d1895bad45ec2ef4c8c430ac0fbaff2ff1cf39 Mon Sep 17 00:00:00 2001 +From: Manish Dharanenthiran +Date: Tue, 18 Apr 2023 15:01:42 +0530 +Subject: [PATCH 2/3] CHROMIUM: ath11k: Add retry mechanism for update_rx_queue + reo cmd + +While reo_cmd ring is full, peer delete update rx queue +will be failed as there is no space to send the command +in ring. During the failure scenario, host will do +dma_unmap and free the allocated address but the HW +still have that particular vaddr. So, on next alloc +cycle kernel will allocated the freed addr but HW will +still have the address. This will result in memory +corruption as the host will try to access/write that +memory which is already in-use. + +To avoid this corruption, added new retry mechanism +for HAL_REO_CMD_UPDATE_RX_QUEUE by adding new list to +dp struct and protecting with new lock for access. +This avoids the host free in failure case and will +be freed only when HW freed that particular vaddr. + +Also, updated below changes +1) reo_flush command for sending 1K desc in one +command instead of sending 11 command for single +TID. + +2) Set FWD_MPDU and valid bit flag so that reo +flush will happen soon instead of waiting to +flush the queue. + +Signed-off-by: Manish Dharanenthiran +Signed-off-by: Tamizh Chelvam Raja +--- + drivers/net/wireless/ath/ath11k/core.h | 3 + + drivers/net/wireless/ath/ath11k/debugfs.c | 12 ++ + drivers/net/wireless/ath/ath11k/dp.c | 2 + + drivers/net/wireless/ath/ath11k/dp.h | 15 ++ + drivers/net/wireless/ath/ath11k/dp_rx.c | 167 +++++++++++++++++----- + 5 files changed, 161 insertions(+), 38 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h +index e543442..180d102 100644 +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -1170,6 +1170,9 @@ struct ath11k_soc_dp_stats { + u32 reo_error[HAL_REO_DEST_RING_ERROR_CODE_MAX]; + u32 reo_error_drop[HAL_REO_DEST_RING_ERROR_CODE_MAX]; + u32 hal_reo_error[DP_REO_DST_RING_MAX]; ++ u32 hal_reo_cmd_drain; ++ u32 reo_cmd_cache_error; ++ u32 reo_cmd_update_rx_queue_error; + struct ath11k_soc_dp_tx_err_stats tx_err; + struct ath11k_dp_ring_bp_stats bp_stats; + }; +diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c +index 44a4e5a..ef23de2 100644 +--- a/drivers/net/wireless/ath/ath11k/debugfs.c ++++ b/drivers/net/wireless/ath/ath11k/debugfs.c +@@ -1566,6 +1566,18 @@ static ssize_t ath11k_debugfs_dump_soc_dp_stats(struct file *file, + "\nNSS Transmit Failures: %d\n", + atomic_read(&soc_stats->tx_err.nss_tx_fail)); + ++ len += scnprintf(buf + len, size - len, ++ "\nHAL_REO_CMD_DRAIN Counter: %u\n", ++ soc_stats->hal_reo_cmd_drain); ++ ++ len += scnprintf(buf + len, size - len, ++ "\nREO_CMD_CACHE_FLUSH Failure: %u\n", ++ soc_stats->reo_cmd_cache_error); ++ ++ len += scnprintf(buf + len, size - len, ++ "\nREO_CMD_UPDATE_RX_QUEUE Failure: %u\n", ++ soc_stats->reo_cmd_update_rx_queue_error); ++ + len += ath11k_debugfs_dump_soc_ring_bp_stats(ab, buf + len, size - len); + + if (len > size) +diff --git a/drivers/net/wireless/ath/ath11k/dp.c b/drivers/net/wireless/ath/ath11k/dp.c +index 38c2cee..2e5f1a1 100644 +--- a/drivers/net/wireless/ath/ath11k/dp.c ++++ b/drivers/net/wireless/ath/ath11k/dp.c +@@ -1127,8 +1127,10 @@ int ath11k_dp_alloc(struct ath11k_base *ab) + + INIT_LIST_HEAD(&dp->reo_cmd_list); + INIT_LIST_HEAD(&dp->reo_cmd_cache_flush_list); ++ INIT_LIST_HEAD(&dp->reo_cmd_update_rx_queue_list); + INIT_LIST_HEAD(&dp->dp_full_mon_mpdu_list); + spin_lock_init(&dp->reo_cmd_lock); ++ spin_lock_init(&dp->reo_cmd_update_queue_lock); + + dp->reo_cmd_cache_flush_count = 0; + +diff --git a/drivers/net/wireless/ath/ath11k/dp.h b/drivers/net/wireless/ath/ath11k/dp.h +index 46873f4..8e192b1 100644 +--- a/drivers/net/wireless/ath/ath11k/dp.h ++++ b/drivers/net/wireless/ath/ath11k/dp.h +@@ -23,6 +23,7 @@ struct dp_rx_tid { + u32 *vaddr; + dma_addr_t paddr; + u32 size; ++ u32 pending_desc_size; + u32 ba_win_sz; + bool active; + +@@ -50,6 +51,14 @@ struct dp_reo_cache_flush_elem { + unsigned long ts; + }; + ++struct dp_reo_update_rx_queue_elem { ++ struct list_head list; ++ struct dp_rx_tid data; ++ int peer_id; ++ u8 tid; ++ bool reo_cmd_update_rx_queue_resend_flag; ++}; ++ + struct dp_reo_cmd { + struct list_head list; + struct dp_rx_tid data; +@@ -292,6 +301,12 @@ struct ath11k_dp { + * - reo_cmd_cache_flush_count + */ + spinlock_t reo_cmd_lock; ++ struct list_head reo_cmd_update_rx_queue_list; ++ /** ++ * protects access to below field, ++ * - reo_cmd_update_rx_queue_list ++ */ ++ spinlock_t reo_cmd_update_queue_lock; + struct ath11k_hp_update_timer reo_cmd_timer; + struct ath11k_hp_update_timer tx_ring_timer[DP_TCL_NUM_RING_MAX]; + }; +diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c +index df16e1f..62f823d 100644 +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -22,6 +22,9 @@ + + #define ATH11K_DP_RX_FRAGMENT_TIMEOUT_MS (2 * HZ) + ++static void ath11k_dp_rx_tid_del_func(struct ath11k_dp *dp, void *ctx, ++ enum hal_reo_cmd_status status); ++ + static inline + u8 *ath11k_dp_rx_h_80211_hdr(struct ath11k_base *ab, struct hal_rx_desc *desc) + { +@@ -729,13 +732,50 @@ static int ath11k_dp_rx_pdev_srng_alloc(struct ath11k *ar) + return 0; + } + ++static int ath11k_peer_rx_tid_delete_handler(struct ath11k_base *ab, ++ struct dp_rx_tid *rx_tid, u8 tid) ++{ ++ struct ath11k_hal_reo_cmd cmd = {0}; ++ struct ath11k_dp *dp = &ab->dp; ++ ++ lockdep_assert_held(&dp->reo_cmd_update_queue_lock); ++ ++ rx_tid->active = false; ++ cmd.flag = HAL_REO_CMD_FLG_NEED_STATUS; ++ cmd.addr_lo = lower_32_bits(rx_tid->paddr); ++ cmd.addr_hi = upper_32_bits(rx_tid->paddr); ++ cmd.upd0 |= HAL_REO_CMD_UPD0_VLD; ++ ++ return ath11k_dp_tx_send_reo_cmd(ab, rx_tid, ++ HAL_REO_CMD_UPDATE_RX_QUEUE, ++ &cmd, ++ ath11k_dp_rx_tid_del_func); ++} ++ + void ath11k_dp_reo_cmd_list_cleanup(struct ath11k_base *ab) + { + struct ath11k_dp *dp = &ab->dp; + struct dp_reo_cmd *cmd, *tmp; + struct dp_reo_cache_flush_elem *cmd_cache, *tmp_cache; ++ struct dp_reo_update_rx_queue_elem *cmd_queue, *tmp_queue; + struct dp_rx_tid *rx_tid; + ++ spin_lock_bh(&dp->reo_cmd_update_queue_lock); ++ list_for_each_entry_safe(cmd_queue, tmp_queue, ++ &dp->reo_cmd_update_rx_queue_list, ++ list) { ++ list_del(&cmd_queue->list); ++ rx_tid = &cmd_queue->data; ++ if (rx_tid->vaddr) { ++ dma_unmap_single(ab->dev, rx_tid->paddr, ++ rx_tid->size, DMA_BIDIRECTIONAL); ++ kfree(rx_tid->vaddr); ++ rx_tid->vaddr = NULL; ++ } ++ kfree(cmd_queue); ++ } ++ spin_unlock_bh(&dp->reo_cmd_update_queue_lock); ++ + spin_lock_bh(&dp->reo_cmd_lock); + list_for_each_entry_safe(cmd, tmp, &dp->reo_cmd_list, list) { + list_del(&cmd->list); +@@ -782,14 +822,18 @@ static void ath11k_dp_reo_cmd_free(struct ath11k_dp *dp, void *ctx, + } + } + +-static void ath11k_dp_reo_cache_flush(struct ath11k_base *ab, ++static int ath11k_dp_reo_cache_flush(struct ath11k_base *ab, + struct dp_rx_tid *rx_tid) + { + struct ath11k_hal_reo_cmd cmd = {0}; + unsigned long tot_desc_sz, desc_sz; + int ret; + +- tot_desc_sz = rx_tid->size; ++ if (rx_tid->pending_desc_size) ++ tot_desc_sz = rx_tid->pending_desc_size; ++ else ++ tot_desc_sz = rx_tid->size; ++ + desc_sz = ath11k_hal_reo_qdesc_size(0, HAL_DESC_REO_NON_QOS_TID); + + while (tot_desc_sz > desc_sz) { +@@ -800,11 +844,17 @@ static void ath11k_dp_reo_cache_flush(struct ath11k_base *ab, + HAL_REO_CMD_FLUSH_CACHE, &cmd, + NULL); + if (ret) +- ath11k_warn(ab, +- "failed to send HAL_REO_CMD_FLUSH_CACHE, tid %d (%d)\n", +- rx_tid->tid, ret); ++ rx_tid->pending_desc_size = tot_desc_sz + desc_sz; ++ ++ /* If this fails with ring full condition, then ++ * no need to retry below as it is expected to ++ * fail within short time ++ */ ++ if (ret == -ENOBUFS) ++ goto exit; + } + ++ rx_tid->pending_desc_size = desc_sz; + memset(&cmd, 0, sizeof(cmd)); + cmd.addr_lo = lower_32_bits(rx_tid->paddr); + cmd.addr_hi = upper_32_bits(rx_tid->paddr); +@@ -812,24 +862,21 @@ static void ath11k_dp_reo_cache_flush(struct ath11k_base *ab, + ret = ath11k_dp_tx_send_reo_cmd(ab, rx_tid, + HAL_REO_CMD_FLUSH_CACHE, + &cmd, ath11k_dp_reo_cmd_free); +- if (ret) { +- ath11k_err(ab, "failed to send HAL_REO_CMD_FLUSH_CACHE cmd, tid %d (%d)\n", +- rx_tid->tid, ret); +- dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size, +- DMA_BIDIRECTIONAL); +- kfree(rx_tid->vaddr); +- rx_tid->vaddr = NULL; +- } ++ ++exit: ++ return ret; + } + + static void ath11k_dp_rx_tid_del_func(struct ath11k_dp *dp, void *ctx, + enum hal_reo_cmd_status status) + { + struct ath11k_base *ab = dp->ab; +- struct dp_rx_tid *rx_tid = ctx; ++ struct dp_rx_tid *rx_tid = ctx, *update_rx_tid; + struct dp_reo_cache_flush_elem *elem, *tmp; ++ struct dp_reo_update_rx_queue_elem *qelem, *qtmp; + + if (status == HAL_REO_CMD_DRAIN) { ++ ab->soc_stats.hal_reo_cmd_drain++; + goto free_desc; + } else if (status != HAL_REO_CMD_SUCCESS) { + /* Shouldn't happen! Cleanup in case of other failure? */ +@@ -838,6 +885,29 @@ static void ath11k_dp_rx_tid_del_func(struct ath11k_dp *dp, void *ctx, + return; + } + ++ /* Check if there is any pending rx_queue, if yes then update it */ ++ spin_lock_bh(&dp->reo_cmd_update_queue_lock); ++ list_for_each_entry_safe(qelem, qtmp, &dp->reo_cmd_update_rx_queue_list, ++ list) { ++ if (qelem->reo_cmd_update_rx_queue_resend_flag && ++ qelem->data.active) { ++ update_rx_tid = &qelem->data; ++ ++ if (ath11k_peer_rx_tid_delete_handler(ab, update_rx_tid, qelem->tid)) { ++ update_rx_tid->active = true; ++ break; ++ } ++ update_rx_tid->vaddr = NULL; ++ update_rx_tid->paddr = 0; ++ update_rx_tid->size = 0; ++ update_rx_tid->pending_desc_size = 0; ++ ++ list_del(&qelem->list); ++ kfree(qelem); ++ } ++ } ++ spin_unlock_bh(&dp->reo_cmd_update_queue_lock); ++ + elem = kzalloc(sizeof(*elem), GFP_ATOMIC); + if (!elem) { + ath11k_warn(ab, "failed to alloc reo_cache_flush_elem, rx tid %d\n", +@@ -858,13 +928,20 @@ static void ath11k_dp_rx_tid_del_func(struct ath11k_dp *dp, void *ctx, + if (dp->reo_cmd_cache_flush_count > DP_REO_DESC_FREE_THRESHOLD || + time_after(jiffies, elem->ts + + msecs_to_jiffies(DP_REO_DESC_FREE_TIMEOUT_MS))) { ++ spin_unlock_bh(&dp->reo_cmd_lock); ++ if (ath11k_dp_reo_cache_flush(ab, &elem->data)) { ++ ab->soc_stats.reo_cmd_cache_error++; ++ /* In failure case, just update the timestamp ++ * for flush cache elem and continue ++ */ ++ spin_lock_bh(&dp->reo_cmd_lock); ++ elem->ts = jiffies; ++ break; ++ } ++ spin_lock_bh(&dp->reo_cmd_lock); + list_del(&elem->list); + dp->reo_cmd_cache_flush_count--; +- spin_unlock_bh(&dp->reo_cmd_lock); +- +- ath11k_dp_reo_cache_flush(ab, &elem->data); + kfree(elem); +- spin_lock_bh(&dp->reo_cmd_lock); + } + } + spin_unlock_bh(&dp->reo_cmd_lock); +@@ -880,34 +957,48 @@ free_desc: + void ath11k_peer_rx_tid_delete(struct ath11k *ar, + struct ath11k_peer *peer, u8 tid) + { +- struct ath11k_hal_reo_cmd cmd = {0}; + struct dp_rx_tid *rx_tid = &peer->rx_tid[tid]; +- int ret; ++ struct dp_reo_update_rx_queue_elem *elem, *tmp; ++ struct ath11k_base *ab = ar->ab; ++ struct ath11k_dp *dp = &ab->dp; + + if (!rx_tid->active) + return; + +- rx_tid->active = false; ++ elem = kzalloc(sizeof(*elem), GFP_ATOMIC); ++ if (!elem) { ++ ath11k_warn(ar->ab, "failed to alloc reo_update_rx_queue_elem, rx tid %d\n", ++ rx_tid->tid); ++ return; ++ } ++ elem->reo_cmd_update_rx_queue_resend_flag = false; ++ elem->peer_id = peer->peer_id; ++ elem->tid = tid; ++ memcpy(&elem->data, rx_tid, sizeof(*rx_tid)); ++ spin_lock_bh(&dp->reo_cmd_update_queue_lock); ++ list_add_tail(&elem->list, &dp->reo_cmd_update_rx_queue_list); + +- cmd.flag = HAL_REO_CMD_FLG_NEED_STATUS; +- cmd.addr_lo = lower_32_bits(rx_tid->paddr); +- cmd.addr_hi = upper_32_bits(rx_tid->paddr); +- cmd.upd0 |= HAL_REO_CMD_UPD0_VLD; +- ret = ath11k_dp_tx_send_reo_cmd(ar->ab, rx_tid, +- HAL_REO_CMD_UPDATE_RX_QUEUE, &cmd, +- ath11k_dp_rx_tid_del_func); +- if (ret) { +- if (ret != -ESHUTDOWN) +- ath11k_err(ar->ab, "failed to send HAL_REO_CMD_UPDATE_RX_QUEUE cmd, tid %d (%d)\n", +- tid, ret); +- dma_unmap_single(ar->ab->dev, rx_tid->paddr, rx_tid->size, +- DMA_BIDIRECTIONAL); +- kfree(rx_tid->vaddr); ++ list_for_each_entry_safe(elem, tmp, &dp->reo_cmd_update_rx_queue_list, ++ list) { ++ rx_tid = &elem->data; ++ ++ if (ath11k_peer_rx_tid_delete_handler(ab, rx_tid, elem->tid)) { ++ rx_tid->active = true; ++ ab->soc_stats.reo_cmd_update_rx_queue_error++; ++ elem->reo_cmd_update_rx_queue_resend_flag = true; ++ break; ++ } ++ rx_tid->vaddr = NULL; ++ rx_tid->paddr = 0; ++ rx_tid->size = 0; ++ rx_tid->pending_desc_size = 0; ++ ++ list_del(&elem->list); ++ kfree(elem); + } ++ spin_unlock_bh(&dp->reo_cmd_update_queue_lock); + +- rx_tid->vaddr = NULL; +- rx_tid->paddr = 0; +- rx_tid->size = 0; ++ return; + } + + static int ath11k_dp_rx_link_desc_return(struct ath11k_base *ab, +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/374-ath11k-Check-skb_headroom-before-using-skb_push.patc b/feeds/ipq95xx/mac80211/patches/qca/374-ath11k-Check-skb_headroom-before-using-skb_push.patc new file mode 100644 index 000000000..6993680dc --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/374-ath11k-Check-skb_headroom-before-using-skb_push.patc @@ -0,0 +1,244 @@ +From efecc6e8355d02aeac7bf1a43397551440a8d0d8 Mon Sep 17 00:00:00 2001 +From: Tamizh Chelvam Raja +Date: Thu, 30 Mar 2023 22:12:56 +0530 +Subject: [PATCH] ath11k: Check skb_headroom before using skb_push + +Below kernel panic may occur if there is no +skb_headroom available for performing skb_push. + +<4>[67506.565072] CPU: 1 PID: 1741 Comm: ap-wireless-opt Not tainted 5.4.89+ #0 +<4>[67506.578860] Hardware name: Generic DT based system +<4>[67506.585728] PC is at fortify_panic+0x10/0x18 +<4>[67506.590406] LR is at fortify_panic+0x10/0x18 + +(fortify_panic) from [<7f2cd3cc>] (ath11k_dp_rx_crypto_icv_len+0x1e0/0x161c [ath11k]) +(ath11k_dp_rx_crypto_icv_len [ath11k]) from [<7f2cdbac>] (ath11k_dp_rx_crypto_icv_len+0x9c0/0x161c [ath11k]) +(ath11k_dp_rx_crypto_icv_len [ath11k]) from [<7f2ce0e8>] (ath11k_dp_rx_crypto_icv_len+0xefc/0x161c [ath11k]) +(ath11k_dp_rx_crypto_icv_len [ath11k]) from [<7f2cedb0>] (ath11k_dp_process_rx+0x4ec/0x544 [ath11k]) +(ath11k_dp_process_rx [ath11k]) from [<7f2c417c>] (ath11k_dp_service_srng+0xdc/0x2a0 [ath11k]) +(ath11k_dp_service_srng [ath11k]) from [<7f0d78c8>] (ath11k_pci_ext_grp_napi_poll+0x20/0x50 [ath11k_pci]) +(ath11k_pci_ext_grp_napi_poll [ath11k_pci]) from [<806a6a74>] (__napi_poll+0x28/0xb8) +(__napi_poll) from [<806a6c9c>] (net_rx_action+0xec/0x280) +(net_rx_action) from [<8010226c>] (__do_softirq+0xc4/0x248) +(__do_softirq) from [<8011f230>] (irq_exit+0x6c/0xcc) +(irq_exit) from [<80162a08>] (__handle_domain_irq+0x8c/0xb0) +(__handle_domain_irq) from [<803f0188>] (gic_handle_irq+0x54/0x8c) +(gic_handle_irq) from [<80101a8c>] (__irq_svc+0x6c/0xa8) + +Fix this by checking skb_headroom and expand the +headroom if required size is not available. + +Signed-off-by: Tamizh Chelvam Raja +--- + drivers/net/wireless/ath/ath11k/dp_rx.c | 70 +++++++++++++++++++++++++ + 1 file changed, 70 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -2478,16 +2478,27 @@ static void ath11k_get_dot11_hdr_from_rx + size_t hdr_len, crypto_len; + struct ieee80211_hdr *hdr; + u16 fc, qos_ctl = 0; ++ int expand_by; + u8 *crypto_hdr; + + if (!(status->flag & RX_FLAG_IV_STRIPPED)) { + crypto_len = ath11k_dp_rx_crypto_param_len(ar, enctype); ++ if (skb_headroom(msdu) < crypto_len) { ++ expand_by = crypto_len - skb_headroom(msdu); ++ if (WARN_ON_ONCE(pskb_expand_head(msdu, expand_by, 0, GFP_ATOMIC))) ++ return; ++ } + crypto_hdr = skb_push(msdu, crypto_len); + ath11k_dp_rx_desc_get_crypto_header(ab, rx_desc, crypto_hdr, enctype); + } + + fc = ath11k_dp_rxdesc_get_mpdu_frame_ctrl(ab, rx_desc); + hdr_len = ieee80211_hdrlen(fc); ++ if (skb_headroom(msdu) < hdr_len) { ++ expand_by = hdr_len - skb_headroom(msdu); ++ if (WARN_ON_ONCE(pskb_expand_head(msdu, expand_by, 0, GFP_ATOMIC))) ++ return; ++ } + skb_push(msdu, hdr_len); + hdr = (struct ieee80211_hdr *)msdu->data; + hdr->frame_control = fc; +@@ -2523,6 +2534,7 @@ static void ath11k_dp_rx_h_undecap_nwifi + u8 da[ETH_ALEN]; + u8 sa[ETH_ALEN]; + u16 qos_ctl = 0; ++ int expand_by = 0; + u8 *qos, *crypto_hdr; + bool add_qos_ctrl = false; + +@@ -2567,26 +2579,46 @@ static void ath11k_dp_rx_h_undecap_nwifi + } + + if (!(status->flag & RX_FLAG_IV_STRIPPED)) { ++ int crypto_param_len = ath11k_dp_rx_crypto_param_len(ar, enctype); ++ ++ if (skb_headroom(msdu) < crypto_param_len) { ++ expand_by = crypto_param_len - skb_headroom(msdu); ++ if (WARN_ON_ONCE(pskb_expand_head(msdu, expand_by, 0, GFP_ATOMIC))) ++ return; ++ } + if (first_hdr) { +- memcpy(skb_push(msdu, +- ath11k_dp_rx_crypto_param_len(ar, enctype)), +- (void *)hdr + hdr_len, +- ath11k_dp_rx_crypto_param_len(ar, enctype)); ++ memcpy(skb_push(msdu, crypto_param_len), ++ (void *)hdr + hdr_len, crypto_param_len); + } else { +- crypto_hdr = skb_push(msdu, ath11k_dp_rx_crypto_param_len(ar, enctype)); ++ crypto_hdr = skb_push(msdu, crypto_param_len); + ath11k_dp_rx_desc_get_crypto_header(ar->ab, + rxcb->rx_desc, crypto_hdr, enctype); + } + } + + if (!rxcb->is_first_msdu || add_qos_ctrl) { ++ if (skb_headroom(msdu) < IEEE80211_QOS_CTL_LEN) { ++ expand_by = IEEE80211_QOS_CTL_LEN - skb_headroom(msdu); ++ if (WARN_ON_ONCE(pskb_expand_head(msdu, expand_by, 0, GFP_ATOMIC))) ++ return; ++ } + memcpy(skb_push(msdu, + IEEE80211_QOS_CTL_LEN), &qos_ctl, + IEEE80211_QOS_CTL_LEN); ++ if (skb_headroom(msdu) < hdr_len) { ++ expand_by = hdr_len - skb_headroom(msdu); ++ if (WARN_ON_ONCE(pskb_expand_head(msdu, expand_by, 0, GFP_ATOMIC))) ++ return; ++ } + memcpy(skb_push(msdu, hdr_len), decap_hdr, hdr_len); + return; + } + ++ if (skb_headroom(msdu) < hdr_len) { ++ expand_by = hdr_len - skb_headroom(msdu); ++ if (WARN_ON_ONCE(pskb_expand_head(msdu, expand_by, 0, GFP_ATOMIC))) ++ return; ++ } + memcpy(skb_push(msdu, hdr_len), hdr, hdr_len); + + /* original 802.11 header has a different DA and in +@@ -2695,6 +2727,7 @@ static void ath11k_dp_rx_h_undecap_eth(s + u8 da[ETH_ALEN]; + u8 sa[ETH_ALEN]; + void *rfc1042; ++ int expand_by; + struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(msdu); + struct ath11k_dp_rfc1042_hdr rfc = {0xaa, 0xaa, 0x03, {0x00, 0x00, 0x00}}; + +@@ -2704,6 +2737,11 @@ static void ath11k_dp_rx_h_undecap_eth(s + ether_addr_copy(sa, eth->h_source); + rfc.snap_type = eth->h_proto; + skb_pull(msdu, sizeof(struct ethhdr)); ++ if (skb_headroom(msdu) < sizeof(struct ath11k_dp_rfc1042_hdr)) { ++ expand_by = sizeof(struct ath11k_dp_rfc1042_hdr) - skb_headroom(msdu); ++ if (WARN_ON_ONCE(pskb_expand_head(msdu, expand_by, 0, GFP_ATOMIC))) ++ return; ++ } + memcpy(skb_push(msdu, sizeof(struct ath11k_dp_rfc1042_hdr)), &rfc, + sizeof(struct ath11k_dp_rfc1042_hdr)); + ath11k_get_dot11_hdr_from_rx_desc(ar, msdu, rxcb, status, enctype); +@@ -2721,6 +2759,11 @@ static void ath11k_dp_rx_h_undecap_eth(s + skb_pull(msdu, sizeof(struct ethhdr)); + + /* push rfc1042/llc/snap */ ++ if (skb_headroom(msdu) < sizeof(struct ath11k_dp_rfc1042_hdr)) { ++ expand_by = sizeof(struct ath11k_dp_rfc1042_hdr) - skb_headroom(msdu); ++ if (WARN_ON_ONCE(pskb_expand_head(msdu, expand_by, 0, GFP_ATOMIC))) ++ return; ++ } + memcpy(skb_push(msdu, sizeof(struct ath11k_dp_rfc1042_hdr)), rfc1042, + sizeof(struct ath11k_dp_rfc1042_hdr)); + +@@ -2729,12 +2772,22 @@ static void ath11k_dp_rx_h_undecap_eth(s + hdr_len = ieee80211_hdrlen(hdr->frame_control); + + if (!(status->flag & RX_FLAG_IV_STRIPPED)) { +- memcpy(skb_push(msdu, +- ath11k_dp_rx_crypto_param_len(ar, enctype)), +- (void *)hdr + hdr_len, +- ath11k_dp_rx_crypto_param_len(ar, enctype)); ++ int crypto_param_len = ath11k_dp_rx_crypto_param_len(ar, enctype); ++ ++ if (skb_headroom(msdu) < crypto_param_len) { ++ expand_by = crypto_param_len - skb_headroom(msdu); ++ if (WARN_ON_ONCE(pskb_expand_head(msdu, expand_by, 0, GFP_ATOMIC))) ++ return; ++ } ++ memcpy(skb_push(msdu, crypto_param_len), ++ (void *)hdr + hdr_len, crypto_param_len); + } + ++ if (skb_headroom(msdu) < hdr_len) { ++ expand_by = hdr_len - skb_headroom(msdu); ++ if (WARN_ON_ONCE(pskb_expand_head(msdu, expand_by, 0, GFP_ATOMIC))) ++ return; ++ } + memcpy(skb_push(msdu, hdr_len), hdr, hdr_len); + + exit: +@@ -2755,6 +2808,7 @@ static void ath11k_dp_rx_h_undecap_snap( + struct ieee80211_hdr *hdr; + size_t hdr_len; + u8 l3_pad_bytes; ++ int expand_by; + struct hal_rx_desc *rx_desc; + struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(msdu); + +@@ -2779,12 +2833,22 @@ static void ath11k_dp_rx_h_undecap_snap( + hdr_len = ieee80211_hdrlen(hdr->frame_control); + + if (!(status->flag & RX_FLAG_IV_STRIPPED)) { +- memcpy(skb_push(msdu, +- ath11k_dp_rx_crypto_param_len(ar, enctype)), +- (void *)hdr + hdr_len, +- ath11k_dp_rx_crypto_param_len(ar, enctype)); ++ int crypto_param_len = ath11k_dp_rx_crypto_param_len(ar, enctype); ++ ++ if (skb_headroom(msdu) < crypto_param_len) { ++ expand_by = crypto_param_len - skb_headroom(msdu); ++ if (WARN_ON_ONCE(pskb_expand_head(msdu, expand_by, 0, GFP_ATOMIC))) ++ return; ++ } ++ memcpy(skb_push(msdu, crypto_param_len), ++ (void *)hdr + hdr_len, crypto_param_len); + } + ++ if (skb_headroom(msdu) < hdr_len) { ++ expand_by = hdr_len - skb_headroom(msdu); ++ if (WARN_ON_ONCE(pskb_expand_head(msdu, expand_by, 0, GFP_ATOMIC))) ++ return; ++ } + memcpy(skb_push(msdu, hdr_len), hdr, hdr_len); + } + +@@ -3177,10 +3241,16 @@ static void ath11k_dp_rx_deliver_msdu(st + u8 decap = DP_RX_DECAP_TYPE_RAW; + bool is_mcbc = rxcb->is_mcbc; + bool is_eapol = rxcb->is_eapol; ++ int expand_by; + + if (status->encoding == RX_ENC_HE && + !(status->flag & RX_FLAG_RADIOTAP_HE) && + !(status->flag & RX_FLAG_SKIP_MONITOR)) { ++ if (skb_headroom(msdu) < sizeof(known)) { ++ expand_by = sizeof(known) - skb_headroom(msdu); ++ if (WARN_ON_ONCE(pskb_expand_head(msdu, expand_by, 0, GFP_ATOMIC))) ++ goto exit; ++ } + he = skb_push(msdu, sizeof(known)); + memcpy(he, &known, sizeof(known)); + status->flag |= RX_FLAG_RADIOTAP_HE; +@@ -3236,6 +3306,7 @@ static void ath11k_dp_rx_deliver_msdu(st + !(is_mcbc && rx_status->flag & RX_FLAG_DECRYPTED)) + rx_status->flag |= RX_FLAG_8023; + ++exit: + ieee80211_rx_napi(ar->hw, pubsta, msdu, napi); + + if (ath11k_debugfs_is_extd_rx_stats_enabled(ar)) { diff --git a/feeds/ipq95xx/mac80211/patches/qca/374-ath11k-fix-VLC-streaming-not-working-for-wan-to-wlan.patch b/feeds/ipq95xx/mac80211/patches/qca/374-ath11k-fix-VLC-streaming-not-working-for-wan-to-wlan.patch new file mode 100644 index 000000000..144d5a9ca --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/374-ath11k-fix-VLC-streaming-not-working-for-wan-to-wlan.patch @@ -0,0 +1,49 @@ +From c9bcb26f30a1b2e3434d851aea19200a6d757cca Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Sat, 3 Jun 2023 18:33:54 +0530 +Subject: [PATCH] ath11k: fix VLC streaming not working for wan to wlan when + multicast to unicast flag enable + +Currently, additional two bytes after 802.11 header are seen on the air. +When per-packet encap mode is native wifi and vdev level encap mode is +eth mode, native wifi encap functionality is skipped. + +This leaves QoS header unremoved in the 802.11 header of the packet. When +sending the packet HW will also add (one more) QoS header. The additional +two bytes before LLC/SNAP header confuses the receiver and those packets +will get dropped at receiver. + +Fix this issue by removing QoS header (native wifi encap functionality) +for all the packets which will be enqueued to hw in native wifi mode. + +Signed-off-by: Aaradhana Sahu +--- + drivers/net/wireless/ath/ath11k/dp_tx.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c +index 3d8417d..5c034e6 100644 +--- a/drivers/net/wireless/ath/ath11k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_tx.c +@@ -347,7 +347,8 @@ tcl_ring_sel: + + switch (ti.encap_type) { + case HAL_TCL_ENCAP_TYPE_NATIVE_WIFI: +- if (arvif->vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED) ++ if ((arvif->vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED) && ++ skb->protocol == cpu_to_be16(ETH_P_PAE)) + is_diff_encap = true; + else + ath11k_dp_tx_encap_nwifi(skb); +@@ -375,7 +376,7 @@ tcl_ring_sel: + if ((!test_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags) && + !(info->control.flags & IEEE80211_TX_CTL_HW_80211_ENCAP) && + !info->control.hw_key && ieee80211_has_protected(hdr->frame_control)) || +- (skb->protocol == cpu_to_be16(ETH_P_PAE) && is_diff_encap)) { ++ is_diff_encap) { + /* HW requirement is that metadata should always point to a + * 8-byte aligned address. So we add alignment pad to start of + * buffer. HTT Metadata should be ensured to be multiple of 8-bytes +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/375-001-mac80211-add-Radio-Measurement-Action-field-values.patch b/feeds/ipq95xx/mac80211/patches/qca/375-001-mac80211-add-Radio-Measurement-Action-field-values.patch new file mode 100644 index 000000000..f0089bf55 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/375-001-mac80211-add-Radio-Measurement-Action-field-values.patch @@ -0,0 +1,42 @@ +From 3f970049cb3a463df1065e273a577344539d7e36 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Tue, 23 May 2023 17:49:29 +0530 +Subject: [PATCH] mac80211: add Radio Measurement Action field values + +Drivers which supports Tx power insertion will have to look +into the outgoing Radio Measurement packet. And based on the +type, driver will fill certain data in it. These values will +aid drivers in classifying the action code inside the +Radio Measurement action packet. + +Hence, add Radio Measurement Action field values + +Signed-off-by: Aditya Kumar Singh +--- + include/linux/ieee80211.h | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h +index d7ef538b5094..e6e0547ba058 100644 +--- a/include/linux/ieee80211.h ++++ b/include/linux/ieee80211.h +@@ -3530,6 +3530,16 @@ enum ieee80211_spectrum_mgmt_actioncode { + WLAN_ACTION_SPCT_CHL_SWITCH = 4, + }; + ++/* RADIO_MEASUREMENT action code */ ++enum ieee80211_radio_measurement_actioncode { ++ WLAN_ACTION_RADIO_MSR_RM_REQ = 0, ++ WLAN_ACTION_RADIO_MSR_RM_REP = 1, ++ WLAN_ACTION_RADIO_MSR_LINK_MSR_REQ = 2, ++ WLAN_ACTION_RADIO_MSR_LINK_MSR_REP = 3, ++ WLAN_ACTION_RADIO_MSR_NBOR_REP_REQ = 4, ++ WLAN_ACTION_RADIO_MSR_NBOR_REP_REP = 5, ++}; ++ + /* HT action codes */ + enum ieee80211_ht_actioncode { + WLAN_HT_ACTION_NOTIFY_CHANWIDTH = 0, +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/375-ath11k-add-support-for-Tx-Power-insertion.patch b/feeds/ipq95xx/mac80211/patches/qca/375-ath11k-add-support-for-Tx-Power-insertion.patch new file mode 100644 index 000000000..653a68856 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/375-ath11k-add-support-for-Tx-Power-insertion.patch @@ -0,0 +1,223 @@ +From 5e151f46e89e10b9a5ccab3943283392f93538b6 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Mon, 22 May 2023 11:05:35 +0530 +Subject: [PATCH 1/2] ath11k: add support for Tx Power insertion + +For certain action frames like the TPC Report IE in the spectrum management +TPC Report action frame, and in the Radio Measurement Link Measurement +Report action frame there is a requirement to fill in the current +and Max Tx power of the device in the packet. + +Add support to fill in these in the above packets. Driver advertises this +capability support via NL80211_FEATURE_TX_POWER_INSERTION feature flag. + +For software encrypted case, PMF packets will be encrypted already hence +driver can't add value in this particular case. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath11k/mac.c | 166 ++++++++++++++++++++++++++ + drivers/net/wireless/ath/ath11k/mac.h | 3 + + 2 files changed, 169 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -261,6 +261,8 @@ static const u32 ath11k_smps_map[] = { + + static int ath11k_start_vdev_delay(struct ieee80211_hw *hw, + struct ieee80211_vif *vif); ++static int ath11k_fw_stats_request(struct ath11k *ar, ++ struct stats_request_params *req_param); + + enum nl80211_he_ru_alloc ath11k_mac_phy_he_ru_to_nl80211_he_ru_alloc(u16 ru_phy) + { +@@ -7321,6 +7323,159 @@ static void ath11k_mgmt_over_wmi_tx_purg + ath11k_mgmt_over_wmi_tx_drop(ar, skb); + } + ++static int ath11k_mac_mgmt_action_frame_fill_elem(struct ath11k_vif *arvif, ++ struct sk_buff *skb) ++{ ++ struct ath11k *ar = arvif->ar; ++ struct ath11k_skb_cb *skb_cb; ++ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; ++ struct ieee80211_mgmt *mgmt; ++ struct ieee80211_bss_conf *bss_conf = &arvif->vif->bss_conf; ++ struct stats_request_params req_param; ++ struct ath11k_fw_stats_pdev *pdev; ++ int ret, cur_tx_power, max_tx_power; ++ bool has_protected; ++ u8 category, *buf, iv_len; ++ u8 action_code, dialog_token; ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ /* make sure category field is present */ ++ if (skb->len < IEEE80211_MIN_ACTION_SIZE) ++ return -EINVAL; ++ ++ has_protected = ieee80211_has_protected(hdr->frame_control); ++ ++ /* SW_CRYPTO and hdr protected case (PMF), packet will be encrypted, ++ * we can't put in data ++ */ ++ if (test_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags) && ++ has_protected) ++ return -EOPNOTSUPP; ++ ++ mgmt = (struct ieee80211_mgmt *)hdr; ++ buf = &mgmt->u.action; ++ ++ /* FCTL_PROTECTED frame might have extra space added for HDR_LEN. Offset that ++ * many bytes if it is there ++ */ ++ if (has_protected) { ++ skb_cb = ATH11K_SKB_CB(skb); ++ ++ switch (skb_cb->cipher) { ++ /* Currently only for CCMP cipher suite, we asked for it via ++ * setting %IEEE80211_KEY_FLAG_GENERATE_IV_MGMT in key. Check ++ * ath11k_install_key() ++ */ ++ case WLAN_CIPHER_SUITE_CCMP: ++ iv_len = IEEE80211_CCMP_HDR_LEN; ++ break; ++ case WLAN_CIPHER_SUITE_TKIP: ++ case WLAN_CIPHER_SUITE_CCMP_256: ++ case WLAN_CIPHER_SUITE_GCMP: ++ case WLAN_CIPHER_SUITE_GCMP_256: ++ iv_len = 0; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ buf = buf + iv_len; ++ } ++ ++ category = *buf++; ++ ++ switch (category) { ++ case WLAN_CATEGORY_RADIO_MEASUREMENT: ++ /* Packet Format: ++ * Action Code | Dialog Token | Variable Len (based on Action Code) ++ */ ++ action_code = *buf++; ++ dialog_token = *buf++; ++ ++ cur_tx_power = bss_conf->txpower; ++ max_tx_power = min(bss_conf->chanctx_conf->def.chan->max_reg_power, ++ (int)ar->max_tx_power / 2); ++ ++ /* fetch current tx power from FW pdev stats */ ++ req_param.pdev_id = ar->pdev->pdev_id; ++ req_param.vdev_id = 0; ++ req_param.stats_id = WMI_REQUEST_PDEV_STAT; ++ ++ ret = ath11k_fw_stats_request(ar, &req_param); ++ if (ret) { ++ ath11k_warn(ar->ab, "failed to request fw pdev stats: %d\n", ret); ++ goto check_rm_action_frame; ++ } ++ ++ spin_lock_bh(&ar->data_lock); ++ pdev = list_first_entry_or_null(&ar->fw_stats_pdevs, ++ struct ath11k_fw_stats_pdev, ++ list); ++ if (!pdev) { ++ spin_unlock_bh(&ar->data_lock); ++ goto check_rm_action_frame; ++ } ++ ++ /* Tx power is set as 2 units per dBm in FW. */ ++ cur_tx_power = pdev->chan_tx_power / 2; ++ spin_unlock_bh(&ar->data_lock); ++ ++check_rm_action_frame: ++ switch (action_code) { ++ case WLAN_ACTION_RADIO_MSR_LINK_MSR_REQ: ++ /* Variable Len Format: ++ * Transmit Power | Max Tx Power ++ * We fill both of these. ++ */ ++ *buf++ = cur_tx_power; ++ *buf = max_tx_power; ++ ++ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, ++ "RRM: Link Measurement Req dialog_token=%u, cur_tx_power=%d, max_tx_power=%d\n", ++ dialog_token, cur_tx_power, max_tx_power); ++ break; ++ case WLAN_ACTION_RADIO_MSR_LINK_MSR_REP: ++ /* Variable Len Format: ++ * TPC Report | Variable Fields ++ * ++ * TPC Report Format: ++ * Element ID | Len | Tx Power | Link Margin ++ * ++ * We fill Tx power in the TPC Report (2nd index) ++ */ ++ buf[2] = cur_tx_power; ++ ++ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, ++ "RRM: Link Measurement Resp dialog_token=%u, cur_tx_power=%d\n", ++ dialog_token, cur_tx_power); ++ break; ++ default: ++ return -EINVAL; ++ } ++ break; ++ default: ++ /* nothing to fill */ ++ return 0; ++ } ++ ++ return 0; ++} ++ ++static int ath11k_mac_mgmt_frame_fill_elem(struct ath11k_vif *arvif, ++ struct sk_buff *skb) ++{ ++ struct ath11k *ar = arvif->ar; ++ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ if (!ieee80211_is_action(hdr->frame_control)) ++ return 0; ++ ++ return ath11k_mac_mgmt_action_frame_fill_elem(arvif, skb); ++} ++ + static void ath11k_mgmt_over_wmi_tx_work(struct work_struct *work) + { + struct ath11k *ar = container_of(work, struct ath11k, wmi_mgmt_tx_work); +@@ -7340,6 +7495,20 @@ static void ath11k_mgmt_over_wmi_tx_work + arvif = ath11k_vif_to_arvif(skb_cb->vif); + mutex_lock(&ar->conf_mutex); + if (ar->allocated_vdev_map & (1LL << arvif->vdev_id)) { ++ /* Fill the data which is required to be filled in by the driver ++ * Example: Max Tx power in Link Measurement Request/Report ++ */ ++ ret = ath11k_mac_mgmt_frame_fill_elem(arvif, skb); ++ if (ret) { ++ /* If we couldn't fill the data due to any reason, let's not discard ++ * transmitting the packet. ++ * For ex: SW crypto and PMF case ++ */ ++ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, ++ "Cant't fill in the required data for the mgmt packet. err=%d\n", ++ ret); ++ } ++ + ret = ath11k_mac_mgmt_tx_wmi(ar, arvif, skb); + if (ret) { + ath11k_warn(ar->ab, "failed to tx mgmt frame, vdev_id %d :%d\n", +@@ -12739,6 +12908,8 @@ static int __ath11k_mac_register(struct + ar->hw->wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE | + NL80211_FEATURE_AP_SCAN; + ++ ar->hw->wiphy->features |= NL80211_FEATURE_TX_POWER_INSERTION; ++ + ar->max_num_stations = TARGET_NUM_STATIONS(ab); + ar->max_num_peers = TARGET_NUM_PEERS_PDEV(ab); + diff --git a/feeds/ipq95xx/mac80211/patches/qca/376-ath11k-Add-nss-event-handler-support-for-link-desc.patch b/feeds/ipq95xx/mac80211/patches/qca/376-ath11k-Add-nss-event-handler-support-for-link-desc.patch new file mode 100644 index 000000000..c9a4595e7 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/376-ath11k-Add-nss-event-handler-support-for-link-desc.patch @@ -0,0 +1,73 @@ +From 69356d5f6947c8a6182e1c6283478ad40c6df37b Mon Sep 17 00:00:00 2001 +From: Tamizh Chelvam Raja +Date: Wed, 21 Jun 2023 20:26:02 +0530 +Subject: [PATCH] ath11k: Add nss event handler support for link desc + +Add NSS event handler support for NSS_WIFILI_LINK_DESC_INFO_MSG. +This event will be given to host from NSS for releasing +link descriptor which used for fragmentation. This needs to be +handled to release the link descriptor back to hardware for +other usage. + +Signed-off-by: Tamizh Chelvam Raja +--- + drivers/net/wireless/ath/ath11k/nss.c | 43 +++++++++++++++++++++++++++ + 1 file changed, 43 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/nss.c ++++ b/drivers/net/wireless/ath/ath11k/nss.c +@@ -100,6 +100,43 @@ static void ath11k_nss_wifili_stats_sync + spin_unlock_bh(&ab->base_lock); + } + ++static void ath11k_nss_wifili_link_desc_set(struct ath11k_base *ab, void *desc, ++ struct ath11k_buffer_addr *buf_addr_info, ++ enum hal_wbm_rel_bm_act action) ++{ ++ struct hal_wbm_release_ring *dst_desc = desc; ++ ++ dst_desc->buf_addr_info = *buf_addr_info; ++ dst_desc->info0 |= FIELD_PREP(HAL_WBM_RELEASE_INFO0_REL_SRC_MODULE, ++ HAL_WBM_REL_SRC_MODULE_SW) | ++ FIELD_PREP(HAL_WBM_RELEASE_INFO0_BM_ACTION, action) | ++ FIELD_PREP(HAL_WBM_RELEASE_INFO0_DESC_TYPE, ++ HAL_WBM_REL_DESC_TYPE_MSDU_LINK); ++} ++ ++static void ath11k_nss_wifili_link_desc_return(struct ath11k_base *ab, ++ struct ath11k_buffer_addr *buf_addr_info) ++{ ++ struct ath11k_dp *dp = &ab->dp; ++ struct hal_srng *srng; ++ u32 *desc; ++ ++ srng = &ab->hal.srng_list[dp->wbm_desc_rel_ring.ring_id]; ++ spin_lock_bh(&srng->lock); ++ ++ ath11k_hal_srng_access_begin(ab, srng); ++ desc = ath11k_hal_srng_src_get_next_entry(ab, srng); ++ ++ if (!desc) ++ goto exit; ++ ++ ath11k_nss_wifili_link_desc_set(ab, desc, buf_addr_info, HAL_WBM_REL_BM_ACT_PUT_IN_IDLE); ++ ++exit: ++ ath11k_hal_srng_access_end(ab, srng); ++ spin_unlock(&srng->lock); ++} ++ + static void ath11k_nss_get_peer_stats(struct ath11k_base *ab, struct nss_wifili_peer_stats *stats) + { + struct ath11k_peer *peer; +@@ -370,6 +407,10 @@ void ath11k_nss_wifili_event_receive(str + ath11k_dbg(ab, ATH11K_DBG_NSS_MESH, "nss wifili mesh capability response %d\n", + ab->nss.mesh_nss_offload_enabled); + break; ++ case NSS_WIFILI_LINK_DESC_INFO_MSG: ++ ath11k_nss_wifili_link_desc_return(ab, ++ (void *)&msg->msg.linkdescinfomsg); ++ break; + default: + ath11k_dbg(ab, ATH11K_DBG_NSS, "unhandled event %d\n", msg_type); + break; diff --git a/feeds/ipq95xx/mac80211/patches/qca/376-ath11k-restrict-user-country-setting-during-active-v.patch b/feeds/ipq95xx/mac80211/patches/qca/376-ath11k-restrict-user-country-setting-during-active-v.patch new file mode 100644 index 000000000..cbbf7c8db --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/376-ath11k-restrict-user-country-setting-during-active-v.patch @@ -0,0 +1,82 @@ +From 78dbca67245e027093a22cc8a9131e142ba3984c Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Fri, 23 Jun 2023 10:13:07 +0530 +Subject: [PATCH] ath11k: restrict user country setting during active vdev + +Currently, if user wants, country setting can be changed on the fly after +the interface(s) have started beaconing. However, hostapd ignores this regulatory +change event since according to its state, it did not ask for it. This leads +to interfaces which were already active continue beaconing with same old data +which is wrong. + +Since there is no potential usecase of changing regulatory on the fly, hence +add change to restrict changing country setting if any of the vdev in it is +active. + +Also since regulatory applies to whole SOC, restrict this further to not allow +if any of pdev on a SOC is having an active vdev. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath11k/reg.c | 38 +++++++++++++++++++++++++++ + 1 file changed, 38 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath11k/reg.c b/drivers/net/wireless/ath/ath11k/reg.c +index 0a3aaef30957..17a837733cd8 100644 +--- a/drivers/net/wireless/ath/ath11k/reg.c ++++ b/drivers/net/wireless/ath/ath11k/reg.c +@@ -43,6 +43,37 @@ static bool ath11k_regdom_changes(struct ath11k *ar, char *alpha2) + return memcmp(regd->alpha2, alpha2, 2) != 0; + } + ++static bool ath11k_reg_validate_pdev_state(struct ath11k *ar) ++{ ++ struct ath11k_base *ab = ar->ab; ++ struct ath11k_pdev *pdev; ++ struct ath11k *tmp_ar; ++ int i; ++ ++ rcu_read_lock(); ++ for (i = 0; i < ab->num_radios; i++) { ++ pdev = rcu_dereference(ab->pdevs_active[i]); ++ if (!pdev) ++ continue; ++ ++ tmp_ar = pdev->ar; ++ if (tmp_ar) { ++ mutex_lock(&tmp_ar->conf_mutex); ++ if (tmp_ar->num_started_vdevs) { ++ if (tmp_ar == ar) ++ ath11k_warn(ab, "%s has active interface, please bring down to set country code", ++ wiphy_name(ar->hw->wiphy)); ++ mutex_unlock(&tmp_ar->conf_mutex); ++ rcu_read_unlock(); ++ return false; ++ } ++ mutex_unlock(&tmp_ar->conf_mutex); ++ } ++ } ++ rcu_read_unlock(); ++ return true; ++} ++ + static void + ath11k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) + { +@@ -77,6 +108,13 @@ ath11k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) + return; + } + ++ /* The SET_INIT_COUNTRY command should not be sent to firmware while any vdev is active. ++ * Also it does not make sense to give the command for certain pdev's alone. ++ * Hence check all the pdev's if any have an active vdev before sending the command. ++ */ ++ if (!ath11k_reg_validate_pdev_state(ar)) ++ return; ++ + /* Set the country code to the firmware and will receive + * the WMI_REG_CHAN_LIST_CC EVENT for updating the + * reg info +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/377-ath11k-power-save-support-during-interface-down.patch b/feeds/ipq95xx/mac80211/patches/qca/377-ath11k-power-save-support-during-interface-down.patch new file mode 100644 index 000000000..e44266454 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/377-ath11k-power-save-support-during-interface-down.patch @@ -0,0 +1,246 @@ +From c451697a64426e33b6002e35572e7d369afb82f2 Mon Sep 17 00:00:00 2001 +From: Tamizh Chelvam Raja +Date: Wed, 26 Jul 2023 08:49:14 +0530 +Subject: [PATCH] ath11k: power save support during interface down + +When all interface down target expects WMI_PDEV_SUSPEND command +to enable power save in the hardware. + +Signed-off-by: Tamizh Chelvam Raja +--- + drivers/net/wireless/ath/ath11k/core.c | 71 ++++++++++++++++++-------- + drivers/net/wireless/ath/ath11k/core.h | 3 ++ + drivers/net/wireless/ath/ath11k/mac.c | 32 ++++++++++-- + drivers/net/wireless/ath/ath11k/qmi.c | 3 +- + 4 files changed, 83 insertions(+), 26 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -1579,9 +1579,30 @@ success: + return 0; + } + ++int ath11k_wait_for_suspend(struct ath11k *ar, u32 suspend_opt) ++{ ++ int ret; ++ unsigned long time_left; ++ ++ ret = ath11k_wmi_pdev_suspend(ar, suspend_opt, ar->pdev->pdev_id); ++ if (ret) { ++ ath11k_warn(ar->ab, "failed to suspend target (%d)\n", ret); ++ return ret; ++ } ++ ++ time_left = wait_for_completion_timeout(&ar->ab->htc_suspend, ATH11K_PM_TIMEOUT); ++ ++ if (!time_left) { ++ ath11k_warn(ar->ab, "suspend time out - target pause event never came\n"); ++ return -ETIMEDOUT; ++ } ++ ++ return ret; ++} ++ + static void ath11k_core_stop(struct ath11k_base *ab) + { +- if (!test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags)) ++ if (!test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags) && !ab->pm_suspend) + ath11k_qmi_firmware_stop(ab); + + ath11k_hif_stop(ab); +@@ -1651,16 +1672,18 @@ static int ath11k_core_pdev_create(struc + goto err_pdev_debug; + } + +- ret = ath11k_nss_setup(ab); +- if (ret) { +- ath11k_err(ab, "failed to setup nss driver interface%d", ret); +- goto err_dp_pdev_free; +- } ++ if (!ab->pm_suspend) { ++ ret = ath11k_nss_setup(ab); ++ if (ret) { ++ ath11k_err(ab, "failed to setup nss driver interface%d", ret); ++ goto err_dp_pdev_free; ++ } + +- ret = ath11k_mac_register(ab); +- if (ret) { +- ath11k_err(ab, "failed register the radio with mac80211: %d\n", ret); +- goto err_nss_tear; ++ ret = ath11k_mac_register(ab); ++ if (ret) { ++ ath11k_err(ab, "failed register the radio with mac80211: %d\n", ret); ++ goto err_nss_tear; ++ } + } + + ret = ath11k_thermal_register(ab); +@@ -1768,11 +1791,13 @@ static int ath11k_core_start(struct ath1 + goto err_hif_stop; + } + +- ret = ath11k_mac_allocate(ab); +- if (ret) { +- ath11k_err(ab, "failed to create new hw device with mac80211 :%d\n", +- ret); +- goto err_hif_stop; ++ if (!ab->pm_suspend) { ++ ret = ath11k_mac_allocate(ab); ++ if (ret) { ++ ath11k_err(ab, "failed to create new hw device with mac80211 :%d\n", ++ ret); ++ goto err_hif_stop; ++ } + } + + ath11k_dp_pdev_pre_alloc(ab); +@@ -2166,7 +2191,7 @@ static void ath11k_core_pre_reconfigure_ + pdev = &ab->pdevs[i]; + ar = pdev->ar; + if (!ar || ar->state == ATH11K_STATE_OFF || +- ar->state == ATH11K_STATE_TM) ++ ar->state == ATH11K_STATE_TM || ab->pm_suspend) + continue; + + list_for_each_entry(arvif, &ar->arvifs, list) +@@ -2224,7 +2249,8 @@ static void ath11k_core_post_reconfigure + case ATH11K_STATE_ON: + ar->state = ATH11K_STATE_RESTARTING; + ath11k_core_halt(ar); +- ieee80211_restart_hw(ar->hw); ++ if (!ab->pm_suspend) ++ ieee80211_restart_hw(ar->hw); + break; + case ATH11K_STATE_OFF: + ath11k_warn(ab, +@@ -2268,6 +2294,9 @@ static void ath11k_core_restart(struct w + + if (!ab->is_reset) + ath11k_core_post_reconfigure_recovery(ab); ++ ++ if (ab->pm_suspend) ++ complete(&ab->pm_restart); + } + + static void ath11k_core_reset(struct work_struct *work) +@@ -2421,7 +2450,9 @@ void ath11k_core_deinit(struct ath11k_ba + + mutex_unlock(&ab->core_lock); + +- ath11k_hif_power_down(ab); ++ if (!ab->pm_suspend) ++ ath11k_hif_power_down(ab); ++ + ath11k_mac_destroy(ab); + ath11k_core_soc_destroy(ab); + +@@ -2473,6 +2504,7 @@ struct ath11k_base *ath11k_core_alloc(st + init_completion(&ab->reset_complete); + init_completion(&ab->reconfigure_complete); + init_completion(&ab->recovery_start); ++ init_completion(&ab->pm_restart); + + INIT_LIST_HEAD(&ab->peers); + INIT_LIST_HEAD(&ab->neighbor_peers); +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -1410,6 +1410,8 @@ struct ath11k_base { + struct mutex base_ast_lock; + struct work_struct wmi_ast_work; + struct list_head wmi_ast_list; ++ struct completion pm_restart; ++ bool pm_suspend; + + /* must be last */ + u8 drv_priv[] __aligned(sizeof(void *)); +@@ -1643,6 +1645,7 @@ int ath11k_coredump_mhi_update_bhie_tabl + phys_addr_t pa, size_t size); + const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab, + const char *filename); ++int ath11k_wait_for_suspend(struct ath11k *ar, u32 suspend_opt); + void ath11k_core_wait_dump_collect(struct ath11k_base *ab); + + static inline const char *ath11k_scan_state_str(enum ath11k_scan_state state) +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -7784,6 +7784,22 @@ static int ath11k_mac_op_start(struct ie + + switch (ar->state) { + case ATH11K_STATE_OFF: ++ if (ab->pm_suspend) { ++ mutex_unlock(&ar->conf_mutex); ++ ath11k_hif_power_up(ab); ++ ++ if (!wait_for_completion_timeout(&ab->pm_restart, ++ ATH11K_PM_RESTART_TIMEOUT)) { ++ ath11k_warn(ar->ab, ++ "Timeout in receiving for pm restart\n"); ++ ar->state = ATH11K_STATE_OFF; ++ return -ETIMEDOUT; ++ } ++ ++ mutex_lock(&ar->conf_mutex); ++ ab->pm_suspend = false; ++ } ++ + ar->state = ATH11K_STATE_ON; + break; + case ATH11K_STATE_RESTARTING: +@@ -7959,8 +7975,18 @@ static void ath11k_mac_op_stop(struct ie + ret); + + clear_bit(ATH11K_CAC_RUNNING, &ar->dev_flags); +- ar->state = ATH11K_STATE_OFF; +- ar->ap_ps_state = ATH11K_AP_PS_STATE_OFF; ++ if (ar->state != ATH11K_STATE_OFF) { ++ ath11k_wait_for_suspend(ar, WMI_PDEV_SUSPEND_AND_DISABLE_INTR); ++ ++ if (!test_bit(ATH11K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags)) ++ ath11k_qmi_firmware_stop(ar->ab); ++ ++ ath11k_hif_power_down(ar->ab); ++ ath11k_qmi_free_resource(ar->ab); ++ ar->ab->pm_suspend = true; ++ ar->state = ATH11K_STATE_OFF; ++ ar->ap_ps_state = ATH11K_AP_PS_STATE_OFF; ++ } + mutex_unlock(&ar->conf_mutex); + + cancel_delayed_work_sync(&ar->scan.timeout); +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -4838,7 +4838,8 @@ static void ath11k_qmi_driver_event_work + case ATH11K_QMI_EVENT_FW_READY: + clear_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags); + if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)) { +- ath11k_hal_dump_srng_stats(ab); ++ if (!ab->pm_suspend) ++ ath11k_hal_dump_srng_stats(ab); + queue_work(ab->workqueue, &ab->restart_work); + break; + } +--- a/drivers/net/wireless/ath/ath11k/pci.c ++++ b/drivers/net/wireless/ath/ath11k/pci.c +@@ -979,7 +979,8 @@ static void ath11k_pci_shutdown(struct p + struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); + + ath11k_pci_set_irq_affinity_hint(ab_pci, NULL); +- ath11k_pci_power_down(ab); ++ if (!ab->pm_suspend) ++ ath11k_pci_power_down(ab); + } + + static __maybe_unused int ath11k_pci_pm_suspend(struct device *dev) +--- a/drivers/net/wireless/ath/ath11k/mac.h ++++ b/drivers/net/wireless/ath/ath11k/mac.h +@@ -126,6 +126,9 @@ struct ath11k_generic_iter { + #define ATH11K_OBSS_PD_SRG_EN BIT(30) + #define ATH11K_OBSS_PD_NON_SRG_EN BIT(31) + ++#define ATH11K_PM_TIMEOUT (3 * HZ) ++#define ATH11K_PM_RESTART_TIMEOUT (10 * HZ) ++ + extern const struct htt_rx_ring_tlv_filter ath11k_mac_mon_status_filter_default; + + #define ATH11K_SCAN_11D_INTERVAL 600000 diff --git a/feeds/ipq95xx/mac80211/patches/qca/380-mac80211-fix-compilation-issues-with-pkg-upgrd.patch b/feeds/ipq95xx/mac80211/patches/qca/380-mac80211-fix-compilation-issues-with-pkg-upgrd.patch new file mode 100644 index 000000000..3e951db4c --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/380-mac80211-fix-compilation-issues-with-pkg-upgrd.patch @@ -0,0 +1,66 @@ +From ae444bf877fd94256a110d03582ddb045c541525 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Wed, 24 Aug 2022 09:25:31 -0800 +Subject: [PATCH] mac80211: fix compilation issues with Pkg Upgrd + +Signed-off-by: Aditya Kumar Singh +--- + net/wireless/nl80211.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -540,10 +540,12 @@ static struct ieee80211_key * + ieee80211_lookup_key(struct ieee80211_sub_if_data *sdata, + u8 key_idx, bool pairwise, const u8 *mac_addr) + { +- struct ieee80211_local *local = sdata->local; ++ struct ieee80211_local *local; + struct ieee80211_key *key; + struct sta_info *sta; + ++ local = sdata->local; ++ + if (mac_addr) { + sta = sta_info_get_bss(sdata, mac_addr); + if (!sta) +--- a/drivers/net/wireless/ath/ath12k/mhi.c ++++ b/drivers/net/wireless/ath/ath12k/mhi.c +@@ -365,7 +365,9 @@ int ath12k_mhi_register(struct ath12k_pc + mhi_ctrl->cntrl_dev = ab->dev; + mhi_ctrl->fw_image = ab_pci->amss_path; + mhi_ctrl->regs = ab->mem; ++#if LINUX_VERSION_IS_GEQ(5,10,0) + mhi_ctrl->reg_len = ab->mem_len; ++#endif + + ret = ath12k_mhi_get_msi(ab_pci); + if (ret) { +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -666,7 +666,11 @@ static int ath12k_pci_msi_alloc(struct a + } + + ab_pci->msi_ep_base_data = msi_desc->msg.data; ++#if LINUX_VERSION_IS_GEQ(5,10,0) + if (msi_desc->pci.msi_attrib.is_64) ++#else ++ if (msi_desc->msi_attrib.is_64) ++#endif + set_bit(ATH12K_PCI_FLAG_IS_MSI_64, &ab_pci->flags); + + ath12k_dbg(ab, ATH12K_DBG_PCI, "msi base data is %d\n", ab_pci->msi_ep_base_data); +--- a/drivers/net/wireless/ath/ath11k/pci.c ++++ b/drivers/net/wireless/ath/ath11k/pci.c +@@ -441,7 +441,11 @@ static int ath11k_pci_alloc_msi(struct a + pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_LO, + &ab->pci.msi.addr_lo); + ++#if LINUX_VERSION_IS_GEQ(5,10,0) + if (msi_desc->pci.msi_attrib.is_64) { ++#else ++ if (msi_desc->msi_attrib.is_64) { ++#endif + pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_HI, + &ab->pci.msi.addr_hi); + } else { diff --git a/feeds/ipq95xx/mac80211/patches/qca/400-ath11k-fix-monitor-mode-bringup-crash.patch b/feeds/ipq95xx/mac80211/patches/qca/400-ath11k-fix-monitor-mode-bringup-crash.patch new file mode 100644 index 000000000..ba9ec95fd --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/400-ath11k-fix-monitor-mode-bringup-crash.patch @@ -0,0 +1,83 @@ +From 457cc85899be982b8f7238e37a11300de846ffac Mon Sep 17 00:00:00 2001 +From: Nagarajan Maran +Date: Tue, 14 Mar 2023 14:38:02 +0530 +Subject: [PATCH] wifi: ath11k: fix monitor mode bringup crash + +When the interface is brought up in monitor mode, it leads +to NULL pointer dereference crash. This crash happens when +the packet type is extracted for a SKB. This extraction +which is present in the received msdu delivery path,is +not needed for the monitor ring packets since they are +all RAW packets. Hence appending the flags with +"RX_FLAG_ONLY_MONITOR" to skip that extraction. + +Observed calltrace: + +Unable to handle kernel NULL pointer dereference at virtual address +0000000000000064 +Mem abort info: + ESR = 0x0000000096000004 + EC = 0x25: DABT (current EL), IL = 32 bits + SET = 0, FnV = 0 + EA = 0, S1PTW = 0 + FSC = 0x04: level 0 translation fault +Data abort info: + ISV = 0, ISS = 0x00000004 + CM = 0, WnR = 0 +user pgtable: 4k pages, 48-bit VAs, pgdp=0000000048517000 +[0000000000000064] pgd=0000000000000000, p4d=0000000000000000 +Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP +Modules linked in: ath11k_pci ath11k qmi_helpers +CPU: 2 PID: 1781 Comm: napi/-271 Not tainted +6.1.0-rc5-wt-ath-656295-gef907406320c-dirty #6 +Hardware name: Qualcomm Technologies, Inc. IPQ8074/AP-HK10-C2 (DT) +pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) +pc : ath11k_hw_qcn9074_rx_desc_get_decap_type+0x34/0x60 [ath11k] +lr : ath11k_hw_qcn9074_rx_desc_get_decap_type+0x5c/0x60 [ath11k] +sp : ffff80000ef5bb10 +x29: ffff80000ef5bb10 x28: 0000000000000000 x27: ffff000007baafa0 +x26: ffff000014a91ed0 x25: 0000000000000000 x24: 0000000000000000 +x23: ffff800002b77378 x22: ffff000014a91ec0 x21: ffff000006c8d600 +x20: 0000000000000000 x19: ffff800002b77740 x18: 0000000000000006 +x17: 736564203634343a x16: 656e694c20657079 x15: 0000000000000143 +x14: 00000000ffffffea x13: ffff80000ef5b8b8 x12: ffff80000ef5b8c8 +x11: ffff80000a591d30 x10: ffff80000a579d40 x9 : c0000000ffffefff +x8 : 0000000000000003 x7 : 0000000000017fe8 x6 : ffff80000a579ce8 +x5 : 0000000000000000 x4 : 0000000000000000 x3 : 0000000000000000 +x2 : 3a35ec12ed7f8900 x1 : 0000000000000000 x0 : 0000000000000052 +Call trace: + ath11k_hw_qcn9074_rx_desc_get_decap_type+0x34/0x60 [ath11k] + ath11k_dp_rx_deliver_msdu.isra.42+0xa4/0x3d0 [ath11k] + ath11k_dp_rx_mon_deliver.isra.43+0x2f8/0x458 [ath11k] + ath11k_dp_rx_process_mon_rings+0x310/0x4c0 [ath11k] + ath11k_dp_service_srng+0x234/0x338 [ath11k] + ath11k_pcic_ext_grp_napi_poll+0x30/0xb8 [ath11k] + __napi_poll+0x5c/0x190 + napi_threaded_poll+0xf0/0x118 + kthread+0xf4/0x110 + ret_from_fork+0x10/0x20 + +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 +Reported-by: Florian Schmidt +Link: https://bugzilla.kernel.org/show_bug.cgi?id=216573 +Signed-off-by: Nagarajan Maran +Signed-off-by: Rajat Soni +--- + drivers/net/wireless/ath/ath11k/dp_rx.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c +index 2160dbb..62a6370 100644 +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -6167,6 +6167,7 @@ static int ath11k_dp_rx_mon_deliver(struct ath11k *ar, u32 mac_id, + } else { + rxs->flag |= RX_FLAG_ALLOW_SAME_PN; + } ++ rxs->flag |= RX_FLAG_ONLY_MONITOR; + ath11k_update_radiotap(ar, ppduinfo, mon_skb, rxs); + + ath11k_dp_rx_deliver_msdu(ar, napi, mon_skb, rxs); +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/401-ath11k-Fix-mutex-dead-lock-and-q6-dump-crash.patch b/feeds/ipq95xx/mac80211/patches/qca/401-ath11k-Fix-mutex-dead-lock-and-q6-dump-crash.patch new file mode 100644 index 000000000..52116b5d7 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/401-ath11k-Fix-mutex-dead-lock-and-q6-dump-crash.patch @@ -0,0 +1,65 @@ +From 0a30d8c3d51d798b50bd792aa49e6a5b5ad14183 Mon Sep 17 00:00:00 2001 +From: Rajat Soni +Date: Wed, 12 Apr 2023 18:06:54 +0530 +Subject: [PATCH] ath11k: Fix mutex dead lock and q6 dump crash + +Issue 1: +Currently for HOST_DDR_REGION_TYPE memory, we are facing crash +because target memory virtual address (vaddr) is NULL. We are +not assigning any value to vaddr. + +Issue 2: +In ath11k_mac_op_start we are using mutex lock and waiting for +waiting for completion of ab->reconfigure_complete. +Before completing ab->reconfigure_complete in function +ath11k_core_reconfigure_on_crash, we are again trying +to get mutex lock in ath11k_spectral_deinit. This results +in dead lock. + +Due to these two issue during SSR case fw recovery pdev +is not recovered properly. + +To resolve these two issues: +Issue1: +During ath11k_qmi_assign_target_mem_chunk we should assign +ab->qmi.target_mem[idx].vaddr. + +Issue 2: +Unlock mutex lock before waiting for completion of +ab->reconfigure_complete and acquiring lock again. + +Signed-off-by: Rajat Soni +--- + drivers/net/wireless/ath/ath11k/mac.c | 2 ++ + drivers/net/wireless/ath/ath11k/qmi.c | 1 + + 2 files changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c +index c787bc3..0173870 100644 +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -7616,7 +7616,9 @@ static int ath11k_mac_op_start(struct ieee80211_hw *hw) + break; + case ATH11K_STATE_RESTARTING: + ar->state = ATH11K_STATE_RESTARTED; ++ mutex_unlock(&ar->conf_mutex); + ath11k_mac_wait_reconfigure(ab); ++ mutex_lock(&ar->conf_mutex); + break; + case ATH11K_STATE_RESTARTED: + case ATH11K_STATE_WEDGED: +diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c +index 6fc1159..e90c72b 100644 +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -2944,6 +2944,7 @@ static int ath11k_qmi_assign_target_mem_chunk(struct ath11k_base *ab) + ab->qmi.target_mem[idx].iaddr = + ioremap(ab->qmi.target_mem[idx].paddr, + ab->qmi.target_mem[i].size); ++ ab->qmi.target_mem[idx].vaddr = ab->qmi.target_mem[idx].iaddr; + ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size; + host_ddr_sz = ab->qmi.target_mem[i].size; + ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/451-ath11k-Higher-RAM-support-for-third-party-platforms.patch b/feeds/ipq95xx/mac80211/patches/qca/451-ath11k-Higher-RAM-support-for-third-party-platforms.patch new file mode 100644 index 000000000..bced256b4 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/451-ath11k-Higher-RAM-support-for-third-party-platforms.patch @@ -0,0 +1,110 @@ +From 6e3cbb6861a690649bf194d9227e7b5bef096cdc Mon Sep 17 00:00:00 2001 +From: Nagarajan Maran +Date: Wed, 15 Feb 2023 10:52:06 +0530 +Subject: [PATCH] ath11k: Higher RAM support for third party platforms. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Currently our 11ax WiFi hardware has the capability of +accessing upto (2^40) GB of RAM. However, our software both driver +and firmware are designed to access up to a highest of 4GB RAM +since RAM hasn’t exceeded 4GB capacity in our devices. + +This change addresses the issue of directly accessing greater than +4GB RAM from our WiFi chipset on third party platforms. + +Signed-off-by: Nagarajan Maran +--- + drivers/net/wireless/ath/ath11k/ce.h | 4 ++-- + drivers/net/wireless/ath/ath11k/dp.c | 2 +- + drivers/net/wireless/ath/ath11k/hal.c | 10 ++++++++++ + drivers/net/wireless/ath/ath11k/mhi.c | 2 +- + drivers/net/wireless/ath/ath11k/pci.c | 2 +- + 5 files changed, 15 insertions(+), 5 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/ce.h ++++ b/drivers/net/wireless/ath/ath11k/ce.h +@@ -141,7 +141,7 @@ struct ath11k_ce_ring { + /* Host address space */ + void *base_addr_owner_space_unaligned; + /* CE address space */ +- u32 base_addr_ce_space_unaligned; ++ dma_addr_t base_addr_ce_space_unaligned; + + /* Actual start of descriptors. + * Aligned to descriptor-size boundary. +@@ -151,7 +151,7 @@ struct ath11k_ce_ring { + void *base_addr_owner_space; + + /* CE address space */ +- u32 base_addr_ce_space; ++ dma_addr_t base_addr_ce_space; + + /* HAL ring id */ + u32 hal_ring_id; +--- a/drivers/net/wireless/ath/ath11k/dp.c ++++ b/drivers/net/wireless/ath/ath11k/dp.c +@@ -742,7 +742,7 @@ int ath11k_dp_link_desc_setup(struct ath + u32 tot_mem_sz; + u32 n_link_desc_bank, last_bank_sz; + u32 entry_sz, align_bytes, n_entries; +- u32 paddr; ++ dma_addr_t paddr; + u32 *desc; + int i, ret; + +--- a/drivers/net/wireless/ath/ath11k/hal.c ++++ b/drivers/net/wireless/ath/ath11k/hal.c +@@ -1002,6 +1002,16 @@ void ath11k_hal_setup_link_idle_list(str + FIELD_PREP(BUFFER_ADDR_INFO0_ADDR, + sbuf[0].paddr)); + ++ ath11k_hif_write32(ab, ++ HAL_SEQ_WCSS_UMAC_WBM_REG + ++ HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX1, ++ FIELD_PREP( ++ HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_39_32, ++ ((u64)sbuf[0].paddr >> ++ HAL_ADDR_MSB_REG_SHIFT)) | ++ FIELD_PREP(HAL_WBM_SCATTERED_DESC_HEAD_P_OFFSET_IX1, ++ (end_offset >> 2))); ++ + ath11k_hif_write32(ab, + HAL_SEQ_WCSS_UMAC_WBM_REG + + HAL_WBM_SCATTERED_DESC_PTR_TAIL_INFO_IX0, +--- a/drivers/net/wireless/ath/ath11k/mhi.c ++++ b/drivers/net/wireless/ath/ath11k/mhi.c +@@ -18,6 +18,11 @@ + + #define MHI_TIMEOUT_DEFAULT_MS 90000 + #define RDDM_DUMP_SIZE 0x420000 ++#ifdef CONFIG_64BIT ++#define MAX_RAM_ADDR 0xFFFFFFFFFFFFFFFF ++#else ++#define MAX_RAM_ADDR 0xFFFFFFFF ++#endif + + static struct mhi_channel_config ath11k_mhi_channels_qca6390[] = { + { +@@ -428,7 +433,7 @@ int ath11k_mhi_register(struct ath11k_pc + return ret; + } else { + mhi_ctrl->iova_start = 0; +- mhi_ctrl->iova_stop = 0xFFFFFFFF; ++ mhi_ctrl->iova_stop = MAX_RAM_ADDR; + } + + ath11k_info(ab, "mhi_ctrl start addr %llx end addr %llx\n", +--- a/drivers/net/wireless/ath/ath11k/pci.c ++++ b/drivers/net/wireless/ath/ath11k/pci.c +@@ -18,7 +18,8 @@ + #include "qmi.h" + + #define ATH11K_PCI_BAR_NUM 0 +-#define ATH11K_PCI_DMA_MASK 32 ++/* Target can access upto (2^40) GB of RAM directly */ ++#define ATH11K_PCI_DMA_MASK 40 + + #define TCSR_SOC_HW_VERSION 0x0224 + #define TCSR_SOC_HW_VERSION_MAJOR_MASK GENMASK(11, 8) diff --git a/feeds/ipq95xx/mac80211/patches/qca/452-ath11k-fix-memory-leak-caused-by-thermal-debug-regis.patch b/feeds/ipq95xx/mac80211/patches/qca/452-ath11k-fix-memory-leak-caused-by-thermal-debug-regis.patch new file mode 100644 index 000000000..3da640be0 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/452-ath11k-fix-memory-leak-caused-by-thermal-debug-regis.patch @@ -0,0 +1,85 @@ +From d9bdef4a0be61ef7ea0be9ad02dfb815555c4c52 Mon Sep 17 00:00:00 2001 +From: P Praneesh +Date: Mon, 29 May 2023 13:06:22 +0530 +Subject: [PATCH] ath11k: fix memory leak caused by thermal debug register + +wiphy_free deallocates rdev via put_device which internally uses +kref_count of kobj. This kref_count gets incremented during device_add and +decremented during device_del. During rmmod, wiphy_free expectes this +kref_count to be zero for deallocating rdev. + +Ath11k driver uses devm_hwmon_device_register_with_groups for thermal +register by passing hw->wiphy->dev which is the child of pci->dev. So the +kref_count incremented for the hw->wiphy->dev is not getting decremented +properly during device_del which causes stale value present in the +kref_count. Because of the positive value in kref_count, put_device failed +to call kfree of rdev which causes memory leaks. + +Fix it by using hwmon_device_register_with_groups instead of +devm_hwmon_device_register_with_groups and free it using +hwmon_device_unregiste during unregister. + +Signed-off-by: P Praneesh +--- + drivers/net/wireless/ath/ath11k/thermal.c | 17 +++++++++++------ + drivers/net/wireless/ath/ath11k/thermal.h | 1 + + 2 files changed, 12 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/thermal.c b/drivers/net/wireless/ath/ath11k/thermal.c +index 4faf123..d30c1f1 100644 +--- a/drivers/net/wireless/ath/ath11k/thermal.c ++++ b/drivers/net/wireless/ath/ath11k/thermal.c +@@ -158,7 +158,6 @@ int ath11k_thermal_set_throttling(struct ath11k *ar, u32 throttle_state) + int ath11k_thermal_register(struct ath11k_base *sc) + { + struct thermal_cooling_device *cdev; +- struct device *hwmon_dev; + struct ath11k *ar; + struct ath11k_pdev *pdev; + int i, ret; +@@ -191,12 +190,13 @@ int ath11k_thermal_register(struct ath11k_base *sc) + if (!IS_REACHABLE(CONFIG_HWMON)) + return 0; + +- hwmon_dev = devm_hwmon_device_register_with_groups(&ar->hw->wiphy->dev, +- "ath11k_hwmon", ar, +- ath11k_hwmon_groups); +- if (IS_ERR(hwmon_dev)) { ++ ar->thermal.hwmon_dev = hwmon_device_register_with_groups(&ar->hw->wiphy->dev, ++ "ath11k_hwmon", ar, ++ ath11k_hwmon_groups); ++ if (IS_ERR(ar->thermal.hwmon_dev)) { + ath11k_err(ar->ab, "failed to register hwmon device: %ld\n", +- PTR_ERR(hwmon_dev)); ++ PTR_ERR(ar->thermal.hwmon_dev)); ++ ar->thermal.hwmon_dev = NULL; + ret = -EINVAL; + goto err_thermal_destroy; + } +@@ -221,6 +221,11 @@ void ath11k_thermal_unregister(struct ath11k_base *sc) + if (!ar) + continue; + ++ if (ar->thermal.hwmon_dev) { ++ hwmon_device_unregister(ar->thermal.hwmon_dev); ++ ar->thermal.hwmon_dev = NULL; ++ } ++ + sysfs_remove_link(&ar->hw->wiphy->dev.kobj, "cooling_device"); + thermal_cooling_device_unregister(ar->thermal.cdev); + } +diff --git a/drivers/net/wireless/ath/ath11k/thermal.h b/drivers/net/wireless/ath/ath11k/thermal.h +index f9af55f..705a0cd 100644 +--- a/drivers/net/wireless/ath/ath11k/thermal.h ++++ b/drivers/net/wireless/ath/ath11k/thermal.h +@@ -16,6 +16,7 @@ + struct ath11k_thermal { + struct thermal_cooling_device *cdev; + struct completion wmi_sync; ++ struct device *hwmon_dev; + + /* protected by conf_mutex */ + u32 throttle_state; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/453-ath11k-compilation-error-fix.patch b/feeds/ipq95xx/mac80211/patches/qca/453-ath11k-compilation-error-fix.patch new file mode 100644 index 000000000..c9a1feee5 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/453-ath11k-compilation-error-fix.patch @@ -0,0 +1,407 @@ +From 67adadf481d7826f450e5fcd2ff33b91899b4059 Mon Sep 17 00:00:00 2001 +From: Bhagavathi Perumal S +Date: Sat, 17 Jun 2023 17:39:03 +0530 +Subject: [PATCH] ath11k compilation error fix + + +This changes has ath11k integration with OpenWRT-ginger branch, Also +fixed the various compilation issues due to kernel upgradation from 5.x to 6.x, +some API names are changed and some unsupported API are disable in the kernel 6.x +this patch support for both the kernel versions + +Signed-off-by: Bhagavathi Perumal S +--- + drivers/net/wireless/ath/ath11k/ahb.c | 19 +++++++++++++++++++ + drivers/net/wireless/ath/ath11k/cfr.c | 2 +- + drivers/net/wireless/ath/ath11k/core.c | 4 ++-- + drivers/net/wireless/ath/ath11k/core.h | 2 ++ + drivers/net/wireless/ath/ath11k/coredump.c | 2 ++ + drivers/net/wireless/ath/ath11k/dp_tx.c | 2 +- + drivers/net/wireless/ath/ath11k/mac.c | 10 +++++----- + drivers/net/wireless/ath/ath11k/mhi.c | 16 ++++++++++++++++ + drivers/net/wireless/ath/ath11k/pcic.c | 19 ++++++++++++++++++- + drivers/net/wireless/ath/ath11k/qmi.c | 2 ++ + drivers/net/wireless/ath/ath11k/qmi.h | 1 + + drivers/net/wireless/ath/ath11k/wmi.c | 4 ++-- + drivers/net/wireless/ath/ath11k/wmi.h | 6 +++++- + drivers/net/wireless/ath/ath12k/ahb.h | 5 +++++ + 14 files changed, 81 insertions(+), 13 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/ahb.c ++++ b/drivers/net/wireless/ath/ath11k/ahb.c +@@ -579,8 +579,13 @@ + irq_grp->ab = ab; + irq_grp->grp_id = i; + init_dummy_netdev(&irq_grp->napi_ndev); ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi, + ath11k_ahb_ext_grp_napi_poll, NAPI_POLL_WEIGHT); ++#else ++ netif_napi_add_weight(&irq_grp->napi_ndev, &irq_grp->napi, ++ ath11k_ahb_ext_grp_napi_poll, NAPI_POLL_WEIGHT); ++#endif + + for (j = 0; j < ATH11K_EXT_IRQ_NUM_MAX; j++) { + if (!nss_offload && ab->hw_params.ring_mask->tx[i] & BIT(j)) { +@@ -733,9 +738,13 @@ + #if LINUX_VERSION_IS_LESS(5, 4, 0) + qcom_register_ssr_notifier(&ab->qmi.ssr_nb); + #else ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab); + rproc_register_subsys_notifier(ab_ahb->tgt_rproc->name, + &ab->qmi.ssr_nb, &ab->qmi.ssr_nb); ++#else ++ ab->qmi.ssr_handle = qcom_register_ssr_notifier("q6wcss", &ab->qmi.ssr_nb); ++#endif + #endif + } + +@@ -744,10 +753,15 @@ + #if LINUX_VERSION_IS_LESS(5, 4, 0) + qcom_unregister_ssr_notifier(&ab->qmi.ssr_nb); + #else ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab); + rproc_unregister_subsys_notifier(ab_ahb->tgt_rproc->name, + &ab->qmi.ssr_nb, + &ab->qmi.ssr_nb); ++#else ++ if (ab->qmi.ssr_handle) ++ qcom_unregister_ssr_notifier(ab->qmi.ssr_handle, &ab->qmi.ssr_nb); ++#endif + #endif + } + #endif +@@ -1224,7 +1238,12 @@ + * and the space is not contiguous, hence remapping the CE registers + * to a new space for accessing them. + */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + ab->mem_ce = ioremap_nocache(HAL_IPQ5018_CE_WFSS_REG_BASE, HAL_IPQ5018_CE_SIZE); ++#else ++ ab->mem_ce = ioremap(HAL_IPQ5018_CE_WFSS_REG_BASE, HAL_IPQ5018_CE_SIZE); ++#endif ++ + if (IS_ERR(ab->mem_ce)) { + dev_err(&pdev->dev, "ce ioremap error\n"); + return -ENOMEM; +--- a/drivers/net/wireless/ath/ath11k/cfr.c ++++ b/drivers/net/wireless/ath/ath11k/cfr.c +@@ -90,7 +90,7 @@ + case 3: /* DUP160/VHT160 */ + return TONES_IN_160MHZ; + } +- ++ fallthrough; + case ATH11K_CFR_PREAMBLE_TYPE_HT: + switch (bw) { + case 0: +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -1901,13 +1901,13 @@ + } + + #if LINUX_VERSION_IS_GEQ(5,4,0) +- if (ath11k_collect_dump && event == SUBSYS_AFTER_POWERUP) { ++ if (ath11k_collect_dump && event == ATH11K_SSR_POWERUP) { + ath11k_collect_dump = false; + wake_up(&ath11k_ssr_dump_wq); + return 0; + } + +- if (event != SUBSYS_PREPARE_FOR_FATAL_SHUTDOWN) ++ if (event != ATH11K_SSR_PREPARE_SHUTDOWN) + return 0; + ath11k_collect_dump = true; + #else +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -97,6 +97,14 @@ + #define HAL_REO_DEST_RING_CTRL_HASH_RING_SHIFT 8 + #define HAL_IPQ5018_REO_DEST_RING_CTRL_HASH_RING_SHIFT 0 + ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) ++#define ATH11K_SSR_POWERUP SUBSYS_AFTER_POWERUP ++#define ATH11K_SSR_PREPARE_SHUTDOWN SUBSYS_PREPARE_FOR_FATAL_SHUTDOWN ++#else ++#define ATH11K_SSR_POWERUP QCOM_SSR_AFTER_POWERUP ++#define ATH11K_SSR_PREPARE_SHUTDOWN QCOM_SSR_NOTIFY_CRASH ++#endif ++ + enum ath11k_supported_bw { + ATH11K_BW_20 = 0, + ATH11K_BW_40 = 1, +@@ -1639,8 +1647,10 @@ + void ath11k_core_dump_bp_stats(struct ath11k_base *ab); + void ath11k_coredump_qdss_dump(struct ath11k_base *ab, + struct ath11k_qmi_event_qdss_trace_save_data *event_data); ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + int ath11k_coredump_mhi_update_bhie_table(struct ath11k_base *ab, void *va, + phys_addr_t pa, size_t size); ++#endif + const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab, + const char *filename); + void ath11k_core_wait_dump_collect(struct ath11k_base *ab); +--- a/drivers/net/wireless/ath/ath11k/coredump.c ++++ b/drivers/net/wireless/ath/ath11k/coredump.c +@@ -374,6 +374,7 @@ + vfree(dump); + } + ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + int ath11k_coredump_mhi_update_bhie_table(struct ath11k_base *ab, void *va, + phys_addr_t pa, size_t size) + { +@@ -392,3 +393,4 @@ + + return ret; + } ++#endif +--- a/drivers/net/wireless/ath/ath11k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_tx.c +@@ -1022,7 +1022,7 @@ + now = ieee80211_txdelay_get_time(); + bin = txdelay_ms_to_bin(txdelay_time_to_ms(now - enqueue_time)); + +- if (!ar->debug.tx_delay_stats) { ++ if (!ar->debug.tx_delay_stats[tid]) { + ath11k_warn(ar->ab, "tx delay stats invalid\n"); + return; + } +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -2066,7 +2066,7 @@ + } + + static bool +-ath11k_peer_assoc_h_ht_masked(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN]) ++ath11k_peer_assoc_h_ht_masked(const u8 ht_mcs_mask[]) + { + int nss; + +@@ -2473,7 +2473,7 @@ + } + + static bool +-ath11k_peer_assoc_h_he_masked(const u16 he_mcs_mask[NL80211_HE_NSS_MAX]) ++ath11k_peer_assoc_h_he_masked(const u16 *he_mcs_mask[]) + { + int nss; + +@@ -3112,8 +3112,8 @@ + vif_mask = &arvif->bitrate_mask; + ath11k_warn(ar->ab, "arvif bit rate masked: he %d vht %d ht %d", + ath11k_peer_assoc_h_he_masked(vif_mask->control[band].he_mcs), +- ath11k_peer_assoc_h_he_masked(vif_mask->control[band].vht_mcs), +- ath11k_peer_assoc_h_he_masked(vif_mask->control[band].ht_mcs)); ++ ath11k_peer_assoc_h_vht_masked(vif_mask->control[band].vht_mcs), ++ ath11k_peer_assoc_h_ht_masked(vif_mask->control[band].ht_mcs)); + WARN_ON_ONCE(1); + return true; + } +@@ -4274,7 +4274,7 @@ + + arg->chan_list.num_chan = req->n_channels; + for (i = 0; i < arg->chan_list.num_chan; i++) { +- if (req->channels) ++ if (req->channels[i]) + chan[i].freq = req->channels[i]->center_freq; + if (req->chandef) + chan[i].phymode = ath11k_phymodes[band][width]; +--- a/drivers/net/wireless/ath/ath11k/mhi.c ++++ b/drivers/net/wireless/ath/ath11k/mhi.c +@@ -38,7 +38,9 @@ + .offload_channel = false, + .doorbell_mode_switch = false, + .auto_queue = false, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + .auto_start = false, ++#endif + }, + { + .num = 1, +@@ -53,7 +55,9 @@ + .offload_channel = false, + .doorbell_mode_switch = false, + .auto_queue = false, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + .auto_start = false, ++#endif + }, + { + .num = 20, +@@ -68,7 +72,9 @@ + .offload_channel = false, + .doorbell_mode_switch = false, + .auto_queue = false, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + .auto_start = true, ++#endif + }, + { + .num = 21, +@@ -83,7 +89,9 @@ + .offload_channel = false, + .doorbell_mode_switch = false, + .auto_queue = true, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + .auto_start = true, ++#endif + }, + }; + +@@ -135,7 +143,9 @@ + .offload_channel = false, + .doorbell_mode_switch = false, + .auto_queue = false, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + .auto_start = false, ++#endif + }, + { + .num = 1, +@@ -150,7 +160,9 @@ + .offload_channel = false, + .doorbell_mode_switch = false, + .auto_queue = false, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + .auto_start = false, ++#endif + }, + { + .num = 20, +@@ -165,7 +177,9 @@ + .offload_channel = false, + .doorbell_mode_switch = false, + .auto_queue = false, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + .auto_start = true, ++#endif + }, + { + .num = 21, +@@ -180,7 +194,9 @@ + .offload_channel = false, + .doorbell_mode_switch = false, + .auto_queue = true, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + .auto_start = true, ++#endif + }, + }; + +--- a/drivers/net/wireless/ath/ath11k/pcic.c ++++ b/drivers/net/wireless/ath/ath11k/pcic.c +@@ -531,8 +531,13 @@ + irq_grp->ab = ab; + irq_grp->grp_id = i; + init_dummy_netdev(&irq_grp->napi_ndev); ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi, + ath11k_pcic_ext_grp_napi_poll, NAPI_POLL_WEIGHT); ++#else ++ netif_napi_add_weight(&irq_grp->napi_ndev, &irq_grp->napi, ++ ath11k_pcic_ext_grp_napi_poll, NAPI_POLL_WEIGHT); ++#endif + + /* tcl, reo, rx_err, wbm release, rxdma rings are offloaded to nss. */ + if (ab->nss.enabled && +@@ -797,8 +802,13 @@ + irq_grp->ab = ab; + irq_grp->grp_id = i; + init_dummy_netdev(&irq_grp->napi_ndev); ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi, + ath11k_pcic_ext_grp_napi_poll, NAPI_POLL_WEIGHT); ++#else ++ netif_napi_add_weight(&irq_grp->napi_ndev, &irq_grp->napi, ++ ath11k_pcic_ext_grp_napi_poll, NAPI_POLL_WEIGHT); ++#endif + + if (ab->hw_params.ring_mask->tx[i] || + ab->hw_params.ring_mask->rx[i] || +@@ -894,8 +904,11 @@ + ath11k_warn(ab, "failed to alloc irqs %d ab %pM\n", ret, ab); + return ret; + } +- ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + for_each_msi_entry(msi_desc, &pdev->dev) { ++#else ++ msi_for_each_desc(msi_desc, &pdev->dev, MSI_DESC_ALL) { ++#endif + if (!ce_done && i == ab->hw_params.ce_count) { + i = 0; + ce_done = true; +@@ -926,7 +939,11 @@ + ab->pci.msi.ep_base_data = msi_desc->msg.data; + } + ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + for_each_msi_entry(msi_desc, &pdev->dev) { ++#else ++ msi_for_each_desc(msi_desc, &pdev->dev, MSI_DESC_ALL) { ++#endif + u32 user_base_data = 0, base_vector = 0; + int vector, num_vectors = 0; + +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -3037,7 +3037,7 @@ + ab->qmi.target_mem[i].size); + ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size; + ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type; +- ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + ret = ath11k_coredump_mhi_update_bhie_table(ab, + ab->qmi.target_mem[idx].vaddr, + ab->qmi.target_mem[idx].paddr, +@@ -3045,7 +3045,7 @@ + if (ret < 0) + ath11k_warn(ab, "qmi fail to update BHI table %d\n", + ret); +- ++#endif + idx++; + break; + default: +--- a/drivers/net/wireless/ath/ath11k/qmi.h ++++ b/drivers/net/wireless/ath/ath11k/qmi.h +@@ -201,6 +201,7 @@ + struct list_head event_list; + spinlock_t event_lock; /* spinlock for qmi event list */ + struct notifier_block ssr_nb; ++ void *ssr_handle; + struct ath11k_qmi_ce_cfg ce_cfg; + struct target_mem_chunk target_mem[ATH11K_QMI_WLANFW_MAX_NUM_MEM_SEG_V01]; + u32 mem_seg_count; +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -53,7 +53,11 @@ + + #define WMI_TLV_LEN GENMASK(15, 0) + #define WMI_TLV_TAG GENMASK(31, 16) +-#define TLV_HDR_SIZE FIELD_SIZEOF(struct wmi_tlv, header) ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) ++#define TLV_HDR_SIZE FIELD_SIZEOF(struct wmi_tlv, header) ++#else ++#define TLV_HDR_SIZE sizeof_field(struct wmi_tlv, header) ++#endif + + #define WMI_CMD_HDR_CMD_ID GENMASK(23, 0) + #define WMI_MAX_MEM_REQS 32 +@@ -7706,11 +7710,11 @@ + const u8 *macaddr, const u32 *tx_antenna); + int ath11k_wmi_pdev_set_rx_ant(struct ath11k *ar, u32 antenna); + int +-ath11k_wmi_peer_set_smart_ant_node_config(struct ath11k *ar, u8 *mac, ++ath11k_wmi_peer_set_smart_ant_node_config(struct ath11k *ar, u8 mac_addr[ETH_ALEN], + struct ath11k_smart_ant_node_config_params *param); + int + ath11k_wmi_peer_set_smart_ant_train_info(struct ath11k *ar, u32 vdev_id, +- u8 *mac, ++ u8 mac_addr[ETH_ALEN], + struct ath11k_smart_ant_train_info *param); + int + ath11k_wmi_peer_set_smart_ant_train_ant_param_cmd(struct ath11k *ar, diff --git a/feeds/ipq95xx/mac80211/patches/qca/454-ath11k-reap-CE-entries-if-ring-is-full-and-intrp-idl.patch b/feeds/ipq95xx/mac80211/patches/qca/454-ath11k-reap-CE-entries-if-ring-is-full-and-intrp-idl.patch new file mode 100644 index 000000000..e5f2773ca --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/454-ath11k-reap-CE-entries-if-ring-is-full-and-intrp-idl.patch @@ -0,0 +1,145 @@ +From adce52457ce04834a2bdd16f46890772f4bce9c1 Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Fri, 14 Jul 2023 15:48:23 +0530 +Subject: [PATCH 1/2] ath11k: reap CE entries if ring is full and intrp idle + for 500ms + +If there is no buffer to send packet via HTC, then check if +interrupts are not processed from that CE for last 500ms. +If so, reap the CE ring and check if we could proceed for new enqueue. + +This change is added because there is a case where intermittently +completion interrupts are not received from CE3 and hence adding +this WAR in host to come out of this issue scenario. + +Signed-off-by: Karthikeyan Kathirvel +Signed-off-by: Sriram R +--- + drivers/net/wireless/ath/ath11k/ce.c | 41 ++++++++++++++++++++++++-- + drivers/net/wireless/ath/ath11k/ce.h | 4 ++- + drivers/net/wireless/ath/ath11k/core.c | 1 + + drivers/net/wireless/ath/ath11k/hal.c | 6 ++-- + drivers/net/wireless/ath/ath11k/hw.h | 1 + + 5 files changed, 47 insertions(+), 6 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/ce.c ++++ b/drivers/net/wireless/ath/ath11k/ce.c +@@ -814,6 +814,31 @@ void ath11k_ce_poll_send_completed(struc + } + EXPORT_SYMBOL(ath11k_ce_per_engine_service); + ++#define ATH11K_CE_RING_FULL_THRESHOLD_TIME_MS 500 ++#define ATH11K_MAX_CE_MANUAL_RETRY 3 ++/* Ths function is called from ce_send path. Returns true If there is no buffer ++ * to send packet via HTC, then check if interrupts are not processed from that ++ * CE for last 500ms. If so, poll manually to reap available entries. ++ */ ++static bool ath11k_is_manual_ce_poll_needed(struct ath11k_base *ab, ++ struct ath11k_ce_pipe *pipe, ++ struct hal_srng *srng) ++{ ++ if (!ab->hw_params.support_ce_manual_poll) ++ return false; ++ ++ if (time_after ++ (jiffies, pipe->timestamp + msecs_to_jiffies(ATH11K_CE_RING_FULL_THRESHOLD_TIME_MS)) && ++ (srng->u.src_ring.hp == srng->u.src_ring.reap_hp) && ++ (srng->u.src_ring.reap_hp == *srng->u.src_ring.tp_addr)) { ++ pipe->ce_manual_poll_count++; ++ pipe->last_ce_manual_poll_ts = jiffies; ++ return true; ++ } ++ ++ return false; ++} ++ + int ath11k_ce_send(struct ath11k_base *ab, struct sk_buff *skb, u8 pipe_id, + u16 transfer_id) + { +@@ -824,7 +849,7 @@ int ath11k_ce_send(struct ath11k_base *a + unsigned int nentries_mask; + int ret = 0; + u8 byte_swap_data = 0; +- int num_used; ++ int num_used, retry = 0; + + /* Check if some entries could be regained by handling tx completion if + * the CE has interrupts disabled and the used entries is more than the +@@ -851,6 +876,7 @@ int ath11k_ce_send(struct ath11k_base *a + if (test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags)) + return -ESHUTDOWN; + ++retry: + spin_lock_bh(&ab->ce.ce_lock); + + write_index = pipe->src_ring->write_index; +@@ -871,8 +897,17 @@ int ath11k_ce_send(struct ath11k_base *a + desc = ath11k_hal_srng_src_get_next_reaped(ab, srng); + if (!desc) { + ath11k_hal_srng_access_end(ab, srng); +- ret = -ENOBUFS; +- goto err_unlock; ++ if (retry++ < ATH11K_MAX_CE_MANUAL_RETRY && ++ ath11k_is_manual_ce_poll_needed(ab, pipe, srng)) { ++ spin_unlock_bh(&srng->lock); ++ spin_unlock_bh(&ab->ce.ce_lock); ++ ++ ath11k_ce_tx_process_cb(pipe); ++ goto retry; ++ } else { ++ ret = -ENOBUFS; ++ goto err_unlock; ++ } + } + + if (pipe->attr_flags & CE_ATTR_BYTE_SWAP_DATA) +--- a/drivers/net/wireless/ath/ath11k/ce.h ++++ b/drivers/net/wireless/ath/ath11k/ce.h +@@ -187,7 +187,9 @@ struct ath11k_ce_pipe { + struct ath11k_ce_ring *src_ring; + struct ath11k_ce_ring *dest_ring; + struct ath11k_ce_ring *status_ring; +- u64 timestamp; ++ unsigned long timestamp; ++ u32 ce_manual_poll_count; ++ u64 last_ce_manual_poll_ts; + + struct ce_tasklet_entry_ts tasklet_ts; + struct ce_tasklet_time tracker[CE_TIME_DURATION_MAX]; +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -903,6 +903,7 @@ static const struct ath11k_hw_params ath + .m3_offset = ATH11K_QMI_IPQ9574_M3_OFFSET, + .caldb_offset = ATH11K_QMI_IPQ9574_CALDB_OFFSET, + .bdf_offset = ATH11K_QMI_IPQ9574_BDF_OFFSET, ++ .support_ce_manual_poll=true, + }, + }; + +--- a/drivers/net/wireless/ath/ath11k/hal.c ++++ b/drivers/net/wireless/ath/ath11k/hal.c +@@ -1442,10 +1442,12 @@ void ath11k_hal_dump_srng_stats(struct a + if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) + continue; + +- ath11k_info(ab, "CE_id %d pipe_num %d %ums before, sched_delay_gt_500US %u, exec_delay_gt_500US %u\n", ++ ath11k_info(ab, "CE_id %d pipe_num %d %ums before, sched_delay_gt_500US %u, exec_delay_gt_500US %u ce_manual_poll_count %d ce_last_manual_poll_done %ums before\n", + i, ce_pipe->pipe_num, + jiffies_to_msecs(jiffies - ce_pipe->timestamp), +- ce_pipe->sched_delay_gt_500US, ce_pipe->exec_delay_gt_500US); ++ ce_pipe->sched_delay_gt_500US, ce_pipe->exec_delay_gt_500US, ++ ce_pipe->ce_manual_poll_count, ++ jiffies_to_msecs(jiffies - ce_pipe->last_ce_manual_poll_ts)); + + for (j = 0; j < CE_TIME_DURATION_MAX; j++) { + last_sched = jiffies_to_msecs(jiffies - +--- a/drivers/net/wireless/ath/ath11k/hw.h ++++ b/drivers/net/wireless/ath/ath11k/hw.h +@@ -258,6 +258,7 @@ struct ath11k_hw_params { + u32 caldb_offset; + u32 qdss_offset; + u32 pageable_offset; ++ bool support_ce_manual_poll; + }; + + struct ath11k_hw_ops { diff --git a/feeds/ipq95xx/mac80211/patches/qca/455-ath11k-added-a-debugfs-to-dump-hal-srng-stats.patch b/feeds/ipq95xx/mac80211/patches/qca/455-ath11k-added-a-debugfs-to-dump-hal-srng-stats.patch new file mode 100644 index 000000000..67632c206 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/455-ath11k-added-a-debugfs-to-dump-hal-srng-stats.patch @@ -0,0 +1,155 @@ +From 4b500b424519d953d38673c24ffea6c93f76e8b6 Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Fri, 14 Jul 2023 16:04:44 +0530 +Subject: [PATCH 2/2] ath11k: added a debugfs to dump hal srng stats + +Added a debugfs to dump hal srng +Cmd ref, + cat /sys/kernel/debug/ath11k//dump_srng_stats + +Signed-off-by: Karthikeyan Kathirvel +Signed-off-by: Sriram R +--- + drivers/net/wireless/ath/ath11k/debugfs.c | 32 ++++++++++++ + drivers/net/wireless/ath/ath11k/hal.c | 64 +++++++++++++++++++++++ + drivers/net/wireless/ath/ath11k/hal.h | 1 + + 3 files changed, 97 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c +index 4f73b2c..20f4fbb 100644 +--- a/drivers/net/wireless/ath/ath11k/debugfs.c ++++ b/drivers/net/wireless/ath/ath11k/debugfs.c +@@ -2434,6 +2434,35 @@ static const struct file_operations fops_ce_latency_stats = { + .read = ath11k_read_ce_latency_stats, + }; + ++static ssize_t ath11k_debugfs_hal_dump_srng_stats_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath11k_base *ab = file->private_data; ++ int len = 0, retval; ++ const int size = 4096 * 6; ++ char *buf; ++ ++ buf = kzalloc(size, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ len = ath11k_debugfs_hal_dump_srng_stats(ab, buf + len, size - len); ++ if (len > size) ++ len = size; ++ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ kfree(buf); ++ ++ return retval; ++} ++ ++static const struct file_operations fops_dump_hal_stats = { ++ .read = ath11k_debugfs_hal_dump_srng_stats_read, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ + int ath11k_debugfs_pdev_create(struct ath11k_base *ab) + { + if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)) +@@ -2464,6 +2493,9 @@ int ath11k_debugfs_pdev_create(struct ath11k_base *ab) + debugfs_create_file("rx_hash", 0600, ab->debugfs_soc, ab, + &fops_soc_rx_hash); + ++ debugfs_create_file("dump_srng_stats", 0600, ab->debugfs_soc, ab, ++ &fops_dump_hal_stats); ++ + return 0; + } + +diff --git a/drivers/net/wireless/ath/ath11k/hal.c b/drivers/net/wireless/ath/ath11k/hal.c +index 44832c5..d61dab3 100644 +--- a/drivers/net/wireless/ath/ath11k/hal.c ++++ b/drivers/net/wireless/ath/ath11k/hal.c +@@ -1424,6 +1424,70 @@ void ath11k_hal_srng_deinit(struct ath11k_base *ab) + } + EXPORT_SYMBOL(ath11k_hal_srng_deinit); + ++ssize_t ath11k_debugfs_hal_dump_srng_stats(struct ath11k_base *ab, char *buf, int size) ++{ ++ struct hal_srng *srng; ++ struct ath11k_ext_irq_grp *irq_grp; ++ struct ath11k_ce_pipe *ce_pipe; ++ unsigned int len = 0; ++ int i; ++ ++ len += scnprintf(buf + len, size - len, "Last interrupt received for each CE:\n"); ++ for (i = 0; i < ab->hw_params.ce_count; i++) { ++ ce_pipe = &ab->ce.ce_pipe[i]; ++ ++ if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) ++ continue; ++ ++ spin_lock_bh(&ab->ce.ce_lock); ++ len += scnprintf(buf + len, size - len, ++ "CE_id %d pipe_num %d %ums before ce_manual_poll_count %d ce_last_manual_tasklet_schedule_ts %ums before\n", ++ i, ce_pipe->pipe_num, ++ jiffies_to_msecs(jiffies - ce_pipe->timestamp), ++ ce_pipe->ce_manual_poll_count, ++ jiffies_to_msecs(jiffies - ce_pipe->last_ce_manual_poll_ts)); ++ spin_unlock_bh(&ab->ce.ce_lock); ++ } ++ ++ len += scnprintf(buf + len, size - len, "\nLast interrupt received for each group:\n"); ++ for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { ++ irq_grp = &ab->ext_irq_grp[i]; ++ len += scnprintf(buf + len, size - len, "group_id %d %ums before\n", ++ irq_grp->grp_id, ++ jiffies_to_msecs(jiffies - irq_grp->timestamp)); ++ } ++ ++ for (i = 0; i < HAL_SRNG_RING_ID_MAX; i++) { ++ srng = &ab->hal.srng_list[i]; ++ ++ spin_lock_bh(&srng->lock); ++ if (!srng->initialized) { ++ spin_unlock_bh(&srng->lock); ++ continue; ++ } ++ ++ if (srng->ring_dir == HAL_SRNG_DIR_SRC) ++ len += scnprintf(buf + len, size - len, ++ "src srng id %u hp %u, reap_hp %u, cur tp %u, cached tp %u last tp %u napi processed before %ums\n", ++ srng->ring_id, srng->u.src_ring.hp, ++ srng->u.src_ring.reap_hp, ++ *srng->u.src_ring.tp_addr, srng->u.src_ring.cached_tp, ++ srng->u.src_ring.last_tp, ++ jiffies_to_msecs(jiffies - srng->timestamp)); ++ else if (srng->ring_dir == HAL_SRNG_DIR_DST) ++ len += scnprintf(buf + len, size - len, ++ "dst srng id %u tp %u, cur hp %u, cached hp %u last hp %u napi processed before %ums\n", ++ srng->ring_id, srng->u.dst_ring.tp, ++ *srng->u.dst_ring.hp_addr, ++ srng->u.dst_ring.cached_hp, ++ srng->u.dst_ring.last_hp, ++ jiffies_to_msecs(jiffies - srng->timestamp)); ++ spin_unlock_bh(&srng->lock); ++ } ++ ++ return len; ++} ++ + void ath11k_hal_dump_srng_stats(struct ath11k_base *ab) + { + struct hal_srng *srng; +diff --git a/drivers/net/wireless/ath/ath11k/hal.h b/drivers/net/wireless/ath/ath11k/hal.h +index 2db26ad..32e7df4 100644 +--- a/drivers/net/wireless/ath/ath11k/hal.h ++++ b/drivers/net/wireless/ath/ath11k/hal.h +@@ -984,4 +984,5 @@ int ath11k_hal_srng_update_shadow_config(struct ath11k_base *ab, + void ath11k_hal_srng_shadow_config(struct ath11k_base *ab); + void ath11k_hal_srng_shadow_update_hp_tp(struct ath11k_base *ab, + struct hal_srng *srng); ++ssize_t ath11k_debugfs_hal_dump_srng_stats(struct ath11k_base *ab, char *buf, int size); + #endif +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/500-001-ath12k-hw_params-changes-for-RDP.patch b/feeds/ipq95xx/mac80211/patches/qca/500-001-ath12k-hw_params-changes-for-RDP.patch new file mode 100644 index 000000000..cf8440361 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/500-001-ath12k-hw_params-changes-for-RDP.patch @@ -0,0 +1,48 @@ +From ae444bf877fd94256a110d03582ddb045c541525 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Wed, 24 Aug 2022 10:25:31 -0800 +Subject: [PATCH] ath12k: hw_params changes for RDP + +Fix hw params which was changed in upstream and is required mandatorily for +downstream. + +Signed-off-by: Aditya Kumar Singh + +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -822,7 +822,7 @@ static const struct ath12k_hw_params ath + .name = "qcn9274 hw1.0", + .hw_rev = ATH12K_HW_QCN9274_HW10, + .fw = { +- .dir = "QCN9274/hw1.0", ++ .dir = "QCN92XX/hw1.0", + .board_size = 256 * 1024, + .cal_offset = 128 * 1024, + }, +@@ -844,14 +844,15 @@ static const struct ath12k_hw_params ath + + .hal_params = &ath12k_hw_hal_params_qcn9274, + +- .rxdma1_enable = false, ++ .rxdma1_enable = true, + .num_rxmda_per_pdev = 1, + .num_rxdma_dst_ring = 0, + .rx_mac_buf_ring = false, + .vdev_start_delay = false, + + .interface_modes = BIT(NL80211_IFTYPE_STATION) | +- BIT(NL80211_IFTYPE_AP), ++ BIT(NL80211_IFTYPE_AP) | ++ BIT(NL80211_IFTYPE_MESH_POINT), + .supports_monitor = false, + + .idle_ps = false, +@@ -859,7 +860,7 @@ static const struct ath12k_hw_params ath + .download_calib = true, + .supports_suspend = false, + .tcl_ring_retry = true, +- .reoq_lut_support = false, ++ .reoq_lut_support = true, + .supports_shadow_regs = false, + + .hal_desc_sz = sizeof(struct hal_rx_desc_qcn9274), diff --git a/feeds/ipq95xx/mac80211/patches/qca/500-ath12k-add-bus-param-struct.patch b/feeds/ipq95xx/mac80211/patches/qca/500-ath12k-add-bus-param-struct.patch new file mode 100644 index 000000000..38a042959 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/500-ath12k-add-bus-param-struct.patch @@ -0,0 +1,190 @@ +From ae444bf877fd94256a110d03582ddb045c541525 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Wed, 24 Aug 2022 11:25:31 -0800 +Subject: [PATCH] ath12k: add bus param struct + +Struct ath12k_bus_params was removed in upstream. Add it back. + +Signed-off-by: Aditya Kumar Singh + +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -929,7 +929,8 @@ void ath12k_core_free(struct ath12k_base + } + + struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size, +- enum ath12k_bus bus) ++ enum ath12k_bus bus, ++ const struct ath12k_bus_params *bus_params) + { + struct ath12k_base *ab; + +@@ -964,6 +965,7 @@ struct ath12k_base *ath12k_core_alloc(st + init_completion(&ab->wow.wakeup_completed); + + ab->dev = dev; ++ ab->bus_params = *bus_params; + ab->hif.bus = bus; + + return ab; +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -648,6 +648,11 @@ struct ath12k_board_data { + size_t len; + }; + ++struct ath12k_bus_params { ++ bool fixed_bdf_addr; ++ bool fixed_mem_region; ++}; ++ + struct ath12k_bp_stats { + /* Head Pointer reported by the last HTT Backpressure event for the ring */ + u16 hp; +@@ -740,6 +745,7 @@ struct ath12k_base { + int bd_api; + + const struct ath12k_hw_params *hw_params; ++ struct ath12k_bus_params bus_params; + + const struct firmware *cal_file; + +@@ -920,7 +926,8 @@ int ath12k_core_pre_init(struct ath12k_b + int ath12k_core_init(struct ath12k_base *ath12k); + void ath12k_core_deinit(struct ath12k_base *ath12k); + struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size, +- enum ath12k_bus bus); ++ enum ath12k_bus bus, ++ const struct ath12k_bus_params *bus_params); + void ath12k_core_free(struct ath12k_base *ath12k); + int ath12k_core_fetch_board_data_api_1(struct ath12k_base *ab, + struct ath12k_board_data *bd, +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -47,6 +47,10 @@ static const struct pci_device_id ath12k + + MODULE_DEVICE_TABLE(pci, ath12k_pci_id_table); + ++static const struct ath12k_bus_params ath12k_pci_bus_params = { ++ .fixed_bdf_addr = false, ++}; ++ + /* TODO: revisit IRQ mapping for new SRNG's */ + static const struct ath12k_msi_config ath12k_msi_config[] = { + { +@@ -1143,7 +1147,8 @@ static int ath12k_pci_probe(struct pci_d + struct ath12k_pci *ab_pci; + int ret; + +- ab = ath12k_core_alloc(&pdev->dev, sizeof(*ab_pci), ATH12K_BUS_PCI); ++ ab = ath12k_core_alloc(&pdev->dev, sizeof(*ab_pci), ATH12K_BUS_PCI, ++ &ath12k_pci_bus_params); + if (!ab) { + dev_err(&pdev->dev, "failed to allocate ath12k base\n"); + return -ENOMEM; +--- a/drivers/net/wireless/ath/ath12k/qmi.c ++++ b/drivers/net/wireless/ath/ath12k/qmi.c +@@ -2520,6 +2520,7 @@ static int ath12k_qmi_load_file_target_m + struct qmi_wlanfw_bdf_download_resp_msg_v01 resp; + struct qmi_txn txn = {}; + const u8 *temp = data; ++ void __iomem *bdf_addr = NULL; + int ret; + u32 remaining = len; + +@@ -2528,6 +2529,15 @@ static int ath12k_qmi_load_file_target_m + return -ENOMEM; + memset(&resp, 0, sizeof(resp)); + ++ if (ab->bus_params.fixed_bdf_addr) { ++ bdf_addr = ioremap(ab->hw_params->bdf_addr, ab->hw_params->fw.board_size); ++ if (!bdf_addr) { ++ ath12k_warn(ab, "qmi ioremap error for BDF\n"); ++ ret = -EIO; ++ goto out_req; ++ } ++ } ++ + while (remaining) { + req->valid = 1; + req->file_id_valid = 1; +@@ -2548,7 +2558,8 @@ static int ath12k_qmi_load_file_target_m + req->end = 1; + } + +- if (type == ATH12K_QMI_FILE_TYPE_EEPROM) { ++ if ((ab->bus_params.fixed_bdf_addr) || ++ (type == ATH12K_QMI_FILE_TYPE_EEPROM)) { + req->data_valid = 0; + req->end = 1; + req->data_len = ATH12K_QMI_MAX_BDF_FILE_NAME_SIZE; +@@ -2556,6 +2567,13 @@ static int ath12k_qmi_load_file_target_m + memcpy(req->data, temp, req->data_len); + } + ++ if (ab->bus_params.fixed_bdf_addr) { ++ if (type == ATH12K_QMI_FILE_TYPE_CALDATA) ++ bdf_addr += ab->hw_params->fw.cal_offset; ++ ++ memcpy_toio(bdf_addr, temp, len); ++ } ++ + ret = qmi_txn_init(&ab->qmi.handle, &txn, + qmi_wlanfw_bdf_download_resp_msg_v01_ei, + &resp); +@@ -2585,15 +2603,22 @@ static int ath12k_qmi_load_file_target_m + goto out; + } + +- remaining -= req->data_len; +- temp += req->data_len; +- req->seg_id++; +- ath12k_dbg(ab, ATH12K_DBG_QMI, +- "qmi bdf download request remaining %i\n", +- remaining); ++ if (ab->bus_params.fixed_bdf_addr) { ++ remaining = 0; ++ } else { ++ remaining -= req->data_len; ++ temp += req->data_len; ++ req->seg_id++; ++ ath12k_dbg(ab, ATH12K_DBG_QMI, ++ "qmi bdf download request remaining %i\n", ++ remaining); ++ } + } + + out: ++ if (ab->bus_params.fixed_bdf_addr) ++ iounmap(bdf_addr); ++out_req: + kfree(req); + return ret; + } +@@ -3079,10 +3104,12 @@ static int ath12k_qmi_event_load_bdf(str + return ret; + } + +- ret = ath12k_qmi_load_bdf_qmi(ab, ATH12K_QMI_BDF_TYPE_REGDB); +- if (ret < 0) { +- ath12k_warn(ab, "qmi failed to load regdb file:%d\n", ret); +- return ret; ++ if (!ab->bus_params.fixed_bdf_addr) { ++ ret = ath12k_qmi_load_bdf_qmi(ab, ATH12K_QMI_BDF_TYPE_REGDB); ++ if (ret < 0) { ++ ath12k_warn(ab, "qmi failed to load regdb file:%d\n", ret); ++ return ret; ++ } + } + + ret = ath12k_qmi_load_bdf_qmi(ab, ATH12K_QMI_BDF_TYPE_ELF); +--- a/drivers/net/wireless/ath/ath12k/hw.h ++++ b/drivers/net/wireless/ath/ath12k/hw.h +@@ -133,6 +133,7 @@ struct ath12k_hw_hal_params { + struct ath12k_hw_params { + const char *name; + u16 hw_rev; ++ u32 bdf_addr; + + struct { + const char *dir; diff --git a/feeds/ipq95xx/mac80211/patches/qca/501-ath12k-add-dts-support.patch b/feeds/ipq95xx/mac80211/patches/qca/501-ath12k-add-dts-support.patch new file mode 100644 index 000000000..fb5a4ce62 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/501-ath12k-add-dts-support.patch @@ -0,0 +1,253 @@ +From ae444bf877fd94256a110d03582ddb045c541525 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Wed, 24 Aug 2022 12:25:31 -0800 +Subject: [PATCH] ath12k: add dts support + +DTS support was removed in upstream. Add it back. + +Signed-off-by: Aditya Kumar Singh + +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -106,6 +106,29 @@ int ath12k_core_resume(struct ath12k_bas + return 0; + } + ++int ath12k_core_check_dt(struct ath12k_base *ab) ++{ ++ size_t max_len = sizeof(ab->qmi.target.bdf_ext); ++ const char *variant = NULL; ++ struct device_node *node; ++ ++ node = ab->dev->of_node; ++ if (!node) ++ return -ENOENT; ++ ++ of_property_read_string(node, "qcom,ath12k-calibration-variant", ++ &variant); ++ if (!variant) ++ return -ENODATA; ++ ++ if (strscpy(ab->qmi.target.bdf_ext, variant, max_len) < 0) ++ ath12k_dbg(ab, ATH12K_DBG_BOOT, ++ "bdf variant string is longer than the buffer can accommodate (variant: %s)\n", ++ variant); ++ ++ return 0; ++} ++ + static int ath12k_core_create_board_name(struct ath12k_base *ab, char *name, + size_t name_len) + { +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + + #include "pci.h" + #include "core.h" +@@ -593,6 +594,7 @@ static int ath12k_pci_config_irq(struct + static void ath12k_pci_init_qmi_ce_config(struct ath12k_base *ab) + { + struct ath12k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg; ++ u32 instance_id = 0; + + cfg->tgt_ce = ab->hw_params->target_ce_config; + cfg->tgt_ce_len = ab->hw_params->target_ce_count; +@@ -600,6 +602,9 @@ static void ath12k_pci_init_qmi_ce_confi + 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 (!of_property_read_u32(ab->dev->of_node, "qrtr_instance_id", &instance_id)) ++ ab->qmi.service_ins_id = instance_id + ATH12K_QMI_WLFW_NODE_ID_BASE; + } + + static void ath12k_pci_ce_irqs_enable(struct ath12k_base *ab) +@@ -1145,6 +1150,7 @@ static int ath12k_pci_probe(struct pci_d + { + struct ath12k_base *ab; + struct ath12k_pci *ab_pci; ++ u32 addr; + int ret; + + ab = ath12k_core_alloc(&pdev->dev, sizeof(*ab_pci), ATH12K_BUS_PCI, +@@ -1164,6 +1170,12 @@ static int ath12k_pci_probe(struct pci_d + pci_set_drvdata(pdev, ab); + spin_lock_init(&ab_pci->window_lock); + ++ /* Set fixed_mem_region to true for ++ * the platforms supports reserved memory. ++ */ ++ if (of_property_read_u32(ab->dev->of_node, "qcom,base-addr", &addr)) ++ ab->bus_params.fixed_mem_region = true; ++ + ret = ath12k_pci_claim(ab_pci, pdev); + if (ret) { + ath12k_err(ab, "failed to claim device: %d\n", ret); +--- a/drivers/net/wireless/ath/ath12k/qmi.c ++++ b/drivers/net/wireless/ath/ath12k/qmi.c +@@ -2296,7 +2296,7 @@ static int ath12k_qmi_respond_fw_mem_req + * failure to firmware and firmware then request multiple blocks of + * small chunk size memory. + */ +- if (ab->qmi.target_mem_delayed) { ++ if (!ab->bus_params.fixed_mem_region && ab->qmi.target_mem_delayed) { + delayed = true; + ath12k_dbg(ab, ATH12K_DBG_QMI, "qmi delays mem_request %d\n", + ab->qmi.mem_seg_count); +@@ -2359,13 +2359,20 @@ static void ath12k_qmi_free_target_mem_c + int i; + + for (i = 0; i < ab->qmi.mem_seg_count; i++) { +- if (!ab->qmi.target_mem[i].v.addr) +- continue; +- dma_free_coherent(ab->dev, +- ab->qmi.target_mem[i].size, +- ab->qmi.target_mem[i].v.addr, +- ab->qmi.target_mem[i].paddr); +- ab->qmi.target_mem[i].v.addr = NULL; ++ if (ab->bus_params.fixed_mem_region) { ++ if (!ab->qmi.target_mem[i].v.ioaddr) ++ continue; ++ iounmap(ab->qmi.target_mem[i].v.ioaddr); ++ ab->qmi.target_mem[i].v.ioaddr = NULL; ++ } else { ++ if (!ab->qmi.target_mem[i].v.addr) ++ continue; ++ dma_free_coherent(ab->dev, ++ ab->qmi.target_mem[i].size, ++ ab->qmi.target_mem[i].v.addr, ++ ab->qmi.target_mem[i].paddr); ++ ab->qmi.target_mem[i].v.addr = NULL; ++ } + } + } + +@@ -2418,14 +2425,68 @@ static int ath12k_qmi_alloc_target_mem_c + return 0; + } + ++static int ath12k_qmi_assign_target_mem_chunk(struct ath12k_base *ab) ++{ ++ struct device *dev = ab->dev; ++ int i, idx; ++ u32 addr = 0; ++ ++ for (i = 0, idx = 0; i < ab->qmi.mem_seg_count; i++) { ++ switch (ab->qmi.target_mem[i].type) { ++ case HOST_DDR_REGION_TYPE: ++ if (of_property_read_u32(dev->of_node, "qcom,base-addr", &addr)) { ++ ath12k_warn(ab, "qmi fail to get base-addr from dt\n"); ++ return -ENOENT; ++ } ++ ab->qmi.target_mem[idx].paddr = addr; ++ ab->qmi.target_mem[idx].v.ioaddr = ++ ioremap(ab->qmi.target_mem[idx].paddr, ++ ab->qmi.target_mem[i].size); ++ 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; ++ case CALDB_MEM_REGION_TYPE: ++ if (ab->qmi.target_mem[i].size > ATH12K_QMI_CALDB_SIZE) { ++ ath12k_warn(ab, "qmi mem size is low to load caldata\n"); ++ return -EINVAL; ++ } ++ ++ if (!of_property_read_u32(dev->of_node, ++ "qcom,caldb-addr", &addr)) { ++ ab->qmi.target_mem[idx].paddr = addr; ++ ab->qmi.target_mem[idx].v.ioaddr = ++ ioremap(ab->qmi.target_mem[idx].paddr, ++ ab->qmi.target_mem[i].size); ++ } else { ++ ab->qmi.target_mem[idx].paddr = 0; ++ ab->qmi.target_mem[idx].v.ioaddr = 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: ++ ath12k_warn(ab, "qmi ignore invalid mem req type %d\n", ++ ab->qmi.target_mem[i].type); ++ break; ++ } ++ } ++ ab->qmi.mem_seg_count = idx; ++ ++ return 0; ++} ++ + static int ath12k_qmi_request_target_cap(struct ath12k_base *ab) + { + struct qmi_wlanfw_cap_req_msg_v01 req; + struct qmi_wlanfw_cap_resp_msg_v01 resp; + struct qmi_txn txn = {}; +- unsigned int board_id = ATH12K_BOARD_ID_DEFAULT; ++ struct device *dev = ab->dev; ++ unsigned int board_id; + int ret = 0; +- int i; ++ int r, i; + + memset(&req, 0, sizeof(req)); + memset(&resp, 0, sizeof(resp)); +@@ -2463,10 +2524,13 @@ static int ath12k_qmi_request_target_cap + ab->qmi.target.chip_family = resp.chip_info.chip_family; + } + +- if (resp.board_info_valid) ++ if (!of_property_read_u32(dev->of_node, "qcom,board_id", &board_id) && ++ board_id != 0xFF) ++ ab->qmi.target.board_id = board_id; ++ else if (resp.board_info_valid) + ab->qmi.target.board_id = resp.board_info.board_id; + else +- ab->qmi.target.board_id = board_id; ++ ab->qmi.target.board_id = ATH12K_BOARD_ID_DEFAULT; + + if (resp.soc_info_valid) + ab->qmi.target.soc_id = resp.soc_info.soc_id; +@@ -2509,6 +2573,10 @@ static int ath12k_qmi_request_target_cap + ab->qmi.target.fw_build_timestamp, + ab->qmi.target.fw_build_id); + ++ r = ath12k_core_check_dt(ab); ++ if (r) ++ ath12k_dbg(ab, ATH12K_DBG_QMI, "DT bdf variant name not set.\n"); ++ + out: + return ret; + } +@@ -3160,11 +3228,20 @@ static void ath12k_qmi_msg_mem_request_c + msg->mem_seg[i].type, msg->mem_seg[i].size); + } + +- ret = ath12k_qmi_alloc_target_mem_chunk(ab); +- if (ret) { +- ath12k_warn(ab, "qmi failed to alloc target memory: %d\n", +- ret); +- return; ++ if (ab->bus_params.fixed_mem_region) { ++ ret = ath12k_qmi_assign_target_mem_chunk(ab); ++ if (ret) { ++ ath12k_warn(ab, "qmi failed to assign target memory: %d\n", ++ ret); ++ return; ++ } ++ } else { ++ ret = ath12k_qmi_alloc_target_mem_chunk(ab); ++ if (ret) { ++ ath12k_warn(ab, "qmi failed to alloc target memory: %d\n", ++ ret); ++ return; ++ } + } + + ath12k_qmi_driver_event_post(qmi, ATH12K_QMI_EVENT_REQUEST_MEM, NULL); diff --git a/feeds/ipq95xx/mac80211/patches/qca/502-ath12k-add-thermal-support.patch b/feeds/ipq95xx/mac80211/patches/qca/502-ath12k-add-thermal-support.patch new file mode 100644 index 000000000..9d04ecdf9 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/502-ath12k-add-thermal-support.patch @@ -0,0 +1,401 @@ +From 49a407e8238e2575f231be33c0b4d1979698118d Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Thu, 1 Sep 2022 15:50:33 +0530 +Subject: [PATCH 1/5] Revert "ath12k: remove thermal support" + +This reverts commit bd2a2d5c554cc2fa2a320519a100dc161d5cecf7. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath12k/Makefile | 1 + + drivers/net/wireless/ath/ath12k/core.c | 12 ++ + drivers/net/wireless/ath/ath12k/core.h | 2 + + drivers/net/wireless/ath/ath12k/mac.c | 1 + + drivers/net/wireless/ath/ath12k/thermal.c | 227 ++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/thermal.h | 55 ++++++ + drivers/net/wireless/ath/ath12k/wmi.c | 2 + + 7 files changed, 300 insertions(+) + create mode 100644 drivers/net/wireless/ath/ath12k/thermal.c + create mode 100644 drivers/net/wireless/ath/ath12k/thermal.h + +--- a/drivers/net/wireless/ath/ath12k/Makefile ++++ b/drivers/net/wireless/ath/ath12k/Makefile +@@ -23,6 +23,7 @@ ath12k-y += core.o \ + dp_mon.o + + ath12k-$(CPTCFG_ATH12K_TRACING) += trace.o ++ath12k-$(CONFIG_THERMAL) += thermal.o + + # for tracing framework to find trace.h + CFLAGS_trace.o := -I$(src) +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -469,8 +469,17 @@ static int ath12k_core_pdev_create(struc + goto err_mac_unregister; + } + ++ ret = ath12k_thermal_register(ab); ++ if (ret) { ++ ath12k_err(ab, "could not register thermal device: %d\n", ++ ret); ++ goto err_dp_pdev_free; ++ } ++ + return 0; + ++err_dp_pdev_free: ++ ath12k_dp_pdev_free(ab); + err_mac_unregister: + ath12k_mac_unregister(ab); + +@@ -479,6 +488,7 @@ err_mac_unregister: + + static void ath12k_core_pdev_destroy(struct ath12k_base *ab) + { ++ ath12k_thermal_unregister(ab); + ath12k_mac_unregister(ab); + ath12k_hif_irq_disable(ab); + ath12k_dp_pdev_free(ab); +@@ -687,6 +697,7 @@ static int ath12k_core_reconfigure_on_cr + int ret; + + mutex_lock(&ab->core_lock); ++ ath12k_thermal_unregister(ab); + ath12k_hif_irq_disable(ab); + ath12k_dp_pdev_free(ab); + ath12k_hif_stop(ab); +@@ -764,6 +775,7 @@ static void ath12k_core_pre_reconfigure_ + complete(&ar->vdev_setup_done); + complete(&ar->vdev_delete_done); + complete(&ar->bss_survey_done); ++ complete(&ar->thermal.wmi_sync); + + wake_up(&ar->dp.tx_empty_waitq); + idr_for_each(&ar->txmgmt_idr, +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -21,6 +21,7 @@ + #include "hw.h" + #include "hal_rx.h" + #include "reg.h" ++#include "thermal.h" + #include "dbring.h" + + #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK) +@@ -593,6 +594,7 @@ struct ath12k { + u32 cached_ppdu_id; + + bool dfs_block_radar_events; ++ struct ath12k_thermal thermal; + bool monitor_conf_enabled; + bool monitor_vdev_created; + bool monitor_started; +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -6971,6 +6971,7 @@ int ath12k_mac_allocate(struct ath12k_ba + init_completion(&ar->bss_survey_done); + init_completion(&ar->scan.started); + init_completion(&ar->scan.completed); ++ init_completion(&ar->thermal.wmi_sync); + + INIT_DELAYED_WORK(&ar->scan.timeout, ath12k_scan_timeout_work); + INIT_WORK(&ar->regd_update_work, ath12k_regd_update_work); +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/thermal.c +@@ -0,0 +1,227 @@ ++// SPDX-License-Identifier: BSD-3-Clause-Clear ++/* ++ * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "core.h" ++#include "debug.h" ++ ++static int ++ath12k_thermal_get_max_throttle_state(struct thermal_cooling_device *cdev, ++ unsigned long *state) ++{ ++ *state = ATH12K_THERMAL_THROTTLE_MAX; ++ ++ return 0; ++} ++ ++static int ++ath12k_thermal_get_cur_throttle_state(struct thermal_cooling_device *cdev, ++ unsigned long *state) ++{ ++ struct ath12k *ar = cdev->devdata; ++ ++ mutex_lock(&ar->conf_mutex); ++ *state = ar->thermal.throttle_state; ++ mutex_unlock(&ar->conf_mutex); ++ ++ return 0; ++} ++ ++static int ++ath12k_thermal_set_cur_throttle_state(struct thermal_cooling_device *cdev, ++ unsigned long throttle_state) ++{ ++ struct ath12k *ar = cdev->devdata; ++ int ret; ++ ++ if (throttle_state > ATH12K_THERMAL_THROTTLE_MAX) { ++ ath12k_warn(ar->ab, "throttle state %ld is exceeding the limit %d\n", ++ throttle_state, ATH12K_THERMAL_THROTTLE_MAX); ++ return -EINVAL; ++ } ++ mutex_lock(&ar->conf_mutex); ++ ret = ath12k_thermal_set_throttling(ar, throttle_state); ++ if (ret == 0) ++ ar->thermal.throttle_state = throttle_state; ++ mutex_unlock(&ar->conf_mutex); ++ return ret; ++} ++ ++static const struct thermal_cooling_device_ops ath12k_thermal_ops = { ++ .get_max_state = ath12k_thermal_get_max_throttle_state, ++ .get_cur_state = ath12k_thermal_get_cur_throttle_state, ++ .set_cur_state = ath12k_thermal_set_cur_throttle_state, ++}; ++ ++static ssize_t ath12k_thermal_show_temp(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct ath12k *ar = dev_get_drvdata(dev); ++ int ret, temperature; ++ unsigned long time_left; ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ /* Can't get temperature when the card is off */ ++ if (ar->state != ATH12K_STATE_ON) { ++ ret = -ENETDOWN; ++ goto out; ++ } ++ ++ reinit_completion(&ar->thermal.wmi_sync); ++ ret = ath12k_wmi_send_pdev_temperature_cmd(ar); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to read temperature %d\n", ret); ++ goto out; ++ } ++ ++ if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags)) { ++ ret = -ESHUTDOWN; ++ goto out; ++ } ++ ++ time_left = wait_for_completion_timeout(&ar->thermal.wmi_sync, ++ ATH12K_THERMAL_SYNC_TIMEOUT_HZ); ++ if (!time_left) { ++ ath12k_warn(ar->ab, "failed to synchronize thermal read\n"); ++ ret = -ETIMEDOUT; ++ goto out; ++ } ++ ++ spin_lock_bh(&ar->data_lock); ++ temperature = ar->thermal.temperature; ++ spin_unlock_bh(&ar->data_lock); ++ ++ /* display in millidegree celcius */ ++ ret = snprintf(buf, PAGE_SIZE, "%d\n", temperature * 1000); ++out: ++ mutex_unlock(&ar->conf_mutex); ++ return ret; ++} ++ ++void ath12k_thermal_event_temperature(struct ath12k *ar, int temperature) ++{ ++ spin_lock_bh(&ar->data_lock); ++ ar->thermal.temperature = temperature; ++ spin_unlock_bh(&ar->data_lock); ++ complete(&ar->thermal.wmi_sync); ++} ++ ++static SENSOR_DEVICE_ATTR(temp1_input, 0444, ath12k_thermal_show_temp, ++ NULL, 0); ++ ++static struct attribute *ath12k_hwmon_attrs[] = { ++ &sensor_dev_attr_temp1_input.dev_attr.attr, ++ NULL, ++}; ++ATTRIBUTE_GROUPS(ath12k_hwmon); ++ ++int ath12k_thermal_set_throttling(struct ath12k *ar, u32 throttle_state) ++{ ++ struct ath12k_base *sc = ar->ab; ++ struct thermal_mitigation_params param; ++ int ret = 0; ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ if (ar->state != ATH12K_STATE_ON) ++ return 0; ++ ++ memset(¶m, 0, sizeof(param)); ++ param.pdev_id = ar->pdev->pdev_id; ++ param.enable = throttle_state ? 1 : 0; ++ param.dc = ATH12K_THERMAL_DEFAULT_DUTY_CYCLE; ++ param.dc_per_event = 0xFFFFFFFF; ++ ++ param.levelconf[0].tmplwm = ATH12K_THERMAL_TEMP_LOW_MARK; ++ param.levelconf[0].tmphwm = ATH12K_THERMAL_TEMP_HIGH_MARK; ++ param.levelconf[0].dcoffpercent = throttle_state; ++ param.levelconf[0].priority = 0; /* disable all data tx queues */ ++ ++ ret = ath12k_wmi_send_thermal_mitigation_param_cmd(ar, ¶m); ++ if (ret) { ++ ath12k_warn(sc, "failed to send thermal mitigation duty cycle %u ret %d\n", ++ throttle_state, ret); ++ } ++ ++ return ret; ++} ++ ++int ath12k_thermal_register(struct ath12k_base *sc) ++{ ++ struct thermal_cooling_device *cdev; ++ struct device *hwmon_dev; ++ struct ath12k *ar; ++ struct ath12k_pdev *pdev; ++ int i, ret; ++ ++ for (i = 0; i < sc->num_radios; i++) { ++ pdev = &sc->pdevs[i]; ++ ar = pdev->ar; ++ if (!ar) ++ continue; ++ ++ cdev = thermal_cooling_device_register("ath12k_thermal", ar, ++ &ath12k_thermal_ops); ++ ++ if (IS_ERR(cdev)) { ++ ath12k_err(sc, "failed to setup thermal device result: %ld\n", ++ PTR_ERR(cdev)); ++ ret = -EINVAL; ++ goto err_thermal_destroy; ++ } ++ ++ ar->thermal.cdev = cdev; ++ ++ ret = sysfs_create_link(&ar->hw->wiphy->dev.kobj, &cdev->device.kobj, ++ "cooling_device"); ++ if (ret) { ++ ath12k_err(sc, "failed to create cooling device symlink\n"); ++ goto err_thermal_destroy; ++ } ++ ++ if (!IS_REACHABLE(CONFIG_HWMON)) ++ return 0; ++ ++ hwmon_dev = devm_hwmon_device_register_with_groups(&ar->hw->wiphy->dev, ++ "ath12k_hwmon", ar, ++ ath12k_hwmon_groups); ++ if (IS_ERR(hwmon_dev)) { ++ ath12k_err(ar->ab, "failed to register hwmon device: %ld\n", ++ PTR_ERR(hwmon_dev)); ++ ret = -EINVAL; ++ goto err_thermal_destroy; ++ } ++ } ++ ++ return 0; ++ ++err_thermal_destroy: ++ ath12k_thermal_unregister(sc); ++ return ret; ++} ++ ++void ath12k_thermal_unregister(struct ath12k_base *sc) ++{ ++ struct ath12k *ar; ++ struct ath12k_pdev *pdev; ++ int i; ++ ++ for (i = 0; i < sc->num_radios; i++) { ++ pdev = &sc->pdevs[i]; ++ ar = pdev->ar; ++ if (!ar) ++ continue; ++ ++ sysfs_remove_link(&ar->hw->wiphy->dev.kobj, "cooling_device"); ++ thermal_cooling_device_unregister(ar->thermal.cdev); ++ } ++} +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/thermal.h +@@ -0,0 +1,55 @@ ++/* SPDX-License-Identifier: BSD-3-Clause-Clear */ ++/* ++ * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef _ATH12K_THERMAL_ ++#define _ATH12K_THERMAL_ ++ ++#define ATH12K_THERMAL_TEMP_LOW_MARK -100 ++#define ATH12K_THERMAL_TEMP_HIGH_MARK 150 ++#define ATH12K_THERMAL_THROTTLE_MAX 100 ++#define ATH12K_THERMAL_DEFAULT_DUTY_CYCLE 100 ++#define ATH12K_HWMON_NAME_LEN 15 ++#define ATH12K_THERMAL_SYNC_TIMEOUT_HZ (5 * HZ) ++ ++struct ath12k_thermal { ++ struct thermal_cooling_device *cdev; ++ struct completion wmi_sync; ++ ++ /* protected by conf_mutex */ ++ u32 throttle_state; ++ /* temperature value in Celcius degree ++ * protected by data_lock ++ */ ++ int temperature; ++}; ++ ++#if IS_REACHABLE(CONFIG_THERMAL) ++int ath12k_thermal_register(struct ath12k_base *sc); ++void ath12k_thermal_unregister(struct ath12k_base *sc); ++int ath12k_thermal_set_throttling(struct ath12k *ar, u32 throttle_state); ++void ath12k_thermal_event_temperature(struct ath12k *ar, int temperature); ++#else ++static inline int ath12k_thermal_register(struct ath12k_base *sc) ++{ ++ return 0; ++} ++ ++static inline void ath12k_thermal_unregister(struct ath12k_base *sc) ++{ ++} ++ ++static inline int ath12k_thermal_set_throttling(struct ath12k *ar, u32 throttle_state) ++{ ++ return 0; ++} ++ ++static inline void ath12k_thermal_event_temperature(struct ath12k *ar, ++ int temperature) ++{ ++} ++ ++#endif ++#endif /* _ATH12K_THERMAL_ */ +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -6923,6 +6923,8 @@ ath12k_wmi_pdev_temperature_event(struct + ath12k_warn(ab, "invalid pdev id in pdev temperature ev %d", ev.pdev_id); + return; + } ++ ++ ath12k_thermal_event_temperature(ar, ev.temp); + } + + static void ath12k_fils_discovery_event(struct ath12k_base *ab, diff --git a/feeds/ipq95xx/mac80211/patches/qca/503-ath12k-add-debugfs.h.patch b/feeds/ipq95xx/mac80211/patches/qca/503-ath12k-add-debugfs.h.patch new file mode 100644 index 000000000..fbcf162a4 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/503-ath12k-add-debugfs.h.patch @@ -0,0 +1,95 @@ +From 3535797e674f7d5815ce20ec82266e282b117b98 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Thu, 1 Sep 2022 15:51:25 +0530 +Subject: [PATCH 2/5] Revert "ath12k: remove debugfs.h" + +This reverts commit cb0c65e98f9148be757795133c807b31942aa397. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath12k/debug.h | 1 + + drivers/net/wireless/ath/ath12k/debugfs.h | 26 +++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/dp_rx.h | 11 ---------- + drivers/net/wireless/ath/ath12k/mac.h | 3 --- + 4 files changed, 27 insertions(+), 14 deletions(-) + create mode 100644 drivers/net/wireless/ath/ath12k/debugfs.h + +--- a/drivers/net/wireless/ath/ath12k/debug.h ++++ b/drivers/net/wireless/ath/ath12k/debug.h +@@ -8,6 +8,7 @@ + #define _ATH12K_DEBUG_H_ + + #include "trace.h" ++#include "debugfs.h" + + enum ath12k_debug_mask { + ATH12K_DBG_AHB = 0x00000001, +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/debugfs.h +@@ -0,0 +1,26 @@ ++/* SPDX-License-Identifier: BSD-3-Clause-Clear */ ++/* ++ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef _ATH12K_DEBUGFS_H_ ++#define _ATH12K_DEBUGFS_H_ ++ ++#define ATH12K_TX_POWER_MAX_VAL 70 ++#define ATH12K_TX_POWER_MIN_VAL 0 ++ ++struct ath_pktlog_hdr { ++ u16 flags; ++ u16 missed_cnt; ++ u16 log_type; ++ u16 size; ++ u32 timestamp; ++ u32 type_specific_data; ++ struct mlo_timestamp m_timestamp; ++ u8 payload[]; ++}; ++ ++#define ATH12K_FW_STATS_BUF_SIZE (1024 * 1024) ++ ++#endif /* _ATH12K_DEBUGFS_H_ */ +--- a/drivers/net/wireless/ath/ath12k/dp_rx.h ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.h +@@ -65,17 +65,6 @@ struct ath12k_dp_rx_rfc1042_hdr { + __be16 snap_type; + } __packed; + +-struct ath_pktlog_hdr { +- u16 flags; +- u16 missed_cnt; +- u16 log_type; +- u16 size; +- u32 timestamp; +- u32 type_specific_data; +- struct mlo_timestamp m_timestamp; +- u8 payload[]; +-}; +- + static inline u32 ath12k_he_gi_to_nl80211_he_gi(u8 sgi) + { + u32 ret = 0; +--- a/drivers/net/wireless/ath/ath12k/mac.h ++++ b/drivers/net/wireless/ath/ath12k/mac.h +@@ -117,9 +117,6 @@ struct ath12k_generic_iter { + + #define ATH12K_CHAN_WIDTH_NUM 8 + +-#define ATH12K_TX_POWER_MAX_VAL 70 +-#define ATH12K_TX_POWER_MIN_VAL 0 +- + extern const struct htt_rx_ring_tlv_filter ath12k_mac_mon_status_filter_default; + + void ath12k_mac_destroy(struct ath12k_base *ab); +--- a/local-symbols ++++ b/local-symbols +@@ -137,4 +137,5 @@ ATH11K_CFR= + ATH11K_SMART_ANT_ALG= + ATH12K= + ATH12K_DEBUG= ++ATH12K_DEBUGFS= + ATH12K_TRACING= diff --git a/feeds/ipq95xx/mac80211/patches/qca/504-ath12k-add-debugfs-support.patch b/feeds/ipq95xx/mac80211/patches/qca/504-ath12k-add-debugfs-support.patch new file mode 100644 index 000000000..48cf0a926 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/504-ath12k-add-debugfs-support.patch @@ -0,0 +1,9427 @@ +From 29a8697dd79305fe297c2c1b8dd28fd08f8b7dea Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Thu, 1 Sep 2022 15:51:39 +0530 +Subject: [PATCH 3/5] Revert "ath12k: remove debugfs support" + +This reverts commit caa2f39cd59ba34be73e788ca2f6d8ed45de980f. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath12k/Kconfig | 8 + + drivers/net/wireless/ath/ath12k/Makefile | 1 + + drivers/net/wireless/ath/ath12k/core.c | 22 +- + drivers/net/wireless/ath/ath12k/core.h | 36 + + drivers/net/wireless/ath/ath12k/debugfs.c | 1216 +++++ + drivers/net/wireless/ath/ath12k/debugfs.h | 205 + + .../wireless/ath/ath12k/debugfs_htt_stats.c | 4599 +++++++++++++++++ + .../wireless/ath/ath12k/debugfs_htt_stats.h | 1714 ++++++ + drivers/net/wireless/ath/ath12k/debugfs_sta.c | 1081 ++++ + drivers/net/wireless/ath/ath12k/debugfs_sta.h | 46 + + drivers/net/wireless/ath/ath12k/dp.c | 6 +- + drivers/net/wireless/ath/ath12k/dp_mon.c | 18 + + drivers/net/wireless/ath/ath12k/dp_rx.c | 9 + + drivers/net/wireless/ath/ath12k/dp_tx.c | 41 + + drivers/net/wireless/ath/ath12k/mac.c | 36 +- + drivers/net/wireless/ath/ath12k/pci.c | 12 +- + drivers/net/wireless/ath/ath12k/wmi.c | 1 + + 17 files changed, 9043 insertions(+), 8 deletions(-) + create mode 100644 drivers/net/wireless/ath/ath12k/debugfs.c + create mode 100644 drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c + create mode 100644 drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h + create mode 100644 drivers/net/wireless/ath/ath12k/debugfs_sta.c + create mode 100644 drivers/net/wireless/ath/ath12k/debugfs_sta.h + +--- a/drivers/net/wireless/ath/ath12k/Kconfig ++++ b/drivers/net/wireless/ath/ath12k/Kconfig +@@ -23,6 +23,14 @@ config ATH12K_DEBUG + + If unsure, say Y to make it easier to debug problems. + ++config ATH12K_DEBUGFS ++ bool "QTI ath12k debugfs support" ++ depends on ATH12K && DEBUG_FS && MAC80211_DEBUGFS ++ help ++ Enable ath12k debugfs support ++ ++ If unsure, say Y to make it easier to debug problems. ++ + config ATH12K_TRACING + bool "ath12k tracing support" + depends on ATH12K && EVENT_TRACING +--- a/drivers/net/wireless/ath/ath12k/Makefile ++++ b/drivers/net/wireless/ath/ath12k/Makefile +@@ -22,6 +22,7 @@ ath12k-y += core.o \ + pci.o \ + dp_mon.o + ++ath12k-$(CPTCFG_ATH12K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o + ath12k-$(CPTCFG_ATH12K_TRACING) += trace.o + ath12k-$(CONFIG_THERMAL) += thermal.o + +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -433,14 +433,22 @@ static int ath12k_core_soc_create(struct + return ret; + } + ++ ret = ath12k_debugfs_soc_create(ab); ++ if (ret) { ++ ath12k_err(ab, "failed to create ath12k debugfs\n"); ++ goto err_qmi_deinit; ++ } ++ + ret = ath12k_hif_power_up(ab); + if (ret) { + ath12k_err(ab, "failed to power up :%d\n", ret); +- goto err_qmi_deinit; ++ goto err_debugfs_reg; + } + + return 0; + ++err_debugfs_reg: ++ ath12k_debugfs_soc_destroy(ab); + err_qmi_deinit: + ath12k_qmi_deinit_service(ab); + return ret; +@@ -448,6 +456,7 @@ err_qmi_deinit: + + static void ath12k_core_soc_destroy(struct ath12k_base *ab) + { ++ ath12k_debugfs_soc_destroy(ab); + ath12k_dp_free(ab); + ath12k_reg_free(ab); + ath12k_qmi_deinit_service(ab); +@@ -457,10 +466,16 @@ static int ath12k_core_pdev_create(struc + { + int ret; + ++ ret = ath12k_debugfs_pdev_create(ab); ++ if (ret) { ++ ath12k_err(ab, "failed to create core pdev debugfs: %d\n", ret); ++ return ret; ++ } ++ + ret = ath12k_mac_register(ab); + if (ret) { + ath12k_err(ab, "failed register the radio with mac80211: %d\n", ret); +- return ret; ++ goto err_pdev_debug; + } + + ret = ath12k_dp_pdev_alloc(ab); +@@ -482,6 +497,8 @@ err_dp_pdev_free: + ath12k_dp_pdev_free(ab); + err_mac_unregister: + ath12k_mac_unregister(ab); ++err_pdev_debug: ++ ath12k_debugfs_pdev_destroy(ab); + + return ret; + } +@@ -492,6 +509,7 @@ static void ath12k_core_pdev_destroy(str + ath12k_mac_unregister(ab); + ath12k_hif_irq_disable(ab); + ath12k_dp_pdev_free(ab); ++ ath12k_debugfs_pdev_destroy(ab); + } + + static int ath12k_core_start(struct ath12k_base *ab, +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -424,8 +424,14 @@ struct ath12k_sta { + u64 rx_duration; + u64 tx_duration; + u8 rssi_comb; ++ struct ath12k_htt_tx_stats *tx_stats; + struct ath12k_rx_peer_stats *rx_stats; + struct ath12k_wbm_tx_stats *wbm_tx_stats; ++ ++#ifdef CPTCFG_MAC80211_DEBUGFS ++ /* protected by conf_mutex */ ++ bool aggr_mode; ++#endif + }; + + #define ATH12K_MIN_5G_FREQ 4150 +@@ -447,6 +453,7 @@ enum ath12k_state { + #define ATH12K_DEFAULT_NOISE_FLOOR -95 + + struct ath12k_fw_stats { ++ struct dentry *debugfs_fwstats; + u32 pdev_id; + u32 stats_id; + struct list_head pdevs; +@@ -454,6 +461,29 @@ struct ath12k_fw_stats { + struct list_head bcn; + }; + ++struct ath12k_dbg_htt_stats { ++ u8 type; ++ u8 reset; ++ struct debug_htt_stats_req *stats_req; ++ /* protects shared stats req buffer */ ++ spinlock_t lock; ++}; ++ ++struct ath12k_debug { ++ struct dentry *debugfs_pdev; ++ struct ath12k_dbg_htt_stats htt_stats; ++ u32 extd_tx_stats; ++ struct ath12k_fw_stats fw_stats; ++ struct completion fw_stats_complete; ++ bool fw_stats_done; ++ u32 extd_rx_stats; ++ u32 pktlog_filter; ++ u32 pktlog_mode; ++ u32 pktlog_peer_valid; ++ u8 pktlog_peer_addr[ETH_ALEN]; ++ u32 rx_filter; ++}; ++ + struct ath12k_per_peer_tx_stats { + u32 succ_bytes; + u32 retry_bytes; +@@ -592,6 +622,9 @@ struct ath12k { + struct ath12k_per_peer_tx_stats cached_stats; + u32 last_ppdu_id; + u32 cached_ppdu_id; ++#ifdef CPTCFG_ATH12K_DEBUGFS ++ struct ath12k_debug debug; ++#endif + + bool dfs_block_radar_events; + struct ath12k_thermal thermal; +@@ -763,6 +796,9 @@ struct ath12k_base { + + /* Current DFS Regulatory */ + enum ath12k_dfs_region dfs_region; ++#ifdef CPTCFG_ATH12K_DEBUGFS ++ struct dentry *debugfs_soc; ++#endif + struct ath12k_soc_dp_stats soc_stats; + + unsigned long dev_flags; +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -0,0 +1,1216 @@ ++// SPDX-License-Identifier: BSD-3-Clause-Clear ++/* ++ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include "debugfs.h" ++ ++#include "core.h" ++#include "debug.h" ++#include "wmi.h" ++#include "hal_rx.h" ++#include "dp_tx.h" ++#include "debugfs_htt_stats.h" ++#include "peer.h" ++ ++static struct dentry *debugfs_ath12k; ++ ++static const char *htt_bp_umac_ring[HTT_SW_UMAC_RING_IDX_MAX] = { ++ "REO2SW1_RING", ++ "REO2SW2_RING", ++ "REO2SW3_RING", ++ "REO2SW4_RING", ++ "WBM2REO_LINK_RING", ++ "REO2TCL_RING", ++ "REO2FW_RING", ++ "RELEASE_RING", ++ "PPE_RELEASE_RING", ++ "TCL2TQM_RING", ++ "TQM_RELEASE_RING", ++ "REO_RELEASE_RING", ++ "WBM2SW0_RELEASE_RING", ++ "WBM2SW1_RELEASE_RING", ++ "WBM2SW2_RELEASE_RING", ++ "WBM2SW3_RELEASE_RING", ++ "REO_CMD_RING", ++ "REO_STATUS_RING", ++}; ++ ++static const char *htt_bp_lmac_ring[HTT_SW_LMAC_RING_IDX_MAX] = { ++ "FW2RXDMA_BUF_RING", ++ "FW2RXDMA_STATUS_RING", ++ "FW2RXDMA_LINK_RING", ++ "SW2RXDMA_BUF_RING", ++ "WBM2RXDMA_LINK_RING", ++ "RXDMA2FW_RING", ++ "RXDMA2SW_RING", ++ "RXDMA2RELEASE_RING", ++ "RXDMA2REO_RING", ++ "MONITOR_STATUS_RING", ++ "MONITOR_BUF_RING", ++ "MONITOR_DESC_RING", ++ "MONITOR_DEST_RING", ++}; ++ ++static void ath12k_fw_stats_pdevs_free(struct list_head *head) ++{ ++ struct ath12k_fw_stats_pdev *i, *tmp; ++ ++ list_for_each_entry_safe(i, tmp, head, list) { ++ list_del(&i->list); ++ kfree(i); ++ } ++} ++ ++static void ath12k_fw_stats_vdevs_free(struct list_head *head) ++{ ++ struct ath12k_fw_stats_vdev *i, *tmp; ++ ++ list_for_each_entry_safe(i, tmp, head, list) { ++ list_del(&i->list); ++ kfree(i); ++ } ++} ++ ++static void ath12k_fw_stats_bcn_free(struct list_head *head) ++{ ++ struct ath12k_fw_stats_bcn *i, *tmp; ++ ++ list_for_each_entry_safe(i, tmp, head, list) { ++ list_del(&i->list); ++ kfree(i); ++ } ++} ++ ++static void ath12k_debugfs_fw_stats_reset(struct ath12k *ar) ++{ ++ spin_lock_bh(&ar->data_lock); ++ ar->debug.fw_stats_done = false; ++ ath12k_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs); ++ ath12k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs); ++ spin_unlock_bh(&ar->data_lock); ++} ++ ++void ath12k_debugfs_fw_stats_process(struct ath12k_base *ab, struct sk_buff *skb) ++{ ++ struct ath12k_fw_stats stats = {}; ++ struct ath12k *ar; ++ struct ath12k_pdev *pdev; ++ bool is_end; ++ static unsigned int num_vdev, num_bcn; ++ size_t total_vdevs_started = 0; ++ int i, ret; ++ ++ INIT_LIST_HEAD(&stats.pdevs); ++ INIT_LIST_HEAD(&stats.vdevs); ++ INIT_LIST_HEAD(&stats.bcn); ++ ++ ret = ath12k_wmi_pull_fw_stats(ab, skb, &stats); ++ if (ret) { ++ ath12k_warn(ab, "failed to pull fw stats: %d\n", ret); ++ goto free; ++ } ++ ++ rcu_read_lock(); ++ ar = ath12k_mac_get_ar_by_pdev_id(ab, stats.pdev_id); ++ if (!ar) { ++ rcu_read_unlock(); ++ ath12k_warn(ab, "failed to get ar for pdev_id %d: %d\n", ++ stats.pdev_id, ret); ++ goto free; ++ } ++ ++ spin_lock_bh(&ar->data_lock); ++ ++ if (stats.stats_id == WMI_REQUEST_PDEV_STAT) { ++ list_splice_tail_init(&stats.pdevs, &ar->debug.fw_stats.pdevs); ++ ar->debug.fw_stats_done = true; ++ goto complete; ++ } ++ ++ if (stats.stats_id == WMI_REQUEST_VDEV_STAT) { ++ if (list_empty(&stats.vdevs)) { ++ ath12k_warn(ab, "empty vdev stats"); ++ goto complete; ++ } ++ /* FW sends all the active VDEV stats irrespective of PDEV, ++ * hence limit until the count of all VDEVs started ++ */ ++ for (i = 0; i < ab->num_radios; i++) { ++ pdev = rcu_dereference(ab->pdevs_active[i]); ++ if (pdev && pdev->ar) ++ total_vdevs_started += ar->num_started_vdevs; ++ } ++ ++ is_end = ((++num_vdev) == total_vdevs_started); ++ ++ list_splice_tail_init(&stats.vdevs, ++ &ar->debug.fw_stats.vdevs); ++ ++ if (is_end) { ++ ar->debug.fw_stats_done = true; ++ num_vdev = 0; ++ } ++ goto complete; ++ } ++ ++ if (stats.stats_id == WMI_REQUEST_BCN_STAT) { ++ if (list_empty(&stats.bcn)) { ++ ath12k_warn(ab, "empty bcn stats"); ++ goto complete; ++ } ++ /* Mark end until we reached the count of all started VDEVs ++ * within the PDEV ++ */ ++ is_end = ((++num_bcn) == ar->num_started_vdevs); ++ ++ list_splice_tail_init(&stats.bcn, ++ &ar->debug.fw_stats.bcn); ++ ++ if (is_end) { ++ ar->debug.fw_stats_done = true; ++ num_bcn = 0; ++ } ++ } ++complete: ++ complete(&ar->debug.fw_stats_complete); ++ rcu_read_unlock(); ++ spin_unlock_bh(&ar->data_lock); ++ ++free: ++ ath12k_fw_stats_pdevs_free(&stats.pdevs); ++ ath12k_fw_stats_vdevs_free(&stats.vdevs); ++ ath12k_fw_stats_bcn_free(&stats.bcn); ++} ++ ++static int ath12k_debugfs_fw_stats_request(struct ath12k *ar, ++ struct stats_request_params *req_param) ++{ ++ struct ath12k_base *ab = ar->ab; ++ unsigned long timeout, time_left; ++ int ret; ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ /* FW stats can get split when exceeding the stats data buffer limit. ++ * In that case, since there is no end marking for the back-to-back ++ * received 'update stats' event, we keep a 3 seconds timeout in case, ++ * fw_stats_done is not marked yet ++ */ ++ timeout = jiffies + msecs_to_jiffies(3 * HZ); ++ ++ ath12k_debugfs_fw_stats_reset(ar); ++ ++ reinit_completion(&ar->debug.fw_stats_complete); ++ ++ ret = ath12k_wmi_send_stats_request_cmd(ar, req_param); ++ ++ if (ret) { ++ ath12k_warn(ab, "could not request fw stats (%d)\n", ++ ret); ++ return ret; ++ } ++ ++ time_left = ++ wait_for_completion_timeout(&ar->debug.fw_stats_complete, ++ 1 * HZ); ++ if (!time_left) ++ return -ETIMEDOUT; ++ ++ for (;;) { ++ if (time_after(jiffies, timeout)) ++ break; ++ ++ spin_lock_bh(&ar->data_lock); ++ if (ar->debug.fw_stats_done) { ++ spin_unlock_bh(&ar->data_lock); ++ break; ++ } ++ spin_unlock_bh(&ar->data_lock); ++ } ++ return 0; ++} ++ ++static int ath12k_open_pdev_stats(struct inode *inode, struct file *file) ++{ ++ struct ath12k *ar = inode->i_private; ++ struct ath12k_base *ab = ar->ab; ++ struct stats_request_params req_param; ++ void *buf = NULL; ++ int ret; ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ if (ar->state != ATH12K_STATE_ON) { ++ ret = -ENETDOWN; ++ goto err_unlock; ++ } ++ ++ buf = vmalloc(ATH12K_FW_STATS_BUF_SIZE); ++ if (!buf) { ++ ret = -ENOMEM; ++ goto err_unlock; ++ } ++ ++ req_param.pdev_id = ar->pdev->pdev_id; ++ req_param.vdev_id = 0; ++ req_param.stats_id = WMI_REQUEST_PDEV_STAT; ++ ++ ret = ath12k_debugfs_fw_stats_request(ar, &req_param); ++ if (ret) { ++ ath12k_warn(ab, "failed to request fw pdev stats: %d\n", ret); ++ goto err_free; ++ } ++ ++ ath12k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, req_param.stats_id, ++ buf); ++ ++ file->private_data = buf; ++ ++ mutex_unlock(&ar->conf_mutex); ++ return 0; ++ ++err_free: ++ vfree(buf); ++ ++err_unlock: ++ mutex_unlock(&ar->conf_mutex); ++ return ret; ++} ++ ++static int ath12k_release_pdev_stats(struct inode *inode, struct file *file) ++{ ++ vfree(file->private_data); ++ ++ return 0; ++} ++ ++static ssize_t ath12k_read_pdev_stats(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ const char *buf = file->private_data; ++ size_t len = strlen(buf); ++ ++ return simple_read_from_buffer(user_buf, count, ppos, buf, len); ++} ++ ++static const struct file_operations fops_pdev_stats = { ++ .open = ath12k_open_pdev_stats, ++ .release = ath12k_release_pdev_stats, ++ .read = ath12k_read_pdev_stats, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++static int ath12k_open_vdev_stats(struct inode *inode, struct file *file) ++{ ++ struct ath12k *ar = inode->i_private; ++ struct stats_request_params req_param; ++ void *buf = NULL; ++ int ret; ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ if (ar->state != ATH12K_STATE_ON) { ++ ret = -ENETDOWN; ++ goto err_unlock; ++ } ++ ++ buf = vmalloc(ATH12K_FW_STATS_BUF_SIZE); ++ if (!buf) { ++ ret = -ENOMEM; ++ goto err_unlock; ++ } ++ ++ req_param.pdev_id = ar->pdev->pdev_id; ++ /* VDEV stats is always sent for all active VDEVs from FW */ ++ req_param.vdev_id = 0; ++ req_param.stats_id = WMI_REQUEST_VDEV_STAT; ++ ++ ret = ath12k_dp_tx_htt_h2t_vdev_stats_ol_req(ar, 0); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to request vdev stats offload: %d\n", ret); ++ goto err_free; ++ } ++ ++ ret = ath12k_debugfs_fw_stats_request(ar, &req_param); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to request fw vdev stats: %d\n", ret); ++ goto err_free; ++ } ++ ++ ath12k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, req_param.stats_id, ++ buf); ++ ++ file->private_data = buf; ++ ++ mutex_unlock(&ar->conf_mutex); ++ return 0; ++ ++err_free: ++ vfree(buf); ++ ++err_unlock: ++ mutex_unlock(&ar->conf_mutex); ++ return ret; ++} ++ ++static int ath12k_release_vdev_stats(struct inode *inode, struct file *file) ++{ ++ vfree(file->private_data); ++ ++ return 0; ++} ++ ++static ssize_t ath12k_read_vdev_stats(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ const char *buf = file->private_data; ++ size_t len = strlen(buf); ++ ++ return simple_read_from_buffer(user_buf, count, ppos, buf, len); ++} ++ ++static const struct file_operations fops_vdev_stats = { ++ .open = ath12k_open_vdev_stats, ++ .release = ath12k_release_vdev_stats, ++ .read = ath12k_read_vdev_stats, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++static int ath12k_open_bcn_stats(struct inode *inode, struct file *file) ++{ ++ struct ath12k *ar = inode->i_private; ++ struct ath12k_vif *arvif; ++ struct stats_request_params req_param; ++ void *buf = NULL; ++ int ret; ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ if (ar->state != ATH12K_STATE_ON) { ++ ret = -ENETDOWN; ++ goto err_unlock; ++ } ++ ++ buf = vmalloc(ATH12K_FW_STATS_BUF_SIZE); ++ if (!buf) { ++ ret = -ENOMEM; ++ goto err_unlock; ++ } ++ ++ req_param.stats_id = WMI_REQUEST_BCN_STAT; ++ req_param.pdev_id = ar->pdev->pdev_id; ++ ++ /* loop all active VDEVs for bcn stats */ ++ list_for_each_entry(arvif, &ar->arvifs, list) { ++ if (!arvif->is_up) ++ continue; ++ ++ req_param.vdev_id = arvif->vdev_id; ++ ret = ath12k_debugfs_fw_stats_request(ar, &req_param); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to request fw bcn stats: %d\n", ret); ++ goto err_free; ++ } ++ } ++ ++ ath12k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, req_param.stats_id, ++ buf); ++ ++ /* since beacon stats request is looped for all active VDEVs, saved fw ++ * stats is not freed for each request until done for all active VDEVs ++ */ ++ spin_lock_bh(&ar->data_lock); ++ ath12k_fw_stats_bcn_free(&ar->debug.fw_stats.bcn); ++ spin_unlock_bh(&ar->data_lock); ++ ++ file->private_data = buf; ++ ++ mutex_unlock(&ar->conf_mutex); ++ return 0; ++ ++err_free: ++ vfree(buf); ++ ++err_unlock: ++ mutex_unlock(&ar->conf_mutex); ++ return ret; ++} ++ ++static int ath12k_release_bcn_stats(struct inode *inode, struct file *file) ++{ ++ vfree(file->private_data); ++ ++ return 0; ++} ++ ++static ssize_t ath12k_read_bcn_stats(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ const char *buf = file->private_data; ++ size_t len = strlen(buf); ++ ++ return simple_read_from_buffer(user_buf, count, ppos, buf, len); ++} ++ ++static const struct file_operations fops_bcn_stats = { ++ .open = ath12k_open_bcn_stats, ++ .release = ath12k_release_bcn_stats, ++ .read = ath12k_read_bcn_stats, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++static ssize_t ath12k_read_simulate_fw_crash(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ const char buf[] = ++ "To simulate firmware crash write one of the keywords to this file:\n" ++ "`assert` - this will send WMI_FORCE_FW_HANG_CMDID to firmware to cause assert.\n" ++ "`hw-restart` - this will simply queue hw restart without fw/hw actually crashing.\n"; ++ ++ return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); ++} ++ ++/* Simulate firmware crash: ++ * 'soft': Call wmi command causing firmware hang. This firmware hang is ++ * recoverable by warm firmware reset. ++ * 'hard': Force firmware crash by setting any vdev parameter for not allowed ++ * vdev id. This is hard firmware crash because it is recoverable only by cold ++ * firmware reset. ++ */ ++static ssize_t ath12k_write_simulate_fw_crash(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k_base *ab = file->private_data; ++ struct ath12k_pdev *pdev; ++ struct ath12k *ar = ab->pdevs[0].ar; ++ char buf[32] = {0}; ++ ssize_t rc; ++ int i, ret, radioup = 0; ++ ++ for (i = 0; i < ab->num_radios; i++) { ++ pdev = &ab->pdevs[i]; ++ ar = pdev->ar; ++ if (ar && ar->state == ATH12K_STATE_ON) { ++ radioup = 1; ++ break; ++ } ++ } ++ /* filter partial writes and invalid commands */ ++ if (*ppos != 0 || count >= sizeof(buf) || count == 0) ++ return -EINVAL; ++ ++ rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count); ++ if (rc < 0) ++ return rc; ++ ++ /* drop the possible '\n' from the end */ ++ if (buf[*ppos - 1] == '\n') ++ buf[*ppos - 1] = '\0'; ++ ++ if (radioup == 0) { ++ ret = -ENETDOWN; ++ goto exit; ++ } ++ ++ if (!strcmp(buf, "assert")) { ++ ath12k_info(ab, "simulating firmware assert crash\n"); ++ ret = ath12k_wmi_force_fw_hang_cmd(ar, ++ ATH12K_WMI_FW_HANG_ASSERT_TYPE, ++ ATH12K_WMI_FW_HANG_DELAY); ++ } else { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ if (ret) { ++ ath12k_warn(ab, "failed to simulate firmware crash: %d\n", ret); ++ goto exit; ++ } ++ ++ ret = count; ++ ++exit: ++ return ret; ++} ++ ++static const struct file_operations fops_simulate_fw_crash = { ++ .read = ath12k_read_simulate_fw_crash, ++ .write = ath12k_write_simulate_fw_crash, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++static ssize_t ath12k_write_enable_extd_tx_stats(struct file *file, ++ const char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ u32 filter; ++ int ret; ++ ++ if (kstrtouint_from_user(ubuf, count, 0, &filter)) ++ return -EINVAL; ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ if (ar->state != ATH12K_STATE_ON) { ++ ret = -ENETDOWN; ++ goto out; ++ } ++ ++ if (filter == ar->debug.extd_tx_stats) { ++ ret = count; ++ goto out; ++ } ++ ++ ar->debug.extd_tx_stats = filter; ++ ret = count; ++ ++out: ++ mutex_unlock(&ar->conf_mutex); ++ return ret; ++} ++ ++static ssize_t ath12k_read_enable_extd_tx_stats(struct file *file, ++ char __user *ubuf, ++ size_t count, loff_t *ppos) ++ ++{ ++ char buf[32] = {0}; ++ struct ath12k *ar = file->private_data; ++ int len = 0; ++ ++ mutex_lock(&ar->conf_mutex); ++ len = scnprintf(buf, sizeof(buf) - len, "%08x\n", ++ ar->debug.extd_tx_stats); ++ mutex_unlock(&ar->conf_mutex); ++ ++ return simple_read_from_buffer(ubuf, count, ppos, buf, len); ++} ++ ++static const struct file_operations fops_extd_tx_stats = { ++ .read = ath12k_read_enable_extd_tx_stats, ++ .write = ath12k_write_enable_extd_tx_stats, ++ .open = simple_open ++}; ++ ++static ssize_t ath12k_write_extd_rx_stats(struct file *file, ++ const char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ struct htt_rx_ring_tlv_filter tlv_filter = {0}; ++ u32 enable, ring_id, rx_filter = 0; ++ int ret, i; ++ ++ if (kstrtouint_from_user(ubuf, count, 0, &enable)) ++ return -EINVAL; ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ if (ar->state != ATH12K_STATE_ON) { ++ ret = -ENETDOWN; ++ goto exit; ++ } ++ ++ if (enable > 1) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ if (enable == ar->debug.extd_rx_stats) { ++ ret = count; ++ goto exit; ++ } ++ ++ if (enable) { ++ rx_filter = HTT_RX_FILTER_TLV_FLAGS_MPDU_START; ++ rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_START; ++ rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END; ++ rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS; ++ rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT; ++ rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE; ++ ++ tlv_filter.rx_filter = rx_filter; ++ tlv_filter.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0; ++ tlv_filter.pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1; ++ tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2; ++ tlv_filter.pkt_filter_flags3 = HTT_RX_FP_CTRL_FILTER_FLASG3 | ++ HTT_RX_FP_DATA_FILTER_FLASG3; ++ } else { ++ tlv_filter = ath12k_mac_mon_status_filter_default; ++ } ++ ++ ar->debug.rx_filter = tlv_filter.rx_filter; ++ tlv_filter.offset_valid = false; ++ ++ for (i = 0; i < ar->ab->hw_params->num_rxmda_per_pdev; i++) { ++ ring_id = ar->dp.rxdma_mon_dst_ring[i].ring_id; ++ ret = ath12k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id, ++ HAL_RXDMA_MONITOR_DST, ++ DP_RXDMA_REFILL_RING_SIZE, ++ &tlv_filter); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to set rx filter for monitor status ring\n"); ++ goto exit; ++ } ++ } ++ ++ ar->debug.extd_rx_stats = enable; ++ ret = count; ++exit: ++ mutex_unlock(&ar->conf_mutex); ++ return ret; ++} ++ ++static ssize_t ath12k_read_extd_rx_stats(struct file *file, ++ char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ char buf[32]; ++ int len = 0; ++ ++ mutex_lock(&ar->conf_mutex); ++ len = scnprintf(buf, sizeof(buf) - len, "%d\n", ++ ar->debug.extd_rx_stats); ++ mutex_unlock(&ar->conf_mutex); ++ ++ return simple_read_from_buffer(ubuf, count, ppos, buf, len); ++} ++ ++static const struct file_operations fops_extd_rx_stats = { ++ .read = ath12k_read_extd_rx_stats, ++ .write = ath12k_write_extd_rx_stats, ++ .open = simple_open, ++}; ++ ++static int ath12k_fill_bp_stats(struct ath12k_base *ab, ++ struct ath12k_bp_stats *bp_stats, ++ char *buf, int len, int size) ++{ ++ lockdep_assert_held(&ab->base_lock); ++ ++ len += scnprintf(buf + len, size - len, "count: %u\n", ++ bp_stats->count); ++ len += scnprintf(buf + len, size - len, "hp: %u\n", ++ bp_stats->hp); ++ len += scnprintf(buf + len, size - len, "tp: %u\n", ++ bp_stats->tp); ++ len += scnprintf(buf + len, size - len, "seen before: %ums\n\n", ++ jiffies_to_msecs(jiffies - bp_stats->jiffies)); ++ return len; ++} ++ ++static ssize_t ath12k_debugfs_dump_soc_ring_bp_stats(struct ath12k_base *ab, ++ char *buf, int size) ++{ ++ struct ath12k_bp_stats *bp_stats; ++ bool stats_rxd = false; ++ u8 i, pdev_idx; ++ int len = 0; ++ ++ len += scnprintf(buf + len, size - len, "\nBackpressure Stats\n"); ++ len += scnprintf(buf + len, size - len, "==================\n"); ++ ++ spin_lock_bh(&ab->base_lock); ++ for (i = 0; i < HTT_SW_UMAC_RING_IDX_MAX; i++) { ++ bp_stats = &ab->soc_stats.bp_stats.umac_ring_bp_stats[i]; ++ ++ if (!bp_stats->count) ++ continue; ++ ++ len += scnprintf(buf + len, size - len, "Ring: %s\n", ++ htt_bp_umac_ring[i]); ++ len = ath12k_fill_bp_stats(ab, bp_stats, buf, len, size); ++ stats_rxd = true; ++ } ++ ++ for (i = 0; i < HTT_SW_LMAC_RING_IDX_MAX; i++) { ++ for (pdev_idx = 0; pdev_idx < MAX_RADIOS; pdev_idx++) { ++ bp_stats = ++ &ab->soc_stats.bp_stats.lmac_ring_bp_stats[i][pdev_idx]; ++ ++ if (!bp_stats->count) ++ continue; ++ ++ len += scnprintf(buf + len, size - len, "Ring: %s\n", ++ htt_bp_lmac_ring[i]); ++ len += scnprintf(buf + len, size - len, "pdev: %d\n", ++ pdev_idx); ++ len = ath12k_fill_bp_stats(ab, bp_stats, buf, len, size); ++ stats_rxd = true; ++ } ++ } ++ spin_unlock_bh(&ab->base_lock); ++ ++ if (!stats_rxd) ++ len += scnprintf(buf + len, size - len, ++ "No Ring Backpressure stats received\n\n"); ++ ++ return len; ++} ++ ++static ssize_t ath12k_debugfs_dump_soc_dp_stats(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k_base *ab = file->private_data; ++ struct ath12k_soc_dp_stats *soc_stats = &ab->soc_stats; ++ int len = 0, i, retval; ++ const int size = 4096; ++ static const char *rxdma_err[HAL_REO_ENTR_RING_RXDMA_ECODE_MAX] = { ++ "Overflow", "MPDU len", "FCS", "Decrypt", "TKIP MIC", ++ "Unencrypt", "MSDU len", "MSDU limit", "WiFi parse", ++ "AMSDU parse", "SA timeout", "DA timeout", ++ "Flow timeout", "Flush req"}; ++ static const char *reo_err[HAL_REO_DEST_RING_ERROR_CODE_MAX] = { ++ "Desc addr zero", "Desc inval", "AMPDU in non BA", ++ "Non BA dup", "BA dup", "Frame 2k jump", "BAR 2k jump", ++ "Frame OOR", "BAR OOR", "No BA session", ++ "Frame SN equal SSN", "PN check fail", "2k err", ++ "PN err", "Desc blocked"}; ++ ++ char *buf; ++ ++ buf = kzalloc(size, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ len += scnprintf(buf + len, size - len, "SOC RX STATS:\n\n"); ++ len += scnprintf(buf + len, size - len, "err ring pkts: %u\n", ++ soc_stats->err_ring_pkts); ++ len += scnprintf(buf + len, size - len, "Invalid RBM: %u\n\n", ++ soc_stats->invalid_rbm); ++ len += scnprintf(buf + len, size - len, "RXDMA errors:\n"); ++ for (i = 0; i < HAL_REO_ENTR_RING_RXDMA_ECODE_MAX; i++) ++ len += scnprintf(buf + len, size - len, "%s: %u\n", ++ rxdma_err[i], soc_stats->rxdma_error[i]); ++ ++ len += scnprintf(buf + len, size - len, "\nREO errors:\n"); ++ for (i = 0; i < HAL_REO_DEST_RING_ERROR_CODE_MAX; i++) ++ len += scnprintf(buf + len, size - len, "%s: %u\n", ++ reo_err[i], soc_stats->reo_error[i]); ++ ++ len += scnprintf(buf + len, size - len, "\nHAL REO errors:\n"); ++ len += scnprintf(buf + len, size - len, ++ "ring0: %u\nring1: %u\nring2: %u\nring3: %u\n", ++ soc_stats->hal_reo_error[0], ++ soc_stats->hal_reo_error[1], ++ soc_stats->hal_reo_error[2], ++ soc_stats->hal_reo_error[3]); ++ ++ len += scnprintf(buf + len, size - len, "\nSOC TX STATS:\n"); ++ len += scnprintf(buf + len, size - len, "\nTCL Ring Full Failures:\n"); ++ ++ for (i = 0; i < DP_TCL_NUM_RING_MAX; i++) ++ len += scnprintf(buf + len, size - len, "ring%d: %u\n", ++ i, soc_stats->tx_err.desc_na[i]); ++ ++ len += scnprintf(buf + len, size - len, ++ "\nMisc Transmit Failures: %d\n", ++ atomic_read(&soc_stats->tx_err.misc_fail)); ++ ++ len += ath12k_debugfs_dump_soc_ring_bp_stats(ab, buf + len, size - len); ++ ++ if (len > size) ++ len = size; ++ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ kfree(buf); ++ ++ return retval; ++} ++ ++static const struct file_operations fops_soc_dp_stats = { ++ .read = ath12k_debugfs_dump_soc_dp_stats, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++int ath12k_debugfs_pdev_create(struct ath12k_base *ab) ++{ ++ if (test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags)) ++ return 0; ++ ++ debugfs_create_file("simulate_fw_crash", 0600, ab->debugfs_soc, ab, ++ &fops_simulate_fw_crash); ++ ++ debugfs_create_file("soc_dp_stats", 0600, ab->debugfs_soc, ab, ++ &fops_soc_dp_stats); ++ ++ return 0; ++} ++ ++void ath12k_debugfs_pdev_destroy(struct ath12k_base *ab) ++{ ++} ++ ++int ath12k_debugfs_soc_create(struct ath12k_base *ab) ++{ ++ char soc_name[64] = { 0 }; ++ ++ if (!(IS_ERR_OR_NULL(ab->debugfs_soc))) ++ return 0; ++ ++ snprintf(soc_name, sizeof(soc_name), "%s_%s", ab->hw_params->name, ++ dev_name(ab->dev)); ++ ++ ab->debugfs_soc = debugfs_create_dir(soc_name, debugfs_ath12k); ++ ++ return PTR_ERR_OR_ZERO(ab->debugfs_soc); ++} ++ ++void ath12k_debugfs_soc_destroy(struct ath12k_base *ab) ++{ ++ debugfs_remove_recursive(ab->debugfs_soc); ++ ab->debugfs_soc = NULL; ++} ++ ++void ath12k_debugfs_fw_stats_init(struct ath12k *ar) ++{ ++ struct dentry *fwstats_dir = debugfs_create_dir("fw_stats", ++ ar->debug.debugfs_pdev); ++ ++ ar->debug.fw_stats.debugfs_fwstats = fwstats_dir; ++ ++ /* all stats debugfs files created are under "fw_stats" directory ++ * created per PDEV ++ */ ++ debugfs_create_file("pdev_stats", 0600, fwstats_dir, ar, ++ &fops_pdev_stats); ++ debugfs_create_file("vdev_stats", 0600, fwstats_dir, ar, ++ &fops_vdev_stats); ++ debugfs_create_file("beacon_stats", 0600, fwstats_dir, ar, ++ &fops_bcn_stats); ++ ++ INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs); ++ INIT_LIST_HEAD(&ar->debug.fw_stats.vdevs); ++ INIT_LIST_HEAD(&ar->debug.fw_stats.bcn); ++ ++ init_completion(&ar->debug.fw_stats_complete); ++} ++ ++static int ath12k_pktlog_enable_hybrid_mode(struct ath12k *ar, u32 filter, ++ u32 mode) ++{ ++ struct ath12k_base *ab = ar->ab; ++ struct htt_tx_ring_tlv_filter tlv_filter = {0}; ++ u32 tx_filter, tx_buf_size, ring_id; ++ int ret; ++ ++ if (mode == ATH12K_PKTLOG_MODE_FULL) { ++ tx_filter = HTT_TX_MON_FILTER_HYBRID_MODE; ++ tx_buf_size = DP_TX_MONITOR_BUF_SIZE; ++ } else if (mode == ATH12K_PKTLOG_MODE_LITE) { ++ ret = ath12k_dp_tx_htt_h2t_ppdu_stats_req(ar, ++ HTT_PPDU_STATS_TAG_PKTLOG); ++ if (ret) { ++ ath12k_err(ar->ab, "failed to enable pktlog lite: %d\n", ret); ++ goto out; ++ } ++ tx_filter = HTT_TX_MON_FILTER_HYBRID_MODE; ++ tx_buf_size = DP_RX_BUFFER_SIZE_LITE; ++ } else { ++ /* TODO: Default tx filter configuration */ ++ tx_buf_size = DP_TX_MONITOR_BUF_SIZE; ++ } ++ ++ tlv_filter.tx_mon_upstream_tlv_flags0 = tx_filter; ++ tlv_filter.tx_mon_upstream_tlv_flags2 = ++ HTT_TX_FILTER_TLV_FLAGS2_TXPCU_PHYTX_OTHER_TRANSMIT_INFO32; ++ ++ ring_id = ab->dp.tx_mon_buf_ring.refill_buf_ring.ring_id; ++ ret = ath12k_dp_tx_htt_tx_filter_setup(ab, ring_id, 0, ++ HAL_TX_MONITOR_BUF, ++ tx_buf_size, ++ &tlv_filter); ++ if (ret) { ++ ath12k_warn(ab, "failed to set tx filter for monitor buf %d\n", ret); ++ goto out; ++ } ++ ++ ath12k_dbg(ab, ATH12K_DBG_WMI, "pktlog filter %d hybrid mode %s\n", ++ filter, ((mode == ATH12K_PKTLOG_MODE_FULL) ? "full" : "lite")); ++ ++ ar->debug.pktlog_filter = filter; ++ ar->debug.pktlog_mode = mode; ++out: ++ return ret; ++} ++ ++static ssize_t ath12k_write_pktlog_filter(struct file *file, ++ const char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ struct ath12k_base *ab = ar->ab; ++ struct htt_rx_ring_tlv_filter tlv_filter = {0}; ++ struct htt_tx_ring_tlv_filter tx_tlv_filter = {0}; ++ u32 rx_filter = 0, filter, mode, ring_id; ++ u8 buf[128] = {0}; ++ int ret, hybrid_enable, rx_buf_sz; ++ ssize_t rc; ++ ++ mutex_lock(&ar->conf_mutex); ++ if (ar->state != ATH12K_STATE_ON) { ++ ret = -ENETDOWN; ++ goto out; ++ } ++ ++ rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count); ++ if (rc < 0) { ++ ret = rc; ++ goto out; ++ } ++ buf[rc] = '\0'; ++ ++ ret = sscanf(buf, "0x%x %u %d", &filter, &mode, &hybrid_enable); ++ if (ret < 2) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ if (ret == 2) ++ hybrid_enable = 0; ++ ++ if ((filter & ATH12K_PKTLOG_RX) && hybrid_enable) { ++ ret = -EINVAL; ++ ath12k_warn(ar->ab, ++ "Invalid configuration. Hybrid mode is only applicable when tx or lite pktlog is used"); ++ goto out; ++ } ++ ++ if (filter) { ++ if (hybrid_enable) ++ filter |= ATH12K_PKTLOG_HYBRID; ++ ret = ath12k_wmi_pdev_pktlog_enable(ar, filter); ++ if (ret) { ++ ath12k_warn(ar->ab, ++ "failed to enable pktlog filter %x: %d\n", ++ ar->debug.pktlog_filter, ret); ++ goto out; ++ } ++ } else { ++ ret = ath12k_wmi_pdev_pktlog_disable(ar); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to disable pktlog: %d\n", ret); ++ goto out; ++ } ++ } ++ ++ /* Clear Tx filter */ ++ ring_id = ab->dp.tx_mon_buf_ring.refill_buf_ring.ring_id; ++ ret = ath12k_dp_tx_htt_tx_filter_setup(ab, ring_id, 0, ++ HAL_TX_MONITOR_BUF, 0, ++ &tx_tlv_filter); ++ if (ret) { ++ ath12k_warn(ab, "failed to set tx filter for monitor buf %d\n", ret); ++ goto out; ++ } ++ ++ /* Clear rx filter set for monitor mode and rx status */ ++ tlv_filter.offset_valid = false; ++ ring_id = ab->dp.rxdma_mon_buf_ring.refill_buf_ring.ring_id; ++ ret = ath12k_dp_tx_htt_rx_filter_setup(ab, ring_id, 0, ++ HAL_RXDMA_MONITOR_BUF, ++ rx_buf_sz, &tlv_filter); ++ if (ret) { ++ ath12k_warn(ab, "failed to set rx filter for monitor status ring %d\n", ++ ret); ++ goto out; ++ } ++ ++ if (filter & ATH12K_PKTLOG_HYBRID) { ++ ret = ath12k_pktlog_enable_hybrid_mode(ar, filter, mode); ++ goto out; ++ } ++ ++#define HTT_RX_FILTER_TLV_LITE_MODE \ ++ (HTT_RX_FILTER_TLV_FLAGS_PPDU_START | \ ++ HTT_RX_FILTER_TLV_FLAGS_PPDU_END | \ ++ HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS | \ ++ HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT | \ ++ HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE | \ ++ HTT_RX_FILTER_TLV_FLAGS_MPDU_START) ++ ++ if (mode == ATH12K_PKTLOG_MODE_FULL) { ++ rx_filter = HTT_RX_FILTER_TLV_LITE_MODE | ++ HTT_RX_FILTER_TLV_FLAGS_MSDU_START | ++ HTT_RX_FILTER_TLV_FLAGS_MSDU_END | ++ HTT_RX_FILTER_TLV_FLAGS_MPDU_END | ++ HTT_RX_FILTER_TLV_FLAGS_PACKET_HEADER | ++ HTT_RX_FILTER_TLV_FLAGS_ATTENTION; ++ rx_buf_sz = DP_RX_BUFFER_SIZE; ++ } else if (mode == ATH12K_PKTLOG_MODE_LITE) { ++ ret = ath12k_dp_tx_htt_h2t_ppdu_stats_req(ar, ++ HTT_PPDU_STATS_TAG_PKTLOG); ++ if (ret) { ++ ath12k_err(ar->ab, "failed to enable pktlog lite: %d\n", ret); ++ goto out; ++ } ++ ++ rx_filter = HTT_RX_FILTER_TLV_LITE_MODE; ++ rx_buf_sz = DP_RX_BUFFER_SIZE_LITE; ++ } else { ++ rx_buf_sz = DP_RX_BUFFER_SIZE; ++ tlv_filter = ath12k_mac_mon_status_filter_default; ++ rx_filter = tlv_filter.rx_filter; ++ ++ ret = ath12k_dp_tx_htt_h2t_ppdu_stats_req(ar, ++ HTT_PPDU_STATS_TAG_DEFAULT); ++ if (ret) { ++ ath12k_err(ar->ab, "failed to send htt ppdu stats req: %d\n", ++ ret); ++ goto out; ++ } ++ } ++ ++ tlv_filter.rx_filter = rx_filter; ++ if (rx_filter) { ++ tlv_filter.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0; ++ tlv_filter.pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1; ++ tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2; ++ tlv_filter.pkt_filter_flags3 = HTT_RX_FP_CTRL_FILTER_FLASG3 | ++ HTT_RX_FP_DATA_FILTER_FLASG3; ++ } ++ ++ ret = ath12k_dp_tx_htt_rx_filter_setup(ab, ring_id, 0, ++ HAL_RXDMA_MONITOR_BUF, ++ rx_buf_sz, &tlv_filter); ++ if (ret) { ++ ath12k_warn(ab, "failed to set rx filter for monitor status ring %d\n", ++ ret); ++ goto out; ++ } ++ ++ ath12k_dbg(ab, ATH12K_DBG_WMI, "pktlog filter %d mode %s\n", ++ filter, ((mode == ATH12K_PKTLOG_MODE_FULL) ? "full" : "lite")); ++ ++ ar->debug.pktlog_filter = filter; ++ ar->debug.pktlog_mode = mode; ++ ret = count; ++ ++out: ++ mutex_unlock(&ar->conf_mutex); ++ return ret; ++} ++ ++static ssize_t ath12k_read_pktlog_filter(struct file *file, ++ char __user *ubuf, ++ size_t count, loff_t *ppos) ++ ++{ ++ char buf[32] = {0}; ++ struct ath12k *ar = file->private_data; ++ int len = 0; ++ ++ mutex_lock(&ar->conf_mutex); ++ len = scnprintf(buf, sizeof(buf) - len, "%08x %08x\n", ++ ar->debug.pktlog_filter, ++ ar->debug.pktlog_mode); ++ mutex_unlock(&ar->conf_mutex); ++ ++ return simple_read_from_buffer(ubuf, count, ppos, buf, len); ++} ++ ++static const struct file_operations fops_pktlog_filter = { ++ .read = ath12k_read_pktlog_filter, ++ .write = ath12k_write_pktlog_filter, ++ .open = simple_open ++}; ++ ++static ssize_t ath12k_write_simulate_radar(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ int ret; ++ ++ ret = ath12k_wmi_simulate_radar(ar); ++ if (ret) ++ return ret; ++ ++ return count; ++} ++ ++static const struct file_operations fops_simulate_radar = { ++ .write = ath12k_write_simulate_radar, ++ .open = simple_open ++}; ++ ++int ath12k_debugfs_register(struct ath12k *ar) ++{ ++ struct ath12k_base *ab = ar->ab; ++ char pdev_name[5]; ++ char buf[100] = {0}; ++ ++ snprintf(pdev_name, sizeof(pdev_name), "%s%d", "mac", ar->pdev_idx); ++ ++ ar->debug.debugfs_pdev = debugfs_create_dir(pdev_name, ab->debugfs_soc); ++ if (IS_ERR(ar->debug.debugfs_pdev)) ++ return PTR_ERR(ar->debug.debugfs_pdev); ++ ++ /* Create a symlink under ieee80211/phy* */ ++ snprintf(buf, 100, "../../ath12k/%pd2", ar->debug.debugfs_pdev); ++ debugfs_create_symlink("ath12k", ar->hw->wiphy->debugfsdir, buf); ++ ++ ath12k_debugfs_htt_stats_init(ar); ++ ++ ath12k_debugfs_fw_stats_init(ar); ++ ++ debugfs_create_file("ext_tx_stats", 0644, ++ ar->debug.debugfs_pdev, ar, ++ &fops_extd_tx_stats); ++ debugfs_create_file("ext_rx_stats", 0644, ++ ar->debug.debugfs_pdev, ar, ++ &fops_extd_rx_stats); ++ debugfs_create_file("pktlog_filter", 0644, ++ ar->debug.debugfs_pdev, ar, ++ &fops_pktlog_filter); ++ ++ if (ar->hw->wiphy->bands[NL80211_BAND_5GHZ]) { ++ debugfs_create_file("dfs_simulate_radar", 0200, ++ ar->debug.debugfs_pdev, ar, ++ &fops_simulate_radar); ++ debugfs_create_bool("dfs_block_radar_events", 0200, ++ ar->debug.debugfs_pdev, ++ &ar->dfs_block_radar_events); ++ } ++ ++ return 0; ++} ++ ++void ath12k_debugfs_unregister(struct ath12k *ar) ++{ ++} ++ ++int ath12k_debugfs_create(void) ++{ ++ debugfs_ath12k = debugfs_create_dir("ath12k", NULL); ++ if (IS_ERR_OR_NULL(debugfs_ath12k)) { ++ if (IS_ERR(debugfs_ath12k)) ++ return PTR_ERR(debugfs_ath12k); ++ else ++ return -ENOMEM; ++ } ++ ++ return 0; ++} ++ ++void ath12k_debugfs_destroy(void) ++{ ++ debugfs_remove_recursive(debugfs_ath12k); ++ debugfs_ath12k = NULL; ++} +--- a/drivers/net/wireless/ath/ath12k/debugfs.h ++++ b/drivers/net/wireless/ath/ath12k/debugfs.h +@@ -7,9 +7,53 @@ + #ifndef _ATH12K_DEBUGFS_H_ + #define _ATH12K_DEBUGFS_H_ + ++#include "hal_tx.h" ++ + #define ATH12K_TX_POWER_MAX_VAL 70 + #define ATH12K_TX_POWER_MIN_VAL 0 + ++/* htt_dbg_ext_stats_type */ ++enum ath12k_dbg_htt_ext_stats_type { ++ ATH12K_DBG_HTT_EXT_STATS_RESET = 0, ++ ATH12K_DBG_HTT_EXT_STATS_PDEV_TX = 1, ++ ATH12K_DBG_HTT_EXT_STATS_PDEV_RX = 2, ++ ATH12K_DBG_HTT_EXT_STATS_PDEV_TX_HWQ = 3, ++ ATH12K_DBG_HTT_EXT_STATS_PDEV_TX_SCHED = 4, ++ ATH12K_DBG_HTT_EXT_STATS_PDEV_ERROR = 5, ++ ATH12K_DBG_HTT_EXT_STATS_PDEV_TQM = 6, ++ ATH12K_DBG_HTT_EXT_STATS_TQM_CMDQ = 7, ++ ATH12K_DBG_HTT_EXT_STATS_TX_DE_INFO = 8, ++ ATH12K_DBG_HTT_EXT_STATS_PDEV_TX_RATE = 9, ++ ATH12K_DBG_HTT_EXT_STATS_PDEV_RX_RATE = 10, ++ ATH12K_DBG_HTT_EXT_STATS_PEER_INFO = 11, ++ ATH12K_DBG_HTT_EXT_STATS_TX_SELFGEN_INFO = 12, ++ ATH12K_DBG_HTT_EXT_STATS_TX_MU_HWQ = 13, ++ ATH12K_DBG_HTT_EXT_STATS_RING_IF_INFO = 14, ++ ATH12K_DBG_HTT_EXT_STATS_SRNG_INFO = 15, ++ ATH12K_DBG_HTT_EXT_STATS_SFM_INFO = 16, ++ ATH12K_DBG_HTT_EXT_STATS_PDEV_TX_MU = 17, ++ ATH12K_DBG_HTT_EXT_STATS_ACTIVE_PEERS_LIST = 18, ++ ATH12K_DBG_HTT_EXT_STATS_PDEV_CCA_STATS = 19, ++ ATH12K_DBG_HTT_EXT_STATS_TWT_SESSIONS = 20, ++ ATH12K_DBG_HTT_EXT_STATS_REO_RESOURCE_STATS = 21, ++ ATH12K_DBG_HTT_EXT_STATS_TX_SOUNDING_INFO = 22, ++ ATH12K_DBG_HTT_EXT_STATS_PDEV_OBSS_PD_STATS = 23, ++ ATH12K_DBG_HTT_EXT_STATS_RING_BACKPRESSURE_STATS = 24, ++ ++ /* keep this last */ ++ ATH12K_DBG_HTT_NUM_EXT_STATS, ++}; ++ ++struct debug_htt_stats_req { ++ bool done; ++ u8 pdev_id; ++ u8 type; ++ u8 peer_addr[ETH_ALEN]; ++ struct completion cmpln; ++ u32 buf_len; ++ u8 buf[]; ++}; ++ + struct ath_pktlog_hdr { + u16 flags; + u16 missed_cnt; +@@ -21,6 +65,167 @@ struct ath_pktlog_hdr { + u8 payload[]; + }; + ++#define ATH12K_HTT_PEER_STATS_RESET BIT(16) ++ ++#define ATH12K_HTT_STATS_BUF_SIZE (1024 * 512) + #define ATH12K_FW_STATS_BUF_SIZE (1024 * 1024) + ++enum ath12k_pktlog_filter { ++ ATH12K_PKTLOG_RX = 0x000000001, ++ ATH12K_PKTLOG_TX = 0x000000002, ++ ATH12K_PKTLOG_RCFIND = 0x000000004, ++ ATH12K_PKTLOG_RCUPDATE = 0x000000008, ++ ATH12K_PKTLOG_EVENT_SMART_ANT = 0x000000020, ++ ATH12K_PKTLOG_EVENT_SW = 0x000000040, ++ ATH12K_PKTLOG_HYBRID = 0x000000200, ++ ATH12K_PKTLOG_ANY = 0x00000006f, ++}; ++ ++enum ath12k_pktlog_mode { ++ ATH12K_PKTLOG_MODE_LITE = 1, ++ ATH12K_PKTLOG_MODE_FULL = 2, ++}; ++ ++enum ath12k_pktlog_enum { ++ ATH12K_PKTLOG_TYPE_TX_CTRL = 1, ++ ATH12K_PKTLOG_TYPE_TX_STAT = 2, ++ ATH12K_PKTLOG_TYPE_TX_MSDU_ID = 3, ++ ATH12K_PKTLOG_TYPE_RX_STAT = 5, ++ ATH12K_PKTLOG_TYPE_RC_FIND = 6, ++ ATH12K_PKTLOG_TYPE_RC_UPDATE = 7, ++ ATH12K_PKTLOG_TYPE_TX_VIRT_ADDR = 8, ++ ATH12K_PKTLOG_TYPE_RX_CBF = 10, ++ ATH12K_PKTLOG_TYPE_RX_STATBUF = 22, ++ ATH12K_PKTLOG_TYPE_PPDU_STATS = 23, ++ ATH12K_PKTLOG_TYPE_LITE_RX = 24, ++}; ++ ++enum ath12k_dbg_aggr_mode { ++ ATH12K_DBG_AGGR_MODE_AUTO, ++ ATH12K_DBG_AGGR_MODE_MANUAL, ++ ATH12K_DBG_AGGR_MODE_MAX, ++}; ++ ++#ifdef CPTCFG_ATH12K_DEBUGFS ++int ath12k_debugfs_soc_create(struct ath12k_base *ab); ++void ath12k_debugfs_soc_destroy(struct ath12k_base *ab); ++int ath12k_debugfs_pdev_create(struct ath12k_base *ab); ++void ath12k_debugfs_pdev_destroy(struct ath12k_base *ab); ++int ath12k_debugfs_register(struct ath12k *ar); ++void ath12k_debugfs_unregister(struct ath12k *ar); ++int ath12k_debugfs_create(void); ++void ath12k_debugfs_destroy(void); ++void ath12k_debugfs_fw_stats_process(struct ath12k_base *ab, struct sk_buff *skb); ++ ++void ath12k_debugfs_fw_stats_init(struct ath12k *ar); ++ ++static inline bool ath12k_debugfs_is_pktlog_lite_mode_enabled(struct ath12k *ar) ++{ ++ return (ar->debug.pktlog_mode == ATH12K_PKTLOG_MODE_LITE); ++} ++ ++static inline bool ath12k_debugfs_is_pktlog_rx_stats_enabled(struct ath12k *ar) ++{ ++ return (!ar->debug.pktlog_peer_valid && ar->debug.pktlog_mode); ++} ++ ++static inline bool ath12k_debugfs_is_pktlog_peer_valid(struct ath12k *ar, u8 *addr) ++{ ++ return (ar->debug.pktlog_peer_valid && ar->debug.pktlog_mode && ++ ether_addr_equal(addr, ar->debug.pktlog_peer_addr)); ++} ++ ++static inline int ath12k_debugfs_is_extd_tx_stats_enabled(struct ath12k *ar) ++{ ++ return ar->debug.extd_tx_stats; ++} ++ ++static inline int ath12k_debugfs_is_extd_rx_stats_enabled(struct ath12k *ar) ++{ ++ return ar->debug.extd_rx_stats; ++} ++ ++static inline int ath12k_debugfs_rx_filter(struct ath12k *ar) ++{ ++ return ar->debug.rx_filter; ++} ++ ++#else ++static inline int ath12k_debugfs_create(void) ++{ ++ return 0; ++} ++ ++static inline void ath12k_debugfs_destroy(void) ++{ ++} ++ ++static inline int ath12k_debugfs_soc_create(struct ath12k_base *ab) ++{ ++ return 0; ++} ++ ++static inline void ath12k_debugfs_soc_destroy(struct ath12k_base *ab) ++{ ++} ++ ++static inline int ath12k_debugfs_pdev_create(struct ath12k_base *ab) ++{ ++ return 0; ++} ++ ++static inline void ath12k_debugfs_pdev_destroy(struct ath12k_base *ab) ++{ ++} ++ ++static inline int ath12k_debugfs_register(struct ath12k *ar) ++{ ++ return 0; ++} ++ ++static inline void ath12k_debugfs_unregister(struct ath12k *ar) ++{ ++} ++ ++static inline void ath12k_debugfs_fw_stats_process(struct ath12k_base *ab, ++ struct sk_buff *skb) ++{ ++} ++ ++static inline void ath12k_debugfs_fw_stats_init(struct ath12k *ar) ++{ ++} ++ ++static inline int ath12k_debugfs_is_extd_tx_stats_enabled(struct ath12k *ar) ++{ ++ return 0; ++} ++ ++static inline int ath12k_debugfs_is_extd_rx_stats_enabled(struct ath12k *ar) ++{ ++ return 0; ++} ++ ++static inline bool ath12k_debugfs_is_pktlog_lite_mode_enabled(struct ath12k *ar) ++{ ++ return false; ++} ++ ++static inline bool ath12k_debugfs_is_pktlog_rx_stats_enabled(struct ath12k *ar) ++{ ++ return false; ++} ++ ++static inline bool ath12k_debugfs_is_pktlog_peer_valid(struct ath12k *ar, u8 *addr) ++{ ++ return false; ++} ++ ++static inline int ath12k_debugfs_rx_filter(struct ath12k *ar) ++{ ++ return 0; ++} ++ ++#endif /* CPTCFG_MAC80211_DEBUGFS*/ ++ + #endif /* _ATH12K_DEBUGFS_H_ */ +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c +@@ -0,0 +1,4599 @@ ++// SPDX-License-Identifier: BSD-3-Clause-Clear ++/* ++ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include ++#include "core.h" ++#include "dp_tx.h" ++#include "dp_rx.h" ++#include "debug.h" ++#include "debugfs_htt_stats.h" ++ ++#define HTT_DBG_OUT(buf, len, fmt, ...) \ ++ scnprintf(buf, len, fmt "\n", ##__VA_ARGS__) ++ ++#define HTT_MAX_STRING_LEN 256 ++#define HTT_MAX_PRINT_CHAR_PER_ELEM 15 ++ ++#define HTT_TLV_HDR_LEN 4 ++ ++#define ARRAY_TO_STRING(out, arr, len) \ ++ do { \ ++ int index = 0; u8 i; \ ++ for (i = 0; i < len; i++) { \ ++ index += scnprintf(out + index, HTT_MAX_STRING_LEN - index, \ ++ " %u:%u,", i, arr[i]); \ ++ if (index < 0 || index >= HTT_MAX_STRING_LEN) \ ++ break; \ ++ } \ ++ } while (0) ++ ++static inline void htt_print_stats_string_tlv(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_stats_string_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ u8 i; ++ u16 index = 0; ++ char data[HTT_MAX_STRING_LEN] = {0}; ++ ++ tag_len = tag_len >> 2; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_STATS_STRING_TLV:"); ++ ++ for (i = 0; i < tag_len; i++) { ++ index += scnprintf(&data[index], ++ HTT_MAX_STRING_LEN - index, ++ "%.*s", 4, (char *)&(htt_stats_buf->data[i])); ++ if (index >= HTT_MAX_STRING_LEN) ++ break; ++ } ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "data = %s\n", data); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void htt_print_tx_pdev_stats_cmn_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_pdev_stats_cmn_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_TX_PDEV_STATS_CMN_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mac_id = %u", ++ htt_stats_buf->mac_id__word & 0xFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "hw_queued = %u", ++ htt_stats_buf->hw_queued); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "hw_reaped = %u", ++ htt_stats_buf->hw_reaped); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "underrun = %u", ++ htt_stats_buf->underrun); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "hw_paused = %u", ++ htt_stats_buf->hw_paused); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "hw_flush = %u", ++ htt_stats_buf->hw_flush); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "hw_filt = %u", ++ htt_stats_buf->hw_filt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_abort = %u", ++ htt_stats_buf->tx_abort); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mpdu_requeued = %u", ++ htt_stats_buf->mpdu_requed); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_xretry = %u", ++ htt_stats_buf->tx_xretry); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "data_rc = %u", ++ htt_stats_buf->data_rc); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mpdu_dropped_xretry = %u", ++ htt_stats_buf->mpdu_dropped_xretry); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "illegal_rate_phy_err = %u", ++ htt_stats_buf->illgl_rate_phy_err); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "cont_xretry = %u", ++ htt_stats_buf->cont_xretry); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_timeout = %u", ++ htt_stats_buf->tx_timeout); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "pdev_resets = %u", ++ htt_stats_buf->pdev_resets); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "phy_underrun = %u", ++ htt_stats_buf->phy_underrun); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "txop_ovf = %u", ++ htt_stats_buf->txop_ovf); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "seq_posted = %u", ++ htt_stats_buf->seq_posted); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "seq_failed_queueing = %u", ++ htt_stats_buf->seq_failed_queueing); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "seq_completed = %u", ++ htt_stats_buf->seq_completed); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "seq_restarted = %u", ++ htt_stats_buf->seq_restarted); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mu_seq_posted = %u", ++ htt_stats_buf->mu_seq_posted); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "seq_switch_hw_paused = %u", ++ htt_stats_buf->seq_switch_hw_paused); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "next_seq_posted_dsr = %u", ++ htt_stats_buf->next_seq_posted_dsr); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "seq_posted_isr = %u", ++ htt_stats_buf->seq_posted_isr); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "seq_ctrl_cached = %u", ++ htt_stats_buf->seq_ctrl_cached); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mpdu_count_tqm = %u", ++ htt_stats_buf->mpdu_count_tqm); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "msdu_count_tqm = %u", ++ htt_stats_buf->msdu_count_tqm); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mpdu_removed_tqm = %u", ++ htt_stats_buf->mpdu_removed_tqm); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "msdu_removed_tqm = %u", ++ htt_stats_buf->msdu_removed_tqm); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mpdus_sw_flush = %u", ++ htt_stats_buf->mpdus_sw_flush); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mpdus_hw_filter = %u", ++ htt_stats_buf->mpdus_hw_filter); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mpdus_truncated = %u", ++ htt_stats_buf->mpdus_truncated); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mpdus_ack_failed = %u", ++ htt_stats_buf->mpdus_ack_failed); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mpdus_expired = %u", ++ htt_stats_buf->mpdus_expired); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mpdus_seq_hw_retry = %u", ++ htt_stats_buf->mpdus_seq_hw_retry); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ack_tlv_proc = %u", ++ htt_stats_buf->ack_tlv_proc); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "coex_abort_mpdu_cnt_valid = %u", ++ htt_stats_buf->coex_abort_mpdu_cnt_valid); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "coex_abort_mpdu_cnt = %u", ++ htt_stats_buf->coex_abort_mpdu_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_total_ppdus_tried_ota = %u", ++ htt_stats_buf->num_total_ppdus_tried_ota); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_data_ppdus_tried_ota = %u", ++ htt_stats_buf->num_data_ppdus_tried_ota); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "local_ctrl_mgmt_enqued = %u", ++ htt_stats_buf->local_ctrl_mgmt_enqued); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "local_ctrl_mgmt_freed = %u", ++ htt_stats_buf->local_ctrl_mgmt_freed); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "local_data_enqued = %u", ++ htt_stats_buf->local_data_enqued); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "local_data_freed = %u", ++ htt_stats_buf->local_data_freed); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mpdu_tried = %u", ++ htt_stats_buf->mpdu_tried); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "isr_wait_seq_posted = %u", ++ htt_stats_buf->isr_wait_seq_posted); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_active_dur_us_low = %u", ++ htt_stats_buf->tx_active_dur_us_low); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_active_dur_us_high = %u\n", ++ htt_stats_buf->tx_active_dur_us_high); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_pdev_stats_urrn_tlv_v(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_pdev_stats_urrn_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char urrn_stats[HTT_MAX_STRING_LEN] = {0}; ++ u16 num_elems = min_t(u16, (tag_len >> 2), HTT_TX_PDEV_MAX_URRN_STATS); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_TX_PDEV_STATS_URRN_TLV_V:"); ++ ++ ARRAY_TO_STRING(urrn_stats, htt_stats_buf->urrn_stats, num_elems); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "urrn_stats = %s\n", urrn_stats); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_pdev_stats_flush_tlv_v(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_pdev_stats_flush_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char flush_errs[HTT_MAX_STRING_LEN] = {0}; ++ u16 num_elems = min_t(u16, (tag_len >> 2), HTT_TX_PDEV_MAX_FLUSH_REASON_STATS); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_TX_PDEV_STATS_FLUSH_TLV_V:"); ++ ++ ARRAY_TO_STRING(flush_errs, htt_stats_buf->flush_errs, num_elems); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "flush_errs = %s\n", flush_errs); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_pdev_stats_sifs_tlv_v(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_pdev_stats_sifs_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char sifs_status[HTT_MAX_STRING_LEN] = {0}; ++ u16 num_elems = min_t(u16, (tag_len >> 2), HTT_TX_PDEV_MAX_SIFS_BURST_STATS); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_TX_PDEV_STATS_SIFS_TLV_V:"); ++ ++ ARRAY_TO_STRING(sifs_status, htt_stats_buf->sifs_status, num_elems); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sifs_status = %s\n", ++ sifs_status); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_pdev_stats_phy_err_tlv_v(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_pdev_stats_phy_err_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char phy_errs[HTT_MAX_STRING_LEN] = {0}; ++ u16 num_elems = min_t(u16, (tag_len >> 2), HTT_TX_PDEV_MAX_PHY_ERR_STATS); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_TX_PDEV_STATS_PHY_ERR_TLV_V:"); ++ ++ ARRAY_TO_STRING(phy_errs, htt_stats_buf->phy_errs, num_elems); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "phy_errs = %s\n", phy_errs); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_pdev_stats_sifs_hist_tlv_v(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_pdev_stats_sifs_hist_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char sifs_hist_status[HTT_MAX_STRING_LEN] = {0}; ++ u16 num_elems = min_t(u16, (tag_len >> 2), HTT_TX_PDEV_MAX_SIFS_BURST_HIST_STATS); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "HTT_TX_PDEV_STATS_SIFS_HIST_TLV_V:"); ++ ++ ARRAY_TO_STRING(sifs_hist_status, htt_stats_buf->sifs_hist_status, num_elems); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sifs_hist_status = %s\n", ++ sifs_hist_status); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_pdev_stats_tx_ppdu_stats_tlv_v(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_pdev_stats_tx_ppdu_stats_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "HTT_TX_PDEV_STATS_TX_PPDU_STATS_TLV_V:"); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_data_ppdus_legacy_su = %u", ++ htt_stats_buf->num_data_ppdus_legacy_su); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_data_ppdus_ac_su = %u", ++ htt_stats_buf->num_data_ppdus_ac_su); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_data_ppdus_ax_su = %u", ++ htt_stats_buf->num_data_ppdus_ax_su); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_data_ppdus_ac_su_txbf = %u", ++ htt_stats_buf->num_data_ppdus_ac_su_txbf); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_data_ppdus_ax_su_txbf = %u\n", ++ htt_stats_buf->num_data_ppdus_ax_su_txbf); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_pdev_stats_tried_mpdu_cnt_hist_tlv_v(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_pdev_stats_tried_mpdu_cnt_hist_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char tried_mpdu_cnt_hist[HTT_MAX_STRING_LEN] = {0}; ++ u32 num_elements = ((tag_len - sizeof(htt_stats_buf->hist_bin_size)) >> 2); ++ u32 required_buffer_size = HTT_MAX_PRINT_CHAR_PER_ELEM * num_elements; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "HTT_TX_PDEV_STATS_TRIED_MPDU_CNT_HIST_TLV_V:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "TRIED_MPDU_CNT_HIST_BIN_SIZE : %u", ++ htt_stats_buf->hist_bin_size); ++ ++ if (required_buffer_size < HTT_MAX_STRING_LEN) { ++ ARRAY_TO_STRING(tried_mpdu_cnt_hist, ++ htt_stats_buf->tried_mpdu_cnt_hist, ++ num_elements); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tried_mpdu_cnt_hist = %s\n", ++ tried_mpdu_cnt_hist); ++ } else { ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "INSUFFICIENT PRINT BUFFER\n"); ++ } ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void htt_print_hw_stats_intr_misc_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_hw_stats_intr_misc_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char hw_intr_name[HTT_STATS_MAX_HW_INTR_NAME_LEN + 1] = {0}; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_HW_STATS_INTR_MISC_TLV:"); ++ memcpy(hw_intr_name, &(htt_stats_buf->hw_intr_name[0]), ++ HTT_STATS_MAX_HW_INTR_NAME_LEN); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "hw_intr_name = %s ", hw_intr_name); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mask = %u", ++ htt_stats_buf->mask); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "count = %u\n", ++ htt_stats_buf->count); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_hw_stats_wd_timeout_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_hw_stats_wd_timeout_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char hw_module_name[HTT_STATS_MAX_HW_MODULE_NAME_LEN + 1] = {0}; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_HW_STATS_WD_TIMEOUT_TLV:"); ++ memcpy(hw_module_name, &(htt_stats_buf->hw_module_name[0]), ++ HTT_STATS_MAX_HW_MODULE_NAME_LEN); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "hw_module_name = %s ", ++ hw_module_name); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "count = %u", ++ htt_stats_buf->count); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void htt_print_hw_stats_pdev_errs_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_hw_stats_pdev_errs_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_HW_STATS_PDEV_ERRS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mac_id = %u", ++ htt_stats_buf->mac_id__word & 0xFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_abort = %u", ++ htt_stats_buf->tx_abort); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_abort_fail_count = %u", ++ htt_stats_buf->tx_abort_fail_count); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_abort = %u", ++ htt_stats_buf->rx_abort); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_abort_fail_count = %u", ++ htt_stats_buf->rx_abort_fail_count); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "warm_reset = %u", ++ htt_stats_buf->warm_reset); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "cold_reset = %u", ++ htt_stats_buf->cold_reset); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_flush = %u", ++ htt_stats_buf->tx_flush); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_glb_reset = %u", ++ htt_stats_buf->tx_glb_reset); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_txq_reset = %u", ++ htt_stats_buf->tx_txq_reset); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_timeout_reset = %u\n", ++ htt_stats_buf->rx_timeout_reset); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void htt_print_msdu_flow_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_msdu_flow_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_MSDU_FLOW_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "last_update_timestamp = %u", ++ htt_stats_buf->last_update_timestamp); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "last_add_timestamp = %u", ++ htt_stats_buf->last_add_timestamp); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "last_remove_timestamp = %u", ++ htt_stats_buf->last_remove_timestamp); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "total_processed_msdu_count = %u", ++ htt_stats_buf->total_processed_msdu_count); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "cur_msdu_count_in_flowq = %u", ++ htt_stats_buf->cur_msdu_count_in_flowq); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sw_peer_id = %u", ++ htt_stats_buf->sw_peer_id); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_flow_no = %u", ++ htt_stats_buf->tx_flow_no__tid_num__drop_rule & 0xFFFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tid_num = %u", ++ (htt_stats_buf->tx_flow_no__tid_num__drop_rule & 0xF0000) >> ++ 16); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "drop_rule = %u", ++ (htt_stats_buf->tx_flow_no__tid_num__drop_rule & 0x100000) >> ++ 20); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "last_cycle_enqueue_count = %u", ++ htt_stats_buf->last_cycle_enqueue_count); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "last_cycle_dequeue_count = %u", ++ htt_stats_buf->last_cycle_dequeue_count); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "last_cycle_drop_count = %u", ++ htt_stats_buf->last_cycle_drop_count); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "current_drop_th = %u\n", ++ htt_stats_buf->current_drop_th); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void htt_print_tx_tid_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_tid_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char tid_name[MAX_HTT_TID_NAME + 1] = {0}; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_TX_TID_STATS_TLV:"); ++ memcpy(tid_name, &(htt_stats_buf->tid_name[0]), MAX_HTT_TID_NAME); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tid_name = %s ", tid_name); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sw_peer_id = %u", ++ htt_stats_buf->sw_peer_id__tid_num & 0xFFFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tid_num = %u", ++ (htt_stats_buf->sw_peer_id__tid_num & 0xFFFF0000) >> 16); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_sched_pending = %u", ++ htt_stats_buf->num_sched_pending__num_ppdu_in_hwq & 0xFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_ppdu_in_hwq = %u", ++ (htt_stats_buf->num_sched_pending__num_ppdu_in_hwq & ++ 0xFF00) >> 8); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tid_flags = 0x%x", ++ htt_stats_buf->tid_flags); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "hw_queued = %u", ++ htt_stats_buf->hw_queued); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "hw_reaped = %u", ++ htt_stats_buf->hw_reaped); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mpdus_hw_filter = %u", ++ htt_stats_buf->mpdus_hw_filter); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "qdepth_bytes = %u", ++ htt_stats_buf->qdepth_bytes); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "qdepth_num_msdu = %u", ++ htt_stats_buf->qdepth_num_msdu); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "qdepth_num_mpdu = %u", ++ htt_stats_buf->qdepth_num_mpdu); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "last_scheduled_tsmp = %u", ++ htt_stats_buf->last_scheduled_tsmp); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "pause_module_id = %u", ++ htt_stats_buf->pause_module_id); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "block_module_id = %u\n", ++ htt_stats_buf->block_module_id); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void htt_print_tx_tid_stats_v1_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_tid_stats_v1_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char tid_name[MAX_HTT_TID_NAME + 1] = {0}; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_TX_TID_STATS_V1_TLV:"); ++ memcpy(tid_name, &(htt_stats_buf->tid_name[0]), MAX_HTT_TID_NAME); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tid_name = %s ", tid_name); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sw_peer_id = %u", ++ htt_stats_buf->sw_peer_id__tid_num & 0xFFFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tid_num = %u", ++ (htt_stats_buf->sw_peer_id__tid_num & 0xFFFF0000) >> 16); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_sched_pending = %u", ++ htt_stats_buf->num_sched_pending__num_ppdu_in_hwq & 0xFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_ppdu_in_hwq = %u", ++ (htt_stats_buf->num_sched_pending__num_ppdu_in_hwq & ++ 0xFF00) >> 8); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tid_flags = 0x%x", ++ htt_stats_buf->tid_flags); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "max_qdepth_bytes = %u", ++ htt_stats_buf->max_qdepth_bytes); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "max_qdepth_n_msdus = %u", ++ htt_stats_buf->max_qdepth_n_msdus); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rsvd = %u", ++ htt_stats_buf->rsvd); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "qdepth_bytes = %u", ++ htt_stats_buf->qdepth_bytes); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "qdepth_num_msdu = %u", ++ htt_stats_buf->qdepth_num_msdu); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "qdepth_num_mpdu = %u", ++ htt_stats_buf->qdepth_num_mpdu); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "last_scheduled_tsmp = %u", ++ htt_stats_buf->last_scheduled_tsmp); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "pause_module_id = %u", ++ htt_stats_buf->pause_module_id); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "block_module_id = %u", ++ htt_stats_buf->block_module_id); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "allow_n_flags = 0x%x", ++ htt_stats_buf->allow_n_flags); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sendn_frms_allowed = %u\n", ++ htt_stats_buf->sendn_frms_allowed); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void htt_print_rx_tid_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_rx_tid_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char tid_name[MAX_HTT_TID_NAME + 1] = {0}; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_RX_TID_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sw_peer_id = %u", ++ htt_stats_buf->sw_peer_id__tid_num & 0xFFFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tid_num = %u", ++ (htt_stats_buf->sw_peer_id__tid_num & 0xFFFF0000) >> 16); ++ memcpy(tid_name, &(htt_stats_buf->tid_name[0]), MAX_HTT_TID_NAME); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tid_name = %s ", tid_name); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "dup_in_reorder = %u", ++ htt_stats_buf->dup_in_reorder); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "dup_past_outside_window = %u", ++ htt_stats_buf->dup_past_outside_window); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "dup_past_within_window = %u", ++ htt_stats_buf->dup_past_within_window); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rxdesc_err_decrypt = %u\n", ++ htt_stats_buf->rxdesc_err_decrypt); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void htt_print_counter_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_counter_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char counter_name[HTT_MAX_STRING_LEN] = {0}; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_COUNTER_TLV:"); ++ ++ ARRAY_TO_STRING(counter_name, ++ htt_stats_buf->counter_name, ++ HTT_MAX_COUNTER_NAME); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "counter_name = %s ", counter_name); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "count = %u\n", ++ htt_stats_buf->count); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void htt_print_peer_stats_cmn_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_peer_stats_cmn_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_PEER_STATS_CMN_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ppdu_cnt = %u", ++ htt_stats_buf->ppdu_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mpdu_cnt = %u", ++ htt_stats_buf->mpdu_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "msdu_cnt = %u", ++ htt_stats_buf->msdu_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "pause_bitmap = %u", ++ htt_stats_buf->pause_bitmap); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "block_bitmap = %u", ++ htt_stats_buf->block_bitmap); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "last_rssi = %d", ++ htt_stats_buf->rssi); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "enqueued_count = %llu", ++ htt_stats_buf->peer_enqueued_count_low | ++ ((u64)htt_stats_buf->peer_enqueued_count_high << 32)); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "dequeued_count = %llu", ++ htt_stats_buf->peer_dequeued_count_low | ++ ((u64)htt_stats_buf->peer_dequeued_count_high << 32)); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "dropped_count = %llu", ++ htt_stats_buf->peer_dropped_count_low | ++ ((u64)htt_stats_buf->peer_dropped_count_high << 32)); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "transmitted_ppdu_bytes = %llu", ++ htt_stats_buf->ppdu_transmitted_bytes_low | ++ ((u64)htt_stats_buf->ppdu_transmitted_bytes_high << 32)); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ttl_removed_count = %u", ++ htt_stats_buf->peer_ttl_removed_count); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "inactive_time = %u\n", ++ htt_stats_buf->inactive_time); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void htt_print_peer_details_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_peer_details_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_PEER_DETAILS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "peer_type = %u", ++ htt_stats_buf->peer_type); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sw_peer_id = %u", ++ htt_stats_buf->sw_peer_id); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "vdev_id = %u", ++ htt_stats_buf->vdev_pdev_ast_idx & 0xFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "pdev_id = %u", ++ (htt_stats_buf->vdev_pdev_ast_idx & 0xFF00) >> 8); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ast_idx = %u", ++ (htt_stats_buf->vdev_pdev_ast_idx & 0xFFFF0000) >> 16); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "mac_addr = %02x:%02x:%02x:%02x:%02x:%02x", ++ htt_stats_buf->mac_addr.mac_addr_l32 & 0xFF, ++ (htt_stats_buf->mac_addr.mac_addr_l32 & 0xFF00) >> 8, ++ (htt_stats_buf->mac_addr.mac_addr_l32 & 0xFF0000) >> 16, ++ (htt_stats_buf->mac_addr.mac_addr_l32 & 0xFF000000) >> 24, ++ (htt_stats_buf->mac_addr.mac_addr_h16 & 0xFF), ++ (htt_stats_buf->mac_addr.mac_addr_h16 & 0xFF00) >> 8); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "peer_flags = 0x%x", ++ htt_stats_buf->peer_flags); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "qpeer_flags = 0x%x\n", ++ htt_stats_buf->qpeer_flags); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void htt_print_tx_peer_rate_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_peer_rate_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char str_buf[HTT_MAX_STRING_LEN] = {0}; ++ char *tx_gi[HTT_TX_PEER_STATS_NUM_GI_COUNTERS] = {NULL}; ++ u8 j; ++ ++ for (j = 0; j < HTT_TX_PEER_STATS_NUM_GI_COUNTERS; j++) { ++ tx_gi[j] = kmalloc(HTT_MAX_STRING_LEN, GFP_ATOMIC); ++ if (!tx_gi[j]) ++ goto fail; ++ } ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_TX_PEER_RATE_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_ldpc = %u", ++ htt_stats_buf->tx_ldpc); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rts_cnt = %u", ++ htt_stats_buf->rts_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ack_rssi = %u", ++ htt_stats_buf->ack_rssi); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->tx_mcs, ++ HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_mcs = %s ", str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->tx_su_mcs, ++ HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_su_mcs = %s ", str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->tx_mu_mcs, ++ HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_mu_mcs = %s ", str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, ++ htt_stats_buf->tx_nss, ++ HTT_TX_PDEV_STATS_NUM_SPATIAL_STREAMS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_nss = %s ", str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, ++ htt_stats_buf->tx_bw, ++ HTT_TX_PDEV_STATS_NUM_BW_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_bw = %s ", str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->tx_stbc, ++ HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_stbc = %s ", str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->tx_pream, ++ HTT_TX_PDEV_STATS_NUM_PREAMBLE_TYPES); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_pream = %s ", str_buf); ++ ++ for (j = 0; j < HTT_TX_PEER_STATS_NUM_GI_COUNTERS; j++) { ++ ARRAY_TO_STRING(tx_gi[j], ++ htt_stats_buf->tx_gi[j], ++ HTT_TX_PEER_STATS_NUM_MCS_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_gi[%u] = %s ", ++ j, tx_gi[j]); ++ } ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, ++ htt_stats_buf->tx_dcm, ++ HTT_TX_PDEV_STATS_NUM_DCM_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_dcm = %s\n", str_buf); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++ ++fail: ++ for (j = 0; j < HTT_TX_PEER_STATS_NUM_GI_COUNTERS; j++) ++ kfree(tx_gi[j]); ++} ++ ++static inline void htt_print_rx_peer_rate_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_rx_peer_rate_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ u8 j; ++ char *rssi_chain[HTT_RX_PEER_STATS_NUM_SPATIAL_STREAMS] = {NULL}; ++ char *rx_gi[HTT_RX_PEER_STATS_NUM_GI_COUNTERS] = {NULL}; ++ char str_buf[HTT_MAX_STRING_LEN] = {0}; ++ ++ for (j = 0; j < HTT_RX_PEER_STATS_NUM_SPATIAL_STREAMS; j++) { ++ rssi_chain[j] = kmalloc(HTT_MAX_STRING_LEN, GFP_ATOMIC); ++ if (!rssi_chain[j]) ++ goto fail; ++ } ++ ++ for (j = 0; j < HTT_RX_PEER_STATS_NUM_GI_COUNTERS; j++) { ++ rx_gi[j] = kmalloc(HTT_MAX_STRING_LEN, GFP_ATOMIC); ++ if (!rx_gi[j]) ++ goto fail; ++ } ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_RX_PEER_RATE_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "nsts = %u", ++ htt_stats_buf->nsts); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_ldpc = %u", ++ htt_stats_buf->rx_ldpc); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rts_cnt = %u", ++ htt_stats_buf->rts_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rssi_mgmt = %u", ++ htt_stats_buf->rssi_mgmt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rssi_data = %u", ++ htt_stats_buf->rssi_data); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rssi_comb = %u", ++ htt_stats_buf->rssi_comb); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->rx_mcs, ++ HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_mcs = %s ", str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->rx_nss, ++ HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_nss = %s ", str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->rx_dcm, ++ HTT_RX_PDEV_STATS_NUM_DCM_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_dcm = %s ", str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->rx_stbc, ++ HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_stbc = %s ", str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->rx_bw, ++ HTT_RX_PDEV_STATS_NUM_BW_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_bw = %s ", str_buf); ++ ++ for (j = 0; j < HTT_RX_PEER_STATS_NUM_SPATIAL_STREAMS; j++) { ++ ARRAY_TO_STRING(rssi_chain[j], htt_stats_buf->rssi_chain[j], ++ HTT_RX_PEER_STATS_NUM_BW_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rssi_chain[%u] = %s ", ++ j, rssi_chain[j]); ++ } ++ ++ for (j = 0; j < HTT_RX_PEER_STATS_NUM_GI_COUNTERS; j++) { ++ ARRAY_TO_STRING(rx_gi[j], htt_stats_buf->rx_gi[j], ++ HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_gi[%u] = %s ", ++ j, rx_gi[j]); ++ } ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->rx_pream, ++ HTT_RX_PDEV_STATS_NUM_PREAMBLE_TYPES); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_pream = %s\n", str_buf); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++ ++fail: ++ for (j = 0; j < HTT_RX_PEER_STATS_NUM_SPATIAL_STREAMS; j++) ++ kfree(rssi_chain[j]); ++ ++ for (j = 0; j < HTT_RX_PEER_STATS_NUM_GI_COUNTERS; j++) ++ kfree(rx_gi[j]); ++} ++ ++static inline void ++htt_print_tx_hwq_mu_mimo_sch_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_hwq_mu_mimo_sch_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_TX_HWQ_MU_MIMO_SCH_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mu_mimo_sch_posted = %u", ++ htt_stats_buf->mu_mimo_sch_posted); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mu_mimo_sch_failed = %u", ++ htt_stats_buf->mu_mimo_sch_failed); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mu_mimo_ppdu_posted = %u\n", ++ htt_stats_buf->mu_mimo_ppdu_posted); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_hwq_mu_mimo_mpdu_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_hwq_mu_mimo_mpdu_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "HTT_TX_HWQ_MU_MIMO_MPDU_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mu_mimo_mpdus_queued_usr = %u", ++ htt_stats_buf->mu_mimo_mpdus_queued_usr); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mu_mimo_mpdus_tried_usr = %u", ++ htt_stats_buf->mu_mimo_mpdus_tried_usr); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mu_mimo_mpdus_failed_usr = %u", ++ htt_stats_buf->mu_mimo_mpdus_failed_usr); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mu_mimo_mpdus_requeued_usr = %u", ++ htt_stats_buf->mu_mimo_mpdus_requeued_usr); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mu_mimo_err_no_ba_usr = %u", ++ htt_stats_buf->mu_mimo_err_no_ba_usr); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mu_mimo_mpdu_underrun_usr = %u", ++ htt_stats_buf->mu_mimo_mpdu_underrun_usr); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mu_mimo_ampdu_underrun_usr = %u\n", ++ htt_stats_buf->mu_mimo_ampdu_underrun_usr); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_hwq_mu_mimo_cmn_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_hwq_mu_mimo_cmn_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_TX_HWQ_MU_MIMO_CMN_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mac_id = %u", ++ htt_stats_buf->mac_id__hwq_id__word & 0xFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "hwq_id = %u\n", ++ (htt_stats_buf->mac_id__hwq_id__word & 0xFF00) >> 8); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_hwq_stats_cmn_tlv(const void *tag_buf, struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_hwq_stats_cmn_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ /* TODO: HKDBG */ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_TX_HWQ_STATS_CMN_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mac_id = %u", ++ htt_stats_buf->mac_id__hwq_id__word & 0xFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "hwq_id = %u", ++ (htt_stats_buf->mac_id__hwq_id__word & 0xFF00) >> 8); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "xretry = %u", ++ htt_stats_buf->xretry); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "underrun_cnt = %u", ++ htt_stats_buf->underrun_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "flush_cnt = %u", ++ htt_stats_buf->flush_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "filt_cnt = %u", ++ htt_stats_buf->filt_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "null_mpdu_bmap = %u", ++ htt_stats_buf->null_mpdu_bmap); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "user_ack_failure = %u", ++ htt_stats_buf->user_ack_failure); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ack_tlv_proc = %u", ++ htt_stats_buf->ack_tlv_proc); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sched_id_proc = %u", ++ htt_stats_buf->sched_id_proc); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "null_mpdu_tx_count = %u", ++ htt_stats_buf->null_mpdu_tx_count); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mpdu_bmap_not_recvd = %u", ++ htt_stats_buf->mpdu_bmap_not_recvd); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_bar = %u", ++ htt_stats_buf->num_bar); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rts = %u", ++ htt_stats_buf->rts); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "cts2self = %u", ++ htt_stats_buf->cts2self); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "qos_null = %u", ++ htt_stats_buf->qos_null); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mpdu_tried_cnt = %u", ++ htt_stats_buf->mpdu_tried_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mpdu_queued_cnt = %u", ++ htt_stats_buf->mpdu_queued_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mpdu_ack_fail_cnt = %u", ++ htt_stats_buf->mpdu_ack_fail_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mpdu_filt_cnt = %u", ++ htt_stats_buf->mpdu_filt_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "false_mpdu_ack_count = %u", ++ htt_stats_buf->false_mpdu_ack_count); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "txq_timeout = %u\n", ++ htt_stats_buf->txq_timeout); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_hwq_difs_latency_stats_tlv_v(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_hwq_difs_latency_stats_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ u16 data_len = min_t(u16, (tag_len >> 2), HTT_TX_HWQ_MAX_DIFS_LATENCY_BINS); ++ char difs_latency_hist[HTT_MAX_STRING_LEN] = {0}; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "HTT_TX_HWQ_DIFS_LATENCY_STATS_TLV_V:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "hist_intvl = %u", ++ htt_stats_buf->hist_intvl); ++ ++ ARRAY_TO_STRING(difs_latency_hist, htt_stats_buf->difs_latency_hist, ++ data_len); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "difs_latency_hist = %s\n", ++ difs_latency_hist); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_hwq_cmd_result_stats_tlv_v(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_hwq_cmd_result_stats_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ u16 data_len; ++ char cmd_result[HTT_MAX_STRING_LEN] = {0}; ++ ++ data_len = min_t(u16, (tag_len >> 2), HTT_TX_HWQ_MAX_CMD_RESULT_STATS); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "HTT_TX_HWQ_CMD_RESULT_STATS_TLV_V:"); ++ ++ ARRAY_TO_STRING(cmd_result, htt_stats_buf->cmd_result, data_len); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "cmd_result = %s\n", cmd_result); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_hwq_cmd_stall_stats_tlv_v(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_hwq_cmd_stall_stats_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ u16 num_elems; ++ char cmd_stall_status[HTT_MAX_STRING_LEN] = {0}; ++ ++ num_elems = min_t(u16, (tag_len >> 2), HTT_TX_HWQ_MAX_CMD_STALL_STATS); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_TX_HWQ_CMD_STALL_STATS_TLV_V:"); ++ ++ ARRAY_TO_STRING(cmd_stall_status, htt_stats_buf->cmd_stall_status, num_elems); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "cmd_stall_status = %s\n", ++ cmd_stall_status); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_hwq_fes_result_stats_tlv_v(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_hwq_fes_result_stats_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ u16 num_elems; ++ char fes_result[HTT_MAX_STRING_LEN] = {0}; ++ ++ num_elems = min_t(u16, (tag_len >> 2), HTT_TX_HWQ_MAX_FES_RESULT_STATS); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "HTT_TX_HWQ_FES_RESULT_STATS_TLV_V:"); ++ ++ ARRAY_TO_STRING(fes_result, htt_stats_buf->fes_result, num_elems); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fes_result = %s\n", fes_result); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_hwq_tried_mpdu_cnt_hist_tlv_v(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_hwq_tried_mpdu_cnt_hist_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char tried_mpdu_cnt_hist[HTT_MAX_STRING_LEN] = {0}; ++ u32 num_elements = ((tag_len - ++ sizeof(htt_stats_buf->hist_bin_size)) >> 2); ++ u32 required_buffer_size = HTT_MAX_PRINT_CHAR_PER_ELEM * num_elements; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "HTT_TX_HWQ_TRIED_MPDU_CNT_HIST_TLV_V:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "TRIED_MPDU_CNT_HIST_BIN_SIZE : %u", ++ htt_stats_buf->hist_bin_size); ++ ++ if (required_buffer_size < HTT_MAX_STRING_LEN) { ++ ARRAY_TO_STRING(tried_mpdu_cnt_hist, ++ htt_stats_buf->tried_mpdu_cnt_hist, ++ num_elements); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "tried_mpdu_cnt_hist = %s\n", ++ tried_mpdu_cnt_hist); ++ } else { ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "INSUFFICIENT PRINT BUFFER "); ++ } ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_hwq_txop_used_cnt_hist_tlv_v(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_hwq_txop_used_cnt_hist_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char txop_used_cnt_hist[HTT_MAX_STRING_LEN] = {0}; ++ u32 num_elements = tag_len >> 2; ++ u32 required_buffer_size = HTT_MAX_PRINT_CHAR_PER_ELEM * num_elements; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "HTT_TX_HWQ_TXOP_USED_CNT_HIST_TLV_V:"); ++ ++ if (required_buffer_size < HTT_MAX_STRING_LEN) { ++ ARRAY_TO_STRING(txop_used_cnt_hist, ++ htt_stats_buf->txop_used_cnt_hist, ++ num_elements); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "txop_used_cnt_hist = %s\n", ++ txop_used_cnt_hist); ++ } else { ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "INSUFFICIENT PRINT BUFFER "); ++ } ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void htt_print_tx_sounding_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ s32 i; ++ const struct htt_tx_sounding_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ const u32 *cbf_20 = htt_stats_buf->cbf_20; ++ const u32 *cbf_40 = htt_stats_buf->cbf_40; ++ const u32 *cbf_80 = htt_stats_buf->cbf_80; ++ const u32 *cbf_160 = htt_stats_buf->cbf_160; ++ ++ if (htt_stats_buf->tx_sounding_mode == HTT_TX_AC_SOUNDING_MODE) { ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "\nHTT_TX_AC_SOUNDING_STATS_TLV:\n"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ac_cbf_20 = IBF : %u, SU_SIFS : %u, SU_RBO : %u, MU_SIFS : %u, MU_RBO : %u ", ++ cbf_20[HTT_IMPLICIT_TXBF_STEER_STATS], ++ cbf_20[HTT_EXPLICIT_TXBF_SU_SIFS_STEER_STATS], ++ cbf_20[HTT_EXPLICIT_TXBF_SU_RBO_STEER_STATS], ++ cbf_20[HTT_EXPLICIT_TXBF_MU_SIFS_STEER_STATS], ++ cbf_20[HTT_EXPLICIT_TXBF_MU_RBO_STEER_STATS]); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ac_cbf_40 = IBF : %u, SU_SIFS : %u, SU_RBO : %u, MU_SIFS : %u, MU_RBO : %u", ++ cbf_40[HTT_IMPLICIT_TXBF_STEER_STATS], ++ cbf_40[HTT_EXPLICIT_TXBF_SU_SIFS_STEER_STATS], ++ cbf_40[HTT_EXPLICIT_TXBF_SU_RBO_STEER_STATS], ++ cbf_40[HTT_EXPLICIT_TXBF_MU_SIFS_STEER_STATS], ++ cbf_40[HTT_EXPLICIT_TXBF_MU_RBO_STEER_STATS]); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ac_cbf_80 = IBF : %u, SU_SIFS : %u, SU_RBO : %u, MU_SIFS : %u, MU_RBO : %u", ++ cbf_80[HTT_IMPLICIT_TXBF_STEER_STATS], ++ cbf_80[HTT_EXPLICIT_TXBF_SU_SIFS_STEER_STATS], ++ cbf_80[HTT_EXPLICIT_TXBF_SU_RBO_STEER_STATS], ++ cbf_80[HTT_EXPLICIT_TXBF_MU_SIFS_STEER_STATS], ++ cbf_80[HTT_EXPLICIT_TXBF_MU_RBO_STEER_STATS]); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ac_cbf_160 = IBF : %u, SU_SIFS : %u, SU_RBO : %u, MU_SIFS : %u, MU_RBO : %u", ++ cbf_160[HTT_IMPLICIT_TXBF_STEER_STATS], ++ cbf_160[HTT_EXPLICIT_TXBF_SU_SIFS_STEER_STATS], ++ cbf_160[HTT_EXPLICIT_TXBF_SU_RBO_STEER_STATS], ++ cbf_160[HTT_EXPLICIT_TXBF_MU_SIFS_STEER_STATS], ++ cbf_160[HTT_EXPLICIT_TXBF_MU_RBO_STEER_STATS]); ++ ++ for (i = 0; i < HTT_TX_PDEV_STATS_NUM_AC_MUMIMO_USER_STATS; i++) { ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "Sounding User %u = 20MHz: %u, 40MHz : %u, 80MHz: %u, 160MHz: %u ", ++ i, ++ htt_stats_buf->sounding[0], ++ htt_stats_buf->sounding[1], ++ htt_stats_buf->sounding[2], ++ htt_stats_buf->sounding[3]); ++ } ++ } else if (htt_stats_buf->tx_sounding_mode == HTT_TX_AX_SOUNDING_MODE) { ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "\nHTT_TX_AX_SOUNDING_STATS_TLV:\n"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ax_cbf_20 = IBF : %u, SU_SIFS : %u, SU_RBO : %u, MU_SIFS : %u, MU_RBO : %u ", ++ cbf_20[HTT_IMPLICIT_TXBF_STEER_STATS], ++ cbf_20[HTT_EXPLICIT_TXBF_SU_SIFS_STEER_STATS], ++ cbf_20[HTT_EXPLICIT_TXBF_SU_RBO_STEER_STATS], ++ cbf_20[HTT_EXPLICIT_TXBF_MU_SIFS_STEER_STATS], ++ cbf_20[HTT_EXPLICIT_TXBF_MU_RBO_STEER_STATS]); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ax_cbf_40 = IBF : %u, SU_SIFS : %u, SU_RBO : %u, MU_SIFS : %u, MU_RBO : %u", ++ cbf_40[HTT_IMPLICIT_TXBF_STEER_STATS], ++ cbf_40[HTT_EXPLICIT_TXBF_SU_SIFS_STEER_STATS], ++ cbf_40[HTT_EXPLICIT_TXBF_SU_RBO_STEER_STATS], ++ cbf_40[HTT_EXPLICIT_TXBF_MU_SIFS_STEER_STATS], ++ cbf_40[HTT_EXPLICIT_TXBF_MU_RBO_STEER_STATS]); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ax_cbf_80 = IBF : %u, SU_SIFS : %u, SU_RBO : %u, MU_SIFS : %u, MU_RBO : %u", ++ cbf_80[HTT_IMPLICIT_TXBF_STEER_STATS], ++ cbf_80[HTT_EXPLICIT_TXBF_SU_SIFS_STEER_STATS], ++ cbf_80[HTT_EXPLICIT_TXBF_SU_RBO_STEER_STATS], ++ cbf_80[HTT_EXPLICIT_TXBF_MU_SIFS_STEER_STATS], ++ cbf_80[HTT_EXPLICIT_TXBF_MU_RBO_STEER_STATS]); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ax_cbf_160 = IBF : %u, SU_SIFS : %u, SU_RBO : %u, MU_SIFS : %u, MU_RBO : %u", ++ cbf_160[HTT_IMPLICIT_TXBF_STEER_STATS], ++ cbf_160[HTT_EXPLICIT_TXBF_SU_SIFS_STEER_STATS], ++ cbf_160[HTT_EXPLICIT_TXBF_SU_RBO_STEER_STATS], ++ cbf_160[HTT_EXPLICIT_TXBF_MU_SIFS_STEER_STATS], ++ cbf_160[HTT_EXPLICIT_TXBF_MU_RBO_STEER_STATS]); ++ ++ for (i = 0; i < HTT_TX_PDEV_STATS_NUM_AX_MUMIMO_USER_STATS; i++) { ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "Sounding User %u = 20MHz: %u, 40MHz : %u, 80MHz: %u, 160MHz: %u ", ++ i, ++ htt_stats_buf->sounding[0], ++ htt_stats_buf->sounding[1], ++ htt_stats_buf->sounding[2], ++ htt_stats_buf->sounding[3]); ++ } ++ } ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_selfgen_cmn_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_selfgen_cmn_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_TX_SELFGEN_CMN_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mac_id = %u", ++ htt_stats_buf->mac_id__word & 0xFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "su_bar = %u", ++ htt_stats_buf->su_bar); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rts = %u", ++ htt_stats_buf->rts); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "cts2self = %u", ++ htt_stats_buf->cts2self); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "qos_null = %u", ++ htt_stats_buf->qos_null); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "delayed_bar_1 = %u", ++ htt_stats_buf->delayed_bar_1); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "delayed_bar_2 = %u", ++ htt_stats_buf->delayed_bar_2); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "delayed_bar_3 = %u", ++ htt_stats_buf->delayed_bar_3); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "delayed_bar_4 = %u", ++ htt_stats_buf->delayed_bar_4); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "delayed_bar_5 = %u", ++ htt_stats_buf->delayed_bar_5); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "delayed_bar_6 = %u", ++ htt_stats_buf->delayed_bar_6); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "delayed_bar_7 = %u\n", ++ htt_stats_buf->delayed_bar_7); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_selfgen_ac_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_selfgen_ac_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_TX_SELFGEN_AC_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ac_su_ndpa = %u", ++ htt_stats_buf->ac_su_ndpa); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ac_su_ndp = %u", ++ htt_stats_buf->ac_su_ndp); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ac_mu_mimo_ndpa = %u", ++ htt_stats_buf->ac_mu_mimo_ndpa); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ac_mu_mimo_ndp = %u", ++ htt_stats_buf->ac_mu_mimo_ndp); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ac_mu_mimo_brpoll_1 = %u", ++ htt_stats_buf->ac_mu_mimo_brpoll_1); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ac_mu_mimo_brpoll_2 = %u", ++ htt_stats_buf->ac_mu_mimo_brpoll_2); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ac_mu_mimo_brpoll_3 = %u\n", ++ htt_stats_buf->ac_mu_mimo_brpoll_3); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_selfgen_ax_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_selfgen_ax_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_TX_SELFGEN_AX_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_su_ndpa = %u", ++ htt_stats_buf->ax_su_ndpa); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_su_ndp = %u", ++ htt_stats_buf->ax_su_ndp); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_mu_mimo_ndpa = %u", ++ htt_stats_buf->ax_mu_mimo_ndpa); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_mu_mimo_ndp = %u", ++ htt_stats_buf->ax_mu_mimo_ndp); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_mu_mimo_brpoll_1 = %u", ++ htt_stats_buf->ax_mu_mimo_brpoll_1); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_mu_mimo_brpoll_2 = %u", ++ htt_stats_buf->ax_mu_mimo_brpoll_2); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_mu_mimo_brpoll_3 = %u", ++ htt_stats_buf->ax_mu_mimo_brpoll_3); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_mu_mimo_brpoll_4 = %u", ++ htt_stats_buf->ax_mu_mimo_brpoll_4); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_mu_mimo_brpoll_5 = %u", ++ htt_stats_buf->ax_mu_mimo_brpoll_5); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_mu_mimo_brpoll_6 = %u", ++ htt_stats_buf->ax_mu_mimo_brpoll_6); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_mu_mimo_brpoll_7 = %u", ++ htt_stats_buf->ax_mu_mimo_brpoll_7); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_basic_trigger = %u", ++ htt_stats_buf->ax_basic_trigger); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_bsr_trigger = %u", ++ htt_stats_buf->ax_bsr_trigger); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_mu_bar_trigger = %u", ++ htt_stats_buf->ax_mu_bar_trigger); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_mu_rts_trigger = %u\n", ++ htt_stats_buf->ax_mu_rts_trigger); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_selfgen_ac_err_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_selfgen_ac_err_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_TX_SELFGEN_AC_ERR_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ac_su_ndp_err = %u", ++ htt_stats_buf->ac_su_ndp_err); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ac_su_ndpa_err = %u", ++ htt_stats_buf->ac_su_ndpa_err); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ac_mu_mimo_ndpa_err = %u", ++ htt_stats_buf->ac_mu_mimo_ndpa_err); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ac_mu_mimo_ndp_err = %u", ++ htt_stats_buf->ac_mu_mimo_ndp_err); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ac_mu_mimo_brp1_err = %u", ++ htt_stats_buf->ac_mu_mimo_brp1_err); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ac_mu_mimo_brp2_err = %u", ++ htt_stats_buf->ac_mu_mimo_brp2_err); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ac_mu_mimo_brp3_err = %u\n", ++ htt_stats_buf->ac_mu_mimo_brp3_err); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_selfgen_ax_err_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_selfgen_ax_err_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_TX_SELFGEN_AX_ERR_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_su_ndp_err = %u", ++ htt_stats_buf->ax_su_ndp_err); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_su_ndpa_err = %u", ++ htt_stats_buf->ax_su_ndpa_err); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_mu_mimo_ndpa_err = %u", ++ htt_stats_buf->ax_mu_mimo_ndpa_err); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_mu_mimo_ndp_err = %u", ++ htt_stats_buf->ax_mu_mimo_ndp_err); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_mu_mimo_brp1_err = %u", ++ htt_stats_buf->ax_mu_mimo_brp1_err); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_mu_mimo_brp2_err = %u", ++ htt_stats_buf->ax_mu_mimo_brp2_err); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_mu_mimo_brp3_err = %u", ++ htt_stats_buf->ax_mu_mimo_brp3_err); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_mu_mimo_brp4_err = %u", ++ htt_stats_buf->ax_mu_mimo_brp4_err); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_mu_mimo_brp5_err = %u", ++ htt_stats_buf->ax_mu_mimo_brp5_err); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_mu_mimo_brp6_err = %u", ++ htt_stats_buf->ax_mu_mimo_brp6_err); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_mu_mimo_brp7_err = %u", ++ htt_stats_buf->ax_mu_mimo_brp7_err); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_basic_trigger_err = %u", ++ htt_stats_buf->ax_basic_trigger_err); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_bsr_trigger_err = %u", ++ htt_stats_buf->ax_bsr_trigger_err); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_mu_bar_trigger_err = %u", ++ htt_stats_buf->ax_mu_bar_trigger_err); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_mu_rts_trigger_err = %u\n", ++ htt_stats_buf->ax_mu_rts_trigger_err); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_pdev_mu_mimo_sch_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_pdev_mu_mimo_sch_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ u8 i; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "HTT_TX_PDEV_MU_MIMO_SCH_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mu_mimo_sch_posted = %u", ++ htt_stats_buf->mu_mimo_sch_posted); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mu_mimo_sch_failed = %u", ++ htt_stats_buf->mu_mimo_sch_failed); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mu_mimo_ppdu_posted = %u\n", ++ htt_stats_buf->mu_mimo_ppdu_posted); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "11ac MU_MIMO SCH STATS:"); ++ ++ for (i = 0; i < HTT_TX_PDEV_STATS_NUM_AC_MUMIMO_USER_STATS; i++) ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ac_mu_mimo_sch_nusers_%u = %u", ++ i, htt_stats_buf->ac_mu_mimo_sch_nusers[i]); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "\n11ax MU_MIMO SCH STATS:"); ++ ++ for (i = 0; i < HTT_TX_PDEV_STATS_NUM_AX_MUMIMO_USER_STATS; i++) ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ax_mu_mimo_sch_nusers_%u = %u", ++ i, htt_stats_buf->ax_mu_mimo_sch_nusers[i]); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "\n11ax OFDMA SCH STATS:"); ++ ++ for (i = 0; i < HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS; i++) ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ax_ofdma_sch_nusers_%u = %u", ++ i, htt_stats_buf->ax_ofdma_sch_nusers[i]); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_pdev_mu_mimo_mpdu_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_pdev_mpdu_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ if (htt_stats_buf->tx_sched_mode == HTT_STATS_TX_SCHED_MODE_MU_MIMO_AC) { ++ if (!htt_stats_buf->user_index) ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "HTT_TX_PDEV_MU_MIMO_AC_MPDU_STATS:\n"); ++ ++ if (htt_stats_buf->user_index < ++ HTT_TX_PDEV_STATS_NUM_AC_MUMIMO_USER_STATS) { ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ac_mu_mimo_mpdus_queued_usr_%u = %u", ++ htt_stats_buf->user_index, ++ htt_stats_buf->mpdus_queued_usr); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ac_mu_mimo_mpdus_tried_usr_%u = %u", ++ htt_stats_buf->user_index, ++ htt_stats_buf->mpdus_tried_usr); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ac_mu_mimo_mpdus_failed_usr_%u = %u", ++ htt_stats_buf->user_index, ++ htt_stats_buf->mpdus_failed_usr); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ac_mu_mimo_mpdus_requeued_usr_%u = %u", ++ htt_stats_buf->user_index, ++ htt_stats_buf->mpdus_requeued_usr); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ac_mu_mimo_err_no_ba_usr_%u = %u", ++ htt_stats_buf->user_index, ++ htt_stats_buf->err_no_ba_usr); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ac_mu_mimo_mpdu_underrun_usr_%u = %u", ++ htt_stats_buf->user_index, ++ htt_stats_buf->mpdu_underrun_usr); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ac_mu_mimo_ampdu_underrun_usr_%u = %u\n", ++ htt_stats_buf->user_index, ++ htt_stats_buf->ampdu_underrun_usr); ++ } ++ } ++ ++ if (htt_stats_buf->tx_sched_mode == HTT_STATS_TX_SCHED_MODE_MU_MIMO_AX) { ++ if (!htt_stats_buf->user_index) ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "HTT_TX_PDEV_MU_MIMO_AX_MPDU_STATS:\n"); ++ ++ if (htt_stats_buf->user_index < ++ HTT_TX_PDEV_STATS_NUM_AX_MUMIMO_USER_STATS) { ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ax_mu_mimo_mpdus_queued_usr_%u = %u", ++ htt_stats_buf->user_index, ++ htt_stats_buf->mpdus_queued_usr); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ax_mu_mimo_mpdus_tried_usr_%u = %u", ++ htt_stats_buf->user_index, ++ htt_stats_buf->mpdus_tried_usr); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ax_mu_mimo_mpdus_failed_usr_%u = %u", ++ htt_stats_buf->user_index, ++ htt_stats_buf->mpdus_failed_usr); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ax_mu_mimo_mpdus_requeued_usr_%u = %u", ++ htt_stats_buf->user_index, ++ htt_stats_buf->mpdus_requeued_usr); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ax_mu_mimo_err_no_ba_usr_%u = %u", ++ htt_stats_buf->user_index, ++ htt_stats_buf->err_no_ba_usr); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ax_mu_mimo_mpdu_underrun_usr_%u = %u", ++ htt_stats_buf->user_index, ++ htt_stats_buf->mpdu_underrun_usr); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ax_mu_mimo_ampdu_underrun_usr_%u = %u\n", ++ htt_stats_buf->user_index, ++ htt_stats_buf->ampdu_underrun_usr); ++ } ++ } ++ ++ if (htt_stats_buf->tx_sched_mode == HTT_STATS_TX_SCHED_MODE_MU_OFDMA_AX) { ++ if (!htt_stats_buf->user_index) ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "HTT_TX_PDEV_AX_MU_OFDMA_MPDU_STATS:\n"); ++ ++ if (htt_stats_buf->user_index < HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS) { ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ax_mu_ofdma_mpdus_queued_usr_%u = %u", ++ htt_stats_buf->user_index, ++ htt_stats_buf->mpdus_queued_usr); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ax_mu_ofdma_mpdus_tried_usr_%u = %u", ++ htt_stats_buf->user_index, ++ htt_stats_buf->mpdus_tried_usr); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ax_mu_ofdma_mpdus_failed_usr_%u = %u", ++ htt_stats_buf->user_index, ++ htt_stats_buf->mpdus_failed_usr); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ax_mu_ofdma_mpdus_requeued_usr_%u = %u", ++ htt_stats_buf->user_index, ++ htt_stats_buf->mpdus_requeued_usr); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ax_mu_ofdma_err_no_ba_usr_%u = %u", ++ htt_stats_buf->user_index, ++ htt_stats_buf->err_no_ba_usr); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ax_mu_ofdma_mpdu_underrun_usr_%u = %u", ++ htt_stats_buf->user_index, ++ htt_stats_buf->mpdu_underrun_usr); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ax_mu_ofdma_ampdu_underrun_usr_%u = %u\n", ++ htt_stats_buf->user_index, ++ htt_stats_buf->ampdu_underrun_usr); ++ } ++ } ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_sched_txq_cmd_posted_tlv_v(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_sched_txq_cmd_posted_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char sched_cmd_posted[HTT_MAX_STRING_LEN] = {0}; ++ u16 num_elements = min_t(u16, (tag_len >> 2), HTT_TX_PDEV_SCHED_TX_MODE_MAX); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_SCHED_TXQ_CMD_POSTED_TLV_V:"); ++ ++ ARRAY_TO_STRING(sched_cmd_posted, htt_stats_buf->sched_cmd_posted, ++ num_elements); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sched_cmd_posted = %s\n", ++ sched_cmd_posted); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_sched_txq_cmd_reaped_tlv_v(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_sched_txq_cmd_reaped_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char sched_cmd_reaped[HTT_MAX_STRING_LEN] = {0}; ++ u16 num_elements = min_t(u16, (tag_len >> 2), HTT_TX_PDEV_SCHED_TX_MODE_MAX); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_SCHED_TXQ_CMD_REAPED_TLV_V:"); ++ ++ ARRAY_TO_STRING(sched_cmd_reaped, htt_stats_buf->sched_cmd_reaped, ++ num_elements); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sched_cmd_reaped = %s\n", ++ sched_cmd_reaped); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_sched_txq_sched_order_su_tlv_v(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_sched_txq_sched_order_su_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char sched_order_su[HTT_MAX_STRING_LEN] = {0}; ++ /* each entry is u32, i.e. 4 bytes */ ++ u32 sched_order_su_num_entries = ++ min_t(u32, (tag_len >> 2), HTT_TX_PDEV_NUM_SCHED_ORDER_LOG); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "HTT_SCHED_TXQ_SCHED_ORDER_SU_TLV_V:"); ++ ++ ARRAY_TO_STRING(sched_order_su, htt_stats_buf->sched_order_su, ++ sched_order_su_num_entries); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sched_order_su = %s\n", ++ sched_order_su); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_sched_txq_sched_ineligibility_tlv_v(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_sched_txq_sched_ineligibility_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char sched_ineligibility[HTT_MAX_STRING_LEN] = {0}; ++ /* each entry is u32, i.e. 4 bytes */ ++ u32 sched_ineligibility_num_entries = tag_len >> 2; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "HTT_SCHED_TXQ_SCHED_INELIGIBILITY_V:"); ++ ++ ARRAY_TO_STRING(sched_ineligibility, htt_stats_buf->sched_ineligibility, ++ sched_ineligibility_num_entries); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sched_ineligibility = %s\n", ++ sched_ineligibility); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_pdev_stats_sched_per_txq_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_pdev_stats_sched_per_txq_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "HTT_TX_PDEV_STATS_SCHED_PER_TXQ_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mac_id = %u", ++ htt_stats_buf->mac_id__txq_id__word & 0xFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "txq_id = %u", ++ (htt_stats_buf->mac_id__txq_id__word & 0xFF00) >> 8); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sched_policy = %u", ++ htt_stats_buf->sched_policy); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "last_sched_cmd_posted_timestamp = %u", ++ htt_stats_buf->last_sched_cmd_posted_timestamp); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "last_sched_cmd_compl_timestamp = %u", ++ htt_stats_buf->last_sched_cmd_compl_timestamp); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sched_2_tac_lwm_count = %u", ++ htt_stats_buf->sched_2_tac_lwm_count); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sched_2_tac_ring_full = %u", ++ htt_stats_buf->sched_2_tac_ring_full); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sched_cmd_post_failure = %u", ++ htt_stats_buf->sched_cmd_post_failure); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_active_tids = %u", ++ htt_stats_buf->num_active_tids); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_ps_schedules = %u", ++ htt_stats_buf->num_ps_schedules); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sched_cmds_pending = %u", ++ htt_stats_buf->sched_cmds_pending); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_tid_register = %u", ++ htt_stats_buf->num_tid_register); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_tid_unregister = %u", ++ htt_stats_buf->num_tid_unregister); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_qstats_queried = %u", ++ htt_stats_buf->num_qstats_queried); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "qstats_update_pending = %u", ++ htt_stats_buf->qstats_update_pending); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "last_qstats_query_timestamp = %u", ++ htt_stats_buf->last_qstats_query_timestamp); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_tqm_cmdq_full = %u", ++ htt_stats_buf->num_tqm_cmdq_full); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_de_sched_algo_trigger = %u", ++ htt_stats_buf->num_de_sched_algo_trigger); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_rt_sched_algo_trigger = %u", ++ htt_stats_buf->num_rt_sched_algo_trigger); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_tqm_sched_algo_trigger = %u", ++ htt_stats_buf->num_tqm_sched_algo_trigger); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "notify_sched = %u\n", ++ htt_stats_buf->notify_sched); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "dur_based_sendn_term = %u\n", ++ htt_stats_buf->dur_based_sendn_term); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void htt_print_stats_tx_sched_cmn_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_stats_tx_sched_cmn_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_STATS_TX_SCHED_CMN_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mac_id = %u", ++ htt_stats_buf->mac_id__word & 0xFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "current_timestamp = %u\n", ++ htt_stats_buf->current_timestamp); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_tqm_gen_mpdu_stats_tlv_v(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_tqm_gen_mpdu_stats_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char gen_mpdu_end_reason[HTT_MAX_STRING_LEN] = {0}; ++ u16 num_elements = min_t(u16, (tag_len >> 2), ++ HTT_TX_TQM_MAX_LIST_MPDU_END_REASON); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_TX_TQM_GEN_MPDU_STATS_TLV_V:"); ++ ++ ARRAY_TO_STRING(gen_mpdu_end_reason, htt_stats_buf->gen_mpdu_end_reason, ++ num_elements); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "gen_mpdu_end_reason = %s\n", ++ gen_mpdu_end_reason); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_tqm_list_mpdu_stats_tlv_v(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_tqm_list_mpdu_stats_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char list_mpdu_end_reason[HTT_MAX_STRING_LEN] = {0}; ++ u16 num_elems = min_t(u16, (tag_len >> 2), HTT_TX_TQM_MAX_LIST_MPDU_END_REASON); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "HTT_TX_TQM_LIST_MPDU_STATS_TLV_V:"); ++ ++ ARRAY_TO_STRING(list_mpdu_end_reason, htt_stats_buf->list_mpdu_end_reason, ++ num_elems); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "list_mpdu_end_reason = %s\n", ++ list_mpdu_end_reason); ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_tqm_list_mpdu_cnt_tlv_v(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_tqm_list_mpdu_cnt_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char list_mpdu_cnt_hist[HTT_MAX_STRING_LEN] = {0}; ++ u16 num_elems = min_t(u16, (tag_len >> 2), ++ HTT_TX_TQM_MAX_LIST_MPDU_CNT_HISTOGRAM_BINS); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_TX_TQM_LIST_MPDU_CNT_TLV_V:"); ++ ++ ARRAY_TO_STRING(list_mpdu_cnt_hist, htt_stats_buf->list_mpdu_cnt_hist, ++ num_elems); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "list_mpdu_cnt_hist = %s\n", ++ list_mpdu_cnt_hist); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_tqm_pdev_stats_tlv_v(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_tqm_pdev_stats_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_TX_TQM_PDEV_STATS_TLV_V:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "msdu_count = %u", ++ htt_stats_buf->msdu_count); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mpdu_count = %u", ++ htt_stats_buf->mpdu_count); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "remove_msdu = %u", ++ htt_stats_buf->remove_msdu); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "remove_mpdu = %u", ++ htt_stats_buf->remove_mpdu); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "remove_msdu_ttl = %u", ++ htt_stats_buf->remove_msdu_ttl); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "send_bar = %u", ++ htt_stats_buf->send_bar); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "bar_sync = %u", ++ htt_stats_buf->bar_sync); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "notify_mpdu = %u", ++ htt_stats_buf->notify_mpdu); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sync_cmd = %u", ++ htt_stats_buf->sync_cmd); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "write_cmd = %u", ++ htt_stats_buf->write_cmd); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "hwsch_trigger = %u", ++ htt_stats_buf->hwsch_trigger); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ack_tlv_proc = %u", ++ htt_stats_buf->ack_tlv_proc); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "gen_mpdu_cmd = %u", ++ htt_stats_buf->gen_mpdu_cmd); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "gen_list_cmd = %u", ++ htt_stats_buf->gen_list_cmd); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "remove_mpdu_cmd = %u", ++ htt_stats_buf->remove_mpdu_cmd); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "remove_mpdu_tried_cmd = %u", ++ htt_stats_buf->remove_mpdu_tried_cmd); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mpdu_queue_stats_cmd = %u", ++ htt_stats_buf->mpdu_queue_stats_cmd); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mpdu_head_info_cmd = %u", ++ htt_stats_buf->mpdu_head_info_cmd); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "msdu_flow_stats_cmd = %u", ++ htt_stats_buf->msdu_flow_stats_cmd); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "remove_msdu_cmd = %u", ++ htt_stats_buf->remove_msdu_cmd); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "remove_msdu_ttl_cmd = %u", ++ htt_stats_buf->remove_msdu_ttl_cmd); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "flush_cache_cmd = %u", ++ htt_stats_buf->flush_cache_cmd); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "update_mpduq_cmd = %u", ++ htt_stats_buf->update_mpduq_cmd); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "enqueue = %u", ++ htt_stats_buf->enqueue); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "enqueue_notify = %u", ++ htt_stats_buf->enqueue_notify); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "notify_mpdu_at_head = %u", ++ htt_stats_buf->notify_mpdu_at_head); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "notify_mpdu_state_valid = %u", ++ htt_stats_buf->notify_mpdu_state_valid); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sched_udp_notify1 = %u", ++ htt_stats_buf->sched_udp_notify1); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sched_udp_notify2 = %u", ++ htt_stats_buf->sched_udp_notify2); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sched_nonudp_notify1 = %u", ++ htt_stats_buf->sched_nonudp_notify1); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sched_nonudp_notify2 = %u\n", ++ htt_stats_buf->sched_nonudp_notify2); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void htt_print_tx_tqm_cmn_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_tqm_cmn_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_TX_TQM_CMN_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mac_id = %u", ++ htt_stats_buf->mac_id__word & 0xFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "max_cmdq_id = %u", ++ htt_stats_buf->max_cmdq_id); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "list_mpdu_cnt_hist_intvl = %u", ++ htt_stats_buf->list_mpdu_cnt_hist_intvl); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "add_msdu = %u", ++ htt_stats_buf->add_msdu); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "q_empty = %u", ++ htt_stats_buf->q_empty); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "q_not_empty = %u", ++ htt_stats_buf->q_not_empty); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "drop_notification = %u", ++ htt_stats_buf->drop_notification); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "desc_threshold = %u\n", ++ htt_stats_buf->desc_threshold); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void htt_print_tx_tqm_error_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_tqm_error_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_TX_TQM_ERROR_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "q_empty_failure = %u", ++ htt_stats_buf->q_empty_failure); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "q_not_empty_failure = %u", ++ htt_stats_buf->q_not_empty_failure); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "add_msdu_failure = %u\n", ++ htt_stats_buf->add_msdu_failure); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void htt_print_tx_tqm_cmdq_status_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_tqm_cmdq_status_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_TX_TQM_CMDQ_STATUS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mac_id = %u", ++ htt_stats_buf->mac_id__cmdq_id__word & 0xFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "cmdq_id = %u\n", ++ (htt_stats_buf->mac_id__cmdq_id__word & 0xFF00) >> 8); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sync_cmd = %u", ++ htt_stats_buf->sync_cmd); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "write_cmd = %u", ++ htt_stats_buf->write_cmd); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "gen_mpdu_cmd = %u", ++ htt_stats_buf->gen_mpdu_cmd); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mpdu_queue_stats_cmd = %u", ++ htt_stats_buf->mpdu_queue_stats_cmd); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mpdu_head_info_cmd = %u", ++ htt_stats_buf->mpdu_head_info_cmd); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "msdu_flow_stats_cmd = %u", ++ htt_stats_buf->msdu_flow_stats_cmd); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "remove_mpdu_cmd = %u", ++ htt_stats_buf->remove_mpdu_cmd); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "remove_msdu_cmd = %u", ++ htt_stats_buf->remove_msdu_cmd); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "flush_cache_cmd = %u", ++ htt_stats_buf->flush_cache_cmd); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "update_mpduq_cmd = %u", ++ htt_stats_buf->update_mpduq_cmd); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "update_msduq_cmd = %u\n", ++ htt_stats_buf->update_msduq_cmd); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_de_eapol_packets_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_de_eapol_packets_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "HTT_TX_DE_EAPOL_PACKETS_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "m1_packets = %u", ++ htt_stats_buf->m1_packets); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "m2_packets = %u", ++ htt_stats_buf->m2_packets); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "m3_packets = %u", ++ htt_stats_buf->m3_packets); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "m4_packets = %u", ++ htt_stats_buf->m4_packets); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "g1_packets = %u", ++ htt_stats_buf->g1_packets); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "g2_packets = %u\n", ++ htt_stats_buf->g2_packets); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_de_classify_failed_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_de_classify_failed_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "HTT_TX_DE_CLASSIFY_FAILED_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ap_bss_peer_not_found = %u", ++ htt_stats_buf->ap_bss_peer_not_found); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ap_bcast_mcast_no_peer = %u", ++ htt_stats_buf->ap_bcast_mcast_no_peer); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sta_delete_in_progress = %u", ++ htt_stats_buf->sta_delete_in_progress); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ibss_no_bss_peer = %u", ++ htt_stats_buf->ibss_no_bss_peer); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "invalid_vdev_type = %u", ++ htt_stats_buf->invalid_vdev_type); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "invalid_ast_peer_entry = %u", ++ htt_stats_buf->invalid_ast_peer_entry); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "peer_entry_invalid = %u", ++ htt_stats_buf->peer_entry_invalid); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ethertype_not_ip = %u", ++ htt_stats_buf->ethertype_not_ip); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "eapol_lookup_failed = %u", ++ htt_stats_buf->eapol_lookup_failed); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "qpeer_not_allow_data = %u", ++ htt_stats_buf->qpeer_not_allow_data); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fse_tid_override = %u", ++ htt_stats_buf->fse_tid_override); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ipv6_jumbogram_zero_length = %u", ++ htt_stats_buf->ipv6_jumbogram_zero_length); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "qos_to_non_qos_in_prog = %u\n", ++ htt_stats_buf->qos_to_non_qos_in_prog); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_de_classify_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_de_classify_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_TX_DE_CLASSIFY_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "arp_packets = %u", ++ htt_stats_buf->arp_packets); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "igmp_packets = %u", ++ htt_stats_buf->igmp_packets); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "dhcp_packets = %u", ++ htt_stats_buf->dhcp_packets); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "host_inspected = %u", ++ htt_stats_buf->host_inspected); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "htt_included = %u", ++ htt_stats_buf->htt_included); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "htt_valid_mcs = %u", ++ htt_stats_buf->htt_valid_mcs); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "htt_valid_nss = %u", ++ htt_stats_buf->htt_valid_nss); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "htt_valid_preamble_type = %u", ++ htt_stats_buf->htt_valid_preamble_type); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "htt_valid_chainmask = %u", ++ htt_stats_buf->htt_valid_chainmask); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "htt_valid_guard_interval = %u", ++ htt_stats_buf->htt_valid_guard_interval); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "htt_valid_retries = %u", ++ htt_stats_buf->htt_valid_retries); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "htt_valid_bw_info = %u", ++ htt_stats_buf->htt_valid_bw_info); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "htt_valid_power = %u", ++ htt_stats_buf->htt_valid_power); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "htt_valid_key_flags = 0x%x", ++ htt_stats_buf->htt_valid_key_flags); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "htt_valid_no_encryption = %u", ++ htt_stats_buf->htt_valid_no_encryption); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fse_entry_count = %u", ++ htt_stats_buf->fse_entry_count); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fse_priority_be = %u", ++ htt_stats_buf->fse_priority_be); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fse_priority_high = %u", ++ htt_stats_buf->fse_priority_high); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fse_priority_low = %u", ++ htt_stats_buf->fse_priority_low); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fse_traffic_ptrn_be = %u", ++ htt_stats_buf->fse_traffic_ptrn_be); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fse_traffic_ptrn_over_sub = %u", ++ htt_stats_buf->fse_traffic_ptrn_over_sub); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fse_traffic_ptrn_bursty = %u", ++ htt_stats_buf->fse_traffic_ptrn_bursty); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fse_traffic_ptrn_interactive = %u", ++ htt_stats_buf->fse_traffic_ptrn_interactive); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fse_traffic_ptrn_periodic = %u", ++ htt_stats_buf->fse_traffic_ptrn_periodic); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fse_hwqueue_alloc = %u", ++ htt_stats_buf->fse_hwqueue_alloc); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fse_hwqueue_created = %u", ++ htt_stats_buf->fse_hwqueue_created); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fse_hwqueue_send_to_host = %u", ++ htt_stats_buf->fse_hwqueue_send_to_host); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mcast_entry = %u", ++ htt_stats_buf->mcast_entry); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "bcast_entry = %u", ++ htt_stats_buf->bcast_entry); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "htt_update_peer_cache = %u", ++ htt_stats_buf->htt_update_peer_cache); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "htt_learning_frame = %u", ++ htt_stats_buf->htt_learning_frame); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fse_invalid_peer = %u", ++ htt_stats_buf->fse_invalid_peer); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mec_notify = %u\n", ++ htt_stats_buf->mec_notify); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_de_classify_status_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_de_classify_status_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "HTT_TX_DE_CLASSIFY_STATUS_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "eok = %u", ++ htt_stats_buf->eok); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "classify_done = %u", ++ htt_stats_buf->classify_done); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "lookup_failed = %u", ++ htt_stats_buf->lookup_failed); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "send_host_dhcp = %u", ++ htt_stats_buf->send_host_dhcp); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "send_host_mcast = %u", ++ htt_stats_buf->send_host_mcast); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "send_host_unknown_dest = %u", ++ htt_stats_buf->send_host_unknown_dest); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "send_host = %u", ++ htt_stats_buf->send_host); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "status_invalid = %u\n", ++ htt_stats_buf->status_invalid); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_de_enqueue_packets_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_de_enqueue_packets_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "HTT_TX_DE_ENQUEUE_PACKETS_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "enqueued_pkts = %u", ++ htt_stats_buf->enqueued_pkts); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "to_tqm = %u", ++ htt_stats_buf->to_tqm); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "to_tqm_bypass = %u\n", ++ htt_stats_buf->to_tqm_bypass); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_de_enqueue_discard_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_de_enqueue_discard_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "HTT_TX_DE_ENQUEUE_DISCARD_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "discarded_pkts = %u", ++ htt_stats_buf->discarded_pkts); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "local_frames = %u", ++ htt_stats_buf->local_frames); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "is_ext_msdu = %u\n", ++ htt_stats_buf->is_ext_msdu); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void htt_print_tx_de_compl_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_de_compl_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_TX_DE_COMPL_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tcl_dummy_frame = %u", ++ htt_stats_buf->tcl_dummy_frame); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tqm_dummy_frame = %u", ++ htt_stats_buf->tqm_dummy_frame); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tqm_notify_frame = %u", ++ htt_stats_buf->tqm_notify_frame); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fw2wbm_enq = %u", ++ htt_stats_buf->fw2wbm_enq); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tqm_bypass_frame = %u\n", ++ htt_stats_buf->tqm_bypass_frame); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_de_fw2wbm_ring_full_hist_tlv(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_de_fw2wbm_ring_full_hist_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char fw2wbm_ring_full_hist[HTT_MAX_STRING_LEN] = {0}; ++ u16 num_elements = tag_len >> 2; ++ u32 required_buffer_size = HTT_MAX_PRINT_CHAR_PER_ELEM * num_elements; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "HTT_TX_DE_FW2WBM_RING_FULL_HIST_TLV"); ++ ++ if (required_buffer_size < HTT_MAX_STRING_LEN) { ++ ARRAY_TO_STRING(fw2wbm_ring_full_hist, ++ htt_stats_buf->fw2wbm_ring_full_hist, ++ num_elements); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "fw2wbm_ring_full_hist = %s\n", ++ fw2wbm_ring_full_hist); ++ } else { ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "INSUFFICIENT PRINT BUFFER "); ++ } ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_de_cmn_stats_tlv(const void *tag_buf, struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_de_cmn_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_TX_DE_CMN_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mac_id = %u", ++ htt_stats_buf->mac_id__word & 0xFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tcl2fw_entry_count = %u", ++ htt_stats_buf->tcl2fw_entry_count); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "not_to_fw = %u", ++ htt_stats_buf->not_to_fw); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "invalid_pdev_vdev_peer = %u", ++ htt_stats_buf->invalid_pdev_vdev_peer); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tcl_res_invalid_addrx = %u", ++ htt_stats_buf->tcl_res_invalid_addrx); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "wbm2fw_entry_count = %u", ++ htt_stats_buf->wbm2fw_entry_count); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "invalid_pdev = %u\n", ++ htt_stats_buf->invalid_pdev); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void htt_print_ring_if_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_ring_if_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char low_wm_hit_count[HTT_MAX_STRING_LEN] = {0}; ++ char high_wm_hit_count[HTT_MAX_STRING_LEN] = {0}; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_RING_IF_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "base_addr = %u", ++ htt_stats_buf->base_addr); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "elem_size = %u", ++ htt_stats_buf->elem_size); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_elems = %u", ++ htt_stats_buf->num_elems__prefetch_tail_idx & 0xFFFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "prefetch_tail_idx = %u", ++ (htt_stats_buf->num_elems__prefetch_tail_idx & ++ 0xFFFF0000) >> 16); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "head_idx = %u", ++ htt_stats_buf->head_idx__tail_idx & 0xFFFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tail_idx = %u", ++ (htt_stats_buf->head_idx__tail_idx & 0xFFFF0000) >> 16); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "shadow_head_idx = %u", ++ htt_stats_buf->shadow_head_idx__shadow_tail_idx & 0xFFFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "shadow_tail_idx = %u", ++ (htt_stats_buf->shadow_head_idx__shadow_tail_idx & ++ 0xFFFF0000) >> 16); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_tail_incr = %u", ++ htt_stats_buf->num_tail_incr); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "lwm_thresh = %u", ++ htt_stats_buf->lwm_thresh__hwm_thresh & 0xFFFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "hwm_thresh = %u", ++ (htt_stats_buf->lwm_thresh__hwm_thresh & 0xFFFF0000) >> 16); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "overrun_hit_count = %u", ++ htt_stats_buf->overrun_hit_count); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "underrun_hit_count = %u", ++ htt_stats_buf->underrun_hit_count); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "prod_blockwait_count = %u", ++ htt_stats_buf->prod_blockwait_count); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "cons_blockwait_count = %u", ++ htt_stats_buf->cons_blockwait_count); ++ ++ ARRAY_TO_STRING(low_wm_hit_count, htt_stats_buf->low_wm_hit_count, ++ HTT_STATS_LOW_WM_BINS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "low_wm_hit_count = %s ", ++ low_wm_hit_count); ++ ++ ARRAY_TO_STRING(high_wm_hit_count, htt_stats_buf->high_wm_hit_count, ++ HTT_STATS_HIGH_WM_BINS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "high_wm_hit_count = %s\n", ++ high_wm_hit_count); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void htt_print_ring_if_cmn_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_ring_if_cmn_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_RING_IF_CMN_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mac_id = %u", ++ htt_stats_buf->mac_id__word & 0xFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_records = %u\n", ++ htt_stats_buf->num_records); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void htt_print_sfm_client_user_tlv_v(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_sfm_client_user_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char dwords_used_by_user_n[HTT_MAX_STRING_LEN] = {0}; ++ u16 num_elems = tag_len >> 2; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_SFM_CLIENT_USER_TLV_V:"); ++ ++ ARRAY_TO_STRING(dwords_used_by_user_n, ++ htt_stats_buf->dwords_used_by_user_n, ++ num_elems); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "dwords_used_by_user_n = %s\n", ++ dwords_used_by_user_n); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void htt_print_sfm_client_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_sfm_client_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_SFM_CLIENT_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "client_id = %u", ++ htt_stats_buf->client_id); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "buf_min = %u", ++ htt_stats_buf->buf_min); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "buf_max = %u", ++ htt_stats_buf->buf_max); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "buf_busy = %u", ++ htt_stats_buf->buf_busy); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "buf_alloc = %u", ++ htt_stats_buf->buf_alloc); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "buf_avail = %u", ++ htt_stats_buf->buf_avail); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_users = %u\n", ++ htt_stats_buf->num_users); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void htt_print_sfm_cmn_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_sfm_cmn_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_SFM_CMN_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mac_id = %u", ++ htt_stats_buf->mac_id__word & 0xFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "buf_total = %u", ++ htt_stats_buf->buf_total); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mem_empty = %u", ++ htt_stats_buf->mem_empty); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "deallocate_bufs = %u", ++ htt_stats_buf->deallocate_bufs); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_records = %u\n", ++ htt_stats_buf->num_records); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void htt_print_sring_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_sring_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_SRING_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mac_id = %u", ++ htt_stats_buf->mac_id__ring_id__arena__ep & 0xFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ring_id = %u", ++ (htt_stats_buf->mac_id__ring_id__arena__ep & 0xFF00) >> 8); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "arena = %u", ++ (htt_stats_buf->mac_id__ring_id__arena__ep & 0xFF0000) >> 16); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ep = %u", ++ (htt_stats_buf->mac_id__ring_id__arena__ep & 0x1000000) >> 24); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "base_addr_lsb = 0x%x", ++ htt_stats_buf->base_addr_lsb); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "base_addr_msb = 0x%x", ++ htt_stats_buf->base_addr_msb); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ring_size = %u", ++ htt_stats_buf->ring_size); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "elem_size = %u", ++ htt_stats_buf->elem_size); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_avail_words = %u", ++ htt_stats_buf->num_avail_words__num_valid_words & 0xFFFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_valid_words = %u", ++ (htt_stats_buf->num_avail_words__num_valid_words & ++ 0xFFFF0000) >> 16); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "head_ptr = %u", ++ htt_stats_buf->head_ptr__tail_ptr & 0xFFFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tail_ptr = %u", ++ (htt_stats_buf->head_ptr__tail_ptr & 0xFFFF0000) >> 16); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "consumer_empty = %u", ++ htt_stats_buf->consumer_empty__producer_full & 0xFFFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "producer_full = %u", ++ (htt_stats_buf->consumer_empty__producer_full & ++ 0xFFFF0000) >> 16); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "prefetch_count = %u", ++ htt_stats_buf->prefetch_count__internal_tail_ptr & 0xFFFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "internal_tail_ptr = %u\n", ++ (htt_stats_buf->prefetch_count__internal_tail_ptr & ++ 0xFFFF0000) >> 16); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void htt_print_sring_cmn_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_sring_cmn_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_SRING_CMN_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_records = %u\n", ++ htt_stats_buf->num_records); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void htt_print_tx_pdev_rate_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_pdev_rate_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ u8 j; ++ char str_buf[HTT_MAX_STRING_LEN] = {0}; ++ char *tx_gi[HTT_TX_PEER_STATS_NUM_GI_COUNTERS] = {NULL}; ++ ++ for (j = 0; j < HTT_TX_PEER_STATS_NUM_GI_COUNTERS; j++) { ++ tx_gi[j] = kmalloc(HTT_MAX_STRING_LEN, GFP_ATOMIC); ++ if (!tx_gi[j]) ++ goto fail; ++ } ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_TX_PDEV_RATE_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mac_id = %u", ++ htt_stats_buf->mac_id__word & 0xFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_ldpc = %u", ++ htt_stats_buf->tx_ldpc); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ac_mu_mimo_tx_ldpc = %u", ++ htt_stats_buf->ac_mu_mimo_tx_ldpc); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_mu_mimo_tx_ldpc = %u", ++ htt_stats_buf->ax_mu_mimo_tx_ldpc); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ofdma_tx_ldpc = %u", ++ htt_stats_buf->ofdma_tx_ldpc); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rts_cnt = %u", ++ htt_stats_buf->rts_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rts_success = %u", ++ htt_stats_buf->rts_success); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ack_rssi = %u", ++ htt_stats_buf->ack_rssi); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "Legacy CCK Rates: 1 Mbps: %u, 2 Mbps: %u, 5.5 Mbps: %u, 11 Mbps: %u", ++ htt_stats_buf->tx_legacy_cck_rate[0], ++ htt_stats_buf->tx_legacy_cck_rate[1], ++ htt_stats_buf->tx_legacy_cck_rate[2], ++ htt_stats_buf->tx_legacy_cck_rate[3]); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "Legacy OFDM Rates: 6 Mbps: %u, 9 Mbps: %u, 12 Mbps: %u, 18 Mbps: %u\n" ++ " 24 Mbps: %u, 36 Mbps: %u, 48 Mbps: %u, 54 Mbps: %u", ++ htt_stats_buf->tx_legacy_ofdm_rate[0], ++ htt_stats_buf->tx_legacy_ofdm_rate[1], ++ htt_stats_buf->tx_legacy_ofdm_rate[2], ++ htt_stats_buf->tx_legacy_ofdm_rate[3], ++ htt_stats_buf->tx_legacy_ofdm_rate[4], ++ htt_stats_buf->tx_legacy_ofdm_rate[5], ++ htt_stats_buf->tx_legacy_ofdm_rate[6], ++ htt_stats_buf->tx_legacy_ofdm_rate[7]); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->tx_mcs, ++ HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_mcs = %s ", str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->ac_mu_mimo_tx_mcs, ++ HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ac_mu_mimo_tx_mcs = %s ", str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->ax_mu_mimo_tx_mcs, ++ HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_mu_mimo_tx_mcs = %s ", str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->ofdma_tx_mcs, ++ HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ofdma_tx_mcs = %s ", str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->tx_nss, ++ HTT_TX_PDEV_STATS_NUM_SPATIAL_STREAMS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_nss = %s ", str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->ac_mu_mimo_tx_nss, ++ HTT_TX_PDEV_STATS_NUM_SPATIAL_STREAMS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ac_mu_mimo_tx_nss = %s ", str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->ax_mu_mimo_tx_nss, ++ HTT_TX_PDEV_STATS_NUM_SPATIAL_STREAMS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_mu_mimo_tx_nss = %s ", str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->ofdma_tx_nss, ++ HTT_TX_PDEV_STATS_NUM_SPATIAL_STREAMS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ofdma_tx_nss = %s ", str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->tx_bw, ++ HTT_TX_PDEV_STATS_NUM_BW_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_bw = %s ", str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->ac_mu_mimo_tx_bw, ++ HTT_TX_PDEV_STATS_NUM_BW_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ac_mu_mimo_tx_bw = %s ", str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->ax_mu_mimo_tx_bw, ++ HTT_TX_PDEV_STATS_NUM_BW_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ax_mu_mimo_tx_bw = %s ", str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->ofdma_tx_bw, ++ HTT_TX_PDEV_STATS_NUM_BW_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ofdma_tx_bw = %s ", str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->tx_stbc, ++ HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_stbc = %s ", str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->tx_pream, ++ HTT_TX_PDEV_STATS_NUM_PREAMBLE_TYPES); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_pream = %s ", str_buf); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HE LTF: 1x: %u, 2x: %u, 4x: %u", ++ htt_stats_buf->tx_he_ltf[1], ++ htt_stats_buf->tx_he_ltf[2], ++ htt_stats_buf->tx_he_ltf[3]); ++ ++ /* SU GI Stats */ ++ for (j = 0; j < HTT_TX_PDEV_STATS_NUM_GI_COUNTERS; j++) { ++ ARRAY_TO_STRING(tx_gi[j], htt_stats_buf->tx_gi[j], ++ HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_gi[%u] = %s ", ++ j, tx_gi[j]); ++ } ++ ++ /* AC MU-MIMO GI Stats */ ++ for (j = 0; j < HTT_TX_PDEV_STATS_NUM_GI_COUNTERS; j++) { ++ ARRAY_TO_STRING(tx_gi[j], htt_stats_buf->ac_mu_mimo_tx_gi[j], ++ HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ac_mu_mimo_tx_gi[%u] = %s ", ++ j, tx_gi[j]); ++ } ++ ++ /* AX MU-MIMO GI Stats */ ++ for (j = 0; j < HTT_TX_PDEV_STATS_NUM_GI_COUNTERS; j++) { ++ ARRAY_TO_STRING(tx_gi[j], htt_stats_buf->ax_mu_mimo_tx_gi[j], ++ HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ax_mu_mimo_tx_gi[%u] = %s ", ++ j, tx_gi[j]); ++ } ++ ++ /* DL OFDMA GI Stats */ ++ for (j = 0; j < HTT_TX_PDEV_STATS_NUM_GI_COUNTERS; j++) { ++ ARRAY_TO_STRING(tx_gi[j], htt_stats_buf->ofdma_tx_gi[j], ++ HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ofdma_tx_gi[%u] = %s ", ++ j, tx_gi[j]); ++ } ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->tx_dcm, ++ HTT_TX_PDEV_STATS_NUM_DCM_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_dcm = %s\n", str_buf); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++fail: ++ for (j = 0; j < HTT_TX_PEER_STATS_NUM_GI_COUNTERS; j++) ++ kfree(tx_gi[j]); ++} ++ ++static inline void htt_print_rx_pdev_rate_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_rx_pdev_rate_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ u8 i, j; ++ u16 index = 0; ++ char *rssi_chain[HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS] = {NULL}; ++ char *rx_gi[HTT_RX_PDEV_STATS_NUM_GI_COUNTERS] = {NULL}; ++ char str_buf[HTT_MAX_STRING_LEN] = {0}; ++ char *rx_pilot_evm_db[HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS] = {NULL}; ++ ++ for (j = 0; j < HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS; j++) { ++ rssi_chain[j] = kmalloc(HTT_MAX_STRING_LEN, GFP_ATOMIC); ++ if (!rssi_chain[j]) ++ goto fail; ++ } ++ ++ for (j = 0; j < HTT_RX_PDEV_STATS_NUM_GI_COUNTERS; j++) { ++ rx_gi[j] = kmalloc(HTT_MAX_STRING_LEN, GFP_ATOMIC); ++ if (!rx_gi[j]) ++ goto fail; ++ } ++ ++ for (j = 0; j < HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS; j++) { ++ rx_pilot_evm_db[j] = kmalloc(HTT_MAX_STRING_LEN, GFP_ATOMIC); ++ if (!rx_pilot_evm_db[j]) ++ goto fail; ++ } ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_RX_PDEV_RATE_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mac_id = %u", ++ htt_stats_buf->mac_id__word & 0xFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "nsts = %u", ++ htt_stats_buf->nsts); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_ldpc = %u", ++ htt_stats_buf->rx_ldpc); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rts_cnt = %u", ++ htt_stats_buf->rts_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rssi_mgmt = %u", ++ htt_stats_buf->rssi_mgmt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rssi_data = %u", ++ htt_stats_buf->rssi_data); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rssi_comb = %u", ++ htt_stats_buf->rssi_comb); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rssi_in_dbm = %d", ++ htt_stats_buf->rssi_in_dbm); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->rx_mcs, ++ HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_mcs = %s ", str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->rx_nss, ++ HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_nss = %s ", str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->rx_dcm, ++ HTT_RX_PDEV_STATS_NUM_DCM_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_dcm = %s ", str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->rx_stbc, ++ HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_stbc = %s ", str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->rx_bw, ++ HTT_RX_PDEV_STATS_NUM_BW_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_bw = %s ", str_buf); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_evm_nss_count = %u", ++ htt_stats_buf->nss_count); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_evm_pilot_count = %u", ++ htt_stats_buf->pilot_count); ++ ++ for (j = 0; j < HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS; j++) { ++ index = 0; ++ ++ for (i = 0; i < HTT_RX_PDEV_STATS_RXEVM_MAX_PILOTS_PER_NSS; i++) ++ index += scnprintf(&rx_pilot_evm_db[j][index], ++ HTT_MAX_STRING_LEN - index, ++ " %u:%d,", ++ i, ++ htt_stats_buf->rx_pilot_evm_db[j][i]); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "pilot_evm_dB[%u] = %s ", ++ j, rx_pilot_evm_db[j]); ++ } ++ ++ index = 0; ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ for (i = 0; i < HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS; i++) ++ index += scnprintf(&str_buf[index], ++ HTT_MAX_STRING_LEN - index, ++ " %u:%d,", i, htt_stats_buf->rx_pilot_evm_db_mean[i]); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "pilot_evm_dB_mean = %s ", str_buf); ++ ++ for (j = 0; j < HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS; j++) { ++ ARRAY_TO_STRING(rssi_chain[j], htt_stats_buf->rssi_chain[j], ++ HTT_RX_PDEV_STATS_NUM_BW_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rssi_chain[%u] = %s ", ++ j, rssi_chain[j]); ++ } ++ ++ for (j = 0; j < HTT_RX_PDEV_STATS_NUM_GI_COUNTERS; j++) { ++ ARRAY_TO_STRING(rx_gi[j], htt_stats_buf->rx_gi[j], ++ HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_gi[%u] = %s ", ++ j, rx_gi[j]); ++ } ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->rx_pream, ++ HTT_RX_PDEV_STATS_NUM_PREAMBLE_TYPES); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_pream = %s", str_buf); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_11ax_su_ext = %u", ++ htt_stats_buf->rx_11ax_su_ext); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_11ac_mumimo = %u", ++ htt_stats_buf->rx_11ac_mumimo); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_11ax_mumimo = %u", ++ htt_stats_buf->rx_11ax_mumimo); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_11ax_ofdma = %u", ++ htt_stats_buf->rx_11ax_ofdma); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "txbf = %u", ++ htt_stats_buf->txbf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->rx_legacy_cck_rate, ++ HTT_RX_PDEV_STATS_NUM_LEGACY_CCK_STATS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_legacy_cck_rate = %s ", ++ str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->rx_legacy_ofdm_rate, ++ HTT_RX_PDEV_STATS_NUM_LEGACY_OFDM_STATS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_legacy_ofdm_rate = %s ", ++ str_buf); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_active_dur_us_low = %u", ++ htt_stats_buf->rx_active_dur_us_low); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_active_dur_us_high = %u", ++ htt_stats_buf->rx_active_dur_us_high); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_11ax_ul_ofdma = %u", ++ htt_stats_buf->rx_11ax_ul_ofdma); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->ul_ofdma_rx_mcs, ++ HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ul_ofdma_rx_mcs = %s ", str_buf); ++ ++ for (j = 0; j < HTT_RX_PDEV_STATS_NUM_GI_COUNTERS; j++) { ++ ARRAY_TO_STRING(rx_gi[j], htt_stats_buf->ul_ofdma_rx_gi[j], ++ HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ul_ofdma_rx_gi[%u] = %s ", ++ j, rx_gi[j]); ++ } ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->ul_ofdma_rx_nss, ++ HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ul_ofdma_rx_nss = %s ", str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->ul_ofdma_rx_bw, ++ HTT_RX_PDEV_STATS_NUM_BW_COUNTERS); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ul_ofdma_rx_bw = %s ", str_buf); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ul_ofdma_rx_stbc = %u", ++ htt_stats_buf->ul_ofdma_rx_stbc); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ul_ofdma_rx_ldpc = %u", ++ htt_stats_buf->ul_ofdma_rx_ldpc); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->rx_ulofdma_non_data_ppdu, ++ HTT_RX_PDEV_MAX_OFDMA_NUM_USER); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_ulofdma_non_data_ppdu = %s ", ++ str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->rx_ulofdma_data_ppdu, ++ HTT_RX_PDEV_MAX_OFDMA_NUM_USER); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_ulofdma_data_ppdu = %s ", ++ str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->rx_ulofdma_mpdu_ok, ++ HTT_RX_PDEV_MAX_OFDMA_NUM_USER); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_ulofdma_mpdu_ok = %s ", str_buf); ++ ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ ARRAY_TO_STRING(str_buf, htt_stats_buf->rx_ulofdma_mpdu_fail, ++ HTT_RX_PDEV_MAX_OFDMA_NUM_USER); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_ulofdma_mpdu_fail = %s", ++ str_buf); ++ ++ for (j = 0; j < HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS; j++) { ++ index = 0; ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ for (i = 0; i < HTT_RX_PDEV_MAX_OFDMA_NUM_USER; i++) ++ index += scnprintf(&str_buf[index], ++ HTT_MAX_STRING_LEN - index, ++ " %u:%d,", ++ i, htt_stats_buf->rx_ul_fd_rssi[j][i]); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "rx_ul_fd_rssi: nss[%u] = %s", j, str_buf); ++ } ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "per_chain_rssi_pkt_type = %#x", ++ htt_stats_buf->per_chain_rssi_pkt_type); ++ ++ for (j = 0; j < HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS; j++) { ++ index = 0; ++ memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ++ for (i = 0; i < HTT_RX_PDEV_STATS_NUM_BW_COUNTERS; i++) ++ index += scnprintf(&str_buf[index], ++ HTT_MAX_STRING_LEN - index, ++ " %u:%d,", ++ i, ++ htt_stats_buf->rx_per_chain_rssi_in_dbm[j][i]); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "rx_per_chain_rssi_in_dbm[%u] = %s ", j, str_buf); ++ } ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "\n"); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++ ++fail: ++ for (j = 0; j < HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS; j++) ++ kfree(rssi_chain[j]); ++ ++ for (j = 0; j < HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS; j++) ++ kfree(rx_pilot_evm_db[j]); ++ ++ for (i = 0; i < HTT_RX_PDEV_STATS_NUM_GI_COUNTERS; i++) ++ kfree(rx_gi[i]); ++} ++ ++static inline void htt_print_rx_soc_fw_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_rx_soc_fw_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_RX_SOC_FW_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fw_reo_ring_data_msdu = %u", ++ htt_stats_buf->fw_reo_ring_data_msdu); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fw_to_host_data_msdu_bcmc = %u", ++ htt_stats_buf->fw_to_host_data_msdu_bcmc); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fw_to_host_data_msdu_uc = %u", ++ htt_stats_buf->fw_to_host_data_msdu_uc); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ofld_remote_data_buf_recycle_cnt = %u", ++ htt_stats_buf->ofld_remote_data_buf_recycle_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ofld_remote_free_buf_indication_cnt = %u", ++ htt_stats_buf->ofld_remote_free_buf_indication_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ofld_buf_to_host_data_msdu_uc = %u", ++ htt_stats_buf->ofld_buf_to_host_data_msdu_uc); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "reo_fw_ring_to_host_data_msdu_uc = %u", ++ htt_stats_buf->reo_fw_ring_to_host_data_msdu_uc); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "wbm_sw_ring_reap = %u", ++ htt_stats_buf->wbm_sw_ring_reap); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "wbm_forward_to_host_cnt = %u", ++ htt_stats_buf->wbm_forward_to_host_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "wbm_target_recycle_cnt = %u", ++ htt_stats_buf->wbm_target_recycle_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "target_refill_ring_recycle_cnt = %u", ++ htt_stats_buf->target_refill_ring_recycle_cnt); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_rx_soc_fw_refill_ring_empty_tlv_v(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_rx_soc_fw_refill_ring_empty_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char refill_ring_empty_cnt[HTT_MAX_STRING_LEN] = {0}; ++ u16 num_elems = min_t(u16, (tag_len >> 2), HTT_RX_STATS_REFILL_MAX_RING); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "HTT_RX_SOC_FW_REFILL_RING_EMPTY_TLV_V:"); ++ ++ ARRAY_TO_STRING(refill_ring_empty_cnt, ++ htt_stats_buf->refill_ring_empty_cnt, ++ num_elems); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "refill_ring_empty_cnt = %s\n", ++ refill_ring_empty_cnt); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_rx_soc_fw_refill_ring_num_rxdma_err_tlv_v(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_rx_soc_fw_refill_ring_num_rxdma_err_tlv_v *htt_stats_buf = ++ tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char rxdma_err_cnt[HTT_MAX_STRING_LEN] = {0}; ++ u16 num_elems = min_t(u16, (tag_len >> 2), HTT_RX_RXDMA_MAX_ERR_CODE); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "HTT_RX_SOC_FW_REFILL_RING_NUM_RXDMA_ERR_TLV_V:"); ++ ++ ARRAY_TO_STRING(rxdma_err_cnt, ++ htt_stats_buf->rxdma_err, ++ num_elems); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rxdma_err = %s\n", ++ rxdma_err_cnt); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_rx_soc_fw_refill_ring_num_reo_err_tlv_v(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_rx_soc_fw_refill_ring_num_reo_err_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char reo_err_cnt[HTT_MAX_STRING_LEN] = {0}; ++ u16 num_elems = min_t(u16, (tag_len >> 2), HTT_RX_REO_MAX_ERR_CODE); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "HTT_RX_SOC_FW_REFILL_RING_NUM_REO_ERR_TLV_V:"); ++ ++ ARRAY_TO_STRING(reo_err_cnt, ++ htt_stats_buf->reo_err, ++ num_elems); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "reo_err = %s\n", ++ reo_err_cnt); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_rx_reo_debug_stats_tlv_v(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_rx_reo_resource_stats_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_RX_REO_RESOURCE_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sample_id = %u", ++ htt_stats_buf->sample_id); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "total_max = %u", ++ htt_stats_buf->total_max); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "total_avg = %u", ++ htt_stats_buf->total_avg); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "total_sample = %u", ++ htt_stats_buf->total_sample); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "non_zeros_avg = %u", ++ htt_stats_buf->non_zeros_avg); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "non_zeros_sample = %u", ++ htt_stats_buf->non_zeros_sample); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "last_non_zeros_max = %u", ++ htt_stats_buf->last_non_zeros_max); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "last_non_zeros_min %u", ++ htt_stats_buf->last_non_zeros_min); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "last_non_zeros_avg %u", ++ htt_stats_buf->last_non_zeros_avg); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "last_non_zeros_sample %u\n", ++ htt_stats_buf->last_non_zeros_sample); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_rx_soc_fw_refill_ring_num_refill_tlv_v(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_rx_soc_fw_refill_ring_num_refill_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char refill_ring_num_refill[HTT_MAX_STRING_LEN] = {0}; ++ u16 num_elems = min_t(u16, (tag_len >> 2), HTT_RX_STATS_REFILL_MAX_RING); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "HTT_RX_SOC_FW_REFILL_RING_NUM_REFILL_TLV_V:"); ++ ++ ARRAY_TO_STRING(refill_ring_num_refill, ++ htt_stats_buf->refill_ring_num_refill, ++ num_elems); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "refill_ring_num_refill = %s\n", ++ refill_ring_num_refill); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void htt_print_rx_pdev_fw_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_rx_pdev_fw_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char fw_ring_mgmt_subtype[HTT_MAX_STRING_LEN] = {0}; ++ char fw_ring_ctrl_subtype[HTT_MAX_STRING_LEN] = {0}; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_RX_PDEV_FW_STATS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mac_id = %u", ++ htt_stats_buf->mac_id__word & 0xFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ppdu_recvd = %u", ++ htt_stats_buf->ppdu_recvd); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mpdu_cnt_fcs_ok = %u", ++ htt_stats_buf->mpdu_cnt_fcs_ok); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mpdu_cnt_fcs_err = %u", ++ htt_stats_buf->mpdu_cnt_fcs_err); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tcp_msdu_cnt = %u", ++ htt_stats_buf->tcp_msdu_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "tcp_ack_msdu_cnt = %u", ++ htt_stats_buf->tcp_ack_msdu_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "udp_msdu_cnt = %u", ++ htt_stats_buf->udp_msdu_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "other_msdu_cnt = %u", ++ htt_stats_buf->other_msdu_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fw_ring_mpdu_ind = %u", ++ htt_stats_buf->fw_ring_mpdu_ind); ++ ++ ARRAY_TO_STRING(fw_ring_mgmt_subtype, ++ htt_stats_buf->fw_ring_mgmt_subtype, ++ HTT_STATS_SUBTYPE_MAX); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fw_ring_mgmt_subtype = %s ", ++ fw_ring_mgmt_subtype); ++ ++ ARRAY_TO_STRING(fw_ring_ctrl_subtype, ++ htt_stats_buf->fw_ring_ctrl_subtype, ++ HTT_STATS_SUBTYPE_MAX); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fw_ring_ctrl_subtype = %s ", ++ fw_ring_ctrl_subtype); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fw_ring_mcast_data_msdu = %u", ++ htt_stats_buf->fw_ring_mcast_data_msdu); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fw_ring_bcast_data_msdu = %u", ++ htt_stats_buf->fw_ring_bcast_data_msdu); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fw_ring_ucast_data_msdu = %u", ++ htt_stats_buf->fw_ring_ucast_data_msdu); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fw_ring_null_data_msdu = %u", ++ htt_stats_buf->fw_ring_null_data_msdu); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fw_ring_mpdu_drop = %u", ++ htt_stats_buf->fw_ring_mpdu_drop); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "ofld_local_data_ind_cnt = %u", ++ htt_stats_buf->ofld_local_data_ind_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "ofld_local_data_buf_recycle_cnt = %u", ++ htt_stats_buf->ofld_local_data_buf_recycle_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "drx_local_data_ind_cnt = %u", ++ htt_stats_buf->drx_local_data_ind_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "drx_local_data_buf_recycle_cnt = %u", ++ htt_stats_buf->drx_local_data_buf_recycle_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "local_nondata_ind_cnt = %u", ++ htt_stats_buf->local_nondata_ind_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "local_nondata_buf_recycle_cnt = %u", ++ htt_stats_buf->local_nondata_buf_recycle_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fw_status_buf_ring_refill_cnt = %u", ++ htt_stats_buf->fw_status_buf_ring_refill_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fw_status_buf_ring_empty_cnt = %u", ++ htt_stats_buf->fw_status_buf_ring_empty_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fw_pkt_buf_ring_refill_cnt = %u", ++ htt_stats_buf->fw_pkt_buf_ring_refill_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fw_pkt_buf_ring_empty_cnt = %u", ++ htt_stats_buf->fw_pkt_buf_ring_empty_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fw_link_buf_ring_refill_cnt = %u", ++ htt_stats_buf->fw_link_buf_ring_refill_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fw_link_buf_ring_empty_cnt = %u", ++ htt_stats_buf->fw_link_buf_ring_empty_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "host_pkt_buf_ring_refill_cnt = %u", ++ htt_stats_buf->host_pkt_buf_ring_refill_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "host_pkt_buf_ring_empty_cnt = %u", ++ htt_stats_buf->host_pkt_buf_ring_empty_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mon_pkt_buf_ring_refill_cnt = %u", ++ htt_stats_buf->mon_pkt_buf_ring_refill_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mon_pkt_buf_ring_empty_cnt = %u", ++ htt_stats_buf->mon_pkt_buf_ring_empty_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "mon_status_buf_ring_refill_cnt = %u", ++ htt_stats_buf->mon_status_buf_ring_refill_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mon_status_buf_ring_empty_cnt = %u", ++ htt_stats_buf->mon_status_buf_ring_empty_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mon_desc_buf_ring_refill_cnt = %u", ++ htt_stats_buf->mon_desc_buf_ring_refill_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mon_desc_buf_ring_empty_cnt = %u", ++ htt_stats_buf->mon_desc_buf_ring_empty_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mon_dest_ring_update_cnt = %u", ++ htt_stats_buf->mon_dest_ring_update_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mon_dest_ring_full_cnt = %u", ++ htt_stats_buf->mon_dest_ring_full_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_suspend_cnt = %u", ++ htt_stats_buf->rx_suspend_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_suspend_fail_cnt = %u", ++ htt_stats_buf->rx_suspend_fail_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_resume_cnt = %u", ++ htt_stats_buf->rx_resume_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_resume_fail_cnt = %u", ++ htt_stats_buf->rx_resume_fail_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_ring_switch_cnt = %u", ++ htt_stats_buf->rx_ring_switch_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_ring_restore_cnt = %u", ++ htt_stats_buf->rx_ring_restore_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_flush_cnt = %u", ++ htt_stats_buf->rx_flush_cnt); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_recovery_reset_cnt = %u\n", ++ htt_stats_buf->rx_recovery_reset_cnt); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_rx_pdev_fw_ring_mpdu_err_tlv_v(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_rx_pdev_fw_ring_mpdu_err_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char fw_ring_mpdu_err[HTT_MAX_STRING_LEN] = {0}; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "HTT_RX_PDEV_FW_RING_MPDU_ERR_TLV_V:"); ++ ++ ARRAY_TO_STRING(fw_ring_mpdu_err, ++ htt_stats_buf->fw_ring_mpdu_err, ++ HTT_RX_STATS_RXDMA_MAX_ERR); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fw_ring_mpdu_err = %s\n", ++ fw_ring_mpdu_err); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_rx_pdev_fw_mpdu_drop_tlv_v(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_rx_pdev_fw_mpdu_drop_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char fw_mpdu_drop[HTT_MAX_STRING_LEN] = {0}; ++ u16 num_elems = min_t(u16, (tag_len >> 2), HTT_RX_STATS_FW_DROP_REASON_MAX); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_RX_PDEV_FW_MPDU_DROP_TLV_V:"); ++ ++ ARRAY_TO_STRING(fw_mpdu_drop, ++ htt_stats_buf->fw_mpdu_drop, ++ num_elems); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "fw_mpdu_drop = %s\n", fw_mpdu_drop); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_rx_pdev_fw_stats_phy_err_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_rx_pdev_fw_stats_phy_err_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char phy_errs[HTT_MAX_STRING_LEN] = {0}; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_RX_PDEV_FW_STATS_PHY_ERR_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mac_id__word = %u", ++ htt_stats_buf->mac_id__word); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "total_phy_err_nct = %u", ++ htt_stats_buf->total_phy_err_cnt); ++ ++ ARRAY_TO_STRING(phy_errs, ++ htt_stats_buf->phy_err, ++ HTT_STATS_PHY_ERR_MAX); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "phy_errs = %s\n", phy_errs); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_pdev_cca_stats_hist_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_pdev_cca_stats_hist_v1_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "\nHTT_PDEV_CCA_STATS_HIST_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "chan_num = %u", ++ htt_stats_buf->chan_num); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_records = %u", ++ htt_stats_buf->num_records); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "valid_cca_counters_bitmap = 0x%x", ++ htt_stats_buf->valid_cca_counters_bitmap); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "collection_interval = %u\n", ++ htt_stats_buf->collection_interval); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "HTT_PDEV_STATS_CCA_COUNTERS_TLV:(in usec)"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "| tx_frame| rx_frame| rx_clear| my_rx_frame| cnt| med_rx_idle| med_tx_idle_global| cca_obss|"); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_pdev_stats_cca_counters_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_pdev_stats_cca_counters_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "|%10u| %10u| %10u| %11u| %10u| %11u| %18u| %10u|", ++ htt_stats_buf->tx_frame_usec, ++ htt_stats_buf->rx_frame_usec, ++ htt_stats_buf->rx_clear_usec, ++ htt_stats_buf->my_rx_frame_usec, ++ htt_stats_buf->usec_cnt, ++ htt_stats_buf->med_rx_idle_usec, ++ htt_stats_buf->med_tx_idle_global_usec, ++ htt_stats_buf->cca_obss_usec); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void htt_print_hw_stats_whal_tx_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_hw_stats_whal_tx_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_HW_STATS_WHAL_TX_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "mac_id = %u", ++ htt_stats_buf->mac_id__word & 0xFF); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "last_unpause_ppdu_id = %u", ++ htt_stats_buf->last_unpause_ppdu_id); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "hwsch_unpause_wait_tqm_write = %u", ++ htt_stats_buf->hwsch_unpause_wait_tqm_write); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "hwsch_dummy_tlv_skipped = %u", ++ htt_stats_buf->hwsch_dummy_tlv_skipped); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "hwsch_misaligned_offset_received = %u", ++ htt_stats_buf->hwsch_misaligned_offset_received); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "hwsch_reset_count = %u", ++ htt_stats_buf->hwsch_reset_count); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "hwsch_dev_reset_war = %u", ++ htt_stats_buf->hwsch_dev_reset_war); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "hwsch_delayed_pause = %u", ++ htt_stats_buf->hwsch_delayed_pause); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "hwsch_long_delayed_pause = %u", ++ htt_stats_buf->hwsch_long_delayed_pause); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sch_rx_ppdu_no_response = %u", ++ htt_stats_buf->sch_rx_ppdu_no_response); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sch_selfgen_response = %u", ++ htt_stats_buf->sch_selfgen_response); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sch_rx_sifs_resp_trigger= %u\n", ++ htt_stats_buf->sch_rx_sifs_resp_trigger); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_pdev_stats_twt_sessions_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_pdev_stats_twt_sessions_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_PDEV_STATS_TWT_SESSIONS_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "pdev_id = %u", ++ htt_stats_buf->pdev_id); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_sessions = %u\n", ++ htt_stats_buf->num_sessions); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_pdev_stats_twt_session_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_pdev_stats_twt_session_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_PDEV_STATS_TWT_SESSION_TLV:"); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "vdev_id = %u", ++ htt_stats_buf->vdev_id); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "peer_mac = %02x:%02x:%02x:%02x:%02x:%02x", ++ htt_stats_buf->peer_mac.mac_addr_l32 & 0xFF, ++ (htt_stats_buf->peer_mac.mac_addr_l32 & 0xFF00) >> 8, ++ (htt_stats_buf->peer_mac.mac_addr_l32 & 0xFF0000) >> 16, ++ (htt_stats_buf->peer_mac.mac_addr_l32 & 0xFF000000) >> 24, ++ (htt_stats_buf->peer_mac.mac_addr_h16 & 0xFF), ++ (htt_stats_buf->peer_mac.mac_addr_h16 & 0xFF00) >> 8); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "flow_id_flags = %u", ++ htt_stats_buf->flow_id_flags); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "dialog_id = %u", ++ htt_stats_buf->dialog_id); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "wake_dura_us = %u", ++ htt_stats_buf->wake_dura_us); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "wake_intvl_us = %u", ++ htt_stats_buf->wake_intvl_us); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "sp_offset_us = %u\n", ++ htt_stats_buf->sp_offset_us); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_pdev_obss_pd_stats_tlv_v(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_pdev_obss_pd_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "OBSS Tx success PPDU = %u", ++ htt_stats_buf->num_obss_tx_ppdu_success); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "OBSS Tx failures PPDU = %u\n", ++ htt_stats_buf->num_obss_tx_ppdu_failure); ++ ++ if (len >= buf_len) ++ buf[buf_len - 1] = 0; ++ else ++ buf[len] = 0; ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void htt_print_backpressure_stats_tlv_v(const u32 *tag_buf, ++ u8 *data) ++{ ++ struct debug_htt_stats_req *stats_req = ++ (struct debug_htt_stats_req *)data; ++ struct htt_ring_backpressure_stats_tlv *htt_stats_buf = ++ (struct htt_ring_backpressure_stats_tlv *)tag_buf; ++ int i; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "pdev_id = %u", ++ htt_stats_buf->pdev_id); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "current_head_idx = %u", ++ htt_stats_buf->current_head_idx); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "current_tail_idx = %u", ++ htt_stats_buf->current_tail_idx); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "num_htt_msgs_sent = %u", ++ htt_stats_buf->num_htt_msgs_sent); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "backpressure_time_ms = %u", ++ htt_stats_buf->backpressure_time_ms); ++ ++ for (i = 0; i < 5; i++) ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "backpressure_hist_%u = %u", ++ i + 1, htt_stats_buf->backpressure_hist[i]); ++ ++ len += HTT_DBG_OUT(buf + len, buf_len - len, ++ "============================"); ++ ++ if (len >= buf_len) { ++ buf[buf_len - 1] = 0; ++ stats_req->buf_len = buf_len - 1; ++ } else { ++ buf[len] = 0; ++ stats_req->buf_len = len; ++ } ++} ++ ++static int ath12k_dbg_htt_ext_stats_parse(struct ath12k_base *ab, ++ u16 tag, u16 len, const void *tag_buf, ++ void *user_data) ++{ ++ struct debug_htt_stats_req *stats_req = user_data; ++ ++ switch (tag) { ++ case HTT_STATS_TX_PDEV_CMN_TAG: ++ htt_print_tx_pdev_stats_cmn_tlv(tag_buf, stats_req); ++ break; ++ case HTT_STATS_TX_PDEV_UNDERRUN_TAG: ++ htt_print_tx_pdev_stats_urrn_tlv_v(tag_buf, len, stats_req); ++ break; ++ case HTT_STATS_TX_PDEV_SIFS_TAG: ++ htt_print_tx_pdev_stats_sifs_tlv_v(tag_buf, len, stats_req); ++ break; ++ case HTT_STATS_TX_PDEV_FLUSH_TAG: ++ htt_print_tx_pdev_stats_flush_tlv_v(tag_buf, len, stats_req); ++ break; ++ case HTT_STATS_TX_PDEV_PHY_ERR_TAG: ++ htt_print_tx_pdev_stats_phy_err_tlv_v(tag_buf, len, stats_req); ++ break; ++ case HTT_STATS_TX_PDEV_SIFS_HIST_TAG: ++ htt_print_tx_pdev_stats_sifs_hist_tlv_v(tag_buf, len, stats_req); ++ break; ++ ++ case HTT_STATS_TX_PDEV_TX_PPDU_STATS_TAG: ++ htt_print_tx_pdev_stats_tx_ppdu_stats_tlv_v(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_TX_PDEV_TRIED_MPDU_CNT_HIST_TAG: ++ htt_print_tx_pdev_stats_tried_mpdu_cnt_hist_tlv_v(tag_buf, len, ++ stats_req); ++ break; ++ ++ case HTT_STATS_STRING_TAG: ++ htt_print_stats_string_tlv(tag_buf, len, stats_req); ++ break; ++ ++ case HTT_STATS_TX_HWQ_CMN_TAG: ++ htt_print_tx_hwq_stats_cmn_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_TX_HWQ_DIFS_LATENCY_TAG: ++ htt_print_tx_hwq_difs_latency_stats_tlv_v(tag_buf, len, stats_req); ++ break; ++ ++ case HTT_STATS_TX_HWQ_CMD_RESULT_TAG: ++ htt_print_tx_hwq_cmd_result_stats_tlv_v(tag_buf, len, stats_req); ++ break; ++ ++ case HTT_STATS_TX_HWQ_CMD_STALL_TAG: ++ htt_print_tx_hwq_cmd_stall_stats_tlv_v(tag_buf, len, stats_req); ++ break; ++ ++ case HTT_STATS_TX_HWQ_FES_STATUS_TAG: ++ htt_print_tx_hwq_fes_result_stats_tlv_v(tag_buf, len, stats_req); ++ break; ++ ++ case HTT_STATS_TX_HWQ_TRIED_MPDU_CNT_HIST_TAG: ++ htt_print_tx_hwq_tried_mpdu_cnt_hist_tlv_v(tag_buf, len, stats_req); ++ break; ++ ++ case HTT_STATS_TX_HWQ_TXOP_USED_CNT_HIST_TAG: ++ htt_print_tx_hwq_txop_used_cnt_hist_tlv_v(tag_buf, len, stats_req); ++ break; ++ case HTT_STATS_TX_TQM_GEN_MPDU_TAG: ++ htt_print_tx_tqm_gen_mpdu_stats_tlv_v(tag_buf, len, stats_req); ++ break; ++ ++ case HTT_STATS_TX_TQM_LIST_MPDU_TAG: ++ htt_print_tx_tqm_list_mpdu_stats_tlv_v(tag_buf, len, stats_req); ++ break; ++ ++ case HTT_STATS_TX_TQM_LIST_MPDU_CNT_TAG: ++ htt_print_tx_tqm_list_mpdu_cnt_tlv_v(tag_buf, len, stats_req); ++ break; ++ ++ case HTT_STATS_TX_TQM_CMN_TAG: ++ htt_print_tx_tqm_cmn_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_TX_TQM_PDEV_TAG: ++ htt_print_tx_tqm_pdev_stats_tlv_v(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_TX_TQM_CMDQ_STATUS_TAG: ++ htt_print_tx_tqm_cmdq_status_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_TX_DE_EAPOL_PACKETS_TAG: ++ htt_print_tx_de_eapol_packets_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_TX_DE_CLASSIFY_FAILED_TAG: ++ htt_print_tx_de_classify_failed_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_TX_DE_CLASSIFY_STATS_TAG: ++ htt_print_tx_de_classify_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_TX_DE_CLASSIFY_STATUS_TAG: ++ htt_print_tx_de_classify_status_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_TX_DE_ENQUEUE_PACKETS_TAG: ++ htt_print_tx_de_enqueue_packets_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_TX_DE_ENQUEUE_DISCARD_TAG: ++ htt_print_tx_de_enqueue_discard_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_TX_DE_FW2WBM_RING_FULL_HIST_TAG: ++ htt_print_tx_de_fw2wbm_ring_full_hist_tlv(tag_buf, len, stats_req); ++ break; ++ ++ case HTT_STATS_TX_DE_CMN_TAG: ++ htt_print_tx_de_cmn_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_RING_IF_TAG: ++ htt_print_ring_if_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_TX_PDEV_MU_MIMO_STATS_TAG: ++ htt_print_tx_pdev_mu_mimo_sch_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_SFM_CMN_TAG: ++ htt_print_sfm_cmn_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_SRING_STATS_TAG: ++ htt_print_sring_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_RX_PDEV_FW_STATS_TAG: ++ htt_print_rx_pdev_fw_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_RX_PDEV_FW_RING_MPDU_ERR_TAG: ++ htt_print_rx_pdev_fw_ring_mpdu_err_tlv_v(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_RX_PDEV_FW_MPDU_DROP_TAG: ++ htt_print_rx_pdev_fw_mpdu_drop_tlv_v(tag_buf, len, stats_req); ++ break; ++ ++ case HTT_STATS_RX_SOC_FW_STATS_TAG: ++ htt_print_rx_soc_fw_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_RX_SOC_FW_REFILL_RING_EMPTY_TAG: ++ htt_print_rx_soc_fw_refill_ring_empty_tlv_v(tag_buf, len, stats_req); ++ break; ++ ++ case HTT_STATS_RX_SOC_FW_REFILL_RING_NUM_REFILL_TAG: ++ htt_print_rx_soc_fw_refill_ring_num_refill_tlv_v( ++ tag_buf, len, stats_req); ++ break; ++ case HTT_STATS_RX_REFILL_RXDMA_ERR_TAG: ++ htt_print_rx_soc_fw_refill_ring_num_rxdma_err_tlv_v( ++ tag_buf, len, stats_req); ++ break; ++ ++ case HTT_STATS_RX_REFILL_REO_ERR_TAG: ++ htt_print_rx_soc_fw_refill_ring_num_reo_err_tlv_v( ++ tag_buf, len, stats_req); ++ break; ++ ++ case HTT_STATS_RX_REO_RESOURCE_STATS_TAG: ++ htt_print_rx_reo_debug_stats_tlv_v( ++ tag_buf, stats_req); ++ break; ++ case HTT_STATS_RX_PDEV_FW_STATS_PHY_ERR_TAG: ++ htt_print_rx_pdev_fw_stats_phy_err_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_TX_PDEV_RATE_STATS_TAG: ++ htt_print_tx_pdev_rate_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_RX_PDEV_RATE_STATS_TAG: ++ htt_print_rx_pdev_rate_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_TX_PDEV_SCHEDULER_TXQ_STATS_TAG: ++ htt_print_tx_pdev_stats_sched_per_txq_tlv(tag_buf, stats_req); ++ break; ++ case HTT_STATS_TX_SCHED_CMN_TAG: ++ htt_print_stats_tx_sched_cmn_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_TX_PDEV_MPDU_STATS_TAG: ++ htt_print_tx_pdev_mu_mimo_mpdu_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_SCHED_TXQ_CMD_POSTED_TAG: ++ htt_print_sched_txq_cmd_posted_tlv_v(tag_buf, len, stats_req); ++ break; ++ ++ case HTT_STATS_RING_IF_CMN_TAG: ++ htt_print_ring_if_cmn_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_SFM_CLIENT_USER_TAG: ++ htt_print_sfm_client_user_tlv_v(tag_buf, len, stats_req); ++ break; ++ ++ case HTT_STATS_SFM_CLIENT_TAG: ++ htt_print_sfm_client_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_TX_TQM_ERROR_STATS_TAG: ++ htt_print_tx_tqm_error_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_SCHED_TXQ_CMD_REAPED_TAG: ++ htt_print_sched_txq_cmd_reaped_tlv_v(tag_buf, len, stats_req); ++ break; ++ ++ case HTT_STATS_SRING_CMN_TAG: ++ htt_print_sring_cmn_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_TX_SOUNDING_STATS_TAG: ++ htt_print_tx_sounding_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_TX_SELFGEN_AC_ERR_STATS_TAG: ++ htt_print_tx_selfgen_ac_err_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_TX_SELFGEN_CMN_STATS_TAG: ++ htt_print_tx_selfgen_cmn_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_TX_SELFGEN_AC_STATS_TAG: ++ htt_print_tx_selfgen_ac_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_TX_SELFGEN_AX_STATS_TAG: ++ htt_print_tx_selfgen_ax_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_TX_SELFGEN_AX_ERR_STATS_TAG: ++ htt_print_tx_selfgen_ax_err_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_TX_HWQ_MUMIMO_SCH_STATS_TAG: ++ htt_print_tx_hwq_mu_mimo_sch_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_TX_HWQ_MUMIMO_MPDU_STATS_TAG: ++ htt_print_tx_hwq_mu_mimo_mpdu_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_TX_HWQ_MUMIMO_CMN_STATS_TAG: ++ htt_print_tx_hwq_mu_mimo_cmn_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_HW_INTR_MISC_TAG: ++ htt_print_hw_stats_intr_misc_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_HW_WD_TIMEOUT_TAG: ++ htt_print_hw_stats_wd_timeout_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_HW_PDEV_ERRS_TAG: ++ htt_print_hw_stats_pdev_errs_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_COUNTER_NAME_TAG: ++ htt_print_counter_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_TX_TID_DETAILS_TAG: ++ htt_print_tx_tid_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_TX_TID_DETAILS_V1_TAG: ++ htt_print_tx_tid_stats_v1_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_RX_TID_DETAILS_TAG: ++ htt_print_rx_tid_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_PEER_STATS_CMN_TAG: ++ htt_print_peer_stats_cmn_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_PEER_DETAILS_TAG: ++ htt_print_peer_details_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_PEER_MSDU_FLOWQ_TAG: ++ htt_print_msdu_flow_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_PEER_TX_RATE_STATS_TAG: ++ htt_print_tx_peer_rate_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_PEER_RX_RATE_STATS_TAG: ++ htt_print_rx_peer_rate_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_TX_DE_COMPL_STATS_TAG: ++ htt_print_tx_de_compl_stats_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_PDEV_CCA_1SEC_HIST_TAG: ++ case HTT_STATS_PDEV_CCA_100MSEC_HIST_TAG: ++ case HTT_STATS_PDEV_CCA_STAT_CUMULATIVE_TAG: ++ htt_print_pdev_cca_stats_hist_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_PDEV_CCA_COUNTERS_TAG: ++ htt_print_pdev_stats_cca_counters_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_WHAL_TX_TAG: ++ htt_print_hw_stats_whal_tx_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_PDEV_TWT_SESSIONS_TAG: ++ htt_print_pdev_stats_twt_sessions_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_PDEV_TWT_SESSION_TAG: ++ htt_print_pdev_stats_twt_session_tlv(tag_buf, stats_req); ++ break; ++ ++ case HTT_STATS_SCHED_TXQ_SCHED_ORDER_SU_TAG: ++ htt_print_sched_txq_sched_order_su_tlv_v(tag_buf, len, stats_req); ++ break; ++ ++ case HTT_STATS_SCHED_TXQ_SCHED_INELIGIBILITY_TAG: ++ htt_print_sched_txq_sched_ineligibility_tlv_v(tag_buf, len, stats_req); ++ break; ++ ++ case HTT_STATS_PDEV_OBSS_PD_TAG: ++ htt_print_pdev_obss_pd_stats_tlv_v(tag_buf, stats_req); ++ break; ++ case HTT_STATS_RING_BACKPRESSURE_STATS_TAG: ++ htt_print_backpressure_stats_tlv_v(tag_buf, user_data); ++ break; ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++void ath12k_debugfs_htt_ext_stats_handler(struct ath12k_base *ab, ++ struct sk_buff *skb) ++{ ++ struct ath12k_htt_extd_stats_msg *msg; ++ struct debug_htt_stats_req *stats_req; ++ struct ath12k *ar; ++ u32 len; ++ u64 cookie; ++ int ret; ++ bool send_completion = false; ++ u8 pdev_id; ++ ++ msg = (struct ath12k_htt_extd_stats_msg *)skb->data; ++ cookie = msg->cookie; ++ ++ if (FIELD_GET(HTT_STATS_COOKIE_MSB, cookie) != HTT_STATS_MAGIC_VALUE) { ++ ath12k_warn(ab, "received invalid htt ext stats event\n"); ++ return; ++ } ++ ++ pdev_id = FIELD_GET(HTT_STATS_COOKIE_LSB, cookie); ++ rcu_read_lock(); ++ ar = ath12k_mac_get_ar_by_pdev_id(ab, pdev_id); ++ rcu_read_unlock(); ++ if (!ar) { ++ ath12k_warn(ab, "failed to get ar for pdev_id %d\n", pdev_id); ++ return; ++ } ++ ++ stats_req = ar->debug.htt_stats.stats_req; ++ if (!stats_req) ++ return; ++ ++ spin_lock_bh(&ar->debug.htt_stats.lock); ++ ++ stats_req->done = FIELD_GET(HTT_T2H_EXT_STATS_INFO1_DONE, msg->info1); ++ if (stats_req->done) ++ send_completion = true; ++ ++ spin_unlock_bh(&ar->debug.htt_stats.lock); ++ ++ len = FIELD_GET(HTT_T2H_EXT_STATS_INFO1_LENGTH, msg->info1); ++ ret = ath12k_dp_htt_tlv_iter(ab, msg->data, len, ++ ath12k_dbg_htt_ext_stats_parse, ++ stats_req); ++ if (ret) ++ ath12k_warn(ab, "Failed to parse tlv %d\n", ret); ++ ++ if (send_completion) ++ complete(&stats_req->cmpln); ++} ++ ++static ssize_t ath12k_read_htt_stats_type(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ char buf[32]; ++ size_t len; ++ ++ len = scnprintf(buf, sizeof(buf), "%u\n", ar->debug.htt_stats.type); ++ ++ return simple_read_from_buffer(user_buf, count, ppos, buf, len); ++} ++ ++static ssize_t ath12k_write_htt_stats_type(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ u8 type; ++ int ret; ++ ++ ret = kstrtou8_from_user(user_buf, count, 0, &type); ++ if (ret) ++ return ret; ++ ++ if (type >= ATH12K_DBG_HTT_NUM_EXT_STATS) ++ return -E2BIG; ++ ++ if (type == ATH12K_DBG_HTT_EXT_STATS_RESET || ++ type == ATH12K_DBG_HTT_EXT_STATS_PEER_INFO) ++ return -EPERM; ++ ++ ar->debug.htt_stats.type = type; ++ ++ ret = count; ++ ++ return ret; ++} ++ ++static const struct file_operations fops_htt_stats_type = { ++ .read = ath12k_read_htt_stats_type, ++ .write = ath12k_write_htt_stats_type, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++static int ath12k_prep_htt_stats_cfg_params(struct ath12k *ar, u8 type, ++ const u8 *mac_addr, ++ struct htt_ext_stats_cfg_params *cfg_params) ++{ ++ if (!cfg_params) ++ return -EINVAL; ++ ++ switch (type) { ++ case ATH12K_DBG_HTT_EXT_STATS_PDEV_TX_HWQ: ++ case ATH12K_DBG_HTT_EXT_STATS_TX_MU_HWQ: ++ cfg_params->cfg0 = HTT_STAT_DEFAULT_CFG0_ALL_HWQS; ++ break; ++ case ATH12K_DBG_HTT_EXT_STATS_PDEV_TX_SCHED: ++ cfg_params->cfg0 = HTT_STAT_DEFAULT_CFG0_ALL_TXQS; ++ break; ++ case ATH12K_DBG_HTT_EXT_STATS_TQM_CMDQ: ++ cfg_params->cfg0 = HTT_STAT_DEFAULT_CFG0_ALL_CMDQS; ++ break; ++ case ATH12K_DBG_HTT_EXT_STATS_PEER_INFO: ++ cfg_params->cfg0 = HTT_STAT_PEER_INFO_MAC_ADDR; ++ cfg_params->cfg0 |= FIELD_PREP(GENMASK(15, 1), ++ HTT_PEER_STATS_REQ_MODE_FLUSH_TQM); ++ cfg_params->cfg1 = HTT_STAT_DEFAULT_PEER_REQ_TYPE; ++ cfg_params->cfg2 |= FIELD_PREP(GENMASK(7, 0), mac_addr[0]); ++ cfg_params->cfg2 |= FIELD_PREP(GENMASK(15, 8), mac_addr[1]); ++ cfg_params->cfg2 |= FIELD_PREP(GENMASK(23, 16), mac_addr[2]); ++ cfg_params->cfg2 |= FIELD_PREP(GENMASK(31, 24), mac_addr[3]); ++ cfg_params->cfg3 |= FIELD_PREP(GENMASK(7, 0), mac_addr[4]); ++ cfg_params->cfg3 |= FIELD_PREP(GENMASK(15, 8), mac_addr[5]); ++ break; ++ case ATH12K_DBG_HTT_EXT_STATS_RING_IF_INFO: ++ case ATH12K_DBG_HTT_EXT_STATS_SRNG_INFO: ++ cfg_params->cfg0 = HTT_STAT_DEFAULT_CFG0_ALL_RINGS; ++ break; ++ case ATH12K_DBG_HTT_EXT_STATS_ACTIVE_PEERS_LIST: ++ cfg_params->cfg0 = HTT_STAT_DEFAULT_CFG0_ACTIVE_PEERS; ++ break; ++ case ATH12K_DBG_HTT_EXT_STATS_PDEV_CCA_STATS: ++ cfg_params->cfg0 = HTT_STAT_DEFAULT_CFG0_CCA_CUMULATIVE; ++ break; ++ case ATH12K_DBG_HTT_EXT_STATS_TX_SOUNDING_INFO: ++ cfg_params->cfg0 = HTT_STAT_DEFAULT_CFG0_ACTIVE_VDEVS; ++ break; ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++int ath12k_debugfs_htt_stats_req(struct ath12k *ar) ++{ ++ struct debug_htt_stats_req *stats_req = ar->debug.htt_stats.stats_req; ++ u8 type = stats_req->type; ++ u64 cookie = 0; ++ int ret, pdev_id = ar->pdev->pdev_id; ++ struct htt_ext_stats_cfg_params cfg_params = { 0 }; ++ ++ init_completion(&stats_req->cmpln); ++ ++ stats_req->done = false; ++ stats_req->pdev_id = pdev_id; ++ ++ cookie = FIELD_PREP(HTT_STATS_COOKIE_MSB, HTT_STATS_MAGIC_VALUE) | ++ FIELD_PREP(HTT_STATS_COOKIE_LSB, pdev_id); ++ ++ ret = ath12k_prep_htt_stats_cfg_params(ar, type, stats_req->peer_addr, ++ &cfg_params); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to set htt stats cfg params: %d\n", ret); ++ return ret; ++ } ++ ++ ret = ath12k_dp_tx_htt_h2t_ext_stats_req(ar, type, &cfg_params, cookie); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to send htt stats request: %d\n", ret); ++ return ret; ++ } ++ ++ while (!wait_for_completion_timeout(&stats_req->cmpln, 3 * HZ)) { ++ spin_lock_bh(&ar->debug.htt_stats.lock); ++ if (!stats_req->done) { ++ stats_req->done = true; ++ spin_unlock_bh(&ar->debug.htt_stats.lock); ++ ath12k_warn(ar->ab, "stats request timed out\n"); ++ return -ETIMEDOUT; ++ } ++ spin_unlock_bh(&ar->debug.htt_stats.lock); ++ } ++ ++ return 0; ++} ++ ++static int ath12k_open_htt_stats(struct inode *inode, struct file *file) ++{ ++ struct ath12k *ar = inode->i_private; ++ struct debug_htt_stats_req *stats_req; ++ u8 type = ar->debug.htt_stats.type; ++ int ret; ++ ++ if (type == ATH12K_DBG_HTT_EXT_STATS_RESET) ++ return -EPERM; ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ if (ar->state != ATH12K_STATE_ON) { ++ ret = -ENETDOWN; ++ goto err_unlock; ++ } ++ ++ if (ar->debug.htt_stats.stats_req) { ++ ret = -EAGAIN; ++ goto err_unlock; ++ } ++ ++ stats_req = vzalloc(sizeof(*stats_req) + ATH12K_HTT_STATS_BUF_SIZE); ++ if (!stats_req) { ++ ret = -ENOMEM; ++ goto err_unlock; ++ } ++ ++ ar->debug.htt_stats.stats_req = stats_req; ++ stats_req->type = type; ++ ++ ret = ath12k_debugfs_htt_stats_req(ar); ++ if (ret < 0) ++ goto out; ++ ++ file->private_data = stats_req; ++ ++ mutex_unlock(&ar->conf_mutex); ++ ++ return 0; ++out: ++ vfree(stats_req); ++ ar->debug.htt_stats.stats_req = NULL; ++err_unlock: ++ mutex_unlock(&ar->conf_mutex); ++ ++ return ret; ++} ++ ++static int ath12k_release_htt_stats(struct inode *inode, struct file *file) ++{ ++ struct ath12k *ar = inode->i_private; ++ ++ mutex_lock(&ar->conf_mutex); ++ vfree(file->private_data); ++ ar->debug.htt_stats.stats_req = NULL; ++ mutex_unlock(&ar->conf_mutex); ++ ++ return 0; ++} ++ ++static ssize_t ath12k_read_htt_stats(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct debug_htt_stats_req *stats_req = file->private_data; ++ char *buf; ++ u32 length = 0; ++ ++ buf = stats_req->buf; ++ length = min_t(u32, stats_req->buf_len, ATH12K_HTT_STATS_BUF_SIZE); ++ return simple_read_from_buffer(user_buf, count, ppos, buf, length); ++} ++ ++static const struct file_operations fops_dump_htt_stats = { ++ .open = ath12k_open_htt_stats, ++ .release = ath12k_release_htt_stats, ++ .read = ath12k_read_htt_stats, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++static ssize_t ath12k_read_htt_stats_reset(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ char buf[32]; ++ size_t len; ++ ++ len = scnprintf(buf, sizeof(buf), "%u\n", ar->debug.htt_stats.reset); ++ ++ return simple_read_from_buffer(user_buf, count, ppos, buf, len); ++} ++ ++static ssize_t ath12k_write_htt_stats_reset(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ u8 type; ++ struct htt_ext_stats_cfg_params cfg_params = { 0 }; ++ int ret; ++ ++ ret = kstrtou8_from_user(user_buf, count, 0, &type); ++ if (ret) ++ return ret; ++ ++ if (type >= ATH12K_DBG_HTT_NUM_EXT_STATS || ++ type == ATH12K_DBG_HTT_EXT_STATS_RESET) ++ return -E2BIG; ++ ++ mutex_lock(&ar->conf_mutex); ++ cfg_params.cfg0 = HTT_STAT_DEFAULT_RESET_START_OFFSET; ++ cfg_params.cfg1 = 1 << (cfg_params.cfg0 + type); ++ ret = ath12k_dp_tx_htt_h2t_ext_stats_req(ar, ++ ATH12K_DBG_HTT_EXT_STATS_RESET, ++ &cfg_params, ++ 0ULL); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to send htt stats request: %d\n", ret); ++ mutex_unlock(&ar->conf_mutex); ++ return ret; ++ } ++ ++ ar->debug.htt_stats.reset = type; ++ mutex_unlock(&ar->conf_mutex); ++ ++ ret = count; ++ ++ return ret; ++} ++ ++static const struct file_operations fops_htt_stats_reset = { ++ .read = ath12k_read_htt_stats_reset, ++ .write = ath12k_write_htt_stats_reset, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++void ath12k_debugfs_htt_stats_init(struct ath12k *ar) ++{ ++ spin_lock_init(&ar->debug.htt_stats.lock); ++ debugfs_create_file("htt_stats_type", 0600, ar->debug.debugfs_pdev, ++ ar, &fops_htt_stats_type); ++ debugfs_create_file("htt_stats", 0400, ar->debug.debugfs_pdev, ++ ar, &fops_dump_htt_stats); ++ debugfs_create_file("htt_stats_reset", 0600, ar->debug.debugfs_pdev, ++ ar, &fops_htt_stats_reset); ++} +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h +@@ -0,0 +1,1714 @@ ++/* SPDX-License-Identifier: BSD-3-Clause-Clear */ ++/* ++ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef DEBUG_HTT_STATS_H ++#define DEBUG_HTT_STATS_H ++ ++#define HTT_STATS_COOKIE_LSB GENMASK_ULL(31, 0) ++#define HTT_STATS_COOKIE_MSB GENMASK_ULL(63, 32) ++#define HTT_STATS_MAGIC_VALUE 0xF0F0F0F0 ++ ++enum htt_tlv_tag_t { ++ HTT_STATS_TX_PDEV_CMN_TAG = 0, ++ HTT_STATS_TX_PDEV_UNDERRUN_TAG = 1, ++ HTT_STATS_TX_PDEV_SIFS_TAG = 2, ++ HTT_STATS_TX_PDEV_FLUSH_TAG = 3, ++ HTT_STATS_TX_PDEV_PHY_ERR_TAG = 4, ++ HTT_STATS_STRING_TAG = 5, ++ HTT_STATS_TX_HWQ_CMN_TAG = 6, ++ HTT_STATS_TX_HWQ_DIFS_LATENCY_TAG = 7, ++ HTT_STATS_TX_HWQ_CMD_RESULT_TAG = 8, ++ HTT_STATS_TX_HWQ_CMD_STALL_TAG = 9, ++ HTT_STATS_TX_HWQ_FES_STATUS_TAG = 10, ++ HTT_STATS_TX_TQM_GEN_MPDU_TAG = 11, ++ HTT_STATS_TX_TQM_LIST_MPDU_TAG = 12, ++ HTT_STATS_TX_TQM_LIST_MPDU_CNT_TAG = 13, ++ HTT_STATS_TX_TQM_CMN_TAG = 14, ++ HTT_STATS_TX_TQM_PDEV_TAG = 15, ++ HTT_STATS_TX_TQM_CMDQ_STATUS_TAG = 16, ++ HTT_STATS_TX_DE_EAPOL_PACKETS_TAG = 17, ++ HTT_STATS_TX_DE_CLASSIFY_FAILED_TAG = 18, ++ HTT_STATS_TX_DE_CLASSIFY_STATS_TAG = 19, ++ HTT_STATS_TX_DE_CLASSIFY_STATUS_TAG = 20, ++ HTT_STATS_TX_DE_ENQUEUE_PACKETS_TAG = 21, ++ HTT_STATS_TX_DE_ENQUEUE_DISCARD_TAG = 22, ++ HTT_STATS_TX_DE_CMN_TAG = 23, ++ HTT_STATS_RING_IF_TAG = 24, ++ HTT_STATS_TX_PDEV_MU_MIMO_STATS_TAG = 25, ++ HTT_STATS_SFM_CMN_TAG = 26, ++ HTT_STATS_SRING_STATS_TAG = 27, ++ HTT_STATS_RX_PDEV_FW_STATS_TAG = 28, ++ HTT_STATS_RX_PDEV_FW_RING_MPDU_ERR_TAG = 29, ++ HTT_STATS_RX_PDEV_FW_MPDU_DROP_TAG = 30, ++ HTT_STATS_RX_SOC_FW_STATS_TAG = 31, ++ HTT_STATS_RX_SOC_FW_REFILL_RING_EMPTY_TAG = 32, ++ HTT_STATS_RX_SOC_FW_REFILL_RING_NUM_REFILL_TAG = 33, ++ HTT_STATS_TX_PDEV_RATE_STATS_TAG = 34, ++ HTT_STATS_RX_PDEV_RATE_STATS_TAG = 35, ++ HTT_STATS_TX_PDEV_SCHEDULER_TXQ_STATS_TAG = 36, ++ HTT_STATS_TX_SCHED_CMN_TAG = 37, ++ HTT_STATS_TX_PDEV_MUMIMO_MPDU_STATS_TAG = 38, ++ HTT_STATS_SCHED_TXQ_CMD_POSTED_TAG = 39, ++ HTT_STATS_RING_IF_CMN_TAG = 40, ++ HTT_STATS_SFM_CLIENT_USER_TAG = 41, ++ HTT_STATS_SFM_CLIENT_TAG = 42, ++ HTT_STATS_TX_TQM_ERROR_STATS_TAG = 43, ++ HTT_STATS_SCHED_TXQ_CMD_REAPED_TAG = 44, ++ HTT_STATS_SRING_CMN_TAG = 45, ++ HTT_STATS_TX_SELFGEN_AC_ERR_STATS_TAG = 46, ++ HTT_STATS_TX_SELFGEN_CMN_STATS_TAG = 47, ++ HTT_STATS_TX_SELFGEN_AC_STATS_TAG = 48, ++ HTT_STATS_TX_SELFGEN_AX_STATS_TAG = 49, ++ HTT_STATS_TX_SELFGEN_AX_ERR_STATS_TAG = 50, ++ HTT_STATS_TX_HWQ_MUMIMO_SCH_STATS_TAG = 51, ++ HTT_STATS_TX_HWQ_MUMIMO_MPDU_STATS_TAG = 52, ++ HTT_STATS_TX_HWQ_MUMIMO_CMN_STATS_TAG = 53, ++ HTT_STATS_HW_INTR_MISC_TAG = 54, ++ HTT_STATS_HW_WD_TIMEOUT_TAG = 55, ++ HTT_STATS_HW_PDEV_ERRS_TAG = 56, ++ HTT_STATS_COUNTER_NAME_TAG = 57, ++ HTT_STATS_TX_TID_DETAILS_TAG = 58, ++ HTT_STATS_RX_TID_DETAILS_TAG = 59, ++ HTT_STATS_PEER_STATS_CMN_TAG = 60, ++ HTT_STATS_PEER_DETAILS_TAG = 61, ++ HTT_STATS_PEER_TX_RATE_STATS_TAG = 62, ++ HTT_STATS_PEER_RX_RATE_STATS_TAG = 63, ++ HTT_STATS_PEER_MSDU_FLOWQ_TAG = 64, ++ HTT_STATS_TX_DE_COMPL_STATS_TAG = 65, ++ HTT_STATS_WHAL_TX_TAG = 66, ++ HTT_STATS_TX_PDEV_SIFS_HIST_TAG = 67, ++ HTT_STATS_RX_PDEV_FW_STATS_PHY_ERR_TAG = 68, ++ HTT_STATS_TX_TID_DETAILS_V1_TAG = 69, ++ HTT_STATS_PDEV_CCA_1SEC_HIST_TAG = 70, ++ HTT_STATS_PDEV_CCA_100MSEC_HIST_TAG = 71, ++ HTT_STATS_PDEV_CCA_STAT_CUMULATIVE_TAG = 72, ++ HTT_STATS_PDEV_CCA_COUNTERS_TAG = 73, ++ HTT_STATS_TX_PDEV_MPDU_STATS_TAG = 74, ++ HTT_STATS_PDEV_TWT_SESSIONS_TAG = 75, ++ HTT_STATS_PDEV_TWT_SESSION_TAG = 76, ++ HTT_STATS_RX_REFILL_RXDMA_ERR_TAG = 77, ++ HTT_STATS_RX_REFILL_REO_ERR_TAG = 78, ++ HTT_STATS_RX_REO_RESOURCE_STATS_TAG = 79, ++ HTT_STATS_TX_SOUNDING_STATS_TAG = 80, ++ HTT_STATS_TX_PDEV_TX_PPDU_STATS_TAG = 81, ++ HTT_STATS_TX_PDEV_TRIED_MPDU_CNT_HIST_TAG = 82, ++ HTT_STATS_TX_HWQ_TRIED_MPDU_CNT_HIST_TAG = 83, ++ HTT_STATS_TX_HWQ_TXOP_USED_CNT_HIST_TAG = 84, ++ HTT_STATS_TX_DE_FW2WBM_RING_FULL_HIST_TAG = 85, ++ HTT_STATS_SCHED_TXQ_SCHED_ORDER_SU_TAG = 86, ++ HTT_STATS_SCHED_TXQ_SCHED_INELIGIBILITY_TAG = 87, ++ HTT_STATS_PDEV_OBSS_PD_TAG = 88, ++ HTT_STATS_HW_WAR_TAG = 89, ++ HTT_STATS_RING_BACKPRESSURE_STATS_TAG = 90, ++ ++ HTT_STATS_MAX_TAG, ++}; ++ ++#define HTT_STATS_MAX_STRING_SZ32 4 ++#define HTT_STATS_MACID_INVALID 0xff ++#define HTT_TX_HWQ_MAX_DIFS_LATENCY_BINS 10 ++#define HTT_TX_HWQ_MAX_CMD_RESULT_STATS 13 ++#define HTT_TX_HWQ_MAX_CMD_STALL_STATS 5 ++#define HTT_TX_HWQ_MAX_FES_RESULT_STATS 10 ++ ++enum htt_tx_pdev_underrun_enum { ++ HTT_STATS_TX_PDEV_NO_DATA_UNDERRUN = 0, ++ HTT_STATS_TX_PDEV_DATA_UNDERRUN_BETWEEN_MPDU = 1, ++ HTT_STATS_TX_PDEV_DATA_UNDERRUN_WITHIN_MPDU = 2, ++ HTT_TX_PDEV_MAX_URRN_STATS = 3, ++}; ++ ++#define HTT_TX_PDEV_MAX_FLUSH_REASON_STATS 71 ++#define HTT_TX_PDEV_MAX_SIFS_BURST_STATS 9 ++#define HTT_TX_PDEV_MAX_SIFS_BURST_HIST_STATS 10 ++#define HTT_TX_PDEV_MAX_PHY_ERR_STATS 18 ++#define HTT_TX_PDEV_SCHED_TX_MODE_MAX 4 ++#define HTT_TX_PDEV_NUM_SCHED_ORDER_LOG 20 ++ ++#define HTT_RX_STATS_REFILL_MAX_RING 4 ++#define HTT_RX_STATS_RXDMA_MAX_ERR 16 ++#define HTT_RX_STATS_FW_DROP_REASON_MAX 16 ++ ++/* Bytes stored in little endian order */ ++/* Length should be multiple of DWORD */ ++struct htt_stats_string_tlv { ++ u32 data[0]; /* Can be variable length */ ++} __packed; ++ ++/* == TX PDEV STATS == */ ++struct htt_tx_pdev_stats_cmn_tlv { ++ u32 mac_id__word; ++ u32 hw_queued; ++ u32 hw_reaped; ++ u32 underrun; ++ u32 hw_paused; ++ u32 hw_flush; ++ u32 hw_filt; ++ u32 tx_abort; ++ u32 mpdu_requed; ++ u32 tx_xretry; ++ u32 data_rc; ++ u32 mpdu_dropped_xretry; ++ u32 illgl_rate_phy_err; ++ u32 cont_xretry; ++ u32 tx_timeout; ++ u32 pdev_resets; ++ u32 phy_underrun; ++ u32 txop_ovf; ++ u32 seq_posted; ++ u32 seq_failed_queueing; ++ u32 seq_completed; ++ u32 seq_restarted; ++ u32 mu_seq_posted; ++ u32 seq_switch_hw_paused; ++ u32 next_seq_posted_dsr; ++ u32 seq_posted_isr; ++ u32 seq_ctrl_cached; ++ u32 mpdu_count_tqm; ++ u32 msdu_count_tqm; ++ u32 mpdu_removed_tqm; ++ u32 msdu_removed_tqm; ++ u32 mpdus_sw_flush; ++ u32 mpdus_hw_filter; ++ u32 mpdus_truncated; ++ u32 mpdus_ack_failed; ++ u32 mpdus_expired; ++ u32 mpdus_seq_hw_retry; ++ u32 ack_tlv_proc; ++ u32 coex_abort_mpdu_cnt_valid; ++ u32 coex_abort_mpdu_cnt; ++ u32 num_total_ppdus_tried_ota; ++ u32 num_data_ppdus_tried_ota; ++ u32 local_ctrl_mgmt_enqued; ++ u32 local_ctrl_mgmt_freed; ++ u32 local_data_enqued; ++ u32 local_data_freed; ++ u32 mpdu_tried; ++ u32 isr_wait_seq_posted; ++ ++ u32 tx_active_dur_us_low; ++ u32 tx_active_dur_us_high; ++}; ++ ++/* NOTE: Variable length TLV, use length spec to infer array size */ ++struct htt_tx_pdev_stats_urrn_tlv_v { ++ u32 urrn_stats[0]; /* HTT_TX_PDEV_MAX_URRN_STATS */ ++}; ++ ++/* NOTE: Variable length TLV, use length spec to infer array size */ ++struct htt_tx_pdev_stats_flush_tlv_v { ++ u32 flush_errs[0]; /* HTT_TX_PDEV_MAX_FLUSH_REASON_STATS */ ++}; ++ ++/* NOTE: Variable length TLV, use length spec to infer array size */ ++struct htt_tx_pdev_stats_sifs_tlv_v { ++ u32 sifs_status[0]; /* HTT_TX_PDEV_MAX_SIFS_BURST_STATS */ ++}; ++ ++/* NOTE: Variable length TLV, use length spec to infer array size */ ++struct htt_tx_pdev_stats_phy_err_tlv_v { ++ u32 phy_errs[0]; /* HTT_TX_PDEV_MAX_PHY_ERR_STATS */ ++}; ++ ++/* NOTE: Variable length TLV, use length spec to infer array size */ ++struct htt_tx_pdev_stats_sifs_hist_tlv_v { ++ u32 sifs_hist_status[0]; /* HTT_TX_PDEV_SIFS_BURST_HIST_STATS */ ++}; ++ ++struct htt_tx_pdev_stats_tx_ppdu_stats_tlv_v { ++ u32 num_data_ppdus_legacy_su; ++ u32 num_data_ppdus_ac_su; ++ u32 num_data_ppdus_ax_su; ++ u32 num_data_ppdus_ac_su_txbf; ++ u32 num_data_ppdus_ax_su_txbf; ++}; ++ ++/* NOTE: Variable length TLV, use length spec to infer array size . ++ * ++ * Tried_mpdu_cnt_hist is the histogram of MPDUs tries per HWQ. ++ * The tries here is the count of the MPDUS within a PPDU that the ++ * HW had attempted to transmit on air, for the HWSCH Schedule ++ * command submitted by FW.It is not the retry attempts. ++ * The histogram bins are 0-29, 30-59, 60-89 and so on. The are ++ * 10 bins in this histogram. They are defined in FW using the ++ * following macros ++ * #define WAL_MAX_TRIED_MPDU_CNT_HISTOGRAM 9 ++ * #define WAL_TRIED_MPDU_CNT_HISTOGRAM_INTERVAL 30 ++ */ ++struct htt_tx_pdev_stats_tried_mpdu_cnt_hist_tlv_v { ++ u32 hist_bin_size; ++ u32 tried_mpdu_cnt_hist[]; /* HTT_TX_PDEV_TRIED_MPDU_CNT_HIST */ ++}; ++ ++/* == SOC ERROR STATS == */ ++ ++/* =============== PDEV ERROR STATS ============== */ ++#define HTT_STATS_MAX_HW_INTR_NAME_LEN 8 ++struct htt_hw_stats_intr_misc_tlv { ++ /* Stored as little endian */ ++ u8 hw_intr_name[HTT_STATS_MAX_HW_INTR_NAME_LEN]; ++ u32 mask; ++ u32 count; ++}; ++ ++#define HTT_STATS_MAX_HW_MODULE_NAME_LEN 8 ++struct htt_hw_stats_wd_timeout_tlv { ++ /* Stored as little endian */ ++ u8 hw_module_name[HTT_STATS_MAX_HW_MODULE_NAME_LEN]; ++ u32 count; ++}; ++ ++struct htt_hw_stats_pdev_errs_tlv { ++ u32 mac_id__word; /* BIT [ 7 : 0] : mac_id */ ++ u32 tx_abort; ++ u32 tx_abort_fail_count; ++ u32 rx_abort; ++ u32 rx_abort_fail_count; ++ u32 warm_reset; ++ u32 cold_reset; ++ u32 tx_flush; ++ u32 tx_glb_reset; ++ u32 tx_txq_reset; ++ u32 rx_timeout_reset; ++}; ++ ++struct htt_hw_stats_whal_tx_tlv { ++ u32 mac_id__word; ++ u32 last_unpause_ppdu_id; ++ u32 hwsch_unpause_wait_tqm_write; ++ u32 hwsch_dummy_tlv_skipped; ++ u32 hwsch_misaligned_offset_received; ++ u32 hwsch_reset_count; ++ u32 hwsch_dev_reset_war; ++ u32 hwsch_delayed_pause; ++ u32 hwsch_long_delayed_pause; ++ u32 sch_rx_ppdu_no_response; ++ u32 sch_selfgen_response; ++ u32 sch_rx_sifs_resp_trigger; ++}; ++ ++/* ============ PEER STATS ============ */ ++struct htt_msdu_flow_stats_tlv { ++ u32 last_update_timestamp; ++ u32 last_add_timestamp; ++ u32 last_remove_timestamp; ++ u32 total_processed_msdu_count; ++ u32 cur_msdu_count_in_flowq; ++ u32 sw_peer_id; ++ u32 tx_flow_no__tid_num__drop_rule; ++ u32 last_cycle_enqueue_count; ++ u32 last_cycle_dequeue_count; ++ u32 last_cycle_drop_count; ++ u32 current_drop_th; ++}; ++ ++#define MAX_HTT_TID_NAME 8 ++ ++/* Tidq stats */ ++struct htt_tx_tid_stats_tlv { ++ /* Stored as little endian */ ++ u8 tid_name[MAX_HTT_TID_NAME]; ++ u32 sw_peer_id__tid_num; ++ u32 num_sched_pending__num_ppdu_in_hwq; ++ u32 tid_flags; ++ u32 hw_queued; ++ u32 hw_reaped; ++ u32 mpdus_hw_filter; ++ ++ u32 qdepth_bytes; ++ u32 qdepth_num_msdu; ++ u32 qdepth_num_mpdu; ++ u32 last_scheduled_tsmp; ++ u32 pause_module_id; ++ u32 block_module_id; ++ u32 tid_tx_airtime; ++}; ++ ++/* Tidq stats */ ++struct htt_tx_tid_stats_v1_tlv { ++ /* Stored as little endian */ ++ u8 tid_name[MAX_HTT_TID_NAME]; ++ u32 sw_peer_id__tid_num; ++ u32 num_sched_pending__num_ppdu_in_hwq; ++ u32 tid_flags; ++ u32 max_qdepth_bytes; ++ u32 max_qdepth_n_msdus; ++ u32 rsvd; ++ ++ u32 qdepth_bytes; ++ u32 qdepth_num_msdu; ++ u32 qdepth_num_mpdu; ++ u32 last_scheduled_tsmp; ++ u32 pause_module_id; ++ u32 block_module_id; ++ u32 tid_tx_airtime; ++ u32 allow_n_flags; ++ u32 sendn_frms_allowed; ++}; ++ ++struct htt_rx_tid_stats_tlv { ++ u32 sw_peer_id__tid_num; ++ u8 tid_name[MAX_HTT_TID_NAME]; ++ u32 dup_in_reorder; ++ u32 dup_past_outside_window; ++ u32 dup_past_within_window; ++ u32 rxdesc_err_decrypt; ++ u32 tid_rx_airtime; ++}; ++ ++#define HTT_MAX_COUNTER_NAME 8 ++struct htt_counter_tlv { ++ u8 counter_name[HTT_MAX_COUNTER_NAME]; ++ u32 count; ++}; ++ ++struct htt_peer_stats_cmn_tlv { ++ u32 ppdu_cnt; ++ u32 mpdu_cnt; ++ u32 msdu_cnt; ++ u32 pause_bitmap; ++ u32 block_bitmap; ++ u32 current_timestamp; ++ u32 peer_tx_airtime; ++ u32 peer_rx_airtime; ++ s32 rssi; ++ u32 peer_enqueued_count_low; ++ u32 peer_enqueued_count_high; ++ u32 peer_dequeued_count_low; ++ u32 peer_dequeued_count_high; ++ u32 peer_dropped_count_low; ++ u32 peer_dropped_count_high; ++ u32 ppdu_transmitted_bytes_low; ++ u32 ppdu_transmitted_bytes_high; ++ u32 peer_ttl_removed_count; ++ u32 inactive_time; ++}; ++ ++struct htt_peer_details_tlv { ++ u32 peer_type; ++ u32 sw_peer_id; ++ u32 vdev_pdev_ast_idx; ++ struct htt_mac_addr mac_addr; ++ u32 peer_flags; ++ u32 qpeer_flags; ++}; ++ ++enum htt_stats_param_type { ++ HTT_STATS_PREAM_OFDM, ++ HTT_STATS_PREAM_CCK, ++ HTT_STATS_PREAM_HT, ++ HTT_STATS_PREAM_VHT, ++ HTT_STATS_PREAM_HE, ++ HTT_STATS_PREAM_RSVD, ++ HTT_STATS_PREAM_RSVD1, ++ ++ HTT_STATS_PREAM_COUNT, ++}; ++ ++#define HTT_TX_PEER_STATS_NUM_MCS_COUNTERS 12 ++#define HTT_TX_PEER_STATS_NUM_GI_COUNTERS 4 ++#define HTT_TX_PEER_STATS_NUM_DCM_COUNTERS 5 ++#define HTT_TX_PEER_STATS_NUM_BW_COUNTERS 4 ++#define HTT_TX_PEER_STATS_NUM_SPATIAL_STREAMS 8 ++#define HTT_TX_PEER_STATS_NUM_PREAMBLE_TYPES HTT_STATS_PREAM_COUNT ++ ++struct htt_tx_peer_rate_stats_tlv { ++ u32 tx_ldpc; ++ u32 rts_cnt; ++ u32 ack_rssi; ++ ++ u32 tx_mcs[HTT_TX_PEER_STATS_NUM_MCS_COUNTERS]; ++ u32 tx_su_mcs[HTT_TX_PEER_STATS_NUM_MCS_COUNTERS]; ++ u32 tx_mu_mcs[HTT_TX_PEER_STATS_NUM_MCS_COUNTERS]; ++ /* element 0,1, ...7 -> NSS 1,2, ...8 */ ++ u32 tx_nss[HTT_TX_PEER_STATS_NUM_SPATIAL_STREAMS]; ++ /* element 0: 20 MHz, 1: 40 MHz, 2: 80 MHz, 3: 160 and 80+80 MHz */ ++ u32 tx_bw[HTT_TX_PEER_STATS_NUM_BW_COUNTERS]; ++ u32 tx_stbc[HTT_TX_PEER_STATS_NUM_MCS_COUNTERS]; ++ u32 tx_pream[HTT_TX_PEER_STATS_NUM_PREAMBLE_TYPES]; ++ ++ /* Counters to track number of tx packets in each GI ++ * (400us, 800us, 1600us & 3200us) in each mcs (0-11) ++ */ ++ u32 tx_gi[HTT_TX_PEER_STATS_NUM_GI_COUNTERS][HTT_TX_PEER_STATS_NUM_MCS_COUNTERS]; ++ ++ /* Counters to track packets in dcm mcs (MCS 0, 1, 3, 4) */ ++ u32 tx_dcm[HTT_TX_PEER_STATS_NUM_DCM_COUNTERS]; ++ ++}; ++ ++#define HTT_RX_PEER_STATS_NUM_MCS_COUNTERS 12 ++#define HTT_RX_PEER_STATS_NUM_GI_COUNTERS 4 ++#define HTT_RX_PEER_STATS_NUM_DCM_COUNTERS 5 ++#define HTT_RX_PEER_STATS_NUM_BW_COUNTERS 4 ++#define HTT_RX_PEER_STATS_NUM_SPATIAL_STREAMS 8 ++#define HTT_RX_PEER_STATS_NUM_PREAMBLE_TYPES HTT_STATS_PREAM_COUNT ++ ++struct htt_rx_peer_rate_stats_tlv { ++ u32 nsts; ++ ++ /* Number of rx ldpc packets */ ++ u32 rx_ldpc; ++ /* Number of rx rts packets */ ++ u32 rts_cnt; ++ ++ u32 rssi_mgmt; /* units = dB above noise floor */ ++ u32 rssi_data; /* units = dB above noise floor */ ++ u32 rssi_comb; /* units = dB above noise floor */ ++ u32 rx_mcs[HTT_RX_PEER_STATS_NUM_MCS_COUNTERS]; ++ /* element 0,1, ...7 -> NSS 1,2, ...8 */ ++ u32 rx_nss[HTT_RX_PEER_STATS_NUM_SPATIAL_STREAMS]; ++ u32 rx_dcm[HTT_RX_PEER_STATS_NUM_DCM_COUNTERS]; ++ u32 rx_stbc[HTT_RX_PEER_STATS_NUM_MCS_COUNTERS]; ++ /* element 0: 20 MHz, 1: 40 MHz, 2: 80 MHz, 3: 160 and 80+80 MHz */ ++ u32 rx_bw[HTT_RX_PEER_STATS_NUM_BW_COUNTERS]; ++ u32 rx_pream[HTT_RX_PEER_STATS_NUM_PREAMBLE_TYPES]; ++ /* units = dB above noise floor */ ++ u8 rssi_chain[HTT_RX_PEER_STATS_NUM_SPATIAL_STREAMS] ++ [HTT_RX_PEER_STATS_NUM_BW_COUNTERS]; ++ ++ /* Counters to track number of rx packets in each GI in each mcs (0-11) */ ++ u32 rx_gi[HTT_RX_PEER_STATS_NUM_GI_COUNTERS] ++ [HTT_RX_PEER_STATS_NUM_MCS_COUNTERS]; ++}; ++ ++enum htt_peer_stats_req_mode { ++ HTT_PEER_STATS_REQ_MODE_NO_QUERY, ++ HTT_PEER_STATS_REQ_MODE_QUERY_TQM, ++ HTT_PEER_STATS_REQ_MODE_FLUSH_TQM, ++}; ++ ++enum htt_peer_stats_tlv_enum { ++ HTT_PEER_STATS_CMN_TLV = 0, ++ HTT_PEER_DETAILS_TLV = 1, ++ HTT_TX_PEER_RATE_STATS_TLV = 2, ++ HTT_RX_PEER_RATE_STATS_TLV = 3, ++ HTT_TX_TID_STATS_TLV = 4, ++ HTT_RX_TID_STATS_TLV = 5, ++ HTT_MSDU_FLOW_STATS_TLV = 6, ++ ++ HTT_PEER_STATS_MAX_TLV = 31, ++}; ++ ++/* =========== MUMIMO HWQ stats =========== */ ++/* MU MIMO stats per hwQ */ ++struct htt_tx_hwq_mu_mimo_sch_stats_tlv { ++ u32 mu_mimo_sch_posted; ++ u32 mu_mimo_sch_failed; ++ u32 mu_mimo_ppdu_posted; ++}; ++ ++struct htt_tx_hwq_mu_mimo_mpdu_stats_tlv { ++ u32 mu_mimo_mpdus_queued_usr; ++ u32 mu_mimo_mpdus_tried_usr; ++ u32 mu_mimo_mpdus_failed_usr; ++ u32 mu_mimo_mpdus_requeued_usr; ++ u32 mu_mimo_err_no_ba_usr; ++ u32 mu_mimo_mpdu_underrun_usr; ++ u32 mu_mimo_ampdu_underrun_usr; ++}; ++ ++struct htt_tx_hwq_mu_mimo_cmn_stats_tlv { ++ u32 mac_id__hwq_id__word; ++}; ++ ++/* == TX HWQ STATS == */ ++struct htt_tx_hwq_stats_cmn_tlv { ++ u32 mac_id__hwq_id__word; ++ ++ /* PPDU level stats */ ++ u32 xretry; ++ u32 underrun_cnt; ++ u32 flush_cnt; ++ u32 filt_cnt; ++ u32 null_mpdu_bmap; ++ u32 user_ack_failure; ++ u32 ack_tlv_proc; ++ u32 sched_id_proc; ++ u32 null_mpdu_tx_count; ++ u32 mpdu_bmap_not_recvd; ++ ++ /* Selfgen stats per hwQ */ ++ u32 num_bar; ++ u32 rts; ++ u32 cts2self; ++ u32 qos_null; ++ ++ /* MPDU level stats */ ++ u32 mpdu_tried_cnt; ++ u32 mpdu_queued_cnt; ++ u32 mpdu_ack_fail_cnt; ++ u32 mpdu_filt_cnt; ++ u32 false_mpdu_ack_count; ++ ++ u32 txq_timeout; ++}; ++ ++/* NOTE: Variable length TLV, use length spec to infer array size */ ++struct htt_tx_hwq_difs_latency_stats_tlv_v { ++ u32 hist_intvl; ++ /* histogram of ppdu post to hwsch - > cmd status received */ ++ u32 difs_latency_hist[]; /* HTT_TX_HWQ_MAX_DIFS_LATENCY_BINS */ ++}; ++ ++/* NOTE: Variable length TLV, use length spec to infer array size */ ++struct htt_tx_hwq_cmd_result_stats_tlv_v { ++ /* Histogram of sched cmd result */ ++ u32 cmd_result[0]; /* HTT_TX_HWQ_MAX_CMD_RESULT_STATS */ ++}; ++ ++/* NOTE: Variable length TLV, use length spec to infer array size */ ++struct htt_tx_hwq_cmd_stall_stats_tlv_v { ++ /* Histogram of various pause conitions */ ++ u32 cmd_stall_status[0]; /* HTT_TX_HWQ_MAX_CMD_STALL_STATS */ ++}; ++ ++/* NOTE: Variable length TLV, use length spec to infer array size */ ++struct htt_tx_hwq_fes_result_stats_tlv_v { ++ /* Histogram of number of user fes result */ ++ u32 fes_result[0]; /* HTT_TX_HWQ_MAX_FES_RESULT_STATS */ ++}; ++ ++/* NOTE: Variable length TLV, use length spec to infer array size ++ * ++ * The hwq_tried_mpdu_cnt_hist is a histogram of MPDUs tries per HWQ. ++ * The tries here is the count of the MPDUS within a PPDU that the HW ++ * had attempted to transmit on air, for the HWSCH Schedule command ++ * submitted by FW in this HWQ .It is not the retry attempts. The ++ * histogram bins are 0-29, 30-59, 60-89 and so on. The are 10 bins ++ * in this histogram. ++ * they are defined in FW using the following macros ++ * #define WAL_MAX_TRIED_MPDU_CNT_HISTOGRAM 9 ++ * #define WAL_TRIED_MPDU_CNT_HISTOGRAM_INTERVAL 30 ++ */ ++struct htt_tx_hwq_tried_mpdu_cnt_hist_tlv_v { ++ u32 hist_bin_size; ++ /* Histogram of number of mpdus on tried mpdu */ ++ u32 tried_mpdu_cnt_hist[]; /* HTT_TX_HWQ_TRIED_MPDU_CNT_HIST */ ++}; ++ ++/* NOTE: Variable length TLV, use length spec to infer array size ++ * ++ * The txop_used_cnt_hist is the histogram of txop per burst. After ++ * completing the burst, we identify the txop used in the burst and ++ * incr the corresponding bin. ++ * Each bin represents 1ms & we have 10 bins in this histogram. ++ * they are deined in FW using the following macros ++ * #define WAL_MAX_TXOP_USED_CNT_HISTOGRAM 10 ++ * #define WAL_TXOP_USED_HISTOGRAM_INTERVAL 1000 ( 1 ms ) ++ */ ++struct htt_tx_hwq_txop_used_cnt_hist_tlv_v { ++ /* Histogram of txop used cnt */ ++ u32 txop_used_cnt_hist[0]; /* HTT_TX_HWQ_TXOP_USED_CNT_HIST */ ++}; ++ ++/* == TX SELFGEN STATS == */ ++struct htt_tx_selfgen_cmn_stats_tlv { ++ u32 mac_id__word; ++ u32 su_bar; ++ u32 rts; ++ u32 cts2self; ++ u32 qos_null; ++ u32 delayed_bar_1; /* MU user 1 */ ++ u32 delayed_bar_2; /* MU user 2 */ ++ u32 delayed_bar_3; /* MU user 3 */ ++ u32 delayed_bar_4; /* MU user 4 */ ++ u32 delayed_bar_5; /* MU user 5 */ ++ u32 delayed_bar_6; /* MU user 6 */ ++ u32 delayed_bar_7; /* MU user 7 */ ++}; ++ ++struct htt_tx_selfgen_ac_stats_tlv { ++ /* 11AC */ ++ u32 ac_su_ndpa; ++ u32 ac_su_ndp; ++ u32 ac_mu_mimo_ndpa; ++ u32 ac_mu_mimo_ndp; ++ u32 ac_mu_mimo_brpoll_1; /* MU user 1 */ ++ u32 ac_mu_mimo_brpoll_2; /* MU user 2 */ ++ u32 ac_mu_mimo_brpoll_3; /* MU user 3 */ ++}; ++ ++struct htt_tx_selfgen_ax_stats_tlv { ++ /* 11AX */ ++ u32 ax_su_ndpa; ++ u32 ax_su_ndp; ++ u32 ax_mu_mimo_ndpa; ++ u32 ax_mu_mimo_ndp; ++ u32 ax_mu_mimo_brpoll_1; /* MU user 1 */ ++ u32 ax_mu_mimo_brpoll_2; /* MU user 2 */ ++ u32 ax_mu_mimo_brpoll_3; /* MU user 3 */ ++ u32 ax_mu_mimo_brpoll_4; /* MU user 4 */ ++ u32 ax_mu_mimo_brpoll_5; /* MU user 5 */ ++ u32 ax_mu_mimo_brpoll_6; /* MU user 6 */ ++ u32 ax_mu_mimo_brpoll_7; /* MU user 7 */ ++ u32 ax_basic_trigger; ++ u32 ax_bsr_trigger; ++ u32 ax_mu_bar_trigger; ++ u32 ax_mu_rts_trigger; ++}; ++ ++struct htt_tx_selfgen_ac_err_stats_tlv { ++ /* 11AC error stats */ ++ u32 ac_su_ndp_err; ++ u32 ac_su_ndpa_err; ++ u32 ac_mu_mimo_ndpa_err; ++ u32 ac_mu_mimo_ndp_err; ++ u32 ac_mu_mimo_brp1_err; ++ u32 ac_mu_mimo_brp2_err; ++ u32 ac_mu_mimo_brp3_err; ++}; ++ ++struct htt_tx_selfgen_ax_err_stats_tlv { ++ /* 11AX error stats */ ++ u32 ax_su_ndp_err; ++ u32 ax_su_ndpa_err; ++ u32 ax_mu_mimo_ndpa_err; ++ u32 ax_mu_mimo_ndp_err; ++ u32 ax_mu_mimo_brp1_err; ++ u32 ax_mu_mimo_brp2_err; ++ u32 ax_mu_mimo_brp3_err; ++ u32 ax_mu_mimo_brp4_err; ++ u32 ax_mu_mimo_brp5_err; ++ u32 ax_mu_mimo_brp6_err; ++ u32 ax_mu_mimo_brp7_err; ++ u32 ax_basic_trigger_err; ++ u32 ax_bsr_trigger_err; ++ u32 ax_mu_bar_trigger_err; ++ u32 ax_mu_rts_trigger_err; ++}; ++ ++/* == TX MU STATS == */ ++#define HTT_TX_PDEV_STATS_NUM_AC_MUMIMO_USER_STATS 4 ++#define HTT_TX_PDEV_STATS_NUM_AX_MUMIMO_USER_STATS 8 ++#define HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS 74 ++ ++struct htt_tx_pdev_mu_mimo_sch_stats_tlv { ++ /* mu-mimo sw sched cmd stats */ ++ u32 mu_mimo_sch_posted; ++ u32 mu_mimo_sch_failed; ++ /* MU PPDU stats per hwQ */ ++ u32 mu_mimo_ppdu_posted; ++ /* ++ * Counts the number of users in each transmission of ++ * the given TX mode. ++ * ++ * Index is the number of users - 1. ++ */ ++ u32 ac_mu_mimo_sch_nusers[HTT_TX_PDEV_STATS_NUM_AC_MUMIMO_USER_STATS]; ++ u32 ax_mu_mimo_sch_nusers[HTT_TX_PDEV_STATS_NUM_AX_MUMIMO_USER_STATS]; ++ u32 ax_ofdma_sch_nusers[HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS]; ++}; ++ ++struct htt_tx_pdev_mu_mimo_mpdu_stats_tlv { ++ u32 mu_mimo_mpdus_queued_usr; ++ u32 mu_mimo_mpdus_tried_usr; ++ u32 mu_mimo_mpdus_failed_usr; ++ u32 mu_mimo_mpdus_requeued_usr; ++ u32 mu_mimo_err_no_ba_usr; ++ u32 mu_mimo_mpdu_underrun_usr; ++ u32 mu_mimo_ampdu_underrun_usr; ++ ++ u32 ax_mu_mimo_mpdus_queued_usr; ++ u32 ax_mu_mimo_mpdus_tried_usr; ++ u32 ax_mu_mimo_mpdus_failed_usr; ++ u32 ax_mu_mimo_mpdus_requeued_usr; ++ u32 ax_mu_mimo_err_no_ba_usr; ++ u32 ax_mu_mimo_mpdu_underrun_usr; ++ u32 ax_mu_mimo_ampdu_underrun_usr; ++ ++ u32 ax_ofdma_mpdus_queued_usr; ++ u32 ax_ofdma_mpdus_tried_usr; ++ u32 ax_ofdma_mpdus_failed_usr; ++ u32 ax_ofdma_mpdus_requeued_usr; ++ u32 ax_ofdma_err_no_ba_usr; ++ u32 ax_ofdma_mpdu_underrun_usr; ++ u32 ax_ofdma_ampdu_underrun_usr; ++}; ++ ++#define HTT_STATS_TX_SCHED_MODE_MU_MIMO_AC 1 ++#define HTT_STATS_TX_SCHED_MODE_MU_MIMO_AX 2 ++#define HTT_STATS_TX_SCHED_MODE_MU_OFDMA_AX 3 ++ ++struct htt_tx_pdev_mpdu_stats_tlv { ++ /* mpdu level stats */ ++ u32 mpdus_queued_usr; ++ u32 mpdus_tried_usr; ++ u32 mpdus_failed_usr; ++ u32 mpdus_requeued_usr; ++ u32 err_no_ba_usr; ++ u32 mpdu_underrun_usr; ++ u32 ampdu_underrun_usr; ++ u32 user_index; ++ u32 tx_sched_mode; /* HTT_STATS_TX_SCHED_MODE_xxx */ ++}; ++ ++/* == TX SCHED STATS == */ ++/* NOTE: Variable length TLV, use length spec to infer array size */ ++struct htt_sched_txq_cmd_posted_tlv_v { ++ u32 sched_cmd_posted[0]; /* HTT_TX_PDEV_SCHED_TX_MODE_MAX */ ++}; ++ ++/* NOTE: Variable length TLV, use length spec to infer array size */ ++struct htt_sched_txq_cmd_reaped_tlv_v { ++ u32 sched_cmd_reaped[0]; /* HTT_TX_PDEV_SCHED_TX_MODE_MAX */ ++}; ++ ++/* NOTE: Variable length TLV, use length spec to infer array size */ ++struct htt_sched_txq_sched_order_su_tlv_v { ++ u32 sched_order_su[0]; /* HTT_TX_PDEV_NUM_SCHED_ORDER_LOG */ ++}; ++ ++enum htt_sched_txq_sched_ineligibility_tlv_enum { ++ HTT_SCHED_TID_SKIP_SCHED_MASK_DISABLED = 0, ++ HTT_SCHED_TID_SKIP_NOTIFY_MPDU, ++ HTT_SCHED_TID_SKIP_MPDU_STATE_INVALID, ++ HTT_SCHED_TID_SKIP_SCHED_DISABLED, ++ HTT_SCHED_TID_SKIP_TQM_BYPASS_CMD_PENDING, ++ HTT_SCHED_TID_SKIP_SECOND_SU_SCHEDULE, ++ ++ HTT_SCHED_TID_SKIP_CMD_SLOT_NOT_AVAIL, ++ HTT_SCHED_TID_SKIP_NO_ENQ, ++ HTT_SCHED_TID_SKIP_LOW_ENQ, ++ HTT_SCHED_TID_SKIP_PAUSED, ++ HTT_SCHED_TID_SKIP_UL, ++ HTT_SCHED_TID_REMOVE_PAUSED, ++ HTT_SCHED_TID_REMOVE_NO_ENQ, ++ HTT_SCHED_TID_REMOVE_UL, ++ HTT_SCHED_TID_QUERY, ++ HTT_SCHED_TID_SU_ONLY, ++ HTT_SCHED_TID_ELIGIBLE, ++ HTT_SCHED_INELIGIBILITY_MAX, ++}; ++ ++/* NOTE: Variable length TLV, use length spec to infer array size */ ++struct htt_sched_txq_sched_ineligibility_tlv_v { ++ /* indexed by htt_sched_txq_sched_ineligibility_tlv_enum */ ++ u32 sched_ineligibility[0]; ++}; ++ ++struct htt_tx_pdev_stats_sched_per_txq_tlv { ++ u32 mac_id__txq_id__word; ++ u32 sched_policy; ++ u32 last_sched_cmd_posted_timestamp; ++ u32 last_sched_cmd_compl_timestamp; ++ u32 sched_2_tac_lwm_count; ++ u32 sched_2_tac_ring_full; ++ u32 sched_cmd_post_failure; ++ u32 num_active_tids; ++ u32 num_ps_schedules; ++ u32 sched_cmds_pending; ++ u32 num_tid_register; ++ u32 num_tid_unregister; ++ u32 num_qstats_queried; ++ u32 qstats_update_pending; ++ u32 last_qstats_query_timestamp; ++ u32 num_tqm_cmdq_full; ++ u32 num_de_sched_algo_trigger; ++ u32 num_rt_sched_algo_trigger; ++ u32 num_tqm_sched_algo_trigger; ++ u32 notify_sched; ++ u32 dur_based_sendn_term; ++}; ++ ++struct htt_stats_tx_sched_cmn_tlv { ++ /* BIT [ 7 : 0] :- mac_id ++ * BIT [31 : 8] :- reserved ++ */ ++ u32 mac_id__word; ++ /* Current timestamp */ ++ u32 current_timestamp; ++}; ++ ++/* == TQM STATS == */ ++#define HTT_TX_TQM_MAX_GEN_MPDU_END_REASON 16 ++#define HTT_TX_TQM_MAX_LIST_MPDU_END_REASON 16 ++#define HTT_TX_TQM_MAX_LIST_MPDU_CNT_HISTOGRAM_BINS 16 ++ ++/* NOTE: Variable length TLV, use length spec to infer array size */ ++struct htt_tx_tqm_gen_mpdu_stats_tlv_v { ++ u32 gen_mpdu_end_reason[0]; /* HTT_TX_TQM_MAX_GEN_MPDU_END_REASON */ ++}; ++ ++/* NOTE: Variable length TLV, use length spec to infer array size */ ++struct htt_tx_tqm_list_mpdu_stats_tlv_v { ++ u32 list_mpdu_end_reason[0]; /* HTT_TX_TQM_MAX_LIST_MPDU_END_REASON */ ++}; ++ ++/* NOTE: Variable length TLV, use length spec to infer array size */ ++struct htt_tx_tqm_list_mpdu_cnt_tlv_v { ++ u32 list_mpdu_cnt_hist[0]; ++ /* HTT_TX_TQM_MAX_LIST_MPDU_CNT_HISTOGRAM_BINS */ ++}; ++ ++struct htt_tx_tqm_pdev_stats_tlv_v { ++ u32 msdu_count; ++ u32 mpdu_count; ++ u32 remove_msdu; ++ u32 remove_mpdu; ++ u32 remove_msdu_ttl; ++ u32 send_bar; ++ u32 bar_sync; ++ u32 notify_mpdu; ++ u32 sync_cmd; ++ u32 write_cmd; ++ u32 hwsch_trigger; ++ u32 ack_tlv_proc; ++ u32 gen_mpdu_cmd; ++ u32 gen_list_cmd; ++ u32 remove_mpdu_cmd; ++ u32 remove_mpdu_tried_cmd; ++ u32 mpdu_queue_stats_cmd; ++ u32 mpdu_head_info_cmd; ++ u32 msdu_flow_stats_cmd; ++ u32 remove_msdu_cmd; ++ u32 remove_msdu_ttl_cmd; ++ u32 flush_cache_cmd; ++ u32 update_mpduq_cmd; ++ u32 enqueue; ++ u32 enqueue_notify; ++ u32 notify_mpdu_at_head; ++ u32 notify_mpdu_state_valid; ++ /* ++ * On receiving TQM_FLOW_NOT_EMPTY_STATUS from TQM, (on MSDUs being enqueued ++ * the flow is non empty), if the number of MSDUs is greater than the threshold, ++ * notify is incremented. UDP_THRESH counters are for UDP MSDUs, and NONUDP are ++ * for non-UDP MSDUs. ++ * MSDUQ_SWNOTIFY_UDP_THRESH1 threshold - sched_udp_notify1 is incremented ++ * MSDUQ_SWNOTIFY_UDP_THRESH2 threshold - sched_udp_notify2 is incremented ++ * MSDUQ_SWNOTIFY_NONUDP_THRESH1 threshold - sched_nonudp_notify1 is incremented ++ * MSDUQ_SWNOTIFY_NONUDP_THRESH2 threshold - sched_nonudp_notify2 is incremented ++ * ++ * Notify signifies that we trigger the scheduler. ++ */ ++ u32 sched_udp_notify1; ++ u32 sched_udp_notify2; ++ u32 sched_nonudp_notify1; ++ u32 sched_nonudp_notify2; ++}; ++ ++struct htt_tx_tqm_cmn_stats_tlv { ++ u32 mac_id__word; ++ u32 max_cmdq_id; ++ u32 list_mpdu_cnt_hist_intvl; ++ ++ /* Global stats */ ++ u32 add_msdu; ++ u32 q_empty; ++ u32 q_not_empty; ++ u32 drop_notification; ++ u32 desc_threshold; ++}; ++ ++struct htt_tx_tqm_error_stats_tlv { ++ /* Error stats */ ++ u32 q_empty_failure; ++ u32 q_not_empty_failure; ++ u32 add_msdu_failure; ++}; ++ ++/* == TQM CMDQ stats == */ ++struct htt_tx_tqm_cmdq_status_tlv { ++ u32 mac_id__cmdq_id__word; ++ u32 sync_cmd; ++ u32 write_cmd; ++ u32 gen_mpdu_cmd; ++ u32 mpdu_queue_stats_cmd; ++ u32 mpdu_head_info_cmd; ++ u32 msdu_flow_stats_cmd; ++ u32 remove_mpdu_cmd; ++ u32 remove_msdu_cmd; ++ u32 flush_cache_cmd; ++ u32 update_mpduq_cmd; ++ u32 update_msduq_cmd; ++}; ++ ++/* == TX-DE STATS == */ ++/* Structures for tx de stats */ ++struct htt_tx_de_eapol_packets_stats_tlv { ++ u32 m1_packets; ++ u32 m2_packets; ++ u32 m3_packets; ++ u32 m4_packets; ++ u32 g1_packets; ++ u32 g2_packets; ++}; ++ ++struct htt_tx_de_classify_failed_stats_tlv { ++ u32 ap_bss_peer_not_found; ++ u32 ap_bcast_mcast_no_peer; ++ u32 sta_delete_in_progress; ++ u32 ibss_no_bss_peer; ++ u32 invalid_vdev_type; ++ u32 invalid_ast_peer_entry; ++ u32 peer_entry_invalid; ++ u32 ethertype_not_ip; ++ u32 eapol_lookup_failed; ++ u32 qpeer_not_allow_data; ++ u32 fse_tid_override; ++ u32 ipv6_jumbogram_zero_length; ++ u32 qos_to_non_qos_in_prog; ++}; ++ ++struct htt_tx_de_classify_stats_tlv { ++ u32 arp_packets; ++ u32 igmp_packets; ++ u32 dhcp_packets; ++ u32 host_inspected; ++ u32 htt_included; ++ u32 htt_valid_mcs; ++ u32 htt_valid_nss; ++ u32 htt_valid_preamble_type; ++ u32 htt_valid_chainmask; ++ u32 htt_valid_guard_interval; ++ u32 htt_valid_retries; ++ u32 htt_valid_bw_info; ++ u32 htt_valid_power; ++ u32 htt_valid_key_flags; ++ u32 htt_valid_no_encryption; ++ u32 fse_entry_count; ++ u32 fse_priority_be; ++ u32 fse_priority_high; ++ u32 fse_priority_low; ++ u32 fse_traffic_ptrn_be; ++ u32 fse_traffic_ptrn_over_sub; ++ u32 fse_traffic_ptrn_bursty; ++ u32 fse_traffic_ptrn_interactive; ++ u32 fse_traffic_ptrn_periodic; ++ u32 fse_hwqueue_alloc; ++ u32 fse_hwqueue_created; ++ u32 fse_hwqueue_send_to_host; ++ u32 mcast_entry; ++ u32 bcast_entry; ++ u32 htt_update_peer_cache; ++ u32 htt_learning_frame; ++ u32 fse_invalid_peer; ++ /* ++ * mec_notify is HTT TX WBM multicast echo check notification ++ * from firmware to host. FW sends SA addresses to host for all ++ * multicast/broadcast packets received on STA side. ++ */ ++ u32 mec_notify; ++}; ++ ++struct htt_tx_de_classify_status_stats_tlv { ++ u32 eok; ++ u32 classify_done; ++ u32 lookup_failed; ++ u32 send_host_dhcp; ++ u32 send_host_mcast; ++ u32 send_host_unknown_dest; ++ u32 send_host; ++ u32 status_invalid; ++}; ++ ++struct htt_tx_de_enqueue_packets_stats_tlv { ++ u32 enqueued_pkts; ++ u32 to_tqm; ++ u32 to_tqm_bypass; ++}; ++ ++struct htt_tx_de_enqueue_discard_stats_tlv { ++ u32 discarded_pkts; ++ u32 local_frames; ++ u32 is_ext_msdu; ++}; ++ ++struct htt_tx_de_compl_stats_tlv { ++ u32 tcl_dummy_frame; ++ u32 tqm_dummy_frame; ++ u32 tqm_notify_frame; ++ u32 fw2wbm_enq; ++ u32 tqm_bypass_frame; ++}; ++ ++/* ++ * The htt_tx_de_fw2wbm_ring_full_hist_tlv is a histogram of time we waited ++ * for the fw2wbm ring buffer. we are requesting a buffer in FW2WBM release ++ * ring,which may fail, due to non availability of buffer. Hence we sleep for ++ * 200us & again request for it. This is a histogram of time we wait, with ++ * bin of 200ms & there are 10 bin (2 seconds max) ++ * They are defined by the following macros in FW ++ * #define ENTRIES_PER_BIN_COUNT 1000 // per bin 1000 * 200us = 200ms ++ * #define RING_FULL_BIN_ENTRIES (WAL_TX_DE_FW2WBM_ALLOC_TIMEOUT_COUNT / ++ * ENTRIES_PER_BIN_COUNT) ++ */ ++struct htt_tx_de_fw2wbm_ring_full_hist_tlv { ++ u32 fw2wbm_ring_full_hist[0]; ++}; ++ ++struct htt_tx_de_cmn_stats_tlv { ++ u32 mac_id__word; ++ ++ /* Global Stats */ ++ u32 tcl2fw_entry_count; ++ u32 not_to_fw; ++ u32 invalid_pdev_vdev_peer; ++ u32 tcl_res_invalid_addrx; ++ u32 wbm2fw_entry_count; ++ u32 invalid_pdev; ++}; ++ ++/* == RING-IF STATS == */ ++#define HTT_STATS_LOW_WM_BINS 5 ++#define HTT_STATS_HIGH_WM_BINS 5 ++ ++struct htt_ring_if_stats_tlv { ++ u32 base_addr; /* DWORD aligned base memory address of the ring */ ++ u32 elem_size; ++ u32 num_elems__prefetch_tail_idx; ++ u32 head_idx__tail_idx; ++ u32 shadow_head_idx__shadow_tail_idx; ++ u32 num_tail_incr; ++ u32 lwm_thresh__hwm_thresh; ++ u32 overrun_hit_count; ++ u32 underrun_hit_count; ++ u32 prod_blockwait_count; ++ u32 cons_blockwait_count; ++ u32 low_wm_hit_count[HTT_STATS_LOW_WM_BINS]; ++ u32 high_wm_hit_count[HTT_STATS_HIGH_WM_BINS]; ++}; ++ ++struct htt_ring_if_cmn_tlv { ++ u32 mac_id__word; ++ u32 num_records; ++}; ++ ++/* == SFM STATS == */ ++/* NOTE: Variable length TLV, use length spec to infer array size */ ++struct htt_sfm_client_user_tlv_v { ++ /* Number of DWORDS used per user and per client */ ++ u32 dwords_used_by_user_n[0]; ++}; ++ ++struct htt_sfm_client_tlv { ++ /* Client ID */ ++ u32 client_id; ++ /* Minimum number of buffers */ ++ u32 buf_min; ++ /* Maximum number of buffers */ ++ u32 buf_max; ++ /* Number of Busy buffers */ ++ u32 buf_busy; ++ /* Number of Allocated buffers */ ++ u32 buf_alloc; ++ /* Number of Available/Usable buffers */ ++ u32 buf_avail; ++ /* Number of users */ ++ u32 num_users; ++}; ++ ++struct htt_sfm_cmn_tlv { ++ u32 mac_id__word; ++ /* Indicates the total number of 128 byte buffers ++ * in the CMEM that are available for buffer sharing ++ */ ++ u32 buf_total; ++ /* Indicates for certain client or all the clients ++ * there is no dowrd saved in SFM, refer to SFM_R1_MEM_EMPTY ++ */ ++ u32 mem_empty; ++ /* DEALLOCATE_BUFFERS, refer to register SFM_R0_DEALLOCATE_BUFFERS */ ++ u32 deallocate_bufs; ++ /* Number of Records */ ++ u32 num_records; ++}; ++ ++/* == SRNG STATS == */ ++struct htt_sring_stats_tlv { ++ u32 mac_id__ring_id__arena__ep; ++ u32 base_addr_lsb; /* DWORD aligned base memory address of the ring */ ++ u32 base_addr_msb; ++ u32 ring_size; ++ u32 elem_size; ++ ++ u32 num_avail_words__num_valid_words; ++ u32 head_ptr__tail_ptr; ++ u32 consumer_empty__producer_full; ++ u32 prefetch_count__internal_tail_ptr; ++}; ++ ++struct htt_sring_cmn_tlv { ++ u32 num_records; ++}; ++ ++/* == PDEV TX RATE CTRL STATS == */ ++#define HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS 12 ++#define HTT_TX_PDEV_STATS_NUM_GI_COUNTERS 4 ++#define HTT_TX_PDEV_STATS_NUM_DCM_COUNTERS 5 ++#define HTT_TX_PDEV_STATS_NUM_BW_COUNTERS 4 ++#define HTT_TX_PDEV_STATS_NUM_SPATIAL_STREAMS 8 ++#define HTT_TX_PDEV_STATS_NUM_PREAMBLE_TYPES HTT_STATS_PREAM_COUNT ++#define HTT_TX_PDEV_STATS_NUM_LEGACY_CCK_STATS 4 ++#define HTT_TX_PDEV_STATS_NUM_LEGACY_OFDM_STATS 8 ++#define HTT_TX_PDEV_STATS_NUM_LTF 4 ++ ++#define HTT_TX_NUM_OF_SOUNDING_STATS_WORDS \ ++ (HTT_TX_PDEV_STATS_NUM_BW_COUNTERS * \ ++ HTT_TX_PDEV_STATS_NUM_AX_MUMIMO_USER_STATS) ++ ++struct htt_tx_pdev_rate_stats_tlv { ++ u32 mac_id__word; ++ u32 tx_ldpc; ++ u32 rts_cnt; ++ /* RSSI value of last ack packet (units = dB above noise floor) */ ++ u32 ack_rssi; ++ ++ u32 tx_mcs[HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS]; ++ ++ u32 tx_su_mcs[HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS]; ++ u32 tx_mu_mcs[HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS]; ++ ++ /* element 0,1, ...7 -> NSS 1,2, ...8 */ ++ u32 tx_nss[HTT_TX_PDEV_STATS_NUM_SPATIAL_STREAMS]; ++ /* element 0: 20 MHz, 1: 40 MHz, 2: 80 MHz, 3: 160 and 80+80 MHz */ ++ u32 tx_bw[HTT_TX_PDEV_STATS_NUM_BW_COUNTERS]; ++ u32 tx_stbc[HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS]; ++ u32 tx_pream[HTT_TX_PDEV_STATS_NUM_PREAMBLE_TYPES]; ++ ++ /* Counters to track number of tx packets ++ * in each GI (400us, 800us, 1600us & 3200us) in each mcs (0-11) ++ */ ++ u32 tx_gi[HTT_TX_PDEV_STATS_NUM_GI_COUNTERS][HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS]; ++ ++ /* Counters to track packets in dcm mcs (MCS 0, 1, 3, 4) */ ++ u32 tx_dcm[HTT_TX_PDEV_STATS_NUM_DCM_COUNTERS]; ++ /* Number of CTS-acknowledged RTS packets */ ++ u32 rts_success; ++ ++ /* ++ * Counters for legacy 11a and 11b transmissions. ++ * ++ * The index corresponds to: ++ * ++ * CCK: 0: 1 Mbps, 1: 2 Mbps, 2: 5.5 Mbps, 3: 11 Mbps ++ * ++ * OFDM: 0: 6 Mbps, 1: 9 Mbps, 2: 12 Mbps, 3: 18 Mbps, ++ * 4: 24 Mbps, 5: 36 Mbps, 6: 48 Mbps, 7: 54 Mbps ++ */ ++ u32 tx_legacy_cck_rate[HTT_TX_PDEV_STATS_NUM_LEGACY_CCK_STATS]; ++ u32 tx_legacy_ofdm_rate[HTT_TX_PDEV_STATS_NUM_LEGACY_OFDM_STATS]; ++ ++ u32 ac_mu_mimo_tx_ldpc; ++ u32 ax_mu_mimo_tx_ldpc; ++ u32 ofdma_tx_ldpc; ++ ++ /* ++ * Counters for 11ax HE LTF selection during TX. ++ * ++ * The index corresponds to: ++ * ++ * 0: unused, 1: 1x LTF, 2: 2x LTF, 3: 4x LTF ++ */ ++ u32 tx_he_ltf[HTT_TX_PDEV_STATS_NUM_LTF]; ++ ++ u32 ac_mu_mimo_tx_mcs[HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS]; ++ u32 ax_mu_mimo_tx_mcs[HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS]; ++ u32 ofdma_tx_mcs[HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS]; ++ ++ u32 ac_mu_mimo_tx_nss[HTT_TX_PDEV_STATS_NUM_SPATIAL_STREAMS]; ++ u32 ax_mu_mimo_tx_nss[HTT_TX_PDEV_STATS_NUM_SPATIAL_STREAMS]; ++ u32 ofdma_tx_nss[HTT_TX_PDEV_STATS_NUM_SPATIAL_STREAMS]; ++ ++ u32 ac_mu_mimo_tx_bw[HTT_TX_PDEV_STATS_NUM_BW_COUNTERS]; ++ u32 ax_mu_mimo_tx_bw[HTT_TX_PDEV_STATS_NUM_BW_COUNTERS]; ++ u32 ofdma_tx_bw[HTT_TX_PDEV_STATS_NUM_BW_COUNTERS]; ++ ++ u32 ac_mu_mimo_tx_gi[HTT_TX_PDEV_STATS_NUM_GI_COUNTERS] ++ [HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS]; ++ u32 ax_mu_mimo_tx_gi[HTT_TX_PDEV_STATS_NUM_GI_COUNTERS] ++ [HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS]; ++ u32 ofdma_tx_gi[HTT_TX_PDEV_STATS_NUM_GI_COUNTERS] ++ [HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS]; ++}; ++ ++/* == PDEV RX RATE CTRL STATS == */ ++#define HTT_RX_PDEV_STATS_NUM_LEGACY_CCK_STATS 4 ++#define HTT_RX_PDEV_STATS_NUM_LEGACY_OFDM_STATS 8 ++#define HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS 12 ++#define HTT_RX_PDEV_STATS_NUM_GI_COUNTERS 4 ++#define HTT_RX_PDEV_STATS_NUM_DCM_COUNTERS 5 ++#define HTT_RX_PDEV_STATS_NUM_BW_COUNTERS 4 ++#define HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS 8 ++#define HTT_RX_PDEV_STATS_NUM_PREAMBLE_TYPES HTT_STATS_PREAM_COUNT ++#define HTT_RX_PDEV_MAX_OFDMA_NUM_USER 8 ++#define HTT_RX_PDEV_STATS_RXEVM_MAX_PILOTS_PER_NSS 16 ++ ++struct htt_rx_pdev_rate_stats_tlv { ++ u32 mac_id__word; ++ u32 nsts; ++ ++ u32 rx_ldpc; ++ u32 rts_cnt; ++ ++ u32 rssi_mgmt; /* units = dB above noise floor */ ++ u32 rssi_data; /* units = dB above noise floor */ ++ u32 rssi_comb; /* units = dB above noise floor */ ++ u32 rx_mcs[HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS]; ++ /* element 0,1, ...7 -> NSS 1,2, ...8 */ ++ u32 rx_nss[HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS]; ++ u32 rx_dcm[HTT_RX_PDEV_STATS_NUM_DCM_COUNTERS]; ++ u32 rx_stbc[HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS]; ++ /* element 0: 20 MHz, 1: 40 MHz, 2: 80 MHz, 3: 160 and 80+80 MHz */ ++ u32 rx_bw[HTT_RX_PDEV_STATS_NUM_BW_COUNTERS]; ++ u32 rx_pream[HTT_RX_PDEV_STATS_NUM_PREAMBLE_TYPES]; ++ u8 rssi_chain[HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS] ++ [HTT_RX_PDEV_STATS_NUM_BW_COUNTERS]; ++ /* units = dB above noise floor */ ++ ++ /* Counters to track number of rx packets ++ * in each GI in each mcs (0-11) ++ */ ++ u32 rx_gi[HTT_RX_PDEV_STATS_NUM_GI_COUNTERS][HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS]; ++ s32 rssi_in_dbm; /* rx Signal Strength value in dBm unit */ ++ ++ u32 rx_11ax_su_ext; ++ u32 rx_11ac_mumimo; ++ u32 rx_11ax_mumimo; ++ u32 rx_11ax_ofdma; ++ u32 txbf; ++ u32 rx_legacy_cck_rate[HTT_RX_PDEV_STATS_NUM_LEGACY_CCK_STATS]; ++ u32 rx_legacy_ofdm_rate[HTT_RX_PDEV_STATS_NUM_LEGACY_OFDM_STATS]; ++ u32 rx_active_dur_us_low; ++ u32 rx_active_dur_us_high; ++ ++ u32 rx_11ax_ul_ofdma; ++ ++ u32 ul_ofdma_rx_mcs[HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS]; ++ u32 ul_ofdma_rx_gi[HTT_TX_PDEV_STATS_NUM_GI_COUNTERS] ++ [HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS]; ++ u32 ul_ofdma_rx_nss[HTT_TX_PDEV_STATS_NUM_SPATIAL_STREAMS]; ++ u32 ul_ofdma_rx_bw[HTT_TX_PDEV_STATS_NUM_BW_COUNTERS]; ++ u32 ul_ofdma_rx_stbc; ++ u32 ul_ofdma_rx_ldpc; ++ ++ /* record the stats for each user index */ ++ u32 rx_ulofdma_non_data_ppdu[HTT_RX_PDEV_MAX_OFDMA_NUM_USER]; /* ppdu level */ ++ u32 rx_ulofdma_data_ppdu[HTT_RX_PDEV_MAX_OFDMA_NUM_USER]; /* ppdu level */ ++ u32 rx_ulofdma_mpdu_ok[HTT_RX_PDEV_MAX_OFDMA_NUM_USER]; /* mpdu level */ ++ u32 rx_ulofdma_mpdu_fail[HTT_RX_PDEV_MAX_OFDMA_NUM_USER]; /* mpdu level */ ++ ++ u32 nss_count; ++ u32 pilot_count; ++ /* RxEVM stats in dB */ ++ s32 rx_pilot_evm_db[HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS] ++ [HTT_RX_PDEV_STATS_RXEVM_MAX_PILOTS_PER_NSS]; ++ /* rx_pilot_evm_db_mean: ++ * EVM mean across pilots, computed as ++ * mean(10*log10(rx_pilot_evm_linear)) = mean(rx_pilot_evm_db) ++ */ ++ s32 rx_pilot_evm_db_mean[HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS]; ++ s8 rx_ul_fd_rssi[HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS] ++ [HTT_RX_PDEV_MAX_OFDMA_NUM_USER]; /* dBm units */ ++ /* per_chain_rssi_pkt_type: ++ * This field shows what type of rx frame the per-chain RSSI was computed ++ * on, by recording the frame type and sub-type as bit-fields within this ++ * field: ++ * BIT [3 : 0] :- IEEE80211_FC0_TYPE ++ * BIT [7 : 4] :- IEEE80211_FC0_SUBTYPE ++ * BIT [31 : 8] :- Reserved ++ */ ++ u32 per_chain_rssi_pkt_type; ++ s8 rx_per_chain_rssi_in_dbm[HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS] ++ [HTT_RX_PDEV_STATS_NUM_BW_COUNTERS]; ++}; ++ ++/* == RX PDEV/SOC STATS == */ ++struct htt_rx_soc_fw_stats_tlv { ++ u32 fw_reo_ring_data_msdu; ++ u32 fw_to_host_data_msdu_bcmc; ++ u32 fw_to_host_data_msdu_uc; ++ u32 ofld_remote_data_buf_recycle_cnt; ++ u32 ofld_remote_free_buf_indication_cnt; ++ ++ u32 ofld_buf_to_host_data_msdu_uc; ++ u32 reo_fw_ring_to_host_data_msdu_uc; ++ ++ u32 wbm_sw_ring_reap; ++ u32 wbm_forward_to_host_cnt; ++ u32 wbm_target_recycle_cnt; ++ ++ u32 target_refill_ring_recycle_cnt; ++}; ++ ++/* NOTE: Variable length TLV, use length spec to infer array size */ ++struct htt_rx_soc_fw_refill_ring_empty_tlv_v { ++ u32 refill_ring_empty_cnt[0]; /* HTT_RX_STATS_REFILL_MAX_RING */ ++}; ++ ++/* NOTE: Variable length TLV, use length spec to infer array size */ ++struct htt_rx_soc_fw_refill_ring_num_refill_tlv_v { ++ u32 refill_ring_num_refill[0]; /* HTT_RX_STATS_REFILL_MAX_RING */ ++}; ++ ++/* RXDMA error code from WBM released packets */ ++enum htt_rx_rxdma_error_code_enum { ++ HTT_RX_RXDMA_OVERFLOW_ERR = 0, ++ HTT_RX_RXDMA_MPDU_LENGTH_ERR = 1, ++ HTT_RX_RXDMA_FCS_ERR = 2, ++ HTT_RX_RXDMA_DECRYPT_ERR = 3, ++ HTT_RX_RXDMA_TKIP_MIC_ERR = 4, ++ HTT_RX_RXDMA_UNECRYPTED_ERR = 5, ++ HTT_RX_RXDMA_MSDU_LEN_ERR = 6, ++ HTT_RX_RXDMA_MSDU_LIMIT_ERR = 7, ++ HTT_RX_RXDMA_WIFI_PARSE_ERR = 8, ++ HTT_RX_RXDMA_AMSDU_PARSE_ERR = 9, ++ HTT_RX_RXDMA_SA_TIMEOUT_ERR = 10, ++ HTT_RX_RXDMA_DA_TIMEOUT_ERR = 11, ++ HTT_RX_RXDMA_FLOW_TIMEOUT_ERR = 12, ++ HTT_RX_RXDMA_FLUSH_REQUEST = 13, ++ HTT_RX_RXDMA_ERR_CODE_RVSD0 = 14, ++ HTT_RX_RXDMA_ERR_CODE_RVSD1 = 15, ++ ++ /* This MAX_ERR_CODE should not be used in any host/target messages, ++ * so that even though it is defined within a host/target interface ++ * definition header file, it isn't actually part of the host/target ++ * interface, and thus can be modified. ++ */ ++ HTT_RX_RXDMA_MAX_ERR_CODE ++}; ++ ++/* NOTE: Variable length TLV, use length spec to infer array size */ ++struct htt_rx_soc_fw_refill_ring_num_rxdma_err_tlv_v { ++ u32 rxdma_err[0]; /* HTT_RX_RXDMA_MAX_ERR_CODE */ ++}; ++ ++/* REO error code from WBM released packets */ ++enum htt_rx_reo_error_code_enum { ++ HTT_RX_REO_QUEUE_DESC_ADDR_ZERO = 0, ++ HTT_RX_REO_QUEUE_DESC_NOT_VALID = 1, ++ HTT_RX_AMPDU_IN_NON_BA = 2, ++ HTT_RX_NON_BA_DUPLICATE = 3, ++ HTT_RX_BA_DUPLICATE = 4, ++ HTT_RX_REGULAR_FRAME_2K_JUMP = 5, ++ HTT_RX_BAR_FRAME_2K_JUMP = 6, ++ HTT_RX_REGULAR_FRAME_OOR = 7, ++ HTT_RX_BAR_FRAME_OOR = 8, ++ HTT_RX_BAR_FRAME_NO_BA_SESSION = 9, ++ HTT_RX_BAR_FRAME_SN_EQUALS_SSN = 10, ++ HTT_RX_PN_CHECK_FAILED = 11, ++ HTT_RX_2K_ERROR_HANDLING_FLAG_SET = 12, ++ HTT_RX_PN_ERROR_HANDLING_FLAG_SET = 13, ++ HTT_RX_QUEUE_DESCRIPTOR_BLOCKED_SET = 14, ++ HTT_RX_REO_ERR_CODE_RVSD = 15, ++ ++ /* This MAX_ERR_CODE should not be used in any host/target messages, ++ * so that even though it is defined within a host/target interface ++ * definition header file, it isn't actually part of the host/target ++ * interface, and thus can be modified. ++ */ ++ HTT_RX_REO_MAX_ERR_CODE ++}; ++ ++/* NOTE: Variable length TLV, use length spec to infer array size */ ++struct htt_rx_soc_fw_refill_ring_num_reo_err_tlv_v { ++ u32 reo_err[0]; /* HTT_RX_REO_MAX_ERR_CODE */ ++}; ++ ++/* == RX PDEV STATS == */ ++#define HTT_STATS_SUBTYPE_MAX 16 ++ ++struct htt_rx_pdev_fw_stats_tlv { ++ u32 mac_id__word; ++ u32 ppdu_recvd; ++ u32 mpdu_cnt_fcs_ok; ++ u32 mpdu_cnt_fcs_err; ++ u32 tcp_msdu_cnt; ++ u32 tcp_ack_msdu_cnt; ++ u32 udp_msdu_cnt; ++ u32 other_msdu_cnt; ++ u32 fw_ring_mpdu_ind; ++ u32 fw_ring_mgmt_subtype[HTT_STATS_SUBTYPE_MAX]; ++ u32 fw_ring_ctrl_subtype[HTT_STATS_SUBTYPE_MAX]; ++ u32 fw_ring_mcast_data_msdu; ++ u32 fw_ring_bcast_data_msdu; ++ u32 fw_ring_ucast_data_msdu; ++ u32 fw_ring_null_data_msdu; ++ u32 fw_ring_mpdu_drop; ++ u32 ofld_local_data_ind_cnt; ++ u32 ofld_local_data_buf_recycle_cnt; ++ u32 drx_local_data_ind_cnt; ++ u32 drx_local_data_buf_recycle_cnt; ++ u32 local_nondata_ind_cnt; ++ u32 local_nondata_buf_recycle_cnt; ++ ++ u32 fw_status_buf_ring_refill_cnt; ++ u32 fw_status_buf_ring_empty_cnt; ++ u32 fw_pkt_buf_ring_refill_cnt; ++ u32 fw_pkt_buf_ring_empty_cnt; ++ u32 fw_link_buf_ring_refill_cnt; ++ u32 fw_link_buf_ring_empty_cnt; ++ ++ u32 host_pkt_buf_ring_refill_cnt; ++ u32 host_pkt_buf_ring_empty_cnt; ++ u32 mon_pkt_buf_ring_refill_cnt; ++ u32 mon_pkt_buf_ring_empty_cnt; ++ u32 mon_status_buf_ring_refill_cnt; ++ u32 mon_status_buf_ring_empty_cnt; ++ u32 mon_desc_buf_ring_refill_cnt; ++ u32 mon_desc_buf_ring_empty_cnt; ++ u32 mon_dest_ring_update_cnt; ++ u32 mon_dest_ring_full_cnt; ++ ++ u32 rx_suspend_cnt; ++ u32 rx_suspend_fail_cnt; ++ u32 rx_resume_cnt; ++ u32 rx_resume_fail_cnt; ++ u32 rx_ring_switch_cnt; ++ u32 rx_ring_restore_cnt; ++ u32 rx_flush_cnt; ++ u32 rx_recovery_reset_cnt; ++}; ++ ++#define HTT_STATS_PHY_ERR_MAX 43 ++ ++struct htt_rx_pdev_fw_stats_phy_err_tlv { ++ u32 mac_id__word; ++ u32 total_phy_err_cnt; ++ /* Counts of different types of phy errs ++ * The mapping of PHY error types to phy_err array elements is HW dependent. ++ * The only currently-supported mapping is shown below: ++ * ++ * 0 phyrx_err_phy_off Reception aborted due to receiving a PHY_OFF TLV ++ * 1 phyrx_err_synth_off ++ * 2 phyrx_err_ofdma_timing ++ * 3 phyrx_err_ofdma_signal_parity ++ * 4 phyrx_err_ofdma_rate_illegal ++ * 5 phyrx_err_ofdma_length_illegal ++ * 6 phyrx_err_ofdma_restart ++ * 7 phyrx_err_ofdma_service ++ * 8 phyrx_err_ppdu_ofdma_power_drop ++ * 9 phyrx_err_cck_blokker ++ * 10 phyrx_err_cck_timing ++ * 11 phyrx_err_cck_header_crc ++ * 12 phyrx_err_cck_rate_illegal ++ * 13 phyrx_err_cck_length_illegal ++ * 14 phyrx_err_cck_restart ++ * 15 phyrx_err_cck_service ++ * 16 phyrx_err_cck_power_drop ++ * 17 phyrx_err_ht_crc_err ++ * 18 phyrx_err_ht_length_illegal ++ * 19 phyrx_err_ht_rate_illegal ++ * 20 phyrx_err_ht_zlf ++ * 21 phyrx_err_false_radar_ext ++ * 22 phyrx_err_green_field ++ * 23 phyrx_err_bw_gt_dyn_bw ++ * 24 phyrx_err_leg_ht_mismatch ++ * 25 phyrx_err_vht_crc_error ++ * 26 phyrx_err_vht_siga_unsupported ++ * 27 phyrx_err_vht_lsig_len_invalid ++ * 28 phyrx_err_vht_ndp_or_zlf ++ * 29 phyrx_err_vht_nsym_lt_zero ++ * 30 phyrx_err_vht_rx_extra_symbol_mismatch ++ * 31 phyrx_err_vht_rx_skip_group_id0 ++ * 32 phyrx_err_vht_rx_skip_group_id1to62 ++ * 33 phyrx_err_vht_rx_skip_group_id63 ++ * 34 phyrx_err_ofdm_ldpc_decoder_disabled ++ * 35 phyrx_err_defer_nap ++ * 36 phyrx_err_fdomain_timeout ++ * 37 phyrx_err_lsig_rel_check ++ * 38 phyrx_err_bt_collision ++ * 39 phyrx_err_unsupported_mu_feedback ++ * 40 phyrx_err_ppdu_tx_interrupt_rx ++ * 41 phyrx_err_unsupported_cbf ++ * 42 phyrx_err_other ++ */ ++ u32 phy_err[HTT_STATS_PHY_ERR_MAX]; ++}; ++ ++/* NOTE: Variable length TLV, use length spec to infer array size */ ++struct htt_rx_pdev_fw_ring_mpdu_err_tlv_v { ++ /* Num error MPDU for each RxDMA error type */ ++ u32 fw_ring_mpdu_err[0]; /* HTT_RX_STATS_RXDMA_MAX_ERR */ ++}; ++ ++/* NOTE: Variable length TLV, use length spec to infer array size */ ++struct htt_rx_pdev_fw_mpdu_drop_tlv_v { ++ /* Num MPDU dropped */ ++ u32 fw_mpdu_drop[0]; /* HTT_RX_STATS_FW_DROP_REASON_MAX */ ++}; ++ ++#define HTT_PDEV_CCA_STATS_TX_FRAME_INFO_PRESENT (0x1) ++#define HTT_PDEV_CCA_STATS_RX_FRAME_INFO_PRESENT (0x2) ++#define HTT_PDEV_CCA_STATS_RX_CLEAR_INFO_PRESENT (0x4) ++#define HTT_PDEV_CCA_STATS_MY_RX_FRAME_INFO_PRESENT (0x8) ++#define HTT_PDEV_CCA_STATS_USEC_CNT_INFO_PRESENT (0x10) ++#define HTT_PDEV_CCA_STATS_MED_RX_IDLE_INFO_PRESENT (0x20) ++#define HTT_PDEV_CCA_STATS_MED_TX_IDLE_GLOBAL_INFO_PRESENT (0x40) ++#define HTT_PDEV_CCA_STATS_CCA_OBBS_USEC_INFO_PRESENT (0x80) ++ ++struct htt_pdev_stats_cca_counters_tlv { ++ /* Below values are obtained from the HW Cycles counter registers */ ++ u32 tx_frame_usec; ++ u32 rx_frame_usec; ++ u32 rx_clear_usec; ++ u32 my_rx_frame_usec; ++ u32 usec_cnt; ++ u32 med_rx_idle_usec; ++ u32 med_tx_idle_global_usec; ++ u32 cca_obss_usec; ++}; ++ ++struct htt_pdev_cca_stats_hist_v1_tlv { ++ u32 chan_num; ++ /* num of CCA records (Num of htt_pdev_stats_cca_counters_tlv)*/ ++ u32 num_records; ++ u32 valid_cca_counters_bitmap; ++ u32 collection_interval; ++ ++ /* This will be followed by an array which contains the CCA stats ++ * collected in the last N intervals, ++ * if the indication is for last N intervals CCA stats. ++ * Then the pdev_cca_stats[0] element contains the oldest CCA stats ++ * and pdev_cca_stats[N-1] will have the most recent CCA stats. ++ * htt_pdev_stats_cca_counters_tlv cca_hist_tlv[1]; ++ */ ++}; ++ ++struct htt_pdev_stats_twt_session_tlv { ++ u32 vdev_id; ++ struct htt_mac_addr peer_mac; ++ u32 flow_id_flags; ++ ++ /* TWT_DIALOG_ID_UNAVAILABLE is used ++ * when TWT session is not initiated by host ++ */ ++ u32 dialog_id; ++ u32 wake_dura_us; ++ u32 wake_intvl_us; ++ u32 sp_offset_us; ++}; ++ ++struct htt_pdev_stats_twt_sessions_tlv { ++ u32 pdev_id; ++ u32 num_sessions; ++ struct htt_pdev_stats_twt_session_tlv twt_session[]; ++}; ++ ++enum htt_rx_reo_resource_sample_id_enum { ++ /* Global link descriptor queued in REO */ ++ HTT_RX_REO_RESOURCE_GLOBAL_LINK_DESC_COUNT_0 = 0, ++ HTT_RX_REO_RESOURCE_GLOBAL_LINK_DESC_COUNT_1 = 1, ++ HTT_RX_REO_RESOURCE_GLOBAL_LINK_DESC_COUNT_2 = 2, ++ /*Number of queue descriptors of this aging group */ ++ HTT_RX_REO_RESOURCE_BUFFERS_USED_AC0 = 3, ++ HTT_RX_REO_RESOURCE_BUFFERS_USED_AC1 = 4, ++ HTT_RX_REO_RESOURCE_BUFFERS_USED_AC2 = 5, ++ HTT_RX_REO_RESOURCE_BUFFERS_USED_AC3 = 6, ++ /* Total number of MSDUs buffered in AC */ ++ HTT_RX_REO_RESOURCE_AGING_NUM_QUEUES_AC0 = 7, ++ HTT_RX_REO_RESOURCE_AGING_NUM_QUEUES_AC1 = 8, ++ HTT_RX_REO_RESOURCE_AGING_NUM_QUEUES_AC2 = 9, ++ HTT_RX_REO_RESOURCE_AGING_NUM_QUEUES_AC3 = 10, ++ ++ HTT_RX_REO_RESOURCE_STATS_MAX = 16 ++}; ++ ++struct htt_rx_reo_resource_stats_tlv_v { ++ /* Variable based on the Number of records. HTT_RX_REO_RESOURCE_STATS_MAX */ ++ u32 sample_id; ++ u32 total_max; ++ u32 total_avg; ++ u32 total_sample; ++ u32 non_zeros_avg; ++ u32 non_zeros_sample; ++ u32 last_non_zeros_max; ++ u32 last_non_zeros_min; ++ u32 last_non_zeros_avg; ++ u32 last_non_zeros_sample; ++}; ++ ++/* == TX SOUNDING STATS == */ ++ ++enum htt_txbf_sound_steer_modes { ++ HTT_IMPLICIT_TXBF_STEER_STATS = 0, ++ HTT_EXPLICIT_TXBF_SU_SIFS_STEER_STATS = 1, ++ HTT_EXPLICIT_TXBF_SU_RBO_STEER_STATS = 2, ++ HTT_EXPLICIT_TXBF_MU_SIFS_STEER_STATS = 3, ++ HTT_EXPLICIT_TXBF_MU_RBO_STEER_STATS = 4, ++ HTT_TXBF_MAX_NUM_OF_MODES = 5 ++}; ++ ++enum htt_stats_sounding_tx_mode { ++ HTT_TX_AC_SOUNDING_MODE = 0, ++ HTT_TX_AX_SOUNDING_MODE = 1, ++}; ++ ++struct htt_tx_sounding_stats_tlv { ++ u32 tx_sounding_mode; /* HTT_TX_XX_SOUNDING_MODE */ ++ /* Counts number of soundings for all steering modes in each bw */ ++ u32 cbf_20[HTT_TXBF_MAX_NUM_OF_MODES]; ++ u32 cbf_40[HTT_TXBF_MAX_NUM_OF_MODES]; ++ u32 cbf_80[HTT_TXBF_MAX_NUM_OF_MODES]; ++ u32 cbf_160[HTT_TXBF_MAX_NUM_OF_MODES]; ++ /* ++ * The sounding array is a 2-D array stored as an 1-D array of ++ * u32. The stats for a particular user/bw combination is ++ * referenced with the following: ++ * ++ * sounding[(user* max_bw) + bw] ++ * ++ * ... where max_bw == 4 for 160mhz ++ */ ++ u32 sounding[HTT_TX_NUM_OF_SOUNDING_STATS_WORDS]; ++}; ++ ++struct htt_pdev_obss_pd_stats_tlv { ++ u32 num_obss_tx_ppdu_success; ++ u32 num_obss_tx_ppdu_failure; ++}; ++ ++struct htt_ring_backpressure_stats_tlv { ++ u32 pdev_id; ++ u32 current_head_idx; ++ u32 current_tail_idx; ++ u32 num_htt_msgs_sent; ++ /* Time in milliseconds for which the ring has been in ++ * its current backpressure condition ++ */ ++ u32 backpressure_time_ms; ++ /* backpressure_hist - histogram showing how many times ++ * different degrees of backpressure duration occurred: ++ * Index 0 indicates the number of times ring was ++ * continuously in backpressure state for 100 - 200ms. ++ * Index 1 indicates the number of times ring was ++ * continuously in backpressure state for 200 - 300ms. ++ * Index 2 indicates the number of times ring was ++ * continuously in backpressure state for 300 - 400ms. ++ * Index 3 indicates the number of times ring was ++ * continuously in backpressure state for 400 - 500ms. ++ * Index 4 indicates the number of times ring was ++ * continuously in backpressure state beyond 500ms. ++ */ ++ u32 backpressure_hist[5]; ++}; ++ ++#ifdef CPTCFG_ATH12K_DEBUGFS ++ ++void ath12k_debugfs_htt_stats_init(struct ath12k *ar); ++void ath12k_debugfs_htt_ext_stats_handler(struct ath12k_base *ab, ++ struct sk_buff *skb); ++int ath12k_debugfs_htt_stats_req(struct ath12k *ar); ++ ++#else /* CPTCFG_ATH12K_DEBUGFS */ ++ ++static inline void ath12k_debugfs_htt_stats_init(struct ath12k *ar) ++{ ++} ++ ++static inline void ath12k_debugfs_htt_ext_stats_handler(struct ath12k_base *ab, ++ struct sk_buff *skb) ++{ ++} ++ ++static inline int ath12k_debugfs_htt_stats_req(struct ath12k *ar) ++{ ++ return 0; ++} ++ ++#endif /* CPTCFG_ATH12K_DEBUGFS */ ++ ++#endif +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/debugfs_sta.c +@@ -0,0 +1,1081 @@ ++// SPDX-License-Identifier: BSD-3-Clause-Clear ++/* ++ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include ++ ++#include "debugfs_sta.h" ++#include "core.h" ++#include "peer.h" ++#include "debug.h" ++#include "dp_tx.h" ++#include "debugfs_htt_stats.h" ++ ++void ath12k_debugfs_sta_add_tx_stats(struct ath12k_sta *arsta, ++ struct ath12k_per_peer_tx_stats *peer_stats, ++ u8 legacy_rate_idx) ++{ ++ struct rate_info *txrate = &arsta->txrate; ++ struct ath12k_htt_tx_stats *tx_stats; ++ int gi, mcs, bw, nss, ru_type, ppdu_type; ++ ++ if (!arsta->tx_stats) ++ return; ++ ++ tx_stats = arsta->tx_stats; ++ gi = FIELD_GET(RATE_INFO_FLAGS_SHORT_GI, arsta->txrate.flags); ++ mcs = txrate->mcs; ++ bw = ath12k_mac_mac80211_bw_to_ath12k_bw(txrate->bw); ++ nss = txrate->nss - 1; ++ ++#define STATS_OP_FMT(name) tx_stats->stats[ATH12K_STATS_TYPE_##name] ++ ++ if (txrate->flags & RATE_INFO_FLAGS_HE_MCS) { ++ STATS_OP_FMT(SUCC).he[0][mcs] += peer_stats->succ_bytes; ++ STATS_OP_FMT(SUCC).he[1][mcs] += peer_stats->succ_pkts; ++ STATS_OP_FMT(FAIL).he[0][mcs] += peer_stats->failed_bytes; ++ STATS_OP_FMT(FAIL).he[1][mcs] += peer_stats->failed_pkts; ++ STATS_OP_FMT(RETRY).he[0][mcs] += peer_stats->retry_bytes; ++ STATS_OP_FMT(RETRY).he[1][mcs] += peer_stats->retry_pkts; ++ } else if (txrate->flags & RATE_INFO_FLAGS_VHT_MCS) { ++ STATS_OP_FMT(SUCC).vht[0][mcs] += peer_stats->succ_bytes; ++ STATS_OP_FMT(SUCC).vht[1][mcs] += peer_stats->succ_pkts; ++ STATS_OP_FMT(FAIL).vht[0][mcs] += peer_stats->failed_bytes; ++ STATS_OP_FMT(FAIL).vht[1][mcs] += peer_stats->failed_pkts; ++ STATS_OP_FMT(RETRY).vht[0][mcs] += peer_stats->retry_bytes; ++ STATS_OP_FMT(RETRY).vht[1][mcs] += peer_stats->retry_pkts; ++ } else if (txrate->flags & RATE_INFO_FLAGS_MCS) { ++ STATS_OP_FMT(SUCC).ht[0][mcs] += peer_stats->succ_bytes; ++ STATS_OP_FMT(SUCC).ht[1][mcs] += peer_stats->succ_pkts; ++ STATS_OP_FMT(FAIL).ht[0][mcs] += peer_stats->failed_bytes; ++ STATS_OP_FMT(FAIL).ht[1][mcs] += peer_stats->failed_pkts; ++ STATS_OP_FMT(RETRY).ht[0][mcs] += peer_stats->retry_bytes; ++ STATS_OP_FMT(RETRY).ht[1][mcs] += peer_stats->retry_pkts; ++ } else { ++ mcs = legacy_rate_idx; ++ ++ STATS_OP_FMT(SUCC).legacy[0][mcs] += peer_stats->succ_bytes; ++ STATS_OP_FMT(SUCC).legacy[1][mcs] += peer_stats->succ_pkts; ++ STATS_OP_FMT(FAIL).legacy[0][mcs] += peer_stats->failed_bytes; ++ STATS_OP_FMT(FAIL).legacy[1][mcs] += peer_stats->failed_pkts; ++ STATS_OP_FMT(RETRY).legacy[0][mcs] += peer_stats->retry_bytes; ++ STATS_OP_FMT(RETRY).legacy[1][mcs] += peer_stats->retry_pkts; ++ } ++ ++ ppdu_type = peer_stats->ppdu_type; ++ if ((ppdu_type == HTT_PPDU_STATS_PPDU_TYPE_MU_OFDMA || ++ ppdu_type == HTT_PPDU_STATS_PPDU_TYPE_MU_MIMO_OFDMA) && ++ (txrate->flags & RATE_INFO_FLAGS_HE_MCS)) { ++ ru_type = peer_stats->ru_tones; ++ ++ if (ru_type <= NL80211_RATE_INFO_HE_RU_ALLOC_996) { ++ STATS_OP_FMT(SUCC).ru_loc[0][ru_type] += peer_stats->succ_bytes; ++ STATS_OP_FMT(SUCC).ru_loc[1][ru_type] += peer_stats->succ_pkts; ++ STATS_OP_FMT(FAIL).ru_loc[0][ru_type] += peer_stats->failed_bytes; ++ STATS_OP_FMT(FAIL).ru_loc[1][ru_type] += peer_stats->failed_pkts; ++ STATS_OP_FMT(RETRY).ru_loc[0][ru_type] += peer_stats->retry_bytes; ++ STATS_OP_FMT(RETRY).ru_loc[1][ru_type] += peer_stats->retry_pkts; ++ if (peer_stats->is_ampdu) { ++ STATS_OP_FMT(AMPDU).ru_loc[0][ru_type] += ++ peer_stats->succ_bytes + peer_stats->retry_bytes; ++ STATS_OP_FMT(AMPDU).ru_loc[1][ru_type] += ++ peer_stats->succ_pkts + peer_stats->retry_pkts; ++ } ++ } ++ } ++ ++ if (ppdu_type < HTT_PPDU_STATS_PPDU_TYPE_MAX) { ++ STATS_OP_FMT(SUCC).transmit_type[0][ppdu_type] += peer_stats->succ_bytes; ++ STATS_OP_FMT(SUCC).transmit_type[1][ppdu_type] += peer_stats->succ_pkts; ++ STATS_OP_FMT(FAIL).transmit_type[0][ppdu_type] += ++ peer_stats->failed_bytes; ++ STATS_OP_FMT(FAIL).transmit_type[1][ppdu_type] += peer_stats->failed_pkts; ++ STATS_OP_FMT(RETRY).transmit_type[0][ppdu_type] += ++ peer_stats->retry_bytes; ++ STATS_OP_FMT(RETRY).transmit_type[1][ppdu_type] += peer_stats->retry_pkts; ++ if (peer_stats->is_ampdu) { ++ STATS_OP_FMT(AMPDU).transmit_type[0][ppdu_type] += ++ peer_stats->succ_bytes + peer_stats->retry_bytes; ++ STATS_OP_FMT(AMPDU).transmit_type[1][ppdu_type] += ++ peer_stats->succ_pkts + peer_stats->retry_pkts; ++ } ++ } ++ ++ if (peer_stats->is_ampdu) { ++ tx_stats->ba_fails += peer_stats->ba_fails; ++ ++ if (txrate->flags & RATE_INFO_FLAGS_HE_MCS) { ++ STATS_OP_FMT(AMPDU).he[0][mcs] += ++ peer_stats->succ_bytes + peer_stats->retry_bytes; ++ STATS_OP_FMT(AMPDU).he[1][mcs] += ++ peer_stats->succ_pkts + peer_stats->retry_pkts; ++ } else if (txrate->flags & RATE_INFO_FLAGS_MCS) { ++ STATS_OP_FMT(AMPDU).ht[0][mcs] += ++ peer_stats->succ_bytes + peer_stats->retry_bytes; ++ STATS_OP_FMT(AMPDU).ht[1][mcs] += ++ peer_stats->succ_pkts + peer_stats->retry_pkts; ++ } else { ++ STATS_OP_FMT(AMPDU).vht[0][mcs] += ++ peer_stats->succ_bytes + peer_stats->retry_bytes; ++ STATS_OP_FMT(AMPDU).vht[1][mcs] += ++ peer_stats->succ_pkts + peer_stats->retry_pkts; ++ } ++ STATS_OP_FMT(AMPDU).bw[0][bw] += ++ peer_stats->succ_bytes + peer_stats->retry_bytes; ++ STATS_OP_FMT(AMPDU).nss[0][nss] += ++ peer_stats->succ_bytes + peer_stats->retry_bytes; ++ STATS_OP_FMT(AMPDU).gi[0][gi] += ++ peer_stats->succ_bytes + peer_stats->retry_bytes; ++ STATS_OP_FMT(AMPDU).bw[1][bw] += ++ peer_stats->succ_pkts + peer_stats->retry_pkts; ++ STATS_OP_FMT(AMPDU).nss[1][nss] += ++ peer_stats->succ_pkts + peer_stats->retry_pkts; ++ STATS_OP_FMT(AMPDU).gi[1][gi] += ++ peer_stats->succ_pkts + peer_stats->retry_pkts; ++ } else { ++ tx_stats->ack_fails += peer_stats->ba_fails; ++ } ++ ++ STATS_OP_FMT(SUCC).bw[0][bw] += peer_stats->succ_bytes; ++ STATS_OP_FMT(SUCC).nss[0][nss] += peer_stats->succ_bytes; ++ STATS_OP_FMT(SUCC).gi[0][gi] += peer_stats->succ_bytes; ++ ++ STATS_OP_FMT(SUCC).bw[1][bw] += peer_stats->succ_pkts; ++ STATS_OP_FMT(SUCC).nss[1][nss] += peer_stats->succ_pkts; ++ STATS_OP_FMT(SUCC).gi[1][gi] += peer_stats->succ_pkts; ++ ++ STATS_OP_FMT(FAIL).bw[0][bw] += peer_stats->failed_bytes; ++ STATS_OP_FMT(FAIL).nss[0][nss] += peer_stats->failed_bytes; ++ STATS_OP_FMT(FAIL).gi[0][gi] += peer_stats->failed_bytes; ++ ++ STATS_OP_FMT(FAIL).bw[1][bw] += peer_stats->failed_pkts; ++ STATS_OP_FMT(FAIL).nss[1][nss] += peer_stats->failed_pkts; ++ STATS_OP_FMT(FAIL).gi[1][gi] += peer_stats->failed_pkts; ++ ++ STATS_OP_FMT(RETRY).bw[0][bw] += peer_stats->retry_bytes; ++ STATS_OP_FMT(RETRY).nss[0][nss] += peer_stats->retry_bytes; ++ STATS_OP_FMT(RETRY).gi[0][gi] += peer_stats->retry_bytes; ++ ++ STATS_OP_FMT(RETRY).bw[1][bw] += peer_stats->retry_pkts; ++ STATS_OP_FMT(RETRY).nss[1][nss] += peer_stats->retry_pkts; ++ STATS_OP_FMT(RETRY).gi[1][gi] += peer_stats->retry_pkts; ++ ++ tx_stats->tx_duration += peer_stats->duration; ++ ++ tx_stats->ru_start = peer_stats->ru_start; ++ tx_stats->ru_tones = peer_stats->ru_tones; ++ ++ if (peer_stats->mu_grpid <= MAX_MU_GROUP_ID && ++ peer_stats->ppdu_type != HTT_PPDU_STATS_PPDU_TYPE_SU) { ++ if (peer_stats->mu_grpid & (MAX_MU_GROUP_ID - 1)) ++ tx_stats->mu_group[peer_stats->mu_grpid] = ++ (peer_stats->mu_pos + 1); ++ } ++} ++ ++void ath12k_debugfs_sta_update_txcompl(struct ath12k *ar, ++ struct sk_buff *msdu, ++ struct hal_tx_status *ts) ++{ ++ struct ath12k_base *ab = ar->ab; ++ struct ath12k_per_peer_tx_stats *peer_stats = &ar->cached_stats; ++ enum hal_tx_rate_stats_pkt_type pkt_type; ++ enum hal_tx_rate_stats_sgi sgi; ++ enum hal_tx_rate_stats_bw bw; ++ struct ath12k_peer *peer; ++ struct ath12k_sta *arsta; ++ struct ieee80211_sta *sta; ++ u16 num_tones_in_ru; ++ u16 rate; ++ u8 rate_idx = 0; ++ int ret; ++ u8 mcs; ++ ++ rcu_read_lock(); ++ spin_lock_bh(&ab->base_lock); ++ peer = ath12k_peer_find_by_id(ab, ts->peer_id); ++ if (!peer || !peer->sta) { ++ ath12k_warn(ab, "failed to find the peer\n"); ++ spin_unlock_bh(&ab->base_lock); ++ rcu_read_unlock(); ++ return; ++ } ++ ++ sta = peer->sta; ++ arsta = (struct ath12k_sta *)sta->drv_priv; ++ ++ memset(&arsta->txrate, 0, sizeof(arsta->txrate)); ++ pkt_type = FIELD_GET(HAL_TX_RATE_STATS_INFO0_PKT_TYPE, ++ ts->rate_stats); ++ mcs = FIELD_GET(HAL_TX_RATE_STATS_INFO0_MCS, ++ ts->rate_stats); ++ sgi = FIELD_GET(HAL_TX_RATE_STATS_INFO0_SGI, ++ ts->rate_stats); ++ bw = FIELD_GET(HAL_TX_RATE_STATS_INFO0_BW, ts->rate_stats); ++ num_tones_in_ru = FIELD_GET(HAL_TX_RATE_STATS_INFO0_TONES_IN_RU, ++ ts->rate_stats); ++ ++ if (pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11A || ++ pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11B) { ++ ret = ath12k_mac_hw_ratecode_to_legacy_rate(mcs, ++ pkt_type, ++ &rate_idx, ++ &rate); ++ if (ret < 0) ++ goto err_out; ++ arsta->txrate.legacy = rate; ++ } else if (pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11N) { ++ if (mcs > 7) { ++ ath12k_warn(ab, "Invalid HT mcs index %d\n", mcs); ++ goto err_out; ++ } ++ ++ arsta->txrate.mcs = mcs + 8 * (arsta->last_txrate.nss - 1); ++ arsta->txrate.flags = RATE_INFO_FLAGS_MCS; ++ if (sgi) ++ arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; ++ } else if (pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11AC) { ++ if (mcs > 9) { ++ ath12k_warn(ab, "Invalid VHT mcs index %d\n", mcs); ++ goto err_out; ++ } ++ ++ arsta->txrate.mcs = mcs; ++ arsta->txrate.flags = RATE_INFO_FLAGS_VHT_MCS; ++ if (sgi) ++ arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; ++ } else if (pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11AX) { ++ arsta->txrate.mcs = mcs; ++ arsta->txrate.flags = RATE_INFO_FLAGS_HE_MCS; ++ arsta->txrate.he_gi = ath12k_he_gi_to_nl80211_he_gi(sgi); ++ arsta->txrate.he_ru_alloc = ++ ath12k_he_ru_tones_to_nl80211_he_ru_alloc(num_tones_in_ru); ++ } ++ ++ arsta->txrate.nss = arsta->last_txrate.nss; ++ arsta->txrate.bw = ath12k_mac_bw_to_mac80211_bw(bw); ++ ++ /* Currently only OFDMA flag is available in tx complettion status ++ * to indicate MUOFDMA ppdu type. Use SU ppdu type as of now to ++ * indicate both SU/MU MIMO for failed/retry count. ++ */ ++ if (ts->flags & HAL_TX_STATUS_FLAGS_OFDMA) ++ peer_stats->ppdu_type = HTT_PPDU_STATS_PPDU_TYPE_MU_OFDMA; ++ else ++ peer_stats->ppdu_type = HTT_PPDU_STATS_PPDU_TYPE_SU; ++ ++ peer_stats->ru_tones = arsta->txrate.he_ru_alloc; ++ ++ ath12k_debugfs_sta_add_tx_stats(arsta, peer_stats, rate_idx); ++ ++err_out: ++ spin_unlock_bh(&ab->base_lock); ++ rcu_read_unlock(); ++} ++ ++static ssize_t ath12k_dbg_sta_dump_tx_stats(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ieee80211_sta *sta = file->private_data; ++ struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k *ar = arsta->arvif->ar; ++ struct ath12k_htt_data_stats *stats; ++ static const char *str_name[ATH12K_STATS_TYPE_MAX] = {"success", "fail", ++ "retry", "ampdu"}; ++ static const char *str[ATH12K_COUNTER_TYPE_MAX] = {"bytes", "packets"}; ++ int len = 0, i, j, k, retval = 0; ++ const int size = 2 * 4096; ++ char *buf, mu_group_id[MAX_MU_GROUP_LENGTH] = {0}; ++ u32 index; ++ static const char *fields[HAL_WBM_REL_HTT_TX_COMP_STATUS_MAX] = { ++ [HAL_WBM_REL_HTT_TX_COMP_STATUS_OK] = "Acked pkt count", ++ [HAL_WBM_REL_HTT_TX_COMP_STATUS_TTL] = "Status ttl pkt count", ++ [HAL_WBM_REL_HTT_TX_COMP_STATUS_DROP] = "Dropped pkt count", ++ [HAL_WBM_REL_HTT_TX_COMP_STATUS_REINJ] = "Reinj pkt count", ++ [HAL_WBM_REL_HTT_TX_COMP_STATUS_INSPECT] = "Inspect pkt count", ++ [HAL_WBM_REL_HTT_TX_COMP_STATUS_MEC_NOTIFY] = ++ "MEC notify pkt count" ++ }; ++ int idx; ++ ++ if (!arsta->tx_stats || !arsta->wbm_tx_stats) ++ return -ENOENT; ++ ++ buf = kzalloc(size, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ spin_lock_bh(&ar->data_lock); ++ for (k = 0; k < ATH12K_STATS_TYPE_MAX; k++) { ++ for (j = 0; j < ATH12K_COUNTER_TYPE_MAX; j++) { ++ stats = &arsta->tx_stats->stats[k]; ++ len += scnprintf(buf + len, size - len, "%s_%s\n", ++ str_name[k], ++ str[j]); ++ len += scnprintf(buf + len, size - len, "==========\n"); ++ len += scnprintf(buf + len, size - len, ++ " HE MCS %s\n\t", ++ str[j]); ++ for (i = 0; i < ATH12K_HE_MCS_NUM; i++) ++ len += scnprintf(buf + len, size - len, ++ "%llu ", ++ stats->he[j][i]); ++ len += scnprintf(buf + len, size - len, "\n"); ++ len += scnprintf(buf + len, size - len, ++ " VHT MCS %s\n\t", ++ str[j]); ++ for (i = 0; i < ATH12K_VHT_MCS_NUM; i++) ++ len += scnprintf(buf + len, size - len, ++ "%llu ", ++ stats->vht[j][i]); ++ len += scnprintf(buf + len, size - len, "\n"); ++ len += scnprintf(buf + len, size - len, " HT MCS %s\n\t", ++ str[j]); ++ for (i = 0; i < ATH12K_HT_MCS_NUM; i++) ++ len += scnprintf(buf + len, size - len, ++ "%llu ", stats->ht[j][i]); ++ len += scnprintf(buf + len, size - len, "\n"); ++ len += scnprintf(buf + len, size - len, ++ " BW %s (20,40,80,160,320 MHz)\n", str[j]); ++ len += scnprintf(buf + len, size - len, ++ "\t%llu %llu %llu %llu %llu\n", ++ stats->bw[j][0], stats->bw[j][1], ++ stats->bw[j][2], stats->bw[j][3], ++ stats->bw[j][4]); ++ len += scnprintf(buf + len, size - len, ++ " NSS %s (1x1,2x2,3x3,4x4)\n", str[j]); ++ len += scnprintf(buf + len, size - len, ++ "\t%llu %llu %llu %llu\n", ++ stats->nss[j][0], stats->nss[j][1], ++ stats->nss[j][2], stats->nss[j][3]); ++ len += scnprintf(buf + len, size - len, ++ " GI %s (0.4us,0.8us,1.6us,3.2us)\n", ++ str[j]); ++ len += scnprintf(buf + len, size - len, ++ "\t%llu %llu %llu %llu\n", ++ stats->gi[j][0], stats->gi[j][1], ++ stats->gi[j][2], stats->gi[j][3]); ++ len += scnprintf(buf + len, size - len, ++ " legacy rate %s (1,2 ... Mbps)\n ", ++ str[j]); ++ for (i = 0; i < ATH12K_LEGACY_NUM; i++) ++ len += scnprintf(buf + len, size - len, "%llu ", ++ stats->legacy[j][i]); ++ ++ len += scnprintf(buf + len, size - len, "\n ru %s:\n", str[j]); ++ len += scnprintf(buf + len, size - len, ++ "\tru 26: %llu\n", stats->ru_loc[j][0]); ++ len += scnprintf(buf + len, size - len, ++ "\tru 52: %llu\n", stats->ru_loc[j][1]); ++ len += scnprintf(buf + len, size - len, ++ "\tru 106: %llu\n", stats->ru_loc[j][2]); ++ len += scnprintf(buf + len, size - len, ++ "\tru 242: %llu\n", stats->ru_loc[j][3]); ++ len += scnprintf(buf + len, size - len, ++ "\tru 484: %llu\n", stats->ru_loc[j][4]); ++ len += scnprintf(buf + len, size - len, ++ "\tru 996: %llu\n", stats->ru_loc[j][5]); ++ ++ len += scnprintf(buf + len, size - len, ++ " ppdu type %s:\n", str[j]); ++ if (k == ATH12K_STATS_TYPE_FAIL || ++ k == ATH12K_STATS_TYPE_RETRY) { ++ len += scnprintf(buf + len, size - len, ++ "\tSU/MIMO: %llu\n", ++ stats->transmit_type[j][0]); ++ len += scnprintf(buf + len, size - len, ++ "\tOFDMA/OFDMA_MIMO: %llu\n", ++ stats->transmit_type[j][2]); ++ } else { ++ len += scnprintf(buf + len, size - len, ++ "\tSU: %llu\n", ++ stats->transmit_type[j][0]); ++ len += scnprintf(buf + len, size - len, ++ "\tMIMO: %llu\n", ++ stats->transmit_type[j][1]); ++ len += scnprintf(buf + len, size - len, ++ "\tOFDMA: %llu\n", ++ stats->transmit_type[j][2]); ++ len += scnprintf(buf + len, size - len, ++ "\tOFDMA_MIMO: %llu\n", ++ stats->transmit_type[j][3]); ++ } ++ } ++ } ++ ++ len += scnprintf(buf + len, size - len, "\n"); ++ ++ for (i = 0; i < MAX_MU_GROUP_ID;) { ++ index = 0; ++ for (j = 0; j < MAX_MU_GROUP_SHOW && i < MAX_MU_GROUP_ID; j++) { ++ index += snprintf(&mu_group_id[index], ++ MAX_MU_GROUP_LENGTH - index, ++ " %d", ++ arsta->tx_stats->mu_group[i]); ++ i++; ++ } ++ len += scnprintf(buf + len, size - len, ++ "User position list for GID %02d->%d: [%s]\n", ++ i - MAX_MU_GROUP_SHOW, i - 1, mu_group_id); ++ } ++ len += scnprintf(buf + len, size - len, ++ "\nLast Packet RU index [%d], Size [%d]\n", ++ arsta->tx_stats->ru_start, arsta->tx_stats->ru_tones); ++ ++ len += scnprintf(buf + len, size - len, ++ "\nTX duration\n %llu usecs\n", ++ arsta->tx_stats->tx_duration); ++ len += scnprintf(buf + len, size - len, ++ "BA fails\n %llu\n", arsta->tx_stats->ba_fails); ++ len += scnprintf(buf + len, size - len, ++ "ack fails\n %llu\n\n", arsta->tx_stats->ack_fails); ++ ++ len += scnprintf(buf + len, size - len, ++ "WBM tx completion stats of data pkts :\n"); ++ ++ for (idx = 0; idx <= HAL_WBM_REL_HTT_TX_COMP_STATUS_MEC_NOTIFY; idx++) { ++ len += scnprintf(buf + len, size - len, ++ "%-23s : %llu\n", ++ fields[idx], ++ arsta->wbm_tx_stats->wbm_tx_comp_stats[idx]); ++ } ++ ++ spin_unlock_bh(&ar->data_lock); ++ ++ if (len > size) ++ len = size; ++ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ kfree(buf); ++ ++ mutex_unlock(&ar->conf_mutex); ++ return retval; ++} ++ ++static const struct file_operations fops_tx_stats = { ++ .read = ath12k_dbg_sta_dump_tx_stats, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++static ssize_t ath12k_dbg_sta_dump_rx_stats(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ieee80211_sta *sta = file->private_data; ++ struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k *ar = arsta->arvif->ar; ++ struct ath12k_rx_peer_stats *rx_stats = arsta->rx_stats; ++ int len = 0, i, retval = 0; ++ const int size = 4 * 4096; ++ char *buf; ++ int he_rates_avail; ++ int rate_table_len; ++ static const char *legacy_rate_str[HAL_RX_MAX_NUM_LEGACY_RATES] = { ++ "1Mbps", "2Mbps", "5.5Mbps", "6Mbps", ++ "9Mbps", "11Mbps", "12Mbps", "18Mbps", ++ "24Mbps", "36 Mbps", "48Mbps", "54Mbps"}; ++ if (!rx_stats) ++ return -ENOENT; ++ ++ buf = kzalloc(size, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ he_rates_avail = (rx_stats->pream_cnt[HAL_RX_PREAMBLE_11AX] > 1) ? 1 : 0; ++ rate_table_len = he_rates_avail ? ATH12K_RX_RATE_TABLE_11AX_NUM : ++ ATH12K_RX_RATE_TABLE_NUM; ++ mutex_lock(&ar->conf_mutex); ++ spin_lock_bh(&ar->ab->base_lock); ++ ++ len += scnprintf(buf + len, size - len, "RX peer stats:\n"); ++ len += scnprintf(buf + len, size - len, "Num of MSDUs: %llu\n", ++ rx_stats->num_msdu); ++ len += scnprintf(buf + len, size - len, "Num of MSDUs with TCP L4: %llu\n", ++ rx_stats->tcp_msdu_count); ++ len += scnprintf(buf + len, size - len, "Num of MSDUs with UDP L4: %llu\n", ++ rx_stats->udp_msdu_count); ++ len += scnprintf(buf + len, size - len, "Num of MSDUs part of AMPDU: %llu\n", ++ rx_stats->ampdu_msdu_count); ++ len += scnprintf(buf + len, size - len, "Num of MSDUs not part of AMPDU: %llu\n", ++ rx_stats->non_ampdu_msdu_count); ++ len += scnprintf(buf + len, size - len, "Num of MSDUs using STBC: %llu\n", ++ rx_stats->stbc_count); ++ len += scnprintf(buf + len, size - len, "Num of MSDUs beamformed: %llu\n", ++ rx_stats->beamformed_count); ++ len += scnprintf(buf + len, size - len, "Num of MPDUs with FCS ok: %llu\n", ++ rx_stats->num_mpdu_fcs_ok); ++ len += scnprintf(buf + len, size - len, "Num of MPDUs with FCS error: %llu\n", ++ rx_stats->num_mpdu_fcs_err); ++ len += scnprintf(buf + len, size - len, ++ "preamble: 11A %llu 11B %llu 11N %llu 11AC %llu 11AX %llu\n", ++ rx_stats->pream_cnt[0], rx_stats->pream_cnt[1], ++ rx_stats->pream_cnt[2], rx_stats->pream_cnt[3], ++ rx_stats->pream_cnt[4]); ++ len += scnprintf(buf + len, size - len, ++ "reception type: SU %llu MU_MIMO %llu MU_OFDMA %llu MU_OFDMA_MIMO %llu\n", ++ rx_stats->reception_type[0], rx_stats->reception_type[1], ++ rx_stats->reception_type[2], rx_stats->reception_type[3]); ++ len += scnprintf(buf + len, size - len, "TID(0-15) Legacy TID(16):"); ++ for (i = 0; i <= IEEE80211_NUM_TIDS; i++) ++ len += scnprintf(buf + len, size - len, "%llu ", rx_stats->tid_count[i]); ++ len += scnprintf(buf + len, size - len, "\nRX Duration:%llu\n", ++ rx_stats->rx_duration); ++ ++ len += scnprintf(buf + len, size - len, "\nRX success packet stats:\n"); ++ len += scnprintf(buf + len, size - len, "\nHE packet stats:\n"); ++ for (i = 0; i <= HAL_RX_MAX_MCS_HE; i++) ++ len += scnprintf(buf + len, size - len, "MCS %d: %llu%s", i, ++ rx_stats->pkt_stats.he_mcs_count[i], ++ (i + 1) % 6 ? "\t" : "\n"); ++ len += scnprintf(buf + len, size - len, "\nVHT packet stats:\n"); ++ for (i = 0; i <= HAL_RX_MAX_MCS_VHT; i++) ++ len += scnprintf(buf + len, size - len, "MCS %d: %llu%s", i, ++ rx_stats->pkt_stats.vht_mcs_count[i], ++ (i + 1) % 5 ? "\t" : "\n"); ++ len += scnprintf(buf + len, size - len, "\nHT packet stats:\n"); ++ for (i = 0; i <= HAL_RX_MAX_MCS_HT; i++) ++ len += scnprintf(buf + len, size - len, "MCS %d: %llu%s", i, ++ rx_stats->pkt_stats.ht_mcs_count[i], ++ (i + 1) % 8 ? "\t" : "\n"); ++ len += scnprintf(buf + len, size - len, "\nLegacy rate packet stats:\n"); ++ for (i = 0; i < HAL_RX_MAX_NUM_LEGACY_RATES; i++) ++ len += scnprintf(buf + len, size - len, "%s: %llu%s", legacy_rate_str[i], ++ rx_stats->pkt_stats.legacy_count[i], ++ (i + 1) % 4 ? "\t" : "\n"); ++ len += scnprintf(buf + len, size - len, "\nNSS packet stats:\n"); ++ for (i = 0; i < HAL_RX_MAX_NSS; i++) ++ len += scnprintf(buf + len, size - len, "%dx%d: %llu ", i + 1, i + 1, ++ rx_stats->pkt_stats.nss_count[i]); ++ len += scnprintf(buf + len, size - len, ++ "\n\nGI: 0.8us %llu 0.4us %llu 1.6us %llu 3.2us %llu\n", ++ rx_stats->pkt_stats.gi_count[0], ++ rx_stats->pkt_stats.gi_count[1], ++ rx_stats->pkt_stats.gi_count[2], ++ rx_stats->pkt_stats.gi_count[3]); ++ len += scnprintf(buf + len, size - len, ++ "BW: 20Mhz %llu 40Mhz %llu 80Mhz %llu 160Mhz %llu 320Mhz %llu\n", ++ rx_stats->pkt_stats.bw_count[0], ++ rx_stats->pkt_stats.bw_count[1], ++ rx_stats->pkt_stats.bw_count[2], ++ rx_stats->pkt_stats.bw_count[3], ++ rx_stats->pkt_stats.bw_count[4]); ++ len += scnprintf(buf + len, size - len, "\nRate Table (packets):\n"); ++ for (i = 0; i < rate_table_len; i++) ++ len += scnprintf(buf + len, size - len, "%10llu%s", ++ rx_stats->pkt_stats.rx_rate[i], ++ (i + 1) % (he_rates_avail ? 12 : 8) ? "\t" : "\n"); ++ ++ len += scnprintf(buf + len, size - len, "\nRX success byte stats:\n"); ++ len += scnprintf(buf + len, size - len, "\nHE byte stats:\n"); ++ for (i = 0; i <= HAL_RX_MAX_MCS_HE; i++) ++ len += scnprintf(buf + len, size - len, "MCS %d: %llu%s", i, ++ rx_stats->byte_stats.he_mcs_count[i], ++ (i + 1) % 6 ? "\t" : "\n"); ++ ++ len += scnprintf(buf + len, size - len, "\nVHT byte stats:\n"); ++ for (i = 0; i <= HAL_RX_MAX_MCS_VHT; i++) ++ len += scnprintf(buf + len, size - len, "MCS %d: %llu%s", i, ++ rx_stats->byte_stats.vht_mcs_count[i], ++ (i + 1) % 5 ? "\t" : "\n"); ++ len += scnprintf(buf + len, size - len, "\nHT byte stats:\n"); ++ for (i = 0; i <= HAL_RX_MAX_MCS_HT; i++) ++ len += scnprintf(buf + len, size - len, "MCS %d: %llu%s", i, ++ rx_stats->byte_stats.ht_mcs_count[i], ++ (i + 1) % 8 ? "\t" : "\n"); ++ len += scnprintf(buf + len, size - len, "\nLegacy rate byte stats:\n"); ++ for (i = 0; i < HAL_RX_MAX_NUM_LEGACY_RATES; i++) ++ len += scnprintf(buf + len, size - len, "%s: %llu%s", legacy_rate_str[i], ++ rx_stats->byte_stats.legacy_count[i], ++ (i + 1) % 4 ? "\t" : "\n"); ++ len += scnprintf(buf + len, size - len, "\nNSS byte stats:\n"); ++ for (i = 0; i < HAL_RX_MAX_NSS; i++) ++ len += scnprintf(buf + len, size - len, "%dx%d: %llu ", i + 1, i + 1, ++ rx_stats->byte_stats.nss_count[i]); ++ len += scnprintf(buf + len, size - len, ++ "\n\nGI: 0.8us %llu 0.4us %llu 1.6us %llu 3.2us %llu\n", ++ rx_stats->byte_stats.gi_count[0], ++ rx_stats->byte_stats.gi_count[1], ++ rx_stats->byte_stats.gi_count[2], ++ rx_stats->byte_stats.gi_count[3]); ++ len += scnprintf(buf + len, size - len, ++ "BW: 20Mhz %llu 40Mhz %llu 80Mhz %llu 160Mhz %llu 320Mhz %llu\n", ++ rx_stats->byte_stats.bw_count[0], ++ rx_stats->byte_stats.bw_count[1], ++ rx_stats->byte_stats.bw_count[2], ++ rx_stats->byte_stats.bw_count[3], ++ rx_stats->byte_stats.bw_count[4]); ++ len += scnprintf(buf + len, size - len, "\nRate Table (bytes):\n"); ++ for (i = 0; i < rate_table_len; i++) ++ len += scnprintf(buf + len, size - len, "%10llu%s", ++ rx_stats->byte_stats.rx_rate[i], ++ (i + 1) % (he_rates_avail ? 12 : 8) ? "\t" : "\n"); ++ len += scnprintf(buf + len, size - len, ++ "\nDCM: %llu\nRU26: %llu\nRU52: %llu\nRU106: %llu\nRU242: %llu\nRU484: %llu\nRU996: %llu\n", ++ rx_stats->dcm_count, rx_stats->ru_alloc_cnt[0], ++ rx_stats->ru_alloc_cnt[1], rx_stats->ru_alloc_cnt[2], ++ rx_stats->ru_alloc_cnt[3], rx_stats->ru_alloc_cnt[4], ++ rx_stats->ru_alloc_cnt[5]); ++ ++ len += scnprintf(buf + len, size - len, "\n"); ++ ++ spin_unlock_bh(&ar->ab->base_lock); ++ ++ if (len > size) ++ len = size; ++ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ kfree(buf); ++ ++ mutex_unlock(&ar->conf_mutex); ++ return retval; ++} ++ ++static const struct file_operations fops_rx_stats = { ++ .read = ath12k_dbg_sta_dump_rx_stats, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++static int ++ath12k_dbg_sta_open_htt_peer_stats(struct inode *inode, struct file *file) ++{ ++ struct ieee80211_sta *sta = inode->i_private; ++ struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k *ar = arsta->arvif->ar; ++ struct debug_htt_stats_req *stats_req; ++ int ret; ++ ++ stats_req = vzalloc(sizeof(*stats_req) + ATH12K_HTT_STATS_BUF_SIZE); ++ if (!stats_req) ++ return -ENOMEM; ++ ++ mutex_lock(&ar->conf_mutex); ++ ar->debug.htt_stats.stats_req = stats_req; ++ stats_req->type = ATH12K_DBG_HTT_EXT_STATS_PEER_INFO; ++ memcpy(stats_req->peer_addr, sta->addr, ETH_ALEN); ++ ret = ath12k_debugfs_htt_stats_req(ar); ++ mutex_unlock(&ar->conf_mutex); ++ if (ret < 0) ++ goto out; ++ ++ file->private_data = stats_req; ++ return 0; ++out: ++ vfree(stats_req); ++ ar->debug.htt_stats.stats_req = NULL; ++ return ret; ++} ++ ++static int ++ath12k_dbg_sta_release_htt_peer_stats(struct inode *inode, struct file *file) ++{ ++ struct ieee80211_sta *sta = inode->i_private; ++ struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k *ar = arsta->arvif->ar; ++ ++ mutex_lock(&ar->conf_mutex); ++ vfree(file->private_data); ++ ar->debug.htt_stats.stats_req = NULL; ++ mutex_unlock(&ar->conf_mutex); ++ ++ return 0; ++} ++ ++static ssize_t ath12k_dbg_sta_read_htt_peer_stats(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct debug_htt_stats_req *stats_req = file->private_data; ++ char *buf; ++ u32 length = 0; ++ ++ buf = stats_req->buf; ++ length = min_t(u32, stats_req->buf_len, ATH12K_HTT_STATS_BUF_SIZE); ++ return simple_read_from_buffer(user_buf, count, ppos, buf, length); ++} ++ ++static const struct file_operations fops_htt_peer_stats = { ++ .open = ath12k_dbg_sta_open_htt_peer_stats, ++ .release = ath12k_dbg_sta_release_htt_peer_stats, ++ .read = ath12k_dbg_sta_read_htt_peer_stats, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++static ssize_t ath12k_dbg_sta_write_peer_pktlog(struct file *file, ++ const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ieee80211_sta *sta = file->private_data; ++ struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k *ar = arsta->arvif->ar; ++ int ret, enable; ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ if (ar->state != ATH12K_STATE_ON) { ++ ret = -ENETDOWN; ++ goto out; ++ } ++ ++ ret = kstrtoint_from_user(buf, count, 0, &enable); ++ if (ret) ++ goto out; ++ ++ ar->debug.pktlog_peer_valid = enable; ++ memcpy(ar->debug.pktlog_peer_addr, sta->addr, ETH_ALEN); ++ ++ /* Send peer based pktlog enable/disable */ ++ ret = ath12k_wmi_pdev_peer_pktlog_filter(ar, sta->addr, enable); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to set peer pktlog filter %pM: %d\n", ++ sta->addr, ret); ++ goto out; ++ } ++ ++ ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "peer pktlog filter set to %d\n", ++ enable); ++ ret = count; ++ ++out: ++ mutex_unlock(&ar->conf_mutex); ++ return ret; ++} ++ ++static ssize_t ath12k_dbg_sta_read_peer_pktlog(struct file *file, ++ char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ieee80211_sta *sta = file->private_data; ++ struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k *ar = arsta->arvif->ar; ++ char buf[32] = {0}; ++ int len; ++ ++ mutex_lock(&ar->conf_mutex); ++ len = scnprintf(buf, sizeof(buf), "%08x %pM\n", ++ ar->debug.pktlog_peer_valid, ++ ar->debug.pktlog_peer_addr); ++ mutex_unlock(&ar->conf_mutex); ++ ++ return simple_read_from_buffer(ubuf, count, ppos, buf, len); ++} ++ ++static const struct file_operations fops_peer_pktlog = { ++ .write = ath12k_dbg_sta_write_peer_pktlog, ++ .read = ath12k_dbg_sta_read_peer_pktlog, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++static ssize_t ath12k_dbg_sta_write_delba(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ieee80211_sta *sta = file->private_data; ++ struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k *ar = arsta->arvif->ar; ++ u32 tid, initiator, reason; ++ int ret; ++ char buf[64] = {0}; ++ ++ ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ++ user_buf, count); ++ if (ret <= 0) ++ return ret; ++ ++ ret = sscanf(buf, "%u %u %u", &tid, &initiator, &reason); ++ if (ret != 3) ++ return -EINVAL; ++ ++ /* Valid TID values are 0 through 15 */ ++ if (tid > HAL_DESC_REO_NON_QOS_TID - 1) ++ return -EINVAL; ++ ++ mutex_lock(&ar->conf_mutex); ++ if (ar->state != ATH12K_STATE_ON || ++ arsta->aggr_mode != ATH12K_DBG_AGGR_MODE_MANUAL) { ++ ret = count; ++ goto out; ++ } ++ ++ ret = ath12k_wmi_delba_send(ar, arsta->arvif->vdev_id, sta->addr, ++ tid, initiator, reason); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to send delba: vdev_id %u peer %pM tid %u initiator %u reason %u\n", ++ arsta->arvif->vdev_id, sta->addr, tid, initiator, ++ reason); ++ } ++ ret = count; ++out: ++ mutex_unlock(&ar->conf_mutex); ++ return ret; ++} ++ ++static const struct file_operations fops_delba = { ++ .write = ath12k_dbg_sta_write_delba, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++static ssize_t ath12k_dbg_sta_write_addba_resp(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ieee80211_sta *sta = file->private_data; ++ struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k *ar = arsta->arvif->ar; ++ u32 tid, status; ++ int ret; ++ char buf[64] = {0}; ++ ++ ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ++ user_buf, count); ++ if (ret <= 0) ++ return ret; ++ ++ ret = sscanf(buf, "%u %u", &tid, &status); ++ if (ret != 2) ++ return -EINVAL; ++ ++ /* Valid TID values are 0 through 15 */ ++ if (tid > HAL_DESC_REO_NON_QOS_TID - 1) ++ return -EINVAL; ++ ++ mutex_lock(&ar->conf_mutex); ++ if (ar->state != ATH12K_STATE_ON || ++ arsta->aggr_mode != ATH12K_DBG_AGGR_MODE_MANUAL) { ++ ret = count; ++ goto out; ++ } ++ ++ ret = ath12k_wmi_addba_set_resp(ar, arsta->arvif->vdev_id, sta->addr, ++ tid, status); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to send addba response: vdev_id %u peer %pM tid %u status%u\n", ++ arsta->arvif->vdev_id, sta->addr, tid, status); ++ } ++ ret = count; ++out: ++ mutex_unlock(&ar->conf_mutex); ++ return ret; ++} ++ ++static const struct file_operations fops_addba_resp = { ++ .write = ath12k_dbg_sta_write_addba_resp, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++static ssize_t ath12k_dbg_sta_write_addba(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ieee80211_sta *sta = file->private_data; ++ struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k *ar = arsta->arvif->ar; ++ u32 tid, buf_size; ++ int ret; ++ char buf[64] = {0}; ++ ++ ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ++ user_buf, count); ++ if (ret <= 0) ++ return ret; ++ ++ ret = sscanf(buf, "%u %u", &tid, &buf_size); ++ if (ret != 2) ++ return -EINVAL; ++ ++ /* Valid TID values are 0 through 15 */ ++ if (tid > HAL_DESC_REO_NON_QOS_TID - 1) ++ return -EINVAL; ++ ++ mutex_lock(&ar->conf_mutex); ++ if (ar->state != ATH12K_STATE_ON || ++ arsta->aggr_mode != ATH12K_DBG_AGGR_MODE_MANUAL) { ++ ret = count; ++ goto out; ++ } ++ ++ ret = ath12k_wmi_addba_send(ar, arsta->arvif->vdev_id, sta->addr, ++ tid, buf_size); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to send addba request: vdev_id %u peer %pM tid %u buf_size %u\n", ++ arsta->arvif->vdev_id, sta->addr, tid, buf_size); ++ } ++ ++ ret = count; ++out: ++ mutex_unlock(&ar->conf_mutex); ++ return ret; ++} ++ ++static const struct file_operations fops_addba = { ++ .write = ath12k_dbg_sta_write_addba, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++static ssize_t ath12k_dbg_sta_read_aggr_mode(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ieee80211_sta *sta = file->private_data; ++ struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k *ar = arsta->arvif->ar; ++ char buf[64]; ++ int len = 0; ++ ++ mutex_lock(&ar->conf_mutex); ++ len = scnprintf(buf, sizeof(buf) - len, ++ "aggregation mode: %s\n\n%s\n%s\n", ++ (arsta->aggr_mode == ATH12K_DBG_AGGR_MODE_AUTO) ? ++ "auto" : "manual", "auto = 0", "manual = 1"); ++ mutex_unlock(&ar->conf_mutex); ++ ++ return simple_read_from_buffer(user_buf, count, ppos, buf, len); ++} ++ ++static ssize_t ath12k_dbg_sta_write_aggr_mode(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ieee80211_sta *sta = file->private_data; ++ struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k *ar = arsta->arvif->ar; ++ u32 aggr_mode; ++ int ret; ++ ++ if (kstrtouint_from_user(user_buf, count, 0, &aggr_mode)) ++ return -EINVAL; ++ ++ if (aggr_mode >= ATH12K_DBG_AGGR_MODE_MAX) ++ return -EINVAL; ++ ++ mutex_lock(&ar->conf_mutex); ++ if (ar->state != ATH12K_STATE_ON || ++ aggr_mode == arsta->aggr_mode) { ++ ret = count; ++ goto out; ++ } ++ ++ ret = ath12k_wmi_addba_clear_resp(ar, arsta->arvif->vdev_id, sta->addr); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to clear addba session ret: %d\n", ++ ret); ++ goto out; ++ } ++ ++ arsta->aggr_mode = aggr_mode; ++out: ++ mutex_unlock(&ar->conf_mutex); ++ return ret; ++} ++ ++static const struct file_operations fops_aggr_mode = { ++ .read = ath12k_dbg_sta_read_aggr_mode, ++ .write = ath12k_dbg_sta_write_aggr_mode, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++static ssize_t ++ath12k_write_htt_peer_stats_reset(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ieee80211_sta *sta = file->private_data; ++ struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k *ar = arsta->arvif->ar; ++ struct htt_ext_stats_cfg_params cfg_params = { 0 }; ++ int ret; ++ u8 type; ++ ++ ret = kstrtou8_from_user(user_buf, count, 0, &type); ++ if (ret) ++ return ret; ++ ++ if (!type) ++ return ret; ++ ++ mutex_lock(&ar->conf_mutex); ++ cfg_params.cfg0 = HTT_STAT_PEER_INFO_MAC_ADDR; ++ cfg_params.cfg0 |= FIELD_PREP(GENMASK(15, 1), ++ HTT_PEER_STATS_REQ_MODE_FLUSH_TQM); ++ ++ cfg_params.cfg1 = HTT_STAT_DEFAULT_PEER_REQ_TYPE; ++ ++ cfg_params.cfg2 |= FIELD_PREP(GENMASK(7, 0), sta->addr[0]); ++ cfg_params.cfg2 |= FIELD_PREP(GENMASK(15, 8), sta->addr[1]); ++ cfg_params.cfg2 |= FIELD_PREP(GENMASK(23, 16), sta->addr[2]); ++ cfg_params.cfg2 |= FIELD_PREP(GENMASK(31, 24), sta->addr[3]); ++ ++ cfg_params.cfg3 |= FIELD_PREP(GENMASK(7, 0), sta->addr[4]); ++ cfg_params.cfg3 |= FIELD_PREP(GENMASK(15, 8), sta->addr[5]); ++ ++ cfg_params.cfg3 |= ATH12K_HTT_PEER_STATS_RESET; ++ ++ ret = ath12k_dp_tx_htt_h2t_ext_stats_req(ar, ++ ATH12K_DBG_HTT_EXT_STATS_PEER_INFO, ++ &cfg_params, ++ 0ULL); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to send htt peer stats request: %d\n", ret); ++ mutex_unlock(&ar->conf_mutex); ++ return ret; ++ } ++ ++ mutex_unlock(&ar->conf_mutex); ++ ++ ret = count; ++ ++ return ret; ++} ++ ++static const struct file_operations fops_htt_peer_stats_reset = { ++ .write = ath12k_write_htt_peer_stats_reset, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++void ath12k_debugfs_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ++ struct ieee80211_sta *sta, struct dentry *dir) ++{ ++ struct ath12k *ar = hw->priv; ++ ++ if (ath12k_debugfs_is_extd_tx_stats_enabled(ar)) ++ debugfs_create_file("tx_stats", 0400, dir, sta, ++ &fops_tx_stats); ++ if (ath12k_debugfs_is_extd_rx_stats_enabled(ar)) ++ debugfs_create_file("rx_stats", 0400, dir, sta, ++ &fops_rx_stats); ++ ++ debugfs_create_file("htt_peer_stats", 0400, dir, sta, ++ &fops_htt_peer_stats); ++ ++ debugfs_create_file("peer_pktlog", 0644, dir, sta, ++ &fops_peer_pktlog); ++ ++ debugfs_create_file("aggr_mode", 0644, dir, sta, &fops_aggr_mode); ++ debugfs_create_file("addba", 0200, dir, sta, &fops_addba); ++ debugfs_create_file("addba_resp", 0200, dir, sta, &fops_addba_resp); ++ debugfs_create_file("delba", 0200, dir, sta, &fops_delba); ++ ++ if (test_bit(WMI_TLV_SERVICE_PER_PEER_HTT_STATS_RESET, ++ ar->ab->wmi_ab.svc_map)) ++ debugfs_create_file("htt_peer_stats_reset", 0600, dir, sta, ++ &fops_htt_peer_stats_reset); ++} +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/debugfs_sta.h +@@ -0,0 +1,46 @@ ++/* SPDX-License-Identifier: BSD-3-Clause-Clear */ ++/* ++ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef _ATH12K_DEBUGFS_STA_H_ ++#define _ATH12K_DEBUGFS_STA_H_ ++ ++#include ++ ++#include "core.h" ++#include "hal_tx.h" ++#include "dp_rx.h" ++ ++#ifdef CPTCFG_ATH12K_DEBUGFS ++ ++void ath12k_debugfs_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ++ struct ieee80211_sta *sta, struct dentry *dir); ++void ath12k_debugfs_sta_add_tx_stats(struct ath12k_sta *arsta, ++ struct ath12k_per_peer_tx_stats *peer_stats, ++ u8 legacy_rate_idx); ++void ath12k_debugfs_sta_update_txcompl(struct ath12k *ar, ++ struct sk_buff *msdu, ++ struct hal_tx_status *ts); ++ ++#else /* CPTCFG_ATH12K_DEBUGFS */ ++ ++#define ath12k_debugfs_sta_op_add NULL ++ ++static inline void ++ath12k_debugfs_sta_add_tx_stats(struct ath12k_sta *arsta, ++ struct ath12k_per_peer_tx_stats *peer_stats, ++ u8 legacy_rate_idx) ++{ ++} ++ ++static inline void ath12k_debugfs_sta_update_txcompl(struct ath12k *ar, ++ struct sk_buff *msdu, ++ struct hal_tx_status *ts) ++{ ++} ++ ++#endif /* CPTCFG_ATH12K_DEBUGFS */ ++ ++#endif /* _ATH12K_DEBUGFS_STA_H_ */ +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -972,12 +972,16 @@ done: + + void ath12k_dp_pdev_free(struct ath12k_base *ab) + { ++ struct ath12k *ar; + int i; + + del_timer_sync(&ab->mon_reap_timer); + +- for (i = 0; i < ab->num_radios; i++) ++ for (i = 0; i < ab->num_radios; i++) { ++ ar = ab->pdevs[i].ar; + ath12k_dp_rx_pdev_free(ab, i); ++ ath12k_debugfs_unregister(ar); ++ } + } + + void ath12k_dp_pdev_pre_alloc(struct ath12k_base *ab) +--- a/drivers/net/wireless/ath/ath12k/dp_mon.c ++++ b/drivers/net/wireless/ath/ath12k/dp_mon.c +@@ -2093,6 +2093,14 @@ int ath12k_dp_mon_srng_process(struct at + buf_ring = &dp->tx_mon_buf_ring; + } + ++ if (ath12k_debugfs_is_pktlog_lite_mode_enabled(ar)) { ++ log_type = ATH12K_PKTLOG_TYPE_LITE_RX; ++ rx_buf_sz = DP_RX_BUFFER_SIZE_LITE; ++ } else if (ath12k_debugfs_is_pktlog_rx_stats_enabled(ar)) { ++ log_type = ATH12K_PKTLOG_TYPE_RX_STATBUF; ++ rx_buf_sz = DP_RX_BUFFER_SIZE; ++ } ++ + srng = &ab->hal.srng_list[mon_dst_ring->ring_id]; + + spin_lock_bh(&srng->lock); +@@ -2155,6 +2163,10 @@ int ath12k_dp_mon_srng_process(struct at + continue; + } + ++ if (ath12k_debugfs_is_pktlog_peer_valid(ar, peer->addr)) ++ trace_ath12k_htt_rxdesc(ar, skb->data, ++ log_type, rx_buf_sz); ++ + dev_kfree_skb_any(skb); + pmon->dest_skb_q[i] = NULL; + } +@@ -2220,6 +2232,9 @@ static void ath12k_dp_mon_rx_update_peer + + arsta->rssi_comb = ppdu_info->rssi_comb; + ++ if (!ath12k_debugfs_is_extd_rx_stats_enabled(ar)) ++ return; ++ + num_msdu = ppdu_info->tcp_msdu_count + ppdu_info->tcp_ack_msdu_count + + ppdu_info->udp_msdu_count + ppdu_info->other_msdu_count; + +@@ -2467,6 +2482,9 @@ ath12k_dp_mon_rx_update_peer_mu_stats(st + { + u32 num_users, i; + ++ if (!ath12k_debugfs_is_extd_rx_stats_enabled(ar)) ++ return; ++ + num_users = ppdu_info->num_users; + if (num_users > HAL_MAX_UL_MU_USERS) + num_users = HAL_MAX_UL_MU_USERS; +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -10,6 +10,8 @@ + #include + #include "core.h" + #include "debug.h" ++#include "debugfs_htt_stats.h" ++#include "debugfs_sta.h" + #include "hal_desc.h" + #include "hw.h" + #include "dp_rx.h" +@@ -1451,6 +1453,9 @@ ath12k_update_per_peer_tx_stats(struct a + peer_stats->ba_fails = + HTT_USR_CMPLTN_LONG_RETRY(usr_stats->cmpltn_cmn.flags) + + HTT_USR_CMPLTN_SHORT_RETRY(usr_stats->cmpltn_cmn.flags); ++ ++ if (ath12k_debugfs_is_extd_tx_stats_enabled(ar)) ++ ath12k_debugfs_sta_add_tx_stats(arsta, peer_stats, rate_idx); + } + + spin_unlock_bh(&ab->base_lock); +@@ -1552,6 +1557,9 @@ static int ath12k_htt_pull_ppdu_stats(st + goto exit; + } + ++ if (ath12k_debugfs_is_pktlog_lite_mode_enabled(ar)) ++ trace_ath12k_htt_ppdu_stats(ar, skb->data, len); ++ + spin_lock_bh(&ar->data_lock); + ppdu_info = ath12k_dp_htt_get_ppdu_desc(ar, ppdu_id); + if (!ppdu_info) { +@@ -1860,6 +1868,7 @@ void ath12k_dp_htt_htc_t2h_msg_handler(s + ath12k_htt_pull_ppdu_stats(ab, skb); + break; + case HTT_T2H_MSG_TYPE_EXT_STATS_CONF: ++ ath12k_debugfs_htt_ext_stats_handler(ab, skb); + break; + case HTT_T2H_MSG_TYPE_PKTLOG: + ath12k_htt_pktlog(ab, skb); +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -7,6 +7,7 @@ + #include "core.h" + #include "dp_tx.h" + #include "debug.h" ++#include "debugfs_sta.h" + #include "hw.h" + + static enum hal_tcl_encap_type +@@ -436,6 +437,23 @@ ath12k_dp_tx_process_htt_tx_complete(str + } + } + ++static void ath12k_dp_tx_cache_peer_stats(struct ath12k *ar, ++ struct sk_buff *msdu, ++ struct hal_tx_status *ts) ++{ ++ struct ath12k_per_peer_tx_stats *peer_stats = &ar->cached_stats; ++ ++ if (ts->try_cnt > 1) { ++ peer_stats->retry_pkts += ts->try_cnt - 1; ++ peer_stats->retry_bytes += (ts->try_cnt - 1) * msdu->len; ++ ++ if (ts->status != HAL_WBM_TQM_REL_REASON_FRAME_ACKED) { ++ peer_stats->failed_pkts += 1; ++ peer_stats->failed_bytes += msdu->len; ++ } ++ } ++} ++ + static void ath12k_dp_tx_complete_msdu(struct ath12k *ar, + struct sk_buff *msdu, + struct hal_tx_status *ts) +@@ -486,6 +504,29 @@ static void ath12k_dp_tx_complete_msdu(s + (info->flags & IEEE80211_TX_CTL_NO_ACK)) + info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; + ++ if (ath12k_debugfs_is_extd_tx_stats_enabled(ar)) { ++ if (ts->flags & HAL_TX_STATUS_FLAGS_FIRST_MSDU) { ++ if (ar->last_ppdu_id == 0) { ++ ar->last_ppdu_id = ts->ppdu_id; ++ } else if (ar->last_ppdu_id == ts->ppdu_id || ++ ar->cached_ppdu_id == ar->last_ppdu_id) { ++ ar->cached_ppdu_id = ar->last_ppdu_id; ++ ar->cached_stats.is_ampdu = true; ++ ath12k_debugfs_sta_update_txcompl(ar, msdu, ts); ++ memset(&ar->cached_stats, 0, ++ sizeof(struct ath12k_per_peer_tx_stats)); ++ } else { ++ ar->cached_stats.is_ampdu = false; ++ ath12k_debugfs_sta_update_txcompl(ar, msdu, ts); ++ memset(&ar->cached_stats, 0, ++ sizeof(struct ath12k_per_peer_tx_stats)); ++ } ++ ar->last_ppdu_id = ts->ppdu_id; ++ } ++ ++ ath12k_dp_tx_cache_peer_stats(ar, msdu, ts); ++ } ++ + /* NOTE: Tx rate status reporting. Tx completion status does not have + * necessary information (for example nss) to build the tx rate. + * Might end up reporting it out-of-band from HTT stats. +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -14,6 +14,7 @@ + #include "dp_tx.h" + #include "dp_rx.h" + #include "peer.h" ++#include "debugfs_sta.h" + + #define CHAN2G(_channel, _freq, _flags) { \ + .band = NL80211_BAND_2GHZ, \ +@@ -3347,12 +3348,20 @@ static int ath12k_mac_station_add(struct + if (ret) { + ath12k_warn(ab, "Failed to add peer: %pM for VDEV: %d\n", + sta->addr, arvif->vdev_id); +- goto free_peer; ++ goto free_rx_stats; + } + + ath12k_dbg(ab, ATH12K_DBG_MAC, "Added peer: %pM for VDEV: %d\n", + sta->addr, arvif->vdev_id); + ++ if (ath12k_debugfs_is_extd_tx_stats_enabled(ar)) { ++ arsta->tx_stats = kzalloc(sizeof(*arsta->tx_stats), GFP_KERNEL); ++ if (!arsta->tx_stats) { ++ ret = -ENOMEM; ++ goto free_peer; ++ } ++ } ++ + if (ieee80211_vif_is_mesh(vif)) { + ret = ath12k_wmi_set_peer_param(ar, sta->addr, + arvif->vdev_id, +@@ -3360,7 +3369,7 @@ static int ath12k_mac_station_add(struct + if (ret) { + ath12k_warn(ab, "failed to STA %pM 4addr capability: %d\n", + sta->addr, ret); +- goto free_peer; ++ goto free_tx_stats; + } + } + +@@ -3368,7 +3377,7 @@ static int ath12k_mac_station_add(struct + if (ret) { + ath12k_warn(ab, "failed to setup dp for peer %pM on vdev %i (%d)\n", + sta->addr, arvif->vdev_id, ret); +- goto free_peer; ++ goto free_tx_stats; + } + + if (ab->hw_params->vdev_start_delay && +@@ -3377,14 +3386,20 @@ static int ath12k_mac_station_add(struct + ret = ath12k_start_vdev_delay(ar->hw, vif); + if (ret) { + ath12k_warn(ab, "failed to delay vdev start: %d\n", ret); +- goto free_peer; ++ goto free_tx_stats; + } + } + + return 0; + ++free_tx_stats: ++ kfree(arsta->tx_stats); ++ arsta->tx_stats = NULL; + free_peer: + ath12k_peer_delete(ar, arvif->vdev_id, sta->addr); ++free_rx_stats: ++ kfree(arsta->rx_stats); ++ arsta->rx_stats = NULL; + dec_num_station: + ath12k_mac_dec_num_stations(arvif, sta); + exit: +@@ -3445,6 +3460,9 @@ static int ath12k_mac_op_sta_state(struc + } + spin_unlock_bh(&ar->ab->base_lock); + ++ kfree(arsta->tx_stats); ++ arsta->tx_stats = NULL; ++ + kfree(arsta->rx_stats); + arsta->rx_stats = NULL; + } else if (old_state == IEEE80211_STA_AUTH && +@@ -6448,6 +6466,10 @@ static const struct ieee80211_ops ath12k + .get_survey = ath12k_mac_op_get_survey, + .flush = ath12k_mac_op_flush, + .sta_statistics = ath12k_mac_op_sta_statistics, ++ ++#ifdef CPTCFG_ATH12K_DEBUGFS ++ .sta_add_debugfs = ath12k_debugfs_sta_op_add, ++#endif + }; + + static void ath12k_mac_update_ch_list(struct ath12k *ar, +@@ -6857,6 +6879,12 @@ static int __ath12k_mac_register(struct + goto err_unregister_hw; + } + ++ ret = ath12k_debugfs_register(ar); ++ if (ret) { ++ ath12k_err(ar->ab, "debugfs registration failed: %d\n", ret); ++ goto err_unregister_hw; ++ } ++ + return 0; + + err_unregister_hw: +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -1271,6 +1271,7 @@ static void ath12k_pci_remove(struct pci + + if (test_bit(ATH12K_FLAG_QMI_FAIL, &ab->dev_flags)) { + ath12k_pci_power_down(ab); ++ ath12k_debugfs_soc_destroy(ab); + ath12k_qmi_deinit_service(ab); + goto qmi_fail; + } +@@ -1343,20 +1344,29 @@ static int ath12k_pci_init(void) + { + int ret; + ++ ret = ath12k_debugfs_create(); ++ if (ret) ++ pr_info("failed to register debugfs ath12k driver: %d\n", ret); ++ + ret = pci_register_driver(&ath12k_pci_driver); + if (ret) { + pr_err("failed to register ath12k pci driver: %d\n", + ret); +- return ret; ++ goto err; + } + + return 0; ++ ++err: ++ ath12k_debugfs_destroy(); ++ return ret; + } + module_init(ath12k_pci_init); + + static void ath12k_pci_exit(void) + { + pci_unregister_driver(&ath12k_pci_driver); ++ ath12k_debugfs_destroy(); + } + + module_exit(ath12k_pci_exit); +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -6751,6 +6751,7 @@ static void ath12k_peer_assoc_conf_event + + static void ath12k_update_stats_event(struct ath12k_base *ab, struct sk_buff *skb) + { ++ ath12k_debugfs_fw_stats_process(ab, skb); + } + + /* PDEV_CTL_FAILSAFE_CHECK_EVENT is received from FW when the frequency scanned diff --git a/feeds/ipq95xx/mac80211/patches/qca/505-ath12k-add-spectral-support.patch b/feeds/ipq95xx/mac80211/patches/qca/505-ath12k-add-spectral-support.patch new file mode 100644 index 000000000..393f94469 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/505-ath12k-add-spectral-support.patch @@ -0,0 +1,1266 @@ +From f411b191075fda64cde9ef3c197224468c75b5d5 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Thu, 1 Sep 2022 15:51:51 +0530 +Subject: [PATCH 4/5] Revert "ath12k: remove spectral support" + +This reverts commit 070381028567d9b8e0d82e6f244909e51902bc49. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath12k/Kconfig | 8 + + drivers/net/wireless/ath/ath12k/Makefile | 1 + + drivers/net/wireless/ath/ath12k/core.c | 10 + + drivers/net/wireless/ath/ath12k/core.h | 6 +- + drivers/net/wireless/ath/ath12k/dbring.c | 1 + + drivers/net/wireless/ath/ath12k/hw.h | 1 + + drivers/net/wireless/ath/ath12k/mac.c | 3 + + drivers/net/wireless/ath/ath12k/spectral.c | 1028 ++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/spectral.h | 83 ++ + 9 files changed, 1140 insertions(+), 1 deletion(-) + create mode 100644 drivers/net/wireless/ath/ath12k/spectral.c + create mode 100644 drivers/net/wireless/ath/ath12k/spectral.h + +--- a/drivers/net/wireless/ath/ath12k/Kconfig ++++ b/drivers/net/wireless/ath/ath12k/Kconfig +@@ -37,3 +37,11 @@ config ATH12K_TRACING + help + Select this to use ath12k tracing infrastructure. + ++config ATH12K_SPECTRAL ++ bool "QTI ath12k spectral scan support" ++ depends on ATH12K_DEBUGFS ++ depends on RELAY ++ help ++ Enable ath12k spectral scan support ++ ++ Say Y to enable access to the FFT/spectral data via debugfs. +--- a/drivers/net/wireless/ath/ath12k/Makefile ++++ b/drivers/net/wireless/ath/ath12k/Makefile +@@ -25,6 +25,7 @@ ath12k-y += core.o \ + ath12k-$(CPTCFG_ATH12K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o + ath12k-$(CPTCFG_ATH12K_TRACING) += trace.o + ath12k-$(CONFIG_THERMAL) += thermal.o ++ath12k-$(CPTCFG_ATH12K_SPECTRAL) += spectral.o + + # for tracing framework to find trace.h + CFLAGS_trace.o := -I$(src) +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -491,8 +491,16 @@ static int ath12k_core_pdev_create(struc + goto err_dp_pdev_free; + } + ++ ret = ath12k_spectral_init(ab); ++ if (ret) { ++ ath12k_err(ab, "failed to init spectral %d\n", ret); ++ goto err_thermal_unregister; ++ } ++ + return 0; + ++err_thermal_unregister: ++ ath12k_thermal_unregister(ab); + err_dp_pdev_free: + ath12k_dp_pdev_free(ab); + err_mac_unregister: +@@ -505,6 +513,7 @@ err_pdev_debug: + + static void ath12k_core_pdev_destroy(struct ath12k_base *ab) + { ++ ath12k_spectral_deinit(ab); + ath12k_thermal_unregister(ab); + ath12k_mac_unregister(ab); + ath12k_hif_irq_disable(ab); +@@ -718,6 +727,7 @@ static int ath12k_core_reconfigure_on_cr + ath12k_thermal_unregister(ab); + ath12k_hif_irq_disable(ab); + ath12k_dp_pdev_free(ab); ++ ath12k_spectral_deinit(ab); + ath12k_hif_stop(ab); + ath12k_wmi_detach(ab); + ath12k_dp_rx_pdev_reo_cleanup(ab); +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -23,6 +23,7 @@ + #include "reg.h" + #include "thermal.h" + #include "dbring.h" ++#include "spectral.h" + + #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK) + +@@ -256,6 +257,7 @@ struct ath12k_vif { + + bool is_started; + bool is_up; ++ bool spectral_enabled; + u32 aid; + u8 bssid[ETH_ALEN]; + struct cfg80211_bitrate_mask bitrate_mask; +@@ -625,7 +627,9 @@ struct ath12k { + #ifdef CPTCFG_ATH12K_DEBUGFS + struct ath12k_debug debug; + #endif +- ++#ifdef CPTCFG_ATH12K_SPECTRAL ++ struct ath12k_spectral spectral; ++#endif + bool dfs_block_radar_events; + struct ath12k_thermal thermal; + bool monitor_conf_enabled; +--- a/drivers/net/wireless/ath/ath12k/dbring.c ++++ b/drivers/net/wireless/ath/ath12k/dbring.c +@@ -269,6 +269,7 @@ int ath12k_dbring_buffer_release_event(s + + switch (ev->fixed.module_id) { + case WMI_DIRECT_BUF_SPECTRAL: ++ ring = ath12k_spectral_get_dbring(ar); + break; + default: + ring = NULL; +--- a/drivers/net/wireless/ath/ath12k/hw.h ++++ b/drivers/net/wireless/ath/ath12k/hw.h +@@ -164,6 +164,7 @@ struct ath12k_hw_params { + int num_rxdma_dst_ring; + bool rx_mac_buf_ring; + bool vdev_start_delay; ++ u8 spectral_fft_sz; + + u16 interface_modes; + bool supports_monitor; +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -2641,6 +2641,9 @@ static int ath12k_start_scan(struct ath1 + + lockdep_assert_held(&ar->conf_mutex); + ++ if (ath12k_spectral_get_mode(ar) == ATH12K_SPECTRAL_BACKGROUND) ++ ath12k_spectral_reset_buffer(ar); ++ + ret = ath12k_wmi_send_scan_start_cmd(ar, arg); + if (ret) + return ret; +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/spectral.c +@@ -0,0 +1,1028 @@ ++// SPDX-License-Identifier: BSD-3-Clause-Clear ++/* ++ * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include ++#include "core.h" ++#include "debug.h" ++ ++#define ATH12K_SPECTRAL_NUM_RESP_PER_EVENT 2 ++#define ATH12K_SPECTRAL_EVENT_TIMEOUT_MS 1 ++ ++#define ATH12K_SPECTRAL_DWORD_SIZE 4 ++/* HW bug, expected BIN size is 2 bytes but HW report as 4 bytes */ ++#define ATH12K_SPECTRAL_BIN_SIZE 4 ++#define ATH12K_SPECTRAL_ATH12K_MIN_BINS 64 ++#define ATH12K_SPECTRAL_ATH12K_MIN_IB_BINS 32 ++#define ATH12K_SPECTRAL_ATH12K_MAX_IB_BINS 256 ++ ++#define ATH12K_SPECTRAL_SCAN_COUNT_MAX 4095 ++ ++/* Max channel computed by sum of 2g and 5g band channels */ ++#define ATH12K_SPECTRAL_TOTAL_CHANNEL 41 ++#define ATH12K_SPECTRAL_SAMPLES_PER_CHANNEL 70 ++#define ATH12K_SPECTRAL_PER_SAMPLE_SIZE (sizeof(struct fft_sample_ath12k) + \ ++ ATH12K_SPECTRAL_ATH12K_MAX_IB_BINS) ++#define ATH12K_SPECTRAL_TOTAL_SAMPLE (ATH12K_SPECTRAL_TOTAL_CHANNEL * \ ++ ATH12K_SPECTRAL_SAMPLES_PER_CHANNEL) ++#define ATH12K_SPECTRAL_SUB_BUFF_SIZE ATH12K_SPECTRAL_PER_SAMPLE_SIZE ++#define ATH12K_SPECTRAL_NUM_SUB_BUF ATH12K_SPECTRAL_TOTAL_SAMPLE ++ ++#define ATH12K_SPECTRAL_20MHZ 20 ++#define ATH12K_SPECTRAL_40MHZ 40 ++#define ATH12K_SPECTRAL_80MHZ 80 ++ ++#define ATH12K_SPECTRAL_SIGNATURE 0xFA ++ ++#define ATH12K_SPECTRAL_TAG_RADAR_SUMMARY 0x0 ++#define ATH12K_SPECTRAL_TAG_RADAR_FFT 0x1 ++#define ATH12K_SPECTRAL_TAG_SCAN_SUMMARY 0x2 ++#define ATH12K_SPECTRAL_TAG_SCAN_SEARCH 0x3 ++ ++#define SPECTRAL_TLV_HDR_LEN GENMASK(15, 0) ++#define SPECTRAL_TLV_HDR_TAG GENMASK(23, 16) ++#define SPECTRAL_TLV_HDR_SIGN GENMASK(31, 24) ++ ++#define SPECTRAL_SUMMARY_INFO0_AGC_TOTAL_GAIN GENMASK(7, 0) ++#define SPECTRAL_SUMMARY_INFO0_OB_FLAG BIT(8) ++#define SPECTRAL_SUMMARY_INFO0_GRP_IDX GENMASK(16, 9) ++#define SPECTRAL_SUMMARY_INFO0_RECENT_RFSAT BIT(17) ++#define SPECTRAL_SUMMARY_INFO0_INBAND_PWR_DB GENMASK(27, 18) ++#define SPECTRAL_SUMMARY_INFO0_FALSE_SCAN BIT(28) ++#define SPECTRAL_SUMMARY_INFO0_DETECTOR_ID GENMASK(30, 29) ++#define SPECTRAL_SUMMARY_INFO0_PRI80 BIT(31) ++ ++#define SPECTRAL_SUMMARY_INFO2_PEAK_SIGNED_IDX GENMASK(11, 0) ++#define SPECTRAL_SUMMARY_INFO2_PEAK_MAGNITUDE GENMASK(21, 12) ++#define SPECTRAL_SUMMARY_INFO2_NARROWBAND_MASK GENMASK(29, 22) ++#define SPECTRAL_SUMMARY_INFO2_GAIN_CHANGE BIT(30) ++ ++struct spectral_tlv { ++ __le32 timestamp; ++ __le32 header; ++} __packed; ++ ++struct spectral_summary_fft_report { ++ __le32 timestamp; ++ __le32 tlv_header; ++ __le32 info0; ++ __le32 reserve0; ++ __le32 info2; ++ __le32 reserve1; ++} __packed; ++ ++struct ath12k_spectral_summary_report { ++ struct wmi_dma_buf_release_meta_data meta; ++ u32 timestamp; ++ u8 agc_total_gain; ++ u8 grp_idx; ++ u16 inb_pwr_db; ++ s16 peak_idx; ++ u16 peak_mag; ++ u8 detector_id; ++ bool out_of_band_flag; ++ bool rf_saturation; ++ bool primary80; ++ bool gain_change; ++ bool false_scan; ++}; ++ ++#define SPECTRAL_FFT_REPORT_INFO0_DETECTOR_ID GENMASK(1, 0) ++#define SPECTRAL_FFT_REPORT_INFO0_FFT_NUM GENMASK(4, 2) ++#define SPECTRAL_FFT_REPORT_INFO0_RADAR_CHECK GENMASK(16, 5) ++#define SPECTRAL_FFT_REPORT_INFO0_PEAK_SIGNED_IDX GENMASK(27, 17) ++#define SPECTRAL_FFT_REPORT_INFO0_CHAIN_IDX GENMASK(30, 28) ++ ++#define SPECTRAL_FFT_REPORT_INFO1_BASE_PWR_DB GENMASK(8, 0) ++#define SPECTRAL_FFT_REPORT_INFO1_TOTAL_GAIN_DB GENMASK(16, 9) ++ ++#define SPECTRAL_FFT_REPORT_INFO2_NUM_STRONG_BINS GENMASK(7, 0) ++#define SPECTRAL_FFT_REPORT_INFO2_PEAK_MAGNITUDE GENMASK(17, 8) ++#define SPECTRAL_FFT_REPORT_INFO2_AVG_PWR_DB GENMASK(24, 18) ++#define SPECTRAL_FFT_REPORT_INFO2_REL_PWR_DB GENMASK(31, 25) ++ ++struct spectral_search_fft_report { ++ __le32 timestamp; ++ __le32 tlv_header; ++ __le32 info0; ++ __le32 info1; ++ __le32 info2; ++ __le32 reserve0; ++ u8 bins[0]; ++} __packed; ++ ++struct ath12k_spectral_search_report { ++ u32 timestamp; ++ u8 detector_id; ++ u8 fft_count; ++ u16 radar_check; ++ s16 peak_idx; ++ u8 chain_idx; ++ u16 base_pwr_db; ++ u8 total_gain_db; ++ u8 strong_bin_count; ++ u16 peak_mag; ++ u8 avg_pwr_db; ++ u8 rel_pwr_db; ++}; ++ ++static struct dentry *create_buf_file_handler(const char *filename, ++ struct dentry *parent, ++ umode_t mode, ++ struct rchan_buf *buf, ++ int *is_global) ++{ ++ struct dentry *buf_file; ++ ++ buf_file = debugfs_create_file(filename, mode, parent, buf, ++ &relay_file_operations); ++ *is_global = 1; ++ return buf_file; ++} ++ ++static int remove_buf_file_handler(struct dentry *dentry) ++{ ++ debugfs_remove(dentry); ++ ++ return 0; ++} ++ ++static const struct rchan_callbacks rfs_scan_cb = { ++ .create_buf_file = create_buf_file_handler, ++ .remove_buf_file = remove_buf_file_handler, ++}; ++ ++static struct ath12k_vif *ath12k_spectral_get_vdev(struct ath12k *ar) ++{ ++ struct ath12k_vif *arvif; ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ if (list_empty(&ar->arvifs)) ++ return NULL; ++ ++ /* if there already is a vif doing spectral, return that. */ ++ list_for_each_entry(arvif, &ar->arvifs, list) ++ if (arvif->spectral_enabled) ++ return arvif; ++ ++ /* otherwise, return the first vif. */ ++ return list_first_entry(&ar->arvifs, typeof(*arvif), list); ++} ++ ++static int ath12k_spectral_scan_trigger(struct ath12k *ar) ++{ ++ struct ath12k_vif *arvif; ++ int ret; ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ arvif = ath12k_spectral_get_vdev(ar); ++ if (!arvif) ++ return -ENODEV; ++ ++ if (ar->spectral.mode == ATH12K_SPECTRAL_DISABLED) ++ return 0; ++ ++ ret = ath12k_wmi_vdev_spectral_enable(ar, arvif->vdev_id, ++ ATH12K_WMI_SPECTRAL_TRIGGER_CMD_CLEAR, ++ ATH12K_WMI_SPECTRAL_ENABLE_CMD_ENABLE); ++ if (ret) ++ return ret; ++ ++ ret = ath12k_wmi_vdev_spectral_enable(ar, arvif->vdev_id, ++ ATH12K_WMI_SPECTRAL_TRIGGER_CMD_TRIGGER, ++ ATH12K_WMI_SPECTRAL_ENABLE_CMD_ENABLE); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++static int ath12k_spectral_scan_config(struct ath12k *ar, ++ enum ath12k_spectral_mode mode) ++{ ++ struct ath12k_wmi_vdev_spectral_conf_param param = { 0 }; ++ struct ath12k_vif *arvif; ++ int ret, count; ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ arvif = ath12k_spectral_get_vdev(ar); ++ if (!arvif) ++ return -ENODEV; ++ ++ arvif->spectral_enabled = (mode != ATH12K_SPECTRAL_DISABLED); ++ ar->spectral.mode = mode; ++ ++ ret = ath12k_wmi_vdev_spectral_enable(ar, arvif->vdev_id, ++ ATH12K_WMI_SPECTRAL_TRIGGER_CMD_CLEAR, ++ ATH12K_WMI_SPECTRAL_ENABLE_CMD_DISABLE); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to enable spectral scan: %d\n", ret); ++ return ret; ++ } ++ ++ if (mode == ATH12K_SPECTRAL_DISABLED) ++ return 0; ++ ++ if (mode == ATH12K_SPECTRAL_BACKGROUND) ++ count = ATH12K_WMI_SPECTRAL_COUNT_DEFAULT; ++ else ++ count = max_t(u16, 1, ar->spectral.count); ++ ++ param.vdev_id = arvif->vdev_id; ++ param.scan_count = count; ++ param.scan_fft_size = ar->spectral.fft_size; ++ param.scan_period = ATH12K_WMI_SPECTRAL_PERIOD_DEFAULT; ++ param.scan_priority = ATH12K_WMI_SPECTRAL_PRIORITY_DEFAULT; ++ param.scan_gc_ena = ATH12K_WMI_SPECTRAL_GC_ENA_DEFAULT; ++ param.scan_restart_ena = ATH12K_WMI_SPECTRAL_RESTART_ENA_DEFAULT; ++ param.scan_noise_floor_ref = ATH12K_WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT; ++ param.scan_init_delay = ATH12K_WMI_SPECTRAL_INIT_DELAY_DEFAULT; ++ param.scan_nb_tone_thr = ATH12K_WMI_SPECTRAL_NB_TONE_THR_DEFAULT; ++ param.scan_str_bin_thr = ATH12K_WMI_SPECTRAL_STR_BIN_THR_DEFAULT; ++ param.scan_wb_rpt_mode = ATH12K_WMI_SPECTRAL_WB_RPT_MODE_DEFAULT; ++ param.scan_rssi_rpt_mode = ATH12K_WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT; ++ param.scan_rssi_thr = ATH12K_WMI_SPECTRAL_RSSI_THR_DEFAULT; ++ param.scan_pwr_format = ATH12K_WMI_SPECTRAL_PWR_FORMAT_DEFAULT; ++ param.scan_rpt_mode = ATH12K_WMI_SPECTRAL_RPT_MODE_DEFAULT; ++ param.scan_bin_scale = ATH12K_WMI_SPECTRAL_BIN_SCALE_DEFAULT; ++ param.scan_dbm_adj = ATH12K_WMI_SPECTRAL_DBM_ADJ_DEFAULT; ++ param.scan_chn_mask = ATH12K_WMI_SPECTRAL_CHN_MASK_DEFAULT; ++ ++ ret = ath12k_wmi_vdev_spectral_conf(ar, ¶m); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to configure spectral scan: %d\n", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static ssize_t ath12k_read_file_spec_scan_ctl(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ char *mode = ""; ++ size_t len; ++ enum ath12k_spectral_mode spectral_mode; ++ ++ mutex_lock(&ar->conf_mutex); ++ spectral_mode = ar->spectral.mode; ++ mutex_unlock(&ar->conf_mutex); ++ ++ switch (spectral_mode) { ++ case ATH12K_SPECTRAL_DISABLED: ++ mode = "disable"; ++ break; ++ case ATH12K_SPECTRAL_BACKGROUND: ++ mode = "background"; ++ break; ++ case ATH12K_SPECTRAL_MANUAL: ++ mode = "manual"; ++ break; ++ } ++ ++ len = strlen(mode); ++ return simple_read_from_buffer(user_buf, count, ppos, mode, len); ++} ++ ++static ssize_t ath12k_write_file_spec_scan_ctl(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ char buf[32]; ++ ssize_t len; ++ int ret; ++ ++ len = min(count, sizeof(buf) - 1); ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ if (strncmp("trigger", buf, 7) == 0) { ++ if (ar->spectral.mode == ATH12K_SPECTRAL_MANUAL || ++ ar->spectral.mode == ATH12K_SPECTRAL_BACKGROUND) { ++ /* reset the configuration to adopt possibly changed ++ * debugfs parameters ++ */ ++ ret = ath12k_spectral_scan_config(ar, ar->spectral.mode); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to reconfigure spectral scan: %d\n", ++ ret); ++ goto unlock; ++ } ++ ++ ret = ath12k_spectral_scan_trigger(ar); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to trigger spectral scan: %d\n", ++ ret); ++ } ++ } else { ++ ret = -EINVAL; ++ } ++ } else if (strncmp("background", buf, 10) == 0) { ++ ret = ath12k_spectral_scan_config(ar, ATH12K_SPECTRAL_BACKGROUND); ++ } else if (strncmp("manual", buf, 6) == 0) { ++ ret = ath12k_spectral_scan_config(ar, ATH12K_SPECTRAL_MANUAL); ++ } else if (strncmp("disable", buf, 7) == 0) { ++ ret = ath12k_spectral_scan_config(ar, ATH12K_SPECTRAL_DISABLED); ++ } else { ++ ret = -EINVAL; ++ } ++ ++unlock: ++ mutex_unlock(&ar->conf_mutex); ++ ++ if (ret) ++ return ret; ++ ++ return count; ++} ++ ++static const struct file_operations fops_scan_ctl = { ++ .read = ath12k_read_file_spec_scan_ctl, ++ .write = ath12k_write_file_spec_scan_ctl, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++static ssize_t ath12k_read_file_spectral_count(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ char buf[32]; ++ size_t len = 0; ++ u16 spectral_count; ++ ++ mutex_lock(&ar->conf_mutex); ++ spectral_count = ar->spectral.count; ++ mutex_unlock(&ar->conf_mutex); ++ ++ len = scnprintf(buf, sizeof(buf) - len, "%d\n", spectral_count); ++ return simple_read_from_buffer(user_buf, count, ppos, buf, len); ++} ++ ++static ssize_t ath12k_write_file_spectral_count(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ unsigned long val; ++ 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, &val)) ++ return -EINVAL; ++ ++ if (val > ATH12K_SPECTRAL_SCAN_COUNT_MAX) ++ return -EINVAL; ++ ++ mutex_lock(&ar->conf_mutex); ++ ar->spectral.count = val; ++ mutex_unlock(&ar->conf_mutex); ++ ++ return count; ++} ++ ++static const struct file_operations fops_scan_count = { ++ .read = ath12k_read_file_spectral_count, ++ .write = ath12k_write_file_spectral_count, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++static ssize_t ath12k_read_file_spectral_bins(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ char buf[32]; ++ unsigned int bins, fft_size; ++ size_t len = 0; ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ fft_size = ar->spectral.fft_size; ++ bins = 1 << fft_size; ++ ++ mutex_unlock(&ar->conf_mutex); ++ ++ len = scnprintf(buf, sizeof(buf) - len, "%d\n", bins); ++ return simple_read_from_buffer(user_buf, count, ppos, buf, len); ++} ++ ++static ssize_t ath12k_write_file_spectral_bins(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ unsigned long val; ++ 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, &val)) ++ return -EINVAL; ++ ++ if (val < ATH12K_SPECTRAL_ATH12K_MIN_BINS || ++ val > SPECTRAL_ATH12K_MAX_NUM_BINS) ++ return -EINVAL; ++ ++ if (!is_power_of_2(val)) ++ return -EINVAL; ++ ++ mutex_lock(&ar->conf_mutex); ++ ar->spectral.fft_size = ilog2(val); ++ mutex_unlock(&ar->conf_mutex); ++ ++ return count; ++} ++ ++static const struct file_operations fops_scan_bins = { ++ .read = ath12k_read_file_spectral_bins, ++ .write = ath12k_write_file_spectral_bins, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++static int ath12k_spectral_pull_summary(struct ath12k *ar, ++ struct wmi_dma_buf_release_meta_data *meta, ++ struct spectral_summary_fft_report *summary, ++ struct ath12k_spectral_summary_report *report) ++{ ++ report->timestamp = __le32_to_cpu(summary->timestamp); ++ report->agc_total_gain = FIELD_GET(SPECTRAL_SUMMARY_INFO0_AGC_TOTAL_GAIN, ++ __le32_to_cpu(summary->info0)); ++ report->out_of_band_flag = FIELD_GET(SPECTRAL_SUMMARY_INFO0_OB_FLAG, ++ __le32_to_cpu(summary->info0)); ++ report->grp_idx = FIELD_GET(SPECTRAL_SUMMARY_INFO0_GRP_IDX, ++ __le32_to_cpu(summary->info0)); ++ report->rf_saturation = FIELD_GET(SPECTRAL_SUMMARY_INFO0_RECENT_RFSAT, ++ __le32_to_cpu(summary->info0)); ++ report->inb_pwr_db = FIELD_GET(SPECTRAL_SUMMARY_INFO0_INBAND_PWR_DB, ++ __le32_to_cpu(summary->info0)); ++ report->false_scan = FIELD_GET(SPECTRAL_SUMMARY_INFO0_FALSE_SCAN, ++ __le32_to_cpu(summary->info0)); ++ report->detector_id = FIELD_GET(SPECTRAL_SUMMARY_INFO0_DETECTOR_ID, ++ __le32_to_cpu(summary->info0)); ++ report->primary80 = FIELD_GET(SPECTRAL_SUMMARY_INFO0_PRI80, ++ __le32_to_cpu(summary->info0)); ++ report->peak_idx = FIELD_GET(SPECTRAL_SUMMARY_INFO2_PEAK_SIGNED_IDX, ++ __le32_to_cpu(summary->info2)); ++ report->peak_mag = FIELD_GET(SPECTRAL_SUMMARY_INFO2_PEAK_MAGNITUDE, ++ __le32_to_cpu(summary->info2)); ++ report->gain_change = FIELD_GET(SPECTRAL_SUMMARY_INFO2_GAIN_CHANGE, ++ __le32_to_cpu(summary->info2)); ++ ++ memcpy(&report->meta, meta, sizeof(*meta)); ++ ++ return 0; ++} ++ ++static int ath12k_spectral_pull_search(struct ath12k *ar, ++ struct spectral_search_fft_report *search, ++ struct ath12k_spectral_search_report *report) ++{ ++ report->timestamp = __le32_to_cpu(search->timestamp); ++ report->detector_id = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_DETECTOR_ID, ++ __le32_to_cpu(search->info0)); ++ report->fft_count = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_FFT_NUM, ++ __le32_to_cpu(search->info0)); ++ report->radar_check = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_RADAR_CHECK, ++ __le32_to_cpu(search->info0)); ++ report->peak_idx = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_PEAK_SIGNED_IDX, ++ __le32_to_cpu(search->info0)); ++ report->chain_idx = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_CHAIN_IDX, ++ __le32_to_cpu(search->info0)); ++ report->base_pwr_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO1_BASE_PWR_DB, ++ __le32_to_cpu(search->info1)); ++ report->total_gain_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO1_TOTAL_GAIN_DB, ++ __le32_to_cpu(search->info1)); ++ report->strong_bin_count = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_NUM_STRONG_BINS, ++ __le32_to_cpu(search->info2)); ++ report->peak_mag = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_PEAK_MAGNITUDE, ++ __le32_to_cpu(search->info2)); ++ report->avg_pwr_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_AVG_PWR_DB, ++ __le32_to_cpu(search->info2)); ++ report->rel_pwr_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_REL_PWR_DB, ++ __le32_to_cpu(search->info2)); ++ ++ return 0; ++} ++ ++static u8 ath12k_spectral_get_max_exp(s8 max_index, u8 max_magnitude, ++ int bin_len, u8 *bins) ++{ ++ int dc_pos; ++ u8 max_exp; ++ ++ dc_pos = bin_len / 2; ++ ++ /* peak index outside of bins */ ++ if (dc_pos <= max_index || -dc_pos >= max_index) ++ return 0; ++ ++ for (max_exp = 0; max_exp < 8; max_exp++) { ++ if (bins[dc_pos + max_index] == (max_magnitude >> max_exp)) ++ break; ++ } ++ ++ /* max_exp not found */ ++ if (bins[dc_pos + max_index] != (max_magnitude >> max_exp)) ++ return 0; ++ ++ return max_exp; ++} ++ ++static void ath12k_spectral_parse_fft(u8 *outbins, u8 *inbins, int num_bins, u8 fft_sz) ++{ ++ int i, j; ++ ++ i = 0; ++ j = 0; ++ while (i < num_bins) { ++ outbins[i] = inbins[j]; ++ i++; ++ j += fft_sz; ++ } ++} ++ ++static ++int ath12k_spectral_process_fft(struct ath12k *ar, ++ struct ath12k_spectral_summary_report *summary, ++ void *data, ++ struct fft_sample_ath12k *fft_sample, ++ u32 data_len) ++{ ++ struct ath12k_base *ab = ar->ab; ++ struct spectral_search_fft_report *fft_report = data; ++ struct ath12k_spectral_search_report search; ++ struct spectral_tlv *tlv; ++ int tlv_len, bin_len, num_bins; ++ u16 length, freq; ++ u8 chan_width_mhz; ++ int ret; ++ ++ lockdep_assert_held(&ar->spectral.lock); ++ ++ if (!ab->hw_params->spectral_fft_sz) { ++ ath12k_warn(ab, "invalid bin size type for hw rev %d\n", ++ ab->hw_rev); ++ return -EINVAL; ++ } ++ ++ tlv = (struct spectral_tlv *)data; ++ tlv_len = FIELD_GET(SPECTRAL_TLV_HDR_LEN, __le32_to_cpu(tlv->header)); ++ /* convert Dword into bytes */ ++ tlv_len *= ATH12K_SPECTRAL_DWORD_SIZE; ++ bin_len = tlv_len - (sizeof(*fft_report) - sizeof(*tlv)); ++ ++ if (data_len < (bin_len + sizeof(*fft_report))) { ++ ath12k_warn(ab, "mismatch in expected bin len %d and data len %d\n", ++ bin_len, data_len); ++ return -EINVAL; ++ } ++ ++ num_bins = bin_len / ATH12K_SPECTRAL_BIN_SIZE; ++ /* Only In-band bins are useful to user for visualize */ ++ num_bins >>= 1; ++ ++ if (num_bins < ATH12K_SPECTRAL_ATH12K_MIN_IB_BINS || ++ num_bins > ATH12K_SPECTRAL_ATH12K_MAX_IB_BINS || ++ !is_power_of_2(num_bins)) { ++ ath12k_warn(ab, "Invalid num of bins %d\n", num_bins); ++ return -EINVAL; ++ } ++ ++ ret = ath12k_spectral_pull_search(ar, data, &search); ++ if (ret) { ++ ath12k_warn(ab, "failed to pull search report %d\n", ret); ++ return ret; ++ } ++ ++ chan_width_mhz = summary->meta.ch_width; ++ ++ switch (chan_width_mhz) { ++ case ATH12K_SPECTRAL_20MHZ: ++ case ATH12K_SPECTRAL_40MHZ: ++ case ATH12K_SPECTRAL_80MHZ: ++ fft_sample->chan_width_mhz = chan_width_mhz; ++ break; ++ default: ++ ath12k_warn(ab, "invalid channel width %d\n", chan_width_mhz); ++ return -EINVAL; ++ } ++ ++ length = sizeof(*fft_sample) - sizeof(struct fft_sample_tlv) + num_bins; ++ fft_sample->tlv.type = ATH_FFT_SAMPLE_ATH12K; ++ fft_sample->tlv.length = __cpu_to_be16(length); ++ ++ fft_sample->tsf = __cpu_to_be32(search.timestamp); ++ fft_sample->max_magnitude = __cpu_to_be16(search.peak_mag); ++ fft_sample->max_index = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_PEAK_SIGNED_IDX, ++ __le32_to_cpu(fft_report->info0)); ++ ++ summary->inb_pwr_db >>= 1; ++ fft_sample->rssi = __cpu_to_be16(summary->inb_pwr_db); ++ fft_sample->noise = __cpu_to_be32(summary->meta.noise_floor[search.chain_idx]); ++ ++ freq = summary->meta.freq1; ++ fft_sample->freq1 = __cpu_to_be16(freq); ++ ++ freq = summary->meta.freq2; ++ fft_sample->freq2 = __cpu_to_be16(freq); ++ ++ ath12k_spectral_parse_fft(fft_sample->data, fft_report->bins, num_bins, ++ ab->hw_params->spectral_fft_sz); ++ ++ fft_sample->max_exp = ath12k_spectral_get_max_exp(fft_sample->max_index, ++ search.peak_mag, ++ num_bins, ++ fft_sample->data); ++ ++ if (ar->spectral.rfs_scan) ++ relay_write(ar->spectral.rfs_scan, fft_sample, ++ length + sizeof(struct fft_sample_tlv)); ++ ++ return 0; ++} ++ ++static int ath12k_spectral_process_data(struct ath12k *ar, ++ struct ath12k_dbring_data *param) ++{ ++ struct ath12k_base *ab = ar->ab; ++ struct spectral_tlv *tlv; ++ struct spectral_summary_fft_report *summary = NULL; ++ struct ath12k_spectral_summary_report summ_rpt; ++ struct fft_sample_ath12k *fft_sample = NULL; ++ u8 *data; ++ u32 data_len, i; ++ u8 sign, tag; ++ int tlv_len, sample_sz; ++ int ret; ++ bool quit = false; ++ ++ spin_lock_bh(&ar->spectral.lock); ++ ++ if (!ar->spectral.enabled) { ++ ret = -EINVAL; ++ goto unlock; ++ } ++ ++ sample_sz = sizeof(*fft_sample) + ATH12K_SPECTRAL_ATH12K_MAX_IB_BINS; ++ fft_sample = kmalloc(sample_sz, GFP_ATOMIC); ++ if (!fft_sample) { ++ ret = -ENOBUFS; ++ goto unlock; ++ } ++ ++ data = param->data; ++ data_len = param->data_sz; ++ i = 0; ++ while (!quit && (i < data_len)) { ++ if ((i + sizeof(*tlv)) > data_len) { ++ ath12k_warn(ab, "failed to parse spectral tlv hdr at bytes %d\n", ++ i); ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ tlv = (struct spectral_tlv *)&data[i]; ++ sign = FIELD_GET(SPECTRAL_TLV_HDR_SIGN, ++ __le32_to_cpu(tlv->header)); ++ if (sign != ATH12K_SPECTRAL_SIGNATURE) { ++ ath12k_warn(ab, "Invalid sign 0x%x at bytes %d\n", ++ sign, i); ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ tlv_len = FIELD_GET(SPECTRAL_TLV_HDR_LEN, ++ __le32_to_cpu(tlv->header)); ++ /* convert Dword into bytes */ ++ tlv_len *= ATH12K_SPECTRAL_DWORD_SIZE; ++ if ((i + sizeof(*tlv) + tlv_len) > data_len) { ++ ath12k_warn(ab, "failed to parse spectral tlv payload at bytes %d tlv_len:%d data_len:%d\n", ++ i, tlv_len, data_len); ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ tag = FIELD_GET(SPECTRAL_TLV_HDR_TAG, ++ __le32_to_cpu(tlv->header)); ++ switch (tag) { ++ case ATH12K_SPECTRAL_TAG_SCAN_SUMMARY: ++ /* HW bug in tlv length of summary report, ++ * HW report 3 DWORD size but the data payload ++ * is 4 DWORD size (16 bytes). ++ * Need to remove this workaround once HW bug fixed ++ */ ++ tlv_len = sizeof(*summary) - sizeof(*tlv); ++ ++ if (tlv_len < (sizeof(*summary) - sizeof(*tlv))) { ++ ath12k_warn(ab, "failed to parse spectral summary at bytes %d tlv_len:%d\n", ++ i, tlv_len); ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ summary = (struct spectral_summary_fft_report *)tlv; ++ ath12k_spectral_pull_summary(ar, ¶m->meta, ++ summary, &summ_rpt); ++ break; ++ case ATH12K_SPECTRAL_TAG_SCAN_SEARCH: ++ if (tlv_len < (sizeof(struct spectral_search_fft_report) - ++ sizeof(*tlv))) { ++ ath12k_warn(ab, "failed to parse spectral search fft at bytes %d\n", ++ i); ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ memset(fft_sample, 0, sample_sz); ++ ret = ath12k_spectral_process_fft(ar, &summ_rpt, tlv, ++ fft_sample, ++ data_len - i); ++ if (ret) { ++ ath12k_warn(ab, "failed to process spectral fft at bytes %d\n", ++ i); ++ goto err; ++ } ++ quit = true; ++ break; ++ } ++ ++ i += sizeof(*tlv) + tlv_len; ++ } ++ ++ ret = 0; ++ ++err: ++ kfree(fft_sample); ++unlock: ++ spin_unlock_bh(&ar->spectral.lock); ++ return ret; ++} ++ ++static int ath12k_spectral_ring_alloc(struct ath12k *ar, ++ struct ath12k_dbring_cap *db_cap) ++{ ++ struct ath12k_spectral *sp = &ar->spectral; ++ int ret; ++ ++ ret = ath12k_dbring_srng_setup(ar, &sp->rx_ring, ++ 0, db_cap->min_elem); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to setup db ring\n"); ++ return ret; ++ } ++ ++ ath12k_dbring_set_cfg(ar, &sp->rx_ring, ++ ATH12K_SPECTRAL_NUM_RESP_PER_EVENT, ++ ATH12K_SPECTRAL_EVENT_TIMEOUT_MS, ++ ath12k_spectral_process_data); ++ ++ ret = ath12k_dbring_buf_setup(ar, &sp->rx_ring, db_cap); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to setup db ring buffer\n"); ++ goto srng_cleanup; ++ } ++ ++ ret = ath12k_dbring_wmi_cfg_setup(ar, &sp->rx_ring, ++ WMI_DIRECT_BUF_SPECTRAL); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to setup db ring cfg\n"); ++ goto buffer_cleanup; ++ } ++ ++ return 0; ++ ++buffer_cleanup: ++ ath12k_dbring_buf_cleanup(ar, &sp->rx_ring); ++srng_cleanup: ++ ath12k_dbring_srng_cleanup(ar, &sp->rx_ring); ++ return ret; ++} ++ ++static inline void ath12k_spectral_ring_free(struct ath12k *ar) ++{ ++ struct ath12k_spectral *sp = &ar->spectral; ++ ++ if (!sp->enabled) ++ return; ++ ++ ath12k_dbring_srng_cleanup(ar, &sp->rx_ring); ++ ath12k_dbring_buf_cleanup(ar, &sp->rx_ring); ++} ++ ++static inline void ath12k_spectral_debug_unregister(struct ath12k *ar) ++{ ++ debugfs_remove(ar->spectral.scan_bins); ++ ar->spectral.scan_bins = NULL; ++ ++ debugfs_remove(ar->spectral.scan_count); ++ ar->spectral.scan_count = NULL; ++ ++ debugfs_remove(ar->spectral.scan_ctl); ++ ar->spectral.scan_ctl = NULL; ++ ++ if (ar->spectral.rfs_scan) { ++ relay_close(ar->spectral.rfs_scan); ++ ar->spectral.rfs_scan = NULL; ++ } ++} ++ ++int ath12k_spectral_vif_stop(struct ath12k_vif *arvif) ++{ ++ if (!arvif->spectral_enabled) ++ return 0; ++ ++ return ath12k_spectral_scan_config(arvif->ar, ATH12K_SPECTRAL_DISABLED); ++} ++ ++void ath12k_spectral_reset_buffer(struct ath12k *ar) ++{ ++ if (!ar->spectral.enabled) ++ return; ++ ++ if (ar->spectral.rfs_scan) ++ relay_reset(ar->spectral.rfs_scan); ++} ++ ++void ath12k_spectral_deinit(struct ath12k_base *ab) ++{ ++ struct ath12k *ar; ++ struct ath12k_spectral *sp; ++ int i; ++ ++ for (i = 0; i < ab->num_radios; i++) { ++ ar = ab->pdevs[i].ar; ++ sp = &ar->spectral; ++ ++ if (!sp->enabled) ++ continue; ++ ++ ath12k_spectral_debug_unregister(ar); ++ ath12k_spectral_ring_free(ar); ++ ++ spin_lock_bh(&sp->lock); ++ ++ sp->mode = ATH12K_SPECTRAL_DISABLED; ++ sp->enabled = false; ++ ++ spin_unlock_bh(&sp->lock); ++ } ++} ++ ++static inline int ath12k_spectral_debug_register(struct ath12k *ar) ++{ ++ int ret; ++ ++ ar->spectral.rfs_scan = relay_open("spectral_scan", ++ ar->debug.debugfs_pdev, ++ ATH12K_SPECTRAL_SUB_BUFF_SIZE, ++ ATH12K_SPECTRAL_NUM_SUB_BUF, ++ &rfs_scan_cb, NULL); ++ if (!ar->spectral.rfs_scan) { ++ ath12k_warn(ar->ab, "failed to open relay in pdev %d\n", ++ ar->pdev_idx); ++ return -EINVAL; ++ } ++ ++ ar->spectral.scan_ctl = debugfs_create_file("spectral_scan_ctl", ++ 0600, ++ ar->debug.debugfs_pdev, ar, ++ &fops_scan_ctl); ++ if (!ar->spectral.scan_ctl) { ++ ath12k_warn(ar->ab, "failed to open debugfs in pdev %d\n", ++ ar->pdev_idx); ++ ret = -EINVAL; ++ goto debug_unregister; ++ } ++ ++ ar->spectral.scan_count = debugfs_create_file("spectral_count", ++ 0600, ++ ar->debug.debugfs_pdev, ar, ++ &fops_scan_count); ++ if (!ar->spectral.scan_count) { ++ ath12k_warn(ar->ab, "failed to open debugfs in pdev %d\n", ++ ar->pdev_idx); ++ ret = -EINVAL; ++ goto debug_unregister; ++ } ++ ++ ar->spectral.scan_bins = debugfs_create_file("spectral_bins", ++ 0600, ++ ar->debug.debugfs_pdev, ar, ++ &fops_scan_bins); ++ if (!ar->spectral.scan_bins) { ++ ath12k_warn(ar->ab, "failed to open debugfs in pdev %d\n", ++ ar->pdev_idx); ++ ret = -EINVAL; ++ goto debug_unregister; ++ } ++ ++ return 0; ++ ++debug_unregister: ++ ath12k_spectral_debug_unregister(ar); ++ return ret; ++} ++ ++int ath12k_spectral_init(struct ath12k_base *ab) ++{ ++ struct ath12k *ar; ++ struct ath12k_spectral *sp; ++ struct ath12k_dbring_cap db_cap; ++ int ret; ++ int i; ++ ++ if (!test_bit(WMI_TLV_SERVICE_FREQINFO_IN_METADATA, ++ ab->wmi_ab.svc_map)) ++ return 0; ++ ++ if (!ab->hw_params->spectral_fft_sz) ++ return 0; ++ ++ for (i = 0; i < ab->num_radios; i++) { ++ ar = ab->pdevs[i].ar; ++ sp = &ar->spectral; ++ ++ ret = ath12k_dbring_get_cap(ar->ab, ar->pdev_idx, ++ WMI_DIRECT_BUF_SPECTRAL, ++ &db_cap); ++ if (ret) ++ continue; ++ ++ idr_init(&sp->rx_ring.bufs_idr); ++ spin_lock_init(&sp->rx_ring.idr_lock); ++ spin_lock_init(&sp->lock); ++ ++ ret = ath12k_spectral_ring_alloc(ar, &db_cap); ++ if (ret) { ++ ath12k_warn(ab, "failed to init spectral ring for pdev %d\n", ++ i); ++ goto deinit; ++ } ++ ++ spin_lock_bh(&sp->lock); ++ ++ sp->mode = ATH12K_SPECTRAL_DISABLED; ++ sp->count = ATH12K_WMI_SPECTRAL_COUNT_DEFAULT; ++ sp->fft_size = ATH12K_WMI_SPECTRAL_FFT_SIZE_DEFAULT; ++ sp->enabled = true; ++ ++ spin_unlock_bh(&sp->lock); ++ ++ ret = ath12k_spectral_debug_register(ar); ++ if (ret) { ++ ath12k_warn(ab, "failed to register spectral for pdev %d\n", ++ i); ++ goto deinit; ++ } ++ } ++ ++ return 0; ++ ++deinit: ++ ath12k_spectral_deinit(ab); ++ return ret; ++} ++ ++enum ath12k_spectral_mode ath12k_spectral_get_mode(struct ath12k *ar) ++{ ++ if (ar->spectral.enabled) ++ return ar->spectral.mode; ++ else ++ return ATH12K_SPECTRAL_DISABLED; ++} ++ ++struct ath12k_dbring *ath12k_spectral_get_dbring(struct ath12k *ar) ++{ ++ if (ar->spectral.enabled) ++ return &ar->spectral.rx_ring; ++ else ++ return NULL; ++} +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/spectral.h +@@ -0,0 +1,83 @@ ++/* SPDX-License-Identifier: BSD-3-Clause-Clear */ ++/* ++ * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef ATH12K_SPECTRAL_H ++#define ATH12K_SPECTRAL_H ++ ++#include "../spectral_common.h" ++#include "dbring.h" ++ ++/* enum ath12k_spectral_mode: ++ * ++ * @SPECTRAL_DISABLED: spectral mode is disabled ++ * @SPECTRAL_BACKGROUND: hardware sends samples when it is not busy with ++ * something else. ++ * @SPECTRAL_MANUAL: spectral scan is enabled, triggering for samples ++ * is performed manually. ++ */ ++enum ath12k_spectral_mode { ++ ATH12K_SPECTRAL_DISABLED = 0, ++ ATH12K_SPECTRAL_BACKGROUND, ++ ATH12K_SPECTRAL_MANUAL, ++}; ++ ++struct ath12k_spectral { ++ struct ath12k_dbring rx_ring; ++ /* Protects enabled */ ++ spinlock_t lock; ++ struct rchan *rfs_scan; /* relay(fs) channel for spectral scan */ ++ struct dentry *scan_ctl; ++ struct dentry *scan_count; ++ struct dentry *scan_bins; ++ enum ath12k_spectral_mode mode; ++ u16 count; ++ u8 fft_size; ++ bool enabled; ++}; ++ ++#ifdef CPTCFG_ATH12K_SPECTRAL ++ ++int ath12k_spectral_init(struct ath12k_base *ab); ++void ath12k_spectral_deinit(struct ath12k_base *ab); ++int ath12k_spectral_vif_stop(struct ath12k_vif *arvif); ++void ath12k_spectral_reset_buffer(struct ath12k *ar); ++enum ath12k_spectral_mode ath12k_spectral_get_mode(struct ath12k *ar); ++struct ath12k_dbring *ath12k_spectral_get_dbring(struct ath12k *ar); ++ ++#else ++ ++static inline int ath12k_spectral_init(struct ath12k_base *ab) ++{ ++ return 0; ++} ++ ++static inline void ath12k_spectral_deinit(struct ath12k_base *ab) ++{ ++} ++ ++static inline int ath12k_spectral_vif_stop(struct ath12k_vif *arvif) ++{ ++ return 0; ++} ++ ++static inline void ath12k_spectral_reset_buffer(struct ath12k *ar) ++{ ++} ++ ++static inline ++enum ath12k_spectral_mode ath12k_spectral_get_mode(struct ath12k *ar) ++{ ++ return ATH12K_SPECTRAL_DISABLED; ++} ++ ++static inline ++struct ath12k_dbring *ath12k_spectral_get_dbring(struct ath12k *ar) ++{ ++ return NULL; ++} ++ ++#endif /* CPTCFG_ATH12K_SPECTRAL */ ++#endif /* ATH12K_SPECTRAL_H */ +--- a/local-symbols ++++ b/local-symbols +@@ -139,3 +139,4 @@ ATH12K= + ATH12K_DEBUG= + ATH12K_DEBUGFS= + ATH12K_TRACING= ++ATH12K_SPECTRAL= diff --git a/feeds/ipq95xx/mac80211/patches/qca/506-ath12k-add-testmode-support.patch b/feeds/ipq95xx/mac80211/patches/qca/506-ath12k-add-testmode-support.patch new file mode 100644 index 000000000..da2217965 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/506-ath12k-add-testmode-support.patch @@ -0,0 +1,338 @@ +From 2258561e0cdaddf1380c55749a199e6c4e95694a Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Thu, 1 Sep 2022 15:52:03 +0530 +Subject: [PATCH 5/5] Revert "ath12k: remove testmode support" + +This reverts commit e8debdc2b28102dde483374e29ecc305639b87a9. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath12k/Makefile | 1 + + drivers/net/wireless/ath/ath12k/mac.c | 3 +- + drivers/net/wireless/ath/ath12k/testmode.c | 200 +++++++++++++++++++ + drivers/net/wireless/ath/ath12k/testmode.h | 30 +++ + drivers/net/wireless/ath/ath12k/testmode_i.h | 51 +++++ + 5 files changed, 284 insertions(+), 1 deletion(-) + create mode 100644 drivers/net/wireless/ath/ath12k/testmode.c + create mode 100644 drivers/net/wireless/ath/ath12k/testmode.h + create mode 100644 drivers/net/wireless/ath/ath12k/testmode_i.h + +--- a/drivers/net/wireless/ath/ath12k/Makefile ++++ b/drivers/net/wireless/ath/ath12k/Makefile +@@ -23,6 +23,7 @@ ath12k-y += core.o \ + dp_mon.o + + ath12k-$(CPTCFG_ATH12K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o ++ath12k-$(CPTCFG_NL80211_TESTMODE) += testmode.o + ath12k-$(CPTCFG_ATH12K_TRACING) += trace.o + ath12k-$(CONFIG_THERMAL) += thermal.o + ath12k-$(CPTCFG_ATH12K_SPECTRAL) += spectral.o +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -13,6 +13,7 @@ + #include "hw.h" + #include "dp_tx.h" + #include "dp_rx.h" ++#include "testmode.h" + #include "peer.h" + #include "debugfs_sta.h" + +@@ -6469,7 +6470,7 @@ static const struct ieee80211_ops ath12k + .get_survey = ath12k_mac_op_get_survey, + .flush = ath12k_mac_op_flush, + .sta_statistics = ath12k_mac_op_sta_statistics, +- ++ CFG80211_TESTMODE_CMD(ath12k_tm_cmd) + #ifdef CPTCFG_ATH12K_DEBUGFS + .sta_add_debugfs = ath12k_debugfs_sta_op_add, + #endif +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/testmode.c +@@ -0,0 +1,200 @@ ++// SPDX-License-Identifier: BSD-3-Clause-Clear ++/* ++ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include "testmode.h" ++#include ++#include "debug.h" ++#include "wmi.h" ++#include "hw.h" ++#include "core.h" ++#include "testmode_i.h" ++ ++static const struct nla_policy ath12k_tm_policy[ATH12K_TM_ATTR_MAX + 1] = { ++ [ATH12K_TM_ATTR_CMD] = { .type = NLA_U32 }, ++ [ATH12K_TM_ATTR_DATA] = { .type = NLA_BINARY, ++ .len = ATH12K_TM_DATA_MAX_LEN }, ++ [ATH12K_TM_ATTR_WMI_CMDID] = { .type = NLA_U32 }, ++ [ATH12K_TM_ATTR_VERSION_MAJOR] = { .type = NLA_U32 }, ++ [ATH12K_TM_ATTR_VERSION_MINOR] = { .type = NLA_U32 }, ++}; ++ ++/* Returns true if callee consumes the skb and the skb should be discarded. ++ * Returns false if skb is not used. Does not sleep. ++ */ ++bool ath12k_tm_event_wmi(struct ath12k *ar, u32 cmd_id, struct sk_buff *skb) ++{ ++ struct sk_buff *nl_skb; ++ bool consumed; ++ int ret; ++ ++ ath12k_dbg(ar->ab, ATH12K_DBG_TESTMODE, ++ "testmode event wmi cmd_id %d skb %pK skb->len %d\n", ++ cmd_id, skb, skb->len); ++ ++ ath12k_dbg_dump(ar->ab, ATH12K_DBG_TESTMODE, NULL, "", skb->data, skb->len); ++ ++ spin_lock_bh(&ar->data_lock); ++ ++ consumed = true; ++ ++ nl_skb = cfg80211_testmode_alloc_event_skb(ar->hw->wiphy, ++ 2 * sizeof(u32) + skb->len, ++ GFP_ATOMIC); ++ if (!nl_skb) { ++ ath12k_warn(ar->ab, ++ "failed to allocate skb for testmode wmi event\n"); ++ goto out; ++ } ++ ++ ret = nla_put_u32(nl_skb, ATH12K_TM_ATTR_CMD, ATH12K_TM_CMD_WMI); ++ if (ret) { ++ ath12k_warn(ar->ab, ++ "failed to put testmode wmi event cmd attribute: %d\n", ++ ret); ++ kfree_skb(nl_skb); ++ goto out; ++ } ++ ++ ret = nla_put_u32(nl_skb, ATH12K_TM_ATTR_WMI_CMDID, cmd_id); ++ if (ret) { ++ ath12k_warn(ar->ab, ++ "failed to put testmode wmi even cmd_id: %d\n", ++ ret); ++ kfree_skb(nl_skb); ++ goto out; ++ } ++ ++ ret = nla_put(nl_skb, ATH12K_TM_ATTR_DATA, skb->len, skb->data); ++ if (ret) { ++ ath12k_warn(ar->ab, ++ "failed to copy skb to testmode wmi event: %d\n", ++ ret); ++ kfree_skb(nl_skb); ++ goto out; ++ } ++ ++ cfg80211_testmode_event(nl_skb, GFP_ATOMIC); ++ ++out: ++ spin_unlock_bh(&ar->data_lock); ++ ++ return consumed; ++} ++ ++static int ath12k_tm_cmd_get_version(struct ath12k *ar, struct nlattr *tb[]) ++{ ++ struct sk_buff *skb; ++ int ret; ++ ++ ath12k_dbg(ar->ab, ATH12K_DBG_TESTMODE, ++ "testmode cmd get version_major %d version_minor %d\n", ++ ATH12K_TESTMODE_VERSION_MAJOR, ++ ATH12K_TESTMODE_VERSION_MINOR); ++ ++ skb = cfg80211_testmode_alloc_reply_skb(ar->hw->wiphy, ++ nla_total_size(sizeof(u32))); ++ if (!skb) ++ return -ENOMEM; ++ ++ ret = nla_put_u32(skb, ATH12K_TM_ATTR_VERSION_MAJOR, ++ ATH12K_TESTMODE_VERSION_MAJOR); ++ if (ret) { ++ kfree_skb(skb); ++ return ret; ++ } ++ ++ ret = nla_put_u32(skb, ATH12K_TM_ATTR_VERSION_MINOR, ++ ATH12K_TESTMODE_VERSION_MINOR); ++ if (ret) { ++ kfree_skb(skb); ++ return ret; ++ } ++ ++ return cfg80211_testmode_reply(skb); ++} ++ ++static int ath12k_tm_cmd_wmi(struct ath12k *ar, struct nlattr *tb[]) ++{ ++ struct ath12k_pdev_wmi *wmi = ar->wmi; ++ struct sk_buff *skb; ++ u32 cmd_id, buf_len; ++ int ret; ++ void *buf; ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ if (ar->state != ATH12K_STATE_ON) { ++ ret = -ENETDOWN; ++ goto out; ++ } ++ ++ if (!tb[ATH12K_TM_ATTR_DATA]) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ if (!tb[ATH12K_TM_ATTR_WMI_CMDID]) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ buf = nla_data(tb[ATH12K_TM_ATTR_DATA]); ++ buf_len = nla_len(tb[ATH12K_TM_ATTR_DATA]); ++ cmd_id = nla_get_u32(tb[ATH12K_TM_ATTR_WMI_CMDID]); ++ ++ ath12k_dbg(ar->ab, ATH12K_DBG_TESTMODE, ++ "testmode cmd wmi cmd_id %d buf %pK buf_len %d\n", ++ cmd_id, buf, buf_len); ++ ++ ath12k_dbg_dump(ar->ab, ATH12K_DBG_TESTMODE, NULL, "", buf, buf_len); ++ ++ skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, buf_len); ++ if (!skb) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ memcpy(skb->data, buf, buf_len); ++ ++ ret = ath12k_wmi_cmd_send(wmi, skb, cmd_id); ++ if (ret) { ++ dev_kfree_skb(skb); ++ ath12k_warn(ar->ab, "failed to transmit wmi command (testmode): %d\n", ++ ret); ++ goto out; ++ } ++ ++ ret = 0; ++ ++out: ++ mutex_unlock(&ar->conf_mutex); ++ return ret; ++} ++ ++int ath12k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ++ void *data, int len) ++{ ++ struct ath12k *ar = hw->priv; ++ struct nlattr *tb[ATH12K_TM_ATTR_MAX + 1]; ++ int ret; ++ ++ ret = nla_parse(tb, ATH12K_TM_ATTR_MAX, data, len, ath12k_tm_policy, ++ NULL); ++ if (ret) ++ return ret; ++ ++ if (!tb[ATH12K_TM_ATTR_CMD]) ++ return -EINVAL; ++ ++ switch (nla_get_u32(tb[ATH12K_TM_ATTR_CMD])) { ++ case ATH12K_TM_CMD_GET_VERSION: ++ return ath12k_tm_cmd_get_version(ar, tb); ++ case ATH12K_TM_CMD_WMI: ++ return ath12k_tm_cmd_wmi(ar, tb); ++ default: ++ return -EOPNOTSUPP; ++ } ++} +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/testmode.h +@@ -0,0 +1,30 @@ ++/* SPDX-License-Identifier: BSD-3-Clause-Clear */ ++/* ++ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include "core.h" ++ ++#ifdef CPTCFG_NL80211_TESTMODE ++ ++bool ath12k_tm_event_wmi(struct ath12k *ar, u32 cmd_id, struct sk_buff *skb); ++int ath12k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ++ void *data, int len); ++ ++#else ++ ++static inline bool ath12k_tm_event_wmi(struct ath12k *ar, u32 cmd_id, ++ struct sk_buff *skb) ++{ ++ return false; ++} ++ ++static inline int ath12k_tm_cmd(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ void *data, int len) ++{ ++ return 0; ++} ++ ++#endif +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/testmode_i.h +@@ -0,0 +1,51 @@ ++/* SPDX-License-Identifier: BSD-3-Clause-Clear */ ++/* ++ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++/* "API" level of the ath12k testmode interface. Bump it after every ++ * incompatible interface change. ++ */ ++#define ATH12K_TESTMODE_VERSION_MAJOR 1 ++ ++/* Bump this after every _compatible_ interface change, for example ++ * addition of a new command or an attribute. ++ */ ++#define ATH12K_TESTMODE_VERSION_MINOR 0 ++ ++#define ATH12K_TM_DATA_MAX_LEN 5000 ++ ++enum ath12k_tm_attr { ++ __ATH12K_TM_ATTR_INVALID = 0, ++ ATH12K_TM_ATTR_CMD = 1, ++ ATH12K_TM_ATTR_DATA = 2, ++ ATH12K_TM_ATTR_WMI_CMDID = 3, ++ ATH12K_TM_ATTR_VERSION_MAJOR = 4, ++ ATH12K_TM_ATTR_VERSION_MINOR = 5, ++ ATH12K_TM_ATTR_WMI_OP_VERSION = 6, ++ ++ /* keep last */ ++ __ATH12K_TM_ATTR_AFTER_LAST, ++ ATH12K_TM_ATTR_MAX = __ATH12K_TM_ATTR_AFTER_LAST - 1, ++}; ++ ++/* All ath12k testmode interface commands specified in ++ * ATH12K_TM_ATTR_CMD ++ */ ++enum ath12k_tm_cmd { ++ /* Returns the supported ath12k testmode interface version in ++ * ATH12K_TM_ATTR_VERSION. Always guaranteed to work. User space ++ * uses this to verify it's using the correct version of the ++ * testmode interface ++ */ ++ ATH12K_TM_CMD_GET_VERSION = 0, ++ ++ /* The command used to transmit a WMI command to the firmware and ++ * the event to receive WMI events from the firmware. Without ++ * struct wmi_cmd_hdr header, only the WMI payload. Command id is ++ * provided with ATH12K_TM_ATTR_WMI_CMDID and payload in ++ * ATH12K_TM_ATTR_DATA. ++ */ ++ ATH12K_TM_CMD_WMI = 1, ++}; diff --git a/feeds/ipq95xx/mac80211/patches/qca/507-ath12k-add-unused-struct-ath12k_skb_cb-eid.patch b/feeds/ipq95xx/mac80211/patches/qca/507-ath12k-add-unused-struct-ath12k_skb_cb-eid.patch new file mode 100644 index 000000000..3e0ed533f --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/507-ath12k-add-unused-struct-ath12k_skb_cb-eid.patch @@ -0,0 +1,40 @@ +From 698cb63c06cd840d0c208b3dce3dff1002ae93c0 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Mon, 5 Sep 2022 11:20:11 +0530 +Subject: [PATCH] Revert "ath12k: remove unused struct ath12k_skb_cb::eid" + +This reverts commit 02460bb5987624cd1e3853deab5f4d48d32d7df3. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/htc.c | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h +index f8e7a122fe6d..2de31d5b1c10 100644 +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -87,6 +87,7 @@ enum ath12k_skb_flags { + + struct ath12k_skb_cb { + dma_addr_t paddr; ++ u8 eid; + u8 flags; + u32 cipher; + struct ath12k *ar; +diff --git a/drivers/net/wireless/ath/ath12k/htc.c b/drivers/net/wireless/ath/ath12k/htc.c +index ff1bddfe4b8f..dff8af327a04 100644 +--- a/drivers/net/wireless/ath/ath12k/htc.c ++++ b/drivers/net/wireless/ath/ath12k/htc.c +@@ -110,6 +110,7 @@ int ath12k_htc_send(struct ath12k_htc *htc, + + ath12k_htc_prepare_tx_skb(ep, skb); + ++ skb_cb->eid = eid; + skb_cb->paddr = dma_map_single(dev, skb->data, skb->len, DMA_TO_DEVICE); + ret = dma_mapping_error(dev, skb_cb->paddr); + if (ret) { +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/508-ath12k-Use-reserved-host-DDR-addresses-from-DT-for-P.patch b/feeds/ipq95xx/mac80211/patches/qca/508-ath12k-Use-reserved-host-DDR-addresses-from-DT-for-P.patch index de1622eb2..a5a5c7d35 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/508-ath12k-Use-reserved-host-DDR-addresses-from-DT-for-P.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/508-ath12k-Use-reserved-host-DDR-addresses-from-DT-for-P.patch @@ -17,11 +17,9 @@ Signed-off-by: P Praneesh drivers/net/wireless/ath/ath12k/qmi.c | 47 ++++++++++++++++++++++++++--------- 3 files changed, 72 insertions(+), 15 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/mhi.c b/drivers/net/wireless/ath/ath12k/mhi.c -index b60ae8c..4fbb2b5 100644 --- a/drivers/net/wireless/ath/ath12k/mhi.c +++ b/drivers/net/wireless/ath/ath12k/mhi.c -@@ -3,6 +3,9 @@ +@@ -6,6 +6,9 @@ #include #include @@ -31,7 +29,7 @@ index b60ae8c..4fbb2b5 100644 #include "core.h" #include "debug.h" -@@ -251,6 +254,26 @@ static void ath12k_mhi_op_write_reg(struct mhi_controller *mhi_cntrl, +@@ -347,6 +350,26 @@ static void ath12k_mhi_op_write_reg(stru writel(val, addr); } @@ -58,7 +56,7 @@ index b60ae8c..4fbb2b5 100644 int ath12k_mhi_register(struct ath12k_pci *ab_pci) { struct ath12k_base *ab = ab_pci->ab; -@@ -278,6 +301,15 @@ int ath12k_mhi_register(struct ath12k_pci *ab_pci) +@@ -376,6 +399,15 @@ int ath12k_mhi_register(struct ath12k_pc return ret; } @@ -74,38 +72,27 @@ index b60ae8c..4fbb2b5 100644 mhi_ctrl->iova_start = 0; mhi_ctrl->iova_stop = 0xffffffff; mhi_ctrl->sbl_size = SZ_512K; -diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c -index acbe8ec..d7142e1 100644 --- a/drivers/net/wireless/ath/ath12k/pci.c +++ b/drivers/net/wireless/ath/ath12k/pci.c -@@ -6,6 +6,7 @@ - #include - #include - #include -+#include - - #include "pci.h" - #include "core.h" -@@ -1184,10 +1185,11 @@ static int ath12k_pci_probe(struct pci_dev *pdev, +@@ -1170,10 +1170,11 @@ static int ath12k_pci_probe(struct pci_d pci_set_drvdata(pdev, ab); spin_lock_init(&ab_pci->window_lock); - /* Set fixed_mem_region to true for - * the platforms supports reserved memory. +- */ +- if (of_property_read_u32(ab->dev->of_node, "qcom,base-addr", &addr)) + /* Set fixed_mem_region to true for platforms support reserved memory + * from DT. If memory is reserved from DT for FW, ath11k driver need not + * allocate memory. - */ -- if (of_property_read_u32(ab->dev->of_node, "qcom,base-addr", &addr)) ++ */ + if (of_property_read_u32(ab->dev->of_node, "memory-region", &addr)) ab->bus_params.fixed_mem_region = true; ret = ath12k_pci_claim(ab_pci, pdev); -diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c -index e6489e5..a05325e 100644 --- a/drivers/net/wireless/ath/ath12k/qmi.c +++ b/drivers/net/wireless/ath/ath12k/qmi.c -@@ -9,6 +9,8 @@ +@@ -10,6 +10,8 @@ #include "core.h" #include "debug.h" #include @@ -114,7 +101,7 @@ index e6489e5..a05325e 100644 #include #define SLEEP_CLOCK_SELECT_INTERNAL_BIT 0x02 -@@ -1930,21 +1932,37 @@ static int ath12k_qmi_alloc_target_mem_chunk(struct ath12k_base *ab) +@@ -2428,21 +2430,37 @@ static int ath12k_qmi_alloc_target_mem_c static int ath12k_qmi_assign_target_mem_chunk(struct ath12k_base *ab) { struct device *dev = ab->dev; @@ -160,7 +147,7 @@ index e6489e5..a05325e 100644 ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type; idx++; break; -@@ -1954,12 +1972,17 @@ static int ath12k_qmi_assign_target_mem_chunk(struct ath12k_base *ab) +@@ -2452,12 +2470,17 @@ static int ath12k_qmi_assign_target_mem_ return -EINVAL; } @@ -168,7 +155,7 @@ index e6489e5..a05325e 100644 - "qcom,caldb-addr", &addr)) { - ab->qmi.target_mem[idx].paddr = addr; - ab->qmi.target_mem[idx].v.ioaddr = -+ if (ath12k_cold_boot_cal && ab->hw_params.cold_boot_calib) { ++ if (ath12k_cold_boot_cal && ab->hw_params->cold_boot_calib) { + if (hremote_node) { + ab->qmi.target_mem[idx].paddr = + res.start + host_ddr_sz; @@ -182,6 +169,3 @@ index e6489e5..a05325e 100644 } else { ab->qmi.target_mem[idx].paddr = 0; ab->qmi.target_mem[idx].v.ioaddr = NULL; --- -2.7.4 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/508-ath12k-add-ath12k_dp_tx_htt_h2t_vde.patch b/feeds/ipq95xx/mac80211/patches/qca/508-ath12k-add-ath12k_dp_tx_htt_h2t_vde.patch new file mode 100644 index 000000000..5d95ccaa8 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/508-ath12k-add-ath12k_dp_tx_htt_h2t_vde.patch @@ -0,0 +1,75 @@ +From a3e18c80aace0b415f34eec22ce4d50228dbc364 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Mon, 5 Sep 2022 11:50:11 +0530 +Subject: [PATCH] Revert "ath12k: remove unused + ath12k_dp_tx_htt_h2t_vdev_stats_ol_req()" + +This reverts commit 3a5232728e3f1751da5d1dcff5aac947bde2955e. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath12k/dp_tx.c | 37 +++++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/dp_tx.h | 1 + + 2 files changed, 38 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c +index e8735735d891..7af609db760f 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -966,6 +966,43 @@ int ath12k_dp_tx_htt_rx_filter_setup(struct ath12k_base *ab, u32 ring_id, + return ret; + } + ++int ++ath12k_dp_tx_htt_h2t_vdev_stats_ol_req(struct ath12k *ar, u64 reset_bitmask) ++{ ++ struct ath12k_base *ab = ar->ab; ++ struct htt_h2t_msg_type_vdev_txrx_stats_req *cmd; ++ struct ath12k_dp *dp = &ab->dp; ++ struct sk_buff *skb; ++ int len = sizeof(*cmd), ret; ++ ++ skb = ath12k_htc_alloc_skb(ab, len); ++ if (!skb) ++ return -ENOMEM; ++ ++ skb_put(skb, len); ++ cmd->hdr = FIELD_PREP(HTT_H2T_VDEV_TXRX_HDR_MSG_TYPE, ++ HTT_H2T_MSG_TYPE_VDEV_TXRX_STATS_CFG); ++ cmd->hdr |= FIELD_PREP(HTT_H2T_VDEV_TXRX_HDR_PDEV_ID, ++ ar->pdev->pdev_id); ++ cmd->hdr |= FIELD_PREP(HTT_H2T_VDEV_TXRX_HDR_ENABLE, true); ++ cmd->hdr |= FIELD_PREP(HTT_H2T_VDEV_TXRX_HDR_INTERVAL, ++ ATH12K_STATS_TIMER_DUR_1SEC); ++ cmd->hdr |= FIELD_PREP(HTT_H2T_VDEV_TXRX_HDR_RESET_STATS, true); ++ cmd->vdev_id_lo_bitmask = (reset_bitmask & HTT_H2T_VDEV_TXRX_LO_BITMASK); ++ cmd->vdev_id_hi_bitmask = ((reset_bitmask & ++ HTT_H2T_VDEV_TXRX_HI_BITMASK) >> 32); ++ ++ ret = ath12k_htc_send(&ab->htc, dp->eid, skb); ++ if (ret) { ++ ath12k_warn(ab, "failed to send htt type vdev stats offload request: %d", ++ ret); ++ dev_kfree_skb_any(skb); ++ return ret; ++ } ++ ++ return 0; ++} ++ + int + ath12k_dp_tx_htt_h2t_ext_stats_req(struct ath12k *ar, u8 type, + struct htt_ext_stats_cfg_params *cfg_params, +diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.h b/drivers/net/wireless/ath/ath12k/dp_tx.h +index 436d77e5e9ee..fcd52bfda232 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_tx.h ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.h +@@ -38,4 +38,5 @@ int ath12k_dp_tx_htt_tx_filter_setup(struct ath12k_base *ab, u32 ring_id, + struct htt_tx_ring_tlv_filter *htt_tlv_filter); + int ath12k_dp_tx_htt_tx_monitor_mode_ring_config(struct ath12k *ar, bool reset); + int ath12k_dp_tx_htt_monitor_mode_ring_config(struct ath12k *ar, bool reset); ++int ath12k_dp_tx_htt_h2t_vdev_stats_ol_req(struct ath12k *ar, u64 reset_bitmask); + #endif +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/509-ath12k-remove-monitor-status-and-monitor-desc-rings.patch b/feeds/ipq95xx/mac80211/patches/qca/509-ath12k-remove-monitor-status-and-monitor-desc-rings.patch index 4a65ea94d..ce9eda48d 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/509-ath12k-remove-monitor-status-and-monitor-desc-rings.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/509-ath12k-remove-monitor-status-and-monitor-desc-rings.patch @@ -15,7 +15,7 @@ Signed-off-by: P Praneesh --- a/drivers/net/wireless/ath/ath12k/dp.c +++ b/drivers/net/wireless/ath/ath12k/dp.c -@@ -266,6 +266,7 @@ int ath12k_dp_srng_setup(struct ath12k_b +@@ -259,6 +259,7 @@ int ath12k_dp_srng_setup(struct ath12k_b params.intr_batch_cntr_thres_entries = 0; params.intr_timer_thres_us = HAL_SRNG_INT_TIMER_THRESHOLD_RX; break; @@ -23,9 +23,9 @@ Signed-off-by: P Praneesh case HAL_TX_MONITOR_DST: params.low_threshold = DP_TX_MONITOR_BUF_SIZE_MAX >> 3; params.flags |= HAL_SRNG_FLAGS_LOW_THRESH_INTR_EN; -@@ -292,7 +293,6 @@ int ath12k_dp_srng_setup(struct ath12k_b - case HAL_WBM_IDLE_LINK: +@@ -286,7 +287,6 @@ int ath12k_dp_srng_setup(struct ath12k_b case HAL_SW2WBM_RELEASE: + case HAL_RXDMA_DST: case HAL_RXDMA_MONITOR_DST: - case HAL_RXDMA_MONITOR_DESC: params.intr_batch_cntr_thres_entries = @@ -45,7 +45,7 @@ Signed-off-by: P Praneesh } static int ath12k_wbm_idle_ring_setup(struct ath12k_base *ab, u32 *n_link_desc) -@@ -813,8 +810,7 @@ int ath12k_dp_link_desc_setup(struct ath +@@ -814,8 +811,7 @@ int ath12k_dp_link_desc_setup(struct ath tot_mem_sz = entry_sz * n_link_desc; /* Setup scatter desc list when the total memory requirement is more */ @@ -57,7 +57,7 @@ Signed-off-by: P Praneesh n_link_desc, --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -720,10 +720,6 @@ ath12k_dp_tx_get_ring_id_type(struct ath +@@ -696,10 +696,6 @@ ath12k_dp_tx_get_ring_id_type(struct ath *htt_ring_id = HTT_RXDMA_MONITOR_DEST_RING; *htt_ring_type = HTT_HW_TO_SW_RING; break; @@ -70,52 +70,14 @@ Signed-off-by: P Praneesh *htt_ring_type = HTT_SW_TO_HW_RING; --- a/drivers/net/wireless/ath/ath12k/hal.h +++ b/drivers/net/wireless/ath/ath12k/hal.h -@@ -458,8 +458,8 @@ enum hal_srng_ring_id { - HAL_SRNG_RING_ID_WMAC1_SW2RXDMA0_BUF = HAL_SRNG_RING_ID_PMAC1_ID_START, - HAL_SRNG_RING_ID_WMAC1_SW2RXDMA1_BUF, - HAL_SRNG_RING_ID_WMAC1_SW2RXDMA2_BUF, -- HAL_SRNG_RING_ID_WMAC1_SW2RXMON_BUF0, -- -+ HAL_SRNG_RING_ID_WMAC1_SW2RXDMA0_STATBUF, -+ HAL_SRNG_RING_ID_WMAC1_SW2RXDMA1_STATBUF, - HAL_SRNG_RING_ID_WMAC1_RXDMA2SW0, - HAL_SRNG_RING_ID_WMAC1_RXDMA2SW1, - HAL_SRNG_RING_ID_WMAC1_RXMON2SW0 = HAL_SRNG_RING_ID_WMAC1_RXDMA2SW1, -@@ -504,9 +504,8 @@ enum hal_ring_type { +@@ -532,9 +532,9 @@ enum hal_ring_type { HAL_RXDMA_BUF, HAL_RXDMA_DST, HAL_RXDMA_MONITOR_BUF, - HAL_RXDMA_MONITOR_STATUS, HAL_RXDMA_MONITOR_DST, -- HAL_RXDMA_MONITOR_DESC, + HAL_RXDMA_MONITOR_DESC, + HAL_RXDMA_MONITOR_STATUS, HAL_RXDMA_DIR_BUF, HAL_PPE2TCL, HAL_PPE_RELEASE, ---- a/drivers/net/wireless/ath/ath12k/hal.c -+++ b/drivers/net/wireless/ath/ath12k/hal.c -@@ -144,7 +144,14 @@ static const struct hal_srng_config hw_s - .ring_dir = HAL_SRNG_DIR_DST, - .max_size = HAL_RXDMA_RING_MAX_SIZE_BE, - }, -- -+ { /* RXDMA_MONITOR_STATUS */ -+ .start_ring_id = HAL_SRNG_RING_ID_WMAC1_SW2RXDMA1_STATBUF, -+ .max_rings = 1, -+ .entry_size = sizeof(struct hal_wbm_buffer_ring) >> 2, -+ .mac_type = ATH12K_HAL_SRNG_PMAC, -+ .ring_dir = HAL_SRNG_DIR_SRC, -+ .max_size = HAL_RXDMA_RING_MAX_SIZE, -+ }, - { /* RXDMA DIR BUF */ - .start_ring_id = HAL_SRNG_RING_ID_RXDMA_DIR_BUF, - .max_rings = 2, -@@ -184,7 +191,7 @@ static const struct hal_srng_config hw_s - .max_size = HAL_RXDMA_RING_MAX_SIZE_BE, - }, - { /* RXDMA_MONITOR_DEST */ -- .start_ring_id = HAL_SRNG_RING_ID_WMAC1_SW2RXMON_BUF0, -+ .start_ring_id = HAL_SRNG_RING_ID_WMAC1_RXMON2SW0, - .max_rings = 1, - .entry_size = sizeof(struct hal_mon_dest_desc) >> 2, - .ring_dir = HAL_SRNG_DIR_DST, diff --git a/feeds/ipq95xx/mac80211/patches/qca/510-ath12k-rearrange-ring-type-enum-to-match-the-hal-rin.patch b/feeds/ipq95xx/mac80211/patches/qca/510-ath12k-rearrange-ring-type-enum-to-match-the-hal-rin.patch index 54db2327b..38be3c6f5 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/510-ath12k-rearrange-ring-type-enum-to-match-the-hal-rin.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/510-ath12k-rearrange-ring-type-enum-to-match-the-hal-rin.patch @@ -15,12 +15,13 @@ Signed-off-by: P Praneesh --- a/drivers/net/wireless/ath/ath12k/hal.h +++ b/drivers/net/wireless/ath/ath12k/hal.h -@@ -503,13 +503,13 @@ enum hal_ring_type { +@@ -531,14 +531,14 @@ enum hal_ring_type { HAL_WBM2SW_RELEASE, HAL_RXDMA_BUF, HAL_RXDMA_DST, - HAL_RXDMA_MONITOR_BUF, - HAL_RXDMA_MONITOR_DST, + HAL_RXDMA_MONITOR_DESC, HAL_RXDMA_MONITOR_STATUS, HAL_RXDMA_DIR_BUF, HAL_PPE2TCL, diff --git a/feeds/ipq95xx/mac80211/patches/qca/512-ath12k-fix-qmi-server-arrive-callback-by-correcting.patch b/feeds/ipq95xx/mac80211/patches/qca/512-ath12k-fix-qmi-server-arrive-callback-by-correcting.patch index 9bf76dbf2..980f4b99f 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/512-ath12k-fix-qmi-server-arrive-callback-by-correcting.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/512-ath12k-fix-qmi-server-arrive-callback-by-correcting.patch @@ -12,37 +12,9 @@ Signed-off-by: P Praneesh drivers/net/wireless/ath/ath12k/mhi.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/mhi.c b/drivers/net/wireless/ath/ath12k/mhi.c -index f60bb7f..a36620c 100644 --- a/drivers/net/wireless/ath/ath12k/mhi.c +++ b/drivers/net/wireless/ath/ath12k/mhi.c -@@ -21,7 +21,7 @@ static struct mhi_channel_config ath12k_mhi_channels_qcn92xx[] = { - .num_elements = 32, - .event_ring = 1, - .dir = DMA_TO_DEVICE, -- .ee_mask = 0x14, -+ .ee_mask = 0x4, - .pollcfg = 0, - .doorbell = MHI_DB_BRST_DISABLE, - .lpm_notify = false, -@@ -35,7 +35,7 @@ static struct mhi_channel_config ath12k_mhi_channels_qcn92xx[] = { - .num_elements = 32, - .event_ring = 1, - .dir = DMA_FROM_DEVICE, -- .ee_mask = 0x14, -+ .ee_mask = 0x4, - .pollcfg = 0, - .doorbell = MHI_DB_BRST_DISABLE, - .lpm_notify = false, -@@ -49,13 +49,14 @@ static struct mhi_channel_config ath12k_mhi_channels_qcn92xx[] = { - .num_elements = 32, - .event_ring = 1, - .dir = DMA_TO_DEVICE, -- .ee_mask = 0x14, -+ .ee_mask = 0x4, - .pollcfg = 0, - .doorbell = MHI_DB_BRST_DISABLE, - .lpm_notify = false, +@@ -59,6 +59,7 @@ static struct mhi_channel_config ath12k_ .offload_channel = false, .doorbell_mode_switch = false, .auto_queue = false, @@ -50,15 +22,7 @@ index f60bb7f..a36620c 100644 }, { .num = 21, -@@ -63,13 +64,14 @@ static struct mhi_channel_config ath12k_mhi_channels_qcn92xx[] = { - .num_elements = 32, - .event_ring = 1, - .dir = DMA_FROM_DEVICE, -- .ee_mask = 0x14, -+ .ee_mask = 0x4, - .pollcfg = 0, - .doorbell = MHI_DB_BRST_DISABLE, - .lpm_notify = false, +@@ -73,6 +74,7 @@ static struct mhi_channel_config ath12k_ .offload_channel = false, .doorbell_mode_switch = false, .auto_queue = true, @@ -66,6 +30,3 @@ index f60bb7f..a36620c 100644 }, }; --- -2.7.4 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/513-ath12k-Add-logic-to-write-qrtr-node-id-to-scratch.patch b/feeds/ipq95xx/mac80211/patches/qca/513-ath12k-Add-logic-to-write-qrtr-node-id-to-scratch.patch index 165df58d1..aa24d62be 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/513-ath12k-Add-logic-to-write-qrtr-node-id-to-scratch.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/513-ath12k-Add-logic-to-write-qrtr-node-id-to-scratch.patch @@ -13,17 +13,17 @@ Signed-off-by: P Praneesh --- a/drivers/net/wireless/ath/ath12k/pci.c +++ b/drivers/net/wireless/ath/ath12k/pci.c -@@ -38,6 +38,9 @@ - - #define QCN92XX_DEVICE_ID 0x1109 +@@ -40,6 +40,9 @@ + #define QCN9274_DEVICE_ID 0x1109 + #define WCN7850_DEVICE_ID 0x1107 +#define PCIE_PCIE_LOCAL_REG_PCIE_LOCAL_RSV0 0x1E03164 +#define QRTR_INSTANCE_MASK 0x000000FF + static const struct pci_device_id ath12k_pci_id_table[] = { - { PCI_VDEVICE(QCOM, QCN92XX_DEVICE_ID) }, - {0} -@@ -647,7 +650,8 @@ static int ath12k_pci_config_irq(struct + { PCI_VDEVICE(QCOM, QCN9274_DEVICE_ID) }, + { PCI_VDEVICE(QCOM, WCN7850_DEVICE_ID) }, +@@ -594,7 +597,8 @@ static int ath12k_pci_config_irq(struct static void ath12k_pci_init_qmi_ce_config(struct ath12k_base *ab) { struct ath12k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg; @@ -31,22 +31,21 @@ Signed-off-by: P Praneesh + struct ath12k_pci *ab_pci = ath12k_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; -@@ -655,8 +659,10 @@ static void ath12k_pci_init_qmi_ce_confi - 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; + cfg->tgt_ce = ab->hw_params->target_ce_config; + cfg->tgt_ce_len = ab->hw_params->target_ce_count; +@@ -603,8 +607,9 @@ static void ath12k_pci_init_qmi_ce_confi + 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 (!of_property_read_u32(ab->dev->of_node, "qrtr_instance_id", &instance_id)) - ab->qmi.service_ins_id = instance_id + ATH12K_QMI_WLFW_NODE_ID_BASE; -+ + ab_pci->instance = (((pci_domain_nr(bus) & 0xF) << 4) | + (bus->number & 0xF)) & QRTR_INSTANCE_MASK; + ab->qmi.service_ins_id += ab_pci->instance; } static void ath12k_pci_ce_irqs_enable(struct ath12k_base *ab) -@@ -819,6 +825,27 @@ static void ath12k_pci_aspm_disable(stru +@@ -792,6 +797,27 @@ static void ath12k_pci_aspm_disable(stru set_bit(ATH12K_PCI_ASPM_RESTORE, &ab_pci->flags); } @@ -74,9 +73,9 @@ Signed-off-by: P Praneesh static void ath12k_pci_aspm_restore(struct ath12k_pci *ab_pci) { if (test_and_clear_bit(ATH12K_PCI_ASPM_RESTORE, &ab_pci->flags)) -@@ -1115,6 +1142,8 @@ int ath12k_pci_power_up(struct ath12k_ba - */ - ath12k_pci_aspm_disable(ab_pci); +@@ -1100,6 +1126,8 @@ int ath12k_pci_power_up(struct ath12k_ba + + ath12k_pci_msi_enable(ab_pci); + ath12k_pci_update_qrtr_node_id(ab); + @@ -85,7 +84,7 @@ Signed-off-by: P Praneesh ath12k_err(ab, "failed to start mhi: %d\n", ret); --- a/drivers/net/wireless/ath/ath12k/pci.h +++ b/drivers/net/wireless/ath/ath12k/pci.h -@@ -87,6 +87,7 @@ struct ath12k_pci { +@@ -100,6 +100,7 @@ struct ath12k_pci { /* enum ath12k_pci_flags */ unsigned long flags; u16 link_ctl; @@ -95,7 +94,7 @@ Signed-off-by: P Praneesh static inline struct ath12k_pci *ath12k_pci_priv(struct ath12k_base *ab) --- a/drivers/net/wireless/ath/ath12k/qmi.h +++ b/drivers/net/wireless/ath/ath12k/qmi.h -@@ -14,7 +14,6 @@ +@@ -15,7 +15,6 @@ #define ATH12K_QMI_MAX_BDF_FILE_NAME_SIZE 64 #define ATH12K_QMI_CALDB_ADDRESS 0x4BA00000 #define ATH12K_QMI_WLANFW_MAX_BUILD_ID_LEN_V01 128 diff --git a/feeds/ipq95xx/mac80211/patches/qca/514-ath12k-fix-pci-read-and-write.patch b/feeds/ipq95xx/mac80211/patches/qca/514-ath12k-fix-pci-read-and-write.patch index b8ccb3fcd..a9add719f 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/514-ath12k-fix-pci-read-and-write.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/514-ath12k-fix-pci-read-and-write.patch @@ -10,7 +10,7 @@ Signed-off-by: P Praneesh --- a/drivers/net/wireless/ath/ath12k/pci.c +++ b/drivers/net/wireless/ath/ath12k/pci.c -@@ -1062,10 +1062,20 @@ int ath12k_pci_start(struct ath12k_base +@@ -1027,10 +1027,20 @@ int ath12k_pci_start(struct ath12k_base return 0; } @@ -31,7 +31,7 @@ Signed-off-by: P Praneesh /* for offset beyond BAR + 4K - 32, may * need to wakeup MHI to access. -@@ -1085,8 +1095,23 @@ u32 ath12k_pci_read32(struct ath12k_base +@@ -1050,8 +1060,23 @@ u32 ath12k_pci_read32(struct ath12k_base if (window_start == WINDOW_START) { spin_lock_bh(&ab_pci->window_lock); ath12k_pci_select_window(ab_pci, offset); @@ -56,8 +56,8 @@ Signed-off-by: P Praneesh + } spin_unlock_bh(&ab_pci->window_lock); } else { - val = ioread32(ab->mem + window_start + -@@ -1105,6 +1130,7 @@ void ath12k_pci_write32(struct ath12k_ba + if ((!window_start) && +@@ -1075,6 +1100,7 @@ void ath12k_pci_write32(struct ath12k_ba { struct ath12k_pci *ab_pci = ath12k_pci_priv(ab); u32 window_start; @@ -65,16 +65,7 @@ Signed-off-by: P Praneesh /* for offset beyond BAR + 4K - 32, may * need to wakeup MHI to access. -@@ -1114,7 +1140,7 @@ void ath12k_pci_write32(struct ath12k_ba - mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev); - - if (offset < WINDOW_START) { -- iowrite32(value, ab->mem + offset); -+ iowrite32(value, ab->mem + offset); - } else { - if (ab->bus_params.static_window_map) - window_start = ath12k_pci_get_window_start(ab, offset); -@@ -1124,8 +1150,23 @@ void ath12k_pci_write32(struct ath12k_ba +@@ -1094,8 +1120,23 @@ void ath12k_pci_write32(struct ath12k_ba if (window_start == WINDOW_START) { spin_lock_bh(&ab_pci->window_lock); ath12k_pci_select_window(ab_pci, offset); @@ -99,4 +90,4 @@ Signed-off-by: P Praneesh + } spin_unlock_bh(&ab_pci->window_lock); } else { - iowrite32(value, ab->mem + window_start + + if ((!window_start) && diff --git a/feeds/ipq95xx/mac80211/patches/qca/515-ath12k-fix-ring-id-from-lmac-offset-of-sw2rxdma.patch b/feeds/ipq95xx/mac80211/patches/qca/515-ath12k-fix-ring-id-from-lmac-offset-of-sw2rxdma.patch deleted file mode 100644 index ced84f267..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/515-ath12k-fix-ring-id-from-lmac-offset-of-sw2rxdma.patch +++ /dev/null @@ -1,33 +0,0 @@ -From ea349467597499ced9d9ff6aec12bdbabe52ed12 Mon Sep 17 00:00:00 2001 -From: Aishwarya R -Date: Tue, 22 Feb 2022 20:22:01 +0530 -Subject: [PATCH] [PATCH 08/14] ath12k: fix ring id from lmac offset of - sw2rxdma - -Signed-off-by: Aishwarya R ---- - drivers/net/wireless/ath/ath12k/dp_tx.c | 7 ++----- - 1 file changed, 2 insertions(+), 5 deletions(-) - -diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c -index b94195c15f65..afdc5097495f 100644 ---- a/drivers/net/wireless/ath/ath12k/dp_tx.c -+++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -703,12 +703,9 @@ ath12k_dp_tx_get_ring_id_type(struct ath12k_base *ab, - * rxbuf ring for each rxdma - */ - if (!ab->hw_params.rx_mac_buf_ring) { -- if (!(ring_id == (HAL_SRNG_RING_ID_WMAC1_SW2RXDMA0_BUF + -- lmac_ring_id_offset) || -- ring_id == (HAL_SRNG_RING_ID_WMAC1_SW2RXDMA1_BUF + -- lmac_ring_id_offset))) { -+ if (!(ring_id == HAL_SRNG_SW2RXDMA_BUF0) || (ring_id == HAL_SRNG_SW2RXDMA_BUF1)) - ret = -EINVAL; -- } -+ - *htt_ring_id = HTT_RXDMA_HOST_BUF_RING; - *htt_ring_type = HTT_SW_TO_HW_RING; - } else { --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/516-ath12k-fix-l1ss.patch b/feeds/ipq95xx/mac80211/patches/qca/516-ath12k-fix-l1ss.patch index 487c48ced..ba92542d7 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/516-ath12k-fix-l1ss.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/516-ath12k-fix-l1ss.patch @@ -15,35 +15,46 @@ Signed-off-by: Aishwarya R drivers/net/wireless/ath/ath12k/hw.h | 1 + drivers/net/wireless/ath/ath12k/pci.c | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) ---- a/drivers/net/wireless/ath/ath12k/core.c -+++ b/drivers/net/wireless/ath/ath12k/core.c -@@ -65,6 +65,7 @@ static const struct ath12k_hw_params ath - .supports_suspend = false, - .hal_desc_sz = sizeof(struct hal_rx_desc_qcn92xx), - .num_tcl_banks = 48, +--- a/drivers/net/wireless/ath/ath12k/hw.h ++++ b/drivers/net/wireless/ath/ath12k/hw.h +@@ -190,6 +190,8 @@ struct ath12k_hw_params { + + const char *qdss_config; + unsigned int qdss_config_len; ++ ++ bool fix_l1ss; + }; + + /* BRINGUP: move to dp.h */ +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -301,6 +301,9 @@ static void ath12k_pci_sw_reset(struct a + ath12k_pci_enable_ltssm(ab); + ath12k_pci_clear_all_intrs(ab); + ath12k_pci_set_wlaon_pwr_ctrl(ab); ++ ++ if (ab->hw_params->fix_l1ss) ++ ath12k_dbg(ab, ATH12K_DBG_PCI, "L1ss fix required\n"); + } + + ath12k_mhi_clear_vector(ab); +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -875,6 +875,8 @@ static const struct ath12k_hw_params ath + + .qdss_config = NULL, + .qdss_config_len = 0, ++ ++ .fix_l1ss = false, + }, + { + .name = "wcn7850 hw2.0", +@@ -934,6 +936,8 @@ static const struct ath12k_hw_params ath + + .qdss_config = ath12k_hw_qdss_config_wcn7850, + .qdss_config_len = sizeof(ath12k_hw_qdss_config_wcn7850), ++ + .fix_l1ss = false, }, }; ---- a/drivers/net/wireless/ath/ath12k/hw.h -+++ b/drivers/net/wireless/ath/ath12k/hw.h -@@ -163,6 +163,7 @@ struct ath12k_hw_params { - bool supports_suspend; - u32 hal_desc_sz; - u32 num_tcl_banks; -+ bool fix_l1ss; - }; - - struct ath12k_hw_ops { ---- a/drivers/net/wireless/ath/ath12k/pci.c -+++ b/drivers/net/wireless/ath/ath12k/pci.c -@@ -363,7 +363,8 @@ static void ath12k_pci_sw_reset(struct a - ath12k_pci_enable_ltssm(ab); - ath12k_pci_clear_all_intrs(ab); - ath12k_pci_set_wlaon_pwr_ctrl(ab); -- ath12k_pci_fix_l1ss(ab); -+ if (ab->hw_params.fix_l1ss) -+ ath12k_pci_fix_l1ss(ab); - } - - ath12k_mhi_clear_vector(ab); diff --git a/feeds/ipq95xx/mac80211/patches/qca/517-ath12k-WAR-for-fw-crash-while-accessing-ce-15.patch b/feeds/ipq95xx/mac80211/patches/qca/517-ath12k-WAR-for-fw-crash-while-accessing-ce-15.patch deleted file mode 100644 index cd524a4b8..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/517-ath12k-WAR-for-fw-crash-while-accessing-ce-15.patch +++ /dev/null @@ -1,66 +0,0 @@ -From adac1ec7f90c4ac8a4b66b39a63a4fac45d9048a Mon Sep 17 00:00:00 2001 -From: P Praneesh -Date: Mon, 3 Jan 2022 12:32:24 +0530 -Subject: [PATCH 09/14] ath12k: WAR for fw crash while accessing ce 15 - -ath12k_dp_cc_init and ath12k_dp_reoq_lut_setup caused fw crash -also accessing 15th ce ring cause fw assertion - -Signed-off-by: P Praneesh ---- - drivers/net/wireless/ath/ath12k/core.c | 4 ++-- - drivers/net/wireless/ath/ath12k/dp.c | 6 ++++++ - 2 files changed, 8 insertions(+), 2 deletions(-) - -diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c -index 78432ef..e494490 100644 ---- a/drivers/net/wireless/ath/ath12k/core.c -+++ b/drivers/net/wireless/ath/ath12k/core.c -@@ -47,11 +47,11 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { - .internal_sleep_clock = false, - .regs = &qcn92xx_regs, - .host_ce_config = ath12k_host_ce_config_qcn92xx, -- .ce_count = 15, -+ .ce_count = 14, - .target_ce_config = ath12k_target_ce_config_wlan_qcn92xx, - .target_ce_count = 9, - .svc_to_ce_map = ath12k_target_service_to_ce_map_wlan_qcn92xx, -- .svc_to_ce_map_len = 18, -+ .svc_to_ce_map_len = 21, - .rxdma1_enable = true, - .num_rxmda_per_pdev = 1, - .rx_mac_buf_ring = false, -diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c -index 28f03cf..a36d8b4 100644 ---- a/drivers/net/wireless/ath/ath12k/dp.c -+++ b/drivers/net/wireless/ath/ath12k/dp.c -@@ -1102,6 +1102,8 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab) - struct sk_buff *skb; - int i; - -+ return; -+ - if (!dp->spt_info) - return; - -@@ -1348,6 +1350,8 @@ static int ath12k_dp_cc_init(struct ath12k_base *ab) - int i, ret = 0; - u32 cmem_base; - -+ return 0; -+ - INIT_LIST_HEAD(&dp->rx_desc_free_list); - INIT_LIST_HEAD(&dp->rx_desc_used_list); - spin_lock_init(&dp->rx_desc_lock); -@@ -1412,6 +1416,8 @@ static int ath12k_dp_reoq_lut_setup(struct ath12k_base *ab) - { - struct ath12k_dp *dp = &ab->dp; - -+ return 0; -+ - dp->reoq_lut.vaddr = dma_alloc_coherent(ab->dev, - DP_REOQ_LUT_SIZE, - &dp->reoq_lut.paddr, --- -2.7.4 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/519-ath12k-fix-cc-ext-event-for-regulatory-build.patch b/feeds/ipq95xx/mac80211/patches/qca/519-ath12k-fix-cc-ext-event-for-regulatory-build.patch index b5fd39ffb..ca1ff240d 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/519-ath12k-fix-cc-ext-event-for-regulatory-build.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/519-ath12k-fix-cc-ext-event-for-regulatory-build.patch @@ -14,11 +14,9 @@ Signed-off-by: Aishwarya R drivers/net/wireless/ath/ath12k/wmi.h | 8 +- 5 files changed, 84 insertions(+), 47 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/mhi.c b/drivers/net/wireless/ath/ath12k/mhi.c -index de6e7240d045..9053c86e1347 100644 --- a/drivers/net/wireless/ath/ath12k/mhi.c +++ b/drivers/net/wireless/ath/ath12k/mhi.c -@@ -232,6 +232,7 @@ static void ath12k_mhi_op_status_cb(struct mhi_controller *mhi_cntrl, +@@ -328,6 +328,7 @@ static void ath12k_mhi_op_status_cb(stru case MHI_CB_EE_RDDM: if (!(test_bit(ATH12K_FLAG_UNREGISTERING, &ab->dev_flags))) queue_work(ab->workqueue_aux, &ab->reset_work); @@ -26,24 +24,9 @@ index de6e7240d045..9053c86e1347 100644 break; default: break; -diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c -index f004dab7fd2b..63a64f18906a 100644 ---- a/drivers/net/wireless/ath/ath12k/pci.c -+++ b/drivers/net/wireless/ath/ath12k/pci.c -@@ -1176,7 +1176,7 @@ static int ath12k_pci_probe(struct pci_dev *pdev, - u32 addr; - int ret; - -- dev_warn(&pdev->dev, "WARNING: ath12k PCI support is experimental!\n"); -+ dev_warn(&pdev->dev, "WARNING: ath12k PCI support is experimental 2!\n"); - - ab = ath12k_core_alloc(&pdev->dev, sizeof(*ab_pci), ATH12K_BUS_PCI, - &ath12k_pci_bus_params); -diff --git a/drivers/net/wireless/ath/ath12k/reg.c b/drivers/net/wireless/ath/ath12k/reg.c -index bfdb4d0c873c..616db59db7f6 100644 --- a/drivers/net/wireless/ath/ath12k/reg.c +++ b/drivers/net/wireless/ath/ath12k/reg.c -@@ -621,7 +621,17 @@ ath12k_reg_build_regd(struct ath12k_base *ab, +@@ -621,7 +621,17 @@ ath12k_reg_build_regd(struct ath12k_base reg_rule = reg_info->reg_rules_5g_ptr + j++; max_bw = min_t(u16, reg_rule->max_bw, reg_info->max_bw_5g); @@ -62,7 +45,7 @@ index bfdb4d0c873c..616db59db7f6 100644 /* FW doesn't pass NL80211_RRF_AUTO_BW flag for * BW Auto correction, we can enable this by default * for all 5G rules here. The regulatory core performs -@@ -635,6 +645,12 @@ ath12k_reg_build_regd(struct ath12k_base *ab, +@@ -635,6 +645,12 @@ ath12k_reg_build_regd(struct ath12k_base reg_rule = reg_info->reg_rules_6g_ap_ptr[WMI_REG_INDOOR_AP] + k++; max_bw = min_t(u16, reg_rule->max_bw, reg_info->max_bw_6g_ap[WMI_REG_INDOOR_AP]); @@ -75,11 +58,9 @@ index bfdb4d0c873c..616db59db7f6 100644 flags = NL80211_RRF_AUTO_BW; } else { break; -diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c -index 5f050140457c..62ef15020b49 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -3291,8 +3291,8 @@ ath12k_wmi_copy_resource_config(struct wmi_resource_config *wmi_cfg, +@@ -3334,8 +3334,8 @@ ath12k_wmi_copy_resource_config(struct w wmi_cfg->sched_params = tg_cfg->sched_params; wmi_cfg->twt_ap_pdev_count = tg_cfg->twt_ap_pdev_count; wmi_cfg->twt_ap_sta_count = tg_cfg->twt_ap_sta_count; @@ -90,17 +71,17 @@ index 5f050140457c..62ef15020b49 100644 } static int ath12k_init_cmd_send(struct ath12k_pdev_wmi *wmi, -@@ -3509,6 +3509,9 @@ int ath12k_wmi_cmd_init(struct ath12k_base *ab) +@@ -3546,6 +3546,9 @@ int ath12k_wmi_cmd_init(struct ath12k_ba memset(&init_param, 0, sizeof(init_param)); memset(&config, 0, sizeof(config)); + if (test_bit(WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT, ab->wmi_ab.svc_map)) + config.is_reg_cc_ext_event_supported = 1; + - wmi_sc->ops->wmi_init_config(ab, &config); + ab->hw_params->wmi_init(ab, &config); memcpy(&wmi_sc->wlan_resource_config, &config, sizeof(config)); -@@ -6647,47 +6650,60 @@ static void ath12k_vdev_install_key_compl_event(struct ath12k_base *ab, +@@ -6678,47 +6681,60 @@ static void ath12k_vdev_install_key_comp rcu_read_unlock(); } @@ -143,8 +124,6 @@ index 5f050140457c..62ef15020b49 100644 - "wmi_ext_service_bitmap 0:0x%x, 1:0x%x, 2:0x%x, 3:0x%x", - ev->wmi_service_segment_bitmap[0], ev->wmi_service_segment_bitmap[1], - ev->wmi_service_segment_bitmap[2], ev->wmi_service_segment_bitmap[3]); -- -- kfree(tb); +static int ath12k_wmi_tlv_services_parser(struct ath12k_base *ab, + u16 tag, u16 len, + const void *ptr, void *data) @@ -191,7 +170,8 @@ index 5f050140457c..62ef15020b49 100644 + } + return 0; +} -+ + +- kfree(tb); +static int ath12k_service_available_event(struct ath12k_base *ab, struct sk_buff *skb) +{ + int ret = 0; @@ -202,11 +182,9 @@ index 5f050140457c..62ef15020b49 100644 } static void ath12k_peer_assoc_conf_event(struct ath12k_base *ab, struct sk_buff *skb) -diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h -index 63d747115304..7c764707058d 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -2045,7 +2045,10 @@ enum wmi_tlv_service { +@@ -2042,7 +2042,10 @@ enum wmi_tlv_service { WMI_TLV_SERVICE_FREQINFO_IN_METADATA = 219, WMI_TLV_SERVICE_EXT2_MSG = 220, @@ -218,15 +196,15 @@ index 63d747115304..7c764707058d 100644 }; enum { -@@ -5116,6 +5119,7 @@ struct target_resource_config { +@@ -5037,6 +5040,7 @@ struct target_resource_config { u32 sched_params; u32 twt_ap_pdev_count; u32 twt_ap_sta_count; + bool is_reg_cc_ext_event_supported; }; - struct wmi_ops { -@@ -5138,7 +5142,7 @@ struct ath12k_wmi_base { + #define WMI_MAX_MEM_REQS 32 +@@ -5054,7 +5058,7 @@ struct ath12k_wmi_base { struct completion service_ready; struct completion unified_ready; @@ -235,6 +213,3 @@ index 63d747115304..7c764707058d 100644 wait_queue_head_t tx_credits_wq; const struct wmi_peer_flags_map *peer_flags; u32 num_mem_chunks; --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/520-ath12k-WAR-AP-bringup-crashes.patch b/feeds/ipq95xx/mac80211/patches/qca/520-ath12k-WAR-AP-bringup-crashes.patch index a8e03f714..3bce91ead 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/520-ath12k-WAR-AP-bringup-crashes.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/520-ath12k-WAR-AP-bringup-crashes.patch @@ -10,40 +10,9 @@ Signed-off-by: P Praneesh drivers/net/wireless/ath/ath12k/mac.c | 4 ++++ 3 files changed, 7 insertions(+) ---- a/drivers/net/wireless/ath/ath12k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -1459,11 +1459,9 @@ struct htt_ppdu_stats_info *ath12k_dp_ht - { - struct htt_ppdu_stats_info *ppdu_info; - -- spin_lock_bh(&ar->data_lock); - if (!list_empty(&ar->ppdu_stats_info)) { - list_for_each_entry(ppdu_info, &ar->ppdu_stats_info, list) { - if (ppdu_info->ppdu_id == ppdu_id) { -- spin_unlock_bh(&ar->data_lock); - return ppdu_info; - } - } -@@ -1477,16 +1475,13 @@ struct htt_ppdu_stats_info *ath12k_dp_ht - kfree(ppdu_info); - } - } -- spin_unlock_bh(&ar->data_lock); - - ppdu_info = kzalloc(sizeof(*ppdu_info), GFP_ATOMIC); - if (!ppdu_info) - return NULL; - -- spin_lock_bh(&ar->data_lock); - list_add_tail(&ppdu_info->list, &ar->ppdu_stats_info); - ar->ppdu_stat_list_depth++; -- spin_unlock_bh(&ar->data_lock); - - return ppdu_info; - } --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -5024,6 +5024,8 @@ static void ath12k_mac_vif_unref(struct +@@ -5091,6 +5091,8 @@ static void ath12k_mac_vif_unref(struct struct sk_buff *skb; int i; @@ -52,7 +21,7 @@ Signed-off-by: P Praneesh for (i = 0; i < ATH12K_HW_MAX_QUEUES; i++) { spin_lock_bh(&dp->tx_desc_lock[i]); -@@ -5141,6 +5143,7 @@ static void ath12k_mac_op_configure_filt +@@ -5208,6 +5210,7 @@ static void ath12k_mac_op_configure_filt *total_flags &= SUPPORTED_FILTERS; ar->filter_flags = *total_flags; @@ -60,7 +29,7 @@ Signed-off-by: P Praneesh /* For monitor mode */ reset_flag = !(ar->filter_flags & FIF_BCN_PRBRESP_PROMISC); -@@ -5154,6 +5157,9 @@ static void ath12k_mac_op_configure_filt +@@ -5221,6 +5224,9 @@ static void ath12k_mac_op_configure_filt ath12k_warn(ar->ab, "fail to set monitor filter: %d\n", ret); } diff --git a/feeds/ipq95xx/mac80211/patches/qca/521-ath12k-change-dtsi-memory-region-name-to-ath-memory-.patch b/feeds/ipq95xx/mac80211/patches/qca/521-ath12k-change-dtsi-memory-region-name-to-ath-memory-.patch index f5963a070..530379b55 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/521-ath12k-change-dtsi-memory-region-name-to-ath-memory-.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/521-ath12k-change-dtsi-memory-region-name-to-ath-memory-.patch @@ -10,32 +10,14 @@ Signed-off-by: P Praneesh drivers/net/wireless/ath/ath12k/qmi.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c -index 5bbcdb1..3634340 100644 --- a/drivers/net/wireless/ath/ath12k/pci.c +++ b/drivers/net/wireless/ath/ath12k/pci.c -@@ -1222,7 +1222,7 @@ static int ath12k_pci_probe(struct pci_dev *pdev, +@@ -1246,7 +1246,7 @@ static int ath12k_pci_probe(struct pci_d * from DT. If memory is reserved from DT for FW, ath11k driver need not * allocate memory. - */ + */ - if (of_property_read_u32(ab->dev->of_node, "memory-region", &addr)) -+ if (!of_property_read_u32(ab->dev->of_node, "ath-memory-region", &addr)) ++ if (!of_property_read_u32(ab->dev->of_node, "memory-region", &addr)) ab->bus_params.fixed_mem_region = true; ret = ath12k_pci_claim(ab_pci, pdev); -diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c -index a2d3370..71bbb3b 100644 ---- a/drivers/net/wireless/ath/ath12k/qmi.c -+++ b/drivers/net/wireless/ath/ath12k/qmi.c -@@ -2355,7 +2355,7 @@ static int ath12k_qmi_assign_target_mem_chunk(struct ath12k_base *ab) - for (i = 0, idx = 0; i < ab->qmi.mem_seg_count; i++) { - switch (ab->qmi.target_mem[i].type) { - case HOST_DDR_REGION_TYPE: -- hremote_node = of_parse_phandle(dev->of_node, "memory-region", 0); -+ hremote_node = of_parse_phandle(dev->of_node, "ath-memory-region", 0); - if (!hremote_node) { - ath12k_warn(ab, "qmi fail to get hremote_node\n"); - return ret; --- -2.7.4 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/522-ath12k-WAR-for-pci-bringup-crash.patch b/feeds/ipq95xx/mac80211/patches/qca/522-ath12k-WAR-for-pci-bringup-crash.patch deleted file mode 100644 index bf97ef418..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/522-ath12k-WAR-for-pci-bringup-crash.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 8046873a495925e3db32ffc4e8d0b3c6cea7b6b0 Mon Sep 17 00:00:00 2001 -From: P Praneesh -Date: Mon, 3 Jan 2022 16:12:42 +0530 -Subject: [PATCH 14/14] ath12k: WAR for pci bringup crash - -Signed-off-by: P Praneesh ---- - drivers/net/wireless/ath/ath12k/debugfs.c | 4 ++++ - drivers/net/wireless/ath/ath12k/dp_rx.c | 2 ++ - drivers/net/wireless/ath/ath12k/spectral.c | 2 ++ - 3 files changed, 8 insertions(+) - ---- a/drivers/net/wireless/ath/ath12k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -4153,6 +4153,8 @@ int ath12k_dp_rx_pdev_alloc(struct ath12 - } - } - -+ return 0; -+ - if (!ab->hw_params.rxdma1_enable) - goto out; - ---- a/drivers/net/wireless/ath/ath12k/spectral.c -+++ b/drivers/net/wireless/ath/ath12k/spectral.c -@@ -958,6 +958,8 @@ int ath12k_spectral_init(struct ath12k_b - int ret; - int i; - -+ return 0; -+ - if (!test_bit(WMI_TLV_SERVICE_FREQINFO_IN_METADATA, - ab->wmi_ab.svc_map)) - return 0; diff --git a/feeds/ipq95xx/mac80211/patches/qca/523-ath12k-dp-tx-fixes.patch b/feeds/ipq95xx/mac80211/patches/qca/523-ath12k-dp-tx-fixes.patch index 15d9cea35..97f7a375e 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/523-ath12k-dp-tx-fixes.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/523-ath12k-dp-tx-fixes.patch @@ -10,36 +10,9 @@ Signed-off-by: Aishwarya R drivers/net/wireless/ath/ath12k/mac.c | 2 -- 3 files changed, 1 insertion(+), 4 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c -index b47b94f3ed62..6632a8923dff 100644 ---- a/drivers/net/wireless/ath/ath12k/dp.c -+++ b/drivers/net/wireless/ath/ath12k/dp.c -@@ -1242,7 +1242,7 @@ void ath12k_dp_cc_config(struct ath12k_base *ab) - /* Enable conversion complete indication */ - val = ath12k_hif_read32(ab, wbm_base + HAL_WBM_SW_COOKIE_CFG2); - val |= FIELD_PREP(HAL_WBM_SW_COOKIE_CFG_RELEASE_PATH_EN, 1) | -- FIELD_PREP(HAL_WBM_SW_COOKIE_CFG_ERR_PATH_EN, 1); -+ FIELD_PREP(HAL_WBM_SW_COOKIE_CFG_ERR_PATH_EN, 1) | - FIELD_PREP(HAL_WBM_SW_COOKIE_CFG_CONV_IND_EN, 1); - - ath12k_hif_write32(ab, wbm_base + HAL_WBM_SW_COOKIE_CFG2, val); -diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c -index be34ba262f7a..7773c05ed246 100644 ---- a/drivers/net/wireless/ath/ath12k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -2526,7 +2526,6 @@ static void ath12k_dp_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *nap - bool is_mcbc = rxcb->is_mcbc; - bool is_eapol = rxcb->is_eapol; - -- status = IEEE80211_SKB_RXCB(msdu); - if (status->encoding == RX_ENC_HE && !(status->flag & RX_FLAG_RADIOTAP_HE) && - !(status->flag & RX_FLAG_SKIP_MONITOR)) { - he = skb_push(msdu, sizeof(known)); -diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index 19a484a0389e..61ef6ed9bf1d 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -5024,8 +5024,6 @@ static void ath12k_mac_vif_unref(struct ath12k_dp *dp, struct ieee80211_vif *vif +@@ -5091,8 +5091,6 @@ static void ath12k_mac_vif_unref(struct struct sk_buff *skb; int i; @@ -48,6 +21,3 @@ index 19a484a0389e..61ef6ed9bf1d 100644 for (i = 0; i < ATH12K_HW_MAX_QUEUES; i++) { spin_lock_bh(&dp->tx_desc_lock[i]); --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/525-ath12k-dp-rx-fixes.patch b/feeds/ipq95xx/mac80211/patches/qca/525-ath12k-dp-rx-fixes.patch deleted file mode 100644 index 0e08d5325..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/525-ath12k-dp-rx-fixes.patch +++ /dev/null @@ -1,62 +0,0 @@ -From cff1d65ca72c17c02dd73ea669bf38e619ec7a2e Mon Sep 17 00:00:00 2001 -From: Aishwarya R -Date: Tue, 15 Feb 2022 15:58:14 +0530 -Subject: [PATCH] ath12k dp rx fixes - -Signed-off-by: Aishwarya R ---- - drivers/net/wireless/ath/ath12k/dp_rx.c | 6 +++--- - drivers/net/wireless/ath/ath12k/hal_rx.c | 4 +++- - 2 files changed, 6 insertions(+), 4 deletions(-) - -diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c -index f8787413536e..4088a8d90a6c 100644 ---- a/drivers/net/wireless/ath/ath12k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -2608,7 +2608,7 @@ static int ath12k_dp_rx_process_msdu(struct ath12k *ar, - - rx_desc = (struct hal_rx_desc *)msdu->data; - lrx_desc = (struct hal_rx_desc *)last_buf->data; -- if (!ath12k_dp_rx_h_msdu_done(rx_desc)) { -+ if (!ath12k_dp_rx_h_msdu_done(lrx_desc)) { - ath12k_warn(ab, "msdu_done bit in msdu_end is not set\n"); - ret = -EIO; - goto free_out; -@@ -2616,7 +2616,7 @@ static int ath12k_dp_rx_process_msdu(struct ath12k *ar, - - rxcb = ATH12K_SKB_RXCB(msdu); - rxcb->rx_desc = rx_desc; -- msdu_len = ath12k_dp_rx_h_msdu_len(ab, rx_desc); -+ msdu_len = ath12k_dp_rx_h_msdu_len(ab, lrx_desc); - l3_pad_bytes = ath12k_dp_rx_h_l3pad(ab, lrx_desc); - - if (rxcb->is_frag) { -@@ -2721,9 +2721,9 @@ int ath12k_dp_process_rx(struct ath12k_base *ab, int ring_id, - - spin_lock_bh(&srng->lock); - -+try_again: - ath12k_hal_srng_access_begin(ab, srng); - --try_again: - while ((rx_desc = ath12k_hal_srng_dst_get_next_entry(ab, srng))) { - struct hal_reo_dest_ring desc = *(struct hal_reo_dest_ring *)rx_desc; - enum hal_reo_dest_ring_push_reason push_reason; -diff --git a/drivers/net/wireless/ath/ath12k/hal_rx.c b/drivers/net/wireless/ath/ath12k/hal_rx.c -index f0932abdeb7b..9c1e8274d96e 100644 ---- a/drivers/net/wireless/ath/ath12k/hal_rx.c -+++ b/drivers/net/wireless/ath/ath12k/hal_rx.c -@@ -832,7 +832,9 @@ void ath12k_hal_reo_hw_setup(struct ath12k_base *ab, u32 ring_hash_map) - val &= ~(HAL_REO1_MISC_CTL_FRAG_DST_RING | - HAL_REO1_MISC_CTL_BAR_DST_RING); - val |= FIELD_PREP(HAL_REO1_MISC_CTL_FRAG_DST_RING, -- HAL_SRNG_RING_ID_REO2SW1); -+ HAL_SRNG_RING_ID_REO2SW0); -+ val |= FIELD_PREP(HAL_REO1_MISC_CTL_BAR_DST_RING, -+ HAL_SRNG_RING_ID_REO2SW0); - ath12k_hif_write32(ab, reo_base + HAL_REO1_MISC_CTRL_ADDR, val); - - ath12k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_0, --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/526-ath12k-wbm-completion.patch b/feeds/ipq95xx/mac80211/patches/qca/526-ath12k-wbm-completion.patch deleted file mode 100644 index b9ca0624c..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/526-ath12k-wbm-completion.patch +++ /dev/null @@ -1,160 +0,0 @@ -From 41153ba967498b708e50b52f6c899b32d1ce11f1 Mon Sep 17 00:00:00 2001 -From: Aishwarya R -Date: Tue, 15 Feb 2022 16:46:18 +0530 -Subject: [PATCH] ath12k wbm completion - -Signed-off-by: Aishwarya R ---- - drivers/net/wireless/ath/ath12k/dp_rx.c | 29 ++++++++++++------------ - drivers/net/wireless/ath/ath12k/hal_rx.c | 4 +++- - drivers/net/wireless/ath/ath12k/hal_rx.h | 2 +- - 3 files changed, 19 insertions(+), 16 deletions(-) - ---- a/drivers/net/wireless/ath/ath12k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -3071,7 +3071,7 @@ static int ath12k_dp_rx_h_defrag_reo_rei - struct hal_rx_msdu_link *msdu_link; - struct hal_rx_msdu_details *msdu0; - struct hal_srng *srng; -- dma_addr_t paddr; -+ dma_addr_t link_paddr, buf_paddr; - u32 desc_bank, msdu_info, msdu_ext_info, mpdu_info; - u32 cookie, hal_rx_desc_sz; - int ret; -@@ -3082,9 +3082,11 @@ static int ath12k_dp_rx_h_defrag_reo_rei - link_desc_banks = dp->link_desc_banks; - reo_dest_ring = rx_tid->dst_ring_desc; - -- ath12k_hal_rx_reo_ent_paddr_get(ab, reo_dest_ring, &paddr, &desc_bank); -+ ath12k_hal_rx_reo_ent_paddr_get(ab, reo_dest_ring, &link_paddr, &cookie); -+ desc_bank = FIELD_GET(DP_LINK_DESC_BANK_MASK, cookie); -+ - msdu_link = (struct hal_rx_msdu_link *)(link_desc_banks[desc_bank].vaddr + -- (paddr - link_desc_banks[desc_bank].paddr)); -+ (link_paddr - link_desc_banks[desc_bank].paddr)); - msdu0 = &msdu_link->msdu_link[0]; - msdu_ext_info = msdu0->rx_msdu_ext_info.info0; - dst_ind = FIELD_GET(RX_MSDU_EXT_DESC_INFO0_REO_DEST_IND, msdu_ext_info); -@@ -3104,10 +3106,10 @@ static int ath12k_dp_rx_h_defrag_reo_rei - /* change msdu len in hal rx desc */ - ath12k_dp_rxdesc_set_msdu_len(ab, rx_desc, defrag_skb->len - hal_rx_desc_sz); - -- paddr = dma_map_single(ab->dev, defrag_skb->data, -+ buf_paddr = dma_map_single(ab->dev, defrag_skb->data, - defrag_skb->len + skb_tailroom(defrag_skb), - DMA_FROM_DEVICE); -- if (dma_mapping_error(ab->dev, paddr)) -+ if (dma_mapping_error(ab->dev, buf_paddr)) - return -ENOMEM; - - spin_lock_bh(&dp->rx_desc_lock); -@@ -3115,6 +3117,7 @@ static int ath12k_dp_rx_h_defrag_reo_rei - struct ath12k_rx_desc_info, - list); - if (!desc_info) { -+ ath12k_warn(ab, "failed to find rx desc for reinject\n"); - ret = -ENOMEM; - spin_unlock_bh(&dp->rx_desc_lock); - goto err_unmap_dma; -@@ -3122,15 +3125,14 @@ static int ath12k_dp_rx_h_defrag_reo_rei - - desc_info->skb = defrag_skb; - -- cookie = desc_info->cookie; -- - list_del(&desc_info->list); - list_add_tail(&desc_info->list, &dp->rx_desc_used_list); - spin_unlock_bh(&dp->rx_desc_lock); - -- ATH12K_SKB_RXCB(defrag_skb)->paddr = paddr; -+ ATH12K_SKB_RXCB(defrag_skb)->paddr = buf_paddr; - -- ath12k_hal_rx_buf_addr_info_set(msdu0, paddr, cookie, HAL_RX_BUF_RBM_SW3_BM); -+ ath12k_hal_rx_buf_addr_info_set(msdu0, buf_paddr, desc_info->cookie, -+ HAL_RX_BUF_RBM_SW3_BM); - - /* Fill mpdu details into reo entrace ring */ - srng = &ab->hal.srng_list[dp->reo_reinject_ring.ring_id]; -@@ -3144,12 +3146,11 @@ static int ath12k_dp_rx_h_defrag_reo_rei - ath12k_hal_srng_access_end(ab, srng); - spin_unlock_bh(&srng->lock); - ret = -ENOSPC; -- goto err_free_idr; -+ goto err_free_desc; - } - memset(reo_ent_ring, 0, sizeof(*reo_ent_ring)); - -- ath12k_hal_rx_reo_ent_paddr_get(ab, reo_dest_ring, &paddr, &desc_bank); -- ath12k_hal_rx_buf_addr_info_set(reo_ent_ring, paddr, desc_bank, -+ ath12k_hal_rx_buf_addr_info_set(reo_ent_ring, link_paddr, cookie, - HAL_RX_BUF_RBM_WBM_CHIP0_IDLE_DESC_LIST); - - mpdu_info = FIELD_PREP(RX_MPDU_DESC_INFO0_MSDU_COUNT, 1) | -@@ -3177,14 +3178,14 @@ static int ath12k_dp_rx_h_defrag_reo_rei - - return 0; - --err_free_idr: -+err_free_desc: - spin_lock_bh(&dp->rx_desc_lock); - list_del(&desc_info->list); - list_add_tail(&desc_info->list, &dp->rx_desc_free_list); - desc_info->skb = NULL; - spin_unlock_bh(&dp->rx_desc_lock); - err_unmap_dma: -- dma_unmap_single(ab->dev, paddr, defrag_skb->len + skb_tailroom(defrag_skb), -+ dma_unmap_single(ab->dev, buf_paddr, defrag_skb->len + skb_tailroom(defrag_skb), - DMA_FROM_DEVICE); - return ret; - } ---- a/drivers/net/wireless/ath/ath12k/hal_rx.c -+++ b/drivers/net/wireless/ath/ath12k/hal_rx.c -@@ -325,6 +325,7 @@ int ath12k_hal_desc_reo_parse_err(struct - struct hal_reo_dest_ring *desc = (struct hal_reo_dest_ring *)rx_desc; - enum hal_reo_dest_ring_push_reason push_reason; - enum hal_reo_dest_ring_error_code err_code; -+ u32 cookie; - - push_reason = FIELD_GET(HAL_REO_DEST_RING_INFO0_PUSH_REASON, - desc->info0); -@@ -345,7 +346,8 @@ int ath12k_hal_desc_reo_parse_err(struct - return -EINVAL; - } - -- ath12k_hal_rx_reo_ent_paddr_get(ab, rx_desc, paddr, desc_bank); -+ ath12k_hal_rx_reo_ent_paddr_get(ab, rx_desc, paddr, &cookie); -+ *desc_bank = FIELD_GET(DP_LINK_DESC_BANK_MASK, cookie); - - return 0; - } -@@ -428,17 +430,14 @@ int ath12k_hal_wbm_desc_parse_err(struct - } - - void ath12k_hal_rx_reo_ent_paddr_get(struct ath12k_base *ab, void *desc, -- dma_addr_t *paddr, u32 *desc_bank) -+ dma_addr_t *paddr, u32 *cookie) - { - struct ath12k_buffer_addr *buff_addr = desc; -- u32 cookie; - - *paddr = ((u64)(FIELD_GET(BUFFER_ADDR_INFO1_ADDR, buff_addr->info1)) << 32) | - FIELD_GET(BUFFER_ADDR_INFO0_ADDR, buff_addr->info0); - -- cookie = FIELD_GET(BUFFER_ADDR_INFO1_SW_COOKIE, buff_addr->info1); -- -- *desc_bank = FIELD_GET(DP_LINK_DESC_BANK_MASK, cookie); -+ *cookie = FIELD_GET(BUFFER_ADDR_INFO1_SW_COOKIE, buff_addr->info1); - } - - void ath12k_hal_rx_msdu_link_desc_set(struct ath12k_base *ab, void *desc, ---- a/drivers/net/wireless/ath/ath12k/hal_rx.h -+++ b/drivers/net/wireless/ath/ath12k/hal_rx.h -@@ -501,7 +501,7 @@ int ath12k_hal_desc_reo_parse_err(struct - int ath12k_hal_wbm_desc_parse_err(struct ath12k_base *ab, void *desc, - struct hal_rx_wbm_rel_info *rel_info); - void ath12k_hal_rx_reo_ent_paddr_get(struct ath12k_base *ab, void *desc, -- dma_addr_t *paddr, u32 *desc_bank); -+ dma_addr_t *paddr, u32 *cookie); - void ath12k_hal_rx_reo_ent_buf_paddr_get(void *rx_desc, - dma_addr_t *paddr, u32 *sw_cookie, - void **pp_buf_addr_info, u8 *rbm, diff --git a/feeds/ipq95xx/mac80211/patches/qca/527-ath12k-update-htt_tx_wbm_completion-descriptor-to-ve.patch b/feeds/ipq95xx/mac80211/patches/qca/527-ath12k-update-htt_tx_wbm_completion-descriptor-to-ve.patch deleted file mode 100644 index f8be0e194..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/527-ath12k-update-htt_tx_wbm_completion-descriptor-to-ve.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 8476c31ebf9f005a552e65ba35d393eb018c71cc Mon Sep 17 00:00:00 2001 -From: Pradeep Kumar Chitrapu -Date: Tue, 25 Jan 2022 20:31:19 -0800 -Subject: [PATCH] ath12k: update htt_tx_wbm_completion descriptor to version 3 - -QCN9224 uses htt descriptor version 3 for htt_tx_wbm_completion. - -Signed-off-by: Pradeep Kumar Chitrapu ---- - drivers/net/wireless/ath/ath12k/dp.h | 11 +++++++---- - drivers/net/wireless/ath/ath12k/dp_tx.c | 12 +++++++----- - drivers/net/wireless/ath/ath12k/hal_desc.h | 3 ++- - 3 files changed, 16 insertions(+), 10 deletions(-) - -diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h -index 77ac536e06aa..c35901369142 100644 ---- a/drivers/net/wireless/ath/ath12k/dp.h -+++ b/drivers/net/wireless/ath/ath12k/dp.h -@@ -409,17 +409,20 @@ struct ath12k_dp { - #define HTT_TX_WBM_COMP_STATUS_OFFSET 8 - - /* HTT tx completion is overlayed in wbm_release_ring */ --#define HTT_TX_WBM_COMP_INFO0_STATUS GENMASK(12, 9) --#define HTT_TX_WBM_COMP_INFO0_REINJECT_REASON GENMASK(16, 13) --#define HTT_TX_WBM_COMP_INFO0_REINJECT_REASON GENMASK(16, 13) -+#define HTT_TX_WBM_COMP_INFO0_STATUS GENMASK(16, 13) -+#define HTT_TX_WBM_COMP_INFO1_REINJECT_REASON GENMASK(3, 0) -+#define HTT_TX_WBM_COMP_INFO1_EXCEPTION_FRAME BIT(4) - --#define HTT_TX_WBM_COMP_INFO1_ACK_RSSI GENMASK(31, 24) -+#define HTT_TX_WBM_COMP_INFO2_ACK_RSSI GENMASK(31, 24) - - struct htt_tx_wbm_completion { -+ u32 rsvd0[2]; - u32 info0; - u32 info1; - u32 info2; - u32 info3; -+ u32 info4; -+ u32 rsvd1; - } __packed; - - enum htt_h2t_msg_type { -diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c -index f3309dca4c70..ebb1358c02c8 100644 ---- a/drivers/net/wireless/ath/ath12k/dp_tx.c -+++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -411,8 +411,8 @@ ath12k_dp_tx_process_htt_tx_complete(struct ath12k_base *ab, - case HAL_WBM_REL_HTT_TX_COMP_STATUS_DROP: - case HAL_WBM_REL_HTT_TX_COMP_STATUS_TTL: - ts.acked = (wbm_status == HAL_WBM_REL_HTT_TX_COMP_STATUS_OK); -- ts.ack_rssi = FIELD_GET(HTT_TX_WBM_COMP_INFO1_ACK_RSSI, -- status_desc->info1); -+ ts.ack_rssi = FIELD_GET(HTT_TX_WBM_COMP_INFO2_ACK_RSSI, -+ status_desc->info2); - ath12k_dp_tx_htt_tx_complete_buf(ab, msdu, tx_ring, &ts); - break; - case HAL_WBM_REL_HTT_TX_COMP_STATUS_REINJ: -@@ -544,6 +544,8 @@ static inline void ath12k_dp_tx_status_parse(struct ath12k_base *ab, - if (ts->buf_rel_source == HAL_WBM_REL_SRC_MODULE_FW) - return; - -+ ts->status = FIELD_GET(HAL_WBM_COMPL_TX_INFO0_TQM_RELEASE_REASON, -+ desc->info0); - ts->ppdu_id = FIELD_GET(HAL_WBM_COMPL_TX_INFO1_TQM_STATUS_NUMBER, - desc->info1); - if (desc->rate_stats.info0 & HAL_TX_RATE_STATS_INFO0_VALID) -@@ -600,12 +602,12 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id) - if (FIELD_GET(HAL_WBM_COMPL_TX_INFO0_CC_DONE, tx_status->info0)) { - /* HW done cookie conversion */ - tx_desc = (struct ath12k_tx_desc_info *) -- (tx_status->buf_addr_info.info0 | -- (((u64)tx_status->buf_addr_info.info1) << 32)); -+ (tx_status->buf_va_lo | -+ (((u64)tx_status->buf_va_hi) << 32)); - } else { - /* SW does cookie conversion to VA */ - desc_id = FIELD_GET(BUFFER_ADDR_INFO1_SW_COOKIE, -- tx_status->buf_addr_info.info1); -+ tx_status->buf_va_hi); - - tx_desc = ath12k_dp_get_tx_desc(ab, desc_id); - } -diff --git a/drivers/net/wireless/ath/ath12k/hal_desc.h b/drivers/net/wireless/ath/ath12k/hal_desc.h -index d6cb39500fc7..b930c22a3ebd 100644 ---- a/drivers/net/wireless/ath/ath12k/hal_desc.h -+++ b/drivers/net/wireless/ath/ath12k/hal_desc.h -@@ -1882,7 +1882,8 @@ struct hal_wbm_completion_ring_rx { - #define HAL_WBM_COMPL_TX_INFO3_LOOPING_COUNT GENMASK(31, 28) - - struct hal_wbm_completion_ring_tx { -- struct ath12k_buffer_addr buf_addr_info; -+ u32 buf_va_lo; -+ u32 buf_va_hi; - u32 info0; - u32 info1; - u32 info2; --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/528-ath12K-Enable-RAM-dump-support.patch b/feeds/ipq95xx/mac80211/patches/qca/528-ath12K-Enable-RAM-dump-support.patch index ae8451c7b..d5eca0c0a 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/528-ath12K-Enable-RAM-dump-support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/528-ath12K-Enable-RAM-dump-support.patch @@ -24,22 +24,18 @@ Signed-off-by: Balamurugan Selvarajan create mode 100644 drivers/net/wireless/ath/ath12k/coredump.c create mode 100644 drivers/net/wireless/ath/ath12k/coredump.h -Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/Makefile -=================================================================== ---- backports-20220209-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/Makefile -+++ backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/Makefile +--- a/drivers/net/wireless/ath/ath12k/Makefile ++++ b/drivers/net/wireless/ath/ath12k/Makefile @@ -27,6 +27,7 @@ ath12k-$(CPTCFG_NL80211_TESTMODE) += tes ath12k-$(CPTCFG_ATH12K_TRACING) += trace.o ath12k-$(CONFIG_THERMAL) += thermal.o ath12k-$(CPTCFG_ATH12K_SPECTRAL) += spectral.o -+ath12k-$(CONFIG_WANT_DEV_COREDUMP) += coredump.o ++ath12k-$(CPTCFG_WANT_DEV_COREDUMP) += coredump.o # for tracing framework to find trace.h CFLAGS_trace.o := -I$(src) -Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.c -=================================================================== ---- backports-20220209-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/core.c -+++ backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.c +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c @@ -10,6 +10,7 @@ #include #include @@ -48,7 +44,7 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor #include "dp_tx.h" #include "dp_rx.h" #include "debug.h" -@@ -946,6 +947,9 @@ static void ath12k_core_reset(struct wor +@@ -925,6 +926,9 @@ static void ath12k_core_reset(struct wor ath12k_dbg(ab, ATH12K_DBG_BOOT, "reset starting\n"); ab->is_reset = true; @@ -58,10 +54,8 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor atomic_set(&ab->recovery_count, 0); ath12k_core_pre_reconfigure_recovery(ab); -Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.h -=================================================================== ---- backports-20220209-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/core.h -+++ backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.h +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h @@ -503,6 +503,14 @@ struct ath12k_per_peer_tx_stats { bool is_ampdu; }; @@ -77,7 +71,7 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor #define ATH12K_FLUSH_TIMEOUT (5 * HZ) #define ATH12K_VDEV_DELETE_TIMEOUT_HZ (5 * HZ) -@@ -834,6 +842,7 @@ struct ath12k_base { +@@ -833,6 +841,7 @@ struct ath12k_base { struct timer_list mon_reap_timer; struct completion htc_suspend; @@ -85,10 +79,8 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor u64 fw_soc_drop_count; -Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/coredump.c -=================================================================== --- /dev/null -+++ backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/coredump.c ++++ b/drivers/net/wireless/ath/ath12k/coredump.c @@ -0,0 +1,222 @@ +// SPDX-License-Identifier: BSD-3-Clause-Clear +/* @@ -287,7 +279,7 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor + for (i = 0; i < ab->qmi.mem_seg_count; i++) { + if (ab->qmi.target_mem[i].type == CALDB_MEM_REGION_TYPE) { + if (ath12k_cold_boot_cal || -+ ab->hw_params.cold_boot_calib) { ++ ab->hw_params->cold_boot_calib) { + continue; + } + } @@ -312,10 +304,8 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor + + kfree(segment); +} -Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/coredump.h -=================================================================== --- /dev/null -+++ backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/coredump.h ++++ b/drivers/net/wireless/ath/ath12k/coredump.h @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: BSD-3-Clause-Clear +/* @@ -404,19 +394,17 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor + +#endif + -Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mhi.c -=================================================================== ---- backports-20220209-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/mhi.c -+++ backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mhi.c -@@ -299,6 +299,7 @@ int ath12k_mhi_register(struct ath12k_pc - mhi_ctrl->cntrl_dev = ab->dev; - mhi_ctrl->fw_image = ab_pci->amss_path; - mhi_ctrl->regs = ab->mem; +--- a/drivers/net/wireless/ath/ath12k/mhi.c ++++ b/drivers/net/wireless/ath/ath12k/mhi.c +@@ -392,6 +392,7 @@ int ath12k_mhi_register(struct ath12k_pc + #if LINUX_VERSION_IS_GEQ(5,10,0) + mhi_ctrl->reg_len = ab->mem_len; + #endif + mhi_ctrl->rddm_size = ATH12K_PCI_FW_RDDM_SZ; ret = ath12k_mhi_get_msi(ab_pci); if (ret) { -@@ -558,3 +559,8 @@ void ath12k_mhi_resume(struct ath12k_pci +@@ -648,3 +649,8 @@ void ath12k_mhi_resume(struct ath12k_pci { ath12k_mhi_set_state(ab_pci, ATH12K_MHI_RESUME); } @@ -425,10 +413,8 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mhi +{ + mhi_download_rddm_image(mhi_ctrl, false); +} -Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mhi.h -=================================================================== ---- backports-20220209-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/mhi.h -+++ backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mhi.h +--- a/drivers/net/wireless/ath/ath12k/mhi.h ++++ b/drivers/net/wireless/ath/ath12k/mhi.h @@ -16,6 +16,7 @@ #define MHISTATUS 0x48 #define MHICTRL 0x38 @@ -437,7 +423,7 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mhi enum ath12k_mhi_state { ATH12K_MHI_INIT, -@@ -39,5 +40,6 @@ void ath12k_mhi_clear_vector(struct ath1 +@@ -42,5 +43,6 @@ void ath12k_mhi_clear_vector(struct ath1 void ath12k_mhi_suspend(struct ath12k_pci *ar_pci); void ath12k_mhi_resume(struct ath12k_pci *ar_pci); diff --git a/feeds/ipq95xx/mac80211/patches/qca/529-b-ath12k-push-HE-MU-MIMO-and-OFDMA-params-to-hardware-.patch b/feeds/ipq95xx/mac80211/patches/qca/529-b-ath12k-push-HE-MU-MIMO-and-OFDMA-params-to-hardware-.patch index 5fb5e2e54..5b0f4067d 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/529-b-ath12k-push-HE-MU-MIMO-and-OFDMA-params-to-hardware-.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/529-b-ath12k-push-HE-MU-MIMO-and-OFDMA-params-to-hardware-.patch @@ -16,11 +16,9 @@ Signed-off-by: Pradeep Kumar Chitrapu drivers/net/wireless/ath/ath12k/wmi.h | 22 ++- 2 files changed, 145 insertions(+), 83 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index dcb99422a3a9..5ebb0da5e713 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -1963,6 +1963,122 @@ static int ath12k_setup_peer_smps(struct ath12k *ar, struct ath12k_vif *arvif, +@@ -2001,6 +2001,122 @@ static int ath12k_setup_peer_smps(struct ath12k_smps_map[smps]); } @@ -143,24 +141,24 @@ index dcb99422a3a9..5ebb0da5e713 100644 static void ath12k_bss_assoc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf) -@@ -1971,6 +2087,7 @@ static void ath12k_bss_assoc(struct ieee80211_hw *hw, - struct ath12k_vif *arvif = (void *)vif->drv_priv; +@@ -2010,6 +2126,7 @@ static void ath12k_bss_assoc(struct ieee struct peer_assoc_params peer_arg; struct ieee80211_sta *ap_sta; + struct ath12k_peer *peer; + struct ieee80211_sta_he_cap he_cap; + bool is_auth = false; int ret; - lockdep_assert_held(&ar->conf_mutex); -@@ -1987,6 +2104,8 @@ static void ath12k_bss_assoc(struct ieee80211_hw *hw, +@@ -2027,6 +2144,8 @@ static void ath12k_bss_assoc(struct ieee rcu_read_unlock(); return; } + /* he_cap here is updated at assoc success for sta mode only */ -+ he_cap = ap_sta->he_cap; ++ he_cap = ap_sta->deflink.he_cap; ath12k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg, false); -@@ -2013,6 +2132,12 @@ static void ath12k_bss_assoc(struct ieee80211_hw *hw, +@@ -2053,6 +2172,12 @@ static void ath12k_bss_assoc(struct ieee return; } @@ -172,8 +170,8 @@ index dcb99422a3a9..5ebb0da5e713 100644 + WARN_ON(arvif->is_up); - arvif->aid = bss_conf->aid; -@@ -2261,6 +2386,8 @@ static void ath12k_mac_op_bss_info_changed(struct ieee80211_hw *hw, + arvif->aid = vif->cfg.aid; +@@ -2311,6 +2436,8 @@ static void ath12k_mac_op_bss_info_chang ether_addr_copy(arvif->bssid, info->bssid); if (changed & BSS_CHANGED_BEACON_ENABLED) { @@ -182,7 +180,7 @@ index dcb99422a3a9..5ebb0da5e713 100644 ath12k_control_beaconing(arvif, info); if (arvif->is_up && vif->bss_conf.he_support && -@@ -4074,9 +4201,10 @@ static int ath12k_mac_copy_he_cap(struct ath12k *ar, +@@ -4139,9 +4266,10 @@ static int ath12k_mac_copy_he_cap(struct he_cap_elem->mac_cap_info[1] &= IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK; @@ -196,7 +194,7 @@ index dcb99422a3a9..5ebb0da5e713 100644 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] |= ar->num_tx_chains - 1; -@@ -4671,69 +4799,6 @@ ath12k_mac_setup_vdev_create_params(struct ath12k_vif *arvif, +@@ -4737,71 +4865,6 @@ ath12k_mac_setup_vdev_create_params(stru params->if_stats_id = ath12k_mac_get_vdev_stats_id(arvif); } @@ -215,18 +213,20 @@ index dcb99422a3a9..5ebb0da5e713 100644 - - hecap_phy_ptr = &cap_band->he_cap_phy_info[0]; - -- hemode = FIELD_PREP(HE_MODE_SU_TX_BFEE, HE_SU_BFEE_ENABLE) | -- FIELD_PREP(HE_MODE_SU_TX_BFER, HECAP_PHY_SUBFMR_GET(hecap_phy_ptr)) | -- FIELD_PREP(HE_MODE_UL_MUMIMO, HECAP_PHY_ULMUMIMO_GET(hecap_phy_ptr)); +- 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 |= FIELD_PREP(HE_MODE_MU_TX_BFER, -- HECAP_PHY_MUBFMR_GET(hecap_phy_ptr)) | -- FIELD_PREP(HE_MODE_DL_OFDMA, HE_DL_MUOFDMA_ENABLE) | -- FIELD_PREP(HE_MODE_UL_OFDMA, HE_UL_MUOFDMA_ENABLE); +- 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 |= FIELD_PREP(HE_MODE_MU_TX_BFEE, HE_MU_BFEE_ENABLE); +- hemode |= u32_encode_bits(HE_MU_BFEE_ENABLE, HE_MODE_MU_TX_BFEE); - } - - return hemode; @@ -250,9 +250,9 @@ index dcb99422a3a9..5ebb0da5e713 100644 - } - param_id = WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE; - param_value = -- FIELD_PREP(HE_VHT_SOUNDING_MODE, HE_VHT_SOUNDING_MODE_ENABLE) | -- FIELD_PREP(HE_TRIG_NONTRIG_SOUNDING_MODE, -- HE_TRIG_NONTRIG_SOUNDING_MODE_ENABLE); +- 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) { @@ -266,7 +266,7 @@ index dcb99422a3a9..5ebb0da5e713 100644 static void ath12k_mac_op_update_vif_offload(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { -@@ -5276,7 +5341,6 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif, +@@ -5345,7 +5408,6 @@ ath12k_mac_vdev_start_restart(struct ath struct ath12k *ar = arvif->ar; struct ath12k_base *ab = ar->ab; struct wmi_vdev_start_req_arg arg = {}; @@ -274,7 +274,7 @@ index dcb99422a3a9..5ebb0da5e713 100644 int ret = 0; lockdep_assert_held(&ar->conf_mutex); -@@ -5317,14 +5381,6 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif, +@@ -5386,14 +5448,6 @@ ath12k_mac_vdev_start_restart(struct ath spin_unlock_bh(&ab->base_lock); /* TODO: Notify if secondary 80Mhz also needs radar detection */ @@ -289,11 +289,9 @@ index dcb99422a3a9..5ebb0da5e713 100644 } arg.channel.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR); -diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h -index 2c1746d8255e..0e0831d4a0f8 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -2786,9 +2786,11 @@ struct rx_reorder_queue_remove_params { +@@ -2783,9 +2783,11 @@ struct rx_reorder_queue_remove_params { #define WMI_VDEV_PARAM_TXBF_SU_TX_BFER BIT(2) #define WMI_VDEV_PARAM_TXBF_MU_TX_BFER BIT(3) @@ -308,7 +306,7 @@ index 2c1746d8255e..0e0831d4a0f8 100644 #define HECAP_PHY_SU_BFER BIT(31) #define HECAP_PHY_SU_BFEE BIT(0) -@@ -2797,19 +2799,19 @@ struct rx_reorder_queue_remove_params { +@@ -2794,19 +2796,19 @@ struct rx_reorder_queue_remove_params { #define HECAP_PHY_UL_MUOFDMA BIT(23) #define HECAP_PHY_SUBFMR_GET(hecap_phy) \ @@ -333,7 +331,7 @@ index 2c1746d8255e..0e0831d4a0f8 100644 #define HE_MODE_SU_TX_BFEE BIT(0) #define HE_MODE_SU_TX_BFER BIT(1) -@@ -2822,8 +2824,12 @@ struct rx_reorder_queue_remove_params { +@@ -2819,8 +2821,12 @@ struct rx_reorder_queue_remove_params { #define HE_DL_MUOFDMA_ENABLE 1 #define HE_UL_MUOFDMA_ENABLE 1 #define HE_DL_MUMIMO_ENABLE 1 @@ -346,6 +344,3 @@ index 2c1746d8255e..0e0831d4a0f8 100644 #define HE_VHT_SOUNDING_MODE_ENABLE 1 #define HE_SU_MU_SOUNDING_MODE_ENABLE 1 --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/529-d-ath12k-add-support-for-setting-fixed-HE-rate-gi-ltf.patch b/feeds/ipq95xx/mac80211/patches/qca/529-d-ath12k-add-support-for-setting-fixed-HE-rate-gi-ltf.patch index b15eeddb6..034eac19c 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/529-d-ath12k-add-support-for-setting-fixed-HE-rate-gi-ltf.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/529-d-ath12k-add-support-for-setting-fixed-HE-rate-gi-ltf.patch @@ -16,11 +16,9 @@ Signed-off-by: Pradeep Kumar Chitrapu drivers/net/wireless/ath/ath12k/wmi.h | 20 + 3 files changed, 572 insertions(+), 44 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index 68f56a44890f..6fce0d554e43 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -354,6 +354,18 @@ ath12k_mac_max_vht_nss(const u16 vht_mcs_mask[NL80211_VHT_NSS_MAX]) +@@ -355,6 +355,18 @@ ath12k_mac_max_vht_nss(const u16 vht_mcs return 1; } @@ -39,7 +37,7 @@ index 68f56a44890f..6fce0d554e43 100644 static u8 ath12k_parse_mpdudensity(u8 mpdudensity) { /* 802.11n D2.0 defined values for "Minimum MPDU Start Spacing": -@@ -1329,6 +1341,14 @@ static void ath12k_peer_assoc_h_ht(struct ath12k *ar, +@@ -1330,6 +1342,14 @@ static void ath12k_peer_assoc_h_ht(struc arg->peer_rate_caps |= WMI_HOST_RC_CW40_FLAG; } @@ -54,12 +52,13 @@ index 68f56a44890f..6fce0d554e43 100644 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)) -@@ -1452,10 +1472,11 @@ static void ath12k_peer_assoc_h_vht(struct ath12k *ar, +@@ -1453,11 +1473,12 @@ static void ath12k_peer_assoc_h_vht(stru struct ath12k_vif *arvif = (void *)vif->drv_priv; 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; @@ -68,15 +67,15 @@ index 68f56a44890f..6fce0d554e43 100644 if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) return; -@@ -1498,6 +1519,25 @@ static void ath12k_peer_assoc_h_vht(struct ath12k *ar, - if (sta->bandwidth == IEEE80211_STA_RX_BW_160) +@@ -1500,6 +1521,25 @@ static void ath12k_peer_assoc_h_vht(stru + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) arg->bw_160 = true; + vht_nss = ath12k_mac_max_vht_nss(vht_mcs_mask); + -+ if (vht_nss > sta->rx_nss) { ++ if (vht_nss > sta->deflink.rx_nss) { + user_rate_valid = false; -+ for (nss_idx = sta->rx_nss - 1; nss_idx >= 0; nss_idx--) { ++ for (nss_idx = sta->deflink.rx_nss - 1; nss_idx >= 0; nss_idx--) { + if (vht_mcs_mask[nss_idx]) { + user_rate_valid = true; + break; @@ -87,14 +86,14 @@ index 68f56a44890f..6fce0d554e43 100644 + 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", -+ sta->rx_nss, sta->addr); -+ vht_mcs_mask[sta->rx_nss - 1] = vht_mcs_mask[vht_nss - 1]; ++ sta->deflink.rx_nss, sta->deflink.addr); ++ vht_mcs_mask[sta->deflink.rx_nss - 1] = vht_mcs_mask[vht_nss - 1]; + } + /* Calculate peer NSS capability from VHT capabilities if STA * supports VHT. */ -@@ -1536,18 +1576,100 @@ static void ath12k_peer_assoc_h_vht(struct ath12k *ar, +@@ -1539,21 +1579,104 @@ static void ath12k_peer_assoc_h_vht(stru /* TODO: rxnss_override */ } @@ -163,6 +162,7 @@ index 68f56a44890f..6fce0d554e43 100644 + + return true; +} ++ + static void ath12k_peer_assoc_h_he(struct ath12k *ar, struct ieee80211_vif *vif, @@ -171,14 +171,17 @@ index 68f56a44890f..6fce0d554e43 100644 { + struct ath12k_vif *arvif = (void *)vif->drv_priv; + struct cfg80211_chan_def def; - const struct ieee80211_sta_he_cap *he_cap = &sta->he_cap; - u8 ampdu_factor; + const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap; + int i; + u8 ampdu_factor, rx_mcs_80, rx_mcs_160, max_nss; + u16 mcs_160_map, mcs_80_map; + bool support_160; - u16 v; + enum nl80211_band band; + u16 *he_mcs_mask; -+ u8 max_nss, he_mcs; ++ u8 he_mcs; + u16 he_tx_mcs = 0, v = 0; -+ int i, he_nss, nss_idx; ++ int he_nss, nss_idx; + bool user_rate_valid = true; + + if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) @@ -195,16 +198,16 @@ index 68f56a44890f..6fce0d554e43 100644 + arg->he_flag = true; - memcpy(&arg->peer_he_cap_macinfo, he_cap->he_cap_elem.mac_cap_info, -@@ -1619,25 +1741,49 @@ static void ath12k_peer_assoc_h_he(struct ath12k *ar, + support_160 = !!(he_cap->he_cap_elem.phy_cap_info[0] & +@@ -1659,25 +1782,49 @@ 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 > sta->rx_nss) { ++ if (he_nss > sta->deflink.rx_nss) { + user_rate_valid = false; -+ for (nss_idx = sta->rx_nss - 1; nss_idx >= 0; nss_idx--) { ++ for (nss_idx = sta->deflink.rx_nss - 1; nss_idx >= 0; nss_idx--) { + if (he_mcs_mask[nss_idx]) { + user_rate_valid = true; + break; @@ -215,11 +218,11 @@ index 68f56a44890f..6fce0d554e43 100644 + 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", -+ sta->rx_nss, sta->addr); -+ he_mcs_mask[sta->rx_nss - 1] = he_mcs_mask[he_nss - 1]; ++ sta->deflink.rx_nss, sta->deflink.addr); ++ he_mcs_mask[sta->deflink.rx_nss - 1] = he_mcs_mask[he_nss - 1]; + } + - switch (sta->bandwidth) { + switch (sta->deflink.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) { @@ -246,7 +249,7 @@ index 68f56a44890f..6fce0d554e43 100644 fallthrough; default: -@@ -1645,11 +1791,34 @@ static void ath12k_peer_assoc_h_he(struct ath12k *ar, +@@ -1685,11 +1832,34 @@ 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); @@ -273,15 +276,15 @@ index 68f56a44890f..6fce0d554e43 100644 + he_mcs_mask[i]) + max_nss = i + 1; + } -+ arg->peer_nss = min(sta->rx_nss, max_nss); ++ arg->peer_nss = min(sta->deflink.rx_nss, max_nss); + + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, + "mac he peer %pM nss %d mcs cnt %d\n", -+ sta->addr, arg->peer_nss, arg->peer_he_mcs_count); ++ sta->deflink.addr, arg->peer_nss, arg->peer_he_mcs_count); } static void ath12k_peer_assoc_h_smps(struct ieee80211_sta *sta, -@@ -1852,6 +2021,7 @@ static void ath12k_peer_assoc_h_phymode(struct ath12k *ar, +@@ -1892,6 +2062,7 @@ static void ath12k_peer_assoc_h_phymode( enum nl80211_band band; const u8 *ht_mcs_mask; const u16 *vht_mcs_mask; @@ -289,7 +292,7 @@ index 68f56a44890f..6fce0d554e43 100644 enum wmi_phy_mode phymode = MODE_UNKNOWN; if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) -@@ -1860,10 +2030,12 @@ static void ath12k_peer_assoc_h_phymode(struct ath12k *ar, +@@ -1900,10 +2071,12 @@ 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; @@ -297,28 +300,26 @@ index 68f56a44890f..6fce0d554e43 100644 switch (band) { case NL80211_BAND_2GHZ: -- if (sta->he_cap.has_he) { -+ if (sta->he_cap.has_he && +- if (sta->deflink.he_cap.has_he) { ++ if (sta->deflink.he_cap.has_he && + !ath12k_peer_assoc_h_he_masked(he_mcs_mask)) { - if (sta->bandwidth == IEEE80211_STA_RX_BW_80) + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80) phymode = MODE_11AX_HE80_2G; - else if (sta->bandwidth == IEEE80211_STA_RX_BW_40) -@@ -1890,8 +2062,8 @@ static void ath12k_peer_assoc_h_phymode(struct ath12k *ar, - break; + else if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40) +@@ -1931,7 +2104,8 @@ static void ath12k_peer_assoc_h_phymode( case NL80211_BAND_5GHZ: case NL80211_BAND_6GHZ: -- /* Check HE first */ -- if (sta->he_cap.has_he) { -+ if (sta->he_cap.has_he && + /* Check HE first */ +- if (sta->deflink.he_cap.has_he) { ++ if (sta->deflink.he_cap.has_he && + !ath12k_peer_assoc_h_he_masked(he_mcs_mask)) { phymode = ath12k_mac_get_phymode_he(ar, sta); - } else if (sta->vht_cap.vht_supported && + } else if (sta->deflink.vht_cap.vht_supported && !ath12k_peer_assoc_h_vht_masked(vht_mcs_mask)) { -@@ -3091,6 +3263,20 @@ ath12k_mac_bitrate_mask_num_vht_rates(struct ath12k *ar, - return num_rates; +@@ -3147,6 +3321,20 @@ ath12k_mac_bitrate_mask_num_vht_rates(st } -+static int + static int +ath12k_mac_bitrate_mask_num_he_rates(struct ath12k *ar, + enum nl80211_band band, + const struct cfg80211_bitrate_mask *mask) @@ -332,10 +333,11 @@ index 68f56a44890f..6fce0d554e43 100644 + return num_rates; +} + - static int ++static int ath12k_mac_set_peer_vht_fixed_rate(struct ath12k_vif *arvif, struct ieee80211_sta *sta, -@@ -3137,6 +3323,57 @@ ath12k_mac_set_peer_vht_fixed_rate(struct ath12k_vif *arvif, + const struct cfg80211_bitrate_mask *mask, +@@ -3192,6 +3380,57 @@ ath12k_mac_set_peer_vht_fixed_rate(struc return ret; } @@ -363,29 +365,29 @@ index 68f56a44890f..6fce0d554e43 100644 + + if (!nss) { + ath12k_warn(ar->ab, "No single HE Fixed rate found to set for %pM", -+ sta->addr); ++ sta->deflink.addr); + return -EINVAL; + } + + /* Avoid updating invalid nss as fixed rate*/ -+ if (nss > sta->rx_nss) ++ 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", -+ sta->addr); ++ sta->deflink.addr); + + rate_code = ATH12K_HW_RATE_CODE(he_rate, nss - 1, + WMI_RATE_PREAMBLE_HE); + -+ ret = ath12k_wmi_set_peer_param(ar, sta->addr, ++ ret = ath12k_wmi_set_peer_param(ar, sta->deflink.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", -+ sta->addr, rate_code, ret); ++ sta->deflink.addr, rate_code, ret); + + return ret; +} @@ -393,7 +395,7 @@ index 68f56a44890f..6fce0d554e43 100644 static int ath12k_station_assoc(struct ath12k *ar, struct ieee80211_vif *vif, struct ieee80211_sta *sta, -@@ -3148,7 +3385,7 @@ static int ath12k_station_assoc(struct ath12k *ar, +@@ -3203,7 +3442,7 @@ static int ath12k_station_assoc(struct a struct cfg80211_chan_def def; enum nl80211_band band; struct cfg80211_bitrate_mask *mask; @@ -402,7 +404,7 @@ index 68f56a44890f..6fce0d554e43 100644 lockdep_assert_held(&ar->conf_mutex); -@@ -3174,9 +3411,10 @@ static int ath12k_station_assoc(struct ath12k *ar, +@@ -3229,9 +3468,10 @@ static int ath12k_station_assoc(struct a } num_vht_rates = ath12k_mac_bitrate_mask_num_vht_rates(ar, band, mask); @@ -415,12 +417,12 @@ index 68f56a44890f..6fce0d554e43 100644 * fixed param. * Note that all other rates and NSS will be disabled for this peer. */ -@@ -3185,7 +3423,12 @@ static int ath12k_station_assoc(struct ath12k *ar, +@@ -3240,7 +3480,12 @@ static int ath12k_station_assoc(struct a band); if (ret) return ret; - } -+ } else if (sta->he_cap.has_he && num_he_rates == 1) { ++ } else if (sta->deflink.he_cap.has_he && num_he_rates == 1) { + ret = ath12k_mac_set_peer_he_fixed_rate(arvif, sta, mask, + band); + if (ret) @@ -429,7 +431,7 @@ index 68f56a44890f..6fce0d554e43 100644 /* Re-assoc is run only to update supported rates for given station. It * doesn't make much sense to reconfigure the peer completely. -@@ -3255,8 +3498,9 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk) +@@ -3310,8 +3555,9 @@ static void ath12k_sta_rc_update_wk(stru enum nl80211_band band; const u8 *ht_mcs_mask; const u16 *vht_mcs_mask; @@ -440,7 +442,7 @@ index 68f56a44890f..6fce0d554e43 100644 const struct cfg80211_bitrate_mask *mask; struct peer_assoc_params peer_arg; -@@ -3271,6 +3515,7 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk) +@@ -3326,6 +3572,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; @@ -448,7 +450,7 @@ index 68f56a44890f..6fce0d554e43 100644 spin_lock_bh(&ar->data_lock); -@@ -3286,8 +3531,9 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk) +@@ -3341,8 +3588,9 @@ static void ath12k_sta_rc_update_wk(stru mutex_lock(&ar->conf_mutex); nss = max_t(u32, 1, nss); @@ -460,7 +462,7 @@ index 68f56a44890f..6fce0d554e43 100644 if (changed & IEEE80211_RC_BW_CHANGED) { err = ath12k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, -@@ -3323,6 +3569,8 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk) +@@ -3378,6 +3626,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); @@ -469,11 +471,11 @@ index 68f56a44890f..6fce0d554e43 100644 /* Peer_assoc_prepare will reject vht rates in * bitrate_mask if its not available in range format and -@@ -3338,11 +3586,25 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk) - if (sta->vht_cap.vht_supported && num_vht_rates == 1) { +@@ -3393,11 +3643,25 @@ static void ath12k_sta_rc_update_wk(stru + if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) { ath12k_mac_set_peer_vht_fixed_rate(arvif, sta, mask, band); -+ } else if (sta->he_cap.has_he && num_he_rates == 1) { ++ } else if (sta->deflink.he_cap.has_he && num_he_rates == 1) { + ath12k_mac_set_peer_he_fixed_rate(arvif, sta, mask, + band); } else { @@ -486,18 +488,18 @@ index 68f56a44890f..6fce0d554e43 100644 + * than peer assoc */ + -+ err = ath12k_wmi_set_peer_param(ar, sta->addr, ++ err = ath12k_wmi_set_peer_param(ar, sta->deflink.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", -+ sta->addr, err); ++ sta->deflink.addr, err); ath12k_peer_assoc_prepare(ar, arvif->vif, sta, &peer_arg, true); -@@ -4930,10 +5192,13 @@ static int ath12k_mac_op_add_interface(struct ieee80211_hw *hw, +@@ -5018,10 +5282,13 @@ static int ath12k_mac_op_add_interface(s for (i = 0; i < ARRAY_SIZE(arvif->bitrate_mask.control); i++) { arvif->bitrate_mask.control[i].legacy = 0xffffffff; @@ -511,7 +513,7 @@ index 68f56a44890f..6fce0d554e43 100644 } bit = __ffs64(ab->free_vdev_map); -@@ -5979,9 +6244,26 @@ ath12k_mac_has_single_legacy_rate(struct ath12k *ar, +@@ -6070,9 +6337,26 @@ ath12k_mac_has_single_legacy_rate(struct if (ath12k_mac_bitrate_mask_num_vht_rates(ar, band, mask)) return false; @@ -538,7 +540,7 @@ index 68f56a44890f..6fce0d554e43 100644 static bool ath12k_mac_bitrate_mask_get_single_nss(struct ath12k *ar, enum nl80211_band band, -@@ -5990,8 +6272,10 @@ ath12k_mac_bitrate_mask_get_single_nss(struct ath12k *ar, +@@ -6081,8 +6365,10 @@ ath12k_mac_bitrate_mask_get_single_nss(s { struct ieee80211_supported_band *sband = &ar->mac.sbands[band]; u16 vht_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map); @@ -549,7 +551,7 @@ index 68f56a44890f..6fce0d554e43 100644 int i; /* No need to consider legacy here. Basic rates are always present -@@ -6018,7 +6302,20 @@ ath12k_mac_bitrate_mask_get_single_nss(struct ath12k *ar, +@@ -6109,7 +6395,20 @@ ath12k_mac_bitrate_mask_get_single_nss(s return false; } @@ -571,7 +573,7 @@ index 68f56a44890f..6fce0d554e43 100644 return false; if (ht_nss_mask == 0) -@@ -6065,54 +6362,162 @@ ath12k_mac_get_single_legacy_rate(struct ath12k *ar, +@@ -6156,54 +6455,162 @@ ath12k_mac_get_single_legacy_rate(struct return 0; } @@ -754,7 +756,7 @@ index 68f56a44890f..6fce0d554e43 100644 return 0; } -@@ -6141,6 +6546,31 @@ ath12k_mac_vht_mcs_range_present(struct ath12k *ar, +@@ -6232,6 +6639,31 @@ ath12k_mac_vht_mcs_range_present(struct return true; } @@ -786,7 +788,7 @@ index 68f56a44890f..6fce0d554e43 100644 static void ath12k_mac_set_bitrate_mask_iter(void *data, struct ieee80211_sta *sta) { -@@ -6172,6 +6602,53 @@ static void ath12k_mac_disable_peer_fixed_rate(void *data, +@@ -6263,6 +6695,53 @@ static void ath12k_mac_disable_peer_fixe sta->addr, ret); } @@ -819,13 +821,13 @@ index 68f56a44890f..6fce0d554e43 100644 + spin_lock_bh(&ar->ab->base_lock); + list_for_each_entry_safe(peer, tmp, &ar->ab->peers, list) { + if (peer->sta) { -+ if (vht_fixed_rate && (!peer->sta->vht_cap.vht_supported || -+ peer->sta->rx_nss < vht_nss)) { ++ if (vht_fixed_rate && (!peer->sta->deflink.vht_cap.vht_supported || ++ peer->sta->deflink.rx_nss < vht_nss)) { + ret = false; + goto exit; + } -+ if (he_fixed_rate && (!peer->sta->he_cap.has_he || -+ peer->sta->rx_nss < he_nss)) { ++ if (he_fixed_rate && (!peer->sta->deflink.he_cap.has_he || ++ peer->sta->deflink.rx_nss < he_nss)) { + ret = false; + goto exit; + } @@ -840,7 +842,7 @@ index 68f56a44890f..6fce0d554e43 100644 static int ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif, -@@ -6183,6 +6660,9 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, +@@ -6274,6 +6753,9 @@ ath12k_mac_op_set_bitrate_mask(struct ie enum nl80211_band band; const u8 *ht_mcs_mask; const u16 *vht_mcs_mask; @@ -850,7 +852,7 @@ index 68f56a44890f..6fce0d554e43 100644 u32 rate; u8 nss; u8 sgi; -@@ -6190,6 +6670,7 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, +@@ -6281,6 +6763,7 @@ ath12k_mac_op_set_bitrate_mask(struct ie int single_nss; int ret; int num_rates; @@ -858,7 +860,7 @@ index 68f56a44890f..6fce0d554e43 100644 if (ath12k_mac_vif_chan(vif, &def)) return -EPERM; -@@ -6197,12 +6678,16 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, +@@ -6288,12 +6771,16 @@ 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; @@ -873,9 +875,9 @@ index 68f56a44890f..6fce0d554e43 100644 + he_ltf = mask->control[band].he_ltf; + /* mac80211 doesn't support sending a fixed HT/VHT MCS alone, rather it - * requires passing atleast one of used basic rates along with them. + * requires passing at least one of used basic rates along with them. * Fixed rate setting across different preambles(legacy, HT, VHT) is -@@ -6226,11 +6711,22 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, +@@ -6317,11 +6804,22 @@ ath12k_mac_op_set_bitrate_mask(struct ie &single_nss)) { rate = WMI_FIXED_RATE_NONE; nss = single_nss; @@ -900,7 +902,7 @@ index 68f56a44890f..6fce0d554e43 100644 /* If multiple rates across different preambles are given * we can reconfigure this info with all peers using PEER_ASSOC -@@ -6265,12 +6761,23 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, +@@ -6356,12 +6854,23 @@ ath12k_mac_op_set_bitrate_mask(struct ie return -EINVAL; } @@ -926,7 +928,7 @@ index 68f56a44890f..6fce0d554e43 100644 arvif->bitrate_mask = *mask; ieee80211_iterate_stations_atomic(ar->hw, ath12k_mac_set_bitrate_mask_iter, -@@ -6281,9 +6788,10 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, +@@ -6372,9 +6881,10 @@ ath12k_mac_op_set_bitrate_mask(struct ie mutex_lock(&ar->conf_mutex); @@ -939,13 +941,11 @@ index 68f56a44890f..6fce0d554e43 100644 arvif->vdev_id, ret); } -diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c -index 550a6a951dad..df05e00ac822 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -1964,8 +1964,8 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar, - FIELD_PREP(WMI_TLV_LEN, - sizeof(*he_mcs) - TLV_HDR_SIZE); +@@ -1988,8 +1988,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 = param->peer_he_rx_mcs_set[i]; - he_mcs->tx_mcs_set = param->peer_he_tx_mcs_set[i]; @@ -954,11 +954,9 @@ index 550a6a951dad..df05e00ac822 100644 ptr += sizeof(*he_mcs); } -diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h -index 0e0831d4a0f8..03944e1094b5 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -119,6 +119,22 @@ enum { +@@ -120,6 +120,21 @@ enum { WMI_HOST_WLAN_2G_5G_CAP = 0x3, }; @@ -977,11 +975,10 @@ index 0e0831d4a0f8..03944e1094b5 100644 + WMI_AUTORATE_1600NS_GI = BIT(10), + WMI_AUTORATE_3200NS_GI = BIT(11), +}; -+ - /* - * wmi command groups. - */ -@@ -1032,7 +1048,9 @@ enum wmi_tlv_vdev_param { + enum wmi_cmd_group { + /* 0 to 2 are reserved */ + WMI_GRP_START = 0x3, +@@ -1030,7 +1045,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, @@ -991,16 +988,13 @@ index 0e0831d4a0f8..03944e1094b5 100644 WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE = 0x87, WMI_VDEV_PARAM_6GHZ_PARAMS = 0x99, WMI_VDEV_PARAM_PROTOTYPE = 0x8000, -@@ -3932,7 +3950,9 @@ struct wmi_vht_rate_set { +@@ -3888,7 +3905,9 @@ struct wmi_vht_rate_set { struct wmi_he_rate_set { - u32 tlv_header; + __le32 tlv_header; + /* MCS at which the peer can receive */ u32 rx_mcs_set; + /* MCS at which the peer can transmit */ u32 tx_mcs_set; } __packed; --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/529-e-ath12k-add-support-for-80P80-and-160-MHz-bandwidth.patch b/feeds/ipq95xx/mac80211/patches/qca/529-e-ath12k-add-support-for-80P80-and-160-MHz-bandwidth.patch index bdfb58ce1..4624cf221 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/529-e-ath12k-add-support-for-80P80-and-160-MHz-bandwidth.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/529-e-ath12k-add-support-for-80P80-and-160-MHz-bandwidth.patch @@ -37,11 +37,9 @@ Signed-off-by: Aishwarya R drivers/net/wireless/ath/ath12k/wmi.h | 30 ++++++++ 5 files changed, 135 insertions(+), 14 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h -index 87f5af07821a..b6cfea69ae95 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h -@@ -659,6 +659,8 @@ struct ath12k_pdev_cap { +@@ -669,6 +669,8 @@ struct ath12k_pdev_cap { u32 tx_chain_mask_shift; u32 rx_chain_mask_shift; struct ath12k_band_cap band[NUM_NL80211_BANDS]; @@ -49,12 +47,10 @@ index 87f5af07821a..b6cfea69ae95 100644 + u8 nss_ratio_info; }; - struct ath12k_pdev { -diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index 6fce0d554e43..e26943018344 100644 + struct mlo_timestamp { --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -1463,6 +1463,33 @@ ath12k_peer_assoc_h_vht_limit(u16 tx_mcs_set, +@@ -1464,6 +1464,33 @@ ath12k_peer_assoc_h_vht_limit(u16 tx_mcs return tx_mcs_set; } @@ -88,7 +84,7 @@ index 6fce0d554e43..e26943018344 100644 static void ath12k_peer_assoc_h_vht(struct ath12k *ar, struct ieee80211_vif *vif, struct ieee80211_sta *sta, -@@ -1477,6 +1504,7 @@ static void ath12k_peer_assoc_h_vht(struct ath12k *ar, +@@ -1479,6 +1506,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; @@ -96,7 +92,7 @@ index 6fce0d554e43..e26943018344 100644 if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) return; -@@ -1570,10 +1598,29 @@ static void ath12k_peer_assoc_h_vht(struct ath12k *ar, +@@ -1573,10 +1601,29 @@ static void ath12k_peer_assoc_h_vht(stru /* TODO: Check */ arg->tx_max_mcs_nss = 0xFF; @@ -129,17 +125,17 @@ index 6fce0d554e43..e26943018344 100644 } static int ath12k_mac_get_max_he_mcs_map(u16 mcs_map, int nss) -@@ -1657,6 +1704,7 @@ static void ath12k_peer_assoc_h_he(struct ath12k *ar, +@@ -1664,6 +1711,7 @@ static void ath12k_peer_assoc_h_he(struc u16 he_tx_mcs = 0, v = 0; - int i, he_nss, nss_idx; + int he_nss, nss_idx; bool user_rate_valid = true; + u32 rx_nss, tx_nss, nss_160; if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) return; -@@ -1816,9 +1864,30 @@ static void ath12k_peer_assoc_h_he(struct ath12k *ar, +@@ -1855,9 +1903,30 @@ static void ath12k_peer_assoc_h_he(struc } - arg->peer_nss = min(sta->rx_nss, max_nss); + arg->peer_nss = min(sta->deflink.rx_nss, max_nss); + if (arg->peer_phymode == MODE_11AX_HE160 || + arg->peer_phymode == MODE_11AX_HE80_80) { @@ -162,15 +158,15 @@ index 6fce0d554e43..e26943018344 100644 + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, - "mac he peer %pM nss %d mcs cnt %d\n", -- sta->addr, arg->peer_nss, arg->peer_he_mcs_count); +- sta->deflink.addr, arg->peer_nss, arg->peer_he_mcs_count); + "mac he peer %pM nss %d mcs cnt %d nss_override 0x%x\n", -+ sta->addr, arg->peer_nss, ++ sta->deflink.addr, arg->peer_nss, + arg->peer_he_mcs_count, + arg->peer_bw_rxnss_override); } static void ath12k_peer_assoc_h_smps(struct ieee80211_sta *sta, -@@ -2105,11 +2174,11 @@ static void ath12k_peer_assoc_prepare(struct ath12k *ar, +@@ -2145,11 +2214,11 @@ static void ath12k_peer_assoc_prepare(st ath12k_peer_assoc_h_basic(ar, vif, sta, arg); ath12k_peer_assoc_h_crypto(ar, vif, sta, arg); ath12k_peer_assoc_h_rates(ar, vif, sta, arg); @@ -183,7 +179,7 @@ index 6fce0d554e43..e26943018344 100644 ath12k_peer_assoc_h_smps(sta, arg); /* TODO: amsdu_disable req? */ -@@ -4232,11 +4301,6 @@ ath12k_create_vht_cap(struct ath12k *ar, u32 rate_cap_tx_chainmask, +@@ -4316,11 +4385,6 @@ ath12k_create_vht_cap(struct ath12k *ar, ath12k_set_vht_txbf_cap(ar, &vht_cap.cap); @@ -195,7 +191,7 @@ index 6fce0d554e43..e26943018344 100644 rxmcs_map = 0; txmcs_map = 0; for (i = 0; i < 8; i++) { -@@ -7150,7 +7214,9 @@ static int ath12k_mac_setup_iface_combinations(struct ath12k *ar) +@@ -7256,7 +7320,9 @@ static int ath12k_mac_setup_iface_combin combinations[0].radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | BIT(NL80211_CHAN_WIDTH_20) | BIT(NL80211_CHAN_WIDTH_40) | @@ -206,7 +202,7 @@ index 6fce0d554e43..e26943018344 100644 ar->hw->wiphy->iface_combinations = combinations; ar->hw->wiphy->n_iface_combinations = 1; -@@ -7291,6 +7357,10 @@ static int __ath12k_mac_register(struct ath12k *ar) +@@ -7397,6 +7463,10 @@ static int __ath12k_mac_register(struct ieee80211_hw_set(ar->hw, SUPPORTS_TX_ENCAP_OFFLOAD); ieee80211_hw_set(ar->hw, SUPPORTS_RX_DECAP_OFFLOAD); } @@ -217,11 +213,9 @@ index 6fce0d554e43..e26943018344 100644 if (ht_cap & WMI_HT_CAP_ENABLED) { ieee80211_hw_set(ar->hw, AMPDU_AGGREGATION); ieee80211_hw_set(ar->hw, TX_AMPDU_SETUP_IN_HW); -diff --git a/drivers/net/wireless/ath/ath12k/mac.h b/drivers/net/wireless/ath/ath12k/mac.h -index f91df777880a..13ce3730c645 100644 --- a/drivers/net/wireless/ath/ath12k/mac.h +++ b/drivers/net/wireless/ath/ath12k/mac.h -@@ -115,6 +115,9 @@ struct ath12k_generic_iter { +@@ -116,6 +116,9 @@ struct ath12k_generic_iter { #define WMI_MAX_SPATIAL_STREAM 3 #define ATH12K_CHAN_WIDTH_NUM 8 @@ -231,11 +225,9 @@ index f91df777880a..13ce3730c645 100644 extern const struct htt_rx_ring_tlv_filter ath12k_mac_mon_status_filter_default; -diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c -index df05e00ac822..1a3bf9f94203 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -419,6 +419,10 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_pdev_wmi *wmi_handle, +@@ -468,6 +468,10 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(st pdev_cap->he_mcs = mac_phy_caps->he_supp_mcs_5g; pdev_cap->tx_chain_mask = mac_phy_caps->tx_chain_mask_5g; pdev_cap->rx_chain_mask = mac_phy_caps->rx_chain_mask_5g; @@ -246,7 +238,7 @@ index df05e00ac822..1a3bf9f94203 100644 } else { return -EINVAL; } -@@ -843,14 +847,26 @@ int ath12k_wmi_vdev_down(struct ath12k *ar, u8 vdev_id) +@@ -888,14 +892,26 @@ int ath12k_wmi_vdev_down(struct ath12k * static void ath12k_wmi_put_wmi_channel(struct wmi_channel *chan, struct wmi_vdev_start_req_arg *arg) { @@ -258,7 +250,7 @@ index df05e00ac822..1a3bf9f94203 100644 chan->band_center_freq1 = arg->channel.band_center_freq1; - if (arg->channel.mode == MODE_11AC_VHT80_80) + -+ if (arg->channel.mode == MODE_11AX_HE160) { ++ if ((arg->channel.mode == MODE_11AX_HE160) || (arg->channel.mode == MODE_11BE_EHT160)) { + if (arg->channel.freq > arg->channel.band_center_freq1) + chan->band_center_freq1 = center_freq1 + 40; + else @@ -273,13 +265,11 @@ index df05e00ac822..1a3bf9f94203 100644 chan->band_center_freq2 = 0; + } - chan->info |= FIELD_PREP(WMI_CHAN_INFO_MODE, arg->channel.mode); + chan->info |= u32_encode_bits(arg->channel.mode, WMI_CHAN_INFO_MODE); if (arg->channel.passive) -diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h -index 03944e1094b5..d7b39115b21f 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -2134,6 +2134,24 @@ enum wmi_direct_buffer_module { +@@ -2131,6 +2131,24 @@ enum wmi_direct_buffer_module { WMI_DIRECT_BUF_MAX }; @@ -304,7 +294,7 @@ index 03944e1094b5..d7b39115b21f 100644 struct wmi_host_pdev_band_to_mac { u32 pdev_id; u32 start_freq; -@@ -2390,6 +2408,12 @@ struct wmi_hw_mode_capabilities { +@@ -2386,6 +2404,12 @@ struct wmi_hw_mode_capabilities { } __packed; #define WMI_MAX_HECAP_PHY_SIZE (3) @@ -317,7 +307,7 @@ index 03944e1094b5..d7b39115b21f 100644 struct wmi_mac_phy_capabilities { u32 hw_mode_id; -@@ -2423,6 +2447,12 @@ struct wmi_mac_phy_capabilities { +@@ -2419,6 +2443,12 @@ struct wmi_mac_phy_capabilities { u32 he_cap_info_2g_ext; u32 he_cap_info_5g_ext; u32 he_cap_info_internal; @@ -330,6 +320,3 @@ index 03944e1094b5..d7b39115b21f 100644 } __packed; struct wmi_hal_reg_capabilities_ext { --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/529-f-ath12k-add-extended-NSS-bandwidth-support-for-160MHz.patch b/feeds/ipq95xx/mac80211/patches/qca/529-f-ath12k-add-extended-NSS-bandwidth-support-for-160MHz.patch index ae169aded..e5fac7584 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/529-f-ath12k-add-extended-NSS-bandwidth-support-for-160MHz.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/529-f-ath12k-add-extended-NSS-bandwidth-support-for-160MHz.patch @@ -30,7 +30,7 @@ index e26943018344..63b51cf33a14 100644 + tx_nss = ath12k_get_nss_160mhz(ar, ar->num_tx_chains); rx_nss = min(arg->peer_nss, tx_nss); + -+ arg->peer_nss = min(sta->rx_nss, ar->num_rx_chains); ++ arg->peer_nss = min(sta->deflink.rx_nss, ar->num_rx_chains); arg->peer_bw_rxnss_override = ATH12K_BW_NSS_MAP_ENABLE; if (!rx_nss) { diff --git a/feeds/ipq95xx/mac80211/patches/qca/530-d-ath12k-add-6-GHz-params-in-peer-assoc-command.patch b/feeds/ipq95xx/mac80211/patches/qca/530-d-ath12k-add-6-GHz-params-in-peer-assoc-command.patch index 6799907e7..8754c2381 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/530-d-ath12k-add-6-GHz-params-in-peer-assoc-command.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/530-d-ath12k-add-6-GHz-params-in-peer-assoc-command.patch @@ -27,7 +27,7 @@ index 560ad76903dd..29a6fe151694 100644 + struct ieee80211_sta *sta, + struct peer_assoc_params *arg) +{ -+ const struct ieee80211_sta_he_cap *he_cap = &sta->he_cap; ++ const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap; + struct cfg80211_chan_def def; + enum nl80211_band band; + u8 ampdu_factor; @@ -37,16 +37,16 @@ index 560ad76903dd..29a6fe151694 100644 + + band = def.chan->band; + -+ if (!arg->he_flag || band != NL80211_BAND_6GHZ || !sta->he_6ghz_capa.capa) ++ if (!arg->he_flag || band != NL80211_BAND_6GHZ || !sta->deflink.he_6ghz_capa.capa) + return; + -+ if (sta->bandwidth == IEEE80211_STA_RX_BW_80) ++ if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80) + arg->bw_80 = true; + -+ if (sta->bandwidth == IEEE80211_STA_RX_BW_160) ++ if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) + arg->bw_160 = true; + -+ arg->peer_he_caps_6ghz = le16_to_cpu(sta->he_6ghz_capa.capa); ++ arg->peer_he_caps_6ghz = le16_to_cpu(sta->deflink.he_6ghz_capa.capa); + arg->peer_mpdu_density = + ath12k_parse_mpdudensity(FIELD_GET(IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START, + arg->peer_he_caps_6ghz)); diff --git a/feeds/ipq95xx/mac80211/patches/qca/530-e-ath12k-support-SMPS-configuration-for-6-GHz.patch b/feeds/ipq95xx/mac80211/patches/qca/530-e-ath12k-support-SMPS-configuration-for-6-GHz.patch index cbe69eecf..671f8cf73 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/530-e-ath12k-support-SMPS-configuration-for-6-GHz.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/530-e-ath12k-support-SMPS-configuration-for-6-GHz.patch @@ -11,16 +11,14 @@ Signed-off-by: Pradeep Kumar Chitrapu drivers/net/wireless/ath/ath12k/mac.c | 31 ++++++++++++++++++--------- 1 file changed, 21 insertions(+), 10 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index 29a6fe151694..74c169bb69d2 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -1948,11 +1948,16 @@ static void ath12k_peer_assoc_h_smps(struct ieee80211_sta *sta, - const struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; +@@ -1985,11 +1985,16 @@ static void ath12k_peer_assoc_h_smps(str + const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap; int smps; - if (!ht_cap->ht_supported) -+ if (!ht_cap->ht_supported && !sta->he_6ghz_capa.capa) ++ if (!ht_cap->ht_supported && !sta->deflink.he_6ghz_capa.capa) return; - smps = ht_cap->cap & IEEE80211_HT_CAP_SM_PS; @@ -30,12 +28,12 @@ index 29a6fe151694..74c169bb69d2 100644 + smps >>= IEEE80211_HT_CAP_SM_PS_SHIFT; + } else { + smps = FIELD_GET(IEEE80211_HE_6GHZ_CAP_SM_PS, -+ le16_to_cpu(sta->he_6ghz_capa.capa)); ++ le16_to_cpu(sta->deflink.he_6ghz_capa.capa)); + } switch (smps) { case WLAN_HT_CAP_SM_PS_STATIC: -@@ -2239,15 +2244,20 @@ static void ath12k_peer_assoc_prepare(struct ath12k *ar, +@@ -2277,15 +2282,20 @@ static void ath12k_peer_assoc_prepare(st static int ath12k_setup_peer_smps(struct ath12k *ar, struct ath12k_vif *arvif, const u8 *addr, @@ -60,26 +58,27 @@ index 29a6fe151694..74c169bb69d2 100644 if (smps >= ARRAY_SIZE(ath12k_smps_map)) return -EINVAL; -@@ -2419,7 +2429,8 @@ static void ath12k_bss_assoc(struct ieee80211_hw *hw, +@@ -2459,7 +2469,8 @@ static void ath12k_bss_assoc(struct ieee } ret = ath12k_setup_peer_smps(ar, arvif, bss_conf->bssid, -- &ap_sta->ht_cap); -+ &ap_sta->ht_cap, -+ le16_to_cpu(ap_sta->he_6ghz_capa.capa)); +- &ap_sta->deflink.ht_cap); ++ &ap_sta->deflink.ht_cap, ++ le16_to_cpu(ap_sta->deflink.he_6ghz_capa.capa)); if (ret) { ath12k_warn(ar->ab, "failed to setup peer SMPS for vdev %d: %d\n", arvif->vdev_id, ret); -@@ -3559,7 +3570,7 @@ static int ath12k_station_assoc(struct ath12k *ar, +@@ -3609,7 +3620,8 @@ static int ath12k_station_assoc(struct a return 0; ret = ath12k_setup_peer_smps(ar, arvif, sta->addr, -- &sta->ht_cap); -+ &sta->ht_cap, le16_to_cpu(sta->he_6ghz_capa.capa)); +- &sta->deflink.ht_cap); ++ &sta->deflink.ht_cap, ++ le16_to_cpu(sta->deflink.he_6ghz_capa.capa)); if (ret) { ath12k_warn(ar->ab, "failed to setup peer SMPS for vdev %d: %d\n", arvif->vdev_id, ret); -@@ -7454,7 +7465,7 @@ static int __ath12k_mac_register(struct ath12k *ar) +@@ -7536,7 +7548,7 @@ static int __ath12k_mac_register(struct * for each band for a dual band capable radio. It will be tricky to * handle it when the ht capability different for each band. */ @@ -88,6 +87,3 @@ index 29a6fe151694..74c169bb69d2 100644 ar->hw->wiphy->features |= NL80211_FEATURE_DYNAMIC_SMPS; ar->hw->wiphy->max_scan_ssids = WLAN_SCAN_PARAMS_MAX_SSID; --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/531-ath12k-Fix-setting-msdu_ext_desc-in-Ethernet-and-RAW.patch b/feeds/ipq95xx/mac80211/patches/qca/531-ath12k-Fix-setting-msdu_ext_desc-in-Ethernet-and-RAW.patch index 966756947..4df0fde09 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/531-ath12k-Fix-setting-msdu_ext_desc-in-Ethernet-and-RAW.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/531-ath12k-Fix-setting-msdu_ext_desc-in-Ethernet-and-RAW.patch @@ -26,7 +26,7 @@ Signed-off-by: Pradeep Kumar Chitrapu --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h -@@ -48,6 +48,8 @@ extern unsigned int ath12k_frame_mode; +@@ -46,6 +46,8 @@ extern unsigned int ath12k_frame_mode; #define ATH12K_RECONFIGURE_TIMEOUT_HZ (10 * HZ) #define ATH12K_RECOVER_START_TIMEOUT_HZ (20 * HZ) @@ -37,7 +37,7 @@ Signed-off-by: Pradeep Kumar Chitrapu ATH12K_BW_40 = 1, --- a/drivers/net/wireless/ath/ath12k/dp.c +++ b/drivers/net/wireless/ath/ath12k/dp.c -@@ -327,8 +327,11 @@ void ath12k_dp_tx_get_vdev_bank_config(s +@@ -320,8 +320,11 @@ void ath12k_dp_tx_get_vdev_bank_config(s * With SW crypto, mac80211 sets key per packet */ if (arvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW && @@ -48,9 +48,9 @@ Signed-off-by: Pradeep Kumar Chitrapu + else + encrypt_type = HAL_ENCRYPT_TYPE_OPEN; - *bank_config |= FIELD_PREP(HAL_TX_BANK_CONFIG_ENCAP_TYPE, arvif->tx_encap_type) | - FIELD_PREP(HAL_TX_BANK_CONFIG_ENCRYPT_TYPE, encrypt_type); -@@ -406,6 +409,15 @@ void ath12k_dp_tx_put_bank_profile(struc + *bank_config |= u32_encode_bits(arvif->tx_encap_type, + HAL_TX_BANK_CONFIG_ENCAP_TYPE) | +@@ -405,6 +408,15 @@ void ath12k_dp_tx_put_bank_profile(struc spin_unlock_bh(&dp->tx_bank_lock); } @@ -68,7 +68,7 @@ Signed-off-by: Pradeep Kumar Chitrapu struct ath12k_dp *dp = &ab->dp; --- a/drivers/net/wireless/ath/ath12k/dp.h +++ b/drivers/net/wireless/ath/ath12k/dp.h -@@ -2060,4 +2060,5 @@ struct ath12k_rx_desc_info *ath12k_dp_ge +@@ -2021,4 +2021,5 @@ struct ath12k_rx_desc_info *ath12k_dp_ge u32 cookie); struct ath12k_tx_desc_info *ath12k_dp_get_tx_desc(struct ath12k_base *ab, u32 desc_id); @@ -76,16 +76,16 @@ Signed-off-by: Pradeep Kumar Chitrapu #endif --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -113,7 +113,7 @@ static void ath12k_hal_tx_cmd_ext_desc_s - tcl_ext_cmd->info1 = FIELD_PREP(HAL_TX_MSDU_EXT_INFO1_BUF_PTR_HI, 0x0) | - FIELD_PREP(HAL_TX_MSDU_EXT_INFO1_BUF_LEN, ti->data_len); +@@ -114,7 +114,7 @@ static void ath12k_hal_tx_cmd_ext_desc_s + u32_encode_bits(ti->data_len, + HAL_TX_MSDU_EXT_INFO1_BUF_LEN); -- tcl_ext_cmd->info1 = FIELD_PREP(HAL_TX_MSDU_EXT_INFO1_EXTN_OVERRIDE, 1) | -+ tcl_ext_cmd->info1 |= FIELD_PREP(HAL_TX_MSDU_EXT_INFO1_EXTN_OVERRIDE, 1) | - FIELD_PREP(HAL_TX_MSDU_EXT_INFO1_ENCAP_TYPE, - ti->encap_type) | - FIELD_PREP(HAL_TX_MSDU_EXT_INFO1_ENCRYPT_TYPE, -@@ -176,21 +176,6 @@ tcl_ring_sel: +- tcl_ext_cmd->info1 = u32_encode_bits(1, HAL_TX_MSDU_EXT_INFO1_EXTN_OVERRIDE) | ++ tcl_ext_cmd->info1 |= u32_encode_bits(1, HAL_TX_MSDU_EXT_INFO1_EXTN_OVERRIDE) | + u32_encode_bits(ti->encap_type, + HAL_TX_MSDU_EXT_INFO1_ENCAP_TYPE) | + u32_encode_bits(ti->encrypt_type, +@@ -177,21 +177,6 @@ tcl_ring_sel: ti.bank_id = arvif->bank_id; ti.meta_data_flags = arvif->tcl_metadata; @@ -107,7 +107,7 @@ Signed-off-by: Pradeep Kumar Chitrapu ti.encap_type = ath12k_dp_tx_get_encap_type(arvif, skb); ti.addr_search_flags = arvif->hal_addr_search_flags; ti.search_type = arvif->search_type; -@@ -244,6 +229,28 @@ tcl_ring_sel: +@@ -245,6 +230,34 @@ tcl_ring_sel: goto fail_remove_tx_buf; } @@ -122,6 +122,12 @@ Signed-off-by: Pradeep Kumar Chitrapu + } + + if (arvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW) { ++ if (skb->protocol == cpu_to_be16(ETH_P_ARP)) { ++ ti.encap_type = HAL_TCL_ENCAP_TYPE_RAW; ++ ti.encrypt_type = HAL_ENCRYPT_TYPE_OPEN; ++ msdu_ext_desc = true; ++ } ++ + if (skb_cb->flags & ATH12K_SKB_CIPHER_SET) { + ti.encrypt_type = + ath12k_dp_tx_get_encrypt_type(skb_cb->cipher); @@ -138,7 +144,7 @@ Signed-off-by: Pradeep Kumar Chitrapu ti.desc_id = tx_desc->desc_id; --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -3212,8 +3212,10 @@ install: +@@ -3261,8 +3261,10 @@ install: if (!wait_for_completion_timeout(&ar->install_key_done, 1 * HZ)) return -ETIMEDOUT; @@ -150,7 +156,7 @@ Signed-off-by: Pradeep Kumar Chitrapu return ar->install_key_status ? -EINVAL : 0; } -@@ -5336,6 +5338,7 @@ static int ath12k_mac_op_add_interface(s +@@ -5402,6 +5404,7 @@ static int ath12k_mac_op_add_interface(s INIT_LIST_HEAD(&arvif->list); @@ -158,7 +164,7 @@ Signed-off-by: Pradeep Kumar Chitrapu /* Should we initialize any worker to handle connection loss indication * from firmware in sta mode? */ -@@ -5623,6 +5626,7 @@ err_vdev_del: +@@ -5689,6 +5692,7 @@ err_vdev_del: ath12k_mac_vif_unref(&ab->dp, vif); ath12k_dp_tx_put_bank_profile(&ab->dp, arvif->bank_id); diff --git a/feeds/ipq95xx/mac80211/patches/qca/532-ath12k-Fix-Access-Violation-with-ath12k_pci-rmmod.patch b/feeds/ipq95xx/mac80211/patches/qca/532-ath12k-Fix-Access-Violation-with-ath12k_pci-rmmod.patch index cbf7ae5ed..811d2c916 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/532-ath12k-Fix-Access-Violation-with-ath12k_pci-rmmod.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/532-ath12k-Fix-Access-Violation-with-ath12k_pci-rmmod.patch @@ -23,7 +23,7 @@ Signed-off-by: Karthikeyan Periyasamy --- a/drivers/net/wireless/ath/ath12k/pci.c +++ b/drivers/net/wireless/ath/ath12k/pci.c -@@ -357,6 +357,8 @@ static void ath12k_pci_force_wake(struct +@@ -297,6 +297,8 @@ static void ath12k_pci_force_wake(struct static void ath12k_pci_sw_reset(struct ath12k_base *ab, bool power_on) { @@ -32,128 +32,3 @@ Signed-off-by: Karthikeyan Periyasamy if (power_on) { ath12k_pci_enable_ltssm(ab); ath12k_pci_clear_all_intrs(ab); -@@ -366,9 +368,9 @@ static void ath12k_pci_sw_reset(struct a - } - - ath12k_mhi_clear_vector(ab); -+ ath12k_pci_clear_dbg_registers(ab); - ath12k_pci_soc_global_reset(ab); - ath12k_mhi_set_mhictrl_reset(ab); -- ath12k_pci_clear_dbg_registers(ab); - } - - static void ath12k_pci_free_ext_irq(struct ath12k_base *ab) -@@ -685,7 +687,32 @@ static void ath12k_pci_ce_irqs_enable(st - } - } - --static int ath12k_pci_enable_msi(struct ath12k_pci *ab_pci) -+static void ath12k_pci_msi_config(struct ath12k_pci *ab_pci, bool enable) -+{ -+ struct pci_dev *dev = ab_pci->pdev; -+ u16 control; -+ -+ pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control); -+ -+ if (enable) -+ control |= PCI_MSI_FLAGS_ENABLE; -+ else -+ control &= ~PCI_MSI_FLAGS_ENABLE; -+ -+ pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control); -+} -+ -+static void ath12k_pci_msi_enable(struct ath12k_pci *ab_pci) -+{ -+ ath12k_pci_msi_config(ab_pci, true); -+} -+ -+static void ath12k_pci_msi_disable(struct ath12k_pci *ab_pci) -+{ -+ ath12k_pci_msi_config(ab_pci, false); -+} -+ -+static int ath12k_pci_alloc_msi(struct ath12k_pci *ab_pci) - { - struct ath12k_base *ab = ab_pci->ab; - const struct ath12k_msi_config *msi_config = ab_pci->msi_config; -@@ -707,6 +734,8 @@ static int ath12k_pci_enable_msi(struct - return num_vectors; - } - -+ ath12k_pci_msi_disable(ab_pci); -+ - msi_desc = irq_get_msi_desc(ab_pci->pdev->irq); - if (!msi_desc) { - ath12k_err(ab, "msi_desc is NULL!\n"); -@@ -728,7 +757,7 @@ free_msi_vector: - return ret; - } - --static void ath12k_pci_disable_msi(struct ath12k_pci *ab_pci) -+static void ath12k_pci_free_msi(struct ath12k_pci *ab_pci) - { - pci_free_irq_vectors(ab_pci->pdev); - } -@@ -1174,6 +1203,8 @@ int ath12k_pci_power_up(struct ath12k_ba - */ - ath12k_pci_aspm_disable(ab_pci); - -+ ath12k_pci_msi_enable(ab_pci); -+ - ath12k_pci_update_qrtr_node_id(ab); - - ret = ath12k_mhi_start(ab_pci); -@@ -1196,6 +1227,7 @@ void ath12k_pci_power_down(struct ath12k - ath12k_pci_aspm_restore(ab_pci); - - ath12k_pci_force_wake(ab_pci->ab); -+ ath12k_pci_msi_disable(ab_pci); - ath12k_mhi_stop(ab_pci); - clear_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags); - ath12k_pci_sw_reset(ab_pci->ab, false); -@@ -1273,20 +1305,20 @@ static int ath12k_pci_probe(struct pci_d - goto err_pci_free_region; - } - -- ret = ath12k_pci_enable_msi(ab_pci); -+ ret = ath12k_pci_alloc_msi(ab_pci); - if (ret) { -- ath12k_err(ab, "failed to enable msi: %d\n", ret); -+ ath12k_err(ab, "failed to alloc msi: %d\n", ret); - goto err_pci_free_region; - } - - ret = ath12k_core_pre_init(ab); - if (ret) -- goto err_pci_disable_msi; -+ goto err_pci_free_msi; - - ret = ath12k_mhi_register(ab_pci); - if (ret) { - ath12k_err(ab, "failed to register mhi: %d\n", ret); -- goto err_pci_disable_msi; -+ goto err_pci_free_msi; - } - - ret = ath12k_hal_srng_init(ab); -@@ -1326,8 +1358,8 @@ err_hal_srng_deinit: - err_mhi_unregister: - ath12k_mhi_unregister(ab_pci); - --err_pci_disable_msi: -- ath12k_pci_disable_msi(ab_pci); -+err_pci_free_msi: -+ ath12k_pci_free_msi(ab_pci); - - err_pci_free_region: - ath12k_pci_free_region(ab_pci); -@@ -1359,7 +1391,7 @@ qmi_fail: - ath12k_mhi_unregister(ab_pci); - - ath12k_pci_free_irq(ab); -- ath12k_pci_disable_msi(ab_pci); -+ ath12k_pci_free_msi(ab_pci); - ath12k_pci_free_region(ab_pci); - - ath12k_hal_srng_deinit(ab); diff --git a/feeds/ipq95xx/mac80211/patches/qca/533-ath12k-WMI-fixes.patch b/feeds/ipq95xx/mac80211/patches/qca/533-ath12k-WMI-fixes.patch index db8062d0c..ae61fbdc4 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/533-ath12k-WMI-fixes.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/533-ath12k-WMI-fixes.patch @@ -5,39 +5,21 @@ Subject: [PATCH] ath12k: WMI fixes Signed-off-by: Ramya Gnanasekar -diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c -index 1e7e73f..c6bf16a 100644 ---- a/drivers/net/wireless/ath/ath12k/dp.c -+++ b/drivers/net/wireless/ath/ath12k/dp.c -@@ -1378,8 +1378,6 @@ static int ath12k_dp_cc_init(struct ath12k_base *ab) - int i, ret = 0; - u32 cmem_base; - -- return 0; -- - INIT_LIST_HEAD(&dp->rx_desc_free_list); - INIT_LIST_HEAD(&dp->rx_desc_used_list); - spin_lock_init(&dp->rx_desc_lock); -diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c -index 01fc36a..6165e6f 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -4065,6 +4065,7 @@ int ath12k_dp_rx_htt_setup(struct ath12k_base *ab) - ret); - return ret; +@@ -4101,6 +4101,7 @@ int ath12k_dp_rxdma_ring_sel_config_wcn7 + DP_RXDMA_REFILL_RING_SIZE, + &tlv_filter); } +#if 0 - ring_id = dp->rxdma_mon_buf_ring.refill_buf_ring.ring_id; - ret = ath12k_dp_tx_htt_srng_setup(ab, ring_id, -@@ -4083,6 +4084,7 @@ int ath12k_dp_rx_htt_setup(struct ath12k_base *ab) + return ret; + } +@@ -4119,6 +4120,7 @@ int ath12k_dp_rx_htt_setup(struct ath12k ret); return ret; } +#endif - ret = ath12k_dp_rxdma_ring_sel_config(ab); - if (ret) { --- -2.17.1 - + if (ab->hw_params->rx_mac_buf_ring) { + for (i = 0; i < ab->hw_params->num_rxmda_per_pdev; i++) { diff --git a/feeds/ipq95xx/mac80211/patches/qca/534-ath12k-Add-support-to-detect-MIC-failure.patch b/feeds/ipq95xx/mac80211/patches/qca/534-ath12k-Add-support-to-detect-MIC-failure.patch deleted file mode 100644 index da267909e..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/534-ath12k-Add-support-to-detect-MIC-failure.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 91a187df94ca793411afcd5ab51a40635dea9376 Mon Sep 17 00:00:00 2001 -From: Ramya Gnanasekar -Date: Wed, 2 Mar 2022 19:38:50 +0530 -Subject: [PATCH] ath12k: Add support to detect MIC failure - -In Beriliyum, crypto hw will set TKIP error and Decrypt error -when it detects MIC failure and ICV failure. In this case, RXDMA -will give higher priority to decrypt error and sets the error code -as decrypt error(3). Ath12k driver expects TKIP MIC error (4) in case -of mic failure and hence no action is taken against the STA which -injected the corrupted packet. - -To overcome the scenario, TKIP error bit set in msdu_end is checked -when decrypt or tkip error is reported by RXDMA and necessary action -is taken. - -Signed-off-by: Ramya Gnanasekar - ---- a/drivers/net/wireless/ath/ath12k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -3750,14 +3750,21 @@ static bool ath12k_dp_rx_h_rxdma_err(str - struct ieee80211_rx_status *status) - { - struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu); -+ struct hal_rx_desc *rx_desc = (struct hal_rx_desc*)msdu->data; - bool drop = false; -+ u32 err_bitmap; - - ar->ab->soc_stats.rxdma_error[rxcb->err_code]++; - - switch (rxcb->err_code) { -+ case HAL_REO_ENTR_RING_RXDMA_ECODE_DECRYPT_ERR: - case HAL_REO_ENTR_RING_RXDMA_ECODE_TKIP_MIC_ERR: -- ath12k_dp_rx_h_tkip_mic_err(ar, msdu, status); -- break; -+ err_bitmap = ath12k_dp_rx_h_mpdu_err(rx_desc); -+ if (err_bitmap & DP_RX_MPDU_ERR_TKIP_MIC) { -+ ath12k_dp_rx_h_tkip_mic_err(ar, msdu, status); -+ break; -+ } -+ fallthrough; - default: - /* TODO: Review other rxdma error code to check if anything is - * worth reporting to mac80211 diff --git a/feeds/ipq95xx/mac80211/patches/qca/535-ath12k-fix-typecast-error-for-32bit.patch b/feeds/ipq95xx/mac80211/patches/qca/535-ath12k-fix-typecast-error-for-32bit.patch index a22191378..3c02890f8 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/535-ath12k-fix-typecast-error-for-32bit.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/535-ath12k-fix-typecast-error-for-32bit.patch @@ -14,11 +14,9 @@ drivers/net/wireless/ath/ath12k/dp_tx.c | 2 +- drivers/net/wireless/ath/ath12k/hal_rx.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h -index 1b54861..50a4acc 100644 --- a/drivers/net/wireless/ath/ath12k/dp.h +++ b/drivers/net/wireless/ath/ath12k/dp.h -@@ -1921,7 +1921,7 @@ enum vdev_stats_offload_timer_duration { +@@ -1883,7 +1883,7 @@ enum vdev_stats_offload_timer_duration { #define HTT_H2T_VDEV_TXRX_HDR_INTERVAL GENMASK(24, 17) #define HTT_H2T_VDEV_TXRX_HDR_RESET_STATS BIT(31) #define HTT_H2T_VDEV_TXRX_LO_BITMASK GENMASK(31, 0) @@ -27,54 +25,3 @@ index 1b54861..50a4acc 100644 struct htt_h2t_msg_type_vdev_txrx_stats_req { u32 hdr; -diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c -index 6165e6f..0c4576c 100644 ---- a/drivers/net/wireless/ath/ath12k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -2772,7 +2772,7 @@ try_again: - mac_id = FIELD_GET(HAL_REO_DEST_RING_INFO0_SRC_LINK_ID, - desc.info0); - -- desc_info = (struct ath12k_rx_desc_info *)((u64)desc.buf_va_hi << 32 | -+ desc_info = (struct ath12k_rx_desc_info *)(uintptr_t)((u64)desc.buf_va_hi << 32 | - desc.buf_va_lo); - - /* retry manual desc retrieval */ -@@ -3447,7 +3447,7 @@ ath12k_dp_process_rx_err_buf(struct ath12k *ar, u32 *ring_desc, - /* TODO check if hw cc will not happen for exception, in that case - * always perform manual conversion - */ -- desc_info = (struct ath12k_rx_desc_info *)((u64)desc.buf_va_hi << 32 | -+ desc_info = (struct ath12k_rx_desc_info *)(uintptr_t)((u64)desc.buf_va_hi << 32 | - desc.buf_va_lo); - - /* retry manual desc retrieval */ -diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c -index 250d675..eb79353 100644 ---- a/drivers/net/wireless/ath/ath12k/dp_tx.c -+++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -615,7 +615,7 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id) - - if (FIELD_GET(HAL_WBM_COMPL_TX_INFO0_CC_DONE, tx_status->info0)) { - /* HW done cookie conversion */ -- tx_desc = (struct ath12k_tx_desc_info *) -+ tx_desc = (struct ath12k_tx_desc_info *)(uintptr_t) - (tx_status->buf_va_lo | - (((u64)tx_status->buf_va_hi) << 32)); - } else { -diff --git a/drivers/net/wireless/ath/ath12k/hal_rx.c b/drivers/net/wireless/ath/ath12k/hal_rx.c -index f8d750f..fc11b5e 100644 ---- a/drivers/net/wireless/ath/ath12k/hal_rx.c -+++ b/drivers/net/wireless/ath/ath12k/hal_rx.c -@@ -403,7 +403,7 @@ int ath12k_hal_wbm_desc_parse_err(struct ath12k_base *ab, void *desc, - wbm_cc_desc->info1); - - rel_info->rx_desc = -- (struct ath12k_rx_desc_info *)((u64)wbm_cc_desc->buf_va_hi << 32 | -+ (struct ath12k_rx_desc_info *)(uintptr_t)((u64)wbm_cc_desc->buf_va_hi << 32 | - wbm_cc_desc->buf_va_lo); - } - --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/536-ath12k-Fixed-8VAP-issue.patch b/feeds/ipq95xx/mac80211/patches/qca/536-ath12k-Fixed-8VAP-issue.patch index 1362d0b5d..65d95f3cf 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/536-ath12k-Fixed-8VAP-issue.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/536-ath12k-Fixed-8VAP-issue.patch @@ -14,11 +14,9 @@ Signed-off-by: Aishwarya R drivers/net/wireless/ath/ath12k/wmi.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) -diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index b2797ca..e99fe57 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -5204,7 +5204,7 @@ ath12k_mac_get_vdev_stats_id(struct ath12k_vif *arvif) +@@ -5274,7 +5274,7 @@ ath12k_mac_get_vdev_stats_id(struct ath1 do { if (ab->free_vdev_stats_id_map & (1LL << vdev_stats_id)) { vdev_stats_id++; @@ -27,20 +25,15 @@ index b2797ca..e99fe57 100644 vdev_stats_id = ATH12K_INVAL_VDEV_STATS_ID; break; } -diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h -index f0acc52..a149150 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -2545,6 +2545,9 @@ struct wmi_vdev_create_cmd { +@@ -2540,6 +2540,9 @@ struct wmi_vdev_create_cmd { struct wmi_mac_addr vdev_macaddr; - u32 num_cfg_txrx_streams; - u32 pdev_id; -+ u32 flags; -+ u32 vdevid_trans; -+ u32 vdev_stats_id_valid; - u32 vdev_stats_id; + __le32 num_cfg_txrx_streams; + __le32 pdev_id; ++ __le32 flags; ++ __le32 vdevid_trans; ++ __le32 vdev_stats_id_valid; + __le32 vdev_stats_id; } __packed; --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/537-ath12k-fix-monitor-ring-config.patch b/feeds/ipq95xx/mac80211/patches/qca/537-ath12k-fix-monitor-ring-config.patch deleted file mode 100644 index 33ec0ba23..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/537-ath12k-fix-monitor-ring-config.patch +++ /dev/null @@ -1,49 +0,0 @@ -From: Karthikeyan Periyasamy -Date: Tue, 1 Mar 2022 15:04:31 +0530 -Subject: [PATCH] ath12k: fix QMI service arrive issue - -QMI new server arrive callback not happen from the second insmod -of ath12k driver. It is due to unintentional register write happen -on PCIE_PCIE_CHDBOFF when configuring monitor ring setup. Since -mac type is not selected for monitor ring, it leads to UMAC ring -setup procedure for PMAC monitor rings. So assign the correct -mac type for monitor ring to avoid unintentional register write, -to resolve this issue. - -Signed-off-by: Karthikeyan Periyasamy ---- - ---- a/drivers/net/wireless/ath/ath12k/hal.c -+++ b/drivers/net/wireless/ath/ath12k/hal.c -@@ -181,6 +181,7 @@ static const struct hal_srng_config hw_s - .start_ring_id = HAL_SRNG_SW2RXMON_BUF0, - .max_rings = 1, - .entry_size = sizeof(struct hal_mon_buf_ring) >> 2, -+ .mac_type = ATH12K_HAL_SRNG_PMAC, - .ring_dir = HAL_SRNG_DIR_SRC, - .max_size = HAL_RXDMA_RING_MAX_SIZE_BE, - }, -@@ -188,6 +189,7 @@ static const struct hal_srng_config hw_s - .start_ring_id = HAL_SRNG_SW2TXMON_BUF0, - .max_rings = 1, - .entry_size = sizeof(struct hal_mon_buf_ring) >> 2, -+ .mac_type = ATH12K_HAL_SRNG_PMAC, - .ring_dir = HAL_SRNG_DIR_SRC, - .max_size = HAL_RXDMA_RING_MAX_SIZE_BE, - }, -@@ -195,6 +197,7 @@ static const struct hal_srng_config hw_s - .start_ring_id = HAL_SRNG_RING_ID_WMAC1_RXMON2SW0, - .max_rings = 1, - .entry_size = sizeof(struct hal_mon_dest_desc) >> 2, -+ .mac_type = ATH12K_HAL_SRNG_PMAC, - .ring_dir = HAL_SRNG_DIR_DST, - .max_size = HAL_RXDMA_RING_MAX_SIZE_BE, - }, -@@ -202,6 +205,7 @@ static const struct hal_srng_config hw_s - .start_ring_id = HAL_SRNG_RING_ID_WMAC1_TXMON2SW0_BUF0, - .max_rings = 1, - .entry_size = sizeof(struct hal_mon_dest_desc) >> 2, -+ .mac_type = ATH12K_HAL_SRNG_PMAC, - .ring_dir = HAL_SRNG_DIR_DST, - .max_size = HAL_RXDMA_RING_MAX_SIZE_BE, - } diff --git a/feeds/ipq95xx/mac80211/patches/qca/538-ath12k-send-beacon-template-after-vdev-restart-durin.patch b/feeds/ipq95xx/mac80211/patches/qca/538-ath12k-send-beacon-template-after-vdev-restart-durin.patch deleted file mode 100644 index 5c5dffd29..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/538-ath12k-send-beacon-template-after-vdev-restart-durin.patch +++ /dev/null @@ -1,43 +0,0 @@ -From a0a5dcf463d100742ed689b5f56cce5127f03e34 Mon Sep 17 00:00:00 2001 -From: Ramya Gnanasekar -Date: Tue, 8 Mar 2022 22:45:51 +0530 -Subject: [PATCH] ath12k: send beacon template after vdev restart during CSA - -If beacon template is sent before vdev is active, it will trigger -firmware assert since firmware expects it only when vdev is active. - -Hence, Changed the sequence in ath12k as expected by firmware. - -Signed-off-by: Ramya Gnanasekar - -diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index b2797ca..b380b37 100644 ---- a/drivers/net/wireless/ath/ath12k/mac.c -+++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -6033,11 +6033,6 @@ ath12k_mac_update_vif_chan(struct ath12k *ar, - if (WARN_ON(!arvif->is_up)) - continue; - -- ret = ath12k_mac_setup_bcn_tmpl(arvif); -- if (ret) -- ath12k_warn(ab, "failed to update bcn tmpl during csa: %d\n", -- ret); -- - ret = ath12k_mac_vdev_restart(arvif, &vifs[i].new_ctx->def); - if (ret) { - ath12k_warn(ab, "failed to restart vdev %d: %d\n", -@@ -6045,6 +6040,11 @@ ath12k_mac_update_vif_chan(struct ath12k *ar, - continue; - } - -+ ret = ath12k_mac_setup_bcn_tmpl(arvif); -+ if (ret) -+ ath12k_warn(ab, "failed to update bcn tmpl during csa: %d\n", -+ ret); -+ - ret = ath12k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid, - arvif->bssid); - if (ret) { --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/540-ath12k-Parse-memory-region-from-reserved-memory.patch b/feeds/ipq95xx/mac80211/patches/qca/540-ath12k-Parse-memory-region-from-reserved-memory.patch deleted file mode 100644 index 9d8663a9a..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/540-ath12k-Parse-memory-region-from-reserved-memory.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 1986d4ccffabad84ffa4ea2d2fcbd21423a2f24f Mon Sep 17 00:00:00 2001 -From: Balamurugan Selvarajan -Date: Tue, 8 Mar 2022 18:49:10 +0530 -Subject: [PATCH] ath12k: Parse memory-region from reserved memory - -parse memory from reserved region. In this case -host need not allocate memory and the memory is -fetched by parsing memory-region property. - -Signed-off-by: Balamurugan Selvarajan ---- - drivers/net/wireless/ath/ath12k/pci.c | 2 +- - drivers/net/wireless/ath/ath12k/qmi.c | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c -index 31bbcb8..11018fa 100644 ---- a/drivers/net/wireless/ath/ath12k/pci.c -+++ b/drivers/net/wireless/ath/ath12k/pci.c -@@ -1303,7 +1303,7 @@ static int ath12k_pci_probe(struct pci_dev *pdev, - * from DT. If memory is reserved from DT for FW, ath11k driver need not - * allocate memory. - */ -- if (!of_property_read_u32(ab->dev->of_node, "ath-memory-region", &addr)) -+ if (!of_property_read_u32(ab->dev->of_node, "memory-region", &addr)) - ab->bus_params.fixed_mem_region = true; - - ret = ath12k_pci_claim(ab_pci, pdev); -diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c -index 250a298..b92fa98 100644 ---- a/drivers/net/wireless/ath/ath12k/qmi.c -+++ b/drivers/net/wireless/ath/ath12k/qmi.c -@@ -1951,7 +1951,7 @@ static int ath12k_qmi_assign_target_mem_chunk(struct ath12k_base *ab) - for (i = 0, idx = 0; i < ab->qmi.mem_seg_count; i++) { - switch (ab->qmi.target_mem[i].type) { - case HOST_DDR_REGION_TYPE: -- hremote_node = of_parse_phandle(dev->of_node, "ath-memory-region", 0); -+ hremote_node = of_parse_phandle(dev->of_node, "memory-region", 0); - if (!hremote_node) { - ath12k_warn(ab, "qmi fail to get hremote_node\n"); - return ret; --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/541-mac80211_hwsim-check-TX-and-STA-bandwidth.patch b/feeds/ipq95xx/mac80211/patches/qca/541-mac80211_hwsim-check-TX-and-STA-bandwidth.patch deleted file mode 100644 index 72efd5962..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/541-mac80211_hwsim-check-TX-and-STA-bandwidth.patch +++ /dev/null @@ -1,197 +0,0 @@ -From a797ffd077c0db1a5e3581b3b6c66ee8e38ea6b7 Mon Sep 17 00:00:00 2001 -From: Johannes Berg -Date: Mon, 14 Feb 2022 17:29:48 +0100 -Subject: [PATCH 01/19] mac80211_hwsim: check TX and STA bandwidth - -Add checks to hwsim to validate that neither TX nor any -station's configured bandwidth can exceed the channel -(context) configuration previously requested. - -Signed-off-by: Johannes Berg ---- - drivers/net/wireless/mac80211_hwsim.c | 101 +++++++++++++++++++++++++- - 1 file changed, 98 insertions(+), 3 deletions(-) - -diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c -index 842084fabfcc..78e6654297ce 100644 ---- a/drivers/net/wireless/mac80211_hwsim.c -+++ b/drivers/net/wireless/mac80211_hwsim.c -@@ -652,6 +652,7 @@ struct mac80211_hwsim_data { - ARRAY_SIZE(hwsim_channels_6ghz)]; - - struct ieee80211_channel *channel; -+ enum nl80211_chan_width bw; - u64 beacon_int /* beacon interval in us */; - unsigned int rx_filter; - bool started, idle, scanning; -@@ -803,6 +804,38 @@ extern int hwsim_tx_virtio(struct mac80211_hwsim_data *data, - #define hwsim_virtio_enabled false - #endif - -+static int hwsim_get_chanwidth(enum nl80211_chan_width bw) -+{ -+ switch (bw) { -+ case NL80211_CHAN_WIDTH_20_NOHT: -+ case NL80211_CHAN_WIDTH_20: -+ return 20; -+ case NL80211_CHAN_WIDTH_40: -+ return 40; -+ case NL80211_CHAN_WIDTH_80: -+ return 80; -+ case NL80211_CHAN_WIDTH_80P80: -+ case NL80211_CHAN_WIDTH_160: -+ return 160; -+ case NL80211_CHAN_WIDTH_5: -+ return 5; -+ case NL80211_CHAN_WIDTH_10: -+ return 10; -+ case NL80211_CHAN_WIDTH_1: -+ return 1; -+ case NL80211_CHAN_WIDTH_2: -+ return 2; -+ case NL80211_CHAN_WIDTH_4: -+ return 4; -+ case NL80211_CHAN_WIDTH_8: -+ return 8; -+ case NL80211_CHAN_WIDTH_16: -+ return 16; -+ } -+ -+ return INT_MAX; -+} -+ - static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, - struct sk_buff *skb, - struct ieee80211_channel *chan); -@@ -1595,7 +1628,8 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, - struct ieee80211_chanctx_conf *chanctx_conf; - struct ieee80211_channel *channel; - bool ack; -- u32 _portid; -+ enum nl80211_chan_width confbw = NL80211_CHAN_WIDTH_20_NOHT; -+ u32 _portid, i; - - if (WARN_ON(skb->len < 10)) { - /* Should not happen; just a sanity check for addr1 use */ -@@ -1605,14 +1639,17 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, - - if (!data->use_chanctx) { - channel = data->channel; -+ confbw = data->bw; - } else if (txi->hw_queue == 4) { - channel = data->tmp_chan; - } else { - chanctx_conf = rcu_dereference(txi->control.vif->chanctx_conf); -- if (chanctx_conf) -+ if (chanctx_conf) { - channel = chanctx_conf->def.chan; -- else -+ confbw = chanctx_conf->def.width; -+ } else { - channel = NULL; -+ } - } - - if (WARN(!channel, "TX w/o channel - queue = %d\n", txi->hw_queue)) { -@@ -1636,6 +1673,25 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, - txi->control.rates, - ARRAY_SIZE(txi->control.rates)); - -+ for (i = 0; i < ARRAY_SIZE(txi->control.rates); i++) { -+ u16 rflags = txi->control.rates[i].flags; -+ /* initialize to data->bw for 5/10 MHz handling */ -+ enum nl80211_chan_width bw = data->bw; -+ -+ if (txi->control.rates[i].idx == -1) -+ break; -+ -+ if (rflags & IEEE80211_TX_RC_40_MHZ_WIDTH) -+ bw = NL80211_CHAN_WIDTH_40; -+ else if (rflags & IEEE80211_TX_RC_80_MHZ_WIDTH) -+ bw = NL80211_CHAN_WIDTH_80; -+ else if (rflags & IEEE80211_TX_RC_160_MHZ_WIDTH) -+ bw = NL80211_CHAN_WIDTH_160; -+ -+ if (WARN_ON(hwsim_get_chanwidth(bw) > hwsim_get_chanwidth(confbw))) -+ return; -+ } -+ - if (skb->len >= 24 + 8 && - ieee80211_is_probe_resp(hdr->frame_control)) { - /* fake header transmission time */ -@@ -1935,6 +1991,7 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) - } - - data->channel = conf->chandef.chan; -+ data->bw = conf->chandef.width; - - for (idx = 0; idx < ARRAY_SIZE(data->survey_data); idx++) { - if (data->survey_data[idx].channel && -@@ -1946,6 +2003,7 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) - } - } else { - data->channel = conf->chandef.chan; -+ data->bw = conf->chandef.width; - } - mutex_unlock(&data->mutex); - -@@ -2077,12 +2135,48 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, - wiphy_dbg(hw->wiphy, " TX Power: %d dBm\n", info->txpower); - } - -+static void -+mac80211_hwsim_sta_rc_update(struct ieee80211_hw *hw, -+ struct ieee80211_vif *vif, -+ struct ieee80211_sta *sta, -+ u32 changed) -+{ -+ struct mac80211_hwsim_data *data = hw->priv; -+ u32 bw = U32_MAX; -+ enum nl80211_chan_width confbw = NL80211_CHAN_WIDTH_20_NOHT; -+ -+ switch (sta->bandwidth) { -+#define C(_bw) case IEEE80211_STA_RX_BW_##_bw: bw = _bw; break -+ C(20); -+ C(40); -+ C(80); -+ C(160); -+#undef C -+ } -+ -+ if (!data->use_chanctx) { -+ confbw = data->bw; -+ } else { -+ struct ieee80211_chanctx_conf *chanctx_conf = -+ rcu_dereference(vif->chanctx_conf); -+ -+ if (!WARN_ON(!chanctx_conf)) -+ confbw = chanctx_conf->def.width; -+ } -+ -+ WARN(bw > hwsim_get_chanwidth(confbw), -+ "intf %pM: bad STA %pM bandwidth %d MHz (%d) > channel config %d MHz (%d)\n", -+ vif->addr, sta->addr, bw, sta->bandwidth, -+ hwsim_get_chanwidth(data->bw), data->bw); -+} -+ - static int mac80211_hwsim_sta_add(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) - { - hwsim_check_magic(vif); - hwsim_set_sta_magic(sta); -+ mac80211_hwsim_sta_rc_update(hw, vif, sta, 0); - - return 0; - } -@@ -2649,6 +2743,7 @@ static int mac80211_hwsim_tx_last_beacon(struct ieee80211_hw *hw) - .sta_add = mac80211_hwsim_sta_add, \ - .sta_remove = mac80211_hwsim_sta_remove, \ - .sta_notify = mac80211_hwsim_sta_notify, \ -+ .sta_rc_update = mac80211_hwsim_sta_rc_update, \ - .set_tim = mac80211_hwsim_set_tim, \ - .conf_tx = mac80211_hwsim_conf_tx, \ - .get_survey = mac80211_hwsim_get_survey, \ --- -2.31.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/542-mac80211_hwsim-don-t-shadow-a-global-variable.patch b/feeds/ipq95xx/mac80211/patches/qca/542-mac80211_hwsim-don-t-shadow-a-global-variable.patch deleted file mode 100644 index 49c971069..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/542-mac80211_hwsim-don-t-shadow-a-global-variable.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 6f0463f20edb03d9f9a778e4d9ba84494f801007 Mon Sep 17 00:00:00 2001 -From: Johannes Berg -Date: Mon, 14 Feb 2022 17:29:49 +0100 -Subject: [PATCH 02/19] mac80211_hwsim: don't shadow a global variable - -The argument to hwsim_init_s1g_channels() shadows a global, -change that to be clearer. - -Signed-off-by: Johannes Berg ---- - drivers/net/wireless/mac80211_hwsim.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c -index 78e6654297ce..b24b60a67d7d 100644 ---- a/drivers/net/wireless/mac80211_hwsim.c -+++ b/drivers/net/wireless/mac80211_hwsim.c -@@ -475,16 +475,16 @@ static const struct ieee80211_sta_s1g_cap hwsim_s1g_cap = { - 0 }, - }; - --static void hwsim_init_s1g_channels(struct ieee80211_channel *channels) -+static void hwsim_init_s1g_channels(struct ieee80211_channel *chans) - { - int ch, freq; - - for (ch = 0; ch < NUM_S1G_CHANS_US; ch++) { - freq = 902000 + (ch + 1) * 500; -- channels[ch].band = NL80211_BAND_S1GHZ; -- channels[ch].center_freq = KHZ_TO_MHZ(freq); -- channels[ch].freq_offset = freq % 1000; -- channels[ch].hw_value = ch + 1; -+ chans[ch].band = NL80211_BAND_S1GHZ; -+ chans[ch].center_freq = KHZ_TO_MHZ(freq); -+ chans[ch].freq_offset = freq % 1000; -+ chans[ch].hw_value = ch + 1; - } - } - --- -2.31.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/543-mac80211_hwsim-Add-custom-regulatory-for-6GHz.patch b/feeds/ipq95xx/mac80211/patches/qca/543-mac80211_hwsim-Add-custom-regulatory-for-6GHz.patch deleted file mode 100644 index 9ffedf9a0..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/543-mac80211_hwsim-Add-custom-regulatory-for-6GHz.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0b181e63ce2d590e034c92e7e4f0f93ab134d613 Mon Sep 17 00:00:00 2001 -From: Ilan Peer -Date: Mon, 14 Feb 2022 17:29:50 +0100 -Subject: [PATCH 03/19] mac80211_hwsim: Add custom regulatory for 6GHz - -Add a custom regulatory domain for testing 6 GHz, including -320 MHz bandwidth. This can be used before the regulatory -databases are all updated etc. - -Signed-off-by: Ilan Peer -Signed-off-by: Johannes Berg ---- - drivers/net/wireless/mac80211_hwsim.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - -diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c -index b24b60a67d7d..2f262d59013f 100644 ---- a/drivers/net/wireless/mac80211_hwsim.c -+++ b/drivers/net/wireless/mac80211_hwsim.c -@@ -173,9 +173,23 @@ static const struct ieee80211_regdomain hwsim_world_regdom_custom_02 = { - } - }; - -+static const struct ieee80211_regdomain hwsim_world_regdom_custom_03 = { -+ .n_reg_rules = 6, -+ .alpha2 = "99", -+ .reg_rules = { -+ REG_RULE(2412 - 10, 2462 + 10, 40, 0, 20, 0), -+ REG_RULE(2484 - 10, 2484 + 10, 40, 0, 20, 0), -+ REG_RULE(5150 - 10, 5240 + 10, 40, 0, 30, 0), -+ REG_RULE(5745 - 10, 5825 + 10, 40, 0, 30, 0), -+ REG_RULE(5855 - 10, 5925 + 10, 40, 0, 33, 0), -+ REG_RULE(5955 - 10, 7125 + 10, 320, 0, 33, 0), -+ } -+}; -+ - static const struct ieee80211_regdomain *hwsim_world_regdom_custom[] = { - &hwsim_world_regdom_custom_01, - &hwsim_world_regdom_custom_02, -+ &hwsim_world_regdom_custom_03, - }; - - struct hwsim_vif_priv { --- -2.31.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/544-ieee80211-Add-EHT-802.11be-definitions.patch b/feeds/ipq95xx/mac80211/patches/qca/544-ieee80211-Add-EHT-802.11be-definitions.patch deleted file mode 100644 index f2c2fc972..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/544-ieee80211-Add-EHT-802.11be-definitions.patch +++ /dev/null @@ -1,354 +0,0 @@ -From 1922079905fa5bd8ee25a6130bee381891419198 Mon Sep 17 00:00:00 2001 -From: Ilan Peer -Date: Mon, 14 Feb 2022 17:29:51 +0100 -Subject: [PATCH 04/19] ieee80211: Add EHT (802.11be) definitions - -Based on Draft P802.11be_D1.4. - -Signed-off-by: Ilan Peer -Signed-off-by: Johannes Berg ---- - include/linux/ieee80211.h | 299 ++++++++++++++++++++++++++++++++++++++ - 1 file changed, 299 insertions(+) - -diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h -index ada431fa46d4..5077ec12120d 100644 ---- a/include/linux/ieee80211.h -+++ b/include/linux/ieee80211.h -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -1925,6 +1926,111 @@ struct ieee80211_mu_edca_param_set { - struct ieee80211_he_mu_edca_param_ac_rec ac_vo; - } __packed; - -+#define IEEE80211_EHT_MCS_NSS_RX 0x0f -+#define IEEE80211_EHT_MCS_NSS_TX 0xf0 -+ -+/** -+ * struct ieee80211_eht_mcs_nss_supp_20mhz_only - EHT 20MHz only station max -+ * supported NSS for per MCS. -+ * -+ * For each field below, bits 0 - 3 indicate the maximal number of spatial -+ * streams for Rx, and bits 4 - 7 indicate the maximal number of spatial streams -+ * for Tx. -+ * -+ * @rx_tx_mcs7_max_nss: indicates the maximum number of spatial streams -+ * supported for reception and the maximum number of spatial streams -+ * supported for transmission for MCS 0 - 7. -+ * @rx_tx_mcs9_max_nss: indicates the maximum number of spatial streams -+ * supported for reception and the maximum number of spatial streams -+ * supported for transmission for MCS 8 - 9. -+ * @rx_tx_mcs11_max_nss: indicates the maximum number of spatial streams -+ * supported for reception and the maximum number of spatial streams -+ * supported for transmission for MCS 10 - 11. -+ * @rx_tx_mcs13_max_nss: indicates the maximum number of spatial streams -+ * supported for reception and the maximum number of spatial streams -+ * supported for transmission for MCS 12 - 13. -+ */ -+struct ieee80211_eht_mcs_nss_supp_20mhz_only { -+ u8 rx_tx_mcs7_max_nss; -+ u8 rx_tx_mcs9_max_nss; -+ u8 rx_tx_mcs11_max_nss; -+ u8 rx_tx_mcs13_max_nss; -+}; -+ -+/** -+ * struct ieee80211_eht_mcs_nss_supp_bw - EHT max supported NSS per MCS (except -+ * 20MHz only stations). -+ * -+ * For each field below, bits 0 - 3 indicate the maximal number of spatial -+ * streams for Rx, and bits 4 - 7 indicate the maximal number of spatial streams -+ * for Tx. -+ * -+ * @rx_tx_mcs9_max_nss: indicates the maximum number of spatial streams -+ * supported for reception and the maximum number of spatial streams -+ * supported for transmission for MCS 0 - 9. -+ * @rx_tx_mcs11_max_nss: indicates the maximum number of spatial streams -+ * supported for reception and the maximum number of spatial streams -+ * supported for transmission for MCS 10 - 11. -+ * @rx_tx_mcs13_max_nss: indicates the maximum number of spatial streams -+ * supported for reception and the maximum number of spatial streams -+ * supported for transmission for MCS 12 - 13. -+ */ -+struct ieee80211_eht_mcs_nss_supp_bw { -+ u8 rx_tx_mcs9_max_nss; -+ u8 rx_tx_mcs11_max_nss; -+ u8 rx_tx_mcs13_max_nss; -+}; -+ -+/** -+ * struct ieee80211_eht_cap_elem_fixed - EHT capabilities fixed data -+ * -+ * This structure is the "EHT Capabilities element" fixed fields as -+ * described in P802.11be_D1.4 section 9.4.2.313. -+ * -+ * @mac_cap_info: MAC capabilities, see IEEE80211_EHT_MAC_CAP* -+ * @phy_cap_info: PHY capabilities, see IEEE80211_EHT_PHY_CAP* -+ */ -+struct ieee80211_eht_cap_elem_fixed { -+ u8 mac_cap_info[2]; -+ u8 phy_cap_info[9]; -+} __packed; -+ -+/** -+ * struct ieee80211_eht_cap_elem - EHT capabilities element -+ * @fixed: fixed parts, see &ieee80211_eht_cap_elem_fixed -+ * @optional: optional parts -+ */ -+struct ieee80211_eht_cap_elem { -+ struct ieee80211_eht_cap_elem_fixed fixed; -+ -+ /* -+ * Followed by: -+ * Supported EHT-MCS And NSS Set field: 4, 3, 6 or 9 octets. -+ * EHT PPE Thresholds field: variable length. -+ */ -+ u8 optional[]; -+} __packed; -+ -+/** -+ * struct ieee80211_eht_operation - eht operation element -+ * -+ * This structure is the "EHT Operation Element" fields as -+ * described in P802.11be_D1.4 section 9.4.2.311 -+ * -+ * FIXME: The spec is unclear how big the fields are, and doesn't -+ * indicate the "Disabled Subchannel Bitmap Present" in the -+ * structure (Figure 9-1002a) at all ... -+ */ -+struct ieee80211_eht_operation { -+ u8 chan_width; -+ u8 ccfs; -+ u8 present_bm; -+ -+ u8 disable_subchannel_bitmap[]; -+} __packed; -+ -+#define IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT 0x1 -+ - /* 802.11ac VHT Capabilities */ - #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000 - #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x00000001 -@@ -2129,6 +2235,8 @@ enum ieee80211_client_reg_power { - #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G 0x04 - #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G 0x08 - #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G 0x10 -+#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK_ALL 0x1e -+ - #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_2G 0x20 - #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G 0x40 - #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK 0xfe -@@ -2599,6 +2707,194 @@ ieee80211_he_spr_size(const u8 *he_spr_ie) - #define S1G_OPER_CH_WIDTH_PRIMARY_1MHZ BIT(0) - #define S1G_OPER_CH_WIDTH_OPER GENMASK(4, 1) - -+/* EHT MAC capabilities as defined in P802.11be_D1.4 section 9.4.2.313.2 */ -+#define IEEE80211_EHT_MAC_CAP0_NSEP_PRIO_ACCESS 0x01 -+#define IEEE80211_EHT_MAC_CAP0_OM_CONTROL 0x02 -+#define IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 0x04 -+#define IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2 0x08 -+#define IEEE80211_EHT_MAC_CAP0_RESTRICTED_TWT 0x10 -+#define IEEE80211_EHT_MAC_CAP0_SCS_TRAFFIC_DESC 0x20 -+#define IEEE80211_EHT_MAC_CAP0_MAX_AMPDU_LEN_MASK 0xc0 -+#define IEEE80211_EHT_MAC_CAP0_MAX_AMPDU_LEN_3895 0 -+#define IEEE80211_EHT_MAC_CAP0_MAX_AMPDU_LEN_7991 1 -+#define IEEE80211_EHT_MAC_CAP0_MAX_AMPDU_LEN_11454 2 -+ -+/* EHT PHY capabilities as defined in P802.11be_D1.4 section 9.4.2.313.3 */ -+#define IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ 0x02 -+#define IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ 0x04 -+#define IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI 0x08 -+#define IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO 0x10 -+#define IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER 0x20 -+#define IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE 0x40 -+ -+/* EHT beamformee number of spatial streams <= 80MHz is split */ -+#define IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK 0x80 -+#define IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK 0x03 -+ -+#define IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK 0x1c -+#define IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK 0xe0 -+ -+#define IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_80MHZ_MASK 0x07 -+#define IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_160MHZ_MASK 0x38 -+ -+/* EHT number of sounding dimensions for 320MHz is split */ -+#define IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_320MHZ_MASK 0xc0 -+#define IEEE80211_EHT_PHY_CAP3_SOUNDING_DIM_320MHZ_MASK 0x01 -+#define IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK 0x02 -+#define IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK 0x04 -+#define IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK 0x08 -+#define IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK 0x10 -+#define IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK 0x20 -+#define IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK 0x40 -+#define IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK 0x80 -+ -+#define IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO 0x01 -+#define IEEE80211_EHT_PHY_CAP4_PSR_SR_SUPP 0x02 -+#define IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP 0x04 -+#define IEEE80211_EHT_PHY_CAP4_EHT_MU_PPDU_4_EHT_LTF_08_GI 0x08 -+#define IEEE80211_EHT_PHY_CAP4_MAX_NC_MASK 0xf0 -+ -+#define IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK 0x01 -+#define IEEE80211_EHT_PHY_CAP5_TX_LESS_242_TONE_RU_SUPP 0x02 -+#define IEEE80211_EHT_PHY_CAP5_RX_LESS_242_TONE_RU_SUPP 0x04 -+#define IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT 0x08 -+#define IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK 0x30 -+#define IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_0US 0 -+#define IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_8US 1 -+#define IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_16US 2 -+#define IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_20US 3 -+ -+/* Maximum number of supported EHT LTF is split */ -+#define IEEE80211_EHT_PHY_CAP5_MAX_NUM_SUPP_EHT_LTF_MASK 0xc0 -+#define IEEE80211_EHT_PHY_CAP6_MAX_NUM_SUPP_EHT_LTF_MASK 0x07 -+ -+#define IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK 0x78 -+#define IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP 0x80 -+ -+#define IEEE80211_EHT_PHY_CAP7_20MHZ_STA_RX_NDP_WIDER_BW 0x01 -+#define IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ 0x02 -+#define IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ 0x04 -+#define IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_320MHZ 0x08 -+#define IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ 0x10 -+#define IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ 0x20 -+#define IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ 0x40 -+#define IEEE80211_EHT_PHY_CAP7_TB_SOUNDING_FDBK_RATE_LIMIT 0x80 -+ -+#define IEEE80211_EHT_PHY_CAP8_RX_1024QAM_WIDER_BW_DL_OFDMA 0x01 -+#define IEEE80211_EHT_PHY_CAP8_RX_4096QAM_WIDER_BW_DL_OFDMA 0x02 -+ -+/* -+ * EHT operation channel width as defined in P802.11be_D1.4 section 9.4.2.311 -+ */ -+#define IEEE80211_EHT_OPER_CHAN_WIDTH 0x7 -+#define IEEE80211_EHT_OPER_CHAN_WIDTH_20MHZ 0 -+#define IEEE80211_EHT_OPER_CHAN_WIDTH_40MHZ 1 -+#define IEEE80211_EHT_OPER_CHAN_WIDTH_80MHZ 2 -+#define IEEE80211_EHT_OPER_CHAN_WIDTH_160MHZ 3 -+#define IEEE80211_EHT_OPER_CHAN_WIDTH_320MHZ 4 -+ -+/* Calculate 802.11be EHT capabilities IE Tx/Rx EHT MCS NSS Support Field size */ -+static inline u8 -+ieee80211_eht_mcs_nss_size(const struct ieee80211_he_cap_elem *he_cap, -+ const struct ieee80211_eht_cap_elem_fixed *eht_cap) -+{ -+ u8 count = 0; -+ -+ /* on 2.4 GHz, if it supports 40 MHz, the result is 3 */ -+ if (he_cap->phy_cap_info[0] & -+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G) -+ return 3; -+ -+ /* on 2.4 GHz, these three bits are reserved, so should be 0 */ -+ if (he_cap->phy_cap_info[0] & -+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G) -+ count += 3; -+ -+ if (he_cap->phy_cap_info[0] & -+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G) -+ count += 3; -+ -+ if (eht_cap->phy_cap_info[0] & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ) -+ count += 3; -+ -+ return count ? count : 4; -+} -+ -+/* 802.11be EHT PPE Thresholds */ -+#define IEEE80211_EHT_PPE_THRES_NSS_POS 0 -+#define IEEE80211_EHT_PPE_THRES_NSS_MASK 0xf -+#define IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK 0x1f0 -+#define IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE 3 -+#define IEEE80211_EHT_PPE_THRES_INFO_HEADER_SIZE 9 -+ -+/* -+ * Calculate 802.11be EHT capabilities IE EHT field size -+ */ -+static inline u8 -+ieee80211_eht_ppe_size(u16 ppe_thres_hdr, const u8 *phy_cap_info) -+{ -+ u32 n; -+ -+ if (!(phy_cap_info[5] & -+ IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT)) -+ return 0; -+ -+ n = hweight16(ppe_thres_hdr & -+ IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK); -+ n *= 1 + u16_get_bits(ppe_thres_hdr, IEEE80211_EHT_PPE_THRES_NSS_MASK); -+ -+ /* -+ * Each pair is 6 bits, and we need to add the 9 "header" bits to the -+ * total size. -+ */ -+ n = n * IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE * 2 + -+ IEEE80211_EHT_PPE_THRES_INFO_HEADER_SIZE; -+ return DIV_ROUND_UP(n, 8); -+} -+ -+static inline bool -+ieee80211_eht_capa_size_ok(const u8 *he_capa, const u8 *data, u8 len) -+{ -+ const struct ieee80211_eht_cap_elem_fixed *elem = (const void *)data; -+ u8 needed = sizeof(struct ieee80211_eht_cap_elem_fixed); -+ -+ if (len < needed || !he_capa) -+ return false; -+ -+ needed += ieee80211_eht_mcs_nss_size((const void *)he_capa, -+ (const void *)data); -+ if (len < needed) -+ return false; -+ -+ if (elem->phy_cap_info[5] & -+ IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT) { -+ u16 ppe_thres_hdr; -+ -+ if (len < needed + sizeof(ppe_thres_hdr)) -+ return false; -+ -+ ppe_thres_hdr = get_unaligned_le16(data + needed); -+ needed += ieee80211_eht_ppe_size(ppe_thres_hdr, -+ elem->phy_cap_info); -+ } -+ -+ return len >= needed; -+} -+ -+static inline bool -+ieee80211_eht_oper_size_ok(const u8 *data, u8 len) -+{ -+ const struct ieee80211_eht_operation *elem = (const void *)data; -+ u8 needed = sizeof(*elem); -+ -+ if (len < needed) -+ return false; -+ -+ if (elem->present_bm & IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT) -+ needed += 2; -+ -+ return len >= needed; -+} - - #define LISTEN_INT_USF GENMASK(15, 14) - #define LISTEN_INT_UI GENMASK(13, 0) -@@ -3054,6 +3350,9 @@ enum ieee80211_eid_ext { - WLAN_EID_EXT_SHORT_SSID_LIST = 58, - WLAN_EID_EXT_HE_6GHZ_CAPA = 59, - WLAN_EID_EXT_UL_MU_POWER_CAPA = 60, -+ WLAN_EID_EXT_EHT_OPERATION = 106, -+ WLAN_EID_EXT_EHT_MULTI_LINK = 107, -+ WLAN_EID_EXT_EHT_CAPABILITY = 108, - }; - - /* Action category code */ --- -2.31.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/545-ath12k-11be-mumimo-and-ofdma-stats-support.patch b/feeds/ipq95xx/mac80211/patches/qca/545-ath12k-11be-mumimo-and-ofdma-stats-support.patch index 675955718..d25608925 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/545-ath12k-11be-mumimo-and-ofdma-stats-support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/545-ath12k-11be-mumimo-and-ofdma-stats-support.patch @@ -28,11 +28,9 @@ Signed-off-by: Balamurugan Mahalingam drivers/net/wireless/ath/ath12k/testmode_i.h | 2 +- 5 files changed, 1212 insertions(+), 9 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h -index cb958c6..3bfd8f1 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h -@@ -467,7 +467,8 @@ struct ath12k_fw_stats { +@@ -465,7 +465,8 @@ struct ath12k_fw_stats { }; struct ath12k_dbg_htt_stats { @@ -42,8 +40,6 @@ index cb958c6..3bfd8f1 100644 u8 reset; struct debug_htt_stats_req *stats_req; /* protects shared stats req buffer */ -diff --git a/drivers/net/wireless/ath/ath12k/debugfs.h b/drivers/net/wireless/ath/ath12k/debugfs.h -index 62e0e40..8c31328 100644 --- a/drivers/net/wireless/ath/ath12k/debugfs.h +++ b/drivers/net/wireless/ath/ath12k/debugfs.h @@ -39,6 +39,14 @@ enum ath12k_dbg_htt_ext_stats_type { @@ -73,11 +69,9 @@ index 62e0e40..8c31328 100644 u8 peer_addr[ETH_ALEN]; struct completion cmpln; u32 buf_len; -diff --git a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c -index bea7184..6319c00 100644 --- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c +++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c -@@ -3896,6 +3896,758 @@ static inline void htt_print_backpressure_stats_tlv_v(const u32 *tag_buf, +@@ -3896,6 +3896,758 @@ static inline void htt_print_backpressur } } @@ -836,7 +830,7 @@ index bea7184..6319c00 100644 static int ath12k_dbg_htt_ext_stats_parse(struct ath12k_base *ab, u16 tag, u16 len, const void *tag_buf, void *user_data) -@@ -4247,6 +4999,50 @@ static int ath12k_dbg_htt_ext_stats_parse(struct ath12k_base *ab, +@@ -4247,6 +4999,50 @@ static int ath12k_dbg_htt_ext_stats_pars case HTT_STATS_RING_BACKPRESSURE_STATS_TAG: htt_print_backpressure_stats_tlv_v(tag_buf, user_data); break; @@ -887,7 +881,7 @@ index bea7184..6319c00 100644 default: break; } -@@ -4324,12 +5120,23 @@ static ssize_t ath12k_write_htt_stats_type(struct file *file, +@@ -4324,12 +5120,23 @@ static ssize_t ath12k_write_htt_stats_ty size_t count, loff_t *ppos) { struct ath12k *ar = file->private_data; @@ -916,7 +910,7 @@ index bea7184..6319c00 100644 if (type >= ATH12K_DBG_HTT_NUM_EXT_STATS) return -E2BIG; -@@ -4339,9 +5146,12 @@ static ssize_t ath12k_write_htt_stats_type(struct file *file, +@@ -4339,9 +5146,12 @@ static ssize_t ath12k_write_htt_stats_ty return -EPERM; ar->debug.htt_stats.type = type; @@ -930,7 +924,7 @@ index bea7184..6319c00 100644 return ret; } -@@ -4425,6 +5235,12 @@ int ath12k_debugfs_htt_stats_req(struct ath12k *ar) +@@ -4425,6 +5235,12 @@ int ath12k_debugfs_htt_stats_req(struct ath12k_warn(ar->ab, "failed to set htt stats cfg params: %d\n", ret); return ret; } @@ -943,7 +937,7 @@ index bea7184..6319c00 100644 ret = ath12k_dp_tx_htt_h2t_ext_stats_req(ar, type, &cfg_params, cookie); if (ret) { -@@ -4476,6 +5292,14 @@ static int ath12k_open_htt_stats(struct inode *inode, struct file *file) +@@ -4476,6 +5292,14 @@ static int ath12k_open_htt_stats(struct ar->debug.htt_stats.stats_req = stats_req; stats_req->type = type; @@ -958,8 +952,6 @@ index bea7184..6319c00 100644 ret = ath12k_debugfs_htt_stats_req(ar); if (ret < 0) -diff --git a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h -index 2eb1d3e..c6d8ea5 100644 --- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h +++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h @@ -103,6 +103,20 @@ enum htt_tlv_tag_t { @@ -1373,8 +1365,6 @@ index 2eb1d3e..c6d8ea5 100644 #ifdef CPTCFG_ATH12K_DEBUGFS void ath12k_debugfs_htt_stats_init(struct ath12k *ar); -diff --git a/drivers/net/wireless/ath/ath12k/testmode_i.h b/drivers/net/wireless/ath/ath12k/testmode_i.h -index f4fe2fe..da64726 100644 --- a/drivers/net/wireless/ath/ath12k/testmode_i.h +++ b/drivers/net/wireless/ath/ath12k/testmode_i.h @@ -47,5 +47,5 @@ enum ath12k_tm_cmd { @@ -1384,6 +1374,3 @@ index f4fe2fe..da64726 100644 - ATH12K_TM_CMD_WMI = 1, + ATH12K_TM_CMD_WMI = 3, }; --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/546-ieee80211-add-EHT-1K-aggregation-definitions.patch b/feeds/ipq95xx/mac80211/patches/qca/546-ieee80211-add-EHT-1K-aggregation-definitions.patch deleted file mode 100644 index 4388df4a7..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/546-ieee80211-add-EHT-1K-aggregation-definitions.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 7dec538a9ba30f270998abc5bb1005552bfb9272 Mon Sep 17 00:00:00 2001 -From: Mordechay Goodstein -Date: Mon, 14 Feb 2022 17:29:52 +0100 -Subject: [PATCH 05/19] ieee80211: add EHT 1K aggregation definitions - -We add the fields for parsing extended ADDBA request/respond, -and new max 1K aggregation for limit ADDBA request/respond. - -Adjust drivers to use the proper macro, IEEE80211_MAX_AMPDU_BUF -> -IEEE80211_MAX_AMPDU_BUF_HE. - -Signed-off-by: Mordechay Goodstein -Signed-off-by: Johannes Berg ---- - drivers/net/wireless/ath/ath11k/mac.c | 2 +- - include/linux/ieee80211.h | 6 +++++- - net/mac80211/agg-rx.c | 2 +- - 3 files changed, 7 insertions(+), 3 deletions(-) - -diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c -index 9f780f8557cc..e9ba0673cd51 100644 ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -8448,7 +8448,7 @@ static int __ath11k_mac_register(struct ath11k *ar) - ar->hw->queues = ATH11K_HW_MAX_QUEUES; - ar->hw->wiphy->tx_queue_len = ATH11K_QUEUE_LEN; - ar->hw->offchannel_tx_hw_queue = ATH11K_HW_MAX_QUEUES - 1; -- ar->hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; -+ ar->hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE; - - ar->hw->vif_data_size = sizeof(struct ath11k_vif); - ar->hw->sta_data_size = sizeof(struct ath11k_sta); -diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h -index 5077ec12120d..27f94d531961 100644 ---- a/include/linux/ieee80211.h -+++ b/include/linux/ieee80211.h -@@ -1024,6 +1024,8 @@ struct ieee80211_tpc_report_ie { - #define IEEE80211_ADDBA_EXT_FRAG_LEVEL_MASK GENMASK(2, 1) - #define IEEE80211_ADDBA_EXT_FRAG_LEVEL_SHIFT 1 - #define IEEE80211_ADDBA_EXT_NO_FRAG BIT(0) -+#define IEEE80211_ADDBA_EXT_BUF_SIZE_MASK GENMASK(7, 5) -+#define IEEE80211_ADDBA_EXT_BUF_SIZE_SHIFT 10 - - struct ieee80211_addba_ext_ie { - u8 data; -@@ -1698,10 +1700,12 @@ struct ieee80211_ht_operation { - * A-MPDU buffer sizes - * According to HT size varies from 8 to 64 frames - * HE adds the ability to have up to 256 frames. -+ * EHT adds the ability to have up to 1K frames. - */ - #define IEEE80211_MIN_AMPDU_BUF 0x8 - #define IEEE80211_MAX_AMPDU_BUF_HT 0x40 --#define IEEE80211_MAX_AMPDU_BUF 0x100 -+#define IEEE80211_MAX_AMPDU_BUF_HE 0x100 -+#define IEEE80211_MAX_AMPDU_BUF_EHT 0x400 - - - /* Spatial Multiplexing Power Save Modes (for capability) */ -diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c -index 7d2925bb966e..0d2bab9d351c 100644 ---- a/net/mac80211/agg-rx.c -+++ b/net/mac80211/agg-rx.c -@@ -310,7 +310,7 @@ void ___ieee80211_start_rx_ba_session(struct sta_info *sta, - } - - if (sta->sta.he_cap.has_he) -- max_buf_size = IEEE80211_MAX_AMPDU_BUF; -+ max_buf_size = IEEE80211_MAX_AMPDU_BUF_HE; - else - max_buf_size = IEEE80211_MAX_AMPDU_BUF_HT; - --- -2.31.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/547-cfg80211-Add-data-structures-to-capture-EHT-capabili.patch b/feeds/ipq95xx/mac80211/patches/qca/547-cfg80211-Add-data-structures-to-capture-EHT-capabili.patch deleted file mode 100644 index a5c781635..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/547-cfg80211-Add-data-structures-to-capture-EHT-capabili.patch +++ /dev/null @@ -1,182 +0,0 @@ -From a3d358fa5d8f5e4a228ef9bb726ae433305ceae9 Mon Sep 17 00:00:00 2001 -From: Ilan Peer -Date: Mon, 14 Feb 2022 17:29:53 +0100 -Subject: [PATCH 06/19] cfg80211: Add data structures to capture EHT - capabilities - -And advertise EHT capabilities to user space when supported. - -Signed-off-by: Ilan Peer -Signed-off-by: Johannes Berg ---- - include/net/cfg80211.h | 63 ++++++++++++++++++++++++++++++++++++ - include/uapi/linux/nl80211.h | 12 +++++++ - net/wireless/nl80211.c | 27 ++++++++++++++++ - 3 files changed, 102 insertions(+) - -diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h -index 76faa9fcf043..e16e9236401c 100644 ---- a/include/net/cfg80211.h -+++ b/include/net/cfg80211.h -@@ -365,6 +365,48 @@ struct ieee80211_sta_he_cap { - u8 ppe_thres[IEEE80211_HE_PPE_THRES_MAX_LEN]; - }; - -+/** -+ * struct ieee80211_eht_mcs_nss_supp - EHT max supported NSS per MCS -+ * -+ * See P802.11be_D1.3 Table 9-401k - "Subfields of the Supported EHT-MCS -+ * and NSS Set field" -+ * -+ * @only_20mhz: MCS/NSS support for 20 MHz-only STA. -+ * @bw._80: MCS/NSS support for BW <= 80 MHz -+ * @bw._160: MCS/NSS support for BW = 160 MHz -+ * @bw._320: MCS/NSS support for BW = 320 MHz -+ */ -+struct ieee80211_eht_mcs_nss_supp { -+ union { -+ struct ieee80211_eht_mcs_nss_supp_20mhz_only only_20mhz; -+ struct { -+ struct ieee80211_eht_mcs_nss_supp_bw _80; -+ struct ieee80211_eht_mcs_nss_supp_bw _160; -+ struct ieee80211_eht_mcs_nss_supp_bw _320; -+ } __packed bw; -+ } __packed; -+} __packed; -+ -+#define IEEE80211_EHT_PPE_THRES_MAX_LEN 32 -+ -+/** -+ * struct ieee80211_sta_eht_cap - STA's EHT capabilities -+ * -+ * This structure describes most essential parameters needed -+ * to describe 802.11be EHT capabilities for a STA. -+ * -+ * @has_eht: true iff EHT data is valid. -+ * @eht_cap_elem: Fixed portion of the eht capabilities element. -+ * @eht_mcs_nss_supp: The supported NSS/MCS combinations. -+ * @eht_ppe_thres: Holds the PPE Thresholds data. -+ */ -+struct ieee80211_sta_eht_cap { -+ bool has_eht; -+ struct ieee80211_eht_cap_elem_fixed eht_cap_elem; -+ struct ieee80211_eht_mcs_nss_supp eht_mcs_nss_supp; -+ u8 eht_ppe_thres[IEEE80211_EHT_PPE_THRES_MAX_LEN]; -+}; -+ - /** - * struct ieee80211_sband_iftype_data - sband data per interface type - * -@@ -384,6 +426,7 @@ struct ieee80211_sband_iftype_data { - u16 types_mask; - struct ieee80211_sta_he_cap he_cap; - struct ieee80211_he_6ghz_capa he_6ghz_capa; -+ struct ieee80211_sta_eht_cap eht_cap; - struct { - const u8 *data; - unsigned int len; -@@ -566,6 +609,26 @@ ieee80211_get_he_6ghz_capa(const struct ieee80211_supported_band *sband, - return data->he_6ghz_capa.capa; - } - -+/** -+ * ieee80211_get_eht_iftype_cap - return ETH capabilities for an sband's iftype -+ * @sband: the sband to search for the iftype on -+ * @iftype: enum nl80211_iftype -+ * -+ * Return: pointer to the struct ieee80211_sta_eht_cap, or NULL is none found -+ */ -+static inline const struct ieee80211_sta_eht_cap * -+ieee80211_get_eht_iftype_cap(const struct ieee80211_supported_band *sband, -+ enum nl80211_iftype iftype) -+{ -+ const struct ieee80211_sband_iftype_data *data = -+ ieee80211_get_sband_iftype_data(sband, iftype); -+ -+ if (data && data->eht_cap.has_eht) -+ return &data->eht_cap; -+ -+ return NULL; -+} -+ - /** - * wiphy_read_of_freq_limits - read frequency limits from device tree - * -diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h -index 195a238a322e..d305a8b8c536 100644 ---- a/include/uapi/linux/nl80211.h -+++ b/include/uapi/linux/nl80211.h -@@ -3766,6 +3766,14 @@ enum nl80211_mpath_info { - * given for all 6 GHz band channels - * @NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS: vendor element capabilities that are - * advertised on this band/for this iftype (binary) -+ * @NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC: EHT MAC capabilities as in EHT -+ * capabilities element -+ * @NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY: EHT PHY capabilities as in EHT -+ * capabilities element -+ * @NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET: EHT supported NSS/MCS as in EHT -+ * capabilities element -+ * @NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE: EHT PPE thresholds information as -+ * defined in EHT capabilities element - * @__NL80211_BAND_IFTYPE_ATTR_AFTER_LAST: internal use - * @NL80211_BAND_IFTYPE_ATTR_MAX: highest band attribute currently defined - */ -@@ -3779,6 +3787,10 @@ enum nl80211_band_iftype_attr { - NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE, - NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA, - NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS, -+ NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC, -+ NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY, -+ NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET, -+ NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE, - - /* keep last */ - __NL80211_BAND_IFTYPE_ATTR_AFTER_LAST, -diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c -index fe5eb2d1fe3a..1e9cc18795c5 100644 ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -1748,6 +1748,7 @@ nl80211_send_iftype_data(struct sk_buff *msg, - const struct ieee80211_sband_iftype_data *iftdata) - { - const struct ieee80211_sta_he_cap *he_cap = &iftdata->he_cap; -+ const struct ieee80211_sta_eht_cap *eht_cap = &iftdata->eht_cap; - - if (nl80211_put_iftypes(msg, NL80211_BAND_IFTYPE_ATTR_IFTYPES, - iftdata->types_mask)) -@@ -1768,6 +1769,32 @@ nl80211_send_iftype_data(struct sk_buff *msg, - return -ENOBUFS; - } - -+ if (eht_cap->has_eht && he_cap->has_he) { -+ u8 mcs_nss_size, ppe_thresh_size; -+ u16 ppe_thres_hdr; -+ -+ mcs_nss_size = -+ ieee80211_eht_mcs_nss_size(&he_cap->he_cap_elem, -+ &eht_cap->eht_cap_elem); -+ -+ ppe_thres_hdr = get_unaligned_le16(&eht_cap->eht_ppe_thres[0]); -+ ppe_thresh_size = -+ ieee80211_eht_ppe_size(ppe_thres_hdr, -+ eht_cap->eht_cap_elem.phy_cap_info); -+ -+ if (nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC, -+ sizeof(eht_cap->eht_cap_elem.mac_cap_info), -+ eht_cap->eht_cap_elem.mac_cap_info) || -+ nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY, -+ sizeof(eht_cap->eht_cap_elem.phy_cap_info), -+ eht_cap->eht_cap_elem.phy_cap_info) || -+ nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET, -+ mcs_nss_size, &eht_cap->eht_mcs_nss_supp) || -+ nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE, -+ ppe_thresh_size, eht_cap->eht_ppe_thres)) -+ return -ENOBUFS; -+ } -+ - if (sband->band == NL80211_BAND_6GHZ && - nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA, - sizeof(iftdata->he_6ghz_capa), --- -2.31.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/548-cfg80211-Add-support-for-EHT-320-MHz-channel-width.patch b/feeds/ipq95xx/mac80211/patches/qca/548-cfg80211-Add-support-for-EHT-320-MHz-channel-width.patch deleted file mode 100644 index abe921642..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/548-cfg80211-Add-support-for-EHT-320-MHz-channel-width.patch +++ /dev/null @@ -1,259 +0,0 @@ -From 266404d2ba15a651e783cecb70457a707f4978bb Mon Sep 17 00:00:00 2001 -From: Jia Ding -Date: Mon, 14 Feb 2022 17:29:54 +0100 -Subject: [PATCH 07/19] cfg80211: Add support for EHT 320 MHz channel width - -Add 320 MHz support in the channel def and center frequency validation -with compatible check. - -Signed-off-by: Jia Ding -Co-authored-by: Karthikeyan Periyasamy -Signed-off-by: Karthikeyan Periyasamy -Co-authored-by: Muna Sinada -Signed-off-by: Muna Sinada -Co-authored-by: Veerendranath Jakkam -Signed-off-by: Veerendranath Jakkam -Link: https://lore.kernel.org/r/1640163883-12696-5-git-send-email-quic_vjakkam@quicinc.com -Signed-off-by: Johannes Berg ---- - drivers/net/wireless/mac80211_hwsim.c | 2 + - include/net/cfg80211.h | 7 ++- - include/uapi/linux/nl80211.h | 3 + - net/wireless/chan.c | 91 ++++++++++++++++++++++++--- - net/wireless/nl80211.c | 2 + - 5 files changed, 97 insertions(+), 8 deletions(-) - ---- a/drivers/net/wireless/mac80211_hwsim.c -+++ b/drivers/net/wireless/mac80211_hwsim.c -@@ -831,6 +831,8 @@ static int hwsim_get_chanwidth(enum nl80 - case NL80211_CHAN_WIDTH_80P80: - case NL80211_CHAN_WIDTH_160: - return 160; -+ case NL80211_CHAN_WIDTH_320: -+ return 320; - case NL80211_CHAN_WIDTH_5: - return 5; - case NL80211_CHAN_WIDTH_10: ---- a/include/net/cfg80211.h -+++ b/include/net/cfg80211.h -@@ -116,7 +116,11 @@ struct wiphy; - * on this channel. - * @IEEE80211_CHAN_PSD: power spectral density (in dBm) - * on this channel. -- * -+ * @IEEE80211_CHAN_NO_320MHZ: If the driver supports 320 MHz on the band, -+ * this flag indicates that a 320 MHz channel cannot use this -+ * channel as the control or any of the secondary channels. -+ * This may be due to the driver or due to regulatory bandwidth -+ * restrictions. - */ - enum ieee80211_channel_flags { - IEEE80211_CHAN_DISABLED = 1<<0, -@@ -139,6 +143,7 @@ enum ieee80211_channel_flags { - IEEE80211_CHAN_8MHZ = 1<<17, - IEEE80211_CHAN_16MHZ = 1<<18, - IEEE80211_CHAN_PSD = 1<<19, -+ IEEE80211_CHAN_NO_320MHZ = 1<<20, - }; - - #define IEEE80211_CHAN_NO_HT40 \ ---- a/include/uapi/linux/nl80211.h -+++ b/include/uapi/linux/nl80211.h -@@ -4760,6 +4760,8 @@ enum nl80211_key_mode { - * @NL80211_CHAN_WIDTH_4: 4 MHz OFDM channel - * @NL80211_CHAN_WIDTH_8: 8 MHz OFDM channel - * @NL80211_CHAN_WIDTH_16: 16 MHz OFDM channel -+ * @NL80211_CHAN_WIDTH_320: 320 MHz channel, the %NL80211_ATTR_CENTER_FREQ1 -+ * attribute must be provided as well - */ - enum nl80211_chan_width { - NL80211_CHAN_WIDTH_20_NOHT, -@@ -4775,6 +4777,7 @@ enum nl80211_chan_width { - NL80211_CHAN_WIDTH_4, - NL80211_CHAN_WIDTH_8, - NL80211_CHAN_WIDTH_16, -+ NL80211_CHAN_WIDTH_320, - }; - - /** ---- a/net/wireless/chan.c -+++ b/net/wireless/chan.c -@@ -181,6 +181,9 @@ static int nl80211_chan_width_to_mhz(enu - case NL80211_CHAN_WIDTH_160: - mhz = 160; - break; -+ case NL80211_CHAN_WIDTH_320: -+ mhz = 320; -+ break; - default: - WARN_ON_ONCE(1); - return -1; -@@ -271,6 +274,17 @@ bool cfg80211_chandef_valid(const struct - case NL80211_CHAN_WIDTH_16: - /* all checked above */ - break; -+ case NL80211_CHAN_WIDTH_320: -+ if (chandef->center_freq1 == control_freq + 150 || -+ chandef->center_freq1 == control_freq + 130 || -+ chandef->center_freq1 == control_freq + 110 || -+ chandef->center_freq1 == control_freq + 90 || -+ chandef->center_freq1 == control_freq - 90 || -+ chandef->center_freq1 == control_freq - 110 || -+ chandef->center_freq1 == control_freq - 130 || -+ chandef->center_freq1 == control_freq - 150) -+ break; -+ fallthrough; - case NL80211_CHAN_WIDTH_160: - if (chandef->center_freq1 == control_freq + 70 || - chandef->center_freq1 == control_freq + 50 || -@@ -307,7 +321,7 @@ bool cfg80211_chandef_valid(const struct - EXPORT_SYMBOL(cfg80211_chandef_valid); - - static void chandef_primary_freqs(const struct cfg80211_chan_def *c, -- u32 *pri40, u32 *pri80) -+ u32 *pri40, u32 *pri80, u32 *pri160) - { - int tmp; - -@@ -315,9 +329,11 @@ static void chandef_primary_freqs(const - case NL80211_CHAN_WIDTH_40: - *pri40 = c->center_freq1; - *pri80 = 0; -+ *pri160 = 0; - break; - case NL80211_CHAN_WIDTH_80: - case NL80211_CHAN_WIDTH_80P80: -+ *pri160 = 0; - *pri80 = c->center_freq1; - /* n_P20 */ - tmp = (30 + c->chan->center_freq - c->center_freq1)/20; -@@ -327,6 +343,7 @@ static void chandef_primary_freqs(const - *pri40 = c->center_freq1 - 20 + 40 * tmp; - break; - case NL80211_CHAN_WIDTH_160: -+ *pri160 = c->center_freq1; - /* n_P20 */ - tmp = (70 + c->chan->center_freq - c->center_freq1)/20; - /* n_P40 */ -@@ -337,6 +354,20 @@ static void chandef_primary_freqs(const - tmp /= 2; - *pri80 = c->center_freq1 - 40 + 80 * tmp; - break; -+ case NL80211_CHAN_WIDTH_320: -+ /* n_P20 */ -+ tmp = (150 + c->chan->center_freq - c->center_freq1) / 20; -+ /* n_P40 */ -+ tmp /= 2; -+ /* freq_P40 */ -+ *pri40 = c->center_freq1 - 140 + 40 * tmp; -+ /* n_P80 */ -+ tmp /= 2; -+ *pri80 = c->center_freq1 - 120 + 80 * tmp; -+ /* n_P160 */ -+ tmp /= 2; -+ *pri160 = c->center_freq1 - 80 + 160 * tmp; -+ break; - default: - WARN_ON_ONCE(1); - } -@@ -346,7 +377,7 @@ const struct cfg80211_chan_def * - cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1, - const struct cfg80211_chan_def *c2) - { -- u32 c1_pri40, c1_pri80, c2_pri40, c2_pri80; -+ u32 c1_pri40, c1_pri80, c2_pri40, c2_pri80, c1_pri160, c2_pri160; - - /* If they are identical, return */ - if (cfg80211_chandef_identical(c1, c2)) -@@ -381,14 +412,31 @@ cfg80211_chandef_compatible(const struct - c2->width == NL80211_CHAN_WIDTH_20) - return c1; - -- chandef_primary_freqs(c1, &c1_pri40, &c1_pri80); -- chandef_primary_freqs(c2, &c2_pri40, &c2_pri80); -+ chandef_primary_freqs(c1, &c1_pri40, &c1_pri80, &c1_pri160); -+ chandef_primary_freqs(c2, &c2_pri40, &c2_pri80, &c2_pri160); - - if (c1_pri40 != c2_pri40) - return NULL; - -- WARN_ON(!c1_pri80 && !c2_pri80); -- if (c1_pri80 && c2_pri80 && c1_pri80 != c2_pri80) -+ if (c1->width == NL80211_CHAN_WIDTH_40) -+ return c2; -+ -+ if (c2->width == NL80211_CHAN_WIDTH_40) -+ return c1; -+ -+ if (c1_pri80 != c2_pri80) -+ return NULL; -+ -+ if (c1->width == NL80211_CHAN_WIDTH_80 && -+ c2->width > NL80211_CHAN_WIDTH_80) -+ return c2; -+ -+ if (c2->width == NL80211_CHAN_WIDTH_80 && -+ c1->width > NL80211_CHAN_WIDTH_80) -+ return c1; -+ -+ WARN_ON(!c1_pri160 && !c2_pri160); -+ if (c1_pri160 && c2_pri160 && c1_pri160 != c2_pri160) - return NULL; - - if (c1->width > c2->width) -@@ -960,7 +1008,10 @@ bool cfg80211_chandef_usable(struct wiph - struct ieee80211_sta_vht_cap *vht_cap; - struct ieee80211_edmg *edmg_cap; - u32 width, control_freq, cap; -- bool ext_nss_cap, support_80_80 = false; -+ bool ext_nss_cap, support_80_80 = false, support_320 = false; -+ const struct ieee80211_sband_iftype_data *iftd; -+ struct ieee80211_supported_band *sband; -+ int i; - - if (WARN_ON(!cfg80211_chandef_valid(chandef))) - return false; -@@ -1062,6 +1113,32 @@ bool cfg80211_chandef_usable(struct wiph - (vht_cap->cap & IEEE80211_VHT_CAP_EXT_NSS_BW_MASK))) - return false; - break; -+ case NL80211_CHAN_WIDTH_320: -+ prohibited_flags |= IEEE80211_CHAN_NO_320MHZ; -+ width = 320; -+ -+ if (chandef->chan->band != NL80211_BAND_6GHZ) -+ return false; -+ -+ sband = wiphy->bands[NL80211_BAND_6GHZ]; -+ if (!sband) -+ return false; -+ -+ for (i = 0; i < sband->n_iftype_data; i++) { -+ iftd = &sband->iftype_data[i]; -+ if (!iftd->eht_cap.has_eht) -+ continue; -+ -+ if (iftd->eht_cap.eht_cap_elem.phy_cap_info[0] & -+ IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ) { -+ support_320 = true; -+ break; -+ } -+ } -+ -+ if (!support_320) -+ return false; -+ break; - default: - WARN_ON_ONCE(1); - return false; ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -10760,6 +10760,8 @@ static int nl80211_join_ibss(struct sk_b - NL80211_EXT_FEATURE_VHT_IBSS)) - return -EINVAL; - break; -+ case NL80211_CHAN_WIDTH_320: -+ return -EINVAL; - default: - return -EINVAL; - } diff --git a/feeds/ipq95xx/mac80211/patches/qca/549-nl80211-add-EHT-MCS-support.patch b/feeds/ipq95xx/mac80211/patches/qca/549-nl80211-add-EHT-MCS-support.patch deleted file mode 100644 index 4dac0a875..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/549-nl80211-add-EHT-MCS-support.patch +++ /dev/null @@ -1,350 +0,0 @@ -From dfcc7315e6c339fedacd1305ebf30a8d22d6cb51 Mon Sep 17 00:00:00 2001 -From: Veerendranath Jakkam -Date: Mon, 14 Feb 2022 17:29:55 +0100 -Subject: [PATCH 08/19] nl80211: add EHT MCS support - -Add support for reporting and calculating EHT bitrates. - -Signed-off-by: Veerendranath Jakkam -Link: https://lore.kernel.org/r/1640163883-12696-7-git-send-email-quic_vjakkam@quicinc.com -Signed-off-by: Johannes Berg ---- - include/net/cfg80211.h | 11 +++ - include/uapi/linux/nl80211.h | 62 +++++++++++++++++ - net/wireless/nl80211.c | 19 +++++ - net/wireless/util.c | 131 +++++++++++++++++++++++++++++++++++ - 4 files changed, 223 insertions(+) - -diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h -index fd81e1bdbb34..2e676901e2f4 100644 ---- a/include/net/cfg80211.h -+++ b/include/net/cfg80211.h -@@ -1600,6 +1600,7 @@ int cfg80211_check_station_change(struct wiphy *wiphy, - * @RATE_INFO_FLAGS_HE_MCS: HE MCS information - * @RATE_INFO_FLAGS_EDMG: 60GHz MCS in EDMG mode - * @RATE_INFO_FLAGS_EXTENDED_SC_DMG: 60GHz extended SC MCS -+ * @RATE_INFO_FLAGS_EHT_MCS: EHT MCS information - */ - enum rate_info_flags { - RATE_INFO_FLAGS_MCS = BIT(0), -@@ -1609,6 +1610,7 @@ enum rate_info_flags { - RATE_INFO_FLAGS_HE_MCS = BIT(4), - RATE_INFO_FLAGS_EDMG = BIT(5), - RATE_INFO_FLAGS_EXTENDED_SC_DMG = BIT(6), -+ RATE_INFO_FLAGS_EHT_MCS = BIT(7), - }; - - /** -@@ -1623,6 +1625,8 @@ enum rate_info_flags { - * @RATE_INFO_BW_80: 80 MHz bandwidth - * @RATE_INFO_BW_160: 160 MHz bandwidth - * @RATE_INFO_BW_HE_RU: bandwidth determined by HE RU allocation -+ * @RATE_INFO_BW_320: 320 MHz bandwidth -+ * @RATE_INFO_BW_EHT_RU: bandwidth determined by EHT RU allocation - */ - enum rate_info_bw { - RATE_INFO_BW_20 = 0, -@@ -1632,6 +1636,8 @@ enum rate_info_bw { - RATE_INFO_BW_80, - RATE_INFO_BW_160, - RATE_INFO_BW_HE_RU, -+ RATE_INFO_BW_320, -+ RATE_INFO_BW_EHT_RU, - }; - - /** -@@ -1649,6 +1655,9 @@ enum rate_info_bw { - * @he_ru_alloc: HE RU allocation (from &enum nl80211_he_ru_alloc, - * only valid if bw is %RATE_INFO_BW_HE_RU) - * @n_bonded_ch: In case of EDMG the number of bonded channels (1-4) -+ * @eht_gi: EHT guard interval (from &enum nl80211_eht_gi) -+ * @eht_ru_alloc: EHT RU allocation (from &enum nl80211_eht_ru_alloc, -+ * only valid if bw is %RATE_INFO_BW_EHT_RU) - */ - struct rate_info { - u8 flags; -@@ -1660,6 +1669,8 @@ struct rate_info { - u8 he_dcm; - u8 he_ru_alloc; - u8 n_bonded_ch; -+ u8 eht_gi; -+ u8 eht_ru_alloc; - }; - - /** -diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h -index 9e05973f3f56..d0ba70ea5d04 100644 ---- a/include/uapi/linux/nl80211.h -+++ b/include/uapi/linux/nl80211.h -@@ -3392,6 +3392,56 @@ enum nl80211_he_ru_alloc { - NL80211_RATE_INFO_HE_RU_ALLOC_2x996, - }; - -+/** -+ * enum nl80211_eht_gi - EHT guard interval -+ * @NL80211_RATE_INFO_EHT_GI_0_8: 0.8 usec -+ * @NL80211_RATE_INFO_EHT_GI_1_6: 1.6 usec -+ * @NL80211_RATE_INFO_EHT_GI_3_2: 3.2 usec -+ */ -+enum nl80211_eht_gi { -+ NL80211_RATE_INFO_EHT_GI_0_8, -+ NL80211_RATE_INFO_EHT_GI_1_6, -+ NL80211_RATE_INFO_EHT_GI_3_2, -+}; -+ -+/** -+ * enum nl80211_eht_ru_alloc - EHT RU allocation values -+ * @NL80211_RATE_INFO_EHT_RU_ALLOC_26: 26-tone RU allocation -+ * @NL80211_RATE_INFO_EHT_RU_ALLOC_52: 52-tone RU allocation -+ * @NL80211_RATE_INFO_EHT_RU_ALLOC_52P26: 52+26-tone RU allocation -+ * @NL80211_RATE_INFO_EHT_RU_ALLOC_106: 106-tone RU allocation -+ * @NL80211_RATE_INFO_EHT_RU_ALLOC_106P26: 106+26 tone RU allocation -+ * @NL80211_RATE_INFO_EHT_RU_ALLOC_242: 242-tone RU allocation -+ * @NL80211_RATE_INFO_EHT_RU_ALLOC_484: 484-tone RU allocation -+ * @NL80211_RATE_INFO_EHT_RU_ALLOC_484P242: 484+242 tone RU allocation -+ * @NL80211_RATE_INFO_EHT_RU_ALLOC_996: 996-tone RU allocation -+ * @NL80211_RATE_INFO_EHT_RU_ALLOC_996P484: 996+484 tone RU allocation -+ * @NL80211_RATE_INFO_EHT_RU_ALLOC_996P484P242: 996+484+242 tone RU allocation -+ * @NL80211_RATE_INFO_EHT_RU_ALLOC_2x996: 2x996-tone RU allocation -+ * @NL80211_RATE_INFO_EHT_RU_ALLOC_2x996P484: 2x996+484 tone RU allocation -+ * @NL80211_RATE_INFO_EHT_RU_ALLOC_3x996: 3x996-tone RU allocation -+ * @NL80211_RATE_INFO_EHT_RU_ALLOC_3x996P484: 3x996+484 tone RU allocation -+ * @NL80211_RATE_INFO_EHT_RU_ALLOC_4x996: 4x996-tone RU allocation -+ */ -+enum nl80211_eht_ru_alloc { -+ NL80211_RATE_INFO_EHT_RU_ALLOC_26, -+ NL80211_RATE_INFO_EHT_RU_ALLOC_52, -+ NL80211_RATE_INFO_EHT_RU_ALLOC_52P26, -+ NL80211_RATE_INFO_EHT_RU_ALLOC_106, -+ NL80211_RATE_INFO_EHT_RU_ALLOC_106P26, -+ NL80211_RATE_INFO_EHT_RU_ALLOC_242, -+ NL80211_RATE_INFO_EHT_RU_ALLOC_484, -+ NL80211_RATE_INFO_EHT_RU_ALLOC_484P242, -+ NL80211_RATE_INFO_EHT_RU_ALLOC_996, -+ NL80211_RATE_INFO_EHT_RU_ALLOC_996P484, -+ NL80211_RATE_INFO_EHT_RU_ALLOC_996P484P242, -+ NL80211_RATE_INFO_EHT_RU_ALLOC_2x996, -+ NL80211_RATE_INFO_EHT_RU_ALLOC_2x996P484, -+ NL80211_RATE_INFO_EHT_RU_ALLOC_3x996, -+ NL80211_RATE_INFO_EHT_RU_ALLOC_3x996P484, -+ NL80211_RATE_INFO_EHT_RU_ALLOC_4x996, -+}; -+ - /** - * enum nl80211_rate_info - bitrate information - * -@@ -3431,6 +3481,13 @@ enum nl80211_he_ru_alloc { - * @NL80211_RATE_INFO_HE_DCM: HE DCM value (u8, 0/1) - * @NL80211_RATE_INFO_RU_ALLOC: HE RU allocation, if not present then - * non-OFDMA was used (u8, see &enum nl80211_he_ru_alloc) -+ * @NL80211_RATE_INFO_320_MHZ_WIDTH: 320 MHz bitrate -+ * @NL80211_RATE_INFO_EHT_MCS: EHT MCS index (u8, 0-15) -+ * @NL80211_RATE_INFO_EHT_NSS: EHT NSS value (u8, 1-8) -+ * @NL80211_RATE_INFO_EHT_GI: EHT guard interval identifier -+ * (u8, see &enum nl80211_eht_gi) -+ * @NL80211_RATE_INFO_EHT_RU_ALLOC: EHT RU allocation, if not present then -+ * non-OFDMA was used (u8, see &enum nl80211_eht_ru_alloc) - * @__NL80211_RATE_INFO_AFTER_LAST: internal use - */ - enum nl80211_rate_info { -@@ -3452,6 +3509,11 @@ enum nl80211_rate_info { - NL80211_RATE_INFO_HE_GI, - NL80211_RATE_INFO_HE_DCM, - NL80211_RATE_INFO_HE_RU_ALLOC, -+ NL80211_RATE_INFO_320_MHZ_WIDTH, -+ NL80211_RATE_INFO_EHT_MCS, -+ NL80211_RATE_INFO_EHT_NSS, -+ NL80211_RATE_INFO_EHT_GI, -+ NL80211_RATE_INFO_EHT_RU_ALLOC, - - /* keep last */ - __NL80211_RATE_INFO_AFTER_LAST, -diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c -index 272373c57625..571a631f3c93 100644 ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -5965,6 +5965,14 @@ bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, int attr) - case RATE_INFO_BW_HE_RU: - rate_flg = 0; - WARN_ON(!(info->flags & RATE_INFO_FLAGS_HE_MCS)); -+ break; -+ case RATE_INFO_BW_320: -+ rate_flg = NL80211_RATE_INFO_320_MHZ_WIDTH; -+ break; -+ case RATE_INFO_BW_EHT_RU: -+ rate_flg = 0; -+ WARN_ON(!(info->flags & RATE_INFO_FLAGS_EHT_MCS)); -+ break; - } - - if (rate_flg && nla_put_flag(msg, rate_flg)) -@@ -5997,6 +6005,17 @@ bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, int attr) - nla_put_u8(msg, NL80211_RATE_INFO_HE_RU_ALLOC, - info->he_ru_alloc)) - return false; -+ } else if (info->flags & RATE_INFO_FLAGS_EHT_MCS) { -+ if (nla_put_u8(msg, NL80211_RATE_INFO_EHT_MCS, info->mcs)) -+ return false; -+ if (nla_put_u8(msg, NL80211_RATE_INFO_EHT_NSS, info->nss)) -+ return false; -+ if (nla_put_u8(msg, NL80211_RATE_INFO_EHT_GI, info->eht_gi)) -+ return false; -+ if (info->bw == RATE_INFO_BW_EHT_RU && -+ nla_put_u8(msg, NL80211_RATE_INFO_EHT_RU_ALLOC, -+ info->eht_ru_alloc)) -+ return false; - } - - nla_nest_end(msg, rate); -diff --git a/net/wireless/util.c b/net/wireless/util.c -index 41ea65deb6e1..fe7cd4449f5b 100644 ---- a/net/wireless/util.c -+++ b/net/wireless/util.c -@@ -1428,6 +1428,135 @@ static u32 cfg80211_calculate_bitrate_he(struct rate_info *rate) - return result / 10000; - } - -+static u32 cfg80211_calculate_bitrate_eht(struct rate_info *rate) -+{ -+#define SCALE 6144 -+ static const u32 mcs_divisors[16] = { -+ 102399, /* 16.666666... */ -+ 51201, /* 8.333333... */ -+ 34134, /* 5.555555... */ -+ 25599, /* 4.166666... */ -+ 17067, /* 2.777777... */ -+ 12801, /* 2.083333... */ -+ 11769, /* 1.851851... */ -+ 10239, /* 1.666666... */ -+ 8532, /* 1.388888... */ -+ 7680, /* 1.250000... */ -+ 6828, /* 1.111111... */ -+ 6144, /* 1.000000... */ -+ 5690, /* 0.926106... */ -+ 5120, /* 0.833333... */ -+ 409600, /* 66.666666... */ -+ 204800, /* 33.333333... */ -+ }; -+ static const u32 rates_996[3] = { 480388888, 453700000, 408333333 }; -+ static const u32 rates_484[3] = { 229411111, 216666666, 195000000 }; -+ static const u32 rates_242[3] = { 114711111, 108333333, 97500000 }; -+ static const u32 rates_106[3] = { 40000000, 37777777, 34000000 }; -+ static const u32 rates_52[3] = { 18820000, 17777777, 16000000 }; -+ static const u32 rates_26[3] = { 9411111, 8888888, 8000000 }; -+ u64 tmp; -+ u32 result; -+ -+ if (WARN_ON_ONCE(rate->mcs > 15)) -+ return 0; -+ if (WARN_ON_ONCE(rate->eht_gi > NL80211_RATE_INFO_EHT_GI_3_2)) -+ return 0; -+ if (WARN_ON_ONCE(rate->eht_ru_alloc > -+ NL80211_RATE_INFO_EHT_RU_ALLOC_4x996)) -+ return 0; -+ if (WARN_ON_ONCE(rate->nss < 1 || rate->nss > 8)) -+ return 0; -+ -+ /* Bandwidth checks for MCS 14 */ -+ if (rate->mcs == 14) { -+ if ((rate->bw != RATE_INFO_BW_EHT_RU && -+ rate->bw != RATE_INFO_BW_80 && -+ rate->bw != RATE_INFO_BW_160 && -+ rate->bw != RATE_INFO_BW_320) || -+ (rate->bw == RATE_INFO_BW_EHT_RU && -+ rate->eht_ru_alloc != NL80211_RATE_INFO_EHT_RU_ALLOC_996 && -+ rate->eht_ru_alloc != NL80211_RATE_INFO_EHT_RU_ALLOC_2x996 && -+ rate->eht_ru_alloc != NL80211_RATE_INFO_EHT_RU_ALLOC_4x996)) { -+ WARN(1, "invalid EHT BW for MCS 14: bw:%d, ru:%d\n", -+ rate->bw, rate->eht_ru_alloc); -+ return 0; -+ } -+ } -+ -+ if (rate->bw == RATE_INFO_BW_320 || -+ (rate->bw == RATE_INFO_BW_EHT_RU && -+ rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_4x996)) -+ result = 4 * rates_996[rate->eht_gi]; -+ else if (rate->bw == RATE_INFO_BW_EHT_RU && -+ rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_3x996P484) -+ result = 3 * rates_996[rate->eht_gi] + rates_484[rate->eht_gi]; -+ else if (rate->bw == RATE_INFO_BW_EHT_RU && -+ rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_3x996) -+ result = 3 * rates_996[rate->eht_gi]; -+ else if (rate->bw == RATE_INFO_BW_EHT_RU && -+ rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_2x996P484) -+ result = 2 * rates_996[rate->eht_gi] + rates_484[rate->eht_gi]; -+ else if (rate->bw == RATE_INFO_BW_160 || -+ (rate->bw == RATE_INFO_BW_EHT_RU && -+ rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_2x996)) -+ result = 2 * rates_996[rate->eht_gi]; -+ else if (rate->bw == RATE_INFO_BW_EHT_RU && -+ rate->eht_ru_alloc == -+ NL80211_RATE_INFO_EHT_RU_ALLOC_996P484P242) -+ result = rates_996[rate->eht_gi] + rates_484[rate->eht_gi] -+ + rates_242[rate->eht_gi]; -+ else if (rate->bw == RATE_INFO_BW_EHT_RU && -+ rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_996P484) -+ result = rates_996[rate->eht_gi] + rates_484[rate->eht_gi]; -+ else if (rate->bw == RATE_INFO_BW_80 || -+ (rate->bw == RATE_INFO_BW_EHT_RU && -+ rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_996)) -+ result = rates_996[rate->eht_gi]; -+ else if (rate->bw == RATE_INFO_BW_EHT_RU && -+ rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_484P242) -+ result = rates_484[rate->eht_gi] + rates_242[rate->eht_gi]; -+ else if (rate->bw == RATE_INFO_BW_40 || -+ (rate->bw == RATE_INFO_BW_EHT_RU && -+ rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_484)) -+ result = rates_484[rate->eht_gi]; -+ else if (rate->bw == RATE_INFO_BW_20 || -+ (rate->bw == RATE_INFO_BW_EHT_RU && -+ rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_242)) -+ result = rates_242[rate->eht_gi]; -+ else if (rate->bw == RATE_INFO_BW_EHT_RU && -+ rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_106P26) -+ result = rates_106[rate->eht_gi] + rates_26[rate->eht_gi]; -+ else if (rate->bw == RATE_INFO_BW_EHT_RU && -+ rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_106) -+ result = rates_106[rate->eht_gi]; -+ else if (rate->bw == RATE_INFO_BW_EHT_RU && -+ rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_52P26) -+ result = rates_52[rate->eht_gi] + rates_26[rate->eht_gi]; -+ else if (rate->bw == RATE_INFO_BW_EHT_RU && -+ rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_52) -+ result = rates_52[rate->eht_gi]; -+ else if (rate->bw == RATE_INFO_BW_EHT_RU && -+ rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_26) -+ result = rates_26[rate->eht_gi]; -+ else { -+ WARN(1, "invalid EHT MCS: bw:%d, ru:%d\n", -+ rate->bw, rate->eht_ru_alloc); -+ return 0; -+ } -+ -+ /* now scale to the appropriate MCS */ -+ tmp = result; -+ tmp *= SCALE; -+ do_div(tmp, mcs_divisors[rate->mcs]); -+ result = tmp; -+ -+ /* and take NSS */ -+ result = (result * rate->nss) / 8; -+ -+ return result / 10000; -+} -+ - u32 cfg80211_calculate_bitrate(struct rate_info *rate) - { - if (rate->flags & RATE_INFO_FLAGS_MCS) -@@ -1442,6 +1571,8 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate) - return cfg80211_calculate_bitrate_vht(rate); - if (rate->flags & RATE_INFO_FLAGS_HE_MCS) - return cfg80211_calculate_bitrate_he(rate); -+ if (rate->flags & RATE_INFO_FLAGS_EHT_MCS) -+ return cfg80211_calculate_bitrate_eht(rate); - - return rate->legacy; - } --- -2.31.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/550-nl80211-add-support-for-320MHz-channel-limitation.patch b/feeds/ipq95xx/mac80211/patches/qca/550-nl80211-add-support-for-320MHz-channel-limitation.patch deleted file mode 100644 index 4b83dcc23..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/550-nl80211-add-support-for-320MHz-channel-limitation.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 203e0f8f34dc20884530465a510a5bc24d564eac Mon Sep 17 00:00:00 2001 -From: Sriram R -Date: Mon, 14 Feb 2022 17:29:56 +0100 -Subject: [PATCH 09/19] nl80211: add support for 320MHz channel limitation - -Add support to advertise drivers or regulatory limitations on 320 MHz -channels to userspace. - -Signed-off-by: Sriram R -Co-authored-by: Karthikeyan Periyasamy -Signed-off-by: Karthikeyan Periyasamy -Co-authored-by: Veerendranath Jakkam -Signed-off-by: Veerendranath Jakkam -Link: https://lore.kernel.org/r/1640163883-12696-6-git-send-email-quic_vjakkam@quicinc.com -Signed-off-by: Johannes Berg ---- - include/uapi/linux/nl80211.h | 5 +++++ - net/wireless/nl80211.c | 3 +++ - net/wireless/reg.c | 6 ++++++ - 3 files changed, 14 insertions(+) - ---- a/include/uapi/linux/nl80211.h -+++ b/include/uapi/linux/nl80211.h -@@ -4058,6 +4058,8 @@ enum nl80211_wmm_rule { - * on this channel in current regulatory domain. - * @NL80211_FREQUENCY_ATTR_PSD: power spectral density (in dBm) - * is allowed on this channel in current regulatory domain. -+ * @NL80211_FREQUENCY_ATTR_NO_320MHZ: any 320 MHz channel using this channel -+ * as the primary or any of the secondary channels isn't possible - * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number - * currently defined - * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use -@@ -4095,6 +4097,7 @@ enum nl80211_frequency_attr { - NL80211_FREQUENCY_ATTR_8MHZ, - NL80211_FREQUENCY_ATTR_16MHZ, - NL80211_FREQUENCY_ATTR_PSD, -+ NL80211_FREQUENCY_ATTR_NO_320MHZ, - - /* keep last */ - __NL80211_FREQUENCY_ATTR_AFTER_LAST, -@@ -4301,6 +4304,7 @@ enum nl80211_sched_scan_match_attr { - * @NL80211_RRF_NO_160MHZ: 160MHz operation not allowed - * @NL80211_RRF_NO_HE: HE operation not allowed - * @NL80211_RRF_PSD: channels has power spectral density value -+ * @NL80211_RRF_NO_320MHZ: 320MHz operation not allowed - */ - enum nl80211_reg_rule_flags { - NL80211_RRF_NO_OFDM = 1<<0, -@@ -4320,6 +4324,7 @@ enum nl80211_reg_rule_flags { - NL80211_RRF_NO_160MHZ = 1<<16, - NL80211_RRF_NO_HE = 1<<17, - NL80211_RRF_PSD = 1<<18, -+ NL80211_RRF_NO_320MHZ = 1<<19, - }; - - #define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -1186,6 +1186,9 @@ static int nl80211_msg_put_channel(struc - if ((chan->flags & IEEE80211_CHAN_16MHZ) && - nla_put_flag(msg, NL80211_FREQUENCY_ATTR_16MHZ)) - goto nla_put_failure; -+ if ((chan->flags & IEEE80211_CHAN_NO_320MHZ) && -+ nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_320MHZ)) -+ goto nla_put_failure; - } - - if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER, ---- a/net/wireless/reg.c -+++ b/net/wireless/reg.c -@@ -1238,6 +1238,8 @@ unsigned int reg_get_max_bandwidth(const - { - unsigned int bw = reg_get_max_bandwidth_from_range(rd, rule); - -+ if (rule->flags & NL80211_RRF_NO_320MHZ) -+ bw = min_t(unsigned int, bw, MHZ_TO_KHZ(160)); - if (rule->flags & NL80211_RRF_NO_160MHZ) - bw = min_t(unsigned int, bw, MHZ_TO_KHZ(80)); - if (rule->flags & NL80211_RRF_NO_80MHZ) -@@ -1613,6 +1615,8 @@ static u32 map_regdom_flags(u32 rd_flags - channel_flags |= IEEE80211_CHAN_NO_HE; - if (rd_flags & NL80211_RRF_PSD) - channel_flags |= IEEE80211_CHAN_PSD; -+ if (rd_flags & NL80211_RRF_NO_320MHZ) -+ channel_flags |= IEEE80211_CHAN_NO_320MHZ; - return channel_flags; - } - -@@ -1781,6 +1785,8 @@ static uint32_t reg_rule_to_chan_bw_flag - bw_flags |= IEEE80211_CHAN_NO_80MHZ; - if (max_bandwidth_khz < MHZ_TO_KHZ(160)) - bw_flags |= IEEE80211_CHAN_NO_160MHZ; -+ if (max_bandwidth_khz < MHZ_TO_KHZ(320)) -+ bw_flags |= IEEE80211_CHAN_NO_320MHZ; - } - return bw_flags; - } diff --git a/feeds/ipq95xx/mac80211/patches/qca/551-cfg80211-add-NO-EHT-flag-to-regulatory.patch b/feeds/ipq95xx/mac80211/patches/qca/551-cfg80211-add-NO-EHT-flag-to-regulatory.patch deleted file mode 100644 index c801048ba..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/551-cfg80211-add-NO-EHT-flag-to-regulatory.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 9627e24290e102e69f5a4eef1d3197b747cc6b72 Mon Sep 17 00:00:00 2001 -From: Ilan Peer -Date: Mon, 14 Feb 2022 17:29:57 +0100 -Subject: [PATCH 10/19] cfg80211: add NO-EHT flag to regulatory - -This may be necessary in some cases, add a flag and propagate -it, just like the NO-HE that already exists. - -Signed-off-by: Ilan Peer -[split off from a combined 320/no-EHT patch] -Signed-off-by: Johannes Berg ---- - include/net/cfg80211.h | 2 ++ - include/uapi/linux/nl80211.h | 3 +++ - net/wireless/nl80211.c | 3 +++ - 3 files changed, 8 insertions(+) - ---- a/include/net/cfg80211.h -+++ b/include/net/cfg80211.h -@@ -121,6 +121,7 @@ struct wiphy; - * channel as the control or any of the secondary channels. - * This may be due to the driver or due to regulatory bandwidth - * restrictions. -+ * @IEEE80211_CHAN_NO_EHT: EHT operation is not permitted on this channel. - */ - enum ieee80211_channel_flags { - IEEE80211_CHAN_DISABLED = 1<<0, -@@ -144,6 +145,7 @@ enum ieee80211_channel_flags { - IEEE80211_CHAN_16MHZ = 1<<18, - IEEE80211_CHAN_PSD = 1<<19, - IEEE80211_CHAN_NO_320MHZ = 1<<20, -+ IEEE80211_CHAN_NO_EHT = 1<<20, - }; - - #define IEEE80211_CHAN_NO_HT40 \ ---- a/include/uapi/linux/nl80211.h -+++ b/include/uapi/linux/nl80211.h -@@ -4060,6 +4060,8 @@ enum nl80211_wmm_rule { - * is allowed on this channel in current regulatory domain. - * @NL80211_FREQUENCY_ATTR_NO_320MHZ: any 320 MHz channel using this channel - * as the primary or any of the secondary channels isn't possible -+ * @NL80211_FREQUENCY_ATTR_NO_EHT: EHT operation is not allowed on this channel -+ * in current regulatory domain. - * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number - * currently defined - * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use -@@ -4098,6 +4100,7 @@ enum nl80211_frequency_attr { - NL80211_FREQUENCY_ATTR_16MHZ, - NL80211_FREQUENCY_ATTR_PSD, - NL80211_FREQUENCY_ATTR_NO_320MHZ, -+ NL80211_FREQUENCY_ATTR_NO_EHT, - - /* keep last */ - __NL80211_FREQUENCY_ATTR_AFTER_LAST, ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -1189,6 +1189,9 @@ static int nl80211_msg_put_channel(struc - if ((chan->flags & IEEE80211_CHAN_NO_320MHZ) && - nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_320MHZ)) - goto nla_put_failure; -+ if ((chan->flags & IEEE80211_CHAN_NO_EHT) && -+ nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_EHT)) -+ goto nla_put_failure; - } - - if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER, diff --git a/feeds/ipq95xx/mac80211/patches/qca/552-cfg80211-Support-configuration-of-station-EHT-capabi.patch b/feeds/ipq95xx/mac80211/patches/qca/552-cfg80211-Support-configuration-of-station-EHT-capabi.patch deleted file mode 100644 index 3e4e999f7..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/552-cfg80211-Support-configuration-of-station-EHT-capabi.patch +++ /dev/null @@ -1,158 +0,0 @@ -From e2ce8511ddd51ca34d2e5cb90e888c896b0ca535 Mon Sep 17 00:00:00 2001 -From: Ilan Peer -Date: Mon, 14 Feb 2022 17:29:58 +0100 -Subject: [PATCH 11/19] cfg80211: Support configuration of station EHT - capabilities - -Add attributes and some code bits to support userspace passing -in EHT capabilities of stations. - -Signed-off-by: Ilan Peer -Signed-off-by: Johannes Berg ---- - include/net/cfg80211.h | 4 ++++ - include/uapi/linux/nl80211.h | 10 +++++++++- - net/wireless/nl80211.c | 37 ++++++++++++++++++++++++++++++++---- - 3 files changed, 46 insertions(+), 5 deletions(-) - ---- a/include/net/cfg80211.h -+++ b/include/net/cfg80211.h -@@ -1542,6 +1542,8 @@ struct sta_txpwr { - * @airtime_weight: airtime scheduler weight for this station - * @txpwr: transmit power for an associated station - * @he_6ghz_capa: HE 6 GHz Band capabilities of station -+ * @eht_capa: EHT capabilities of station -+ * @eht_capa_len: the length of the EHT capabilities - */ - struct station_parameters { - const u8 *supported_rates; -@@ -1576,6 +1578,8 @@ struct station_parameters { - enum nl80211_mgmt_rts_cts_conf mgmt_rts_cts; - struct sta_txpwr txpwr; - const struct ieee80211_he_6ghz_capa *he_6ghz_capa; -+ const struct ieee80211_eht_cap_elem *eht_capa; -+ u8 eht_capa_len; - }; - - /** ---- a/include/uapi/linux/nl80211.h -+++ b/include/uapi/linux/nl80211.h -@@ -11,7 +11,7 @@ - * Copyright 2008 Jouni Malinen - * Copyright 2008 Colin McCabe - * Copyright 2015-2017 Intel Deutschland GmbH -- * Copyright (C) 2018-2021 Intel Corporation -+ * Copyright (C) 2018-2022 Intel Corporation - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above -@@ -2690,6 +2690,10 @@ enum nl80211_commands { - * for co-located APs and neighbor APs in ESS to be added in all - * EMA beacons. - * -+ * @NL80211_ATTR_EHT_CAPABILITY: EHT Capability information element (from -+ * association request when used with NL80211_CMD_NEW_STATION). Can be set -+ * only if %NL80211_STA_FLAG_WME is set. -+ * - * @NUM_NL80211_ATTR: total number of nl80211_attrs available - * @NL80211_ATTR_MAX: highest attribute number currently defined - * @__NL80211_ATTR_AFTER_LAST: internal use -@@ -3214,6 +3218,8 @@ enum nl80211_attrs { - - NL80211_ATTR_EMA_RNR_ELEMS, - -+ NL80211_ATTR_EHT_CAPABILITY = NL80211_ATTR_MBSSID_ELEMS + 15, -+ - /* add attributes here, update the policy in nl80211.c */ - - __NL80211_ATTR_AFTER_LAST, -@@ -3269,6 +3275,8 @@ enum nl80211_attrs { - #define NL80211_HE_MAX_CAPABILITY_LEN 54 - #define NL80211_MAX_NR_CIPHER_SUITES 5 - #define NL80211_MAX_NR_AKM_SUITES 2 -+#define NL80211_EHT_MIN_CAPABILITY_LEN 13 -+#define NL80211_EHT_MAX_CAPABILITY_LEN 51 - - #define NL80211_MIN_REMAIN_ON_CHANNEL_TIME 10 - ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -5,7 +5,7 @@ - * Copyright 2006-2010 Johannes Berg - * Copyright 2013-2014 Intel Mobile Communications GmbH - * Copyright 2015-2017 Intel Deutschland GmbH -- * Copyright (C) 2018-2021 Intel Corporation -+ * Copyright (C) 2018-2022 Intel Corporation - */ - - #include -@@ -812,6 +812,10 @@ static const struct nla_policy nl80211_p - [NL80211_ATTR_AWGN_INTERFERENCE_BITMAP] = { .type = NLA_U32 }, - [NL80211_ATTR_6G_REG_POWER_MODE] = NLA_POLICY_RANGE(NLA_U8, 0, 2), - [NL80211_ATTR_EMA_RNR_ELEMS] = { .type = NLA_NESTED }, -+ [NL80211_ATTR_EHT_CAPABILITY] = -+ NLA_POLICY_RANGE(NLA_BINARY, -+ NL80211_EHT_MIN_CAPABILITY_LEN, -+ NL80211_EHT_MAX_CAPABILITY_LEN), - }; - - /* policy for the key attributes */ -@@ -6549,7 +6553,7 @@ int cfg80211_check_station_change(struct - if (params->supported_rates) - return -EINVAL; - if (params->ext_capab || params->ht_capa || params->vht_capa || -- params->he_capa) -+ params->he_capa || params->eht_capa) - return -EINVAL; - } - -@@ -6752,6 +6756,18 @@ static int nl80211_set_station_tdls(stru - nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]); - params->he_capa_len = - nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]); -+ -+ if (info->attrs[NL80211_ATTR_EHT_CAPABILITY]) { -+ params->eht_capa = -+ nla_data(info->attrs[NL80211_ATTR_EHT_CAPABILITY]); -+ params->eht_capa_len = -+ nla_len(info->attrs[NL80211_ATTR_EHT_CAPABILITY]); -+ -+ if (!ieee80211_eht_capa_size_ok((const u8 *)params->he_capa, -+ (const u8 *)params->eht_capa, -+ params->eht_capa_len)) -+ return -EINVAL; -+ } - } - - err = nl80211_parse_sta_channel_info(info, params); -@@ -7019,6 +7035,18 @@ static int nl80211_new_station(struct sk - nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]); - params.he_capa_len = - nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]); -+ -+ if (info->attrs[NL80211_ATTR_EHT_CAPABILITY]) { -+ params.eht_capa = -+ nla_data(info->attrs[NL80211_ATTR_EHT_CAPABILITY]); -+ params.eht_capa_len = -+ nla_len(info->attrs[NL80211_ATTR_EHT_CAPABILITY]); -+ -+ if (!ieee80211_eht_capa_size_ok((const u8 *)params.he_capa, -+ (const u8 *)params.eht_capa, -+ params.eht_capa_len)) -+ return -EINVAL; -+ } - } - - if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]) -@@ -7068,8 +7096,9 @@ static int nl80211_new_station(struct sk - params.ht_capa = NULL; - params.vht_capa = NULL; - -- /* HE requires WME */ -- if (params.he_capa_len || params.he_6ghz_capa) -+ /* HE and EHT require WME */ -+ if (params.he_capa_len || params.he_6ghz_capa || -+ params.eht_capa_len) - return -EINVAL; - } - diff --git a/feeds/ipq95xx/mac80211/patches/qca/553-mac80211-Support-parsing-EHT-elements.patch b/feeds/ipq95xx/mac80211/patches/qca/553-mac80211-Support-parsing-EHT-elements.patch deleted file mode 100644 index 00de93e40..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/553-mac80211-Support-parsing-EHT-elements.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 7505f22fcce284f387dd90d38434a5e16a1832eb Mon Sep 17 00:00:00 2001 -From: Ilan Peer -Date: Mon, 14 Feb 2022 17:29:59 +0100 -Subject: [PATCH 12/19] mac80211: Support parsing EHT elements - -Parse the new EHT elements in the element parsing utilities. - -Signed-off-by: Ilan Peer -Signed-off-by: Johannes Berg ---- - net/mac80211/ieee80211_i.h | 3 +++ - net/mac80211/util.c | 11 +++++++++++ - 2 files changed, 14 insertions(+) - -diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h -index 0fb6fc7a99ea..c408036d0d62 100644 ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -1591,6 +1591,8 @@ struct ieee802_11_elems { - const struct ieee80211_s1g_oper_ie *s1g_oper; - const struct ieee80211_s1g_bcn_compat_ie *s1g_bcn_compat; - const struct ieee80211_aid_response_ie *aid_resp; -+ const struct ieee80211_eht_cap_elem *eht_cap; -+ const struct ieee80211_eht_operation *eht_operation; - - /* length of them, respectively */ - u8 ext_capab_len; -@@ -1612,6 +1614,7 @@ struct ieee802_11_elems { - u8 bssid_index_len; - u8 tx_pwr_env_len[IEEE80211_TPE_MAX_IE_COUNT]; - u8 tx_pwr_env_num; -+ u8 eht_cap_len; - - /* whether a parse error occurred while retrieving these elements */ - bool parse_error; -diff --git a/net/mac80211/util.c b/net/mac80211/util.c -index f71b042a5c8b..c999f66fff18 100644 ---- a/net/mac80211/util.c -+++ b/net/mac80211/util.c -@@ -1006,6 +1006,17 @@ static void ieee80211_parse_extension_element(u32 *crc, - if (len >= sizeof(*elems->he_6ghz_capa)) - elems->he_6ghz_capa = data; - break; -+ case WLAN_EID_EXT_EHT_CAPABILITY: -+ if (ieee80211_eht_capa_size_ok(elems->he_cap, -+ data, len)) { -+ elems->eht_cap = data; -+ elems->eht_cap_len = len; -+ } -+ break; -+ case WLAN_EID_EXT_EHT_OPERATION: -+ if (ieee80211_eht_oper_size_ok(data, len)) -+ elems->eht_operation = data; -+ break; - } - } - --- -2.31.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/554-mac80211-Add-initial-support-for-EHT-and-320-MHz-cha.patch b/feeds/ipq95xx/mac80211/patches/qca/554-mac80211-Add-initial-support-for-EHT-and-320-MHz-cha.patch deleted file mode 100644 index 9ee268e58..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/554-mac80211-Add-initial-support-for-EHT-and-320-MHz-cha.patch +++ /dev/null @@ -1,683 +0,0 @@ -From 902b8079f70ce307af3448045267032578196d36 Mon Sep 17 00:00:00 2001 -From: Ilan Peer -Date: Mon, 14 Feb 2022 17:30:00 +0100 -Subject: [PATCH 13/19] mac80211: Add initial support for EHT and 320 MHz - channels - -Add initial support for EHT and 320 MHz bandwidth in mac80211. - -As a new IEEE80211_STA_RX_BW_320 is added to -enum ieee80211_sta_rx_bandwidth, update the drivers to avoid -compilation warnings. - -Signed-off-by: Ilan Peer -Signed-off-by: Johannes Berg ---- - drivers/net/wireless/mac80211_hwsim.c | 1 + - include/net/mac80211.h | 2 + - net/mac80211/chan.c | 5 +- - net/mac80211/ieee80211_i.h | 3 + - net/mac80211/mesh.c | 5 +- - net/mac80211/mlme.c | 109 +++++++++++++++----- - net/mac80211/util.c | 142 ++++++++++++++++++++------ - net/mac80211/vht.c | 4 +- - 8 files changed, 212 insertions(+), 59 deletions(-) - -Index: b/drivers/net/wireless/mac80211_hwsim.c -=================================================================== ---- a/drivers/net/wireless/mac80211_hwsim.c 2022-04-22 16:11:14.603977642 +0530 -+++ b/drivers/net/wireless/mac80211_hwsim.c 2022-04-22 16:11:14.599977678 +0530 -@@ -2167,6 +2167,7 @@ mac80211_hwsim_sta_rc_update(struct ieee - C(40); - C(80); - C(160); -+ C(320); - #undef C - } - -Index: b/include/net/mac80211.h -=================================================================== ---- a/include/net/mac80211.h 2022-04-22 16:11:14.603977642 +0530 -+++ b/include/net/mac80211.h 2022-04-22 16:11:14.599977678 +0530 -@@ -2078,6 +2078,7 @@ enum ieee80211_sta_state { - * @IEEE80211_STA_RX_BW_80: station can receive up to 80 MHz - * @IEEE80211_STA_RX_BW_160: station can receive up to 160 MHz - * (including 80+80 MHz) -+ * @IEEE80211_STA_RX_BW_320: station can receive up to 320 MHz - * - * Implementation note: 20 must be zero to be initialized - * correctly, the values must be sorted. -@@ -2087,6 +2088,7 @@ enum ieee80211_sta_rx_bandwidth { - IEEE80211_STA_RX_BW_40, - IEEE80211_STA_RX_BW_80, - IEEE80211_STA_RX_BW_160, -+ IEEE80211_STA_RX_BW_320, - }; - - /** -Index: b/net/mac80211/chan.c -=================================================================== ---- a/net/mac80211/chan.c 2022-04-22 16:11:14.603977642 +0530 -+++ b/net/mac80211/chan.c 2022-04-22 16:11:14.599977678 +0530 -@@ -218,6 +218,8 @@ static enum nl80211_chan_width ieee80211 - * might be smaller than the configured bw (160). - */ - return NL80211_CHAN_WIDTH_160; -+ case IEEE80211_STA_RX_BW_320: -+ return NL80211_CHAN_WIDTH_320; - default: - WARN_ON(1); - return NL80211_CHAN_WIDTH_20; -@@ -417,7 +419,7 @@ static void ieee80211_change_chanctx(str - { - u32 changed; - -- /* expected to handle only 20/40/80/160 channel widths */ -+ /* expected to handle only 20/40/80/160/320 channel widths */ - switch (chandef->width) { - case NL80211_CHAN_WIDTH_20_NOHT: - case NL80211_CHAN_WIDTH_20: -@@ -425,6 +427,7 @@ static void ieee80211_change_chanctx(str - case NL80211_CHAN_WIDTH_80: - case NL80211_CHAN_WIDTH_80P80: - case NL80211_CHAN_WIDTH_160: -+ case NL80211_CHAN_WIDTH_320: - break; - default: - WARN_ON(1); -Index: b/net/mac80211/ieee80211_i.h -=================================================================== ---- a/net/mac80211/ieee80211_i.h 2022-04-22 16:11:14.603977642 +0530 -+++ b/net/mac80211/ieee80211_i.h 2022-04-22 16:11:14.599977678 +0530 -@@ -377,6 +377,8 @@ enum ieee80211_sta_flags { - IEEE80211_STA_DISABLE_WMM = BIT(14), - IEEE80211_STA_ENABLE_RRM = BIT(15), - IEEE80211_STA_DISABLE_HE = BIT(16), -+ IEEE80211_STA_DISABLE_EHT = BIT(17), -+ IEEE80211_STA_DISABLE_320MHZ = BIT(18), - }; - - struct ieee80211_mgd_auth_data { -@@ -2443,6 +2445,7 @@ bool ieee80211_chandef_vht_oper(struct i - struct cfg80211_chan_def *chandef); - bool ieee80211_chandef_he_6ghz_oper(struct ieee80211_sub_if_data *sdata, - const struct ieee80211_he_operation *he_oper, -+ const struct ieee80211_eht_operation *eht_oper, - struct cfg80211_chan_def *chandef); - bool ieee80211_chandef_s1g_oper(const struct ieee80211_s1g_oper_ie *oper, - struct cfg80211_chan_def *chandef); -Index: b/net/mac80211/mesh.c -=================================================================== ---- a/net/mac80211/mesh.c 2022-04-22 16:11:14.603977642 +0530 -+++ b/net/mac80211/mesh.c 2022-04-22 16:11:14.599977678 +0530 -@@ -1,7 +1,7 @@ - // SPDX-License-Identifier: GPL-2.0-only - /* - * Copyright (c) 2008, 2009 open80211s Ltd. -- * Copyright (C) 2018 - 2020 Intel Corporation -+ * Copyright (C) 2018 - 2021 Intel Corporation - * Authors: Luis Carlos Cobo - * Javier Cardona - */ -@@ -104,7 +104,8 @@ bool mesh_matches_local(struct ieee80211 - ieee80211_chandef_vht_oper(&sdata->local->hw, vht_cap_info, - ie->vht_operation, ie->ht_operation, - &sta_chan_def); -- ieee80211_chandef_he_6ghz_oper(sdata, ie->he_operation, &sta_chan_def); -+ ieee80211_chandef_he_6ghz_oper(sdata, ie->he_operation, NULL, -+ &sta_chan_def); - - if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef, - &sta_chan_def)) -Index: b/net/mac80211/mlme.c -=================================================================== ---- a/net/mac80211/mlme.c 2022-04-22 16:11:14.603977642 +0530 -+++ b/net/mac80211/mlme.c 2022-04-22 16:11:14.603977642 +0530 -@@ -149,6 +149,7 @@ ieee80211_determine_chantype(struct ieee - const struct ieee80211_ht_operation *ht_oper, - const struct ieee80211_vht_operation *vht_oper, - const struct ieee80211_he_operation *he_oper, -+ const struct ieee80211_eht_operation *eht_oper, - const struct ieee80211_s1g_oper_ie *s1g_oper, - struct cfg80211_chan_def *chandef, bool tracking) - { -@@ -164,12 +165,14 @@ ieee80211_determine_chantype(struct ieee - chandef->freq1_offset = channel->freq_offset; - - if (channel->band == NL80211_BAND_6GHZ) { -- if (!ieee80211_chandef_he_6ghz_oper(sdata, he_oper, chandef)) { -+ if (!ieee80211_chandef_he_6ghz_oper(sdata, he_oper, eht_oper, -+ chandef)) { - mlme_dbg(sdata, -- "bad 6 GHz operation, disabling HT/VHT/HE\n"); -+ "bad 6 GHz operation, disabling HT/VHT/HE/EHT\n"); - ret = IEEE80211_STA_DISABLE_HT | - IEEE80211_STA_DISABLE_VHT | -- IEEE80211_STA_DISABLE_HE; -+ IEEE80211_STA_DISABLE_HE | -+ IEEE80211_STA_DISABLE_EHT; - } else { - ret = 0; - } -@@ -196,7 +199,8 @@ ieee80211_determine_chantype(struct ieee - mlme_dbg(sdata, "HT operation missing / HT not supported\n"); - ret = IEEE80211_STA_DISABLE_HT | - IEEE80211_STA_DISABLE_VHT | -- IEEE80211_STA_DISABLE_HE; -+ IEEE80211_STA_DISABLE_HE | -+ IEEE80211_STA_DISABLE_EHT; - goto out; - } - -@@ -219,7 +223,8 @@ ieee80211_determine_chantype(struct ieee - ht_oper->primary_chan, channel->band); - ret = IEEE80211_STA_DISABLE_HT | - IEEE80211_STA_DISABLE_VHT | -- IEEE80211_STA_DISABLE_HE; -+ IEEE80211_STA_DISABLE_HE | -+ IEEE80211_STA_DISABLE_EHT; - goto out; - } - -@@ -260,7 +265,7 @@ ieee80211_determine_chantype(struct ieee - if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HE)) - sdata_info(sdata, - "HE AP VHT information is invalid, disabling HE\n"); -- ret = IEEE80211_STA_DISABLE_HE; -+ ret = IEEE80211_STA_DISABLE_HE | IEEE80211_STA_DISABLE_EHT; - goto out; - } - } else if (!ieee80211_chandef_vht_oper(&sdata->local->hw, -@@ -340,7 +345,8 @@ out: - if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) { - ret = IEEE80211_STA_DISABLE_HT | - IEEE80211_STA_DISABLE_VHT | -- IEEE80211_STA_DISABLE_HE; -+ IEEE80211_STA_DISABLE_HE | -+ IEEE80211_STA_DISABLE_EHT; - break; - } - -@@ -349,7 +355,11 @@ out: - - if (!he_oper || !cfg80211_chandef_usable(sdata->wdev.wiphy, chandef, - IEEE80211_CHAN_NO_HE)) -- ret |= IEEE80211_STA_DISABLE_HE; -+ ret |= IEEE80211_STA_DISABLE_HE | IEEE80211_STA_DISABLE_EHT; -+ -+ if (!eht_oper || !cfg80211_chandef_usable(sdata->wdev.wiphy, chandef, -+ IEEE80211_CHAN_NO_EHT)) -+ ret |= IEEE80211_STA_DISABLE_EHT; - - if (chandef->width != vht_chandef.width && !tracking) - sdata_info(sdata, -@@ -366,6 +376,7 @@ static int ieee80211_config_bw(struct ie - const struct ieee80211_ht_operation *ht_oper, - const struct ieee80211_vht_operation *vht_oper, - const struct ieee80211_he_operation *he_oper, -+ const struct ieee80211_eht_operation *eht_oper, - const struct ieee80211_s1g_oper_ie *s1g_oper, - const u8 *bssid, u32 *changed) - { -@@ -391,9 +402,16 @@ static int ieee80211_config_bw(struct ie - /* don't check HE if we associated as non-HE station */ - if (ifmgd->flags & IEEE80211_STA_DISABLE_HE || - !ieee80211_get_he_iftype_cap(sband, -- ieee80211_vif_type_p2p(&sdata->vif))) -- -+ ieee80211_vif_type_p2p(&sdata->vif))) { - he_oper = NULL; -+ eht_oper = NULL; -+ } -+ -+ /* don't check EHT if we associated as non-EHT station */ -+ if (ifmgd->flags & IEEE80211_STA_DISABLE_EHT || -+ !ieee80211_get_eht_iftype_cap(sband, -+ ieee80211_vif_type_p2p(&sdata->vif))) -+ eht_oper = NULL; - - if (WARN_ON_ONCE(!sta)) - return -EINVAL; -@@ -413,7 +431,8 @@ static int ieee80211_config_bw(struct ie - - /* calculate new channel (type) based on HT/VHT/HE operation IEs */ - flags = ieee80211_determine_chantype(sdata, sband, chan, vht_cap_info, -- ht_oper, vht_oper, he_oper, -+ ht_oper, vht_oper, -+ he_oper, eht_oper, - s1g_oper, &chandef, true); - - /* -@@ -447,9 +466,11 @@ static int ieee80211_config_bw(struct ie - if (flags != (ifmgd->flags & (IEEE80211_STA_DISABLE_HT | - IEEE80211_STA_DISABLE_VHT | - IEEE80211_STA_DISABLE_HE | -+ IEEE80211_STA_DISABLE_EHT | - IEEE80211_STA_DISABLE_40MHZ | - IEEE80211_STA_DISABLE_80P80MHZ | -- IEEE80211_STA_DISABLE_160MHZ)) || -+ IEEE80211_STA_DISABLE_160MHZ | -+ IEEE80211_STA_DISABLE_320MHZ)) || - !cfg80211_chandef_valid(&chandef)) { - sdata_info(sdata, - "AP %pM changed caps/bw in a way we can't support (0x%x/0x%x) - disconnect\n", -@@ -985,13 +1006,14 @@ skip_rates: - &assoc_data->ap_vht_cap); - - /* -- * If AP doesn't support HT, mark HE as disabled. -+ * If AP doesn't support HT, mark HE and EHT as disabled. - * If on the 5GHz band, make sure it supports VHT. - */ - if (ifmgd->flags & IEEE80211_STA_DISABLE_HT || - (sband->band == NL80211_BAND_5GHZ && - ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) -- ifmgd->flags |= IEEE80211_STA_DISABLE_HE; -+ ifmgd->flags |= IEEE80211_STA_DISABLE_HE | -+ IEEE80211_STA_DISABLE_EHT; - - if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HE)) - ieee80211_add_he_ie(sdata, skb, sband); -@@ -4254,6 +4276,7 @@ static void ieee80211_rx_mgmt_beacon(str - if (ieee80211_config_bw(sdata, sta, elems->ht_cap_elem, - elems->vht_cap_elem, elems->ht_operation, - elems->vht_operation, elems->he_operation, -+ elems->eht_operation, - elems->s1g_oper, bssid, &changed)) { - mutex_unlock(&local->sta_mtx); - sdata_info(sdata, -@@ -5020,6 +5043,7 @@ static int ieee80211_prep_channel(struct - const struct ieee80211_ht_operation *ht_oper = NULL; - const struct ieee80211_vht_operation *vht_oper = NULL; - const struct ieee80211_he_operation *he_oper = NULL; -+ const struct ieee80211_eht_operation *eht_oper = NULL; - const struct ieee80211_s1g_oper_ie *s1g_oper = NULL; - struct ieee80211_supported_band *sband; - struct cfg80211_chan_def chandef; -@@ -5048,22 +5072,31 @@ static int ieee80211_prep_channel(struct - - /* disable HT/VHT/HE if we don't support them */ - if (!sband->ht_cap.ht_supported && !is_6ghz) { -- mlme_dbg(sdata, "HT not supported, disabling HT/VHT/HE\n"); -+ mlme_dbg(sdata, "HT not supported, disabling HT/VHT/HE/EHT\n"); - ifmgd->flags |= IEEE80211_STA_DISABLE_HT; - ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; - ifmgd->flags |= IEEE80211_STA_DISABLE_HE; -+ ifmgd->flags |= IEEE80211_STA_DISABLE_EHT; - } - - if (!sband->vht_cap.vht_supported && is_5ghz) { -- mlme_dbg(sdata, "VHT not supported, disabling VHT/HE\n"); -+ mlme_dbg(sdata, "VHT not supported, disabling VHT/HE/EHT\n"); - ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; - ifmgd->flags |= IEEE80211_STA_DISABLE_HE; -+ ifmgd->flags |= IEEE80211_STA_DISABLE_EHT; - } - - if (!ieee80211_get_he_iftype_cap(sband, - ieee80211_vif_type_p2p(&sdata->vif))) { -- mlme_dbg(sdata, "HE not supported, disabling it\n"); -+ mlme_dbg(sdata, "HE not supported, disabling HE and EHT\n"); - ifmgd->flags |= IEEE80211_STA_DISABLE_HE; -+ ifmgd->flags |= IEEE80211_STA_DISABLE_EHT; -+ } -+ -+ if (!ieee80211_get_eht_iftype_cap(sband, -+ ieee80211_vif_type_p2p(&sdata->vif))) { -+ mlme_dbg(sdata, "EHT not supported, disabling EHT\n"); -+ ifmgd->flags |= IEEE80211_STA_DISABLE_EHT; - } - - if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) && !is_6ghz) { -@@ -5085,6 +5118,7 @@ static int ieee80211_prep_channel(struct - ifmgd->flags |= IEEE80211_STA_DISABLE_HT; - ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; - ifmgd->flags |= IEEE80211_STA_DISABLE_HE; -+ ifmgd->flags |= IEEE80211_STA_DISABLE_EHT; - } - - if (!elems->vht_cap_elem) { -@@ -5123,7 +5157,29 @@ static int ieee80211_prep_channel(struct - } - - if (!ieee80211_verify_sta_he_mcs_support(sdata, sband, he_oper)) -- ifmgd->flags |= IEEE80211_STA_DISABLE_HE; -+ ifmgd->flags |= IEEE80211_STA_DISABLE_HE | -+ IEEE80211_STA_DISABLE_EHT; -+ } -+ -+ /* -+ * EHT requires HE to be supported as well. Specifically for 6 GHz -+ * channels, the operation channel information can only be deduced from -+ * both the 6 GHz operation information (from the HE operation IE) and -+ * EHT operation. -+ */ -+ if (!(ifmgd->flags & (IEEE80211_STA_DISABLE_HE | -+ IEEE80211_STA_DISABLE_EHT)) && he_oper) { -+ const struct cfg80211_bss_ies *ies; -+ const u8 *eht_oper_ie; -+ -+ ies = rcu_dereference(cbss->ies); -+ eht_oper_ie = cfg80211_find_ext_ie(WLAN_EID_EXT_EHT_OPERATION, -+ ies->data, ies->len); -+ if (eht_oper_ie && eht_oper_ie[1] >= -+ 1 + sizeof(struct ieee80211_eht_operation)) -+ eht_oper = (void *)(eht_oper_ie + 3); -+ else -+ eht_oper = NULL; - } - - if (sband->band == NL80211_BAND_S1GHZ) { -@@ -5136,7 +5192,8 @@ static int ieee80211_prep_channel(struct - ifmgd->flags |= ieee80211_determine_chantype(sdata, sband, - cbss->channel, - bss->vht_cap_info, -- ht_oper, vht_oper, he_oper, -+ ht_oper, vht_oper, -+ he_oper, eht_oper, - s1g_oper, - &chandef, false); - -@@ -5627,6 +5684,7 @@ int ieee80211_mgd_assoc(struct ieee80211 - ifmgd->flags |= IEEE80211_STA_DISABLE_HT; - ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; - ifmgd->flags |= IEEE80211_STA_DISABLE_HE; -+ ifmgd->flags |= IEEE80211_STA_DISABLE_EHT; - netdev_info(sdata->dev, - "disabling HT/VHT/HE due to WEP/TKIP use\n"); - } -@@ -5634,11 +5692,12 @@ int ieee80211_mgd_assoc(struct ieee80211 - - sband = local->hw.wiphy->bands[req->bss->channel->band]; - -- /* also disable HT/VHT/HE if the AP doesn't use WMM */ -+ /* also disable HT/VHT/HE/EHT if the AP doesn't use WMM */ - if (!bss->wmm_used) { - ifmgd->flags |= IEEE80211_STA_DISABLE_HT; - ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; - ifmgd->flags |= IEEE80211_STA_DISABLE_HE; -+ ifmgd->flags |= IEEE80211_STA_DISABLE_EHT; - netdev_info(sdata->dev, - "disabling HT/VHT/HE as WMM/QoS is not supported by the AP\n"); - } -@@ -5692,9 +5751,11 @@ int ieee80211_mgd_assoc(struct ieee80211 - memcpy(&assoc_data->ap_vht_cap, vht_elem->data, - sizeof(struct ieee80211_vht_cap)); - } else if (is_5ghz) { -- sdata_info(sdata, "VHT capa missing/short, disabling VHT/HE\n"); -+ sdata_info(sdata, -+ "VHT capa missing/short, disabling VHT/HE/EHT\n"); - ifmgd->flags |= IEEE80211_STA_DISABLE_VHT | -- IEEE80211_STA_DISABLE_HE; -+ IEEE80211_STA_DISABLE_HE | -+ IEEE80211_STA_DISABLE_EHT; - } - rcu_read_unlock(); - -@@ -5773,6 +5834,7 @@ int ieee80211_mgd_assoc(struct ieee80211 - ifmgd->flags |= IEEE80211_STA_DISABLE_HT; - ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; - ifmgd->flags |= IEEE80211_STA_DISABLE_HE; -+ ifmgd->flags |= IEEE80211_STA_DISABLE_EHT; - } - - if (req->flags & ASSOC_REQ_DISABLE_VHT) { -@@ -5781,8 +5843,9 @@ int ieee80211_mgd_assoc(struct ieee80211 - } - - if (req->flags & ASSOC_REQ_DISABLE_HE) { -- mlme_dbg(sdata, "HE disabled by flag, disabling VHT\n"); -+ mlme_dbg(sdata, "HE disabled by flag, disabling HE/EHT\n"); - ifmgd->flags |= IEEE80211_STA_DISABLE_HE; -+ ifmgd->flags |= IEEE80211_STA_DISABLE_EHT; - } - - err = ieee80211_prep_connection(sdata, req->bss, true, override); -Index: b/net/mac80211/util.c -=================================================================== ---- a/net/mac80211/util.c 2022-04-22 16:11:14.603977642 +0530 -+++ b/net/mac80211/util.c 2022-04-22 16:11:28.375852888 +0530 -@@ -3067,6 +3067,10 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, - else - ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW; - break; -+ case NL80211_CHAN_WIDTH_320: -+ /* HT information element should not be included on 6GHz */ -+ WARN_ON(1); -+ return pos; - default: - ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE; - break; -@@ -3106,6 +3110,10 @@ void ieee80211_ie_build_wide_bw_cs(u8 *p - case NL80211_CHAN_WIDTH_80P80: - *pos++ = IEEE80211_VHT_CHANWIDTH_80P80MHZ; - break; -+ case NL80211_CHAN_WIDTH_320: -+ /* The behavior is not defined for 320 MHz channels */ -+ WARN_ON(1); -+ fallthrough; - default: - *pos++ = IEEE80211_VHT_CHANWIDTH_USE_HT; - } -@@ -3158,6 +3166,10 @@ u8 *ieee80211_ie_build_vht_oper(u8 *pos, - case NL80211_CHAN_WIDTH_80: - vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ; - break; -+ case NL80211_CHAN_WIDTH_320: -+ /* VHT information element should not be included on 6GHz */ -+ WARN_ON(1); -+ return pos; - default: - vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_USE_HT; - break; -@@ -3218,6 +3230,13 @@ u8 *ieee80211_ie_build_he_oper(u8 *pos, - he_6ghz_op->ccfs1 = 0; - - switch (chandef->width) { -+ case NL80211_CHAN_WIDTH_320: -+ /* -+ * TODO: mesh operation is not defined over 6GHz 320 MHz -+ * channels. -+ */ -+ WARN_ON(1); -+ break; - case NL80211_CHAN_WIDTH_160: - /* Convert 160 MHz channel width to new style as interop - * workaround. -@@ -3407,18 +3426,20 @@ bool ieee80211_chandef_vht_oper(struct i - - bool ieee80211_chandef_he_6ghz_oper(struct ieee80211_sub_if_data *sdata, - const struct ieee80211_he_operation *he_oper, -+ const struct ieee80211_eht_operation *eht_oper, - struct cfg80211_chan_def *chandef) - { - struct ieee80211_local *local = sdata->local; - struct ieee80211_supported_band *sband; - enum nl80211_iftype iftype = ieee80211_vif_type_p2p(&sdata->vif); - const struct ieee80211_sta_he_cap *he_cap; -+ const struct ieee80211_sta_eht_cap *eht_cap; - struct cfg80211_chan_def he_chandef = *chandef; - const struct ieee80211_he_6ghz_oper *he_6ghz_oper; - enum nl80211_regulatory_power_modes mode; - struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; -- bool support_80_80, support_160; -- u8 he_phy_cap; -+ bool support_80_80, support_160, support_320; -+ u8 he_phy_cap, eht_phy_cap; - u32 freq; - u8 reg_info; - u8 reg_6g_power_mode; -@@ -3449,6 +3470,12 @@ bool ieee80211_chandef_he_6ghz_oper(stru - return false; - } - -+ eht_cap = ieee80211_get_eht_iftype_cap(sband, iftype); -+ if (!eht_cap) { -+ sdata_info(sdata, "Missing iftype sband data/EHT cap"); -+ eht_oper = NULL; -+ } -+ - he_6ghz_oper = ieee80211_he_6ghz_oper(he_oper); - - if (!he_6ghz_oper) { -@@ -3477,6 +3504,11 @@ bool ieee80211_chandef_he_6ghz_oper(stru - } else - mode = 3 * (1 + reg_6g_power_mode) + reg_info; - -+ /* -+ * The EHT operation IE does not contain the primary channel so the -+ * primary channel frequency should be taken from the 6 GHz operation -+ * information. -+ */ - freq = ieee80211_channel_to_frequency(he_6ghz_oper->primary, - NL80211_BAND_6GHZ); - he_chandef.chan = ieee80211_get_6g_channel_khz(sdata->local->hw.wiphy, -@@ -3495,43 +3527,80 @@ bool ieee80211_chandef_he_6ghz_oper(stru - break; - } - -- switch (u8_get_bits(he_6ghz_oper->control, -- IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH)) { -- case IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_20MHZ: -- he_chandef.width = NL80211_CHAN_WIDTH_20; -- break; -- case IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_40MHZ: -- he_chandef.width = NL80211_CHAN_WIDTH_40; -- break; -- case IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_80MHZ: -- he_chandef.width = NL80211_CHAN_WIDTH_80; -- break; -- case IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_160MHZ: -- he_chandef.width = NL80211_CHAN_WIDTH_80; -- if (!he_6ghz_oper->ccfs1) -+ if (!eht_oper) { -+ switch (u8_get_bits(he_6ghz_oper->control, -+ IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH)) { -+ case IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_20MHZ: -+ he_chandef.width = NL80211_CHAN_WIDTH_20; -+ break; -+ case IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_40MHZ: -+ he_chandef.width = NL80211_CHAN_WIDTH_40; -+ break; -+ case IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_80MHZ: -+ he_chandef.width = NL80211_CHAN_WIDTH_80; -+ break; -+ case IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_160MHZ: -+ he_chandef.width = NL80211_CHAN_WIDTH_80; -+ if (!he_6ghz_oper->ccfs1) -+ break; -+ if (abs(he_6ghz_oper->ccfs1 - he_6ghz_oper->ccfs0) == 8) { -+ if (support_160) -+ he_chandef.width = NL80211_CHAN_WIDTH_160; -+ } else { -+ if (support_80_80) -+ he_chandef.width = NL80211_CHAN_WIDTH_80P80; -+ } -+ break; -+ } -+ -+ if (he_chandef.width == NL80211_CHAN_WIDTH_160) { -+ he_chandef.center_freq1 = -+ ieee80211_channel_to_frequency(he_6ghz_oper->ccfs1, -+ NL80211_BAND_6GHZ); -+ } else { -+ he_chandef.center_freq1 = -+ ieee80211_channel_to_frequency(he_6ghz_oper->ccfs0, -+ NL80211_BAND_6GHZ); -+ if (support_80_80 || support_160) -+ he_chandef.center_freq2 = -+ ieee80211_channel_to_frequency(he_6ghz_oper->ccfs1, -+ NL80211_BAND_6GHZ); -+ } -+ } else { -+ eht_phy_cap = eht_cap->eht_cap_elem.phy_cap_info[0]; -+ support_320 = -+ eht_phy_cap & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ; -+ -+ switch (u8_get_bits(eht_oper->chan_width, -+ IEEE80211_EHT_OPER_CHAN_WIDTH)) { -+ case IEEE80211_EHT_OPER_CHAN_WIDTH_20MHZ: -+ he_chandef.width = NL80211_CHAN_WIDTH_20; -+ break; -+ case IEEE80211_EHT_OPER_CHAN_WIDTH_40MHZ: -+ he_chandef.width = NL80211_CHAN_WIDTH_40; -+ break; -+ case IEEE80211_EHT_OPER_CHAN_WIDTH_80MHZ: -+ he_chandef.width = NL80211_CHAN_WIDTH_80; - break; -- if (abs(he_6ghz_oper->ccfs1 - he_6ghz_oper->ccfs0) == 8) { -+ case IEEE80211_EHT_OPER_CHAN_WIDTH_160MHZ: - if (support_160) - he_chandef.width = NL80211_CHAN_WIDTH_160; -- } else { -- if (support_80_80) -- he_chandef.width = NL80211_CHAN_WIDTH_80P80; -+ else -+ he_chandef.width = NL80211_CHAN_WIDTH_80; -+ break; -+ case IEEE80211_EHT_OPER_CHAN_WIDTH_320MHZ: -+ if (support_320) -+ he_chandef.width = NL80211_CHAN_WIDTH_320; -+ else if (support_160) -+ he_chandef.width = NL80211_CHAN_WIDTH_160; -+ else -+ he_chandef.width = NL80211_CHAN_WIDTH_80; -+ break; - } -- break; -- } - -- if (he_chandef.width == NL80211_CHAN_WIDTH_160) { -- he_chandef.center_freq1 = -- ieee80211_channel_to_frequency(he_6ghz_oper->ccfs1, -- NL80211_BAND_6GHZ); -- } else { - he_chandef.center_freq1 = -- ieee80211_channel_to_frequency(he_6ghz_oper->ccfs0, -+ ieee80211_channel_to_frequency(eht_oper->ccfs, - NL80211_BAND_6GHZ); -- if (support_80_80 || support_160) -- he_chandef.center_freq2 = -- ieee80211_channel_to_frequency(he_6ghz_oper->ccfs1, -- NL80211_BAND_6GHZ); - } - - if (!cfg80211_chandef_valid(&he_chandef)) { -@@ -4038,6 +4107,15 @@ u32 ieee80211_chandef_downgrade(struct c - ret = IEEE80211_STA_DISABLE_80P80MHZ | - IEEE80211_STA_DISABLE_160MHZ; - break; -+ case NL80211_CHAN_WIDTH_320: -+ /* n_P20 */ -+ tmp = (150 + c->chan->center_freq - c->center_freq1) / 20; -+ /* n_P160 */ -+ tmp /= 8; -+ c->center_freq1 = c->center_freq1 - 80 + 160 * tmp; -+ c->width = NL80211_CHAN_WIDTH_160; -+ ret = IEEE80211_STA_DISABLE_320MHZ; -+ break; - default: - case NL80211_CHAN_WIDTH_20_NOHT: - WARN_ON_ONCE(1); -Index: b/net/mac80211/vht.c -=================================================================== ---- a/net/mac80211/vht.c 2022-04-22 16:11:14.603977642 +0530 -+++ b/net/mac80211/vht.c 2022-04-22 16:11:14.603977642 +0530 -@@ -4,7 +4,7 @@ - * - * Portions of this file - * Copyright(c) 2015 - 2016 Intel Deutschland GmbH -- * Copyright (C) 2018 - 2020 Intel Corporation -+ * Copyright (C) 2018 - 2021 Intel Corporation - */ - - #include -@@ -436,6 +436,8 @@ ieee80211_chan_width_to_rx_bw(enum nl802 - case NL80211_CHAN_WIDTH_160: - case NL80211_CHAN_WIDTH_80P80: - return IEEE80211_STA_RX_BW_160; -+ case NL80211_CHAN_WIDTH_320: -+ return IEEE80211_STA_RX_BW_320; - default: - WARN_ON_ONCE(1); - return IEEE80211_STA_RX_BW_20; diff --git a/feeds/ipq95xx/mac80211/patches/qca/555-mac80211-Add-EHT-capabilities-to-association-probe-r.patch b/feeds/ipq95xx/mac80211/patches/qca/555-mac80211-Add-EHT-capabilities-to-association-probe-r.patch deleted file mode 100644 index fc6e941a4..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/555-mac80211-Add-EHT-capabilities-to-association-probe-r.patch +++ /dev/null @@ -1,257 +0,0 @@ -From 11d782b5d8b637c36aea693b18969e9fd4c6897b Mon Sep 17 00:00:00 2001 -From: Ilan Peer -Date: Mon, 14 Feb 2022 17:30:01 +0100 -Subject: [PATCH 14/19] mac80211: Add EHT capabilities to association/probe - request - -Add the EHT capabilities element to both probe request and -association request frames, if advertised by the driver. - -Signed-off-by: Ilan Peer -Signed-off-by: Johannes Berg ---- - net/mac80211/ieee80211_i.h | 5 +++ - net/mac80211/main.c | 14 ++++++- - net/mac80211/mlme.c | 48 ++++++++++++++++++++++- - net/mac80211/util.c | 79 ++++++++++++++++++++++++++++++++++++++ - 4 files changed, 144 insertions(+), 2 deletions(-) - -diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h -index b64bcdd4550e..c56c4b13f4dd 100644 ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -2524,4 +2524,9 @@ u32 ieee80211_calc_expected_tx_airtime(struct ieee80211_hw *hw, - void ieee80211_init_frag_cache(struct ieee80211_fragment_cache *cache); - void ieee80211_destroy_frag_cache(struct ieee80211_fragment_cache *cache); - -+u8 ieee80211_ie_len_eht_cap(struct ieee80211_sub_if_data *sdata, u8 iftype); -+u8 *ieee80211_ie_build_eht_cap(u8 *pos, -+ const struct ieee80211_sta_he_cap *he_cap, -+ const struct ieee80211_sta_eht_cap *eht_cap, -+ u8 *end); - #endif /* IEEE80211_I_H */ -diff --git a/net/mac80211/main.c b/net/mac80211/main.c -index d49c44cc171f..289b7e835995 100644 ---- a/net/mac80211/main.c -+++ b/net/mac80211/main.c -@@ -909,7 +909,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) - int result, i; - enum nl80211_band band; - int channels, max_bitrates; -- bool supp_ht, supp_vht, supp_he; -+ bool supp_ht, supp_vht, supp_he, supp_eht; - struct cfg80211_chan_def dflt_chandef = {}; - - if (ieee80211_hw_check(hw, QUEUE_CONTROL) && -@@ -978,6 +978,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) - supp_ht = false; - supp_vht = false; - supp_he = false; -+ supp_eht = false; - for (band = 0; band < NUM_NL80211_BANDS; band++) { - struct ieee80211_supported_band *sband; - -@@ -1021,6 +1022,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) - iftd = &sband->iftype_data[i]; - - supp_he = supp_he || iftd->he_cap.has_he; -+ supp_eht = supp_eht || iftd->eht_cap.has_eht; - } - - /* HT, VHT, HE require QoS, thus >= 4 queues */ -@@ -1028,6 +1030,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) - (supp_ht || supp_vht || supp_he))) - return -EINVAL; - -+ /* EHT requires HE support */ -+ if (WARN_ON(supp_eht && !supp_he)) -+ return -EINVAL; -+ - if (!sband->ht_cap.ht_supported) - continue; - -@@ -1134,6 +1140,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) - 3 + sizeof(struct ieee80211_he_cap_elem) + - sizeof(struct ieee80211_he_mcs_nss_supp) + - IEEE80211_HE_PPE_THRES_MAX_LEN; -+ -+ if (supp_eht) -+ local->scan_ies_len += -+ 3 + sizeof(struct ieee80211_eht_cap_elem) + -+ sizeof(struct ieee80211_eht_mcs_nss_supp) + -+ IEEE80211_EHT_PPE_THRES_MAX_LEN; - } - - if (!local->ops->hw_scan) { -diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c -index b8c0de56daf2..161779b2296e 100644 ---- a/net/mac80211/mlme.c -+++ b/net/mac80211/mlme.c -@@ -687,6 +687,48 @@ static void ieee80211_add_he_ie(struct ieee80211_sub_if_data *sdata, - ieee80211_ie_build_he_6ghz_cap(sdata, skb); - } - -+static void ieee80211_add_eht_ie(struct ieee80211_sub_if_data *sdata, -+ struct sk_buff *skb, -+ struct ieee80211_supported_band *sband) -+{ -+ u8 *pos; -+ const struct ieee80211_sta_he_cap *he_cap; -+ const struct ieee80211_sta_eht_cap *eht_cap; -+ struct ieee80211_chanctx_conf *chanctx_conf; -+ u8 eht_cap_size; -+ bool reg_cap = false; -+ -+ rcu_read_lock(); -+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); -+ if (!WARN_ON_ONCE(!chanctx_conf)) -+ reg_cap = cfg80211_chandef_usable(sdata->wdev.wiphy, -+ &chanctx_conf->def, -+ IEEE80211_CHAN_NO_HE | -+ IEEE80211_CHAN_NO_EHT); -+ rcu_read_unlock(); -+ -+ he_cap = ieee80211_get_he_iftype_cap(sband, -+ ieee80211_vif_type_p2p(&sdata->vif)); -+ eht_cap = ieee80211_get_eht_iftype_cap(sband, -+ ieee80211_vif_type_p2p(&sdata->vif)); -+ -+ /* -+ * EHT capabilities element is only added if the HE capabilities element -+ * was added so assume that 'he_cap' is valid and don't check it. -+ */ -+ if (WARN_ON(!he_cap || !eht_cap || !reg_cap)) -+ return; -+ -+ eht_cap_size = -+ 2 + 1 + sizeof(eht_cap->eht_cap_elem) + -+ ieee80211_eht_mcs_nss_size(&he_cap->he_cap_elem, -+ &eht_cap->eht_cap_elem) + -+ ieee80211_eht_ppe_size(eht_cap->eht_ppe_thres[0], -+ eht_cap->eht_cap_elem.phy_cap_info); -+ pos = skb_put(skb, eht_cap_size); -+ ieee80211_ie_build_eht_cap(pos, he_cap, eht_cap, pos + eht_cap_size); -+} -+ - static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) - { - struct ieee80211_local *local = sdata->local; -@@ -1015,9 +1057,13 @@ skip_rates: - ifmgd->flags |= IEEE80211_STA_DISABLE_HE | - IEEE80211_STA_DISABLE_EHT; - -- if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HE)) -+ if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HE)) { - ieee80211_add_he_ie(sdata, skb, sband); - -+ if (!(ifmgd->flags & IEEE80211_STA_DISABLE_EHT)) -+ ieee80211_add_eht_ie(sdata, skb, sband); -+ } -+ - /* if present, add any custom non-vendor IEs that go after HE */ - if (assoc_data->ie_len) { - noffset = ieee80211_ie_split_vendor(assoc_data->ie, -diff --git a/net/mac80211/util.c b/net/mac80211/util.c -index e4715761545f..3aade17ea6c4 100644 ---- a/net/mac80211/util.c -+++ b/net/mac80211/util.c -@@ -1810,6 +1810,7 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_sub_if_data *sdata, - struct ieee80211_local *local = sdata->local; - struct ieee80211_supported_band *sband; - const struct ieee80211_sta_he_cap *he_cap; -+ const struct ieee80211_sta_eht_cap *eht_cap; - u8 *pos = buffer, *end = buffer + buffer_len; - size_t noffset; - int supp_rates_len, i; -@@ -1990,6 +1991,18 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_sub_if_data *sdata, - goto out_err; - } - -+ eht_cap = ieee80211_get_eht_iftype_cap(sband, -+ ieee80211_vif_type_p2p(&sdata->vif)); -+ -+ if (eht_cap && -+ cfg80211_any_usable_channels(local->hw.wiphy, BIT(sband->band), -+ IEEE80211_CHAN_NO_HE | -+ IEEE80211_CHAN_NO_EHT)) { -+ pos = ieee80211_ie_build_eht_cap(pos, he_cap, eht_cap, end); -+ if (!pos) -+ goto out_err; -+ } -+ - if (cfg80211_any_usable_channels(local->hw.wiphy, - BIT(NL80211_BAND_6GHZ), - IEEE80211_CHAN_NO_HE)) { -@@ -4722,3 +4735,69 @@ u16 ieee80211_encode_usf(int listen_interval) - - return (u16) listen_interval; - } -+ -+u8 ieee80211_ie_len_eht_cap(struct ieee80211_sub_if_data *sdata, u8 iftype) -+{ -+ const struct ieee80211_sta_he_cap *he_cap; -+ const struct ieee80211_sta_eht_cap *eht_cap; -+ struct ieee80211_supported_band *sband; -+ u8 n; -+ -+ sband = ieee80211_get_sband(sdata); -+ if (!sband) -+ return 0; -+ -+ he_cap = ieee80211_get_he_iftype_cap(sband, iftype); -+ eht_cap = ieee80211_get_eht_iftype_cap(sband, iftype); -+ if (!he_cap || !eht_cap) -+ return 0; -+ -+ n = ieee80211_eht_mcs_nss_size(&he_cap->he_cap_elem, -+ &eht_cap->eht_cap_elem); -+ return 2 + 1 + -+ sizeof(he_cap->he_cap_elem) + n + -+ ieee80211_eht_ppe_size(eht_cap->eht_ppe_thres[0], -+ eht_cap->eht_cap_elem.phy_cap_info); -+ return 0; -+} -+ -+u8 *ieee80211_ie_build_eht_cap(u8 *pos, -+ const struct ieee80211_sta_he_cap *he_cap, -+ const struct ieee80211_sta_eht_cap *eht_cap, -+ u8 *end) -+{ -+ u8 mcs_nss_len, ppet_len; -+ u8 ie_len; -+ u8 *orig_pos = pos; -+ -+ /* Make sure we have place for the IE */ -+ if (!he_cap || !eht_cap) -+ return orig_pos; -+ -+ mcs_nss_len = ieee80211_eht_mcs_nss_size(&he_cap->he_cap_elem, -+ &eht_cap->eht_cap_elem); -+ ppet_len = ieee80211_eht_ppe_size(eht_cap->eht_ppe_thres[0], -+ eht_cap->eht_cap_elem.phy_cap_info); -+ -+ ie_len = 2 + 1 + sizeof(eht_cap->eht_cap_elem) + mcs_nss_len + ppet_len; -+ if ((end - pos) < ie_len) -+ return orig_pos; -+ -+ *pos++ = WLAN_EID_EXTENSION; -+ *pos++ = ie_len - 2; -+ *pos++ = WLAN_EID_EXT_EHT_CAPABILITY; -+ -+ /* Fixed data */ -+ memcpy(pos, &eht_cap->eht_cap_elem, sizeof(eht_cap->eht_cap_elem)); -+ pos += sizeof(eht_cap->eht_cap_elem); -+ -+ memcpy(pos, &eht_cap->eht_mcs_nss_supp, mcs_nss_len); -+ pos += mcs_nss_len; -+ -+ if (ppet_len) { -+ memcpy(pos, &eht_cap->eht_ppe_thres, ppet_len); -+ pos += ppet_len; -+ } -+ -+ return pos; -+} --- -2.31.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/556-mac80211-Handle-station-association-response-with-EH.patch b/feeds/ipq95xx/mac80211/patches/qca/556-mac80211-Handle-station-association-response-with-EH.patch deleted file mode 100644 index 3fb8b8498..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/556-mac80211-Handle-station-association-response-with-EH.patch +++ /dev/null @@ -1,220 +0,0 @@ -From b74956c25f5287b41ffbbfb0f61b42eb063764a3 Mon Sep 17 00:00:00 2001 -From: Ilan Peer -Date: Mon, 14 Feb 2022 17:30:02 +0100 -Subject: [PATCH 15/19] mac80211: Handle station association response with EHT - -When the association is an EHT association, parse the EHT -element from the association response and update the -station's EHT capabilities accordingly. - -Signed-off-by: Ilan Peer -Signed-off-by: Johannes Berg ---- - include/net/mac80211.h | 4 ++ - net/mac80211/Makefile | 3 +- - net/mac80211/eht.c | 76 ++++++++++++++++++++++++++++++++++++++ - net/mac80211/ieee80211_i.h | 7 ++++ - net/mac80211/mlme.c | 15 ++++++++ - net/mac80211/vht.c | 16 +++++++- - 6 files changed, 118 insertions(+), 3 deletions(-) - create mode 100644 net/mac80211/eht.c - ---- a/include/net/mac80211.h -+++ b/include/net/mac80211.h -@@ -667,6 +667,7 @@ struct ieee80211_fils_discovery { - * @pwr_reduction: power constraint of BSS. - * @nss_ap_isolate: Used for notifying the NSS host about AP isolate feature - * @beacon_tx_mode: Beacon Tx Mode setting. -+ * @eht_support: does this BSS support EHT - */ - struct ieee80211_bss_conf { - const u8 *bssid; -@@ -748,6 +749,7 @@ struct ieee80211_bss_conf { - u8 pwr_reduction; - bool nss_ap_isolate; - enum nl80211_beacon_tx_mode beacon_tx_mode; -+ bool eht_support; - - /* Mesh configuration for nss offload */ - u8 nss_offld_ttl; -@@ -2144,6 +2146,7 @@ struct ieee80211_sta_txpwr { - * @vht_cap: VHT capabilities of this STA; restricted to our own capabilities - * @he_cap: HE capabilities of this STA - * @he_6ghz_capa: on 6 GHz, holds the HE 6 GHz band capabilities -+ * @eht_cap: EHT capabilities of this STA - * @max_rx_aggregation_subframes: maximal amount of frames in a single AMPDU - * that this station is allowed to transmit to us. - * Can be modified by driver. -@@ -2184,6 +2187,7 @@ struct ieee80211_sta { - struct ieee80211_sta_vht_cap vht_cap; - struct ieee80211_sta_he_cap he_cap; - struct ieee80211_he_6ghz_capa he_6ghz_capa; -+ struct ieee80211_sta_eht_cap eht_cap; - u16 max_rx_aggregation_subframes; - bool wme; - u8 uapsd_queues; ---- a/net/mac80211/Makefile -+++ b/net/mac80211/Makefile -@@ -34,7 +34,8 @@ mac80211-y := \ - trace.o mlme.o \ - tdls.o \ - ocb.o \ -- airtime.o -+ airtime.o \ -+ eht.o - - mac80211-$(CPTCFG_MAC80211_LEDS) += led.o - mac80211-$(CPTCFG_MAC80211_DEBUGFS) += \ ---- /dev/null -+++ b/net/mac80211/eht.c -@@ -0,0 +1,76 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * EHT handling -+ * -+ * Copyright(c) 2021-2022 Intel Corporation -+ */ -+ -+#include "ieee80211_i.h" -+ -+void -+ieee80211_eht_cap_ie_to_sta_eht_cap(struct ieee80211_sub_if_data *sdata, -+ struct ieee80211_supported_band *sband, -+ const u8 *he_cap_ie, u8 he_cap_len, -+ const struct ieee80211_eht_cap_elem *eht_cap_ie_elem, -+ u8 eht_cap_len, struct sta_info *sta) -+{ -+ struct ieee80211_sta_eht_cap *eht_cap = &sta->sta.eht_cap; -+ struct ieee80211_he_cap_elem *he_cap_ie_elem = (void *)he_cap_ie; -+ u8 eht_ppe_size = 0; -+ u8 mcs_nss_size; -+ u8 eht_total_size = sizeof(eht_cap->eht_cap_elem); -+ u8 *pos = (u8 *)eht_cap_ie_elem; -+ -+ memset(eht_cap, 0, sizeof(*eht_cap)); -+ -+ if (!eht_cap_ie_elem || -+ !ieee80211_get_eht_iftype_cap(sband, -+ ieee80211_vif_type_p2p(&sdata->vif))) -+ return; -+ -+ mcs_nss_size = ieee80211_eht_mcs_nss_size(he_cap_ie_elem, -+ &eht_cap_ie_elem->fixed); -+ -+ eht_total_size += mcs_nss_size; -+ -+ /* Calculate the PPE thresholds length only if the header is present */ -+ if (eht_cap_ie_elem->fixed.phy_cap_info[5] & -+ IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT) { -+ u16 eht_ppe_hdr; -+ -+ if (eht_cap_len < eht_total_size + sizeof(u16)) -+ return; -+ -+ eht_ppe_hdr = get_unaligned_le16(eht_cap_ie_elem->optional + mcs_nss_size); -+ eht_ppe_size = -+ ieee80211_eht_ppe_size(eht_ppe_hdr, -+ eht_cap_ie_elem->fixed.phy_cap_info); -+ eht_total_size += eht_ppe_size; -+ -+ /* we calculate as if NSS > 8 are valid, but don't handle that */ -+ if (eht_ppe_size > sizeof(eht_cap->eht_ppe_thres)) -+ return; -+ } -+ -+ if (eht_cap_len < eht_total_size) -+ return; -+ -+ /* Copy the static portion of the EHT capabilities */ -+ memcpy(&eht_cap->eht_cap_elem, pos, sizeof(eht_cap->eht_cap_elem)); -+ pos += sizeof(eht_cap->eht_cap_elem); -+ -+ /* Copy MCS/NSS which depends on the peer capabilities */ -+ memset(&eht_cap->eht_mcs_nss_supp, 0, -+ sizeof(eht_cap->eht_mcs_nss_supp)); -+ memcpy(&eht_cap->eht_mcs_nss_supp, pos, mcs_nss_size); -+ -+ if (eht_ppe_size) -+ memcpy(eht_cap->eht_ppe_thres, -+ &eht_cap_ie_elem->optional[mcs_nss_size], -+ eht_ppe_size); -+ -+ eht_cap->has_eht = true; -+ -+ sta->cur_max_bandwidth = ieee80211_sta_cap_rx_bw(sta); -+ sta->sta.bandwidth = ieee80211_sta_cur_vht_bw(sta); -+} ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -2555,4 +2555,11 @@ u8 *ieee80211_ie_build_eht_cap(u8 *pos, - const struct ieee80211_sta_he_cap *he_cap, - const struct ieee80211_sta_eht_cap *eht_cap, - u8 *end); -+ -+void -+ieee80211_eht_cap_ie_to_sta_eht_cap(struct ieee80211_sub_if_data *sdata, -+ struct ieee80211_supported_band *sband, -+ const u8 *he_cap_ie, u8 he_cap_len, -+ const struct ieee80211_eht_cap_elem *eht_cap_ie_elem, -+ u8 eht_cap_len, struct sta_info *sta); - #endif /* IEEE80211_I_H */ ---- a/net/mac80211/mlme.c -+++ b/net/mac80211/mlme.c -@@ -3574,10 +3574,25 @@ static bool ieee80211_assoc_success(stru - bss_conf->twt_protected = false; - - changed |= ieee80211_recalc_twt_req(sdata, sta, elems); -+ -+ if (elems->eht_operation && elems->eht_cap && -+ !(ifmgd->flags & IEEE80211_STA_DISABLE_EHT)) { -+ ieee80211_eht_cap_ie_to_sta_eht_cap(sdata, sband, -+ elems->he_cap, -+ elems->he_cap_len, -+ elems->eht_cap, -+ elems->eht_cap_len, -+ sta); -+ -+ bss_conf->eht_support = sta->sta.eht_cap.has_eht; -+ } else { -+ bss_conf->eht_support = false; -+ } - } else { - bss_conf->he_support = false; - bss_conf->twt_requester = false; - bss_conf->twt_protected = false; -+ bss_conf->eht_support = false; - } - - bss_conf->twt_broadcast = ---- a/net/mac80211/vht.c -+++ b/net/mac80211/vht.c -@@ -314,15 +314,27 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(stru - } - } - --/* FIXME: move this to some better location - parses HE now */ -+/* FIXME: move this to some better location - parses HE/EHT now */ - enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta) - { - struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.vht_cap; - struct ieee80211_sta_he_cap *he_cap = &sta->sta.he_cap; -+ struct ieee80211_sta_eht_cap *eht_cap = &sta->sta.eht_cap; - u32 cap_width; - - if (he_cap->has_he) { -- u8 info = he_cap->he_cap_elem.phy_cap_info[0]; -+ u8 info; -+ -+ if (eht_cap->has_eht && -+ sta->sdata->vif.bss_conf.chandef.chan->band == -+ NL80211_BAND_6GHZ) { -+ info = eht_cap->eht_cap_elem.phy_cap_info[0]; -+ -+ if (info & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ) -+ return IEEE80211_STA_RX_BW_320; -+ } -+ -+ info = he_cap->he_cap_elem.phy_cap_info[0]; - - if (sta->sdata->vif.bss_conf.chandef.chan->band == - NL80211_BAND_2GHZ) { diff --git a/feeds/ipq95xx/mac80211/patches/qca/557-mac80211-Add-support-for-storing-station-EHT-capabil.patch b/feeds/ipq95xx/mac80211/patches/qca/557-mac80211-Add-support-for-storing-station-EHT-capabil.patch deleted file mode 100644 index fb7b81b69..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/557-mac80211-Add-support-for-storing-station-EHT-capabil.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 6ccc5460dd590459c261a03ca07a7098a6f4e2f6 Mon Sep 17 00:00:00 2001 -From: Ilan Peer -Date: Mon, 14 Feb 2022 17:30:03 +0100 -Subject: [PATCH 16/19] mac80211: Add support for storing station EHT - capabilities - -When a station configuration is updated, also update the station -EHT capabilities. - -Signed-off-by: Ilan Peer -Signed-off-by: Johannes Berg ---- - net/mac80211/cfg.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c -index aac4115e0767..d4738199003c 100644 ---- a/net/mac80211/cfg.c -+++ b/net/mac80211/cfg.c -@@ -1730,6 +1730,14 @@ static int sta_apply_parameters(struct ieee80211_local *local, - (void *)params->he_6ghz_capa, - sta); - -+ if (params->eht_capa) -+ ieee80211_eht_cap_ie_to_sta_eht_cap(sdata, sband, -+ (u8 *)params->he_capa, -+ params->he_capa_len, -+ params->eht_capa, -+ params->eht_capa_len, -+ sta); -+ - if (params->opmode_notif_used) { - /* returned value is only needed for rc update, but the - * rc isn't initialized here yet, so ignore it --- -2.31.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/558-mac80211-calculate-max-RX-NSS-for-EHT-mode.patch b/feeds/ipq95xx/mac80211/patches/qca/558-mac80211-calculate-max-RX-NSS-for-EHT-mode.patch deleted file mode 100644 index e9f168586..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/558-mac80211-calculate-max-RX-NSS-for-EHT-mode.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 12ddf0558a8001b119f4b06b14f6901afdc28384 Mon Sep 17 00:00:00 2001 -From: Mordechay Goodstein -Date: Mon, 14 Feb 2022 17:30:04 +0100 -Subject: [PATCH 17/19] mac80211: calculate max RX NSS for EHT mode - -If the station supports EHT mode, calculate the maximum RX NSS -from EHT station capabilities. - -Signed-off-by: Mordechay Goodstein -Signed-off-by: Johannes Berg ---- - net/mac80211/vht.c | 14 +++++++++++++- - 1 file changed, 13 insertions(+), 1 deletion(-) - -diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c -index 9060ff2bd06c..33fc189e1da8 100644 ---- a/net/mac80211/vht.c -+++ b/net/mac80211/vht.c -@@ -497,13 +497,24 @@ enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta) - - void ieee80211_sta_set_rx_nss(struct sta_info *sta) - { -- u8 ht_rx_nss = 0, vht_rx_nss = 0, he_rx_nss = 0, rx_nss; -+ u8 ht_rx_nss = 0, vht_rx_nss = 0, he_rx_nss = 0, eht_rx_nss = 0, rx_nss; - bool support_160; - - /* if we received a notification already don't overwrite it */ - if (sta->sta.rx_nss) - return; - -+ if (sta->sta.eht_cap.has_eht) { -+ int i; -+ const u8 *rx_nss_mcs = (void *)&sta->sta.eht_cap.eht_mcs_nss_supp; -+ -+ /* get the max nss for EHT over all possible bandwidths and mcs */ -+ for (i = 0; i < sizeof(struct ieee80211_eht_mcs_nss_supp); i++) -+ eht_rx_nss = max_t(u8, eht_rx_nss, -+ u8_get_bits(rx_nss_mcs[i], -+ IEEE80211_EHT_MCS_NSS_RX)); -+ } -+ - if (sta->sta.he_cap.has_he) { - int i; - u8 rx_mcs_80 = 0, rx_mcs_160 = 0; -@@ -569,6 +580,7 @@ void ieee80211_sta_set_rx_nss(struct sta_info *sta) - - rx_nss = max(vht_rx_nss, ht_rx_nss); - rx_nss = max(he_rx_nss, rx_nss); -+ rx_nss = max(eht_rx_nss, rx_nss); - sta->sta.rx_nss = max_t(u8, 1, rx_nss); - } - --- -2.31.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/559-mac80211-parse-AddBA-request-with-extended-AddBA-ele.patch b/feeds/ipq95xx/mac80211/patches/qca/559-mac80211-parse-AddBA-request-with-extended-AddBA-ele.patch deleted file mode 100644 index 2f50af179..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/559-mac80211-parse-AddBA-request-with-extended-AddBA-ele.patch +++ /dev/null @@ -1,76 +0,0 @@ -From bc043dd0138c79c8add16e08eb3c6c032106aab6 Mon Sep 17 00:00:00 2001 -From: Mordechay Goodstein -Date: Mon, 14 Feb 2022 17:30:05 +0100 -Subject: [PATCH 18/19] mac80211: parse AddBA request with extended AddBA - element - -In EHT requesting aggregation with 1K needs the use of extended -the AddBA element for the buffer size, so add the logic to parse -it and make sure it's in limits of the EHT aggregation size. - -Signed-off-by: Mordechay Goodstein -Signed-off-by: Johannes Berg ---- - net/mac80211/agg-rx.c | 18 +++++++++++++++--- - 1 file changed, 15 insertions(+), 3 deletions(-) - -diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c -index 0d2bab9d351c..218cdc554d71 100644 ---- a/net/mac80211/agg-rx.c -+++ b/net/mac80211/agg-rx.c -@@ -180,7 +180,8 @@ static void sta_rx_agg_reorder_timer_expired(struct timer_list *t) - - static void ieee80211_add_addbaext(struct ieee80211_sub_if_data *sdata, - struct sk_buff *skb, -- const struct ieee80211_addba_ext_ie *req) -+ const struct ieee80211_addba_ext_ie *req, -+ u16 buf_size) - { - struct ieee80211_supported_band *sband; - struct ieee80211_addba_ext_ie *resp; -@@ -210,6 +211,8 @@ static void ieee80211_add_addbaext(struct ieee80211_sub_if_data *sdata, - frag_level = cap_frag_level; - resp->data |= u8_encode_bits(frag_level, - IEEE80211_ADDBA_EXT_FRAG_LEVEL_MASK); -+ resp->data |= u8_encode_bits(buf_size >> IEEE80211_ADDBA_EXT_BUF_SIZE_SHIFT, -+ IEEE80211_ADDBA_EXT_BUF_SIZE_MASK); - } - - static void ieee80211_send_addba_resp(struct sta_info *sta, u8 *da, u16 tid, -@@ -261,7 +264,7 @@ static void ieee80211_send_addba_resp(struct sta_info *sta, u8 *da, u16 tid, - mgmt->u.action.u.addba_resp.status = cpu_to_le16(status); - - if (sta->sta.he_cap.has_he && addbaext) -- ieee80211_add_addbaext(sdata, skb, addbaext); -+ ieee80211_add_addbaext(sdata, skb, addbaext, buf_size); - - ieee80211_tx_skb(sdata, skb); - } -@@ -309,7 +312,9 @@ void ___ieee80211_start_rx_ba_session(struct sta_info *sta, - goto end; - } - -- if (sta->sta.he_cap.has_he) -+ if (sta->sta.eht_cap.has_eht) -+ max_buf_size = IEEE80211_MAX_AMPDU_BUF_EHT; -+ else if (sta->sta.he_cap.has_he) - max_buf_size = IEEE80211_MAX_AMPDU_BUF_HE; - else - max_buf_size = IEEE80211_MAX_AMPDU_BUF_HT; -@@ -502,6 +507,13 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, - goto free; - } - -+ if (sta->sta.eht_cap.has_eht && elems && elems->addba_ext_ie) { -+ u8 buf_size_1k = u8_get_bits(elems->addba_ext_ie->data, -+ IEEE80211_ADDBA_EXT_BUF_SIZE_MASK); -+ -+ buf_size |= buf_size_1k << IEEE80211_ADDBA_EXT_BUF_SIZE_SHIFT; -+ } -+ - __ieee80211_start_rx_ba_session(sta, dialog_token, timeout, - start_seq_num, ba_policy, tid, - buf_size, true, false, --- -2.31.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/560-mac80211_hwsim-Advertise-support-for-EHT-capabilitie.patch b/feeds/ipq95xx/mac80211/patches/qca/560-mac80211_hwsim-Advertise-support-for-EHT-capabilitie.patch deleted file mode 100644 index aa3838014..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/560-mac80211_hwsim-Advertise-support-for-EHT-capabilitie.patch +++ /dev/null @@ -1,256 +0,0 @@ -From 399c5e1f3c181a1de8463b21523152a1a899a673 Mon Sep 17 00:00:00 2001 -From: Ilan Peer -Date: Mon, 14 Feb 2022 17:30:06 +0100 -Subject: [PATCH 19/19] mac80211_hwsim: Advertise support for EHT capabilities - -Add EHT capabilities to bands. - -Signed-off-by: Ilan Peer -Signed-off-by: Johannes Berg ---- - drivers/net/wireless/mac80211_hwsim.c | 171 ++++++++++++++++++++++++-- - 1 file changed, 159 insertions(+), 12 deletions(-) - -diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c -index dabc7fb0b2bf..5085783efe9c 100644 ---- a/drivers/net/wireless/mac80211_hwsim.c -+++ b/drivers/net/wireless/mac80211_hwsim.c -@@ -4,7 +4,7 @@ - * Copyright (c) 2008, Jouni Malinen - * Copyright (c) 2011, Javier Lopez - * Copyright (c) 2016 - 2017 Intel Deutschland GmbH -- * Copyright (C) 2018 - 2020 Intel Corporation -+ * Copyright (C) 2018 - 2022 Intel Corporation - */ - - /* -@@ -2912,7 +2912,7 @@ out_err: - nlmsg_free(mcast_skb); - } - --static const struct ieee80211_sband_iftype_data he_capa_2ghz[] = { -+static const struct ieee80211_sband_iftype_data sband_capa_2ghz[] = { - { - .types_mask = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_AP), -@@ -2958,6 +2958,66 @@ static const struct ieee80211_sband_iftype_data he_capa_2ghz[] = { - .tx_mcs_80p80 = cpu_to_le16(0xffff), - }, - }, -+ .eht_cap = { -+ .has_eht = true, -+ .eht_cap_elem = { -+ .mac_cap_info[0] = -+ IEEE80211_EHT_MAC_CAP0_NSEP_PRIO_ACCESS | -+ IEEE80211_EHT_MAC_CAP0_OM_CONTROL | -+ IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1, -+ .phy_cap_info[0] = -+ IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ | -+ IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI | -+ IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO | -+ IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER | -+ IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE, -+ .phy_cap_info[3] = -+ IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK | -+ IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK | -+ IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK | -+ IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK | -+ IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK | -+ IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK | -+ IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK, -+ .phy_cap_info[4] = -+ IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO | -+ IEEE80211_EHT_PHY_CAP4_PSR_SR_SUPP | -+ IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP | -+ IEEE80211_EHT_PHY_CAP4_EHT_MU_PPDU_4_EHT_LTF_08_GI | -+ IEEE80211_EHT_PHY_CAP4_MAX_NC_MASK, -+ .phy_cap_info[5] = -+ IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK | -+ IEEE80211_EHT_PHY_CAP5_TX_LESS_242_TONE_RU_SUPP | -+ IEEE80211_EHT_PHY_CAP5_RX_LESS_242_TONE_RU_SUPP | -+ IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT | -+ IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK | -+ IEEE80211_EHT_PHY_CAP5_MAX_NUM_SUPP_EHT_LTF_MASK, -+ .phy_cap_info[6] = -+ IEEE80211_EHT_PHY_CAP6_MAX_NUM_SUPP_EHT_LTF_MASK | -+ IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK, -+ .phy_cap_info[7] = -+ IEEE80211_EHT_PHY_CAP7_20MHZ_STA_RX_NDP_WIDER_BW, -+ }, -+ -+ /* For all MCS and bandwidth, set 8 NSS for both Tx and -+ * Rx -+ */ -+ .eht_mcs_nss_supp = { -+ /* -+ * Since B0, B1, B2 and B3 are not set in -+ * the supported channel width set field in the -+ * HE PHY capabilities information field the -+ * device is a 20MHz only device on 2.4GHz band. -+ */ -+ .only_20mhz = { -+ .rx_tx_mcs7_max_nss = 0x88, -+ .rx_tx_mcs9_max_nss = 0x88, -+ .rx_tx_mcs11_max_nss = 0x88, -+ .rx_tx_mcs13_max_nss = 0x88, -+ }, -+ }, -+ /* PPE threshold information is not supported */ -+ }, - }, - #ifdef CPTCFG_MAC80211_MESH - { -@@ -3000,7 +3060,7 @@ static const struct ieee80211_sband_iftype_data he_capa_2ghz[] = { - #endif - }; - --static const struct ieee80211_sband_iftype_data he_capa_5ghz[] = { -+static const struct ieee80211_sband_iftype_data sband_capa_5ghz[] = { - { - /* TODO: should we support other types, e.g., P2P?*/ - .types_mask = BIT(NL80211_IFTYPE_STATION) | -@@ -3098,7 +3158,7 @@ static const struct ieee80211_sband_iftype_data he_capa_5ghz[] = { - #endif - }; - --static const struct ieee80211_sband_iftype_data he_capa_6ghz[] = { -+static const struct ieee80211_sband_iftype_data sband_capa_6ghz[] = { - { - /* TODO: should we support other types, e.g., P2P?*/ - .types_mask = BIT(NL80211_IFTYPE_STATION) | -@@ -3158,6 +3218,93 @@ static const struct ieee80211_sband_iftype_data he_capa_6ghz[] = { - .tx_mcs_80p80 = cpu_to_le16(0xfffa), - }, - }, -+ .eht_cap = { -+ .has_eht = true, -+ .eht_cap_elem = { -+ .mac_cap_info[0] = -+ IEEE80211_EHT_MAC_CAP0_NSEP_PRIO_ACCESS | -+ IEEE80211_EHT_MAC_CAP0_OM_CONTROL | -+ IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1, -+ .phy_cap_info[0] = -+ IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ | -+ IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ | -+ IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI | -+ IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO | -+ IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER | -+ IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE | -+ IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK, -+ .phy_cap_info[1] = -+ IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK | -+ IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK | -+ IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK, -+ .phy_cap_info[2] = -+ IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_80MHZ_MASK | -+ IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_160MHZ_MASK | -+ IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_320MHZ_MASK, -+ .phy_cap_info[3] = -+ IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK | -+ IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK | -+ IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK | -+ IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK | -+ IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK | -+ IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK | -+ IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK, -+ .phy_cap_info[4] = -+ IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO | -+ IEEE80211_EHT_PHY_CAP4_PSR_SR_SUPP | -+ IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP | -+ IEEE80211_EHT_PHY_CAP4_EHT_MU_PPDU_4_EHT_LTF_08_GI | -+ IEEE80211_EHT_PHY_CAP4_MAX_NC_MASK, -+ .phy_cap_info[5] = -+ IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK | -+ IEEE80211_EHT_PHY_CAP5_TX_LESS_242_TONE_RU_SUPP | -+ IEEE80211_EHT_PHY_CAP5_RX_LESS_242_TONE_RU_SUPP | -+ IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT | -+ IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK | -+ IEEE80211_EHT_PHY_CAP5_MAX_NUM_SUPP_EHT_LTF_MASK, -+ .phy_cap_info[6] = -+ IEEE80211_EHT_PHY_CAP6_MAX_NUM_SUPP_EHT_LTF_MASK | -+ IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK | -+ IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP, -+ .phy_cap_info[7] = -+ IEEE80211_EHT_PHY_CAP7_20MHZ_STA_RX_NDP_WIDER_BW | -+ IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ | -+ IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ | -+ IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_320MHZ | -+ IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ | -+ IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ | -+ IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ, -+ }, -+ -+ /* For all MCS and bandwidth, set 8 NSS for both Tx and -+ * Rx -+ */ -+ .eht_mcs_nss_supp = { -+ /* -+ * As B1 and B2 are set in the supported -+ * channel width set field in the HE PHY -+ * capabilities information field and 320MHz in -+ * 6GHz is supported include all the following -+ * MCS/NSS. -+ */ -+ .bw._80 = { -+ .rx_tx_mcs9_max_nss = 0x88, -+ .rx_tx_mcs11_max_nss = 0x88, -+ .rx_tx_mcs13_max_nss = 0x88, -+ }, -+ .bw._160 = { -+ .rx_tx_mcs9_max_nss = 0x88, -+ .rx_tx_mcs11_max_nss = 0x88, -+ .rx_tx_mcs13_max_nss = 0x88, -+ }, -+ .bw._320 = { -+ .rx_tx_mcs9_max_nss = 0x88, -+ .rx_tx_mcs11_max_nss = 0x88, -+ .rx_tx_mcs13_max_nss = 0x88, -+ }, -+ }, -+ /* PPE threshold information is not supported */ -+ }, - }, - #ifdef CPTCFG_MAC80211_MESH - { -@@ -3214,22 +3361,22 @@ static const struct ieee80211_sband_iftype_data he_capa_6ghz[] = { - #endif - }; - --static void mac80211_hwsim_he_capab(struct ieee80211_supported_band *sband) -+static void mac80211_hwsim_sband_capab(struct ieee80211_supported_band *sband) - { - u16 n_iftype_data; - - if (sband->band == NL80211_BAND_2GHZ) { -- n_iftype_data = ARRAY_SIZE(he_capa_2ghz); -+ n_iftype_data = ARRAY_SIZE(sband_capa_2ghz); - sband->iftype_data = -- (struct ieee80211_sband_iftype_data *)he_capa_2ghz; -+ (struct ieee80211_sband_iftype_data *)sband_capa_2ghz; - } else if (sband->band == NL80211_BAND_5GHZ) { -- n_iftype_data = ARRAY_SIZE(he_capa_5ghz); -+ n_iftype_data = ARRAY_SIZE(sband_capa_5ghz); - sband->iftype_data = -- (struct ieee80211_sband_iftype_data *)he_capa_5ghz; -+ (struct ieee80211_sband_iftype_data *)sband_capa_5ghz; - } else if (sband->band == NL80211_BAND_6GHZ) { -- n_iftype_data = ARRAY_SIZE(he_capa_6ghz); -+ n_iftype_data = ARRAY_SIZE(sband_capa_6ghz); - sband->iftype_data = -- (struct ieee80211_sband_iftype_data *)he_capa_6ghz; -+ (struct ieee80211_sband_iftype_data *)sband_capa_6ghz; - } else { - return; - } -@@ -3552,7 +3699,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, - sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; - } - -- mac80211_hwsim_he_capab(sband); -+ mac80211_hwsim_sband_capab(sband); - - hw->wiphy->bands[band] = sband; - } --- -2.31.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/561-nl80211-fix-attribute-definition-for-older-kernels.patch b/feeds/ipq95xx/mac80211/patches/qca/561-nl80211-fix-attribute-definition-for-older-kernels.patch index c53fbbdcf..918a115b9 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/561-nl80211-fix-attribute-definition-for-older-kernels.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/561-nl80211-fix-attribute-definition-for-older-kernels.patch @@ -13,20 +13,20 @@ Signed-off-by: Aloka Dixit --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c -@@ -812,10 +812,16 @@ static const struct nla_policy nl80211_p - [NL80211_ATTR_AWGN_INTERFERENCE_BITMAP] = { .type = NLA_U32 }, - [NL80211_ATTR_6G_REG_POWER_MODE] = NLA_POLICY_RANGE(NLA_U8, 0, 2), - [NL80211_ATTR_EMA_RNR_ELEMS] = { .type = NLA_NESTED }, +@@ -820,10 +820,16 @@ static const struct nla_policy nl80211_p + [NL80211_ATTR_MBSSID_ELEMS] = { .type = NLA_NESTED }, + [NL80211_ATTR_RADAR_BACKGROUND] = { .type = NLA_FLAG }, + [NL80211_ATTR_AP_SETTINGS_FLAGS] = { .type = NLA_U32 }, +#if LINUX_VERSION_IS_GEQ(5,10,0) [NL80211_ATTR_EHT_CAPABILITY] = - NLA_POLICY_RANGE(NLA_BINARY, - NL80211_EHT_MIN_CAPABILITY_LEN, - NL80211_EHT_MAX_CAPABILITY_LEN), + NLA_POLICY_RANGE(NLA_BINARY, + NL80211_EHT_MIN_CAPABILITY_LEN, + NL80211_EHT_MAX_CAPABILITY_LEN), +#else + [NL80211_ATTR_EHT_CAPABILITY] = + { .type = NLA_BINARY, + .len = NL80211_EHT_MAX_CAPABILITY_LEN }, +#endif - }; - - /* policy for the key attributes */ + [NL80211_ATTR_DISABLE_EHT] = { .type = NLA_FLAG }, + [NL80211_ATTR_MLO_LINKS] = + NLA_POLICY_NESTED_ARRAY(nl80211_policy), diff --git a/feeds/ipq95xx/mac80211/patches/qca/562-ath12k-use-the-macro-IEEE80211_MAX_AMPDU_BUF_HE.patch b/feeds/ipq95xx/mac80211/patches/qca/562-ath12k-use-the-macro-IEEE80211_MAX_AMPDU_BUF_HE.patch deleted file mode 100644 index 4b8d68cdc..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/562-ath12k-use-the-macro-IEEE80211_MAX_AMPDU_BUF_HE.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 4b1bac75070182002e1a7a0042b56bda8886dad5 Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Fri, 25 Feb 2022 09:28:02 -0800 -Subject: [PATCH 2/2] ath12k: use the macro IEEE80211_MAX_AMPDU_BUF_HE - -Adjust the ath12k driver to use the updated macro, -IEEE80211_MAX_AMPDU_BUF -> IEEE80211_MAX_AMPDU_BUF_HE. - -Signed-off-by: Aloka Dixit ---- - drivers/net/wireless/ath/ath12k/mac.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index b2797ca3a3cd..030f52447397 100644 ---- a/drivers/net/wireless/ath/ath12k/mac.c -+++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -7494,7 +7494,7 @@ static int __ath12k_mac_register(struct ath12k *ar) - ar->hw->queues = ATH12K_HW_MAX_QUEUES; - ar->hw->wiphy->tx_queue_len = ATH12K_QUEUE_LEN; - ar->hw->offchannel_tx_hw_queue = ATH12K_HW_MAX_QUEUES - 1; -- ar->hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; -+ ar->hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE; - - ar->hw->vif_data_size = sizeof(struct ath12k_vif); - ar->hw->sta_data_size = sizeof(struct ath12k_sta); --- -2.31.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/563-nl80211-add-support-to-send-EHT-capabilities-from-us.patch b/feeds/ipq95xx/mac80211/patches/qca/563-nl80211-add-support-to-send-EHT-capabilities-from-us.patch deleted file mode 100644 index 1d83df76d..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/563-nl80211-add-support-to-send-EHT-capabilities-from-us.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 037eb51965d6ee6891c173b5effeb98e7d91ff0f Mon Sep 17 00:00:00 2001 -From: Vikram Kandukuri -Date: Wed, 22 Dec 2021 14:34:40 +0530 -Subject: [PATCH 01/27] nl80211: add support to send EHT capabilities from - userspace - -Add support to process EHT capabilities element passed by the userspace -in beacon template and store the pointer in struct cfg80211_ap_settings. - -Add new attribute NL80211_ATTR_EHT_CAPABILITY to be used by the -userspace to pass EHT capabilities of a station trying to associate. - -Signed-off-by: Vikram Kandukuri -Signed-off-by: Aloka Dixit -Signed-off-by: Veerendranath Jakkam ---- - include/net/cfg80211.h | 2 ++ - net/wireless/nl80211.c | 3 +++ - 2 files changed, 5 insertions(+) - -diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h -index 6b9ed661cca6..20c6ebc6436d 100644 ---- a/include/net/cfg80211.h -+++ b/include/net/cfg80211.h -@@ -1290,6 +1290,7 @@ struct cfg80211_unsol_bcast_probe_resp { - * @ht_cap: HT capabilities (or %NULL if HT isn't enabled) - * @vht_cap: VHT capabilities (or %NULL if VHT isn't enabled) - * @he_cap: HE capabilities (or %NULL if HE isn't enabled) -+ * @eht_cap: EHT capabilities (or %NULL if EHT isn't enabled) - * @ht_required: stations must support HT - * @vht_required: stations must support VHT - * @twt_responder: Enable Target Wait Time -@@ -1327,6 +1328,7 @@ struct cfg80211_ap_settings { - const struct ieee80211_vht_cap *vht_cap; - const struct ieee80211_he_cap_elem *he_cap; - const struct ieee80211_he_operation *he_oper; -+ const struct ieee80211_eht_cap_elem *eht_cap; - bool ht_required, vht_required, he_required, sae_h2e_required; - bool twt_responder; - u32 flags; -diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c -index 1e2d7a3f8889..92cbf810cc7d 100644 ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -5459,6 +5459,9 @@ static void nl80211_calculate_ap_params(struct cfg80211_ap_settings *params) - cap = cfg80211_find_ext_elem(WLAN_EID_EXT_HE_OPERATION, ies, ies_len); - if (cap && cap->datalen >= sizeof(*params->he_oper) + 1) - params->he_oper = (void *)(cap->data + 1); -+ cap = cfg80211_find_ext_ie(WLAN_EID_EXT_EHT_CAPABILITY, ies, ies_len); -+ if (cap && cap->datalen >= sizeof(*params->eht_cap) + 1) -+ params->eht_cap = (void *)(cap->data + 1); - } - - static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev, --- -2.31.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/566-ath12k-propagation-of-EHT-capabilities-from-firmware.patch b/feeds/ipq95xx/mac80211/patches/qca/566-ath12k-propagation-of-EHT-capabilities-from-firmware.patch index ed88aefd8..64eab67a7 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/566-ath12k-propagation-of-EHT-capabilities-from-firmware.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/566-ath12k-propagation-of-EHT-capabilities-from-firmware.patch @@ -20,7 +20,7 @@ Signed-off-by: Pradeep Kumar Chitrapu --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h -@@ -657,6 +657,14 @@ struct ath12k_band_cap { +@@ -659,6 +659,14 @@ struct ath12k_band_cap { u32 he_cap_phy_info[PSOC_HOST_MAX_PHY_SIZE]; struct ath12k_ppe_threshold he_ppet; u16 he_6ghz_capa; @@ -37,7 +37,7 @@ Signed-off-by: Pradeep Kumar Chitrapu struct ath12k_pdev_cap { --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -4472,6 +4472,48 @@ static void ath12k_gen_ppe_thresh(struct +@@ -4560,6 +4560,48 @@ static void ath12k_gen_ppe_thresh(struct } } @@ -86,7 +86,7 @@ Signed-off-by: Pradeep Kumar Chitrapu static void ath12k_mac_filter_he_cap_mesh(struct ieee80211_he_cap_elem *he_cap_elem) { -@@ -4622,18 +4664,158 @@ static void ath12k_mac_set_hemcsmap(stru +@@ -4711,18 +4753,156 @@ static void ath12k_mac_set_hemcsmap(stru cpu_to_le16(txmcs_map_160 & 0xffff); } @@ -205,8 +205,6 @@ Signed-off-by: Pradeep Kumar Chitrapu + ~IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ; + eht_cap_elem->phy_cap_info[4] &= + ~IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO; -+ eht_cap_elem->phy_cap_info[5] &= -+ ~IEEE80211_EHT_PHY_CAP5_TX_LESS_242_TONE_RU_SUPP; + break; + case NL80211_IFTYPE_STATION: + eht_cap_elem->phy_cap_info[7] &= @@ -254,7 +252,7 @@ Signed-off-by: Pradeep Kumar Chitrapu switch (i) { case NL80211_IFTYPE_STATION: -@@ -4646,91 +4828,40 @@ static int ath12k_mac_copy_he_cap(struct +@@ -4735,91 +4915,40 @@ static int ath12k_mac_copy_he_cap(struct } data[idx].types_mask = BIT(i); @@ -358,7 +356,7 @@ Signed-off-by: Pradeep Kumar Chitrapu band = &ar->mac.sbands[NL80211_BAND_5GHZ]; band->iftype_data = ar->mac.iftype[NL80211_BAND_5GHZ]; band->n_iftype_data = count; -@@ -4738,9 +4869,9 @@ static void ath12k_mac_setup_he_cap(stru +@@ -4827,9 +4956,9 @@ static void ath12k_mac_setup_he_cap(stru if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP && ar->supports_6ghz) { @@ -371,7 +369,7 @@ Signed-off-by: Pradeep Kumar Chitrapu band = &ar->mac.sbands[NL80211_BAND_6GHZ]; band->iftype_data = ar->mac.iftype[NL80211_BAND_6GHZ]; band->n_iftype_data = count; -@@ -4788,7 +4919,7 @@ static int __ath12k_set_antenna(struct a +@@ -4877,7 +5006,7 @@ static int __ath12k_set_antenna(struct a /* Reload HT/VHT/HE capability */ ath12k_mac_setup_ht_vht_cap(ar, &ar->pdev->cap, NULL); @@ -380,7 +378,7 @@ Signed-off-by: Pradeep Kumar Chitrapu return 0; } -@@ -7426,7 +7557,7 @@ static int __ath12k_mac_register(struct +@@ -7532,7 +7661,7 @@ static int __ath12k_mac_register(struct goto err; ath12k_mac_setup_ht_vht_cap(ar, cap, &ht_cap); @@ -403,7 +401,7 @@ Signed-off-by: Pradeep Kumar Chitrapu }; struct wmi_tlv_rdy_parse { -@@ -4213,14 +4216,125 @@ err: +@@ -4202,14 +4205,125 @@ err: return ret; } @@ -529,7 +527,7 @@ Signed-off-by: Pradeep Kumar Chitrapu case WMI_TAG_ARRAY_STRUCT: if (!parse->dma_ring_cap_done) { ret = ath12k_wmi_tlv_dma_ring_caps(ab, len, ptr, -@@ -4229,6 +4343,22 @@ static int ath12k_wmi_tlv_svc_rdy_ext2_p +@@ -4218,6 +4332,22 @@ static int ath12k_wmi_tlv_svc_rdy_ext2_p return ret; parse->dma_ring_cap_done = true; @@ -552,7 +550,7 @@ Signed-off-by: Pradeep Kumar Chitrapu } break; default: -@@ -4241,7 +4371,7 @@ static int ath12k_wmi_tlv_svc_rdy_ext2_p +@@ -4230,7 +4360,7 @@ static int ath12k_wmi_tlv_svc_rdy_ext2_p static int ath12k_service_ready_ext2_event(struct ath12k_base *ab, struct sk_buff *skb) { @@ -563,7 +561,7 @@ Signed-off-by: Pradeep Kumar Chitrapu ret = ath12k_wmi_tlv_iter(ab, skb->data, skb->len, --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -1835,6 +1835,7 @@ enum wmi_tlv_tag { +@@ -1831,6 +1831,7 @@ enum wmi_tlv_tag { /* TODO add all the missing cmds */ WMI_TAG_PDEV_PEER_PKTLOG_FILTER_CMD = 0x301, WMI_TAG_PDEV_PEER_PKTLOG_FILTER_INFO, @@ -571,7 +569,7 @@ Signed-off-by: Pradeep Kumar Chitrapu WMI_TAG_FILS_DISCOVERY_TMPL_CMD = 0x344, WMI_TAG_MAC_PHY_CAPABILITIES_EXT = 0x36F, WMI_TAG_REGULATORY_RULE_EXT_STRUCT = 0x3A9, -@@ -2164,7 +2165,6 @@ struct ath12k_ppe_threshold { +@@ -2160,7 +2161,6 @@ struct ath12k_ppe_threshold { u32 ru_bit_mask; u32 ppet16_ppet8_ru3_ru0[PSOC_HOST_MAX_NUM_SS]; }; @@ -579,7 +577,7 @@ Signed-off-by: Pradeep Kumar Chitrapu struct ath12k_service_ext_param { u32 default_conc_scan_config_bits; u32 default_fw_config_bits; -@@ -2182,6 +2182,7 @@ struct ath12k_hw_mode_caps { +@@ -2178,6 +2178,7 @@ struct ath12k_hw_mode_caps { u32 hw_mode_config_type; }; @@ -587,7 +585,7 @@ Signed-off-by: Pradeep Kumar Chitrapu #define PSOC_HOST_MAX_PHY_SIZE (3) #define ATH12K_11B_SUPPORT BIT(0) #define ATH12K_11G_SUPPORT BIT(1) -@@ -2203,6 +2204,32 @@ struct ath12k_hal_reg_capabilities_ext { +@@ -2199,6 +2200,32 @@ struct ath12k_hal_reg_capabilities_ext { u32 high_5ghz_chan; }; @@ -620,7 +618,7 @@ Signed-off-by: Pradeep Kumar Chitrapu #define WMI_HOST_MAX_PDEV 3 struct wlan_host_mem_chunk { -@@ -2474,6 +2501,65 @@ struct wmi_soc_hal_reg_capabilities { +@@ -2469,6 +2496,65 @@ struct wmi_soc_hal_reg_capabilities { u32 num_phy; } __packed; diff --git a/feeds/ipq95xx/mac80211/patches/qca/568-ath12k-Adding-320-MHz-bandwidth-changes.patch b/feeds/ipq95xx/mac80211/patches/qca/568-ath12k-Adding-320-MHz-bandwidth-changes.patch index 3950c8aac..bdc65acb7 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/568-ath12k-Adding-320-MHz-bandwidth-changes.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/568-ath12k-Adding-320-MHz-bandwidth-changes.patch @@ -91,7 +91,7 @@ index 2caa803d4f43..2470340dc46f 100644 + break; default: ath12k_warn(ar->ab, "Invalid bandwidth %d in rc update for %pM\n", - sta->bandwidth, sta->addr); + sta->deflink.bandwidth, sta->addr); diff --git a/drivers/net/wireless/ath/ath12k/mac.h b/drivers/net/wireless/ath/ath12k/mac.h index 73398441c806..b69aa20fd614 100644 --- a/drivers/net/wireless/ath/ath12k/mac.h diff --git a/feeds/ipq95xx/mac80211/patches/qca/569-ath12k-adding-EHT-PHY-modes.patch b/feeds/ipq95xx/mac80211/patches/qca/569-ath12k-adding-EHT-PHY-modes.patch index faebf9b28..75e74849b 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/569-ath12k-adding-EHT-PHY-modes.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/569-ath12k-adding-EHT-PHY-modes.patch @@ -12,11 +12,9 @@ Signed-off-by: Muna Sinada drivers/net/wireless/ath/ath12k/wmi.h | 31 +++++++++- 2 files changed, 90 insertions(+), 22 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index 2470340dc46f..16c72d043afa 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -187,32 +187,35 @@ ath12k_phymodes[NUM_NL80211_BANDS][ATH12K_CHAN_WIDTH_NUM] = { +@@ -185,32 +185,35 @@ ath12k_phymodes[NUM_NL80211_BANDS][ATH12 [NL80211_BAND_2GHZ] = { [NL80211_CHAN_WIDTH_5] = MODE_UNKNOWN, [NL80211_CHAN_WIDTH_10] = MODE_UNKNOWN, @@ -68,35 +66,35 @@ index 2470340dc46f..16c72d043afa 100644 }, }; -@@ -2142,6 +2145,36 @@ static enum wmi_phy_mode ath12k_mac_get_phymode_he(struct ath12k *ar, +@@ -2180,6 +2183,36 @@ static enum wmi_phy_mode ath12k_mac_get_ return MODE_UNKNOWN; } +static enum wmi_phy_mode ath12k_mac_get_phymode_eht(struct ath12k *ar, + struct ieee80211_sta *sta) +{ -+ if (sta->bandwidth == IEEE80211_STA_RX_BW_320) -+ if (sta->eht_cap.eht_cap_elem.phy_cap_info[0] & ++ if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_320) ++ if (sta->deflink.eht_cap.eht_cap_elem.phy_cap_info[0] & + IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ) + return MODE_11BE_EHT320; -+ if (sta->bandwidth == IEEE80211_STA_RX_BW_160) { -+ if (sta->he_cap.he_cap_elem.phy_cap_info[0] & ++ if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) { ++ if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] & + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G) + return MODE_11BE_EHT160; -+ else if (sta->he_cap.he_cap_elem.phy_cap_info[0] & ++ else if (sta->deflink.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; + /* not sure if this is a valid case? */ + return MODE_11BE_EHT160; + } + -+ if (sta->bandwidth == IEEE80211_STA_RX_BW_80) ++ if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80) + return MODE_11BE_EHT80; + -+ if (sta->bandwidth == IEEE80211_STA_RX_BW_40) ++ if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40) + return MODE_11BE_EHT40; + -+ if (sta->bandwidth == IEEE80211_STA_RX_BW_20) ++ if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20) + return MODE_11BE_EHT20; + + return MODE_UNKNOWN; @@ -105,41 +103,38 @@ index 2470340dc46f..16c72d043afa 100644 static void ath12k_peer_assoc_h_phymode(struct ath12k *ar, struct ieee80211_vif *vif, struct ieee80211_sta *sta, -@@ -2164,9 +2197,14 @@ static void ath12k_peer_assoc_h_phymode(struct ath12k *ar, - he_mcs_mask = arvif->bitrate_mask.control[band].he_mcs; +@@ -2203,8 +2236,13 @@ static void ath12k_peer_assoc_h_phymode( switch (band) { -- case NL80211_BAND_2GHZ: -- if (sta->he_cap.has_he && + case NL80211_BAND_2GHZ: +- if (sta->deflink.he_cap.has_he && - !ath12k_peer_assoc_h_he_masked(he_mcs_mask)) { -+ case NL80211_BAND_2GHZ: -+ if (sta->eht_cap.has_eht) { -+ if (sta->bandwidth == IEEE80211_STA_RX_BW_40) ++ if (sta->deflink.eht_cap.has_eht) { ++ if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40) + phymode = MODE_11BE_EHT40_2G; + else + phymode = MODE_11BE_EHT20_2G; -+ } else if (sta->he_cap.has_he && ++ } else if (sta->deflink.he_cap.has_he && + !ath12k_peer_assoc_h_he_masked(he_mcs_mask)) { - if (sta->bandwidth == IEEE80211_STA_RX_BW_80) + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80) phymode = MODE_11AX_HE80_2G; - else if (sta->bandwidth == IEEE80211_STA_RX_BW_40) -@@ -2193,7 +2231,10 @@ static void ath12k_peer_assoc_h_phymode(struct ath12k *ar, + else if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40) +@@ -2231,8 +2269,10 @@ static void ath12k_peer_assoc_h_phymode( break; case NL80211_BAND_5GHZ: case NL80211_BAND_6GHZ: -- if (sta->he_cap.has_he && +- /* Check HE first */ +- if (sta->deflink.he_cap.has_he && + /* Check EHT first */ -+ if (sta->eht_cap.has_eht) { ++ if (sta->deflink.eht_cap.has_eht) { + phymode = ath12k_mac_get_phymode_eht(ar, sta); -+ } else if (sta->he_cap.has_he && ++ } else if (sta->deflink.he_cap.has_he && !ath12k_peer_assoc_h_he_masked(he_mcs_mask)) { phymode = ath12k_mac_get_phymode_he(ar, sta); - } else if (sta->vht_cap.vht_supported && -diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h -index 7c96ce8f4ea4..b5262db8a457 100644 + } else if (sta->deflink.vht_cap.vht_supported && --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -2760,8 +2760,17 @@ enum wmi_phy_mode { +@@ -2758,8 +2758,17 @@ enum wmi_phy_mode { MODE_11AX_HE20_2G = 21, MODE_11AX_HE40_2G = 22, MODE_11AX_HE80_2G = 23, @@ -159,7 +154,7 @@ index 7c96ce8f4ea4..b5262db8a457 100644 }; static inline const char *ath12k_wmi_phymode_str(enum wmi_phy_mode mode) -@@ -2815,6 +2824,24 @@ static inline const char *ath12k_wmi_phymode_str(enum wmi_phy_mode mode) +@@ -2813,6 +2822,24 @@ static inline const char *ath12k_wmi_phy return "11ax-he40-2g"; case MODE_11AX_HE80_2G: return "11ax-he80-2g"; @@ -184,6 +179,3 @@ index 7c96ce8f4ea4..b5262db8a457 100644 case MODE_UNKNOWN: /* skip */ break; --- -2.31.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/570-nl80211-ensure-HE-capabilities-are-set-for-EHT.patch b/feeds/ipq95xx/mac80211/patches/qca/570-nl80211-ensure-HE-capabilities-are-set-for-EHT.patch index eb136d80b..1a6e04173 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/570-nl80211-ensure-HE-capabilities-are-set-for-EHT.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/570-nl80211-ensure-HE-capabilities-are-set-for-EHT.patch @@ -11,21 +11,16 @@ Signed-off-by: Aloka Dixit net/wireless/nl80211.c | 4 ++++ 1 file changed, 4 insertions(+) -diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c -index 92cbf810cc7d..a32980eb1b6f 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c -@@ -6992,6 +6992,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) - if (params.he_6ghz_capa && (params.ht_capa || params.vht_capa)) +@@ -7308,6 +7308,10 @@ static int nl80211_new_station(struct sk + (params.link_sta_params.ht_capa || params.link_sta_params.vht_capa)) return -EINVAL; + /* Ensure that HE capabilities are set along with EHT */ -+ if (params.eht_capa && !params.he_capa) ++ if (params.link_sta_params.eht_capa && !params.link_sta_params.he_capa) + return -EINVAL; + /* When you run into this, adjust the code below for the new flag */ BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7); --- -2.31.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/571-nl80211-beacon-EHT-rate-support.patch b/feeds/ipq95xx/mac80211/patches/qca/571-nl80211-beacon-EHT-rate-support.patch index 7897b7c25..bac770d9d 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/571-nl80211-beacon-EHT-rate-support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/571-nl80211-beacon-EHT-rate-support.patch @@ -1,7 +1,7 @@ -From 22f80dbfaa8d7b0e2a463d484e01938d5a189054 Mon Sep 17 00:00:00 2001 +From 9368f8e3e822442c13542885dac02331df46163c Mon Sep 17 00:00:00 2001 From: Aloka Dixit Date: Tue, 20 Jul 2021 16:15:31 -0700 -Subject: [PATCH] nl80211: beacon EHT rate support +Subject: [PATCH 09/27] nl80211: beacon EHT rate support Add new attributes and feature flags to support EHT rates for beacons. Parse the beacon rate passed by the userspace, validate and pass it @@ -10,15 +10,13 @@ down to mac80211. Signed-off-by: Aloka Dixit --- include/net/cfg80211.h | 1 + - include/uapi/linux/nl80211.h | 20 ++++- - net/wireless/nl80211.c | 179 ++++++++++++++++++++++++++++++++++++++++++- - 3 files changed, 194 insertions(+), 6 deletions(-) + include/uapi/linux/nl80211.h | 21 ++++- + net/wireless/nl80211.c | 148 ++++++++++++++++++++++++++++++++++- + 3 files changed, 164 insertions(+), 6 deletions(-) -diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h -index 436bd6c09eb1..34bec2b6d1ee 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h -@@ -792,6 +792,7 @@ struct cfg80211_bitrate_mask { +@@ -794,6 +794,7 @@ struct cfg80211_bitrate_mask { enum nl80211_he_gi he_gi; enum nl80211_he_ltf he_ltf; u16 he_ul_mcs[NL80211_HE_NSS_MAX]; @@ -26,11 +24,9 @@ index 436bd6c09eb1..34bec2b6d1ee 100644 } control[NUM_NL80211_BANDS]; }; -diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h -index 52b9f6abdd60..e5a9689beb06 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h -@@ -1838,8 +1838,9 @@ enum nl80211_commands { +@@ -1880,8 +1880,9 @@ enum nl80211_commands { * The driver must also specify support for this with the extended * features NL80211_EXT_FEATURE_BEACON_RATE_LEGACY, * NL80211_EXT_FEATURE_BEACON_RATE_HT, @@ -42,7 +38,7 @@ index 52b9f6abdd60..e5a9689beb06 100644 * * @NL80211_ATTR_FRAME_MATCH: A binary attribute which typically must contain * at least one byte, currently used with @NL80211_CMD_REGISTER_FRAME. -@@ -5120,6 +5121,8 @@ enum nl80211_key_attributes { +@@ -5220,6 +5221,8 @@ enum nl80211_key_attributes { * @NL80211_TXRATE_HE_GI: configure HE GI, 0.8us, 1.6us and 3.2us. * @NL80211_TXRATE_HE_LTF: configure HE LTF, 1XLTF, 2XLTF and 4XLTF. * @NL80211_TXRATE_HE_UL: HE MCS rates of connected HE STA for uplink traffic. @@ -51,7 +47,7 @@ index 52b9f6abdd60..e5a9689beb06 100644 * @__NL80211_TXRATE_AFTER_LAST: internal * @NL80211_TXRATE_MAX: highest TX rate attribute */ -@@ -5133,6 +5136,7 @@ enum nl80211_tx_rate_attributes { +@@ -5233,6 +5236,7 @@ enum nl80211_tx_rate_attributes { NL80211_TXRATE_HE_GI, NL80211_TXRATE_HE_LTF, NL80211_TXRATE_HE_UL, @@ -59,7 +55,7 @@ index 52b9f6abdd60..e5a9689beb06 100644 /* keep last */ __NL80211_TXRATE_AFTER_LAST, -@@ -5167,6 +5171,14 @@ enum nl80211_txrate_gi { +@@ -5267,6 +5271,14 @@ enum nl80211_txrate_gi { }; /** @@ -74,7 +70,7 @@ index 52b9f6abdd60..e5a9689beb06 100644 * enum nl80211_band - Frequency band * @NL80211_BAND_2GHZ: 2.4 GHz ISM band * @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz) -@@ -6262,6 +6274,9 @@ enum nl80211_feature_flags { +@@ -6362,6 +6374,9 @@ enum nl80211_feature_flags { * @NL80211_EXT_FEATURE_WIDE_BAND_SCAN: Driver/device supports wide band scan * on a frequency along with its corresponding phymode (40Mhz, 80Mhz) * @@ -84,7 +80,7 @@ index 52b9f6abdd60..e5a9689beb06 100644 * @NUM_NL80211_EXT_FEATURES: number of extended features. * @MAX_NL80211_EXT_FEATURES: highest extended feature index. */ -@@ -6331,6 +6346,7 @@ enum nl80211_ext_feature_index { +@@ -6431,6 +6446,7 @@ enum nl80211_ext_feature_index { NL80211_EXT_FEATURE_WIDE_BAND_SCAN, NL80211_EXT_FEATURE_RADAR_BACKGROUND, NL80211_EXT_FEATURE_STA_MGMT_RTS_CTS, @@ -92,11 +88,9 @@ index 52b9f6abdd60..e5a9689beb06 100644 /* add new features before the definition below */ NUM_NL80211_EXT_FEATURES, -diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c -index d2ffa9c0b1fc..6e62db0c2ec6 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c -@@ -390,6 +390,8 @@ static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = { +@@ -399,6 +399,8 @@ static const struct nla_policy nl80211_t .type = NLA_EXACT_LEN_WARN, .len = sizeof(struct nl80211_txrate_he), }, @@ -105,7 +99,7 @@ index d2ffa9c0b1fc..6e62db0c2ec6 100644 }; static const struct nla_policy -@@ -4927,6 +4929,139 @@ static bool he_set_mcs_mask(struct genl_info *info, +@@ -5058,6 +5060,151 @@ static bool he_set_mcs_mask(struct genl_ return true; } @@ -140,8 +134,20 @@ index d2ffa9c0b1fc..6e62db0c2ec6 100644 + mcs_13 = mcs->rx_tx_mcs13_max_nss; + } else { + const struct ieee80211_eht_mcs_nss_supp_bw *mcs; ++ enum nl80211_chan_width width; + -+ switch (wdev->chandef.width) { ++ switch (wdev->iftype) { ++ case NL80211_IFTYPE_AP: ++ width = wdev->u.ap.preset_chandef.width; ++ break; ++ case NL80211_IFTYPE_MESH_POINT: ++ width = wdev->u.mesh.chandef.width; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ switch (width) { + case NL80211_CHAN_WIDTH_320: + mcs = &eht_cap->eht_mcs_nss_supp.bw._320; + break; @@ -219,7 +225,7 @@ index d2ffa9c0b1fc..6e62db0c2ec6 100644 + return false; + + if (!(eht_cap->eht_cap_elem.phy_cap_info[6] & -+ IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP)) ++ IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP)) + return false; + } + @@ -245,7 +251,7 @@ index d2ffa9c0b1fc..6e62db0c2ec6 100644 static int nl80211_parse_tx_bitrate_mask(struct genl_info *info, struct nlattr *attrs[], enum nl80211_attrs attr, -@@ -4946,6 +5081,7 @@ static int nl80211_parse_tx_bitrate_mask(struct genl_info *info, +@@ -5078,6 +5225,7 @@ static int nl80211_parse_tx_bitrate_mask /* Default to all rates enabled */ for (i = 0; i < NUM_NL80211_BANDS; i++) { const struct ieee80211_sta_he_cap *he_cap; @@ -253,8 +259,8 @@ index d2ffa9c0b1fc..6e62db0c2ec6 100644 if (!default_all_enabled) break; -@@ -4972,6 +5108,13 @@ static int nl80211_parse_tx_bitrate_mask(struct genl_info *info, - he_tx_mcs_map = he_get_txmcsmap(info, he_cap); +@@ -5104,6 +5252,13 @@ static int nl80211_parse_tx_bitrate_mask + he_tx_mcs_map = he_get_txmcsmap(info, link_id, he_cap); he_build_mcs_mask(he_tx_mcs_map, mask->control[i].he_mcs); + eht_cap = ieee80211_get_eht_iftype_cap(sband, wdev->iftype); @@ -267,7 +273,7 @@ index d2ffa9c0b1fc..6e62db0c2ec6 100644 mask->control[i].he_gi = 0xFF; mask->control[i].he_ltf = 0xFF; } -@@ -5052,13 +5195,20 @@ static int nl80211_parse_tx_bitrate_mask(struct genl_info *info, +@@ -5186,13 +5341,20 @@ static int nl80211_parse_tx_bitrate_mask return -EINVAL; } @@ -289,7 +295,7 @@ index d2ffa9c0b1fc..6e62db0c2ec6 100644 return -EINVAL; for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) -@@ -5073,6 +5223,10 @@ static int nl80211_parse_tx_bitrate_mask(struct genl_info *info, +@@ -5207,6 +5369,10 @@ static int nl80211_parse_tx_bitrate_mask if (mask->control[band].he_mcs[i]) goto out; @@ -300,7 +306,7 @@ index d2ffa9c0b1fc..6e62db0c2ec6 100644 /* legacy and mcs rates may not be both empty */ return -EINVAL; } -@@ -5086,7 +5240,7 @@ static int validate_beacon_tx_rate(struct cfg80211_registered_device *rdev, +@@ -5220,7 +5386,7 @@ static int validate_beacon_tx_rate(struc enum nl80211_band band, struct cfg80211_bitrate_mask *beacon_rate) { @@ -309,7 +315,7 @@ index d2ffa9c0b1fc..6e62db0c2ec6 100644 u32 rate = beacon_rate->control[band].legacy; /* Allow only one rate */ -@@ -5132,8 +5286,21 @@ static int validate_beacon_tx_rate(struct cfg80211_registered_device *rdev, +@@ -5266,8 +5432,21 @@ static int validate_beacon_tx_rate(struc return -EINVAL; } @@ -333,7 +339,7 @@ index d2ffa9c0b1fc..6e62db0c2ec6 100644 return -EINVAL; if (rate && -@@ -5152,6 +5319,10 @@ static int validate_beacon_tx_rate(struct cfg80211_registered_device *rdev, +@@ -5286,6 +5465,10 @@ static int validate_beacon_tx_rate(struc !wiphy_ext_feature_isset(&rdev->wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE)) return -EINVAL; @@ -344,6 +350,3 @@ index d2ffa9c0b1fc..6e62db0c2ec6 100644 return 0; } --- -2.7.4 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/572-ath12k-prepare-EHT-peer-assoc-parameters.patch b/feeds/ipq95xx/mac80211/patches/qca/572-ath12k-prepare-EHT-peer-assoc-parameters.patch index b92f1b3d2..34a63b536 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/572-ath12k-prepare-EHT-peer-assoc-parameters.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/572-ath12k-prepare-EHT-peer-assoc-parameters.patch @@ -143,14 +143,14 @@ index 16c72d043afa..7377787a7fc7 100644 + struct ieee80211_sta *sta, + struct peer_assoc_params *arg) +{ -+ const struct ieee80211_sta_eht_cap *eht_cap = &sta->eht_cap; ++ const struct ieee80211_sta_eht_cap *eht_cap = &sta->deflink.eht_cap; + const struct ieee80211_eht_mcs_nss_supp *mcs_nss = + &eht_cap->eht_mcs_nss_supp; + const struct ieee80211_eht_mcs_nss_supp_bw *mcs_nss_supp_bw = + &mcs_nss->bw._80; + u8 mcs_idx = WMI_EHTCAP_TXRX_MCS_NSS_IDX_80; + -+ if (!sta->he_cap.has_he || !eht_cap->has_eht) ++ if (!sta->deflink.he_cap.has_he || !eht_cap->has_eht) + return; + + arg->eht_flag = true; @@ -164,7 +164,7 @@ index 16c72d043afa..7377787a7fc7 100644 + memcpy(arg->peer_eht_cap_phy, eht_cap->eht_cap_elem.phy_cap_info, + sizeof(eht_cap->eht_cap_elem.phy_cap_info)); + -+ switch (sta->bandwidth) { ++ switch (sta->deflink.bandwidth) { + case IEEE80211_STA_RX_BW_320: + mcs_nss_supp_bw = &mcs_nss->bw._320; + mcs_idx = WMI_EHTCAP_TXRX_MCS_NSS_IDX_320; diff --git a/feeds/ipq95xx/mac80211/patches/qca/573-ath12k-add-WMI-support-for-EHT-peer.patch b/feeds/ipq95xx/mac80211/patches/qca/573-ath12k-add-WMI-support-for-EHT-peer.patch index 7b252c2c8..d7b414b17 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/573-ath12k-add-WMI-support-for-EHT-peer.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/573-ath12k-add-WMI-support-for-EHT-peer.patch @@ -15,34 +15,35 @@ Signed-off-by: Pradeep Kumar Chitrapu --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -1731,6 +1731,7 @@ ath12k_wmi_copy_peer_flags(struct wmi_pe - bool hw_crypto_disabled) +@@ -1804,6 +1804,7 @@ static void ath12k_wmi_copy_peer_flags(s + bool hw_crypto_disabled) { cmd->peer_flags = 0; + cmd->peer_flags_ext = 0; if (param->is_wme_set) { if (param->qos_flag) -@@ -1745,7 +1746,8 @@ ath12k_wmi_copy_peer_flags(struct wmi_pe - cmd->peer_flags |= WMI_PEER_80MHZ; +@@ -1818,7 +1819,8 @@ static void ath12k_wmi_copy_peer_flags(s + cmd->peer_flags |= cpu_to_le32(WMI_PEER_80MHZ); if (param->bw_160) - cmd->peer_flags |= WMI_PEER_160MHZ; + cmd->peer_flags |= cpu_to_le32(WMI_PEER_160MHZ); - + if (param->bw_320) -+ cmd->peer_flags_ext |= WMI_PEER_EXT_320MHZ; ++ cmd->peer_flags_ext |= cpu_to_le32(WMI_PEER_EXT_320MHZ); /* Typically if STBC is enabled for VHT it should be enabled * for HT as well **/ -@@ -1772,6 +1774,8 @@ ath12k_wmi_copy_peer_flags(struct wmi_pe - cmd->peer_flags |= WMI_PEER_TWT_REQ; +@@ -1845,6 +1847,9 @@ static void ath12k_wmi_copy_peer_flags(s + cmd->peer_flags |= cpu_to_le32(WMI_PEER_TWT_REQ); if (param->twt_responder) - cmd->peer_flags |= WMI_PEER_TWT_RESP; + cmd->peer_flags |= cpu_to_le32(WMI_PEER_TWT_RESP); + if (param->eht_flag) -+ cmd->peer_flags_ext |= WMI_PEER_EXT_EHT; ++ cmd->peer_flags_ext |= cpu_to_le32(WMI_PEER_EXT_EHT); ++ } /* Suppress authorization for all AUTH modes that need 4-way handshake -@@ -1816,6 +1820,7 @@ int ath12k_wmi_send_peer_assoc_cmd(struc +@@ -1889,6 +1894,7 @@ int ath12k_wmi_send_peer_assoc_cmd(struc struct wmi_peer_assoc_complete_cmd *cmd; struct wmi_vht_rate_set *mcs; struct wmi_he_rate_set *he_mcs; @@ -50,7 +51,7 @@ Signed-off-by: Pradeep Kumar Chitrapu struct sk_buff *skb; struct wmi_tlv *tlv; void *ptr; -@@ -1832,7 +1837,9 @@ int ath12k_wmi_send_peer_assoc_cmd(struc +@@ -1905,7 +1911,9 @@ int ath12k_wmi_send_peer_assoc_cmd(struc TLV_HDR_SIZE + (peer_legacy_rates_align * sizeof(u8)) + TLV_HDR_SIZE + (peer_ht_rates_align * sizeof(u8)) + sizeof(*mcs) + TLV_HDR_SIZE + @@ -61,7 +62,7 @@ Signed-off-by: Pradeep Kumar Chitrapu skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len); if (!skb) -@@ -1876,6 +1883,16 @@ int ath12k_wmi_send_peer_assoc_cmd(struc +@@ -1948,6 +1956,16 @@ int ath12k_wmi_send_peer_assoc_cmd(struc memcpy(&cmd->peer_ppet, ¶m->peer_ppet, sizeof(param->peer_ppet)); @@ -78,7 +79,7 @@ Signed-off-by: Pradeep Kumar Chitrapu /* Update peer legacy rate information */ ptr += sizeof(*cmd); -@@ -1947,6 +1964,32 @@ int ath12k_wmi_send_peer_assoc_cmd(struc +@@ -2014,6 +2032,32 @@ int ath12k_wmi_send_peer_assoc_cmd(struc ptr += sizeof(*he_mcs); } @@ -111,7 +112,7 @@ Signed-off-by: Pradeep Kumar Chitrapu /* fill ML Partner links Header TAG */ len = 0; tlv = ptr; -@@ -1962,7 +2005,7 @@ int ath12k_wmi_send_peer_assoc_cmd(struc +@@ -2029,7 +2073,7 @@ int ath12k_wmi_send_peer_assoc_cmd(struc } ath12k_dbg(ar->ab, ATH12K_DBG_WMI, @@ -120,7 +121,7 @@ Signed-off-by: Pradeep Kumar Chitrapu cmd->vdev_id, cmd->peer_associd, param->peer_mac, cmd->peer_flags, cmd->peer_rate_caps, cmd->peer_caps, cmd->peer_listen_intval, cmd->peer_ht_caps, -@@ -1972,7 +2015,10 @@ int ath12k_wmi_send_peer_assoc_cmd(struc +@@ -2039,7 +2083,10 @@ int ath12k_wmi_send_peer_assoc_cmd(struc cmd->peer_he_ops, cmd->peer_he_cap_info_ext, cmd->peer_he_cap_phy[0], cmd->peer_he_cap_phy[1], cmd->peer_he_cap_phy[2], @@ -134,7 +135,7 @@ Signed-off-by: Pradeep Kumar Chitrapu } --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -1840,6 +1840,7 @@ enum wmi_tlv_tag { +@@ -1836,6 +1836,7 @@ enum wmi_tlv_tag { WMI_TAG_MAC_PHY_CAPABILITIES_EXT = 0x36F, WMI_TAG_REGULATORY_RULE_EXT_STRUCT = 0x3A9, WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT, @@ -142,7 +143,7 @@ Signed-off-by: Pradeep Kumar Chitrapu WMI_TAG_MAX }; -@@ -3738,6 +3739,7 @@ struct peer_assoc_params { +@@ -3698,6 +3699,7 @@ struct peer_assoc_params { bool bw_40; bool bw_80; bool bw_160; @@ -150,23 +151,23 @@ Signed-off-by: Pradeep Kumar Chitrapu bool stbc_flag; bool ldpc_flag; bool static_mimops_flag; -@@ -3803,6 +3805,15 @@ struct wmi_peer_assoc_complete_cmd { - u32 peer_he_cap_info_internal; - u32 min_data_rate; - u32 peer_he_caps_6ghz; -+ u32 sta_type; -+ u32 bss_max_idle_option; -+ u32 auth_mode; -+ u32 peer_flags_ext; -+ u32 puncture_20mhz_bitmap; -+ u32 peer_eht_cap_mac[WMI_MAX_EHTCAP_MAC_SIZE]; -+ u32 peer_eht_cap_phy[WMI_MAX_EHTCAP_PHY_SIZE]; -+ u32 peer_eht_ops; +@@ -3763,6 +3765,15 @@ struct wmi_peer_assoc_complete_cmd { + __le32 peer_he_cap_info_internal; + __le32 min_data_rate; + __le32 peer_he_caps_6ghz; ++ __le32 sta_type; ++ __le32 bss_max_idle_option; ++ __le32 auth_mode; ++ __le32 peer_flags_ext; ++ __le32 puncture_20mhz_bitmap; ++ __le32 peer_eht_cap_mac[WMI_MAX_EHTCAP_MAC_SIZE]; ++ __le32 peer_eht_cap_phy[WMI_MAX_EHTCAP_PHY_SIZE]; ++ __le32 peer_eht_ops; + struct wmi_ppe_threshold peer_eht_ppet; } __packed; struct wmi_stop_scan_cmd { -@@ -4100,6 +4111,9 @@ struct wmi_unit_test_cmd { +@@ -4054,6 +4065,9 @@ struct wmi_unit_test_cmd { #define WMI_PEER_160MHZ 0x40000000 #define WMI_PEER_SAFEMODE_EN 0x80000000 @@ -176,7 +177,7 @@ Signed-off-by: Pradeep Kumar Chitrapu struct beacon_tmpl_params { u8 vdev_id; u32 tim_ie_offset; -@@ -4132,6 +4146,12 @@ struct wmi_he_rate_set { +@@ -4086,6 +4100,12 @@ struct wmi_he_rate_set { u32 tx_mcs_set; } __packed; @@ -191,11 +192,11 @@ Signed-off-by: Pradeep Kumar Chitrapu #define MAX_6G_REG_RULES 5 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -2065,6 +2065,12 @@ static void ath12k_peer_assoc_h_eht(stru +@@ -2101,6 +2101,12 @@ static void ath12k_peer_assoc_h_eht(stru return; arg->eht_flag = true; -+ if (sta->bandwidth == IEEE80211_STA_RX_BW_320) { ++ if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_320) { + arg->bw_40 = true; + arg->bw_80 = true; + arg->bw_160 = true; diff --git a/feeds/ipq95xx/mac80211/patches/qca/576-cfg80211-EHT-operation-element-support-in-AP-mode.patch b/feeds/ipq95xx/mac80211/patches/qca/576-cfg80211-EHT-operation-element-support-in-AP-mode.patch deleted file mode 100644 index 3ff2109f6..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/576-cfg80211-EHT-operation-element-support-in-AP-mode.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 51ce3290be96550dfa86df548f75f219171b5696 Mon Sep 17 00:00:00 2001 -From: Aloka Dixit -Date: Tue, 21 Sep 2021 11:40:31 -0700 -Subject: [PATCH 14/27] cfg80211: EHT operation element support in AP mode - -Add new parameter in struct cfg80211_ap_settings to store a pointer -to EHT operation element data received from the userspace. - -Signed-off-by: Aloka Dixit ---- - include/net/cfg80211.h | 2 ++ - net/wireless/nl80211.c | 3 +++ - 2 files changed, 5 insertions(+) - -diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h -index 685fdf41db42..72d7fb559d82 100644 ---- a/include/net/cfg80211.h -+++ b/include/net/cfg80211.h -@@ -1292,6 +1292,7 @@ struct cfg80211_unsol_bcast_probe_resp { - * @vht_cap: VHT capabilities (or %NULL if VHT isn't enabled) - * @he_cap: HE capabilities (or %NULL if HE isn't enabled) - * @eht_cap: EHT capabilities (or %NULL if EHT isn't enabled) -+ * @eht_oper: EHT operation IE (or %NULL if EHT isn't enabled) - * @ht_required: stations must support HT - * @vht_required: stations must support VHT - * @twt_responder: Enable Target Wait Time -@@ -1330,6 +1331,7 @@ struct cfg80211_ap_settings { - const struct ieee80211_he_cap_elem *he_cap; - const struct ieee80211_he_operation *he_oper; - const struct ieee80211_eht_cap_elem *eht_cap; -+ const struct ieee80211_eht_operation *eht_oper; - bool ht_required, vht_required, he_required, sae_h2e_required; - bool twt_responder; - u32 flags; -diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c -index 5961e9cd86d4..9bbb44a272ec 100644 ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -5602,6 +5602,9 @@ static void nl80211_calculate_ap_params(struct cfg80211_ap_settings *params) - cap = cfg80211_find_ext_ie(WLAN_EID_EXT_EHT_CAPABILITY, ies, ies_len); - if (cap && cap->datalen >= sizeof(*params->eht_cap) + 1) - params->eht_cap = (void *)(cap->data + 1); -+ cap = cfg80211_find_ext_ie(WLAN_EID_EXT_EHT_OPERATION, ies, ies_len); -+ if (cap && cap->datalen >= sizeof(*params->eht_oper) + 1) -+ params->eht_oper = (void *)(cap->data + 1); - } - - static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev, --- -2.31.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/577-mac80211-EHT-operation-element-support-in-AP-mode.patch b/feeds/ipq95xx/mac80211/patches/qca/577-mac80211-EHT-operation-element-support-in-AP-mode.patch index e4171f46d..78a9d9a33 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/577-mac80211-EHT-operation-element-support-in-AP-mode.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/577-mac80211-EHT-operation-element-support-in-AP-mode.patch @@ -16,31 +16,32 @@ Signed-off-by: Aloka Dixit --- a/include/net/mac80211.h +++ b/include/net/mac80211.h -@@ -668,6 +668,8 @@ struct ieee80211_fils_discovery { +@@ -682,6 +682,8 @@ struct ieee80211_fils_discovery { + * @color_change_color: the bss color that will be used after the change. * @nss_ap_isolate: Used for notifying the NSS host about AP isolate feature * @beacon_tx_mode: Beacon Tx Mode setting. - * @eht_support: does this BSS support EHT + * @eht_oper: EHT operation information of the BSS (AP/Mesh) or of the AP we -+ * are connected to (STA) ++ * are connected to (STA) */ struct ieee80211_bss_conf { const u8 *bssid; -@@ -750,6 +752,11 @@ struct ieee80211_bss_conf { - bool nss_ap_isolate; - enum nl80211_beacon_tx_mode beacon_tx_mode; +@@ -753,6 +755,12 @@ struct ieee80211_bss_conf { + u8 tx_pwr_env_num; + u8 pwr_reduction; bool eht_support; + struct { + u8 chan_width; -+ u8 ccfs; ++ u8 ccfs0; ++ u8 ccfs1; + u8 present_bm; + } eht_oper; - /* Mesh configuration for nss offload */ - u8 nss_offld_ttl; + bool csa_active; + bool mu_mimo_owner; --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -1319,6 +1319,14 @@ static int ieee80211_start_ap(struct wip - sizeof(*params->he_cap)); +@@ -1244,6 +1244,14 @@ static int ieee80211_start_ap(struct wip + IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO; } + if (params->eht_cap && params->eht_oper) { @@ -52,31 +53,42 @@ Signed-off-by: Aloka Dixit + } + mutex_lock(&local->mtx); - err = ieee80211_vif_use_channel(sdata, ¶ms->chandef, - IEEE80211_CHANCTX_SHARED); + err = ieee80211_link_use_channel(link, ¶ms->chandef, + IEEE80211_CHANCTX_SHARED); --- a/net/mac80211/eht.c +++ b/net/mac80211/eht.c -@@ -74,3 +74,14 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(stru - sta->cur_max_bandwidth = ieee80211_sta_cap_rx_bw(sta); - sta->sta.bandwidth = ieee80211_sta_cur_vht_bw(sta); +@@ -75,3 +75,25 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(stru + link_sta->cur_max_bandwidth = ieee80211_sta_cap_rx_bw(link_sta); + link_sta->pub->bandwidth = ieee80211_sta_cur_vht_bw(link_sta); } + +void ieee80211_eht_op_ie_to_bss_conf(struct ieee80211_vif *vif, + const struct ieee80211_eht_operation *op_ie) +{ ++ struct ieee80211_eht_operation_info *eht_oper_info; ++ + if (!op_ie) + return; + -+ vif->bss_conf.eht_oper.chan_width = op_ie->chan_width; -+ vif->bss_conf.eht_oper.ccfs = op_ie->ccfs; -+ vif->bss_conf.eht_oper.present_bm = op_ie->present_bm; ++ if (op_ie->params && IEEE80211_EHT_OPER_INFO_PRESENT) { ++ eht_oper_info = op_ie->optional; ++ ++ vif->bss_conf.eht_oper.chan_width = ++ u8_get_bits(eht_oper_info->control, ++ IEEE80211_EHT_OPER_CHAN_WIDTH); ++ vif->bss_conf.eht_oper.ccfs0 = eht_oper_info->ccfs0; ++ vif->bss_conf.eht_oper.ccfs1 = eht_oper_info->ccfs1; ++ vif->bss_conf.eht_oper.present_bm = ++ u8_get_bits(eht_oper_info->control, ++ IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT); ++ } +} --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h -@@ -2562,4 +2562,6 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(stru - const u8 *he_cap_ie, u8 he_cap_len, +@@ -2550,4 +2550,6 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(stru const struct ieee80211_eht_cap_elem *eht_cap_ie_elem, - u8 eht_cap_len, struct sta_info *sta); + u8 eht_cap_len, + struct link_sta_info *link_sta); +void ieee80211_eht_op_ie_to_bss_conf(struct ieee80211_vif *vif, -+ const struct ieee80211_eht_operation *eht_op); ++ const struct ieee80211_eht_operation *op_ie); #endif /* IEEE80211_I_H */ diff --git a/feeds/ipq95xx/mac80211/patches/qca/578-ath12k-EHT-operation-element-support-in-AP-mode.patch b/feeds/ipq95xx/mac80211/patches/qca/578-ath12k-EHT-operation-element-support-in-AP-mode.patch index 358327ee4..20296ae67 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/578-ath12k-EHT-operation-element-support-in-AP-mode.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/578-ath12k-EHT-operation-element-support-in-AP-mode.patch @@ -24,7 +24,7 @@ index 7377787a7fc7..ad0a90b330d6 100644 + memcpy(&arg->peer_eht_ops, &vif->bss_conf.eht_oper, + sizeof(vif->bss_conf.eht_oper)); - switch (sta->bandwidth) { + switch (sta->deflink.bandwidth) { case IEEE80211_STA_RX_BW_320: @@ -2924,6 +2926,22 @@ static void ath12k_mac_op_bss_info_changed(struct ieee80211_hw *hw, if (ret) diff --git a/feeds/ipq95xx/mac80211/patches/qca/579-mac80211-Add-320-Mhz-support.patch b/feeds/ipq95xx/mac80211/patches/qca/579-mac80211-Add-320-Mhz-support.patch index 7b212fc3d..aa47fe247 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/579-mac80211-Add-320-Mhz-support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/579-mac80211-Add-320-Mhz-support.patch @@ -13,11 +13,9 @@ Signed-off-by: Karthikeyan Periyasamy net/mac80211/mlme.c | 3 +++ 3 files changed, 5 insertions(+) -diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c -index 5085783efe9c..f8fa693a21a7 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c -@@ -1958,6 +1958,7 @@ static const char * const hwsim_chanwidths[] = { +@@ -2125,6 +2125,7 @@ static const char * const hwsim_chanwidt [NL80211_CHAN_WIDTH_4] = "4MHz", [NL80211_CHAN_WIDTH_8] = "8MHz", [NL80211_CHAN_WIDTH_16] = "16MHz", @@ -25,11 +23,9 @@ index 5085783efe9c..f8fa693a21a7 100644 }; static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) -diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c -index aa25769d5b17..f5db2ea38047 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c -@@ -929,6 +929,7 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) +@@ -937,6 +937,7 @@ ieee80211_mesh_build_beacon(struct ieee8 case NL80211_CHAN_WIDTH_80: case NL80211_CHAN_WIDTH_80P80: case NL80211_CHAN_WIDTH_160: @@ -37,28 +33,25 @@ index aa25769d5b17..f5db2ea38047 100644 /* Channel Switch Wrapper + Wide Bandwidth CSA IE */ ie_len = 2 + 2 + sizeof(struct ieee80211_wide_bw_chansw_ie); -diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c -index cae0a2145484..5fa4991a7a27 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c -@@ -448,6 +448,9 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata, - if (ifmgd->flags & IEEE80211_STA_DISABLE_160MHZ && +@@ -483,10 +483,12 @@ static int ieee80211_config_bw(struct ie + if (link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_160MHZ && chandef.width == NL80211_CHAN_WIDTH_160) flags |= ieee80211_chandef_downgrade(&chandef); -+ if (ifmgd->flags & IEEE80211_STA_DISABLE_320MHZ && ++ if (link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_320MHZ && + chandef.width == NL80211_CHAN_WIDTH_320) -+ flags |= ieee80211_chandef_downgrade(&chandef); - if (ifmgd->flags & IEEE80211_STA_DISABLE_40MHZ && ++ flags |= ieee80211_chandef_downgrade(&chandef); + if (link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_40MHZ && chandef.width > NL80211_CHAN_WIDTH_20) flags |= ieee80211_chandef_downgrade(&chandef); --- -2.31.1 - -diff --git a/net/wireless/chan.c b/net/wireless/chan.c -index 669b80e4005e..e914bad271ec 100644 +- + if (cfg80211_chandef_identical(&chandef, &link->conf->chandef)) + return 0; + --- a/net/wireless/chan.c +++ b/net/wireless/chan.c -@@ -360,6 +360,11 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef) +@@ -256,6 +256,11 @@ bool cfg80211_chandef_valid(const struct chandef->center_freq2 - chandef->center_freq1 == 80) return false; break; diff --git a/feeds/ipq95xx/mac80211/patches/qca/580-cfg80211-Support-disabling-EHT-mode.patch b/feeds/ipq95xx/mac80211/patches/qca/580-cfg80211-Support-disabling-EHT-mode.patch deleted file mode 100644 index 428c9f64f..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/580-cfg80211-Support-disabling-EHT-mode.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 52c2f9c2d335783e2906b715082946ebfcac57ea Mon Sep 17 00:00:00 2001 -From: Muna Sinada -Date: Mon, 20 Sep 2021 16:10:38 -0700 -Subject: [PATCH 18/27] cfg80211: Support disabling EHT mode - -Allow user to disable EHT mode. This forces EHT capable interfaces -to disable during association. - -Signed-off-by: Muna Sinada ---- - include/net/cfg80211.h | 2 ++ - include/uapi/linux/nl80211.h | 1 + - net/wireless/nl80211.c | 7 +++++++ - 3 files changed, 10 insertions(+) - -diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h -index 72d7fb559d82..529e06057b13 100644 ---- a/include/net/cfg80211.h -+++ b/include/net/cfg80211.h -@@ -2745,6 +2745,7 @@ struct cfg80211_auth_request { - * userspace if this flag is set. Only applicable for cfg80211_connect() - * request (connect callback). - * @ASSOC_REQ_DISABLE_HE: Disable HE -+ * @ASSOC_REQ_DISABLE_EHT: Disable EHT - */ - enum cfg80211_assoc_req_flags { - ASSOC_REQ_DISABLE_HT = BIT(0), -@@ -2752,6 +2753,7 @@ enum cfg80211_assoc_req_flags { - ASSOC_REQ_USE_RRM = BIT(2), - CONNECT_REQ_EXTERNAL_AUTH_SUPPORT = BIT(3), - ASSOC_REQ_DISABLE_HE = BIT(4), -+ ASSOC_REQ_DISABLE_EHT = BIT(5), - }; - - /** -diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h -index c1f5f141144f..d9ac4865a0d5 100644 ---- a/include/uapi/linux/nl80211.h -+++ b/include/uapi/linux/nl80211.h -@@ -3176,6 +3176,7 @@ enum nl80211_attrs { - - NL80211_ATTR_EHT_CAPABILITY, - -+ NL80211_ATTR_DISABLE_EHT, - /* add attributes here, update the policy in nl80211.c */ - - __NL80211_ATTR_AFTER_LAST, -diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c -index 9bbb44a272ec..9cdb87048542 100644 ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -809,6 +809,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { - { .type = NLA_BINARY, - .len = NL80211_EHT_MAX_CAPABILITY_LEN }, - #endif -+ [NL80211_ATTR_DISABLE_EHT] = { .type = NLA_FLAG }, - }; - - /* policy for the key attributes */ -@@ -10542,6 +10543,9 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) - if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HE])) - req.flags |= ASSOC_REQ_DISABLE_HE; - -+ if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_EHT])) -+ req.flags |= ASSOC_REQ_DISABLE_EHT; -+ - if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) - memcpy(&req.vht_capa_mask, - nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]), -@@ -11330,6 +11334,9 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) - if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HE])) - connect.flags |= ASSOC_REQ_DISABLE_HE; - -+ if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_EHT])) -+ connect.flags |= ASSOC_REQ_DISABLE_EHT; -+ - if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) - memcpy(&connect.vht_capa_mask, - nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]), --- -2.31.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/581-mac80211-Support-disabling-EHT-mode.patch b/feeds/ipq95xx/mac80211/patches/qca/581-mac80211-Support-disabling-EHT-mode.patch index dd7181b43..09f62cafc 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/581-mac80211-Support-disabling-EHT-mode.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/581-mac80211-Support-disabling-EHT-mode.patch @@ -11,29 +11,23 @@ Signed-off-by: Muna Sinada net/mac80211/mlme.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) -diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c -index 5fa4991a7a27..02f83b5cb52b 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c -@@ -5767,7 +5767,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, - ifmgd->flags |= IEEE80211_STA_DISABLE_HE; - ifmgd->flags |= IEEE80211_STA_DISABLE_EHT; +@@ -6936,7 +6936,7 @@ int ieee80211_mgd_assoc(struct ieee80211 + conn_flags |= IEEE80211_CONN_DISABLE_HE; + conn_flags |= IEEE80211_CONN_DISABLE_EHT; netdev_info(sdata->dev, - "disabling HT/VHT/HE due to WEP/TKIP use\n"); + "disabling HT/VHT/HE/EHT due to WEP/TKIP use\n"); } } -@@ -5929,6 +5929,9 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, - ifmgd->flags |= IEEE80211_STA_DISABLE_EHT; +@@ -6951,7 +6951,7 @@ int ieee80211_mgd_assoc(struct ieee80211 } -+ if (req->flags & ASSOC_REQ_DISABLE_EHT) -+ ifmgd->flags |= IEEE80211_STA_DISABLE_EHT; -+ - err = ieee80211_prep_connection(sdata, req->bss, true, override); - if (err) - goto err_clear; --- -2.31.1 - + if (req->flags & ASSOC_REQ_DISABLE_HT) { +- mlme_dbg(sdata, "HT disabled by flag, disabling HT/VHT/HE\n"); ++ mlme_dbg(sdata, "HT disabled by flag, disabling HT/VHT/HE/EHT\n"); + conn_flags |= IEEE80211_CONN_DISABLE_HT; + conn_flags |= IEEE80211_CONN_DISABLE_VHT; + conn_flags |= IEEE80211_CONN_DISABLE_HE; diff --git a/feeds/ipq95xx/mac80211/patches/qca/582-ath12k-add-support-for-setting-fixed-HE-rate-gi-ltf.patch b/feeds/ipq95xx/mac80211/patches/qca/582-ath12k-add-support-for-setting-fixed-HE-rate-gi-ltf.patch index 52763b2c6..cd86cb56e 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/582-ath12k-add-support-for-setting-fixed-HE-rate-gi-ltf.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/582-ath12k-add-support-for-setting-fixed-HE-rate-gi-ltf.patch @@ -13,23 +13,27 @@ Signed-off-by: Muna Sinada drivers/net/wireless/ath/ath12k/mac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index ad0a90b330d6..d2f78576d3aa 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -2397,10 +2397,10 @@ static void ath12k_peer_assoc_h_phymode(struct ath12k *ar, - if (sta->eht_cap.has_eht) { +@@ -2418,7 +2418,7 @@ static void ath12k_peer_assoc_h_phymode( + else + phymode = MODE_11AX_HE20_2G; + } else if (sta->deflink.vht_cap.vht_supported && +- !ath12k_peer_assoc_h_vht_masked(vht_mcs_mask)) { ++ !ath12k_peer_assoc_h_vht_masked(vht_mcs_mask)) { + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40) + phymode = MODE_11AC_VHT40; + else +@@ -2441,10 +2441,10 @@ static void ath12k_peer_assoc_h_phymode( + if (sta->deflink.eht_cap.has_eht) { phymode = ath12k_mac_get_phymode_eht(ar, sta); - } else if (sta->he_cap.has_he && + } else if (sta->deflink.he_cap.has_he && - !ath12k_peer_assoc_h_he_masked(he_mcs_mask)) { + !ath12k_peer_assoc_h_he_masked(he_mcs_mask)) { phymode = ath12k_mac_get_phymode_he(ar, sta); - } else if (sta->vht_cap.vht_supported && + } else if (sta->deflink.vht_cap.vht_supported && - !ath12k_peer_assoc_h_vht_masked(vht_mcs_mask)) { + !ath12k_peer_assoc_h_vht_masked(vht_mcs_mask)) { phymode = ath12k_mac_get_phymode_vht(ar, sta); - } else if (sta->ht_cap.ht_supported && + } else if (sta->deflink.ht_cap.ht_supported && !ath12k_peer_assoc_h_ht_masked(ht_mcs_mask)) { --- -2.31.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/584-ath12k-Add-EHT-fixed-rate-settings.patch b/feeds/ipq95xx/mac80211/patches/qca/584-ath12k-Add-EHT-fixed-rate-settings.patch index 8f480f145..30c8a0026 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/584-ath12k-Add-EHT-fixed-rate-settings.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/584-ath12k-Add-EHT-fixed-rate-settings.patch @@ -15,7 +15,7 @@ Signed-off-by: Aloka Dixit --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -377,6 +377,18 @@ ath12k_mac_max_he_nss(const u16 he_mcs_m +@@ -375,6 +375,18 @@ ath12k_mac_max_he_nss(const u16 he_mcs_m return 1; } @@ -34,7 +34,7 @@ Signed-off-by: Aloka Dixit static u8 ath12k_parse_mpdudensity(u8 mpdudensity) { /* 802.11n D2.0 defined values for "Minimum MPDU Start Spacing": -@@ -1955,62 +1967,84 @@ static void ath12k_peer_assoc_h_he_6ghz( +@@ -1991,62 +2003,84 @@ static void ath12k_peer_assoc_h_he_6ghz( static void ath12k_mac_set_eht_mcs_nss_bitmap_20mhz_only( const struct ieee80211_eht_mcs_nss_supp_20mhz_only *mcsnss, @@ -169,7 +169,7 @@ Signed-off-by: Aloka Dixit } static void ath12k_mac_set_eht_ppe_threshold(const u8 *ppe_thres, -@@ -2049,17 +2083,45 @@ static void ath12k_mac_set_eht_ppe_thres +@@ -2085,17 +2119,45 @@ static void ath12k_mac_set_eht_ppe_thres } } @@ -192,7 +192,7 @@ Signed-off-by: Aloka Dixit { + struct ath12k_vif *arvif = (void *)vif->drv_priv; + struct cfg80211_chan_def def; - const struct ieee80211_sta_eht_cap *eht_cap = &sta->eht_cap; + const struct ieee80211_sta_eht_cap *eht_cap = &sta->deflink.eht_cap; const struct ieee80211_eht_mcs_nss_supp *mcs_nss = &eht_cap->eht_mcs_nss_supp; const struct ieee80211_eht_mcs_nss_supp_bw *mcs_nss_supp_bw = @@ -213,17 +213,17 @@ Signed-off-by: Aloka Dixit + if (ath12k_peer_assoc_h_eht_masked(eht_mcs_mask)) + return; - if (!sta->he_cap.has_he || !eht_cap->has_eht) + if (!sta->deflink.he_cap.has_he || !eht_cap->has_eht) return; -@@ -2077,6 +2139,25 @@ static void ath12k_peer_assoc_h_eht(stru +@@ -2119,6 +2181,25 @@ static void ath12k_peer_assoc_h_eht(stru memcpy(&arg->peer_eht_ops, &vif->bss_conf.eht_oper, sizeof(vif->bss_conf.eht_oper)); + eht_nss = ath12k_mac_max_eht_nss(eht_mcs_mask); + -+ if (eht_nss > sta->rx_nss) { ++ if (eht_nss > sta->deflink.rx_nss) { + user_rate_valid = false; -+ for (nss_idx = (sta->rx_nss - 1); nss_idx >= 0; nss_idx--) { ++ for (nss_idx = (sta->deflink.rx_nss - 1); nss_idx >= 0; nss_idx--) { + if (eht_mcs_mask[nss_idx]) { + user_rate_valid = true; + break; @@ -234,14 +234,14 @@ Signed-off-by: Aloka Dixit + if (!user_rate_valid) { + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, + "Setting eht range MCS value to peer supported nss:%d for peer %pM\n", -+ sta->rx_nss, sta->addr); -+ eht_mcs_mask[sta->rx_nss - 1] = eht_mcs_mask[eht_nss - 1]; ++ sta->deflink.rx_nss, sta->deflink.addr); ++ eht_mcs_mask[sta->deflink.rx_nss - 1] = eht_mcs_mask[eht_nss - 1]; + } + - switch (sta->bandwidth) { + switch (sta->deflink.bandwidth) { case IEEE80211_STA_RX_BW_320: mcs_nss_supp_bw = &mcs_nss->bw._320; -@@ -2084,7 +2165,8 @@ static void ath12k_peer_assoc_h_eht(stru +@@ -2126,7 +2207,8 @@ static void ath12k_peer_assoc_h_eht(stru arg->peer_eht_mcs_count++; ath12k_mac_set_eht_mcs_nss_bitmap(&mcs_nss->bw._320, &arg->peer_eht_rx_mcs_set[mcs_idx], @@ -251,7 +251,7 @@ Signed-off-by: Aloka Dixit fallthrough; case IEEE80211_STA_RX_BW_160: -@@ -2093,7 +2175,8 @@ static void ath12k_peer_assoc_h_eht(stru +@@ -2135,7 +2217,8 @@ static void ath12k_peer_assoc_h_eht(stru arg->peer_eht_mcs_count++; ath12k_mac_set_eht_mcs_nss_bitmap(&mcs_nss->bw._160, &arg->peer_eht_rx_mcs_set[mcs_idx], @@ -261,7 +261,7 @@ Signed-off-by: Aloka Dixit fallthrough; default: -@@ -2101,17 +2184,46 @@ static void ath12k_peer_assoc_h_eht(stru +@@ -2143,17 +2226,46 @@ static void ath12k_peer_assoc_h_eht(stru mcs_idx = WMI_EHTCAP_TXRX_MCS_NSS_IDX_80; ath12k_mac_set_eht_mcs_nss_bitmap_20mhz_only(&mcs_nss->only_20mhz, &arg->peer_eht_rx_mcs_set[mcs_idx], @@ -281,7 +281,7 @@ Signed-off-by: Aloka Dixit break; } + -+ if (!(sta->he_cap.he_cap_elem.phy_cap_info[0] & ++ if (!(sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] & + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK_ALL)) { + if (mcs_nss->only_20mhz.rx_tx_mcs13_max_nss) + max_nss = mcs_nss->only_20mhz.rx_tx_mcs13_max_nss; @@ -302,15 +302,15 @@ Signed-off-by: Aloka Dixit + + max_nss = max(max_nss, (uint8_t)eht_nss); + -+ arg->peer_nss = min(sta->rx_nss, max_nss); ++ arg->peer_nss = min(sta->deflink.rx_nss, max_nss); + + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, + "mac he peer %pM nss %d mcs cnt %d\n", -+ sta->addr, arg->peer_nss, arg->peer_he_mcs_count); ++ sta->deflink.addr, arg->peer_nss, arg->peer_he_mcs_count); } static void ath12k_peer_assoc_h_smps(struct ieee80211_sta *sta, -@@ -2350,6 +2462,7 @@ static void ath12k_peer_assoc_h_phymode( +@@ -2392,6 +2504,7 @@ static void ath12k_peer_assoc_h_phymode( const u8 *ht_mcs_mask; const u16 *vht_mcs_mask; const u16 *he_mcs_mask; @@ -318,31 +318,31 @@ Signed-off-by: Aloka Dixit enum wmi_phy_mode phymode = MODE_UNKNOWN; if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) -@@ -2359,10 +2472,12 @@ static void ath12k_peer_assoc_h_phymode( +@@ -2401,10 +2514,12 @@ static void ath12k_peer_assoc_h_phymode( 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; + eht_mcs_mask = arvif->bitrate_mask.control[band].eht_mcs; switch (band) { - case NL80211_BAND_2GHZ: -- if (sta->eht_cap.has_eht) { -+ if (sta->eht_cap.has_eht && + case NL80211_BAND_2GHZ: +- if (sta->deflink.eht_cap.has_eht) { ++ if (sta->deflink.eht_cap.has_eht && + !ath12k_peer_assoc_h_eht_masked(eht_mcs_mask)) { - if (sta->bandwidth == IEEE80211_STA_RX_BW_40) + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40) phymode = MODE_11BE_EHT40_2G; else -@@ -2396,7 +2511,8 @@ static void ath12k_peer_assoc_h_phymode( +@@ -2438,7 +2553,8 @@ static void ath12k_peer_assoc_h_phymode( case NL80211_BAND_5GHZ: case NL80211_BAND_6GHZ: /* Check EHT first */ -- if (sta->eht_cap.has_eht) { -+ if (sta->eht_cap.has_eht && +- if (sta->deflink.eht_cap.has_eht) { ++ if (sta->deflink.eht_cap.has_eht && + !ath12k_peer_assoc_h_eht_masked(eht_mcs_mask)) { phymode = ath12k_mac_get_phymode_eht(ar, sta); - } else if (sta->he_cap.has_he && + } else if (sta->deflink.he_cap.has_he && !ath12k_peer_assoc_h_he_masked(he_mcs_mask)) { -@@ -3640,6 +3756,20 @@ ath12k_mac_bitrate_mask_num_he_rates(str +@@ -3694,6 +3810,20 @@ ath12k_mac_bitrate_mask_num_he_rates(str } static int @@ -363,7 +363,7 @@ Signed-off-by: Aloka Dixit ath12k_mac_set_peer_vht_fixed_rate(struct ath12k_vif *arvif, struct ieee80211_sta *sta, const struct cfg80211_bitrate_mask *mask, -@@ -3736,6 +3866,57 @@ ath12k_mac_set_peer_he_fixed_rate(struct +@@ -3790,6 +3920,57 @@ ath12k_mac_set_peer_he_fixed_rate(struct return ret; } @@ -391,29 +391,29 @@ Signed-off-by: Aloka Dixit + + if (!nss) { + ath12k_warn(ar->ab, "No single EHT Fixed rate found to set for %pM", -+ sta->addr); ++ sta->deflink.addr); + return -EINVAL; + } + + /* Avoid updating invalid nss as fixed rate*/ -+ if (nss > sta->rx_nss) ++ if (nss > sta->deflink.rx_nss) + return -EINVAL; + + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, + "Setting Fixed EHT Rate for peer %pM. Device will not switch to any other selected rates", -+ sta->addr); ++ sta->deflink.addr); + + rate_code = ATH12K_HW_RATE_CODE(eht_rate, nss - 1, + WMI_RATE_PREAMBLE_EHT); + -+ ret = ath12k_wmi_set_peer_param(ar, sta->addr, ++ ret = ath12k_wmi_set_peer_param(ar, sta->deflink.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", -+ sta->addr, rate_code, ret); ++ sta->deflink.addr, rate_code, ret); + + return ret; +} @@ -421,7 +421,7 @@ Signed-off-by: Aloka Dixit static int ath12k_station_assoc(struct ath12k *ar, struct ieee80211_vif *vif, struct ieee80211_sta *sta, -@@ -3747,7 +3928,7 @@ static int ath12k_station_assoc(struct a +@@ -3801,7 +3982,7 @@ static int ath12k_station_assoc(struct a struct cfg80211_chan_def def; enum nl80211_band band; struct cfg80211_bitrate_mask *mask; @@ -430,7 +430,7 @@ Signed-off-by: Aloka Dixit lockdep_assert_held(&ar->conf_mutex); -@@ -3774,10 +3955,11 @@ static int ath12k_station_assoc(struct a +@@ -3828,10 +4009,11 @@ static int ath12k_station_assoc(struct a 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); @@ -444,13 +444,13 @@ Signed-off-by: Aloka Dixit + * specific fixed param. * Note that all other rates and NSS will be disabled for this peer. */ - if (sta->vht_cap.vht_supported && num_vht_rates == 1) { -@@ -3790,7 +3972,12 @@ static int ath12k_station_assoc(struct a + if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) { +@@ -3844,7 +4026,12 @@ static int ath12k_station_assoc(struct a band); if (ret) return ret; - } -+ } else if (sta->eht_cap.has_eht && num_eht_rates == 1) { ++ } else if (sta->deflink.eht_cap.has_eht && num_eht_rates == 1) { + ret = ath12k_mac_set_peer_eht_fixed_rate(arvif, sta, mask, + band); + if (ret) @@ -459,7 +459,7 @@ Signed-off-by: Aloka Dixit /* Re-assoc is run only to update supported rates for given station. It * doesn't make much sense to reconfigure the peer completely. -@@ -3861,8 +4048,9 @@ static void ath12k_sta_rc_update_wk(stru +@@ -3916,8 +4103,9 @@ static void ath12k_sta_rc_update_wk(stru const u8 *ht_mcs_mask; const u16 *vht_mcs_mask; const u16 *he_mcs_mask; @@ -470,7 +470,7 @@ Signed-off-by: Aloka Dixit const struct cfg80211_bitrate_mask *mask; struct peer_assoc_params peer_arg; -@@ -3878,6 +4066,7 @@ static void ath12k_sta_rc_update_wk(stru +@@ -3933,6 +4121,7 @@ static void ath12k_sta_rc_update_wk(stru 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; @@ -478,7 +478,7 @@ Signed-off-by: Aloka Dixit spin_lock_bh(&ar->data_lock); -@@ -3893,9 +4082,10 @@ static void ath12k_sta_rc_update_wk(stru +@@ -3948,9 +4137,10 @@ static void ath12k_sta_rc_update_wk(stru mutex_lock(&ar->conf_mutex); nss = max_t(u32, 1, nss); @@ -491,8 +491,8 @@ Signed-off-by: Aloka Dixit + ath12k_mac_max_eht_nss(eht_mcs_mask))); if (changed & IEEE80211_RC_BW_CHANGED) { - err = ath12k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, -@@ -3933,6 +4123,8 @@ static void ath12k_sta_rc_update_wk(stru + err = ath12k_wmi_set_peer_param(ar, sta->deflink.addr, arvif->vdev_id, +@@ -3988,6 +4178,8 @@ static void ath12k_sta_rc_update_wk(stru mask); num_he_rates = ath12k_mac_bitrate_mask_num_he_rates(ar, band, mask); @@ -501,11 +501,11 @@ Signed-off-by: Aloka Dixit /* Peer_assoc_prepare will reject vht rates in * bitrate_mask if its not available in range format and -@@ -3951,9 +4143,12 @@ static void ath12k_sta_rc_update_wk(stru - } else if (sta->he_cap.has_he && num_he_rates == 1) { +@@ -4006,9 +4198,12 @@ static void ath12k_sta_rc_update_wk(stru + } else if (sta->deflink.he_cap.has_he && num_he_rates == 1) { ath12k_mac_set_peer_he_fixed_rate(arvif, sta, mask, band); -+ } else if (sta->eht_cap.has_eht && num_eht_rates == 1) { ++ } else if (sta->deflink.eht_cap.has_eht && num_eht_rates == 1) { + ath12k_mac_set_peer_eht_fixed_rate(arvif, sta, mask, + band); } else { @@ -516,7 +516,7 @@ Signed-off-by: Aloka Dixit * other rates using peer_assoc command. Also clear * the peer fixed rate settings as it has higher proprity * than peer assoc -@@ -5712,6 +5907,8 @@ static int ath12k_mac_op_add_interface(s +@@ -5783,6 +5978,8 @@ static int ath12k_mac_op_add_interface(s 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)); @@ -525,7 +525,7 @@ Signed-off-by: Aloka Dixit } bit = __ffs64(ab->free_vdev_map); -@@ -6762,6 +6959,9 @@ ath12k_mac_has_single_legacy_rate(struct +@@ -6835,6 +7032,9 @@ ath12k_mac_has_single_legacy_rate(struct if (ath12k_mac_bitrate_mask_num_he_rates(ar, band, mask)) return false; @@ -535,7 +535,7 @@ Signed-off-by: Aloka Dixit return num_rates == 1; } -@@ -6788,9 +6988,12 @@ ath12k_mac_bitrate_mask_get_single_nss(s +@@ -6861,9 +7061,12 @@ ath12k_mac_bitrate_mask_get_single_nss(s struct ieee80211_supported_band *sband = &ar->mac.sbands[band]; u16 vht_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map); u16 he_mcs_map = 0; @@ -548,7 +548,7 @@ Signed-off-by: Aloka Dixit int i; /* No need to consider legacy here. Basic rates are always present -@@ -6830,7 +7033,57 @@ ath12k_mac_bitrate_mask_get_single_nss(s +@@ -6903,7 +7106,57 @@ ath12k_mac_bitrate_mask_get_single_nss(s return false; } @@ -607,7 +607,7 @@ Signed-off-by: Aloka Dixit return false; if (ht_nss_mask == 0) -@@ -6878,53 +7131,58 @@ ath12k_mac_get_single_legacy_rate(struct +@@ -6951,53 +7204,58 @@ ath12k_mac_get_single_legacy_rate(struct } static int @@ -683,7 +683,7 @@ Signed-off-by: Aloka Dixit break; default: ath12k_warn(ar->ab, "Invalid GI\n"); -@@ -6932,16 +7190,16 @@ ath12k_mac_set_auto_rate_GI_LTF(struct a +@@ -7005,16 +7263,16 @@ ath12k_mac_set_auto_rate_GI_LTF(struct a } } @@ -705,7 +705,7 @@ Signed-off-by: Aloka Dixit break; default: ath12k_warn(ar->ab, "Invalid LTF\n"); -@@ -6949,16 +7207,16 @@ ath12k_mac_set_auto_rate_GI_LTF(struct a +@@ -7022,16 +7280,16 @@ ath12k_mac_set_auto_rate_GI_LTF(struct a } } @@ -725,7 +725,7 @@ Signed-off-by: Aloka Dixit return ret; } -@@ -6967,7 +7225,9 @@ ath12k_mac_set_auto_rate_GI_LTF(struct a +@@ -7040,7 +7298,9 @@ ath12k_mac_set_auto_rate_GI_LTF(struct a static int ath12k_mac_set_rate_params(struct ath12k_vif *arvif, u32 rate, u8 nss, u8 sgi, u8 ldpc, @@ -736,7 +736,7 @@ Signed-off-by: Aloka Dixit { struct ath12k *ar = arvif->ar; u32 vdev_param; -@@ -6983,7 +7243,11 @@ static int ath12k_mac_set_rate_params(st +@@ -7056,7 +7316,11 @@ static int ath12k_mac_set_rate_params(st "he_gi:0x%02x, he_ltf:0x%02x, he_fixed_rate:%d\n", he_gi, he_ltf, he_fixed_rate); @@ -749,7 +749,7 @@ Signed-off-by: Aloka Dixit vdev_param = WMI_VDEV_PARAM_FIXED_RATE; ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, vdev_param, rate); -@@ -7012,7 +7276,17 @@ static int ath12k_mac_set_rate_params(st +@@ -7085,7 +7349,17 @@ static int ath12k_mac_set_rate_params(st return ret; } @@ -768,7 +768,7 @@ Signed-off-by: Aloka Dixit if (he_fixed_rate) { ret = ath12k_mac_set_fixed_rate_GI_LTF(arvif, he_gi, he_ltf); -@@ -7086,6 +7360,37 @@ ath12k_mac_he_mcs_range_present(struct a +@@ -7159,6 +7433,37 @@ ath12k_mac_he_mcs_range_present(struct a return true; } @@ -806,7 +806,7 @@ Signed-off-by: Aloka Dixit static void ath12k_mac_set_bitrate_mask_iter(void *data, struct ieee80211_sta *sta) { -@@ -7118,17 +7423,18 @@ static void ath12k_mac_disable_peer_fixe +@@ -7191,17 +7496,18 @@ static void ath12k_mac_disable_peer_fixe } static bool @@ -830,7 +830,7 @@ Signed-off-by: Aloka Dixit if (ath12k_mac_bitrate_mask_num_vht_rates(ar, band, mask) == 1) vht_fixed_rate = true; -@@ -7136,11 +7442,15 @@ ath12k_mac_validate_vht_he_fixed_rate_se +@@ -7209,11 +7515,15 @@ ath12k_mac_validate_vht_he_fixed_rate_se if (ath12k_mac_bitrate_mask_num_he_rates(ar, band, mask) == 1) he_fixed_rate = true; @@ -847,19 +847,19 @@ Signed-off-by: Aloka Dixit rcu_read_lock(); spin_lock_bh(&ar->ab->base_lock); -@@ -7156,6 +7466,11 @@ ath12k_mac_validate_vht_he_fixed_rate_se +@@ -7229,6 +7539,11 @@ ath12k_mac_validate_vht_he_fixed_rate_se ret = false; goto exit; } -+ if (eht_fixed_rate && (!peer->sta->eht_cap.has_eht || -+ peer->sta->rx_nss < eht_nss)) { ++ if (eht_fixed_rate && (!peer->sta->deflink.eht_cap.has_eht || ++ peer->sta->deflink.rx_nss < eht_nss)) { + ret = false; + goto exit; + } } } exit: -@@ -7176,8 +7491,11 @@ ath12k_mac_op_set_bitrate_mask(struct ie +@@ -7249,8 +7564,11 @@ ath12k_mac_op_set_bitrate_mask(struct ie const u8 *ht_mcs_mask; const u16 *vht_mcs_mask; const u16 *he_mcs_mask; @@ -871,7 +871,7 @@ Signed-off-by: Aloka Dixit u32 rate; u8 nss; u8 sgi; -@@ -7186,6 +7504,7 @@ ath12k_mac_op_set_bitrate_mask(struct ie +@@ -7259,6 +7577,7 @@ ath12k_mac_op_set_bitrate_mask(struct ie int ret; int num_rates; bool he_fixed_rate = false; @@ -879,7 +879,7 @@ Signed-off-by: Aloka Dixit if (ath12k_mac_vif_chan(vif, &def)) return -EPERM; -@@ -7194,6 +7513,7 @@ ath12k_mac_op_set_bitrate_mask(struct ie +@@ -7267,6 +7586,7 @@ ath12k_mac_op_set_bitrate_mask(struct ie ht_mcs_mask = mask->control[band].ht_mcs; vht_mcs_mask = mask->control[band].vht_mcs; he_mcs_mask = mask->control[band].he_mcs; @@ -887,7 +887,7 @@ Signed-off-by: Aloka Dixit ldpc = !!(ar->ht_cap_info & WMI_HT_CAP_LDPC); sgi = mask->control[band].gi; -@@ -7203,6 +7523,9 @@ ath12k_mac_op_set_bitrate_mask(struct ie +@@ -7276,6 +7596,9 @@ ath12k_mac_op_set_bitrate_mask(struct ie he_gi = mask->control[band].he_gi; he_ltf = mask->control[band].he_ltf; @@ -897,7 +897,7 @@ Signed-off-by: Aloka Dixit /* 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 -@@ -7235,13 +7558,14 @@ ath12k_mac_op_set_bitrate_mask(struct ie +@@ -7308,13 +7631,14 @@ ath12k_mac_op_set_bitrate_mask(struct ie } else { rate = WMI_FIXED_RATE_NONE; @@ -916,7 +916,7 @@ Signed-off-by: Aloka Dixit /* If multiple rates across different preambles are given * we can reconfigure this info with all peers using PEER_ASSOC -@@ -7288,6 +7612,18 @@ ath12k_mac_op_set_bitrate_mask(struct ie +@@ -7361,6 +7685,18 @@ ath12k_mac_op_set_bitrate_mask(struct ie return -EINVAL; } @@ -935,7 +935,7 @@ Signed-off-by: Aloka Dixit mutex_lock(&ar->conf_mutex); ieee80211_iterate_stations_atomic(ar->hw, ath12k_mac_disable_peer_fixed_rate, -@@ -7304,7 +7640,8 @@ ath12k_mac_op_set_bitrate_mask(struct ie +@@ -7377,7 +7713,8 @@ ath12k_mac_op_set_bitrate_mask(struct ie mutex_lock(&ar->conf_mutex); ret = ath12k_mac_set_rate_params(arvif, rate, nss, sgi, ldpc, he_gi, @@ -947,7 +947,7 @@ Signed-off-by: Aloka Dixit arvif->vdev_id, ret); --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -4964,6 +4964,7 @@ enum wmi_rate_preamble { +@@ -4885,6 +4885,7 @@ enum wmi_rate_preamble { WMI_RATE_PREAMBLE_HT, WMI_RATE_PREAMBLE_VHT, WMI_RATE_PREAMBLE_HE, diff --git a/feeds/ipq95xx/mac80211/patches/qca/586-mac80211-copy-MU-MIMO-and-OFDMA-EHT-capability-flags.patch b/feeds/ipq95xx/mac80211/patches/qca/586-mac80211-copy-MU-MIMO-and-OFDMA-EHT-capability-flags.patch index 304fa8b36..28b9d3630 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/586-mac80211-copy-MU-MIMO-and-OFDMA-EHT-capability-flags.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/586-mac80211-copy-MU-MIMO-and-OFDMA-EHT-capability-flags.patch @@ -15,20 +15,20 @@ Signed-off-by: Pradeep Kumar Chitrapu --- a/include/net/mac80211.h +++ b/include/net/mac80211.h -@@ -670,6 +670,12 @@ struct ieee80211_fils_discovery { - * @eht_support: does this BSS support EHT - * @eht_oper: EHT operation information of the BSS (AP/Mesh) or of the AP we - * are connected to (STA) +@@ -655,6 +655,12 @@ struct ieee80211_fils_discovery { + * @he_full_ul_mumimo: does this BSS support the reception (AP) or transmission + * (non-AP STA) of an HE TB PPDU on an RU that spans the entire PPDU + * bandwidth + * @eht_su_beamformer: does this BSS support operation as an EHT SU beamformer + * @eht_su_beamformee: does this BSS support operation as an EHT SU beamformee + * @eht_mu_beamformer: does this BSS support operation as an EHT MU beamformer + * @eht_80mhz_full_ul_mumimo: does this BSS support the reception (AP) or transmission + * (non-AP STA) of an EHT TB PPDU on an RU that spans the entire PPDU + * bandwidth - */ - struct ieee80211_bss_conf { - const u8 *bssid; -@@ -757,6 +763,10 @@ struct ieee80211_bss_conf { + * @he_obss_pd: OBSS Packet Detection parameters. + * @he_bss_color: BSS coloring settings, if BSS supports HE + * @fils_discovery: FILS discovery configuration +@@ -760,6 +766,10 @@ struct ieee80211_bss_conf { u8 ccfs; u8 present_bm; } eht_oper; @@ -37,11 +37,11 @@ Signed-off-by: Pradeep Kumar Chitrapu + bool eht_mu_beamformer; + bool eht_80mhz_full_bw_ul_mumimo; - /* Mesh configuration for nss offload */ - u8 nss_offld_ttl; + bool csa_active; + bool mu_mimo_owner; --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -1324,6 +1324,18 @@ static int ieee80211_start_ap(struct wip +@@ -1249,6 +1249,18 @@ static int ieee80211_start_ap(struct wip return -EOPNOTSUPP; sdata->vif.bss_conf.eht_support = true; diff --git a/feeds/ipq95xx/mac80211/patches/qca/588-ath12k-11be-bringup-fixes-for-D1.3-compatibility.patch b/feeds/ipq95xx/mac80211/patches/qca/588-ath12k-11be-bringup-fixes-for-D1.3-compatibility.patch index 554ee1dbd..c3b9937be 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/588-ath12k-11be-bringup-fixes-for-D1.3-compatibility.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/588-ath12k-11be-bringup-fixes-for-D1.3-compatibility.patch @@ -21,7 +21,7 @@ Signed-off-by: Aloka Dixit --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -5039,14 +5039,6 @@ ath12k_mac_filter_he_cap_mesh(struct iee +@@ -5108,14 +5108,6 @@ ath12k_mac_filter_he_cap_mesh(struct iee IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU | IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU; he_cap_elem->phy_cap_info[8] &= ~m; @@ -36,7 +36,7 @@ Signed-off-by: Aloka Dixit } static __le16 ath12k_mac_setup_he_6ghz_cap(struct ath12k_pdev_cap *pcap, -@@ -5156,14 +5148,10 @@ static void ath12k_mac_copy_he_cap(struc +@@ -5226,14 +5218,10 @@ static void ath12k_mac_copy_he_cap(struc case NL80211_IFTYPE_AP: he_cap_elem->phy_cap_info[3] &= ~IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK; @@ -53,7 +53,7 @@ Signed-off-by: Aloka Dixit ath12k_mac_filter_he_cap_mesh(he_cap_elem); --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h -@@ -2806,14 +2806,16 @@ ieee80211_eht_mcs_nss_size(const struct +@@ -2892,14 +2892,16 @@ ieee80211_eht_mcs_nss_size(const struct { u8 count = 0; @@ -78,7 +78,7 @@ Signed-off-by: Aloka Dixit count += 3; if (he_cap->phy_cap_info[0] & -@@ -2823,7 +2825,7 @@ ieee80211_eht_mcs_nss_size(const struct +@@ -2909,7 +2911,7 @@ ieee80211_eht_mcs_nss_size(const struct if (eht_cap->phy_cap_info[0] & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ) count += 3; @@ -87,7 +87,7 @@ Signed-off-by: Aloka Dixit } /* 802.11be EHT PPE Thresholds */ -@@ -2874,7 +2876,8 @@ ieee80211_eht_capa_size_ok(const u8 *he_ +@@ -2960,7 +2962,8 @@ ieee80211_eht_capa_size_ok(const u8 *he_ return false; if (elem->phy_cap_info[5] & @@ -99,9 +99,9 @@ Signed-off-by: Aloka Dixit if (len < needed + sizeof(ppe_thres_hdr)) --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h -@@ -3277,7 +3277,7 @@ enum nl80211_attrs { - #define NL80211_HE_MAX_CAPABILITY_LEN 54 - #define NL80211_MAX_NR_CIPHER_SUITES 5 +@@ -3362,7 +3362,7 @@ enum nl80211_attrs { + * present in %NL80211_CMD_GET_WIPHY response. + */ #define NL80211_MAX_NR_AKM_SUITES 2 -#define NL80211_EHT_MIN_CAPABILITY_LEN 13 +#define NL80211_EHT_MIN_CAPABILITY_LEN 12 @@ -110,7 +110,7 @@ Signed-off-by: Aloka Dixit #define NL80211_MIN_REMAIN_ON_CHANNEL_TIME 10 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -1317,7 +1317,7 @@ static int ieee80211_start_ap(struct wip +@@ -1244,7 +1244,7 @@ static int ieee80211_start_ap(struct wip IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO; } @@ -121,7 +121,7 @@ Signed-off-by: Aloka Dixit --- a/net/mac80211/eht.c +++ b/net/mac80211/eht.c -@@ -35,7 +35,8 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(stru +@@ -36,7 +36,8 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(stru /* Calculate the PPE thresholds length only if the header is present */ if (eht_cap_ie_elem->fixed.phy_cap_info[5] & @@ -133,12 +133,12 @@ Signed-off-by: Aloka Dixit if (eht_cap_len < eht_total_size + sizeof(u16)) --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c -@@ -3578,7 +3578,7 @@ static bool ieee80211_assoc_success(stru +@@ -4080,7 +4080,7 @@ static bool ieee80211_assoc_config_link( - changed |= ieee80211_recalc_twt_req(sdata, sta, elems); + *changed |= ieee80211_recalc_twt_req(link, link_sta, elems); - if (elems->eht_operation && elems->eht_cap && + if (elems->eht_cap && - !(ifmgd->flags & IEEE80211_STA_DISABLE_EHT)) { + !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_EHT)) { ieee80211_eht_cap_ie_to_sta_eht_cap(sdata, sband, elems->he_cap, diff --git a/feeds/ipq95xx/mac80211/patches/qca/589-ath12k-workaround-to-match-STA.patch b/feeds/ipq95xx/mac80211/patches/qca/589-ath12k-workaround-to-match-STA.patch index 5ade8cad5..88dee483a 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/589-ath12k-workaround-to-match-STA.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/589-ath12k-workaround-to-match-STA.patch @@ -6,64 +6,9 @@ Subject: [PATCH] ath12k: workaround to match STA Signed-off-by: Pradeep Kumar Chitrapu Signed-off-by: Aloka Dixit ---- a/drivers/net/wireless/mac80211_hwsim.c -+++ b/drivers/net/wireless/mac80211_hwsim.c -@@ -2963,7 +2963,7 @@ static const struct ieee80211_sband_ifty - .has_eht = true, - .eht_cap_elem = { - .mac_cap_info[0] = -- IEEE80211_EHT_MAC_CAP0_NSEP_PRIO_ACCESS | -+ IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS | - IEEE80211_EHT_MAC_CAP0_OM_CONTROL | - IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1, - .phy_cap_info[0] = -@@ -3223,7 +3223,7 @@ static const struct ieee80211_sband_ifty - .has_eht = true, - .eht_cap_elem = { - .mac_cap_info[0] = -- IEEE80211_EHT_MAC_CAP0_NSEP_PRIO_ACCESS | -+ IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS | - IEEE80211_EHT_MAC_CAP0_OM_CONTROL | - IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1, - .phy_cap_info[0] = --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h -@@ -2018,20 +2018,14 @@ struct ieee80211_eht_cap_elem { - - /** - * struct ieee80211_eht_operation - eht operation element -- * -- * This structure is the "EHT Operation Element" fields as -- * described in P802.11be_D1.4 section 9.4.2.311 -- * -- * FIXME: The spec is unclear how big the fields are, and doesn't -- * indicate the "Disabled Subchannel Bitmap Present" in the -- * structure (Figure 9-1002a) at all ... - */ - struct ieee80211_eht_operation { -- u8 chan_width; -+ u8 chan_width:3, -+ reserved1:5; - u8 ccfs; -- u8 present_bm; -- -- u8 disable_subchannel_bitmap[]; -+ u8 disable_sub_chan_bitmap_present:1, -+ reserved2:7; -+ u8 disable_subchannel_bitmap[2]; - } __packed; - - #define IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT 0x1 -@@ -2714,7 +2708,7 @@ ieee80211_he_spr_size(const u8 *he_spr_i - #define S1G_OPER_CH_WIDTH_OPER GENMASK(4, 1) - - /* EHT MAC capabilities as defined in P802.11be_D1.4 section 9.4.2.313.2 */ --#define IEEE80211_EHT_MAC_CAP0_NSEP_PRIO_ACCESS 0x01 -+#define IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS 0x01 - #define IEEE80211_EHT_MAC_CAP0_OM_CONTROL 0x02 - #define IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 0x04 - #define IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2 0x08 -@@ -2799,6 +2793,8 @@ ieee80211_he_spr_size(const u8 *he_spr_i +@@ -2885,6 +2885,8 @@ ieee80211_he_spr_size(const u8 *he_spr_i #define IEEE80211_EHT_OPER_CHAN_WIDTH_160MHZ 3 #define IEEE80211_EHT_OPER_CHAN_WIDTH_320MHZ 4 @@ -72,7 +17,7 @@ Signed-off-by: Aloka Dixit /* Calculate 802.11be EHT capabilities IE Tx/Rx EHT MCS NSS Support Field size */ static inline u8 ieee80211_eht_mcs_nss_size(const struct ieee80211_he_cap_elem *he_cap, -@@ -2870,6 +2866,9 @@ ieee80211_eht_capa_size_ok(const u8 *he_ +@@ -2956,6 +2958,9 @@ ieee80211_eht_capa_size_ok(const u8 *he_ if (len < needed || !he_capa) return false; @@ -82,27 +27,17 @@ Signed-off-by: Aloka Dixit needed += ieee80211_eht_mcs_nss_size((const void *)he_capa, (const void *)data); if (len < needed) -@@ -2900,9 +2899,6 @@ ieee80211_eht_oper_size_ok(const u8 *dat - if (len < needed) - return false; - -- if (elem->present_bm & IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT) -- needed += 2; -- - return len >= needed; - } - --- a/net/mac80211/eht.c +++ b/net/mac80211/eht.c -@@ -15,7 +15,6 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(stru - u8 eht_cap_len, struct sta_info *sta) +@@ -16,7 +16,6 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(stru + struct link_sta_info *link_sta) { - struct ieee80211_sta_eht_cap *eht_cap = &sta->sta.eht_cap; + struct ieee80211_sta_eht_cap *eht_cap = &link_sta->pub->eht_cap; - struct ieee80211_he_cap_elem *he_cap_ie_elem = (void *)he_cap_ie; u8 eht_ppe_size = 0; u8 mcs_nss_size; u8 eht_total_size = sizeof(eht_cap->eht_cap_elem); -@@ -28,8 +27,11 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(stru +@@ -29,8 +28,11 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(stru ieee80211_vif_type_p2p(&sdata->vif))) return; @@ -115,25 +50,15 @@ Signed-off-by: Aloka Dixit eht_total_size += mcs_nss_size; -@@ -82,7 +84,7 @@ void ieee80211_eht_op_ie_to_bss_conf(str - if (!op_ie) - return; - -- vif->bss_conf.eht_oper.chan_width = op_ie->chan_width; -+ vif->bss_conf.eht_oper.chan_width = u8_get_bits(op_ie->chan_width, IEEE80211_EHT_OPER_CHAN_WIDTH); - vif->bss_conf.eht_oper.ccfs = op_ie->ccfs; -- vif->bss_conf.eht_oper.present_bm = op_ie->present_bm; -+ vif->bss_conf.eht_oper.present_bm = u8_get_bits(op_ie->chan_width, IEEE80211_EHT_OPER_PRESENT_BM); - } --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c -@@ -497,10 +497,12 @@ void ieee80211_sta_set_rx_nss(struct sta +@@ -529,10 +529,12 @@ void ieee80211_sta_set_rx_nss(struct lin - if (sta->sta.eht_cap.has_eht) { + if (link_sta->pub->eht_cap.has_eht) { int i; -+ int eht_mcs_set_size = ieee80211_eht_mcs_nss_size(&sta->sta.he_cap, -+ &sta->sta.eht_cap); - const u8 *rx_nss_mcs = (void *)&sta->sta.eht_cap.eht_mcs_nss_supp; ++ int eht_mcs_set_size = ieee80211_eht_mcs_nss_size(&link_sta->pub->he_cap, ++ &link_sta->pub->eht_cap); + const u8 *rx_nss_mcs = (void *)&link_sta->pub->eht_cap.eht_mcs_nss_supp; /* get the max nss for EHT over all possible bandwidths and mcs */ - for (i = 0; i < sizeof(struct ieee80211_eht_mcs_nss_supp); i++) diff --git a/feeds/ipq95xx/mac80211/patches/qca/590-nl80211-advertise-RU-puncturing-support-to-userspace.patch b/feeds/ipq95xx/mac80211/patches/qca/590-nl80211-advertise-RU-puncturing-support-to-userspace.patch index 357423086..34b173b66 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/590-nl80211-advertise-RU-puncturing-support-to-userspace.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/590-nl80211-advertise-RU-puncturing-support-to-userspace.patch @@ -20,10 +20,10 @@ Signed-off-by: Aloka Dixit --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h -@@ -5198,6 +5198,10 @@ struct wiphy_iftype_akm_suites { - * @ema_max_profile_periodicity: maximum profile periodicity supported by - * the driver. Setting this field to a non-zero value indicates that the - * driver supports enhanced multi-BSSID advertisements (EMA AP). +@@ -5344,6 +5344,10 @@ struct wiphy_iftype_akm_suites { + * NL80211_MAX_NR_AKM_SUITES in order to avoid compatibility issues with + * legacy userspace and maximum allowed value is + * CFG80211_MAX_NUM_AKM_SUITES. + * + * @ru_punct_supp_bw: Whether the driver supports RU puncturing, and if so, + * for which bandwidths. See &enum nl80211_ru_punct_supp_bw for the @@ -31,9 +31,9 @@ Signed-off-by: Aloka Dixit */ struct wiphy { struct mutex mtx; -@@ -5348,6 +5352,8 @@ struct wiphy { - u8 mbssid_max_interfaces; +@@ -5495,6 +5499,8 @@ struct wiphy { u8 ema_max_profile_periodicity; + u16 max_num_akm_suites; + enum nl80211_ru_punct_supp_bw ru_punct_supp_bw; + @@ -42,28 +42,27 @@ Signed-off-by: Aloka Dixit --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h -@@ -2695,6 +2695,10 @@ enum nl80211_commands { - * association request when used with NL80211_CMD_NEW_STATION). Can be set - * only if %NL80211_STA_FLAG_WME is set. +@@ -2772,6 +2772,10 @@ enum nl80211_commands { + * for co-located APs and neighbor APs in ESS to be added in all + * EMA beacons. * + * @NL80211_ATTR_RU_PUNCT_SUPP_BW: (u8) Minimum bandwidth for which -+ * the driver supports preamble puncturing, value should be of type -+ * &enum nl80211_ru_punct_supp_bw ++ * the driver supports preamble puncturing, value should be of type ++ * &enum nl80211_ru_punct_supp_bw + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use -@@ -3222,6 +3226,9 @@ enum nl80211_attrs { - NL80211_ATTR_EHT_CAPABILITY = NL80211_ATTR_MBSSID_ELEMS + 15, +@@ -3314,6 +3318,8 @@ enum nl80211_attrs { + + NL80211_ATTR_EMA_RNR_ELEMS, - NL80211_ATTR_DISABLE_EHT, -+ + NL80211_ATTR_RU_PUNCT_SUPP_BW, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, -@@ -7729,6 +7736,23 @@ enum nl80211_ap_settings_flags { +@@ -7828,6 +7834,23 @@ enum nl80211_ap_settings_flags { }; /** @@ -89,7 +88,7 @@ Signed-off-by: Aloka Dixit */ --- a/net/wireless/core.c +++ b/net/wireless/core.c -@@ -908,6 +908,10 @@ int wiphy_register(struct wiphy *wiphy) +@@ -899,6 +899,10 @@ int wiphy_register(struct wiphy *wiphy) return -EINVAL; } @@ -102,16 +101,16 @@ Signed-off-by: Aloka Dixit * Validate we have a policy (can be explicitly set to --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c -@@ -831,6 +831,8 @@ static const struct nla_policy nl80211_p - .len = NL80211_EHT_MAX_CAPABILITY_LEN }, - #endif - [NL80211_ATTR_DISABLE_EHT] = { .type = NLA_FLAG }, +@@ -852,6 +852,8 @@ static const struct nla_policy nl80211_p + [NL80211_ATTR_AWGN_INTERFERENCE_BITMAP] = { .type = NLA_U32 }, + [NL80211_ATTR_6G_REG_POWER_MODE] = NLA_POLICY_RANGE(NLA_U8, 0, 2), + [NL80211_ATTR_EMA_RNR_ELEMS] = { .type = NLA_NESTED }, + [NL80211_ATTR_RU_PUNCT_SUPP_BW] = -+ NLA_POLICY_MAX(NLA_U8, NL80211_RU_PUNCT_SUPP_BW_320), ++ NLA_POLICY_MAX(NLA_U8, NL80211_RU_PUNCT_SUPP_BW_320), }; /* policy for the key attributes */ -@@ -2346,6 +2348,20 @@ fail: +@@ -2402,6 +2404,20 @@ fail: return -ENOBUFS; } @@ -132,9 +131,9 @@ Signed-off-by: Aloka Dixit struct nl80211_dump_wiphy_state { s64 filter_wiphy; long start; -@@ -2934,6 +2950,9 @@ static int nl80211_send_wiphy(struct cfg - if (nl80211_put_mbssid_support(&rdev->wiphy, msg)) - goto nla_put_failure; +@@ -3006,6 +3022,9 @@ static int nl80211_send_wiphy(struct cfg + if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_MLO) + nla_put_flag(msg, NL80211_ATTR_MLO_SUPPORT); + if (nl80211_put_ru_punct_supp_bw(rdev, msg)) + goto nla_put_failure; diff --git a/feeds/ipq95xx/mac80211/patches/qca/591-cfg80211-validate-RU-puncturing-bitmap.patch b/feeds/ipq95xx/mac80211/patches/qca/591-cfg80211-validate-RU-puncturing-bitmap.patch index 9548036d3..05afe6571 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/591-cfg80211-validate-RU-puncturing-bitmap.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/591-cfg80211-validate-RU-puncturing-bitmap.patch @@ -21,11 +21,9 @@ Signed-off-by: Aloka Dixit net/wireless/chan.c | 99 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 1 deletion(-) -Index: backports-20220209-5.4.164-f40abb4788/include/net/cfg80211.h -=================================================================== ---- backports-20220209-5.4.164-f40abb4788.orig/include/net/cfg80211.h -+++ backports-20220209-5.4.164-f40abb4788/include/net/cfg80211.h -@@ -747,6 +747,11 @@ struct key_params { +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -771,6 +771,11 @@ struct key_params { * chan will define the primary channel and all other * parameters are ignored. * @freq1_offset: offset from @center_freq1, in KHz @@ -37,7 +35,7 @@ Index: backports-20220209-5.4.164-f40abb4788/include/net/cfg80211.h */ struct cfg80211_chan_def { struct ieee80211_channel *chan; -@@ -755,6 +760,8 @@ struct cfg80211_chan_def { +@@ -779,6 +784,8 @@ struct cfg80211_chan_def { u32 center_freq2; struct ieee80211_edmg edmg; u16 freq1_offset; @@ -46,7 +44,7 @@ Index: backports-20220209-5.4.164-f40abb4788/include/net/cfg80211.h }; /* -@@ -886,7 +893,10 @@ cfg80211_chandef_identical(const struct +@@ -913,7 +920,10 @@ cfg80211_chandef_identical(const struct chandef1->width == chandef2->width && chandef1->center_freq1 == chandef2->center_freq1 && chandef1->freq1_offset == chandef2->freq1_offset && @@ -58,10 +56,8 @@ Index: backports-20220209-5.4.164-f40abb4788/include/net/cfg80211.h } /** -Index: backports-20220209-5.4.164-f40abb4788/net/wireless/chan.c -=================================================================== ---- backports-20220209-5.4.164-f40abb4788.orig/net/wireless/chan.c -+++ backports-20220209-5.4.164-f40abb4788/net/wireless/chan.c +--- a/net/wireless/chan.c ++++ b/net/wireless/chan.c @@ -32,6 +32,8 @@ void cfg80211_chandef_create(struct cfg8 chandef->center_freq2 = 0; chandef->edmg.bw_config = 0; @@ -71,7 +67,7 @@ Index: backports-20220209-5.4.164-f40abb4788/net/wireless/chan.c switch (chan_type) { case NL80211_CHAN_NO_HT: -@@ -196,6 +198,101 @@ static int cfg80211_chandef_get_width(co +@@ -196,6 +198,106 @@ static int cfg80211_chandef_get_width(co return nl80211_chan_width_to_mhz(c->width); } @@ -105,6 +101,9 @@ Index: backports-20220209-5.4.164-f40abb4788/net/wireless/chan.c + + switch (chandef->width) { + case NL80211_CHAN_WIDTH_80: ++ /* Subchannel bits outside operating BW shouldn't be set */ ++ if (chandef->ru_punct_bitmap & 0xFFF0) ++ return false; + bitmap &= 0xF; + non_ofdma_bitmap = &ru_punct_bitmap_80[0]; + non_ofdma_bitmap_count = ARRAY_SIZE(ru_punct_bitmap_80); @@ -112,6 +111,8 @@ Index: backports-20220209-5.4.164-f40abb4788/net/wireless/chan.c + break; + + case NL80211_CHAN_WIDTH_160: ++ if (chandef->ru_punct_bitmap & 0xFF00) ++ return false; + bitmap &= 0xFF; + non_ofdma_bitmap = &ru_punct_bitmap_160[0]; + non_ofdma_bitmap_count = ARRAY_SIZE(ru_punct_bitmap_160); @@ -173,7 +174,7 @@ Index: backports-20220209-5.4.164-f40abb4788/net/wireless/chan.c bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef) { u32 control_freq, oper_freq; -@@ -316,6 +413,9 @@ bool cfg80211_chandef_valid(const struct +@@ -321,6 +423,9 @@ bool cfg80211_chandef_valid(const struct !cfg80211_edmg_chandef_valid(chandef)) return false; diff --git a/feeds/ipq95xx/mac80211/patches/qca/592-nl80211-validate-RU-puncturing-bitmap.patch b/feeds/ipq95xx/mac80211/patches/qca/592-nl80211-validate-RU-puncturing-bitmap.patch index db2b3eada..81235563f 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/592-nl80211-validate-RU-puncturing-bitmap.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/592-nl80211-validate-RU-puncturing-bitmap.patch @@ -21,10 +21,10 @@ Signed-off-by: Aloka Dixit --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h -@@ -2698,6 +2698,13 @@ enum nl80211_commands { - * @NL80211_ATTR_RU_PUNCT_SUPP_BW: (u8) Minimum bandwidth for which - * the driver supports preamble puncturing, value should be of type - * &enum nl80211_ru_punct_supp_bw +@@ -2776,6 +2776,14 @@ enum nl80211_commands { + * the driver supports preamble puncturing, value should be of type + * &enum nl80211_ru_punct_supp_bw + * + * @NL80211_ATTR_RU_PUNCT_SUPP_HE: flag attribute, used to indicate that RU + * puncturing bitmap validation should include OFDMA bitmaps. + * @@ -32,10 +32,11 @@ Signed-off-by: Aloka Dixit + * bit corresponds to the lowest 20 MHz channel. Each bit set to 1 + * indicates that the sub-channel is punctured, set 0 indicates that the + * channel is active. - * ++ * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined -@@ -3229,6 +3236,10 @@ enum nl80211_attrs { + * @__NL80211_ATTR_AFTER_LAST: internal use +@@ -3320,6 +3328,10 @@ enum nl80211_attrs { NL80211_ATTR_RU_PUNCT_SUPP_BW, @@ -48,16 +49,16 @@ Signed-off-by: Aloka Dixit __NL80211_ATTR_AFTER_LAST, --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c -@@ -833,6 +833,8 @@ static const struct nla_policy nl80211_p - [NL80211_ATTR_DISABLE_EHT] = { .type = NLA_FLAG }, +@@ -854,6 +854,8 @@ static const struct nla_policy nl80211_p + [NL80211_ATTR_EMA_RNR_ELEMS] = { .type = NLA_NESTED }, [NL80211_ATTR_RU_PUNCT_SUPP_BW] = - NLA_POLICY_MAX(NLA_U8, NL80211_RU_PUNCT_SUPP_BW_320), + NLA_POLICY_MAX(NLA_U8, NL80211_RU_PUNCT_SUPP_BW_320), + [NL80211_ATTR_RU_PUNCT_SUPP_HE] = { .type = NLA_FLAG }, + [NL80211_ATTR_RU_PUNCT_BITMAP] = { .type = NLA_U16 }, }; /* policy for the key attributes */ -@@ -3167,6 +3169,46 @@ static bool nl80211_can_set_dev_channel( +@@ -3239,6 +3241,46 @@ static bool nl80211_can_set_dev_channel( wdev->iftype == NL80211_IFTYPE_P2P_GO; } @@ -104,7 +105,7 @@ Signed-off-by: Aloka Dixit int nl80211_parse_chandef(struct cfg80211_registered_device *rdev, struct genl_info *info, struct cfg80211_chan_def *chandef) -@@ -3175,6 +3217,7 @@ int nl80211_parse_chandef(struct cfg8021 +@@ -3247,6 +3289,7 @@ int nl80211_parse_chandef(struct cfg8021 struct nlattr **attrs = info->attrs; enum nl80211_regulatory_power_modes mode = NL80211_REG_AP_LPI; u32 control_freq; @@ -112,7 +113,7 @@ Signed-off-by: Aloka Dixit if (!attrs[NL80211_ATTR_WIPHY_FREQ]) return -EINVAL; -@@ -3262,6 +3305,12 @@ int nl80211_parse_chandef(struct cfg8021 +@@ -3343,6 +3386,12 @@ int nl80211_parse_chandef(struct cfg8021 nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ2]); } @@ -125,7 +126,7 @@ Signed-off-by: Aloka Dixit if (info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]) { chandef->edmg.channels = nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNELS]); -@@ -3735,6 +3784,16 @@ static int nl80211_send_chandef(struct s +@@ -3835,6 +3884,16 @@ static int nl80211_send_chandef(struct s if (chandef->center_freq2 && nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ2, chandef->center_freq2)) return -ENOBUFS; diff --git a/feeds/ipq95xx/mac80211/patches/qca/594-ath12k-advertise-RU-puncturing-support-to-kernel.patch b/feeds/ipq95xx/mac80211/patches/qca/594-ath12k-advertise-RU-puncturing-support-to-kernel.patch index 46dfcf8fb..d545c2af7 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/594-ath12k-advertise-RU-puncturing-support-to-kernel.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/594-ath12k-advertise-RU-puncturing-support-to-kernel.patch @@ -33,7 +33,7 @@ index 40809dc16fde..437a876000a5 100644 +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -8130,6 +8130,8 @@ static int __ath12k_mac_register(struct ath12k *ar) - ar->hw->wiphy->interface_modes = ab->hw_params.interface_modes; + ar->hw->wiphy->interface_modes = ab->hw_params->interface_modes; + ar->hw->wiphy->ru_punct_supp_bw = NL80211_RU_PUNCT_SUPP_BW_80; + diff --git a/feeds/ipq95xx/mac80211/patches/qca/595-ath12k-configure-RU-puncturing-bitmap.patch b/feeds/ipq95xx/mac80211/patches/qca/595-ath12k-configure-RU-puncturing-bitmap.patch index 8889c5e2e..0de873c60 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/595-ath12k-configure-RU-puncturing-bitmap.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/595-ath12k-configure-RU-puncturing-bitmap.patch @@ -24,15 +24,15 @@ Signed-off-by: Aloka Dixit reinit_completion(&ar->vdev_setup_done); reinit_completion(&ar->vdev_delete_done); -@@ -2220,6 +2222,7 @@ static void ath12k_peer_assoc_h_eht(stru +@@ -2264,6 +2266,7 @@ static void ath12k_peer_assoc_h_eht(stru max_nss = max(max_nss, (uint8_t)eht_nss); - arg->peer_nss = min(sta->rx_nss, max_nss); + arg->peer_nss = min(sta->deflink.rx_nss, max_nss); + arg->ru_punct_bitmap = ~def.ru_punct_bitmap; ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac he peer %pM nss %d mcs cnt %d\n", -@@ -6409,6 +6412,7 @@ ath12k_mac_vdev_start_restart(struct ath +@@ -6502,6 +6505,7 @@ ath12k_mac_vdev_start_restart(struct ath 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 * 2; @@ -40,39 +40,50 @@ Signed-off-by: Aloka Dixit arg.pref_tx_streams = ar->num_tx_chains; arg.pref_rx_streams = ar->num_rx_chains; +@@ -6527,8 +6531,8 @@ ath12k_mac_vdev_start_restart(struct ath + arg.channel.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR); + + ath12k_dbg(ab, ATH12K_DBG_MAC, +- "mac vdev %d start center_freq %d phymode %s\n", +- arg.vdev_id, arg.channel.freq, ++ "mac vdev %d start center_freq %d punct bitmap 0x%x phymode %s\n", ++ arg.vdev_id, arg.channel.freq, arg.ru_punct_bitmap, + ath12k_wmi_phymode_str(arg.channel.mode)); + + ret = ath12k_wmi_vdev_start(ar, &arg, restart); --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -937,6 +937,7 @@ int ath12k_wmi_vdev_start(struct ath12k - cmd->cac_duration_ms = arg->cac_duration_ms; - cmd->regdomain = arg->regdomain; - cmd->he_ops = arg->he_ops; -+ cmd->ru_punct_bitmap = arg->ru_punct_bitmap; +@@ -979,6 +979,7 @@ int ath12k_wmi_vdev_start(struct ath12k + cmd->cac_duration_ms = cpu_to_le32(arg->cac_duration_ms); + cmd->regdomain = cpu_to_le32(arg->regdomain); + cmd->he_ops = cpu_to_le32(arg->he_ops); ++ cmd->ru_punct_bitmap = cpu_to_le32(arg->ru_punct_bitmap); if (!restart) { if (arg->ssid) { -@@ -1899,6 +1900,7 @@ int ath12k_wmi_send_peer_assoc_cmd(struc +@@ -1929,6 +1930,7 @@ int ath12k_wmi_send_peer_assoc_cmd(struc - cmd->peer_new_assoc = param->peer_new_assoc; - cmd->peer_associd = param->peer_associd; -+ cmd->ru_punct_bitmap = param->ru_punct_bitmap; + cmd->peer_new_assoc = cpu_to_le32(param->peer_new_assoc); + cmd->peer_associd = cpu_to_le32(param->peer_associd); ++ cmd->ru_punct_bitmap = cpu_to_le32(param->ru_punct_bitmap); ath12k_wmi_copy_peer_flags(cmd, param, test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -2729,6 +2729,11 @@ struct wmi_vdev_start_request_cmd { - u32 he_ops; - u32 cac_duration_ms; - u32 regdomain; -+ u32 min_data_rate; -+ u32 mbss_capability_flags; -+ u32 vdevid_trans; -+ u32 eht_ops; -+ u32 ru_punct_bitmap; +@@ -2724,6 +2724,11 @@ struct wmi_vdev_start_request_cmd { + __le32 he_ops; + __le32 cac_duration_ms; + __le32 regdomain; ++ __le32 min_data_rate; ++ __le32 mbss_capability_flags; ++ __le32 vdevid_trans; ++ __le32 eht_ops; ++ __le32 ru_punct_bitmap; } __packed; #define MGMT_TX_DL_FRM_LEN 64 -@@ -2925,6 +2930,7 @@ struct wmi_vdev_start_req_arg { +@@ -2920,6 +2925,7 @@ struct wmi_vdev_start_req_arg { u32 pref_rx_streams; u32 pref_tx_streams; u32 num_noa_descriptors; @@ -80,7 +91,7 @@ Signed-off-by: Aloka Dixit }; struct peer_create_params { -@@ -3802,6 +3808,7 @@ struct peer_assoc_params { +@@ -3763,6 +3769,7 @@ struct peer_assoc_params { u32 peer_eht_tx_mcs_set[WMI_MAX_EHTCAP_RATE_SET]; u32 peer_eht_ops; struct ath12k_ppe_threshold peer_eht_ppet; @@ -88,12 +99,12 @@ Signed-off-by: Aloka Dixit }; struct wmi_peer_assoc_complete_cmd { -@@ -3837,7 +3844,7 @@ struct wmi_peer_assoc_complete_cmd { - u32 bss_max_idle_option; - u32 auth_mode; - u32 peer_flags_ext; -- u32 puncture_20mhz_bitmap; -+ u32 ru_punct_bitmap; - u32 peer_eht_cap_mac[WMI_MAX_EHTCAP_MAC_SIZE]; - u32 peer_eht_cap_phy[WMI_MAX_EHTCAP_PHY_SIZE]; - u32 peer_eht_ops; +@@ -3798,7 +3805,7 @@ struct wmi_peer_assoc_complete_cmd { + __le32 bss_max_idle_option; + __le32 auth_mode; + __le32 peer_flags_ext; +- __le32 puncture_20mhz_bitmap; ++ __le32 ru_punct_bitmap; + __le32 peer_eht_cap_mac[WMI_MAX_EHTCAP_MAC_SIZE]; + __le32 peer_eht_cap_phy[WMI_MAX_EHTCAP_PHY_SIZE]; + __le32 peer_eht_ops; diff --git a/feeds/ipq95xx/mac80211/patches/qca/596-ath12k-Add-support-for-QDSS-dump-collection.patch b/feeds/ipq95xx/mac80211/patches/qca/596-ath12k-Add-support-for-QDSS-dump-collection.patch index dba105847..600003eb0 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/596-ath12k-Add-support-for-QDSS-dump-collection.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/596-ath12k-Add-support-for-QDSS-dump-collection.patch @@ -32,11 +32,9 @@ Signed-off-by: Dinesh Karthikeyan drivers/net/wireless/ath/ath12k/qmi.h | 78 +++ 5 files changed, 932 insertions(+) -Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.c -=================================================================== ---- backports-20220209-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/core.c 2022-03-16 20:03:13.010096087 +0530 -+++ backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.c 2022-03-16 20:03:13.010096087 +0530 -@@ -728,6 +728,9 @@ +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -704,6 +704,9 @@ int ath12k_core_qmi_firmware_ready(struc goto err_core_stop; } ath12k_hif_irq_enable(ab); @@ -46,19 +44,17 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor mutex_unlock(&ab->core_lock); return 0; -Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.h -=================================================================== ---- backports-20220209-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/core.h 2022-03-16 20:03:13.010096087 +0530 -+++ backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.h 2022-03-16 20:03:13.010096087 +0530 -@@ -808,6 +808,7 @@ +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -809,6 +809,7 @@ struct ath12k_base { - struct ath12k_hw_params hw_params; + const struct ath12k_hw_params *hw_params; struct ath12k_bus_params bus_params; + bool is_qdss_tracing; const struct firmware *cal_file; -@@ -860,6 +861,8 @@ +@@ -861,6 +862,8 @@ struct ath12k_base { u64 fw_soc_drop_count; @@ -67,7 +63,7 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor /* must be last */ u8 drv_priv[0] __aligned(sizeof(void *)); }; -@@ -1009,6 +1012,7 @@ +@@ -1007,6 +1010,7 @@ int ath12k_core_check_dt(struct ath12k_b void ath12k_core_halt(struct ath12k *ar); int ath12k_core_resume(struct ath12k_base *ab); int ath12k_core_suspend(struct ath12k_base *ab); @@ -75,104 +71,8 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor const struct firmware *ath12k_core_firmware_request(struct ath12k_base *ab, const char *filename); -Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs.c -=================================================================== ---- backports-20220209-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/debugfs.c 2022-03-16 20:03:13.010096087 +0530 -+++ backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs.c 2022-03-16 20:03:13.010096087 +0530 -@@ -839,6 +839,79 @@ - .llseek = default_llseek, - }; - -+static ssize_t ath12k_read_trace_qdss(struct file *file, -+ char __user *user_buf, -+ size_t count, loff_t *ppos) -+{ -+ const char buf[] = -+ "1 - this will start qdss trace collection\n" -+ "0 - this will stop and save the qdss trace collection\n"; -+ -+ return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); -+} -+ -+static ssize_t -+ath12k_write_trace_qdss(struct file *file, -+ const char __user *user_buf, -+ size_t count, loff_t *ppos) -+{ -+ struct ath12k_base *ab = file->private_data; -+ struct ath12k_pdev *pdev; -+ struct ath12k *ar; -+ int i, ret; -+ bool radioup = false; -+ bool qdss_enable; -+ -+ if (kstrtobool_from_user(user_buf, count, &qdss_enable)) -+ return -EINVAL; -+ -+ for (i = 0; i < ab->num_radios; i++) { -+ pdev = &ab->pdevs[i]; -+ ar = pdev->ar; -+ if (ar && ar->state == ATH12K_STATE_ON) { -+ radioup = true; -+ break; -+ } -+ } -+ -+ if (!radioup) { -+ ath12k_err(ab, "radio is not up\n"); -+ ret = -ENETDOWN; -+ goto exit; -+ } -+ -+ if (qdss_enable) { -+ if (ab->is_qdss_tracing) { -+ ret = count; -+ goto exit; -+ } -+ ath12k_config_qdss(ab); -+ } else { -+ if (!ab->is_qdss_tracing) { -+ ret = count; -+ goto exit; -+ } -+ ret = ath12k_send_qdss_trace_mode_req(ab, -+ QMI_WLANFW_QDSS_TRACE_OFF_V01); -+ if (ret < 0) -+ ath12k_warn(ab, -+ "Failed to stop QDSS: %d\n", ret); -+ } -+ -+ ret = count; -+ -+exit: -+ return ret; -+} -+ -+static const struct file_operations fops_trace_qdss = { -+ .read = ath12k_read_trace_qdss, -+ .write = ath12k_write_trace_qdss, -+ .open = simple_open, -+ .owner = THIS_MODULE, -+ .llseek = default_llseek, -+}; -+ - int ath12k_debugfs_pdev_create(struct ath12k_base *ab) - { - if (test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags)) -@@ -850,6 +923,9 @@ - debugfs_create_file("soc_dp_stats", 0600, ab->debugfs_soc, ab, - &fops_soc_dp_stats); - -+ debugfs_create_file("trace_qdss", 0600, ab->debugfs_soc, ab, -+ &fops_trace_qdss); -+ - return 0; - } - -Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi.c -=================================================================== ---- backports-20220209-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/qmi.c 2022-03-16 20:03:13.010096087 +0530 -+++ backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi.c 2022-03-16 20:03:48.890894677 +0530 +--- a/drivers/net/wireless/ath/ath12k/qmi.c ++++ b/drivers/net/wireless/ath/ath12k/qmi.c @@ -9,6 +9,7 @@ #include "qmi.h" #include "core.h" @@ -181,127 +81,10 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi #include #include #include -@@ -23,6 +24,190 @@ - MODULE_PARM_DESC(cold_boot_cal, - "Decrease the channel switch time but increase the driver load time (Default: true)"); +@@ -178,6 +179,73 @@ static struct qmi_elem_info wlfw_host_ml + }, + }; -+static struct qmi_elem_info qmi_wlfw_qdss_trace_config_download_req_msg_v01_ei[] = { -+ { -+ .data_type = QMI_OPT_FLAG, -+ .elem_len = 1, -+ .elem_size = sizeof(u8), -+ .array_type = NO_ARRAY, -+ .tlv_type = 0x10, -+ .offset = offsetof(struct -+ qmi_wlanfw_qdss_trace_config_download_req_msg_v01, -+ total_size_valid), -+ }, -+ { -+ .data_type = QMI_UNSIGNED_4_BYTE, -+ .elem_len = 1, -+ .elem_size = sizeof(u32), -+ .array_type = NO_ARRAY, -+ .tlv_type = 0x10, -+ .offset = offsetof(struct -+ qmi_wlanfw_qdss_trace_config_download_req_msg_v01, -+ total_size), -+ }, -+ { -+ .data_type = QMI_OPT_FLAG, -+ .elem_len = 1, -+ .elem_size = sizeof(u8), -+ .array_type = NO_ARRAY, -+ .tlv_type = 0x11, -+ .offset = offsetof(struct -+ qmi_wlanfw_qdss_trace_config_download_req_msg_v01, -+ seg_id_valid), -+ }, -+ { -+ .data_type = QMI_UNSIGNED_4_BYTE, -+ .elem_len = 1, -+ .elem_size = sizeof(u32), -+ .array_type = NO_ARRAY, -+ .tlv_type = 0x11, -+ .offset = offsetof(struct -+ qmi_wlanfw_qdss_trace_config_download_req_msg_v01, -+ seg_id), -+ }, -+ { -+ .data_type = QMI_OPT_FLAG, -+ .elem_len = 1, -+ .elem_size = sizeof(u8), -+ .array_type = NO_ARRAY, -+ .tlv_type = 0x12, -+ .offset = offsetof(struct -+ qmi_wlanfw_qdss_trace_config_download_req_msg_v01, -+ data_valid), -+ }, -+ { -+ .data_type = QMI_DATA_LEN, -+ .elem_len = 1, -+ .elem_size = sizeof(u16), -+ .array_type = NO_ARRAY, -+ .tlv_type = 0x12, -+ .offset = offsetof(struct -+ qmi_wlanfw_qdss_trace_config_download_req_msg_v01, -+ data_len), -+ }, -+ { -+ .data_type = QMI_UNSIGNED_1_BYTE, -+ .elem_len = QMI_WLANFW_MAX_DATA_SIZE_V01, -+ .elem_size = sizeof(u8), -+ .array_type = VAR_LEN_ARRAY, -+ .tlv_type = 0x12, -+ .offset = offsetof(struct -+ qmi_wlanfw_qdss_trace_config_download_req_msg_v01, -+ data), -+ }, -+ { -+ .data_type = QMI_OPT_FLAG, -+ .elem_len = 1, -+ .elem_size = sizeof(u8), -+ .array_type = NO_ARRAY, -+ .tlv_type = 0x13, -+ .offset = offsetof(struct -+ qmi_wlanfw_qdss_trace_config_download_req_msg_v01, -+ end_valid), -+ }, -+ { -+ .data_type = QMI_UNSIGNED_1_BYTE, -+ .elem_len = 1, -+ .elem_size = sizeof(u8), -+ .array_type = NO_ARRAY, -+ .tlv_type = 0x13, -+ .offset = offsetof(struct -+ qmi_wlanfw_qdss_trace_config_download_req_msg_v01, -+ end), -+ }, -+ { -+ .data_type = QMI_EOTI, -+ .array_type = NO_ARRAY, -+ .tlv_type = QMI_COMMON_TLV_TYPE, -+ }, -+}; -+ -+static struct qmi_elem_info qmi_wlanfw_qdss_trace_config_download_resp_msg_v01_ei[] = { -+ { -+ .data_type = QMI_STRUCT, -+ .elem_len = 1, -+ .elem_size = sizeof(struct qmi_response_type_v01), -+ .array_type = NO_ARRAY, -+ .tlv_type = 0x02, -+ .offset = offsetof(struct -+ qmi_wlanfw_qdss_trace_config_download_resp_msg_v01, -+ resp), -+ .ei_array = qmi_response_type_v01_ei, -+ }, -+ { -+ .data_type = QMI_EOTI, -+ .array_type = NO_ARRAY, -+ .tlv_type = QMI_COMMON_TLV_TYPE, -+ }, -+}; -+ +static struct qmi_elem_info qmi_wlanfw_qdss_trace_mode_req_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, @@ -372,7 +155,7 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi static struct qmi_elem_info qmi_wlanfw_host_cap_req_msg_v01_ei[] = { { .data_type = QMI_OPT_FLAG, -@@ -618,6 +803,42 @@ +@@ -864,6 +932,42 @@ static struct qmi_elem_info qmi_wlanfw_i cal_done_enable), }, { @@ -415,7 +198,7 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi .data_type = QMI_EOTI, .array_type = NO_ARRAY, .tlv_type = QMI_COMMON_TLV_TYPE, -@@ -1654,6 +1875,85 @@ +@@ -1997,6 +2101,85 @@ static struct qmi_elem_info qmi_wlanfw_w }, }; @@ -501,80 +284,10 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi static struct qmi_elem_info qmi_wlanfw_mem_ready_ind_msg_v01_ei[] = { { .data_type = QMI_EOTI, -@@ -1675,6 +1975,144 @@ - }, - }; +@@ -2089,6 +2272,47 @@ out: + return ret; + } -+int ath12k_qmi_send_qdss_trace_config_download_req(struct ath12k_base *ab, -+ const u8 *buffer, unsigned int buffer_len) -+{ -+ int ret = 0; -+ struct qmi_wlanfw_qdss_trace_config_download_req_msg_v01 *req; -+ struct qmi_wlanfw_qdss_trace_config_download_resp_msg_v01 resp; -+ struct qmi_txn txn; -+ const u8 *temp = buffer; -+ int max_len = QMI_WLANFW_QDSS_TRACE_CONFIG_DOWNLOAD_REQ_MSG_V01_MAX_LEN; -+ unsigned int remaining; -+ -+ req = kzalloc(sizeof(*req), GFP_KERNEL); -+ if (!req) -+ return -ENOMEM; -+ -+ remaining = buffer_len; -+ while (remaining) { -+ memset(&resp, 0, sizeof(resp)); -+ req->total_size_valid = 1; -+ req->total_size = buffer_len; -+ req->seg_id_valid = 1; -+ req->data_valid = 1; -+ req->end_valid = 1; -+ -+ if (remaining > QMI_WLANFW_MAX_DATA_SIZE_V01) { -+ req->data_len = QMI_WLANFW_MAX_DATA_SIZE_V01; -+ } else { -+ req->data_len = remaining; -+ req->end = 1; -+ } -+ memcpy(req->data, temp, req->data_len); -+ -+ ret = qmi_txn_init(&ab->qmi.handle, &txn, -+ qmi_wlanfw_qdss_trace_config_download_resp_msg_v01_ei, -+ &resp); -+ if (ret < 0) -+ goto out; -+ -+ ret = qmi_send_request(&ab->qmi.handle, NULL, &txn, -+ QMI_WLANFW_QDSS_TRACE_CONFIG_DOWNLOAD_REQ_V01, -+ max_len, -+ qmi_wlfw_qdss_trace_config_download_req_msg_v01_ei, -+ req); -+ if (ret < 0) { -+ ath12k_warn(ab, "Failed to send QDSS config download request = %d\n", -+ ret); -+ qmi_txn_cancel(&txn); -+ goto out; -+ } -+ -+ ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH12K_QMI_WLANFW_TIMEOUT_MS)); -+ if (ret < 0) -+ goto out; -+ -+ if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { -+ ath12k_warn(ab, "QDSS config download request failed, result: %d, err: %d\n", -+ resp.resp.result, resp.resp.error); -+ ret = -EINVAL; -+ goto out; -+ } -+ remaining -= req->data_len; -+ temp += req->data_len; -+ req->seg_id++; -+ } -+ -+out: -+ kfree(req); -+ return ret; -+} -+ +int ath12k_send_qdss_trace_mode_req(struct ath12k_base *ab, + enum qmi_wlanfw_qdss_trace_mode_enum_v01 mode) +{ @@ -616,37 +329,10 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi + return ret; +} + -+static int ath12k_qmi_send_qdss_config(struct ath12k_base *ab) -+{ -+ struct device *dev = ab->dev; -+ const struct firmware *fw_entry; -+ char filename[ATH12K_QMI_MAX_QDSS_CONFIG_FILE_NAME_SIZE]; -+ int ret; -+ -+ snprintf(filename, sizeof(filename), -+ "%s/%s/%s", ATH12K_FW_DIR, ab->hw_params.fw.dir, -+ ATH12K_QMI_DEFAULT_QDSS_CONFIG_FILE_NAME); -+ ret = request_firmware(&fw_entry, filename, dev); -+ if (ret) { -+ ath12k_warn(ab, "qmi failed to load QDSS config: %s\n", filename); -+ return ret; -+ } -+ -+ ret = ath12k_qmi_send_qdss_trace_config_download_req(ab, fw_entry->data, -+ fw_entry->size); -+ if (ret < 0) { -+ ath12k_warn(ab, "qmi failed to load QDSS config to FW: %d\n", ret); -+ goto out; -+ } -+out: -+ release_firmware(fw_entry); -+ return ret; -+} -+ - static int ath12k_qmi_host_cap_send(struct ath12k_base *ab) + static int ath12k_qmi_send_qdss_config(struct ath12k_base *ab) { - struct qmi_wlanfw_host_cap_req_msg_v01 req; -@@ -1773,6 +2211,12 @@ + unsigned int config_len; +@@ -2241,6 +2465,12 @@ static int ath12k_qmi_fw_ind_register_se req->cal_done_enable = 1; req->fw_init_done_enable_valid = 1; req->fw_init_done_enable = 1; @@ -659,7 +345,7 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi req->pin_connect_result_enable_valid = 0; req->pin_connect_result_enable = 0; -@@ -2572,6 +3016,18 @@ +@@ -3074,6 +3304,18 @@ out: return ret; } @@ -678,7 +364,7 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi void ath12k_qmi_firmware_stop(struct ath12k_base *ab) { int ret; -@@ -2629,6 +3085,37 @@ +@@ -3131,6 +3373,37 @@ static int ath12k_qmi_process_coldboot_c return 0; } @@ -716,7 +402,7 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi static int ath12k_qmi_driver_event_post(struct ath12k_qmi *qmi, enum ath12k_qmi_event_type type, -@@ -2686,6 +3173,190 @@ +@@ -3188,6 +3461,191 @@ static int ath12k_qmi_event_mem_request( return ret; } @@ -735,7 +421,7 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi + + switch (ab->qmi.qdss_mem[0].type) { + case QDSS_ETR_MEM_REGION_TYPE: -+ if (ab->qmi.qdss_mem[0].size > QMI_Q6_QDSS_ETR_SIZE_QCN92XX) { ++ if (ab->qmi.qdss_mem[0].size > QMI_Q6_QDSS_ETR_SIZE_QCN9274) { + ath12k_warn(ab, "%s: FW requests more memory 0x%x\n", + __func__, ab->qmi.qdss_mem[0].size); + return -ENOMEM; @@ -748,12 +434,13 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi + } + + ret = of_address_to_resource(ab->hremote_node, 0, &res); ++ of_node_put(ab->hremote_node); + if (ret) { + ath12k_warn(ab, "qmi fail to get reg from hremote\n"); + return ret; + } + -+ ab->qmi.qdss_mem[0].paddr = (phys_addr_t)res.start + QMI_Q6_QDSS_ETR_OFFSET_QCN92XX; ++ ab->qmi.qdss_mem[0].paddr = (phys_addr_t)res.start + QMI_Q6_QDSS_ETR_OFFSET_QCN9274; + ab->qmi.qdss_mem[0].v.ioaddr = + ioremap(ab->qmi.qdss_mem[0].paddr, + ab->qmi.qdss_mem[0].size); @@ -907,7 +594,7 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi static int ath12k_qmi_event_load_bdf(struct ath12k_qmi *qmi) { struct ath12k_base *ab = qmi->ab; -@@ -2803,6 +3474,84 @@ +@@ -3312,6 +3770,84 @@ static void ath12k_qmi_msg_cold_boot_cal ath12k_dbg(ab, ATH12K_DBG_QMI, "qmi cold boot calibration done\n"); } @@ -992,7 +679,7 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi static const struct qmi_msg_handler ath12k_qmi_msg_handlers[] = { { .type = QMI_INDICATION, -@@ -2833,6 +3582,22 @@ +@@ -3342,6 +3878,22 @@ static const struct qmi_msg_handler ath1 sizeof(struct qmi_wlanfw_fw_cold_cal_done_ind_msg_v01), .fn = ath12k_qmi_msg_cold_boot_cal_done_cb, }, @@ -1015,7 +702,7 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi }; static int ath12k_qmi_ops_new_server(struct qmi_handle *qmi_hdl, -@@ -2935,6 +3700,12 @@ +@@ -3444,6 +3996,12 @@ static void ath12k_qmi_driver_event_work break; case ATH12K_QMI_EVENT_COLD_BOOT_CAL_DONE: break; @@ -1028,11 +715,9 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi default: ath12k_warn(ab, "invalid event type: %d", event->type); break; -Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi.h -=================================================================== ---- backports-20220209-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/qmi.h 2022-03-16 20:03:13.010096087 +0530 -+++ backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi.h 2022-03-16 20:03:13.010096087 +0530 -@@ -27,11 +27,17 @@ +--- a/drivers/net/wireless/ath/ath12k/qmi.h ++++ b/drivers/net/wireless/ath/ath12k/qmi.h +@@ -29,11 +29,17 @@ #define ATH12K_QMI_FW_MEM_REQ_SEGMENT_CNT 3 #define ATH12K_QMI_WLFW_MAX_DEV_MEM_NUM_V01 4 #define ATH12K_QMI_DEVMEM_CMEM_INDEX 0 @@ -1044,13 +729,13 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi #define QMI_WLFW_COLD_BOOT_CAL_DONE_IND_V01 0x0021 #define QMI_WLFW_FW_READY_IND_V01 0x0038 +#define QMI_WLFW_QDSS_TRACE_REQ_MEM_IND_V01 0x003F -+#define QMI_Q6_QDSS_ETR_SIZE_QCN92XX 0x100000 ++#define QMI_Q6_QDSS_ETR_SIZE_QCN9274 0x100000 +#define QMI_WLFW_QDSS_TRACE_SAVE_IND_V01 0x0041 -+#define QMI_Q6_QDSS_ETR_OFFSET_QCN92XX 0x2500000 ++#define QMI_Q6_QDSS_ETR_OFFSET_QCN9274 0x2500000 #define QMI_WLANFW_MAX_DATA_SIZE_V01 6144 #define ATH12K_FIRMWARE_MODE_OFF 4 -@@ -67,6 +73,8 @@ +@@ -71,6 +77,8 @@ enum ath12k_qmi_event_type { ATH12K_QMI_EVENT_FORCE_FW_ASSERT, ATH12K_QMI_EVENT_POWER_UP, ATH12K_QMI_EVENT_POWER_DOWN, @@ -1059,76 +744,7 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi ATH12K_QMI_EVENT_MAX, }; -@@ -136,6 +144,8 @@ - struct ath12k_qmi_ce_cfg ce_cfg; - struct target_mem_chunk target_mem[ATH12K_QMI_WLANFW_MAX_NUM_MEM_SEG_V01]; - u32 mem_seg_count; -+ struct target_mem_chunk qdss_mem[ATH12K_QMI_WLANFW_MAX_NUM_MEM_SEG_V01]; -+ u32 qdss_mem_seg_len; - u32 target_mem_mode; - bool target_mem_delayed; - u8 cal_done; -@@ -146,6 +156,51 @@ - struct dev_mem_info dev_mem[ATH12K_QMI_WLFW_MAX_DEV_MEM_NUM_V01]; - }; - -+#define QMI_WLANFW_QDSS_TRACE_CONFIG_DOWNLOAD_REQ_MSG_V01_MAX_LEN 6167 -+#define QMI_WLANFW_QDSS_TRACE_CONFIG_DOWNLOAD_RESP_MSG_V01_MAX_LEN 7 -+#define QMI_WLANFW_QDSS_TRACE_CONFIG_DOWNLOAD_REQ_V01 0x0044 -+#define QMI_WLANFW_QDSS_TRACE_CONFIG_DOWNLOAD_RESP_V01 0x0044 -+ -+struct qmi_wlanfw_qdss_trace_config_download_req_msg_v01 { -+ u8 total_size_valid; -+ u32 total_size; -+ u8 seg_id_valid; -+ u32 seg_id; -+ u8 data_valid; -+ u32 data_len; -+ u8 data[QMI_WLANFW_MAX_DATA_SIZE_V01]; -+ u8 end_valid; -+ u8 end; -+}; -+ -+struct qmi_wlanfw_qdss_trace_config_download_resp_msg_v01 { -+ struct qmi_response_type_v01 resp; -+}; -+ -+#define QMI_WLANFW_QDSS_TRACE_MODE_REQ_V01 0x0045 -+#define QMI_WLANFW_QDSS_TRACE_MODE_REQ_MSG_V01_MAX_LEN 25 -+#define QMI_WLANFW_QDSS_TRACE_MODE_RESP_MSG_V01_MAX_LEN 7 -+#define QMI_WLANFW_QDSS_TRACE_MODE_RESP_V01 0x0045 -+#define QMI_WLANFW_QDSS_STOP_ALL_TRACE 0x01 -+ -+enum qmi_wlanfw_qdss_trace_mode_enum_v01 { -+ WLFW_QDSS_TRACE_MODE_ENUM_MIN_VAL_V01 = INT_MIN, -+ QMI_WLANFW_QDSS_TRACE_OFF_V01 = 0, -+ QMI_WLANFW_QDSS_TRACE_ON_V01 = 1, -+ WLFW_QDSS_TRACE_MODE_ENUM_MAX_VAL_V01 = INT_MAX, -+}; -+ -+struct qmi_wlanfw_qdss_trace_mode_req_msg_v01 { -+ u8 mode_valid; -+ enum qmi_wlanfw_qdss_trace_mode_enum_v01 mode; -+ u8 option_valid; -+ u64 option; -+}; -+ -+struct qmi_wlanfw_qdss_trace_mode_resp_msg_v01 { -+ struct qmi_response_type_v01 resp; -+}; -+ - #define QMI_WLANFW_HOST_CAP_REQ_MSG_V01_MAX_LEN 261 - #define QMI_WLANFW_HOST_CAP_REQ_V01 0x0034 - #define QMI_WLANFW_HOST_CAP_RESP_MSG_V01_MAX_LEN 7 -@@ -158,6 +213,7 @@ - #define CALDB_MEM_REGION_TYPE 0x4 - #define QMI_WLANFW_MAX_PLATFORM_NAME_LEN_V01 64 - #define QMI_WLANFW_MAX_HOST_DDR_RANGE_SIZE_V01 3 -+#define QDSS_ETR_MEM_REGION_TYPE 0x6 - - struct qmi_wlanfw_host_ddr_range { - u64 start; -@@ -249,6 +305,12 @@ +@@ -325,6 +333,12 @@ struct qmi_wlanfw_ind_register_req_msg_v u8 xo_cal_enable; u8 cal_done_enable_valid; u8 cal_done_enable; @@ -1141,16 +757,7 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi }; struct qmi_wlanfw_ind_register_resp_msg_v01 { -@@ -264,6 +326,8 @@ - #define QMI_WLANFW_RESPOND_MEM_REQ_V01 0x0036 - #define QMI_WLANFW_RESPOND_MEM_RESP_V01 0x0036 - #define QMI_WLANFW_MAX_NUM_MEM_CFG_V01 2 -+#define QMI_WLFW_QDSS_TRACE_MEM_INFO_REQ_V01 0x0040 -+#define QMI_WLANFW_MAX_STR_LEN_V01 16 - - struct qmi_wlanfw_mem_cfg_s_v01 { - u64 offset; -@@ -519,6 +583,30 @@ +@@ -607,6 +621,30 @@ struct qmi_wlanfw_wlan_cfg_resp_msg_v01 struct qmi_response_type_v01 resp; }; @@ -1181,21 +788,16 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi int ath12k_qmi_firmware_start(struct ath12k_base *ab, u32 mode); void ath12k_qmi_firmware_stop(struct ath12k_base *ab); -@@ -526,5 +614,9 @@ - void ath12k_qmi_msg_recv_work(struct work_struct *work); +@@ -615,4 +653,6 @@ void ath12k_qmi_msg_recv_work(struct wor void ath12k_qmi_deinit_service(struct ath12k_base *ab); int ath12k_qmi_init_service(struct ath12k_base *ab); -+int ath12k_qmi_send_qdss_trace_config_download_req(struct ath12k_base *ab, -+ const u8 *buffer, unsigned int len); +int ath12k_send_qdss_trace_mode_req(struct ath12k_base *ab, + enum qmi_wlanfw_qdss_trace_mode_enum_v01 mode); #endif -Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/coredump.c -=================================================================== ---- backports-20220209-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/coredump.c 2022-03-16 20:03:13.010096087 +0530 -+++ backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/coredump.c 2022-03-16 20:03:13.010096087 +0530 -@@ -220,3 +220,72 @@ +--- a/drivers/net/wireless/ath/ath12k/coredump.c ++++ b/drivers/net/wireless/ath/ath12k/coredump.c +@@ -220,3 +220,72 @@ void ath12k_coredump_download_rddm(struc kfree(segment); } @@ -1268,11 +870,9 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor + kfree(dump); +} + -Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/coredump.h -=================================================================== ---- backports-20220209-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/coredump.h 2022-03-16 20:03:13.010096087 +0530 -+++ backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/coredump.h 2022-03-16 20:03:13.010096087 +0530 -@@ -71,6 +71,8 @@ +--- a/drivers/net/wireless/ath/ath12k/coredump.h ++++ b/drivers/net/wireless/ath/ath12k/coredump.h +@@ -71,6 +71,8 @@ struct ath12k_coredump_segment_info { void ath12k_coredump_download_rddm(struct ath12k_base *ab); void ath12k_coredump_build_inline(struct ath12k_base *ab, struct ath12k_dump_segment *segments, int num_seg); @@ -1281,7 +881,7 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor #else static inline void ath12k_coredump_download_rddm(struct ath12k_base *ab) { -@@ -81,6 +83,11 @@ +@@ -81,6 +83,11 @@ static inline void ath12k_coredump_build int num_seg) { } @@ -1293,3 +893,94 @@ Index: backports-20220209-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor #endif #endif +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -839,6 +839,79 @@ static const struct file_operations fops + .llseek = default_llseek, + }; + ++static ssize_t ath12k_read_trace_qdss(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ const char buf[] = ++ "1 - this will start qdss trace collection\n" ++ "0 - this will stop and save the qdss trace collection\n"; ++ ++ return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); ++} ++ ++static ssize_t ++ath12k_write_trace_qdss(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k_base *ab = file->private_data; ++ struct ath12k_pdev *pdev; ++ struct ath12k *ar; ++ int i, ret; ++ bool radioup = false; ++ bool qdss_enable; ++ ++ if (kstrtobool_from_user(user_buf, count, &qdss_enable)) ++ return -EINVAL; ++ ++ for (i = 0; i < ab->num_radios; i++) { ++ pdev = &ab->pdevs[i]; ++ ar = pdev->ar; ++ if (ar && ar->state == ATH12K_STATE_ON) { ++ radioup = true; ++ break; ++ } ++ } ++ ++ if (!radioup) { ++ ath12k_err(ab, "radio is not up\n"); ++ ret = -ENETDOWN; ++ goto exit; ++ } ++ ++ if (qdss_enable) { ++ if (ab->is_qdss_tracing) { ++ ret = count; ++ goto exit; ++ } ++ ath12k_config_qdss(ab); ++ } else { ++ if (!ab->is_qdss_tracing) { ++ ret = count; ++ goto exit; ++ } ++ ret = ath12k_send_qdss_trace_mode_req(ab, ++ QMI_WLANFW_QDSS_TRACE_OFF_V01); ++ if (ret < 0) ++ ath12k_warn(ab, ++ "Failed to stop QDSS: %d\n", ret); ++ } ++ ++ ret = count; ++ ++exit: ++ return ret; ++} ++ ++static const struct file_operations fops_trace_qdss = { ++ .read = ath12k_read_trace_qdss, ++ .write = ath12k_write_trace_qdss, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ + int ath12k_debugfs_pdev_create(struct ath12k_base *ab) + { + if (test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags)) +@@ -850,6 +923,8 @@ int ath12k_debugfs_pdev_create(struct at + debugfs_create_file("soc_dp_stats", 0600, ab->debugfs_soc, ab, + &fops_soc_dp_stats); + ++ debugfs_create_file("trace_qdss", 0600, ab->debugfs_soc, ab, ++ &fops_trace_qdss); + return 0; + } + diff --git a/feeds/ipq95xx/mac80211/patches/qca/597-ath12k-Add-support-for-wmi-based-fw-log.patch b/feeds/ipq95xx/mac80211/patches/qca/597-ath12k-Add-support-for-wmi-based-fw-log.patch index a39f9f2bf..bb78cea8b 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/597-ath12k-Add-support-for-wmi-based-fw-log.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/597-ath12k-Add-support-for-wmi-based-fw-log.patch @@ -25,11 +25,9 @@ Signed-off-by: Dinesh Karthikeyan drivers/net/wireless/ath/ath12k/wmi.c | 27 +++++++++ 8 files changed, 177 insertions(+), 2 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c -index 954e17e..0a4929d 100644 --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c -@@ -731,6 +731,10 @@ int ath12k_core_qmi_firmware_ready(struct ath12k_base *ab) +@@ -707,6 +707,10 @@ int ath12k_core_qmi_firmware_ready(struc ath12k_config_qdss(ab); @@ -40,16 +38,15 @@ index 954e17e..0a4929d 100644 mutex_unlock(&ab->core_lock); return 0; -diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h -index 96b6d46..1f84a7b 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h -@@ -115,9 +115,11 @@ struct ath12k_skb_rxcb { +@@ -118,10 +118,12 @@ struct ath12k_skb_rxcb { }; enum ath12k_hw_rev { -- ATH12K_HW_QCN92XX_HW10, -+ ATH12K_HW_QCN92XX_HW10 = 0, +- ATH12K_HW_QCN9274_HW10, ++ ATH12K_HW_QCN9274_HW10 = 0, + ATH12K_HW_WCN7850_HW20 }; +#define ATH12K_DIAG_HW_ID_OFFSET 16 @@ -57,11 +54,9 @@ index 96b6d46..1f84a7b 100644 enum ath12k_firmware_mode { /* the default mode, standard 802.11 functionality */ ATH12K_FIRMWARE_MODE_NORMAL, -diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c -index 3996fbb..0e8e868 100644 --- a/drivers/net/wireless/ath/ath12k/qmi.c +++ b/drivers/net/wireless/ath/ath12k/qmi.c -@@ -1975,6 +1975,50 @@ static struct qmi_elem_info qmi_wlanfw_cold_boot_cal_done_ind_msg_v01_ei[] = { +@@ -2201,6 +2201,50 @@ static struct qmi_elem_info qmi_wlanfw_c }, }; @@ -109,10 +104,10 @@ index 3996fbb..0e8e868 100644 + }, +}; + - int ath12k_qmi_send_qdss_trace_config_download_req(struct ath12k_base *ab, - const u8 *buffer, unsigned int buffer_len) - { -@@ -3552,6 +3596,52 @@ free_event_data: + static int ath12k_qmi_send_qdss_trace_config_download_req(struct ath12k_base *ab, + const u8 *buffer, + unsigned int buffer_len) +@@ -3848,6 +3892,52 @@ free_event_data: kfree(event_data); } @@ -165,11 +160,9 @@ index 3996fbb..0e8e868 100644 static const struct qmi_msg_handler ath12k_qmi_msg_handlers[] = { { .type = QMI_INDICATION, -diff --git a/drivers/net/wireless/ath/ath12k/qmi.h b/drivers/net/wireless/ath/ath12k/qmi.h -index 5ad7727..72cc215 100644 --- a/drivers/net/wireless/ath/ath12k/qmi.h +++ b/drivers/net/wireless/ath/ath12k/qmi.h -@@ -607,6 +607,18 @@ struct ath12k_qmi_event_qdss_trace_save_data { +@@ -645,6 +645,18 @@ struct ath12k_qmi_event_qdss_trace_save_ struct qdss_trace_mem_seg mem_seg[QDSS_TRACE_SEG_LEN_MAX]; }; @@ -188,17 +181,15 @@ index 5ad7727..72cc215 100644 int ath12k_qmi_firmware_start(struct ath12k_base *ab, u32 mode); void ath12k_qmi_firmware_stop(struct ath12k_base *ab); -@@ -619,4 +631,5 @@ int ath12k_qmi_send_qdss_trace_config_download_req(struct ath12k_base *ab, +@@ -655,4 +667,5 @@ int ath12k_qmi_init_service(struct ath12 int ath12k_send_qdss_trace_mode_req(struct ath12k_base *ab, enum qmi_wlanfw_qdss_trace_mode_enum_v01 mode); +int ath12k_enable_fwlog(struct ath12k_base *ab); #endif -diff --git a/drivers/net/wireless/ath/ath12k/testmode.c b/drivers/net/wireless/ath/ath12k/testmode.c -index a09cb42..42bcfed 100644 --- a/drivers/net/wireless/ath/ath12k/testmode.c +++ b/drivers/net/wireless/ath/ath12k/testmode.c -@@ -19,8 +19,42 @@ static const struct nla_policy ath12k_tm_policy[ATH12K_TM_ATTR_MAX + 1] = { +@@ -19,8 +19,45 @@ static const struct nla_policy ath12k_tm [ATH12K_TM_ATTR_WMI_CMDID] = { .type = NLA_U32 }, [ATH12K_TM_ATTR_VERSION_MAJOR] = { .type = NLA_U32 }, [ATH12K_TM_ATTR_VERSION_MINOR] = { .type = NLA_U32 }, @@ -221,6 +212,9 @@ index a09cb42..42bcfed 100644 + } + } + ++ if (!ar) ++ return; ++ + nl_skb = cfg80211_testmode_alloc_event_skb(ar->hw->wiphy, len, GFP_ATOMIC); + + if (!nl_skb) { @@ -241,8 +235,6 @@ index a09cb42..42bcfed 100644 /* Returns true if callee consumes the skb and the skb should be discarded. * Returns false if skb is not used. Does not sleep. */ -diff --git a/drivers/net/wireless/ath/ath12k/testmode.h b/drivers/net/wireless/ath/ath12k/testmode.h -index d7cd997..79b9fc0 100644 --- a/drivers/net/wireless/ath/ath12k/testmode.h +++ b/drivers/net/wireless/ath/ath12k/testmode.h @@ -11,7 +11,7 @@ @@ -254,7 +246,7 @@ index d7cd997..79b9fc0 100644 #else static inline bool ath12k_tm_event_wmi(struct ath12k *ar, u32 cmd_id, -@@ -27,4 +27,8 @@ static inline int ath12k_tm_cmd(struct ieee80211_hw *hw, +@@ -27,4 +27,8 @@ static inline int ath12k_tm_cmd(struct i return 0; } @@ -263,8 +255,6 @@ index d7cd997..79b9fc0 100644 + +} #endif -diff --git a/drivers/net/wireless/ath/ath12k/testmode_i.h b/drivers/net/wireless/ath/ath12k/testmode_i.h -index f4fe2fe..7e0bbbd 100644 --- a/drivers/net/wireless/ath/ath12k/testmode_i.h +++ b/drivers/net/wireless/ath/ath12k/testmode_i.h @@ -24,6 +24,7 @@ enum ath12k_tm_attr { @@ -275,8 +265,6 @@ index f4fe2fe..7e0bbbd 100644 /* keep last */ __ATH12K_TM_ATTR_AFTER_LAST, -diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c -index dc46c51..5267075 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -19,6 +19,7 @@ @@ -287,7 +275,7 @@ index dc46c51..5267075 100644 struct wmi_tlv_policy { size_t min_len; -@@ -7092,6 +7093,29 @@ static void ath12k_wmi_event_wow_wakeup_host(struct ath12k_base *ab, struct sk_b +@@ -7273,6 +7274,29 @@ static void ath12k_wmi_event_wow_wakeup_ complete(&ab->wow.wakeup_completed); } @@ -305,7 +293,7 @@ index dc46c51..5267075 100644 + if (tlv_tag == WMI_TAG_ARRAY_BYTE) { + data = skb->data + sizeof(struct wmi_tlv); + dev_id = (uint32_t *)data; -+ *dev_id = ab->hw_params.hw_rev + ATH12K_DIAG_HW_ID_OFFSET; ++ *dev_id = ab->hw_params->hw_rev + ATH12K_DIAG_HW_ID_OFFSET; + } else { + ath12k_warn(ab, "WMI Diag Event missing required tlv\n"); + return; @@ -317,7 +305,7 @@ index dc46c51..5267075 100644 static void ath12k_wmi_tlv_op_rx(struct ath12k_base *ab, struct sk_buff *skb) { struct wmi_cmd_hdr *cmd_hdr; -@@ -7202,6 +7226,9 @@ static void ath12k_wmi_tlv_op_rx(struct ath12k_base *ab, struct sk_buff *skb) +@@ -7383,6 +7407,9 @@ static void ath12k_wmi_tlv_op_rx(struct case WMI_WOW_WAKEUP_HOST_EVENTID: ath12k_wmi_event_wow_wakeup_host(ab, skb); break; @@ -327,6 +315,3 @@ index dc46c51..5267075 100644 /* TODO: Add remaining events */ default: ath12k_dbg(ab, ATH12K_DBG_WMI, "Unknown eventid: 0x%x\n", id); --- -2.7.4 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/601-ath12k-Handle-FW-updated-MU-EDCA-params.patch b/feeds/ipq95xx/mac80211/patches/qca/601-ath12k-Handle-FW-updated-MU-EDCA-params.patch index abba80e1c..8564e7643 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/601-ath12k-Handle-FW-updated-MU-EDCA-params.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/601-ath12k-Handle-FW-updated-MU-EDCA-params.patch @@ -26,7 +26,7 @@ Signed-off-by: Muna Sinada + .min_len = sizeof(struct wmi_pdev_update_muedca_event) }, }; - static void ath12k_init_wmi_config_qcn92xx(struct ath12k_base *ab, + static void ath12k_init_wmi_config_qcn9274(struct ath12k_base *ab, @@ -7308,6 +7310,79 @@ static void ath12k_wmi_diag_event(struct ath12k_fwlog_write(ab, data, tlv_len); } diff --git a/feeds/ipq95xx/mac80211/patches/qca/602-ath12k-report-tx-bitrate-for-iw-wlan-station-dump.patch b/feeds/ipq95xx/mac80211/patches/qca/602-ath12k-report-tx-bitrate-for-iw-wlan-station-dump.patch index 0f209dc77..75f3e6f81 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/602-ath12k-report-tx-bitrate-for-iw-wlan-station-dump.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/602-ath12k-report-tx-bitrate-for-iw-wlan-station-dump.patch @@ -7,11 +7,9 @@ Subject: [PATCH 2/2] Add support to display EHT tx rate info in iw station Signed-off-by: Pradeep Kumar Chitrapu Signed-off-by: Balamurugan Mahalingam -diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h -index 5e7325d..b1cddfa 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h -@@ -425,6 +425,7 @@ struct ath12k_sta { +@@ -429,6 +429,7 @@ struct ath12k_sta { struct work_struct update_wk; struct rate_info txrate; @@ -19,140 +17,9 @@ index 5e7325d..b1cddfa 100644 struct rate_info last_txrate; u64 rx_duration; u64 tx_duration; -diff --git a/drivers/net/wireless/ath/ath12k/debugfs_sta.c b/drivers/net/wireless/ath/ath12k/debugfs_sta.c -index c8aebc3..12b336d 100644 ---- a/drivers/net/wireless/ath/ath12k/debugfs_sta.c -+++ b/drivers/net/wireless/ath/ath12k/debugfs_sta.c -@@ -176,103 +176,9 @@ void ath12k_debugfs_sta_add_tx_stats(struct ath12k_sta *arsta, - } - - void ath12k_debugfs_sta_update_txcompl(struct ath12k *ar, -- struct sk_buff *msdu, - struct hal_tx_status *ts) - { -- struct ath12k_base *ab = ar->ab; -- struct ath12k_per_peer_tx_stats *peer_stats = &ar->cached_stats; -- enum hal_tx_rate_stats_pkt_type pkt_type; -- enum hal_tx_rate_stats_sgi sgi; -- enum hal_tx_rate_stats_bw bw; -- struct ath12k_peer *peer; -- struct ath12k_sta *arsta; -- struct ieee80211_sta *sta; -- u16 num_tones_in_ru; -- u16 rate; -- u8 rate_idx = 0; -- int ret; -- u8 mcs; -- -- rcu_read_lock(); -- spin_lock_bh(&ab->base_lock); -- peer = ath12k_peer_find_by_id(ab, ts->peer_id); -- if (!peer || !peer->sta) { -- ath12k_warn(ab, "failed to find the peer\n"); -- spin_unlock_bh(&ab->base_lock); -- rcu_read_unlock(); -- return; -- } -- -- sta = peer->sta; -- arsta = (struct ath12k_sta *)sta->drv_priv; -- -- memset(&arsta->txrate, 0, sizeof(arsta->txrate)); -- pkt_type = FIELD_GET(HAL_TX_RATE_STATS_INFO0_PKT_TYPE, -- ts->rate_stats); -- mcs = FIELD_GET(HAL_TX_RATE_STATS_INFO0_MCS, -- ts->rate_stats); -- sgi = FIELD_GET(HAL_TX_RATE_STATS_INFO0_SGI, -- ts->rate_stats); -- bw = FIELD_GET(HAL_TX_RATE_STATS_INFO0_BW, ts->rate_stats); -- num_tones_in_ru = FIELD_GET(HAL_TX_RATE_STATS_INFO0_TONES_IN_RU, -- ts->rate_stats); -- -- if (pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11A || -- pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11B) { -- ret = ath12k_mac_hw_ratecode_to_legacy_rate(mcs, -- pkt_type, -- &rate_idx, -- &rate); -- if (ret < 0) -- goto err_out; -- arsta->txrate.legacy = rate; -- } else if (pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11N) { -- if (mcs > 7) { -- ath12k_warn(ab, "Invalid HT mcs index %d\n", mcs); -- goto err_out; -- } -- -- arsta->txrate.mcs = mcs + 8 * (arsta->last_txrate.nss - 1); -- arsta->txrate.flags = RATE_INFO_FLAGS_MCS; -- if (sgi) -- arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; -- } else if (pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11AC) { -- if (mcs > 9) { -- ath12k_warn(ab, "Invalid VHT mcs index %d\n", mcs); -- goto err_out; -- } -- -- arsta->txrate.mcs = mcs; -- arsta->txrate.flags = RATE_INFO_FLAGS_VHT_MCS; -- if (sgi) -- arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; -- } else if (pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11AX) { -- arsta->txrate.mcs = mcs; -- arsta->txrate.flags = RATE_INFO_FLAGS_HE_MCS; -- arsta->txrate.he_gi = ath12k_he_gi_to_nl80211_he_gi(sgi); -- arsta->txrate.he_ru_alloc = -- ath12k_he_ru_tones_to_nl80211_he_ru_alloc(num_tones_in_ru); -- } -- -- arsta->txrate.nss = arsta->last_txrate.nss; -- arsta->txrate.bw = ath12k_mac_bw_to_mac80211_bw(bw); -- -- /* Currently only OFDMA flag is available in tx complettion status -- * to indicate MUOFDMA ppdu type. Use SU ppdu type as of now to -- * indicate both SU/MU MIMO for failed/retry count. -- */ -- if (ts->flags & HAL_TX_STATUS_FLAGS_OFDMA) -- peer_stats->ppdu_type = HTT_PPDU_STATS_PPDU_TYPE_MU_OFDMA; -- else -- peer_stats->ppdu_type = HTT_PPDU_STATS_PPDU_TYPE_SU; -- -- peer_stats->ru_tones = arsta->txrate.he_ru_alloc; -- -- ath12k_debugfs_sta_add_tx_stats(arsta, peer_stats, rate_idx); -- --err_out: -- spin_unlock_bh(&ab->base_lock); -- rcu_read_unlock(); -+ ath12k_dp_tx_update_txcompl(ar, ts); - } - - static ssize_t ath12k_dbg_sta_dump_tx_stats(struct file *file, -diff --git a/drivers/net/wireless/ath/ath12k/debugfs_sta.h b/drivers/net/wireless/ath/ath12k/debugfs_sta.h -index c356850..eec6600 100644 ---- a/drivers/net/wireless/ath/ath12k/debugfs_sta.h -+++ b/drivers/net/wireless/ath/ath12k/debugfs_sta.h -@@ -21,7 +21,6 @@ void ath12k_debugfs_sta_add_tx_stats(struct ath12k_sta *arsta, - struct ath12k_per_peer_tx_stats *peer_stats, - u8 legacy_rate_idx); - void ath12k_debugfs_sta_update_txcompl(struct ath12k *ar, -- struct sk_buff *msdu, - struct hal_tx_status *ts); - - #else /* CPTCFG_ATH12K_DEBUGFS */ -@@ -36,7 +35,6 @@ ath12k_debugfs_sta_add_tx_stats(struct ath12k_sta *arsta, - } - - static inline void ath12k_debugfs_sta_update_txcompl(struct ath12k *ar, -- struct sk_buff *msdu, - struct hal_tx_status *ts) - { - } -diff --git a/drivers/net/wireless/ath/ath12k/dp_mon.c b/drivers/net/wireless/ath/ath12k/dp_mon.c -index 6c2694c..e09ad5b 100644 --- a/drivers/net/wireless/ath/ath12k/dp_mon.c +++ b/drivers/net/wireless/ath/ath12k/dp_mon.c -@@ -290,7 +290,7 @@ static void ath12k_dp_mon_parse_he_sig_b1_mu(u8 *tlv_data, +@@ -290,7 +290,7 @@ static void ath12k_dp_mon_parse_he_sig_b ru_tones = u32_get_bits(info0, HAL_RX_HE_SIG_B1_MU_INFO_INFO0_RU_ALLOCATION); @@ -161,20 +28,20 @@ index 6c2694c..e09ad5b 100644 ppdu_info->he_RU[0] = ru_tones; ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_MU_MIMO; } -diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c -index e574f48..887a5ec 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -1444,7 +1444,7 @@ ath12k_update_per_peer_tx_stats(struct ath12k *ar, +@@ -1430,8 +1430,8 @@ ath12k_update_per_peer_tx_stats(struct a arsta->txrate.flags = RATE_INFO_FLAGS_HE_MCS; arsta->txrate.he_dcm = dcm; arsta->txrate.he_gi = ath12k_he_gi_to_nl80211_he_gi(sgi); -- arsta->txrate.he_ru_alloc = ath12k_he_ru_tones_to_nl80211_he_ru_alloc( -+ arsta->txrate.he_ru_alloc = ath12k_mac_he_ru_tones_to_nl80211_he_ru_alloc( - (user_rate->ru_end - - user_rate->ru_start) + 1); +- v = ath12k_he_ru_tones_to_nl80211_he_ru_alloc((user_rate->ru_end - +- user_rate->ru_start) + 1); ++ v = ath12k_mac_he_ru_tones_to_nl80211_he_ru_alloc((user_rate->ru_end - ++ user_rate->ru_start) + 1); + arsta->txrate.he_ru_alloc = v; break; -@@ -1453,7 +1453,7 @@ ath12k_update_per_peer_tx_stats(struct ath12k *ar, + case WMI_RATE_PREAMBLE_EHT: +@@ -1439,7 +1439,7 @@ ath12k_update_per_peer_tx_stats(struct a arsta->txrate.flags = RATE_INFO_FLAGS_EHT_MCS; arsta->txrate.he_dcm = dcm; arsta->txrate.he_gi = ath12k_he_gi_to_nl80211_he_gi(sgi); @@ -183,7 +50,7 @@ index e574f48..887a5ec 100644 (user_rate->ru_end - user_rate->ru_start) + 1); break; -@@ -2492,7 +2492,7 @@ static void ath12k_dp_rx_h_rate(struct ath12k *ar, struct hal_rx_desc *rx_desc, +@@ -2481,7 +2481,7 @@ static void ath12k_dp_rx_h_rate(struct a } rx_status->encoding = RX_ENC_HE; rx_status->nss = nss; @@ -192,11 +59,17 @@ index e574f48..887a5ec 100644 rx_status->bw = ath12k_mac_bw_to_mac80211_bw(bw); break; case RX_MSDU_START_PKT_TYPE_11BE: -diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c -index 42cb317..10701cb 100644 --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -463,6 +463,114 @@ static void ath12k_dp_tx_cache_peer_stats(struct ath12k *ar, +@@ -9,6 +9,7 @@ + #include "debug.h" + #include "debugfs_sta.h" + #include "hw.h" ++#include "peer.h" + + static enum hal_tcl_encap_type + ath12k_dp_tx_get_encap_type(struct ath12k_vif *arvif, struct sk_buff *skb) +@@ -467,6 +468,114 @@ static void ath12k_dp_tx_cache_peer_stat } } @@ -311,16 +184,17 @@ index 42cb317..10701cb 100644 static void ath12k_dp_tx_complete_msdu(struct ath12k *ar, struct sk_buff *msdu, struct hal_tx_status *ts) -@@ -513,7 +621,7 @@ static void ath12k_dp_tx_complete_msdu(struct ath12k *ar, +@@ -517,7 +626,8 @@ static void ath12k_dp_tx_complete_msdu(s (info->flags & IEEE80211_TX_CTL_NO_ACK)) info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; - if (ath12k_debugfs_is_extd_tx_stats_enabled(ar)) { -+ if (ath12k_debugfs_is_extd_tx_stats_enabled(ar) || ab->hw_params.single_pdev_only) { ++ if (ath12k_debugfs_is_extd_tx_stats_enabled(ar) || ++ ab->hw_params->single_pdev_only) { if (ts->flags & HAL_TX_STATUS_FLAGS_FIRST_MSDU) { if (ar->last_ppdu_id == 0) { ar->last_ppdu_id = ts->ppdu_id; -@@ -521,12 +629,12 @@ static void ath12k_dp_tx_complete_msdu(struct ath12k *ar, +@@ -525,12 +635,12 @@ static void ath12k_dp_tx_complete_msdu(s ar->cached_ppdu_id == ar->last_ppdu_id) { ar->cached_ppdu_id = ar->last_ppdu_id; ar->cached_stats.is_ampdu = true; @@ -335,7 +209,7 @@ index 42cb317..10701cb 100644 memset(&ar->cached_stats, 0, sizeof(struct ath12k_per_peer_tx_stats)); } -@@ -568,6 +676,9 @@ static inline void ath12k_dp_tx_status_parse(struct ath12k_base *ab, +@@ -573,6 +683,9 @@ static void ath12k_dp_tx_status_parse(st ts->rate_stats = desc->rate_stats.info0; else ts->rate_stats = 0; @@ -345,8 +219,6 @@ index 42cb317..10701cb 100644 } void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id) -diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.h b/drivers/net/wireless/ath/ath12k/dp_tx.h -index a7e5061..422024e 100644 --- a/drivers/net/wireless/ath/ath12k/dp_tx.h +++ b/drivers/net/wireless/ath/ath12k/dp_tx.h @@ -15,6 +15,7 @@ struct ath12k_dp_htt_wbm_tx_status { @@ -357,11 +229,9 @@ index a7e5061..422024e 100644 int ath12k_dp_tx_htt_h2t_ver_req_msg(struct ath12k_base *ab); int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif, struct sk_buff *skb); -diff --git a/drivers/net/wireless/ath/ath12k/hal_rx.h b/drivers/net/wireless/ath/ath12k/hal_rx.h -index 6a6e7be..5e16ab6 100644 --- a/drivers/net/wireless/ath/ath12k/hal_rx.h +++ b/drivers/net/wireless/ath/ath12k/hal_rx.h -@@ -507,33 +507,6 @@ void ath12k_hal_rx_reo_ent_buf_paddr_get(void *rx_desc, +@@ -548,33 +548,6 @@ void ath12k_hal_rx_reo_ent_buf_paddr_get void **pp_buf_addr_info, u8 *rbm, u32 *msdu_cnt); @@ -395,11 +265,9 @@ index 6a6e7be..5e16ab6 100644 #define REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_0 0xDDBEEF #define REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_1 0xADBEEF #define REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_2 0xBDBEEF -diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index 15c2d7e..998510d 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -246,6 +246,93 @@ static const u32 ath12k_smps_map[] = { +@@ -249,6 +249,93 @@ static const u32 ath12k_smps_map[] = { static int ath12k_start_vdev_delay(struct ieee80211_hw *hw, struct ieee80211_vif *vif); @@ -493,7 +361,7 @@ index 15c2d7e..998510d 100644 u8 ath12k_mac_bw_to_mac80211_bw(u8 bw) { u8 ret = 0; -@@ -2222,8 +2309,12 @@ static void ath12k_peer_assoc_prepare(struct ath12k *ar, +@@ -2594,8 +2681,12 @@ static void ath12k_peer_assoc_prepare(st struct peer_assoc_params *arg, bool reassoc) { @@ -506,7 +374,7 @@ index 15c2d7e..998510d 100644 memset(arg, 0, sizeof(*arg)); reinit_completion(&ar->peer_assoc_done); -@@ -2240,6 +2331,8 @@ static void ath12k_peer_assoc_prepare(struct ath12k *ar, +@@ -2613,6 +2704,8 @@ static void ath12k_peer_assoc_prepare(st ath12k_peer_assoc_h_qos(ar, vif, sta, arg); ath12k_peer_assoc_h_smps(sta, arg); @@ -515,11 +383,9 @@ index 15c2d7e..998510d 100644 /* TODO: amsdu_disable req? */ } -diff --git a/drivers/net/wireless/ath/ath12k/mac.h b/drivers/net/wireless/ath/ath12k/mac.h -index 7339844..6cf02cb 100644 --- a/drivers/net/wireless/ath/ath12k/mac.h +++ b/drivers/net/wireless/ath/ath12k/mac.h -@@ -146,6 +146,9 @@ void ath12k_mac_drain_tx(struct ath12k *ar); +@@ -146,6 +146,9 @@ void ath12k_mac_drain_tx(struct ath12k * void ath12k_mac_peer_cleanup_all(struct ath12k *ar); int ath12k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx); u8 ath12k_mac_bw_to_mac80211_bw(u8 bw); @@ -529,6 +395,128 @@ index 7339844..6cf02cb 100644 enum ath12k_supported_bw ath12k_mac_mac80211_bw_to_ath12k_bw(enum rate_info_bw bw); enum hal_encrypt_type ath12k_dp_tx_get_encrypt_type(u32 cipher); #endif --- -2.17.1 - +--- a/drivers/net/wireless/ath/ath12k/debugfs_sta.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs_sta.c +@@ -176,103 +176,9 @@ void ath12k_debugfs_sta_add_tx_stats(str + } + + void ath12k_debugfs_sta_update_txcompl(struct ath12k *ar, +- struct sk_buff *msdu, + struct hal_tx_status *ts) + { +- struct ath12k_base *ab = ar->ab; +- struct ath12k_per_peer_tx_stats *peer_stats = &ar->cached_stats; +- enum hal_tx_rate_stats_pkt_type pkt_type; +- enum hal_tx_rate_stats_sgi sgi; +- enum hal_tx_rate_stats_bw bw; +- struct ath12k_peer *peer; +- struct ath12k_sta *arsta; +- struct ieee80211_sta *sta; +- u16 num_tones_in_ru; +- u16 rate; +- u8 rate_idx = 0; +- int ret; +- u8 mcs; +- +- rcu_read_lock(); +- spin_lock_bh(&ab->base_lock); +- peer = ath12k_peer_find_by_id(ab, ts->peer_id); +- if (!peer || !peer->sta) { +- ath12k_warn(ab, "failed to find the peer\n"); +- spin_unlock_bh(&ab->base_lock); +- rcu_read_unlock(); +- return; +- } +- +- sta = peer->sta; +- arsta = (struct ath12k_sta *)sta->drv_priv; +- +- memset(&arsta->txrate, 0, sizeof(arsta->txrate)); +- pkt_type = FIELD_GET(HAL_TX_RATE_STATS_INFO0_PKT_TYPE, +- ts->rate_stats); +- mcs = FIELD_GET(HAL_TX_RATE_STATS_INFO0_MCS, +- ts->rate_stats); +- sgi = FIELD_GET(HAL_TX_RATE_STATS_INFO0_SGI, +- ts->rate_stats); +- bw = FIELD_GET(HAL_TX_RATE_STATS_INFO0_BW, ts->rate_stats); +- num_tones_in_ru = FIELD_GET(HAL_TX_RATE_STATS_INFO0_TONES_IN_RU, +- ts->rate_stats); +- +- if (pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11A || +- pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11B) { +- ret = ath12k_mac_hw_ratecode_to_legacy_rate(mcs, +- pkt_type, +- &rate_idx, +- &rate); +- if (ret < 0) +- goto err_out; +- arsta->txrate.legacy = rate; +- } else if (pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11N) { +- if (mcs > 7) { +- ath12k_warn(ab, "Invalid HT mcs index %d\n", mcs); +- goto err_out; +- } +- +- arsta->txrate.mcs = mcs + 8 * (arsta->last_txrate.nss - 1); +- arsta->txrate.flags = RATE_INFO_FLAGS_MCS; +- if (sgi) +- arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; +- } else if (pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11AC) { +- if (mcs > 9) { +- ath12k_warn(ab, "Invalid VHT mcs index %d\n", mcs); +- goto err_out; +- } +- +- arsta->txrate.mcs = mcs; +- arsta->txrate.flags = RATE_INFO_FLAGS_VHT_MCS; +- if (sgi) +- arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; +- } else if (pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11AX) { +- arsta->txrate.mcs = mcs; +- arsta->txrate.flags = RATE_INFO_FLAGS_HE_MCS; +- arsta->txrate.he_gi = ath12k_he_gi_to_nl80211_he_gi(sgi); +- arsta->txrate.he_ru_alloc = +- ath12k_he_ru_tones_to_nl80211_he_ru_alloc(num_tones_in_ru); +- } +- +- arsta->txrate.nss = arsta->last_txrate.nss; +- arsta->txrate.bw = ath12k_mac_bw_to_mac80211_bw(bw); +- +- /* Currently only OFDMA flag is available in tx complettion status +- * to indicate MUOFDMA ppdu type. Use SU ppdu type as of now to +- * indicate both SU/MU MIMO for failed/retry count. +- */ +- if (ts->flags & HAL_TX_STATUS_FLAGS_OFDMA) +- peer_stats->ppdu_type = HTT_PPDU_STATS_PPDU_TYPE_MU_OFDMA; +- else +- peer_stats->ppdu_type = HTT_PPDU_STATS_PPDU_TYPE_SU; +- +- peer_stats->ru_tones = arsta->txrate.he_ru_alloc; +- +- ath12k_debugfs_sta_add_tx_stats(arsta, peer_stats, rate_idx); +- +-err_out: +- spin_unlock_bh(&ab->base_lock); +- rcu_read_unlock(); ++ ath12k_dp_tx_update_txcompl(ar, ts); + } + + static ssize_t ath12k_dbg_sta_dump_tx_stats(struct file *file, +--- a/drivers/net/wireless/ath/ath12k/debugfs_sta.h ++++ b/drivers/net/wireless/ath/ath12k/debugfs_sta.h +@@ -21,7 +21,6 @@ void ath12k_debugfs_sta_add_tx_stats(str + struct ath12k_per_peer_tx_stats *peer_stats, + u8 legacy_rate_idx); + void ath12k_debugfs_sta_update_txcompl(struct ath12k *ar, +- struct sk_buff *msdu, + struct hal_tx_status *ts); + + #else /* CPTCFG_ATH12K_DEBUGFS */ +@@ -36,7 +35,6 @@ ath12k_debugfs_sta_add_tx_stats(struct a + } + + static inline void ath12k_debugfs_sta_update_txcompl(struct ath12k *ar, +- struct sk_buff *msdu, + struct hal_tx_status *ts) + { + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/603-ath12k-add-support-to-configure-spatial-reuse-par.patch b/feeds/ipq95xx/mac80211/patches/qca/603-ath12k-add-support-to-configure-spatial-reuse-par.patch index 4bf54b0d2..6eb1ebf96 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/603-ath12k-add-support-to-configure-spatial-reuse-par.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/603-ath12k-add-support-to-configure-spatial-reuse-par.patch @@ -18,54 +18,9 @@ Signed-off-by: Muna Sinada drivers/net/wireless/ath/ath12k/wmi.h | 36 ++++ 6 files changed, 471 insertions(+), 4 deletions(-) ---- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c -+++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c -@@ -3846,6 +3846,18 @@ htt_print_pdev_obss_pd_stats_tlv_v(const - htt_stats_buf->num_obss_tx_ppdu_success); - len += HTT_DBG_OUT(buf + len, buf_len - len, "OBSS Tx failures PPDU = %u\n", - htt_stats_buf->num_obss_tx_ppdu_failure); -+ len += HTT_DBG_OUT(buf + len, buf_len - len, "Non-SRG Opportunities = %u\n", -+ htt_stats_buf->num_non_srg_opportunities); -+ len += HTT_DBG_OUT(buf + len, buf_len - len, "Non-SRG tried PPDU = %u\n", -+ htt_stats_buf->num_non_srg_ppdu_tried); -+ len += HTT_DBG_OUT(buf + len, buf_len - len, "Non-SRG success PPDU = %u\n", -+ htt_stats_buf->num_non_srg_ppdu_success); -+ len += HTT_DBG_OUT(buf + len, buf_len - len, "SRG Opportunities = %u\n", -+ htt_stats_buf->num_srg_opportunities); -+ len += HTT_DBG_OUT(buf + len, buf_len - len, "SRG tried PPDU = %u\n", -+ htt_stats_buf->num_srg_ppdu_tried); -+ len += HTT_DBG_OUT(buf + len, buf_len - len, "SRG success PPDU = %u\n", -+ htt_stats_buf->num_srg_ppdu_success); - - if (len >= buf_len) - buf[buf_len - 1] = 0; ---- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h -+++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h -@@ -1657,8 +1657,19 @@ struct htt_tx_sounding_stats_tlv { - }; - - struct htt_pdev_obss_pd_stats_tlv { -- u32 num_obss_tx_ppdu_success; -- u32 num_obss_tx_ppdu_failure; -+ u32 num_obss_tx_ppdu_success; -+ u32 num_obss_tx_ppdu_failure; -+ u32 num_sr_tx_transmissions; -+ u32 num_spatial_reuse_opportunities; -+ u32 num_non_srg_opportunities; -+ u32 num_non_srg_ppdu_tried; -+ u32 num_non_srg_ppdu_success; -+ u32 num_srg_opportunities; -+ u32 num_srg_ppdu_tried; -+ u32 num_srg_ppdu_success; -+ u32 num_psr_opportunities; -+ u32 num_psr_ppdu_tried; -+ u32 num_psr_ppdu_success; - }; - - struct htt_ring_backpressure_stats_tlv { --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -2607,6 +2607,182 @@ static int ath12k_mac_fils_discovery(str +@@ -3125,6 +3125,182 @@ static int ath12k_mac_fils_discovery(str return ret; } @@ -248,7 +203,7 @@ Signed-off-by: Muna Sinada static void ath12k_mac_op_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, -@@ -2853,8 +3029,7 @@ static void ath12k_mac_op_bss_info_chang +@@ -3389,8 +3565,7 @@ static void ath12k_mac_op_bss_info_chang } if (changed & BSS_CHANGED_HE_OBSS_PD) @@ -275,11 +230,11 @@ Signed-off-by: Muna Sinada void ath12k_mac_destroy(struct ath12k_base *ab); --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -3053,6 +3053,233 @@ ath12k_wmi_send_obss_spr_cmd(struct ath1 +@@ -3160,6 +3160,232 @@ int ath12k_wmi_obss_color_cfg_cmd(struct + return ret; } - int -+ath12k_wmi_pdev_set_srg_bss_color_bitmap(struct ath12k *ar, u32 *bitmap) ++int ath12k_wmi_pdev_set_srg_bss_color_bitmap(struct ath12k *ar, u32 *bitmap) +{ + struct ath12k_pdev_wmi *wmi = ar->wmi; + struct ath12k_base *ab = wmi->wmi_ab->ab; @@ -505,13 +460,12 @@ Signed-off-by: Muna Sinada + return ret; +} + -+int - ath12k_wmi_send_obss_color_collision_cfg_cmd(struct ath12k *ar, u32 vdev_id, - u8 bss_color, u32 period, - bool enable) + int ath12k_wmi_send_bss_color_change_enable_cmd(struct ath12k *ar, u32 vdev_id, + bool enable) + { --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -274,6 +274,16 @@ enum wmi_tlv_cmd_id { +@@ -270,6 +270,16 @@ enum wmi_tlv_cmd_id { WMI_PDEV_DMA_RING_CFG_REQ_CMDID, WMI_PDEV_HE_TB_ACTION_FRM_CMDID, WMI_PDEV_PKTLOG_FILTER_CMDID, @@ -528,7 +482,7 @@ Signed-off-by: Muna Sinada WMI_VDEV_CREATE_CMDID = WMI_TLV_CMD(WMI_GRP_VDEV), WMI_VDEV_DELETE_CMDID, WMI_VDEV_START_REQUEST_CMDID, -@@ -938,6 +948,9 @@ enum wmi_tlv_pdev_param { +@@ -934,6 +944,9 @@ enum wmi_tlv_pdev_param { WMI_PDEV_PARAM_RADIO_CHAN_STATS_ENABLE, WMI_PDEV_PARAM_RADIO_DIAGNOSIS_ENABLE, WMI_PDEV_PARAM_MESH_MCAST_ENABLE, @@ -538,8 +492,8 @@ Signed-off-by: Muna Sinada }; enum wmi_tlv_vdev_param { -@@ -1839,6 +1852,12 @@ enum wmi_tlv_tag { - WMI_TAG_MUEDCA_PARAMS_CONFIG_EVENT = 0x32a, +@@ -1845,6 +1858,12 @@ enum wmi_tlv_tag { + WMI_TAG_SERVICE_READY_EXT2_EVENT = 0x334, WMI_TAG_FILS_DISCOVERY_TMPL_CMD = 0x344, WMI_TAG_MAC_PHY_CAPABILITIES_EXT = 0x36F, + WMI_TAG_PDEV_SRG_BSS_COLOR_BITMAP_CMD = 0x37b, @@ -550,8 +504,8 @@ Signed-off-by: Muna Sinada + WMI_TAG_PDEV_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD, WMI_TAG_REGULATORY_RULE_EXT_STRUCT = 0x3A9, WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT, - WMI_TAG_MAX -@@ -2064,6 +2083,7 @@ enum wmi_tlv_service { + WMI_TAG_EHT_RATE_SET = 0x3C4, +@@ -2071,6 +2090,7 @@ enum wmi_tlv_service { WMI_TLV_SERVICE_PER_PEER_HTT_STATS_RESET = 213, WMI_TLV_SERVICE_FREQINFO_IN_METADATA = 219, WMI_TLV_SERVICE_EXT2_MSG = 220, @@ -559,8 +513,8 @@ Signed-off-by: Muna Sinada WMI_MAX_EXT_SERVICE = 256, -@@ -4958,6 +4978,12 @@ struct wmi_obss_spatial_reuse_params_cmd - u32 vdev_id; +@@ -5080,6 +5100,12 @@ struct wmi_obss_spatial_reuse_params_cmd + __le32 vdev_id; } __packed; +struct wmi_pdev_obss_pd_bitmap_cmd { @@ -572,7 +526,7 @@ Signed-off-by: Muna Sinada #define ATH12K_BSS_COLOR_COLLISION_SCAN_PERIOD_MS 200 #define ATH12K_OBSS_COLOR_COLLISION_DETECTION_DISABLE 0 #define ATH12K_OBSS_COLOR_COLLISION_DETECTION 1 -@@ -5501,6 +5527,16 @@ int ath12k_wmi_send_twt_enable_cmd(struc +@@ -5623,6 +5649,16 @@ int ath12k_wmi_send_twt_enable_cmd(struc int ath12k_wmi_send_twt_disable_cmd(struct ath12k *ar, u32 pdev_id); int ath12k_wmi_send_obss_spr_cmd(struct ath12k *ar, u32 vdev_id, struct ieee80211_he_obss_pd *he_obss_pd); @@ -586,6 +540,50 @@ Signed-off-by: Muna Sinada + u32 *bitmap); +int ath12k_wmi_pdev_non_srg_obss_bssid_enable_bitmap(struct ath12k *ar, + u32 *bitmap); - int ath12k_wmi_send_obss_color_collision_cfg_cmd(struct ath12k *ar, u32 vdev_id, - u8 bss_color, u32 period, - bool enable); + int ath12k_wmi_obss_color_cfg_cmd(struct ath12k *ar, u32 vdev_id, + u8 bss_color, u32 period, + bool enable); +--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c +@@ -3846,6 +3846,17 @@ htt_print_pdev_obss_pd_stats_tlv_v(const + htt_stats_buf->num_obss_tx_ppdu_success); + len += HTT_DBG_OUT(buf + len, buf_len - len, "OBSS Tx failures PPDU = %u\n", + htt_stats_buf->num_obss_tx_ppdu_failure); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "Non-SRG Opportunities = %u\n", ++ htt_stats_buf->num_non_srg_opportunities); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "Non-SRG tried PPDU = %u\n", ++ htt_stats_buf->num_non_srg_ppdu_tried); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "Non-SRG success PPDU = %u\n", ++ htt_stats_buf->num_non_srg_ppdu_success); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "SRG Opportunities = %u\n", ++ htt_stats_buf->num_srg_opportunities); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "SRG tried PPDU = %u\n", ++ htt_stats_buf->num_srg_ppdu_tried); ++ len += HTT_DBG_OUT(buf + len, buf_len - len, "SRG success PPDU = %u\n", + + if (len >= buf_len) + buf[buf_len - 1] = 0; +--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h ++++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h +@@ -1785,8 +1785,19 @@ struct htt_tx_sounding_stats_tlv { + }; + + struct htt_pdev_obss_pd_stats_tlv { +- u32 num_obss_tx_ppdu_success; +- u32 num_obss_tx_ppdu_failure; ++ u32 num_obss_tx_ppdu_success; ++ u32 num_obss_tx_ppdu_failure; ++ u32 num_sr_tx_transmissions; ++ u32 num_spatial_reuse_opportunities; ++ u32 num_non_srg_opportunities; ++ u32 num_non_srg_ppdu_tried; ++ u32 num_non_srg_ppdu_success; ++ u32 num_srg_opportunities; ++ u32 num_srg_ppdu_tried; ++ u32 num_srg_ppdu_success; ++ u32 num_psr_opportunities; ++ u32 num_psr_ppdu_tried; ++ u32 num_psr_ppdu_success; + }; + + struct htt_ring_backpressure_stats_tlv { diff --git a/feeds/ipq95xx/mac80211/patches/qca/605-ath12k-skip-NULL-buff-segments-in-RDDM.patch b/feeds/ipq95xx/mac80211/patches/qca/605-ath12k-skip-NULL-buff-segments-in-RDDM.patch index 09876793f..0ec71e300 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/605-ath12k-skip-NULL-buff-segments-in-RDDM.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/605-ath12k-skip-NULL-buff-segments-in-RDDM.patch @@ -13,11 +13,9 @@ Signed-off-by: Balamurugan Selvarajan drivers/net/wireless/ath/ath12k/coredump.c | 11 +++++++++++ 1 file changed, 11 insertions(+) -diff --git a/drivers/net/wireless/ath/ath12k/coredump.c b/drivers/net/wireless/ath/ath12k/coredump.c -index 770ad01..e122b3b 100644 --- a/drivers/net/wireless/ath/ath12k/coredump.c +++ b/drivers/net/wireless/ath/ath12k/coredump.c -@@ -153,6 +153,7 @@ void ath12k_coredump_download_rddm(struct ath12k_base *ab) +@@ -153,6 +153,7 @@ void ath12k_coredump_download_rddm(struc struct image_info *rddm_img, *fw_img; struct ath12k_dump_segment *segment, *seg_info; int i, rem_seg_cnt = 0, len, num_seg, seg_sz; @@ -25,7 +23,7 @@ index 770ad01..e122b3b 100644 ath12k_mhi_coredump(mhi_ctrl, false); -@@ -175,6 +176,10 @@ void ath12k_coredump_download_rddm(struct ath12k_base *ab) +@@ -175,6 +176,10 @@ void ath12k_coredump_download_rddm(struc seg_info = segment; for (i = 0; i < fw_img->entries ; i++) { @@ -36,26 +34,26 @@ index 770ad01..e122b3b 100644 seg_sz = fw_img->mhi_buf[i].len; seg_info->len = PAGE_ALIGN(seg_sz); seg_info->addr = fw_img->mhi_buf[i].dma_addr; -@@ -184,6 +189,10 @@ void ath12k_coredump_download_rddm(struct ath12k_base *ab) +@@ -184,6 +189,10 @@ void ath12k_coredump_download_rddm(struc } for (i = 0; i < rddm_img->entries; i++) { -+ if (!fw_img->mhi_buf[i].buf) { ++ if (!rddm_img->mhi_buf[i].buf) { + skip_count++; + continue; + } seg_sz = rddm_img->mhi_buf[i].len; seg_info->len = PAGE_ALIGN(seg_sz); seg_info->addr = rddm_img->mhi_buf[i].dma_addr; -@@ -196,6 +205,7 @@ void ath12k_coredump_download_rddm(struct ath12k_base *ab) +@@ -196,6 +205,7 @@ void ath12k_coredump_download_rddm(struc if (ab->qmi.target_mem[i].type == CALDB_MEM_REGION_TYPE) { if (ath12k_cold_boot_cal || - ab->hw_params.cold_boot_calib) { + ab->hw_params->cold_boot_calib) { + skip_count++; continue; } } -@@ -206,6 +216,7 @@ void ath12k_coredump_download_rddm(struct ath12k_base *ab) +@@ -206,6 +216,7 @@ void ath12k_coredump_download_rddm(struc seg_info++; } @@ -63,6 +61,3 @@ index 770ad01..e122b3b 100644 if(!ab->fw_recovery_support) { ath12k_coredump_seg_info.chip_id = ar_pci->dev_id; ath12k_coredump_seg_info.qrtr_id = ar_pci->ab->qmi.service_ins_id; --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/607-ath12k-Fix-TX-completion-ring-mask-for-WBM2SW-ring-4.patch b/feeds/ipq95xx/mac80211/patches/qca/607-ath12k-Fix-TX-completion-ring-mask-for-WBM2SW-ring-4.patch index 021bccc55..ddfe10ea0 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/607-ath12k-Fix-TX-completion-ring-mask-for-WBM2SW-ring-4.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/607-ath12k-Fix-TX-completion-ring-mask-for-WBM2SW-ring-4.patch @@ -16,32 +16,9 @@ Signed-off-by: Pradeep Kumar Chitrapu drivers/net/wireless/ath/ath12k/hw.c | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c -index ffe5618041ee..e2e39772bc32 100644 ---- a/drivers/net/wireless/ath/ath12k/dp.c -+++ b/drivers/net/wireless/ath/ath12k/dp.c -@@ -881,11 +881,11 @@ int ath12k_dp_service_srng(struct ath12k_base *ab, - int tot_work_done = 0; - bool flag; - -- while (ab->hw_params.ring_mask->tx[grp_id] >> i) { -- if (ab->hw_params.ring_mask->tx[grp_id] & BIT(i)) -- ath12k_dp_tx_completion_handler(ab, i); -- i++; -- } -+ -+ if (ab->hw_params.ring_mask->tx[grp_id]) { -+ i = __fls(ab->hw_params.ring_mask->tx[grp_id]); -+ ath12k_dp_tx_completion_handler(ab, (i == 4) ? 3 : i); -+ } - - if (ab->hw_params.ring_mask->rx_err[grp_id]) { - work_done = ath12k_dp_process_rx_err(ab, napi, budget); -diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c -index 0066996c7b00..3b0f65edbf59 100644 --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -79,6 +79,7 @@ static void ath12k_dp_tx_release_txbuf(struct ath12k_dp *dp, +@@ -79,6 +79,7 @@ static void ath12k_dp_tx_release_txbuf(s u8 pool_id) { spin_lock_bh(&dp->tx_desc_lock[pool_id]); @@ -49,19 +26,26 @@ index 0066996c7b00..3b0f65edbf59 100644 list_move_tail(&tx_desc->list, &dp->tx_desc_free_list[pool_id]); spin_unlock_bh(&dp->tx_desc_lock[pool_id]); } -diff --git a/drivers/net/wireless/ath/ath12k/hw.c b/drivers/net/wireless/ath/ath12k/hw.c -index 514d74f69a8c..2b2f1afdd940 100644 --- a/drivers/net/wireless/ath/ath12k/hw.c +++ b/drivers/net/wireless/ath/ath12k/hw.c -@@ -38,7 +38,7 @@ const struct ath12k_hw_ops qcn92xx_ops = { +@@ -90,7 +90,10 @@ static const struct ath12k_hw_ops wcn785 #define ATH12K_TX_RING_MASK_0 0x1 #define ATH12K_TX_RING_MASK_1 0x2 #define ATH12K_TX_RING_MASK_2 0x4 -#define ATH12K_TX_RING_MASK_3 0x8 -+#define ATH12K_TX_RING_MASK_3 0x10 ++/* ATH12K_TX_RING_MASK_4 corresponds to the interrupt mask ++ * for the 4th TX Data ring which uses WBM2SW4RELEASE and ++ * hence uses the mask with 4th bit set ++ */ + #define ATH12K_TX_RING_MASK_4 0x10 #define ATH12K_RX_RING_MASK_0 0x1 - #define ATH12K_RX_RING_MASK_1 0x2 --- -2.17.1 - +@@ -535,7 +538,7 @@ static const struct ath12k_hw_ring_mask + ATH12K_TX_RING_MASK_0, + ATH12K_TX_RING_MASK_1, + ATH12K_TX_RING_MASK_2, +- ATH12K_TX_RING_MASK_3, ++ ATH12K_TX_RING_MASK_4, + }, + .rx_mon_dest = { + 0, 0, 0, diff --git a/feeds/ipq95xx/mac80211/patches/qca/608-ath12k-Fix-rx-stats-support-by-enabling-monitor-ring.patch b/feeds/ipq95xx/mac80211/patches/qca/608-ath12k-Fix-rx-stats-support-by-enabling-monitor-ring.patch index baacccf18..dbd69d3cf 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/608-ath12k-Fix-rx-stats-support-by-enabling-monitor-ring.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/608-ath12k-Fix-rx-stats-support-by-enabling-monitor-ring.patch @@ -24,28 +24,9 @@ Signed-off-by: P Praneesh drivers/net/wireless/ath/ath12k/mac.c | 5 +- 10 files changed, 101 insertions(+), 67 deletions(-) ---- a/drivers/net/wireless/ath/ath12k/debugfs.c -+++ b/drivers/net/wireless/ath/ath12k/debugfs.c -@@ -641,6 +641,7 @@ static ssize_t ath12k_write_extd_rx_stat - rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS; - rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT; - rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE; -+ rx_filter |= HTT_RX_FILTER_TLV_FLAGS_ENABLE_FP; - - tlv_filter.rx_filter = rx_filter; - tlv_filter.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0; -@@ -657,7 +658,7 @@ static ssize_t ath12k_write_extd_rx_stat - - for (i = 0; i < ar->ab->hw_params.num_rxmda_per_pdev; i++) { - ring_id = ar->dp.rxdma_mon_dst_ring[i].ring_id; -- ret = ath12k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id, -+ ret = ath12k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id + i, - HAL_RXDMA_MONITOR_DST, - DP_RXDMA_REFILL_RING_SIZE, - &tlv_filter); --- a/drivers/net/wireless/ath/ath12k/dp.h +++ b/drivers/net/wireless/ath/ath12k/dp.h -@@ -455,11 +455,14 @@ enum htt_srng_ring_id { +@@ -419,11 +419,14 @@ enum htt_srng_ring_id { HTT_RXDMA_MONITOR_BUF_RING, HTT_RXDMA_MONITOR_DESC_RING, HTT_RXDMA_MONITOR_DEST_RING, @@ -60,7 +41,7 @@ Signed-off-by: P Praneesh }; /* host -> target HTT_SRING_SETUP message -@@ -787,6 +790,8 @@ enum htt_stats_internal_ppdu_frametype { +@@ -751,6 +754,8 @@ enum htt_stats_internal_ppdu_frametype { #define HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PS BIT(25) #define HTT_RX_RING_SELECTION_CFG_CMD_INFO1_BUF_SIZE GENMASK(15, 0) #define HTT_RX_RING_SELECTION_CFG_CMD_OFFSET_VALID BIT(26) @@ -69,7 +50,7 @@ Signed-off-by: P Praneesh #define HTT_RX_RING_SELECTION_CFG_RX_PACKET_OFFSET GENMASK(15, 0) #define HTT_RX_RING_SELECTION_CFG_RX_HEADER_OFFSET GENMASK(31, 16) -@@ -810,6 +815,7 @@ enum htt_rx_filter_tlv_flags { +@@ -774,6 +779,7 @@ enum htt_rx_filter_tlv_flags { HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS = BIT(10), HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT = BIT(11), HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE = BIT(12), @@ -77,7 +58,7 @@ Signed-off-by: P Praneesh }; enum htt_rx_mgmt_pkt_filter_tlv_flags0 { -@@ -1119,6 +1125,8 @@ struct htt_rx_ring_selection_cfg_cmd { +@@ -1083,6 +1089,8 @@ struct htt_rx_ring_selection_cfg_cmd { u32 rx_mpdu_offset; u32 rx_msdu_offset; u32 rx_attn_offset; @@ -88,7 +69,7 @@ Signed-off-by: P Praneesh struct htt_rx_ring_tlv_filter { --- a/drivers/net/wireless/ath/ath12k/dp_mon.c +++ b/drivers/net/wireless/ath/ath12k/dp_mon.c -@@ -17,7 +17,7 @@ ath12k_dp_mon_rx_handle_ofdma_info(void +@@ -17,7 +17,7 @@ static void ath12k_dp_mon_rx_handle_ofdm (struct hal_rx_ppdu_end_user_stats *)rx_tlv; rx_user_status->ul_ofdma_user_v0_word0 = __le32_to_cpu(ppdu_end_user->info6); @@ -96,7 +77,7 @@ Signed-off-by: P Praneesh + rx_user_status->ul_ofdma_user_v0_word1 = __le32_to_cpu(ppdu_end_user->rsvd5[3]); } - static inline void + static void @@ -26,15 +26,15 @@ ath12k_dp_mon_rx_populate_byte_count(voi { struct hal_rx_ppdu_end_user_stats *ppdu_end_user = @@ -116,7 +97,7 @@ Signed-off-by: P Praneesh + HAL_RX_PPDU_END_USER_STATS_INFO8_MPDU_ERR_BYTE_COUNT); } - static inline void + static void @@ -594,11 +594,16 @@ ath12k_dp_mon_rx_parse_status_tlv(struct (struct hal_rx_ppdu_start *)tlv_data; @@ -253,7 +234,7 @@ Signed-off-by: P Praneesh if ((ptr - skb->data) >= DP_RX_BUFFER_SIZE) break; -@@ -2071,10 +2066,9 @@ int ath12k_dp_mon_srng_process(struct at +@@ -2070,10 +2065,9 @@ int ath12k_dp_mon_srng_process(struct at struct hal_srng *srng; struct dp_rxdma_ring *buf_ring; u64 cookie; @@ -265,7 +246,7 @@ Signed-off-by: P Praneesh struct hal_rx_mon_ppdu_info *ppdu_info; struct ath12k_peer *peer = NULL; u32 rx_buf_sz; -@@ -2135,10 +2129,12 @@ int ath12k_dp_mon_srng_process(struct at +@@ -2134,10 +2128,12 @@ int ath12k_dp_mon_srng_process(struct at pmon->dest_skb_q[dest_idx] = skb; dest_idx++; ppdu_id = mon_dst_desc->ppdu_id; @@ -281,7 +262,7 @@ Signed-off-by: P Praneesh for (i = 0; i < dest_idx; i++) { skb = pmon->dest_skb_q[i]; -@@ -2510,11 +2506,12 @@ int ath12k_dp_mon_rx_process_stats(struc +@@ -2509,11 +2505,12 @@ int ath12k_dp_mon_rx_process_stats(struc struct dp_rxdma_ring *buf_ring; struct ath12k_sta *arsta = NULL; struct ath12k_peer *peer; @@ -295,9 +276,9 @@ Signed-off-by: P Praneesh + + __skb_queue_head_init(&skb_list); - srng_id = ath12k_hw_mac_id_to_srng_id(&ab->hw_params, mac_id); + srng_id = ath12k_hw_mac_id_to_srng_id(ab->hw_params, mac_id); mon_dst_ring = &pdev_dp->rxdma_mon_dst_ring[srng_id]; -@@ -2530,6 +2527,7 @@ int ath12k_dp_mon_rx_process_stats(struc +@@ -2529,6 +2526,7 @@ int ath12k_dp_mon_rx_process_stats(struc ath12k_hal_srng_dst_peek(ab, srng); if (unlikely(!mon_dst_desc)) break; @@ -305,7 +286,7 @@ Signed-off-by: P Praneesh cookie = mon_dst_desc->cookie; buf_id = u32_get_bits(cookie, DP_RXDMA_BUF_COOKIE_BUF_ID); -@@ -2547,62 +2545,68 @@ int ath12k_dp_mon_rx_process_stats(struc +@@ -2546,62 +2544,68 @@ int ath12k_dp_mon_rx_process_stats(struc dma_unmap_single(ab->dev, rxcb->paddr, skb->len + skb_tailroom(skb), DMA_FROM_DEVICE); @@ -419,7 +400,7 @@ Signed-off-by: P Praneesh return num_buffs_reaped; } -@@ -2613,7 +2617,8 @@ int ath12k_dp_mon_process_ring(struct at +@@ -2612,7 +2616,8 @@ int ath12k_dp_mon_process_ring(struct at int num_buffs_reaped = 0; if (!ar->monitor_started) @@ -431,35 +412,26 @@ Signed-off-by: P Praneesh flag, napi); --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -4071,7 +4071,6 @@ int ath12k_dp_rx_htt_setup(struct ath12k - ret); - return ret; +@@ -4148,7 +4148,6 @@ int ath12k_dp_rxdma_ring_sel_config_wcn7 + DP_RXDMA_REFILL_RING_SIZE, + &tlv_filter); } -#if 0 - ring_id = dp->rxdma_mon_buf_ring.refill_buf_ring.ring_id; - ret = ath12k_dp_tx_htt_srng_setup(ab, ring_id, -@@ -4090,7 +4089,6 @@ int ath12k_dp_rx_htt_setup(struct ath12k + return ret; + } +@@ -4167,7 +4166,6 @@ int ath12k_dp_rx_htt_setup(struct ath12k ret); return ret; } -#endif - ret = ath12k_dp_rxdma_ring_sel_config(ab); - if (ret) { -@@ -4178,8 +4176,6 @@ int ath12k_dp_rx_pdev_alloc(struct ath12 - } - } - -- return 0; -- - if (!ab->hw_params.rxdma1_enable) - goto out; - + if (ab->hw_params->rx_mac_buf_ring) { + for (i = 0; i < ab->hw_params->num_rxmda_per_pdev; i++) { --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -846,7 +846,7 @@ ath12k_dp_tx_get_ring_id_type(struct ath - } +@@ -812,7 +812,7 @@ ath12k_dp_tx_get_ring_id_type(struct ath + *htt_ring_type = HTT_HW_TO_SW_RING; break; case HAL_RXDMA_MONITOR_BUF: - *htt_ring_id = HTT_RXDMA_MONITOR_BUF_RING; @@ -467,7 +439,7 @@ Signed-off-by: P Praneesh *htt_ring_type = HTT_SW_TO_HW_RING; break; case HAL_RXDMA_MONITOR_STATUS: -@@ -854,7 +854,7 @@ ath12k_dp_tx_get_ring_id_type(struct ath +@@ -820,7 +820,7 @@ ath12k_dp_tx_get_ring_id_type(struct ath *htt_ring_type = HTT_SW_TO_HW_RING; break; case HAL_RXDMA_MONITOR_DST: @@ -476,16 +448,16 @@ Signed-off-by: P Praneesh *htt_ring_type = HTT_HW_TO_SW_RING; break; case HAL_TX_MONITOR_BUF: -@@ -1116,6 +1116,8 @@ int ath12k_dp_tx_htt_rx_filter_setup(str - !!(params.flags & HAL_SRNG_FLAGS_DATA_TLV_SWAP)); - cmd->info0 |= FIELD_PREP(HTT_RX_RING_SELECTION_CFG_CMD_OFFSET_VALID, - tlv_filter->offset_valid); -+ cmd->info0 |= FIELD_PREP(HTT_RX_RING_SELECTION_CFG_CMD_RXMON_GCONF_EN, -+ true); - - cmd->info1 = FIELD_PREP(HTT_RX_RING_SELECTION_CFG_CMD_INFO1_BUF_SIZE, - rx_buf_size); -@@ -1258,7 +1260,7 @@ int ath12k_dp_tx_htt_monitor_mode_ring_c +@@ -1080,6 +1080,8 @@ int ath12k_dp_tx_htt_rx_filter_setup(str + HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PS); + cmd->info0 |= u32_encode_bits(tlv_filter->offset_valid, + HTT_RX_RING_SELECTION_CFG_CMD_OFFSET_VALID); ++ cmd->info0 |= u32_encode_bits(true, ++ HTT_RX_RING_SELECTION_CFG_CMD_RXMON_GCONF_EN); + cmd->info1 = u32_encode_bits(rx_buf_size, + HTT_RX_RING_SELECTION_CFG_CMD_INFO1_BUF_SIZE); + cmd->pkt_type_en_flags0 = tlv_filter->pkt_filter_flags0; +@@ -1221,7 +1223,7 @@ int ath12k_dp_tx_htt_monitor_mode_ring_c return ret; } @@ -496,19 +468,19 @@ Signed-off-by: P Praneesh return ret; --- a/drivers/net/wireless/ath/ath12k/hal.c +++ b/drivers/net/wireless/ath/ath12k/hal.c -@@ -178,7 +178,7 @@ static const struct hal_srng_config hw_s - .max_size = HAL_WBM2PPE_RELEASE_RING_BASE_MSB_RING_SIZE, +@@ -147,7 +147,7 @@ static const struct hal_srng_config hw_s + .max_size = HAL_RXDMA_RING_MAX_SIZE_BE, }, - { /* RXDMA_MONITOR_BUF */ + [HAL_RXDMA_MONITOR_BUF] = { - .start_ring_id = HAL_SRNG_SW2RXMON_BUF0, -+ .start_ring_id = HAL_SRNG_RING_ID_WMAC1_SW2RXDMA2_BUF, ++ .start_ring_id = HAL_SRNG_SW2RXMON_BUF0, /* HAL_SRNG_RING_ID_WMAC1_SW2RXDMA2_BUF, */ .max_rings = 1, .entry_size = sizeof(struct hal_mon_buf_ring) >> 2, .mac_type = ATH12K_HAL_SRNG_PMAC, -@@ -186,7 +186,7 @@ static const struct hal_srng_config hw_s - .max_size = HAL_RXDMA_RING_MAX_SIZE_BE, +@@ -181,7 +181,7 @@ static const struct hal_srng_config hw_s + .max_size = HAL_WBM2PPE_RELEASE_RING_BASE_MSB_RING_SIZE, }, - { /* TX_MONITOR_BUF*/ + [HAL_TX_MONITOR_BUF] = { - .start_ring_id = HAL_SRNG_SW2TXMON_BUF0, + .start_ring_id = HAL_SRNG_RING_ID_WMAC1_SW2TXMON_BUF0, .max_rings = 1, @@ -516,7 +488,7 @@ Signed-off-by: P Praneesh .mac_type = ATH12K_HAL_SRNG_PMAC, --- a/drivers/net/wireless/ath/ath12k/hal.h +++ b/drivers/net/wireless/ath/ath12k/hal.h -@@ -477,8 +477,8 @@ enum hal_srng_ring_id { +@@ -493,8 +493,8 @@ enum hal_srng_ring_id { HAL_SRNG_RING_ID_WMAC1_RXMON2SW0 = HAL_SRNG_RING_ID_WMAC1_RXDMA2SW1, HAL_SRNG_RING_ID_WMAC1_SW2RXDMA1_DESC, HAL_SRNG_RING_ID_RXDMA_DIR_BUF, @@ -537,7 +509,7 @@ Signed-off-by: P Praneesh struct hal_tlv_64_hdr { u64 tl; u8 value[]; -@@ -2916,9 +2918,8 @@ struct hal_mon_buf_ring { +@@ -2918,9 +2920,8 @@ struct hal_mon_buf_ring { #define HAL_MON_DEST_COOKIE_BUF_ID GENMASK(17, 0) @@ -551,7 +523,7 @@ Signed-off-by: P Praneesh #define HAL_MON_DEST_INFO0_RING_ID GENMASK(27, 20) --- a/drivers/net/wireless/ath/ath12k/hal_rx.h +++ b/drivers/net/wireless/ath/ath12k/hal_rx.h -@@ -155,6 +155,7 @@ struct hal_rx_mon_ppdu_info { +@@ -156,6 +156,7 @@ struct hal_rx_mon_ppdu_info { u32 preamble_type; u32 mpdu_len; u16 chan_num; @@ -559,7 +531,7 @@ Signed-off-by: P Praneesh u16 tcp_msdu_count; u16 tcp_ack_msdu_count; u16 udp_msdu_count; -@@ -232,11 +233,15 @@ struct hal_rx_mon_ppdu_info { +@@ -233,11 +234,15 @@ struct hal_rx_mon_ppdu_info { }; #define HAL_RX_PPDU_START_INFO0_PPDU_ID GENMASK(15, 0) @@ -577,7 +549,7 @@ Signed-off-by: P Praneesh } __packed; #define HAL_RX_PPDU_END_USER_STATS_INFO0_MPDU_CNT_FCS_ERR GENMASK(25, 16) -@@ -245,7 +250,7 @@ struct hal_rx_ppdu_start { +@@ -246,7 +251,7 @@ struct hal_rx_ppdu_start { #define HAL_RX_PPDU_END_USER_STATS_INFO1_FC_VALID BIT(9) #define HAL_RX_PPDU_END_USER_STATS_INFO1_QOS_CTRL_VALID BIT(10) #define HAL_RX_PPDU_END_USER_STATS_INFO1_HT_CTRL_VALID BIT(11) @@ -586,7 +558,7 @@ Signed-off-by: P Praneesh #define HAL_RX_PPDU_END_USER_STATS_INFO2_AST_INDEX GENMASK(15, 0) #define HAL_RX_PPDU_END_USER_STATS_INFO2_FRAME_CTRL GENMASK(31, 16) -@@ -261,8 +266,9 @@ struct hal_rx_ppdu_start { +@@ -262,8 +267,9 @@ struct hal_rx_ppdu_start { #define HAL_RX_PPDU_END_USER_STATS_INFO6_TID_BITMAP GENMASK(15, 0) #define HAL_RX_PPDU_END_USER_STATS_INFO6_TID_EOSP_BITMAP GENMASK(31, 16) @@ -598,7 +570,7 @@ Signed-off-by: P Praneesh struct hal_rx_ppdu_end_user_stats { __le32 rsvd0[2]; -@@ -274,8 +280,13 @@ struct hal_rx_ppdu_end_user_stats { +@@ -275,8 +281,13 @@ struct hal_rx_ppdu_end_user_stats { __le32 rsvd1[2]; __le32 info4; __le32 info5; @@ -613,7 +585,7 @@ Signed-off-by: P Praneesh } __packed; struct hal_rx_ppdu_end_user_stats_ext { -@@ -286,6 +297,7 @@ struct hal_rx_ppdu_end_user_stats_ext { +@@ -287,6 +298,7 @@ struct hal_rx_ppdu_end_user_stats_ext { __le32 info4; __le32 info5; __le32 info6; @@ -621,7 +593,7 @@ Signed-off-by: P Praneesh } __packed; #define HAL_RX_HT_SIG_INFO_INFO0_MCS GENMASK(6, 0) -@@ -428,30 +440,33 @@ enum hal_rx_ul_reception_type { +@@ -429,30 +441,33 @@ enum hal_rx_ul_reception_type { HAL_RECEPTION_TYPE_FRAMELESS }; @@ -666,7 +638,7 @@ Signed-off-by: P Praneesh struct hal_rx_rxpcu_classification_overview { --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -5875,8 +5875,29 @@ void ath12k_mac_drain_tx(struct ath12k * +@@ -5969,8 +5969,29 @@ void ath12k_mac_drain_tx(struct ath12k * static int ath12k_mac_config_mon_status_default(struct ath12k *ar, bool enable) { @@ -685,7 +657,7 @@ Signed-off-by: P Praneesh + + tlv_filter.offset_valid = false; + -+ for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) { ++ for (i = 0; i < ab->hw_params->num_rxmda_per_pdev; i++) { + ring_id = ar->dp.rxdma_mon_dst_ring[i].ring_id; + ret = ath12k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, + ar->dp.mac_id + i, @@ -698,7 +670,7 @@ Signed-off-by: P Praneesh } static int ath12k_mac_op_start(struct ieee80211_hw *hw) -@@ -6491,8 +6512,6 @@ static void ath12k_mac_op_configure_filt +@@ -6586,8 +6607,6 @@ static void ath12k_mac_op_configure_filt u64 multicast) { struct ath12k *ar = hw->priv; @@ -707,7 +679,7 @@ Signed-off-by: P Praneesh mutex_lock(&ar->conf_mutex); -@@ -6500,27 +6519,6 @@ static void ath12k_mac_op_configure_filt +@@ -6595,27 +6614,6 @@ static void ath12k_mac_op_configure_filt *total_flags &= SUPPORTED_FILTERS; ar->filter_flags = *total_flags; @@ -735,11 +707,22 @@ Signed-off-by: P Praneesh mutex_unlock(&ar->conf_mutex); } -@@ -8069,6 +8067,7 @@ static void ath12k_mac_op_sta_statistics +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -641,6 +641,7 @@ static ssize_t ath12k_write_extd_rx_stat + rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS; + rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT; + rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE; ++ rx_filter |= HTT_RX_FILTER_TLV_FLAGS_ENABLE_FP; - /* TODO: Use real NF instead of default one. */ - sinfo->signal = arsta->rssi_comb + ATH12K_DEFAULT_NOISE_FLOOR; -+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL); - } + tlv_filter.rx_filter = rx_filter; + tlv_filter.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0; +@@ -657,7 +658,7 @@ static ssize_t ath12k_write_extd_rx_stat - static const struct ieee80211_ops ath12k_ops = { + for (i = 0; i < ar->ab->hw_params->num_rxmda_per_pdev; i++) { + ring_id = ar->dp.rxdma_mon_dst_ring[i].ring_id; +- ret = ath12k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id, ++ ret = ath12k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id + i, + HAL_RXDMA_MONITOR_DST, + DP_RXDMA_REFILL_RING_SIZE, + &tlv_filter); diff --git a/feeds/ipq95xx/mac80211/patches/qca/610-ath12k-Add-support-for-1024-BlockAck-bitmap-for-EHT.patch b/feeds/ipq95xx/mac80211/patches/qca/610-ath12k-Add-support-for-1024-BlockAck-bitmap-for-EHT.patch index 25d8e9cd5..b5f6b6c2f 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/610-ath12k-Add-support-for-1024-BlockAck-bitmap-for-EHT.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/610-ath12k-Add-support-for-1024-BlockAck-bitmap-for-EHT.patch @@ -19,7 +19,7 @@ Signed-off-by: Pradeep Kumar Chitrapu --- a/drivers/net/wireless/ath/ath12k/dp.h +++ b/drivers/net/wireless/ath/ath12k/dp.h -@@ -184,7 +184,7 @@ struct ath12k_pdev_dp { +@@ -145,7 +145,7 @@ struct ath12k_pdev_dp { #define DP_RX_HASH_ENABLE 1 /* Enable hash based Rx steering */ @@ -30,7 +30,7 @@ Signed-off-by: Pradeep Kumar Chitrapu --- a/drivers/net/wireless/ath/ath12k/hal_desc.h +++ b/drivers/net/wireless/ath/ath12k/hal_desc.h -@@ -2314,6 +2314,34 @@ struct hal_rx_reo_queue_ext { +@@ -2316,6 +2316,34 @@ struct hal_rx_reo_queue_ext { struct hal_rx_mpdu_link_ptr mpdu_link[15]; } __packed; @@ -65,7 +65,7 @@ Signed-off-by: Pradeep Kumar Chitrapu /* hal_rx_reo_queue_ext * Consumer: REO * Producer: REO -@@ -2500,13 +2528,13 @@ struct hal_rx_reo_queue { +@@ -2502,13 +2530,13 @@ struct hal_rx_reo_queue { #define HAL_REO_UPD_RX_QUEUE_INFO1_PN_HANDLE_ENABLE BIT(30) #define HAL_REO_UPD_RX_QUEUE_INFO1_IGNORE_AMPDU_FLG BIT(31) @@ -88,7 +88,15 @@ Signed-off-by: Pradeep Kumar Chitrapu struct hal_reo_cmd_hdr cmd; --- a/drivers/net/wireless/ath/ath12k/hal_rx.c +++ b/drivers/net/wireless/ath/ath12k/hal_rx.c -@@ -704,12 +704,15 @@ u32 ath12k_hal_reo_qdesc_size(u32 ba_win +@@ -702,6 +702,7 @@ void ath12k_hal_reo_update_rx_reo_queue_ + u32 ath12k_hal_reo_qdesc_size(u32 ba_window_size, u8 tid) + { + u32 num_ext_desc; ++ u32 num_1k_desc = 0; + + if (ba_window_size <= 1) { + if (tid != HAL_DESC_REO_NON_QOS_TID) +@@ -712,12 +713,16 @@ u32 ath12k_hal_reo_qdesc_size(u32 ba_win num_ext_desc = 1; } else if (ba_window_size <= 210) { num_ext_desc = 2; @@ -97,18 +105,19 @@ Signed-off-by: Pradeep Kumar Chitrapu num_ext_desc = 3; + } else { + num_ext_desc = 10; ++ num_1k_desc = 1; } return sizeof(struct hal_rx_reo_queue) + - (num_ext_desc * sizeof(struct hal_rx_reo_queue_ext)); + (num_ext_desc * sizeof(struct hal_rx_reo_queue_ext)) + -+ sizeof(struct hal_rx_reo_queue_1k); ++ (num_1k_desc * sizeof(struct hal_rx_reo_queue_1k)); } void ath12k_hal_reo_qdesc_setup(void *vaddr, int tid, u32 ba_window_size, --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -3305,6 +3305,22 @@ static void ath12k_mac_op_bss_info_chang +@@ -3353,6 +3353,22 @@ static void ath12k_mac_op_bss_info_chang if (ret) ath12k_warn(ar->ab, "failed to update bcn template: %d\n", ret); @@ -131,7 +140,7 @@ Signed-off-by: Pradeep Kumar Chitrapu } if (changed & (BSS_CHANGED_BEACON_INFO | BSS_CHANGED_BEACON)) { -@@ -3342,44 +3358,37 @@ static void ath12k_mac_op_bss_info_chang +@@ -3390,44 +3406,37 @@ static void ath12k_mac_op_bss_info_chang } ath12k_control_beaconing(arvif, info); @@ -205,7 +214,7 @@ Signed-off-by: Pradeep Kumar Chitrapu } } -@@ -8466,7 +8475,7 @@ static int __ath12k_mac_register(struct +@@ -8542,7 +8551,7 @@ static int __ath12k_mac_register(struct ar->hw->queues = ATH12K_HW_MAX_QUEUES; ar->hw->wiphy->tx_queue_len = ATH12K_QUEUE_LEN; ar->hw->offchannel_tx_hw_queue = ATH12K_HW_MAX_QUEUES - 1; @@ -216,38 +225,11 @@ Signed-off-by: Pradeep Kumar Chitrapu ar->hw->sta_data_size = sizeof(struct ath12k_sta); --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -68,6 +68,8 @@ struct wmi_tlv { +@@ -68,6 +68,7 @@ struct wmi_tlv { #define WMI_APPEND_TO_EXISTING_CHAN_LIST_FLAG 1 #define WMI_BA_MODE_BUFFER_SIZE_256 3 +#define WMI_BA_MODE_BUFFER_SIZE_1024 6 -+ - /* - * HW mode config type replicated from FW header + + /* HW mode config type replicated from FW header * @WMI_HOST_HW_MODE_SINGLE: Only one PHY is active. -diff --git a/drivers/net/wireless/ath/ath12k/hal_rx.c b/drivers/net/wireless/ath/ath12k/hal_rx.c -index f1f12fc421a6..c0428ad3bad5 100644 ---- a/drivers/net/wireless/ath/ath12k/hal_rx.c -+++ b/drivers/net/wireless/ath/ath12k/hal_rx.c -@@ -698,6 +698,7 @@ void ath12k_hal_reo_update_rx_reo_queue_status(struct ath12k_base *ab, - u32 ath12k_hal_reo_qdesc_size(u32 ba_window_size, u8 tid) - { - u32 num_ext_desc; -+ u32 num_1k_desc = 0; - - if (ba_window_size <= 1) { - if (tid != HAL_DESC_REO_NON_QOS_TID) -@@ -712,11 +713,12 @@ u32 ath12k_hal_reo_qdesc_size(u32 ba_window_size, u8 tid) - num_ext_desc = 3; - } else { - num_ext_desc = 10; -+ num_1k_desc = 1; - } - - return sizeof(struct hal_rx_reo_queue) + - (num_ext_desc * sizeof(struct hal_rx_reo_queue_ext)) + -- sizeof(struct hal_rx_reo_queue_1k); -+ (num_1k_desc * sizeof(struct hal_rx_reo_queue_1k)); - } - - void ath12k_hal_reo_qdesc_setup(void *vaddr, int tid, u32 ba_window_size, diff --git a/feeds/ipq95xx/mac80211/patches/qca/611-ath12k-Fixed-issue-in-reading-pdev-temperature-value.patch b/feeds/ipq95xx/mac80211/patches/qca/611-ath12k-Fixed-issue-in-reading-pdev-temperature-value.patch index a206fdd24..b4b6ab5c4 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/611-ath12k-Fixed-issue-in-reading-pdev-temperature-value.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/611-ath12k-Fixed-issue-in-reading-pdev-temperature-value.patch @@ -14,11 +14,9 @@ Signed-off-by: Aishwarya R drivers/net/wireless/ath/ath12k/wmi.c | 54 ++++++++++++++++++++---------------------------------- 1 file changed, 20 insertions(+), 34 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c -index ba0be25..fcf90df 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -5668,31 +5668,6 @@ int ath12k_wmi_pull_fw_stats(struct ath12k_base *ab, struct sk_buff *skb, +@@ -5887,31 +5887,6 @@ int ath12k_wmi_pull_fw_stats(struct ath1 return 0; } @@ -50,26 +48,26 @@ index ba0be25..fcf90df 100644 size_t ath12k_wmi_fw_stats_num_vdevs(struct list_head *head) { struct ath12k_fw_stats_vdev *i; -@@ -7151,23 +7126,34 @@ ath12k_wmi_pdev_temperature_event(struct ath12k_base *ab, +@@ -7368,23 +7343,36 @@ ath12k_wmi_pdev_temperature_event(struct struct sk_buff *skb) { struct ath12k *ar; - struct wmi_pdev_temperature_event ev = {0}; + const void **tb; -+ int ret; -+ const struct wmi_pdev_temperature_event *ev; -+ ++ int ret; ++ struct wmi_pdev_temperature_event *ev; + +- if (ath12k_pull_pdev_temp_ev(ab, skb->data, skb->len, &ev) != 0) { +- ath12k_warn(ab, "failed to extract pdev temperature event"); +- return; +- } + tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); + if (IS_ERR(tb)) { + ret = PTR_ERR(tb); + ath12k_warn(ab, "failed to parse tlv: %d\n", ret); + return; + } - -- if (ath12k_pull_pdev_temp_ev(ab, skb->data, skb->len, &ev) != 0) { -- ath12k_warn(ab, "failed to extract pdev temperature event"); -- return; -- } ++ + ev = tb[WMI_TAG_PDEV_TEMPERATURE_EVENT]; + if (!ev) { + ath12k_warn(ab, "failed to fetch pdev temp ev"); @@ -79,13 +77,15 @@ index ba0be25..fcf90df 100644 ath12k_dbg(ab, ATH12K_DBG_WMI, - "pdev temperature ev temp %d pdev_id %d\n", ev.temp, ev.pdev_id); -+ "pdev temperature ev temp %d pdev_id %d\n", ev->temp, ev->pdev_id); ++ "pdev temperature ev temp %d pdev_id %d\n", ev->temp, ++ ev->pdev_id); - ar = ath12k_mac_get_ar_by_pdev_id(ab, ev.pdev_id); + ar = ath12k_mac_get_ar_by_pdev_id(ab, ev->pdev_id); if (!ar) { - ath12k_warn(ab, "invalid pdev id in pdev temperature ev %d", ev.pdev_id); -+ ath12k_warn(ab, "invalid pdev id in pdev temperature ev %d", ev->pdev_id); ++ ath12k_warn(ab, "invalid pdev id in pdev temperature ev %d", ++ ev->pdev_id); return; } @@ -94,6 +94,3 @@ index ba0be25..fcf90df 100644 } static void ath12k_fils_discovery_event(struct ath12k_base *ab, --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/612-01-ath12k-add-WMI-resource-config-for-EMA.patch b/feeds/ipq95xx/mac80211/patches/qca/612-01-ath12k-add-WMI-resource-config-for-EMA.patch index ada317c02..bf88c189a 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/612-01-ath12k-add-WMI-resource-config-for-EMA.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/612-01-ath12k-add-WMI-resource-config-for-EMA.patch @@ -36,7 +36,7 @@ Signed-off-by: Aloka Dixit + config->beacon_tx_offload_max_vdev += config->ema_max_vap_cnt; } - static const struct wmi_ops wmi_qcn92xx_ops = { + static const struct wmi_ops wmi_qcn9274_ops = { @@ -3412,8 +3415,11 @@ ath12k_wmi_copy_resource_config(struct w wmi_cfg->sched_params = tg_cfg->sched_params; wmi_cfg->twt_ap_pdev_count = tg_cfg->twt_ap_pdev_count; diff --git a/feeds/ipq95xx/mac80211/patches/qca/612-03-ath12k-MBSSID-configuration-during-vdev-create-start.patch b/feeds/ipq95xx/mac80211/patches/qca/612-03-ath12k-MBSSID-configuration-during-vdev-create-start.patch index 63ca44bbd..6f0a8d61f 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/612-03-ath12k-MBSSID-configuration-during-vdev-create-start.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/612-03-ath12k-MBSSID-configuration-during-vdev-create-start.patch @@ -16,7 +16,7 @@ Signed-off-by: Aloka Dixit --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -6065,17 +6065,62 @@ ath12k_mac_get_vdev_stats_id(struct ath1 +@@ -6159,17 +6159,62 @@ ath12k_mac_get_vdev_stats_id(struct ath1 return vdev_stats_id; } @@ -82,7 +82,7 @@ Signed-off-by: Aloka Dixit if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) { params->chains[NL80211_BAND_2GHZ].tx = ar->num_tx_chains; -@@ -6092,6 +6137,7 @@ ath12k_mac_setup_vdev_create_params(stru +@@ -6186,6 +6231,7 @@ ath12k_mac_setup_vdev_create_params(stru } params->if_stats_id = ath12k_mac_get_vdev_stats_id(arvif); @@ -90,7 +90,7 @@ Signed-off-by: Aloka Dixit } static void ath12k_mac_op_update_vif_offload(struct ieee80211_hw *hw, -@@ -6232,7 +6278,12 @@ static int ath12k_mac_op_add_interface(s +@@ -6326,7 +6372,12 @@ static int ath12k_mac_op_add_interface(s for (i = 0; i < ARRAY_SIZE(vif->hw_queue); i++) vif->hw_queue[i] = i % (ATH12K_HW_MAX_QUEUES - 1); @@ -104,7 +104,7 @@ Signed-off-by: Aloka Dixit ret = ath12k_wmi_vdev_create(ar, vif->addr, &vdev_param); if (ret) { -@@ -6669,6 +6720,17 @@ ath12k_mac_vdev_start_restart(struct ath +@@ -6740,6 +6791,17 @@ ath12k_mac_vdev_start_restart(struct ath arg.pref_tx_streams = ar->num_tx_chains; arg.pref_rx_streams = ar->num_rx_chains; @@ -124,30 +124,38 @@ Signed-off-by: Aloka Dixit arg.ssid_len = arvif->u.ap.ssid_len; --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -727,6 +727,9 @@ int ath12k_wmi_vdev_create(struct ath12k - cmd->num_cfg_txrx_streams = WMI_NUM_SUPPORTED_BAND_MAX; - cmd->pdev_id = param->pdev_id; - cmd->vdev_stats_id = param->if_stats_id; -+ cmd->mbssid_flags = param->mbssid_flags; -+ cmd->mbssid_tx_vdev_id = param->mbssid_tx_vdev_id; +@@ -774,6 +774,9 @@ int ath12k_wmi_vdev_create(struct ath12k + cmd->num_cfg_txrx_streams = cpu_to_le32(WMI_NUM_SUPPORTED_BAND_MAX); + cmd->pdev_id = cpu_to_le32(param->pdev_id); + cmd->vdev_stats_id = cpu_to_le32(param->if_stats_id); ++ cmd->mbssid_flags = cpu_to_le32(param->mbssid_flags); ++ cmd->mbssid_tx_vdev_id = cpu_to_le32(param->mbssid_tx_vdev_id); + ether_addr_copy(cmd->vdev_macaddr.addr, macaddr); ptr = skb->data + sizeof(*cmd); -@@ -943,6 +946,8 @@ int ath12k_wmi_vdev_start(struct ath12k - cmd->cac_duration_ms = arg->cac_duration_ms; - cmd->regdomain = arg->regdomain; - cmd->he_ops = arg->he_ops; -+ cmd->mbssid_flags = arg->mbssid_flags; -+ cmd->mbssid_tx_vdev_id = arg->mbssid_tx_vdev_id; - cmd->ru_punct_bitmap = arg->ru_punct_bitmap; +@@ -985,6 +988,8 @@ int ath12k_wmi_vdev_start(struct ath12k + cmd->cac_duration_ms = cpu_to_le32(arg->cac_duration_ms); + cmd->regdomain = cpu_to_le32(arg->regdomain); + cmd->he_ops = cpu_to_le32(arg->he_ops); ++ cmd->mbssid_flags = cpu_to_le32(arg->mbssid_flags); ++ cmd->mbssid_tx_vdev_id = cpu_to_le32(arg->mbssid_tx_vdev_id); + cmd->ru_punct_bitmap = cpu_to_le32(arg->ru_punct_bitmap); if (!restart) { --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -138,6 +138,14 @@ enum { - WMI_AUTORATE_3200NS_GI = BIT(11), - }; +@@ -2093,6 +2093,7 @@ enum wmi_tlv_service { + WMI_TLV_SERVICE_EXT2_MSG = 220, + WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT = 249, + ++ WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT = 253, + WMI_MAX_EXT_SERVICE = 256, + + WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281, +@@ -2240,6 +2241,14 @@ struct ath12k_hal_reg_capabilities_ext { + #define WMI_MAX_EHTCAP_PHY_SIZE 3 + #define WMI_MAX_EHTCAP_RATE_SET 3 +enum { + WMI_HOST_VDEV_FLAGS_NON_MBSSID_AP = 0x00000001, @@ -158,18 +166,9 @@ Signed-off-by: Aloka Dixit +}; + /* - * wmi command groups. - */ -@@ -2097,7 +2105,7 @@ enum wmi_tlv_service { - WMI_TLV_SERVICE_FREQINFO_IN_METADATA = 219, - WMI_TLV_SERVICE_EXT2_MSG = 220, - WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT = 249, -- -+ WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT = 253, - WMI_MAX_EXT_SERVICE = 256, - - WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281, -@@ -2674,6 +2682,8 @@ struct vdev_create_params { + * 0 – index indicated EHT-MCS map for 20Mhz only sta (4 bytes valid) + * 1 – index for <= 80MHz bw (only 3 bytes are valid and other is reserved) +@@ -2668,6 +2677,8 @@ struct vdev_create_params { u8 rx; } chains[NUM_NL80211_BANDS]; u32 pdev_id; @@ -178,29 +177,29 @@ Signed-off-by: Aloka Dixit u8 if_stats_id; }; -@@ -2688,8 +2698,8 @@ struct wmi_vdev_create_cmd { +@@ -2682,8 +2693,8 @@ struct wmi_vdev_create_cmd { struct wmi_mac_addr vdev_macaddr; - u32 num_cfg_txrx_streams; - u32 pdev_id; -- u32 flags; -- u32 vdevid_trans; -+ u32 mbssid_flags; -+ u32 mbssid_tx_vdev_id; - u32 vdev_stats_id_valid; - u32 vdev_stats_id; + __le32 num_cfg_txrx_streams; + __le32 pdev_id; +- __le32 flags; +- __le32 vdevid_trans; ++ __le32 mbssid_flags; ++ __le32 mbssid_tx_vdev_id; + __le32 vdev_stats_id_valid; + __le32 vdev_stats_id; } __packed; -@@ -2755,8 +2765,8 @@ struct wmi_vdev_start_request_cmd { - u32 cac_duration_ms; - u32 regdomain; - u32 min_data_rate; -- u32 mbss_capability_flags; -- u32 vdevid_trans; -+ u32 mbssid_flags; -+ u32 mbssid_tx_vdev_id; - u32 eht_ops; - u32 ru_punct_bitmap; +@@ -2749,8 +2760,8 @@ struct wmi_vdev_start_request_cmd { + __le32 cac_duration_ms; + __le32 regdomain; + __le32 min_data_rate; +- __le32 mbss_capability_flags; +- __le32 vdevid_trans; ++ __le32 mbssid_flags; ++ __le32 mbssid_tx_vdev_id; + __le32 eht_ops; + __le32 ru_punct_bitmap; } __packed; -@@ -2955,6 +2965,9 @@ struct wmi_vdev_start_req_arg { +@@ -2949,6 +2960,9 @@ struct wmi_vdev_start_req_arg { u32 pref_rx_streams; u32 pref_tx_streams; u32 num_noa_descriptors; @@ -210,12 +209,12 @@ Signed-off-by: Aloka Dixit u32 ru_punct_bitmap; }; -@@ -3216,6 +3229,8 @@ struct wmi_pdev_suspend_cmd { - struct wmi_pdev_resume_cmd { - u32 tlv_header; +@@ -4635,6 +4649,8 @@ struct wmi_pdev_temperature_event { + /* temperature value in Celcius degree */ + s32 temp; u32 pdev_id; + u32 mbssid_flags; + u32 mbssid_tx_vdev_id; } __packed; - struct wmi_pdev_bss_chan_info_req_cmd { + #define WMI_AC_BE 0 diff --git a/feeds/ipq95xx/mac80211/patches/qca/612-04-ath12k-create-a-structure-for-WMI-vdev-up-parameters.patch b/feeds/ipq95xx/mac80211/patches/qca/612-04-ath12k-create-a-structure-for-WMI-vdev-up-parameters.patch index a5b545c7a..4ec710ed5 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/612-04-ath12k-create-a-structure-for-WMI-vdev-up-parameters.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/612-04-ath12k-create-a-structure-for-WMI-vdev-up-parameters.patch @@ -15,7 +15,7 @@ Signed-off-by: Aloka Dixit --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -856,8 +856,11 @@ static inline int ath12k_mac_vdev_setup_ +@@ -854,8 +854,11 @@ static int ath12k_mac_vdev_setup_sync(st static int ath12k_monitor_vdev_up(struct ath12k *ar, int vdev_id) { int ret = 0; @@ -28,7 +28,7 @@ Signed-off-by: Aloka Dixit if (ret) { ath12k_warn(ar->ab, "failed to put up monitor vdev %i: %d\n", vdev_id, ret); -@@ -875,6 +878,7 @@ static int ath12k_mac_monitor_vdev_start +@@ -873,6 +876,7 @@ static int ath12k_mac_monitor_vdev_start struct ieee80211_channel *channel = NULL; struct wmi_vdev_start_req_arg arg = {}; int ret = 0; @@ -68,16 +68,16 @@ Signed-off-by: Aloka Dixit if (ret) { ath12k_warn(ar->ab, "failed to bring up vdev %d: %i\n", arvif->vdev_id, ret); -@@ -2854,6 +2863,7 @@ static void ath12k_bss_assoc(struct ieee - struct ieee80211_sta *ap_sta; +@@ -2854,6 +2863,7 @@ static void ath12k_bss_assoc struct ieee80211_sta_he_cap he_cap; + bool is_auth = false; int ret; + struct vdev_up_params params = { 0 }; lockdep_assert_held(&ar->conf_mutex); -@@ -2909,7 +2919,10 @@ static void ath12k_bss_assoc(struct ieee - arvif->aid = bss_conf->aid; +@@ -2955,7 +2965,10 @@ static void ath12k_bss_assoc(struct ieee + arvif->aid = vif->cfg.aid; ether_addr_copy(arvif->bssid, bss_conf->bssid); - ret = ath12k_wmi_vdev_up(ar, arvif->vdev_id, arvif->aid, arvif->bssid); @@ -88,7 +88,7 @@ Signed-off-by: Aloka Dixit if (ret) { ath12k_warn(ar->ab, "failed to set vdev %d up: %d\n", arvif->vdev_id, ret); -@@ -6776,6 +6789,8 @@ ath12k_mac_update_vif_chan(struct ath12k +@@ -7008,6 +7021,8 @@ ath12k_mac_update_vif_chan(struct ath12k /* TODO: Update ar->rx_channel */ for (i = 0; i < n_vifs; i++) { @@ -97,7 +97,7 @@ Signed-off-by: Aloka Dixit arvif = (void *)vifs[i].vif->drv_priv; if (WARN_ON(!arvif->is_started)) -@@ -6796,8 +6811,10 @@ ath12k_mac_update_vif_chan(struct ath12k +@@ -7028,8 +7043,10 @@ ath12k_mac_update_vif_chan(struct ath12k ath12k_warn(ab, "failed to update bcn tmpl during csa: %d\n", ret); @@ -112,7 +112,7 @@ Signed-off-by: Aloka Dixit arvif->vdev_id, ret); --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -1000,7 +1000,7 @@ int ath12k_wmi_vdev_start(struct ath12k +@@ -1042,7 +1042,7 @@ int ath12k_wmi_vdev_start(struct ath12k return ret; } @@ -121,25 +121,25 @@ Signed-off-by: Aloka Dixit { struct ath12k_pdev_wmi *wmi = ar->wmi; struct wmi_vdev_up_cmd *cmd; -@@ -1015,10 +1015,13 @@ int ath12k_wmi_vdev_up(struct ath12k *ar +@@ -1057,10 +1057,13 @@ int ath12k_wmi_vdev_up(struct ath12k *ar - cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_VDEV_UP_CMD) | - FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); -- cmd->vdev_id = vdev_id; -- cmd->vdev_assoc_id = aid; + cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_VDEV_UP_CMD, + sizeof(*cmd)); +- cmd->vdev_id = cpu_to_le32(vdev_id); +- cmd->vdev_assoc_id = cpu_to_le32(aid); - - ether_addr_copy(cmd->vdev_bssid.addr, bssid); -+ cmd->vdev_id = params->vdev_id; -+ cmd->vdev_assoc_id = params->aid; ++ cmd->vdev_id = cpu_to_le32(params->vdev_id); ++ cmd->vdev_assoc_id = cpu_to_le16(params->aid); + ether_addr_copy(cmd->vdev_bssid.addr, params->bssid); -+ cmd->profile_idx = params->profile_idx; -+ cmd->profile_count = params->profile_count; ++ cmd->profile_idx = cpu_to_le32(params->profile_idx); ++ cmd->profile_count = cpu_to_le32(params->profile_count); + if (params->tx_bssid) + ether_addr_copy(cmd->tx_vdev_bssid.addr, params->tx_bssid); ret = ath12k_wmi_cmd_send(wmi, skb, WMI_VDEV_UP_CMDID); if (ret) { -@@ -1028,7 +1031,7 @@ int ath12k_wmi_vdev_up(struct ath12k *ar +@@ -1070,7 +1073,7 @@ int ath12k_wmi_vdev_up(struct ath12k *ar ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "WMI mgmt vdev up id 0x%x assoc id %d bssid %pM\n", @@ -150,33 +150,33 @@ Signed-off-by: Aloka Dixit } --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -2691,14 +2691,23 @@ struct wmi_vdev_delete_cmd { - u32 vdev_id; +@@ -2711,14 +2711,23 @@ struct wmi_vdev_delete_cmd { + __le32 vdev_id; } __packed; +struct vdev_up_params { -+ u32 vdev_id; -+ u16 aid; ++ __le32 vdev_id; ++ __le16 aid; + const u8 *bssid; -+ u32 profile_idx; -+ u32 profile_count; ++ __le32 profile_idx; ++ __le32 profile_count; + u8 *tx_bssid; -+}; ++} __packed; + struct wmi_vdev_up_cmd { - u32 tlv_header; - u32 vdev_id; - u32 vdev_assoc_id; + __le32 tlv_header; + __le32 vdev_id; + __le32 vdev_assoc_id; struct wmi_mac_addr vdev_bssid; - struct wmi_mac_addr trans_bssid; + struct wmi_mac_addr tx_vdev_bssid; - u32 profile_idx; -- u32 profile_num; -+ u32 profile_count; + __le32 profile_idx; +- __le32 profile_num; ++ __le32 profile_count; } __packed; struct wmi_vdev_stop_cmd { -@@ -5602,8 +5611,7 @@ int ath12k_wmi_bcn_tmpl(struct ath12k *a +@@ -5568,8 +5577,7 @@ int ath12k_wmi_bcn_tmpl(struct ath12k *a struct ieee80211_mutable_offsets *offs, struct sk_buff *bcn); int ath12k_wmi_vdev_down(struct ath12k *ar, u8 vdev_id); diff --git a/feeds/ipq95xx/mac80211/patches/qca/612-05-ath12k-configure-MBSSID-device-parameters.patch b/feeds/ipq95xx/mac80211/patches/qca/612-05-ath12k-configure-MBSSID-device-parameters.patch index 1619101d5..81d97038a 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/612-05-ath12k-configure-MBSSID-device-parameters.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/612-05-ath12k-configure-MBSSID-device-parameters.patch @@ -19,7 +19,7 @@ Signed-off-by: Aloka Dixit --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h -@@ -277,6 +277,7 @@ struct ath12k_vif { +@@ -274,6 +274,7 @@ struct ath12k_vif { u8 tx_encap_type; u8 vdev_stats_id; struct ath12k_fw_vdev_ol_stats vdev_stats; @@ -67,7 +67,7 @@ Signed-off-by: Aloka Dixit ret = ath12k_wmi_vdev_up(arvif->ar, ¶ms); if (ret) { ath12k_warn(ar->ab, "failed to bring up vdev %d: %i\n", -@@ -2954,7 +2968,7 @@ static void ath12k_bss_disassoc(struct i +@@ -3010,7 +3024,7 @@ static void ath12k_bss_disassoc(struct i struct ieee80211_vif *vif) { struct ath12k *ar = hw->priv; @@ -76,7 +76,7 @@ Signed-off-by: Aloka Dixit int ret; lockdep_assert_held(&ar->conf_mutex); -@@ -2968,6 +2982,11 @@ static void ath12k_bss_disassoc(struct i +@@ -3024,6 +3038,11 @@ static void ath12k_bss_disassoc(struct i arvif->vdev_id, ret); arvif->is_up = false; @@ -88,17 +88,17 @@ Signed-off-by: Aloka Dixit /* TODO: cancel connection_loss_work */ } -@@ -3352,7 +3371,8 @@ static void ath12k_mac_op_bss_info_chang - ret = ath12k_wmi_send_obss_color_collision_cfg_cmd( - ar, arvif->vdev_id, info->he_bss_color.color, - ATH12K_BSS_COLOR_COLLISION_DETECTION_AP_PERIOD_MS, -- info->he_bss_color.enabled); -+ arvif->vif->bss_conf.nontransmitted ? -+ 0 : info->he_bss_color.enabled); +@@ -3593,7 +3612,8 @@ static void ath12k_mac_op_bss_info_chang + arvif->vdev_id, + info->he_bss_color.color, + ATH12K_BSS_COLOR_AP_PERIODS, +- info->he_bss_color.enabled); ++ arvif->vif->bss_conf.nontransmitted ? ++ 0 : info->he_bss_color.enabled); if (ret) ath12k_warn(ar->ab, "failed to set bss color collision on vdev %i: %d\n", arvif->vdev_id, ret); -@@ -6747,7 +6767,7 @@ ath12k_mac_update_vif_chan(struct ath12k +@@ -6979,7 +6999,7 @@ ath12k_mac_update_vif_chan(struct ath12k int n_vifs) { struct ath12k_base *ab = ar->ab; @@ -107,7 +107,7 @@ Signed-off-by: Aloka Dixit int ret; int i; bool monitor_vif = false; -@@ -6814,6 +6834,12 @@ ath12k_mac_update_vif_chan(struct ath12k +@@ -7046,6 +7066,12 @@ ath12k_mac_update_vif_chan(struct ath12k params.vdev_id = arvif->vdev_id; params.aid = arvif->aid; params.bssid = arvif->bssid; diff --git a/feeds/ipq95xx/mac80211/patches/qca/612-07-ath12k-EMA-beacon-support.patch b/feeds/ipq95xx/mac80211/patches/qca/612-07-ath12k-EMA-beacon-support.patch index 861123d94..75ceb3712 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/612-07-ath12k-EMA-beacon-support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/612-07-ath12k-EMA-beacon-support.patch @@ -17,11 +17,12 @@ Signed-off-by: Aloka Dixit --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -1195,37 +1195,114 @@ static void ath12k_mac_setup_bcn_tmpl_vi +@@ -1195,37 +1195,116 @@ static void ath12k_mac_setup_bcn_tmpl_vi arvif->wpaie_present = true; } -static int ath12k_mac_setup_bcn_tmpl(struct ath12k_vif *arvif) ++ +static int __ath12k_mac_setup_bcn_tmpl(struct ath12k_vif *arvif, + struct sk_buff *bcn, + struct ieee80211_mutable_offsets offs, @@ -57,7 +58,7 @@ Signed-off-by: Aloka Dixit + + tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv; + beacons = ieee80211_beacon_get_template_ema_list(tx_arvif->ar->hw, -+ tx_arvif->vif); ++ tx_arvif->vif, 0); + if (!beacons || !beacons->cnt) { + ath12k_warn(arvif->ar->ab, + "failed to get ema beacon templates from mac80211\n"); @@ -96,9 +97,9 @@ Signed-off-by: Aloka Dixit + if (arvif->vif->mbssid_tx_vif) + tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv; -- bcn = ieee80211_beacon_get_template(hw, vif, &offs); +- bcn = ieee80211_beacon_get_template(hw, vif, &offs, 0); + bcn = ieee80211_beacon_get_template(tx_arvif->ar->hw, tx_arvif->vif, -+ &offs); ++ &offs, 0); if (!bcn) { - ath12k_warn(ab, "failed to get beacon template from mac80211\n"); + ath12k_warn(arvif->ar->ab, @@ -141,13 +142,14 @@ Signed-off-by: Aloka Dixit + else + return ath12k_mac_setup_bcn_tmpl_non_ema(arvif); +} ++ + static void ath12k_control_beaconing(struct ath12k_vif *arvif, struct ieee80211_bss_conf *info) { --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -1679,7 +1679,7 @@ int ath12k_wmi_send_bcn_offload_control_ +@@ -1714,7 +1714,7 @@ int ath12k_wmi_send_bcn_offload_control_ int ath12k_wmi_bcn_tmpl(struct ath12k *ar, u32 vdev_id, struct ieee80211_mutable_offsets *offs, @@ -156,18 +158,18 @@ Signed-off-by: Aloka Dixit { struct ath12k_pdev_wmi *wmi = ar->wmi; struct wmi_bcn_tmpl_cmd *cmd; -@@ -1704,6 +1704,8 @@ int ath12k_wmi_bcn_tmpl(struct ath12k *a - cmd->csa_switch_count_offset = offs->cntdwn_counter_offs[0]; - cmd->ext_csa_switch_count_offset = offs->cntdwn_counter_offs[1]; - cmd->buf_len = bcn->len; -+ cmd->mbssid_ie_offset = offs->mbssid_off; -+ cmd->ema_params = ema_params; +@@ -1739,6 +1739,8 @@ int ath12k_wmi_bcn_tmpl(struct ath12k *a + cmd->csa_switch_count_offset = cpu_to_le32(offs->cntdwn_counter_offs[0]); + cmd->ext_csa_switch_count_offset = cpu_to_le32(offs->cntdwn_counter_offs[1]); + cmd->buf_len = cpu_to_le32(bcn->len); ++ cmd->mbssid_ie_offset = cpu_to_le32(offs->mbssid_off); ++ cmd->ema_params = cpu_to_le32(ema_params); ptr = skb->data + sizeof(*cmd); --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -3698,6 +3698,11 @@ struct wmi_get_pdev_temperature_cmd { +@@ -3681,6 +3681,11 @@ struct wmi_get_pdev_temperature_cmd { #define WMI_BEACON_TX_BUFFER_SIZE 512 @@ -177,21 +179,21 @@ Signed-off-by: Aloka Dixit +#define WMI_BEACON_EMA_PARAM_LAST_TMPL_SHIFT 24 + struct wmi_bcn_tmpl_cmd { - u32 tlv_header; - u32 vdev_id; -@@ -3708,6 +3713,11 @@ struct wmi_bcn_tmpl_cmd { - u32 csa_event_bitmap; - u32 mbssid_ie_offset; - u32 esp_ie_offset; -+ u32 csc_switch_count_offset; -+ u32 csc_event_bitmap; -+ u32 mu_edca_ie_offset; -+ u32 feature_enable_bitmap; -+ u32 ema_params; + __le32 tlv_header; + __le32 vdev_id; +@@ -3691,6 +3696,11 @@ struct wmi_bcn_tmpl_cmd { + __le32 csa_event_bitmap; + __le32 mbssid_ie_offset; + __le32 esp_ie_offset; ++ __le32 csc_switch_count_offset; ++ __le32 csc_event_bitmap; ++ __le32 mu_edca_ie_offset; ++ __le32 feature_enable_bitmap; ++ __le32 ema_params; } __packed; struct wmi_key_seq_counter { -@@ -5609,7 +5619,7 @@ int ath12k_wmi_mgmt_send(struct ath12k * +@@ -5575,7 +5585,7 @@ int ath12k_wmi_mgmt_send(struct ath12k * struct sk_buff *frame); int ath12k_wmi_bcn_tmpl(struct ath12k *ar, u32 vdev_id, struct ieee80211_mutable_offsets *offs, diff --git a/feeds/ipq95xx/mac80211/patches/qca/614-ath12k-Fix-firmware-assert-due-to-ce-count-mismatch.patch b/feeds/ipq95xx/mac80211/patches/qca/614-ath12k-Fix-firmware-assert-due-to-ce-count-mismatch.patch index 05584d42e..f4cfadb67 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/614-ath12k-Fix-firmware-assert-due-to-ce-count-mismatch.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/614-ath12k-Fix-firmware-assert-due-to-ce-count-mismatch.patch @@ -13,13 +13,11 @@ Signed-off-by: P Praneesh drivers/net/wireless/ath/ath12k/hw.c | 14 +++++++------- 3 files changed, 17 insertions(+), 9 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/ce.c b/drivers/net/wireless/ath/ath12k/ce.c -index 5bcdacd..83ec1f3 100644 --- a/drivers/net/wireless/ath/ath12k/ce.c +++ b/drivers/net/wireless/ath/ath12k/ce.c -@@ -132,6 +132,14 @@ const struct ce_attr ath12k_host_ce_config_qcn92xx[] = { - .dest_nentries = 512, - .recv_cb = ath12k_htc_rx_completion_handler, +@@ -140,6 +140,14 @@ const struct ce_attr ath12k_host_ce_conf + .src_sz_max = 0, + .dest_nentries = 0, }, + + /* CE15: reserved for customer use */ @@ -31,69 +29,4 @@ index 5bcdacd..83ec1f3 100644 + }, }; - static int ath12k_ce_rx_buf_enqueue_pipe(struct ath12k_ce_pipe *pipe, -diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c -index 6c20d22..022de5c 100644 ---- a/drivers/net/wireless/ath/ath12k/core.c -+++ b/drivers/net/wireless/ath/ath12k/core.c -@@ -48,9 +48,9 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { - .internal_sleep_clock = false, - .regs = &qcn92xx_regs, - .host_ce_config = ath12k_host_ce_config_qcn92xx, -- .ce_count = 14, -+ .ce_count = 16, - .target_ce_config = ath12k_target_ce_config_wlan_qcn92xx, -- .target_ce_count = 9, -+ .target_ce_count = 12, - .svc_to_ce_map = ath12k_target_service_to_ce_map_wlan_qcn92xx, - .svc_to_ce_map_len = 21, - .rxdma1_enable = true, -diff --git a/drivers/net/wireless/ath/ath12k/hw.c b/drivers/net/wireless/ath/ath12k/hw.c -index 2b2f1af..cbb5e18 100644 ---- a/drivers/net/wireless/ath/ath12k/hw.c -+++ b/drivers/net/wireless/ath/ath12k/hw.c -@@ -160,7 +160,7 @@ const struct ce_pipe_config ath12k_target_ce_config_wlan_qcn92xx[] = { - .pipedir = __cpu_to_le32(PIPEDIR_OUT), - .nentries = __cpu_to_le32(32), - .nbytes_max = __cpu_to_le32(2048), -- .flags = __cpu_to_le32(8192), -+ .flags = __cpu_to_le32(CE_ATTR_FLAGS), - .reserved = __cpu_to_le32(0), - }, - -@@ -170,7 +170,7 @@ const struct ce_pipe_config ath12k_target_ce_config_wlan_qcn92xx[] = { - .pipedir = __cpu_to_le32(PIPEDIR_OUT), - .nentries = __cpu_to_le32(32), - .nbytes_max = __cpu_to_le32(2048), -- .flags = __cpu_to_le32(8192), -+ .flags = __cpu_to_le32(CE_ATTR_FLAGS), - .reserved = __cpu_to_le32(0), - }, - -@@ -273,11 +273,6 @@ const struct service_to_pipe ath12k_target_service_to_ce_map_wlan_qcn92xx[] = { - __cpu_to_le32(1), - }, - { -- __cpu_to_le32(ATH12K_HTC_SVC_ID_PKT_LOG), -- __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ -- __cpu_to_le32(5), -- }, -- { - __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_CONTROL_MAC1), - __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */ - __cpu_to_le32(7), -@@ -288,6 +283,11 @@ const struct service_to_pipe ath12k_target_service_to_ce_map_wlan_qcn92xx[] = { - __cpu_to_le32(2), - }, - { -+ __cpu_to_le32(ATH12K_HTC_SVC_ID_PKT_LOG), -+ __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ -+ __cpu_to_le32(5), -+ }, -+ { - __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_CONTROL_DIAG), - __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ - __cpu_to_le32(14), --- -2.7.4 - + const struct ce_attr ath12k_host_ce_config_wcn7850[] = { diff --git a/feeds/ipq95xx/mac80211/patches/qca/614-ath12k-Skip-SW-decryption-for-groupcast-mgmt-frames.patch b/feeds/ipq95xx/mac80211/patches/qca/614-ath12k-Skip-SW-decryption-for-groupcast-mgmt-frames.patch deleted file mode 100644 index e8d5e03aa..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/614-ath12k-Skip-SW-decryption-for-groupcast-mgmt-frames.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 4240bd1ee0f6fe498c1f4488f90ffb36076d57df Mon Sep 17 00:00:00 2001 -From: Ramya Gnanasekar -Date: Wed, 20 Apr 2022 11:23:28 +0530 -Subject: [PATCH] ath12k: Skip SW decryption for groupcast mgmt frames - -When protected bit is set, multicast/broadcast management frames will not -be decrypted by crypto HW and will be forwarded as encrypted payload -to the host. -In QCN9274, crypto hardware decrypts mutlicast/broadcast management -frames with protected bit set. Since host expects it to be encrypted -frame tires to decrypt again and fails. This causes mesh MPATH request which -is broadcast action frame get dropped. -Hence skipped the decryption routine for multicast/broadcast management -frames as well in case of PMF since it is already decrypted by crypto. - -Signed-off-by: Ramya Gnanasekar - -diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c -index 7d3d92d..4f38c7e 100644 ---- a/drivers/net/wireless/ath/ath12k/wmi.c -+++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -6689,12 +6689,10 @@ static void ath12k_mgmt_rx_event(struct ath12k_base *ab, struct sk_buff *skb) - */ - status->flag |= RX_FLAG_SKIP_MONITOR; - -- /* In case of PMF, FW delivers decrypted frames with Protected Bit set. -- * Don't clear that. Also, FW delivers broadcast management frames -- * (ex: group privacy action frames in mesh) as encrypted payload. -+ /* In case of PMF, FW delivers decrypted frames with Protected Bit set -+ * including group privacy action frames. - */ -- if (ieee80211_has_protected(hdr->frame_control) && -- !is_multicast_ether_addr(ieee80211_get_DA(hdr))) { -+ if (ieee80211_has_protected(hdr->frame_control)) { - status->flag |= RX_FLAG_DECRYPTED; - - if (!ieee80211_is_robust_mgmt_frame(skb)) { --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/614-ath12k-wbm-err-invalid-frames.patch b/feeds/ipq95xx/mac80211/patches/qca/614-ath12k-wbm-err-invalid-frames.patch deleted file mode 100644 index 877fe5da5..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/614-ath12k-wbm-err-invalid-frames.patch +++ /dev/null @@ -1,133 +0,0 @@ -From 3b1e0b4fbfba55486a3c74a1bb7ca7f8237286c5 Mon Sep 17 00:00:00 2001 -From: Sriram R -Date: Thu, 7 Apr 2022 14:30:17 +0530 -Subject: [PATCH] ath12k: drop invalid frames in wbm err path - -Drop frames with invalid peer id and frames having continuation -bit set even after sg frames are dropped in wbm err path - -Signed-off-by: Sriram R ---- - drivers/net/wireless/ath/ath12k/dp_rx.c | 27 ++++++++++++++++++++++----- - drivers/net/wireless/ath/ath12k/hal_desc.h | 4 ++++ - drivers/net/wireless/ath/ath12k/hal_rx.c | 4 ++++ - drivers/net/wireless/ath/ath12k/hal_rx.h | 1 + - 4 files changed, 31 insertions(+), 5 deletions(-) - -diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c -index 6e556ce..728c001 100644 ---- a/drivers/net/wireless/ath/ath12k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -3668,13 +3668,20 @@ static int ath12k_dp_rx_h_null_q_desc(struct ath12k *ar, struct sk_buff *msdu, - struct sk_buff_head *msdu_list) - { - struct ath12k_base *ab = ar->ab; -- u16 msdu_len; -+ u16 msdu_len, peer_id; - struct hal_rx_desc *desc = (struct hal_rx_desc *)msdu->data; - u8 l3pad_bytes; - struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu); - u32 hal_rx_desc_sz = ar->ab->hw_params.hal_desc_sz; - - msdu_len = ath12k_dp_rx_h_msdu_len(ab, desc); -+ peer_id = ath12k_dp_rx_h_peer_id(ab, desc); -+ -+ if(!ath12k_peer_find_by_id(ab, peer_id)) { -+ ath12k_dbg(ab, ATH12K_DBG_DATA, "invalid peer id received in wbm err pkt%d\n", -+ peer_id); -+ return -EINVAL; -+ } - - if (!rxcb->is_frag && ((msdu_len + hal_rx_desc_sz) > DP_RX_BUFFER_SIZE)) { - /* First buffer will be freed by the caller, so deduct it's length */ -@@ -3683,6 +3690,13 @@ static int ath12k_dp_rx_h_null_q_desc(struct ath12k *ar, struct sk_buff *msdu, - return -EINVAL; - } - -+ /* Even after cleaning up the sg buffers in the msdu list with above check -+ * any msdu received with continuation flag needs to be dropped as invalid. -+ * This protects against some random err frame with continuation flag. -+ */ -+ if (rxcb->is_continuation) -+ return -EINVAL; -+ - if (!ath12k_dp_rx_h_msdu_done(desc)) { - ath12k_warn(ar->ab, - "msdu_done bit not set in null_q_des processing\n"); -@@ -3699,9 +3713,6 @@ static int ath12k_dp_rx_h_null_q_desc(struct ath12k *ar, struct sk_buff *msdu, - * This error can show up both in a REO destination or WBM release ring. - */ - -- rxcb->is_first_msdu = ath12k_dp_rx_h_first_msdu(ab, desc); -- rxcb->is_last_msdu = ath12k_dp_rx_h_last_msdu(ab, desc); -- - if (rxcb->is_frag) { - skb_pull(msdu, hal_rx_desc_sz); - } else { -@@ -3912,7 +3923,9 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab, - - num_buffs_reaped++; - total_num_buffs_reaped++; -- budget--; -+ -+ if (!err_info.continuation) -+ budget--; - - if (err_info.push_reason != - HAL_REO_DEST_RING_PUSH_REASON_ERR_DETECTED) { -@@ -3924,6 +3937,10 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab, - rxcb->err_code = err_info.err_code; - rxcb->rx_desc = (struct hal_rx_desc *)msdu->data; - __skb_queue_tail(&msdu_list[mac_id], msdu); -+ -+ rxcb->is_first_msdu = err_info.first_msdu; -+ rxcb->is_last_msdu = err_info.last_msdu; -+ rxcb->is_continuation = err_info.continuation; - } - - ath12k_hal_srng_access_end(ab, srng); -diff --git a/drivers/net/wireless/ath/ath12k/hal_desc.h b/drivers/net/wireless/ath/ath12k/hal_desc.h -index f81bfcb..d925a2c 100644 ---- a/drivers/net/wireless/ath/ath12k/hal_desc.h -+++ b/drivers/net/wireless/ath/ath12k/hal_desc.h -@@ -1971,6 +1971,10 @@ struct hal_wbm_release_ring_cc_rx { - #define HAL_WBM_RELEASE_INFO0_REO_ERROR_CODE GENMASK(30, 26) - #define HAL_WBM_RELEASE_INFO0_WBM_INTERNAL_ERROR BIT(31) - -+#define HAL_WBM_RELEASE_INFO3_FIRST_MSDU BIT(0) -+#define HAL_WBM_RELEASE_INFO3_LAST_MSDU BIT(1) -+#define HAL_WBM_RELEASE_INFO3_CONTINUATION BIT(2) -+ - #define HAL_WBM_RELEASE_INFO5_LOOPING_COUNT GENMASK(31, 28) - - struct hal_wbm_release_ring { -diff --git a/drivers/net/wireless/ath/ath12k/hal_rx.c b/drivers/net/wireless/ath/ath12k/hal_rx.c -index fc11b5e..c6b412e 100644 ---- a/drivers/net/wireless/ath/ath12k/hal_rx.c -+++ b/drivers/net/wireless/ath/ath12k/hal_rx.c -@@ -410,6 +410,10 @@ int ath12k_hal_wbm_desc_parse_err(struct ath12k_base *ab, void *desc, - rel_info->err_rel_src = rel_src; - rel_info->hw_cc_done = hw_cc_done; - -+ rel_info->first_msdu = FIELD_GET(HAL_WBM_RELEASE_INFO3_FIRST_MSDU, wbm_desc->info3); -+ rel_info->last_msdu = FIELD_GET(HAL_WBM_RELEASE_INFO3_LAST_MSDU, wbm_desc->info3); -+ rel_info->continuation = FIELD_GET(HAL_WBM_RELEASE_INFO3_CONTINUATION, wbm_desc->info3); -+ - if (rel_info->err_rel_src == HAL_WBM_REL_SRC_MODULE_REO) { - rel_info->push_reason = - FIELD_GET(HAL_WBM_RELEASE_INFO0_REO_PUSH_REASON, -diff --git a/drivers/net/wireless/ath/ath12k/hal_rx.h b/drivers/net/wireless/ath/ath12k/hal_rx.h -index c1402e7..df6aaa2 100644 ---- a/drivers/net/wireless/ath/ath12k/hal_rx.h -+++ b/drivers/net/wireless/ath/ath12k/hal_rx.h -@@ -14,6 +14,7 @@ struct hal_rx_wbm_rel_info { - u32 err_code; - bool first_msdu; - bool last_msdu; -+ bool continuation; - void *rx_desc; - bool hw_cc_done; - }; --- -2.7.4 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/616-ath12k-add-WMI-calls-to-manually-add-del-pause-resum.patch b/feeds/ipq95xx/mac80211/patches/qca/616-ath12k-add-WMI-calls-to-manually-add-del-pause-resum.patch index 58c173999..bf34999ce 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/616-ath12k-add-WMI-calls-to-manually-add-del-pause-resum.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/616-ath12k-add-WMI-calls-to-manually-add-del-pause-resum.patch @@ -34,7 +34,7 @@ Signed-off-by: Aloka Dixit + .min_len = sizeof(struct wmi_twt_add_dialog_event) }, }; - static void ath12k_init_wmi_config_qcn92xx(struct ath12k_base *ab, + static void ath12k_init_wmi_config_qcn9274(struct ath12k_base *ab, @@ -3051,11 +3053,12 @@ ath12k_wmi_send_twt_enable_cmd(struct at /* TODO add MBSSID support */ cmd->mbss_support = 0; diff --git a/feeds/ipq95xx/mac80211/patches/qca/617-ath12k-add-debugfs-for-TWT-debug-calls.patch b/feeds/ipq95xx/mac80211/patches/qca/617-ath12k-add-debugfs-for-TWT-debug-calls.patch index d84bca383..8f4b4d5fe 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/617-ath12k-add-debugfs-for-TWT-debug-calls.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/617-ath12k-add-debugfs-for-TWT-debug-calls.patch @@ -54,9 +54,39 @@ Signed-off-by: Aloka Dixit }; struct ath12k_vif_iter { +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -6717,6 +6717,10 @@ static int ath12k_mac_op_add_interface(s + if (vif->type != NL80211_IFTYPE_MONITOR && ar->monitor_conf_enabled) + ath12k_mac_monitor_vdev_create(ar); + ++ ret = ath12k_debugfs_add_interface(arvif); ++ if (ret) ++ goto err_peer_del; ++ + mutex_unlock(&ar->conf_mutex); + + return ret; +@@ -6752,6 +6756,7 @@ err_vdev_del: + spin_unlock_bh(&ar->data_lock); + + err: ++ ath12k_debugfs_remove_interface(arvif); + mutex_unlock(&ar->conf_mutex); + + return ret; +@@ -6852,6 +6857,8 @@ err_vdev_del: + ath12k_mac_txpower_recalc(ar); + clear_bit(ATH12K_FLAG_MONITOR_ENABLED, &ar->monitor_flags); + ++ ath12k_debugfs_remove_interface(arvif); ++ + /* TODO: recal traffic pause state based on the available vdevs */ + + mutex_unlock(&ar->conf_mutex); --- a/drivers/net/wireless/ath/ath12k/debugfs.c +++ b/drivers/net/wireless/ath/ath12k/debugfs.c -@@ -1340,3 +1340,225 @@ void ath12k_debugfs_destroy(void) +@@ -1263,3 +1263,225 @@ void ath12k_debugfs_destroy(void) debugfs_remove_recursive(debugfs_ath12k); debugfs_ath12k = NULL; } @@ -284,7 +314,7 @@ Signed-off-by: Aloka Dixit +} --- a/drivers/net/wireless/ath/ath12k/debugfs.h +++ b/drivers/net/wireless/ath/ath12k/debugfs.h -@@ -150,6 +150,9 @@ static inline int ath12k_debugfs_rx_filt +@@ -160,6 +160,9 @@ static inline int ath12k_debugfs_rx_filt return ar->debug.rx_filter; } @@ -294,50 +324,17 @@ Signed-off-by: Aloka Dixit #else static inline int ath12k_debugfs_create(void) { -@@ -226,6 +229,15 @@ static inline int ath12k_debugfs_rx_filt +@@ -236,6 +239,13 @@ static inline int ath12k_debugfs_rx_filt return 0; } --#endif /* CPTCFG_MAC80211_DEBUGFS*/ +static inline int ath12k_debugfs_add_interface(struct ath12k_vif *arvif) +{ -+ return 0; +} + +static inline void ath12k_debugfs_remove_interface(struct ath12k_vif *arvif) +{ +} -+ -+#endif /* CPTCFG_ATH12K_DEBUGFS*/ + #endif /* CPTCFG_MAC80211_DEBUGFS*/ #endif /* _ATH12K_DEBUGFS_H_ */ ---- a/drivers/net/wireless/ath/ath12k/mac.c -+++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -6613,6 +6613,10 @@ static int ath12k_mac_op_add_interface(s - if (vif->type != NL80211_IFTYPE_MONITOR && ar->monitor_conf_enabled) - ath12k_mac_monitor_vdev_create(ar); - -+ ret = ath12k_debugfs_add_interface(arvif); -+ if (ret) -+ goto err_peer_del; -+ - mutex_unlock(&ar->conf_mutex); - - return ret; -@@ -6648,6 +6652,7 @@ err_vdev_del: - spin_unlock_bh(&ar->data_lock); - - err: -+ ath12k_debugfs_remove_interface(arvif); - mutex_unlock(&ar->conf_mutex); - - return ret; -@@ -6748,6 +6753,8 @@ err_vdev_del: - ath12k_mac_txpower_recalc(ar); - clear_bit(ATH12K_FLAG_MONITOR_ENABLED, &ar->monitor_flags); - -+ ath12k_debugfs_remove_interface(arvif); -+ - /* TODO: recal traffic pause state based on the available vdevs */ - - mutex_unlock(&ar->conf_mutex); diff --git a/feeds/ipq95xx/mac80211/patches/qca/618-ath12k-remove-msdu-and-mpdu-tags-from-rxdesc.patch b/feeds/ipq95xx/mac80211/patches/qca/618-ath12k-remove-msdu-and-mpdu-tags-from-rxdesc.patch deleted file mode 100644 index ac8433bea..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/618-ath12k-remove-msdu-and-mpdu-tags-from-rxdesc.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 0f6ea84179c8bf9bba550019b5e90bad8de2085c Mon Sep 17 00:00:00 2001 -From: Sriram R -Date: Fri, 22 Apr 2022 17:10:12 +0530 -Subject: [PATCH] ath12k: remove msdu and mpdu tags from rxdesc - -This is a temporary change to remove tags from rxdesc - -Signed-off-by: Sriram R ---- - drivers/net/wireless/ath/ath12k/hal.c | 11 ++--------- - drivers/net/wireless/ath/ath12k/rx_desc.h | 2 -- - 2 files changed, 2 insertions(+), 11 deletions(-) - -diff --git a/drivers/net/wireless/ath/ath12k/hal.c b/drivers/net/wireless/ath/ath12k/hal.c -index 0a146d4..c575a6a 100644 ---- a/drivers/net/wireless/ath/ath12k/hal.c -+++ b/drivers/net/wireless/ath/ath12k/hal.c -@@ -350,12 +350,6 @@ static void ath12k_hw_qcn92xx_rx_desc_copy_end_tlv(struct hal_rx_desc *fdesc, - sizeof(struct rx_msdu_end_qcn92xx)); - } - --static u32 ath12k_hw_qcn92xx_rx_desc_get_mpdu_start_tag(struct hal_rx_desc *desc) --{ -- return FIELD_GET(HAL_TLV_HDR_TAG, -- __le64_to_cpu(desc->u.qcn92xx.mpdu_start_tag)); --} -- - static u32 ath12k_hw_qcn92xx_rx_desc_get_mpdu_ppdu_id(struct hal_rx_desc *desc) - { - return __le16_to_cpu(desc->u.qcn92xx.mpdu_start.phy_ppdu_id); -@@ -378,12 +372,12 @@ static u8 *ath12k_hw_qcn92xx_rx_desc_get_msdu_payload(struct hal_rx_desc *desc) - - static u32 ath12k_hw_qcn92xx_rx_desc_get_mpdu_start_offset(void) - { -- return offsetof(struct hal_rx_desc_qcn92xx, mpdu_start_tag); -+ return offsetof(struct hal_rx_desc_qcn92xx, mpdu_start); - } - - static u32 ath12k_hw_qcn92xx_rx_desc_get_msdu_end_offset(void) - { -- return offsetof(struct hal_rx_desc_qcn92xx, msdu_end_tag); -+ return offsetof(struct hal_rx_desc_qcn92xx, msdu_end); - } - - static bool ath12k_hw_qcn92xx_rx_desc_mac_addr2_valid(struct hal_rx_desc *desc) -@@ -487,7 +481,6 @@ static const struct hal_ops hal_qcn92xx_ops = { - .rx_desc_get_mpdu_tid = ath12k_hw_qcn92xx_rx_desc_get_mpdu_tid, - .rx_desc_get_mpdu_peer_id = ath12k_hw_qcn92xx_rx_desc_get_mpdu_peer_id, - .rx_desc_copy_end_tlv = ath12k_hw_qcn92xx_rx_desc_copy_end_tlv, -- .rx_desc_get_mpdu_start_tag = ath12k_hw_qcn92xx_rx_desc_get_mpdu_start_tag, - .rx_desc_get_mpdu_ppdu_id = ath12k_hw_qcn92xx_rx_desc_get_mpdu_ppdu_id, - .rx_desc_set_msdu_len = ath12k_hw_qcn92xx_rx_desc_set_msdu_len, - .rx_desc_get_msdu_payload = ath12k_hw_qcn92xx_rx_desc_get_msdu_payload, -diff --git a/drivers/net/wireless/ath/ath12k/rx_desc.h b/drivers/net/wireless/ath/ath12k/rx_desc.h -index 02c54e9..92417cb 100644 ---- a/drivers/net/wireless/ath/ath12k/rx_desc.h -+++ b/drivers/net/wireless/ath/ath12k/rx_desc.h -@@ -1394,9 +1394,7 @@ struct rx_msdu_end_qcn92xx { - * Need to remove unused qwords and make them compact/aligned - */ - struct hal_rx_desc_qcn92xx { -- __le64 msdu_end_tag; - struct rx_msdu_end_qcn92xx msdu_end; -- __le64 mpdu_start_tag; - struct rx_mpdu_start_qcn92xx mpdu_start; - u8 msdu_payload[0]; - } __packed; --- -2.7.4 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/619-mac80211-support-320-Mhz-in-Wide-bandwidth-CSA.patch b/feeds/ipq95xx/mac80211/patches/qca/619-mac80211-support-320-Mhz-in-Wide-bandwidth-CSA.patch index cfd7bf203..4ef325497 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/619-mac80211-support-320-Mhz-in-Wide-bandwidth-CSA.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/619-mac80211-support-320-Mhz-in-Wide-bandwidth-CSA.patch @@ -11,11 +11,9 @@ channel width and frequency has to be updated to cfg80211_chan_def. Signed-off-by: Ramya Gnanasekar -Index: b/include/linux/ieee80211.h -=================================================================== ---- a/include/linux/ieee80211.h 2022-05-23 10:53:51.287421979 +0530 -+++ b/include/linux/ieee80211.h 2022-05-23 10:53:51.283422015 +0530 -@@ -1786,20 +1786,26 @@ struct ieee80211_vht_cap { +--- a/include/linux/ieee80211.h ++++ b/include/linux/ieee80211.h +@@ -1826,20 +1826,26 @@ struct ieee80211_vht_cap { } __packed; /** @@ -53,7 +51,7 @@ Index: b/include/linux/ieee80211.h /** * struct ieee80211_vht_operation - VHT operation IE * -@@ -2089,7 +2095,7 @@ struct ieee80211_eht_operation { +@@ -2155,7 +2161,7 @@ struct ieee80211_eht_operation_info { * Note: This function is exported by cfg80211. */ int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap, @@ -62,10 +60,8 @@ Index: b/include/linux/ieee80211.h int mcs, bool ext_nss_bw_capable, unsigned int max_vht_nss); -Index: b/net/mac80211/spectmgmt.c -=================================================================== ---- a/net/mac80211/spectmgmt.c 2022-05-23 10:53:51.287421979 +0530 -+++ b/net/mac80211/spectmgmt.c 2022-05-23 10:54:12.043228847 +0530 +--- a/net/mac80211/spectmgmt.c ++++ b/net/mac80211/spectmgmt.c @@ -30,13 +30,17 @@ int ieee80211_parse_ch_switch_ie(struct int new_freq; u8 new_chan_no; @@ -79,14 +75,14 @@ Index: b/net/mac80211/spectmgmt.c + struct ieee80211_he_operation he_oper; + struct ieee80211_he_6ghz_oper he_6ghz_oper; + struct ieee80211_eht_operation eht_oper; ++ struct ieee80211_eht_operation_info eht_oper_info; int secondary_channel_offset = -1; - u8 new_seg1; + u8 new_seg1, new_chan_width; -+ u32 eht_oper_params = 0; memset(csa_ie, 0, sizeof(*csa_ie)); -@@ -136,48 +140,74 @@ int ieee80211_parse_ch_switch_ie(struct +@@ -136,48 +140,78 @@ int ieee80211_parse_ch_switch_ie(struct } if (wide_bw_chansw_ie) { @@ -106,11 +102,6 @@ Index: b/net/mac80211/spectmgmt.c + he_6ghz_oper.ccfs0 = wide_bw_chansw_ie->new_center_freq_seg0; + he_6ghz_oper.ccfs1 = new_seg1; + -+ eht_oper.chan_width = (eht_oper_params & -+ IEEE80211_EHT_OPER_CHAN_WIDTH) | -+ new_chan_width; -+ eht_oper.ccfs = wide_bw_chansw_ie->new_center_freq_seg0; -+ + he_oper.he_oper_params = u32_encode_bits(1, + IEEE80211_HE_OPERATION_6GHZ_OP_INFO); + he_oper.optional[0] = he_6ghz_oper.primary; @@ -118,6 +109,15 @@ Index: b/net/mac80211/spectmgmt.c + he_oper.optional[2] = he_6ghz_oper.ccfs0; + he_oper.optional[3] = he_6ghz_oper.ccfs1; + ++ eht_oper_info.control = (eht_oper.params & ++ IEEE80211_EHT_OPER_CHAN_WIDTH) | ++ new_chan_width; ++ eht_oper_info.ccfs0 = wide_bw_chansw_ie->new_center_freq_seg0; ++ eht_oper_info.ccfs1 = wide_bw_chansw_ie->new_center_freq_seg1; ++ eht_oper.optional[0] = eht_oper_info.control; ++ eht_oper.optional[1] = eht_oper_info.ccfs0; ++ eht_oper.optional[2] = eht_oper_info.ccfs1; ++ + new_chandef = csa_ie->chandef; + + if (!ieee80211_chandef_he_6ghz_oper(sdata, &he_oper, @@ -131,7 +131,7 @@ Index: b/net/mac80211/spectmgmt.c - ht_oper.operation_mode = cpu_to_le16(new_seg1 << - IEEE80211_HT_OP_MODE_CCFS2_SHIFT); + ht_oper.operation_mode = cpu_to_le16(new_seg1 << -+ IEEE80211_HT_OP_MODE_CCFS2_SHIFT); ++ IEEE80211_HT_OP_MODE_CCFS2_SHIFT); - /* default, for the case of IEEE80211_VHT_CHANWIDTH_USE_HT, - * to the previously parsed chandef @@ -145,8 +145,8 @@ Index: b/net/mac80211/spectmgmt.c - &new_vht_chandef)) - new_vht_chandef.chan = NULL; + /* default, for the case of IEEE80211_VHT_CHANWIDTH_USE_HT, -+ * to the previously parsed chandef -+ */ ++ * to the previously parsed chandef ++ */ + new_chandef = csa_ie->chandef; + + /* ignore if parsing fails */ @@ -157,17 +157,17 @@ Index: b/net/mac80211/spectmgmt.c + new_chandef.chan = NULL; + } - if (sta_flags & IEEE80211_STA_DISABLE_80P80MHZ && + if (conn_flags & IEEE80211_CONN_DISABLE_80P80MHZ && - new_vht_chandef.width == NL80211_CHAN_WIDTH_80P80) - ieee80211_chandef_downgrade(&new_vht_chandef); + new_chandef.width == NL80211_CHAN_WIDTH_80P80) + ieee80211_chandef_downgrade(&new_chandef); - if (sta_flags & IEEE80211_STA_DISABLE_160MHZ && + if (conn_flags & IEEE80211_CONN_DISABLE_160MHZ && - new_vht_chandef.width == NL80211_CHAN_WIDTH_160) - ieee80211_chandef_downgrade(&new_vht_chandef); + new_chandef.width == NL80211_CHAN_WIDTH_160) + ieee80211_chandef_downgrade(&new_chandef); -+ if (sta_flags & IEEE80211_STA_DISABLE_320MHZ && ++ if (conn_flags & IEEE80211_CONN_DISABLE_320MHZ && + new_chandef.width == NL80211_CHAN_WIDTH_320) + ieee80211_chandef_downgrade(&new_chandef); } @@ -188,11 +188,9 @@ Index: b/net/mac80211/spectmgmt.c } if (elems->max_channel_switch_time) -Index: b/net/mac80211/util.c -=================================================================== ---- a/net/mac80211/util.c 2022-05-23 10:53:51.287421979 +0530 -+++ b/net/mac80211/util.c 2022-05-23 10:53:51.287421979 +0530 -@@ -3114,18 +3114,17 @@ void ieee80211_ie_build_wide_bw_cs(u8 *p +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -3185,18 +3185,17 @@ void ieee80211_ie_build_wide_bw_cs(u8 *p /* New channel width */ switch (chandef->width) { case NL80211_CHAN_WIDTH_80: @@ -216,7 +214,31 @@ Index: b/net/mac80211/util.c default: *pos++ = IEEE80211_VHT_CHANWIDTH_USE_HT; } -@@ -4258,7 +4257,8 @@ int ieee80211_send_action_csa(struct iee +@@ -4196,6 +4195,7 @@ ieee80211_conn_flags_t ieee80211_chandef + case NL80211_CHAN_WIDTH_40: + c->width = NL80211_CHAN_WIDTH_20; + c->center_freq1 = c->chan->center_freq; ++ c->center_freq2 = 0; + ret = IEEE80211_CONN_DISABLE_40MHZ | + IEEE80211_CONN_DISABLE_VHT; + break; +@@ -4205,6 +4205,7 @@ ieee80211_conn_flags_t ieee80211_chandef + tmp /= 2; + /* freq_P40 */ + c->center_freq1 = c->center_freq1 - 20 + 40 * tmp; ++ c->center_freq2 = 0; + c->width = NL80211_CHAN_WIDTH_40; + ret = IEEE80211_CONN_DISABLE_VHT; + break; +@@ -4220,6 +4221,7 @@ ieee80211_conn_flags_t ieee80211_chandef + /* n_P80 */ + tmp /= 4; + c->center_freq1 = c->center_freq1 - 40 + 80 * tmp; ++ c->center_freq2 = 0; + c->width = NL80211_CHAN_WIDTH_80; + ret = IEEE80211_CONN_DISABLE_80P80MHZ | + IEEE80211_CONN_DISABLE_160MHZ; +@@ -4363,7 +4365,8 @@ int ieee80211_send_action_csa(struct iee if (csa_settings->chandef.width == NL80211_CHAN_WIDTH_80 || csa_settings->chandef.width == NL80211_CHAN_WIDTH_80P80 || @@ -226,11 +248,9 @@ Index: b/net/mac80211/util.c skb_put(skb, 5); ieee80211_ie_build_wide_bw_cs(pos, &csa_settings->chandef); } -Index: b/net/wireless/util.c -=================================================================== ---- a/net/wireless/util.c 2022-05-23 10:53:51.287421979 +0530 -+++ b/net/wireless/util.c 2022-05-23 10:53:51.287421979 +0530 -@@ -2317,7 +2317,7 @@ void cfg80211_send_layer2_update(struct +--- a/net/wireless/util.c ++++ b/net/wireless/util.c +@@ -2346,7 +2346,7 @@ void cfg80211_send_layer2_update(struct EXPORT_SYMBOL(cfg80211_send_layer2_update); int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap, @@ -239,7 +259,7 @@ Index: b/net/wireless/util.c int mcs, bool ext_nss_bw_capable, unsigned int max_vht_nss) { -@@ -2416,6 +2416,8 @@ int ieee80211_get_vht_max_nss(struct iee +@@ -2445,6 +2445,8 @@ int ieee80211_get_vht_max_nss(struct iee ext_nss_bw == 2) return (3 * max_vht_nss) / 4; break; @@ -248,31 +268,3 @@ Index: b/net/wireless/util.c } /* not covered or invalid combination received */ -diff --git a/net/mac80211/util.c b/net/mac80211/util.c -index 191a8d69cdc3..d3b2e0a0d3c8 100644 ---- a/net/mac80211/util.c -+++ b/net/mac80211/util.c -@@ -4173,6 +4173,7 @@ u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c) - case NL80211_CHAN_WIDTH_40: - c->width = NL80211_CHAN_WIDTH_20; - c->center_freq1 = c->chan->center_freq; -+ c->center_freq2 = 0; - ret = IEEE80211_STA_DISABLE_40MHZ | - IEEE80211_STA_DISABLE_VHT; - break; -@@ -4182,6 +4183,7 @@ u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c) - tmp /= 2; - /* freq_P40 */ - c->center_freq1 = c->center_freq1 - 20 + 40 * tmp; -+ c->center_freq2 = 0; - c->width = NL80211_CHAN_WIDTH_40; - ret = IEEE80211_STA_DISABLE_VHT; - break; -@@ -4197,6 +4199,7 @@ u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c) - /* n_P80 */ - tmp /= 4; - c->center_freq1 = c->center_freq1 - 40 + 80 * tmp; -+ c->center_freq2 = 0; - c->width = NL80211_CHAN_WIDTH_80; - ret = IEEE80211_STA_DISABLE_80P80MHZ | - IEEE80211_STA_DISABLE_160MHZ; diff --git a/feeds/ipq95xx/mac80211/patches/qca/624-0002-ath12k-build-6-GHZ-regd-based-on-vdev-type-and-6-GHZ-power.patch b/feeds/ipq95xx/mac80211/patches/qca/624-0002-ath12k-build-6-GHZ-regd-based-on-vdev-type-and-6-GHZ-power.patch index 5eafb1aea..30a87360a 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/624-0002-ath12k-build-6-GHZ-regd-based-on-vdev-type-and-6-GHZ-power.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/624-0002-ath12k-build-6-GHZ-regd-based-on-vdev-type-and-6-GHZ-power.patch @@ -16,11 +16,9 @@ Signed-off-by: Aishwarya R drivers/net/wireless/ath/ath12k/wmi.h | 1 + 4 files changed, 65 insertions(+), 27 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index 8692260..1b3de60 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -530,6 +530,17 @@ struct ath12k *ath12k_mac_get_ar_by_vdev_id(struct ath12k_base *ab, u32 vdev_id) +@@ -634,6 +634,17 @@ struct ath12k *ath12k_mac_get_ar_by_vdev return NULL; } @@ -38,11 +36,9 @@ index 8692260..1b3de60 100644 struct ath12k *ath12k_mac_get_ar_by_pdev_id(struct ath12k_base *ab, u32 pdev_id) { int i; -diff --git a/drivers/net/wireless/ath/ath12k/mac.h b/drivers/net/wireless/ath/ath12k/mac.h -index 7339844..5a8e913 100644 --- a/drivers/net/wireless/ath/ath12k/mac.h +++ b/drivers/net/wireless/ath/ath12k/mac.h -@@ -141,6 +141,7 @@ struct ath12k_vif *ath12k_mac_get_arvif_by_vdev_id(struct ath12k_base *ab, +@@ -150,6 +150,7 @@ struct ath12k_vif *ath12k_mac_get_arvif_ u32 vdev_id); struct ath12k *ath12k_mac_get_ar_by_vdev_id(struct ath12k_base *ab, u32 vdev_id); struct ath12k *ath12k_mac_get_ar_by_pdev_id(struct ath12k_base *ab, u32 pdev_id); @@ -50,11 +46,9 @@ index 7339844..5a8e913 100644 void ath12k_mac_drain_tx(struct ath12k *ar); void ath12k_mac_peer_cleanup_all(struct ath12k *ar); -diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c -index fc9a04c..7b701cd 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -6044,26 +6044,16 @@ static bool ath12k_reg_is_world_alpha(char *alpha) +@@ -6619,26 +6619,16 @@ static bool ath12k_reg_is_world_alpha(ch return alpha[0] == '0' && alpha[1] == '0'; } @@ -87,7 +81,7 @@ index fc9a04c..7b701cd 100644 if (reg_info->status_code != REG_SET_CC_STATUS_PASS) { /* In case of failure to set the requested ctry, -@@ -6071,7 +6061,7 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk +@@ -6646,7 +6636,7 @@ static int ath12k_reg_chan_list_event(st * and return from here. */ ath12k_warn(ab, "Failed to set the requested Country regulatory setting\n"); @@ -96,16 +90,16 @@ index fc9a04c..7b701cd 100644 } pdev_idx = reg_info->phy_id; -@@ -6083,7 +6073,7 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk +@@ -6658,7 +6648,7 @@ static int ath12k_reg_chan_list_event(st */ - if (ab->hw_params.single_pdev_only && - pdev_idx < ab->hw_params.num_rxmda_per_pdev) + if (ab->hw_params->single_pdev_only && + pdev_idx < ab->hw_params->num_rxmda_per_pdev) - goto mem_free; + goto retfail; else goto fallback; } -@@ -6094,7 +6084,7 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk +@@ -6669,7 +6659,7 @@ static int ath12k_reg_chan_list_event(st if (ab->default_regd[pdev_idx] && !ab->new_regd[pdev_idx] && !memcmp((char *)ab->default_regd[pdev_idx]->alpha2, (char *)reg_info->alpha2, 2)) @@ -114,7 +108,7 @@ index fc9a04c..7b701cd 100644 /* Intersect new rules with default regd if a new country setting was * requested, i.e a default regd was already set during initialization -@@ -6106,8 +6096,14 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk +@@ -6681,8 +6671,14 @@ static int ath12k_reg_chan_list_event(st !ath12k_reg_is_world_alpha((char *)reg_info->alpha2)) intersect = true; @@ -131,7 +125,7 @@ index fc9a04c..7b701cd 100644 if (!regd) { ath12k_warn(ab, "failed to build regd from reg_info\n"); goto fallback; -@@ -6139,7 +6135,7 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk +@@ -6714,7 +6710,7 @@ static int ath12k_reg_chan_list_event(st ab->dfs_region = reg_info->dfs_region; spin_unlock(&ab->base_lock); @@ -140,7 +134,7 @@ index fc9a04c..7b701cd 100644 fallback: /* Fallback to older reg (by sending previous country setting -@@ -6151,17 +6147,46 @@ fallback: +@@ -6726,17 +6722,46 @@ fallback: */ /* TODO: This is rare, but still should also be handled */ WARN_ON(1); @@ -192,11 +186,9 @@ index fc9a04c..7b701cd 100644 } kfree(reg_info); } -diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h -index 2ab7add..53e162d 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -4620,6 +4620,7 @@ struct ath12k_targ_cap { +@@ -4845,6 +4845,7 @@ struct ath12k_targ_cap { }; enum wmi_vdev_type { @@ -204,6 +196,3 @@ index 2ab7add..53e162d 100644 WMI_VDEV_TYPE_AP = 1, WMI_VDEV_TYPE_STA = 2, WMI_VDEV_TYPE_IBSS = 3, --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/624-0003-ath12k-get-6-GHZ-power-type-from-HE-operation-element.patch b/feeds/ipq95xx/mac80211/patches/qca/624-0003-ath12k-get-6-GHZ-power-type-from-HE-operation-element.patch index 8e55c3504..254d094f1 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/624-0003-ath12k-get-6-GHZ-power-type-from-HE-operation-element.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/624-0003-ath12k-get-6-GHZ-power-type-from-HE-operation-element.patch @@ -14,11 +14,9 @@ Signed-off-by: Aishwarya R drivers/net/wireless/ath/ath12k/mac.c | 11 +++++++++++ 1 file changed, 11 insertions(+) -diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index 1b3de60..506f437 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -6174,6 +6174,7 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, +@@ -7360,6 +7360,7 @@ ath12k_mac_op_assign_vif_chanctx(struct struct ath12k_vif *arvif = (void *)vif->drv_priv; int ret; struct peer_create_params param; @@ -26,7 +24,7 @@ index 1b3de60..506f437 100644 mutex_lock(&ar->conf_mutex); -@@ -6181,6 +6182,16 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, +@@ -7367,6 +7368,16 @@ ath12k_mac_op_assign_vif_chanctx(struct "mac chanctx assign ptr %pK vdev_id %i\n", ctx, arvif->vdev_id); @@ -40,9 +38,6 @@ index 1b3de60..506f437 100644 + power_type = IEEE80211_REG_LPI_AP; + } + - /* for QCA6390 bss peer must be created before vdev_start */ - if (ab->hw_params.vdev_start_delay && + /* for some targets bss peer must be created before vdev_start */ + if (ab->hw_params->vdev_start_delay && arvif->vdev_type != WMI_VDEV_TYPE_AP && --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/624-0006-ath12k-save-max-tx-power-in-vdev-start-response-even.patch b/feeds/ipq95xx/mac80211/patches/qca/624-0006-ath12k-save-max-tx-power-in-vdev-start-response-even.patch index d7723510d..3e386221e 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/624-0006-ath12k-save-max-tx-power-in-vdev-start-response-even.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/624-0006-ath12k-save-max-tx-power-in-vdev-start-response-even.patch @@ -15,23 +15,19 @@ Signed-off-by: Aishwarya R drivers/net/wireless/ath/ath12k/wmi.h | 1 + 3 files changed, 4 insertions(+) -diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h -index 3602ecd..55c80dd 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h -@@ -679,6 +679,7 @@ struct ath12k { - #endif - bool dfs_block_radar_events; - struct ath12k_thermal thermal; -+ s8 max_allowed_tx_power; - bool monitor_conf_enabled; - bool monitor_vdev_created; +@@ -662,6 +662,7 @@ struct ath12k { bool monitor_started; -diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c -index 7b701cd..69f0614 100644 + int monitor_vdev_id; + u8 twt_enabled; ++ s8 max_allowed_tx_power; + }; + + struct ath12k_band_cap { --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -4293,6 +4293,7 @@ static int ath12k_pull_vdev_start_resp_tlv(struct ath12k_base *ab, struct sk_buf +@@ -4892,6 +4892,7 @@ static int ath12k_pull_vdev_start_resp_t vdev_rsp->mac_id = ev->mac_id; vdev_rsp->cfgd_tx_streams = ev->cfgd_tx_streams; vdev_rsp->cfgd_rx_streams = ev->cfgd_rx_streams; @@ -39,7 +35,7 @@ index 7b701cd..69f0614 100644 kfree(tb); return 0; -@@ -6343,6 +6344,7 @@ static void ath12k_vdev_start_resp_event(struct ath12k_base *ab, struct sk_buff +@@ -6918,6 +6919,7 @@ static void ath12k_vdev_start_resp_event } ar->last_wmi_vdev_start_status = 0; @@ -47,11 +43,9 @@ index 7b701cd..69f0614 100644 status = vdev_start_resp.status; -diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h -index 53e162d..1ed4cea 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -4010,6 +4010,7 @@ struct wmi_vdev_start_resp_event { +@@ -4222,6 +4222,7 @@ struct wmi_vdev_start_resp_event { }; u32 cfgd_tx_streams; u32 cfgd_rx_streams; @@ -59,6 +53,3 @@ index 53e162d..1ed4cea 100644 } __packed; /* VDEV start response status codes */ --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/624-0007-ath12k-fill-parameters-for-vdev_set_tpc_power-wmi-co.patch b/feeds/ipq95xx/mac80211/patches/qca/624-0007-ath12k-fill-parameters-for-vdev_set_tpc_power-wmi-co.patch index b12505f29..834a355ae 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/624-0007-ath12k-fill-parameters-for-vdev_set_tpc_power-wmi-co.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/624-0007-ath12k-fill-parameters-for-vdev_set_tpc_power-wmi-co.patch @@ -14,9 +14,9 @@ Signed-off-by: Aishwarya R Index: b/drivers/net/wireless/ath/ath12k/mac.c =================================================================== ---- a/drivers/net/wireless/ath/ath12k/mac.c 2022-07-08 23:43:00.405976521 +0530 -+++ b/drivers/net/wireless/ath/ath12k/mac.c 2022-07-08 23:43:46.301481104 +0530 -@@ -7353,6 +7353,283 @@ static u8 ath12k_mac_get_num_pwr_levels( +--- a/drivers/net/wireless/ath/ath12k/mac.c 2023-03-09 10:09:07.547033301 +0530 ++++ b/drivers/net/wireless/ath/ath12k/mac.c 2023-03-09 10:10:33.614370979 +0530 +@@ -7353,6 +7353,280 @@ static u8 ath12k_mac_get_num_pwr_levels( return num_pwr_levels; } @@ -247,10 +247,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c + &temp_chan, + &ctx->def, + &tx_power); -+ max_tx_power[pwr_lvl_idx] = -+ min_t(s8, -+ tx_power, -+ reg_tpc_info->tpe[pwr_lvl_idx]); ++ max_tx_power[pwr_lvl_idx] = tx_power; + } + } + @@ -266,7 +263,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c + ath12k_dbg(ab, ATH12K_DBG_MAC, + "eirp power : %d firmware report power : %d\n", + eirp_power, ar->max_allowed_tx_power); -+ if ((ar->max_allowed_tx_power) && (ab->hw_params.idle_ps)) ++ if ((ar->max_allowed_tx_power) && (ab->hw_params->idle_ps)) + eirp_power = min_t(s8, + eirp_power, + ar->max_allowed_tx_power); @@ -279,7 +276,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c + * firmware updated ap tx power + * and max power derived from above mentioned parameters. + */ -+ if ((ar->max_allowed_tx_power) && (ab->hw_params.idle_ps)) ++ if ((ar->max_allowed_tx_power) && (ab->hw_params->idle_ps)) + max_tx_power[pwr_lvl_idx] = + min_t(s8, + max_tx_power[pwr_lvl_idx], @@ -302,8 +299,8 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c struct ieee80211_chanctx_conf *ctx) Index: b/drivers/net/wireless/ath/ath12k/mac.h =================================================================== ---- a/drivers/net/wireless/ath/ath12k/mac.h 2022-07-08 23:43:00.405976521 +0530 -+++ b/drivers/net/wireless/ath/ath12k/mac.h 2022-07-08 23:43:00.401976563 +0530 +--- a/drivers/net/wireless/ath/ath12k/mac.h 2023-03-09 10:09:07.547033301 +0530 ++++ b/drivers/net/wireless/ath/ath12k/mac.h 2023-03-09 10:09:07.543033331 +0530 @@ -149,6 +149,9 @@ struct ath12k *ath12k_mac_get_ar_by_vdev struct ath12k *ath12k_mac_get_ar_by_pdev_id(struct ath12k_base *ab, u32 pdev_id); enum wmi_vdev_type ath12k_mac_get_ar_vdev_type(struct ath12k *ar); diff --git a/feeds/ipq95xx/mac80211/patches/qca/624-0013-ath12k-update-the-eirp-power-based-on-ieee80211_get_.patch b/feeds/ipq95xx/mac80211/patches/qca/624-0013-ath12k-update-the-eirp-power-based-on-ieee80211_get_.patch index 293d9a9d1..d8384b881 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/624-0013-ath12k-update-the-eirp-power-based-on-ieee80211_get_.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/624-0013-ath12k-update-the-eirp-power-based-on-ieee80211_get_.patch @@ -14,11 +14,11 @@ Signed-off-by: Aishwarya R drivers/net/wireless/ath/ath12k/mac.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 53 insertions(+), 14 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index 5c1b782..7c97f24 100644 ---- a/drivers/net/wireless/ath/ath12k/mac.c -+++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -6316,7 +6316,8 @@ static void ath12k_mac_get_psd_channel(struct ath12k *ar, +Index: b/drivers/net/wireless/ath/ath12k/mac.c +=================================================================== +--- a/drivers/net/wireless/ath/ath12k/mac.c 2023-03-09 10:11:06.870115094 +0530 ++++ b/drivers/net/wireless/ath/ath12k/mac.c 2023-03-09 10:11:30.765931238 +0530 +@@ -7423,7 +7423,8 @@ static void ath12k_mac_get_psd_channel(s u16 *center_freq, u8 i, struct ieee80211_channel **temp_chan, @@ -28,7 +28,7 @@ index 5c1b782..7c97f24 100644 { /* It is to get the the center frequency for each 20MHz. * For example, if the chan is 160MHz and center frequency is 6025, -@@ -6330,7 +6331,9 @@ static void ath12k_mac_get_psd_channel(struct ath12k *ar, +@@ -7437,7 +7438,9 @@ static void ath12k_mac_get_psd_channel(s * struct ieee80211_channel of it and get the max_reg_power. */ *center_freq = *start_freq + i * step_freq; @@ -39,7 +39,7 @@ index 5c1b782..7c97f24 100644 *tx_power = (*temp_chan)->max_reg_power; } -@@ -6340,9 +6343,10 @@ static void ath12k_mac_get_eirp_power(struct ath12k *ar, +@@ -7447,9 +7450,10 @@ static void ath12k_mac_get_eirp_power(st u8 i, struct ieee80211_channel **temp_chan, struct cfg80211_chan_def *def, @@ -52,7 +52,7 @@ index 5c1b782..7c97f24 100644 * 160MHz&80P80 bandwidth, and then plus 10 to the center frequency, * it is the center frequency of a channel number. * For example, when configured channel number is 1. -@@ -6356,8 +6360,13 @@ static void ath12k_mac_get_eirp_power(struct ath12k *ar, +@@ -7463,8 +7467,13 @@ static void ath12k_mac_get_eirp_power(st * struct ieee80211_channel of it and get the max_reg_power. */ *center_freq = ath12k_mac_get_seg_freq(def, *start_freq, i); @@ -68,7 +68,7 @@ index 5c1b782..7c97f24 100644 *tx_power = (*temp_chan)->max_reg_power; } -@@ -6375,6 +6384,26 @@ void ath12k_mac_fill_reg_tpc_info(struct ath12k *ar, +@@ -7482,6 +7491,26 @@ void ath12k_mac_fill_reg_tpc_info(struct s8 max_tx_power[IEEE80211_MAX_NUM_PWR_LEVEL], psd_power, tx_power = 0, eirp_power = 0; u16 oper_freq = 0, start_freq = 0, center_freq = 0; @@ -95,7 +95,7 @@ index 5c1b782..7c97f24 100644 chan = ctx->def.chan; oper_freq = ctx->def.chan->center_freq; -@@ -6401,7 +6430,8 @@ void ath12k_mac_fill_reg_tpc_info(struct ath12k *ar, +@@ -7509,7 +7538,8 @@ void ath12k_mac_fill_reg_tpc_info(struct ¢er_freq, pwr_lvl_idx, &temp_chan, @@ -105,7 +105,7 @@ index 5c1b782..7c97f24 100644 psd_power = temp_chan->psd; eirp_power = tx_power; max_tx_power[pwr_lvl_idx] = -@@ -6416,7 +6446,8 @@ void ath12k_mac_fill_reg_tpc_info(struct ath12k *ar, +@@ -7524,7 +7554,8 @@ void ath12k_mac_fill_reg_tpc_info(struct pwr_lvl_idx, &temp_chan, &ctx->def, @@ -115,7 +115,7 @@ index 5c1b782..7c97f24 100644 psd_power = temp_chan->psd; /* convert psd power to EIRP power based * on channel width -@@ -6439,7 +6470,8 @@ void ath12k_mac_fill_reg_tpc_info(struct ath12k *ar, +@@ -7547,7 +7578,8 @@ void ath12k_mac_fill_reg_tpc_info(struct ¢er_freq, pwr_lvl_idx, &temp_chan, @@ -125,7 +125,7 @@ index 5c1b782..7c97f24 100644 eirp_power = tx_power; max_tx_power[pwr_lvl_idx] = reg_tpc_info->tpe[pwr_lvl_idx]; -@@ -6451,7 +6483,8 @@ void ath12k_mac_fill_reg_tpc_info(struct ath12k *ar, +@@ -7559,7 +7591,8 @@ void ath12k_mac_fill_reg_tpc_info(struct pwr_lvl_idx, &temp_chan, &ctx->def, @@ -135,7 +135,7 @@ index 5c1b782..7c97f24 100644 max_tx_power[pwr_lvl_idx] = min_t(s8, tx_power, -@@ -6468,7 +6501,8 @@ void ath12k_mac_fill_reg_tpc_info(struct ath12k *ar, +@@ -7576,7 +7609,8 @@ void ath12k_mac_fill_reg_tpc_info(struct ¢er_freq, pwr_lvl_idx, &temp_chan, @@ -145,17 +145,17 @@ index 5c1b782..7c97f24 100644 psd_power = temp_chan->psd; eirp_power = tx_power; max_tx_power[pwr_lvl_idx] = psd_power; -@@ -6479,7 +6513,8 @@ void ath12k_mac_fill_reg_tpc_info(struct ath12k *ar, +@@ -7587,7 +7621,8 @@ void ath12k_mac_fill_reg_tpc_info(struct pwr_lvl_idx, &temp_chan, &ctx->def, - &tx_power); + &tx_power, + reg_6g_power_mode); - max_tx_power[pwr_lvl_idx] = - min_t(s8, - tx_power, -@@ -6527,7 +6562,7 @@ void ath12k_mac_fill_reg_tpc_info(struct ath12k *ar, + max_tx_power[pwr_lvl_idx] = tx_power; + } + } +@@ -7632,7 +7667,7 @@ void ath12k_mac_fill_reg_tpc_info(struct reg_tpc_info->is_psd_power = is_psd_power; reg_tpc_info->eirp_power = eirp_power; reg_tpc_info->power_type_6g = @@ -164,7 +164,7 @@ index 5c1b782..7c97f24 100644 } static void ath12k_mac_parse_tx_pwr_env(struct ath12k *ar, -@@ -6543,8 +6578,12 @@ static void ath12k_mac_parse_tx_pwr_env(struct ath12k *ar, +@@ -7648,8 +7683,12 @@ static void ath12k_mac_parse_tx_pwr_env( u8 pwr_count, pwr_interpret, pwr_category; u8 psd_index = 0, non_psd_index = 0, local_tpe_count = 0, reg_tpe_count = 0; bool use_local_tpe, non_psd_set = false, psd_set = false; @@ -178,6 +178,3 @@ index 5c1b782..7c97f24 100644 for (i = 0; i < bss_conf->tx_pwr_env_num; i++) { single_tpe = &bss_conf->tx_pwr_env[i]; --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/624-0014-ath12k-porting-6-GHZ-regulatory-changes.patch b/feeds/ipq95xx/mac80211/patches/qca/624-0014-ath12k-porting-6-GHZ-regulatory-changes.patch index 090627925..687fbb17a 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/624-0014-ath12k-porting-6-GHZ-regulatory-changes.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/624-0014-ath12k-porting-6-GHZ-regulatory-changes.patch @@ -14,11 +14,9 @@ Signed-off-by: Aishwarya R drivers/net/wireless/ath/ath12k/wmi.h | 5 +++++ 4 files changed, 28 insertions(+), 7 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h -index c36ee45..ac3ad74 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h -@@ -781,6 +781,12 @@ struct ath12k_soc_dp_stats { +@@ -806,6 +806,12 @@ struct ath12k_soc_dp_stats { struct ath12k_dp_ring_bp_stats bp_stats; }; @@ -31,21 +29,19 @@ index c36ee45..ac3ad74 100644 /* Master structure to hold the hw data which may be used in core module */ struct ath12k_base { enum ath12k_hw_rev hw_rev; -@@ -851,6 +857,9 @@ struct ath12k_base { +@@ -877,6 +883,9 @@ struct ath12k_base { /* Current DFS Regulatory */ enum ath12k_dfs_region dfs_region; + struct ath12k_reg_rule reg_rule_2g; -+ struct ath12k_reg_rule reg_rule_5g; -+ struct ath12k_reg_rule reg_rule_6g; ++ struct ath12k_reg_rule reg_rule_5g; ++ struct ath12k_reg_rule reg_rule_6g; #ifdef CPTCFG_ATH12K_DEBUGFS struct dentry *debugfs_soc; #endif -diff --git a/drivers/net/wireless/ath/ath12k/reg.c b/drivers/net/wireless/ath/ath12k/reg.c -index ffd14eb..99a4d82 100644 --- a/drivers/net/wireless/ath/ath12k/reg.c +++ b/drivers/net/wireless/ath/ath12k/reg.c -@@ -43,6 +43,17 @@ ath12k_ieee80211_ap_pwr_type_convert(enum ieee80211_ap_reg_power power_type) +@@ -43,6 +43,17 @@ ath12k_ieee80211_ap_pwr_type_convert(enu } } @@ -63,7 +59,7 @@ index ffd14eb..99a4d82 100644 static struct cur_reg_rule *ath12k_get_active_6g_reg_rule(struct cur_regulatory_info *reg_info, u32 *max_bw_6g, int *max_elements, -@@ -781,7 +792,7 @@ ath12k_reg_build_regd(struct ath12k_base *ab, +@@ -781,7 +792,7 @@ ath12k_reg_build_regd(struct ath12k_base reg_rule->start_freq, reg_rule->end_freq, max_bw, reg_rule->ant_gain, reg_rule->reg_power, @@ -72,11 +68,9 @@ index ffd14eb..99a4d82 100644 /* Update dfs cac timeout if the dfs domain is ETSI and the * new rule covers weather radar band. -diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c -index 6389c6c..360d44d 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -6238,8 +6238,7 @@ retfail: +@@ -6807,8 +6807,7 @@ retfail: } @@ -86,7 +80,7 @@ index 6389c6c..360d44d 100644 { struct cur_regulatory_info *reg_info; int ret, i, j; -@@ -6248,10 +6247,7 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk +@@ -6817,10 +6816,7 @@ static int ath12k_reg_chan_list_event(st if (!reg_info) return -ENOMEM; @@ -98,11 +92,9 @@ index 6389c6c..360d44d 100644 if (ret) { ath12k_warn(ab, "failed to extract regulatory info from received event\n"); -diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h -index c840228..b7497e8 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -4208,6 +4208,11 @@ struct wmi_regulatory_rule_struct { +@@ -4421,6 +4421,11 @@ struct wmi_regulatory_rule_struct { #define WMI_REG_CLIENT_MAX 4 @@ -114,6 +106,3 @@ index c840228..b7497e8 100644 struct wmi_reg_chan_list_cc_ext_event { u32 status_code; u32 phy_id; --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/624-0015-ath12k-fix-kernel-panic-during-mac.patch b/feeds/ipq95xx/mac80211/patches/qca/624-0015-ath12k-fix-kernel-panic-during-mac.patch index 5c9f64e89..cd84f7705 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/624-0015-ath12k-fix-kernel-panic-during-mac.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/624-0015-ath12k-fix-kernel-panic-during-mac.patch @@ -11,11 +11,9 @@ Signed-off-by: Aishwarya R drivers/net/wireless/ath/ath12k/mac.c | 128 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 65 insertions(+), 63 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index 7290189..a017ce6 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -9034,73 +9034,75 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar, +@@ -9082,74 +9082,75 @@ static int ath12k_mac_setup_channels_rat } if (supported_bands & WMI_HOST_WLAN_5G_CAP) { @@ -50,9 +48,6 @@ index 7290189..a017ce6 100644 - band->n_bitrates = ath12k_a_rates_size; - band->bitrates = ath12k_a_rates; - ar->hw->wiphy->bands[NL80211_BAND_6GHZ] = band; -- ath12k_mac_update_ch_list(ar, band, -- reg_cap->low_5ghz_chan, -- reg_cap->high_5ghz_chan); + /* If 5g end and 6g start overlaps, decide band based on + * the difference between target limit and ATH12K_5G_MAX_CENTER. + */ @@ -69,10 +64,7 @@ index 7290189..a017ce6 100644 + + return -ENOMEM; + } - -- band->n_channels = band->chan_6g[0]->n_channels; -- band->channels = band->chan_6g[0]->channels; -- } ++ + band = &ar->mac.sbands[NL80211_BAND_5GHZ]; + band->band = NL80211_BAND_5GHZ; + band->n_channels = ARRAY_SIZE(ath12k_5ghz_channels); @@ -80,7 +72,18 @@ index 7290189..a017ce6 100644 + band->n_bitrates = ath12k_a_rates_size; + band->bitrates = ath12k_a_rates; + ar->hw->wiphy->bands[NL80211_BAND_5GHZ] = band; - ++ ++ if (ar->ab->hw_params->single_pdev_only) { ++ phy_id = ath12k_get_phy_id(ar, WMI_HOST_WLAN_5G_CAP); ++ } + ath12k_mac_update_ch_list(ar, band, +- reg_cap->low_5ghz_chan, +- reg_cap->high_5ghz_chan); +- +- band->n_channels = band->chan_6g[0]->n_channels; +- band->channels = band->chan_6g[0]->channels; +- } +- - if ((reg_cap->low_5ghz_chan >= ATH12K_MIN_5G_FREQ) && - ((reg_cap->high_5ghz_chan < ATH12K_MAX_5G_FREQ) || - ((reg_cap->high_5ghz_chan - ATH12K_5G_MAX_CENTER) < (ATH12K_HALF_20MHZ_BW * 2)))) { @@ -92,13 +95,26 @@ index 7290189..a017ce6 100644 - kfree(ar->mac.sbands[NL80211_BAND_6GHZ].channels); - return -ENOMEM; - } -+ if (ar->ab->hw_params.single_pdev_only) { -+ phy_id = ath12k_get_phy_id(ar, WMI_HOST_WLAN_5G_CAP); -+ } -+ ath12k_mac_update_ch_list(ar, band, +- +- band = &ar->mac.sbands[NL80211_BAND_5GHZ]; +- band->band = NL80211_BAND_5GHZ; +- band->n_channels = ARRAY_SIZE(ath12k_5ghz_channels); +- band->channels = channels; +- band->n_bitrates = ath12k_a_rates_size; +- band->bitrates = ath12k_a_rates; +- ar->hw->wiphy->bands[NL80211_BAND_5GHZ] = band; +- +- if (ar->ab->hw_params->single_pdev_only) { +- phy_id = ath12k_get_phy_id(ar, WMI_HOST_WLAN_5G_CAP); +- reg_cap = &ar->ab->hal_reg_cap[phy_id]; +- } +- +- ath12k_mac_update_ch_list(ar, band, +- reg_cap->low_5ghz_chan, +- reg_cap->high_5ghz_chan); + reg_cap->low_5ghz_chan, + reg_cap->high_5ghz_chan); -+ + + } else if (reg_cap->low_5ghz_chan >= ATH12K_MIN_6G_FREQ && + reg_cap->high_5ghz_chan <= ATH12K_MAX_6G_FREQ) { + band = &ar->mac.sbands[NL80211_BAND_6GHZ]; @@ -113,29 +129,14 @@ index 7290189..a017ce6 100644 + kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels); + break; + } - -- band = &ar->mac.sbands[NL80211_BAND_5GHZ]; -- band->band = NL80211_BAND_5GHZ; -- band->n_channels = ARRAY_SIZE(ath12k_5ghz_channels); -- band->channels = channels; -- band->n_bitrates = ath12k_a_rates_size; -- band->bitrates = ath12k_a_rates; -- ar->hw->wiphy->bands[NL80211_BAND_5GHZ] = band; -- -- if (ar->ab->hw_params.single_pdev_only) { -- phy_id = ath12k_get_phy_id(ar, WMI_HOST_WLAN_5G_CAP); -- reg_cap = &ar->ab->hal_reg_cap[phy_id]; -- } ++ + chan_6g->channels = channels; + chan_6g->n_channels = ARRAY_SIZE(ath12k_6ghz_channels); + band->chan_6g[i] = chan_6g; + channels = NULL; + chan_6g = NULL; + } - -- ath12k_mac_update_ch_list(ar, band, -- reg_cap->low_5ghz_chan, -- reg_cap->high_5ghz_chan); ++ + if (i < NL80211_REG_NUM_POWER_MODES) { + for (i = i - 1; i >= 0; i--) { + chan_6g = band->chan_6g[i]; @@ -151,9 +152,6 @@ index 7290189..a017ce6 100644 + ath12k_mac_update_ch_list(ar, band, + reg_cap->low_5ghz_chan, + reg_cap->high_5ghz_chan); - /* For 6G sband, the strcut channels and int numchannels will * have the default value. During ieee80211_hw_register(), --- -2.17.1 - + * all sbands are parsed and at that time code can crash while diff --git a/feeds/ipq95xx/mac80211/patches/qca/624-0016-ath12k-Disable-6-GHz-Transmit-power-envelope-for-320.patch b/feeds/ipq95xx/mac80211/patches/qca/624-0016-ath12k-Disable-6-GHz-Transmit-power-envelope-for-320.patch index bb2d0bf5f..d69a5c359 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/624-0016-ath12k-Disable-6-GHz-Transmit-power-envelope-for-320.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/624-0016-ath12k-Disable-6-GHz-Transmit-power-envelope-for-320.patch @@ -13,40 +13,7 @@ Signed-off-by: Aishwarya R --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -3674,8 +3674,12 @@ static void ath12k_mac_op_bss_info_chang - ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev_id %i txpower %d\n", - arvif->vdev_id, info->txpower); - -+ /* TODO: Transmit Power Envelope specification for 320 is not -+ * available yet. Need to add TPE 320 support when spec is ready -+ */ - if (ar->supports_6ghz && info->chandef.chan && - info->chandef.chan->band == NL80211_BAND_6GHZ && -+ info->chandef.width != NL80211_CHAN_WIDTH_320 && - (arvif->vdev_type == WMI_VDEV_TYPE_STA || - arvif->vdev_type == WMI_VDEV_TYPE_AP) && - test_bit(WMI_TLV_SERVICE_EXT_TPC_REG_SUPPORT, -@@ -7004,14 +7008,18 @@ ath12k_mac_vdev_start_restart(struct ath - return ret; - } - -+ /* TODO: Transmit Power Envelope specification for 320 is not -+ * available yet. Need to add TPE 320 support when spec is ready -+ */ - if (ar->supports_6ghz && -+ chandef->width != NL80211_CHAN_WIDTH_320 && - chandef->chan->band == NL80211_BAND_6GHZ && - (arvif->vdev_type == WMI_VDEV_TYPE_STA || arvif->vdev_type == WMI_VDEV_TYPE_AP) && - test_bit(WMI_TLV_SERVICE_EXT_TPC_REG_SUPPORT, ar->ab->wmi_ab.svc_map)) { - ath12k_mac_fill_reg_tpc_info(ar, arvif->vif, &arvif->chanctx); - ath12k_wmi_send_vdev_set_tpc_power(ar, arvif->vdev_id, - &arvif->reg_tpc_info); -- } -+ } - - ar->num_started_vdevs++; - ath12k_dbg(ab, ATH12K_DBG_MAC, "vdev %pM started, vdev_id %d\n", -@@ -7142,6 +7150,7 @@ ath12k_mac_update_vif_chan(struct ath12k +@@ -7226,6 +7226,7 @@ ath12k_mac_update_vif_chan(struct ath12k int ret; int i; bool monitor_vif = false; @@ -54,7 +21,7 @@ Signed-off-by: Aishwarya R lockdep_assert_held(&ar->conf_mutex); -@@ -7166,10 +7175,18 @@ ath12k_mac_update_vif_chan(struct ath12k +@@ -7250,10 +7251,18 @@ ath12k_mac_update_vif_chan(struct ath12k if (WARN_ON(!arvif->is_started)) continue; @@ -73,7 +40,7 @@ Signed-off-by: Aishwarya R continue; } -@@ -7829,8 +7846,13 @@ ath12k_mac_op_assign_vif_chanctx(struct +@@ -7912,8 +7921,13 @@ ath12k_mac_op_assign_vif_chanctx(struct power_type = IEEE80211_REG_LPI_AP; arvif->chanctx = *ctx; @@ -87,4 +54,4 @@ Signed-off-by: Aishwarya R + } } - /* for QCA6390 bss peer must be created before vdev_start */ + /* for some targets bss peer must be created before vdev_start */ diff --git a/feeds/ipq95xx/mac80211/patches/qca/624-0017-ath12k-Enable-set-tpc-power-cmd-for-320.patch b/feeds/ipq95xx/mac80211/patches/qca/624-0017-ath12k-Enable-set-tpc-power-cmd-for-320.patch new file mode 100644 index 000000000..ea34e9a08 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/624-0017-ath12k-Enable-set-tpc-power-cmd-for-320.patch @@ -0,0 +1,61 @@ +From 70ab6ca18864d0511e2f6cea1d12be58ee926c81 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Wed, 12 Apr 2023 21:25:43 +0530 +Subject: [PATCH] ath12k: enable sending TPC power command for 320 MHz + +TPE spec is not yet defined for 320 MHz. However, for proper +Tx power related calculations, it is mandatory to send SET_TPC_POWER +command to firmware in 320 MHz as well. + +Add support to form and send the TPC power command for 320 MHz bandwidth +as well. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath12k/mac.c | 9 +++++++++++++++ + include/linux/ieee80211.h | 2 +- + 2 files changed, 10 insertions(+), 1 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -7433,6 +7433,9 @@ static u8 ath12k_mac_get_num_pwr_levels( + case NL80211_CHAN_WIDTH_160: + num_pwr_levels = 8; + break; ++ case NL80211_CHAN_WIDTH_320: ++ num_pwr_levels = 16; ++ break; + default: + return 1; + } +@@ -7451,6 +7454,9 @@ static u8 ath12k_mac_get_num_pwr_levels( + case NL80211_CHAN_WIDTH_160: + num_pwr_levels = 4; + break; ++ case NL80211_CHAN_WIDTH_320: ++ num_pwr_levels = 5; ++ break; + default: + return 1; + } +@@ -7473,6 +7479,9 @@ static u16 ath12k_mac_get_6g_start_frequ + * with center frequency 5955, its diff is 6025 - 5955 = 70. + */ + switch (chan_def->width) { ++ case NL80211_CHAN_WIDTH_320: ++ diff_seq = 150; ++ break; + case NL80211_CHAN_WIDTH_160: + diff_seq = 70; + break; +--- a/include/linux/ieee80211.h ++++ b/include/linux/ieee80211.h +@@ -2593,7 +2593,7 @@ struct ieee80211_he_6ghz_oper { + * In "Table 9-277—Meaning of Maximum Transmit Power Count subfield" + * of "IEEE Std 802.11ax™‐2021", the max power level is 8. + */ +-#define IEEE80211_MAX_NUM_PWR_LEVEL 8 ++#define IEEE80211_MAX_NUM_PWR_LEVEL 16 + + #define IEEE80211_TPE_MAX_POWER_COUNT 8 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/625-ath12k-Replace-HTT_DBG_OUT-with-scnprintf.patch b/feeds/ipq95xx/mac80211/patches/qca/625-ath12k-Replace-HTT_DBG_OUT-with-scnprintf.patch index f9e0e9ece..9ae24be09 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/625-ath12k-Replace-HTT_DBG_OUT-with-scnprintf.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/625-ath12k-Replace-HTT_DBG_OUT-with-scnprintf.patch @@ -19,10 +19,8 @@ Signed-off-by: Dinesh Karthikeyan drivers/net/wireless/ath/ath12k/dp.h | 7 + 3 files changed, 1083 insertions(+), 1015 deletions(-) -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c 2022-05-10 10:47:12.729567300 +0530 -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c 2022-05-10 10:49:01.776667887 +0530 +--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c @@ -11,14 +11,14 @@ #include "debug.h" #include "debugfs_htt_stats.h" @@ -41,7 +39,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb #define ARRAY_TO_STRING(out, arr, len) \ do { \ int index = 0; u8 i; \ -@@ -44,7 +44,7 @@ +@@ -44,7 +44,7 @@ static inline void htt_print_stats_strin tag_len = tag_len >> 2; @@ -50,7 +48,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb for (i = 0; i < tag_len; i++) { index += scnprintf(&data[index], -@@ -54,7 +54,7 @@ +@@ -54,7 +54,7 @@ static inline void htt_print_stats_strin break; } @@ -59,7 +57,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -71,107 +71,108 @@ +@@ -71,107 +71,108 @@ static inline void htt_print_tx_pdev_sta u8 *buf = stats_req->buf; u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -220,7 +218,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->tx_active_dur_us_high); if (len >= buf_len) -@@ -194,7 +195,7 @@ +@@ -194,7 +195,7 @@ htt_print_tx_pdev_stats_urrn_tlv_v(const char urrn_stats[HTT_MAX_STRING_LEN] = {0}; u16 num_elems = min_t(u16, (tag_len >> 2), HTT_TX_PDEV_MAX_URRN_STATS); @@ -229,7 +227,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb ARRAY_TO_STRING(urrn_stats, htt_stats_buf->urrn_stats, num_elems); len += HTT_DBG_OUT(buf + len, buf_len - len, "urrn_stats = %s\n", urrn_stats); -@@ -219,7 +220,7 @@ +@@ -219,7 +220,7 @@ htt_print_tx_pdev_stats_flush_tlv_v(cons char flush_errs[HTT_MAX_STRING_LEN] = {0}; u16 num_elems = min_t(u16, (tag_len >> 2), HTT_TX_PDEV_MAX_FLUSH_REASON_STATS); @@ -238,7 +236,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb ARRAY_TO_STRING(flush_errs, htt_stats_buf->flush_errs, num_elems); len += HTT_DBG_OUT(buf + len, buf_len - len, "flush_errs = %s\n", flush_errs); -@@ -244,7 +245,7 @@ +@@ -244,7 +245,7 @@ htt_print_tx_pdev_stats_sifs_tlv_v(const char sifs_status[HTT_MAX_STRING_LEN] = {0}; u16 num_elems = min_t(u16, (tag_len >> 2), HTT_TX_PDEV_MAX_SIFS_BURST_STATS); @@ -247,7 +245,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb ARRAY_TO_STRING(sifs_status, htt_stats_buf->sifs_status, num_elems); len += HTT_DBG_OUT(buf + len, buf_len - len, "sifs_status = %s\n", -@@ -270,7 +271,7 @@ +@@ -270,7 +271,7 @@ htt_print_tx_pdev_stats_phy_err_tlv_v(co char phy_errs[HTT_MAX_STRING_LEN] = {0}; u16 num_elems = min_t(u16, (tag_len >> 2), HTT_TX_PDEV_MAX_PHY_ERR_STATS); @@ -256,7 +254,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb ARRAY_TO_STRING(phy_errs, htt_stats_buf->phy_errs, num_elems); len += HTT_DBG_OUT(buf + len, buf_len - len, "phy_errs = %s\n", phy_errs); -@@ -295,8 +296,8 @@ +@@ -295,8 +296,8 @@ htt_print_tx_pdev_stats_sifs_hist_tlv_v( char sifs_hist_status[HTT_MAX_STRING_LEN] = {0}; u16 num_elems = min_t(u16, (tag_len >> 2), HTT_TX_PDEV_MAX_SIFS_BURST_HIST_STATS); @@ -267,7 +265,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb ARRAY_TO_STRING(sifs_hist_status, htt_stats_buf->sifs_hist_status, num_elems); len += HTT_DBG_OUT(buf + len, buf_len - len, "sifs_hist_status = %s\n", -@@ -319,22 +320,22 @@ +@@ -319,22 +320,22 @@ htt_print_tx_pdev_stats_tx_ppdu_stats_tl u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -297,7 +295,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->num_data_ppdus_ax_su_txbf); if (len >= buf_len) -@@ -358,9 +359,9 @@ +@@ -358,9 +359,9 @@ htt_print_tx_pdev_stats_tried_mpdu_cnt_h u32 num_elements = ((tag_len - sizeof(htt_stats_buf->hist_bin_size)) >> 2); u32 required_buffer_size = HTT_MAX_PRINT_CHAR_PER_ELEM * num_elements; @@ -310,7 +308,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->hist_bin_size); if (required_buffer_size < HTT_MAX_STRING_LEN) { -@@ -391,13 +392,13 @@ +@@ -391,13 +392,13 @@ static inline void htt_print_hw_stats_in u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; char hw_intr_name[HTT_STATS_MAX_HW_INTR_NAME_LEN + 1] = {0}; @@ -328,7 +326,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->count); if (len >= buf_len) -@@ -418,12 +419,12 @@ +@@ -418,12 +419,12 @@ htt_print_hw_stats_wd_timeout_tlv(const u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; char hw_module_name[HTT_STATS_MAX_HW_MODULE_NAME_LEN + 1] = {0}; @@ -344,7 +342,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->count); if (len >= buf_len) -@@ -441,29 +442,30 @@ +@@ -441,29 +442,30 @@ static inline void htt_print_hw_stats_pd u8 *buf = stats_req->buf; u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -388,7 +386,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->rx_timeout_reset); if (len >= buf_len) -@@ -481,35 +483,34 @@ +@@ -481,35 +483,34 @@ static inline void htt_print_msdu_flow_s u8 *buf = stats_req->buf; u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -442,7 +440,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->current_drop_th); if (len >= buf_len) -@@ -528,38 +529,39 @@ +@@ -528,38 +529,39 @@ static inline void htt_print_tx_tid_stat u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; char tid_name[MAX_HTT_TID_NAME + 1] = {0}; @@ -503,7 +501,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->block_module_id); if (len >= buf_len) -@@ -578,42 +580,43 @@ +@@ -578,42 +580,43 @@ static inline void htt_print_tx_tid_stat u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; char tid_name[MAX_HTT_TID_NAME + 1] = {0}; @@ -570,7 +568,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->sendn_frms_allowed); if (len >= buf_len) -@@ -632,21 +635,22 @@ +@@ -632,21 +635,22 @@ static inline void htt_print_rx_tid_stat u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; char tid_name[MAX_HTT_TID_NAME + 1] = {0}; @@ -603,7 +601,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->rxdesc_err_decrypt); if (len >= buf_len) -@@ -666,7 +670,7 @@ +@@ -666,7 +670,7 @@ static inline void htt_print_counter_tlv u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; char counter_name[HTT_MAX_STRING_LEN] = {0}; @@ -612,7 +610,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb ARRAY_TO_STRING(counter_name, htt_stats_buf->counter_name, -@@ -691,34 +695,34 @@ +@@ -691,34 +695,34 @@ static inline void htt_print_peer_stats_ u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -660,7 +658,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->inactive_time); if (len >= buf_len) -@@ -736,29 +740,32 @@ +@@ -736,29 +740,32 @@ static inline void htt_print_peer_detail u8 *buf = stats_req->buf; u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -712,7 +710,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->qpeer_flags); if (len >= buf_len) -@@ -963,12 +970,12 @@ +@@ -963,12 +970,12 @@ htt_print_tx_hwq_mu_mimo_sch_stats_tlv(c u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -729,7 +727,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->mu_mimo_ppdu_posted); if (len >= buf_len) -@@ -988,21 +995,21 @@ +@@ -988,21 +995,21 @@ htt_print_tx_hwq_mu_mimo_mpdu_stats_tlv( u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -760,7 +758,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->mu_mimo_ampdu_underrun_usr); if (len >= buf_len) -@@ -1021,12 +1028,13 @@ +@@ -1021,12 +1028,13 @@ htt_print_tx_hwq_mu_mimo_cmn_stats_tlv(c u8 *buf = stats_req->buf; u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -779,7 +777,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -1043,52 +1051,53 @@ +@@ -1043,52 +1051,53 @@ htt_print_tx_hwq_stats_cmn_tlv(const voi u8 *buf = stats_req->buf; u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -858,7 +856,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->txq_timeout); if (len >= buf_len) -@@ -1111,9 +1120,9 @@ +@@ -1111,9 +1120,9 @@ htt_print_tx_hwq_difs_latency_stats_tlv_ u16 data_len = min_t(u16, (tag_len >> 2), HTT_TX_HWQ_MAX_DIFS_LATENCY_BINS); char difs_latency_hist[HTT_MAX_STRING_LEN] = {0}; @@ -870,7 +868,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->hist_intvl); ARRAY_TO_STRING(difs_latency_hist, htt_stats_buf->difs_latency_hist, -@@ -1134,7 +1143,7 @@ +@@ -1134,7 +1143,7 @@ htt_print_tx_hwq_cmd_result_stats_tlv_v( u16 tag_len, struct debug_htt_stats_req *stats_req) { @@ -879,7 +877,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb u8 *buf = stats_req->buf; u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; -@@ -1143,10 +1152,8 @@ +@@ -1143,10 +1152,8 @@ htt_print_tx_hwq_cmd_result_stats_tlv_v( data_len = min_t(u16, (tag_len >> 2), HTT_TX_HWQ_MAX_CMD_RESULT_STATS); @@ -892,7 +890,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb len += HTT_DBG_OUT(buf + len, buf_len - len, "cmd_result = %s\n", cmd_result); -@@ -1172,7 +1179,7 @@ +@@ -1172,7 +1179,7 @@ htt_print_tx_hwq_cmd_stall_stats_tlv_v(c num_elems = min_t(u16, (tag_len >> 2), HTT_TX_HWQ_MAX_CMD_STALL_STATS); @@ -901,7 +899,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb ARRAY_TO_STRING(cmd_stall_status, htt_stats_buf->cmd_stall_status, num_elems); len += HTT_DBG_OUT(buf + len, buf_len - len, "cmd_stall_status = %s\n", -@@ -1200,8 +1207,8 @@ +@@ -1200,8 +1207,8 @@ htt_print_tx_hwq_fes_result_stats_tlv_v( num_elems = min_t(u16, (tag_len >> 2), HTT_TX_HWQ_MAX_FES_RESULT_STATS); @@ -912,7 +910,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb ARRAY_TO_STRING(fes_result, htt_stats_buf->fes_result, num_elems); len += HTT_DBG_OUT(buf + len, buf_len - len, "fes_result = %s\n", fes_result); -@@ -1228,9 +1235,9 @@ +@@ -1228,9 +1235,9 @@ htt_print_tx_hwq_tried_mpdu_cnt_hist_tlv sizeof(htt_stats_buf->hist_bin_size)) >> 2); u32 required_buffer_size = HTT_MAX_PRINT_CHAR_PER_ELEM * num_elements; @@ -925,7 +923,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->hist_bin_size); if (required_buffer_size < HTT_MAX_STRING_LEN) { -@@ -1266,8 +1273,8 @@ +@@ -1266,8 +1273,8 @@ htt_print_tx_hwq_txop_used_cnt_hist_tlv_ u32 num_elements = tag_len >> 2; u32 required_buffer_size = HTT_MAX_PRINT_CHAR_PER_ELEM * num_elements; @@ -936,7 +934,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (required_buffer_size < HTT_MAX_STRING_LEN) { ARRAY_TO_STRING(txop_used_cnt_hist, -@@ -1301,31 +1308,31 @@ +@@ -1301,31 +1308,31 @@ static inline void htt_print_tx_sounding const u32 *cbf_160 = htt_stats_buf->cbf_160; if (htt_stats_buf->tx_sounding_mode == HTT_TX_AC_SOUNDING_MODE) { @@ -977,7 +975,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb cbf_160[HTT_IMPLICIT_TXBF_STEER_STATS], cbf_160[HTT_EXPLICIT_TXBF_SU_SIFS_STEER_STATS], cbf_160[HTT_EXPLICIT_TXBF_SU_RBO_STEER_STATS], -@@ -1333,8 +1340,8 @@ +@@ -1333,8 +1340,8 @@ static inline void htt_print_tx_sounding cbf_160[HTT_EXPLICIT_TXBF_MU_RBO_STEER_STATS]); for (i = 0; i < HTT_TX_PDEV_STATS_NUM_AC_MUMIMO_USER_STATS; i++) { @@ -988,7 +986,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb i, htt_stats_buf->sounding[0], htt_stats_buf->sounding[1], -@@ -1342,31 +1349,31 @@ +@@ -1342,31 +1349,31 @@ static inline void htt_print_tx_sounding htt_stats_buf->sounding[3]); } } else if (htt_stats_buf->tx_sounding_mode == HTT_TX_AX_SOUNDING_MODE) { @@ -1029,7 +1027,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb cbf_160[HTT_IMPLICIT_TXBF_STEER_STATS], cbf_160[HTT_EXPLICIT_TXBF_SU_SIFS_STEER_STATS], cbf_160[HTT_EXPLICIT_TXBF_SU_RBO_STEER_STATS], -@@ -1374,8 +1381,8 @@ +@@ -1374,8 +1381,8 @@ static inline void htt_print_tx_sounding cbf_160[HTT_EXPLICIT_TXBF_MU_RBO_STEER_STATS]); for (i = 0; i < HTT_TX_PDEV_STATS_NUM_AX_MUMIMO_USER_STATS; i++) { @@ -1040,7 +1038,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb i, htt_stats_buf->sounding[0], htt_stats_buf->sounding[1], -@@ -1400,31 +1407,32 @@ +@@ -1400,31 +1407,32 @@ htt_print_tx_selfgen_cmn_stats_tlv(const u8 *buf = stats_req->buf; u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -1087,7 +1085,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->delayed_bar_7); if (len >= buf_len) -@@ -1444,20 +1452,20 @@ +@@ -1444,20 +1452,20 @@ htt_print_tx_selfgen_ac_stats_tlv(const u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -1116,7 +1114,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->ac_mu_mimo_brpoll_3); if (len >= buf_len) -@@ -1477,36 +1485,36 @@ +@@ -1477,36 +1485,36 @@ htt_print_tx_selfgen_ax_stats_tlv(const u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -1169,7 +1167,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->ax_mu_rts_trigger); if (len >= buf_len) -@@ -1526,20 +1534,20 @@ +@@ -1526,20 +1534,20 @@ htt_print_tx_selfgen_ac_err_stats_tlv(co u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -1198,7 +1196,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->ac_mu_mimo_brp3_err); if (len >= buf_len) -@@ -1559,36 +1567,36 @@ +@@ -1559,36 +1567,36 @@ htt_print_tx_selfgen_ax_err_stats_tlv(co u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -1251,7 +1249,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->ax_mu_rts_trigger_err); if (len >= buf_len) -@@ -1609,34 +1617,34 @@ +@@ -1609,34 +1617,34 @@ htt_print_tx_pdev_mu_mimo_sch_stats_tlv( u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; u8 i; @@ -1300,7 +1298,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb i, htt_stats_buf->ax_ofdma_sch_nusers[i]); if (len >= buf_len) -@@ -1658,36 +1666,36 @@ +@@ -1658,36 +1666,36 @@ htt_print_tx_pdev_mu_mimo_mpdu_stats_tlv if (htt_stats_buf->tx_sched_mode == HTT_STATS_TX_SCHED_MODE_MU_MIMO_AC) { if (!htt_stats_buf->user_index) @@ -1351,7 +1349,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb "ac_mu_mimo_ampdu_underrun_usr_%u = %u\n", htt_stats_buf->user_index, htt_stats_buf->ampdu_underrun_usr); -@@ -1696,36 +1704,36 @@ +@@ -1696,36 +1704,36 @@ htt_print_tx_pdev_mu_mimo_mpdu_stats_tlv if (htt_stats_buf->tx_sched_mode == HTT_STATS_TX_SCHED_MODE_MU_MIMO_AX) { if (!htt_stats_buf->user_index) @@ -1402,7 +1400,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb "ax_mu_mimo_ampdu_underrun_usr_%u = %u\n", htt_stats_buf->user_index, htt_stats_buf->ampdu_underrun_usr); -@@ -1734,35 +1742,35 @@ +@@ -1734,35 +1742,35 @@ htt_print_tx_pdev_mu_mimo_mpdu_stats_tlv if (htt_stats_buf->tx_sched_mode == HTT_STATS_TX_SCHED_MODE_MU_OFDMA_AX) { if (!htt_stats_buf->user_index) @@ -1452,7 +1450,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb "ax_mu_ofdma_ampdu_underrun_usr_%u = %u\n", htt_stats_buf->user_index, htt_stats_buf->ampdu_underrun_usr); -@@ -1789,7 +1797,7 @@ +@@ -1789,7 +1797,7 @@ htt_print_sched_txq_cmd_posted_tlv_v(con char sched_cmd_posted[HTT_MAX_STRING_LEN] = {0}; u16 num_elements = min_t(u16, (tag_len >> 2), HTT_TX_PDEV_SCHED_TX_MODE_MAX); @@ -1461,7 +1459,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb ARRAY_TO_STRING(sched_cmd_posted, htt_stats_buf->sched_cmd_posted, num_elements); -@@ -1816,7 +1824,7 @@ +@@ -1816,7 +1824,7 @@ htt_print_sched_txq_cmd_reaped_tlv_v(con char sched_cmd_reaped[HTT_MAX_STRING_LEN] = {0}; u16 num_elements = min_t(u16, (tag_len >> 2), HTT_TX_PDEV_SCHED_TX_MODE_MAX); @@ -1470,7 +1468,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb ARRAY_TO_STRING(sched_cmd_reaped, htt_stats_buf->sched_cmd_reaped, num_elements); -@@ -1845,8 +1853,8 @@ +@@ -1845,8 +1853,8 @@ htt_print_sched_txq_sched_order_su_tlv_v u32 sched_order_su_num_entries = min_t(u32, (tag_len >> 2), HTT_TX_PDEV_NUM_SCHED_ORDER_LOG); @@ -1481,7 +1479,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb ARRAY_TO_STRING(sched_order_su, htt_stats_buf->sched_order_su, sched_order_su_num_entries); -@@ -1874,8 +1882,8 @@ +@@ -1874,8 +1882,8 @@ htt_print_sched_txq_sched_ineligibility_ /* each entry is u32, i.e. 4 bytes */ u32 sched_ineligibility_num_entries = tag_len >> 2; @@ -1492,7 +1490,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb ARRAY_TO_STRING(sched_ineligibility, htt_stats_buf->sched_ineligibility, sched_ineligibility_num_entries); -@@ -1898,54 +1906,56 @@ +@@ -1898,54 +1906,56 @@ htt_print_tx_pdev_stats_sched_per_txq_tl u8 *buf = stats_req->buf; u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -1577,7 +1575,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->dur_based_sendn_term); if (len >= buf_len) -@@ -1963,11 +1973,12 @@ +@@ -1963,11 +1973,12 @@ static inline void htt_print_stats_tx_sc u8 *buf = stats_req->buf; u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -1594,7 +1592,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->current_timestamp); if (len >= buf_len) -@@ -1991,7 +2002,7 @@ +@@ -1991,7 +2002,7 @@ htt_print_tx_tqm_gen_mpdu_stats_tlv_v(co u16 num_elements = min_t(u16, (tag_len >> 2), HTT_TX_TQM_MAX_LIST_MPDU_END_REASON); @@ -1603,7 +1601,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb ARRAY_TO_STRING(gen_mpdu_end_reason, htt_stats_buf->gen_mpdu_end_reason, num_elements); -@@ -2018,8 +2029,8 @@ +@@ -2018,8 +2029,8 @@ htt_print_tx_tqm_list_mpdu_stats_tlv_v(c char list_mpdu_end_reason[HTT_MAX_STRING_LEN] = {0}; u16 num_elems = min_t(u16, (tag_len >> 2), HTT_TX_TQM_MAX_LIST_MPDU_END_REASON); @@ -1614,7 +1612,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb ARRAY_TO_STRING(list_mpdu_end_reason, htt_stats_buf->list_mpdu_end_reason, num_elems); -@@ -2046,7 +2057,7 @@ +@@ -2046,7 +2057,7 @@ htt_print_tx_tqm_list_mpdu_cnt_tlv_v(con u16 num_elems = min_t(u16, (tag_len >> 2), HTT_TX_TQM_MAX_LIST_MPDU_CNT_HISTOGRAM_BINS); @@ -1623,7 +1621,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb ARRAY_TO_STRING(list_mpdu_cnt_hist, htt_stats_buf->list_mpdu_cnt_hist, num_elems); -@@ -2070,68 +2081,68 @@ +@@ -2070,68 +2081,68 @@ htt_print_tx_tqm_pdev_stats_tlv_v(const u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -1724,7 +1722,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->sched_nonudp_notify2); if (len >= buf_len) -@@ -2149,23 +2160,24 @@ +@@ -2149,23 +2160,24 @@ static inline void htt_print_tx_tqm_cmn_ u8 *buf = stats_req->buf; u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -1759,7 +1757,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->desc_threshold); if (len >= buf_len) -@@ -2184,12 +2196,12 @@ +@@ -2184,12 +2196,12 @@ static inline void htt_print_tx_tqm_erro u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -1776,7 +1774,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->add_msdu_failure); if (len >= buf_len) -@@ -2207,33 +2219,34 @@ +@@ -2207,33 +2219,34 @@ static inline void htt_print_tx_tqm_cmdq u8 *buf = stats_req->buf; u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -1827,7 +1825,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->update_msduq_cmd); if (len >= buf_len) -@@ -2253,19 +2266,19 @@ +@@ -2253,19 +2266,19 @@ htt_print_tx_de_eapol_packets_stats_tlv( u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -1855,7 +1853,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->g2_packets); if (len >= buf_len) -@@ -2285,33 +2298,33 @@ +@@ -2285,33 +2298,33 @@ htt_print_tx_de_classify_failed_stats_tl u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -1904,7 +1902,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->qos_to_non_qos_in_prog); if (len >= buf_len) -@@ -2331,72 +2344,72 @@ +@@ -2331,72 +2344,72 @@ htt_print_tx_de_classify_stats_tlv(const u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -2011,7 +2009,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->mec_notify); if (len >= buf_len) -@@ -2416,23 +2429,23 @@ +@@ -2416,23 +2429,23 @@ htt_print_tx_de_classify_status_stats_tl u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -2045,7 +2043,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->status_invalid); if (len >= buf_len) -@@ -2452,13 +2465,13 @@ +@@ -2452,13 +2465,13 @@ htt_print_tx_de_enqueue_packets_stats_tl u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -2064,7 +2062,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->to_tqm_bypass); if (len >= buf_len) -@@ -2478,13 +2491,13 @@ +@@ -2478,13 +2491,13 @@ htt_print_tx_de_enqueue_discard_stats_tl u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -2083,7 +2081,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->is_ext_msdu); if (len >= buf_len) -@@ -2503,16 +2516,16 @@ +@@ -2503,16 +2516,16 @@ static inline void htt_print_tx_de_compl u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -2106,7 +2104,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->tqm_bypass_frame); if (len >= buf_len) -@@ -2566,21 +2579,22 @@ +@@ -2566,21 +2579,22 @@ htt_print_tx_de_cmn_stats_tlv(const void u8 *buf = stats_req->buf; u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -2138,7 +2136,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->invalid_pdev); if (len >= buf_len) -@@ -2600,39 +2614,49 @@ +@@ -2600,39 +2614,49 @@ static inline void htt_print_ring_if_sta u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; char low_wm_hit_count[HTT_MAX_STRING_LEN] = {0}; char high_wm_hit_count[HTT_MAX_STRING_LEN] = {0}; @@ -2214,7 +2212,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->cons_blockwait_count); ARRAY_TO_STRING(low_wm_hit_count, htt_stats_buf->low_wm_hit_count, -@@ -2660,11 +2684,12 @@ +@@ -2660,11 +2684,12 @@ static inline void htt_print_ring_if_cmn u8 *buf = stats_req->buf; u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -2231,7 +2229,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->num_records); if (len >= buf_len) -@@ -2686,7 +2711,7 @@ +@@ -2686,7 +2711,7 @@ static inline void htt_print_sfm_client_ char dwords_used_by_user_n[HTT_MAX_STRING_LEN] = {0}; u16 num_elems = tag_len >> 2; @@ -2240,7 +2238,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb ARRAY_TO_STRING(dwords_used_by_user_n, htt_stats_buf->dwords_used_by_user_n, -@@ -2710,20 +2735,20 @@ +@@ -2710,20 +2735,20 @@ static inline void htt_print_sfm_client_ u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -2269,7 +2267,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->num_users); if (len >= buf_len) -@@ -2741,17 +2766,18 @@ +@@ -2741,17 +2766,18 @@ static inline void htt_print_sfm_cmn_tlv u8 *buf = stats_req->buf; u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -2295,7 +2293,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->num_records); if (len >= buf_len) -@@ -2769,43 +2795,45 @@ +@@ -2769,43 +2795,45 @@ static inline void htt_print_sring_stats u8 *buf = stats_req->buf; u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -2374,7 +2372,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -2823,8 +2851,8 @@ +@@ -2823,8 +2851,8 @@ static inline void htt_print_sring_cmn_t u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -2385,7 +2383,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->num_records); if (len >= buf_len) -@@ -2846,6 +2874,7 @@ +@@ -2846,6 +2874,7 @@ static inline void htt_print_tx_pdev_rat char str_buf[HTT_MAX_STRING_LEN] = {0}; char *tx_gi[HTT_TX_PEER_STATS_NUM_GI_COUNTERS] = {NULL}; u32 tx_bw[HTT_TX_PDEV_STATS_NUM_BW_COUNTERS + 1] = { 0 }; @@ -2393,7 +2391,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb for (j = 0; j < HTT_TX_PEER_STATS_NUM_GI_COUNTERS; j++) { tx_gi[j] = kmalloc(HTT_MAX_STRING_LEN, GFP_ATOMIC); -@@ -2853,34 +2882,34 @@ +@@ -2853,34 +2882,34 @@ static inline void htt_print_tx_pdev_rat goto fail; } @@ -2442,7 +2440,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->tx_legacy_ofdm_rate[0], htt_stats_buf->tx_legacy_ofdm_rate[1], htt_stats_buf->tx_legacy_ofdm_rate[2], -@@ -3040,6 +3069,7 @@ +@@ -3040,6 +3069,7 @@ static inline void htt_print_rx_pdev_rat char *rx_gi[HTT_RX_PDEV_STATS_NUM_GI_COUNTERS] = {NULL}; char str_buf[HTT_MAX_STRING_LEN] = {0}; char *rx_pilot_evm_db[HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS] = {NULL}; @@ -2450,7 +2448,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb for (j = 0; j < HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS; j++) { rssi_chain[j] = kmalloc(HTT_MAX_STRING_LEN, GFP_ATOMIC); -@@ -3059,22 +3089,22 @@ +@@ -3059,22 +3089,22 @@ static inline void htt_print_rx_pdev_rat goto fail; } @@ -2483,7 +2481,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->rssi_in_dbm); memset(str_buf, 0x0, HTT_MAX_STRING_LEN); -@@ -3104,29 +3134,29 @@ +@@ -3104,29 +3134,29 @@ static inline void htt_print_rx_pdev_rat len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_evm_nss_count = %u", htt_stats_buf->nss_count); @@ -2525,7 +2523,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb for (j = 0; j < HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS; j++) { ARRAY_TO_STRING(rssi_chain[j], htt_stats_buf->rssi_chain[j], -@@ -3147,15 +3177,15 @@ +@@ -3147,15 +3177,15 @@ static inline void htt_print_rx_pdev_rat HTT_RX_PDEV_STATS_NUM_PREAMBLE_TYPES); len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_pream = %s", str_buf); @@ -2546,7 +2544,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->txbf); memset(str_buf, 0x0, HTT_MAX_STRING_LEN); -@@ -3170,11 +3200,11 @@ +@@ -3170,11 +3200,11 @@ static inline void htt_print_rx_pdev_rat len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_legacy_ofdm_rate = %s ", str_buf); @@ -2561,7 +2559,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->rx_11ax_ul_ofdma); memset(str_buf, 0x0, HTT_MAX_STRING_LEN); -@@ -3183,9 +3213,7 @@ +@@ -3183,9 +3213,7 @@ static inline void htt_print_rx_pdev_rat len += HTT_DBG_OUT(buf + len, buf_len - len, "ul_ofdma_rx_mcs = %s ", str_buf); for (j = 0; j < HTT_RX_PDEV_STATS_NUM_GI_COUNTERS; j++) { @@ -2572,7 +2570,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb j, rx_gi[j]); } -@@ -3199,9 +3227,9 @@ +@@ -3199,9 +3227,9 @@ static inline void htt_print_rx_pdev_rat HTT_RX_PDEV_STATS_NUM_BW_COUNTERS); len += HTT_DBG_OUT(buf + len, buf_len - len, "ul_ofdma_rx_bw = %s ", str_buf); @@ -2584,7 +2582,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->ul_ofdma_rx_ldpc); memset(str_buf, 0x0, HTT_MAX_STRING_LEN); -@@ -3231,16 +3259,15 @@ +@@ -3231,16 +3259,15 @@ static inline void htt_print_rx_pdev_rat index = 0; memset(str_buf, 0x0, HTT_MAX_STRING_LEN); for (i = 0; i < HTT_RX_PDEV_MAX_OFDMA_NUM_USER; i++) @@ -2608,7 +2606,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb for (j = 0; j < HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS; j++) { index = 0; -@@ -3254,7 +3281,7 @@ +@@ -3254,7 +3281,7 @@ static inline void htt_print_rx_pdev_rat len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_per_chain_rssi_in_dbm[%u] = %s ", j, str_buf); } @@ -2617,7 +2615,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -3308,33 +3335,33 @@ +@@ -3308,33 +3335,33 @@ static inline void htt_print_rx_soc_fw_s u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -2668,7 +2666,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->target_refill_ring_recycle_cnt); if (len >= buf_len) -@@ -3357,8 +3384,8 @@ +@@ -3357,8 +3384,8 @@ htt_print_rx_soc_fw_refill_ring_empty_tl char refill_ring_empty_cnt[HTT_MAX_STRING_LEN] = {0}; u16 num_elems = min_t(u16, (tag_len >> 2), HTT_RX_STATS_REFILL_MAX_RING); @@ -2679,7 +2677,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb ARRAY_TO_STRING(refill_ring_empty_cnt, htt_stats_buf->refill_ring_empty_cnt, -@@ -3387,8 +3414,8 @@ +@@ -3387,8 +3414,8 @@ htt_print_rx_soc_fw_refill_ring_num_rxdm char rxdma_err_cnt[HTT_MAX_STRING_LEN] = {0}; u16 num_elems = min_t(u16, (tag_len >> 2), HTT_RX_RXDMA_MAX_ERR_CODE); @@ -2690,7 +2688,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb ARRAY_TO_STRING(rxdma_err_cnt, htt_stats_buf->rxdma_err, -@@ -3416,8 +3443,8 @@ +@@ -3416,8 +3443,8 @@ htt_print_rx_soc_fw_refill_ring_num_reo_ char reo_err_cnt[HTT_MAX_STRING_LEN] = {0}; u16 num_elems = min_t(u16, (tag_len >> 2), HTT_RX_REO_MAX_ERR_CODE); @@ -2701,7 +2699,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb ARRAY_TO_STRING(reo_err_cnt, htt_stats_buf->reo_err, -@@ -3442,26 +3469,26 @@ +@@ -3442,26 +3469,26 @@ htt_print_rx_reo_debug_stats_tlv_v(const u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -2739,7 +2737,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->last_non_zeros_sample); if (len >= buf_len) -@@ -3484,8 +3511,8 @@ +@@ -3484,8 +3511,8 @@ htt_print_rx_soc_fw_refill_ring_num_refi char refill_ring_num_refill[HTT_MAX_STRING_LEN] = {0}; u16 num_elems = min_t(u16, (tag_len >> 2), HTT_RX_STATS_REFILL_MAX_RING); @@ -2750,7 +2748,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb ARRAY_TO_STRING(refill_ring_num_refill, htt_stats_buf->refill_ring_num_refill, -@@ -3508,112 +3535,99 @@ +@@ -3508,112 +3535,99 @@ static inline void htt_print_rx_pdev_fw_ u8 *buf = stats_req->buf; u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -2913,7 +2911,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->rx_recovery_reset_cnt); if (len >= buf_len) -@@ -3634,8 +3648,8 @@ +@@ -3634,8 +3648,8 @@ htt_print_rx_pdev_fw_ring_mpdu_err_tlv_v u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; char fw_ring_mpdu_err[HTT_MAX_STRING_LEN] = {0}; @@ -2924,7 +2922,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb ARRAY_TO_STRING(fw_ring_mpdu_err, htt_stats_buf->fw_ring_mpdu_err, -@@ -3663,7 +3677,7 @@ +@@ -3663,7 +3677,7 @@ htt_print_rx_pdev_fw_mpdu_drop_tlv_v(con char fw_mpdu_drop[HTT_MAX_STRING_LEN] = {0}; u16 num_elems = min_t(u16, (tag_len >> 2), HTT_RX_STATS_FW_DROP_REASON_MAX); @@ -2933,7 +2931,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb ARRAY_TO_STRING(fw_mpdu_drop, htt_stats_buf->fw_mpdu_drop, -@@ -3687,11 +3701,12 @@ +@@ -3687,11 +3701,12 @@ htt_print_rx_pdev_fw_stats_phy_err_tlv(c u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; char phy_errs[HTT_MAX_STRING_LEN] = {0}; @@ -2950,7 +2948,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->total_phy_err_cnt); ARRAY_TO_STRING(phy_errs, -@@ -3716,19 +3731,19 @@ +@@ -3716,19 +3731,19 @@ htt_print_pdev_cca_stats_hist_tlv(const u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -2978,7 +2976,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb "| tx_frame| rx_frame| rx_clear| my_rx_frame| cnt| med_rx_idle| med_tx_idle_global| cca_obss|"); if (len >= buf_len) -@@ -3748,7 +3763,7 @@ +@@ -3748,7 +3763,7 @@ htt_print_pdev_stats_cca_counters_tlv(co u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -2987,7 +2985,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb "|%10u| %10u| %10u| %11u| %10u| %11u| %18u| %10u|", htt_stats_buf->tx_frame_usec, htt_stats_buf->rx_frame_usec, -@@ -3774,32 +3789,33 @@ +@@ -3774,32 +3789,33 @@ static inline void htt_print_hw_stats_wh u8 *buf = stats_req->buf; u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -3036,7 +3034,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->sch_rx_sifs_resp_trigger); if (len >= buf_len) -@@ -3819,10 +3835,10 @@ +@@ -3819,10 +3835,10 @@ htt_print_pdev_stats_twt_sessions_tlv(co u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -3050,7 +3048,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->num_sessions); if (len >= buf_len) -@@ -3841,27 +3857,29 @@ +@@ -3841,27 +3857,29 @@ htt_print_pdev_stats_twt_session_tlv(con u8 *buf = stats_req->buf; u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -3095,16 +3093,14 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->sp_offset_us); if (len >= buf_len) -@@ -3881,22 +3899,10 @@ +@@ -3881,21 +3899,10 @@ htt_print_pdev_obss_pd_stats_tlv_v(const u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; - len += HTT_DBG_OUT(buf + len, buf_len - len, "OBSS Tx success PPDU = %u", -+ len += scnprintf(buf + len, buf_len - len, "OBSS Tx success PPDU = %u\n", - htt_stats_buf->num_obss_tx_ppdu_success); +- htt_stats_buf->num_obss_tx_ppdu_success); - len += HTT_DBG_OUT(buf + len, buf_len - len, "OBSS Tx failures PPDU = %u\n", -+ len += scnprintf(buf + len, buf_len - len, "OBSS Tx failures PPDU = %u\n", - htt_stats_buf->num_obss_tx_ppdu_failure); +- htt_stats_buf->num_obss_tx_ppdu_failure); - len += HTT_DBG_OUT(buf + len, buf_len - len, "Non-SRG Opportunities = %u\n", - htt_stats_buf->num_non_srg_opportunities); - len += HTT_DBG_OUT(buf + len, buf_len - len, "Non-SRG tried PPDU = %u\n", @@ -3116,11 +3112,14 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb - len += HTT_DBG_OUT(buf + len, buf_len - len, "SRG tried PPDU = %u\n", - htt_stats_buf->num_srg_ppdu_tried); - len += HTT_DBG_OUT(buf + len, buf_len - len, "SRG success PPDU = %u\n", -- htt_stats_buf->num_srg_ppdu_success); ++ len += scnprintf(buf + len, buf_len - len, "OBSS Tx success PPDU = %u\n", ++ htt_stats_buf->num_obss_tx_ppdu_success); ++ len += scnprintf(buf + len, buf_len - len, "OBSS Tx failures PPDU = %u\n", ++ htt_stats_buf->num_obss_tx_ppdu_failure); if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -3918,24 +3924,24 @@ +@@ -3917,24 +3924,24 @@ static inline void htt_print_backpressur u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -3154,7 +3153,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb "============================"); if (len >= buf_len) { -@@ -3957,28 +3963,28 @@ +@@ -3956,28 +3963,28 @@ htt_print_tx_selfgen_be_stats_tlv(const u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -3205,7 +3204,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ARRAY_TO_STRING(str_buf, htt_stats_buf->be_mu_mimo_brpoll_queued, -@@ -3998,18 +4004,18 @@ +@@ -3997,18 +4004,18 @@ htt_print_tx_selfgen_be_stats_tlv(const len += HTT_DBG_OUT(buf + len, buf_len - len, "be_ul_mumimo_trigger = %s ", str_buf); @@ -3236,7 +3235,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -4029,8 +4035,8 @@ +@@ -4028,8 +4035,8 @@ htt_print_tx_selfgen_be_sched_status_sta u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -3247,7 +3246,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ARRAY_TO_STRING(str_buf, htt_stats_buf->be_su_ndpa_sch_status, -@@ -4123,8 +4129,8 @@ +@@ -4122,8 +4129,8 @@ htt_print_tx_pdev_be_ul_mu_mimo_sch_stat u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -3258,7 +3257,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb for (i = 0; i < HTT_TX_PDEV_STATS_NUM_UL_MUMIMO_USER_STATS; i++) { len += HTT_DBG_OUT(buf + len, buf_len - len, "be_ul_mu_mimo_basic_sch_nusers_%u = %u", i, -@@ -4161,10 +4167,10 @@ +@@ -4160,10 +4167,10 @@ htt_print_tx_pdev_be_rate_stats_tlv(cons goto fail; } @@ -3273,7 +3272,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb memset(str_buf, 0x0, HTT_MAX_STRING_LEN); /* MCS -2 and -1 will be printed first */ -@@ -4257,6 +4263,7 @@ +@@ -4256,6 +4263,7 @@ htt_print_ul_mumimo_trig_be_stats(const u8 *buf = stats_req->buf; u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -3281,7 +3280,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb for (i = 0; i < HTT_TX_PEER_STATS_NUM_GI_COUNTERS; i++) { rx_gi[i] = kmalloc(HTT_MAX_STRING_LEN, GFP_ATOMIC); -@@ -4264,13 +4271,13 @@ +@@ -4263,13 +4271,13 @@ htt_print_ul_mumimo_trig_be_stats(const goto fail; } @@ -3301,7 +3300,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb /* TODO: Check if enough space is present before writing BE MCS Counters */ index = 0; -@@ -4318,12 +4325,12 @@ +@@ -4317,12 +4325,12 @@ htt_print_ul_mumimo_trig_be_stats(const len += HTT_DBG_OUT(buf + len, buf_len - len, "be_ul_mumimo_rx_bw = %s ", str_buf); @@ -3320,7 +3319,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb for (i = 0; i < HTT_RX_PDEV_STATS_ULMUMIMO_NUM_SPATIAL_STREAMS; i++) { memset(str_buf, 0x0, HTT_MAX_STRING_LEN); -@@ -4364,7 +4371,7 @@ +@@ -4363,7 +4371,7 @@ htt_print_ul_mumimo_trig_be_stats(const "be_rx_ulmumimo_pilot_evm_dB_mean: user [%u] = %s ", i, str_buf); } @@ -3329,7 +3328,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -4389,6 +4396,7 @@ +@@ -4388,6 +4396,7 @@ htt_print_be_ul_ofdma_trigger_stats(cons u8 *buf = stats_req->buf; u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -3337,7 +3336,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb for (i = 0; i < HTT_TX_PEER_STATS_NUM_GI_COUNTERS; i++) { rx_gi[i] = kmalloc(HTT_MAX_STRING_LEN, GFP_ATOMIC); -@@ -4396,12 +4404,12 @@ +@@ -4395,12 +4404,12 @@ htt_print_be_ul_ofdma_trigger_stats(cons goto fail; } @@ -3356,7 +3355,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ARRAY_TO_STRING(str_buf, htt_trigger_stats_buf->be_ul_ofdma_rx_mcs, -@@ -4437,9 +4445,9 @@ +@@ -4436,9 +4445,9 @@ htt_print_be_ul_ofdma_trigger_stats(cons len += HTT_DBG_OUT(buf + len, buf_len - len, "be_ul_ofdma_rx_bw = %s ", str_buf); @@ -3368,7 +3367,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_trigger_stats_buf->be_ul_ofdma_rx_ldpc); memset(str_buf, 0x0, HTT_MAX_STRING_LEN); -@@ -4505,8 +4513,8 @@ +@@ -4504,8 +4513,8 @@ htt_print_tx_pdev_be_dl_mu_ofdma_sch_sta u32 len = stats_req->buf_len; u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; @@ -3379,7 +3378,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb for (i = 0; i < HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS; i++) { len += HTT_DBG_OUT(buf + len, buf_len - len, -@@ -4574,13 +4582,13 @@ +@@ -4573,13 +4582,13 @@ htt_print_tx_pdev_rate_stats_be_ofdma_tl goto fail; } @@ -3399,7 +3398,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ARRAY_TO_STRING(str_buf, htt_stats_buf->be_ofdma_tx_mcs, -@@ -4639,26 +4647,26 @@ +@@ -4638,26 +4647,26 @@ htt_print_tx_selfgen_be_err_stats_tlv(co const struct htt_tx_selfgen_be_err_stats_tlv *htt_stats_buf = tag_buf; @@ -3446,7 +3445,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb memset(str_buf, 0x0, HTT_MAX_STRING_LEN); ARRAY_TO_STRING(str_buf, htt_stats_buf->be_mu_mimo_brp_err, -@@ -4684,19 +4692,19 @@ +@@ -4683,19 +4692,19 @@ htt_print_tx_selfgen_be_err_stats_tlv(co len += HTT_DBG_OUT(buf + len, buf_len - len, "be_ul_mumimo_trigger_err = %s ", str_buf); @@ -3479,7 +3478,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb } static int ath12k_dbg_htt_ext_stats_parse(struct ath12k_base *ab, -@@ -5118,14 +5126,14 @@ +@@ -5117,14 +5126,14 @@ void ath12k_debugfs_htt_ext_stats_handle u8 pdev_id; msg = (struct ath12k_htt_extd_stats_msg *)skb->data; @@ -3497,7 +3496,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb rcu_read_lock(); ar = ath12k_mac_get_ar_by_pdev_id(ab, pdev_id); rcu_read_unlock(); -@@ -5140,13 +5148,14 @@ +@@ -5139,13 +5148,14 @@ void ath12k_debugfs_htt_ext_stats_handle spin_lock_bh(&ar->debug.htt_stats.lock); @@ -3514,11 +3513,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb ret = ath12k_dp_htt_tlv_iter(ab, msg->data, len, ath12k_dbg_htt_ext_stats_parse, stats_req); -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h 2022-05-10 10:47:12.729567300 +0530 -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h 2022-05-10 10:47:12.729567300 +0530 -@@ -320,6 +320,10 @@ +--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h ++++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h +@@ -320,6 +320,10 @@ struct htt_hw_stats_whal_tx_tlv { }; /* ============ PEER STATS ============ */ @@ -3529,7 +3526,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb struct htt_msdu_flow_stats_tlv { u32 last_update_timestamp; u32 last_add_timestamp; -@@ -336,6 +340,11 @@ +@@ -336,6 +340,11 @@ struct htt_msdu_flow_stats_tlv { #define MAX_HTT_TID_NAME 8 @@ -3541,7 +3538,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb /* Tidq stats */ struct htt_tx_tid_stats_tlv { /* Stored as little endian */ -@@ -356,6 +365,11 @@ +@@ -356,6 +365,11 @@ struct htt_tx_tid_stats_tlv { u32 tid_tx_airtime; }; @@ -3553,7 +3550,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb /* Tidq stats */ struct htt_tx_tid_stats_v1_tlv { /* Stored as little endian */ -@@ -378,6 +392,9 @@ +@@ -378,6 +392,9 @@ struct htt_tx_tid_stats_v1_tlv { u32 sendn_frms_allowed; }; @@ -3563,7 +3560,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb struct htt_rx_tid_stats_tlv { u32 sw_peer_id__tid_num; u8 tid_name[MAX_HTT_TID_NAME]; -@@ -416,6 +433,10 @@ +@@ -416,6 +433,10 @@ struct htt_peer_stats_cmn_tlv { u32 inactive_time; }; @@ -3574,7 +3571,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb struct htt_peer_details_tlv { u32 peer_type; u32 sw_peer_id; -@@ -540,6 +561,9 @@ +@@ -540,6 +561,9 @@ struct htt_tx_hwq_mu_mimo_mpdu_stats_tlv u32 mu_mimo_ampdu_underrun_usr; }; @@ -3584,7 +3581,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb struct htt_tx_hwq_mu_mimo_cmn_stats_tlv { u32 mac_id__hwq_id__word; }; -@@ -822,6 +846,9 @@ +@@ -822,6 +846,9 @@ struct htt_sched_txq_sched_ineligibility u32 sched_ineligibility[0]; }; @@ -3594,7 +3591,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb struct htt_tx_pdev_stats_sched_per_txq_tlv { u32 mac_id__txq_id__word; u32 sched_policy; -@@ -943,6 +970,9 @@ +@@ -943,6 +970,9 @@ struct htt_tx_tqm_error_stats_tlv { }; /* == TQM CMDQ stats == */ @@ -3604,7 +3601,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb struct htt_tx_tqm_cmdq_status_tlv { u32 mac_id__cmdq_id__word; u32 sync_cmd; -@@ -1088,6 +1118,15 @@ +@@ -1088,6 +1118,15 @@ struct htt_tx_de_cmn_stats_tlv { #define HTT_STATS_LOW_WM_BINS 5 #define HTT_STATS_HIGH_WM_BINS 5 @@ -3620,7 +3617,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb struct htt_ring_if_stats_tlv { u32 base_addr; /* DWORD aligned base memory address of the ring */ u32 elem_size; -@@ -1150,6 +1189,19 @@ +@@ -1150,6 +1189,19 @@ struct htt_sfm_cmn_tlv { }; /* == SRNG STATS == */ @@ -3640,11 +3637,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb struct htt_sring_stats_tlv { u32 mac_id__ring_id__arena__ep; u32 base_addr_lsb; /* DWORD aligned base memory address of the ring */ -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/dp.h 2022-05-10 10:47:12.729567300 +0530 -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp.h 2022-05-10 10:47:12.729567300 +0530 -@@ -2022,6 +2022,13 @@ +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -1983,6 +1983,13 @@ struct ath12k_htt_extd_stats_msg { u8 data[0]; } __packed; diff --git a/feeds/ipq95xx/mac80211/patches/qca/625-ath12k-supporting-5.9G-band-with-160Mhz.patch b/feeds/ipq95xx/mac80211/patches/qca/625-ath12k-supporting-5.9G-band-with-160Mhz.patch index 290837e25..00dd5cb30 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/625-ath12k-supporting-5.9G-band-with-160Mhz.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/625-ath12k-supporting-5.9G-band-with-160Mhz.patch @@ -14,11 +14,9 @@ Signed-off-by: Aishwarya R drivers/net/wireless/ath/ath12k/wmi.h | 1 + 5 files changed, 73 insertions(+), 27 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h -index 78cba92..a29ba3f 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h -@@ -495,8 +495,12 @@ struct ath12k_sta { +@@ -496,8 +496,12 @@ struct ath12k_sta { #define ATH12K_MIN_6G_FREQ (ATH12K_6G_MIN_CENTER - ATH12K_HALF_20MHZ_BW) #define ATH12K_MAX_6G_FREQ (ATH12K_6G_MAX_CENTER + ATH12K_HALF_20MHZ_BW) @@ -47,19 +45,17 @@ index 78cba92..a29ba3f 100644 /* Current DFS Regulatory */ enum ath12k_dfs_region dfs_region; - struct ath12k_reg_rule reg_rule_2g; -- struct ath12k_reg_rule reg_rule_5g; -- struct ath12k_reg_rule reg_rule_6g; +- struct ath12k_reg_rule reg_rule_5g; +- struct ath12k_reg_rule reg_rule_6g; + struct ath12k_reg_freq reg_freq_2g; -+ struct ath12k_reg_freq reg_freq_5g; -+ struct ath12k_reg_freq reg_freq_6g; ++ struct ath12k_reg_freq reg_freq_5g; ++ struct ath12k_reg_freq reg_freq_6g; #ifdef CPTCFG_ATH12K_DEBUGFS struct dentry *debugfs_soc; #endif -diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c -index 728c001..01de5b0 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -2539,9 +2539,11 @@ void ath12k_dp_rx_h_ppdu(struct ath12k *ar, struct hal_rx_desc *rx_desc, +@@ -2528,9 +2528,11 @@ void ath12k_dp_rx_h_ppdu(struct ath12k * center_freq <= ATH12K_MAX_6G_FREQ) { rx_status->band = NL80211_BAND_6GHZ; rx_status->freq = center_freq; @@ -73,11 +69,9 @@ index 728c001..01de5b0 100644 rx_status->band = NL80211_BAND_5GHZ; } -diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index d65f0f3..797b69a 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -89,6 +89,7 @@ static const struct ieee80211_channel ath12k_5ghz_channels[] = { +@@ -89,6 +89,7 @@ static const struct ieee80211_channel at CHAN5G(165, 5825, 0), CHAN5G(169, 5845, 0), CHAN5G(173, 5865, 0), @@ -85,7 +79,7 @@ index d65f0f3..797b69a 100644 }; static const struct ieee80211_channel ath12k_6ghz_channels[] = { -@@ -8995,6 +8996,28 @@ static void ath12k_mac_update_ch_list(struct ath12k *ar, +@@ -9069,6 +9070,28 @@ static void ath12k_mac_update_ch_list(st } } @@ -114,7 +108,7 @@ index d65f0f3..797b69a 100644 static u32 ath12k_get_phy_id(struct ath12k *ar, u32 band) { struct ath12k_pdev *pdev = ar->pdev; -@@ -9014,8 +9037,9 @@ static u32 ath12k_get_phy_id(struct ath12k *ar, u32 band) +@@ -9088,8 +9111,9 @@ static u32 ath12k_get_phy_id(struct ath1 static int ath12k_mac_setup_channels_rates(struct ath12k *ar, u32 supported_bands) { @@ -125,7 +119,7 @@ index d65f0f3..797b69a 100644 void *channels; u32 phy_id; struct ieee80211_6ghz_channel *chan_6g; -@@ -9027,7 +9051,8 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar, +@@ -9101,7 +9125,8 @@ static int ath12k_mac_setup_channels_rat ARRAY_SIZE(ath12k_6ghz_channels)) != ATH12K_NUM_CHANS); @@ -135,12 +129,12 @@ index d65f0f3..797b69a 100644 if (supported_bands & WMI_HOST_WLAN_2G_CAP) { channels = kmemdup(ath12k_2ghz_channels, -@@ -9044,13 +9069,15 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar, +@@ -9118,13 +9143,13 @@ static int ath12k_mac_setup_channels_rat band->bitrates = ath12k_g_rates; ar->hw->wiphy->bands[NL80211_BAND_2GHZ] = band; -- if (ar->ab->hw_params.single_pdev_only) { -+ if (ab->hw_params.single_pdev_only) { +- if (ar->ab->hw_params->single_pdev_only) { ++ if (ab->hw_params->single_pdev_only) { phy_id = ath12k_get_phy_id(ar, WMI_HOST_WLAN_2G_CAP); - reg_cap = &ar->ab->hal_reg_cap[phy_id]; + temp_reg_cap = &ab->hal_reg_cap[phy_id]; @@ -148,26 +142,22 @@ index d65f0f3..797b69a 100644 ath12k_mac_update_ch_list(ar, band, - reg_cap->low_2ghz_chan, - reg_cap->high_2ghz_chan); -+ max(temp_reg_cap->low_2ghz_chan, -+ ab->reg_freq_2g.start_freq), -+ min(temp_reg_cap->high_2ghz_chan, -+ ab->reg_freq_2g.end_freq)); ++ temp_reg_cap->low_2ghz_chan, ++ temp_reg_cap->high_2ghz_chan); } if (supported_bands & WMI_HOST_WLAN_5G_CAP) { -@@ -9081,12 +9108,16 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar, +@@ -9155,12 +9180,14 @@ static int ath12k_mac_setup_channels_rat - if (ar->ab->hw_params.single_pdev_only) { + if (ar->ab->hw_params->single_pdev_only) { phy_id = ath12k_get_phy_id(ar, WMI_HOST_WLAN_5G_CAP); + temp_reg_cap = &ab->hal_reg_cap[phy_id]; } ath12k_mac_update_ch_list(ar, band, - reg_cap->low_5ghz_chan, - reg_cap->high_5ghz_chan); -+ max(temp_reg_cap->low_5ghz_chan, -+ ab->reg_freq_5g.start_freq), -+ min(temp_reg_cap->high_5ghz_chan, -+ ab->reg_freq_5g.end_freq)); ++ temp_reg_cap->low_5ghz_chan, ++ temp_reg_cap->high_5ghz_chan); - } else if (reg_cap->low_5ghz_chan >= ATH12K_MIN_6G_FREQ && + ath12k_mac_update_5_9_ch_list(ar, band); @@ -175,7 +165,7 @@ index d65f0f3..797b69a 100644 reg_cap->high_5ghz_chan <= ATH12K_MAX_6G_FREQ) { band = &ar->mac.sbands[NL80211_BAND_6GHZ]; band->band = NL80211_BAND_6GHZ; -@@ -9120,9 +9151,12 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar, +@@ -9194,9 +9221,11 @@ static int ath12k_mac_setup_channels_rat band->n_bitrates = ath12k_a_rates_size; band->bitrates = ath12k_a_rates; ar->hw->wiphy->bands[NL80211_BAND_6GHZ] = band; @@ -183,18 +173,15 @@ index d65f0f3..797b69a 100644 ath12k_mac_update_ch_list(ar, band, - reg_cap->low_5ghz_chan, - reg_cap->high_5ghz_chan); -+ max(temp_reg_cap->low_5ghz_chan, -+ ab->reg_freq_6g.start_freq), -+ min(temp_reg_cap->high_5ghz_chan, -+ ab->reg_freq_6g.end_freq)); - ++ temp_reg_cap->low_5ghz_chan, ++ temp_reg_cap->high_5ghz_chan); ++ /* For 6G sband, the strcut channels and int numchannels will * have the default value. During ieee80211_hw_register(), -diff --git a/drivers/net/wireless/ath/ath12k/reg.c b/drivers/net/wireless/ath/ath12k/reg.c -index ea0000f..f45a641 100644 + * all sbands are parsed and at that time code can crash while --- a/drivers/net/wireless/ath/ath12k/reg.c +++ b/drivers/net/wireless/ath/ath12k/reg.c -@@ -43,15 +43,15 @@ ath12k_ieee80211_ap_pwr_type_convert(enum ieee80211_ap_reg_power power_type) +@@ -43,15 +43,15 @@ ath12k_ieee80211_ap_pwr_type_convert(enu } } @@ -216,7 +203,7 @@ index ea0000f..f45a641 100644 } static struct cur_reg_rule -@@ -715,6 +715,7 @@ ath12k_reg_build_regd(struct ath12k_base *ab, +@@ -715,6 +715,7 @@ ath12k_reg_build_regd(struct ath12k_base reg_info->max_bw_2g); flags = NL80211_RRF_NO_320MHZ; pwr_mode = 0; @@ -224,7 +211,7 @@ index ea0000f..f45a641 100644 } else if (reg_info->num_5g_reg_rules && (j < reg_info->num_5g_reg_rules)) { reg_rule = reg_info->reg_rules_5g_ptr + j++; -@@ -739,6 +740,10 @@ ath12k_reg_build_regd(struct ath12k_base *ab, +@@ -739,6 +740,10 @@ ath12k_reg_build_regd(struct ath12k_base */ flags = NL80211_RRF_AUTO_BW | NL80211_RRF_NO_320MHZ; pwr_mode = 0; @@ -235,7 +222,7 @@ index ea0000f..f45a641 100644 } else if (reg_info->is_ext_reg_event && reg_6g_number) { if (!reg_6g_itr_set) { reg_rule_6g = ath12k_get_active_6g_reg_rule(reg_info, -@@ -762,9 +767,9 @@ ath12k_reg_build_regd(struct ath12k_base *ab, +@@ -762,9 +767,9 @@ ath12k_reg_build_regd(struct ath12k_base flags |= NL80211_RRF_PSD; if (reg_rule->end_freq <= ATH12K_MAX_6G_FREQ) @@ -247,18 +234,13 @@ index ea0000f..f45a641 100644 } if (reg_6g_itr_set && k >= max_elements) { -diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h -index e724eb0..5674cd4 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -2137,6 +2137,7 @@ enum wmi_tlv_service { +@@ -2124,6 +2124,7 @@ enum wmi_tlv_service { WMI_TLV_SERVICE_PER_PEER_HTT_STATS_RESET = 213, WMI_TLV_SERVICE_FREQINFO_IN_METADATA = 219, WMI_TLV_SERVICE_EXT2_MSG = 220, + WMI_TLV_SERVICE_5_9GHZ_SUPPORT = 247, WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT = 249, + WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT = 253, - WMI_MAX_EXT_SERVICE = 256, --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/626-mac80211-add-EHT-support-for-mesh.patch b/feeds/ipq95xx/mac80211/patches/qca/626-mac80211-add-EHT-support-for-mesh.patch index bc27eebe5..c1ad0032c 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/626-mac80211-add-EHT-support-for-mesh.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/626-mac80211-add-EHT-support-for-mesh.patch @@ -17,7 +17,7 @@ Signed-off-by: Ramya Gnanasekar --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h -@@ -3898,6 +3898,12 @@ struct ieee80211_multiple_bssid_configur +@@ -4009,6 +4009,12 @@ struct ieee80211_multiple_bssid_configur #define WLAN_OUI_TYPE_MICROSOFT_WPS 4 #define WLAN_OUI_TYPE_MICROSOFT_TPC 8 @@ -32,7 +32,7 @@ Signed-off-by: Ramya Gnanasekar */ --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h -@@ -2420,6 +2420,12 @@ u8 *ieee80211_ie_build_he_cap(u8 *pos, +@@ -2411,6 +2411,12 @@ u8 *ieee80211_ie_build_he_cap(ieee80211_ void ieee80211_ie_build_he_6ghz_cap(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); u8 *ieee80211_ie_build_he_oper(u8 *pos, struct cfg80211_chan_def *chandef); @@ -42,7 +42,7 @@ Signed-off-by: Ramya Gnanasekar + const struct ieee80211_sta_eht_cap *eht_cap, + u8 *end); +u8 *ieee80211_ie_build_eht_oper(u8 *pos, struct cfg80211_chan_def *chandef); - int ieee80211_parse_bitrates(struct cfg80211_chan_def *chandef, + int ieee80211_parse_bitrates(enum nl80211_chan_width width, const struct ieee80211_supported_band *sband, const u8 *srates, int srates_len, u32 *rates); --- a/net/mac80211/mesh.c @@ -56,7 +56,7 @@ Signed-off-by: Ramya Gnanasekar &sta_chan_def); if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef, -@@ -644,6 +644,66 @@ int mesh_add_he_6ghz_cap_ie(struct ieee8 +@@ -644,6 +644,67 @@ int mesh_add_he_6ghz_cap_ie(struct ieee8 return 0; } @@ -109,7 +109,8 @@ Signed-off-by: Ramya Gnanasekar + sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_10) + return 0; + -+ len = 2 + 1 + sizeof(struct ieee80211_eht_operation); ++ len = 2 + 1 + sizeof(struct ieee80211_eht_operation) + ++ sizeof(struct ieee80211_eht_operation_info); + + if (skb_tailroom(skb) < len) + return -ENOMEM; @@ -123,7 +124,7 @@ Signed-off-by: Ramya Gnanasekar static void ieee80211_mesh_path_timer(struct timer_list *t) { struct ieee80211_sub_if_data *sdata = -@@ -681,6 +741,7 @@ ieee80211_mesh_update_bss_params(struct +@@ -681,6 +742,7 @@ ieee80211_mesh_update_bss_params(struct struct ieee80211_supported_band *sband; const struct element *cap; const struct ieee80211_he_operation *he_oper = NULL; @@ -131,7 +132,7 @@ Signed-off-by: Ramya Gnanasekar sband = ieee80211_get_sband(sdata); if (!sband) -@@ -702,6 +763,18 @@ ieee80211_mesh_update_bss_params(struct +@@ -702,6 +764,18 @@ ieee80211_mesh_update_bss_params(struct if (he_oper) sdata->vif.bss_conf.he_oper.params = __le32_to_cpu(he_oper->he_oper_params); @@ -150,7 +151,7 @@ Signed-off-by: Ramya Gnanasekar } /** -@@ -821,7 +894,7 @@ ieee80211_mesh_build_beacon(struct ieee8 +@@ -821,7 +895,7 @@ ieee80211_mesh_build_beacon(struct ieee8 struct ieee80211_chanctx_conf *chanctx_conf; struct mesh_csa_settings *csa; enum nl80211_band band; @@ -159,7 +160,7 @@ Signed-off-by: Ramya Gnanasekar u8 *pos; struct ieee80211_sub_if_data *sdata; int hdr_len = offsetofend(struct ieee80211_mgmt, u.beacon); -@@ -834,6 +907,8 @@ ieee80211_mesh_build_beacon(struct ieee8 +@@ -834,6 +908,8 @@ ieee80211_mesh_build_beacon(struct ieee8 ie_len_he_cap = ieee80211_ie_len_he_cap(sdata, NL80211_IFTYPE_MESH_POINT); @@ -168,16 +169,17 @@ Signed-off-by: Ramya Gnanasekar head_len = hdr_len + 2 + /* NULL SSID */ /* Channel Switch Announcement */ -@@ -857,6 +932,8 @@ ieee80211_mesh_build_beacon(struct ieee8 +@@ -857,6 +933,9 @@ ieee80211_mesh_build_beacon(struct ieee8 2 + 1 + sizeof(struct ieee80211_he_operation) + sizeof(struct ieee80211_he_6ghz_oper) + 2 + 1 + sizeof(struct ieee80211_he_6ghz_capa) + + ie_len_eht_cap + + 2 + 1 + sizeof(struct ieee80211_eht_operation) + ++ + sizeof(struct ieee80211_eht_operation_info) + ifmsh->ie_len; bcn = kzalloc(sizeof(*bcn) + head_len + tail_len, GFP_KERNEL); -@@ -978,6 +1055,8 @@ ieee80211_mesh_build_beacon(struct ieee8 +@@ -978,6 +1057,8 @@ ieee80211_mesh_build_beacon(struct ieee8 mesh_add_he_cap_ie(sdata, skb, ie_len_he_cap) || mesh_add_he_oper_ie(sdata, skb) || mesh_add_he_6ghz_cap_ie(sdata, skb) || @@ -217,16 +219,17 @@ Signed-off-by: Ramya Gnanasekar skb = dev_alloc_skb(local->tx_headroom + hdr_len + 2 + /* capability info */ -@@ -241,6 +243,8 @@ static int mesh_plink_frame_tx(struct ie +@@ -241,6 +243,9 @@ static int mesh_plink_frame_tx(struct ie 2 + 1 + sizeof(struct ieee80211_he_operation) + sizeof(struct ieee80211_he_6ghz_oper) + 2 + 1 + sizeof(struct ieee80211_he_6ghz_capa) + + ie_len_eht_cap + + 2 + 1 + sizeof(struct ieee80211_eht_operation) + ++ sizeof(struct ieee80211_eht_operation_info) + 2 + 8 + /* peering IE */ sdata->u.mesh.ie_len); if (!skb) -@@ -332,7 +336,9 @@ static int mesh_plink_frame_tx(struct ie +@@ -332,7 +337,9 @@ static int mesh_plink_frame_tx(struct ie mesh_add_vht_oper_ie(sdata, skb) || mesh_add_he_cap_ie(sdata, skb, ie_len_he_cap) || mesh_add_he_oper_ie(sdata, skb) || @@ -237,20 +240,21 @@ Signed-off-by: Ramya Gnanasekar goto free; } -@@ -455,6 +461,10 @@ static void mesh_sta_info_init(struct ie +@@ -457,6 +464,11 @@ static void mesh_sta_info_init(struct ie elems->he_6ghz_capa, - sta); + &sta->deflink); -+ ieee80211_eht_cap_ie_to_sta_eht_cap(sdata, sband, elems->he_cap, elems->he_cap_len, ++ ieee80211_eht_cap_ie_to_sta_eht_cap(sdata, sband, elems->he_cap, ++ elems->he_cap_len, + elems->eht_cap, elems->eht_cap_len, -+ sta); ++ &sta->deflink); + - if (bw != sta->sta.bandwidth) + if (bw != sta->sta.deflink.bandwidth) changed |= IEEE80211_RC_BW_CHANGED; --- a/net/mac80211/util.c +++ b/net/mac80211/util.c -@@ -3070,6 +3070,7 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, +@@ -3141,6 +3141,7 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, ht_oper->primary_chan = ieee80211_frequency_to_channel( chandef->chan->center_freq); switch (chandef->width) { @@ -258,7 +262,7 @@ Signed-off-by: Ramya Gnanasekar case NL80211_CHAN_WIDTH_160: case NL80211_CHAN_WIDTH_80P80: case NL80211_CHAN_WIDTH_80: -@@ -3079,10 +3080,6 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, +@@ -3150,10 +3151,6 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, else ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW; break; @@ -269,7 +273,7 @@ Signed-off-by: Ramya Gnanasekar default: ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE; break; -@@ -3142,19 +3139,31 @@ u8 *ieee80211_ie_build_vht_oper(u8 *pos, +@@ -3213,19 +3210,31 @@ u8 *ieee80211_ie_build_vht_oper(u8 *pos, const struct cfg80211_chan_def *chandef) { struct ieee80211_vht_operation *vht_oper; @@ -305,7 +309,7 @@ Signed-off-by: Ramya Gnanasekar case NL80211_CHAN_WIDTH_160: /* * Convert 160 MHz channel width to new style as interop -@@ -3162,7 +3171,7 @@ u8 *ieee80211_ie_build_vht_oper(u8 *pos, +@@ -3233,7 +3242,7 @@ u8 *ieee80211_ie_build_vht_oper(u8 *pos, */ vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ; vht_oper->center_freq_seg1_idx = vht_oper->center_freq_seg0_idx; @@ -314,7 +318,7 @@ Signed-off-by: Ramya Gnanasekar vht_oper->center_freq_seg0_idx -= 8; else vht_oper->center_freq_seg0_idx += 8; -@@ -3177,10 +3186,6 @@ u8 *ieee80211_ie_build_vht_oper(u8 *pos, +@@ -3248,10 +3257,6 @@ u8 *ieee80211_ie_build_vht_oper(u8 *pos, case NL80211_CHAN_WIDTH_80: vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ; break; @@ -325,7 +329,7 @@ Signed-off-by: Ramya Gnanasekar default: vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_USE_HT; break; -@@ -3198,6 +3203,7 @@ u8 *ieee80211_ie_build_he_oper(u8 *pos, +@@ -3269,6 +3274,7 @@ u8 *ieee80211_ie_build_he_oper(u8 *pos, struct ieee80211_he_6ghz_oper *he_6ghz_op; u32 he_oper_params; u8 ie_len = 1 + sizeof(struct ieee80211_he_operation); @@ -333,7 +337,7 @@ Signed-off-by: Ramya Gnanasekar if (chandef->chan->band == NL80211_BAND_6GHZ) ie_len += sizeof(struct ieee80211_he_6ghz_oper); -@@ -3227,27 +3233,30 @@ u8 *ieee80211_ie_build_he_oper(u8 *pos, +@@ -3298,27 +3304,30 @@ u8 *ieee80211_ie_build_he_oper(u8 *pos, if (chandef->chan->band != NL80211_BAND_6GHZ) goto out; @@ -375,7 +379,7 @@ Signed-off-by: Ramya Gnanasekar case NL80211_CHAN_WIDTH_160: /* Convert 160 MHz channel width to new style as interop * workaround. -@@ -3255,7 +3264,7 @@ u8 *ieee80211_ie_build_he_oper(u8 *pos, +@@ -3326,7 +3335,7 @@ u8 *ieee80211_ie_build_he_oper(u8 *pos, he_6ghz_op->control = IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_160MHZ; he_6ghz_op->ccfs1 = he_6ghz_op->ccfs0; @@ -384,15 +388,16 @@ Signed-off-by: Ramya Gnanasekar he_6ghz_op->ccfs0 -= 8; else he_6ghz_op->ccfs0 += 8; -@@ -3284,6 +3293,51 @@ out: +@@ -3355,6 +3364,59 @@ out: return pos; } +u8 *ieee80211_ie_build_eht_oper(u8 *pos, struct cfg80211_chan_def *chandef) +{ + struct ieee80211_eht_operation *eht_oper; -+ u32 eht_oper_params = 0; -+ u8 ie_len = 1 + sizeof(struct ieee80211_eht_operation); ++ struct ieee80211_eht_operation_info *eht_oper_info; ++ u8 ie_len = 1 + sizeof(struct ieee80211_eht_operation) + ++ sizeof(struct ieee80211_eht_operation_info); + u8 chwidth = 0; + + *pos++ = WLAN_EID_EXTENSION; @@ -402,6 +407,8 @@ Signed-off-by: Ramya Gnanasekar + eht_oper = (struct ieee80211_eht_operation *)pos; + pos += sizeof(struct ieee80211_eht_operation); + ++ eht_oper_info = (struct ieee80211_eht_operation_info *)pos; ++ pos += sizeof(struct ieee80211_eht_operation_info); + + switch (chandef->width) { + case NL80211_CHAN_WIDTH_320: @@ -424,11 +431,16 @@ Signed-off-by: Ramya Gnanasekar + break; + } + -+ eht_oper_params = (eht_oper_params & IEEE80211_EHT_OPER_CHAN_WIDTH) | -+ chwidth; -+ eht_oper->chan_width = cpu_to_le32(eht_oper_params); -+ eht_oper->ccfs = ++ eht_oper->params |= IEEE80211_EHT_OPER_INFO_PRESENT; ++ ++ eht_oper_info->control = chwidth; ++ eht_oper_info->ccfs0 = + ieee80211_frequency_to_channel(chandef->center_freq1); ++ eht_oper_info->ccfs1 = 0; /* How to get this? */ ++ ++ eht_oper->optional[0] = eht_oper_info->control; ++ eht_oper->optional[1] = eht_oper_info->ccfs0; ++ eht_oper->optional[2] = eht_oper_info->ccfs1; + + return pos; +} @@ -436,7 +448,7 @@ Signed-off-by: Ramya Gnanasekar bool ieee80211_chandef_ht_oper(const struct ieee80211_ht_operation *ht_oper, struct cfg80211_chan_def *chandef) { -@@ -4828,7 +4882,7 @@ u8 ieee80211_ie_len_eht_cap(struct ieee8 +@@ -4869,7 +4931,7 @@ u8 ieee80211_ie_len_eht_cap(struct ieee8 n = ieee80211_eht_mcs_nss_size(&he_cap->he_cap_elem, &eht_cap->eht_cap_elem); return 2 + 1 + @@ -447,7 +459,7 @@ Signed-off-by: Ramya Gnanasekar return 0; --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -5720,6 +5720,47 @@ static void ath12k_gen_eht_mcs_nss(struc +@@ -5803,6 +5803,47 @@ static void ath12k_gen_eht_mcs_nss(struc sizeof(struct ieee80211_eht_mcs_nss_supp_bw)); } @@ -495,7 +507,7 @@ Signed-off-by: Ramya Gnanasekar static void ath12k_mac_copy_eht_cap(struct ath12k *ar, struct ath12k_band_cap *band_cap, struct ieee80211_he_cap_elem *he_cap_elem, -@@ -5754,6 +5795,9 @@ static void ath12k_mac_copy_eht_cap(stru +@@ -5837,6 +5878,9 @@ static void ath12k_mac_copy_eht_cap(stru IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ | IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ); break; @@ -507,7 +519,7 @@ Signed-off-by: Ramya Gnanasekar } --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c -@@ -259,6 +259,7 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(s +@@ -269,6 +269,7 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(s case NL80211_CHAN_WIDTH_80: case NL80211_CHAN_WIDTH_80P80: case NL80211_CHAN_WIDTH_160: diff --git a/feeds/ipq95xx/mac80211/patches/qca/627-ath12k-Cleanup-checkpatch-warnings-in-htt-stats.patch b/feeds/ipq95xx/mac80211/patches/qca/627-ath12k-Cleanup-checkpatch-warnings-in-htt-stats.patch index d2c9b70ec..f564a8cef 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/627-ath12k-Cleanup-checkpatch-warnings-in-htt-stats.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/627-ath12k-Cleanup-checkpatch-warnings-in-htt-stats.patch @@ -12,11 +12,9 @@ Signed-off-by: Dinesh Karthikeyan .../net/wireless/ath/ath12k/debugfs_htt_stats.c | 1483 ++++++++++---------- 1 file changed, 741 insertions(+), 742 deletions(-) -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c 2022-05-10 11:57:54.499324987 +0530 -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c 2022-05-10 11:59:17.378665529 +0530 -@@ -83,103 +83,103 @@ +--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c +@@ -83,103 +83,103 @@ static inline void htt_print_tx_pdev_sta len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n", u32_get_bits(mac_id_word, HTT_STATS_MAC_ID)); len += scnprintf(buf + len, buf_len - len, "hw_queued = %u\n", @@ -169,7 +167,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -202,7 +202,6 @@ +@@ -202,7 +202,6 @@ htt_print_tx_pdev_stats_urrn_tlv_v(const len += scnprintf(buf + len, buf_len - len, "HTT_TX_PDEV_STATS_URRN_TLV_V:\n"); @@ -177,7 +175,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->urrn_stats, "urrn_stats", num_elems, "\n\n"); -@@ -298,7 +297,7 @@ +@@ -298,7 +297,7 @@ htt_print_tx_pdev_stats_sifs_hist_tlv_v( u16 num_elems = min_t(u16, (tag_len >> 2), HTT_TX_PDEV_MAX_SIFS_BURST_HIST_STATS); len += scnprintf(buf + len, buf_len - len, @@ -186,7 +184,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->sifs_hist_status, "sifs_hist_status", num_elems, "\n\n"); -@@ -321,22 +320,22 @@ +@@ -321,22 +320,22 @@ htt_print_tx_pdev_stats_tx_ppdu_stats_tl u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; len += scnprintf(buf + len, buf_len - len, @@ -215,7 +213,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -358,9 +357,9 @@ +@@ -358,9 +357,9 @@ htt_print_tx_pdev_stats_tried_mpdu_cnt_h u32 num_elements = ((tag_len - sizeof(htt_stats_buf->hist_bin_size)) >> 2); len += scnprintf(buf + len, buf_len - len, @@ -227,7 +225,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->tried_mpdu_cnt_hist, "tried_mpdu_cnt_hist = %s\n", num_elements, "\n\n"); -@@ -386,9 +385,9 @@ +@@ -386,9 +385,9 @@ static inline void htt_print_hw_stats_in HTT_STATS_MAX_HW_INTR_NAME_LEN); len += scnprintf(buf + len, buf_len - len, "hw_intr_name = %s\n", hw_intr_name); len += scnprintf(buf + len, buf_len - len, "mask = %u\n", @@ -239,7 +237,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -412,9 +411,9 @@ +@@ -412,9 +411,9 @@ htt_print_hw_stats_wd_timeout_tlv(const memcpy(hw_module_name, &(htt_stats_buf->hw_module_name[0]), HTT_STATS_MAX_HW_MODULE_NAME_LEN); len += scnprintf(buf + len, buf_len - len, "hw_module_name = %s\n", @@ -251,7 +249,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -435,27 +434,27 @@ +@@ -435,27 +434,27 @@ static inline void htt_print_hw_stats_pd len += scnprintf(buf + len, buf_len - len, "HTT_HW_STATS_PDEV_ERRS_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n", @@ -290,7 +288,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -476,17 +475,17 @@ +@@ -476,17 +475,17 @@ static inline void htt_print_msdu_flow_s len += scnprintf(buf + len, buf_len - len, "HTT_MSDU_FLOW_STATS_TLV:"); len += scnprintf(buf + len, buf_len - len, "last_update_timestamp = %u\n", @@ -314,7 +312,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb len += scnprintf(buf + len, buf_len - len, "tx_flow_no = %u\n", u32_get_bits(drop_rule, HTT_MSDU_FLOW_STATS_TX_FLOW_NO)); len += scnprintf(buf + len, buf_len - len, "tid_num = %u\n", -@@ -494,13 +493,13 @@ +@@ -494,13 +493,13 @@ static inline void htt_print_msdu_flow_s len += scnprintf(buf + len, buf_len - len, "drop_rule = %u\n", u32_get_bits(drop_rule, HTT_MSDU_FLOW_STATS_DROP_RULE)); len += scnprintf(buf + len, buf_len - len, "last_cycle_enqueue_count = %u\n", @@ -332,7 +330,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -533,25 +532,25 @@ +@@ -533,25 +532,25 @@ static inline void htt_print_tx_tid_stat len += scnprintf(buf + len, buf_len - len, "num_ppdu_in_hwq = %u\n", u32_get_bits(num_ppdu, HTT_TX_TID_STATS_NUM_PPDU_IN_HWQ)); len += scnprintf(buf + len, buf_len - len, "tid_flags = 0x%x\n", @@ -368,7 +366,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -584,29 +583,29 @@ +@@ -584,29 +583,29 @@ static inline void htt_print_tx_tid_stat len += scnprintf(buf + len, buf_len - len, "num_ppdu_in_hwq = %u\n", u32_get_bits(num_ppdu, HTT_TX_TID_STATS_V1_NUM_PPDU_IN_HWQ)); len += scnprintf(buf + len, buf_len - len, "tid_flags = 0x%x\n", @@ -410,7 +408,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -634,13 +633,13 @@ +@@ -634,13 +633,13 @@ static inline void htt_print_rx_tid_stat memcpy(tid_name, &(htt_stats_buf->tid_name[0]), MAX_HTT_TID_NAME); len += scnprintf(buf + len, buf_len - len, "tid_name = %s\n", tid_name); len += scnprintf(buf + len, buf_len - len, "dup_in_reorder = %u\n", @@ -428,7 +426,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -683,33 +682,33 @@ +@@ -683,33 +682,33 @@ static inline void htt_print_peer_stats_ len += scnprintf(buf + len, buf_len - len, "HTT_PEER_STATS_CMN_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "ppdu_cnt = %u\n", @@ -478,7 +476,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -732,9 +731,9 @@ +@@ -732,9 +731,9 @@ static inline void htt_print_peer_detail len += scnprintf(buf + len, buf_len - len, "HTT_PEER_DETAILS_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "peer_type = %u\n", @@ -490,7 +488,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb len += scnprintf(buf + len, buf_len - len, "vdev_id = %u\n", u32_get_bits(ast_idx, HTT_PEER_DETAILS_VDEV_ID)); len += scnprintf(buf + len, buf_len - len, "pdev_id = %u\n", -@@ -750,9 +749,9 @@ +@@ -750,9 +749,9 @@ static inline void htt_print_peer_detail u32_get_bits(mac_addr_16, HTT_MAC_ADDR_H16_0), u32_get_bits(mac_addr_16, HTT_MAC_ADDR_H16_1)); len += scnprintf(buf + len, buf_len - len, "peer_flags = 0x%x\n", @@ -502,7 +500,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -780,11 +779,11 @@ +@@ -780,11 +779,11 @@ static inline void htt_print_tx_peer_rat len += scnprintf(buf + len, buf_len - len, "HTT_TX_PEER_RATE_STATS_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "tx_ldpc = %u\n", @@ -517,7 +515,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->tx_mcs, "tx_mcs = %s\n", HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS, "\n"); -@@ -848,17 +847,17 @@ +@@ -848,17 +847,17 @@ static inline void htt_print_rx_peer_rat len += scnprintf(buf + len, buf_len - len, "HTT_RX_PEER_RATE_STATS_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "nsts = %u\n", @@ -541,7 +539,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_mcs, "rx_mcs", HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS, "\n"); -@@ -873,14 +872,14 @@ +@@ -873,14 +872,14 @@ static inline void htt_print_rx_peer_rat for (j = 0; j < HTT_RX_PEER_STATS_NUM_SPATIAL_STREAMS; j++) { len += scnprintf(buf + len, buf_len - len, "rssi_chain[%u] = %s\n", @@ -558,7 +556,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_gi[j], NULL, HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS, "\n"); } -@@ -914,11 +913,11 @@ +@@ -914,11 +913,11 @@ htt_print_tx_hwq_mu_mimo_sch_stats_tlv(c len += scnprintf(buf + len, buf_len - len, "HTT_TX_HWQ_MU_MIMO_SCH_STATS_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "mu_mimo_sch_posted = %u\n", @@ -573,7 +571,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -938,21 +937,21 @@ +@@ -938,21 +937,21 @@ htt_print_tx_hwq_mu_mimo_mpdu_stats_tlv( u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; len += scnprintf(buf + len, buf_len - len, @@ -603,7 +601,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -1002,45 +1001,45 @@ +@@ -1002,45 +1001,45 @@ htt_print_tx_hwq_stats_cmn_tlv(const voi len += scnprintf(buf + len, buf_len - len, "hwq_id = %u\n", u32_get_bits(mac_id_word, HTT_TX_HWQ_STATS_HWQ_ID)); len += scnprintf(buf + len, buf_len - len, "xretry = %u\n", @@ -669,7 +667,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -1062,9 +1061,9 @@ +@@ -1062,9 +1061,9 @@ htt_print_tx_hwq_difs_latency_stats_tlv_ u16 data_len = min_t(u16, (tag_len >> 2), HTT_TX_HWQ_MAX_DIFS_LATENCY_BINS); len += scnprintf(buf + len, buf_len - len, @@ -681,7 +679,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->difs_latency_hist, "difs_latency_hist", data_len, "\n\n"); -@@ -1091,7 +1090,7 @@ +@@ -1091,7 +1090,7 @@ htt_print_tx_hwq_cmd_result_stats_tlv_v( data_len = min_t(u16, (tag_len >> 2), HTT_TX_HWQ_MAX_CMD_RESULT_STATS); len += scnprintf(buf + len, buf_len - len, @@ -690,7 +688,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->cmd_result, "cmd_result", data_len, "\n\n"); -@@ -1144,7 +1143,7 @@ +@@ -1144,7 +1143,7 @@ htt_print_tx_hwq_fes_result_stats_tlv_v( num_elems = min_t(u16, (tag_len >> 2), HTT_TX_HWQ_MAX_FES_RESULT_STATS); len += scnprintf(buf + len, buf_len - len, @@ -699,7 +697,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->fes_result, "fes_result", num_elems, "\n\n"); -@@ -1170,9 +1169,9 @@ +@@ -1170,9 +1169,9 @@ htt_print_tx_hwq_tried_mpdu_cnt_hist_tlv sizeof(htt_stats_buf->hist_bin_size)) >> 2); len += scnprintf(buf + len, buf_len - len, @@ -711,7 +709,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->tried_mpdu_cnt_hist, "tried_mpdu_cnt_hist", num_elements, "\n\n"); if (len >= buf_len) -@@ -1195,7 +1194,7 @@ +@@ -1195,7 +1194,7 @@ htt_print_tx_hwq_txop_used_cnt_hist_tlv_ u32 num_elements = tag_len >> 2; len += scnprintf(buf + len, buf_len - len, @@ -720,7 +718,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->txop_used_cnt_hist, "txop_used_cnt_hist", num_elements, "\n\n"); -@@ -1223,85 +1222,85 @@ +@@ -1223,85 +1222,85 @@ static inline void htt_print_tx_sounding if (htt_stats_buf->tx_sounding_mode == HTT_TX_AC_SOUNDING_MODE) { len += scnprintf(buf + len, buf_len - len, @@ -874,7 +872,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb } } -@@ -1325,29 +1324,29 @@ +@@ -1325,29 +1324,29 @@ htt_print_tx_selfgen_cmn_stats_tlv(const len += scnprintf(buf + len, buf_len - len, "HTT_TX_SELFGEN_CMN_STATS_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n", @@ -916,7 +914,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -1368,19 +1367,19 @@ +@@ -1368,19 +1367,19 @@ htt_print_tx_selfgen_ac_stats_tlv(const len += scnprintf(buf + len, buf_len - len, "HTT_TX_SELFGEN_AC_STATS_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "ac_su_ndpa = %u\n", @@ -943,7 +941,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -1401,35 +1400,35 @@ +@@ -1401,35 +1400,35 @@ htt_print_tx_selfgen_ax_stats_tlv(const len += scnprintf(buf + len, buf_len - len, "HTT_TX_SELFGEN_AX_STATS_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "ax_su_ndpa = %u\n", @@ -994,7 +992,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -1450,19 +1449,19 @@ +@@ -1450,19 +1449,19 @@ htt_print_tx_selfgen_ac_err_stats_tlv(co len += scnprintf(buf + len, buf_len - len, "HTT_TX_SELFGEN_AC_ERR_STATS_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "ac_su_ndp_err = %u\n", @@ -1021,7 +1019,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -1483,35 +1482,35 @@ +@@ -1483,35 +1482,35 @@ htt_print_tx_selfgen_ax_err_stats_tlv(co len += scnprintf(buf + len, buf_len - len, "HTT_TX_SELFGEN_AX_ERR_STATS_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "ax_su_ndp_err = %u\n", @@ -1072,7 +1070,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -1532,34 +1531,34 @@ +@@ -1532,34 +1531,34 @@ htt_print_tx_pdev_mu_mimo_sch_stats_tlv( u8 i; len += scnprintf(buf + len, buf_len - len, @@ -1117,7 +1115,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -1581,113 +1580,113 @@ +@@ -1581,113 +1580,113 @@ htt_print_tx_pdev_mu_mimo_mpdu_stats_tlv if (htt_stats_buf->tx_sched_mode == HTT_STATS_TX_SCHED_MODE_MU_MIMO_AC) { if (!htt_stats_buf->user_index) len += scnprintf(buf + len, buf_len - len, @@ -1315,7 +1313,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb } } -@@ -1761,7 +1760,7 @@ +@@ -1761,7 +1760,7 @@ htt_print_sched_txq_sched_order_su_tlv_v min_t(u32, (tag_len >> 2), HTT_TX_PDEV_NUM_SCHED_ORDER_LOG); len += scnprintf(buf + len, buf_len - len, @@ -1324,7 +1322,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->sched_order_su, "sched_order_su", sched_order_su_num_entries, "\n\n"); -@@ -1787,7 +1786,7 @@ +@@ -1787,7 +1786,7 @@ htt_print_sched_txq_sched_ineligibility_ u32 sched_ineligibility_num_entries = tag_len >> 2; len += scnprintf(buf + len, buf_len - len, @@ -1333,7 +1331,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->sched_ineligibility, "sched_ineligibility", sched_ineligibility_num_entries, -@@ -1812,54 +1811,54 @@ +@@ -1812,54 +1811,54 @@ htt_print_tx_pdev_stats_sched_per_txq_tl u32 mac_id_word = __le32_to_cpu(htt_stats_buf->mac_id__txq_id__word); len += scnprintf(buf + len, buf_len - len, @@ -1411,7 +1409,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -1880,9 +1879,9 @@ +@@ -1880,9 +1879,9 @@ static inline void htt_print_stats_tx_sc len += scnprintf(buf + len, buf_len - len, "HTT_STATS_TX_SCHED_CMN_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n", @@ -1423,7 +1421,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -1929,7 +1928,7 @@ +@@ -1929,7 +1928,7 @@ htt_print_tx_tqm_list_mpdu_stats_tlv_v(c u16 num_elems = min_t(u16, (tag_len >> 2), HTT_TX_TQM_MAX_LIST_MPDU_END_REASON); len += scnprintf(buf + len, buf_len - len, @@ -1432,7 +1430,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->list_mpdu_end_reason, "list_mpdu_end_reason", num_elems, "\n\n"); -@@ -1978,67 +1977,67 @@ +@@ -1978,67 +1977,67 @@ htt_print_tx_tqm_pdev_stats_tlv_v(const len += scnprintf(buf + len, buf_len - len, "HTT_TX_TQM_PDEV_STATS_TLV_V:\n"); len += scnprintf(buf + len, buf_len - len, "msdu_count = %u\n", @@ -1531,7 +1529,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -2059,21 +2058,21 @@ +@@ -2059,21 +2058,21 @@ static inline void htt_print_tx_tqm_cmn_ len += scnprintf(buf + len, buf_len - len, "HTT_TX_TQM_CMN_STATS_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n", @@ -1561,7 +1559,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -2093,11 +2092,11 @@ +@@ -2093,11 +2092,11 @@ static inline void htt_print_tx_tqm_erro len += scnprintf(buf + len, buf_len - len, "HTT_TX_TQM_ERROR_STATS_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "q_empty_failure = %u\n", @@ -1576,7 +1574,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -2122,27 +2121,27 @@ +@@ -2122,27 +2121,27 @@ static inline void htt_print_tx_tqm_cmdq len += scnprintf(buf + len, buf_len - len, "cmdq_id = %u\n\n", u32_get_bits(mac_id_word, HTT_TX_TQM_CMDQ_STATUS_CMDQ_ID)); len += scnprintf(buf + len, buf_len - len, "sync_cmd = %u\n", @@ -1615,7 +1613,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -2162,19 +2161,19 @@ +@@ -2162,19 +2161,19 @@ htt_print_tx_de_eapol_packets_stats_tlv( u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; len += scnprintf(buf + len, buf_len - len, @@ -1642,7 +1640,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -2194,33 +2193,33 @@ +@@ -2194,33 +2193,33 @@ htt_print_tx_de_classify_failed_stats_tl u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; len += scnprintf(buf + len, buf_len - len, @@ -1690,7 +1688,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -2241,71 +2240,71 @@ +@@ -2241,71 +2240,71 @@ htt_print_tx_de_classify_stats_tlv(const len += scnprintf(buf + len, buf_len - len, "HTT_TX_DE_CLASSIFY_STATS_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "arp_packets = %u\n", @@ -1795,7 +1793,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -2325,23 +2324,23 @@ +@@ -2325,23 +2324,23 @@ htt_print_tx_de_classify_status_stats_tl u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; len += scnprintf(buf + len, buf_len - len, @@ -1828,7 +1826,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -2361,13 +2360,13 @@ +@@ -2361,13 +2360,13 @@ htt_print_tx_de_enqueue_packets_stats_tl u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; len += scnprintf(buf + len, buf_len - len, @@ -1846,7 +1844,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -2387,13 +2386,13 @@ +@@ -2387,13 +2386,13 @@ htt_print_tx_de_enqueue_discard_stats_tl u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; len += scnprintf(buf + len, buf_len - len, @@ -1864,7 +1862,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -2413,15 +2412,15 @@ +@@ -2413,15 +2412,15 @@ static inline void htt_print_tx_de_compl len += scnprintf(buf + len, buf_len - len, "HTT_TX_DE_COMPL_STATS_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "tcl_dummy_frame = %u\n", @@ -1885,7 +1883,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -2443,7 +2442,7 @@ +@@ -2443,7 +2442,7 @@ htt_print_tx_de_fw2wbm_ring_full_hist_tl u16 num_elements = tag_len >> 2; len += scnprintf(buf + len, buf_len - len, @@ -1894,7 +1892,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->fw2wbm_ring_full_hist, "fw2wbm_ring_full_hist", num_elements, "\n\n"); -@@ -2467,19 +2466,19 @@ +@@ -2467,19 +2466,19 @@ htt_print_tx_de_cmn_stats_tlv(const void len += scnprintf(buf + len, buf_len - len, "HTT_TX_DE_CMN_STATS_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n", @@ -1921,7 +1919,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -2503,9 +2502,9 @@ +@@ -2503,9 +2502,9 @@ static inline void htt_print_ring_if_sta len += scnprintf(buf + len, buf_len - len, "HTT_RING_IF_STATS_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "base_addr = %u\n", @@ -1933,7 +1931,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb len += scnprintf(buf + len, buf_len - len, "num_elems = %lu\n", (unsigned long)u32_get_bits(tail_idx, HTT_RING_IF_STATS_NUM_ELEMS)); -@@ -2533,13 +2532,13 @@ +@@ -2533,13 +2532,13 @@ static inline void htt_print_ring_if_sta (unsigned long)u32_get_bits(thresh, HTT_RING_IF_STATS_HWM_THRESH)); len += scnprintf(buf + len, buf_len - len, "overrun_hit_count = %u\n", @@ -1951,7 +1949,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->low_wm_hit_count, "low_wm_hit_count", HTT_STATS_LOW_WM_BINS, "\n"); -@@ -2567,7 +2566,7 @@ +@@ -2567,7 +2566,7 @@ static inline void htt_print_ring_if_cmn len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n", u32_get_bits(mac_id_word, HTT_STATS_MAC_ID)); len += scnprintf(buf + len, buf_len - len, "num_records = %u\n", @@ -1960,7 +1958,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -2610,19 +2609,19 @@ +@@ -2610,19 +2609,19 @@ static inline void htt_print_sfm_client_ len += scnprintf(buf + len, buf_len - len, "HTT_SFM_CLIENT_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "client_id = %u\n", @@ -1987,7 +1985,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -2643,15 +2642,15 @@ +@@ -2643,15 +2642,15 @@ static inline void htt_print_sfm_cmn_tlv len += scnprintf(buf + len, buf_len - len, "HTT_SFM_CMN_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n", @@ -2008,7 +2006,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -2684,13 +2683,13 @@ +@@ -2684,13 +2683,13 @@ static inline void htt_print_sring_stats len += scnprintf(buf + len, buf_len - len, "ep = %u\n", u32_get_bits(mac_id_word, HTT_SRING_STATS_EP)); len += scnprintf(buf + len, buf_len - len, "base_addr_lsb = 0x%x\n", @@ -2026,7 +2024,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb len += scnprintf(buf + len, buf_len - len, "num_avail_words = %u\n", u32_get_bits(avail_words, HTT_SRING_STATS_NUM_AVAIL_WORDS)); len += scnprintf(buf + len, buf_len - len, "num_valid_words = %u\n", -@@ -2726,7 +2725,7 @@ +@@ -2726,7 +2725,7 @@ static inline void htt_print_sring_cmn_t len += scnprintf(buf + len, buf_len - len, "HTT_SRING_CMN_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "num_records = %u\n", @@ -2035,7 +2033,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -2756,40 +2755,40 @@ +@@ -2756,40 +2755,40 @@ static inline void htt_print_tx_pdev_rat len += scnprintf(buf + len, buf_len - len, "HTT_TX_PDEV_RATE_STATS_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n", @@ -2101,7 +2099,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->tx_mcs, "tx_mcs", HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS, "\n"); -@@ -2946,21 +2945,21 @@ +@@ -2946,21 +2945,21 @@ static inline void htt_print_rx_pdev_rat len += scnprintf(buf + len, buf_len - len, "HTT_RX_PDEV_RATE_STATS_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n", @@ -2131,7 +2129,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_mcs, "rx_mcs", HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS, "\n"); -@@ -2974,10 +2973,10 @@ +@@ -2974,10 +2973,10 @@ static inline void htt_print_rx_pdev_rat HTT_RX_PDEV_STATS_NUM_BW_COUNTERS, "\n"); len += scnprintf(buf + len, buf_len - len, "rx_evm_nss_count = %u\n", @@ -2144,7 +2142,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb for (j = 0; j < HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS; j++) { len += scnprintf(buf + len, buf_len - len, -@@ -3020,15 +3019,15 @@ +@@ -3020,15 +3019,15 @@ static inline void htt_print_rx_pdev_rat HTT_RX_PDEV_STATS_NUM_PREAMBLE_TYPES, "\n"); len += scnprintf(buf + len, buf_len - len, "rx_11ax_su_ext = %u\n", @@ -2165,7 +2163,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_legacy_cck_rate, "rx_legacy_cck_rate", -@@ -3039,11 +3038,11 @@ +@@ -3039,11 +3038,11 @@ static inline void htt_print_rx_pdev_rat HTT_RX_PDEV_STATS_NUM_LEGACY_OFDM_STATS, "\n"); len += scnprintf(buf + len, buf_len - len, "rx_active_dur_us_low = %u\n", @@ -2180,7 +2178,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->ul_ofdma_rx_mcs, "ul_ofdma_rx_mcs", -@@ -3051,7 +3050,7 @@ +@@ -3051,7 +3050,7 @@ static inline void htt_print_rx_pdev_rat for (j = 0; j < HTT_RX_PDEV_STATS_NUM_GI_COUNTERS; j++) { len += scnprintf(buf + len, buf_len - len, "ul_ofdma_rx_gi[%u] = %s\n", @@ -2189,7 +2187,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->ul_ofdma_rx_gi[j], NULL, HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS, "\n"); -@@ -3065,9 +3064,9 @@ +@@ -3065,9 +3064,9 @@ static inline void htt_print_rx_pdev_rat HTT_RX_PDEV_STATS_NUM_BW_COUNTERS, "\n"); len += scnprintf(buf + len, buf_len - len, "ul_ofdma_rx_stbc = %u\n", @@ -2201,7 +2199,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_ulofdma_non_data_ppdu, "rx_ulofdma_non_data_ppdu", -@@ -3160,32 +3159,32 @@ +@@ -3160,32 +3159,32 @@ static inline void htt_print_rx_soc_fw_s len += scnprintf(buf + len, buf_len - len, "HTT_RX_SOC_FW_STATS_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "fw_reo_ring_data_msdu = %u\n", @@ -2250,7 +2248,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -3207,7 +3206,7 @@ +@@ -3207,7 +3206,7 @@ htt_print_rx_soc_fw_refill_ring_empty_tl u16 num_elems = min_t(u16, (tag_len >> 2), HTT_RX_STATS_REFILL_MAX_RING); len += scnprintf(buf + len, buf_len - len, @@ -2259,7 +2257,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->refill_ring_empty_cnt, "refill_ring_empty_cnt", num_elems, "\n\n"); -@@ -3233,7 +3232,7 @@ +@@ -3233,7 +3232,7 @@ htt_print_rx_soc_fw_refill_ring_num_rxdm u16 num_elems = min_t(u16, (tag_len >> 2), HTT_RX_RXDMA_MAX_ERR_CODE); len += scnprintf(buf + len, buf_len - len, @@ -2268,7 +2266,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rxdma_err, "rxdma_err", num_elems, "\n\n"); -@@ -3258,7 +3257,7 @@ +@@ -3258,7 +3257,7 @@ htt_print_rx_soc_fw_refill_ring_num_reo_ u16 num_elems = min_t(u16, (tag_len >> 2), HTT_RX_REO_MAX_ERR_CODE); len += scnprintf(buf + len, buf_len - len, @@ -2277,7 +2275,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->reo_err, "reo_err", num_elems, "\n\n"); -@@ -3282,25 +3281,25 @@ +@@ -3282,25 +3281,25 @@ htt_print_rx_reo_debug_stats_tlv_v(const len += scnprintf(buf + len, buf_len - len, "HTT_RX_REO_RESOURCE_STATS_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "sample_id = %u\n", @@ -2313,7 +2311,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -3322,7 +3321,7 @@ +@@ -3322,7 +3321,7 @@ htt_print_rx_soc_fw_refill_ring_num_refi u16 num_elems = min_t(u16, (tag_len >> 2), HTT_RX_STATS_REFILL_MAX_RING); len += scnprintf(buf + len, buf_len - len, @@ -2322,7 +2320,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->refill_ring_num_refill, "refill_ring_num_refill", num_elems, "\n\n"); -@@ -3346,96 +3345,96 @@ +@@ -3346,96 +3345,96 @@ static inline void htt_print_rx_pdev_fw_ len += scnprintf(buf + len, buf_len - len, "HTT_RX_PDEV_FW_STATS_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n", @@ -2466,7 +2464,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -3455,7 +3454,7 @@ +@@ -3455,7 +3454,7 @@ htt_print_rx_pdev_fw_ring_mpdu_err_tlv_v u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; len += scnprintf(buf + len, buf_len - len, @@ -2475,7 +2473,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->fw_ring_mpdu_err, "fw_ring_mpdu_err", HTT_RX_STATS_RXDMA_MAX_ERR, "\n"); -@@ -3504,9 +3503,9 @@ +@@ -3504,9 +3503,9 @@ htt_print_rx_pdev_fw_stats_phy_err_tlv(c len += scnprintf(buf + len, buf_len - len, "HTT_RX_PDEV_FW_STATS_PHY_ERR_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "mac_id__word = %u\n", @@ -2487,7 +2485,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->phy_err, "phy_errs", HTT_STATS_PHY_ERR_MAX, "\n\n"); -@@ -3530,18 +3529,18 @@ +@@ -3530,18 +3529,18 @@ htt_print_pdev_cca_stats_hist_tlv(const len += scnprintf(buf + len, buf_len - len, "\nHTT_PDEV_CCA_STATS_HIST_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "chan_num = %u\n", @@ -2512,7 +2510,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -3561,15 +3560,15 @@ +@@ -3561,15 +3560,15 @@ htt_print_pdev_stats_cca_counters_tlv(co u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; len += scnprintf(buf + len, buf_len - len, @@ -2537,7 +2535,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -3590,30 +3589,30 @@ +@@ -3590,30 +3589,30 @@ static inline void htt_print_hw_stats_wh len += scnprintf(buf + len, buf_len - len, "HTT_HW_STATS_WHAL_TX_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n", @@ -2581,7 +2579,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -3634,9 +3633,9 @@ +@@ -3634,9 +3633,9 @@ htt_print_pdev_stats_twt_sessions_tlv(co len += scnprintf(buf + len, buf_len - len, "HTT_PDEV_STATS_TWT_SESSIONS_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "pdev_id = %u\n", @@ -2593,7 +2591,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -3659,7 +3658,7 @@ +@@ -3659,7 +3658,7 @@ htt_print_pdev_stats_twt_session_tlv(con len += scnprintf(buf + len, buf_len - len, "HTT_PDEV_STATS_TWT_SESSION_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "vdev_id = %u\n", @@ -2602,7 +2600,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb len += scnprintf(buf + len, buf_len - len, "peer_mac = %02x:%02x:%02x:%02x:%02x:%02x\n", u32_get_bits(mac_addr, HTT_MAC_ADDR_L32_0), -@@ -3669,15 +3668,15 @@ +@@ -3669,15 +3668,15 @@ htt_print_pdev_stats_twt_session_tlv(con u32_get_bits(mac_addr_16, HTT_MAC_ADDR_H16_0), u32_get_bits(mac_addr_16, HTT_MAC_ADDR_H16_1)); len += scnprintf(buf + len, buf_len - len, "flow_id_flags = %u\n", @@ -2623,19 +2621,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb if (len >= buf_len) buf[buf_len - 1] = 0; -@@ -3697,9 +3696,9 @@ - u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; - - len += scnprintf(buf + len, buf_len - len, "OBSS Tx success PPDU = %u\n", -- htt_stats_buf->num_obss_tx_ppdu_success); -+ htt_stats_buf->num_obss_tx_ppdu_success); - len += scnprintf(buf + len, buf_len - len, "OBSS Tx failures PPDU = %u\n", -- htt_stats_buf->num_obss_tx_ppdu_failure); -+ htt_stats_buf->num_obss_tx_ppdu_failure); - - if (len >= buf_len) - buf[buf_len - 1] = 0; -@@ -3722,24 +3721,24 @@ +@@ -3722,24 +3721,24 @@ static inline void htt_print_backpressur u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; len += scnprintf(buf + len, buf_len - len, "pdev_id = %u\n", diff --git a/feeds/ipq95xx/mac80211/patches/qca/631-ath12k-Add-support-for-new-htt_stats.patch b/feeds/ipq95xx/mac80211/patches/qca/631-ath12k-Add-support-for-new-htt_stats.patch index 7749900d0..26b4b92d3 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/631-ath12k-Add-support-for-new-htt_stats.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/631-ath12k-Add-support-for-new-htt_stats.patch @@ -36,10 +36,8 @@ Signed-off-by: Dinesh Karthikeyan .../net/wireless/ath/ath12k/debugfs_htt_stats.h | 530 +++++++++++- 3 files changed, 1464 insertions(+), 14 deletions(-) -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/debugfs.h 2022-09-15 16:40:36.310975989 +0530 -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs.h 2022-09-15 16:40:36.298975957 +0530 +--- a/drivers/net/wireless/ath/ath12k/debugfs.h ++++ b/drivers/net/wireless/ath/ath12k/debugfs.h @@ -47,7 +47,15 @@ enum ath12k_dbg_htt_ext_stats_type { ATH12K_DBG_HTT_EXT_STATS_PDEV_RX_RATE_EXT = 30, ATH12K_DBG_HTT_EXT_STATS_PDEV_TX_RATE_TXBF = 31, @@ -56,10 +54,8 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb /* keep this last */ ATH12K_DBG_HTT_NUM_EXT_STATS, -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c 2022-09-15 16:40:36.310975989 +0530 -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c 2022-09-15 16:40:52.183017809 +0530 +--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c @@ -335,6 +335,74 @@ htt_print_tx_pdev_stats_tx_ppdu_stats_tl stats_req->buf_len = len; } @@ -95,11 +91,11 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb + + for (j = 0; j < HTT_STATS_MAX_NUM_MU_PPDU_PER_BURST; j++) { + len += scnprintf(buf + len, buf_len - len, -+ "%s_mu_mimo_num_ppdu_posted_per_burst_nr4 %u:%u,", ++ "%s_mu_mimo_num_ppdu_posted_per_burst_nr4 %u:%u,\n", + hw_mode_prefix[k], j, + htt_stats_buf->mu_mimo_num_ppdu_posted_per_burst[j]); + len += scnprintf(buf + len, buf_len - len, -+ "%s_mu_mimo_num_ppdu_posted_per_burst_nr8 %u:%u,", ++ "%s_mu_mimo_num_ppdu_posted_per_burst_nr8 %u:%u,\n", + hw_mode_prefix[k], j, + htt_stats_buf->mu_mimo_num_ppdu_posted_per_burst + [max + j]); @@ -107,11 +103,11 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb + + for (j = 0; j < HTT_STATS_MAX_NUM_MU_PPDU_PER_BURST; j++) { + len += scnprintf(buf + len, buf_len - len, -+ "%s_mu_mimo_num_ppdu_completed_per_burst_nr4 %u:%u,", ++ "%s_mu_mimo_num_ppdu_completed_per_burst_nr4 %u:%u,\n", + hw_mode_prefix[k], j, + htt_stats_buf->mu_mimo_num_ppdu_completed_per_burst[j]); + len += scnprintf(buf + len, buf_len - len, -+ "%s_mu_mimo_num_ppdu_completed_per_burst_nr8 %u:%u,", ++ "%s_mu_mimo_num_ppdu_completed_per_burst_nr8 %u:%u,\n", + hw_mode_prefix[k], j, + htt_stats_buf->mu_mimo_num_ppdu_completed_per_burst + [max + j]); @@ -119,11 +115,11 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb + + for (j = 0; j < HTT_STATS_MAX_NUM_SCHED_STATUS; j++) { + len += scnprintf(buf + len, buf_len - len, -+ "%s_mu_mimo_num_seq_term_status_nr4 %u:%u,", ++ "%s_mu_mimo_num_seq_term_status_nr4 %u:%u,\n", + hw_mode_prefix[k], j, + htt_stats_buf->mu_mimo_num_seq_term_status[j]); + len += scnprintf(buf + len, buf_len - len, -+ "%s_mu_mimo_num_seq_term_status_nr8 %u:%u,", ++ "%s_mu_mimo_num_seq_term_status_nr8 %u:%u,\n", + hw_mode_prefix[k], j, + htt_stats_buf->mu_mimo_num_seq_term_status + [HTT_STATS_MAX_NUM_SCHED_STATUS + j]); @@ -484,46 +480,20 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb len += scnprintf(buf + len, buf_len - len, "HTT_RX_PDEV_RATE_EXT_STATS_TLV:\n"); len += scnprintf(buf + len, buf_len - len, "rssi_mcast_in_dbm = %d\n", -@@ -3125,10 +3496,14 @@ static inline void htt_print_rx_pdev_rat +@@ -3118,6 +3489,12 @@ static inline void htt_print_rx_pdev_rat + htt_stats_buf->rssi_mgmt_in_dbm); for (j = 0; j < HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS; j++) { - len += scnprintf(buf + len, buf_len - len, -- "\nrx_per_chain_rssi_ext_in_dbm[%u] = ", j); -- PRINT_ARRAY_TO_BUF(buf, len, -- htt_stats_buf->rx_per_chain_rssi_ext_in_dbm[j], -- "NULL", HTT_RX_PDEV_STATS_NUM_BW_EXT_COUNTERS, "\n"); -+ "rx_per_chain_rssi_ext_in_dbm[%u] = ", j); + for (i = 0; i < HTT_RX_PDEV_STATS_NUM_BW_EXT_COUNTERS; i++) + len += scnprintf(buf + len, + buf_len - len, + " %u:%d,", + i, + htt_stats_buf->rx_per_chain_rssi_ext_in_dbm[j][i]); -+ len += scnprintf(buf + len, buf_len - len, "\n"); - } - - PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_mcs_ext, -@@ -3166,6 +3541,19 @@ static inline void htt_print_rx_pdev_rat - "rx_11ax_dl_ofdma_mcs_ext", - HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS_EXT, "\n"); - -+ PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_bw_ext, -+ "rx_bw_ext", -+ HTT_RX_PDEV_STATS_NUM_BW_EXT2_COUNTERS, "\n"); -+ -+ for (j = 0; j < HTT_RX_PDEV_STATS_NUM_REDUCED_CHAN_TYPES; j++) { -+ len += scnprintf(buf + len, buf_len - len, j == 0 ? -+ "\nhalf_rx_bw = " : -+ "\nquarter_rx_bw = "); -+ PRINT_ARRAY_TO_BUF(buf, len, -+ htt_stats_buf->reduced_rx_bw[j], -+ NULL, HTT_RX_PDEV_STATS_NUM_BW_COUNTERS, "\n"); -+ } -+ - PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_su_punctured_mode, - "rx_su_punctured_mode", - HTT_RX_PDEV_STATS_NUM_PUNCTURED_MODE_COUNTERS, "\n\n"); -@@ -4813,6 +5201,156 @@ htt_print_pdev_tx_rate_txbf_stats_tlv(co + len += scnprintf(buf + len, buf_len - len, "\nrssi_chain_ext[%u] = ", j); + PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rssi_chain_ext[j], + NULL, HTT_RX_PDEV_STATS_NUM_BW_EXT_COUNTERS, "\n"); +@@ -4813,6 +5190,156 @@ htt_print_pdev_tx_rate_txbf_stats_tlv(co stats_req->buf_len = len; } @@ -680,7 +650,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb static inline void htt_print_txbf_ofdma_ndpa_stats_tlv(const void *tag_buf, struct debug_htt_stats_req *stats_req) -@@ -5419,6 +5957,73 @@ static inline void htt_print_phy_reset_s +@@ -5419,6 +5946,73 @@ static inline void htt_print_phy_reset_s stats_req->buf_len = len; } @@ -754,7 +724,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb static inline void htt_print_peer_ctrl_path_txrx_stats_tlv(const void *tag_buf, struct debug_htt_stats_req *stats_req) -@@ -5558,6 +6163,279 @@ static inline void htt_print_peer_sched_ +@@ -5558,6 +6152,279 @@ static inline void htt_print_peer_sched_ stats_req->buf_len = len; } @@ -1034,7 +1004,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb static int ath12k_dbg_htt_ext_stats_parse(struct ath12k_base *ab, u16 tag, u16 len, const void *tag_buf, void *user_data) -@@ -5588,6 +6466,10 @@ static int ath12k_dbg_htt_ext_stats_pars +@@ -5588,6 +6455,10 @@ static int ath12k_dbg_htt_ext_stats_pars htt_print_tx_pdev_stats_tx_ppdu_stats_tlv_v(tag_buf, stats_req); break; @@ -1045,7 +1015,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb case HTT_STATS_TX_PDEV_TRIED_MPDU_CNT_HIST_TAG: htt_print_tx_pdev_stats_tried_mpdu_cnt_hist_tlv_v(tag_buf, len, stats_req); -@@ -5688,6 +6570,26 @@ static int ath12k_dbg_htt_ext_stats_pars +@@ -5688,6 +6559,26 @@ static int ath12k_dbg_htt_ext_stats_pars htt_print_tx_pdev_mu_mimo_sch_stats_tlv(tag_buf, stats_req); break; @@ -1072,7 +1042,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb case HTT_STATS_SFM_CMN_TAG: htt_print_sfm_cmn_tlv(tag_buf, stats_req); break; -@@ -5998,6 +6900,11 @@ static int ath12k_dbg_htt_ext_stats_pars +@@ -5998,6 +6889,11 @@ static int ath12k_dbg_htt_ext_stats_pars case HTT_STATS_TXBF_OFDMA_NDPA_STATS_TAG: htt_print_txbf_ofdma_ndpa_stats_tlv(tag_buf, stats_req); break; @@ -1084,7 +1054,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb case HTT_STATS_TXBF_OFDMA_NDP_STATS_TAG: htt_print_txbf_ofdma_ndp_stats_tlv(tag_buf, stats_req); break; -@@ -6007,18 +6914,69 @@ static int ath12k_dbg_htt_ext_stats_pars +@@ -6007,18 +6903,69 @@ static int ath12k_dbg_htt_ext_stats_pars case HTT_STATS_TXBF_OFDMA_STEER_STATS_TAG: htt_print_txbf_ofdma_steer_stats_tlv(tag_buf, stats_req); break; @@ -1154,10 +1124,8 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb case HTT_STATS_PEER_CTRL_PATH_TXRX_STATS_TAG: htt_print_peer_ctrl_path_txrx_stats_tlv(tag_buf, stats_req); break; -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h 2022-09-15 16:40:36.310975989 +0530 -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h 2022-09-15 16:40:36.306975979 +0530 +--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h ++++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h @@ -116,15 +116,33 @@ enum htt_tlv_tag_t { HTT_STATS_PEER_CTRL_PATH_TXRX_STATS_TAG = 101, HTT_STATS_PDEV_CTRL_PATH_TX_STATS_TAG = 102, @@ -1297,24 +1265,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb #define HTT_STATS_TX_SCHED_MODE_MU_MIMO_AC 1 #define HTT_STATS_TX_SCHED_MODE_MU_MIMO_AX 2 #define HTT_STATS_TX_SCHED_MODE_MU_OFDMA_AX 3 -@@ -1615,6 +1706,8 @@ struct htt_tx_pdev_rate_stats_tlv { - */ - #define HTT_RX_PDEV_STATS_NUM_RU_SIZE_160MHZ_CNTRS 7 /* includes 996x2 */ - -+#define HTT_RX_PDEV_STATS_NUM_REDUCED_CHAN_TYPES 2 -+ - enum HTT_RX_PDEV_STATS_BE_RU_SIZE { - HTT_RX_PDEV_STATS_BE_RU_SIZE_26, - HTT_RX_PDEV_STATS_BE_RU_SIZE_52, -@@ -1760,6 +1853,7 @@ struct htt_rx_pdev_rate_ext_stats_tlv { - u32 rx_gi_ext_2[HTT_RX_PDEV_STATS_NUM_GI_COUNTERS] - [HTT_RX_PDEV_STATS_NUM_EXTRA2_MCS_COUNTERS]; - u32 rx_su_punctured_mode[HTT_RX_PDEV_STATS_NUM_PUNCTURED_MODE_COUNTERS]; -+ u32 reduced_rx_bw[HTT_RX_PDEV_STATS_NUM_REDUCED_CHAN_TYPES][HTT_RX_PDEV_STATS_NUM_BW_COUNTERS]; - }; - - /* == RX PDEV/SOC STATS == */ -@@ -2175,20 +2269,6 @@ enum htt_tx_selfgen_sch_tsflag_error_sta +@@ -2175,20 +2266,6 @@ enum htt_tx_selfgen_sch_tsflag_error_sta HTT_TX_SELFGEN_SCH_TSFLAG_ERROR_STATS_VALID = 8 }; @@ -1335,16 +1286,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb /* 0...13,-2,-1 */ #define HTT_TX_PDEV_STATS_NUM_BE_MCS_COUNTERS 16 /* 20,40,80,160,320 MHz */ -@@ -2408,8 +2488,6 @@ static inline int ath12k_debugfs_htt_sta - - #endif /* CPTCFG_ATH12K_DEBUGFS */ - --#define HTT_RX_PDEV_STATS_NUM_REDUCED_CHAN_TYPES 2 -- - struct htt_rx_pdev_ul_mumimo_trig_stats_tlv { - u32 mac_id__word; - u32 rx_11ax_ul_mumimo; -@@ -2758,4 +2836,429 @@ struct htt_peer_sched_stats_tlv { +@@ -2758,4 +2835,429 @@ struct htt_peer_sched_stats_tlv { u32 peer_rx_active_dur_us_high; u32 peer_curr_rate_kbps; }; diff --git a/feeds/ipq95xx/mac80211/patches/qca/634-ath12k-Introduced-module-param-to-En-Dis-FW-segmente.patch b/feeds/ipq95xx/mac80211/patches/qca/634-ath12k-Introduced-module-param-to-En-Dis-FW-segmente.patch index c6f124352..d9af235ef 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/634-ath12k-Introduced-module-param-to-En-Dis-FW-segmente.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/634-ath12k-Introduced-module-param-to-En-Dis-FW-segmente.patch @@ -26,7 +26,7 @@ index 225ad2e..4dba3da 100644 +MODULE_PARM_DESC(fw_mem_seg, "Enable/Disable FW segmentted memory"); + static const struct pci_device_id ath12k_pci_id_table[] = { - { PCI_VDEVICE(QCOM, QCN92XX_DEVICE_ID) }, + { PCI_VDEVICE(QCOM, QCN9274_DEVICE_ID) }, {0} @@ -1306,6 +1311,10 @@ static int ath12k_pci_probe(struct pci_dev *pdev, if (!of_property_read_u32(ab->dev->of_node, "memory-region", &addr)) diff --git a/feeds/ipq95xx/mac80211/patches/qca/635-ath12k-Add-pageable-mem-type-for-qcn9274.patch b/feeds/ipq95xx/mac80211/patches/qca/635-ath12k-Add-pageable-mem-type-for-qcn9274.patch index 9d5618106..65f0b660a 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/635-ath12k-Add-pageable-mem-type-for-qcn9274.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/635-ath12k-Add-pageable-mem-type-for-qcn9274.patch @@ -14,11 +14,9 @@ Signed-off-by: Balamurugan Selvarajan drivers/net/wireless/ath/ath12k/qmi.h | 1 + 4 files changed, 78 insertions(+), 40 deletions(-) -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/core.h -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.h -@@ -924,6 +924,7 @@ struct ath12k_base { +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -926,6 +926,7 @@ struct ath12k_base { u64 fw_soc_drop_count; struct device_node *hremote_node; @@ -26,7 +24,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor /* must be last */ u8 drv_priv[0] __aligned(sizeof(void *)); -@@ -1075,6 +1076,9 @@ void ath12k_core_halt(struct ath12k *ar) +@@ -1074,6 +1075,9 @@ void ath12k_core_halt(struct ath12k *ar) int ath12k_core_resume(struct ath12k_base *ab); int ath12k_core_suspend(struct ath12k_base *ab); int ath12k_config_qdss(struct ath12k_base *ab); @@ -36,10 +34,8 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor const struct firmware *ath12k_core_firmware_request(struct ath12k_base *ab, const char *filename); -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/coredump.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/coredump.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/coredump.c +--- a/drivers/net/wireless/ath/ath12k/coredump.c ++++ b/drivers/net/wireless/ath/ath12k/coredump.c @@ -311,3 +311,21 @@ out: kfree(dump); } @@ -62,11 +58,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor + + return ret; +} -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/qmi.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi.c -@@ -2433,70 +2433,89 @@ static int ath12k_qmi_assign_target_mem_ +--- a/drivers/net/wireless/ath/ath12k/qmi.c ++++ b/drivers/net/wireless/ath/ath12k/qmi.c +@@ -2707,70 +2707,90 @@ static int ath12k_qmi_assign_target_mem_ struct device *dev = ab->dev; struct device_node *hremote_node = NULL; struct resource res; @@ -95,6 +89,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi - return ret; - } + ret = of_address_to_resource(hremote_node, 0, &res); ++ of_node_put(hremote_node); + if (ret) { + ath12k_warn(ab, "qmi fail to get reg from hremote\n"); + return ret; @@ -137,7 +132,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi - return -EINVAL; - } - -- if (ath12k_cold_boot_cal && ab->hw_params.cold_boot_calib) { +- if (ath12k_cold_boot_cal && ab->hw_params->cold_boot_calib) { - if (hremote_node) { - ab->qmi.target_mem[idx].paddr = - res.start + host_ddr_sz; @@ -149,7 +144,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi - ATH12K_QMI_CALDB_ADDRESS; - } + if (ath12k_cold_boot_cal && -+ ab->hw_params.cold_boot_calib) { ++ ab->hw_params->cold_boot_calib) { + ab->qmi.target_mem[idx].v.ioaddr = + ioremap(ab->qmi.target_mem[idx].paddr, + ab->qmi.target_mem[i].size); @@ -167,7 +162,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi + ab->qmi.target_mem[i].type; idx++; break; -+ case PAGEABLE_MEM_TYPE: ++ case PAGEABLE_MEM_REGION_TYPE: + ab->qmi.target_mem[idx].v.ioaddr = + ioremap(ab->qmi.target_mem[idx].paddr, + ab->qmi.target_mem[i].size); @@ -196,11 +191,11 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi ab->qmi.mem_seg_count = idx; return 0; -@@ -3250,7 +3269,14 @@ int ath12k_qmi_pci_alloc_qdss_mem(struct +@@ -3539,7 +3559,14 @@ int ath12k_qmi_pci_alloc_qdss_mem(struct return ret; } -- ab->qmi.qdss_mem[0].paddr = (phys_addr_t)res.start + QMI_Q6_QDSS_ETR_OFFSET_QCN92XX; +- ab->qmi.qdss_mem[0].paddr = (phys_addr_t)res.start + QMI_Q6_QDSS_ETR_OFFSET_QCN9274; + if ((ab->host_ddr_fixed_mem_off + ab->qmi.qdss_mem[0].size) > + ((res.end - res.start) + 1)) { + ath12k_warn(ab, @@ -212,7 +207,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi ab->qmi.qdss_mem[0].v.ioaddr = ioremap(ab->qmi.qdss_mem[0].paddr, ab->qmi.qdss_mem[0].size); -@@ -3258,6 +3284,7 @@ int ath12k_qmi_pci_alloc_qdss_mem(struct +@@ -3547,6 +3574,7 @@ int ath12k_qmi_pci_alloc_qdss_mem(struct ath12k_warn(ab, "WARNING etr-addr remap failed\n"); return -ENOMEM; } @@ -220,23 +215,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi break; default: ath12k_warn(ab, "qmi ignore invalid qdss mem req type %d\n", -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/qmi.h -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi.h -@@ -211,6 +211,7 @@ struct qmi_wlanfw_qdss_trace_mode_resp_m - #define BDF_MEM_REGION_TYPE 0x2 - #define M3_DUMP_REGION_TYPE 0x3 - #define CALDB_MEM_REGION_TYPE 0x4 -+#define PAGEABLE_MEM_TYPE 0x9 - #define QMI_WLANFW_MAX_PLATFORM_NAME_LEN_V01 64 - #define QMI_WLANFW_MAX_HOST_DDR_RANGE_SIZE_V01 3 - #define QDSS_ETR_MEM_REGION_TYPE 0x6 -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/core.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.c -@@ -923,6 +923,8 @@ static void ath12k_core_reset(struct wor +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -902,6 +902,8 @@ static void ath12k_core_reset(struct wor ath12k_dbg(ab, ATH12K_DBG_BOOT, "reset starting\n"); ab->is_reset = true; diff --git a/feeds/ipq95xx/mac80211/patches/qca/635-ath12k-Add-support-to-handle-AWGN-interference-for-6.patch b/feeds/ipq95xx/mac80211/patches/qca/635-ath12k-Add-support-to-handle-AWGN-interference-for-6.patch index 069e21752..8739f23c3 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/635-ath12k-Add-support-to-handle-AWGN-interference-for-6.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/635-ath12k-Add-support-to-handle-AWGN-interference-for-6.patch @@ -28,76 +28,19 @@ Signed-off-by: Aishwarya R --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -708,6 +708,10 @@ struct ath12k { - bool monitor_started; int monitor_vdev_id; u8 twt_enabled; + s8 max_allowed_tx_power; + + struct cfg80211_chan_def awgn_chandef; -+ u32 chan_bw_interference_bitmap; -+ bool awgn_intf_handling_in_prog; ++ u32 chan_bw_interference_bitmap; ++ bool awgn_intf_handling_in_prog; }; struct ath12k_band_cap { ---- a/drivers/net/wireless/ath/ath12k/debugfs.c -+++ b/drivers/net/wireless/ath/ath12k/debugfs.c -@@ -1276,6 +1276,41 @@ static const struct file_operations fops - .open = simple_open - }; - -+static ssize_t ath12k_write_simulate_awgn(struct file *file, -+ const char __user *user_buf, -+ size_t count, loff_t *ppos) -+{ -+ struct ath12k *ar = file->private_data; -+ int ret; -+ u32 chan_bw_interference_bitmap; -+ -+ mutex_lock(&ar->conf_mutex); -+ if (ar->state != ATH12K_STATE_ON) { -+ ret = -ENETDOWN; -+ goto exit; -+ } -+ -+ if (kstrtou32_from_user(user_buf, count, 0, &chan_bw_interference_bitmap)) { -+ mutex_unlock(&ar->conf_mutex); -+ return -EINVAL; -+ } -+ -+ ret = ath12k_wmi_simulate_awgn(ar, chan_bw_interference_bitmap); -+ if (ret) -+ goto exit; -+ -+ ret = count; -+ -+exit: -+ mutex_unlock(&ar->conf_mutex); -+ return ret; -+} -+ -+static const struct file_operations fops_simulate_awgn = { -+ .write = ath12k_write_simulate_awgn, -+ .open = simple_open -+}; -+ - int ath12k_debugfs_register(struct ath12k *ar) - { - struct ath12k_base *ab = ar->ab; -@@ -1315,6 +1350,12 @@ int ath12k_debugfs_register(struct ath12 - &ar->dfs_block_radar_events); - } - -+ if (ar->hw->wiphy->bands[NL80211_BAND_6GHZ]) { -+ debugfs_create_file("simulate_awgn", 0200, -+ ar->debug.debugfs_pdev, ar, -+ &fops_simulate_awgn); -+ } -+ - return 0; - } - --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -1088,7 +1088,7 @@ static int ath12k_mac_monitor_vdev_delet +@@ -1077,7 +1077,7 @@ static int ath12k_mac_monitor_vdev_delet return ret; } @@ -106,7 +49,7 @@ Signed-off-by: Aishwarya R ath12k_mac_get_any_chandef_iter(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *conf, void *data) -@@ -6266,6 +6266,10 @@ static int ath12k_mac_op_start(struct ie +@@ -6349,6 +6349,10 @@ static int ath12k_mac_op_start(struct ie ar->num_peers = 0; ar->allocated_vdev_map = 0; @@ -117,7 +60,7 @@ Signed-off-by: Aishwarya R /* Configure monitor status ring with default rx_filter to get rx status * such as rssi, rx_duration. */ -@@ -6339,6 +6343,10 @@ static void ath12k_mac_op_stop(struct ie +@@ -6423,6 +6427,10 @@ static void ath12k_mac_op_stop(struct ie synchronize_rcu(); atomic_set(&ar->num_pending_mgmt_tx, 0); @@ -128,7 +71,7 @@ Signed-off-by: Aishwarya R } static u8 -@@ -7185,6 +7193,75 @@ ath12k_mac_change_chanctx_fill_iter(void +@@ -7269,6 +7277,75 @@ ath12k_mac_change_chanctx_fill_iter(void arg->next_vif++; } @@ -204,7 +147,7 @@ Signed-off-by: Aishwarya R static void ath12k_mac_update_vif_chan(struct ath12k *ar, struct ieee80211_vif_chanctx_switch *vifs, -@@ -7192,6 +7269,7 @@ ath12k_mac_update_vif_chan(struct ath12k +@@ -7276,6 +7353,7 @@ ath12k_mac_update_vif_chan(struct ath12k { struct ath12k_base *ab = ar->ab; struct ath12k_vif *arvif, *tx_arvif; @@ -212,7 +155,7 @@ Signed-off-by: Aishwarya R int ret; int i; bool monitor_vif = false; -@@ -7199,7 +7277,9 @@ ath12k_mac_update_vif_chan(struct ath12k +@@ -7283,7 +7361,9 @@ ath12k_mac_update_vif_chan(struct ath12k lockdep_assert_held(&ar->conf_mutex); @@ -223,7 +166,7 @@ Signed-off-by: Aishwarya R for (i = 0; i < n_vifs; i++) { struct vdev_up_params params = { 0 }; -@@ -7265,6 +7345,37 @@ ath12k_mac_update_vif_chan(struct ath12k +@@ -7349,6 +7429,37 @@ ath12k_mac_update_vif_chan(struct ath12k if (!ath12k_mac_monitor_stop(ar)) ath12k_mac_monitor_start(ar); } @@ -263,7 +206,7 @@ Signed-off-by: Aishwarya R static void --- a/drivers/net/wireless/ath/ath12k/mac.h +++ b/drivers/net/wireless/ath/ath12k/mac.h -@@ -161,4 +161,7 @@ enum nl80211_he_ru_alloc ath12k_mac_phy_ +@@ -160,4 +160,7 @@ enum nl80211_he_ru_alloc ath12k_mac_phy_ enum nl80211_he_ru_alloc ath12k_mac_he_ru_tones_to_nl80211_he_ru_alloc(u16 ru_tones); enum ath12k_supported_bw ath12k_mac_mac80211_bw_to_ath12k_bw(enum rate_info_bw bw); enum hal_encrypt_type ath12k_dp_tx_get_encrypt_type(u32 cipher); @@ -273,7 +216,7 @@ Signed-off-by: Aishwarya R #endif --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -7774,6 +7774,224 @@ ath12k_wmi_pdev_dfs_radar_detected_event +@@ -7803,6 +7803,224 @@ ath12k_wmi_pdev_dfs_radar_detected_event exit: kfree(tb); } @@ -498,7 +441,7 @@ Signed-off-by: Aishwarya R static void ath12k_wmi_pdev_temperature_event(struct ath12k_base *ab, -@@ -8200,6 +8418,9 @@ static void ath12k_wmi_tlv_op_rx(struct +@@ -8231,6 +8449,9 @@ static void ath12k_wmi_tlv_op_rx(struct case WMI_DIAG_EVENTID: ath12k_wmi_diag_event(ab, skb); break; @@ -508,7 +451,7 @@ Signed-off-by: Aishwarya R case WMI_MUEDCA_PARAMS_CONFIG_EVENTID: ath12k_wmi_pdev_update_muedca_params_status_event(ab, skb); break; -@@ -8343,6 +8564,43 @@ int ath12k_wmi_simulate_radar(struct ath +@@ -8373,6 +8594,43 @@ int ath12k_wmi_simulate_radar(struct ath return ath12k_wmi_send_unit_test_cmd(ar, wmi_ut, dfs_args); } @@ -554,7 +497,7 @@ Signed-off-by: Aishwarya R u32 i; --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -1914,6 +1914,7 @@ enum wmi_tlv_tag { +@@ -1901,6 +1901,7 @@ enum wmi_tlv_tag { WMI_TAG_VDEV_SET_TPC_POWER_CMD = 0x3B5, WMI_TAG_VDEV_CH_POWER_INFO, WMI_TAG_EHT_RATE_SET = 0x3C4, @@ -562,7 +505,7 @@ Signed-off-by: Aishwarya R WMI_TAG_MAX }; -@@ -2144,7 +2145,7 @@ enum wmi_tlv_service { +@@ -2132,7 +2133,7 @@ enum wmi_tlv_service { WMI_TLV_SERVICE_EXT_TPC_REG_SUPPORT = 280, WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281, @@ -571,7 +514,7 @@ Signed-off-by: Aishwarya R WMI_TLV_SERVICE_BE = 289, WMI_MAX_EXT2_SERVICE, }; -@@ -4230,6 +4231,17 @@ struct wmi_dfs_unit_test_arg { +@@ -4183,6 +4184,17 @@ struct wmi_dfs_unit_test_arg { u32 radar_param; }; @@ -587,9 +530,9 @@ Signed-off-by: Aishwarya R +}; + struct wmi_unit_test_cmd { - u32 tlv_header; - u32 vdev_id; -@@ -4803,6 +4815,42 @@ struct wmi_pdev_radar_ev { + __le32 tlv_header; + __le32 vdev_id; +@@ -4753,6 +4765,42 @@ struct wmi_pdev_radar_ev { s32 sidx; } __packed; @@ -632,7 +575,7 @@ Signed-off-by: Aishwarya R struct wmi_pdev_temperature_event { /* temperature value in Celcius degree */ s32 temp; -@@ -5953,6 +6001,7 @@ void ath12k_wmi_fw_stats_fill(struct ath +@@ -5879,6 +5927,7 @@ void ath12k_wmi_fw_stats_fill(struct ath struct ath12k_fw_stats *fw_stats, u32 stats_id, char *buf); int ath12k_wmi_simulate_radar(struct ath12k *ar); @@ -640,3 +583,60 @@ Signed-off-by: Aishwarya R int ath12k_wmi_send_twt_enable_cmd(struct ath12k *ar, u32 pdev_id); int ath12k_wmi_send_twt_disable_cmd(struct ath12k *ar, u32 pdev_id); int ath12k_wmi_send_twt_add_dialog_cmd(struct ath12k *ar, +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -1199,6 +1199,41 @@ static const struct file_operations fops + .open = simple_open + }; + ++static ssize_t ath12k_write_simulate_awgn(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ int ret; ++ u32 chan_bw_interference_bitmap; ++ ++ mutex_lock(&ar->conf_mutex); ++ if (ar->state != ATH12K_STATE_ON) { ++ ret = -ENETDOWN; ++ goto exit; ++ } ++ ++ if (kstrtou32_from_user(user_buf, count, 0, &chan_bw_interference_bitmap)) { ++ mutex_unlock(&ar->conf_mutex); ++ return -EINVAL; ++ } ++ ++ ret = ath12k_wmi_simulate_awgn(ar, chan_bw_interference_bitmap); ++ if (ret) ++ goto exit; ++ ++ ret = count; ++ ++exit: ++ mutex_unlock(&ar->conf_mutex); ++ return ret; ++} ++ ++static const struct file_operations fops_simulate_awgn = { ++ .write = ath12k_write_simulate_awgn, ++ .open = simple_open ++}; ++ + int ath12k_debugfs_register(struct ath12k *ar) + { + struct ath12k_base *ab = ar->ab; +@@ -1238,6 +1273,12 @@ int ath12k_debugfs_register(struct ath12 + &ar->dfs_block_radar_events); + } + ++ if (ar->hw->wiphy->bands[NL80211_BAND_6GHZ]) { ++ debugfs_create_file("simulate_awgn", 0200, ++ ar->debug.debugfs_pdev, ar, ++ &fops_simulate_awgn); ++ } ++ + return 0; + } + diff --git a/feeds/ipq95xx/mac80211/patches/qca/635-ath12k-Comment-out-RX_MPDU_END-and-RX_MSDU_END-stats-parsing.patch b/feeds/ipq95xx/mac80211/patches/qca/635-ath12k-Comment-out-RX_MPDU_END-and-RX_MSDU_END-stats-parsing.patch index 430f13664..895eb904b 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/635-ath12k-Comment-out-RX_MPDU_END-and-RX_MSDU_END-stats-parsing.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/635-ath12k-Comment-out-RX_MPDU_END-and-RX_MSDU_END-stats-parsing.patch @@ -12,16 +12,14 @@ Signed-off-by: Manish Dharanenthiran drivers/net/wireless/ath/ath12k/dp_mon.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/dp_mon.c b/drivers/net/wireless/ath/ath12k/dp_mon.c -index 32c8fb4..bdb1902 100644 --- a/drivers/net/wireless/ath/ath12k/dp_mon.c +++ b/drivers/net/wireless/ath/ath12k/dp_mon.c -@@ -826,22 +826,13 @@ ath12k_dp_mon_rx_parse_status_tlv(struct ath12k_base *ab, +@@ -826,22 +826,15 @@ ath12k_dp_mon_rx_parse_status_tlv(struct break; } case HAL_RX_MSDU_END: { -- struct rx_msdu_end_qcn92xx *msdu_end = -- (struct rx_msdu_end_qcn92xx *)tlv_data; +- struct rx_msdu_end_qcn9274 *msdu_end = +- (struct rx_msdu_end_qcn9274 *)tlv_data; - bool is_first_msdu_in_mpdu; - u16 msdu_end_info; - @@ -33,16 +31,15 @@ index 32c8fb4..bdb1902 100644 - pmon->mon_mpdu->tail = NULL; - } + /* TODO: RX_MSDU TLV will be handled once MON BUF ADDR TLVs are -+ enabled */ ++ * enabled ++ */ break; } case HAL_RX_MPDU_END: - list_add_tail(&pmon->mon_mpdu->list, &pmon->dp_rx_mon_mpdu_list); + /* TODO: RX_MSDU TLV will be handled once MON BUF ADDR TLVs are -+ enabled */ ++ * enabled ++ */ break; case HAL_DUMMY: return HAL_RX_MON_STATUS_BUF_DONE; --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/635-ath12k-fix-enabling-reoq-lut.patch b/feeds/ipq95xx/mac80211/patches/qca/635-ath12k-fix-enabling-reoq-lut.patch index ca4001433..e59fedd1b 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/635-ath12k-fix-enabling-reoq-lut.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/635-ath12k-fix-enabling-reoq-lut.patch @@ -19,17 +19,15 @@ Signed-off-by: Sriram R --- a/drivers/net/wireless/ath/ath12k/dp.c +++ b/drivers/net/wireless/ath/ath12k/dp.c -@@ -1439,8 +1439,7 @@ free: +@@ -1432,6 +1432,7 @@ free: static int ath12k_dp_reoq_lut_setup(struct ath12k_base *ab) { struct ath12k_dp *dp = &ab->dp; -- -- return 0; + u32 val; - dp->reoq_lut.vaddr = dma_alloc_coherent(ab->dev, - DP_REOQ_LUT_SIZE, -@@ -1455,7 +1454,15 @@ static int ath12k_dp_reoq_lut_setup(stru + if (!ab->hw_params->reoq_lut_support) + return 0; +@@ -1449,7 +1450,16 @@ static int ath12k_dp_reoq_lut_setup(stru memset(dp->reoq_lut.vaddr, 0, DP_REOQ_LUT_SIZE); ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_LUT_BASE0, @@ -43,12 +41,13 @@ Signed-off-by: Sriram R + + ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_MAX_PEERID, + HAL_REO_QDESC_MAX_PEERID); - ++ return 0; } + --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -19,6 +19,7 @@ +@@ -17,6 +17,7 @@ #include "dp_tx.h" #include "peer.h" #include "dp_mon.h" @@ -67,7 +66,7 @@ Signed-off-by: Sriram R /* WCSS Relative address */ #define HAL_SEQ_WCSS_UMAC_OFFSET 0x00a00000 #define HAL_SEQ_WCSS_UMAC_REO_REG 0x00a38000 -@@ -132,6 +134,9 @@ struct ath12k_base; +@@ -134,6 +136,9 @@ struct ath12k_base; #define HAL_REO1_SW_COOKIE_CFG1 0x00000054 #define HAL_REO1_QDESC_LUT_BASE0 0x00000058 #define HAL_REO1_QDESC_LUT_BASE1 0x0000005c @@ -77,7 +76,7 @@ Signed-off-by: Sriram R #define HAL_REO1_RING_BASE_LSB 0x000004e4 #define HAL_REO1_RING_BASE_MSB 0x000004e8 #define HAL_REO1_RING_ID 0x000004ec -@@ -308,6 +313,7 @@ struct ath12k_base; +@@ -327,6 +332,7 @@ struct ath12k_base; #define HAL_REO1_SW_COOKIE_CFG_ALIGN BIT(18) #define HAL_REO1_SW_COOKIE_CFG_ENABLE BIT(19) #define HAL_REO1_SW_COOKIE_CFG_GLOBAL_ENABLE BIT(20) @@ -87,7 +86,7 @@ Signed-off-by: Sriram R #define HAL_CE_DST_R0_DEST_CTRL_MAX_LEN GENMASK(15, 0) --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -3849,6 +3849,7 @@ ath12k_wmi_copy_resource_config(struct w +@@ -3893,6 +3893,7 @@ ath12k_wmi_copy_resource_config(struct w wmi_cfg->flags2 = WMI_RSRC_CFG_FLAGS2_CALC_NEXT_DTIM_COUNT_SET; wmi_cfg->host_service_flags &= ~(1 << WMI_RSRC_CFG_HOST_SVC_FLAG_REG_CC_EXT_SUPPORT_BIT); wmi_cfg->host_service_flags |= 1 << WMI_RSRC_CFG_HOST_SVC_FLAG_REG_CC_EXT_SUPPORT_BIT; @@ -97,7 +96,7 @@ Signed-off-by: Sriram R } --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -2395,6 +2395,7 @@ struct wmi_init_cmd { +@@ -2392,6 +2392,7 @@ struct wmi_init_cmd { } __packed; #define WMI_RSRC_CFG_HOST_SVC_FLAG_REG_CC_EXT_SUPPORT_BIT 4 diff --git a/feeds/ipq95xx/mac80211/patches/qca/635-ath12k_diag_support.patch b/feeds/ipq95xx/mac80211/patches/qca/635-ath12k_diag_support.patch index d062e24a9..709e91416 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/635-ath12k_diag_support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/635-ath12k_diag_support.patch @@ -13,139 +13,9 @@ Signed-off-by: Karthik M drivers/net/wireless/ath/ath12k/qmi.h | 34 ++++ 3 files changed, 415 insertions(+) ---- a/drivers/net/wireless/ath/ath12k/debugfs.c -+++ b/drivers/net/wireless/ath/ath12k/debugfs.c -@@ -13,6 +13,7 @@ - #include "dp_tx.h" - #include "debugfs_htt_stats.h" - #include "peer.h" -+#include "qmi.h" - - static struct dentry *debugfs_ath12k; - -@@ -1311,6 +1312,108 @@ static const struct file_operations fops - .open = simple_open - }; - -+static ssize_t ath12k_athdiag_read(struct file *file, -+ char __user *user_buf, -+ size_t count, loff_t *ppos) -+{ -+ struct ath12k *ar = file->private_data; -+ u8 *buf; -+ int ret; -+ -+ if (*ppos <= 0) -+ return -EINVAL; -+ -+ if (!count) -+ return 0; -+ -+ mutex_lock(&ar->conf_mutex); -+ -+ if (ar->state != ATH12K_STATE_ON) { -+ ath12k_warn(ar->ab, "pdev %d not in ON state\n", ar->pdev->pdev_id); -+ mutex_unlock(&ar->conf_mutex); -+ return -ENETDOWN; -+ } -+ -+ buf = vmalloc(count); -+ if (!buf) { -+ ret = -ENOMEM; -+ goto exit; -+ } -+ -+ ret = ath12k_qmi_mem_read(ar->ab, *ppos, buf, count); -+ if (ret < 0) { -+ ath12k_warn(ar->ab, "failed to read address 0x%08x via diagnose window from debugfs: %d\n", -+ (u32)(*ppos), ret); -+ goto exit; -+ } -+ -+ ret = copy_to_user(user_buf, buf, count); -+ if (ret) { -+ ret = -EFAULT; -+ goto exit; -+ } -+ -+ count -= ret; -+ *ppos += count; -+ ret = count; -+exit: -+ vfree(buf); -+ mutex_unlock(&ar->conf_mutex); -+ return ret; -+} -+ -+static ssize_t ath12k_athdiag_write(struct file *file, -+ const char __user *user_buf, -+ size_t count, loff_t *ppos) -+{ -+ struct ath12k *ar = file->private_data; -+ u8 *buf; -+ int ret; -+ -+ if (*ppos <= 0) -+ return -EINVAL; -+ -+ if (!count) -+ return 0; -+ -+ mutex_lock(&ar->conf_mutex); -+ -+ buf = vmalloc(count); -+ if (!buf) { -+ ret = -ENOMEM; -+ goto exit; -+ } -+ -+ ret = copy_from_user(buf, user_buf, count); -+ if (ret) { -+ ret = -EFAULT; -+ goto exit; -+ } -+ -+ ret = ath12k_qmi_mem_write(ar->ab, *ppos, buf, count); -+ if (ret < 0) { -+ ath12k_warn(ar->ab, "failed to write address 0x%08x via diagnose window from debugfs: %d\n", -+ (u32)(*ppos), ret); -+ goto exit; -+ } -+ -+ *ppos += count; -+ ret = count; -+ -+exit: -+ vfree(buf); -+ mutex_unlock(&ar->conf_mutex); -+ return ret; -+} -+ -+static const struct file_operations fops_athdiag = { -+ .read = ath12k_athdiag_read, -+ .write = ath12k_athdiag_write, -+ .open = simple_open, -+ .owner = THIS_MODULE, -+ .llseek = default_llseek, -+}; -+ - int ath12k_debugfs_register(struct ath12k *ar) - { - struct ath12k_base *ab = ar->ab; -@@ -1356,6 +1459,10 @@ int ath12k_debugfs_register(struct ath12 - &fops_simulate_awgn); - } - -+ debugfs_create_file("athdiag", S_IRUSR | S_IWUSR, -+ ar->debug.debugfs_pdev, ar, -+ &fops_athdiag); -+ - return 0; - } - --- a/drivers/net/wireless/ath/ath12k/qmi.c +++ b/drivers/net/wireless/ath/ath12k/qmi.c -@@ -2019,6 +2019,280 @@ struct qmi_elem_info wlfw_ini_resp_msg_v +@@ -2245,6 +2245,280 @@ struct qmi_elem_info wlfw_ini_resp_msg_v }, }; @@ -423,12 +293,12 @@ Signed-off-by: Karthik M + return ret; +} + - int ath12k_qmi_send_qdss_trace_config_download_req(struct ath12k_base *ab, - const u8 *buffer, unsigned int buffer_len) - { + static int ath12k_qmi_send_qdss_trace_config_download_req(struct ath12k_base *ab, + const u8 *buffer, + unsigned int buffer_len) --- a/drivers/net/wireless/ath/ath12k/qmi.h +++ b/drivers/net/wireless/ath/ath12k/qmi.h -@@ -608,6 +608,40 @@ struct ath12k_qmi_event_qdss_trace_save_ +@@ -645,6 +645,40 @@ struct ath12k_qmi_event_qdss_trace_save_ struct qdss_trace_mem_seg mem_seg[QDSS_TRACE_SEG_LEN_MAX]; }; diff --git a/feeds/ipq95xx/mac80211/patches/qca/636-ath12k-enable-vdev-stats-offload.patch b/feeds/ipq95xx/mac80211/patches/qca/636-ath12k-enable-vdev-stats-offload.patch index 5a787fd48..a72856e66 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/636-ath12k-enable-vdev-stats-offload.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/636-ath12k-enable-vdev-stats-offload.patch @@ -45,6 +45,121 @@ Signed-off-by: P Praneesh }; struct ath12k_dbg_htt_stats { +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -1259,8 +1259,7 @@ struct htt_resp_msg { + (((u64)__le32_to_cpu(msg_u32) << 32) | (__le32_to_cpu(msg_l32))) + #define HTT_T2H_VDEV_STATS_PERIODIC_MSG_TYPE GENMASK(7, 0) + #define HTT_T2H_VDEV_STATS_PERIODIC_PDEV_ID GENMASK(15, 8) +-#define HTT_T2H_VDEV_STATS_PERIODIC_NUM_VDEV GENMASK(23, 16) +-#define HTT_T2H_VDEV_STATS_PERIODIC_PAYLOAD_BYTES GENMASK(15, 0) ++#define HTT_T2H_VDEV_STATS_PERIODIC_PAYLOAD_BYTES GENMASK(23, 16) + #define HTT_VDEV_TXRX_STATS_COMMON_TLV 0 + #define HTT_VDEV_TXRX_STATS_HW_STATS_TLV 1 + +@@ -1880,17 +1879,13 @@ struct htt_ext_stats_cfg_params { + u32 cfg3; + }; + +-enum vdev_stats_offload_timer_duration { +- ATH12K_STATS_TIMER_DUR_500MS = 1, +- ATH12K_STATS_TIMER_DUR_1SEC = 2, +- ATH12K_STATS_TIMER_DUR_2SEC = 3, +-}; ++#define ATH12K_STATS_TIMER_DUR_1SEC 1000 + + #define HTT_H2T_VDEV_TXRX_HDR_MSG_TYPE GENMASK(7, 0) + #define HTT_H2T_VDEV_TXRX_HDR_PDEV_ID GENMASK(15, 8) + #define HTT_H2T_VDEV_TXRX_HDR_ENABLE BIT(16) + #define HTT_H2T_VDEV_TXRX_HDR_INTERVAL GENMASK(24, 17) +-#define HTT_H2T_VDEV_TXRX_HDR_RESET_STATS BIT(31) ++#define HTT_H2T_VDEV_TXRX_HDR_RESET_STATS GENMASK(26, 25) + #define HTT_H2T_VDEV_TXRX_LO_BITMASK GENMASK(31, 0) + #define HTT_H2T_VDEV_TXRX_HI_BITMASK GENMASK_ULL(63, 32) + +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -1744,28 +1744,29 @@ static void ath12k_htt_vdev_txrx_stats_h + struct htt_t2h_vdev_txrx_stats_ind *vdev_tlv; + struct htt_t2h_vdev_common_stats_tlv *soc_tlv; + struct ath12k_vif *arvif; ++ const struct htt_tlv *tlv; + u32 *data = (u32 *)skb->data; +- u32 num_vdevs, vdev_id; ++ u32 vdev_id; + u16 payload_bytes, tlv_tag, tlv_len; + +- num_vdevs = u32_get_bits(*data, HTT_T2H_VDEV_STATS_PERIODIC_NUM_VDEV); +- data++; +- + payload_bytes = u32_get_bits(*data, HTT_T2H_VDEV_STATS_PERIODIC_PAYLOAD_BYTES); +- data += 3; ++ data += 4; + + if (payload_bytes > skb->len) + return; + +- while (payload_bytes > 0 && num_vdevs > 0) { +- tlv_tag = u32_get_bits(*data, HAL_TLV_HDR_TAG); +- tlv_len = u32_get_bits(*data, HAL_TLV_HDR_LEN); ++ while (payload_bytes > 0) { ++ tlv = (struct htt_tlv *)data; ++ tlv_tag = u32_get_bits(*data, HTT_TLV_TAG); ++ tlv_len = u32_get_bits(*data, HTT_TLV_LEN); + data++; + +- if (tlv_tag == HTT_VDEV_TXRX_STATS_HW_STATS_TLV) { ++ if (tlv_tag == HTT_STATS_VDEV_TXRX_STATS_HW_STATS_TAG) { + vdev_tlv = (struct htt_t2h_vdev_txrx_stats_ind *)data; + vdev_id = __le32_to_cpu(vdev_tlv->vdev_id); + arvif = ath12k_mac_get_arvif_by_vdev_id(ab, vdev_id); ++ if (!arvif) ++ goto next; + + arvif->vdev_stats.rx_msdu_byte_cnt = + HTT_VDEV_GET_STATS_U64(vdev_tlv->rx_msdu_byte_cnt_lo, +@@ -1794,15 +1795,18 @@ static void ath12k_htt_vdev_txrx_stats_h + arvif->vdev_stats.tx_msdu_ttl_pkt_cnt = + HTT_VDEV_GET_STATS_U64(vdev_tlv->msdu_ttl_cnt_lo, + vdev_tlv->msdu_ttl_cnt_hi); +- } +- +- if (tlv_tag == HTT_VDEV_TXRX_STATS_COMMON_TLV) { ++ } else if (tlv_tag == HTT_STATS_SOC_TXRX_STATS_COMMON_TAG) { + soc_tlv = (struct htt_t2h_vdev_common_stats_tlv *)data; + ab->fw_soc_drop_count = + HTT_VDEV_GET_STATS_U64(soc_tlv->soc_drop_count_lo, + soc_tlv->soc_drop_count_hi); ++ } else { ++ break; + } ++ ++next: + data += tlv_len >> 2; ++ tlv_len += 4; + payload_bytes -= tlv_len; + } + } +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -6611,6 +6611,17 @@ static int ath12k_mac_op_add_interface(s + goto err; + } + ++ /* Send vdev stats offload commands to firmware before first vdev ++ * creation. ie., when num_created_vdevs = 0 ++ */ ++ if (ar->debug.fw_stats.en_vdev_stats_ol && !ar->num_created_vdevs) { ++ ret = ath12k_dp_tx_htt_h2t_vdev_stats_ol_req(ar, 0); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to request vdev stats offload: %d\n", ret); ++ goto err; ++ } ++ } ++ + memset(arvif, 0, sizeof(*arvif)); + + arvif->ar = ar; --- a/drivers/net/wireless/ath/ath12k/debugfs.c +++ b/drivers/net/wireless/ath/ath12k/debugfs.c @@ -329,12 +329,6 @@ static int ath12k_open_vdev_stats(struct @@ -116,7 +231,7 @@ Signed-off-by: P Praneesh static ssize_t ath12k_read_simulate_fw_crash(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) -@@ -1020,6 +1063,8 @@ void ath12k_debugfs_fw_stats_init(struct +@@ -943,6 +1035,8 @@ void ath12k_debugfs_fw_stats_init(struct &fops_vdev_stats); debugfs_create_file("beacon_stats", 0600, fwstats_dir, ar, &fops_bcn_stats); @@ -125,104 +240,9 @@ Signed-off-by: P Praneesh INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs); INIT_LIST_HEAD(&ar->debug.fw_stats.vdevs); ---- a/drivers/net/wireless/ath/ath12k/dp.h -+++ b/drivers/net/wireless/ath/ath12k/dp.h -@@ -1295,8 +1295,7 @@ struct htt_resp_msg { - (((u64)__le32_to_cpu(msg_u32) << 32) | (__le32_to_cpu(msg_l32))) - #define HTT_T2H_VDEV_STATS_PERIODIC_MSG_TYPE GENMASK(7, 0) - #define HTT_T2H_VDEV_STATS_PERIODIC_PDEV_ID GENMASK(15, 8) --#define HTT_T2H_VDEV_STATS_PERIODIC_NUM_VDEV GENMASK(23, 16) --#define HTT_T2H_VDEV_STATS_PERIODIC_PAYLOAD_BYTES GENMASK(15, 0) -+#define HTT_T2H_VDEV_STATS_PERIODIC_PAYLOAD_BYTES GENMASK(23, 16) - #define HTT_VDEV_TXRX_STATS_COMMON_TLV 0 - #define HTT_VDEV_TXRX_STATS_HW_STATS_TLV 1 - -@@ -1918,17 +1917,13 @@ struct htt_ext_stats_cfg_params { - u32 cfg3; - }; - --enum vdev_stats_offload_timer_duration { -- ATH12K_STATS_TIMER_DUR_500MS = 1, -- ATH12K_STATS_TIMER_DUR_1SEC = 2, -- ATH12K_STATS_TIMER_DUR_2SEC = 3, --}; -+#define ATH12K_STATS_TIMER_DUR_1SEC 1000 - - #define HTT_H2T_VDEV_TXRX_HDR_MSG_TYPE GENMASK(7, 0) - #define HTT_H2T_VDEV_TXRX_HDR_PDEV_ID GENMASK(15, 8) - #define HTT_H2T_VDEV_TXRX_HDR_ENABLE BIT(16) - #define HTT_H2T_VDEV_TXRX_HDR_INTERVAL GENMASK(24, 17) --#define HTT_H2T_VDEV_TXRX_HDR_RESET_STATS BIT(31) -+#define HTT_H2T_VDEV_TXRX_HDR_RESET_STATS GENMASK(26, 25) - #define HTT_H2T_VDEV_TXRX_LO_BITMASK GENMASK(31, 0) - #define HTT_H2T_VDEV_TXRX_HI_BITMASK GENMASK_ULL(63, 32) - ---- a/drivers/net/wireless/ath/ath12k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -1726,28 +1726,29 @@ void ath12k_htt_vdev_txrx_stats_handler( - struct htt_t2h_vdev_txrx_stats_ind *vdev_tlv; - struct htt_t2h_vdev_common_stats_tlv *soc_tlv; - struct ath12k_vif *arvif; -+ const struct htt_tlv *tlv; - u32 *data = (u32 *)skb->data; -- u32 num_vdevs, vdev_id; -+ u32 vdev_id; - u16 payload_bytes, tlv_tag, tlv_len; - -- num_vdevs = u32_get_bits(*data, HTT_T2H_VDEV_STATS_PERIODIC_NUM_VDEV); -- data++; -- - payload_bytes = u32_get_bits(*data, HTT_T2H_VDEV_STATS_PERIODIC_PAYLOAD_BYTES); -- data += 3; -+ data += 4; - - if (payload_bytes > skb->len) - return; - -- while (payload_bytes > 0 && num_vdevs > 0) { -- tlv_tag = u32_get_bits(*data, HAL_TLV_HDR_TAG); -- tlv_len = u32_get_bits(*data, HAL_TLV_HDR_LEN); -+ while (payload_bytes > 0) { -+ tlv = (struct htt_tlv *)data; -+ tlv_tag = u32_get_bits(*data, HTT_TLV_TAG); -+ tlv_len = u32_get_bits(*data, HTT_TLV_LEN); - data++; - -- if (tlv_tag == HTT_VDEV_TXRX_STATS_HW_STATS_TLV) { -+ if (tlv_tag == HTT_STATS_VDEV_TXRX_STATS_HW_STATS_TAG) { - vdev_tlv = (struct htt_t2h_vdev_txrx_stats_ind *)data; - vdev_id = __le32_to_cpu(vdev_tlv->vdev_id); - arvif = ath12k_mac_get_arvif_by_vdev_id(ab, vdev_id); -+ if (!arvif) -+ goto next; - - arvif->vdev_stats.rx_msdu_byte_cnt = - HTT_VDEV_GET_STATS_U64(vdev_tlv->rx_msdu_byte_cnt_lo, -@@ -1776,15 +1777,18 @@ void ath12k_htt_vdev_txrx_stats_handler( - arvif->vdev_stats.tx_msdu_ttl_pkt_cnt = - HTT_VDEV_GET_STATS_U64(vdev_tlv->msdu_ttl_cnt_lo, - vdev_tlv->msdu_ttl_cnt_hi); -- } -- -- if (tlv_tag == HTT_VDEV_TXRX_STATS_COMMON_TLV) { -+ } else if (tlv_tag == HTT_STATS_SOC_TXRX_STATS_COMMON_TAG) { - soc_tlv = (struct htt_t2h_vdev_common_stats_tlv *)data; - ab->fw_soc_drop_count = - HTT_VDEV_GET_STATS_U64(soc_tlv->soc_drop_count_lo, - soc_tlv->soc_drop_count_hi); -+ } else { -+ break; - } -+ -+next: - data += tlv_len >> 2; -+ tlv_len += 4; - payload_bytes -= tlv_len; - } - } --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -1183,13 +1183,19 @@ ath12k_dp_tx_htt_h2t_vdev_stats_ol_req(s +@@ -1146,13 +1146,19 @@ ath12k_dp_tx_htt_h2t_vdev_stats_ol_req(s return -ENOMEM; skb_put(skb, len); @@ -243,23 +263,3 @@ Signed-off-by: P Praneesh cmd->hdr |= FIELD_PREP(HTT_H2T_VDEV_TXRX_HDR_RESET_STATS, true); cmd->vdev_id_lo_bitmask = (reset_bitmask & HTT_H2T_VDEV_TXRX_LO_BITMASK); cmd->vdev_id_hi_bitmask = ((reset_bitmask & ---- a/drivers/net/wireless/ath/ath12k/mac.c -+++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -6519,6 +6519,17 @@ static int ath12k_mac_op_add_interface(s - goto err; - } - -+ /* Send vdev stats offload commands to firmware before first vdev -+ * creation. ie., when num_created_vdevs = 0 -+ */ -+ if (ar->debug.fw_stats.en_vdev_stats_ol && !ar->num_created_vdevs) { -+ ret = ath12k_dp_tx_htt_h2t_vdev_stats_ol_req(ar, 0); -+ if (ret) { -+ ath12k_warn(ar->ab, "failed to request vdev stats offload: %d\n", ret); -+ goto err; -+ } -+ } -+ - memset(arvif, 0, sizeof(*arvif)); - - arvif->ar = ar; diff --git a/feeds/ipq95xx/mac80211/patches/qca/637-mac80211-add-RU-puncturing-support-for-mesh.patch b/feeds/ipq95xx/mac80211/patches/qca/637-mac80211-add-RU-puncturing-support-for-mesh.patch index 5ab97aa55..73f37cf1f 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/637-mac80211-add-RU-puncturing-support-for-mesh.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/637-mac80211-add-RU-puncturing-support-for-mesh.patch @@ -52,24 +52,9 @@ Signed-off-by: Rameshkumar Sundaram 10 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 include/net/cfg80211.c -diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h -index 1e23fe6..9f212d7 100644 ---- a/include/linux/ieee80211.h -+++ b/include/linux/ieee80211.h -@@ -2031,7 +2031,7 @@ struct ieee80211_eht_operation { - u8 ccfs; - u8 disable_sub_chan_bitmap_present:1, - reserved2:7; -- u8 disable_subchannel_bitmap[2]; -+ __le16 disable_subchannel_bitmap; - } __packed; - - #define IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT 0x1 -diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h -index a90c205..a4261f5 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h -@@ -957,6 +957,13 @@ cfg80211_chandef_compatible(const struct cfg80211_chan_def *chandef1, +@@ -959,6 +959,13 @@ cfg80211_chandef_compatible(const struct bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef); /** @@ -83,65 +68,35 @@ index a90c205..a4261f5 100644 * cfg80211_chandef_usable - check if secondary channels can be used * @wiphy: the wiphy to validate against * @chandef: the channel definition to check -@@ -1587,6 +1594,7 @@ struct station_parameters { - const u8 *supported_oper_classes; - u8 supported_oper_classes_len; +@@ -1568,6 +1575,7 @@ struct link_station_parameters { + const struct ieee80211_ht_cap *ht_capa; + const struct ieee80211_vht_cap *vht_capa; u8 opmode_notif; + u16 ru_punct_bitmap; bool opmode_notif_used; - int support_p2p_ps; const struct ieee80211_he_cap_elem *he_capa; -diff --git a/include/net/mac80211.h b/include/net/mac80211.h -index bfbb53f..3c14e9b 100644 + u8 he_capa_len; --- a/include/net/mac80211.h +++ b/include/net/mac80211.h -@@ -2166,6 +2166,7 @@ struct ieee80211_sta_txpwr { +@@ -2241,6 +2241,7 @@ struct ieee80211_sta_txpwr { * @he_cap: HE capabilities of this STA * @he_6ghz_capa: on 6 GHz, holds the HE 6 GHz band capabilities * @eht_cap: EHT capabilities of this STA + * @ru_punct_bitmap: RU Puncturing bitmap of this STA - * @max_rx_aggregation_subframes: maximal amount of frames in a single AMPDU - * that this station is allowed to transmit to us. - * Can be modified by driver. -@@ -2207,6 +2208,7 @@ struct ieee80211_sta { + * @bandwidth: current bandwidth the station can receive with + * @rx_nss: in HT/VHT, the maximum number of spatial streams the + * station can receive at the moment, changed by operating mode +@@ -2258,6 +2259,7 @@ struct ieee80211_link_sta { struct ieee80211_sta_he_cap he_cap; struct ieee80211_he_6ghz_capa he_6ghz_capa; struct ieee80211_sta_eht_cap eht_cap; + u16 ru_punct_bitmap; - u16 max_rx_aggregation_subframes; - bool wme; - u8 uapsd_queues; -diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c -index 75858c2..a8d76d2 100644 ---- a/net/mac80211/cfg.c -+++ b/net/mac80211/cfg.c -@@ -1946,14 +1946,19 @@ static int sta_apply_parameters(struct ieee80211_local *local, - (void *)params->he_6ghz_capa, - sta); -- if (params->eht_capa) -+ if (params->eht_capa) { - ieee80211_eht_cap_ie_to_sta_eht_cap(sdata, sband, - (u8 *)params->he_capa, - params->he_capa_len, - params->eht_capa, - params->eht_capa_len, - sta); -- -+ /* 802.11s mesh STA may have different eht punctruing pattern, -+ * update it here so that drivers can use if needed. -+ */ -+ if (ieee80211_vif_is_mesh(&sdata->vif) && params->ru_punct_bitmap) -+ sta->sta.ru_punct_bitmap = params->ru_punct_bitmap; -+ } - if (params->opmode_notif_used) { - /* returned value is only needed for rc update, but the - * rc isn't initialized here yet, so ignore it -diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c -index 5aefebb..09a1f21 100644 + u8 rx_nss; + enum ieee80211_sta_rx_bandwidth bandwidth; --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c -@@ -107,6 +107,11 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, +@@ -107,6 +107,11 @@ bool mesh_matches_local(struct ieee80211 ieee80211_chandef_he_6ghz_oper(sdata, ie->he_operation, ie->eht_operation, &sta_chan_def); @@ -153,35 +108,39 @@ index 5aefebb..09a1f21 100644 if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef, &sta_chan_def)) return false; -diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c -index 2566367..54df484 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c -@@ -425,6 +425,7 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata, +@@ -425,6 +425,7 @@ static void mesh_sta_info_init(struct ie + struct ieee80211_supported_band *sband; u32 rates, basic_rates = 0, changed = 0; - enum ieee80211_sta_rx_bandwidth bw = sta->sta.bandwidth; - struct ieee80211_sta_rx_stats *stats; + enum ieee80211_sta_rx_bandwidth bw = sta->sta.deflink.bandwidth; + struct cfg80211_chan_def eht_chandef; sband = ieee80211_get_sband(sdata); if (!sband) -@@ -477,6 +478,37 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata, - sta->sta.bandwidth = IEEE80211_STA_RX_BW_20; +@@ -477,6 +478,43 @@ static void mesh_sta_info_init(struct ie + sta->sta.deflink.bandwidth = IEEE80211_STA_RX_BW_20; } + /* 802.11s mesh peer may have different eht puncturing pattern, + * update it here so that drivers can use if needed. + */ + if (elems->eht_operation && -+ elems->eht_operation->chan_width >= IEEE80211_EHT_OPER_CHAN_WIDTH_80MHZ && -+ elems->eht_operation->disable_sub_chan_bitmap_present) { ++ (elems->eht_operation->params & IEEE80211_EHT_OPER_INFO_PRESENT) && ++ (u8_get_bits(elems->eht_operation->optional[0], ++ IEEE80211_EHT_OPER_CHAN_WIDTH) >= ++ IEEE80211_EHT_OPER_CHAN_WIDTH_80MHZ) && ++ (elems->eht_operation->params & ++ IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT)) { + struct ieee80211_channel *chan = sdata->vif.bss_conf.chandef.chan; + + cfg80211_chandef_create(&eht_chandef, chan, NL80211_CHAN_NO_HT); -+ eht_chandef.ru_punct_bitmap = elems->eht_operation->disable_subchannel_bitmap; ++ eht_chandef.ru_punct_bitmap = (elems->eht_operation->optional[4] << 8) | ++ elems->eht_operation->optional[3]; + eht_chandef.ru_punct_bitmap_supp_he = 0; + /* Validate Peer's Puncturing Bitmap and reset if invalid */ -+ switch (elems->eht_operation->chan_width) { ++ switch (u8_get_bits(elems->eht_operation->optional[0], ++ IEEE80211_EHT_OPER_CHAN_WIDTH)) { + case IEEE80211_EHT_OPER_CHAN_WIDTH_80MHZ: + eht_chandef.width = NL80211_CHAN_WIDTH_80; + break; @@ -194,38 +153,58 @@ index 2566367..54df484 100644 + default: + eht_chandef.width = NL80211_CHAN_WIDTH_20; + } -+ eht_chandef.center_freq1 = ieee80211_channel_to_frequency(elems->eht_operation->ccfs, ++ eht_chandef.center_freq1 = ieee80211_channel_to_frequency(elems->eht_operation->optional[1], + chan->band); + if (cfg80211_ru_punct_bitmap_valid(&eht_chandef)) -+ sta->sta.ru_punct_bitmap = elems->eht_operation->disable_subchannel_bitmap; ++ sta->sta.deflink.ru_punct_bitmap = eht_chandef.ru_punct_bitmap; + } + if (!test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) rate_control_rate_init(sta); else -diff --git a/net/mac80211/util.c b/net/mac80211/util.c -index 6dbfc19..016bd55 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c -@@ -3323,6 +3323,13 @@ u8 *ieee80211_ie_build_eht_oper(u8 *pos, struct cfg80211_chan_def *chandef) - eht_oper->ccfs = - ieee80211_frequency_to_channel(chandef->center_freq1); +@@ -3372,6 +3372,9 @@ u8 *ieee80211_ie_build_eht_oper(u8 *pos, + sizeof(struct ieee80211_eht_operation_info); + u8 chwidth = 0; + ++ if (chandef->ru_punct_bitmap) ++ ie_len += 2; ++ + *pos++ = WLAN_EID_EXTENSION; + *pos++ = ie_len; + *pos++ = WLAN_EID_EXT_EHT_OPERATION; +@@ -3380,7 +3383,8 @@ u8 *ieee80211_ie_build_eht_oper(u8 *pos, + pos += sizeof(struct ieee80211_eht_operation); + + eht_oper_info = (struct ieee80211_eht_operation_info *)pos; +- pos += sizeof(struct ieee80211_eht_operation_info); ++ pos += sizeof(struct ieee80211_eht_operation_info) + ++ chandef->ru_punct_bitmap ? 2 : 0; + + switch (chandef->width) { + case NL80211_CHAN_WIDTH_320: +@@ -3414,6 +3418,17 @@ u8 *ieee80211_ie_build_eht_oper(u8 *pos, + eht_oper->optional[1] = eht_oper_info->ccfs0; + eht_oper->optional[2] = eht_oper_info->ccfs1; + if (chandef->ru_punct_bitmap) { -+ eht_oper->disable_sub_chan_bitmap_present = 1; -+ eht_oper->disable_subchannel_bitmap = chandef->ru_punct_bitmap; -+ } else { -+ eht_oper->disable_sub_chan_bitmap_present = 0; -+ eht_oper->disable_subchannel_bitmap = 0; ++ eht_oper->params |= ++ IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT; ++ ++ eht_oper_info->optional[0] = chandef->ru_punct_bitmap && 0x00FF; ++ eht_oper_info->optional[1] = chandef->ru_punct_bitmap >> 8; ++ ++ eht_oper->optional[3] = eht_oper_info->optional[0]; ++ eht_oper->optional[4] = eht_oper_info->optional[1]; + } ++ return pos; } -diff --git a/net/wireless/chan.c b/net/wireless/chan.c -index 6389861..261e104 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c -@@ -292,6 +292,7 @@ bool cfg80211_ru_punct_bitmap_valid(const struct cfg80211_chan_def *chandef) +@@ -292,6 +292,7 @@ bool cfg80211_ru_punct_bitmap_valid(cons return true; } @@ -233,21 +212,39 @@ index 6389861..261e104 100644 bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef) { -diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c -index f532a13..b430664 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c -@@ -7329,6 +7329,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) +@@ -7546,6 +7546,10 @@ static int nl80211_new_station(struct sk nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]); } + if (info->attrs[NL80211_ATTR_RU_PUNCT_BITMAP]) -+ params.ru_punct_bitmap = ++ params.link_sta_params.ru_punct_bitmap = + nla_get_u16(info->attrs[NL80211_ATTR_RU_PUNCT_BITMAP]); + if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) params.plink_action = nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); --- -2.7.4 - +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1805,13 +1805,19 @@ static int sta_link_apply_parameters(str + (void *)params->he_6ghz_capa, + link_sta); + +- if (params->eht_capa) ++ if (params->eht_capa) { + ieee80211_eht_cap_ie_to_sta_eht_cap(sdata, sband, + (u8 *)params->he_capa, + params->he_capa_len, + params->eht_capa, + params->eht_capa_len, + link_sta); ++ /* 802.11s mesh STA may have different eht punctruing pattern, ++ * update it here so that drivers can use if needed. ++ */ ++ if (ieee80211_vif_is_mesh(&sdata->vif) && params->ru_punct_bitmap) ++ link_sta->pub->ru_punct_bitmap = params->ru_punct_bitmap; ++ } + + if (params->opmode_notif_used) { + /* returned value is only needed for rc update, but the diff --git a/feeds/ipq95xx/mac80211/patches/qca/638-01-ath12k-Add-support-for-Green-AP.patch b/feeds/ipq95xx/mac80211/patches/qca/638-01-ath12k-Add-support-for-Green-AP.patch index e03ddce8c..dc676b15f 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/638-01-ath12k-Add-support-for-Green-AP.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/638-01-ath12k-Add-support-for-Green-AP.patch @@ -17,19 +17,9 @@ Signed-off-by: Sivashankari Madhavan drivers/net/wireless/ath/ath12k/wmi.h | 7 ++++ 7 files changed, 101 insertions(+) ---- a/drivers/net/wireless/ath/ath12k/core.c -+++ b/drivers/net/wireless/ath/ath12k/core.c -@@ -67,6 +67,7 @@ static const struct ath12k_hw_params ath - .hal_desc_sz = sizeof(struct hal_rx_desc_qcn92xx), - .num_tcl_banks = 48, - .fix_l1ss = false, -+ .supports_ap_ps = true, - }, - }; - --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h -@@ -566,6 +566,11 @@ struct ath12k_per_peer_tx_stats { +@@ -532,6 +532,11 @@ struct ath12k_per_peer_tx_stats { bool is_ampdu; }; @@ -41,28 +31,29 @@ Signed-off-by: Sivashankari Madhavan enum ath12k_fw_recovery_option { ATH12K_FW_RECOVERY_DISABLE = 0, ATH12K_FW_RECOVERY_ENABLE_AUTO, /* Automatically recover after FW assert */ -@@ -709,6 +714,8 @@ struct ath12k { - bool monitor_started; +@@ -669,6 +674,8 @@ struct ath12k { int monitor_vdev_id; u8 twt_enabled; + s8 max_allowed_tx_power; + bool ap_ps_enabled; + enum ath12k_ap_ps_state ap_ps_state; struct cfg80211_chan_def awgn_chandef; - u32 chan_bw_interference_bitmap; + u32 chan_bw_interference_bitmap; --- a/drivers/net/wireless/ath/ath12k/hw.h +++ b/drivers/net/wireless/ath/ath12k/hw.h -@@ -165,6 +165,7 @@ struct ath12k_hw_params { - u32 hal_desc_sz; - u32 num_tcl_banks; +@@ -193,6 +193,8 @@ struct ath12k_hw_params { + unsigned int qdss_config_len; + bool fix_l1ss; ++ + bool supports_ap_ps; }; - struct ath12k_hw_ops { + /* BRINGUP: move to dp.h */ --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -3787,6 +3787,11 @@ static void ath12k_mac_op_bss_info_chang +@@ -3829,6 +3829,11 @@ static void ath12k_mac_op_bss_info_chang changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP) ath12k_mac_fils_discovery(arvif, info); @@ -74,16 +65,16 @@ Signed-off-by: Sivashankari Madhavan mutex_unlock(&ar->conf_mutex); } -@@ -4809,6 +4814,8 @@ static int ath12k_mac_station_add(struct +@@ -4849,6 +4854,8 @@ static int ath12k_mac_station_add(struct ath12k_dbg(ab, ATH12K_DBG_MAC, "Added peer: %pM for VDEV: %d\n", sta->addr, arvif->vdev_id); + ath12k_mac_ap_ps_recalc(ar); + - if (ath12k_debugfs_is_extd_tx_stats_enabled(ar)) { - arsta->tx_stats = kzalloc(sizeof(*arsta->tx_stats), GFP_KERNEL); - if (!arsta->tx_stats) { -@@ -4920,6 +4927,7 @@ static int ath12k_mac_op_sta_state(struc + if (ieee80211_vif_is_mesh(vif)) { + ret = ath12k_wmi_set_peer_param(ar, sta->addr, + arvif->vdev_id, +@@ -4943,6 +4950,7 @@ static int ath12k_mac_op_sta_state(struc kfree(arsta->rx_stats); arsta->rx_stats = NULL; @@ -91,7 +82,7 @@ Signed-off-by: Sivashankari Madhavan } else if (old_state == IEEE80211_STA_AUTH && new_state == IEEE80211_STA_ASSOC && (vif->type == NL80211_IFTYPE_AP || -@@ -6715,6 +6723,8 @@ static int ath12k_mac_op_add_interface(s +@@ -6771,6 +6779,8 @@ static int ath12k_mac_op_add_interface(s ath12k_dp_vdev_tx_attach(ar, arvif); @@ -100,7 +91,7 @@ Signed-off-by: Sivashankari Madhavan if (vif->type != NL80211_IFTYPE_MONITOR && ar->monitor_conf_enabled) ath12k_mac_monitor_vdev_create(ar); -@@ -6856,6 +6866,7 @@ err_vdev_del: +@@ -6912,6 +6922,7 @@ err_vdev_del: /* Recalc txpower for remaining vdev */ ath12k_mac_txpower_recalc(ar); @@ -108,7 +99,7 @@ Signed-off-by: Sivashankari Madhavan clear_bit(ATH12K_FLAG_MONITOR_ENABLED, &ar->monitor_flags); ath12k_debugfs_remove_interface(arvif); -@@ -9056,6 +9067,39 @@ exit: +@@ -9115,6 +9126,39 @@ exit: return ret; } @@ -148,11 +139,11 @@ Signed-off-by: Sivashankari Madhavan static void ath12k_mac_op_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, -@@ -9533,6 +9577,9 @@ static int __ath12k_mac_register(struct +@@ -9601,6 +9645,9 @@ static int __ath12k_mac_register(struct ieee80211_hw_set(ar->hw, USES_RSS); } -+ if (ar->ab->hw_params.supports_ap_ps) ++ if (ar->ab->hw_params->supports_ap_ps) + ieee80211_hw_set(ar->hw, SUPPORTS_AP_PS); + ar->hw->wiphy->features |= NL80211_FEATURE_STATIC_SMPS; @@ -160,7 +151,7 @@ Signed-off-by: Sivashankari Madhavan --- a/drivers/net/wireless/ath/ath12k/mac.h +++ b/drivers/net/wireless/ath/ath12k/mac.h -@@ -128,6 +128,7 @@ struct ath12k_generic_iter { +@@ -131,6 +131,7 @@ struct ath12k_generic_iter { extern const struct htt_rx_ring_tlv_filter ath12k_mac_mon_status_filter_default; @@ -170,7 +161,7 @@ Signed-off-by: Sivashankari Madhavan int ath12k_mac_register(struct ath12k_base *ab); --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -8729,3 +8729,35 @@ int ath12k_wmi_wow_enable(struct ath12k +@@ -8745,3 +8745,35 @@ int ath12k_wmi_wow_enable(struct ath12k return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_CMDID); } @@ -208,8 +199,8 @@ Signed-off-by: Sivashankari Madhavan +} --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -3253,6 +3253,12 @@ struct wmi_fwtest_set_param_cmd_param { - u32 param_value; +@@ -3218,6 +3218,12 @@ enum wmi_bss_chan_info_req_type { + WMI_BSS_SURVEY_REQ_TYPE_READ_CLEAR, }; +struct wmi_pdev_ap_ps_cmd { @@ -219,9 +210,9 @@ Signed-off-by: Sivashankari Madhavan +}; + struct wmi_pdev_set_param_cmd { - u32 tlv_header; - u32 pdev_id; -@@ -6046,6 +6052,7 @@ int ath12k_wmi_probe_resp_tmpl(struct at + __le32 tlv_header; + __le32 pdev_id; +@@ -5971,6 +5977,7 @@ int ath12k_wmi_probe_resp_tmpl(struct at struct sk_buff *tmpl); int ath12k_wmi_set_hw_mode(struct ath12k_base *ab, enum wmi_host_hw_mode_config_type mode); @@ -229,3 +220,23 @@ Signed-off-by: Sivashankari Madhavan int ath12k_wmi_wow_host_wakeup_ind(struct ath12k *ar); int ath12k_wmi_wow_enable(struct ath12k *ar); int ath12k_wmi_send_vdev_set_tpc_power(struct ath12k *ar, +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -877,6 +877,8 @@ static const struct ath12k_hw_params ath + .qdss_config_len = 0, + + .fix_l1ss = false, ++ ++ .supports_ap_ps = true, + }, + { + .name = "wcn7850 hw2.0", +@@ -938,6 +940,8 @@ static const struct ath12k_hw_params ath + .qdss_config_len = sizeof(ath12k_hw_qdss_config_wcn7850), + + .fix_l1ss = false, ++ ++ .supports_ap_ps = true, + }, + }; + diff --git a/feeds/ipq95xx/mac80211/patches/qca/638-02-cfg80211-Add-the-support-for-Green-AP.patch b/feeds/ipq95xx/mac80211/patches/qca/638-02-cfg80211-Add-the-support-for-Green-AP.patch index f3276edb3..88c6ab02a 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/638-02-cfg80211-Add-the-support-for-Green-AP.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/638-02-cfg80211-Add-the-support-for-Green-AP.patch @@ -14,11 +14,9 @@ Signed-off-by: Sivashankari Madhavan net/wireless/trace.h | 2 +- 5 files changed, 41 insertions(+), 19 deletions(-) -Index: backports-20220404-5.4.164-f40abb4788/include/net/cfg80211.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/include/net/cfg80211.h -+++ backports-20220404-5.4.164-f40abb4788/include/net/cfg80211.h -@@ -1401,6 +1401,8 @@ struct cfg80211_ap_settings { +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -1409,6 +1409,8 @@ struct cfg80211_ap_settings { struct cfg80211_unsol_bcast_probe_resp unsol_bcast_probe_resp; struct cfg80211_mbssid_config mbssid_config; enum nl80211_beacon_tx_mode beacon_tx_mode; @@ -27,7 +25,7 @@ Index: backports-20220404-5.4.164-f40abb4788/include/net/cfg80211.h }; /** -@@ -3919,8 +3921,8 @@ struct mgmt_frame_regs { +@@ -4009,8 +4011,8 @@ struct mgmt_frame_regs { * @set_rekey_data: give the data necessary for GTK rekeying to the driver * * @start_ap: Start acting in AP mode defined by the parameters. @@ -38,22 +36,20 @@ Index: backports-20220404-5.4.164-f40abb4788/include/net/cfg80211.h * @stop_ap: Stop being an AP, including stopping beaconing. * * @add_station: Add a new station. -@@ -4273,8 +4275,8 @@ struct cfg80211_ops { +@@ -4373,8 +4375,8 @@ struct cfg80211_ops { int (*start_ap)(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ap_settings *settings); - int (*change_beacon)(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_ap_settings *info); + int (*update_ap)(struct wiphy *wiphy, struct net_device *dev, -+ struct cfg80211_ap_settings *settings); - int (*stop_ap)(struct wiphy *wiphy, struct net_device *dev); ++ struct cfg80211_ap_settings *settings); + int (*stop_ap)(struct wiphy *wiphy, struct net_device *dev, + unsigned int link_id); - -Index: backports-20220404-5.4.164-f40abb4788/include/uapi/linux/nl80211.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/include/uapi/linux/nl80211.h -+++ backports-20220404-5.4.164-f40abb4788/include/uapi/linux/nl80211.h -@@ -376,11 +376,13 @@ +--- a/include/uapi/linux/nl80211.h ++++ b/include/uapi/linux/nl80211.h +@@ -387,11 +387,13 @@ * or %NL80211_ATTR_MAC. * * @NL80211_CMD_GET_BEACON: (not used) @@ -70,7 +66,7 @@ Index: backports-20220404-5.4.164-f40abb4788/include/uapi/linux/nl80211.h * @NL80211_CMD_START_AP: Start AP operation on an AP interface, parameters * are like for %NL80211_CMD_SET_BEACON, and additionally parameters that * do not change are used, these include %NL80211_ATTR_BEACON_INTERVAL, -@@ -1274,7 +1276,8 @@ enum nl80211_commands { +@@ -1310,7 +1312,8 @@ enum nl80211_commands { NL80211_CMD_DEL_KEY, NL80211_CMD_GET_BEACON, @@ -80,19 +76,19 @@ Index: backports-20220404-5.4.164-f40abb4788/include/uapi/linux/nl80211.h NL80211_CMD_START_AP, NL80211_CMD_NEW_BEACON = NL80211_CMD_START_AP, NL80211_CMD_STOP_AP, -@@ -2516,6 +2519,11 @@ enum nl80211_commands { +@@ -2561,6 +2564,11 @@ enum nl80211_commands { * association request when used with NL80211_CMD_NEW_STATION). Can be set * only if %NL80211_STA_FLAG_WME is set. * + * @NL80211_ATTR_AP_PS: enable/disable AP power save. -+ * This attribute type is u8 and valid range is 0 to 1. -+ * 0 for disable AP power save mode. -+ * 1 for enable AP power save mode. -+ * ++ * This attribute type is u8 and valid range is 0 to 1. ++ * 0 for disable AP power save mode. ++ * 1 for enable AP power save mode. ++ * * @NL80211_ATTR_FTM_RESPONDER: nested attribute which user-space can include * in %NL80211_CMD_START_AP or %NL80211_CMD_SET_BEACON for fine timing * measurement (FTM) responder functionality and containing parameters as -@@ -3249,6 +3257,8 @@ enum nl80211_attrs { +@@ -3328,6 +3336,8 @@ enum nl80211_attrs { NL80211_ATTR_RU_PUNCT_BITMAP, @@ -101,11 +97,9 @@ Index: backports-20220404-5.4.164-f40abb4788/include/uapi/linux/nl80211.h /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, -Index: backports-20220404-5.4.164-f40abb4788/net/wireless/nl80211.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/net/wireless/nl80211.c -+++ backports-20220404-5.4.164-f40abb4788/net/wireless/nl80211.c -@@ -835,6 +835,7 @@ static const struct nla_policy nl80211_p +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -855,6 +855,7 @@ static const struct nla_policy nl80211_p NLA_POLICY_MAX(NLA_U8, NL80211_RU_PUNCT_SUPP_BW_320), [NL80211_ATTR_RU_PUNCT_SUPP_HE] = { .type = NLA_FLAG }, [NL80211_ATTR_RU_PUNCT_BITMAP] = { .type = NLA_U16 }, @@ -113,7 +107,7 @@ Index: backports-20220404-5.4.164-f40abb4788/net/wireless/nl80211.c }; /* policy for the key attributes */ -@@ -6163,19 +6164,20 @@ out: +@@ -6296,7 +6297,7 @@ out: return err; } @@ -121,7 +115,8 @@ Index: backports-20220404-5.4.164-f40abb4788/net/wireless/nl80211.c +static int nl80211_update_ap(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev = info->user_ptr[0]; - struct net_device *dev = info->user_ptr[1]; + unsigned int link_id = nl80211_link_id(info->attrs); +@@ -6304,12 +6305,13 @@ static int nl80211_set_beacon(struct sk_ struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_ap_settings *params; int err; @@ -135,8 +130,8 @@ Index: backports-20220404-5.4.164-f40abb4788/net/wireless/nl80211.c + if (!rdev->ops->update_ap) return -EOPNOTSUPP; - if (!wdev->beacon_interval) -@@ -6185,8 +6187,16 @@ static int nl80211_set_beacon(struct sk_ + if (!wdev->links[link_id].ap.beacon_interval) +@@ -6319,8 +6321,16 @@ static int nl80211_set_beacon(struct sk_ if (!params) return -ENOMEM; @@ -154,7 +149,7 @@ Index: backports-20220404-5.4.164-f40abb4788/net/wireless/nl80211.c goto out; if (info->attrs[NL80211_ATTR_FILS_DISCOVERY]) { -@@ -6207,7 +6217,7 @@ static int nl80211_set_beacon(struct sk_ +@@ -6332,7 +6342,7 @@ static int nl80211_set_beacon(struct sk_ } wdev_lock(wdev); @@ -163,8 +158,8 @@ Index: backports-20220404-5.4.164-f40abb4788/net/wireless/nl80211.c wdev_unlock(wdev); out: -@@ -16029,10 +16039,10 @@ static const struct genl_small_ops nl802 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, +@@ -16790,10 +16800,10 @@ static const struct genl_small_ops nl802 + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { - .cmd = NL80211_CMD_SET_BEACON, @@ -173,14 +168,12 @@ Index: backports-20220404-5.4.164-f40abb4788/net/wireless/nl80211.c .flags = GENL_UNS_ADMIN_PERM, - .doit = nl80211_set_beacon, + .doit = nl80211_update_ap, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_MLO_VALID_LINK_ID), }, - { -Index: backports-20220404-5.4.164-f40abb4788/net/wireless/rdev-ops.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/net/wireless/rdev-ops.h -+++ backports-20220404-5.4.164-f40abb4788/net/wireless/rdev-ops.h -@@ -160,13 +160,13 @@ static inline int rdev_start_ap(struct c +--- a/net/wireless/rdev-ops.h ++++ b/net/wireless/rdev-ops.h +@@ -165,13 +165,13 @@ static inline int rdev_start_ap(struct c return ret; } @@ -197,12 +190,10 @@ Index: backports-20220404-5.4.164-f40abb4788/net/wireless/rdev-ops.h trace_rdev_return_int(&rdev->wiphy, ret); return ret; } -Index: backports-20220404-5.4.164-f40abb4788/net/wireless/trace.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/net/wireless/trace.h -+++ backports-20220404-5.4.164-f40abb4788/net/wireless/trace.h -@@ -595,7 +595,7 @@ TRACE_EVENT(rdev_start_ap, - __entry->inactivity_timeout) +--- a/net/wireless/trace.h ++++ b/net/wireless/trace.h +@@ -597,7 +597,7 @@ TRACE_EVENT(rdev_start_ap, + __entry->inactivity_timeout, __entry->link_id) ); -TRACE_EVENT(rdev_change_beacon, diff --git a/feeds/ipq95xx/mac80211/patches/qca/638-03-mac80211-Add-the-support-for-Green-AP.patch b/feeds/ipq95xx/mac80211/patches/qca/638-03-mac80211-Add-the-support-for-Green-AP.patch index a5a31a450..f992706a8 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/638-03-mac80211-Add-the-support-for-Green-AP.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/638-03-mac80211-Add-the-support-for-Green-AP.patch @@ -14,10 +14,8 @@ Signed-off-by: Sivashankari Madhavan net/mac80211/debugfs.c | 1 + 5 files changed, 31 insertions(+), 14 deletions(-) -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath6kl/cfg80211.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath6kl/cfg80211.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath6kl/cfg80211.c +--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c ++++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -2953,8 +2953,8 @@ static int ath6kl_start_ap(struct wiphy return 0; } @@ -37,8 +35,8 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath6kl/cfg + return ath6kl_set_ies(vif, &settings->beacon); } - static int ath6kl_stop_ap(struct wiphy *wiphy, struct net_device *dev) -@@ -3454,7 +3454,7 @@ static struct cfg80211_ops ath6kl_cfg802 + static int ath6kl_stop_ap(struct wiphy *wiphy, struct net_device *dev, +@@ -3456,7 +3456,7 @@ static struct cfg80211_ops ath6kl_cfg802 .resume = __ath6kl_cfg80211_resume, #endif .start_ap = ath6kl_start_ap, @@ -47,11 +45,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath6kl/cfg .stop_ap = ath6kl_stop_ap, .del_station = ath6kl_del_station, .change_station = ath6kl_change_station, -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/wil6210/cfg80211.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/wil6210/cfg80211.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/wil6210/cfg80211.c -@@ -2081,17 +2081,18 @@ void wil_cfg80211_ap_recovery(struct wil +--- a/drivers/net/wireless/ath/wil6210/cfg80211.c ++++ b/drivers/net/wireless/ath/wil6210/cfg80211.c +@@ -2080,17 +2080,18 @@ void wil_cfg80211_ap_recovery(struct wil } } @@ -78,15 +74,13 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/wil6210/cf .set_default_key = wil_cfg80211_set_default_key, /* AP mode */ - .change_beacon = wil_cfg80211_change_beacon, -+ .update_ap = wil_cfg80211_update_ap, ++ .update_ap = wil_cfg80211_update_ap, .start_ap = wil_cfg80211_start_ap, .stop_ap = wil_cfg80211_stop_ap, .add_station = wil_cfg80211_add_station, -Index: backports-20220404-5.4.164-f40abb4788/include/net/mac80211.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/include/net/mac80211.h -+++ backports-20220404-5.4.164-f40abb4788/include/net/mac80211.h -@@ -301,7 +301,7 @@ struct ieee80211_vif_chanctx_switch { +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -319,7 +319,7 @@ struct ieee80211_vif_chanctx_switch { * @BSS_CHANGED_IDLE: Idle changed for this BSS/interface. * @BSS_CHANGED_SSID: SSID changed for this BSS (AP and IBSS mode) * @BSS_CHANGED_AP_PROBE_RESP: Probe Response changed for this BSS (AP mode) @@ -95,15 +89,15 @@ Index: backports-20220404-5.4.164-f40abb4788/include/net/mac80211.h * @BSS_CHANGED_TXPOWER: TX power setting changed for this interface * @BSS_CHANGED_P2P_PS: P2P powersave settings (CTWindow, opportunistic PS) * changed -@@ -763,6 +763,7 @@ struct ieee80211_bss_conf { - u8 ccfs; +@@ -767,6 +767,7 @@ struct ieee80211_bss_conf { + u8 ccfs1; u8 present_bm; } eht_oper; + bool ap_ps_enable; bool eht_su_beamformer; bool eht_su_beamformee; bool eht_mu_beamformer; -@@ -2521,6 +2522,8 @@ struct ieee80211_txq { +@@ -2647,6 +2648,8 @@ struct ieee80211_txq { * @IEEE80211_HW_SUPPORTS_RX_DECAP_OFFLOAD: Hardware supports rx decapsulation * offload * @@ -112,7 +106,7 @@ Index: backports-20220404-5.4.164-f40abb4788/include/net/mac80211.h * @IEEE80211_HW_SUPPORTS_CONC_MON_RX_DECAP: Hardware supports concurrent rx * decapsulation offload and passing raw 802.11 frames for monitor iface. * If this is supported, the driver must pass both 802.3 frames for real -@@ -2589,6 +2592,7 @@ enum ieee80211_hw_flags { +@@ -2723,6 +2726,7 @@ enum ieee80211_hw_flags { IEEE80211_HW_SUPPORTS_NSS_OFFLOAD, IEEE80211_HW_SUPPORTS_MESH_NSS_OFFLOAD, IEEE80211_HW_SUPPORTS_TID_CLASS_OFFLOAD, @@ -120,50 +114,50 @@ Index: backports-20220404-5.4.164-f40abb4788/include/net/mac80211.h /* keep last, obviously */ NUM_IEEE80211_HW_FLAGS -Index: backports-20220404-5.4.164-f40abb4788/net/mac80211/cfg.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/net/mac80211/cfg.c -+++ backports-20220404-5.4.164-f40abb4788/net/mac80211/cfg.c -@@ -1466,12 +1466,12 @@ error: +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1432,13 +1432,13 @@ error: return err; } -static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, +- struct cfg80211_ap_settings *params) +static int ieee80211_update_ap(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_ap_settings *params) ++ struct cfg80211_ap_settings *params) { - struct ieee80211_sub_if_data *sdata; + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_link_data *link; struct beacon_data *old; - int err; + int err = -EINVAL; + struct ieee80211_bss_conf *link_conf; u32 changed; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); -@@ -1487,9 +1487,20 @@ static int ieee80211_change_beacon(struc +@@ -1460,9 +1460,20 @@ static int ieee80211_change_beacon(struc if (!old) return -ENOENT; -- err = ieee80211_assign_beacon(sdata, ¶ms->beacon, NULL, NULL); +- err = ieee80211_assign_beacon(sdata, link, ¶ms->beacon, NULL, NULL); - if (err < 0) - return err; + if (params->beacon.head || params->beacon.tail) { -+ err = ieee80211_assign_beacon(sdata, ¶ms->beacon, NULL, NULL); ++ err = ieee80211_assign_beacon(sdata, link, ¶ms->beacon, NULL, NULL); + if (err < 0) + return err; + } + + if (ieee80211_hw_check(&sdata->local->hw, SUPPORTS_AP_PS) && -+ params->ap_ps_valid) { -+ sdata->vif.bss_conf.ap_ps_enable = params->ap_ps_enable; ++ params->ap_ps_valid) { ++ link_conf->ap_ps_enable = params->ap_ps_enable; + if (err < 0) + err = BSS_CHANGED_PS; + else + err |= BSS_CHANGED_PS; + } - changed = err; - if (params->fils_discovery.max_interval) { -@@ -4788,7 +4799,7 @@ const struct cfg80211_ops mac80211_confi + if (params->beacon.he_bss_color_valid && + params->beacon.he_bss_color.enabled != link_conf->he_bss_color.enabled) { +@@ -4945,7 +4956,7 @@ const struct cfg80211_ops mac80211_confi .set_default_mgmt_key = ieee80211_config_default_mgmt_key, .set_default_beacon_key = ieee80211_config_default_beacon_key, .start_ap = ieee80211_start_ap, @@ -172,11 +166,9 @@ Index: backports-20220404-5.4.164-f40abb4788/net/mac80211/cfg.c .stop_ap = ieee80211_stop_ap, .add_station = ieee80211_add_station, .del_station = ieee80211_del_station, -Index: backports-20220404-5.4.164-f40abb4788/net/mac80211/debugfs.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/net/mac80211/debugfs.c -+++ backports-20220404-5.4.164-f40abb4788/net/mac80211/debugfs.c -@@ -579,6 +579,7 @@ static const char *hw_flag_names[] = { +--- a/net/mac80211/debugfs.c ++++ b/net/mac80211/debugfs.c +@@ -571,6 +571,7 @@ static const char *hw_flag_names[] = { FLAG(SUPPORTS_NSS_OFFLOAD), FLAG(SUPPORTS_MESH_NSS_OFFLOAD), FLAG(SUPPORTS_TID_CLASS_OFFLOAD), @@ -184,3 +176,42 @@ Index: backports-20220404-5.4.164-f40abb4788/net/mac80211/debugfs.c #undef FLAG }; +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -202,7 +202,6 @@ int ieee80211_hw_config(struct ieee80211 + + #define BSS_CHANGED_VIF_CFG_FLAGS (BSS_CHANGED_ASSOC |\ + BSS_CHANGED_IDLE |\ +- BSS_CHANGED_PS |\ + BSS_CHANGED_IBSS |\ + BSS_CHANGED_ARP_FILTER |\ + BSS_CHANGED_SSID) +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -2222,11 +2222,25 @@ void ieee80211_recalc_ps(struct ieee8021 + + void ieee80211_recalc_ps_vif(struct ieee80211_sub_if_data *sdata) + { ++ struct ieee80211_link_data *link; ++ u16 link_id; + bool ps_allowed = ieee80211_powersave_allowed(sdata); + + if (sdata->vif.cfg.ps != ps_allowed) { + sdata->vif.cfg.ps = ps_allowed; +- ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_PS); ++ if (!sdata->vif.valid_links) { ++ ieee80211_link_info_change_notify(sdata, &sdata->deflink, ++ BSS_CHANGED_PS); ++ } else { ++ for_each_set_bit(link_id, &sdata->vif.valid_links, ++ IEEE80211_MLD_MAX_NUM_LINKS) { ++ link = sdata_dereference(sdata->link[link_id], sdata); ++ if (!link) ++ continue; ++ ++ ieee80211_link_info_change_notify(sdata, link, BSS_CHANGED_PS); ++ } ++ } + } + } + diff --git a/feeds/ipq95xx/mac80211/patches/qca/638-ath12k-Send-Puncturing-pattern-of-peer-mesh-during-a.patch b/feeds/ipq95xx/mac80211/patches/qca/638-ath12k-Send-Puncturing-pattern-of-peer-mesh-during-a.patch index 850594ab9..1726cac21 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/638-ath12k-Send-Puncturing-pattern-of-peer-mesh-during-a.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/638-ath12k-Send-Puncturing-pattern-of-peer-mesh-during-a.patch @@ -14,25 +14,20 @@ Signed-off-by: Rameshkumar Sundaram drivers/net/wireless/ath/ath12k/mac.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index e733ae5..7959226 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -2518,10 +2518,12 @@ static void ath12k_peer_assoc_h_eht(struct ath12k *ar, +@@ -2553,10 +2553,12 @@ static void ath12k_peer_assoc_h_eht(stru - arg->peer_nss = min(sta->rx_nss, max_nss); + arg->peer_nss = min(sta->deflink.rx_nss, max_nss); arg->ru_punct_bitmap = ~def.ru_punct_bitmap; -+ if (ieee80211_vif_is_mesh(vif) && sta->ru_punct_bitmap) -+ arg->ru_punct_bitmap = ~sta->ru_punct_bitmap; ++ if (ieee80211_vif_is_mesh(vif) && sta->deflink.ru_punct_bitmap) ++ arg->ru_punct_bitmap = ~sta->deflink.ru_punct_bitmap; ath12k_dbg(ar->ab, ATH12K_DBG_MAC, - "mac he peer %pM nss %d mcs cnt %d\n", -- sta->addr, arg->peer_nss, arg->peer_he_mcs_count); +- sta->deflink.addr, arg->peer_nss, arg->peer_he_mcs_count); + "mac he peer %pM nss %d mcs cnt %d ru_punct_bitmap 0x%x\n", -+ sta->addr, arg->peer_nss, arg->peer_he_mcs_count, arg->ru_punct_bitmap); ++ sta->deflink.addr, arg->peer_nss, arg->peer_he_mcs_count, arg->ru_punct_bitmap); } static void ath12k_peer_assoc_h_smps(struct ieee80211_sta *sta, --- -2.7.4 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/638-ath12k-disable-spectral-scan-during-spectral-deinit.patch b/feeds/ipq95xx/mac80211/patches/qca/638-ath12k-disable-spectral-scan-during-spectral-deinit.patch index c501b4478..25b183cd9 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/638-ath12k-disable-spectral-scan-during-spectral-deinit.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/638-ath12k-disable-spectral-scan-during-spectral-deinit.patch @@ -15,7 +15,7 @@ Signed-off-by: Karthikeyan Periyasamy --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -6796,6 +6796,11 @@ static void ath12k_mac_op_remove_interfa +@@ -6892,6 +6892,11 @@ static void ath12k_mac_op_remove_interfa ath12k_dbg(ab, ATH12K_DBG_MAC, "mac remove interface (vdev %d)\n", arvif->vdev_id); diff --git a/feeds/ipq95xx/mac80211/patches/qca/639-01-ath12k-add-wait-operation-for-tx-management-packets-.patch b/feeds/ipq95xx/mac80211/patches/qca/639-01-ath12k-add-wait-operation-for-tx-management-packets-.patch index c283545eb..e01a63b0b 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/639-01-ath12k-add-wait-operation-for-tx-management-packets-.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/639-01-ath12k-add-wait-operation-for-tx-management-packets-.patch @@ -78,12 +78,11 @@ Signed-off-by: Karthik M return 0; } -@@ -6002,6 +6017,8 @@ static int ath12k_mac_mgmt_tx_wmi(struct +@@ -6002,6 +6017,7 @@ static int ath12k_mac_mgmt_tx_wmi(struct buf_id = idr_alloc(&ar->txmgmt_idr, skb, 0, ATH12K_TX_MGMT_NUM_PENDING_MAX, GFP_ATOMIC); spin_unlock_bh(&ar->txmgmt_idr_lock); -+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, -+ "mac tx mgmt frame, buf id %d\n", buf_id); ++ if (buf_id < 0) return -ENOSPC; @@ -113,7 +112,7 @@ Signed-off-by: Karthik M + ath12k_mgmt_over_wmi_tx_drop(ar, skb); } else { - atomic_inc(&ar->num_pending_mgmt_tx); -+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, ++ ath12k_dbg(ar->ab, ATH12K_DBG_MGMT, + "mac tx mgmt frame, vdev_id %d\n", + arvif->vdev_id); } @@ -171,7 +170,7 @@ Signed-off-by: Karthik M spin_lock_bh(&ar->txmgmt_idr_lock); msdu = idr_find(&ar->txmgmt_idr, desc_id); -@@ -5668,10 +5669,19 @@ static int wmi_process_mgmt_tx_comp(stru +@@ -5668,10 +5669,16 @@ static int wmi_process_mgmt_tx_comp(stru ieee80211_tx_status_irqsafe(ar->hw, msdu); @@ -182,9 +181,6 @@ Signed-off-by: Karthik M + if (num_mgmt < 0) WARN_ON_ONCE(1); -+ ath12k_dbg(ar->ab, ATH12K_DBG_WMI, -+ "wmi mgmt tx comp pending %d desc id %d\n", -+ num_mgmt, desc_id); + + if (!num_mgmt) + wake_up(&ar->txmgmt_empty_waitq); diff --git a/feeds/ipq95xx/mac80211/patches/qca/639-03-ath12k-disabling-credit-flow-for-WMI-path.patch b/feeds/ipq95xx/mac80211/patches/qca/639-03-ath12k-disabling-credit-flow-for-WMI-path.patch index 355bbadcf..cfeb31284 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/639-03-ath12k-disabling-credit-flow-for-WMI-path.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/639-03-ath12k-disabling-credit-flow-for-WMI-path.patch @@ -58,7 +58,7 @@ Signed-off-by: Karthik M }, /* CE8: target autonomous hif_memcpy */ -@@ -371,18 +373,31 @@ err_unlock: +@@ -456,18 +458,31 @@ err_unlock: return skb; } @@ -77,7 +77,7 @@ Signed-off-by: Karthik M dma_unmap_single(ab->dev, ATH12K_SKB_CB(skb)->paddr, skb->len, DMA_TO_DEVICE); - dev_kfree_skb_any(skb); -+ if ((!pipe->send_cb) || ab->hw_params.credit_flow) { ++ if ((!pipe->send_cb) || ab->hw_params->credit_flow) { + dev_kfree_skb_any(skb); + continue; + } @@ -92,7 +92,7 @@ Signed-off-by: Karthik M } } -@@ -512,7 +527,7 @@ static int ath12k_ce_alloc_pipe(struct a +@@ -597,7 +612,7 @@ static int ath12k_ce_alloc_pipe(struct a pipe->attr_flags = attr->flags; if (attr->src_nentries) { @@ -101,11 +101,11 @@ Signed-off-by: Karthik M nentries = roundup_pow_of_two(attr->src_nentries); desc_sz = ath12k_hal_ce_get_desc_size(HAL_CE_DESC_SRC); ring = ath12k_ce_alloc_ring(ab, nentries, desc_sz); -@@ -543,9 +558,10 @@ static int ath12k_ce_alloc_pipe(struct a +@@ -628,9 +643,10 @@ static int ath12k_ce_alloc_pipe(struct a void ath12k_ce_per_engine_service(struct ath12k_base *ab, u16 ce_id) { struct ath12k_ce_pipe *pipe = &ab->ce.ce_pipe[ce_id]; -+ const struct ce_attr *attr = &ab->hw_params.host_ce_config[ce_id]; ++ const struct ce_attr *attr = &ab->hw_params->host_ce_config[ce_id]; - if (pipe->send_cb) - pipe->send_cb(pipe); @@ -114,11 +114,11 @@ Signed-off-by: Karthik M if (pipe->recv_cb) ath12k_ce_recv_process_cb(pipe); -@@ -554,9 +570,10 @@ void ath12k_ce_per_engine_service(struct +@@ -639,9 +655,10 @@ void ath12k_ce_per_engine_service(struct void ath12k_ce_poll_send_completed(struct ath12k_base *ab, u8 pipe_id) { struct ath12k_ce_pipe *pipe = &ab->ce.ce_pipe[pipe_id]; -+ const struct ce_attr *attr = &ab->hw_params.host_ce_config[pipe_id]; ++ const struct ce_attr *attr = &ab->hw_params->host_ce_config[pipe_id]; - if ((pipe->attr_flags & CE_ATTR_DIS_INTR) && pipe->send_cb) - pipe->send_cb(pipe); @@ -129,41 +129,31 @@ Signed-off-by: Karthik M int ath12k_ce_send(struct ath12k_base *ab, struct sk_buff *skb, u8 pipe_id, --- a/drivers/net/wireless/ath/ath12k/ce.h +++ b/drivers/net/wireless/ath/ath12k/ce.h -@@ -102,6 +102,8 @@ struct ce_attr { +@@ -98,6 +98,8 @@ struct ce_attr { unsigned int dest_nentries; - void (*recv_cb)(struct ath12k_base *, struct sk_buff *); + void (*recv_cb)(struct ath12k_base *ab, struct sk_buff *skb); + + void (*send_cb)(struct ath12k_base *, struct sk_buff *); }; #define CE_DESC_RING_ALIGN 8 -@@ -155,7 +157,7 @@ struct ath12k_ce_pipe { +@@ -151,7 +153,7 @@ struct ath12k_ce_pipe { unsigned int buf_sz; unsigned int rx_buf_needed; -- void (*send_cb)(struct ath12k_ce_pipe *); +- void (*send_cb)(struct ath12k_ce_pipe *pipe); + void (*send_cb)(struct ath12k_base *, struct sk_buff *); - void (*recv_cb)(struct ath12k_base *, struct sk_buff *); + void (*recv_cb)(struct ath12k_base *ab, struct sk_buff *skb); struct tasklet_struct intr_tq; ---- a/drivers/net/wireless/ath/ath12k/core.c -+++ b/drivers/net/wireless/ath/ath12k/core.c -@@ -68,6 +68,7 @@ static const struct ath12k_hw_params ath - .num_tcl_banks = 48, - .fix_l1ss = false, - .supports_ap_ps = true, -+ .credit_flow = false, - }, - }; - --- a/drivers/net/wireless/ath/ath12k/htc.c +++ b/drivers/net/wireless/ath/ath12k/htc.c @@ -82,6 +82,8 @@ int ath12k_htc_send(struct ath12k_htc *h struct ath12k_base *ab = htc->ab; int credits = 0; int ret; -+ bool credit_flow_enabled = (ab->hw_params.credit_flow && ++ bool credit_flow_enabled = (ab->hw_params->credit_flow && + ep->tx_credit_flow_enabled); if (eid >= ATH12K_HTC_EP_COUNT) { @@ -177,7 +167,7 @@ Signed-off-by: Karthik M credits = DIV_ROUND_UP(skb->len, htc->target_credit_size); spin_lock_bh(&htc->tx_lock); if (ep->tx_credits < credits) { -@@ -127,7 +129,7 @@ int ath12k_htc_send(struct ath12k_htc *h +@@ -126,7 +128,7 @@ int ath12k_htc_send(struct ath12k_htc *h err_unmap: dma_unmap_single(dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE); err_credits: @@ -186,7 +176,7 @@ Signed-off-by: Karthik M spin_lock_bh(&htc->tx_lock); ep->tx_credits += credits; ath12k_dbg(ab, ATH12K_DBG_HTC, -@@ -204,23 +206,25 @@ static int ath12k_htc_process_trailer(st +@@ -203,23 +205,25 @@ static int ath12k_htc_process_trailer(st break; } @@ -196,7 +186,7 @@ Signed-off-by: Karthik M - if (record->hdr.len < len) { - ath12k_warn(ab, "Credit report too long\n"); - status = -EINVAL; -+ if (ab->hw_params.credit_flow) { ++ if (ab->hw_params->credit_flow) { + switch (record->hdr.id) { + case ATH12K_HTC_RECORD_CREDITS: + len = sizeof(struct ath12k_htc_credit_report); @@ -227,7 +217,7 @@ Signed-off-by: Karthik M } if (status) -@@ -246,6 +250,29 @@ static void ath12k_htc_suspend_complete( +@@ -245,6 +249,29 @@ static void ath12k_htc_suspend_complete( complete(&ab->htc_suspend); } @@ -261,20 +251,20 @@ Signed-off-by: Karthik M disable_credit_flow_ctrl = true; } -+ if (!ab->hw_params.credit_flow) { ++ if (!ab->hw_params->credit_flow) { + flags |= ATH12K_HTC_CONN_FLAGS_DISABLE_CREDIT_FLOW_CTRL; + disable_credit_flow_ctrl = true; + } + - req_msg->flags_len = FIELD_PREP(HTC_SVC_MSG_CONNECTIONFLAGS, flags); - req_msg->msg_svc_id |= FIELD_PREP(HTC_SVC_MSG_SERVICE_ID, - conn_req->service_id); -@@ -729,7 +761,10 @@ int ath12k_htc_start(struct ath12k_htc * - msg->msg_id = FIELD_PREP(HTC_MSG_MESSAGEID, - ATH12K_HTC_MSG_SETUP_COMPLETE_EX_ID); + req_msg->flags_len = u32_encode_bits(flags, HTC_SVC_MSG_CONNECTIONFLAGS); + req_msg->msg_svc_id |= u32_encode_bits(conn_req->service_id, + HTC_SVC_MSG_SERVICE_ID); +@@ -728,7 +760,10 @@ int ath12k_htc_start(struct ath12k_htc * + msg->msg_id = u32_encode_bits(ATH12K_HTC_MSG_SETUP_COMPLETE_EX_ID, + HTC_MSG_MESSAGEID); - ath12k_dbg(ab, ATH12K_DBG_HTC, "HTC is using TX credit flow control\n"); -+ if (ab->hw_params.credit_flow) ++ if (ab->hw_params->credit_flow) + ath12k_dbg(ab, ATH12K_DBG_HTC, "HTC is using TX credit flow control\n"); + else + msg->flags |= ATH12K_GLOBAL_DISABLE_CREDIT_FLOW; @@ -313,17 +303,17 @@ Signed-off-by: Karthik M #endif --- a/drivers/net/wireless/ath/ath12k/hw.h +++ b/drivers/net/wireless/ath/ath12k/hw.h -@@ -166,6 +166,7 @@ struct ath12k_hw_params { - u32 num_tcl_banks; +@@ -195,6 +195,7 @@ struct ath12k_hw_params { bool fix_l1ss; + bool supports_ap_ps; + bool credit_flow; }; - struct ath12k_hw_ops { + /* BRINGUP: move to dp.h */ --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -338,21 +338,37 @@ int ath12k_wmi_cmd_send(struct ath12k_pd +@@ -386,21 +386,37 @@ int ath12k_wmi_cmd_send(struct ath12k_pd { struct ath12k_wmi_base *wmi_sc = wmi->wmi_ab; int ret = -EOPNOTSUPP; @@ -336,10 +326,7 @@ Signed-off-by: Karthik M - - if (ret && test_bit(ATH12K_FLAG_CRASH_FLUSH, &wmi_sc->ab->dev_flags)) - ret = -ESHUTDOWN; -- -- (ret != -EAGAIN); -- }), WMI_SEND_TIMEOUT_HZ); -+ if (ab->hw_params.credit_flow) { ++ if (ab->hw_params->credit_flow) { + wait_event_timeout(wmi_sc->tx_credits_wq, ({ + ret = ath12k_wmi_cmd_send_nowait(wmi, skb, cmd_id); + @@ -354,10 +341,12 @@ Signed-off-by: Karthik M + if (ret && test_bit(ATH12K_FLAG_CRASH_FLUSH, + &wmi_sc->ab->dev_flags)) + ret = -ESHUTDOWN; -+ + +- (ret != -EAGAIN); +- }), WMI_SEND_TIMEOUT_HZ); + (ret != -ENOBUFS); + }), WMI_SEND_TIMEOUT_HZ); -+ } ++ } if (ret == -EAGAIN) ath12k_warn(wmi_sc->ab, "wmi command %d timeout\n", cmd_id); @@ -369,7 +358,7 @@ Signed-off-by: Karthik M return ret; } -@@ -6673,7 +6689,30 @@ static void ath12k_wmi_op_ep_tx_credits( +@@ -6707,7 +6723,30 @@ static void ath12k_wmi_op_ep_tx_credits( static void ath12k_wmi_htc_tx_complete(struct ath12k_base *ab, struct sk_buff *skb) { @@ -385,7 +374,7 @@ Signed-off-by: Karthik M + return; + + wmi_ep_count = ab->htc.wmi_ep_count; -+ if (wmi_ep_count > ab->hw_params.max_radios) ++ if (wmi_ep_count > ab->hw_params->max_radios) + return; + + for (i = 0; i < ab->htc.wmi_ep_count; i++) { @@ -400,7 +389,7 @@ Signed-off-by: Karthik M } static bool ath12k_reg_is_world_alpha(char *alpha) -@@ -8477,6 +8516,7 @@ static int ath12k_connect_pdev_htc_servi +@@ -8505,6 +8544,7 @@ static int ath12k_connect_pdev_htc_servi ab->wmi_ab.wmi_endpoint_id[pdev_idx] = conn_resp.eid; ab->wmi_ab.wmi[pdev_idx].eid = conn_resp.eid; ab->wmi_ab.max_msg_len[pdev_idx] = conn_resp.max_msg_len; @@ -410,7 +399,7 @@ Signed-off-by: Karthik M } --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -2708,6 +2708,7 @@ struct ath12k_pdev_wmi { +@@ -2703,6 +2703,7 @@ struct ath12k_pdev_wmi { enum ath12k_htc_ep_id eid; const struct wmi_peer_flags_map *peer_flags; u32 rx_decap_mode; @@ -418,3 +407,21 @@ Signed-off-by: Karthik M }; struct vdev_create_params { +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -879,6 +879,7 @@ static const struct ath12k_hw_params ath + .fix_l1ss = false, + + .supports_ap_ps = true, ++ .credit_flow = false, + }, + { + .name = "wcn7850 hw2.0", +@@ -942,6 +943,7 @@ static const struct ath12k_hw_params ath + .fix_l1ss = false, + + .supports_ap_ps = true, ++ .credit_flow = false, + }, + }; + diff --git a/feeds/ipq95xx/mac80211/patches/qca/639-04-ath12k-fix-bss-chan-info-request-wmi-command.patch b/feeds/ipq95xx/mac80211/patches/qca/639-04-ath12k-fix-bss-chan-info-request-wmi-command.patch index 8d6fe78b3..83dfb4b8a 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/639-04-ath12k-fix-bss-chan-info-request-wmi-command.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/639-04-ath12k-fix-bss-chan-info-request-wmi-command.patch @@ -15,25 +15,25 @@ Signed-off-by: P Praneesh --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -1411,6 +1411,7 @@ int ath12k_wmi_pdev_bss_chan_info_reques - WMI_TAG_PDEV_BSS_CHAN_INFO_REQUEST) | - FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); - cmd->req_type = type; -+ cmd->pdev_id = ar->pdev->pdev_id; +@@ -1490,6 +1490,7 @@ int ath12k_wmi_pdev_bss_chan_info_reques + cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PDEV_BSS_CHAN_INFO_REQUEST, + sizeof(*cmd)); + cmd->req_type = cpu_to_le32(type); ++ cmd->pdev_id = cpu_to_le32(ar->pdev->pdev_id); ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "WMI bss chan info req type %d\n", type); --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -3290,6 +3290,7 @@ struct wmi_pdev_bss_chan_info_req_cmd { - u32 tlv_header; +@@ -3253,6 +3253,7 @@ struct wmi_pdev_bss_chan_info_req_cmd { + __le32 tlv_header; /* ref wmi_bss_chan_info_req_type */ - u32 req_type; -+ u32 pdev_id; + __le32 req_type; ++ __le32 pdev_id; } __packed; struct wmi_ap_ps_peer_cmd { -@@ -4567,7 +4568,6 @@ struct wmi_vdev_stopped_event { +@@ -4519,7 +4520,6 @@ struct wmi_vdev_stopped_event { } __packed; struct wmi_pdev_bss_chan_info_event { @@ -41,7 +41,7 @@ Signed-off-by: P Praneesh u32 freq; /* Units in MHz */ u32 noise_floor; /* units are dBm */ /* rx clear - how often the channel was unused */ -@@ -4585,6 +4585,7 @@ struct wmi_pdev_bss_chan_info_event { +@@ -4537,6 +4537,7 @@ struct wmi_pdev_bss_chan_info_event { /*rx_cycle cnt for my bss in 64bits format */ u32 rx_bss_cycle_count_low; u32 rx_bss_cycle_count_high; diff --git a/feeds/ipq95xx/mac80211/patches/qca/639-ath12k-Add-coredump-segment-for-dynamic-paging.patch b/feeds/ipq95xx/mac80211/patches/qca/639-ath12k-Add-coredump-segment-for-dynamic-paging.patch index 875c97657..660e1ee30 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/639-ath12k-Add-coredump-segment-for-dynamic-paging.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/639-ath12k-Add-coredump-segment-for-dynamic-paging.patch @@ -31,13 +31,13 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor @@ -208,10 +208,18 @@ if (ab->qmi.target_mem[i].type == CALDB_MEM_REGION_TYPE) { if (ath12k_cold_boot_cal || - ab->hw_params.cold_boot_calib) { + ab->hw_params->cold_boot_calib) { + /* Add separate segment type for CALDB*/ skip_count++; continue; } } -+ if (ab->qmi.target_mem[i].type == PAGEABLE_MEM_TYPE) { ++ if (ab->qmi.target_mem[i].type == PAGEABLE_MEM_REGION_TYPE) { + seg_info->len = ab->qmi.target_mem[i].size; + seg_info->addr = ab->qmi.target_mem[i].paddr; + seg_info->vaddr = ab->qmi.target_mem[i].v.ioaddr; diff --git a/feeds/ipq95xx/mac80211/patches/qca/640-001-ath12k-Enable-monitor-interface-support.patch b/feeds/ipq95xx/mac80211/patches/qca/640-001-ath12k-Enable-monitor-interface-support.patch index f18cee687..510c7393f 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/640-001-ath12k-Enable-monitor-interface-support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/640-001-ath12k-Enable-monitor-interface-support.patch @@ -16,20 +16,9 @@ Signed-off-by: P Praneesh drivers/net/wireless/ath/ath12k/mac.c | 73 +++++++++++++++++++++----------- 4 files changed, 53 insertions(+), 31 deletions(-) -Index: b/drivers/net/wireless/ath/ath12k/core.c -=================================================================== ---- a/drivers/net/wireless/ath/ath12k/core.c 2022-07-26 22:41:46.965952263 +0530 -+++ b/drivers/net/wireless/ath/ath12k/core.c 2022-07-26 22:42:09.181763205 +0530 -@@ -60,7 +60,7 @@ static const struct ath12k_hw_params ath - .interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_MESH_POINT), -- .supports_monitor = false, -+ .supports_monitor = true, - .idle_ps = false, - .cold_boot_calib = false, - .supports_suspend = false, -@@ -850,6 +850,10 @@ static void ath12k_core_restart(struct w +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -827,6 +827,10 @@ static void ath12k_core_restart(struct w ath12k_mac_tx_mgmt_pending_free, ar); idr_destroy(&ar->txmgmt_idr); wake_up(&ar->txmgmt_empty_waitq); @@ -40,11 +29,9 @@ Index: b/drivers/net/wireless/ath/ath12k/core.c } wake_up(&ab->wmi_ab.tx_credits_wq); -Index: b/drivers/net/wireless/ath/ath12k/core.h -=================================================================== ---- a/drivers/net/wireless/ath/ath12k/core.h 2022-07-26 22:41:46.965952263 +0530 -+++ b/drivers/net/wireless/ath/ath12k/core.h 2022-07-26 22:41:46.961952297 +0530 -@@ -207,7 +207,9 @@ enum ath12k_dev_flags { +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -208,7 +208,9 @@ enum ath12k_dev_flags { }; enum ath12k_monitor_flags { @@ -56,20 +43,18 @@ Index: b/drivers/net/wireless/ath/ath12k/core.h struct ath12k_fw_vdev_ol_stats { @@ -710,9 +712,6 @@ struct ath12k { + #endif bool dfs_block_radar_events; struct ath12k_thermal thermal; - s8 max_allowed_tx_power; - bool monitor_conf_enabled; - bool monitor_vdev_created; - bool monitor_started; int monitor_vdev_id; u8 twt_enabled; - bool ap_ps_enabled; -Index: b/drivers/net/wireless/ath/ath12k/dp_mon.c -=================================================================== ---- a/drivers/net/wireless/ath/ath12k/dp_mon.c 2022-07-26 22:41:46.965952263 +0530 -+++ b/drivers/net/wireless/ath/ath12k/dp_mon.c 2022-07-26 22:41:46.961952297 +0530 -@@ -2607,7 +2607,7 @@ int ath12k_dp_mon_process_ring(struct at + s8 max_allowed_tx_power; +--- a/drivers/net/wireless/ath/ath12k/dp_mon.c ++++ b/drivers/net/wireless/ath/ath12k/dp_mon.c +@@ -2608,7 +2608,7 @@ int ath12k_dp_mon_process_ring(struct at struct ath12k *ar = ath12k_ab_to_ar(ab, mac_id); int num_buffs_reaped = 0; @@ -78,10 +63,8 @@ Index: b/drivers/net/wireless/ath/ath12k/dp_mon.c num_buffs_reaped = ath12k_dp_mon_rx_process_stats(ar, mac_id, napi, &budget); else -Index: b/drivers/net/wireless/ath/ath12k/mac.c -=================================================================== ---- a/drivers/net/wireless/ath/ath12k/mac.c 2022-07-26 22:41:46.965952263 +0530 -+++ b/drivers/net/wireless/ath/ath12k/mac.c 2022-07-26 22:41:46.961952297 +0530 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -980,7 +980,7 @@ static int ath12k_mac_monitor_vdev_creat lockdep_assert_held(&ar->conf_mutex); @@ -194,7 +177,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c ret = ath12k_mac_monitor_stop(ar); if (ret) goto exit; -@@ -3342,7 +3355,7 @@ static int ath12k_mac_config_obss_pd(str +@@ -3394,7 +3407,7 @@ static int ath12k_mac_config_obss_pd(str /* Set and enable SRG/non-SRG OBSS PD Threshold */ param_id = WMI_PDEV_PARAM_SET_CMD_OBSS_PD_THRESHOLD; @@ -203,7 +186,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c ret = ath12k_wmi_pdev_set_param(ar, param_id, 0, pdev_id); if (ret) ath12k_warn(ar->ab, -@@ -6717,6 +6730,9 @@ static int ath12k_mac_op_add_interface(s +@@ -6806,6 +6819,9 @@ static int ath12k_mac_op_add_interface(s goto err_peer_del; } break; @@ -213,7 +196,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c default: break; } -@@ -6739,7 +6755,8 @@ static int ath12k_mac_op_add_interface(s +@@ -6828,7 +6844,8 @@ static int ath12k_mac_op_add_interface(s ath12k_mac_ap_ps_recalc(ar); @@ -223,7 +206,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c ath12k_mac_monitor_vdev_create(ar); ret = ath12k_debugfs_add_interface(arvif); -@@ -6856,8 +6873,9 @@ static void ath12k_mac_op_remove_interfa +@@ -6945,8 +6962,9 @@ static void ath12k_mac_op_remove_interfa if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { ar->monitor_vdev_id = -1; @@ -235,7 +218,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c ret = ath12k_mac_monitor_vdev_delete(ar); } -@@ -6886,7 +6904,7 @@ err_vdev_del: +@@ -6975,7 +6993,7 @@ err_vdev_del: /* Recalc txpower for remaining vdev */ ath12k_mac_txpower_recalc(ar); ath12k_mac_ap_ps_recalc(ar); @@ -244,7 +227,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c ath12k_debugfs_remove_interface(arvif); -@@ -6914,7 +6932,6 @@ static void ath12k_mac_op_configure_filt +@@ -7003,7 +7021,6 @@ static void ath12k_mac_op_configure_filt mutex_lock(&ar->conf_mutex); @@ -252,7 +235,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c *total_flags &= SUPPORTED_FILTERS; ar->filter_flags = *total_flags; -@@ -7389,7 +7406,8 @@ ath12k_mac_update_vif_chan(struct ath12k +@@ -7478,7 +7495,8 @@ ath12k_mac_update_vif_chan(struct ath12k } /* Restart the internal monitor vdev on new channel */ @@ -262,16 +245,16 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c if (!ath12k_mac_monitor_stop(ar)) ath12k_mac_monitor_start(ar); } -@@ -8077,7 +8095,7 @@ ath12k_mac_op_assign_vif_chanctx(struct +@@ -8167,7 +8185,7 @@ ath12k_mac_op_assign_vif_chanctx(struct - if (ab->hw_params.vdev_start_delay && + if (ab->hw_params->vdev_start_delay && (arvif->vdev_type == WMI_VDEV_TYPE_AP || - arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)) { + arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)) { param.vdev_id = arvif->vdev_id; param.peer_type = WMI_PEER_TYPE_DEFAULT; param.peer_addr = ar->mac_addr; -@@ -8106,7 +8124,8 @@ ath12k_mac_op_assign_vif_chanctx(struct +@@ -8196,7 +8214,8 @@ ath12k_mac_op_assign_vif_chanctx(struct goto out; } @@ -281,7 +264,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c ath12k_mac_monitor_start(ar); arvif->is_started = true; -@@ -8153,6 +8172,7 @@ ath12k_mac_op_unassign_vif_chanctx(struc +@@ -8244,6 +8263,7 @@ ath12k_mac_op_unassign_vif_chanctx(struc arvif->is_started = false; mutex_unlock(&ar->conf_mutex); @@ -289,7 +272,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c } ret = ath12k_mac_vdev_stop(arvif); -@@ -8167,7 +8187,8 @@ ath12k_mac_op_unassign_vif_chanctx(struc +@@ -8258,7 +8278,8 @@ ath12k_mac_op_unassign_vif_chanctx(struc ath12k_wmi_vdev_down(ar, arvif->vdev_id); if (arvif->vdev_type != WMI_VDEV_TYPE_MONITOR && @@ -299,7 +282,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c ath12k_mac_monitor_stop(ar); mutex_unlock(&ar->conf_mutex); -@@ -9588,6 +9609,7 @@ static int __ath12k_mac_register(struct +@@ -9692,6 +9713,7 @@ static int __ath12k_mac_register(struct ieee80211_hw_set(ar->hw, SPECTRUM_MGMT); ieee80211_hw_set(ar->hw, CONNECTION_MONITOR); ieee80211_hw_set(ar->hw, SUPPORTS_PER_STA_GTK); @@ -307,7 +290,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c ieee80211_hw_set(ar->hw, CHANCTX_STA_CSA); ieee80211_hw_set(ar->hw, QUEUE_CONTROL); ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG); -@@ -9824,7 +9846,9 @@ int ath12k_mac_allocate(struct ath12k_ba +@@ -9928,7 +9950,9 @@ int ath12k_mac_allocate(struct ath12k_ba INIT_WORK(&ar->wmi_mgmt_tx_work, ath12k_mgmt_over_wmi_tx_work); skb_queue_head_init(&ar->wmi_mgmt_tx_queue); @@ -318,3 +301,14 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c } return 0; +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -853,7 +853,7 @@ static const struct ath12k_hw_params ath + .interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_MESH_POINT), +- .supports_monitor = false, ++ .supports_monitor = true, + + .idle_ps = false, + .cold_boot_calib = false, diff --git a/feeds/ipq95xx/mac80211/patches/qca/640-002-ath12k-refactor-monitor-stats-ring-processing.patch b/feeds/ipq95xx/mac80211/patches/qca/640-002-ath12k-refactor-monitor-stats-ring-processing.patch index e1f33d5f3..3a2d10e37 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/640-002-ath12k-refactor-monitor-stats-ring-processing.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/640-002-ath12k-refactor-monitor-stats-ring-processing.patch @@ -24,7 +24,7 @@ Signed-off-by: P Praneesh buf_id); return HAL_RX_MON_STATUS_PPDU_NOT_DONE; } -@@ -1230,7 +1231,11 @@ ath12k_dp_mon_rx_parse_mon_status(struct +@@ -1232,7 +1233,11 @@ ath12k_dp_mon_rx_parse_mon_status(struct struct sk_buff *head_msdu, *tail_msdu; enum hal_rx_mon_status hal_status = HAL_RX_MON_STATUS_BUF_DONE; @@ -37,30 +37,7 @@ Signed-off-by: P Praneesh list_for_each_entry_safe(mon_mpdu, tmp, &pmon->dp_rx_mon_mpdu_list, list) { list_del(&mon_mpdu->list); -@@ -1255,7 +1260,8 @@ int ath12k_dp_mon_buf_replenish(struct a - struct sk_buff *skb; - struct hal_srng *srng; - dma_addr_t paddr; -- u32 cookie, buf_id; -+ u64 cookie; -+ int buf_id; - - srng = &ab->hal.srng_list[buf_ring->refill_buf_ring.ring_id]; - spin_lock_bh(&srng->lock); -@@ -1284,8 +1290,11 @@ int ath12k_dp_mon_buf_replenish(struct a - buf_ring->bufs_max * 3, GFP_ATOMIC); - spin_unlock_bh(&buf_ring->idr_lock); - -- if (unlikely(buf_id < 0)) -+ if (unlikely(buf_id < 0)) { -+ ath12k_warn(ab, "idr allocation failed with ret %d code\n", -+ buf_id); - goto fail_dma_unmap; -+ } - - mon_buf = (struct hal_mon_buf_ring *) - ath12k_hal_srng_src_get_next_entry(ab, srng); -@@ -2043,135 +2052,6 @@ ath12k_dp_mon_tx_parse_mon_status(struct +@@ -2044,135 +2049,6 @@ ath12k_dp_mon_tx_parse_mon_status(struct return tlv_status; } @@ -90,7 +67,7 @@ Signed-off-by: P Praneesh - memset(ppdu_info, 0, sizeof(*ppdu_info)); - ppdu_info->peer_id = HAL_INVALID_PEERID; - -- srng_id = ath12k_hw_mac_id_to_srng_id(&ab->hw_params, mac_id); +- srng_id = ath12k_hw_mac_id_to_srng_id(ab->hw_params, mac_id); - - if (flag == ATH12K_DP_RX_MONITOR_MODE) { - mon_dst_ring = &pdev_dp->rxdma_mon_dst_ring[srng_id]; @@ -196,7 +173,7 @@ Signed-off-by: P Praneesh static void ath12k_dp_mon_rx_update_peer_rate_table_stats(struct ath12k_rx_peer_stats *rx_stats, struct hal_rx_mon_ppdu_info *ppdu_info, -@@ -2481,6 +2361,172 @@ ath12k_dp_mon_rx_update_peer_mu_stats(st +@@ -2482,6 +2358,167 @@ ath12k_dp_mon_rx_update_peer_mu_stats(st ath12k_dp_mon_rx_update_user_stats(ar, ppdu_info, i); } @@ -224,7 +201,7 @@ Signed-off-by: P Praneesh + + __skb_queue_head_init(&skb_list); + -+ srng_id = ath12k_hw_mac_id_to_srng_id(&ab->hw_params, mac_id); ++ srng_id = ath12k_hw_mac_id_to_srng_id(ab->hw_params, mac_id); + + if (flag == ATH12K_DP_RX_MONITOR_MODE) { + mon_dst_ring = &pdev_dp->rxdma_mon_dst_ring[srng_id]; @@ -253,12 +230,8 @@ Signed-off-by: P Praneesh + break; + + if (u32_get_bits(mon_dst_desc->info0, HAL_MON_DEST_INFO0_EMPTY_DESC)) { -+ /* Empty descriptor is intended for drop statistics, HW doesn't -+ * consume any buffer in this case. Instead of replenishing the -+ * new buffer, just move to the next entry in the destination ring -+ */ + ab->soc_stats.mon_drop_desc++; -+ goto next_entry; ++ goto move_next; + } + + cookie = mon_dst_desc->cookie; @@ -270,7 +243,7 @@ Signed-off-by: P Praneesh + spin_unlock_bh(&buf_ring->idr_lock); + + if (unlikely(!skb)) { -+ ath12k_warn(ab, "montior destination with invalid buf_id %d\n", ++ ath12k_warn(ab, "mon: dest desc with inval buf_id %d\n", + buf_id); + goto move_next; + } @@ -295,7 +268,6 @@ Signed-off-by: P Praneesh + __skb_queue_tail(&skb_list, skb); +move_next: + ath12k_dp_mon_buf_replenish(ab, buf_ring, 1); -+next_entry: + ath12k_hal_srng_dst_get_next_entry(ab, srng); + num_buffs_reaped++; + } @@ -369,7 +341,7 @@ Signed-off-by: P Praneesh int ath12k_dp_mon_rx_process_stats(struct ath12k *ar, int mac_id, struct napi_struct *napi, int *budget) { -@@ -2513,12 +2559,16 @@ int ath12k_dp_mon_rx_process_stats(struc +@@ -2514,12 +2551,16 @@ int ath12k_dp_mon_rx_process_stats(struc ath12k_hal_srng_access_begin(ab, srng); while (likely(*budget)) { @@ -387,7 +359,16 @@ Signed-off-by: P Praneesh cookie = mon_dst_desc->cookie; buf_id = u32_get_bits(cookie, DP_RXDMA_BUF_COOKIE_BUF_ID); -@@ -2541,11 +2591,15 @@ int ath12k_dp_mon_rx_process_stats(struc +@@ -2528,7 +2569,7 @@ int ath12k_dp_mon_rx_process_stats(struc + spin_unlock_bh(&buf_ring->idr_lock); + + if (unlikely(!skb)) { +- ath12k_warn(ab, "montior destination with invalid buf_id %d\n", ++ ath12k_warn(ab, "mon stats: dest ring with inval buf_id %d\n", + buf_id); + goto move_next; + } +@@ -2542,11 +2583,15 @@ int ath12k_dp_mon_rx_process_stats(struc HAL_MON_DEST_INFO0_END_REASON); if ((end_reason == HAL_MON_FLUSH_DETECTED) || (end_reason == HAL_MON_PPDU_TRUNCATED)) { @@ -404,7 +385,7 @@ Signed-off-by: P Praneesh __skb_queue_tail(&skb_list, skb); move_next: ath12k_dp_mon_buf_replenish(ab, buf_ring, 1); -@@ -2559,23 +2613,27 @@ move_next: +@@ -2560,23 +2605,27 @@ move_next: if (!num_buffs_reaped) return 0; @@ -437,7 +418,7 @@ Signed-off-by: P Praneesh ppdu_info->peer_id); goto next_skb; } -@@ -2593,6 +2651,7 @@ move_next: +@@ -2594,6 +2643,7 @@ move_next: next_skb: spin_unlock_bh(&ab->base_lock); rcu_read_unlock(); @@ -467,7 +448,7 @@ Signed-off-by: P Praneesh }; --- a/drivers/net/wireless/ath/ath12k/debugfs.c +++ b/drivers/net/wireless/ath/ath12k/debugfs.c -@@ -867,6 +867,10 @@ static ssize_t ath12k_debugfs_dump_soc_d +@@ -866,6 +866,10 @@ static ssize_t ath12k_debugfs_dump_soc_d "\nMisc Transmit Failures: %d\n", atomic_read(&soc_stats->tx_err.misc_fail)); diff --git a/feeds/ipq95xx/mac80211/patches/qca/640-003-ath12k-add-filter-settings-to-enable-monitor-mode.patch b/feeds/ipq95xx/mac80211/patches/qca/640-003-ath12k-add-filter-settings-to-enable-monitor-mode.patch index a6d7e13e2..6d6057195 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/640-003-ath12k-add-filter-settings-to-enable-monitor-mode.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/640-003-ath12k-add-filter-settings-to-enable-monitor-mode.patch @@ -13,20 +13,9 @@ Signed-off-by: P Praneesh drivers/net/wireless/ath/ath12k/dp_tx.c | 51 ++++++++++++++++++++++++++----- 3 files changed, 88 insertions(+), 12 deletions(-) ---- a/drivers/net/wireless/ath/ath12k/debugfs.c -+++ b/drivers/net/wireless/ath/ath12k/debugfs.c -@@ -685,7 +685,7 @@ static ssize_t ath12k_write_extd_rx_stat - rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS; - rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT; - rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE; -- rx_filter |= HTT_RX_FILTER_TLV_FLAGS_ENABLE_FP; -+ rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_START_USER_INFO; - - tlv_filter.rx_filter = rx_filter; - tlv_filter.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0; --- a/drivers/net/wireless/ath/ath12k/dp.h +++ b/drivers/net/wireless/ath/ath12k/dp.h -@@ -788,7 +788,12 @@ enum htt_stats_internal_ppdu_frametype { +@@ -752,7 +752,12 @@ enum htt_stats_internal_ppdu_frametype { #define HTT_RX_RING_SELECTION_CFG_CMD_INFO0_RING_ID GENMASK(23, 16) #define HTT_RX_RING_SELECTION_CFG_CMD_INFO0_SS BIT(24) #define HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PS BIT(25) @@ -40,7 +29,7 @@ Signed-off-by: P Praneesh #define HTT_RX_RING_SELECTION_CFG_CMD_OFFSET_VALID BIT(26) #define HTT_RX_RING_SELECTION_CFG_CMD_DROP_THRES_VAL BIT(27) #define HTT_RX_RING_SELECTION_CFG_CMD_RXMON_GCONF_EN BIT(28) -@@ -815,7 +820,7 @@ enum htt_rx_filter_tlv_flags { +@@ -779,7 +784,7 @@ enum htt_rx_filter_tlv_flags { HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS = BIT(10), HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT = BIT(11), HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE = BIT(12), @@ -49,7 +38,7 @@ Signed-off-by: P Praneesh }; enum htt_rx_mgmt_pkt_filter_tlv_flags0 { -@@ -1104,6 +1109,21 @@ enum htt_rx_data_pkt_filter_tlv_flasg3 { +@@ -1068,6 +1073,21 @@ enum htt_rx_data_pkt_filter_tlv_flasg3 { HTT_RX_FILTER_TLV_FLAGS_PER_MSDU_HEADER | \ HTT_RX_FILTER_TLV_FLAGS_ATTENTION) @@ -71,7 +60,7 @@ Signed-off-by: P Praneesh /* msdu start. mpdu end, attention, rx hdr tlv's are not subscribed */ #define HTT_RX_TLV_FLAGS_RXDMA_RING \ (HTT_RX_FILTER_TLV_FLAGS_MPDU_START | \ -@@ -1125,10 +1145,22 @@ struct htt_rx_ring_selection_cfg_cmd { +@@ -1089,10 +1109,22 @@ struct htt_rx_ring_selection_cfg_cmd { u32 rx_mpdu_offset; u32 rx_msdu_offset; u32 rx_attn_offset; @@ -96,7 +85,7 @@ Signed-off-by: P Praneesh struct htt_rx_ring_tlv_filter { u32 rx_filter; /* see htt_rx_filter_tlv_flags */ u32 pkt_filter_flags0; /* MGMT */ -@@ -1143,6 +1175,13 @@ struct htt_rx_ring_tlv_filter { +@@ -1107,6 +1139,13 @@ struct htt_rx_ring_tlv_filter { u16 rx_msdu_end_offset; u16 rx_msdu_start_offset; u16 rx_attn_offset; @@ -112,23 +101,22 @@ Signed-off-by: P Praneesh #define HTT_STATS_FRAME_CTRL_TYPE_MGMT 0x0 --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -1116,16 +1116,27 @@ int ath12k_dp_tx_htt_rx_filter_setup(str - !!(params.flags & HAL_SRNG_FLAGS_DATA_TLV_SWAP)); - cmd->info0 |= FIELD_PREP(HTT_RX_RING_SELECTION_CFG_CMD_OFFSET_VALID, - tlv_filter->offset_valid); -+ cmd->info0 |= FIELD_PREP(HTT_RX_RING_SELECTION_CFG_CMD_DROP_THRES_VAL, -+ tlv_filter->drop_threshold_valid); - cmd->info0 |= FIELD_PREP(HTT_RX_RING_SELECTION_CFG_CMD_RXMON_GCONF_EN, - true); - - cmd->info1 = FIELD_PREP(HTT_RX_RING_SELECTION_CFG_CMD_INFO1_BUF_SIZE, - rx_buf_size); -+ cmd->info1 |= FIELD_PREP(HTT_RX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_MGMT, -+ tlv_filter->conf_len_mgmt); -+ cmd->info1 |= FIELD_PREP(HTT_RX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_CTRL, -+ tlv_filter->conf_len_ctrl); -+ cmd->info1 |= FIELD_PREP(HTT_RX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_DATA, -+ tlv_filter->conf_len_data); +@@ -1080,15 +1080,26 @@ int ath12k_dp_tx_htt_rx_filter_setup(str + HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PS); + cmd->info0 |= u32_encode_bits(tlv_filter->offset_valid, + HTT_RX_RING_SELECTION_CFG_CMD_OFFSET_VALID); ++ cmd->info0 |= u32_encode_bits(tlv_filter->drop_threshold_valid, ++ HTT_RX_RING_SELECTION_CFG_CMD_DROP_THRES_VAL); + cmd->info0 |= u32_encode_bits(true, + HTT_RX_RING_SELECTION_CFG_CMD_RXMON_GCONF_EN); + cmd->info1 = u32_encode_bits(rx_buf_size, + HTT_RX_RING_SELECTION_CFG_CMD_INFO1_BUF_SIZE); ++ cmd->info1 |= u32_encode_bits(tlv_filter->conf_len_mgmt, ++ HTT_RX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_MGMT); ++ cmd->info1 |= u32_encode_bits(tlv_filter->conf_len_ctrl, ++ HTT_RX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_CTRL); ++ cmd->info1 |= u32_encode_bits(tlv_filter->conf_len_data, ++ HTT_RX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_DATA); + cmd->pkt_type_en_flags0 = tlv_filter->pkt_filter_flags0; cmd->pkt_type_en_flags1 = tlv_filter->pkt_filter_flags1; @@ -140,7 +128,7 @@ Signed-off-by: P Praneesh if (tlv_filter->offset_valid) { cmd->rx_packet_offset = -@@ -1278,15 +1289,13 @@ int ath12k_dp_tx_htt_monitor_mode_ring_c +@@ -1241,15 +1252,13 @@ int ath12k_dp_tx_htt_monitor_mode_ring_c int ath12k_dp_tx_htt_rx_monitor_mode_ring_config(struct ath12k *ar, bool reset) { struct ath12k_base *ab = ar->ab; @@ -158,24 +146,24 @@ Signed-off-by: P Praneesh tlv_filter.pkt_filter_flags0 = HTT_RX_MON_FP_MGMT_FILTER_FLAGS0 | HTT_RX_MON_MO_MGMT_FILTER_FLAGS0; -@@ -1301,11 +1310,38 @@ int ath12k_dp_tx_htt_rx_monitor_mode_rin +@@ -1264,11 +1273,38 @@ int ath12k_dp_tx_htt_rx_monitor_mode_rin HTT_RX_MON_MO_CTRL_FILTER_FLASG3 | HTT_RX_MON_FP_DATA_FILTER_FLASG3 | HTT_RX_MON_MO_DATA_FILTER_FLASG3; + + tlv_filter.drop_threshold_valid = true; + tlv_filter.info0 = -+ FIELD_PREP(HTT_RX_TLV_FILTER_INFO0_RX_DROP_THRESHOLD, -+ HTT_RX_RING_TLV_DROP_THRESHOLD_VALUE); ++ u32_encode_bits(HTT_RX_RING_TLV_DROP_THRESHOLD_VALUE, ++ HTT_RX_TLV_FILTER_INFO0_RX_DROP_THRESHOLD); + tlv_filter.info0 |= -+ FIELD_PREP(HTT_RX_TLV_FILTER_INFO0_EN_MSDU_MPDU_LOG_MGMT_TYPE, -+ true); ++ u32_encode_bits(true, ++ HTT_RX_TLV_FILTER_INFO0_EN_MSDU_MPDU_LOG_MGMT_TYPE); + tlv_filter.info0 |= -+ FIELD_PREP(HTT_RX_TLV_FILTER_INFO0_EN_MSDU_MPDU_LOG_CTRL_TYPE, -+ true); ++ u32_encode_bits(true, ++ HTT_RX_TLV_FILTER_INFO0_EN_MSDU_MPDU_LOG_CTRL_TYPE); + tlv_filter.info0 |= -+ FIELD_PREP(HTT_RX_TLV_FILTER_INFO0_EN_MSDU_MPDU_LOG_DATA_TYPE, -+ true); ++ u32_encode_bits(true, ++ HTT_RX_TLV_FILTER_INFO0_EN_MSDU_MPDU_LOG_DATA_TYPE); + + tlv_filter.conf_len_ctrl = HTT_RX_RING_DEFAULT_DMA_LENGTH; + tlv_filter.conf_len_mgmt = HTT_RX_RING_DEFAULT_DMA_LENGTH; @@ -189,10 +177,10 @@ Signed-off-by: P Praneesh + HTT_RX_RING_PKT_TLV_OFFSET); } -- if (ab->hw_params.rxdma1_enable) { +- if (ab->hw_params->rxdma1_enable) { - ret = ath12k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, 0, - HAL_RXDMA_MONITOR_BUF, -+ for (i = 0; i < ar->ab->hw_params.num_rxmda_per_pdev; i++) { ++ for (i = 0; i < ar->ab->hw_params->num_rxmda_per_pdev; i++) { + ring_id = ar->dp.rxdma_mon_dst_ring[i].ring_id; + + ret = ath12k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id + i, @@ -200,3 +188,14 @@ Signed-off-by: P Praneesh DP_RXDMA_REFILL_RING_SIZE, &tlv_filter); if (ret) { +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -684,7 +684,7 @@ static ssize_t ath12k_write_extd_rx_stat + rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS; + rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT; + rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE; +- rx_filter |= HTT_RX_FILTER_TLV_FLAGS_ENABLE_FP; ++ rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_START_USER_INFO; + + tlv_filter.rx_filter = rx_filter; + tlv_filter.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0; diff --git a/feeds/ipq95xx/mac80211/patches/qca/640-004-ath12k-add-monitor-buffer-address-TLV-parsing.patch b/feeds/ipq95xx/mac80211/patches/qca/640-004-ath12k-add-monitor-buffer-address-TLV-parsing.patch index da490982c..498186e30 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/640-004-ath12k-add-monitor-buffer-address-TLV-parsing.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/640-004-ath12k-add-monitor-buffer-address-TLV-parsing.patch @@ -51,7 +51,7 @@ Signed-off-by: P Praneesh break; } case HAL_RXPCU_PPDU_END_INFO: { -@@ -794,47 +796,17 @@ ath12k_dp_mon_rx_parse_status_tlv(struct +@@ -794,49 +796,17 @@ ath12k_dp_mon_rx_parse_status_tlv(struct break; } @@ -60,8 +60,8 @@ Signed-off-by: P Praneesh - break; - case HAL_MON_BUF_ADDR: { - struct dp_rxdma_ring *buf_ring = &ab->dp.rxdma_mon_buf_ring; -- struct hal_mon_packet_info *packet_info = -- (struct hal_mon_packet_info *)tlv_data; +- struct dp_mon_packet_info *packet_info = +- (struct dp_mon_packet_info *)tlv_data; - int buf_id = u32_get_bits(packet_info->cookie, - DP_RXDMA_BUF_COOKIE_BUF_ID); - struct sk_buff *msdu; @@ -89,7 +89,8 @@ Signed-off-by: P Praneesh - } - case HAL_RX_MSDU_END: { - /* TODO: RX_MSDU TLV will be handled once MON BUF ADDR TLVs are -- enabled */ +- * enabled +- */ + case HAL_PHYRX_OTHER_RECEIVE_INFO: { + struct phyrx_common_user_info *cmn_usr_info = + (struct phyrx_common_user_info *)tlv_data; @@ -101,13 +102,14 @@ Signed-off-by: P Praneesh + return HAL_RX_MON_STATUS_BUF_ADDR; case HAL_RX_MPDU_END: - /* TODO: RX_MSDU TLV will be handled once MON BUF ADDR TLVs are -- enabled */ +- * enabled +- */ - break; + return HAL_RX_MON_STATUS_MPDU_END; case HAL_DUMMY: return HAL_RX_MON_STATUS_BUF_DONE; case HAL_RX_PPDU_END_STATUS_DONE: -@@ -847,54 +819,178 @@ ath12k_dp_mon_rx_parse_status_tlv(struct +@@ -849,54 +819,178 @@ ath12k_dp_mon_rx_parse_status_tlv(struct return HAL_RX_MON_STATUS_PPDU_NOT_DONE; } @@ -136,11 +138,6 @@ Signed-off-by: P Praneesh + rx_status->rate_idx = ath12k_mac_hw_rate_to_idx(sband, rate_mcs, + is_cck); + } - -- rx_pkt_offset = ar->ab->hw_params.hal_desc_sz; -- l2_hdr_offset = ath12k_dp_rx_h_l3pad(ar->ab, -- (struct hal_rx_desc *)msdu->data); -- skb_pull(msdu, rx_pkt_offset + l2_hdr_offset); + break; + case RX_MSDU_START_PKT_TYPE_11N: + rx_status->encoding = RX_ENC_HT; @@ -249,12 +246,17 @@ Signed-off-by: P Praneesh + if (rx_status->band < NUM_NL80211_BANDS) + rx_status->freq = ieee80211_channel_to_frequency(channel_num, + rx_status->band); -+ + +- rx_pkt_offset = ar->ab->hw_params->hal_desc_sz; +- l2_hdr_offset = ath12k_dp_rx_h_l3pad(ar->ab, +- (struct hal_rx_desc *)msdu->data); +- skb_pull(msdu, rx_pkt_offset + l2_hdr_offset); + ath12k_dp_mon_fill_rx_rate(ar, ppdu_info, rx_status); } -+#define DP_MON_RX_PKT_OFFSET 8 ++#define DP_MON_RX_PKT_OFFSET 8 +#define DP_MON_RX_L2_HDR_OFFSET 2 ++ + static struct sk_buff * -ath12k_dp_mon_rx_merg_msdus(struct ath12k *ar, @@ -281,10 +283,10 @@ Signed-off-by: P Praneesh goto err_merge_fail; - rx_desc = (struct hal_rx_desc *)head_msdu->data; -- err_bitmap = ath12k_dp_rx_h_mpdu_err(rx_desc); +- err_bitmap = ath12k_dp_rx_h_mpdu_err(ab, rx_desc); + err_bitmap = ppdu_info->mon_mpdu[mpdu_idx].msdu_info[0].errmap; - if (err_bitmap & DP_RX_MPDU_ERR_FCS) + if (err_bitmap & HAL_RX_MPDU_ERR_FCS) *fcs_err = true; - decap_format = ath12k_dp_rx_h_decap_type(ab, rx_desc); @@ -306,7 +308,7 @@ Signed-off-by: P Praneesh prev_buf = msdu; msdu = msdu->next; -@@ -902,15 +998,14 @@ ath12k_dp_mon_rx_merg_msdus(struct ath12 +@@ -904,15 +998,14 @@ ath12k_dp_mon_rx_merg_msdus(struct ath12 prev_buf->next = NULL; @@ -316,7 +318,7 @@ Signed-off-by: P Praneesh u8 qos_pkt = 0; - rx_desc = (struct hal_rx_desc *)head_msdu->data; -- hdr_desc = ab->hal.ops->rx_desc_get_msdu_payload(rx_desc); +- hdr_desc = ab->hw_params->hal_ops->rx_desc_get_msdu_payload(rx_desc); + msdu_payload = head_msdu->data; /* Base size */ @@ -325,7 +327,7 @@ Signed-off-by: P Praneesh if (ieee80211_is_data_qos(wh->frame_control)) qos_pkt = 1; -@@ -918,12 +1013,13 @@ ath12k_dp_mon_rx_merg_msdus(struct ath12 +@@ -920,12 +1013,13 @@ ath12k_dp_mon_rx_merg_msdus(struct ath12 msdu = head_msdu; while (msdu) { @@ -341,7 +343,7 @@ Signed-off-by: P Praneesh } prev_buf = msdu; msdu = msdu->next; -@@ -1048,7 +1144,8 @@ static void ath12k_dp_mon_update_radiota +@@ -1050,7 +1144,8 @@ static void ath12k_dp_mon_update_radiota } static void ath12k_dp_mon_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *napi, @@ -351,7 +353,7 @@ Signed-off-by: P Praneesh struct ieee80211_rx_status *status) { static const struct ieee80211_radiotap_he known = { -@@ -1073,7 +1170,7 @@ static void ath12k_dp_mon_rx_deliver_msd +@@ -1075,7 +1170,7 @@ static void ath12k_dp_mon_rx_deliver_msd } if (!(status->flag & RX_FLAG_ONLY_MONITOR)) @@ -360,7 +362,7 @@ Signed-off-by: P Praneesh spin_lock_bh(&ar->ab->base_lock); peer = ath12k_dp_rx_h_find_peer(ar->ab, msdu); if (peer && peer->sta) -@@ -1122,7 +1219,7 @@ static void ath12k_dp_mon_rx_deliver_msd +@@ -1124,7 +1219,7 @@ static void ath12k_dp_mon_rx_deliver_msd ieee80211_rx_napi(ar->hw, pubsta, msdu, napi); } @@ -369,7 +371,7 @@ Signed-off-by: P Praneesh struct sk_buff *head_msdu, struct hal_rx_mon_ppdu_info *ppduinfo, struct napi_struct *napi) -@@ -1132,8 +1229,8 @@ static int ath12k_dp_mon_rx_deliver(stru +@@ -1134,8 +1229,8 @@ static int ath12k_dp_mon_rx_deliver(stru struct ieee80211_rx_status *rxs = &dp->rx_status; bool fcs_err = false; @@ -380,7 +382,7 @@ Signed-off-by: P Praneesh if (!mon_skb) goto mon_deliver_fail; -@@ -1158,7 +1255,8 @@ static int ath12k_dp_mon_rx_deliver(stru +@@ -1160,7 +1255,8 @@ static int ath12k_dp_mon_rx_deliver(stru } rxs->flag |= RX_FLAG_ONLY_MONITOR; ath12k_dp_mon_update_radiotap(ar, ppduinfo, mon_skb, rxs); @@ -390,7 +392,7 @@ Signed-off-by: P Praneesh mon_skb = skb_next; } while (mon_skb); rxs->flag = 0; -@@ -1175,18 +1273,147 @@ mon_deliver_fail: +@@ -1177,18 +1273,147 @@ mon_deliver_fail: return -EINVAL; } @@ -417,31 +419,31 @@ Signed-off-by: P Praneesh +static void +ath12k_dp_mon_parse_rx_msdu_end(u8 *tlv_data, struct hal_rx_mon_ppdu_info *ppdu_info) +{ -+ struct rx_msdu_end_qcn92xx *msdu_end = -+ (struct rx_msdu_end_qcn92xx *)tlv_data; ++ struct rx_msdu_end_qcn9274 *msdu_end = ++ (struct rx_msdu_end_qcn9274 *)tlv_data; + u32 info = __le32_to_cpu(msdu_end->info13); + u32 errmap = 0, mpdu_idx, msdu_idx, decap_format; + + if (info & RX_MSDU_END_INFO13_FCS_ERR) -+ errmap |= DP_RX_MPDU_ERR_FCS; ++ errmap |= HAL_RX_MPDU_ERR_FCS; + + if (info & RX_MSDU_END_INFO13_DECRYPT_ERR) -+ errmap |= DP_RX_MPDU_ERR_DECRYPT; ++ errmap |= HAL_RX_MPDU_ERR_DECRYPT; + + if (info & RX_MSDU_END_INFO13_TKIP_MIC_ERR) -+ errmap |= DP_RX_MPDU_ERR_TKIP_MIC; ++ errmap |= HAL_RX_MPDU_ERR_TKIP_MIC; + + if (info & RX_MSDU_END_INFO13_A_MSDU_ERROR) -+ errmap |= DP_RX_MPDU_ERR_AMSDU_ERR; ++ errmap |= HAL_RX_MPDU_ERR_AMSDU_ERR; + + if (info & RX_MSDU_END_INFO13_OVERFLOW_ERR) -+ errmap |= DP_RX_MPDU_ERR_OVERFLOW; ++ errmap |= HAL_RX_MPDU_ERR_OVERFLOW; + + if (info & RX_MSDU_END_INFO13_MSDU_LEN_ERR) -+ errmap |= DP_RX_MPDU_ERR_MSDU_LEN; ++ errmap |= HAL_RX_MPDU_ERR_MSDU_LEN; + + if (info & RX_MSDU_END_INFO13_MPDU_LEN_ERR) -+ errmap |= DP_RX_MPDU_ERR_MPDU_LEN; ++ errmap |= HAL_RX_MPDU_ERR_MPDU_LEN; + + decap_format = u32_get_bits(info, RX_MSDU_END_INFO11_DECAP_FORMAT); + @@ -458,15 +460,15 @@ Signed-off-by: P Praneesh +{ + int offset; + -+ if (ppdu_info->mpdu_count >= HAL_RX_MAX_MPDU) { ++ if (ppdu_info->mpdu_count > HAL_RX_MAX_MPDU) { + ath12k_warn(ar->ab, "MPDU count reached max limit\n"); + return; + } + + switch (hal_status) { + case HAL_RX_MON_STATUS_BUF_ADDR: { -+ struct hal_mon_packet_info *packet_info = -+ (struct hal_mon_packet_info *)tlv_data; ++ struct dp_mon_packet_info *packet_info = ++ (struct dp_mon_packet_info *)tlv_data; + int buf_id = u32_get_bits(packet_info->cookie, + DP_RXDMA_BUF_COOKIE_BUF_ID); + struct sk_buff *msdu; @@ -482,7 +484,7 @@ Signed-off-by: P Praneesh + + if (unlikely(!msdu)) { + ath12k_warn(ar->ab, -+ "montior destination with invalid buf_id %d\n", ++ "mon buf_addr: dest desc with inval buf_id %d\n", + buf_id); + return; + } @@ -542,7 +544,7 @@ Signed-off-by: P Praneesh do { tlv = (struct hal_tlv_64_hdr *)ptr; -@@ -1204,50 +1431,53 @@ ath12k_dp_mon_parse_rx_dest(struct ath12 +@@ -1206,50 +1431,53 @@ ath12k_dp_mon_parse_rx_dest(struct ath12 if (tlv_tag == HAL_RX_PPDU_END) tlv_len = sizeof(struct hal_rx_rxpcu_classification_overview); @@ -617,7 +619,17 @@ Signed-off-by: P Praneesh } return hal_status; } -@@ -2468,8 +2698,9 @@ move_next: +@@ -1262,7 +1490,8 @@ int ath12k_dp_mon_buf_replenish(struct a + struct sk_buff *skb; + struct hal_srng *srng; + dma_addr_t paddr; +- u32 cookie, buf_id; ++ u32 cookie; ++ int buf_id; + + srng = &ab->hal.srng_list[buf_ring->refill_buf_ring.ring_id]; + spin_lock_bh(&srng->lock); +@@ -2468,8 +2697,9 @@ move_next: log_type, rx_buf_sz); if (flag == ATH12K_DP_RX_MONITOR_MODE) @@ -629,7 +641,7 @@ Signed-off-by: P Praneesh else hal_status = ath12k_dp_mon_tx_parse_mon_status(ar, pmon, mac_id, -@@ -2610,7 +2841,7 @@ move_next: +@@ -2610,7 +2840,7 @@ move_next: while ((skb = __skb_dequeue(&skb_list))) { @@ -640,16 +652,16 @@ Signed-off-by: P Praneesh dev_kfree_skb_any(skb); --- a/drivers/net/wireless/ath/ath12k/dp_mon.h +++ b/drivers/net/wireless/ath/ath12k/dp_mon.h -@@ -22,6 +22,8 @@ - #define HAL_RX_UL_OFDMA_USER_INFO_V0_W1_RU_START GENMASK(15, 9) - #define HAL_RX_UL_OFDMA_USER_INFO_V0_W1_RU_SIZE GENMASK(18, 16) +@@ -12,6 +12,8 @@ + #define ATH12K_DP_TX_MONITOR_MODE 0 + #define ATH12K_DP_RX_MONITOR_MODE 1 +#define ATH12K_WIFIRX_DOT11_OFFSET 5 + enum dp_mon_tx_ppdu_info_type { DP_MON_TX_PROT_PPDU_INFO, DP_MON_TX_DATA_PPDU_INFO -@@ -225,7 +227,7 @@ struct dp_mon_tx_ppdu_info { +@@ -74,7 +76,7 @@ struct dp_mon_tx_ppdu_info { enum hal_rx_mon_status ath12k_dp_mon_rx_parse_mon_status(struct ath12k *ar, @@ -712,9 +724,9 @@ Signed-off-by: P Praneesh #define HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO1_RSSI_COMB GENMASK(15, 8) struct hal_rx_phyrx_rssi_legacy_info { -@@ -487,6 +506,13 @@ struct hal_rx_msdu_list { - u8 rbm[HAL_RX_NUM_MSDU_DESC]; - }; +@@ -526,6 +545,13 @@ struct hal_rx_resp_req_info { + __le32 reserved2[5]; + } __packed; +#define HAL_RX_PHY_CMN_USER_INFO0_GI GENMASK(17, 16) +struct phyrx_common_user_info { diff --git a/feeds/ipq95xx/mac80211/patches/qca/640-005-ath12k-eht-tlv-parsing.patch b/feeds/ipq95xx/mac80211/patches/qca/640-005-ath12k-eht-tlv-parsing.patch index 32ebeae31..0862cdd69 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/640-005-ath12k-eht-tlv-parsing.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/640-005-ath12k-eht-tlv-parsing.patch @@ -1103,7 +1103,7 @@ Signed-off-by: P Praneesh }; #define HAL_RX_PPDU_START_INFO0_PPDU_ID GENMASK(15, 0) -@@ -513,6 +542,373 @@ struct phyrx_common_user_info { +@@ -552,6 +581,373 @@ struct phyrx_common_user_info { __le32 rsvd1; }; @@ -1477,10 +1477,10 @@ Signed-off-by: P Praneesh void ath12k_hal_reo_status_queue_stats(struct ath12k_base *ab, u32 *reo_desc, struct hal_reo_status *status); void ath12k_hal_reo_flush_queue_status(struct ath12k_base *ab, u32 *reo_desc, -@@ -645,4 +1041,142 @@ void ath12k_hal_rx_reo_ent_buf_paddr_get - #define HE_STA_MCS_KNOWN 0x20 - #define HE_STA_DCM_KNOWN 0x40 - #define HE_STA_CODING_KNOWN 0x80 +@@ -702,4 +1098,142 @@ void ath12k_hal_rx_reo_ent_buf_paddr_get + #define HAL_RX_MPDU_ERR_MSDU_LEN BIT(5) + #define HAL_RX_MPDU_ERR_MPDU_LEN BIT(6) + #define HAL_RX_MPDU_ERR_UNENCRYPTED_FRAME BIT(7) + +/* U-SIG Common Mask */ +#define USIG_PHY_VERSION_KNOWN 0x00000001 @@ -1620,27 +1620,6 @@ Signed-off-by: P Praneesh +#define EHT_USER_BEAMFORMING_SHIFT 29 +#define EHT_USER_SPATIAL_CONFIG_SHIFT 24 #endif ---- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c -+++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c -@@ -14,8 +14,6 @@ - #define HTT_MAX_STRING_LEN 256 - #define HTT_MAX_PRINT_CHAR_PER_ELEM 15 - --#define HTT_TLV_HDR_LEN 4 -- - #define PRINT_ARRAY_TO_BUF(out, buflen, arr, str, len, newline) \ - do { \ - int index = 0; u8 i; const char *str_val = str; \ ---- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h -+++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h -@@ -10,6 +10,7 @@ - #define HTT_STATS_COOKIE_LSB GENMASK_ULL(31, 0) - #define HTT_STATS_COOKIE_MSB GENMASK_ULL(63, 32) - #define HTT_STATS_MAGIC_VALUE 0xF0F0F0F0 -+#define HTT_TLV_HDR_LEN 4 - - enum htt_tlv_tag_t { - HTT_STATS_TX_PDEV_CMN_TAG = 0, --- a/drivers/net/wireless/ath/ath12k/dp_mon.h +++ b/drivers/net/wireless/ath/ath12k/dp_mon.h @@ -8,6 +8,7 @@ @@ -1651,3 +1630,23 @@ Signed-off-by: P Praneesh #define ATH12K_DP_TX_MONITOR_MODE 0 #define ATH12K_DP_RX_MONITOR_MODE 1 +--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c +@@ -14,7 +14,6 @@ + #define HTT_MAX_STRING_LEN 256 + #define HTT_MAX_PRINT_CHAR_PER_ELEM 15 + +-#define HTT_TLV_HDR_LEN 4 + + #define PRINT_ARRAY_TO_BUF(out, buflen, arr, str, len, newline) \ + do { \ +--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h ++++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h +@@ -10,6 +10,7 @@ + #define HTT_STATS_COOKIE_LSB GENMASK_ULL(31, 0) + #define HTT_STATS_COOKIE_MSB GENMASK_ULL(63, 32) + #define HTT_STATS_MAGIC_VALUE 0xF0F0F0F0 ++#define HTT_TLV_HDR_LEN 4 + + enum htt_tlv_tag_t { + HTT_STATS_TX_PDEV_CMN_TAG = 0, diff --git a/feeds/ipq95xx/mac80211/patches/qca/640-008-ath12k-fix-hal_rx-structures.patch b/feeds/ipq95xx/mac80211/patches/qca/640-008-ath12k-fix-hal_rx-structures.patch index eef56deb5..e360ecd35 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/640-008-ath12k-fix-hal_rx-structures.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/640-008-ath12k-fix-hal_rx-structures.patch @@ -57,7 +57,7 @@ Signed-off-by: Aaradhana Sahu #define HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_MCS GENMASK(18, 15) #define HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_DCM BIT(19) #define HAL_RX_HE_SIG_B2_OFDMA_INFO_INFO0_STA_CODING BIT(20) -@@ -694,33 +693,33 @@ struct hal_mon_usig_hdr { +@@ -733,33 +732,33 @@ struct hal_mon_usig_hdr { union hal_mon_usig_non_cmn usig_2; } __packed; @@ -253,8 +253,8 @@ Signed-off-by: Aaradhana Sahu break; --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -1853,6 +1853,8 @@ void ath12k_dp_htt_htc_t2h_msg_handler(s - resp->peer_map_ev.info1); +@@ -1871,6 +1871,8 @@ void ath12k_dp_htt_htc_t2h_msg_handler(s + HTT_T2H_PEER_MAP_INFO1_MAC_ADDR_H16); ath12k_dp_get_mac_addr(resp->peer_map_ev.mac_addr_l32, peer_mac_h16, mac_addr); + ast_hash = FIELD_GET(HTT_T2H_PEER_MAP_INFO2_AST_HASH_VAL, diff --git a/feeds/ipq95xx/mac80211/patches/qca/640-ath12k-Ignore-frags-from-uninitialized-peer-in-dp.patch b/feeds/ipq95xx/mac80211/patches/qca/640-ath12k-Ignore-frags-from-uninitialized-peer-in-dp.patch index c323bad4f..4b06dfafb 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/640-ath12k-Ignore-frags-from-uninitialized-peer-in-dp.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/640-ath12k-Ignore-frags-from-uninitialized-peer-in-dp.patch @@ -46,15 +46,15 @@ Signed-off-by: Harshitha Prem --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -883,7 +883,6 @@ void ath12k_peer_rx_tid_cleanup(struct a +@@ -894,7 +894,6 @@ void ath12k_dp_rx_peer_tid_cleanup(struc - ath12k_peer_rx_tid_delete(ar, peer, i); + ath12k_dp_rx_peer_tid_delete(ar, peer, i); ath12k_dp_rx_frags_cleanup(rx_tid, true); - spin_unlock_bh(&ar->ab->base_lock); del_timer_sync(&rx_tid->frag_timer); spin_lock_bh(&ar->ab->base_lock); -@@ -2909,6 +2908,7 @@ int ath12k_peer_rx_frag_setup(struct ath +@@ -2932,6 +2931,7 @@ int ath12k_dp_rx_peer_frag_setup(struct } peer->tfm_mmic = tfm; @@ -62,7 +62,7 @@ Signed-off-by: Harshitha Prem spin_unlock_bh(&ab->base_lock); return 0; -@@ -3364,6 +3364,14 @@ static int ath12k_dp_rx_frag_h_mpdu(stru +@@ -3389,6 +3389,14 @@ static int ath12k_dp_rx_frag_h_mpdu(stru ret = -ENOENT; goto out_unlock; } @@ -77,7 +77,7 @@ Signed-off-by: Harshitha Prem rx_tid = &peer->rx_tid[tid]; if ((!skb_queue_empty(&rx_tid->rx_frags) && seqno != rx_tid->cur_sn) || -@@ -3379,7 +3387,7 @@ static int ath12k_dp_rx_frag_h_mpdu(stru +@@ -3404,7 +3412,7 @@ static int ath12k_dp_rx_frag_h_mpdu(stru goto out_unlock; } @@ -90,14 +90,14 @@ Signed-off-by: Harshitha Prem +++ b/drivers/net/wireless/ath/ath12k/dp.c @@ -38,6 +38,7 @@ void ath12k_dp_peer_cleanup(struct ath12 - ath12k_peer_rx_tid_cleanup(ar, peer); + ath12k_dp_rx_peer_tid_cleanup(ar, peer); crypto_free_shash(peer->tfm_mmic); + peer->dp_setup_done = false; spin_unlock_bh(&ab->base_lock); } @@ -73,7 +74,8 @@ int ath12k_dp_peer_setup(struct ath12k * - ret = ath12k_peer_rx_frag_setup(ar, addr, vdev_id); + ret = ath12k_dp_rx_peer_frag_setup(ar, addr, vdev_id); if (ret) { ath12k_warn(ab, "failed to setup rx defrag context\n"); - return ret; @@ -108,10 +108,10 @@ Signed-off-by: Harshitha Prem /* TODO: Setup other peer specific resource used in data path */ --- a/drivers/net/wireless/ath/ath12k/peer.h +++ b/drivers/net/wireless/ath/ath12k/peer.h -@@ -42,6 +42,11 @@ struct ath12k_peer { - u16 sec_type_grp; +@@ -45,6 +45,11 @@ struct ath12k_peer { struct ppdu_user_delayba ppdu_stats_delayba; bool delayba_flag; + bool is_authorized; + + /* The below flag indicates whether + * a peer has setup its datapath or not diff --git a/feeds/ipq95xx/mac80211/patches/qca/640-ath12k-allocate-memory-based-on-MEM-type-in-segmente.patch b/feeds/ipq95xx/mac80211/patches/qca/640-ath12k-allocate-memory-based-on-MEM-type-in-segmente.patch deleted file mode 100644 index 0ebf4b5e5..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/640-ath12k-allocate-memory-based-on-MEM-type-in-segmente.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 5a41a3b492e0fe88a5dd744eda940eecdefe66a5 Mon Sep 17 00:00:00 2001 -From: Balamurugan Selvarajan -Date: Wed, 1 Jun 2022 13:13:37 +0530 -Subject: [PATCH] ath12k: allocate memory based on MEM type in segmented mode - -In segmented mode earlier logic was based on number of -segments. When the number of segments gets increased in -the firmware, the same must be maintained in the host else -driver initialization will fail. - -Initially QCN9224 firmware will request higher memory greater -than MAX_ORDER, host will fail in memory allocation and set's -target_mem_delayed falg to true. Post this firmware will request -memory in smaller chunks. With current logic memory gets allocated -based on memory type. For the non-supported memory type -the host will fill NULL and firmware will handle gracefully -without crashing. - -Signed-off-by: Balamurugan Selvarajan ---- - drivers/net/wireless/ath/ath12k/qmi.c | 41 ++++++++++++++++----------- - 1 file changed, 25 insertions(+), 16 deletions(-) - -diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c -index 81821f4..595f62b 100644 ---- a/drivers/net/wireless/ath/ath12k/qmi.c -+++ b/drivers/net/wireless/ath/ath12k/qmi.c -@@ -18,6 +18,7 @@ - - #define SLEEP_CLOCK_SELECT_INTERNAL_BIT 0x02 - #define HOST_CSTATE_BIT 0x04 -+#define MB(x) ((x) * 1024 * 1024) - - bool ath12k_cold_boot_cal = 1; - module_param_named(cold_boot_cal, ath12k_cold_boot_cal, bool, 0644); -@@ -2404,27 +2405,35 @@ static int ath12k_qmi_alloc_target_mem_chunk(struct ath12k_base *ab) - - for (i = 0; i < ab->qmi.mem_seg_count; i++) { - chunk = &ab->qmi.target_mem[i]; -- chunk->v.addr = dma_alloc_coherent(ab->dev, -+ switch (chunk->type) { -+ case HOST_DDR_REGION_TYPE: -+ case M3_DUMP_REGION_TYPE: -+ case PAGEABLE_MEM_TYPE: -+ chunk->v.addr = dma_alloc_coherent(ab->dev, - chunk->size, - &chunk->paddr, -- GFP_KERNEL); -- if (!chunk->v.addr) { -- if (ab->qmi.mem_seg_count <= ATH12K_QMI_FW_MEM_REQ_SEGMENT_CNT) { -- ath12k_dbg(ab, ATH12K_DBG_QMI, -- "qmi dma allocation failed (%d B type %u), will try later with small size\n", -- chunk->size, -- chunk->type); -- ath12k_qmi_free_target_mem_chunk(ab); -- ab->qmi.target_mem_delayed = true; -- return 0; -+ GFP_KERNEL | __GFP_NOWARN); -+ if (!chunk->v.addr) { -+ if (chunk->size > MB(2)) { -+ ath12k_warn(ab, -+ "qmi dma allocation failed (%d B type %u), will try later with small size\n", -+ chunk->size, -+ chunk->type); -+ ath12k_qmi_free_target_mem_chunk(ab); -+ ab->qmi.target_mem_delayed = true; -+ return 0; -+ } -+ return -ENOMEM; - } -- ath12k_err(ab, "failed to alloc memory, size: 0x%x, type: %u\n", -- chunk->size, -- chunk->type); -- return -EINVAL; -+ break; -+ default: -+ ath12k_warn(ab, "memory type %d not supported\n", -+ chunk->type); -+ chunk->paddr = 0; -+ chunk->v.addr = NULL; -+ break; - } - } -- - return 0; - } - --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/640-ath12k-fix-secu-connection-due-to-auth-early.patch b/feeds/ipq95xx/mac80211/patches/qca/640-ath12k-fix-secu-connection-due-to-auth-early.patch index 1365c37cb..5b2ce7859 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/640-ath12k-fix-secu-connection-due-to-auth-early.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/640-ath12k-fix-secu-connection-due-to-auth-early.patch @@ -32,48 +32,9 @@ Signed-off-by: Thiraviyam Mariyappan --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -3062,6 +3062,8 @@ static void ath12k_bss_assoc(struct ieee - struct ath12k_vif *arvif = (void *)vif->drv_priv; - struct peer_assoc_params peer_arg; - struct ieee80211_sta *ap_sta; -+ struct ath12k_peer *peer; -+ bool is_auth = false; - struct ieee80211_sta_he_cap he_cap; - int ret; - struct vdev_up_params params = { 0 }; -@@ -3136,13 +3138,23 @@ static void ath12k_bss_assoc(struct ieee - "mac vdev %d up (associated) bssid %pM aid %d\n", - arvif->vdev_id, bss_conf->bssid, bss_conf->aid); +@@ -5004,6 +5004,34 @@ static int ath12k_mac_op_sta_state(struc -+ spin_lock_bh(&ar->ab->base_lock); -+ -+ peer = ath12k_peer_find(ar->ab, arvif->vdev_id, arvif->bssid); -+ if (peer && peer->is_authorized) -+ is_auth = true; -+ -+ spin_unlock_bh(&ar->ab->base_lock); -+ - /* Authorize BSS Peer */ -- ret = ath12k_wmi_set_peer_param(ar, arvif->bssid, -- arvif->vdev_id, -- WMI_PEER_AUTHORIZE, -- 1); -- if (ret) -- ath12k_warn(ar->ab, "Unable to authorize BSS peer: %d\n", ret); -+ if (is_auth) { -+ ret = ath12k_wmi_set_peer_param(ar, arvif->bssid, -+ arvif->vdev_id, -+ WMI_PEER_AUTHORIZE, -+ 1); -+ if (ret) -+ ath12k_warn(ar->ab, "Unable to authorize BSS peer: %d\n", ret); -+ } - - ret = ath12k_wmi_send_obss_spr_cmd(ar, arvif->vdev_id, - &bss_conf->he_obss_pd); -@@ -4936,6 +4948,34 @@ static int ath12k_mac_op_sta_state(struc - ath12k_warn(ar->ab, "Failed to associate station: %pM\n", - sta->addr); + spin_unlock_bh(&ar->ab->base_lock); } else if (old_state == IEEE80211_STA_ASSOC && + new_state == IEEE80211_STA_AUTHORIZED) { + spin_lock_bh(&ar->ab->base_lock); @@ -106,13 +67,3 @@ Signed-off-by: Thiraviyam Mariyappan new_state == IEEE80211_STA_AUTH && (vif->type == NL80211_IFTYPE_AP || vif->type == NL80211_IFTYPE_MESH_POINT || ---- a/drivers/net/wireless/ath/ath12k/peer.h -+++ b/drivers/net/wireless/ath/ath12k/peer.h -@@ -42,6 +42,7 @@ struct ath12k_peer { - u16 sec_type_grp; - struct ppdu_user_delayba ppdu_stats_delayba; - bool delayba_flag; -+ bool is_authorized; - - /* The below flag indicates whether - * a peer has setup its datapath or not diff --git a/feeds/ipq95xx/mac80211/patches/qca/641-0001-ath12k-fix-4-addr-tx-failure-for-AP-and-STA-modes.patch b/feeds/ipq95xx/mac80211/patches/qca/641-0001-ath12k-fix-4-addr-tx-failure-for-AP-and-STA-modes.patch index 7693ec64e..67b66135f 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/641-0001-ath12k-fix-4-addr-tx-failure-for-AP-and-STA-modes.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/641-0001-ath12k-fix-4-addr-tx-failure-for-AP-and-STA-modes.patch @@ -41,17 +41,18 @@ Signed-off-by: Thiraviyam Mariyappan struct rate_info txrate; u32 peer_nss; struct rate_info last_txrate; -@@ -485,6 +486,7 @@ struct ath12k_sta { +@@ -485,6 +486,8 @@ struct ath12k_sta { /* protected by conf_mutex */ bool aggr_mode; #endif ++ + bool use_4addr_set; }; #define ATH12K_HALF_20MHZ_BW 10 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -4754,6 +4754,31 @@ static void ath12k_sta_rc_update_wk(stru +@@ -4804,6 +4804,31 @@ static void ath12k_sta_rc_update_wk(stru mutex_unlock(&ar->conf_mutex); } @@ -83,7 +84,7 @@ Signed-off-by: Thiraviyam Mariyappan static int ath12k_mac_inc_num_stations(struct ath12k_vif *arvif, struct ieee80211_sta *sta) { -@@ -4892,8 +4917,10 @@ static int ath12k_mac_op_sta_state(struc +@@ -4942,8 +4967,10 @@ static int ath12k_mac_op_sta_state(struc /* cancel must be done outside the mutex to avoid deadlock */ if ((old_state == IEEE80211_STA_NONE && @@ -95,7 +96,7 @@ Signed-off-by: Thiraviyam Mariyappan mutex_lock(&ar->conf_mutex); -@@ -4902,6 +4929,7 @@ static int ath12k_mac_op_sta_state(struc +@@ -4952,6 +4979,7 @@ static int ath12k_mac_op_sta_state(struc memset(arsta, 0, sizeof(*arsta)); arsta->arvif = arvif; INIT_WORK(&arsta->update_wk, ath12k_sta_rc_update_wk); @@ -103,7 +104,7 @@ Signed-off-by: Thiraviyam Mariyappan ret = ath12k_mac_station_add(ar, vif, sta); if (ret) -@@ -5025,6 +5053,19 @@ out: +@@ -5103,6 +5131,19 @@ out: return ret; } @@ -123,7 +124,7 @@ Signed-off-by: Thiraviyam Mariyappan static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, -@@ -9224,6 +9265,7 @@ static const struct ieee80211_ops ath12k +@@ -9320,6 +9361,7 @@ static const struct ieee80211_ops ath12k .cancel_hw_scan = ath12k_mac_op_cancel_hw_scan, .set_key = ath12k_mac_op_set_key, .sta_state = ath12k_mac_op_sta_state, diff --git a/feeds/ipq95xx/mac80211/patches/qca/641-0002-ath12k-handle-4addr-NULL-EAPOL-frame-from-wbm-err-path.patch b/feeds/ipq95xx/mac80211/patches/qca/641-0002-ath12k-handle-4addr-NULL-EAPOL-frame-from-wbm-err-path.patch index 3017b76c0..919f43cb7 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/641-0002-ath12k-handle-4addr-NULL-EAPOL-frame-from-wbm-err-path.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/641-0002-ath12k-handle-4addr-NULL-EAPOL-frame-from-wbm-err-path.patch @@ -28,7 +28,7 @@ Signed-off-by: Thiraviyam Mariyappan --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -3778,6 +3778,53 @@ static void ath12k_dp_rx_h_tkip_mic_err( +@@ -3804,6 +3804,56 @@ static void ath12k_dp_rx_h_tkip_mic_err( HAL_ENCRYPT_TYPE_TKIP_MIC, status, false); } @@ -40,21 +40,24 @@ Signed-off-by: Thiraviyam Mariyappan + u8 l3pad_bytes; + struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu); + struct hal_rx_desc *rx_desc = (struct hal_rx_desc*)msdu->data; -+ u32 hal_rx_desc_sz = ar->ab->hw_params.hal_desc_sz; ++ u32 hal_rx_desc_sz = ar->ab->hw_params->hal_desc_sz; + struct ieee80211_hdr *hdr; + size_t hdr_len; -+ struct ath12k_dp_rfc1042_hdr *llc; ++ struct ath12k_dp_rx_rfc1042_hdr *llc; + bool drop = false; + + msdu_len = ath12k_dp_rx_h_msdu_len(ab, rx_desc); + peer_id = ath12k_dp_rx_h_peer_id(ab, rx_desc); + ar->ab->soc_stats.rxdma_error[rxcb->err_code]++; + ++ spin_lock_bh(&ab->base_lock); + if(!ath12k_peer_find_by_id(ab, peer_id)) { ++ spin_unlock_bh(&ab->base_lock); + ath12k_dbg(ab, ATH12K_DBG_DATA, "invalid peer id received in wbm err pkt%d\n", + peer_id); + return -EINVAL; + } ++ spin_unlock_bh(&ab->base_lock); + l3pad_bytes = ath12k_dp_rx_h_l3pad(ab, rx_desc); + + if ((hal_rx_desc_sz + l3pad_bytes + msdu_len) > DP_RX_BUFFER_SIZE) @@ -82,26 +85,26 @@ Signed-off-by: Thiraviyam Mariyappan static bool ath12k_dp_rx_h_rxdma_err(struct ath12k *ar, struct sk_buff *msdu, struct ieee80211_rx_status *status) { -@@ -3789,6 +3836,9 @@ static bool ath12k_dp_rx_h_rxdma_err(str +@@ -3816,6 +3866,9 @@ static bool ath12k_dp_rx_h_rxdma_err(str ar->ab->soc_stats.rxdma_error[rxcb->err_code]++; switch (rxcb->err_code) { -+ case HAL_REO_ENTR_RING_RXDMA_ECODE_ARXDMA_UNAUTH_WDS_ERR: ++ case HAL_REO_ENTR_RING_RXDMA_ECODE_UNAUTH_WDS_ERR: + drop = ath12k_dp_rx_h_4addr_null_frame_handler(ar, msdu, status); + break; case HAL_REO_ENTR_RING_RXDMA_ECODE_DECRYPT_ERR: case HAL_REO_ENTR_RING_RXDMA_ECODE_TKIP_MIC_ERR: - err_bitmap = ath12k_dp_rx_h_mpdu_err(rx_desc); + err_bitmap = ath12k_dp_rx_h_mpdu_err(ab, rx_desc); --- a/drivers/net/wireless/ath/ath12k/hal_desc.h +++ b/drivers/net/wireless/ath/ath12k/hal_desc.h -@@ -986,6 +986,10 @@ enum hal_reo_entr_rxdma_ecode { +@@ -993,6 +993,10 @@ enum hal_reo_entr_rxdma_ecode { HAL_REO_ENTR_RING_RXDMA_ECODE_FLOW_TIMEOUT_ERR, HAL_REO_ENTR_RING_RXDMA_ECODE_FLUSH_REQUEST_ERR, HAL_REO_ENTR_RING_RXDMA_ECODE_AMSDU_FRAG_ERR, -+ HAL_REO_ENTR_RING_RXDMA_ECODE_ARXDMA_MULTICAST_ECHO_ERR, -+ HAL_REO_ENTR_RING_RXDMA_ECODE_ARXDMA_AMSDU_ADDR_MISMATCH_ERR, -+ HAL_REO_ENTR_RING_RXDMA_ECODE_ARXDMA_UNAUTH_WDS_ERR, -+ HAL_REO_ENTR_RING_RXDMA_ECODE_ARXDMA_GROUPCAST_AMSDU_OR_WDS_ERR, ++ HAL_REO_ENTR_RING_RXDMA_ECODE_MULTICAST_ECHO_ERR, ++ HAL_REO_ENTR_RING_RXDMA_ECODE_AMSDU_ADDR_MISMATCH_ERR, ++ HAL_REO_ENTR_RING_RXDMA_ECODE_UNAUTH_WDS_ERR, ++ HAL_REO_ENTR_RING_RXDMA_ECODE_GROUPCAST_AMSDU_OR_WDS_ERR, HAL_REO_ENTR_RING_RXDMA_ECODE_MAX, }; diff --git a/feeds/ipq95xx/mac80211/patches/qca/641-ath12k-Add-support-for-PCSS-SSR-dump-collection.patch b/feeds/ipq95xx/mac80211/patches/qca/641-ath12k-Add-support-for-PCSS-SSR-dump-collection.patch index bf1304dfb..e777b63cf 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/641-ath12k-Add-support-for-PCSS-SSR-dump-collection.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/641-ath12k-Add-support-for-PCSS-SSR-dump-collection.patch @@ -30,23 +30,9 @@ Signed-off-by: Dinesh Karthikeyan drivers/net/wireless/ath/ath12k/wmi.h | 15 ++ 8 files changed, 442 insertions(+) -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/core.h 2022-07-17 14:36:35.867436883 +0530 -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.h 2022-07-17 14:36:35.855436846 +0530 -@@ -552,6 +552,7 @@ - u32 pktlog_peer_valid; - u8 pktlog_peer_addr[ETH_ALEN]; - u32 rx_filter; -+ bool enable_m3_dump; - }; - - struct ath12k_per_peer_tx_stats { -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/coredump.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/coredump.c 2022-07-17 14:36:35.867436883 +0530 -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/coredump.c 2022-07-17 14:37:39.195631007 +0530 -@@ -220,6 +220,13 @@ +--- a/drivers/net/wireless/ath/ath12k/coredump.c ++++ b/drivers/net/wireless/ath/ath12k/coredump.c +@@ -220,6 +220,13 @@ void ath12k_coredump_download_rddm(struc seg_info->type = ATH12K_FW_PAGEABLE_DATA; seg_info++; } @@ -60,7 +46,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor seg_info->len = ab->qmi.target_mem[i].size; seg_info->addr = ab->qmi.target_mem[i].paddr; seg_info->vaddr = ab->qmi.target_mem[i].v.addr; -@@ -337,3 +344,45 @@ +@@ -337,3 +344,45 @@ int ath12k_coredump_mhi_update_bhie_tabl return ret; } @@ -106,11 +92,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor + if (ret < 0) + ath12k_warn(ab, "qmi M3 dump upload done failed\n"); +} -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/coredump.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/coredump.h 2022-07-17 14:36:35.867436883 +0530 -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/coredump.h 2022-07-17 14:36:35.855436846 +0530 -@@ -79,6 +79,8 @@ +--- a/drivers/net/wireless/ath/ath12k/coredump.h ++++ b/drivers/net/wireless/ath/ath12k/coredump.h +@@ -79,6 +79,8 @@ void ath12k_coredump_build_inline(struct struct ath12k_dump_segment *segments, int num_seg); void ath12k_coredump_qdss_dump(struct ath12k_base *ab, struct ath12k_qmi_event_qdss_trace_save_data *event_data); @@ -119,7 +103,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor #else static inline void ath12k_coredump_download_rddm(struct ath12k_base *ab) { -@@ -94,6 +96,11 @@ +@@ -94,6 +96,11 @@ ath12k_coredump_qdss_dump(struct ath12k_ struct ath12k_qmi_event_qdss_trace_save_data *event_data) { } @@ -131,92 +115,8 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor #endif #endif -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/debugfs.c 2022-07-17 14:36:35.867436883 +0530 -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs.c 2022-07-17 14:36:35.855436846 +0530 -@@ -1459,6 +1459,67 @@ - .llseek = default_llseek, - }; - -+static ssize_t ath12k_write_enable_m3_dump(struct file *file, -+ const char __user *ubuf, -+ size_t count, loff_t *ppos) -+{ -+ struct ath12k *ar = file->private_data; -+ bool enable; -+ int ret; -+ -+ if (kstrtobool_from_user(ubuf, count, &enable)) -+ return -EINVAL; -+ -+ mutex_lock(&ar->conf_mutex); -+ -+ if (ar->state != ATH12K_STATE_ON) { -+ ret = -ENETDOWN; -+ goto exit; -+ } -+ -+ if (enable == ar->debug.enable_m3_dump) { -+ ret = count; -+ goto exit; -+ } -+ -+ ret = ath12k_wmi_pdev_m3_dump_enable(ar, enable); -+ if (ret) { -+ ath12k_warn(ar->ab, -+ "failed to enable m3 ssr dump %d\n", -+ ret); -+ goto exit; -+ } -+ -+ ar->debug.enable_m3_dump = enable; -+ ret = count; -+ -+exit: -+ mutex_unlock(&ar->conf_mutex); -+ return ret; -+} -+ -+static ssize_t ath12k_read_enable_m3_dump(struct file *file, -+ char __user *ubuf, -+ size_t count, loff_t *ppos) -+{ -+ struct ath12k *ar = file->private_data; -+ char buf[32]; -+ size_t len = 0; -+ -+ mutex_lock(&ar->conf_mutex); -+ len = scnprintf(buf, sizeof(buf) - len, "%d\n", -+ ar->debug.enable_m3_dump); -+ mutex_unlock(&ar->conf_mutex); -+ -+ return simple_read_from_buffer(ubuf, count, ppos, buf, len); -+} -+ -+static const struct file_operations fops_enable_m3_dump = { -+ .read = ath12k_read_enable_m3_dump, -+ .write = ath12k_write_enable_m3_dump, -+ .open = simple_open -+}; -+ - int ath12k_debugfs_register(struct ath12k *ar) - { - struct ath12k_base *ab = ar->ab; -@@ -1508,6 +1569,9 @@ - ar->debug.debugfs_pdev, ar, - &fops_athdiag); - -+ debugfs_create_file("enable_m3_dump", 0644, -+ ar->debug.debugfs_pdev, ar, -+ &fops_enable_m3_dump); - return 0; - } - -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/qmi.c 2022-07-17 14:36:35.867436883 +0530 -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi.c 2022-07-17 14:36:35.859436859 +0530 +--- a/drivers/net/wireless/ath/ath12k/qmi.c ++++ b/drivers/net/wireless/ath/ath12k/qmi.c @@ -15,6 +15,7 @@ #include #include @@ -225,32 +125,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi #define SLEEP_CLOCK_SELECT_INTERNAL_BIT 0x02 #define HOST_CSTATE_BIT 0x04 -@@ -578,6 +579,24 @@ - .ei_array = qmi_response_type_v01_ei, - }, - { -+ .data_type = QMI_OPT_FLAG, -+ .elem_len = 1, -+ .elem_size = sizeof(u8), -+ .array_type = NO_ARRAY, -+ .tlv_type = 0x20, -+ .offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01, -+ m3_dump_upload_req_enable_valid), -+ }, -+ { -+ .data_type = QMI_UNSIGNED_1_BYTE, -+ .elem_len = 1, -+ .elem_size = sizeof(u8), -+ .array_type = NO_ARRAY, -+ .tlv_type = 0x20, -+ .offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01, -+ m3_dump_upload_req_enable), -+ }, -+ { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, -@@ -839,6 +858,24 @@ +@@ -968,6 +969,24 @@ static struct qmi_elem_info qmi_wlanfw_i qdss_trace_save_enable), }, { @@ -275,7 +150,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi .data_type = QMI_EOTI, .array_type = NO_ARRAY, .tlv_type = QMI_COMMON_TLV_TYPE, -@@ -2293,6 +2330,87 @@ +@@ -2519,6 +2538,87 @@ out: return ret; } @@ -360,10 +235,10 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi + }, +}; + - int ath12k_qmi_send_qdss_trace_config_download_req(struct ath12k_base *ab, - const u8 *buffer, unsigned int buffer_len) - { -@@ -2535,6 +2653,8 @@ + static int ath12k_qmi_send_qdss_trace_config_download_req(struct ath12k_base *ab, + const u8 *buffer, + unsigned int buffer_len) +@@ -2789,6 +2889,8 @@ static int ath12k_qmi_fw_ind_register_se req->qdss_trace_save_enable = 1; req->qdss_trace_free_enable_valid = 1; req->qdss_trace_free_enable = 1; @@ -372,7 +247,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi req->pin_connect_result_enable_valid = 0; req->pin_connect_result_enable = 0; -@@ -2782,6 +2902,17 @@ +@@ -3056,6 +3158,17 @@ static int ath12k_qmi_assign_target_mem_ "qmi fail to update BHI table %d\n", ret); idx++; break; @@ -390,7 +265,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi default: ath12k_warn(ab, "qmi ignore invalid mem req type %d\n", -@@ -3422,6 +3553,71 @@ +@@ -3710,6 +3823,71 @@ static int ath12k_qmi_process_coldboot_c return 0; } @@ -462,7 +337,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi static void ath12k_qmi_qdss_mem_free(struct ath12k_qmi *qmi) { struct ath12k_base *ab = qmi->ab; -@@ -3819,6 +4015,30 @@ +@@ -4114,6 +4292,30 @@ static void ath12k_qmi_msg_cold_boot_cal ath12k_dbg(ab, ATH12K_DBG_QMI, "qmi cold boot calibration done\n"); } @@ -493,7 +368,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi static void ath12k_wlfw_qdss_trace_req_mem_ind_cb(struct qmi_handle *qmi_hdl, struct sockaddr_qrtr *sq, struct qmi_txn *txn, -@@ -3975,6 +4195,14 @@ +@@ -4270,6 +4472,14 @@ static const struct qmi_msg_handler ath1 }, { .type = QMI_INDICATION, @@ -508,7 +383,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi .msg_id = QMI_WLFW_QDSS_TRACE_REQ_MEM_IND_V01, .ei = qmi_wlanfw_request_mem_ind_msg_v01_ei, .decoded_size = -@@ -4097,6 +4325,9 @@ +@@ -4392,6 +4602,9 @@ static void ath12k_qmi_driver_event_work case ATH12K_QMI_EVENT_QDSS_TRACE_SAVE: ath12k_qmi_event_qdss_trace_save_hdlr(qmi, event->data); break; @@ -518,11 +393,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi default: ath12k_warn(ab, "invalid event type: %d", event->type); break; -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/qmi.h 2022-07-17 14:36:35.867436883 +0530 -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi.h 2022-07-17 14:36:35.859436859 +0530 -@@ -29,6 +29,7 @@ +--- a/drivers/net/wireless/ath/ath12k/qmi.h ++++ b/drivers/net/wireless/ath/ath12k/qmi.h +@@ -31,6 +31,7 @@ #define ATH12K_QMI_DEVMEM_CMEM_INDEX 0 #define ATH12K_QMI_MAX_QDSS_CONFIG_FILE_NAME_SIZE 64 #define ATH12K_QMI_DEFAULT_QDSS_CONFIG_FILE_NAME "qdss_trace_config.bin" @@ -530,16 +403,16 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi #define QMI_WLFW_REQUEST_MEM_IND_V01 0x0035 #define QMI_WLFW_FW_MEM_READY_IND_V01 0x0037 -@@ -38,6 +39,8 @@ - #define QMI_Q6_QDSS_ETR_SIZE_QCN92XX 0x100000 +@@ -40,6 +41,8 @@ + #define QMI_Q6_QDSS_ETR_SIZE_QCN9274 0x100000 #define QMI_WLFW_QDSS_TRACE_SAVE_IND_V01 0x0041 - #define QMI_Q6_QDSS_ETR_OFFSET_QCN92XX 0x2500000 + #define QMI_Q6_QDSS_ETR_OFFSET_QCN9274 0x2500000 +#define QMI_WLFW_M3_DUMP_UPLOAD_REQ_IND_V01 0x004D +#define QMI_WLFW_M3_DUMP_UPLOAD_DONE_REQ_V01 0x004E #define QMI_WLANFW_MAX_DATA_SIZE_V01 6144 #define ATH12K_FIRMWARE_MODE_OFF 4 -@@ -75,6 +78,7 @@ +@@ -79,6 +82,7 @@ enum ath12k_qmi_event_type { ATH12K_QMI_EVENT_POWER_DOWN, ATH12K_QMI_EVENT_QDSS_TRACE_REQ_MEM = 15, ATH12K_QMI_EVENT_QDSS_TRACE_SAVE, @@ -547,7 +420,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi ATH12K_QMI_EVENT_MAX, }; -@@ -84,6 +88,13 @@ +@@ -88,6 +92,13 @@ struct ath12k_qmi_driver_event { void *data; }; @@ -561,7 +434,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi struct ath12k_qmi_ce_cfg { const struct ce_pipe_config *tgt_ce; int tgt_ce_len; -@@ -156,6 +167,12 @@ +@@ -160,6 +171,12 @@ struct ath12k_qmi { struct dev_mem_info dev_mem[ATH12K_QMI_WLFW_MAX_DEV_MEM_NUM_V01]; }; @@ -574,7 +447,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi #define QMI_WLANFW_QDSS_TRACE_CONFIG_DOWNLOAD_REQ_MSG_V01_MAX_LEN 6167 #define QMI_WLANFW_QDSS_TRACE_CONFIG_DOWNLOAD_RESP_MSG_V01_MAX_LEN 7 #define QMI_WLANFW_QDSS_TRACE_CONFIG_DOWNLOAD_REQ_V01 0x0044 -@@ -202,6 +219,16 @@ +@@ -206,6 +223,16 @@ struct qmi_wlanfw_qdss_trace_mode_resp_m }; #define QMI_WLANFW_HOST_CAP_REQ_MSG_V01_MAX_LEN 261 @@ -591,7 +464,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi #define QMI_WLANFW_HOST_CAP_REQ_V01 0x0034 #define QMI_WLANFW_HOST_CAP_RESP_MSG_V01_MAX_LEN 7 #define QMI_WLFW_HOST_CAP_RESP_V01 0x0034 -@@ -312,6 +339,8 @@ +@@ -339,6 +366,8 @@ struct qmi_wlanfw_ind_register_req_msg_v u8 qdss_trace_save_enable; u8 qdss_trace_free_enable_valid; u8 qdss_trace_free_enable; @@ -600,7 +473,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi }; struct qmi_wlanfw_ind_register_resp_msg_v01 { -@@ -536,6 +565,8 @@ +@@ -563,6 +592,8 @@ struct qmi_wlanfw_bdf_download_resp_msg_ #define QMI_WLANFW_M3_INFO_RESP_V01 0x003C #define QMI_WLANFW_M3_INFO_REQ_V01 0x003C @@ -609,7 +482,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi struct qmi_wlanfw_m3_info_req_msg_v01 { u64 addr; u32 size; -@@ -654,6 +685,12 @@ +@@ -691,6 +722,12 @@ struct wlfw_ini_resp_msg_v01 { struct qmi_response_type_v01 resp; }; @@ -622,18 +495,16 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/qmi int ath12k_qmi_firmware_start(struct ath12k_base *ab, u32 mode); void ath12k_qmi_firmware_stop(struct ath12k_base *ab); -@@ -667,4 +704,6 @@ +@@ -702,4 +739,6 @@ int ath12k_qmi_init_service(struct ath12 int ath12k_send_qdss_trace_mode_req(struct ath12k_base *ab, enum qmi_wlanfw_qdss_trace_mode_enum_v01 mode); int ath12k_enable_fwlog(struct ath12k_base *ab); +int ath12k_qmi_m3_dump_upload_done_ind_send(struct ath12k_base *ab, + u32 pdev_id, int status); #endif -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/wmi.c 2022-07-17 14:36:35.867436883 +0530 -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi.c 2022-07-17 14:36:35.859436859 +0530 -@@ -8654,6 +8654,37 @@ +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -8683,6 +8683,37 @@ int ath12k_wmi_simulate_awgn(struct ath1 return ath12k_wmi_send_unit_test_cmd(ar, wmi_ut, awgn_args); } @@ -671,11 +542,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi int ath12k_wmi_connect(struct ath12k_base *ab) { u32 i; -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/wmi.h 2022-07-17 14:36:35.867436883 +0530 -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi.h 2022-07-17 14:36:35.859436859 +0530 -@@ -2150,6 +2150,11 @@ +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -2138,6 +2138,11 @@ enum wmi_tlv_service { WMI_MAX_EXT2_SERVICE, }; @@ -687,7 +556,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi enum { WMI_SMPS_FORCED_MODE_NONE = 0, WMI_SMPS_FORCED_MODE_DISABLED, -@@ -4252,6 +4257,15 @@ +@@ -4204,6 +4209,15 @@ enum wmi_awgn_test_args_idx { WMI_AWGN_MAX_TEST_ARGS, }; @@ -701,9 +570,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi +}; + struct wmi_unit_test_cmd { - u32 tlv_header; - u32 vdev_id; -@@ -6060,5 +6074,6 @@ + __le32 tlv_header; + __le32 vdev_id; +@@ -5985,5 +5999,6 @@ int ath12k_wmi_wow_enable(struct ath12k int ath12k_wmi_send_vdev_set_tpc_power(struct ath12k *ar, u32 vdev_id, struct ath12k_reg_tpc_power_info *param); diff --git a/feeds/ipq95xx/mac80211/patches/qca/641-ath12k-Add-support-for-recording-EHT-Tx-Rx-rate-info.patch b/feeds/ipq95xx/mac80211/patches/qca/641-ath12k-Add-support-for-recording-EHT-Tx-Rx-rate-info.patch index 3b35bc015..ce91f38fd 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/641-ath12k-Add-support-for-recording-EHT-Tx-Rx-rate-info.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/641-ath12k-Add-support-for-recording-EHT-Tx-Rx-rate-info.patch @@ -68,6 +68,67 @@ Signed-off-by: Balamurugan Mahalingam u64 bw[ATH12K_COUNTER_TYPE_MAX][ATH12K_BW_NUM]; u64 nss[ATH12K_COUNTER_TYPE_MAX][ATH12K_NSS_NUM]; u64 gi[ATH12K_COUNTER_TYPE_MAX][ATH12K_GI_NUM]; +--- a/drivers/net/wireless/ath/ath12k/dp_mon.c ++++ b/drivers/net/wireless/ath/ath12k/dp_mon.c +@@ -3270,8 +3270,8 @@ ath12k_dp_mon_rx_update_peer_rate_table_ + u32 bw_idx = ppdu_info->bw; + u32 gi_idx = ppdu_info->gi; + +- if ((mcs_idx > HAL_RX_MAX_MCS_HE) || (nss_idx >= HAL_RX_MAX_NSS) || +- (bw_idx >= HAL_RX_BW_MAX) || (gi_idx >= HAL_RX_GI_MAX)) { ++ if (mcs_idx > HAL_RX_MAX_MCS_BE || nss_idx >= HAL_RX_MAX_NSS || ++ bw_idx >= HAL_RX_BW_MAX || gi_idx >= HAL_RX_GI_MAX) { + return; + } + +@@ -3283,6 +3283,10 @@ ath12k_dp_mon_rx_update_peer_rate_table_ + gi_idx = ath12k_he_gi_to_nl80211_he_gi(ppdu_info->gi); + rate_idx = mcs_idx * 12 + 12 * 12 * nss_idx; + rate_idx += bw_idx * 3 + gi_idx; ++ } else if (ppdu_info->preamble_type == HAL_RX_PREAMBLE_11BE) { ++ gi_idx = ath12k_he_gi_to_nl80211_he_gi(ppdu_info->gi); ++ rate_idx = mcs_idx * 12 + 12 * 12 * nss_idx; ++ rate_idx += bw_idx * 3 + gi_idx; + } else { + return; + } +@@ -3380,6 +3384,12 @@ static void ath12k_dp_mon_rx_update_peer + rx_stats->byte_stats.he_mcs_count[ppdu_info->mcs] += ppdu_info->mpdu_len; + } + ++ if (ppdu_info->preamble_type == HAL_RX_PREAMBLE_11BE && ++ ppdu_info->mcs <= HAL_RX_MAX_MCS_BE) { ++ rx_stats->pkt_stats.be_mcs_count[ppdu_info->mcs] += num_msdu; ++ rx_stats->byte_stats.be_mcs_count[ppdu_info->mcs] += ppdu_info->mpdu_len; ++ } ++ + if ((ppdu_info->preamble_type == HAL_RX_PREAMBLE_11A || + ppdu_info->preamble_type == HAL_RX_PREAMBLE_11B) && + ppdu_info->rate < HAL_RX_LEGACY_RATE_INVALID) { +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -1371,6 +1371,11 @@ ath12k_update_per_peer_tx_stats(struct a + return; + } + ++ if (flags == WMI_RATE_PREAMBLE_EHT && mcs > ATH12K_EHT_MCS_MAX) { ++ ath12k_warn(ab, "Invalid EHT mcs %d peer stats", mcs); ++ return; ++ } ++ + if (flags == WMI_RATE_PREAMBLE_VHT && mcs > ATH12K_VHT_MCS_MAX) { + ath12k_warn(ab, "Invalid VHT mcs %d peer stats", mcs); + return; +--- a/drivers/net/wireless/ath/ath12k/hal_rx.h ++++ b/drivers/net/wireless/ath/ath12k/hal_rx.h +@@ -71,6 +71,7 @@ enum hal_rx_preamble { + HAL_RX_PREAMBLE_11N, + HAL_RX_PREAMBLE_11AC, + HAL_RX_PREAMBLE_11AX, ++ HAL_RX_PREAMBLE_11BE = 6, + HAL_RX_PREAMBLE_MAX, + }; + --- a/drivers/net/wireless/ath/ath12k/debugfs_sta.c +++ b/drivers/net/wireless/ath/ath12k/debugfs_sta.c @@ -32,7 +32,14 @@ void ath12k_debugfs_sta_add_tx_stats(str @@ -92,7 +153,7 @@ Signed-off-by: Balamurugan Mahalingam ppdu_type == HTT_PPDU_STATS_PPDU_TYPE_MU_MIMO_OFDMA) && - (txrate->flags & RATE_INFO_FLAGS_HE_MCS)) { + (txrate->flags & RATE_INFO_FLAGS_HE_MCS || -+ txrate->flags & RATE_INFO_FLAGS_EHT_MCS)) { ++ txrate->flags & RATE_INFO_FLAGS_EHT_MCS)) { ru_type = peer_stats->ru_tones; if (ru_type <= NL80211_RATE_INFO_HE_RU_ALLOC_996) { @@ -149,64 +210,3 @@ Signed-off-by: Balamurugan Mahalingam len += scnprintf(buf + len, size - len, "\nHE byte stats:\n"); for (i = 0; i <= HAL_RX_MAX_MCS_HE; i++) len += scnprintf(buf + len, size - len, "MCS %d: %llu%s", i, ---- a/drivers/net/wireless/ath/ath12k/dp_mon.c -+++ b/drivers/net/wireless/ath/ath12k/dp_mon.c -@@ -3414,8 +3414,8 @@ ath12k_dp_mon_rx_update_peer_rate_table_ - u32 bw_idx = ppdu_info->bw; - u32 gi_idx = ppdu_info->gi; - -- if ((mcs_idx > HAL_RX_MAX_MCS_HE) || (nss_idx >= HAL_RX_MAX_NSS) || -- (bw_idx >= HAL_RX_BW_MAX) || (gi_idx >= HAL_RX_GI_MAX)) { -+ if (mcs_idx > HAL_RX_MAX_MCS_BE || nss_idx >= HAL_RX_MAX_NSS || -+ bw_idx >= HAL_RX_BW_MAX || gi_idx >= HAL_RX_GI_MAX) { - return; - } - -@@ -3427,6 +3427,10 @@ ath12k_dp_mon_rx_update_peer_rate_table_ - gi_idx = ath12k_he_gi_to_nl80211_he_gi(ppdu_info->gi); - rate_idx = mcs_idx * 12 + 12 * 12 * nss_idx; - rate_idx += bw_idx * 3 + gi_idx; -+ } else if (ppdu_info->preamble_type == HAL_RX_PREAMBLE_11BE) { -+ gi_idx = ath12k_he_gi_to_nl80211_he_gi(ppdu_info->gi); -+ rate_idx = mcs_idx * 12 + 12 * 12 * nss_idx; -+ rate_idx += bw_idx * 3 + gi_idx; - } else { - return; - } -@@ -3524,6 +3528,12 @@ static void ath12k_dp_mon_rx_update_peer - rx_stats->byte_stats.he_mcs_count[ppdu_info->mcs] += ppdu_info->mpdu_len; - } - -+ if (ppdu_info->preamble_type == HAL_RX_PREAMBLE_11BE && -+ ppdu_info->mcs <= HAL_RX_MAX_MCS_BE) { -+ rx_stats->pkt_stats.be_mcs_count[ppdu_info->mcs] += num_msdu; -+ rx_stats->byte_stats.be_mcs_count[ppdu_info->mcs] += ppdu_info->mpdu_len; -+ } -+ - if ((ppdu_info->preamble_type == HAL_RX_PREAMBLE_11A || - ppdu_info->preamble_type == HAL_RX_PREAMBLE_11B) && - ppdu_info->rate < HAL_RX_LEGACY_RATE_INVALID) { ---- a/drivers/net/wireless/ath/ath12k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -1353,6 +1353,11 @@ ath12k_update_per_peer_tx_stats(struct a - return; - } - -+ if (flags == WMI_RATE_PREAMBLE_EHT && mcs > ATH12K_EHT_MCS_MAX) { -+ ath12k_warn(ab, "Invalid EHT mcs %d peer stats", mcs); -+ return; -+ } -+ - if (flags == WMI_RATE_PREAMBLE_VHT && mcs > ATH12K_VHT_MCS_MAX) { - ath12k_warn(ab, "Invalid VHT mcs %d peer stats", mcs); - return; ---- a/drivers/net/wireless/ath/ath12k/hal_rx.h -+++ b/drivers/net/wireless/ath/ath12k/hal_rx.h -@@ -71,6 +71,7 @@ enum hal_rx_preamble { - HAL_RX_PREAMBLE_11N, - HAL_RX_PREAMBLE_11AC, - HAL_RX_PREAMBLE_11AX, -+ HAL_RX_PREAMBLE_11BE = 6, - HAL_RX_PREAMBLE_MAX, - }; - diff --git a/feeds/ipq95xx/mac80211/patches/qca/641-ath12k-Update-the-Rate-Table-information-display.patch b/feeds/ipq95xx/mac80211/patches/qca/641-ath12k-Update-the-Rate-Table-information-display.patch index 208e634f5..218ef7695 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/641-ath12k-Update-the-Rate-Table-information-display.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/641-ath12k-Update-the-Rate-Table-information-display.patch @@ -14,11 +14,9 @@ Signed-off-by: Balamurugan Mahalingam drivers/net/wireless/ath/ath12k/dp_mon.c | 23 +--- 3 files changed, 104 insertions(+), 35 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h -index 44ae29c..76ba04a 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h -@@ -348,7 +348,7 @@ struct ath12k_rx_peer_rate_stats { +@@ -349,7 +349,7 @@ struct ath12k_rx_peer_rate_stats { u64 bw_count[HAL_RX_BW_MAX]; u64 gi_count[HAL_RX_GI_MAX]; u64 legacy_count[HAL_RX_MAX_NUM_LEGACY_RATES]; @@ -27,11 +25,52 @@ index 44ae29c..76ba04a 100644 }; struct ath12k_rx_peer_stats { -diff --git a/drivers/net/wireless/ath/ath12k/debugfs_sta.c b/drivers/net/wireless/ath/ath12k/debugfs_sta.c -index 3eff14c..4a7b678 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_mon.c ++++ b/drivers/net/wireless/ath/ath12k/dp_mon.c +@@ -3264,7 +3264,6 @@ ath12k_dp_mon_rx_update_peer_rate_table_ + struct hal_rx_user_status *user_stats, + u32 num_msdu) + { +- u32 rate_idx = 0; + u32 mcs_idx = (user_stats) ? user_stats->mcs : ppdu_info->mcs; + u32 nss_idx = (user_stats) ? user_stats->nss - 1 : ppdu_info->nss - 1; + u32 bw_idx = ppdu_info->bw; +@@ -3275,27 +3274,15 @@ ath12k_dp_mon_rx_update_peer_rate_table_ + return; + } + +- if (ppdu_info->preamble_type == HAL_RX_PREAMBLE_11N || +- ppdu_info->preamble_type == HAL_RX_PREAMBLE_11AC) { +- rate_idx = mcs_idx * 8 + 8 * 10 * nss_idx; +- rate_idx += bw_idx * 2 + gi_idx; +- } else if (ppdu_info->preamble_type == HAL_RX_PREAMBLE_11AX) { ++ if (ppdu_info->preamble_type == HAL_RX_PREAMBLE_11AX || ++ ppdu_info->preamble_type == HAL_RX_PREAMBLE_11BE) + gi_idx = ath12k_he_gi_to_nl80211_he_gi(ppdu_info->gi); +- rate_idx = mcs_idx * 12 + 12 * 12 * nss_idx; +- rate_idx += bw_idx * 3 + gi_idx; +- } else if (ppdu_info->preamble_type == HAL_RX_PREAMBLE_11BE) { +- gi_idx = ath12k_he_gi_to_nl80211_he_gi(ppdu_info->gi); +- rate_idx = mcs_idx * 12 + 12 * 12 * nss_idx; +- rate_idx += bw_idx * 3 + gi_idx; +- } else { +- return; +- } + +- rx_stats->pkt_stats.rx_rate[rate_idx] += num_msdu; ++ rx_stats->pkt_stats.rx_rate[bw_idx][gi_idx][nss_idx][mcs_idx] += num_msdu; + if (user_stats) +- rx_stats->byte_stats.rx_rate[rate_idx] += user_stats->mpdu_ok_byte_count; ++ rx_stats->byte_stats.rx_rate[bw_idx][gi_idx][nss_idx][mcs_idx] += user_stats->mpdu_ok_byte_count; + else +- rx_stats->byte_stats.rx_rate[rate_idx] += ppdu_info->mpdu_len; ++ rx_stats->byte_stats.rx_rate[bw_idx][gi_idx][nss_idx][mcs_idx] += ppdu_info->mpdu_len; + } + + static void ath12k_dp_mon_rx_update_peer_su_stats(struct ath12k *ar, --- a/drivers/net/wireless/ath/ath12k/debugfs_sta.c +++ b/drivers/net/wireless/ath/ath12k/debugfs_sta.c -@@ -381,8 +381,7 @@ static ssize_t ath12k_dbg_sta_dump_rx_stats(struct file *file, +@@ -381,8 +381,7 @@ static ssize_t ath12k_dbg_sta_dump_rx_st int len = 0, i, retval = 0; const int size = 4 * 4096; char *buf; @@ -41,7 +80,7 @@ index 3eff14c..4a7b678 100644 static const char *legacy_rate_str[HAL_RX_MAX_NUM_LEGACY_RATES] = { "1Mbps", "2Mbps", "5.5Mbps", "6Mbps", "9Mbps", "11Mbps", "12Mbps", "18Mbps", -@@ -394,9 +393,6 @@ static ssize_t ath12k_dbg_sta_dump_rx_stats(struct file *file, +@@ -394,9 +393,6 @@ static ssize_t ath12k_dbg_sta_dump_rx_st if (!buf) return -ENOMEM; @@ -51,12 +90,12 @@ index 3eff14c..4a7b678 100644 mutex_lock(&ar->conf_mutex); spin_lock_bh(&ar->ab->base_lock); -@@ -420,10 +416,10 @@ static ssize_t ath12k_dbg_sta_dump_rx_stats(struct file *file, +@@ -420,10 +416,10 @@ static ssize_t ath12k_dbg_sta_dump_rx_st len += scnprintf(buf + len, size - len, "Num of MPDUs with FCS error: %llu\n", rx_stats->num_mpdu_fcs_err); len += scnprintf(buf + len, size - len, - "preamble: 11A %llu 11B %llu 11N %llu 11AC %llu 11AX %llu\n", -+ "preamble: 11A %llu 11B %llu 11N %llu 11AC %llu 11AX %llu 11BE %llu\n", ++ "preamble: 11A %llu 11B %llu 11N %llu 11AC %llu 11AX %llu 11BE%llu\n", rx_stats->pream_cnt[0], rx_stats->pream_cnt[1], rx_stats->pream_cnt[2], rx_stats->pream_cnt[3], - rx_stats->pream_cnt[4]); @@ -64,7 +103,7 @@ index 3eff14c..4a7b678 100644 len += scnprintf(buf + len, size - len, "reception type: SU %llu MU_MIMO %llu MU_OFDMA %llu MU_OFDMA_MIMO %llu\n", rx_stats->reception_type[0], rx_stats->reception_type[1], -@@ -478,12 +474,54 @@ static ssize_t ath12k_dbg_sta_dump_rx_stats(struct file *file, +@@ -478,10 +474,51 @@ static ssize_t ath12k_dbg_sta_dump_rx_st rx_stats->pkt_stats.bw_count[3], rx_stats->pkt_stats.bw_count[4]); len += scnprintf(buf + len, size - len, "\nRate Table (packets):\n"); @@ -108,8 +147,6 @@ index 3eff14c..4a7b678 100644 + mcs, rx_stats->pkt_stats.rx_rate[bw][gi][nss][mcs]); + } + } - -- len += scnprintf(buf + len, size - len, "\nRX success byte stats:\n"); + if (nss++ >= HAL_RX_MAX_NSS - 1) { + nss = 0; + if (gi++ >= HAL_RX_GI_MAX - 1) { @@ -119,12 +156,10 @@ index 3eff14c..4a7b678 100644 + } + } + } -+ -+ len += scnprintf(buf + len, size - len, "\n\nRX success byte stats:\n"); + + len += scnprintf(buf + len, size - len, "\nRX success byte stats:\n"); len += scnprintf(buf + len, size - len, "\nEHT byte stats:\n"); - for (i = 0; i <= HAL_RX_MAX_MCS_BE; i++) - len += scnprintf(buf + len, size - len, "MCS %d: %llu%s", i, -@@ -528,10 +566,54 @@ static ssize_t ath12k_dbg_sta_dump_rx_stats(struct file *file, +@@ -528,10 +565,55 @@ static ssize_t ath12k_dbg_sta_dump_rx_st rx_stats->byte_stats.bw_count[3], rx_stats->byte_stats.bw_count[4]); len += scnprintf(buf + len, size - len, "\nRate Table (bytes):\n"); @@ -133,6 +168,7 @@ index 3eff14c..4a7b678 100644 - rx_stats->byte_stats.rx_rate[i], - (i + 1) % (he_rates_avail ? 12 : 8) ? "\t" : "\n"); + ++ + bw = 0; + gi = 0; + nss = 0; @@ -183,51 +219,3 @@ index 3eff14c..4a7b678 100644 len += scnprintf(buf + len, size - len, "\nDCM: %llu\nRU26: %llu\nRU52: %llu\nRU106: %llu\nRU242: %llu\nRU484: %llu\nRU996: %llu\n", rx_stats->dcm_count, rx_stats->ru_alloc_cnt[0], -diff --git a/drivers/net/wireless/ath/ath12k/dp_mon.c b/drivers/net/wireless/ath/ath12k/dp_mon.c -index e090d3e..4edb630 100644 ---- a/drivers/net/wireless/ath/ath12k/dp_mon.c -+++ b/drivers/net/wireless/ath/ath12k/dp_mon.c -@@ -2199,7 +2199,6 @@ ath12k_dp_mon_rx_update_peer_rate_table_stats(struct ath12k_rx_peer_stats *rx_st - struct hal_rx_user_status *user_stats, - u32 num_msdu) - { -- u32 rate_idx = 0; - u32 mcs_idx = (user_stats) ? user_stats->mcs : ppdu_info->mcs; - u32 nss_idx = (user_stats) ? user_stats->nss - 1 : ppdu_info->nss - 1; - u32 bw_idx = ppdu_info->bw; -@@ -2210,27 +2209,15 @@ ath12k_dp_mon_rx_update_peer_rate_table_stats(struct ath12k_rx_peer_stats *rx_st - return; - } - -- if (ppdu_info->preamble_type == HAL_RX_PREAMBLE_11N || -- ppdu_info->preamble_type == HAL_RX_PREAMBLE_11AC) { -- rate_idx = mcs_idx * 8 + 8 * 10 * nss_idx; -- rate_idx += bw_idx * 2 + gi_idx; -- } else if (ppdu_info->preamble_type == HAL_RX_PREAMBLE_11AX) { -+ if (ppdu_info->preamble_type == HAL_RX_PREAMBLE_11AX || -+ ppdu_info->preamble_type == HAL_RX_PREAMBLE_11BE) - gi_idx = ath12k_he_gi_to_nl80211_he_gi(ppdu_info->gi); -- rate_idx = mcs_idx * 12 + 12 * 12 * nss_idx; -- rate_idx += bw_idx * 3 + gi_idx; -- } else if (ppdu_info->preamble_type == HAL_RX_PREAMBLE_11BE) { -- gi_idx = ath12k_he_gi_to_nl80211_he_gi(ppdu_info->gi); -- rate_idx = mcs_idx * 12 + 12 * 12 * nss_idx; -- rate_idx += bw_idx * 3 + gi_idx; -- } else { -- return; -- } - -- rx_stats->pkt_stats.rx_rate[rate_idx] += num_msdu; -+ rx_stats->pkt_stats.rx_rate[bw_idx][gi_idx][nss_idx][mcs_idx] += num_msdu; - if (user_stats) -- rx_stats->byte_stats.rx_rate[rate_idx] += user_stats->mpdu_ok_byte_count; -+ rx_stats->byte_stats.rx_rate[bw_idx][gi_idx][nss_idx][mcs_idx] += user_stats->mpdu_ok_byte_count; - else -- rx_stats->byte_stats.rx_rate[rate_idx] += ppdu_info->mpdu_len; -+ rx_stats->byte_stats.rx_rate[bw_idx][gi_idx][nss_idx][mcs_idx] += ppdu_info->mpdu_len; - } - - static void ath12k_dp_mon_rx_update_peer_su_stats(struct ath12k *ar, --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/641-ath12k-add-hw_param-for-wakeup_mhi.patch b/feeds/ipq95xx/mac80211/patches/qca/641-ath12k-add-hw_param-for-wakeup_mhi.patch index fda33e165..f26564acc 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/641-ath12k-add-hw_param-for-wakeup_mhi.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/641-ath12k-add-hw_param-for-wakeup_mhi.patch @@ -19,82 +19,77 @@ Signed-off-by: Harshitha Prem drivers/net/wireless/ath/ath12k/pci.c | 20 ++++++++++++-------- 3 files changed, 14 insertions(+), 8 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c -index bbbb34c..429a8c3 100644 ---- a/drivers/net/wireless/ath/ath12k/core.c -+++ b/drivers/net/wireless/ath/ath12k/core.c -@@ -69,6 +69,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { - .fix_l1ss = false, +--- a/drivers/net/wireless/ath/ath12k/hw.h ++++ b/drivers/net/wireless/ath/ath12k/hw.h +@@ -196,6 +196,7 @@ struct ath12k_hw_params { + + bool supports_ap_ps; + bool credit_flow; ++ bool wakeup_mhi; + }; + + /* BRINGUP: move to dp.h */ +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -1055,7 +1055,8 @@ u32 ath12k_pci_read32(struct ath12k_base + /* for offset beyond BAR + 4K - 32, may + * need to wakeup MHI to access. + */ +- if (test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && ++ if (ab->hw_params->wakeup_mhi && ++ test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && + offset >= ACCESS_ALWAYS_OFF) + mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev); + +@@ -1099,7 +1100,8 @@ u32 ath12k_pci_read32(struct ath12k_base + } + } + +- if (test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && ++ if (ab->hw_params->wakeup_mhi && ++ test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && + offset >= ACCESS_ALWAYS_OFF) + mhi_device_put(ab_pci->mhi_ctrl->mhi_dev); + +@@ -1115,8 +1117,9 @@ void ath12k_pci_write32(struct ath12k_ba + /* for offset beyond BAR + 4K - 32, may + * need to wakeup MHI to access. + */ +- if (test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && +- offset >= ACCESS_ALWAYS_OFF) ++ if (ab->hw_params->wakeup_mhi && ++ test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && ++ offset >= ACCESS_ALWAYS_OFF) + mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev); + + if (offset < WINDOW_START) { +@@ -1159,8 +1162,9 @@ void ath12k_pci_write32(struct ath12k_ba + } + } + +- if (test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && +- offset >= ACCESS_ALWAYS_OFF) ++ if (ab->hw_params->wakeup_mhi && ++ test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && ++ offset >= ACCESS_ALWAYS_OFF) + mhi_device_put(ab_pci->mhi_ctrl->mhi_dev); + } + +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -880,6 +880,7 @@ static const struct ath12k_hw_params ath + + .supports_ap_ps = true, + .credit_flow = false, ++ .wakeup_mhi = false, + }, + { + .name = "wcn7850 hw2.0", +@@ -944,6 +945,7 @@ static const struct ath12k_hw_params ath + .supports_ap_ps = true, .credit_flow = false, + .wakeup_mhi = false, }, }; -diff --git a/drivers/net/wireless/ath/ath12k/hw.h b/drivers/net/wireless/ath/ath12k/hw.h -index 6e830bb..d820765 100644 ---- a/drivers/net/wireless/ath/ath12k/hw.h -+++ b/drivers/net/wireless/ath/ath12k/hw.h -@@ -167,6 +167,7 @@ struct ath12k_hw_params { - bool fix_l1ss; - bool supports_ap_ps; - bool credit_flow; -+ bool wakeup_mhi; - }; - - struct ath12k_hw_ops { -diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c -index 4dba3da..75de7f7 100644 ---- a/drivers/net/wireless/ath/ath12k/pci.c -+++ b/drivers/net/wireless/ath/ath12k/pci.c -@@ -1115,8 +1115,9 @@ u32 ath12k_pci_read32(struct ath12k_base *ab, u32 offset) - /* for offset beyond BAR + 4K - 32, may - * need to wakeup MHI to access. - */ -- if (test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && -- offset >= ACCESS_ALWAYS_OFF) -+ if (ab->hw_params.wakeup_mhi && -+ test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && -+ offset >= ACCESS_ALWAYS_OFF) - mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev); - - if (offset < WINDOW_START) { -@@ -1154,8 +1155,9 @@ u32 ath12k_pci_read32(struct ath12k_base *ab, u32 offset) - } - } - -- if (test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && -- offset >= ACCESS_ALWAYS_OFF) -+ if (ab->hw_params.wakeup_mhi && -+ test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && -+ offset >= ACCESS_ALWAYS_OFF) - mhi_device_put(ab_pci->mhi_ctrl->mhi_dev); - - return val; -@@ -1170,8 +1172,9 @@ void ath12k_pci_write32(struct ath12k_base *ab, u32 offset, u32 value) - /* for offset beyond BAR + 4K - 32, may - * need to wakeup MHI to access. - */ -- if (test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && -- offset >= ACCESS_ALWAYS_OFF) -+ if (ab->hw_params.wakeup_mhi && -+ test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && -+ offset >= ACCESS_ALWAYS_OFF) - mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev); - - if (offset < WINDOW_START) { -@@ -1209,8 +1212,9 @@ void ath12k_pci_write32(struct ath12k_base *ab, u32 offset, u32 value) - } - } - -- if (test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && -- offset >= ACCESS_ALWAYS_OFF) -+ if (ab->hw_params.wakeup_mhi && -+ test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && -+ offset >= ACCESS_ALWAYS_OFF) - mhi_device_put(ab_pci->mhi_ctrl->mhi_dev); - } - --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/646-ath12k-Fix-RU-allocation-incrementation-in-tx_stats.patch b/feeds/ipq95xx/mac80211/patches/qca/646-ath12k-Fix-RU-allocation-incrementation-in-tx_stats.patch index 3a06d9df6..b2293d13c 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/646-ath12k-Fix-RU-allocation-incrementation-in-tx_stats.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/646-ath12k-Fix-RU-allocation-incrementation-in-tx_stats.patch @@ -13,33 +13,29 @@ Signed-off-by: Dinesh Karthikeyan drivers/net/wireless/ath/ath12k/dp_rx.c | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) -diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h -index 000e0d6..351953d 100644 --- a/drivers/net/wireless/ath/ath12k/dp.h +++ b/drivers/net/wireless/ath/ath12k/dp.h -@@ -1521,6 +1521,8 @@ enum HTT_PPDU_STATS_PPDU_TYPE { - FIELD_GET(HTT_PPDU_STATS_USER_RATE_FLAGS_GI_M, _val) +@@ -1524,6 +1524,8 @@ enum HTT_PPDU_STATS_PPDU_TYPE { + u32_get_bits(_val, HTT_PPDU_STATS_USER_RATE_FLAGS_GI_M) #define HTT_USR_RATE_DCM(_val) \ - FIELD_GET(HTT_PPDU_STATS_USER_RATE_FLAGS_DCM_M, _val) + u32_get_bits(_val, HTT_PPDU_STATS_USER_RATE_FLAGS_DCM_M) +#define HTT_USR_RATE_PPDU_TYPE(_val) \ -+ FIELD_GET(HTT_PPDU_STATS_USER_RATE_INFO1_PPDU_TYPE_M, _val) ++ u32_get_bits(_val, HTT_PPDU_STATS_USER_RATE_INFO1_PPDU_TYPE_M) #define HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_LTF_SIZE_M GENMASK(1, 0) #define HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_STBC_M BIT(2) -diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c -index 3b10bf2..e82bf65 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -1303,7 +1303,7 @@ ath12k_update_per_peer_tx_stats(struct ath12k *ar, +@@ -1320,7 +1320,7 @@ ath12k_update_per_peer_tx_stats(struct a struct htt_ppdu_stats_common *common = &ppdu_stats->common; int ret; u8 flags, mcs, nss, bw, sgi, dcm, rate_idx = 0; -- u32 succ_bytes = 0; -+ u32 succ_bytes = 0, ppdu_type; +- u32 v, succ_bytes = 0; ++ u32 v, succ_bytes = 0, ppdu_type; u16 rate = 0, succ_pkts = 0; u32 tx_duration = 0; u8 tid = HTT_PPDU_STATS_NON_QOS_TID; -@@ -1338,6 +1338,7 @@ ath12k_update_per_peer_tx_stats(struct ath12k *ar, +@@ -1355,6 +1355,7 @@ ath12k_update_per_peer_tx_stats(struct a mcs = HTT_USR_RATE_MCS(user_rate->rate_flags); sgi = HTT_USR_RATE_GI(user_rate->rate_flags); dcm = HTT_USR_RATE_DCM(user_rate->rate_flags); @@ -47,14 +43,12 @@ index 3b10bf2..e82bf65 100644 /* Note: If host configured fixed rates and in some other special * cases, the broadcast/management frames are sent in different rates. -@@ -1447,6 +1448,7 @@ ath12k_update_per_peer_tx_stats(struct ath12k *ar, +@@ -1469,7 +1470,7 @@ ath12k_update_per_peer_tx_stats(struct a peer_stats->ba_fails = HTT_USR_CMPLTN_LONG_RETRY(usr_stats->cmpltn_cmn.flags) + HTT_USR_CMPLTN_SHORT_RETRY(usr_stats->cmpltn_cmn.flags); +- + peer_stats->ppdu_type = ppdu_type; - if (ath12k_debugfs_is_extd_tx_stats_enabled(ar)) ath12k_debugfs_sta_add_tx_stats(arsta, peer_stats, rate_idx); --- -2.7.4 - + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/647-02-cfg80211-Skip-punctured-channel-validation-for-5GHz.patch b/feeds/ipq95xx/mac80211/patches/qca/647-02-cfg80211-Skip-punctured-channel-validation-for-5GHz.patch index a5478b39f..2cd83aba3 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/647-02-cfg80211-Skip-punctured-channel-validation-for-5GHz.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/647-02-cfg80211-Skip-punctured-channel-validation-for-5GHz.patch @@ -18,7 +18,7 @@ Signed-off-by: Karthik M --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h -@@ -4762,7 +4762,7 @@ struct ieee80211_iface_combination { +@@ -4888,7 +4888,7 @@ struct ieee80211_iface_combination { * @radar_detect_widths: * bitmap of channel widths supported for radar detection */ @@ -29,21 +29,20 @@ Signed-off-by: Karthik M * @radar_detect_regions: --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c -@@ -325,9 +325,12 @@ enum ieee80211_sta_rx_bandwidth ieee8021 - if (he_cap->has_he) { - u8 info; +@@ -339,8 +339,12 @@ ieee80211_sta_cap_rx_bw(struct link_sta_ + rcu_read_lock(); + link_conf = rcu_dereference(sdata->vif.link_conf[link_id]); + /* TODO: 5GHz is reusing the same PHY capability + * to advertise the 320MHz support. Removind band + * specific check for now. + */ if (eht_cap->has_eht && -- sta->sdata->vif.bss_conf.chandef.chan->band == -- NL80211_BAND_6GHZ) { -+ sta->sdata->vif.bss_conf.chandef.chan->band != NL80211_BAND_2GHZ) { +- link_conf->chandef.chan->band == NL80211_BAND_6GHZ) { ++ link_conf->chandef.chan->band != NL80211_BAND_6GHZ) { info = eht_cap->eht_cap_elem.phy_cap_info[0]; - if (info & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ) + if (info & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ) { --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -15,6 +15,12 @@ @@ -59,7 +58,7 @@ Signed-off-by: Karthik M static bool cfg80211_valid_60g_freq(u32 freq) { return freq >= 58320 && freq <= 70200; -@@ -617,7 +623,8 @@ static u32 cfg80211_get_end_freq(u32 cen +@@ -627,7 +633,8 @@ static u32 cfg80211_get_end_freq(u32 cen static int cfg80211_get_chans_dfs_required(struct wiphy *wiphy, u32 center_freq, @@ -69,7 +68,7 @@ Signed-off-by: Karthik M { struct ieee80211_channel *c; u32 freq, start_freq, end_freq; -@@ -626,6 +633,8 @@ static int cfg80211_get_chans_dfs_requir +@@ -636,6 +643,8 @@ static int cfg80211_get_chans_dfs_requir end_freq = cfg80211_get_end_freq(center_freq, bandwidth); for (freq = start_freq; freq <= end_freq; freq += MHZ_TO_KHZ(20)) { @@ -78,7 +77,7 @@ Signed-off-by: Karthik M c = ieee80211_get_channel_khz(wiphy, freq); if (!c) return -EINVAL; -@@ -658,7 +667,7 @@ int cfg80211_chandef_dfs_required(struct +@@ -668,7 +677,7 @@ int cfg80211_chandef_dfs_required(struct ret = cfg80211_get_chans_dfs_required(wiphy, ieee80211_chandef_to_khz(chandef), @@ -87,7 +86,7 @@ Signed-off-by: Karthik M if (ret < 0) return ret; else if (ret > 0) -@@ -669,7 +678,7 @@ int cfg80211_chandef_dfs_required(struct +@@ -679,7 +688,7 @@ int cfg80211_chandef_dfs_required(struct ret = cfg80211_get_chans_dfs_required(wiphy, MHZ_TO_KHZ(chandef->center_freq2), @@ -96,7 +95,7 @@ Signed-off-by: Karthik M if (ret < 0) return ret; else if (ret > 0) -@@ -694,9 +703,20 @@ int cfg80211_chandef_dfs_required(struct +@@ -704,9 +713,20 @@ int cfg80211_chandef_dfs_required(struct } EXPORT_SYMBOL(cfg80211_chandef_dfs_required); @@ -104,7 +103,7 @@ Signed-off-by: Karthik M +{ + if (chandef->width == NL80211_CHAN_WIDTH_320 && + chandef->center_freq1 == CENTER_FREQ_5G_240MHZ && -+ chandef->ru_punct_bitmap == FIXED_PUNCTURE_PATTERN) { ++ ((chandef->ru_punct_bitmap & FIXED_PUNCTURE_PATTERN) == FIXED_PUNCTURE_PATTERN)) { + return true; + } + return false; @@ -118,7 +117,7 @@ Signed-off-by: Karthik M { struct ieee80211_channel *c; u32 freq, start_freq, end_freq; -@@ -712,6 +732,8 @@ static int cfg80211_get_chans_dfs_usable +@@ -722,6 +742,8 @@ static int cfg80211_get_chans_dfs_usable * (require CAC). Allow DFS and non-DFS channel mix. */ for (freq = start_freq; freq <= end_freq; freq += MHZ_TO_KHZ(20)) { @@ -127,7 +126,7 @@ Signed-off-by: Karthik M c = ieee80211_get_channel_khz(wiphy, freq); if (!c) return -EINVAL; -@@ -746,7 +768,7 @@ bool cfg80211_chandef_dfs_usable(struct +@@ -756,7 +778,7 @@ bool cfg80211_chandef_dfs_usable(struct r1 = cfg80211_get_chans_dfs_usable(wiphy, MHZ_TO_KHZ(chandef->center_freq1), @@ -136,7 +135,7 @@ Signed-off-by: Karthik M if (r1 < 0) return false; -@@ -756,7 +778,7 @@ bool cfg80211_chandef_dfs_usable(struct +@@ -766,7 +788,7 @@ bool cfg80211_chandef_dfs_usable(struct WARN_ON(!chandef->center_freq2); r2 = cfg80211_get_chans_dfs_usable(wiphy, MHZ_TO_KHZ(chandef->center_freq2), @@ -145,7 +144,7 @@ Signed-off-by: Karthik M if (r2 < 0) return false; break; -@@ -902,7 +924,8 @@ bool cfg80211_any_wiphy_oper_chan(struct +@@ -950,7 +972,8 @@ bool cfg80211_any_wiphy_oper_chan(struct static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy, u32 center_freq, @@ -155,7 +154,7 @@ Signed-off-by: Karthik M { struct ieee80211_channel *c; u32 freq, start_freq, end_freq; -@@ -920,6 +943,8 @@ static bool cfg80211_get_chans_dfs_avail +@@ -968,6 +991,8 @@ static bool cfg80211_get_chans_dfs_avail * had gone through CAC return false */ for (freq = start_freq; freq <= end_freq; freq += MHZ_TO_KHZ(20)) { @@ -164,7 +163,7 @@ Signed-off-by: Karthik M c = ieee80211_get_channel_khz(wiphy, freq); if (!c) return false; -@@ -951,7 +976,7 @@ static bool cfg80211_chandef_dfs_availab +@@ -999,7 +1024,7 @@ static bool cfg80211_chandef_dfs_availab r = cfg80211_get_chans_dfs_available(wiphy, MHZ_TO_KHZ(chandef->center_freq1), @@ -173,7 +172,7 @@ Signed-off-by: Karthik M /* If any of channels unavailable for cf1 just return */ if (!r) -@@ -962,7 +987,7 @@ static bool cfg80211_chandef_dfs_availab +@@ -1010,7 +1035,7 @@ static bool cfg80211_chandef_dfs_availab WARN_ON(!chandef->center_freq2); r = cfg80211_get_chans_dfs_available(wiphy, MHZ_TO_KHZ(chandef->center_freq2), @@ -182,7 +181,7 @@ Signed-off-by: Karthik M break; default: WARN_ON(chandef->center_freq2); -@@ -974,7 +999,8 @@ static bool cfg80211_chandef_dfs_availab +@@ -1022,7 +1047,8 @@ static bool cfg80211_chandef_dfs_availab static unsigned int cfg80211_get_chans_dfs_cac_time(struct wiphy *wiphy, u32 center_freq, @@ -192,7 +191,7 @@ Signed-off-by: Karthik M { struct ieee80211_channel *c; u32 start_freq, end_freq, freq; -@@ -984,6 +1010,8 @@ static unsigned int cfg80211_get_chans_d +@@ -1032,6 +1058,8 @@ static unsigned int cfg80211_get_chans_d end_freq = cfg80211_get_end_freq(center_freq, bandwidth); for (freq = start_freq; freq <= end_freq; freq += MHZ_TO_KHZ(20)) { @@ -201,7 +200,7 @@ Signed-off-by: Karthik M c = ieee80211_get_channel_khz(wiphy, freq); if (!c) return 0; -@@ -1017,21 +1045,22 @@ cfg80211_chandef_dfs_cac_time(struct wip +@@ -1065,21 +1093,22 @@ cfg80211_chandef_dfs_cac_time(struct wip t1 = cfg80211_get_chans_dfs_cac_time(wiphy, MHZ_TO_KHZ(chandef->center_freq1), @@ -227,7 +226,7 @@ Signed-off-by: Karthik M { struct ieee80211_channel *c; u32 freq, start_freq, end_freq; -@@ -1040,6 +1069,8 @@ static bool cfg80211_secondary_chans_ok( +@@ -1088,6 +1117,8 @@ static bool cfg80211_secondary_chans_ok( end_freq = cfg80211_get_end_freq(center_freq, bandwidth); for (freq = start_freq; freq <= end_freq; freq += MHZ_TO_KHZ(20)) { @@ -236,7 +235,7 @@ Signed-off-by: Karthik M c = ieee80211_get_channel_khz(wiphy, freq); if (!c || c->flags & prohibited_flags) return false; -@@ -1218,10 +1249,14 @@ bool cfg80211_chandef_usable(struct wiph +@@ -1266,10 +1297,14 @@ bool cfg80211_chandef_usable(struct wiph prohibited_flags |= IEEE80211_CHAN_NO_320MHZ; width = 320; @@ -253,7 +252,7 @@ Signed-off-by: Karthik M if (!sband) return false; -@@ -1266,14 +1301,16 @@ bool cfg80211_chandef_usable(struct wiph +@@ -1314,14 +1349,16 @@ bool cfg80211_chandef_usable(struct wiph if (!cfg80211_secondary_chans_ok(wiphy, ieee80211_chandef_to_khz(chandef), @@ -274,7 +273,7 @@ Signed-off-by: Karthik M --- a/net/wireless/reg.c +++ b/net/wireless/reg.c -@@ -1785,7 +1785,8 @@ static uint32_t reg_rule_to_chan_bw_flag +@@ -1790,7 +1790,8 @@ static uint32_t reg_rule_to_chan_bw_flag bw_flags |= IEEE80211_CHAN_NO_80MHZ; if (max_bandwidth_khz < MHZ_TO_KHZ(160)) bw_flags |= IEEE80211_CHAN_NO_160MHZ; diff --git a/feeds/ipq95xx/mac80211/patches/qca/647-cfg80211-Fix-incorrect-channel-flag-for-disabling-EH.patch b/feeds/ipq95xx/mac80211/patches/qca/647-cfg80211-Fix-incorrect-channel-flag-for-disabling-EH.patch deleted file mode 100644 index c5794cc4f..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/647-cfg80211-Fix-incorrect-channel-flag-for-disabling-EH.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 1ea2bc646d939cf0e74f34568e1377442336c18b Mon Sep 17 00:00:00 2001 -From: Pradeep Kumar Chitrapu -Date: Wed, 6 Jul 2022 09:02:20 -0700 -Subject: [PATCH] cfg80211: Fix incorrect channel flag for disabling EHT - -Signed-off-by: Pradeep Kumar Chitrapu ---- - include/net/cfg80211.h | 2 +- - net/mac80211/mlme.c | 3 +++ - 2 files changed, 4 insertions(+), 1 deletion(-) - -diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h -index 234dae99dd9b..372f8062579f 100644 ---- a/include/net/cfg80211.h -+++ b/include/net/cfg80211.h -@@ -145,7 +145,7 @@ enum ieee80211_channel_flags { - IEEE80211_CHAN_16MHZ = 1<<18, - IEEE80211_CHAN_PSD = 1<<19, - IEEE80211_CHAN_NO_320MHZ = 1<<20, -- IEEE80211_CHAN_NO_EHT = 1<<20, -+ IEEE80211_CHAN_NO_EHT = 1<<21, - }; - - #define IEEE80211_CHAN_NO_HT40 \ -diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c -index 0385468eeecd..28f8dd2a0107 100644 ---- a/net/mac80211/mlme.c -+++ b/net/mac80211/mlme.c -@@ -810,6 +810,9 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) - sizeof(struct ieee80211_he_mcs_nss_supp) + - IEEE80211_HE_PPE_THRES_MAX_LEN + - 2 + 1 + sizeof(struct ieee80211_he_6ghz_capa) + -+ 2 + 1 + sizeof(struct ieee80211_eht_cap_elem) + -+ sizeof(struct ieee80211_eht_mcs_nss_supp) + -+ IEEE80211_EHT_PPE_THRES_MAX_LEN + - assoc_data->ie_len + /* extra IEs */ - (assoc_data->fils_kek_len ? 16 /* AES-SIV */ : 0) + - 9 + /* WMM */ --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/648-ath12k-fix-target-assert-during-channel-switch.patch b/feeds/ipq95xx/mac80211/patches/qca/648-ath12k-fix-target-assert-during-channel-switch.patch index e77112c29..0f3821980 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/648-ath12k-fix-target-assert-during-channel-switch.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/648-ath12k-fix-target-assert-during-channel-switch.patch @@ -124,8 +124,8 @@ Signed-off-by: Aaradhana Sahu + spin_lock_bh(&ar->data_lock); + + /* Set arsta bw and prev bw */ -+ arsta->bw = sta->bandwidth; -+ arsta->bw_prev = sta->bandwidth; ++ arsta->bw = sta->deflink.bandwidth; ++ arsta->bw_prev = sta->deflink.bandwidth; + + spin_unlock_bh(&ar->data_lock); } else if (old_state == IEEE80211_STA_ASSOC && diff --git a/feeds/ipq95xx/mac80211/patches/qca/649-ath12k-fix-double-free-of-peer-rx_tid-during-reo-cmd.patch b/feeds/ipq95xx/mac80211/patches/qca/649-ath12k-fix-double-free-of-peer-rx_tid-during-reo-cmd.patch index ca1b5fddf..480526ae6 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/649-ath12k-fix-double-free-of-peer-rx_tid-during-reo-cmd.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/649-ath12k-fix-double-free-of-peer-rx_tid-during-reo-cmd.patch @@ -28,11 +28,9 @@ Signed-off-by: Harshitha Prem drivers/net/wireless/ath/ath12k/dp_rx.c | 52 +++++++++++++++++-------- 2 files changed, 37 insertions(+), 17 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h -index 04bbf9d..f65e3fb 100644 --- a/drivers/net/wireless/ath/ath12k/dp.h +++ b/drivers/net/wireless/ath/ath12k/dp.h -@@ -201,7 +201,7 @@ struct ath12k_pdev_dp { +@@ -162,7 +162,7 @@ struct ath12k_pdev_dp { #define DP_REO_REINJECT_RING_SIZE 32 #define DP_RX_RELEASE_RING_SIZE 1024 #define DP_REO_EXCEPTION_RING_SIZE 128 @@ -41,15 +39,13 @@ index 04bbf9d..f65e3fb 100644 #define DP_REO_STATUS_RING_SIZE 2048 #define DP_RXDMA_BUF_RING_SIZE 4096 #define DP_RXDMA_REFILL_RING_SIZE 2048 -diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c -index 857845e..762a698 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -634,13 +634,18 @@ void ath12k_dp_reo_cmd_list_cleanup(struct ath12k_base *ab) +@@ -587,13 +587,18 @@ void ath12k_dp_rx_reo_cmd_list_cleanup(s struct ath12k_dp *dp = &ab->dp; - struct dp_reo_cmd *cmd, *tmp; - struct dp_reo_cache_flush_elem *cmd_cache, *tmp_cache; -+ struct dp_rx_tid *rx_tid; + struct ath12k_dp_rx_reo_cmd *cmd, *tmp; + struct ath12k_dp_rx_reo_cache_flush_elem *cmd_cache, *tmp_cache; ++ struct ath12k_dp_rx_tid *rx_tid; spin_lock_bh(&dp->reo_cmd_lock); list_for_each_entry_safe(cmd, tmp, &dp->reo_cmd_list, list) { @@ -60,14 +56,14 @@ index 857845e..762a698 100644 + rx_tid = &cmd->data; + if (rx_tid->vaddr) { + dma_unmap_single(ab->dev, rx_tid->paddr, -+ rx_tid->size, DMA_BIDIRECTIONAL); ++ rx_tid->size, DMA_BIDIRECTIONAL); + kfree(rx_tid->vaddr); + rx_tid->vaddr = NULL; + } kfree(cmd); } -@@ -648,9 +653,13 @@ void ath12k_dp_reo_cmd_list_cleanup(struct ath12k_base *ab) +@@ -601,9 +606,13 @@ void ath12k_dp_rx_reo_cmd_list_cleanup(s &dp->reo_cmd_cache_flush_list, list) { list_del(&cmd_cache->list); dp->reo_cmd_cache_flush_count--; @@ -84,7 +80,7 @@ index 857845e..762a698 100644 kfree(cmd_cache); } spin_unlock_bh(&dp->reo_cmd_lock); -@@ -664,10 +673,12 @@ static void ath12k_dp_reo_cmd_free(struct ath12k_dp *dp, void *ctx, +@@ -617,10 +626,12 @@ static void ath12k_dp_reo_cmd_free(struc if (status != HAL_REO_CMD_SUCCESS) ath12k_warn(dp->ab, "failed to flush rx tid hw desc, tid %d status %d\n", rx_tid->tid, status); @@ -99,8 +95,8 @@ index 857845e..762a698 100644 + } } - static void ath12k_dp_reo_cache_flush(struct ath12k_base *ab, -@@ -706,6 +717,7 @@ static void ath12k_dp_reo_cache_flush(struct ath12k_base *ab, + static int ath12k_dp_reo_cmd_send(struct ath12k_base *ab, struct ath12k_dp_rx_tid *rx_tid, +@@ -704,6 +715,7 @@ static void ath12k_dp_reo_cache_flush(st dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size, DMA_BIDIRECTIONAL); kfree(rx_tid->vaddr); @@ -108,7 +104,7 @@ index 857845e..762a698 100644 } } -@@ -726,9 +738,11 @@ static void ath12k_dp_rx_tid_del_func(struct ath12k_dp *dp, void *ctx, +@@ -724,9 +736,11 @@ static void ath12k_dp_rx_tid_del_func(st } elem = kzalloc(sizeof(*elem), GFP_ATOMIC); @@ -122,7 +118,7 @@ index 857845e..762a698 100644 elem->ts = jiffies; memcpy(&elem->data, rx_tid, sizeof(*rx_tid)); -@@ -758,6 +772,7 @@ free_desc: +@@ -756,6 +770,7 @@ free_desc: dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size, DMA_BIDIRECTIONAL); kfree(rx_tid->vaddr); @@ -130,7 +126,7 @@ index 857845e..762a698 100644 } static void ath12k_peer_rx_tid_qref_setup(struct ath12k_base *ab, u16 peer_id, u16 tid, -@@ -799,6 +814,7 @@ void ath12k_peer_rx_tid_delete(struct ath12k *ar, +@@ -809,6 +824,7 @@ void ath12k_dp_rx_peer_tid_delete(struct if (!rx_tid->active) return; @@ -138,7 +134,7 @@ index 857845e..762a698 100644 cmd.flag = HAL_REO_CMD_FLG_NEED_STATUS; cmd.addr_lo = lower_32_bits(rx_tid->paddr); cmd.addr_hi = upper_32_bits(rx_tid->paddr); -@@ -815,8 +831,9 @@ void ath12k_peer_rx_tid_delete(struct ath12k *ar, +@@ -825,8 +841,9 @@ void ath12k_dp_rx_peer_tid_delete(struct } ath12k_peer_rx_tid_qref_reset(ar->ab, peer->peer_id, tid); @@ -150,7 +146,7 @@ index 857845e..762a698 100644 } static int ath12k_dp_rx_link_desc_return(struct ath12k_base *ab, -@@ -967,7 +984,8 @@ int ath12k_peer_rx_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_id, +@@ -978,7 +995,8 @@ int ath12k_dp_rx_peer_tid_setup(struct a ba_win_sz, ssn, true); spin_unlock_bh(&ab->base_lock); if (ret) { @@ -160,7 +156,7 @@ index 857845e..762a698 100644 return ret; } -@@ -1003,6 +1021,8 @@ int ath12k_peer_rx_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_id, +@@ -1014,6 +1032,8 @@ int ath12k_dp_rx_peer_tid_setup(struct a ret = dma_mapping_error(ab->dev, paddr); if (ret) { spin_unlock_bh(&ab->base_lock); @@ -169,7 +165,7 @@ index 857845e..762a698 100644 goto err_mem_free; } -@@ -1019,8 +1039,8 @@ int ath12k_peer_rx_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_id, +@@ -1037,8 +1057,8 @@ int ath12k_dp_rx_peer_tid_setup(struct a return ret; err_mem_free: @@ -180,6 +176,3 @@ index 857845e..762a698 100644 return ret; } --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/649-ath12k-fix-incorrect-handling-of-AMSDU-frames.patch b/feeds/ipq95xx/mac80211/patches/qca/649-ath12k-fix-incorrect-handling-of-AMSDU-frames.patch index 5c4086556..deb20da85 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/649-ath12k-fix-incorrect-handling-of-AMSDU-frames.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/649-ath12k-fix-incorrect-handling-of-AMSDU-frames.patch @@ -21,20 +21,15 @@ Signed-off-by: Harshitha Prem drivers/net/wireless/ath/ath12k/dp_rx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) -diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c -index 857845e..8ecec63 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -223,7 +223,8 @@ static void ath12k_dp_rxdesc_set_msdu_len(struct ath12k_base *ab, +@@ -197,7 +197,8 @@ static void ath12k_dp_rxdesc_set_msdu_le static bool ath12k_dp_rx_h_is_mcbc(struct ath12k_base *ab, struct hal_rx_desc *desc) { -- return ab->hal.ops->rx_desc_is_mcbc(desc); +- return ab->hw_params->hal_ops->rx_desc_is_mcbc(desc); + return (ath12k_dp_rx_h_first_msdu(ab, desc) && -+ ab->hal.ops->rx_desc_is_mcbc(desc)); ++ ab->hw_params->hal_ops->rx_desc_is_mcbc(desc)); } static bool ath12k_dp_rxdesc_mac_addr2_valid(struct ath12k_base *ab, --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/649-ath12k-switch-to-using-ieee80211_tx_status_ext.patch b/feeds/ipq95xx/mac80211/patches/qca/649-ath12k-switch-to-using-ieee80211_tx_status_ext.patch index bb1f8b036..3de9da329 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/649-ath12k-switch-to-using-ieee80211_tx_status_ext.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/649-ath12k-switch-to-using-ieee80211_tx_status_ext.patch @@ -54,7 +54,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_ + status.skb = msdu; + status.info = info; + rate = arsta->last_txrate; -+ status.rate = &rate; ++ status.rates = &rate; + spin_unlock_bh(&ab->base_lock); + + ieee80211_tx_status_ext(ar->hw, &status); diff --git a/feeds/ipq95xx/mac80211/patches/qca/650-ath12k-Add-support-for-bss-color-enablement.patch b/feeds/ipq95xx/mac80211/patches/qca/650-ath12k-Add-support-for-bss-color-enablement.patch index fe9ed056c..103e19836 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/650-ath12k-Add-support-for-bss-color-enablement.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/650-ath12k-Add-support-for-bss-color-enablement.patch @@ -15,11 +15,11 @@ Signed-off-by: Dinesh Karthikeyan drivers/net/wireless/ath/ath12k/wmi.h | 15 +++++++ 5 files changed, 117 insertions(+), 5 deletions(-) -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.h +Index: backports-20220822-5.4.164-ef7197996efe/drivers/net/wireless/ath/ath12k/core.h =================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/core.h -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.h -@@ -318,6 +318,8 @@ struct ath12k_vif { +--- backports-20220822-5.4.164-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/core.h ++++ backports-20220822-5.4.164-ef7197996efe/drivers/net/wireless/ath/ath12k/core.h +@@ -319,6 +319,8 @@ struct ath12k_vif { u8 vdev_stats_id; struct ath12k_fw_vdev_ol_stats vdev_stats; u8 nontransmitting_vif_count; @@ -28,22 +28,22 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor #ifdef CPTCFG_ATH12K_DEBUGFS struct dentry *debugfs_twt; #endif /* CPTCFG_ATH12K_DEBUGFS */ -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac.c +Index: backports-20220822-5.4.164-ef7197996efe/drivers/net/wireless/ath/ath12k/mac.c =================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/mac.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac.c -@@ -1408,6 +1408,26 @@ static int ath12k_mac_setup_bcn_tmpl(str - return ath12k_mac_setup_bcn_tmpl_non_ema(arvif); +--- backports-20220822-5.4.164-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/mac.c ++++ backports-20220822-5.4.164-ef7197996efe/drivers/net/wireless/ath/ath12k/mac.c +@@ -1410,6 +1410,26 @@ static int ath12k_mac_setup_bcn_tmpl(str } + +void ath12k_mac_bcn_tx_event(struct ath12k_vif *arvif) +{ + struct ieee80211_vif *vif = arvif->vif; + -+ if (!vif->color_change_active && !arvif->bcca_zero_sent) ++ if (!vif->bss_conf.color_change_active && !arvif->bcca_zero_sent) + return; + -+ if (vif->color_change_active && ieee80211_beacon_cntdwn_is_complete(vif)) { ++ if (vif->bss_conf.color_change_active && ieee80211_beacon_cntdwn_is_complete(vif)) { + arvif->bcca_zero_sent = true; + ieee80211_color_change_finish(vif); + return; @@ -51,7 +51,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac + + arvif->bcca_zero_sent = false; + -+ if (vif->color_change_active) ++ if (vif->bss_conf.color_change_active) + ieee80211_beacon_update_cntdwn(vif); + ath12k_mac_setup_bcn_tmpl(arvif); +} @@ -59,7 +59,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac static void ath12k_control_beaconing(struct ath12k_vif *arvif, struct ieee80211_bss_conf *info) { -@@ -3502,6 +3522,7 @@ static void ath12k_mac_op_bss_info_chang +@@ -3542,6 +3562,7 @@ static void ath12k_mac_op_bss_info_chang int ret = 0; u8 rateidx; u32 rate; @@ -67,7 +67,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac mutex_lock(&ar->conf_mutex); -@@ -3534,10 +3555,17 @@ static void ath12k_mac_op_bss_info_chang +@@ -3574,10 +3595,17 @@ static void ath12k_mac_op_bss_info_chang "Set staggered beacon mode for VDEV: %d\n", arvif->vdev_id); @@ -89,25 +89,25 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac if (arvif->is_up && vif->bss_conf.he_support) { param_id = WMI_VDEV_PARAM_BA_MODE; -@@ -3774,15 +3802,36 @@ static void ath12k_mac_op_bss_info_chang +@@ -3814,16 +3842,36 @@ static void ath12k_mac_op_bss_info_chang ath12k_mac_config_obss_pd(ar, &info->he_obss_pd); if (changed & BSS_CHANGED_HE_BSS_COLOR) { + color_collision_detect = (info->he_bss_color.enabled && + info->he_bss_color.collision_detection_enabled); if (vif->type == NL80211_IFTYPE_AP) { - ret = ath12k_wmi_send_obss_color_collision_cfg_cmd( - ar, arvif->vdev_id, info->he_bss_color.color, - ATH12K_BSS_COLOR_COLLISION_DETECTION_AP_PERIOD_MS, - arvif->vif->bss_conf.nontransmitted ? -- 0 : info->he_bss_color.enabled); -+ 0 : color_collision_detect); + ret = ath12k_wmi_obss_color_cfg_cmd(ar, + arvif->vdev_id, + info->he_bss_color.color, + ATH12K_BSS_COLOR_AP_PERIODS, + arvif->vif->bss_conf.nontransmitted ? +- 0 : info->he_bss_color.enabled); ++ 0 : color_collision_detect); if (ret) ath12k_warn(ar->ab, "failed to set bss color collision on vdev %i: %d\n", arvif->vdev_id, ret); + + param_id = WMI_VDEV_PARAM_BSS_COLOR; -+ + param_value = info->he_bss_color.color << IEEE80211_HE_OPERATION_BSS_COLOR_OFFSET; + + if (!info->he_bss_color.enabled) @@ -127,7 +127,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac } else if (vif->type == NL80211_IFTYPE_STATION) { ret = ath12k_wmi_send_bss_color_change_enable_cmd(ar, arvif->vdev_id, -@@ -9809,6 +9858,10 @@ static int __ath12k_mac_register(struct +@@ -9901,6 +9949,10 @@ static int __ath12k_mac_register(struct wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_STA_TX_PWR); @@ -138,21 +138,21 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac ar->hw->wiphy->cipher_suites = cipher_suites; ar->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac.h +Index: backports-20220822-5.4.164-ef7197996efe/drivers/net/wireless/ath/ath12k/mac.h =================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/mac.h -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac.h +--- backports-20220822-5.4.164-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/mac.h ++++ backports-20220822-5.4.164-ef7197996efe/drivers/net/wireless/ath/ath12k/mac.h @@ -164,4 +164,5 @@ enum hal_encrypt_type ath12k_dp_tx_get_e void ath12k_mac_get_any_chandef_iter(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *conf, void *data); +void ath12k_mac_bcn_tx_event(struct ath12k_vif *arvif); #endif -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi.c +Index: backports-20220822-5.4.164-ef7197996efe/drivers/net/wireless/ath/ath12k/wmi.c =================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/wmi.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi.c -@@ -137,6 +137,8 @@ static const struct wmi_tlv_policy wmi_t +--- backports-20220822-5.4.164-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/wmi.c ++++ backports-20220822-5.4.164-ef7197996efe/drivers/net/wireless/ath/ath12k/wmi.c +@@ -135,6 +135,8 @@ static const struct wmi_tlv_policy wmi_t .min_len = sizeof(struct wmi_pdev_update_muedca_event) }, [WMI_TAG_TWT_ADD_DIALOG_COMPLETE_EVENT] = { .min_len = sizeof(struct wmi_twt_add_dialog_event) }, @@ -160,8 +160,8 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi + = { .min_len = sizeof(struct wmi_obss_color_collision_event) }, }; - static void ath12k_init_wmi_config_qcn92xx(struct ath12k_base *ab, -@@ -7033,6 +7035,7 @@ static void ath12k_vdev_start_resp_event + static __le32 ath12k_wmi_tlv_hdr(u32 cmd, u32 len) +@@ -7066,6 +7068,7 @@ static void ath12k_vdev_start_resp_event static void ath12k_bcn_tx_status_event(struct ath12k_base *ab, struct sk_buff *skb) { @@ -169,7 +169,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi u32 vdev_id, tx_status; if (ath12k_pull_bcn_tx_status_ev(ab, skb->data, skb->len, -@@ -7040,6 +7043,17 @@ static void ath12k_bcn_tx_status_event(s +@@ -7073,6 +7076,17 @@ static void ath12k_bcn_tx_status_event(s ath12k_warn(ab, "failed to extract bcn tx status"); return; } @@ -187,7 +187,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi } static void ath12k_vdev_stopped_event(struct ath12k_base *ab, struct sk_buff *skb) -@@ -8347,6 +8361,57 @@ exit: +@@ -8382,6 +8396,58 @@ exit: kfree(tb); } @@ -222,7 +222,8 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi + } + switch (ev->evt_type) { + case WMI_BSS_COLOR_COLLISION_DETECTION: -+ ieeee80211_obss_color_collision_notify(arvif->vif, ev->obss_color_bitmap); ++ ieeee80211_obss_color_collision_notify(arvif->vif, ev->obss_color_bitmap, ++ GFP_KERNEL); + + ath12k_dbg(ab, ATH12K_DBG_WMI, + "OBSS color collision detected vdev:%d, event:%d, bitmap:%08llx\n", @@ -239,13 +240,13 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi + +exit: + kfree(tb); -+ rcu_read_unlock(); ++ rcu_read_unock(); +} + static void ath12k_wmi_tlv_op_rx(struct ath12k_base *ab, struct sk_buff *skb) { struct wmi_cmd_hdr *cmd_hdr; -@@ -8472,6 +8537,9 @@ static void ath12k_wmi_tlv_op_rx(struct +@@ -8507,6 +8573,9 @@ static void ath12k_wmi_tlv_op_rx(struct case WMI_MUEDCA_PARAMS_CONFIG_EVENTID: ath12k_wmi_pdev_update_muedca_params_status_event(ab, skb); break; @@ -255,11 +256,11 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi /* TODO: Add remaining events */ default: ath12k_dbg(ab, ATH12K_DBG_WMI, "Unknown eventid: 0x%x\n", id); -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi.h +Index: backports-20220822-5.4.164-ef7197996efe/drivers/net/wireless/ath/ath12k/wmi.h =================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/wmi.h -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi.h -@@ -814,6 +814,8 @@ enum wmi_tlv_event_id { +--- backports-20220822-5.4.164-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/wmi.h ++++ backports-20220822-5.4.164-ef7197996efe/drivers/net/wireless/ath/ath12k/wmi.h +@@ -801,6 +801,8 @@ enum wmi_tlv_event_id { WMI_MDNS_STATS_EVENTID = WMI_TLV_CMD(WMI_GRP_MDNS_OFL), WMI_SAP_OFL_ADD_STA_EVENTID = WMI_TLV_CMD(WMI_GRP_SAP_OFL), WMI_SAP_OFL_DEL_STA_EVENTID, @@ -268,9 +269,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi WMI_OCB_SET_CONFIG_RESP_EVENTID = WMI_TLV_CMD(WMI_GRP_OCB), WMI_OCB_GET_TSF_TIMER_RESP_EVENTID, WMI_DCC_GET_STATS_RESP_EVENTID, -@@ -5503,6 +5505,13 @@ struct wmi_pdev_obss_pd_bitmap_cmd { - #define ATH12K_BSS_COLOR_COLLISION_DETECTION_STA_PERIOD_MS 10000 - #define ATH12K_BSS_COLOR_COLLISION_DETECTION_AP_PERIOD_MS 5000 +@@ -5423,6 +5425,13 @@ struct wmi_pdev_obss_pd_bitmap_cmd { + #define ATH12K_BSS_COLOR_STA_PERIODS 10000 + #define ATH12K_BSS_COLOR_AP_PERIODS 5000 +enum wmi_bss_color_collision { + WMI_BSS_COLOR_COLLISION_DISABLE = 0, @@ -280,10 +281,10 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi +}; + struct wmi_obss_color_collision_cfg_params_cmd { - u32 tlv_header; - u32 vdev_id; -@@ -5520,6 +5529,12 @@ struct wmi_bss_color_change_enable_param - u32 enable; + __le32 tlv_header; + __le32 vdev_id; +@@ -5440,6 +5449,12 @@ struct wmi_bss_color_change_enable_param + __le32 enable; } __packed; +struct wmi_obss_color_collision_event { @@ -295,11 +296,11 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi #define ATH12K_IPV4_TH_SEED_SIZE 5 #define ATH12K_IPV6_TH_SEED_SIZE 11 -Index: backports-20220404-5.4.164-f40abb4788/net/mac80211/cfg.c +Index: backports-20220822-5.4.164-ef7197996efe/net/mac80211/cfg.c =================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/net/mac80211/cfg.c -+++ backports-20220404-5.4.164-f40abb4788/net/mac80211/cfg.c -@@ -4779,7 +4779,7 @@ ieee80211_color_change(struct wiphy *wip +--- backports-20220822-5.4.164-ef7197996efe.orig/net/mac80211/cfg.c ++++ backports-20220822-5.4.164-ef7197996efe/net/mac80211/cfg.c +@@ -4782,7 +4782,7 @@ ieee80211_color_change(struct wiphy *wip cfg80211_color_change_started_notify(sdata->dev, params->count); if (changed) diff --git a/feeds/ipq95xx/mac80211/patches/qca/650-ath12k-Update-HTT-ppdu-stats-from-the-firmware-descr.patch b/feeds/ipq95xx/mac80211/patches/qca/650-ath12k-Update-HTT-ppdu-stats-from-the-firmware-descr.patch index 2a9d299f4..e79d1e41a 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/650-ath12k-Update-HTT-ppdu-stats-from-the-firmware-descr.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/650-ath12k-Update-HTT-ppdu-stats-from-the-firmware-descr.patch @@ -25,37 +25,11 @@ Signed-off-by: P Praneesh drivers/net/wireless/ath/ath12k/dp_rx.c | 126 ++++++++++++++++----- 3 files changed, 131 insertions(+), 28 deletions(-) ---- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h -+++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h -@@ -180,6 +180,25 @@ enum htt_tx_pdev_underrun_enum { - HTT_TX_PDEV_MAX_URRN_STATS = 3, - }; - -+enum htt_ppdu_stats_ru_size { -+ HTT_PPDU_STATS_RU_26, -+ HTT_PPDU_STATS_RU_52, -+ HTT_PPDU_STATS_RU_52_26, -+ HTT_PPDU_STATS_RU_106, -+ HTT_PPDU_STATS_RU_106_26, -+ HTT_PPDU_STATS_RU_242, -+ HTT_PPDU_STATS_RU_484, -+ HTT_PPDU_STATS_RU_484_242, -+ HTT_PPDU_STATS_RU_996, -+ HTT_PPDU_STATS_RU_996_484, -+ HTT_PPDU_STATS_RU_996_484_242, -+ HTT_PPDU_STATS_RU_996x2, -+ HTT_PPDU_STATS_RU_996x2_484, -+ HTT_PPDU_STATS_RU_996x3, -+ HTT_PPDU_STATS_RU_996x3_484, -+ HTT_PPDU_STATS_RU_996x4, -+}; -+ - #define HTT_TX_PDEV_MAX_FLUSH_REASON_STATS 71 - #define HTT_TX_PDEV_MAX_SIFS_BURST_STATS 9 - #define HTT_TX_PDEV_MAX_SIFS_BURST_HIST_STATS 10 ---- a/drivers/net/wireless/ath/ath12k/dp.h -+++ b/drivers/net/wireless/ath/ath12k/dp.h -@@ -1519,6 +1519,7 @@ enum htt_ppdu_stats_gi { +Index: b/drivers/net/wireless/ath/ath12k/dp.h +=================================================================== +--- a/drivers/net/wireless/ath/ath12k/dp.h 2023-04-20 13:03:51.805609906 +0530 ++++ b/drivers/net/wireless/ath/ath12k/dp.h 2023-04-20 13:04:05.681523988 +0530 +@@ -1483,6 +1483,7 @@ enum htt_ppdu_stats_gi { #define HTT_PPDU_STATS_USER_RATE_INFO0_USER_POS_M GENMASK(3, 0) #define HTT_PPDU_STATS_USER_RATE_INFO0_MU_GROUP_ID_M GENMASK(11, 4) @@ -63,7 +37,7 @@ Signed-off-by: P Praneesh enum HTT_PPDU_STATS_PPDU_TYPE { HTT_PPDU_STATS_PPDU_TYPE_SU, -@@ -1533,7 +1534,12 @@ enum HTT_PPDU_STATS_PPDU_TYPE { +@@ -1497,7 +1498,12 @@ enum HTT_PPDU_STATS_PPDU_TYPE { HTT_PPDU_STATS_PPDU_TYPE_MAX }; @@ -77,7 +51,7 @@ Signed-off-by: P Praneesh #define HTT_PPDU_STATS_USER_RATE_INFO1_PPDU_TYPE_M GENMASK(5, 1) #define HTT_PPDU_STATS_USER_RATE_FLAGS_LTF_SIZE_M GENMASK(1, 0) -@@ -1574,6 +1580,10 @@ enum HTT_PPDU_STATS_PPDU_TYPE { +@@ -1538,6 +1544,10 @@ enum HTT_PPDU_STATS_PPDU_TYPE { #define HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_GI_M GENMASK(27, 24) #define HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_DCM_M BIT(28) #define HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_LDPC_M BIT(29) @@ -88,7 +62,7 @@ Signed-off-by: P Praneesh struct htt_ppdu_stats_user_rate { u8 tid_num; -@@ -1588,6 +1598,8 @@ struct htt_ppdu_stats_user_rate { +@@ -1552,6 +1562,8 @@ struct htt_ppdu_stats_user_rate { u32 rate_flags; /* %HTT_PPDU_STATS_USER_RATE_FLAGS_ */ /* Note: resp_rate_info is only valid for if resp_type is UL */ u32 resp_rate_flags; /* %HTT_PPDU_STATS_USER_RATE_RESP_FLAGS_ */ @@ -97,9 +71,27 @@ Signed-off-by: P Praneesh } __packed; #define HTT_PPDU_STATS_TX_INFO_FLAGS_RATECODE_M GENMASK(7, 0) ---- a/drivers/net/wireless/ath/ath12k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -1206,7 +1206,7 @@ static int ath12k_htt_tlv_ppdu_stats_par +@@ -1618,6 +1630,7 @@ struct htt_ppdu_stats_usr_cmpltn_cmn { + #define HTT_PPDU_STATS_ACK_BA_INFO_TID_NUM GENMASK(31, 25) + + #define HTT_PPDU_STATS_NON_QOS_TID 16 ++#define HTT_PPDU_STATS_PPDU_ID GENMASK(24, 0) + + struct htt_ppdu_stats_usr_cmpltn_ack_ba_status { + u32 ppdu_id; +Index: b/drivers/net/wireless/ath/ath12k/dp_rx.c +=================================================================== +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c 2023-04-20 13:03:51.805609906 +0530 ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c 2023-04-20 13:03:51.801609932 +0530 +@@ -1214,6 +1214,7 @@ static int ath12k_htt_tlv_ppdu_stats_par + struct htt_ppdu_user_stats *user_stats; + int cur_user; + u16 peer_id; ++ u32 ppdu_id; + + ppdu_info = (struct htt_ppdu_stats_info *)data; + +@@ -1244,7 +1245,7 @@ static int ath12k_htt_tlv_ppdu_stats_par user_stats->is_valid_peer_id = true; memcpy((void *)&user_stats->rate, ptr, sizeof(struct htt_ppdu_stats_user_rate)); @@ -108,7 +100,7 @@ Signed-off-by: P Praneesh break; case HTT_PPDU_STATS_TAG_USR_COMPLTN_COMMON: if (len < sizeof(struct htt_ppdu_stats_usr_cmpltn_cmn)) { -@@ -1225,7 +1225,7 @@ static int ath12k_htt_tlv_ppdu_stats_par +@@ -1263,7 +1264,7 @@ static int ath12k_htt_tlv_ppdu_stats_par user_stats->is_valid_peer_id = true; memcpy((void *)&user_stats->cmpltn_cmn, ptr, sizeof(struct htt_ppdu_stats_usr_cmpltn_cmn)); @@ -117,8 +109,20 @@ Signed-off-by: P Praneesh break; case HTT_PPDU_STATS_TAG_USR_COMPLTN_ACK_BA_STATUS: if (len < -@@ -1246,7 +1246,10 @@ static int ath12k_htt_tlv_ppdu_stats_par +@@ -1273,6 +1274,8 @@ static int ath12k_htt_tlv_ppdu_stats_par + return -EINVAL; + } + ++ ppdu_id = ++ ((struct htt_ppdu_stats_usr_cmpltn_ack_ba_status *)ptr)->ppdu_id; + peer_id = + ((struct htt_ppdu_stats_usr_cmpltn_ack_ba_status *)ptr)->sw_peer_id; + cur_user = ath12k_get_ppdu_user_index(&ppdu_info->ppdu_stats, +@@ -1282,9 +1285,13 @@ static int ath12k_htt_tlv_ppdu_stats_par + user_stats = &ppdu_info->ppdu_stats.user_stats[cur_user]; + user_stats->peer_id = peer_id; user_stats->is_valid_peer_id = true; ++ ppdu_info->ppdu_id = FIELD_GET(HTT_PPDU_STATS_PPDU_ID, ppdu_id); memcpy((void *)&user_stats->ack_ba, ptr, sizeof(struct htt_ppdu_stats_usr_cmpltn_ack_ba_status)); - user_stats->tlv_flags |= BIT(tag); @@ -129,7 +133,7 @@ Signed-off-by: P Praneesh break; } return 0; -@@ -1257,11 +1260,17 @@ int ath12k_dp_htt_tlv_iter(struct ath12k +@@ -1295,11 +1302,17 @@ int ath12k_dp_htt_tlv_iter(struct ath12k const void *ptr, void *data), void *data) { @@ -147,7 +151,7 @@ Signed-off-by: P Praneesh while (len > 0) { if (len < sizeof(*tlv)) { ath12k_err(ab, "htt tlv parse failure at byte %zd (%zu bytes left, %zu expected)\n", -@@ -1279,7 +1288,7 @@ int ath12k_dp_htt_tlv_iter(struct ath12k +@@ -1317,7 +1330,7 @@ int ath12k_dp_htt_tlv_iter(struct ath12k tlv_tag, ptr - begin, len, tlv_len); return -EINVAL; } @@ -156,7 +160,7 @@ Signed-off-by: P Praneesh if (ret == -ENOMEM) return ret; -@@ -1289,38 +1298,76 @@ int ath12k_dp_htt_tlv_iter(struct ath12k +@@ -1327,38 +1340,76 @@ int ath12k_dp_htt_tlv_iter(struct ath12k return 0; } @@ -207,7 +211,7 @@ Signed-off-by: P Praneesh struct htt_ppdu_stats_common *common = &ppdu_stats->common; int ret; u8 flags, mcs, nss, bw, sgi, dcm, rate_idx = 0; - u32 succ_bytes = 0, ppdu_type; + u32 v, succ_bytes = 0, ppdu_type; - u16 rate = 0, succ_pkts = 0; - u32 tx_duration = 0; + u16 rate = 0, succ_pkts = 0, ru_start, ru_end; @@ -239,9 +243,9 @@ Signed-off-by: P Praneesh - BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_ACK_BA_STATUS)) { + if (tlv_bitmap & BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_ACK_BA_STATUS)) { succ_bytes = usr_stats->ack_ba.success_bytes; - succ_pkts = FIELD_GET(HTT_PPDU_STATS_ACK_BA_INFO_NUM_MSDU_M, - usr_stats->ack_ba.info); -@@ -1332,13 +1379,38 @@ ath12k_update_per_peer_tx_stats(struct a + succ_pkts = u32_get_bits(usr_stats->ack_ba.info, + HTT_PPDU_STATS_ACK_BA_INFO_NUM_MSDU_M); +@@ -1370,13 +1421,38 @@ ath12k_update_per_peer_tx_stats(struct a tx_duration = common->fes_duration_us; user_rate = &usr_stats->rate; @@ -286,13 +290,13 @@ Signed-off-by: P Praneesh /* Note: If host configured fixed rates and in some other special * cases, the broadcast/management frames are sent in different rates. -@@ -1419,18 +1491,17 @@ ath12k_update_per_peer_tx_stats(struct a +@@ -1457,18 +1533,17 @@ ath12k_update_per_peer_tx_stats(struct a arsta->txrate.flags = RATE_INFO_FLAGS_HE_MCS; arsta->txrate.he_dcm = dcm; arsta->txrate.he_gi = ath12k_he_gi_to_nl80211_he_gi(sgi); -- arsta->txrate.he_ru_alloc = ath12k_mac_he_ru_tones_to_nl80211_he_ru_alloc( -- (user_rate->ru_end - -- user_rate->ru_start) + 1); +- v = ath12k_mac_he_ru_tones_to_nl80211_he_ru_alloc((user_rate->ru_end - +- user_rate->ru_start) + 1); +- arsta->txrate.he_ru_alloc = v; + arsta->txrate.he_ru_alloc = ru_tones; + peer_stats->ru_tones = arsta->txrate.he_ru_alloc; break; @@ -304,13 +308,13 @@ Signed-off-by: P Praneesh - arsta->txrate.he_ru_alloc = ath12k_mac_he_ru_tones_to_nl80211_he_ru_alloc( - (user_rate->ru_end - - user_rate->ru_start) + 1); -+ arsta->txrate.he_ru_alloc = -+ ath12k_mac_he_ru_tones_to_nl80211_he_ru_alloc( -+ (ru_end - ru_start) + 1); ++ v = ath12k_mac_he_ru_tones_to_nl80211_he_ru_alloc( ++ (ru_end - ru_start) + 1); ++ arsta->txrate.he_ru_alloc = v; break; default: break; -@@ -1450,6 +1521,7 @@ ath12k_update_per_peer_tx_stats(struct a +@@ -1488,6 +1563,7 @@ ath12k_update_per_peer_tx_stats(struct a peer_stats->succ_bytes = succ_bytes; peer_stats->is_ampdu = is_ampdu; peer_stats->duration = tx_duration; @@ -318,7 +322,7 @@ Signed-off-by: P Praneesh peer_stats->ba_fails = HTT_USR_CMPLTN_LONG_RETRY(usr_stats->cmpltn_cmn.flags) + HTT_USR_CMPLTN_SHORT_RETRY(usr_stats->cmpltn_cmn.flags); -@@ -1464,12 +1536,12 @@ ath12k_update_per_peer_tx_stats(struct a +@@ -1501,12 +1577,12 @@ ath12k_update_per_peer_tx_stats(struct a } static void ath12k_htt_update_ppdu_stats(struct ath12k *ar, @@ -333,7 +337,7 @@ Signed-off-by: P Praneesh } static -@@ -1490,7 +1562,7 @@ struct htt_ppdu_stats_info *ath12k_dp_ht +@@ -1527,7 +1603,7 @@ struct htt_ppdu_stats_info *ath12k_dp_ht typeof(*ppdu_info), list); list_del(&ppdu_info->list); ar->ppdu_stat_list_depth--; @@ -342,3 +346,33 @@ Signed-off-by: P Praneesh kfree(ppdu_info); } } +Index: b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h +=================================================================== +--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h 2023-04-20 13:03:51.805609906 +0530 ++++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h 2023-04-20 13:03:51.805609906 +0530 +@@ -180,6 +180,25 @@ enum htt_tx_pdev_underrun_enum { + HTT_TX_PDEV_MAX_URRN_STATS = 3, + }; + ++enum htt_ppdu_stats_ru_size { ++ HTT_PPDU_STATS_RU_26, ++ HTT_PPDU_STATS_RU_52, ++ HTT_PPDU_STATS_RU_52_26, ++ HTT_PPDU_STATS_RU_106, ++ HTT_PPDU_STATS_RU_106_26, ++ HTT_PPDU_STATS_RU_242, ++ HTT_PPDU_STATS_RU_484, ++ HTT_PPDU_STATS_RU_484_242, ++ HTT_PPDU_STATS_RU_996, ++ HTT_PPDU_STATS_RU_996_484, ++ HTT_PPDU_STATS_RU_996_484_242, ++ HTT_PPDU_STATS_RU_996x2, ++ HTT_PPDU_STATS_RU_996x2_484, ++ HTT_PPDU_STATS_RU_996x3, ++ HTT_PPDU_STATS_RU_996x3_484, ++ HTT_PPDU_STATS_RU_996x4, ++}; ++ + #define HTT_TX_PDEV_MAX_FLUSH_REASON_STATS 71 + #define HTT_TX_PDEV_MAX_SIFS_BURST_STATS 9 + #define HTT_TX_PDEV_MAX_SIFS_BURST_HIST_STATS 10 diff --git a/feeds/ipq95xx/mac80211/patches/qca/651-ath12k-Add-debugfs-interface-to-configure-firmware-d.patch b/feeds/ipq95xx/mac80211/patches/qca/651-ath12k-Add-debugfs-interface-to-configure-firmware-d.patch index 7df940fec..4b4ff0731 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/651-ath12k-Add-debugfs-interface-to-configure-firmware-d.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/651-ath12k-Add-debugfs-interface-to-configure-firmware-d.patch @@ -41,11 +41,9 @@ Signed-off-by: Sivashankari Madhavan drivers/net/wireless/ath/ath12k/wmi.h | 16 ++++++ 4 files changed, 136 insertions(+) -diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h -index dec1347..a607329 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h -@@ -946,6 +946,9 @@ struct ath12k_base { +@@ -903,6 +903,9 @@ struct ath12k_base { struct completion htc_suspend; bool fw_recovery_support; @@ -55,8 +53,6 @@ index dec1347..a607329 100644 u64 fw_soc_drop_count; struct device_node *hremote_node; -diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c -index 17a20df..52be2b9 100644 --- a/drivers/net/wireless/ath/ath12k/debugfs.c +++ b/drivers/net/wireless/ath/ath12k/debugfs.c @@ -1003,11 +1003,79 @@ static const struct file_operations fops_fw_recovery = { @@ -134,16 +130,14 @@ index 17a20df..52be2b9 100644 return 0; + debugfs_create_file("fw_dbglog_config", 0600, ab->debugfs_soc, ab, -+ &fops_fw_dbglog); ++ &fops_fw_dbglog); + debugfs_create_file("set_fw_recovery", 0600, ab->debugfs_soc, ab, &fops_fw_recovery); -diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c -index a2b18be..aa6ef25 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -8335,6 +8335,55 @@ static const char *ath12k_wmi_twt_add_dialog_event_status(u32 status) +@@ -8361,6 +8361,55 @@ static const char *ath12k_wmi_twt_add_di } } @@ -199,12 +193,10 @@ index a2b18be..aa6ef25 100644 static void ath12k_wmi_twt_add_dialog_event(struct ath12k_base *ab, struct sk_buff *skb) { -diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h -index 06cff42..ac06454 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -5754,6 +5754,21 @@ struct wmi_ops { - struct target_resource_config *config); +@@ -5669,6 +5669,21 @@ struct target_resource_config { + u32 ema_max_profile_period; }; +enum wmi_dblog_param { @@ -225,7 +217,7 @@ index 06cff42..ac06454 100644 #define WMI_MAX_MEM_REQS 32 #define MAX_RADIOS 3 -@@ -6090,6 +6105,7 @@ int ath12k_wmi_probe_resp_tmpl(struct ath12k *ar, u32 vdev_id, +@@ -6015,6 +6030,7 @@ int ath12k_wmi_probe_resp_tmpl(struct at int ath12k_wmi_set_hw_mode(struct ath12k_base *ab, enum wmi_host_hw_mode_config_type mode); int ath12k_wmi_pdev_ap_ps_cmd_send(struct ath12k *ar, u8 pdev_id, u32 value); @@ -233,6 +225,3 @@ index 06cff42..ac06454 100644 int ath12k_wmi_wow_host_wakeup_ind(struct ath12k *ar); int ath12k_wmi_wow_enable(struct ath12k *ar); int ath12k_wmi_send_vdev_set_tpc_power(struct ath12k *ar, --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/651-mac80211-Update-11be-EHT-elements-to-Draft-2.0-version.patch b/feeds/ipq95xx/mac80211/patches/qca/651-mac80211-Update-11be-EHT-elements-to-Draft-2.0-version.patch deleted file mode 100644 index bbbf39242..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/651-mac80211-Update-11be-EHT-elements-to-Draft-2.0-version.patch +++ /dev/null @@ -1,426 +0,0 @@ -From 9b729b3e18e90684ac94c0c92f1b515293fb6027 Mon Sep 17 00:00:00 2001 -From: Balamurugan Mahalingam -Date: Tue, 26 Jul 2022 00:45:34 -0700 -Subject: [PATCH] ath12k: Update 11be EHT elements to Draft 2.0 version - -Update the EHT operations elements to Draft 2.0 and fix interop -issues with stations - -Signed-off-by: Balamurugan Mahalingam ---- - include/linux/ieee80211.h | 25 +++++++++++++++++++------ - include/net/mac80211.h | 3 ++- - net/mac80211/eht.c | 5 +++-- - net/mac80211/mesh.c | 8 ++++++++ - net/mac80211/mesh_plink.c | 13 ++++++++++--- - net/mac80211/spectmgmt.c | 3 ++- - net/mac80211/util.c | 23 ++++++++++++++++------- - 7 files changed, 60 insertions(+), 20 deletions(-) - -Index: b/include/linux/ieee80211.h -=================================================================== ---- a/include/linux/ieee80211.h 2022-11-18 18:35:15.600296202 +0530 -+++ b/include/linux/ieee80211.h 2022-11-18 18:35:15.596296230 +0530 -@@ -1996,7 +1996,7 @@ struct ieee80211_eht_mcs_nss_supp_bw { - * struct ieee80211_eht_cap_elem_fixed - EHT capabilities fixed data - * - * This structure is the "EHT Capabilities element" fixed fields as -- * described in P802.11be_D1.4 section 9.4.2.313. -+ * described in P802.11be_D2.0 section 9.4.2.313. - * - * @mac_cap_info: MAC capabilities, see IEEE80211_EHT_MAC_CAP* - * @phy_cap_info: PHY capabilities, see IEEE80211_EHT_PHY_CAP* -@@ -2022,16 +2022,25 @@ struct ieee80211_eht_cap_elem { - u8 optional[]; - } __packed; - -+#define EHTOP_PARAMS_EHTOP_INFORMATION_PRESENT BIT(0) -+#define EHTOP_PARAMS_DISABLED_SUBCHANNEL_BITMAP_PRESENT BIT(1) -+#define EHTOP_PARAMS_EHT_DEFAULT_PE_DURATION BIT(2) -+#define EHTOP_PARAMS_GROUP_ADDRESSED_BU_INDICATION_LIMIT BIT(3) -+#define EHTOP_PARAMS_GROUP_ADDRESSED_BU_INDICATION_EXPONENT BIT(4) -+ -+#define DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE 2 -+ - /** - * struct ieee80211_eht_operation - eht operation element - */ - struct ieee80211_eht_operation { -+ u8 ehtop_params; -+ struct ieee80211_eht_mcs_nss_supp_20mhz_only basic_eht_mcs; - u8 chan_width:3, - reserved1:5; -- u8 ccfs; -- u8 disable_sub_chan_bitmap_present:1, -- reserved2:7; -- __le16 disable_subchannel_bitmap; -+ u8 ccfs0; -+ u8 ccfs1; -+ __le16 disable_subchannel_bitmap[0]; - } __packed; - - #define IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT 0x1 -@@ -2790,7 +2799,7 @@ ieee80211_he_spr_size(const u8 *he_spr_i - #define IEEE80211_EHT_PHY_CAP8_RX_4096QAM_WIDER_BW_DL_OFDMA 0x02 - - /* -- * EHT operation channel width as defined in P802.11be_D1.4 section 9.4.2.311 -+ * EHT operation channel width as defined in P802.11be_D2.0 section 9.4.2.311 - */ - #define IEEE80211_EHT_OPER_CHAN_WIDTH 0x7 - #define IEEE80211_EHT_OPER_CHAN_WIDTH_20MHZ 0 -@@ -2902,6 +2911,10 @@ ieee80211_eht_oper_size_ok(const u8 *dat - const struct ieee80211_eht_operation *elem = (const void *)data; - u8 needed = sizeof(*elem); - -+ if (elem->ehtop_params & -+ EHTOP_PARAMS_DISABLED_SUBCHANNEL_BITMAP_PRESENT) -+ needed += DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE; -+ - if (len < needed) - return false; - -Index: b/include/net/mac80211.h -=================================================================== ---- a/include/net/mac80211.h 2022-11-18 18:35:15.600296202 +0530 -+++ b/include/net/mac80211.h 2022-11-18 18:35:15.600296202 +0530 -@@ -760,7 +760,8 @@ struct ieee80211_bss_conf { - bool eht_support; - struct { - u8 chan_width; -- u8 ccfs; -+ u8 ccfs0; -+ u8 ccfs1; - u8 present_bm; - } eht_oper; - bool ap_ps_enable; -Index: b/net/mac80211/eht.c -=================================================================== ---- a/net/mac80211/eht.c 2022-11-18 18:35:15.600296202 +0530 -+++ b/net/mac80211/eht.c 2022-11-18 18:35:15.600296202 +0530 -@@ -85,6 +85,7 @@ void ieee80211_eht_op_ie_to_bss_conf(str - return; - - vif->bss_conf.eht_oper.chan_width = u8_get_bits(op_ie->chan_width, IEEE80211_EHT_OPER_CHAN_WIDTH); -- vif->bss_conf.eht_oper.ccfs = op_ie->ccfs; -- vif->bss_conf.eht_oper.present_bm = u8_get_bits(op_ie->chan_width, IEEE80211_EHT_OPER_PRESENT_BM); -+ vif->bss_conf.eht_oper.ccfs0 = op_ie->ccfs0; -+ vif->bss_conf.eht_oper.ccfs1 = op_ie->ccfs1; -+ vif->bss_conf.eht_oper.present_bm = u8_get_bits(op_ie->ehtop_params, EHTOP_PARAMS_EHTOP_INFORMATION_PRESENT); - } -Index: b/net/mac80211/mesh.c -=================================================================== ---- a/net/mac80211/mesh.c 2022-11-18 18:35:15.600296202 +0530 -+++ b/net/mac80211/mesh.c 2022-11-18 18:35:15.600296202 +0530 -@@ -699,12 +699,14 @@ int mesh_add_eht_oper_ie(struct ieee8021 - return 0; - - len = 2 + 1 + sizeof(struct ieee80211_eht_operation); -+ if (sdata->vif.bss_conf.chandef.ru_punct_bitmap) -+ len += DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE; - - if (skb_tailroom(skb) < len) - return -ENOMEM; - - pos = skb_put(skb, len); -- ieee80211_ie_build_eht_oper(pos, &sdata->vif.bss_conf.chandef); -+ ieee80211_ie_build_eht_oper(pos, &sdata->vif.bss_conf.chandef, eht_cap); - - return 0; - } -@@ -903,6 +905,7 @@ ieee80211_mesh_build_beacon(struct ieee8 - u8 *pos; - struct ieee80211_sub_if_data *sdata; - int hdr_len = offsetofend(struct ieee80211_mgmt, u.beacon); -+ int eht_optional_sz = 0; - - sdata = container_of(ifmsh, struct ieee80211_sub_if_data, u.mesh); - rcu_read_lock(); -@@ -914,6 +917,10 @@ ieee80211_mesh_build_beacon(struct ieee8 - NL80211_IFTYPE_MESH_POINT); - ie_len_eht_cap = ieee80211_ie_len_eht_cap(sdata, - NL80211_IFTYPE_MESH_POINT); -+ -+ if (sdata->vif.bss_conf.chandef.ru_punct_bitmap) -+ eht_optional_sz = DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE; -+ - head_len = hdr_len + - 2 + /* NULL SSID */ - /* Channel Switch Announcement */ -@@ -939,6 +946,7 @@ ieee80211_mesh_build_beacon(struct ieee8 - 2 + 1 + sizeof(struct ieee80211_he_6ghz_capa) + - ie_len_eht_cap + - 2 + 1 + sizeof(struct ieee80211_eht_operation) + -+ + eht_optional_sz + - ifmsh->ie_len; - - bcn = kzalloc(sizeof(*bcn) + head_len + tail_len, GFP_KERNEL); -Index: b/net/mac80211/mesh_plink.c -=================================================================== ---- a/net/mac80211/mesh_plink.c 2022-11-18 18:35:15.600296202 +0530 -+++ b/net/mac80211/mesh_plink.c 2022-11-18 18:35:15.600296202 +0530 -@@ -222,6 +222,10 @@ static int mesh_plink_frame_tx(struct ie - u8 ie_len_he_cap, ie_len_eht_cap; - int hdr_len = offsetofend(struct ieee80211_mgmt, u.action.u.self_prot); - int err = -ENOMEM; -+ int eht_optional_sz = 0; -+ -+ if (sdata->vif.bss_conf.chandef.ru_punct_bitmap) -+ eht_optional_sz = DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE; - - ie_len_he_cap = ieee80211_ie_len_he_cap(sdata, - NL80211_IFTYPE_MESH_POINT); -@@ -245,6 +249,7 @@ static int mesh_plink_frame_tx(struct ie - 2 + 1 + sizeof(struct ieee80211_he_6ghz_capa) + - ie_len_eht_cap + - 2 + 1 + sizeof(struct ieee80211_eht_operation) + -+ + eht_optional_sz + - 2 + 8 + /* peering IE */ - sdata->u.mesh.ie_len); - if (!skb) -@@ -483,7 +488,7 @@ static void mesh_sta_info_init(struct ie - */ - if (elems->eht_operation && - elems->eht_operation->chan_width >= IEEE80211_EHT_OPER_CHAN_WIDTH_80MHZ && -- elems->eht_operation->disable_sub_chan_bitmap_present) { -+ elems->eht_operation->ehtop_params & EHTOP_PARAMS_DISABLED_SUBCHANNEL_BITMAP_PRESENT) { - struct ieee80211_channel *chan = sdata->vif.bss_conf.chandef.chan; - - cfg80211_chandef_create(&eht_chandef, chan, NL80211_CHAN_NO_HT); -@@ -503,10 +508,12 @@ static void mesh_sta_info_init(struct ie - default: - eht_chandef.width = NL80211_CHAN_WIDTH_20; - } -- eht_chandef.center_freq1 = ieee80211_channel_to_frequency(elems->eht_operation->ccfs, -+ eht_chandef.center_freq1 = ieee80211_channel_to_frequency(elems->eht_operation->ccfs0, -+ chan->band); -+ eht_chandef.center_freq2 = ieee80211_channel_to_frequency(elems->eht_operation->ccfs1, - chan->band); - if (cfg80211_ru_punct_bitmap_valid(&eht_chandef)) -- sta->sta.ru_punct_bitmap = elems->eht_operation->disable_subchannel_bitmap; -+ sta->sta.ru_punct_bitmap = elems->eht_operation->disable_subchannel_bitmap[0]; - } - - if (!test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) -Index: b/net/mac80211/spectmgmt.c -=================================================================== ---- a/net/mac80211/spectmgmt.c 2022-11-18 18:35:15.600296202 +0530 -+++ b/net/mac80211/spectmgmt.c 2022-11-18 18:35:15.600296202 +0530 -@@ -152,7 +152,8 @@ int ieee80211_parse_ch_switch_ie(struct - eht_oper.chan_width = (eht_oper_params & - IEEE80211_EHT_OPER_CHAN_WIDTH) | - new_chan_width; -- eht_oper.ccfs = wide_bw_chansw_ie->new_center_freq_seg0; -+ eht_oper.ccfs0 = wide_bw_chansw_ie->new_center_freq_seg0; -+ eht_oper.ccfs1 = wide_bw_chansw_ie->new_center_freq_seg1; - - he_oper.he_oper_params = u32_encode_bits(1, - IEEE80211_HE_OPERATION_6GHZ_OP_INFO); -Index: b/net/mac80211/util.c -=================================================================== ---- a/net/mac80211/util.c 2022-11-18 18:35:15.600296202 +0530 -+++ b/net/mac80211/util.c 2022-11-18 18:37:02.219529000 +0530 -@@ -3293,27 +3293,50 @@ out: - return pos; - } - --u8 *ieee80211_ie_build_eht_oper(u8 *pos, struct cfg80211_chan_def *chandef) -+u8 *ieee80211_ie_build_eht_oper(u8 *pos, struct cfg80211_chan_def *chandef, -+ const struct ieee80211_sta_eht_cap *eht_cap) - { - struct ieee80211_eht_operation *eht_oper; - u32 eht_oper_params = 0; -- u8 ie_len = 1 + sizeof(struct ieee80211_eht_operation); -+ u8 ie_len; - u8 chwidth = 0; - -+ ie_len = 1 + sizeof(struct ieee80211_eht_operation); -+ if (chandef->ru_punct_bitmap) -+ ie_len += DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE; -+ - *pos++ = WLAN_EID_EXTENSION; - *pos++ = ie_len; - *pos++ = WLAN_EID_EXT_EHT_OPERATION; - -+ memset(pos, 0, sizeof(struct ieee80211_eht_operation)); - eht_oper = (struct ieee80211_eht_operation *)pos; - pos += sizeof(struct ieee80211_eht_operation); - -+ eht_oper->ccfs0 = -+ ieee80211_frequency_to_channel(chandef->center_freq1); -+ if (chandef->center_freq2) -+ eht_oper->ccfs1 = -+ ieee80211_frequency_to_channel(chandef->center_freq2); -+ else -+ eht_oper->ccfs1 = 0; - - switch (chandef->width) { - case NL80211_CHAN_WIDTH_320: - chwidth = IEEE80211_EHT_OPER_CTRL_CHANWIDTH_320MHZ; -+ eht_oper->ccfs1 = eht_oper->ccfs0; -+ if (chandef->chan->center_freq < chandef->center_freq1) -+ eht_oper->ccfs0 -= 16; -+ else -+ eht_oper->ccfs0 += 16; - break; - case NL80211_CHAN_WIDTH_160: - chwidth = IEEE80211_EHT_OPER_CTRL_CHANWIDTH_160MHZ; -+ eht_oper->ccfs1 = eht_oper->ccfs0; -+ if (chandef->chan->center_freq < chandef->center_freq1) -+ eht_oper->ccfs0 -= 8; -+ else -+ eht_oper->ccfs0 += 8; - break; - case NL80211_CHAN_WIDTH_80P80: - chwidth = IEEE80211_EHT_OPER_CTRL_CHANWIDTH_160MHZ; -@@ -3329,18 +3352,21 @@ u8 *ieee80211_ie_build_eht_oper(u8 *pos, - break; - } - -+ eht_oper->ehtop_params |= EHTOP_PARAMS_EHTOP_INFORMATION_PRESENT; -+ memcpy(&eht_oper->basic_eht_mcs, -+ &eht_cap->eht_mcs_nss_supp.only_20mhz, -+ sizeof(struct ieee80211_eht_mcs_nss_supp_20mhz_only)); -+ - eht_oper_params = (eht_oper_params & IEEE80211_EHT_OPER_CHAN_WIDTH) | - chwidth; - eht_oper->chan_width = cpu_to_le32(eht_oper_params); -- eht_oper->ccfs = -- ieee80211_frequency_to_channel(chandef->center_freq1); - - if (chandef->ru_punct_bitmap) { -- eht_oper->disable_sub_chan_bitmap_present = 1; -- eht_oper->disable_subchannel_bitmap = chandef->ru_punct_bitmap; -+ eht_oper->ehtop_params |= EHTOP_PARAMS_DISABLED_SUBCHANNEL_BITMAP_PRESENT; -+ eht_oper->disable_subchannel_bitmap[0] = chandef->ru_punct_bitmap; -+ pos += DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE; - } else { -- eht_oper->disable_sub_chan_bitmap_present = 0; -- eht_oper->disable_subchannel_bitmap = 0; -+ eht_oper->ehtop_params &= ~EHTOP_PARAMS_DISABLED_SUBCHANNEL_BITMAP_PRESENT; - } - return pos; - } -@@ -3496,6 +3522,58 @@ bool ieee80211_chandef_vht_oper(struct i - return true; - } - -+void ieee80211_chandef_eht_oper(struct ieee80211_sub_if_data *sdata, -+ const struct ieee80211_eht_operation *eht_oper, -+ bool support_160, bool support_320, -+ struct cfg80211_chan_def *chandef) -+{ -+ -+ chandef->center_freq1 = -+ ieee80211_channel_to_frequency(eht_oper->ccfs0, -+ chandef->chan->band); -+ -+ switch (u8_get_bits(eht_oper->chan_width, -+ IEEE80211_EHT_OPER_CHAN_WIDTH)) { -+ case IEEE80211_EHT_OPER_CHAN_WIDTH_20MHZ: -+ chandef->width = NL80211_CHAN_WIDTH_20; -+ break; -+ case IEEE80211_EHT_OPER_CHAN_WIDTH_40MHZ: -+ chandef->width = NL80211_CHAN_WIDTH_40; -+ break; -+ case IEEE80211_EHT_OPER_CHAN_WIDTH_80MHZ: -+ chandef->width = NL80211_CHAN_WIDTH_80; -+ break; -+ case IEEE80211_EHT_OPER_CHAN_WIDTH_160MHZ: -+ if (support_160) { -+ chandef->width = NL80211_CHAN_WIDTH_160; -+ chandef->center_freq1 = -+ ieee80211_channel_to_frequency(eht_oper->ccfs1, -+ chandef->chan->band); -+ } else { -+ chandef->width = NL80211_CHAN_WIDTH_80; -+ } -+ break; -+ case IEEE80211_EHT_OPER_CHAN_WIDTH_320MHZ: -+ if (support_320) { -+ chandef->width = NL80211_CHAN_WIDTH_320; -+ chandef->center_freq1 = -+ ieee80211_channel_to_frequency(eht_oper->ccfs1, -+ chandef->chan->band); -+ } else if (support_160) { -+ chandef->width = NL80211_CHAN_WIDTH_160; -+ } else { -+ chandef->width = NL80211_CHAN_WIDTH_80; -+ -+ if (chandef->center_freq1 > chandef->chan->center_freq) -+ chandef->center_freq1 -= 40; -+ else -+ chandef->center_freq1 += 40; -+ } -+ break; -+ } -+} -+ -+ - bool ieee80211_chandef_he_6ghz_oper(struct ieee80211_sub_if_data *sdata, - const struct ieee80211_he_operation *he_oper, - const struct ieee80211_eht_operation *eht_oper, -@@ -3599,7 +3677,8 @@ bool ieee80211_chandef_he_6ghz_oper(stru - break; - } - -- if (!eht_oper) { -+ if (!eht_oper || -+ !(eht_oper->ehtop_params & EHTOP_PARAMS_EHTOP_INFORMATION_PRESENT)) { - switch (u8_get_bits(he_6ghz_oper->control, - IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH)) { - case IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_20MHZ: -@@ -3642,37 +3721,8 @@ bool ieee80211_chandef_he_6ghz_oper(stru - eht_phy_cap = eht_cap->eht_cap_elem.phy_cap_info[0]; - support_320 = - eht_phy_cap & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ; -- -- switch (u8_get_bits(eht_oper->chan_width, -- IEEE80211_EHT_OPER_CHAN_WIDTH)) { -- case IEEE80211_EHT_OPER_CHAN_WIDTH_20MHZ: -- he_chandef.width = NL80211_CHAN_WIDTH_20; -- break; -- case IEEE80211_EHT_OPER_CHAN_WIDTH_40MHZ: -- he_chandef.width = NL80211_CHAN_WIDTH_40; -- break; -- case IEEE80211_EHT_OPER_CHAN_WIDTH_80MHZ: -- he_chandef.width = NL80211_CHAN_WIDTH_80; -- break; -- case IEEE80211_EHT_OPER_CHAN_WIDTH_160MHZ: -- if (support_160) -- he_chandef.width = NL80211_CHAN_WIDTH_160; -- else -- he_chandef.width = NL80211_CHAN_WIDTH_80; -- break; -- case IEEE80211_EHT_OPER_CHAN_WIDTH_320MHZ: -- if (support_320) -- he_chandef.width = NL80211_CHAN_WIDTH_320; -- else if (support_160) -- he_chandef.width = NL80211_CHAN_WIDTH_160; -- else -- he_chandef.width = NL80211_CHAN_WIDTH_80; -- break; -- } -- -- he_chandef.center_freq1 = -- ieee80211_channel_to_frequency(eht_oper->ccfs, -- NL80211_BAND_6GHZ); -+ ieee80211_chandef_eht_oper(sdata, eht_oper, support_160, -+ support_320, &he_chandef); - } - - if (!cfg80211_chandef_valid(&he_chandef)) { -Index: b/net/mac80211/ieee80211_i.h -=================================================================== ---- a/net/mac80211/ieee80211_i.h 2022-11-18 18:35:15.600296202 +0530 -+++ b/net/mac80211/ieee80211_i.h 2022-11-18 18:35:15.600296202 +0530 -@@ -2425,7 +2425,8 @@ u8 *ieee80211_ie_build_eht_cap(u8 *pos, - const struct ieee80211_sta_he_cap *he_cap, - const struct ieee80211_sta_eht_cap *eht_cap, - u8 *end); --u8 *ieee80211_ie_build_eht_oper(u8 *pos, struct cfg80211_chan_def *chandef); -+u8 *ieee80211_ie_build_eht_oper(u8 *pos, struct cfg80211_chan_def *chandef, -+ const struct ieee80211_sta_eht_cap *eht_cap); - int ieee80211_parse_bitrates(struct cfg80211_chan_def *chandef, - const struct ieee80211_supported_band *sband, - const u8 *srates, int srates_len, u32 *rates); diff --git a/feeds/ipq95xx/mac80211/patches/qca/652-01-ath12k-single-wiphy-registration-per-SOC.patch b/feeds/ipq95xx/mac80211/patches/qca/652-01-ath12k-single-wiphy-registration-per-SOC.patch index 0e35ba5f4..87fa12fee 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/652-01-ath12k-single-wiphy-registration-per-SOC.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/652-01-ath12k-single-wiphy-registration-per-SOC.patch @@ -20,11 +20,9 @@ Signed-off-by: Sriram R drivers/net/wireless/ath/ath12k/wmi.c | 12 +- 6 files changed, 257 insertions(+), 213 deletions(-) -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/core.c 2022-08-08 19:09:16.049418214 +0530 -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.c 2022-08-08 19:09:16.037418192 +0530 -@@ -514,23 +514,23 @@ +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -473,23 +473,23 @@ static int ath12k_core_pdev_create(struc return ret; } @@ -54,7 +52,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor } ret = ath12k_spectral_init(ab); -@@ -543,10 +543,10 @@ +@@ -502,10 +502,10 @@ static int ath12k_core_pdev_create(struc err_thermal_unregister: ath12k_thermal_unregister(ab); @@ -67,7 +65,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor err_pdev_debug: ath12k_debugfs_pdev_destroy(ab); -@@ -623,13 +623,6 @@ +@@ -576,13 +576,6 @@ static int ath12k_core_start(struct ath1 goto err_hif_stop; } @@ -81,8 +79,8 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor ath12k_dp_cc_config(ab); ath12k_dp_pdev_pre_alloc(ab); -@@ -637,20 +630,27 @@ - ret = ath12k_dp_pdev_reo_setup(ab); +@@ -590,20 +583,27 @@ static int ath12k_core_start(struct ath1 + ret = ath12k_dp_rx_pdev_reo_setup(ab); if (ret) { ath12k_err(ab, "failed to initialize reo destination rings: %d\n", ret); - goto err_mac_destroy; @@ -112,7 +110,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor } /* put hardware to DBS mode */ -@@ -658,7 +658,7 @@ +@@ -611,7 +611,7 @@ static int ath12k_core_start(struct ath1 ret = ath12k_wmi_set_hw_mode(ab, WMI_HOST_HW_MODE_DBS); if (ret) { ath12k_err(ab, "failed to send dbs mode: %d\n", ret); @@ -121,7 +119,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor } } -@@ -666,15 +666,15 @@ +@@ -619,15 +619,15 @@ static int ath12k_core_start(struct ath1 if (ret) { ath12k_err(ab, "failed to send htt version request message: %d\n", ret); @@ -132,15 +130,15 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor return 0; -err_reo_cleanup: -- ath12k_dp_pdev_reo_cleanup(ab); +- ath12k_dp_rx_pdev_reo_cleanup(ab); err_mac_destroy: ath12k_mac_destroy(ab); +err_reo_cleanup: -+ ath12k_dp_pdev_reo_cleanup(ab); ++ ath12k_dp_rx_pdev_reo_cleanup(ab); err_hif_stop: ath12k_hif_stop(ab); err_wmi_detach: -@@ -822,6 +822,8 @@ +@@ -798,6 +798,8 @@ static void ath12k_core_restart(struct w ab->stats.fw_crash_counter++; spin_unlock_bh(&ab->base_lock); @@ -149,7 +147,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor for (i = 0; i < ab->num_radios; i++) { pdev = &ab->pdevs[i]; ar = pdev->ar; -@@ -834,7 +836,6 @@ +@@ -810,7 +812,6 @@ static void ath12k_core_restart(struct w } } @@ -157,7 +155,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor ath12k_mac_drain_tx(ar); complete(&ar->scan.started); complete(&ar->scan.completed); -@@ -879,7 +880,7 @@ +@@ -855,7 +856,7 @@ static void ath12k_core_restart(struct w case ATH12K_STATE_ON: ar->state = ATH12K_STATE_RESTARTING; ath12k_core_halt(ar); @@ -166,11 +164,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor break; case ATH12K_STATE_OFF: ath12k_warn(ab, -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/core.h 2022-08-08 19:09:16.049418214 +0530 -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.h 2022-08-08 19:09:16.041418199 +0530 -@@ -597,9 +597,8 @@ +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -598,9 +598,8 @@ enum ath12k_fw_recovery_option { struct ath12k { struct ath12k_base *ab; @@ -181,7 +177,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor struct ath12k_pdev_wmi *wmi; struct ath12k_pdev_dp dp; u8 mac_addr[ETH_ALEN]; -@@ -843,11 +842,24 @@ +@@ -843,11 +842,24 @@ struct ath12k_reg_freq { }; @@ -206,17 +202,15 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor struct ath12k_qmi qmi; struct ath12k_wmi_base wmi_ab; struct completion fw_ready; -@@ -1168,5 +1180,4 @@ +@@ -1165,5 +1177,4 @@ static inline const char *ath12k_bus_str return "unknown"; } - #endif /* _CORE_H_ */ -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/mac.c 2022-08-08 19:09:16.049418214 +0530 -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac.c 2022-08-08 19:12:36.297805109 +0530 -@@ -9601,9 +9601,9 @@ +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -9680,9 +9680,9 @@ static int ath12k_mac_setup_channels_rat return 0; } @@ -227,8 +221,8 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac + struct ieee80211_hw *hw = ab->ah->hw; struct ieee80211_iface_combination *combinations; struct ieee80211_iface_limit *limits; - int n_limits; -@@ -9644,8 +9644,8 @@ + int n_limits, max_interfaces; +@@ -9736,8 +9736,8 @@ static int ath12k_mac_setup_iface_combin BIT(NL80211_CHAN_WIDTH_160) | BIT(NL80211_CHAN_WIDTH_320); @@ -239,7 +233,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac return 0; } -@@ -9695,19 +9695,12 @@ +@@ -9787,19 +9787,12 @@ static void __ath12k_mac_unregister(stru { cancel_work_sync(&ar->regd_update_work); @@ -259,7 +253,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac } void ath12k_mac_unregister(struct ath12k_base *ab) -@@ -9724,211 +9717,96 @@ +@@ -9816,211 +9809,96 @@ void ath12k_mac_unregister(struct ath12k __ath12k_mac_unregister(ar); } @@ -320,7 +314,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac - ar->hw->wiphy->available_antennas_rx = cap->rx_chain_mask; - ar->hw->wiphy->available_antennas_tx = cap->tx_chain_mask; - -- ar->hw->wiphy->interface_modes = ab->hw_params.interface_modes; +- ar->hw->wiphy->interface_modes = ab->hw_params->interface_modes; + ath12k_pdev_caps_update(ar); - ar->hw->wiphy->ru_punct_supp_bw = NL80211_RU_PUNCT_SUPP_BW_80; @@ -359,7 +353,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac - ieee80211_hw_set(ar->hw, USES_RSS); - } - -- if (ar->ab->hw_params.supports_ap_ps) +- if (ar->ab->hw_params->supports_ap_ps) - ieee80211_hw_set(ar->hw, SUPPORTS_AP_PS); - - ar->hw->wiphy->features |= NL80211_FEATURE_STATIC_SMPS; @@ -444,7 +438,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac - goto err_free_if_combs; - } - -- if (!ab->hw_params.supports_monitor) +- if (!ab->hw_params->supports_monitor) - /* There's a race between calling ieee80211_register_hw() - * and here where the monitor mode is enabled for a little - * while. But that time is so short and in practise it make @@ -517,7 +511,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac for (i = 0; i < ab->num_radios; i++) { pdev = &ab->pdevs[i]; ar = pdev->ar; -@@ -9943,17 +9821,146 @@ +@@ -10035,17 +9913,146 @@ int ath12k_mac_register(struct ath12k_ba if (ret) goto err_cleanup; @@ -550,7 +544,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac + /* TODO: SET_IEEE80211_PERM_ADDR() */ + SET_IEEE80211_DEV(hw, ab->dev); + -+ hw->wiphy->interface_modes = ab->hw_params.interface_modes; ++ hw->wiphy->interface_modes = ab->hw_params->interface_modes; + hw->wiphy->ru_punct_supp_bw = NL80211_RU_PUNCT_SUPP_BW_80; + + ieee80211_hw_set(hw, SIGNAL_DBM); @@ -573,7 +567,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac + ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD); + } + -+ if (ab->hw_params.supports_ap_ps) ++ if (ab->hw_params->supports_ap_ps) + ieee80211_hw_set(hw, SUPPORTS_AP_PS); + + hw->wiphy->features |= NL80211_FEATURE_STATIC_SMPS; @@ -630,7 +624,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac + goto err_full_cleanup; + } + -+ if (!ab->hw_params.supports_monitor) ++ if (!ab->hw_params->supports_monitor) + /* There's a race between calling ieee80211_register_hw() + * and here where the monitor mode is enabled for a little + * while. But that time is so short and in practise it make @@ -667,7 +661,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac err_cleanup: for (i = i - 1; i >= 0; i--) { pdev = &ab->pdevs[i]; -@@ -9961,32 +9968,56 @@ +@@ -10053,32 +10060,56 @@ err_cleanup: __ath12k_mac_unregister(ar); } @@ -732,8 +726,8 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac + ar->hw = hw; ar->pdev = pdev; ar->pdev_idx = i; - ar->lmac_id = ath12k_hw_get_mac_from_pdev_id(&ab->hw_params, i); -@@ -10028,11 +10059,6 @@ + ar->lmac_id = ath12k_hw_get_mac_from_pdev_id(ab->hw_params, i); +@@ -10120,11 +10151,6 @@ int ath12k_mac_allocate(struct ath12k_ba } return 0; @@ -745,7 +739,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac } void ath12k_mac_destroy(struct ath12k_base *ab) -@@ -10047,7 +10073,9 @@ +@@ -10139,7 +10165,9 @@ void ath12k_mac_destroy(struct ath12k_ba if (!ar) continue; @@ -756,11 +750,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac + ieee80211_free_hw(ab->ah->hw); + ab->ah = NULL; } -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/reg.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/reg.c 2022-08-08 19:09:16.049418214 +0530 -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/reg.c 2022-08-08 19:09:16.041418199 +0530 -@@ -701,10 +701,10 @@ +--- a/drivers/net/wireless/ath/ath12k/reg.c ++++ b/drivers/net/wireless/ath/ath12k/reg.c +@@ -701,10 +701,10 @@ void ath12k_regd_update_work(struct work } } @@ -774,11 +766,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/reg } void ath12k_reg_free(struct ath12k_base *ab) -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/reg.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/reg.h 2022-08-08 19:09:16.049418214 +0530 -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/reg.h 2022-08-08 19:09:16.041418199 +0530 -@@ -26,7 +26,7 @@ +--- a/drivers/net/wireless/ath/ath12k/reg.h ++++ b/drivers/net/wireless/ath/ath12k/reg.h +@@ -26,7 +26,7 @@ enum ath12k_dfs_region { }; /* ATH12K Regulatory API's */ @@ -787,11 +777,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/reg void ath12k_reg_free(struct ath12k_base *ab); void ath12k_regd_update_work(struct work_struct *work); struct ieee80211_regdomain * -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/wmi.c 2022-08-08 19:09:16.049418214 +0530 -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi.c 2022-08-08 19:09:16.045418207 +0530 -@@ -5848,7 +5848,8 @@ +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -5881,7 +5881,8 @@ static void ath12k_wmi_event_scan_foreig break; case ATH12K_SCAN_RUNNING: case ATH12K_SCAN_ABORTING: @@ -801,7 +789,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi break; } } -@@ -6797,7 +6798,8 @@ +@@ -6830,7 +6831,8 @@ static int ath12k_reg_handle_chan_list(s ar = ab->pdevs[pdev_idx].ar; kfree(ab->new_regd[pdev_idx]); ab->new_regd[pdev_idx] = regd; @@ -811,7 +799,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi } else { /* Multiple events for the same *ar is not expected. But we * can still clear any previously stored default_regd if we -@@ -7191,7 +7193,7 @@ +@@ -7224,7 +7226,7 @@ static void ath12k_mgmt_rx_event(struct status->freq, status->band, status->signal, status->rate_idx); @@ -820,7 +808,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi exit: rcu_read_unlock(); -@@ -7351,7 +7353,7 @@ +@@ -7384,7 +7386,7 @@ static void ath12k_peer_sta_kickout_even goto exit; } @@ -829,7 +817,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi arg.mac_addr, NULL); if (!sta) { ath12k_warn(ab, "Spurious quick kickout for STA %pM\n", -@@ -7831,7 +7833,7 @@ +@@ -7864,7 +7866,7 @@ ath12k_wmi_pdev_dfs_radar_detected_event if (ar->dfs_block_radar_events) ath12k_info(ab, "DFS Radar detected, but ignored as requested\n"); else diff --git a/feeds/ipq95xx/mac80211/patches/qca/652-03-ath12k-vdev-statemachine-changes-for-single-wiphy.patch b/feeds/ipq95xx/mac80211/patches/qca/652-03-ath12k-vdev-statemachine-changes-for-single-wiphy.patch index f404726e7..261d37cca 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/652-03-ath12k-vdev-statemachine-changes-for-single-wiphy.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/652-03-ath12k-vdev-statemachine-changes-for-single-wiphy.patch @@ -19,7 +19,7 @@ Signed-off-by: Sriram R --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h -@@ -300,6 +300,7 @@ struct ath12k_vif { +@@ -301,6 +301,7 @@ struct ath12k_vif { } ap; } u; @@ -29,7 +29,7 @@ Signed-off-by: Sriram R bool spectral_enabled; --- a/drivers/net/wireless/ath/ath12k/hw.h +++ b/drivers/net/wireless/ath/ath12k/hw.h -@@ -65,6 +65,8 @@ +@@ -68,6 +68,8 @@ #define TARGET_RX_BATCHMODE 1 #define TARGET_EMA_MAX_PROFILE_PERIOD 8 @@ -40,7 +40,16 @@ Signed-off-by: Sriram R --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -6788,37 +6788,19 @@ static void ath12k_mac_op_update_vif_off +@@ -1129,7 +1129,7 @@ static int ath12k_mac_monitor_start(stru + ath12k_mac_get_any_chandef_iter, + &chandef); + if (!chandef) +- return 0; ++ return -EINVAL; + + ret = ath12k_mac_monitor_vdev_start(ar, ar->monitor_vdev_id, chandef); + if (ret) { +@@ -6878,37 +6878,19 @@ static void ath12k_mac_op_update_vif_off } } @@ -61,8 +70,7 @@ Signed-off-by: Sriram R - int bit; - - vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD; -+ int ret, vdev_id; - +- - mutex_lock(&ar->conf_mutex); - - if (vif->type == NL80211_IFTYPE_AP && @@ -71,7 +79,8 @@ Signed-off-by: Sriram R - ret = -ENOBUFS; - goto err; - } -- ++ int ret, vdev_id; + - if (ar->num_created_vdevs > (TARGET_NUM_VDEVS - 1)) { - ath12k_warn(ab, "failed to create vdev, reached max vdev limit %d\n", - TARGET_NUM_VDEVS); @@ -82,7 +91,7 @@ Signed-off-by: Sriram R /* Send vdev stats offload commands to firmware before first vdev * creation. ie., when num_created_vdevs = 0 -@@ -6831,34 +6813,9 @@ static int ath12k_mac_op_add_interface(s +@@ -6921,34 +6903,15 @@ static int ath12k_mac_op_add_interface(s } } @@ -109,8 +118,12 @@ Signed-off-by: Sriram R - sizeof(arvif->bitrate_mask.control[i].he_mcs)); - memset(arvif->bitrate_mask.control[i].eht_mcs, 0xff, - sizeof(arvif->bitrate_mask.control[i].eht_mcs)); -- } -- ++ if (!ab->free_vdev_map) { ++ ath12k_warn(ar->ab, "failed to create vdev. No free vdev id left.\n"); ++ ret = -EINVAL; ++ goto err; + } + - bit = __ffs64(ab->free_vdev_map); + vdev_id = __ffs64(ab->free_vdev_map); @@ -119,7 +132,7 @@ Signed-off-by: Sriram R arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE; switch (vif->type) { -@@ -6874,17 +6831,18 @@ static int ath12k_mac_op_add_interface(s +@@ -6964,17 +6927,18 @@ static int ath12k_mac_op_add_interface(s break; case NL80211_IFTYPE_MONITOR: arvif->vdev_type = WMI_VDEV_TYPE_MONITOR; @@ -140,7 +153,7 @@ Signed-off-by: Sriram R vif->cab_queue = arvif->vdev_id % (ATH12K_HW_MAX_QUEUES - 1); for (i = 0; i < ARRAY_SIZE(vif->hw_queue); i++) vif->hw_queue[i] = i % (ATH12K_HW_MAX_QUEUES - 1); -@@ -6904,8 +6862,10 @@ static int ath12k_mac_op_add_interface(s +@@ -6994,8 +6958,10 @@ static int ath12k_mac_op_add_interface(s } ar->num_created_vdevs++; @@ -151,7 +164,7 @@ Signed-off-by: Sriram R ar->allocated_vdev_map |= 1LL << arvif->vdev_id; ab->free_vdev_map &= ~(1LL << arvif->vdev_id); -@@ -6994,7 +6954,7 @@ static int ath12k_mac_op_add_interface(s +@@ -7084,7 +7050,7 @@ static int ath12k_mac_op_add_interface(s goto err_peer_del; param_id = WMI_VDEV_PARAM_RTS_THRESHOLD; @@ -160,7 +173,7 @@ Signed-off-by: Sriram R ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param_id, param_value); if (ret) { -@@ -7041,6 +7001,7 @@ err_peer_del: +@@ -7131,6 +7097,7 @@ err_peer_del: err_vdev_del: ath12k_wmi_vdev_delete(ar, arvif->vdev_id); ar->num_created_vdevs--; @@ -168,7 +181,7 @@ Signed-off-by: Sriram R ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id); ab->free_vdev_map |= 1LL << arvif->vdev_id; ab->free_vdev_stats_id_map &= ~(1LL << arvif->vdev_stats_id); -@@ -7049,10 +7010,110 @@ err_vdev_del: +@@ -7139,10 +7106,110 @@ err_vdev_del: spin_unlock_bh(&ar->data_lock); err: @@ -281,7 +294,7 @@ Signed-off-by: Sriram R } static void ath12k_mac_vif_unref(struct ath12k_dp *dp, struct ieee80211_vif *vif) -@@ -7083,12 +7144,22 @@ static void ath12k_mac_vif_unref(struct +@@ -7173,12 +7240,22 @@ static void ath12k_mac_vif_unref(struct static void ath12k_mac_op_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { @@ -306,7 +319,7 @@ Signed-off-by: Sriram R mutex_lock(&ar->conf_mutex); ath12k_dbg(ab, ATH12K_DBG_MAC, "mac remove interface (vdev %d)\n", -@@ -7134,6 +7205,7 @@ static void ath12k_mac_op_remove_interfa +@@ -7224,6 +7301,7 @@ static void ath12k_mac_op_remove_interfa ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id); ab->free_vdev_stats_id_map &= ~(1LL << arvif->vdev_stats_id); ar->num_created_vdevs--; @@ -314,7 +327,7 @@ Signed-off-by: Sriram R ath12k_dbg(ab, ATH12K_DBG_MAC, "vdev %pM deleted, vdev_id %d\n", vif->addr, arvif->vdev_id); -@@ -7162,6 +7234,7 @@ err_vdev_del: +@@ -7252,6 +7330,7 @@ err_vdev_del: /* TODO: recal traffic pause state based on the available vdevs */ mutex_unlock(&ar->conf_mutex); @@ -322,26 +335,39 @@ Signed-off-by: Sriram R } /* FIXME: Has to be verified. */ -@@ -7769,8 +7842,15 @@ static void ath12k_mac_op_change_chanctx +@@ -7855,8 +7934,20 @@ static void ath12k_mac_op_change_chanctx struct ieee80211_chanctx_conf *ctx, u32 changed) { - struct ath12k *ar = hw->priv; - struct ath12k_base *ab = ar->ab; ++ struct ath12k_hw *ah = hw->priv; + struct ath12k *ar; + struct ath12k_base *ab; + ++ mutex_lock(&ah->conf_mutex); ++ + ar = ath12k_get_ar_by_ctx(hw, ctx); + -+ if (!ar) ++ if (!ar) { ++ mutex_unlock(&ah->conf_mutex); + return; ++ } + + ab = ar->ab; mutex_lock(&ar->conf_mutex); -@@ -8338,13 +8418,43 @@ ath12k_mac_op_assign_vif_chanctx(struct - struct ieee80211_vif *vif, +@@ -7877,6 +7968,7 @@ static void ath12k_mac_op_change_chanctx + + unlock: + mutex_unlock(&ar->conf_mutex); ++ mutex_unlock(&ah->conf_mutex); + } + + static int ath12k_start_vdev_delay(struct ieee80211_hw *hw, +@@ -8431,13 +8523,43 @@ ath12k_mac_op_assign_vif_chanctx(struct + struct ieee80211_bss_conf *link_conf, struct ieee80211_chanctx_conf *ctx) { - struct ath12k *ar = hw->priv; @@ -386,7 +412,7 @@ Signed-off-by: Sriram R mutex_lock(&ar->conf_mutex); ath12k_dbg(ab, ATH12K_DBG_MAC, -@@ -8428,6 +8538,7 @@ ath12k_mac_op_assign_vif_chanctx(struct +@@ -8521,6 +8643,7 @@ ath12k_mac_op_assign_vif_chanctx(struct out: mutex_unlock(&ar->conf_mutex); @@ -394,8 +420,8 @@ Signed-off-by: Sriram R return ret; } -@@ -8437,11 +8548,29 @@ ath12k_mac_op_unassign_vif_chanctx(struc - struct ieee80211_vif *vif, +@@ -8531,11 +8654,29 @@ ath12k_mac_op_unassign_vif_chanctx(struc + struct ieee80211_bss_conf *link_conf, struct ieee80211_chanctx_conf *ctx) { - struct ath12k *ar = hw->priv; @@ -426,7 +452,7 @@ Signed-off-by: Sriram R mutex_lock(&ar->conf_mutex); ath12k_dbg(ab, ATH12K_DBG_MAC, -@@ -8459,11 +8588,13 @@ ath12k_mac_op_unassign_vif_chanctx(struc +@@ -8553,11 +8694,13 @@ ath12k_mac_op_unassign_vif_chanctx(struc ret = ath12k_mac_monitor_stop(ar); if (ret) { mutex_unlock(&ar->conf_mutex); @@ -440,7 +466,7 @@ Signed-off-by: Sriram R return; } -@@ -8484,6 +8615,7 @@ ath12k_mac_op_unassign_vif_chanctx(struc +@@ -8578,6 +8721,7 @@ ath12k_mac_op_unassign_vif_chanctx(struc ath12k_mac_monitor_stop(ar); mutex_unlock(&ar->conf_mutex); @@ -448,7 +474,7 @@ Signed-off-by: Sriram R } static int -@@ -8492,7 +8624,22 @@ ath12k_mac_op_switch_vif_chanctx(struct +@@ -8586,7 +8730,22 @@ ath12k_mac_op_switch_vif_chanctx(struct int n_vifs, enum ieee80211_chanctx_switch_mode mode) { diff --git a/feeds/ipq95xx/mac80211/patches/qca/652-04-ath12k-Support-scan-for-single-wiphy-architecture.patch b/feeds/ipq95xx/mac80211/patches/qca/652-04-ath12k-Support-scan-for-single-wiphy-architecture.patch index 6d1cf469c..7c7dca118 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/652-04-ath12k-Support-scan-for-single-wiphy-architecture.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/652-04-ath12k-Support-scan-for-single-wiphy-architecture.patch @@ -39,7 +39,7 @@ Signed-off-by: Sriram R static int ath12k_start_vdev_delay(struct ieee80211_hw *hw, struct ieee80211_vif *vif); -@@ -3876,6 +3877,74 @@ static void ath12k_mac_op_bss_info_chang +@@ -3935,6 +3936,81 @@ static void ath12k_mac_op_bss_info_chang mutex_unlock(&ar->conf_mutex); } @@ -57,14 +57,15 @@ Signed-off-by: Sriram R + if (ret) { + ath12k_warn(ar->ab, "failed to delete WMI scan vdev %d: %d\n", + arvif->vdev_id, ret); -+ return ret; ++ goto clean_up; + } + + time_left = wait_for_completion_timeout(&ar->vdev_delete_done, + ATH12K_VDEV_DELETE_TIMEOUT_HZ); + if (time_left == 0) { + ath12k_warn(ar->ab, "Timeout in receiving vdev delete response\n"); -+ return -ETIMEDOUT; ++ ret = -ETIMEDOUT; ++ goto clean_up; + } + + ar->ab->free_vdev_map |= 1LL << arvif->vdev_id; @@ -72,8 +73,14 @@ Signed-off-by: Sriram R + ar->ab->free_vdev_stats_id_map &= ~(1LL << arvif->vdev_stats_id); + ar->num_created_vdevs--; + arvif->is_created = false; ++ ++clean_up: + arvif->ar = NULL; + ++ spin_lock_bh(&ar->data_lock); ++ list_del(&arvif->list); ++ spin_unlock_bh(&ar->data_lock); ++ + return ret; +} + @@ -114,7 +121,7 @@ Signed-off-by: Sriram R void __ath12k_mac_scan_finish(struct ath12k *ar) { lockdep_assert_held(&ar->data_lock); -@@ -4042,12 +4111,60 @@ static int ath12k_mac_op_hw_scan(struct +@@ -4101,12 +4177,60 @@ static int ath12k_mac_op_hw_scan(struct struct ieee80211_vif *vif, struct ieee80211_scan_request *hw_req) { @@ -176,7 +183,7 @@ Signed-off-by: Sriram R mutex_lock(&ar->conf_mutex); -@@ -4124,7 +4241,18 @@ exit: +@@ -4183,7 +4307,18 @@ exit: static void ath12k_mac_op_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { @@ -196,7 +203,7 @@ Signed-off-by: Sriram R mutex_lock(&ar->conf_mutex); ath12k_scan_abort(ar); -@@ -6817,6 +6945,7 @@ static int ath12k_mac_vdev_create(struct +@@ -6907,6 +7042,7 @@ static int ath12k_mac_vdev_create(struct arvif->vdev_id = vdev_id; arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE; @@ -204,7 +211,7 @@ Signed-off-by: Sriram R switch (vif->type) { case NL80211_IFTYPE_UNSPECIFIED: -@@ -6974,8 +7103,6 @@ static int ath12k_mac_vdev_create(struct +@@ -7064,8 +7200,6 @@ static int ath12k_mac_vdev_create(struct if (ret) goto err_peer_del; @@ -213,7 +220,7 @@ Signed-off-by: Sriram R return ret; err_peer_del: -@@ -7010,6 +7137,7 @@ err_vdev_del: +@@ -7100,6 +7234,7 @@ err_vdev_del: spin_unlock_bh(&ar->data_lock); err: @@ -221,7 +228,7 @@ Signed-off-by: Sriram R return ret; } -@@ -7057,7 +7185,6 @@ static struct ath12k *ath12k_mac_assign_ +@@ -7147,7 +7282,6 @@ static struct ath12k *ath12k_mac_assign_ ath12k_warn(ab, "failed to create vdev %d ret %d", bit, ret); goto unlock; } @@ -229,7 +236,7 @@ Signed-off-by: Sriram R /* TODO Apply any parameters for the vdev which were received after * add_interface, corresponding to this vif -@@ -7148,7 +7275,6 @@ static void ath12k_mac_op_remove_interfa +@@ -7238,7 +7372,6 @@ static void ath12k_mac_op_remove_interfa struct ath12k *ar; struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); struct ath12k_base *ab; @@ -237,7 +244,7 @@ Signed-off-by: Sriram R int ret; mutex_lock(&ah->conf_mutex); -@@ -7177,21 +7303,9 @@ static void ath12k_mac_op_remove_interfa +@@ -7267,21 +7400,9 @@ static void ath12k_mac_op_remove_interfa arvif->vdev_id, ret); } @@ -261,7 +268,7 @@ Signed-off-by: Sriram R if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { ar->monitor_vdev_id = -1; -@@ -7201,12 +7315,6 @@ static void ath12k_mac_op_remove_interfa +@@ -7291,20 +7412,10 @@ static void ath12k_mac_op_remove_interfa ret = ath12k_mac_monitor_vdev_delete(ar); } @@ -274,7 +281,24 @@ Signed-off-by: Sriram R ath12k_dbg(ab, ATH12K_DBG_MAC, "vdev %pM deleted, vdev_id %d\n", vif->addr, arvif->vdev_id); -@@ -8437,19 +8545,34 @@ ath12k_mac_op_assign_vif_chanctx(struct + err_vdev_del: +- spin_lock_bh(&ar->data_lock); +- list_del(&arvif->list); +- spin_unlock_bh(&ar->data_lock); +- + ath12k_peer_cleanup(ar, arvif->vdev_id); + + idr_for_each(&ar->txmgmt_idr, +@@ -8512,7 +8623,7 @@ ath12k_mac_op_assign_vif_chanctx(struct + struct ieee80211_chanctx_conf *ctx) + { + struct ath12k_hw *ah = hw->priv; +- struct ath12k *ar; ++ struct ath12k *ar, *arvif_ar; + struct ath12k_base *ab; + struct ath12k_vif *arvif = (void *)vif->drv_priv; + int ret; +@@ -8530,19 +8641,38 @@ ath12k_mac_op_assign_vif_chanctx(struct return -EINVAL; } } else { @@ -299,9 +323,13 @@ Signed-off-by: Sriram R + return -EBUSY; + } + -+ ret = ath12k_mac_vdev_delete(arvif->ar, vif); ++ arvif_ar = arvif->ar; ++ ++ mutex_lock(&arvif_ar->conf_mutex); ++ ret = ath12k_mac_vdev_delete(arvif_ar, vif); ++ mutex_unlock(&arvif_ar->conf_mutex); + if (ret) -+ ath12k_warn(arvif->ar->ab, "unable to delete vdev %d\n", ret); ++ ath12k_warn(arvif_ar->ab, "unable to delete vdev %d\n", ret); + + mutex_lock(&ar->conf_mutex); + ret = ath12k_mac_vdev_create(ar, vif); diff --git a/feeds/ipq95xx/mac80211/patches/qca/652-05-ath12k-Cache-configs-for-vdev-before-actual-vdev-cre.patch b/feeds/ipq95xx/mac80211/patches/qca/652-05-ath12k-Cache-configs-for-vdev-before-actual-vdev-cre.patch index 648199713..14dd68e59 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/652-05-ath12k-Cache-configs-for-vdev-before-actual-vdev-cre.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/652-05-ath12k-Cache-configs-for-vdev-before-actual-vdev-cre.patch @@ -21,11 +21,9 @@ Signed-off-by: Sriram R drivers/net/wireless/ath/ath12k/testmode.c | 6 +- 5 files changed, 162 insertions(+), 28 deletions(-) -Index: b/drivers/net/wireless/ath/ath12k/core.h -=================================================================== ---- a/drivers/net/wireless/ath/ath12k/core.h 2022-08-28 00:07:34.984773946 +0530 -+++ b/drivers/net/wireless/ath/ath12k/core.h 2022-08-28 00:07:34.976774009 +0530 -@@ -262,6 +262,25 @@ struct ath12k_reg_tpc_power_info { +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -263,6 +263,25 @@ struct ath12k_reg_tpc_power_info { struct chan_power_info chan_power_info[IEEE80211_MAX_NUM_PWR_LEVEL]; }; @@ -45,13 +43,13 @@ Index: b/drivers/net/wireless/ath/ath12k/core.h +struct ath12k_vif_cache { + struct ath12k_tx_conf tx_conf; + struct ath12k_key_conf key_conf; -+ u32 bss_conf_changed; ++ u64 bss_conf_changed; +}; + struct ath12k_vif { u32 vdev_id; enum wmi_vdev_type vdev_type; -@@ -321,6 +340,7 @@ struct ath12k_vif { +@@ -322,6 +341,7 @@ struct ath12k_vif { u8 nontransmitting_vif_count; bool bcca_zero_sent; bool do_not_send_tmpl; @@ -59,10 +57,8 @@ Index: b/drivers/net/wireless/ath/ath12k/core.h #ifdef CPTCFG_ATH12K_DEBUGFS struct dentry *debugfs_twt; #endif /* CPTCFG_ATH12K_DEBUGFS */ -Index: b/drivers/net/wireless/ath/ath12k/debugfs_sta.c -=================================================================== ---- a/drivers/net/wireless/ath/ath12k/debugfs_sta.c 2022-08-28 00:07:34.984773946 +0530 -+++ b/drivers/net/wireless/ath/ath12k/debugfs_sta.c 2022-08-28 00:07:34.976774009 +0530 +--- a/drivers/net/wireless/ath/ath12k/debugfs_sta.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs_sta.c @@ -1059,7 +1059,16 @@ static const struct file_operations fops void ath12k_debugfs_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct dentry *dir) @@ -88,10 +84,8 @@ Index: b/drivers/net/wireless/ath/ath12k/debugfs_sta.c + + mutex_unlock(&ah->conf_mutex); } -Index: b/drivers/net/wireless/ath/ath12k/mac.c -=================================================================== ---- a/drivers/net/wireless/ath/ath12k/mac.c 2022-08-28 00:07:34.984773946 +0530 -+++ b/drivers/net/wireless/ath/ath12k/mac.c 2022-08-28 00:08:42.948237154 +0530 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -248,7 +248,7 @@ static const u32 ath12k_smps_map[] = { }; @@ -127,7 +121,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c struct ath12k *ath12k_mac_get_ar_by_vdev_id(struct ath12k_base *ab, u32 vdev_id) { int i; -@@ -3120,11 +3139,10 @@ static bool ath12k_mac_set_eht_txbf_conf +@@ -3160,11 +3179,10 @@ static bool ath12k_mac_set_eht_txbf_conf return true; } @@ -140,7 +134,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c struct ath12k_vif *arvif = (void *)vif->drv_priv; struct peer_assoc_params peer_arg; struct ieee80211_sta *ap_sta; -@@ -3229,10 +3247,9 @@ static void ath12k_bss_assoc(struct ieee +@@ -3269,10 +3287,9 @@ static void ath12k_bss_assoc(struct ieee arvif->vdev_id, ret); } @@ -152,24 +146,24 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c struct ath12k_vif *arvif = (void *)vif->drv_priv, *tx_arvif; int ret; -@@ -3540,12 +3557,11 @@ static int ath12k_mac_config_obss_pd(str +@@ -3580,12 +3597,11 @@ static int ath12k_mac_config_obss_pd(str return 0; } -static void ath12k_mac_op_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, -- u32 changed) +- u64 changed) +static void ath12k_mac_bss_info_changed(struct ath12k *ar, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, -+ u32 changed) ++ u64 changed) { - struct ath12k *ar = hw->priv; struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); struct cfg80211_chan_def def; u32 param_id, param_value; -@@ -3560,7 +3576,7 @@ static void ath12k_mac_op_bss_info_chang +@@ -3600,7 +3616,7 @@ static void ath12k_mac_op_bss_info_chang u32 rate; bool color_collision_detect; @@ -178,10 +172,10 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c if (changed & BSS_CHANGED_BEACON_INT) { arvif->beacon_interval = info->beacon_int; -@@ -3752,9 +3768,9 @@ static void ath12k_mac_op_bss_info_chang +@@ -3792,9 +3808,9 @@ static void ath12k_mac_op_bss_info_chang if (changed & BSS_CHANGED_ASSOC) { - if (info->assoc) + if (vif->cfg.assoc) - ath12k_bss_assoc(hw, vif, info); + ath12k_bss_assoc(ar, vif, info); else @@ -190,14 +184,14 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c } if (changed & BSS_CHANGED_TXPOWER) { -@@ -3877,6 +3893,31 @@ static void ath12k_mac_op_bss_info_chang +@@ -3940,6 +3956,31 @@ static void ath12k_mac_op_bss_info_chang mutex_unlock(&ar->conf_mutex); } +static void ath12k_mac_op_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, -+ u32 changed) ++ u64 changed) +{ + struct ath12k_hw *ah = hw->priv; + struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); @@ -222,7 +216,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c static int ath12k_mac_vdev_delete(struct ath12k *ar, struct ieee80211_vif *vif) { struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); -@@ -4378,31 +4419,41 @@ static int ath12k_clear_peer_keys(struct +@@ -4441,31 +4482,41 @@ static int ath12k_clear_peer_keys(struct return first_errno; } @@ -276,7 +270,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c mutex_lock(&ar->conf_mutex); -@@ -4498,6 +4549,39 @@ static int ath12k_mac_op_set_key(struct +@@ -4561,6 +4612,39 @@ static int ath12k_mac_op_set_key(struct exit: mutex_unlock(&ar->conf_mutex); @@ -316,8 +310,8 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c return ret; } -@@ -5121,7 +5205,7 @@ static int ath12k_mac_station_add(struct - if (ab->hw_params.vdev_start_delay && +@@ -5185,7 +5269,7 @@ static int ath12k_mac_station_add(struct + if (ab->hw_params->vdev_start_delay && !arvif->is_started && arvif->vdev_type != WMI_VDEV_TYPE_AP) { - ret = ath12k_start_vdev_delay(ar->hw, vif); @@ -325,7 +319,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c if (ret) { ath12k_warn(ab, "failed to delay vdev start: %d\n", ret); goto free_tx_stats; -@@ -5150,12 +5234,21 @@ static int ath12k_mac_op_sta_state(struc +@@ -5214,12 +5298,21 @@ static int ath12k_mac_op_sta_state(struc enum ieee80211_sta_state old_state, enum ieee80211_sta_state new_state) { @@ -348,7 +342,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c /* cancel must be done outside the mutex to avoid deadlock */ if ((old_state == IEEE80211_STA_NONE && new_state == IEEE80211_STA_NOTEXIST)) { -@@ -5264,6 +5357,7 @@ static int ath12k_mac_op_sta_state(struc +@@ -5356,6 +5449,7 @@ static int ath12k_mac_op_sta_state(struc } mutex_unlock(&ar->conf_mutex); @@ -356,7 +350,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c return ret; } -@@ -5271,21 +5365,34 @@ static int ath12k_mac_op_sta_set_txpwr(s +@@ -5363,21 +5457,34 @@ static int ath12k_mac_op_sta_set_txpwr(s struct ieee80211_vif *vif, struct ieee80211_sta *sta) { @@ -375,10 +369,10 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c + goto out; + } + - if (sta->txpwr.type == NL80211_TX_POWER_AUTOMATIC) { + if (sta->deflink.txpwr.type == NL80211_TX_POWER_AUTOMATIC) { txpwr = 0; } else { - txpwr = sta->txpwr.power; + txpwr = sta->deflink.txpwr.power; - if (!txpwr) - return -EINVAL; + if (!txpwr) { @@ -396,7 +390,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c mutex_lock(&ar->conf_mutex); -@@ -5294,11 +5401,13 @@ static int ath12k_mac_op_sta_set_txpwr(s +@@ -5386,11 +5493,13 @@ static int ath12k_mac_op_sta_set_txpwr(s if (ret) { ath12k_warn(ar->ab, "failed to set tx power for station ret: %d\n", ret); @@ -412,7 +406,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c return ret; } -@@ -5320,17 +5429,27 @@ static void ath12k_mac_op_sta_rc_update( +@@ -5412,17 +5521,27 @@ static void ath12k_mac_op_sta_rc_update( struct ieee80211_sta *sta, u32 changed) { @@ -441,7 +435,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c ath12k_warn(ar->ab, "mac sta rc update failed to find peer %pM on vdev %i\n", sta->addr, arvif->vdev_id); return; -@@ -5405,6 +5524,7 @@ static void ath12k_mac_op_sta_rc_update( +@@ -5497,6 +5616,7 @@ static void ath12k_mac_op_sta_rc_update( arsta->changed |= changed; spin_unlock_bh(&ar->data_lock); @@ -449,12 +443,13 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c ieee80211_queue_work(hw, &arsta->update_wk); } -@@ -5466,16 +5586,18 @@ exit: +@@ -5558,17 +5678,18 @@ exit: return ret; } -static int ath12k_mac_op_conf_tx(struct ieee80211_hw *hw, -- struct ieee80211_vif *vif, u16 ac, +- struct ieee80211_vif *vif, +- unsigned int link_id, u16 ac, - const struct ieee80211_tx_queue_params *params) +static int ath12k_mac_conf_tx(struct ath12k *ar, + struct ieee80211_vif *vif, u16 ac, @@ -473,7 +468,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c switch (ac) { case IEEE80211_AC_VO: -@@ -5515,7 +5637,37 @@ static int ath12k_mac_op_conf_tx(struct +@@ -5608,7 +5729,38 @@ static int ath12k_mac_op_conf_tx(struct ath12k_warn(ar->ab, "failed to set sta uapsd: %d\n", ret); exit: @@ -481,7 +476,8 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c +} + +static int ath12k_mac_op_conf_tx(struct ieee80211_hw *hw, -+ struct ieee80211_vif *vif, u16 ac, ++ struct ieee80211_vif *vif, ++ unsigned int link_id, u16 ac, + const struct ieee80211_tx_queue_params *params) +{ + struct ath12k_hw *ah = hw->priv; @@ -511,7 +507,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c return ret; } -@@ -6868,10 +7020,9 @@ static int ath12k_mac_setup_vdev_create_ +@@ -6965,10 +7117,9 @@ static int ath12k_mac_setup_vdev_create_ return 0; } @@ -524,7 +520,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c struct ath12k_base *ab = ar->ab; struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); u32 param_id, param_value; -@@ -6916,6 +7067,31 @@ static void ath12k_mac_op_update_vif_off +@@ -7013,6 +7164,31 @@ static void ath12k_mac_op_update_vif_off } } @@ -556,7 +552,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c static int ath12k_mac_vdev_create(struct ath12k *ar, struct ieee80211_vif *vif) { struct ath12k_base *ab = ar->ab; -@@ -7002,7 +7178,7 @@ static int ath12k_mac_vdev_create(struct +@@ -7099,7 +7275,7 @@ static int ath12k_mac_vdev_create(struct list_add(&arvif->list, &ar->arvifs); spin_unlock_bh(&ar->data_lock); @@ -565,7 +561,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c nss = get_num_chains(ar->cfg_tx_chainmask) ? : 1; ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, -@@ -7141,6 +7317,39 @@ err: +@@ -7238,6 +7414,39 @@ err: return ret; } @@ -605,7 +601,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c static struct ath12k *ath12k_mac_assign_vif_to_vdev(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_chanctx_conf *ctx) -@@ -7186,9 +7395,10 @@ static struct ath12k *ath12k_mac_assign_ +@@ -7283,9 +7492,10 @@ static struct ath12k *ath12k_mac_assign_ goto unlock; } @@ -617,7 +613,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c unlock: mutex_unlock(&ar->conf_mutex); -@@ -7278,12 +7488,13 @@ static void ath12k_mac_op_remove_interfa +@@ -7375,12 +7585,13 @@ static void ath12k_mac_op_remove_interfa int ret; mutex_lock(&ah->conf_mutex); @@ -633,7 +629,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c ab = ar->ab; mutex_lock(&ar->conf_mutex); -@@ -7433,9 +7644,18 @@ static int ath12k_mac_op_ampdu_action(st +@@ -7530,9 +7741,18 @@ static int ath12k_mac_op_ampdu_action(st struct ieee80211_vif *vif, struct ieee80211_ampdu_params *params) { @@ -653,7 +649,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c mutex_lock(&ar->conf_mutex); switch (params->action) { -@@ -7458,6 +7678,7 @@ static int ath12k_mac_op_ampdu_action(st +@@ -7555,6 +7775,7 @@ static int ath12k_mac_op_ampdu_action(st } mutex_unlock(&ar->conf_mutex); @@ -661,7 +657,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c return ret; } -@@ -7981,10 +8202,9 @@ unlock: +@@ -8078,10 +8299,9 @@ unlock: mutex_unlock(&ar->conf_mutex); } @@ -673,7 +669,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c struct ath12k_base *ab = ar->ab; struct ath12k_vif *arvif = (void *)vif->drv_priv; int ret; -@@ -8685,13 +8905,12 @@ ath12k_mac_op_unassign_vif_chanctx(struc +@@ -8784,13 +9004,12 @@ ath12k_mac_op_unassign_vif_chanctx(struc * remove_interface() or when there is a change in channel * that moves the vif to a new ar */ @@ -689,7 +685,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c ab = ar->ab; mutex_lock(&ar->conf_mutex); -@@ -8709,16 +8928,11 @@ ath12k_mac_op_unassign_vif_chanctx(struc +@@ -8808,16 +9027,11 @@ ath12k_mac_op_unassign_vif_chanctx(struc if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { ret = ath12k_mac_monitor_stop(ar); @@ -709,7 +705,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c } ret = ath12k_mac_vdev_stop(arvif); -@@ -8737,6 +8951,7 @@ ath12k_mac_op_unassign_vif_chanctx(struc +@@ -8836,6 +9050,7 @@ ath12k_mac_op_unassign_vif_chanctx(struc test_bit(MONITOR_VDEV_CREATED, &ar->monitor_flags)) ath12k_mac_monitor_stop(ar); @@ -717,7 +713,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c mutex_unlock(&ar->conf_mutex); mutex_unlock(&ah->conf_mutex); } -@@ -9454,9 +9669,10 @@ ath12k_mac_op_set_bitrate_mask(struct ie +@@ -9553,9 +9768,10 @@ ath12k_mac_op_set_bitrate_mask(struct ie struct ieee80211_vif *vif, const struct cfg80211_bitrate_mask *mask) { @@ -729,7 +725,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c enum nl80211_band band; const u8 *ht_mcs_mask; const u16 *vht_mcs_mask; -@@ -9479,6 +9695,14 @@ ath12k_mac_op_set_bitrate_mask(struct ie +@@ -9578,6 +9794,14 @@ ath12k_mac_op_set_bitrate_mask(struct ie if (ath12k_mac_vif_chan(vif, &def)) return -EPERM; @@ -744,7 +740,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c band = def.chan->band; ht_mcs_mask = mask->control[band].ht_mcs; vht_mcs_mask = mask->control[band].vht_mcs; -@@ -9487,8 +9711,10 @@ ath12k_mac_op_set_bitrate_mask(struct ie +@@ -9586,8 +9810,10 @@ ath12k_mac_op_set_bitrate_mask(struct ie ldpc = !!(ar->ht_cap_info & WMI_HT_CAP_LDPC); sgi = mask->control[band].gi; @@ -757,7 +753,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c he_gi = mask->control[band].he_gi; he_ltf = mask->control[band].he_ltf; -@@ -9510,7 +9736,7 @@ ath12k_mac_op_set_bitrate_mask(struct ie +@@ -9609,7 +9835,7 @@ ath12k_mac_op_set_bitrate_mask(struct ie if (ret) { ath12k_warn(ar->ab, "failed to get single legacy rate for vdev %i: %d\n", arvif->vdev_id, ret); @@ -766,7 +762,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c } ieee80211_iterate_stations_atomic(ar->hw, ath12k_mac_disable_peer_fixed_rate, -@@ -9567,7 +9793,8 @@ ath12k_mac_op_set_bitrate_mask(struct ie +@@ -9666,7 +9892,8 @@ ath12k_mac_op_set_bitrate_mask(struct ie */ ath12k_warn(ar->ab, "Setting more than one MCS Value in bitrate mask not supported\n"); @@ -776,7 +772,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c } num_rates = ath12k_mac_bitrate_mask_num_he_rates(ar, band, -@@ -9579,7 +9806,8 @@ ath12k_mac_op_set_bitrate_mask(struct ie +@@ -9678,7 +9905,8 @@ ath12k_mac_op_set_bitrate_mask(struct ie num_rates > 1) { ath12k_warn(ar->ab, "Setting more than one HE MCS Value in bitrate mask not supported\n"); @@ -786,7 +782,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c } num_rates = ath12k_mac_bitrate_mask_num_eht_rates(ar, band, -@@ -9591,7 +9819,8 @@ ath12k_mac_op_set_bitrate_mask(struct ie +@@ -9690,7 +9918,8 @@ ath12k_mac_op_set_bitrate_mask(struct ie num_rates > 1) { ath12k_warn(ar->ab, "Setting more than one EHT MCS Value in bitrate mask not supported\n"); @@ -796,7 +792,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c } mutex_lock(&ar->conf_mutex); -@@ -9618,7 +9847,8 @@ ath12k_mac_op_set_bitrate_mask(struct ie +@@ -9717,7 +9946,8 @@ ath12k_mac_op_set_bitrate_mask(struct ie } mutex_unlock(&ar->conf_mutex); @@ -806,20 +802,16 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c return ret; } -Index: b/drivers/net/wireless/ath/ath12k/mac.h -=================================================================== ---- a/drivers/net/wireless/ath/ath12k/mac.h 2022-08-28 00:07:34.984773946 +0530 -+++ b/drivers/net/wireless/ath/ath12k/mac.h 2022-08-28 00:07:34.980773978 +0530 +--- a/drivers/net/wireless/ath/ath12k/mac.h ++++ b/drivers/net/wireless/ath/ath12k/mac.h @@ -165,4 +165,5 @@ void ath12k_mac_get_any_chandef_iter(str struct ieee80211_chanctx_conf *conf, void *data); void ath12k_mac_bcn_tx_event(struct ath12k_vif *arvif); +struct ath12k *ath12k_get_ar_by_vif(struct ieee80211_hw *hw, struct ieee80211_vif *vif); #endif -Index: b/drivers/net/wireless/ath/ath12k/testmode.c -=================================================================== ---- a/drivers/net/wireless/ath/ath12k/testmode.c 2022-08-28 00:07:34.984773946 +0530 -+++ b/drivers/net/wireless/ath/ath12k/testmode.c 2022-08-28 00:07:34.980773978 +0530 +--- a/drivers/net/wireless/ath/ath12k/testmode.c ++++ b/drivers/net/wireless/ath/ath12k/testmode.c @@ -219,10 +219,21 @@ out: int ath12k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void *data, int len) diff --git a/feeds/ipq95xx/mac80211/patches/qca/652-06-ath12k-Add-additional-checks-for-vif-and-sta-iterato.patch b/feeds/ipq95xx/mac80211/patches/qca/652-06-ath12k-Add-additional-checks-for-vif-and-sta-iterato.patch index 9ec9f32c8..d3ebf956f 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/652-06-ath12k-Add-additional-checks-for-vif-and-sta-iterato.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/652-06-ath12k-Add-additional-checks-for-vif-and-sta-iterato.patch @@ -58,8 +58,8 @@ Signed-off-by: Sriram R + struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); struct ath12k_mac_change_chanctx_arg *arg = data; -- if (rcu_access_pointer(vif->chanctx_conf) != arg->ctx) -+ if ((rcu_access_pointer(vif->chanctx_conf) != arg->ctx) || +- if (rcu_access_pointer(vif->bss_conf.chanctx_conf) != arg->ctx) ++ if ((rcu_access_pointer(vif->bss_conf.chanctx_conf) != arg->ctx) || + (arvif->ar != arg->ar)) return; @@ -72,7 +72,7 @@ Signed-off-by: Sriram R struct ath12k_mac_change_chanctx_arg *arg = data; struct ieee80211_chanctx_conf *ctx; - ctx = rcu_access_pointer(vif->chanctx_conf); + ctx = rcu_access_pointer(vif->bss_conf.chanctx_conf); - if (ctx != arg->ctx) + if ((ctx != arg->ctx) || + (arvif->ar != arg->ar)) diff --git a/feeds/ipq95xx/mac80211/patches/qca/652-07-ath12k-modify-regulatory-support-for-single-wiphy-ar.patch b/feeds/ipq95xx/mac80211/patches/qca/652-07-ath12k-modify-regulatory-support-for-single-wiphy-ar.patch index f88055d56..929d02fce 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/652-07-ath12k-modify-regulatory-support-for-single-wiphy-ar.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/652-07-ath12k-modify-regulatory-support-for-single-wiphy-ar.patch @@ -25,11 +25,9 @@ Signed-off-by: Sriram R drivers/net/wireless/ath/ath12k/reg.c | 109 +++++++++++++++++++++++---------- 3 files changed, 85 insertions(+), 34 deletions(-) -Index: b/drivers/net/wireless/ath/ath12k/core.h -=================================================================== ---- a/drivers/net/wireless/ath/ath12k/core.h 2022-08-01 18:27:08.929744331 +0530 -+++ b/drivers/net/wireless/ath/ath12k/core.h 2022-08-01 18:27:08.925744362 +0530 -@@ -872,6 +872,8 @@ struct ath12k_hw { +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -873,6 +873,8 @@ struct ath12k_hw { * concurrent debugfs configuration and concurrent FW statistics events. */ struct mutex conf_mutex; @@ -38,11 +36,9 @@ Index: b/drivers/net/wireless/ath/ath12k/core.h u8 num_radio; struct ath12k radio[0] __aligned(sizeof(void *)); }; -Index: b/drivers/net/wireless/ath/ath12k/mac.c -=================================================================== ---- a/drivers/net/wireless/ath/ath12k/mac.c 2022-08-01 18:27:08.929744331 +0530 -+++ b/drivers/net/wireless/ath/ath12k/mac.c 2022-08-01 18:27:08.925744362 +0530 -@@ -10165,6 +10165,7 @@ static int ath12k_mac_setup_channels_rat +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -10280,6 +10280,7 @@ static int ath12k_mac_setup_channels_rat u32 supported_bands) { struct ath12k_base *ab = ar->ab; @@ -50,17 +46,17 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c struct ieee80211_supported_band *band; struct ath12k_hal_reg_capabilities_ext *reg_cap, *temp_reg_cap; void *channels; -@@ -10205,6 +10206,8 @@ static int ath12k_mac_setup_channels_rat - ab->reg_freq_2g.start_freq), - min(temp_reg_cap->high_2ghz_chan, - ab->reg_freq_2g.end_freq)); +@@ -10318,6 +10319,8 @@ static int ath12k_mac_setup_channels_rat + ath12k_mac_update_ch_list(ar, band, + temp_reg_cap->low_2ghz_chan, + temp_reg_cap->high_2ghz_chan); + + ah->supported_band_mask |= BIT(NL80211_BAND_2GHZ); } if (supported_bands & WMI_HOST_WLAN_5G_CAP) { -@@ -10244,6 +10247,8 @@ static int ath12k_mac_setup_channels_rat - ab->reg_freq_5g.end_freq)); +@@ -10355,6 +10358,8 @@ static int ath12k_mac_setup_channels_rat + temp_reg_cap->high_5ghz_chan); ath12k_mac_update_5_9_ch_list(ar, band); + @@ -68,7 +64,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c } else if (reg_cap->low_5ghz_chan >= ATH12K_MIN_6G_FREQ && reg_cap->high_5ghz_chan <= ATH12K_MAX_6G_FREQ) { band = &ar->mac.sbands[NL80211_BAND_6GHZ]; -@@ -10293,6 +10298,8 @@ static int ath12k_mac_setup_channels_rat +@@ -10402,6 +10407,8 @@ static int ath12k_mac_setup_channels_rat * to prevent APIs from breaking */ band->n_channels = band->chan_6g[0]->n_channels; band->channels = band->chan_6g[0]->channels; @@ -77,7 +73,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c } } -@@ -10632,7 +10639,6 @@ int ath12k_mac_register(struct ath12k_ba +@@ -10759,7 +10766,6 @@ int ath12k_mac_register(struct ath12k_ba pdev = &ab->pdevs[i]; ar = pdev->ar; @@ -85,10 +81,8 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c ret = ath12k_regd_update(ar, true); if (ret) { ath12k_err(ar->ab, "ath12k regd update failed: %d\n", ret); -Index: b/drivers/net/wireless/ath/ath12k/reg.c -=================================================================== ---- a/drivers/net/wireless/ath/ath12k/reg.c 2022-08-01 18:27:08.929744331 +0530 -+++ b/drivers/net/wireless/ath/ath12k/reg.c 2022-08-01 18:29:46.460535198 +0530 +--- a/drivers/net/wireless/ath/ath12k/reg.c ++++ b/drivers/net/wireless/ath/ath12k/reg.c @@ -91,11 +91,11 @@ static struct cur_reg_rule return reg_rule; } diff --git a/feeds/ipq95xx/mac80211/patches/qca/652-08-ath12k-Add-provision-for-common-log.patch b/feeds/ipq95xx/mac80211/patches/qca/652-08-ath12k-Add-provision-for-common-log.patch index f5726f65c..d3cccbec1 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/652-08-ath12k-Add-provision-for-common-log.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/652-08-ath12k-Add-provision-for-common-log.patch @@ -53,10 +53,10 @@ Signed-off-by: Karthikeyan Periyasamy vaf.va = &args; - if (ath12k_debug_mask & mask) -- dev_printk(KERN_DEBUG, ab->dev, "%pV", &vaf); +- dev_dbg(ab->dev, "%pV", &vaf); + if (ath12k_debug_mask & mask) { + if (ab) -+ dev_printk(KERN_DEBUG, ab->dev, "%pV", &vaf); ++ dev_dbg(ab->dev, "%pV", &vaf); + else + pr_devel("ath12k: %pV", &vaf); + } @@ -65,18 +65,18 @@ Signed-off-by: Karthikeyan Periyasamy --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -3906,6 +3906,10 @@ static void ath12k_mac_op_bss_info_chang +@@ -3965,6 +3965,10 @@ static void ath12k_mac_op_bss_info_chang mutex_lock(&ah->conf_mutex); if (!arvif->is_created) { + ath12k_info(NULL, -+ "bss info parameter changes %x cached to apply after vdev create on channel assign\n", ++ "bss info parameter changes %llx cached to apply after vdev create on channel assign\n", + changed); + arvif->cache.bss_conf_changed |= changed; mutex_unlock(&ah->conf_mutex); return; -@@ -4170,6 +4174,7 @@ static int ath12k_mac_op_hw_scan(struct +@@ -4236,6 +4240,7 @@ static int ath12k_mac_op_hw_scan(struct */ ar = ath12k_mac_select_scan_device(hw, vif, hw_req); if (!ar) { @@ -84,7 +84,7 @@ Signed-off-by: Karthikeyan Periyasamy mutex_unlock(&ah->conf_mutex); return -EINVAL; } -@@ -4290,6 +4295,7 @@ static void ath12k_mac_op_cancel_hw_scan +@@ -4356,6 +4361,7 @@ static void ath12k_mac_op_cancel_hw_scan mutex_lock(&ah->conf_mutex); if (!arvif->is_created) { @@ -92,7 +92,7 @@ Signed-off-by: Karthikeyan Periyasamy mutex_unlock(&ah->conf_mutex); return; } -@@ -4572,6 +4578,7 @@ static int ath12k_mac_op_set_key(struct +@@ -4638,6 +4644,7 @@ static int ath12k_mac_op_set_key(struct arvif->cache.key_conf.key = key; arvif->cache.key_conf.changed = true; @@ -100,7 +100,7 @@ Signed-off-by: Karthikeyan Periyasamy mutex_unlock(&ah->conf_mutex); /* STA should be NULL before vdev create else need to warn */ -@@ -5247,6 +5254,7 @@ static int ath12k_mac_op_sta_state(struc +@@ -5314,6 +5321,7 @@ static int ath12k_mac_op_sta_state(struc ar = ath12k_get_ar_by_vif(hw, vif); if (!ar) { @@ -108,7 +108,7 @@ Signed-off-by: Karthikeyan Periyasamy mutex_unlock(&ah->conf_mutex); return -EINVAL; } -@@ -5377,6 +5385,7 @@ static int ath12k_mac_op_sta_set_txpwr(s +@@ -5472,6 +5480,7 @@ static int ath12k_mac_op_sta_set_txpwr(s ar = ath12k_get_ar_by_vif(hw, vif); if (!ar) { @@ -116,7 +116,7 @@ Signed-off-by: Karthikeyan Periyasamy ret = -EINVAL; goto out; } -@@ -5442,6 +5451,7 @@ static void ath12k_mac_op_sta_rc_update( +@@ -5537,6 +5546,7 @@ static void ath12k_mac_op_sta_rc_update( ar = ath12k_get_ar_by_vif(hw, vif); if (!ar) { @@ -124,15 +124,16 @@ Signed-off-by: Karthikeyan Periyasamy mutex_unlock(&ah->conf_mutex); return; } -@@ -5656,6 +5666,7 @@ static int ath12k_mac_op_conf_tx(struct +@@ -5752,6 +5762,8 @@ static int ath12k_mac_op_conf_tx(struct */ mutex_lock(&ah->conf_mutex); if (!arvif->is_created) { -+ ath12k_info(NULL, "tx queue params cached since vif is not assigned to radio\n"); ++ ath12k_dbg(NULL, ATH12K_DBG_MAC, ++ "tx queue params cached since vif is not assigned to radio\n"); arvif->cache.tx_conf.changed = true; arvif->cache.tx_conf.ac = ac; arvif->cache.tx_conf.tx_queue_params = *params; -@@ -7083,6 +7094,8 @@ static void ath12k_mac_op_update_vif_off +@@ -7181,6 +7193,8 @@ static void ath12k_mac_op_update_vif_off */ ar = ath12k_get_ar_by_vif(hw, vif); if (!ar) { @@ -141,7 +142,7 @@ Signed-off-by: Karthikeyan Periyasamy mutex_unlock(&ah->conf_mutex); return; } -@@ -7368,8 +7381,11 @@ static struct ath12k *ath12k_mac_assign_ +@@ -7473,8 +7487,11 @@ static struct ath12k *ath12k_mac_assign_ ar = ath12k_get_ar_by_ctx(hw, ctx); @@ -154,7 +155,7 @@ Signed-off-by: Karthikeyan Periyasamy ab = ar->ab; -@@ -7491,6 +7507,8 @@ static void ath12k_mac_op_remove_interfa +@@ -7596,6 +7613,8 @@ static void ath12k_mac_op_remove_interfa ar = ath12k_get_ar_by_vif(hw, vif); if (!ar) { @@ -163,7 +164,7 @@ Signed-off-by: Karthikeyan Periyasamy mutex_unlock(&ah->conf_mutex); return; } -@@ -7652,6 +7670,7 @@ static int ath12k_mac_op_ampdu_action(st +@@ -7753,6 +7772,7 @@ static int ath12k_mac_op_ampdu_action(st ar = ath12k_get_ar_by_vif(hw, vif); if (!ar) { @@ -171,7 +172,7 @@ Signed-off-by: Karthikeyan Periyasamy mutex_unlock(&ah->conf_mutex); return -EPERM; } -@@ -7690,8 +7709,11 @@ static int ath12k_mac_op_add_chanctx(str +@@ -7791,8 +7811,11 @@ static int ath12k_mac_op_add_chanctx(str ar = ath12k_get_ar_by_ctx(hw, ctx); @@ -184,7 +185,7 @@ Signed-off-by: Karthikeyan Periyasamy ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac chanctx add freq %u width %d ptr %pK\n", -@@ -7718,8 +7740,11 @@ static void ath12k_mac_op_remove_chanctx +@@ -7819,8 +7842,11 @@ static void ath12k_mac_op_remove_chanctx ar = ath12k_get_ar_by_ctx(hw, ctx); @@ -197,19 +198,15 @@ Signed-off-by: Karthikeyan Periyasamy ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac chanctx remove freq %u width %d ptr %pK\n", -@@ -8181,8 +8206,10 @@ static void ath12k_mac_op_change_chanctx - +@@ -8282,6 +8308,7 @@ static void ath12k_mac_op_change_chanctx ar = ath12k_get_ar_by_ctx(hw, ctx); -- if (!ar) -+ if (!ar) { + if (!ar) { + ath12k_err(NULL, "unable to determine device for the passed channel ctx\n"); + mutex_unlock(&ah->conf_mutex); return; -+ } - - ab = ar->ab; - -@@ -8772,6 +8799,8 @@ ath12k_mac_op_assign_vif_chanctx(struct + } +@@ -8882,6 +8909,8 @@ ath12k_mac_op_assign_vif_chanctx(struct } else { ar = ath12k_get_ar_by_ctx(hw, ctx); if (!ar) { @@ -218,7 +215,7 @@ Signed-off-by: Karthikeyan Periyasamy mutex_unlock(&ah->conf_mutex); return -EINVAL; } -@@ -8912,6 +8941,8 @@ ath12k_mac_op_unassign_vif_chanctx(struc +@@ -9027,6 +9056,8 @@ ath12k_mac_op_unassign_vif_chanctx(struc */ ar = ath12k_get_ar_by_vif(hw, vif); if (!ar) { @@ -227,7 +224,7 @@ Signed-off-by: Karthikeyan Periyasamy mutex_unlock(&ah->conf_mutex); WARN_ON(1); return; -@@ -8981,8 +9012,11 @@ ath12k_mac_op_switch_vif_chanctx(struct +@@ -9096,8 +9127,11 @@ ath12k_mac_op_switch_vif_chanctx(struct } ar = ath12k_get_ar_by_ctx(hw, vifs->old_ctx); @@ -240,7 +237,7 @@ Signed-off-by: Karthikeyan Periyasamy mutex_lock(&ar->conf_mutex); -@@ -9109,6 +9143,8 @@ static void ath12k_mac_op_flush(struct i +@@ -9224,6 +9258,8 @@ static void ath12k_mac_op_flush(struct i } else { ar = ath12k_get_ar_by_vif(hw, vif); if (!ar) { @@ -249,7 +246,7 @@ Signed-off-by: Karthikeyan Periyasamy goto out; } ath12k_mac_flush(ar); -@@ -9711,6 +9747,8 @@ ath12k_mac_op_set_bitrate_mask(struct ie +@@ -9826,6 +9862,8 @@ ath12k_mac_op_set_bitrate_mask(struct ie ar = ath12k_get_ar_by_vif(hw, vif); if (!ar) { diff --git a/feeds/ipq95xx/mac80211/patches/qca/652-09-ath12k-Add-support-for-multi-chip-wiphy.patch b/feeds/ipq95xx/mac80211/patches/qca/652-09-ath12k-Add-support-for-multi-chip-wiphy.patch index bfe6536ff..96d05f8d8 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/652-09-ath12k-Add-support-for-multi-chip-wiphy.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/652-09-ath12k-Add-support-for-multi-chip-wiphy.patch @@ -33,20 +33,13 @@ Signed-off-by: Sriram R --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c -@@ -31,6 +31,9 @@ module_param_named(frame_mode, ath12k_fr +@@ -31,6 +31,192 @@ module_param_named(frame_mode, ath12k_fr MODULE_PARM_DESC(frame_mode, "Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)"); +static DEFINE_MUTEX(ath12k_hw_lock); +static struct list_head ath12k_hw_groups = LIST_HEAD_INIT(ath12k_hw_groups); + - static const struct ath12k_hw_params ath12k_hw_params[] = { - { - .name = "qcn92xx hw1.0", -@@ -73,6 +76,179 @@ static const struct ath12k_hw_params ath - }, - }; - +/* This function needs to be used only when dt has multi chip grouping information */ +static struct ath12k_hw_group *ath12k_core_hw_group_find_by_id(u8 group_id) +{ @@ -76,26 +69,35 @@ Signed-off-by: Sriram R +static void __ath12k_core_put_hw_group(struct ath12k_base *ab) +{ + struct ath12k_hw_group *ag = ab->ag; -+ int i; -+ bool found = false; ++ u8 chip_id = ab->chip_id; + + if (!ag) + return; + + lockdep_assert_held(&ag->mutex_lock); + -+ for (i = 0; i < ag->num_chip; i++) { -+ if (ag->ab[i] == ab) { -+ found = true; -+ ag->ab[i] = NULL; -+ ab->ag = NULL; ++ if (chip_id >= ag->num_chip) { ++ ath12k_err(ab, "failed to put Invalid chip id %d in the group id %d max chip %d\n", ++ chip_id, ag->id, ag->num_chip); + -+ if (ag->num_probed) -+ ag->num_probed--; -+ } ++ return; + } + -+ if (found && !ag->num_probed) ++ if (ag->ab[chip_id] != ab) { ++ ath12k_err(ab, "failed to put chip id %d in the group id %d\n", ++ chip_id, ag->id); ++ ++ return; ++ } ++ ++ ag->ab[chip_id] = NULL; ++ ab->ag = NULL; ++ ab->chip_id = ATH12K_INVALID_CHIP_ID; ++ ++ if (ag->num_probed) ++ ag->num_probed--; ++ ++ if (!ag->num_probed) + ath12k_core_hw_group_free(ag); +} + @@ -199,6 +201,7 @@ Signed-off-by: Sriram R + goto again; + } + ++ ab->chip_id = ag->num_probed; + ag->ab[ag->num_probed++] = ab; + ab->ag = ag; + return ag; @@ -223,7 +226,7 @@ Signed-off-by: Sriram R int ath12k_core_suspend(struct ath12k_base *ab) { int ret; -@@ -455,6 +631,11 @@ success: +@@ -414,6 +600,11 @@ success: static void ath12k_core_stop(struct ath12k_base *ab) { @@ -235,7 +238,7 @@ Signed-off-by: Sriram R if (!test_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags)) ath12k_qmi_firmware_stop(ab); -@@ -475,22 +656,14 @@ static int ath12k_core_soc_create(struct +@@ -434,22 +625,14 @@ static int ath12k_core_soc_create(struct return ret; } @@ -259,7 +262,7 @@ Signed-off-by: Sriram R err_qmi_deinit: ath12k_qmi_deinit_service(ab); return ret; -@@ -498,39 +671,20 @@ err_qmi_deinit: +@@ -457,39 +640,20 @@ err_qmi_deinit: static void ath12k_core_soc_destroy(struct ath12k_base *ab) { @@ -301,7 +304,7 @@ Signed-off-by: Sriram R } ret = ath12k_spectral_init(ab); -@@ -543,11 +697,36 @@ static int ath12k_core_pdev_create(struc +@@ -502,11 +666,36 @@ static int ath12k_core_pdev_create(struc err_thermal_unregister: ath12k_thermal_unregister(ab); @@ -343,7 +346,7 @@ Signed-off-by: Sriram R ath12k_debugfs_pdev_destroy(ab); return ret; -@@ -555,10 +734,6 @@ err_pdev_debug: +@@ -514,10 +703,6 @@ err_pdev_debug: static void ath12k_core_pdev_destroy(struct ath12k_base *ab) { @@ -354,23 +357,23 @@ Signed-off-by: Sriram R ath12k_dp_pdev_free(ab); ath12k_debugfs_pdev_destroy(ab); } -@@ -568,6 +743,9 @@ static int ath12k_core_start(struct ath1 +@@ -527,6 +712,9 @@ static int ath12k_core_start(struct ath1 { int ret; + lockdep_assert_held(&ab->ag->mutex_lock); + lockdep_assert_held(&ab->core_lock); + - ret = ath12k_qmi_firmware_start(ab, mode); + ret = ath12k_wmi_attach(ab); if (ret) { ath12k_err(ab, "failed to attach wmi: %d\n", ret); -@@ -625,32 +803,23 @@ static int ath12k_core_start(struct ath1 +@@ -578,32 +766,23 @@ static int ath12k_core_start(struct ath1 ath12k_dp_cc_config(ab); - ath12k_dp_pdev_pre_alloc(ab); - - ret = ath12k_dp_pdev_reo_setup(ab); + ret = ath12k_dp_rx_pdev_reo_setup(ab); if (ret) { ath12k_err(ab, "failed to initialize reo destination rings: %d\n", ret); goto err_hif_stop; @@ -399,7 +402,7 @@ Signed-off-by: Sriram R } /* put hardware to DBS mode */ -@@ -658,7 +827,7 @@ static int ath12k_core_start(struct ath1 +@@ -611,7 +790,7 @@ static int ath12k_core_start(struct ath1 ret = ath12k_wmi_set_hw_mode(ab, WMI_HOST_HW_MODE_DBS); if (ret) { ath12k_err(ab, "failed to send dbs mode: %d\n", ret); @@ -408,7 +411,7 @@ Signed-off-by: Sriram R } } -@@ -666,13 +835,16 @@ static int ath12k_core_start(struct ath1 +@@ -619,13 +798,16 @@ static int ath12k_core_start(struct ath1 if (ret) { ath12k_err(ab, "failed to send htt version request message: %d\n", ret); @@ -426,15 +429,12 @@ Signed-off-by: Sriram R -err_mac_destroy: - ath12k_mac_destroy(ab); err_reo_cleanup: - ath12k_dp_pdev_reo_cleanup(ab); + ath12k_dp_rx_pdev_reo_cleanup(ab); err_hif_stop: -@@ -681,12 +853,116 @@ err_wmi_detach: - ath12k_wmi_detach(ab); - err_firmware_stop: - ath12k_qmi_firmware_stop(ab); -+ return ret; -+} -+ +@@ -635,6 +817,110 @@ err_wmi_detach: + return ret; + } + +static int ath12k_core_hw_group_start(struct ath12k_hw_group *ag) +{ + struct ath12k_base *ab = ag->ab[0]; @@ -482,7 +482,7 @@ Signed-off-by: Sriram R + /* Setup pdev features for all ab */ + for (i = 0; i < ag->num_chip; i++) { + ab = ag->ab[i]; - ++ + mutex_lock(&ab->core_lock); + + ret = ath12k_core_pdev_init(ab); @@ -536,16 +536,21 @@ Signed-off-by: Sriram R + } + + ath12k_mac_destroy(ag); - return ret; - } ++ return ret; ++} ++ + static int ath12k_core_start_firmware(struct ath12k_base *ab, + enum ath12k_firmware_mode mode) + { +@@ -654,6 +940,7 @@ static int ath12k_core_start_firmware(st int ath12k_core_qmi_firmware_ready(struct ath12k_base *ab) { + struct ath12k_hw_group *ag; int ret; - ret = ath12k_ce_init_pipes(ab); -@@ -718,36 +994,45 @@ int ath12k_core_qmi_firmware_ready(struc + ret = ath12k_core_start_firmware(ab, ATH12K_FIRMWARE_MODE_NORMAL); +@@ -691,36 +978,44 @@ int ath12k_core_qmi_firmware_ready(struc if (ath12k_frame_mode == ATH12K_HW_TXRX_RAW) set_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags); @@ -599,11 +604,10 @@ Signed-off-by: Sriram R ath12k_dp_free(ab); mutex_unlock(&ab->core_lock); + mutex_unlock(&ag->mutex_lock); -+ - return ret; - } + err_firmware_stop: + ath12k_qmi_firmware_stop(ab); -@@ -756,10 +1041,9 @@ static int ath12k_core_reconfigure_on_cr +@@ -732,10 +1027,9 @@ static int ath12k_core_reconfigure_on_cr int ret; mutex_lock(&ab->core_lock); @@ -614,8 +618,8 @@ Signed-off-by: Sriram R - ath12k_spectral_deinit(ab); ath12k_hif_stop(ab); ath12k_wmi_detach(ab); - ath12k_dp_pdev_reo_cleanup(ab); -@@ -812,102 +1096,109 @@ void ath12k_core_halt(struct ath12k *ar) + ath12k_dp_rx_pdev_reo_cleanup(ab); +@@ -788,102 +1082,109 @@ void ath12k_core_halt(struct ath12k *ar) static void ath12k_core_restart(struct work_struct *work) { struct ath12k_base *ab = container_of(work, struct ath12k_base, restart_work); @@ -633,9 +637,6 @@ Signed-off-by: Sriram R - ieee80211_stop_queues(ab->ah->hw); + ieee80211_stop_queues(ag->ah->hw); -+ -+ for (i = 0; i < ag->num_chip; i++) { -+ ab = ag->ab[i]; - for (i = 0; i < ab->num_radios; i++) { - pdev = &ab->pdevs[i]; @@ -646,6 +647,9 @@ Signed-off-by: Sriram R - list_for_each_entry(arvif, &ar->arvifs, list) { - if (arvif->is_started) { - ath12k_debugfs_remove_interface(arvif); ++ for (i = 0; i < ag->num_chip; i++) { ++ ab = ag->ab[i]; ++ + for (j = 0; j < ab->num_radios; j++) { + pdev = &ab->pdevs[j]; + ar = pdev->ar; @@ -800,7 +804,7 @@ Signed-off-by: Sriram R } static void ath12k_core_reset(struct work_struct *work) -@@ -987,31 +1278,163 @@ int ath12k_core_pre_init(struct ath12k_b +@@ -939,31 +1240,163 @@ int ath12k_core_pre_init(struct ath12k_b return 0; } @@ -975,16 +979,18 @@ Signed-off-by: Sriram R void ath12k_core_free(struct ath12k_base *ab) --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h -@@ -175,6 +175,8 @@ struct ath12k_he { +@@ -176,7 +176,9 @@ struct ath12k_he { }; #define MAX_RADIOS 3 +- +#define ATH12K_MAX_SOCS 3 +#define ATH12K_INVALID_GRP_ID 0xFF - ++#define ATH12K_INVALID_CHIP_ID 0xFF enum { WMI_HOST_TP_SCALE_MAX = 0, -@@ -204,6 +206,8 @@ enum ath12k_dev_flags { + WMI_HOST_TP_SCALE_50 = 1, +@@ -205,6 +207,8 @@ enum ath12k_dev_flags { ATH12K_FLAG_REGISTERED, ATH12K_FLAG_QMI_FAIL, ATH12K_FLAG_HTC_SUSPEND_COMPLETE, @@ -993,7 +999,7 @@ Signed-off-by: Sriram R }; enum ath12k_monitor_flags { -@@ -684,6 +688,8 @@ struct ath12k { +@@ -685,6 +689,8 @@ struct ath12k { /* pdev_idx starts from 0 whereas pdev->pdev_id starts with 1 */ u8 pdev_idx; u8 lmac_id; @@ -1002,7 +1008,7 @@ Signed-off-by: Sriram R struct completion peer_assoc_done; struct completion peer_delete_done; -@@ -878,12 +884,26 @@ struct ath12k_hw { +@@ -879,16 +885,31 @@ struct ath12k_hw { struct ath12k radio[0] __aligned(sizeof(void *)); }; @@ -1029,7 +1035,12 @@ Signed-off-by: Sriram R struct ath12k_qmi qmi; struct ath12k_wmi_base wmi_ab; struct completion fw_ready; -@@ -1144,6 +1164,8 @@ int ath12k_coredump_mhi_update_bhie_tabl + int num_radios; ++ u8 chip_id; + /* HW channel counters frequency value in hertz common to all MACs */ + u32 cc_freq_hz; + +@@ -1142,6 +1163,8 @@ int ath12k_coredump_mhi_update_bhie_tabl void __iomem *va, phys_addr_t pa, size_t size); @@ -1040,7 +1051,7 @@ Signed-off-by: Sriram R --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -6368,7 +6368,8 @@ static void ath12k_mac_setup_he_eht_cap( +@@ -6464,7 +6464,8 @@ static void ath12k_mac_setup_he_eht_cap( band->n_iftype_data = count; } @@ -1050,7 +1061,7 @@ Signed-off-by: Sriram R count = ath12k_mac_copy_he_eht_cap(ar, cap, ar->mac.iftype[NL80211_BAND_5GHZ], NL80211_BAND_5GHZ); -@@ -7019,7 +7020,8 @@ static int ath12k_mac_setup_vdev_create_ +@@ -7116,7 +7117,8 @@ static int ath12k_mac_setup_vdev_create_ params->chains[NL80211_BAND_2GHZ].tx = ar->num_tx_chains; params->chains[NL80211_BAND_2GHZ].rx = ar->num_rx_chains; } @@ -1060,7 +1071,7 @@ Signed-off-by: Sriram R params->chains[NL80211_BAND_5GHZ].tx = ar->num_tx_chains; params->chains[NL80211_BAND_5GHZ].rx = ar->num_rx_chains; } -@@ -9906,22 +9908,36 @@ static void +@@ -10007,22 +10009,36 @@ static void ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw, enum ieee80211_reconfig_type reconfig_type) { @@ -1106,7 +1117,7 @@ Signed-off-by: Sriram R } static void -@@ -10434,10 +10450,13 @@ static const struct wiphy_iftype_ext_cap +@@ -10548,10 +10564,13 @@ static const struct wiphy_iftype_ext_cap }, }; @@ -1121,7 +1132,7 @@ Signed-off-by: Sriram R idr_for_each(&ar->txmgmt_idr, ath12k_mac_tx_mgmt_pending_free, ar); idr_destroy(&ar->txmgmt_idr); -@@ -10446,26 +10465,39 @@ static void __ath12k_mac_unregister(stru +@@ -10560,26 +10579,39 @@ static void __ath12k_mac_unregister(stru kfree(ar->mac.sbands[NL80211_BAND_6GHZ].channels); } @@ -1173,7 +1184,7 @@ Signed-off-by: Sriram R } static int __ath12k_mac_register(struct ath12k *ar) -@@ -10497,12 +10529,6 @@ static int __ath12k_mac_register(struct +@@ -10611,12 +10643,6 @@ static int __ath12k_mac_register(struct if (cap->nss_ratio_enabled) ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW); @@ -1186,7 +1197,7 @@ Signed-off-by: Sriram R /* TODO: Check if HT capability advertised from firmware is different * for each band for a dual band capable radio. It will be tricky to * handle it when the ht capability different for each band. -@@ -10520,14 +10546,15 @@ static int __ath12k_mac_register(struct +@@ -10634,14 +10660,15 @@ static int __ath12k_mac_register(struct return 0; } @@ -1205,7 +1216,7 @@ Signed-off-by: Sriram R u32 antennas_rx, antennas_tx; bool unregister = false; static const u32 cipher_suites[] = { -@@ -10542,17 +10569,23 @@ int ath12k_mac_register(struct ath12k_ba +@@ -10656,17 +10683,23 @@ int ath12k_mac_register(struct ath12k_ba WLAN_CIPHER_SUITE_CCMP_256, }; @@ -1235,7 +1246,7 @@ Signed-off-by: Sriram R if (ab->pdevs_macaddr_valid) { ether_addr_copy(ar->mac_addr, pdev->mac_addr); } else { -@@ -10572,25 +10605,27 @@ int ath12k_mac_register(struct ath12k_ba +@@ -10686,25 +10719,28 @@ int ath12k_mac_register(struct ath12k_ba antennas_tx = max_t(u32, antennas_tx, cap->tx_chain_mask); hw->wiphy->max_ap_assoc_sta += ar->max_num_stations; @@ -1247,32 +1258,33 @@ Signed-off-by: Sriram R hw->wiphy->available_antennas_tx = antennas_tx; - ret = ath12k_mac_setup_iface_combinations(ab); -+ /* TODO Add link/ar specific iface combinations ++ /* TODO: Add link/ar specific iface combinations + * For now, setting up combination once for the group + */ + ret = ath12k_mac_setup_iface_combinations(ab_dflt); if (ret) { - ath12k_err(ab, "failed to setup interface combinations: %d\n", ret); -+ ath12k_err(NULL, "failed to setup interface combinations: %d\n", ret); ++ ath12k_err(NULL, "failed to setup interface combinations: %d\n", ++ ret); goto err_cleanup; } - /* Initialize channel counters frequency value in hertz */ - ab->cc_freq_hz = 320000; - ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS)) - 1; -- -- /* TODO: SET_IEEE80211_PERM_ADDR() */ -- SET_IEEE80211_DEV(hw, ab->dev); + SET_IEEE80211_PERM_ADDR(hw, ab_dflt->mac_addr); + SET_IEEE80211_DEV(hw, ab_dflt->dev); -- hw->wiphy->interface_modes = ab->hw_params.interface_modes; +- /* TODO: SET_IEEE80211_PERM_ADDR() */ +- SET_IEEE80211_DEV(hw, ab->dev); +- +- hw->wiphy->interface_modes = ab->hw_params->interface_modes; + /* Iface modes are expected to be similar for partner chips */ -+ hw->wiphy->interface_modes = ab_dflt->hw_params.interface_modes; ++ hw->wiphy->interface_modes = ab_dflt->hw_params->interface_modes; hw->wiphy->ru_punct_supp_bw = NL80211_RU_PUNCT_SUPP_BW_80; ieee80211_hw_set(hw, SIGNAL_DBM); -@@ -10608,6 +10643,12 @@ int ath12k_mac_register(struct ath12k_ba +@@ -10722,6 +10758,12 @@ int ath12k_mac_register(struct ath12k_ba ieee80211_hw_set(hw, QUEUE_CONTROL); ieee80211_hw_set(hw, SUPPORTS_TX_FRAG); ieee80211_hw_set(hw, REPORTS_LOW_ACK); @@ -1285,7 +1297,7 @@ Signed-off-by: Sriram R if (ath12k_frame_mode == ATH12K_HW_TXRX_ETHERNET) { ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD); ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD); -@@ -10632,6 +10673,7 @@ int ath12k_mac_register(struct ath12k_ba +@@ -10746,6 +10788,7 @@ int ath12k_mac_register(struct ath12k_ba hw->wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE | NL80211_FEATURE_AP_SCAN; @@ -1293,7 +1305,7 @@ Signed-off-by: Sriram R hw->queues = ATH12K_HW_MAX_QUEUES; hw->wiphy->tx_queue_len = ATH12K_QUEUE_LEN; hw->offchannel_tx_hw_queue = ATH12K_HW_MAX_QUEUES - 1; -@@ -10652,9 +10694,10 @@ int ath12k_mac_register(struct ath12k_ba +@@ -10770,9 +10813,10 @@ int ath12k_mac_register(struct ath12k_ba hw->wiphy->mbssid_max_interfaces = ab->num_radios * TARGET_NUM_VDEVS; hw->wiphy->ema_max_profile_periodicity = TARGET_EMA_MAX_PROFILE_PERIOD; @@ -1306,7 +1318,7 @@ Signed-off-by: Sriram R hw->netdev_features = NETIF_F_HW_CSUM; ieee80211_hw_set(hw, SW_CRYPTO_CONTROL); ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); -@@ -10662,11 +10705,11 @@ int ath12k_mac_register(struct ath12k_ba +@@ -10780,11 +10824,11 @@ int ath12k_mac_register(struct ath12k_ba ret = ieee80211_register_hw(hw); if (ret) { @@ -1315,12 +1327,12 @@ Signed-off-by: Sriram R goto err_full_cleanup; } -- if (!ab->hw_params.supports_monitor) -+ if (!ab_dflt->hw_params.supports_monitor) +- if (!ab->hw_params->supports_monitor) ++ if (!ab_dflt->hw_params->supports_monitor) /* There's a race between calling ieee80211_register_hw() * and here where the monitor mode is enabled for a little * while. But that time is so short and in practise it make -@@ -10674,10 +10717,10 @@ int ath12k_mac_register(struct ath12k_ba +@@ -10792,10 +10836,10 @@ int ath12k_mac_register(struct ath12k_ba */ hw->wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MONITOR); @@ -1334,7 +1346,7 @@ Signed-off-by: Sriram R ret = ath12k_regd_update(ar, true); if (ret) { ath12k_err(ar->ab, "ath12k regd update failed: %d\n", ret); -@@ -10689,76 +10732,70 @@ int ath12k_mac_register(struct ath12k_ba +@@ -10807,76 +10851,70 @@ int ath12k_mac_register(struct ath12k_ba ath12k_err(ar->ab, "debugfs registration failed: %d\n", ret); goto err_unregister_hw; } @@ -1431,30 +1443,31 @@ Signed-off-by: Sriram R + ar->hw = ah->hw; ar->pdev = pdev; ar->pdev_idx = i; - ar->lmac_id = ath12k_hw_get_mac_from_pdev_id(&ab->hw_params, i); + ar->lmac_id = ath12k_hw_get_mac_from_pdev_id(ab->hw_params, i); + ar->link_idx = *link_id; ar->wmi = &ab->wmi_ab.wmi[i]; /* FIXME wmi[0] is already initialized during attach, -@@ -10794,26 +10831,91 @@ int ath12k_mac_allocate(struct ath12k_ba +@@ -10912,26 +10950,91 @@ int ath12k_mac_allocate(struct ath12k_ba clear_bit(MONITOR_VDEV_STARTED, &ar->monitor_flags); ar->monitor_vdev_id = -1; clear_bit(MONITOR_VDEV_CREATED, &ar->monitor_flags); + + *link_id = *link_id + 1; -+ } -+ + } + + /* Initialize channel counters frequency value in hertz */ + ab->cc_freq_hz = 320000; + ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS)) - 1; + + ath12k_dp_pdev_pre_alloc(ab); + -+ return 0; -+} -+ + return 0; + } + +-void ath12k_mac_destroy(struct ath12k_base *ab) +int ath12k_mac_allocate(struct ath12k_hw_group *ag) -+{ + { + struct ieee80211_hw *hw; + struct ath12k_hw *ah; + size_t len; @@ -1490,18 +1503,17 @@ Signed-off-by: Sriram R + i, ag->id); + goto err_mac_destroy; + } - } - - return 0; ++ } ++ ++ return 0; + +err_mac_destroy: + ath12k_mac_destroy(ag); + return ret; - } - --void ath12k_mac_destroy(struct ath12k_base *ab) ++} ++ +void ath12k_mac_destroy(struct ath12k_hw_group *ag) - { ++{ + struct ath12k_base *ab; + struct ath12k_hw *ah = ag->ah; struct ath12k *ar; @@ -1691,7 +1703,7 @@ Signed-off-by: Sriram R } --- a/drivers/net/wireless/ath/ath12k/pci.c +++ b/drivers/net/wireless/ath/ath12k/pci.c -@@ -1377,6 +1377,7 @@ static int ath12k_pci_probe(struct pci_d +@@ -1326,6 +1326,7 @@ static int ath12k_pci_probe(struct pci_d ath12k_err(ab, "failed to init core: %d\n", ret); goto err_free_irq; } @@ -1699,7 +1711,7 @@ Signed-off-by: Sriram R return 0; err_free_irq: -@@ -1412,10 +1413,11 @@ static void ath12k_pci_remove(struct pci +@@ -1361,10 +1362,11 @@ static void ath12k_pci_remove(struct pci ath12k_pci_power_down(ab); ath12k_debugfs_soc_destroy(ab); ath12k_qmi_deinit_service(ab); @@ -1714,7 +1726,7 @@ Signed-off-by: Sriram R ath12k_core_deinit(ab); --- a/drivers/net/wireless/ath/ath12k/qmi.c +++ b/drivers/net/wireless/ath/ath12k/qmi.c -@@ -4299,7 +4299,8 @@ static void ath12k_qmi_driver_event_work +@@ -4576,7 +4576,8 @@ static void ath12k_qmi_driver_event_work break; case ATH12K_QMI_EVENT_FW_READY: clear_bit(ATH12K_FLAG_QMI_FAIL, &ab->dev_flags); @@ -1724,7 +1736,7 @@ Signed-off-by: Sriram R ath12k_hal_dump_srng_stats(ab); queue_work(ab->workqueue, &ab->restart_work); break; -@@ -4312,8 +4313,15 @@ static void ath12k_qmi_driver_event_work +@@ -4589,8 +4590,15 @@ static void ath12k_qmi_driver_event_work clear_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags); clear_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags); @@ -1744,7 +1756,7 @@ Signed-off-by: Sriram R break; --- a/drivers/net/wireless/ath/ath12k/mhi.c +++ b/drivers/net/wireless/ath/ath12k/mhi.c -@@ -235,7 +235,7 @@ static void ath12k_mhi_op_status_cb(stru +@@ -328,7 +328,7 @@ static void ath12k_mhi_op_status_cb(stru ath12k_warn(ab, "firmware crashed: MHI_CB_SYS_ERROR\n"); break; case MHI_CB_EE_RDDM: diff --git a/feeds/ipq95xx/mac80211/patches/qca/652-10-ath12k-Enable-mac-based-registration-for-default-gro.patch b/feeds/ipq95xx/mac80211/patches/qca/652-10-ath12k-Enable-mac-based-registration-for-default-gro.patch index 4d2d4fe98..905fb8a7a 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/652-10-ath12k-Enable-mac-based-registration-for-default-gro.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/652-10-ath12k-Enable-mac-based-registration-for-default-gro.patch @@ -17,7 +17,7 @@ Signed-off-by: Karthikeyan Periyasamy --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c -@@ -1101,13 +1101,20 @@ static void ath12k_core_restart(struct w +@@ -1088,13 +1088,20 @@ static void ath12k_core_restart(struct w struct ath12k *ar; struct ath12k_pdev *pdev; struct ath12k_vif *arvif; @@ -39,7 +39,7 @@ Signed-off-by: Karthikeyan Periyasamy for (i = 0; i < ag->num_chip; i++) { ab = ag->ab[i]; -@@ -1196,9 +1203,15 @@ static void ath12k_core_restart(struct w +@@ -1183,9 +1190,15 @@ static void ath12k_core_restart(struct w complete(&ab->driver_recovery); } @@ -60,21 +60,19 @@ Signed-off-by: Karthikeyan Periyasamy static void ath12k_core_reset(struct work_struct *work) --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h -@@ -174,9 +174,10 @@ struct ath12k_he { +@@ -175,8 +175,9 @@ struct ath12k_he { u32 heop_param; }; -#define MAX_RADIOS 3 -#define ATH12K_MAX_SOCS 3 --#define ATH12K_INVALID_GRP_ID 0xFF -+#define MAX_RADIOS 3 -+#define ATH12K_MAX_SOCS 3 -+#define ATH12K_GROUP_MAX_RADIO (ATH12K_MAX_SOCS * MAX_RADIOS) -+#define ATH12K_INVALID_GRP_ID 0xFF - ++#define MAX_RADIOS 3 ++#define ATH12K_MAX_SOCS 3 ++#define ATH12K_GROUP_MAX_RADIO (ATH12K_MAX_SOCS * MAX_RADIOS) + #define ATH12K_INVALID_GRP_ID 0xFF + #define ATH12K_INVALID_CHIP_ID 0xFF enum { - WMI_HOST_TP_SCALE_MAX = 0, -@@ -623,7 +624,7 @@ enum ath12k_fw_recovery_option { +@@ -624,7 +625,7 @@ enum ath12k_fw_recovery_option { struct ath12k { struct ath12k_base *ab; @@ -83,7 +81,7 @@ Signed-off-by: Karthikeyan Periyasamy struct ath12k_pdev *pdev; struct ath12k_pdev_wmi *wmi; struct ath12k_pdev_dp dp; -@@ -886,13 +887,15 @@ struct ath12k_hw { +@@ -887,13 +888,15 @@ struct ath12k_hw { /* Holds info on the group of SOCs that are registered as a single wiphy */ struct ath12k_hw_group { @@ -101,7 +99,7 @@ Signed-off-by: Karthikeyan Periyasamy struct ath12k_base *ab[ATH12K_MAX_SOCS]; struct mutex mutex_lock; }; -@@ -902,7 +905,6 @@ struct ath12k_base { +@@ -903,7 +906,6 @@ struct ath12k_base { enum ath12k_hw_rev hw_rev; struct platform_device *pdev; struct device *dev; @@ -129,25 +127,25 @@ Signed-off-by: Karthikeyan Periyasamy ath12k_mac_get_any_chandef_iter, &chandef); if (!chandef) -@@ -1374,7 +1374,7 @@ static int ath12k_mac_setup_bcn_tmpl_ema +@@ -1375,7 +1375,7 @@ static int ath12k_mac_setup_bcn_tmpl_ema return -1; tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv; - beacons = ieee80211_beacon_get_template_ema_list(tx_arvif->ar->hw, + beacons = ieee80211_beacon_get_template_ema_list(tx_arvif->ar->ah->hw, - tx_arvif->vif); + tx_arvif->vif, 0); if (!beacons || !beacons->cnt) { ath12k_warn(arvif->ar->ab, -@@ -1422,7 +1422,7 @@ static int ath12k_mac_setup_bcn_tmpl_non +@@ -1423,7 +1423,7 @@ static int ath12k_mac_setup_bcn_tmpl_non if (arvif->vif->mbssid_tx_vif) tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv; - bcn = ieee80211_beacon_get_template(tx_arvif->ar->hw, tx_arvif->vif, + bcn = ieee80211_beacon_get_template(tx_arvif->ar->ah->hw, tx_arvif->vif, - &offs); + &offs, 0); if (!bcn) { ath12k_warn(arvif->ar->ab, -@@ -1567,7 +1567,7 @@ static void ath12k_peer_assoc_h_basic(st +@@ -1569,7 +1569,7 @@ static void ath12k_peer_assoc_h_basic(st arg->peer_associd = aid; arg->auth_flag = true; /* TODO: STA WAR in ath10k for listen interval required? */ @@ -156,7 +154,7 @@ Signed-off-by: Karthikeyan Periyasamy arg->peer_nss = 1; arg->peer_caps = vif->bss_conf.assoc_capability; } -@@ -1583,13 +1583,15 @@ static void ath12k_peer_assoc_h_crypto(s +@@ -1585,13 +1585,15 @@ static void ath12k_peer_assoc_h_crypto(s struct ath12k_vif *arvif = (struct ath12k_vif *)vif->drv_priv; const u8 *rsnie = NULL; const u8 *wpaie = NULL; @@ -173,7 +171,7 @@ Signed-off-by: Karthikeyan Periyasamy IEEE80211_BSS_TYPE_ANY, IEEE80211_PRIVACY_ANY); if (arvif->rsnie_present || arvif->wpaie_present) { -@@ -1609,7 +1611,7 @@ static void ath12k_peer_assoc_h_crypto(s +@@ -1611,7 +1613,7 @@ static void ath12k_peer_assoc_h_crypto(s ies->data, ies->len); rcu_read_unlock(); @@ -182,16 +180,16 @@ Signed-off-by: Karthikeyan Periyasamy } /* FIXME: base on RSN IE/WPA IE is a correct idea? */ -@@ -1654,7 +1656,7 @@ static void ath12k_peer_assoc_h_rates(st +@@ -1656,7 +1658,7 @@ static void ath12k_peer_assoc_h_rates(st return; band = def.chan->band; - sband = ar->hw->wiphy->bands[band]; + sband = ar->ah->hw->wiphy->bands[band]; - ratemask = sta->supp_rates[band]; + ratemask = sta->deflink.supp_rates[band]; ratemask &= arvif->bitrate_mask.control[band].legacy; rates = sband->bitrates; -@@ -3314,7 +3316,7 @@ static void ath12k_recalculate_mgmt_rate +@@ -3354,7 +3356,7 @@ static void ath12k_recalculate_mgmt_rate lockdep_assert_held(&ar->conf_mutex); @@ -200,7 +198,7 @@ Signed-off-by: Karthikeyan Periyasamy basic_rate_idx = ffs(vif->bss_conf.basic_rates) - 1; bitrate = sband->bitrates[basic_rate_idx].bitrate; -@@ -3342,6 +3344,7 @@ static int ath12k_mac_fils_discovery(str +@@ -3382,6 +3384,7 @@ static int ath12k_mac_fils_discovery(str { struct ath12k *ar = arvif->ar; struct sk_buff *tmpl; @@ -208,7 +206,7 @@ Signed-off-by: Karthikeyan Periyasamy int ret; u32 interval; bool unsol_bcast_probe_resp_enabled = false; -@@ -3349,7 +3352,7 @@ static int ath12k_mac_fils_discovery(str +@@ -3389,7 +3392,7 @@ static int ath12k_mac_fils_discovery(str if (info->fils_discovery.max_interval) { interval = info->fils_discovery.max_interval; @@ -217,7 +215,7 @@ Signed-off-by: Karthikeyan Periyasamy if (tmpl) ret = ath12k_wmi_fils_discovery_tmpl(ar, arvif->vdev_id, tmpl); -@@ -3357,7 +3360,7 @@ static int ath12k_mac_fils_discovery(str +@@ -3397,7 +3400,7 @@ static int ath12k_mac_fils_discovery(str unsol_bcast_probe_resp_enabled = 1; interval = info->unsol_bcast_probe_resp_interval; @@ -226,7 +224,7 @@ Signed-off-by: Karthikeyan Periyasamy arvif->vif); if (tmpl) ret = ath12k_wmi_probe_resp_tmpl(ar, arvif->vdev_id, -@@ -3994,6 +3997,8 @@ ath12k_mac_select_scan_device(struct iee +@@ -4057,6 +4060,8 @@ ath12k_mac_select_scan_device(struct iee void __ath12k_mac_scan_finish(struct ath12k *ar) { @@ -235,7 +233,7 @@ Signed-off-by: Karthikeyan Periyasamy lockdep_assert_held(&ar->data_lock); switch (ar->scan.state) { -@@ -4007,9 +4012,9 @@ void __ath12k_mac_scan_finish(struct ath +@@ -4070,9 +4075,9 @@ void __ath12k_mac_scan_finish(struct ath ATH12K_SCAN_ABORTING), }; @@ -247,7 +245,7 @@ Signed-off-by: Karthikeyan Periyasamy } fallthrough; case ATH12K_SCAN_STARTING: -@@ -4274,7 +4279,7 @@ static int ath12k_mac_op_hw_scan(struct +@@ -4337,7 +4342,7 @@ static int ath12k_mac_op_hw_scan(struct } /* Add a 200ms margin to account for event/command processing */ @@ -256,7 +254,7 @@ Signed-off-by: Karthikeyan Periyasamy msecs_to_jiffies(arg.max_scan_time + ATH12K_MAC_SCAN_TIMEOUT_MSECS)); -@@ -4440,7 +4445,7 @@ static int ath12k_mac_set_key(struct ath +@@ -4503,7 +4508,7 @@ static int ath12k_mac_set_key(struct ath int ret = 0; u32 flags = 0; @@ -265,7 +263,7 @@ Signed-off-by: Karthikeyan Periyasamy ab = ar->ab; -@@ -6440,7 +6445,7 @@ static void ath12k_mgmt_over_wmi_tx_drop +@@ -6536,7 +6541,7 @@ static void ath12k_mgmt_over_wmi_tx_drop { int num_mgmt; @@ -274,7 +272,7 @@ Signed-off-by: Karthikeyan Periyasamy num_mgmt = atomic_dec_if_positive(&ar->num_pending_mgmt_tx); -@@ -6640,6 +6645,7 @@ static void ath12k_mac_op_tx(struct ieee +@@ -6736,6 +6741,7 @@ static void ath12k_mac_op_tx(struct ieee struct ieee80211_vif *vif = info->control.vif; struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); struct ath12k *ar = arvif->ar; @@ -282,7 +280,7 @@ Signed-off-by: Karthikeyan Periyasamy struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_key_conf *key = info->control.hw_key; struct ath12k_sta *arsta = NULL; -@@ -6663,7 +6669,7 @@ static void ath12k_mac_op_tx(struct ieee +@@ -6759,7 +6765,7 @@ static void ath12k_mac_op_tx(struct ieee if (ret) { ath12k_warn(ar->ab, "failed to queue management frame %d\n", ret); @@ -291,7 +289,7 @@ Signed-off-by: Karthikeyan Periyasamy } return; } -@@ -6678,7 +6684,7 @@ static void ath12k_mac_op_tx(struct ieee +@@ -6774,7 +6780,7 @@ static void ath12k_mac_op_tx(struct ieee else ath12k_warn(ar->ab, "failed to transmit frame %d\n", ret); @@ -300,7 +298,7 @@ Signed-off-by: Karthikeyan Periyasamy } } -@@ -6976,7 +6982,7 @@ static int ath12k_mac_setup_vdev_params_ +@@ -7073,7 +7079,7 @@ static int ath12k_mac_setup_vdev_params_ tx_arvif = (void *)tx_vif->drv_priv; if (arvif->vif->bss_conf.nontransmitted) { @@ -309,7 +307,7 @@ Signed-off-by: Karthikeyan Periyasamy return -EINVAL; *flags = WMI_HOST_VDEV_FLAGS_NON_TRANSMIT_AP; -@@ -7111,7 +7117,7 @@ static int ath12k_mac_vdev_create(struct +@@ -7210,7 +7216,7 @@ static int ath12k_mac_vdev_create(struct { struct ath12k_base *ab = ar->ab; struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); @@ -318,7 +316,7 @@ Signed-off-by: Karthikeyan Periyasamy struct vdev_create_params vdev_param = {0}; struct peer_create_params peer_param; u32 param_id, param_value; -@@ -7334,7 +7340,7 @@ err: +@@ -7433,7 +7439,7 @@ err: static void ath12k_mac_vif_cache_flush(struct ath12k *ar, struct ieee80211_vif *vif) { @@ -327,7 +325,7 @@ Signed-off-by: Karthikeyan Periyasamy struct ath12k_vif *arvif = (void *)vif->drv_priv; int ret; -@@ -7997,7 +8003,7 @@ static int ath12k_mac_num_chanctxs(struc +@@ -8096,7 +8102,7 @@ static int ath12k_mac_num_chanctxs(struc { int num = 0; @@ -336,7 +334,7 @@ Signed-off-by: Karthikeyan Periyasamy ath12k_mac_num_chanctxs_iter, &num); -@@ -8032,7 +8038,7 @@ static void ath12k_mac_update_rx_channel +@@ -8131,7 +8137,7 @@ static void ath12k_mac_update_rx_channel */ rcu_read_lock(); if (!ctx && ath12k_mac_num_chanctxs(ar) == 1) { @@ -345,7 +343,7 @@ Signed-off-by: Karthikeyan Periyasamy ath12k_mac_get_any_chandef_iter, &def); if (vifs) -@@ -8175,10 +8181,11 @@ ath12k_mac_update_active_vif_chan(struct +@@ -8274,10 +8280,11 @@ ath12k_mac_update_active_vif_chan(struct struct ieee80211_chanctx_conf *ctx) { struct ath12k_mac_change_chanctx_arg arg = { .ctx = ctx, .ar = ar }; @@ -358,7 +356,7 @@ Signed-off-by: Karthikeyan Periyasamy IEEE80211_IFACE_ITER_NORMAL, ath12k_mac_change_chanctx_cnt_iter, &arg); -@@ -8189,7 +8196,7 @@ ath12k_mac_update_active_vif_chan(struct +@@ -8288,7 +8295,7 @@ ath12k_mac_update_active_vif_chan(struct if (!arg.vifs) return; @@ -367,7 +365,7 @@ Signed-off-by: Karthikeyan Periyasamy IEEE80211_IFACE_ITER_NORMAL, ath12k_mac_change_chanctx_fill_iter, &arg); -@@ -8417,7 +8424,7 @@ static void ath12k_mac_get_psd_channel(s +@@ -8516,7 +8523,7 @@ static void ath12k_mac_get_psd_channel(s */ *center_freq = *start_freq + i * step_freq; /* -1 to reg_6g_power_mode to make it 0 based indexing */ @@ -376,7 +374,7 @@ Signed-off-by: Karthikeyan Periyasamy reg_6g_power_mode - 1); *tx_power = (*temp_chan)->max_reg_power; } -@@ -8450,7 +8457,7 @@ static void ath12k_mac_get_eirp_power(st +@@ -8549,7 +8556,7 @@ static void ath12k_mac_get_eirp_power(st *center_freq += 10; /* -1 to reg_6g_power_mode to make it 0 based indexing */ @@ -385,7 +383,7 @@ Signed-off-by: Karthikeyan Periyasamy reg_6g_power_mode - 1); *tx_power = (*temp_chan)->max_reg_power; } -@@ -9101,7 +9108,7 @@ static void ath12k_mac_flush(struct ath1 +@@ -9202,7 +9209,7 @@ static void ath12k_mac_flush(struct ath1 struct ath12k_base *ab = ar->ab; long time_left; @@ -394,7 +392,7 @@ Signed-off-by: Karthikeyan Periyasamy time_left = wait_event_timeout(ar->dp.tx_empty_waitq, (atomic_read(&ar->dp.num_tx_pending) == 0), -@@ -9633,7 +9640,7 @@ static void ath12k_mac_set_bitrate_mask_ +@@ -9734,7 +9741,7 @@ static void ath12k_mac_set_bitrate_mask_ arsta->changed |= IEEE80211_RC_SUPP_RATES_CHANGED; spin_unlock_bh(&ar->data_lock); @@ -403,7 +401,7 @@ Signed-off-by: Karthikeyan Periyasamy } static void ath12k_mac_disable_peer_fixed_rate(void *data, -@@ -9790,7 +9797,7 @@ ath12k_mac_op_set_bitrate_mask(struct ie +@@ -9891,7 +9898,7 @@ ath12k_mac_op_set_bitrate_mask(struct ie arvif->vdev_id, ret); goto out; } @@ -412,7 +410,7 @@ Signed-off-by: Karthikeyan Periyasamy ath12k_mac_disable_peer_fixed_rate, arvif); } else if (ath12k_mac_bitrate_mask_get_single_nss(ar, band, mask, -@@ -9799,7 +9806,7 @@ ath12k_mac_op_set_bitrate_mask(struct ie +@@ -9900,7 +9907,7 @@ ath12k_mac_op_set_bitrate_mask(struct ie nss = single_nss; mutex_lock(&ar->conf_mutex); arvif->bitrate_mask = *mask; @@ -421,7 +419,7 @@ Signed-off-by: Karthikeyan Periyasamy ath12k_mac_set_bitrate_mask_iter, arvif); mutex_unlock(&ar->conf_mutex); -@@ -9876,12 +9883,12 @@ ath12k_mac_op_set_bitrate_mask(struct ie +@@ -9977,12 +9984,12 @@ ath12k_mac_op_set_bitrate_mask(struct ie } mutex_lock(&ar->conf_mutex); @@ -436,7 +434,7 @@ Signed-off-by: Karthikeyan Periyasamy ath12k_mac_set_bitrate_mask_iter, arvif); -@@ -10219,7 +10226,7 @@ static int ath12k_mac_setup_channels_rat +@@ -10320,7 +10327,7 @@ static int ath12k_mac_setup_channels_rat u32 supported_bands) { struct ath12k_base *ab = ar->ab; @@ -445,25 +443,25 @@ Signed-off-by: Karthikeyan Periyasamy struct ieee80211_supported_band *band; struct ath12k_hal_reg_capabilities_ext *reg_cap, *temp_reg_cap; void *channels; -@@ -10249,7 +10256,7 @@ static int ath12k_mac_setup_channels_rat +@@ -10350,7 +10357,7 @@ static int ath12k_mac_setup_channels_rat band->channels = channels; band->n_bitrates = ath12k_g_rates_size; band->bitrates = ath12k_g_rates; - ar->hw->wiphy->bands[NL80211_BAND_2GHZ] = band; + ah->hw->wiphy->bands[NL80211_BAND_2GHZ] = band; - if (ab->hw_params.single_pdev_only) { + if (ab->hw_params->single_pdev_only) { phy_id = ath12k_get_phy_id(ar, WMI_HOST_WLAN_2G_CAP); -@@ -10288,7 +10295,7 @@ static int ath12k_mac_setup_channels_rat +@@ -10389,7 +10396,7 @@ static int ath12k_mac_setup_channels_rat band->channels = channels; band->n_bitrates = ath12k_a_rates_size; band->bitrates = ath12k_a_rates; - ar->hw->wiphy->bands[NL80211_BAND_5GHZ] = band; + ah->hw->wiphy->bands[NL80211_BAND_5GHZ] = band; - if (ar->ab->hw_params.single_pdev_only) { + if (ar->ab->hw_params->single_pdev_only) { phy_id = ath12k_get_phy_id(ar, WMI_HOST_WLAN_5G_CAP); -@@ -10336,7 +10343,7 @@ static int ath12k_mac_setup_channels_rat +@@ -10437,7 +10444,7 @@ static int ath12k_mac_setup_channels_rat ar->supports_6ghz = true; band->n_bitrates = ath12k_a_rates_size; band->bitrates = ath12k_a_rates; @@ -471,8 +469,8 @@ Signed-off-by: Karthikeyan Periyasamy + ah->hw->wiphy->bands[NL80211_BAND_6GHZ] = band; ath12k_mac_update_ch_list(ar, band, - max(temp_reg_cap->low_5ghz_chan, -@@ -10360,13 +10367,18 @@ static int ath12k_mac_setup_channels_rat + max(temp_reg_cap->low_5ghz_chan, +@@ -10461,18 +10468,23 @@ static int ath12k_mac_setup_channels_rat return 0; } @@ -485,24 +483,22 @@ Signed-off-by: Karthikeyan Periyasamy struct ieee80211_iface_limit *limits; + struct ath12k_base *ab_dflt; + struct ath12k *ar; - int n_limits; + int n_limits, max_interfaces; + bool ap, mesh; +- ap = ab->hw_params->interface_modes & BIT(NL80211_IFTYPE_AP); + ar = ah->radio; + ab_dflt = ar->ab; + ++ ap = ab_dflt->hw_params->interface_modes & BIT(NL80211_IFTYPE_AP); + + mesh = IS_ENABLED(CPTCFG_MAC80211_MESH) && +- ab->hw_params->interface_modes & BIT(NL80211_IFTYPE_MESH_POINT); ++ ab_dflt->hw_params->interface_modes & BIT(NL80211_IFTYPE_MESH_POINT); + combinations = kzalloc(sizeof(*combinations), GFP_KERNEL); if (!combinations) - return -ENOMEM; -@@ -10386,7 +10398,7 @@ static int ath12k_mac_setup_iface_combin - limits[1].types |= BIT(NL80211_IFTYPE_AP); - - if (IS_ENABLED(CPTCFG_MAC80211_MESH) && -- ab->hw_params.interface_modes & BIT(NL80211_IFTYPE_MESH_POINT)) -+ ab_dflt->hw_params.interface_modes & BIT(NL80211_IFTYPE_MESH_POINT)) - limits[1].types |= BIT(NL80211_IFTYPE_MESH_POINT); - - combinations[0].limits = limits; -@@ -10471,15 +10483,11 @@ static void __ath12k_mac_unregister(stru +@@ -10585,15 +10597,11 @@ static void __ath12k_mac_unregister(stru __ath12k_mac_post_unregister(ar); } @@ -519,7 +515,7 @@ Signed-off-by: Karthikeyan Periyasamy ar = ah->radio; for (i = 0; i < ah->num_radio; i++) { __ath12k_mac_pre_unregister(ar); -@@ -10500,6 +10508,20 @@ void ath12k_mac_unregister(struct ath12k +@@ -10614,6 +10622,20 @@ void ath12k_mac_unregister(struct ath12k SET_IEEE80211_DEV(ah->hw, NULL); } @@ -540,7 +536,7 @@ Signed-off-by: Karthikeyan Periyasamy static int __ath12k_mac_register(struct ath12k *ar) { struct ieee80211_hw *hw; -@@ -10507,7 +10529,7 @@ static int __ath12k_mac_register(struct +@@ -10621,7 +10643,7 @@ static int __ath12k_mac_register(struct int ret; u32 ht_cap = 0; @@ -549,7 +545,7 @@ Signed-off-by: Karthikeyan Periyasamy init_waitqueue_head(&ar->txmgmt_empty_waitq); idr_init(&ar->txmgmt_idr); spin_lock_init(&ar->txmgmt_idr_lock); -@@ -10546,11 +10568,10 @@ static int __ath12k_mac_register(struct +@@ -10660,11 +10682,10 @@ static int __ath12k_mac_register(struct return 0; } @@ -562,7 +558,7 @@ Signed-off-by: Karthikeyan Periyasamy struct ath12k_base *ab, *ab_dflt; struct ath12k *ar; struct ath12k_pdev *pdev; -@@ -10569,12 +10590,6 @@ int ath12k_mac_register(struct ath12k_hw +@@ -10683,12 +10704,6 @@ int ath12k_mac_register(struct ath12k_hw WLAN_CIPHER_SUITE_CCMP_256, }; @@ -575,7 +571,7 @@ Signed-off-by: Karthikeyan Periyasamy hw = ah->hw; hw->wiphy->max_ap_assoc_sta = 0; antennas_rx = 0; -@@ -10583,6 +10598,11 @@ int ath12k_mac_register(struct ath12k_hw +@@ -10697,6 +10712,11 @@ int ath12k_mac_register(struct ath12k_hw ar = ah->radio; ab = ar->ab; @@ -587,28 +583,28 @@ Signed-off-by: Karthikeyan Periyasamy for (i = 0; i < ah->num_radio; i++) { ab = ar->ab; pdev = ar->pdev; -@@ -10613,9 +10633,9 @@ int ath12k_mac_register(struct ath12k_hw +@@ -10727,9 +10747,9 @@ int ath12k_mac_register(struct ath12k_hw hw->wiphy->available_antennas_tx = antennas_tx; - /* TODO Add link/ar specific iface combinations + /* TODO: Add link/ar specific iface combinations - * For now, setting up combination once for the group + * For now, setting up combination once for the wiphy (ah) */ - ret = ath12k_mac_setup_iface_combinations(ab_dflt); + ret = ath12k_mac_setup_iface_combinations(ah); if (ret) { - ath12k_err(NULL, "failed to setup interface combinations: %d\n", ret); - goto err_cleanup; -@@ -10654,7 +10674,7 @@ int ath12k_mac_register(struct ath12k_hw + ath12k_err(NULL, "failed to setup interface combinations: %d\n", + ret); +@@ -10769,7 +10789,7 @@ int ath12k_mac_register(struct ath12k_hw ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD); } -- if (ab->hw_params.supports_ap_ps) -+ if (ab_dflt->hw_params.supports_ap_ps) +- if (ab->hw_params->supports_ap_ps) ++ if (ab_dflt->hw_params->supports_ap_ps) ieee80211_hw_set(hw, SUPPORTS_AP_PS); hw->wiphy->features |= NL80211_FEATURE_STATIC_SMPS; -@@ -10691,7 +10711,7 @@ int ath12k_mac_register(struct ath12k_hw +@@ -10810,7 +10830,7 @@ int ath12k_mac_register(struct ath12k_hw hw->wiphy->iftype_ext_capab = ath12k_iftypes_ext_capa; hw->wiphy->num_iftype_ext_capab = ARRAY_SIZE(ath12k_iftypes_ext_capa); @@ -617,7 +613,7 @@ Signed-off-by: Karthikeyan Periyasamy hw->wiphy->ema_max_profile_periodicity = TARGET_EMA_MAX_PROFILE_PERIOD; ah->hw->wiphy->regulatory_flags = REGULATORY_WIPHY_SELF_MANAGED; -@@ -10764,6 +10784,35 @@ err_cleanup: +@@ -10883,6 +10903,35 @@ err_cleanup: return ret; } @@ -653,7 +649,7 @@ Signed-off-by: Karthikeyan Periyasamy static inline struct ath12k *ath12k_mac_get_ar(struct ath12k_hw *ah, u8 link_idx) { -@@ -10775,71 +10824,59 @@ static inline struct ath12k *ath12k_mac_ +@@ -10894,71 +10943,58 @@ static inline struct ath12k *ath12k_mac_ return ar + link_idx; } @@ -665,36 +661,20 @@ Signed-off-by: Karthikeyan Periyasamy struct ath12k *ar; struct ath12k_pdev *pdev; - int i; - +- - ab->ah = ah; -+ pdev = &ab->pdevs[mac_id]; -+ ar = ath12k_mac_get_ar(ah, link_id); -+ if (!ar) -+ return -EINVAL; - +- - for (i = 0; i < ab->num_radios; i++) { - pdev = &ab->pdevs[i]; - ar = ath12k_mac_get_ar(ah, *link_id); - if (!ar) - return -EINVAL; -+ ar->ab = ab; -+ ar->ah = ah; -+ ar->pdev = pdev; -+ ar->pdev_idx = mac_id; -+ ar->lmac_id = ath12k_hw_get_mac_from_pdev_id(&ab->hw_params, mac_id); -+ ar->link_idx = link_id; -+ -+ ar->wmi = &ab->wmi_ab.wmi[mac_id]; -+ /* FIXME wmi[0] is already initialized during attach, -+ * Should we do this again? -+ */ -+ ath12k_wmi_pdev_attach(ab, mac_id); - ar->ab = ab; - ar->hw = ah->hw; - ar->pdev = pdev; - ar->pdev_idx = i; -- ar->lmac_id = ath12k_hw_get_mac_from_pdev_id(&ab->hw_params, i); +- ar->lmac_id = ath12k_hw_get_mac_from_pdev_id(ab->hw_params, i); - ar->link_idx = *link_id; - - ar->wmi = &ab->wmi_ab.wmi[i]; @@ -702,6 +682,10 @@ Signed-off-by: Karthikeyan Periyasamy - * Should we do this again? - */ - ath12k_wmi_pdev_attach(ab, i); ++ pdev = &ab->pdevs[mac_id]; ++ ar = ath12k_mac_get_ar(ah, link_id); ++ if (!ar) ++ return -EINVAL; - ar->cfg_tx_chainmask = pdev->cap.tx_chain_mask; - ar->cfg_rx_chainmask = pdev->cap.rx_chain_mask; @@ -731,6 +715,21 @@ Signed-off-by: Karthikeyan Periyasamy - clear_bit(MONITOR_VDEV_STARTED, &ar->monitor_flags); - ar->monitor_vdev_id = -1; - clear_bit(MONITOR_VDEV_CREATED, &ar->monitor_flags); ++ ar->ab = ab; ++ ar->ah = ah; ++ ar->pdev = pdev; ++ ar->pdev_idx = mac_id; ++ ar->lmac_id = ath12k_hw_get_mac_from_pdev_id(ab->hw_params, mac_id); ++ ar->link_idx = link_id; ++ ++ ar->wmi = &ab->wmi_ab.wmi[mac_id]; ++ /* FIXME wmi[0] is already initialized during attach, ++ * Should we do this again? ++ */ ++ ath12k_wmi_pdev_attach(ab, mac_id); + +- *link_id = *link_id + 1; +- } + ar->cfg_tx_chainmask = pdev->cap.tx_chain_mask; + ar->cfg_rx_chainmask = pdev->cap.rx_chain_mask; + ar->num_tx_chains = get_num_chains(pdev->cap.tx_chain_mask); @@ -751,15 +750,12 @@ Signed-off-by: Karthikeyan Periyasamy + init_completion(&ar->scan.completed); + init_completion(&ar->thermal.wmi_sync); -- *link_id = *link_id + 1; -- } -+ INIT_DELAYED_WORK(&ar->scan.timeout, ath12k_scan_timeout_work); -+ INIT_WORK(&ar->regd_update_work, ath12k_regd_update_work); - - /* Initialize channel counters frequency value in hertz */ - ab->cc_freq_hz = 320000; - ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS)) - 1; -- ++ INIT_DELAYED_WORK(&ar->scan.timeout, ath12k_scan_timeout_work); ++ INIT_WORK(&ar->regd_update_work, ath12k_regd_update_work); + - ath12k_dp_pdev_pre_alloc(ab); + INIT_WORK(&ar->wmi_mgmt_tx_work, ath12k_mgmt_over_wmi_tx_work); + skb_queue_head_init(&ar->wmi_mgmt_tx_queue); @@ -769,7 +765,7 @@ Signed-off-by: Karthikeyan Periyasamy return 0; } -@@ -10847,40 +10884,98 @@ static int ath12k_mac_chip_setup(struct +@@ -10966,40 +11002,98 @@ static int ath12k_mac_chip_setup(struct int ath12k_mac_allocate(struct ath12k_hw_group *ag) { struct ieee80211_hw *hw; @@ -892,7 +888,7 @@ Signed-off-by: Karthikeyan Periyasamy } return 0; -@@ -10896,6 +10991,7 @@ void ath12k_mac_destroy(struct ath12k_hw +@@ -11015,6 +11109,7 @@ void ath12k_mac_destroy(struct ath12k_hw struct ath12k_hw *ah = ag->ah; struct ath12k *ar; struct ath12k_pdev *pdev; @@ -900,7 +896,7 @@ Signed-off-by: Karthikeyan Periyasamy int i, j; if (!ah) -@@ -10916,6 +11012,14 @@ void ath12k_mac_destroy(struct ath12k_hw +@@ -11035,6 +11130,14 @@ void ath12k_mac_destroy(struct ath12k_hw } } @@ -919,7 +915,7 @@ Signed-off-by: Karthikeyan Periyasamy } --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -5705,7 +5705,7 @@ static int wmi_process_mgmt_tx_comp(stru +@@ -5738,7 +5738,7 @@ static int wmi_process_mgmt_tx_comp(stru if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) && !status) info->flags |= IEEE80211_TX_STAT_ACK; @@ -928,7 +924,7 @@ Signed-off-by: Karthikeyan Periyasamy num_mgmt = atomic_dec_if_positive(&ar->num_pending_mgmt_tx); -@@ -5848,7 +5848,7 @@ static void ath12k_wmi_event_scan_foreig +@@ -5881,7 +5881,7 @@ static void ath12k_wmi_event_scan_foreig break; case ATH12K_SCAN_RUNNING: case ATH12K_SCAN_ABORTING: @@ -937,7 +933,7 @@ Signed-off-by: Karthikeyan Periyasamy freq); break; } -@@ -5988,10 +5988,11 @@ static int ath12k_pull_roam_ev(struct at +@@ -6021,10 +6021,11 @@ static int ath12k_pull_roam_ev(struct at static int freq_to_idx(struct ath12k *ar, int freq) { struct ieee80211_supported_band *sband; @@ -950,7 +946,7 @@ Signed-off-by: Karthikeyan Periyasamy if (!sband) continue; -@@ -6799,7 +6800,7 @@ static int ath12k_reg_handle_chan_list(s +@@ -6832,7 +6833,7 @@ static int ath12k_reg_handle_chan_list(s kfree(ab->new_regd[pdev_idx]); ab->new_regd[pdev_idx] = regd; @@ -959,7 +955,7 @@ Signed-off-by: Karthikeyan Periyasamy } else { /* Multiple events for the same *ar is not expected. But we * can still clear any previously stored default_regd if we -@@ -7193,7 +7194,7 @@ static void ath12k_mgmt_rx_event(struct +@@ -7226,7 +7227,7 @@ static void ath12k_mgmt_rx_event(struct status->freq, status->band, status->signal, status->rate_idx); @@ -968,7 +964,7 @@ Signed-off-by: Karthikeyan Periyasamy exit: rcu_read_unlock(); -@@ -7353,7 +7354,7 @@ static void ath12k_peer_sta_kickout_even +@@ -7386,7 +7387,7 @@ static void ath12k_peer_sta_kickout_even goto exit; } @@ -977,7 +973,7 @@ Signed-off-by: Karthikeyan Periyasamy arg.mac_addr, NULL); if (!sta) { ath12k_warn(ab, "Spurious quick kickout for STA %pM\n", -@@ -7833,7 +7834,7 @@ ath12k_wmi_pdev_dfs_radar_detected_event +@@ -7866,7 +7867,7 @@ ath12k_wmi_pdev_dfs_radar_detected_event if (ar->dfs_block_radar_events) ath12k_info(ab, "DFS Radar detected, but ignored as requested\n"); else @@ -986,7 +982,7 @@ Signed-off-by: Karthikeyan Periyasamy exit: kfree(tb); -@@ -7965,6 +7966,7 @@ ath12k_wmi_dcs_awgn_interference_event(s +@@ -7998,6 +7999,7 @@ ath12k_wmi_dcs_awgn_interference_event(s struct cfg80211_chan_def *chandef = NULL; struct ath12k *ar; const struct wmi_tlv *tlv; @@ -994,7 +990,7 @@ Signed-off-by: Karthikeyan Periyasamy u16 tlv_tag; u8 *ptr; int ret; -@@ -8034,10 +8036,12 @@ ath12k_wmi_dcs_awgn_interference_event(s +@@ -8067,10 +8069,12 @@ ath12k_wmi_dcs_awgn_interference_event(s goto exit; } @@ -1008,7 +1004,7 @@ Signed-off-by: Karthikeyan Periyasamy &chandef); if (!chandef) { ath12k_warn(ab, "chandef is not available\n"); -@@ -8045,7 +8049,7 @@ ath12k_wmi_dcs_awgn_interference_event(s +@@ -8078,7 +8082,7 @@ ath12k_wmi_dcs_awgn_interference_event(s } ar->awgn_chandef = *chandef; @@ -1017,7 +1013,7 @@ Signed-off-by: Karthikeyan Periyasamy spin_lock_bh(&ar->data_lock); ar->awgn_intf_handling_in_prog = true; -@@ -8293,7 +8297,7 @@ ath12k_wmi_pdev_update_muedca_params_sta +@@ -8328,7 +8332,7 @@ ath12k_wmi_pdev_update_muedca_params_sta ev->ecwmin[WMI_AC_VO]); params->ac_vo.mu_edca_timer = ev->muedca_expiration_time[WMI_AC_VO]; @@ -1026,7 +1022,7 @@ Signed-off-by: Karthikeyan Periyasamy kfree(params); -@@ -8822,14 +8826,14 @@ static void ath12k_wmi_pdev_detach(struc +@@ -8859,14 +8863,14 @@ static void ath12k_wmi_pdev_detach(struc } int ath12k_wmi_pdev_attach(struct ath12k_base *ab, @@ -1035,8 +1031,8 @@ Signed-off-by: Karthikeyan Periyasamy { struct ath12k_pdev_wmi *wmi_handle; -- if (pdev_id >= ab->hw_params.max_radios) -+ if (pdev_idx >= ab->hw_params.max_radios) +- if (pdev_id >= ab->hw_params->max_radios) ++ if (pdev_idx >= ab->hw_params->max_radios) return -EINVAL; - wmi_handle = &ab->wmi_ab.wmi[pdev_id]; @@ -1152,7 +1148,7 @@ Signed-off-by: Karthikeyan Periyasamy } --- a/drivers/net/wireless/ath/ath12k/debugfs.c +++ b/drivers/net/wireless/ath/ath12k/debugfs.c -@@ -1591,6 +1591,7 @@ static const struct file_operations fops +@@ -1362,6 +1362,7 @@ static const struct file_operations fops int ath12k_debugfs_register(struct ath12k *ar) { struct ath12k_base *ab = ar->ab; @@ -1160,7 +1156,7 @@ Signed-off-by: Karthikeyan Periyasamy char pdev_name[5]; char buf[100] = {0}; -@@ -1602,7 +1603,7 @@ int ath12k_debugfs_register(struct ath12 +@@ -1373,7 +1374,7 @@ int ath12k_debugfs_register(struct ath12 /* Create a symlink under ieee80211/phy* */ snprintf(buf, 100, "../../ath12k/%pd2", ar->debug.debugfs_pdev); @@ -1169,7 +1165,7 @@ Signed-off-by: Karthikeyan Periyasamy ath12k_debugfs_htt_stats_init(ar); -@@ -1618,7 +1619,7 @@ int ath12k_debugfs_register(struct ath12 +@@ -1389,7 +1390,7 @@ int ath12k_debugfs_register(struct ath12 ar->debug.debugfs_pdev, ar, &fops_pktlog_filter); @@ -1178,7 +1174,7 @@ Signed-off-by: Karthikeyan Periyasamy debugfs_create_file("dfs_simulate_radar", 0200, ar->debug.debugfs_pdev, ar, &fops_simulate_radar); -@@ -1627,7 +1628,7 @@ int ath12k_debugfs_register(struct ath12 +@@ -1398,7 +1399,7 @@ int ath12k_debugfs_register(struct ath12 &ar->dfs_block_radar_events); } @@ -1189,7 +1185,7 @@ Signed-off-by: Karthikeyan Periyasamy &fops_simulate_awgn); --- a/drivers/net/wireless/ath/ath12k/dp_mon.c +++ b/drivers/net/wireless/ath/ath12k/dp_mon.c -@@ -1799,7 +1799,7 @@ ath12k_dp_mon_fill_rx_stats(struct ath12 +@@ -1798,7 +1798,7 @@ ath12k_dp_mon_fill_rx_stats(struct ath12 } if (unlikely(rx_status->band == NUM_NL80211_BANDS || @@ -1209,7 +1205,7 @@ Signed-off-by: Karthikeyan Periyasamy static int ath12k_dp_mon_rx_deliver(struct ath12k *ar, u32 mpdu_idx, --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -2621,7 +2621,7 @@ void ath12k_dp_rx_h_ppdu(struct ath12k * +@@ -2641,7 +2641,7 @@ void ath12k_dp_rx_h_ppdu(struct ath12k * rx_status->band = NL80211_BAND_5GHZ; } @@ -1218,7 +1214,7 @@ Signed-off-by: Karthikeyan Periyasamy ath12k_err(ar->ab, "sband is NULL for status band %d channel_num %d center_freq %d pdev_id %d\n", rx_status->band, channel_num, center_freq, ar->pdev_idx); -@@ -2725,7 +2725,7 @@ static void ath12k_dp_rx_deliver_msdu(st +@@ -2745,7 +2745,7 @@ static void ath12k_dp_rx_deliver_msdu(st !(is_mcbc && rx_status->flag & RX_FLAG_DECRYPTED)) rx_status->flag |= RX_FLAG_8023; @@ -1227,7 +1223,7 @@ Signed-off-by: Karthikeyan Periyasamy } static int ath12k_dp_rx_process_msdu(struct ath12k *ar, -@@ -3106,7 +3106,7 @@ mic_fail: +@@ -3128,7 +3128,7 @@ mic_fail: ath12k_dp_rx_h_ppdu(ar, rx_desc, rxs); ath12k_dp_rx_h_undecap(ar, msdu, rx_desc, HAL_ENCRYPT_TYPE_TKIP_MIC, rxs, true); @@ -1238,7 +1234,7 @@ Signed-off-by: Karthikeyan Periyasamy --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -414,7 +414,7 @@ ath12k_dp_tx_htt_tx_complete_buf(struct +@@ -418,7 +418,7 @@ ath12k_dp_tx_htt_tx_complete_buf(struct } } @@ -1247,8 +1243,8 @@ Signed-off-by: Karthikeyan Periyasamy } static void -@@ -678,7 +678,7 @@ static void ath12k_dp_tx_complete_msdu(s - status.rate = &rate; +@@ -684,7 +684,7 @@ static void ath12k_dp_tx_complete_msdu(s + status.rates = &rate; spin_unlock_bh(&ab->base_lock); - ieee80211_tx_status_ext(ar->hw, &status); diff --git a/feeds/ipq95xx/mac80211/patches/qca/652-ath12k-fix-fixrate-issue.patch b/feeds/ipq95xx/mac80211/patches/qca/652-ath12k-fix-fixrate-issue.patch index ef0e24a12..a0ca3f38a 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/652-ath12k-fix-fixrate-issue.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/652-ath12k-fix-fixrate-issue.patch @@ -80,7 +80,7 @@ index 93782ec..8fa34b0 100644 + } + + /* Avoid updating invalid nss as fixed rate*/ -+ if (nss > sta->rx_nss) ++ if (nss > sta->deflink.rx_nss) + return -EINVAL; + + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, @@ -126,7 +126,7 @@ index 93782ec..8fa34b0 100644 band); if (ret) return ret; -+ } else if (sta->ht_cap.ht_supported && num_ht_rates == 1) { ++ } else if (sta->deflink.ht_cap.ht_supported && num_ht_rates == 1) { + ret = ath12k_mac_set_peer_ht_fixed_rate(arvif, sta, mask, + band); + if (ret) @@ -153,10 +153,10 @@ index 93782ec..8fa34b0 100644 mask); num_he_rates = ath12k_mac_bitrate_mask_num_he_rates(ar, band, @@ -4810,6 +4883,9 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk) - } else if (sta->eht_cap.has_eht && num_eht_rates == 1) { + } else if (sta->deflink.eht_cap.has_eht && num_eht_rates == 1) { ath12k_mac_set_peer_eht_fixed_rate(arvif, sta, mask, band); -+ } else if (sta->ht_cap.ht_supported && num_ht_rates == 1) { ++ } else if (sta->deflink.ht_cap.ht_supported && num_ht_rates == 1) { + ath12k_mac_set_peer_ht_fixed_rate(arvif, sta, mask, + band); } else { diff --git a/feeds/ipq95xx/mac80211/patches/qca/653-001-ath12k-allocate-dst-ring-descriptors-from-cacheable-.patch b/feeds/ipq95xx/mac80211/patches/qca/653-001-ath12k-allocate-dst-ring-descriptors-from-cacheable-.patch index c12e876a9..bcfd1e953 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/653-001-ath12k-allocate-dst-ring-descriptors-from-cacheable-.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/653-001-ath12k-allocate-dst-ring-descriptors-from-cacheable-.patch @@ -22,22 +22,8 @@ Signed-off-by: Balamurugan Selvarajan drivers/net/wireless/ath/ath12k/hw.h | 1 + 7 files changed, 134 insertions(+), 8 deletions(-) -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/core.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.c -@@ -73,6 +73,7 @@ static const struct ath12k_hw_params ath - .supports_ap_ps = true, - .credit_flow = false, - .wakeup_mhi = false, -+ .alloc_cacheable_memory =true, - }, - }; - -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/dp.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp.c +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c @@ -104,8 +104,11 @@ void ath12k_dp_srng_cleanup(struct ath12 if (!ring->vaddr_unaligned) return; @@ -52,7 +38,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp. ring->vaddr_unaligned = NULL; } -@@ -231,6 +234,7 @@ int ath12k_dp_srng_setup(struct ath12k_b +@@ -223,6 +226,7 @@ int ath12k_dp_srng_setup(struct ath12k_b int entry_sz = ath12k_hal_srng_get_entrysize(ab, type); int max_entries = ath12k_hal_srng_get_max_entries(ab, type); int ret; @@ -60,14 +46,14 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp. if (max_entries < 0 || entry_sz < 0) return -EINVAL; -@@ -239,9 +243,26 @@ int ath12k_dp_srng_setup(struct ath12k_b +@@ -231,9 +235,26 @@ int ath12k_dp_srng_setup(struct ath12k_b num_entries = max_entries; ring->size = (num_entries * entry_sz) + HAL_RING_BASE_ALIGN - 1; - ring->vaddr_unaligned = dma_alloc_coherent(ab->dev, ring->size, - &ring->paddr_unaligned, - GFP_KERNEL); -+ if (ab->hw_params.alloc_cacheable_memory) { ++ if (ab->hw_params->alloc_cacheable_memory) { + /* Allocate the reo dst and tx completion rings from cacheable memory */ + switch (type) { + case HAL_REO_DST: @@ -90,7 +76,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp. if (!ring->vaddr_unaligned) return -ENOMEM; -@@ -306,6 +327,11 @@ int ath12k_dp_srng_setup(struct ath12k_b +@@ -299,6 +320,11 @@ int ath12k_dp_srng_setup(struct ath12k_b return -EINVAL; } @@ -102,11 +88,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp. ret = ath12k_hal_srng_setup(ab, type, ring_num, mac_id, ¶ms); if (ret < 0) { ath12k_warn(ab, "failed to setup srng: %d ring_id %d\n", -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/dp.h -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp.h -@@ -66,6 +66,7 @@ struct dp_srng { +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -29,6 +29,7 @@ struct dp_srng { dma_addr_t paddr; int size; u32 ring_id; @@ -114,41 +98,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp. }; struct dp_rxdma_ring { -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_tx.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/dp_tx.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -723,14 +723,24 @@ void ath12k_dp_tx_completion_handler(str - struct dp_tx_ring *tx_ring = &dp->tx_ring[ring_id]; - u32 *desc; - u8 mac_id; -+ int valid_entries; - - spin_lock_bh(&status_ring->lock); - - ath12k_hal_srng_access_begin(ab, status_ring); - -+ valid_entries = ath12k_hal_srng_dst_num_free(ab, status_ring, false); -+ if (!valid_entries) { -+ ath12k_hal_srng_access_end(ab, status_ring); -+ spin_unlock_bh(&status_ring->lock); -+ return; -+ } -+ -+ ath12k_hal_srng_dst_invalidate_entry(ab, status_ring, valid_entries); -+ - while ((ATH12K_TX_COMPL_NEXT(tx_ring->tx_status_head) != - tx_ring->tx_status_tail) && -- (desc = ath12k_hal_srng_dst_get_next_entry(ab, status_ring))) { -+ (desc = ath12k_hal_srng_dst_get_next_cache_entry(ab, status_ring))) { - memcpy(&tx_ring->tx_status[tx_ring->tx_status_head], - desc, sizeof(struct hal_wbm_release_ring)); - tx_ring->tx_status_head = -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/hal.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/hal.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/hal.c -@@ -925,6 +925,21 @@ u32 *ath12k_hal_srng_dst_peek(struct ath +--- a/drivers/net/wireless/ath/ath12k/hal.c ++++ b/drivers/net/wireless/ath/ath12k/hal.c +@@ -1558,6 +1558,21 @@ u32 *ath12k_hal_srng_dst_peek(struct ath return NULL; } @@ -170,7 +122,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/hal u32 *ath12k_hal_srng_dst_get_next_entry(struct ath12k_base *ab, struct hal_srng *srng) { -@@ -938,11 +953,74 @@ u32 *ath12k_hal_srng_dst_get_next_entry( +@@ -1571,11 +1586,74 @@ u32 *ath12k_hal_srng_dst_get_next_entry( desc = srng->ring_base_vaddr + srng->u.dst_ring.tp; srng->u.dst_ring.tp = (srng->u.dst_ring.tp + srng->entry_size) % @@ -246,7 +198,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/hal int ath12k_hal_srng_dst_num_free(struct ath12k_base *ab, struct hal_srng *srng, bool sync_hw_ptr) { -@@ -1073,11 +1151,15 @@ void ath12k_hal_srng_access_begin(struct +@@ -1706,11 +1784,15 @@ void ath12k_hal_srng_access_begin(struct { lockdep_assert_held(&srng->lock); @@ -264,11 +216,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/hal } /* Update cached ring head/tail pointers to HW. ath12k_hal_srng_access_begin() -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/hal.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/hal.h -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/hal.h -@@ -610,6 +610,7 @@ enum hal_srng_dir { +--- a/drivers/net/wireless/ath/ath12k/hal.h ++++ b/drivers/net/wireless/ath/ath12k/hal.h +@@ -626,6 +626,7 @@ enum hal_srng_dir { #define HAL_SRNG_FLAGS_MSI_INTR 0x00020000 #define HAL_SRNG_FLAGS_HIGH_THRESH_INTR_EN 0x00080000 #define HAL_SRNG_FLAGS_LMAC_RING 0x80000000 @@ -276,7 +226,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/hal #define HAL_SRNG_TLV_HDR_TAG GENMASK(9, 1) #define HAL_SRNG_TLV_HDR_LEN GENMASK(25, 10) -@@ -1127,4 +1128,8 @@ int ath12k_hal_srng_update_shadow_config +@@ -1152,4 +1153,8 @@ int ath12k_hal_srng_update_shadow_config void ath12k_hal_srng_shadow_config(struct ath12k_base *ab); void ath12k_hal_srng_shadow_update_hp_tp(struct ath12k_base *ab, struct hal_srng *srng); @@ -285,15 +235,59 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/hal +void ath12k_hal_srng_dst_invalidate_entry(struct ath12k_base *ab, + struct hal_srng *srng, int entries); #endif -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/hw.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/hw.h -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/hw.h -@@ -170,6 +170,7 @@ struct ath12k_hw_params { +--- a/drivers/net/wireless/ath/ath12k/hw.h ++++ b/drivers/net/wireless/ath/ath12k/hw.h +@@ -199,6 +199,7 @@ struct ath12k_hw_params { bool supports_ap_ps; bool credit_flow; bool wakeup_mhi; + bool alloc_cacheable_memory; }; - struct ath12k_hw_ops { + /* BRINGUP: move to dp.h */ +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -881,6 +881,7 @@ static const struct ath12k_hw_params ath + .supports_ap_ps = true, + .credit_flow = false, + .wakeup_mhi = false, ++ .alloc_cacheable_memory = true, + }, + { + .name = "wcn7850 hw2.0", +@@ -946,6 +947,7 @@ static const struct ath12k_hw_params ath + .supports_ap_ps = true, + .credit_flow = false, + .wakeup_mhi = false, ++ .alloc_cacheable_memory = false, + }, + }; + +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -688,14 +688,24 @@ void ath12k_dp_tx_completion_handler(str + u32 *desc; + u8 mac_id; + u64 desc_va; ++ int valid_entries; + + spin_lock_bh(&status_ring->lock); + + ath12k_hal_srng_access_begin(ab, status_ring); + ++ valid_entries = ath12k_hal_srng_dst_num_free(ab, status_ring, false); ++ if (!valid_entries) { ++ ath12k_hal_srng_access_end(ab, status_ring); ++ spin_unlock_bh(&status_ring->lock); ++ return; ++ } ++ ++ ath12k_hal_srng_dst_invalidate_entry(ab, status_ring, valid_entries); ++ + while ((ATH12K_TX_COMPL_NEXT(tx_ring->tx_status_head) != + tx_ring->tx_status_tail) && +- (desc = ath12k_hal_srng_dst_get_next_entry(ab, status_ring))) { ++ (desc = ath12k_hal_srng_dst_get_next_cache_entry(ab, status_ring))) { + memcpy(&tx_ring->tx_status[tx_ring->tx_status_head], + desc, sizeof(struct hal_wbm_release_ring)); + tx_ring->tx_status_head = diff --git a/feeds/ipq95xx/mac80211/patches/qca/653-002-ath12k-Allow-fast-rx-by-bypassing-stats-update.patch b/feeds/ipq95xx/mac80211/patches/qca/653-002-ath12k-Allow-fast-rx-by-bypassing-stats-update.patch index cef917f8b..719bf6c6e 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/653-002-ath12k-Allow-fast-rx-by-bypassing-stats-update.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/653-002-ath12k-Allow-fast-rx-by-bypassing-stats-update.patch @@ -19,10 +19,8 @@ Signed-off-by: Balamurugan Selvarajan drivers/net/wireless/ath/ath12k/peer.h | 1 + 7 files changed, 190 insertions(+), 8 deletions(-) -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/core.h -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.h +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h @@ -116,6 +116,7 @@ struct ath12k_skb_rxcb { u8 is_frag; u8 tid; @@ -31,7 +29,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor }; enum ath12k_hw_rev { -@@ -1012,6 +1013,7 @@ struct ath12k_base { +@@ -1013,6 +1014,7 @@ struct ath12k_base { struct device_node *hremote_node; u32 host_ddr_fixed_mem_off; @@ -39,11 +37,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor /* must be last */ u8 drv_priv[0] __aligned(sizeof(void *)); -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/debugfs.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs.c -@@ -1072,6 +1072,67 @@ static const struct file_operations fops +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -1071,6 +1071,67 @@ static const struct file_operations fops .llseek = default_llseek, }; @@ -61,7 +57,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb + tlv_filter.rxmon_disable = true; + } + -+ for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) { ++ for (i = 0; i < ab->hw_params->num_rxmda_per_pdev; i++) { + ring_id = ar->dp.rxdma_mon_dst_ring[i].ring_id; + ath12k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, + ar->dp.mac_id + i, @@ -111,34 +107,33 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb int ath12k_debugfs_pdev_create(struct ath12k_base *ab) { if (test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags)) -@@ -1092,6 +1153,9 @@ int ath12k_debugfs_pdev_create(struct at +@@ -1090,6 +1151,10 @@ int ath12k_debugfs_pdev_create(struct at + debugfs_create_file("trace_qdss", 0600, ab->debugfs_soc, ab, &fops_trace_qdss); - ++ + debugfs_create_file("stats_disable", 0600, ab->debugfs_soc, ab, + &fops_soc_stats_disable); + return 0; } -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_rx.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/dp_rx.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -260,6 +260,12 @@ static u16 ath12k_dp_rxdesc_get_mpdu_fra - return ab->hal.ops->rx_desc_get_mpdu_frame_ctl(desc); +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -236,6 +236,12 @@ static u16 ath12k_dp_rxdesc_get_mpdu_fra + return ab->hw_params->hal_ops->rx_desc_get_mpdu_frame_ctl(desc); } +static inline u8 ath12k_dp_rx_h_msdu_end_ip_valid(struct ath12k_base *ab, + struct hal_rx_desc *desc) +{ -+ return ab->hal.ops->rx_desc_get_ip_valid(desc); ++ return ab->hw_params->hal_ops->rx_desc_get_ip_valid(desc); +} + static void ath12k_dp_service_mon_ring(struct timer_list *t) { struct ath12k_base *ab = from_timer(ab, t, mon_reap_timer); -@@ -2430,10 +2436,60 @@ ath12k_dp_rx_h_find_peer(struct ath12k_b +@@ -2449,10 +2455,60 @@ ath12k_dp_rx_h_find_peer(struct ath12k_b return peer; } @@ -199,8 +194,8 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_ + bool *fast_rx) { bool fill_crypto_hdr; - struct ath12k_skb_rxcb *rxcb; -@@ -2442,6 +2498,8 @@ static void ath12k_dp_rx_h_mpdu(struct a + struct ath12k_base *ab = ar->ab; +@@ -2462,6 +2518,8 @@ static void ath12k_dp_rx_h_mpdu(struct a struct ieee80211_hdr *hdr; struct ath12k_peer *peer; u32 err_bitmap; @@ -209,7 +204,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_ /* PN for multicast packets will be checked in mac80211 */ rxcb = ATH12K_SKB_RXCB(msdu); -@@ -2454,6 +2512,27 @@ static void ath12k_dp_rx_h_mpdu(struct a +@@ -2474,6 +2532,27 @@ static void ath12k_dp_rx_h_mpdu(struct a spin_lock_bh(&ar->ab->base_lock); peer = ath12k_dp_rx_h_find_peer(ar->ab, msdu); if (peer) { @@ -237,7 +232,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_ if (rxcb->is_mcbc) enctype = peer->sec_type_grp; else -@@ -2731,7 +2810,8 @@ static void ath12k_dp_rx_deliver_msdu(st +@@ -2751,7 +2830,8 @@ static void ath12k_dp_rx_deliver_msdu(st static int ath12k_dp_rx_process_msdu(struct ath12k *ar, struct sk_buff *msdu, struct sk_buff_head *msdu_list, @@ -247,7 +242,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_ { struct ath12k_base *ab = ar->ab; struct hal_rx_desc *rx_desc, *lrx_desc; -@@ -2786,8 +2866,11 @@ static int ath12k_dp_rx_process_msdu(str +@@ -2806,8 +2886,11 @@ static int ath12k_dp_rx_process_msdu(str } } @@ -260,7 +255,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_ rx_status->flag |= RX_FLAG_SKIP_MONITOR | RX_FLAG_DUP_VALIDATED; -@@ -2808,6 +2891,7 @@ static void ath12k_dp_rx_process_receive +@@ -2828,6 +2911,7 @@ static void ath12k_dp_rx_process_receive struct ath12k *ar; u8 mac_id; int ret; @@ -268,7 +263,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_ if (skb_queue_empty(msdu_list)) return; -@@ -2816,6 +2900,11 @@ static void ath12k_dp_rx_process_receive +@@ -2836,6 +2920,11 @@ static void ath12k_dp_rx_process_receive while ((msdu = __skb_dequeue(msdu_list))) { rxcb = ATH12K_SKB_RXCB(msdu); @@ -280,7 +275,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_ mac_id = rxcb->mac_id; ar = ab->pdevs[mac_id].ar; if (!rcu_dereference(ab->pdevs_active[mac_id])) { -@@ -2828,7 +2917,7 @@ static void ath12k_dp_rx_process_receive +@@ -2848,7 +2937,7 @@ static void ath12k_dp_rx_process_receive continue; } @@ -289,7 +284,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_ if (ret) { ath12k_dbg(ab, ATH12K_DBG_DATA, "Unable to process msdu %d", ret); -@@ -2836,7 +2925,8 @@ static void ath12k_dp_rx_process_receive +@@ -2856,7 +2945,8 @@ static void ath12k_dp_rx_process_receive continue; } @@ -299,15 +294,15 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_ } rcu_read_unlock(); -@@ -3758,6 +3848,7 @@ static int ath12k_dp_rx_h_null_q_desc(st +@@ -3781,6 +3871,7 @@ static int ath12k_dp_rx_h_null_q_desc(st u8 l3pad_bytes; struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu); - u32 hal_rx_desc_sz = ar->ab->hw_params.hal_desc_sz; + u32 hal_rx_desc_sz = ar->ab->hw_params->hal_desc_sz; + bool fast_rx; msdu_len = ath12k_dp_rx_h_msdu_len(ab, desc); peer_id = ath12k_dp_rx_h_peer_id(ab, desc); -@@ -3810,8 +3901,8 @@ static int ath12k_dp_rx_h_null_q_desc(st +@@ -3833,8 +3924,8 @@ static int ath12k_dp_rx_h_null_q_desc(st skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes); } ath12k_dp_rx_h_ppdu(ar, desc, status); @@ -318,15 +313,15 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_ rxcb->tid = ath12k_dp_rx_h_tid(ab, desc); -@@ -3893,6 +3984,7 @@ static bool ath12k_dp_rx_h_4addr_null_fr +@@ -3916,6 +4007,7 @@ static bool ath12k_dp_rx_h_4addr_null_fr size_t hdr_len; - struct ath12k_dp_rfc1042_hdr *llc; + struct ath12k_dp_rx_rfc1042_hdr *llc; bool drop = false; + bool fast_rx = false; msdu_len = ath12k_dp_rx_h_msdu_len(ab, rx_desc); peer_id = ath12k_dp_rx_h_peer_id(ab, rx_desc); -@@ -3913,7 +4005,7 @@ static bool ath12k_dp_rx_h_4addr_null_fr +@@ -3936,7 +4028,7 @@ static bool ath12k_dp_rx_h_4addr_null_fr ath12k_dp_rx_h_ppdu(ar, rx_desc, status); @@ -335,51 +330,45 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_ rxcb->tid = ath12k_dp_rx_h_tid(ab, rx_desc); -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/hal.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/hal.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/hal.c -@@ -460,6 +460,16 @@ static u16 ath12k_hw_qcn92xx_rx_desc_get - return __le16_to_cpu(desc->u.qcn92xx.mpdu_start.frame_ctrl); +--- a/drivers/net/wireless/ath/ath12k/hal.c ++++ b/drivers/net/wireless/ath/ath12k/hal.c +@@ -471,6 +471,16 @@ static u16 ath12k_hw_qcn9274_rx_desc_get + return __le16_to_cpu(desc->u.qcn9274.mpdu_start.frame_ctrl); } -+static u8 ath12k_hal_qcn92xx_rx_desc_get_ip_valid(struct hal_rx_desc *desc) ++static u8 ath12k_hal_qcn9274_rx_desc_get_ip_valid(struct hal_rx_desc *desc) +{ + bool ipv4, ipv6; + ipv4 = FIELD_GET(RX_MSDU_END_INFO11_IPV4, -+ __le32_to_cpu(desc->u.qcn92xx.msdu_end.info11)); ++ __le32_to_cpu(desc->u.qcn9274.msdu_end.info11)); + ipv6 = FIELD_GET(RX_MSDU_END_INFO11_IPV6, -+ __le32_to_cpu(desc->u.qcn92xx.msdu_end.info11)); ++ __le32_to_cpu(desc->u.qcn9274.msdu_end.info11)); + return (ipv4 || ipv6); +} + - static const struct hal_ops hal_qcn92xx_ops = { - .rx_desc_get_first_msdu = ath12k_hw_qcn92xx_rx_desc_get_first_msdu, - .rx_desc_get_last_msdu = ath12k_hw_qcn92xx_rx_desc_get_last_msdu, -@@ -493,6 +503,7 @@ static const struct hal_ops hal_qcn92xx_ - .rx_desc_get_crypto_header = ath12k_hw_qcn92xx_rx_desc_get_crypto_hdr, - .rx_desc_get_mpdu_frame_ctl = ath12k_hw_qcn92xx_rx_desc_get_mpdu_frame_ctl, - .tcl_to_wbm_rbm_map = ath12k_hal_qcn92xx_tcl_to_wbm_rbm_map, -+ .rx_desc_get_ip_valid = ath12k_hal_qcn92xx_rx_desc_get_ip_valid, + static int ath12k_hal_srng_create_config_qcn9274(struct ath12k_base *ab) + { + struct ath12k_hal *hal = &ab->hal; +@@ -673,6 +683,7 @@ const struct hal_ops hal_qcn9274_ops = { + .dp_rx_h_ip_cksum_fail = ath12k_hw_qcn9274_dp_rx_h_ip_cksum_fail, + .dp_rx_h_is_decrypted = ath12k_hw_qcn9274_dp_rx_h_is_decrypted, + .dp_rx_h_mpdu_err = ath12k_hw_qcn9274_dp_rx_h_mpdu_err, ++ .rx_desc_get_ip_valid = ath12k_hal_qcn9274_rx_desc_get_ip_valid, }; - static int ath12k_hal_alloc_cont_rdp(struct ath12k_base *ab) -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/hal.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/hal.h -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/hal.h -@@ -1068,6 +1068,7 @@ struct hal_ops { - void (*rx_desc_get_crypto_header)(struct hal_rx_desc *desc, - u8 *crypto_hdr, - enum hal_encrypt_type enctype); + static bool ath12k_hw_wcn7850_rx_desc_get_first_msdu(struct hal_rx_desc *desc) +--- a/drivers/net/wireless/ath/ath12k/hal.h ++++ b/drivers/net/wireless/ath/ath12k/hal.h +@@ -1091,6 +1091,7 @@ struct hal_ops { + bool (*dp_rx_h_ip_cksum_fail)(struct hal_rx_desc *desc); + bool (*dp_rx_h_is_decrypted)(struct hal_rx_desc *desc); + u32 (*dp_rx_h_mpdu_err)(struct hal_rx_desc *desc); + u8 (*rx_desc_get_ip_valid)(struct hal_rx_desc *desc); const struct ath12k_hal_tcl_to_wbm_rbm_map *tcl_to_wbm_rbm_map; }; -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/peer.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/peer.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/peer.c +--- a/drivers/net/wireless/ath/ath12k/peer.c ++++ b/drivers/net/wireless/ath/ath12k/peer.c @@ -267,6 +267,7 @@ int ath12k_peer_create(struct ath12k *ar { struct ath12k_peer *peer; @@ -396,11 +385,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/pee if (sta) { arsta = (struct ath12k_sta *)sta->drv_priv; -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/peer.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/peer.h -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/peer.h -@@ -21,6 +21,7 @@ struct ppdu_user_delayba { +--- a/drivers/net/wireless/ath/ath12k/peer.h ++++ b/drivers/net/wireless/ath/ath12k/peer.h +@@ -23,6 +23,7 @@ struct ppdu_user_delayba { struct ath12k_peer { struct list_head list; struct ieee80211_sta *sta; @@ -408,11 +395,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/pee int vdev_id; u8 addr[ETH_ALEN]; int peer_id; -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/dp.h -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp.h -@@ -1183,6 +1183,7 @@ struct htt_rx_ring_tlv_filter { +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -1147,6 +1147,7 @@ struct htt_rx_ring_tlv_filter { u32 info0; u32 info1; bool drop_threshold_valid; @@ -420,19 +405,18 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp. }; #define HTT_STATS_FRAME_CTRL_TYPE_MGMT 0x0 -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_tx.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/dp_tx.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -1151,8 +1151,9 @@ int ath12k_dp_tx_htt_rx_filter_setup(str - tlv_filter->offset_valid); - cmd->info0 |= FIELD_PREP(HTT_RX_RING_SELECTION_CFG_CMD_DROP_THRES_VAL, - tlv_filter->drop_threshold_valid); -- cmd->info0 |= FIELD_PREP(HTT_RX_RING_SELECTION_CFG_CMD_RXMON_GCONF_EN, -- true); +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -1121,8 +1121,10 @@ int ath12k_dp_tx_htt_rx_filter_setup(str + HTT_RX_RING_SELECTION_CFG_CMD_OFFSET_VALID); + cmd->info0 |= u32_encode_bits(tlv_filter->drop_threshold_valid, + HTT_RX_RING_SELECTION_CFG_CMD_DROP_THRES_VAL); +- cmd->info0 |= u32_encode_bits(true, +- HTT_RX_RING_SELECTION_CFG_CMD_RXMON_GCONF_EN); + if (!tlv_filter->rxmon_disable) -+ cmd->info0 |= FIELD_PREP(HTT_RX_RING_SELECTION_CFG_CMD_RXMON_GCONF_EN, -+ true); - - cmd->info1 = FIELD_PREP(HTT_RX_RING_SELECTION_CFG_CMD_INFO1_BUF_SIZE, - rx_buf_size); ++ cmd->info0 |= u32_encode_bits(true, ++ HTT_RX_RING_SELECTION_CFG_CMD_RXMON_GCONF_EN); ++ + cmd->info1 = u32_encode_bits(rx_buf_size, + HTT_RX_RING_SELECTION_CFG_CMD_INFO1_BUF_SIZE); + cmd->info1 |= u32_encode_bits(tlv_filter->conf_len_mgmt, diff --git a/feeds/ipq95xx/mac80211/patches/qca/654-ath12k-Add-HE-UL-MU-fixed-rate-setting.patch b/feeds/ipq95xx/mac80211/patches/qca/654-ath12k-Add-HE-UL-MU-fixed-rate-setting.patch index b24f3c79d..46fed26d5 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/654-ath12k-Add-HE-UL-MU-fixed-rate-setting.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/654-ath12k-Add-HE-UL-MU-fixed-rate-setting.patch @@ -140,8 +140,8 @@ Signed-off-by: Rajat Soni + /* TODO: + * check when UL is valid + */ -+ if (he_ul_fixed_rate && (!peer->sta->he_cap.has_he || -+ peer->sta->rx_nss < he_ul_nss)) { ++ if (he_ul_fixed_rate && (!peer->sta->deflink.he_cap.has_he || ++ peer->sta->deflink.rx_nss < he_ul_nss)) { + ret = false; + goto exit; + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/654-ath12k-Add-pktlog-support-through-debugfs.patch b/feeds/ipq95xx/mac80211/patches/qca/654-ath12k-Add-pktlog-support-through-debugfs.patch index 0eae617a9..b10c6db5e 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/654-ath12k-Add-pktlog-support-through-debugfs.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/654-ath12k-Add-pktlog-support-through-debugfs.patch @@ -63,7 +63,7 @@ Signed-off-by: Karthik M @@ -28,6 +28,7 @@ ath12k-$(CPTCFG_ATH12K_TRACING) += trace ath12k-$(CONFIG_THERMAL) += thermal.o ath12k-$(CPTCFG_ATH12K_SPECTRAL) += spectral.o - ath12k-$(CONFIG_WANT_DEV_COREDUMP) += coredump.o + ath12k-$(CPTCFG_WANT_DEV_COREDUMP) += coredump.o +ath12k-$(CPTCFG_ATH12K_PKTLOG) += pktlog.o # for tracing framework to find trace.h @@ -78,7 +78,7 @@ Signed-off-by: Karthik M #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK) -@@ -585,6 +586,11 @@ struct ath12k_debug { +@@ -587,6 +588,11 @@ struct ath12k_debug { u32 pktlog_mode; u32 pktlog_peer_valid; u8 pktlog_peer_addr[ETH_ALEN]; @@ -88,11 +88,11 @@ Signed-off-by: Karthik M + bool is_pkt_logging; +#endif u32 rx_filter; - bool enable_m3_dump; }; + --- a/drivers/net/wireless/ath/ath12k/debugfs.c +++ b/drivers/net/wireless/ath/ath12k/debugfs.c -@@ -1540,6 +1540,7 @@ int ath12k_debugfs_register(struct ath12 +@@ -1254,6 +1254,7 @@ int ath12k_debugfs_register(struct ath12 ath12k_debugfs_htt_stats_init(ar); ath12k_debugfs_fw_stats_init(ar); @@ -100,7 +100,7 @@ Signed-off-by: Karthik M debugfs_create_file("ext_tx_stats", 0644, ar->debug.debugfs_pdev, ar, -@@ -1578,6 +1579,7 @@ int ath12k_debugfs_register(struct ath12 +@@ -1285,6 +1286,7 @@ int ath12k_debugfs_register(struct ath12 void ath12k_debugfs_unregister(struct ath12k *ar) { @@ -110,9 +110,9 @@ Signed-off-by: Karthik M int ath12k_debugfs_create(void) --- a/drivers/net/wireless/ath/ath12k/debugfs.h +++ b/drivers/net/wireless/ath/ath12k/debugfs.h -@@ -259,4 +259,31 @@ static inline void ath12k_debugfs_remove +@@ -247,4 +247,31 @@ static inline int ath12k_debugfs_rx_filt - #endif /* CPTCFG_ATH12K_DEBUGFS*/ + #endif /* CPTCFG_MAC80211_DEBUGFS*/ +#ifdef CPTCFG_ATH12K_PKTLOG +void ath12k_init_pktlog(struct ath12k *ar); @@ -144,7 +144,7 @@ Signed-off-by: Karthik M #endif /* _ATH12K_DEBUGFS_H_ */ --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -1578,8 +1578,10 @@ static int ath12k_htt_pull_ppdu_stats(st +@@ -1668,8 +1668,10 @@ static int ath12k_htt_pull_ppdu_stats(st goto exit; } @@ -156,7 +156,7 @@ Signed-off-by: Karthik M spin_lock_bh(&ar->data_lock); ppdu_info = ath12k_dp_htt_get_ppdu_desc(ar, ppdu_id); -@@ -1663,6 +1665,7 @@ static void ath12k_htt_pktlog(struct ath +@@ -1753,6 +1755,7 @@ static void ath12k_htt_pktlog(struct ath trace_ath12k_htt_pktlog(ar, data->payload, hdr->size, ar->ab->pktlog_defs_checksum); @@ -768,7 +768,7 @@ Signed-off-by: Karthik M +ATH12K_PKTLOG= --- a/drivers/net/wireless/ath/ath12k/dp_mon.c +++ b/drivers/net/wireless/ath/ath12k/dp_mon.c -@@ -3380,9 +3380,12 @@ move_next: +@@ -3664,9 +3664,12 @@ move_next: memset(ppdu_info, 0, sizeof(*ppdu_info)); while ((skb = __skb_dequeue(&skb_list))) { @@ -781,9 +781,9 @@ Signed-off-by: Karthik M + } if (flag == ATH12K_DP_RX_MONITOR_MODE) - hal_status = ath12k_dp_mon_rx_parse_mon_status(ar, pmon, mac_id, -@@ -3408,9 +3411,12 @@ move_next: - goto next_skb; + hal_status = +@@ -3705,9 +3708,12 @@ move_next: + ath12k_dp_mon_rx_update_peer_mu_stats(ar, ppdu_info); } - if (ath12k_debugfs_is_pktlog_peer_valid(ar, peer->addr)) diff --git a/feeds/ipq95xx/mac80211/patches/qca/656-ath12k-fix-scheduling-while-atomic-in-beacon_tx_status.patch b/feeds/ipq95xx/mac80211/patches/qca/656-ath12k-fix-scheduling-while-atomic-in-beacon_tx_status.patch index ec5f19002..ae0bd1d09 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/656-ath12k-fix-scheduling-while-atomic-in-beacon_tx_status.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/656-ath12k-fix-scheduling-while-atomic-in-beacon_tx_status.patch @@ -22,7 +22,7 @@ Signed-off-by: Manish Dharanenthiran --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h -@@ -350,6 +350,7 @@ struct ath12k_vif { +@@ -353,6 +353,7 @@ struct ath12k_vif { #ifdef CPTCFG_ATH12K_DEBUGFS struct dentry *debugfs_twt; #endif /* CPTCFG_ATH12K_DEBUGFS */ @@ -32,24 +32,24 @@ Signed-off-by: Manish Dharanenthiran struct ath12k_vif_iter { --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -1468,6 +1468,7 @@ static int ath12k_mac_setup_bcn_tmpl(str +@@ -1477,6 +1477,7 @@ static int ath12k_mac_setup_bcn_tmpl(str void ath12k_mac_bcn_tx_event(struct ath12k_vif *arvif) { struct ieee80211_vif *vif = arvif->vif; + struct ath12k *ar = arvif->ar; - if (!vif->color_change_active && !arvif->bcca_zero_sent) + if (!vif->bss_conf.color_change_active && !arvif->bcca_zero_sent) return; -@@ -1482,7 +1483,7 @@ void ath12k_mac_bcn_tx_event(struct ath1 +@@ -1491,7 +1492,7 @@ void ath12k_mac_bcn_tx_event(struct ath1 - if (vif->color_change_active) + if (vif->bss_conf.color_change_active) ieee80211_beacon_update_cntdwn(vif); - ath12k_mac_setup_bcn_tmpl(arvif); + ieee80211_queue_work(ar->ah->hw, &arvif->update_bcn_template_work); } static void ath12k_control_beaconing(struct ath12k_vif *arvif, -@@ -7113,6 +7114,21 @@ static void ath12k_mac_op_update_vif_off +@@ -7312,6 +7313,25 @@ static void ath12k_mac_op_update_vif_off mutex_unlock(&ah->conf_mutex); } @@ -58,10 +58,14 @@ Signed-off-by: Manish Dharanenthiran + struct ath12k_vif *arvif = container_of(work, struct ath12k_vif, + update_bcn_template_work); + struct ath12k *ar = arvif->ar; -+ int ret; ++ int ret = -EINVAL; ++ ++ if (!ar) ++ return; + + mutex_lock(&ar->conf_mutex); -+ ret = ath12k_mac_setup_bcn_tmpl(arvif); ++ if (arvif->is_created) ++ ret = ath12k_mac_setup_bcn_tmpl(arvif); + mutex_unlock(&ar->conf_mutex); + if (ret) + ath12k_warn(ar->ab, "failed to update bcn tmpl for vdev_id: %d ret: %d\n", @@ -71,7 +75,7 @@ Signed-off-by: Manish Dharanenthiran static int ath12k_mac_vdev_create(struct ath12k *ar, struct ieee80211_vif *vif) { struct ath12k_base *ab = ar->ab; -@@ -7454,6 +7470,7 @@ static int ath12k_mac_op_add_interface(s +@@ -7653,6 +7673,7 @@ static int ath12k_mac_op_add_interface(s INIT_LIST_HEAD(&arvif->list); arvif->key_cipher = INVALID_CIPHER; @@ -79,7 +83,7 @@ Signed-off-by: Manish Dharanenthiran 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_FORCE_SGI; -@@ -7511,6 +7528,8 @@ static void ath12k_mac_op_remove_interfa +@@ -7710,6 +7731,8 @@ static void ath12k_mac_op_remove_interfa struct ath12k_base *ab; int ret; diff --git a/feeds/ipq95xx/mac80211/patches/qca/656-ath12k-pktlog-rx-filter-changes.patch b/feeds/ipq95xx/mac80211/patches/qca/656-ath12k-pktlog-rx-filter-changes.patch index 55414032a..5ab8ab271 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/656-ath12k-pktlog-rx-filter-changes.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/656-ath12k-pktlog-rx-filter-changes.patch @@ -20,7 +20,7 @@ Signed-off-by: Karthik M --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h -@@ -588,13 +588,17 @@ struct ath12k_debug { +@@ -590,12 +590,16 @@ struct ath12k_debug { u8 pktlog_peer_addr[ETH_ALEN]; #ifdef CPTCFG_ATH12K_PKTLOG struct dentry *debugfs_pktlog; @@ -29,7 +29,6 @@ Signed-off-by: Karthik M bool is_pkt_logging; #endif u32 rx_filter; - bool enable_m3_dump; }; +int ath12k_pktlog_rx_filter_setting(struct ath12k *ar, @@ -41,7 +40,7 @@ Signed-off-by: Karthik M u32 retry_bytes; --- a/drivers/net/wireless/ath/ath12k/debugfs.c +++ b/drivers/net/wireless/ath/ath12k/debugfs.c -@@ -1142,6 +1142,25 @@ void ath12k_debugfs_fw_stats_init(struct +@@ -951,6 +951,25 @@ void ath12k_debugfs_fw_stats_init(struct init_completion(&ar->debug.fw_stats_complete); } @@ -51,7 +50,7 @@ Signed-off-by: Karthik M +{ + int ret, i; + u32 ring_id; -+ for (i = 0; i < ar->ab->hw_params.num_rxmda_per_pdev; i++) { ++ for (i = 0; i < ar->ab->hw_params->num_rxmda_per_pdev; i++) { + ring_id = ar->dp.rxdma_mon_dst_ring[i].ring_id; + ret = ath12k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, + ar->dp.mac_id + i, @@ -67,7 +66,7 @@ Signed-off-by: Karthik M static int ath12k_pktlog_enable_hybrid_mode(struct ath12k *ar, u32 filter, u32 mode) { -@@ -1197,8 +1216,7 @@ static ssize_t ath12k_write_pktlog_filte +@@ -1006,8 +1025,7 @@ static ssize_t ath12k_write_pktlog_filte struct ath12k *ar = file->private_data; struct ath12k_base *ab = ar->ab; struct htt_rx_ring_tlv_filter tlv_filter = {0}; @@ -77,7 +76,7 @@ Signed-off-by: Karthik M u8 buf[128] = {0}; int ret, hybrid_enable, rx_buf_sz; ssize_t rc; -@@ -1227,7 +1245,7 @@ static ssize_t ath12k_write_pktlog_filte +@@ -1036,7 +1054,7 @@ static ssize_t ath12k_write_pktlog_filte if ((filter & ATH12K_PKTLOG_RX) && hybrid_enable) { ret = -EINVAL; @@ -86,7 +85,7 @@ Signed-off-by: Karthik M "Invalid configuration. Hybrid mode is only applicable when tx or lite pktlog is used"); goto out; } -@@ -1239,36 +1257,33 @@ static ssize_t ath12k_write_pktlog_filte +@@ -1048,36 +1066,33 @@ static ssize_t ath12k_write_pktlog_filte filter |= ATH12K_PKTLOG_HYBRID; ret = ath12k_wmi_pdev_pktlog_enable(ar, filter); if (ret) { @@ -136,7 +135,7 @@ Signed-off-by: Karthik M goto out; } -@@ -1287,12 +1302,12 @@ static ssize_t ath12k_write_pktlog_filte +@@ -1096,12 +1111,12 @@ static ssize_t ath12k_write_pktlog_filte HTT_RX_FILTER_TLV_FLAGS_MPDU_END | HTT_RX_FILTER_TLV_FLAGS_PACKET_HEADER | HTT_RX_FILTER_TLV_FLAGS_ATTENTION; @@ -151,7 +150,7 @@ Signed-off-by: Karthik M goto out; } -@@ -1306,7 +1321,7 @@ static ssize_t ath12k_write_pktlog_filte +@@ -1115,7 +1130,7 @@ static ssize_t ath12k_write_pktlog_filte ret = ath12k_dp_tx_htt_h2t_ppdu_stats_req(ar, HTT_PPDU_STATS_TAG_DEFAULT); if (ret) { @@ -160,7 +159,7 @@ Signed-off-by: Karthik M ret); goto out; } -@@ -1321,12 +1336,10 @@ static ssize_t ath12k_write_pktlog_filte +@@ -1130,12 +1145,10 @@ static ssize_t ath12k_write_pktlog_filte HTT_RX_FP_DATA_FILTER_FLASG3; } @@ -189,9 +188,9 @@ Signed-off-by: Karthik M u16 log_type; --- a/drivers/net/wireless/ath/ath12k/dp_mon.c +++ b/drivers/net/wireless/ath/ath12k/dp_mon.c -@@ -3298,9 +3298,8 @@ int ath12k_dp_mon_srng_process(struct at - struct sk_buff_head skb_list; +@@ -3582,9 +3582,8 @@ int ath12k_dp_mon_srng_process(struct at struct ath12k_peer *peer = NULL; + struct ath12k_sta *arsta = NULL; u64 cookie; - u32 hal_status, end_reason, rx_buf_sz, ppdu_id; + u32 hal_status, end_reason, ppdu_id; @@ -200,7 +199,7 @@ Signed-off-by: Karthik M __skb_queue_head_init(&skb_list); -@@ -3314,14 +3313,6 @@ int ath12k_dp_mon_srng_process(struct at +@@ -3598,14 +3597,6 @@ int ath12k_dp_mon_srng_process(struct at buf_ring = &dp->tx_mon_buf_ring; } @@ -215,7 +214,7 @@ Signed-off-by: Karthik M srng = &ab->hal.srng_list[mon_dst_ring->ring_id]; spin_lock_bh(&srng->lock); ath12k_hal_srng_access_begin(ab, srng); -@@ -3380,13 +3371,6 @@ move_next: +@@ -3664,13 +3655,6 @@ move_next: memset(ppdu_info, 0, sizeof(*ppdu_info)); while ((skb = __skb_dequeue(&skb_list))) { @@ -227,10 +226,10 @@ Signed-off-by: Karthik M - } - if (flag == ATH12K_DP_RX_MONITOR_MODE) - hal_status = ath12k_dp_mon_rx_parse_mon_status(ar, pmon, mac_id, - skb, napi); -@@ -3411,13 +3395,6 @@ move_next: - goto next_skb; + hal_status = + ath12k_dp_mon_rx_parse_mon_status(ar, ppdu_info, mac_id, +@@ -3708,13 +3692,6 @@ move_next: + ath12k_dp_mon_rx_update_peer_mu_stats(ar, ppdu_info); } - if (ath12k_debugfs_is_pktlog_peer_valid(ar, peer->addr)) { @@ -243,7 +242,7 @@ Signed-off-by: Karthik M next_skb: spin_unlock_bh(&ab->base_lock); rcu_read_unlock(); -@@ -3754,7 +3731,8 @@ int ath12k_dp_mon_rx_process_stats(struc +@@ -3746,7 +3723,8 @@ int ath12k_dp_mon_rx_process_stats(struc struct sk_buff_head skb_list; u64 cookie; int num_buffs_reaped = 0, srng_id, buf_id; @@ -253,7 +252,7 @@ Signed-off-by: Karthik M __skb_queue_head_init(&skb_list); -@@ -3762,11 +3740,25 @@ int ath12k_dp_mon_rx_process_stats(struc +@@ -3754,11 +3732,25 @@ int ath12k_dp_mon_rx_process_stats(struc mon_dst_ring = &pdev_dp->rxdma_mon_dst_ring[srng_id]; buf_ring = &dp->rxdma_mon_buf_ring; @@ -279,7 +278,7 @@ Signed-off-by: Karthik M mon_dst_desc = (struct hal_mon_dest_desc *) ath12k_hal_srng_dst_peek(ab, srng); if (unlikely(!mon_dst_desc)) -@@ -3847,6 +3839,12 @@ move_next: +@@ -3843,6 +3835,12 @@ move_next: ath12k_dp_mon_rx_update_peer_mu_stats(ar, ppdu_info); } @@ -294,7 +293,7 @@ Signed-off-by: Karthik M rcu_read_unlock(); --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -1723,7 +1723,7 @@ exit: +@@ -1741,7 +1741,7 @@ exit: static void ath12k_htt_pktlog(struct ath12k_base *ab, struct sk_buff *skb) { struct htt_pktlog_msg *data = (struct htt_pktlog_msg *)skb->data; @@ -819,7 +818,7 @@ Signed-off-by: Karthik M spinlock_t lock; --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -8068,8 +8068,8 @@ ath12k_wmi_pktlog_decode_info(struct ath +@@ -8101,8 +8101,8 @@ ath12k_wmi_pktlog_decode_info(struct ath struct ath12k *ar; const void **tb; int ret; diff --git a/feeds/ipq95xx/mac80211/patches/qca/656-mac80211-Fix-the-ht_capa-check-warning.patch b/feeds/ipq95xx/mac80211/patches/qca/656-mac80211-Fix-the-ht_capa-check-warning.patch deleted file mode 100644 index 60d778d03..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/656-mac80211-Fix-the-ht_capa-check-warning.patch +++ /dev/null @@ -1,38 +0,0 @@ -From bafcea78f5615d24185cc07832ee3ef2ce01f0e2 Mon Sep 17 00:00:00 2001 -From: Sivashankari Madhavan -Date: Mon, 1 Aug 2022 10:27:42 +0530 -Subject: [PATCH] mac80211: Fix the ht_capa check warning - -In sta_ht_capa_read() we allocate the memory for ht_capabilies -buffer size for print. Based on this size we move the buffer -pointer and pass the remaining size to scnprintf for printing. -In problematic case, we calculating the remaining size by sizeof (buf) -instead of allocated buffer size in PRINT_HT_CAP define. - -p += scnprintf(p, sizeof (buf) + buf - p, "\t" _str "\n"); -(i.e) sizeof (buf) + buf - p = 8 + 1000 - 1200 = -ive value passing to scnprintf. -So only observing Warning. - -Now i changed the remaining size calculation based on allocated buffer size. - -Signed-off-by: Sivashankari Madhavan ---- - net/mac80211/debugfs_sta.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c -index 4e2a364..39adfac 100644 ---- a/net/mac80211/debugfs_sta.c -+++ b/net/mac80211/debugfs_sta.c -@@ -441,7 +441,7 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, - #define PRINT_HT_CAP(_cond, _str) \ - do { \ - if (_cond) \ -- p += scnprintf(p, sizeof(buf)+buf-p, "\t" _str "\n"); \ -+ p += scnprintf(p, bufsz + buf - p, "\t" _str "\n"); \ - } while (0) - char *buf, *p; - int i; --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/657-ath12k-Add-missing-per-peer-parameters.patch b/feeds/ipq95xx/mac80211/patches/qca/657-ath12k-Add-missing-per-peer-parameters.patch index c163fb829..b01d1c1bd 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/657-ath12k-Add-missing-per-peer-parameters.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/657-ath12k-Add-missing-per-peer-parameters.patch @@ -46,11 +46,9 @@ Signed-off-by: Dinesh Karthikeyan drivers/net/wireless/ath/ath12k/mac.c | 11 ++ 5 files changed, 253 insertions(+), 2 deletions(-) -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/core.h 2022-08-18 11:42:04.665091872 +0530 -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.h 2022-08-18 11:42:04.649091842 +0530 -@@ -496,6 +496,16 @@ struct ath12k_wbm_tx_stats { +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -498,6 +498,16 @@ struct ath12k_wbm_tx_stats { u64 wbm_tx_comp_stats[HAL_WBM_REL_HTT_TX_COMP_STATUS_MAX]; }; @@ -67,7 +65,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor struct ath12k_sta { struct ath12k_vif *arvif; -@@ -525,6 +535,8 @@ struct ath12k_sta { +@@ -528,6 +538,8 @@ struct ath12k_sta { bool use_4addr_set; u16 tcl_metadata; u32 bw_prev; @@ -76,10 +74,8 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor }; #define ATH12K_HALF_20MHZ_BW 10 -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/debugfs.h 2022-08-18 11:42:04.665091872 +0530 -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs.h 2022-08-18 11:42:04.653091850 +0530 +--- a/drivers/net/wireless/ath/ath12k/debugfs.h ++++ b/drivers/net/wireless/ath/ath12k/debugfs.h @@ -12,6 +12,8 @@ #define ATH12K_TX_POWER_MAX_VAL 70 #define ATH12K_TX_POWER_MIN_VAL 0 @@ -89,10 +85,8 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb /* htt_dbg_ext_stats_type */ enum ath12k_dbg_htt_ext_stats_type { ATH12K_DBG_HTT_EXT_STATS_RESET = 0, -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs_sta.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/debugfs_sta.c 2022-08-18 11:42:04.665091872 +0530 -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs_sta.c 2022-08-18 11:42:04.653091850 +0530 +--- a/drivers/net/wireless/ath/ath12k/debugfs_sta.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs_sta.c @@ -12,6 +12,7 @@ #include "debug.h" #include "dp_tx.h" @@ -303,11 +297,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb debugfs_create_file("htt_peer_stats", 0400, dir, sta, &fops_htt_peer_stats); -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_rx.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/dp_rx.c 2022-08-18 11:42:04.665091872 +0530 -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_rx.c 2022-08-18 11:44:35.385368762 +0530 -@@ -2747,6 +2747,7 @@ static void ath12k_dp_rx_deliver_msdu(st +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -2766,6 +2766,7 @@ static void ath12k_dp_rx_deliver_msdu(st u8 decap = DP_RX_DECAP_TYPE_RAW; bool is_mcbc = rxcb->is_mcbc; bool is_eapol = rxcb->is_eapol; @@ -315,7 +307,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_ if (status->encoding == RX_ENC_HE && !(status->flag & RX_FLAG_RADIOTAP_HE) && !(status->flag & RX_FLAG_SKIP_MONITOR)) { -@@ -2808,6 +2809,18 @@ static void ath12k_dp_rx_deliver_msdu(st +@@ -2827,6 +2828,18 @@ static void ath12k_dp_rx_deliver_msdu(st rx_status->flag |= RX_FLAG_8023; ieee80211_rx_napi(ar->ah->hw, pubsta, msdu, napi); @@ -334,28 +326,28 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_ } static int ath12k_dp_rx_process_msdu(struct ath12k *ar, -@@ -2951,6 +2964,9 @@ int ath12k_dp_process_rx(struct ath12k_b - int mac_id; +@@ -2971,6 +2984,9 @@ int ath12k_dp_rx_process(struct ath12k_b u32 *rx_desc; int i; + u64 desc_va; + struct ath12k_sta *arsta = NULL; + struct ath12k_peer *peer = NULL; + struct ath12k *ar; __skb_queue_head_init(&msdu_list); -@@ -2972,6 +2988,8 @@ try_again: - mac_id = FIELD_GET(HAL_REO_DEST_RING_INFO0_SRC_LINK_ID, - desc.info0); +@@ -2992,6 +3008,8 @@ try_again: + mac_id = u32_get_bits(desc.info0, + HAL_REO_DEST_RING_INFO0_SRC_LINK_ID); -+ ar = ab->pdevs[mac_id].ar; ++ ar = ab->pdevs[mac_id].ar; + - desc_info = (struct ath12k_rx_desc_info *)(uintptr_t)((u64)desc.buf_va_hi << 32 | - desc.buf_va_lo); + desc_va = ((u64)desc.buf_va_hi << 32 | desc.buf_va_lo); + desc_info = (struct ath12k_rx_desc_info *)((unsigned long)desc_va); -@@ -3016,6 +3034,19 @@ try_again: - desc.rx_mpdu_info.peer_meta_data); - rxcb->tid = FIELD_GET(RX_MPDU_DESC_INFO0_TID, desc.rx_mpdu_info.info0); +@@ -3037,6 +3055,19 @@ try_again: + rxcb->tid = u32_get_bits(desc.rx_mpdu_info.info0, + RX_MPDU_DESC_INFO0_TID); + if (ath12k_debugfs_is_extd_rx_stats_enabled(ar) && rxcb->peer_id) { + rcu_read_lock(); @@ -373,16 +365,16 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_ __skb_queue_tail(&msdu_list, msdu); if (!rxcb->is_continuation) { -@@ -3852,6 +3883,8 @@ static int ath12k_dp_rx_h_null_q_desc(st +@@ -3874,6 +3905,8 @@ static int ath12k_dp_rx_h_null_q_desc(st struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu); - u32 hal_rx_desc_sz = ar->ab->hw_params.hal_desc_sz; + u32 hal_rx_desc_sz = ar->ab->hw_params->hal_desc_sz; bool fast_rx; + struct ath12k_sta *arsta = NULL; + struct ath12k_peer *peer = NULL; msdu_len = ath12k_dp_rx_h_msdu_len(ab, desc); peer_id = ath12k_dp_rx_h_peer_id(ab, desc); -@@ -3913,6 +3946,18 @@ static int ath12k_dp_rx_h_null_q_desc(st +@@ -3935,6 +3968,18 @@ static int ath12k_dp_rx_h_null_q_desc(st * rx with mac80211. Need not worry about cleaning up amsdu_list. */ @@ -401,11 +393,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_ return 0; } -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/mac.c 2022-08-18 11:42:04.665091872 +0530 -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac.c 2022-08-18 11:42:04.657091857 +0530 -@@ -6392,6 +6392,7 @@ static void ath12k_mac_setup_he_eht_cap( +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -6469,6 +6469,7 @@ static void ath12k_mac_setup_he_eht_cap( band->iftype_data = ar->mac.iftype[NL80211_BAND_6GHZ]; band->n_iftype_data = count; } @@ -413,7 +403,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac } static int __ath12k_set_antenna(struct ath12k *ar, u32 tx_ant, u32 rx_ant) -@@ -6649,6 +6650,7 @@ static void ath12k_mac_op_tx(struct ieee +@@ -6726,6 +6727,7 @@ static void ath12k_mac_op_tx(struct ieee struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_key_conf *key = info->control.hw_key; struct ath12k_sta *arsta = NULL; @@ -421,7 +411,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac u32 info_flags = info->flags; bool is_prb_rsp; int ret; -@@ -6686,6 +6688,15 @@ static void ath12k_mac_op_tx(struct ieee +@@ -6763,6 +6765,15 @@ static void ath12k_mac_op_tx(struct ieee ret); ieee80211_free_txskb(ah->hw, skb); } diff --git a/feeds/ipq95xx/mac80211/patches/qca/657-ath12k-Fix-memory-leak.patch b/feeds/ipq95xx/mac80211/patches/qca/657-ath12k-Fix-memory-leak.patch index 203e56873..2e0d4da80 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/657-ath12k-Fix-memory-leak.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/657-ath12k-Fix-memory-leak.patch @@ -1,45 +1,47 @@ -From fee3d6501992e40a91bb2d237af10923485cb826 Mon Sep 17 00:00:00 2001 +From cc50855ca3ea21a6f4fb92e452914f5b05c6339c Mon Sep 17 00:00:00 2001 From: Rajat Soni -Date: Wed, 17 Aug 2022 10:51:12 +0530 +Date: Wed, 15 Feb 2023 14:04:54 -0800 Subject: [PATCH] ath12k: Fix memory leak During rmmod, insmod and in SSR case memory leak is observed. -Freed buff->payload in ath12k_dbring_buf_cleanup(). -In ath12k_dp_cc_cleanup(), return is there after variable declaration -that don't allow func to do cleanup and memory is not getting freed. -So removed return. +Allocate arsta->rx_stats and ar->tx_stats if arsta->rx_stats and ar->tx_stats +is NULL respectively. rx_stats/tx_stats for each arsta is allocated when adding +a station. arsta->rx_stats and arsta->tx_stats will be freed when a station is +removed. ath12k_mac_station_add is called multiple times, so we need to stop +allocating rx_stats multiple times for same arsta. -Signed-off-by: Rajat Soni +Signed-off-by: Sidhanta Sahu --- - drivers/net/wireless/ath/ath12k/dbring.c | 1 + - drivers/net/wireless/ath/ath12k/dp.c | 2 -- - 2 files changed, 1 insertion(+), 2 deletions(-) + drivers/net/wireless/ath/ath12k/mac.c | 13 ++++++++----- + 1 files changed, 8 insertions(+), 5 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/dbring.c b/drivers/net/wireless/ath/ath12k/dbring.c -index 026eed9..1c7855e 100644 ---- a/drivers/net/wireless/ath/ath12k/dbring.c -+++ b/drivers/net/wireless/ath/ath12k/dbring.c -@@ -349,6 +349,7 @@ void ath12k_dbring_buf_cleanup(struct ath12k *ar, struct ath12k_dbring *ring) - idr_remove(&ring->bufs_idr, buf_id); - dma_unmap_single(ar->ab->dev, buff->paddr, - ring->buf_sz, DMA_FROM_DEVICE); -+ kfree(buff->payload); - kfree(buff); +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -5334,10 +5334,12 @@ static int ath12k_mac_station_add(struct + goto exit; } -diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c -index 6166ea4..32a2f8f 100644 ---- a/drivers/net/wireless/ath/ath12k/dp.c -+++ b/drivers/net/wireless/ath/ath12k/dp.c -@@ -1124,8 +1124,6 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab) - struct sk_buff *skb; - int i; +- arsta->rx_stats = kzalloc(sizeof(*arsta->rx_stats), GFP_KERNEL); + if (!arsta->rx_stats) { +- ret = -ENOMEM; +- goto dec_num_station; ++ arsta->rx_stats = kzalloc(sizeof(*arsta->rx_stats), GFP_KERNEL); ++ if (!arsta->rx_stats) { ++ ret = -ENOMEM; ++ goto dec_num_station; ++ } + } -- return; -- - if (!dp->spt_info) - return; + peer_param.vdev_id = arvif->vdev_id; +@@ -5354,8 +5356,9 @@ static int ath12k_mac_station_add(struct + ath12k_dbg(ab, ATH12K_DBG_MAC, "Added peer: %pM for VDEV: %d\n", + sta->addr, arvif->vdev_id); --- -2.17.1 - +- if (ath12k_debugfs_is_extd_tx_stats_enabled(ar)) { +- arsta->tx_stats = kzalloc(sizeof(*arsta->tx_stats), GFP_KERNEL); ++ if (ath12k_debugfs_is_extd_tx_stats_enabled(ar) && (!arsta->tx_stats)) { ++ arsta->tx_stats = kzalloc(sizeof(*arsta->tx_stats), ++ GFP_KERNEL); + if (!arsta->tx_stats) { + ret = -ENOMEM; + goto free_peer; diff --git a/feeds/ipq95xx/mac80211/patches/qca/657-ath12k-add-module-param-to-enable-disable-MLO.patch b/feeds/ipq95xx/mac80211/patches/qca/657-ath12k-add-module-param-to-enable-disable-MLO.patch index 7365bd82c..2ae6ecee6 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/657-ath12k-add-module-param-to-enable-disable-MLO.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/657-ath12k-add-module-param-to-enable-disable-MLO.patch @@ -8,22 +8,20 @@ Signed-off-by: Karthikeyan Periyasamy drivers/net/wireless/ath/ath12k/core.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c -index 7ffb03c168ba..4fd41b1af8be 100644 --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c -@@ -31,6 +31,10 @@ module_param_named(frame_mode, ath12k_frame_mode, uint, 0644); +@@ -31,6 +31,10 @@ module_param_named(frame_mode, ath12k_fr MODULE_PARM_DESC(frame_mode, "Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)"); -+static unsigned int ath12k_mlo_capable = false; ++unsigned int ath12k_mlo_capable = true; +module_param_named(mlo_capable, ath12k_mlo_capable, uint, 0644); +MODULE_PARM_DESC(mlo_capable, "mlo capable: 0-disable, 1-enable"); + static DEFINE_MUTEX(ath12k_hw_lock); static struct list_head ath12k_hw_groups = LIST_HEAD_INIT(ath12k_hw_groups); -@@ -159,7 +163,7 @@ ath12k_core_hw_group_alloc(u8 id, u8 max_chip) +@@ -126,14 +130,14 @@ ath12k_core_hw_group_alloc(u8 id, u8 max static struct ath12k_hw_group *ath12k_core_get_hw_group(struct ath12k_base *ab) { struct ath12k_hw_group *ag = NULL; @@ -32,29 +30,45 @@ index 7ffb03c168ba..4fd41b1af8be 100644 struct device *dev = ab->dev; u32 group_id, num_chips; int ret; -@@ -171,7 +175,11 @@ static struct ath12k_hw_group *ath12k_core_get_hw_group(struct ath12k_base *ab) + + lockdep_assert_held(&ath12k_hw_lock); + +- /* If there is no grouping info in the dt, we don't enalbe ++ /* If there is no grouping info in the dt, we don't enable + * multi soc hw grouping and registration, rather the single * soc is added to hw group and based on the number of links * within the soc, all links are combined into a single wiphy. - */ -- mlo = of_parse_phandle(dev->of_node, "qcom,wsi", 0); -+ if (ath12k_mlo_capable) -+ mlo = of_parse_phandle(dev->of_node, "qcom,wsi", 0); -+ else -+ mlo = NULL; -+ - if (!mlo) { - group_id = ATH12K_INVALID_GRP_ID; - } else { -@@ -182,7 +190,8 @@ static struct ath12k_hw_group *ath12k_core_get_hw_group(struct ath12k_base *ab) - - again: - if (group_id == ATH12K_INVALID_GRP_ID) { -- ath12k_info(ab, "Grouping of multiple SoC not done\n"); -+ ath12k_info(ab, "Grouping of multiple SoC not done. mlo capable %d\n", -+ ath12k_mlo_capable); - - ag = ath12k_core_hw_group_alloc(group_id, 1); - } else { --- -2.37.0 +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -40,6 +40,7 @@ + #define ATH12K_RX_RATE_TABLE_11AX_NUM 576 + extern unsigned int ath12k_frame_mode; ++extern unsigned int ath12k_mlo_capable; + + #define ATH12K_MON_TIMER_INTERVAL 10 + #define ATH12K_RESET_TIMEOUT_HZ (20 * HZ) +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -11242,15 +11242,14 @@ int ath12k_mac_allocate(struct ath12k_hw + for (i = 0; i < ag->num_chip; i++) + total_radio += ag->ab[i]->num_radios; + +- /* Each pdev get register separately in the default +- * (ATH12K_INVALID_GRP_ID) group. +- * where as in other group, all pdev get combined in +- * register as single wiphy. ++ /* All pdev get combined and register as single wiphy in the non-invalid ++ * group where also multi-link is enabled. where as in other group, ++ * each pdev get register separately. + */ +- if (ag->id == ATH12K_INVALID_GRP_ID) +- num_radios = 1; +- else ++ if (ag->id != ATH12K_INVALID_GRP_ID && ath12k_mlo_capable) + num_radios = total_radio; ++ else ++ num_radios = 1; + + num_hw = total_radio / num_radios; + diff --git a/feeds/ipq95xx/mac80211/patches/qca/657-mac80211-Avoid-encapsulation-of-EAPOL-frames-if-OFFL.patch b/feeds/ipq95xx/mac80211/patches/qca/657-mac80211-Avoid-encapsulation-of-EAPOL-frames-if-OFFL.patch index 095fb45ea..ac675022b 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/657-mac80211-Avoid-encapsulation-of-EAPOL-frames-if-OFFL.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/657-mac80211-Avoid-encapsulation-of-EAPOL-frames-if-OFFL.patch @@ -18,11 +18,9 @@ Signed-off-by: Aaradhana Sahu net/mac80211/tx.c | 58 ++++++++++++++++++++++++++------------ 2 files changed, 45 insertions(+), 18 deletions(-) -diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h -index 055ef3d..960ee88 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h -@@ -2004,6 +2004,11 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, +@@ -1985,6 +1985,11 @@ netdev_tx_t ieee80211_subif_start_xmit(s struct net_device *dev); netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb, struct net_device *dev); @@ -34,11 +32,9 @@ index 055ef3d..960ee88 100644 void __ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev, u32 info_flags, -diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c -index c1c33d1..a02ee4d 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c -@@ -39,7 +39,8 @@ +@@ -38,7 +38,8 @@ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata, struct net_device *dev, struct sta_info *sta, @@ -48,7 +44,7 @@ index c1c33d1..a02ee4d 100644 static inline void ieee80211_tx_stats(struct net_device *dev, u32 len) { -@@ -4342,7 +4343,7 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, +@@ -4317,7 +4318,7 @@ void __ieee80211_subif_start_xmit(struct !is_multicast_ether_addr(skb->data)) { if (sta) key = rcu_dereference(sta->ptk[sta->ptk_idx]); @@ -57,7 +53,7 @@ index c1c33d1..a02ee4d 100644 rcu_read_unlock(); return; } -@@ -4412,7 +4413,7 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, +@@ -4387,7 +4388,7 @@ void __ieee80211_subif_start_xmit(struct if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) { if (sta) key = rcu_dereference(sta->ptk[sta->ptk_idx]); @@ -66,7 +62,7 @@ index c1c33d1..a02ee4d 100644 } else { ieee80211_tx_stats(dev, skb->len); ieee80211_xmit(sdata, sta, skb); -@@ -4647,7 +4648,8 @@ static bool ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata, +@@ -4672,7 +4673,8 @@ static bool ieee80211_tx_8023(struct iee static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata, struct net_device *dev, struct sta_info *sta, @@ -74,26 +70,26 @@ index c1c33d1..a02ee4d 100644 + struct ieee80211_key *key, struct sk_buff *skb, + u32 info_flags, u32 ctrl_flags, u64 *cookie) { - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_tx_info *info; struct ethhdr *ehdr = (struct ethhdr *)skb->data; -@@ -4674,7 +4676,7 @@ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata, - goto out_free; +@@ -4704,7 +4706,7 @@ static void ieee80211_8023_xmit(struct i + info = IEEE80211_SKB_CB(skb); memset(info, 0, sizeof(*info)); - + info->flags |= info_flags; ieee80211_aggr_check(sdata, sta, skb); - tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; -@@ -4692,11 +4694,12 @@ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata, - tid_tx->last_tx = jiffies; + if (!ieee80211_hw_check(&local->hw, SUPPORTS_NSS_OFFLOAD) && sta) { +@@ -4725,11 +4727,12 @@ static void ieee80211_8023_xmit(struct i } } + - if (unlikely(skb->sk && - skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS && + if (unlikely(((skb->sk && -+ skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS) || -+ ((ctrl_flags & IEEE80211_TX_CTL_REQ_TX_STATUS) && !multicast)) && ++ skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS) || ++ ((ctrl_flags & IEEE80211_TX_CTL_REQ_TX_STATUS) && !multicast)) && !ieee80211_hw_check(&local->hw, SUPPORTS_NSS_OFFLOAD))) info->ack_frame_id = ieee80211_store_ack_skb(local, skb, - &info->flags, NULL); @@ -101,7 +97,7 @@ index c1c33d1..a02ee4d 100644 info->hw_queue = sdata->vif.hw_queue[skb_get_queue_mapping(skb)]; -@@ -4731,7 +4734,8 @@ out_free: +@@ -4764,7 +4767,8 @@ out_free: void ieee80211_8023_xmit_ap(struct ieee80211_sub_if_data *sdata, struct net_device *dev, struct sta_info *sta, @@ -109,9 +105,9 @@ index c1c33d1..a02ee4d 100644 + struct ieee80211_key *key, struct sk_buff *skb, + u32 info_flags, u32 ctrl_flags, u64 *cookie) { - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_tx_info *info; struct ieee80211_local *local = sdata->local; -@@ -4740,13 +4744,18 @@ void ieee80211_8023_xmit_ap(struct ieee80211_sub_if_data *sdata, +@@ -4773,6 +4777,9 @@ void ieee80211_8023_xmit_ap(struct ieee8 unsigned long flags; int q; u16 q_map; @@ -119,6 +115,11 @@ index c1c33d1..a02ee4d 100644 + unsigned char *ra = ehdr->h_dest; + bool multicast = is_multicast_ether_addr(ra); + /* + * If the skb is shared we need to obtain our own copy. +@@ -4784,11 +4791,13 @@ void ieee80211_8023_xmit_ap(struct ieee8 + + info = IEEE80211_SKB_CB(skb); memset(info, 0, sizeof(*info)); + info->flags |= info_flags; @@ -133,14 +134,14 @@ index c1c33d1..a02ee4d 100644 info->flags |= IEEE80211_TX_CTL_HW_80211_ENCAP; info->control.vif = &sdata->vif; -@@ -4785,14 +4794,23 @@ void ieee80211_8023_xmit_ap(struct ieee80211_sub_if_data *sdata, +@@ -4827,14 +4836,23 @@ void ieee80211_8023_xmit_ap(struct ieee8 if (sta) atomic_inc(&sta->tx_drv_pkts); } - netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb, struct net_device *dev) -+{ + { + return __ieee80211_subif_start_xmit_8023(skb, dev, 0, 0, NULL); +} + @@ -149,7 +150,7 @@ index c1c33d1..a02ee4d 100644 + u32 info_flags, + u32 ctrl_flags, + u64 *cookie) - { ++{ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ethhdr *ehdr = (struct ethhdr *)skb->data; struct ieee80211_key *key = NULL; @@ -158,7 +159,7 @@ index c1c33d1..a02ee4d 100644 #ifdef CPTCFG_MAC80211_NSS_SUPPORT ieee80211_xmit_nss_fixup(skb, dev); -@@ -4808,14 +4826,15 @@ netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb, +@@ -4850,14 +4868,15 @@ netdev_tx_t ieee80211_subif_start_xmit_8 kfree_skb(skb); goto out; } @@ -176,7 +177,7 @@ index c1c33d1..a02ee4d 100644 goto skip_offload; key = rcu_dereference(sta->ptk[sta->ptk_idx]); -@@ -4826,12 +4845,12 @@ netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb, +@@ -4868,12 +4887,12 @@ netdev_tx_t ieee80211_subif_start_xmit_8 goto skip_offload; if (sdata->vif.type == NL80211_IFTYPE_AP) { @@ -191,7 +192,7 @@ index c1c33d1..a02ee4d 100644 goto out; skip_offload: -@@ -6243,7 +6262,10 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev, +@@ -6364,7 +6383,10 @@ int ieee80211_tx_control_port(struct wip mutex_lock(&local->mtx); local_bh_disable(); @@ -203,6 +204,3 @@ index c1c33d1..a02ee4d 100644 local_bh_enable(); mutex_unlock(&local->mtx); --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/658-ath12k-move-info-print-to-dbg-print.patch b/feeds/ipq95xx/mac80211/patches/qca/658-ath12k-move-info-print-to-dbg-print.patch deleted file mode 100644 index 5e13b672c..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/658-ath12k-move-info-print-to-dbg-print.patch +++ /dev/null @@ -1,32 +0,0 @@ -From bbe2c737eb2b62035424552822bc13be532927e3 Mon Sep 17 00:00:00 2001 -From: Aaradhana Sahu -Date: Wed, 10 Aug 2022 13:15:45 +0530 -Subject: [PATCH] ath12k: move info print to dbg print - -This patch moves unwanted "ath12k: tx queue params cached since -vif is not assigned" warning to debug as this may affect debugging - -So, moved ath12k info print to ath12k dbg print - -Signed-off-by: Aaradhana Sahu ---- - drivers/net/wireless/ath/ath12k/mac.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index f119e8f..04552a5 100644 ---- a/drivers/net/wireless/ath/ath12k/mac.c -+++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -5671,7 +5671,8 @@ static int ath12k_mac_op_conf_tx(struct ieee80211_hw *hw, - */ - mutex_lock(&ah->conf_mutex); - if (!arvif->is_created) { -- ath12k_info(NULL, "tx queue params cached since vif is not assigned to radio\n"); -+ ath12k_dbg(NULL, ATH12K_DBG_MAC, -+ "tx queue params cached since vif is not assigned to radio\n"); - arvif->cache.tx_conf.changed = true; - arvif->cache.tx_conf.ac = ac; - arvif->cache.tx_conf.tx_queue_params = *params; --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/660-ath12k-Account-correct-segment-count-in-coreudmp.patch b/feeds/ipq95xx/mac80211/patches/qca/660-ath12k-Account-correct-segment-count-in-coreudmp.patch index 5a0bd05f7..34b25ca6b 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/660-ath12k-Account-correct-segment-count-in-coreudmp.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/660-ath12k-Account-correct-segment-count-in-coreudmp.patch @@ -21,7 +21,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor ab->qmi.target_mem[i].type == CALDB_MEM_REGION_TYPE || - ab->qmi.target_mem[i].type == M3_DUMP_REGION_TYPE) + ab->qmi.target_mem[i].type == M3_DUMP_REGION_TYPE || -+ ab->qmi.target_mem[i].type == PAGEABLE_MEM_TYPE) ++ ab->qmi.target_mem[i].type == PAGEABLE_MEM_REGION_TYPE) rem_seg_cnt++; } diff --git a/feeds/ipq95xx/mac80211/patches/qca/660-ath12k-Fix-vdev-restart-start-sequence-during-channe.patch b/feeds/ipq95xx/mac80211/patches/qca/660-ath12k-Fix-vdev-restart-start-sequence-during-channe.patch index 7b89dc68c..62a1bcab9 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/660-ath12k-Fix-vdev-restart-start-sequence-during-channe.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/660-ath12k-Fix-vdev-restart-start-sequence-during-channe.patch @@ -27,11 +27,9 @@ other non transmitting vif. Signed-off-by: Aditya Kumar Singh Signed-off-by: Ramya Gnanasekar -Index: b/drivers/net/wireless/ath/ath12k/mac.c -=================================================================== ---- a/drivers/net/wireless/ath/ath12k/mac.c 2022-09-28 16:39:16.191003380 +0530 -+++ b/drivers/net/wireless/ath/ath12k/mac.c 2022-09-28 16:40:07.986577249 +0530 -@@ -897,8 +897,10 @@ static inline int ath12k_mac_vdev_setup_ +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -897,8 +897,10 @@ static int ath12k_mac_vdev_setup_sync(st ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "ath12k vdev setup timeout %d\n", ATH12K_VDEV_SETUP_TIMEOUT_HZ); if (!wait_for_completion_timeout(&ar->vdev_setup_done, @@ -43,14 +41,15 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c return ar->last_wmi_vdev_start_status ? -EINVAL : 0; } -@@ -8098,9 +8100,88 @@ static int ath12k_mac_vdev_start(struct +@@ -8175,9 +8177,88 @@ static int ath12k_mac_vdev_start(struct } static int ath12k_mac_vdev_restart(struct ath12k_vif *arvif, - const struct cfg80211_chan_def *chandef) + const struct cfg80211_chan_def *chandef, + bool pseudo_restart) -+{ + { +- return ath12k_mac_vdev_start_restart(arvif, chandef, true); + struct ath12k_base *ab = arvif->ar->ab; + int ret; + @@ -78,8 +77,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c + struct ieee80211_chanctx_conf *new_ctx, + u64 vif_down_failed_map, + int vdev_index) - { -- return ath12k_mac_vdev_start_restart(arvif, chandef, true); ++{ + struct ath12k *ar = arvif->ar; + struct ath12k_vif *tx_arvif; + struct ieee80211_chanctx_conf old_chanctx; @@ -134,7 +132,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c } struct ath12k_mac_change_chanctx_arg { -@@ -8225,19 +8306,23 @@ ath12k_mac_update_vif_chan(struct ath12k +@@ -8302,19 +8383,23 @@ ath12k_mac_update_vif_chan(struct ath12k struct ath12k_vif *arvif, *tx_arvif; struct cfg80211_chan_def *chandef = NULL; int ret; @@ -165,7 +163,7 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c arvif = (void *)vifs[i].vif->drv_priv; if (vifs[i].vif->type == NL80211_IFTYPE_MONITOR) -@@ -8254,46 +8339,64 @@ ath12k_mac_update_vif_chan(struct ath12k +@@ -8331,41 +8416,56 @@ ath12k_mac_update_vif_chan(struct ath12k if (WARN_ON(!arvif->is_started)) continue; @@ -175,15 +173,15 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c - spin_unlock_bh(&ar->data_lock); + if (!arvif->is_up) + continue; - -- ret = ath12k_mac_vdev_restart(arvif, &vifs[i].new_ctx->def); ++ + if (arvif->vif->mbssid_tx_vif && + arvif == (struct ath12k_vif *)arvif->vif->mbssid_tx_vif->drv_priv) { + tx_vif = arvif->vif->mbssid_tx_vif; + tx_arvif = ath12k_vif_to_arvif(tx_vif); + trans_vdev_index = i; + } -+ + +- ret = ath12k_mac_vdev_restart(arvif, &vifs[i].new_ctx->def); + ret = ath12k_wmi_vdev_down(ar, arvif->vdev_id); if (ret) { - ath12k_warn(ab, "failed to restart vdev %d: %d\n", @@ -200,33 +198,21 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c - if (WARN_ON(!arvif->is_up)) - continue; + chandef = &vifs[0].new_ctx->def; - -- ret = ath12k_mac_setup_bcn_tmpl(arvif); -- if (ret) -- ath12k_warn(ab, "failed to update bcn tmpl during csa: %d\n", -- ret); ++ + ath12k_mac_update_rx_channel(ar, NULL, vifs, n_vifs); - -- params.vdev_id = arvif->vdev_id; -- params.aid = arvif->aid; -- params.bssid = arvif->bssid; -- if (arvif->vif->mbssid_tx_vif) { -- tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv; -- params.tx_bssid = tx_arvif->bssid; -- params.profile_idx = arvif->vif->bss_conf.bssid_index; -- params.profile_count = tx_arvif->nontransmitting_vif_count; ++ + if (tx_arvif) { + ret = ath12k_vdev_restart_sequence(tx_arvif, + vifs[trans_vdev_index].new_ctx, + vif_down_failed_map, + trans_vdev_index); -+ -+ if (ret) { + +- ret = ath12k_mac_setup_bcn_tmpl(arvif); + if (ret) +- ath12k_warn(ab, "failed to update bcn tmpl during csa: %d\n", +- ret); + ath12k_warn(ab, "failed to restart vdev:%d: %d\n", + tx_arvif->vdev_id, ret); -+ goto restart_fail; - } -- ret = ath12k_wmi_vdev_up(arvif->ar, ¶ms); + } + + for (i = 0; i < n_vifs; i++) { @@ -242,24 +228,26 @@ Index: b/drivers/net/wireless/ath/ath12k/mac.c + ret = ath12k_vdev_restart_sequence(arvif, + vifs[i].new_ctx, + vif_down_failed_map, i); -+ + +- params.vdev_id = arvif->vdev_id; +- params.aid = arvif->aid; +- params.bssid = arvif->bssid; +- if (arvif->vif->mbssid_tx_vif) { +- tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv; +- params.tx_bssid = tx_arvif->bssid; +- params.profile_idx = arvif->vif->bss_conf.bssid_index; +- params.profile_count = tx_arvif->nontransmitting_vif_count; +- } +- ret = ath12k_wmi_vdev_up(arvif->ar, ¶ms); if (ret) { - ath12k_warn(ab, "failed to bring vdev up %d: %d\n", + ath12k_warn(ab, "failed to bring up vdev %d: %d\n", arvif->vdev_id, ret); continue; } - } - -+restart_fail: - /* Restart the internal monitor vdev on new channel */ - if (!monitor_vif && - test_bit(MONITOR_VDEV_CREATED, &ar->monitor_flags)) { -Index: b/drivers/net/wireless/ath/ath12k/wmi.h -=================================================================== ---- a/drivers/net/wireless/ath/ath12k/wmi.h 2022-09-28 16:39:16.191003380 +0530 -+++ b/drivers/net/wireless/ath/ath12k/wmi.h 2022-09-28 16:39:16.187003413 +0530 -@@ -2810,7 +2810,7 @@ struct wmi_ssid { +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -2805,7 +2805,7 @@ struct wmi_ssid { u32 ssid[8]; } __packed; @@ -267,4 +255,4 @@ Index: b/drivers/net/wireless/ath/ath12k/wmi.h +#define ATH12K_VDEV_SETUP_TIMEOUT_HZ (10 * HZ) struct wmi_vdev_start_request_cmd { - u32 tlv_header; + __le32 tlv_header; diff --git a/feeds/ipq95xx/mac80211/patches/qca/661-002-ath12k-Introduced-module-param-for-enabling-fwlog.patch b/feeds/ipq95xx/mac80211/patches/qca/661-002-ath12k-Introduced-module-param-for-enabling-fwlog.patch index 04bbadc3b..036105488 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/661-002-ath12k-Introduced-module-param-for-enabling-fwlog.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/661-002-ath12k-Introduced-module-param-for-enabling-fwlog.patch @@ -14,7 +14,7 @@ Signed-off-by: Balamurugan Selvarajan --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c -@@ -35,6 +35,10 @@ unsigned int ath12k_mlo_capable = false; +@@ -35,6 +35,10 @@ unsigned int ath12k_mlo_capable = true; module_param_named(mlo_capable, ath12k_mlo_capable, uint, 0644); MODULE_PARM_DESC(mlo_capable, "mlo capable: 0-disable, 1-enable"); diff --git a/feeds/ipq95xx/mac80211/patches/qca/661-ath12k-Add-TPC-stats-support.patch b/feeds/ipq95xx/mac80211/patches/qca/661-ath12k-Add-TPC-stats-support.patch index e039a755a..1e309ab77 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/661-ath12k-Add-TPC-stats-support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/661-ath12k-Add-TPC-stats-support.patch @@ -62,10 +62,8 @@ Signed-off-by: Sivashankari Madhavan drivers/net/wireless/ath/ath12k/wmi.h | 249 +++++++- 5 files changed, 1525 insertions(+), 2 deletions(-) -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/core.h -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.h +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h @@ -68,8 +68,9 @@ enum wme_ac { }; @@ -77,10 +75,10 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor #define ATH12K_EHT_MCS_MAX 15 enum ath12k_crypt_mode { -@@ -782,6 +783,12 @@ struct ath12k { +@@ -784,6 +785,12 @@ struct ath12k { struct cfg80211_chan_def awgn_chandef; - u32 chan_bw_interference_bitmap; - bool awgn_intf_handling_in_prog; + u32 chan_bw_interference_bitmap; + bool awgn_intf_handling_in_prog; + + u8 tpc_stats_type; + /* tpc_stats ptr is protected by data lock */ @@ -90,11 +88,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor }; struct ath12k_band_cap { -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/debugfs.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs.c -@@ -1511,6 +1511,741 @@ static const struct file_operations fops +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -1327,6 +1327,741 @@ static const struct file_operations fops .open = simple_open }; @@ -297,7 +293,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb +u16 ath12k_get_ratecode(u16 pream_idx, u16 nss, u16 mcs_rate) +{ + u16 mode_type = ~0; -+ ++ + /* Below assignments are just for printing purpose only */ + switch (pream_idx) { + case WMI_TPC_PREAM_CCK: @@ -342,7 +338,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb + default: + return mode_type; + } -+ ++ + return ((mode_type << 8) | ((nss & 0x7) << 5) | (mcs_rate & 0x1F)); +} + @@ -556,11 +552,11 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb + for (i = WMI_TPC_PREAM_HE20; i <= WMI_TPC_PREAM_HE160; ++i) + max_rates[i] = ATH12K_HE_RATES_WITH_EXTRA_MCS; + } -+ ++ + if (type == ATH12K_DBG_TPC_STATS_MU || + type == ATH12K_DBG_TPC_STATS_MU_WITH_TXBF) { + pream_idx = WMI_TPC_PREAM_VHT20; -+ ++ + for (i = WMI_TPC_PREAM_CCK; i <= WMI_TPC_PREAM_HT40; ++i) { + max_rix += max_nss[i] * max_rates[i]; + } @@ -570,9 +566,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb + for (i = rate_pream_idx + 1 ; i < WMI_TPC_PREAM_MAX; i++) { + nss = (max_nss[i - 1] < tpc_stats->tpc_config.num_tx_chain ? + max_nss[i - 1] : tpc_stats->tpc_config.num_tx_chain); -+ ++ + rate_idx[i] = rate_idx[i - 1] + max_rates[i - 1] * nss; -+ ++ + if (pream_type[i] == WMI_RATE_PREAMBLE_EHT) { + eht_rate_idx[j] = eht_rate_idx[j - 1] + max_rates[i] * nss; + /*For Filling the next eht_rate_idx for fetch rates pwr info rates array2*/ @@ -621,9 +617,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb + continue; + } + } -+ ++ + nss = (max_nss[i] < ar->num_tx_chains ? max_nss[i] : ar->num_tx_chains); -+ ++ + if (!(tpc_stats->tpc_config.caps & (1 << ATH12K_TPC_STATS_SUPPORT_BE_PUNC))) { + if (i == WMI_TPC_PREAM_EHT60 || i == WMI_TPC_PREAM_EHT120 || + i == WMI_TPC_PREAM_EHT140 || i == WMI_TPC_PREAM_EHT200 || @@ -836,7 +832,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb static ssize_t ath12k_write_simulate_awgn(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) -@@ -1731,6 +2466,8 @@ int ath12k_debugfs_register(struct ath12 +@@ -1384,6 +2119,8 @@ int ath12k_debugfs_register(struct ath12 ath12k_debugfs_fw_stats_init(ar); ath12k_init_pktlog(ar); @@ -845,10 +841,10 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb debugfs_create_file("ext_tx_stats", 0644, ar->debug.debugfs_pdev, ar, &fops_extd_tx_stats); -@@ -1763,6 +2500,15 @@ int ath12k_debugfs_register(struct ath12 - debugfs_create_file("enable_m3_dump", 0644, - ar->debug.debugfs_pdev, ar, - &fops_enable_m3_dump); +@@ -1409,6 +2146,15 @@ int ath12k_debugfs_register(struct ath12 + &fops_simulate_awgn); + } + + + debugfs_create_file("tpc_stats", 0400, + ar->debug.debugfs_pdev, ar, @@ -857,14 +853,12 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb + debugfs_create_file("tpc_stats_type", 0600, + ar->debug.debugfs_pdev, ar, + &fops_tpc_stats_type); -+ ++ return 0; } -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/debugfs.h -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs.h +--- a/drivers/net/wireless/ath/ath12k/debugfs.h ++++ b/drivers/net/wireless/ath/ath12k/debugfs.h @@ -63,6 +63,67 @@ enum ath12k_dbg_htt_ext_stats_type { ATH12K_DBG_HTT_NUM_EXT_STATS, }; @@ -933,22 +927,18 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb struct debug_htt_stats_req { bool done; bool override_cfg_param; -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/wmi.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi.c -@@ -83,6 +83,10 @@ static const struct wmi_tlv_policy wmi_t - = { .min_len = 0 }, - [WMI_TAG_ARRAY_UINT32] - = { .min_len = 0 }, -+ [WMI_TAG_ARRAY_STRUCT] -+ = { .min_len = 0 }, -+ [WMI_TAG_ARRAY_INT16] -+ = { .min_len = 0 }, - [WMI_TAG_SERVICE_READY_EVENT] - = { .min_len = sizeof(struct wmi_service_ready_event) }, - [WMI_TAG_SERVICE_READY_EXT_EVENT] -@@ -139,6 +143,8 @@ static const struct wmi_tlv_policy wmi_t +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -81,6 +81,8 @@ struct wmi_tlv_dma_buf_release_parse { + static const struct wmi_tlv_policy wmi_tlv_policies[] = { + [WMI_TAG_ARRAY_BYTE] = { .min_len = 0 }, + [WMI_TAG_ARRAY_UINT32] = { .min_len = 0 }, ++ [WMI_TAG_ARRAY_STRUCT] = { .min_len = 0 }, ++ [WMI_TAG_ARRAY_INT16] = { .min_len = 0 }, + [WMI_TAG_SERVICE_READY_EVENT] = { + .min_len = sizeof(struct wmi_service_ready_event) }, + [WMI_TAG_SERVICE_READY_EXT_EVENT] = { +@@ -137,6 +139,8 @@ static const struct wmi_tlv_policy wmi_t .min_len = sizeof(struct wmi_twt_add_dialog_event) }, [WMI_TAG_OBSS_COLOR_COLLISION_EVT] = { .min_len = sizeof(struct wmi_obss_color_collision_event) }, @@ -956,8 +946,8 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi + = { .min_len = sizeof(struct wmi_cp_stats_event_fixed_param) }, }; - static void ath12k_init_wmi_config_qcn92xx(struct ath12k_base *ab, -@@ -8270,6 +8276,459 @@ static void ath12k_wmi_event_wow_wakeup_ + static __le32 ath12k_wmi_tlv_hdr(u32 cmd, u32 len) +@@ -8305,6 +8309,459 @@ static void ath12k_wmi_event_wow_wakeup_ complete(&ab->wow.wakeup_completed); } @@ -987,9 +977,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi + "Total size and reg_array_len doesn't match for tpc stats\n"); + return -EINVAL; + } -+ ++ + memcpy(®_pwr->tpc_reg_pwr, ev, sizeof(struct wmi_max_reg_power_fixed_param)); -+ ++ + reg_pwr->reg_pwr_array = kzalloc(reg_pwr->tpc_reg_pwr.reg_array_len, + GFP_ATOMIC); + if (!reg_pwr->reg_pwr_array) @@ -1064,9 +1054,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi + "Total size and ctl_array_len doesn't match for tpc stats\n"); + return -EINVAL; + } -+ ++ + memcpy(&ctl_array->tpc_ctl_pwr, ev, sizeof(struct wmi_tpc_ctl_pwr_fixed_param)); -+ ++ + ctl_array->ctl_pwr_table = kzalloc(ctl_array->tpc_ctl_pwr.ctl_array_len, + GFP_ATOMIC); + if (!ctl_array->ctl_pwr_table) @@ -1376,22 +1366,22 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi + void *ptr; + u32 *pdev_ids, buf_len; + int ret; -+ ++ + buf_len = sizeof(*cmd) + sizeof(u32) + TLV_HDR_SIZE; -+ ++ + skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, buf_len); + if (!skb) + return -ENOMEM; + cmd = (struct wmi_request_ctrl_path_stats_cmd_fixed_param *)skb->data; + cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_CTRL_PATH_CMD_FIXED_PARAM) | + FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); -+ ++ + cmd->stats_id_mask = WMI_REQ_CTRL_PATH_PDEV_TX_STAT; + cmd->action = WMI_REQUEST_CTRL_PATH_STAT_GET; + cmd->subid = ar->tpc_stats_type; -+ ++ + ptr = skb->data + sizeof(*cmd); -+ ++ + tlv = ptr; + tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_UINT32) | + FIELD_PREP(WMI_TLV_LEN, sizeof(u32)); @@ -1417,7 +1407,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi static void ath12k_wmi_diag_event(struct ath12k_base *ab, struct sk_buff *skb) { const struct wmi_tlv *tlv; -@@ -8657,6 +9116,9 @@ static void ath12k_wmi_tlv_op_rx(struct +@@ -8691,6 +9148,9 @@ static void ath12k_wmi_tlv_op_rx(struct case WMI_OBSS_COLOR_COLLISION_DETECTION_EVENTID: ath12k_wmi_obss_color_collision_event(ab, skb); break; @@ -1427,11 +1417,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi /* TODO: Add remaining events */ default: ath12k_dbg(ab, ATH12K_DBG_WMI, "Unknown eventid: 0x%x\n", id); -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/wmi.h -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi.h -@@ -295,6 +295,7 @@ enum wmi_tlv_cmd_id { +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -282,6 +282,7 @@ enum wmi_tlv_cmd_id { WMI_PDEV_SET_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID, WMI_PDEV_SET_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID, WMI_PDEV_SET_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID, @@ -1439,7 +1427,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi WMI_VDEV_CREATE_CMDID = WMI_TLV_CMD(WMI_GRP_VDEV), WMI_VDEV_DELETE_CMDID, WMI_VDEV_START_REQUEST_CMDID, -@@ -483,6 +484,11 @@ enum wmi_tlv_cmd_id { +@@ -470,6 +471,11 @@ enum wmi_tlv_cmd_id { WMI_REQUEST_RCPI_CMDID, WMI_REQUEST_PEER_STATS_INFO_CMDID, WMI_REQUEST_RADIO_CHAN_STATS_CMDID, @@ -1451,7 +1439,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi WMI_SET_ARP_NS_OFFLOAD_CMDID = WMI_TLV_CMD(WMI_GRP_ARP_NS_OFL), WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMDID, WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMDID, -@@ -753,6 +759,9 @@ enum wmi_tlv_event_id { +@@ -740,6 +746,9 @@ enum wmi_tlv_event_id { WMI_UPDATE_RCPI_EVENTID, WMI_PEER_STATS_INFO_EVENTID, WMI_RADIO_CHAN_STATS_EVENTID, @@ -1461,7 +1449,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi WMI_NLO_MATCH_EVENTID = WMI_TLV_CMD(WMI_GRP_NLO_OFL), WMI_NLO_SCAN_COMPLETE_EVENTID, WMI_APFIND_EVENTID, -@@ -1164,6 +1173,7 @@ enum wmi_tlv_tag { +@@ -1151,6 +1160,7 @@ enum wmi_tlv_tag { WMI_TAG_ARRAY_BYTE, WMI_TAG_ARRAY_STRUCT, WMI_TAG_ARRAY_FIXED_STRUCT, @@ -1469,7 +1457,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi WMI_TAG_LAST_ARRAY_ENUM = 31, WMI_TAG_SERVICE_READY_EVENT, WMI_TAG_HAL_REG_CAPABILITIES, -@@ -1926,6 +1936,14 @@ enum wmi_tlv_tag { +@@ -1913,6 +1923,14 @@ enum wmi_tlv_tag { WMI_TAG_EHT_RATE_SET = 0x3C4, WMI_TAG_DCS_AWGN_INT_TYPE = 0x3C5, WMI_TAG_PDEV_PKTLOG_DECODE_INFO = 0x414, @@ -1484,7 +1472,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi WMI_TAG_MAX }; -@@ -5759,6 +5777,234 @@ struct target_resource_config { +@@ -5679,6 +5697,234 @@ struct target_resource_config { u32 ema_max_profile_period; }; @@ -1716,10 +1704,10 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi + WMI_REQ_CTRL_PATH_BTCOEX_STAT = 8, +}; + - struct wmi_ops { - void (*wmi_init_config)(struct ath12k_base *ab, - struct target_resource_config *config); -@@ -6122,5 +6368,6 @@ int ath12k_wmi_send_vdev_set_tpc_power(s + enum wmi_dblog_param { + WMI_DEBUG_LOG_PARAM_LOG_LEVEL = 0x1, + WMI_DEBUG_LOG_PARAM_VDEV_ENABLE, +@@ -6047,5 +6293,6 @@ int ath12k_wmi_send_vdev_set_tpc_power(s u32 vdev_id, struct ath12k_reg_tpc_power_info *param); int ath12k_wmi_pdev_m3_dump_enable(struct ath12k *ar, u32 enable); diff --git a/feeds/ipq95xx/mac80211/patches/qca/661-ath12k-add-length-validation-before-skb_put-call.patch b/feeds/ipq95xx/mac80211/patches/qca/661-ath12k-add-length-validation-before-skb_put-call.patch index 778f2aaf9..f6b7f5722 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/661-ath12k-add-length-validation-before-skb_put-call.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/661-ath12k-add-length-validation-before-skb_put-call.patch @@ -64,8 +64,6 @@ Signed-off-by: P Praneesh drivers/net/wireless/ath/ath12k/dp_rx.c | 28 +++++++++++++++++++++------- 3 files changed, 29 insertions(+), 11 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h -index 80754e0..d14714e 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -890,7 +890,9 @@ struct ath12k_soc_dp_stats { @@ -76,13 +74,11 @@ index 80754e0..d14714e 100644 u32 reo_error[HAL_REO_DEST_RING_ERROR_CODE_MAX]; + u32 reo_error_drop[HAL_REO_DEST_RING_ERROR_CODE_MAX]; u32 hal_reo_error[DP_REO_DST_RING_MAX]; - u32 mon_drop_desc; struct ath12k_soc_dp_tx_err_stats tx_err; -diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c -index c3d1962..a40168b 100644 + struct ath12k_dp_ring_bp_stats bp_stats; --- a/drivers/net/wireless/ath/ath12k/debugfs.c +++ b/drivers/net/wireless/ath/ath12k/debugfs.c -@@ -840,13 +840,15 @@ static ssize_t ath12k_debugfs_dump_soc_dp_stats(struct file *file, +@@ -838,13 +838,15 @@ static ssize_t ath12k_debugfs_dump_soc_d soc_stats->invalid_rbm); len += scnprintf(buf + len, size - len, "RXDMA errors:\n"); for (i = 0; i < HAL_REO_ENTR_RING_RXDMA_ECODE_MAX; i++) @@ -102,11 +98,9 @@ index c3d1962..a40168b 100644 len += scnprintf(buf + len, size - len, "\nHAL REO errors:\n"); len += scnprintf(buf + len, size - len, -diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c -index c4ef2e4..b62d8ab 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -3968,8 +3968,6 @@ static bool ath12k_dp_rx_h_reo_err(struct ath12k *ar, struct sk_buff *msdu, +@@ -3990,8 +3990,6 @@ static bool ath12k_dp_rx_h_reo_err(struc struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu); bool drop = false; @@ -115,7 +109,7 @@ index c4ef2e4..b62d8ab 100644 switch (rxcb->err_code) { case HAL_REO_DEST_RING_ERROR_CODE_DESC_ADDR_ZERO: if (ath12k_dp_rx_h_null_q_desc(ar, msdu, status, msdu_list)) -@@ -3989,10 +3987,15 @@ static bool ath12k_dp_rx_h_reo_err(struct ath12k *ar, struct sk_buff *msdu, +@@ -4011,10 +4009,15 @@ static bool ath12k_dp_rx_h_reo_err(struc break; } @@ -132,7 +126,7 @@ index c4ef2e4..b62d8ab 100644 struct ieee80211_rx_status *status) { struct ath12k_base *ab = ar->ab; -@@ -4007,6 +4010,14 @@ static void ath12k_dp_rx_h_tkip_mic_err(struct ath12k *ar, struct sk_buff *msdu, +@@ -4029,6 +4032,14 @@ static void ath12k_dp_rx_h_tkip_mic_err( l3pad_bytes = ath12k_dp_rx_h_l3pad(ab, desc); msdu_len = ath12k_dp_rx_h_msdu_len(ab, desc); @@ -147,7 +141,7 @@ index c4ef2e4..b62d8ab 100644 skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len); skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes); -@@ -4017,6 +4028,7 @@ static void ath12k_dp_rx_h_tkip_mic_err(struct ath12k *ar, struct sk_buff *msdu, +@@ -4039,6 +4050,7 @@ static void ath12k_dp_rx_h_tkip_mic_err( ath12k_dp_rx_h_undecap(ar, msdu, desc, HAL_ENCRYPT_TYPE_TKIP_MIC, status, false); @@ -155,7 +149,7 @@ index c4ef2e4..b62d8ab 100644 } static bool ath12k_dp_rx_h_4addr_null_frame_handler(struct ath12k *ar, struct sk_buff *msdu, -@@ -4036,7 +4048,6 @@ static bool ath12k_dp_rx_h_4addr_null_frame_handler(struct ath12k *ar, struct s +@@ -4058,7 +4070,6 @@ static bool ath12k_dp_rx_h_4addr_null_fr msdu_len = ath12k_dp_rx_h_msdu_len(ab, rx_desc); peer_id = ath12k_dp_rx_h_peer_id(ab, rx_desc); @@ -163,25 +157,25 @@ index c4ef2e4..b62d8ab 100644 if(!ath12k_peer_find_by_id(ab, peer_id)) { ath12k_dbg(ab, ATH12K_DBG_DATA, "invalid peer id received in wbm err pkt%d\n", -@@ -4075,8 +4086,6 @@ static bool ath12k_dp_rx_h_rxdma_err(struct ath12k *ar, struct sk_buff *msdu, +@@ -4098,8 +4109,6 @@ static bool ath12k_dp_rx_h_rxdma_err(str bool drop = false; u32 err_bitmap; - ar->ab->soc_stats.rxdma_error[rxcb->err_code]++; - switch (rxcb->err_code) { - case HAL_REO_ENTR_RING_RXDMA_ECODE_ARXDMA_UNAUTH_WDS_ERR: + case HAL_REO_ENTR_RING_RXDMA_ECODE_UNAUTH_WDS_ERR: drop = ath12k_dp_rx_h_4addr_null_frame_handler(ar, msdu, status); -@@ -4085,7 +4094,7 @@ static bool ath12k_dp_rx_h_rxdma_err(struct ath12k *ar, struct sk_buff *msdu, +@@ -4108,7 +4117,7 @@ static bool ath12k_dp_rx_h_rxdma_err(str case HAL_REO_ENTR_RING_RXDMA_ECODE_TKIP_MIC_ERR: - err_bitmap = ath12k_dp_rx_h_mpdu_err(rx_desc); - if (err_bitmap & DP_RX_MPDU_ERR_TKIP_MIC) { + err_bitmap = ath12k_dp_rx_h_mpdu_err(ab, rx_desc); + if (err_bitmap & HAL_RX_MPDU_ERR_TKIP_MIC) { - ath12k_dp_rx_h_tkip_mic_err(ar, msdu, status); + drop = ath12k_dp_rx_h_tkip_mic_err(ar, msdu, status); break; } fallthrough; -@@ -4097,6 +4106,11 @@ static bool ath12k_dp_rx_h_rxdma_err(struct ath12k *ar, struct sk_buff *msdu, +@@ -4120,6 +4129,11 @@ static bool ath12k_dp_rx_h_rxdma_err(str break; } @@ -193,6 +187,3 @@ index c4ef2e4..b62d8ab 100644 return drop; } --- -2.7.4 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/661-ath12k-fill-peer-meta-data-during-reo_reinject.patch b/feeds/ipq95xx/mac80211/patches/qca/661-ath12k-fill-peer-meta-data-during-reo_reinject.patch index b4679cdc3..595c95117 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/661-ath12k-fill-peer-meta-data-during-reo_reinject.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/661-ath12k-fill-peer-meta-data-during-reo_reinject.patch @@ -14,27 +14,24 @@ Signed-off-by: P Praneesh drivers/net/wireless/ath/ath12k/dp_rx.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c -index c4ef2e4..a8a9bce 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -3437,10 +3437,12 @@ static int ath12k_dp_rx_h_defrag_reo_reinject(struct ath12k *ar, struct dp_rx_ti +@@ -3459,11 +3459,13 @@ static int ath12k_dp_rx_h_defrag_reo_rei reo_ent_ring->rx_mpdu_info.peer_meta_data = reo_dest_ring->rx_mpdu_info.peer_meta_data; - reo_ent_ring->queue_addr_lo = lower_32_bits(rx_tid->paddr); -- reo_ent_ring->info0 = FIELD_PREP(HAL_REO_ENTR_RING_INFO0_QUEUE_ADDR_HI, -- upper_32_bits(rx_tid->paddr)) | -- FIELD_PREP(HAL_REO_ENTR_RING_INFO0_DEST_IND, dst_ind); +- reo_ent_ring->info0 = u32_encode_bits(upper_32_bits(rx_tid->paddr), +- HAL_REO_ENTR_RING_INFO0_QUEUE_ADDR_HI) | +- u32_encode_bits(dst_ind, HAL_REO_ENTR_RING_INFO0_DEST_IND); +- + /* Firmware expects physical address to be filled in queue_addr_lo in + * the MLO scenario and in case of non MLO peer meta data needs to be + * filled. + */ + reo_ent_ring->queue_addr_lo = reo_dest_ring->rx_mpdu_info.peer_meta_data; -+ reo_ent_ring->info0 = FIELD_PREP(HAL_REO_ENTR_RING_INFO0_DEST_IND, dst_ind); - - reo_ent_ring->info1 = FIELD_PREP(HAL_REO_ENTR_RING_INFO1_MPDU_SEQ_NUM, - rx_tid->cur_sn); --- -2.7.4 - ++ reo_ent_ring->info0 = u32_encode_bits(dst_ind, ++ HAL_REO_ENTR_RING_INFO0_DEST_IND); + reo_ent_ring->info1 = u32_encode_bits(rx_tid->cur_sn, + HAL_REO_ENTR_RING_INFO1_MPDU_SEQ_NUM); + dest_ring_info0 = u32_get_bits(reo_dest_ring->info0, diff --git a/feeds/ipq95xx/mac80211/patches/qca/662-ath12k-Fix-memory-leak-in-rx_desc-and-tx_desc.patch b/feeds/ipq95xx/mac80211/patches/qca/662-ath12k-Fix-memory-leak-in-rx_desc-and-tx_desc.patch index 246b12ca7..d5806fc8c 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/662-ath12k-Fix-memory-leak-in-rx_desc-and-tx_desc.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/662-ath12k-Fix-memory-leak-in-rx_desc-and-tx_desc.patch @@ -12,11 +12,9 @@ Signed-off-by: Rajat Soni drivers/net/wireless/ath/ath12k/dp.h | 2 ++ 2 files changed, 29 insertions(+), 4 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c -index 9b300b0..3a5b38f 100644 --- a/drivers/net/wireless/ath/ath12k/dp.c +++ b/drivers/net/wireless/ath/ath12k/dp.c -@@ -1152,6 +1152,7 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab) +@@ -1152,6 +1152,7 @@ static void ath12k_dp_cc_cleanup(struct struct ath12k_dp *dp = &ab->dp; struct sk_buff *skb; int i; @@ -24,7 +22,7 @@ index 9b300b0..3a5b38f 100644 if (!dp->spt_info) return; -@@ -1171,6 +1172,13 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab) +@@ -1171,6 +1172,13 @@ static void ath12k_dp_cc_cleanup(struct dev_kfree_skb_any(skb); } @@ -38,7 +36,7 @@ index 9b300b0..3a5b38f 100644 spin_unlock_bh(&dp->rx_desc_lock); /* TX Descriptor cleanup */ -@@ -1193,6 +1201,20 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab) +@@ -1193,6 +1201,20 @@ static void ath12k_dp_cc_cleanup(struct spin_unlock_bh(&dp->tx_desc_lock[i]); } @@ -59,17 +57,7 @@ index 9b300b0..3a5b38f 100644 /* unmap SPT pages */ for (i = 0; i < dp->num_spt_pages; i++) { if (!dp->spt_info[i].vaddr) -@@ -1205,9 +1227,6 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab) - - dp->tx_spt_pages = NULL; - -- for (i = 0; i < ATH12K_NUM_SPT_PAGES; i++) -- kfree(dp->spt_info[i].vaddr); -- - kfree(dp->spt_info); - } - -@@ -1354,6 +1373,8 @@ static int ath12k_dp_cc_desc_init(struct ath12k_base *ab) +@@ -1353,6 +1375,8 @@ static int ath12k_dp_cc_desc_init(struct return -ENOMEM; } @@ -78,7 +66,7 @@ index 9b300b0..3a5b38f 100644 for (j = 0; j < ATH12K_MAX_SPT_ENTRIES; j++) { rx_descs[j].cookie = ath12k_dp_cc_cookie_gen(i, j); rx_descs[j].magic = ATH12K_DP_RX_DESC_MAGIC; -@@ -1381,8 +1402,10 @@ static int ath12k_dp_cc_desc_init(struct ath12k_base *ab) +@@ -1380,8 +1404,10 @@ static int ath12k_dp_cc_desc_init(struct return -ENOMEM; } @@ -90,11 +78,9 @@ index 9b300b0..3a5b38f 100644 ppt_idx = ATH12K_NUM_RX_SPT_PAGES + tx_spt_page; tx_descs[j].desc_id = ath12k_dp_cc_cookie_gen(ppt_idx, j); tx_descs[j].pool_id = pool_id; -diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h -index fac18e5..18c8da4 100644 --- a/drivers/net/wireless/ath/ath12k/dp.h +++ b/drivers/net/wireless/ath/ath12k/dp.h -@@ -330,6 +330,8 @@ struct ath12k_tx_desc_info { +@@ -291,6 +291,8 @@ struct ath12k_tx_desc_info { struct ath12k_spt_info { dma_addr_t paddr; u32 *vaddr; @@ -103,6 +89,3 @@ index fac18e5..18c8da4 100644 }; struct ath12k_reo_queue_ref { --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/662-ath11k-fix-clear-peer-keys-during-disassoc.patch b/feeds/ipq95xx/mac80211/patches/qca/662-ath12k-fix-clear-peer-keys-during-disassoc.patch similarity index 100% rename from feeds/ipq95xx/mac80211/patches/qca/662-ath11k-fix-clear-peer-keys-during-disassoc.patch rename to feeds/ipq95xx/mac80211/patches/qca/662-ath12k-fix-clear-peer-keys-during-disassoc.patch diff --git a/feeds/ipq95xx/mac80211/patches/qca/662-ath12k-fix-radar-detection-issue-in-160mhz.patch b/feeds/ipq95xx/mac80211/patches/qca/662-ath12k-fix-radar-detection-issue-in-160mhz.patch index fc5aa68d1..404d1db6a 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/662-ath12k-fix-radar-detection-issue-in-160mhz.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/662-ath12k-fix-radar-detection-issue-in-160mhz.patch @@ -22,7 +22,7 @@ Signed-off-by: Manish Dharanenthiran --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -7835,7 +7835,7 @@ static void ath12k_mac_op_remove_chanctx +@@ -7987,7 +7987,7 @@ static void ath12k_mac_op_remove_chanctx static int ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif, const struct cfg80211_chan_def *chandef, @@ -31,7 +31,7 @@ Signed-off-by: Manish Dharanenthiran { struct ath12k *ar = arvif->ar; struct ath12k_base *ab = ar->ab; -@@ -7885,6 +7885,8 @@ ath12k_mac_vdev_start_restart(struct ath +@@ -8037,6 +8037,8 @@ ath12k_mac_vdev_start_restart(struct ath arg.channel.chan_radar = !!(chandef->chan->flags & IEEE80211_CHAN_RADAR); @@ -40,7 +40,7 @@ Signed-off-by: Manish Dharanenthiran arg.channel.passive = arg.channel.chan_radar; spin_lock_bh(&ab->base_lock); -@@ -7997,20 +7999,23 @@ err: +@@ -8149,20 +8151,23 @@ err: } static int ath12k_mac_vdev_start(struct ath12k_vif *arvif, @@ -68,7 +68,7 @@ Signed-off-by: Manish Dharanenthiran ret = ath12k_mac_vdev_stop(arvif); if (ret) { -@@ -8019,7 +8024,7 @@ static int ath12k_mac_vdev_restart(struc +@@ -8171,7 +8176,7 @@ static int ath12k_mac_vdev_restart(struc return ret; } @@ -77,7 +77,7 @@ Signed-off-by: Manish Dharanenthiran if (ret) { ath12k_warn(ab, "failed to start vdev %d: %d during restart\n", arvif->vdev_id, ret); -@@ -8041,22 +8046,27 @@ static int ath12k_vdev_restart_sequence( +@@ -8193,22 +8198,27 @@ static int ath12k_vdev_restart_sequence( struct vdev_up_params params = { 0 }; int ret = -EINVAL; @@ -112,7 +112,7 @@ Signed-off-by: Manish Dharanenthiran if (!arvif->is_up) return -EOPNOTSUPP; -@@ -8290,10 +8300,9 @@ ath12k_mac_update_vif_chan(struct ath12k +@@ -8442,10 +8452,9 @@ ath12k_mac_update_vif_chan(struct ath12k vifs[i].new_ctx, vif_down_failed_map, i); @@ -124,7 +124,7 @@ Signed-off-by: Manish Dharanenthiran } } -@@ -8394,7 +8403,8 @@ static void ath12k_mac_op_change_chanctx +@@ -8546,7 +8555,8 @@ static void ath12k_mac_op_change_chanctx if (WARN_ON(changed & IEEE80211_CHANCTX_CHANGE_CHANNEL)) goto unlock; @@ -134,7 +134,7 @@ Signed-off-by: Manish Dharanenthiran ath12k_mac_update_active_vif_chan(ar, ctx); /* TODO: Recalc radar detection */ -@@ -8413,7 +8423,8 @@ static int ath12k_start_vdev_delay(struc +@@ -8565,7 +8575,8 @@ static int ath12k_start_vdev_delay(struc if (WARN_ON(arvif->is_started)) return -EBUSY; @@ -144,7 +144,7 @@ Signed-off-by: Manish Dharanenthiran if (ret) { ath12k_warn(ab, "failed to start vdev %i addr %pM on freq %d: %d\n", arvif->vdev_id, vif->addr, -@@ -9064,7 +9075,7 @@ ath12k_mac_op_assign_vif_chanctx(struct +@@ -9217,7 +9228,7 @@ ath12k_mac_op_assign_vif_chanctx(struct goto out; } diff --git a/feeds/ipq95xx/mac80211/patches/qca/662-mac80211-add-eht_capa-for-debugfs_sta.patch b/feeds/ipq95xx/mac80211/patches/qca/662-mac80211-add-eht_capa-for-debugfs_sta.patch index c17df17b9..96274295e 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/662-mac80211-add-eht_capa-for-debugfs_sta.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/662-mac80211-add-eht_capa-for-debugfs_sta.patch @@ -8,22 +8,19 @@ Subject: [PATCH] mac80211: add eht_capa for debugfs_sta net/mac80211/debugfs_sta.c | 210 +++++++++++++++++++++++++++++++++++++ 2 files changed, 213 insertions(+) -diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h -index 5173df9..c98d34e 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h -@@ -2733,6 +2733,9 @@ ieee80211_he_spr_size(const u8 *he_spr_ie) - #define IEEE80211_EHT_MAC_CAP0_MAX_AMPDU_LEN_3895 0 - #define IEEE80211_EHT_MAC_CAP0_MAX_AMPDU_LEN_7991 1 - #define IEEE80211_EHT_MAC_CAP0_MAX_AMPDU_LEN_11454 2 +@@ -2817,6 +2817,10 @@ ieee80211_he_spr_size(const u8 *he_spr_i + + #define IEEE80211_EHT_MAC_CAP1_MAX_AMPDU_LEN_MASK 0x01 + +#define IEEE80211_EHT_MAC_CAP1_MAX_AMPDU_LEN_EXP 0x01 +#define IEEE80211_EHT_MAC_CAP1_EHT_TRS 0x02 +#define IEEE80211_EHT_MAC_CAP1_TXOP_SHARE_MODE2 0x04 - - /* EHT PHY capabilities as defined in P802.11be_D1.4 section 9.4.2.313.3 */ ++ + /* EHT PHY capabilities as defined in P802.11be_D2.0 section 9.4.2.313.3 */ #define IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ 0x02 -diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c -index 39adfac..d00a939 100644 + #define IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ 0x04 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -1056,6 +1056,215 @@ out: @@ -36,7 +33,7 @@ index 39adfac..d00a939 100644 + char *buf, *p; + size_t buf_sz = PAGE_SIZE; + struct sta_info *sta = file->private_data; -+ struct ieee80211_sta_eht_cap *ehtc = &sta->sta.eht_cap; ++ struct ieee80211_sta_eht_cap *ehtc = &sta->sta.deflink.eht_cap; + struct ieee80211_eht_mcs_nss_supp *nss = &ehtc->eht_mcs_nss_supp; + u8 ppe_size; + u8 *cap; @@ -85,7 +82,7 @@ index 39adfac..d00a939 100644 + PFLAG(MAC, 0, TRIG_TXOP_SHARING_MODE2, "Triggered TXOP Sharing Mode 2 Support"); + PFLAG(MAC, 0, RESTRICTED_TWT, "Restrived TWT Support"); + PFLAG(MAC, 0, SCS_TRAFFIC_DESC, "SCS Traffic Description Support"); -+ PFLAG_RANGE(MAC, MAX_AMPDU_LEN, 0, 0, 0, 6, "Maximum MPDU Length-%d"); ++ PFLAG_RANGE(MAC, MAX_MPDU_LEN, 0, 0, 0, 6, "Maximum MPDU Length-%d"); + PFLAG(MAC, 1, MAX_AMPDU_LEN_EXP, "Maximum A-MPDU Length Exponent Extension"); + PFLAG(MAC, 1, EHT_TRS, "EHT TRS Support"); + PFLAG(MAC, 1, TXOP_SHARE_MODE2, "TXOP Return Support In TXOP Sharing Mode 2"); @@ -242,7 +239,7 @@ index 39adfac..d00a939 100644 static ssize_t sta_reset_mac80211_tx_pkts_flow_read(struct file *file, char __user *userbuf, -@@ -1264,6 +1473,7 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) +@@ -1264,6 +1473,7 @@ void ieee80211_sta_debugfs_add(struct st DEBUGFS_ADD(ht_capa); DEBUGFS_ADD(vht_capa); DEBUGFS_ADD(he_capa); @@ -250,6 +247,3 @@ index 39adfac..d00a939 100644 DEBUGFS_ADD(reset_mac80211_tx_pkts_flow); DEBUGFS_ADD(reset_mac80211_rx_pkts_flow); DEBUGFS_ADD(mac80211_tx_pkts_flow); --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/663-ath12k-Clear-auth-flag-only-for-actual-association.patch b/feeds/ipq95xx/mac80211/patches/qca/663-ath12k-Clear-auth-flag-only-for-actual-association.patch index f6ea4060b..fee76f521 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/663-ath12k-Clear-auth-flag-only-for-actual-association.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/663-ath12k-Clear-auth-flag-only-for-actual-association.patch @@ -18,11 +18,9 @@ Signed-off-by: Thiraviyam Mariyappan drivers/net/wireless/ath/ath12k/wmi.h | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) -diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index c1254ed..5c80ca4 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -3178,6 +3178,7 @@ static void ath12k_bss_assoc(struct ath12k *ar, +@@ -3218,6 +3218,7 @@ static void ath12k_bss_assoc(struct ath1 rcu_read_unlock(); @@ -30,7 +28,7 @@ index c1254ed..5c80ca4 100644 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", -@@ -4811,6 +4812,7 @@ static int ath12k_station_assoc(struct ath12k *ar, +@@ -4854,6 +4855,7 @@ static int ath12k_station_assoc(struct a ath12k_peer_assoc_prepare(ar, vif, sta, &peer_arg, reassoc); @@ -38,7 +36,7 @@ index c1254ed..5c80ca4 100644 ret = ath12k_wmi_send_peer_assoc_cmd(ar, &peer_arg); if (ret) { ath12k_warn(ar->ab, "failed to run peer assoc for STA %pM vdev %i: %d\n", -@@ -5072,6 +5074,7 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk) +@@ -5116,6 +5118,7 @@ static void ath12k_sta_rc_update_wk(stru ath12k_peer_assoc_prepare(ar, arvif->vif, sta, &peer_arg, true); @@ -46,24 +44,20 @@ index c1254ed..5c80ca4 100644 err = ath12k_wmi_send_peer_assoc_cmd(ar, &peer_arg); if (err) ath12k_warn(ar->ab, "failed to run peer assoc for STA %pM vdev %i: %d\n", -diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c -index b5d9344..896bd85 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -1830,7 +1830,7 @@ ath12k_wmi_copy_peer_flags(struct wmi_peer_assoc_complete_cmd *cmd, - cmd->peer_flags |= WMI_PEER_AUTH; +@@ -1902,7 +1902,7 @@ static void ath12k_wmi_copy_peer_flags(s + cmd->peer_flags |= cpu_to_le32(WMI_PEER_AUTH); if (param->need_ptk_4_way) { - cmd->peer_flags |= WMI_PEER_NEED_PTK_4_WAY; + cmd->peer_flags |= cpu_to_le32(WMI_PEER_NEED_PTK_4_WAY); - if (!hw_crypto_disabled) + if (!hw_crypto_disabled && param->is_assoc) - cmd->peer_flags &= ~WMI_PEER_AUTH; + cmd->peer_flags &= cpu_to_le32(~WMI_PEER_AUTH); } if (param->need_gtk_2_way) -diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h -index 9a091fb..5730916 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -3975,6 +3975,7 @@ struct peer_assoc_params { +@@ -3933,6 +3933,7 @@ struct peer_assoc_params { u32 peer_eht_ops; struct ath12k_ppe_threshold peer_eht_ppet; u32 ru_punct_bitmap; @@ -71,6 +65,3 @@ index 9a091fb..5730916 100644 }; struct wmi_peer_assoc_complete_cmd { --- -2.7.4 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/663-ath12k-add-FTM-Mode-Support.patch b/feeds/ipq95xx/mac80211/patches/qca/663-ath12k-add-FTM-Mode-Support.patch new file mode 100644 index 000000000..8ade31bcd --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/663-ath12k-add-FTM-Mode-Support.patch @@ -0,0 +1,789 @@ +From ee76760fa88227ebde17924ac02fc2631bd04db6 Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Fri, 9 Sep 2022 12:17:52 +0530 +Subject: [PATCH] ath12k: add FTM Mode Support + +FTM (Factory test Mode) provide interface to send the test mode +and calibration related command to firmware. FTM daemon registers +a handler with Diag for receiving the QDART message, FTM daemon sends +Tx command to wifi driver via CFG80211. Wifi driver sends the WMI command +to FW and FW response via WMI events, wifi driver creates SKB and send to +CFG80211, CFG80211 sends FW response to FTM daemon via netlink message. + +Command: insmod ath12k ftm_mode=1 + +Signed-off-by: Sowmiya Sree Elavalagan +Signed-off-by: Aaradhana Sahu +--- + drivers/net/wireless/ath/ath12k/core.c | 14 +- + drivers/net/wireless/ath/ath12k/core.h | 11 + + drivers/net/wireless/ath/ath12k/debug.h | 1 + + drivers/net/wireless/ath/ath12k/mac.c | 11 +- + drivers/net/wireless/ath/ath12k/qmi.c | 5 + + drivers/net/wireless/ath/ath12k/testmode.c | 289 ++++++++++++++++++- + drivers/net/wireless/ath/ath12k/testmode.h | 14 +- + drivers/net/wireless/ath/ath12k/testmode_i.h | 14 + + drivers/net/wireless/ath/ath12k/wmi.c | 36 +++ + drivers/net/wireless/ath/ath12k/wmi.h | 19 ++ + 10 files changed, 402 insertions(+), 12 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -31,6 +31,10 @@ module_param_named(frame_mode, ath12k_fr + MODULE_PARM_DESC(frame_mode, + "Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)"); + ++unsigned int ath12k_ftm_mode; ++module_param_named(ftm_mode, ath12k_ftm_mode, uint, 0444); ++MODULE_PARM_DESC(ftm_mode, "Boots up in factory test mode"); ++ + unsigned int ath12k_mlo_capable = true; + module_param_named(mlo_capable, ath12k_mlo_capable, uint, 0644); + MODULE_PARM_DESC(mlo_capable, "mlo capable: 0-disable, 1-enable"); +@@ -627,6 +631,11 @@ static int ath12k_core_soc_create(struct + { + int ret; + ++ if (ath12k_ftm_mode) { ++ ab->fw_mode = ATH12K_FIRMWARE_MODE_FTM; ++ ath12k_info(ab, "Booting in ftm mode\n"); ++ } ++ + ret = ath12k_qmi_init_service(ab); + if (ret) { + ath12k_err(ab, "failed to initialize qmi :%d\n", ret); +@@ -996,7 +1005,7 @@ int ath12k_core_qmi_firmware_ready(struc + /* This should be the last function, add core related + * initializations within this function + */ +- ret = ath12k_core_start(ab, ATH12K_FIRMWARE_MODE_NORMAL); ++ ret = ath12k_core_start(ab, ab->fw_mode); + if (ret) { + ath12k_err(ab, "failed to start core: %d\n", ret); + goto err_dp_free; +@@ -1162,7 +1171,8 @@ static void ath12k_core_restart(struct w + for (j = 0; j < ab->num_radios; j++) { + pdev = &ab->pdevs[j]; + ar = pdev->ar; +- if (!ar || ar->state == ATH12K_STATE_OFF) ++ if (!ar || ar->state == ATH12K_STATE_OFF || ++ ar->state == ATH12K_STATE_TM) + continue; + + mutex_lock(&ar->conf_mutex); +@@ -1186,6 +1196,9 @@ static void ath12k_core_restart(struct w + ath12k_warn(ab, + "device is wedged, will not restart radio %d\n", j); + break; ++ case ATH12K_STATE_TM: ++ ath12k_warn(ab, "fw mode reset done radio %d\n", j); ++ break; + } + mutex_unlock(&ar->conf_mutex); + } +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -214,6 +214,7 @@ enum ath12k_dev_flags { + ATH12K_FLAG_HTC_SUSPEND_COMPLETE, + ATH12K_FLAG_QMI_FW_READY_COMPLETE, + ATH12K_FLAG_HW_GROUP_ATTACHED, ++ ATH12K_FLAG_FTM_SEGMENTED, + }; + + enum ath12k_monitor_flags { +@@ -568,12 +569,19 @@ enum ath12k_state { + ATH12K_STATE_RESTARTING, + ATH12K_STATE_RESTARTED, + ATH12K_STATE_WEDGED, ++ ATH12K_STATE_TM, + /* Add other states as required */ + }; + + /* Antenna noise floor */ + #define ATH12K_DEFAULT_NOISE_FLOOR -95 + ++struct ath12k_ftm_event_obj { ++ u32 data_pos; ++ u32 expected_seq; ++ u8 *eventdata; ++}; ++ + struct ath12k_fw_stats { + struct dentry *debugfs_fwstats; + u32 pdev_id; +@@ -781,6 +789,8 @@ struct ath12k { + int monitor_vdev_id; + u8 twt_enabled; + s8 max_allowed_tx_power; ++ struct completion fw_mode_reset; ++ u8 ftm_msgref; + bool ap_ps_enabled; + enum ath12k_ap_ps_state ap_ps_state; + +@@ -939,6 +949,7 @@ struct ath12k_hw_group { + /* Master structure to hold the hw data which may be used in core module */ + struct ath12k_base { + enum ath12k_hw_rev hw_rev; ++ enum ath12k_firmware_mode fw_mode; + struct platform_device *pdev; + struct device *dev; + struct ath12k_hw_group *ag; +@@ -1031,6 +1042,8 @@ struct ath12k_base { + /* protected by data_lock */ + u32 fw_crash_counter; + } stats; ++ bool ftm_segment_handler; ++ struct ath12k_ftm_event_obj ftm_event_obj; + u32 pktlog_defs_checksum; + + struct ath12k_dbring_cap *db_caps; +--- a/drivers/net/wireless/ath/ath12k/debug.h ++++ b/drivers/net/wireless/ath/ath12k/debug.h +@@ -34,6 +34,7 @@ __printf(2, 3) void ath12k_err(struct at + __printf(2, 3) void ath12k_warn(struct ath12k_base *ab, const char *fmt, ...); + + extern unsigned int ath12k_debug_mask; ++extern unsigned int ath12k_ftm_mode; + + #ifdef CPTCFG_ATH12K_DEBUG + __printf(3, 4) void __ath12k_dbg(struct ath12k_base *ab, +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -700,7 +700,10 @@ struct ath12k *ath12k_mac_get_ar_by_pdev + return NULL; + + for (i = 0; i < ab->num_radios; i++) { +- pdev = rcu_dereference(ab->pdevs_active[i]); ++ if (ab->fw_mode == ATH12K_FIRMWARE_MODE_FTM) ++ pdev = &ab->pdevs[i]; ++ else ++ pdev = rcu_dereference(ab->pdevs_active[i]); + + if (pdev && pdev->pdev_id == pdev_id) + return (pdev->ar ? pdev->ar : NULL); +@@ -6966,6 +6969,7 @@ static int ath12k_mac_radio_start(struct + case ATH12K_STATE_RESTARTED: + case ATH12K_STATE_WEDGED: + case ATH12K_STATE_ON: ++ case ATH12K_STATE_TM: + WARN_ON(1); + ret = -EINVAL; + goto err; +@@ -7122,6 +7126,12 @@ static int ath12k_mac_op_start(struct ie + ar = ah->radio; + ab = ar->ab; + ++ if (ath12k_ftm_mode) { ++ ath12k_err(ab, "fail to start mac operations in ftm mode\n"); ++ mutex_unlock(&ah->conf_mutex); ++ return -EWOULDBLOCK; ++ } ++ + /* TODO Maintain state for ah? */ + + for (i = 0; i < ah->num_radio; i++) { +--- a/drivers/net/wireless/ath/ath12k/qmi.c ++++ b/drivers/net/wireless/ath/ath12k/qmi.c +@@ -3759,6 +3759,11 @@ int ath12k_config_qdss(struct ath12k_bas + { + int ret; + ++ /* Disabling qdss trace for FTM as it causes hig evt latency in FW ++*/ ++ if (ab->fw_mode == ATH12K_FIRMWARE_MODE_FTM) ++ return 0; ++ + ret = ath12k_qmi_send_qdss_config(ab); + if (ret < 0) + ath12k_warn(ab, +--- a/drivers/net/wireless/ath/ath12k/testmode.c ++++ b/drivers/net/wireless/ath/ath12k/testmode.c +@@ -10,8 +10,12 @@ + #include "wmi.h" + #include "hw.h" + #include "core.h" ++#include "hif.h" + #include "testmode_i.h" + ++#define ATH12K_FTM_SEGHDR_CURRENT_SEQ GENMASK(3, 0) ++#define ATH12K_FTM_SEGHDR_TOTAL_SEGMENTS GENMASK(7, 4) ++ + static const struct nla_policy ath12k_tm_policy[ATH12K_TM_ATTR_MAX + 1] = { + [ATH12K_TM_ATTR_CMD] = { .type = NLA_U32 }, + [ATH12K_TM_ATTR_DATA] = { .type = NLA_BINARY, +@@ -58,66 +62,168 @@ void ath12k_fwlog_write(struct ath12k_ba + /* Returns true if callee consumes the skb and the skb should be discarded. + * Returns false if skb is not used. Does not sleep. + */ +-bool ath12k_tm_event_wmi(struct ath12k *ar, u32 cmd_id, struct sk_buff *skb) ++struct ath12k *ath12k_tm_get_ar(struct ath12k_base *ab) ++{ ++ struct ath12k_pdev *pdev; ++ struct ath12k *ar = NULL; ++ int i; ++ ++ for (i = 0; i < ab->num_radios; i++) { ++ pdev = &ab->pdevs[i]; ++ ar = pdev->ar; ++ if (ar) { ++ if (ar->state == ATH12K_STATE_TM) ++ break; ++ } ++ } ++ return ar; ++} ++/* This function handles unsegmented events. Data in various events are aggregated ++* in application layer, this event is unsegmented from host perspective. ++*/ ++void ath12k_tm_wmi_event_unsegmented(struct ath12k_base *ab, u32 cmd_id, struct sk_buff *skb) + { + struct sk_buff *nl_skb; +- bool consumed; +- int ret; ++ struct ath12k *ar; + +- ath12k_dbg(ar->ab, ATH12K_DBG_TESTMODE, +- "testmode event wmi cmd_id %d skb %pK skb->len %d\n", +- cmd_id, skb, skb->len); ++ ath12k_dbg(ab, ATH12K_DBG_TESTMODE, ++ "testmode event wmi cmd_id %d skb length %d\n", ++ cmd_id, skb->len); + +- ath12k_dbg_dump(ar->ab, ATH12K_DBG_TESTMODE, NULL, "", skb->data, skb->len); ++ ath12k_dbg_dump(ab, ATH12K_DBG_TESTMODE, NULL, "", skb->data, skb->len); ++ ++ ar = ath12k_tm_get_ar(ab); ++ if (!ar) { ++ ath12k_warn(ab, "testmode event not handled due to invalid pdev\n"); ++ return; ++ } + + spin_lock_bh(&ar->data_lock); + +- consumed = true; + + nl_skb = cfg80211_testmode_alloc_event_skb(ar->ah->hw->wiphy, +- 2 * sizeof(u32) + skb->len, ++ 2 * nla_total_size(sizeof(u32)) + ++ nla_total_size(skb->len), + GFP_ATOMIC); + if (!nl_skb) { +- ath12k_warn(ar->ab, ++ ath12k_warn(ab, + "failed to allocate skb for testmode wmi event\n"); + goto out; + } +- +- ret = nla_put_u32(nl_skb, ATH12K_TM_ATTR_CMD, ATH12K_TM_CMD_WMI); +- if (ret) { +- ath12k_warn(ar->ab, +- "failed to put testmode wmi event cmd attribute: %d\n", +- ret); ++ if (nla_put_u32(nl_skb, ATH12K_TM_ATTR_CMD, ATH12K_TM_CMD_WMI) || ++ nla_put_u32(nl_skb, ATH12K_TM_ATTR_WMI_CMDID, cmd_id) || ++ nla_put(nl_skb, ATH12K_TM_ATTR_DATA, skb->len, skb->data)) { ++ ath12k_warn(ab, "failed to populate testmode unsegmented event\n"); + kfree_skb(nl_skb); + goto out; + } + +- ret = nla_put_u32(nl_skb, ATH12K_TM_ATTR_WMI_CMDID, cmd_id); +- if (ret) { +- ath12k_warn(ar->ab, +- "failed to put testmode wmi even cmd_id: %d\n", +- ret); +- kfree_skb(nl_skb); ++ ++ cfg80211_testmode_event(nl_skb, GFP_ATOMIC); ++ spin_unlock_bh(&ar->data_lock); ++ return; ++ ++out: ++ spin_unlock_bh(&ar->data_lock); ++ ath12k_warn(ab, "Failed to send testmode event to higher layers\n"); ++} ++ ++/* This function handles segmented events. ++* Data of various events received from fw is aggregated and ++* sent to application layer ++*/ ++int ath12k_tm_process_event(struct ath12k_base *ab, u32 cmd_id, ++ const struct wmi_ftm_event_msg *ftm_msg, ++ u16 length) ++{ ++ struct sk_buff *nl_skb; ++ int ret = 0; ++ struct ath12k *ar; ++ u8 const *buf_pos; ++ u16 datalen; ++ u8 total_segments, current_seq; ++ u32 data_pos; ++ u32 pdev_id; ++ ++ ath12k_dbg(ab, ATH12K_DBG_TESTMODE, ++ "testmode event wmi cmd_id %d ftm event msg %pK datalen %d\n", ++ cmd_id, ftm_msg, length); ++ ath12k_dbg_dump(ab, ATH12K_DBG_TESTMODE, NULL, "", ftm_msg, length); ++ pdev_id = DP_HW2SW_MACID(ftm_msg->seg_hdr.pdev_id); ++ ++ if (pdev_id >= ab->num_radios) { ++ ath12k_warn(ab, "testmode event not handled due to invalid pdev id\n"); ++ return -EINVAL; ++ } ++ ++ ar = ab->pdevs[pdev_id].ar; ++ if (!ar) { ++ ath12k_warn(ab, "testmode event not handled due to absence of pdev\n"); ++ return -ENODEV; ++ } ++ ++ current_seq = FIELD_GET(ATH12K_FTM_SEGHDR_CURRENT_SEQ, ++ ftm_msg->seg_hdr.segmentinfo); ++ total_segments = FIELD_GET(ATH12K_FTM_SEGHDR_TOTAL_SEGMENTS, ++ ftm_msg->seg_hdr.segmentinfo); ++ datalen = length - (sizeof(struct wmi_ftm_seg_hdr)); ++ buf_pos = ftm_msg->data; ++ ++ spin_lock_bh(&ar->data_lock); ++ if (current_seq == 0) { ++ ab->ftm_event_obj.expected_seq = 0; ++ ab->ftm_event_obj.data_pos = 0; ++ } ++ ++ data_pos = ab->ftm_event_obj.data_pos; ++ ++ if ((data_pos + datalen) > ATH12K_FTM_EVENT_MAX_BUF_LENGTH) { ++ ath12k_warn(ab, ++ "Invalid event length date_pos[%d] datalen[%d]\n", ++ data_pos, datalen); + goto out; + } + +- ret = nla_put(nl_skb, ATH12K_TM_ATTR_DATA, skb->len, skb->data); +- if (ret) { +- ath12k_warn(ar->ab, +- "failed to copy skb to testmode wmi event: %d\n", +- ret); ++ memcpy(&ab->ftm_event_obj.eventdata[data_pos], buf_pos, datalen); ++ data_pos += datalen; ++ ++ if (++ab->ftm_event_obj.expected_seq != total_segments) { ++ ab->ftm_event_obj.data_pos = data_pos; ++ ath12k_dbg(ab, ATH12K_DBG_TESTMODE, ++ "partial data received current_seq[%d], total_seg[%d]\n", ++ current_seq, total_segments); ++ goto out; ++ } ++ ++ ath12k_dbg(ab, ATH12K_DBG_TESTMODE, ++ "total data length[%d] = [%d]\n", ++ data_pos, ftm_msg->seg_hdr.len); ++ nl_skb = cfg80211_testmode_alloc_event_skb(ar->ah->hw->wiphy, ++ 2 * nla_total_size(sizeof(u32)) + ++ nla_total_size(data_pos), ++ GFP_ATOMIC); ++ if (!nl_skb) { ++ ath12k_warn(ab, ++ "failed to allocate skb for testmode wmi event\n"); ++ goto out; ++ } ++ ++ if (nla_put_u32(nl_skb, ATH12K_TM_ATTR_CMD, ++ ATH12K_TM_CMD_WMI_FTM) || ++ nla_put_u32(nl_skb, ATH12K_TM_ATTR_WMI_CMDID, cmd_id) || ++ nla_put(nl_skb, ATH12K_TM_ATTR_DATA, data_pos, ++ &ab->ftm_event_obj.eventdata[0])) { ++ ath12k_warn(ab, "failed to populate testmode event"); + kfree_skb(nl_skb); + goto out; + } + + cfg80211_testmode_event(nl_skb, GFP_ATOMIC); +- + out: + spin_unlock_bh(&ar->data_lock); ++ return ret; + +- return consumed; + } +- + static int ath12k_tm_cmd_get_version(struct ath12k *ar, struct nlattr *tb[]) + { + struct sk_buff *skb; +@@ -133,16 +239,10 @@ static int ath12k_tm_cmd_get_version(str + if (!skb) + return -ENOMEM; + +- ret = nla_put_u32(skb, ATH12K_TM_ATTR_VERSION_MAJOR, +- ATH12K_TESTMODE_VERSION_MAJOR); +- if (ret) { +- kfree_skb(skb); +- return ret; +- } +- +- ret = nla_put_u32(skb, ATH12K_TM_ATTR_VERSION_MINOR, +- ATH12K_TESTMODE_VERSION_MINOR); +- if (ret) { ++ if (nla_put_u32(skb, ATH12K_TM_ATTR_VERSION_MAJOR, ++ ATH12K_TESTMODE_VERSION_MAJOR) || ++ nla_put_u32(skb, ATH12K_TM_ATTR_VERSION_MINOR, ++ ATH12K_TESTMODE_VERSION_MINOR)) { + kfree_skb(skb); + return ret; + } +@@ -150,6 +250,39 @@ static int ath12k_tm_cmd_get_version(str + return cfg80211_testmode_reply(skb); + } + ++static int ath12k_tm_cmd_testmode_start(struct ath12k *ar, struct nlattr *tb[]) ++{ ++ int ret; ++ ath12k_dbg(ar->ab, ATH12K_DBG_TESTMODE, " enter testmode cmd fw start\n"); ++ mutex_lock(&ar->conf_mutex); ++ ++ if (ar->state == ATH12K_STATE_TM) { ++ ret = -EALREADY; ++ goto err; ++ } ++ ++ /* start utf only when the driver is not in use */ ++ if (ar->state != ATH12K_STATE_OFF) { ++ ret = -EBUSY; ++ goto err; ++ } ++ ++ ar->ab->ftm_event_obj.eventdata = ++ kzalloc(ATH12K_FTM_EVENT_MAX_BUF_LENGTH, GFP_KERNEL); ++ if (!ar->ab->ftm_event_obj.eventdata) { ++ ret = -ENOMEM; ++ goto err; ++ } ++ ++ ar->state = ATH12K_STATE_TM; ++ ar->ftm_msgref = 0; ++ mutex_unlock(&ar->conf_mutex); ++ ath12k_dbg(ar->ab, ATH12K_DBG_TESTMODE, " enter testmode cmd started\n"); ++ return 0; ++err: ++ mutex_unlock(&ar->conf_mutex); ++ return ret; ++} + static int ath12k_tm_cmd_wmi(struct ath12k *ar, struct nlattr *tb[]) + { + struct ath12k_pdev_wmi *wmi = ar->wmi; +@@ -161,11 +294,6 @@ static int ath12k_tm_cmd_wmi(struct ath1 + + mutex_lock(&ar->conf_mutex); + +- if (ar->state != ATH12K_STATE_ON) { +- ret = -ENETDOWN; +- goto out; +- } +- + if (!tb[ATH12K_TM_ATTR_DATA]) { + ret = -EINVAL; + goto out; +@@ -178,6 +306,11 @@ static int ath12k_tm_cmd_wmi(struct ath1 + + buf = nla_data(tb[ATH12K_TM_ATTR_DATA]); + buf_len = nla_len(tb[ATH12K_TM_ATTR_DATA]); ++ if (!buf_len) { ++ ath12k_warn(ar->ab, "No data present in testmode command\n"); ++ ret = -EINVAL; ++ goto out; ++ } + cmd_id = nla_get_u32(tb[ATH12K_TM_ATTR_WMI_CMDID]); + + ptr = (u32 *)buf; +@@ -188,8 +321,8 @@ static int ath12k_tm_cmd_wmi(struct ath1 + *ptr = ar->pdev->pdev_id; + + ath12k_dbg(ar->ab, ATH12K_DBG_TESTMODE, +- "testmode cmd wmi cmd_id %d buf %pK buf_len %d\n", +- cmd_id, buf, buf_len); ++ "testmode cmd wmi cmd_id %d buf length %d\n", ++ cmd_id, buf_len); + + ath12k_dbg_dump(ar->ab, ATH12K_DBG_TESTMODE, NULL, "", buf, buf_len); + +@@ -216,17 +349,98 @@ out: + return ret; + } + ++static int ath12k_tm_cmd_process_ftm(struct ath12k *ar, struct nlattr *tb[]) ++{ ++ struct ath12k_pdev_wmi *wmi = ar->wmi; ++ struct sk_buff *skb; ++ u32 cmd_id, buf_len, hdr_info; ++ int ret; ++ void *buf; ++ ++ /* if buf_len is 0 no data is sent, return error */ ++ u8 segnumber = 0, seginfo; ++ u16 chunk_len, total_bytes, num_segments; ++ u8 *bufpos; ++ struct wmi_ftm_cmd *ftm_cmd; ++ mutex_lock(&ar->conf_mutex); ++ ath12k_dbg(ar->ab, ATH12K_DBG_TESTMODE, "ar->state %d\n", ar->state); ++ if (ar->state != ATH12K_STATE_TM) { ++ ret = -ENETDOWN; ++ goto out; ++ } ++ ++ if (!tb[ATH12K_TM_ATTR_DATA]) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ buf = nla_data(tb[ATH12K_TM_ATTR_DATA]); ++ buf_len = nla_len(tb[ATH12K_TM_ATTR_DATA]); ++ cmd_id = WMI_PDEV_UTF_CMDID; ++ ath12k_dbg(ar->ab, ATH12K_DBG_TESTMODE, ++ "testmode cmd wmi cmd_id %d buf %pK buf_len %d\n", ++ cmd_id, buf, buf_len); ++ ath12k_dbg_dump(ar->ab, ATH12K_DBG_TESTMODE, NULL, "", buf, buf_len); ++ bufpos = buf; ++ total_bytes = buf_len; ++ num_segments = total_bytes / MAX_WMI_UTF_LEN; ++ if (buf_len - (num_segments * MAX_WMI_UTF_LEN)) ++ num_segments++; ++ ++ while (buf_len) { ++ if (buf_len > MAX_WMI_UTF_LEN) ++ chunk_len = MAX_WMI_UTF_LEN; /* MAX message */ ++ else ++ chunk_len = buf_len; ++ ++ skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, (chunk_len + ++ sizeof(struct wmi_ftm_cmd))); ++ ++ if (!skb) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ ftm_cmd = (struct wmi_ftm_cmd *)skb->data; ++ hdr_info = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_BYTE) | ++ FIELD_PREP(WMI_TLV_LEN, (chunk_len + ++ sizeof(struct wmi_ftm_seg_hdr))); ++ ftm_cmd->tlv_header = hdr_info; ++ ftm_cmd->seg_hdr.len = total_bytes; ++ ftm_cmd->seg_hdr.msgref = ar->ftm_msgref; ++ seginfo = FIELD_PREP(ATH12K_FTM_SEGHDR_TOTAL_SEGMENTS, num_segments) | ++ FIELD_PREP(ATH12K_FTM_SEGHDR_CURRENT_SEQ, segnumber); ++ ftm_cmd->seg_hdr.segmentinfo = seginfo; ++ segnumber++; ++ memcpy(&ftm_cmd->data, bufpos, chunk_len); ++ ret = ath12k_wmi_cmd_send(wmi, skb, cmd_id); ++ if (ret) { ++ ath12k_warn(ar->ab, "ftm wmi command fail: %d\n", ret); ++ goto out; ++ } ++ ++ buf_len -= chunk_len; ++ bufpos += chunk_len; ++ } ++ ++ar->ftm_msgref; ++ ret = 0; ++out: ++ mutex_unlock(&ar->conf_mutex); ++ return ret; ++} + int ath12k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + void *data, int len) + { + struct ath12k_hw *ah = hw->priv; + struct ath12k *ar; ++ struct ath12k_base *ab; + struct nlattr *tb[ATH12K_TM_ATTR_MAX + 1]; + int ret; + + mutex_lock(&ah->conf_mutex); + + ar = ath12k_get_ar_by_vif(hw, vif); ++ ab = ar->ab; + if (!ar) { + mutex_unlock(&ah->conf_mutex); + return -EINVAL; +@@ -243,10 +457,17 @@ int ath12k_tm_cmd(struct ieee80211_hw *h + return -EINVAL; + + switch (nla_get_u32(tb[ATH12K_TM_ATTR_CMD])) { +- case ATH12K_TM_CMD_GET_VERSION: +- return ath12k_tm_cmd_get_version(ar, tb); + case ATH12K_TM_CMD_WMI: + return ath12k_tm_cmd_wmi(ar, tb); ++ case ATH12K_TM_CMD_TESTMODE_START: ++ return ath12k_tm_cmd_testmode_start(ar, tb); ++ case ATH12K_TM_CMD_GET_VERSION: ++ return ath12k_tm_cmd_get_version(ar, tb); ++ case ATH12K_TM_CMD_WMI_FTM: ++ set_bit(ATH12K_FLAG_FTM_SEGMENTED, &ab->dev_flags); ++ return ath12k_tm_cmd_process_ftm(ar, tb); ++ case ATH12K_TM_CMD_TESTMODE_STOP: ++ return 0; + default: + return -EOPNOTSUPP; + } +--- a/drivers/net/wireless/ath/ath12k/testmode.h ++++ b/drivers/net/wireless/ath/ath12k/testmode.h +@@ -5,21 +5,31 @@ + */ + + #include "core.h" ++#include "hif.h" + + #ifdef CPTCFG_NL80211_TESTMODE + +-bool ath12k_tm_event_wmi(struct ath12k *ar, u32 cmd_id, struct sk_buff *skb); ++void ath12k_tm_wmi_event_unsegmented(struct ath12k_base *ab, u32 cmd_id, struct sk_buff *skb); ++int ath12k_tm_process_event(struct ath12k_base *ab, u32 cmd_id, ++ const struct wmi_ftm_event_msg *ftm_msg, ++ u16 length); + int ath12k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + void *data, int len); + void ath12k_fwlog_write(struct ath12k_base *ab, u8 *data, int len); + #else + +-static inline bool ath12k_tm_event_wmi(struct ath12k *ar, u32 cmd_id, +- struct sk_buff *skb) ++static inline void ath12k_tm_wmi_event__unsegmented(struct ath12k_base *ab, u32 cmd_id, ++ struct sk_buff *skb) + { +- return false; ++ return; + } + ++static inline int ath12k_tm_process_event(struct ath12k_base *ab, u32 cmd_id, ++ const struct wmi_ftm_event_msg *msg, ++ u16 length) ++{ ++ return 0; ++} + static inline int ath12k_tm_cmd(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + void *data, int len) +--- a/drivers/net/wireless/ath/ath12k/testmode_i.h ++++ b/drivers/net/wireless/ath/ath12k/testmode_i.h +@@ -15,6 +15,7 @@ + #define ATH12K_TESTMODE_VERSION_MINOR 0 + + #define ATH12K_TM_DATA_MAX_LEN 5000 ++#define ATH12K_FTM_EVENT_MAX_BUF_LENGTH 2048 + + enum ath12k_tm_attr { + __ATH12K_TM_ATTR_INVALID = 0, +@@ -42,6 +43,12 @@ enum ath12k_tm_cmd { + */ + ATH12K_TM_CMD_GET_VERSION = 0, + ++ /* Boots the UTF firmware, the netdev interface must be down at thetime. */ ++ ATH12K_TM_CMD_TESTMODE_START = 1, ++ ++ /* Shuts down the UTF firmware and puts the driver back into OFFstate.*/ ++ ATH12K_TM_CMD_TESTMODE_STOP = 2, ++ + /* The command used to transmit a WMI command to the firmware and + * the event to receive WMI events from the firmware. Without + * struct wmi_cmd_hdr header, only the WMI payload. Command id is +@@ -49,4 +56,11 @@ enum ath12k_tm_cmd { + * ATH12K_TM_ATTR_DATA. + */ + ATH12K_TM_CMD_WMI = 3, ++ ++ /* The command used to transmit a FTM WMI command to the firmware ++ * and the event to receive WMI events from the firmware.The data ++ * received only contain the payload, Need to add the tlv ++ * header and send the cmd to fw with commandid WMI_PDEV_UTF_CMDID. ++ */ ++ ATH12K_TM_CMD_WMI_FTM = 4, + }; +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -8154,6 +8154,35 @@ ath12k_wmi_pktlog_decode_info(struct ath + kfree(tb); + } + ++static void ath12k_wmi_tm_event_segmented(struct ath12k_base *ab, u32 cmd_id, ++ struct sk_buff *skb) ++{ ++ const void **tb; ++ const struct wmi_ftm_event_msg *ev; ++ u16 length; ++ int ret; ++ ++ tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); ++ ++ if (IS_ERR(tb)) { ++ ret = PTR_ERR(tb); ++ ath12k_warn(ab, "failed to parse ftm event tlv: %d\n", ret); ++ return; ++ } ++ ++ ev = tb[WMI_TAG_ARRAY_BYTE]; ++ if (!ev) { ++ ath12k_warn(ab, "failed to fetch ftm msg\n"); ++ kfree(tb); ++ return; ++ } ++ ++ length = skb->len - TLV_HDR_SIZE; ++ ret = ath12k_tm_process_event(ab, cmd_id, ev, length); ++ if (!ret) ++ ath12k_warn(ab, "Failed to process ftm event\n"); ++ kfree(tb); ++} + static void + ath12k_wmi_pdev_temperature_event(struct ath12k_base *ab, + struct sk_buff *skb) +@@ -9149,6 +9178,12 @@ static void ath12k_wmi_tlv_op_rx(struct + case WMI_OBSS_COLOR_COLLISION_DETECTION_EVENTID: + ath12k_wmi_obss_color_collision_event(ab, skb); + break; ++ case WMI_PDEV_UTF_EVENTID: ++ if (test_bit(ATH12K_FLAG_FTM_SEGMENTED, &ab->dev_flags)) ++ ath12k_wmi_tm_event_segmented(ab, id, skb); ++ else ++ ath12k_tm_wmi_event_unsegmented(ab, id, skb); ++ break; + case WMI_STATS_CTRL_PATH_EVENTID: + ath12k_process_tpc_stats(ab, skb); + break; +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -3786,6 +3786,25 @@ struct wmi_get_pdev_temperature_cmd { + __le32 pdev_id; + } __packed; + ++#define MAX_WMI_UTF_LEN 252 ++ ++struct wmi_ftm_seg_hdr { ++ u32 len; ++ u32 msgref; ++ u32 segmentinfo; ++ u32 pdev_id; ++} __packed; ++ ++struct wmi_ftm_cmd { ++ u32 tlv_header; ++ struct wmi_ftm_seg_hdr seg_hdr; ++ u8 data[]; ++} __packed; ++ ++struct wmi_ftm_event_msg { ++ struct wmi_ftm_seg_hdr seg_hdr; ++ u8 data[]; ++} __packed; + #define WMI_BEACON_TX_BUFFER_SIZE 512 + + #define WMI_BEACON_EMA_PARAM_PERIODICITY_SHIFT 0 +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -1269,6 +1269,7 @@ static int ath12k_pci_probe(struct pci_d + ab_pci->ab = ab; + ab_pci->pdev = pdev; + ab->hif.ops = &ath12k_pci_hif_ops; ++ ab->fw_mode = ATH12K_FIRMWARE_MODE_NORMAL; + pci_set_drvdata(pdev, ab); + spin_lock_init(&ab_pci->window_lock); + diff --git a/feeds/ipq95xx/mac80211/patches/qca/664-ath12k-increase-msi.patch b/feeds/ipq95xx/mac80211/patches/qca/664-ath12k-increase-msi.patch index 7e35e5a52..a18e9e3db 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/664-ath12k-increase-msi.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/664-ath12k-increase-msi.patch @@ -16,10 +16,10 @@ Signed-off-by: P Praneesh --- a/drivers/net/wireless/ath/ath12k/hw.c +++ b/drivers/net/wireless/ath/ath12k/hw.c -@@ -308,12 +308,14 @@ const struct ath12k_hw_ring_mask ath12k_ +@@ -539,12 +539,14 @@ static const struct ath12k_hw_ring_mask ATH12K_TX_RING_MASK_1, ATH12K_TX_RING_MASK_2, - ATH12K_TX_RING_MASK_3, + ATH12K_TX_RING_MASK_4, + 0, 0, 0, 0, 0, 0, 0, 0, }, .rx_mon_dest = { @@ -32,7 +32,7 @@ Signed-off-by: P Praneesh }, .rx = { 0, 0, 0, 0, -@@ -321,27 +323,32 @@ const struct ath12k_hw_ring_mask ath12k_ +@@ -552,27 +554,32 @@ static const struct ath12k_hw_ring_mask ATH12K_RX_RING_MASK_1, ATH12K_RX_RING_MASK_2, ATH12K_RX_RING_MASK_3, @@ -68,7 +68,7 @@ Signed-off-by: P Praneesh --- a/drivers/net/wireless/ath/ath12k/hw.h +++ b/drivers/net/wireless/ath/ath12k/hw.h -@@ -107,7 +107,7 @@ enum ath12k_bus { +@@ -110,7 +110,7 @@ enum ath12k_bus { ATH12K_BUS_PCI, }; @@ -79,7 +79,7 @@ Signed-off-by: P Praneesh struct hal_tcl_data_cmd; --- a/drivers/net/wireless/ath/ath12k/pci.c +++ b/drivers/net/wireless/ath/ath12k/pci.c -@@ -66,12 +66,13 @@ static const struct ath12k_bus_params at +@@ -67,12 +67,13 @@ static const struct ath12k_bus_params at /* TODO: revisit IRQ mapping for new SRNG's */ static const struct ath12k_msi_config ath12k_msi_config[] = { { diff --git a/feeds/ipq95xx/mac80211/patches/qca/664-ath12k-prevent-monitor-memset.patch b/feeds/ipq95xx/mac80211/patches/qca/664-ath12k-prevent-monitor-memset.patch index c7fbd491b..9567e3c36 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/664-ath12k-prevent-monitor-memset.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/664-ath12k-prevent-monitor-memset.patch @@ -46,7 +46,7 @@ Signed-off-by: P Praneesh - err_bitmap = ppdu_info->mon_mpdu[mpdu_idx].msdu_info[0].errmap; + err_bitmap = ppdu_info->cmn_mpdu_info.mon_mpdu[mpdu_idx].msdu_info[0].errmap; - if (err_bitmap & DP_RX_MPDU_ERR_FCS) + if (err_bitmap & HAL_RX_MPDU_ERR_FCS) *fcs_err = true; - decap_format = ppdu_info->mon_mpdu[mpdu_idx].msdu_info[0].decap_format; @@ -82,8 +82,8 @@ Signed-off-by: P Praneesh { int offset; -- if (ppdu_info->mpdu_count >= HAL_RX_MAX_MPDU) { -+ if (ppdu_info->cmn_mpdu_info.mpdu_count >= HAL_RX_MAX_MPDU) { +- if (ppdu_info->mpdu_count > HAL_RX_MAX_MPDU) { ++ if (ppdu_info->cmn_mpdu_info.mpdu_count > HAL_RX_MAX_MPDU) { ath12k_warn(ar->ab, "MPDU count reached max limit\n"); return; } @@ -104,7 +104,7 @@ Signed-off-by: P Praneesh + mpdu_count = ppdu_info->cmn_mpdu_info.mpdu_count; + msdu_count = ppdu_info->cmn_mpdu_info.mon_mpdu[mpdu_count].msdu_count; if (ath12k_dp_pkt_set_pktlen(msdu, offset) || - msdu_count >= HAL_RX_MAX_MSDU) { + msdu_count > HAL_RX_MAX_MSDU) { dev_kfree_skb_any(msdu); @@ -2356,20 +2357,22 @@ ath12k_dp_mon_parse_rx_dest_tlv(struct a } @@ -147,7 +147,7 @@ Signed-off-by: P Praneesh if (!mon_mpdu) continue; -@@ -3566,6 +3569,23 @@ ath12k_dp_mon_rx_update_peer_mu_stats(st +@@ -3564,6 +3567,23 @@ ath12k_dp_mon_rx_update_peer_mu_stats(st ath12k_dp_mon_rx_update_user_stats(ar, ppdu_info, i); } @@ -156,7 +156,7 @@ Signed-off-by: P Praneesh +{ + int i, len; + -+ len = (sizeof(struct hal_rx_mon_ppdu_info) - ++ len = (sizeof(struct hal_rx_mon_ppdu_info) - + sizeof(struct hal_rx_mon_cmn_mpdu_info)); + + memset(ppdu_info, 0, len); @@ -171,7 +171,7 @@ Signed-off-by: P Praneesh int ath12k_dp_mon_srng_process(struct ath12k *ar, int mac_id, int *budget, bool flag, struct napi_struct *napi) { -@@ -3659,7 +3679,7 @@ move_next: +@@ -3652,7 +3672,7 @@ move_next: return 0; if (!ppdu_info->ppdu_continuation) @@ -180,7 +180,7 @@ Signed-off-by: P Praneesh while ((skb = __skb_dequeue(&skb_list))) { if (flag == ATH12K_DP_RX_MONITOR_MODE) -@@ -3704,7 +3724,7 @@ next_skb: +@@ -3697,7 +3717,7 @@ next_skb: rcu_read_unlock(); free_skb: dev_kfree_skb_any(skb); @@ -189,7 +189,7 @@ Signed-off-by: P Praneesh ppdu_info->peer_id = HAL_INVALID_PEERID; } -@@ -3813,7 +3833,7 @@ move_next: +@@ -3801,7 +3821,7 @@ move_next: return 0; if (!ppdu_info->ppdu_continuation) @@ -198,7 +198,7 @@ Signed-off-by: P Praneesh while ((skb = __skb_dequeue(&skb_list))) { -@@ -3858,7 +3878,7 @@ next_skb: +@@ -3846,7 +3866,7 @@ next_skb: rcu_read_unlock(); free_skb: dev_kfree_skb_any(skb); diff --git a/feeds/ipq95xx/mac80211/patches/qca/664-d-ath12k-Remove-mod-operator-overhead-for-dst-ring-acc.patch b/feeds/ipq95xx/mac80211/patches/qca/664-d-ath12k-Remove-mod-operator-overhead-for-dst-ring-acc.patch index 7e98e4250..1989a41b7 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/664-d-ath12k-Remove-mod-operator-overhead-for-dst-ring-acc.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/664-d-ath12k-Remove-mod-operator-overhead-for-dst-ring-acc.patch @@ -15,7 +15,7 @@ Signed-off-by: Pradeep Kumar Chitrapu --- a/drivers/net/wireless/ath/ath12k/dp.h +++ b/drivers/net/wireless/ath/ath12k/dp.h -@@ -77,8 +77,6 @@ struct dp_rxdma_ring { +@@ -40,8 +40,6 @@ struct dp_rxdma_ring { int bufs_max; }; @@ -26,20 +26,21 @@ Signed-off-by: Pradeep Kumar Chitrapu struct dp_srng tcl_data_ring; --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -759,9 +759,10 @@ void ath12k_dp_tx_completion_handler(str +@@ -772,10 +772,11 @@ void ath12k_dp_tx_completion_handler(str struct sk_buff *msdu; struct hal_tx_status ts = { 0 }; struct dp_tx_ring *tx_ring = &dp->tx_ring[ring_id]; - u32 *desc; + u32 *desc, desc_id; u8 mac_id; + u64 desc_va; - int valid_entries; + int valid_entries, count = 0, i = 0; + struct hal_wbm_completion_ring_tx *tx_status; spin_lock_bh(&status_ring->lock); -@@ -776,32 +777,21 @@ void ath12k_dp_tx_completion_handler(str +@@ -790,32 +791,21 @@ void ath12k_dp_tx_completion_handler(str ath12k_hal_srng_dst_invalidate_entry(ab, status_ring, valid_entries); @@ -55,7 +56,7 @@ Signed-off-by: Pradeep Kumar Chitrapu - } + count++; -- if ((ath12k_hal_srng_dst_peek(ab, status_ring) != NULL) && +- if (ath12k_hal_srng_dst_peek(ab, status_ring) && - (ATH12K_TX_COMPL_NEXT(tx_ring->tx_status_head) == tx_ring->tx_status_tail)) { - /* TODO: Process pending tx_status messages when kfifo_is_full() */ - ath12k_warn(ab, "Unable to process some of the tx_status ring desc because status_fifo is full\n"); @@ -78,10 +79,10 @@ Signed-off-by: Pradeep Kumar Chitrapu + tx_status = &tx_ring->tx_status[i++]; ath12k_dp_tx_status_parse(ab, tx_status, &ts); - if (FIELD_GET(HAL_WBM_COMPL_TX_INFO0_CC_DONE, tx_status->info0)) { + if (u32_get_bits(tx_status->info0, HAL_WBM_COMPL_TX_INFO0_CC_DONE)) { --- a/drivers/net/wireless/ath/ath12k/hal.c +++ b/drivers/net/wireless/ath/ath12k/hal.c -@@ -963,8 +963,7 @@ u32 *ath12k_hal_srng_dst_get_next_entry( +@@ -1596,8 +1596,7 @@ u32 *ath12k_hal_srng_dst_get_next_entry( desc = srng->ring_base_vaddr + srng->u.dst_ring.tp; @@ -91,7 +92,7 @@ Signed-off-by: Pradeep Kumar Chitrapu /* wrap around to start of ring*/ if (srng->u.dst_ring.tp == srng->ring_size) -@@ -988,8 +987,11 @@ u32 *ath12k_hal_srng_dst_get_next_cache_ +@@ -1621,8 +1620,11 @@ u32 *ath12k_hal_srng_dst_get_next_cache_ desc = srng->ring_base_vaddr + srng->u.dst_ring.tp; diff --git a/feeds/ipq95xx/mac80211/patches/qca/664-f-ath12k-Optimize-tx-completions-in-case-of-stats-disa.patch b/feeds/ipq95xx/mac80211/patches/qca/664-f-ath12k-Optimize-tx-completions-in-case-of-stats-disa.patch index 2c9ed800a..c57fd8a9a 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/664-f-ath12k-Optimize-tx-completions-in-case-of-stats-disa.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/664-f-ath12k-Optimize-tx-completions-in-case-of-stats-disa.patch @@ -14,11 +14,9 @@ Signed-off-by: Pradeep Kumar Chitrapu drivers/net/wireless/ath/ath12k/dp_tx.c | 100 +++++++++++++----------- 1 file changed, 55 insertions(+), 45 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c -index 9562b9a7c965..9be5ef95536f 100644 --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -600,9 +600,37 @@ err_out: +@@ -611,9 +611,37 @@ err_out: spin_unlock_bh(&ab->base_lock); } @@ -57,7 +55,7 @@ index 9562b9a7c965..9be5ef95536f 100644 { struct ieee80211_tx_status status = { 0 }; -@@ -612,10 +640,12 @@ static void ath12k_dp_tx_complete_msdu(struct ath12k *ar, +@@ -623,10 +651,12 @@ static void ath12k_dp_tx_complete_msdu(s struct ath12k_peer *peer; struct ath12k_sta *arsta; struct rate_info rate; @@ -71,7 +69,7 @@ index 9562b9a7c965..9be5ef95536f 100644 /* Must not happen */ return; } -@@ -629,11 +659,14 @@ static void ath12k_dp_tx_complete_msdu(struct ath12k *ar, +@@ -640,11 +670,14 @@ static void ath12k_dp_tx_complete_msdu(s flags = skb_cb->flags; @@ -87,7 +85,7 @@ index 9562b9a7c965..9be5ef95536f 100644 HAL_WBM_TQM_REL_REASON_FRAME_ACKED; } if (skb_has_frag_list(msdu)) { -@@ -644,6 +677,8 @@ static void ath12k_dp_tx_complete_msdu(struct ath12k *ar, +@@ -655,6 +688,8 @@ static void ath12k_dp_tx_complete_msdu(s return; } @@ -96,7 +94,7 @@ index 9562b9a7c965..9be5ef95536f 100644 rcu_read_lock(); if (!rcu_dereference(ab->pdevs_active[ar->pdev_idx])) { -@@ -662,47 +697,47 @@ static void ath12k_dp_tx_complete_msdu(struct ath12k *ar, +@@ -673,48 +708,48 @@ static void ath12k_dp_tx_complete_msdu(s /* skip tx rate update from ieee80211_status*/ info->status.rates[0].idx = -1; @@ -107,7 +105,7 @@ index 9562b9a7c965..9be5ef95536f 100644 info->status.ack_signal = ATH12K_DEFAULT_NOISE_FLOOR + - ts->ack_rssi; + ts.ack_rssi; - info->status.is_valid_ack_signal = true; + info->status.flags = IEEE80211_TX_STATUS_ACK_SIGNAL_VALID; } - if (ts->status == HAL_WBM_TQM_REL_REASON_CMD_REMOVE_TX && @@ -115,7 +113,8 @@ index 9562b9a7c965..9be5ef95536f 100644 (info->flags & IEEE80211_TX_CTL_NO_ACK)) info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; - if (ath12k_debugfs_is_extd_tx_stats_enabled(ar) || ab->hw_params.single_pdev_only) { + if (ath12k_debugfs_is_extd_tx_stats_enabled(ar) || + ab->hw_params->single_pdev_only) { - if (ts->flags & HAL_TX_STATUS_FLAGS_FIRST_MSDU) { + if (ts.flags & HAL_TX_STATUS_FLAGS_FIRST_MSDU) { if (ar->last_ppdu_id == 0) { @@ -156,16 +155,16 @@ index 9562b9a7c965..9be5ef95536f 100644 spin_unlock_bh(&ab->base_lock); dev_kfree_skb_any(msdu); goto exit; -@@ -723,32 +758,6 @@ exit: +@@ -735,33 +770,6 @@ exit: rcu_read_unlock(); } --static inline void ath12k_dp_tx_status_parse(struct ath12k_base *ab, -- struct hal_wbm_completion_ring_tx *desc, -- struct hal_tx_status *ts) +-static void ath12k_dp_tx_status_parse(struct ath12k_base *ab, +- struct hal_wbm_completion_ring_tx *desc, +- struct hal_tx_status *ts) -{ - ts->buf_rel_source = -- FIELD_GET(HAL_WBM_COMPL_TX_INFO0_REL_SRC_MODULE, desc->info0); +- u32_get_bits(desc->info0, HAL_WBM_COMPL_TX_INFO0_REL_SRC_MODULE); - if (ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_FW && - ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM) - return; @@ -173,10 +172,11 @@ index 9562b9a7c965..9be5ef95536f 100644 - if (ts->buf_rel_source == HAL_WBM_REL_SRC_MODULE_FW) - return; - -- ts->status = FIELD_GET(HAL_WBM_COMPL_TX_INFO0_TQM_RELEASE_REASON, -- desc->info0); -- ts->ppdu_id = FIELD_GET(HAL_WBM_COMPL_TX_INFO1_TQM_STATUS_NUMBER, -- desc->info1); +- ts->status = u32_get_bits(desc->info0, +- HAL_WBM_COMPL_TX_INFO0_TQM_RELEASE_REASON); +- +- ts->ppdu_id = u32_get_bits(desc->info1, +- HAL_WBM_COMPL_TX_INFO1_TQM_STATUS_NUMBER); - if (desc->rate_stats.info0 & HAL_TX_RATE_STATS_INFO0_VALID) - ts->rate_stats = desc->rate_stats.info0; - else @@ -189,7 +189,7 @@ index 9562b9a7c965..9be5ef95536f 100644 static inline bool ath12k_dp_tx_completion_valid(struct hal_wbm_release_ring *desc) { struct htt_tx_wbm_completion *status_desc; -@@ -773,12 +782,12 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id) +@@ -786,13 +794,13 @@ void ath12k_dp_tx_completion_handler(str struct hal_srng *status_ring = &ab->hal.srng_list[hal_ring_id]; struct ath12k_tx_desc_info *tx_desc = NULL; struct sk_buff *msdu; @@ -197,21 +197,22 @@ index 9562b9a7c965..9be5ef95536f 100644 struct dp_tx_ring *tx_ring = &dp->tx_ring[ring_id]; u32 *desc, desc_id; u8 mac_id; + u64 desc_va; int valid_entries, count = 0, i = 0; struct hal_wbm_completion_ring_tx *tx_status; + enum hal_wbm_rel_src_module buf_rel_source; spin_lock_bh(&status_ring->lock); -@@ -808,7 +817,6 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id) +@@ -825,7 +833,6 @@ void ath12k_dp_tx_completion_handler(str while (count--) { tx_status = &tx_ring->tx_status[i++]; - ath12k_dp_tx_status_parse(ab, tx_status, &ts); - if (FIELD_GET(HAL_WBM_COMPL_TX_INFO0_CC_DONE, tx_status->info0)) { + if (u32_get_bits(tx_status->info0, HAL_WBM_COMPL_TX_INFO0_CC_DONE)) { /* HW done cookie conversion */ -@@ -833,7 +841,9 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id) +@@ -851,7 +858,9 @@ void ath12k_dp_tx_completion_handler(str * to reduce contention */ ath12k_dp_tx_release_txbuf(dp, tx_desc, tx_desc->pool_id); @@ -222,7 +223,7 @@ index 9562b9a7c965..9be5ef95536f 100644 ath12k_dp_tx_process_htt_tx_complete(ab, (void *)tx_status, mac_id, msdu, -@@ -846,7 +856,7 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id) +@@ -864,7 +873,7 @@ void ath12k_dp_tx_completion_handler(str if (atomic_dec_and_test(&ar->dp.num_tx_pending)) wake_up(&ar->dp.tx_empty_waitq); @@ -231,6 +232,3 @@ index 9562b9a7c965..9be5ef95536f 100644 } } --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/664-h-ath12k-fix-transmitting-packets-during-recovery.patch b/feeds/ipq95xx/mac80211/patches/qca/664-h-ath12k-fix-transmitting-packets-during-recovery.patch index 37967ddf6..b33c98b79 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/664-h-ath12k-fix-transmitting-packets-during-recovery.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/664-h-ath12k-fix-transmitting-packets-during-recovery.patch @@ -21,25 +21,9 @@ Signed-off-by: Pradeep Kumar Chitrapu drivers/net/wireless/ath/ath12k/mac.c | 5 +++++ 2 files changed, 8 insertions(+) -diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c -index cbe14ec7cb1a..0490dfcfa695 100644 ---- a/drivers/net/wireless/ath/ath12k/dp_tx.c -+++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -882,6 +882,9 @@ int ath12k_dp_tx_send_reo_cmd(struct ath12k_base *ab, struct dp_rx_tid *rx_tid, - struct hal_srng *cmd_ring; - int cmd_num; - -+ if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags)) -+ return -ESHUTDOWN; -+ - cmd_ring = &ab->hal.srng_list[dp->reo_cmd_ring.ring_id]; - cmd_num = ath12k_hal_reo_cmd_send(ab, cmd_ring, type, cmd); - -diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index 4c80e4793fb1..1cd1b514b7a2 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -6689,6 +6689,11 @@ static void ath12k_mac_op_tx(struct ieee80211_hw *hw, +@@ -6745,6 +6745,11 @@ static void ath12k_mac_op_tx(struct ieee return; } @@ -51,6 +35,15 @@ index 4c80e4793fb1..1cd1b514b7a2 100644 memset(skb_cb, 0, sizeof(*skb_cb)); skb_cb->vif = vif; --- -2.17.1 - +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -648,6 +648,9 @@ static int ath12k_dp_reo_cmd_send(struct + struct hal_srng *cmd_ring; + int cmd_num; + ++ if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags)) ++ return -ESHUTDOWN; ++ + cmd_ring = &ab->hal.srng_list[dp->reo_cmd_ring.ring_id]; + cmd_num = ath12k_hal_reo_cmd_send(ab, cmd_ring, type, cmd); + diff --git a/feeds/ipq95xx/mac80211/patches/qca/664-j-ath12k-add-branch-predictors-in-dp_tx.patch b/feeds/ipq95xx/mac80211/patches/qca/664-j-ath12k-add-branch-predictors-in-dp_tx.patch index 24e79ef46..8d8a27278 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/664-j-ath12k-add-branch-predictors-in-dp_tx.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/664-j-ath12k-add-branch-predictors-in-dp_tx.patch @@ -21,7 +21,7 @@ Signed-off-by: Pradeep Kumar Chitrapu spin_unlock_bh(&dp->tx_desc_lock[ring_id]); ath12k_warn(dp->ab, "failed to allocate data Tx buffer\n"); return NULL; -@@ -142,11 +142,11 @@ int ath12k_dp_tx(struct ath12k *ar, stru +@@ -145,11 +145,11 @@ int ath12k_dp_tx(struct ath12k *ar, stru bool tcl_ring_retry; bool msdu_ext_desc = false; @@ -36,7 +36,7 @@ Signed-off-by: Pradeep Kumar Chitrapu return -ENOTSUPP; /* Let the default ring selection be based on current processor -@@ -168,7 +168,7 @@ tcl_ring_sel: +@@ -171,7 +171,7 @@ tcl_ring_sel: tx_ring = &dp->tx_ring[ti.ring_id]; tx_desc = ath12k_dp_tx_assign_buffer(dp, ti.ring_id); @@ -45,18 +45,18 @@ Signed-off-by: Pradeep Kumar Chitrapu ab->soc_stats.tx_err.txbuf_na[ti.ring_id]++; if (ring_map == (BIT(DP_TCL_NUM_RING_MAX) - 1)) return -ENOSPC; -@@ -200,8 +200,8 @@ tcl_ring_sel: +@@ -203,8 +203,8 @@ tcl_ring_sel: ti.bss_ast_idx = arvif->ast_idx; ti.dscp_tid_tbl_idx = 0; - if (skb->ip_summed == CHECKSUM_PARTIAL && - ti.encap_type != HAL_TCL_ENCAP_TYPE_RAW) { + if (likely(skb->ip_summed == CHECKSUM_PARTIAL && -+ ti.encap_type != HAL_TCL_ENCAP_TYPE_RAW)) { - ti.flags0 |= FIELD_PREP(HAL_TCL_DATA_CMD_INFO2_IP4_CKSUM_EN, 1) | - FIELD_PREP(HAL_TCL_DATA_CMD_INFO2_UDP4_CKSUM_EN, 1) | - FIELD_PREP(HAL_TCL_DATA_CMD_INFO2_UDP6_CKSUM_EN, 1) | -@@ -235,15 +235,15 @@ tcl_ring_sel: ++ ti.encap_type != HAL_TCL_ENCAP_TYPE_RAW)) { + ti.flags0 |= u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_IP4_CKSUM_EN) | + u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_UDP4_CKSUM_EN) | + u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_UDP6_CKSUM_EN) | +@@ -238,15 +238,15 @@ tcl_ring_sel: } ti.paddr = dma_map_single(ab->dev, skb->data, skb->len, DMA_TO_DEVICE); @@ -75,16 +75,16 @@ Signed-off-by: Pradeep Kumar Chitrapu msdu_ext_desc = true; if (skb->protocol == cpu_to_be16(ETH_P_PAE)) { -@@ -252,7 +252,7 @@ tcl_ring_sel: +@@ -255,7 +255,7 @@ tcl_ring_sel: } } - if (arvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW) { + if (unlikely(arvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW)) { - if (skb_cb->flags & ATH12K_SKB_CIPHER_SET) { - ti.encrypt_type = - ath12k_dp_tx_get_encrypt_type(skb_cb->cipher); -@@ -272,7 +272,7 @@ tcl_ring_sel: + if (skb->protocol == cpu_to_be16(ETH_P_ARP)) { + ti.encap_type = HAL_TCL_ENCAP_TYPE_RAW; + ti.encrypt_type = HAL_ENCRYPT_TYPE_OPEN; +@@ -281,7 +281,7 @@ tcl_ring_sel: skb_cb->vif = arvif->vif; skb_cb->ar = ar; @@ -93,25 +93,27 @@ Signed-off-by: Pradeep Kumar Chitrapu skb_ext_desc = dev_alloc_skb(sizeof(struct hal_tx_msdu_ext_desc)); if (!skb_ext_desc) { ret = -ENOMEM; -@@ -307,7 +307,7 @@ tcl_ring_sel: +@@ -316,7 +316,7 @@ tcl_ring_sel: ath12k_hal_srng_access_begin(ab, tcl_ring); - hal_tcl_desc = (void *)ath12k_hal_srng_src_get_next_entry(ab, tcl_ring); + hal_tcl_desc = ath12k_hal_srng_src_get_next_entry(ab, tcl_ring); - if (!hal_tcl_desc) { + if (unlikely(!hal_tcl_desc)) { /* NOTE: It is highly unlikely we'll be running out of tcl_ring * desc because the desc is directly enqueued onto hw queue. */ -@@ -321,7 +321,7 @@ tcl_ring_sel: +@@ -330,8 +330,8 @@ tcl_ring_sel: * checking this ring earlier for each pkt tx. * Restart ring selection if some rings are not checked yet. */ -- if (ring_map != (BIT(DP_TCL_NUM_RING_MAX) - 1)) { -+ if (unlikely(ring_map != (BIT(DP_TCL_NUM_RING_MAX) - 1))) { +- if (ring_map != (BIT(ab->hw_params->max_tx_ring) - 1) && +- ab->hw_params->tcl_ring_retry) { ++ if (unlikely(ring_map != (BIT(ab->hw_params->max_tx_ring) - 1) && ++ ab->hw_params->tcl_ring_retry)) { tcl_ring_retry = true; ring_selector++; } -@@ -365,7 +365,7 @@ static void ath12k_dp_tx_free_txbuf(stru +@@ -375,7 +375,7 @@ static void ath12k_dp_tx_free_txbuf(stru skb_cb = ATH12K_SKB_CB(msdu); dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); @@ -120,7 +122,7 @@ Signed-off-by: Pradeep Kumar Chitrapu dma_unmap_single(ab->dev, skb_cb->paddr_ext_desc, sizeof(struct hal_tx_msdu_ext_desc), DMA_TO_DEVICE); -@@ -397,7 +397,7 @@ ath12k_dp_tx_htt_tx_complete_buf(struct +@@ -407,7 +407,7 @@ ath12k_dp_tx_htt_tx_complete_buf(struct wake_up(&ar->dp.tx_empty_waitq); dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); @@ -129,7 +131,7 @@ Signed-off-by: Pradeep Kumar Chitrapu dma_unmap_single(ab->dev, skb_cb->paddr_ext_desc, sizeof(struct hal_tx_msdu_ext_desc), DMA_TO_DEVICE); -@@ -652,7 +652,7 @@ static void ath12k_dp_tx_complete_msdu(s +@@ -663,7 +663,7 @@ static void ath12k_dp_tx_complete_msdu(s u8 flags = 0; @@ -138,7 +140,7 @@ Signed-off-by: Pradeep Kumar Chitrapu /* Must not happen */ return; } -@@ -660,7 +660,7 @@ static void ath12k_dp_tx_complete_msdu(s +@@ -671,7 +671,7 @@ static void ath12k_dp_tx_complete_msdu(s skb_cb = ATH12K_SKB_CB(msdu); dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); @@ -147,7 +149,7 @@ Signed-off-by: Pradeep Kumar Chitrapu dma_unmap_single(ab->dev, skb_cb->paddr_ext_desc, sizeof(struct hal_tx_msdu_ext_desc), DMA_TO_DEVICE); -@@ -686,12 +686,12 @@ static void ath12k_dp_tx_complete_msdu(s +@@ -697,12 +697,12 @@ static void ath12k_dp_tx_complete_msdu(s ath12k_dp_tx_status_parse(ab, tx_status, &ts); @@ -162,17 +164,18 @@ Signed-off-by: Pradeep Kumar Chitrapu dev_kfree_skb_any(msdu); return; } -@@ -716,7 +716,8 @@ static void ath12k_dp_tx_complete_msdu(s +@@ -727,8 +727,8 @@ static void ath12k_dp_tx_complete_msdu(s (info->flags & IEEE80211_TX_CTL_NO_ACK)) info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; -- if (ath12k_debugfs_is_extd_tx_stats_enabled(ar) || ab->hw_params.single_pdev_only) { +- if (ath12k_debugfs_is_extd_tx_stats_enabled(ar) || +- ab->hw_params->single_pdev_only) { + if (unlikely(ath12k_debugfs_is_extd_tx_stats_enabled(ar)) || -+ ab->hw_params.single_pdev_only) { ++ ab->hw_params->single_pdev_only) { if (ts.flags & HAL_TX_STATUS_FLAGS_FIRST_MSDU) { if (ar->last_ppdu_id == 0) { ar->last_ppdu_id = ts.ppdu_id; -@@ -741,10 +742,10 @@ static void ath12k_dp_tx_complete_msdu(s +@@ -753,10 +753,10 @@ static void ath12k_dp_tx_complete_msdu(s spin_lock_bh(&ab->base_lock); peer = ath12k_peer_find_by_id(ab, ts.peer_id); @@ -187,16 +190,16 @@ Signed-off-by: Pradeep Kumar Chitrapu spin_unlock_bh(&ab->base_lock); dev_kfree_skb_any(msdu); return; -@@ -827,7 +828,7 @@ void ath12k_dp_tx_completion_handler(str +@@ -840,7 +840,7 @@ void ath12k_dp_tx_completion_handler(str while (count--) { tx_status = &tx_ring->tx_status[i++]; -- if (FIELD_GET(HAL_WBM_COMPL_TX_INFO0_CC_DONE, tx_status->info0)) { -+ if (likely(FIELD_GET(HAL_WBM_COMPL_TX_INFO0_CC_DONE, tx_status->info0))) { +- if (u32_get_bits(tx_status->info0, HAL_WBM_COMPL_TX_INFO0_CC_DONE)) { ++ if (likely(u32_get_bits(tx_status->info0, HAL_WBM_COMPL_TX_INFO0_CC_DONE))) { /* HW done cookie conversion */ - tx_desc = (struct ath12k_tx_desc_info *)(uintptr_t) - (tx_status->buf_va_lo | -@@ -839,7 +840,7 @@ void ath12k_dp_tx_completion_handler(str + desc_va = ((u64)tx_status->buf_va_hi << 32 | + tx_status->buf_va_lo); +@@ -852,7 +852,7 @@ void ath12k_dp_tx_completion_handler(str tx_desc = ath12k_dp_get_tx_desc(ab, desc_id); } diff --git a/feeds/ipq95xx/mac80211/patches/qca/664-k-ath12k-Make-use-of-TID-classification-offload.patch b/feeds/ipq95xx/mac80211/patches/qca/664-k-ath12k-Make-use-of-TID-classification-offload.patch index 8bd28ec8a..597d4fabe 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/664-k-ath12k-Make-use-of-TID-classification-offload.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/664-k-ath12k-Make-use-of-TID-classification-offload.patch @@ -13,11 +13,9 @@ Signed-off-by: Pradeep Kumar Chitrapu drivers/net/wireless/ath/ath12k/mac.c | 1 + 3 files changed, 2 insertions(+), 19 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c -index 5bbd20f82f2f..fd908f900fb4 100644 --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -39,19 +39,6 @@ static void ath12k_dp_tx_encap_nwifi(struct sk_buff *skb) +@@ -39,19 +39,6 @@ static void ath12k_dp_tx_encap_nwifi(str hdr->frame_control &= ~__cpu_to_le16(IEEE80211_STYPE_QOS_DATA); } @@ -37,36 +35,32 @@ index 5bbd20f82f2f..fd908f900fb4 100644 enum hal_encrypt_type ath12k_dp_tx_get_encrypt_type(u32 cipher) { switch (cipher) { -@@ -209,10 +196,6 @@ tcl_ring_sel: - FIELD_PREP(HAL_TCL_DATA_CMD_INFO2_TCP6_CKSUM_EN, 1); +@@ -212,10 +199,6 @@ tcl_ring_sel: + u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_TCP6_CKSUM_EN); } -- ti.flags1 |= FIELD_PREP(HAL_TCL_DATA_CMD_INFO3_TID_OVERWRITE, 1); +- ti.flags1 |= u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO3_TID_OVERWRITE); - - ti.tid = ath12k_dp_tx_get_tid(skb); - switch (ti.encap_type) { case HAL_TCL_ENCAP_TYPE_NATIVE_WIFI: ath12k_dp_tx_encap_nwifi(skb); -diff --git a/drivers/net/wireless/ath/ath12k/hal_tx.c b/drivers/net/wireless/ath/ath12k/hal_tx.c -index ffb65ff93d14..81c087ddf6c8 100644 --- a/drivers/net/wireless/ath/ath12k/hal_tx.c +++ b/drivers/net/wireless/ath/ath12k/hal_tx.c -@@ -61,8 +61,7 @@ void ath12k_hal_tx_cmd_desc_setup(struct ath12k_base *ab, void *cmd, - FIELD_PREP(HAL_TCL_DATA_CMD_INFO2_DATA_LEN, ti->data_len) | - FIELD_PREP(HAL_TCL_DATA_CMD_INFO2_PKT_OFFSET, ti->pkt_offset); +@@ -60,8 +60,7 @@ void ath12k_hal_tx_cmd_desc_setup(struct + u32_encode_bits(ti->data_len, HAL_TCL_DATA_CMD_INFO2_DATA_LEN) | + u32_encode_bits(ti->pkt_offset, HAL_TCL_DATA_CMD_INFO2_PKT_OFFSET); - tcl_cmd->info3 = (ti->flags1 | -- FIELD_PREP(HAL_TCL_DATA_CMD_INFO3_TID, ti->tid)) | +- u32_encode_bits(ti->tid, HAL_TCL_DATA_CMD_INFO3_TID)) | + tcl_cmd->info3 = ti->flags1 | - FIELD_PREP(HAL_TCL_DATA_CMD_INFO3_PMAC_ID, ti->lmac_id) | - FIELD_PREP(HAL_TCL_DATA_CMD_INFO3_VDEV_ID, ti->vdev_id); + u32_encode_bits(ti->lmac_id, HAL_TCL_DATA_CMD_INFO3_PMAC_ID) | + u32_encode_bits(ti->vdev_id, HAL_TCL_DATA_CMD_INFO3_VDEV_ID); -diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index 1cd1b514b7a2..5af1732e19f5 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -10855,6 +10855,7 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah) +@@ -10929,6 +10929,7 @@ static int ath12k_mac_hw_register(struct ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER); ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU); ieee80211_hw_set(hw, USES_RSS); @@ -74,6 +68,3 @@ index 1cd1b514b7a2..5af1732e19f5 100644 if (ath12k_frame_mode == ATH12K_HW_TXRX_ETHERNET) { ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD); --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/665-ath12k-Update-obss-color-detection-notify-to-queue-work.patch b/feeds/ipq95xx/mac80211/patches/qca/665-ath12k-Update-obss-color-detection-notify-to-queue-work.patch index 0692f8a8e..2d98989aa 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/665-ath12k-Update-obss-color-detection-notify-to-queue-work.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/665-ath12k-Update-obss-color-detection-notify-to-queue-work.patch @@ -25,7 +25,7 @@ Signed-off-by: Manish Dharanenthiran --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h -@@ -353,6 +353,8 @@ struct ath12k_vif { +@@ -358,6 +358,8 @@ struct ath12k_vif { struct dentry *debugfs_twt; #endif /* CPTCFG_ATH12K_DEBUGFS */ struct work_struct update_bcn_template_work; @@ -36,7 +36,7 @@ Signed-off-by: Manish Dharanenthiran struct ath12k_vif_iter { --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -7175,6 +7175,23 @@ static void ath12k_update_bcn_template_w +@@ -7385,6 +7385,26 @@ static void ath12k_update_bcn_template_w arvif->vdev_id, ret); } @@ -46,13 +46,16 @@ Signed-off-by: Manish Dharanenthiran + update_obss_color_notify_work); + struct ath12k *ar; + -+ if (!arvif || !arvif->is_created) -+ return; -+ + ar = arvif->ar; + ++ if (!ar) ++ return; ++ + mutex_lock(&ar->conf_mutex); -+ ieeee80211_obss_color_collision_notify(arvif->vif, arvif->obss_color_bitmap); ++ if (arvif->is_created) ++ ieeee80211_obss_color_collision_notify(arvif->vif, ++ arvif->obss_color_bitmap, ++ GFP_KERNEL); + arvif->obss_color_bitmap = 0; + mutex_unlock(&ar->conf_mutex); +} @@ -60,7 +63,7 @@ Signed-off-by: Manish Dharanenthiran static int ath12k_mac_vdev_create(struct ath12k *ar, struct ieee80211_vif *vif) { struct ath12k_base *ab = ar->ab; -@@ -7516,7 +7533,9 @@ static int ath12k_mac_op_add_interface(s +@@ -7726,7 +7746,9 @@ static int ath12k_mac_op_add_interface(s INIT_LIST_HEAD(&arvif->list); arvif->key_cipher = INVALID_CIPHER; @@ -70,7 +73,7 @@ Signed-off-by: Manish Dharanenthiran 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_FORCE_SGI; -@@ -7574,6 +7593,7 @@ static void ath12k_mac_op_remove_interfa +@@ -7784,6 +7806,7 @@ static void ath12k_mac_op_remove_interfa struct ath12k_base *ab; int ret; @@ -80,7 +83,7 @@ Signed-off-by: Manish Dharanenthiran mutex_lock(&ah->conf_mutex); --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -8942,6 +8942,7 @@ ath12k_wmi_obss_color_collision_event(st +@@ -9001,6 +9001,7 @@ ath12k_wmi_obss_color_collision_event(st const void **tb; const struct wmi_obss_color_collision_event *ev; struct ath12k_vif *arvif; @@ -88,7 +91,7 @@ Signed-off-by: Manish Dharanenthiran int ret; tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); -@@ -8955,7 +8956,7 @@ ath12k_wmi_obss_color_collision_event(st +@@ -9014,7 +9015,7 @@ ath12k_wmi_obss_color_collision_event(st ev = tb[WMI_TAG_OBSS_COLOR_COLLISION_EVT]; if (!ev) { ath12k_warn(ab, "failed to fetch obss color collision ev"); @@ -97,7 +100,7 @@ Signed-off-by: Manish Dharanenthiran } arvif = ath12k_mac_get_arvif_by_vdev_id(ab, ev->vdev_id); -@@ -8963,16 +8964,21 @@ ath12k_wmi_obss_color_collision_event(st +@@ -9022,17 +9023,20 @@ ath12k_wmi_obss_color_collision_event(st { ath12k_warn(ab, "failed to find arvif with vedv id %d in obss_color_collision_event\n", ev->vdev_id); @@ -107,7 +110,8 @@ Signed-off-by: Manish Dharanenthiran + switch (ev->evt_type) { case WMI_BSS_COLOR_COLLISION_DETECTION: -- ieeee80211_obss_color_collision_notify(arvif->vif, ev->obss_color_bitmap); +- ieeee80211_obss_color_collision_notify(arvif->vif, ev->obss_color_bitmap, +- GFP_KERNEL); + ar = arvif->ar; + arvif->obss_color_bitmap = ev->obss_color_bitmap; @@ -116,13 +120,12 @@ Signed-off-by: Manish Dharanenthiran ev->vdev_id, ev->evt_type, ev->obss_color_bitmap); - break; + rcu_read_unlock(); -+ + ieee80211_queue_work(ar->ah->hw, &arvif->update_obss_color_notify_work); + goto exit; case WMI_BSS_COLOR_COLLISION_DISABLE: case WMI_BSS_COLOR_FREE_SLOT_TIMER_EXPIRY: case WMI_BSS_COLOR_FREE_SLOT_AVAILABLE: -@@ -8982,9 +8988,10 @@ ath12k_wmi_obss_color_collision_event(st +@@ -9042,9 +9046,10 @@ ath12k_wmi_obss_color_collision_event(st goto exit; } @@ -130,7 +133,7 @@ Signed-off-by: Manish Dharanenthiran + rcu_read_unlock(); exit: kfree(tb); -- rcu_read_unlock(); +- rcu_read_unock(); } static void ath12k_wmi_tlv_op_rx(struct ath12k_base *ab, struct sk_buff *skb) diff --git a/feeds/ipq95xx/mac80211/patches/qca/665-ath12k-Update-wbm_tx_stats-upon-tx-completion.patch b/feeds/ipq95xx/mac80211/patches/qca/665-ath12k-Update-wbm_tx_stats-upon-tx-completion.patch index d6866bf66..eb68d7f57 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/665-ath12k-Update-wbm_tx_stats-upon-tx-completion.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/665-ath12k-Update-wbm_tx_stats-upon-tx-completion.patch @@ -13,11 +13,9 @@ Signed-off-by: Dinesh Karthikeyan drivers/net/wireless/ath/ath12k/mac.c | 9 +++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) -diff --git a/drivers/net/wireless/ath/ath12k/debugfs_sta.c b/drivers/net/wireless/ath/ath12k/debugfs_sta.c -index 826d6e1..4da9f97 100644 --- a/drivers/net/wireless/ath/ath12k/debugfs_sta.c +++ b/drivers/net/wireless/ath/ath12k/debugfs_sta.c -@@ -210,8 +210,15 @@ static ssize_t ath12k_dbg_sta_dump_tx_stats(struct file *file, +@@ -210,8 +210,15 @@ static ssize_t ath12k_dbg_sta_dump_tx_st const int size = 2 * 4096; char *buf, mu_group_id[MAX_MU_GROUP_LENGTH] = {0}; u32 index; @@ -34,7 +32,7 @@ index 826d6e1..4da9f97 100644 return -ENOENT; buf = kzalloc(size, GFP_KERNEL); -@@ -353,6 +360,14 @@ static ssize_t ath12k_dbg_sta_dump_tx_stats(struct file *file, +@@ -353,6 +360,14 @@ static ssize_t ath12k_dbg_sta_dump_tx_st len += scnprintf(buf + len, size - len, "ack fails\n %llu\n\n", arsta->tx_stats->ack_fails); @@ -49,11 +47,9 @@ index 826d6e1..4da9f97 100644 spin_unlock_bh(&ar->data_lock); if (len > size) -diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c -index bdaafd7..082caba 100644 --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -634,6 +634,7 @@ static void ath12k_dp_tx_complete_msdu(struct ath12k *ar, +@@ -645,6 +645,7 @@ static void ath12k_dp_tx_complete_msdu(s struct rate_info rate; struct hal_tx_status ts = { 0 }; enum hal_wbm_tqm_rel_reason rel_status; @@ -61,7 +57,7 @@ index bdaafd7..082caba 100644 struct ieee80211_vif *vif; u8 flags = 0; -@@ -684,6 +685,9 @@ static void ath12k_dp_tx_complete_msdu(struct ath12k *ar, +@@ -695,6 +696,9 @@ static void ath12k_dp_tx_complete_msdu(s return; } @@ -71,10 +67,10 @@ index bdaafd7..082caba 100644 vif = skb_cb->vif; info = IEEE80211_SKB_CB(msdu); -@@ -745,6 +749,12 @@ static void ath12k_dp_tx_complete_msdu(struct ath12k *ar, +@@ -756,6 +760,12 @@ static void ath12k_dp_tx_complete_msdu(s status.info = info; rate = arsta->last_txrate; - status.rate = &rate; + status.rates = &rate; + + if (unlikely(ath12k_debugfs_is_extd_tx_stats_enabled(ar))) { + if(arsta->wbm_tx_stats && wbm_status < HAL_WBM_REL_HTT_TX_COMP_STATUS_MAX) @@ -84,11 +80,9 @@ index bdaafd7..082caba 100644 spin_unlock_bh(&ab->base_lock); if (flags & ATH12K_SKB_HW_80211_ENCAP) -diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index f16a1d6..f3c1c1d 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -5212,6 +5212,11 @@ static int ath12k_mac_station_add(struct ath12k *ar, +@@ -5351,6 +5351,11 @@ static int ath12k_mac_station_add(struct ret = -ENOMEM; goto free_peer; } @@ -99,8 +93,8 @@ index f16a1d6..f3c1c1d 100644 + } } - if (ieee80211_vif_is_mesh(vif)) { -@@ -5247,6 +5252,8 @@ static int ath12k_mac_station_add(struct ath12k *ar, + ath12k_mac_ap_ps_recalc(ar); +@@ -5388,6 +5393,8 @@ static int ath12k_mac_station_add(struct free_tx_stats: kfree(arsta->tx_stats); arsta->tx_stats = NULL; @@ -109,7 +103,7 @@ index f16a1d6..f3c1c1d 100644 free_peer: ath12k_peer_delete(ar, arvif->vdev_id, sta->addr); free_rx_stats: -@@ -5327,6 +5334,8 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, +@@ -5468,6 +5475,8 @@ static int ath12k_mac_op_sta_state(struc kfree(arsta->tx_stats); arsta->tx_stats = NULL; @@ -118,6 +112,3 @@ index f16a1d6..f3c1c1d 100644 kfree(arsta->rx_stats); arsta->rx_stats = NULL; --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/665-ath12k-add-register-changes-for-QCN9274-version-2.patch b/feeds/ipq95xx/mac80211/patches/qca/665-ath12k-add-register-changes-for-QCN9274-version-2.patch index 981d6f8b9..3b1ed37dd 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/665-ath12k-add-register-changes-for-QCN9274-version-2.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/665-ath12k-add-register-changes-for-QCN9274-version-2.patch @@ -24,76 +24,9 @@ Signed-off-by: P Praneesh drivers/net/wireless/ath/ath12k/wmi.c | 1 + 11 files changed, 387 insertions(+), 112 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c -index 37dae2a..a7f6bb5 100644 ---- a/drivers/net/wireless/ath/ath12k/core.c -+++ b/drivers/net/wireless/ath/ath12k/core.c -@@ -81,7 +81,47 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { - .supports_ap_ps = true, - .credit_flow = false, - .wakeup_mhi = false, -- .alloc_cacheable_memory =true, -+ .alloc_cacheable_memory = true, -+ }, -+ { -+ .name = "qcn92xx hw2.0", -+ .hw_rev = ATH12K_HW_QCN92XX_HW20, -+ .fw = { -+ .dir = "QCN92XX/hw1.0", -+ .board_size = 256 * 1024, -+ .cal_offset = 128 * 1024, -+ }, -+ .max_radios = 1, -+ .single_pdev_only = false, -+ .qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_QCN92XX, -+ .hw_ops = &qcn92xx_ops, -+ .ring_mask = &ath12k_hw_ring_mask_qcn92xx, -+ .internal_sleep_clock = false, -+ .regs = &qcn92xx_v2_regs, -+ .host_ce_config = ath12k_host_ce_config_qcn92xx, -+ .ce_count = 16, -+ .target_ce_config = ath12k_target_ce_config_wlan_qcn92xx, -+ .target_ce_count = 12, -+ .svc_to_ce_map = ath12k_target_service_to_ce_map_wlan_qcn92xx, -+ .svc_to_ce_map_len = 21, -+ .rxdma1_enable = true, -+ .num_rxmda_per_pdev = 1, -+ .rx_mac_buf_ring = false, -+ .vdev_start_delay = false, -+ .interface_modes = BIT(NL80211_IFTYPE_STATION) | -+ BIT(NL80211_IFTYPE_AP) | -+ BIT(NL80211_IFTYPE_MESH_POINT), -+ .supports_monitor = true, -+ .idle_ps = false, -+ .cold_boot_calib = false, -+ .supports_suspend = false, -+ .hal_desc_sz = sizeof(struct hal_rx_desc_qcn92xx), -+ .num_tcl_banks = 48, -+ .fix_l1ss = false, -+ .supports_ap_ps = true, -+ .credit_flow = false, -+ .wakeup_mhi = false, -+ .alloc_cacheable_memory = true, - }, - }; - -diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h -index f5090e5..cbb28eb 100644 ---- a/drivers/net/wireless/ath/ath12k/core.h -+++ b/drivers/net/wireless/ath/ath12k/core.h -@@ -124,6 +124,7 @@ struct ath12k_skb_rxcb { - - enum ath12k_hw_rev { - ATH12K_HW_QCN92XX_HW10 = 0, -+ ATH12K_HW_QCN92XX_HW20 = 1, - }; - - #define ATH12K_DIAG_HW_ID_OFFSET 16 -diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c -index 455e608..24df514 100644 --- a/drivers/net/wireless/ath/ath12k/dp.c +++ b/drivers/net/wireless/ath/ath12k/dp.c -@@ -1242,7 +1242,8 @@ static void ath12k_dp_reoq_lut_cleanup(struct ath12k_base *ab) +@@ -1244,7 +1244,8 @@ static void ath12k_dp_reoq_lut_cleanup(s dp->reoq_lut.vaddr, dp->reoq_lut.paddr); dp->reoq_lut.vaddr = NULL; @@ -103,25 +36,25 @@ index 455e608..24df514 100644 } void ath12k_dp_free(struct ath12k_base *ab) -@@ -1274,7 +1275,7 @@ void ath12k_dp_cc_config(struct ath12k_base *ab) +@@ -1276,7 +1277,7 @@ void ath12k_dp_cc_config(struct ath12k_b u32 wbm_base = HAL_SEQ_WCSS_UMAC_WBM_REG; u32 val = 0; - ath12k_hif_write32(ab, reo_base + HAL_REO1_SW_COOKIE_CFG0, cmem_base); + ath12k_hif_write32(ab, reo_base + HAL_REO1_SW_COOKIE_CFG0(ab), cmem_base); - val |= FIELD_PREP(HAL_REO1_SW_COOKIE_CFG_CMEM_BASE_ADDR_MSB, - ATH12K_CMEM_ADDR_MSB) | -@@ -1284,7 +1285,7 @@ void ath12k_dp_cc_config(struct ath12k_base *ab) - FIELD_PREP(HAL_REO1_SW_COOKIE_CFG_ENABLE, 1) | - FIELD_PREP(HAL_REO1_SW_COOKIE_CFG_GLOBAL_ENABLE, 1); + val |= u32_encode_bits(ATH12K_CMEM_ADDR_MSB, + HAL_REO1_SW_COOKIE_CFG_CMEM_BASE_ADDR_MSB) | +@@ -1288,7 +1289,7 @@ void ath12k_dp_cc_config(struct ath12k_b + u32_encode_bits(1, HAL_REO1_SW_COOKIE_CFG_ENABLE) | + u32_encode_bits(1, HAL_REO1_SW_COOKIE_CFG_GLOBAL_ENABLE); - ath12k_hif_write32(ab, reo_base + HAL_REO1_SW_COOKIE_CFG1, val); + ath12k_hif_write32(ab, reo_base + HAL_REO1_SW_COOKIE_CFG1(ab), val); /* Enable HW CC for WBM */ ath12k_hif_write32(ab, wbm_base + HAL_WBM_SW_COOKIE_CFG0, cmem_base); -@@ -1505,15 +1506,16 @@ static int ath12k_dp_reoq_lut_setup(struct ath12k_base *ab) +@@ -1510,15 +1511,16 @@ static int ath12k_dp_reoq_lut_setup(stru memset(dp->reoq_lut.vaddr, 0, DP_REOQ_LUT_SIZE); @@ -142,90 +75,9 @@ index 455e608..24df514 100644 HAL_REO_QDESC_MAX_PEERID); return 0; -diff --git a/drivers/net/wireless/ath/ath12k/hal.c b/drivers/net/wireless/ath/ath12k/hal.c -index 7686e65..7dd00e0 100644 --- a/drivers/net/wireless/ath/ath12k/hal.c +++ b/drivers/net/wireless/ath/ath12k/hal.c -@@ -1240,21 +1240,21 @@ void ath12k_hal_setup_link_idle_list(struct ath12k_base *ab, - } - - ath12k_hif_write32(ab, -- HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_R0_IDLE_LIST_CONTROL_ADDR, -+ HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_R0_IDLE_LIST_CTRL_ADDR(ab), - FIELD_PREP(HAL_WBM_SCATTER_BUFFER_SIZE, reg_scatter_buf_sz) | - FIELD_PREP(HAL_WBM_LINK_DESC_IDLE_LIST_MODE, 0x1)); - ath12k_hif_write32(ab, -- HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_R0_IDLE_LIST_SIZE_ADDR, -+ HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_R0_IDLE_LIST_SIZE_ADDR(ab), - FIELD_PREP(HAL_WBM_SCATTER_RING_SIZE_OF_IDLE_LINK_DESC_LIST, - reg_scatter_buf_sz * nsbufs)); - ath12k_hif_write32(ab, - HAL_SEQ_WCSS_UMAC_WBM_REG + -- HAL_WBM_SCATTERED_RING_BASE_LSB, -+ HAL_WBM_SCATTERED_RING_BASE_LSB(ab), - FIELD_PREP(BUFFER_ADDR_INFO0_ADDR, - sbuf[0].paddr & HAL_ADDR_LSB_REG_MASK)); - ath12k_hif_write32(ab, - HAL_SEQ_WCSS_UMAC_WBM_REG + -- HAL_WBM_SCATTERED_RING_BASE_MSB, -+ HAL_WBM_SCATTERED_RING_BASE_MSB(ab), - FIELD_PREP( - HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_39_32, - (u64)sbuf[0].paddr >> HAL_ADDR_MSB_REG_SHIFT) | -@@ -1265,12 +1265,12 @@ void ath12k_hal_setup_link_idle_list(struct ath12k_base *ab, - /* Setup head and tail pointers for the idle list */ - ath12k_hif_write32(ab, - HAL_SEQ_WCSS_UMAC_WBM_REG + -- HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX0, -+ HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX0(ab), - FIELD_PREP(BUFFER_ADDR_INFO0_ADDR, - sbuf[nsbufs - 1].paddr)); - ath12k_hif_write32(ab, - HAL_SEQ_WCSS_UMAC_WBM_REG + -- HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX1, -+ HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX1(ab), - FIELD_PREP( - HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_39_32, - ((u64)sbuf[nsbufs - 1].paddr >> -@@ -1279,18 +1279,18 @@ void ath12k_hal_setup_link_idle_list(struct ath12k_base *ab, - (end_offset >> 2))); - ath12k_hif_write32(ab, - HAL_SEQ_WCSS_UMAC_WBM_REG + -- HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX0, -+ HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX0(ab), - FIELD_PREP(BUFFER_ADDR_INFO0_ADDR, - sbuf[0].paddr)); - - ath12k_hif_write32(ab, - HAL_SEQ_WCSS_UMAC_WBM_REG + -- HAL_WBM_SCATTERED_DESC_PTR_TAIL_INFO_IX0, -+ HAL_WBM_SCATTERED_DESC_PTR_TAIL_INFO_IX0(ab), - FIELD_PREP(BUFFER_ADDR_INFO0_ADDR, - sbuf[0].paddr)); - ath12k_hif_write32(ab, - HAL_SEQ_WCSS_UMAC_WBM_REG + -- HAL_WBM_SCATTERED_DESC_PTR_TAIL_INFO_IX1, -+ HAL_WBM_SCATTERED_DESC_PTR_TAIL_INFO_IX1(ab), - FIELD_PREP( - HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_39_32, - ((u64)sbuf[0].paddr >> HAL_ADDR_MSB_REG_SHIFT)) | -@@ -1298,13 +1298,13 @@ void ath12k_hal_setup_link_idle_list(struct ath12k_base *ab, - 0)); - ath12k_hif_write32(ab, - HAL_SEQ_WCSS_UMAC_WBM_REG + -- HAL_WBM_SCATTERED_DESC_PTR_HP_ADDR, -+ HAL_WBM_SCATTERED_DESC_PTR_HP_ADDR(ab), - 2 * tot_link_desc); - - /* Enable the SRNG */ - ath12k_hif_write32(ab, - HAL_SEQ_WCSS_UMAC_WBM_REG + -- HAL_WBM_IDLE_LINK_RING_MISC_ADDR, -+ HAL_WBM_IDLE_LINK_RING_MISC_ADDR(ab), - FIELD_PREP(HAL_WBM_IDLE_LINK_RING_MISC_SRNG_ENABLE, - 1) | - FIELD_PREP(HAL_WBM_IDLE_LINK_RING_MISC_RIND_ID_DISABLE, -@@ -1538,27 +1538,27 @@ static int ath12k_hal_srng_create_config(struct ath12k_base *ab) +@@ -493,27 +493,27 @@ static int ath12k_hal_srng_create_config return -ENOMEM; s = &hal->srng_config[HAL_REO_DST]; @@ -260,36 +112,7 @@ index 7686e65..7dd00e0 100644 s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_STATUS_HP; s = &hal->srng_config[HAL_TCL_DATA]; -@@ -1601,21 +1601,21 @@ static int ath12k_hal_srng_create_config(struct ath12k_base *ab) - HAL_SEQ_WCSS_UMAC_CE0_DST_REG; - - s = &hal->srng_config[HAL_WBM_IDLE_LINK]; -- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_IDLE_LINK_RING_BASE_LSB; -+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_IDLE_LINK_RING_BASE_LSB(ab); - s->reg_start[1] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_IDLE_LINK_RING_HP; - - s = &hal->srng_config[HAL_SW2WBM_RELEASE]; -- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_SW_RELEASE_RING_BASE_LSB; -+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_SW_REL_RING_BASE_LSB(ab); - s->reg_start[1] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_SW_RELEASE_RING_HP; -- s->reg_size[0] = HAL_WBM_SW1_RELEASE_RING_BASE_LSB - -- HAL_WBM_SW_RELEASE_RING_BASE_LSB; -+ s->reg_size[0] = HAL_WBM_SW1_RELEASE_RING_BASE_LSB(ab) - -+ HAL_WBM_SW_REL_RING_BASE_LSB(ab); - s->reg_size[1] = HAL_WBM_SW1_RELEASE_RING_HP - HAL_WBM_SW_RELEASE_RING_HP; - - s = &hal->srng_config[HAL_WBM2SW_RELEASE]; -- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM0_RELEASE_RING_BASE_LSB; -+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM0_RELEASE_RING_BASE_LSB(ab); - s->reg_start[1] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM0_RELEASE_RING_HP; -- s->reg_size[0] = HAL_WBM1_RELEASE_RING_BASE_LSB - -- HAL_WBM0_RELEASE_RING_BASE_LSB; -+ s->reg_size[0] = HAL_WBM1_RELEASE_RING_BASE_LSB(ab) - -+ HAL_WBM0_RELEASE_RING_BASE_LSB(ab); - s->reg_size[1] = HAL_WBM1_RELEASE_RING_HP - HAL_WBM0_RELEASE_RING_HP; - - /* Some LMAC rings are not accesed from the host: -@@ -1629,7 +1629,7 @@ static int ath12k_hal_srng_create_config(struct ath12k_base *ab) +@@ -584,7 +584,7 @@ static int ath12k_hal_srng_create_config s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_PPE2TCL1_RING_HP; s = &hal->srng_config[HAL_PPE_RELEASE]; @@ -298,76 +121,55 @@ index 7686e65..7dd00e0 100644 s->reg_start[1] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_PPE_RELEASE_RING_HP; return 0; -@@ -1644,6 +1644,7 @@ int ath12k_hal_srng_init(struct ath12k_base *ab) +@@ -933,26 +933,26 @@ static int ath12k_hal_srng_create_config + return -ENOMEM; - switch (ab->hw_rev) { - case ATH12K_HW_QCN92XX_HW10: -+ case ATH12K_HW_QCN92XX_HW20: - ab->hal.ops = &hal_qcn92xx_ops; - break; - default: -diff --git a/drivers/net/wireless/ath/ath12k/hal.h b/drivers/net/wireless/ath/ath12k/hal.h -index b41e3d8..e644d48 100644 + s = &hal->srng_config[HAL_REO_DST]; +- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_RING_BASE_LSB; ++ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_RING_BASE_LSB(ab); + s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_RING_HP; +- s->reg_size[0] = HAL_REO2_RING_BASE_LSB - HAL_REO1_RING_BASE_LSB; ++ s->reg_size[0] = HAL_REO2_RING_BASE_LSB(ab) - HAL_REO1_RING_BASE_LSB(ab); + s->reg_size[1] = HAL_REO2_RING_HP - HAL_REO1_RING_HP; + + s = &hal->srng_config[HAL_REO_EXCEPTION]; +- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_SW0_RING_BASE_LSB; ++ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_SW0_RING_BASE_LSB(ab); + s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_SW0_RING_HP; + + s = &hal->srng_config[HAL_REO_REINJECT]; + s->max_rings = 1; +- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_SW2REO_RING_BASE_LSB; ++ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_SW2REO_RING_BASE_LSB(ab); + s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_SW2REO_RING_HP; + + s = &hal->srng_config[HAL_REO_CMD]; +- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_CMD_RING_BASE_LSB; ++ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_CMD_RING_BASE_LSB(ab); + s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_CMD_HP; + + s = &hal->srng_config[HAL_REO_STATUS]; +- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_STATUS_RING_BASE_LSB; ++ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_STATUS_RING_BASE_LSB(ab); + s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_STATUS_HP; + + s = &hal->srng_config[HAL_TCL_DATA]; --- a/drivers/net/wireless/ath/ath12k/hal.h +++ b/drivers/net/wireless/ath/ath12k/hal.h -@@ -61,24 +61,24 @@ struct ath12k_base; - #define HAL_TCL1_RING_DSCP_TID_MAP 0x00000240 - #define HAL_TCL1_RING_BASE_LSB 0x00000900 - #define HAL_TCL1_RING_BASE_MSB 0x00000904 --#define HAL_TCL1_RING_ID(ab) ab->hw_params.regs->hal_tcl1_ring_id --#define HAL_TCL1_RING_MISC(ab) ab->hw_params.regs->hal_tcl1_ring_misc -+#define HAL_TCL1_RING_ID(ab) (ab)->hw_params.regs->hal_tcl1_ring_id -+#define HAL_TCL1_RING_MISC(ab) (ab)->hw_params.regs->hal_tcl1_ring_misc - #define HAL_TCL1_RING_TP_ADDR_LSB(ab) \ -- ab->hw_params.regs->hal_tcl1_ring_tp_addr_lsb -+ (ab)->hw_params.regs->hal_tcl1_ring_tp_addr_lsb - #define HAL_TCL1_RING_TP_ADDR_MSB(ab) \ -- ab->hw_params.regs->hal_tcl1_ring_tp_addr_msb -+ (ab)->hw_params.regs->hal_tcl1_ring_tp_addr_msb - #define HAL_TCL1_RING_CONSUMER_INT_SETUP_IX0(ab) \ -- ab->hw_params.regs->hal_tcl1_ring_consumer_int_setup_ix0 -+ (ab)->hw_params.regs->hal_tcl1_ring_consumer_int_setup_ix0 - #define HAL_TCL1_RING_CONSUMER_INT_SETUP_IX1(ab) \ -- ab->hw_params.regs->hal_tcl1_ring_consumer_int_setup_ix1 -+ (ab)->hw_params.regs->hal_tcl1_ring_consumer_int_setup_ix1 - #define HAL_TCL1_RING_MSI1_BASE_LSB(ab) \ -- ab->hw_params.regs->hal_tcl1_ring_msi1_base_lsb -+ (ab)->hw_params.regs->hal_tcl1_ring_msi1_base_lsb - #define HAL_TCL1_RING_MSI1_BASE_MSB(ab) \ -- ab->hw_params.regs->hal_tcl1_ring_msi1_base_msb -+ (ab)->hw_params.regs->hal_tcl1_ring_msi1_base_msb - #define HAL_TCL1_RING_MSI1_DATA(ab) \ -- ab->hw_params.regs->hal_tcl1_ring_msi1_data -+ (ab)->hw_params.regs->hal_tcl1_ring_msi1_data - #define HAL_TCL2_RING_BASE_LSB 0x00000978 --#define HAL_TCL_RING_BASE_LSB(ab) ab->hw_params.regs->hal_tcl_ring_base_lsb -+#define HAL_TCL_RING_BASE_LSB(ab) (ab)->hw_params.regs->hal_tcl_ring_base_lsb - - #define HAL_TCL1_RING_MSI1_BASE_LSB_OFFSET(ab) \ - (HAL_TCL1_RING_MSI1_BASE_LSB(ab) - HAL_TCL1_RING_BASE_LSB) -@@ -112,7 +112,7 @@ struct ath12k_base; - - /* TCL STATUS ring address */ - #define HAL_TCL_STATUS_RING_BASE_LSB(ab) \ -- ab->hw_params.regs->hal_tcl_status_ring_base_lsb -+ (ab)->hw_params.regs->hal_tcl_status_ring_base_lsb - #define HAL_TCL_STATUS_RING_HP 0x00002048 - - /* PPE2TCL1 Ring address */ -@@ -120,56 +120,59 @@ struct ath12k_base; +@@ -122,56 +122,59 @@ struct ath12k_base; #define HAL_TCL_PPE2TCL1_RING_HP 0x00002038 /* WBM PPE Release Ring address */ -#define HAL_WBM_PPE_RELEASE_RING_BASE_LSB 0x0000043c +#define HAL_WBM_PPE_RELEASE_RING_BASE_LSB(ab) \ -+ (ab)->hw_params.regs->hal_ppe_rel_ring_base ++ (ab)->hw_params->regs->hal_ppe_rel_ring_base #define HAL_WBM_PPE_RELEASE_RING_HP 0x00003020 /* REO2SW(x) R0 ring configuration address */ #define HAL_REO1_GEN_ENABLE 0x00000000 -#define HAL_REO1_MISC_CTRL_ADDR 0x00000b7c +#define HAL_REO1_MISC_CTRL_ADDR(ab) \ -+ (ab)->hw_params.regs->hal_reo1_misc_ctrl_addr ++ (ab)->hw_params->regs->hal_reo1_misc_ctrl_addr #define HAL_REO1_DEST_RING_CTRL_IX_0 0x00000004 #define HAL_REO1_DEST_RING_CTRL_IX_1 0x00000008 #define HAL_REO1_DEST_RING_CTRL_IX_2 0x0000000c @@ -394,29 +196,29 @@ index b41e3d8..e644d48 100644 -#define HAL_REO1_AGING_THRESH_IX_1 0x00000b0c -#define HAL_REO1_AGING_THRESH_IX_2 0x00000b10 -#define HAL_REO1_AGING_THRESH_IX_3 0x00000b14 -+#define HAL_REO1_SW_COOKIE_CFG0(ab) (ab)->hw_params.regs->hal_reo1_sw_cookie_cfg0 -+#define HAL_REO1_SW_COOKIE_CFG1(ab) (ab)->hw_params.regs->hal_reo1_sw_cookie_cfg1 -+#define HAL_REO1_QDESC_LUT_BASE0(ab) (ab)->hw_params.regs->hal_reo1_qdesc_lut_base0 -+#define HAL_REO1_QDESC_LUT_BASE1(ab) (ab)->hw_params.regs->hal_reo1_qdesc_lut_base1 -+#define HAL_REO1_QDESC_ADDR_READ(ab) (ab)->hw_params.regs->hal_reo1_qdesc_addr_read -+#define HAL_REO1_QDESC_MAX_PEERID(ab) (ab)->hw_params.regs->hal_reo1_qdesc_max_peerid ++#define HAL_REO1_SW_COOKIE_CFG0(ab) (ab)->hw_params->regs->hal_reo1_sw_cookie_cfg0 ++#define HAL_REO1_SW_COOKIE_CFG1(ab) (ab)->hw_params->regs->hal_reo1_sw_cookie_cfg1 ++#define HAL_REO1_QDESC_LUT_BASE0(ab) (ab)->hw_params->regs->hal_reo1_qdesc_lut_base0 ++#define HAL_REO1_QDESC_LUT_BASE1(ab) (ab)->hw_params->regs->hal_reo1_qdesc_lut_base1 ++#define HAL_REO1_QDESC_ADDR_READ(ab) (ab)->hw_params->regs->hal_reo1_qdesc_addr_read ++#define HAL_REO1_QDESC_MAX_PEERID(ab) (ab)->hw_params->regs->hal_reo1_qdesc_max_peerid + -+#define HAL_REO1_RING_BASE_LSB(ab) (ab)->hw_params.regs->hal_reo1_ring_base_lsb -+#define HAL_REO1_RING_BASE_MSB(ab) (ab)->hw_params.regs->hal_reo1_ring_base_msb -+#define HAL_REO1_RING_ID(ab) (ab)->hw_params.regs->hal_reo1_ring_id -+#define HAL_REO1_RING_MISC(ab) (ab)->hw_params.regs->hal_reo1_ring_misc -+#define HAL_REO1_RING_HP_ADDR_LSB(ab) (ab)->hw_params.regs->hal_reo1_ring_hp_addr_lsb -+#define HAL_REO1_RING_HP_ADDR_MSB(ab) (ab)->hw_params.regs->hal_reo1_ring_hp_addr_msb ++#define HAL_REO1_RING_BASE_LSB(ab) (ab)->hw_params->regs->hal_reo1_ring_base_lsb ++#define HAL_REO1_RING_BASE_MSB(ab) (ab)->hw_params->regs->hal_reo1_ring_base_msb ++#define HAL_REO1_RING_ID(ab) (ab)->hw_params->regs->hal_reo1_ring_id ++#define HAL_REO1_RING_MISC(ab) (ab)->hw_params->regs->hal_reo1_ring_misc ++#define HAL_REO1_RING_HP_ADDR_LSB(ab) (ab)->hw_params->regs->hal_reo1_ring_hp_addr_lsb ++#define HAL_REO1_RING_HP_ADDR_MSB(ab) (ab)->hw_params->regs->hal_reo1_ring_hp_addr_msb +#define HAL_REO1_RING_PRODUCER_INT_SETUP(ab) \ -+ (ab)->hw_params.regs->hal_reo1_ring_producer_int_setup -+#define HAL_REO1_RING_MSI1_BASE_LSB(ab) (ab)->hw_params.regs->hal_reo1_ring_msi1_base_lsb -+#define HAL_REO1_RING_MSI1_BASE_MSB(ab) (ab)->hw_params.regs->hal_reo1_ring_msi1_base_msb -+#define HAL_REO1_RING_MSI1_DATA(ab) (ab)->hw_params.regs->hal_reo1_ring_msi1_data -+#define HAL_REO2_RING_BASE_LSB(ab) (ab)->hw_params.regs->hal_reo2_ring_base -+#define HAL_REO1_AGING_THRESH_IX_0(ab) (ab)->hw_params.regs->hal_reo1_aging_thres_ix0 -+#define HAL_REO1_AGING_THRESH_IX_1(ab) (ab)->hw_params.regs->hal_reo1_aging_thres_ix1 -+#define HAL_REO1_AGING_THRESH_IX_2(ab) (ab)->hw_params.regs->hal_reo1_aging_thres_ix2 -+#define HAL_REO1_AGING_THRESH_IX_3(ab) (ab)->hw_params.regs->hal_reo1_aging_thres_ix3 ++ (ab)->hw_params->regs->hal_reo1_ring_producer_int_setup ++#define HAL_REO1_RING_MSI1_BASE_LSB(ab) (ab)->hw_params->regs->hal_reo1_ring_msi1_base_lsb ++#define HAL_REO1_RING_MSI1_BASE_MSB(ab) (ab)->hw_params->regs->hal_reo1_ring_msi1_base_msb ++#define HAL_REO1_RING_MSI1_DATA(ab) (ab)->hw_params->regs->hal_reo1_ring_msi1_data ++#define HAL_REO2_RING_BASE_LSB(ab) (ab)->hw_params->regs->hal_reo2_ring_base ++#define HAL_REO1_AGING_THRESH_IX_0(ab) (ab)->hw_params->regs->hal_reo1_aging_thres_ix0 ++#define HAL_REO1_AGING_THRESH_IX_1(ab) (ab)->hw_params->regs->hal_reo1_aging_thres_ix1 ++#define HAL_REO1_AGING_THRESH_IX_2(ab) (ab)->hw_params->regs->hal_reo1_aging_thres_ix2 ++#define HAL_REO1_AGING_THRESH_IX_3(ab) (ab)->hw_params->regs->hal_reo1_aging_thres_ix3 #define HAL_REO1_RING_MSI1_BASE_LSB_OFFSET \ - (HAL_REO1_RING_MSI1_BASE_LSB - HAL_REO1_RING_BASE_LSB) @@ -447,13 +249,13 @@ index b41e3d8..e644d48 100644 /* REO2SW(x) R2 ring pointers (head/tail) address */ #define HAL_REO1_RING_HP 0x00003048 -@@ -179,20 +182,24 @@ struct ath12k_base; +@@ -181,20 +184,24 @@ struct ath12k_base; #define HAL_REO1_RING_TP_OFFSET (HAL_REO1_RING_TP - HAL_REO1_RING_HP) /* REO2SW0 ring configuration address */ -#define HAL_REO_SW0_RING_BASE_LSB 0x000008a4 +#define HAL_REO_SW0_RING_BASE_LSB(ab) \ -+ (ab)->hw_params.regs->hal_reo2_sw0_ring_base ++ (ab)->hw_params->regs->hal_reo2_sw0_ring_base /* REO2SW0 R2 ring pointer (head/tail) address */ #define HAL_REO_SW0_RING_HP 0x00003088 @@ -461,7 +263,7 @@ index b41e3d8..e644d48 100644 /* REO CMD R0 address */ -#define HAL_REO_CMD_RING_BASE_LSB 0x0000028c +#define HAL_REO_CMD_RING_BASE_LSB(ab) \ -+ (ab)->hw_params.regs->hal_reo_cmd_ring_base ++ (ab)->hw_params->regs->hal_reo_cmd_ring_base /* REO CMD R2 address */ #define HAL_REO_CMD_HP 0x00003020 @@ -470,87 +272,26 @@ index b41e3d8..e644d48 100644 -#define HAL_SW2REO_RING_BASE_LSB 0x00000304 -#define HAL_SW2REO1_RING_BASE_LSB 0x0000037c +#define HAL_SW2REO_RING_BASE_LSB(ab) \ -+ (ab)->hw_params.regs->hal_sw2reo_ring_base ++ (ab)->hw_params->regs->hal_sw2reo_ring_base +#define HAL_SW2REO1_RING_BASE_LSB(ab) \ -+ (ab)->hw_params.regs->hal_sw2reo1_ring_base ++ (ab)->hw_params->regs->hal_sw2reo1_ring_base /* SW2REO R2 address */ #define HAL_SW2REO_RING_HP 0x00003028 -@@ -209,36 +216,52 @@ struct ath12k_base; +@@ -211,7 +218,8 @@ struct ath12k_base; #define HAL_CE_DST_STATUS_RING_HP 0x00000408 /* REO status address */ -#define HAL_REO_STATUS_RING_BASE_LSB 0x00000a84 +#define HAL_REO_STATUS_RING_BASE_LSB(ab) \ -+ (ab)->hw_params.regs->hal_reo_status_ring_base ++ ((ab)->hw_params->regs->hal_reo_status_ring_base) #define HAL_REO_STATUS_HP 0x000030a8 /* WBM Idle R0 address */ --#define HAL_WBM_IDLE_LINK_RING_BASE_LSB 0x00000d0c --#define HAL_WBM_IDLE_LINK_RING_MISC_ADDR 0x00000d1c --#define HAL_WBM_R0_IDLE_LIST_CONTROL_ADDR 0x00000210 --#define HAL_WBM_R0_IDLE_LIST_SIZE_ADDR 0x00000214 --#define HAL_WBM_SCATTERED_RING_BASE_LSB 0x00000220 --#define HAL_WBM_SCATTERED_RING_BASE_MSB 0x00000224 --#define HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX0 0x00000230 --#define HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX1 0x00000234 --#define HAL_WBM_SCATTERED_DESC_PTR_TAIL_INFO_IX0 0x00000240 --#define HAL_WBM_SCATTERED_DESC_PTR_TAIL_INFO_IX1 0x00000244 --#define HAL_WBM_SCATTERED_DESC_PTR_HP_ADDR 0x0000024c -+#define HAL_WBM_IDLE_LINK_RING_BASE_LSB(ab) \ -+ (ab)->hw_params.regs->hal_wbm_idle_link_ring_base -+#define HAL_WBM_IDLE_LINK_RING_MISC_ADDR(ab) \ -+ (ab)->hw_params.regs->hal_wbm_idle_link_ring_misc -+#define HAL_WBM_R0_IDLE_LIST_CTRL_ADDR(ab) \ -+ (ab)->hw_params.regs->hal_wbm_idle_list_ctrl_addr -+#define HAL_WBM_R0_IDLE_LIST_SIZE_ADDR(ab) \ -+ (ab)->hw_params.regs->hal_wbm_idle_list_size_addr -+#define HAL_WBM_SCATTERED_RING_BASE_LSB(ab) \ -+ (ab)->hw_params.regs->hal_wbm_scat_ring_base_lsb -+#define HAL_WBM_SCATTERED_RING_BASE_MSB(ab) \ -+ (ab)->hw_params.regs->hal_wbm_scat_ring_base_msb -+#define HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX0(ab) \ -+ (ab)->hw_params.regs->hal_wbm_scat_desc_ptr_head_ix0 -+#define HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX1(ab) \ -+ (ab)->hw_params.regs->hal_wbm_scat_desc_ptr_head_ix1 -+#define HAL_WBM_SCATTERED_DESC_PTR_TAIL_INFO_IX0(ab) \ -+ (ab)->hw_params.regs->hal_wbm_scat_desc_ptr_tail_ix0 -+#define HAL_WBM_SCATTERED_DESC_PTR_TAIL_INFO_IX1(ab) \ -+ (ab)->hw_params.regs->hal_wbm_scat_desc_ptr_tail_ix1 -+#define HAL_WBM_SCATTERED_DESC_PTR_HP_ADDR(ab) \ -+ (ab)->hw_params.regs->hal_wbm_scat_desc_ptr_hp_addr - - /* WBM Idle R2 address */ - #define HAL_WBM_IDLE_LINK_RING_HP 0x000030b8 - - /* SW2WBM R0 release address */ --#define HAL_WBM_SW_RELEASE_RING_BASE_LSB 0x0000034c --#define HAL_WBM_SW1_RELEASE_RING_BASE_LSB 0x000003c4 -+#define HAL_WBM_SW_REL_RING_BASE_LSB(ab) \ -+ (ab)->hw_params.regs->hal_wbm_sw_rel_ring_base -+#define HAL_WBM_SW1_RELEASE_RING_BASE_LSB(ab) \ -+ (ab)->hw_params.regs->hal_wbm_sw1_rel_ring_base - - /* SW2WBM R2 release address */ - #define HAL_WBM_SW_RELEASE_RING_HP 0x00003010 - #define HAL_WBM_SW1_RELEASE_RING_HP 0x00003018 - - /* WBM2SW R0 release address */ --#define HAL_WBM0_RELEASE_RING_BASE_LSB 0x00000dd8 --#define HAL_WBM1_RELEASE_RING_BASE_LSB 0x00000e50 -+#define HAL_WBM0_RELEASE_RING_BASE_LSB(ab) \ -+ (ab)->hw_params.regs->hal_wbm0_rel_ring_base -+#define HAL_WBM1_RELEASE_RING_BASE_LSB(ab) \ -+ (ab)->hw_params.regs->hal_wbm1_rel_ring_base - - /* WBM2SW R2 release address */ - #define HAL_WBM0_RELEASE_RING_HP 0x000030c8 -diff --git a/drivers/net/wireless/ath/ath12k/hal_rx.c b/drivers/net/wireless/ath/ath12k/hal_rx.c -index eed5466..b21932a 100644 --- a/drivers/net/wireless/ath/ath12k/hal_rx.c +++ b/drivers/net/wireless/ath/ath12k/hal_rx.c -@@ -856,7 +856,7 @@ void ath12k_hal_reo_hw_setup(struct ath12k_base *ab, u32 ring_hash_map) - FIELD_PREP(HAL_REO1_GEN_ENABLE_AGING_FLUSH_ENABLE, 1); +@@ -861,7 +861,7 @@ void ath12k_hal_reo_hw_setup(struct ath1 + u32_encode_bits(1, HAL_REO1_GEN_ENABLE_AGING_FLUSH_ENABLE); ath12k_hif_write32(ab, reo_base + HAL_REO1_GEN_ENABLE, val); - val = ath12k_hif_read32(ab, reo_base + HAL_REO1_MISC_CTRL_ADDR); @@ -558,10 +299,10 @@ index eed5466..b21932a 100644 val &= ~(HAL_REO1_MISC_CTL_FRAG_DST_RING | HAL_REO1_MISC_CTL_BAR_DST_RING); -@@ -864,15 +864,15 @@ void ath12k_hal_reo_hw_setup(struct ath12k_base *ab, u32 ring_hash_map) - HAL_SRNG_RING_ID_REO2SW0); - val |= FIELD_PREP(HAL_REO1_MISC_CTL_BAR_DST_RING, - HAL_SRNG_RING_ID_REO2SW0); +@@ -869,15 +869,15 @@ void ath12k_hal_reo_hw_setup(struct ath1 + HAL_REO1_MISC_CTL_FRAG_DST_RING); + val |= u32_encode_bits(HAL_SRNG_RING_ID_REO2SW0, + HAL_REO1_MISC_CTL_BAR_DST_RING); - ath12k_hif_write32(ab, reo_base + HAL_REO1_MISC_CTRL_ADDR, val); + ath12k_hif_write32(ab, reo_base + HAL_REO1_MISC_CTRL_ADDR(ab), val); @@ -579,15 +320,12 @@ index eed5466..b21932a 100644 HAL_DEFAULT_VO_REO_TIMEOUT_USEC); ath12k_hal_reo_ring_ctrl_hash_ix2_setup(ab, ring_hash_map); -diff --git a/drivers/net/wireless/ath/ath12k/hw.c b/drivers/net/wireless/ath/ath12k/hw.c -index 2ee8e26..45f5aef 100644 --- a/drivers/net/wireless/ath/ath12k/hw.c +++ b/drivers/net/wireless/ath/ath12k/hw.c -@@ -371,4 +371,147 @@ const struct ath12k_hw_regs qcn92xx_regs = { - /* PCIe base address */ - .pcie_qserdes_sysclk_en_sel = 0x01e0c0a8, - .pcie_pcs_osc_dtct_config_base = 0x01e0d45c, -+ +@@ -624,6 +624,44 @@ static const struct ath12k_hw_regs qcn92 + /* TCL STATUS ring address */ + .hal_tcl_status_ring_base_lsb = 0x00000d38, + + /* REO dest ring address */ + .hal_reo2_ring_base = 0x0000055c, + .hal_reo1_misc_ctrl_addr = 0x00000b7c, @@ -626,31 +364,30 @@ index 2ee8e26..45f5aef 100644 + .hal_reo_status_ring_base = 0x00000a84, + + /* WBM idle link ring address */ -+ .hal_wbm_idle_link_ring_base = 0x00000d0c, -+ .hal_wbm_idle_link_ring_misc = 0x00000d1c, -+ .hal_wbm_idle_list_ctrl_addr = 0x00000210, -+ .hal_wbm_idle_list_size_addr = 0x00000214, -+ .hal_wbm_scat_ring_base_lsb = 0x00000220, -+ .hal_wbm_scat_ring_base_msb = 0x00000224, -+ .hal_wbm_scat_desc_ptr_head_ix0 = 0x00000230, -+ .hal_wbm_scat_desc_ptr_head_ix1 = 0x00000234, -+ .hal_wbm_scat_desc_ptr_tail_ix0 = 0x00000240, -+ .hal_wbm_scat_desc_ptr_tail_ix1 = 0x00000244, -+ .hal_wbm_scat_desc_ptr_hp_addr = 0x0000024c, -+ + .hal_wbm_idle_ring_base_lsb = 0x00000d0c, + .hal_wbm_idle_ring_misc_addr = 0x00000d1c, + .hal_wbm_r0_idle_list_cntl_addr = 0x00000210, +@@ -636,11 +674,99 @@ static const struct ath12k_hw_regs qcn92 + .hal_wbm_scattered_desc_tail_info_ix1 = 0x00000244, + .hal_wbm_scattered_desc_ptr_hp_addr = 0x0000024c, + + /* SW2WBM release ring address */ -+ .hal_wbm_sw_rel_ring_base = 0x0000034c, -+ .hal_wbm_sw1_rel_ring_base = 0x000003c4, + .hal_wbm_sw_release_ring_base_lsb = 0x0000034c, + .hal_wbm_sw1_release_ring_base_lsb = 0x000003c4, + + /* WBM2SW release ring address */ -+ .hal_wbm0_rel_ring_base = 0x00000dd8, -+ .hal_wbm1_rel_ring_base = 0x00000e50, -+ + .hal_wbm0_release_ring_base_lsb = 0x00000dd8, + .hal_wbm1_release_ring_base_lsb = 0x00000e50, + + /* PPE release ring address */ + .hal_ppe_rel_ring_base = 0x0000043c, ++ ++ /* PCIe base address */ ++ .pcie_qserdes_sysclk_en_sel = 0x01e0c0a8, ++ .pcie_pcs_osc_dtct_config_base = 0x01e0d45c, +}; + -+const struct ath12k_hw_regs qcn92xx_v2_regs = { ++const struct ath12k_hw_regs qcn9274_v2_regs = { + /* SW2TCL(x) R0 ring configuration address */ + .hal_tcl1_ring_id = 0x00000908, + .hal_tcl1_ring_misc = 0x00000910, @@ -666,10 +403,6 @@ index 2ee8e26..45f5aef 100644 + /* TCL STATUS ring address */ + .hal_tcl_status_ring_base_lsb = 0x00000d38, + -+ /* PCIe base address */ -+ .pcie_qserdes_sysclk_en_sel = 0x01e0c0a8, -+ .pcie_pcs_osc_dtct_config_base = 0x01e0d45c, -+ + /* REO DEST ring address */ + .hal_reo2_ring_base = 0x00000578, + .hal_reo1_misc_ctrl_addr = 0x00000b9c, @@ -708,106 +441,105 @@ index 2ee8e26..45f5aef 100644 + .hal_reo_status_ring_base = 0x00000aa0, + + /* WBM idle link ring address */ -+ .hal_wbm_idle_link_ring_base = 0x00000d3c, -+ .hal_wbm_idle_link_ring_misc = 0x00000d4c, -+ .hal_wbm_idle_list_ctrl_addr = 0x00000240, -+ .hal_wbm_idle_list_size_addr = 0x00000244, -+ .hal_wbm_scat_ring_base_lsb = 0x00000250, -+ .hal_wbm_scat_ring_base_msb = 0x00000254, -+ .hal_wbm_scat_desc_ptr_head_ix0 = 0x00000260, -+ .hal_wbm_scat_desc_ptr_head_ix1 = 0x00000264, -+ .hal_wbm_scat_desc_ptr_tail_ix0 = 0x00000270, -+ .hal_wbm_scat_desc_ptr_tail_ix1 = 0x00000274, -+ .hal_wbm_scat_desc_ptr_hp_addr = 0x0000027c, ++ .hal_wbm_idle_ring_base_lsb = 0x00000d3c, ++ .hal_wbm_idle_ring_misc_addr = 0x00000d4c, ++ .hal_wbm_r0_idle_list_cntl_addr = 0x00000240, ++ .hal_wbm_r0_idle_list_size_addr = 0x00000244, ++ .hal_wbm_scattered_ring_base_lsb = 0x00000250, ++ .hal_wbm_scattered_ring_base_msb = 0x00000254, ++ .hal_wbm_scattered_desc_head_info_ix0 = 0x00000260, ++ .hal_wbm_scattered_desc_head_info_ix1 = 0x00000264, ++ .hal_wbm_scattered_desc_tail_info_ix0 = 0x00000270, ++ .hal_wbm_scattered_desc_tail_info_ix1 = 0x00000274, ++ .hal_wbm_scattered_desc_ptr_hp_addr = 0x0000027c, + + /* SW2WBM release ring address */ -+ .hal_wbm_sw_rel_ring_base = 0x0000037c, -+ .hal_wbm_sw1_rel_ring_base = 0x000003f4, ++ .hal_wbm_sw_release_ring_base_lsb = 0x0000037c, ++ .hal_wbm_sw1_release_ring_base_lsb = 0x000003f4, + + /* WBM2SW release ring address */ -+ .hal_wbm0_rel_ring_base = 0x00000e08, -+ .hal_wbm1_rel_ring_base = 0x00000e80, ++ .hal_wbm0_release_ring_base_lsb = 0x00000e08, ++ .hal_wbm1_release_ring_base_lsb = 0x00000e80, + + /* PPE release ring address */ + .hal_ppe_rel_ring_base = 0x0000046c, - }; -diff --git a/drivers/net/wireless/ath/ath12k/hw.h b/drivers/net/wireless/ath/ath12k/hw.h -index 699538f..49eb7fc 100644 ---- a/drivers/net/wireless/ath/ath12k/hw.h -+++ b/drivers/net/wireless/ath/ath12k/hw.h -@@ -239,12 +239,54 @@ struct ath12k_hw_regs { - u32 hal_tcl1_ring_msi1_base_msb; - u32 hal_tcl1_ring_msi1_data; - u32 hal_tcl_ring_base_lsb; -- - u32 hal_tcl_status_ring_base_lsb; -- - u32 pcie_qserdes_sysclk_en_sel; - u32 pcie_pcs_osc_dtct_config_base; -+ u32 hal_reo2_ring_base; -+ u32 hal_reo1_misc_ctrl_addr; -+ u32 hal_reo1_sw_cookie_cfg0; -+ u32 hal_reo1_sw_cookie_cfg1; -+ u32 hal_reo1_qdesc_lut_base0; -+ u32 hal_reo1_qdesc_lut_base1; -+ u32 hal_reo1_qdesc_addr_read; -+ u32 hal_reo1_qdesc_max_peerid; -+ u32 hal_reo1_ring_base_lsb; -+ u32 hal_reo1_ring_base_msb; -+ u32 hal_reo1_ring_id; -+ u32 hal_reo1_ring_misc; -+ u32 hal_reo1_ring_hp_addr_lsb; -+ u32 hal_reo1_ring_hp_addr_msb; -+ u32 hal_reo1_ring_producer_int_setup; -+ u32 hal_reo1_ring_msi1_base_lsb; -+ u32 hal_reo1_ring_msi1_base_msb; -+ u32 hal_reo1_ring_msi1_data; -+ u32 hal_reo1_aging_thres_ix0; -+ u32 hal_reo1_aging_thres_ix1; -+ u32 hal_reo1_aging_thres_ix2; -+ u32 hal_reo1_aging_thres_ix3; -+ u32 hal_reo2_sw0_ring_base; -+ u32 hal_sw2reo_ring_base; -+ u32 hal_sw2reo1_ring_base; -+ u32 hal_reo_cmd_ring_base; -+ u32 hal_reo_status_ring_base; -+ u32 hal_wbm_idle_link_ring_base; -+ u32 hal_wbm_idle_link_ring_misc; -+ u32 hal_wbm_idle_list_ctrl_addr; -+ u32 hal_wbm_idle_list_size_addr; -+ u32 hal_wbm_scat_ring_base_lsb; -+ u32 hal_wbm_scat_ring_base_msb; -+ u32 hal_wbm_scat_desc_ptr_head_ix0; -+ u32 hal_wbm_scat_desc_ptr_head_ix1; -+ u32 hal_wbm_scat_desc_ptr_tail_ix0; -+ u32 hal_wbm_scat_desc_ptr_tail_ix1; -+ u32 hal_wbm_scat_desc_ptr_hp_addr; -+ u32 hal_wbm_sw_rel_ring_base; -+ u32 hal_wbm_sw1_rel_ring_base; -+ u32 hal_wbm0_rel_ring_base; -+ u32 hal_wbm1_rel_ring_base; -+ u32 hal_ppe_rel_ring_base; ++ + /* PCIe base address */ + .pcie_qserdes_sysclk_en_sel = 0x01e0c0a8, + .pcie_pcs_osc_dtct_config_base = 0x01e0d45c, +@@ -957,6 +1083,72 @@ static const struct ath12k_hw_params ath + .wakeup_mhi = false, + .alloc_cacheable_memory = false, + }, ++ { ++ .name = "qcn9274 hw2.0", ++ .hw_rev = ATH12K_HW_QCN9274_HW20, ++ .fw = { ++ .dir = "QCN92XX/hw1.0", ++ .board_size = 256 * 1024, ++ .cal_offset = 128 * 1024, ++ }, ++ .max_radios = 1, ++ .single_pdev_only = false, ++ .qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_QCN9274, ++ .internal_sleep_clock = false, ++ ++ .hw_ops = &qcn9274_ops, ++ .ring_mask = &ath12k_hw_ring_mask_qcn9274, ++ .regs = &qcn9274_v2_regs, ++ ++ .host_ce_config = ath12k_host_ce_config_qcn9274, ++ .ce_count = 16, ++ .target_ce_config = ath12k_target_ce_config_wlan_qcn9274, ++ .target_ce_count = 12, ++ .svc_to_ce_map = ath12k_target_service_to_ce_map_wlan_qcn9274, ++ .svc_to_ce_map_len = 21, ++ ++ .hal_params = &ath12k_hw_hal_params_qcn9274, ++ ++ .rxdma1_enable = true, ++ .num_rxmda_per_pdev = 1, ++ .num_rxdma_dst_ring = 0, ++ .rx_mac_buf_ring = false, ++ .vdev_start_delay = false, ++ ++ .interface_modes = BIT(NL80211_IFTYPE_STATION) | ++ BIT(NL80211_IFTYPE_AP) | ++ BIT(NL80211_IFTYPE_MESH_POINT), ++ .supports_monitor = true, ++ ++ .idle_ps = false, ++ .cold_boot_calib = false, ++ .download_calib = true, ++ .supports_suspend = false, ++ .tcl_ring_retry = true, ++ .reoq_lut_support = true, ++ .supports_shadow_regs = false, ++ ++ .hal_desc_sz = sizeof(struct hal_rx_desc_qcn9274), ++ .num_tcl_banks = 48, ++ .max_tx_ring = 4, ++ .static_window_map = true, ++ ++ .mhi_config = &ath12k_mhi_config_qcn9274, ++ ++ .wmi_init = ath12k_wmi_init_qcn9274, ++ ++ .hal_ops = &hal_qcn9274_ops, ++ ++ .qdss_config = NULL, ++ .qdss_config_len = 0, ++ ++ .fix_l1ss = false, ++ ++ .supports_ap_ps = true, ++ .credit_flow = false, ++ .wakeup_mhi = false, ++ .alloc_cacheable_memory = true, ++ }, }; - extern const struct ath12k_hw_regs qcn92xx_regs; -+extern const struct ath12k_hw_regs qcn92xx_v2_regs; - #endif -diff --git a/drivers/net/wireless/ath/ath12k/mhi.c b/drivers/net/wireless/ath/ath12k/mhi.c -index f1ff9c2..881a027 100644 ---- a/drivers/net/wireless/ath/ath12k/mhi.c -+++ b/drivers/net/wireless/ath/ath12k/mhi.c -@@ -328,7 +328,8 @@ int ath12k_mhi_register(struct ath12k_pci *ab_pci) - mhi_ctrl->read_reg = ath12k_mhi_op_read_reg; - mhi_ctrl->write_reg = ath12k_mhi_op_write_reg; - -- if (ab->hw_rev == ATH12K_HW_QCN92XX_HW10) -+ if ((ab->hw_rev == ATH12K_HW_QCN92XX_HW10) || -+ (ab->hw_rev == ATH12K_HW_QCN92XX_HW20)) - ath12k_mhi_config = &ath12k_mhi_config_qcn92xx; - - ret = mhi_register_controller(mhi_ctrl, ath12k_mhi_config); -diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c -index 257812c..4104bd8 100644 + int ath12k_hw_init(struct ath12k_base *ab) --- a/drivers/net/wireless/ath/ath12k/pci.c +++ b/drivers/net/wireless/ath/ath12k/pci.c @@ -27,9 +27,9 @@ @@ -823,7 +555,7 @@ index 257812c..4104bd8 100644 /* BAR0 + 4k is always accessible, and no * need to force wakeup. -@@ -887,6 +887,22 @@ static void ath12k_pci_aspm_disable(struct ath12k_pci *ab_pci) +@@ -824,6 +824,22 @@ static void ath12k_pci_aspm_disable(stru set_bit(ATH12K_PCI_ASPM_RESTORE, &ab_pci->flags); } @@ -846,7 +578,64 @@ index 257812c..4104bd8 100644 static void ath12k_pci_update_qrtr_node_id(struct ath12k_base *ab) { struct ath12k_pci *ab_pci = ath12k_pci_priv(ab); -@@ -1306,7 +1322,7 @@ static int ath12k_pci_probe(struct pci_dev *pdev, +@@ -1069,15 +1085,16 @@ u32 ath12k_pci_read32(struct ath12k_base + /* for offset beyond BAR + 4K - 32, may + * need to wakeup MHI to access. + */ +- if (ab->hw_params->wakeup_mhi && +- test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && +- offset >= ACCESS_ALWAYS_OFF) ++ if (test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && ++ offset >= ACCESS_ALWAYS_OFF && ab->hw_params->wakeup_mhi) + mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev); + + if (offset < WINDOW_START) { + val = ioread32(ab->mem + offset); + } else { +- if (ab->hw_params->static_window_map) ++ /* TODO: */ ++ if (offset == TCSR_SOC_HW_VERSION || ++ ab->hw_params->static_window_map) + window_start = ath12k_pci_get_window_start(ab, offset); + else + window_start = WINDOW_START; +@@ -1114,9 +1131,8 @@ u32 ath12k_pci_read32(struct ath12k_base + } + } + +- if (ab->hw_params->wakeup_mhi && +- test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && +- offset >= ACCESS_ALWAYS_OFF) ++ if (test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && ++ offset >= ACCESS_ALWAYS_OFF && ab->hw_params->wakeup_mhi) + mhi_device_put(ab_pci->mhi_ctrl->mhi_dev); + + return val; +@@ -1131,9 +1147,8 @@ void ath12k_pci_write32(struct ath12k_ba + /* for offset beyond BAR + 4K - 32, may + * need to wakeup MHI to access. + */ +- if (ab->hw_params->wakeup_mhi && +- test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && +- offset >= ACCESS_ALWAYS_OFF) ++ if (test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && ++ offset >= ACCESS_ALWAYS_OFF && ab->hw_params->wakeup_mhi) + mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev); + + if (offset < WINDOW_START) { +@@ -1176,9 +1191,8 @@ void ath12k_pci_write32(struct ath12k_ba + } + } + +- if (ab->hw_params->wakeup_mhi && +- test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && +- offset >= ACCESS_ALWAYS_OFF) ++ if (test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && ++ offset >= ACCESS_ALWAYS_OFF && ab->hw_params->wakeup_mhi) + mhi_device_put(ab_pci->mhi_ctrl->mhi_dev); + } + +@@ -1253,7 +1267,7 @@ static int ath12k_pci_probe(struct pci_d { struct ath12k_base *ab; struct ath12k_pci *ab_pci; @@ -854,33 +643,85 @@ index 257812c..4104bd8 100644 + u32 soc_hw_version_major, soc_hw_version_minor, addr; int ret; - dev_warn(&pdev->dev, "WARNING: ath12k PCI support is experimental 2!\n"); -@@ -1349,7 +1365,12 @@ static int ath12k_pci_probe(struct pci_dev *pdev, - case QCN92XX_DEVICE_ID: + ab = ath12k_core_alloc(&pdev->dev, sizeof(*ab_pci), ATH12K_BUS_PCI, +@@ -1294,7 +1308,13 @@ static int ath12k_pci_probe(struct pci_d + switch (pci_dev->device) { + case QCN9274_DEVICE_ID: ab_pci->msi_config = &ath12k_msi_config[0]; - ab->bus_params.static_window_map = true; -- ab->hw_rev = ATH12K_HW_QCN92XX_HW10; +- ab->hw_rev = ATH12K_HW_QCN9274_HW10; + ath12k_pci_read_hw_version(ab, &soc_hw_version_major, + &soc_hw_version_minor); ++ + if (soc_hw_version_major == 0x2) -+ ab->hw_rev = ATH12K_HW_QCN92XX_HW20; ++ ab->hw_rev = ATH12K_HW_QCN9274_HW20; + else -+ ab->hw_rev = ATH12K_HW_QCN92XX_HW10; ++ ab->hw_rev = ATH12K_HW_QCN9274_HW10; break; - default: - dev_err(&pdev->dev, "Unknown PCI device found: 0x%x\n", -diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c -index 5fb1b57..2a2f9dd 100644 ---- a/drivers/net/wireless/ath/ath12k/wmi.c -+++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -9391,6 +9391,7 @@ int ath12k_wmi_attach(struct ath12k_base *ab) + case WCN7850_DEVICE_ID: + ab_pci->msi_config = &ath12k_msi_config[0]; +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -125,7 +125,8 @@ struct ath12k_skb_rxcb { - switch (ab->hw_rev) { - case ATH12K_HW_QCN92XX_HW10: -+ case ATH12K_HW_QCN92XX_HW20: - ab->wmi_ab.ops = &wmi_qcn92xx_ops; - break; - default: --- -2.7.4 - + enum ath12k_hw_rev { + ATH12K_HW_QCN9274_HW10 = 0, +- ATH12K_HW_WCN7850_HW20 ++ ATH12K_HW_QCN9274_HW20, ++ ATH12K_HW_WCN7850_HW20, + }; + + #define ATH12K_DIAG_HW_ID_OFFSET 16 +--- a/drivers/net/wireless/ath/ath12k/hw.h ++++ b/drivers/net/wireless/ath/ath12k/hw.h +@@ -275,6 +275,38 @@ struct ath12k_hw_regs { + + u32 hal_tcl_status_ring_base_lsb; + ++ u32 hal_reo2_ring_base; ++ u32 hal_reo1_misc_ctrl_addr; ++ u32 hal_reo1_sw_cookie_cfg0; ++ u32 hal_reo1_sw_cookie_cfg1; ++ u32 hal_reo1_qdesc_lut_base0; ++ u32 hal_reo1_qdesc_lut_base1; ++ u32 hal_reo1_qdesc_addr_read; ++ u32 hal_reo1_qdesc_max_peerid; ++ u32 hal_reo1_ring_base_lsb; ++ u32 hal_reo1_ring_base_msb; ++ u32 hal_reo1_ring_id; ++ u32 hal_reo1_ring_misc; ++ u32 hal_reo1_ring_hp_addr_lsb; ++ u32 hal_reo1_ring_hp_addr_msb; ++ u32 hal_reo1_ring_producer_int_setup; ++ u32 hal_reo1_ring_msi1_base_lsb; ++ u32 hal_reo1_ring_msi1_base_msb; ++ u32 hal_reo1_ring_msi1_data; ++ u32 hal_reo1_aging_thres_ix0; ++ u32 hal_reo1_aging_thres_ix1; ++ u32 hal_reo1_aging_thres_ix2; ++ u32 hal_reo1_aging_thres_ix3; ++ ++ u32 hal_reo2_sw0_ring_base; ++ ++ u32 hal_sw2reo_ring_base; ++ u32 hal_sw2reo1_ring_base; ++ ++ u32 hal_reo_cmd_ring_base; ++ ++ u32 hal_reo_status_ring_base; ++ + u32 hal_wbm_idle_ring_base_lsb; + u32 hal_wbm_idle_ring_misc_addr; + u32 hal_wbm_r0_idle_list_cntl_addr; +@@ -289,9 +321,12 @@ struct ath12k_hw_regs { + + u32 hal_wbm_sw_release_ring_base_lsb; + u32 hal_wbm_sw1_release_ring_base_lsb; ++ + u32 hal_wbm0_release_ring_base_lsb; + u32 hal_wbm1_release_ring_base_lsb; + ++ u32 hal_ppe_rel_ring_base; ++ + u32 pcie_qserdes_sysclk_en_sel; + u32 pcie_pcs_osc_dtct_config_base; + }; diff --git a/feeds/ipq95xx/mac80211/patches/qca/665-ath12k-delete-desc-list-before-adding-to-free-list.patch b/feeds/ipq95xx/mac80211/patches/qca/665-ath12k-delete-desc-list-before-adding-to-free-list.patch deleted file mode 100644 index f759f056f..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/665-ath12k-delete-desc-list-before-adding-to-free-list.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 84a3c6759f15b7cedc4ed1fd292a64d91c0bd127 Mon Sep 17 00:00:00 2001 -From: Rajat Soni -Date: Thu, 8 Sep 2022 14:48:28 +0530 -Subject: [PATCH] ath12k: delete desc list before adding to free list - -Host crash is seen when we do rmmod after pinging AP to STA -because in ath12k_dp_cc_cleanup() during rx desc cleanup -dma_unmap_single is getting incorrect address that causes crash. - -To resolve this desc info list should be deleted before adding -to free list. - -Signed-off-by: Rajat Soni ---- - drivers/net/wireless/ath/ath12k/dp_rx.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c -index eada13a..978bc40 100644 ---- a/drivers/net/wireless/ath/ath12k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -3004,7 +3004,7 @@ try_again: - desc_info->skb = NULL; - - spin_lock_bh(&dp->rx_desc_lock); -- list_add_tail(&desc_info->list, &dp->rx_desc_free_list); -+ list_move_tail(&desc_info->list, &dp->rx_desc_free_list); - spin_unlock_bh(&dp->rx_desc_lock); - - rxcb = ATH12K_SKB_RXCB(msdu); -@@ -3702,7 +3702,7 @@ ath12k_dp_process_rx_err_buf(struct ath12k *ar, u32 *ring_desc, - msdu = desc_info->skb; - desc_info->skb = NULL; - spin_lock_bh(&ab->dp.rx_desc_lock); -- list_add_tail(&desc_info->list, &ab->dp.rx_desc_free_list); -+ list_move_tail(&desc_info->list, &ab->dp.rx_desc_free_list); - spin_unlock_bh(&ab->dp.rx_desc_lock); - - rxcb = ATH12K_SKB_RXCB(msdu); -@@ -4204,7 +4204,7 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab, - desc_info->skb = NULL; - - spin_lock_bh(&dp->rx_desc_lock); -- list_add_tail(&desc_info->list, &dp->rx_desc_free_list); -+ list_move_tail(&desc_info->list, &dp->rx_desc_free_list); - spin_unlock_bh(&dp->rx_desc_lock); - - rxcb = ATH12K_SKB_RXCB(msdu); --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/666-ath12k-Fixed-dma-unmapping-in-tx-desc-cleanup.patch b/feeds/ipq95xx/mac80211/patches/qca/666-ath12k-Fixed-dma-unmapping-in-tx-desc-cleanup.patch index 97bb7752c..42e6af6c3 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/666-ath12k-Fixed-dma-unmapping-in-tx-desc-cleanup.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/666-ath12k-Fixed-dma-unmapping-in-tx-desc-cleanup.patch @@ -23,21 +23,14 @@ Signed-off-by: Rajat Soni drivers/net/wireless/ath/ath12k/dp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c -index 455e608..6181c83 100644 --- a/drivers/net/wireless/ath/ath12k/dp.c +++ b/drivers/net/wireless/ath/ath12k/dp.c -@@ -1194,8 +1194,8 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab) +@@ -1194,7 +1194,7 @@ static void ath12k_dp_cc_cleanup(struct if (!skb) continue; - dma_unmap_single(ab->dev, ATH12K_SKB_RXCB(skb)->paddr, -- skb->len + skb_tailroom(skb), DMA_FROM_DEVICE); + dma_unmap_single(ab->dev, ATH12K_SKB_CB(skb)->paddr, -+ skb->len, DMA_TO_DEVICE); + skb->len, DMA_TO_DEVICE); dev_kfree_skb_any(skb); } - --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/666-ath12k-add-RAW-Mode-support.patch b/feeds/ipq95xx/mac80211/patches/qca/666-ath12k-add-RAW-Mode-support.patch new file mode 100644 index 000000000..df5c87d4e --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/666-ath12k-add-RAW-Mode-support.patch @@ -0,0 +1,33 @@ +From f4227ac6fbb661285e17479196abad1ad3588474 Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Wed, 14 Sep 2022 17:26:38 +0530 +Subject: [PATCH] ath12k: add RAW Mode support + +adding RAW Mode encap type support for software and hardware encrption. + +command: insmod ath12k.ko cryptmode=1 frame_mode=0 (SW encryption) + insmod ath12k.ko cryptmode=0 frame_mode=0 (HW encryption) + +Signed-off-by: Aaradhana Sahu +--- + drivers/net/wireless/ath/ath12k/dp_tx.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c +index 082caba..65f74e1 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -16,6 +16,10 @@ static enum hal_tcl_encap_type + ath12k_dp_tx_get_encap_type(struct ath12k_vif *arvif, struct sk_buff *skb) + { + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); ++ struct ath12k_base *ab = arvif->ar->ab; ++ ++ if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags)) ++ return HAL_TCL_ENCAP_TYPE_RAW; + + if (tx_info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) + return HAL_TCL_ENCAP_TYPE_ETHERNET; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/666-ath12k-fix-320Mhz-bytes-packets-counters-in-peer-stats.patch b/feeds/ipq95xx/mac80211/patches/qca/666-ath12k-fix-320Mhz-bytes-packets-counters-in-peer-stats.patch index e25fc3e1d..2cbe74a28 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/666-ath12k-fix-320Mhz-bytes-packets-counters-in-peer-stats.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/666-ath12k-fix-320Mhz-bytes-packets-counters-in-peer-stats.patch @@ -15,29 +15,11 @@ Signed-off-by: Thiraviyam Mariyappan drivers/net/wireless/ath/ath12k/hal_rx.h | 10 +++++----- 5 files changed, 20 insertions(+), 9 deletions(-) ---- a/drivers/net/wireless/ath/ath12k/debugfs_sta.c -+++ b/drivers/net/wireless/ath/ath12k/debugfs_sta.c -@@ -488,7 +488,7 @@ static ssize_t ath12k_dbg_sta_dump_rx_st - rx_stats->pkt_stats.bw_count[1], - rx_stats->pkt_stats.bw_count[2], - rx_stats->pkt_stats.bw_count[3], -- rx_stats->pkt_stats.bw_count[4]); -+ rx_stats->pkt_stats.bw_count[5]); - len += scnprintf(buf + len, size - len, "\nRate Table (packets):\n"); - num_run = HAL_RX_BW_MAX * HAL_RX_GI_MAX * HAL_RX_MAX_NSS; - -@@ -580,7 +580,7 @@ static ssize_t ath12k_dbg_sta_dump_rx_st - rx_stats->byte_stats.bw_count[1], - rx_stats->byte_stats.bw_count[2], - rx_stats->byte_stats.bw_count[3], -- rx_stats->byte_stats.bw_count[4]); -+ rx_stats->byte_stats.bw_count[5]); - len += scnprintf(buf + len, size - len, "\nRate Table (bytes):\n"); - - bw = 0; ---- a/drivers/net/wireless/ath/ath12k/dp.h -+++ b/drivers/net/wireless/ath/ath12k/dp.h -@@ -1488,6 +1488,8 @@ enum HTT_PPDU_STATS_BW { +Index: b/drivers/net/wireless/ath/ath12k/dp.h +=================================================================== +--- a/drivers/net/wireless/ath/ath12k/dp.h 2023-02-01 09:47:21.819657790 +0530 ++++ b/drivers/net/wireless/ath/ath12k/dp.h 2023-02-01 09:47:21.815657824 +0530 +@@ -1452,6 +1452,8 @@ enum HTT_PPDU_STATS_BW { HTT_PPDU_STATS_BANDWIDTH_80MHZ = 4, HTT_PPDU_STATS_BANDWIDTH_160MHZ = 5, /* includes 80+80 */ HTT_PPDU_STATS_BANDWIDTH_DYN = 6, @@ -46,9 +28,11 @@ Signed-off-by: Thiraviyam Mariyappan }; #define HTT_PPDU_STATS_CMN_FLAGS_FRAME_TYPE_M GENMASK(7, 0) ---- a/drivers/net/wireless/ath/ath12k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -1355,6 +1355,32 @@ static u32 ath12k_dp_rx_ru_alloc_from_ru +Index: b/drivers/net/wireless/ath/ath12k/dp_rx.c +=================================================================== +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c 2023-02-01 09:47:21.819657790 +0530 ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c 2023-02-01 09:47:21.815657824 +0530 +@@ -1376,6 +1376,32 @@ static u32 ath12k_dp_rx_ru_alloc_from_ru return width; } @@ -81,7 +65,7 @@ Signed-off-by: Thiraviyam Mariyappan static void ath12k_update_per_peer_tx_stats(struct ath12k *ar, struct htt_ppdu_stats_info *ppdu_info, u8 user) -@@ -1424,7 +1450,7 @@ ath12k_update_per_peer_tx_stats(struct a +@@ -1445,7 +1471,7 @@ ath12k_update_per_peer_tx_stats(struct a } flags = HTT_USR_RATE_PREAMBLE(rate_flags); @@ -90,8 +74,10 @@ Signed-off-by: Thiraviyam Mariyappan nss = HTT_USR_RATE_NSS(rate_flags) + 1; mcs = HTT_USR_RATE_MCS(rate_flags); sgi = HTT_USR_RATE_GI(rate_flags); ---- a/drivers/net/wireless/ath/ath12k/hal_rx.h -+++ b/drivers/net/wireless/ath/ath12k/hal_rx.h +Index: b/drivers/net/wireless/ath/ath12k/hal_rx.h +=================================================================== +--- a/drivers/net/wireless/ath/ath12k/hal_rx.h 2023-02-01 09:47:21.819657790 +0530 ++++ b/drivers/net/wireless/ath/ath12k/hal_rx.h 2023-02-01 09:47:21.815657824 +0530 @@ -61,6 +61,7 @@ enum hal_rx_bw { HAL_RX_BW_40MHZ, HAL_RX_BW_80MHZ, diff --git a/feeds/ipq95xx/mac80211/patches/qca/666-mac80211-Fix-Green-AP-Crash-issue.patch b/feeds/ipq95xx/mac80211/patches/qca/666-mac80211-Fix-Green-AP-Crash-issue.patch index c8308cbba..8263fd812 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/666-mac80211-Fix-Green-AP-Crash-issue.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/666-mac80211-Fix-Green-AP-Crash-issue.patch @@ -18,31 +18,25 @@ Signed-off-by: Sivashankari Madhavan net/mac80211/cfg.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) -diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c -index bfbe75e..410772d 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -1472,7 +1472,7 @@ static int ieee80211_update_ap(struct wiphy *wiphy, struct net_device *dev, - struct ieee80211_sub_if_data *sdata; +@@ -1480,7 +1480,7 @@ static int ieee80211_update_ap(struct wi struct beacon_data *old; int err = -EINVAL; + struct ieee80211_bss_conf *link_conf; - u32 changed; + u32 changed = 0; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); sdata_assert_lock(sdata); -@@ -1501,8 +1501,10 @@ static int ieee80211_update_ap(struct wiphy *wiphy, struct net_device *dev, - else - err |= BSS_CHANGED_PS; + +@@ -1521,7 +1521,9 @@ static int ieee80211_update_ap(struct wi + err |= BSS_CHANGED_HE_BSS_COLOR; } -+ -+ if (err > 0) -+ changed = err; - changed = err; ++ if (err > 0) ++ changed = err; ++ if (params->fils_discovery.max_interval) { err = ieee80211_set_fils_discovery(sdata, - ¶ms->fils_discovery); --- -2.17.1 - + ¶ms->fils_discovery, diff --git a/feeds/ipq95xx/mac80211/patches/qca/668-ath12k-fix-memory-leaks-during-multicast-tx.patch b/feeds/ipq95xx/mac80211/patches/qca/668-ath12k-fix-memory-leaks-during-multicast-tx.patch index 168a16a9e..60ade2f33 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/668-ath12k-fix-memory-leaks-during-multicast-tx.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/668-ath12k-fix-memory-leaks-during-multicast-tx.patch @@ -27,7 +27,7 @@ Signed-off-by: P Praneesh dma_unmap_single(ab->dev, ATH12K_SKB_CB(skb)->paddr, skb->len, DMA_TO_DEVICE); + -+ if (ATH12K_SKB_CB(skb)->paddr_ext_desc) { ++ if (tx_desc_info->skb_ext_desc) { + dma_unmap_single(ab->dev, ATH12K_SKB_CB(skb)->paddr_ext_desc, + tx_desc_info->skb_ext_desc->len, DMA_TO_DEVICE); + dev_kfree_skb_any(tx_desc_info->skb_ext_desc); @@ -38,7 +38,7 @@ Signed-off-by: P Praneesh --- a/drivers/net/wireless/ath/ath12k/dp.h +++ b/drivers/net/wireless/ath/ath12k/dp.h -@@ -320,6 +320,7 @@ struct ath12k_rx_desc_info { +@@ -281,6 +281,7 @@ struct ath12k_rx_desc_info { struct ath12k_tx_desc_info { struct list_head list; struct sk_buff *skb; @@ -56,18 +56,18 @@ Signed-off-by: P Praneesh list_move_tail(&tx_desc->list, &dp->tx_desc_free_list[ring_id]); spin_unlock_bh(&dp->tx_desc_lock[ring_id]); } -@@ -276,15 +277,14 @@ tcl_ring_sel: - ti.paddr = dma_map_single(ab->dev, skb_ext_desc->data, +@@ -286,7 +287,9 @@ tcl_ring_sel: skb_ext_desc->len, DMA_TO_DEVICE); ret = dma_mapping_error(ab->dev, ti.paddr); -- if (ret) { + if (ret) { - kfree(skb_ext_desc); -- goto fail_unmap_dma; -- } -+ if (ret) -+ goto fail_unmap_dma_ext_desc; ++ atomic_inc(&ab->soc_stats.tx_err.misc_fail); ++ ath12k_warn(ab, "Failed to DMA map data Tx buffer\n"); ++ dev_kfree_skb_any(skb_ext_desc); + goto fail_unmap_dma; + } - ti.data_len = skb_ext_desc->len; +@@ -294,6 +297,7 @@ tcl_ring_sel: ti.type = HAL_TCL_DESC_TYPE_EXT_DESC; skb_cb->paddr_ext_desc = ti.paddr; @@ -75,7 +75,7 @@ Signed-off-by: P Praneesh } hal_ring_id = tx_ring->tcl_data_ring.ring_id; -@@ -314,7 +314,7 @@ tcl_ring_sel: +@@ -324,7 +328,7 @@ tcl_ring_sel: ring_selector++; } @@ -84,7 +84,7 @@ Signed-off-by: P Praneesh } ath12k_hal_tx_cmd_desc_setup(ab, hal_tcl_desc, &ti); -@@ -330,10 +330,15 @@ tcl_ring_sel: +@@ -340,10 +344,15 @@ tcl_ring_sel: return 0; @@ -103,7 +103,7 @@ Signed-off-by: P Praneesh fail_remove_tx_buf: ath12k_dp_tx_release_txbuf(dp, tx_desc, ti.ring_id); -@@ -345,7 +350,8 @@ fail_remove_tx_buf: +@@ -355,7 +364,8 @@ fail_remove_tx_buf: static void ath12k_dp_tx_free_txbuf(struct ath12k_base *ab, struct sk_buff *msdu, u8 mac_id, @@ -113,12 +113,12 @@ Signed-off-by: P Praneesh { struct ath12k *ar; struct ath12k_skb_cb *skb_cb; -@@ -354,10 +360,12 @@ static void ath12k_dp_tx_free_txbuf(stru +@@ -364,10 +374,12 @@ static void ath12k_dp_tx_free_txbuf(stru dma_unmap_single_attrs(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); - if (unlikely(skb_cb->paddr_ext_desc)) -+ if (unlikely(skb_cb->paddr_ext_desc)) { ++ if (unlikely(skb_ext_desc)) { dma_unmap_single_attrs(ab->dev, skb_cb->paddr_ext_desc, - sizeof(struct hal_tx_msdu_ext_desc), - DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); @@ -129,7 +129,7 @@ Signed-off-by: P Praneesh dev_kfree_skb_any(msdu); -@@ -370,7 +378,8 @@ static void +@@ -380,7 +392,8 @@ static void ath12k_dp_tx_htt_tx_complete_buf(struct ath12k_base *ab, struct sk_buff *msdu, struct dp_tx_ring *tx_ring, @@ -139,12 +139,12 @@ Signed-off-by: P Praneesh { struct ieee80211_tx_info *info; struct ath12k_skb_cb *skb_cb; -@@ -387,9 +396,11 @@ ath12k_dp_tx_htt_tx_complete_buf(struct +@@ -397,9 +410,11 @@ ath12k_dp_tx_htt_tx_complete_buf(struct wake_up(&ar->dp.tx_empty_waitq); dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); - if (unlikely(skb_cb->paddr_ext_desc)) -+ if (unlikely(skb_cb->paddr_ext_desc)) { ++ if (unlikely(skb_ext_desc)) { dma_unmap_single(ab->dev, skb_cb->paddr_ext_desc, - sizeof(struct hal_tx_msdu_ext_desc), DMA_TO_DEVICE); + skb_ext_desc->len, DMA_TO_DEVICE); @@ -153,7 +153,7 @@ Signed-off-by: P Praneesh flags = skb_cb->flags; -@@ -437,7 +448,8 @@ static void +@@ -447,7 +462,8 @@ static void ath12k_dp_tx_process_htt_tx_complete(struct ath12k_base *ab, void *desc, u8 mac_id, struct sk_buff *msdu, @@ -163,10 +163,10 @@ Signed-off-by: P Praneesh { struct htt_tx_wbm_completion *status_desc; struct ath12k_dp_htt_wbm_tx_status ts = {0}; -@@ -454,11 +466,11 @@ ath12k_dp_tx_process_htt_tx_complete(str +@@ -465,11 +481,11 @@ ath12k_dp_tx_process_htt_tx_complete(str ts.acked = (wbm_status == HAL_WBM_REL_HTT_TX_COMP_STATUS_OK); - ts.ack_rssi = FIELD_GET(HTT_TX_WBM_COMP_INFO2_ACK_RSSI, - status_desc->info2); + ts.ack_rssi = u32_get_bits(status_desc->info2, + HTT_TX_WBM_COMP_INFO2_ACK_RSSI); - ath12k_dp_tx_htt_tx_complete_buf(ab, msdu, tx_ring, &ts); + ath12k_dp_tx_htt_tx_complete_buf(ab, msdu, tx_ring, &ts, skb_ext_desc); break; @@ -177,7 +177,7 @@ Signed-off-by: P Praneesh break; case HAL_WBM_REL_HTT_TX_COMP_STATUS_MEC_NOTIFY: /* This event is to be handled only when the driver decides to -@@ -626,7 +638,8 @@ static inline void ath12k_dp_tx_status_p +@@ -637,7 +653,8 @@ static inline void ath12k_dp_tx_status_p static void ath12k_dp_tx_complete_msdu(struct ath12k *ar, struct sk_buff *msdu, struct hal_wbm_release_ring *tx_status, @@ -187,7 +187,7 @@ Signed-off-by: P Praneesh { struct ieee80211_tx_status status = { 0 }; -@@ -652,10 +665,12 @@ static void ath12k_dp_tx_complete_msdu(s +@@ -663,10 +680,12 @@ static void ath12k_dp_tx_complete_msdu(s dma_unmap_single_attrs(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); @@ -203,7 +203,7 @@ Signed-off-by: P Praneesh flags = skb_cb->flags; -@@ -790,7 +805,7 @@ void ath12k_dp_tx_completion_handler(str +@@ -801,7 +820,7 @@ void ath12k_dp_tx_completion_handler(str int hal_ring_id = dp->tx_ring[ring_id].tcl_comp_ring.ring_id; struct hal_srng *status_ring = &ab->hal.srng_list[hal_ring_id]; struct ath12k_tx_desc_info *tx_desc = NULL; @@ -212,15 +212,16 @@ Signed-off-by: P Praneesh struct dp_tx_ring *tx_ring = &dp->tx_ring[ring_id]; u32 *desc, desc_id; u8 mac_id; -@@ -849,6 +864,7 @@ void ath12k_dp_tx_completion_handler(str +@@ -861,7 +880,7 @@ void ath12k_dp_tx_completion_handler(str msdu = tx_desc->skb; mac_id = tx_desc->mac_id; +- + skb_ext_desc = tx_desc->skb_ext_desc; /* Release descriptor as soon as extracting necessary info * to reduce contention */ -@@ -859,7 +875,7 @@ void ath12k_dp_tx_completion_handler(str +@@ -872,7 +891,7 @@ void ath12k_dp_tx_completion_handler(str ath12k_dp_tx_process_htt_tx_complete(ab, (void *)tx_status, mac_id, msdu, @@ -229,7 +230,7 @@ Signed-off-by: P Praneesh continue; } -@@ -868,7 +884,7 @@ void ath12k_dp_tx_completion_handler(str +@@ -881,7 +900,7 @@ void ath12k_dp_tx_completion_handler(str if (atomic_dec_and_test(&ar->dp.num_tx_pending)) wake_up(&ar->dp.tx_empty_waitq); diff --git a/feeds/ipq95xx/mac80211/patches/qca/668-ath12k-regdb-encoding-board-2-binary.patch b/feeds/ipq95xx/mac80211/patches/qca/668-ath12k-regdb-encoding-board-2-binary.patch index abad5d601..50ba15216 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/668-ath12k-regdb-encoding-board-2-binary.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/668-ath12k-regdb-encoding-board-2-binary.patch @@ -17,7 +17,7 @@ Signed-off-by: Karthik M --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c -@@ -403,7 +403,7 @@ int ath12k_core_check_dt(struct ath12k_b +@@ -325,7 +325,7 @@ int ath12k_core_check_dt(struct ath12k_b } static int ath12k_core_create_board_name(struct ath12k_base *ab, char *name, @@ -26,7 +26,7 @@ Signed-off-by: Karthik M { /* strlen(',variant=') + strlen(ab->qmi.target.bdf_ext) */ char variant[9 + ATH12K_QMI_BDF_EXT_STR_LENGTH] = { 0 }; -@@ -411,12 +411,33 @@ static int ath12k_core_create_board_name +@@ -333,12 +333,33 @@ static int ath12k_core_create_board_name if (ab->qmi.target.bdf_ext[0] != '\0') scnprintf(variant, sizeof(variant), ",variant=%s", ab->qmi.target.bdf_ext); @@ -66,7 +66,7 @@ Signed-off-by: Karthik M ath12k_dbg(ab, ATH12K_DBG_BOOT, "boot using board name '%s'\n", name); -@@ -457,7 +478,9 @@ static int ath12k_core_parse_bd_ie_board +@@ -379,7 +400,9 @@ static int ath12k_core_parse_bd_ie_board struct ath12k_board_data *bd, const void *buf, size_t buf_len, const char *boardname, @@ -77,7 +77,7 @@ Signed-off-by: Karthik M { const struct ath12k_fw_ie *hdr; bool name_match_found; -@@ -467,7 +490,7 @@ static int ath12k_core_parse_bd_ie_board +@@ -389,7 +412,7 @@ static int ath12k_core_parse_bd_ie_board name_match_found = false; @@ -86,7 +86,7 @@ Signed-off-by: Karthik M while (buf_len > sizeof(struct ath12k_fw_ie)) { hdr = buf; board_ie_id = le32_to_cpu(hdr->id); -@@ -478,48 +501,51 @@ static int ath12k_core_parse_bd_ie_board +@@ -400,48 +423,51 @@ static int ath12k_core_parse_bd_ie_board buf += sizeof(*hdr); if (buf_len < ALIGN(board_ie_len, 4)) { @@ -153,7 +153,7 @@ Signed-off-by: Karthik M /* jump over the padding */ board_ie_len = ALIGN(board_ie_len, 4); -@@ -535,8 +561,11 @@ out: +@@ -457,8 +483,11 @@ out: } static int ath12k_core_fetch_board_data_api_n(struct ath12k_base *ab, @@ -167,13 +167,8 @@ Signed-off-by: Karthik M { size_t len, magic_len; const u8 *data; -@@ -597,18 +626,20 @@ static int ath12k_core_fetch_board_data_ - if (len < ALIGN(ie_len, 4)) { - ath12k_err(ab, "invalid length for board ie_id %d ie_len %zu len %zu\n", - ie_id, ie_len, len); -- return -EINVAL; -+ ret = -EINVAL; -+ goto err; +@@ -523,15 +552,16 @@ static int ath12k_core_fetch_board_data_ + goto err; } - switch (ie_id) { @@ -193,7 +188,7 @@ Signed-off-by: Karthik M else if (ret) /* there was an error, bail out */ goto err; -@@ -616,6 +647,7 @@ static int ath12k_core_fetch_board_data_ +@@ -539,6 +569,7 @@ static int ath12k_core_fetch_board_data_ goto out; } @@ -201,7 +196,7 @@ Signed-off-by: Karthik M /* jump over the padding */ ie_len = ALIGN(ie_len, 4); -@@ -625,9 +657,10 @@ static int ath12k_core_fetch_board_data_ +@@ -548,9 +579,10 @@ static int ath12k_core_fetch_board_data_ out: if (!bd->data || !bd->len) { @@ -215,7 +210,7 @@ Signed-off-by: Karthik M ret = -ENODATA; goto err; } -@@ -644,6 +677,7 @@ int ath12k_core_fetch_board_data_api_1(s +@@ -567,6 +599,7 @@ int ath12k_core_fetch_board_data_api_1(s char *filename) { bd->fw = ath12k_core_firmware_request(ab, filename); @@ -223,7 +218,7 @@ Signed-off-by: Karthik M if (IS_ERR(bd->fw)) return PTR_ERR(bd->fw); -@@ -653,28 +687,43 @@ int ath12k_core_fetch_board_data_api_1(s +@@ -576,28 +609,43 @@ int ath12k_core_fetch_board_data_api_1(s return 0; } @@ -236,7 +231,7 @@ Signed-off-by: Karthik M - ret = ath12k_core_create_board_name(ab, boardname, BOARD_NAME_SIZE); + ret = ath12k_core_create_board_name(ab, boardname, boarddefaultname, -+ BOARD_NAME_SIZE); ++ BOARD_NAME_SIZE); if (ret) { ath12k_err(ab, "failed to create board name: %d", ret); return ret; @@ -245,36 +240,34 @@ Signed-off-by: Karthik M ab->bd_api = 2; - ret = ath12k_core_fetch_board_data_api_n(ab, bd, boardname); + ret = ath12k_core_fetch_board_data_api_n(ab, bd, boardname, -+ ATH12K_BD_IE_BOARD, -+ ATH12K_BD_IE_BOARD_NAME, -+ ATH12K_BD_IE_BOARD_DATA); ++ ATH12K_BD_IE_BOARD, ++ ATH12K_BD_IE_BOARD_NAME, ++ ATH12K_BD_IE_BOARD_DATA); + if (!ret) + goto success; + + ret = ath12k_core_fetch_board_data_api_n(ab, bd, boarddefaultname, -+ ATH12K_BD_IE_BOARD, -+ ATH12K_BD_IE_BOARD_NAME, -+ ATH12K_BD_IE_BOARD_DATA); ++ ATH12K_BD_IE_BOARD, ++ ATH12K_BD_IE_BOARD_NAME, ++ ATH12K_BD_IE_BOARD_DATA); if (!ret) goto success; ab->bd_api = 1; ret = ath12k_core_fetch_board_data_api_1(ab, bd, ATH12K_DEFAULT_BOARD_FILE); -- if (ret) { + if (ret) { - ath12k_err(ab, "failed to fetch board-2.bin or board.bin from %s\n", -- ab->hw_params.fw.dir); -+ if (ret) -+ ath12k_err(ab, "failed to fetch board.bin from %s\n", -+ ab->hw_params.fw.dir); -+ else { ++ ath12k_err(ab, "failed to fetch board-2.bin from %s\n", + ab->hw_params->fw.dir); ++ } else { + ret = ath12k_core_fetch_board_data_api_1(ab, bd, ATH12K_BOARD_API2_FILE); + if (ret) + ath12k_err(ab, "failed to fetch board-2.bin from %s\n", -+ ab->hw_params.fw.dir); ++ ab->hw_params->fw.dir); return ret; } -@@ -683,6 +732,45 @@ success: +@@ -606,6 +654,45 @@ success: return 0; } @@ -309,7 +302,7 @@ Signed-off-by: Karthik M + ret = ath12k_core_fetch_board_data_api_1(ab, bd, ATH12K_REGDB_FILE_NAME); + if (ret) { + ath12k_err(ab, "failed to fetch %s file from %s\n", -+ ATH12K_REGDB_FILE_NAME, ab->hw_params.fw.dir); ++ ATH12K_REGDB_FILE_NAME, ab->hw_params->fw.dir); + return ret; + } + @@ -322,7 +315,7 @@ Signed-off-by: Karthik M lockdep_assert_held(&ab->ag->mutex_lock); --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h -@@ -59,6 +59,11 @@ enum ath12k_supported_bw { +@@ -60,6 +60,11 @@ enum ath12k_supported_bw { ATH12K_BW_320 = 4, }; @@ -334,7 +327,7 @@ Signed-off-by: Karthik M enum wme_ac { WME_AC_BE, WME_AC_BK, -@@ -851,6 +856,9 @@ struct ath12k_pdev { +@@ -853,6 +858,9 @@ struct ath12k_pdev { struct mlo_timestamp timestamp; }; @@ -344,7 +337,7 @@ Signed-off-by: Karthik M struct ath12k_board_data { const struct firmware *fw; const void *data; -@@ -912,6 +920,13 @@ struct ath12k_reg_freq { +@@ -913,6 +921,13 @@ struct ath12k_reg_freq { u32 end_freq; }; @@ -358,16 +351,16 @@ Signed-off-by: Karthik M struct ath12k_hw { struct ieee80211_hw *hw; -@@ -1057,6 +1072,8 @@ struct ath12k_base { - u32 rx_hash_ix2; - u32 rx_hash_ix3; +@@ -1058,6 +1073,8 @@ struct ath12k_base { + bool stats_disable; + u32 rx_hash; + struct vendor_info id; + /* must be last */ u8 drv_priv[0] __aligned(sizeof(void *)); }; -@@ -1200,6 +1217,8 @@ int ath12k_core_fetch_board_data_api_1(s +@@ -1198,6 +1215,8 @@ int ath12k_core_fetch_board_data_api_1(s char *filename); int ath12k_core_fetch_bdf(struct ath12k_base *ath12k, struct ath12k_board_data *bd); @@ -378,7 +371,7 @@ Signed-off-by: Karthik M --- a/drivers/net/wireless/ath/ath12k/qmi.c +++ b/drivers/net/wireless/ath/ath12k/qmi.c -@@ -3167,12 +3167,12 @@ static int ath12k_qmi_load_bdf_qmi(struc +@@ -3441,12 +3441,12 @@ static int ath12k_qmi_load_bdf_qmi(struc break; case ATH12K_QMI_BDF_TYPE_REGDB: @@ -396,7 +389,7 @@ Signed-off-by: Karthik M ath12k_warn(ab, "unknown file type for load %d", type); --- a/drivers/net/wireless/ath/ath12k/hw.h +++ b/drivers/net/wireless/ath/ath12k/hw.h -@@ -81,6 +81,8 @@ +@@ -84,6 +84,8 @@ #define ATH12K_AMSS_FILE "amss.bin" #define ATH12K_M3_FILE "m3.bin" #define ATH12K_REGDB_FILE_NAME "regdb.bin" @@ -405,7 +398,7 @@ Signed-off-by: Karthik M enum ath12k_hw_rate_cck { ATH12K_HW_RATE_CCK_LP_11M = 0, -@@ -222,12 +224,32 @@ enum ath12k_bd_ie_board_type { +@@ -255,12 +257,32 @@ enum ath12k_bd_ie_board_type { ATH12K_BD_IE_BOARD_DATA = 1, }; diff --git a/feeds/ipq95xx/mac80211/patches/qca/670-01-ath12k-Add-MLO-caps.patch b/feeds/ipq95xx/mac80211/patches/qca/670-01-ath12k-Add-MLO-caps.patch new file mode 100644 index 000000000..172421e8e --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/670-01-ath12k-Add-MLO-caps.patch @@ -0,0 +1,633 @@ +From 0f010961dd09ba1c44ba84c000ad7f084a28778d Mon Sep 17 00:00:00 2001 +From: Bhagavathi Perumal S +Date: Tue, 15 Jun 2021 12:27:39 +0530 +Subject: [PATCH 1/4] ath12k: Add MLO caps + +Added MLO setup related handsake message in QMI. Also filled MLO +parameter in host capability send message. Added MLO global memory +type request support in host with RDDM download support. + +Signed-off-by: Bhagavathi Perumal S +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/core.c | 95 ++++++- + drivers/net/wireless/ath/ath12k/core.h | 16 ++ + drivers/net/wireless/ath/ath12k/qmi.c | 364 ++++++++++++++++++++++++- + drivers/net/wireless/ath/ath12k/qmi.h | 26 +- + drivers/net/wireless/ath/ath12k/wmi.c | 14 +- + drivers/net/wireless/ath/ath12k/wmi.h | 25 +- + 6 files changed, 513 insertions(+), 27 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -1350,15 +1350,36 @@ int ath12k_core_pre_init(struct ath12k_b + return 0; + } + +-static int ath12k_core_hw_group_create(struct ath12k_hw_group *ag) ++static int ath12k_core_get_chip(struct ath12k_hw_group *ag, ++ struct ath12k_base **ab, ++ u8 max_ab, u8 *num_ab) + { +- int i, ret; +- struct ath12k_base *ab; ++ int i; + + lockdep_assert_held(&ag->mutex_lock); + +- for(i = 0; i < ag->num_chip; i++) { +- ab = ag->ab[i]; ++ if (ag->num_chip != ag->num_probed) ++ return -EINVAL; ++ ++ if (max_ab < ag->num_probed) ++ return -ENOMEM; ++ ++ *num_ab = 0; ++ for (i = 0; i < ag->num_probed; i++) { ++ ab[i] = ag->ab[i]; ++ *num_ab = *num_ab + 1; ++ } ++ ++ return 0; ++} ++ ++static int ath12k_core_hw_group_create(struct ath12k_base **ab_group, u8 num_ab) ++{ ++ int i, ret = 0; ++ struct ath12k_base *ab; ++ ++ for(i = 0; i < num_ab; i++) { ++ ab = ab_group[i]; + + mutex_lock(&ab->core_lock); + ret = ath12k_core_soc_create(ab); +@@ -1371,7 +1392,6 @@ static int ath12k_core_hw_group_create(s + mutex_unlock(&ab->core_lock); + } + +- return 0; + out: + return ret; + } +@@ -1379,6 +1399,9 @@ out: + int ath12k_core_init(struct ath12k_base *ab) + { + struct ath12k_hw_group *ag; ++ struct ath12k_base *ab_group[ATH12K_MAX_SOCS]; ++ bool is_ready = false; ++ u8 num_ab; + int ret; + + ret = ath12k_debugfs_soc_create(ab); +@@ -1392,7 +1415,7 @@ int ath12k_core_init(struct ath12k_base + ag = ath12k_core_get_hw_group(ab); + if (!ag) { + mutex_unlock(&ath12k_hw_lock); +- ath12k_warn(ab, "unable to get hw group\n"); ++ ath12k_err(ab, "unable to get hw group\n"); + goto err_debugfs; + } + mutex_unlock(&ath12k_hw_lock); +@@ -1402,19 +1425,30 @@ int ath12k_core_init(struct ath12k_base + ath12k_dbg(ab, ATH12K_DBG_BOOT, "num chips in group %d, num probed %d\n", + ag->num_chip, ag->num_probed); + +- if (ath12k_core_hw_group_create_ready(ag)) { +- ret = ath12k_core_hw_group_create(ag); ++ is_ready = ath12k_core_hw_group_create_ready(ag); ++ if (is_ready) { ++ ret = ath12k_core_get_chip(ag, ab_group, ATH12K_MAX_SOCS, &num_ab); + if (ret) { +- ath12k_warn(ab, "unable to create hw group\n"); +- goto err_hw_group; ++ mutex_unlock(&ag->mutex_lock); ++ ath12k_err(ab, "unable to get chip from hw group %d\n", ret); ++ goto err_debugfs; + } + } + + mutex_unlock(&ag->mutex_lock); + ++ if (is_ready) { ++ ret = ath12k_core_hw_group_create(ab_group, num_ab); ++ if (ret) { ++ ath12k_warn(ab, "unable to create hw group\n"); ++ goto err_hw_group; ++ } ++ } ++ + return 0; + + err_hw_group: ++ mutex_lock(&ag->mutex_lock); + __ath12k_core_put_hw_group(ab); + mutex_unlock(&ag->mutex_lock); + err_debugfs: +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -191,6 +191,8 @@ struct ath12k_he { + #define ATH12K_GROUP_MAX_RADIO (ATH12K_MAX_SOCS * MAX_RADIOS) + #define ATH12K_INVALID_GRP_ID 0xFF + #define ATH12K_INVALID_CHIP_ID 0xFF ++#define ATH12K_MAX_MLO_PEER 0x100 ++ + enum { + WMI_HOST_TP_SCALE_MAX = 0, + WMI_HOST_TP_SCALE_50 = 1, +@@ -943,6 +945,15 @@ struct ath12k_hw { + struct ath12k radio[0] __aligned(sizeof(void *)); + }; + ++struct ath12k_mlo_memory { ++ struct reserved_mem *rsv; ++ union { ++ void __iomem *ioaddr; ++ void *addr; ++ } v; ++ u32 size; ++}; ++ + /* Holds info on the group of SOCs that are registered as a single wiphy */ + struct ath12k_hw_group { + /* Keep this always as first member */ +@@ -955,6 +966,7 @@ struct ath12k_hw_group { + unsigned long dev_flags; + struct ath12k_hw *ah[ATH12K_GROUP_MAX_RADIO]; + struct ath12k_base *ab[ATH12K_MAX_SOCS]; ++ struct ath12k_mlo_memory mlo_mem; + struct mutex mutex_lock; + }; + +--- a/drivers/net/wireless/ath/ath12k/qmi.c ++++ b/drivers/net/wireless/ath/ath12k/qmi.c +@@ -12,6 +12,7 @@ + #include "coredump.h" + #include + #include ++#include + #include + #include + #include +@@ -573,7 +574,7 @@ static struct qmi_elem_info qmi_wlanfw_h + mlo_capable_valid), + }, + { +- .data_type = QMI_OPT_FLAG, ++ .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, +@@ -2755,28 +2756,106 @@ static int ath12k_qmi_send_qdss_config(s + return 0; + } + +-static void ath12k_host_cap_parse_mlo(struct qmi_wlanfw_host_cap_req_msg_v01 *req) ++static int ath12k_qmi_fill_mlo_host_caps(struct ath12k_base *ab, ++ struct qmi_wlanfw_host_cap_req_msg_v01 *req) + { +- req->mlo_capable_valid = 1; +- req->mlo_capable = 1; +- req->mlo_chip_id_valid = 1; +- req->mlo_chip_id = 0; +- req->mlo_group_id_valid = 1; ++ struct wlfw_host_mlo_chip_info_s_v01 *info; ++ struct ath12k_hw_group *ag = ab->ag; ++ struct ath12k_base *partner_ab; ++ int ret, i, j, link_id; ++ ++ mutex_lock(&ag->mutex_lock); ++ ++ if (ag->id == ATH12K_INVALID_GRP_ID) { ++ ath12k_dbg(ab, ATH12K_DBG_QMI, "Skip MLO cap send for chip id %d\n", ++ ab->chip_id); ++ ++ mutex_unlock(&ag->mutex_lock); ++ return 0; ++ } ++ ++ if (ab->chip_id == ATH12K_INVALID_CHIP_ID) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ req->mlo_capable = true; ++ req->mlo_capable_valid = true; ++ ++ req->mlo_chip_id = ab->chip_id; ++ req->mlo_chip_id_valid = true; ++ ++ req->mlo_group_id = ag->id; ++ req->mlo_group_id_valid = true; ++ ++ req->max_mlo_peer = ab->hw_params->max_mlo_peer; ++ req->max_mlo_peer_valid = true; ++ ++ req->mlo_num_chips = ag->num_chip; ++ req->mlo_num_chips_valid = true; ++ ++ link_id = 0; ++ for (i = 0; i < ag->num_chip; i++) { ++ info = &req->mlo_chip_info[i]; ++ partner_ab = ag->ab[i]; ++ ++ if (partner_ab->chip_id == ATH12K_INVALID_CHIP_ID) { ++ ret = -EINVAL; ++ goto chip_cleanup; ++ } ++ ++ info->chip_id = partner_ab->chip_id; ++ ++ /* TODO: Need to get the phy count */ ++ info->num_local_links = partner_ab->hw_params->num_local_link; ++ ++ ath12k_dbg(ab, ATH12K_DBG_QMI, "MLO chip id %d num_link %d\n", ++ partner_ab->chip_id, info->num_local_links); ++ ++ for (j = 0; j < info->num_local_links; j++) { ++ info->hw_link_id[j] = link_id; ++ info->valid_mlo_link_id[j] = true; ++ ++ ath12k_dbg(ab, ATH12K_DBG_QMI, "MLO link id %d\n", ++ info->hw_link_id[j]); ++ ++ link_id++; ++ } ++ } ++ ++ req->mlo_chip_info_valid = true; ++ ++ ath12k_dbg(ab, ATH12K_DBG_QMI, "MLO host cap chosen\n"); ++ ++ mutex_unlock(&ag->mutex_lock); ++ return 0; ++ ++chip_cleanup: ++ for (i = i - 1; i >= 0; i--) { ++ info = &req->mlo_chip_info[i]; ++ ++ memset(info, 0, sizeof(*info)); ++ } ++ ++ req->mlo_num_chips = 0; ++ req->mlo_num_chips_valid = 0; ++ ++ req->max_mlo_peer = 0; ++ req->max_mlo_peer_valid = 0; ++ + req->mlo_group_id = 0; +- req->max_mlo_peer_valid = 1; +- /* Max peer number generally won't change for the same device +- * but needs to be synced with host driver. +- */ +- req->max_mlo_peer = 32; +- req->mlo_num_chips_valid = 1; +- req->mlo_num_chips = 1; +- req->mlo_chip_info_valid = 1; +- req->mlo_chip_info[0].chip_id = 0; +- req->mlo_chip_info[0].num_local_links = 2; +- req->mlo_chip_info[0].hw_link_id[0] = 0; +- req->mlo_chip_info[0].hw_link_id[1] = 1; +- req->mlo_chip_info[0].valid_mlo_link_id[0] = 1; +- req->mlo_chip_info[0].valid_mlo_link_id[1] = 1; ++ req->mlo_group_id_valid = 0; ++ ++ req->mlo_chip_id = 0; ++ req->mlo_chip_id_valid = 0; ++ ++ req->mlo_capable = 0; ++ req->mlo_capable_valid = 0; ++ ++out: ++ mutex_unlock(&ag->mutex_lock); ++ ++ return ret; + } + + static int ath12k_qmi_host_cap_send(struct ath12k_base *ab) +@@ -2820,8 +2899,12 @@ static int ath12k_qmi_host_cap_send(stru + */ + req.nm_modem |= SLEEP_CLOCK_SELECT_INTERNAL_BIT; + req.nm_modem |= PLATFORM_CAP_PCIE_GLOBAL_RESET; ++ } + +- ath12k_host_cap_parse_mlo(&req); ++ ret = ath12k_qmi_fill_mlo_host_caps(ab, &req); ++ if (ret < 0) { ++ ath12k_warn(ab, "Failed to get MLO capability,err = %d\n", ret); ++ goto out; + } + + ret = qmi_txn_init(&ab->qmi.handle, &txn, +@@ -3007,6 +3090,29 @@ out: + return ret; + } + ++static void ath12k_qmi_free_mlo_mem_chunk(struct ath12k_base *ab, ++ struct target_mem_chunk *chunk) ++{ ++ struct ath12k_hw_group *ag = ab->ag; ++ ++ lockdep_assert_held(&ag->mutex_lock); ++ ++ if (!ag->mlo_mem.rsv) ++ return; ++ ++ if (ag->num_started) ++ goto skip_unmap; ++ ++ iounmap(ag->mlo_mem.v.ioaddr); ++ ag->mlo_mem.v.ioaddr = NULL; ++ ag->mlo_mem.rsv = NULL; ++ ag->mlo_mem.size = 0; ++ ++skip_unmap: ++ chunk->v.ioaddr = NULL; ++ chunk->paddr = NULL; ++} ++ + void ath12k_qmi_free_target_mem_chunk(struct ath12k_base *ab) + { + int i; +@@ -3015,8 +3121,13 @@ void ath12k_qmi_free_target_mem_chunk(st + if (ab->bus_params.fixed_mem_region) { + if (!ab->qmi.target_mem[i].v.ioaddr) + continue; +- iounmap(ab->qmi.target_mem[i].v.ioaddr); +- ab->qmi.target_mem[i].v.ioaddr = NULL; ++ ++ if (ab->qmi.target_mem[i].type == MLO_GLOBAL_MEM_REGION_TYPE) { ++ ath12k_qmi_free_mlo_mem_chunk(ab, &ab->qmi.target_mem[i]); ++ } else { ++ iounmap(ab->qmi.target_mem[i].v.ioaddr); ++ ab->qmi.target_mem[i].v.ioaddr = NULL; ++ } + } else { + if (!ab->qmi.target_mem[i].v.addr) + continue; +@@ -3078,6 +3189,79 @@ static int ath12k_qmi_alloc_target_mem_c + return 0; + } + ++static int ath12k_qmi_assign_mlo_mem_chunk(struct ath12k_base *ab, ++ struct target_mem_chunk *chunk) ++{ ++ struct ath12k_hw_group *ag = ab->ag; ++ struct device_node *mlo_global_mem_node; ++ struct reserved_mem *mlo_mem; ++ int ret = 0; ++ ++ mutex_lock(&ag->mutex_lock); ++ ++ if (ag->mlo_mem.rsv) { ++ if (ag->mlo_mem.size != chunk->size) { ++ ath12k_warn(ab, "MLO memory requested size %x is mismatch %x\n", ++ chunk->size, ag->mlo_mem.size); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ goto skip_remap; ++ } ++ ++ mlo_global_mem_node = of_find_node_by_name(NULL, "mlo_global_mem_0"); ++ if (!mlo_global_mem_node) { ++ ath12k_warn(ab, "qmi fail to get MLO global memory node\n"); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ mlo_mem = of_reserved_mem_lookup(mlo_global_mem_node); ++ if (!mlo_mem) { ++ of_node_put(mlo_global_mem_node); ++ ath12k_warn(ab, "qmi fail to get MLO memory resource node %px\n", ++ mlo_mem); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ of_node_put(mlo_global_mem_node); ++ ++ if (chunk->size > mlo_mem->size) { ++ ath12k_warn(ab, "MLO memory requested size %x is beyond %pa\n", ++ chunk->size, &mlo_mem->size); ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ ag->mlo_mem.v.ioaddr = ioremap(mlo_mem->base, chunk->size); ++ if (!ag->mlo_mem.v.ioaddr) { ++ ath12k_warn(ab, "failed to allocate MLO memory requested size %x\n", ++ chunk->size); ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ ag->mlo_mem.rsv = mlo_mem; ++ ag->mlo_mem.size = chunk->size; ++ ++ memset_io(ag->mlo_mem.v.ioaddr, 0, ag->mlo_mem.size); ++ ++skip_remap: ++ ath12k_dbg(ab, ATH12K_DBG_QMI, "MLO mem node start 0x%llx size %llu ioaddr %p req size %u\n", ++ (unsigned long long)ag->mlo_mem.rsv->base, ++ (unsigned long long)ag->mlo_mem.rsv->size, ++ ag->mlo_mem.v.ioaddr, ++ chunk->size); ++ ++ chunk->paddr = ag->mlo_mem.rsv->base; ++ chunk->v.ioaddr = ag->mlo_mem.v.ioaddr; ++out: ++ mutex_unlock(&ag->mutex_lock); ++ return ret; ++} ++ + static int ath12k_qmi_assign_target_mem_chunk(struct ath12k_base *ab) + { + struct device *dev = ab->dev; +@@ -3102,12 +3286,14 @@ static int ath12k_qmi_assign_target_mem_ + host_ddr_sz = (res.end - res.start) + 1; + + for (i = 0, idx = 0; i < ab->qmi.mem_seg_count; i++) { +- ab->qmi.target_mem[idx].paddr = res.start + sz; ++ if (ab->qmi.target_mem[i].type != MLO_GLOBAL_MEM_REGION_TYPE) { ++ ab->qmi.target_mem[idx].paddr = res.start + sz; + +- if (ab->qmi.target_mem[i].size > (host_ddr_sz - sz)) { +- ath12k_warn(ab, "No fixed mem to assign for type %d\n", +- ab->qmi.target_mem[i].type); +- return -EINVAL; ++ if (ab->qmi.target_mem[i].size > (host_ddr_sz - sz)) { ++ ath12k_warn(ab, "No fixed mem to assign for type %d\n", ++ ab->qmi.target_mem[i].type); ++ return -EINVAL; ++ } + } + + switch (ab->qmi.target_mem[i].type) { +@@ -3169,12 +3355,26 @@ static int ath12k_qmi_assign_target_mem_ + sz += ab->qmi.target_mem[i].size; + idx++; + break; ++ case MLO_GLOBAL_MEM_REGION_TYPE: ++ ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size; + ++ ret = ath12k_qmi_assign_mlo_mem_chunk(ab, &ab->qmi.target_mem[idx]); ++ if (ret) { ++ ath12k_warn(ab, "qmi failed to assign MLO target memory: %d\n", ++ ret); ++ return ret; ++ } ++ ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type; ++ idx++; ++ break; + default: + ath12k_warn(ab, "qmi ignore invalid mem req type %d\n", + ab->qmi.target_mem[i].type); + break; + } ++ ++ ath12k_dbg(ab, ATH12K_DBG_QMI, "qmi target mem seg idx %d i %d type %d size %d\n", ++ idx, i, ab->qmi.target_mem[idx - 1].type, ab->qmi.target_mem[idx - 1].size); + } + ab->host_ddr_fixed_mem_off = sz; + ab->qmi.mem_seg_count = idx; +@@ -4231,6 +4431,7 @@ static void ath12k_qmi_msg_mem_request_c + for (i = 0; i < qmi->mem_seg_count ; i++) { + ab->qmi.target_mem[i].type = msg->mem_seg[i].type; + ab->qmi.target_mem[i].size = msg->mem_seg[i].size; ++ + ath12k_dbg(ab, ATH12K_DBG_QMI, "qmi mem seg type %d size %d\n", + msg->mem_seg[i].type, msg->mem_seg[i].size); + } +@@ -4545,6 +4746,7 @@ static void ath12k_qmi_driver_event_work + int ret; + + spin_lock(&qmi->event_lock); ++ + while (!list_empty(&qmi->event_list)) { + event = list_first_entry(&qmi->event_list, + struct ath12k_qmi_driver_event, list); +--- a/drivers/net/wireless/ath/ath12k/qmi.h ++++ b/drivers/net/wireless/ath/ath12k/qmi.h +@@ -222,7 +222,7 @@ struct qmi_wlanfw_qdss_trace_mode_resp_m + struct qmi_response_type_v01 resp; + }; + +-#define QMI_WLANFW_HOST_CAP_REQ_MSG_V01_MAX_LEN 261 ++#define QMI_WLANFW_HOST_CAP_REQ_MSG_V01_MAX_LEN 351 + + struct qmi_wlanfw_m3_dump_upload_done_req_msg_v01 { + u32 pdev_id; +@@ -251,6 +251,7 @@ enum ath12k_qmi_target_mem { + BDF_MEM_REGION_TYPE = 0x2, + M3_DUMP_REGION_TYPE = 0x3, + CALDB_MEM_REGION_TYPE = 0x4, ++ MLO_GLOBAL_MEM_REGION_TYPE = 0x8, + PAGEABLE_MEM_REGION_TYPE = 0x9, + }; + +@@ -400,6 +401,11 @@ enum qmi_wlanfw_mem_type_enum_v01 { + QMI_WLANFW_MEM_M3_V01 = 3, + QMI_WLANFW_MEM_CAL_V01 = 4, + QMI_WLANFW_MEM_DPD_V01 = 5, ++ QMI_WLANFW_MEM_QDSS_V01 = 6, ++ QMI_WLANFW_MEM_HANG_DATA_V01 = 7, ++ QMI_WLANFW_MEM_MLO_GLOBAL_V01 = 8, ++ QMI_WLANFW_MEM_PAGEABLE_V01 = 9, ++ QMI_WLANFW_MEM_AFC_V01 = 10, + WLANFW_MEM_TYPE_ENUM_MAX_VAL_V01 = INT_MAX, + }; + +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -2329,6 +2329,23 @@ enum { + WMI_HOST_VDEV_FLAGS_SCAN_MODE_VAP = 0x00000010, + }; + ++/* HW mode MLO capability flags ++ * WMI_HOST_MLO_CAP_FLAG_NONE: Do not support MLO for the specific HW mode ++ * WMI_HOST_MLO_CAP_FLAG_NON_STR_IN_DBS: Support STR MLO when DBS for the specific HW mode ++ * WMI_HOST_MLO_CAP_FLAG_STR_IN_DBS: Support Non-STR MLO when DBS for the specific HW mode ++ * WMI_HOST_MLO_CAP_FLAG_NON_STR_IN_SBS: Support STR MLO when SBS for the specific HW mode ++ * WMI_HOST_MLO_CAP_FLAG_STR_IN_SBS: Support Non-STR MLO when SBS for the specific HW mode ++ * WMI_HOST_MLO_CAP_FLAG_STR: Support STR for the specific HW mode ++ * WMI_HOST_MLO_CAP_FLAG_EMLSR: Support eMLSR mode ++ */ ++#define WMI_HOST_MLO_CAP_FLAG_NONE 0x0 ++#define WMI_HOST_MLO_CAP_FLAG_NON_STR_IN_DBS 0x1 ++#define WMI_HOST_MLO_CAP_FLAG_STR_IN_DBS 0x2 ++#define WMI_HOST_MLO_CAP_FLAG_NON_STR_IN_SBS 0x4 ++#define WMI_HOST_MLO_CAP_FLAG_STR_IN_SBS 0x8 ++#define WMI_HOST_MLO_CAP_FLAG_STR 0x10 ++#define WMI_HOST_MLO_CAP_FLAG_EMLSR 0x20 ++ + /* + * 0 – index indicated EHT-MCS map for 20Mhz only sta (4 bytes valid) + * 1 – index for <= 80MHz bw (only 3 bytes are valid and other is reserved) +@@ -2569,11 +2586,14 @@ struct wmi_soc_mac_phy_hw_mode_caps { + u32 num_chainmask_tables; + } __packed; + ++#define WMI_HW_MODE_INFO0_CONFIG_TYPE GENMASK(26, 0) ++#define WMI_HW_MODE_INFO0_MLO_CAP_FLAG GENMASK(31, 27) ++ + struct wmi_hw_mode_capabilities { + __le32 tlv_header; + u32 hw_mode_id; + u32 phy_id_map; +- u32 hw_mode_config_type; ++ u32 hw_mode_info0; + } __packed; + + #define WMI_MAX_HECAP_PHY_SIZE (3) +@@ -2586,7 +2606,8 @@ struct wmi_hw_mode_capabilities { + + struct wmi_mac_phy_capabilities { + u32 hw_mode_id; +- u32 pdev_id; ++ u16 pdev_id; ++ u16 hw_link_id; + u32 phy_id; + u32 supported_flags; + u32 supported_bands; +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -1016,6 +1016,8 @@ static const struct ath12k_hw_params ath + .credit_flow = false, + .wakeup_mhi = false, + .alloc_cacheable_memory = true, ++ .max_mlo_peer = ATH12K_MAX_MLO_PEER, ++ .num_local_link = 1, + }, + { + .name = "wcn7850 hw2.0", +@@ -1082,6 +1084,8 @@ static const struct ath12k_hw_params ath + .credit_flow = false, + .wakeup_mhi = false, + .alloc_cacheable_memory = false, ++ .max_mlo_peer = 32, ++ .num_local_link = 2, + }, + { + .name = "qcn9274 hw2.0", +@@ -1148,6 +1152,8 @@ static const struct ath12k_hw_params ath + .credit_flow = false, + .wakeup_mhi = false, + .alloc_cacheable_memory = true, ++ .max_mlo_peer = ATH12K_MAX_MLO_PEER, ++ .num_local_link = 1, + }, + }; + +--- a/drivers/net/wireless/ath/ath12k/hw.h ++++ b/drivers/net/wireless/ath/ath12k/hw.h +@@ -203,6 +203,8 @@ struct ath12k_hw_params { + bool credit_flow; + bool wakeup_mhi; + bool alloc_cacheable_memory; ++ u16 max_mlo_peer; ++ u8 num_local_link; + }; + + /* BRINGUP: move to dp.h */ diff --git a/feeds/ipq95xx/mac80211/patches/qca/670-02-ath12k-Add-mlo-wmi-setup-apis.patch b/feeds/ipq95xx/mac80211/patches/qca/670-02-ath12k-Add-mlo-wmi-setup-apis.patch new file mode 100644 index 000000000..720f24c11 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/670-02-ath12k-Add-mlo-wmi-setup-apis.patch @@ -0,0 +1,373 @@ +From 31ba379043c3bde8f69d1e898dcd0d54b669e3c5 Mon Sep 17 00:00:00 2001 +From: Bhagavathi Perumal S +Date: Tue, 14 Sep 2021 13:06:02 +0530 +Subject: [PATCH 2/4] ath12k: Add mlo wmi setup apis + +Added WMI helper function for the MLO setup/teardown command and event. +Add appropriate WMI tag, command id and event id to parse the event and +send request. + +Signed-off-by: Bhagavathi Perumal S +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/core.c | 8 -- + drivers/net/wireless/ath/ath12k/core.h | 3 +- + drivers/net/wireless/ath/ath12k/wmi.c | 170 ++++++++++++++++++++++++- + drivers/net/wireless/ath/ath12k/wmi.h | 66 +++++++++- + 4 files changed, 229 insertions(+), 18 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -853,7 +853,8 @@ struct mlo_timestamp { + + struct ath12k_pdev { + struct ath12k *ar; +- u32 pdev_id; ++ u16 pdev_id; ++ u16 hw_link_id; + struct ath12k_pdev_cap cap; + u8 mac_addr[ETH_ALEN]; + struct mlo_timestamp timestamp; +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -485,6 +485,8 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(st + mac_phy_caps = wmi_mac_phy_caps + phy_idx; + + pdev->pdev_id = mac_phy_caps->pdev_id; ++ pdev->hw_link_id = mac_phy_caps->hw_link_id; ++ + pdev_cap->supported_bands |= mac_phy_caps->supported_bands; + pdev_cap->ampdu_density = mac_phy_caps->ampdu_density; + +@@ -9026,6 +9028,66 @@ exit: + kfree(tb); + } + ++static void ath12k_wmi_event_mlo_setup_complete(struct ath12k_base *ab, ++ struct sk_buff *skb) ++{ ++ const void **tb; ++ const struct wmi_mlo_setup_complete_event_fixed_param *ev; ++ int ret; ++ ++ tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); ++ if (IS_ERR(tb)) { ++ ret = PTR_ERR(tb); ++ ath12k_warn(ab, ++ "failed to parse mlo setup complete event tlv %d\n", ++ ret); ++ return; ++ } ++ ++ ev = tb[WMI_TAG_MLO_SETUP_COMPLETE_EVENT]; ++ if (!ev) { ++ ath12k_warn(ab, "failed to fetch mlo setup complete event\n"); ++ kfree(tb); ++ return; ++ } ++ ++ if (ev->status) ++ ath12k_warn(ab, "mlo setup, pdev id %u, err %u\n", ++ ev->pdev_id, ev->status); ++ ++ kfree(tb); ++} ++ ++static void ath12k_wmi_event_teardown_complete(struct ath12k_base *ab, ++ struct sk_buff *skb) ++{ ++ const void **tb; ++ const struct wmi_mlo_teardown_complete_fixed_param *ev; ++ int ret; ++ ++ tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); ++ if (IS_ERR(tb)) { ++ ret = PTR_ERR(tb); ++ ath12k_warn(ab, ++ "failed to parse teardown complete event tlv %d\n", ++ ret); ++ return; ++ } ++ ++ ev = tb[WMI_TAG_MLO_TEARDOWN_COMPLETE]; ++ if (!ev) { ++ ath12k_warn(ab, "failed to fetch teardown complete event\n"); ++ kfree(tb); ++ return; ++ } ++ ++ if (ev->status) ++ ath12k_warn(ab, "mlo teardown, pdev id %u, err %u\n", ++ ev->pdev_id, ev->status); ++ ++ kfree(tb); ++} ++ + static void ath12k_wmi_tlv_op_rx(struct ath12k_base *ab, struct sk_buff *skb) + { + struct wmi_cmd_hdr *cmd_hdr; +@@ -9160,6 +9222,12 @@ static void ath12k_wmi_tlv_op_rx(struct + case WMI_STATS_CTRL_PATH_EVENTID: + ath12k_process_tpc_stats(ab, skb); + break; ++ case WMI_MLO_SETUP_COMPLETE_EVENTID: ++ ath12k_wmi_event_mlo_setup_complete(ab, skb); ++ break; ++ case WMI_MLO_TEARDOWN_COMPLETE_EVENTID: ++ ath12k_wmi_event_teardown_complete(ab, skb); ++ break; + /* TODO: Add remaining events */ + default: + ath12k_dbg(ab, ATH12K_DBG_WMI, "Unknown eventid: 0x%x\n", id); +@@ -9516,3 +9584,100 @@ int ath12k_wmi_pdev_ap_ps_cmd_send(struc + + return ret; + } ++ ++int ath12k_wmi_mlo_setup(struct ath12k *ar, ++ struct wmi_mlo_setup_params *mlo_params) ++{ ++ struct ath12k_pdev_wmi *wmi = ar->wmi; ++ struct wmi_mlo_setup_cmd_fixed_param *cmd; ++ struct sk_buff *skb; ++ struct wmi_tlv *tlv; ++ u32 *plinks; ++ u32 num_links; ++ int i, ret, len; ++ ++ num_links = mlo_params->num_partner_links; ++ ++ len = sizeof(*cmd) + TLV_HDR_SIZE + (num_links * sizeof(u32)); ++ skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len); ++ if (!skb) ++ return -ENOMEM; ++ ++ cmd = (struct wmi_mlo_setup_cmd_fixed_param *)skb->data; ++ cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_MLO_SETUP_CMD) | ++ FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); ++ cmd->mld_group_id = mlo_params->group_id; ++ cmd->pdev_id = ar->pdev->pdev_id; ++ ++ tlv = (struct wmi_tlv *)(skb->data + sizeof(*cmd)); ++ tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_UINT32) | ++ FIELD_PREP(WMI_TLV_LEN, num_links); ++ ++ plinks = (u32 *)tlv->value; ++ for (i = 0; i < num_links; i++) ++ plinks[i] = mlo_params->partner_link_id[i]; ++ ++ ret = ath12k_wmi_cmd_send(wmi, skb, WMI_MLO_SETUP_CMDID); ++ if (ret) { ++ ath12k_warn(ar->ab, ++ "failed to submit WMI_MLO_SETUP_CMDID cmd\n"); ++ dev_kfree_skb(skb); ++ } ++ ++ return ret; ++} ++ ++int ath12k_wmi_mlo_ready(struct ath12k *ar) ++{ ++ struct ath12k_pdev_wmi *wmi = ar->wmi; ++ struct wmi_mlo_ready_cmd_fixed_param *cmd; ++ struct sk_buff *skb; ++ int ret, len; ++ ++ len = sizeof(*cmd); ++ skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len); ++ if (!skb) ++ return -ENOMEM; ++ ++ cmd = (struct wmi_mlo_ready_cmd_fixed_param *)skb->data; ++ cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_MLO_READY_CMD) | ++ FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); ++ cmd->pdev_id = ar->pdev->pdev_id; ++ ++ ret = ath12k_wmi_cmd_send(wmi, skb, WMI_MLO_READY_CMDID); ++ if (ret) { ++ ath12k_warn(ar->ab, ++ "failed to submit WMI_MLO_READY_CMDID cmd\n"); ++ dev_kfree_skb(skb); ++ } ++ ++ return ret; ++} ++ ++int ath12k_wmi_mlo_teardown(struct ath12k *ar) ++{ ++ struct ath12k_pdev_wmi *wmi = ar->wmi; ++ struct wmi_mlo_teardown_fixed_param *cmd; ++ struct sk_buff *skb; ++ int ret, len; ++ ++ len = sizeof(*cmd); ++ skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len); ++ if (!skb) ++ return -ENOMEM; ++ ++ cmd = (struct wmi_mlo_teardown_fixed_param *)skb->data; ++ cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_MLO_TEARDOWN_CMD) | ++ FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); ++ cmd->pdev_id = ar->pdev->pdev_id; ++ cmd->reason_code = WMI_MLO_TEARDOWN_SSR_REASON; ++ ++ ret = ath12k_wmi_cmd_send(wmi, skb, WMI_MLO_TEARDOWN_CMDID); ++ if (ret) { ++ ath12k_warn(ar->ab, ++ "failed to submit WMI MLO teardown cmd\n"); ++ dev_kfree_skb(skb); ++ } ++ ++ return ret; ++} +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -202,6 +202,7 @@ enum wmi_cmd_group { + WMI_GRP_TWT = 0x3e, + WMI_GRP_MOTION_DET = 0x3f, + WMI_GRP_SPATIAL_REUSE = 0x40, ++ WMI_GRP_MLO = 0x48, + }; + + #define WMI_CMD_GRP(grp_id) (((grp_id) << 12) | 0x1) +@@ -626,6 +627,11 @@ enum wmi_tlv_cmd_id { + WMI_PDEV_OBSS_PD_SPATIAL_REUSE_CMDID = + WMI_TLV_CMD(WMI_GRP_SPATIAL_REUSE), + WMI_PDEV_OBSS_PD_SPATIAL_REUSE_SET_DEF_OBSS_THRESH_CMDID, ++ WMI_MLO_LINK_SET_ACTIVE_CMDID = WMI_TLV_CMD(WMI_GRP_MLO), ++ WMI_MLO_SETUP_CMDID, ++ WMI_MLO_READY_CMDID, ++ WMI_MLO_TEARDOWN_CMDID, ++ WMI_MLO_PEER_TID_TO_LINK_MAP_CMDID, + }; + + enum wmi_tlv_event_id { +@@ -849,6 +855,9 @@ enum wmi_tlv_event_id { + WMI_TWT_DEL_DIALOG_EVENTID, + WMI_TWT_PAUSE_DIALOG_EVENTID, + WMI_TWT_RESUME_DIALOG_EVENTID, ++ WMI_MLO_LINK_SET_ACTIVE_RESP_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_MLO), ++ WMI_MLO_SETUP_COMPLETE_EVENTID, ++ WMI_MLO_TEARDOWN_COMPLETE_EVENTID, + }; + + enum wmi_tlv_pdev_param { +@@ -1923,6 +1932,14 @@ enum wmi_tlv_tag { + WMI_TAG_VDEV_CH_POWER_INFO, + WMI_TAG_EHT_RATE_SET = 0x3C4, + WMI_TAG_DCS_AWGN_INT_TYPE = 0x3C5, ++ WMI_TAG_MLO_TX_SEND_PARAMS, ++ WMI_TAG_MLO_PARTNER_LINK_PARAMS, ++ WMI_TAG_MLO_PARTNER_LINK_PARAMS_PEER_ASSOC, ++ WMI_TAG_MLO_SETUP_CMD, ++ WMI_TAG_MLO_SETUP_COMPLETE_EVENT, ++ WMI_TAG_MLO_READY_CMD, ++ WMI_TAG_MLO_TEARDOWN_CMD, ++ WMI_TAG_MLO_TEARDOWN_COMPLETE, + WMI_TAG_PDEV_PKTLOG_DECODE_INFO = 0x414, + WMI_TAG_TPC_STATS_GET_CMD = 0x38B, + WMI_TAG_TPC_STATS_EVENT_FIXED_PARAM, +@@ -2278,6 +2295,7 @@ struct ath12k_ppe_threshold { + u32 ru_bit_mask; + u32 ppet16_ppet8_ru3_ru0[PSOC_HOST_MAX_NUM_SS]; + }; ++ + struct ath12k_service_ext_param { + u32 default_conc_scan_config_bits; + u32 default_fw_config_bits; +@@ -2699,6 +2717,25 @@ enum wmi_eht_mcs_support { + WMI_EHT_MCS_NOT_SUPPORTED = 3, + }; + ++#define EML_INFO_EMLSR_SUPPORT BIT(0) ++#define EML_INFO_EMLSR_PADDING_DELAY GENMASK(3, 1) ++#define EML_INFO_EMLSR_TRANSITION_DELAY GENMASK(6, 4) ++#define EML_INFO_EMLMR_SUPPORT BIT(7) ++#define EML_INFO_EMLMR_PADDING_DELAY GENMASK(10, 8) ++#define EML_INFO_TRANSITION_TIMEOUT GENMASK(14, 11) ++ ++enum wmi_mld_cap_tid_to_link_map { ++ WMI_MLD_MAP_TID_TO_LINK_NONE, ++ WMI_MLD_MAP_EACH_TID_TO_SAME_OR_DIFF_LINK_SET, ++ WMI_MLD_MAP_ALL_TID_TO_SAME_LINK_SET, ++}; ++ ++#define MLD_INFO_MAX_SIMULTANEOUS_LINK GENMASK(3, 0) ++#define MLD_INFO_SRS_SUPPORT BIT(4) ++#define MLD_INFO_TID_TO_LINK_MAP_SUPPORT GENMASK(6, 5) ++#define MLD_INFO_FREQ_SEPARATION_STR GENMASK(11, 7) ++#define MLD_INFO_AAR_SUPPORT BIT(12) ++ + struct wmi_mac_phy_caps_ext { + u32 hw_mode_id; + union { +@@ -2720,6 +2757,8 @@ struct wmi_mac_phy_caps_ext { + u32 eht_cap_info_internal; + u32 eht_supp_mcs_ext_2G[WMI_MAX_EHT_SUPP_MCS_2G_SIZE]; + u32 eht_supp_mcs_ext_5G[WMI_MAX_EHT_SUPP_MCS_5G_SIZE]; ++ u32 eml_info; ++ u32 mld_info; + } __packed; + + /* 2 word representation of MAC addr */ +@@ -5975,6 +6014,7 @@ struct wmi_dbglog_config_cmd_fixed_param + + #define MAX_RADIOS 3 + ++#define WMI_MLO_CMD_TIMEOUT_HZ (5 * HZ) + #define WMI_SERVICE_READY_TIMEOUT_HZ (5 * HZ) + #define WMI_SEND_TIMEOUT_HZ (3 * HZ) + +@@ -6162,6 +6202,43 @@ struct wmi_wow_ev_arg { + u32 data_len; + }; + ++struct wmi_mlo_setup_cmd_fixed_param { ++ u32 tlv_header; ++ u32 mld_group_id; ++ u32 pdev_id; ++} __packed; ++ ++struct wmi_mlo_setup_params { ++ u32 group_id; ++ u8 num_partner_links; ++ u8 *partner_link_id; ++}; ++ ++struct wmi_mlo_ready_cmd_fixed_param { ++ u32 tlv_header; ++ u32 pdev_id; ++} __packed; ++ ++enum wmi_mlo_tear_down_reason_code_type { ++ WMI_MLO_TEARDOWN_SSR_REASON, ++}; ++ ++struct wmi_mlo_teardown_fixed_param { ++ u32 tlv_header; ++ u32 pdev_id; ++ u32 reason_code; ++} __packed; ++ ++struct wmi_mlo_setup_complete_event_fixed_param { ++ u32 pdev_id; ++ u32 status; ++} __packed; ++ ++struct wmi_mlo_teardown_complete_fixed_param { ++ u32 pdev_id; ++ u32 status; ++} __packed; ++ + #define ATH12K_FW_STATS_BUF_SIZE (1024 * 1024) + + void ath12k_wmi_init_qcn9274(struct ath12k_base *ab, +@@ -6326,4 +6403,8 @@ int ath12k_wmi_send_vdev_set_tpc_power(s + int ath12k_wmi_pdev_m3_dump_enable(struct ath12k *ar, u32 enable); + int ath12k_wmi_pdev_get_tpc_table_cmdid(struct ath12k *ar); + void ath12k_wmi_free_tpc_stats_mem(struct ath12k *ar); ++int ath12k_wmi_mlo_setup(struct ath12k *ar, ++ struct wmi_mlo_setup_params *mlo_params); ++int ath12k_wmi_mlo_ready(struct ath12k *ar); ++int ath12k_wmi_mlo_teardown(struct ath12k *ar); + #endif diff --git a/feeds/ipq95xx/mac80211/patches/qca/670-03-ath12k-Setup-MLO-link.patch b/feeds/ipq95xx/mac80211/patches/qca/670-03-ath12k-Setup-MLO-link.patch new file mode 100644 index 000000000..08736552e --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/670-03-ath12k-Setup-MLO-link.patch @@ -0,0 +1,496 @@ +From 3bf3dd9b2835ecec877ed43e794cc66f27f6e6fe Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Sat, 30 Jul 2022 20:57:20 +0530 +Subject: [PATCH 3/5] ath12k: Setup MLO link + +Add MLO setup/teardown procedure in the core group start/stop +procedure. Added MAC procedure to handle the hw related request. +WMI MLO setup comprise the WMI (setup & ready) procedures. + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/core.h | 10 ++- + drivers/net/wireless/ath/ath12k/mac.c | 102 ++++++++++++++++++++++++- + drivers/net/wireless/ath/ath12k/wmi.c | 35 ++++++++- + drivers/net/wireless/ath/ath12k/wmi.h | 22 ++++++ + 4 files changed, 164 insertions(+), 5 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -803,6 +803,9 @@ struct ath12k { + struct wmi_tpc_stats_event *tpc_stats; + struct completion tpc_complete; + bool tpc_request; ++ ++ struct completion mlo_setup_done; ++ u32 mlo_setup_status; + }; + + struct ath12k_band_cap { +@@ -954,7 +957,9 @@ struct ath12k_mlo_memory { + u32 size; + }; + +-/* Holds info on the group of SOCs that are registered as a single wiphy */ ++/* Holds info on the group of SOCs that are registered as a single wiphy ++ * or single SOC where each radio registered as separate wiphy in non-MLO ++ */ + struct ath12k_hw_group { + /* Keep this always as first member */ + struct list_head list; +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -6966,6 +6966,149 @@ static int ath12k_mac_config_mon_status_ + return ret; + } + ++static int __ath12k_mac_mlo_ready(struct ath12k *ar) ++{ ++ int ret; ++ ++ ret = ath12k_wmi_mlo_ready(ar); ++ if (ret) { ++ ath12k_err(ar->ab, "MLO ready failed for pdev_idx %d: %d\n", ++ ar->pdev_idx, ret); ++ ++ return ret; ++ } ++ ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "MLO ready done for pdev_idx %d\n", ++ ar->pdev_idx); ++ ++ return 0; ++} ++ ++int ath12k_mac_mlo_ready(struct ath12k_hw *ah) ++{ ++ struct ath12k *ar; ++ int ret; ++ int i; ++ ++ ar = ah->radio; ++ for (i = 0; i < ah->num_radio; i++) { ++ ret = __ath12k_mac_mlo_ready(ar); ++ if (ret) ++ goto out; ++ ++ ar++; ++ } ++ ++out: ++ return ret; ++ ++} ++ ++static int __ath12k_mac_mlo_setup(struct ath12k *ar) ++{ ++ struct ath12k_base *partner_ab, *ab = ar->ab; ++ struct ath12k_hw_group *ag = ab->ag; ++ struct ath12k_pdev *pdev; ++ struct wmi_mlo_setup_params mlo_params = { 0 }; ++ u8 num_link = 0, partner_link_id[ATH12K_GROUP_MAX_RADIO] = { 0 }; ++ int chip_idx, pdev_idx, ret; ++ unsigned long time_left; ++ ++ lockdep_assert_held(&ag->mutex_lock); ++ ++ reinit_completion(&ar->mlo_setup_done); ++ for (chip_idx = 0; chip_idx < ag->num_chip; chip_idx++) { ++ partner_ab = ag->ab[chip_idx]; ++ ++ for (pdev_idx = 0; pdev_idx < partner_ab->num_radios; pdev_idx++) { ++ pdev = &partner_ab->pdevs[pdev_idx]; ++ ++ /* Avoid the self link */ ++ if (ar == pdev->ar) ++ continue; ++ ++ partner_link_id[num_link] = pdev->hw_link_id; ++ num_link++; ++ ++ ath12k_dbg(ab, ATH12K_DBG_MAC, ++ "chip_id %d pdev_idx %d link id %d num_link %d\n", ++ chip_idx, pdev_idx, pdev->hw_link_id, num_link); ++ } ++ } ++ ++ mlo_params.group_id = ag->id; ++ mlo_params.partner_link_id = partner_link_id; ++ mlo_params.num_partner_links = num_link; ++ ar->mlo_setup_status = 0; ++ ++ ath12k_dbg(ab, ATH12K_DBG_MAC, "grp id %d num_link %d\n", ag->id, num_link); ++ ++ ret = ath12k_wmi_mlo_setup(ar, &mlo_params); ++ if (ret) { ++ ath12k_err(ab, "failed to setup MLO for pdev_idx %d: %d\n", ++ ar->pdev_idx, ret); ++ return ret; ++ } ++ ++ time_left = wait_for_completion_timeout(&ar->mlo_setup_done, ++ WMI_MLO_CMD_TIMEOUT_HZ); ++ if (!time_left || ar->mlo_setup_status) ++ return ar->mlo_setup_status ? : -ETIMEDOUT; ++ ++ ath12k_dbg(ab, ATH12K_DBG_MAC, "MLO setup done for pdev_idx %d\n", ++ ar->pdev_idx); ++ return 0; ++} ++ ++static int __ath12k_mac_mlo_teardown(struct ath12k *ar) ++{ ++ struct ath12k_base *ab = ar->ab; ++ int ret; ++ ++ ret = ath12k_wmi_mlo_teardown(ar); ++ if (ret) { ++ ath12k_err(ab, "failed to teardown MLO for pdev_idx %d: %d\n", ++ ar->pdev_idx, ret); ++ return ret; ++ } ++ ++ ath12k_dbg(ab, ATH12K_DBG_MAC, "MLO teardown for pdev_idx %d\n", ++ ar->pdev_idx); ++ return 0; ++} ++ ++int ath12k_mac_mlo_setup(struct ath12k_hw *ah) ++{ ++ struct ath12k *ar; ++ int ret, fbret; ++ int i; ++ ++ ar = ah->radio; ++ for (i = 0; i < ah->num_radio; i++) { ++ ret = __ath12k_mac_mlo_setup(ar); ++ if (ret) { ++ ath12k_err(ar->ab, "failed to setup mlo %d\n", ret); ++ goto err_setup; ++ } ++ ++ ar++; ++ } ++ ++ return 0; ++ ++err_setup: ++ ar = ah->radio; ++ for (i = i - 1; i >= 0; i--) { ++ fbret = __ath12k_mac_mlo_teardown(ar); ++ if (fbret) ++ ath12k_err(ar->ab, "MLO teardown failed %d in setup cleanup\n", ++ fbret); ++ ++ ar++; ++ } ++ return ret; ++} ++ + static int ath12k_mac_radio_start(struct ath12k *ar) + { + struct ath12k_base *ab = ar->ab; +@@ -7091,8 +7234,28 @@ err: + return ret; + } + ++int ath12k_mac_mlo_teardown(struct ath12k_hw *ah) ++{ ++ struct ath12k *ar; ++ int ret; ++ int i; ++ ++ ar = ah->radio; ++ for (i = 0; i < ah->num_radio; i++) { ++ ret = __ath12k_mac_mlo_teardown(ar); ++ if (ret) ++ goto out; ++ ++ ar++; ++ } ++ ++out: ++ return ret; ++} ++ + static void ath12k_mac_radio_stop(struct ath12k *ar) + { ++ struct ath12k_base *ab = ar->ab; + struct htt_ppdu_stats_info *ppdu_stats, *tmp; + int ret; + +@@ -7101,7 +7264,7 @@ static void ath12k_mac_radio_stop(struct + mutex_lock(&ar->conf_mutex); + ret = ath12k_mac_config_mon_status_default(ar, false); + if (ret && (ret != -ENOTSUPP)) +- ath12k_err(ar->ab, "failed to clear rx_filter for monitor status ring: (%d)\n", ++ ath12k_err(ab, "failed to clear rx_filter for monitor status ring: (%d)\n", + ret); + + clear_bit(ATH12K_CAC_RUNNING, &ar->dev_flags); +@@ -7118,7 +7281,7 @@ static void ath12k_mac_radio_stop(struct + } + spin_unlock_bh(&ar->data_lock); + +- rcu_assign_pointer(ar->ab->pdevs_active[ar->pdev_idx], NULL); ++ rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], NULL); + + synchronize_rcu(); + +@@ -7156,6 +7319,7 @@ static int ath12k_mac_op_start(struct ie + + mutex_unlock(&ah->conf_mutex); + return 0; ++ + err: + ar = ah->radio; + for (i = i - 1; i >= 0; i--) { +@@ -7177,9 +7341,9 @@ static void ath12k_mac_op_stop(struct ie + + /* TODO Maintain state for ah? */ + +- for (i = 0; i < ah->num_radio; i++) { ++ for (i = ah->num_radio - 1, ar = ar + (ah->num_radio - 1); i >= 0; i--) { + ath12k_mac_radio_stop(ar); +- ar++; ++ ar--; + } + + mutex_unlock(&ah->conf_mutex); +@@ -9811,6 +9975,7 @@ ath12k_mac_set_fixed_rate_GI_LTF(struct + ltf, ret); + return ret; + } ++ + return 0; + } + +@@ -11054,7 +11219,7 @@ void ath12k_mac_unregister(struct ath12k + struct ath12k_hw *ah = ag->ah; + int i; + +- for (i = 0; i < ag->num_hw; i++) { ++ for (i = ag->num_hw - 1; i >= 0; i--) { + ah = ag->ah[i]; + if (!ah) + continue; +@@ -11415,6 +11580,7 @@ static int ath12k_mac_setup(struct ath12 + init_completion(&ar->scan.started); + init_completion(&ar->scan.completed); + init_completion(&ar->thermal.wmi_sync); ++ init_completion(&ar->mlo_setup_done); + + INIT_DELAYED_WORK(&ar->scan.timeout, ath12k_scan_timeout_work); + INIT_WORK(&ar->regd_update_work, ath12k_regd_update_work); +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -9033,7 +9033,9 @@ static void ath12k_wmi_event_mlo_setup_c + { + const void **tb; + const struct wmi_mlo_setup_complete_event_fixed_param *ev; +- int ret; ++ struct ath12k *ar = NULL; ++ struct ath12k_pdev *pdev; ++ int ret, i; + + tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); + if (IS_ERR(tb)) { +@@ -9052,9 +9054,31 @@ static void ath12k_wmi_event_mlo_setup_c + } + + if (ev->status) +- ath12k_warn(ab, "mlo setup, pdev id %u, err %u\n", ++ ath12k_warn(ab, "mlo setup, pdev id %u, status %u\n", ++ ev->pdev_id, ev->status); ++ ++ if (ev->pdev_id > ab->num_radios) ++ goto skip_lookup; ++ ++ for (i = 0; i < ab->num_radios; i++) { ++ pdev = &ab->pdevs[i]; ++ if (pdev && pdev->pdev_id == ev->pdev_id) { ++ ar = pdev->ar; ++ break; ++ } ++ } ++ ++skip_lookup: ++ if (!ar) { ++ ath12k_warn(ab, "invalid pdev_id %d status %u in setup complete event\n", + ev->pdev_id, ev->status); ++ goto out; ++ } ++ ++ ar->mlo_setup_status = ev->status; ++ complete(&ar->mlo_setup_done); + ++out: + kfree(tb); + } + +@@ -9082,7 +9106,7 @@ static void ath12k_wmi_event_teardown_co + } + + if (ev->status) +- ath12k_warn(ab, "mlo teardown, pdev id %u, err %u\n", ++ ath12k_warn(ab, "mlo teardown, pdev id %u, status %u\n", + ev->pdev_id, ev->status); + + kfree(tb); +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -913,6 +913,74 @@ err_wmi_detach: + return ret; + } + ++static int ath12k_core_mlo_teardown(struct ath12k_hw_group *ag) ++{ ++ struct ath12k_hw *ah; ++ int ret; ++ int i; ++ ++ if (ag->id == ATH12K_INVALID_GRP_ID) ++ return 0; ++ ++ for (i = ag->num_hw - 1; i >= 0; i--) { ++ ah = ag->ah[i]; ++ if (!ah) ++ continue; ++ ++ ret = ath12k_mac_mlo_teardown(ah); ++ if (ret) ++ goto out; ++ } ++ ++out: ++ return ret; ++} ++ ++static int ath12k_core_mlo_setup(struct ath12k_hw_group *ag) ++{ ++ struct ath12k_hw *ah; ++ int ret; ++ int i; ++ ++ if (ag->id == ATH12K_INVALID_GRP_ID) ++ return 0; ++ ++ for (i = 0; i < ag->num_hw; i++) { ++ ah = ag->ah[i]; ++ if (!ah) ++ continue; ++ ++ ret = ath12k_mac_mlo_setup(ah); ++ if (ret) ++ goto err_setup; ++ } ++ ++ for (i = 0; i < ag->num_hw; i++) { ++ ah = ag->ah[i]; ++ if (!ah) ++ continue; ++ ++ ret = ath12k_mac_mlo_ready(ah); ++ if (ret) ++ goto err_ready; ++ } ++ ++ return 0; ++ ++err_ready: ++ i = ag->num_hw; ++err_setup: ++ for (i = i - 1; i >= 0; i--) { ++ ah = ag->ah[i]; ++ if (!ah) ++ continue; ++ ++ ath12k_mac_mlo_teardown(ah); ++ } ++ ++ return ret; ++} ++ + static int ath12k_core_hw_group_start(struct ath12k_hw_group *ag) + { + struct ath12k_base *ab = ag->ab[0]; +@@ -949,11 +1017,17 @@ static int ath12k_core_hw_group_start(st + mutex_unlock(&ab->core_lock); + } + ++ ret = ath12k_core_mlo_setup(ag); ++ if (ret) { ++ ath12k_err(NULL, "failed to setup MLO: %d\n", ret); ++ goto err_pdev_destroy; ++ } ++ + if (!is_registered) { + ret = ath12k_mac_register(ag); + if (ret) { + ath12k_err(ab, "failed register the radio with mac80211: %d\n", ret); +- goto err_pdev_destroy; ++ goto err_mlo_teardown; + } + } + +@@ -1005,6 +1079,8 @@ pdev_cleanup: + } + + ath12k_mac_unregister(ag); ++err_mlo_teardown: ++ ath12k_core_mlo_teardown(ag); + i = ag->num_chip; + err_pdev_destroy: + for (i = i - 1; i >= 0; i--) { +@@ -1488,7 +1564,7 @@ static void ath12k_core_hw_group_stop(st + + clear_bit(ATH12K_FLAG_REGISTERED, &ag->dev_flags); + +- for (i = 0; i < ag->num_chip; i++) { ++ for (i = ag->num_chip - 1; i >= 0; i--) { + ab = ag->ab[i]; + + mutex_lock(&ab->core_lock); +@@ -1500,7 +1576,9 @@ static void ath12k_core_hw_group_stop(st + + ath12k_mac_unregister(ag); + +- for (i = 0; i < ag->num_chip; i++) { ++ ath12k_core_mlo_teardown(ag); ++ ++ for (i = ag->num_chip - 1; i >= 0; i--) { + ab = ag->ab[i]; + + mutex_lock(&ab->core_lock); +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -1854,10 +1854,8 @@ static void ath12k_htt_mlo_offset_event_ + HTT_T2H_MLO_OFFSET_INFO_PDEV_ID); + ar = ath12k_mac_get_ar_by_pdev_id(ab, pdev_id); + +- if (!ar) { +- ath12k_warn(ab, "invalid pdev id %d on htt mlo offset\n", pdev_id); ++ if (!ar) + return; +- } + + spin_lock_bh(&ar->data_lock); + pdev = ar->pdev; +--- a/drivers/net/wireless/ath/ath12k/mac.h ++++ b/drivers/net/wireless/ath/ath12k/mac.h +@@ -12,6 +12,7 @@ + + struct ath12k; + struct ath12k_base; ++struct ath12k_hw; + struct ath12k_hw_group; + + struct ath12k_generic_iter { +@@ -167,4 +168,7 @@ void ath12k_mac_get_any_chandef_iter(str + void *data); + void ath12k_mac_bcn_tx_event(struct ath12k_vif *arvif); + struct ath12k *ath12k_get_ar_by_vif(struct ieee80211_hw *hw, struct ieee80211_vif *vif); ++int ath12k_mac_mlo_setup(struct ath12k_hw *ah); ++int ath12k_mac_mlo_ready(struct ath12k_hw *ah); ++int ath12k_mac_mlo_teardown(struct ath12k_hw *ah); + #endif diff --git a/feeds/ipq95xx/mac80211/patches/qca/670-04-ath12k-add-MLO-global-memory-support-in-coredump.patch b/feeds/ipq95xx/mac80211/patches/qca/670-04-ath12k-add-MLO-global-memory-support-in-coredump.patch new file mode 100644 index 000000000..fad7d92e2 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/670-04-ath12k-add-MLO-global-memory-support-in-coredump.patch @@ -0,0 +1,41 @@ +From 6f020eda282241af244f99f1726b7c548619015a Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Thu, 11 Aug 2022 15:04:12 +0530 +Subject: [PATCH] ath12k: add MLO global memory support in coredump + +Add MLO global memory type support in the coredump module. So that +SSR dump collect this memory region. + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/coredump.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath12k/coredump.c ++++ b/drivers/net/wireless/ath/ath12k/coredump.c +@@ -164,7 +164,8 @@ void ath12k_coredump_download_rddm(struc + if (ab->qmi.target_mem[i].type == HOST_DDR_REGION_TYPE || + ab->qmi.target_mem[i].type == CALDB_MEM_REGION_TYPE || + ab->qmi.target_mem[i].type == M3_DUMP_REGION_TYPE || +- ab->qmi.target_mem[i].type == PAGEABLE_MEM_REGION_TYPE) ++ ab->qmi.target_mem[i].type == PAGEABLE_MEM_REGION_TYPE || ++ ab->qmi.target_mem[i].type == MLO_GLOBAL_MEM_REGION_TYPE) + rem_seg_cnt++; + } + +@@ -214,6 +215,15 @@ void ath12k_coredump_download_rddm(struc + continue; + } + } ++ ++ if (ab->qmi.target_mem[i].type == MLO_GLOBAL_MEM_REGION_TYPE) { ++ seg_info->len = ab->qmi.target_mem[i].size; ++ seg_info->addr = ab->qmi.target_mem[i].paddr; ++ seg_info->vaddr = ab->qmi.target_mem[i].v.ioaddr; ++ seg_info->type = ATH12K_FW_MLO_GLOBAL; ++ seg_info++; ++ continue; ++ } + if (ab->qmi.target_mem[i].type == PAGEABLE_MEM_REGION_TYPE) { + seg_info->len = ab->qmi.target_mem[i].size; + seg_info->addr = ab->qmi.target_mem[i].paddr; diff --git a/feeds/ipq95xx/mac80211/patches/qca/670-ath12k-Add-support-for-cold-boot-calibartion.patch b/feeds/ipq95xx/mac80211/patches/qca/670-ath12k-Add-support-for-cold-boot-calibartion.patch new file mode 100644 index 000000000..3e15fa9d5 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/670-ath12k-Add-support-for-cold-boot-calibartion.patch @@ -0,0 +1,151 @@ +From 36e81f08830b00707d67731f5740495866191330 Mon Sep 17 00:00:00 2001 +From: Ganesh Babu Jothiram +Date: Mon, 19 Sep 2022 16:32:29 +0530 +Subject: [PATCH] ath12k: Add support for cold boot calibartion + +In case of cold boot calibration support enabled, + The firmware mode set to cold boot calibration initially and +upon completion of cold boot calibration OR timeout, +The firmware power reseted and mode set to Mission Mode. + Memory allocated on request from firmware for CALDB via QMI to +support cold boot calibration. + +Signed-off-by: Ganesh Babu Jothiram +--- + drivers/net/wireless/ath/ath12k/core.c | 2 +- + drivers/net/wireless/ath/ath12k/coredump.c | 23 ++++++++----- + drivers/net/wireless/ath/ath12k/pci.c | 2 ++ + drivers/net/wireless/ath/ath12k/qmi.c | 39 +++++++++++++++++++++- + drivers/net/wireless/ath/ath12k/qmi.h | 2 ++ + 5 files changed, 58 insertions(+), 10 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/coredump.c ++++ b/drivers/net/wireless/ath/ath12k/coredump.c +@@ -162,7 +162,7 @@ void ath12k_coredump_download_rddm(struc + + for (i = 0; i < ab->qmi.mem_seg_count; i++) { + if (ab->qmi.target_mem[i].type == HOST_DDR_REGION_TYPE || +- ab->qmi.target_mem[i].type == CALDB_MEM_REGION_TYPE || ++ (ab->qmi.target_mem[i].type == CALDB_MEM_REGION_TYPE && ath12k_cold_boot_cal && ab->hw_params->cold_boot_calib) || + ab->qmi.target_mem[i].type == M3_DUMP_REGION_TYPE || + ab->qmi.target_mem[i].type == PAGEABLE_MEM_REGION_TYPE || + ab->qmi.target_mem[i].type == MLO_GLOBAL_MEM_REGION_TYPE) +@@ -207,13 +207,20 @@ void ath12k_coredump_download_rddm(struc + } + + for (i = 0; i < ab->qmi.mem_seg_count; i++) { +- if (ab->qmi.target_mem[i].type == CALDB_MEM_REGION_TYPE) { +- if (ath12k_cold_boot_cal || +- ab->hw_params->cold_boot_calib) { +- /* Add separate segment type for CALDB*/ +- skip_count++; +- continue; +- } ++ if (ab->qmi.target_mem[i].type == CALDB_MEM_REGION_TYPE && ++ ath12k_cold_boot_cal && ++ ab->hw_params->cold_boot_calib) { ++ seg_info->len = ab->qmi.target_mem[i].size; ++ seg_info->addr = ab->qmi.target_mem[i].paddr; ++ seg_info->vaddr = ab->qmi.target_mem[i].v.ioaddr; ++ seg_info->type = ATH12K_FW_CALDB; ++ ath12k_info(ab, ++ "seg vaddr is %px len is 0x%x type %d\n", ++ seg_info->vaddr, ++ seg_info->len, ++ seg_info->type); ++ seg_info++; ++ continue; + } + + if (ab->qmi.target_mem[i].type == MLO_GLOBAL_MEM_REGION_TYPE) { +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -1368,6 +1368,8 @@ static int ath12k_pci_probe(struct pci_d + goto err_free_irq; + } + ++ ath12k_qmi_fwreset_from_cold_boot(ab); ++ + return 0; + + err_free_irq: +--- a/drivers/net/wireless/ath/ath12k/qmi.c ++++ b/drivers/net/wireless/ath/ath12k/qmi.c +@@ -8,6 +8,7 @@ + + #include "qmi.h" + #include "core.h" ++#include "hif.h" + #include "debug.h" + #include "coredump.h" + #include +@@ -4002,6 +4003,41 @@ int ath12k_qmi_firmware_start(struct ath + return 0; + } + ++ ++int ath12k_qmi_fwreset_from_cold_boot(struct ath12k_base *ab) ++{ ++ int timeout; ++ ++ if (ath12k_cold_boot_cal == 0 || ++ ab->hw_params->cold_boot_calib == 0){ ++ ath12k_info(ab, "Cold boot cal is not supported/enabled\n"); ++ return 0; ++ } ++ ++ ath12k_dbg(ab, ATH12K_DBG_QMI, "wait for cold boot done\n"); ++ ++ timeout = wait_event_timeout(ab->qmi.cold_boot_waitq, ++ (ab->qmi.cal_done == 1), ++ ATH12K_COLD_BOOT_FW_RESET_DELAY); ++ if (timeout <= 0) { ++ ath12k_warn(ab, "Coldboot Calibration timed out\n"); ++ /*set cal_timeout to switch to mission mode on firware reset*/ ++ ab->qmi.cal_timeout = 1; ++ } ++ ++ /* reset the firmware */ ++ ath12k_info(ab, "power down to restart firmware in mission mode\n"); ++ ath12k_qmi_firmware_stop(ab); ++ ath12k_hif_power_down(ab); ++ ath12k_info(ab, "power up to restart firmware in mission mode\n"); ++ /* reset host fixed mem off to zero */ ++ ab->host_ddr_fixed_mem_off = 0; ++ ath12k_hif_power_up(ab); ++ ath12k_dbg(ab, ATH12K_DBG_QMI, "exit wait for cold boot done\n"); ++ return 0; ++} ++EXPORT_SYMBOL(ath12k_qmi_fwreset_from_cold_boot); ++ + static int ath12k_qmi_process_coldboot_calibration(struct ath12k_base *ab) + { + int timeout; +@@ -4793,7 +4829,8 @@ static void ath12k_qmi_driver_event_work + } + + if (ath12k_cold_boot_cal && ab->qmi.cal_done == 0 && +- ab->hw_params->cold_boot_calib) { ++ ab->hw_params->cold_boot_calib && ++ ab->qmi.cal_timeout == 0) { + ath12k_qmi_process_coldboot_calibration(ab); + } else { + clear_bit(ATH12K_FLAG_CRASH_FLUSH, +--- a/drivers/net/wireless/ath/ath12k/qmi.h ++++ b/drivers/net/wireless/ath/ath12k/qmi.h +@@ -164,6 +164,7 @@ struct ath12k_qmi { + u32 target_mem_mode; + bool target_mem_delayed; + u8 cal_done; ++ u8 cal_timeout; + struct target_info target; + struct m3_mem_region m3_mem; + unsigned int service_ins_id; +@@ -744,6 +745,7 @@ int ath12k_qmi_init_service(struct ath12 + + int ath12k_send_qdss_trace_mode_req(struct ath12k_base *ab, + enum qmi_wlanfw_qdss_trace_mode_enum_v01 mode); ++int ath12k_qmi_fwreset_from_cold_boot(struct ath12k_base *ab); + int ath12k_enable_fwlog(struct ath12k_base *ab); + int ath12k_qmi_m3_dump_upload_done_ind_send(struct ath12k_base *ab, + u32 pdev_id, int status); diff --git a/feeds/ipq95xx/mac80211/patches/qca/670-ath12k-Adding-support-for-mgmt-frames-stats.patch b/feeds/ipq95xx/mac80211/patches/qca/670-ath12k-Adding-support-for-mgmt-frames-stats.patch index 2e003f96e..715611056 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/670-ath12k-Adding-support-for-mgmt-frames-stats.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/670-ath12k-Adding-support-for-mgmt-frames-stats.patch @@ -22,11 +22,9 @@ Signed-off-by: Manish Dharanenthiran drivers/net/wireless/ath/ath12k/wmi.c | 63 ++++++++++++++++ 4 files changed, 178 insertions(+), 4 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h -index 92f5ec2..7c5629e 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h -@@ -272,6 +272,16 @@ struct ath12k_reg_tpc_power_info { +@@ -282,6 +282,16 @@ struct ath12k_reg_tpc_power_info { struct chan_power_info chan_power_info[IEEE80211_MAX_NUM_PWR_LEVEL]; }; @@ -43,7 +41,7 @@ index 92f5ec2..7c5629e 100644 struct ath12k_tx_conf { bool changed; u16 ac; -@@ -358,6 +368,7 @@ struct ath12k_vif { +@@ -368,6 +378,7 @@ struct ath12k_vif { struct work_struct update_bcn_template_work; u64 obss_color_bitmap; struct work_struct update_obss_color_notify_work; @@ -51,12 +49,10 @@ index 92f5ec2..7c5629e 100644 }; struct ath12k_vif_iter { -diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c -index c177396..331b2d5 100644 --- a/drivers/net/wireless/ath/ath12k/debugfs.c +++ b/drivers/net/wireless/ath/ath12k/debugfs.c -@@ -2512,6 +2512,89 @@ static const struct file_operations fops_enable_m3_dump = { - .open = simple_open +@@ -2348,6 +2348,89 @@ static const struct file_operations fops + .open = simple_open }; +static ssize_t ath12k_dump_mgmt_stats(struct file *file, @@ -145,22 +141,20 @@ index c177396..331b2d5 100644 int ath12k_debugfs_register(struct ath12k *ar) { struct ath12k_base *ab = ar->ab; -@@ -2576,6 +2659,10 @@ int ath12k_debugfs_register(struct ath12k *ar) - debugfs_create_file("tpc_stats_type", 0600, +@@ -2406,6 +2489,10 @@ int ath12k_debugfs_register(struct ath12 ar->debug.debugfs_pdev, ar, &fops_tpc_stats_type); -+ + + debugfs_create_file("dump_mgmt_stats", 0644, + ar->debug.debugfs_pdev, ar, + &fops_dump_mgmt_stats); - ++ return 0; } -diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index 907c37c..355f634 100644 + --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -6755,9 +6755,9 @@ static int ath12k_mac_mgmt_tx(struct ath12k *ar, struct sk_buff *skb, +@@ -6839,9 +6839,9 @@ static int ath12k_mac_mgmt_tx(struct ath */ if (is_prb_rsp && atomic_read(&ar->num_pending_mgmt_tx) > ATH12K_PRB_RSP_DROP_THRESHOLD) { @@ -172,7 +166,7 @@ index 907c37c..355f634 100644 } if (skb_queue_len_lockless(q) >= ATH12K_TX_MGMT_NUM_PENDING_MAX) { -@@ -6784,10 +6784,12 @@ static void ath12k_mac_op_tx(struct ieee80211_hw *hw, +@@ -6868,10 +6868,12 @@ static void ath12k_mac_op_tx(struct ieee struct ath12k_hw *ah = ar->ah; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_key_conf *key = info->control.hw_key; @@ -185,7 +179,7 @@ index 907c37c..355f634 100644 int ret; if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { -@@ -6811,12 +6813,21 @@ static void ath12k_mac_op_tx(struct ieee80211_hw *hw, +@@ -6895,12 +6897,21 @@ static void ath12k_mac_op_tx(struct ieee if (info_flags & IEEE80211_TX_CTL_HW_80211_ENCAP) { skb_cb->flags |= ATH12K_SKB_HW_80211_ENCAP; } else if (ieee80211_is_mgmt(hdr->frame_control)) { @@ -196,7 +190,7 @@ index 907c37c..355f634 100644 - ath12k_warn(ar->ab, "failed to queue management frame %d\n", - ret); + if (ret != -EBUSY) -+ ath12k_warn(ar->ab, "failed to queue management frame %d\n", ret); ++ ath12k_warn(ar->ab, "failed to queue mgmt stype 0x%x frame %d\n", frm_type, ret); + ieee80211_free_txskb(ah->hw, skb); + spin_lock_bh(&ar->data_lock); @@ -209,8 +203,8 @@ index 907c37c..355f634 100644 } return; } -@@ -7768,8 +7779,10 @@ err_vdev_del: - +@@ -8033,8 +8044,10 @@ static void ath12k_mac_op_remove_interfa + err_vdev_del: ath12k_peer_cleanup(ar, arvif->vdev_id); + spin_lock_bh(&ar->data_lock); @@ -220,11 +214,9 @@ index 907c37c..355f634 100644 ath12k_mac_vif_unref(&ab->dp, vif); ath12k_dp_tx_put_bank_profile(&ab->dp, arvif->bank_id); -diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c -index 2a2f9dd..d06b2db 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -5689,8 +5689,14 @@ static int wmi_process_mgmt_tx_comp(struct ath12k *ar, u32 desc_id, +@@ -5722,8 +5722,14 @@ static int wmi_process_mgmt_tx_comp(stru struct sk_buff *msdu; struct ieee80211_tx_info *info; struct ath12k_skb_cb *skb_cb; @@ -239,7 +231,7 @@ index 2a2f9dd..d06b2db 100644 spin_lock_bh(&ar->txmgmt_idr_lock); msdu = idr_find(&ar->txmgmt_idr, desc_id); -@@ -5698,6 +5704,7 @@ static int wmi_process_mgmt_tx_comp(struct ath12k *ar, u32 desc_id, +@@ -5731,6 +5737,7 @@ static int wmi_process_mgmt_tx_comp(stru ath12k_warn(ar->ab, "received mgmt tx compl for invalid msdu_id: %d\n", desc_id); spin_unlock_bh(&ar->txmgmt_idr_lock); @@ -247,7 +239,7 @@ index 2a2f9dd..d06b2db 100644 return -ENOENT; } -@@ -5707,6 +5714,29 @@ static int wmi_process_mgmt_tx_comp(struct ath12k *ar, u32 desc_id, +@@ -5740,6 +5747,29 @@ static int wmi_process_mgmt_tx_comp(stru skb_cb = ATH12K_SKB_CB(msdu); dma_unmap_single(ar->ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); @@ -277,7 +269,7 @@ index 2a2f9dd..d06b2db 100644 info = IEEE80211_SKB_CB(msdu); if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) && !status) info->flags |= IEEE80211_TX_STAT_ACK; -@@ -7099,6 +7129,11 @@ static void ath12k_mgmt_rx_event(struct ath12k_base *ab, struct sk_buff *skb) +@@ -7129,6 +7159,11 @@ static void ath12k_mgmt_rx_event(struct struct ieee80211_hdr *hdr; u16 fc; struct ieee80211_supported_band *sband; @@ -289,7 +281,7 @@ index 2a2f9dd..d06b2db 100644 if (ath12k_pull_mgmt_rx_params_tlv(ab, skb, &rx_ev) != 0) { ath12k_warn(ab, "failed to extract mgmt rx event"); -@@ -7164,6 +7199,34 @@ static void ath12k_mgmt_rx_event(struct ath12k_base *ab, struct sk_buff *skb) +@@ -7194,6 +7229,34 @@ static void ath12k_mgmt_rx_event(struct hdr = (struct ieee80211_hdr *)skb->data; fc = le16_to_cpu(hdr->frame_control); @@ -324,6 +316,3 @@ index 2a2f9dd..d06b2db 100644 /* Firmware is guaranteed to report all essential management frames via * WMI while it can deliver some extra via HTT. Since there can be --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/670-ath12k-enhance-peer-create-delete-log.patch b/feeds/ipq95xx/mac80211/patches/qca/670-ath12k-enhance-peer-create-delete-log.patch index b23bc8309..9012e27bf 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/670-ath12k-enhance-peer-create-delete-log.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/670-ath12k-enhance-peer-create-delete-log.patch @@ -16,11 +16,9 @@ Signed-off-by: Hari Chandrakanthan drivers/net/wireless/ath/ath12k/wmi.c | 18 +++++++++++------- 3 files changed, 28 insertions(+), 20 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index b93841d..64367cf 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -885,6 +885,8 @@ void ath12k_mac_peer_cleanup_all(struct ath12k *ar) +@@ -888,6 +888,8 @@ void ath12k_mac_peer_cleanup_all(struct ar->num_peers = 0; ar->num_stations = 0; @@ -28,18 +26,18 @@ index b93841d..64367cf 100644 + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "ath12k mac peer cleanup done\n"); } - static inline int ath12k_mac_vdev_setup_sync(struct ath12k *ar) -@@ -3974,7 +3976,8 @@ static int ath12k_mac_vdev_delete(struct ath12k *ar, struct ieee80211_vif *vif) + static int ath12k_mac_vdev_setup_sync(struct ath12k *ar) +@@ -4022,7 +4024,8 @@ static int ath12k_mac_vdev_delete(struct time_left = wait_for_completion_timeout(&ar->vdev_delete_done, ATH12K_VDEV_DELETE_TIMEOUT_HZ); if (time_left == 0) { - ath12k_warn(ar->ab, "Timeout in receiving vdev delete response\n"); + ath12k_warn(ar->ab, "Timeout in receiving vdev delete response vdev_id : %d\n", + arvif->vdev_id); - return -ETIMEDOUT; + ret = -ETIMEDOUT; + goto clean_up; } - -@@ -5298,8 +5301,8 @@ static int ath12k_mac_station_add(struct ath12k *ar, +@@ -5356,8 +5359,8 @@ static int ath12k_mac_station_add(struct goto free_rx_stats; } @@ -48,9 +46,9 @@ index b93841d..64367cf 100644 + ath12k_dbg(ab, ATH12K_DBG_MAC, "Added peer: %pM for VDEV: %d num_stations : %d\n", + sta->addr, arvif->vdev_id, ar->num_stations); - ath12k_mac_ap_ps_recalc(ar); - -@@ -5410,18 +5413,18 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, + if (ath12k_debugfs_is_extd_tx_stats_enabled(ar) && (!arsta->tx_stats)) { + arsta->tx_stats = kzalloc(sizeof(*arsta->tx_stats), +@@ -5469,18 +5472,18 @@ static int ath12k_mac_op_sta_state(struc ret = ath12k_peer_delete(ar, arvif->vdev_id, sta->addr); if (ret) @@ -75,7 +73,7 @@ index b93841d..64367cf 100644 peer->sta = NULL; list_del(&peer->list); kfree(peer); -@@ -7737,8 +7740,8 @@ static void ath12k_mac_op_remove_interface(struct ieee80211_hw *hw, +@@ -8019,8 +8022,8 @@ static void ath12k_mac_op_remove_interfa if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { ret = ath12k_peer_delete(ar, arvif->vdev_id, vif->addr); if (ret) @@ -86,11 +84,9 @@ index b93841d..64367cf 100644 } ret = ath12k_mac_vdev_delete(ar, vif); -diff --git a/drivers/net/wireless/ath/ath12k/peer.c b/drivers/net/wireless/ath/ath12k/peer.c -index 3b69c09..19e7da4 100644 --- a/drivers/net/wireless/ath/ath12k/peer.c +++ b/drivers/net/wireless/ath/ath12k/peer.c -@@ -218,14 +218,15 @@ int ath12k_wait_for_peer_delete_done(struct ath12k *ar, u32 vdev_id, +@@ -218,14 +218,15 @@ int ath12k_wait_for_peer_delete_done(str ret = ath12k_wait_for_peer_deleted(ar, vdev_id, addr); if (ret) { @@ -108,11 +104,9 @@ index 3b69c09..19e7da4 100644 return -ETIMEDOUT; } -diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c -index 0d71bd4..63dddea 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -824,7 +824,8 @@ int ath12k_wmi_vdev_delete(struct ath12k *ar, u8 vdev_id) +@@ -868,7 +868,8 @@ int ath12k_wmi_vdev_delete(struct ath12k dev_kfree_skb(skb); } @@ -122,7 +116,7 @@ index 0d71bd4..63dddea 100644 return ret; } -@@ -876,7 +877,8 @@ int ath12k_wmi_vdev_down(struct ath12k *ar, u8 vdev_id) +@@ -920,7 +921,8 @@ int ath12k_wmi_vdev_down(struct ath12k * ret = ath12k_wmi_cmd_send(wmi, skb, WMI_VDEV_DOWN_CMDID); if (ret) { @@ -132,7 +126,7 @@ index 0d71bd4..63dddea 100644 dev_kfree_skb(skb); } -@@ -1091,8 +1093,8 @@ int ath12k_wmi_send_peer_create_cmd(struct ath12k *ar, +@@ -1131,8 +1133,8 @@ int ath12k_wmi_send_peer_create_cmd(stru } ath12k_dbg(ar->ab, ATH12K_DBG_WMI, @@ -143,8 +137,8 @@ index 0d71bd4..63dddea 100644 return ret; } -@@ -1117,12 +1119,14 @@ int ath12k_wmi_send_peer_delete_cmd(struct ath12k *ar, - cmd->vdev_id = vdev_id; +@@ -1157,12 +1159,14 @@ int ath12k_wmi_send_peer_delete_cmd(stru + cmd->vdev_id = cpu_to_le32(vdev_id); ath12k_dbg(ar->ab, ATH12K_DBG_WMI, - "WMI peer delete vdev_id %d peer_addr %pM\n", @@ -161,6 +155,3 @@ index 0d71bd4..63dddea 100644 dev_kfree_skb(skb); } --- -2.7.4 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/672-ath12k-Fix-freeing-hal-reo-status-entry-in-host.patch b/feeds/ipq95xx/mac80211/patches/qca/672-ath12k-Fix-freeing-hal-reo-status-entry-in-host.patch index db1c94d67..5bef8c30f 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/672-ath12k-Fix-freeing-hal-reo-status-entry-in-host.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/672-ath12k-Fix-freeing-hal-reo-status-entry-in-host.patch @@ -1,6 +1,6 @@ -From 095061ec382cff5f484f392673968eb35d1be570 Mon Sep 17 00:00:00 2001 +From 3a0f9e84c24342c2bdb26eb88b6379bbd93a3d72 Mon Sep 17 00:00:00 2001 From: Manish Dharanenthiran -Date: Mon, 3 Oct 2022 16:58:34 +0530 +Date: Fri, 21 Oct 2022 08:56:09 +0530 Subject: [PATCH] ath12k: Fix freeing hal reo status entry in host in failure case @@ -17,25 +17,25 @@ failure case and retry later to avoid memory corruption. Signed-off-by: Manish Dharanenthiran --- - drivers/net/wireless/ath/ath12k/dp_rx.c | 41 +++++++++++++++++-------- - 1 file changed, 28 insertions(+), 13 deletions(-) + drivers/net/wireless/ath/ath12k/dp_rx.c | 40 +++++++++++++++++-------- + 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c -index aff17c6..a7d44ae 100644 +index 242738a..ce32d74 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -693,7 +693,7 @@ static void ath12k_dp_reo_cmd_free(struct ath12k_dp *dp, void *ctx, - } +@@ -694,7 +694,7 @@ static int ath12k_dp_reo_cmd_send(struct ath12k_base *ab, struct ath12k_dp_rx_ti + return 0; } -static void ath12k_dp_reo_cache_flush(struct ath12k_base *ab, +static int ath12k_dp_reo_cache_flush(struct ath12k_base *ab, - struct dp_rx_tid *rx_tid) + struct ath12k_dp_rx_tid *rx_tid) { struct ath12k_hal_reo_cmd cmd = {0}; -@@ -711,9 +711,17 @@ static void ath12k_dp_reo_cache_flush(struct ath12k_base *ab, - HAL_REO_CMD_FLUSH_CACHE, &cmd, - NULL); +@@ -712,9 +712,16 @@ static void ath12k_dp_reo_cache_flush(struct ath12k_base *ab, + HAL_REO_CMD_FLUSH_CACHE, &cmd, + NULL); if (ret) + { ath12k_warn(ab, @@ -43,7 +43,6 @@ index aff17c6..a7d44ae 100644 - rx_tid->tid, ret); + "failed to send HAL_REO_CMD_FLUSH_CACHE, tid %d (%d) desc_sz(%ld)\n", + rx_tid->tid, ret, desc_sz); -+ + /* If this fails with ring full condition, then + * no need to retry below as it is expected to + * fail within short time */ @@ -53,10 +52,10 @@ index aff17c6..a7d44ae 100644 } memset(&cmd, 0, sizeof(cmd)); -@@ -723,14 +731,12 @@ static void ath12k_dp_reo_cache_flush(struct ath12k_base *ab, - ret = ath12k_dp_tx_send_reo_cmd(ab, rx_tid, - HAL_REO_CMD_FLUSH_CACHE, - &cmd, ath12k_dp_reo_cmd_free); +@@ -724,14 +731,12 @@ static void ath12k_dp_reo_cache_flush(struct ath12k_base *ab, + ret = ath12k_dp_reo_cmd_send(ab, rx_tid, + HAL_REO_CMD_FLUSH_CACHE, + &cmd, ath12k_dp_reo_cmd_free); - if (ret) { + if (ret) ath12k_err(ab, "failed to send HAL_REO_CMD_FLUSH_CACHE cmd, tid %d (%d)\n", @@ -72,10 +71,10 @@ index aff17c6..a7d44ae 100644 } static void ath12k_dp_rx_tid_del_func(struct ath12k_dp *dp, void *ctx, -@@ -768,13 +774,22 @@ static void ath12k_dp_rx_tid_del_func(struct ath12k_dp *dp, void *ctx, - if (dp->reo_cmd_cache_flush_count > DP_REO_DESC_FREE_THRESHOLD || +@@ -769,13 +774,22 @@ static void ath12k_dp_rx_tid_del_func(struct ath12k_dp *dp, void *ctx, + if (dp->reo_cmd_cache_flush_count > ATH12K_DP_RX_REO_DESC_FREE_THRES || time_after(jiffies, elem->ts + - msecs_to_jiffies(DP_REO_DESC_FREE_TIMEOUT_MS))) { + msecs_to_jiffies(ATH12K_DP_RX_REO_DESC_FREE_TIMEOUT_MS))) { - list_del(&elem->list); - dp->reo_cmd_cache_flush_count--; spin_unlock_bh(&dp->reo_cmd_lock); @@ -87,8 +86,8 @@ index aff17c6..a7d44ae 100644 + * for flush cache elem and continue */ + spin_lock_bh(&dp->reo_cmd_lock); + elem->ts = jiffies + -+ msecs_to_jiffies(DP_REO_DESC_FREE_TIMEOUT_MS); -+ ath12k_err(ab, "Failed to send HAL_REO_CMD_FLUSH_CACHE cmd" ++ msecs_to_jiffies(ATH12K_DP_RX_REO_DESC_FREE_TIMEOUT_MS); ++ ath12k_warn(ab, "Failed to send HAL_REO_CMD_FLUSH_CACHE cmd" + "Updating timestamp (%ld) in the list\n", elem->ts); + continue; + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/673-ath12k-RDP454-bringup.patch b/feeds/ipq95xx/mac80211/patches/qca/673-ath12k-RDP454-bringup.patch new file mode 100644 index 000000000..6c8a45459 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/673-ath12k-RDP454-bringup.patch @@ -0,0 +1,123 @@ +From 1aa2d88e00469cd93fd3972fa4a42304283782cc Mon Sep 17 00:00:00 2001 +From: Ganesh Babu Jothiram +Date: Mon, 10 Oct 2022 17:13:29 +0530 +Subject: [PATCH] ath12k: RDP454 bringup + +Updated HW param max_radios to support split PHY HW. +Dualmac firmware selected based on board_id that matches to 0x1xxx. + +Signed-off-by: Ganesh Babu Jothiram +--- + drivers/net/wireless/ath/ath12k/hw.c | 2 +- + drivers/net/wireless/ath/ath12k/hw.h | 1 + + drivers/net/wireless/ath/ath12k/mhi.c | 12 +++++++++++- + 3 files changed, 13 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -1091,7 +1091,7 @@ static const struct ath12k_hw_params ath + .board_size = 256 * 1024, + .cal_offset = 128 * 1024, + }, +- .max_radios = 1, ++ .max_radios = 2, + .single_pdev_only = false, + .qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_QCN9274, + .internal_sleep_clock = false, +--- a/drivers/net/wireless/ath/ath12k/hw.h ++++ b/drivers/net/wireless/ath/ath12k/hw.h +@@ -82,6 +82,7 @@ + #define ATH12K_DEFAULT_BOARD_FILE "board.bin" + #define ATH12K_DEFAULT_CAL_FILE "caldata.bin" + #define ATH12K_AMSS_FILE "amss.bin" ++#define ATH12K_AMSS_DUALMAC_FILE "amss_dualmac.bin" + #define ATH12K_M3_FILE "m3.bin" + #define ATH12K_REGDB_FILE_NAME "regdb.bin" + #define ATH12K_REGDB_BINARY "regdb" +--- a/drivers/net/wireless/ath/ath12k/mhi.c ++++ b/drivers/net/wireless/ath/ath12k/mhi.c +@@ -376,14 +376,26 @@ static int ath12k_mhi_read_addr_from_dt( + int ath12k_mhi_register(struct ath12k_pci *ab_pci) + { + struct ath12k_base *ab = ab_pci->ab; ++ struct device *dev = ab->dev; + struct mhi_controller *mhi_ctrl; ++ unsigned int board_id; ++ const char *filename = ATH12K_AMSS_FILE; + int ret; + + mhi_ctrl = mhi_alloc_controller(); + if (!mhi_ctrl) + return -ENOMEM; + +- ath12k_core_create_firmware_path(ab, ATH12K_AMSS_FILE, ++ if (!of_property_read_u32(dev->of_node, "qcom,board_id", &board_id)) { ++ if (board_id & 0x1000) { ++ filename = ATH12K_AMSS_DUALMAC_FILE; ++ ath12k_dbg(ab, ATH12K_DBG_BOOT, ++ "DUALMAC FW %s selected for Split PHY HW\n", ++ filename); ++ } ++ } ++ ++ ath12k_core_create_firmware_path(ab, filename, + ab_pci->amss_path, + sizeof(ab_pci->amss_path)); + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -614,7 +614,8 @@ struct ath12k_vif *ath12k_mac_get_arvif_ + + for (i = 0; i < ab->num_radios; i++) { + pdev = rcu_dereference(ab->pdevs_active[i]); +- if (pdev && pdev->ar) { ++ if (pdev && pdev->ar && ++ (pdev->ar->allocated_vdev_map & (1LL << vdev_id))) { + arvif = ath12k_mac_get_arvif(pdev->ar, vdev_id); + if (arvif) + return arvif; +--- a/drivers/net/wireless/ath/ath12k/coredump.c ++++ b/drivers/net/wireless/ath/ath12k/coredump.c +@@ -162,7 +162,8 @@ void ath12k_coredump_download_rddm(struc + + for (i = 0; i < ab->qmi.mem_seg_count; i++) { + if (ab->qmi.target_mem[i].type == HOST_DDR_REGION_TYPE || +- (ab->qmi.target_mem[i].type == CALDB_MEM_REGION_TYPE && ath12k_cold_boot_cal && ab->hw_params->cold_boot_calib) || ++ (ab->qmi.target_mem[i].type == CALDB_MEM_REGION_TYPE && ++ ath12k_cold_boot_cal && ab->hw_params->cold_boot_calib) || + ab->qmi.target_mem[i].type == M3_DUMP_REGION_TYPE || + ab->qmi.target_mem[i].type == PAGEABLE_MEM_REGION_TYPE || + ab->qmi.target_mem[i].type == MLO_GLOBAL_MEM_REGION_TYPE) +@@ -207,19 +208,20 @@ void ath12k_coredump_download_rddm(struc + } + + for (i = 0; i < ab->qmi.mem_seg_count; i++) { +- if (ab->qmi.target_mem[i].type == CALDB_MEM_REGION_TYPE && +- ath12k_cold_boot_cal && +- ab->hw_params->cold_boot_calib) { +- seg_info->len = ab->qmi.target_mem[i].size; +- seg_info->addr = ab->qmi.target_mem[i].paddr; +- seg_info->vaddr = ab->qmi.target_mem[i].v.ioaddr; +- seg_info->type = ATH12K_FW_CALDB; +- ath12k_info(ab, +- "seg vaddr is %px len is 0x%x type %d\n", +- seg_info->vaddr, +- seg_info->len, ++ if (ab->qmi.target_mem[i].type == CALDB_MEM_REGION_TYPE) { ++ if (ath12k_cold_boot_cal && ++ ab->hw_params->cold_boot_calib) { ++ seg_info->len = ab->qmi.target_mem[i].size; ++ seg_info->addr = ab->qmi.target_mem[i].paddr; ++ seg_info->vaddr = ab->qmi.target_mem[i].v.ioaddr; ++ seg_info->type = ATH12K_FW_CALDB; ++ ath12k_info(ab, ++ "seg vaddr is %px len is 0x%x type %d\n", ++ seg_info->vaddr, ++ seg_info->len, + seg_info->type); +- seg_info++; ++ seg_info++; ++ } + continue; + } + diff --git a/feeds/ipq95xx/mac80211/patches/qca/673-ath12k-enable-service-flag-for-survey-dump-stats.patch b/feeds/ipq95xx/mac80211/patches/qca/673-ath12k-enable-service-flag-for-survey-dump-stats.patch index c04f73373..2a750217d 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/673-ath12k-enable-service-flag-for-survey-dump-stats.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/673-ath12k-enable-service-flag-for-survey-dump-stats.patch @@ -1,23 +1,24 @@ -From 9af7636f0890abee0233b1dbfbb1874c4fd06b90 Mon Sep 17 00:00:00 2001 +From aa7fb78d5dfc96f7e2301d6a108282fbcf8bbd27 Mon Sep 17 00:00:00 2001 From: Thiraviyam Mariyappan -Date: Mon, 3 Oct 2022 20:23:20 +0530 +Date: Mon, 17 Oct 2022 10:50:40 +0530 Subject: [PATCH] ath12k: enable service flag for survey dump stats survey dump statistics was not displaying channel rx and tx time because of survice flag was not enabled. - so enabled the service flag "bss_chan_info" in wmi_resource_config to fetch and print the stats for specific pdev. Signed-off-by: Thiraviyam Mariyappan --- - drivers/net/wireless/ath/ath12k/wmi.c | 1 + - drivers/net/wireless/ath/ath12k/wmi.h | 3 ++- - 2 files changed, 3 insertions(+), 1 deletion(-) + drivers/net/wireless/ath/ath12k/wmi.c | 2 +- + drivers/net/wireless/ath/ath12k/wmi.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) +diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c +index 7dd7e7d..1fecef0 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -3874,7 +3874,7 @@ ath12k_wmi_copy_resource_config(struct w +@@ -3914,7 +3914,7 @@ ath12k_wmi_copy_resource_config(struct wmi_resource_config *wmi_cfg, wmi_cfg->bpf_instruction_size = tg_cfg->bpf_instruction_size; wmi_cfg->max_bssid_rx_filters = tg_cfg->max_bssid_rx_filters; wmi_cfg->use_pdev_id = tg_cfg->use_pdev_id; @@ -26,13 +27,18 @@ Signed-off-by: Thiraviyam Mariyappan wmi_cfg->peer_map_unmap_version = tg_cfg->peer_map_unmap_version; wmi_cfg->sched_params = tg_cfg->sched_params; wmi_cfg->twt_ap_pdev_count = tg_cfg->twt_ap_pdev_count; +diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h +index 238bfae..4c7812c 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -2442,6 +2442,7 @@ struct wmi_init_cmd { - +@@ -2473,6 +2473,7 @@ struct wmi_init_cmd { #define WMI_RSRC_CFG_HOST_SVC_FLAG_REG_CC_EXT_SUPPORT_BIT 4 #define WMI_RSRC_CFG_HOST_SVC_FLAG_REO_QREF_SUPPORT_BIT 12 -+#define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5) #define WMI_RSRC_CFG_FLAGS2_CALC_NEXT_DTIM_COUNT_SET BIT(9) - #define WMI_RSRC_CFG_FLAGS2_INTRABSS_MEC_WDS_LEARNING_DISABLE BIT(15) ++#define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5) + struct wmi_resource_config { + __le32 tlv_header; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/674-ath12k-fix-rmmod-issue-in-SSR-case.patch b/feeds/ipq95xx/mac80211/patches/qca/674-ath12k-fix-rmmod-issue-in-SSR-case.patch new file mode 100644 index 000000000..c995d6867 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/674-ath12k-fix-rmmod-issue-in-SSR-case.patch @@ -0,0 +1,48 @@ +From d5ad6ee3ce26443ef13164a12727a95663be87aa Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Mon, 17 Oct 2022 16:25:35 +0530 +Subject: [PATCH] ath12k: fix rmmod issue in SSR case + +Currently, we are calling ath12k_hif_power_down immediate after +ath12k_core_stop function, ath12k_hif_power_down is responsible for +sending mhi_power_off state to firmware by this it's power off one +chip while the core does not stop for other parallel running chips, +due to which other chips receive MHI_CB_EE_RDDM callback. + +Hence all other chips are crashing during rmmod + +Fix it by calling ath12k_hif_power_down function after stopping core +for all chips. + +Signed-off-by: Aaradhana Sahu +--- + drivers/net/wireless/ath/ath12k/core.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c +index 981443f..cee7a21 100644 +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -1586,11 +1586,18 @@ static void ath12k_core_hw_group_stop(struct ath12k_hw_group *ag) + ath12k_core_pdev_destroy(ab); + ath12k_core_stop(ab); + ++ mutex_unlock(&ab->core_lock); ++ } ++ ++ for (i = ag->num_chip - 1; i >= 0; i--) { ++ ab = ag->ab[i]; ++ ++ mutex_lock(&ab->core_lock); ++ + ath12k_hif_power_down(ab); + + mutex_unlock(&ab->core_lock); + } +- + ath12k_mac_destroy(ag); + + ath12k_core_hw_group_destroy(ag); +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/674-mac80211-Fix-Channel-Switch-Announcement-6-GHz.patch b/feeds/ipq95xx/mac80211/patches/qca/674-mac80211-Fix-Channel-Switch-Announcement-6-GHz.patch new file mode 100644 index 000000000..2e8a68bb1 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/674-mac80211-Fix-Channel-Switch-Announcement-6-GHz.patch @@ -0,0 +1,227 @@ +From 9f49c1672ef95835c530443efc7235e4c0950fc1 Mon Sep 17 00:00:00 2001 +From: Sidhanta Sahu +Date: Tue, 18 Oct 2022 17:37:31 -0700 +Subject: [PATCH] mac80211: Fix Channel Switch Announcement 6 GHz + +STA fails to switch to new bandwidth or channel when CSA is trigerred from AP. +STA parses the new channel def using wide channel switch IE and regulatory +power mode in 6GHz. In presence of wide channel switch IE, CSA chandef needs to +be updated. + +Signed-off-by: Sidhanta Sahu +--- + include/linux/ieee80211.h | 4 +++ + include/uapi/linux/nl80211.h | 4 +++ + net/mac80211/ieee80211_i.h | 5 ++++ + net/mac80211/spectmgmt.c | 46 +++++++++++++++++++++++-------- + net/mac80211/util.c | 53 ++++++++++++++++++++++++++++++++++++ + net/wireless/util.c | 1 + + 6 files changed, 102 insertions(+), 11 deletions(-) + +--- a/include/linux/ieee80211.h ++++ b/include/linux/ieee80211.h +@@ -1700,6 +1700,10 @@ struct ieee80211_ht_operation { + u8 basic_set[16]; + } __packed; + ++/* Determine primary channel index */ ++#define PRIMARY_CENTER_CHAN_IDX(chan, ccfs_idx, bw) \ ++ ((chan > ccfs_idx) ? ccfs_idx + (bw/20) : ccfs_idx - (bw/20)) ++ + /* for ht_param */ + #define IEEE80211_HT_PARAM_CHA_SEC_OFFSET 0x03 + #define IEEE80211_HT_PARAM_CHA_SEC_NONE 0x00 +--- a/include/uapi/linux/nl80211.h ++++ b/include/uapi/linux/nl80211.h +@@ -4110,6 +4110,10 @@ enum nl80211_band_attr { + + #define NL80211_BAND_ATTR_HT_CAPA NL80211_BAND_ATTR_HT_CAPA + ++#define NL80211_NUM_POWER_MODES_PER_IFTYPE 3 ++#define GET_POWER_MODE_FOR_NON_AP_STA(pwr_mode_usr, pwr_mode_bcn) \ ++ (NL80211_NUM_POWER_MODES_PER_IFTYPE * (1 + pwr_mode_usr) + pwr_mode_bcn) ++ + enum nl80211_regulatory_power_modes { + NL80211_REG_AP_LPI, + NL80211_REG_AP_SP, +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -2464,6 +2464,11 @@ void ieee80211_chandef_eht_oper(struct i + const struct ieee80211_eht_operation *eht_oper, + bool support_160, bool support_320, + struct cfg80211_chan_def *chandef); ++struct ieee80211_channel ++*ieee80211_get_channel_6ghz_pwr_mode(const struct ieee80211_sub_if_data *sdata, ++ const struct ieee80211_he_operation *he_oper, ++ const int new_chan_idx); ++ + bool ieee80211_chandef_he_6ghz_oper(struct ieee80211_sub_if_data *sdata, + const struct ieee80211_he_operation *he_oper, + const struct ieee80211_eht_operation *eht_oper, +--- a/net/mac80211/spectmgmt.c ++++ b/net/mac80211/spectmgmt.c +@@ -40,7 +40,7 @@ int ieee80211_parse_ch_switch_ie(struct + struct ieee80211_eht_operation eht_oper; + struct ieee80211_eht_operation_info eht_oper_info; + int secondary_channel_offset = -1; +- u8 new_seg1, new_chan_width; ++ u8 new_seg0, new_seg1, new_chan_width; + + memset(csa_ie, 0, sizeof(*csa_ie)); + +@@ -89,8 +89,17 @@ int ieee80211_parse_ch_switch_ie(struct + elems->mesh_chansw_params_ie->mesh_reason); + } + +- new_freq = ieee80211_channel_to_frequency(new_chan_no, new_band); +- new_chan = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq); ++ if (new_band == NL80211_BAND_6GHZ) { ++ new_chan = ieee80211_get_channel_6ghz_pwr_mode(sdata, ++ elems->he_operation, ++ new_chan_no); ++ } else { ++ new_freq = ieee80211_channel_to_frequency(new_chan_no, ++ new_band); ++ new_chan = ieee80211_get_channel(sdata->local->hw.wiphy, ++ new_freq); ++ } ++ + if (!new_chan || new_chan->flags & IEEE80211_CHAN_DISABLED) { + sdata_info(sdata, + "BSS %pM switches to unsupported channel (%d MHz), disconnecting\n", +@@ -140,13 +149,17 @@ int ieee80211_parse_ch_switch_ie(struct + } + + if (wide_bw_chansw_ie) { ++ new_seg0 = wide_bw_chansw_ie->new_center_freq_seg0; + new_seg1 = wide_bw_chansw_ie->new_center_freq_seg1; + new_chan_width = wide_bw_chansw_ie->new_channel_width; +- if (current_band == NL80211_BAND_6GHZ && +- new_chan_width == IEEE80211_EHT_OPER_CHAN_WIDTH_320MHZ) { ++ if (new_band == NL80211_BAND_6GHZ) { + he_6ghz_oper.primary = new_chan_no; +- he_6ghz_oper.control = new_chan_width; +- he_6ghz_oper.ccfs0 = wide_bw_chansw_ie->new_center_freq_seg0; ++ if (new_chan_width == IEEE80211_CHANWIDTH_160MHZ) ++ he_6ghz_oper.control = IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_160MHZ; ++ else if (new_chan_width == IEEE80211_CHANWIDTH_80MHZ) ++ he_6ghz_oper.control = IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_80MHZ; ++ ++ he_6ghz_oper.ccfs0 = new_seg0; + he_6ghz_oper.ccfs1 = new_seg1; + + he_oper.he_oper_params = u32_encode_bits(1, +@@ -156,11 +169,25 @@ int ieee80211_parse_ch_switch_ie(struct + he_oper.optional[2] = he_6ghz_oper.ccfs0; + he_oper.optional[3] = he_6ghz_oper.ccfs1; + +- eht_oper_info.control = (eht_oper.params & +- IEEE80211_EHT_OPER_CHAN_WIDTH) | +- new_chan_width; +- eht_oper_info.ccfs0 = wide_bw_chansw_ie->new_center_freq_seg0; +- eht_oper_info.ccfs1 = wide_bw_chansw_ie->new_center_freq_seg1; ++ eht_oper.params |= IEEE80211_EHT_OPER_INFO_PRESENT; ++ eht_oper_info.ccfs0 = new_seg0; ++ eht_oper_info.ccfs1 = new_seg1; ++ if (new_chan_width == IEEE80211_CHANWIDTH_320MHZ) { ++ eht_oper_info.control = IEEE80211_EHT_OPER_CHAN_WIDTH_320MHZ; ++ eht_oper_info.ccfs0 = ++ PRIMARY_CENTER_CHAN_IDX(new_chan_no, ++ new_seg0, 320); ++ eht_oper_info.ccfs1 = new_seg0; ++ } else if (new_chan_width == IEEE80211_CHANWIDTH_160MHZ) { ++ eht_oper_info.control = IEEE80211_EHT_OPER_CHAN_WIDTH_160MHZ; ++ eht_oper_info.ccfs0 = ++ PRIMARY_CENTER_CHAN_IDX(new_chan_no, ++ new_seg0, 160); ++ eht_oper_info.ccfs1 = new_seg0; ++ } else if (new_chan_width == IEEE80211_CHANWIDTH_80MHZ) { ++ eht_oper_info.control = IEEE80211_EHT_OPER_CHAN_WIDTH_80MHZ; ++ } ++ + eht_oper.optional[0] = eht_oper_info.control; + eht_oper.optional[1] = eht_oper_info.ccfs0; + eht_oper.optional[2] = eht_oper_info.ccfs1; +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -3641,6 +3641,59 @@ void ieee80211_chandef_eht_oper(struct i + } + } + ++struct ieee80211_channel ++*ieee80211_get_channel_6ghz_pwr_mode(const struct ieee80211_sub_if_data *sdata, ++ const struct ieee80211_he_operation *he_oper, ++ const int new_chan_idx) ++{ ++ enum nl80211_iftype iftype = ieee80211_vif_type_p2p(&sdata->vif); ++ enum nl80211_regulatory_power_modes mode; ++ struct ieee80211_channel *new_chan; ++ const struct ieee80211_he_6ghz_oper *he_6ghz_oper; ++ u8 reg_info; ++ u8 reg_6g_power_mode; ++ u32 new_freq; ++ ++ ++ he_6ghz_oper = ieee80211_he_6ghz_oper(he_oper); ++ ++ if (!he_6ghz_oper) { ++ sdata_info(sdata, ++ "HE 6GHz operation missing (on Channel: %d), expect issues\n", ++ new_chan_idx); ++ return false; ++ } ++ /* 6G Power mode present in the beacon */ ++ reg_info = (he_6ghz_oper->control & IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO) >> ++ IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO_LSB; ++ ++ /* 6G Power mode configured by the user */ ++ reg_6g_power_mode = sdata->wdev.reg_6g_power_mode; ++ ++ /** ++ * For AP/AP_VLAN/MESH_POINT interfaces, the 6G power mode depends on the ++ * mode configured by user (LPI/SP/VLP). For other interfaces (for ex STA) ++ * mode depends on the power mode present in beacon as well as power mode ++ * configured by the user for that interface ++ */ ++ if (iftype == NL80211_IFTYPE_AP || iftype == NL80211_IFTYPE_AP_VLAN || ++ iftype == NL80211_IFTYPE_MESH_POINT) { ++ mode = reg_6g_power_mode; ++ } else ++ mode = GET_POWER_MODE_FOR_NON_AP_STA(reg_6g_power_mode, reg_info); ++ ++ /* ++ * The EHT operation IE does not contain the primary channel so the ++ * primary channel frequency should be taken from the 6 GHz operation ++ * information. ++ */ ++ new_freq = ieee80211_channel_to_frequency(new_chan_idx, ++ NL80211_BAND_6GHZ); ++ new_chan = ieee80211_get_6g_channel_khz(sdata->local->hw.wiphy, ++ MHZ_TO_KHZ(new_freq), mode); ++ return new_chan; ++} ++ + bool ieee80211_chandef_he_6ghz_oper(struct ieee80211_sub_if_data *sdata, + const struct ieee80211_he_operation *he_oper, + const struct ieee80211_eht_operation *eht_oper, +--- a/net/wireless/util.c ++++ b/net/wireless/util.c +@@ -1811,6 +1811,7 @@ bool ieee80211_operating_class_to_band(u + *band = NL80211_BAND_5GHZ; + return true; + case 131 ... 135: ++ case 137: + *band = NL80211_BAND_6GHZ; + return true; + case 81: +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -1283,7 +1283,7 @@ static int cmp_bss(struct cfg80211_bss * + const u8 *ie2 = NULL; + int i, r; + +- if (a->channel != b->channel) ++ if (!cfg80211_channel_identical(a->channel, b->channel)) + return b->channel->center_freq - a->channel->center_freq; + + a_ies = rcu_access_pointer(a->ies); diff --git a/feeds/ipq95xx/mac80211/patches/qca/675-01-cfg80211-Extend-interface-combination-advertisement-.patch b/feeds/ipq95xx/mac80211/patches/qca/675-01-cfg80211-Extend-interface-combination-advertisement-.patch new file mode 100644 index 000000000..7bd755530 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/675-01-cfg80211-Extend-interface-combination-advertisement-.patch @@ -0,0 +1,1613 @@ +From 1c326ee47eb453b884aa0436916f73c458e1a7f3 Mon Sep 17 00:00:00 2001 +From: Vasanthakumar Thiagarajan +Date: Sat, 8 Oct 2022 13:59:17 +0530 +Subject: [PATCH 1/3] cfg80211/mac80211: extend iface comb +advertisement for multi-hardware dev + +When driver combines multiple discrete hardware under one wiphy, it is +required for the driver to be able to advertise iface combination +capabilities per underlying physical hardware. Iface combination for each +underlying hardware is described with an identifier, the same index which +is used in wiphy->hw_chans[] to learn the channel capabilities of the +respective hardware. It should be noted that the supporting drivers also +need to signal the iface comb capabilities that are common for all the +hardware through the existing interface to maintain the backward +compatibility with the user space. Provision to advertise per physical +hardware specific iface comb capabilities and the sanity checks on the +advertised capabilities are implemented in this commit. + +Example: + +Say driver abstracts two discrete hardware under one wiphy, +wiphy->hw_chans[0] supporting 2 GHz and wiphy->hw_chans[1] supporting +5 GHz. Each hardware can operate on only one channel at any given time +but under the wiphy there can be concurrent interfaces on both the radios. +2 GHz hardware supports #STA <= 1, #AP <= 3 total 4 and 5 GHz hardware +supports #STA <= 1, #AP <= 4 total 5 + +struct ieee80211_iface_limit limits_common[] = { + { .max = 1, .types = BIT(NL80211_IFTYPE_STATION), }, + { .max = 3, .types = BIT(NL80211_IFTYPE_AP), }, +}; + +limits_common[] defines the minimum (common) capability out of all the +underlying hardware specific capabilities. This is reported in the existing +advertisement mechanism. Common max_interfaces across 2 GHz and 5 GHz is 4, +common num_different_channels is 1. + +struct ieee80211_iface_limit limits_2ghz[] = { + { .max = 1, .types = BIT(NL80211_IFTYPE_STATION), }, + { .max = 3, .types = BIT(NL80211_IFTYPE_AP), }, +}; + +struct ieee80211_iface_limit limits_5ghz[] = { + { .max = 1, .types = BIT(NL80211_IFTYPE_STATION), }, + { .max = 4, .types = BIT(NL80211_IFTYPE_AP), }, +}; + +struct ieee80211_iface_combination combination = { + .limits = limits_common, + .max_interfaces = 4, + .num_different_channels = 1, + ... + .freq_range = { + { + .hw_chan_idx = 0, + .limits = limits_2ghz, + .max_interfaces = 4, + .num_different_channels = 1, + .n_limits = ARRAY_SIZE(limits_2ghz), + }, + { + .hw_chan_idx = 1, + .limits = limits_5ghz, + .max_interfaces = 5, + .num_different_channels = 1, + .n_limits = ARRAY_SIZE(limits_5ghz), + }, + }, +}; + +Signed-off-by: Vasanthakumar Thiagarajan +--- + include/net/cfg80211.h | 188 +++++++++++++++++++- + net/mac80211/chan.c | 29 ++- + net/mac80211/ieee80211_i.h | 5 +- + net/mac80211/main.c | 58 ++++++ + net/mac80211/util.c | 315 ++++++++++++++++++++++++++------ + net/wireless/core.c | 265 ++++++++++++++++++++++----- + net/wireless/util.c | 356 +++++++++++++++++++++++++++++++++---- + 7 files changed, 1073 insertions(+), 143 deletions(-) + +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -1486,27 +1486,60 @@ struct cfg80211_color_change_settings { + }; + + /** ++ * struct iface_comb_per_hw_params - HW specific interface combinations input ++ * ++ * Used to pass per-hw interface combination parameters ++ * ++ * @num_different_channels: the number of different channels we want to use ++ * with in the per-hw supported channels. ++ * @iftype_num: array with the number of interfaces of each interface ++ * type. The index is the interface type as specified in &enum ++ * nl80211_iftype. ++ */ ++ ++struct iface_comb_per_hw_params { ++ int num_different_channels; ++ int iftype_num[NUM_NL80211_IFTYPES]; ++}; ++ ++/** + * struct iface_combination_params - input parameters for interface combinations + * + * Used to pass interface combination parameters + * + * @num_different_channels: the number of different channels we want +- * to use for verification ++ * to use for verification, not applicable when hw specific interface ++ * combination parameters are passed in @per_hw_params + * @radar_detect: a bitmap where each bit corresponds to a channel + * width where radar detection is needed, as in the definition of + * &struct ieee80211_iface_combination.@radar_detect_widths + * @iftype_num: array with the number of interfaces of each interface + * type. The index is the interface type as specified in &enum +- * nl80211_iftype. ++ * nl80211_iftype. This will hold the interfaces which are not ++ * yet assigned a channel when hw specific interface combination ++ * is passed in @per_hw_params. + * @new_beacon_int: set this to the beacon interval of a new interface + * that's not operating yet, if such is to be checked as part of + * the verification ++ * @per_hw: underlying hw specific interface combinations. Per-hw channel ++ * list index as advertised in wiphy @hw_chans is used as index ++ * in @per_hw to maintain the interface combination of the corresponding ++ * hw. ++ * @chandef: Channel definition for which the interface combination is to be ++ * checked, when checking during interface preparation on a new channel, ++ * for example. This will be used when the driver advertises underlying ++ * hw specific interface combination in a multi-mac device. This will be ++ * NULL when the interface combination check is not due to channel or the ++ * interface combination does not include per-hw advertisement. ++ * + */ + struct iface_combination_params { + int num_different_channels; + u8 radar_detect; + int iftype_num[NUM_NL80211_IFTYPES]; + u32 new_beacon_int; ++ struct iface_comb_per_hw_params *per_hw; ++ const struct cfg80211_chan_def *chandef; + }; + + /** +@@ -4796,6 +4829,32 @@ struct ieee80211_iface_limit { + }; + + /** ++ * strucieee80211_iface_per_hw - hardware specific interface combination ++ * ++ * Drivers registering multiple radios under a single wiphy can advertise ++ * radio specific interface combinations through this structure. Please note ++ * that to maintain the compatibility with the user space which is not aware ++ * of this extension of per-hardware interface combination signaling, ++ * the driver should still advertise it's interface combination (mostly ++ * common minimum capability) using the existing interface combination signaling ++ * method. ++ * ++ * @hw_chans_idx: index of hardware specific channel list as per wiphy @hw_chans ++ * @limits: limits for the given interface type ++ * @num_different_channels: number of different channels which can be active ++ * concurrently in this hw ++ * @max_interfaces: maximum number of total interfaces allowed in this group ++ * @n_limits: number of limitations ++ */ ++struct ieee80211_iface_per_hw { ++ u8 hw_chans_idx; ++ const struct ieee80211_iface_limit *limits; ++ u32 num_different_channels; ++ u16 max_interfaces; ++ u8 n_limits; ++}; ++ ++/** + * struct ieee80211_iface_combination - possible interface combination + * + * With this structure the driver can describe which interface +@@ -4853,6 +4912,62 @@ struct ieee80211_iface_limit { + * .num_different_channels = 2, + * }; + * ++ * ++ * 4. Hardware specific interface combination with driver supporting two hw ++ * (MAC), one underlying MAC supporting 2 GHz band and the other supporting ++ * 5 GHz band. ++ * ++ * Allow #STA <= 1, #AP <= 1, channels = 1, total 2 in 2 GHz radio and ++ * ++ * Allow #STA <= 1, #AP <= 2, channels = 1, total 3 in 5 GHz radio ++ * ++ * Drivers advertising per-hardware interface combination should also ++ * advertise a sub-set of capabilities using existing interface mainly for ++ * maintaining compatibility with the user space which is not aware of the ++ * new per-hardware advertisement. ++ * ++ * Sub-set interface combination advertised in the existing infrastructure: ++ * Allow #STA <= 1, #AP <= 1, channel = 1, total 2 ++ * ++ * .. code-block:: c ++ * ++ * struct ieee80211_iface_limit limits4[] = { ++ * { .max = 1, .types = BIT(NL80211_IFTYPE_STATION), }, ++ * { .max = 1, .types = BIT(NL80211_IFTYPE_AP), }, ++ * }; ++ * struct ieee80211_iface_limit limits5_2ghz[] = { ++ * { .max = 1, .types = BIT(NL80211_IFTYPE_STATION), }, ++ * { .max = 1, .types = BIT(NL80211_IFTYPE_AP), }, ++ * }; ++ * struct ieee80211_iface_limit limits5_5ghz[] = { ++ * { .max = 1, .types = BIT(NL80211_IFTYPE_STATION), }, ++ * { .max = 2, .types = BIT(NL80211_IFTYPE_AP), }, ++ * }; ++ * struct ieee80211_iface_per_hw hw_combinations[] = { ++ * { ++ * .hw_chans_idx = 0, ++ * .limits = limits5_2ghz, ++ * .num_different_channels = 1, ++ * .max_interfaces = 2, ++ * .n_limits = ARRAY_SIZE(limits5_2ghz), ++ * }, ++ * { ++ * .hw_chans_idx = 1, ++ * .limits = limits5_5ghz, ++ * .num_different_channels = 1, ++ * .max_interfaces = 3, ++ * .n_limits = ARRAY_SIZE(limits5_5ghz), ++ * }, ++ * }; ++ * struct ieee80211_iface_combination combination4 = { ++ * .limits = limits4, ++ * .n_limits = ARRAY_SIZE(limits4), ++ * .max_interfaces = 2, ++ * .num_different_channels = 1, ++ * .iface_hw_list = hw_combinations, ++ * .n_hw_list = ARRAY_SIZE(hw_combinations), ++ * }; ++ * + */ + struct ieee80211_iface_combination { + /** +@@ -4910,6 +5025,20 @@ struct ieee80211_iface_combination { + * combination must be greater or equal to this value. + */ + u32 beacon_int_min_gcd; ++ ++ /** ++ * @iface_hw_list: ++ * This wiphy has multiple underlying radios, describe interface ++ * combination for each of them, valid only when the driver advertises ++ * multi-radio presence in wiphy @hw_chans. ++ */ ++ const struct ieee80211_iface_per_hw *iface_hw_list; ++ ++ /** ++ * @n_hw_list: ++ * number of hardware in @iface_hw_List ++ */ ++ u32 n_hw_list; + }; + + struct ieee80211_txrx_stypes { +@@ -5158,6 +5287,18 @@ struct wiphy_iftype_akm_suites { + }; + + /** ++ * struct ieee80211_supported_chans_per_hw - supported channels as per the ++ * underlying constituent hw configuration ++ * ++ * @n_chans: number of channels in @chans ++ * @chans: list of channels supported by the constituent hw ++ */ ++struct ieee80211_chans_per_hw { ++ int n_chans; ++ struct ieee80211_channel chans[]; ++}; ++ ++/** + * struct wiphy - wireless hardware description + * @mtx: mutex for the data (structures) of this device + * @reg_notifier: the driver's regulatory notification callback, +@@ -5370,6 +5511,13 @@ struct wiphy_iftype_akm_suites { + * @ru_punct_supp_bw: Whether the driver supports RU puncturing, and if so, + * for which bandwidths. See &enum nl80211_ru_punct_supp_bw for the + * possible values for this field. ++ * @hw_chans: list of the channels supported by every constituent underlying hw. ++ * The drivers registering multiple radios under the a wiphy can advertise ++ * the list of channels supported by each hw in this list. Undelying hw ++ * specific channel list can be used while describing interface combination ++ * for each of the underlying hw. ++ * @num_hw: number of underlying hw for which the channels list are advertised ++ * in @hw_chans. + */ + struct wiphy { + struct mutex mtx; +@@ -5525,6 +5673,9 @@ struct wiphy { + + enum nl80211_ru_punct_supp_bw ru_punct_supp_bw; + ++ struct ieee80211_chans_per_hw **hw_chans; ++ int num_hw; ++ + char priv[] __aligned(NETDEV_ALIGN); + }; + +@@ -8682,9 +8833,32 @@ int cfg80211_check_combinations(struct w + int cfg80211_iter_combinations(struct wiphy *wiphy, + struct iface_combination_params *params, + void (*iter)(const struct ieee80211_iface_combination *c, +- void *data), ++ void *data, int hw_chan_idx), + void *data); + ++/** ++ * cfg80211_per_hw_iface_comb_advertised - if per-hw iface combination supported ++ * ++ * @wiphy: the wiphy ++ * ++ * This function is used to check underlying per-hw interface combination is ++ * advertised by the driver. ++ */ ++bool cfg80211_per_hw_iface_comb_advertised(struct wiphy *wiphy); ++ ++/** ++ * cfg80211_get_hw_idx_by_chan - get the hw index by the channel ++ * ++ * @wiphy: the wiphy ++ * @chandef: channel definition for which the supported hw index is ++ * required ++ * ++ * returns -1 in case the channel is not supported by any of the constituent ++ * hw ++ */ ++int cfg80211_get_hw_idx_by_chan(struct wiphy *wiphy, ++ const struct cfg80211_chan_def *chandef); ++ + /* + * cfg80211_stop_iface - trigger interface disconnection + * +@@ -8878,6 +9052,16 @@ bool cfg80211_iftype_allowed(struct wiph + void cfg80211_assoc_comeback(struct net_device *netdev, + const u8 *ap_addr, u32 timeout); + ++/** ++ * cfg80211_hw_chans_includes_dfs - check if per-hardware channel includes DFS ++ * @chans: hardware channel list ++ * ++ * Check if the given per-hardware list includes channels in DFS range. ++ * Please note the channel is checked against the entire range of DFS ++ * freq in 5 GHz irrespective of regulatory configurations. ++ */ ++bool cfg80211_hw_chans_includes_dfs(const struct ieee80211_chans_per_hw *chans); ++ + /* Logging, debugging and troubleshooting/diagnostic helpers. */ + + /* wiphy_printk helpers, similar to dev_printk */ +--- a/net/mac80211/chan.c ++++ b/net/mac80211/chan.c +@@ -47,26 +47,41 @@ int ieee80211_chanctx_refcount(struct ie + ieee80211_chanctx_num_reserved(local, ctx); + } + +-static int ieee80211_num_chanctx(struct ieee80211_local *local) ++static int ieee80211_num_chanctx(struct ieee80211_local *local, ++ const struct cfg80211_chan_def *chandef) + { + struct ieee80211_chanctx *ctx; + int num = 0; ++ int hw_idx, ctx_idx; + + lockdep_assert_held(&local->chanctx_mtx); + +- list_for_each_entry(ctx, &local->chanctx_list, list) +- num++; ++ hw_idx = cfg80211_get_hw_idx_by_chan(local->hw.wiphy, chandef); ++ ++ list_for_each_entry(ctx, &local->chanctx_list, list) { ++ if (hw_idx < 0) ++ num++; ++ else { ++ ctx_idx = ++ cfg80211_get_hw_idx_by_chan(local->hw.wiphy, ++ &ctx->conf.def); ++ if (ctx_idx == hw_idx) ++ num++; ++ } ++ } + + return num; + } + +-static bool ieee80211_can_create_new_chanctx(struct ieee80211_local *local) ++static bool ieee80211_can_create_new_chanctx(struct ieee80211_local *local, ++ const struct cfg80211_chan_def *chandef) + { + lockdep_assert_held(&local->chanctx_mtx); +- return ieee80211_num_chanctx(local) < ieee80211_max_num_channels(local); ++ return ieee80211_num_chanctx(local, chandef) < ++ ieee80211_max_num_channels(local, chandef); + } + +-static struct ieee80211_chanctx * ++struct ieee80211_chanctx * + ieee80211_link_get_chanctx(struct ieee80211_link_data *link) + { + struct ieee80211_local *local __maybe_unused = link->sdata->local; +@@ -1099,7 +1114,7 @@ int ieee80211_link_reserve_chanctx(struc + + new_ctx = ieee80211_find_reservation_chanctx(local, chandef, mode); + if (!new_ctx) { +- if (ieee80211_can_create_new_chanctx(local)) { ++ if (ieee80211_can_create_new_chanctx(local, chandef)) { + new_ctx = ieee80211_new_chanctx(local, chandef, mode); + if (IS_ERR(new_ctx)) + return PTR_ERR(new_ctx); +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -2500,6 +2500,8 @@ void ieee80211_link_copy_chanctx_to_vlan + bool clear); + int ieee80211_chanctx_refcount(struct ieee80211_local *local, + struct ieee80211_chanctx *ctx); ++struct ieee80211_chanctx * ++ieee80211_link_get_chanctx(struct ieee80211_link_data *link); + + void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, + struct ieee80211_chanctx *chanctx); +@@ -2521,7 +2523,8 @@ int ieee80211_check_combinations(struct + const struct cfg80211_chan_def *chandef, + enum ieee80211_chanctx_mode chanmode, + u8 radar_detect); +-int ieee80211_max_num_channels(struct ieee80211_local *local); ++int ieee80211_max_num_channels(struct ieee80211_local *local, ++ const struct cfg80211_chan_def *chandef); + void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local, + struct ieee80211_chanctx *ctx); + +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -939,6 +939,45 @@ static int ieee80211_init_cipher_suites( + return 0; + } + ++static int ++ieee80211_check_per_hw_iface_comb(struct ieee80211_local *local, ++ const struct ieee80211_iface_combination *c) ++{ ++ int h, l; ++ u32 hw_idx_bm = 0; ++ ++ if (!local->use_chanctx) ++ return -EINVAL; ++ ++ for (h = 0; h < c->n_hw_list; h++) { ++ const struct ieee80211_iface_per_hw *hl; ++ const struct ieee80211_chans_per_hw *chans; ++ ++ hl = &c->iface_hw_list[h]; ++ ++ if (hl->hw_chans_idx >= local->hw.wiphy->num_hw) ++ return -EINVAL; ++ ++ chans = local->hw.wiphy->hw_chans[hl->hw_chans_idx]; ++ if (c->radar_detect_widths && ++ cfg80211_hw_chans_includes_dfs(chans) && ++ hl->num_different_channels > 1) ++ return -EINVAL; ++ ++ for (l = 0; l < hl->n_limits; l++) ++ if ((hl->limits[l].types & BIT(NL80211_IFTYPE_ADHOC)) && ++ hl->limits[l].max > 1) ++ return -EINVAL; ++ ++ if (hw_idx_bm & BIT(h)) ++ return -EINVAL; ++ ++ hw_idx_bm |= BIT(h); ++ } ++ ++ return 0; ++} ++ + int ieee80211_register_hw(struct ieee80211_hw *hw) + { + struct ieee80211_local *local = hw_to_local(hw); +@@ -1053,6 +1092,25 @@ int ieee80211_register_hw(struct ieee802 + } + } + ++ for (i = 0; i < local->hw.wiphy->n_iface_combinations; i++) { ++ const struct ieee80211_iface_combination *comb; ++ ++ comb = &local->hw.wiphy->iface_combinations[i]; ++ ++ if (comb->n_hw_list && !local->hw.wiphy->num_hw) ++ return -EINVAL; ++ ++ if (!comb->n_hw_list) ++ continue; ++ ++ /* ++ * Run through similar validations on the per-hardware ++ * interface combinations, if advertised. ++ */ ++ if (ieee80211_check_per_hw_iface_comb(local, comb)) ++ return -EINVAL; ++ } ++ + /* Only HW csum features are currently compatible with mac80211 */ + if (WARN_ON(hw->netdev_features & ~MAC80211_SUPPORTED_FEATURES)) + return -EINVAL; +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -4733,16 +4733,174 @@ static u8 ieee80211_chanctx_radar_detect + return radar_detect; + } + ++static void ++ieee80211_prepare_iface_combination(struct ieee80211_sub_if_data *sdata, ++ const struct cfg80211_chan_def *chandef, ++ enum ieee80211_chanctx_mode chanmode, ++ struct iface_combination_params *params, ++ int *total) ++{ ++ struct ieee80211_local *local = sdata->local; ++ struct ieee80211_sub_if_data *sdata_iter; ++ enum nl80211_iftype iftype = sdata->wdev.iftype; ++ struct ieee80211_chanctx *ctx; ++ ++ lockdep_assert_held(&local->chanctx_mtx); ++ ++ if (chandef) ++ params->num_different_channels = 1; ++ ++ if (iftype != NL80211_IFTYPE_UNSPECIFIED) ++ params->iftype_num[iftype] = 1; ++ ++ list_for_each_entry(ctx, &local->chanctx_list, list) { ++ if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED) ++ continue; ++ params->radar_detect |= ++ ieee80211_chanctx_radar_detect(local, ctx); ++ if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) { ++ params->num_different_channels++; ++ continue; ++ } ++ if (chandef && chanmode == IEEE80211_CHANCTX_SHARED && ++ cfg80211_chandef_compatible(chandef, ++ &ctx->conf.def)) ++ continue; ++ params->num_different_channels++; ++ } ++ ++ list_for_each_entry_rcu(sdata_iter, &local->interfaces, list) { ++ struct wireless_dev *wdev_iter; ++ ++ wdev_iter = &sdata_iter->wdev; ++ ++ if (sdata_iter == sdata || ++ !ieee80211_sdata_running(sdata_iter) || ++ cfg80211_iftype_allowed(local->hw.wiphy, ++ wdev_iter->iftype, 0, 1)) ++ continue; ++ ++ params->iftype_num[wdev_iter->iftype]++; ++ (*total)++; ++ } ++} ++ ++static void ++ieee80211_get_per_hw_sdata_active_iface(struct ieee80211_sub_if_data *sdata, ++ struct iface_combination_params *params, ++ int *total) ++{ ++ struct ieee80211_local *local = sdata->local; ++ unsigned int link_id; ++ int idx; ++ ++ for (link_id = 0; link_id < ARRAY_SIZE(sdata->link); link_id++) { ++ struct ieee80211_link_data *link; ++ struct ieee80211_chanctx *ctx; ++ ++ link = sdata_dereference(sdata->link[link_id], sdata); ++ if (!link) ++ continue; ++ ++ ctx = ieee80211_link_get_chanctx(link); ++ if (ctx && ++ ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED) ++ ctx = ctx->replace_ctx; ++ ++ idx = -1; ++ if (ctx) ++ idx = cfg80211_get_hw_idx_by_chan(local->hw.wiphy, ++ &ctx->conf.def); ++ ++ if (idx >= 0) ++ params->per_hw[idx].iftype_num[sdata->wdev.iftype]++; ++ else ++ params->iftype_num[sdata->wdev.iftype]++; ++ ++ if (total) ++ (*total)++; ++ } ++} ++ ++static int ++ieee80211_prepare_per_hw_iface_combination(struct ieee80211_sub_if_data *sdata, ++ const struct cfg80211_chan_def *chandef, ++ enum ieee80211_chanctx_mode chanmode, ++ struct iface_combination_params *params, ++ int *total) ++{ ++ struct ieee80211_local *local = sdata->local; ++ struct ieee80211_sub_if_data *sdata_iter; ++ enum nl80211_iftype iftype = sdata->wdev.iftype; ++ struct ieee80211_chanctx *ctx; ++ int hchan_idx; ++ size_t size; ++ bool sdata_included = false; ++ ++ lockdep_assert_held(&local->chanctx_mtx); ++ ++ size = sizeof(*params->per_hw) * local->hw.wiphy->num_hw; ++ /* caller should free this memory upon success status */ ++ params->per_hw = kzalloc(size, GFP_KERNEL); ++ if (!params->per_hw) ++ return -ENOMEM; ++ ++ hchan_idx = cfg80211_get_hw_idx_by_chan(local->hw.wiphy, chandef); ++ if (hchan_idx >= 0) { ++ params->per_hw[hchan_idx].num_different_channels = 1; ++ if (iftype != NL80211_IFTYPE_UNSPECIFIED) { ++ params->per_hw[hchan_idx].iftype_num[iftype] = 1; ++ sdata_included = true; ++ } ++ } ++ ++ list_for_each_entry(ctx, &local->chanctx_list, list) { ++ if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED) ++ continue; ++ hchan_idx = cfg80211_get_hw_idx_by_chan(local->hw.wiphy, ++ &ctx->conf.def); ++ if (WARN_ON(hchan_idx < 0)) ++ continue; ++ ++ params->radar_detect |= ++ ieee80211_chanctx_radar_detect(local, ctx); ++ if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) { ++ params->per_hw[hchan_idx].num_different_channels++; ++ continue; ++ } ++ if (chandef && chanmode == IEEE80211_CHANCTX_SHARED && ++ cfg80211_chandef_compatible(chandef, ++ &ctx->conf.def)) ++ continue; ++ params->per_hw[hchan_idx].num_different_channels++; ++ } ++ ++ list_for_each_entry_rcu(sdata_iter, &local->interfaces, list) { ++ struct wireless_dev *wdev_iter; ++ ++ wdev_iter = &sdata_iter->wdev; ++ ++ if ((sdata_included && sdata_iter == sdata) || ++ !ieee80211_sdata_running(sdata_iter) || ++ cfg80211_iftype_allowed(local->hw.wiphy, ++ wdev_iter->iftype, 0, 1)) ++ continue; ++ ++ ieee80211_get_per_hw_sdata_active_iface(sdata_iter, params, ++ total); ++ } ++ ++ return 0; ++} ++ + int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata, + const struct cfg80211_chan_def *chandef, + enum ieee80211_chanctx_mode chanmode, + u8 radar_detect) + { + struct ieee80211_local *local = sdata->local; +- struct ieee80211_sub_if_data *sdata_iter; + enum nl80211_iftype iftype = sdata->wdev.iftype; +- struct ieee80211_chanctx *ctx; +- int total = 1; ++ int total = 1, ret; + struct iface_combination_params params = { + .radar_detect = radar_detect, + }; +@@ -4776,73 +4934,119 @@ int ieee80211_check_combinations(struct + return 0; + } + +- if (chandef) +- params.num_different_channels = 1; ++ if (cfg80211_per_hw_iface_comb_advertised(local->hw.wiphy)) { ++ ret = ieee80211_prepare_per_hw_iface_combination(sdata, chandef, ++ chanmode, ++ ¶ms, ++ &total); ++ if (ret) ++ return ret; ++ } else { ++ ieee80211_prepare_iface_combination(sdata, chandef, chanmode, ++ ¶ms, &total); ++ } + +- if (iftype != NL80211_IFTYPE_UNSPECIFIED) +- params.iftype_num[iftype] = 1; ++ if (total == 1 && !params.radar_detect) { ++ kfree(params.per_hw); ++ return 0; ++ } ++ ++ ret = cfg80211_check_combinations(local->hw.wiphy, ¶ms); ++ ++ kfree(params.per_hw); ++ ++ return ret; ++} ++ ++ ++static void ++ieee80211_iter_max_chans(const struct ieee80211_iface_combination *c, ++ void *data, int hw_chan_idx) ++{ ++ u32 *max_num_different_channels = data; ++ ++ *max_num_different_channels = max(*max_num_different_channels, ++ c->num_different_channels); ++} ++ ++static void ++ieee80211_iter_per_hw_max_chans(const struct ieee80211_iface_combination *c, ++ void *data, int hw_chan_idx) ++{ ++ u32 *max_num_different_channels = data; ++ u32 max_supported_different_channels = 0; ++ int i; ++ ++ for (i = 0; i < c->n_hw_list; i++) { ++ const struct ieee80211_iface_per_hw *h; ++ ++ h = &c->iface_hw_list[i]; ++ if (hw_chan_idx != -1) { ++ if (h->hw_chans_idx == hw_chan_idx) { ++ max_supported_different_channels = ++ h->num_different_channels; ++ break; ++ } ++ continue; ++ } ++ max_supported_different_channels += h->num_different_channels; ++ } ++ ++ *max_num_different_channels = max(*max_num_different_channels, ++ max_supported_different_channels); ++} + ++static int ++ieee80211_max_num_channels_hw_list(struct ieee80211_local *local, ++ const struct cfg80211_chan_def *chandef) ++{ ++ struct ieee80211_sub_if_data *sdata; ++ struct ieee80211_chanctx *ctx; ++ u32 max_num_different_channels = 1; ++ size_t size; ++ int err, hchan_idx; ++ struct iface_combination_params params = {0}; ++ ++ size = sizeof(*params.per_hw) * local->hw.wiphy->num_hw; ++ /* caller should free this memory */ ++ params.per_hw = kzalloc(size, GFP_KERNEL); ++ if (!params.per_hw) ++ return -ENOMEM; ++ ++ params.chandef = chandef; + list_for_each_entry(ctx, &local->chanctx_list, list) { + if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED) + continue; ++ hchan_idx = cfg80211_get_hw_idx_by_chan(local->hw.wiphy, ++ &ctx->conf.def); ++ if (WARN_ON(hchan_idx < 0)) ++ continue; ++ + params.radar_detect |= + ieee80211_chanctx_radar_detect(local, ctx); +- if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) { +- params.num_different_channels++; +- continue; +- } +- if (chandef && chanmode == IEEE80211_CHANCTX_SHARED) { +- /* 6 GHz chandefs could be different for different +- * interfaces beacuse of operating power modes. +- * Hence, we skip the chandef compatibility check. +- */ +- enum nl80211_band chan_band = chandef->chan->band; +- bool is_6ghz_band = chan_band == NL80211_BAND_6GHZ +- ? true : false; +- +- if (is_6ghz_band) +- continue; +- +- if (!is_6ghz_band && +- cfg80211_chandef_compatible(chandef, +- &ctx->conf.def)) +- continue; +- } +- params.num_different_channels++; ++ params.per_hw[hchan_idx].num_different_channels++; + } + +- list_for_each_entry_rcu(sdata_iter, &local->interfaces, list) { +- struct wireless_dev *wdev_iter; +- +- wdev_iter = &sdata_iter->wdev; ++ list_for_each_entry_rcu(sdata, &local->interfaces, list) { ++ struct wireless_dev *wdev = &sdata->wdev; + +- if (sdata_iter == sdata || +- !ieee80211_sdata_running(sdata_iter) || ++ if(!ieee80211_sdata_running(sdata) || + cfg80211_iftype_allowed(local->hw.wiphy, +- wdev_iter->iftype, 0, 1)) ++ wdev->iftype, 0, 1)) + continue; +- +- params.iftype_num[wdev_iter->iftype]++; +- total++; ++ ieee80211_get_per_hw_sdata_active_iface(sdata, ¶ms, NULL); + } + +- if (total == 1 && !params.radar_detect) +- return 0; +- +- return cfg80211_check_combinations(local->hw.wiphy, ¶ms); +-} +- +-static void +-ieee80211_iter_max_chans(const struct ieee80211_iface_combination *c, +- void *data) +-{ +- u32 *max_num_different_channels = data; ++ err = cfg80211_iter_combinations(local->hw.wiphy, ¶ms, ++ ieee80211_iter_per_hw_max_chans, ++ &max_num_different_channels); ++ kfree(params.per_hw); + +- *max_num_different_channels = max(*max_num_different_channels, +- c->num_different_channels); ++ return err < 0 ? err : max_num_different_channels; + } + +-int ieee80211_max_num_channels(struct ieee80211_local *local) ++int ieee80211_max_num_channels(struct ieee80211_local *local, ++ const struct cfg80211_chan_def *chandef) + { + struct ieee80211_sub_if_data *sdata; + struct ieee80211_chanctx *ctx; +@@ -4852,6 +5056,9 @@ int ieee80211_max_num_channels(struct ie + + lockdep_assert_held(&local->chanctx_mtx); + ++ if (cfg80211_per_hw_iface_comb_advertised(local->hw.wiphy)) ++ return ieee80211_max_num_channels_hw_list(local, chandef); ++ + list_for_each_entry(ctx, &local->chanctx_list, list) { + if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED) + continue; +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -570,10 +570,125 @@ use_default_name: + } + EXPORT_SYMBOL(wiphy_new_nm); + ++static int ++wiphy_verify_comb_limit(struct wiphy *wiphy, ++ const struct ieee80211_iface_limit *limits, ++ u8 n_limits, u32 bcn_int_min_gcd, u32 *iface_cnt, ++ u16 *all_iftypes) ++{ ++ int l; ++ ++ for (l = 0; l < n_limits; l++) { ++ u16 types = limits[l].types; ++ ++ /* ++ * Don't advertise an unsupported type ++ * in a combination. ++ */ ++ if (WARN_ON((wiphy->interface_modes & types) != types)) ++ return -EINVAL; ++ ++ /* interface types shouldn't overlap */ ++ if (WARN_ON(types & *all_iftypes)) ++ return -EINVAL; ++ ++ *all_iftypes |= types; ++ ++ /* Shouldn't list software iftypes in combinations! */ ++ if (WARN_ON(wiphy->software_iftypes & types)) ++ return -EINVAL; ++ ++ /* Only a single P2P_DEVICE can be allowed */ ++ if (WARN_ON(types & BIT(NL80211_IFTYPE_P2P_DEVICE) && ++ limits[l].max > 1)) ++ return -EINVAL; ++ ++ /* Only a single NAN can be allowed */ ++ if (WARN_ON(types & BIT(NL80211_IFTYPE_NAN) && ++ limits[l].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) && ++ bcn_int_min_gcd)) ++ return -EINVAL; ++ ++ *iface_cnt += limits[l].max; ++ } ++ ++ return 0; ++} ++ ++static int ++wiphy_verify_comb_per_hw(struct wiphy *wiphy, ++ const struct ieee80211_iface_combination *comb) ++{ ++ int h; ++ u32 hw_idx_bitmap = 0; ++ int ret; ++ ++ for (h = 0; h < comb->n_hw_list; h++) { ++ const struct ieee80211_iface_per_hw *hl; ++ const struct ieee80211_chans_per_hw *chans; ++ u32 iface_cnt = 0; ++ u16 all_iftypes = 0; ++ ++ hl = &comb->iface_hw_list[h]; ++ ++ if (hl->hw_chans_idx >= wiphy->num_hw) ++ return -EINVAL; ++ ++ if (hw_idx_bitmap & BIT(hl->hw_chans_idx)) ++ return -EINVAL; ++ ++ hw_idx_bitmap |= BIT(hl->hw_chans_idx); ++ chans = wiphy->hw_chans[hl->hw_chans_idx]; ++ ++ if (WARN_ON(hl->max_interfaces < 2 && (!comb->radar_detect_widths || ++ !(cfg80211_hw_chans_includes_dfs(chans))))) ++ return -EINVAL; ++ ++ if (WARN_ON(!hl->num_different_channels)) ++ return -EINVAL; ++ ++ if (WARN_ON(comb->radar_detect_widths && ++ cfg80211_hw_chans_includes_dfs(chans) && ++ hl->num_different_channels > 1)) ++ return -EINVAL; ++ ++ if (WARN_ON(!hl->n_limits)) ++ return -EINVAL; ++ ++ ret = wiphy_verify_comb_limit(wiphy, hl->limits, hl->n_limits, ++ comb->beacon_int_min_gcd, ++ &iface_cnt, &all_iftypes); ++ if (ret) ++ return ret; ++ ++ if (WARN_ON(all_iftypes & BIT(NL80211_IFTYPE_WDS))) ++ return -EINVAL; ++ ++ if (WARN_ON(iface_cnt < comb->max_interfaces)) ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ + static int wiphy_verify_combinations(struct wiphy *wiphy) + { + const struct ieee80211_iface_combination *c; +- int i, j; ++ int i; ++ int ret; + + for (i = 0; i < wiphy->n_iface_combinations; i++) { + u32 cnt = 0; +@@ -600,61 +715,127 @@ static int wiphy_verify_combinations(str + if (WARN_ON(!c->n_limits)) + return -EINVAL; + +- for (j = 0; j < c->n_limits; j++) { +- u16 types = c->limits[j].types; ++ ret = wiphy_verify_comb_limit(wiphy, c->limits, c->n_limits, ++ c->beacon_int_min_gcd, ++ &cnt, &all_iftypes); ++ if (ret) ++ return ret; + +- /* interface types shouldn't overlap */ +- if (WARN_ON(types & all_iftypes)) +- return -EINVAL; +- all_iftypes |= types; ++ if (WARN_ON(all_iftypes & BIT(NL80211_IFTYPE_WDS))) ++ return -EINVAL; + +- if (WARN_ON(!c->limits[j].max)) +- return -EINVAL; ++ /* You can't even choose that many! */ ++ if (WARN_ON(cnt < c->max_interfaces)) ++ return -EINVAL; + +- /* Shouldn't list software iftypes in combinations! */ +- if (WARN_ON(wiphy->software_iftypes & types)) +- return -EINVAL; ++ /* ++ * Do similar validations on the freq range specific interface ++ * combinations when advertised. ++ */ ++ if (WARN_ON(c->n_hw_list && ++ wiphy_verify_comb_per_hw(wiphy, c))) ++ return -EINVAL; ++ } + +- /* Only a single P2P_DEVICE can be allowed */ +- if (WARN_ON(types & BIT(NL80211_IFTYPE_P2P_DEVICE) && +- c->limits[j].max > 1)) +- return -EINVAL; ++ return 0; ++} + +- /* Only a single NAN can be allowed */ +- if (WARN_ON(types & BIT(NL80211_IFTYPE_NAN) && +- c->limits[j].max > 1)) +- return -EINVAL; ++static int cfg80211_check_hw_chans(const struct ieee80211_chans_per_hw *chans1, ++ const struct ieee80211_chans_per_hw *chans2) ++{ ++ int i, j; ++ ++ if (!chans1 || !chans2) ++ 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)) { ++ if (!chans1->n_chans || !chans2->n_chans) ++ return -EINVAL; ++ ++ /* for now same channel is not allowed in more than one sub-hw */ ++ for (i = 0; i < chans1->n_chans; i++) ++ for (j = 0; j < chans2->n_chans; j++) ++ if (chans1->chans[i].center_freq == ++ chans2->chans[j].center_freq) + return -EINVAL; ++ return 0; ++} ++ ++static bool ++cfg80211_hw_chans_in_supported_list(struct wiphy *wiphy, ++ const struct ieee80211_chans_per_hw *chans) ++{ ++ enum nl80211_band band; ++ struct ieee80211_supported_band *sband; ++ bool found; ++ int i, j; ++ ++ for (i = 0; i < chans->n_chans; i++) { ++ found = false; ++ for (band = 0; band < NUM_NL80211_BANDS; band++) { ++ sband = wiphy->bands[band]; ++ if (!sband) ++ continue; ++ for (j = 0; j < sband->n_channels; j++) { ++ if (chans->chans[i].center_freq == ++ sband->channels[j].center_freq) { ++ found = true; ++ break; ++ } + } + +- cnt += c->limits[j].max; +- /* +- * Don't advertise an unsupported type +- * in a combination. +- */ +- if (WARN_ON((wiphy->interface_modes & types) != types)) +- return -EINVAL; ++ if (found) ++ break; + } + +- if (WARN_ON(all_iftypes & BIT(NL80211_IFTYPE_WDS))) +- return -EINVAL; ++ if (!found) ++ return false; ++ } + +- /* You can't even choose that many! */ +- if (WARN_ON(cnt < c->max_interfaces)) ++ return true; ++} ++ ++static int cfg80211_validate_per_hw_chans(struct wiphy *wiphy) ++{ ++ int i, j; ++ int ret; ++ ++ if (!wiphy->num_hw) ++ return 0; ++ ++ if (!wiphy->hw_chans) ++ return -EINVAL; ++ ++ /* ++ * to advertise channel list for one hw, sband alone should ++ * be sufficient ++ */ ++ if (wiphy->num_hw < 2) ++ return -EINVAL; ++ ++ for (i = 0; i < wiphy->num_hw; i++) { ++ for (j = 0; j < wiphy->num_hw; j++) { ++ const struct ieee80211_chans_per_hw *hw_chans1; ++ const struct ieee80211_chans_per_hw *hw_chans2; ++ ++ if (i == j) ++ continue; ++ ++ hw_chans1 = wiphy->hw_chans[i]; ++ hw_chans2 = wiphy->hw_chans[j]; ++ ret = cfg80211_check_hw_chans(hw_chans1, hw_chans2); ++ if (ret) ++ return ret; ++ } ++ } ++ ++ for (i = 0; i < wiphy->num_hw; i++) { ++ const struct ieee80211_chans_per_hw *hw_chans; ++ ++ hw_chans = wiphy->hw_chans[i]; ++ if (!cfg80211_hw_chans_in_supported_list(wiphy, hw_chans)) { ++ WARN_ON(1); + return -EINVAL; ++ } + } + + return 0; +@@ -903,6 +1084,11 @@ int wiphy_register(struct wiphy *wiphy) + NL80211_RU_PUNCT_SUPP_BW_320)) + return -EINVAL; + ++ if (cfg80211_validate_per_hw_chans(&rdev->wiphy)) { ++ WARN_ON(1); ++ return -EINVAL; ++ } ++ + for (i = 0; i < rdev->wiphy.n_vendor_commands; i++) { + /* + * Validate we have a policy (can be explicitly set to +--- a/net/wireless/util.c ++++ b/net/wireless/util.c +@@ -2034,19 +2034,271 @@ int cfg80211_validate_beacon_int(struct + return 0; + } + ++static const struct ieee80211_iface_per_hw * ++cfg80211_get_hw_iface_comb_by_idx(struct wiphy *wiphy, ++ const struct ieee80211_iface_combination *c, ++ int idx) ++{ ++ int i; ++ ++ for (i = 0; i < c->n_hw_list; i++) ++ if (c->iface_hw_list[i].hw_chans_idx == idx) ++ break; ++ ++ if (i == c->n_hw_list) ++ return NULL; ++ ++ return &c->iface_hw_list[i]; ++} ++ ++static int ++cfg80211_validate_per_hw_iface_comb_limits(struct wiphy *wiphy, ++ struct iface_combination_params *params, ++ const struct ieee80211_iface_combination *c, ++ int *num_per_hw_ifaces, u32 *all_iftypes) ++{ ++ struct ieee80211_iface_limit **limits; ++ const struct ieee80211_iface_per_hw *per_hw_comb; ++ int iftype_num[NUM_NL80211_IFTYPES] = { 0 }; ++ int *n_limits; ++ int ret = 0; ++ int i, j, iftype; ++ ++ limits = kzalloc(sizeof(*limits) * wiphy->num_hw, GFP_KERNEL); ++ if (!limits) ++ return -ENOMEM; ++ ++ n_limits = kzalloc(sizeof(*n_limits) * wiphy->num_hw, GFP_KERNEL); ++ if (!n_limits) { ++ kfree(limits); ++ return -ENOMEM; ++ } ++ ++ for (i = 0; i < wiphy->num_hw; i++) { ++ per_hw_comb = cfg80211_get_hw_iface_comb_by_idx(wiphy, c, i); ++ if (!per_hw_comb) { ++ ret = -EINVAL; ++ goto out_free; ++ } ++ ++ limits[i] = kmemdup(per_hw_comb->limits, ++ per_hw_comb->n_limits * ++ sizeof(limits[i][0]), GFP_KERNEL); ++ if (!limits[i]) { ++ ret = -ENOMEM; ++ goto out_free; ++ } ++ ++ n_limits[i] = per_hw_comb->n_limits; ++ } ++ ++ for (i = 0; i < wiphy->num_hw; i++) { ++ per_hw_comb = cfg80211_get_hw_iface_comb_by_idx(wiphy, c, i); ++ if (!per_hw_comb) { ++ ret = -EINVAL; ++ goto out_free; ++ } ++ ++ if (num_per_hw_ifaces[i] > per_hw_comb->max_interfaces) { ++ ret = -EINVAL; ++ goto out_free; ++ } ++ ++ if (params->per_hw[i].num_different_channels > ++ per_hw_comb->num_different_channels) { ++ ret = -EINVAL; ++ goto out_free; ++ } ++ ++ for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) { ++ if (cfg80211_iftype_allowed(wiphy, iftype, 0, 1)) ++ continue; ++ for (j = 0; j < n_limits[i]; j++) { ++ *all_iftypes |= limits[i][j].types; ++ if (!(limits[i][j].types & BIT(iftype))) ++ continue; ++ if (limits[i][j].max < ++ params->per_hw[i].iftype_num[iftype]) { ++ ret = -EINVAL; ++ goto out_free; ++ } ++ ++ limits[i][j].max -= ++ params->per_hw[i].iftype_num[iftype]; ++ } ++ } ++ } ++ ++ memcpy(iftype_num, params->iftype_num, NUM_NL80211_IFTYPES); ++ for (i = 0; i < wiphy->num_hw; i++) { ++ u16 rem_iface; ++ per_hw_comb = cfg80211_get_hw_iface_comb_by_idx(wiphy, c, i); ++ if (!per_hw_comb) { ++ ret = -EINVAL; ++ goto out_free; ++ } ++ ++ /* ++ * we'll not be here in the first place if the numbre of per-hw ++ * interfaces are more than the advertised ones. So it is safe ++ * to ignore that error case here. ++ */ ++ rem_iface = per_hw_comb->max_interfaces - num_per_hw_ifaces[i]; ++ if (!rem_iface) ++ continue; ++ ++ /* ++ * check if the interfaces which are not yet assigned the ++ * operating channel can be accommodated with all the available ++ * per-hw interface combination advertisements. ++ */ ++ for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) { ++ if (cfg80211_iftype_allowed(wiphy, iftype, 0, 1)) ++ continue; ++ if (!rem_iface) ++ break; ++ for (j = 0; j < n_limits[i]; j++) { ++ u16 num_avail; ++ if (!(limits[i][j].types & BIT(iftype))) ++ continue; ++ if (!rem_iface) ++ break; ++ num_avail = min(rem_iface, limits[i][j].max); ++ if (num_avail < iftype_num[iftype]) { ++ iftype_num[iftype] -= num_avail; ++ rem_iface -= num_avail; ++ } else { ++ rem_iface -= iftype_num[iftype]; ++ iftype_num[iftype] = 0; ++ } ++ } ++ } ++ } ++ ++ for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) { ++ if (iftype_num[iftype]) { ++ ret = -EINVAL; ++ goto out_free; ++ } ++ } ++ ++out_free: ++ for (i = 0; i < wiphy->num_hw; i++) ++ kfree(limits[i]); ++ ++ kfree(n_limits); ++ kfree(limits); ++ ++ return ret; ++} ++ ++static int ++cfg80211_validate_iface_comb_limits(struct wiphy *wiphy, ++ struct iface_combination_params *params, ++ const struct ieee80211_iface_combination *c, ++ int num_interfaces, u32 *all_iftypes) ++{ ++ struct ieee80211_iface_limit *limits; ++ int j, iftype; ++ int ret = 0; ++ ++ if (num_interfaces > c->max_interfaces) ++ return -EINVAL; ++ if (params->num_different_channels > c->num_different_channels) ++ return -EINVAL; ++ ++ limits = kmemdup(c->limits, sizeof(limits[0]) * c->n_limits, ++ GFP_KERNEL); ++ if (!limits) ++ return -ENOMEM; ++ ++ for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) { ++ if (cfg80211_iftype_allowed(wiphy, iftype, 0, 1)) ++ continue; ++ for (j = 0; j < c->n_limits; j++) { ++ *all_iftypes |= limits[j].types; ++ if (!(limits[j].types & BIT(iftype))) ++ continue; ++ if (limits[j].max < params->iftype_num[iftype]) { ++ ret = -EINVAL; ++ goto out_free; ++ } ++ limits[j].max -= params->iftype_num[iftype]; ++ } ++ } ++out_free: ++ kfree(limits); ++ return ret; ++} ++ ++bool cfg80211_per_hw_iface_comb_advertised(struct wiphy *wiphy) ++{ ++ int i; ++ ++ for (i = 0; i < wiphy->n_iface_combinations; i++) { ++ const struct ieee80211_iface_combination *c; ++ c = &wiphy->iface_combinations[i]; ++ if (c->n_hw_list) ++ return true; ++ } ++ ++ return false; ++} ++EXPORT_SYMBOL(cfg80211_per_hw_iface_comb_advertised); ++ ++static bool ++cfg80211_chan_supported_by_sub_hw(struct ieee80211_chans_per_hw *hw_chans, ++ const struct cfg80211_chan_def *chandef) ++{ ++ int i; ++ ++ for (i = 0; i < hw_chans->n_chans; i++) ++ if (chandef->chan->center_freq == ++ hw_chans->chans[i].center_freq) ++ return true; ++ ++ return false; ++} ++ ++int ++cfg80211_get_hw_idx_by_chan(struct wiphy *wiphy, ++ const struct cfg80211_chan_def *chandef) ++{ ++ int i; ++ ++ if (!chandef) ++ return -1; ++ ++ if (!cfg80211_chandef_valid(chandef)) ++ return -1; ++ ++ for (i = 0; i < wiphy->num_hw; i++) { ++ if (cfg80211_chan_supported_by_sub_hw(wiphy->hw_chans[i], ++ chandef)) ++ return i; ++ } ++ ++ return -1; ++} ++EXPORT_SYMBOL(cfg80211_get_hw_idx_by_chan); ++ + int cfg80211_iter_combinations(struct wiphy *wiphy, + struct iface_combination_params *params, + void (*iter)(const struct ieee80211_iface_combination *c, +- void *data), ++ void *data, int hw_chan_idx), + void *data) + { + const struct ieee80211_regdomain *regdom; + enum nl80211_dfs_regions region = 0; +- int i, j, iftype; ++ int i, iftype; + int num_interfaces = 0; ++ int *num_per_hw_ifaces = NULL; + u32 used_iftypes = 0; + u32 beacon_int_gcd; + bool beacon_int_different; ++ bool per_hw_iface_comb_used; ++ int hw_chan_idx = -1; ++ int ret = 0; + + /* + * This is a bit strange, since the iteration used to rely only on +@@ -2069,50 +2321,66 @@ int cfg80211_iter_combinations(struct wi + rcu_read_unlock(); + } + ++ per_hw_iface_comb_used = cfg80211_per_hw_iface_comb_advertised(wiphy); ++ if (per_hw_iface_comb_used) { ++ num_per_hw_ifaces = kzalloc(sizeof(*num_per_hw_ifaces) * ++ wiphy->num_hw, GFP_KERNEL); ++ if (!num_per_hw_ifaces) ++ return -ENOMEM; ++ ++ hw_chan_idx = cfg80211_get_hw_idx_by_chan(wiphy, ++ params->chandef); ++ } ++ + for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) { + num_interfaces += params->iftype_num[iftype]; + if (params->iftype_num[iftype] > 0 && + !cfg80211_iftype_allowed(wiphy, iftype, 0, 1)) + used_iftypes |= BIT(iftype); ++ ++ if (!per_hw_iface_comb_used) ++ continue; ++ ++ /* account per_hw interfaces, if advertised */ ++ for (i = 0; i < wiphy->num_hw; i++) { ++ struct iface_comb_per_hw_params *per_hw; ++ per_hw = ¶ms->per_hw[i]; ++ num_per_hw_ifaces[i] += per_hw->iftype_num[iftype]; ++ if (per_hw->iftype_num[iftype] > 0 && ++ !cfg80211_iftype_allowed(wiphy, iftype, 0, 1)) ++ used_iftypes |= BIT(iftype); ++ } + } + + for (i = 0; i < wiphy->n_iface_combinations; i++) { + const struct ieee80211_iface_combination *c; +- struct ieee80211_iface_limit *limits; + u32 all_iftypes = 0; + + c = &wiphy->iface_combinations[i]; + +- if (num_interfaces > c->max_interfaces) +- continue; +- if (params->num_different_channels > c->num_different_channels) +- continue; ++ if (per_hw_iface_comb_used) ++ ret = cfg80211_validate_per_hw_iface_comb_limits(wiphy, ++ params, c, ++ num_per_hw_ifaces, ++ &all_iftypes); ++ else ++ ret = cfg80211_validate_iface_comb_limits(wiphy, params, ++ c, ++ num_interfaces, ++ &all_iftypes); ++ if (ret == -ENOMEM) ++ goto out_free; + +- limits = kmemdup(c->limits, sizeof(limits[0]) * c->n_limits, +- GFP_KERNEL); +- if (!limits) +- return -ENOMEM; +- +- for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) { +- if (cfg80211_iftype_allowed(wiphy, iftype, 0, 1)) +- continue; +- for (j = 0; j < c->n_limits; j++) { +- all_iftypes |= limits[j].types; +- if (!(limits[j].types & BIT(iftype))) +- continue; +- if (limits[j].max < params->iftype_num[iftype]) +- goto cont; +- limits[j].max -= params->iftype_num[iftype]; +- } +- } ++ if (ret) ++ continue; + + if (params->radar_detect != +- (c->radar_detect_widths & params->radar_detect)) +- goto cont; ++ (c->radar_detect_widths & params->radar_detect)) ++ continue; + + if (params->radar_detect && c->radar_detect_regions && + !(c->radar_detect_regions & BIT(region))) +- goto cont; ++ continue; + + /* Finally check that all iftypes that we're currently + * using are actually part of this combination. If they +@@ -2120,32 +2388,32 @@ int cfg80211_iter_combinations(struct wi + * to continue to the next. + */ + if ((all_iftypes & used_iftypes) != used_iftypes) +- goto cont; ++ continue; + + if (beacon_int_gcd) { + if (c->beacon_int_min_gcd && + beacon_int_gcd < c->beacon_int_min_gcd) +- goto cont; ++ continue; + if (!c->beacon_int_min_gcd && beacon_int_different) +- goto cont; ++ continue; + } + + /* This combination covered all interface types and + * supported the requested numbers, so we're good. + */ + +- (*iter)(c, data); +- cont: +- kfree(limits); ++ (*iter)(c, data, hw_chan_idx); + } + +- return 0; ++out_free: ++ kfree(num_per_hw_ifaces); ++ return ret; + } + EXPORT_SYMBOL(cfg80211_iter_combinations); + + static void + cfg80211_iter_sum_ifcombs(const struct ieee80211_iface_combination *c, +- void *data) ++ void *data, int hw_chan_idx) + { + int *num = data; + (*num)++; +@@ -2534,3 +2802,21 @@ cfg80211_get_iftype_ext_capa(struct wiph + return NULL; + } + EXPORT_SYMBOL(cfg80211_get_iftype_ext_capa); ++ ++bool ++cfg80211_hw_chans_includes_dfs(const struct ieee80211_chans_per_hw *chans) ++{ ++ int i; ++ ++ for (i = 0; i < chans->n_chans; i++) { ++ if (chans->chans[i].band == NL80211_BAND_5GHZ && ++ ((chans->chans[i].center_freq >= 5250 && ++ chans->chans[i].center_freq <= 5340) || ++ (chans->chans[i].center_freq >= 5480 && ++ chans->chans[i].center_freq <= 5720))) ++ return true; ++ } ++ ++ return false; ++} ++EXPORT_SYMBOL(cfg80211_hw_chans_includes_dfs); diff --git a/feeds/ipq95xx/mac80211/patches/qca/675-01-nl80211-add-support-for-background-cac-stop.patch b/feeds/ipq95xx/mac80211/patches/qca/675-01-nl80211-add-support-for-background-cac-stop.patch new file mode 100644 index 000000000..ecd2dfa21 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/675-01-nl80211-add-support-for-background-cac-stop.patch @@ -0,0 +1,76 @@ +From a2db5f6f212436dff2c5420cde8e23adabb6bce0 Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Wed, 19 Oct 2022 23:29:38 +0530 +Subject: [PATCH 1/4] nl80211: add support for background cac stop + +Added changes to support aborting ongoing background +cac via new netlink command +NL80211_CMD_STOP_BGRADAR_DETECT. + + +Signed-off-by: Harshitha Prem +--- + include/uapi/linux/nl80211.h | 2 ++ + net/wireless/mlme.c | 2 +- + net/wireless/nl80211.c | 20 +++++++++++++++++++- + 3 files changed, 22 insertions(+), 2 deletions(-) + +--- a/include/uapi/linux/nl80211.h ++++ b/include/uapi/linux/nl80211.h +@@ -1544,6 +1544,8 @@ enum nl80211_commands { + NL80211_CMD_UPDATE_HE_MUEDCA_PARAMS, + + NL80211_CMD_AWGN_DETECT, ++ ++ NL80211_CMD_STOP_BGRADAR_DETECT, + /* add new commands above here */ + + /* used to define NL80211_CMD_MAX below */ +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -10200,6 +10200,16 @@ unlock: + return err; + } + ++static int nl80211_stop_radar_detection(struct sk_buff *skb, ++ struct genl_info *info) ++{ ++ struct net_device *dev = info->user_ptr[1]; ++ struct wireless_dev *wdev = dev->ieee80211_ptr; ++ ++ cfg80211_stop_background_radar_detection(wdev); ++ ++ return 0; ++} + static int nl80211_notify_radar_detection(struct sk_buff *skb, + struct genl_info *info) + { +@@ -17636,6 +17646,15 @@ static const struct genl_small_ops nl802 + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_MLO_VALID_LINK_ID), + }, ++ { ++ .cmd = NL80211_CMD_STOP_BGRADAR_DETECT, ++ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, ++ .doit = nl80211_stop_radar_detection, ++ .flags = GENL_UNS_ADMIN_PERM, ++ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP | ++ NL80211_FLAG_NO_WIPHY_MTX | ++ NL80211_FLAG_MLO_UNSUPPORTED), ++ }, + }; + + static struct genl_family nl80211_fam __genl_ro_after_init = { +@@ -19585,6 +19604,12 @@ nl80211_radar_notify(struct cfg80211_reg + goto nla_put_failure; + } + ++ if (rdev->background_radar_wdev && ++ cfg80211_chandef_identical(&rdev->background_radar_chandef, chandef)) { ++ if(nla_put_flag(msg, NL80211_ATTR_RADAR_BACKGROUND)) ++ goto nla_put_failure; ++ } ++ + if (nla_put_u32(msg, NL80211_ATTR_RADAR_EVENT, event)) + goto nla_put_failure; + diff --git a/feeds/ipq95xx/mac80211/patches/qca/675-02-cfg80211-add-minimum-background-cac-timeout.patch b/feeds/ipq95xx/mac80211/patches/qca/675-02-cfg80211-add-minimum-background-cac-timeout.patch new file mode 100644 index 000000000..c429132a6 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/675-02-cfg80211-add-minimum-background-cac-timeout.patch @@ -0,0 +1,133 @@ +From 9a42d08c1b0d5cafc7a0567e7bb881c86dec167f Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Wed, 19 Oct 2022 23:32:54 +0530 +Subject: [PATCH 2/4] cfg80211: add minimum background cac timeout + +As per ETSI standard ETSI EN 301 893 V1.7.1 (2012-06), +annex D, the DFS parameters should be as follows + +Minimum offchannel CAC timeout - 6 minutes +Maxmimum offchannel CAC timeout - 4 hours + +For channels whose nominal bandwidth falls completely or +partly within the band 5600 MHz to 5650 MHz, +the CAC Time shall be 10 minutes. + +For channels whose nominal bandwidth falls completely or +partly within the band 5600 MHz to 5650 MHz, +the Off-Channel CAC Time shall be within the +range 1 to 24 hours. + +Signed-off-by: Harshitha Prem +--- + net/wireless/chan.c | 13 +++++++++++-- + net/wireless/core.h | 2 +- + 2 files changed, 12 insertions(+), 3 deletions(-) + +Index: backports-20220822-5.4.213-ef7197996efe/net/wireless/chan.c +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/net/wireless/chan.c 2023-05-30 15:25:55.521564440 +0530 ++++ backports-20220822-5.4.213-ef7197996efe/net/wireless/chan.c 2023-05-30 15:25:55.517564430 +0530 +@@ -1079,10 +1079,10 @@ static unsigned int cfg80211_get_chans_d + + unsigned int + cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy, +- const struct cfg80211_chan_def *chandef) ++ const struct cfg80211_chan_def *chandef, bool is_bgcac) + { + int width; +- unsigned int t1 = 0, t2 = 0; ++ unsigned int t1 = 0, t2 = 0, dfs_cac_time; + + if (WARN_ON(!cfg80211_chandef_valid(chandef))) + return 0; +@@ -1096,13 +1096,33 @@ cfg80211_chandef_dfs_cac_time(struct wip + width, chandef->ru_punct_bitmap); + + if (!chandef->center_freq2) +- return t1; ++ goto exit; + + t2 = cfg80211_get_chans_dfs_cac_time(wiphy, + MHZ_TO_KHZ(chandef->center_freq2), + width, chandef->ru_punct_bitmap); + +- return max(t1, t2); ++exit: ++ dfs_cac_time = max(t1, t2); ++ if (is_bgcac) { ++ if (regulatory_pre_cac_allowed(wiphy)) { ++ ++ /* For ETSI, ++ off-channel CAC time = 6 * CAC time ++ e.g., off-channel CAC time = (6 * 60) secs = 6 mins ++ weather-radar off-channel CAC time = (6 * 10) mins = 1 hour ++ */ ++ dfs_cac_time = dfs_cac_time * 6; ++ } else { ++ /* For FCC, ++ off-channel CAC time = CAC time + 2 ++ e.g., off-channel CAC time = (60 + 2) seconds ++ */ ++ dfs_cac_time = dfs_cac_time + REG_BG_PRE_CAC_EXPIRY_GRACE_MS; ++ } ++ } ++ ++ return dfs_cac_time; + } + + static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, +Index: backports-20220822-5.4.213-ef7197996efe/net/wireless/core.h +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/net/wireless/core.h 2023-05-30 15:25:55.521564440 +0530 ++++ backports-20220822-5.4.213-ef7197996efe/net/wireless/core.h 2023-05-30 15:25:55.517564430 +0530 +@@ -480,7 +480,7 @@ void cfg80211_dfs_channels_update_work(s + + unsigned int + cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy, +- const struct cfg80211_chan_def *chandef); ++ const struct cfg80211_chan_def *chandef, bool is_bgcac); + + void cfg80211_sched_dfs_chan_update(struct cfg80211_registered_device *rdev); + +Index: backports-20220822-5.4.213-ef7197996efe/net/wireless/mlme.c +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/net/wireless/mlme.c 2023-05-30 15:25:55.521564440 +0530 ++++ backports-20220822-5.4.213-ef7197996efe/net/wireless/mlme.c 2023-05-30 15:25:55.517564430 +0530 +@@ -1122,7 +1122,8 @@ cfg80211_start_background_radar_detectio + if (err) + return err; + +- cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, chandef); ++ cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, chandef, ++ true); + if (!cac_time_ms) + cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS; + +Index: backports-20220822-5.4.213-ef7197996efe/net/wireless/nl80211.c +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/net/wireless/nl80211.c 2023-05-30 15:25:55.521564440 +0530 ++++ backports-20220822-5.4.213-ef7197996efe/net/wireless/nl80211.c 2023-05-30 15:25:55.521564440 +0530 +@@ -10183,7 +10183,8 @@ static int nl80211_start_radar_detection + goto unlock; + } + +- cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, &chandef); ++ cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, &chandef, ++ false); + if (WARN_ON(!cac_time_ms)) + cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS; + +Index: backports-20220822-5.4.213-ef7197996efe/net/wireless/reg.h +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/net/wireless/reg.h 2023-05-12 14:29:40.000000000 +0530 ++++ backports-20220822-5.4.213-ef7197996efe/net/wireless/reg.h 2023-05-30 15:26:33.597655373 +0530 +@@ -154,6 +154,8 @@ bool regulatory_indoor_allowed(void); + */ + #define REG_PRE_CAC_EXPIRY_GRACE_MS 2000 + ++#define REG_BG_PRE_CAC_EXPIRY_GRACE_MS 2000 ++ + /** + * regulatory_propagate_dfs_state - Propagate DFS channel state to other wiphys + * @wiphy - wiphy on which radar is detected and the event will be propagated diff --git a/feeds/ipq95xx/mac80211/patches/qca/675-02-nl80211-Send-multi-hw-channel-list-and-interface.patch b/feeds/ipq95xx/mac80211/patches/qca/675-02-nl80211-Send-multi-hw-channel-list-and-interface.patch new file mode 100644 index 000000000..54506e7a9 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/675-02-nl80211-Send-multi-hw-channel-list-and-interface.patch @@ -0,0 +1,311 @@ +From 933756ec29d0b4227d6bfab249b2514064ef0cc4 Mon Sep 17 00:00:00 2001 +From: Vasanthakumar Thiagarajan +Date: Sat, 8 Oct 2022 14:09:36 +0530 +Subject: [PATCH 2/3] nl80211: Send multi-hw channel list and interface + combination to user space + +Signed-off-by: Vasanthakumar Thiagarajan +--- + include/net/cfg80211.h | 18 ++--- + include/uapi/linux/nl80211.h | 98 ++++++++++++++++++++++++++- + net/wireless/nl80211.c | 125 ++++++++++++++++++++++++++++++++++- + 3 files changed, 230 insertions(+), 11 deletions(-) + +--- a/include/uapi/linux/nl80211.h ++++ b/include/uapi/linux/nl80211.h +@@ -2803,6 +2803,11 @@ enum nl80211_commands { + * indicates that the sub-channel is punctured, set 0 indicates that the + * channel is active. + * ++ * @NL80211_ATTR_MULTI_HW_MACS: nested attribute to send the hardware mac ++ * specific channel capabilities to user space. Drivers registering ++ * multiple physical hardware under a wiphy can use this attribute, ++ * see &enum nl80211_multi_hw_mac_attrs. ++ * + * @NUM_NL80211_ATTR: total number of nl80211_attrs available + * @NL80211_ATTR_MAX: highest attribute number currently defined + * @__NL80211_ATTR_AFTER_LAST: internal use +@@ -3353,6 +3358,7 @@ enum nl80211_attrs { + + NL80211_ATTR_AP_PS, + ++ NL80211_ATTR_MULTI_HW_MACS, + /* add attributes here, update the policy in nl80211.c */ + + __NL80211_ATTR_AFTER_LAST, +@@ -5918,6 +5924,10 @@ enum nl80211_iface_limit_attrs { + * @NL80211_IFACE_COMB_BI_MIN_GCD: u32 attribute specifying the minimum GCD of + * different beacon intervals supported by all the interface combinations + * in this group (if not present, all beacon intervals be identical). ++ * @NL80211_IFACE_COMB_PER_HW_COMB: nested attribute specifying the interface ++ * combination for each underlying hardware when multiple hardware are ++ * registered under a single wiphy, ++ * see &enum nl80211_if_combination_per_hw_comb_attrs. + * @NUM_NL80211_IFACE_COMB: number of attributes + * @MAX_NL80211_IFACE_COMB: highest attribute number + * +@@ -5934,7 +5944,18 @@ enum nl80211_iface_limit_attrs { + * numbers = [ #{STA} <= 1, #{P2P-client,P2P-GO} <= 3 ], max = 4 + * => allows a STA plus three P2P interfaces + * +- * The list of these four possibilities could completely be contained ++ * When describing per-hw combinations, the first possibility can ++ * further include the finer capabilities like below ++ * hw_chan_idx = 0, numbers = [ #{STA} <= 1, #{AP} <= 1 ], ++ * channels = 1, max = 2 ++ * => allows a STA plus an AP interface on the underlying hw mac ++ * advertised at index 0 in wiphy @hw_chans array. ++ * hw_chan_idx = 1, numbers = [ #{STA} <= 1, #{AP} <= 2 ], ++ * channels = 1, max = 3 ++ * => allows a STA plus two AP interfaces on the underlying hw mac ++ * advertised at index 1 in wiphy @hw_chans array. ++ * ++ * The list of these five possibilities could completely be contained + * within the %NL80211_ATTR_INTERFACE_COMBINATIONS attribute to indicate + * that any of these groups must match. + * +@@ -5953,12 +5974,44 @@ enum nl80211_if_combination_attrs { + NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, + NL80211_IFACE_COMB_RADAR_DETECT_REGIONS, + NL80211_IFACE_COMB_BI_MIN_GCD, ++ NL80211_IFACE_COMB_PER_HW_COMB, + + /* keep last */ + NUM_NL80211_IFACE_COMB, + MAX_NL80211_IFACE_COMB = NUM_NL80211_IFACE_COMB - 1 + }; + ++/** ++ * enum nl80211_if_combination_per_hw_comb_attrs - per-hw iface combination ++ * attributes with multi-hw radios ++ * ++ * @NL80211_IFACE_COMB_PER_HW_COMB_UNSPEC: (reserved) ++ * @NL80211_IFACE_COMB_PER_HW_COMB_HW_IDX: u8 attribute specifying the index ++ * to the wiphy @hw_chans list for which the iface combination is being ++ * described. ++ * @NL80211_IFACE_COMB_PER_HW_COMB_LIMITS: nested attribute containing the ++ * limits for the given interface types, see ++ * &enum nl80211_iface_limit_attrs. ++ * @NL80211_IFACE_COMB_PER_HW_COMB_MAXIMUM: u32 attribute giving the maximum ++ * number of interfaces that can be created in this group. This number ++ * does not apply to the interfaces purely managed in software. ++ * @NL80211_IFACE_COMB_PER_HW_COMB_NUM_CHANNELS: u32 attribute specifying the ++ * number of different channels that can be used in this group. ++ * @NUM_NL80211_IFACE_COMB_PER_HW_COMB: number of attributes ++ * @MAX_NL80211_IFACE_COMB_PER_HW_COMB: highest attribute number ++ */ ++enum nl80211_if_combination_per_hw_comb_attrs { ++ NL80211_IFACE_COMB_PER_HW_COMB_UNSPEC, ++ NL80211_IFACE_COMB_PER_HW_COMB_HW_IDX, ++ NL80211_IFACE_COMB_PER_HW_COMB_LIMITS, ++ NL80211_IFACE_COMB_PER_HW_COMB_MAXIMUM, ++ NL80211_IFACE_COMB_PER_HW_COMB_NUM_CHANNELS, ++ ++ /* keep last */ ++ NUM_NL80211_IFACE_COMB_PER_HW_COMB, ++ MAX_NL80211_IFACE_COMB_PER_HW_COMB = ++ NUM_NL80211_IFACE_COMB_PER_HW_COMB - 1 ++}; + + /** + * enum nl80211_plink_state - state of a mesh peer link finite state machine +@@ -7898,4 +7951,46 @@ enum nl80211_beacon_tx_mode { + NL80211_BEACON_STAGGERED_MODE = 1, + NL80211_BEACON_BURST_MODE = 2, + }; ++ ++/** ++ * nl80211_multi_hw_mac_attrs - multi-hw mac attributes ++ * ++ * ++ * @NL80211_MULTI_HW_MAC_ATTR_INVALID: invalid ++ * @NL80211_MULTI_HW_MAC_ATTR_IDX: (u8) array index in wiphy @hw_chans to refer an ++ * underlying hw mac for which the supported channel list is advertised. ++ * @NL80211_MULTI_HW_MAC_ATTR_CHAN_LIST: nested attribute specifying list of ++ * supported channels, see &enum nl80211_multi_hw_mac_chan_list_attrs ++ * @__NL80211_MULTI_HW_MAC_ATTR_LAST: internal use ++ * @NL80211_MULTI_HW_MAC_ATTR_MAX: maximum multi-hw mac attribute ++ */ ++enum nl80211_multi_hw_mac_attrs { ++ __NL80211_MULTI_HW_MAC_ATTR_INVALID, ++ ++ NL80211_MULTI_HW_MAC_ATTR_IDX, ++ NL80211_MULTI_HW_MAC_ATTR_CHAN_LIST, ++ ++ /* keep last */ ++ __NL80211_MULTI_HW_MAC_ATTR_LAST, ++ NL80211_MULTI_HW_MAC_ATTR_MAX = __NL80211_MULTI_HW_MAC_ATTR_LAST - 1 ++}; ++ ++/** ++ * nl80211_multi_hw_mac_chan_list_attrs - channel attributes for multi-hw ++ * ++ * @__NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_INVALID: invalid ++ * @NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_FREQ: channel center frequency in MHz ++ * @__NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_LAST: internal use ++ * @NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_MAX: maximum channel attribute ++ */ ++enum nl80211_multi_hw_mac_chan_list_attrs { ++ __NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_INVALID, ++ ++ NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_FREQ, ++ ++ /* keep last */ ++ __NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_LAST, ++ NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_MAX = ++ __NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_LAST - 1 ++}; + #endif /* __LINUX_NL80211_H */ +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -1653,6 +1653,71 @@ nla_put_failure: + return -ENOBUFS; + } + ++static int ++nl80211_put_per_hw_iface_combinations(struct wiphy *wiphy, struct sk_buff *msg, ++ const struct ieee80211_iface_combination *c) ++{ ++ struct nlattr *hw_combis; ++ int i; ++ ++ hw_combis = nla_nest_start(msg, NL80211_IFACE_COMB_PER_HW_COMB); ++ if (!hw_combis) ++ return -ENOBUFS; ++ ++ for (i = 0; i < c->n_hw_list; i++) { ++ struct nlattr *hw_combi, *limits; ++ int l; ++ ++ hw_combi = nla_nest_start(msg, i + 1); ++ if (!hw_combi) ++ return -ENOBUFS; ++ ++ if (nla_put_u8(msg, NL80211_IFACE_COMB_PER_HW_COMB_HW_IDX, ++ c->iface_hw_list[i].hw_chans_idx)) ++ return -ENOBUFS; ++ ++ limits = nla_nest_start(msg, ++ NL80211_IFACE_COMB_PER_HW_COMB_LIMITS); ++ if (!limits) ++ return -ENOBUFS; ++ ++ for (l = 0; l < c->iface_hw_list->n_limits; l++) { ++ struct nlattr *limit; ++ ++ limit = nla_nest_start(msg, l + 1); ++ if (!limit) ++ return -ENOBUFS; ++ ++ if (nla_put_u16(msg, NL80211_IFACE_LIMIT_MAX, ++ c->iface_hw_list[i].limits[l].max)) ++ return -ENOBUFS; ++ ++ if (nla_put_u16(msg, NL80211_IFACE_LIMIT_TYPES, ++ c->iface_hw_list[i].limits[l].types)) ++ return -ENOBUFS; ++ ++ nla_nest_end(msg, limit); ++ } ++ nla_nest_end(msg, limits); ++ ++ if (nla_put_u32(msg, ++ NL80211_IFACE_COMB_PER_HW_COMB_NUM_CHANNELS, ++ c->iface_hw_list[i].num_different_channels)) ++ return -ENOBUFS; ++ ++ if (nla_put_u16(msg, ++ NL80211_IFACE_COMB_PER_HW_COMB_MAXIMUM, ++ c->iface_hw_list[i].max_interfaces)) ++ return -ENOBUFS; ++ ++ nla_nest_end(msg, hw_combi); ++ } ++ ++ nla_nest_end(msg, hw_combis); ++ ++ return 0; ++} ++ + static int nl80211_put_iface_combinations(struct wiphy *wiphy, + struct sk_buff *msg, + bool large) +@@ -1716,6 +1781,9 @@ static int nl80211_put_iface_combination + c->beacon_int_min_gcd)) + goto nla_put_failure; + ++ if (large && nl80211_put_per_hw_iface_combinations(wiphy, msg, c)) ++ goto nla_put_failure; ++ + nla_nest_end(msg, nl_combi); + } + +@@ -2408,6 +2476,54 @@ fail: + return -ENOBUFS; + } + ++static int nl80211_put_multi_hw_support(struct wiphy *wiphy, ++ struct sk_buff *msg) ++{ ++ struct nlattr *hw_macs, *hw_mac; ++ struct nlattr *chans, *chan; ++ int i, c; ++ ++ if (!wiphy->num_hw) ++ return 0; ++ ++ hw_macs = nla_nest_start(msg, NL80211_ATTR_MULTI_HW_MACS); ++ if (!hw_macs) ++ return -ENOBUFS; ++ ++ for (i = 0; i < wiphy->num_hw; i++) { ++ hw_mac = nla_nest_start(msg, i + 1); ++ if (!hw_mac) ++ return -ENOBUFS; ++ ++ if (nla_put_u8(msg, NL80211_MULTI_HW_MAC_ATTR_IDX, i)) ++ return -ENOBUFS; ++ ++ chans = nla_nest_start(msg, ++ NL80211_MULTI_HW_MAC_ATTR_CHAN_LIST); ++ if (!chans) ++ return -ENOBUFS; ++ ++ for (c = 0; c < wiphy->hw_chans[i]->n_chans; c++) { ++ chan = nla_nest_start(msg, c + 1); ++ if (!chan) ++ return -ENOBUFS; ++ ++ if (nla_put_u32(msg, ++ NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_FREQ, ++ wiphy->hw_chans[i]->chans[c].center_freq)) ++ return -ENOBUFS; ++ ++ nla_nest_end(msg, chan); ++ } ++ nla_nest_end(msg, chans); ++ ++ nla_nest_end(msg, hw_mac); ++ } ++ ++ nla_nest_end(msg, hw_macs); ++ return 0; ++} ++ + static int + nl80211_put_ru_punct_supp_bw(struct cfg80211_registered_device *rdev, + struct sk_buff *msg) +@@ -3030,6 +3146,13 @@ static int nl80211_send_wiphy(struct cfg + goto nla_put_failure; + + /* done */ ++ state->split_start++; ++ break; ++ case 17: ++ if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_MLO) ++ nla_put_flag(msg, NL80211_ATTR_MLO_SUPPORT); ++ if (nl80211_put_multi_hw_support(&rdev->wiphy, msg)) ++ goto nla_put_failure; + state->split_start = 0; + break; + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/675-03-ath12k-Advertise-interface-combination.patch b/feeds/ipq95xx/mac80211/patches/qca/675-03-ath12k-Advertise-interface-combination.patch new file mode 100644 index 000000000..8039e990a --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/675-03-ath12k-Advertise-interface-combination.patch @@ -0,0 +1,153 @@ +From 948e5d509a5c4c6eab215da16f068ecdb96d9d98 Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Sat, 8 Oct 2022 14:14:03 +0530 +Subject: [PATCH 3/3] ath12k: Advertise interface combination + +Advertise interface combination for each of those +underlying radios in a wiphy during mac registeration. + +Signed-off-by: Harshitha Prem +--- + drivers/net/wireless/ath/ath12k/mac.c | 115 +++++++++++++++++++++++++- + include/net/cfg80211.h | 2 +- + net/wireless/core.c | 7 ++ + 3 files changed, 122 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -11213,7 +11213,15 @@ static void __ath12k_mac_unregister(stru + __ath12k_mac_pre_unregister(ar); + __ath12k_mac_post_unregister(ar); + } ++static void ath12k_mac_cleanup_chans(struct ath12k_hw *ah) ++{ ++ int i; ++ for (i = 0; i < ah->num_radio; i++) ++ kfree(ah->hw->wiphy->hw_chans[i]); + ++ kfree(ah->hw->wiphy->iface_combinations[0].iface_hw_list); ++ kfree(ah->hw->wiphy->hw_chans); ++} + static void ath12k_mac_hw_unregister(struct ath12k_hw *ah) + { + struct ath12k *ar; +@@ -11232,6 +11240,8 @@ static void ath12k_mac_hw_unregister(str + __ath12k_mac_post_unregister(ar); + ar++; + } ++ if ( ah->num_radio > 1 ) ++ ath12k_mac_cleanup_chans(ah); + + kfree(ah->hw->wiphy->iface_combinations[0].limits); + kfree(ah->hw->wiphy->iface_combinations); +@@ -11298,7 +11308,94 @@ static int __ath12k_mac_register(struct + + return 0; + } ++static int ath12k_setup_per_hw_if_comb(struct ath12k_hw *ah) { ++ struct ieee80211_iface_per_hw *if_per_hw; ++ struct ieee80211_hw *hw = ah->hw; ++ struct ieee80211_iface_combination *if_comb = hw->wiphy->iface_combinations; ++ int i; ++ ++ if_per_hw = kzalloc(sizeof(struct ieee80211_iface_per_hw) * ah->num_radio, ++ GFP_KERNEL); ++ if (!if_per_hw) ++ return -ENOMEM; ++ for (i = 0; i < ah->num_radio; i++) { ++ struct ieee80211_iface_per_hw *per_hw_if = &if_per_hw[i]; ++ per_hw_if->hw_chans_idx = i; ++ per_hw_if->num_different_channels = if_comb->num_different_channels; ++ per_hw_if->max_interfaces = if_comb->max_interfaces; ++ per_hw_if->limits = if_comb->limits; ++ per_hw_if->n_limits = if_comb->n_limits; ++ } ++ ++ if_comb->iface_hw_list = if_per_hw; ++ if_comb->n_hw_list = hw->wiphy->num_hw; ++ ++ ath12k_info(NULL, "Interface combination for %d hardwares is advertised ", ++ if_comb->n_hw_list); ++ ++ return 0; ++ ++ ++ ++} ++static struct ieee80211_chans_per_hw * ++ath12k_setup_per_hw_chan(struct ath12k *ar) ++{ ++ struct ieee80211_chans_per_hw *chans; ++ struct ieee80211_supported_band *band; ++ struct ath12k_pdev *pdev = ar->pdev; ++ int chan_sz; ++ ++ if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) { ++ band = &ar->mac.sbands[NL80211_BAND_2GHZ]; ++ } else if (pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP && !ar->supports_6ghz) { ++ band = &ar->mac.sbands[NL80211_BAND_5GHZ]; ++ } else if (pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP && ar->supports_6ghz) { ++ band = &ar->mac.sbands[NL80211_BAND_6GHZ]; ++ } ++ ++ chan_sz = struct_size(chans, chans, band->n_channels); ++ chans = kzalloc(chan_sz, GFP_KERNEL); ++ if (!chans) ++ return NULL; ++ memcpy(chans->chans, band->channels, sizeof(struct ieee80211_channel) * band->n_channels); ++ ++ chans->n_chans = band->n_channels; ++ return chans; ++ ++ ++} ++static int ath12k_alloc_per_hw_chans(struct ath12k_hw *ah) ++{ ++ struct ieee80211_chans_per_hw **chans; ++ struct ath12k *ar; ++ struct ieee80211_hw *hw = ah->hw; ++ int i; ++ ar = ah->radio; ++ ++ chans = kzalloc(sizeof(*chans) * ah->num_radio, ++ GFP_KERNEL); ++ if (!chans) ++ return -ENOMEM; + ++ for (i = 0; i < ah->num_radio; i++) { ++ chans[i] = ath12k_setup_per_hw_chan(ar); ++ if (!chans[i]) ++ goto err_free; ++ ar++; ++ ++ } ++ hw->wiphy->hw_chans = chans; ++ hw->wiphy->num_hw = ah->num_radio; ++ return 0; ++ ++err_free: ++ for (i = i - 1; i >= 0; i--) ++ kfree(chans[i]); ++ kfree(chans); ++ ++ return -ENOMEM; ++} + static int ath12k_mac_hw_register(struct ath12k_hw *ah) + { + struct ieee80211_hw *hw; +@@ -11374,6 +11471,15 @@ static int ath12k_mac_hw_register(struct + goto err_cleanup; + } + ++ if (ah->num_radio > 1) { ++ ret = ath12k_alloc_per_hw_chans(ah); ++ if (ret) ++ goto err_cleanup; ++ ret = ath12k_setup_per_hw_if_comb(ah); ++ if (ret) ++ goto err_cleanup; ++ } ++ + SET_IEEE80211_PERM_ADDR(hw, ab_dflt->mac_addr); + SET_IEEE80211_DEV(hw, ab_dflt->dev); + diff --git a/feeds/ipq95xx/mac80211/patches/qca/675-ath12k-Disable-HW-checksum-advertisement-to-netdevic.patch b/feeds/ipq95xx/mac80211/patches/qca/675-ath12k-Disable-HW-checksum-advertisement-to-netdevic.patch deleted file mode 100644 index 5f44399f9..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/675-ath12k-Disable-HW-checksum-advertisement-to-netdevic.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 531bec4e117f61ddf6508bb8b18621ae72fab576 Mon Sep 17 00:00:00 2001 -From: P Praneesh -Date: Wed, 12 Oct 2022 12:03:56 +0530 -Subject: [PATCH] ath12k: Disable HW checksum advertisement to netdevice - -Disabling Hardware checksum advertisement to ath12k netdevice -to avoid unexpected failures in the transmit path as suggested -by SFE. - -Signed-off-by: P Praneesh ---- - drivers/net/wireless/ath/ath12k/mac.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index 6172021..953b0ca 100644 ---- a/drivers/net/wireless/ath/ath12k/mac.c -+++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -11224,7 +11224,6 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah) - ah->hw->wiphy->reg_notifier = ath12k_reg_notifier; - - if (!test_bit(ATH12K_FLAG_RAW_MODE, &ag->dev_flags)) { -- hw->netdev_features = NETIF_F_HW_CSUM; - ieee80211_hw_set(hw, SW_CRYPTO_CONTROL); - ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); - } --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/675-ath12k-single-wiphy-incorrect-channel-survey-dump.patch b/feeds/ipq95xx/mac80211/patches/qca/675-ath12k-single-wiphy-incorrect-channel-survey-dump.patch new file mode 100644 index 000000000..f29d9e16f --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/675-ath12k-single-wiphy-incorrect-channel-survey-dump.patch @@ -0,0 +1,35 @@ +From 3e5d5c19409d2d65207452a47a1921a3c5ad3fdf Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Mon, 26 Sep 2022 10:51:25 +0530 +Subject: [PATCH] ath12k: [single wiphy] incorrect channel survey dump + +For survey dump collection, freq_to_idx() api is used +to map the index of particular frequency to populate its +survey. + +In case of single wiphy, wiphy is aware of all the +frequency bands present, the index was incorrect because +the mapping did not consider whether the freq band is +present in its radio structure (ar). Hence, channel survey +sent to userspace was invalid. + +To handle this, the freq_to_idx() api should map index for the +particular band in the ar structure. + +Signed-off-by: Harshitha Prem +--- + drivers/net/wireless/ath/ath12k/wmi.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -6065,6 +6065,9 @@ static int freq_to_idx(struct ath12k *ar + int band, ch, idx = 0; + + for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; band++) { ++ if (!ar->mac.sbands[band].channels) ++ continue; ++ + sband = hw->wiphy->bands[band]; + if (!sband) + continue; diff --git a/feeds/ipq95xx/mac80211/patches/qca/676-01-ath12k-prepare-vif-and-sta-for-MLO-handling.patch b/feeds/ipq95xx/mac80211/patches/qca/676-01-ath12k-prepare-vif-and-sta-for-MLO-handling.patch new file mode 100644 index 000000000..aedc4dd48 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/676-01-ath12k-prepare-vif-and-sta-for-MLO-handling.patch @@ -0,0 +1,5287 @@ +From 0144e259111a1bc79b965f9b0f3ac7e0161b7f2c Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Tue, 8 Nov 2022 14:21:41 +0530 +Subject: [PATCH] ath12k: prepare vif and sta for MLO handling + +Use arvif and arsta per radio and not per hw which comprises +multiple links. Also configs from mac80211 will be done +per link, hence do some refactoring so that these configs +are applied at link level. + +Split ath12k_vif which is the driver private of ieee80211_vif +to store link specific information. +Buy default the ath12k vif will have a preallocated link vif +called by deflink which will be used by non ML and the first +link vif of ML vif. Remaining link vifs are allocated during +channel assignment where vdev create/start happens. THis link +vif will be freed during interface down. + +Currently change_vif_links() mac80211 op is not used, rather +these links are set during channel assign. + +To refactor existing ath12k_vif to make use of link vifs, following +changes are made, +1. ieee80211_vif attribute in functions across ath12k is limited to + functions which are interface to mac80211 only. +2. THese functions which passed ieee80211_vif are replaced with ath12k_link_vif which is previously +arvif/ath12k_vif and internally ath12k_vif and vif are fetched. +3. ath12k_vif now called by varname ahvif stores multiple arvifs and +pointer to ieee80211_vif. +4. To avoid passing link_id across multiple functions and validating +them the arvif of corresponding link id is fetched and passed in these +functions and validation is done common to these functions. +5. Currently 0 is used as the default link id for non ML and these +link info is used across the driver. Later this will be replaced with +appropriate link id passed from mac80211 with MLO support +6. For mac ops which doesnt get link_id, it implies the config or info +is common for the vif, and hence it will be applied to all arvifs. + +Also, move link specific sta info to ath12k_link_sta +and use deflink currently for all link specific +operations. + +Signed-off-by: Sriram R +--- + drivers/net/wireless/ath/ath12k/core.c | 2 +- + drivers/net/wireless/ath/ath12k/core.h | 99 +- + drivers/net/wireless/ath/ath12k/debugfs.c | 26 +- + drivers/net/wireless/ath/ath12k/debugfs.h | 8 +- + drivers/net/wireless/ath/ath12k/debugfs_sta.c | 65 +- + drivers/net/wireless/ath/ath12k/debugfs_sta.h | 4 +- + drivers/net/wireless/ath/ath12k/dp.c | 25 +- + drivers/net/wireless/ath/ath12k/dp.h | 6 +- + drivers/net/wireless/ath/ath12k/dp_mon.c | 22 +- + drivers/net/wireless/ath/ath12k/dp_rx.c | 48 +- + drivers/net/wireless/ath/ath12k/dp_rx.h | 2 +- + drivers/net/wireless/ath/ath12k/dp_tx.c | 35 +- + drivers/net/wireless/ath/ath12k/dp_tx.h | 4 +- + drivers/net/wireless/ath/ath12k/mac.c | 1663 ++++++++++++----- + drivers/net/wireless/ath/ath12k/mac.h | 11 +- + drivers/net/wireless/ath/ath12k/peer.c | 14 +- + drivers/net/wireless/ath/ath12k/peer.h | 2 +- + drivers/net/wireless/ath/ath12k/spectral.c | 6 +- + drivers/net/wireless/ath/ath12k/spectral.h | 4 +- + drivers/net/wireless/ath/ath12k/testmode.c | 3 +- + drivers/net/wireless/ath/ath12k/wmi.c | 50 +- + 21 files changed, 1410 insertions(+), 689 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -1268,7 +1268,7 @@ static void ath12k_core_restart(struct w + int ret; + struct ath12k *ar; + struct ath12k_pdev *pdev; +- struct ath12k_vif *arvif; ++ struct ath12k_link_vif *arvif; + struct ath12k_hw *ah; + int i, j; + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -311,12 +311,11 @@ struct ath12k_vif_cache { + u64 bss_conf_changed; + }; + +-struct ath12k_vif { ++struct ath12k_link_vif { + u32 vdev_id; +- enum wmi_vdev_type vdev_type; +- enum wmi_vdev_subtype vdev_subtype; + u32 beacon_interval; + u32 dtim_period; ++ u8 addr[ETH_ALEN]; + u16 ast_hash; + u16 ast_idx; + u16 tcl_metadata; +@@ -324,7 +323,6 @@ struct ath12k_vif { + u8 search_type; + + struct ath12k *ar; +- struct ieee80211_vif *vif; + + int bank_id; + u8 vdev_id_check_en; +@@ -332,39 +330,18 @@ struct ath12k_vif { + u16 tx_seq_no; + struct wmi_wmm_params_all_arg wmm_params; + struct list_head list; +- union { +- struct { +- u32 uapsd; +- } sta; +- struct { +- /* 127 stations; wmi limit */ +- u8 tim_bitmap[16]; +- u8 tim_len; +- u32 ssid_len; +- u8 ssid[IEEE80211_MAX_SSID_LEN]; +- bool hidden_ssid; +- /* P2P_IE with NoA attribute for P2P_GO case */ +- u32 noa_len; +- u8 *noa_data; +- } ap; +- } u; + + bool is_created; + bool is_started; + bool is_up; + bool spectral_enabled; +- u32 aid; + u8 bssid[ETH_ALEN]; + struct cfg80211_bitrate_mask bitrate_mask; + int num_legacy_stations; + int rtscts_prot_mode; + int txpower; +- bool rsnie_present; +- bool wpaie_present; + struct ieee80211_chanctx_conf chanctx; + struct ath12k_reg_tpc_power_info reg_tpc_info; +- u32 key_cipher; +- u8 tx_encap_type; + u8 vdev_stats_id; + struct ath12k_fw_vdev_ol_stats vdev_stats; + u8 nontransmitting_vif_count; +@@ -378,13 +355,48 @@ struct ath12k_vif { + struct work_struct update_bcn_template_work; + u64 obss_color_bitmap; + struct work_struct update_obss_color_notify_work; ++ u8 link_id; ++ struct ath12k_vif *ahvif; ++}; ++ ++struct ath12k_vif { ++ enum wmi_vdev_type vdev_type; ++ enum wmi_vdev_subtype vdev_subtype; ++ struct ieee80211_vif *vif; ++ struct ath12k_hw *ah; ++ bool rsnie_present; ++ bool wpaie_present; ++ u8 tx_encap_type; ++ u32 key_cipher; ++ union { ++ struct { ++ u32 uapsd; ++ } sta; ++ struct { ++ /* 127 stations; wmi limit */ ++ u8 tim_bitmap[16]; ++ u8 tim_len; ++ u32 ssid_len; ++ u8 ssid[IEEE80211_MAX_SSID_LEN]; ++ bool hidden_ssid; ++ /* P2P_IE with NoA attribute for P2P_GO case */ ++ u32 noa_len; ++ u8 *noa_data; ++ } ap; ++ } u; ++ ++ struct ath12k_link_vif deflink; ++ struct ath12k_link_vif *link[IEEE80211_MLD_MAX_NUM_LINKS]; ++ /* indicates bitmap of link vdev created in FW */ ++ u16 links_map; ++ u32 aid; + struct ath12k_mgmt_frame_stats mgmt_stats; + }; + + struct ath12k_vif_iter { + u32 vdev_id; + struct ath12k *ar; +- struct ath12k_vif *arvif; ++ struct ath12k_link_vif *arvif; + }; + + #define HAL_AST_IDX_INVALID 0xFFFF +@@ -534,40 +546,50 @@ struct ath12k_driver_rx_pkts_flow { + atomic_t pkts_out; + }; + +-struct ath12k_sta { +- struct ath12k_vif *arvif; ++struct ath12k_link_sta { ++ struct ath12k_link_vif *arvif; ++ struct ath12k_sta *ahsta; + + /* the following are protected by ar->data_lock */ + u32 changed; /* IEEE80211_RC_* */ + u32 bw; + u32 nss; + u32 smps; +- enum hal_pn_type pn_type; + + struct work_struct update_wk; +- struct work_struct set_4addr_wk; + struct rate_info txrate; + u32 peer_nss; + struct rate_info last_txrate; + u64 rx_duration; + u64 tx_duration; + u8 rssi_comb; ++ + struct ath12k_htt_tx_stats *tx_stats; + struct ath12k_rx_peer_stats *rx_stats; ++ struct ath12k_driver_tx_pkts_flow drv_tx_pkts; ++ struct ath12k_driver_rx_pkts_flow drv_rx_pkts; + struct ath12k_wbm_tx_stats *wbm_tx_stats; + +-#ifdef CPTCFG_MAC80211_DEBUGFS +- /* protected by conf_mutex */ +- bool aggr_mode; +-#endif +- +- bool use_4addr_set; + u16 tcl_metadata; + u32 bw_prev; +- struct ath12k_driver_tx_pkts_flow drv_tx_pkts; +- struct ath12k_driver_rx_pkts_flow drv_rx_pkts; ++ u8 link_id; + }; + ++struct ath12k_sta { ++ struct ath12k_vif *ahvif; ++ #ifdef CPTCFG_MAC80211_DEBUGFS ++ /* protected by conf_mutex */ ++ bool aggr_mode; ++ #endif ++ bool use_4addr_set; ++ struct work_struct set_4addr_wk; ++ enum hal_pn_type pn_type; ++ ++ struct ath12k_link_sta deflink; ++ struct ath12k_link_sta *link[IEEE80211_MLD_MAX_NUM_LINKS]; ++ /* indicates bitmap of link sta created in FW */ ++ u16 links_map; ++ }; + #define ATH12K_HALF_20MHZ_BW 10 + #define ATH12K_5G_MIN_CENTER 4900 + #define ATH12K_5G_MAX_CENTER 5920 +@@ -1305,7 +1327,7 @@ static inline struct ath12k_skb_rxcb *AT + return (struct ath12k_skb_rxcb *)skb->cb; + } + +-static inline struct ath12k_vif *ath12k_vif_to_arvif(struct ieee80211_vif *vif) ++static inline struct ath12k_vif *ath12k_vif_to_ahvif(struct ieee80211_vif *vif) + { + return (struct ath12k_vif *)vif->drv_priv; + } +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -379,7 +379,7 @@ static const struct file_operations fops + static int ath12k_open_bcn_stats(struct inode *inode, struct file *file) + { + struct ath12k *ar = inode->i_private; +- struct ath12k_vif *arvif; ++ struct ath12k_link_vif *arvif; + struct stats_request_params req_param; + void *buf = NULL; + int ret; +@@ -2353,7 +2353,7 @@ static ssize_t ath12k_dump_mgmt_stats(st + size_t count, loff_t *ppos) + { + struct ath12k *ar = file->private_data; +- struct ath12k_vif *arvif = NULL; ++ struct ath12k_link_vif *arvif = NULL; + struct ath12k_mgmt_frame_stats *mgmt_stats; + int len = 0, ret, i; + int size = (TARGET_NUM_VDEVS - 1) * 1500; +@@ -2380,9 +2380,9 @@ static ssize_t ath12k_dump_mgmt_stats(st + if (!arvif) + break; + +- if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) ++ if (arvif->ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) + continue; +- mgmt_stats = &arvif->mgmt_stats; ++ mgmt_stats = &arvif->ahvif->mgmt_stats; + len += scnprintf(buf + len, size - len, "MGMT frame stats for vdev %u :\n", arvif->vdev_id); + len += scnprintf(buf + len, size - len, " TX stats :\n "); + len += scnprintf(buf + len, size - len, " Success frames:\n"); +@@ -2524,7 +2524,7 @@ static ssize_t ath12k_write_twt_add_dial + const char __user *ubuf, + size_t count, loff_t *ppos) + { +- struct ath12k_vif *arvif = file->private_data; ++ struct ath12k_link_vif *arvif = file->private_data; + struct wmi_twt_add_dialog_params params = { 0 }; + u8 buf[128] = {0}; + int ret; +@@ -2573,7 +2573,7 @@ static ssize_t ath12k_write_twt_del_dial + const char __user *ubuf, + size_t count, loff_t *ppos) + { +- struct ath12k_vif *arvif = file->private_data; ++ struct ath12k_link_vif *arvif = file->private_data; + struct wmi_twt_del_dialog_params params = { 0 }; + u8 buf[64] = {0}; + int ret; +@@ -2612,7 +2612,7 @@ static ssize_t ath12k_write_twt_pause_di + const char __user *ubuf, + size_t count, loff_t *ppos) + { +- struct ath12k_vif *arvif = file->private_data; ++ struct ath12k_link_vif *arvif = file->private_data; + struct wmi_twt_pause_dialog_params params = { 0 }; + u8 buf[64] = {0}; + int ret; +@@ -2651,7 +2651,7 @@ static ssize_t ath12k_write_twt_resume_d + const char __user *ubuf, + size_t count, loff_t *ppos) + { +- struct ath12k_vif *arvif = file->private_data; ++ struct ath12k_link_vif *arvif = file->private_data; + struct wmi_twt_resume_dialog_params params = { 0 }; + u8 buf[64] = {0}; + int ret; +@@ -2708,11 +2708,13 @@ static const struct file_operations ath1 + .open = simple_open + }; + +-int ath12k_debugfs_add_interface(struct ath12k_vif *arvif) ++int ath12k_debugfs_add_interface(struct ath12k_link_vif *arvif) + { +- if (arvif->vif->type == NL80211_IFTYPE_AP && !arvif->debugfs_twt) { ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ ++ if (ahvif->vif->type == NL80211_IFTYPE_AP && !arvif->debugfs_twt) { + arvif->debugfs_twt = debugfs_create_dir("twt", +- arvif->vif->debugfs_dir); ++ ahvif->vif->debugfs_dir); + if (!arvif->debugfs_twt || IS_ERR(arvif->debugfs_twt)) { + ath12k_warn(arvif->ar->ab, + "failed to create directory %p\n", +@@ -2736,7 +2738,7 @@ int ath12k_debugfs_add_interface(struct + return 0; + } + +-void ath12k_debugfs_remove_interface(struct ath12k_vif *arvif) ++void ath12k_debugfs_remove_interface(struct ath12k_link_vif *arvif) + { + debugfs_remove_recursive(arvif->debugfs_twt); + arvif->debugfs_twt = NULL; +--- a/drivers/net/wireless/ath/ath12k/debugfs.h ++++ b/drivers/net/wireless/ath/ath12k/debugfs.h +@@ -243,8 +243,8 @@ static inline int ath12k_debugfs_rx_filt + return ar->debug.rx_filter; + } + +-int ath12k_debugfs_add_interface(struct ath12k_vif *arvif); +-void ath12k_debugfs_remove_interface(struct ath12k_vif *arvif); ++int ath12k_debugfs_add_interface(struct ath12k_link_vif *arvif); ++void ath12k_debugfs_remove_interface(struct ath12k_link_vif *arvif); + + #else + static inline int ath12k_debugfs_create(void) +@@ -322,11 +322,11 @@ static inline int ath12k_debugfs_rx_filt + return 0; + } + +-static inline int ath12k_debugfs_add_interface(struct ath12k_vif *arvif) ++static inline int ath12k_debugfs_add_interface(struct ath12k_link_vif *arvif) + { + } + +-static inline void ath12k_debugfs_remove_interface(struct ath12k_vif *arvif) ++static inline void ath12k_debugfs_remove_interface(struct ath12k_link_vif *arvif) + { + } + #endif /* CPTCFG_MAC80211_DEBUGFS*/ +--- a/drivers/net/wireless/ath/ath12k/debugfs_sta.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs_sta.c +@@ -14,7 +14,7 @@ + #include "debugfs_htt_stats.h" + #include "debugfs.h" + +-void ath12k_debugfs_sta_add_tx_stats(struct ath12k_sta *arsta, ++void ath12k_debugfs_sta_add_tx_stats(struct ath12k_link_sta *arsta, + struct ath12k_per_peer_tx_stats *peer_stats, + u8 legacy_rate_idx) + { +@@ -200,7 +200,8 @@ static ssize_t ath12k_dbg_sta_dump_tx_st + size_t count, loff_t *ppos) + { + struct ieee80211_sta *sta = file->private_data; +- struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_link_sta *arsta = &ahsta->deflink; + struct ath12k *ar = arsta->arvif->ar; + struct ath12k_htt_data_stats *stats; + static const char *str_name[ATH12K_STATS_TYPE_MAX] = {"success", "fail", +@@ -391,7 +392,8 @@ static ssize_t ath12k_dbg_sta_dump_rx_st + size_t count, loff_t *ppos) + { + struct ieee80211_sta *sta = file->private_data; +- struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_link_sta *arsta = &ahsta->deflink; + struct ath12k *ar = arsta->arvif->ar; + struct ath12k_rx_peer_stats *rx_stats = arsta->rx_stats; + int len = 0, i, retval = 0; +@@ -661,7 +663,8 @@ static int + ath12k_dbg_sta_open_htt_peer_stats(struct inode *inode, struct file *file) + { + struct ieee80211_sta *sta = inode->i_private; +- struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_link_sta *arsta = &ahsta->deflink; + struct ath12k *ar = arsta->arvif->ar; + struct debug_htt_stats_req *stats_req; + int type = ar->debug.htt_stats.type; +@@ -697,7 +700,8 @@ static int + ath12k_dbg_sta_release_htt_peer_stats(struct inode *inode, struct file *file) + { + struct ieee80211_sta *sta = inode->i_private; +- struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_link_sta *arsta = &ahsta->deflink; + struct ath12k *ar = arsta->arvif->ar; + + mutex_lock(&ar->conf_mutex); +@@ -734,7 +738,8 @@ static ssize_t ath12k_dbg_sta_write_peer + size_t count, loff_t *ppos) + { + struct ieee80211_sta *sta = file->private_data; +- struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_link_sta *arsta = &ahsta->deflink; + struct ath12k *ar = arsta->arvif->ar; + int ret, enable; + +@@ -774,7 +779,8 @@ static ssize_t ath12k_dbg_sta_read_peer_ + size_t count, loff_t *ppos) + { + struct ieee80211_sta *sta = file->private_data; +- struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_link_sta *arsta = &ahsta->deflink; + struct ath12k *ar = arsta->arvif->ar; + char buf[32] = {0}; + int len; +@@ -801,7 +807,8 @@ static ssize_t ath12k_dbg_sta_write_delb + size_t count, loff_t *ppos) + { + struct ieee80211_sta *sta = file->private_data; +- struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_link_sta *arsta = &ahsta->deflink; + struct ath12k *ar = arsta->arvif->ar; + u32 tid, initiator, reason; + int ret; +@@ -822,7 +829,7 @@ static ssize_t ath12k_dbg_sta_write_delb + + mutex_lock(&ar->conf_mutex); + if (ar->state != ATH12K_STATE_ON || +- arsta->aggr_mode != ATH12K_DBG_AGGR_MODE_MANUAL) { ++ ahsta->aggr_mode != ATH12K_DBG_AGGR_MODE_MANUAL) { + ret = count; + goto out; + } +@@ -852,7 +859,8 @@ static ssize_t ath12k_dbg_sta_write_addb + size_t count, loff_t *ppos) + { + struct ieee80211_sta *sta = file->private_data; +- struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_link_sta *arsta = &ahsta->deflink; + struct ath12k *ar = arsta->arvif->ar; + u32 tid, status; + int ret; +@@ -873,7 +881,7 @@ static ssize_t ath12k_dbg_sta_write_addb + + mutex_lock(&ar->conf_mutex); + if (ar->state != ATH12K_STATE_ON || +- arsta->aggr_mode != ATH12K_DBG_AGGR_MODE_MANUAL) { ++ ahsta->aggr_mode != ATH12K_DBG_AGGR_MODE_MANUAL) { + ret = count; + goto out; + } +@@ -902,7 +910,8 @@ static ssize_t ath12k_dbg_sta_write_addb + size_t count, loff_t *ppos) + { + struct ieee80211_sta *sta = file->private_data; +- struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_link_sta *arsta = &ahsta->deflink; + struct ath12k *ar = arsta->arvif->ar; + u32 tid, buf_size; + int ret; +@@ -923,7 +932,7 @@ static ssize_t ath12k_dbg_sta_write_addb + + mutex_lock(&ar->conf_mutex); + if (ar->state != ATH12K_STATE_ON || +- arsta->aggr_mode != ATH12K_DBG_AGGR_MODE_MANUAL) { ++ ahsta->aggr_mode != ATH12K_DBG_AGGR_MODE_MANUAL) { + ret = count; + goto out; + } +@@ -953,7 +962,8 @@ static ssize_t ath12k_dbg_sta_read_aggr_ + size_t count, loff_t *ppos) + { + struct ieee80211_sta *sta = file->private_data; +- struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_link_sta *arsta = &ahsta->deflink; + struct ath12k *ar = arsta->arvif->ar; + char buf[64]; + int len = 0; +@@ -961,7 +971,7 @@ static ssize_t ath12k_dbg_sta_read_aggr_ + mutex_lock(&ar->conf_mutex); + len = scnprintf(buf, sizeof(buf) - len, + "aggregation mode: %s\n\n%s\n%s\n", +- (arsta->aggr_mode == ATH12K_DBG_AGGR_MODE_AUTO) ? ++ (ahsta->aggr_mode == ATH12K_DBG_AGGR_MODE_AUTO) ? + "auto" : "manual", "auto = 0", "manual = 1"); + mutex_unlock(&ar->conf_mutex); + +@@ -973,7 +983,8 @@ static ssize_t ath12k_dbg_sta_write_aggr + size_t count, loff_t *ppos) + { + struct ieee80211_sta *sta = file->private_data; +- struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_link_sta *arsta = &ahsta->deflink; + struct ath12k *ar = arsta->arvif->ar; + u32 aggr_mode; + int ret; +@@ -986,7 +997,7 @@ static ssize_t ath12k_dbg_sta_write_aggr + + mutex_lock(&ar->conf_mutex); + if (ar->state != ATH12K_STATE_ON || +- aggr_mode == arsta->aggr_mode) { ++ aggr_mode == ahsta->aggr_mode) { + ret = count; + goto out; + } +@@ -998,7 +1009,7 @@ static ssize_t ath12k_dbg_sta_write_aggr + goto out; + } + +- arsta->aggr_mode = aggr_mode; ++ ahsta->aggr_mode = aggr_mode; + out: + mutex_unlock(&ar->conf_mutex); + return ret; +@@ -1018,7 +1029,8 @@ ath12k_write_htt_peer_stats_reset(struct + size_t count, loff_t *ppos) + { + struct ieee80211_sta *sta = file->private_data; +- struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_link_sta *arsta = &ahsta->deflink; + struct ath12k *ar = arsta->arvif->ar; + struct htt_ext_stats_cfg_params cfg_params = { 0 }; + int ret; +@@ -1078,7 +1090,8 @@ ath12k_dbg_sta_dump_driver_tx_pkts_flow( + size_t count, loff_t *ppos) + { + struct ieee80211_sta *sta = file->private_data; +- struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_link_sta *arsta = &ahsta->deflink; + struct ath12k *ar = arsta->arvif->ar; + int len = 0, ret_val; + const int size = ATH12K_DRV_TX_STATS_SIZE; +@@ -1123,7 +1136,8 @@ static ssize_t ath12k_dbg_sta_reset_tx_s + size_t count, loff_t *ppos) + { + struct ieee80211_sta *sta = file->private_data; +- struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_link_sta *arsta = &ahsta->deflink; + struct ath12k *ar = arsta->arvif->ar; + int ret, reset; + +@@ -1161,7 +1175,8 @@ ath12k_dbg_sta_dump_driver_rx_pkts_flow( + size_t count, loff_t *ppos) + { + struct ieee80211_sta *sta = file->private_data; +- struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_link_sta *arsta = &ahsta->deflink; + struct ath12k *ar = arsta->arvif->ar; + struct ath12k_rx_peer_stats *rx_stats = arsta->rx_stats; + int len = 0, ret_val = 0; +@@ -1211,7 +1226,8 @@ static ssize_t ath12k_dbg_sta_reset_rx_s + size_t count, loff_t *ppos) + { + struct ieee80211_sta *sta = file->private_data; +- struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_link_sta *arsta = &ahsta->deflink; + struct ath12k *ar = arsta->arvif->ar; + int ret, reset; + +@@ -1250,7 +1266,8 @@ void ath12k_debugfs_sta_op_add(struct ie + + mutex_lock(&ah->conf_mutex); + +- ar = ath12k_get_ar_by_vif(hw, vif); ++ /* TODO for ML vifs */ ++ ar = ath12k_get_ar_by_vif(hw, vif, 0); + if (!ar) { + mutex_unlock(&ah->conf_mutex); + return; +--- a/drivers/net/wireless/ath/ath12k/debugfs_sta.h ++++ b/drivers/net/wireless/ath/ath12k/debugfs_sta.h +@@ -17,7 +17,7 @@ + + void ath12k_debugfs_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, struct dentry *dir); +-void ath12k_debugfs_sta_add_tx_stats(struct ath12k_sta *arsta, ++void ath12k_debugfs_sta_add_tx_stats(struct ath12k_link_sta *arsta, + struct ath12k_per_peer_tx_stats *peer_stats, + u8 legacy_rate_idx); + void ath12k_debugfs_sta_update_txcompl(struct ath12k *ar, +@@ -28,7 +28,7 @@ void ath12k_debugfs_sta_update_txcompl(s + #define ath12k_debugfs_sta_op_add NULL + + static inline void +-ath12k_debugfs_sta_add_tx_stats(struct ath12k_sta *arsta, ++ath12k_debugfs_sta_add_tx_stats(struct ath12k_link_sta *arsta, + struct ath12k_per_peer_tx_stats *peer_stats, + u8 legacy_rate_idx) + { +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -342,22 +342,23 @@ int ath12k_dp_srng_setup(struct ath12k_b + } + + static +-void ath12k_dp_tx_get_vdev_bank_config(struct ath12k_base *ab, struct ath12k_vif *arvif, ++void ath12k_dp_tx_get_vdev_bank_config(struct ath12k_base *ab, struct ath12k_link_vif *arvif, + u32 *bank_config) + { ++ struct ath12k_vif *ahvif = arvif->ahvif; + enum hal_encrypt_type encrypt_type = 0; + + /* Only valid for raw frames with HW crypto enabled. + * With SW crypto, mac80211 sets key per packet + */ +- if (arvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW && ++ if (ahvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW && + test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags) && +- arvif->key_cipher != INVALID_CIPHER) +- encrypt_type = ath12k_dp_tx_get_encrypt_type(arvif->key_cipher); ++ ahvif->key_cipher != INVALID_CIPHER) ++ encrypt_type = ath12k_dp_tx_get_encrypt_type(ahvif->key_cipher); + else + encrypt_type = HAL_ENCRYPT_TYPE_OPEN; + +- *bank_config |= u32_encode_bits(arvif->tx_encap_type, ++ *bank_config |= u32_encode_bits(ahvif->tx_encap_type, + HAL_TX_BANK_CONFIG_ENCAP_TYPE) | + u32_encode_bits(encrypt_type, + HAL_TX_BANK_CONFIG_ENCRYPT_TYPE); +@@ -374,7 +375,7 @@ void ath12k_dp_tx_get_vdev_bank_config(s + HAL_TX_ADDRY_EN), + HAL_TX_BANK_CONFIG_ADDRY_EN); + +- *bank_config |= u32_encode_bits(ieee80211_vif_is_mesh(arvif->vif) ? 3 : 0, ++ *bank_config |= u32_encode_bits(ieee80211_vif_is_mesh(ahvif->vif) ? 3 : 0, + HAL_TX_BANK_CONFIG_MESH_EN) | + u32_encode_bits(arvif->vdev_id_check_en, + HAL_TX_BANK_CONFIG_VDEV_ID_CHECK_EN); +@@ -382,7 +383,7 @@ void ath12k_dp_tx_get_vdev_bank_config(s + *bank_config |= u32_encode_bits(0, HAL_TX_BANK_CONFIG_DSCP_TIP_MAP_ID); + } + +-static int ath12k_dp_tx_get_bank_profile(struct ath12k_base *ab, struct ath12k_vif *arvif, ++static int ath12k_dp_tx_get_bank_profile(struct ath12k_base *ab, struct ath12k_link_vif *arvif, + struct ath12k_dp *dp) + { + int bank_id = DP_INVALID_BANK_ID; +@@ -439,7 +440,7 @@ void ath12k_dp_tx_put_bank_profile(struc + spin_unlock_bh(&dp->tx_bank_lock); + } + +-void ath12k_dp_tx_update_bank_profile(struct ath12k_vif *arvif) ++void ath12k_dp_tx_update_bank_profile(struct ath12k_link_vif *arvif) + { + struct ath12k_base *ab = arvif->ar->ab; + struct ath12k_dp *dp = &ab->dp; +@@ -1101,9 +1102,11 @@ int ath12k_dp_htt_connect(struct ath12k_ + return 0; + } + +-static void ath12k_dp_update_vdev_search(struct ath12k_vif *arvif) ++static void ath12k_dp_update_vdev_search(struct ath12k_link_vif *arvif) + { +- switch (arvif->vdev_type) { ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ ++ switch (ahvif->vdev_type) { + case WMI_VDEV_TYPE_STA: + /* TODO Verify the search type and flags since ast hash + * is not part of peer mapv3 +@@ -1122,7 +1125,7 @@ static void ath12k_dp_update_vdev_search + } + } + +-void ath12k_dp_vdev_tx_attach(struct ath12k *ar, struct ath12k_vif *arvif) ++void ath12k_dp_vdev_tx_attach(struct ath12k *ar, struct ath12k_link_vif *arvif) + { + struct ath12k_base *ab = ar->ab; + +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -15,7 +15,7 @@ + struct ath12k_base; + struct ath12k_peer; + struct ath12k_dp; +-struct ath12k_vif; ++struct ath12k_link_vif; + struct hal_tcl_status_ring; + struct ath12k_ext_irq_grp; + +@@ -2066,7 +2066,7 @@ int ath12k_dp_service_srng(struct ath12k + struct ath12k_ext_irq_grp *irq_grp, + int budget); + int ath12k_dp_htt_connect(struct ath12k_dp *dp); +-void ath12k_dp_vdev_tx_attach(struct ath12k *ar, struct ath12k_vif *arvif); ++void ath12k_dp_vdev_tx_attach(struct ath12k *ar, struct ath12k_link_vif *arvif); + void ath12k_dp_free(struct ath12k_base *ab); + int ath12k_dp_alloc(struct ath12k_base *ab); + void ath12k_dp_cc_config(struct ath12k_base *ab); +@@ -2092,5 +2092,5 @@ struct ath12k_rx_desc_info *ath12k_dp_ge + u32 cookie); + struct ath12k_tx_desc_info *ath12k_dp_get_tx_desc(struct ath12k_base *ab, + u32 desc_id); +-void ath12k_dp_tx_update_bank_profile(struct ath12k_vif *arvif); ++void ath12k_dp_tx_update_bank_profile(struct ath12k_link_vif *arvif); + #endif +--- a/drivers/net/wireless/ath/ath12k/dp_mon.c ++++ b/drivers/net/wireless/ath/ath12k/dp_mon.c +@@ -3295,7 +3295,7 @@ ath12k_dp_mon_rx_update_peer_rate_table_ + } + + static void ath12k_dp_mon_rx_update_peer_su_stats(struct ath12k *ar, +- struct ath12k_sta *arsta, ++ struct ath12k_link_sta *arsta, + struct hal_rx_mon_ppdu_info *ppdu_info) + { + struct ath12k_rx_peer_stats *rx_stats = arsta->rx_stats; +@@ -3460,7 +3460,8 @@ ath12k_dp_mon_rx_update_user_stats(struc + struct hal_rx_mon_ppdu_info *ppdu_info, + u32 uid) + { +- struct ath12k_sta *arsta = NULL; ++ struct ath12k_sta *ahsta = NULL; ++ struct ath12k_link_sta *arsta; + struct ath12k_rx_peer_stats *rx_stats = NULL; + struct hal_rx_user_status *user_stats = &ppdu_info->userstats[uid]; + struct ath12k_peer *peer; +@@ -3477,7 +3478,8 @@ ath12k_dp_mon_rx_update_user_stats(struc + return; + } + +- arsta = (struct ath12k_sta *)peer->sta->drv_priv; ++ ahsta = (struct ath12k_sta *)peer->sta->drv_priv; ++ arsta = &ahsta->deflink; + rx_stats = arsta->rx_stats; + + if (!rx_stats) +@@ -3606,7 +3608,7 @@ int ath12k_dp_mon_srng_process(struct at + struct hal_rx_mon_ppdu_info *ppdu_info = &pmon->mon_ppdu_info; + struct sk_buff_head skb_list; + struct ath12k_peer *peer = NULL; +- struct ath12k_sta *arsta = NULL; ++ struct ath12k_sta *ahsta = NULL; + u64 cookie; + u32 hal_status, end_reason, ppdu_id; + int num_buffs_reaped = 0, srng_id, buf_id; +@@ -3715,8 +3717,9 @@ move_next: + } + + if (ppdu_info->reception_type == HAL_RX_RECEPTION_TYPE_SU) { +- arsta = (struct ath12k_sta *)peer->sta->drv_priv; +- ath12k_dp_mon_rx_update_peer_su_stats(ar, arsta, ppdu_info); ++ ahsta = (struct ath12k_sta *)peer->sta->drv_priv; ++ ath12k_dp_mon_rx_update_peer_su_stats(ar, &ahsta->deflink, ++ ppdu_info); + } else if ((ppdu_info->fc_valid) && + (ppdu_info->ast_index != HAL_AST_IDX_INVALID)) { + ath12k_dp_mon_rx_process_ulofdma(ppdu_info); +@@ -3749,7 +3752,7 @@ int ath12k_dp_mon_rx_process_stats(struc + struct dp_srng *mon_dst_ring; + struct hal_srng *srng; + struct dp_rxdma_ring *buf_ring; +- struct ath12k_sta *arsta = NULL; ++ struct ath12k_sta *ahsta = NULL; + struct ath12k_peer *peer; + struct sk_buff_head skb_list; + u64 cookie; +@@ -3860,8 +3863,9 @@ move_next: + } + + if (ppdu_info->reception_type == HAL_RX_RECEPTION_TYPE_SU) { +- arsta = (struct ath12k_sta *)peer->sta->drv_priv; +- ath12k_dp_mon_rx_update_peer_su_stats(ar, arsta, ++ ahsta = (struct ath12k_sta *)peer->sta->drv_priv; ++ /* TODO Extend for Link STA */ ++ ath12k_dp_mon_rx_update_peer_su_stats(ar, &ahsta->deflink, + ppdu_info); + } else if ((ppdu_info->fc_valid) && + (ppdu_info->ast_index != HAL_AST_IDX_INVALID)) { +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -1095,13 +1095,15 @@ int ath12k_dp_rx_ampdu_start(struct ath1 + struct ieee80211_ampdu_params *params) + { + struct ath12k_base *ab = ar->ab; +- struct ath12k_sta *arsta = (void *)params->sta->drv_priv; ++ struct ath12k_sta *ahsta = (void *)params->sta->drv_priv; ++ struct ath12k_link_sta *arsta = &ahsta->deflink; + int vdev_id = arsta->arvif->vdev_id; + int ret; + ++ /* TODO Handle per link in ath12k_mac_op_ampdu_action() for ML STA */ + ret = ath12k_dp_rx_peer_tid_setup(ar, params->sta->addr, vdev_id, + params->tid, params->buf_size, +- params->ssn, arsta->pn_type); ++ params->ssn, ahsta->pn_type); + if (ret) + ath12k_warn(ab, "failed to setup rx tid %d\n", ret); + +@@ -1113,7 +1115,8 @@ int ath12k_dp_rx_ampdu_stop(struct ath12 + { + struct ath12k_base *ab = ar->ab; + struct ath12k_peer *peer; +- struct ath12k_sta *arsta = (void *)params->sta->drv_priv; ++ struct ath12k_sta *ahsta = (void *)params->sta->drv_priv; ++ struct ath12k_link_sta *arsta = &ahsta->deflink; + int vdev_id = arsta->arvif->vdev_id; + bool active; + int ret; +@@ -1145,7 +1148,7 @@ int ath12k_dp_rx_ampdu_stop(struct ath12 + return ret; + } + +-int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_vif *arvif, ++int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_link_vif *arvif, + const u8 *peer_addr, + enum set_key_cmd key_cmd, + struct ieee80211_key_conf *key) +@@ -1432,7 +1435,8 @@ ath12k_update_per_peer_tx_stats(struct a + struct ath12k_base *ab = ar->ab; + struct ath12k_peer *peer; + struct ieee80211_sta *sta; +- struct ath12k_sta *arsta; ++ struct ath12k_sta *ahsta; ++ struct ath12k_link_sta *arsta; + struct htt_ppdu_stats_user_rate *user_rate; + struct htt_ppdu_stats *ppdu_stats = &ppdu_info->ppdu_stats; + struct ath12k_per_peer_tx_stats *peer_stats = &ar->peer_tx_stats; +@@ -1559,7 +1563,8 @@ ath12k_update_per_peer_tx_stats(struct a + } + + sta = peer->sta; +- arsta = (struct ath12k_sta *)sta->drv_priv; ++ ahsta = (struct ath12k_sta *)sta->drv_priv; ++ arsta = &ahsta->deflink; + + memset(&arsta->txrate, 0, sizeof(arsta->txrate)); + +@@ -1900,7 +1905,7 @@ static void ath12k_htt_vdev_txrx_stats_h + { + struct htt_t2h_vdev_txrx_stats_ind *vdev_tlv; + struct htt_t2h_vdev_common_stats_tlv *soc_tlv; +- struct ath12k_vif *arvif; ++ struct ath12k_link_vif *arvif; + const struct htt_tlv *tlv; + u32 *data = (u32 *)skb->data; + u32 vdev_id; +@@ -2829,7 +2834,8 @@ static void ath12k_dp_rx_deliver_msdu(st + u8 decap = DP_RX_DECAP_TYPE_RAW; + bool is_mcbc = rxcb->is_mcbc; + bool is_eapol = rxcb->is_eapol; +- struct ath12k_sta *arsta = NULL; ++ struct ath12k_link_sta *arsta = NULL; ++ struct ath12k_sta *ahsta = NULL; + + if (status->encoding == RX_ENC_HE && !(status->flag & RX_FLAG_RADIOTAP_HE) && + !(status->flag & RX_FLAG_SKIP_MONITOR)) { +@@ -2895,9 +2901,10 @@ static void ath12k_dp_rx_deliver_msdu(st + if (ath12k_debugfs_is_extd_rx_stats_enabled(ar)) { + if (!(status->flag & RX_FLAG_ONLY_MONITOR)) { + spin_lock_bh(&ar->ab->base_lock); +- if (peer && peer->sta) +- arsta = +- (struct ath12k_sta *)peer->sta->drv_priv; ++ if (peer && peer->sta) { ++ ahsta = (struct ath12k_sta *)peer->sta->drv_priv; ++ arsta = &ahsta->deflink; ++ } + spin_unlock_bh(&ar->ab->base_lock); + if (arsta) + atomic_inc(&arsta->drv_rx_pkts.pkts_out); +@@ -3047,7 +3054,8 @@ int ath12k_dp_rx_process(struct ath12k_b + u32 *rx_desc; + int i; + u64 desc_va; +- struct ath12k_sta *arsta = NULL; ++ struct ath12k_sta *ahsta = NULL; ++ struct ath12k_link_sta *arsta = NULL; + struct ath12k_peer *peer = NULL; + struct ath12k *ar; + +@@ -3122,9 +3130,10 @@ try_again: + rcu_read_lock(); + spin_lock_bh(&ab->base_lock); + peer = ath12k_peer_find_by_id(ab, rxcb->peer_id); +- if (peer && peer->sta) +- arsta = +- (struct ath12k_sta *)peer->sta->drv_priv; ++ if (peer && peer->sta) { ++ ahsta = (struct ath12k_sta *)peer->sta->drv_priv; ++ arsta = &ahsta->deflink; ++ } + spin_unlock_bh(&ab->base_lock); + if (arsta) + atomic_inc(&arsta->drv_rx_pkts.pkts_frm_hw); +@@ -3970,7 +3979,8 @@ static int ath12k_dp_rx_h_null_q_desc(st + struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu); + u32 hal_rx_desc_sz = ar->ab->hw_params->hal_desc_sz; + bool fast_rx; +- struct ath12k_sta *arsta = NULL; ++ struct ath12k_sta *ahsta = NULL; ++ struct ath12k_link_sta *arsta = NULL; + struct ath12k_peer *peer = NULL; + + msdu_len = ath12k_dp_rx_h_msdu_len(ab, desc); +@@ -4038,8 +4048,10 @@ static int ath12k_dp_rx_h_null_q_desc(st + spin_lock_bh(&ar->ab->base_lock); + if (peer_id) + peer = ath12k_peer_find_by_id(ar->ab, rxcb->peer_id); +- if (peer && peer->sta) +- arsta = (struct ath12k_sta *)peer->sta->drv_priv; ++ if (peer && peer->sta) { ++ ahsta = (struct ath12k_sta *)peer->sta->drv_priv; ++ arsta = &ahsta->deflink; ++ } + spin_unlock_bh(&ar->ab->base_lock); + if (arsta) + atomic_inc(&arsta->drv_rx_pkts.pkts_frm_hw); +--- a/drivers/net/wireless/ath/ath12k/dp_rx.h ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.h +@@ -88,7 +88,7 @@ int ath12k_dp_rx_ampdu_start(struct ath1 + struct ieee80211_ampdu_params *params); + int ath12k_dp_rx_ampdu_stop(struct ath12k *ar, + struct ieee80211_ampdu_params *params); +-int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_vif *arvif, ++int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_link_vif *arvif, + const u8 *peer_addr, + enum set_key_cmd key_cmd, + struct ieee80211_key_conf *key); +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -13,7 +13,7 @@ + #include + + static enum hal_tcl_encap_type +-ath12k_dp_tx_get_encap_type(struct ath12k_vif *arvif, struct sk_buff *skb) ++ath12k_dp_tx_get_encap_type(struct ath12k_link_vif *arvif, struct sk_buff *skb) + { + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ath12k_base *ab = arvif->ar->ab; +@@ -117,9 +117,10 @@ static void ath12k_hal_tx_cmd_ext_desc_s + HAL_TX_MSDU_EXT_INFO1_ENCRYPT_TYPE); + } + +-int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif, +- struct ath12k_sta *arsta, struct sk_buff *skb) ++int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif, ++ struct ath12k_sta *ahsta, struct sk_buff *skb) + { ++ struct ath12k_vif *ahvif = arvif->ahvif; + struct ath12k_base *ab = ar->ab; + struct ath12k_dp *dp = &ab->dp; + struct hal_tx_info ti = {0}; +@@ -177,9 +178,10 @@ tcl_ring_sel: + ti.bank_id = arvif->bank_id; + + if (ieee80211_has_a4(hdr->frame_control) && +- is_multicast_ether_addr(hdr->addr3) && arsta && +- arsta->use_4addr_set) { +- ti.meta_data_flags = arsta->tcl_metadata; ++ is_multicast_ether_addr(hdr->addr3) && ahsta && ++ ahsta->use_4addr_set) { ++ /* TODO set tcl metadata based on primary link sta ? */ ++ ti.meta_data_flags = ahsta->deflink.tcl_metadata; + ti.flags0 |= FIELD_PREP(HAL_TCL_DATA_CMD_INFO2_TO_FW, 1); + } else { + ti.meta_data_flags = arvif->tcl_metadata; +@@ -234,8 +236,8 @@ tcl_ring_sel: + goto fail_remove_tx_buf; + } + +- if (unlikely((arvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_ETHERNET && +- !(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)))) { ++ if (unlikely((ahvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_ETHERNET && ++ !(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)))) { + msdu_ext_desc = true; + + if (skb->protocol == cpu_to_be16(ETH_P_PAE)) { +@@ -244,7 +246,7 @@ tcl_ring_sel: + } + } + +- if (unlikely(arvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW)) { ++ if (unlikely(ahvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW)) { + if (skb->protocol == cpu_to_be16(ETH_P_ARP)) { + ti.encap_type = HAL_TCL_ENCAP_TYPE_RAW; + ti.encrypt_type = HAL_ENCRYPT_TYPE_OPEN; +@@ -267,7 +269,7 @@ tcl_ring_sel: + ti.desc_id = tx_desc->desc_id; + ti.data_len = skb->len; + skb_cb->paddr = ti.paddr; +- skb_cb->vif = arvif->vif; ++ skb_cb->vif = ahvif->vif; + skb_cb->ar = ar; + + if (unlikely(msdu_ext_desc)) { +@@ -523,7 +525,8 @@ void ath12k_dp_tx_update_txcompl(struct + enum hal_tx_rate_stats_sgi sgi; + enum hal_tx_rate_stats_bw bw; + struct ath12k_peer *peer; +- struct ath12k_sta *arsta; ++ struct ath12k_sta *ahsta; ++ struct ath12k_link_sta *arsta; + struct ieee80211_sta *sta; + u16 rate, ru_tones; + u8 mcs, rate_idx, ofdma; +@@ -537,8 +540,10 @@ void ath12k_dp_tx_update_txcompl(struct + goto err_out; + } + ++ /* TODO move to per link stats */ + sta = peer->sta; +- arsta = (struct ath12k_sta *)sta->drv_priv; ++ ahsta = (struct ath12k_sta *)sta->drv_priv; ++ arsta = &ahsta->deflink; + + memset(&arsta->txrate, 0, sizeof(arsta->txrate)); + pkt_type = FIELD_GET(HAL_TX_RATE_STATS_INFO0_PKT_TYPE, +@@ -662,7 +667,8 @@ static void ath12k_dp_tx_complete_msdu(s + struct ieee80211_tx_info *info; + struct ath12k_skb_cb *skb_cb; + struct ath12k_peer *peer; +- struct ath12k_sta *arsta; ++ struct ath12k_sta *ahsta; ++ struct ath12k_link_sta *arsta; + struct rate_info rate; + struct hal_tx_status ts = { 0 }; + enum hal_wbm_tqm_rel_reason rel_status; +@@ -777,7 +783,8 @@ static void ath12k_dp_tx_complete_msdu(s + return; + } + +- arsta = (struct ath12k_sta *)peer->sta->drv_priv; ++ ahsta = (struct ath12k_sta *)peer->sta->drv_priv; ++ arsta = &ahsta->deflink; + status.sta = peer->sta; + status.skb = msdu; + status.info = info; +--- a/drivers/net/wireless/ath/ath12k/dp_tx.h ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.h +@@ -17,8 +17,8 @@ struct ath12k_dp_htt_wbm_tx_status { + + void ath12k_dp_tx_update_txcompl(struct ath12k *ar, struct hal_tx_status *ts); + int ath12k_dp_tx_htt_h2t_ver_req_msg(struct ath12k_base *ab); +-int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif, +- struct ath12k_sta *arsta, struct sk_buff *skb); ++int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif, ++ struct ath12k_sta *ahsta, struct sk_buff *skb); + void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id); + + int ath12k_dp_tx_htt_h2t_ppdu_stats_req(struct ath12k *ar, u32 mask); +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -247,9 +247,11 @@ static const u32 ath12k_smps_map[] = { + [WLAN_HT_CAP_SM_PS_DISABLED] = WMI_PEER_SMPS_PS_NONE, + }; + +-static int ath12k_mac_vdev_create(struct ath12k *ar, struct ieee80211_vif *vif); ++static int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif); + static int ath12k_start_vdev_delay(struct ath12k *ar, + struct ieee80211_vif *vif); ++static void ath12k_update_bcn_template_work(struct work_struct *work); ++static void ath12k_update_obss_color_notify_work(struct work_struct *work); + + enum nl80211_he_ru_alloc ath12k_mac_phy_he_ru_to_nl80211_he_ru_alloc(u16 ru_phy) + { +@@ -514,12 +516,22 @@ static u8 ath12k_parse_mpdudensity(u8 mp + } + + static int ath12k_mac_vif_chan(struct ieee80211_vif *vif, +- struct cfg80211_chan_def *def) +-{ ++ struct cfg80211_chan_def *def, ++ u8 link_id) ++ { ++ struct ieee80211_bss_conf *link_conf; + struct ieee80211_chanctx_conf *conf; + + rcu_read_lock(); +- conf = rcu_dereference(vif->bss_conf.chanctx_conf); ++ ++ link_conf = rcu_dereference(vif->link_conf[link_id]); ++ ++ if (!link_conf) { ++ rcu_read_unlock(); ++ return -ENOENT; ++ } ++ ++ conf = rcu_dereference(link_conf->chanctx_conf); + if (!conf) { + rcu_read_unlock(); + return -ENOENT; +@@ -576,14 +588,32 @@ static void ath12k_get_arvif_iter(void * + struct ieee80211_vif *vif) + { + struct ath12k_vif_iter *arvif_iter = data; +- struct ath12k_vif *arvif = (void *)vif->drv_priv; ++ struct ath12k_vif *ahvif = (void *)vif->drv_priv; ++ struct ath12k_link_vif *arvif; ++ u16 links_map; ++ u8 link_id; ++ ++ /* TODO Revisit lock usage for ahvif->link. Currently this is ++ * used with vif protected by rcu lock and since the ahvif->links_map ++ * or link wont be modified it is safe to access below without its mutex ++ */ ++ links_map = ahvif->links_map; ++ ++ for_each_set_bit(link_id, &links_map, IEEE80211_MLD_MAX_NUM_LINKS) { ++ arvif = ahvif->link[link_id]; ++ ++ if (WARN_ON(arvif == NULL)) ++ continue; + +- if ((arvif->vdev_id == arvif_iter->vdev_id) && +- (arvif->ar == arvif_iter->ar)) +- arvif_iter->arvif = arvif; ++ if ((arvif->vdev_id == arvif_iter->vdev_id) && ++ (arvif->ar == arvif_iter->ar)) { ++ arvif_iter->arvif = arvif; ++ break; ++ } ++ } + } + +-struct ath12k_vif *ath12k_mac_get_arvif(struct ath12k *ar, u32 vdev_id) ++struct ath12k_link_vif *ath12k_mac_get_arvif(struct ath12k *ar, u32 vdev_id) + { + struct ath12k_vif_iter arvif_iter; + u32 flags; +@@ -605,12 +635,12 @@ struct ath12k_vif *ath12k_mac_get_arvif( + return arvif_iter.arvif; + } + +-struct ath12k_vif *ath12k_mac_get_arvif_by_vdev_id(struct ath12k_base *ab, ++struct ath12k_link_vif *ath12k_mac_get_arvif_by_vdev_id(struct ath12k_base *ab, + u32 vdev_id) + { + int i; + struct ath12k_pdev *pdev; +- struct ath12k_vif *arvif; ++ struct ath12k_link_vif *arvif; + + for (i = 0; i < ab->num_radios; i++) { + pdev = rcu_dereference(ab->pdevs_active[i]); +@@ -652,9 +682,11 @@ static struct ath12k *ath12k_get_ar_by_c + return ath12k_mac_get_ar_by_band(hw, ctx->def.chan->band); + } + +-struct ath12k *ath12k_get_ar_by_vif(struct ieee80211_hw *hw, struct ieee80211_vif *vif) ++struct ath12k *ath12k_get_ar_by_vif(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ++ u8 link_id) + { +- struct ath12k_vif *arvif; ++ struct ath12k_vif *ahvif; ++ struct ath12k_link_vif *arvif; + struct ath12k_hw *ah = hw->priv; + struct ath12k *ar = NULL; + +@@ -663,9 +695,14 @@ struct ath12k *ath12k_get_ar_by_vif(stru + if (!vif) + return NULL; + +- arvif = ath12k_vif_to_arvif(vif); ++ ahvif = ath12k_vif_to_ahvif(vif); + +- if (arvif->is_created) ++ if (!(ahvif->links_map & BIT(link_id))) ++ return NULL; ++ ++ arvif = ahvif->link[link_id]; ++ ++ if (arvif && arvif->is_created) + ar = arvif->ar; + + return ar; +@@ -734,7 +771,7 @@ static void ath12k_pdev_caps_update(stru + static int ath12k_mac_txpower_recalc(struct ath12k *ar) + { + struct ath12k_pdev *pdev = ar->pdev; +- struct ath12k_vif *arvif; ++ struct ath12k_link_vif *arvif; + int ret, txpower = -1; + u32 param; + +@@ -788,7 +825,7 @@ fail: + return ret; + } + +-static int ath12k_recalc_rtscts_prot(struct ath12k_vif *arvif) ++static int ath12k_recalc_rtscts_prot(struct ath12k_link_vif *arvif) + { + struct ath12k *ar = arvif->ar; + u32 vdev_param, rts_cts = 0; +@@ -827,7 +864,7 @@ static int ath12k_recalc_rtscts_prot(str + return ret; + } + +-static int ath12k_mac_set_kickout(struct ath12k_vif *arvif) ++static int ath12k_mac_set_kickout(struct ath12k_link_vif *arvif) + { + struct ath12k *ar = arvif->ar; + u32 param; +@@ -1257,10 +1294,11 @@ out: + return ret; + } + +-static void ath12k_mac_setup_bcn_tmpl_vif_params(struct ath12k_vif *arvif, ++static void ath12k_mac_setup_bcn_tmpl_vif_params(struct ath12k_link_vif *arvif, + struct sk_buff *bcn) + { + struct ieee80211_mgmt *mgmt; ++ struct ath12k_vif *ahvif = arvif->ahvif; + struct ieee80211_vht_cap *vht_cap; + u8 *ies; + const u8 *vht_cap_ie; +@@ -1269,25 +1307,31 @@ static void ath12k_mac_setup_bcn_tmpl_vi + mgmt = (struct ieee80211_mgmt *)bcn->data; + ies += sizeof(mgmt->u.beacon); + +- if (cfg80211_find_ie(WLAN_EID_RSN, ies, (skb_tail_pointer(bcn) - ies))) +- arvif->rsnie_present = true; ++ /* avoid ie parsing if already done for this ahvif */ ++ if (!ahvif->rsnie_present && ++ cfg80211_find_ie(WLAN_EID_RSN, ies, (skb_tail_pointer(bcn) - ies))) ++ ahvif->rsnie_present = true; ++ + vht_cap_ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, ies, (skb_tail_pointer(bcn) - ies)); + if (vht_cap_ie && vht_cap_ie[1] >= sizeof(*vht_cap)) { + vht_cap = (void *)(vht_cap_ie + 2); + arvif->vht_cap = vht_cap->vht_cap_info; + } + +- if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, ++ /* avoid ie parsing if already done for this ahvif */ ++ if (!ahvif->wpaie_present && ++ cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, + WLAN_OUI_TYPE_MICROSOFT_WPA, + ies, (skb_tail_pointer(bcn) - ies))) +- arvif->wpaie_present = true; ++ ahvif->wpaie_present = true; + } + + +-static bool ath12k_mac_setup_bcn_tmpl_nontx_vif_params(struct ath12k_vif *tx_arvif, +- struct ath12k_vif *arvif, ++static bool ath12k_mac_setup_bcn_tmpl_nontx_vif_params(struct ath12k_link_vif *tx_arvif, ++ struct ath12k_link_vif *arvif, + struct sk_buff *bcn) + { ++ struct ath12k_vif *ahvif = arvif->ahvif; + struct ieee80211_mgmt *mgmt; + const u8 *ies, *profile, *next_profile; + int ies_len; +@@ -1295,7 +1339,7 @@ static bool ath12k_mac_setup_bcn_tmpl_no + if (arvif == tx_arvif) + return true; + +- arvif->rsnie_present = tx_arvif->rsnie_present; ++ ahvif->rsnie_present = ahvif->rsnie_present; + + ies = bcn->data + ieee80211_get_hdrlen_from_skb(bcn); + ies += sizeof(mgmt->u.beacon); +@@ -1322,14 +1366,14 @@ static bool ath12k_mac_setup_bcn_tmpl_no + profile += (2 + profile[1]); /* nontx capabilities */ + profile_len -= (2 + profile[1]); + profile += (2 + profile[1]); /* SSID */ +- if (profile[2] == arvif->vif->bss_conf.bssid_index) { ++ if (profile[2] == ahvif->vif->bss_conf.bssid_index) { + profile_len -= 5; + profile = profile + 5; + + if (cfg80211_find_ie(WLAN_EID_RSN, profile, + profile_len)) +- arvif->rsnie_present = true; +- else if (tx_arvif->rsnie_present) { ++ ahvif->rsnie_present = true; ++ else if (ahvif->rsnie_present) { + nie = cfg80211_find_ext_ie(WLAN_EID_EXT_NON_INHERITANCE, + profile, + profile_len); +@@ -1341,7 +1385,7 @@ static bool ath12k_mac_setup_bcn_tmpl_no + for (i = 0; i < nie_len; i++) { + if (nie[i] == + WLAN_EID_RSN) { +- arvif->rsnie_present = false; ++ ahvif->rsnie_present = false; + break; + } + } +@@ -1358,7 +1402,7 @@ static bool ath12k_mac_setup_bcn_tmpl_no + return false; + } + +-static int __ath12k_mac_setup_bcn_tmpl(struct ath12k_vif *arvif, ++static int __ath12k_mac_setup_bcn_tmpl(struct ath12k_link_vif *arvif, + struct sk_buff *bcn, + struct ieee80211_mutable_offsets offs, + int ema_idx, int ema_cnt) +@@ -1378,20 +1422,25 @@ static int __ath12k_mac_setup_bcn_tmpl(s + return ath12k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn, ema_param); + } + +-static int ath12k_mac_setup_bcn_tmpl_ema(struct ath12k_vif *arvif) ++static int ath12k_mac_setup_bcn_tmpl_ema(struct ath12k_link_vif *arvif) + { +- struct ath12k_vif *tx_arvif; ++ struct ath12k_link_vif *tx_arvif; ++ struct ath12k_vif *tx_ahvif, *ahvif = arvif->ahvif; + struct ieee80211_ema_beacons *beacons; + u8 i = 0; + int ret = 0; + bool found_vdev = false; + +- if (!arvif->vif->mbssid_tx_vif) ++ if (!ahvif->vif->mbssid_tx_vif) + return -1; + +- tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv; ++ /* FIXME there could be multiple tx link vifs, so this basically ++ * requires change for MLO ++ */ ++ tx_ahvif = (void *) ahvif->vif->mbssid_tx_vif->drv_priv; ++ tx_arvif = &tx_ahvif->deflink; + beacons = ieee80211_beacon_get_template_ema_list(tx_arvif->ar->ah->hw, +- tx_arvif->vif, 0); ++ tx_ahvif->vif, 0); + if (!beacons || !beacons->cnt) { + ath12k_warn(arvif->ar->ab, + "failed to get ema beacon templates from mac80211\n"); +@@ -1403,7 +1452,7 @@ static int ath12k_mac_setup_bcn_tmpl_ema + beacons->bcn[0].skb); + found_vdev = true; + } else { +- arvif->wpaie_present= tx_arvif->wpaie_present; ++ ahvif->wpaie_present = ahvif->wpaie_present; + } + + for (i = 0; i < beacons->cnt; i++) { +@@ -1428,17 +1477,24 @@ static int ath12k_mac_setup_bcn_tmpl_ema + return ret; + } + +-static int ath12k_mac_setup_bcn_tmpl_non_ema(struct ath12k_vif *arvif) ++static int ath12k_mac_setup_bcn_tmpl_non_ema(struct ath12k_link_vif *arvif) + { +- struct ath12k_vif *tx_arvif = arvif; ++ struct ath12k_link_vif *tx_arvif = arvif; ++ struct ath12k_vif *tx_ahvif = arvif->ahvif; ++ struct ath12k_vif *ahvif = arvif->ahvif; + struct ieee80211_mutable_offsets offs = {}; + struct sk_buff *bcn; + int ret; + +- if (arvif->vif->mbssid_tx_vif) +- tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv; ++ /* FIXME there could be multiple tx link vifs, so this basically ++ * requires change for MLO ++ */ ++ if (ahvif->vif->mbssid_tx_vif) { ++ tx_ahvif = (void *) ahvif->vif->mbssid_tx_vif->drv_priv; ++ tx_arvif = &tx_ahvif->deflink; ++ } + +- bcn = ieee80211_beacon_get_template(tx_arvif->ar->ah->hw, tx_arvif->vif, ++ bcn = ieee80211_beacon_get_template(tx_arvif->ar->ah->hw, ahvif->vif, + &offs, 0); + if (!bcn) { + ath12k_warn(arvif->ar->ab, +@@ -1463,15 +1519,19 @@ static int ath12k_mac_setup_bcn_tmpl_non + return ret; + } + +-static int ath12k_mac_setup_bcn_tmpl(struct ath12k_vif *arvif) ++static int ath12k_mac_setup_bcn_tmpl(struct ath12k_link_vif *arvif) + { +- struct ieee80211_vif *vif = arvif->vif; ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ieee80211_vif *vif = ahvif->vif; + +- if (arvif->vdev_type != WMI_VDEV_TYPE_AP) ++ if (ahvif->vdev_type != WMI_VDEV_TYPE_AP) + return 0; + ++ /* FIXME there could be multiple tx link vifs, so this basically ++ * requires change for MLO. For simpler case mbssid_tx_vif is NULL ++ */ + if (vif->mbssid_tx_vif && +- arvif != (void *)vif->mbssid_tx_vif->drv_priv && ++ ahvif != (void *)vif->mbssid_tx_vif->drv_priv && + arvif->is_up) + return 0; + +@@ -1482,9 +1542,9 @@ static int ath12k_mac_setup_bcn_tmpl(str + } + + +-void ath12k_mac_bcn_tx_event(struct ath12k_vif *arvif) ++void ath12k_mac_bcn_tx_event(struct ath12k_link_vif *arvif) + { +- struct ieee80211_vif *vif = arvif->vif; ++ struct ieee80211_vif *vif = arvif->ahvif->vif; + struct ath12k *ar = arvif->ar; + + if (!vif->bss_conf.color_change_active && !arvif->bcca_zero_sent) +@@ -1503,16 +1563,23 @@ void ath12k_mac_bcn_tx_event(struct ath1 + ieee80211_queue_work(ar->ah->hw, &arvif->update_bcn_template_work); + } + +-static void ath12k_control_beaconing(struct ath12k_vif *arvif, ++static void ath12k_control_beaconing(struct ath12k_link_vif *arvif, + struct ieee80211_bss_conf *info) + { + struct ath12k *ar = arvif->ar; +- struct ath12k_vif *tx_arvif = NULL; ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ath12k_vif *tx_ahvif = NULL; ++ struct ath12k_link_vif *tx_arvif = NULL; + int ret = 0; + struct vdev_up_params params = { 0 }; + +- if (arvif->vif->mbssid_tx_vif) +- tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv; ++ /* FIXME there could be multiple tx link vifs, so this basically ++ * requires change for MLO. For Non MLO no change in behavior ++ */ ++ if (ahvif->vif->mbssid_tx_vif) { ++ tx_ahvif = (void *) ahvif->vif->mbssid_tx_vif->drv_priv; ++ tx_arvif = &tx_ahvif->deflink; ++ } + + lockdep_assert_held(&arvif->ar->conf_mutex); + +@@ -1539,12 +1606,12 @@ static void ath12k_control_beaconing(str + + arvif->tx_seq_no = 0x1000; + +- arvif->aid = 0; ++ ahvif->aid = 0; + + ether_addr_copy(arvif->bssid, info->bssid); + + params.vdev_id = arvif->vdev_id; +- params.aid = arvif->aid; ++ params.aid = ahvif->aid; + params.bssid = arvif->bssid; + if (tx_arvif) { + params.tx_bssid = tx_arvif->bssid; +@@ -1566,12 +1633,16 @@ static void ath12k_control_beaconing(str + } + + static void ath12k_peer_assoc_h_basic(struct ath12k *ar, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta, ++ struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta, + struct peer_assoc_params *arg) + { +- struct ath12k_vif *arvif = (void *)vif->drv_priv; ++ struct ieee80211_vif *vif = arvif->ahvif->vif; + u32 aid; ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + + lockdep_assert_held(&ar->conf_mutex); + +@@ -1591,30 +1662,36 @@ static void ath12k_peer_assoc_h_basic(st + } + + static void ath12k_peer_assoc_h_crypto(struct ath12k *ar, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta, ++ struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta, + struct peer_assoc_params *arg) + { ++ struct ieee80211_vif *vif = arvif->ahvif->vif; + struct ieee80211_bss_conf *info = &vif->bss_conf; ++ struct ath12k_vif *ahvif = arvif->ahvif; + struct cfg80211_chan_def def; + struct cfg80211_bss *bss; +- struct ath12k_vif *arvif = (struct ath12k_vif *)vif->drv_priv; + const u8 *rsnie = NULL; + const u8 *wpaie = NULL; + struct ieee80211_hw *hw; ++ u8 link_id = arvif->link_id; ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + + lockdep_assert_held(&ar->conf_mutex); + +- if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) ++ if (WARN_ON(ath12k_mac_vif_chan(vif, &def, link_id))) + return; + + hw = ar->ah->hw; + bss = cfg80211_get_bss(hw->wiphy, def.chan, info->bssid, NULL, 0, + IEEE80211_BSS_TYPE_ANY, IEEE80211_PRIVACY_ANY); + +- if (arvif->rsnie_present || arvif->wpaie_present) { ++ if (ahvif->rsnie_present || ahvif->wpaie_present) { + arg->need_ptk_4_way = true; +- if (arvif->wpaie_present) ++ if (ahvif->wpaie_present) + arg->need_gtk_2_way = true; + } else if (bss) { + const struct cfg80211_bss_ies *ies; +@@ -1654,11 +1731,11 @@ static void ath12k_peer_assoc_h_crypto(s + } + + static void ath12k_peer_assoc_h_rates(struct ath12k *ar, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta, ++ struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta, + struct peer_assoc_params *arg) + { +- struct ath12k_vif *arvif = (void *)vif->drv_priv; ++ struct ieee80211_vif *vif = arvif->ahvif->vif; + struct wmi_rate_set_arg *rateset = &arg->peer_legacy_rates; + struct cfg80211_chan_def def; + const struct ieee80211_supported_band *sband; +@@ -1667,10 +1744,15 @@ static void ath12k_peer_assoc_h_rates(st + u32 ratemask; + u8 rate; + int i; ++ u8 link_id = arvif->link_id; ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + + lockdep_assert_held(&ar->conf_mutex); + +- if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) ++ if (WARN_ON(ath12k_mac_vif_chan(vif, &def, link_id))) + return; + + band = def.chan->band; +@@ -1716,22 +1798,28 @@ ath12k_peer_assoc_h_vht_masked(const u16 + } + + static void ath12k_peer_assoc_h_ht(struct ath12k *ar, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta, ++ struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta, + struct peer_assoc_params *arg) + { +- const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap; +- struct ath12k_vif *arvif = (void *)vif->drv_priv; ++ const struct ieee80211_sta_ht_cap *ht_cap; ++ struct ieee80211_vif *vif = arvif->ahvif->vif; + struct cfg80211_chan_def def; + enum nl80211_band band; + const u8 *ht_mcs_mask; + int i, n; + u8 max_nss; + u32 stbc; ++ u8 link_id = arvif->link_id; ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); ++ ht_cap = &sta->deflink.ht_cap; + + lockdep_assert_held(&ar->conf_mutex); + +- if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) ++ if (WARN_ON(ath12k_mac_vif_chan(vif, &def, link_id))) + return; + + if (!ht_cap->ht_supported) +@@ -1912,12 +2000,12 @@ static u8 ath12k_get_nss_160mhz(struct a + } + + static void ath12k_peer_assoc_h_vht(struct ath12k *ar, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta, ++ struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta, + struct peer_assoc_params *arg) + { +- const struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap; +- struct ath12k_vif *arvif = (void *)vif->drv_priv; ++ const struct ieee80211_sta_vht_cap *vht_cap; ++ struct ieee80211_vif *vif = arvif->ahvif->vif; + struct cfg80211_chan_def def; + enum nl80211_band band; + u16 *vht_mcs_mask; +@@ -1927,8 +2015,14 @@ static void ath12k_peer_assoc_h_vht(stru + int i, vht_nss, nss_idx; + bool user_rate_valid = true; + u32 rx_nss, tx_nss, nss_160; ++ u8 link_id = arvif->link_id; ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + +- if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) ++ vht_cap = &sta->deflink.vht_cap; ++ if (WARN_ON(ath12k_mac_vif_chan(vif, &def, link_id))) + return; + + if (!vht_cap->vht_supported) +@@ -2114,13 +2208,13 @@ ath12k_peer_assoc_h_he_masked(const u16 + + + static void ath12k_peer_assoc_h_he(struct ath12k *ar, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta, ++ struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta, + struct peer_assoc_params *arg) + { +- struct ath12k_vif *arvif = (void *)vif->drv_priv; ++ struct ieee80211_vif *vif = arvif->ahvif->vif; + struct cfg80211_chan_def def; +- const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap; ++ const struct ieee80211_sta_he_cap *he_cap; + int i; + u8 ampdu_factor, rx_mcs_80, rx_mcs_160, max_nss; + u16 mcs_160_map, mcs_80_map; +@@ -2132,8 +2226,14 @@ static void ath12k_peer_assoc_h_he(struc + int he_nss, nss_idx; + bool user_rate_valid = true; + u32 rx_nss, tx_nss, nss_160; ++ u8 link_id = arvif->link_id; ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); ++ he_cap = &sta->deflink.he_cap; + +- if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) ++ if (WARN_ON(ath12k_mac_vif_chan(vif, &def, link_id))) + return; + + if (!he_cap->has_he) +@@ -2354,16 +2454,23 @@ static void ath12k_peer_assoc_h_he(struc + } + + static void ath12k_peer_assoc_h_he_6ghz(struct ath12k *ar, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta, ++ struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta, + struct peer_assoc_params *arg) + { +- const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap; ++ struct ieee80211_vif *vif = arvif->ahvif->vif; ++ const struct ieee80211_sta_he_cap *he_cap; + struct cfg80211_chan_def def; + enum nl80211_band band; + u8 ampdu_factor; ++ u8 link_id = arvif->link_id; ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; + +- if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); ++ he_cap = &sta->deflink.he_cap; ++ ++ if (WARN_ON(ath12k_mac_vif_chan(vif, &def, link_id))) + return; + + band = def.chan->band; +@@ -2532,25 +2639,32 @@ ath12k_peer_assoc_h_eht_masked(const u16 + } + + static void ath12k_peer_assoc_h_eht(struct ath12k *ar, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta, ++ struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta, + struct peer_assoc_params *arg) + { +- struct ath12k_vif *arvif = (void *)vif->drv_priv; ++ struct ieee80211_vif *vif = arvif->ahvif->vif; + struct cfg80211_chan_def def; +- const struct ieee80211_sta_eht_cap *eht_cap = &sta->deflink.eht_cap; +- const struct ieee80211_eht_mcs_nss_supp *mcs_nss = +- &eht_cap->eht_mcs_nss_supp; +- const struct ieee80211_eht_mcs_nss_supp_bw *mcs_nss_supp_bw = +- &mcs_nss->bw._80; ++ const struct ieee80211_sta_eht_cap *eht_cap; ++ const struct ieee80211_eht_mcs_nss_supp *mcs_nss; ++ const struct ieee80211_eht_mcs_nss_supp_bw *mcs_nss_supp_bw; + u8 mcs_idx = WMI_EHTCAP_TXRX_MCS_NSS_IDX_80; + enum nl80211_band band; + u16 *eht_mcs_mask; + u8 max_nss; + int eht_nss, nss_idx; + bool user_rate_valid = true; ++ u8 link_id = arvif->link_id; ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); ++ ++ eht_cap = &sta->deflink.eht_cap; ++ mcs_nss = &eht_cap->eht_mcs_nss_supp; ++ mcs_nss_supp_bw = &mcs_nss->bw._80; + +- if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) ++ if (WARN_ON(ath12k_mac_vif_chan(vif, &def, link_id))) + return; + + band = def.chan->band; +@@ -2671,11 +2785,16 @@ static void ath12k_peer_assoc_h_eht(stru + sta->deflink.addr, arg->peer_nss, arg->peer_he_mcs_count, arg->ru_punct_bitmap); + } + +-static void ath12k_peer_assoc_h_smps(struct ieee80211_sta *sta, ++static void ath12k_peer_assoc_h_smps(struct ath12k_link_sta *arsta, + struct peer_assoc_params *arg) + { +- const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap; ++ const struct ieee80211_sta_ht_cap *ht_cap; + int smps; ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); ++ ht_cap = &sta->deflink.ht_cap; + + if (!ht_cap->ht_supported && !sta->deflink.he_6ghz_capa.capa) + return; +@@ -2704,13 +2823,17 @@ static void ath12k_peer_assoc_h_smps(str + } + + static void ath12k_peer_assoc_h_qos(struct ath12k *ar, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta, ++ struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta, + struct peer_assoc_params *arg) + { +- struct ath12k_vif *arvif = (void *)vif->drv_priv; ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; + +- switch (arvif->vdev_type) { ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); ++ ++ switch (ahvif->vdev_type) { + case WMI_VDEV_TYPE_AP: + if (sta->wme) { + /* TODO: Check WME vs QoS */ +@@ -2740,13 +2863,17 @@ static void ath12k_peer_assoc_h_qos(stru + } + + static int ath12k_peer_assoc_qos_ap(struct ath12k *ar, +- struct ath12k_vif *arvif, +- struct ieee80211_sta *sta) ++ struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta) + { + struct ap_ps_params params; + u32 max_sp; + u32 uapsd; + int ret; ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + + lockdep_assert_held(&ar->conf_mutex); + +@@ -2806,15 +2933,23 @@ err: + return ret; + } + +-static bool ath12k_mac_sta_has_ofdm_only(struct ieee80211_sta *sta) ++static bool ath12k_mac_sta_has_ofdm_only(struct ath12k_link_sta *arsta) + { ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + return sta->deflink.supp_rates[NL80211_BAND_2GHZ] >> +- ATH12K_MAC_FIRST_OFDM_RATE_IDX; ++ ATH12K_MAC_FIRST_OFDM_RATE_IDX; + } + + static enum wmi_phy_mode ath12k_mac_get_phymode_vht(struct ath12k *ar, +- struct ieee80211_sta *sta) ++ struct ath12k_link_sta *arsta) + { ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) { + switch (sta->deflink.vht_cap.cap & + IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) { +@@ -2841,8 +2976,12 @@ static enum wmi_phy_mode ath12k_mac_get_ + } + + static enum wmi_phy_mode ath12k_mac_get_phymode_he(struct ath12k *ar, +- struct ieee80211_sta *sta) ++ struct ath12k_link_sta *arsta) + { ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) { + if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] & + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G) +@@ -2867,8 +3006,12 @@ static enum wmi_phy_mode ath12k_mac_get_ + } + + static enum wmi_phy_mode ath12k_mac_get_phymode_eht(struct ath12k *ar, +- struct ieee80211_sta *sta) ++ struct ath12k_link_sta *arsta) + { ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_320) + if (sta->deflink.eht_cap.eht_cap_elem.phy_cap_info[0] & + IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ) +@@ -2897,11 +3040,11 @@ static enum wmi_phy_mode ath12k_mac_get_ + } + + static void ath12k_peer_assoc_h_phymode(struct ath12k *ar, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta, ++ struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta, + struct peer_assoc_params *arg) + { +- struct ath12k_vif *arvif = (void *)vif->drv_priv; ++ struct ieee80211_vif *vif = arvif->ahvif->vif; + struct cfg80211_chan_def def; + enum nl80211_band band; + const u8 *ht_mcs_mask; +@@ -2909,8 +3052,13 @@ static void ath12k_peer_assoc_h_phymode( + const u16 *he_mcs_mask; + const u16 *eht_mcs_mask; + enum wmi_phy_mode phymode = MODE_UNKNOWN; ++ u8 link_id = arvif->link_id; ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + +- if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) ++ if (WARN_ON(ath12k_mac_vif_chan(vif, &def, link_id))) + return; + + band = def.chan->band; +@@ -2947,7 +3095,7 @@ static void ath12k_peer_assoc_h_phymode( + phymode = MODE_11NG_HT40; + else + phymode = MODE_11NG_HT20; +- } else if (ath12k_mac_sta_has_ofdm_only(sta)) { ++ } else if (ath12k_mac_sta_has_ofdm_only(arsta)) { + phymode = MODE_11G; + } else { + phymode = MODE_11B; +@@ -2958,13 +3106,13 @@ static void ath12k_peer_assoc_h_phymode( + /* Check EHT first */ + if (sta->deflink.eht_cap.has_eht && + !ath12k_peer_assoc_h_eht_masked(eht_mcs_mask)) { +- phymode = ath12k_mac_get_phymode_eht(ar, sta); ++ phymode = ath12k_mac_get_phymode_eht(ar, arsta); + } else if (sta->deflink.he_cap.has_he && + !ath12k_peer_assoc_h_he_masked(he_mcs_mask)) { +- phymode = ath12k_mac_get_phymode_he(ar, sta); ++ phymode = ath12k_mac_get_phymode_he(ar, arsta); + } else if (sta->deflink.vht_cap.vht_supported && + !ath12k_peer_assoc_h_vht_masked(vht_mcs_mask)) { +- phymode = ath12k_mac_get_phymode_vht(ar, sta); ++ phymode = ath12k_mac_get_phymode_vht(ar, arsta); + } else if (sta->deflink.ht_cap.ht_supported && + !ath12k_peer_assoc_h_ht_masked(ht_mcs_mask)) { + if (sta->deflink.bandwidth >= IEEE80211_STA_RX_BW_40) +@@ -2987,40 +3135,37 @@ static void ath12k_peer_assoc_h_phymode( + } + + static void ath12k_peer_assoc_prepare(struct ath12k *ar, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta, ++ struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta, + struct peer_assoc_params *arg, + bool reassoc) + { +- struct ath12k_sta *arsta; +- + lockdep_assert_held(&ar->conf_mutex); + +- arsta = (struct ath12k_sta *)sta->drv_priv; +- + memset(arg, 0, sizeof(*arg)); + + reinit_completion(&ar->peer_assoc_done); + + arg->peer_new_assoc = !reassoc; +- ath12k_peer_assoc_h_basic(ar, vif, sta, arg); +- ath12k_peer_assoc_h_crypto(ar, vif, sta, arg); +- ath12k_peer_assoc_h_rates(ar, vif, sta, arg); +- ath12k_peer_assoc_h_phymode(ar, vif, sta, arg); +- ath12k_peer_assoc_h_ht(ar, vif, sta, arg); +- ath12k_peer_assoc_h_vht(ar, vif, sta, arg); +- ath12k_peer_assoc_h_he(ar, vif, sta, arg); +- ath12k_peer_assoc_h_he_6ghz(ar, vif, sta, arg); +- ath12k_peer_assoc_h_eht(ar, vif, sta, arg); +- ath12k_peer_assoc_h_qos(ar, vif, sta, arg); +- ath12k_peer_assoc_h_smps(sta, arg); ++ ath12k_peer_assoc_h_basic(ar, arvif, arsta, arg); ++ ath12k_peer_assoc_h_crypto(ar, arvif, arsta, arg); ++ ath12k_peer_assoc_h_rates(ar, arvif, arsta, arg); ++ ath12k_peer_assoc_h_phymode(ar, arvif, arsta, arg); ++ ath12k_peer_assoc_h_ht(ar, arvif, arsta, arg); ++ ath12k_peer_assoc_h_vht(ar, arvif, arsta, arg); ++ ath12k_peer_assoc_h_he(ar, arvif, arsta, arg); ++ ath12k_peer_assoc_h_he_6ghz(ar, arvif, arsta, arg); ++ ath12k_peer_assoc_h_eht(ar, arvif, arsta, arg); ++ ath12k_peer_assoc_h_qos(ar, arvif, arsta, arg); ++ ath12k_peer_assoc_h_smps(arsta, arg); + + arsta->peer_nss = arg->peer_nss; + + /* TODO: amsdu_disable req? */ + } + +-static int ath12k_setup_peer_smps(struct ath12k *ar, struct ath12k_vif *arvif, ++static int ath12k_setup_peer_smps(struct ath12k *ar, ++ struct ath12k_link_vif *arvif, + const u8 *addr, + const struct ieee80211_sta_ht_cap *ht_cap, + u16 he_6ghz_capa) +@@ -3045,31 +3190,32 @@ static int ath12k_setup_peer_smps(struct + ath12k_smps_map[smps]); + } + +-static bool ath12k_mac_set_he_txbf_conf(struct ath12k_vif *arvif) ++static bool 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; + +- if (!arvif->vif->bss_conf.he_support) ++ if (!ahvif->vif->bss_conf.he_support) + return true; + +- if (arvif->vif->bss_conf.he_su_beamformer) { ++ if (ahvif->vif->bss_conf.he_su_beamformer) { + value |= FIELD_PREP(HE_MODE_SU_TX_BFER, HE_SU_BFER_ENABLE); +- if (arvif->vif->bss_conf.he_mu_beamformer && +- arvif->vdev_type == WMI_VDEV_TYPE_AP) ++ if (ahvif->vif->bss_conf.he_mu_beamformer && ++ ahvif->vdev_type == WMI_VDEV_TYPE_AP) + value |= FIELD_PREP(HE_MODE_MU_TX_BFER, HE_MU_BFER_ENABLE); + } + +- if (arvif->vif->type != NL80211_IFTYPE_MESH_POINT) { ++ if (ahvif->vif->type != NL80211_IFTYPE_MESH_POINT) { + value |= FIELD_PREP(HE_MODE_DL_OFDMA, HE_DL_MUOFDMA_ENABLE) | + FIELD_PREP(HE_MODE_UL_OFDMA, HE_UL_MUOFDMA_ENABLE); + +- if (arvif->vif->bss_conf.he_full_ul_mumimo) ++ if (ahvif->vif->bss_conf.he_full_ul_mumimo) + value |= FIELD_PREP(HE_MODE_UL_MUMIMO, HE_UL_MUMIMO_ENABLE); + +- if (arvif->vif->bss_conf.he_su_beamformee) ++ if (ahvif->vif->bss_conf.he_su_beamformee) + value |= FIELD_PREP(HE_MODE_SU_TX_BFEE, HE_SU_BFEE_ENABLE); + } + +@@ -3096,16 +3242,17 @@ static bool ath12k_mac_set_he_txbf_conf( + } + + static bool ath12k_mac_vif_recalc_sta_he_txbf(struct ath12k *ar, +- struct ieee80211_vif *vif, ++ struct ath12k_link_vif *arvif, + struct ieee80211_sta_he_cap *he_cap) + { +- struct ath12k_vif *arvif = (void *)vif->drv_priv; ++ struct ieee80211_vif *vif = arvif->ahvif->vif; + struct ieee80211_he_cap_elem he_cap_elem = {0}; + struct ieee80211_sta_he_cap *cap_band; + struct cfg80211_chan_def def; + u32 param = WMI_VDEV_PARAM_SET_HEMU_MODE; + u32 hemode = 0; + int ret; ++ u8 link_id = arvif->link_id; + + if (!vif->bss_conf.he_support) + return true; +@@ -3113,7 +3260,7 @@ static bool ath12k_mac_vif_recalc_sta_he + if (vif->type != NL80211_IFTYPE_STATION) + return false; + +- if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) ++ if (WARN_ON(ath12k_mac_vif_chan(vif, &def, link_id))) + return false; + + if (def.chan->band == NL80211_BAND_2GHZ) +@@ -3161,33 +3308,34 @@ static bool ath12k_mac_vif_recalc_sta_he + return true; + } + +-static bool ath12k_mac_set_eht_txbf_conf(struct ath12k_vif *arvif) ++static bool 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; + +- if (!arvif->vif->bss_conf.eht_support) ++ if (!ahvif->vif->bss_conf.eht_support) + return true; + +- if (arvif->vif->bss_conf.eht_su_beamformer) { ++ if (ahvif->vif->bss_conf.eht_su_beamformer) { + value |= FIELD_PREP(EHT_MODE_SU_TX_BFER, EHT_SU_BFER_ENABLE); +- if (arvif->vif->bss_conf.eht_mu_beamformer && +- arvif->vdev_type == WMI_VDEV_TYPE_AP) ++ if (ahvif->vif->bss_conf.eht_mu_beamformer && ++ ahvif->vdev_type == WMI_VDEV_TYPE_AP) + value |= FIELD_PREP(EHT_MODE_MU_TX_BFER, EHT_MU_BFER_ENABLE) | + FIELD_PREP(EHT_MODE_DL_OFDMA_MUMIMO, EHT_DL_MUOFDMA_ENABLE) | + FIELD_PREP(EHT_MODE_UL_OFDMA_MUMIMO, EHT_UL_MUOFDMA_ENABLE); + } + +- if (arvif->vif->type != NL80211_IFTYPE_MESH_POINT) { ++ if (ahvif->vif->type != NL80211_IFTYPE_MESH_POINT) { + value |= FIELD_PREP(EHT_MODE_DL_OFDMA, EHT_DL_MUOFDMA_ENABLE) | + FIELD_PREP(EHT_MODE_UL_OFDMA, EHT_UL_MUOFDMA_ENABLE); + +- if (arvif->vif->bss_conf.eht_80mhz_full_bw_ul_mumimo) ++ if (ahvif->vif->bss_conf.eht_80mhz_full_bw_ul_mumimo) + value |= FIELD_PREP(EHT_MODE_MUMIMO, EHT_UL_MUMIMO_ENABLE); + +- if (arvif->vif->bss_conf.eht_su_beamformee) ++ if (ahvif->vif->bss_conf.eht_su_beamformee) + value |= FIELD_PREP(EHT_MODE_SU_TX_BFEE, EHT_SU_BFEE_ENABLE); + } + +@@ -3202,12 +3350,15 @@ static bool ath12k_mac_set_eht_txbf_conf + } + + static void ath12k_bss_assoc(struct ath12k *ar, +- struct ieee80211_vif *vif, ++ struct ath12k_link_vif *arvif, + struct ieee80211_bss_conf *bss_conf) + { +- struct ath12k_vif *arvif = (void *)vif->drv_priv; ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ieee80211_vif *vif = ahvif->vif; + struct peer_assoc_params peer_arg; + struct ieee80211_sta *ap_sta; ++ struct ath12k_link_sta *arsta; ++ struct ath12k_sta *ahsta; + struct ath12k_peer *peer; + struct ieee80211_sta_he_cap he_cap; + bool is_auth = false; +@@ -3216,8 +3367,11 @@ static void ath12k_bss_assoc(struct ath1 + + lockdep_assert_held(&ar->conf_mutex); + ++ if (!arvif) ++ return; ++ + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %i assoc bssid %pM aid %d\n", +- arvif->vdev_id, arvif->bssid, arvif->aid); ++ arvif->vdev_id, arvif->bssid, ahvif->aid); + + rcu_read_lock(); + +@@ -3228,10 +3382,14 @@ static void ath12k_bss_assoc(struct ath1 + rcu_read_unlock(); + return; + } ++ ++ ahsta = (struct ath12k_sta *)ap_sta->drv_priv; ++ arsta = &ahsta->deflink; ++ + /* he_cap here is updated at assoc success for sta mode only */ + he_cap = ap_sta->deflink.he_cap; + +- ath12k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg, false); ++ ath12k_peer_assoc_prepare(ar, arvif, arsta, &peer_arg, false); + + rcu_read_unlock(); + +@@ -3258,7 +3416,7 @@ static void ath12k_bss_assoc(struct ath1 + return; + } + +- if (!ath12k_mac_vif_recalc_sta_he_txbf(ar, vif, &he_cap)) { ++ if (!ath12k_mac_vif_recalc_sta_he_txbf(ar, arvif, &he_cap)) { + ath12k_warn(ar->ab, "failed to recalc he txbf for vdev %i on bss %pM\n", + arvif->vdev_id, bss_conf->bssid); + return; +@@ -3266,11 +3424,11 @@ static void ath12k_bss_assoc(struct ath1 + + WARN_ON(arvif->is_up); + +- arvif->aid = vif->cfg.aid; ++ ahvif->aid = vif->cfg.aid; + ether_addr_copy(arvif->bssid, bss_conf->bssid); + + params.vdev_id = arvif->vdev_id; +- params.aid = arvif->aid; ++ params.aid = ahvif->aid; + params.bssid = arvif->bssid; + ret = ath12k_wmi_vdev_up(ar, ¶ms); + if (ret) { +@@ -3311,9 +3469,11 @@ static void ath12k_bss_assoc(struct ath1 + } + + static void ath12k_bss_disassoc(struct ath12k *ar, +- struct ieee80211_vif *vif) ++ struct ath12k_link_vif *arvif) + { +- struct ath12k_vif *arvif = (void *)vif->drv_priv, *tx_arvif; ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ath12k_vif *tx_ahvif; ++ struct ath12k_link_vif *tx_arvif; + int ret; + + lockdep_assert_held(&ar->conf_mutex); +@@ -3327,8 +3487,11 @@ static void ath12k_bss_disassoc(struct a + arvif->vdev_id, ret); + + arvif->is_up = false; +- if (arvif->vif->mbssid_tx_vif) { +- tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv; ++ ++ /* FIXME mbssid for MLO */ ++ if (ahvif->vif->mbssid_tx_vif) { ++ tx_ahvif = (void *) ahvif->vif->mbssid_tx_vif->drv_priv; ++ tx_arvif = &tx_ahvif->deflink; + if (tx_arvif != arvif) + tx_arvif->nontransmitting_vif_count--; + } +@@ -3362,10 +3525,10 @@ static u32 ath12k_mac_get_rate_hw_value( + } + + static void ath12k_recalculate_mgmt_rate(struct ath12k *ar, +- struct ieee80211_vif *vif, +- struct cfg80211_chan_def *def) ++ struct ath12k_link_vif *arvif, ++ struct cfg80211_chan_def *def, ++ struct ieee80211_bss_conf *link_conf) + { +- struct ath12k_vif *arvif = (void *)vif->drv_priv; + const struct ieee80211_supported_band *sband; + u8 basic_rate_idx; + int hw_rate_code; +@@ -3376,7 +3539,7 @@ static void ath12k_recalculate_mgmt_rate + lockdep_assert_held(&ar->conf_mutex); + + sband = ar->ah->hw->wiphy->bands[def->chan->band]; +- basic_rate_idx = ffs(vif->bss_conf.basic_rates) - 1; ++ basic_rate_idx = ffs(link_conf->basic_rates) - 1; + bitrate = sband->bitrates[basic_rate_idx].bitrate; + + hw_rate_code = ath12k_mac_get_rate_hw_value(bitrate); +@@ -3398,9 +3561,10 @@ static void ath12k_recalculate_mgmt_rate + ath12k_warn(ar->ab, "failed to set beacon tx rate %d\n", ret); + } + +-static int ath12k_mac_fils_discovery(struct ath12k_vif *arvif, ++static int ath12k_mac_fils_discovery(struct ath12k_link_vif *arvif, + struct ieee80211_bss_conf *info) + { ++ struct ath12k_vif *ahvif = arvif->ahvif; + struct ath12k *ar = arvif->ar; + struct sk_buff *tmpl; + struct ath12k_hw *ah = ar->ah; +@@ -3411,7 +3575,7 @@ static int ath12k_mac_fils_discovery(str + if (info->fils_discovery.max_interval) { + interval = info->fils_discovery.max_interval; + +- tmpl = ieee80211_get_fils_discovery_tmpl(ah->hw, arvif->vif); ++ tmpl = ieee80211_get_fils_discovery_tmpl(ah->hw, ahvif->vif); + if (tmpl) + ret = ath12k_wmi_fils_discovery_tmpl(ar, arvif->vdev_id, + tmpl); +@@ -3420,7 +3584,7 @@ static int ath12k_mac_fils_discovery(str + interval = info->unsol_bcast_probe_resp_interval; + + tmpl = ieee80211_get_unsol_bcast_probe_resp_tmpl(ah->hw, +- arvif->vif); ++ ahvif->vif); + if (tmpl) + ret = ath12k_wmi_probe_resp_tmpl(ar, arvif->vdev_id, + tmpl); +@@ -3622,11 +3786,12 @@ static int ath12k_mac_config_obss_pd(str + } + + static void ath12k_mac_bss_info_changed(struct ath12k *ar, +- struct ieee80211_vif *vif, ++ struct ath12k_link_vif *arvif, + struct ieee80211_bss_conf *info, + u64 changed) + { +- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ieee80211_vif *vif = ahvif->vif; + struct cfg80211_chan_def def; + u32 param_id, param_value; + enum nl80211_band band; +@@ -3639,6 +3804,7 @@ static void ath12k_mac_bss_info_changed( + u8 rateidx; + u32 rate; + bool color_collision_detect; ++ u8 link_id = arvif->link_id; + + lockdep_assert_held(&ar->conf_mutex); + +@@ -3719,10 +3885,10 @@ static void ath12k_mac_bss_info_changed( + + if (changed & BSS_CHANGED_SSID && + vif->type == NL80211_IFTYPE_AP) { +- arvif->u.ap.ssid_len = vif->cfg.ssid_len; ++ ahvif->u.ap.ssid_len = vif->cfg.ssid_len; + if (vif->cfg.ssid_len) +- memcpy(arvif->u.ap.ssid, vif->cfg.ssid, vif->cfg.ssid_len); +- arvif->u.ap.hidden_ssid = info->hidden_ssid; ++ memcpy(ahvif->u.ap.ssid, vif->cfg.ssid, vif->cfg.ssid_len); ++ ahvif->u.ap.hidden_ssid = info->hidden_ssid; + } + + if (changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid)) +@@ -3832,9 +3998,9 @@ static void ath12k_mac_bss_info_changed( + + if (changed & BSS_CHANGED_ASSOC) { + if (vif->cfg.assoc) +- ath12k_bss_assoc(ar, vif, info); ++ ath12k_bss_assoc(ar, arvif, info); + else +- ath12k_bss_disassoc(ar, vif); ++ ath12k_bss_disassoc(ar, arvif); + } + + if (changed & BSS_CHANGED_TXPOWER) { +@@ -3843,8 +4009,8 @@ static void ath12k_mac_bss_info_changed( + + if (ar->supports_6ghz && info->chandef.chan && + info->chandef.chan->band == NL80211_BAND_6GHZ && +- (arvif->vdev_type == WMI_VDEV_TYPE_STA || +- arvif->vdev_type == WMI_VDEV_TYPE_AP) && ++ (ahvif->vdev_type == WMI_VDEV_TYPE_STA || ++ ahvif->vdev_type == WMI_VDEV_TYPE_AP) && + test_bit(WMI_TLV_SERVICE_EXT_TPC_REG_SUPPORT, + ar->ab->wmi_ab.svc_map)) { + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, +@@ -3856,7 +4022,7 @@ static void ath12k_mac_bss_info_changed( + } + + if (changed & BSS_CHANGED_MCAST_RATE && +- !ath12k_mac_vif_chan(arvif->vif, &def)) { ++ !ath12k_mac_vif_chan(ahvif->vif, &def, link_id)) { + band = def.chan->band; + mcast_rate = vif->bss_conf.mcast_rate[band]; + +@@ -3900,8 +4066,8 @@ static void ath12k_mac_bss_info_changed( + } + + if (changed & BSS_CHANGED_BASIC_RATES && +- !ath12k_mac_vif_chan(arvif->vif, &def)) +- ath12k_recalculate_mgmt_rate(ar, vif, &def); ++ !ath12k_mac_vif_chan(ahvif->vif, &def, link_id)) ++ ath12k_recalculate_mgmt_rate(ar, arvif, &def, info); + + if (changed & BSS_CHANGED_TWT) { + if (info->twt_requester || info->twt_responder) +@@ -3921,7 +4087,7 @@ static void ath12k_mac_bss_info_changed( + arvif->vdev_id, + info->he_bss_color.color, + ATH12K_BSS_COLOR_AP_PERIODS, +- arvif->vif->bss_conf.nontransmitted ? ++ ahvif->vif->bss_conf.nontransmitted ? + 0 : color_collision_detect); + if (ret) + ath12k_warn(ar->ab, "failed to set bss color collision on vdev %i: %d\n", +@@ -3972,16 +4138,52 @@ static void ath12k_mac_bss_info_changed( + } + } + ++static void ath12k_mac_op_vif_cfg_changed(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ u64 changed) ++{ ++ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); ++ struct ath12k_link_vif *arvif; ++ struct ath12k *ar; ++ ++ if (changed & BSS_CHANGED_SSID && ++ vif->type == NL80211_IFTYPE_AP) { ++ ahvif->u.ap.ssid_len = vif->cfg.ssid_len; ++ if (vif->cfg.ssid_len) ++ memcpy(ahvif->u.ap.ssid, vif->cfg.ssid, vif->cfg.ssid_len); ++ } ++ ++ if (changed & BSS_CHANGED_ASSOC) { ++ /* TODO Handle STA ML assoc */ ++ arvif = &ahvif->deflink; ++ ar = arvif->ar; ++ if (vif->cfg.assoc) ++ ath12k_bss_assoc(ar, arvif, &vif->bss_conf); ++ else ++ ath12k_bss_disassoc(ar, arvif); ++ } ++} ++ + static void ath12k_mac_op_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, + u64 changed) + { + struct ath12k_hw *ah = hw->priv; +- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); ++ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); ++ struct ath12k_link_vif *arvif; + struct ath12k *ar; ++ u8 link_id = info->link_id; + + mutex_lock(&ah->conf_mutex); ++ arvif = ahvif->link[link_id]; ++ ++ if (arvif == NULL) { ++ /* TODO handle link based ahvif caching */ ++ mutex_unlock(&ah->conf_mutex); ++ return; ++ } ++ + if (!arvif->is_created) { + ath12k_info(NULL, + "bss info parameter changes %llx cached to apply after vdev create on channel assign\n", +@@ -3995,15 +4197,14 @@ static void ath12k_mac_op_bss_info_chang + + mutex_lock(&ar->conf_mutex); + +- ath12k_mac_bss_info_changed(ar, vif, info, changed); ++ ath12k_mac_bss_info_changed(ar, arvif, info, changed); + + mutex_unlock(&ar->conf_mutex); + mutex_unlock(&ah->conf_mutex); + } + +-static int ath12k_mac_vdev_delete(struct ath12k *ar, struct ieee80211_vif *vif) ++static int ath12k_mac_vdev_delete(struct ath12k *ar, struct ath12k_link_vif *arvif) + { +- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + unsigned long time_left; + int ret = 0; + +@@ -4043,6 +4244,61 @@ clean_up: + return ret; + } + ++static struct ath12k_link_vif * ++ath12k_mac_get_link_vif( struct ath12k_hw *ah, struct ieee80211_vif *vif, u8 link_id) ++{ ++ struct ath12k_vif *ahvif = (void *)vif->drv_priv; ++ struct ath12k_link_vif *arvif; ++ int i; ++ ++ lockdep_assert_held(&ah->conf_mutex); ++ ++ if(ahvif->link[link_id]) ++ return ahvif->link[link_id]; ++ ++ /* Not a ML vif */ ++ if (!vif->valid_links) { ++ link_id = 0; ++ arvif = &ahvif->deflink; ++ } else { ++ /* first link vif is fetched from deflink*/ ++ if (!ahvif->links_map) ++ arvif = &ahvif->deflink; ++ else ++ arvif = (struct ath12k_link_vif *) ++ kzalloc(sizeof(struct ath12k_link_vif), ++ GFP_KERNEL); ++ ++ if (arvif == NULL) ++ return NULL; ++ ++ } ++ ++ ahvif->link[link_id] = arvif; ++ arvif->ahvif = ahvif; ++ arvif->link_id = link_id; ++ ahvif->links_map |= BIT(link_id); ++ ++ 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_FORCE_SGI; ++ 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)); ++ memset(arvif->bitrate_mask.control[i].eht_mcs, 0xff, ++ sizeof(arvif->bitrate_mask.control[i].eht_mcs)); ++ } ++ ++ INIT_LIST_HEAD(&arvif->list); ++ INIT_WORK(&arvif->update_obss_color_notify_work, ath12k_update_obss_color_notify_work); ++ INIT_WORK(&arvif->update_bcn_template_work, ath12k_update_bcn_template_work); ++ ++ return arvif; ++} ++ + static struct ath12k* + ath12k_mac_select_scan_device(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, +@@ -4246,7 +4502,7 @@ static int ath12k_mac_op_hw_scan(struct + struct ieee80211_scan_request *hw_req) + { + struct ath12k_hw *ah = hw->priv; +- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); ++ struct ath12k_link_vif *arvif; + struct cfg80211_scan_request *req = &hw_req->req; + struct ath12k *ar; + struct scan_req_params arg; +@@ -4266,6 +4522,8 @@ static int ath12k_mac_op_hw_scan(struct + return -EINVAL; + } + ++ /* TODO ML vif handling */ ++ arvif = ath12k_mac_get_link_vif(ah, vif, 0); + /* If the vif is already assigned to a specific vdev of an ar, + * check whether its already started, vdev which is started + * are not allowed to switch to a new radio. +@@ -4280,7 +4538,7 @@ static int ath12k_mac_op_hw_scan(struct + mutex_unlock(&ah->conf_mutex); + return -EINVAL; + } else if (ar != arvif->ar) { +- ret = ath12k_mac_vdev_delete(arvif->ar, vif); ++ ret = ath12k_mac_vdev_delete(arvif->ar, arvif); + if (ret) + ath12k_warn(arvif->ar->ab, "unable to delete scan vdev %d\n", ret); + } else { +@@ -4290,7 +4548,7 @@ static int ath12k_mac_op_hw_scan(struct + + if (create) { + mutex_lock(&ar->conf_mutex); +- ret = ath12k_mac_vdev_create(ar, vif); ++ ret = ath12k_mac_vdev_create(ar, arvif); + if (ret) { + mutex_unlock(&ar->conf_mutex); + mutex_unlock(&ah->conf_mutex); +@@ -4376,11 +4634,26 @@ exit: + static void ath12k_mac_op_cancel_hw_scan(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) + { +- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); ++ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); ++ struct ath12k_link_vif *arvif; + struct ath12k_hw *ah = hw->priv; + struct ath12k *ar; ++ /* TODO we currently use temp link id as 0, for runtime ++ * force AP scan handle accordingly by identifying the ++ * active scan link ++ */ ++ u8 link_id = 0; + + mutex_lock(&ah->conf_mutex); ++ ++ if (!(ahvif->links_map & BIT(link_id))) { ++ mutex_unlock(&ah->conf_mutex); ++ ath12k_err(NULL, "unable to select device to cancel scan\n"); ++ return; ++ } ++ ++ arvif = ahvif->link[link_id]; ++ + if (!arvif->is_created) { + ath12k_err(NULL, "unable to select device to cancel scan\n"); + mutex_unlock(&ah->conf_mutex); +@@ -4397,12 +4670,13 @@ static void ath12k_mac_op_cancel_hw_scan + cancel_delayed_work_sync(&ar->scan.timeout); + } + +-static int ath12k_install_key(struct ath12k_vif *arvif, ++static int ath12k_install_key(struct ath12k_link_vif *arvif, + struct ieee80211_key_conf *key, + enum set_key_cmd cmd, + const u8 *macaddr, u32 flags) + { + int ret; ++ struct ath12k_vif *ahvif = arvif->ahvif; + struct ath12k *ar = arvif->ar; + struct wmi_vdev_install_key_arg arg = { + .vdev_id = arvif->vdev_id, +@@ -4464,15 +4738,15 @@ install: + if (!wait_for_completion_timeout(&ar->install_key_done, 1 * HZ)) + return -ETIMEDOUT; + +- if (ether_addr_equal(macaddr, arvif->vif->addr)) { +- arvif->key_cipher = key->cipher; ++ if (ether_addr_equal(macaddr, arvif->addr)) { ++ ahvif->key_cipher = key->cipher; + ath12k_dp_tx_update_bank_profile(arvif); + } + + return ar->install_key_status ? -EINVAL : 0; + } + +-static int ath12k_clear_peer_keys(struct ath12k_vif *arvif, ++static int ath12k_clear_peer_keys(struct ath12k_link_vif *arvif, + const u8 *addr) + { + struct ath12k *ar = arvif->ar; +@@ -4515,20 +4789,37 @@ static int ath12k_clear_peer_keys(struct + } + + static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta, ++ struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta, + struct ieee80211_key_conf *key) + { + struct ath12k_base *ab; + struct ath12k_peer *peer; +- struct ath12k_sta *arsta; ++ struct ath12k_sta *ahsta = NULL; + const u8 *peer_addr; +- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ieee80211_vif *vif = ahvif->vif; ++ struct ieee80211_bss_conf *link_conf; + int ret = 0; + u32 flags = 0; ++ u8 link_id = arvif->link_id; ++ struct ieee80211_sta *sta = NULL; ++ ++ if (arsta) { ++ ahsta = arsta->ahsta; ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); ++ } + + lockdep_assert_held(&ar->ah->conf_mutex); + ++ rcu_read_lock(); ++ link_conf = rcu_dereference(vif->link_conf[link_id]); ++ ++ if (!link_conf) { ++ rcu_read_unlock(); ++ return -EINVAL; ++ } ++ + ab = ar->ab; + + /* BIP needs to be done in software */ +@@ -4536,28 +4827,33 @@ static int ath12k_mac_set_key(struct ath + key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 || + key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 || + key->cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256) { ++ rcu_read_unlock(); + ret = 1; + goto out; + } + + if (test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags)) { ++ rcu_read_unlock(); + ret = 1; + goto out; + } + + if (key->keyidx > WMI_MAX_KEY_INDEX) { ++ rcu_read_unlock(); + ret = -ENOSPC; + goto out; + } + +- mutex_lock(&ar->conf_mutex); +- + if (sta) + peer_addr = sta->addr; +- else if (arvif->vdev_type == WMI_VDEV_TYPE_STA) +- peer_addr = vif->bss_conf.bssid; ++ else if (ahvif->vdev_type == WMI_VDEV_TYPE_STA) ++ peer_addr = link_conf->bssid; + else +- peer_addr = vif->addr; ++ peer_addr = link_conf->addr; ++ ++ rcu_read_unlock(); ++ ++ mutex_lock(&ar->conf_mutex); + + key->hw_key_idx = key->keyidx; + +@@ -4621,8 +4917,6 @@ static int ath12k_mac_set_key(struct ath + ath12k_warn(ab, "peer %pM disappeared!\n", peer_addr); + + if (sta) { +- arsta = (struct ath12k_sta *)sta->drv_priv; +- + switch (key->cipher) { + case WLAN_CIPHER_SUITE_TKIP: + case WLAN_CIPHER_SUITE_CCMP: +@@ -4630,12 +4924,12 @@ static int ath12k_mac_set_key(struct ath + case WLAN_CIPHER_SUITE_GCMP: + case WLAN_CIPHER_SUITE_GCMP_256: + if (cmd == SET_KEY) +- arsta->pn_type = HAL_PN_TYPE_WPA; ++ ahsta->pn_type = HAL_PN_TYPE_WPA; + else +- arsta->pn_type = HAL_PN_TYPE_NONE; ++ ahsta->pn_type = HAL_PN_TYPE_NONE; + break; + default: +- arsta->pn_type = HAL_PN_TYPE_NONE; ++ ahsta->pn_type = HAL_PN_TYPE_NONE; + break; + } + } +@@ -4654,11 +4948,17 @@ static int ath12k_mac_op_set_key(struct + { + struct ath12k *ar; + struct ath12k_hw *ah = hw->priv; +- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); ++ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); ++ struct ath12k_link_vif *arvif; ++ struct ath12k_link_sta *arsta = NULL; ++ struct ath12k_sta *ahsta; + int ret; + + mutex_lock(&ah->conf_mutex); + ++ /* TODO modify for all link vif configuration */ ++ arvif = &ahvif->deflink; ++ + if (!arvif->is_created) { + arvif->cache.key_conf.cmd = cmd; + arvif->cache.key_conf.sta = sta; +@@ -4675,7 +4975,12 @@ static int ath12k_mac_op_set_key(struct + } + + ar = arvif->ar; +- ret = ath12k_mac_set_key(ar, cmd, vif, sta, key); ++ ++ if (sta) { ++ ahsta = (struct ath12k_sta *)sta->drv_priv; ++ arsta = &ahsta->deflink; ++ } ++ ret = ath12k_mac_set_key(ar, cmd, arvif, arsta, key); + + mutex_unlock(&ah->conf_mutex); + return ret; +@@ -4752,8 +5057,8 @@ ath12k_mac_bitrate_mask_num_eht_rates(st + } + + static int +-ath12k_mac_set_peer_vht_fixed_rate(struct ath12k_vif *arvif, +- struct ieee80211_sta *sta, ++ath12k_mac_set_peer_vht_fixed_rate(struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta, + const struct cfg80211_bitrate_mask *mask, + enum nl80211_band band) + { +@@ -4761,6 +5066,10 @@ ath12k_mac_set_peer_vht_fixed_rate(struc + u8 vht_rate, nss; + u32 rate_code; + int ret, i; ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + + lockdep_assert_held(&ar->conf_mutex); + +@@ -4798,8 +5107,8 @@ ath12k_mac_set_peer_vht_fixed_rate(struc + } + + static int +-ath12k_mac_set_peer_he_fixed_rate(struct ath12k_vif *arvif, +- struct ieee80211_sta *sta, ++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) + { +@@ -4807,6 +5116,10 @@ ath12k_mac_set_peer_he_fixed_rate(struct + u8 he_rate, nss; + u32 rate_code; + int ret, i; ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + + lockdep_assert_held(&ar->conf_mutex); + +@@ -4849,8 +5162,8 @@ ath12k_mac_set_peer_he_fixed_rate(struct + } + + static int +-ath12k_mac_set_peer_ht_fixed_rate(struct ath12k_vif *arvif, +- struct ieee80211_sta *sta, ++ath12k_mac_set_peer_ht_fixed_rate(struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta, + const struct cfg80211_bitrate_mask *mask, + enum nl80211_band band) + { +@@ -4858,6 +5171,10 @@ ath12k_mac_set_peer_ht_fixed_rate(struct + u8 ht_rate, nss; + u32 rate_code; + int ret, i; ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + + lockdep_assert_held(&ar->conf_mutex); + +@@ -4900,8 +5217,8 @@ ath12k_mac_set_peer_ht_fixed_rate(struct + } + + static int +-ath12k_mac_set_peer_eht_fixed_rate(struct ath12k_vif *arvif, +- struct ieee80211_sta *sta, ++ath12k_mac_set_peer_eht_fixed_rate(struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta, + const struct cfg80211_bitrate_mask *mask, + enum nl80211_band band) + { +@@ -4909,6 +5226,10 @@ ath12k_mac_set_peer_eht_fixed_rate(struc + u8 eht_rate, nss; + u32 rate_code; + int ret, i; ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + + lockdep_assert_held(&ar->conf_mutex); + +@@ -4953,9 +5274,12 @@ ath12k_mac_set_peer_eht_fixed_rate(struc + static int ath12k_station_assoc(struct ath12k *ar, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, +- bool reassoc) ++ bool reassoc, u8 link_id) + { +- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); ++ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); ++ struct ath12k_link_vif *arvif = ahvif->link[link_id]; ++ struct ath12k_link_sta *arsta; ++ struct ath12k_sta *ahsta; + struct peer_assoc_params peer_arg; + int ret = 0; + struct cfg80211_chan_def def; +@@ -4965,13 +5289,19 @@ static int ath12k_station_assoc(struct a + + lockdep_assert_held(&ar->conf_mutex); + +- if (WARN_ON(ath12k_mac_vif_chan(vif, &def))) ++ if (!arvif) ++ return -EINVAL; ++ ++ if (WARN_ON(ath12k_mac_vif_chan(vif, &def, link_id))) + return -EPERM; + + band = def.chan->band; + mask = &arvif->bitrate_mask; + +- ath12k_peer_assoc_prepare(ar, vif, sta, &peer_arg, reassoc); ++ ahsta = (struct ath12k_sta *)sta->drv_priv; ++ arsta = ahsta->link[link_id]; ++ ++ ath12k_peer_assoc_prepare(ar, arvif, arsta, &peer_arg, reassoc); + + peer_arg.is_assoc = true; + ret = ath12k_wmi_send_peer_assoc_cmd(ar, &peer_arg); +@@ -4998,22 +5328,22 @@ static int ath12k_station_assoc(struct a + * Note that all other rates and NSS will be disabled for this peer. + */ + if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) { +- ret = ath12k_mac_set_peer_vht_fixed_rate(arvif, sta, mask, ++ ret = ath12k_mac_set_peer_vht_fixed_rate(arvif, arsta, mask, + band); + if (ret) + return ret; + } else if (sta->deflink.he_cap.has_he && num_he_rates == 1) { +- ret = ath12k_mac_set_peer_he_fixed_rate(arvif, sta, mask, ++ ret = ath12k_mac_set_peer_he_fixed_rate(arvif, arsta, mask, + band); + if (ret) + return ret; + } else if (sta->deflink.eht_cap.has_eht && num_eht_rates == 1) { +- ret = ath12k_mac_set_peer_eht_fixed_rate(arvif, sta, mask, ++ ret = ath12k_mac_set_peer_eht_fixed_rate(arvif, arsta, mask, + band); + if (ret) + return ret; + } else if (sta->deflink.ht_cap.ht_supported && num_ht_rates == 1) { +- ret = ath12k_mac_set_peer_ht_fixed_rate(arvif, sta, mask, ++ ret = ath12k_mac_set_peer_ht_fixed_rate(arvif, arsta, mask, + band); + if (ret) + return ret; +@@ -5042,7 +5372,7 @@ static int ath12k_station_assoc(struct a + } + + if (sta->wme && sta->uapsd_queues) { +- ret = ath12k_peer_assoc_qos_ap(ar, arvif, sta); ++ ret = ath12k_peer_assoc_qos_ap(ar, arvif, arsta); + if (ret) { + ath12k_warn(ar->ab, "failed to set qos params for STA %pM for vdev %i: %d\n", + sta->addr, arvif->vdev_id, ret); +@@ -5055,13 +5385,18 @@ static int ath12k_station_assoc(struct a + + static int ath12k_station_disassoc(struct ath12k *ar, + struct ieee80211_vif *vif, +- struct ieee80211_sta *sta) ++ struct ieee80211_sta *sta, ++ u8 link_id) + { +- struct ath12k_vif *arvif = (void *)vif->drv_priv; ++ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); ++ struct ath12k_link_vif *arvif = ahvif->link[link_id]; + int ret = 0; + + lockdep_assert_held(&ar->conf_mutex); + ++ if (!arvif) ++ return -EINVAL; ++ + if (!sta->wme) { + arvif->num_legacy_stations--; + ret = ath12k_recalc_rtscts_prot(arvif); +@@ -5075,8 +5410,9 @@ static int ath12k_station_disassoc(struc + static void ath12k_sta_rc_update_wk(struct work_struct *wk) + { + struct ath12k *ar; +- struct ath12k_vif *arvif; +- struct ath12k_sta *arsta; ++ struct ath12k_link_vif *arvif; ++ struct ath12k_vif *ahvif; ++ struct ath12k_link_sta *arsta; + struct ieee80211_sta *sta; + struct cfg80211_chan_def def; + enum nl80211_band band; +@@ -5090,12 +5426,14 @@ static void ath12k_sta_rc_update_wk(stru + struct peer_assoc_params peer_arg; + enum wmi_phy_mode peer_phymode; + +- arsta = container_of(wk, struct ath12k_sta, update_wk); ++ arsta = container_of(wk, struct ath12k_link_sta, update_wk); + sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv); + arvif = arsta->arvif; ++ ahvif = arvif->ahvif; + ar = arvif->ar; + +- if (WARN_ON(ath12k_mac_vif_chan(arvif->vif, &def))) ++ /* TODO get link_id and pass for ML - link STA */ ++ if (WARN_ON(ath12k_mac_vif_chan(ahvif->vif, &def, 0))) + return; + + band = def.chan->band; +@@ -5126,7 +5464,7 @@ static void ath12k_sta_rc_update_wk(stru + + if (changed & IEEE80211_RC_BW_CHANGED) { + /* Get the the peer phymode */ +- ath12k_peer_assoc_h_phymode(ar, arvif->vif, sta, &peer_arg); ++ ath12k_peer_assoc_h_phymode(ar, arvif, arsta, &peer_arg); + peer_phymode = peer_arg.peer_phymode; + + if (bw > bw_prev) { +@@ -5217,16 +5555,16 @@ static void ath12k_sta_rc_update_wk(stru + * across HT/VHT and for multiple VHT MCS support. + */ + if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) { +- ath12k_mac_set_peer_vht_fixed_rate(arvif, sta, mask, ++ ath12k_mac_set_peer_vht_fixed_rate(arvif, arsta, mask, + band); + } else if (sta->deflink.he_cap.has_he && num_he_rates == 1) { +- ath12k_mac_set_peer_he_fixed_rate(arvif, sta, mask, ++ ath12k_mac_set_peer_he_fixed_rate(arvif, arsta, mask, + band); + } else if (sta->deflink.eht_cap.has_eht && num_eht_rates == 1) { +- ath12k_mac_set_peer_eht_fixed_rate(arvif, sta, mask, ++ ath12k_mac_set_peer_eht_fixed_rate(arvif, arsta, mask, + band); + } else if (sta->deflink.ht_cap.ht_supported && num_ht_rates == 1) { +- ath12k_mac_set_peer_ht_fixed_rate(arvif, sta, mask, ++ ath12k_mac_set_peer_ht_fixed_rate(arvif, arsta, mask, + band); + } else { + /* If the peer is non-VHT/HE/EHT or no fixed VHT/HE/EHT +@@ -5244,7 +5582,7 @@ static void ath12k_sta_rc_update_wk(stru + ath12k_warn(ar->ab, + "failed to disable peer fixed rate for STA %pM ret %d\n", + sta->deflink.addr, err); +- ath12k_peer_assoc_prepare(ar, arvif->vif, sta, ++ ath12k_peer_assoc_prepare(ar, arvif, arsta, + &peer_arg, true); + + peer_arg.is_assoc = false; +@@ -5265,36 +5603,49 @@ err_rc_bw_changed: + static void ath12k_sta_set_4addr_wk(struct work_struct *wk) + { + struct ath12k *ar; +- struct ath12k_vif *arvif; +- struct ath12k_sta *arsta; ++ struct ath12k_link_vif *arvif; ++ struct ath12k_sta *ahsta; ++ struct ath12k_link_sta *arsta; + struct ieee80211_sta *sta; + int ret = 0; ++ u16 links_map; ++ u8 link_id; + +- arsta = container_of(wk, struct ath12k_sta, set_4addr_wk); +- sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv); +- arvif = arsta->arvif; +- ar = arvif->ar; ++ ahsta = container_of(wk, struct ath12k_sta, set_4addr_wk); ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + +- ath12k_dbg(ar->ab, ATH12K_DBG_MAC, +- "setting USE_4ADDR for peer %pM\n", sta->addr); ++ links_map = ahsta->links_map; + +- ret = ath12k_wmi_set_peer_param(ar, sta->addr, +- arvif->vdev_id, +- WMI_PEER_USE_4ADDR, 1); ++ for_each_set_bit(link_id, &links_map, IEEE80211_MLD_MAX_NUM_LINKS) { ++ arsta = ahsta->link[link_id]; ++ arvif = arsta->arvif; ++ ar = arvif->ar; + +- if (ret) +- ath12k_warn(ar->ab, "failed to set peer %pM 4addr capability: %d\n", +- sta->addr, ret); ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, ++ "setting USE_4ADDR for peer %pM\n", sta->addr); ++ ++ ret = ath12k_wmi_set_peer_param(ar, sta->addr, ++ arvif->vdev_id, ++ WMI_PEER_USE_4ADDR, 1); ++ if (ret) ++ ath12k_warn(ar->ab, "failed to set peer %pM 4addr capability: %d\n", ++ sta->addr, ret); ++ } + } + +-static int ath12k_mac_inc_num_stations(struct ath12k_vif *arvif, +- struct ieee80211_sta *sta) ++static int ath12k_mac_inc_num_stations(struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta) + { ++ struct ath12k_vif *ahvif = arvif->ahvif; + struct ath12k *ar = arvif->ar; ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + + lockdep_assert_held(&ar->conf_mutex); + +- if (arvif->vdev_type == WMI_VDEV_TYPE_STA && !sta->tdls) ++ if (ahvif->vdev_type == WMI_VDEV_TYPE_STA && !sta->tdls) + return 0; + + if (ar->num_stations >= ar->max_num_stations) +@@ -5305,32 +5656,44 @@ static int ath12k_mac_inc_num_stations(s + return 0; + } + +-static void ath12k_mac_dec_num_stations(struct ath12k_vif *arvif, +- struct ieee80211_sta *sta) ++static void ath12k_mac_dec_num_stations(struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta) + { ++ struct ath12k_vif *ahvif = arvif->ahvif; + struct ath12k *ar = arvif->ar; ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + + lockdep_assert_held(&ar->conf_mutex); + +- if (arvif->vdev_type == WMI_VDEV_TYPE_STA && !sta->tdls) ++ if (ahvif->vdev_type == WMI_VDEV_TYPE_STA && !sta->tdls) + return; + + ar->num_stations--; + } + + static int ath12k_mac_station_add(struct ath12k *ar, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta) ++ struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta) + { + struct ath12k_base *ab = ar->ab; +- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); +- struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ieee80211_vif *vif = arvif->ahvif->vif; ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; + struct peer_create_params peer_param; + int ret; + + lockdep_assert_held(&ar->conf_mutex); + +- ret = ath12k_mac_inc_num_stations(arvif, sta); ++ if (!arvif) ++ return -EINVAL; ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); ++ ++ ret = ath12k_mac_inc_num_stations(arvif, arsta); + if (ret) { + ath12k_warn(ab, "refusing to associate station: too many connected already (%d)\n", + ar->max_num_stations); +@@ -5395,7 +5758,7 @@ static int ath12k_mac_station_add(struct + + if (ab->hw_params->vdev_start_delay && + !arvif->is_started && +- arvif->vdev_type != WMI_VDEV_TYPE_AP) { ++ ahvif->vdev_type != WMI_VDEV_TYPE_AP) { + ret = ath12k_start_vdev_delay(ar, vif); + if (ret) { + ath12k_warn(ab, "failed to delay vdev start: %d\n", ret); +@@ -5416,7 +5779,7 @@ free_rx_stats: + kfree(arsta->rx_stats); + arsta->rx_stats = NULL; + dec_num_station: +- ath12k_mac_dec_num_stations(arvif, sta); ++ ath12k_mac_dec_num_stations(arvif, arsta); + exit: + return ret; + } +@@ -5429,14 +5792,22 @@ static int ath12k_mac_op_sta_state(struc + { + struct ath12k_hw *ah = hw->priv; + struct ath12k *ar; +- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); +- struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_link_vif *arvif; ++ struct ath12k_link_sta *arsta; ++ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; + struct ath12k_peer *peer; + int ret = 0; + ++ /* TODO handle ML link vif/sta separately */ ++ if (vif->valid_links) ++ return 0; ++ + mutex_lock(&ah->conf_mutex); + +- ar = ath12k_get_ar_by_vif(hw, vif); ++ arvif = &ahvif->deflink; ++ arsta = &ahsta->deflink; ++ ar = arvif->ar; + if (!ar) { + ath12k_err(NULL, "unable to determine device to set sta state\n"); + mutex_unlock(&ah->conf_mutex); +@@ -5447,19 +5818,23 @@ static int ath12k_mac_op_sta_state(struc + if ((old_state == IEEE80211_STA_NONE && + new_state == IEEE80211_STA_NOTEXIST)) { + cancel_work_sync(&arsta->update_wk); +- cancel_work_sync(&arsta->set_4addr_wk); ++ cancel_work_sync(&ahsta->set_4addr_wk); ++ ahsta->link[0] = NULL; ++ ahsta->links_map = 0; + } + + mutex_lock(&ar->conf_mutex); + + if (old_state == IEEE80211_STA_NOTEXIST && + new_state == IEEE80211_STA_NONE) { ++ ahsta->link[0] = arsta; ++ ahsta->links_map = 1; + memset(arsta, 0, sizeof(*arsta)); + arsta->arvif = arvif; + INIT_WORK(&arsta->update_wk, ath12k_sta_rc_update_wk); +- INIT_WORK(&arsta->set_4addr_wk, ath12k_sta_set_4addr_wk); ++ INIT_WORK(&ahsta->set_4addr_wk, ath12k_sta_set_4addr_wk); + +- ret = ath12k_mac_station_add(ar, vif, sta); ++ ret = ath12k_mac_station_add(ar, arvif, arsta); + if (ret) + ath12k_warn(ar->ab, "Failed to add station: %pM for VDEV: %d\n", + sta->addr, arvif->vdev_id); +@@ -5475,7 +5850,7 @@ static int ath12k_mac_op_sta_state(struc + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "Removed peer: %pM for VDEV: %d num_peers : %d\n", + sta->addr, arvif->vdev_id, ar->num_peers); + +- ath12k_mac_dec_num_stations(arvif, sta); ++ ath12k_mac_dec_num_stations(arvif, arsta); + spin_lock_bh(&ar->ab->base_lock); + peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr); + if (peer && peer->sta == sta) { +@@ -5501,7 +5876,7 @@ static int ath12k_mac_op_sta_state(struc + (vif->type == NL80211_IFTYPE_AP || + vif->type == NL80211_IFTYPE_MESH_POINT || + vif->type == NL80211_IFTYPE_ADHOC)) { +- ret = ath12k_station_assoc(ar, vif, sta, false); ++ ret = ath12k_station_assoc(ar, vif, sta, false, 0); + if (ret) + ath12k_warn(ar->ab, "Failed to associate station: %pM\n", + sta->addr); +@@ -5585,7 +5960,7 @@ static int ath12k_mac_op_sta_state(struc + (vif->type == NL80211_IFTYPE_AP || + vif->type == NL80211_IFTYPE_MESH_POINT || + vif->type == NL80211_IFTYPE_ADHOC)) { +- ret = ath12k_station_disassoc(ar, vif, sta); ++ ret = ath12k_station_disassoc(ar, vif, sta, 0); + if (ret) + ath12k_warn(ar->ab, "Failed to disassociate station: %pM\n", + sta->addr); +@@ -5602,13 +5977,25 @@ static int ath12k_mac_op_sta_set_txpwr(s + { + struct ath12k_hw *ah = hw->priv; + struct ath12k *ar; +- struct ath12k_vif *arvif = (void *)vif->drv_priv; ++ struct ath12k_vif *ahvif = (void *)vif->drv_priv; ++ struct ath12k_link_vif *arvif; + int ret = 0; + s16 txpwr; ++ /* TODO use link id from op after support is available */ ++ u8 link_id = 0; + + mutex_lock(&ah->conf_mutex); + +- ar = ath12k_get_ar_by_vif(hw, vif); ++ /* TODO get arvif based on link id */ ++ arvif = ahvif->link[link_id]; ++ ++ if (!arvif) { ++ ath12k_err(NULL, "unable to determine device to set sta txpwr\n"); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ ar = ath12k_get_ar_by_vif(hw, vif, link_id); + if (!ar) { + ath12k_err(NULL, "unable to determine device to set sta txpwr\n"); + ret = -EINVAL; +@@ -5652,11 +6039,11 @@ static void ath12k_mac_op_sta_set_4addr( + struct ieee80211_sta *sta, bool enabled) + { + struct ath12k_hw *ah = hw->priv; +- struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; + +- if (enabled && !arsta->use_4addr_set) { +- ieee80211_queue_work(ah->hw, &arsta->set_4addr_wk); +- arsta->use_4addr_set = true; ++ if (enabled && !ahsta->use_4addr_set) { ++ ieee80211_queue_work(ah->hw, &ahsta->set_4addr_wk); ++ ahsta->use_4addr_set = true; + } + } + +@@ -5665,13 +6052,23 @@ static void ath12k_mac_op_sta_rc_update( + struct ieee80211_sta *sta, + u32 changed) + { +- struct ath12k_hw *ah = hw->priv; + struct ath12k *ar; +- struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; +- struct ath12k_vif *arvif = (void *)vif->drv_priv; ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_vif *ahvif = (void *)vif->drv_priv; ++ struct ath12k_link_vif *arvif; ++ struct ath12k_link_sta *arsta; + struct ath12k_peer *peer; + u32 bw, smps; ++ /* TODO update link id after op supports */ ++ u8 link_id = 0; + ++ arvif = ahvif->link[link_id]; ++ arsta = ahsta->link[link_id]; ++ ++ if (!arvif) { ++ ath12k_err(NULL, "unable to determine device for sta update\n"); ++ return; ++ } + + if (arvif->is_created) + ar = arvif->ar; +@@ -5686,7 +6083,6 @@ static void ath12k_mac_op_sta_rc_update( + peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr); + if (!peer) { + spin_unlock_bh(&ar->ab->base_lock); +- mutex_unlock(&ah->conf_mutex); + ath12k_warn(ar->ab, "mac sta rc update failed to find peer %pM on vdev %i\n", + sta->addr, arvif->vdev_id); + return; +@@ -5765,14 +6161,14 @@ static void ath12k_mac_op_sta_rc_update( + ieee80211_queue_work(hw, &arsta->update_wk); + } + +-static int ath12k_conf_tx_uapsd(struct ath12k *ar, struct ieee80211_vif *vif, ++static int ath12k_conf_tx_uapsd(struct ath12k *ar, struct ath12k_link_vif *arvif, + u16 ac, bool enable) + { +- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); ++ struct ath12k_vif *ahvif = arvif->ahvif; + u32 value = 0; + int ret = 0; + +- if (arvif->vdev_type != WMI_VDEV_TYPE_STA) ++ if (ahvif->vdev_type != WMI_VDEV_TYPE_STA) + return 0; + + switch (ac) { +@@ -5794,20 +6190,21 @@ static int ath12k_conf_tx_uapsd(struct a + break; + } + ++ /* TODO move link specific ? */ + if (enable) +- arvif->u.sta.uapsd |= value; ++ ahvif->u.sta.uapsd |= value; + else +- arvif->u.sta.uapsd &= ~value; ++ ahvif->u.sta.uapsd &= ~value; + + ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id, + WMI_STA_PS_PARAM_UAPSD, +- arvif->u.sta.uapsd); ++ ahvif->u.sta.uapsd); + if (ret) { + ath12k_warn(ar->ab, "could not set uapsd params %d\n", ret); + goto exit; + } + +- if (arvif->u.sta.uapsd) ++ if (ahvif->u.sta.uapsd) + value = WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD; + else + value = WMI_STA_PS_RX_WAKE_POLICY_WAKE; +@@ -5823,10 +6220,9 @@ exit: + } + + static int ath12k_mac_conf_tx(struct ath12k *ar, +- struct ieee80211_vif *vif, u16 ac, ++ struct ath12k_link_vif *arvif, u16 ac, + const struct ieee80211_tx_queue_params *params) + { +- struct ath12k_vif *arvif = (void *)vif->drv_priv; + struct wmi_wmm_params_arg *p = NULL; + int ret; + +@@ -5867,7 +6263,7 @@ static int ath12k_mac_conf_tx(struct ath + goto exit; + } + +- ret = ath12k_conf_tx_uapsd(ar, vif, ac, params->uapsd); ++ ret = ath12k_conf_tx_uapsd(ar, arvif, ac, params->uapsd); + + if (ret) + ath12k_warn(ar->ab, "failed to set sta uapsd: %d\n", ret); +@@ -5883,13 +6279,22 @@ static int ath12k_mac_op_conf_tx(struct + { + struct ath12k_hw *ah = hw->priv; + struct ath12k *ar; +- struct ath12k_vif *arvif = (void *)vif->drv_priv; ++ struct ath12k_vif *ahvif = (void *)vif->drv_priv; ++ struct ath12k_link_vif *arvif; + int ret; + ++ mutex_lock(&ah->conf_mutex); ++ arvif = &ahvif->deflink; ++ ++ /* TODO replace arvif caching to link based ahvif caching */ ++ if (arvif == NULL) { ++ mutex_unlock(&ah->conf_mutex); ++ return 0; ++ } ++ + /* If the tx config is received before a vdev is assigned to vif + * cache the info to be updated once vdev is created + */ +- mutex_lock(&ah->conf_mutex); + if (!arvif->is_created) { + ath12k_dbg(NULL, ATH12K_DBG_MAC, + "tx queue params cached since vif is not assigned to radio\n"); +@@ -5904,7 +6309,7 @@ static int ath12k_mac_op_conf_tx(struct + ar = arvif->ar; + + mutex_lock(&ar->conf_mutex); +- ret = ath12k_mac_conf_tx(ar, vif, ac, params); ++ ret = ath12k_mac_conf_tx(ar, arvif, ac, params); + mutex_unlock(&ar->conf_mutex); + + return ret; +@@ -5976,10 +6381,11 @@ ath12k_create_ht_cap(struct ath12k *ar, + return ht_cap; + } + +-static int ath12k_mac_set_txbf_conf(struct ath12k_vif *arvif) ++static int ath12k_mac_set_txbf_conf(struct ath12k_link_vif *arvif) + { + u32 value = 0; + struct ath12k *ar = arvif->ar; ++ struct ath12k_vif *ahvif = arvif->ahvif; + int nsts; + int sound_dim; + u32 vht_cap = ar->pdev->cap.vht_cap; +@@ -6007,7 +6413,7 @@ static int ath12k_mac_set_txbf_conf(stru + value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFER; + + if ((vht_cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) && +- arvif->vdev_type == WMI_VDEV_TYPE_AP) ++ ahvif->vdev_type == WMI_VDEV_TYPE_AP) + value |= WMI_VDEV_PARAM_TXBF_MU_TX_BFER; + } + +@@ -6017,7 +6423,7 @@ static int ath12k_mac_set_txbf_conf(stru + value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFEE; + + if ((vht_cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) && +- arvif->vdev_type == WMI_VDEV_TYPE_STA) ++ ahvif->vdev_type == WMI_VDEV_TYPE_STA) + value |= WMI_VDEV_PARAM_TXBF_MU_TX_BFEE; + } + +@@ -6722,7 +7128,7 @@ static int ath12k_mac_vif_txmgmt_idr_rem + return 0; + } + +-static int ath12k_mac_mgmt_tx_wmi(struct ath12k *ar, struct ath12k_vif *arvif, ++static int ath12k_mac_mgmt_tx_wmi(struct ath12k *ar, struct ath12k_link_vif *arvif, + struct sk_buff *skb) + { + struct ath12k_base *ab = ar->ab; +@@ -6791,7 +7197,8 @@ static void ath12k_mgmt_over_wmi_tx_work + { + struct ath12k *ar = container_of(work, struct ath12k, wmi_mgmt_tx_work); + struct ath12k_skb_cb *skb_cb; +- struct ath12k_vif *arvif; ++ struct ath12k_vif *ahvif; ++ struct ath12k_link_vif *arvif; + struct sk_buff *skb; + int ret; + +@@ -6803,7 +7210,9 @@ static void ath12k_mgmt_over_wmi_tx_work + continue; + } + +- arvif = ath12k_vif_to_arvif(skb_cb->vif); ++ ahvif = ath12k_vif_to_ahvif(skb_cb->vif); ++ /* TODO check this for extending link specific */ ++ arvif = &ahvif->deflink; + mutex_lock(&ar->conf_mutex); + if (ar->allocated_vdev_map & (1LL << arvif->vdev_id) && + arvif->is_started) { +@@ -6867,20 +7276,23 @@ static void ath12k_mac_op_tx(struct ieee + struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB(skb); + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_vif *vif = info->control.vif; +- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); ++ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); ++ /* TODO extend link specific */ ++ struct ath12k_link_vif *arvif = &ahvif->deflink; + struct ath12k *ar = arvif->ar; + struct ath12k_hw *ah = ar->ah; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_key_conf *key = info->control.hw_key; +- struct ath12k_mgmt_frame_stats *mgmt_stats = &arvif->mgmt_stats; +- struct ath12k_sta *arsta = NULL; ++ struct ath12k_mgmt_frame_stats *mgmt_stats = &ahvif->mgmt_stats; ++ struct ath12k_sta *ahsta = NULL; ++ struct ath12k_link_sta *arsta = NULL; + struct ieee80211_sta *sta = control->sta; + u32 info_flags = info->flags; + bool is_prb_rsp; + u16 frm_type = 0; + int ret; + +- if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { ++ if (ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { + ieee80211_free_txskb(ah->hw, skb); + return; + } +@@ -6919,8 +7331,8 @@ static void ath12k_mac_op_tx(struct ieee + } + return; + } +- if (control->sta) +- arsta = (struct ath12k_sta *)control->sta->drv_priv; ++ if (sta) ++ ahsta = (struct ath12k_sta *)control->sta->drv_priv; + + /* Must call mac80211 tx status handler, else when stats is disabled we + * free the skb from driver. Own tx packets on monitor will also be +@@ -6932,7 +7344,7 @@ static void ath12k_mac_op_tx(struct ieee + test_bit(MONITOR_VDEV_CREATED, &ar->monitor_flags)) + skb_cb->flags |= ATH12K_SKB_TX_STATUS; + +- ret = ath12k_dp_tx(ar, arvif, arsta, skb); ++ ret = ath12k_dp_tx(ar, arvif, ahsta, skb); + if (unlikely(ret)) { + if (ret == -ENOMEM) + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "failed to transmit frame %d\n", +@@ -6943,13 +7355,11 @@ static void ath12k_mac_op_tx(struct ieee + ieee80211_free_txskb(ah->hw, skb); + } + +- if (ath12k_debugfs_is_extd_tx_stats_enabled(ar) && sta) { +- arsta = (struct ath12k_sta *)sta->drv_priv; +- if (arsta) { +- atomic_inc(&arsta->drv_tx_pkts.pkts_in); +- if (!ret) +- atomic_inc(&arsta->drv_tx_pkts.pkts_out); +- } ++ if (ath12k_debugfs_is_extd_tx_stats_enabled(ar) && ahsta) { ++ arsta = &ahsta->deflink; ++ atomic_inc(&arsta->drv_tx_pkts.pkts_in); ++ if (!ret) ++ atomic_inc(&arsta->drv_tx_pkts.pkts_out); + } + } + +@@ -7380,7 +7790,7 @@ static void ath12k_mac_op_stop(struct ie + } + + static u8 +-ath12k_mac_get_vdev_stats_id(struct ath12k_vif *arvif) ++ath12k_mac_get_vdev_stats_id(struct ath12k_link_vif *arvif) + { + struct ath12k_base *ab = arvif->ar->ab; + u8 vdev_stats_id = 0; +@@ -7402,50 +7812,53 @@ ath12k_mac_get_vdev_stats_id(struct ath1 + return vdev_stats_id; + } + +-static int ath12k_mac_setup_vdev_params_mbssid(struct ath12k_vif *arvif, ++static int ath12k_mac_setup_vdev_params_mbssid(struct ath12k_link_vif *arvif, + u32 *flags, u32 *tx_vdev_id) + { + struct ath12k *ar = arvif->ar; +- struct ath12k_vif *tx_arvif; ++ struct ath12k_link_vif *tx_arvif; + struct ieee80211_vif *tx_vif; ++ struct ath12k_vif *ahvif = arvif->ahvif; + + *tx_vdev_id = 0; +- tx_vif = arvif->vif->mbssid_tx_vif; ++ /* FIXME MBSSID with MLO */ ++ tx_vif = arvif->ahvif->vif->mbssid_tx_vif; + if (!tx_vif) { + *flags = WMI_HOST_VDEV_FLAGS_NON_MBSSID_AP; + return 0; + } + +- tx_arvif = (void *)tx_vif->drv_priv; ++ tx_arvif = &ath12k_vif_to_ahvif(tx_vif)->deflink; + +- if (arvif->vif->bss_conf.nontransmitted) { ++ if (ahvif->vif->bss_conf.nontransmitted) { + if (ar->ah->hw->wiphy != ieee80211_vif_to_wdev(tx_vif)->wiphy) + return -EINVAL; + + *flags = WMI_HOST_VDEV_FLAGS_NON_TRANSMIT_AP; +- *tx_vdev_id = ath12k_vif_to_arvif(tx_vif)->vdev_id; ++ *tx_vdev_id = tx_arvif->vdev_id; + } else if (tx_arvif == arvif) { + *flags = WMI_HOST_VDEV_FLAGS_TRANSMIT_AP; + } else { + return -EINVAL; + } + +- if (arvif->vif->bss_conf.ema_ap) ++ if (ahvif->vif->bss_conf.ema_ap) + *flags |= WMI_HOST_VDEV_FLAGS_EMA_MODE; + + return 0; + } + +-static int ath12k_mac_setup_vdev_create_params(struct ath12k_vif *arvif, ++static int ath12k_mac_setup_vdev_create_params(struct ath12k_link_vif *arvif, + struct vdev_create_params *params) + { ++ struct ath12k_vif *ahvif = arvif->ahvif; + struct ath12k *ar = arvif->ar; + struct ath12k_pdev *pdev = ar->pdev; + int ret; + + params->if_id = arvif->vdev_id; +- params->type = arvif->vdev_type; +- params->subtype = arvif->vdev_subtype; ++ params->type = ahvif->vdev_type; ++ params->subtype = ahvif->vdev_subtype; + params->pdev_id = pdev->pdev_id; + params->mbssid_flags = 0; + params->mbssid_tx_vdev_id = 0; +@@ -7479,10 +7892,11 @@ static int ath12k_mac_setup_vdev_create_ + } + + static void ath12k_mac_update_vif_offload(struct ath12k *ar, +- struct ieee80211_vif *vif) ++ struct ath12k_link_vif *arvif) + { + struct ath12k_base *ab = ar->ab; +- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ieee80211_vif *vif = ahvif->vif; + u32 param_id, param_value; + int ret; + +@@ -7494,14 +7908,14 @@ static void ath12k_mac_update_vif_offloa + IEEE80211_OFFLOAD_DECAP_ENABLED); + + if (vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED) +- arvif->tx_encap_type = ATH12K_HW_TXRX_ETHERNET; ++ ahvif->tx_encap_type = ATH12K_HW_TXRX_ETHERNET; + else if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags)) +- arvif->tx_encap_type = ATH12K_HW_TXRX_RAW; ++ ahvif->tx_encap_type = ATH12K_HW_TXRX_RAW; + else +- arvif->tx_encap_type = ATH12K_HW_TXRX_NATIVE_WIFI; ++ ahvif->tx_encap_type = ATH12K_HW_TXRX_NATIVE_WIFI; + + ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, +- param_id, arvif->tx_encap_type); ++ param_id, ahvif->tx_encap_type); + if (ret) { + ath12k_warn(ab, "failed to set vdev %d tx encap mode: %d\n", + arvif->vdev_id, ret); +@@ -7529,24 +7943,25 @@ static void ath12k_mac_op_update_vif_off + struct ieee80211_vif *vif) + { + struct ath12k_hw *ah = hw->priv; +- struct ath12k *ar; +- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); ++ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); ++ struct ath12k_link_vif *arvif; + + mutex_lock(&ah->conf_mutex); + ++ /* TODO ML link vifs handling, currently checking default only */ + /* If the update_vif_offload() is received from mac80211 before + * vdev is created, no action is needed since the flags would + * be applied right after vdev create based on vif->offload_flags + */ +- ar = ath12k_get_ar_by_vif(hw, vif); +- if (!ar) { ++ arvif = &ahvif->deflink; ++ if (!arvif->ar) { + ath12k_info(NULL, + "unable to determine device to apply vif encap/decap flags, setting will be applied on channel assignment\n"); + mutex_unlock(&ah->conf_mutex); + return; + } + +- ath12k_mac_update_vif_offload(ar, vif); ++ ath12k_mac_update_vif_offload(arvif->ar, arvif); + ath12k_dp_tx_update_bank_profile(arvif); + + mutex_unlock(&ah->conf_mutex); +@@ -7554,7 +7969,7 @@ static void ath12k_mac_op_update_vif_off + + static void ath12k_update_bcn_template_work(struct work_struct *work) + { +- struct ath12k_vif *arvif = container_of(work, struct ath12k_vif, ++ struct ath12k_link_vif *arvif = container_of(work, struct ath12k_link_vif, + update_bcn_template_work); + struct ath12k *ar = arvif->ar; + int ret = -EINVAL; +@@ -7573,7 +7988,7 @@ static void ath12k_update_bcn_template_w + + static void ath12k_update_obss_color_notify_work(struct work_struct *work) + { +- struct ath12k_vif *arvif = container_of(work, struct ath12k_vif, ++ struct ath12k_link_vif *arvif = container_of(work, struct ath12k_link_vif, + update_obss_color_notify_work); + struct ath12k *ar; + +@@ -7584,27 +7999,45 @@ static void ath12k_update_obss_color_not + + mutex_lock(&ar->conf_mutex); + if (arvif->is_created) +- ieeee80211_obss_color_collision_notify(arvif->vif, ++ ieeee80211_obss_color_collision_notify(arvif->ahvif->vif, + arvif->obss_color_bitmap, + GFP_KERNEL); + arvif->obss_color_bitmap = 0; + mutex_unlock(&ar->conf_mutex); + } + +-static int ath12k_mac_vdev_create(struct ath12k *ar, struct ieee80211_vif *vif) ++static int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif) + { ++ struct ieee80211_vif *vif = arvif->ahvif->vif; + struct ath12k_base *ab = ar->ab; +- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); ++ struct ath12k_vif *ahvif = arvif->ahvif; + struct ieee80211_hw *hw = ar->ah->hw; + struct vdev_create_params vdev_param = {0}; + struct peer_create_params peer_param; ++ struct ieee80211_bss_conf *link_conf; + u32 param_id, param_value; + u16 nss; + int i; + int ret, vdev_id; ++ u8 link_addr[ETH_ALEN]; ++ int txpower; + + lockdep_assert_held(&ar->conf_mutex); + ++ rcu_read_lock(); ++ ++ link_conf = rcu_dereference(vif->link_conf[arvif->link_id]); ++ ++ if (!link_conf) { ++ rcu_read_unlock(); ++ return -EINVAL; ++ } ++ ++ memcpy(link_addr, link_conf->addr, ETH_ALEN); ++ memcpy(arvif->addr, link_conf->addr, ETH_ALEN); ++ txpower = link_conf->txpower; ++ rcu_read_unlock(); ++ + /* Send vdev stats offload commands to firmware before first vdev + * creation. ie., when num_created_vdevs = 0 + */ +@@ -7625,22 +8058,22 @@ static int ath12k_mac_vdev_create(struct + vdev_id = __ffs64(ab->free_vdev_map); + + arvif->vdev_id = vdev_id; +- arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE; ++ ahvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE; + arvif->ar = ar; + + switch (vif->type) { + case NL80211_IFTYPE_UNSPECIFIED: + case NL80211_IFTYPE_STATION: +- arvif->vdev_type = WMI_VDEV_TYPE_STA; ++ ahvif->vdev_type = WMI_VDEV_TYPE_STA; + break; + case NL80211_IFTYPE_MESH_POINT: +- arvif->vdev_subtype = WMI_VDEV_SUBTYPE_MESH_11S; ++ ahvif->vdev_subtype = WMI_VDEV_SUBTYPE_MESH_11S; + fallthrough; + case NL80211_IFTYPE_AP: +- arvif->vdev_type = WMI_VDEV_TYPE_AP; ++ ahvif->vdev_type = WMI_VDEV_TYPE_AP; + break; + case NL80211_IFTYPE_MONITOR: +- arvif->vdev_type = WMI_VDEV_TYPE_MONITOR; ++ ahvif->vdev_type = WMI_VDEV_TYPE_MONITOR; + ar->monitor_vdev_id = vdev_id; + break; + default: +@@ -7649,7 +8082,7 @@ static int ath12k_mac_vdev_create(struct + } + + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev create id %d type %d subtype %d map %llx\n", +- arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype, ++ arvif->vdev_id, ahvif->vdev_type, ahvif->vdev_subtype, + ab->free_vdev_map); + + /* TODO Revisit this sharing of common queues across all ar's */ +@@ -7664,7 +8097,7 @@ static int ath12k_mac_vdev_create(struct + goto err; + } + +- ret = ath12k_wmi_vdev_create(ar, vif->addr, &vdev_param); ++ ret = ath12k_wmi_vdev_create(ar, link_addr, &vdev_param); + if (ret) { + ath12k_warn(ab, "failed to create WMI vdev %d: %d\n", + arvif->vdev_id, ret); +@@ -7674,7 +8107,7 @@ static int ath12k_mac_vdev_create(struct + ar->num_created_vdevs++; + arvif->is_created = true; + ath12k_dbg(ab, ATH12K_DBG_MAC, "vdev %pM created, vdev_id %d\n", +- vif->addr, arvif->vdev_id); ++ link_addr, arvif->vdev_id); + + ar->allocated_vdev_map |= 1LL << arvif->vdev_id; + ab->free_vdev_map &= ~(1LL << arvif->vdev_id); +@@ -7683,7 +8116,7 @@ static int ath12k_mac_vdev_create(struct + list_add(&arvif->list, &ar->arvifs); + spin_unlock_bh(&ar->data_lock); + +- ath12k_mac_update_vif_offload(ar, vif); ++ ath12k_mac_update_vif_offload(ar, arvif); + + nss = get_num_chains(ar->cfg_tx_chainmask) ? : 1; + ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, +@@ -7694,10 +8127,10 @@ static int ath12k_mac_vdev_create(struct + goto err_vdev_del; + } + +- switch (arvif->vdev_type) { ++ switch (ahvif->vdev_type) { + case WMI_VDEV_TYPE_AP: + peer_param.vdev_id = arvif->vdev_id; +- peer_param.peer_addr = vif->addr; ++ peer_param.peer_addr = link_addr; + peer_param.peer_type = WMI_PEER_TYPE_DEFAULT; + ret = ath12k_peer_create(ar, arvif, NULL, &peer_param); + if (ret) { +@@ -7758,7 +8191,7 @@ static int ath12k_mac_vdev_create(struct + break; + } + +- arvif->txpower = vif->bss_conf.txpower; ++ arvif->txpower = txpower; + ret = ath12k_mac_txpower_recalc(ar); + if (ret) + goto err_peer_del; +@@ -7787,19 +8220,19 @@ static int ath12k_mac_vdev_create(struct + return ret; + + err_peer_del: +- if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { ++ if (ahvif->vdev_type == WMI_VDEV_TYPE_AP) { + reinit_completion(&ar->peer_delete_done); + +- ret = ath12k_wmi_send_peer_delete_cmd(ar, vif->addr, ++ ret = ath12k_wmi_send_peer_delete_cmd(ar, link_addr, + arvif->vdev_id); + if (ret) { + ath12k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n", +- arvif->vdev_id, vif->addr); ++ arvif->vdev_id, link_addr); + goto err; + } + + ret = ath12k_wait_for_peer_delete_done(ar, arvif->vdev_id, +- vif->addr); ++ link_addr); + if (ret) + goto err; + +@@ -7825,13 +8258,17 @@ err: + static void ath12k_mac_vif_cache_flush(struct ath12k *ar, struct ieee80211_vif *vif) + { + struct ath12k_hw *ah = ar->ah; +- struct ath12k_vif *arvif = (void *)vif->drv_priv; ++ struct ath12k_vif *ahvif = (void *)vif->drv_priv; ++ struct ath12k_link_vif *arvif; + int ret; + + lockdep_assert_held(&ah->conf_mutex); + ++ /* TODO extend for all link vifs */ ++ arvif = &ahvif->deflink; ++ + if (arvif->cache.tx_conf.changed) { +- ret = ath12k_mac_conf_tx(ar, vif, arvif->cache.tx_conf.ac, ++ ret = ath12k_mac_conf_tx(ar, arvif, arvif->cache.tx_conf.ac, + &arvif->cache.tx_conf.tx_queue_params); + if (ret) + ath12k_warn(ar->ab, +@@ -7839,13 +8276,13 @@ static void ath12k_mac_vif_cache_flush(s + } + + if (arvif->cache.bss_conf_changed) { +- ath12k_mac_bss_info_changed(ar, vif, &vif->bss_conf, ++ ath12k_mac_bss_info_changed(ar, arvif, &vif->bss_conf, + arvif->cache.bss_conf_changed); + } + + if (arvif->cache.key_conf.changed) { + ret = ath12k_mac_set_key(ar, arvif->cache.key_conf.cmd, +- vif, arvif->cache.key_conf.sta, ++ arvif, NULL, + arvif->cache.key_conf.key); + if (ret) + ath12k_warn(ar->ab, "unable to apply set key param to vdev %d ret %d\n", +@@ -7856,13 +8293,13 @@ static void ath12k_mac_vif_cache_flush(s + } + + static struct ath12k *ath12k_mac_assign_vif_to_vdev(struct ieee80211_hw *hw, +- struct ieee80211_vif *vif, ++ struct ath12k_link_vif *arvif, + struct ieee80211_chanctx_conf *ctx) + { + struct ath12k_hw *ah = hw->priv; + struct ath12k *ar; + struct ath12k_base *ab; +- struct ath12k_vif *arvif = (void *)vif->drv_priv; ++ struct ieee80211_vif *vif = arvif->ahvif->vif; + u8 bit; + int ret; + +@@ -7897,7 +8334,7 @@ static struct ath12k *ath12k_mac_assign_ + goto unlock; + } + +- ret = ath12k_mac_vdev_create(ar, vif); ++ ret = ath12k_mac_vdev_create(ar, arvif); + if (ret) { + ath12k_warn(ab, "failed to create vdev %d ret %d", bit, ret); + goto unlock; +@@ -7917,7 +8354,7 @@ out: + static int ath12k_mac_op_add_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) + { +- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); ++ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + struct ath12k_hw *ah = hw->priv; + int i; + +@@ -7930,29 +8367,16 @@ static int ath12k_mac_op_add_interface(s + */ + + mutex_lock(&ah->conf_mutex); +- memset(arvif, 0, sizeof(*arvif)); +- +- arvif->vdev_type = vif->type; +- arvif->vif = vif; ++ memset(ahvif, 0, sizeof(*ahvif)); + +- INIT_LIST_HEAD(&arvif->list); +- arvif->key_cipher = INVALID_CIPHER; ++ ahvif->vdev_type = vif->type; ++ ahvif->vif = vif; ++ ahvif->ah = ah; + +- INIT_WORK(&arvif->update_obss_color_notify_work, ath12k_update_obss_color_notify_work); +- INIT_WORK(&arvif->update_bcn_template_work, ath12k_update_bcn_template_work); ++ ahvif->deflink.ahvif = ahvif; ++ ahvif->deflink.link_id = 0; + +- 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_FORCE_SGI; +- 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)); +- memset(arvif->bitrate_mask.control[i].eht_mcs, 0xff, +- sizeof(arvif->bitrate_mask.control[i].eht_mcs)); +- } ++ ahvif->key_cipher = INVALID_CIPHER; + + /* Allocate Default Queue now and reassign during actual vdev create */ + vif->cab_queue = ATH12K_HW_DEFAULT_QUEUE; +@@ -7989,25 +8413,25 @@ static void ath12k_mac_vif_unref(struct + } + } + +-static void ath12k_mac_op_remove_interface(struct ieee80211_hw *hw, +- struct ieee80211_vif *vif) ++static void ath12k_mac_remove_link_interface(struct ieee80211_hw *hw, ++ struct ath12k_link_vif *arvif) + { + struct ath12k_hw *ah = hw->priv; + struct ath12k *ar; +- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ieee80211_vif *vif = ahvif->vif; + struct ath12k_base *ab; + int ret; + + cancel_work_sync(&arvif->update_obss_color_notify_work); + cancel_work_sync(&arvif->update_bcn_template_work); + +- mutex_lock(&ah->conf_mutex); ++ lockdep_assert_held(&ah->conf_mutex); + +- ar = ath12k_get_ar_by_vif(hw, vif); ++ ar = arvif->ar; + if (!ar) { + ath12k_dbg(NULL, ATH12K_DBG_MAC, + "unable to determine device to remove interface\n"); +- mutex_unlock(&ah->conf_mutex); + return; + } + +@@ -8023,18 +8447,18 @@ static void ath12k_mac_op_remove_interfa + ath12k_warn(ab, "failed to stop spectral for vdev %i: %d\n", + arvif->vdev_id, ret); + +- if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { +- ret = ath12k_peer_delete(ar, arvif->vdev_id, vif->addr); ++ if (ahvif->vdev_type == WMI_VDEV_TYPE_AP) { ++ ret = ath12k_peer_delete(ar, arvif->vdev_id, arvif->addr); + if (ret) + ath12k_warn(ab, "failed to submit AP self-peer removal on vdev %d: %d" + " num_peer : %d\n", arvif->vdev_id, ret, ar->num_peers); + } + +- ret = ath12k_mac_vdev_delete(ar, vif); ++ ret = ath12k_mac_vdev_delete(ar, arvif); + if (ret) + goto err_vdev_del; + +- if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { ++ if (ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { + ar->monitor_vdev_id = -1; + clear_bit(MONITOR_VDEV_CREATED, &ar->monitor_flags); + } else if (test_bit(MONITOR_VDEV_CREATED, &ar->monitor_flags) && +@@ -8043,7 +8467,7 @@ static void ath12k_mac_op_remove_interfa + } + + ath12k_dbg(ab, ATH12K_DBG_MAC, "vdev %pM deleted, vdev_id %d\n", +- vif->addr, arvif->vdev_id); ++ arvif->addr, arvif->vdev_id); + + err_vdev_del: + ath12k_peer_cleanup(ar, arvif->vdev_id); +@@ -8055,7 +8479,7 @@ err_vdev_del: + + ath12k_mac_vif_unref(&ab->dp, vif); + ath12k_dp_tx_put_bank_profile(&ab->dp, arvif->bank_id); +- arvif->key_cipher = INVALID_CIPHER; ++ ahvif->key_cipher = INVALID_CIPHER; + + /* Recalc txpower for remaining vdev */ + ath12k_mac_txpower_recalc(ar); +@@ -8067,6 +8491,35 @@ err_vdev_del: + /* TODO: recal traffic pause state based on the available vdevs */ + + mutex_unlock(&ar->conf_mutex); ++} ++ ++static void ath12k_mac_op_remove_interface(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif) ++{ ++ struct ath12k_hw *ah = hw->priv; ++ struct ath12k_vif *ahvif = (void *)vif->drv_priv; ++ struct ath12k_link_vif *arvif; ++ u16 links_map; ++ u8 link_id; ++ ++ mutex_lock(&ah->conf_mutex); ++ ++ links_map = ahvif->links_map; ++ ++ for_each_set_bit(link_id, &links_map, IEEE80211_MLD_MAX_NUM_LINKS) { ++ arvif = ahvif->link[link_id]; ++ ++ if (arvif == NULL) ++ continue; ++ ++ ath12k_mac_remove_link_interface(hw, arvif); ++ ++ if (arvif != &ahvif->deflink) ++ kfree(arvif); ++ ++ ahvif->link[link_id] = NULL; ++ } ++ + mutex_unlock(&ah->conf_mutex); + } + +@@ -8162,9 +8615,13 @@ static int ath12k_mac_op_ampdu_action(st + struct ath12k *ar; + int ret = -EINVAL; + ++ /* TODO handle for ML link vifs */ ++ if (vif->valid_links) ++ return 0; ++ + mutex_lock(&ah->conf_mutex); + +- ar = ath12k_get_ar_by_vif(hw, vif); ++ ar = ath12k_get_ar_by_vif(hw, vif, 0); + if (!ar) { + ath12k_err(NULL, "unable to determine device to set ampdu params\n"); + mutex_unlock(&ah->conf_mutex); +@@ -8258,17 +8715,32 @@ static void ath12k_mac_op_remove_chanctx + mutex_unlock(&ar->conf_mutex); + } + +-static int ath12k_mac_set_6g_nonht_dup_conf(struct ath12k_vif *arvif, +- const struct cfg80211_chan_def *chandef) ++static int ath12k_mac_set_6g_nonht_dup_conf(struct ath12k_link_vif *arvif, ++ const struct cfg80211_chan_def *chandef) + { + struct ath12k *ar = arvif->ar; + int param_id, ret = 0; + uint8_t value = 0; + bool is_psc = cfg80211_channel_is_psc(chandef->chan); + enum wmi_phy_mode mode = ath12k_phymodes[chandef->chan->band][chandef->width]; ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ieee80211_bss_conf *link_conf; ++ u8 link_addr[ETH_ALEN]; ++ ++ rcu_read_lock(); ++ ++ link_conf = rcu_dereference(ahvif->vif->link_conf[arvif->link_id]); ++ ++ if (!link_conf) { ++ rcu_read_unlock(); ++ return -EINVAL; ++ } + +- if ((arvif->vdev_type == WMI_VDEV_TYPE_AP) && +- !arvif->vif->bss_conf.nontransmitted && ++ memcpy(link_addr, link_conf->addr, ETH_ALEN); ++ rcu_read_unlock(); ++ ++ if ((ahvif->vdev_type == WMI_VDEV_TYPE_AP) && ++ !ahvif->vif->bss_conf.nontransmitted && + (chandef->chan->band == NL80211_BAND_6GHZ)) { + param_id = WMI_VDEV_PARAM_6GHZ_PARAMS; + if (mode > MODE_11AX_HE20 && !is_psc) { +@@ -8278,17 +8750,18 @@ static int ath12k_mac_set_6g_nonht_dup_c + } + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, + "Set 6GHz non-ht dup params for vdev %pM ,vdev_id %d param %d value %d\n", +- arvif->vif->addr, arvif->vdev_id, param_id, value); ++ link_addr, arvif->vdev_id, param_id, value); + ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param_id, value); + } + return ret; + } + + static int +-ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif, ++ath12k_mac_vdev_start_restart(struct ath12k_link_vif *arvif, + const struct cfg80211_chan_def *chandef, + bool restart, bool radar_enabled) + { ++ struct ath12k_vif *ahvif = arvif->ahvif; + struct ath12k *ar = arvif->ar; + struct ath12k_base *ab = ar->ab; + struct wmi_vdev_start_req_arg arg = {}; +@@ -8328,10 +8801,10 @@ ath12k_mac_vdev_start_restart(struct ath + return ret; + } + +- if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { +- arg.ssid = arvif->u.ap.ssid; +- arg.ssid_len = arvif->u.ap.ssid_len; +- arg.hidden_ssid = arvif->u.ap.hidden_ssid; ++ if (ahvif->vdev_type == WMI_VDEV_TYPE_AP) { ++ arg.ssid = ahvif->u.ap.ssid; ++ arg.ssid_len = ahvif->u.ap.ssid_len; ++ arg.hidden_ssid = ahvif->u.ap.hidden_ssid; + + /* For now allow DFS for AP mode */ + arg.channel.chan_radar = +@@ -8371,16 +8844,16 @@ ath12k_mac_vdev_start_restart(struct ath + + if (ar->supports_6ghz && + chandef->chan->band == NL80211_BAND_6GHZ && +- (arvif->vdev_type == WMI_VDEV_TYPE_STA || arvif->vdev_type == WMI_VDEV_TYPE_AP) && ++ (ahvif->vdev_type == WMI_VDEV_TYPE_STA || ahvif->vdev_type == WMI_VDEV_TYPE_AP) && + test_bit(WMI_TLV_SERVICE_EXT_TPC_REG_SUPPORT, ar->ab->wmi_ab.svc_map)) { +- ath12k_mac_fill_reg_tpc_info(ar, arvif->vif, &arvif->chanctx); ++ ath12k_mac_fill_reg_tpc_info(ar, arvif, &arvif->chanctx); + ath12k_wmi_send_vdev_set_tpc_power(ar, arvif->vdev_id, + &arvif->reg_tpc_info); + } + + ar->num_started_vdevs++; + ath12k_dbg(ab, ATH12K_DBG_MAC, "vdev %pM started, vdev_id %d\n", +- arvif->vif->addr, arvif->vdev_id); ++ arvif->addr, arvif->vdev_id); + + /* Enable CAC Flag in the driver by checking the channel DFS cac time, + * i.e dfs_cac_ms value which will be valid only for radar channels +@@ -8389,7 +8862,7 @@ ath12k_mac_vdev_start_restart(struct ath + * during CAC. + */ + /* TODO Set the flag for other interface types as required */ +- if (arvif->vdev_type == WMI_VDEV_TYPE_AP && ++ if (ahvif->vdev_type == WMI_VDEV_TYPE_AP && + chandef->chan->dfs_cac_ms && + chandef->chan->dfs_state == NL80211_DFS_USABLE) { + set_bit(ATH12K_CAC_RUNNING, &ar->dev_flags); +@@ -8411,7 +8884,7 @@ ath12k_mac_vdev_start_restart(struct ath + return 0; + } + +-static int ath12k_mac_vdev_stop(struct ath12k_vif *arvif) ++static int ath12k_mac_vdev_stop(struct ath12k_link_vif *arvif) + { + struct ath12k *ar = arvif->ar; + int ret; +@@ -8438,7 +8911,7 @@ static int ath12k_mac_vdev_stop(struct a + + ar->num_started_vdevs--; + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "vdev %pM stopped, vdev_id %d\n", +- arvif->vif->addr, arvif->vdev_id); ++ arvif->addr, arvif->vdev_id); + + if (test_bit(ATH12K_CAC_RUNNING, &ar->dev_flags)) { + clear_bit(ATH12K_CAC_RUNNING, &ar->dev_flags); +@@ -8451,7 +8924,7 @@ err: + return ret; + } + +-static int ath12k_mac_vdev_start(struct ath12k_vif *arvif, ++static int ath12k_mac_vdev_start(struct ath12k_link_vif *arvif, + const struct cfg80211_chan_def *chandef, + bool radar_enabled) + { +@@ -8459,7 +8932,7 @@ static int ath12k_mac_vdev_start(struct + radar_enabled); + } + +-static int ath12k_mac_vdev_restart(struct ath12k_vif *arvif, ++static int ath12k_mac_vdev_restart(struct ath12k_link_vif *arvif, + const struct cfg80211_chan_def *chandef, + bool pseudo_restart, bool radar_enabled) + { +@@ -8487,17 +8960,18 @@ static int ath12k_mac_vdev_restart(struc + return ret; + } + +-static int ath12k_vdev_restart_sequence(struct ath12k_vif *arvif, ++static int ath12k_vdev_restart_sequence(struct ath12k_link_vif *arvif, + struct ieee80211_chanctx_conf *new_ctx, + u64 vif_down_failed_map, + int vdev_index) + { + struct ath12k *ar = arvif->ar; +- struct ath12k_vif *tx_arvif; ++ struct ath12k_link_vif *tx_arvif; ++ struct ath12k_vif *tx_ahvif; + struct ieee80211_chanctx_conf old_chanctx; +- struct ieee80211_vif *tx_vif; + struct vdev_up_params params = { 0 }; + int ret = -EINVAL; ++ struct ath12k_vif *ahvif = arvif->ahvif; + + spin_lock_bh(&ar->data_lock); + old_chanctx = arvif->chanctx; +@@ -8530,13 +9004,14 @@ static int ath12k_vdev_restart_sequence( + } + + params.vdev_id = arvif->vdev_id; +- params.aid = arvif->aid; ++ params.aid = ahvif->aid; + params.bssid = arvif->bssid; +- if (arvif->vif->mbssid_tx_vif) { +- tx_vif = arvif->vif->mbssid_tx_vif; +- tx_arvif = ath12k_vif_to_arvif(tx_vif); ++ if (ahvif->vif->mbssid_tx_vif) { ++ tx_ahvif = (void *) ahvif->vif->mbssid_tx_vif->drv_priv; ++ /* TODO ML mbssid changes */ ++ tx_arvif = &tx_ahvif->deflink; + params.tx_bssid = tx_arvif->bssid; +- params.profile_idx = arvif->vif->bss_conf.bssid_index; ++ params.profile_idx = ahvif->vif->bss_conf.bssid_index; + params.profile_count = tx_arvif->nontransmitting_vif_count; + } + +@@ -8562,36 +9037,79 @@ static void + ath12k_mac_change_chanctx_cnt_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) + { +- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); ++ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); ++ struct ath12k_link_vif *arvif; + struct ath12k_mac_change_chanctx_arg *arg = data; ++ u16 links_map; ++ u8 link_id; ++ struct ieee80211_bss_conf *link_conf; ++ struct ath12k_hw *ah = ahvif->ah; + +- if ((rcu_access_pointer(vif->bss_conf.chanctx_conf) != arg->ctx) || +- (arvif->ar != arg->ar)) +- return; ++ lockdep_assert_held(&ah->conf_mutex); ++ ++ links_map = ahvif->links_map; ++ ++ for_each_set_bit(link_id, &links_map, IEEE80211_MLD_MAX_NUM_LINKS) { ++ arvif = ahvif->link[link_id]; ++ ++ if (WARN_ON(arvif == NULL)) ++ continue; ++ ++ link_conf = rcu_dereference(vif->link_conf[arvif->link_id]); + +- arg->n_vifs++; ++ if (WARN_ON(link_conf == NULL)) ++ continue; ++ ++ if ((rcu_access_pointer(link_conf->chanctx_conf) != arg->ctx) || ++ (arvif->ar != arg->ar)) ++ continue; ++ ++ arg->n_vifs++; ++ } + } + + static void + ath12k_mac_change_chanctx_fill_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) + { +- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); ++ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); ++ struct ath12k_link_vif *arvif; + struct ath12k_mac_change_chanctx_arg *arg = data; + struct ieee80211_chanctx_conf *ctx; ++ u16 links_map; ++ u8 link_id; ++ struct ieee80211_bss_conf *link_conf; ++ struct ath12k_hw *ah = ahvif->ah; + +- ctx = rcu_access_pointer(vif->bss_conf.chanctx_conf); +- if ((ctx != arg->ctx) || +- (arvif->ar != arg->ar)) +- return; ++ lockdep_assert_held(&ah->conf_mutex); + +- if (WARN_ON(arg->next_vif == arg->n_vifs)) +- return; ++ links_map = ahvif->links_map; ++ ++ for_each_set_bit(link_id, &links_map, IEEE80211_MLD_MAX_NUM_LINKS) { ++ arvif = ahvif->link[link_id]; ++ ++ if (WARN_ON(arvif == NULL)) ++ continue; ++ ++ link_conf = rcu_dereference(vif->link_conf[arvif->link_id]); ++ ++ if (WARN_ON(link_conf == NULL)) ++ continue; + +- arg->vifs[arg->next_vif].vif = vif; +- arg->vifs[arg->next_vif].old_ctx = ctx; +- arg->vifs[arg->next_vif].new_ctx = ctx; +- arg->next_vif++; ++ ctx = rcu_access_pointer(link_conf->chanctx_conf); ++ if ((ctx != arg->ctx) || ++ (arvif->ar != arg->ar)) ++ continue; ++ ++ if (WARN_ON(arg->next_vif == arg->n_vifs)) ++ return; ++ ++ arg->vifs[arg->next_vif].vif = vif; ++ arg->vifs[arg->next_vif].old_ctx = ctx; ++ arg->vifs[arg->next_vif].new_ctx = ctx; ++ arg->vifs[arg->next_vif].link_conf = link_conf; ++ arg->next_vif++; ++ } + } + + static void ath12k_mac_num_chanctxs_iter(struct ieee80211_hw *hw, +@@ -8669,7 +9187,8 @@ ath12k_mac_update_vif_chan(struct ath12k + int n_vifs) + { + struct ath12k_base *ab = ar->ab; +- struct ath12k_vif *arvif, *tx_arvif; ++ struct ath12k_link_vif *arvif, *tx_arvif; ++ struct ath12k_vif *ahvif; + struct cfg80211_chan_def *chandef = NULL; + int ret; + int i, trans_vdev_index; +@@ -8689,7 +9208,11 @@ ath12k_mac_update_vif_chan(struct ath12k + tx_arvif = NULL; + + for (i = 0; i < n_vifs; i++) { +- arvif = (void *)vifs[i].vif->drv_priv; ++ ahvif = (void *)vifs[i].vif->drv_priv; ++ arvif = ahvif->link[vifs[i].link_conf->link_id]; ++ ++ if (WARN_ON(!arvif)) ++ continue; + + if (vifs[i].vif->type == NL80211_IFTYPE_MONITOR) + monitor_vif = true; +@@ -8708,10 +9231,11 @@ ath12k_mac_update_vif_chan(struct ath12k + if (!arvif->is_up) + continue; + +- if (arvif->vif->mbssid_tx_vif && +- arvif == (struct ath12k_vif *)arvif->vif->mbssid_tx_vif->drv_priv) { +- tx_vif = arvif->vif->mbssid_tx_vif; +- tx_arvif = ath12k_vif_to_arvif(tx_vif); ++ if (ahvif->vif->mbssid_tx_vif && ++ ahvif == (struct ath12k_vif *)ahvif->vif->mbssid_tx_vif->drv_priv) { ++ tx_vif = ahvif->vif->mbssid_tx_vif; ++ /* TODO ML mbssid changes */ ++ tx_arvif = &ath12k_vif_to_ahvif(tx_vif)->deflink; + trans_vdev_index = i; + } + +@@ -8740,12 +9264,16 @@ ath12k_mac_update_vif_chan(struct ath12k + } + + for (i = 0; i < n_vifs; i++) { +- arvif = (void *)vifs[i].vif->drv_priv; ++ ahvif = (void *)vifs[i].vif->drv_priv; ++ arvif = ahvif->link[vifs[i].link_conf->link_id]; ++ ++ if (WARN_ON(!arvif)) ++ continue; + + if (vifs[i].vif->type == NL80211_IFTYPE_MONITOR) + monitor_vif = true; + +- if (arvif->vif->mbssid_tx_vif && ++ if (ahvif->vif->mbssid_tx_vif && + arvif == tx_arvif) + continue; + +@@ -8875,7 +9403,8 @@ static int ath12k_start_vdev_delay(struc + struct ieee80211_vif *vif) + { + struct ath12k_base *ab = ar->ab; +- struct ath12k_vif *arvif = (void *)vif->drv_priv; ++ struct ath12k_vif *ahvif = (void *)vif->drv_priv; ++ struct ath12k_link_vif *arvif = &ahvif->deflink; + int ret; + + if (WARN_ON(arvif->is_started)) +@@ -8885,12 +9414,12 @@ static int ath12k_start_vdev_delay(struc + arvif->chanctx.radar_enabled); + if (ret) { + ath12k_warn(ab, "failed to start vdev %i addr %pM on freq %d: %d\n", +- arvif->vdev_id, vif->addr, ++ arvif->vdev_id, arvif->addr, + arvif->chanctx.def.chan->center_freq, ret); + return ret; + } + +- if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { ++ if (ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { + ret = ath12k_monitor_vdev_up(ar, arvif->vdev_id); + if (ret) { + ath12k_warn(ab, "failed put monitor up: %d\n", ret); +@@ -9101,11 +9630,12 @@ static void ath12k_mac_get_eirp_power(st + } + + void ath12k_mac_fill_reg_tpc_info(struct ath12k *ar, +- struct ieee80211_vif *vif, ++ struct ath12k_link_vif *arvif, + struct ieee80211_chanctx_conf *ctx) + { + struct ath12k_base *ab = ar->ab; +- struct ath12k_vif *arvif = (void *)vif->drv_priv; ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ieee80211_vif *vif = ahvif->vif; + struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + struct ath12k_reg_tpc_power_info *reg_tpc_info = &arvif->reg_tpc_info; + struct ieee80211_channel *chan, *temp_chan; +@@ -9120,9 +9650,9 @@ void ath12k_mac_fill_reg_tpc_info(struct + * AP cant parse its own beacon. Hence, we get the 6g power mode + * from the wdev corresponding to the struct ieee80211_vif + */ +- if (arvif->vdev_type == WMI_VDEV_TYPE_STA) ++ if (ahvif->vdev_type == WMI_VDEV_TYPE_STA) + reg_6g_power_mode = vif->bss_conf.power_type; +- else if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { ++ else if (ahvif->vdev_type == WMI_VDEV_TYPE_AP) { + struct wireless_dev *wdev = ieee80211_vif_to_wdev(vif); + /* With respect to ieee80211, the 6G AP power mode starts from index + * 1 while the power type stored in struct wireless_dev is based on +@@ -9140,7 +9670,7 @@ void ath12k_mac_fill_reg_tpc_info(struct + start_freq = ath12k_mac_get_6g_start_frequency(&ctx->def); + pwr_reduction = bss_conf->pwr_reduction; + +- if (arvif->vdev_type == WMI_VDEV_TYPE_STA && ++ if (ahvif->vdev_type == WMI_VDEV_TYPE_STA && + arvif->reg_tpc_info.num_pwr_levels) { + is_tpe_present = true; + num_pwr_levels = arvif->reg_tpc_info.num_pwr_levels; +@@ -9294,11 +9824,12 @@ void ath12k_mac_fill_reg_tpc_info(struct + } + + static void ath12k_mac_parse_tx_pwr_env(struct ath12k *ar, +- struct ieee80211_vif *vif, ++ struct ath12k_link_vif *arvif, + struct ieee80211_chanctx_conf *ctx) + { + struct ath12k_base *ab = ar->ab; +- struct ath12k_vif *arvif = (void *)vif->drv_priv; ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ieee80211_vif *vif = ahvif->vif; + struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + struct ieee80211_tx_pwr_env *single_tpe; + enum wmi_reg_6g_client_type client_type; +@@ -9426,21 +9957,34 @@ ath12k_mac_op_assign_vif_chanctx(struct + struct ath12k_hw *ah = hw->priv; + struct ath12k *ar, *arvif_ar; + struct ath12k_base *ab; +- struct ath12k_vif *arvif = (void *)vif->drv_priv; ++ struct ath12k_vif *ahvif = (void *)vif->drv_priv; ++ struct ath12k_link_vif *arvif; + int ret; + struct peer_create_params param; + enum ieee80211_ap_reg_power power_type; + ++ u8 link_id = link_conf->link_id; ++ + if (!ctx) + return -EINVAL; + + mutex_lock(&ah->conf_mutex); ++ ++ arvif = ath12k_mac_get_link_vif(ah, vif, link_id); ++ if (!arvif) { ++ ath12k_err(NULL, "unable to allocate link vif\n"); ++ return -ENOMEM; ++ } ++ + if (!arvif->is_created) { +- ar = ath12k_mac_assign_vif_to_vdev(hw, vif, ctx); ++ ar = ath12k_mac_assign_vif_to_vdev(hw, arvif, ctx); + if (!ar) { + mutex_unlock(&ah->conf_mutex); + return -EINVAL; + } ++ } else if(vif->valid_links){ ++ ar = arvif->ar; ++ /* Note below case not expected for MLO/not handled now */ + } else { + ar = ath12k_get_ar_by_ctx(hw, ctx); + if (!ar) { +@@ -9452,6 +9996,7 @@ ath12k_mac_op_assign_vif_chanctx(struct + + /* If vif is already assigned, but now the chan is different and belongs + * to a different ar, then delete the old vdev in different ar and create new ++ * This is not expected for MLO + */ + if (ar != arvif->ar) { + if (WARN_ON(arvif->is_started)) { +@@ -9462,13 +10007,13 @@ ath12k_mac_op_assign_vif_chanctx(struct + arvif_ar = arvif->ar; + + mutex_lock(&arvif_ar->conf_mutex); +- ret = ath12k_mac_vdev_delete(arvif_ar, vif); ++ ret = ath12k_mac_vdev_delete(arvif_ar, arvif); + mutex_unlock(&arvif_ar->conf_mutex); + if (ret) + ath12k_warn(arvif_ar->ab, "unable to delete vdev %d\n", ret); + + mutex_lock(&ar->conf_mutex); +- ret = ath12k_mac_vdev_create(ar, vif); ++ ret = ath12k_mac_vdev_create(ar, arvif); + if (ret) { + mutex_unlock(&ar->conf_mutex); + mutex_unlock(&ah->conf_mutex); +@@ -9488,8 +10033,8 @@ ath12k_mac_op_assign_vif_chanctx(struct + ctx, arvif->vdev_id); + + if (ar->supports_6ghz && ctx->def.chan->band == NL80211_BAND_6GHZ && +- (arvif->vdev_type == WMI_VDEV_TYPE_STA || +- arvif->vdev_type == WMI_VDEV_TYPE_AP)) { ++ (ahvif->vdev_type == WMI_VDEV_TYPE_STA || ++ ahvif->vdev_type == WMI_VDEV_TYPE_AP)) { + power_type = vif->bss_conf.power_type; + ath12k_dbg(ab, ATH12K_DBG_MAC, "mac chanctx power type %d\n", + power_type); +@@ -9500,16 +10045,16 @@ ath12k_mac_op_assign_vif_chanctx(struct + /* TODO: Transmit Power Envelope specification for 320 is not + * available yet. Need to add TPE 320 support when spec is ready + */ +- if (arvif->vdev_type == WMI_VDEV_TYPE_STA && ++ if (ahvif->vdev_type == WMI_VDEV_TYPE_STA && + ctx->def.width != NL80211_CHAN_WIDTH_320) { +- ath12k_mac_parse_tx_pwr_env(ar, vif, ctx); ++ ath12k_mac_parse_tx_pwr_env(ar, arvif, ctx); + } + } + + /* for some targets bss peer must be created before vdev_start */ + if (ab->hw_params->vdev_start_delay && +- arvif->vdev_type != WMI_VDEV_TYPE_AP && +- arvif->vdev_type != WMI_VDEV_TYPE_MONITOR && ++ ahvif->vdev_type != WMI_VDEV_TYPE_AP && ++ ahvif->vdev_type != WMI_VDEV_TYPE_MONITOR && + !ath12k_peer_find_by_vdev_id(ab, arvif->vdev_id)) { + memcpy(&arvif->chanctx, ctx, sizeof(*ctx)); + ret = 0; +@@ -9522,8 +10067,8 @@ ath12k_mac_op_assign_vif_chanctx(struct + } + + if (ab->hw_params->vdev_start_delay && +- (arvif->vdev_type == WMI_VDEV_TYPE_AP || +- arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)) { ++ (ahvif->vdev_type == WMI_VDEV_TYPE_AP || ++ ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR)) { + param.vdev_id = arvif->vdev_id; + param.peer_type = WMI_PEER_TYPE_DEFAULT; + param.peer_addr = ar->mac_addr; +@@ -9536,7 +10081,7 @@ ath12k_mac_op_assign_vif_chanctx(struct + } + } + +- if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { ++ if (ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { + ret = ath12k_mac_monitor_start(ar); + if (ret) + goto out; +@@ -9547,12 +10092,12 @@ ath12k_mac_op_assign_vif_chanctx(struct + ret = ath12k_mac_vdev_start(arvif, &ctx->def, ctx->radar_enabled); + if (ret) { + ath12k_warn(ab, "failed to start vdev %i addr %pM on freq %d: %d\n", +- arvif->vdev_id, vif->addr, ++ arvif->vdev_id, arvif->addr, + ctx->def.chan->center_freq, ret); + goto out; + } + +- if (arvif->vdev_type != WMI_VDEV_TYPE_MONITOR && ++ if (ahvif->vdev_type != WMI_VDEV_TYPE_MONITOR && + test_bit(MONITOR_VDEV_CREATED, &ar->monitor_flags)) + ath12k_mac_monitor_start(ar); + +@@ -9575,11 +10120,14 @@ ath12k_mac_op_unassign_vif_chanctx(struc + struct ieee80211_bss_conf *link_conf, + struct ieee80211_chanctx_conf *ctx) + { +- struct ath12k_vif *arvif = (void *)vif->drv_priv; ++ struct ath12k_vif *ahvif = (void *)vif->drv_priv; ++ struct ath12k_link_vif *arvif; + struct ath12k_hw *ah = hw->priv; + struct ath12k_base *ab; + struct ath12k *ar; + int ret; ++ /* TODO tmp, link_id passed through func */ ++ u8 link_id = 0; + + mutex_lock(&ah->conf_mutex); + /* The vif is expected to be attached to an ar's VDEV. +@@ -9589,7 +10137,17 @@ ath12k_mac_op_unassign_vif_chanctx(struc + * remove_interface() or when there is a change in channel + * that moves the vif to a new ar + */ +- ar = ath12k_get_ar_by_vif(hw, vif); ++ arvif = ahvif->link[link_id]; ++ ++ if (!arvif) { ++ ath12k_err(NULL, ++ "unable to determine the assigned link vif on link id %d\n", ++ link_id); ++ mutex_unlock(&ah->conf_mutex); ++ return; ++ } ++ ++ ar = arvif->ar; + if (!ar) { + ath12k_err(NULL, + "unable to determine device to stop vdev during channel unassign\n"); +@@ -9608,11 +10166,11 @@ ath12k_mac_op_unassign_vif_chanctx(struc + WARN_ON(!arvif->is_started); + + if (ab->hw_params->vdev_start_delay && +- arvif->vdev_type == WMI_VDEV_TYPE_MONITOR && ++ ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR && + ath12k_peer_find_by_addr(ab, ar->mac_addr)) + ath12k_peer_delete(ar, arvif->vdev_id, ar->mac_addr); + +- if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { ++ if (ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { + ret = ath12k_mac_monitor_stop(ar); + if (ret) + goto out; +@@ -9629,10 +10187,10 @@ ath12k_mac_op_unassign_vif_chanctx(struc + arvif->is_started = false; + + if (ab->hw_params->vdev_start_delay && +- arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) ++ ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) + ath12k_wmi_vdev_down(ar, arvif->vdev_id); + +- if (arvif->vdev_type != WMI_VDEV_TYPE_MONITOR && ++ if (ahvif->vdev_type != WMI_VDEV_TYPE_MONITOR && + ar->num_started_vdevs == 1 && + test_bit(MONITOR_VDEV_CREATED, &ar->monitor_flags)) + ath12k_mac_monitor_stop(ar); +@@ -9683,7 +10241,7 @@ ath12k_mac_op_switch_vif_chanctx(struct + static int + ath12k_set_vdev_param_to_all_vifs(struct ath12k *ar, int param, u32 value) + { +- struct ath12k_vif *arvif; ++ struct ath12k_link_vif *arvif; + int ret = 0; + + mutex_lock(&ar->conf_mutex); +@@ -9791,7 +10349,8 @@ static void ath12k_mac_op_flush(struct i + ar++; + } + } else { +- ar = ath12k_get_ar_by_vif(hw, vif); ++ /* TODO in case of ML links, flush all link vif */ ++ ar = ath12k_get_ar_by_vif(hw, vif, 0); + if (!ar) { + ath12k_err(NULL, + "unable to determine device for tx flush\n"); +@@ -9993,15 +10552,31 @@ ath12k_mac_get_single_legacy_rate(struct + } + + static int +-ath12k_mac_set_fixed_rate_GI_LTF(struct ath12k_vif *arvif, u8 gi, u8 ltf) ++ath12k_mac_set_fixed_rate_GI_LTF(struct ath12k_link_vif *arvif, u8 gi, u8 ltf) + { ++ struct ieee80211_vif *vif = arvif->ahvif->vif; ++ struct ieee80211_bss_conf *link_conf; + struct ath12k *ar = arvif->ar; + int param, ret; ++ bool eht_support; + + /* 0.8 = 0, 1.6 = 2 and 3.2 = 3. */ + if (gi && gi != 0xFF) + gi += 1; + ++ rcu_read_lock(); ++ ++ link_conf = rcu_dereference(vif->link_conf[arvif->link_id]); ++ ++ if (!link_conf) { ++ rcu_read_unlock(); ++ return -EINVAL; ++ } ++ ++ eht_support = link_conf->eht_support; ++ ++ rcu_read_unlock(); ++ + ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, + WMI_VDEV_PARAM_SGI, gi); + if (ret) { +@@ -10013,7 +10588,7 @@ ath12k_mac_set_fixed_rate_GI_LTF(struct + if (ltf != 0xFF) + ltf += 1; + +- if (arvif->vif->bss_conf.eht_support) ++ if (eht_support) + param = WMI_VDEV_PARAM_EHT_LTF; + else + param = WMI_VDEV_PARAM_HE_LTF; +@@ -10030,7 +10605,7 @@ ath12k_mac_set_fixed_rate_GI_LTF(struct + } + + static int +-ath12k_mac_set_auto_rate_GI_LTF(struct ath12k_vif *arvif, u16 gi, u8 ltf) ++ath12k_mac_set_auto_rate_GI_LTF(struct ath12k_link_vif *arvif, u16 gi, u8 ltf) + { + struct ath12k *ar = arvif->ar; + int ret; +@@ -10086,19 +10661,36 @@ ath12k_mac_set_auto_rate_GI_LTF(struct a + return 0; + } + +-static int ath12k_mac_set_rate_params(struct ath12k_vif *arvif, ++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, + u8 eht_gi, u8 eht_ltf, + bool eht_fixed_rate, + int he_ul_rate, u8 he_ul_nss) + { ++ struct ieee80211_vif *vif = arvif->ahvif->vif; ++ struct ieee80211_bss_conf *link_conf; + struct ath12k *ar = arvif->ar; + u32 vdev_param, rate_code; + int ret; ++ bool he_support, eht_support; + + lockdep_assert_held(&ar->conf_mutex); + ++ rcu_read_lock(); ++ ++ link_conf = rcu_dereference(vif->link_conf[arvif->link_id]); ++ ++ if (!link_conf) { ++ rcu_read_unlock(); ++ return -EINVAL; ++ } ++ ++ eht_support = link_conf->eht_support; ++ he_support = link_conf->he_support; ++ ++ rcu_read_unlock(); ++ + 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); +@@ -10111,7 +10703,7 @@ static int ath12k_mac_set_rate_params(st + "eht_gi:0x%02x, eht_ltf:0x%02x, eht_fixed_rate:%d\n", eht_gi, + eht_ltf, eht_fixed_rate); + +- if (!arvif->vif->bss_conf.he_support || !arvif->vif->bss_conf.eht_support) { ++ if (!he_support || !eht_support) { + vdev_param = WMI_VDEV_PARAM_FIXED_RATE; + ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, + vdev_param, rate); +@@ -10140,7 +10732,7 @@ static int ath12k_mac_set_rate_params(st + return ret; + } + +- if (arvif->vif->bss_conf.eht_support) { ++ if (eht_support) { + if (eht_fixed_rate) { + ret = ath12k_mac_set_fixed_rate_GI_LTF(arvif, eht_gi, + eht_ltf); +@@ -10150,7 +10742,7 @@ static int ath12k_mac_set_rate_params(st + } + if (ret) + return ret; +- } else if (arvif->vif->bss_conf.he_support) { ++ } else if (he_support) { + if (he_fixed_rate) { + ret = ath12k_mac_set_fixed_rate_GI_LTF(arvif, he_gi, + he_ltf); +@@ -10288,13 +10880,21 @@ ath12k_mac_eht_mcs_range_present(struct + static void ath12k_mac_set_bitrate_mask_iter(void *data, + struct ieee80211_sta *sta) + { +- struct ath12k_vif *arvif = data; +- struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_link_vif *arvif = data; ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_link_sta *arsta; + struct ath12k *ar = arvif->ar; ++ u8 link_id = arvif->link_id; + +- if (arsta->arvif != arvif) ++ if (ahsta->ahvif != arvif->ahvif) + return; + ++ /* Check if there is a link sta in the vif link */ ++ if (!(BIT(link_id) & ahsta->links_map)) ++ return; ++ ++ arsta = ahsta->link[link_id]; ++ + spin_lock_bh(&ar->data_lock); + arsta->changed |= IEEE80211_RC_SUPP_RATES_CHANGED; + spin_unlock_bh(&ar->data_lock); +@@ -10305,14 +10905,22 @@ static void ath12k_mac_set_bitrate_mask_ + static void ath12k_mac_disable_peer_fixed_rate(void *data, + struct ieee80211_sta *sta) + { +- struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; +- struct ath12k_vif *arvif = data; +- struct ath12k *ar = arvif->ar; ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_link_vif *arvif = data; ++ struct ath12k *ar; + int ret; ++ u8 link_id = arvif->link_id; + +- if (arsta->arvif != arvif) ++ if (ahsta->ahvif != arvif->ahvif) + return; + ++ /* Check if there is a link sta in the vif link */ ++ if (!(BIT(link_id) & ahsta->links_map)) ++ return; ++ ++ ar = arvif->ar; ++ ++ /* TODO move to sta->link addr */ + ret = ath12k_wmi_set_peer_param(ar, sta->addr, + arvif->vdev_id, + WMI_PEER_PARAM_FIXED_RATE, +@@ -10395,13 +11003,25 @@ exit: + } + + static bool +-ath12k_mac_check_fixed_rate_settings_for_mumimo(struct ath12k_vif *arvif, const u16 *vht_mcs_mask, const u16 *he_mcs_mask) ++ath12k_mac_check_fixed_rate_settings_for_mumimo(struct ath12k_link_vif *arvif, ++ const u16 *vht_mcs_mask, ++ const u16 *he_mcs_mask) + { + struct ath12k *ar = arvif->ar; + struct ieee80211_he_cap_elem he_cap_elem = {0}; + int nss_idx; + int he_nss; + int vht_nss; ++ struct ieee80211_bss_conf *link_conf; ++ ++ rcu_read_lock(); ++ ++ link_conf = rcu_dereference(arvif->ahvif->vif->link_conf[arvif->link_id]); ++ ++ if (!link_conf) { ++ rcu_read_unlock(); ++ return -EINVAL; ++ } + + vht_nss = ath12k_mac_max_vht_nss(vht_mcs_mask); + +@@ -10411,21 +11031,26 @@ ath12k_mac_check_fixed_rate_settings_for + continue; + + if (arvif->vht_cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) { ++ rcu_read_unlock(); + ath12k_warn(ar->ab, "vht fixed NSS rate is allowed only when MU MIMO is disabled\n"); + return false; + } + } + } + +- if (!arvif->vif->bss_conf.he_support) ++ if (!link_conf->he_support) { ++ rcu_read_unlock(); + return true; ++ } + + he_nss = ath12k_mac_max_he_nss(he_mcs_mask); + +- if (he_nss == 1) +- return true; ++ if (he_nss == 1) { ++ rcu_read_unlock(); ++ return true; ++ } + +- memcpy(&he_cap_elem, &arvif->vif->bss_conf.he_cap_elem, sizeof(he_cap_elem)); ++ memcpy(&he_cap_elem, &link_conf->he_cap_elem, sizeof(he_cap_elem)); + + for (nss_idx = he_nss-1; nss_idx >= 0; nss_idx--) { + if (he_mcs_mask[nss_idx]) +@@ -10433,11 +11058,13 @@ ath12k_mac_check_fixed_rate_settings_for + + if ((he_cap_elem.phy_cap_info[2] & IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO) || + (he_cap_elem.phy_cap_info[4] & IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER)) { +- ath12k_warn(ar->ab, "he fixed NSS rate is allowed only when MU MIMO is disabled\n"); +- return false; ++ rcu_read_unlock(); ++ ath12k_warn(ar->ab, "he fixed NSS rate is allowed only when MU MIMO is disabled\n"); ++ return false; + } + } + ++ rcu_read_unlock(); + return true; + } + +@@ -10447,7 +11074,7 @@ ath12k_mac_op_set_bitrate_mask(struct ie + const struct cfg80211_bitrate_mask *mask) + { + struct ath12k_hw *ah = hw->priv; +- struct ath12k_vif *arvif = (void *)vif->drv_priv; ++ struct ath12k_vif *ahvif = (void *)vif->drv_priv; + struct cfg80211_chan_def def; + struct ath12k *ar; + enum nl80211_band band; +@@ -10470,13 +11097,23 @@ ath12k_mac_op_set_bitrate_mask(struct ie + int he_ul_rate = -1; + bool he_fixed_rate = false; + bool eht_fixed_rate = false; ++ struct ath12k_link_vif *arvif; ++ /* TODO move after link id passed through this op */ ++ u8 link_id = 0; + +- if (ath12k_mac_vif_chan(vif, &def)) ++ if (ath12k_mac_vif_chan(vif, &def, link_id)) + return -EPERM; + + mutex_lock(&ah->conf_mutex); + +- ar = ath12k_get_ar_by_vif(hw, vif); ++ arvif = ahvif->link[link_id]; ++ ++ if (!arvif) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ ar = ath12k_get_ar_by_vif(hw, vif, link_id); + if (!ar) { + ath12k_err(NULL, + "unable to determine device to set bitrates, configs can be applied after device bringup\n"); +@@ -10792,14 +11429,14 @@ exit: + } + + void ath12k_mac_ap_ps_recalc(struct ath12k *ar) { +- struct ath12k_vif *arvif; ++ struct ath12k_link_vif *arvif; + enum ath12k_ap_ps_state state = ATH12K_AP_PS_STATE_OFF; + int ret; + bool allow_ap_ps = true; + + lockdep_assert_held(&ar->conf_mutex); + list_for_each_entry(arvif, &ar->arvifs, list) { +- if (arvif->vdev_type != WMI_VDEV_TYPE_AP) { ++ if (arvif->ahvif->vdev_type != WMI_VDEV_TYPE_AP) { + allow_ap_ps = false; + break; + } +@@ -10829,7 +11466,10 @@ static void ath12k_mac_op_sta_statistics + struct ieee80211_sta *sta, + struct station_info *sinfo) + { +- struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_link_sta *arsta = &ahsta->deflink; ++ ++ /* TODO accumulate link sta stats here? */ + + sinfo->rx_duration = arsta->rx_duration; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION); +@@ -10867,7 +11507,8 @@ static const struct ieee80211_ops ath12k + .remove_interface = ath12k_mac_op_remove_interface, + .update_vif_offload = ath12k_mac_op_update_vif_offload, + .config = ath12k_mac_op_config, +- .bss_info_changed = ath12k_mac_op_bss_info_changed, ++ .link_info_changed = ath12k_mac_op_bss_info_changed, ++ .vif_cfg_changed = ath12k_mac_op_vif_cfg_changed, + .configure_filter = ath12k_mac_op_configure_filter, + .hw_scan = ath12k_mac_op_hw_scan, + .cancel_hw_scan = ath12k_mac_op_cancel_hw_scan, +@@ -11558,6 +12199,9 @@ static int ath12k_mac_hw_register(struct + hw->wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE | + NL80211_FEATURE_AP_SCAN; + ++ if (ag->mlo_capable) ++ hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_MLO; ++ + /* TODO Split queues per chip */ + hw->queues = ATH12K_HW_MAX_QUEUES; + hw->wiphy->tx_queue_len = ATH12K_QUEUE_LEN; +--- a/drivers/net/wireless/ath/ath12k/mac.h ++++ b/drivers/net/wireless/ath/ath12k/mac.h +@@ -145,14 +145,14 @@ u8 ath12k_mac_hw_rate_to_idx(const struc + void __ath12k_mac_scan_finish(struct ath12k *ar); + void ath12k_mac_scan_finish(struct ath12k *ar); + +-struct ath12k_vif *ath12k_mac_get_arvif(struct ath12k *ar, u32 vdev_id); +-struct ath12k_vif *ath12k_mac_get_arvif_by_vdev_id(struct ath12k_base *ab, ++struct ath12k_link_vif *ath12k_mac_get_arvif(struct ath12k *ar, u32 vdev_id); ++struct ath12k_link_vif *ath12k_mac_get_arvif_by_vdev_id(struct ath12k_base *ab, + u32 vdev_id); + struct ath12k *ath12k_mac_get_ar_by_vdev_id(struct ath12k_base *ab, u32 vdev_id); + struct ath12k *ath12k_mac_get_ar_by_pdev_id(struct ath12k_base *ab, u32 pdev_id); + + void ath12k_mac_fill_reg_tpc_info(struct ath12k *ar, +- struct ieee80211_vif *vif, ++ struct ath12k_link_vif *arvif, + struct ieee80211_chanctx_conf *ctx); + void ath12k_mac_drain_tx(struct ath12k *ar); + void ath12k_mac_peer_cleanup_all(struct ath12k *ar); +@@ -166,8 +166,9 @@ enum hal_encrypt_type ath12k_dp_tx_get_e + void ath12k_mac_get_any_chandef_iter(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *conf, + void *data); +-void ath12k_mac_bcn_tx_event(struct ath12k_vif *arvif); +-struct ath12k *ath12k_get_ar_by_vif(struct ieee80211_hw *hw, struct ieee80211_vif *vif); ++void ath12k_mac_bcn_tx_event(struct ath12k_link_vif *arvif); ++struct ath12k *ath12k_get_ar_by_vif(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ++ u8 link_id); + int ath12k_mac_mlo_setup(struct ath12k_hw *ah); + int ath12k_mac_mlo_ready(struct ath12k_hw *ah); + int ath12k_mac_mlo_teardown(struct ath12k_hw *ah); +--- a/drivers/net/wireless/ath/ath12k/peer.c ++++ b/drivers/net/wireless/ath/ath12k/peer.c +@@ -263,12 +263,14 @@ static int ath12k_wait_for_peer_created( + return ath12k_wait_for_peer_common(ar->ab, vdev_id, addr, true); + } + +-int ath12k_peer_create(struct ath12k *ar, struct ath12k_vif *arvif, ++int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif, + struct ieee80211_sta *sta, struct peer_create_params *param) + { + struct ath12k_peer *peer; +- struct ath12k_sta *arsta; +- struct ieee80211_vif *vif = arvif->vif; ++ struct ath12k_sta *ahsta; ++ struct ath12k_link_sta *arsta; ++ u8 link_id = arvif->link_id; ++ struct ieee80211_vif *vif = arvif->ahvif->vif; + + int ret; + +@@ -330,7 +332,7 @@ int ath12k_peer_create(struct ath12k *ar + peer->pdev_idx = ar->pdev_idx; + peer->sta = sta; + +- if (arvif->vif->type == NL80211_IFTYPE_STATION) { ++ if (vif->type == NL80211_IFTYPE_STATION) { + arvif->ast_hash = peer->ast_hash; + arvif->ast_idx = peer->hw_peer_id; + } +@@ -340,7 +342,9 @@ int ath12k_peer_create(struct ath12k *ar + peer->vif = vif; + + if (sta) { +- arsta = (struct ath12k_sta *)sta->drv_priv; ++ /* TODO handling for ML PEER */ ++ ahsta = (struct ath12k_sta *)sta->drv_priv; ++ arsta = ahsta->link[link_id]; + arsta->tcl_metadata |= FIELD_PREP(HTT_TCL_META_DATA_TYPE, 0) | + FIELD_PREP(HTT_TCL_META_DATA_PEER_ID, + peer->peer_id); +--- a/drivers/net/wireless/ath/ath12k/peer.h ++++ b/drivers/net/wireless/ath/ath12k/peer.h +@@ -63,7 +63,7 @@ struct ath12k_peer *ath12k_peer_find_by_ + struct ath12k_peer *ath12k_peer_find_by_id(struct ath12k_base *ab, int peer_id); + void ath12k_peer_cleanup(struct ath12k *ar, u32 vdev_id); + int ath12k_peer_delete(struct ath12k *ar, u32 vdev_id, u8 *addr); +-int ath12k_peer_create(struct ath12k *ar, struct ath12k_vif *arvif, ++int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif, + struct ieee80211_sta *sta, struct peer_create_params *param); + int ath12k_wait_for_peer_delete_done(struct ath12k *ar, u32 vdev_id, + const u8 *addr); +--- a/drivers/net/wireless/ath/ath12k/spectral.c ++++ b/drivers/net/wireless/ath/ath12k/spectral.c +@@ -156,7 +156,7 @@ static const struct rchan_callbacks rfs_ + + static struct ath12k_vif *ath12k_spectral_get_vdev(struct ath12k *ar) + { +- struct ath12k_vif *arvif; ++ struct ath12k_link_vif *arvif; + + lockdep_assert_held(&ar->conf_mutex); + +@@ -174,7 +174,7 @@ static struct ath12k_vif *ath12k_spectra + + static int ath12k_spectral_scan_trigger(struct ath12k *ar) + { +- struct ath12k_vif *arvif; ++ struct ath12k_link_vif *arvif; + int ret; + + lockdep_assert_held(&ar->conf_mutex); +@@ -205,7 +205,7 @@ static int ath12k_spectral_scan_config(s + enum ath12k_spectral_mode mode) + { + struct ath12k_wmi_vdev_spectral_conf_param param = { 0 }; +- struct ath12k_vif *arvif; ++ struct ath12k_link_vif *arvif; + int ret, count; + + lockdep_assert_held(&ar->conf_mutex); +--- a/drivers/net/wireless/ath/ath12k/spectral.h ++++ b/drivers/net/wireless/ath/ath12k/spectral.h +@@ -42,7 +42,7 @@ struct ath12k_spectral { + + int ath12k_spectral_init(struct ath12k_base *ab); + void ath12k_spectral_deinit(struct ath12k_base *ab); +-int ath12k_spectral_vif_stop(struct ath12k_vif *arvif); ++int ath12k_spectral_vif_stop(struct ath12k_link_vif *arvif); + void ath12k_spectral_reset_buffer(struct ath12k *ar); + enum ath12k_spectral_mode ath12k_spectral_get_mode(struct ath12k *ar); + struct ath12k_dbring *ath12k_spectral_get_dbring(struct ath12k *ar); +@@ -58,7 +58,7 @@ static inline void ath12k_spectral_deini + { + } + +-static inline int ath12k_spectral_vif_stop(struct ath12k_vif *arvif) ++static inline int ath12k_spectral_vif_stop(struct ath12k_link_vif *arvif) + { + return 0; + } +--- a/drivers/net/wireless/ath/ath12k/testmode.c ++++ b/drivers/net/wireless/ath/ath12k/testmode.c +@@ -442,7 +442,8 @@ int ath12k_tm_cmd(struct ieee80211_hw *h + + mutex_lock(&ah->conf_mutex); + +- ar = ath12k_get_ar_by_vif(hw, vif); ++ /* TODO cmd for all ML vifs */ ++ ar = ath12k_get_ar_by_vif(hw, vif, 0); + ab = ar->ab; + if (!ar) { + mutex_unlock(&ah->conf_mutex); +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -5728,7 +5728,7 @@ static int wmi_process_mgmt_tx_comp(stru + struct ath12k_skb_cb *skb_cb; + struct ieee80211_hdr *hdr; + struct ieee80211_vif *vif; +- struct ath12k_vif *arvif; ++ struct ath12k_vif *ahvif; + struct ath12k_mgmt_frame_stats *mgmt_stats; + u16 frm_type; + int num_mgmt; +@@ -5762,8 +5762,8 @@ static int wmi_process_mgmt_tx_comp(stru + goto skip_mgmt_stats; + } + +- arvif = ath12k_vif_to_arvif(vif); +- mgmt_stats = &arvif->mgmt_stats; ++ ahvif = ath12k_vif_to_ahvif(vif); ++ mgmt_stats = &ahvif->mgmt_stats; + + if (!status) + mgmt_stats->tx_compl_succ[frm_type]++; +@@ -6595,7 +6595,7 @@ ath12k_wmi_fw_vdev_stats_fill(struct ath + { + u32 len = *length; + u32 buf_len = ATH12K_FW_STATS_BUF_SIZE; +- struct ath12k_vif *arvif = ath12k_mac_get_arvif(ar, vdev->vdev_id); ++ struct ath12k_link_vif *arvif = ath12k_mac_get_arvif(ar, vdev->vdev_id); + u8 *vif_macaddr; + int i; + +@@ -6605,7 +6605,7 @@ ath12k_wmi_fw_vdev_stats_fill(struct ath + if (!arvif) + return; + +- vif_macaddr = arvif->vif->addr; ++ vif_macaddr = arvif->addr; + + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "VDEV ID", vdev->vdev_id); +@@ -6691,7 +6691,7 @@ ath12k_wmi_fw_bcn_stats_fill(struct ath1 + { + u32 len = *length; + u32 buf_len = ATH12K_FW_STATS_BUF_SIZE; +- struct ath12k_vif *arvif = ath12k_mac_get_arvif(ar, bcn->vdev_id); ++ struct ath12k_link_vif *arvif = ath12k_mac_get_arvif(ar, bcn->vdev_id); + u8 *vdev_macaddr; + + if (!arvif) { +@@ -6700,7 +6700,7 @@ ath12k_wmi_fw_bcn_stats_fill(struct ath1 + return; + } + +- vdev_macaddr = arvif->vif->addr; ++ vdev_macaddr = arvif->addr; + + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "VDEV ID", bcn->vdev_id); +@@ -7111,7 +7111,7 @@ static void ath12k_vdev_start_resp_event + + static void ath12k_bcn_tx_status_event(struct ath12k_base *ab, struct sk_buff *skb) + { +- struct ath12k_vif *arvif; ++ struct ath12k_link_vif *arvif; + u32 vdev_id, tx_status; + + if (ath12k_pull_bcn_tx_status_ev(ab, skb->data, skb->len, +@@ -7168,7 +7168,7 @@ static void ath12k_mgmt_rx_event(struct + struct ieee80211_supported_band *sband; + struct ath12k_peer *peer; + struct ieee80211_vif *vif; +- struct ath12k_vif *arvif; ++ struct ath12k_vif *ahvif; + struct ath12k_mgmt_frame_stats *mgmt_stats; + u16 frm_type = 0; + +@@ -7257,8 +7257,8 @@ static void ath12k_mgmt_rx_event(struct + + spin_lock_bh(&ar->data_lock); + +- arvif = ath12k_vif_to_arvif(vif); +- mgmt_stats = &arvif->mgmt_stats; ++ ahvif = ath12k_vif_to_ahvif(vif); ++ mgmt_stats = &ahvif->mgmt_stats; + mgmt_stats->rx_cnt[frm_type]++; + + spin_unlock_bh(&ar->data_lock); +@@ -7840,7 +7840,8 @@ ath12k_wmi_process_csa_switch_count_even + const u32 *vdev_ids) + { + int i; +- struct ath12k_vif *arvif; ++ struct ath12k_link_vif *arvif; ++ struct ieee80211_bss_conf *link_conf; + + /* Finish CSA once the switch count becomes NULL */ + if (ev->current_switch_count) +@@ -7855,9 +7856,14 @@ ath12k_wmi_process_csa_switch_count_even + vdev_ids[i]); + continue; + } ++ link_conf = arvif->ahvif->vif->link_conf[arvif->link_id]; ++ ++ if (!link_conf) ++ continue; + +- if (arvif->is_up && arvif->vif->bss_conf.csa_active) +- ieee80211_csa_finish(arvif->vif); ++ /* FIXME some changes are expected for ML vifs */ ++ if (arvif->is_up && link_conf->csa_active) ++ ieee80211_csa_finish(arvif->ahvif->vif); + } + rcu_read_unlock(); + } +@@ -9072,7 +9078,7 @@ ath12k_wmi_obss_color_collision_event(st + { + const void **tb; + const struct wmi_obss_color_collision_event *ev; +- struct ath12k_vif *arvif; ++ struct ath12k_link_vif *arvif; + struct ath12k *ar; + int ret; + +@@ -9461,13 +9467,15 @@ ath12k_wmi_send_unit_test_cmd(struct ath + + int ath12k_wmi_simulate_radar(struct ath12k *ar) + { +- struct ath12k_vif *arvif; ++ struct ath12k_link_vif *arvif; ++ struct ath12k_vif *ahvif; + u32 dfs_args[DFS_MAX_TEST_ARGS]; + struct wmi_unit_test_cmd wmi_ut; + bool arvif_found = false; + + list_for_each_entry(arvif, &ar->arvifs, list) { +- if (arvif->is_started && arvif->vdev_type == WMI_VDEV_TYPE_AP) { ++ ahvif = arvif->ahvif; ++ if (arvif->is_started && ahvif->vdev_type == WMI_VDEV_TYPE_AP) { + arvif_found = true; + break; + } +@@ -9496,7 +9504,8 @@ int ath12k_wmi_simulate_radar(struct ath + + int ath12k_wmi_simulate_awgn(struct ath12k *ar, u32 chan_bw_interference_bitmap) + { +- struct ath12k_vif *arvif; ++ struct ath12k_link_vif *arvif; ++ struct ath12k_vif *ahvif; + u32 awgn_args[WMI_AWGN_MAX_TEST_ARGS]; + struct wmi_unit_test_cmd wmi_ut; + bool arvif_found = false; +@@ -9507,7 +9516,8 @@ int ath12k_wmi_simulate_awgn(struct ath1 + } + + list_for_each_entry(arvif, &ar->arvifs, list) { +- if (arvif->is_started && arvif->vdev_type == WMI_VDEV_TYPE_AP) { ++ ahvif = arvif->ahvif; ++ if (arvif->is_started && ahvif->vdev_type == WMI_VDEV_TYPE_AP) { + arvif_found = true; + break; + } +@@ -9533,7 +9543,7 @@ int ath12k_wmi_simulate_awgn(struct ath1 + + int ath12k_wmi_pdev_m3_dump_enable(struct ath12k *ar, u32 enable) + { +- struct ath12k_vif *arvif; ++ struct ath12k_link_vif *arvif; + u32 m3_args[WMI_M3_MAX_TEST_ARGS]; + struct wmi_unit_test_cmd wmi_ut; + bool arvif_found = false; diff --git a/feeds/ipq95xx/mac80211/patches/qca/676-02-ath12k-MLO-vdev-bringup-changes.patch b/feeds/ipq95xx/mac80211/patches/qca/676-02-ath12k-MLO-vdev-bringup-changes.patch new file mode 100644 index 000000000..639057654 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/676-02-ath12k-MLO-vdev-bringup-changes.patch @@ -0,0 +1,805 @@ +From 3aca73b1f849abd2e6b1d86396b0446bca8046dd Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Tue, 11 Oct 2022 13:11:24 +0530 +Subject: [PATCH] ath12k: MLO vdev bringup changes + +Add support for bringup of MLO vdevs. This involves +bringup of all the link vdevs across different radios +and all sending partner link info in vdev start command. + +With single wiphy support, since multiple radios are tied +to same wiphy and vif/ahvif in case of MLO, the actual link +vif corresponding to the link can be obtained only during +channel assignment. + +Since the partner link info is required in vdev start command +all the link vdevs needs to be created before giving the vdev +start to firmware. Note that this logic will not work seamlessly +with MBSSID and DFS support which requires some more additional +changes. FW support to add partner vdev info dynamically might be +required to achieve the same. + +Signed-off-by: Sriram R +--- + drivers/net/wireless/ath/ath12k/core.h | 4 + + drivers/net/wireless/ath/ath12k/mac.c | 198 +++++++++++++++++++++++-- + drivers/net/wireless/ath/ath12k/wmi.c | 79 +++++++++- + drivers/net/wireless/ath/ath12k/wmi.h | 48 ++++++ + 4 files changed, 309 insertions(+), 20 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -334,6 +334,7 @@ struct ath12k_link_vif { + bool is_created; + bool is_started; + bool is_up; ++ bool pending_up; + bool spectral_enabled; + u8 bssid[ETH_ALEN]; + struct cfg80211_bitrate_mask bitrate_mask; +@@ -391,6 +392,8 @@ struct ath12k_vif { + u16 links_map; + u32 aid; + struct ath12k_mgmt_frame_stats mgmt_stats; ++ u8 num_vdev_created; ++ u8 num_vdev_started; + }; + + struct ath12k_vif_iter { +@@ -989,6 +992,7 @@ struct ath12k_hw { + bool regd_updated; + u8 supported_band_mask; + u8 num_radio; ++ struct ath12k_link_vif *scan_arvif; + struct ath12k radio[0] __aligned(sizeof(void *)); + }; + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -750,6 +750,19 @@ struct ath12k *ath12k_mac_get_ar_by_pdev + return NULL; + } + ++bool ath12k_mac_is_ml_arvif(struct ath12k_link_vif *arvif) ++{ ++ struct ath12k *ar = arvif->ar; ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ if (ahvif->vif->valid_links & BIT(arvif->link_id)) ++ return true; ++ ++ return false; ++} ++ + static void ath12k_pdev_caps_update(struct ath12k *ar) + { + struct ath12k_base *ab = ar->ab; +@@ -1495,7 +1508,7 @@ static int ath12k_mac_setup_bcn_tmpl_non + } + + bcn = ieee80211_beacon_get_template(tx_arvif->ar->ah->hw, ahvif->vif, +- &offs, 0); ++ &offs, arvif->link_id); + if (!bcn) { + ath12k_warn(arvif->ar->ab, + "failed to get beacon template from mac80211\n"); +@@ -1608,7 +1621,7 @@ static void ath12k_control_beaconing(str + + ahvif->aid = 0; + +- ether_addr_copy(arvif->bssid, info->bssid); ++ ether_addr_copy(arvif->bssid, info->addr); + + params.vdev_id = arvif->vdev_id; + params.aid = ahvif->aid; +@@ -3837,7 +3850,8 @@ static void ath12k_mac_bss_info_changed( + "Set staggered beacon mode for VDEV: %d\n", + arvif->vdev_id); + +- if (!arvif->do_not_send_tmpl || !arvif->bcca_zero_sent) { ++ if ((!arvif->do_not_send_tmpl || !arvif->bcca_zero_sent) && ++ arvif->is_started) { + ret = ath12k_mac_setup_bcn_tmpl(arvif); + if (ret) + ath12k_warn(ar->ab, "failed to update bcn template: %d\n", +@@ -3891,10 +3905,13 @@ static void ath12k_mac_bss_info_changed( + ahvif->u.ap.hidden_ssid = info->hidden_ssid; + } + +- if (changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid)) ++ if (changed & BSS_CHANGED_BSSID && info->bssid && !is_zero_ether_addr(info->bssid)) + ether_addr_copy(arvif->bssid, info->bssid); + +- if (changed & BSS_CHANGED_BEACON_ENABLED) { ++ if (changed & BSS_CHANGED_BEACON_ENABLED && !arvif->is_started) ++ arvif->pending_up = true; ++ ++ if (changed & BSS_CHANGED_BEACON_ENABLED && arvif->is_started) { + if (info->enable_beacon) { + ath12k_mac_set_he_txbf_conf(arvif); + ath12k_mac_set_eht_txbf_conf(arvif); +@@ -4232,6 +4249,7 @@ static int ath12k_mac_vdev_delete(struct + ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id); + ar->ab->free_vdev_stats_id_map &= ~(1LL << arvif->vdev_stats_id); + ar->num_created_vdevs--; ++ arvif->ahvif->num_vdev_created--; + arvif->is_created = false; + + clean_up: +@@ -4245,7 +4263,7 @@ clean_up: + } + + static struct ath12k_link_vif * +-ath12k_mac_get_link_vif( struct ath12k_hw *ah, struct ieee80211_vif *vif, u8 link_id) ++ath12k_mac_assign_link_vif( struct ath12k_hw *ah, struct ieee80211_vif *vif, u8 link_id) + { + struct ath12k_vif *ahvif = (void *)vif->drv_priv; + struct ath12k_link_vif *arvif; +@@ -4262,16 +4280,22 @@ ath12k_mac_get_link_vif( struct ath12k_h + arvif = &ahvif->deflink; + } else { + /* first link vif is fetched from deflink*/ +- if (!ahvif->links_map) ++ if (!ahvif->links_map) { + arvif = &ahvif->deflink; +- else ++ } else { + arvif = (struct ath12k_link_vif *) + kzalloc(sizeof(struct ath12k_link_vif), + GFP_KERNEL); + +- if (arvif == NULL) +- return NULL; ++ if (arvif == NULL) ++ return NULL; + ++ INIT_LIST_HEAD(&arvif->list); ++ INIT_WORK(&arvif->update_obss_color_notify_work, ++ ath12k_update_obss_color_notify_work); ++ INIT_WORK(&arvif->update_bcn_template_work, ++ ath12k_update_bcn_template_work); ++ } + } + + ahvif->link[link_id] = arvif; +@@ -4292,10 +4316,6 @@ ath12k_mac_get_link_vif( struct ath12k_h + sizeof(arvif->bitrate_mask.control[i].eht_mcs)); + } + +- INIT_LIST_HEAD(&arvif->list); +- INIT_WORK(&arvif->update_obss_color_notify_work, ath12k_update_obss_color_notify_work); +- INIT_WORK(&arvif->update_bcn_template_work, ath12k_update_bcn_template_work); +- + return arvif; + } + +@@ -4523,7 +4543,7 @@ static int ath12k_mac_op_hw_scan(struct + } + + /* TODO ML vif handling */ +- arvif = ath12k_mac_get_link_vif(ah, vif, 0); ++ arvif = ath12k_mac_assign_link_vif(ah, vif, 0); + /* If the vif is already assigned to a specific vdev of an ar, + * check whether its already started, vdev which is started + * are not allowed to switch to a new radio. +@@ -4533,6 +4553,9 @@ static int ath12k_mac_op_hw_scan(struct + * delete-create vdev's for the same ar, in case the request is + * always on the same band for the vif + */ ++ if (!arvif) ++ return -ENOMEM; ++ + if (arvif->is_created) { + if (ar != arvif->ar && arvif->is_started) { + mutex_unlock(&ah->conf_mutex); +@@ -4557,6 +4580,10 @@ static int ath12k_mac_op_hw_scan(struct + } + mutex_unlock(&ar->conf_mutex); + } ++ ++ if (vif->valid_links) ++ ah->scan_arvif = arvif; ++ + mutex_unlock(&ah->conf_mutex); + + mutex_lock(&ar->conf_mutex); +@@ -7888,6 +7915,15 @@ static int ath12k_mac_setup_vdev_create_ + } + + params->if_stats_id = ath12k_mac_get_vdev_stats_id(arvif); ++ ++ if (ath12k_mac_is_ml_arvif(arvif)) { ++ if (hweight16(ahvif->vif->valid_links) > ATH12K_WMI_MLO_MAX_LINKS) { ++ WARN_ON(1); ++ return -EINVAL; ++ } ++ ether_addr_copy(params->mld_addr, ahvif->vif->addr); ++ } ++ + return 0; + } + +@@ -8013,7 +8049,7 @@ static int ath12k_mac_vdev_create(struct + struct ath12k_vif *ahvif = arvif->ahvif; + struct ieee80211_hw *hw = ar->ah->hw; + struct vdev_create_params vdev_param = {0}; +- struct peer_create_params peer_param; ++ struct peer_create_params peer_param = {0}; + struct ieee80211_bss_conf *link_conf; + u32 param_id, param_value; + u16 nss; +@@ -8105,6 +8141,7 @@ static int ath12k_mac_vdev_create(struct + } + + ar->num_created_vdevs++; ++ ahvif->num_vdev_created++; + arvif->is_created = true; + ath12k_dbg(ab, ATH12K_DBG_MAC, "vdev %pM created, vdev_id %d\n", + link_addr, arvif->vdev_id); +@@ -8375,6 +8412,11 @@ static int ath12k_mac_op_add_interface(s + + ahvif->deflink.ahvif = ahvif; + ahvif->deflink.link_id = 0; ++ INIT_LIST_HEAD(&ahvif->deflink.list); ++ INIT_WORK(&ahvif->deflink.update_obss_color_notify_work, ++ ath12k_update_obss_color_notify_work); ++ INIT_WORK(&ahvif->deflink.update_bcn_template_work, ++ ath12k_update_bcn_template_work); + + ahvif->key_cipher = INVALID_CIPHER; + +@@ -8490,6 +8532,9 @@ err_vdev_del: + + /* TODO: recal traffic pause state based on the available vdevs */ + ++ ahvif->link[arvif->link_id] = NULL; ++ ahvif->links_map &= ~BIT(arvif->link_id); ++ + mutex_unlock(&ar->conf_mutex); + } + +@@ -8512,12 +8557,13 @@ static void ath12k_mac_op_remove_interfa + if (arvif == NULL) + continue; + ++ if (WARN_ON(arvif->link_id != link_id)) ++ continue; ++ + ath12k_mac_remove_link_interface(hw, arvif); + + if (arvif != &ahvif->deflink) + kfree(arvif); +- +- ahvif->link[link_id] = NULL; + } + + mutex_unlock(&ah->conf_mutex); +@@ -8655,6 +8701,16 @@ static int ath12k_mac_op_ampdu_action(st + return ret; + } + ++static int ath12k_mac_op_change_vif_links(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ u16 old_links, u16 new_links, ++ struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS]) ++{ ++ ath12k_info(NULL, ++ "link changed for MLD %pM old %d new %d\n", vif->addr, old_links, new_links); ++ return 0; ++} ++ + static int ath12k_mac_op_add_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *ctx) + { +@@ -8756,6 +8812,61 @@ static int ath12k_mac_set_6g_nonht_dup_c + return ret; + } + ++static void ++ath12k_mac_mlo_get_vdev_args(struct ath12k_link_vif *arvif, ++ struct wmi_ml_arg *ml_arg) ++{ ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ath12k_link_vif *arvif_p; ++ u16 links_map; ++ u8 link_id; ++ struct wmi_ml_partner_info *partner_info; ++ struct ieee80211_bss_conf *link_conf; ++ ++ if (!ath12k_mac_is_ml_arvif(arvif)) ++ return; ++ ++ if (hweight16(ahvif->vif->valid_links) > ATH12K_WMI_MLO_MAX_LINKS) ++ return; ++ ++ rcu_read_lock(); ++ ++ ml_arg->enabled = true; ++ /* TODO check assoc and mcast vdev for AP mode */ ++ ++ links_map = ahvif->links_map; ++ ++ partner_info = ml_arg->partner_info; ++ ++ for_each_set_bit(link_id, &links_map, IEEE80211_MLD_MAX_NUM_LINKS) { ++ arvif_p = ahvif->link[link_id]; ++ ++ if (WARN_ON(arvif_p == NULL)) ++ continue; ++ ++ if (arvif == arvif_p) ++ continue; ++ ++ link_conf = rcu_dereference(ahvif->vif->link_conf[arvif_p->link_id]); ++ ++ if (!link_conf) ++ continue; ++ ++ if (!arvif_p->ar) { ++ ath12k_warn(NULL, "invalid ar in the arvif_p from link_id %d links_map: %d\n", ++ link_id, links_map); ++ continue; ++ } ++ ++ partner_info->vdev_id = arvif_p->vdev_id; ++ partner_info->hw_link_id = arvif_p->ar->pdev->hw_link_id; ++ ether_addr_copy(partner_info->addr, link_conf->addr); ++ ml_arg->num_partner_links++; ++ partner_info++; ++ } ++ rcu_read_unlock(); ++} ++ + static int + ath12k_mac_vdev_start_restart(struct ath12k_link_vif *arvif, + const struct cfg80211_chan_def *chandef, +@@ -8823,6 +8934,9 @@ ath12k_mac_vdev_start_restart(struct ath + + arg.channel.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR); + ++ if (!restart) ++ ath12k_mac_mlo_get_vdev_args(arvif, &arg.ml); ++ + ath12k_dbg(ab, ATH12K_DBG_MAC, + "mac vdev %d start center_freq %d punct bitmap 0x%x phymode %s\n", + arg.vdev_id, arg.channel.freq, arg.ru_punct_bitmap, +@@ -9025,6 +9139,79 @@ static int ath12k_vdev_restart_sequence( + return ret; + } + ++static int ath12k_mac_mlo_vdev_start(struct ath12k_link_vif *arvif) ++{ ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ath12k *ar = arvif->ar; ++ struct ath12k_hw *ah = ar->ah; ++ struct ath12k_link_vif *arvif_p; ++ u8 link_id; ++ int ret = 0; ++ u16 links_map; ++ bool radar_enabled = arvif->chanctx.radar_enabled; ++ ++ lockdep_assert_held(&ah->conf_mutex); ++ /* TODO some changes are expected in this func wrt DFS statemachine */ ++ /* FIXME Note that this logic is temp and wont work for MBSSID cases ++ * There are two options, 1, the set link should have some pre channel info ++ * or FW should support dynamic partner add/remove support ++ */ ++ ++ /* we need to wait for all the link vdev in the vif to be created ++ * before we start ++ */ ++ if (ahvif->num_vdev_created != hweight16(ahvif->vif->valid_links)) ++ goto out; ++ ++ links_map = ahvif->links_map; ++ for_each_set_bit(link_id, &links_map, IEEE80211_MLD_MAX_NUM_LINKS) { ++ arvif_p = ahvif->link[link_id]; ++ ++ if (!arvif_p->ar) { ++ ath12k_warn(ar->ab, "invalid ar in the arvif_p from link_id %d links_map: %d\n", ++ link_id, links_map); ++ continue; ++ } ++ ++ ar = arvif_p->ar; ++ ++ /* TODO cant hold rcu lock due to call of ath12k_mac_bss_info_changed ++ * option is to take a backup if link info, anyways this function would ++ * change after FW support for dynamic add ++ */ ++ if (WARN_ON(!ahvif->vif->link_conf[link_id])) ++ continue; ++ ++ mutex_lock(&ar->conf_mutex); ++ ret = ath12k_mac_vdev_start(arvif_p, &arvif_p->chanctx.def, ++ radar_enabled); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to start vdev %i on freq %d: %d\n", ++ arvif_p->vdev_id, arvif_p->chanctx.def.chan->center_freq, ret); ++ ++ mutex_unlock(&ar->conf_mutex); ++ /* The already started vdevs will be cleaned up during unassign */ ++ goto out; ++ } ++ ++ /* ToDO MLO AP + Monitor */ ++ arvif_p->is_started = true; ++ ++ /* Enable beaconing now. ++ * this will be done by usual code flow from mac80211 for the last link ++ */ ++ if (arvif_p != arvif && arvif_p->pending_up) { ++ ath12k_mac_bss_info_changed(ar, arvif_p, ahvif->vif->link_conf[link_id], ++ BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON); ++ arvif_p->pending_up = false; ++ } ++ mutex_unlock(&ar->conf_mutex); ++ ahvif->num_vdev_started++; ++ } ++out: ++ return ret; ++} ++ + struct ath12k_mac_change_chanctx_arg { + struct ieee80211_chanctx_conf *ctx; + struct ieee80211_vif_chanctx_switch *vifs; +@@ -9225,8 +9412,10 @@ ath12k_mac_update_vif_chan(struct ath12k + vifs[i].old_ctx->def.width, + vifs[i].new_ctx->def.width); + +- if (WARN_ON(!arvif->is_started)) ++ if (WARN_ON(!arvif->is_started)) { ++ memcpy(&arvif->chanctx, vifs[i].new_ctx, sizeof(*vifs[i].new_ctx)); + continue; ++ } + + if (!arvif->is_up) + continue; +@@ -9970,7 +10159,13 @@ ath12k_mac_op_assign_vif_chanctx(struct + + mutex_lock(&ah->conf_mutex); + +- arvif = ath12k_mac_get_link_vif(ah, vif, link_id); ++ /* clear any scan arvifs since its always attached to link 0 by default */ ++ if (ah->scan_arvif && vif->valid_links) { ++ ath12k_mac_remove_link_interface(hw, ah->scan_arvif); ++ ah->scan_arvif = NULL; ++ } ++ ++ arvif = ath12k_mac_assign_link_vif(ah, vif, link_id); + if (!arvif) { + ath12k_err(NULL, "unable to allocate link vif\n"); + return -ENOMEM; +@@ -9982,9 +10177,8 @@ ath12k_mac_op_assign_vif_chanctx(struct + mutex_unlock(&ah->conf_mutex); + return -EINVAL; + } +- } else if(vif->valid_links){ +- ar = arvif->ar; +- /* Note below case not expected for MLO/not handled now */ ++ } else if (vif->valid_links){ ++ /* not expected to be here */ + } else { + ar = ath12k_get_ar_by_ctx(hw, ctx); + if (!ar) { +@@ -10089,6 +10283,15 @@ ath12k_mac_op_assign_vif_chanctx(struct + goto out; + } + ++ if (ath12k_mac_is_ml_arvif(arvif) && ++ ahvif->vdev_type == WMI_VDEV_TYPE_AP) { ++ mutex_unlock(&ar->conf_mutex); ++ memcpy(&arvif->chanctx, ctx, sizeof(*ctx)); ++ ret = ath12k_mac_mlo_vdev_start(arvif); ++ mutex_unlock(&ah->conf_mutex); ++ return ret; ++ } ++ + ret = ath12k_mac_vdev_start(arvif, &ctx->def, ctx->radar_enabled); + if (ret) { + ath12k_warn(ab, "failed to start vdev %i addr %pM on freq %d: %d\n", +@@ -10126,17 +10329,10 @@ ath12k_mac_op_unassign_vif_chanctx(struc + struct ath12k_base *ab; + struct ath12k *ar; + int ret; +- /* TODO tmp, link_id passed through func */ +- u8 link_id = 0; ++ u8 link_id = link_conf->link_id; + + mutex_lock(&ah->conf_mutex); +- /* The vif is expected to be attached to an ar's VDEV. +- * We leave the vif/vdev in this function as is +- * and not delete the vdev symmetric to assign_vif_chanctx() +- * the VDEV will be deleted and unassigned either during +- * remove_interface() or when there is a change in channel +- * that moves the vif to a new ar +- */ ++ + arvif = ahvif->link[link_id]; + + if (!arvif) { +@@ -10163,7 +10359,8 @@ ath12k_mac_op_unassign_vif_chanctx(struc + "mac chanctx unassign ptr %pK vdev_id %i\n", + ctx, arvif->vdev_id); + +- WARN_ON(!arvif->is_started); ++ if (!arvif->is_started) ++ goto out; + + if (ab->hw_params->vdev_start_delay && + ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR && +@@ -10176,7 +10373,9 @@ ath12k_mac_op_unassign_vif_chanctx(struc + goto out; + + arvif->is_started = false; +- goto out; ++ mutex_unlock(&ar->conf_mutex); ++ ath12k_mac_remove_link_interface(hw, arvif); ++ goto unassign_exit; + } + + ret = ath12k_mac_vdev_stop(arvif); +@@ -10186,6 +10385,12 @@ ath12k_mac_op_unassign_vif_chanctx(struc + + arvif->is_started = false; + ++ if (ath12k_mac_is_ml_arvif(arvif) && ++ ahvif->vdev_type == WMI_VDEV_TYPE_AP) { ++ WARN_ON(ahvif->num_vdev_started == 0); ++ ahvif->num_vdev_started--; ++ } ++ + if (ab->hw_params->vdev_start_delay && + ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) + ath12k_wmi_vdev_down(ar, arvif->vdev_id); +@@ -10195,8 +10400,12 @@ ath12k_mac_op_unassign_vif_chanctx(struc + test_bit(MONITOR_VDEV_CREATED, &ar->monitor_flags)) + ath12k_mac_monitor_stop(ar); + ++ mutex_unlock(&ar->conf_mutex); ++ ath12k_mac_remove_link_interface(hw, arvif); ++ goto unassign_exit; + out: + mutex_unlock(&ar->conf_mutex); ++unassign_exit: + mutex_unlock(&ah->conf_mutex); + } + +@@ -11509,6 +11718,7 @@ static const struct ieee80211_ops ath12k + .config = ath12k_mac_op_config, + .link_info_changed = ath12k_mac_op_bss_info_changed, + .vif_cfg_changed = ath12k_mac_op_vif_cfg_changed, ++ .change_vif_links = ath12k_mac_op_change_vif_links, + .configure_filter = ath12k_mac_op_configure_filter, + .hw_scan = ath12k_mac_op_hw_scan, + .cancel_hw_scan = ath12k_mac_op_cancel_hw_scan, +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -773,18 +773,23 @@ int ath12k_wmi_vdev_create(struct ath12k + { + struct ath12k_pdev_wmi *wmi = ar->wmi; + struct wmi_vdev_create_cmd *cmd; ++ struct wmi_vdev_create_mlo_params *ml_params; + struct sk_buff *skb; + struct wmi_vdev_txrx_streams *txrx_streams; + struct wmi_tlv *tlv; + int ret, len; + void *ptr; ++ bool is_ml_vdev; ++ ++ is_ml_vdev = is_valid_ether_addr(param->mld_addr); + + /* It can be optimized my sending tx/rx chain configuration + * only for supported bands instead of always sending it for + * both the bands. + */ + len = sizeof(*cmd) + TLV_HDR_SIZE + +- (WMI_NUM_SUPPORTED_BAND_MAX * sizeof(*txrx_streams)); ++ (WMI_NUM_SUPPORTED_BAND_MAX * sizeof(*txrx_streams)) + ++ (is_ml_vdev ? TLV_HDR_SIZE + sizeof(*ml_params) : 0); + + skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len); + if (!skb) +@@ -831,6 +836,23 @@ int ath12k_wmi_vdev_create(struct ath12k + txrx_streams->supported_rx_streams = + param->chains[NL80211_BAND_5GHZ].rx; + ++ if (is_ml_vdev) { ++ ptr = skb->data + sizeof(*cmd) + TLV_HDR_SIZE + ++ (WMI_NUM_SUPPORTED_BAND_MAX * sizeof(*txrx_streams)); ++ tlv = ptr; ++ tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_STRUCT) | ++ FIELD_PREP(WMI_TLV_LEN, sizeof(*ml_params)); ++ ++ ptr += TLV_HDR_SIZE; ++ ml_params = ptr; ++ ++ ml_params->tlv_header = ++ FIELD_PREP(WMI_TLV_TAG, WMI_TAG_MLO_VDEV_CREATE_PARAMS) | ++ FIELD_PREP(WMI_TLV_LEN, sizeof(ml_params->mld_macaddr.addr)); ++ ++ ether_addr_copy(ml_params->mld_macaddr.addr, param->mld_addr); ++ } ++ + ret = ath12k_wmi_cmd_send(wmi, skb, WMI_VDEV_CREATE_CMDID); + if (ret) { + ath12k_warn(ar->ab, +@@ -988,16 +1010,23 @@ int ath12k_wmi_vdev_start(struct ath12k + { + struct ath12k_pdev_wmi *wmi = ar->wmi; + struct wmi_vdev_start_request_cmd *cmd; ++ struct wmi_vdev_start_mlo_params *ml_params; ++ struct wmi_partner_link_info *partner_info; + struct sk_buff *skb; + struct wmi_channel *chan; + struct wmi_tlv *tlv; + void *ptr; +- int ret, len; ++ int ret, len, ml_arg_size = 0; ++ u8 i; + + if (WARN_ON(arg->ssid_len > sizeof(cmd->ssid.ssid))) + return -EINVAL; + +- len = sizeof(*cmd) + sizeof(*chan) + TLV_HDR_SIZE; ++ if (!restart && arg->ml.enabled) ++ ml_arg_size = TLV_HDR_SIZE + sizeof(*ml_params) + ++ TLV_HDR_SIZE + (arg->ml.num_partner_links * sizeof(*partner_info));; ++ ++ len = sizeof(*cmd) + sizeof(*chan) + TLV_HDR_SIZE + ml_arg_size; + + skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len); + if (!skb) +@@ -1051,6 +1080,48 @@ int ath12k_wmi_vdev_start(struct ath12k + + ptr += sizeof(*tlv); + ++ if (!ml_arg_size) ++ goto send; ++ ++ tlv = ptr; ++ tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_STRUCT) | ++ FIELD_PREP(WMI_TLV_LEN, sizeof(*ml_params)); ++ ptr += TLV_HDR_SIZE; ++ ++ ml_params = ptr; ++ ++ ml_params->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_MLO_VDEV_START_PARAMS) | ++ FIELD_PREP(WMI_TLV_LEN, sizeof(*ml_params) - TLV_HDR_SIZE); ++ ++ ml_params->flags = FIELD_PREP(ATH12K_WMI_FLAG_MLO_ENABLED, ++ arg->ml.enabled) | ++ FIELD_PREP(ATH12K_WMI_FLAG_MLO_ASSOC_LINK, ++ arg->ml.assoc_link) | ++ FIELD_PREP(ATH12K_WMI_FLAG_MLO_MCAST_VDEV, ++ arg->ml.mcast_link); ++ ++ ptr += sizeof(*ml_params); ++ ++ tlv = ptr; ++ tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_STRUCT) | ++ FIELD_PREP(WMI_TLV_LEN, arg->ml.num_partner_links * ++ sizeof(*partner_info)); ++ ptr += TLV_HDR_SIZE; ++ ++ partner_info = ptr; ++ ++ for (i = 0; i < arg->ml.num_partner_links; i++) { ++ partner_info->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_MLO_PARTNER_LINK_PARAMS) | ++ FIELD_PREP(WMI_TLV_LEN, sizeof(*partner_info) - TLV_HDR_SIZE); ++ ++ partner_info->vdev_id = arg->ml.partner_info[i].vdev_id; ++ partner_info->hw_link_id = arg->ml.partner_info[i].hw_link_id; ++ ether_addr_copy(partner_info->vdev_addr.addr, arg->ml.partner_info[i].addr); ++ ++ partner_info++; ++ } ++ ++send: + if (restart) + ret = ath12k_wmi_cmd_send(wmi, skb, + WMI_VDEV_RESTART_REQUEST_CMDID); +@@ -7856,7 +7927,7 @@ ath12k_wmi_process_csa_switch_count_even + vdev_ids[i]); + continue; + } +- link_conf = arvif->ahvif->vif->link_conf[arvif->link_id]; ++ link_conf = rcu_dereference(arvif->ahvif->vif->link_conf[arvif->link_id]); + + if (!link_conf) + continue; +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -1940,6 +1940,10 @@ enum wmi_tlv_tag { + WMI_TAG_MLO_READY_CMD, + WMI_TAG_MLO_TEARDOWN_CMD, + WMI_TAG_MLO_TEARDOWN_COMPLETE, ++ WMI_TAG_MLO_PEER_ASSOC_PARAMS = 0x3D0, ++ WMI_TAG_MLO_PEER_CREATE_PARAMS = 0x3D5, ++ WMI_TAG_MLO_VDEV_START_PARAMS = 0x3D6, ++ WMI_TAG_MLO_VDEV_CREATE_PARAMS = 0x3D7, + WMI_TAG_PDEV_PKTLOG_DECODE_INFO = 0x414, + WMI_TAG_TPC_STATS_GET_CMD = 0x38B, + WMI_TAG_TPC_STATS_EVENT_FIXED_PARAM, +@@ -2823,6 +2827,7 @@ struct vdev_create_params { + u32 mbssid_flags; + u32 mbssid_tx_vdev_id; + u8 if_stats_id; ++ u8 mld_addr[ETH_ALEN]; + }; + + #define ATH12K_MAX_VDEV_STATS_ID 0x30 +@@ -2849,6 +2854,32 @@ struct wmi_vdev_txrx_streams { + u32 supported_rx_streams; + } __packed; + ++struct wmi_vdev_create_mlo_params { ++ u32 tlv_header; ++ struct wmi_mac_addr mld_macaddr; ++} __packed; ++ ++#define ATH12K_WMI_FLAG_MLO_ENABLED BIT(0) ++#define ATH12K_WMI_FLAG_MLO_ASSOC_LINK BIT(1) ++#define ATH12K_WMI_FLAG_MLO_PRIMARY_UMAC BIT(2) ++#define ATH12K_WMI_FLAG_MLO_LOGICAL_LINK_IDX_VALID BIT(3) ++#define ATH12K_WMI_FLAG_MLO_PEER_ID_VALID BIT(4) ++#define ATH12K_WMI_FLAG_MLO_MCAST_VDEV BIT(5) ++#define ATH12K_WMI_FLAG_MLO_EMLSR_SUPPORT BIT(6) ++#define ATH12K_WMI_FLAG_MLO_FORCED_INACTIVE BIT(7) ++ ++struct wmi_vdev_start_mlo_params { ++ u32 tlv_header; ++ u32 flags; ++} __packed; ++ ++struct wmi_partner_link_info { ++ u32 tlv_header; ++ u32 vdev_id; ++ u32 hw_link_id; ++ struct wmi_mac_addr vdev_addr; ++} __packed; ++ + struct wmi_vdev_delete_cmd { + __le32 tlv_header; + __le32 vdev_id; +@@ -3094,6 +3125,22 @@ struct wmi_channel_arg { + enum wmi_phy_mode mode; + }; + ++#define ATH12K_WMI_MLO_MAX_LINKS 3 ++ ++struct wmi_ml_partner_info { ++ u32 vdev_id; ++ u32 hw_link_id; ++ u8 addr[ETH_ALEN]; ++}; ++ ++struct wmi_ml_arg { ++ bool enabled; ++ bool assoc_link; ++ bool mcast_link; ++ u8 num_partner_links; ++ struct wmi_ml_partner_info partner_info[ATH12K_WMI_MLO_MAX_LINKS]; ++}; ++ + struct wmi_vdev_start_req_arg { + u32 vdev_id; + struct wmi_channel_arg channel; +@@ -3116,6 +3163,7 @@ struct wmi_vdev_start_req_arg { + u32 mbssid_flags; + u32 mbssid_tx_vdev_id; + u32 ru_punct_bitmap; ++ struct wmi_ml_arg ml; + }; + + struct peer_create_params { +--- a/drivers/net/wireless/ath/ath12k/mac.h ++++ b/drivers/net/wireless/ath/ath12k/mac.h +@@ -172,4 +172,5 @@ struct ath12k *ath12k_get_ar_by_vif(stru + int ath12k_mac_mlo_setup(struct ath12k_hw *ah); + int ath12k_mac_mlo_ready(struct ath12k_hw *ah); + int ath12k_mac_mlo_teardown(struct ath12k_hw *ah); ++bool ath12k_mac_is_ml_arvif(struct ath12k_link_vif *arvif); + #endif diff --git a/feeds/ipq95xx/mac80211/patches/qca/676-03-ath12k-changes-for-handling-multi-link-sta.patch b/feeds/ipq95xx/mac80211/patches/qca/676-03-ath12k-changes-for-handling-multi-link-sta.patch new file mode 100644 index 000000000..3f502e406 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/676-03-ath12k-changes-for-handling-multi-link-sta.patch @@ -0,0 +1,2179 @@ +From ff3c4e5421e88cd8b5ec3ec0f9ab9c170ac5ecbb Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Thu, 5 Jan 2023 17:16:43 +0530 +Subject: [PATCH] ath12k: changes for handling multi link sta + +Add support to create and maintain multi link sta in driver and send +corresponding peer create/assoc/delete commands to the firmware +based on new mac80211 ops to identify change in link sta. + +This patch adds, +1. Refactoring of ath12k_mac_op_sta_state and new helpers to handle multi link +sta and non ML sta. +2. MLO Peer create and peer assoc wmi changes +3. HTT MLO peer map and unmap changes +4. Support for ath12k_mac_op_change_sta_links for add/remove link sta + +In order to avoid any new locking per ah or add new changes in datapath +related to ML handling, creation/maintenance of new ml peer obj types or +new ML peer list per ah or ath12k_peer obj for ML is avoided. +Rather the per link peer obj store ml info along with existing info +and can be referred/searched for using ml peer id or addr in current +operating ab itself. +The lookups by id will look for matching link peer id and ml peer id +while looping the list. The ml id starts from 8192 onwards so search +can be optimized specific to ml peer id as well based on arg peer id, +similarly for addr and mld addr. + +This can be further optimized to have specific lookup for ml id or +ml addr specific apis and use in dp where the ml and link id/addr +matches for legacy peer types when required. + +Things such as creation/deletion of tid queue will be owned +only by primary link peer and skipped for other parnter link peers. + +The statemachine changes are restricted to AP mode until testing. + +Signed-off-by: Sriram R +--- + drivers/net/wireless/ath/ath12k/core.h | 16 +- + drivers/net/wireless/ath/ath12k/dp.c | 7 + + drivers/net/wireless/ath/ath12k/dp.h | 35 + + drivers/net/wireless/ath/ath12k/dp_rx.c | 16 + + drivers/net/wireless/ath/ath12k/mac.c | 868 ++++++++++++++++++------ + drivers/net/wireless/ath/ath12k/peer.c | 161 ++++- + drivers/net/wireless/ath/ath12k/peer.h | 28 + + drivers/net/wireless/ath/ath12k/wmi.c | 82 ++- + drivers/net/wireless/ath/ath12k/wmi.h | 39 ++ + 9 files changed, 1017 insertions(+), 235 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -52,6 +52,9 @@ extern unsigned int ath12k_mlo_capable; + + #define INVALID_CIPHER 0xFFFFFFFF + ++#define ATH12K_MAX_MLO_PEERS 256 ++#define ATH12K_MLO_PEER_ID_INVALID 0xFFFF ++ + enum ath12k_supported_bw { + ATH12K_BW_20 = 0, + ATH12K_BW_40 = 1, +@@ -553,6 +556,9 @@ struct ath12k_link_sta { + struct ath12k_link_vif *arvif; + struct ath12k_sta *ahsta; + ++ /* link address similar to ieee80211_link_sta */ ++ u8 addr[ETH_ALEN]; ++ + /* the following are protected by ar->data_lock */ + u32 changed; /* IEEE80211_RC_* */ + u32 bw; +@@ -575,7 +581,11 @@ struct ath12k_link_sta { + + u16 tcl_metadata; + u32 bw_prev; +- u8 link_id; ++ u8 link_id; /* IEEE link id */ ++ u8 link_idx; /* for fw use only */ ++ ++ /* For now the assoc link will be considered primary */ ++ bool is_assoc_link; + }; + + struct ath12k_sta { +@@ -592,6 +602,9 @@ struct ath12k_sta { + struct ath12k_link_sta *link[IEEE80211_MLD_MAX_NUM_LINKS]; + /* indicates bitmap of link sta created in FW */ + u16 links_map; ++ u16 ml_peer_id; ++ u8 assoc_link_id; ++ u8 num_peer; + }; + #define ATH12K_HALF_20MHZ_BW 10 + #define ATH12K_5G_MIN_CENTER 4900 +@@ -993,6 +1006,7 @@ struct ath12k_hw { + u8 supported_band_mask; + u8 num_radio; + struct ath12k_link_vif *scan_arvif; ++ DECLARE_BITMAP(free_ml_peer_id_map, ATH12K_MAX_MLO_PEERS); + struct ath12k radio[0] __aligned(sizeof(void *)); + }; + +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -36,6 +36,11 @@ void ath12k_dp_peer_cleanup(struct ath12 + return; + } + ++ if (!peer->primary_link) { ++ spin_unlock_bh(&ab->base_lock); ++ return; ++ } ++ + ath12k_dp_rx_peer_tid_cleanup(ar, peer); + crypto_free_shash(peer->tfm_mmic); + peer->dp_setup_done = false; +@@ -49,6 +54,8 @@ int ath12k_dp_peer_setup(struct ath12k * + u32 reo_dest; + int ret = 0, tid; + ++ /* TODO setup resources only for primary link peer for ML case */ ++ + /* NOTE: reo_dest ring id starts from 1 unlike mac_id which starts from 0 */ + reo_dest = ar->dp.mac_id + 1; + ret = ath12k_wmi_set_peer_param(ar, addr, vdev_id, +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -1248,6 +1248,8 @@ enum htt_t2h_msg_type { + HTT_T2H_MSG_TYPE_EXT_STATS_CONF = 0x1c, + HTT_T2H_MSG_TYPE_BKPRESSURE_EVENT_IND = 0x24, + HTT_T2H_MSG_TYPE_MLO_TIMESTAMP_OFFSET_IND = 0x28, ++ HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP = 0x29, ++ HTT_T2H_MSG_TYPE_MLO_RX_PEER_UNMAP = 0x2a, + HTT_T2H_MSG_TYPE_PEER_MAP3 = 0x2b, + HTT_T2H_MSG_TYPE_VDEV_TXRX_STATS_PERIODIC_IND = 0x2c, + }; +@@ -2062,6 +2064,39 @@ static inline void ath12k_dp_get_mac_add + memcpy(addr + 4, &addr_h16, ETH_ALEN - 4); + } + ++#define ATH12K_ML_PEER_ID GENMASK(13, 0) ++#define ATH12K_ML_PEER_ID_VALID BIT(13) ++ ++#define ATH12K_HTT_MLO_PEER_MAP_TLV_LINK_INFO_TAG 0 ++#define ATH12K_HTT_MAX_MLO_LINKS 3 ++#define ATH12K_HTT_MLO_CHIP_ID GENMASK(2, 0) ++ ++struct ath11k_htt_mlo_link_peer_info { ++ struct htt_tlv tlv_hdr; ++ u16 sw_peer_id; ++ u8 vdev_id; ++ u8 chip_id; ++} __packed; ++ ++#define ATH12K_HTT_MLO_PEER_MAP_INFO0_PEER_ID GENMASK(23, 8) ++#define ATH12K_HTT_MLO_PEER_MAP_MAC_ADDR_H16 GENMASK(15, 0) ++ ++struct ath11k_htt_mlo_peer_map_msg { ++ u32 info0; ++ struct htt_mac_addr mac_addr; ++ u32 info1; ++ u32 info2; ++ u32 info3; ++ u32 rsvd0; ++ u32 rsvd1; ++ struct ath11k_htt_mlo_link_peer_info link_peer[ATH12K_HTT_MAX_MLO_LINKS]; ++} __packed; ++ ++#define ATH12K_HTT_MLO_PEER_UNMAP_PEER_ID GENMASK(23, 8) ++struct ath11k_htt_mlo_peer_unmap_msg { ++ u32 info0; ++} __packed; ++ + int ath12k_dp_service_srng(struct ath12k_base *ab, + struct ath12k_ext_irq_grp *irq_grp, + int budget); +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -1003,6 +1003,11 @@ int ath12k_dp_rx_peer_tid_setup(struct a + return -ENOENT; + } + ++ if (!peer->primary_link) { ++ spin_unlock_bh(&ab->base_lock); ++ return 0; ++ } ++ + if (ab->hw_params->reoq_lut_support && !dp->reoq_lut.vaddr) { + spin_unlock_bh(&ab->base_lock); + ath12k_warn(ab, "reo qref table is not setup\n"); +@@ -2044,6 +2049,12 @@ void ath12k_dp_htt_htc_t2h_msg_handler(s + HTT_T2H_PEER_UNMAP_INFO_PEER_ID); + ath12k_peer_unmap_event(ab, peer_id); + break; ++ case HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP: ++ ath12k_peer_mlo_map_event(ab, skb); ++ break; ++ case HTT_T2H_MSG_TYPE_MLO_RX_PEER_UNMAP: ++ ath12k_peer_mlo_unmap_event(ab, skb); ++ break; + case HTT_T2H_MSG_TYPE_PPDU_STATS_IND: + ath12k_htt_pull_ppdu_stats(ab, skb); + break; +@@ -3217,6 +3228,11 @@ int ath12k_dp_rx_peer_frag_setup(struct + return -ENOENT; + } + ++ if (!peer->primary_link) { ++ spin_unlock_bh(&ab->base_lock); ++ return 0; ++ } ++ + for (i = 0; i <= IEEE80211_NUM_TIDS; i++) { + rx_tid = &peer->rx_tid[i]; + rx_tid->ab = ab; +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -1664,7 +1664,7 @@ static void ath12k_peer_assoc_h_basic(st + else + aid = sta->aid; + +- ether_addr_copy(arg->peer_mac, sta->addr); ++ ether_addr_copy(arg->peer_mac, arsta->addr); + arg->vdev_id = arvif->vdev_id; + arg->peer_associd = aid; + arg->auth_flag = true; +@@ -2091,7 +2091,7 @@ static void ath12k_peer_assoc_h_vht(stru + 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", +- sta->deflink.rx_nss, sta->deflink.addr); ++ sta->deflink.rx_nss, arsta->addr); + vht_mcs_mask[sta->deflink.rx_nss - 1] = vht_mcs_mask[vht_nss - 1]; + } + +@@ -2149,7 +2149,7 @@ static void ath12k_peer_assoc_h_vht(stru + + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, + "mac vht peer %pM max_mpdu %d flags 0x%x nss_override 0x%x\n", +- sta->addr, arg->peer_max_mpdu, arg->peer_flags, ++ arsta->addr, arg->peer_max_mpdu, arg->peer_flags, + arg->peer_bw_rxnss_override); + } + +@@ -2378,7 +2378,7 @@ static void ath12k_peer_assoc_h_he(struc + 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", +- sta->deflink.rx_nss, sta->deflink.addr); ++ sta->deflink.rx_nss, arsta->addr); + he_mcs_mask[sta->deflink.rx_nss - 1] = he_mcs_mask[he_nss - 1]; + } + +@@ -2461,7 +2461,7 @@ static void ath12k_peer_assoc_h_he(struc + + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, + "mac he peer %pM nss %d mcs cnt %d nss_override 0x%x\n", +- sta->deflink.addr, arg->peer_nss, ++ arsta->addr, arg->peer_nss, + arg->peer_he_mcs_count, + arg->peer_bw_rxnss_override); + } +@@ -2723,7 +2723,7 @@ static void ath12k_peer_assoc_h_eht(stru + if (!user_rate_valid) { + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, + "Setting eht range MCS value to peer supported nss:%d for peer %pM\n", +- sta->deflink.rx_nss, sta->deflink.addr); ++ sta->deflink.rx_nss, arsta->addr); + eht_mcs_mask[sta->deflink.rx_nss - 1] = eht_mcs_mask[eht_nss - 1]; + } + +@@ -2795,7 +2795,7 @@ static void ath12k_peer_assoc_h_eht(stru + + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, + "mac he peer %pM nss %d mcs cnt %d ru_punct_bitmap 0x%x\n", +- sta->deflink.addr, arg->peer_nss, arg->peer_he_mcs_count, arg->ru_punct_bitmap); ++ arsta->addr, arg->peer_nss, arg->peer_he_mcs_count, arg->ru_punct_bitmap); + } + + static void ath12k_peer_assoc_h_smps(struct ath12k_link_sta *arsta, +@@ -2872,7 +2872,54 @@ static void ath12k_peer_assoc_h_qos(stru + } + + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac peer %pM qos %d\n", +- sta->addr, arg->qos_flag); ++ arsta->addr, arg->qos_flag); ++} ++ ++static void ath12k_peer_assoc_h_mlo(struct ath12k_link_sta *arsta, ++ struct peer_assoc_params *arg) ++{ ++ struct ath12k_link_vif *arvif; ++ struct ath12k_link_sta *arsta_p; ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; ++ struct peer_assoc_mlo_params *ml = &arg->ml; ++ u8 i = 0, link_id; ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); ++ ++ if (!sta->mlo || ahsta->ml_peer_id == ATH12K_MLO_PEER_ID_INVALID) ++ return; ++ ++ ml->enabled = true; ++ ml->assoc_link = arsta->is_assoc_link; ++ /* For now considering the primary umac based on assoc link */ ++ ml->primary_umac = arsta->is_assoc_link; ++ ml->peer_id_valid = true; ++ ml->logical_link_idx_valid = true; ++ ++ ether_addr_copy(ml->mld_addr, sta->addr); ++ ml->logical_link_idx = arsta->link_idx; ++ ml->ml_peer_id = ahsta->ml_peer_id; ++ ml->ieee_link_id = arsta->link_id; ++ ml->num_partner_links = 0; ++ ++ for_each_set_bit(link_id, &sta->valid_links, IEEE80211_MLD_MAX_NUM_LINKS) { ++ if (i > ATH12K_WMI_MLO_MAX_LINKS) ++ break; ++ arsta_p = ahsta->link[link_id]; ++ arvif = arsta_p->arvif; ++ ++ if (arsta_p == arsta) ++ continue; ++ ml->partner_info[i].vdev_id = arvif->vdev_id; ++ ml->partner_info[i].hw_link_id = arvif->ar->pdev->hw_link_id; ++ ml->partner_info[i].assoc_link = arsta_p->is_assoc_link; ++ ml->partner_info[i].primary_umac = arsta_p->is_assoc_link; ++ ml->partner_info[i].logical_link_idx_valid = true; ++ ml->partner_info[i].logical_link_idx = arsta_p->link_idx; ++ ml->num_partner_links++; ++ i++; ++ } + } + + static int ath12k_peer_assoc_qos_ap(struct ath12k *ar, +@@ -2915,26 +2962,26 @@ static int ath12k_peer_assoc_qos_ap(stru + + params.param = WMI_AP_PS_PEER_PARAM_UAPSD; + params.value = uapsd; +- ret = ath12k_wmi_send_set_ap_ps_param_cmd(ar, sta->addr, ¶ms); ++ ret = ath12k_wmi_send_set_ap_ps_param_cmd(ar, arsta->addr, ¶ms); + if (ret) + goto err; + + params.param = WMI_AP_PS_PEER_PARAM_MAX_SP; + params.value = max_sp; +- ret = ath12k_wmi_send_set_ap_ps_param_cmd(ar, sta->addr, ¶ms); ++ ret = ath12k_wmi_send_set_ap_ps_param_cmd(ar, arsta->addr, ¶ms); + if (ret) + goto err; + + /* TODO revisit during testing */ + params.param = WMI_AP_PS_PEER_PARAM_SIFS_RESP_FRMTYPE; + params.value = DISABLE_SIFS_RESPONSE_TRIGGER; +- ret = ath12k_wmi_send_set_ap_ps_param_cmd(ar, sta->addr, ¶ms); ++ ret = ath12k_wmi_send_set_ap_ps_param_cmd(ar, arsta->addr, ¶ms); + if (ret) + goto err; + + params.param = WMI_AP_PS_PEER_PARAM_SIFS_RESP_UAPSD; + params.value = DISABLE_SIFS_RESPONSE_TRIGGER; +- ret = ath12k_wmi_send_set_ap_ps_param_cmd(ar, sta->addr, ¶ms); ++ ret = ath12k_wmi_send_set_ap_ps_param_cmd(ar, arsta->addr, ¶ms); + if (ret) + goto err; + +@@ -3141,7 +3188,7 @@ static void ath12k_peer_assoc_h_phymode( + } + + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac peer %pM phymode %s\n", +- sta->addr, ath12k_wmi_phymode_str(phymode)); ++ arsta->addr, ath12k_wmi_phymode_str(phymode)); + + arg->peer_phymode = phymode; + WARN_ON(phymode == MODE_UNKNOWN); +@@ -3171,6 +3218,7 @@ static void ath12k_peer_assoc_prepare(st + ath12k_peer_assoc_h_eht(ar, arvif, arsta, arg); + ath12k_peer_assoc_h_qos(ar, arvif, arsta, arg); + ath12k_peer_assoc_h_smps(arsta, arg); ++ ath12k_peer_assoc_h_mlo(arsta, arg); + + arsta->peer_nss = arg->peer_nss; + +@@ -4872,7 +4920,7 @@ static int ath12k_mac_set_key(struct ath + } + + if (sta) +- peer_addr = sta->addr; ++ peer_addr = arsta->addr; + else if (ahvif->vdev_type == WMI_VDEV_TYPE_STA) + peer_addr = link_conf->bssid; + else +@@ -5111,24 +5159,24 @@ ath12k_mac_set_peer_vht_fixed_rate(struc + + if (!nss) { + ath12k_warn(ar->ab, "No single VHT Fixed rate found to set for %pM", +- sta->addr); ++ arsta->addr); + return -EINVAL; + } + + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, + "Setting Fixed VHT Rate for peer %pM. Device will not switch to any other selected rates", +- sta->addr); ++ arsta->addr); + + rate_code = ATH12K_HW_RATE_CODE(vht_rate, nss - 1, + WMI_RATE_PREAMBLE_VHT); +- ret = ath12k_wmi_set_peer_param(ar, sta->addr, ++ 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", +- sta->addr, rate_code, ret); ++ arsta->addr, rate_code, ret); + + return ret; + } +@@ -5161,7 +5209,7 @@ ath12k_mac_set_peer_he_fixed_rate(struct + + if (!nss) { + ath12k_warn(ar->ab, "No single HE Fixed rate found to set for %pM", +- sta->deflink.addr); ++ arsta->addr); + return -EINVAL; + } + +@@ -5171,19 +5219,19 @@ ath12k_mac_set_peer_he_fixed_rate(struct + + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, + "Setting Fixed HE Rate for peer %pM. Device will not switch to any other selected rates", +- sta->deflink.addr); ++ arsta->addr); + + rate_code = ATH12K_HW_RATE_CODE(he_rate, nss - 1, + WMI_RATE_PREAMBLE_HE); + +- ret = ath12k_wmi_set_peer_param(ar, sta->deflink.addr, ++ 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", +- sta->deflink.addr, rate_code, ret); ++ arsta->addr, rate_code, ret); + + return ret; + } +@@ -5271,7 +5319,7 @@ ath12k_mac_set_peer_eht_fixed_rate(struc + + if (!nss) { + ath12k_warn(ar->ab, "No single EHT Fixed rate found to set for %pM", +- sta->deflink.addr); ++ arsta->addr); + return -EINVAL; + } + +@@ -5281,38 +5329,40 @@ ath12k_mac_set_peer_eht_fixed_rate(struc + + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, + "Setting Fixed EHT Rate for peer %pM. Device will not switch to any other selected rates", +- sta->deflink.addr); ++ arsta->addr); + + rate_code = ATH12K_HW_RATE_CODE(eht_rate, nss - 1, + WMI_RATE_PREAMBLE_EHT); + +- ret = ath12k_wmi_set_peer_param(ar, sta->deflink.addr, ++ 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", +- sta->deflink.addr, rate_code, ret); ++ arsta->addr, rate_code, ret); + + return ret; + } + + static int ath12k_station_assoc(struct ath12k *ar, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta, +- bool reassoc, u8 link_id) ++ struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta, ++ bool reassoc) + { +- struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); +- struct ath12k_link_vif *arvif = ahvif->link[link_id]; +- struct ath12k_link_sta *arsta; +- struct ath12k_sta *ahsta; ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_vif *vif = ahvif->vif; ++ struct ieee80211_sta *sta; ++ struct ieee80211_link_sta *link_sta; + struct peer_assoc_params peer_arg; + int ret = 0; + struct cfg80211_chan_def def; + enum nl80211_band band; + struct cfg80211_bitrate_mask *mask; + u8 num_vht_rates, num_he_rates, num_eht_rates, num_ht_rates; ++ u8 link_id = arvif->link_id; + + lockdep_assert_held(&ar->conf_mutex); + +@@ -5322,6 +5372,11 @@ static int ath12k_station_assoc(struct a + if (WARN_ON(ath12k_mac_vif_chan(vif, &def, link_id))) + return -EPERM; + ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); ++ ++ if (WARN_ON(rcu_access_pointer(sta->link[link_id]) == NULL)) ++ return -EINVAL; ++ + band = def.chan->band; + mask = &arvif->bitrate_mask; + +@@ -5334,13 +5389,13 @@ static int ath12k_station_assoc(struct a + ret = ath12k_wmi_send_peer_assoc_cmd(ar, &peer_arg); + if (ret) { + ath12k_warn(ar->ab, "failed to run peer assoc for STA %pM vdev %i: %d\n", +- sta->addr, arvif->vdev_id, ret); ++ arsta->addr, arvif->vdev_id, ret); + return ret; + } + + if (!wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ)) { + ath12k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n", +- sta->addr, arvif->vdev_id); ++ arsta->addr, arvif->vdev_id); + return -ETIMEDOUT; + } + +@@ -5382,7 +5437,7 @@ static int ath12k_station_assoc(struct a + if (reassoc) + return 0; + +- ret = ath12k_setup_peer_smps(ar, arvif, sta->addr, ++ ret = ath12k_setup_peer_smps(ar, arvif, arsta->addr, + &sta->deflink.ht_cap, + le16_to_cpu(sta->deflink.he_6ghz_capa.capa)); + if (ret) { +@@ -5402,21 +5457,35 @@ static int ath12k_station_assoc(struct a + ret = ath12k_peer_assoc_qos_ap(ar, arvif, arsta); + if (ret) { + ath12k_warn(ar->ab, "failed to set qos params for STA %pM for vdev %i: %d\n", +- sta->addr, arvif->vdev_id, ret); ++ arsta->addr, arvif->vdev_id, ret); + return ret; + } + } + ++ spin_lock_bh(&ar->data_lock); ++ ++ /* Set arsta bw and prev bw */ ++ rcu_read_lock(); ++ link_sta = rcu_dereference(sta->link[link_id]); ++ if (link_sta) { ++ arsta->bw = link_sta->bandwidth; ++ arsta->bw_prev = link_sta->bandwidth; ++ } else { ++ ath12k_warn(ar->ab, "failed to get link sta to store bw"); ++ } ++ rcu_read_unlock(); ++ ++ spin_unlock_bh(&ar->data_lock); ++ + return 0; + } + + static int ath12k_station_disassoc(struct ath12k *ar, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta, +- u8 link_id) ++ struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta) + { +- struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); +- struct ath12k_link_vif *arvif = ahvif->link[link_id]; ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; + int ret = 0; + + lockdep_assert_held(&ar->conf_mutex); +@@ -5424,6 +5493,8 @@ static int ath12k_station_disassoc(struc + if (!arvif) + return -EINVAL; + ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); ++ + if (!sta->wme) { + arvif->num_legacy_stations--; + ret = ath12k_recalc_rtscts_prot(arvif); +@@ -5434,6 +5505,69 @@ static int ath12k_station_disassoc(struc + return 0; + } + ++static int ath12k_station_authorize(struct ath12k *ar, ++ struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta) ++{ ++ struct ath12k_peer *peer; ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; ++ int ret = 0; ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); ++ ++ spin_lock_bh(&ar->ab->base_lock); ++ ++ peer = ath12k_peer_find(ar->ab, arvif->vdev_id, arsta->addr); ++ if (peer) ++ peer->is_authorized = true; ++ ++ spin_unlock_bh(&ar->ab->base_lock); ++ ++ if (ahvif->vif->type == NL80211_IFTYPE_STATION && arvif->is_up) { ++ ret = ath12k_wmi_set_peer_param(ar, arsta->addr, ++ arvif->vdev_id, ++ WMI_PEER_AUTHORIZE, ++ 1); ++ if (ret) ++ ath12k_warn(ar->ab, "Unable to authorize peer %pM vdev %d: %d\n", ++ arsta->addr, arvif->vdev_id, ret); ++ } ++ ++ return ret; ++} ++ ++static int ath12k_station_unauthorize(struct ath12k *ar, ++ struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta) ++{ ++ struct ath12k_peer *peer; ++ int ret = 0; ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ spin_lock_bh(&ar->ab->base_lock); ++ ++ peer = ath12k_peer_find(ar->ab, arvif->vdev_id, arsta->addr); ++ if (peer) ++ peer->is_authorized = false; ++ ++ spin_unlock_bh(&ar->ab->base_lock); ++ ++ /* Driver should clear the peer keys during mac80211's ref ptr ++ * gets cleared in __sta_info_destroy_part2 (trans from ++ * IEEE80211_STA_AUTHORIZED to IEEE80211_STA_ASSOC) ++ */ ++ ret = ath12k_clear_peer_keys(arvif, arsta->addr); ++ if (ret) ++ ath12k_warn(ar->ab, "failed to clear all peer keys for vdev %i: %d\n", ++ arvif->vdev_id, ret); ++ ++ return ret; ++} ++ + static void ath12k_sta_rc_update_wk(struct work_struct *wk) + { + struct ath12k *ar; +@@ -5452,9 +5586,11 @@ static void ath12k_sta_rc_update_wk(stru + const struct cfg80211_bitrate_mask *mask; + struct peer_assoc_params peer_arg; + enum wmi_phy_mode peer_phymode; ++ struct ath12k_sta *ahsta; + + arsta = container_of(wk, struct ath12k_link_sta, update_wk); +- sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv); ++ ahsta = arsta->ahsta; ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + arvif = arsta->arvif; + ahvif = arvif->ahvif; + ar = arvif->ar; +@@ -5499,64 +5635,64 @@ static void ath12k_sta_rc_update_wk(stru + * followed by WMI_PEER_CHWIDTH + */ + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac BW upgrade for sta %pM new BW %d, old BW %d\n", +- sta->addr, bw, bw_prev); +- err = ath12k_wmi_set_peer_param(ar, sta->addr, ++ arsta->addr, bw, bw_prev); ++ err = ath12k_wmi_set_peer_param(ar, arsta->addr, + arvif->vdev_id, WMI_PEER_PHYMODE, + peer_phymode); + if (err) { + ath12k_warn(ar->ab, "failed to update STA %pM peer phymode %d: %d\n", +- sta->addr, peer_phymode, err); ++ arsta->addr, peer_phymode, err); + goto err_rc_bw_changed; + } +- err = ath12k_wmi_set_peer_param(ar, sta->addr, ++ err = ath12k_wmi_set_peer_param(ar, arsta->addr, + arvif->vdev_id, WMI_PEER_CHWIDTH, + bw); + if (err) + ath12k_warn(ar->ab, "failed to update STA %pM peer bw %d: %d\n", +- sta->addr, bw, err); ++ arsta->addr, bw, err); + } else { + /* BW is downgraded. In this case we send + * WMI_PEER_CHWIDTH followed by WMI_PEER_PHYMODE + */ + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac BW downgrade for sta %pM new BW %d,old BW %d\n", +- sta->addr, bw, bw_prev); +- err = ath12k_wmi_set_peer_param(ar, sta->addr, ++ arsta->addr, bw, bw_prev); ++ err = ath12k_wmi_set_peer_param(ar, arsta->addr, + arvif->vdev_id, WMI_PEER_CHWIDTH, + bw); + if (err) { + ath12k_warn(ar->ab, "failed to update STA %pM peer bw %d: %d\n", +- sta->addr, bw, err); ++ arsta->addr, bw, err); + goto err_rc_bw_changed; + } +- err = ath12k_wmi_set_peer_param(ar, sta->addr, ++ err = ath12k_wmi_set_peer_param(ar, arsta->addr, + arvif->vdev_id, WMI_PEER_PHYMODE, + peer_phymode); + if (err) + ath12k_warn(ar->ab, "failed to update STA %pM peer phymode %d: %d\n", +- sta->addr, peer_phymode, err); ++ arsta->addr, peer_phymode, err); + } + } + + if (changed & IEEE80211_RC_NSS_CHANGED) { + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac update sta %pM nss %d\n", +- sta->addr, nss); ++ arsta->addr, nss); + +- err = ath12k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, ++ err = ath12k_wmi_set_peer_param(ar, arsta->addr, arvif->vdev_id, + WMI_PEER_NSS, nss); + if (err) + ath12k_warn(ar->ab, "failed to update STA %pM nss %d: %d\n", +- sta->addr, nss, err); ++ arsta->addr, nss, err); + } + + if (changed & IEEE80211_RC_SMPS_CHANGED) { + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac update sta %pM smps %d\n", +- sta->addr, smps); ++ arsta->addr, smps); + +- err = ath12k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, ++ err = ath12k_wmi_set_peer_param(ar, arsta->addr, arvif->vdev_id, + WMI_PEER_MIMO_PS_STATE, smps); + if (err) + ath12k_warn(ar->ab, "failed to update STA %pM smps %d: %d\n", +- sta->addr, smps, err); ++ arsta->addr, smps, err); + } + + if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) { +@@ -5601,14 +5737,14 @@ static void ath12k_sta_rc_update_wk(stru + * than peer assoc + */ + +- err = ath12k_wmi_set_peer_param(ar, sta->deflink.addr, ++ 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", +- sta->deflink.addr, err); ++ arsta->addr, err); + ath12k_peer_assoc_prepare(ar, arvif, arsta, + &peer_arg, true); + +@@ -5616,11 +5752,11 @@ static void ath12k_sta_rc_update_wk(stru + err = ath12k_wmi_send_peer_assoc_cmd(ar, &peer_arg); + if (err) + ath12k_warn(ar->ab, "failed to run peer assoc for STA %pM vdev %i: %d\n", +- sta->addr, arvif->vdev_id, err); ++ arsta->addr, arvif->vdev_id, err); + + if (!wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ)) + ath12k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n", +- sta->addr, arvif->vdev_id); ++ arsta->addr, arvif->vdev_id); + } + } + err_rc_bw_changed: +@@ -5649,14 +5785,14 @@ static void ath12k_sta_set_4addr_wk(stru + ar = arvif->ar; + + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, +- "setting USE_4ADDR for peer %pM\n", sta->addr); ++ "setting USE_4ADDR for peer %pM\n", arsta->addr); + +- ret = ath12k_wmi_set_peer_param(ar, sta->addr, ++ ret = ath12k_wmi_set_peer_param(ar, arsta->addr, + arvif->vdev_id, + WMI_PEER_USE_4ADDR, 1); + if (ret) + ath12k_warn(ar->ab, "failed to set peer %pM 4addr capability: %d\n", +- sta->addr, ret); ++ arsta->addr, ret); + } + } + +@@ -5701,6 +5837,70 @@ static void ath12k_mac_dec_num_stations( + ar->num_stations--; + } + ++static void ath12k_mac_station_post_remove(struct ath12k *ar, ++ struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta) ++{ ++ struct ath12k_peer *peer; ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); ++ ++ ath12k_mac_dec_num_stations(arvif, arsta); ++ ++ spin_lock_bh(&ar->ab->base_lock); ++ peer = ath12k_peer_find(ar->ab, arvif->vdev_id, arsta->addr); ++ if (peer && peer->sta == sta) { ++ ath12k_warn(ar->ab, "Found peer entry %pM n vdev %i after it was supposedly removed\n", ++ arsta->addr, arvif->vdev_id); ++ peer->sta = NULL; ++ list_del(&peer->list); ++ kfree(peer); ++ ar->num_peers--; ++ } ++ spin_unlock_bh(&ar->ab->base_lock); ++ ++ kfree(arsta->tx_stats); ++ arsta->tx_stats = NULL; ++ ++ kfree(arsta->rx_stats); ++ arsta->rx_stats = NULL; ++ ath12k_mac_ap_ps_recalc(ar); ++ ahsta->ahvif = NULL; ++} ++ ++static int ath12k_mac_station_remove(struct ath12k *ar, ++ struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta) ++{ ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; ++ int ret; ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ /* This would be done separately */ ++ if (sta->mlo) ++ return 0; ++ ++ ath12k_dp_peer_cleanup(ar, arvif->vdev_id, arsta->addr); ++ ++ ret = ath12k_peer_delete(ar, arvif->vdev_id, arsta->addr); ++ if (ret) ++ ath12k_warn(ar->ab, "Failed to delete peer: %pM for VDEV: %d\n", ++ arsta->addr, arvif->vdev_id); ++ else ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "Removed peer: %pM for VDEV: %d\n", ++ arsta->addr, arvif->vdev_id); ++ ++ ath12k_mac_station_post_remove(ar, arvif, arsta); ++ ++ return ret; ++} ++ + static int ath12k_mac_station_add(struct ath12k *ar, + struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta) +@@ -5710,7 +5910,7 @@ static int ath12k_mac_station_add(struct + struct ath12k_vif *ahvif = arvif->ahvif; + struct ath12k_sta *ahsta = arsta->ahsta; + struct ieee80211_sta *sta; +- struct peer_create_params peer_param; ++ struct peer_create_params peer_param = {0}; + int ret; + + lockdep_assert_held(&ar->conf_mutex); +@@ -5736,18 +5936,19 @@ static int ath12k_mac_station_add(struct + } + + peer_param.vdev_id = arvif->vdev_id; +- peer_param.peer_addr = sta->addr; ++ peer_param.peer_addr = arsta->addr; + peer_param.peer_type = WMI_PEER_TYPE_DEFAULT; ++ peer_param.ml_enabled = sta->mlo; + + ret = ath12k_peer_create(ar, arvif, sta, &peer_param); + if (ret) { + ath12k_warn(ab, "Failed to add peer: %pM for VDEV: %d\n", +- sta->addr, arvif->vdev_id); ++ arsta->addr, arvif->vdev_id); + goto free_rx_stats; + } + + ath12k_dbg(ab, ATH12K_DBG_MAC, "Added peer: %pM for VDEV: %d num_stations : %d\n", +- sta->addr, arvif->vdev_id, ar->num_stations); ++ arsta->addr, arvif->vdev_id, ar->num_stations); + + if (ath12k_debugfs_is_extd_tx_stats_enabled(ar) && (!arsta->tx_stats)) { + arsta->tx_stats = kzalloc(sizeof(*arsta->tx_stats), +@@ -5766,20 +5967,20 @@ static int ath12k_mac_station_add(struct + ath12k_mac_ap_ps_recalc(ar); + + if (ieee80211_vif_is_mesh(vif)) { +- ret = ath12k_wmi_set_peer_param(ar, sta->addr, ++ ret = ath12k_wmi_set_peer_param(ar, arsta->addr, + arvif->vdev_id, + WMI_PEER_USE_4ADDR, 1); + if (ret) { + ath12k_warn(ab, "failed to STA %pM 4addr capability: %d\n", +- sta->addr, ret); ++ arsta->addr, ret); + goto free_tx_stats; + } + } + +- ret = ath12k_dp_peer_setup(ar, arvif->vdev_id, sta->addr); ++ ret = ath12k_dp_peer_setup(ar, arvif->vdev_id, arsta->addr); + if (ret) { + ath12k_warn(ab, "failed to setup dp for peer %pM on vdev %i (%d)\n", +- sta->addr, arvif->vdev_id, ret); ++ arsta->addr, arvif->vdev_id, ret); + goto free_tx_stats; + } + +@@ -5793,6 +5994,9 @@ static int ath12k_mac_station_add(struct + } + } + ++ INIT_WORK(&arsta->update_wk, ath12k_sta_rc_update_wk); ++ ++ ahsta->ahvif = ahvif; + return 0; + + free_tx_stats: +@@ -5801,7 +6005,7 @@ free_tx_stats: + kfree(arsta->wbm_tx_stats); + arsta->wbm_tx_stats = NULL; + free_peer: +- ath12k_peer_delete(ar, arvif->vdev_id, sta->addr); ++ ath12k_peer_delete(ar, arvif->vdev_id, arsta->addr); + free_rx_stats: + kfree(arsta->rx_stats); + arsta->rx_stats = NULL; +@@ -5811,190 +6015,244 @@ exit: + return ret; + } + +-static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta, +- enum ieee80211_sta_state old_state, +- enum ieee80211_sta_state new_state) ++static u16 ath12k_mac_alloc_ml_peer_id(struct ath12k_hw *ah) ++{ ++ ++ u16 ml_peer_id; ++ ++ lockdep_assert_held(&ah->conf_mutex); ++ ++ for (ml_peer_id = 0; ml_peer_id < ATH12K_MAX_MLO_PEERS; ml_peer_id++) { ++ if (test_bit(ml_peer_id, ah->free_ml_peer_id_map)) ++ continue; ++ ++ set_bit(ml_peer_id, ah->free_ml_peer_id_map); ++ break; ++ } ++ ++ if (ml_peer_id == ATH12K_MAX_MLO_PEERS) ++ ml_peer_id = ATH12K_MLO_PEER_ID_INVALID; ++ ++ return ml_peer_id; ++} ++ ++static int ath12k_mac_assign_link_sta(struct ath12k_hw *ah, ++ struct ath12k_sta *ahsta, ++ struct ath12k_link_sta *arsta, ++ struct ath12k_vif *ahvif, ++ u8 link_id) ++{ ++ struct ieee80211_link_sta *link_sta; ++ struct ieee80211_sta *sta; ++ ++ lockdep_assert_held(&ah->conf_mutex); ++ ++ if (!arsta || link_id > IEEE80211_MLD_MAX_NUM_LINKS) ++ return -EINVAL; ++ ++ if (WARN_ON(!ahvif->link[link_id])) ++ return -EINVAL; ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); ++ ++ memset(arsta, 0, sizeof(*arsta)); ++ ++ rcu_read_lock(); ++ link_sta = rcu_dereference(sta->link[link_id]); ++ if (!link_sta) { ++ rcu_read_unlock(); ++ return -EINVAL; ++ } ++ ether_addr_copy(arsta->addr, link_sta->addr); ++ rcu_read_unlock(); ++ ++ /* logical index of the link sta in order of creation */ ++ arsta->link_idx = ahsta->num_peer++; ++ ++ ahsta->link[link_id] = arsta; ++ ahsta->links_map |= BIT(link_id); ++ arsta->arvif = ahvif->link[link_id]; ++ arsta->ahsta = ahsta; ++ arsta->link_id = link_id; ++ ++ return 0; ++} ++ ++static int ath12k_mac_unassign_link_sta(struct ath12k_hw *ah, ++ struct ath12k_sta *ahsta, ++ u8 link_id) ++{ ++ lockdep_assert_held(&ah->conf_mutex); ++ ++ if (link_id > IEEE80211_MLD_MAX_NUM_LINKS) ++ return -EINVAL; ++ ++ ahsta->link[link_id] = NULL; ++ ahsta->links_map &= ~BIT(link_id); ++ ++ return 0; ++} ++ ++static struct ath12k_link_sta * ++ath12k_mac_alloc_assign_link_sta(struct ath12k_hw *ah, struct ath12k_sta *ahsta, ++ struct ath12k_vif *ahvif, u8 link_id) + { +- struct ath12k_hw *ah = hw->priv; +- struct ath12k *ar; +- struct ath12k_link_vif *arvif; + struct ath12k_link_sta *arsta; +- struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); +- struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; +- struct ath12k_peer *peer; +- int ret = 0; + +- /* TODO handle ML link vif/sta separately */ +- if (vif->valid_links) +- return 0; ++ lockdep_assert_held(&ah->conf_mutex); + +- mutex_lock(&ah->conf_mutex); ++ if (link_id > IEEE80211_MLD_MAX_NUM_LINKS) ++ return NULL; ++ ++ if (ahsta->link[link_id]) { ++ WARN_ON(1); ++ return NULL; ++ } ++ ++ arsta = kzalloc(sizeof(*arsta), GFP_KERNEL); ++ if (!arsta) ++ return NULL; ++ ++ if (ath12k_mac_assign_link_sta(ah, ahsta, arsta, ahvif, link_id)) { ++ kfree(arsta); ++ return NULL; ++ } ++ ++ return arsta; ++} ++ ++static int ath12k_mac_free_unassign_link_sta(struct ath12k_hw *ah, ++ struct ath12k_sta *ahsta, ++ u8 link_id) ++{ ++ struct ath12k_link_sta *arsta; ++ ++ lockdep_assert_held(&ah->conf_mutex); ++ ++ if (link_id > IEEE80211_MLD_MAX_NUM_LINKS) ++ return -EINVAL; ++ ++ arsta = ahsta->link[link_id]; ++ ++ WARN_ON(arsta == NULL); ++ ++ ath12k_mac_unassign_link_sta(ah, ahsta, link_id); ++ ++ if (arsta != &ahsta->deflink) ++ kfree(arsta); ++ ++ return 0; ++} ++ ++static void ath12k_mac_ml_station_remove(struct ath12k_vif *ahvif, ++ struct ath12k_sta *ahsta) ++{ ++ struct ieee80211_sta *sta; ++ struct ath12k_hw *ah = ahvif->ah; ++ struct ath12k_link_vif *arvif; ++ struct ath12k_link_sta *arsta; ++ struct ath12k *ar; ++ u8 link_id; ++ ++ lockdep_assert_held(&ah->conf_mutex); ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); ++ ++ ath12k_ml_peer_delete(ahvif, ahsta); ++ ++ /* validate link station removal and clear arsta links */ ++ for_each_set_bit(link_id, &sta->valid_links, IEEE80211_MLD_MAX_NUM_LINKS) { ++ arvif = ahvif->link[link_id]; ++ arsta = ahsta->link[link_id]; ++ ++ if (WARN_ON(!arvif || !arsta)) ++ continue; ++ ++ ar = arvif->ar; ++ ++ mutex_lock(&ar->conf_mutex); ++ ath12k_mac_station_post_remove(ar, arvif, arsta); ++ mutex_unlock(&ar->conf_mutex); ++ ++ ath12k_mac_free_unassign_link_sta(ah, ahsta, link_id); ++ } ++ clear_bit(ahsta->ml_peer_id, ah->free_ml_peer_id_map); ++ ahsta->ml_peer_id = ATH12K_MLO_PEER_ID_INVALID; ++} ++ ++static int ath12k_mac_handle_link_sta_state(struct ieee80211_hw *hw, ++ struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta, ++ enum ieee80211_sta_state old_state, ++ enum ieee80211_sta_state new_state) ++{ ++ struct ath12k *ar = arvif->ar; ++ struct ieee80211_vif *vif = arvif->ahvif->vif; ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; ++ int ret = 0; + +- arvif = &ahvif->deflink; +- arsta = &ahsta->deflink; +- ar = arvif->ar; + if (!ar) { + ath12k_err(NULL, "unable to determine device to set sta state\n"); +- mutex_unlock(&ah->conf_mutex); + return -EINVAL; + } + +- /* cancel must be done outside the mutex to avoid deadlock */ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); ++ ++ /* cancel must be done outside the ar mutex to avoid deadlock */ + if ((old_state == IEEE80211_STA_NONE && + new_state == IEEE80211_STA_NOTEXIST)) { ++ /* ML sta needs separate handling */ ++ if (sta->mlo) ++ return 0; + cancel_work_sync(&arsta->update_wk); +- cancel_work_sync(&ahsta->set_4addr_wk); +- ahsta->link[0] = NULL; +- ahsta->links_map = 0; + } + + mutex_lock(&ar->conf_mutex); + + if (old_state == IEEE80211_STA_NOTEXIST && + new_state == IEEE80211_STA_NONE) { +- ahsta->link[0] = arsta; +- ahsta->links_map = 1; +- memset(arsta, 0, sizeof(*arsta)); +- arsta->arvif = arvif; +- INIT_WORK(&arsta->update_wk, ath12k_sta_rc_update_wk); +- INIT_WORK(&ahsta->set_4addr_wk, ath12k_sta_set_4addr_wk); + + ret = ath12k_mac_station_add(ar, arvif, arsta); + if (ret) + ath12k_warn(ar->ab, "Failed to add station: %pM for VDEV: %d\n", +- sta->addr, arvif->vdev_id); ++ arsta->addr, arvif->vdev_id); + } else if ((old_state == IEEE80211_STA_NONE && + new_state == IEEE80211_STA_NOTEXIST)) { +- ath12k_dp_peer_cleanup(ar, arvif->vdev_id, sta->addr); +- +- ret = ath12k_peer_delete(ar, arvif->vdev_id, sta->addr); ++ ret = ath12k_mac_station_remove(ar, arvif, arsta); + if (ret) +- ath12k_warn(ar->ab, "Failed to delete peer: %pM for VDEV: %d num_peers : %d\n", +- sta->addr, arvif->vdev_id, ar->num_peers); +- else +- ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "Removed peer: %pM for VDEV: %d num_peers : %d\n", +- sta->addr, arvif->vdev_id, ar->num_peers); +- +- ath12k_mac_dec_num_stations(arvif, arsta); +- spin_lock_bh(&ar->ab->base_lock); +- peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr); +- if (peer && peer->sta == sta) { +- ath12k_warn(ar->ab, "Found peer entry %pM n vdev %d after it was supposedly removed" +- " num_peers : %d\n", vif->addr, arvif->vdev_id, ar->num_peers); +- peer->sta = NULL; +- list_del(&peer->list); +- kfree(peer); +- ar->num_peers--; +- } +- spin_unlock_bh(&ar->ab->base_lock); +- +- kfree(arsta->tx_stats); +- arsta->tx_stats = NULL; +- kfree(arsta->wbm_tx_stats); +- arsta->wbm_tx_stats = NULL; +- +- kfree(arsta->rx_stats); +- arsta->rx_stats = NULL; +- ath12k_mac_ap_ps_recalc(ar); ++ ath12k_warn(ar->ab, "Failed to remove station: %pM for VDEV: %d\n", ++ arsta->addr, arvif->vdev_id); ++ if (sta->valid_links) ++ ath12k_mac_free_unassign_link_sta(arvif->ahvif->ah, ++ arsta->ahsta, arsta->link_id); + } else if (old_state == IEEE80211_STA_AUTH && + new_state == IEEE80211_STA_ASSOC && + (vif->type == NL80211_IFTYPE_AP || + vif->type == NL80211_IFTYPE_MESH_POINT || + vif->type == NL80211_IFTYPE_ADHOC)) { +- ret = ath12k_station_assoc(ar, vif, sta, false, 0); ++ ret = ath12k_station_assoc(ar, arvif, arsta, false); + if (ret) + ath12k_warn(ar->ab, "Failed to associate station: %pM\n", +- sta->addr); +- +- spin_lock_bh(&ar->data_lock); +- +- /* Set arsta bw and prev bw */ +- arsta->bw = sta->deflink.bandwidth; +- arsta->bw_prev = sta->deflink.bandwidth; +- +- spin_unlock_bh(&ar->data_lock); ++ arsta->addr); + } else if (old_state == IEEE80211_STA_ASSOC && + new_state == IEEE80211_STA_AUTHORIZED) { +- spin_lock_bh(&ar->ab->base_lock); +- +- peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr); +- if (peer) +- peer->is_authorized = true; +- +- spin_unlock_bh(&ar->ab->base_lock); +- +- if (vif->type == NL80211_IFTYPE_STATION && arvif->is_up) { +- ret = ath12k_wmi_set_peer_param(ar, sta->addr, +- arvif->vdev_id, +- WMI_PEER_AUTHORIZE, +- 1); +- if (ret) +- ath12k_warn(ar->ab, "Unable to authorize peer %pM vdev %d: %d\n", +- sta->addr, arvif->vdev_id, ret); +- } ++ ret = ath12k_station_authorize(ar, arvif, arsta); + } else if (old_state == IEEE80211_STA_AUTHORIZED && + new_state == IEEE80211_STA_ASSOC) { +- spin_lock_bh(&ar->ab->base_lock); +- +- peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr); +- if (peer) +- peer->is_authorized = false; +- +- spin_unlock_bh(&ar->ab->base_lock); +- } else if (old_state == IEEE80211_STA_ASSOC && +- new_state == IEEE80211_STA_AUTHORIZED) { +- spin_lock_bh(&ar->ab->base_lock); +- +- peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr); +- if (peer) +- peer->is_authorized = true; +- +- spin_unlock_bh(&ar->ab->base_lock); +- +- if (vif->type == NL80211_IFTYPE_STATION && arvif->is_up) { +- ret = ath12k_wmi_set_peer_param(ar, sta->addr, +- arvif->vdev_id, +- WMI_PEER_AUTHORIZE, +- 1); +- if (ret) +- ath12k_warn(ar->ab, "Unable to authorize peer %pM vdev %d: %d\n", +- sta->addr, arvif->vdev_id, ret); +- } +- } else if (old_state == IEEE80211_STA_AUTHORIZED && +- new_state == IEEE80211_STA_ASSOC) { +- spin_lock_bh(&ar->ab->base_lock); +- +- peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr); +- if (peer) +- peer->is_authorized = false; +- +- spin_unlock_bh(&ar->ab->base_lock); +- +- /* Driver should clear the peer keys during mac80211's ref ptr +- * gets cleared in __sta_info_destroy_part2 (trans from +- * IEEE80211_STA_AUTHORIZED to IEEE80211_STA_ASSOC) +- */ +- ret = ath12k_clear_peer_keys(arvif, sta->addr); +- if (ret) { +- ath12k_warn(ar->ab, "failed to clear all peer keys for vdev %i: %d\n", +- arvif->vdev_id, ret); +- return ret; +- } ++ ath12k_station_unauthorize(ar, arvif, arsta); + } else if (old_state == IEEE80211_STA_ASSOC && + new_state == IEEE80211_STA_AUTH && + (vif->type == NL80211_IFTYPE_AP || + vif->type == NL80211_IFTYPE_MESH_POINT || + vif->type == NL80211_IFTYPE_ADHOC)) { +- ret = ath12k_station_disassoc(ar, vif, sta, 0); ++ ret = ath12k_station_disassoc(ar, arvif, arsta); + if (ret) + ath12k_warn(ar->ab, "Failed to disassociate station: %pM\n", +- sta->addr); ++ arsta->addr); + } + + mutex_unlock(&ar->conf_mutex); +- mutex_unlock(&ah->conf_mutex); + return ret; + } + +@@ -6005,7 +6263,9 @@ static int ath12k_mac_op_sta_set_txpwr(s + struct ath12k_hw *ah = hw->priv; + struct ath12k *ar; + struct ath12k_vif *ahvif = (void *)vif->drv_priv; ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; + struct ath12k_link_vif *arvif; ++ struct ath12k_link_sta *arsta; + int ret = 0; + s16 txpwr; + /* TODO use link id from op after support is available */ +@@ -6015,6 +6275,7 @@ static int ath12k_mac_op_sta_set_txpwr(s + + /* TODO get arvif based on link id */ + arvif = ahvif->link[link_id]; ++ arsta = ahsta->link[link_id]; + + if (!arvif) { + ath12k_err(NULL, "unable to determine device to set sta txpwr\n"); +@@ -6046,7 +6307,7 @@ static int ath12k_mac_op_sta_set_txpwr(s + + mutex_lock(&ar->conf_mutex); + +- ret = ath12k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, ++ ret = ath12k_wmi_set_peer_param(ar, arsta->addr, arvif->vdev_id, + WMI_PEER_USE_FIXED_PWR, txpwr); + if (ret) { + ath12k_warn(ar->ab, "failed to set tx power for station ret: %d\n", +@@ -6061,6 +6322,175 @@ out: + return ret; + } + ++static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_sta *sta, ++ enum ieee80211_sta_state old_state, ++ enum ieee80211_sta_state new_state) ++{ ++ struct ath12k_hw *ah = hw->priv; ++ struct ath12k_link_vif *arvif; ++ struct ath12k_link_sta *arsta; ++ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ int ret = 0; ++ u8 link_id = 0; ++ ++ mutex_lock(&ah->conf_mutex); ++ ++ if (vif->valid_links && sta->valid_links) { ++ if (!sta->mlo) ++ WARN_ON(hweight16(sta->valid_links) != 1); ++ link_id = ffs(sta->valid_links) - 1; ++ } ++ ++ if ((old_state == IEEE80211_STA_NONE && ++ new_state == IEEE80211_STA_NOTEXIST)) { ++ cancel_work_sync(&ahsta->set_4addr_wk); ++ } ++ ++ if ((old_state == IEEE80211_STA_NOTEXIST && ++ new_state == IEEE80211_STA_NONE)) { ++ INIT_WORK(&ahsta->set_4addr_wk, ath12k_sta_set_4addr_wk); ++ if (!sta->mlo) { ++ ret = ath12k_mac_assign_link_sta(ah, ahsta, &ahsta->deflink, ++ ahvif, link_id); ++ if (ret) ++ return ret; ++ } ++ } ++ ++ if (!sta->mlo) { ++ arvif = ahvif->link[link_id]; ++ arsta = ahsta->link[link_id]; ++ ++ if (WARN_ON(arvif == NULL || arsta == NULL)) ++ return -EINVAL; ++ ++ ret = ath12k_mac_handle_link_sta_state(hw, arvif, arsta, ++ old_state, new_state); ++ mutex_unlock(&ah->conf_mutex); ++ return ret; ++ } ++ ++ /* Support only AP for now */ ++ if (vif->type != NL80211_IFTYPE_AP) ++ return -EINVAL; ++ ++ if (!sta->valid_links) ++ WARN_ON(1); ++ ++ /* assign default link to the first link sta */ ++ if (!ahsta->links_map && hweight16(sta->valid_links) == 1 && ++ new_state == IEEE80211_STA_NONE && old_state == IEEE80211_STA_NOTEXIST) { ++ ahsta->ml_peer_id = ath12k_mac_alloc_ml_peer_id(ah); ++ ++ if (ahsta->ml_peer_id == ATH12K_MLO_PEER_ID_INVALID) { ++ ath12k_err(NULL, "unable to allocate ml peer id for sta %pM", sta->addr); ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOSPC; ++ } ++ ++ ath12k_mac_assign_link_sta(ah, ahsta, &ahsta->deflink, ++ ahvif, link_id); ++ ++ ahsta->deflink.is_assoc_link = true; ++ ahsta->assoc_link_id = link_id; ++ } ++ ++ if (new_state == IEEE80211_STA_NOTEXIST && old_state == IEEE80211_STA_NONE) { ++ ath12k_mac_ml_station_remove(ahvif, ahsta); ++ goto exit; ++ } ++ ++ for_each_set_bit(link_id, &sta->valid_links, IEEE80211_MLD_MAX_NUM_LINKS) { ++ arvif = ahvif->link[link_id]; ++ arsta = ahsta->link[link_id]; ++ ++ /* some assumptions went wrong! */ ++ if (WARN_ON(!arvif || !arsta)) ++ continue; ++ ++ ret = ath12k_mac_handle_link_sta_state(hw, arvif, arsta, ++ old_state, new_state); ++ if (ret) { ++ ath12k_err(NULL, "unable to move link sta %d of sta %pM from state %d to %d", ++ link_id, arsta->addr, old_state, new_state); ++ mutex_unlock(&ah->conf_mutex); ++ return ret; ++ } ++ } ++ ++ if (old_state == IEEE80211_STA_AUTH && new_state == IEEE80211_STA_ASSOC) { ++ /* TODO sync wait for ML peer map success, else clear ml peer info on ++ * all partners? TBD on testing ++ */ ++ } ++ ++exit: ++ mutex_unlock(&ah->conf_mutex); ++ ++ return ret; ++} ++ ++static int ath12k_mac_op_change_sta_links(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_sta *sta, ++ u16 old_links, u16 new_links) ++{ ++ struct ath12k_hw *ah = hw->priv; ++ struct ath12k *ar; ++ struct ath12k_link_vif *arvif; ++ struct ath12k_link_sta *arsta; ++ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ u8 link_id; ++ int ret; ++ ++ if (!sta->valid_links) ++ return -EINVAL; ++ ++ mutex_lock(&ah->conf_mutex); ++ ++ if (ahsta->ml_peer_id == ATH12K_MLO_PEER_ID_INVALID) { ++ ath12k_err(NULL, "unable to add link for ml sta %pM", sta->addr); ++ mutex_unlock(&ah->conf_mutex); ++ return -EINVAL; ++ } ++ ++ /* this op is expected only after initial sta insertion with default link */ ++ WARN_ON(ahsta->links_map == 0); ++ ++ for_each_set_bit(link_id, &new_links, IEEE80211_MLD_MAX_NUM_LINKS) { ++ if (ahsta->links_map & BIT(link_id)) ++ continue; ++ ++ arvif = ahvif->link[link_id]; ++ arsta = ath12k_mac_alloc_assign_link_sta(ah, ahsta, ahvif, link_id); ++ ++ if (!arvif || !arsta) { ++ ath12k_err(NULL, "Failed to alloc/assign link sta"); ++ continue; ++ } ++ ++ ar = arvif->ar; ++ ++ mutex_lock(&ar->conf_mutex); ++ ret = ath12k_mac_station_add(ar, arvif, arsta); ++ if (ret) ++ ath12k_warn(ar->ab, "Failed to add station: %pM for VDEV: %d\n", ++ arsta->addr, arvif->vdev_id); ++ mutex_unlock(&ar->conf_mutex); ++ } ++ ++ /* FW doesnt support removal of one of link stas. All sta would be removed during ML STA ++ * delete in sta_state(), hence link sta removal is not handled here. ++ */ ++ mutex_unlock(&ah->conf_mutex); ++ ++ return 0; ++} ++ + static void ath12k_mac_op_sta_set_4addr(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, bool enabled) +@@ -6107,11 +6537,11 @@ static void ath12k_mac_op_sta_rc_update( + + spin_lock_bh(&ar->ab->base_lock); + +- peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr); ++ peer = ath12k_peer_find(ar->ab, arvif->vdev_id, arsta->addr); + if (!peer) { + spin_unlock_bh(&ar->ab->base_lock); + ath12k_warn(ar->ab, "mac sta rc update failed to find peer %pM on vdev %i\n", +- sta->addr, arvif->vdev_id); ++ arsta->addr, arvif->vdev_id); + return; + } + +@@ -6119,7 +6549,7 @@ static void ath12k_mac_op_sta_rc_update( + + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, + "mac sta rc update for %pM changed %08x bw %d nss %d smps %d\n", +- sta->addr, changed, sta->deflink.bandwidth, sta->deflink.rx_nss, ++ arsta->addr, changed, sta->deflink.bandwidth, sta->deflink.rx_nss, + sta->smps_mode); + + spin_lock_bh(&ar->data_lock); +@@ -6145,7 +6575,7 @@ static void ath12k_mac_op_sta_rc_update( + break; + default: + ath12k_warn(ar->ab, "Invalid bandwidth %d in rc update for %pM\n", +- sta->deflink.bandwidth, sta->addr); ++ sta->deflink.bandwidth, arsta->addr); + bw = WMI_PEER_CHWIDTH_20MHZ; + break; + } +@@ -6173,7 +6603,7 @@ static void ath12k_mac_op_sta_rc_update( + break; + default: + ath12k_warn(ar->ab, "Invalid smps %d in sta rc update for %pM\n", +- sta->smps_mode, sta->addr); ++ sta->smps_mode, arsta->addr); + smps = WMI_PEER_SMPS_PS_NONE; + break; + } +@@ -11092,6 +11522,7 @@ static void ath12k_mac_set_bitrate_mask_ + static void ath12k_mac_disable_peer_fixed_rate(void *data, + struct ieee80211_sta *sta) + { ++ struct ath12k_link_sta *arsta; + struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; + struct ath12k_link_vif *arvif = data; + struct ath12k *ar; +@@ -11105,17 +11536,19 @@ static void ath12k_mac_disable_peer_fixe + if (!(BIT(link_id) & ahsta->links_map)) + return; + ++ arsta = ahsta->link[link_id]; ++ + ar = arvif->ar; + + /* TODO move to sta->link addr */ +- ret = ath12k_wmi_set_peer_param(ar, sta->addr, ++ ret = ath12k_wmi_set_peer_param(ar, arsta->addr, + arvif->vdev_id, + WMI_PEER_PARAM_FIXED_RATE, + WMI_FIXED_RATE_NONE); + if (ret) + ath12k_warn(ar->ab, + "failed to disable peer fixed rate for STA %pM ret %d\n", +- sta->addr, ret); ++ arsta->addr, ret); + } + + static bool +@@ -11721,6 +12154,7 @@ static const struct ieee80211_ops ath12k + .get_survey = ath12k_mac_op_get_survey, + .flush = ath12k_mac_op_flush, + .sta_statistics = ath12k_mac_op_sta_statistics, ++ .change_sta_links = ath12k_mac_op_change_sta_links, + CFG80211_TESTMODE_CMD(ath12k_tm_cmd) + #ifdef CPTCFG_ATH12K_DEBUGFS + .sta_add_debugfs = ath12k_debugfs_sta_op_add, +--- a/drivers/net/wireless/ath/ath12k/peer.c ++++ b/drivers/net/wireless/ath/ath12k/peer.c +@@ -8,6 +8,10 @@ + #include "peer.h" + #include "debug.h" + ++/* TODO extend peer search apis for ml addr either combined or separately ++ * based on dp needs ++ */ ++ + struct ath12k_peer *ath12k_peer_find(struct ath12k_base *ab, int vdev_id, + const u8 *addr) + { +@@ -63,6 +67,20 @@ struct ath12k_peer *ath12k_peer_find_by_ + return NULL; + } + ++static struct ath12k_peer *ath12k_peer_find_by_ml_id(struct ath12k_base *ab, ++ int ml_peer_id) ++{ ++ struct ath12k_peer *peer; ++ ++ lockdep_assert_held(&ab->base_lock); ++ ++ list_for_each_entry(peer, &ab->peers, list) ++ if (ml_peer_id == peer->ml_peer_id) ++ return peer; ++ ++ return NULL; ++} ++ + struct ath12k_peer *ath12k_peer_find_by_id(struct ath12k_base *ab, + int peer_id) + { +@@ -70,6 +88,9 @@ struct ath12k_peer *ath12k_peer_find_by_ + + lockdep_assert_held(&ab->base_lock); + ++ if (peer_id & ATH12K_ML_PEER_ID_VALID) ++ return ath12k_peer_find_by_ml_id(ab, peer_id); ++ + list_for_each_entry(peer, &ab->peers, list) + if (peer_id == peer->peer_id) + return peer; +@@ -160,6 +181,60 @@ exit: + spin_unlock_bh(&ab->base_lock); + } + ++void ath12k_peer_mlo_map_event(struct ath12k_base *ab, struct sk_buff *skb) ++{ ++ struct ath11k_htt_mlo_peer_map_msg *msg; ++ u16 ml_peer_id; ++ struct ath12k_peer *peer; ++ u16 mld_mac_h16; ++ u8 mld_addr[ETH_ALEN]; ++ ++ msg = (struct ath11k_htt_mlo_peer_map_msg *)skb->data; ++ ++ ml_peer_id = FIELD_GET(ATH12K_HTT_MLO_PEER_MAP_INFO0_PEER_ID, msg->info0); ++ ++ ml_peer_id |= ATH12K_ML_PEER_ID_VALID; ++ ++ spin_lock_bh(&ab->base_lock); ++ peer = ath12k_peer_find_by_id(ab, ml_peer_id); ++ ++ /* TODO a sync wait to check ml peer map success or delete ++ * ml peer info in all link peers and make peer assoc failure ++ * TBA after testing basic changes ++ */ ++ if (!peer) { ++ ath12k_warn(ab, "peer corresponding to ml peer id %d not found", ml_peer_id); ++ spin_unlock_bh(&ab->base_lock); ++ return; ++ } ++ mld_mac_h16 = FIELD_GET(ATH12K_HTT_MLO_PEER_MAP_MAC_ADDR_H16, ++ msg->mac_addr.mac_addr_h16); ++ ath12k_dp_get_mac_addr(msg->mac_addr.mac_addr_l32, mld_mac_h16, mld_addr); ++ ++ WARN_ON(memcmp(mld_addr, peer->ml_addr, ETH_ALEN)); ++ ++ spin_unlock_bh(&ab->base_lock); ++ ++ ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "htt MLO peer map peer %pM id %d\n", ++ mld_addr, ml_peer_id); ++ ++ /* TODO rx queue setup for the ML peer */ ++} ++ ++void ath12k_peer_mlo_unmap_event(struct ath12k_base *ab, struct sk_buff *skb) ++{ ++ struct ath11k_htt_mlo_peer_unmap_msg *msg; ++ u16 ml_peer_id; ++ ++ msg = (struct ath11k_htt_mlo_peer_unmap_msg *)skb->data; ++ ++ ml_peer_id = FIELD_GET(ATH12K_HTT_MLO_PEER_UNMAP_PEER_ID, msg->info0); ++ ++ ml_peer_id |= ATH12K_ML_PEER_ID_VALID; ++ ++ ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "htt MLO peer unmap peer ml id %d\n", ml_peer_id); ++} ++ + static int ath12k_wait_for_peer_common(struct ath12k_base *ab, int vdev_id, + const u8 *addr, bool expect_mapped) + { +@@ -233,7 +308,7 @@ int ath12k_wait_for_peer_delete_done(str + return 0; + } + +-int ath12k_peer_delete(struct ath12k *ar, u32 vdev_id, u8 *addr) ++static int ath12k_peer_delete_send(struct ath12k *ar, u32 vdev_id, u8 *addr) + { + int ret; + +@@ -249,6 +324,19 @@ int ath12k_peer_delete(struct ath12k *ar + return ret; + } + ++ return 0; ++} ++ ++int ath12k_peer_delete(struct ath12k *ar, u32 vdev_id, u8 *addr) ++{ ++ int ret; ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ ret = ath12k_peer_delete_send(ar, vdev_id, addr); ++ if (ret) ++ return ret; ++ + ret = ath12k_wait_for_peer_delete_done(ar, vdev_id, addr); + if (ret) + return ret; +@@ -258,6 +346,76 @@ int ath12k_peer_delete(struct ath12k *ar + return 0; + } + ++int ath12k_ml_peer_delete(struct ath12k_vif *ahvif, struct ath12k_sta *ahsta) ++{ ++ struct ath12k_link_vif *arvif; ++ struct ath12k_link_sta *arsta; ++ struct ieee80211_sta *sta; ++ struct ath12k *ar; ++ int ret, err_ret = 0; ++ u8 link_id = 0; ++ struct ath12k_hw *ah = ahvif->ah; ++ ++ lockdep_assert_held(&ah->conf_mutex); ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); ++ ++ if (!sta->mlo) ++ return -EINVAL; ++ ++ /* FW expects delete of all link peers at once before waiting for reception ++ * of peer unmap or delete responses ++ */ ++ for_each_set_bit(link_id, &sta->valid_links, IEEE80211_MLD_MAX_NUM_LINKS) { ++ arvif = ahvif->link[link_id]; ++ arsta = ahsta->link[link_id]; ++ ++ if (WARN_ON(!arvif || !arsta)) ++ continue; ++ ++ ar = arvif->ar; ++ ++ cancel_work_sync(&arsta->update_wk); ++ ++ mutex_lock(&ar->conf_mutex); ++ ath12k_dp_peer_cleanup(ar, arvif->vdev_id, arsta->addr); ++ ++ ret = ath12k_peer_delete_send(ar, arvif->vdev_id, arsta->addr); ++ if (ret) { ++ mutex_unlock(&ar->conf_mutex); ++ ath12k_warn(ar->ab, ++ "failed to delete peer vdev_id %d addr %pM ret %d\n", ++ arvif->vdev_id, arsta->addr, ret); ++ err_ret = ret; ++ continue; ++ } ++ mutex_unlock(&ar->conf_mutex); ++ } ++ ++ /* Ensure all link peers are deleted and unmapped */ ++ for_each_set_bit(link_id, &sta->valid_links, IEEE80211_MLD_MAX_NUM_LINKS) { ++ arvif = ahvif->link[link_id]; ++ arsta = ahsta->link[link_id]; ++ ++ if (WARN_ON(!arvif || !arsta)) ++ continue; ++ ++ ar = arvif->ar; ++ ++ mutex_lock(&ar->conf_mutex); ++ ret = ath12k_wait_for_peer_delete_done(ar, arvif->vdev_id, arsta->addr); ++ if (ret) { ++ err_ret = ret; ++ mutex_unlock(&ar->conf_mutex); ++ continue; ++ } ++ ar->num_peers--; ++ mutex_unlock(&ar->conf_mutex); ++ } ++ ++ return err_ret; ++} ++ + static int ath12k_wait_for_peer_created(struct ath12k *ar, int vdev_id, const u8 *addr) + { + return ath12k_wait_for_peer_common(ar->ab, vdev_id, addr, true); +@@ -342,15 +500,27 @@ int ath12k_peer_create(struct ath12k *ar + peer->vif = vif; + + if (sta) { +- /* TODO handling for ML PEER */ + ahsta = (struct ath12k_sta *)sta->drv_priv; + arsta = ahsta->link[link_id]; + arsta->tcl_metadata |= FIELD_PREP(HTT_TCL_META_DATA_TYPE, 0) | + FIELD_PREP(HTT_TCL_META_DATA_PEER_ID, + peer->peer_id); ++ peer->link_id = arsta->link_id; + + /* set HTT extension valid bit to 0 by default */ + arsta->tcl_metadata &= ~HTT_TCL_META_DATA_VALID_HTT; ++ ++ /* Fill ML info into created peer */ ++ if (sta->mlo) { ++ peer->ml_peer_id = ahsta->ml_peer_id | ATH12K_ML_PEER_ID_VALID; ++ /* the assoc link is considered primary for now */ ++ peer->primary_link = arsta->is_assoc_link; ++ ether_addr_copy(peer->ml_addr, sta->addr); ++ } else { ++ peer->ml_peer_id = ATH12K_MLO_PEER_ID_INVALID; ++ peer->primary_link = true; ++ } ++ + } + + +--- a/drivers/net/wireless/ath/ath12k/peer.h ++++ b/drivers/net/wireless/ath/ath12k/peer.h +@@ -20,6 +20,12 @@ struct ppdu_user_delayba { + u32 resp_rate_flags; + } __packed; + ++/* Note: The ml info is embedded into the link peer ++ * objects, based on hot dp requirements to fetch link peer ++ * or ml peer based on ml peer id and ml address separate ++ * ml peer list maintained in ah can be done. For now it ++ * doesnt seem to be needed ++ */ + struct ath12k_peer { + struct list_head list; + struct ieee80211_sta *sta; +@@ -33,6 +39,12 @@ struct ath12k_peer { + + /* protected by ab->data_lock */ + struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1]; ++ ++ /* rx tid queue is setup once for primary link peer ++ * in case of ML and cloned into partner peer data ++ * but would be accessed (only if required)and safely ++ * by ensuring primary parner is still valid ++ */ + struct ath12k_dp_rx_tid rx_tid[IEEE80211_NUM_TIDS + 1]; + + /* Info used in MMIC verification of +@@ -51,6 +63,19 @@ struct ath12k_peer { + * a peer has setup its datapath or not + */ + bool dp_setup_done; ++ ++ u16 ml_peer_id; ++ /* TODO remove or fill below these info if required/not required during dp change */ ++ /* for reference to ath12k_link_sta */ ++ u8 link_id; ++ ++ /* To ensure only certain work related to dp is done once */ ++ bool primary_link; ++ ++ /* any other ML info common for all partners can be added ++ * here and would be same for all partner peers ++ */ ++ u8 ml_addr[ETH_ALEN]; + }; + + void ath12k_peer_unmap_event(struct ath12k_base *ab, u16 peer_id); +@@ -63,6 +88,7 @@ struct ath12k_peer *ath12k_peer_find_by_ + struct ath12k_peer *ath12k_peer_find_by_id(struct ath12k_base *ab, int peer_id); + void ath12k_peer_cleanup(struct ath12k *ar, u32 vdev_id); + int ath12k_peer_delete(struct ath12k *ar, u32 vdev_id, u8 *addr); ++int ath12k_ml_peer_delete(struct ath12k_vif *ahvif, struct ath12k_sta *ahsta); + int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif, + struct ieee80211_sta *sta, struct peer_create_params *param); + int ath12k_wait_for_peer_delete_done(struct ath12k *ar, u32 vdev_id, +@@ -70,5 +96,7 @@ int ath12k_wait_for_peer_delete_done(str + struct ath12k_peer *ath12k_peer_find_by_vdev_id(struct ath12k_base *ab, + int vdev_id); + struct ath12k_peer *ath12k_peer_find_by_ast(struct ath12k_base *ab, int ast_hash); ++void ath12k_peer_mlo_map_event(struct ath12k_base *ab, struct sk_buff *skb); ++void ath12k_peer_mlo_unmap_event(struct ath12k_base *ab, struct sk_buff *skb); + + #endif /* _PEER_H_ */ +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -1183,9 +1183,14 @@ int ath12k_wmi_send_peer_create_cmd(stru + struct ath12k_pdev_wmi *wmi = ar->wmi; + struct wmi_peer_create_cmd *cmd; + struct sk_buff *skb; +- int ret; ++ int ret, len; ++ struct wmi_peer_create_mlo_params *ml_param; ++ void *ptr; ++ struct wmi_tlv *tlv; + +- skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd)); ++ len = sizeof(*cmd) + TLV_HDR_SIZE + sizeof(*ml_param); ++ ++ skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len); + if (!skb) + return -ENOMEM; + +@@ -1197,6 +1202,18 @@ int ath12k_wmi_send_peer_create_cmd(stru + cmd->peer_type = cpu_to_le32(param->peer_type); + cmd->vdev_id = cpu_to_le32(param->vdev_id); + ++ ptr = skb->data + sizeof(*cmd); ++ tlv = ptr; ++ tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_STRUCT) | ++ FIELD_PREP(WMI_TLV_LEN, sizeof(*ml_param)); ++ ptr += TLV_HDR_SIZE; ++ ++ ml_param = ptr; ++ ml_param->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_MLO_PEER_CREATE_PARAMS) | ++ FIELD_PREP(WMI_TLV_LEN, sizeof(*ml_param) - TLV_HDR_SIZE); ++ ++ ml_param->flags = FIELD_PREP(ATH12K_WMI_FLAG_MLO_ENABLED, param->ml_enabled); ++ + ret = ath12k_wmi_cmd_send(wmi, skb, WMI_PEER_CREATE_CMDID); + if (ret) { + ath12k_warn(ar->ab, "failed to submit WMI_PEER_CREATE cmd\n"); +@@ -1204,8 +1221,8 @@ int ath12k_wmi_send_peer_create_cmd(stru + } + + ath12k_dbg(ar->ab, ATH12K_DBG_WMI, +- "WMI peer create vdev_id %d peer_addr %pM num_peer : %d\n", +- param->vdev_id, param->peer_addr, ar->num_peers); ++ "WMI peer create vdev_id %d peer_addr %pM ml_enabled %d\n", ++ param->vdev_id, param->peer_addr, param->ml_enabled); + + return ret; + } +@@ -2014,6 +2031,8 @@ int ath12k_wmi_send_peer_assoc_cmd(struc + struct wmi_vht_rate_set *mcs; + struct wmi_he_rate_set *he_mcs; + struct wmi_eht_rate_set *eht_mcs; ++ struct wmi_peer_assoc_mlo_params *ml_params; ++ struct wmi_peer_assoc_mlo_partner_info *partner_info; + struct sk_buff *skb; + struct wmi_tlv *tlv; + void *ptr; +@@ -2032,7 +2051,8 @@ int ath12k_wmi_send_peer_assoc_cmd(struc + sizeof(*mcs) + TLV_HDR_SIZE + + (sizeof(*he_mcs) * param->peer_he_mcs_count) + + TLV_HDR_SIZE + (sizeof(*eht_mcs) * param->peer_eht_mcs_count) + +- TLV_HDR_SIZE + TLV_HDR_SIZE;/* For MLO */ ++ TLV_HDR_SIZE + sizeof(*ml_params) + ++ TLV_HDR_SIZE + (param->ml.num_partner_links * sizeof(*partner_info)); + + skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len); + if (!skb) +@@ -2153,13 +2173,35 @@ int ath12k_wmi_send_peer_assoc_cmd(struc + ptr += sizeof(*he_mcs); + } + +- /* WAR fill MLO Header TAG with 0 length */ +- len = 0; ++ /* MLO params */ + tlv = ptr; + tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_STRUCT) | +- FIELD_PREP(WMI_TLV_LEN, len); ++ FIELD_PREP(WMI_TLV_LEN, sizeof(*ml_params)); + ptr += TLV_HDR_SIZE; + ++ ml_params = ptr; ++ ml_params->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_MLO_PEER_ASSOC_PARAMS) | ++ FIELD_PREP(WMI_TLV_LEN, sizeof(*ml_params) - TLV_HDR_SIZE); ++ ++ ml_params->flags = FIELD_PREP(ATH12K_WMI_FLAG_MLO_ENABLED, ++ param->ml.enabled) | ++ FIELD_PREP(ATH12K_WMI_FLAG_MLO_ASSOC_LINK, ++ param->ml.assoc_link) | ++ FIELD_PREP(ATH12K_WMI_FLAG_MLO_PRIMARY_UMAC, ++ param->ml.primary_umac) | ++ FIELD_PREP(ATH12K_WMI_FLAG_MLO_LOGICAL_LINK_IDX_VALID, ++ param->ml.logical_link_idx_valid) | ++ FIELD_PREP(ATH12K_WMI_FLAG_MLO_PEER_ID_VALID, ++ param->ml.peer_id_valid); ++ ++ ether_addr_copy(ml_params->mld_addr.addr, param->ml.mld_addr); ++ ml_params->logical_link_idx = param->ml.logical_link_idx; ++ ml_params->ml_peer_id = param->ml.ml_peer_id; ++ ml_params->ieee_link_id = param->ml.ieee_link_id; ++ /* TODO emlsr params */ ++ ++ ptr += sizeof(*ml_params); ++ + /* Loop through the EHT rate set. + */ + len = param->peer_eht_mcs_count * sizeof(*eht_mcs); +@@ -2179,13 +2221,33 @@ int ath12k_wmi_send_peer_assoc_cmd(struc + ptr += sizeof(*eht_mcs); + } + +- /* fill ML Partner links Header TAG */ +- len = 0; ++ /* fill ML Partner links */ + tlv = ptr; + tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_STRUCT) | +- FIELD_PREP(WMI_TLV_LEN, len); ++ FIELD_PREP(WMI_TLV_LEN, ++ param->ml.num_partner_links * sizeof(*partner_info)); + ptr += TLV_HDR_SIZE; + ++ for (i = 0; i < param->ml.num_partner_links; i++) { ++ partner_info = ptr; ++ partner_info->tlv_header = FIELD_PREP(WMI_TLV_TAG, ++ WMI_TAG_MLO_PARTNER_LINK_PARAMS_PEER_ASSOC) | ++ FIELD_PREP(WMI_TLV_LEN, ++ sizeof(*partner_info) - TLV_HDR_SIZE); ++ partner_info->vdev_id = param->ml.partner_info[i].vdev_id; ++ partner_info->hw_link_id = param->ml.partner_info[i].hw_link_id; ++ ++ partner_info->flags = FIELD_PREP(ATH12K_WMI_FLAG_MLO_ENABLED, 1) | ++ FIELD_PREP(ATH12K_WMI_FLAG_MLO_ASSOC_LINK, ++ param->ml.partner_info[i].assoc_link) | ++ FIELD_PREP(ATH12K_WMI_FLAG_MLO_PRIMARY_UMAC, ++ param->ml.partner_info[i].primary_umac) | ++ FIELD_PREP(ATH12K_WMI_FLAG_MLO_LOGICAL_LINK_IDX_VALID, ++ param->ml.partner_info[i].logical_link_idx_valid); ++ partner_info->logical_link_idx = param->ml.partner_info[i].logical_link_idx; ++ ptr += sizeof(*partner_info); ++ } ++ + ret = ath12k_wmi_cmd_send(wmi, skb, WMI_PEER_ASSOC_CMDID); + if (ret) { + ath12k_warn(ar->ab, +@@ -2194,7 +2256,7 @@ int ath12k_wmi_send_peer_assoc_cmd(struc + } + + ath12k_dbg(ar->ab, ATH12K_DBG_WMI, +- "wmi peer assoc vdev id %d assoc id %d peer mac %pM peer_flags %x rate_caps %x peer_caps %x listen_intval %d ht_caps %x max_mpdu %d nss %d phymode %d peer_mpdu_density %d vht_caps %x he cap_info %x he ops %x he cap_info_ext %x he phy %x %x %x peer_bw_rxnss_override %x peer_flags_ext %x eht mac_cap %x %x eht phy_cap %x %x %x eht ops %x\n", ++ "wmi peer assoc vdev id %d assoc id %d peer mac %pM peer_flags %x rate_caps %x peer_caps %x listen_intval %d ht_caps %x max_mpdu %d nss %d phymode %d peer_mpdu_density %d vht_caps %x he cap_info %x he ops %x he cap_info_ext %x he phy %x %x %x peer_bw_rxnss_override %x peer_flags_ext %x eht mac_cap %x %x eht phy_cap %x %x %x eht ops %x ml flags %x ml peer id %d num_partner_links %d\n", + cmd->vdev_id, cmd->peer_associd, param->peer_mac, + cmd->peer_flags, cmd->peer_rate_caps, cmd->peer_caps, + cmd->peer_listen_intval, cmd->peer_ht_caps, +@@ -2207,7 +2269,10 @@ int ath12k_wmi_send_peer_assoc_cmd(struc + cmd->peer_bw_rxnss_override, cmd->peer_flags_ext, + cmd->peer_eht_cap_mac[0], cmd->peer_eht_cap_mac[1], + cmd->peer_eht_cap_phy[0], cmd->peer_eht_cap_phy[1], +- cmd->peer_eht_cap_phy[2], cmd->peer_eht_ops); ++ cmd->peer_eht_cap_phy[2], cmd->peer_eht_ops, ++ ml_params->flags, ml_params->ml_peer_id, ++ param->ml.num_partner_links ++ ); + + return ret; + } +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -3131,6 +3131,10 @@ struct wmi_ml_partner_info { + u32 vdev_id; + u32 hw_link_id; + u8 addr[ETH_ALEN]; ++ bool assoc_link; ++ bool primary_umac; ++ bool logical_link_idx_valid; ++ u32 logical_link_idx; + }; + + struct wmi_ml_arg { +@@ -3170,6 +3174,7 @@ struct peer_create_params { + const u8 *peer_addr; + u32 peer_type; + u32 vdev_id; ++ bool ml_enabled; + }; + + struct peer_delete_params { +@@ -3313,6 +3318,11 @@ enum wmi_peer_type { + WMI_PEER_TYPE_TDLS = 2, + }; + ++struct wmi_peer_create_mlo_params { ++ u32 tlv_header; ++ u32 flags; ++} __packed; ++ + struct wmi_peer_create_cmd { + __le32 tlv_header; + __le32 vdev_id; +@@ -3999,6 +4009,20 @@ struct wmi_rate_set_arg { + u8 rates[WMI_MAX_SUPPORTED_RATES]; + }; + ++struct peer_assoc_mlo_params { ++ bool enabled; ++ bool assoc_link; ++ bool primary_umac; ++ bool peer_id_valid; ++ bool logical_link_idx_valid; ++ u8 mld_addr[ETH_ALEN]; ++ u32 logical_link_idx; ++ u32 ml_peer_id; ++ u32 ieee_link_id; ++ u8 num_partner_links; ++ struct wmi_ml_partner_info partner_info[ATH12K_WMI_MLO_MAX_LINKS]; ++}; ++ + struct peer_assoc_params { + struct wmi_mac_addr peer_macaddr; + u32 vdev_id; +@@ -4071,8 +4095,29 @@ struct peer_assoc_params { + struct ath12k_ppe_threshold peer_eht_ppet; + u32 ru_punct_bitmap; + bool is_assoc; ++ struct peer_assoc_mlo_params ml; + }; + ++struct wmi_peer_assoc_mlo_partner_info { ++ u32 tlv_header; ++ u32 vdev_id; ++ u32 hw_link_id; ++ u32 flags; ++ u32 logical_link_idx; ++} __packed; ++ ++struct wmi_peer_assoc_mlo_params { ++ u32 tlv_header; ++ u32 flags; ++ struct wmi_mac_addr mld_addr; ++ u32 logical_link_idx; ++ u32 ml_peer_id; ++ u32 ieee_link_id; ++ u32 emlsr_trans_timeout_us; ++ u32 emlsr_trans_delay_us; ++ u32 emlsr_padding_delay_us; ++} __packed; ++ + struct wmi_peer_assoc_complete_cmd { + __le32 tlv_header; + struct wmi_mac_addr peer_macaddr; diff --git a/feeds/ipq95xx/mac80211/patches/qca/676-04-ath12k-setup-ML-reo-queue-LUT.patch b/feeds/ipq95xx/mac80211/patches/qca/676-04-ath12k-setup-ML-reo-queue-LUT.patch new file mode 100644 index 000000000..6ecc4f4ec --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/676-04-ath12k-setup-ML-reo-queue-LUT.patch @@ -0,0 +1,204 @@ +From 34cc01f22ff045e55499263f7e36b2c3330d6228 Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Sat, 12 Nov 2022 18:14:16 +0530 +Subject: [PATCH] ath12k: setup ML reo queue LUT + +Setup the ML reo queue look up table for handling +data from ML peers. The ML peer id created by the host +is used for managing this table. +Note that only the ML reoq is setup for ML peer and the +non ML LUT for the link peers is not required. + +Signed-off-by: Sriram R +--- + drivers/net/wireless/ath/ath12k/dp.c | 31 ++++++++++++++--- + drivers/net/wireless/ath/ath12k/dp.h | 1 + + drivers/net/wireless/ath/ath12k/dp_rx.c | 44 ++++++++++++++++--------- + drivers/net/wireless/ath/ath12k/peer.c | 2 ++ + drivers/net/wireless/ath/ath12k/peer.h | 1 + + 5 files changed, 59 insertions(+), 20 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -1257,12 +1257,19 @@ static void ath12k_dp_reoq_lut_cleanup(s + if (!dp->reoq_lut.vaddr) + return; + +- dma_free_coherent(ab->dev, DP_REOQ_LUT_SIZE, +- dp->reoq_lut.vaddr, dp->reoq_lut.paddr); +- dp->reoq_lut.vaddr = NULL; ++ if (dp->reoq_lut.vaddr) { ++ ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_LUT_BASE0(ab), 0); ++ dma_free_coherent(ab->dev, DP_REOQ_LUT_SIZE, ++ dp->reoq_lut.vaddr, dp->reoq_lut.paddr); ++ dp->reoq_lut.vaddr = NULL; ++ } + +- ath12k_hif_write32(ab, +- HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_LUT_BASE0(ab), 0); ++ if (dp->ml_reoq_lut.vaddr) { ++ ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_LUT_BASE1(ab), 0); ++ dma_free_coherent(ab->dev, DP_REOQ_LUT_SIZE, ++ dp->ml_reoq_lut.vaddr, dp->ml_reoq_lut.paddr); ++ dp->ml_reoq_lut.vaddr = NULL; ++ } + } + + void ath12k_dp_free(struct ath12k_base *ab) +@@ -1526,11 +1533,30 @@ static int ath12k_dp_reoq_lut_setup(stru + return -ENOMEM; + } + ++ dp->ml_reoq_lut.vaddr = dma_alloc_coherent(ab->dev, ++ DP_REOQ_LUT_SIZE, ++ &dp->ml_reoq_lut.paddr, ++ GFP_KERNEL); ++ ++ if (!dp->ml_reoq_lut.vaddr) { ++ ath12k_warn(ab, "failed to allocate memory for ML reoq table"); ++ ++ /* cleanup non-ML REOQ LUT allocated above */ ++ dma_free_coherent(ab->dev, DP_REOQ_LUT_SIZE, ++ dp->reoq_lut.vaddr, dp->reoq_lut.paddr); ++ dp->reoq_lut.vaddr = NULL; ++ return -ENOMEM; ++ } ++ + memset(dp->reoq_lut.vaddr, 0, DP_REOQ_LUT_SIZE); ++ memset(dp->ml_reoq_lut.vaddr, 0, DP_REOQ_LUT_SIZE); + + ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_LUT_BASE0(ab), + dp->reoq_lut.paddr >> 8); + ++ ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_LUT_BASE1(ab), ++ dp->ml_reoq_lut.paddr >> 8); ++ + val = ath12k_hif_read32(ab, + HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_ADDR_READ(ab)); + +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -359,6 +359,7 @@ struct ath12k_dp { + struct dp_rxdma_ring rxdma_mon_buf_ring; + struct dp_rxdma_ring tx_mon_buf_ring; + struct ath12k_reo_q_addr_lut reoq_lut; ++ struct ath12k_reo_q_addr_lut ml_reoq_lut; + }; + + /* HTT definitions */ +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -807,15 +807,22 @@ static void ath12k_peer_rx_tid_qref_setu + { + struct ath12k_reo_queue_ref *qref; + struct ath12k_dp *dp = &ab->dp; ++ bool ml_peer = false; + + if (!ab->hw_params->reoq_lut_support) + return; + +- /* TODO: based on ML peer or not, select the LUT. below assumes non +- * ML peer +- */ +- qref = (struct ath12k_reo_queue_ref *)dp->reoq_lut.vaddr + +- (peer_id * (IEEE80211_NUM_TIDS + 1) + tid); ++ if (peer_id & ATH12K_ML_PEER_ID_VALID) { ++ peer_id &= ~ATH12K_ML_PEER_ID_VALID; ++ ml_peer = true; ++ } ++ ++ if (ml_peer) ++ qref = (struct ath12k_reo_queue_ref *)dp->ml_reoq_lut.vaddr + ++ (peer_id * (IEEE80211_NUM_TIDS + 1) + tid); ++ else ++ qref = (struct ath12k_reo_queue_ref *)dp->reoq_lut.vaddr + ++ (peer_id * (IEEE80211_NUM_TIDS + 1) + tid); + + qref->info0 = u32_encode_bits(lower_32_bits(paddr), + BUFFER_ADDR_INFO0_ADDR); +@@ -828,15 +835,22 @@ static void ath12k_peer_rx_tid_qref_rese + { + struct ath12k_reo_queue_ref *qref; + struct ath12k_dp *dp = &ab->dp; ++ bool ml_peer = false; + + if (!ab->hw_params->reoq_lut_support) + return; + +- /* TODO: based on ML peer or not, select the LUT. below assumes non +- * ML peer +- */ +- qref = (struct ath12k_reo_queue_ref *)dp->reoq_lut.vaddr + +- (peer_id * (IEEE80211_NUM_TIDS + 1) + tid); ++ if (peer_id & ATH12K_ML_PEER_ID_VALID) { ++ peer_id &= ~ATH12K_ML_PEER_ID_VALID; ++ ml_peer = true; ++ } ++ ++ if (ml_peer) ++ qref = (struct ath12k_reo_queue_ref *)dp->ml_reoq_lut.vaddr + ++ (peer_id * (IEEE80211_NUM_TIDS + 1) + tid); ++ else ++ qref = (struct ath12k_reo_queue_ref *)dp->reoq_lut.vaddr + ++ (peer_id * (IEEE80211_NUM_TIDS + 1) + tid); + + qref->info0 = u32_encode_bits(0, BUFFER_ADDR_INFO0_ADDR); + qref->info1 = u32_encode_bits(0, BUFFER_ADDR_INFO1_ADDR) | +@@ -869,7 +883,11 @@ void ath12k_dp_rx_peer_tid_delete(struct + kfree(rx_tid->vaddr); + } + +- ath12k_peer_rx_tid_qref_reset(ar->ab, peer->peer_id, tid); ++ if (peer->mlo) ++ ath12k_peer_rx_tid_qref_reset(ar->ab, peer->ml_peer_id, tid); ++ else ++ ath12k_peer_rx_tid_qref_reset(ar->ab, peer->peer_id, tid); ++ + rx_tid->vaddr = NULL; + rx_tid->paddr = 0; + rx_tid->size = 0; +@@ -1008,7 +1026,7 @@ int ath12k_dp_rx_peer_tid_setup(struct a + return 0; + } + +- if (ab->hw_params->reoq_lut_support && !dp->reoq_lut.vaddr) { ++ if (ab->hw_params->reoq_lut_support && (!dp->reoq_lut.vaddr || !dp->ml_reoq_lut.vaddr)) { + spin_unlock_bh(&ab->base_lock); + ath12k_warn(ab, "reo qref table is not setup\n"); + return -EINVAL; +@@ -1080,7 +1098,10 @@ int ath12k_dp_rx_peer_tid_setup(struct a + /* Update the REO queue LUT at the corresponding peer id + * and tid with qaddr. + */ +- ath12k_peer_rx_tid_qref_setup(ab, peer->peer_id, tid, paddr); ++ if (peer->mlo) ++ ath12k_peer_rx_tid_qref_setup(ab, peer->ml_peer_id, tid, paddr); ++ else ++ ath12k_peer_rx_tid_qref_setup(ab, peer->peer_id, tid, paddr); + spin_unlock_bh(&ab->base_lock); + } else { + spin_unlock_bh(&ab->base_lock); +--- a/drivers/net/wireless/ath/ath12k/peer.c ++++ b/drivers/net/wireless/ath/ath12k/peer.c +@@ -505,9 +505,11 @@ int ath12k_peer_create(struct ath12k *ar + /* the assoc link is considered primary for now */ + peer->primary_link = arsta->is_assoc_link; + ether_addr_copy(peer->ml_addr, sta->addr); ++ peer->mlo = true; + } else { + peer->ml_peer_id = ATH12K_MLO_PEER_ID_INVALID; + peer->primary_link = true; ++ peer->mlo = false; + } + + } +--- a/drivers/net/wireless/ath/ath12k/peer.h ++++ b/drivers/net/wireless/ath/ath12k/peer.h +@@ -64,6 +64,7 @@ struct ath12k_peer { + */ + bool dp_setup_done; + ++ bool mlo; + u16 ml_peer_id; + /* TODO remove or fill below these info if required/not required during dp change */ + /* for reference to ath12k_link_sta */ diff --git a/feeds/ipq95xx/mac80211/patches/qca/676-05-ath12k-set-idle-link-desc-buf-manager-based-on-chip.patch b/feeds/ipq95xx/mac80211/patches/qca/676-05-ath12k-set-idle-link-desc-buf-manager-based-on-chip.patch new file mode 100644 index 000000000..c1ae09f6f --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/676-05-ath12k-set-idle-link-desc-buf-manager-based-on-chip.patch @@ -0,0 +1,155 @@ +From aa5bb11f1e8bdea88d56b7ce755c507aa0024ed9 Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Sat, 12 Nov 2022 18:15:25 +0530 +Subject: [PATCH] ath12k: set idle link desc buf manager based on chip + +Currently the idle link desc buffer manager value +is always set to chip0 idle desc list. Configure this +appropriately based on the chip id. + +Signed-off-by: Karthikeyan Periyasamy +Signed-off-by: Sriram R +--- + drivers/net/wireless/ath/ath12k/dp.c | 10 ++++++++-- + drivers/net/wireless/ath/ath12k/dp.h | 1 + + drivers/net/wireless/ath/ath12k/dp_rx.c | 4 ++-- + drivers/net/wireless/ath/ath12k/hal.c | 4 ++-- + drivers/net/wireless/ath/ath12k/hal.h | 4 ++-- + 5 files changed, 15 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c +index 152a0f0..5254b9e 100644 +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -659,6 +659,7 @@ static int ath12k_dp_scatter_idle_link_desc_setup(struct ath12k_base *ab, + int i; + int ret = 0; + u32 end_offset, cookie; ++ u8 rbm_id; + + n_entries_per_buf = HAL_WBM_IDLE_SCATTER_BUF_SIZE / + ath12k_hal_srng_get_entrysize(ab, HAL_WBM_IDLE_LINK); +@@ -680,6 +681,7 @@ static int ath12k_dp_scatter_idle_link_desc_setup(struct ath12k_base *ab, + scatter_idx = 0; + scatter_buf = slist[scatter_idx].vaddr; + rem_entries = n_entries_per_buf; ++ rbm_id = dp->idle_link_rbm_id; + + for (i = 0; i < n_link_desc_bank; i++) { + align_bytes = link_desc_banks[i].vaddr - +@@ -689,7 +691,8 @@ static int ath12k_dp_scatter_idle_link_desc_setup(struct ath12k_base *ab, + paddr = link_desc_banks[i].paddr; + while (n_entries) { + cookie = DP_LINK_DESC_COOKIE_SET(n_entries, i); +- ath12k_hal_set_link_desc_addr(scatter_buf, cookie, paddr); ++ ath12k_hal_set_link_desc_addr(scatter_buf, cookie, ++ paddr, rbm_id); + n_entries--; + paddr += HAL_LINK_DESC_SIZE; + if (rem_entries) { +@@ -830,6 +833,7 @@ int ath12k_dp_link_desc_setup(struct ath12k_base *ab, + u32 *desc; + int i, ret; + u32 cookie; ++ u8 rbm_id; + + tot_mem_sz = n_link_desc * HAL_LINK_DESC_SIZE; + tot_mem_sz += HAL_LINK_DESC_ALIGN; +@@ -860,6 +864,7 @@ int ath12k_dp_link_desc_setup(struct ath12k_base *ab, + /* Setup link desc idle list for HW internal usage */ + entry_sz = ath12k_hal_srng_get_entrysize(ab, ring_type); + tot_mem_sz = entry_sz * n_link_desc; ++ rbm_id = ab->dp.idle_link_rbm_id; + + /* Setup scatter desc list when the total memory requirement is more */ + if (tot_mem_sz > DP_LINK_DESC_ALLOC_SIZE_THRESH) { +@@ -890,7 +895,7 @@ int ath12k_dp_link_desc_setup(struct ath12k_base *ab, + (desc = ath12k_hal_srng_src_get_next_entry(ab, srng))) { + cookie = DP_LINK_DESC_COOKIE_SET(n_entries, i); + ath12k_hal_set_link_desc_addr((struct hal_wbm_link_desc *)desc, +- cookie, paddr); ++ cookie, paddr, rbm_id); + n_entries--; + paddr += HAL_LINK_DESC_SIZE; + } +@@ -1580,6 +1585,7 @@ int ath12k_dp_alloc(struct ath12k_base *ab) + spin_lock_init(&dp->reo_cmd_lock); + + dp->reo_cmd_cache_flush_count = 0; ++ dp->idle_link_rbm_id = HAL_RX_BUF_RBM_WBM_CHIP0_IDLE_DESC_LIST + ab->chip_id; + + ret = ath12k_wbm_idle_ring_setup(ab, &n_link_desc); + if (ret) { +diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h +index c0ff609..861b4ca 100644 +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -315,6 +315,7 @@ struct ath12k_dp { + u8 htt_tgt_ver_major; + u8 htt_tgt_ver_minor; + struct dp_link_desc_bank link_desc_banks[DP_LINK_DESC_BANKS_MAX]; ++ u8 idle_link_rbm_id; + struct dp_srng wbm_idle_ring; + struct dp_srng wbm_desc_rel_ring; + struct dp_srng tcl_cmd_ring; +diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c +index a99f5aa..7d6a139 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -3560,7 +3560,7 @@ static int ath12k_dp_rx_h_defrag_reo_reinject(struct ath12k *ar, + memset(reo_ent_ring, 0, sizeof(*reo_ent_ring)); + + ath12k_hal_rx_buf_addr_info_set(reo_ent_ring, link_paddr, cookie, +- HAL_RX_BUF_RBM_WBM_CHIP0_IDLE_DESC_LIST); ++ dp->idle_link_rbm_id); + + mpdu_info = u32_encode_bits(1, RX_MPDU_DESC_INFO0_MSDU_COUNT) | + u32_encode_bits(0, RX_MPDU_DESC_INFO0_FRAG_FLAG) | +@@ -3931,7 +3931,7 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi, + (paddr - link_desc_banks[desc_bank].paddr); + ath12k_hal_rx_msdu_link_info_get(link_desc_va, &num_msdus, msdu_cookies, + &rbm); +- if (rbm != HAL_RX_BUF_RBM_WBM_CHIP0_IDLE_DESC_LIST && ++ if (rbm != dp->idle_link_rbm_id && + rbm != HAL_RX_BUF_RBM_SW3_BM && + rbm != ab->hw_params->hal_params->rx_buf_rbm) { + ab->soc_stats.invalid_rbm++; +diff --git a/drivers/net/wireless/ath/ath12k/hal.c b/drivers/net/wireless/ath/ath12k/hal.c +index dd638f3..dbc5d87 100644 +--- a/drivers/net/wireless/ath/ath12k/hal.c ++++ b/drivers/net/wireless/ath/ath12k/hal.c +@@ -1548,14 +1548,14 @@ u32 ath12k_hal_ce_dst_status_get_length(void *buf) + } + + void ath12k_hal_set_link_desc_addr(struct hal_wbm_link_desc *desc, u32 cookie, +- dma_addr_t paddr) ++ dma_addr_t paddr, u8 rbm_id) + { + desc->buf_addr_info.info0 = u32_encode_bits((paddr & HAL_ADDR_LSB_REG_MASK), + BUFFER_ADDR_INFO0_ADDR); + desc->buf_addr_info.info1 = + u32_encode_bits(((u64)paddr >> HAL_ADDR_MSB_REG_SHIFT), + BUFFER_ADDR_INFO1_ADDR) | +- u32_encode_bits(1, BUFFER_ADDR_INFO1_RET_BUF_MGR) | ++ u32_encode_bits(rbm_id, BUFFER_ADDR_INFO1_RET_BUF_MGR) | + u32_encode_bits(cookie, BUFFER_ADDR_INFO1_SW_COOKIE); + } + +diff --git a/drivers/net/wireless/ath/ath12k/hal.h b/drivers/net/wireless/ath/ath12k/hal.h +index 498be29..7cfef2e 100644 +--- a/drivers/net/wireless/ath/ath12k/hal.h ++++ b/drivers/net/wireless/ath/ath12k/hal.h +@@ -1121,8 +1121,8 @@ dma_addr_t ath12k_hal_srng_get_tp_addr(struct ath12k_base *ab, + struct hal_srng *srng); + dma_addr_t ath12k_hal_srng_get_hp_addr(struct ath12k_base *ab, + struct hal_srng *srng); +-void ath12k_hal_set_link_desc_addr(struct hal_wbm_link_desc *desc, u32 cookie, +- dma_addr_t paddr); ++void ath12k_hal_set_link_desc_addr(struct hal_wbm_link_desc *desc, ++ u32 cookie, dma_addr_t paddr, u8 rbm_id); + u32 ath12k_hal_ce_get_desc_size(enum hal_ce_desc type); + void ath12k_hal_ce_src_set_desc(void *buf, dma_addr_t paddr, u32 len, u32 id, + u8 byte_swap_data); +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/676-06-ath12k-perform-Tx-address-translation.patch b/feeds/ipq95xx/mac80211/patches/qca/676-06-ath12k-perform-Tx-address-translation.patch new file mode 100644 index 000000000..7bfe8aab4 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/676-06-ath12k-perform-Tx-address-translation.patch @@ -0,0 +1,155 @@ +From f4b2d84b5ab4820d2a66b388c2c17c2a755af010 Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Sat, 5 Nov 2022 13:14:14 +0530 +Subject: [PATCH] ath12k: perform Tx address translation + +When the link id is mentioned in the tx control info, +use it to convert the RA/TA to the corresponding +link sta and link vif address before transmission. + +For eth data frames, always enqueue the frame on the +primary link/umac. + +TODO: nwifi/raw data frame handling + +Signed-off-by: Sriram R +--- + drivers/net/wireless/ath/ath12k/mac.c | 64 +++++++++++++++++++++++++++ + 1 file changed, 64 insertions(+) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -7723,6 +7723,75 @@ static int ath12k_mac_mgmt_tx(struct ath + return 0; + } + ++static u8 ath12k_mac_get_tx_link(struct ieee80211_sta *sta, struct ieee80211_vif *vif, ++ u8 link, struct sk_buff *skb, u32 info_flags) ++{ ++ struct ath12k_sta *ahsta; ++ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); ++ struct ieee80211_link_sta *link_sta; ++ struct ieee80211_bss_conf *bss_conf; ++ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; ++ ++ /* Use the link id passed or the default vif link */ ++ if (!sta) { ++ if (link != IEEE80211_LINK_UNSPECIFIED) ++ return link; ++ ++ return ahvif->deflink.link_id; ++ } ++ ++ ahsta = (struct ath12k_sta *)sta->drv_priv; ++ ++ /* use default */ ++ if (!sta->mlo) ++ return ahsta->deflink.link_id; ++ ++ /* enqueue eth data frames on assoc link */ ++ if (info_flags & IEEE80211_TX_CTL_HW_80211_ENCAP) ++ return ahsta->assoc_link_id; ++ ++ /* 802.11 frame cases */ ++ if (link == IEEE80211_LINK_UNSPECIFIED) ++ link = ahsta->deflink.link_id; ++ ++ /* Perform address conversion for ML STA Tx */ ++ bss_conf = rcu_dereference(vif->link_conf[link]); ++ link_sta = rcu_dereference(sta->link[link]); ++ if (bss_conf && link_sta) { ++ ether_addr_copy(hdr->addr1, link_sta->addr); ++ ether_addr_copy(hdr->addr2, bss_conf->addr); ++ } else if (bss_conf) { ++ /* In certain cases where a ML sta associated and added subset of links ++ * on which the ML AP is active, but now sends some frame (ex Probe request) ++ * on a different link which is active in our MLD but was not added during ++ * previous association, we can still honor the Tx to that ML STA via the ++ * requested link. ++ * The control would reach here in such case only when that link address ++ * is same as the MLD address or in worst case clients used MLD address at TA wrongly ++ * which would have helped identify the ML sta object and pass it here. ++ * If the link address of that STA is different from MLD address, then ++ * the sta object would be NULL and control wont reach here but return at the ++ * start of the function itself with !sta check. Also this would not need any ++ * translation at hdr->addr1 from MLD to link address since the RA is the ++ * MLD address (same as that link address ideally) already. ++ */ ++ ether_addr_copy(hdr->addr2, bss_conf->addr); ++ ++ ath12k_dbg(NULL, ATH12K_DBG_MAC, ++ "unable to determine link sta addr for translation - Frame control %x link %d sta links %x ahsta links %x\n", ++ hdr->frame_control, link, sta->valid_links, ahsta->links_map); ++ } else { ++ ath12k_err(NULL, "unable to determine Tx link for frame %x link %d\n vif links %x sta links %x ahvif links %x ahsta links %x", ++ hdr->frame_control, link, vif->valid_links, ++ sta->valid_links, ahvif->links_map, ahsta->links_map); ++ link = IEEE80211_MLD_MAX_NUM_LINKS; ++ } ++ ++ /* todo nwifi/raw data frames */ ++ return link; ++ ++} ++ + static void ath12k_mac_op_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) +@@ -7731,10 +7800,9 @@ static void ath12k_mac_op_tx(struct ieee + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_vif *vif = info->control.vif; + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); +- /* TODO extend link specific */ +- struct ath12k_link_vif *arvif = &ahvif->deflink; +- struct ath12k *ar = arvif->ar; +- struct ath12k_hw *ah = ar->ah; ++ struct ath12k_link_vif *arvif; ++ struct ath12k *ar; ++ struct ath12k_hw *ah; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_key_conf *key = info->control.hw_key; + struct ath12k_mgmt_frame_stats *mgmt_stats = &ahvif->mgmt_stats; +@@ -7745,20 +7813,39 @@ static void ath12k_mac_op_tx(struct ieee + bool is_prb_rsp; + u16 frm_type = 0; + int ret; ++ u8 link = u32_get_bits(info->control.flags, IEEE80211_TX_CTRL_MLO_LINK); + + if (ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { +- ieee80211_free_txskb(ah->hw, skb); ++ ieee80211_free_txskb(hw, skb); + return; + } + ++ memset(skb_cb, 0, sizeof(*skb_cb)); ++ skb_cb->vif = vif; ++ ++ /* handle only for MLO case, use deflink for non MLO case */ ++ if (vif->valid_links) { ++ link = ath12k_mac_get_tx_link(sta, vif, link, skb, info_flags); ++ ++ if (link >= IEEE80211_MLD_MAX_NUM_LINKS) { ++ ieee80211_free_txskb(hw, skb); ++ return; ++ } ++ if (WARN_ON(!ahvif->link[link])) { ++ ieee80211_free_txskb(hw, skb); ++ return; ++ } ++ arvif = ahvif->link[link]; ++ ar = arvif->ar; ++ } ++ ++ ah = ar->ah; ++ + if (unlikely(test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))) { + ieee80211_free_txskb(ar->ah->hw, skb); + return; + } + +- memset(skb_cb, 0, sizeof(*skb_cb)); +- skb_cb->vif = vif; +- + if (key) { + skb_cb->cipher = key->cipher; + skb_cb->flags |= ATH12K_SKB_CIPHER_SET; diff --git a/feeds/ipq95xx/mac80211/patches/qca/676-ath12k-enable-qdss-config.patch b/feeds/ipq95xx/mac80211/patches/qca/676-ath12k-enable-qdss-config.patch new file mode 100644 index 000000000..301c30cfa --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/676-ath12k-enable-qdss-config.patch @@ -0,0 +1,248 @@ +From 165ac2ffd9343e9f30fe5be7e75f228c2e79db88 Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Fri, 11 Nov 2022 08:33:34 +0530 +Subject: [PATCH] ath12k: enable qdss config + +QDSS config should be enabled by default. + +Signed-off-by: Harshitha Prem +--- + drivers/net/wireless/ath/ath12k/coredump.c | 74 +++++++++++----------- + drivers/net/wireless/ath/ath12k/coredump.h | 1 + + drivers/net/wireless/ath/ath12k/hw.c | 9 --- + drivers/net/wireless/ath/ath12k/hw.h | 3 - + drivers/net/wireless/ath/ath12k/qmi.c | 36 +++++------ + 5 files changed, 55 insertions(+), 68 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/coredump.c ++++ b/drivers/net/wireless/ath/ath12k/coredump.c +@@ -146,6 +146,36 @@ void ath12k_coredump_build_inline(struct + vfree(file_data); + } + ++static enum ath12k_fw_crash_dump_type ++ath12k_coredump_get_dump_type(u32 mem_region_type) ++{ ++ enum ath12k_fw_crash_dump_type dump_type; ++ ++ /* note: only add the supported memory type, ++ which is used to calculate the rem_seg_cnt */ ++ switch(mem_region_type) { ++ case HOST_DDR_REGION_TYPE: ++ dump_type = ATH12K_FW_REMOTE_MEM_DATA; ++ break; ++ case CALDB_MEM_REGION_TYPE: ++ dump_type = ATH12K_FW_CALDB; ++ break; ++ case M3_DUMP_REGION_TYPE: ++ dump_type = ATH12K_FW_M3_DUMP; ++ break; ++ case PAGEABLE_MEM_REGION_TYPE: ++ dump_type = ATH12K_FW_PAGEABLE_DATA; ++ break; ++ case MLO_GLOBAL_MEM_REGION_TYPE: ++ dump_type = ATH12K_FW_MLO_GLOBAL; ++ break; ++ default: ++ dump_type = ATH12K_FW_DUMP_TYPE_MAX; ++ break; ++ } ++ ++ return dump_type; ++} + void ath12k_coredump_download_rddm(struct ath12k_base *ab) + { + struct ath12k_pci *ar_pci = (struct ath12k_pci *)ab->drv_priv; +@@ -154,6 +184,7 @@ void ath12k_coredump_download_rddm(struc + struct ath12k_dump_segment *segment, *seg_info; + int i, rem_seg_cnt = 0, len, num_seg, seg_sz, qdss_seg_cnt = 1; + int skip_count = 0; ++ enum ath12k_fw_crash_dump_type mem_type; + + ath12k_mhi_coredump(mhi_ctrl, false); + +@@ -208,51 +239,31 @@ void ath12k_coredump_download_rddm(struc + } + + for (i = 0; i < ab->qmi.mem_seg_count; i++) { +- if (ab->qmi.target_mem[i].type == CALDB_MEM_REGION_TYPE) { +- if (ath12k_cold_boot_cal && +- ab->hw_params->cold_boot_calib) { +- seg_info->len = ab->qmi.target_mem[i].size; +- seg_info->addr = ab->qmi.target_mem[i].paddr; +- seg_info->vaddr = ab->qmi.target_mem[i].v.ioaddr; +- seg_info->type = ATH12K_FW_CALDB; +- ath12k_info(ab, +- "seg vaddr is %px len is 0x%x type %d\n", +- seg_info->vaddr, +- seg_info->len, +- seg_info->type); +- seg_info++; +- } ++ mem_type = ath12k_coredump_get_dump_type(ab->qmi.target_mem[i].type); ++ if(mem_type == ATH12K_FW_DUMP_TYPE_MAX) { ++ ath12k_info(ab, "target mem region type %d not supported", ab->qmi.target_mem[i].type); + continue; + } + +- if (ab->qmi.target_mem[i].type == MLO_GLOBAL_MEM_REGION_TYPE) { +- seg_info->len = ab->qmi.target_mem[i].size; +- seg_info->addr = ab->qmi.target_mem[i].paddr; +- seg_info->vaddr = ab->qmi.target_mem[i].v.ioaddr; +- seg_info->type = ATH12K_FW_MLO_GLOBAL; +- seg_info++; ++ if (mem_type == ATH12K_FW_CALDB && ++ !(ath12k_cold_boot_cal && ab->hw_params->cold_boot_calib)) + continue; +- } +- if (ab->qmi.target_mem[i].type == PAGEABLE_MEM_REGION_TYPE) { +- seg_info->len = ab->qmi.target_mem[i].size; +- seg_info->addr = ab->qmi.target_mem[i].paddr; +- seg_info->vaddr = ab->qmi.target_mem[i].v.ioaddr; +- seg_info->type = ATH12K_FW_PAGEABLE_DATA; +- seg_info++; +- continue; +- } +- if (ab->qmi.target_mem[i].type == M3_DUMP_REGION_TYPE) { +- seg_info->len = ab->qmi.target_mem[i].size; +- seg_info->addr = ab->qmi.target_mem[i].paddr; +- seg_info->vaddr = ab->qmi.target_mem[i].v.ioaddr; +- seg_info->type = ATH12K_FW_M3_DUMP; +- seg_info++; ++ ++ if (!ab->qmi.target_mem[i].paddr) { ++ skip_count++; ++ ath12k_info(ab, "Skipping mem region type %d", ab->qmi.target_mem[i].type); + continue; + } ++ + seg_info->len = ab->qmi.target_mem[i].size; + seg_info->addr = ab->qmi.target_mem[i].paddr; +- seg_info->vaddr = ab->qmi.target_mem[i].v.addr; +- seg_info->type = ATH12K_FW_REMOTE_MEM_DATA; ++ seg_info->vaddr = ab->qmi.target_mem[i].v.ioaddr; ++ seg_info->type = mem_type; ++ ath12k_info(ab, ++ "seg vaddr is %px len is 0x%x type %d\n", ++ seg_info->vaddr, ++ seg_info->len, ++ seg_info->type); + seg_info++; + } + +--- a/drivers/net/wireless/ath/ath12k/coredump.h ++++ b/drivers/net/wireless/ath/ath12k/coredump.h +@@ -19,6 +19,9 @@ enum ath12k_fw_crash_dump_type { + ATH12K_FW_CALDB, + ATH12K_FW_AFC, + ATH12K_FW_MLO_GLOBAL, ++ ++ /* keep last */ ++ ATH12K_FW_DUMP_TYPE_MAX, + }; + + struct ath12k_dump_segment { +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -1007,9 +1007,6 @@ static const struct ath12k_hw_params ath + + .hal_ops = &hal_qcn9274_ops, + +- .qdss_config = NULL, +- .qdss_config_len = 0, +- + .fix_l1ss = false, + + .supports_ap_ps = true, +@@ -1075,9 +1072,6 @@ static const struct ath12k_hw_params ath + + .hal_ops = &hal_wcn7850_ops, + +- .qdss_config = ath12k_hw_qdss_config_wcn7850, +- .qdss_config_len = sizeof(ath12k_hw_qdss_config_wcn7850), +- + .fix_l1ss = false, + + .supports_ap_ps = true, +@@ -1143,9 +1137,6 @@ static const struct ath12k_hw_params ath + + .hal_ops = &hal_qcn9274_ops, + +- .qdss_config = NULL, +- .qdss_config_len = 0, +- + .fix_l1ss = false, + + .supports_ap_ps = true, +--- a/drivers/net/wireless/ath/ath12k/hw.h ++++ b/drivers/net/wireless/ath/ath12k/hw.h +@@ -195,9 +195,6 @@ struct ath12k_hw_params { + + const struct hal_ops *hal_ops; + +- const char *qdss_config; +- unsigned int qdss_config_len; +- + bool fix_l1ss; + + bool supports_ap_ps; +--- a/drivers/net/wireless/ath/ath12k/qmi.c ++++ b/drivers/net/wireless/ath/ath12k/qmi.c +@@ -2735,26 +2735,31 @@ out: + + static int ath12k_qmi_send_qdss_config(struct ath12k_base *ab) + { +- unsigned int config_len; +- const char *config; ++ struct device *dev = ab->dev; ++ const struct firmware *fw_entry; ++ char filename[ATH12K_QMI_MAX_QDSS_CONFIG_FILE_NAME_SIZE]; + int ret; + +- config = ab->hw_params->qdss_config; +- if (!config) +- /* this hw doesn't need qdss config */ +- return 0; ++ snprintf(filename, sizeof(filename), ++ "%s/%s/%s", ATH12K_FW_DIR, ab->hw_params->fw.dir, ++ ATH12K_QMI_DEFAULT_QDSS_CONFIG_FILE_NAME); ++ ret = request_firmware(&fw_entry, filename, dev); + +- config_len = ab->hw_params->qdss_config_len; ++ if (ret) { ++ ath12k_warn(ab, "qmi failed to load QDSS config: %s\n", filename); ++ return ret; ++ } + +- ret = ath12k_qmi_send_qdss_trace_config_download_req(ab, +- config, +- config_len); ++ ret = ath12k_qmi_send_qdss_trace_config_download_req(ab, fw_entry->data, ++ fw_entry->size); + if (ret < 0) { + ath12k_warn(ab, "qmi failed to load QDSS config to FW: %d\n", ret); +- return ret; ++ goto out; + } ++out: ++ release_firmware(fw_entry); ++ return ret; + +- return 0; + } + + static int ath12k_qmi_fill_mlo_host_caps(struct ath12k_base *ab, +@@ -4440,13 +4445,6 @@ static int ath12k_qmi_event_load_bdf(str + return ret; + } + +- /* TODO: QDSS should be removed after WCN7850 firmware is fixed */ +- ret = ath12k_qmi_send_qdss_config(ab); +- if (ret < 0) { +- ath12k_warn(ab, "Failed to download QDSS config to FW: %d\n", ret); +- return ret; +- } +- + return ret; + } + diff --git a/feeds/ipq95xx/mac80211/patches/qca/676-e-mac80211-Deliver-the-frame-to-driver-tx-ops-directly.patch b/feeds/ipq95xx/mac80211/patches/qca/676-e-mac80211-Deliver-the-frame-to-driver-tx-ops-directly.patch deleted file mode 100644 index 70901a406..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/676-e-mac80211-Deliver-the-frame-to-driver-tx-ops-directly.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0400a5c33fdbee60fbad83e78269696ad2af7eec Mon Sep 17 00:00:00 2001 -From: Balamurugan Mahalingam -Date: Sat, 15 Oct 2022 01:00:51 -0700 -Subject: [PATCH 5/7] mac80211: Deliver the frame to driver tx ops directly - -Deliver the frame to driver directly in the forwarding path -to improve the throughput performance. - -Reset the fast xmit flag in ieee80211 datapath to ensure -other features handled as normal through the ath12k_dp_tx -function - -Signed-off-by: Balamurugan Mahalingam ---- - net/mac80211/tx.c | 13 ++++++++++++- - 1 file changed, 12 insertions(+), 1 deletion(-) - -diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c -index a02ee4d..400fab8 100644 ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -4580,6 +4580,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, - #ifdef CPTCFG_MAC80211_NSS_SUPPORT - ieee80211_xmit_nss_fixup(skb, dev); - #endif -+ skb->fast_xmit = 0; - - if (unlikely(ieee80211_multicast_to_unicast(skb, dev))) { - struct sk_buff_head queue; -@@ -4797,7 +4798,17 @@ void ieee80211_8023_xmit_ap(struct ieee80211_sub_if_data *sdata, - netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb, - struct net_device *dev) - { -- return __ieee80211_subif_start_xmit_8023(skb, dev, 0, 0, NULL); -+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); -+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); -+ -+ info->control.vif = &sdata->vif; -+ -+ if (skb->fast_xmit) { -+ drv_tx(sdata->local, NULL, skb); -+ return NETDEV_TX_OK; -+ } else { -+ return __ieee80211_subif_start_xmit_8023(skb, dev, 0, 0, NULL); -+ } - } - - netdev_tx_t __ieee80211_subif_start_xmit_8023(struct sk_buff *skb, --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/677-01-wifi-cfg80211-get-correct-AP-link-chandef.patch b/feeds/ipq95xx/mac80211/patches/qca/677-01-wifi-cfg80211-get-correct-AP-link-chandef.patch new file mode 100644 index 000000000..852de9114 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/677-01-wifi-cfg80211-get-correct-AP-link-chandef.patch @@ -0,0 +1,33 @@ +From 6de876eb9bd0fe64e444cf4ebd183976bb1c1b35 Mon Sep 17 00:00:00 2001 +From: Shaul Triebitz +Date: Mon, 1 Aug 2022 14:12:29 +0300 +Subject: [PATCH] wifi: cfg80211: get correct AP link chandef + +When checking for channel regulatory validity, use the +AP link chandef (and not mesh's chandef). + +Fixes: 7b0a0e3c3a88 ("wifi: cfg80211: do some rework towards MLO link APIs") +Signed-off-by: Shaul Triebitz +Signed-off-by: Johannes Berg +--- + net/wireless/reg.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/wireless/reg.c b/net/wireless/reg.c +index 6a14068..9a897fa 100644 +--- a/net/wireless/reg.c ++++ b/net/wireless/reg.c +@@ -2411,6 +2411,10 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev) + switch (iftype) { + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_P2P_GO: ++ if (!wdev->links[link].ap.beacon_interval) ++ continue; ++ chandef = wdev->links[link].ap.chandef; ++ break; + case NL80211_IFTYPE_MESH_POINT: + if (!wdev->u.mesh.beacon_interval) + continue; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/677-02-wifi-cfg80211-Add-link_id-parameter-to-various-key-o.patch b/feeds/ipq95xx/mac80211/patches/qca/677-02-wifi-cfg80211-Add-link_id-parameter-to-various-key-o.patch new file mode 100644 index 000000000..6787f77d4 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/677-02-wifi-cfg80211-Add-link_id-parameter-to-various-key-o.patch @@ -0,0 +1,954 @@ +From 535cb980756ba578c8c78752ca26a9f6eaf4dbd2 Mon Sep 17 00:00:00 2001 +From: Veerendranath Jakkam +Date: Fri, 18 Nov 2022 16:39:31 +0530 +Subject: [PATCH] wifi: cfg80211: Add link_id parameter to various key + operations for MLO + +Add support for various key operations on MLD by adding new parameter +link_id. Pass the link_id received from userspace to driver for add_key, +get_key, del_key, set_default_key, set_default_mgmt_key and +set_default_beacon_key to support configuring keys specific to each MLO +link. Userspace must not specify link ID for MLO pairwise key since it +is common for all the MLO links. + +Signed-off-by: Veerendranath Jakkam +Link: https://lore.kernel.org/r/20220730052643.1959111-4-quic_vjakkam@quicinc.com +Signed-off-by: Johannes Berg +Signed-off-by: Sriram R +--- + drivers/net/wireless/ath/ath6kl/cfg80211.c | 8 +- + drivers/net/wireless/ath/wil6210/cfg80211.c | 10 +- + include/net/cfg80211.h | 37 ++++-- + include/uapi/linux/nl80211.h | 14 ++- + net/mac80211/cfg.c | 17 +-- + net/wireless/ibss.c | 2 +- + net/wireless/nl80211.c | 126 +++++++++++++++----- + net/wireless/rdev-ops.h | 58 +++++---- + net/wireless/sme.c | 2 +- + net/wireless/trace.h | 86 +++++++------ + net/wireless/util.c | 4 +- + net/wireless/wext-compat.c | 11 +- + 12 files changed, 245 insertions(+), 130 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c +index 9d2f2b1..972b9bb 100644 +--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c ++++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c +@@ -1124,7 +1124,7 @@ void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq, + } + + static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, +- u8 key_index, bool pairwise, ++ int link_id, u8 key_index, bool pairwise, + const u8 *mac_addr, + struct key_params *params) + { +@@ -1249,7 +1249,7 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, + } + + static int ath6kl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, +- u8 key_index, bool pairwise, ++ int link_id, u8 key_index, bool pairwise, + const u8 *mac_addr) + { + struct ath6kl *ar = ath6kl_priv(ndev); +@@ -1279,7 +1279,7 @@ static int ath6kl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, + } + + static int ath6kl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, +- u8 key_index, bool pairwise, ++ int link_id, u8 key_index, bool pairwise, + const u8 *mac_addr, void *cookie, + void (*callback) (void *cookie, + struct key_params *)) +@@ -1314,7 +1314,7 @@ static int ath6kl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, + } + + static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy, +- struct net_device *ndev, ++ struct net_device *ndev, int link_id, + u8 key_index, bool unicast, + bool multicast) + { +diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c +index 678953f..43f4915 100644 +--- a/drivers/net/wireless/ath/wil6210/cfg80211.c ++++ b/drivers/net/wireless/ath/wil6210/cfg80211.c +@@ -1620,7 +1620,7 @@ static void wil_del_rx_key(u8 key_index, enum wmi_key_usage key_usage, + } + + static int wil_cfg80211_add_key(struct wiphy *wiphy, +- struct net_device *ndev, ++ struct net_device *ndev, int link_id, + u8 key_index, bool pairwise, + const u8 *mac_addr, + struct key_params *params) +@@ -1696,7 +1696,7 @@ static int wil_cfg80211_add_key(struct wiphy *wiphy, + } + + static int wil_cfg80211_del_key(struct wiphy *wiphy, +- struct net_device *ndev, ++ struct net_device *ndev, int link_id, + u8 key_index, bool pairwise, + const u8 *mac_addr) + { +@@ -1723,7 +1723,7 @@ static int wil_cfg80211_del_key(struct wiphy *wiphy, + + /* Need to be present or wiphy_new() will WARN */ + static int wil_cfg80211_set_default_key(struct wiphy *wiphy, +- struct net_device *ndev, ++ struct net_device *ndev, int link_id, + u8 key_index, bool unicast, + bool multicast) + { +@@ -2072,8 +2072,8 @@ void wil_cfg80211_ap_recovery(struct wil6210_priv *wil) + key_params.key = vif->gtk; + key_params.key_len = vif->gtk_len; + key_params.seq_len = IEEE80211_GCMP_PN_LEN; +- rc = wil_cfg80211_add_key(wiphy, ndev, vif->gtk_index, false, +- NULL, &key_params); ++ rc = wil_cfg80211_add_key(wiphy, ndev, -1, vif->gtk_index, ++ false, NULL, &key_params); + if (rc) + wil_err(wil, "vif %d recovery add key failed (%d)\n", + i, rc); +diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h +index f273b3b..aad987c 100644 +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -4013,22 +4013,33 @@ struct mgmt_frame_regs { + * @del_intf_link: Remove an MLO link from the given interface. + * + * @add_key: add a key with the given parameters. @mac_addr will be %NULL +- * when adding a group key. ++ * when adding a group key. @link_id will be -1 for non-MLO connection. ++ * For MLO connection, @link_id will be >= 0 for group key and -1 for ++ * pairwise key, @mac_addr will be peer's MLD address for MLO pairwise key. + * + * @get_key: get information about the key with the given parameters. + * @mac_addr will be %NULL when requesting information for a group + * key. All pointers given to the @callback function need not be valid + * after it returns. This function should return an error if it is + * not possible to retrieve the key, -ENOENT if it doesn't exist. ++ * @link_id will be -1 for non-MLO connection. For MLO connection, ++ * @link_id will be >= 0 for group key and -1 for pairwise key, @mac_addr ++ * will be peer's MLD address for MLO pairwise key. + * + * @del_key: remove a key given the @mac_addr (%NULL for a group key) +- * and @key_index, return -ENOENT if the key doesn't exist. ++ * and @key_index, return -ENOENT if the key doesn't exist. @link_id will ++ * be -1 for non-MLO connection. For MLO connection, @link_id will be >= 0 ++ * for group key and -1 for pairwise key, @mac_addr will be peer's MLD ++ * address for MLO pairwise key. + * +- * @set_default_key: set the default key on an interface ++ * @set_default_key: set the default key on an interface. @link_id will be >= 0 ++ * for MLO connection and -1 for non-MLO connection. + * +- * @set_default_mgmt_key: set the default management frame key on an interface ++ * @set_default_mgmt_key: set the default management frame key on an interface. ++ * @link_id will be >= 0 for MLO connection and -1 for non-MLO connection. + * +- * @set_default_beacon_key: set the default Beacon frame key on an interface ++ * @set_default_beacon_key: set the default Beacon frame key on an interface. ++ * @link_id will be >= 0 for MLO connection and -1 for non-MLO connection. + * + * @set_rekey_data: give the data necessary for GTK rekeying to the driver + * +@@ -4377,22 +4388,24 @@ struct cfg80211_ops { + unsigned int link_id); + + int (*add_key)(struct wiphy *wiphy, struct net_device *netdev, +- u8 key_index, bool pairwise, const u8 *mac_addr, +- struct key_params *params); ++ int link_id, u8 key_index, bool pairwise, ++ const u8 *mac_addr, struct key_params *params); + int (*get_key)(struct wiphy *wiphy, struct net_device *netdev, +- u8 key_index, bool pairwise, const u8 *mac_addr, +- void *cookie, ++ int link_id, u8 key_index, bool pairwise, ++ const u8 *mac_addr, void *cookie, + void (*callback)(void *cookie, struct key_params*)); + int (*del_key)(struct wiphy *wiphy, struct net_device *netdev, +- u8 key_index, bool pairwise, const u8 *mac_addr); ++ int link_id, u8 key_index, bool pairwise, ++ const u8 *mac_addr); + int (*set_default_key)(struct wiphy *wiphy, +- struct net_device *netdev, ++ struct net_device *netdev, int link_id, + u8 key_index, bool unicast, bool multicast); + int (*set_default_mgmt_key)(struct wiphy *wiphy, +- struct net_device *netdev, ++ struct net_device *netdev, int link_id, + u8 key_index); + int (*set_default_beacon_key)(struct wiphy *wiphy, + struct net_device *netdev, ++ int link_id, + u8 key_index); + + int (*start_ap)(struct wiphy *wiphy, struct net_device *dev, +diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h +index f5c326c..6bfc12e 100644 +--- a/include/uapi/linux/nl80211.h ++++ b/include/uapi/linux/nl80211.h +@@ -377,14 +377,22 @@ + * the non-transmitting interfaces are deleted as well. + * + * @NL80211_CMD_GET_KEY: Get sequence counter information for a key specified +- * by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC. ++ * by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC. %NL80211_ATTR_MAC ++ * represents peer's MLD address for MLO pairwise key. For MLO group key, ++ * the link is identified by %NL80211_ATTR_MLO_LINK_ID. + * @NL80211_CMD_SET_KEY: Set key attributes %NL80211_ATTR_KEY_DEFAULT, + * %NL80211_ATTR_KEY_DEFAULT_MGMT, or %NL80211_ATTR_KEY_THRESHOLD. ++ * For MLO connection, the link to set default key is identified by ++ * %NL80211_ATTR_MLO_LINK_ID. + * @NL80211_CMD_NEW_KEY: add a key with given %NL80211_ATTR_KEY_DATA, + * %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC, %NL80211_ATTR_KEY_CIPHER, +- * and %NL80211_ATTR_KEY_SEQ attributes. ++ * and %NL80211_ATTR_KEY_SEQ attributes. %NL80211_ATTR_MAC represents ++ * peer's MLD address for MLO pairwise key. The link to add MLO ++ * group key is identified by %NL80211_ATTR_MLO_LINK_ID. + * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX +- * or %NL80211_ATTR_MAC. ++ * or %NL80211_ATTR_MAC. %NL80211_ATTR_MAC represents peer's MLD address ++ * for MLO pairwise key. The link to delete group key is identified by ++ * %NL80211_ATTR_MLO_LINK_ID. + * + * @NL80211_CMD_GET_BEACON: (not used) + * @NL80211_CMD_UPDATE_AP: Update AP parameters which can vary at the +diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c +index 281a686..612229c 100644 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -434,8 +434,8 @@ static int ieee80211_set_tx(struct ieee80211_sub_if_data *sdata, + } + + static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, +- u8 key_idx, bool pairwise, const u8 *mac_addr, +- struct key_params *params) ++ int link_id, u8 key_idx, bool pairwise, ++ const u8 *mac_addr, struct key_params *params) + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; +@@ -581,7 +581,8 @@ ieee80211_lookup_key(struct ieee80211_sub_if_data *sdata, + } + + static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, +- u8 key_idx, bool pairwise, const u8 *mac_addr) ++ int link_id, u8 key_idx, bool pairwise, ++ const u8 *mac_addr) + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; +@@ -608,8 +609,8 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, + } + + static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, +- u8 key_idx, bool pairwise, const u8 *mac_addr, +- void *cookie, ++ int link_id, u8 key_idx, bool pairwise, ++ const u8 *mac_addr, void *cookie, + void (*callback)(void *cookie, + struct key_params *params)) + { +@@ -714,7 +715,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, + + static int ieee80211_config_default_key(struct wiphy *wiphy, + struct net_device *dev, +- u8 key_idx, bool uni, ++ int link_id, u8 key_idx, bool uni, + bool multi) + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); +@@ -726,7 +727,7 @@ static int ieee80211_config_default_key(struct wiphy *wiphy, + + static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy, + struct net_device *dev, +- u8 key_idx) ++ int link_id, u8 key_idx) + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + +@@ -737,7 +738,7 @@ static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy, + + static int ieee80211_config_default_beacon_key(struct wiphy *wiphy, + struct net_device *dev, +- u8 key_idx) ++ int link_id, u8 key_idx) + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + +diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c +index e7e453f..5a0e232 100644 +--- a/net/wireless/ibss.c ++++ b/net/wireless/ibss.c +@@ -171,7 +171,7 @@ static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext) + */ + if (rdev->ops->del_key) + for (i = 0; i < 6; i++) +- rdev_del_key(rdev, dev, i, false, NULL); ++ rdev_del_key(rdev, dev, -1, i, false, NULL); + + if (wdev->u.ibss.current_bss) { + cfg80211_unhold_bss(wdev->u.ibss.current_bss); +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index a7345de..1b06692 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -1602,7 +1602,6 @@ static int nl80211_key_allowed(struct wireless_dev *wdev) + return -ENOLINK; + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_P2P_CLIENT: +- /* for MLO, require driver validation of the link ID */ + if (wdev->connected) + return 0; + return -ENOLINK; +@@ -4481,6 +4480,38 @@ static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info) + return rdev_set_noack_map(rdev, dev, noack_map); + } + ++static int nl80211_validate_key_link_id(struct genl_info *info, ++ struct wireless_dev *wdev, ++ int link_id, bool pairwise) ++{ ++ if (pairwise) { ++ if (link_id != -1) { ++ GENL_SET_ERR_MSG(info, ++ "link ID not allowed for pairwise key"); ++ return -EINVAL; ++ } ++ ++ return 0; ++ } ++ ++ if (wdev->valid_links) { ++ if (link_id == -1) { ++ GENL_SET_ERR_MSG(info, ++ "link ID must for MLO group key"); ++ return -EINVAL; ++ } ++ if (!(wdev->valid_links & BIT(link_id))) { ++ GENL_SET_ERR_MSG(info, "invalid link ID for MLO group key"); ++ return -EINVAL; ++ } ++ } else if (link_id != -1) { ++ GENL_SET_ERR_MSG(info, "link ID not allowed for non-MLO group key"); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ + struct get_key_cookie { + struct sk_buff *msg; + int error; +@@ -4542,13 +4573,15 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) + void *hdr; + struct sk_buff *msg; + bool bigtk_support = false; ++ int link_id = nl80211_link_id_or_invalid(info->attrs); ++ struct wireless_dev *wdev = dev->ieee80211_ptr; + + if (wiphy_ext_feature_isset(&rdev->wiphy, + NL80211_EXT_FEATURE_BEACON_PROTECTION)) + bigtk_support = true; + +- if ((dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION || +- dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_CLIENT) && ++ if ((wdev->iftype == NL80211_IFTYPE_STATION || ++ wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) && + wiphy_ext_feature_isset(&rdev->wiphy, + NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT)) + bigtk_support = true; +@@ -4600,8 +4633,12 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr)) + goto nla_put_failure; + +- err = rdev_get_key(rdev, dev, key_idx, pairwise, mac_addr, &cookie, +- get_key_callback); ++ err = nl80211_validate_key_link_id(info, wdev, link_id, pairwise); ++ if (err) ++ goto free_msg; ++ ++ err = rdev_get_key(rdev, dev, link_id, key_idx, pairwise, mac_addr, ++ &cookie, get_key_callback); + + if (err) + goto free_msg; +@@ -4625,6 +4662,8 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) + struct key_parse key; + int err; + struct net_device *dev = info->user_ptr[1]; ++ int link_id = nl80211_link_id_or_invalid(info->attrs); ++ struct wireless_dev *wdev = dev->ieee80211_ptr; + + err = nl80211_parse_key(info, &key); + if (err) +@@ -4640,7 +4679,7 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) + !(key.p.mode == NL80211_KEY_SET_TX)) + return -EINVAL; + +- wdev_lock(dev->ieee80211_ptr); ++ wdev_lock(wdev); + + if (key.def) { + if (!rdev->ops->set_default_key) { +@@ -4648,18 +4687,22 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) + goto out; + } + +- err = nl80211_key_allowed(dev->ieee80211_ptr); ++ err = nl80211_key_allowed(wdev); ++ if (err) ++ goto out; ++ ++ err = nl80211_validate_key_link_id(info, wdev, link_id, false); + if (err) + goto out; + +- err = rdev_set_default_key(rdev, dev, key.idx, +- key.def_uni, key.def_multi); ++ err = rdev_set_default_key(rdev, dev, link_id, key.idx, ++ key.def_uni, key.def_multi); + + if (err) + goto out; + + #ifdef CPTCFG_CFG80211_WEXT +- dev->ieee80211_ptr->wext.default_key = key.idx; ++ wdev->wext.default_key = key.idx; + #endif + } else if (key.defmgmt) { + if (key.def_uni || !key.def_multi) { +@@ -4672,16 +4715,20 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) + goto out; + } + +- err = nl80211_key_allowed(dev->ieee80211_ptr); ++ err = nl80211_key_allowed(wdev); ++ if (err) ++ goto out; ++ ++ err = nl80211_validate_key_link_id(info, wdev, link_id, false); + if (err) + goto out; + +- err = rdev_set_default_mgmt_key(rdev, dev, key.idx); ++ err = rdev_set_default_mgmt_key(rdev, dev, link_id, key.idx); + if (err) + goto out; + + #ifdef CPTCFG_CFG80211_WEXT +- dev->ieee80211_ptr->wext.default_mgmt_key = key.idx; ++ wdev->wext.default_mgmt_key = key.idx; + #endif + } else if (key.defbeacon) { + if (key.def_uni || !key.def_multi) { +@@ -4694,11 +4741,15 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) + goto out; + } + +- err = nl80211_key_allowed(dev->ieee80211_ptr); ++ err = nl80211_key_allowed(wdev); ++ if (err) ++ goto out; ++ ++ err = nl80211_validate_key_link_id(info, wdev, link_id, false); + if (err) + goto out; + +- err = rdev_set_default_beacon_key(rdev, dev, key.idx); ++ err = rdev_set_default_beacon_key(rdev, dev, link_id, key.idx); + if (err) + goto out; + } else if (key.p.mode == NL80211_KEY_SET_TX && +@@ -4714,14 +4765,18 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) + goto out; + } + +- err = rdev_add_key(rdev, dev, key.idx, ++ err = nl80211_validate_key_link_id(info, wdev, link_id, true); ++ if (err) ++ goto out; ++ ++ err = rdev_add_key(rdev, dev, link_id, key.idx, + NL80211_KEYTYPE_PAIRWISE, + mac_addr, &key.p); + } else { + err = -EINVAL; + } + out: +- wdev_unlock(dev->ieee80211_ptr); ++ wdev_unlock(wdev); + + return err; + } +@@ -4733,6 +4788,8 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) + struct net_device *dev = info->user_ptr[1]; + struct key_parse key; + const u8 *mac_addr = NULL; ++ int link_id = nl80211_link_id_or_invalid(info->attrs); ++ struct wireless_dev *wdev = dev->ieee80211_ptr; + + err = nl80211_parse_key(info, &key); + if (err) +@@ -4774,18 +4831,23 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) + return -EINVAL; + } + +- wdev_lock(dev->ieee80211_ptr); +- err = nl80211_key_allowed(dev->ieee80211_ptr); ++ wdev_lock(wdev); ++ err = nl80211_key_allowed(wdev); + if (err) + GENL_SET_ERR_MSG(info, "key not allowed"); ++ ++ if (!err) ++ err = nl80211_validate_key_link_id(info, wdev, link_id, ++ key.type == NL80211_KEYTYPE_PAIRWISE); ++ + if (!err) { +- err = rdev_add_key(rdev, dev, key.idx, ++ err = rdev_add_key(rdev, dev, link_id, key.idx, + key.type == NL80211_KEYTYPE_PAIRWISE, + mac_addr, &key.p); + if (err) + GENL_SET_ERR_MSG(info, "key addition failed"); + } +- wdev_unlock(dev->ieee80211_ptr); ++ wdev_unlock(wdev); + + return err; + } +@@ -4797,6 +4859,8 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) + struct net_device *dev = info->user_ptr[1]; + u8 *mac_addr = NULL; + struct key_parse key; ++ int link_id = nl80211_link_id_or_invalid(info->attrs); ++ struct wireless_dev *wdev = dev->ieee80211_ptr; + + err = nl80211_parse_key(info, &key); + if (err) +@@ -4824,27 +4888,31 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) + if (!rdev->ops->del_key) + return -EOPNOTSUPP; + +- wdev_lock(dev->ieee80211_ptr); +- err = nl80211_key_allowed(dev->ieee80211_ptr); ++ wdev_lock(wdev); ++ err = nl80211_key_allowed(wdev); + + if (key.type == NL80211_KEYTYPE_GROUP && mac_addr && + !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) + err = -ENOENT; + + if (!err) +- err = rdev_del_key(rdev, dev, key.idx, ++ err = nl80211_validate_key_link_id(info, wdev, link_id, ++ key.type == NL80211_KEYTYPE_PAIRWISE); ++ ++ if (!err) ++ err = rdev_del_key(rdev, dev, link_id, key.idx, + key.type == NL80211_KEYTYPE_PAIRWISE, + mac_addr); + + #ifdef CPTCFG_CFG80211_WEXT + if (!err) { +- if (key.idx == dev->ieee80211_ptr->wext.default_key) +- dev->ieee80211_ptr->wext.default_key = -1; +- else if (key.idx == dev->ieee80211_ptr->wext.default_mgmt_key) +- dev->ieee80211_ptr->wext.default_mgmt_key = -1; ++ if (key.idx == wdev->wext.default_key) ++ wdev->wext.default_key = -1; ++ else if (key.idx == wdev->wext.default_mgmt_key) ++ wdev->wext.default_mgmt_key = -1; + } + #endif +- wdev_unlock(dev->ieee80211_ptr); ++ wdev_unlock(wdev); + + return err; + } +diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h +index 3a1c3f8..3a89f86 100644 +--- a/net/wireless/rdev-ops.h ++++ b/net/wireless/rdev-ops.h +@@ -77,65 +77,69 @@ rdev_change_virtual_intf(struct cfg80211_registered_device *rdev, + } + + static inline int rdev_add_key(struct cfg80211_registered_device *rdev, +- struct net_device *netdev, u8 key_index, +- bool pairwise, const u8 *mac_addr, ++ struct net_device *netdev, int link_id, ++ u8 key_index, bool pairwise, const u8 *mac_addr, + struct key_params *params) + { + int ret; +- trace_rdev_add_key(&rdev->wiphy, netdev, key_index, pairwise, ++ trace_rdev_add_key(&rdev->wiphy, netdev, link_id, key_index, pairwise, + mac_addr, params->mode); +- ret = rdev->ops->add_key(&rdev->wiphy, netdev, key_index, pairwise, +- mac_addr, params); ++ ret = rdev->ops->add_key(&rdev->wiphy, netdev, link_id, key_index, ++ pairwise, mac_addr, params); + trace_rdev_return_int(&rdev->wiphy, ret); + return ret; + } + + static inline int + rdev_get_key(struct cfg80211_registered_device *rdev, struct net_device *netdev, +- u8 key_index, bool pairwise, const u8 *mac_addr, void *cookie, ++ int link_id, u8 key_index, bool pairwise, const u8 *mac_addr, ++ void *cookie, + void (*callback)(void *cookie, struct key_params*)) + { + int ret; +- trace_rdev_get_key(&rdev->wiphy, netdev, key_index, pairwise, mac_addr); +- ret = rdev->ops->get_key(&rdev->wiphy, netdev, key_index, pairwise, +- mac_addr, cookie, callback); ++ trace_rdev_get_key(&rdev->wiphy, netdev, link_id, key_index, pairwise, ++ mac_addr); ++ ret = rdev->ops->get_key(&rdev->wiphy, netdev, link_id, key_index, ++ pairwise, mac_addr, cookie, callback); + trace_rdev_return_int(&rdev->wiphy, ret); + return ret; + } + + static inline int rdev_del_key(struct cfg80211_registered_device *rdev, +- struct net_device *netdev, u8 key_index, +- bool pairwise, const u8 *mac_addr) ++ struct net_device *netdev, int link_id, ++ u8 key_index, bool pairwise, const u8 *mac_addr) + { + int ret; +- trace_rdev_del_key(&rdev->wiphy, netdev, key_index, pairwise, mac_addr); +- ret = rdev->ops->del_key(&rdev->wiphy, netdev, key_index, pairwise, +- mac_addr); ++ trace_rdev_del_key(&rdev->wiphy, netdev, link_id, key_index, pairwise, ++ mac_addr); ++ ret = rdev->ops->del_key(&rdev->wiphy, netdev, link_id, key_index, ++ pairwise, mac_addr); + trace_rdev_return_int(&rdev->wiphy, ret); + return ret; + } + + static inline int + rdev_set_default_key(struct cfg80211_registered_device *rdev, +- struct net_device *netdev, u8 key_index, bool unicast, +- bool multicast) ++ struct net_device *netdev, int link_id, u8 key_index, ++ bool unicast, bool multicast) + { + int ret; +- trace_rdev_set_default_key(&rdev->wiphy, netdev, key_index, ++ trace_rdev_set_default_key(&rdev->wiphy, netdev, link_id, key_index, + unicast, multicast); +- ret = rdev->ops->set_default_key(&rdev->wiphy, netdev, key_index, +- unicast, multicast); ++ ret = rdev->ops->set_default_key(&rdev->wiphy, netdev, link_id, ++ key_index, unicast, multicast); + trace_rdev_return_int(&rdev->wiphy, ret); + return ret; + } + + static inline int + rdev_set_default_mgmt_key(struct cfg80211_registered_device *rdev, +- struct net_device *netdev, u8 key_index) ++ struct net_device *netdev, int link_id, u8 key_index) + { + int ret; +- trace_rdev_set_default_mgmt_key(&rdev->wiphy, netdev, key_index); +- ret = rdev->ops->set_default_mgmt_key(&rdev->wiphy, netdev, ++ trace_rdev_set_default_mgmt_key(&rdev->wiphy, netdev, link_id, ++ key_index); ++ ret = rdev->ops->set_default_mgmt_key(&rdev->wiphy, netdev, link_id, + key_index); + trace_rdev_return_int(&rdev->wiphy, ret); + return ret; +@@ -143,13 +147,15 @@ rdev_set_default_mgmt_key(struct cfg80211_registered_device *rdev, + + static inline int + rdev_set_default_beacon_key(struct cfg80211_registered_device *rdev, +- struct net_device *netdev, u8 key_index) ++ struct net_device *netdev, int link_id, ++ u8 key_index) + { + int ret; + +- trace_rdev_set_default_beacon_key(&rdev->wiphy, netdev, key_index); +- ret = rdev->ops->set_default_beacon_key(&rdev->wiphy, netdev, +- key_index); ++ trace_rdev_set_default_beacon_key(&rdev->wiphy, netdev, link_id, ++ key_index); ++ ret = rdev->ops->set_default_beacon_key(&rdev->wiphy, netdev, link_id, ++ key_index); + trace_rdev_return_int(&rdev->wiphy, ret); + return ret; + } +diff --git a/net/wireless/sme.c b/net/wireless/sme.c +index b0f1a55..238ce2f 100644 +--- a/net/wireless/sme.c ++++ b/net/wireless/sme.c +@@ -1323,7 +1323,7 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, + NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT)) + max_key_idx = 7; + for (i = 0; i <= max_key_idx; i++) +- rdev_del_key(rdev, dev, i, false, NULL); ++ rdev_del_key(rdev, dev, -1, i, false, NULL); + } + + rdev_set_qos_map(rdev, dev, NULL); +diff --git a/net/wireless/trace.h b/net/wireless/trace.h +index f3e2ba7..aa2df9d 100644 +--- a/net/wireless/trace.h ++++ b/net/wireless/trace.h +@@ -434,13 +434,14 @@ TRACE_EVENT(rdev_change_virtual_intf, + ); + + DECLARE_EVENT_CLASS(key_handle, +- TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, +- bool pairwise, const u8 *mac_addr), +- TP_ARGS(wiphy, netdev, key_index, pairwise, mac_addr), ++ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int link_id, ++ u8 key_index, bool pairwise, const u8 *mac_addr), ++ TP_ARGS(wiphy, netdev, link_id, key_index, pairwise, mac_addr), + TP_STRUCT__entry( + WIPHY_ENTRY + NETDEV_ENTRY + MAC_ENTRY(mac_addr) ++ __field(int, link_id) + __field(u8, key_index) + __field(bool, pairwise) + ), +@@ -448,34 +449,38 @@ DECLARE_EVENT_CLASS(key_handle, + WIPHY_ASSIGN; + NETDEV_ASSIGN; + MAC_ASSIGN(mac_addr, mac_addr); ++ __entry->link_id = link_id; + __entry->key_index = key_index; + __entry->pairwise = pairwise; + ), +- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", key_index: %u, pairwise: %s, mac addr: " MAC_PR_FMT, +- WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index, +- BOOL_TO_STR(__entry->pairwise), MAC_PR_ARG(mac_addr)) ++ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", link_id: %d, " ++ "key_index: %u, pairwise: %s, mac addr: " MAC_PR_FMT, ++ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->link_id, ++ __entry->key_index, BOOL_TO_STR(__entry->pairwise), ++ MAC_PR_ARG(mac_addr)) + ); + + DEFINE_EVENT(key_handle, rdev_get_key, +- TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, +- bool pairwise, const u8 *mac_addr), +- TP_ARGS(wiphy, netdev, key_index, pairwise, mac_addr) ++ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int link_id, ++ u8 key_index, bool pairwise, const u8 *mac_addr), ++ TP_ARGS(wiphy, netdev, link_id, key_index, pairwise, mac_addr) + ); + + DEFINE_EVENT(key_handle, rdev_del_key, +- TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, +- bool pairwise, const u8 *mac_addr), +- TP_ARGS(wiphy, netdev, key_index, pairwise, mac_addr) ++ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int link_id, ++ u8 key_index, bool pairwise, const u8 *mac_addr), ++ TP_ARGS(wiphy, netdev, link_id, key_index, pairwise, mac_addr) + ); + + TRACE_EVENT(rdev_add_key, +- TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, +- bool pairwise, const u8 *mac_addr, u8 mode), +- TP_ARGS(wiphy, netdev, key_index, pairwise, mac_addr, mode), ++ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int link_id, ++ u8 key_index, bool pairwise, const u8 *mac_addr, u8 mode), ++ TP_ARGS(wiphy, netdev, link_id, key_index, pairwise, mac_addr, mode), + TP_STRUCT__entry( + WIPHY_ENTRY + NETDEV_ENTRY + MAC_ENTRY(mac_addr) ++ __field(int, link_id) + __field(u8, key_index) + __field(bool, pairwise) + __field(u8, mode) +@@ -484,24 +489,27 @@ TRACE_EVENT(rdev_add_key, + WIPHY_ASSIGN; + NETDEV_ASSIGN; + MAC_ASSIGN(mac_addr, mac_addr); ++ __entry->link_id = link_id; + __entry->key_index = key_index; + __entry->pairwise = pairwise; + __entry->mode = mode; + ), +- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", key_index: %u, " +- "mode: %u, pairwise: %s, mac addr: " MAC_PR_FMT, +- WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index, +- __entry->mode, BOOL_TO_STR(__entry->pairwise), +- MAC_PR_ARG(mac_addr)) ++ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", link_id: %d, " ++ "key_index: %u, mode: %u, pairwise: %s, " ++ "mac addr: " MAC_PR_FMT, ++ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->link_id, ++ __entry->key_index, __entry->mode, ++ BOOL_TO_STR(__entry->pairwise), MAC_PR_ARG(mac_addr)) + ); + + TRACE_EVENT(rdev_set_default_key, +- TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, +- bool unicast, bool multicast), +- TP_ARGS(wiphy, netdev, key_index, unicast, multicast), ++ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int link_id, ++ u8 key_index, bool unicast, bool multicast), ++ TP_ARGS(wiphy, netdev, link_id, key_index, unicast, multicast), + TP_STRUCT__entry( + WIPHY_ENTRY + NETDEV_ENTRY ++ __field(int, link_id) + __field(u8, key_index) + __field(bool, unicast) + __field(bool, multicast) +@@ -509,48 +517,58 @@ TRACE_EVENT(rdev_set_default_key, + TP_fast_assign( + WIPHY_ASSIGN; + NETDEV_ASSIGN; ++ __entry->link_id = link_id; + __entry->key_index = key_index; + __entry->unicast = unicast; + __entry->multicast = multicast; + ), +- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", key index: %u, unicast: %s, multicast: %s", +- WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index, +- BOOL_TO_STR(__entry->unicast), ++ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", link_id: %d, " ++ "key index: %u, unicast: %s, multicast: %s", ++ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->link_id, ++ __entry->key_index, BOOL_TO_STR(__entry->unicast), + BOOL_TO_STR(__entry->multicast)) + ); + + TRACE_EVENT(rdev_set_default_mgmt_key, +- TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index), +- TP_ARGS(wiphy, netdev, key_index), ++ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int link_id, ++ u8 key_index), ++ TP_ARGS(wiphy, netdev, link_id, key_index), + TP_STRUCT__entry( + WIPHY_ENTRY + NETDEV_ENTRY ++ __field(int, link_id) + __field(u8, key_index) + ), + TP_fast_assign( + WIPHY_ASSIGN; + NETDEV_ASSIGN; ++ __entry->link_id = link_id; + __entry->key_index = key_index; + ), +- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", key index: %u", +- WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index) ++ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", link_id: %d, " ++ "key index: %u", WIPHY_PR_ARG, NETDEV_PR_ARG, ++ __entry->link_id, __entry->key_index) + ); + + TRACE_EVENT(rdev_set_default_beacon_key, +- TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index), +- TP_ARGS(wiphy, netdev, key_index), ++ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int link_id, ++ u8 key_index), ++ TP_ARGS(wiphy, netdev, link_id, key_index), + TP_STRUCT__entry( + WIPHY_ENTRY + NETDEV_ENTRY ++ __field(int, link_id) + __field(u8, key_index) + ), + TP_fast_assign( + WIPHY_ASSIGN; + NETDEV_ASSIGN; ++ __entry->link_id = link_id; + __entry->key_index = key_index; + ), +- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", key index: %u", +- WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index) ++ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", link_id: %d, " ++ "key index: %u", WIPHY_PR_ARG, NETDEV_PR_ARG, ++ __entry->link_id, __entry->key_index) + ); + + TRACE_EVENT(rdev_start_ap, +diff --git a/net/wireless/util.c b/net/wireless/util.c +index 805694c..6d3c195 100644 +--- a/net/wireless/util.c ++++ b/net/wireless/util.c +@@ -959,13 +959,13 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev) + for (i = 0; i < CFG80211_MAX_WEP_KEYS; i++) { + if (!wdev->connect_keys->params[i].cipher) + continue; +- if (rdev_add_key(rdev, dev, i, false, NULL, ++ if (rdev_add_key(rdev, dev, -1, i, false, NULL, + &wdev->connect_keys->params[i])) { + netdev_err(dev, "failed to set key %d\n", i); + continue; + } + if (wdev->connect_keys->def == i && +- rdev_set_default_key(rdev, dev, i, true, true)) { ++ rdev_set_default_key(rdev, dev, -1, i, true, true)) { + netdev_err(dev, "failed to set defkey %d\n", i); + continue; + } +diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c +index a9767bf..3dd0946 100644 +--- a/net/wireless/wext-compat.c ++++ b/net/wireless/wext-compat.c +@@ -470,7 +470,7 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, + !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) + err = -ENOENT; + else +- err = rdev_del_key(rdev, dev, idx, pairwise, ++ err = rdev_del_key(rdev, dev, -1, idx, pairwise, + addr); + } + wdev->wext.connect.privacy = false; +@@ -509,7 +509,7 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, + if (wdev->connected || + (wdev->iftype == NL80211_IFTYPE_ADHOC && + wdev->u.ibss.current_bss)) +- err = rdev_add_key(rdev, dev, idx, pairwise, addr, params); ++ err = rdev_add_key(rdev, dev, -1, idx, pairwise, addr, params); + else if (params->cipher != WLAN_CIPHER_SUITE_WEP40 && + params->cipher != WLAN_CIPHER_SUITE_WEP104) + return -EINVAL; +@@ -546,7 +546,8 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, + __cfg80211_leave_ibss(rdev, wdev->netdev, true); + rejoin = true; + } +- err = rdev_set_default_key(rdev, dev, idx, true, true); ++ err = rdev_set_default_key(rdev, dev, -1, idx, true, ++ true); + } + if (!err) { + wdev->wext.default_key = idx; +@@ -561,7 +562,7 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, + if (wdev->connected || + (wdev->iftype == NL80211_IFTYPE_ADHOC && + wdev->u.ibss.current_bss)) +- err = rdev_set_default_mgmt_key(rdev, dev, idx); ++ err = rdev_set_default_mgmt_key(rdev, dev, -1, idx); + if (!err) + wdev->wext.default_mgmt_key = idx; + return err; +@@ -632,7 +633,7 @@ static int cfg80211_wext_siwencode(struct net_device *dev, + if (wdev->connected || + (wdev->iftype == NL80211_IFTYPE_ADHOC && + wdev->u.ibss.current_bss)) +- err = rdev_set_default_key(rdev, dev, idx, true, ++ err = rdev_set_default_key(rdev, dev, -1, idx, true, + true); + if (!err) + wdev->wext.default_key = idx; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/677-03-wifi-nl80211-send-MLO-links-channel-info-in-GET_INTE.patch b/feeds/ipq95xx/mac80211/patches/qca/677-03-wifi-nl80211-send-MLO-links-channel-info-in-GET_INTE.patch new file mode 100644 index 000000000..8c5866377 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/677-03-wifi-nl80211-send-MLO-links-channel-info-in-GET_INTE.patch @@ -0,0 +1,45 @@ +From 9156a0e8ff84ca02d843c277caf0cfcf30f32f1c Mon Sep 17 00:00:00 2001 +From: Veerendranath Jakkam +Date: Fri, 22 Jul 2022 18:40:00 +0530 +Subject: [PATCH] wifi: nl80211: send MLO links channel info in GET_INTERFACE + +Currently, MLO link level channel information not sent to +userspace when NL80211_CMD_GET_INTERFACE requested on MLD. + +Add support to send channel information for all valid links +for NL80211_CMD_GET_INTERFACE request. + +Signed-off-by: Veerendranath Jakkam +Link: https://lore.kernel.org/r/20220722131000.3437894-1-quic_vjakkam@quicinc.com +Signed-off-by: Johannes Berg +--- + net/wireless/nl80211.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 1b06692..7e8fdd7 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -3997,12 +3997,19 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag + + for_each_valid_link(wdev, link_id) { + struct nlattr *link = nla_nest_start(msg, link_id + 1); ++ struct cfg80211_chan_def chandef = {}; ++ int ret; + + if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id)) + goto nla_put_failure; + if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, + wdev->links[link_id].addr)) + goto nla_put_failure; ++ ++ ret = rdev_get_channel(rdev, wdev, link_id, &chandef); ++ if (ret == 0 && nl80211_send_chandef(msg, &chandef)) ++ goto nla_put_failure; ++ + nla_nest_end(msg, link); + } + +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/677-04-wifi-cfg80211-Add-link_id-to-cfg80211_ch_switch_star.patch b/feeds/ipq95xx/mac80211/patches/qca/677-04-wifi-cfg80211-Add-link_id-to-cfg80211_ch_switch_star.patch new file mode 100644 index 000000000..f515f32f2 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/677-04-wifi-cfg80211-Add-link_id-to-cfg80211_ch_switch_star.patch @@ -0,0 +1,154 @@ +From 22925c32d8c9b57007e6ebd6508574501d943c6a Mon Sep 17 00:00:00 2001 +From: Veerendranath Jakkam +Date: Fri, 18 Nov 2022 16:48:15 +0530 +Subject: [PATCH] wifi: cfg80211: Add link_id to + cfg80211_ch_switch_started_notify() + +Add link_id parameter to cfg80211_ch_switch_started_notify() to allow +driver to indicate on which link channel switch started on MLD. + +Send the data to userspace so it knows as well. + +Signed-off-by: Veerendranath Jakkam +Link: https://lore.kernel.org/r/20220722131143.3438042-1-quic_vjakkam@quicinc.com +Link: https://lore.kernel.org/r/20220722131143.3438042-2-quic_vjakkam@quicinc.com +[squash two patches] +Signed-off-by: Johannes Berg +--- + include/net/cfg80211.h | 4 +++- + net/mac80211/cfg.c | 2 +- + net/mac80211/mlme.c | 2 +- + net/wireless/nl80211.c | 18 ++++++++++++++---- + net/wireless/trace.h | 11 +++++++---- + 5 files changed, 26 insertions(+), 11 deletions(-) + +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -8556,6 +8556,7 @@ void cfg80211_ch_switch_notify(struct ne + * cfg80211_ch_switch_started_notify - notify channel switch start + * @dev: the device on which the channel switch started + * @chandef: the future channel definition ++ * @link_id: the link ID for MLO, must be 0 for non-MLO + * @count: the number of TBTTs until the channel switch happens + * @quiet: whether or not immediate quiet was requested by the AP + * +@@ -8565,7 +8566,8 @@ void cfg80211_ch_switch_notify(struct ne + */ + void cfg80211_ch_switch_started_notify(struct net_device *dev, + struct cfg80211_chan_def *chandef, +- u8 count, bool quiet); ++ unsigned int link_id, u8 count, ++ bool quiet); + + /** + * ieee80211_operating_class_to_band - convert operating class to band +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -3936,7 +3936,7 @@ __ieee80211_channel_switch(struct wiphy + IEEE80211_QUEUE_STOP_REASON_CSA); + + cfg80211_ch_switch_started_notify(sdata->dev, +- &sdata->deflink.csa_chandef, ++ &sdata->deflink.csa_chandef, 0, + params->count, params->block_tx); + + if (changed) { +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -1905,7 +1905,8 @@ ieee80211_sta_process_chanswitch(struct + mutex_unlock(&local->mtx); + + cfg80211_ch_switch_started_notify(sdata->dev, &csa_ie.chandef, +- csa_ie.count, csa_ie.mode); ++ link->link_id, csa_ie.count, ++ csa_ie.mode); + + if (local->ops->channel_switch) { + /* use driver's channel switch callback */ +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -19597,11 +19597,13 @@ EXPORT_SYMBOL(cfg80211_pmksa_candidate_n + + static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, + struct net_device *netdev, ++ unsigned int link_id, + struct cfg80211_chan_def *chandef, + gfp_t gfp, + enum nl80211_commands notif, + u8 count, bool quiet) + { ++ struct wireless_dev *wdev = netdev->ieee80211_ptr; + struct sk_buff *msg; + void *hdr; + +@@ -19618,6 +19620,10 @@ static void nl80211_ch_switch_notify(str + if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex)) + goto nla_put_failure; + ++ if (wdev->valid_links && ++ nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id)) ++ goto nla_put_failure; ++ + if (nl80211_send_chandef(msg, chandef)) + goto nla_put_failure; + +@@ -19677,7 +19683,7 @@ void cfg80211_ch_switch_notify(struct ne + + cfg80211_sched_dfs_chan_update(rdev); + +- nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL, ++ nl80211_ch_switch_notify(rdev, dev, link_id, chandef, GFP_KERNEL, + NL80211_CMD_CH_SWITCH_NOTIFY, 0, false); + } + EXPORT_SYMBOL(cfg80211_ch_switch_notify); +@@ -19733,15 +19739,19 @@ nla_put_failure: + + void cfg80211_ch_switch_started_notify(struct net_device *dev, + struct cfg80211_chan_def *chandef, +- u8 count, bool quiet) ++ unsigned int link_id, u8 count, ++ bool quiet) + { + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct wiphy *wiphy = wdev->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); + +- trace_cfg80211_ch_switch_started_notify(dev, chandef); ++ ASSERT_WDEV_LOCK(wdev); ++ WARN_INVALID_LINK_ID(wdev, link_id); ++ ++ trace_cfg80211_ch_switch_started_notify(dev, chandef, link_id); + +- nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL, ++ nl80211_ch_switch_notify(rdev, dev, link_id, chandef, GFP_KERNEL, + NL80211_CMD_CH_SWITCH_STARTED_NOTIFY, + count, quiet); + } +--- a/net/wireless/trace.h ++++ b/net/wireless/trace.h +@@ -3267,18 +3267,21 @@ TRACE_EVENT(cfg80211_ch_switch_notify, + + TRACE_EVENT(cfg80211_ch_switch_started_notify, + TP_PROTO(struct net_device *netdev, +- struct cfg80211_chan_def *chandef), +- TP_ARGS(netdev, chandef), ++ struct cfg80211_chan_def *chandef, ++ unsigned int link_id), ++ TP_ARGS(netdev, chandef, link_id), + TP_STRUCT__entry( + NETDEV_ENTRY + CHAN_DEF_ENTRY ++ __field(unsigned int, link_id) + ), + TP_fast_assign( + NETDEV_ASSIGN; + CHAN_DEF_ASSIGN(chandef); ++ __entry->link_id = link_id; + ), +- TP_printk(NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT, +- NETDEV_PR_ARG, CHAN_DEF_PR_ARG) ++ TP_printk(NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT ", link:%d", ++ NETDEV_PR_ARG, CHAN_DEF_PR_ARG, __entry->link_id) + ); + + TRACE_EVENT(cfg80211_radar_event, diff --git a/feeds/ipq95xx/mac80211/patches/qca/677-05-wifi-nl80211-use-link-ID-in-NL80211_CMD_SET_BSS.patch b/feeds/ipq95xx/mac80211/patches/qca/677-05-wifi-nl80211-use-link-ID-in-NL80211_CMD_SET_BSS.patch new file mode 100644 index 000000000..064b7e59d --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/677-05-wifi-nl80211-use-link-ID-in-NL80211_CMD_SET_BSS.patch @@ -0,0 +1,59 @@ +From e3f9866ec25ab17dba77418be742566553905651 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Tue, 6 Sep 2022 22:37:03 +0200 +Subject: [PATCH] wifi: nl80211: use link ID in NL80211_CMD_SET_BSS + +We clearly need the link ID here, to know the right BSS +to configure. Use/require it. + +Signed-off-by: Johannes Berg +--- + include/net/cfg80211.h | 2 ++ + net/wireless/nl80211.c | 4 +++- + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h +index 7ef765f..f8cd14d 100644 +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -2185,6 +2185,7 @@ struct mpath_info { + * + * Used to change BSS parameters (mainly for AP mode). + * ++ * @link_id: link_id or -1 for non-MLD + * @use_cts_prot: Whether to use CTS protection + * (0 = no, 1 = yes, -1 = do not change) + * @use_short_preamble: Whether the use of short preambles is allowed +@@ -2202,6 +2203,7 @@ struct mpath_info { + * @p2p_opp_ps: P2P opportunistic PS (-1 = no change) + */ + struct bss_parameters { ++ int link_id; + int use_cts_prot; + int use_short_preamble; + int use_short_slot_time; +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 0ca6e9c..b838325 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -8211,6 +8211,7 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) + int err; + + memset(¶ms, 0, sizeof(params)); ++ params.link_id = nl80211_link_id_or_invalid(info->attrs); + /* default to not changing parameters */ + params.use_cts_prot = -1; + params.use_short_preamble = -1; +@@ -17055,7 +17056,8 @@ static const struct genl_small_ops nl80211_small_ops[] = { + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = nl80211_set_bss, + .flags = GENL_UNS_ADMIN_PERM, +- .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), ++ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP | ++ NL80211_FLAG_MLO_VALID_LINK_ID), + }, + { + .cmd = NL80211_CMD_GET_REG, +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/677-06-wifi-mac80211-accept-STA-changes-without-link-change.patch b/feeds/ipq95xx/mac80211/patches/qca/677-06-wifi-mac80211-accept-STA-changes-without-link-change.patch new file mode 100644 index 000000000..f8d75f8d7 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/677-06-wifi-mac80211-accept-STA-changes-without-link-change.patch @@ -0,0 +1,51 @@ +From f6f3cc63f52aba89f49d9d0994dc385ce2aa7d19 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Sat, 23 Jul 2022 22:08:49 +0200 +Subject: [PATCH] wifi: mac80211: accept STA changes without link changes + +If there's no link ID, then check that there are no changes to +the link, and if so accept them, unless a new link is created. +While at it, reject creating a new link without an address. + +This fixes authorizing an MLD (peer) that has no link 0. + +Signed-off-by: Johannes Berg +--- + net/mac80211/cfg.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c +index f8f1cb6..aa45d8e 100644 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1775,6 +1775,18 @@ static int sta_link_apply_parameters(struct ieee80211_local *local, + rcu_dereference_protected(sta->link[link_id], + lockdep_is_held(&local->sta_mtx)); + ++ /* ++ * If there are no changes, then accept a link that doesn't exist, ++ * unless it's a new link. ++ */ ++ if (params->link_id < 0 && !new_link && ++ !params->link_mac && !params->txpwr_set && ++ !params->supported_rates_len && ++ !params->ht_capa && !params->vht_capa && ++ !params->he_capa && !params->eht_capa && ++ !params->opmode_notif_used) ++ return 0; ++ + if (!link || !link_sta) + return -EINVAL; + +@@ -1790,6 +1802,8 @@ static int sta_link_apply_parameters(struct ieee80211_local *local, + params->link_mac)) { + return -EINVAL; + } ++ } else if (new_link) { ++ return -EINVAL; + } + + if (params->txpwr_set) { +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/677-07-wifi-mac80211-properly-set-old_links-when-removing-a.patch b/feeds/ipq95xx/mac80211/patches/qca/677-07-wifi-mac80211-properly-set-old_links-when-removing-a.patch new file mode 100644 index 000000000..c43f7c7cd --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/677-07-wifi-mac80211-properly-set-old_links-when-removing-a.patch @@ -0,0 +1,41 @@ +From 104d639b041c4a51002bfb7ba2b2eddb1c23cf80 Mon Sep 17 00:00:00 2001 +From: Shaul Triebitz +Date: Sun, 24 Jul 2022 11:07:32 +0300 +Subject: [PATCH] wifi: mac80211: properly set old_links when removing a link + +In ieee80211_sta_remove_link, valid_links is set to +the new_links before calling drv_change_sta_links, but +is used for the old_links. + +Fixes: cb71f1d136a6 ("wifi: mac80211: add sta link addition/removal") +Signed-off-by: Shaul Triebitz +Signed-off-by: Johannes Berg +--- + net/mac80211/sta_info.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c +index b354906..3822665 100644 +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -2823,6 +2823,7 @@ hash: + void ieee80211_sta_remove_link(struct sta_info *sta, unsigned int link_id) + { + struct ieee80211_sub_if_data *sdata = sta->sdata; ++ u16 old_links = sta->sta.valid_links; + + lockdep_assert_held(&sdata->local->sta_mtx); + +@@ -2830,8 +2831,7 @@ void ieee80211_sta_remove_link(struct sta_info *sta, unsigned int link_id) + + if (test_sta_flag(sta, WLAN_STA_INSERTED)) + drv_change_sta_links(sdata->local, sdata, &sta->sta, +- sta->sta.valid_links, +- sta->sta.valid_links & ~BIT(link_id)); ++ old_links, sta->sta.valid_links); + + sta_remove_link(sta, link_id, true); + } +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/677-08-wifi-mac80211-set-link-BSSID.patch b/feeds/ipq95xx/mac80211/patches/qca/677-08-wifi-mac80211-set-link-BSSID.patch new file mode 100644 index 000000000..d98b61448 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/677-08-wifi-mac80211-set-link-BSSID.patch @@ -0,0 +1,33 @@ +From 59dccb83c08904cd2bf508f41bf1322746ee4622 Mon Sep 17 00:00:00 2001 +From: Shaul Triebitz +Date: Thu, 4 Aug 2022 16:50:18 +0300 +Subject: [PATCH] wifi: mac80211: set link BSSID + +For an AP interface, set the link BSSID when the link +is initialized. + +Signed-off-by: Shaul Triebitz +Signed-off-by: Johannes Berg +--- + net/mac80211/iface.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c +index dc44279..925fedd 100644 +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -418,9 +418,11 @@ static void ieee80211_link_init(struct ieee80211_sub_if_data *sdata, + case NL80211_IFTYPE_AP: + ether_addr_copy(link_conf->addr, + sdata->wdev.links[link_id].addr); ++ link_conf->bssid = link_conf->addr; + WARN_ON(!(sdata->wdev.valid_links & BIT(link_id))); + break; + case NL80211_IFTYPE_STATION: ++ /* station sets the bssid in ieee80211_mgd_setup_link */ + break; + default: + WARN_ON(1); +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/677-09-wifi-mac80211-use-link-in-TXQ-parameter-configuratio.patch b/feeds/ipq95xx/mac80211/patches/qca/677-09-wifi-mac80211-use-link-in-TXQ-parameter-configuratio.patch new file mode 100644 index 000000000..b8bed292f --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/677-09-wifi-mac80211-use-link-in-TXQ-parameter-configuratio.patch @@ -0,0 +1,65 @@ +From 96ebe205ff94eb3ac31eb725017dd330331dfe6e Mon Sep 17 00:00:00 2001 +From: Shaul Triebitz +Date: Tue, 2 Aug 2022 15:22:42 +0300 +Subject: [PATCH] wifi: mac80211: use link in TXQ parameter configuration + +Configure the correct link per the passed parameters. + +Signed-off-by: Shaul Triebitz +Signed-off-by: Johannes Berg +--- + net/mac80211/cfg.c | 24 +++++++++++++++++++++++- + 1 file changed, 23 insertions(+), 1 deletion(-) + +diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c +index aa45d8e..3c3e13b 100644 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -23,6 +23,24 @@ + #include "mesh.h" + #include "wme.h" + ++static struct ieee80211_link_data * ++ieee80211_link_or_deflink(struct ieee80211_sub_if_data *sdata, int link_id) ++{ ++ struct ieee80211_link_data *link; ++ ++ if (link_id < 0) { ++ if (sdata->vif.valid_links) ++ return ERR_PTR(-EINVAL); ++ ++ return &sdata->deflink; ++ } ++ ++ link = sdata_dereference(sdata->link[link_id], sdata); ++ if (!link) ++ return ERR_PTR(-ENOLINK); ++ return link; ++} ++ + static void ieee80211_set_mu_mimo_follow(struct ieee80211_sub_if_data *sdata, + struct vif_params *params) + { +@@ -2770,7 +2788,8 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, + { + struct ieee80211_local *local = wiphy_priv(wiphy); + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); +- struct ieee80211_link_data *link = &sdata->deflink; ++ struct ieee80211_link_data *link = ++ ieee80211_link_or_deflink(sdata, params->link_id); + struct ieee80211_tx_queue_params p; + + if (!local->ops->conf_tx) +@@ -2779,6 +2798,9 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, + if (local->hw.queues < IEEE80211_NUM_ACS) + return -EOPNOTSUPP; + ++ if (IS_ERR(link)) ++ return PTR_ERR(link); ++ + memset(&p, 0, sizeof(p)); + p.aifs = params->aifs; + p.cw_max = params->cwmax; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/677-10-wifi-mac80211-properly-implement-MLO-key-handling.patch b/feeds/ipq95xx/mac80211/patches/qca/677-10-wifi-mac80211-properly-implement-MLO-key-handling.patch new file mode 100644 index 000000000..c80682a73 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/677-10-wifi-mac80211-properly-implement-MLO-key-handling.patch @@ -0,0 +1,907 @@ +From dba1d480a2e01696442a7fee482c69c1c99c2bae Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Fri, 18 Nov 2022 17:06:22 +0530 +Subject: [PATCH] wifi: mac80211: properly implement MLO key handling + +Implement key installation and lookup (on TX and RX) +for MLO, so we can use multiple GTKs/IGTKs/BIGTKs. + +Co-authored-by: Ilan Peer +Signed-off-by: Ilan Peer +Signed-off-by: Johannes Berg +--- + include/net/mac80211.h | 2 + + net/mac80211/cfg.c | 75 ++++++++++++--- + net/mac80211/ieee80211_i.h | 1 + + net/mac80211/iface.c | 9 ++ + net/mac80211/key.c | 190 +++++++++++++++++++++++++------------ + net/mac80211/key.h | 13 ++- + net/mac80211/rx.c | 44 +++++---- + net/mac80211/tx.c | 56 +++++++++-- + 8 files changed, 286 insertions(+), 104 deletions(-) + +diff --git a/include/net/mac80211.h b/include/net/mac80211.h +index 30a80c1..96b7593 100644 +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -2091,6 +2091,7 @@ enum ieee80211_key_flags { + * - Temporal Authenticator Rx MIC Key (64 bits) + * @icv_len: The ICV length for this key type + * @iv_len: The IV length for this key type ++ * @link_id: the link ID for MLO, or -1 for non-MLO or pairwise keys + */ + struct ieee80211_key_conf { + atomic64_t tx_pn; +@@ -2100,6 +2101,7 @@ struct ieee80211_key_conf { + u8 hw_key_idx; + s8 keyidx; + u16 flags; ++ s8 link_id; + u16 vlan_id; + u8 keylen; + u8 key[]; +diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c +index 3c3e13b..7c90f1f 100644 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -24,12 +24,18 @@ + #include "wme.h" + + static struct ieee80211_link_data * +-ieee80211_link_or_deflink(struct ieee80211_sub_if_data *sdata, int link_id) ++ieee80211_link_or_deflink(struct ieee80211_sub_if_data *sdata, int link_id, ++ bool require_valid) + { + struct ieee80211_link_data *link; + + if (link_id < 0) { +- if (sdata->vif.valid_links) ++ /* ++ * For keys, if sdata is not an MLD, we might not use ++ * the return value at all (if it's not a pairwise key), ++ * so in that case (require_valid==false) don't error. ++ */ ++ if (require_valid && sdata->vif.valid_links) + return ERR_PTR(-EINVAL); + + return &sdata->deflink; +@@ -456,6 +462,8 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, + const u8 *mac_addr, struct key_params *params) + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ struct ieee80211_link_data *link = ++ ieee80211_link_or_deflink(sdata, link_id, false); + struct ieee80211_local *local = sdata->local; + struct sta_info *sta = NULL; + struct ieee80211_key *key; +@@ -464,6 +472,9 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, + if (!ieee80211_sdata_running(sdata)) + return -ENETDOWN; + ++ if (IS_ERR(link)) ++ return PTR_ERR(link); ++ + if (pairwise && params->mode == NL80211_KEY_SET_TX) + return ieee80211_set_tx(sdata, mac_addr, key_idx); + +@@ -472,6 +483,8 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_TKIP: + case WLAN_CIPHER_SUITE_WEP104: ++ if (link_id >= 0) ++ return -EINVAL; + if (WARN_ON_ONCE(fips_enabled)) + return -EINVAL; + break; +@@ -484,6 +497,8 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, + if (IS_ERR(key)) + return PTR_ERR(key); + ++ key->conf.link_id = link_id; ++ + if (pairwise) + key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE; + +@@ -546,7 +561,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, + break; + } + +- err = ieee80211_key_link(key, sdata, sta); ++ err = ieee80211_key_link(key, link, sta); + + out_unlock: + mutex_unlock(&local->sta_mtx); +@@ -555,20 +570,39 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, + } + + static struct ieee80211_key * +-ieee80211_lookup_key(struct ieee80211_sub_if_data *sdata, ++ieee80211_lookup_key(struct ieee80211_sub_if_data *sdata, int link_id, + u8 key_idx, bool pairwise, const u8 *mac_addr) + { + struct ieee80211_local *local; ++ struct ieee80211_link_data *link = &sdata->deflink; + struct ieee80211_key *key; +- struct sta_info *sta; + + local = sdata->local; + ++ if (link_id >= 0) { ++ link = rcu_dereference_check(sdata->link[link_id], ++ lockdep_is_held(&sdata->wdev.mtx)); ++ if (!link) ++ return NULL; ++ } ++ + if (mac_addr) { ++ struct sta_info *sta; ++ struct link_sta_info *link_sta; ++ + sta = sta_info_get_bss(sdata, mac_addr); + if (!sta) + return NULL; + ++ if (link_id >= 0) { ++ link_sta = rcu_dereference_check(sta->link[link_id], ++ lockdep_is_held(&local->sta_mtx)); ++ if (!link_sta) ++ return NULL; ++ } else { ++ link_sta = &sta->deflink; ++ } ++ + if (pairwise && key_idx < NUM_DEFAULT_KEYS) + return rcu_dereference_check_key_mtx(local, + sta->ptk[key_idx]); +@@ -578,7 +612,7 @@ ieee80211_lookup_key(struct ieee80211_sub_if_data *sdata, + NUM_DEFAULT_MGMT_KEYS + + NUM_DEFAULT_BEACON_KEYS) + return rcu_dereference_check_key_mtx(local, +- sta->deflink.gtk[key_idx]); ++ link_sta->gtk[key_idx]); + + return NULL; + } +@@ -587,7 +621,7 @@ ieee80211_lookup_key(struct ieee80211_sub_if_data *sdata, + return rcu_dereference_check_key_mtx(local, + sdata->keys[key_idx]); + +- key = rcu_dereference_check_key_mtx(local, sdata->deflink.gtk[key_idx]); ++ key = rcu_dereference_check_key_mtx(local, link->gtk[key_idx]); + if (key) + return key; + +@@ -610,7 +644,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, + mutex_lock(&local->sta_mtx); + mutex_lock(&local->key_mtx); + +- key = ieee80211_lookup_key(sdata, key_idx, pairwise, mac_addr); ++ key = ieee80211_lookup_key(sdata, link_id, key_idx, pairwise, mac_addr); + if (!key) { + ret = -ENOENT; + goto out_unlock; +@@ -646,7 +680,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, + + rcu_read_lock(); + +- key = ieee80211_lookup_key(sdata, key_idx, pairwise, mac_addr); ++ key = ieee80211_lookup_key(sdata, link_id, key_idx, pairwise, mac_addr); + if (!key) + goto out; + +@@ -737,8 +771,13 @@ static int ieee80211_config_default_key(struct wiphy *wiphy, + bool multi) + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ struct ieee80211_link_data *link = ++ ieee80211_link_or_deflink(sdata, link_id, false); + +- ieee80211_set_default_key(sdata, key_idx, uni, multi); ++ if (IS_ERR(link)) ++ return PTR_ERR(link); ++ ++ ieee80211_set_default_key(link, key_idx, uni, multi); + + return 0; + } +@@ -748,8 +787,13 @@ static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy, + int link_id, u8 key_idx) + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ struct ieee80211_link_data *link = ++ ieee80211_link_or_deflink(sdata, link_id, true); + +- ieee80211_set_default_mgmt_key(sdata, key_idx); ++ if (IS_ERR(link)) ++ return PTR_ERR(link); ++ ++ ieee80211_set_default_mgmt_key(link, key_idx); + + return 0; + } +@@ -759,8 +803,13 @@ static int ieee80211_config_default_beacon_key(struct wiphy *wiphy, + int link_id, u8 key_idx) + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ struct ieee80211_link_data *link = ++ ieee80211_link_or_deflink(sdata, link_id, true); ++ ++ if (IS_ERR(link)) ++ return PTR_ERR(link); + +- ieee80211_set_default_beacon_key(sdata, key_idx); ++ ieee80211_set_default_beacon_key(link, key_idx); + + return 0; + } +@@ -2789,7 +2838,7 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, + struct ieee80211_local *local = wiphy_priv(wiphy); + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_link_data *link = +- ieee80211_link_or_deflink(sdata, params->link_id); ++ ieee80211_link_or_deflink(sdata, params->link_id, true); + struct ieee80211_tx_queue_params p; + + if (!local->ops->conf_tx) +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index 900c864..501ec44 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -226,6 +226,7 @@ struct ieee80211_rx_data { + struct ieee80211_sub_if_data *sdata; + struct ieee80211_link_data *link; + struct sta_info *sta; ++ struct link_sta_info *link_sta; + struct ieee80211_key *key; + + unsigned int flags; +diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c +index 925fedd..2c02d76 100644 +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -446,10 +446,19 @@ struct link_container { + static void ieee80211_free_links(struct ieee80211_sub_if_data *sdata, + struct link_container **links) + { ++ LIST_HEAD(keys); + unsigned int link_id; + ++ for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) { ++ if (!links[link_id]) ++ continue; ++ ieee80211_remove_link_keys(&links[link_id]->data, &keys); ++ } ++ + synchronize_rcu(); + ++ ieee80211_free_key_list(sdata->local, &keys); ++ + for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) { + if (!links[link_id]) + continue; +diff --git a/net/mac80211/key.c b/net/mac80211/key.c +index ddf2efc..6296dac 100644 +--- a/net/mac80211/key.c ++++ b/net/mac80211/key.c +@@ -346,9 +346,10 @@ static void ieee80211_pairwise_rekey(struct ieee80211_key *old, + } + } + +-static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, ++static void __ieee80211_set_default_key(struct ieee80211_link_data *link, + int idx, bool uni, bool multi) + { ++ struct ieee80211_sub_if_data *sdata = link->sdata; + struct ieee80211_key *key = NULL; + + assert_key_lock(sdata->local); +@@ -356,7 +357,7 @@ static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, + if (idx >= 0 && idx < NUM_DEFAULT_KEYS) { + key = key_mtx_dereference(sdata->local, sdata->keys[idx]); + if (!key) +- key = key_mtx_dereference(sdata->local, sdata->deflink.gtk[idx]); ++ key = key_mtx_dereference(sdata->local, link->gtk[idx]); + } + + if (uni) { +@@ -367,47 +368,48 @@ static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, + } + + if (multi) +- rcu_assign_pointer(sdata->deflink.default_multicast_key, key); ++ rcu_assign_pointer(link->default_multicast_key, key); + + ieee80211_debugfs_key_update_default(sdata); + } + +-void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx, ++void ieee80211_set_default_key(struct ieee80211_link_data *link, int idx, + bool uni, bool multi) + { +- mutex_lock(&sdata->local->key_mtx); +- __ieee80211_set_default_key(sdata, idx, uni, multi); +- mutex_unlock(&sdata->local->key_mtx); ++ mutex_lock(&link->sdata->local->key_mtx); ++ __ieee80211_set_default_key(link, idx, uni, multi); ++ mutex_unlock(&link->sdata->local->key_mtx); + } + + static void +-__ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx) ++__ieee80211_set_default_mgmt_key(struct ieee80211_link_data *link, int idx) + { ++ struct ieee80211_sub_if_data *sdata = link->sdata; + struct ieee80211_key *key = NULL; + + assert_key_lock(sdata->local); + + if (idx >= NUM_DEFAULT_KEYS && + idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) +- key = key_mtx_dereference(sdata->local, +- sdata->deflink.gtk[idx]); ++ key = key_mtx_dereference(sdata->local, link->gtk[idx]); + +- rcu_assign_pointer(sdata->deflink.default_mgmt_key, key); ++ rcu_assign_pointer(link->default_mgmt_key, key); + + ieee80211_debugfs_key_update_default(sdata); + } + +-void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, ++void ieee80211_set_default_mgmt_key(struct ieee80211_link_data *link, + int idx) + { +- mutex_lock(&sdata->local->key_mtx); +- __ieee80211_set_default_mgmt_key(sdata, idx); +- mutex_unlock(&sdata->local->key_mtx); ++ mutex_lock(&link->sdata->local->key_mtx); ++ __ieee80211_set_default_mgmt_key(link, idx); ++ mutex_unlock(&link->sdata->local->key_mtx); + } + + static void +-__ieee80211_set_default_beacon_key(struct ieee80211_sub_if_data *sdata, int idx) ++__ieee80211_set_default_beacon_key(struct ieee80211_link_data *link, int idx) + { ++ struct ieee80211_sub_if_data *sdata = link->sdata; + struct ieee80211_key *key = NULL; + + assert_key_lock(sdata->local); +@@ -415,28 +417,30 @@ __ieee80211_set_default_beacon_key(struct ieee80211_sub_if_data *sdata, int idx) + if (idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS && + idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS + + NUM_DEFAULT_BEACON_KEYS) +- key = key_mtx_dereference(sdata->local, +- sdata->deflink.gtk[idx]); ++ key = key_mtx_dereference(sdata->local, link->gtk[idx]); + +- rcu_assign_pointer(sdata->deflink.default_beacon_key, key); ++ rcu_assign_pointer(link->default_beacon_key, key); + + ieee80211_debugfs_key_update_default(sdata); + } + +-void ieee80211_set_default_beacon_key(struct ieee80211_sub_if_data *sdata, ++void ieee80211_set_default_beacon_key(struct ieee80211_link_data *link, + int idx) + { +- mutex_lock(&sdata->local->key_mtx); +- __ieee80211_set_default_beacon_key(sdata, idx); +- mutex_unlock(&sdata->local->key_mtx); ++ mutex_lock(&link->sdata->local->key_mtx); ++ __ieee80211_set_default_beacon_key(link, idx); ++ mutex_unlock(&link->sdata->local->key_mtx); + } + + static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, +- struct sta_info *sta, +- bool pairwise, +- struct ieee80211_key *old, +- struct ieee80211_key *new) ++ struct ieee80211_link_data *link, ++ struct sta_info *sta, ++ bool pairwise, ++ struct ieee80211_key *old, ++ struct ieee80211_key *new) + { ++ struct link_sta_info *link_sta = sta ? &sta->deflink : NULL; ++ int link_id; + int idx; + int ret = 0; + bool defunikey, defmultikey, defmgmtkey, defbeaconkey; +@@ -448,13 +452,36 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, + + if (new) { + idx = new->conf.keyidx; +- list_add_tail_rcu(&new->list, &sdata->key_list); + is_wep = new->conf.cipher == WLAN_CIPHER_SUITE_WEP40 || + new->conf.cipher == WLAN_CIPHER_SUITE_WEP104; ++ link_id = new->conf.link_id; + } else { + idx = old->conf.keyidx; + is_wep = old->conf.cipher == WLAN_CIPHER_SUITE_WEP40 || + old->conf.cipher == WLAN_CIPHER_SUITE_WEP104; ++ link_id = old->conf.link_id; ++ } ++ ++ if (WARN(old && old->conf.link_id != link_id, ++ "old link ID %d doesn't match new link ID %d\n", ++ old->conf.link_id, link_id)) ++ return -EINVAL; ++ ++ if (link_id >= 0) { ++ if (!link) { ++ link = sdata_dereference(sdata->link[link_id], sdata); ++ if (!link) ++ return -ENOLINK; ++ } ++ ++ if (sta) { ++ link_sta = rcu_dereference_protected(sta->link[link_id], ++ lockdep_is_held(&sta->local->sta_mtx)); ++ if (!link_sta) ++ return -ENOLINK; ++ } ++ } else { ++ link = &sdata->deflink; + } + + if ((is_wep || pairwise) && idx >= NUM_DEFAULT_KEYS) +@@ -484,6 +511,9 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, + if (ret) + return ret; + ++ if (new) ++ list_add_tail_rcu(&new->list, &sdata->key_list); ++ + if (sta) { + if (pairwise) { + rcu_assign_pointer(sta->ptk[idx], new); +@@ -491,7 +521,7 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, + !(new->conf.flags & IEEE80211_KEY_FLAG_NO_AUTO_TX)) + _ieee80211_set_tx_key(new, true); + } else { +- rcu_assign_pointer(sta->deflink.gtk[idx], new); ++ rcu_assign_pointer(link_sta->gtk[idx], new); + } + /* Only needed for transition from no key -> key. + * Still triggers unnecessary when using Extended Key ID +@@ -505,39 +535,39 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, + sdata->default_unicast_key); + defmultikey = old && + old == key_mtx_dereference(sdata->local, +- sdata->deflink.default_multicast_key); ++ link->default_multicast_key); + defmgmtkey = old && + old == key_mtx_dereference(sdata->local, +- sdata->deflink.default_mgmt_key); ++ link->default_mgmt_key); + defbeaconkey = old && + old == key_mtx_dereference(sdata->local, +- sdata->deflink.default_beacon_key); ++ link->default_beacon_key); + + if (defunikey && !new) +- __ieee80211_set_default_key(sdata, -1, true, false); ++ __ieee80211_set_default_key(link, -1, true, false); + if (defmultikey && !new) +- __ieee80211_set_default_key(sdata, -1, false, true); ++ __ieee80211_set_default_key(link, -1, false, true); + if (defmgmtkey && !new) +- __ieee80211_set_default_mgmt_key(sdata, -1); ++ __ieee80211_set_default_mgmt_key(link, -1); + if (defbeaconkey && !new) +- __ieee80211_set_default_beacon_key(sdata, -1); ++ __ieee80211_set_default_beacon_key(link, -1); + + if (is_wep || pairwise) + rcu_assign_pointer(sdata->keys[idx], new); + else +- rcu_assign_pointer(sdata->deflink.gtk[idx], new); ++ rcu_assign_pointer(link->gtk[idx], new); + + if (defunikey && new) +- __ieee80211_set_default_key(sdata, new->conf.keyidx, ++ __ieee80211_set_default_key(link, new->conf.keyidx, + true, false); + if (defmultikey && new) +- __ieee80211_set_default_key(sdata, new->conf.keyidx, ++ __ieee80211_set_default_key(link, new->conf.keyidx, + false, true); + if (defmgmtkey && new) +- __ieee80211_set_default_mgmt_key(sdata, ++ __ieee80211_set_default_mgmt_key(link, + new->conf.keyidx); + if (defbeaconkey && new) +- __ieee80211_set_default_beacon_key(sdata, ++ __ieee80211_set_default_beacon_key(link, + new->conf.keyidx); + } + +@@ -570,6 +600,7 @@ ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, + */ + key->conf.flags = 0; + key->flags = 0; ++ key->conf.link_id = -1; + /* VLAN ID initialised to zero for non-vlan interfaces */ + key->conf.vlan_id = 0; + +@@ -801,9 +832,10 @@ static bool ieee80211_key_identical(struct ieee80211_sub_if_data *sdata, + } + + int ieee80211_key_link(struct ieee80211_key *key, +- struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_link_data *link, + struct sta_info *sta) + { ++ struct ieee80211_sub_if_data *sdata = link->sdata; + static atomic_t key_color = ATOMIC_INIT(0); + struct ieee80211_key *old_key = NULL; + int idx = key->conf.keyidx; +@@ -831,15 +863,24 @@ int ieee80211_key_link(struct ieee80211_key *key, + (old_key && old_key->conf.cipher != key->conf.cipher)) + goto out; + } else if (sta) { +- old_key = key_mtx_dereference(sdata->local, +- sta->deflink.gtk[idx]); ++ struct link_sta_info *link_sta = &sta->deflink; ++ int link_id = key->conf.link_id; ++ ++ if (link_id >= 0) { ++ link_sta = rcu_dereference_protected(sta->link[link_id], ++ lockdep_is_held(&sta->local->sta_mtx)); ++ if (!link_sta) ++ return -ENOLINK; ++ } ++ ++ old_key = key_mtx_dereference(sdata->local, link_sta->gtk[idx]); + } else { + if (idx < NUM_DEFAULT_KEYS) + old_key = key_mtx_dereference(sdata->local, + sdata->keys[idx]); + if (!old_key) + old_key = key_mtx_dereference(sdata->local, +- sdata->deflink.gtk[idx]); ++ link->gtk[idx]); + } + + /* Non-pairwise keys must also not switch the cipher on rekey */ +@@ -870,7 +911,7 @@ int ieee80211_key_link(struct ieee80211_key *key, + + increment_tailroom_need_count(sdata); + +- ret = ieee80211_key_replace(sdata, sta, pairwise, old_key, key); ++ ret = ieee80211_key_replace(sdata, link, sta, pairwise, old_key, key); + + if (!ret) { + ieee80211_debugfs_key_add(key); +@@ -894,9 +935,9 @@ void ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom) + * Replace key with nothingness if it was ever used. + */ + if (key->sdata) +- ieee80211_key_replace(key->sdata, key->sta, +- key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, +- key, NULL); ++ ieee80211_key_replace(key->sdata, NULL, key->sta, ++ key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, ++ key, NULL); + ieee80211_key_destroy(key, delay_tailroom); + } + +@@ -1023,15 +1064,45 @@ static void ieee80211_free_keys_iface(struct ieee80211_sub_if_data *sdata, + ieee80211_debugfs_key_remove_beacon_default(sdata); + + list_for_each_entry_safe(key, tmp, &sdata->key_list, list) { +- ieee80211_key_replace(key->sdata, key->sta, +- key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, +- key, NULL); ++ ieee80211_key_replace(key->sdata, NULL, key->sta, ++ key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, ++ key, NULL); + list_add_tail(&key->list, keys); + } + + ieee80211_debugfs_key_update_default(sdata); + } + ++void ieee80211_remove_link_keys(struct ieee80211_link_data *link, ++ struct list_head *keys) ++{ ++ struct ieee80211_sub_if_data *sdata = link->sdata; ++ struct ieee80211_local *local = sdata->local; ++ struct ieee80211_key *key, *tmp; ++ ++ mutex_lock(&local->key_mtx); ++ list_for_each_entry_safe(key, tmp, &sdata->key_list, list) { ++ if (key->conf.link_id != link->link_id) ++ continue; ++ ieee80211_key_replace(key->sdata, link, key->sta, ++ key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, ++ key, NULL); ++ list_add_tail(&key->list, keys); ++ } ++ mutex_unlock(&local->key_mtx); ++} ++ ++void ieee80211_free_key_list(struct ieee80211_local *local, ++ struct list_head *keys) ++{ ++ struct ieee80211_key *key, *tmp; ++ ++ mutex_lock(&local->key_mtx); ++ list_for_each_entry_safe(key, tmp, keys, list) ++ __ieee80211_key_destroy(key, false); ++ mutex_unlock(&local->key_mtx); ++} ++ + void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata, + bool force_synchronize) + { +@@ -1091,9 +1162,9 @@ void ieee80211_free_sta_keys(struct ieee80211_local *local, + key = key_mtx_dereference(local, sta->deflink.gtk[i]); + if (!key) + continue; +- ieee80211_key_replace(key->sdata, key->sta, +- key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, +- key, NULL); ++ ieee80211_key_replace(key->sdata, NULL, key->sta, ++ key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, ++ key, NULL); + __ieee80211_key_destroy(key, key->sdata->vif.type == + NL80211_IFTYPE_STATION); + } +@@ -1102,9 +1173,9 @@ void ieee80211_free_sta_keys(struct ieee80211_local *local, + key = key_mtx_dereference(local, sta->ptk[i]); + if (!key) + continue; +- ieee80211_key_replace(key->sdata, key->sta, +- key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, +- key, NULL); ++ ieee80211_key_replace(key->sdata, NULL, key->sta, ++ key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, ++ key, NULL); + __ieee80211_key_destroy(key, key->sdata->vif.type == + NL80211_IFTYPE_STATION); + } +@@ -1311,7 +1382,8 @@ ieee80211_gtk_rekey_add(struct ieee80211_vif *vif, + if (sdata->u.mgd.mfp != IEEE80211_MFP_DISABLED) + key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT; + +- err = ieee80211_key_link(key, sdata, NULL); ++ /* FIXME: this function needs to get a link ID */ ++ err = ieee80211_key_link(key, &sdata->deflink, NULL); + if (err) + return ERR_PTR(err); + +diff --git a/net/mac80211/key.h b/net/mac80211/key.h +index 7340faa..3855248 100644 +--- a/net/mac80211/key.h ++++ b/net/mac80211/key.h +@@ -22,6 +22,7 @@ + + struct ieee80211_local; + struct ieee80211_sub_if_data; ++struct ieee80211_link_data; + struct sta_info; + + /** +@@ -144,17 +145,21 @@ ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, + * to make it used, free old key. On failure, also free the new key. + */ + int ieee80211_key_link(struct ieee80211_key *key, +- struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_link_data *link, + struct sta_info *sta); + int ieee80211_set_tx_key(struct ieee80211_key *key); + void ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom); + void ieee80211_key_free_unused(struct ieee80211_key *key); +-void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx, ++void ieee80211_set_default_key(struct ieee80211_link_data *link, int idx, + bool uni, bool multi); +-void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, ++void ieee80211_set_default_mgmt_key(struct ieee80211_link_data *link, + int idx); +-void ieee80211_set_default_beacon_key(struct ieee80211_sub_if_data *sdata, ++void ieee80211_set_default_beacon_key(struct ieee80211_link_data *link, + int idx); ++void ieee80211_remove_link_keys(struct ieee80211_link_data *link, ++ struct list_head *keys); ++void ieee80211_free_key_list(struct ieee80211_local *local, ++ struct list_head *keys); + void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata, + bool force_synchronize); + void ieee80211_free_sta_keys(struct ieee80211_local *local, +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 8dcd67d..bc68124 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -1953,7 +1953,6 @@ static struct ieee80211_key * + ieee80211_rx_get_bigtk(struct ieee80211_rx_data *rx, int idx) + { + struct ieee80211_key *key = NULL; +- struct ieee80211_sub_if_data *sdata = rx->sdata; + int idx2; + + /* Make sure key gets set if either BIGTK key index is set so that +@@ -1972,14 +1971,14 @@ ieee80211_rx_get_bigtk(struct ieee80211_rx_data *rx, int idx) + idx2 = idx - 1; + } + +- if (rx->sta) +- key = rcu_dereference(rx->sta->deflink.gtk[idx]); ++ if (rx->link_sta) ++ key = rcu_dereference(rx->link_sta->gtk[idx]); + if (!key) +- key = rcu_dereference(sdata->deflink.gtk[idx]); +- if (!key && rx->sta) +- key = rcu_dereference(rx->sta->deflink.gtk[idx2]); ++ key = rcu_dereference(rx->link->gtk[idx]); ++ if (!key && rx->link_sta) ++ key = rcu_dereference(rx->link_sta->gtk[idx2]); + if (!key) +- key = rcu_dereference(sdata->deflink.gtk[idx2]); ++ key = rcu_dereference(rx->link->gtk[idx2]); + + return key; + } +@@ -2085,15 +2084,15 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) + if (mmie_keyidx < NUM_DEFAULT_KEYS || + mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) + return RX_DROP_MONITOR; /* unexpected BIP keyidx */ +- if (rx->sta) { ++ if (rx->link_sta) { + if (ieee80211_is_group_privacy_action(skb) && + test_sta_flag(rx->sta, WLAN_STA_MFP)) + return RX_DROP_MONITOR; + +- rx->key = rcu_dereference(rx->sta->deflink.gtk[mmie_keyidx]); ++ rx->key = rcu_dereference(rx->link_sta->gtk[mmie_keyidx]); + } + if (!rx->key) +- rx->key = rcu_dereference(rx->sdata->deflink.gtk[mmie_keyidx]); ++ rx->key = rcu_dereference(rx->link->gtk[mmie_keyidx]); + } else if (!ieee80211_has_protected(fc)) { + /* + * The frame was not protected, so skip decryption. However, we +@@ -2102,25 +2101,24 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) + * have been expected. + */ + struct ieee80211_key *key = NULL; +- struct ieee80211_sub_if_data *sdata = rx->sdata; + int i; + + if (ieee80211_is_beacon(fc)) { + key = ieee80211_rx_get_bigtk(rx, -1); + } else if (ieee80211_is_mgmt(fc) && + is_multicast_ether_addr(hdr->addr1)) { +- key = rcu_dereference(rx->sdata->deflink.default_mgmt_key); ++ key = rcu_dereference(rx->link->default_mgmt_key); + } else { +- if (rx->sta) { ++ if (rx->link_sta) { + for (i = 0; i < NUM_DEFAULT_KEYS; i++) { +- key = rcu_dereference(rx->sta->deflink.gtk[i]); ++ key = rcu_dereference(rx->link_sta->gtk[i]); + if (key) + break; + } + } + if (!key) { + for (i = 0; i < NUM_DEFAULT_KEYS; i++) { +- key = rcu_dereference(sdata->deflink.gtk[i]); ++ key = rcu_dereference(rx->link->gtk[i]); + if (key) + break; + } +@@ -2149,13 +2147,13 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) + return RX_DROP_UNUSABLE; + + /* check per-station GTK first, if multicast packet */ +- if (is_multicast_ether_addr(hdr->addr1) && rx->sta) +- rx->key = rcu_dereference(rx->sta->deflink.gtk[keyidx]); ++ if (is_multicast_ether_addr(hdr->addr1) && rx->link_sta) ++ rx->key = rcu_dereference(rx->link_sta->gtk[keyidx]); + + /* if not found, try default key */ + if (!rx->key) { + if (is_multicast_ether_addr(hdr->addr1)) +- rx->key = rcu_dereference(rx->sdata->deflink.gtk[keyidx]); ++ rx->key = rcu_dereference(rx->link->gtk[keyidx]); + if (!rx->key) + rx->key = rcu_dereference(rx->sdata->keys[keyidx]); + +@@ -5043,7 +5041,17 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx, + if (!link) + return true; + rx->link = link; ++ ++ if (rx->sta) { ++ rx->link_sta = ++ rcu_dereference(rx->sta->link[rx->link_id]); ++ if (!rx->link_sta) ++ return true; ++ } + } else { ++ if (rx->sta) ++ rx->link_sta = &rx->sta->deflink; ++ + rx->link = &sdata->deflink; + } + +diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c +index eab0871..7458c74 100644 +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -590,6 +590,51 @@ ieee80211_tx_h_check_control_port_protocol(struct ieee80211_tx_data *tx) + return TX_CONTINUE; + } + ++static struct ieee80211_key * ++ieee80211_select_link_key(struct ieee80211_tx_data *tx) ++{ ++ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; ++ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); ++ enum { ++ USE_NONE, ++ USE_MGMT_KEY, ++ USE_MCAST_KEY, ++ } which_key = USE_NONE; ++ struct ieee80211_link_data *link; ++ unsigned int link_id; ++ ++ if (ieee80211_is_group_privacy_action(tx->skb)) ++ which_key = USE_MCAST_KEY; ++ else if (ieee80211_is_mgmt(hdr->frame_control) && ++ is_multicast_ether_addr(hdr->addr1) && ++ ieee80211_is_robust_mgmt_frame(tx->skb)) ++ which_key = USE_MGMT_KEY; ++ else if (is_multicast_ether_addr(hdr->addr1)) ++ which_key = USE_MCAST_KEY; ++ else ++ return NULL; ++ ++ link_id = u32_get_bits(info->control.flags, IEEE80211_TX_CTRL_MLO_LINK); ++ if (link_id == IEEE80211_LINK_UNSPECIFIED) { ++ link = &tx->sdata->deflink; ++ } else { ++ link = rcu_dereference(tx->sdata->link[link_id]); ++ if (!link) ++ return NULL; ++ } ++ ++ switch (which_key) { ++ case USE_NONE: ++ break; ++ case USE_MGMT_KEY: ++ return rcu_dereference(link->default_mgmt_key); ++ case USE_MCAST_KEY: ++ return rcu_dereference(link->default_multicast_key); ++ } ++ ++ return NULL; ++} ++ + static ieee80211_tx_result debug_noinline + ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) + { +@@ -605,16 +650,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) + if (tx->sta && + (key = rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx]))) + tx->key = key; +- else if (ieee80211_is_group_privacy_action(tx->skb) && +- (key = rcu_dereference(tx->sdata->deflink.default_multicast_key))) +- tx->key = key; +- else if (ieee80211_is_mgmt(hdr->frame_control) && +- is_multicast_ether_addr(hdr->addr1) && +- ieee80211_is_robust_mgmt_frame(tx->skb) && +- (key = rcu_dereference(tx->sdata->deflink.default_mgmt_key))) +- tx->key = key; +- else if (is_multicast_ether_addr(hdr->addr1) && +- (key = rcu_dereference(tx->sdata->deflink.default_multicast_key))) ++ else if ((key = ieee80211_select_link_key(tx))) + tx->key = key; + else if (!is_multicast_ether_addr(hdr->addr1) && + (key = rcu_dereference(tx->sdata->default_unicast_key))) +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/677-11-wifi-cfg80211-add-link-id-to-txq-params.patch b/feeds/ipq95xx/mac80211/patches/qca/677-11-wifi-cfg80211-add-link-id-to-txq-params.patch new file mode 100644 index 000000000..cdbcfc6a5 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/677-11-wifi-cfg80211-add-link-id-to-txq-params.patch @@ -0,0 +1,69 @@ +From 1833500c8b15291d5def5c7c167b3b91d107738a Mon Sep 17 00:00:00 2001 +From: Shaul Triebitz +Date: Tue, 2 Aug 2022 15:22:42 +0300 +Subject: [PATCH] wifi: cfg80211: add link id to txq params + +The Tx queue parameters are per link, so add the link ID +from nl80211 parameters to the API. + +While at it, lock the wdev when calling into the driver +so it (and we) can check the link ID appropriately. + +Signed-off-by: Shaul Triebitz +Signed-off-by: Johannes Berg +--- + include/net/cfg80211.h | 2 ++ + net/wireless/nl80211.c | 17 +++++++++++++++-- + 2 files changed, 17 insertions(+), 2 deletions(-) + +diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h +index f8cd14d..952d460 100644 +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -2400,6 +2400,7 @@ struct ocb_setup { + * @cwmax: Maximum contention window [a value of the form 2^n-1 in the range + * 1..32767] + * @aifs: Arbitration interframe space [0..255] ++ * @link_id: link_id or -1 for non-MLD + */ + struct ieee80211_txq_params { + enum nl80211_ac ac; +@@ -2407,6 +2408,7 @@ struct ieee80211_txq_params { + u16 cwmin; + u16 cwmax; + u8 aifs; ++ int link_id; + }; + + /** +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index b838325..a873ba6 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -3615,8 +3615,21 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) + if (result) + goto out; + +- result = rdev_set_txq_params(rdev, netdev, +- &txq_params); ++ txq_params.link_id = ++ nl80211_link_id_or_invalid(info->attrs); ++ ++ wdev_lock(netdev->ieee80211_ptr); ++ if (txq_params.link_id >= 0 && ++ !(netdev->ieee80211_ptr->valid_links & ++ BIT(txq_params.link_id))) ++ result = -ENOLINK; ++ else if (txq_params.link_id >= 0 && ++ !netdev->ieee80211_ptr->valid_links) ++ result = -EINVAL; ++ else ++ result = rdev_set_txq_params(rdev, netdev, ++ &txq_params); ++ wdev_unlock(netdev->ieee80211_ptr); + if (result) + goto out; + } +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/677-12-wifi-mac80211-add-link-information-in-ieee80211_rx_s.patch b/feeds/ipq95xx/mac80211/patches/qca/677-12-wifi-mac80211-add-link-information-in-ieee80211_rx_s.patch new file mode 100644 index 000000000..d61e3d3cd --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/677-12-wifi-mac80211-add-link-information-in-ieee80211_rx_s.patch @@ -0,0 +1,220 @@ +From 5cd40b81f972ecd3822b9b4b4a91ffb071c262f2 Mon Sep 17 00:00:00 2001 +From: Vasanthakumar Thiagarajan +Date: Fri, 18 Nov 2022 17:28:38 +0530 +Subject: [PATCH] wifi: mac80211: add link information in ieee80211_rx_status + +In MLO, when the address translation from link to MLD is done +in fw/hw, it is necessary to be able to have some information +on the link on which the frame has been received. Extend the +rx API to include link_id and a valid flag in ieee80211_rx_status. +Also make chanes to mac80211 rx APIs to make use of the reported +link_id after sanity checks. + +Signed-off-by: Vasanthakumar Thiagarajan +Link: https://lore.kernel.org/r/20220817104213.2531-2-quic_vthiagar@quicinc.com +Signed-off-by: Johannes Berg +--- + include/net/mac80211.h | 7 +++- + net/mac80211/rx.c | 95 +++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 99 insertions(+), 3 deletions(-) + +diff --git a/include/net/mac80211.h b/include/net/mac80211.h +index 96b7593..7b8762b 100644 +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -1573,9 +1573,12 @@ enum mac80211_rx_encoding { + * @rx_flags: internal RX flags for mac80211 + * @ampdu_reference: A-MPDU reference number, must be a different value for + * each A-MPDU but the same for each subframe within one A-MPDU +- * @ampdu_delimiter_crc: A-MPDU delimiter CRC + * @zero_length_psdu_type: radiotap type of the 0-length PSDU + * @eht_ru: EHT RUm, from & enum nl80211_eht_ru_alloc ++ * @link_valid: if the link which is identified by @link_id is valid. This flag ++ * is set only when connection is MLO. ++ * @link_id: id of the link used to receive the packet. This is used along with ++ * @link_valid. + */ + struct ieee80211_rx_status { + u64 mactime; +@@ -1598,10 +1601,10 @@ struct ieee80211_rx_status { + s8 signal; + u8 chains; + s8 chain_signal[IEEE80211_MAX_CHAINS]; +- u8 ampdu_delimiter_crc; + u8 zero_length_psdu_type; + u8 eht_ru; + u8 eht_num_user; ++ u8 link_valid:1, link_id:4; + }; + + static inline u32 +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index bc68124..eeeaddf 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -4713,6 +4713,15 @@ void ieee80211_check_fast_rx_iface(struct ieee80211_sub_if_data *sdata) + mutex_unlock(&local->sta_mtx); + } + ++static bool ++ieee80211_rx_is_valid_sta_link_id(struct ieee80211_sta *sta, u8 link_id) ++{ ++ if (!sta->mlo) ++ return false; ++ ++ return !!(sta->valid_links & BIT(link_id)); ++} ++ + static void ieee80211_rx_8023(struct ieee80211_rx_data *rx, + struct ieee80211_fast_rx *fast_rx, + int orig_len) +@@ -5113,6 +5122,7 @@ static void __ieee80211_rx_handle_8023(struct ieee80211_hw *hw, + #endif + { + struct ieee80211_local *local = hw_to_local(hw); ++ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); + struct ieee80211_fast_rx *fast_rx; + struct ieee80211_rx_data rx; + +@@ -5133,7 +5143,31 @@ static void __ieee80211_rx_handle_8023(struct ieee80211_hw *hw, + + rx.sta = container_of(pubsta, struct sta_info, sta); + rx.sdata = rx.sta->sdata; +- rx.link = &rx.sdata->deflink; ++ ++ if (status->link_valid && ++ !ieee80211_rx_is_valid_sta_link_id(pubsta, status->link_id)) ++ goto drop; ++ ++ /* ++ * TODO: Should the frame be dropped if the right link_id is not ++ * available? Or may be it is fine in the current form to proceed with ++ * the frame processing because with frame being in 802.3 format, ++ * link_id is used only for stats purpose and updating the stats on ++ * the deflink is fine? ++ */ ++ if (status->link_valid) ++ rx.link_id = status->link_id; ++ ++ if (rx.link_id >= 0) { ++ struct ieee80211_link_data *link; ++ ++ link = rcu_dereference(rx.sdata->link[rx.link_id]); ++ if (!link) ++ goto drop; ++ rx.link = link; ++ } else { ++ rx.link = &rx.sdata->deflink; ++ } + + fast_rx = rcu_dereference(rx.sta->fast_rx); + if (!fast_rx) +@@ -5163,7 +5197,19 @@ static bool ieee80211_rx_for_interface(struct ieee80211_rx_data *rx, + rx->sta = link_sta->sta; + rx->link_id = link_sta->link_id; + } else { ++ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); ++ + rx->sta = sta_info_get_bss(rx->sdata, hdr->addr2); ++ if (rx->sta) { ++ if (status->link_valid && ++ !ieee80211_rx_is_valid_sta_link_id(&rx->sta->sta, ++ status->link_id)) ++ return false; ++ ++ rx->link_id = status->link_valid ? status->link_id : -1; ++ } else { ++ rx->link_id = -1; ++ } + } + + return ieee80211_prepare_and_rx_handle(rx, skb, consume); +@@ -5183,6 +5229,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, + #endif + { + struct ieee80211_local *local = hw_to_local(hw); ++ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); + struct ieee80211_sub_if_data *sdata; + struct ieee80211_hdr *hdr; + __le16 fc; +@@ -5227,10 +5274,39 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, + + if (ieee80211_is_data(fc)) { + struct sta_info *sta, *prev_sta; ++ u8 link_id = status->link_id; + + if (pubsta) { + rx.sta = container_of(pubsta, struct sta_info, sta); + rx.sdata = rx.sta->sdata; ++ ++ if (status->link_valid && ++ !ieee80211_rx_is_valid_sta_link_id(pubsta, link_id)) ++ goto out; ++ ++ if (status->link_valid) ++ rx.link_id = status->link_id; ++ ++ /* ++ * In MLO connection, fetch the link_id using addr2 ++ * when the driver does not pass link_id in status. ++ * When the address translation is already performed by ++ * driver/hw, the valid link_id must be passed in ++ * status. ++ */ ++ ++ if (!status->link_valid && pubsta->mlo) { ++ struct ieee80211_hdr *hdr = (void *)skb->data; ++ struct link_sta_info *link_sta; ++ ++ link_sta = link_sta_info_get_bss(rx.sdata, ++ hdr->addr2); ++ if (!link_sta) ++ goto out; ++ ++ rx.link_id = link_sta->link_id; ++ } ++ + if (ieee80211_prepare_and_rx_handle(&rx, skb, true)) + return; + goto out; +@@ -5244,6 +5320,13 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, + continue; + } + ++ if ((status->link_valid && ++ !ieee80211_rx_is_valid_sta_link_id(&prev_sta->sta, ++ link_id)) || ++ (!status->link_valid && prev_sta->sta.mlo)) ++ continue; ++ ++ rx.link_id = status->link_valid ? link_id : -1; + rx.sta = prev_sta; + rx.sdata = prev_sta->sdata; + ieee80211_prepare_and_rx_handle(&rx, skb, false); +@@ -5252,6 +5335,13 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, + } + + if (prev_sta) { ++ if ((status->link_valid && ++ !ieee80211_rx_is_valid_sta_link_id(&prev_sta->sta, ++ link_id)) || ++ (!status->link_valid && prev_sta->sta.mlo)) ++ goto out; ++ ++ rx.link_id = status->link_valid ? link_id : -1; + rx.sta = prev_sta; + rx.sdata = prev_sta->sdata; + +@@ -5421,6 +5511,9 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, + + status->rx_flags = 0; + ++ if (WARN_ON_ONCE(status->link_id >= IEEE80211_LINK_UNSPECIFIED)) ++ goto drop; ++ + /* + * Frames with failed FCS/PLCP checksum are not returned, + * all other frames are returned without radiotap header +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/677-13-wifi-mac80211-use-the-corresponding-link-for-stats-u.patch b/feeds/ipq95xx/mac80211/patches/qca/677-13-wifi-mac80211-use-the-corresponding-link-for-stats-u.patch new file mode 100644 index 000000000..8e82f13b6 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/677-13-wifi-mac80211-use-the-corresponding-link-for-stats-u.patch @@ -0,0 +1,96 @@ +From 2ebcf0e4674473b89dc8d38633e8c3a567898865 Mon Sep 17 00:00:00 2001 +From: Vasanthakumar Thiagarajan +Date: Fri, 18 Nov 2022 17:32:24 +0530 +Subject: [PATCH] wifi: mac80211: use the corresponding link for stats update + +With link_id reported in rx_status for MLO connection, do the +stats update on the appropriate link instead of always deflink. + +Signed-off-by: Vasanthakumar Thiagarajan +Link: https://lore.kernel.org/r/20220817104213.2531-3-quic_vthiagar@quicinc.com +Signed-off-by: Johannes Berg +--- + net/mac80211/rx.c | 35 +++++++++++++++++++++++++++++------ + 1 file changed, 29 insertions(+), 6 deletions(-) + +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index eeeaddf..36cda3b 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -4729,19 +4729,30 @@ static void ieee80211_rx_8023(struct ieee80211_rx_data *rx, + struct ieee80211_sta_rx_stats *stats; + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); + struct sta_info *sta = rx->sta; ++ struct link_sta_info *link_sta; + struct sk_buff *skb = rx->skb; + void *sa = skb->data + ETH_ALEN; + void *da = skb->data; + +- stats = &sta->deflink.rx_stats; ++ if (rx->link_id >= 0) { ++ link_sta = rcu_dereference(sta->link[rx->link_id]); ++ if (WARN_ON_ONCE(!link_sta)) { ++ dev_kfree_skb(rx->skb); ++ return; ++ } ++ } else { ++ link_sta = &sta->deflink; ++ } ++ ++ stats = &link_sta->rx_stats; + if (fast_rx->uses_rss) +- stats = this_cpu_ptr(sta->deflink.pcpu_rx_stats); ++ stats = this_cpu_ptr(link_sta->pcpu_rx_stats); + + /* statistics part of ieee80211_rx_h_sta_process() */ + if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) { + stats->last_signal = status->signal; + if (!fast_rx->uses_rss) +- ewma_signal_add(&sta->deflink.rx_stats_avg.signal, ++ ewma_signal_add(&link_sta->rx_stats_avg.signal, + -status->signal); + } + +@@ -4757,7 +4768,7 @@ static void ieee80211_rx_8023(struct ieee80211_rx_data *rx, + + stats->chain_signal_last[i] = signal; + if (!fast_rx->uses_rss) +- ewma_signal_add(&sta->deflink.rx_stats_avg.chain_signal[i], ++ ewma_signal_add(&link_sta->rx_stats_avg.chain_signal[i], + -signal); + } + } +@@ -4841,7 +4852,8 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx, + u8 da[ETH_ALEN]; + u8 sa[ETH_ALEN]; + } addrs __aligned(2); +- struct ieee80211_sta_rx_stats *stats = &sta->deflink.rx_stats; ++ struct link_sta_info *link_sta; ++ struct ieee80211_sta_rx_stats *stats; + struct ieee80211s_hdr *mesh_hdr; + struct mesh_path *mppath; + u8 da_offs = fast_rx->da_offs, sa_offs = fast_rx->sa_offs; +@@ -5001,8 +5013,19 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx, + return true; + drop: + dev_kfree_skb(skb); ++ ++ if (rx->link_id >= 0) { ++ link_sta = rcu_dereference(sta->link[rx->link_id]); ++ if (!link_sta) ++ return true; ++ } else { ++ link_sta = &sta->deflink; ++ } ++ + if (fast_rx->uses_rss) +- stats = this_cpu_ptr(sta->deflink.pcpu_rx_stats); ++ stats = this_cpu_ptr(link_sta->pcpu_rx_stats); ++ else ++ stats = &link_sta->rx_stats; + + stats->dropped++; + return true; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/677-14-wifi-mac80211-use-link-ID-for-MLO-in-queued-frames.patch b/feeds/ipq95xx/mac80211/patches/qca/677-14-wifi-mac80211-use-link-ID-for-MLO-in-queued-frames.patch new file mode 100644 index 000000000..950e0d581 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/677-14-wifi-mac80211-use-link-ID-for-MLO-in-queued-frames.patch @@ -0,0 +1,139 @@ +From 6a86504231243df1a7ab3a5cbab4cfbbde8b45bc Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Wed, 17 Aug 2022 21:57:19 +0200 +Subject: [PATCH] wifi: mac80211: use link ID for MLO in queued frames + +When queuing frames to an interface store the link ID we +determined (which possibly came from the driver in the +RX status in the first place) in the RX status, and use +it in the MLME code to send probe responses, beacons and +CSA frames to the right link. + +Signed-off-by: Johannes Berg +--- + net/mac80211/mlme.c | 8 ++++++++ + net/mac80211/rx.c | 26 +++++++++++++++++++------- + 2 files changed, 27 insertions(+), 7 deletions(-) + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index c66a6f3..0093977 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -5657,6 +5657,13 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, + + sdata_lock(sdata); + ++ if (rx_status->link_valid) { ++ link = sdata_dereference(sdata->link[rx_status->link_id], ++ sdata); ++ if (!link) ++ goto out; ++ } ++ + switch (fc & IEEE80211_FCTL_STYPE) { + case IEEE80211_STYPE_BEACON: + ieee80211_rx_mgmt_beacon(link, (void *)mgmt, +@@ -5733,6 +5740,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, + } + break; + } ++out: + sdata_unlock(sdata); + } + +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 36cda3b..78c322d 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -254,9 +254,19 @@ ieee80211_rx_radiotap_hdrlen(struct ieee80211_local *local, + } + + static void __ieee80211_queue_skb_to_iface(struct ieee80211_sub_if_data *sdata, ++ int link_id, + struct sta_info *sta, + struct sk_buff *skb) + { ++ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); ++ ++ if (link_id >= 0) { ++ status->link_valid = 1; ++ status->link_id = link_id; ++ } else { ++ status->link_valid = 0; ++ } ++ + skb_queue_tail(&sdata->skb_queue, skb); + ieee80211_queue_work(&sdata->local->hw, &sdata->work); + if (sta) +@@ -264,11 +274,12 @@ static void __ieee80211_queue_skb_to_iface(struct ieee80211_sub_if_data *sdata, + } + + static void ieee80211_queue_skb_to_iface(struct ieee80211_sub_if_data *sdata, ++ int link_id, + struct sta_info *sta, + struct sk_buff *skb) + { + skb->protocol = 0; +- __ieee80211_queue_skb_to_iface(sdata, sta, skb); ++ __ieee80211_queue_skb_to_iface(sdata, link_id, sta, skb); + } + + static void ieee80211_handle_mu_mimo_mon(struct ieee80211_sub_if_data *sdata, +@@ -311,7 +322,7 @@ static void ieee80211_handle_mu_mimo_mon(struct ieee80211_sub_if_data *sdata, + if (!skb) + return; + +- ieee80211_queue_skb_to_iface(sdata, NULL, skb); ++ ieee80211_queue_skb_to_iface(sdata, -1, NULL, skb); + } + + /* +@@ -1487,7 +1498,7 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx, + /* if this mpdu is fragmented - terminate rx aggregation session */ + sc = le16_to_cpu(hdr->seq_ctrl); + if (sc & IEEE80211_SCTL_FRAG) { +- ieee80211_queue_skb_to_iface(rx->sdata, NULL, skb); ++ ieee80211_queue_skb_to_iface(rx->sdata, rx->link_id, NULL, skb); + return; + } + +@@ -3240,7 +3251,8 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) + (tf->action_code == WLAN_TDLS_CHANNEL_SWITCH_REQUEST || + tf->action_code == WLAN_TDLS_CHANNEL_SWITCH_RESPONSE)) { + rx->skb->protocol = cpu_to_be16(ETH_P_TDLS); +- __ieee80211_queue_skb_to_iface(sdata, rx->sta, rx->skb); ++ __ieee80211_queue_skb_to_iface(sdata, rx->link_id, ++ rx->sta, rx->skb); + return RX_QUEUED; + } + } +@@ -3830,7 +3842,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) + return RX_QUEUED; + + queue: +- ieee80211_queue_skb_to_iface(sdata, rx->sta, rx->skb); ++ ieee80211_queue_skb_to_iface(sdata, rx->link_id, rx->sta, rx->skb); + return RX_QUEUED; + } + +@@ -3988,7 +4000,7 @@ ieee80211_rx_h_ext(struct ieee80211_rx_data *rx) + return RX_DROP_MONITOR; + + /* for now only beacons are ext, so queue them */ +- ieee80211_queue_skb_to_iface(sdata, rx->sta, rx->skb); ++ ieee80211_queue_skb_to_iface(sdata, rx->link_id, rx->sta, rx->skb); + + return RX_QUEUED; + } +@@ -4045,7 +4057,7 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) + return RX_DROP_MONITOR; + } + +- ieee80211_queue_skb_to_iface(sdata, rx->sta, rx->skb); ++ ieee80211_queue_skb_to_iface(sdata, rx->link_id, rx->sta, rx->skb); + + return RX_QUEUED; + } +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/677-15-wifi-mac80211-mlme-don-t-add-empty-EML-capabilities.patch b/feeds/ipq95xx/mac80211/patches/qca/677-15-wifi-mac80211-mlme-don-t-add-empty-EML-capabilities.patch new file mode 100644 index 000000000..c22296087 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/677-15-wifi-mac80211-mlme-don-t-add-empty-EML-capabilities.patch @@ -0,0 +1,48 @@ +From 55051ffe7f3d44875fb90d8fe9601ea0604c0186 Mon Sep 17 00:00:00 2001 +From: Mordechay Goodstein +Date: Sat, 30 Jul 2022 03:51:08 +0300 +Subject: [PATCH] wifi: mac80211: mlme: don't add empty EML capabilities + +Draft P802.11be_D2.1, section 35.3.17 states that the EML Capabilities +Field shouldn't be included in case the device doesn't have support for +EMLSR or EMLMR. + +Fixes: 81151ce462e5 ("wifi: mac80211: support MLO authentication/association with one link") +Signed-off-by: Mordechay Goodstein +Signed-off-by: Johannes Berg +--- + net/mac80211/mlme.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 0093977..5b5892b 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -1222,14 +1222,21 @@ static void ieee80211_assoc_add_ml_elem(struct ieee80211_sub_if_data *sdata, + ml_elem = skb_put(skb, sizeof(*ml_elem)); + ml_elem->control = + cpu_to_le16(IEEE80211_ML_CONTROL_TYPE_BASIC | +- IEEE80211_MLC_BASIC_PRES_EML_CAPA | + IEEE80211_MLC_BASIC_PRES_MLD_CAPA_OP); + common = skb_put(skb, sizeof(*common)); + common->len = sizeof(*common) + +- 2 + /* EML capabilities */ + 2; /* MLD capa/ops */ + memcpy(common->mld_mac_addr, sdata->vif.addr, ETH_ALEN); +- skb_put_data(skb, &eml_capa, sizeof(eml_capa)); ++ ++ /* add EML_CAPA only if needed, see Draft P802.11be_D2.1, 35.3.17 */ ++ if (eml_capa & ++ cpu_to_le16((IEEE80211_EML_CAP_EMLSR_SUPP | ++ IEEE80211_EML_CAP_EMLMR_SUPPORT))) { ++ common->len += 2; /* EML capabilities */ ++ ml_elem->control |= ++ cpu_to_le16(IEEE80211_MLC_BASIC_PRES_EML_CAPA); ++ skb_put_data(skb, &eml_capa, sizeof(eml_capa)); ++ } + /* need indication from userspace to support this */ + mld_capa_ops &= ~cpu_to_le16(IEEE80211_MLD_CAP_OP_TID_TO_LINK_MAP_NEG_SUPP); + skb_put_data(skb, &mld_capa_ops, sizeof(mld_capa_ops)); +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/677-16-wifi-mac80211-fix-control-port-frame-addressing.patch b/feeds/ipq95xx/mac80211/patches/qca/677-16-wifi-mac80211-fix-control-port-frame-addressing.patch new file mode 100644 index 000000000..74a715cb4 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/677-16-wifi-mac80211-fix-control-port-frame-addressing.patch @@ -0,0 +1,47 @@ +From c6ea8120d6eb238568a3f355fa7695453d56a47a Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Wed, 24 Aug 2022 12:30:16 +0200 +Subject: [PATCH] wifi: mac80211: fix control port frame addressing + +For an AP interface, when userspace specifieds the link ID to +transmit the control port frame on (in particular for the +initial 4-way-HS), due to the logic in ieee80211_build_hdr() +for a frame transmitted from/to an MLD, we currently build a +header with + + A1 = DA = MLD address of the peer MLD + A2 = local link address (!) + A3 = SA = local MLD address + +This clearly makes no sense, and leads to two problems: + - if the frame were encrypted (not true for the initial + 4-way-HS) the AAD would be calculated incorrectly + - if iTXQs are used, the frame is dropped by logic in + ieee80211_tx_dequeue() + +Fix the addressing, which fixes the first bullet, and the +second bullet for peer MLDs, I'll fix the second one for +non-MLD peers separately. + +Signed-off-by: Johannes Berg +--- + net/mac80211/tx.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c +index 7458c74..9018de8 100644 +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -2713,7 +2713,8 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata, + goto free; + } + memcpy(hdr.addr2, link->conf->addr, ETH_ALEN); +- } else if (link_id == IEEE80211_LINK_UNSPECIFIED) { ++ } else if (link_id == IEEE80211_LINK_UNSPECIFIED || ++ (sta && sta->sta.mlo)) { + memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN); + } else { + struct ieee80211_bss_conf *conf; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/677-17-wifi-mac80211-fix-potential-deadlock-in-ieee80211_ke.patch b/feeds/ipq95xx/mac80211/patches/qca/677-17-wifi-mac80211-fix-potential-deadlock-in-ieee80211_ke.patch new file mode 100644 index 000000000..4e03a9b8a --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/677-17-wifi-mac80211-fix-potential-deadlock-in-ieee80211_ke.patch @@ -0,0 +1,36 @@ +From 4396c5149aea506fdcf4caaefda9e0c80ed6edd7 Mon Sep 17 00:00:00 2001 +From: Sun Ke +Date: Sat, 27 Aug 2022 10:24:52 +0800 +Subject: [PATCH] wifi: mac80211: fix potential deadlock in + ieee80211_key_link() + +Add the missing unlock before return in the error handling case. + +Fixes: ccdde7c74ffd ("wifi: mac80211: properly implement MLO key handling") +Signed-off-by: Sun Ke +Link: https://lore.kernel.org/r/20220827022452.823381-1-sunke32@huawei.com +Signed-off-by: Johannes Berg +--- + net/mac80211/key.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/net/mac80211/key.c b/net/mac80211/key.c +index 6296dac..4d2ae2a 100644 +--- a/net/mac80211/key.c ++++ b/net/mac80211/key.c +@@ -869,8 +869,10 @@ int ieee80211_key_link(struct ieee80211_key *key, + if (link_id >= 0) { + link_sta = rcu_dereference_protected(sta->link[link_id], + lockdep_is_held(&sta->local->sta_mtx)); +- if (!link_sta) +- return -ENOLINK; ++ if (!link_sta) { ++ ret = -ENOLINK; ++ goto out; ++ } + } + + old_key = key_mtx_dereference(sdata->local, link_sta->gtk[idx]); +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/677-18-wifi-mac80211-use-correct-rx-link_sta-instead-of-def.patch b/feeds/ipq95xx/mac80211/patches/qca/677-18-wifi-mac80211-use-correct-rx-link_sta-instead-of-def.patch new file mode 100644 index 000000000..cd4462f15 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/677-18-wifi-mac80211-use-correct-rx-link_sta-instead-of-def.patch @@ -0,0 +1,225 @@ +From 3cd9ae67ecd07f4c8f9e680755580f4843c1e53a Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Fri, 2 Sep 2022 16:12:40 +0200 +Subject: [PATCH] wifi: mac80211: use correct rx link_sta instead of default + +Use rx->link_sta everywhere instead of accessing the default link. + +Signed-off-by: Benjamin Berg +Signed-off-by: Johannes Berg +--- + net/mac80211/rx.c | 69 ++++++++++++++++++++++++----------------------- + 1 file changed, 35 insertions(+), 34 deletions(-) + +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 78c322d..103c3db 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -1545,7 +1545,7 @@ ieee80211_rx_h_check_dup(struct ieee80211_rx_data *rx) + if (unlikely(ieee80211_has_retry(hdr->frame_control) && + rx->sta->last_seq_ctrl[rx->seqno_idx] == hdr->seq_ctrl)) { + I802_DEBUG_INC(rx->local->dot11FrameDuplicateCount); +- rx->sta->deflink.rx_stats.num_duplicates++; ++ rx->link_sta->rx_stats.num_duplicates++; + return RX_DROP_UNUSABLE; + } else if (!(status->flag & RX_FLAG_AMSDU_MORE)) { + rx->sta->last_seq_ctrl[rx->seqno_idx] = hdr->seq_ctrl; +@@ -1830,12 +1830,13 @@ static ieee80211_rx_result debug_noinline + ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) + { + struct sta_info *sta = rx->sta; ++ struct link_sta_info *link_sta = rx->link_sta; + struct sk_buff *skb = rx->skb; + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + int i; + +- if (!sta) ++ if (!sta || !link_sta) + return RX_CONTINUE; + + /* +@@ -1851,47 +1852,47 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) + NL80211_IFTYPE_ADHOC); + if (ether_addr_equal(bssid, rx->sdata->u.ibss.bssid) && + test_sta_flag(sta, WLAN_STA_AUTHORIZED)) { +- sta->deflink.rx_stats.last_rx = jiffies; ++ link_sta->rx_stats.last_rx = jiffies; + if (ieee80211_is_data(hdr->frame_control) && + !is_multicast_ether_addr(hdr->addr1)) +- sta->deflink.rx_stats.last_rate = ++ link_sta->rx_stats.last_rate = + sta_stats_encode_rate(status); + } + } else if (rx->sdata->vif.type == NL80211_IFTYPE_OCB) { +- sta->deflink.rx_stats.last_rx = jiffies; ++ link_sta->rx_stats.last_rx = jiffies; + } else if (!ieee80211_is_s1g_beacon(hdr->frame_control) && + !is_multicast_ether_addr(hdr->addr1)) { + /* + * Mesh beacons will update last_rx when if they are found to + * match the current local configuration when processed. + */ +- sta->deflink.rx_stats.last_rx = jiffies; ++ link_sta->rx_stats.last_rx = jiffies; + if (ieee80211_is_data(hdr->frame_control)) +- sta->deflink.rx_stats.last_rate = sta_stats_encode_rate(status); ++ link_sta->rx_stats.last_rate = sta_stats_encode_rate(status); + } + +- sta->deflink.rx_stats.fragments++; ++ link_sta->rx_stats.fragments++; + +- u64_stats_update_begin(&rx->sta->deflink.rx_stats.syncp); +- sta->deflink.rx_stats.bytes += rx->skb->len; +- u64_stats_update_end(&rx->sta->deflink.rx_stats.syncp); ++ u64_stats_update_begin(&link_sta->rx_stats.syncp); ++ link_sta->rx_stats.bytes += rx->skb->len; ++ u64_stats_update_end(&link_sta->rx_stats.syncp); + + if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) { +- sta->deflink.rx_stats.last_signal = status->signal; +- ewma_signal_add(&sta->deflink.rx_stats_avg.signal, ++ link_sta->rx_stats.last_signal = status->signal; ++ ewma_signal_add(&link_sta->rx_stats_avg.signal, + -status->signal); + } + + if (status->chains) { +- sta->deflink.rx_stats.chains = status->chains; ++ link_sta->rx_stats.chains = status->chains; + for (i = 0; i < ARRAY_SIZE(status->chain_signal); i++) { + int signal = status->chain_signal[i]; + + if (!(status->chains & BIT(i))) + continue; + +- sta->deflink.rx_stats.chain_signal_last[i] = signal; +- ewma_signal_add(&sta->deflink.rx_stats_avg.chain_signal[i], ++ link_sta->rx_stats.chain_signal_last[i] = signal; ++ ewma_signal_add(&link_sta->rx_stats_avg.chain_signal[i], + -signal); + } + } +@@ -1952,7 +1953,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) + * Update counter and free packet here to avoid + * counting this as a dropped packed. + */ +- sta->deflink.rx_stats.packets++; ++ link_sta->rx_stats.packets++; + dev_kfree_skb(rx->skb); + return RX_QUEUED; + } +@@ -2488,7 +2489,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) + out: + ieee80211_led_rx(rx->local); + if (rx->sta) +- rx->sta->deflink.rx_stats.packets++; ++ rx->link_sta->rx_stats.packets++; + return RX_CONTINUE; + } + +@@ -2850,9 +2851,9 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) + * for non-QoS-data frames. Here we know it's a data + * frame, so count MSDUs. + */ +- u64_stats_update_begin(&rx->sta->deflink.rx_stats.syncp); +- rx->sta->deflink.rx_stats.msdu[rx->seqno_idx]++; +- u64_stats_update_end(&rx->sta->deflink.rx_stats.syncp); ++ u64_stats_update_begin(&rx->link_sta->rx_stats.syncp); ++ rx->link_sta->rx_stats.msdu[rx->seqno_idx]++; ++ u64_stats_update_end(&rx->link_sta->rx_stats.syncp); + } + + if ((sdata->vif.type == NL80211_IFTYPE_AP || +@@ -3560,7 +3561,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) + switch (mgmt->u.action.category) { + case WLAN_CATEGORY_HT: + /* reject HT action frames from stations not supporting HT */ +- if (!rx->sta->sta.deflink.ht_cap.ht_supported) ++ if (!rx->link_sta->pub->ht_cap.ht_supported) + goto invalid; + + if (sdata->vif.type != NL80211_IFTYPE_STATION && +@@ -3624,26 +3625,26 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) + struct sta_opmode_info sta_opmode = {}; + + /* If it doesn't support 40 MHz it can't change ... */ +- if (!(rx->sta->sta.deflink.ht_cap.cap & ++ if (!(rx->link_sta->pub->ht_cap.cap & + IEEE80211_HT_CAP_SUP_WIDTH_20_40)) + goto handled; + + if (chanwidth == IEEE80211_HT_CHANWIDTH_20MHZ) + max_bw = IEEE80211_STA_RX_BW_20; + else +- max_bw = ieee80211_sta_cap_rx_bw(&rx->sta->deflink); ++ max_bw = ieee80211_sta_cap_rx_bw(rx->link_sta); + + /* set cur_max_bandwidth and recalc sta bw */ +- rx->sta->deflink.cur_max_bandwidth = max_bw; +- new_bw = ieee80211_sta_cur_vht_bw(&rx->sta->deflink); ++ rx->link_sta->cur_max_bandwidth = max_bw; ++ new_bw = ieee80211_sta_cur_vht_bw(rx->link_sta); + +- if (rx->sta->sta.deflink.bandwidth == new_bw) ++ if (rx->link_sta->pub->bandwidth == new_bw) + goto handled; + +- rx->sta->sta.deflink.bandwidth = new_bw; ++ rx->link_sta->pub->bandwidth = new_bw; + sband = rx->local->hw.wiphy->bands[status->band]; + sta_opmode.bw = +- ieee80211_sta_rx_bw_to_chan_width(&rx->sta->deflink); ++ ieee80211_sta_rx_bw_to_chan_width(rx->link_sta); + sta_opmode.changed = STA_OPMODE_MAX_BW_CHANGED; + + rate_control_rate_update(local, sband, rx->sta, 0, +@@ -3837,7 +3838,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) + + handled: + if (rx->sta) +- rx->sta->deflink.rx_stats.packets++; ++ rx->link_sta->rx_stats.packets++; + dev_kfree_skb(rx->skb); + return RX_QUEUED; + +@@ -3881,7 +3882,7 @@ ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx) + + if (cfg80211_rx_mgmt_ext(&rx->sdata->wdev, &info)) { + if (rx->sta) +- rx->sta->deflink.rx_stats.packets++; ++ rx->link_sta->rx_stats.packets++; + dev_kfree_skb(rx->skb); + return RX_QUEUED; + } +@@ -3919,7 +3920,7 @@ ieee80211_rx_h_action_post_userspace(struct ieee80211_rx_data *rx) + + handled: + if (rx->sta) +- rx->sta->deflink.rx_stats.packets++; ++ rx->link_sta->rx_stats.packets++; + dev_kfree_skb(rx->skb); + return RX_QUEUED; + } +@@ -4139,7 +4140,7 @@ static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx, + case RX_DROP_MONITOR: + I802_DEBUG_INC(rx->sdata->local->rx_handlers_drop); + if (rx->sta) +- rx->sta->deflink.rx_stats.dropped++; ++ rx->link_sta->rx_stats.dropped++; + fallthrough; + case RX_CONTINUE: { + struct ieee80211_rate *rate = NULL; +@@ -4158,7 +4159,7 @@ static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx, + case RX_DROP_UNUSABLE: + I802_DEBUG_INC(rx->sdata->local->rx_handlers_drop); + if (rx->sta) +- rx->sta->deflink.rx_stats.dropped++; ++ rx->link_sta->rx_stats.dropped++; + dev_kfree_skb(rx->skb); + break; + case RX_QUEUED: +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/677-19-wifi-mac80211-maintain-link_id-in-link_sta.patch b/feeds/ipq95xx/mac80211/patches/qca/677-19-wifi-mac80211-maintain-link_id-in-link_sta.patch new file mode 100644 index 000000000..ea83b4a2f --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/677-19-wifi-mac80211-maintain-link_id-in-link_sta.patch @@ -0,0 +1,49 @@ +From 4d9d59181a0f745526877da463992d1fd2cc3fbc Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Fri, 19 Aug 2022 13:12:38 +0200 +Subject: [PATCH] wifi: mac80211: maintain link_id in link_sta + +To helper drivers if they e.g. have a lookup of the link_sta +pointer, add the link ID to the link_sta structure. + +Signed-off-by: Johannes Berg +--- + include/net/mac80211.h | 2 ++ + net/mac80211/sta_info.c | 1 + + 2 files changed, 3 insertions(+) + +diff --git a/include/net/mac80211.h b/include/net/mac80211.h +index 7b8762b..a52abde 100644 +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -2250,6 +2250,7 @@ struct ieee80211_sta_txpwr { + * @addr: MAC address of the Link STA. For non-MLO STA this is same as the addr + * in ieee80211_sta. For MLO Link STA this addr can be same or different + * from addr in ieee80211_sta (representing MLD STA addr) ++ * @link_id: the link ID for this link STA (0 for deflink) + * @supp_rates: Bitmap of supported rates + * @ht_cap: HT capabilities of this STA; restricted to our own capabilities + * @vht_cap: VHT capabilities of this STA; restricted to our own capabilities +@@ -2267,6 +2268,7 @@ struct ieee80211_sta_txpwr { + */ + struct ieee80211_link_sta { + u8 addr[ETH_ALEN]; ++ u8 link_id; + + u32 supp_rates[NUM_NL80211_BANDS]; + struct ieee80211_sta_ht_cap ht_cap; +diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c +index 3822665..6bff796 100644 +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -477,6 +477,7 @@ static void sta_info_add_link(struct sta_info *sta, + link_info->sta = sta; + link_info->link_id = link_id; + link_info->pub = link_sta; ++ link_sta->link_id = link_id; + rcu_assign_pointer(sta->link[link_id], link_info); + rcu_assign_pointer(sta->sta.link[link_id], link_sta); + } +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/677-20-wifi-mac80211-make-smps_mode-per-link.patch b/feeds/ipq95xx/mac80211/patches/qca/677-20-wifi-mac80211-make-smps_mode-per-link.patch new file mode 100644 index 000000000..c888cd58f --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/677-20-wifi-mac80211-make-smps_mode-per-link.patch @@ -0,0 +1,274 @@ +From 04a7a8ff5e38b76139d40c775279d44d0e5426df Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Fri, 18 Nov 2022 17:56:47 +0530 +Subject: [PATCH] wifi: mac80211: make smps_mode per-link + +The SMPS power save mode needs to be per-link rather than being shared +for all links. As such, move it into struct ieee80211_link_sta. + +Signed-off-by: Benjamin Berg +Signed-off-by: Johannes Berg +Signed-off-by: Sriram R +--- + drivers/net/wireless/ath/ath10k/mac.c | 6 +++--- + drivers/net/wireless/ath/ath11k/mac.c | 6 +++--- + drivers/net/wireless/ath/ath12k/mac.c | 6 +++--- + drivers/net/wireless/ath/ath9k/xmit.c | 2 +- + include/net/mac80211.h | 4 ++-- + net/mac80211/he.c | 4 ++-- + net/mac80211/ht.c | 7 ++++--- + net/mac80211/rc80211_minstrel_ht.c | 6 +++--- + net/mac80211/rx.c | 4 ++-- + net/mac80211/sta_info.c | 3 ++- + 10 files changed, 25 insertions(+), 23 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c +index 8f295f4..93fa331 100644 +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -8523,7 +8523,7 @@ static void ath10k_sta_rc_update(struct ieee80211_hw *hw, + "mac sta rc update for %pM changed %08x bw %d nss %d smps %d\n", + sta->addr, changed, sta->deflink.bandwidth, + sta->deflink.rx_nss, +- sta->smps_mode); ++ sta->deflink.smps_mode); + + if (changed & IEEE80211_RC_BW_CHANGED) { + bw = WMI_PEER_CHWIDTH_20MHZ; +@@ -8557,7 +8557,7 @@ static void ath10k_sta_rc_update(struct ieee80211_hw *hw, + if (changed & IEEE80211_RC_SMPS_CHANGED) { + smps = WMI_PEER_SMPS_PS_NONE; + +- switch (sta->smps_mode) { ++ switch (sta->deflink.smps_mode) { + case IEEE80211_SMPS_AUTOMATIC: + case IEEE80211_SMPS_OFF: + smps = WMI_PEER_SMPS_PS_NONE; +@@ -8570,7 +8570,7 @@ static void ath10k_sta_rc_update(struct ieee80211_hw *hw, + break; + case IEEE80211_SMPS_NUM_MODES: + ath10k_warn(ar, "Invalid smps %d in sta rc update for %pM\n", +- sta->smps_mode, sta->addr); ++ sta->deflink.smps_mode, sta->addr); + smps = WMI_PEER_SMPS_PS_NONE; + break; + } +diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c +index a8323a9..f1197e3 100644 +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -6386,7 +6386,7 @@ static void ath11k_mac_op_sta_rc_update(struct ieee80211_hw *hw, + "mac sta rc update for %pM changed %08x bw %d nss %d smps %d\n", + sta->addr, changed, sta->deflink.bandwidth, + sta->deflink.rx_nss, +- sta->smps_mode); ++ sta->deflink.smps_mode); + + spin_lock_bh(&ar->data_lock); + +@@ -6423,7 +6423,7 @@ static void ath11k_mac_op_sta_rc_update(struct ieee80211_hw *hw, + if (changed & IEEE80211_RC_SMPS_CHANGED) { + smps = WMI_PEER_SMPS_PS_NONE; + +- switch (sta->smps_mode) { ++ switch (sta->deflink.smps_mode) { + case IEEE80211_SMPS_AUTOMATIC: + case IEEE80211_SMPS_OFF: + smps = WMI_PEER_SMPS_PS_NONE; +@@ -6436,7 +6436,7 @@ static void ath11k_mac_op_sta_rc_update(struct ieee80211_hw *hw, + break; + default: + ath11k_warn(ar->ab, "Invalid smps %d in sta rc update for %pM\n", +- sta->smps_mode, sta->addr); ++ sta->deflink.smps_mode, sta->addr); + smps = WMI_PEER_SMPS_PS_NONE; + break; + } +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index e643236..a702420 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -6519,7 +6519,7 @@ static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw, + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, + "mac sta rc update for %pM changed %08x bw %d nss %d smps %d\n", + arsta->addr, changed, sta->deflink.bandwidth, sta->deflink.rx_nss, +- sta->smps_mode); ++ sta->deflink.smps_mode); + + spin_lock_bh(&ar->data_lock); + +@@ -6559,7 +6559,7 @@ static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw, + if (changed & IEEE80211_RC_SMPS_CHANGED) { + smps = WMI_PEER_SMPS_PS_NONE; + +- switch (sta->smps_mode) { ++ switch (sta->deflink.smps_mode) { + case IEEE80211_SMPS_AUTOMATIC: + case IEEE80211_SMPS_OFF: + smps = WMI_PEER_SMPS_PS_NONE; +@@ -6572,7 +6572,7 @@ static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw, + break; + default: + ath12k_warn(ar->ab, "Invalid smps %d in sta rc update for %pM\n", +- sta->smps_mode, arsta->addr); ++ sta->deflink.smps_mode, arsta->addr); + smps = WMI_PEER_SMPS_PS_NONE; + break; + } +diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c +index 2a1af09..36cd071 100644 +--- a/drivers/net/wireless/ath/ath9k/xmit.c ++++ b/drivers/net/wireless/ath/ath9k/xmit.c +@@ -2160,7 +2160,7 @@ static void setup_frame_info(struct ieee80211_hw *hw, + fi->keyix = an->ps_key; + else + fi->keyix = ATH9K_TXKEYIX_INVALID; +- fi->dyn_smps = sta && sta->smps_mode == IEEE80211_SMPS_DYNAMIC; ++ fi->dyn_smps = sta && sta->deflink.smps_mode == IEEE80211_SMPS_DYNAMIC; + fi->keytype = keytype; + fi->framelen = framelen; + fi->tx_power = txpower; +diff --git a/include/net/mac80211.h b/include/net/mac80211.h +index a52abde..c13fdca 100644 +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -2251,6 +2251,7 @@ struct ieee80211_sta_txpwr { + * in ieee80211_sta. For MLO Link STA this addr can be same or different + * from addr in ieee80211_sta (representing MLD STA addr) + * @link_id: the link ID for this link STA (0 for deflink) ++ * @smps_mode: current SMPS mode (off, static or dynamic) + * @supp_rates: Bitmap of supported rates + * @ht_cap: HT capabilities of this STA; restricted to our own capabilities + * @vht_cap: VHT capabilities of this STA; restricted to our own capabilities +@@ -2269,6 +2270,7 @@ struct ieee80211_sta_txpwr { + struct ieee80211_link_sta { + u8 addr[ETH_ALEN]; + u8 link_id; ++ enum ieee80211_smps_mode smps_mode; + + u32 supp_rates[NUM_NL80211_BANDS]; + struct ieee80211_sta_ht_cap ht_cap; +@@ -2308,7 +2310,6 @@ struct ieee80211_link_sta { + * if wme is supported. The bits order is like in + * IEEE80211_WMM_IE_STA_QOSINFO_AC_*. + * @max_sp: max Service Period. Only valid if wme is supported. +- * @smps_mode: current SMPS mode (off, static or dynamic) + * @rates: rate control selection table + * @tdls: indicates whether the STA is a TDLS peer + * @tdls_initiator: indicates the STA is an initiator of the TDLS link. Only +@@ -2343,7 +2344,6 @@ struct ieee80211_sta { + bool wme; + u8 uapsd_queues; + u8 max_sp; +- enum ieee80211_smps_mode smps_mode; + struct ieee80211_sta_rates __rcu *rates; + bool tdls; + bool tdls_initiator; +diff --git a/net/mac80211/he.c b/net/mac80211/he.c +index 08f92dc..89d42cc 100644 +--- a/net/mac80211/he.c ++++ b/net/mac80211/he.c +@@ -31,9 +31,9 @@ ieee80211_update_from_he_6ghz_capa(const struct ieee80211_he_6ghz_capa *he_6ghz_ + break; + } + +- sta->sta.smps_mode = smps_mode; ++ link_sta->pub->smps_mode = smps_mode; + } else { +- sta->sta.smps_mode = IEEE80211_SMPS_OFF; ++ link_sta->pub->smps_mode = IEEE80211_SMPS_OFF; + } + + switch (le16_get_bits(he_6ghz_capa->capa, +diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c +index ba1689b..45c4c8e 100644 +--- a/net/mac80211/ht.c ++++ b/net/mac80211/ht.c +@@ -300,12 +300,13 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, + break; + } + +- if (smps_mode != sta->sta.smps_mode) ++ if (smps_mode != link_sta->pub->smps_mode) + changed = true; +- sta->sta.smps_mode = smps_mode; ++ link_sta->pub->smps_mode = smps_mode; + } else { +- sta->sta.smps_mode = IEEE80211_SMPS_OFF; ++ link_sta->pub->smps_mode = IEEE80211_SMPS_OFF; + } ++ + return changed; + } + +diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c +index 2a72b2f..06507a5 100644 +--- a/net/mac80211/rc80211_minstrel_ht.c ++++ b/net/mac80211/rc80211_minstrel_ht.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-only + /* + * Copyright (C) 2010-2013 Felix Fietkau +- * Copyright (C) 2019-2021 Intel Corporation ++ * Copyright (C) 2019-2022 Intel Corporation + */ + #include + #include +@@ -1478,7 +1478,7 @@ minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, + * - for fallback rates, to increase chances of getting through + */ + if (offset > 0 || +- (mi->sta->smps_mode == IEEE80211_SMPS_DYNAMIC && ++ (mi->sta->deflink.smps_mode == IEEE80211_SMPS_DYNAMIC && + group->streams > 1)) { + ratetbl->rate[offset].count = ratetbl->rate[offset].count_rts; + flags |= IEEE80211_TX_RC_USE_RTS_CTS; +@@ -1779,7 +1779,7 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, + nss = minstrel_mcs_groups[i].streams; + + /* Mark MCS > 7 as unsupported if STA is in static SMPS mode */ +- if (sta->smps_mode == IEEE80211_SMPS_STATIC && nss > 1) ++ if (sta->deflink.smps_mode == IEEE80211_SMPS_STATIC && nss > 1) + continue; + + /* HT rate */ +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 103c3db..fe4ad25 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -3601,9 +3601,9 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) + } + + /* if no change do nothing */ +- if (rx->sta->sta.smps_mode == smps_mode) ++ if (rx->link_sta->pub->smps_mode == smps_mode) + goto handled; +- rx->sta->sta.smps_mode = smps_mode; ++ rx->link_sta->pub->smps_mode = smps_mode; + sta_opmode.smps_mode = + ieee80211_smps_mode_to_smps_mode(smps_mode); + sta_opmode.changed = STA_OPMODE_SMPS_MODE_CHANGED; +diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c +index 6bff796..e485b55 100644 +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -480,6 +480,8 @@ static void sta_info_add_link(struct sta_info *sta, + link_sta->link_id = link_id; + rcu_assign_pointer(sta->link[link_id], link_info); + rcu_assign_pointer(sta->sta.link[link_id], link_sta); ++ ++ link_sta->smps_mode = IEEE80211_SMPS_OFF; + } + + static struct sta_info * +@@ -639,7 +641,6 @@ __sta_info_alloc(struct ieee80211_sub_if_data *sdata, + } + } + +- sta->sta.smps_mode = IEEE80211_SMPS_OFF; + sta->sta.max_rc_amsdu_len = IEEE80211_MAX_MPDU_LEN_HT_BA; + + sta->cparams.ce_threshold = CODEL_DISABLED_THRESHOLD; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/677-21-wifi-mac80211-move-link-code-to-a-new-file.patch b/feeds/ipq95xx/mac80211/patches/qca/677-21-wifi-mac80211-move-link-code-to-a-new-file.patch new file mode 100644 index 000000000..b437a0f10 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/677-21-wifi-mac80211-move-link-code-to-a-new-file.patch @@ -0,0 +1,595 @@ +From 184bbaf48db540e19f1926ed2aa9683aca3807ac Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Fri, 2 Sep 2022 16:12:37 +0200 +Subject: [PATCH] wifi: mac80211: move link code to a new file + +We probably should've done that originally, we already have +about 300 lines of code there, and will add more. Move all +the link code we wrote to a new file. + +Signed-off-by: Johannes Berg +--- + net/mac80211/Makefile | 1 + + net/mac80211/ieee80211_i.h | 14 +- + net/mac80211/iface.c | 251 ----------------------------------- + net/mac80211/link.c | 262 +++++++++++++++++++++++++++++++++++++ + 4 files changed, 274 insertions(+), 254 deletions(-) + create mode 100644 net/mac80211/link.c + +diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile +index 53ce57a..7025d4b 100644 +--- a/net/mac80211/Makefile ++++ b/net/mac80211/Makefile +@@ -16,6 +16,7 @@ mac80211-y := \ + s1g.o \ + ibss.o \ + iface.o \ ++ link.o \ + rate.o \ + michael.o \ + tkip.o \ +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index 501ec44..799aff2 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1975,9 +1975,6 @@ void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata); + int ieee80211_add_virtual_monitor(struct ieee80211_local *local); + void ieee80211_del_virtual_monitor(struct ieee80211_local *local); + +-int ieee80211_vif_set_links(struct ieee80211_sub_if_data *sdata, +- u16 new_links); +- + bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata); + void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata, + bool update_bss); +@@ -1988,6 +1985,17 @@ static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata) + return test_bit(SDATA_STATE_RUNNING, &sdata->state); + } + ++/* link handling */ ++void ieee80211_link_setup(struct ieee80211_link_data *link); ++void ieee80211_link_init(struct ieee80211_sub_if_data *sdata, ++ int link_id, ++ struct ieee80211_link_data *link, ++ struct ieee80211_bss_conf *link_conf); ++void ieee80211_link_stop(struct ieee80211_link_data *link); ++int ieee80211_vif_set_links(struct ieee80211_sub_if_data *sdata, ++ u16 new_links); ++void ieee80211_vif_clear_links(struct ieee80211_sub_if_data *sdata); ++ + /* tx handling */ + void ieee80211_clear_tx_pending(struct ieee80211_local *local); + void ieee80211_tx_pending(struct tasklet_struct *t); +diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c +index 2c02d76..c054f49 100644 +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -380,257 +380,6 @@ static int ieee80211_open(struct net_device *dev) + return err; + } + +-static void ieee80211_link_setup(struct ieee80211_link_data *link) +-{ +- if (link->sdata->vif.type == NL80211_IFTYPE_STATION) +- ieee80211_mgd_setup_link(link); +-} +- +-static void ieee80211_link_init(struct ieee80211_sub_if_data *sdata, +- int link_id, +- struct ieee80211_link_data *link, +- struct ieee80211_bss_conf *link_conf) +-{ +- bool deflink = link_id < 0; +- +- if (link_id < 0) +- link_id = 0; +- +- rcu_assign_pointer(sdata->vif.link_conf[link_id], link_conf); +- rcu_assign_pointer(sdata->link[link_id], link); +- +- link->sdata = sdata; +- link->link_id = link_id; +- link->conf = link_conf; +- link_conf->link_id = link_id; +- +- INIT_WORK(&link->csa_finalize_work, +- ieee80211_csa_finalize_work); +- INIT_WORK(&link->color_change_finalize_work, +- ieee80211_color_change_finalize_work); +- INIT_LIST_HEAD(&link->assigned_chanctx_list); +- INIT_LIST_HEAD(&link->reserved_chanctx_list); +- INIT_DELAYED_WORK(&link->dfs_cac_timer_work, +- ieee80211_dfs_cac_timer_work); +- +- if (!deflink) { +- switch (sdata->vif.type) { +- case NL80211_IFTYPE_AP: +- ether_addr_copy(link_conf->addr, +- sdata->wdev.links[link_id].addr); +- link_conf->bssid = link_conf->addr; +- WARN_ON(!(sdata->wdev.valid_links & BIT(link_id))); +- break; +- case NL80211_IFTYPE_STATION: +- /* station sets the bssid in ieee80211_mgd_setup_link */ +- break; +- default: +- WARN_ON(1); +- } +- } +-} +- +-static void ieee80211_link_stop(struct ieee80211_link_data *link) +-{ +- if (link->sdata->vif.type == NL80211_IFTYPE_STATION) +- ieee80211_mgd_stop_link(link); +- +- ieee80211_link_release_channel(link); +-} +- +-struct link_container { +- struct ieee80211_link_data data; +- struct ieee80211_bss_conf conf; +-}; +- +-static void ieee80211_free_links(struct ieee80211_sub_if_data *sdata, +- struct link_container **links) +-{ +- LIST_HEAD(keys); +- unsigned int link_id; +- +- for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) { +- if (!links[link_id]) +- continue; +- ieee80211_remove_link_keys(&links[link_id]->data, &keys); +- } +- +- synchronize_rcu(); +- +- ieee80211_free_key_list(sdata->local, &keys); +- +- for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) { +- if (!links[link_id]) +- continue; +- ieee80211_link_stop(&links[link_id]->data); +- kfree(links[link_id]); +- } +-} +- +-static int ieee80211_check_dup_link_addrs(struct ieee80211_sub_if_data *sdata) +-{ +- unsigned int i, j; +- +- for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) { +- struct ieee80211_link_data *link1; +- +- link1 = sdata_dereference(sdata->link[i], sdata); +- if (!link1) +- continue; +- for (j = i + 1; j < IEEE80211_MLD_MAX_NUM_LINKS; j++) { +- struct ieee80211_link_data *link2; +- +- link2 = sdata_dereference(sdata->link[j], sdata); +- if (!link2) +- continue; +- +- if (ether_addr_equal(link1->conf->addr, +- link2->conf->addr)) +- return -EALREADY; +- } +- } +- +- return 0; +-} +- +-static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata, +- struct link_container **to_free, +- u16 new_links) +-{ +- u16 old_links = sdata->vif.valid_links; +- unsigned long add = new_links & ~old_links; +- unsigned long rem = old_links & ~new_links; +- unsigned int link_id; +- int ret; +- struct link_container *links[IEEE80211_MLD_MAX_NUM_LINKS] = {}, *link; +- struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS]; +- struct ieee80211_link_data *old_data[IEEE80211_MLD_MAX_NUM_LINKS]; +- bool use_deflink = old_links == 0; /* set for error case */ +- +- sdata_assert_lock(sdata); +- +- memset(to_free, 0, sizeof(links)); +- +- if (old_links == new_links) +- return 0; +- +- /* if there were no old links, need to clear the pointers to deflink */ +- if (!old_links) +- rem |= BIT(0); +- +- /* allocate new link structures first */ +- for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) { +- link = kzalloc(sizeof(*link), GFP_KERNEL); +- if (!link) { +- ret = -ENOMEM; +- goto free; +- } +- links[link_id] = link; +- } +- +- /* keep track of the old pointers for the driver */ +- BUILD_BUG_ON(sizeof(old) != sizeof(sdata->vif.link_conf)); +- memcpy(old, sdata->vif.link_conf, sizeof(old)); +- /* and for us in error cases */ +- BUILD_BUG_ON(sizeof(old_data) != sizeof(sdata->link)); +- memcpy(old_data, sdata->link, sizeof(old_data)); +- +- /* grab old links to free later */ +- for_each_set_bit(link_id, &rem, IEEE80211_MLD_MAX_NUM_LINKS) { +- if (rcu_access_pointer(sdata->link[link_id]) != &sdata->deflink) { +- /* +- * we must have allocated the data through this path so +- * we know we can free both at the same time +- */ +- to_free[link_id] = container_of(rcu_access_pointer(sdata->link[link_id]), +- typeof(*links[link_id]), +- data); +- } +- +- RCU_INIT_POINTER(sdata->link[link_id], NULL); +- RCU_INIT_POINTER(sdata->vif.link_conf[link_id], NULL); +- } +- +- /* link them into data structures */ +- for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) { +- WARN_ON(!use_deflink && +- rcu_access_pointer(sdata->link[link_id]) == &sdata->deflink); +- +- link = links[link_id]; +- ieee80211_link_init(sdata, link_id, &link->data, &link->conf); +- ieee80211_link_setup(&link->data); +- } +- +- if (new_links == 0) +- ieee80211_link_init(sdata, -1, &sdata->deflink, +- &sdata->vif.bss_conf); +- +- sdata->vif.valid_links = new_links; +- +- ret = ieee80211_check_dup_link_addrs(sdata); +- if (!ret) { +- /* tell the driver */ +- ret = drv_change_vif_links(sdata->local, sdata, +- old_links, new_links, +- old); +- } +- +- if (ret) { +- /* restore config */ +- memcpy(sdata->link, old_data, sizeof(old_data)); +- memcpy(sdata->vif.link_conf, old, sizeof(old)); +- sdata->vif.valid_links = old_links; +- /* and free (only) the newly allocated links */ +- memset(to_free, 0, sizeof(links)); +- goto free; +- } +- +- /* use deflink/bss_conf again if and only if there are no more links */ +- use_deflink = new_links == 0; +- +- goto deinit; +-free: +- /* if we failed during allocation, only free all */ +- for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) { +- kfree(links[link_id]); +- links[link_id] = NULL; +- } +-deinit: +- if (use_deflink) +- ieee80211_link_init(sdata, -1, &sdata->deflink, +- &sdata->vif.bss_conf); +- return ret; +-} +- +-int ieee80211_vif_set_links(struct ieee80211_sub_if_data *sdata, +- u16 new_links) +-{ +- struct link_container *links[IEEE80211_MLD_MAX_NUM_LINKS]; +- int ret; +- +- ret = ieee80211_vif_update_links(sdata, links, new_links); +- ieee80211_free_links(sdata, links); +- +- return ret; +-} +- +-static void ieee80211_vif_clear_links(struct ieee80211_sub_if_data *sdata) +-{ +- struct link_container *links[IEEE80211_MLD_MAX_NUM_LINKS]; +- +- /* +- * The locking here is different because when we free links +- * in the station case we need to be able to cancel_work_sync() +- * something that also takes the lock. +- */ +- +- sdata_lock(sdata); +- ieee80211_vif_update_links(sdata, links, 0); +- sdata_unlock(sdata); +- +- ieee80211_free_links(sdata, links); +-} +- + static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_down) + { + struct ieee80211_local *local = sdata->local; +diff --git a/net/mac80211/link.c b/net/mac80211/link.c +new file mode 100644 +index 0000000..096f313 +--- /dev/null ++++ b/net/mac80211/link.c +@@ -0,0 +1,262 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * MLO link handling ++ * ++ * Copyright (C) 2022 Intel Corporation ++ */ ++#include ++#include ++#include ++#include "ieee80211_i.h" ++#include "driver-ops.h" ++ ++void ieee80211_link_setup(struct ieee80211_link_data *link) ++{ ++ if (link->sdata->vif.type == NL80211_IFTYPE_STATION) ++ ieee80211_mgd_setup_link(link); ++} ++ ++void ieee80211_link_init(struct ieee80211_sub_if_data *sdata, ++ int link_id, ++ struct ieee80211_link_data *link, ++ struct ieee80211_bss_conf *link_conf) ++{ ++ bool deflink = link_id < 0; ++ ++ if (link_id < 0) ++ link_id = 0; ++ ++ rcu_assign_pointer(sdata->vif.link_conf[link_id], link_conf); ++ rcu_assign_pointer(sdata->link[link_id], link); ++ ++ link->sdata = sdata; ++ link->link_id = link_id; ++ link->conf = link_conf; ++ link_conf->link_id = link_id; ++ ++ INIT_WORK(&link->csa_finalize_work, ++ ieee80211_csa_finalize_work); ++ INIT_WORK(&link->color_change_finalize_work, ++ ieee80211_color_change_finalize_work); ++ INIT_LIST_HEAD(&link->assigned_chanctx_list); ++ INIT_LIST_HEAD(&link->reserved_chanctx_list); ++ INIT_DELAYED_WORK(&link->dfs_cac_timer_work, ++ ieee80211_dfs_cac_timer_work); ++ ++ if (!deflink) { ++ switch (sdata->vif.type) { ++ case NL80211_IFTYPE_AP: ++ ether_addr_copy(link_conf->addr, ++ sdata->wdev.links[link_id].addr); ++ link_conf->bssid = link_conf->addr; ++ WARN_ON(!(sdata->wdev.valid_links & BIT(link_id))); ++ break; ++ case NL80211_IFTYPE_STATION: ++ /* station sets the bssid in ieee80211_mgd_setup_link */ ++ break; ++ default: ++ WARN_ON(1); ++ } ++ } ++} ++ ++void ieee80211_link_stop(struct ieee80211_link_data *link) ++{ ++ if (link->sdata->vif.type == NL80211_IFTYPE_STATION) ++ ieee80211_mgd_stop_link(link); ++ ++ ieee80211_link_release_channel(link); ++} ++ ++struct link_container { ++ struct ieee80211_link_data data; ++ struct ieee80211_bss_conf conf; ++}; ++ ++static void ieee80211_free_links(struct ieee80211_sub_if_data *sdata, ++ struct link_container **links) ++{ ++ LIST_HEAD(keys); ++ unsigned int link_id; ++ ++ for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) { ++ if (!links[link_id]) ++ continue; ++ ieee80211_remove_link_keys(&links[link_id]->data, &keys); ++ } ++ ++ synchronize_rcu(); ++ ++ ieee80211_free_key_list(sdata->local, &keys); ++ ++ for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) { ++ if (!links[link_id]) ++ continue; ++ ieee80211_link_stop(&links[link_id]->data); ++ kfree(links[link_id]); ++ } ++} ++ ++static int ieee80211_check_dup_link_addrs(struct ieee80211_sub_if_data *sdata) ++{ ++ unsigned int i, j; ++ ++ for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) { ++ struct ieee80211_link_data *link1; ++ ++ link1 = sdata_dereference(sdata->link[i], sdata); ++ if (!link1) ++ continue; ++ for (j = i + 1; j < IEEE80211_MLD_MAX_NUM_LINKS; j++) { ++ struct ieee80211_link_data *link2; ++ ++ link2 = sdata_dereference(sdata->link[j], sdata); ++ if (!link2) ++ continue; ++ ++ if (ether_addr_equal(link1->conf->addr, ++ link2->conf->addr)) ++ return -EALREADY; ++ } ++ } ++ ++ return 0; ++} ++ ++static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata, ++ struct link_container **to_free, ++ u16 new_links) ++{ ++ u16 old_links = sdata->vif.valid_links; ++ unsigned long add = new_links & ~old_links; ++ unsigned long rem = old_links & ~new_links; ++ unsigned int link_id; ++ int ret; ++ struct link_container *links[IEEE80211_MLD_MAX_NUM_LINKS] = {}, *link; ++ struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS]; ++ struct ieee80211_link_data *old_data[IEEE80211_MLD_MAX_NUM_LINKS]; ++ bool use_deflink = old_links == 0; /* set for error case */ ++ ++ sdata_assert_lock(sdata); ++ ++ memset(to_free, 0, sizeof(links)); ++ ++ if (old_links == new_links) ++ return 0; ++ ++ /* if there were no old links, need to clear the pointers to deflink */ ++ if (!old_links) ++ rem |= BIT(0); ++ ++ /* allocate new link structures first */ ++ for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) { ++ link = kzalloc(sizeof(*link), GFP_KERNEL); ++ if (!link) { ++ ret = -ENOMEM; ++ goto free; ++ } ++ links[link_id] = link; ++ } ++ ++ /* keep track of the old pointers for the driver */ ++ BUILD_BUG_ON(sizeof(old) != sizeof(sdata->vif.link_conf)); ++ memcpy(old, sdata->vif.link_conf, sizeof(old)); ++ /* and for us in error cases */ ++ BUILD_BUG_ON(sizeof(old_data) != sizeof(sdata->link)); ++ memcpy(old_data, sdata->link, sizeof(old_data)); ++ ++ /* grab old links to free later */ ++ for_each_set_bit(link_id, &rem, IEEE80211_MLD_MAX_NUM_LINKS) { ++ if (rcu_access_pointer(sdata->link[link_id]) != &sdata->deflink) { ++ /* ++ * we must have allocated the data through this path so ++ * we know we can free both at the same time ++ */ ++ to_free[link_id] = container_of(rcu_access_pointer(sdata->link[link_id]), ++ typeof(*links[link_id]), ++ data); ++ } ++ ++ RCU_INIT_POINTER(sdata->link[link_id], NULL); ++ RCU_INIT_POINTER(sdata->vif.link_conf[link_id], NULL); ++ } ++ ++ /* link them into data structures */ ++ for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) { ++ WARN_ON(!use_deflink && ++ rcu_access_pointer(sdata->link[link_id]) == &sdata->deflink); ++ ++ link = links[link_id]; ++ ieee80211_link_init(sdata, link_id, &link->data, &link->conf); ++ ieee80211_link_setup(&link->data); ++ } ++ ++ if (new_links == 0) ++ ieee80211_link_init(sdata, -1, &sdata->deflink, ++ &sdata->vif.bss_conf); ++ ++ sdata->vif.valid_links = new_links; ++ ++ ret = ieee80211_check_dup_link_addrs(sdata); ++ if (!ret) { ++ /* tell the driver */ ++ ret = drv_change_vif_links(sdata->local, sdata, ++ old_links, new_links, ++ old); ++ } ++ ++ if (ret) { ++ /* restore config */ ++ memcpy(sdata->link, old_data, sizeof(old_data)); ++ memcpy(sdata->vif.link_conf, old, sizeof(old)); ++ sdata->vif.valid_links = old_links; ++ /* and free (only) the newly allocated links */ ++ memset(to_free, 0, sizeof(links)); ++ goto free; ++ } ++ ++ /* use deflink/bss_conf again if and only if there are no more links */ ++ use_deflink = new_links == 0; ++ ++ goto deinit; ++free: ++ /* if we failed during allocation, only free all */ ++ for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) { ++ kfree(links[link_id]); ++ links[link_id] = NULL; ++ } ++deinit: ++ if (use_deflink) ++ ieee80211_link_init(sdata, -1, &sdata->deflink, ++ &sdata->vif.bss_conf); ++ return ret; ++} ++ ++int ieee80211_vif_set_links(struct ieee80211_sub_if_data *sdata, ++ u16 new_links) ++{ ++ struct link_container *links[IEEE80211_MLD_MAX_NUM_LINKS]; ++ int ret; ++ ++ ret = ieee80211_vif_update_links(sdata, links, new_links); ++ ieee80211_free_links(sdata, links); ++ ++ return ret; ++} ++ ++void ieee80211_vif_clear_links(struct ieee80211_sub_if_data *sdata) ++{ ++ struct link_container *links[IEEE80211_MLD_MAX_NUM_LINKS]; ++ ++ /* ++ * The locking here is different because when we free links ++ * in the station case we need to be able to cancel_work_sync() ++ * something that also takes the lock. ++ */ ++ ++ sdata_lock(sdata); ++ ieee80211_vif_update_links(sdata, links, 0); ++ sdata_unlock(sdata); ++ ++ ieee80211_free_links(sdata, links); ++} +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/677-22-wifi-mac80211-isolate-driver-from-inactive-links.patch b/feeds/ipq95xx/mac80211/patches/qca/677-22-wifi-mac80211-isolate-driver-from-inactive-links.patch new file mode 100644 index 000000000..8fa9a5833 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/677-22-wifi-mac80211-isolate-driver-from-inactive-links.patch @@ -0,0 +1,697 @@ +From e989305cd76c7a4ceee4fb0f024d419efeb10c93 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Fri, 18 Nov 2022 18:26:34 +0530 +Subject: [PATCH] wifi: mac80211: isolate driver from inactive links + +In order to let the driver select active links and properly +make multi-link connections, as a first step isolate the +driver from inactive links, and set the active links to be +only the association link for client-side interfaces. For +AP side nothing changes since APs always have to have all +their links active. + +To simplify things, update the for_each_sta_active_link() +API to include the appropriate vif pointer. + +This also implies not allocating a chanctx for an inactive +link, which requires a few more changes. + +Since we now no longer try to program multiple links to the +driver, remove the check in the MLME code. + +Signed-off-by: Johannes Berg +--- + include/net/mac80211.h | 30 +++---- + net/mac80211/chan.c | 6 ++ + net/mac80211/driver-ops.c | 172 ++++++++++++++++++++++++++++++++++++++ + net/mac80211/driver-ops.h | 167 ++++++------------------------------ + net/mac80211/key.c | 8 ++ + net/mac80211/link.c | 66 ++++++++++++--- + net/mac80211/mlme.c | 8 +- + net/mac80211/util.c | 2 +- + 8 files changed, 286 insertions(+), 173 deletions(-) + +diff --git a/include/net/mac80211.h b/include/net/mac80211.h +index c13fdca..685d5e8 100644 +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -1897,6 +1897,9 @@ struct ieee80211_vif_cfg { + * @link_conf: in case of MLD, the per-link BSS configuration, + * indexed by link ID + * @valid_links: bitmap of valid links, or 0 for non-MLO. ++ * @active_links: The bitmap of active links, or 0 for non-MLO. ++ * The driver shouldn't change this directly, but use the ++ * API calls meant for that purpose. + * @addr: address of this interface + * @p2p: indicates whether this AP or STA interface is a p2p + * interface, i.e. a GO or p2p-sta respectively +@@ -1932,7 +1935,7 @@ struct ieee80211_vif { + struct ieee80211_vif_cfg cfg; + struct ieee80211_bss_conf bss_conf; + struct ieee80211_bss_conf __rcu *link_conf[IEEE80211_MLD_MAX_NUM_LINKS]; +- u16 valid_links; ++ u16 valid_links, active_links; + u8 addr[ETH_ALEN] __aligned(2); + bool p2p; + +@@ -1963,12 +1966,11 @@ struct ieee80211_vif { + u8 drv_priv[] __aligned(sizeof(void *)); + }; + +-/* FIXME: for now loop over all the available links; later will be changed +- * to loop only over the active links. +- */ +-#define for_each_vif_active_link(vif, link, link_id) \ +- for (link_id = 0; link_id < ARRAY_SIZE((vif)->link_conf); link_id++) \ +- if ((link = rcu_dereference((vif)->link_conf[link_id]))) ++#define for_each_vif_active_link(vif, link, link_id) \ ++ for (link_id = 0; link_id < ARRAY_SIZE((vif)->link_conf); link_id++) \ ++ if ((!(vif)->active_links || \ ++ (vif)->active_links & BIT(link_id)) && \ ++ (link = rcu_dereference((vif)->link_conf[link_id]))) + + static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif) + { +@@ -2382,13 +2384,13 @@ struct ieee80211_sta { + u8 drv_priv[] __aligned(sizeof(void *)); + }; + +-/* FIXME: need to loop only over links which are active and check the actual +- * lock +- */ +-#define for_each_sta_active_link(sta, link_sta, link_id) \ +- for (link_id = 0; link_id < ARRAY_SIZE((sta)->link); link_id++) \ +- if (((link_sta) = rcu_dereference_protected((sta)->link[link_id],\ +- 1))) \ ++/* FIXME: check the locking correctly */ ++#define for_each_sta_active_link(vif, sta, link_sta, link_id) \ ++ for (link_id = 0; link_id < ARRAY_SIZE((sta)->link); link_id++) \ ++ if ((!(vif)->active_links || \ ++ (vif)->active_links & BIT(link_id)) && \ ++ ((link_sta) = rcu_dereference_protected((sta)->link[link_id],\ ++ 1))) + + /** + * enum sta_notify_cmd - sta notify command +diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c +index 778455b..527fb5a 100644 +--- a/net/mac80211/chan.c ++++ b/net/mac80211/chan.c +@@ -1811,6 +1811,12 @@ int ieee80211_link_use_channel(struct ieee80211_link_data *link, + + lockdep_assert_held(&local->mtx); + ++ if (sdata->vif.active_links && ++ !(sdata->vif.active_links & BIT(link->link_id))) { ++ ieee80211_link_update_chandef(link, chandef); ++ return 0; ++ } ++ + mutex_lock(&local->chanctx_mtx); + + ret = cfg80211_chandef_dfs_required(local->hw.wiphy, +diff --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c +index 08b3a1a..7a6bff0 100644 +--- a/net/mac80211/driver-ops.c ++++ b/net/mac80211/driver-ops.c +@@ -216,6 +216,10 @@ int drv_conf_tx(struct ieee80211_local *local, + if (!check_sdata_in_driver(sdata)) + return -EIO; + ++ if (sdata->vif.active_links && ++ !(sdata->vif.active_links & BIT(link->link_id))) ++ return 0; ++ + if (params->cw_min == 0 || params->cw_min > params->cw_max) { + /* + * If we can't configure hardware anyway, don't warn. We may +@@ -296,6 +300,60 @@ void drv_reset_tsf(struct ieee80211_local *local, + trace_drv_return_void(local); + } + ++int drv_assign_vif_chanctx(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_bss_conf *link_conf, ++ struct ieee80211_chanctx *ctx) ++{ ++ int ret = 0; ++ ++ drv_verify_link_exists(sdata, link_conf); ++ if (!check_sdata_in_driver(sdata)) ++ return -EIO; ++ ++ if (sdata->vif.active_links && ++ !(sdata->vif.active_links & BIT(link_conf->link_id))) ++ return 0; ++ ++ trace_drv_assign_vif_chanctx(local, sdata, link_conf, ctx); ++ if (local->ops->assign_vif_chanctx) { ++ WARN_ON_ONCE(!ctx->driver_present); ++ ret = local->ops->assign_vif_chanctx(&local->hw, ++ &sdata->vif, ++ link_conf, ++ &ctx->conf); ++ } ++ trace_drv_return_int(local, ret); ++ ++ return ret; ++} ++ ++void drv_unassign_vif_chanctx(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_bss_conf *link_conf, ++ struct ieee80211_chanctx *ctx) ++{ ++ might_sleep(); ++ ++ drv_verify_link_exists(sdata, link_conf); ++ if (!check_sdata_in_driver(sdata)) ++ return; ++ ++ if (sdata->vif.active_links && ++ !(sdata->vif.active_links & BIT(link_conf->link_id))) ++ return; ++ ++ trace_drv_unassign_vif_chanctx(local, sdata, link_conf, ctx); ++ if (local->ops->unassign_vif_chanctx) { ++ WARN_ON_ONCE(!ctx->driver_present); ++ local->ops->unassign_vif_chanctx(&local->hw, ++ &sdata->vif, ++ link_conf, ++ &ctx->conf); ++ } ++ trace_drv_return_void(local); ++} ++ + int drv_switch_vif_chanctx(struct ieee80211_local *local, + struct ieee80211_vif_chanctx_switch *vifs, + int n_vifs, enum ieee80211_chanctx_switch_mode mode) +@@ -390,3 +448,117 @@ void drv_config_mesh_offload_path(struct ieee80211_local *local, + /* TODO: trace event */ + } + #endif ++ ++void drv_link_info_changed(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_bss_conf *info, ++ int link_id, u64 changed) ++{ ++ might_sleep(); ++ ++ if (WARN_ON_ONCE(changed & (BSS_CHANGED_BEACON | ++ BSS_CHANGED_BEACON_ENABLED) && ++ sdata->vif.type != NL80211_IFTYPE_AP && ++ sdata->vif.type != NL80211_IFTYPE_ADHOC && ++ sdata->vif.type != NL80211_IFTYPE_MESH_POINT && ++ sdata->vif.type != NL80211_IFTYPE_OCB)) ++ return; ++ ++ if (WARN_ON_ONCE(sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE || ++ sdata->vif.type == NL80211_IFTYPE_NAN || ++ (sdata->vif.type == NL80211_IFTYPE_MONITOR && ++ !sdata->vif.bss_conf.mu_mimo_owner && ++ !(changed & BSS_CHANGED_TXPOWER)))) ++ return; ++ ++ if (!check_sdata_in_driver(sdata)) ++ return; ++ ++ if (sdata->vif.active_links && ++ !(sdata->vif.active_links & BIT(link_id))) ++ return; ++ ++ trace_drv_link_info_changed(local, sdata, info, changed); ++ if (local->ops->link_info_changed) ++ local->ops->link_info_changed(&local->hw, &sdata->vif, ++ info, changed); ++ else if (local->ops->bss_info_changed) ++ local->ops->bss_info_changed(&local->hw, &sdata->vif, ++ info, changed); ++ trace_drv_return_void(local); ++} ++ ++int drv_set_key(struct ieee80211_local *local, ++ enum set_key_cmd cmd, ++ struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_sta *sta, ++ struct ieee80211_key_conf *key) ++{ ++ int ret; ++ ++ might_sleep(); ++ ++ sdata = get_bss_sdata(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return -EIO; ++ ++ if (WARN_ON(key->link_id >= 0 && sdata->vif.active_links && ++ !(sdata->vif.active_links & BIT(key->link_id)))) ++ return -ENOLINK; ++ ++ trace_drv_set_key(local, cmd, sdata, sta, key); ++ ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key); ++ trace_drv_return_int(local, ret); ++ return ret; ++} ++ ++int drv_change_vif_links(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata, ++ u16 old_links, u16 new_links, ++ struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS]) ++{ ++ int ret = -EOPNOTSUPP; ++ ++ might_sleep(); ++ ++ if (!check_sdata_in_driver(sdata)) ++ return -EIO; ++ ++ if (old_links == new_links) ++ return 0; ++ ++ trace_drv_change_vif_links(local, sdata, old_links, new_links); ++ if (local->ops->change_vif_links) ++ ret = local->ops->change_vif_links(&local->hw, &sdata->vif, ++ old_links, new_links, old); ++ trace_drv_return_int(local, ret); ++ ++ return ret; ++} ++ ++int drv_change_sta_links(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_sta *sta, ++ u16 old_links, u16 new_links) ++{ ++ int ret = -EOPNOTSUPP; ++ ++ might_sleep(); ++ ++ if (!check_sdata_in_driver(sdata)) ++ return -EIO; ++ ++ old_links &= sdata->vif.active_links; ++ new_links &= sdata->vif.active_links; ++ ++ if (old_links == new_links) ++ return 0; ++ ++ trace_drv_change_sta_links(local, sdata, sta, old_links, new_links); ++ if (local->ops->change_sta_links) ++ ret = local->ops->change_sta_links(&local->hw, &sdata->vif, sta, ++ old_links, new_links); ++ trace_drv_return_int(local, ret); ++ ++ return ret; ++} +diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h +index ada16cf..7a3b7cc 100644 +--- a/net/mac80211/driver-ops.h ++++ b/net/mac80211/driver-ops.h +@@ -165,40 +165,10 @@ static inline void drv_vif_cfg_changed(struct ieee80211_local *local, + trace_drv_return_void(local); + } + +-static inline void drv_link_info_changed(struct ieee80211_local *local, +- struct ieee80211_sub_if_data *sdata, +- struct ieee80211_bss_conf *info, +- int link_id, u64 changed) +-{ +- might_sleep(); +- +- if (WARN_ON_ONCE(changed & (BSS_CHANGED_BEACON | +- BSS_CHANGED_BEACON_ENABLED) && +- sdata->vif.type != NL80211_IFTYPE_AP && +- sdata->vif.type != NL80211_IFTYPE_ADHOC && +- sdata->vif.type != NL80211_IFTYPE_MESH_POINT && +- sdata->vif.type != NL80211_IFTYPE_OCB)) +- return; +- +- if (WARN_ON_ONCE(sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE || +- sdata->vif.type == NL80211_IFTYPE_NAN || +- (sdata->vif.type == NL80211_IFTYPE_MONITOR && +- !sdata->vif.bss_conf.mu_mimo_owner && +- !(changed & BSS_CHANGED_TXPOWER)))) +- return; +- +- if (!check_sdata_in_driver(sdata)) +- return; +- +- trace_drv_link_info_changed(local, sdata, info, changed); +- if (local->ops->link_info_changed) +- local->ops->link_info_changed(&local->hw, &sdata->vif, +- info, changed); +- else if (local->ops->bss_info_changed) +- local->ops->bss_info_changed(&local->hw, &sdata->vif, +- info, changed); +- trace_drv_return_void(local); +-} ++void drv_link_info_changed(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_bss_conf *info, ++ int link_id, u64 changed); + + static inline void drv_nss_bss_info_changed(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, +@@ -273,27 +243,11 @@ static inline int drv_set_tim(struct ieee80211_local *local, + return ret; + } + +-static inline int drv_set_key(struct ieee80211_local *local, +- enum set_key_cmd cmd, +- struct ieee80211_sub_if_data *sdata, +- struct ieee80211_sta *sta, +- struct ieee80211_key_conf *key) +-{ +- int ret; +- +- might_sleep(); +- +- if (!ieee80211_hw_check(&local->hw, SUPPORTS_NSS_OFFLOAD)) +- sdata = get_bss_sdata(sdata); +- +- if (!check_sdata_in_driver(sdata)) +- return -EIO; +- +- trace_drv_set_key(local, cmd, sdata, sta, key); +- ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key); +- trace_drv_return_int(local, ret); +- return ret; +-} ++int drv_set_key(struct ieee80211_local *local, ++ enum set_key_cmd cmd, ++ struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_sta *sta, ++ struct ieee80211_key_conf *key); + + static inline void drv_update_tkip_key(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, +@@ -969,52 +923,14 @@ static inline void drv_verify_link_exists(struct ieee80211_sub_if_data *sdata, + sdata_assert_lock(sdata); + } + +-static inline int drv_assign_vif_chanctx(struct ieee80211_local *local, +- struct ieee80211_sub_if_data *sdata, +- struct ieee80211_bss_conf *link_conf, +- struct ieee80211_chanctx *ctx) +-{ +- int ret = 0; +- +- drv_verify_link_exists(sdata, link_conf); +- if (!check_sdata_in_driver(sdata)) +- return -EIO; +- +- trace_drv_assign_vif_chanctx(local, sdata, link_conf, ctx); +- if (local->ops->assign_vif_chanctx) { +- WARN_ON_ONCE(!ctx->driver_present); +- ret = local->ops->assign_vif_chanctx(&local->hw, +- &sdata->vif, +- link_conf, +- &ctx->conf); +- } +- trace_drv_return_int(local, ret); +- +- return ret; +-} +- +-static inline void drv_unassign_vif_chanctx(struct ieee80211_local *local, +- struct ieee80211_sub_if_data *sdata, +- struct ieee80211_bss_conf *link_conf, +- struct ieee80211_chanctx *ctx) +-{ +- might_sleep(); +- +- drv_verify_link_exists(sdata, link_conf); +- if (!check_sdata_in_driver(sdata)) +- return; +- +- trace_drv_unassign_vif_chanctx(local, sdata, link_conf, ctx); +- if (local->ops->unassign_vif_chanctx) { +- WARN_ON_ONCE(!ctx->driver_present); +- local->ops->unassign_vif_chanctx(&local->hw, +- &sdata->vif, +- link_conf, +- &ctx->conf); +- } +- trace_drv_return_void(local); +-} +- ++int drv_assign_vif_chanctx(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_bss_conf *link_conf, ++ struct ieee80211_chanctx *ctx); ++void drv_unassign_vif_chanctx(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_bss_conf *link_conf, ++ struct ieee80211_chanctx *ctx); + int drv_switch_vif_chanctx(struct ieee80211_local *local, + struct ieee80211_vif_chanctx_switch *vifs, + int n_vifs, enum ieee80211_chanctx_switch_mode mode); +@@ -1556,47 +1472,14 @@ static inline void drv_twt_teardown_request(struct ieee80211_local *local, + trace_drv_return_void(local); + } + +-static inline int drv_change_vif_links(struct ieee80211_local *local, +- struct ieee80211_sub_if_data *sdata, +- u16 old_links, u16 new_links, +- struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS]) +-{ +- int ret = -EOPNOTSUPP; +- +- might_sleep(); +- +- if (!check_sdata_in_driver(sdata)) +- return -EIO; +- +- trace_drv_change_vif_links(local, sdata, old_links, new_links); +- if (local->ops->change_vif_links) +- ret = local->ops->change_vif_links(&local->hw, &sdata->vif, +- old_links, new_links, old); +- trace_drv_return_int(local, ret); +- +- return ret; +-} +- +-static inline int drv_change_sta_links(struct ieee80211_local *local, +- struct ieee80211_sub_if_data *sdata, +- struct ieee80211_sta *sta, +- u16 old_links, u16 new_links) +-{ +- int ret = -EOPNOTSUPP; +- +- might_sleep(); +- +- if (!check_sdata_in_driver(sdata)) +- return -EIO; +- +- trace_drv_change_sta_links(local, sdata, sta, old_links, new_links); +- if (local->ops->change_sta_links) +- ret = local->ops->change_sta_links(&local->hw, &sdata->vif, sta, +- old_links, new_links); +- trace_drv_return_int(local, ret); +- +- return ret; +-} ++int drv_change_vif_links(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata, ++ u16 old_links, u16 new_links, ++ struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS]); ++int drv_change_sta_links(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_sta *sta, ++ u16 old_links, u16 new_links); + + #ifdef CPTCFG_MAC80211_MESH + void drv_config_mesh_offload_path(struct ieee80211_local *local, +diff --git a/net/mac80211/key.c b/net/mac80211/key.c +index 4d2ae2a..583b018 100644 +--- a/net/mac80211/key.c ++++ b/net/mac80211/key.c +@@ -179,6 +179,10 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) + } + } + ++ if (key->conf.link_id >= 0 && sdata->vif.active_links && ++ !(sdata->vif.active_links & BIT(key->conf.link_id))) ++ return 0; ++ + ret = drv_set_key(key->local, SET_KEY, sdata, + sta ? &sta->sta : NULL, &key->conf); + +@@ -248,6 +252,10 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) + sta = key->sta; + sdata = key->sdata; + ++ if (key->conf.link_id >= 0 && sdata->vif.active_links && ++ !(sdata->vif.active_links & BIT(key->conf.link_id))) ++ return; ++ + if (!(key->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC | + IEEE80211_KEY_FLAG_PUT_MIC_SPACE | + IEEE80211_KEY_FLAG_RESERVE_TAILROOM))) +diff --git a/net/mac80211/link.c b/net/mac80211/link.c +index 096f313..8df348a 100644 +--- a/net/mac80211/link.c ++++ b/net/mac80211/link.c +@@ -73,28 +73,37 @@ struct link_container { + struct ieee80211_bss_conf conf; + }; + +-static void ieee80211_free_links(struct ieee80211_sub_if_data *sdata, +- struct link_container **links) ++static void ieee80211_tear_down_links(struct ieee80211_sub_if_data *sdata, ++ struct link_container **links, u16 mask) + { ++ struct ieee80211_link_data *link; + LIST_HEAD(keys); + unsigned int link_id; + + for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) { +- if (!links[link_id]) ++ if (!(mask & BIT(link_id))) ++ continue; ++ link = &links[link_id]->data; ++ if (link_id == 0 && !link) ++ link = &sdata->deflink; ++ if (WARN_ON(!link)) + continue; +- ieee80211_remove_link_keys(&links[link_id]->data, &keys); ++ ieee80211_remove_link_keys(link, &keys); ++ ieee80211_link_stop(link); + } + + synchronize_rcu(); + + ieee80211_free_key_list(sdata->local, &keys); ++} + +- for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) { +- if (!links[link_id]) +- continue; +- ieee80211_link_stop(&links[link_id]->data); ++static void ieee80211_free_links(struct ieee80211_sub_if_data *sdata, ++ struct link_container **links) ++{ ++ unsigned int link_id; ++ ++ for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) + kfree(links[link_id]); +- } + } + + static int ieee80211_check_dup_link_addrs(struct ieee80211_sub_if_data *sdata) +@@ -123,11 +132,38 @@ static int ieee80211_check_dup_link_addrs(struct ieee80211_sub_if_data *sdata) + return 0; + } + ++static void ieee80211_set_vif_links_bitmaps(struct ieee80211_sub_if_data *sdata, ++ u16 links) ++{ ++ sdata->vif.valid_links = links; ++ ++ if (!links) { ++ sdata->vif.active_links = 0; ++ return; ++ } ++ ++ switch (sdata->vif.type) { ++ case NL80211_IFTYPE_AP: ++ /* in an AP all links are always active */ ++ sdata->vif.active_links = links; ++ break; ++ case NL80211_IFTYPE_STATION: ++ if (sdata->vif.active_links) ++ break; ++ WARN_ON(hweight16(links) > 1); ++ sdata->vif.active_links = links; ++ break; ++ default: ++ WARN_ON(1); ++ } ++} ++ + static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata, + struct link_container **to_free, + u16 new_links) + { + u16 old_links = sdata->vif.valid_links; ++ u16 old_active = sdata->vif.active_links; + unsigned long add = new_links & ~old_links; + unsigned long rem = old_links & ~new_links; + unsigned int link_id; +@@ -195,13 +231,17 @@ static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata, + ieee80211_link_init(sdata, -1, &sdata->deflink, + &sdata->vif.bss_conf); + +- sdata->vif.valid_links = new_links; +- + ret = ieee80211_check_dup_link_addrs(sdata); + if (!ret) { ++ /* for keys we will not be able to undo this */ ++ ieee80211_tear_down_links(sdata, to_free, rem); ++ ++ ieee80211_set_vif_links_bitmaps(sdata, new_links); ++ + /* tell the driver */ + ret = drv_change_vif_links(sdata->local, sdata, +- old_links, new_links, ++ old_links & old_active, ++ new_links & sdata->vif.active_links, + old); + } + +@@ -209,7 +249,7 @@ static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata, + /* restore config */ + memcpy(sdata->link, old_data, sizeof(old_data)); + memcpy(sdata->vif.link_conf, old, sizeof(old)); +- sdata->vif.valid_links = old_links; ++ ieee80211_set_vif_links_bitmaps(sdata, old_links); + /* and free (only) the newly allocated links */ + memset(to_free, 0, sizeof(links)); + goto free; +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 5b5892b..3e46156 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -4042,11 +4042,11 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link, + goto out; + } + +- sband = ieee80211_get_link_sband(link); +- if (!sband) { ++ if (WARN_ON(!link->conf->chandef.chan)) { + ret = false; + goto out; + } ++ sband = local->hw.wiphy->bands[link->conf->chandef.chan->band]; + + if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) && + (!elems->he_cap || !elems->he_operation)) { +@@ -4846,8 +4846,10 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, + err = ieee80211_prep_channel(sdata, link, + assoc_data->link[link_id].bss, + &link->u.mgd.conn_flags); +- if (err) ++ if (err) { ++ link_info(link, "prep_channel failed\n"); + goto out_err; ++ } + } + + err = ieee80211_mgd_setup_link_sta(link, sta, link_sta, +diff --git a/net/mac80211/util.c b/net/mac80211/util.c +index 27ae770..069aa7e 100644 +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -2904,7 +2904,7 @@ void ieee80211_recalc_min_chandef(struct ieee80211_sub_if_data *sdata, + */ + rcu_read_unlock(); + +- if (WARN_ON_ONCE(!chanctx_conf)) ++ if (!chanctx_conf) + goto unlock; + + chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/677-23-wifi-mac80211-add-vif-sta-link-RCU-dereference-macro.patch b/feeds/ipq95xx/mac80211/patches/qca/677-23-wifi-mac80211-add-vif-sta-link-RCU-dereference-macro.patch new file mode 100644 index 000000000..bbd119cc7 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/677-23-wifi-mac80211-add-vif-sta-link-RCU-dereference-macro.patch @@ -0,0 +1,103 @@ +From 9dfbdc8c77493cd5791002b464054bfc503eff02 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Fri, 18 Nov 2022 18:48:12 +0530 +Subject: [PATCH] wifi: mac80211: add vif/sta link RCU dereference macros + +Add macros (and an exported function) to allow checking some +link RCU protected accesses that are happening in callbacks +from mac80211 and are thus under the correct lock. + +Signed-off-by: Johannes Berg +--- + drivers/net/wireless/mac80211_hwsim.c | 16 ++++++++++++++-- + include/net/mac80211.h | 17 ++++++++++++++--- + net/mac80211/sta_info.c | 10 ++++++++++ + 3 files changed, 38 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c +index be0a05a..1a7d74e 100644 +--- a/drivers/net/wireless/mac80211_hwsim.c ++++ b/drivers/net/wireless/mac80211_hwsim.c +@@ -2991,6 +2991,19 @@ static int mac80211_hwsim_set_rts_threshold(struct ieee80211_hw *hw, u32 value) + return -EOPNOTSUPP; + } + ++/** ++ * lockdep_vif_mutex_held - for lockdep checks on link poiners ++ * @vif: the interface to check ++ */ ++static inline bool lockdep_vif_mutex_held(struct ieee80211_vif *vif) ++{ ++ return lockdep_is_held(&ieee80211_vif_to_wdev(vif)->mtx); ++} ++ ++#define link_conf_dereference_protected(vif, link_id) \ ++ rcu_dereference_protected((vif)->link_conf[link_id], \ ++ lockdep_vif_mutex_held(vif)) ++ + static int mac80211_hwsim_change_vif_links(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + u16 old_links, u16 new_links, +@@ -3006,8 +3019,7 @@ static int mac80211_hwsim_change_vif_links(struct ieee80211_hw *hw, + for_each_set_bit(i, &add, IEEE80211_MLD_MAX_NUM_LINKS) { + struct ieee80211_bss_conf *link_conf; + +- /* FIXME: figure out how to get the locking here */ +- link_conf = rcu_dereference_protected(vif->link_conf[i], 1); ++ link_conf = link_conf_dereference_protected(vif, i); + if (WARN_ON(!link_conf)) + continue; + +diff --git a/include/net/mac80211.h b/include/net/mac80211.h +index 685d5e8..550c294 100644 +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -2384,13 +2384,24 @@ struct ieee80211_sta { + u8 drv_priv[] __aligned(sizeof(void *)); + }; + +-/* FIXME: check the locking correctly */ ++#ifdef CONFIG_LOCKDEP ++bool lockdep_sta_mutex_held(struct ieee80211_sta *pubsta); ++#else ++static inline bool lockdep_sta_mutex_held(struct ieee80211_sta *pubsta) ++{ ++ return true; ++} ++#endif ++ ++#define link_sta_dereference_protected(sta, link_id) \ ++ rcu_dereference_protected((sta)->link[link_id], \ ++ lockdep_sta_mutex_held(sta)) ++ + #define for_each_sta_active_link(vif, sta, link_sta, link_id) \ + for (link_id = 0; link_id < ARRAY_SIZE((sta)->link); link_id++) \ + if ((!(vif)->active_links || \ + (vif)->active_links & BIT(link_id)) && \ +- ((link_sta) = rcu_dereference_protected((sta)->link[link_id],\ +- 1))) ++ ((link_sta) = link_sta_dereference_protected(sta, link_id))) + + /** + * enum sta_notify_cmd - sta notify command +diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c +index e485b55..492ea9b 100644 +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -2860,3 +2860,13 @@ void ieee80211_sta_set_max_amsdu_subframes(struct sta_info *sta, + if (val) + sta->sta.max_amsdu_subframes = 4 << val; + } ++ ++#ifdef CONFIG_LOCKDEP ++bool lockdep_sta_mutex_held(struct ieee80211_sta *pubsta) ++{ ++ struct sta_info *sta = container_of(pubsta, struct sta_info, sta); ++ ++ return lockdep_is_held(&sta->local->sta_mtx); ++} ++EXPORT_SYMBOL(lockdep_sta_mutex_held); ++#endif +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/677-24-wifi-mac80211-use-link_id-in-ieee80211_change_bss.patch b/feeds/ipq95xx/mac80211/patches/qca/677-24-wifi-mac80211-use-link_id-in-ieee80211_change_bss.patch new file mode 100644 index 000000000..d7dc24fe9 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/677-24-wifi-mac80211-use-link_id-in-ieee80211_change_bss.patch @@ -0,0 +1,123 @@ +From 102b3a72307d6c9e4bbd190bbca04f7ef60b907c Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Fri, 18 Nov 2022 18:53:56 +0530 +Subject: [PATCH] wifi: mac80211: use link_id in ieee80211_change_bss() + +We should set the parameters here per link, except +unfortunately ap_isolate, but we can't really change +that anymore so it'll remain a quirk in the API in +that you need to change it on one of the valid links +and it'll apply to all. + +Signed-off-by: Johannes Berg +--- + net/mac80211/cfg.c | 40 +++++++++++++++++++++------------------- + 1 file changed, 21 insertions(+), 19 deletions(-) + +diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c +index 7c90f1f..90250f4 100644 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -2747,47 +2747,50 @@ static int ieee80211_change_bss(struct wiphy *wiphy, + struct bss_parameters *params) + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ struct ieee80211_link_data *link; + struct ieee80211_supported_band *sband; + u32 changed = 0, nss_changed = 0;; + +- if (!sdata_dereference(sdata->deflink.u.ap.beacon, sdata)) ++ link = ieee80211_link_or_deflink(sdata, params->link_id, true); ++ if (IS_ERR(link)) ++ return PTR_ERR(link); ++ ++ if (!sdata_dereference(link->u.ap.beacon, sdata)) + return -ENOENT; + +- sband = ieee80211_get_sband(sdata); ++ sband = ieee80211_get_link_sband(link); + if (!sband) + return -EINVAL; + + if (params->use_cts_prot >= 0) { +- sdata->vif.bss_conf.use_cts_prot = params->use_cts_prot; ++ link->conf->use_cts_prot = params->use_cts_prot; + changed |= BSS_CHANGED_ERP_CTS_PROT; + } + if (params->use_short_preamble >= 0) { +- sdata->vif.bss_conf.use_short_preamble = +- params->use_short_preamble; ++ link->conf->use_short_preamble = params->use_short_preamble; + changed |= BSS_CHANGED_ERP_PREAMBLE; + } + +- if (!sdata->vif.bss_conf.use_short_slot && ++ if (!link->conf->use_short_slot && + (sband->band == NL80211_BAND_5GHZ || + sband->band == NL80211_BAND_6GHZ)) { +- sdata->vif.bss_conf.use_short_slot = true; ++ link->conf->use_short_slot = true; + changed |= BSS_CHANGED_ERP_SLOT; + } + + if (params->use_short_slot_time >= 0) { +- sdata->vif.bss_conf.use_short_slot = +- params->use_short_slot_time; ++ link->conf->use_short_slot = params->use_short_slot_time; + changed |= BSS_CHANGED_ERP_SLOT; + } + + if (params->basic_rates) { +- ieee80211_parse_bitrates(sdata->vif.bss_conf.chandef.width, ++ ieee80211_parse_bitrates(link->conf->chandef.width, + wiphy->bands[sband->band], + params->basic_rates, + params->basic_rates_len, +- &sdata->vif.bss_conf.basic_rates); ++ &link->conf->basic_rates); + changed |= BSS_CHANGED_BASIC_RATES; +- ieee80211_check_rate_mask(&sdata->deflink); ++ ieee80211_check_rate_mask(link); + } + + if (params->ap_isolate >= 0) { +@@ -2801,30 +2804,29 @@ static int ieee80211_change_bss(struct wiphy *wiphy, + } + + if (params->ht_opmode >= 0) { +- sdata->vif.bss_conf.ht_operation_mode = +- (u16) params->ht_opmode; ++ link->conf->ht_operation_mode = (u16)params->ht_opmode; + changed |= BSS_CHANGED_HT; + } + + if (params->p2p_ctwindow >= 0) { +- sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow &= ++ link->conf->p2p_noa_attr.oppps_ctwindow &= + ~IEEE80211_P2P_OPPPS_CTWINDOW_MASK; +- sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |= ++ link->conf->p2p_noa_attr.oppps_ctwindow |= + params->p2p_ctwindow & IEEE80211_P2P_OPPPS_CTWINDOW_MASK; + changed |= BSS_CHANGED_P2P_PS; + } + + if (params->p2p_opp_ps > 0) { +- sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |= ++ link->conf->p2p_noa_attr.oppps_ctwindow |= + IEEE80211_P2P_OPPPS_ENABLE_BIT; + changed |= BSS_CHANGED_P2P_PS; + } else if (params->p2p_opp_ps == 0) { +- sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow &= ++ link->conf->p2p_noa_attr.oppps_ctwindow &= + ~IEEE80211_P2P_OPPPS_ENABLE_BIT; + changed |= BSS_CHANGED_P2P_PS; + } + +- ieee80211_link_info_change_notify(sdata, &sdata->deflink, changed); ++ ieee80211_link_info_change_notify(sdata, link, changed); + + ieee80211_nss_bss_info_change_notify(sdata, nss_changed); + +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/677-25-wifi-mac80211-remove-support-for-AddBA-with-fragment.patch b/feeds/ipq95xx/mac80211/patches/qca/677-25-wifi-mac80211-remove-support-for-AddBA-with-fragment.patch new file mode 100644 index 000000000..2229b7288 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/677-25-wifi-mac80211-remove-support-for-AddBA-with-fragment.patch @@ -0,0 +1,60 @@ +From d63efc91afc854dbb5747d3e6afcfa56826c9ae2 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Fri, 30 Sep 2022 13:24:11 +0200 +Subject: [PATCH] wifi: mac80211: remove support for AddBA with fragmentation + +HE added support for dynamic fragmentation inside aggregation +sessions, but no existing driver ever advertises it. Thus, +remove the code for now, it cannot work as-is in MLO. For it +to properly work in MLO, we'd need to validate that the frag +level is identical across all the link bands/iftypes, which +is a good amount of complex code that's just not worth it as +long as no driver has support for it. + +Signed-off-by: Johannes Berg +--- + net/mac80211/agg-rx.c | 19 ------------------- + 1 file changed, 19 deletions(-) + +diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c +index c36df80..3054db6 100644 +--- a/net/mac80211/agg-rx.c ++++ b/net/mac80211/agg-rx.c +@@ -183,34 +183,15 @@ static void ieee80211_add_addbaext(struct ieee80211_sub_if_data *sdata, + const struct ieee80211_addba_ext_ie *req, + u16 buf_size) + { +- struct ieee80211_supported_band *sband; + struct ieee80211_addba_ext_ie *resp; +- const struct ieee80211_sta_he_cap *he_cap; +- u8 frag_level, cap_frag_level; + u8 *pos; + +- sband = ieee80211_get_sband(sdata); +- if (!sband) +- return; +- he_cap = ieee80211_get_he_iftype_cap(sband, +- ieee80211_vif_type_p2p(&sdata->vif)); +- if (!he_cap) +- return; +- + pos = skb_put_zero(skb, 2 + sizeof(struct ieee80211_addba_ext_ie)); + *pos++ = WLAN_EID_ADDBA_EXT; + *pos++ = sizeof(struct ieee80211_addba_ext_ie); + resp = (struct ieee80211_addba_ext_ie *)pos; + resp->data = req->data & IEEE80211_ADDBA_EXT_NO_FRAG; + +- frag_level = u32_get_bits(req->data, +- IEEE80211_ADDBA_EXT_FRAG_LEVEL_MASK); +- cap_frag_level = u32_get_bits(he_cap->he_cap_elem.mac_cap_info[0], +- IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_MASK); +- if (frag_level > cap_frag_level) +- frag_level = cap_frag_level; +- resp->data |= u8_encode_bits(frag_level, +- IEEE80211_ADDBA_EXT_FRAG_LEVEL_MASK); + resp->data |= u8_encode_bits(buf_size >> IEEE80211_ADDBA_EXT_BUF_SIZE_SHIFT, + IEEE80211_ADDBA_EXT_BUF_SIZE_MASK); + } +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/678-ath12k-add-mac-ops-to-get-tx-power.patch b/feeds/ipq95xx/mac80211/patches/qca/678-ath12k-add-mac-ops-to-get-tx-power.patch index e4d149909..0bf7cf2e1 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/678-ath12k-add-mac-ops-to-get-tx-power.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/678-ath12k-add-mac-ops-to-get-tx-power.patch @@ -16,7 +16,7 @@ Signed-off-by: Ramya Gnanasekar --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c -@@ -303,6 +303,57 @@ bool ath12k_core_hw_group_start_ready(st +@@ -229,6 +229,57 @@ bool ath12k_core_hw_group_start_ready(st return (ag->num_started == ag->num_chip); } @@ -76,7 +76,7 @@ Signed-off-by: Ramya Gnanasekar int ret; --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h -@@ -609,9 +609,6 @@ struct ath12k_debug { +@@ -665,9 +665,6 @@ struct ath12k_debug { struct dentry *debugfs_pdev; struct ath12k_dbg_htt_stats htt_stats; u32 extd_tx_stats; @@ -86,19 +86,20 @@ Signed-off-by: Ramya Gnanasekar u32 extd_rx_stats; u32 pktlog_filter; u32 pktlog_mode; -@@ -806,6 +803,11 @@ struct ath12k { - struct wmi_tpc_stats_event *tpc_stats; - struct completion tpc_complete; - bool tpc_request; +@@ -866,6 +863,12 @@ struct ath12k { + + struct completion mlo_setup_done; + u32 mlo_setup_status; + -+ /* fw pdev_stats can be requested by get_txpower mac ops too */ + struct ath12k_fw_stats fw_stats; + struct completion fw_stats_complete; + bool fw_stats_done; ++ ++ unsigned long last_tx_power_update; }; struct ath12k_band_cap { -@@ -1227,6 +1229,11 @@ void ath12k_core_put_hw_group(struct ath +@@ -1315,6 +1318,11 @@ void ath12k_core_put_hw_group(struct ath const struct firmware *ath12k_core_firmware_request(struct ath12k_base *ab, const char *filename); @@ -112,7 +113,7 @@ Signed-off-by: Ramya Gnanasekar { --- a/drivers/net/wireless/ath/ath12k/debugfs.c +++ b/drivers/net/wireless/ath/ath12k/debugfs.c -@@ -54,86 +54,28 @@ static const char *htt_bp_lmac_ring[HTT_ +@@ -53,86 +53,28 @@ static const char *htt_bp_lmac_ring[HTT_ "MONITOR_DEST_RING", }; @@ -208,7 +209,7 @@ Signed-off-by: Ramya Gnanasekar } /* FW sends all the active VDEV stats irrespective of PDEV, * hence limit until the count of all VDEVs started -@@ -146,43 +88,34 @@ void ath12k_debugfs_fw_stats_process(str +@@ -145,43 +87,34 @@ void ath12k_debugfs_fw_stats_process(str is_end = ((++num_vdev) == total_vdevs_started); @@ -262,7 +263,7 @@ Signed-off-by: Ramya Gnanasekar } static int ath12k_debugfs_fw_stats_request(struct ath12k *ar, -@@ -203,7 +136,7 @@ static int ath12k_debugfs_fw_stats_reque +@@ -202,7 +135,7 @@ static int ath12k_debugfs_fw_stats_reque ath12k_debugfs_fw_stats_reset(ar); @@ -271,7 +272,7 @@ Signed-off-by: Ramya Gnanasekar ret = ath12k_wmi_send_stats_request_cmd(ar, req_param); -@@ -214,7 +147,7 @@ static int ath12k_debugfs_fw_stats_reque +@@ -213,7 +146,7 @@ static int ath12k_debugfs_fw_stats_reque } time_left = @@ -280,7 +281,7 @@ Signed-off-by: Ramya Gnanasekar 1 * HZ); if (!time_left) return -ETIMEDOUT; -@@ -224,7 +157,7 @@ static int ath12k_debugfs_fw_stats_reque +@@ -223,7 +156,7 @@ static int ath12k_debugfs_fw_stats_reque break; spin_lock_bh(&ar->data_lock); @@ -289,7 +290,7 @@ Signed-off-by: Ramya Gnanasekar spin_unlock_bh(&ar->data_lock); break; } -@@ -264,7 +197,7 @@ static int ath12k_open_pdev_stats(struct +@@ -263,7 +196,7 @@ static int ath12k_open_pdev_stats(struct goto err_free; } @@ -298,7 +299,7 @@ Signed-off-by: Ramya Gnanasekar buf); file->private_data = buf; -@@ -336,7 +269,7 @@ static int ath12k_open_vdev_stats(struct +@@ -335,7 +268,7 @@ static int ath12k_open_vdev_stats(struct goto err_free; } @@ -307,7 +308,7 @@ Signed-off-by: Ramya Gnanasekar buf); file->private_data = buf; -@@ -414,14 +347,14 @@ static int ath12k_open_bcn_stats(struct +@@ -413,14 +346,14 @@ static int ath12k_open_bcn_stats(struct } } @@ -324,7 +325,7 @@ Signed-off-by: Ramya Gnanasekar spin_unlock_bh(&ar->data_lock); file->private_data = buf; -@@ -475,12 +408,12 @@ static ssize_t ath12k_write_enable_vdev_ +@@ -474,12 +407,12 @@ static ssize_t ath12k_write_enable_vdev_ mutex_lock(&ar->conf_mutex); @@ -339,7 +340,7 @@ Signed-off-by: Ramya Gnanasekar ret = count; out: -@@ -499,7 +432,7 @@ static ssize_t ath12k_read_enable_vdev_s +@@ -498,7 +431,7 @@ static ssize_t ath12k_read_enable_vdev_s mutex_lock(&ar->conf_mutex); len = scnprintf(buf, sizeof(buf) - len, "%u\n", @@ -348,7 +349,7 @@ Signed-off-by: Ramya Gnanasekar mutex_unlock(&ar->conf_mutex); return simple_read_from_buffer(ubuf, count, ppos, buf, len); -@@ -1302,7 +1235,7 @@ void ath12k_debugfs_fw_stats_init(struct +@@ -1301,7 +1234,7 @@ void ath12k_debugfs_fw_stats_init(struct struct dentry *fwstats_dir = debugfs_create_dir("fw_stats", ar->debug.debugfs_pdev); @@ -357,7 +358,7 @@ Signed-off-by: Ramya Gnanasekar /* all stats debugfs files created are under "fw_stats" directory * created per PDEV -@@ -1316,11 +1249,6 @@ void ath12k_debugfs_fw_stats_init(struct +@@ -1315,11 +1248,6 @@ void ath12k_debugfs_fw_stats_init(struct debugfs_create_file("en_vdev_stats_ol", 0600, fwstats_dir, ar, &fops_vdev_stats_offload); @@ -394,7 +395,15 @@ Signed-off-by: Ramya Gnanasekar --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -7371,7 +7371,7 @@ static int ath12k_mac_vdev_create(struct +@@ -8166,6 +8166,7 @@ static int ath12k_mac_radio_start(struct + ar->num_created_vdevs = 0; + ar->num_peers = 0; + ar->allocated_vdev_map = 0; ++ ar->chan_tx_pwr = ATH12K_PDEV_TX_POWER_INVALID; + + spin_lock_bh(&ar->data_lock); + ar->awgn_intf_handling_in_prog = false; +@@ -8594,7 +8595,7 @@ static int ath12k_mac_vdev_create(struct /* Send vdev stats offload commands to firmware before first vdev * creation. ie., when num_created_vdevs = 0 */ @@ -403,7 +412,31 @@ Signed-off-by: Ramya Gnanasekar ret = ath12k_dp_tx_htt_h2t_vdev_stats_ol_req(ar, 0); if (ret) { ath12k_warn(ar->ab, "failed to request vdev stats offload: %d\n", ret); -@@ -10625,6 +10625,106 @@ static void ath12k_mac_op_sta_statistics +@@ -9254,6 +9255,7 @@ static int ath12k_mac_op_add_chanctx(str + ar->rx_channel = ctx->def.chan; + spin_unlock_bh(&ar->data_lock); + ++ ar->chan_tx_pwr = ATH12K_PDEV_TX_POWER_INVALID; + mutex_unlock(&ar->conf_mutex); + + return 0; +@@ -9285,6 +9287,7 @@ static void ath12k_mac_op_remove_chanctx + ar->rx_channel = NULL; + spin_unlock_bh(&ar->data_lock); + ++ ar->chan_tx_pwr = ATH12K_PDEV_TX_POWER_INVALID; + mutex_unlock(&ar->conf_mutex); + } + +@@ -9870,6 +9873,7 @@ static void ath12k_mac_update_rx_channel + ar->rx_channel = NULL; + } + rcu_read_unlock(); ++ ar->chan_tx_pwr = ATH12K_PDEV_TX_POWER_INVALID; + } + + static void +@@ -12213,6 +12217,127 @@ static void ath12k_mac_op_sta_statistics sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL); } @@ -459,7 +492,7 @@ Signed-off-by: Ramya Gnanasekar + */ + mutex_lock(&ah->conf_mutex); + -+ ar = ath12k_get_ar_by_vif(hw, vif); ++ ar = ath12k_get_ar_by_vif(hw, vif, 0); + if (!ar) { + goto err_fallback; + } @@ -469,6 +502,20 @@ Signed-off-by: Ramya Gnanasekar + goto err_fallback; + } + ++ mutex_lock(&ar->conf_mutex); ++ if (test_bit(ATH12K_CAC_RUNNING, &ar->dev_flags)) { ++ mutex_unlock(&ar->conf_mutex); ++ mutex_unlock(&ah->conf_mutex); ++ *dbm = 0; ++ return 0; ++ } ++ ++ /* Limit the requests to Firmware for fetching the tx power */ ++ if (ar->chan_tx_pwr != ATH12K_PDEV_TX_POWER_INVALID && ++ time_before(jiffies, msecs_to_jiffies(ATH12K_PDEV_TX_POWER_REFRESH_TIME_MSECS) + ++ ar->last_tx_power_update)) ++ goto get_tx_power; ++ + req_param.pdev_id = ar->pdev->pdev_id; + req_param.vdev_id = 0; + req_param.stats_id = WMI_REQUEST_PDEV_STAT; @@ -476,6 +523,7 @@ Signed-off-by: Ramya Gnanasekar + ret = ath12k_fw_stats_request(ar, &req_param); + if (ret) { + ath12k_warn(ab, "failed to request fw pdev stats: %d\n", ret); ++ mutex_unlock(&ar->conf_mutex); + goto err_fallback; + } + @@ -485,17 +533,23 @@ Signed-off-by: Ramya Gnanasekar + list); + if (!pdev) { + spin_unlock_bh(&ar->data_lock); ++ mutex_unlock(&ar->conf_mutex); + goto err_fallback; + } + + /* tx power is set as 2 units per dBm in FW. */ -+ *dbm = pdev->chan_tx_power/2; ++ ar->chan_tx_pwr = pdev->chan_tx_power/2; ++ ar->last_tx_power_update = jiffies; + + spin_unlock_bh(&ar->data_lock); ++ ++get_tx_power: ++ *dbm = ar->chan_tx_pwr; ++ ++ mutex_unlock(&ar->conf_mutex); + mutex_unlock(&ah->conf_mutex); + -+ ath12k_dbg(ab, ATH12K_DBG_MAC, "txpower from firmware %d, reported %d dBm\n", -+ pdev->chan_tx_power, *dbm); ++ ath12k_dbg(ab, ATH12K_DBG_MAC, "txpower reported %d dBm\n", *dbm); + return 0; + +err_fallback: @@ -510,7 +564,7 @@ Signed-off-by: Ramya Gnanasekar static const struct ieee80211_ops ath12k_ops = { .tx = ath12k_mac_op_tx, .start = ath12k_mac_op_start, -@@ -10663,6 +10763,7 @@ static const struct ieee80211_ops ath12k +@@ -12254,6 +12379,7 @@ static const struct ieee80211_ops ath12k #ifdef CPTCFG_ATH12K_DEBUGFS .sta_add_debugfs = ath12k_debugfs_sta_op_add, #endif @@ -518,7 +572,7 @@ Signed-off-by: Ramya Gnanasekar }; static void ath12k_mac_update_ch_list(struct ath12k *ar, -@@ -11265,6 +11366,11 @@ static int ath12k_mac_hw_register(struct +@@ -12978,6 +13104,11 @@ static int ath12k_mac_hw_register(struct goto err_unregister_hw; } @@ -532,7 +586,7 @@ Signed-off-by: Ramya Gnanasekar ath12k_err(ar->ab, "debugfs registration failed: %d\n", ret); --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -6702,7 +6702,7 @@ void ath12k_wmi_fw_stats_fill(struct ath +@@ -6867,7 +6867,7 @@ void ath12k_wmi_fw_stats_fill(struct ath spin_lock_bh(&ar->data_lock); if (stats_id == WMI_REQUEST_PDEV_STAT) { @@ -541,7 +595,7 @@ Signed-off-by: Ramya Gnanasekar struct ath12k_fw_stats_pdev, list); if (!pdev) { ath12k_warn(ar->ab, "failed to get pdev stats\n"); -@@ -7764,7 +7764,52 @@ static void ath12k_peer_assoc_conf_event +@@ -7929,7 +7929,52 @@ static void ath12k_peer_assoc_conf_event static void ath12k_update_stats_event(struct ath12k_base *ab, struct sk_buff *skb) { @@ -595,3 +649,15 @@ Signed-off-by: Ramya Gnanasekar } /* PDEV_CTL_FAILSAFE_CHECK_EVENT is received from FW when the frequency scanned +--- a/drivers/net/wireless/ath/ath12k/mac.h ++++ b/drivers/net/wireless/ath/ath12k/mac.h +@@ -128,6 +128,9 @@ struct ath12k_generic_iter { + #define ATH12K_OBSS_PD_SRG_EN BIT(30) + #define ATH12K_OBSS_PD_NON_SRG_EN BIT(31) + ++#define ATH12K_PDEV_TX_POWER_INVALID (-1) ++#define ATH12K_PDEV_TX_POWER_REFRESH_TIME_MSECS 5000 /* msecs */ ++ + extern const struct htt_rx_ring_tlv_filter ath12k_mac_mon_status_filter_default; + + void ath12k_mac_ap_ps_recalc(struct ath12k *ar); diff --git a/feeds/ipq95xx/mac80211/patches/qca/679-01-wifi-ath12k-send-host-cap-until-all-the-chip-in-the-.patch b/feeds/ipq95xx/mac80211/patches/qca/679-01-wifi-ath12k-send-host-cap-until-all-the-chip-in-the-.patch new file mode 100644 index 000000000..27c92c4c7 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/679-01-wifi-ath12k-send-host-cap-until-all-the-chip-in-the-.patch @@ -0,0 +1,247 @@ +From c7df4610729a1112efeb6618352bee9f2273c0d5 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Sun, 23 Oct 2022 19:05:47 +0530 +Subject: [PATCH 2/3] wifi: ath12k: send host cap until all the chip in the + group are ready + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/core.c | 23 ++++++++ + drivers/net/wireless/ath/ath12k/qmi.c | 82 ++++++++++++++++++++++++-- + drivers/net/wireless/ath/ath12k/qmi.h | 18 ++++++ + 3 files changed, 118 insertions(+), 5 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -1171,6 +1171,27 @@ static int ath12k_core_start_firmware(st + return ret; + } + ++static void ath12k_core_trigger_partner(struct ath12k_base *ab) ++{ ++ struct ath12k_hw_group *ag = ab->ag; ++ struct ath12k_base *partner_ab; ++ int i; ++ bool found = false; ++ ++ lockdep_assert_held(&ag->mutex_lock); ++ ++ for (i = 0; i < ag->num_chip; i++) { ++ partner_ab = ag->ab[i]; ++ if (!partner_ab) ++ continue; ++ ++ if (found) ++ ath12k_qmi_trigger_host_cap(partner_ab); ++ ++ found = (partner_ab == ab) ? true : false; ++ } ++} ++ + int ath12k_core_qmi_firmware_ready(struct ath12k_base *ab) + { + struct ath12k_hw_group *ag; +@@ -1235,6 +1256,8 @@ int ath12k_core_qmi_firmware_ready(struc + } + + ath12k_dbg(ab, ATH12K_DBG_BOOT, "group %d started\n", ag->id); ++ } else { ++ ath12k_core_trigger_partner(ab); + } + + mutex_unlock(&ag->mutex_lock); +--- a/drivers/net/wireless/ath/ath12k/qmi.c ++++ b/drivers/net/wireless/ath/ath12k/qmi.c +@@ -19,6 +19,8 @@ + #include + #include + ++#define ATH12K_QMI_INVALID_RADIO 0xFF ++ + #define SLEEP_CLOCK_SELECT_INTERNAL_BIT 0x02 + #define HOST_CSTATE_BIT 0x04 + #define PLATFORM_CAP_PCIE_GLOBAL_RESET 0x08 +@@ -2775,7 +2777,6 @@ static int ath12k_qmi_fill_mlo_host_caps + if (ag->id == ATH12K_INVALID_GRP_ID) { + ath12k_dbg(ab, ATH12K_DBG_QMI, "Skip MLO cap send for chip id %d\n", + ab->chip_id); +- + mutex_unlock(&ag->mutex_lock); + return 0; + } +@@ -4188,9 +4189,77 @@ ath12k_qmi_driver_event_post(struct ath1 + return 0; + } + ++void ath12k_qmi_trigger_host_cap(struct ath12k_base *ab) ++{ ++ struct ath12k_qmi *qmi = &ab->qmi; ++ bool block; ++ ++ spin_lock(&qmi->event_lock); ++ ++ block = ath12k_qmi_get_event_block(qmi); ++ if (block) ++ ath12k_qmi_set_event_block(qmi, false); ++ ++ spin_unlock(&qmi->event_lock); ++ ++ if (block) { ++ ath12k_dbg(ab, ATH12K_DBG_QMI, "Trigger host cap for chip id %d\n", ++ ab->chip_id); ++ ++ ath12k_qmi_driver_event_post(qmi, ATH12K_QMI_EVENT_HOST_CAP, NULL); ++ } ++} ++ ++static bool ath12k_qmi_hw_group_host_cap_ready(struct ath12k_hw_group *ag) ++{ ++ struct ath12k_base *ab; ++ int i; ++ ++ lockdep_assert_held(&ag->mutex_lock); ++ ++ for (i = 0; i < ag->num_chip; i++) { ++ ab = ag->ab[i]; ++ ++ if (!(ab && ab->qmi.num_radios != ATH12K_QMI_INVALID_RADIO)) ++ return false; ++ } ++ ++ return true; ++} ++ ++static struct ath12k_base * ++ath12k_qmi_hw_group_find_blocked_chip(struct ath12k_hw_group *ag) ++{ ++ struct ath12k_base *ab; ++ struct ath12k_qmi *qmi; ++ bool block; ++ int i; ++ ++ lockdep_assert_held(&ag->mutex_lock); ++ ++ for (i = 0; i < ag->num_chip; i++) { ++ ab = ag->ab[i]; ++ if (!ab) ++ continue; ++ ++ qmi = &ab->qmi; ++ ++ spin_lock(&qmi->event_lock); ++ block = ath12k_qmi_get_event_block(qmi); ++ spin_unlock(&qmi->event_lock); ++ ++ if (block) ++ return ab; ++ } ++ ++ return NULL; ++} ++ + static int ath12k_qmi_event_server_arrive(struct ath12k_qmi *qmi) + { +- struct ath12k_base *ab = qmi->ab; ++ struct ath12k_base *ab = qmi->ab, *block_ab; ++ struct ath12k_hw_group *ag = ab->ag; ++ bool host_cap_ready; + int ret; + + ret = ath12k_qmi_fw_ind_register_send(ab); +@@ -4199,6 +4268,29 @@ static int ath12k_qmi_event_server_arriv + return ret; + } + ++ qmi->num_radios = ab->hw_params->num_local_link; ++ ++ spin_lock(&qmi->event_lock); ++ ath12k_qmi_set_event_block(&ab->qmi, true); ++ spin_unlock(&qmi->event_lock); ++ ++ mutex_lock(&ag->mutex_lock); ++ host_cap_ready = ath12k_qmi_hw_group_host_cap_ready(ag); ++ if (host_cap_ready) { ++ block_ab = ath12k_qmi_hw_group_find_blocked_chip(ag); ++ if (block_ab) ++ ath12k_qmi_trigger_host_cap(block_ab); ++ } ++ mutex_unlock(&ag->mutex_lock); ++ ++ return ret; ++} ++ ++static int ath12k_qmi_event_host_cap(struct ath12k_qmi *qmi) ++{ ++ struct ath12k_base *ab = qmi->ab; ++ int ret; ++ + ret = ath12k_qmi_host_cap_send(ab); + if (ret < 0) { + ath12k_warn(ab, "qmi failed to send host cap QMI:%d\n", ret); +@@ -4842,7 +4934,6 @@ static void ath12k_qmi_driver_event_work + } + set_bit(ATH12K_FLAG_QMI_FW_READY_COMPLETE, + &ab->dev_flags); +- + } + + break; +@@ -4857,6 +4948,11 @@ static void ath12k_qmi_driver_event_work + case ATH12K_QMI_EVENT_M3_DUMP_UPLOAD_REQ: + ath12k_qmi_event_m3_dump_upload_req(qmi, event->data); + break; ++ case ATH12K_QMI_EVENT_HOST_CAP: ++ ret = ath12k_qmi_event_host_cap(qmi); ++ if (ret < 0) ++ set_bit(ATH12K_FLAG_QMI_FAIL, &ab->dev_flags); ++ break; + default: + ath12k_warn(ab, "invalid event type: %d", event->type); + break; +@@ -4874,6 +4970,7 @@ int ath12k_qmi_init_service(struct ath12 + memset(&ab->qmi.target, 0, sizeof(struct target_info)); + memset(&ab->qmi.target_mem, 0, sizeof(struct target_mem_chunk)); + ab->qmi.ab = ab; ++ ab->qmi.num_radios = ATH12K_QMI_INVALID_RADIO; + + ab->qmi.target_mem_mode = ATH12K_QMI_TARGET_MEM_MODE_DEFAULT; + ret = qmi_handle_init(&ab->qmi.handle, ATH12K_QMI_RESP_LEN_MAX, +--- a/drivers/net/wireless/ath/ath12k/qmi.h ++++ b/drivers/net/wireless/ath/ath12k/qmi.h +@@ -83,6 +83,7 @@ enum ath12k_qmi_event_type { + ATH12K_QMI_EVENT_QDSS_TRACE_REQ_MEM = 15, + ATH12K_QMI_EVENT_QDSS_TRACE_SAVE, + ATH12K_QMI_EVENT_M3_DUMP_UPLOAD_REQ = 18, ++ ATH12K_QMI_EVENT_HOST_CAP, + ATH12K_QMI_EVENT_MAX, + }; + +@@ -165,6 +166,8 @@ struct ath12k_qmi { + bool target_mem_delayed; + u8 cal_done; + u8 cal_timeout; ++ bool block_event; /* protect by event spinlock */ ++ u8 num_radios; + struct target_info target; + struct m3_mem_region m3_mem; + unsigned int service_ins_id; +@@ -750,4 +753,19 @@ int ath12k_enable_fwlog(struct ath12k_ba + int ath12k_qmi_m3_dump_upload_done_ind_send(struct ath12k_base *ab, + u32 pdev_id, int status); + void ath12k_qmi_free_target_mem_chunk(struct ath12k_base *ab); ++void ath12k_qmi_trigger_host_cap(struct ath12k_base *ab); ++ ++static inline void ath12k_qmi_set_event_block(struct ath12k_qmi *qmi, bool block) ++{ ++ lockdep_assert_held(&qmi->event_lock); ++ ++ qmi->block_event = block; ++} ++ ++static inline bool ath12k_qmi_get_event_block(struct ath12k_qmi *qmi) ++{ ++ lockdep_assert_held(&qmi->event_lock); ++ ++ return qmi->block_event; ++} + #endif diff --git a/feeds/ipq95xx/mac80211/patches/qca/679-02-wifi-ath12k-add-phy-count-capability-learn.patch b/feeds/ipq95xx/mac80211/patches/qca/679-02-wifi-ath12k-add-phy-count-capability-learn.patch new file mode 100644 index 000000000..09a37ee1c --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/679-02-wifi-ath12k-add-phy-count-capability-learn.patch @@ -0,0 +1,195 @@ +From 3d50ec5a539a73deecb81591c482f76460fd5ea6 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Wed, 26 Oct 2022 06:57:24 +0530 +Subject: [PATCH 3/3] wifi: ath12k: add phy count capability learn + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/qmi.c | 108 +++++++++++++++++++++++++- + drivers/net/wireless/ath/ath12k/qmi.h | 17 ++++ + 2 files changed, 124 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath12k/qmi.c ++++ b/drivers/net/wireless/ath/ath12k/qmi.c +@@ -716,6 +716,67 @@ static struct qmi_elem_info qmi_wlanfw_h + }, + }; + ++static struct qmi_elem_info qmi_wlanfw_phy_cap_req_msg_v01_ei[] = { ++ { ++ .data_type = QMI_EOTI, ++ .array_type = NO_ARRAY, ++ .tlv_type = QMI_COMMON_TLV_TYPE, ++ }, ++}; ++ ++static struct qmi_elem_info qmi_wlanfw_phy_cap_resp_msg_v01_ei[] = { ++ { ++ .data_type = QMI_STRUCT, ++ .elem_len = 1, ++ .elem_size = sizeof(struct qmi_response_type_v01), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x02, ++ .offset = offsetof(struct qmi_wlanfw_phy_cap_resp_msg_v01, resp), ++ .ei_array = qmi_response_type_v01_ei, ++ }, ++ { ++ .data_type = QMI_OPT_FLAG, ++ .elem_len = 1, ++ .elem_size = sizeof(u8), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x10, ++ .offset = offsetof(struct qmi_wlanfw_phy_cap_resp_msg_v01, ++ num_phy_valid), ++ }, ++ { ++ .data_type = QMI_UNSIGNED_1_BYTE, ++ .elem_len = 1, ++ .elem_size = sizeof(u8), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x10, ++ .offset = offsetof(struct qmi_wlanfw_phy_cap_resp_msg_v01, ++ num_phy), ++ }, ++ { ++ .data_type = QMI_OPT_FLAG, ++ .elem_len = 1, ++ .elem_size = sizeof(u8), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x11, ++ .offset = offsetof(struct qmi_wlanfw_phy_cap_resp_msg_v01, ++ board_id_valid), ++ }, ++ { ++ .data_type = QMI_UNSIGNED_4_BYTE, ++ .elem_len = 1, ++ .elem_size = sizeof(u32), ++ .array_type = NO_ARRAY, ++ .tlv_type = 0x11, ++ .offset = offsetof(struct qmi_wlanfw_phy_cap_resp_msg_v01, ++ board_id), ++ }, ++ { ++ .data_type = QMI_EOTI, ++ .array_type = NO_ARRAY, ++ .tlv_type = QMI_COMMON_TLV_TYPE, ++ }, ++}; ++ + static struct qmi_elem_info qmi_wlanfw_ind_register_req_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, +@@ -2772,7 +2833,7 @@ static int ath12k_qmi_fill_mlo_host_caps + + mutex_lock(&ag->mutex_lock); + +- if (ag->id == ATH12K_INVALID_GRP_ID) { ++ if (ag->id == ATH12K_INVALID_GRP_ID || !ab->qmi.num_radios) { + ath12k_dbg(ab, ATH12K_DBG_QMI, "Skip MLO cap send for chip id %d\n", + ab->chip_id); + mutex_unlock(&ag->mutex_lock); +@@ -2941,6 +3002,49 @@ out: + return ret; + } + ++static int ath12k_qmi_phy_cap_send(struct ath12k_base *ab) ++{ ++ struct qmi_wlanfw_phy_cap_req_msg_v01 req = { }; ++ struct qmi_wlanfw_phy_cap_resp_msg_v01 resp = { }; ++ struct qmi_txn txn = { }; ++ int ret; ++ ++ ret = qmi_txn_init(&ab->qmi.handle, &txn, ++ qmi_wlanfw_phy_cap_resp_msg_v01_ei, &resp); ++ if (ret < 0) ++ goto out; ++ ++ ret = qmi_send_request(&ab->qmi.handle, NULL, &txn, ++ QMI_WLANFW_PHY_CAP_REQ_V01, ++ QMI_WLANFW_PHY_CAP_REQ_MSG_V01_MAX_LEN, ++ qmi_wlanfw_phy_cap_req_msg_v01_ei, &req); ++ if (ret < 0) { ++ ath12k_warn(ab, "failed to send phy capability request, err = %d\n", ret); ++ goto out; ++ } ++ ++ ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH12K_QMI_WLANFW_TIMEOUT_MS)); ++ if (ret < 0) ++ goto out; ++ ++ if (resp.resp.result != QMI_RESULT_SUCCESS_V01) ++ goto out; ++ ++ if (!resp.num_phy_valid) ++ goto out; ++ ++ ab->qmi.num_radios = resp.num_phy; ++ ++ ath12k_dbg(ab, ATH12K_DBG_QMI, "PHY capability resp valid %d num_phy %d valid %d board_id %d\n", ++ resp.num_phy_valid, resp.num_phy, ++ resp.board_id_valid, resp.board_id); ++ return 0; ++ ++out: ++ ab->qmi.num_radios = ab->hw_params->num_local_link; ++ return ret; ++} ++ + static int ath12k_qmi_fw_ind_register_send(struct ath12k_base *ab) + { + struct qmi_wlanfw_ind_register_req_msg_v01 *req; +@@ -4238,7 +4342,7 @@ static int ath12k_qmi_event_server_arriv + return ret; + } + +- qmi->num_radios = ab->hw_params->num_local_link; ++ ath12k_qmi_phy_cap_send(ab); + + spin_lock(&qmi->event_lock); + ath12k_qmi_set_event_block(&ab->qmi, true); +--- a/drivers/net/wireless/ath/ath12k/qmi.h ++++ b/drivers/net/wireless/ath/ath12k/qmi.h +@@ -334,6 +334,23 @@ struct qmi_wlanfw_host_cap_resp_msg_v01 + struct qmi_response_type_v01 resp; + }; + ++#define QMI_WLANFW_PHY_CAP_REQ_MSG_V01_MAX_LEN 0 ++#define QMI_WLANFW_PHY_CAP_REQ_V01 0x0057 ++#define QMI_WLANFW_PHY_CAP_RESP_MSG_V01_MAX_LEN 18 ++#define QMI_WLANFW_PHY_CAP_RESP_V01 0x0057 ++ ++struct qmi_wlanfw_phy_cap_req_msg_v01 { ++ char placeholder; ++}; ++ ++struct qmi_wlanfw_phy_cap_resp_msg_v01 { ++ struct qmi_response_type_v01 resp; ++ u8 num_phy_valid; ++ u8 num_phy; ++ u8 board_id_valid; ++ u32 board_id; ++}; ++ + #define QMI_WLANFW_IND_REGISTER_REQ_MSG_V01_MAX_LEN 54 + #define QMI_WLANFW_IND_REGISTER_REQ_V01 0x0020 + #define QMI_WLANFW_IND_REGISTER_RESP_MSG_V01_MAX_LEN 18 +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -1014,7 +1014,7 @@ static const struct ath12k_hw_params ath + .wakeup_mhi = false, + .alloc_cacheable_memory = true, + .max_mlo_peer = ATH12K_MAX_MLO_PEER, +- .num_local_link = 1, ++ .num_local_link = 0, + }, + { + .name = "wcn7850 hw2.0", +@@ -1144,7 +1144,7 @@ static const struct ath12k_hw_params ath + .wakeup_mhi = false, + .alloc_cacheable_memory = true, + .max_mlo_peer = ATH12K_MAX_MLO_PEER, +- .num_local_link = 1, ++ .num_local_link = 0, + }, + }; + diff --git a/feeds/ipq95xx/mac80211/patches/qca/679-ath12k-Fix-the-avg-ack-signal-inconsistency-issue.patch b/feeds/ipq95xx/mac80211/patches/qca/679-ath12k-Fix-the-avg-ack-signal-inconsistency-issue.patch index bc7be656c..ac59a64ba 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/679-ath12k-Fix-the-avg-ack-signal-inconsistency-issue.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/679-ath12k-Fix-the-avg-ack-signal-inconsistency-issue.patch @@ -24,11 +24,11 @@ Signed-off-by: Sivashankari Madhavan drivers/net/wireless/ath/ath12k/dp_tx.c | 2 ++ 1 file changed, 2 insertions(+) -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_tx.c +Index: backports-20220822-5.4.164-ef7197996efe/drivers/net/wireless/ath/ath12k/dp_tx.c =================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/dp_tx.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -720,6 +720,8 @@ static inline void ath12k_dp_tx_status_p +--- backports-20220822-5.4.164-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ backports-20220822-5.4.164-ef7197996efe/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -639,6 +639,8 @@ static inline void ath12k_dp_tx_status_p desc->info0); ts->ppdu_id = FIELD_GET(HAL_WBM_COMPL_TX_INFO1_TQM_STATUS_NUMBER, desc->info1); @@ -37,11 +37,11 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_ if (desc->rate_stats.info0 & HAL_TX_RATE_STATS_INFO0_VALID) ts->rate_stats = desc->rate_stats.info0; else -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi.c +Index: backports-20220822-5.4.164-ef7197996efe/drivers/net/wireless/ath/ath12k/wmi.c =================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/wmi.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi.c -@@ -5692,7 +5692,8 @@ static int ath12k_pull_mgmt_rx_params_tl +--- backports-20220822-5.4.164-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/wmi.c ++++ backports-20220822-5.4.164-ef7197996efe/drivers/net/wireless/ath/ath12k/wmi.c +@@ -5848,7 +5848,8 @@ static int ath12k_pull_mgmt_rx_params_tl } static int wmi_process_mgmt_tx_comp(struct ath12k *ar, u32 desc_id, @@ -51,7 +51,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi { struct sk_buff *msdu; struct ieee80211_tx_info *info; -@@ -5746,8 +5747,11 @@ skip_mgmt_stats: +@@ -5902,8 +5903,11 @@ skip_mgmt_stats: spin_unlock_bh(&ar->data_lock); info = IEEE80211_SKB_CB(msdu); @@ -59,12 +59,12 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi + if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) && !status) { info->flags |= IEEE80211_TX_STAT_ACK; + info->status.ack_signal = ack_rssi; -+ info->status.is_valid_ack_signal = true; ++ info->status.flags |= IEEE80211_TX_STATUS_ACK_SIGNAL_VALID; + } ieee80211_tx_status_irqsafe(ar->ah->hw, msdu); -@@ -5792,6 +5796,8 @@ static int ath12k_pull_mgmt_tx_compl_par +@@ -5948,6 +5952,8 @@ static int ath12k_pull_mgmt_tx_compl_par param->pdev_id = ev->pdev_id; param->desc_id = ev->desc_id; param->status = ev->status; @@ -73,7 +73,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi kfree(tb); return 0; -@@ -7296,7 +7302,8 @@ static void ath12k_mgmt_tx_compl_event(s +@@ -7455,7 +7461,8 @@ static void ath12k_mgmt_tx_compl_event(s } wmi_process_mgmt_tx_comp(ar, tx_compl_param.desc_id, @@ -83,11 +83,11 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi ath12k_dbg(ab, ATH12K_DBG_MGMT, "mgmt tx compl ev pdev_id %d, desc_id %d, status %d", -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi.h +Index: backports-20220822-5.4.164-ef7197996efe/drivers/net/wireless/ath/ath12k/wmi.h =================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/wmi.h -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi.h -@@ -5010,6 +5010,8 @@ struct wmi_mgmt_tx_compl_event { +--- backports-20220822-5.4.164-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/wmi.h ++++ backports-20220822-5.4.164-ef7197996efe/drivers/net/wireless/ath/ath12k/wmi.h +@@ -5112,6 +5112,8 @@ struct wmi_mgmt_tx_compl_event { u32 desc_id; u32 status; u32 pdev_id; diff --git a/feeds/ipq95xx/mac80211/patches/qca/681-001-ath12k-allocate-ppdu_info-separately-during-pdev_dp-.patch b/feeds/ipq95xx/mac80211/patches/qca/681-001-ath12k-allocate-ppdu_info-separately-during-pdev_dp-.patch index bf0740003..49adf38bc 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/681-001-ath12k-allocate-ppdu_info-separately-during-pdev_dp-.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/681-001-ath12k-allocate-ppdu_info-separately-during-pdev_dp-.patch @@ -1,6 +1,6 @@ -From 0a21b762a16c512c5c5c11afdd15efb40c8bdb94 Mon Sep 17 00:00:00 2001 +From d7e7b5821ef5da0e10703ee1ae2956d72f48b91f Mon Sep 17 00:00:00 2001 From: P Praneesh -Date: Fri, 4 Nov 2022 00:27:58 +0530 +Date: Wed, 15 Feb 2023 14:25:15 -0800 Subject: [PATCH] ath12k: allocate ppdu_info separately during pdev_dp alloc ppdu_info structure has 1024 MPDU array and it is currently present @@ -9,34 +9,28 @@ this much large contiguous memory. Hence allocating it separately during monitor pdev attach. Signed-off-by: P Praneesh +Signed-off-by: Sidhanta Sahu --- - drivers/net/wireless/ath/ath12k/core.c | 8 ++++++++ + drivers/net/wireless/ath/ath12k/dp.c | 1 + drivers/net/wireless/ath/ath12k/dp.h | 2 +- - drivers/net/wireless/ath/ath12k/dp_mon.c | 4 ++-- - drivers/net/wireless/ath/ath12k/dp_rx.c | 17 ++++++++++++----- - 4 files changed, 23 insertions(+), 8 deletions(-) + drivers/net/wireless/ath/ath12k/dp_mon.c | 4 +-- + drivers/net/wireless/ath/ath12k/dp_rx.c | 43 +++++++++++++++++++++--- + drivers/net/wireless/ath/ath12k/dp_rx.h | 1 + + 5 files changed, 43 insertions(+), 8 deletions(-) ---- a/drivers/net/wireless/ath/ath12k/core.c -+++ b/drivers/net/wireless/ath/ath12k/core.c -@@ -837,6 +837,15 @@ err_debugfs_pdev: - - static void ath12k_core_pdev_destroy(struct ath12k_base *ab) - { -+ struct ath12k *ar; -+ int i; -+ -+ for (i = 0; i < ab->num_radios; i++) { -+ ar = ab->pdevs[i].ar; -+ kfree(ar->dp.mon_data); -+ ar->dp.mon_data = NULL; -+ } -+ - ath12k_dp_pdev_free(ab); - ath12k_debugfs_pdev_destroy(ab); +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -1032,6 +1032,7 @@ void ath12k_dp_pdev_free(struct ath12k_b + for (i = 0; i < ab->num_radios; i++) { + ar = ab->pdevs[i].ar; + ath12k_dp_rx_pdev_free(ab, i); ++ ath12k_dp_rx_pdev_mon_detach(ab, i); + ath12k_debugfs_unregister(ar); + } } --- a/drivers/net/wireless/ath/ath12k/dp.h +++ b/drivers/net/wireless/ath/ath12k/dp.h -@@ -167,7 +167,7 @@ struct ath12k_pdev_dp { +@@ -131,7 +131,7 @@ struct ath12k_pdev_dp { struct dp_srng tx_mon_dst_ring[MAX_RXDMA_PER_PDEV]; struct ieee80211_rx_status rx_status; @@ -47,7 +41,7 @@ Signed-off-by: P Praneesh #define DP_NUM_CLIENTS_MAX 64 --- a/drivers/net/wireless/ath/ath12k/dp_mon.c +++ b/drivers/net/wireless/ath/ath12k/dp_mon.c -@@ -3596,7 +3596,7 @@ int ath12k_dp_mon_srng_process(struct at +@@ -3597,7 +3597,7 @@ int ath12k_dp_mon_srng_process(struct at { struct hal_mon_dest_desc *mon_dst_desc; struct ath12k_pdev_dp *pdev_dp = &ar->dp; @@ -56,7 +50,7 @@ Signed-off-by: P Praneesh struct ath12k_base *ab = ar->ab; struct ath12k_dp *dp = &ab->dp; struct sk_buff *skb; -@@ -3741,7 +3741,7 @@ int ath12k_dp_mon_rx_process_stats(struc +@@ -3743,7 +3743,7 @@ int ath12k_dp_mon_rx_process_stats(struc { struct ath12k_base *ab = ar->ab; struct ath12k_pdev_dp *pdev_dp = &ar->dp; @@ -67,14 +61,33 @@ Signed-off-by: P Praneesh struct hal_mon_dest_desc *mon_dst_desc; --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -4625,7 +4625,15 @@ out: +@@ -4773,10 +4773,34 @@ out: + return 0; + } + ++static int ath12k_dp_rx_pdev_mon_status_detach(struct ath12k *ar) ++{ ++ struct ath12k_pdev_dp *dp = &ar->dp; ++ struct ath12k_mon_data *pmon = dp->mon_data; ++ ++ if (!pmon) { ++ ath12k_err(ar->ab, "pmon is NULL\n"); ++ return -EINVAL; ++ } ++ ++ vfree(pmon); ++ dp->mon_data = NULL; ++ ++ return 0; ++} ++ static int ath12k_dp_rx_pdev_mon_status_attach(struct ath12k *ar) { struct ath12k_pdev_dp *dp = &ar->dp; - struct ath12k_mon_data *pmon = (struct ath12k_mon_data *)&dp->mon_data; + struct ath12k_mon_data *pmon; + -+ pmon = kzalloc(sizeof(*pmon), GFP_KERNEL); ++ pmon = vzalloc(sizeof(*pmon)); + if (!pmon) { + ath12k_warn(ar->ab, "pmon allocation failed \n"); + return -ENOMEM; @@ -84,7 +97,7 @@ Signed-off-by: P Praneesh skb_queue_head_init(&pmon->rx_status_q); -@@ -4639,7 +4647,6 @@ static int ath12k_dp_rx_pdev_mon_status_ +@@ -4790,7 +4814,6 @@ static int ath12k_dp_rx_pdev_mon_status_ int ath12k_dp_rx_pdev_mon_attach(struct ath12k *ar) { struct ath12k_pdev_dp *dp = &ar->dp; @@ -92,8 +105,8 @@ Signed-off-by: P Praneesh int ret = 0; ret = ath12k_dp_rx_pdev_mon_status_attach(ar); -@@ -4654,9 +4661,9 @@ int ath12k_dp_rx_pdev_mon_attach(struct - if (!ar->ab->hw_params.rxdma1_enable) +@@ -4805,13 +4828,23 @@ int ath12k_dp_rx_pdev_mon_attach(struct + if (!ar->ab->hw_params->rxdma1_enable) return 0; - pmon->mon_last_linkdesc_paddr = 0; @@ -105,3 +118,27 @@ Signed-off-by: P Praneesh return 0; } + ++void ath12k_dp_rx_pdev_mon_detach(struct ath12k_base *ab, const int pdev_idx) ++{ ++ struct ath12k *ar = ab->pdevs[pdev_idx].ar; ++ int ret; ++ ++ ret = ath12k_dp_rx_pdev_mon_status_detach(ar); ++ if (ret) ++ ath12k_warn(ar->ab, "pdev_mon_status_detach() failed %d\n", ret); ++} ++ + int ath12k_dp_rx_pktlog_start(struct ath12k_base *ab) + { + /* start reap timer */ +--- a/drivers/net/wireless/ath/ath12k/dp_rx.h ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.h +@@ -126,6 +126,7 @@ int ath12k_dp_htt_tlv_iter(struct ath12k + const void *ptr, void *data), + void *data); + int ath12k_dp_rx_pdev_mon_attach(struct ath12k *ar); ++void ath12k_dp_rx_pdev_mon_detach(struct ath12k_base *ab, const int pdev_idx); + int ath12k_dp_rx_peer_frag_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_id); + + int ath12k_dp_rx_pktlog_start(struct ath12k_base *ab); diff --git a/feeds/ipq95xx/mac80211/patches/qca/681-002-ath12k-Avoid-TLV-parsing-overhead-by-looping-till-sk.patch b/feeds/ipq95xx/mac80211/patches/qca/681-002-ath12k-Avoid-TLV-parsing-overhead-by-looping-till-sk.patch index 61e7a8b85..e2329d056 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/681-002-ath12k-Avoid-TLV-parsing-overhead-by-looping-till-sk.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/681-002-ath12k-Avoid-TLV-parsing-overhead-by-looping-till-sk.patch @@ -8,18 +8,20 @@ size of the allocated buffer. In monitor destination descriptor, end offset is received for each buffer which implies the acutal size of buffer DMA'ed by hardware. -Make use of the end offset for skb_put, so that skb->len is used as a upper +Make Use the end offset for skb_put, so that skb->len is used as a upper limit instead of DP_RX_BUFFER_SIZE while parsing the individual -monitor TLVs to improve CPU utilization. +monitor TLVs. Signed-off-by: P Praneesh --- drivers/net/wireless/ath/ath12k/dp_mon.c | 28 +++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) +diff --git a/drivers/net/wireless/ath/ath12k/dp_mon.c b/drivers/net/wireless/ath/ath12k/dp_mon.c +index 3abb14c..e22ba90 100644 --- a/drivers/net/wireless/ath/ath12k/dp_mon.c +++ b/drivers/net/wireless/ath/ath12k/dp_mon.c -@@ -2430,7 +2430,7 @@ ath12k_dp_mon_parse_rx_dest(struct ath12 +@@ -2430,7 +2430,7 @@ ath12k_dp_mon_parse_rx_dest(struct ath12k *ar, struct hal_rx_mon_ppdu_info *ppdu ptr += tlv_len; ptr = PTR_ALIGN(ptr, HAL_TLV_64_ALIGN); @@ -28,7 +30,7 @@ Signed-off-by: P Praneesh break; } while ((hal_status == HAL_RX_MON_STATUS_PPDU_NOT_DONE) || -@@ -3609,7 +3609,7 @@ int ath12k_dp_mon_srng_process(struct at +@@ -3609,7 +3609,7 @@ int ath12k_dp_mon_srng_process(struct ath12k *ar, int mac_id, int *budget, struct ath12k_peer *peer = NULL; struct ath12k_sta *arsta = NULL; u64 cookie; @@ -37,14 +39,14 @@ Signed-off-by: P Praneesh int num_buffs_reaped = 0, srng_id, buf_id; __skb_queue_head_init(&skb_list); -@@ -3670,6 +3670,17 @@ int ath12k_dp_mon_srng_process(struct at +@@ -3670,6 +3670,17 @@ int ath12k_dp_mon_srng_process(struct ath12k *ar, int mac_id, int *budget, if (end_reason == HAL_MON_END_OF_PPDU) *budget -= 1; + end_offset = u32_get_bits(mon_dst_desc->info0, + HAL_MON_DEST_INFO0_END_OFFSET); + -+ if (likely(end_offset <= DP_RX_BUFFER_SIZE)) { ++ if (likely(end_offset < DP_RX_BUFFER_SIZE)) { + skb_put(skb, end_offset); + } else { + ath12k_warn(ab, "invalid offset received from mon dest %u\n", @@ -55,7 +57,7 @@ Signed-off-by: P Praneesh __skb_queue_tail(&skb_list, skb); move_next: ath12k_dp_mon_buf_replenish(ab, buf_ring, 1); -@@ -3755,7 +3766,7 @@ int ath12k_dp_mon_rx_process_stats(struc +@@ -3755,7 +3766,7 @@ int ath12k_dp_mon_rx_process_stats(struct ath12k *ar, int mac_id, struct sk_buff_head skb_list; u64 cookie; int num_buffs_reaped = 0, srng_id, buf_id; @@ -64,14 +66,14 @@ Signed-off-by: P Praneesh u16 log_type = 0; __skb_queue_head_init(&skb_list); -@@ -3810,6 +3821,17 @@ int ath12k_dp_mon_rx_process_stats(struc +@@ -3810,6 +3821,17 @@ int ath12k_dp_mon_rx_process_stats(struct ath12k *ar, int mac_id, if (end_reason == HAL_MON_END_OF_PPDU) *budget -= 1; + end_offset = u32_get_bits(mon_dst_desc->info0, + HAL_MON_DEST_INFO0_END_OFFSET); + -+ if (likely(end_offset <= DP_RX_BUFFER_SIZE)) { ++ if (likely(end_offset < DP_RX_BUFFER_SIZE)) { + skb_put(skb, end_offset); + } else { + ath12k_warn(ab, "invalid offset received on mon stats dest %u\n", @@ -82,3 +84,6 @@ Signed-off-by: P Praneesh __skb_queue_tail(&skb_list, skb); move_next: ath12k_dp_mon_buf_replenish(ab, buf_ring, 1); +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/681-ath11k-Encoding-regdb.bin-in-board-2.bin.patch b/feeds/ipq95xx/mac80211/patches/qca/681-ath11k-Encoding-regdb.bin-in-board-2.bin.patch deleted file mode 100644 index fcb64bb82..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/681-ath11k-Encoding-regdb.bin-in-board-2.bin.patch +++ /dev/null @@ -1,540 +0,0 @@ -From 280215228b96d7a6a4000a5f65bd015d7c21ffac Mon Sep 17 00:00:00 2001 -From: Karthik M -Date: Fri, 14 Oct 2022 20:28:38 +0530 -Subject: [PATCH] ath11k: Encoding regdb.bin in board-2.bin - -Add support to encode regdb.bin in board-2.bin along with the bdf files. - -Signed-off-by: Karthik M ---- - drivers/net/wireless/ath/ath11k/core.c | 96 ++++++++++++-------------- - drivers/net/wireless/ath/ath11k/core.h | 6 +- - drivers/net/wireless/ath/ath11k/hw.h | 2 + - drivers/net/wireless/ath/ath11k/qmi.c | 56 ++++++++++----- - drivers/net/wireless/ath/ath11k/qmi.h | 3 + - 5 files changed, 96 insertions(+), 67 deletions(-) - ---- a/drivers/net/wireless/ath/ath11k/core.c -+++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -149,7 +149,7 @@ static const struct ath11k_hw_params ath - .supports_suspend = false, - .hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074), - .reo_dest_ring_map_shift = HAL_REO_DEST_RING_CTRL_HASH_RING_SHIFT, -- .supports_regdb = false, -+ .supports_regdb = true, - .fix_l1ss = true, - .credit_flow = false, - .hal_params = &ath11k_hw_hal_params_ipq8074, -@@ -228,7 +228,7 @@ static const struct ath11k_hw_params ath - .supports_suspend = false, - .hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074), - .reo_dest_ring_map_shift = HAL_REO_DEST_RING_CTRL_HASH_RING_SHIFT, -- .supports_regdb = false, -+ .supports_regdb = true, - .fix_l1ss = true, - .credit_flow = false, - .max_tx_ring = DP_TCL_NUM_RING_MAX, -@@ -378,7 +378,7 @@ static const struct ath11k_hw_params ath - .supports_suspend = false, - .hal_desc_sz = sizeof(struct hal_rx_desc_qcn9074), - .reo_dest_ring_map_shift = HAL_REO_DEST_RING_CTRL_HASH_RING_SHIFT, -- .supports_regdb = false, -+ .supports_regdb = true, - .fix_l1ss = true, - .credit_flow = false, - .hal_params = &ath11k_hw_hal_params_ipq8074, -@@ -589,6 +589,7 @@ static const struct ath11k_hw_params ath - .hal_params = &ath11k_hw_hal_params_ipq8074, - .host_ce_config = ath11k_host_ce_config_qcn9074, - .reo_dest_ring_map_shift = HAL_REO_DEST_RING_CTRL_HASH_RING_SHIFT, -+ .supports_regdb = true, - .ce_count = 6, - .target_ce_config = ath11k_target_ce_config_wlan_ipq5018, - .target_ce_count = 9, -@@ -669,6 +670,7 @@ static const struct ath11k_hw_params ath - .idle_ps = false, - .supports_suspend = false, - .host_ce_config = ath11k_host_ce_config_qcn9074, -+ .supports_regdb = true, - .ce_count = 6, - .target_ce_config = ath11k_target_ce_config_wlan_ipq5018, - .target_ce_count = 9, -@@ -720,6 +722,7 @@ static const struct ath11k_hw_params ath - .regs = &ipq8074_regs, - .qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ8074, - .host_ce_config = ath11k_host_ce_config_ipq9574, -+ .supports_regdb = true, - .ce_count = 10, - .target_ce_config = ath11k_target_ce_config_wlan_ipq9574, - .target_ce_count = 10, -@@ -956,7 +959,7 @@ int ath11k_core_check_dt(struct ath11k_b - } - - static int ath11k_core_create_board_name(struct ath11k_base *ab, char *name, -- size_t name_len) -+ char *defaultname, size_t name_len) - { - /* strlen(',variant=') + strlen(ab->qmi.target.bdf_ext) */ - char variant[9 + ATH11K_QMI_BDF_EXT_STR_LENGTH] = { 0 }; -@@ -968,7 +971,8 @@ static int ath11k_core_create_board_name - switch (ab->id.bdf_search) { - case ATH11K_BDF_SEARCH_BUS_AND_BOARD: - scnprintf(name, name_len, -- "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x,qmi-chip-id=%d,qmi-board-id=%d%s", -+ "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x," -+ "subsystem-device=%04x,qmi-chip-id=%d,qmi-board-id=%d%s", - ath11k_bus_str(ab->hif.bus), - ab->id.vendor, ab->id.device, - ab->id.subsystem_vendor, -@@ -983,6 +987,12 @@ static int ath11k_core_create_board_name - ath11k_bus_str(ab->hif.bus), - ab->qmi.target.chip_id, - ab->qmi.target.board_id, variant); -+ -+ scnprintf(defaultname, name_len, -+ "bus=%s,qmi-chip-id=%d,qmi-board-id=%d%s", -+ ath11k_bus_str(ab->hif.bus), -+ ab->qmi.target.chip_id, -+ ATH11K_DEFAULT_ID, variant); - break; - } - -@@ -1025,7 +1035,9 @@ static int ath11k_core_parse_bd_ie_board - struct ath11k_board_data *bd, - const void *buf, size_t buf_len, - const char *boardname, -- int bd_ie_type) -+ int ie_id, -+ int name_id, -+ int data_id) - { - const struct ath11k_fw_ie *hdr; - bool name_match_found; -@@ -1035,7 +1047,7 @@ static int ath11k_core_parse_bd_ie_board - - name_match_found = false; - -- /* go through ATH11K_BD_IE_BOARD_ elements */ -+ /* go through ATH11K_BD_IE_BOARD_/ATH11K_BD_IE_REGDB_ elements */ - while (buf_len > sizeof(struct ath11k_fw_ie)) { - hdr = buf; - board_ie_id = le32_to_cpu(hdr->id); -@@ -1046,48 +1058,51 @@ static int ath11k_core_parse_bd_ie_board - buf += sizeof(*hdr); - - if (buf_len < ALIGN(board_ie_len, 4)) { -- ath11k_err(ab, "invalid ATH11K_BD_IE_BOARD length: %zu < %zu\n", -+ ath11k_err(ab, "invalid %s length: %zu < %zu\n", -+ ath11k_bd_ie_type_str(ie_id), - buf_len, ALIGN(board_ie_len, 4)); - ret = -EINVAL; - goto out; - } - -- switch (board_ie_id) { -- case ATH11K_BD_IE_BOARD_NAME: -+ if (board_ie_id == name_id) { - ath11k_dbg_dump(ab, ATH11K_DBG_BOOT, "board name", "", - board_ie_data, board_ie_len); - - if (board_ie_len != strlen(boardname)) -- break; -+ goto next; - - ret = memcmp(board_ie_data, boardname, strlen(boardname)); - if (ret) -- break; -+ goto next; - - name_match_found = true; - ath11k_dbg(ab, ATH11K_DBG_BOOT, -- "boot found match for name '%s'", -+ "boot found match %s for name '%s'", -+ ath11k_bd_ie_type_str(ie_id), - boardname); -- break; -- case ATH11K_BD_IE_BOARD_DATA: -+ } else if (board_ie_id == data_id) { - if (!name_match_found) - /* no match found */ -- break; -+ goto next; - - ath11k_dbg(ab, ATH11K_DBG_BOOT, -- "boot found board data for '%s'", boardname); -+ "boot found %s for '%s'", -+ ath11k_bd_ie_type_str(ie_id), -+ boardname); - - bd->data = board_ie_data; - bd->len = board_ie_len; - - ret = 0; - goto out; -- default: -- ath11k_warn(ab, "unknown ATH11K_BD_IE_BOARD found: %d\n", -+ } else { -+ ath11k_warn(ab, "unknown %s id found: %d\n", -+ ath11k_bd_ie_type_str(ie_id), - board_ie_id); -- break; - } - -+next: - /* jump over the padding */ - board_ie_len = ALIGN(board_ie_len, 4); - -@@ -1104,7 +1119,10 @@ out: - - static int ath11k_core_fetch_board_data_api_n(struct ath11k_base *ab, - struct ath11k_board_data *bd, -- const char *boardname) -+ const char *boardname, -+ int ie_id_match, -+ int name_id, -+ int data_id) - { - size_t len, magic_len; - const u8 *data; -@@ -1169,22 +1187,23 @@ static int ath11k_core_fetch_board_data_ - goto err; - } - -- switch (ie_id) { -- case ATH11K_BD_IE_BOARD: -+ if (ie_id == ie_id_match) { - ret = ath11k_core_parse_bd_ie_board(ab, bd, data, - ie_len, - boardname, -- ATH11K_BD_IE_BOARD); -+ ie_id_match, -+ name_id, -+ data_id); - if (ret == -ENOENT) - /* no match found, continue */ -- break; -+ goto next; - else if (ret) - /* there was an error, bail out */ - goto err; - /* either found or error, so stop searching */ - goto out; - } -- -+next: - /* jump over the padding */ - ie_len = ALIGN(ie_len, 4); - -@@ -1194,8 +1213,9 @@ static int ath11k_core_fetch_board_data_ - - out: - if (!bd->data || !bd->len) { -- ath11k_err(ab, -- "failed to fetch board data for %s from %s\n", -+ ath11k_dbg(ab, ATH11K_DBG_BOOT, -+ "failed to fetch %s for %s from %s\n", -+ ath11k_bd_ie_type_str(ie_id_match), - boardname, filepath); - ret = -ENODATA; - goto err; -@@ -1223,28 +1243,43 @@ int ath11k_core_fetch_board_data_api_1(s - return 0; - } - --#define BOARD_NAME_SIZE 200 - int ath11k_core_fetch_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd) - { -- char boardname[BOARD_NAME_SIZE]; -+ char boardname[BOARD_NAME_SIZE], boarddefaultname[BOARD_NAME_SIZE]; - int ret; - -- ret = ath11k_core_create_board_name(ab, boardname, BOARD_NAME_SIZE); -+ ret = ath11k_core_create_board_name(ab, boardname, boarddefaultname, -+ BOARD_NAME_SIZE); - if (ret) { - ath11k_err(ab, "failed to create board name: %d", ret); - return ret; - } - - ab->bd_api = 2; -- ret = ath11k_core_fetch_board_data_api_n(ab, bd, boardname); -+ ret = ath11k_core_fetch_board_data_api_n(ab, bd, boardname, -+ ATH11K_BD_IE_BOARD, -+ ATH11K_BD_IE_BOARD_NAME, -+ ATH11K_BD_IE_BOARD_DATA); -+ if (!ret) -+ goto success; -+ -+ ret = ath11k_core_fetch_board_data_api_n(ab, bd, boarddefaultname, -+ ATH11K_BD_IE_BOARD, -+ ATH11K_BD_IE_BOARD_NAME, -+ ATH11K_BD_IE_BOARD_DATA); - if (!ret) - goto success; - - ab->bd_api = 1; - ret = ath11k_core_fetch_board_data_api_1(ab, bd, ATH11K_DEFAULT_BOARD_FILE); - if (ret) { -- ath11k_err(ab, "failed to fetch board-2.bin or board.bin from %s\n", -+ ath11k_err(ab, "failed to fetch board.bin from %s\n", - ab->hw_params.fw.dir); -+ } else { -+ ret = ath11k_core_fetch_board_data_api_1(ab, bd, ATH11K_BOARD_API2_FILE); -+ if (ret) -+ ath11k_err(ab, "failed to fetch board-2.bin from %s\n", -+ ab->hw_params.fw.dir); - return ret; - } - -@@ -1255,14 +1290,42 @@ success: - - int ath11k_core_fetch_regdb(struct ath11k_base *ab, struct ath11k_board_data *bd) - { -+ char regdbname[REGDB_NAME_SIZE], regdbdefaultname[REGDB_NAME_SIZE]; - int ret; - -+ ret = ath11k_core_create_board_name(ab, regdbname, regdbdefaultname, -+ REGDB_NAME_SIZE); -+ -+ if (ret) { -+ ath11k_err(ab, "failed to create regdb name: %d", ret); -+ return ret; -+ } -+ -+ ab->bd_api = 2; -+ ret = ath11k_core_fetch_board_data_api_n(ab, bd, regdbname, -+ ATH11K_BD_IE_REGDB, -+ ATH11K_BD_IE_REGDB_NAME, -+ ATH11K_BD_IE_REGDB_DATA); -+ if (!ret) -+ goto success; -+ -+ ret = ath11k_core_fetch_board_data_api_n(ab, bd, regdbdefaultname, -+ ATH11K_BD_IE_REGDB, -+ ATH11K_BD_IE_REGDB_NAME, -+ ATH11K_BD_IE_REGDB_DATA); -+ if (!ret) -+ goto success; -+ -+ ab->bd_api = 1; - ret = ath11k_core_fetch_board_data_api_1(ab, bd, ATH11K_REGDB_FILE_NAME); -- if (ret) -- ath11k_dbg(ab, ATH11K_DBG_BOOT, "failed to fetch %s from %s\n", -+ if (ret) { -+ ath11k_err(ab, "failed to fetch %s file from %s\n", - ATH11K_REGDB_FILE_NAME, ab->hw_params.fw.dir); -- -- return ret; -+ return ret; -+ } -+success: -+ ath11k_dbg(ab, ATH11K_DBG_BOOT, "using board api %d\n", ab->bd_api); -+ return 0; - } - - static void ath11k_core_stop(struct ath11k_base *ab) ---- a/drivers/net/wireless/ath/ath11k/core.h -+++ b/drivers/net/wireless/ath/ath11k/core.h -@@ -84,6 +84,9 @@ enum ath11k_bdf_search { - ATH11K_BDF_SEARCH_BUS_AND_BOARD, - }; - -+#define BOARD_NAME_SIZE 100 -+#define REGDB_NAME_SIZE 100 -+ - enum wme_ac { - WME_AC_BE, - WME_AC_BK, -@@ -1466,7 +1469,8 @@ void ath11k_core_free(struct ath11k_base - int ath11k_core_fetch_bdf(struct ath11k_base *ath11k, - struct ath11k_board_data *bd); - int ath11k_config_qdss(struct ath11k_base *ab); --int ath11k_core_fetch_regdb(struct ath11k_base *ab, struct ath11k_board_data *bd); -+int ath11k_core_fetch_regdb(struct ath11k_base *ab, -+ struct ath11k_board_data *bd); - int ath11k_core_fetch_board_data_api_1(struct ath11k_base *ab, - struct ath11k_board_data *bd, - const char *name); ---- a/drivers/net/wireless/ath/ath11k/hw.h -+++ b/drivers/net/wireless/ath/ath11k/hw.h -@@ -106,6 +106,8 @@ struct ath11k_cfr_peer_tx_param; - #define ATH11K_AMSS_FILE "amss.bin" - #define ATH11K_M3_FILE "m3.bin" - #define ATH11K_REGDB_FILE_NAME "regdb.bin" -+#define ATH11K_REGDB_BINARY "regdb" -+#define ATH11K_DEFAULT_ID 255 - #define NODE_ID_BASE 0x27 - - enum ath11k_hw_rate_cck { -@@ -364,12 +366,32 @@ enum ath11k_bd_ie_board_type { - ATH11K_BD_IE_BOARD_DATA = 1, - }; - -+enum ath12k_bd_ie_regdb_type { -+ ATH11K_BD_IE_REGDB_NAME = 0, -+ ATH11K_BD_IE_REGDB_DATA = 1, -+}; -+ - enum ath11k_bd_ie_type { - /* contains sub IEs of enum ath11k_bd_ie_board_type */ - ATH11K_BD_IE_BOARD = 0, -- ATH11K_BD_IE_BOARD_EXT = 1, -+ ATH11K_BD_IE_REGDB = 1, -+ ATH11K_BD_IE_BOARD_EXT = 2, - }; - -+static inline const char *ath11k_bd_ie_type_str(enum ath11k_bd_ie_type type) -+{ -+ switch (type) { -+ case ATH11K_BD_IE_BOARD: -+ return "board data"; -+ case ATH11K_BD_IE_REGDB: -+ return "regdb data"; -+ case ATH11K_BD_IE_BOARD_EXT: -+ return "board data ext"; -+ } -+ -+ return "unknown"; -+} -+ - struct ath11k_hw_regs { - u32 hal_tcl1_ring_base_lsb; - u32 hal_tcl1_ring_base_msb; ---- a/drivers/net/wireless/ath/ath11k/qmi.c -+++ b/drivers/net/wireless/ath/ath11k/qmi.c -@@ -1409,6 +1409,24 @@ static struct qmi_elem_info qmi_wlanfw_c - eeprom_read_timeout), - }, - { -+ .data_type = QMI_OPT_FLAG, -+ .elem_len = 1, -+ .elem_size = sizeof(u8), -+ .array_type = NO_ARRAY, -+ .tlv_type = 0x24, -+ .offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01, -+ regdb_support_valid), -+ }, -+ { -+ .data_type = QMI_UNSIGNED_1_BYTE, -+ .elem_len = 1, -+ .elem_size = sizeof(u8), -+ .array_type = NO_ARRAY, -+ .tlv_type = 0x24, -+ .offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01, -+ regdb_support), -+ }, -+ { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, -@@ -3165,6 +3183,11 @@ static int ath11k_qmi_request_target_cap - ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi cal data supported from eeprom\n"); - } - -+ if (resp.regdb_support_valid) { -+ ab->qmi.target.regdb = resp.regdb_support; -+ ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi regdb download is supported\n"); -+ } -+ - ath11k_info(ab, "chip_id 0x%x chip_family 0x%x board_id 0x%x soc_id 0x%x\n", - ab->qmi.target.chip_id, ab->qmi.target.chip_family, - ab->qmi.target.board_id, ab->qmi.target.soc_id); -@@ -3199,7 +3222,7 @@ static int ath11k_qmi_load_file_target_m - - memset(&resp, 0, sizeof(resp)); - -- if (ab->bus_params.fixed_bdf_addr) { -+ if (ab->bus_params.fixed_bdf_addr && !ab->qmi.target.regdb) { - bdf_addr = ioremap(ab->hw_params.bdf_addr, ab->hw_params.fw.board_size); - if (!bdf_addr) { - ath11k_warn(ab, "qmi ioremap error for bdf_addr\n"); -@@ -3228,7 +3251,7 @@ static int ath11k_qmi_load_file_target_m - req->end = 1; - } - -- if (ab->bus_params.fixed_bdf_addr || -+ if ((ab->bus_params.fixed_bdf_addr && !ab->qmi.target.regdb) || - type == ATH11K_QMI_FILE_TYPE_EEPROM) { - req->data_valid = 0; - req->end = 1; -@@ -3237,7 +3260,7 @@ static int ath11k_qmi_load_file_target_m - memcpy(req->data, temp, req->data_len); - } - -- if (ab->bus_params.fixed_bdf_addr) { -+ if (ab->bus_params.fixed_bdf_addr && !ab->qmi.target.regdb) { - if (type == ATH11K_QMI_FILE_TYPE_CALDATA) - bdf_addr += ab->hw_params.fw.cal_offset; - -@@ -3276,7 +3299,7 @@ static int ath11k_qmi_load_file_target_m - goto err_iounmap; - } - -- if (ab->bus_params.fixed_bdf_addr || -+ if ((ab->bus_params.fixed_bdf_addr && !ab->qmi.target.regdb) || - type == ATH11K_QMI_FILE_TYPE_EEPROM) { - remaining = 0; - } else { -@@ -3289,7 +3312,7 @@ static int ath11k_qmi_load_file_target_m - } - - err_iounmap: -- if (ab->bus_params.fixed_bdf_addr) -+ if (ab->bus_params.fixed_bdf_addr && !ab->qmi.target.regdb) - iounmap(bdf_addr); - - err_free_req: -@@ -3335,22 +3358,23 @@ static int ath11k_qmi_load_bdf_qmi(struc - - if (regdb) { - ret = ath11k_core_fetch_regdb(ab, &bd); -+ if (ret) { -+ ath11k_warn(ab, "qmi failed to fetch regdb file: %d\n", ret); -+ goto out; -+ } -+ bdf_type = ATH11K_QMI_BDF_TYPE_REGDB; - } else { - ret = ath11k_core_fetch_bdf(ab, &bd); -- if (ret) -+ if (ret) { - ath11k_warn(ab, "qmi failed to fetch board file: %d\n", ret); -+ goto out; -+ } -+ if (bd.len >= SELFMAG && memcmp(bd.data, ELFMAG, SELFMAG) == 0) -+ bdf_type = ATH11K_QMI_BDF_TYPE_ELF; -+ else -+ bdf_type = ATH11K_QMI_BDF_TYPE_BIN; - } - -- if (ret) -- goto out; -- -- if (regdb) -- bdf_type = ATH11K_QMI_BDF_TYPE_REGDB; -- else if (bd.len >= SELFMAG && memcmp(bd.data, ELFMAG, SELFMAG) == 0) -- bdf_type = ATH11K_QMI_BDF_TYPE_ELF; -- else -- bdf_type = ATH11K_QMI_BDF_TYPE_BIN; -- - ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi bdf_type %d\n", bdf_type); - - fw_size = min_t(u32, ab->hw_params.fw.board_size, bd.len); ---- a/drivers/net/wireless/ath/ath11k/qmi.h -+++ b/drivers/net/wireless/ath/ath11k/qmi.h -@@ -177,6 +177,7 @@ struct target_info { - u32 soc_id; - u32 fw_version; - u32 eeprom_caldata; -+ u8 regdb; - char fw_build_timestamp[ATH11K_QMI_WLANFW_MAX_TIMESTAMP_LEN_V01 + 1]; - char fw_build_id[ATH11K_QMI_WLANFW_MAX_BUILD_ID_LEN_V01 + 1]; - char bdf_ext[ATH11K_QMI_BDF_EXT_STR_LENGTH]; -@@ -574,6 +575,8 @@ struct qmi_wlanfw_cap_resp_msg_v01 { - u32 otp_version; - u8 eeprom_read_timeout_valid; - u32 eeprom_read_timeout; -+ u8 regdb_support_valid; -+ u8 regdb_support; - }; - - struct qmi_wlanfw_cap_req_msg_v01 { diff --git a/feeds/ipq95xx/mac80211/patches/qca/681-ath12k-Adds-the-firmware-SSR-recovery-debugs.patch b/feeds/ipq95xx/mac80211/patches/qca/681-ath12k-Adds-the-firmware-SSR-recovery-debugs.patch deleted file mode 100644 index 90e0a2142..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/681-ath12k-Adds-the-firmware-SSR-recovery-debugs.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 8f5704eee10cf03caed35a4696a8e34187c972de Mon Sep 17 00:00:00 2001 -From: Sivashankari Madhavan -Date: Mon, 14 Nov 2022 15:19:13 +0530 -Subject: [PATCH] ath12k: Adds the firmware SSR recovery debugs - -Adds the debug print to ensure this is a simulated firmware crash -in the firmware SSR recovery case. - -root@OpenWrt:/# echo 1 > /sys/kernel/debug/ath12k//set_fw_recovery -root@OpenWrt:/# echo assert > /sys/kernel/debug/ath12k//simulate_fw_crash -.... -[ 235.647604] ath12k_pci 0003:01:00.0: group_id 12 4294902926ms before -[ 235.717724] ath12k_pci 0003:01:00.0: WLAN target is restarting -.... - -Signed-off-by: Sivashankari Madhavan ---- - drivers/net/wireless/ath/ath12k/coredump.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/net/wireless/ath/ath12k/coredump.c b/drivers/net/wireless/ath/ath12k/coredump.c -index 73e7851..10a15ff 100644 ---- a/drivers/net/wireless/ath/ath12k/coredump.c -+++ b/drivers/net/wireless/ath/ath12k/coredump.c -@@ -272,6 +272,7 @@ void ath12k_coredump_download_rddm(struct ath12k_base *ab) - - BUG_ON(1); - } else { -+ ath12k_info(ab, "WLAN target is restarting"); - ath12k_coredump_build_inline(ab, segment, num_seg); - } - --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/682-mac80211-WAR-to-fix-warning-during-AWGN-simulation-i.patch b/feeds/ipq95xx/mac80211/patches/qca/682-mac80211-WAR-to-fix-warning-during-AWGN-simulation-i.patch deleted file mode 100644 index 63f4612eb..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/682-mac80211-WAR-to-fix-warning-during-AWGN-simulation-i.patch +++ /dev/null @@ -1,40 +0,0 @@ -From d3b3d9b85c04c42286f56381687319379b09b069 Mon Sep 17 00:00:00 2001 -From: Ramya Gnanasekar -Date: Wed, 2 Nov 2022 10:27:17 +0530 -Subject: [PATCH] mac80211: WAR to fix warning during AWGN simulation in - repeater - -6 GHz has different power level for different modes and -hence channel context will be different for AP and STA -which is expected. - -During issue, since there are 2 channel context for AP and STA, -warning is thrown since AP thinks it as channel context for -different channels. - -Fixing the issue through WAR: by commenting the warning. - -Signed-off-by: Ramya Gnanasekar - -Index: b/net/mac80211/util.c -=================================================================== ---- a/net/mac80211/util.c 2022-11-03 09:43:07.993093213 +0530 -+++ b/net/mac80211/util.c 2022-11-03 09:46:40.575386832 +0530 -@@ -4145,12 +4145,11 @@ void ieee80211_awgn_detected_work(struct - } - mutex_unlock(&local->chanctx_mtx); - -- if (num_chanctx > 1) -- /* XXX: multi-channel is not supported yet */ -- WARN_ON_ONCE(1); -- else -- cfg80211_awgn_event(local->hw.wiphy, &chandef, GFP_KERNEL, -- local->chan_bw_interference_bitmap); -+ /* TODO: Validate number of channel context -+ * since multi-channel is not supported. -+ */ -+ cfg80211_awgn_event(local->hw.wiphy, &chandef, GFP_KERNEL, -+ local->chan_bw_interference_bitmap); - } - - void ieee80211_dfs_radar_detected_work(struct work_struct *work) diff --git a/feeds/ipq95xx/mac80211/patches/qca/683-ath12k-Debug-prints-to-prevent-buffer-overflow.patch b/feeds/ipq95xx/mac80211/patches/qca/683-ath12k-Debug-prints-to-prevent-buffer-overflow.patch index 5c856d624..ef625d74b 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/683-ath12k-Debug-prints-to-prevent-buffer-overflow.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/683-ath12k-Debug-prints-to-prevent-buffer-overflow.patch @@ -1,7 +1,7 @@ -From ceb2fcfd062fc4ab8180019b00e62fc292ece4d2 Mon Sep 17 00:00:00 2001 +From 5d42d095c5a898bf670f0271053fee4d9be0827d Mon Sep 17 00:00:00 2001 From: Manish Dharanenthiran -Date: Fri, 4 Nov 2022 10:23:58 +0530 -Subject: [PATCH] ath12k: [WAR] Add warning to detect buffer overflow +Date: Mon, 19 Dec 2022 14:24:55 +0530 +Subject: [PATCH] ath12k: Add warning to detect buffer overflow During Mesh 4 node testing, ath12k receives SKB with header length greater than the MAX @@ -14,23 +14,22 @@ dumped the msdu data for debugging purpose. Signed-off-by: Manish Dharanenthiran --- - drivers/net/wireless/ath/ath12k/dp_rx.c | 57 +++++++++++++++++++++++-- - 1 file changed, 54 insertions(+), 3 deletions(-) + drivers/net/wireless/ath/ath12k/dp_rx.c | 51 +++++++++++++++++++++++-- + 1 file changed, 48 insertions(+), 3 deletions(-) --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -2239,6 +2239,31 @@ static int ath12k_dp_rx_crypto_icv_len(s - return 0; +@@ -2940,6 +2940,31 @@ static void ath12k_dp_rx_deliver_msdu(st + } } -+static int ath12k_dp_rx_check_msdu_header_len(struct ath12k *ar, ++static bool ath12k_dp_rx_check_max_nwifi_hdr_len(struct ath12k_base *ab, + struct hal_rx_desc *rx_desc, + struct sk_buff *msdu) +{ -+ struct ath12k_base *ab = ar->ab; ++ u8 decap_type; + struct ieee80211_hdr *hdr; + u32 hdr_len; -+ u8 decap_type; + + decap_type = ath12k_dp_rx_h_decap_type(ab, rx_desc); + if (decap_type == DP_RX_DECAP_TYPE_NATIVE_WIFI) { @@ -45,52 +44,18 @@ Signed-off-by: Manish Dharanenthiran + return true; + } + } ++ + return false; +} + - static void ath12k_dp_rx_h_undecap_nwifi(struct ath12k *ar, - struct sk_buff *msdu, - enum hal_encrypt_type enctype, -@@ -2246,7 +2271,7 @@ static void ath12k_dp_rx_h_undecap_nwifi - { - struct ath12k_base *ab = ar->ab; - struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu); -- u8 decap_hdr[DP_MAX_NWIFI_HDR_LEN]; -+ u8 decap_hdr[DP_MAX_NWIFI_HDR_LEN] = {0}; - struct ieee80211_hdr *hdr; - size_t hdr_len; - u8 *crypto_hdr; -@@ -2270,8 +2295,13 @@ static void ath12k_dp_rx_h_undecap_nwifi - - /* TODO Add other QoS ctl fields when required */ - -- /* copy decap header before overwriting for reuse below */ -- memcpy(decap_hdr, (uint8_t *)hdr, hdr_len); -+ if (hdr_len > DP_MAX_NWIFI_HDR_LEN) { -+ ath12k_err(ab, "hdr len received in %s is greater than MAX LEN [%u > %d]\n", -+ __func__, (unsigned int)hdr_len, DP_MAX_NWIFI_HDR_LEN); -+ } else { -+ /* copy decap header before overwriting for reuse below */ -+ memcpy(decap_hdr, (uint8_t *)hdr, hdr_len); -+ } - - /* Rebuild crypto header for mac80211 use */ - if (!(status->flag & RX_FLAG_IV_STRIPPED)) { -@@ -2284,7 +2314,8 @@ static void ath12k_dp_rx_h_undecap_nwifi - memcpy(skb_push(msdu, - IEEE80211_QOS_CTL_LEN), &qos_ctl, - IEEE80211_QOS_CTL_LEN); -- memcpy(skb_push(msdu, hdr_len), decap_hdr, hdr_len); -+ memcpy(skb_push(msdu, hdr_len), decap_hdr[0] ? decap_hdr : (uint8_t *)hdr, -+ hdr_len); - } - - static void ath12k_dp_rx_h_undecap_raw(struct ath12k *ar, struct sk_buff *msdu, -@@ -2935,6 +2966,11 @@ static int ath12k_dp_rx_process_msdu(str + static int ath12k_dp_rx_process_msdu(struct ath12k *ar, + struct sk_buff *msdu, + struct sk_buff_head *msdu_list, +@@ -2999,6 +3024,11 @@ static int ath12k_dp_rx_process_msdu(str } } -+ if (ath12k_dp_rx_check_msdu_header_len(ar, rx_desc, msdu)) { ++ if (ath12k_dp_rx_check_max_nwifi_hdr_len(ab, rx_desc, msdu)) { + ret = -EINVAL; + goto free_out; + } @@ -98,42 +63,21 @@ Signed-off-by: Manish Dharanenthiran ath12k_dp_rx_h_mpdu(ar, msdu, rx_desc, rx_status, fast_rx); if (*fast_rx) return 0; -@@ -3288,6 +3324,9 @@ mic_fail: - RX_FLAG_IV_STRIPPED | RX_FLAG_DECRYPTED; - skb_pull(msdu, hal_rx_desc_sz); - -+ if (ath12k_dp_rx_check_msdu_header_len(ar, rx_desc, msdu)) -+ return -EINVAL; -+ - ath12k_dp_rx_h_ppdu(ar, rx_desc, rxs); - ath12k_dp_rx_h_undecap(ar, msdu, rx_desc, - HAL_ENCRYPT_TYPE_TKIP_MIC, rxs, true); -@@ -3999,6 +4038,10 @@ static int ath12k_dp_rx_h_null_q_desc(st +@@ -4066,6 +4096,9 @@ static int ath12k_dp_rx_h_null_q_desc(st skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len); skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes); } -+ -+ if (ath12k_dp_rx_check_msdu_header_len(ar, desc, msdu)) ++ if (ath12k_dp_rx_check_max_nwifi_hdr_len(ab, desc, msdu)) + return -EINVAL; + ath12k_dp_rx_h_ppdu(ar, desc, status); fast_rx = false; ath12k_dp_rx_h_mpdu(ar, msdu, desc, status, &fast_rx); -@@ -4084,6 +4127,9 @@ static bool ath12k_dp_rx_h_tkip_mic_err( +@@ -4194,6 +4227,9 @@ static bool ath12k_dp_rx_h_4addr_null_fr skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len); skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes); -+ if (ath12k_dp_rx_check_msdu_header_len(ar, desc, msdu)) -+ return true; -+ - ath12k_dp_rx_h_ppdu(ar, desc, status); - - status->flag |= (RX_FLAG_MMIC_STRIPPED | RX_FLAG_MMIC_ERROR | -@@ -4125,6 +4171,9 @@ static bool ath12k_dp_rx_h_4addr_null_fr - skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len); - skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes); - -+ if (ath12k_dp_rx_check_msdu_header_len(ar, rx_desc, msdu)) ++ if (ath12k_dp_rx_check_max_nwifi_hdr_len(ab, rx_desc, msdu)) + return true; + ath12k_dp_rx_h_ppdu(ar, rx_desc, status); diff --git a/feeds/ipq95xx/mac80211/patches/qca/683-ath12k-add-Wide-Band-Scan-support.patch b/feeds/ipq95xx/mac80211/patches/qca/683-ath12k-add-Wide-Band-Scan-support.patch deleted file mode 100644 index 22144ecc7..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/683-ath12k-add-Wide-Band-Scan-support.patch +++ /dev/null @@ -1,596 +0,0 @@ -From 7ee97b019fd4ff21b0eb260c08e0824ec2f16ea8 Mon Sep 17 00:00:00 2001 -From: Thiraviyam Mariyappan -Date: Sat, 5 Nov 2022 18:46:08 +0530 -Subject: [PATCH] ath12k: add Wide Band Scan support - -Wide Band Scan allows to perform off-channel scan on requested channel -/frequency along with corresponding phy mode/bandwidth (40Mhz, 80Mhz). -This helps to capture off-channel data frames in AP+monitor mode and -also doing wide band scan instead of normal 20Mhz scan before -spectral dump, allows to fetch FFT reports for the complete requested -bandwidth (40Mhz, 80Mhz). -Below are the FW expectations and configs from host to request Wide -Band Scan, -1. SCAN_PHYMODE_SUPPORT service advertised from FW. -2. SCAN_CHAN_LIST_CMD updated with the phymode and other channel - params of the requested channel to do wide band scan. -3. START_SCAN_CMD updated with all the seven supported TLVs and - PHYMODE TLV being the last.PHYMODE TLV holds the (wmi_phy_mode + 1) - value corresponding to wide band scan channel. Scan flags - scan_f_wide_band and scan_f_passive need to be set for wide band - scan request from host. -In case of supporting NL80211_EXT_FEATURE_WIDE_BAND_SCAN, -cfg80211_scan_request holds the cfg80211_chan_def of the requested -channel from which we update the center frequencies and phymode params -needed for SCAN_CHAN_LIST_CMD and START_SCAN_CMD to FW. - -Signed-off-by: Thiraviyam Mariyappan -Signed-off-by: Sathishkumar Muruganandam ---- - drivers/net/wireless/ath/ath12k/mac.c | 42 ++++++- - drivers/net/wireless/ath/ath12k/reg.c | 94 +-------------- - drivers/net/wireless/ath/ath12k/wmi.c | 164 ++++++++++++++++++++++++-- - drivers/net/wireless/ath/ath12k/wmi.h | 34 +++++- - 4 files changed, 225 insertions(+), 109 deletions(-) - ---- a/drivers/net/wireless/ath/ath12k/mac.c -+++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -4190,6 +4190,28 @@ static int ath12k_start_scan(struct ath1 - return 0; - } - -+static void ath12k_mac_update_scan_params(struct cfg80211_scan_request *req, -+ struct scan_req_params *arg) -+{ -+ int i; -+ struct chan_info *chan = &arg->chan_list.chan[0]; -+ enum nl80211_band band; -+ enum nl80211_chan_width width; -+ -+ if (req->chandef) { -+ band = req->chandef->chan->band; -+ width = req->chandef->width; -+ } -+ -+ arg->chan_list.num_chan = req->n_channels; -+ for (i = 0; i < arg->chan_list.num_chan; i++) { -+ if (req->channels) -+ chan[i].freq = req->channels[i]->center_freq; -+ if (req->chandef) -+ chan[i].phymode = ath12k_phymodes[band][width]; -+ } -+} -+ - static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_scan_request *hw_req) -@@ -4198,7 +4220,7 @@ static int ath12k_mac_op_hw_scan(struct - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); - struct cfg80211_scan_request *req = &hw_req->req; - struct ath12k *ar; -- struct scan_req_params arg; -+ struct scan_req_params *arg; - int ret = 0; - int i; - bool create = true; -@@ -4273,35 +4295,45 @@ static int ath12k_mac_op_hw_scan(struct - if (ret) - goto exit; - -- memset(&arg, 0, sizeof(arg)); -- ath12k_wmi_start_scan_init(ar, &arg); -- arg.vdev_id = arvif->vdev_id; -- arg.scan_id = ATH12K_SCAN_ID; -+ arg = kzalloc(sizeof(*arg), GFP_KERNEL); -+ if (!arg) { -+ ret = -ENOMEM; -+ goto exit; -+ } -+ -+ ath12k_wmi_start_scan_init(ar, arg); -+ arg->vdev_id = arvif->vdev_id; -+ arg->scan_id = ATH12K_SCAN_ID; - - if (req->ie_len) { -- arg.extraie.len = req->ie_len; -- arg.extraie.ptr = kzalloc(req->ie_len, GFP_KERNEL); -- memcpy(arg.extraie.ptr, req->ie, req->ie_len); -+ arg->extraie.len = req->ie_len; -+ arg->extraie.ptr = kzalloc(req->ie_len, GFP_KERNEL); -+ memcpy(arg->extraie.ptr, req->ie, req->ie_len); - } - - if (req->n_ssids) { -- arg.num_ssids = req->n_ssids; -- for (i = 0; i < arg.num_ssids; i++) { -- arg.ssid[i].length = req->ssids[i].ssid_len; -- memcpy(&arg.ssid[i].ssid, req->ssids[i].ssid, -+ arg->num_ssids = req->n_ssids; -+ for (i = 0; i < arg->num_ssids; i++) { -+ arg->ssid[i].length = req->ssids[i].ssid_len; -+ memcpy(&arg->ssid[i].ssid, req->ssids[i].ssid, - req->ssids[i].ssid_len); - } - } else { -- arg.scan_flags |= WMI_SCAN_FLAG_PASSIVE; -+ arg->scan_flags |= WMI_SCAN_FLAG_PASSIVE; - } - -- if (req->n_channels) { -- arg.num_chan = req->n_channels; -- for (i = 0; i < arg.num_chan; i++) -- arg.chan_list[i] = req->channels[i]->center_freq; -- } -+ if (req->n_channels) -+ ath12k_mac_update_scan_params(req, arg); - -- ret = ath12k_start_scan(ar, &arg); -+ if (req->chandef) { -+ arg->scan_f_wide_band = true; -+ arg->scan_f_passive = true; -+ arg->chandef = req->chandef; -+ ret = ath12k_wmi_update_scan_chan_list(ar, arg); -+ if (ret) -+ goto exit; -+ } -+ ret = ath12k_start_scan(ar, arg); - if (ret) { - ath12k_warn(ar->ab, "failed to start hw scan: %d\n", ret); - spin_lock_bh(&ar->data_lock); -@@ -4311,12 +4343,16 @@ static int ath12k_mac_op_hw_scan(struct - - /* Add a 200ms margin to account for event/command processing */ - ieee80211_queue_delayed_work(ar->ah->hw, &ar->scan.timeout, -- msecs_to_jiffies(arg.max_scan_time + -+ msecs_to_jiffies(arg->max_scan_time + - ATH12K_MAC_SCAN_TIMEOUT_MSECS)); - - exit: -- if (req->ie_len) -- kfree(arg.extraie.ptr); -+ if (arg) { -+ if (arg->extraie.ptr) -+ kfree(arg->extraie.ptr); -+ -+ kfree(arg); -+ } - - mutex_unlock(&ar->conf_mutex); - return ret; -@@ -11175,6 +11211,11 @@ static int __ath12k_mac_register(struct - wiphy_ext_feature_set(hw->wiphy, - NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP); - } -+ if (test_bit(WMI_TLV_SERVICE_SCAN_PHYMODE_SUPPORT, -+ ar->ab->wmi_ab.svc_map)) -+ wiphy_ext_feature_set(hw->wiphy, -+ NL80211_EXT_FEATURE_WIDE_BAND_SCAN); -+ - - return 0; - } ---- a/drivers/net/wireless/ath/ath12k/reg.c -+++ b/drivers/net/wireless/ath/ath12k/reg.c -@@ -161,99 +161,7 @@ exit: - - int ath12k_reg_update_chan_list(struct ath12k *ar) - { -- struct ieee80211_supported_band **bands; -- struct scan_chan_list_params *params; -- struct ieee80211_channel *channel; -- struct ieee80211_hw *hw = ar->ah->hw; -- struct channel_param *ch; -- enum nl80211_band band; -- int num_channels = 0; -- int params_len; -- int i, ret; -- -- bands = hw->wiphy->bands; -- for (band = 0; band < NUM_NL80211_BANDS; band++) { -- if (!(ar->mac.sbands[band].channels && bands[band])) -- continue; -- -- for (i = 0; i < bands[band]->n_channels; i++) { -- if (bands[band]->channels[i].flags & -- IEEE80211_CHAN_DISABLED) -- continue; -- -- num_channels++; -- } -- } -- -- if (WARN_ON(!num_channels)) -- return -EINVAL; -- -- params_len = sizeof(struct scan_chan_list_params) + -- num_channels * sizeof(struct channel_param); -- params = kzalloc(params_len, GFP_KERNEL); -- -- if (!params) -- return -ENOMEM; -- -- params->pdev_id = ar->pdev->pdev_id; -- params->nallchans = num_channels; -- -- ch = params->ch_param; -- -- for (band = 0; band < NUM_NL80211_BANDS; band++) { -- if (!(ar->mac.sbands[band].channels && bands[band])) -- continue; -- -- for (i = 0; i < bands[band]->n_channels; i++) { -- channel = &bands[band]->channels[i]; -- -- if (channel->flags & IEEE80211_CHAN_DISABLED) -- continue; -- -- /* TODO: Set to true/false based on some condition? */ -- ch->allow_ht = true; -- ch->allow_vht = true; -- ch->allow_he = true; -- -- ch->dfs_set = -- !!(channel->flags & IEEE80211_CHAN_RADAR); -- ch->is_chan_passive = !!(channel->flags & -- IEEE80211_CHAN_NO_IR); -- ch->is_chan_passive |= ch->dfs_set; -- ch->mhz = channel->center_freq; -- ch->cfreq1 = channel->center_freq; -- ch->minpower = 0; -- ch->maxpower = channel->max_power * 2; -- ch->maxregpower = channel->max_reg_power * 2; -- ch->antennamax = channel->max_antenna_gain * 2; -- -- /* TODO: Use appropriate phymodes */ -- if (channel->band == NL80211_BAND_2GHZ) -- ch->phy_mode = MODE_11G; -- else -- ch->phy_mode = MODE_11A; -- -- if (channel->band == NL80211_BAND_6GHZ && -- cfg80211_channel_is_psc(channel)) -- ch->psc_channel = true; -- -- ath12k_dbg(ar->ab, ATH12K_DBG_WMI, -- "mac channel [%d/%d] freq %d maxpower %d regpower %d antenna %d mode %d\n", -- i, params->nallchans, -- ch->mhz, ch->maxpower, ch->maxregpower, -- ch->antennamax, ch->phy_mode); -- -- ch++; -- /* TODO: use quarrter/half rate, cfreq12, dfs_cfreq2 -- * set_agile, reg_class_idx -- */ -- } -- } -- -- ret = ath12k_wmi_send_scan_chan_list_cmd(ar, params); -- kfree(params); -- -- return ret; -+ return ath12k_wmi_update_scan_chan_list(ar, NULL); - } - - static void ath12k_copy_regd(struct ieee80211_regdomain *regd_orig, ---- a/drivers/net/wireless/ath/ath12k/wmi.c -+++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -2076,6 +2076,110 @@ int ath12k_wmi_send_peer_assoc_cmd(struc - return ret; - } - -+int ath12k_wmi_update_scan_chan_list(struct ath12k *ar, -+ struct scan_req_params *arg) -+{ -+ struct ieee80211_supported_band **bands; -+ struct scan_chan_list_params *params; -+ struct channel_param *ch; -+ struct cfg80211_chan_def *chandef; -+ struct ieee80211_channel *channel, *req_channel; -+ enum nl80211_band band; -+ int num_channels = 0; -+ int params_len, i, ret; -+ bool found = false; -+ -+ bands = ar->ah->hw->wiphy->bands; -+ for (band = 0; band < NUM_NL80211_BANDS; band++) { -+ if (!bands[band]) -+ continue; -+ for (i = 0; i < bands[band]->n_channels; i++) { -+ if (bands[band]->channels[i].flags & -+ IEEE80211_CHAN_DISABLED) -+ continue; -+ -+ num_channels++; -+ } -+ } -+ -+ if (WARN_ON(!num_channels)) -+ return -EINVAL; -+ -+ params_len = sizeof(struct scan_chan_list_params) + -+ num_channels * sizeof(struct channel_param); -+ params = kzalloc(params_len, GFP_KERNEL); -+ -+ if (!params) -+ return -ENOMEM; -+ -+ params->pdev_id = ar->pdev->pdev_id; -+ params->nallchans = num_channels; -+ -+ ch = params->ch_param; -+ chandef = arg ? arg->chandef : NULL; -+ req_channel = chandef ? chandef->chan : NULL; -+ -+ for (band = 0; band < NUM_NL80211_BANDS; band++) { -+ if (!bands[band]) -+ continue; -+ -+ for (i = 0; i < bands[band]->n_channels; i++) { -+ channel = &bands[band]->channels[i]; -+ -+ if (channel->flags & IEEE80211_CHAN_DISABLED) -+ continue; -+ -+ if (req_channel && !found && -+ req_channel->center_freq == channel->center_freq) { -+ ch->mhz = arg->chan_list.chan[0].freq; -+ ch->cfreq1 = chandef->center_freq1; -+ ch->cfreq2 = chandef->center_freq2; -+ -+ ch->phy_mode = arg->chan_list.chan[0].phymode; -+ channel = req_channel; -+ found = true; -+ } else { -+ ch->mhz = channel->center_freq; -+ ch->cfreq1 = channel->center_freq; -+ ch->phy_mode = (channel->band == NL80211_BAND_2GHZ) ? -+ MODE_11G : MODE_11A; -+ } -+ -+ /* TODO: Set to true/false based on some condition? */ -+ ch->allow_ht = true; -+ ch->allow_vht = true; -+ ch->allow_he = true; -+ -+ ch->dfs_set = -+ !!(channel->flags & IEEE80211_CHAN_RADAR); -+ ch->is_chan_passive = !!(channel->flags & -+ IEEE80211_CHAN_NO_IR); -+ ch->is_chan_passive |= ch->dfs_set; -+ ch->minpower = 0; -+ ch->maxpower = channel->max_power * 2; -+ ch->maxregpower = channel->max_reg_power * 2; -+ ch->antennamax = channel->max_antenna_gain * 2; -+ -+ if (channel->band == NL80211_BAND_6GHZ && -+ cfg80211_channel_is_psc(channel)) -+ ch->psc_channel = true; -+ -+ ath12k_dbg(ar->ab, ATH12K_DBG_WMI, -+ "mac channel [%d/%d] freq %d maxpower %d regpower %d antenna %d mode %d flag 0x%x chandef: %pk\n", -+ i, params->nallchans, -+ ch->mhz, ch->maxpower, ch->maxregpower, -+ ch->antennamax, ch->phy_mode, channel->flags, -+ chandef); -+ ch++; -+ } -+ } -+ -+ ret = ath12k_wmi_send_scan_chan_list_cmd(ar, params); -+ kfree(params); -+ -+ return ret; -+} -+ - void ath12k_wmi_start_scan_init(struct ath12k *ar, - struct scan_req_params *arg) - { -@@ -2195,15 +2299,17 @@ int ath12k_wmi_send_scan_start_cmd(struc - void *ptr; - int i, ret, len; - u32 *tmp_ptr; -+ u8 *phy_ptr; - u8 extraie_len_with_pad = 0; - struct hint_short_ssid *s_ssid = NULL; - struct hint_bssid *hint_bssid = NULL; -+ u8 phymode_roundup = 0; - - len = sizeof(*cmd); - - len += TLV_HDR_SIZE; -- if (params->num_chan) -- len += params->num_chan * sizeof(u32); -+ if (params->chan_list.num_chan) -+ len += params->chan_list.num_chan * sizeof(u32); - - len += TLV_HDR_SIZE; - if (params->num_ssids) -@@ -2227,6 +2333,20 @@ int ath12k_wmi_send_scan_start_cmd(struc - len += TLV_HDR_SIZE + - params->num_hint_s_ssid * sizeof(struct hint_short_ssid); - -+ len += TLV_HDR_SIZE; -+ if (params->scan_f_en_ie_whitelist_in_probe) -+ len += params->ie_whitelist.num_vendor_oui * -+ sizeof(struct wmi_vendor_oui); -+ -+ len += TLV_HDR_SIZE; -+ if (params->scan_f_wide_band) -+ phymode_roundup = -+ roundup(params->chan_list.num_chan * sizeof(u8), -+ sizeof(u32)); -+ -+ len += phymode_roundup; -+ -+ - skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len); - if (!skb) - return -ENOMEM; -@@ -2258,7 +2378,7 @@ int ath12k_wmi_send_scan_start_cmd(struc - cmd->max_scan_time = params->max_scan_time; - cmd->probe_delay = params->probe_delay; - cmd->burst_duration = params->burst_duration; -- cmd->num_chan = params->num_chan; -+ cmd->num_chan = params->chan_list.num_chan; - cmd->num_bssid = params->num_bssid; - cmd->num_ssids = params->num_ssids; - cmd->ie_len = params->extraie.len; -@@ -2266,7 +2386,7 @@ int ath12k_wmi_send_scan_start_cmd(struc - - ptr += sizeof(*cmd); - -- len = params->num_chan * sizeof(u32); -+ len = params->chan_list.num_chan * sizeof(u32); - - tlv = ptr; - tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_UINT32) | -@@ -2274,8 +2394,8 @@ int ath12k_wmi_send_scan_start_cmd(struc - ptr += TLV_HDR_SIZE; - tmp_ptr = (u32 *)ptr; - -- for (i = 0; i < params->num_chan; ++i) -- tmp_ptr[i] = params->chan_list[i]; -+ for (i = 0; i < params->chan_list.num_chan; ++i) -+ tmp_ptr[i] = params->chan_list.chan[i].freq; - - ptr += len; - -@@ -2327,6 +2447,36 @@ int ath12k_wmi_send_scan_start_cmd(struc - - ptr += extraie_len_with_pad; - -+ len = params->ie_whitelist.num_vendor_oui * sizeof(struct wmi_vendor_oui); -+ tlv = ptr; -+ tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_STRUCT) | -+ FIELD_PREP(WMI_TLV_LEN, len); -+ ptr += TLV_HDR_SIZE; -+ -+ if (params->scan_f_en_ie_whitelist_in_probe) { -+ /* TODO: fill vendor OUIs for probe req ie whitelisting */ -+ /* currently added for FW TLV validation */ -+ } -+ -+ ptr += cmd->num_vendor_oui * sizeof(struct wmi_vendor_oui); -+ -+ len = phymode_roundup; -+ tlv = ptr; -+ tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_BYTE) | -+ FIELD_PREP(WMI_TLV_LEN, len); -+ ptr += TLV_HDR_SIZE; -+ -+ /* Wide Band Scan */ -+ if (params->scan_f_wide_band) { -+ phy_ptr = ptr; -+ /* Add PHY mode TLV for wide band scan with phymode + 1 value -+ * so that phymode '0' is ignored by FW as default value. -+ */ -+ for (i = 0; i < params->chan_list.num_chan; ++i) -+ phy_ptr[i] = params->chan_list.chan[i].phymode + 1; -+ } -+ ptr += phymode_roundup; -+ - if (params->num_hint_s_ssid) { - len = params->num_hint_s_ssid * sizeof(struct hint_short_ssid); - tlv = ptr; -@@ -2516,7 +2666,7 @@ int ath12k_wmi_send_scan_chan_list_cmd(s - FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); - cmd->pdev_id = chan_list->pdev_id; - cmd->num_scan_chans = num_send_chans; -- if (num_sends) -+ if (num_sends || chan_list->append_chan_list) - cmd->flags |= WMI_APPEND_TO_EXISTING_CHAN_LIST_FLAG; - - ath12k_dbg(ar->ab, ATH12K_DBG_WMI, ---- a/drivers/net/wireless/ath/ath12k/wmi.h -+++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -3401,7 +3401,7 @@ enum scan_dwelltime_adaptive_mode { - - #define WLAN_SCAN_MAX_NUM_SSID 10 - #define WLAN_SCAN_MAX_NUM_BSSID 10 --#define WLAN_SCAN_MAX_NUM_CHANNELS 40 -+#define WLAN_SCAN_MAX_NUM_CHANNELS 60 - - #define WLAN_SSID_MAX_LEN 32 - -@@ -3442,6 +3442,12 @@ struct wmi_vdev_set_tpc_power_cmd { - - - #define WMI_IE_BITMAP_SIZE 8 -+#define PROBE_REQ_MAX_OUIS 16 -+ -+struct wmi_vendor_oui { -+ u32 tlv_header; -+ u32 oui_type_subtype; /* vendor OUI type and subtype */ -+}; - - #define WMI_SCAN_MAX_NUM_SSID 0x0A - /* prefix used by scan requestor ids on the host */ -@@ -3576,6 +3582,22 @@ struct hint_bssid { - struct wmi_mac_addr bssid; - }; - -+struct chan_info { -+ u32 freq; -+ u32 phymode; -+}; -+ -+struct chan_list { -+ u32 num_chan; -+ struct chan_info chan[WLAN_SCAN_MAX_NUM_CHANNELS]; -+}; -+ -+struct probe_req_whitelist { -+ u32 ie_bitmap[WMI_IE_BITMAP_SIZE]; -+ u32 num_vendor_oui; -+ u32 voui[PROBE_REQ_MAX_OUIS]; -+}; -+ - struct scan_req_params { - u32 scan_id; - u32 scan_req_id; -@@ -3638,17 +3660,17 @@ struct scan_req_params { - scan_f_forced:1, - scan_f_2ghz:1, - scan_f_5ghz:1, -- scan_f_80mhz:1; -+ scan_f_wide_band:1; - }; - u32 scan_flags; - }; - enum scan_dwelltime_adaptive_mode adaptive_dwell_time_mode; - u32 burst_duration; -- u32 num_chan; - u32 num_bssid; - u32 num_ssids; - u32 n_probes; -- u32 chan_list[WLAN_SCAN_MAX_NUM_CHANNELS]; -+ struct chan_list chan_list; -+ struct cfg80211_chan_def *chandef; - u32 notify_scan_events; - struct wlan_ssid ssid[WLAN_SCAN_MAX_NUM_SSID]; - struct wmi_mac_addr bssid_list[WLAN_SCAN_MAX_NUM_BSSID]; -@@ -3659,6 +3681,7 @@ struct scan_req_params { - u32 num_hint_bssid; - struct hint_short_ssid hint_s_ssid[WLAN_SCAN_MAX_HINT_S_SSID]; - struct hint_bssid hint_bssid[WLAN_SCAN_MAX_HINT_BSSID]; -+ struct probe_req_whitelist ie_whitelist; - }; - - struct wmi_ssid_arg { -@@ -4041,6 +4064,7 @@ struct wmi_stop_scan_cmd { - struct scan_chan_list_params { - u32 pdev_id; - u16 nallchans; -+ bool append_chan_list; - struct channel_param ch_param[1]; - }; - -@@ -6285,6 +6309,8 @@ int ath12k_wmi_vdev_delete(struct ath12k - void ath12k_wmi_start_scan_init(struct ath12k *ar, struct scan_req_params *arg); - int ath12k_wmi_send_scan_start_cmd(struct ath12k *ar, - struct scan_req_params *params); -+int ath12k_wmi_update_scan_chan_list(struct ath12k *ar, -+ struct scan_req_params *params); - int ath12k_wmi_send_scan_stop_cmd(struct ath12k *ar, - struct scan_cancel_param *param); - int ath12k_wmi_send_wmm_update_cmd_tlv(struct ath12k *ar, u32 vdev_id, diff --git a/feeds/ipq95xx/mac80211/patches/qca/683-ath12k-do-not-drop-data-frames-from-unassociated-sta.patch b/feeds/ipq95xx/mac80211/patches/qca/683-ath12k-do-not-drop-data-frames-from-unassociated-sta.patch index 38cb3c2bb..360de7471 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/683-ath12k-do-not-drop-data-frames-from-unassociated-sta.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/683-ath12k-do-not-drop-data-frames-from-unassociated-sta.patch @@ -1,6 +1,6 @@ -From 11c7570b3133ab635ffba74f81c037203ddd676c Mon Sep 17 00:00:00 2001 +From 589cb7039d7774f13781a8ca4783fb994c5ee096 Mon Sep 17 00:00:00 2001 From: Hari Chandrakanthan -Date: Mon, 7 Nov 2022 12:43:18 +0530 +Date: Mon, 7 Nov 2022 11:33:50 +0530 Subject: [PATCH] ath12k : do not drop data frames from unassociated stations in the driver @@ -27,14 +27,14 @@ Signed-off-by: Hari Chandrakanthan 1 file changed, 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c -index 803d396..fbc6c15 100644 +index 4074633..74d2128 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -3971,12 +3971,6 @@ static int ath12k_dp_rx_h_null_q_desc(struct ath12k *ar, struct sk_buff *msdu, +@@ -3987,12 +3987,6 @@ static int ath12k_dp_rx_h_null_q_desc(struct ath12k *ar, struct sk_buff *msdu, msdu_len = ath12k_dp_rx_h_msdu_len(ab, desc); peer_id = ath12k_dp_rx_h_peer_id(ab, desc); -- if(!ath12k_peer_find_by_id(ab, peer_id)) { +- if (!ath12k_peer_find_by_id(ab, peer_id)) { - ath12k_dbg(ab, ATH12K_DBG_DATA, "invalid peer id received in wbm err pkt%d\n", - peer_id); - return -EINVAL; diff --git a/feeds/ipq95xx/mac80211/patches/qca/684-01-cfg80211-DFS-radar-detection-with-radar-bitmap.patch b/feeds/ipq95xx/mac80211/patches/qca/684-01-cfg80211-DFS-radar-detection-with-radar-bitmap.patch new file mode 100644 index 000000000..5c728ed90 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/684-01-cfg80211-DFS-radar-detection-with-radar-bitmap.patch @@ -0,0 +1,145 @@ +From 6305016b60ecea78d8f0333cfed05d8aa2314766 Mon Sep 17 00:00:00 2001 +From: Nagarajan Maran +Date: Mon, 7 Nov 2022 02:17:32 +0530 +Subject: [PATCH] cfg80211: DFS radar detection with radar bitmap + +Signed-off-by: Nagarajan Maran +--- + include/net/cfg80211.h | 1 + + include/uapi/linux/nl80211.h | 4 ++++ + net/wireless/chan.c | 27 ++++++++++++++++++++------- + net/wireless/mlme.c | 1 + + net/wireless/nl80211.c | 4 ++++ + net/wireless/reg.c | 1 + + 6 files changed, 31 insertions(+), 7 deletions(-) + +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -788,6 +788,7 @@ struct cfg80211_chan_def { + u16 freq1_offset; + u16 ru_punct_bitmap; + bool ru_punct_bitmap_supp_he; ++ u16 radar_bitmap; + }; + + /* +--- a/include/uapi/linux/nl80211.h ++++ b/include/uapi/linux/nl80211.h +@@ -2816,6 +2816,10 @@ enum nl80211_commands { + * multiple physical hardware under a wiphy can use this attribute, + * see &enum nl80211_multi_hw_mac_attrs. + * ++ * @NL80211_ATTR_RADAR_BITMAP: (u16) RADAR bitmap where the lowest bit ++ * corresponds to the lowest 20MHZ channel. Each bit set to 1 ++ * indicates that radar is detected in that sub-channel. ++ * + * @NUM_NL80211_ATTR: total number of nl80211_attrs available + * @NL80211_ATTR_MAX: highest attribute number currently defined + * @__NL80211_ATTR_AFTER_LAST: internal use +@@ -3367,6 +3371,8 @@ enum nl80211_attrs { + NL80211_ATTR_AP_PS, + + NL80211_ATTR_MULTI_HW_MACS, ++ ++ NL80211_ATTR_RADAR_BITMAP, + /* add attributes here, update the policy in nl80211.c */ + + __NL80211_ATTR_AFTER_LAST, +--- a/net/wireless/chan.c ++++ b/net/wireless/chan.c +@@ -564,20 +564,30 @@ EXPORT_SYMBOL(cfg80211_chandef_compatibl + + static void cfg80211_set_chans_dfs_state(struct wiphy *wiphy, u32 center_freq, + u32 bandwidth, +- enum nl80211_dfs_state dfs_state) ++ enum nl80211_dfs_state dfs_state, ++ u16 radar_bitmap) + { + struct ieee80211_channel *c; + u32 freq; ++ int i; + +- for (freq = center_freq - bandwidth/2 + 10; +- freq <= center_freq + bandwidth/2 - 10; +- freq += 20) { ++ for (i = 0, freq = center_freq - bandwidth / 2 + 10; ++ freq <= center_freq + bandwidth / 2 - 10; ++ freq += 20, i++) { + c = ieee80211_get_channel(wiphy, freq); +- if (!c || !(c->flags & IEEE80211_CHAN_RADAR)) ++ if (!c || !(c->flags & IEEE80211_CHAN_RADAR) ) + continue; + +- c->dfs_state = dfs_state; +- c->dfs_state_entered = jiffies; ++ if (radar_bitmap && dfs_state == NL80211_DFS_UNAVAILABLE) { ++ if (radar_bitmap & 1 << i) { ++ c->dfs_state = dfs_state; ++ c->dfs_state_entered = jiffies; ++ } ++ } ++ else { ++ c->dfs_state = dfs_state; ++ c->dfs_state_entered = jiffies; ++ } + } + } + +@@ -595,12 +605,15 @@ void cfg80211_set_dfs_state(struct wiphy + return; + + cfg80211_set_chans_dfs_state(wiphy, chandef->center_freq1, +- width, dfs_state); ++ width, dfs_state, ++ chandef->radar_bitmap); + + if (!chandef->center_freq2) + return; ++ + cfg80211_set_chans_dfs_state(wiphy, chandef->center_freq2, +- width, dfs_state); ++ width, dfs_state, ++ chandef->radar_bitmap >> 4); + } + + static u32 cfg80211_get_start_freq(u32 center_freq, +--- a/net/wireless/mlme.c ++++ b/net/wireless/mlme.c +@@ -959,6 +959,7 @@ void __cfg80211_radar_event(struct wiphy + + memcpy(&rdev->radar_chandef, chandef, sizeof(struct cfg80211_chan_def)); + queue_work(cfg80211_wq, &rdev->propagate_radar_detect_wk); ++ chandef->radar_bitmap = 0; + } + EXPORT_SYMBOL(__cfg80211_radar_event); + +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -858,6 +858,7 @@ static const struct nla_policy nl80211_p + [NL80211_ATTR_RU_PUNCT_SUPP_HE] = { .type = NLA_FLAG }, + [NL80211_ATTR_RU_PUNCT_BITMAP] = { .type = NLA_U16 }, + [NL80211_ATTR_AP_PS] = NLA_POLICY_MAX(NLA_U8, 1), ++ [NL80211_ATTR_RADAR_BITMAP] = { .type = NLA_U16 }, + }; + + /* policy for the key attributes */ +@@ -4031,6 +4032,9 @@ static int nl80211_send_chandef(struct s + return -ENOBUFS; + } + ++ if (nla_put_u16(msg, NL80211_ATTR_RADAR_BITMAP, chandef->radar_bitmap)) ++ return -ENOBUFS; ++ + return 0; + } + +--- a/net/wireless/reg.c ++++ b/net/wireless/reg.c +@@ -4325,6 +4325,7 @@ void regulatory_propagate_dfs_state(stru + + nl80211_radar_notify(rdev, chandef, event, NULL, GFP_KERNEL); + } ++ chandef->radar_bitmap = 0; + } + + static int __init regulatory_init_db(void) diff --git a/feeds/ipq95xx/mac80211/patches/qca/684-02-mac80211-radar-bitmap-during-DFS-radar-detection.patch b/feeds/ipq95xx/mac80211/patches/qca/684-02-mac80211-radar-bitmap-during-DFS-radar-detection.patch new file mode 100644 index 000000000..55e3c235c --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/684-02-mac80211-radar-bitmap-during-DFS-radar-detection.patch @@ -0,0 +1,138 @@ +From 8402e052f7e0f2e9e4af88308077628e67aa6132 Mon Sep 17 00:00:00 2001 +From: Nagarajan Maran +Date: Mon, 7 Nov 2022 02:22:24 +0530 +Subject: [PATCH] mac80211: radar bitmap during DFS radar detection + +Signed-off-by: Nagarajan Maran +--- + include/net/mac80211.h | 9 +++++++++ + net/mac80211/ieee80211_i.h | 1 + + net/mac80211/util.c | 14 ++++++++++++++ + 3 files changed, 24 insertions(+) + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -6565,6 +6565,15 @@ void ieee80211_cqm_beacon_loss_notify(st + void ieee80211_radar_detected(struct ieee80211_hw *hw); + + /** ++ * ieee80211_radar_detected_bitmap - inform that a radar was detected ++ * with bitmap ++ * @hw: pointer as obtained from ieee80211_alloc_hw() ++ * @radar_bitmap: denotes the bitmap of radar. ++ */ ++void ieee80211_radar_detected_bitmap(struct ieee80211_hw *hw, u16 radar_bitmap); ++ ++ ++/** + * ieee80211_chswitch_done - Complete channel switch process + * @vif: &struct ieee80211_vif pointer from the add_interface callback. + * @success: make the channel switch successful or not +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1296,6 +1296,11 @@ struct mac80211_memory_stats { + atomic_t malloc_size; + }; + ++struct channel_radar_info { ++ struct list_head list; ++ u16 radar_bitmap; ++}; ++ + struct ieee80211_local { + /* embed the driver visible part. + * don't cast (use the static inlines below), but we keep +@@ -1390,6 +1395,7 @@ struct ieee80211_local { + bool wowlan; + + struct work_struct radar_detected_work; ++ struct list_head radar_info_list; + + /* number of RX chains the hardware has */ + u8 rx_chains; +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -4271,10 +4271,10 @@ void ieee80211_awgn_detected_work(struct + local->chan_bw_interference_bitmap); + } + +-void ieee80211_dfs_radar_detected_work(struct work_struct *work) ++static void ++ieee80211_dfs_radar_detected_processing(struct ieee80211_local *local, ++ u16 radar_bitmap) + { +- struct ieee80211_local *local = +- container_of(work, struct ieee80211_local, radar_detected_work); + struct cfg80211_chan_def chandef = local->hw.conf.chandef; + struct ieee80211_chanctx *ctx; + int num_chanctx = 0; +@@ -4293,6 +4293,8 @@ void ieee80211_dfs_radar_detected_work(s + ieee80211_dfs_cac_cancel(local); + wiphy_unlock(local->hw.wiphy); + ++ chandef.radar_bitmap = radar_bitmap; ++ + if (num_chanctx > 1) + /* XXX: multi-channel is not supported yet */ + WARN_ON(1); +@@ -4300,6 +4302,26 @@ void ieee80211_dfs_radar_detected_work(s + cfg80211_radar_event(local->hw.wiphy, &chandef, GFP_KERNEL); + } + ++void ieee80211_dfs_radar_detected_work(struct work_struct *work) ++{ ++ struct ieee80211_local *local = ++ container_of(work, struct ieee80211_local, radar_detected_work); ++ struct channel_radar_info *radar_info, *temp; ++ u16 radar_bitmap; ++ ++ if (list_empty(&local->radar_info_list)) ++ return ieee80211_dfs_radar_detected_processing(local, 0); ++ ++ list_for_each_entry_safe(radar_info, temp, &local->radar_info_list, list) { ++ radar_bitmap = radar_info->radar_bitmap; ++ ++ ieee80211_dfs_radar_detected_processing(local, radar_bitmap); ++ ++ list_del(&radar_info->list); ++ kfree(radar_info); ++ } ++} ++ + void ieee80211_radar_detected(struct ieee80211_hw *hw) + { + struct ieee80211_local *local = hw_to_local(hw); +@@ -4310,6 +4332,23 @@ void ieee80211_radar_detected(struct iee + } + EXPORT_SYMBOL(ieee80211_radar_detected); + ++void ieee80211_radar_detected_bitmap(struct ieee80211_hw *hw, u16 radar_bitmap) ++{ ++ struct ieee80211_local *local = hw_to_local(hw); ++ struct channel_radar_info *radar_info; ++ ++ radar_info = kzalloc(sizeof(*radar_info), GFP_ATOMIC); ++ if (!radar_info) ++ return; ++ ++ INIT_LIST_HEAD(&radar_info->list); ++ radar_info->radar_bitmap = radar_bitmap; ++ ++ list_add_tail(&radar_info->list, &local->radar_info_list); ++ schedule_work(&local->radar_detected_work); ++} ++EXPORT_SYMBOL(ieee80211_radar_detected_bitmap); ++ + void ieee80211_awgn_detected(struct ieee80211_hw *hw, u32 chan_bw_interference_bitmap) + { + struct ieee80211_local *local = hw_to_local(hw); +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -782,6 +782,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_ + wiphy->extended_capabilities_len = + ARRAY_SIZE(local->ext_capa); + ++ INIT_LIST_HEAD(&local->radar_info_list); + INIT_LIST_HEAD(&local->interfaces); + INIT_LIST_HEAD(&local->mon_list); + diff --git a/feeds/ipq95xx/mac80211/patches/qca/684-03-ath12k-radar-bitmap-generation-durin-DFS-radar-detec.patch b/feeds/ipq95xx/mac80211/patches/qca/684-03-ath12k-radar-bitmap-generation-durin-DFS-radar-detec.patch new file mode 100644 index 000000000..47bf33daa --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/684-03-ath12k-radar-bitmap-generation-durin-DFS-radar-detec.patch @@ -0,0 +1,136 @@ +From 4eac23e7b738f462d7c1b208118dbb3bca2beebe Mon Sep 17 00:00:00 2001 +From: Nagarajan Maran +Date: Mon, 7 Nov 2022 02:28:19 +0530 +Subject: [PATCH] ath12k: radar-bitmap generation durin DFS radar detection + +Signed-off-by: Nagarajan Maran +--- + drivers/net/wireless/ath/ath12k/mac.c | 27 ++++++++++++ + drivers/net/wireless/ath/ath12k/mac.h | 1 + + drivers/net/wireless/ath/ath12k/wmi.c | 59 ++++++++++++++++++++++++++- + 3 files changed, 86 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -13307,3 +13307,30 @@ void ath12k_mac_destroy(struct ath12k_hw + ag->ah[i] = NULL; + } + } ++ ++u16 ath12k_calculate_subchannel_count(enum nl80211_chan_width width) { ++ u16 width_num = 0; ++ ++ switch (width) { ++ case NL80211_CHAN_WIDTH_20_NOHT: ++ case NL80211_CHAN_WIDTH_20: ++ width_num = 20; ++ break; ++ case NL80211_CHAN_WIDTH_40: ++ width_num = 40; ++ break; ++ case NL80211_CHAN_WIDTH_80: ++ case NL80211_CHAN_WIDTH_80P80: ++ width_num = 80; ++ break; ++ case NL80211_CHAN_WIDTH_160: ++ width_num = 160; ++ break; ++ case NL80211_CHAN_WIDTH_320: ++ width_num = 320; ++ break; ++ default: ++ break; ++ } ++ return width_num/20; ++} +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -8085,6 +8085,71 @@ ath12k_wmi_pdev_csa_switch_count_status_ + kfree(tb); + } + ++static void ath12k_dfs_calculate_subchannels(struct ath12k_base *ab, const struct wmi_pdev_radar_ev *radar) ++{ ++ struct ath12k *ar; ++ u32 center_freq; ++ enum nl80211_chan_width width; ++ u32 radar_found_freq, sub_channel_cfreq, radar_found_freq_low, radar_found_freq_high; ++ u16 radar_bitmap = 0, subchannel_count; ++ int i; ++ struct cfg80211_chan_def *chandef; ++ struct ath12k_mac_any_chandef_arg arg; ++ ++ ar = ath12k_mac_get_ar_by_pdev_id(ab, radar->pdev_id); ++ ++ arg.ar = ar; ++ arg.def = NULL; ++ ieee80211_iter_chan_contexts_atomic(ar->ah->hw, ath12k_mac_get_any_chandef_iter, ++ &arg); ++ chandef = arg.def; ++ if (!chandef) { ++ ath12k_err(ab, "Channel information not available\n"); ++ return; ++ } ++ ++ ath12k_dbg(ab, ATH12K_DBG_WMI, " Operating freq:%u center_freq1:%u, center_freq2:%u", ++ chandef->chan->center_freq, chandef->center_freq1,chandef->center_freq2); ++ ++ width = chandef->width; ++ subchannel_count = ath12k_calculate_subchannel_count(width); ++ if (!subchannel_count) ++ { ++ ath12k_warn(ab, "invalid subchannel count for bandwith=%d\n",width); ++ goto mark_radar; ++ } ++ ++ center_freq = chandef->center_freq1; ++ ++ radar_found_freq = center_freq + radar->freq_offset; ++ ++ radar_found_freq_high = radar_found_freq_low = radar_found_freq; ++ ++ if (radar->is_chirp) { ++ radar_found_freq_high = radar_found_freq_high + 10; ++ radar_found_freq_low = radar_found_freq_low - 10; ++ } ++ ++ sub_channel_cfreq = center_freq - ((subchannel_count-1) * 10); ++ ++ for(i=0; i < subchannel_count; i++) { ++ if (sub_channel_cfreq >= 5260 && ++ ((radar_found_freq_low >= sub_channel_cfreq-10 && ++ radar_found_freq_low <= sub_channel_cfreq+10) || ++ (radar_found_freq_high >= sub_channel_cfreq-10 && ++ radar_found_freq_high <= sub_channel_cfreq+10))) ++ radar_bitmap |= 1 << i; ++ ++ sub_channel_cfreq += 20; ++ } ++ ++ ath12k_dbg(ab, ATH12K_DBG_WMI, "radar_bitmap:%0x and subchannel_count:%d", ++ radar_bitmap,subchannel_count); ++ ++mark_radar: ++ ieee80211_radar_detected_bitmap(ar->ah->hw,radar_bitmap); ++} ++ + static void + ath12k_wmi_pdev_dfs_radar_detected_event(struct ath12k_base *ab, struct sk_buff *skb) + { +@@ -8128,7 +8193,7 @@ ath12k_wmi_pdev_dfs_radar_detected_event + if (ar->dfs_block_radar_events) + ath12k_info(ab, "DFS Radar detected, but ignored as requested\n"); + else +- ieee80211_radar_detected(ar->ah->hw); ++ ath12k_dfs_calculate_subchannels(ab, ev); + + exit: + kfree(tb); +--- a/drivers/net/wireless/ath/ath12k/mac.h ++++ b/drivers/net/wireless/ath/ath12k/mac.h +@@ -173,4 +173,5 @@ int ath12k_mac_mlo_setup(struct ath12k_h + int ath12k_mac_mlo_ready(struct ath12k_hw *ah); + int ath12k_mac_mlo_teardown(struct ath12k_hw *ah); + bool ath12k_mac_is_ml_arvif(struct ath12k_link_vif *arvif); ++u16 ath12k_calculate_subchannel_count(enum nl80211_chan_width width); + #endif diff --git a/feeds/ipq95xx/mac80211/patches/qca/684-04-ath12k-Add-debugfs-extended-support-radar-simulation.patch b/feeds/ipq95xx/mac80211/patches/qca/684-04-ath12k-Add-debugfs-extended-support-radar-simulation.patch new file mode 100644 index 000000000..2906cccba --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/684-04-ath12k-Add-debugfs-extended-support-radar-simulation.patch @@ -0,0 +1,134 @@ +From f4057b3056b851ac030d31dc1d9b868d96047465 Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Mon, 21 Nov 2022 10:40:02 +0530 +Subject: [PATCH] ath12k: Add debugfs extended support for radar simulation + +Add support for simulating dfs with additional parameters +using the same radar simluation debugfs command + +echo > +/sys/kernel/debug/ieee80211/phyX/ath12k/dfs_simulate_radar + +Signed-off-by: Nagarajan Maran +Signed-off-by: Harshitha Prem +--- + drivers/net/wireless/ath/ath12k/debugfs.c | 62 ++++++++++++++++++++++- + drivers/net/wireless/ath/ath12k/wmi.c | 4 +- + drivers/net/wireless/ath/ath12k/wmi.h | 2 +- + 3 files changed, 64 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -1487,14 +1487,74 @@ static const struct file_operations fops + .open = simple_open + }; + ++#define SEGMENT_ID GENMASK(1,0) ++#define CHRIP_ID BIT(2) ++#define OFFSET GENMASK(10,3) ++#define DETECTOR_ID GENMASK(12,11) ++ + static ssize_t ath12k_write_simulate_radar(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) + { + struct ath12k *ar = file->private_data; + int ret; ++ u32 radar_params; ++ u8 agile = 0, segment = 0, chirp = 0; ++ int offset = 0; ++ int len; ++ char buf[64], *token, *sptr; ++ ++ len = min(count, sizeof(buf) - 1); ++ if (copy_from_user(buf, user_buf, len)) { ++ return -EFAULT; ++ } ++ ++ /* For backward compatibility */ ++ if (len <= 2) ++ goto send_cmd; ++ ++ buf[len] = '\0'; ++ sptr = buf; ++ token = strsep(&sptr, " "); ++ if (!token) ++ return -EINVAL; ++ ++ if (kstrtou8(token, 16, &segment)) ++ return -EINVAL; ++ ++ token = strsep(&sptr, " "); ++ if (!token) ++ return -EINVAL; ++ ++ if (kstrtou8(token, 16, &chirp)) ++ return -EINVAL; ++ ++ token = strsep(&sptr, " "); ++ if (!token) ++ return -EINVAL; ++ ++ if (kstrtoint(token, 10, &offset)) ++ return -EINVAL; ++ ++ token = strsep(&sptr, " "); ++ if (!token) ++ return -EINVAL; ++ ++ if (kstrtou8(token, 16, &agile)) ++ return -EINVAL; ++ ++ if ((segment > 1) || (chirp > 1) || (agile > 2)) ++ return -EINVAL; ++ ++ if (agile && ar->agile_chandef.chan == NULL) ++ return -EINVAL; ++send_cmd: ++ radar_params = u32_encode_bits(segment, SEGMENT_ID) | ++ u32_encode_bits(chirp, CHRIP_ID) | ++ u32_encode_bits(offset, OFFSET) | ++ u32_encode_bits(agile, DETECTOR_ID); + +- ret = ath12k_wmi_simulate_radar(ar); ++ ret = ath12k_wmi_simulate_radar(ar,radar_params); + if (ret) + return ret; + +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -9709,7 +9709,7 @@ ath12k_wmi_send_unit_test_cmd(struct ath + return ret; + } + +-int ath12k_wmi_simulate_radar(struct ath12k *ar) ++int ath12k_wmi_simulate_radar(struct ath12k *ar, u32 radar_params) + { + struct ath12k_link_vif *arvif; + struct ath12k_vif *ahvif; +@@ -9730,11 +9730,10 @@ int ath12k_wmi_simulate_radar(struct ath + + dfs_args[DFS_TEST_CMDID] = 0; + dfs_args[DFS_TEST_PDEV_ID] = ar->pdev->pdev_id; +- /* Currently we could pass segment_id(b0 - b1), chirp(b2) +- * freq offset (b3 - b10) to unit test. For simulation +- * purpose this can be set to 0 which is valid. ++ /* Currently we pass segment_id(b0 - b1), chirp(b2) ++ * freq offset (b3 - b10), detector_id(b11 - b12) to unit test. + */ +- dfs_args[DFS_TEST_RADAR_PARAM] = 0; ++ dfs_args[DFS_TEST_RADAR_PARAM] = radar_params; + + wmi_ut.vdev_id = cpu_to_le32(arvif->vdev_id); + wmi_ut.module_id = cpu_to_le32(DFS_UNIT_TEST_MODULE); +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -6458,7 +6458,7 @@ size_t ath12k_wmi_fw_stats_num_vdevs(str + void ath12k_wmi_fw_stats_fill(struct ath12k *ar, + struct ath12k_fw_stats *fw_stats, u32 stats_id, + char *buf); +-int ath12k_wmi_simulate_radar(struct ath12k *ar); ++int ath12k_wmi_simulate_radar(struct ath12k *ar, u32 radar_params); + int ath12k_wmi_simulate_awgn(struct ath12k *ar, u32 chan_bw_interference_bitmap); + int ath12k_wmi_send_twt_enable_cmd(struct ath12k *ar, u32 pdev_id); + int ath12k_wmi_send_twt_disable_cmd(struct ath12k *ar, u32 pdev_id); diff --git a/feeds/ipq95xx/mac80211/patches/qca/684-ath12k-Check-skb_headroom-before-using-skb_push.patch b/feeds/ipq95xx/mac80211/patches/qca/684-ath12k-Check-skb_headroom-before-using-skb_push.patch index 7d279f41f..c539d58d5 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/684-ath12k-Check-skb_headroom-before-using-skb_push.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/684-ath12k-Check-skb_headroom-before-using-skb_push.patch @@ -16,19 +16,17 @@ Signed-off-by: Manish Dharanenthiran drivers/net/wireless/ath/ath12k/dp_rx.c | 41 +++++++++++++++++++++++++ 1 file changed, 41 insertions(+) -diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c -index b83eb2b..7bc28ab 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -2274,6 +2274,7 @@ static void ath12k_dp_rx_h_undecap_nwifi(struct ath12k *ar, - u8 decap_hdr[DP_MAX_NWIFI_HDR_LEN] = {0}; +@@ -2305,6 +2305,7 @@ static void ath12k_dp_rx_h_undecap_nwifi + u8 decap_hdr[DP_MAX_NWIFI_HDR_LEN]; struct ieee80211_hdr *hdr; size_t hdr_len; + int expand_by = 0; u8 *crypto_hdr; u16 qos_ctl = 0; -@@ -2305,15 +2306,31 @@ static void ath12k_dp_rx_h_undecap_nwifi(struct ath12k *ar, +@@ -2331,15 +2332,31 @@ static void ath12k_dp_rx_h_undecap_nwifi /* Rebuild crypto header for mac80211 use */ if (!(status->flag & RX_FLAG_IV_STRIPPED)) { @@ -57,10 +55,10 @@ index b83eb2b..7bc28ab 100644 + if (WARN_ON_ONCE(pskb_expand_head(msdu, expand_by, 0, GFP_ATOMIC))) + return; + } - memcpy(skb_push(msdu, hdr_len), decap_hdr[0] ? decap_hdr : (uint8_t *)hdr, - hdr_len); + memcpy(skb_push(msdu, hdr_len), decap_hdr, hdr_len); } -@@ -2389,16 +2406,27 @@ static void ath12k_get_dot11_hdr_from_rx_desc(struct ath12k *ar, + +@@ -2414,16 +2431,27 @@ static void ath12k_get_dot11_hdr_from_rx struct ieee80211_hdr *hdr; u16 qos_ctl = 0; __le16 fc; @@ -88,34 +86,35 @@ index b83eb2b..7bc28ab 100644 skb_push(msdu, hdr_len); hdr = (struct ieee80211_hdr *)msdu->data; hdr->frame_control = fc; -@@ -2430,6 +2458,7 @@ static void ath12k_dp_rx_h_undecap_eth(struct ath12k *ar, +@@ -2455,6 +2483,7 @@ static void ath12k_dp_rx_h_undecap_eth(s struct ethhdr *eth; u8 da[ETH_ALEN]; u8 sa[ETH_ALEN]; + int expand_by; struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu); - struct ath12k_dp_rfc1042_hdr rfc = {0xaa, 0xaa, 0x03, {0x00, 0x00, 0x00}}; + struct ath12k_dp_rx_rfc1042_hdr rfc = {0xaa, 0xaa, 0x03, {0x00, 0x00, 0x00}}; -@@ -2438,6 +2467,11 @@ static void ath12k_dp_rx_h_undecap_eth(struct ath12k *ar, +@@ -2463,6 +2492,11 @@ static void ath12k_dp_rx_h_undecap_eth(s ether_addr_copy(sa, eth->h_source); rfc.snap_type = eth->h_proto; skb_pull(msdu, sizeof(struct ethhdr)); -+ if (skb_headroom(msdu) < sizeof(struct ath12k_dp_rfc1042_hdr)) { -+ expand_by = sizeof(struct ath12k_dp_rfc1042_hdr) - skb_headroom(msdu); ++ if (skb_headroom(msdu) < sizeof(struct ath12k_dp_rx_rfc1042_hdr)) { ++ expand_by = sizeof(struct ath12k_dp_rx_rfc1042_hdr) - skb_headroom(msdu); + if (WARN_ON_ONCE(pskb_expand_head(msdu, expand_by, 0, GFP_ATOMIC))) + return; + } - memcpy(skb_push(msdu, sizeof(struct ath12k_dp_rfc1042_hdr)), &rfc, - sizeof(struct ath12k_dp_rfc1042_hdr)); + memcpy(skb_push(msdu, sizeof(struct ath12k_dp_rx_rfc1042_hdr)), &rfc, + sizeof(struct ath12k_dp_rx_rfc1042_hdr)); ath12k_get_dot11_hdr_from_rx_desc(ar, msdu, rxcb, status, enctype); -@@ -2829,12 +2863,18 @@ static void ath12k_dp_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *nap +@@ -2860,6 +2894,7 @@ static void ath12k_dp_rx_deliver_msdu(st struct ath12k_peer *peer; struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu); u8 decap = DP_RX_DECAP_TYPE_RAW; + int expand_by; bool is_mcbc = rxcb->is_mcbc; bool is_eapol = rxcb->is_eapol; - struct ath12k_sta *arsta = NULL; + struct ath12k_link_sta *arsta = NULL; +@@ -2867,6 +2902,11 @@ static void ath12k_dp_rx_deliver_msdu(st if (status->encoding == RX_ENC_HE && !(status->flag & RX_FLAG_RADIOTAP_HE) && !(status->flag & RX_FLAG_SKIP_MONITOR)) { @@ -127,7 +126,7 @@ index b83eb2b..7bc28ab 100644 he = skb_push(msdu, sizeof(known)); memcpy(he, &known, sizeof(known)); status->flag |= RX_FLAG_RADIOTAP_HE; -@@ -2892,6 +2932,7 @@ static void ath12k_dp_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *nap +@@ -2924,6 +2964,7 @@ static void ath12k_dp_rx_deliver_msdu(st !(is_mcbc && rx_status->flag & RX_FLAG_DECRYPTED)) rx_status->flag |= RX_FLAG_8023; @@ -135,6 +134,3 @@ index b83eb2b..7bc28ab 100644 ieee80211_rx_napi(ar->ah->hw, pubsta, msdu, napi); if (ath12k_debugfs_is_extd_rx_stats_enabled(ar)) { --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/684-mac80211-Update-CCFS1-in-EHT-Operation-IE-for-11s.patch b/feeds/ipq95xx/mac80211/patches/qca/684-mac80211-Update-CCFS1-in-EHT-Operation-IE-for-11s.patch new file mode 100644 index 000000000..ea067744f --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/684-mac80211-Update-CCFS1-in-EHT-Operation-IE-for-11s.patch @@ -0,0 +1,116 @@ +From cdb9bac8b25fb7dddf4d08ba01e5520f6dcbbc77 Mon Sep 17 00:00:00 2001 +From: Ramya Gnanasekar +Date: Mon, 14 Nov 2022 16:21:57 +0530 +Subject: [PATCH] mac80211: Update CCFS1 in EHT Operation IE for 11s +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +IEEE P802.11be™/D2.0, May 2022 mandates CCFS1 filed in EHT +Operation IE. +Also, as per, IEEE P802.11be™/D2.0, May 2022 EHT operational IE +should contain Basic MCS and NSS set field for every spatial +stream. Added code changes to copy the mcs nss set from EHT +capabilities + +Signed-off-by: Ramya Gnanasekar +Signed-off-by: Aditya Kumar Singh +--- + net/mac80211/ieee80211_i.h | 3 ++- + net/mac80211/mesh.c | 3 ++- + net/mac80211/util.c | 28 ++++++++++++++++++++++++---- + 3 files changed, 28 insertions(+), 6 deletions(-) + +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index 80ecf85..1faad33 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -2439,7 +2439,8 @@ u8 *ieee80211_ie_build_eht_cap(u8 *pos, + const struct ieee80211_sta_he_cap *he_cap, + const struct ieee80211_sta_eht_cap *eht_cap, + u8 *end); +-u8 *ieee80211_ie_build_eht_oper(u8 *pos, struct cfg80211_chan_def *chandef); ++u8 *ieee80211_ie_build_eht_oper(u8 *pos, struct cfg80211_chan_def *chandef, ++ const struct ieee80211_sta_eht_cap *eht_cap); + int ieee80211_parse_bitrates(enum nl80211_chan_width width, + const struct ieee80211_supported_band *sband, + const u8 *srates, int srates_len, u32 *rates); +diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c +index b616687..e19dacd 100644 +--- a/net/mac80211/mesh.c ++++ b/net/mac80211/mesh.c +@@ -705,7 +705,8 @@ int mesh_add_eht_oper_ie(struct ieee80211_sub_if_data *sdata, + return -ENOMEM; + + pos = skb_put(skb, len); +- ieee80211_ie_build_eht_oper(pos, &sdata->vif.bss_conf.chandef); ++ ieee80211_ie_build_eht_oper(pos, &sdata->vif.bss_conf.chandef, ++ eht_cap); + + return 0; + } +diff --git a/net/mac80211/util.c b/net/mac80211/util.c +index 383d6b4..b87a2db 100644 +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -3371,7 +3371,8 @@ out: + return pos; + } + +-u8 *ieee80211_ie_build_eht_oper(u8 *pos, struct cfg80211_chan_def *chandef) ++u8 *ieee80211_ie_build_eht_oper(u8 *pos, struct cfg80211_chan_def *chandef, ++ const struct ieee80211_sta_eht_cap *eht_cap) + { + struct ieee80211_eht_operation *eht_oper; + struct ieee80211_eht_operation_info *eht_oper_info; +@@ -3393,12 +3394,30 @@ u8 *ieee80211_ie_build_eht_oper(u8 *pos, struct cfg80211_chan_def *chandef) + pos += sizeof(struct ieee80211_eht_operation_info) + + chandef->ru_punct_bitmap ? 2 : 0; + ++ eht_oper_info->ccfs0 = ++ ieee80211_frequency_to_channel(chandef->center_freq1); ++ if (chandef->center_freq2) ++ eht_oper_info->ccfs1 = ++ ieee80211_frequency_to_channel(chandef->center_freq2); ++ else ++ eht_oper_info->ccfs1 = 0; ++ + switch (chandef->width) { + case NL80211_CHAN_WIDTH_320: + chwidth = IEEE80211_EHT_OPER_CTRL_CHANWIDTH_320MHZ; ++ eht_oper_info->ccfs1 = eht_oper_info->ccfs0; ++ if (chandef->chan->center_freq < chandef->center_freq1) ++ eht_oper_info->ccfs0 -= 16; ++ else ++ eht_oper_info->ccfs0 += 16; + break; + case NL80211_CHAN_WIDTH_160: + chwidth = IEEE80211_EHT_OPER_CTRL_CHANWIDTH_160MHZ; ++ eht_oper_info->ccfs1 = eht_oper_info->ccfs0; ++ if (chandef->chan->center_freq < chandef->center_freq1) ++ eht_oper_info->ccfs0 -= 8; ++ else ++ eht_oper_info->ccfs0 -= 8; + break; + case NL80211_CHAN_WIDTH_80P80: + chwidth = IEEE80211_EHT_OPER_CTRL_CHANWIDTH_160MHZ; +@@ -3414,12 +3433,13 @@ u8 *ieee80211_ie_build_eht_oper(u8 *pos, struct cfg80211_chan_def *chandef) + break; + } + ++ memcpy(&eht_oper->basic_mcs_nss, ++ &eht_cap->eht_mcs_nss_supp.only_20mhz, ++ sizeof(struct ieee80211_eht_mcs_nss_supp_20mhz_only)); ++ + eht_oper->params |= IEEE80211_EHT_OPER_INFO_PRESENT; + + eht_oper_info->control = chwidth; +- eht_oper_info->ccfs0 = +- ieee80211_frequency_to_channel(chandef->center_freq1); +- eht_oper_info->ccfs1 = 0; /* How to get this? */ + + eht_oper->optional[0] = eht_oper_info->control; + eht_oper->optional[1] = eht_oper_info->ccfs0; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/685-01-wifi-ath12k-Moved-the-Tx-Descriptor-before-Rx-Descri.patch b/feeds/ipq95xx/mac80211/patches/qca/685-01-wifi-ath12k-Moved-the-Tx-Descriptor-before-Rx-Descri.patch new file mode 100644 index 000000000..fcaf56e49 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/685-01-wifi-ath12k-Moved-the-Tx-Descriptor-before-Rx-Descri.patch @@ -0,0 +1,142 @@ +From 7f06cfda943121374126a07b1cfe58d5540bf7c8 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Thu, 27 Oct 2022 17:14:06 +0530 +Subject: [PATCH] wifi: ath12k: Moved the Tx Descriptor before Rx + Descriptor in the SPT + +Here the plan is to move the Rx descriptor behind the Tx descriptor. +It will help in placing the Partner chip Rx descriptor based on the chip id. + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/dp.c | 63 +++++++++++++++------------- + drivers/net/wireless/ath/ath12k/dp.h | 6 ++- + 2 files changed, 40 insertions(+), 29 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -1238,7 +1238,6 @@ static void ath12k_dp_cc_cleanup(struct + dp->spt_info[i].vaddr = NULL; + } + +- dp->tx_spt_pages = NULL; + kfree(dp->spt_info); + } + +@@ -1374,37 +1373,12 @@ static int ath12k_dp_cc_desc_init(struct + struct ath12k_dp *dp = &ab->dp; + struct ath12k_rx_desc_info *rx_descs; + struct ath12k_tx_desc_info *tx_descs; ++ struct ath12k_spt_info *tx_spt_pages, *rx_spt_pages; + u32 i, j, pool_id, tx_spt_page; + u32 ppt_idx; + +- spin_lock_bh(&dp->rx_desc_lock); +- +- /* First ATH12K_NUM_RX_SPT_PAGES of allocated SPT pages are used for RX */ +- for (i = 0; i < ATH12K_NUM_RX_SPT_PAGES; i++) { +- rx_descs = kcalloc(ATH12K_MAX_SPT_ENTRIES, sizeof(*rx_descs), +- GFP_ATOMIC); +- +- if (!rx_descs) { +- spin_unlock_bh(&dp->rx_desc_lock); +- return -ENOMEM; +- } +- +- dp->spt_info->rxbaddr[i] = &rx_descs[0]; +- +- for (j = 0; j < ATH12K_MAX_SPT_ENTRIES; j++) { +- rx_descs[j].cookie = ath12k_dp_cc_cookie_gen(i, j); +- rx_descs[j].magic = ATH12K_DP_RX_DESC_MAGIC; +- list_add_tail(&rx_descs[j].list, &dp->rx_desc_free_list); +- +- /* Update descriptor VA in SPT */ +- *(struct ath12k_rx_desc_info **)((u8 *)dp->spt_info[i].vaddr + +- (j * sizeof(u64))) = &rx_descs[j]; +- } +- } +- +- spin_unlock_bh(&dp->rx_desc_lock); + /* pointer to start of TX pages */ +- dp->tx_spt_pages = &dp->spt_info[ATH12K_NUM_RX_SPT_PAGES]; ++ tx_spt_pages = &dp->spt_info[ATH12K_TX_SPT_PAGE_OFFSET]; + + for (pool_id = 0; pool_id < ATH12K_HW_MAX_QUEUES; pool_id++) { + spin_lock_bh(&dp->tx_desc_lock[pool_id]); +@@ -1422,7 +1396,7 @@ static int ath12k_dp_cc_desc_init(struct + dp->spt_info->txbaddr[tx_spt_page] = &tx_descs[0]; + + for (j = 0; j < ATH12K_MAX_SPT_ENTRIES; j++) { +- ppt_idx = ATH12K_NUM_RX_SPT_PAGES + tx_spt_page; ++ ppt_idx = ATH12K_TX_SPT_PAGE_OFFSET + tx_spt_page; + tx_descs[j].desc_id = ath12k_dp_cc_cookie_gen(ppt_idx, j); + tx_descs[j].pool_id = pool_id; + list_add_tail(&tx_descs[j].list, +@@ -1430,12 +1404,44 @@ static int ath12k_dp_cc_desc_init(struct + + /* Update descriptor VA in SPT */ + *(struct ath12k_tx_desc_info **) +- ((u8 *)dp->tx_spt_pages[tx_spt_page].vaddr + ++ ((u8 *)tx_spt_pages[tx_spt_page].vaddr + + (j * sizeof(u64))) = &tx_descs[j]; + } + } + spin_unlock_bh(&dp->tx_desc_lock[pool_id]); + } ++ ++ spin_lock_bh(&dp->rx_desc_lock); ++ ++ /* pointer to start of RX pages */ ++ rx_spt_pages = &dp->spt_info[ATH12K_RX_SPT_PAGE_OFFSET]; ++ ++ /* First ATH12K_NUM_RX_SPT_PAGES of allocated SPT pages are used for RX */ ++ for (i = 0; i < ATH12K_NUM_RX_SPT_PAGES; i++) { ++ rx_descs = kcalloc(ATH12K_MAX_SPT_ENTRIES, sizeof(*rx_descs), ++ GFP_ATOMIC); ++ ++ if (!rx_descs) { ++ spin_unlock_bh(&dp->rx_desc_lock); ++ return -ENOMEM; ++ } ++ ++ dp->spt_info->rxbaddr[i] = &rx_descs[0]; ++ ++ for (j = 0; j < ATH12K_MAX_SPT_ENTRIES; j++) { ++ ppt_idx = ATH12K_RX_SPT_PAGE_OFFSET + i; ++ rx_descs[j].cookie = ath12k_dp_cc_cookie_gen(ppt_idx, j); ++ rx_descs[j].magic = ATH12K_DP_RX_DESC_MAGIC; ++ list_add_tail(&rx_descs[j].list, &dp->rx_desc_free_list); ++ ++ /* Update descriptor VA in SPT */ ++ *(struct ath12k_rx_desc_info **)((u8 *)rx_spt_pages[i].vaddr + ++ (j * sizeof(u64))) = &rx_descs[j]; ++ } ++ } ++ ++ spin_unlock_bh(&dp->rx_desc_lock); ++ + return 0; + } + +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -215,7 +215,9 @@ struct ath12k_pdev_dp { + #define ATH12K_TX_SPT_PAGES_PER_POOL (ATH12K_NUM_POOL_TX_DESC / \ + ATH12K_MAX_SPT_ENTRIES) + #define ATH12K_NUM_TX_SPT_PAGES (ATH12K_TX_SPT_PAGES_PER_POOL * ATH12K_HW_MAX_QUEUES) +-#define ATH12K_NUM_SPT_PAGES (ATH12K_NUM_RX_SPT_PAGES + ATH12K_NUM_TX_SPT_PAGES) ++#define ATH12K_TX_SPT_PAGE_OFFSET 0 ++#define ATH12K_RX_SPT_PAGE_OFFSET ATH12K_NUM_TX_SPT_PAGES ++#define ATH12K_NUM_SPT_PAGES (ATH12K_NUM_TX_SPT_PAGES + ATH12K_NUM_RX_SPT_PAGES) + + /* The SPT pages are divided for RX and TX, first block for RX + * and remaining for TX +@@ -341,8 +343,6 @@ struct ath12k_dp { + struct ath12k_hp_update_timer tx_ring_timer[DP_TCL_NUM_RING_MAX]; + struct ath12k_spt_info *spt_info; + u32 num_spt_pages; +- /* start address of TX SPT pages */ +- struct ath12k_spt_info *tx_spt_pages; + struct list_head rx_desc_free_list; + struct list_head rx_desc_used_list; + /* protects the free and used desc list */ diff --git a/feeds/ipq95xx/mac80211/patches/qca/685-02-wifi-ath12k-Refactor-Tx-Rx-Descriptor-procedure.patch b/feeds/ipq95xx/mac80211/patches/qca/685-02-wifi-ath12k-Refactor-Tx-Rx-Descriptor-procedure.patch new file mode 100644 index 000000000..c91445520 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/685-02-wifi-ath12k-Refactor-Tx-Rx-Descriptor-procedure.patch @@ -0,0 +1,199 @@ +From fcd5cb82dd5bb7c397391164831cdee616e6c7a5 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Fri, 28 Oct 2022 11:16:25 +0530 +Subject: [PATCH] wifi: ath12k: Refactor Tx/Rx Descriptor procedure + +Rx Descriptor are placed in different location in the PPT based on the chip id. +so that the cookie is different for each SoC Rx descriptor which help in +processing partner chip Rxdma buffer to primary UMAC REO ring. + +Ex: + SoC0 SoC1 + + ---------- ---------- + | | | | + | Tx | | Tx | + ---------- ---------- + | Rx | | Rx | + | (SoC0) | | (SoC0) | + ---------- ---------- + | Rx | | Rx | + | (SoC1) | | (SoC1) | + ---------- ---------- + + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/dp.c | 50 +++++++++++++++++++++++++--- + drivers/net/wireless/ath/ath12k/dp.h | 1 + + 2 files changed, 47 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -1336,7 +1336,7 @@ static u32 ath12k_dp_cc_cookie_gen(u16 p + return (u32)ppt_idx << ATH12K_CC_PPT_SHIFT | spt_idx; + } + +-static u8 *ath12k_dp_cc_find_desc(struct ath12k_base *ab, u32 cookie) ++static u8 *ath12k_dp_cc_find_desc(struct ath12k_base *ab, u32 cookie, bool is_rx) + { + struct ath12k_dp *dp = &ab->dp; + u16 spt_page_id, spt_idx; +@@ -1345,6 +1345,13 @@ static u8 *ath12k_dp_cc_find_desc(struct + spt_idx = u32_get_bits(cookie, ATH12k_DP_CC_COOKIE_SPT); + spt_page_id = u32_get_bits(cookie, ATH12K_DP_CC_COOKIE_PPT); + ++ if (is_rx) { ++ if (WARN_ON(spt_page_id < dp->rx_spt_base)) ++ return NULL; ++ ++ spt_page_id = spt_page_id - dp->rx_spt_base; ++ } ++ + spt_va = (u8 *)dp->spt_info[spt_page_id].vaddr; + + return (spt_va + spt_idx * sizeof(u64)); +@@ -1355,7 +1362,7 @@ struct ath12k_rx_desc_info *ath12k_dp_ge + { + u8 *desc_addr_ptr; + +- desc_addr_ptr = ath12k_dp_cc_find_desc(ab, cookie); ++ desc_addr_ptr = ath12k_dp_cc_find_desc(ab, cookie, true); + return *(struct ath12k_rx_desc_info **)desc_addr_ptr; + } + +@@ -1364,10 +1371,40 @@ struct ath12k_tx_desc_info *ath12k_dp_ge + { + u8 *desc_addr_ptr; + +- desc_addr_ptr = ath12k_dp_cc_find_desc(ab, desc_id); ++ desc_addr_ptr = ath12k_dp_cc_find_desc(ab, desc_id, false); + return *(struct ath12k_tx_desc_info **)desc_addr_ptr; + } + ++static void ath12k_dp_tx_cmem_init(struct ath12k_base *ab, struct ath12k_dp *dp) ++{ ++ u32 cmem_base; ++ int i; ++ ++ cmem_base = ab->qmi.dev_mem[ATH12K_QMI_DEVMEM_CMEM_INDEX].start; ++ ++ for (i = 0; i < ATH12K_NUM_TX_SPT_PAGES; i++) { ++ /* Write to PPT in CMEM */ ++ ath12k_hif_write32(ab, cmem_base + ATH12K_PPT_ADDR_OFFSET(i), ++ dp->spt_info[i].paddr >> ATH12K_SPT_4K_ALIGN_OFFSET); ++ } ++} ++ ++static void ath12k_dp_rx_cmem_init(struct ath12k_base *ab, struct ath12k_dp *dp) ++{ ++ u32 cmem_base; ++ int i; ++ ++ cmem_base = ab->qmi.dev_mem[ATH12K_QMI_DEVMEM_CMEM_INDEX].start; ++ cmem_base += ATH12K_PPT_ADDR_OFFSET(dp->rx_spt_base); ++ ++ for (i = ATH12K_RX_SPT_PAGE_OFFSET; ++ i < (ATH12K_RX_SPT_PAGE_OFFSET + ATH12K_NUM_RX_SPT_PAGES); i++) { ++ /* Write to PPT in CMEM */ ++ ath12k_hif_write32(ab, cmem_base + ATH12K_PPT_ADDR_OFFSET(i), ++ dp->spt_info[i].paddr >> ATH12K_SPT_4K_ALIGN_OFFSET); ++ } ++} ++ + static int ath12k_dp_cc_desc_init(struct ath12k_base *ab) + { + struct ath12k_dp *dp = &ab->dp; +@@ -1427,9 +1464,9 @@ static int ath12k_dp_cc_desc_init(struct + } + + dp->spt_info->rxbaddr[i] = &rx_descs[0]; ++ ppt_idx = dp->rx_spt_base + ATH12K_RX_SPT_PAGE_OFFSET + i; + + for (j = 0; j < ATH12K_MAX_SPT_ENTRIES; j++) { +- ppt_idx = ATH12K_RX_SPT_PAGE_OFFSET + i; + rx_descs[j].cookie = ath12k_dp_cc_cookie_gen(ppt_idx, j); + rx_descs[j].magic = ATH12K_DP_RX_DESC_MAGIC; + list_add_tail(&rx_descs[j].list, &dp->rx_desc_free_list); +@@ -1473,6 +1510,7 @@ static int ath12k_dp_cc_init(struct ath1 + return -ENOMEM; + } + ++ dp->rx_spt_base = ab->chip_id * ATH12K_NUM_RX_SPT_PAGES; + cmem_base = ab->qmi.dev_mem[ATH12K_QMI_DEVMEM_CMEM_INDEX].start; + + for (i = 0; i < dp->num_spt_pages; i++) { +@@ -1491,12 +1529,12 @@ static int ath12k_dp_cc_init(struct ath1 + ret = -EINVAL; + goto free; + } +- +- /* Write to PPT in CMEM */ +- ath12k_hif_write32(ab, cmem_base + ATH12K_PPT_ADDR_OFFSET(i), +- dp->spt_info[i].paddr >> ATH12K_SPT_4K_ALIGN_OFFSET); + } + ++ ath12k_dp_tx_cmem_init(ab, dp); ++ ++ ath12k_dp_rx_cmem_init(ab, dp); ++ + ret = ath12k_dp_cc_desc_init(ab); + if (ret) { + ath12k_warn(ab, "HW CC desc init failed %d", ret); +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -343,6 +343,7 @@ struct ath12k_dp { + struct ath12k_hp_update_timer tx_ring_timer[DP_TCL_NUM_RING_MAX]; + struct ath12k_spt_info *spt_info; + u32 num_spt_pages; ++ u32 rx_spt_base; + struct list_head rx_desc_free_list; + struct list_head rx_desc_used_list; + /* protects the free and used desc list */ +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -3102,8 +3102,13 @@ try_again: + desc_info = (struct ath12k_rx_desc_info *)((unsigned long)desc_va); + + /* retry manual desc retrieval */ +- if (!desc_info) ++ if (!desc_info) { + desc_info = ath12k_dp_get_rx_desc(ab, cookie); ++ if (!desc_info) { ++ ath12k_warn(ab, "Rx with invalid buf cookie 0x%x\n", cookie); ++ continue; ++ } ++ } + + if (desc_info->magic != ATH12K_DP_RX_DESC_MAGIC) + ath12k_warn(ab, "Check HW CC implementation"); +@@ -3803,8 +3808,13 @@ ath12k_dp_process_rx_err_buf(struct ath1 + desc_info = (struct ath12k_rx_desc_info *)((unsigned long)desc_va); + + /* retry manual desc retrieval */ +- if (!desc_info) ++ if (!desc_info) { + desc_info = ath12k_dp_get_rx_desc(ab, cookie); ++ if (!desc_info) { ++ ath12k_warn(ab, "RX Exception, invalid buf cookie 0x%x\n", cookie); ++ return -EINVAL; ++ } ++ } + + if (desc_info->magic != ATH12K_DP_RX_DESC_MAGIC) + ath12k_warn(ab, " RX Exception, Check HW CC implementation"); +@@ -4298,8 +4308,13 @@ int ath12k_dp_rx_process_wbm_err(struct + desc_info = (struct ath12k_rx_desc_info *)err_info.rx_desc; + + /* retry manual desc retrieval if hw cc is not done */ +- if (!desc_info) ++ if (!desc_info) { + desc_info = ath12k_dp_get_rx_desc(ab, err_info.cookie); ++ if (!desc_info) { ++ ath12k_warn(ab, "WBM RX err, invalid buf cookie 0x%x\n", err_info.cookie); ++ continue; ++ } ++ } + + /* FIXME Extract mac id correctly. Since descs are not tied + * to mac, we can extract from vdev id in ring desc. diff --git a/feeds/ipq95xx/mac80211/patches/qca/685-03-wifi-ath12k-Refactor-SW-cookie-procedure.patch b/feeds/ipq95xx/mac80211/patches/qca/685-03-wifi-ath12k-Refactor-SW-cookie-procedure.patch new file mode 100644 index 000000000..f868ff8c3 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/685-03-wifi-ath12k-Refactor-SW-cookie-procedure.patch @@ -0,0 +1,134 @@ +From 3931964b94389f164accc1945da8ee03cd59e7c6 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Tue, 1 Nov 2022 15:12:30 +0530 +Subject: [PATCH] wifi: ath12k: Refactor SW cookie procedure + +Since Rxdma is DMAC type, so no need to handle mac_id specific handling in the +replinish API. So removed. Also in the SW cookie, no need to reserve the mac_id +bits. + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/dbring.c | 4 ++-- + drivers/net/wireless/ath/ath12k/dp.c | 2 +- + drivers/net/wireless/ath/ath12k/dp.h | 6 ++++-- + drivers/net/wireless/ath/ath12k/dp_rx.c | 15 ++++++--------- + drivers/net/wireless/ath/ath12k/dp_rx.h | 2 +- + 5 files changed, 14 insertions(+), 15 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/dbring.c ++++ b/drivers/net/wireless/ath/ath12k/dbring.c +@@ -51,8 +51,8 @@ static int ath12k_dbring_bufs_replenish( + + buff->paddr = paddr; + +- cookie = u32_encode_bits(ar->pdev_idx, DP_RXDMA_BUF_COOKIE_PDEV_ID) | +- u32_encode_bits(buf_id, DP_RXDMA_BUF_COOKIE_BUF_ID); ++ cookie = u32_encode_bits(ar->pdev_idx, DP_DIR_BUF_COOKIE_PDEV_ID) | ++ u32_encode_bits(buf_id, DP_DIR_BUF_COOKIE_BUF_ID); + + ath12k_hal_rx_buf_addr_info_set(desc, paddr, cookie, 0); + +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -1001,7 +1001,7 @@ int ath12k_dp_service_srng(struct ath12k + struct ath12k_dp *dp = &ab->dp; + struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring; + +- ath12k_dp_rx_bufs_replenish(ab, 0, rx_ring, 0, ++ ath12k_dp_rx_bufs_replenish(ab, rx_ring, 0, + ab->hw_params->hal_params->rx_buf_rbm, + true); + } +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -182,8 +182,10 @@ struct ath12k_pdev_dp { + #define DP_RX_BUFFER_SIZE_LITE 1024 + #define DP_RX_BUFFER_ALIGN_SIZE 128 + +-#define DP_RXDMA_BUF_COOKIE_BUF_ID GENMASK(17, 0) +-#define DP_RXDMA_BUF_COOKIE_PDEV_ID GENMASK(19, 18) ++#define DP_DIR_BUF_COOKIE_BUF_ID GENMASK(17, 0) ++#define DP_DIR_BUF_COOKIE_PDEV_ID GENMASK(19, 18) ++ ++#define DP_RXDMA_BUF_COOKIE_BUF_ID GENMASK(19, 0) + + #define DP_HW2SW_MACID(mac_id) ({ typeof(mac_id) x = (mac_id); x ? x - 1 : 0; }) + #define DP_SW2HW_MACID(mac_id) ((mac_id) + 1) +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -283,7 +283,7 @@ static int ath12k_dp_purge_mon_ring(stru + } + + /* Returns number of Rx buffers replenished */ +-int ath12k_dp_rx_bufs_replenish(struct ath12k_base *ab, int mac_id, ++int ath12k_dp_rx_bufs_replenish(struct ath12k_base *ab, + struct dp_rxdma_ring *rx_ring, + int req_entries, + enum hal_rx_buf_return_buf_manager mgr, +@@ -364,9 +364,7 @@ int ath12k_dp_rx_bufs_replenish(struct a + spin_unlock_bh(&rx_ring->idr_lock); + if (buf_id < 0) + goto fail_idr_remove; +- cookie = u32_encode_bits(mac_id, +- DP_RXDMA_BUF_COOKIE_PDEV_ID) | +- u32_encode_bits(buf_id, ++ cookie = u32_encode_bits(buf_id, + DP_RXDMA_BUF_COOKIE_BUF_ID); + } + +@@ -464,7 +462,7 @@ static int ath12k_dp_rxdma_ring_buf_setu + if ((ringtype == HAL_RXDMA_MONITOR_BUF) || (ringtype == HAL_TX_MONITOR_BUF)) + ath12k_dp_mon_buf_replenish(ab, rx_ring, num_entries); + else +- ath12k_dp_rx_bufs_replenish(ab, 0, rx_ring, num_entries, ++ ath12k_dp_rx_bufs_replenish(ab, rx_ring, num_entries, + ab->hw_params->hal_params->rx_buf_rbm, + ringtype == HAL_RXDMA_BUF); + return 0; +@@ -3069,7 +3067,6 @@ int ath12k_dp_rx_process(struct ath12k_b + bool done = false; + int mac_id; + u32 *rx_desc; +- int i; + u64 desc_va; + struct ath12k_sta *ahsta = NULL; + struct ath12k_link_sta *arsta = NULL; +@@ -3194,7 +3191,7 @@ try_again: + goto exit; + + /* TODO: Move to implicit BM? */ +- ath12k_dp_rx_bufs_replenish(ab, i, rx_ring, num_buffs_reaped, ++ ath12k_dp_rx_bufs_replenish(ab, rx_ring, num_buffs_reaped, + ab->hw_params->hal_params->rx_buf_rbm, true); + + ath12k_dp_rx_process_received_packets(ab, napi, &msdu_list, +@@ -3965,7 +3962,7 @@ exit: + + rx_ring = &dp->rx_refill_buf_ring; + +- ath12k_dp_rx_bufs_replenish(ab, 0, rx_ring, tot_n_bufs_reaped, ++ ath12k_dp_rx_bufs_replenish(ab, rx_ring, tot_n_bufs_reaped, + ab->hw_params->hal_params->rx_buf_rbm, true); + + return tot_n_bufs_reaped; +@@ -4365,7 +4362,7 @@ int ath12k_dp_rx_process_wbm_err(struct + if (!total_num_buffs_reaped) + goto done; + +- ath12k_dp_rx_bufs_replenish(ab, 0, rx_ring, num_buffs_reaped, ++ ath12k_dp_rx_bufs_replenish(ab, rx_ring, num_buffs_reaped, + ab->hw_params->hal_params->rx_buf_rbm, true); + + rcu_read_lock(); +--- a/drivers/net/wireless/ath/ath12k/dp_rx.h ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.h +@@ -116,7 +116,7 @@ int ath12k_dp_rx_process_err(struct ath1 + int ath12k_dp_rx_process(struct ath12k_base *ab, int mac_id, + struct napi_struct *napi, + int budget); +-int ath12k_dp_rx_bufs_replenish(struct ath12k_base *ab, int mac_id, ++int ath12k_dp_rx_bufs_replenish(struct ath12k_base *ab, + struct dp_rxdma_ring *rx_ring, + int req_entries, + enum hal_rx_buf_return_buf_manager mgr, diff --git a/feeds/ipq95xx/mac80211/patches/qca/672-ath12k-Fix-failed-to-remove-key-issue.patch b/feeds/ipq95xx/mac80211/patches/qca/685-ath12k-Fix-failed-to-remove-key-issue.patch similarity index 60% rename from feeds/ipq95xx/mac80211/patches/qca/672-ath12k-Fix-failed-to-remove-key-issue.patch rename to feeds/ipq95xx/mac80211/patches/qca/685-ath12k-Fix-failed-to-remove-key-issue.patch index c5e1c4ddd..e70c06c05 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/672-ath12k-Fix-failed-to-remove-key-issue.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/685-ath12k-Fix-failed-to-remove-key-issue.patch @@ -1,6 +1,6 @@ -From 44e945216cdc8cd5aba32a4374ab8a210619745e Mon Sep 17 00:00:00 2001 +From d4051cded8ddbbf1479b8f2b24fe5c1cf5d27b81 Mon Sep 17 00:00:00 2001 From: Sivashankari Madhavan -Date: Mon, 26 Sep 2022 14:22:27 +0530 +Date: Thu, 17 Nov 2022 13:03:33 +0530 Subject: [PATCH] ath12k: Fix failed to remove key issue While enabling the AP mode, driver caches the key information @@ -9,7 +9,8 @@ information are used to install the keys after vdev create. Once this key information are cached properly, then mac80211 sets KEY_FLAG_UPLOADED_TO_HARDWARE flag to the key->flags. Based on this flag, while bringing down AP, driver tries to -disable the uninstalled keys which leads to following failuremessages. +disable the uninstalled keys which leads to following failure +messages. wlan1: failed to remove key (4, ff:ff:ff:ff:ff:ff) from hardware (1) @@ -19,19 +20,17 @@ add support to cache the list of key information. Signed-off-by: Sivashankari Madhavan --- drivers/net/wireless/ath/ath12k/core.c | 14 +-- - drivers/net/wireless/ath/ath12k/core.h | 4 +- + drivers/net/wireless/ath/ath12k/core.h | 3 +- drivers/net/wireless/ath/ath12k/dp.c | 3 +- drivers/net/wireless/ath/ath12k/dp_tx.c | 3 +- - drivers/net/wireless/ath/ath12k/mac.c | 118 ++++++++++++++---------- + drivers/net/wireless/ath/ath12k/mac.c | 137 ++++++++++++++---------- drivers/net/wireless/ath/ath12k/wmi.c | 7 +- - 6 files changed, 89 insertions(+), 60 deletions(-) + 6 files changed, 97 insertions(+), 70 deletions(-) -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/core.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.c -@@ -1202,14 +1202,16 @@ int ath12k_core_qmi_firmware_ready(struc - return ret; +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -1215,14 +1215,16 @@ int ath12k_core_qmi_firmware_ready(struc + goto err_firmware_stop; } + ag = ab->ag; @@ -51,7 +50,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor break; default: ath12k_info(ab, "invalid crypto_mode: %d\n", ath12k_crypto_mode); -@@ -1217,9 +1219,7 @@ int ath12k_core_qmi_firmware_ready(struc +@@ -1230,9 +1232,7 @@ int ath12k_core_qmi_firmware_ready(struc } if (ath12k_frame_mode == ATH12K_HW_TXRX_RAW) @@ -62,11 +61,9 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor mutex_lock(&ag->mutex_lock); mutex_lock(&ab->core_lock); -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/core.h -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/core.h -@@ -287,8 +287,8 @@ struct ath12k_tx_conf { +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -303,8 +303,8 @@ struct ath12k_tx_conf { }; struct ath12k_key_conf { @@ -76,7 +73,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor struct ieee80211_sta *sta; struct ieee80211_key_conf *key; }; -@@ -938,6 +938,7 @@ struct vendor_info { +@@ -1001,6 +1001,7 @@ struct vendor_info { struct ath12k_hw { struct ieee80211_hw *hw; const struct ieee80211_ops *ops; @@ -84,39 +81,44 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/cor /* To synchronize concurrent synchronous mac80211 callback operations, * concurrent debugfs configuration and concurrent FW statistics events. -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/dp.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp.c -@@ -352,13 +352,14 @@ static - void ath12k_dp_tx_get_vdev_bank_config(struct ath12k_base *ab, struct ath12k_vif *arvif, +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -353,13 +353,14 @@ void ath12k_dp_tx_get_vdev_bank_config(s u32 *bank_config) { + struct ath12k_vif *ahvif = arvif->ahvif; + struct ath12k_hw_group *ag = ab->ag; enum hal_encrypt_type encrypt_type = 0; /* Only valid for raw frames with HW crypto enabled. * With SW crypto, mac80211 sets key per packet */ - if (arvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW && + if (ahvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW && - test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags) && + test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ag->dev_flags) && - arvif->key_cipher != INVALID_CIPHER) - encrypt_type = ath12k_dp_tx_get_encrypt_type(arvif->key_cipher); + ahvif->key_cipher != INVALID_CIPHER) + encrypt_type = ath12k_dp_tx_get_encrypt_type(ahvif->key_cipher); else -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_tx.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/dp_tx.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -113,6 +113,7 @@ int ath12k_dp_tx(struct ath12k *ar, stru - struct ath12k_sta *arsta, struct sk_buff *skb) +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -18,7 +18,7 @@ ath12k_dp_tx_get_encap_type(struct ath12 + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ath12k_base *ab = arvif->ar->ab; + +- if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags)) ++ if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->ag->dev_flags)) + return HAL_TCL_ENCAP_TYPE_RAW; + + if (tx_info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) +@@ -122,6 +122,7 @@ int ath12k_dp_tx(struct ath12k *ar, stru { + struct ath12k_vif *ahvif = arvif->ahvif; struct ath12k_base *ab = ar->ab; + struct ath12k_hw_group *ag = ab->ag; struct ath12k_dp *dp = &ab->dp; struct hal_tx_info ti = {0}; struct ath12k_tx_desc_info *tx_desc = NULL; -@@ -202,7 +203,7 @@ tcl_ring_sel: +@@ -212,7 +213,7 @@ tcl_ring_sel: ath12k_dp_tx_encap_nwifi(skb); break; case HAL_TCL_ENCAP_TYPE_RAW: @@ -125,19 +127,25 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_ ret = -EINVAL; goto fail_remove_tx_buf; } -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/mac.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac.c -@@ -4349,6 +4349,7 @@ static int ath12k_install_key(struct ath - { +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -4339,6 +4339,7 @@ ath12k_mac_assign_link_vif( struct ath12 + return NULL; + + INIT_LIST_HEAD(&arvif->list); ++ INIT_LIST_HEAD(&arvif->cache.key_conf.list); + INIT_WORK(&arvif->update_obss_color_notify_work, + ath12k_update_obss_color_notify_work); + INIT_WORK(&arvif->update_bcn_template_work, +@@ -4753,6 +4754,7 @@ static int ath12k_install_key(struct ath int ret; + struct ath12k_vif *ahvif = arvif->ahvif; struct ath12k *ar = arvif->ar; + struct ath12k_hw_group *ag = ar->ab->ag; struct wmi_vdev_install_key_arg arg = { .vdev_id = arvif->vdev_id, .key_idx = key->keyidx, -@@ -4362,7 +4363,7 @@ static int ath12k_install_key(struct ath +@@ -4766,7 +4768,7 @@ static int ath12k_install_key(struct ath reinit_completion(&ar->install_key_done); @@ -146,7 +154,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac return 0; if (cmd == DISABLE_KEY) { -@@ -4396,7 +4397,7 @@ static int ath12k_install_key(struct ath +@@ -4800,7 +4802,7 @@ static int ath12k_install_key(struct ath return -EOPNOTSUPP; } @@ -155,7 +163,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV | IEEE80211_KEY_FLAG_RESERVE_TAILROOM; -@@ -4476,27 +4477,6 @@ static int ath12k_mac_set_key(struct ath +@@ -4897,28 +4899,6 @@ static int ath12k_mac_set_key(struct ath ab = ar->ab; @@ -164,26 +172,36 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac - key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 || - key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 || - key->cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256) { +- rcu_read_unlock(); - ret = 1; - goto out; - } - - if (test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags)) { +- rcu_read_unlock(); - ret = 1; - goto out; - } - - if (key->keyidx > WMI_MAX_KEY_INDEX) { +- rcu_read_unlock(); - ret = -ENOSPC; - goto out; - } - + if (sta) + peer_addr = arsta->addr; + else if (ahvif->vdev_type == WMI_VDEV_TYPE_STA) +@@ -4928,8 +4908,6 @@ static int ath12k_mac_set_key(struct ath + + rcu_read_unlock(); + - mutex_lock(&ar->conf_mutex); - - if (sta) - peer_addr = sta->addr; - else if (arvif->vdev_type == WMI_VDEV_TYPE_STA) -@@ -4518,12 +4498,12 @@ static int ath12k_mac_set_key(struct ath + key->hw_key_idx = key->keyidx; + + /* the peer should not disappear in mid-way (unless FW goes awry) since +@@ -4944,12 +4922,12 @@ static int ath12k_mac_set_key(struct ath ath12k_warn(ab, "cannot install key for non-existent peer %pM\n", peer_addr); ret = -EOPNOTSUPP; @@ -198,7 +216,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac } } -@@ -4535,13 +4515,13 @@ static int ath12k_mac_set_key(struct ath +@@ -4961,13 +4939,13 @@ static int ath12k_mac_set_key(struct ath ret = ath12k_install_key(arvif, key, cmd, peer_addr, flags); if (ret) { ath12k_warn(ab, "ath12k_install_key failed (%d)\n", ret); @@ -206,7 +224,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac + goto out; } - ret = ath12k_dp_peer_rx_pn_replay_config(arvif, peer_addr, cmd, key); + ret = ath12k_dp_rx_peer_pn_replay_config(arvif, peer_addr, cmd, key); if (ret) { ath12k_warn(ab, "failed to offload PN replay detection %d\n", ret); - goto exit; @@ -214,7 +232,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac } spin_lock_bh(&ab->base_lock); -@@ -4587,8 +4567,6 @@ static int ath12k_mac_set_key(struct ath +@@ -5011,8 +4989,6 @@ static int ath12k_mac_set_key(struct ath spin_unlock_bh(&ab->base_lock); @@ -223,40 +241,41 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac out: return ret; } -@@ -4597,18 +4575,47 @@ static int ath12k_mac_op_set_key(struct - struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) - { -- struct ath12k *ar; +@@ -5024,6 +5000,8 @@ static int ath12k_mac_op_set_key(struct + struct ath12k *ar; struct ath12k_hw *ah = hw->priv; - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + struct ath12k_hw_group *ag = ah->ag; + struct ath12k_key_conf *key_conf = NULL; -+ struct ath12k *ar; - int ret; -- -+ + struct ath12k_link_vif *arvif; + struct ath12k_link_sta *arsta = NULL; + struct ath12k_sta *ahsta; +@@ -5031,14 +5009,41 @@ static int ath12k_mac_op_set_key(struct + mutex_lock(&ah->conf_mutex); + /* BIP needs to be done in software */ -+ if (key->cipher == WLAN_CIPHER_SUITE_AES_CMAC || -+ key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 || -+ key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 || -+ key->cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256) { -+ ret = 1; -+ goto out; -+ } ++ if (key->cipher == WLAN_CIPHER_SUITE_AES_CMAC || ++ key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 || ++ key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 || ++ key->cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256) { ++ ret = 1; ++ goto out; ++ } + + if (test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ag->dev_flags)) { -+ ret = 1; -+ goto out; -+ } ++ ret = 1; ++ goto out; ++ } + -+ if (key->keyidx > WMI_MAX_KEY_INDEX) { -+ ret = -ENOSPC; -+ goto out; -+ } ++ if (key->keyidx > WMI_MAX_KEY_INDEX) { ++ ret = -ENOSPC; ++ goto out; ++ } + + /* TODO modify for all link vif configuration */ + arvif = &ahvif->deflink; + if (!arvif->is_created) { - arvif->cache.key_conf.cmd = cmd; - arvif->cache.key_conf.sta = sta; @@ -277,41 +296,38 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac ath12k_info(NULL, "set key param cached since vif not assign to radio\n"); mutex_unlock(&ah->conf_mutex); -@@ -4618,10 +4625,15 @@ static int ath12k_mac_op_set_key(struct - - return 0; +@@ -5055,8 +5060,13 @@ static int ath12k_mac_op_set_key(struct + ahsta = (struct ath12k_sta *)sta->drv_priv; + arsta = &ahsta->deflink; } -- -+ - ar = arvif->ar; -+ ++ + mutex_lock(&ar->conf_mutex); + - ret = ath12k_mac_set_key(ar, cmd, vif, sta, key); + ret = ath12k_mac_set_key(ar, cmd, arvif, arsta, key); + mutex_unlock(&ar->conf_mutex); +out: mutex_unlock(&ah->conf_mutex); return ret; } -@@ -7376,6 +7388,7 @@ static void ath12k_mac_update_vif_offloa - struct ieee80211_vif *vif) +@@ -8449,6 +8459,7 @@ static void ath12k_mac_update_vif_offloa + struct ath12k_link_vif *arvif) { struct ath12k_base *ab = ar->ab; + struct ath12k_hw_group *ag = ab->ag; - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = arvif->ahvif; + struct ieee80211_vif *vif = ahvif->vif; u32 param_id, param_value; - int ret; -@@ -7389,7 +7402,7 @@ static void ath12k_mac_update_vif_offloa +@@ -8463,7 +8474,7 @@ static void ath12k_mac_update_vif_offloa if (vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED) - arvif->tx_encap_type = ATH12K_HW_TXRX_ETHERNET; + ahvif->tx_encap_type = ATH12K_HW_TXRX_ETHERNET; - else if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags)) + else if (test_bit(ATH12K_FLAG_RAW_MODE, &ag->dev_flags)) - arvif->tx_encap_type = ATH12K_HW_TXRX_RAW; + ahvif->tx_encap_type = ATH12K_HW_TXRX_RAW; else - arvif->tx_encap_type = ATH12K_HW_TXRX_NATIVE_WIFI; -@@ -7405,7 +7418,7 @@ static void ath12k_mac_update_vif_offloa + ahvif->tx_encap_type = ATH12K_HW_TXRX_NATIVE_WIFI; +@@ -8479,7 +8490,7 @@ static void ath12k_mac_update_vif_offloa param_id = WMI_VDEV_PARAM_RX_DECAP_TYPE; if (vif->offload_flags & IEEE80211_OFFLOAD_DECAP_ENABLED) param_value = ATH12K_HW_TXRX_ETHERNET; @@ -320,15 +336,17 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac param_value = ATH12K_HW_TXRX_RAW; else param_value = ATH12K_HW_TXRX_NATIVE_WIFI; -@@ -7707,6 +7720,7 @@ static void ath12k_mac_vif_cache_flush(s - { +@@ -8815,6 +8826,9 @@ static void ath12k_mac_vif_cache_flush(s struct ath12k_hw *ah = ar->ah; - struct ath12k_vif *arvif = (void *)vif->drv_priv; + struct ath12k_vif *ahvif = (void *)vif->drv_priv; + struct ath12k_link_vif *arvif; + struct ath12k_key_conf *key_conf, *tmp; ++ struct ath12k_link_sta *arsta = NULL; ++ struct ath12k_sta *ahsta; int ret; lockdep_assert_held(&ah->conf_mutex); -@@ -7717,23 +7731,30 @@ static void ath12k_mac_vif_cache_flush(s +@@ -8828,23 +8842,35 @@ static void ath12k_mac_vif_cache_flush(s if (ret) ath12k_warn(ar->ab, "unable to apply tx config parameters to vdev %d\n", ret); @@ -337,70 +355,73 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac } if (arvif->cache.bss_conf_changed) { - ath12k_mac_bss_info_changed(ar, vif, &vif->bss_conf, + ath12k_mac_bss_info_changed(ar, arvif, &vif->bss_conf, arvif->cache.bss_conf_changed); -+ -+ arvif->cache.bss_conf_changed = 0; - } +- } - if (arvif->cache.key_conf.changed) { - ret = ath12k_mac_set_key(ar, arvif->cache.key_conf.cmd, -- vif, arvif->cache.key_conf.sta, +- arvif, NULL, - arvif->cache.key_conf.key); - if (ret) - ath12k_warn(ar->ab, "unable to apply set key param to vdev %d ret %d\n", - arvif->vdev_id, ret); ++ arvif->cache.bss_conf_changed = 0; + } + +- memset(&arvif->cache, 0, sizeof(struct ath12k_vif_cache)); + if (!list_empty(&arvif->cache.key_conf.list)) { + list_for_each_entry_safe(key_conf, tmp, &arvif->cache.key_conf.list, list) { ++ if (key_conf->sta) { ++ ahsta = (struct ath12k_sta *)key_conf->sta->drv_priv; ++ arsta = ahsta->link[link_id]; ++ } ++ + ret = ath12k_mac_set_key(ar, key_conf->cmd, -+ vif, key_conf->sta, ++ arvif, arsta, + key_conf->key); + if (ret) + ath12k_warn(ar->ab, "unable to apply set key param to vdev %d ret %d\n", + arvif->vdev_id, ret); -+ ++ + list_del(&key_conf->list); + kfree(key_conf); + } - } -- -- memset(&arvif->cache, 0, sizeof(struct ath12k_vif_cache)); ++ } } static struct ath12k *ath12k_mac_assign_vif_to_vdev(struct ieee80211_hw *hw, -@@ -7819,6 +7840,8 @@ static int ath12k_mac_op_add_interface(s - INIT_LIST_HEAD(&arvif->list); - arvif->key_cipher = INVALID_CIPHER; - -+ INIT_LIST_HEAD(&arvif->cache.key_conf.list); -+ - INIT_WORK(&arvif->update_obss_color_notify_work, ath12k_update_obss_color_notify_work); - INIT_WORK(&arvif->update_bcn_template_work, ath12k_update_bcn_template_work); - -@@ -7876,6 +7899,7 @@ static void ath12k_mac_op_remove_interfa - struct ath12k_hw *ah = hw->priv; +@@ -8931,6 +8957,7 @@ static int ath12k_mac_op_add_interface(s + ahvif->deflink.ahvif = ahvif; + ahvif->deflink.link_id = 0; + INIT_LIST_HEAD(&ahvif->deflink.list); ++ INIT_LIST_HEAD(&ahvif->deflink.cache.key_conf.list); + INIT_WORK(&ahvif->deflink.update_obss_color_notify_work, + ath12k_update_obss_color_notify_work); + INIT_WORK(&ahvif->deflink.update_bcn_template_work, +@@ -8980,6 +9007,7 @@ static void ath12k_mac_remove_link_inter struct ath12k *ar; - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); + struct ath12k_vif *ahvif = arvif->ahvif; + struct ieee80211_vif *vif = ahvif->vif; + struct ath12k_key_conf *key_conf; struct ath12k_base *ab; int ret; -@@ -7946,7 +7970,13 @@ err_vdev_del: - clear_bit(MONITOR_CONF_ENABLED, &ar->monitor_flags); +@@ -9048,6 +9076,13 @@ err_vdev_del: ath12k_debugfs_remove_interface(arvif); -- -+ + + if (!list_empty(&arvif->cache.key_conf.list)) { + list_for_each_entry(key_conf, &arvif->cache.key_conf.list, list) { + list_del(&key_conf->list); + kfree(key_conf); + } + } ++ /* TODO: recal traffic pause state based on the available vdevs */ - mutex_unlock(&ar->conf_mutex); -@@ -11189,6 +11219,7 @@ static int ath12k_mac_hw_register(struct + ahvif->link[arvif->link_id] = NULL; +@@ -12925,6 +12960,7 @@ static int ath12k_mac_hw_register(struct struct ath12k_pdev_cap *cap; struct ath12k_base *ab, *ab_dflt; struct ath12k *ar; @@ -408,7 +429,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac struct ath12k_pdev *pdev; int i, j, ret; u32 antennas_rx, antennas_tx; -@@ -11212,6 +11243,7 @@ static int ath12k_mac_hw_register(struct +@@ -12948,6 +12984,7 @@ static int ath12k_mac_hw_register(struct ar = ah->radio; ab = ar->ab; @@ -416,7 +437,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac /* Use the first chip in group to advertise some features/info * these are expected to be similar for chips in group -@@ -11338,7 +11370,7 @@ static int ath12k_mac_hw_register(struct +@@ -13088,7 +13125,7 @@ static int ath12k_mac_hw_register(struct ah->hw->wiphy->regulatory_flags = REGULATORY_WIPHY_SELF_MANAGED; ah->hw->wiphy->reg_notifier = ath12k_reg_notifier; @@ -425,7 +446,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac hw->netdev_features = NETIF_F_HW_CSUM; ieee80211_hw_set(hw, SW_CRYPTO_CONTROL); ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); -@@ -11557,6 +11589,7 @@ int ath12k_mac_allocate(struct ath12k_hw +@@ -13311,6 +13348,7 @@ int ath12k_mac_allocate(struct ath12k_hw ah->ops = ops; ah->num_radio = num_radios; ag->ah[i] = ah; @@ -433,20 +454,18 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/mac ath12k_info(NULL, "ath12k hw device created with %d radios in group %d with %d chips\n", -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/wmi.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi.c -@@ -150,6 +150,8 @@ static const struct wmi_tlv_policy wmi_t - static void ath12k_init_wmi_config_qcn92xx(struct ath12k_base *ab, - struct target_resource_config *config) +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -157,6 +157,8 @@ static __le32 ath12k_wmi_tlv_cmd_hdr(u32 + void ath12k_wmi_init_qcn9274(struct ath12k_base *ab, + struct target_resource_config *config) { + struct ath12k_hw_group *ag = ab->ag; + config->num_vdevs = ab->num_radios * TARGET_NUM_VDEVS; if (ab->num_radios == 2) { -@@ -174,7 +176,7 @@ static void ath12k_init_wmi_config_qcn92 +@@ -181,7 +183,7 @@ void ath12k_wmi_init_qcn9274(struct ath1 config->rx_timeout_pri[2] = TARGET_RX_TIMEOUT_LO_PRI; config->rx_timeout_pri[3] = TARGET_RX_TIMEOUT_HI_PRI; @@ -455,7 +474,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi config->rx_decap_mode = TARGET_DECAP_MODE_RAW; else config->rx_decap_mode = TARGET_DECAP_MODE_NATIVE_WIFI; -@@ -1863,6 +1865,7 @@ int ath12k_wmi_send_peer_assoc_cmd(struc +@@ -2027,6 +2029,7 @@ int ath12k_wmi_send_peer_assoc_cmd(struc struct peer_assoc_params *param) { struct ath12k_pdev_wmi *wmi = ar->wmi; @@ -463,7 +482,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/wmi struct wmi_peer_assoc_complete_cmd *cmd; struct wmi_vht_rate_set *mcs; struct wmi_he_rate_set *he_mcs; -@@ -1906,7 +1909,7 @@ int ath12k_wmi_send_peer_assoc_cmd(struc +@@ -2072,7 +2075,7 @@ int ath12k_wmi_send_peer_assoc_cmd(struc ath12k_wmi_copy_peer_flags(cmd, param, test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, diff --git a/feeds/ipq95xx/mac80211/patches/qca/685-ath12k-WAR-for-memory-leak-caused-by-thermal-registe.patch b/feeds/ipq95xx/mac80211/patches/qca/685-ath12k-WAR-for-memory-leak-caused-by-thermal-registe.patch deleted file mode 100644 index 38ee083d0..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/685-ath12k-WAR-for-memory-leak-caused-by-thermal-registe.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 80cb6d37008c0919f6414c190d7c672873747556 Mon Sep 17 00:00:00 2001 -From: P Praneesh -Date: Thu, 17 Nov 2022 10:54:08 +0530 -Subject: [PATCH] ath12k: WAR for memory leak caused by thermal register - -wiphy_free deallocates rdev via put_device which internally uses -kref_count of kobj. This kref_count gets incremented during device_add and -decremented during device_del. During rmmod, wiphy_free expectes this -kref_count to be zero for deallocating rdev. - -Ath12k driver uses devm_hwmon_device_register_with_groups for thermal -register by passing hw->wiphy->dev which is the child of pci->dev. So the -kref_count incremented for the hw->wiphy->dev is not getting decremented -properly during device_del which causes stale value present in the -kref_count. Because of the positive value in kref_count, put_device failed -to call kfree of rdev which causes memory leaks. - -Add a workaround to handle this memory leak, by passing pci's dev pointer -instead of wiphy->dev which got created during ieee80211_alloc_hw_nm. - -Need to check devm_hwmon_device_register_with_groups internals to fix it -properly. - -Signed-off-by: P Praneesh ---- - drivers/net/wireless/ath/ath12k/thermal.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/net/wireless/ath/ath12k/thermal.c b/drivers/net/wireless/ath/ath12k/thermal.c -index e29a488..b1d7575 100644 ---- a/drivers/net/wireless/ath/ath12k/thermal.c -+++ b/drivers/net/wireless/ath/ath12k/thermal.c -@@ -199,7 +199,7 @@ int ath12k_thermal_register(struct ath12k_base *ab) - if (!IS_REACHABLE(CONFIG_HWMON)) - return 0; - -- hwmon_dev = devm_hwmon_device_register_with_groups(&hw->wiphy->dev, -+ hwmon_dev = devm_hwmon_device_register_with_groups(ab->dev, - "ath12k_hwmon", ar, - ath12k_hwmon_groups); - if (IS_ERR(hwmon_dev)) { --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/685-ath12k-fix-memory-leak-caused-by-thermal-debug-regis.patch b/feeds/ipq95xx/mac80211/patches/qca/685-ath12k-fix-memory-leak-caused-by-thermal-debug-regis.patch new file mode 100644 index 000000000..efffc6b15 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/685-ath12k-fix-memory-leak-caused-by-thermal-debug-regis.patch @@ -0,0 +1,84 @@ +From 3415d4354010eeccb1add438346b6f4a6558b967 Mon Sep 17 00:00:00 2001 +From: P Praneesh +Date: Mon, 29 May 2023 11:41:07 +0530 +Subject: [PATCH] ath12k: fix memory leak caused by thermal debug register + +wiphy_free deallocates rdev via put_device which internally uses +kref_count of kobj. This kref_count gets incremented during device_add and +decremented during device_del. During rmmod, wiphy_free expectes this +kref_count to be zero for deallocating rdev. + +Ath12k driver uses devm_hwmon_device_register_with_groups for thermal +register by passing hw->wiphy->dev which is the child of pci->dev. So the +kref_count incremented for the hw->wiphy->dev is not getting decremented +properly during device_del which causes stale value present in the +kref_count. Because of the positive value in kref_count, put_device failed +to call kfree of rdev which causes memory leaks. + +Fix it by using hwmon_device_register_with_groups instead of devm_hwmon_device_register_with_groups +and free it using hwmon_device_unregiste during unregister. + +Signed-off-by: P Praneesh +--- + drivers/net/wireless/ath/ath12k/thermal.c | 17 +++++++++++------ + drivers/net/wireless/ath/ath12k/thermal.h | 1 + + 2 files changed, 12 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/thermal.c b/drivers/net/wireless/ath/ath12k/thermal.c +index e29a488..2cf191a 100644 +--- a/drivers/net/wireless/ath/ath12k/thermal.c ++++ b/drivers/net/wireless/ath/ath12k/thermal.c +@@ -158,7 +158,6 @@ int ath12k_thermal_set_throttling(struct ath12k *ar, u32 throttle_state) + int ath12k_thermal_register(struct ath12k_base *ab) + { + struct thermal_cooling_device *cdev; +- struct device *hwmon_dev; + struct ath12k *ar; + struct ath12k_pdev *pdev; + struct ieee80211_hw *hw; +@@ -199,12 +198,13 @@ int ath12k_thermal_register(struct ath12k_base *ab) + if (!IS_REACHABLE(CONFIG_HWMON)) + return 0; + +- hwmon_dev = devm_hwmon_device_register_with_groups(&hw->wiphy->dev, +- "ath12k_hwmon", ar, +- ath12k_hwmon_groups); +- if (IS_ERR(hwmon_dev)) { ++ ar->thermal.hwmon_dev = hwmon_device_register_with_groups(&hw->wiphy->dev, ++ "ath12k_hwmon", ar, ++ ath12k_hwmon_groups); ++ if (IS_ERR(ar->thermal.hwmon_dev)) { + ath12k_err(ar->ab, "failed to register hwmon device: %ld\n", +- PTR_ERR(hwmon_dev)); ++ PTR_ERR(ar->thermal.hwmon_dev)); ++ ar->thermal.hwmon_dev = NULL; + ret = -EINVAL; + goto err_thermal_destroy; + } +@@ -237,6 +237,11 @@ void ath12k_thermal_unregister(struct ath12k_base *ab) + snprintf(pdev_name, sizeof(pdev_name), "%s%d", "cooling_device", + ar->link_idx); + ++ if (ar->thermal.hwmon_dev) { ++ hwmon_device_unregister(ar->thermal.hwmon_dev); ++ ar->thermal.hwmon_dev = NULL; ++ } ++ + sysfs_remove_link(&hw->wiphy->dev.kobj, pdev_name); + thermal_cooling_device_unregister(ar->thermal.cdev); + } +diff --git a/drivers/net/wireless/ath/ath12k/thermal.h b/drivers/net/wireless/ath/ath12k/thermal.h +index 8ae3f84..c940b12 100644 +--- a/drivers/net/wireless/ath/ath12k/thermal.h ++++ b/drivers/net/wireless/ath/ath12k/thermal.h +@@ -17,6 +17,7 @@ + struct ath12k_thermal { + struct thermal_cooling_device *cdev; + struct completion wmi_sync; ++ struct device *hwmon_dev; + + /* protected by conf_mutex */ + u32 throttle_state; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/685-ath12k-fix-null-pointer-access-when-vdev-creation-fa.patch b/feeds/ipq95xx/mac80211/patches/qca/685-ath12k-fix-null-pointer-access-when-vdev-creation-fa.patch deleted file mode 100644 index ce1dfc1bb..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/685-ath12k-fix-null-pointer-access-when-vdev-creation-fa.patch +++ /dev/null @@ -1,97 +0,0 @@ -From b123da8d55223cac57011aaba7adecac81fc29db Mon Sep 17 00:00:00 2001 -From: P Praneesh -Date: Sat, 19 Nov 2022 16:49:33 +0530 -Subject: [PATCH] ath12k: fix null pointer access when vdev creation fails - -vdev create fails when driver gets request for MAC address which is -already presents. If this failure observed for tx VAP in the MBSSID, -while sending beacon for non transmitted VAP, tx VAP arvif is -getting accessed which is not initialised properly during vdev creation. - -Fix it by allowing beacon template updation process only when the -mbssid tx arvif is created otherwise return failure. - -[ 412.918052] ath12k_pci 0003:01:00.0: failed to vdev 3 create peer for AP: -22 -[ 412.918055] ath12k_pci 0003:01:00.0: WMI vdev delete id 3 num_peers : 4 -[ 412.918058] ath12k_pci 0003:01:00.0: failed to create vdev 0 ret -22 -... -... -[ 414.256946] Unable to handle kernel access to user memory outside uaccess routines at virtual address 0000000000000008 -[ 414.257188] Call trace: -[ 414.257193] ath12k_mac_tx_mgmt_pending_free+0x5d88/0x8370 [ath12k] -[ 414.257198] ath12k_mac_ap_ps_recalc+0x210/0x310c [ath12k] -[ 414.257202] ath12k_mac_ap_ps_recalc+0x1124/0x310c [ath12k] -[ 414.257211] ieee80211_bss_info_change_notify+0xa4/0xe4 [mac80211] -[ 414.257217] ieee80211_nan_func_match+0x37ec/0x3aa0 [mac80211] -[ 414.257222] nl80211_parse_chandef+0x28f8/0x2a5c [cfg80211] -[ 414.257226] genl_family_rcv_msg+0x314/0x3b0 -[ 414.257227] genl_rcv_msg+0x58/0x84 -[ 414.257229] netlink_rcv_skb+0x94/0x10c -[ 414.257231] genl_rcv+0x34/0x48 -[ 414.257232] netlink_unicast+0x138/0x1f8 -[ 414.257233] netlink_sendmsg+0x28c/0x328 - -Signed-off-by: P Praneesh ---- - drivers/net/wireless/ath/ath12k/mac.c | 16 +++++++++++++--- - drivers/net/wireless/ath/ath12k/peer.c | 2 ++ - 2 files changed, 15 insertions(+), 3 deletions(-) - ---- a/drivers/net/wireless/ath/ath12k/mac.c -+++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -1385,6 +1385,11 @@ static int ath12k_mac_setup_bcn_tmpl_ema - return -1; - - tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv; -+ if (!tx_arvif->is_created) { -+ ath12k_warn(arvif->ar->ab, "mbssid tx VIF is not yet created\n"); -+ return -EPERM; -+ } -+ - beacons = ieee80211_beacon_get_template_ema_list(tx_arvif->ar->ah->hw, - tx_arvif->vif); - if (!beacons || !beacons->cnt) { -@@ -1430,8 +1435,14 @@ static int ath12k_mac_setup_bcn_tmpl_non - struct sk_buff *bcn; - int ret; - -- if (arvif->vif->mbssid_tx_vif) -+ if (arvif->vif->mbssid_tx_vif) { - tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv; -+ if (!tx_arvif->is_created) { -+ ath12k_warn(arvif->ar->ab, -+ "For non ema bcn setup, mbssid_tx_vif is not yet created\n"); -+ tx_arvif = arvif; -+ } -+ } - - bcn = ieee80211_beacon_get_template(tx_arvif->ar->ah->hw, tx_arvif->vif, - &offs); -@@ -7628,7 +7639,6 @@ static struct ath12k *ath12k_mac_assign_ - struct ath12k *ar; - struct ath12k_base *ab; - struct ath12k_vif *arvif = (void *)vif->drv_priv; -- u8 bit; - int ret; - - lockdep_assert_held(&ah->conf_mutex); -@@ -7664,7 +7674,7 @@ static struct ath12k *ath12k_mac_assign_ - - ret = ath12k_mac_vdev_create(ar, vif); - if (ret) { -- ath12k_warn(ab, "failed to create vdev %d ret %d", bit, ret); -+ ath12k_warn(ab, "failed to create vdev %d ret %d", arvif->vdev_id, ret); - goto unlock; - } - ---- a/drivers/net/wireless/ath/ath12k/peer.c -+++ b/drivers/net/wireless/ath/ath12k/peer.c -@@ -283,6 +283,8 @@ int ath12k_peer_create(struct ath12k *ar - spin_lock_bh(&ar->ab->base_lock); - peer = ath12k_peer_find_by_pdev_idx(ar->ab, ar->pdev_idx, param->peer_addr); - if (peer) { -+ ath12k_warn(ar->ab, -+ "peer %pM already present in ab\n", param->peer_addr); - spin_unlock_bh(&ar->ab->base_lock); - return -EINVAL; - } diff --git a/feeds/ipq95xx/mac80211/patches/qca/685-mac80211-Revert-mac80211-reject-clear-user-rate-mask.patch b/feeds/ipq95xx/mac80211/patches/qca/685-mac80211-Revert-mac80211-reject-clear-user-rate-mask.patch new file mode 100644 index 000000000..585ec780e --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/685-mac80211-Revert-mac80211-reject-clear-user-rate-mask.patch @@ -0,0 +1,112 @@ +From f7082761b35cde6e22d591d2ea7809e9fe706a91 Mon Sep 17 00:00:00 2001 +From: Maharaja Kennadyrajan +Date: Tue, 20 Dec 2022 13:19:46 +0530 +Subject: [PATCH] mac80211: Revert "mac80211: validate user rate mask before + configuring driver" + +Ben reported that when the user rate mask is rejected for not +matching any basic rate, the driver had already been configured. +This is clearly an oversight in my original change, fix this by +doing the validation before calling the driver. + +Change-Id: Ia474f80ebdc1f392068a62f2613b4aed40796b22 +Signed-off-by: Maharaja Kennadyrajan +--- + net/mac80211/cfg.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -2763,7 +2763,6 @@ static int ieee80211_change_bss(struct w + params->basic_rates_len, + &link->conf->basic_rates); + changed |= BSS_CHANGED_BASIC_RATES; +- ieee80211_check_rate_mask(link); + } + + if (params->ap_isolate >= 0) { +@@ -3388,21 +3387,6 @@ static int ieee80211_set_bitrate_mask(st + if (!ieee80211_sdata_running(sdata)) + return -ENETDOWN; + +- /* +- * If active validate the setting and reject it if it doesn't leave +- * at least one basic rate usable, since we really have to be able +- * to send something, and if we're an AP we have to be able to do +- * so at a basic rate so that all clients can receive it. +- */ +- if (rcu_access_pointer(sdata->vif.bss_conf.chanctx_conf) && +- sdata->vif.bss_conf.chandef.chan) { +- u32 basic_rates = sdata->vif.bss_conf.basic_rates; +- enum nl80211_band band = sdata->vif.bss_conf.chandef.chan->band; +- +- if (!(mask->control[band].legacy & basic_rates)) +- return -EINVAL; +- } +- + if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL)) { + ret = drv_set_bitrate_mask(local, sdata, mask); + if (ret) +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -2673,8 +2673,6 @@ static u32 ieee80211_link_set_associated + bss->has_erp_value, + bss->erp_value); + +- ieee80211_check_rate_mask(link); +- + link->u.mgd.bss = cbss; + memcpy(link->u.mgd.bssid, cbss->bssid, ETH_ALEN); + +--- a/net/mac80211/rate.c ++++ b/net/mac80211/rate.c +@@ -270,38 +270,6 @@ static void rate_control_free(struct iee + kfree(ctrl_ref); + } + +-void ieee80211_check_rate_mask(struct ieee80211_link_data *link) +-{ +- struct ieee80211_sub_if_data *sdata = link->sdata; +- struct ieee80211_local *local = sdata->local; +- struct ieee80211_supported_band *sband; +- u32 user_mask, basic_rates = link->conf->basic_rates; +- enum nl80211_band band; +- +- if (WARN_ON(!link->conf->chandef.chan)) +- return; +- +- band = link->conf->chandef.chan->band; +- if (band == NL80211_BAND_S1GHZ) { +- /* TODO */ +- return; +- } +- +- if (WARN_ON_ONCE(!basic_rates)) +- return; +- +- user_mask = sdata->rc_rateidx_mask[band]; +- sband = local->hw.wiphy->bands[band]; +- +- if (user_mask & basic_rates) +- return; +- +- sdata_dbg(sdata, +- "no overlap between basic rates (0x%x) and user mask (0x%x on band %d) - clearing the latter", +- basic_rates, user_mask, band); +- sdata->rc_rateidx_mask[band] = (1 << sband->n_bitrates) - 1; +-} +- + static bool rc_no_data_or_no_ack_use_min(struct ieee80211_tx_rate_control *txrc) + { + struct sk_buff *skb = txrc->skb; +--- a/net/mac80211/rate.h ++++ b/net/mac80211/rate.h +@@ -85,8 +85,6 @@ static inline void rate_control_add_debu + #endif + } + +-void ieee80211_check_rate_mask(struct ieee80211_link_data *link); +- + /* Get a reference to the rate control algorithm. If `name' is NULL, get the + * first available algorithm. */ + int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, diff --git a/feeds/ipq95xx/mac80211/patches/qca/685-mac80211-fix-mesh-EHT-operation-info-IE-element.patch b/feeds/ipq95xx/mac80211/patches/qca/685-mac80211-fix-mesh-EHT-operation-info-IE-element.patch new file mode 100644 index 000000000..0c31c6c9f --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/685-mac80211-fix-mesh-EHT-operation-info-IE-element.patch @@ -0,0 +1,152 @@ +From 01f966aefe9e41c2267be22362832babd0c605f3 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Tue, 15 Nov 2022 09:11:40 +0530 +Subject: [PATCH] mac80211: fix mesh EHT operation info IE element + +Currently, EHT Operation Info IE length was incorrectly calculated due to which +mesh beacon was not getting parsed properly on receiver's end. Also, when ru +puncturing was enabled, there was a further mis-calculation of length. + +Alongwith incorrect length, the IE values were also not populated correctly due +to incorrect offset of EHT Operation IE structure members. + +Add fix to properly calculate length and then accordingly populate the IE. + +Fixes: 86a6ba117e ("mac80211: Package Upgrade 08/18/2022") + +Signed-off-by: Aditya Kumar Singh +--- + include/linux/ieee80211.h | 3 +++ + net/mac80211/mesh.c | 17 +++++++++++++---- + net/mac80211/util.c | 27 ++++++++++++--------------- + 3 files changed, 28 insertions(+), 19 deletions(-) + +--- a/include/linux/ieee80211.h ++++ b/include/linux/ieee80211.h +@@ -2071,6 +2071,9 @@ struct ieee80211_eht_cap_elem { + #define IEEE80211_EHT_OPER_GROUP_ADDRESSED_BU_IND_LIMIT 0x08 + #define IEEE80211_EHT_OPER_GROUP_ADDRESSED_BU_IND_EXP_MASK 0x30 + ++#define IEEE80211_EHT_OPERATION_FIXED_LEN 0x5 ++#define IEEE80211_EHT_OPERATION_INFO_FIXED_LEN 0x3 ++#define DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE 0x2 + /** + * struct ieee80211_eht_operation - eht operation element + * +--- a/net/mac80211/mesh.c ++++ b/net/mac80211/mesh.c +@@ -698,8 +698,11 @@ int mesh_add_eht_oper_ie(struct ieee8021 + sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_10) + return 0; + +- len = 2 + 1 + sizeof(struct ieee80211_eht_operation) + +- sizeof(struct ieee80211_eht_operation_info); ++ len = 2 + 1 + IEEE80211_EHT_OPERATION_FIXED_LEN + ++ IEEE80211_EHT_OPERATION_INFO_FIXED_LEN; ++ ++ if (sdata->vif.bss_conf.chandef.ru_punct_bitmap) ++ len += DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE; + + if (skb_tailroom(skb) < len) + return -ENOMEM; +@@ -905,6 +908,7 @@ ieee80211_mesh_build_beacon(struct ieee8 + u8 *pos; + struct ieee80211_sub_if_data *sdata; + int hdr_len = offsetofend(struct ieee80211_mgmt, u.beacon); ++ int eht_optional_sz = 0; + + sdata = container_of(ifmsh, struct ieee80211_sub_if_data, u.mesh); + rcu_read_lock(); +@@ -916,6 +920,10 @@ ieee80211_mesh_build_beacon(struct ieee8 + NL80211_IFTYPE_MESH_POINT); + ie_len_eht_cap = ieee80211_ie_len_eht_cap(sdata, + NL80211_IFTYPE_MESH_POINT); ++ ++ if (sdata->vif.bss_conf.chandef.ru_punct_bitmap) ++ eht_optional_sz = DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE; ++ + head_len = hdr_len + + 2 + /* NULL SSID */ + /* Channel Switch Announcement */ +@@ -940,8 +948,9 @@ ieee80211_mesh_build_beacon(struct ieee8 + sizeof(struct ieee80211_he_6ghz_oper) + + 2 + 1 + sizeof(struct ieee80211_he_6ghz_capa) + + ie_len_eht_cap + +- 2 + 1 + sizeof(struct ieee80211_eht_operation) + +- + sizeof(struct ieee80211_eht_operation_info) + ++ 2 + 1 + IEEE80211_EHT_OPERATION_FIXED_LEN + ++ IEEE80211_EHT_OPERATION_INFO_FIXED_LEN + ++ eht_optional_sz + + ifmsh->ie_len; + + bcn = kzalloc(sizeof(*bcn) + head_len + tail_len, GFP_KERNEL); +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -3376,23 +3376,28 @@ u8 *ieee80211_ie_build_eht_oper(u8 *pos, + { + struct ieee80211_eht_operation *eht_oper; + struct ieee80211_eht_operation_info *eht_oper_info; +- u8 ie_len = 1 + sizeof(struct ieee80211_eht_operation) + +- sizeof(struct ieee80211_eht_operation_info); ++ u8 ie_len = 1 + IEEE80211_EHT_OPERATION_FIXED_LEN + ++ IEEE80211_EHT_OPERATION_INFO_FIXED_LEN; + u8 chwidth = 0; + + if (chandef->ru_punct_bitmap) +- ie_len += 2; ++ ie_len += DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE; + + *pos++ = WLAN_EID_EXTENSION; + *pos++ = ie_len; + *pos++ = WLAN_EID_EXT_EHT_OPERATION; + + eht_oper = (struct ieee80211_eht_operation *)pos; +- pos += sizeof(struct ieee80211_eht_operation); ++ ++ eht_oper->params |= IEEE80211_EHT_OPER_INFO_PRESENT; ++ ++ memcpy(&eht_oper->basic_mcs_nss, ++ &eht_cap->eht_mcs_nss_supp.only_20mhz, ++ sizeof(struct ieee80211_eht_mcs_nss_supp_20mhz_only)); ++ ++ pos += IEEE80211_EHT_OPERATION_FIXED_LEN; + + eht_oper_info = (struct ieee80211_eht_operation_info *)pos; +- pos += sizeof(struct ieee80211_eht_operation_info) + +- chandef->ru_punct_bitmap ? 2 : 0; + + eht_oper_info->ccfs0 = + ieee80211_frequency_to_channel(chandef->center_freq1); +@@ -3433,27 +3438,19 @@ u8 *ieee80211_ie_build_eht_oper(u8 *pos, + break; + } + +- memcpy(&eht_oper->basic_mcs_nss, +- &eht_cap->eht_mcs_nss_supp.only_20mhz, +- sizeof(struct ieee80211_eht_mcs_nss_supp_20mhz_only)); +- +- eht_oper->params |= IEEE80211_EHT_OPER_INFO_PRESENT; +- + eht_oper_info->control = chwidth; + +- eht_oper->optional[0] = eht_oper_info->control; +- eht_oper->optional[1] = eht_oper_info->ccfs0; +- eht_oper->optional[2] = eht_oper_info->ccfs1; ++ pos += IEEE80211_EHT_OPERATION_INFO_FIXED_LEN; + + if (chandef->ru_punct_bitmap) { ++ pos += DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE; + eht_oper->params |= + IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT; + +- eht_oper_info->optional[0] = chandef->ru_punct_bitmap && 0x00FF; ++ eht_oper_info->optional[0] = chandef->ru_punct_bitmap & 0x00FF; + eht_oper_info->optional[1] = chandef->ru_punct_bitmap >> 8; +- +- eht_oper->optional[3] = eht_oper_info->optional[0]; +- eht_oper->optional[4] = eht_oper_info->optional[1]; ++ } else { ++ eht_oper->params &= ~IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT; + } + + return pos; diff --git a/feeds/ipq95xx/mac80211/patches/qca/687-ath12k-remove-mac-Tx-management-debug-prints.patch b/feeds/ipq95xx/mac80211/patches/qca/687-ath12k-remove-mac-Tx-management-debug-prints.patch deleted file mode 100644 index 185d48f8a..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/687-ath12k-remove-mac-Tx-management-debug-prints.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 37c92c53b272a60dce1d7aa7f187944e8dcaaed4 Mon Sep 17 00:00:00 2001 -From: Aditya Kumar Singh -Date: Thu, 17 Nov 2022 22:09:07 +0530 -Subject: [PATCH] ath12k: remove mac Tx management debug prints - -A few debug prints were printed for every management Tx hapenning -in the driver. This leads to flooding of debug prints on console -when the debug logs are enabled. - -Remove debug prints for Tx management packets. - -Signed-off-by: Aditya Kumar Singh ---- - drivers/net/wireless/ath/ath12k/mac.c | 7 +------ - drivers/net/wireless/ath/ath12k/wmi.c | 4 ---- - 2 files changed, 1 insertion(+), 10 deletions(-) - ---- a/drivers/net/wireless/ath/ath12k/mac.c -+++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -7517,8 +7517,7 @@ static int ath12k_mac_mgmt_tx_wmi(struct - buf_id = idr_alloc(&ar->txmgmt_idr, skb, 0, - ATH12K_TX_MGMT_NUM_PENDING_MAX, GFP_ATOMIC); - spin_unlock_bh(&ar->txmgmt_idr_lock); -- ath12k_dbg(ar->ab, ATH12K_DBG_MAC, -- "mac tx mgmt frame, buf id %d\n", buf_id); -+ - if (buf_id < 0) - return -ENOSPC; - -@@ -7597,7 +7596,7 @@ static void ath12k_mgmt_over_wmi_tx_work - arvif->vdev_id, ret); - ath12k_mgmt_over_wmi_tx_drop(ar, skb); - } else { -- ath12k_dbg(ar->ab, ATH12K_DBG_MAC, -+ ath12k_dbg(ar->ab, ATH12K_DBG_MGMT, - "mac tx mgmt frame, vdev_id %d\n", - arvif->vdev_id); - } ---- a/drivers/net/wireless/ath/ath12k/wmi.c -+++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -5913,10 +5913,6 @@ skip_mgmt_stats: - if (num_mgmt < 0) - WARN_ON_ONCE(1); - -- ath12k_dbg(ar->ab, ATH12K_DBG_WMI, -- "wmi mgmt tx comp pending %d desc id %d\n", -- num_mgmt, desc_id); -- - if (!num_mgmt) - wake_up(&ar->txmgmt_empty_waitq); - diff --git a/feeds/ipq95xx/mac80211/patches/qca/688-01-wifi-ath12k-Added-MLO-capable-field-in-hw-group-stru.patch b/feeds/ipq95xx/mac80211/patches/qca/688-01-wifi-ath12k-Added-MLO-capable-field-in-hw-group-stru.patch new file mode 100644 index 000000000..17ae720ea --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/688-01-wifi-ath12k-Added-MLO-capable-field-in-hw-group-stru.patch @@ -0,0 +1,193 @@ +From 01c7dffa2e0c11659e099312fd58c7da60022b0d Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Mon, 21 Nov 2022 14:59:57 +0530 +Subject: [PATCH] wifi: ath12k: Added MLO capable field in hw group structure + +MLO capability field is required to enable MLO setup. This capable +is disabled implicitly when the total links in the hw group is +not more than one. + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/core.c | 5 +++-- + drivers/net/wireless/ath/ath12k/core.h | 2 +- + drivers/net/wireless/ath/ath12k/mac.c | 7 +++---- + drivers/net/wireless/ath/ath12k/qmi.c | 19 ++++++++++++++++--- + 4 files changed, 23 insertions(+), 10 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -129,6 +129,7 @@ ath12k_core_hw_group_alloc(u8 id, u8 max + + ag->id = id; + ag->num_chip = max_chip; ++ ag->mlo_capable = !!ath12k_mlo_capable; + list_add(&ag->list, &ath12k_hw_groups); + mutex_init(&ag->mutex_lock); + +@@ -151,12 +152,12 @@ static struct ath12k_hw_group *ath12k_co + * within the soc, all links are combined into a single wiphy. + */ + mlo = of_parse_phandle(dev->of_node, "qcom,wsi", 0); +- if (!mlo) { +- group_id = ATH12K_INVALID_GRP_ID; +- } else { ++ if (mlo && ath12k_mlo_capable) { + ret = of_property_read_u32(mlo, "id", &group_id); + if (ret) + group_id = ATH12K_INVALID_GRP_ID; ++ } else { ++ group_id = ATH12K_INVALID_GRP_ID; + } + + again: +@@ -987,7 +988,7 @@ static int ath12k_core_mlo_teardown(stru + int ret; + int i; + +- if (ag->id == ATH12K_INVALID_GRP_ID) ++ if (!ag->mlo_capable) + return 0; + + for (i = ag->num_hw - 1; i >= 0; i--) { +@@ -1010,7 +1011,7 @@ static int ath12k_core_mlo_setup(struct + int ret; + int i; + +- if (ag->id == ATH12K_INVALID_GRP_ID) ++ if (!ag->mlo_capable) + return 0; + + for (i = 0; i < ag->num_hw; i++) { +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -40,7 +40,6 @@ + #define ATH12K_RX_RATE_TABLE_11AX_NUM 576 + + extern unsigned int ath12k_frame_mode; +-extern unsigned int ath12k_mlo_capable; + + #define ATH12K_MON_TIMER_INTERVAL 10 + #define ATH12K_RESET_TIMEOUT_HZ (20 * HZ) +@@ -1031,6 +1030,7 @@ struct ath12k_hw_group { + u8 num_probed; + u8 num_started; + u8 num_hw; ++ bool mlo_capable; + unsigned long dev_flags; + struct ath12k_hw *ah[ATH12K_GROUP_MAX_RADIO]; + struct ath12k_base *ab[ATH12K_MAX_SOCS]; +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -13066,11 +13066,10 @@ int ath12k_mac_allocate(struct ath12k_hw + for (i = 0; i < ag->num_chip; i++) + total_radio += ag->ab[i]->num_radios; + +- /* All pdev get combined and register as single wiphy in the non-invalid +- * group where also multi-link is enabled. where as in other group, +- * each pdev get register separately. ++ /* All pdev get combined and register as single wiphy if MLO capable ++ * is enabled. where as in other group, each pdev get register separately. + */ +- if (ag->id != ATH12K_INVALID_GRP_ID && ath12k_mlo_capable) ++ if (ag->mlo_capable) + num_radios = total_radio; + else + num_radios = 1; +--- a/drivers/net/wireless/ath/ath12k/qmi.c ++++ b/drivers/net/wireless/ath/ath12k/qmi.c +@@ -2835,14 +2835,25 @@ static int ath12k_qmi_fill_mlo_host_caps + + mutex_lock(&ag->mutex_lock); + +- if (ag->id == ATH12K_INVALID_GRP_ID || !ab->qmi.num_radios) { +- ath12k_dbg(ab, ATH12K_DBG_QMI, "Skip MLO cap send for chip id %d\n", ++ if (!ag->mlo_capable) { ++ ath12k_dbg(ab, ATH12K_DBG_QMI, "Skip MLO cap send for chip id %d since it's not MLO capable\n", + ab->chip_id); + mutex_unlock(&ag->mutex_lock); + return 0; + } + ++ if (ag->id == ATH12K_INVALID_GRP_ID || !ab->qmi.num_radios) { ++ ag->mlo_capable = false; ++ ++ ath12k_dbg(ab, ATH12K_DBG_QMI, "Skip MLO cap send for chip id %d due to group_id %d qmi num_radio %d\n", ++ ab->chip_id, ag->id, ab->qmi.num_radios); ++ mutex_unlock(&ag->mutex_lock); ++ return 0; ++ } ++ + if (ab->chip_id == ATH12K_INVALID_CHIP_ID) { ++ ath12k_err(ab, "failed to send MLO cap send due to Invalid chip id\n"); ++ + ret = -EINVAL; + goto out; + } +@@ -2874,8 +2885,7 @@ static int ath12k_qmi_fill_mlo_host_caps + + info->chip_id = partner_ab->chip_id; + +- /* TODO: Need to get the phy count */ +- info->num_local_links = partner_ab->hw_params->num_local_link; ++ info->num_local_links = partner_ab->qmi.num_radios; + + ath12k_dbg(ab, ATH12K_DBG_QMI, "MLO chip id %d num_link %d\n", + partner_ab->chip_id, info->num_local_links); +@@ -2891,6 +2901,10 @@ static int ath12k_qmi_fill_mlo_host_caps + } + } + ++ /* Disable MLO capable if there is no Multi-link in a group */ ++ if (link_id <= 1) ++ ag->mlo_capable = false; ++ + req->mlo_chip_info_valid = true; + + ath12k_dbg(ab, ATH12K_DBG_QMI, "MLO host cap chosen\n"); +@@ -2920,6 +2934,7 @@ chip_cleanup: + req->mlo_capable = 0; + req->mlo_capable_valid = 0; + ++ ag->mlo_capable = false; + out: + mutex_unlock(&ag->mutex_lock); + +@@ -3029,11 +3044,15 @@ static int ath12k_qmi_phy_cap_send(struc + if (ret < 0) + goto out; + +- if (resp.resp.result != QMI_RESULT_SUCCESS_V01) ++ if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { ++ ret = -EOPNOTSUPP; + goto out; ++ } + +- if (!resp.num_phy_valid) ++ if (!resp.num_phy_valid) { ++ ret = -ENODATA; + goto out; ++ } + + ab->qmi.num_radios = resp.num_phy; + +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -1627,6 +1627,7 @@ int ath12k_dp_alloc(struct ath12k_base * + u32 n_link_desc = 0; + int ret; + int i; ++ u8 chip_id; + + dp->ab = ab; + +@@ -1635,7 +1636,8 @@ int ath12k_dp_alloc(struct ath12k_base * + spin_lock_init(&dp->reo_cmd_lock); + + dp->reo_cmd_cache_flush_count = 0; +- dp->idle_link_rbm_id = HAL_RX_BUF_RBM_WBM_CHIP0_IDLE_DESC_LIST + ab->chip_id; ++ chip_id = (ab->ag->mlo_capable) ? ab->chip_id : 0; ++ dp->idle_link_rbm_id = HAL_RX_BUF_RBM_WBM_CHIP0_IDLE_DESC_LIST + chip_id; + + ret = ath12k_wbm_idle_ring_setup(ab, &n_link_desc); + if (ret) { diff --git a/feeds/ipq95xx/mac80211/patches/qca/688-02-wifi-ath12k-Add-partner-Rxdma-buffer-processing-in-D.patch b/feeds/ipq95xx/mac80211/patches/qca/688-02-wifi-ath12k-Add-partner-Rxdma-buffer-processing-in-D.patch new file mode 100644 index 000000000..10f4cefb5 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/688-02-wifi-ath12k-Add-partner-Rxdma-buffer-processing-in-D.patch @@ -0,0 +1,208 @@ +From 4324b3cc7f27371428c233af74a052cd027f661f Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Fri, 4 Nov 2022 17:12:09 +0530 +Subject: [PATCH] wifi: ath12k: Add partner Rxdma buffer processing in DP Rx + path + +In MLO enabled setup, we can expect partner SoC Rxdma buffers enqueued +to primary UMAC REO ring. So we need to get the partner radio information through +source link information and use for sw cookie conversion if hw conversion fails. + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/dp_rx.c | 72 ++++++++++++++++--------- + drivers/net/wireless/ath/ath12k/mac.c | 18 +++++++ + 3 files changed, 66 insertions(+), 25 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -1033,6 +1033,7 @@ struct ath12k_hw_group { + unsigned long dev_flags; + struct ath12k_hw *ah[ATH12K_GROUP_MAX_RADIO]; + struct ath12k_base *ab[ATH12K_MAX_SOCS]; ++ struct ath12k __rcu *hw_links[ATH12K_GROUP_MAX_RADIO]; + struct ath12k_mlo_memory mlo_mem; + struct mutex mutex_lock; + }; +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -3081,10 +3081,11 @@ static void ath12k_dp_rx_process_receive + int ath12k_dp_rx_process(struct ath12k_base *ab, int ring_id, + struct napi_struct *napi, int budget) + { ++ struct ath12k_base *src_ab; + struct ath12k_rx_desc_info *desc_info; + struct ath12k_dp *dp = &ab->dp; + struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring; +- int num_buffs_reaped = 0; ++ int i, num_buffs_reaped[ATH12K_MAX_SOCS] = { }; + struct sk_buff_head msdu_list; + struct ath12k_skb_rxcb *rxcb; + int total_msdu_reaped = 0; +@@ -3098,6 +3099,7 @@ int ath12k_dp_rx_process(struct ath12k_b + struct ath12k_link_sta *arsta = NULL; + struct ath12k_peer *peer = NULL; + struct ath12k *ar; ++ u8 hw_link_id; + + __skb_queue_head_init(&msdu_list); + +@@ -3116,17 +3118,39 @@ try_again: + cookie = u32_get_bits(desc.buf_addr_info.info1, + BUFFER_ADDR_INFO1_SW_COOKIE); + +- mac_id = u32_get_bits(desc.info0, +- HAL_REO_DEST_RING_INFO0_SRC_LINK_ID); +- +- ar = ab->pdevs[mac_id].ar; ++ hw_link_id = u32_get_bits(desc.info0, ++ HAL_REO_DEST_RING_INFO0_SRC_LINK_ID); + + desc_va = ((u64)desc.buf_va_hi << 32 | desc.buf_va_lo); + desc_info = (struct ath12k_rx_desc_info *)((unsigned long)desc_va); + ++ rcu_read_lock(); ++ ++ if (hw_link_id < ATH12K_GROUP_MAX_RADIO) ++ ar = rcu_dereference(ab->ag->hw_links[hw_link_id]); ++ else ++ ar = NULL; ++ ++ if (!ar) { ++ rcu_read_unlock(); ++ ++ ab->soc_stats.hal_reo_error[dp->reo_dst_ring[ring_id].ring_id]++; ++ ath12k_warn(ab, "Rx with invalid/inactive hw_link_id %d cookie 0x%x\n", hw_link_id, cookie); ++ ++ if (desc_info) { ++ dev_kfree_skb_any(desc_info->skb); ++ desc_info->skb = NULL; ++ } ++ continue; ++ } ++ ++ mac_id = ar->pdev_idx; ++ src_ab = ar->ab; ++ rcu_read_unlock(); ++ + /* retry manual desc retrieval */ + if (!desc_info) { +- desc_info = ath12k_dp_get_rx_desc(ab, cookie); ++ desc_info = ath12k_dp_get_rx_desc(src_ab, cookie); + if (!desc_info) { + ath12k_warn(ab, "Rx with invalid buf cookie 0x%x\n", cookie); + continue; +@@ -3139,16 +3163,16 @@ try_again: + msdu = desc_info->skb; + desc_info->skb = NULL; + +- spin_lock_bh(&dp->rx_desc_lock); +- list_move_tail(&desc_info->list, &dp->rx_desc_free_list); +- spin_unlock_bh(&dp->rx_desc_lock); ++ spin_lock_bh(&src_ab->dp.rx_desc_lock); ++ list_move_tail(&desc_info->list, &src_ab->dp.rx_desc_free_list); ++ spin_unlock_bh(&src_ab->dp.rx_desc_lock); + + rxcb = ATH12K_SKB_RXCB(msdu); +- dma_unmap_single(ab->dev, rxcb->paddr, ++ dma_unmap_single(src_ab->dev, rxcb->paddr, + msdu->len + skb_tailroom(msdu), + DMA_FROM_DEVICE); + +- num_buffs_reaped++; ++ num_buffs_reaped[src_ab->chip_id]++; + + push_reason = u32_get_bits(desc.info0, + HAL_REO_DEST_RING_INFO0_PUSH_REASON); +@@ -3173,13 +3197,13 @@ try_again: + + if (ath12k_debugfs_is_extd_rx_stats_enabled(ar) && rxcb->peer_id) { + rcu_read_lock(); +- spin_lock_bh(&ab->base_lock); +- peer = ath12k_peer_find_by_id(ab, rxcb->peer_id); ++ spin_lock_bh(&src_ab->base_lock); ++ peer = ath12k_peer_find_by_id(src_ab, rxcb->peer_id); + if (peer && peer->sta) { + ahsta = (struct ath12k_sta *)peer->sta->drv_priv; + arsta = &ahsta->deflink; + } +- spin_unlock_bh(&ab->base_lock); ++ spin_unlock_bh(&src_ab->base_lock); + if (arsta) + atomic_inc(&arsta->drv_rx_pkts.pkts_frm_hw); + rcu_read_unlock(); +@@ -3216,9 +3240,20 @@ try_again: + if (!total_msdu_reaped) + goto exit; + +- /* TODO: Move to implicit BM? */ +- ath12k_dp_rx_bufs_replenish(ab, rx_ring, num_buffs_reaped, +- ab->hw_params->hal_params->rx_buf_rbm, true); ++ for (i = 0; i < ab->ag->num_chip; i++) { ++ if (!num_buffs_reaped[i]) ++ continue; ++ ++ src_ab = ab->ag->ab[i]; ++ if (!src_ab) ++ continue; ++ ++ rx_ring = &src_ab->dp.rx_refill_buf_ring; ++ ++ /* TODO: Move to implicit BM? */ ++ ath12k_dp_rx_bufs_replenish(src_ab, rx_ring, num_buffs_reaped[i], ++ src_ab->hw_params->hal_params->rx_buf_rbm, true); ++ } + + ath12k_dp_rx_process_received_packets(ab, napi, &msdu_list, + ring_id); +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -12969,8 +12969,17 @@ static int ath12k_mac_setup(struct ath12 + { + struct ath12k *ar; + struct ath12k_pdev *pdev; ++ struct ath12k_hw_group *ag = ab->ag; ++ u16 hw_link_id; + + pdev = &ab->pdevs[mac_id]; ++ hw_link_id = pdev->hw_link_id; ++ ++ if (hw_link_id >= ATH12K_GROUP_MAX_RADIO) { ++ ath12k_err(ab, "HW link id %d is not supported\n", hw_link_id); ++ return -ENOENT; ++ } ++ + ar = ath12k_mac_get_ar(ah, link_id); + if (!ar) + return -EINVAL; +@@ -13017,6 +13026,7 @@ static int ath12k_mac_setup(struct ath12 + clear_bit(MONITOR_VDEV_STARTED, &ar->monitor_flags); + ar->monitor_vdev_id = -1; + clear_bit(MONITOR_VDEV_CREATED, &ar->monitor_flags); ++ rcu_assign_pointer(ag->hw_links[hw_link_id], ar); + + return 0; + } +@@ -13131,6 +13141,7 @@ void ath12k_mac_destroy(struct ath12k_hw + struct ath12k_pdev *pdev; + struct ieee80211_ops *ops; + int i, j; ++ u16 hw_link_id; + + if (!ah) + return; +@@ -13142,6 +13153,13 @@ void ath12k_mac_destroy(struct ath12k_hw + + for (j = 0; j < ab->num_radios; j++) { + pdev = &ab->pdevs[j]; ++ hw_link_id = pdev->hw_link_id; ++ ++ if (hw_link_id < ATH12K_GROUP_MAX_RADIO) { ++ rcu_assign_pointer(ag->hw_links[hw_link_id], NULL); ++ synchronize_rcu(); ++ } ++ + ar = pdev->ar; + if (!ar) + continue; diff --git a/feeds/ipq95xx/mac80211/patches/qca/688-03-wifi-ath12k-Do-partner-rx-descriptor-init-in-each-So.patch b/feeds/ipq95xx/mac80211/patches/qca/688-03-wifi-ath12k-Do-partner-rx-descriptor-init-in-each-So.patch new file mode 100644 index 000000000..ae0a52b76 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/688-03-wifi-ath12k-Do-partner-rx-descriptor-init-in-each-So.patch @@ -0,0 +1,64 @@ +From 3750aa9bf92888df7f2524adebf5831955dbfcbb Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Wed, 16 Nov 2022 20:40:50 +0530 +Subject: [PATCH] wifi: ath12k: Do partner rx descriptor init in each SoC + +In MLO setup, REO UMAC recieves the partner SoC Rxdma buffer. In that case, +to make the HW conversion work. Each SoC need to configure the partner SoC +Rxdma rx descriptor in the cmem configuration. + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/core.c | 3 +++ + drivers/net/wireless/ath/ath12k/dp.c | 17 +++++++++++++++++ + drivers/net/wireless/ath/ath12k/dp.h | 1 + + 3 files changed, 21 insertions(+) + +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -1024,6 +1024,9 @@ static int ath12k_core_mlo_setup(struct + goto err_setup; + } + ++ for (i = 0; i < ag->num_chip; i++) ++ ath12k_dp_partner_cc_init(ag->ab[i]); ++ + for (i = 0; i < ag->num_hw; i++) { + ah = ag->ah[i]; + if (!ah) +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -1499,6 +1499,23 @@ static int ath12k_dp_cc_desc_init(struct + return 0; + } + ++void ath12k_dp_partner_cc_init(struct ath12k_base *ab) ++{ ++ struct ath12k_hw_group *ag = ab->ag; ++ struct ath12k_base *partner_ab; ++ struct ath12k_dp *dp; ++ int i; ++ ++ for (i = 0; i < ag->num_chip; i++) { ++ partner_ab = ag->ab[i]; ++ if (partner_ab == ab) ++ continue; ++ ++ dp = &partner_ab->dp; ++ ath12k_dp_rx_cmem_init(ab, dp); ++ } ++} ++ + static int ath12k_dp_cc_init(struct ath12k_base *ab) + { + struct ath12k_dp *dp = &ab->dp; +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -2109,6 +2109,7 @@ void ath12k_dp_vdev_tx_attach(struct ath + void ath12k_dp_free(struct ath12k_base *ab); + int ath12k_dp_alloc(struct ath12k_base *ab); + void ath12k_dp_cc_config(struct ath12k_base *ab); ++void ath12k_dp_partner_cc_init(struct ath12k_base *ab); + int ath12k_dp_pdev_alloc(struct ath12k_base *ab); + void ath12k_dp_pdev_pre_alloc(struct ath12k_base *ab); + void ath12k_dp_pdev_free(struct ath12k_base *ab); diff --git a/feeds/ipq95xx/mac80211/patches/qca/688-ath12k-key-operations-for-Multi-link-Station-and-Acc.patch b/feeds/ipq95xx/mac80211/patches/qca/688-ath12k-key-operations-for-Multi-link-Station-and-Acc.patch new file mode 100644 index 000000000..70bd90e5c --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/688-ath12k-key-operations-for-Multi-link-Station-and-Acc.patch @@ -0,0 +1,148 @@ +From 8b93ff3de4fb66d8045c6bdcb893eeff33c5ca22 Mon Sep 17 00:00:00 2001 +From: Rameshkumar Sundaram +Date: Fri, 18 Nov 2022 10:22:22 +0530 +Subject: [PATCH] ath12k: key operations for Multi-link Station and Access + point + +Mac80211 will provide valid link_id (in key_conf) only for +group keys in an MLD, for pairwise keys add changes to set/delete key +for all link STA if set key arrives for one (ML) STA. +For non ML STA in Non ML Vap do set/delete key in default link STA. + +Also do set/delete key on default link if link_id is invalid(-1) for +a group key in which case it is non ML VAP. + +Eapol frames are sent as 802.11 packets to mac80211, hence +set rx_status's link_valid and link_id for packets from ML STA's +before delivering it to Mac80211 RX path. + +Signed-off-by: Rameshkumar Sundaram +--- + drivers/net/wireless/ath/ath12k/dp_rx.c | 7 +++- + drivers/net/wireless/ath/ath12k/mac.c | 50 ++++++++++++++++++------- + 2 files changed, 42 insertions(+), 15 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -2915,8 +2915,13 @@ static void ath12k_dp_rx_deliver_msdu(st + + spin_lock_bh(&ab->base_lock); + peer = ath12k_dp_rx_h_find_peer(ab, msdu); +- if (peer && peer->sta) ++ if (peer && peer->sta) { + pubsta = peer->sta; ++ if (pubsta->valid_links) { ++ status->link_valid = 1; ++ status->link_id = peer->link_id; ++ } ++ } + spin_unlock_bh(&ab->base_lock); + + ath12k_dbg(ab, ATH12K_DBG_DATA, +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -4933,7 +4933,8 @@ static int ath12k_mac_set_key(struct ath + + ret = ath12k_install_key(arvif, key, cmd, peer_addr, flags); + if (ret) { +- ath12k_warn(ab, "ath12k_install_key failed (%d)\n", ret); ++ ath12k_warn(ab, "ath12k_install_key cmd %d failed (%d) for peer %pM on vdev %d (link id %d)\n", ++ cmd, ret, peer_addr, arvif->vdev_id, link_id); + goto out; + } + +@@ -4992,7 +4993,6 @@ static int ath12k_mac_op_set_key(struct + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) + { +- struct ath12k *ar; + struct ath12k_hw *ah = hw->priv; + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + struct ath12k_hw_group *ag = ah->ag; +@@ -5000,7 +5000,8 @@ static int ath12k_mac_op_set_key(struct + struct ath12k_link_vif *arvif; + struct ath12k_link_sta *arsta = NULL; + struct ath12k_sta *ahsta; +- int ret; ++ int ret = -ENOLINK; ++ u8 link_id; + + mutex_lock(&ah->conf_mutex); + +@@ -5023,8 +5024,13 @@ static int ath12k_mac_op_set_key(struct + goto out; + } + +- /* TODO modify for all link vif configuration */ +- arvif = &ahvif->deflink; ++ if (key->link_id >= 0 && key->link_id < IEEE80211_MLD_MAX_NUM_LINKS) { ++ arvif = ahvif->link[key->link_id]; ++ if (WARN_ON(!arvif)) ++ goto out; ++ } else { ++ arvif = &ahvif->deflink; ++ } + + if (!arvif->is_created) { + key_conf = kzalloc(sizeof(*key_conf), GFP_ATOMIC); +@@ -5049,18 +5055,34 @@ static int ath12k_mac_op_set_key(struct + return 0; + } + +- ar = arvif->ar; +- + if (sta) { + ahsta = (struct ath12k_sta *)sta->drv_priv; +- arsta = &ahsta->deflink; ++ if (sta->mlo) { ++ for_each_set_bit(link_id, &sta->valid_links, IEEE80211_MLD_MAX_NUM_LINKS) { ++ arvif = ahvif->link[link_id]; ++ arsta = ahsta->link[link_id]; ++ if (WARN_ON(!arvif || !arsta)) ++ continue; ++ mutex_lock(&arvif->ar->conf_mutex); ++ ret = ath12k_mac_set_key(arvif->ar, cmd, arvif, arsta, key); ++ mutex_unlock(&arvif->ar->conf_mutex); ++ if (ret) ++ break; ++ } ++ } else { ++ arsta = &ahsta->deflink; ++ arvif = arsta->arvif; ++ if (WARN_ON(!arvif)) ++ goto out; ++ mutex_lock(&arvif->ar->conf_mutex); ++ ret = ath12k_mac_set_key(arvif->ar, cmd, arvif, arsta, key); ++ mutex_unlock(&arvif->ar->conf_mutex); ++ } ++ } else { ++ mutex_lock(&arvif->ar->conf_mutex); ++ ret = ath12k_mac_set_key(arvif->ar, cmd, arvif, arsta, key); ++ mutex_unlock(&arvif->ar->conf_mutex); + } +- +- mutex_lock(&ar->conf_mutex); +- +- ret = ath12k_mac_set_key(ar, cmd, arvif, arsta, key); +- +- mutex_unlock(&ar->conf_mutex); + out: + mutex_unlock(&ah->conf_mutex); + return ret; +--- a/drivers/net/wireless/ath/ath12k/dp_mon.c ++++ b/drivers/net/wireless/ath/ath12k/dp_mon.c +@@ -2167,8 +2167,13 @@ static void ath12k_dp_mon_rx_deliver_msd + decap = ppduinfo->cmn_mpdu_info.mon_mpdu[mpdu_idx].msdu_info[0].decap_format; + spin_lock_bh(&ar->ab->base_lock); + peer = ath12k_dp_rx_h_find_peer(ar->ab, msdu); +- if (peer && peer->sta) ++ if (peer && peer->sta) { + pubsta = peer->sta; ++ if (pubsta->valid_links) { ++ status->link_valid = 1; ++ status->link_id = peer->link_id; ++ } ++ } + spin_unlock_bh(&ar->ab->base_lock); + + ath12k_dbg(ar->ab, ATH12K_DBG_DATA, diff --git a/feeds/ipq95xx/mac80211/patches/qca/673-ath12k-remove-reserve-member-of-wbm-completion-struct.patch b/feeds/ipq95xx/mac80211/patches/qca/688-ath12k-remove-reserve-member-of-wbm-completion-struct.patch similarity index 100% rename from feeds/ipq95xx/mac80211/patches/qca/673-ath12k-remove-reserve-member-of-wbm-completion-struct.patch rename to feeds/ipq95xx/mac80211/patches/qca/688-ath12k-remove-reserve-member-of-wbm-completion-struct.patch diff --git a/feeds/ipq95xx/mac80211/patches/qca/688-cfg80211-get-channel-and-txpower-value-for-each-link.patch b/feeds/ipq95xx/mac80211/patches/qca/688-cfg80211-get-channel-and-txpower-value-for-each-link.patch new file mode 100644 index 000000000..8e44510f5 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/688-cfg80211-get-channel-and-txpower-value-for-each-link.patch @@ -0,0 +1,82 @@ +From 9ba378572e0427602b7619a30ea616395f3c1ed8 Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Fri, 18 Nov 2022 17:32:19 +0530 +Subject: [PATCH] cfg80211: get channel and txpower value for each link + +Currently, wdev->valid_links set for multilink operation but channel +attribute values are filling when it's not set, because of this we +are not getting value of channel attribute for multilink. + +So, added rdev_get_channel and rdev_get_tx_power function for each link. + +Signed-off-by: Aaradhana Sahu +--- + net/wireless/nl80211.c | 53 +++++++++++++++++++++++++++--------------- + 1 file changed, 34 insertions(+), 19 deletions(-) + +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -4070,25 +4070,6 @@ static int nl80211_send_iface(struct sk_ + nla_put_u8(msg, NL80211_ATTR_4ADDR, wdev->use_4addr)) + goto nla_put_failure; + +- if (rdev->ops->get_channel && !wdev->valid_links) { +- struct cfg80211_chan_def chandef = {}; +- int ret; +- +- ret = rdev_get_channel(rdev, wdev, 0, &chandef); +- if (ret == 0 && nl80211_send_chandef(msg, &chandef)) +- goto nla_put_failure; +- } +- +- if (rdev->ops->get_tx_power) { +- int dbm, ret; +- +- ret = rdev_get_tx_power(rdev, wdev, &dbm); +- if (ret == 0 && +- nla_put_u32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL, +- DBM_TO_MBM(dbm))) +- goto nla_put_failure; +- } +- + wdev_lock(wdev); + switch (wdev->iftype) { + case NL80211_IFTYPE_AP: +@@ -4150,10 +4131,37 @@ static int nl80211_send_iface(struct sk_ + if (ret == 0 && nl80211_send_chandef(msg, &chandef)) + goto nla_put_failure; + ++ if (rdev->ops->get_tx_power) { ++ int dbm, ret; ++ /* TODO find tx_power according to link_id */ ++ ret = rdev_get_tx_power(rdev, wdev, &dbm); ++ if (ret == 0 && ++ nla_put_u32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL, ++ DBM_TO_MBM(dbm))) ++ goto nla_put_failure; ++ } + nla_nest_end(msg, link); + } + + nla_nest_end(msg, links); ++ } else { ++ if (rdev->ops->get_channel) { ++ struct cfg80211_chan_def chandef = {}; ++ int ret; ++ ++ ret = rdev_get_channel(rdev, wdev, 0, &chandef); ++ if (ret == 0 && nl80211_send_chandef(msg, &chandef)) ++ goto nla_put_failure; ++ } ++ ++ if (rdev->ops->get_tx_power) { ++ int dbm, ret; ++ ret = rdev_get_tx_power(rdev, wdev, &dbm); ++ if (ret == 0 && ++ nla_put_u32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL, ++ DBM_TO_MBM(dbm))) ++ goto nla_put_failure; ++ } + } + + genlmsg_end(msg, hdr); diff --git a/feeds/ipq95xx/mac80211/patches/qca/689-01-cfg80211-get-link-information-of-associated-station.patch b/feeds/ipq95xx/mac80211/patches/qca/689-01-cfg80211-get-link-information-of-associated-station.patch new file mode 100644 index 000000000..7cd15a128 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/689-01-cfg80211-get-link-information-of-associated-station.patch @@ -0,0 +1,79 @@ +From 3d87a3fe565d921b8d6296b105e08afeb02d798f Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Wed, 30 Nov 2022 12:51:08 +0530 +Subject: [PATCH] cfg80211: get link information of associated station + +struct station_info contains all information related to +station dump. + +Currently, no information present in struct +station_info related to link of associated station. + +So, add link related information for associated station. + +Signed-off-by: Aaradhana Sahu +--- + include/net/cfg80211.h | 7 +++++++ + net/wireless/nl80211.c | 18 ++++++++++++++++++ + 2 files changed, 25 insertions(+) + +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -1896,6 +1896,11 @@ struct cfg80211_tid_stats { + + #define IEEE80211_MAX_CHAINS 4 + ++struct link_station_info { ++ u8 addr[ETH_ALEN] __aligned(2); ++ /* TODO: packet stats */ ++}; ++ + /** + * struct station_info - station information + * +@@ -2021,6 +2026,8 @@ struct station_info { + u32 airtime_link_metric; + + u8 connected_to_as; ++ u16 valid_links; ++ struct link_station_info links[IEEE80211_MLD_MAX_NUM_LINKS]; + }; + + /** +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -6682,7 +6682,8 @@ static int nl80211_send_station(struct s + const u8 *mac_addr, struct station_info *sinfo) + { + void *hdr; +- struct nlattr *sinfoattr, *bss_param; ++ struct nlattr *sinfoattr, *bss_param, *links, *link; ++ unsigned int link_id = 0; + + hdr = nl80211hdr_put(msg, portid, seq, flags, cmd); + if (!hdr) { +@@ -6694,6 +6695,24 @@ static int nl80211_send_station(struct s + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr) || + nla_put_u32(msg, NL80211_ATTR_GENERATION, sinfo->generation)) + goto nla_put_failure; ++ if (sinfo->valid_links) { ++ links = nla_nest_start(msg, ++ NL80211_ATTR_MLO_LINKS); ++ if (!links) ++ goto nla_put_failure; ++ ++ for_each_valid_link(sinfo, link_id) { ++ link = nla_nest_start(msg, link_id + 1); ++ if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id)) ++ goto nla_put_failure; ++ if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ++ sinfo->links[link_id].addr)) ++ goto nla_put_failure; ++ nla_nest_end(msg, link); ++ } ++ ++ nla_nest_end(msg, links); ++ } + + sinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_STA_INFO); + if (!sinfoattr) diff --git a/feeds/ipq95xx/mac80211/patches/qca/689-01-mac80211-use-link-conf.patch b/feeds/ipq95xx/mac80211/patches/qca/689-01-mac80211-use-link-conf.patch new file mode 100644 index 000000000..5d4d7f4d7 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/689-01-mac80211-use-link-conf.patch @@ -0,0 +1,218 @@ +From 8d3df0c886f4393fa8e1dacd2a3532f8d913ad97 Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Wed, 23 Nov 2022 14:26:24 +0530 +Subject: [PATCH] mac80211: use link conf and link sta + +Use link conf and link sta for link specific operations. +The link conf is replaced in start ap. +Link sta is updated with NSS during link station add. + +Also, moved the condition for link bss address validation +to differentiate link bss address from ML address. + +Signed-off-by: Sriram R +--- + net/mac80211/cfg.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1333,40 +1333,40 @@ static int ieee80211_start_ap(struct wip + } + + if (params->he_cap) { +- memcpy(&sdata->vif.bss_conf.he_cap_elem, params->he_cap, ++ memcpy(&link_conf->he_cap_elem, params->he_cap, + sizeof(*params->he_cap)); +- sdata->vif.bss_conf.he_su_beamformer = ++ link_conf->he_su_beamformer = + params->he_cap->phy_cap_info[3] & + IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER; +- sdata->vif.bss_conf.he_su_beamformee = ++ link_conf->he_su_beamformee = + params->he_cap->phy_cap_info[4] & + IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE; +- sdata->vif.bss_conf.he_mu_beamformer = ++ link_conf->he_mu_beamformer = + params->he_cap->phy_cap_info[4] & + IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER; +- sdata->vif.bss_conf.he_full_ul_mumimo = ++ link_conf->he_full_ul_mumimo = + params->he_cap->phy_cap_info[2] & + IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO; + } + + if (params->eht_cap) { +- if (!sdata->vif.bss_conf.he_support) ++ if (!link_conf->he_support) + return -EOPNOTSUPP; + +- sdata->vif.bss_conf.eht_support = true; +- sdata->vif.bss_conf.eht_su_beamformer = ++ link_conf->eht_support = true; ++ link_conf->eht_su_beamformer = + params->eht_cap->fixed.phy_cap_info[0] & + IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER; +- sdata->vif.bss_conf.eht_su_beamformee = ++ link_conf->eht_su_beamformee = + params->eht_cap->fixed.phy_cap_info[0] & + IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE; +- sdata->vif.bss_conf.eht_mu_beamformer = ++ link_conf->eht_mu_beamformer = + params->eht_cap->fixed.phy_cap_info[7] & + IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ; +- sdata->vif.bss_conf.eht_80mhz_full_bw_ul_mumimo = ++ link_conf->eht_80mhz_full_bw_ul_mumimo = + params->eht_cap->fixed.phy_cap_info[7] & + IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ; +- ieee80211_eht_op_ie_to_bss_conf(&sdata->vif, params->eht_oper); ++ ieee80211_eht_op_ie_to_bss_conf(link_conf, params->eht_oper); + } + + mutex_lock(&local->mtx); +@@ -1893,6 +1893,15 @@ static int sta_link_apply_parameters(str + link_sta->pub->ru_punct_bitmap = params->ru_punct_bitmap; + } + ++ /* update nss if not done already for the link sta, ++ * for the deflink the nss will be updated once the assoc ++ * flag is set through set station. For the non-deflink sta ++ * we would reach here only during assoc, so we would have all ++ * caps to calculate the nss. ++ */ ++ if (&sta->deflink != link_sta) ++ ieee80211_sta_set_rx_nss(link_sta); ++ + if (params->opmode_notif_used) { + /* returned value is only needed for rc update, but the + * rc isn't initialized here yet, so ignore it +--- a/net/mac80211/eht.c ++++ b/net/mac80211/eht.c +@@ -79,7 +79,7 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(stru + link_sta->pub->bandwidth = ieee80211_sta_cur_vht_bw(link_sta); + } + +-void ieee80211_eht_op_ie_to_bss_conf(struct ieee80211_vif *vif, ++void ieee80211_eht_op_ie_to_bss_conf(struct ieee80211_bss_conf *link_conf, + const struct ieee80211_eht_operation *op_ie) + { + struct ieee80211_eht_operation_info *eht_oper_info; +@@ -90,12 +90,12 @@ void ieee80211_eht_op_ie_to_bss_conf(str + if (op_ie->params && IEEE80211_EHT_OPER_INFO_PRESENT) { + eht_oper_info = op_ie->optional; + +- vif->bss_conf.eht_oper.chan_width = ++ link_conf->eht_oper.chan_width = + u8_get_bits(eht_oper_info->control, + IEEE80211_EHT_OPER_CHAN_WIDTH); +- vif->bss_conf.eht_oper.ccfs0 = eht_oper_info->ccfs0; +- vif->bss_conf.eht_oper.ccfs1 = eht_oper_info->ccfs1; +- vif->bss_conf.eht_oper.present_bm = ++ link_conf->eht_oper.ccfs0 = eht_oper_info->ccfs0; ++ link_conf->eht_oper.ccfs1 = eht_oper_info->ccfs1; ++ link_conf->eht_oper.present_bm = + u8_get_bits(eht_oper_info->control, + IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT); + } +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -2600,6 +2600,6 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(stru + const struct ieee80211_eht_cap_elem *eht_cap_ie_elem, + u8 eht_cap_len, + struct link_sta_info *link_sta); +-void ieee80211_eht_op_ie_to_bss_conf(struct ieee80211_vif *vif, ++void ieee80211_eht_op_ie_to_bss_conf(struct ieee80211_bss_conf *link_conf, + const struct ieee80211_eht_operation *op_ie); + #endif /* IEEE80211_I_H */ +--- a/net/mac80211/mesh.c ++++ b/net/mac80211/mesh.c +@@ -784,7 +784,7 @@ ieee80211_mesh_update_bss_params(struct + eht_oper = (void *)(cap->data + 1); + + if (eht_oper) +- ieee80211_eht_op_ie_to_bss_conf(&sdata->vif, eht_oper); ++ ieee80211_eht_op_ie_to_bss_conf(&sdata->vif.bss_conf, eht_oper); + } + + /** +--- a/net/mac80211/agg-rx.c ++++ b/net/mac80211/agg-rx.c +@@ -207,6 +207,8 @@ static void ieee80211_send_addba_resp(st + struct ieee80211_mgmt *mgmt; + bool amsdu = ieee80211_hw_check(&local->hw, SUPPORTS_AMSDU_IN_AMPDU); + u16 capab; ++ struct ieee80211_link_data *link; ++ u8 link_id; + + skb = dev_alloc_skb(sizeof(*mgmt) + + 2 + sizeof(struct ieee80211_addba_ext_ie) + +@@ -218,14 +220,29 @@ static void ieee80211_send_addba_resp(st + mgmt = skb_put_zero(skb, 24); + memcpy(mgmt->da, da, ETH_ALEN); + memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); +- if (sdata->vif.type == NL80211_IFTYPE_AP || +- sdata->vif.type == NL80211_IFTYPE_AP_VLAN || +- sdata->vif.type == NL80211_IFTYPE_MESH_POINT) ++ if (sdata->vif.type == NL80211_IFTYPE_AP) { + memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); +- else if (sdata->vif.type == NL80211_IFTYPE_STATION) ++ /* Override MLD address in A2/A3 with link addr ++ * in case of AP MLO and a non ML STA ++ */ ++ if (sdata->vif.valid_links && sta && !sta->sta.mlo) { ++ link_id = sta->deflink.link_id; ++ rcu_read_lock(); ++ link = rcu_dereference(sdata->link[link_id]); ++ if (link) { ++ memcpy(mgmt->sa, link->conf->addr, ETH_ALEN); ++ memcpy(mgmt->bssid, link->conf->addr, ETH_ALEN); ++ } ++ rcu_read_unlock(); ++ } ++ } else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN || ++ sdata->vif.type == NL80211_IFTYPE_MESH_POINT) { ++ memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); ++ } else if (sdata->vif.type == NL80211_IFTYPE_STATION) { + memcpy(mgmt->bssid, sdata->deflink.u.mgd.bssid, ETH_ALEN); +- else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) ++ } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { + memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN); ++ } + + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); +@@ -269,6 +286,9 @@ void ___ieee80211_start_rx_ba_session(st + int i, ret = -EOPNOTSUPP; + u16 status = WLAN_STATUS_REQUEST_DECLINED; + u16 max_buf_size; ++ u8 link_id; ++ enum nl80211_band band; ++ struct ieee80211_bss_conf *link_conf; + + if (tid >= IEEE80211_FIRST_TSPEC_TSID) { + ht_dbg(sta->sdata, +@@ -277,8 +297,22 @@ void ___ieee80211_start_rx_ba_session(st + goto end; + } + +- if (!sta->sta.deflink.ht_cap.ht_supported && +- sta->sdata->vif.bss_conf.chandef.chan->band != NL80211_BAND_6GHZ) { ++ link_id = sta->sta.deflink.link_id; ++ rcu_read_lock(); ++ link_conf = rcu_dereference(sta->sdata->vif.link_conf[link_id]); ++ ++ if (WARN_ON(!link_conf || (!link_conf->chandef.chan))) { ++ ht_dbg(sta->sdata, ++ "STA %pM BA session couldnt setup due to invalid link %d\n", ++ sta->sta.addr, link_id); ++ rcu_read_unlock(); ++ goto end; ++ } ++ ++ band = link_conf->chandef.chan->band; ++ ++ rcu_read_unlock(); ++ if (!sta->sta.deflink.ht_cap.ht_supported && band != NL80211_BAND_6GHZ) { + ht_dbg(sta->sdata, + "STA %pM erroneously requests BA session on tid %d w/o QoS\n", + sta->sta.addr, tid); diff --git a/feeds/ipq95xx/mac80211/patches/qca/689-02-ath12k-use-link-conf-for-all-bss-config-operations.patch b/feeds/ipq95xx/mac80211/patches/qca/689-02-ath12k-use-link-conf-for-all-bss-config-operations.patch new file mode 100644 index 000000000..a9e95ccff --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/689-02-ath12k-use-link-conf-for-all-bss-config-operations.patch @@ -0,0 +1,525 @@ +From f5348b7077a1e3bd385a8f69032f1826df7a2d5d Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Wed, 23 Nov 2022 14:26:46 +0530 +Subject: [PATCH 1/2] ath12k: use link conf for all bss config operations + +replace use of default bss_conf in vif with link conf + +Signed-off-by: Sriram R +--- + drivers/net/wireless/ath/ath12k/mac.c | 229 +++++++++++++++++++++----- + 1 file changed, 191 insertions(+), 38 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -584,6 +584,22 @@ static u8 ath12k_mac_bitrate_to_rate(int + (ath12k_mac_bitrate_is_cck(bitrate) ? BIT(7) : 0); + } + ++static struct ++ieee80211_bss_conf *ath12k_get_link_bss_conf(struct ath12k_link_vif *arvif) ++{ ++ struct ieee80211_vif *vif = arvif->ahvif->vif; ++ struct ieee80211_bss_conf *link_conf = NULL; ++ ++ WARN_ON(!rcu_read_lock_held()); ++ ++ if (arvif->link_id > IEEE80211_MLD_MAX_NUM_LINKS) ++ return NULL; ++ ++ link_conf = rcu_dereference(vif->link_conf[arvif->link_id]); ++ ++ return link_conf; ++} ++ + static void ath12k_get_arvif_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) + { +@@ -1546,11 +1562,19 @@ void ath12k_mac_bcn_tx_event(struct ath1 + { + struct ieee80211_vif *vif = arvif->ahvif->vif; + struct ath12k *ar = arvif->ar; ++ struct ieee80211_bss_conf* link_conf; ++ ++ link_conf = ath12k_get_link_bss_conf(arvif); ++ ++ if (!link_conf) { ++ ath12k_warn(ar->ab, "unable to access bss link conf in bcn tx event\n"); ++ return; ++ } + +- if (!vif->bss_conf.color_change_active && !arvif->bcca_zero_sent) ++ if (!link_conf->color_change_active && !arvif->bcca_zero_sent) + return; + +- if (vif->bss_conf.color_change_active && ieee80211_beacon_cntdwn_is_complete(vif)) { ++ if (link_conf->color_change_active && ieee80211_beacon_cntdwn_is_complete(vif)) { + arvif->bcca_zero_sent = true; + ieee80211_color_change_finish(vif); + return; +@@ -1558,7 +1582,7 @@ void ath12k_mac_bcn_tx_event(struct ath1 + + arvif->bcca_zero_sent = false; + +- if (vif->bss_conf.color_change_active) ++ if (link_conf->color_change_active) + ieee80211_beacon_update_cntdwn(vif); + ieee80211_queue_work(ar->ah->hw, &arvif->update_bcn_template_work); + } +@@ -1667,8 +1691,8 @@ static void ath12k_peer_assoc_h_crypto(s + struct peer_assoc_params *arg) + { + struct ieee80211_vif *vif = arvif->ahvif->vif; +- struct ieee80211_bss_conf *info = &vif->bss_conf; + struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ieee80211_bss_conf *info; + struct cfg80211_chan_def def; + struct cfg80211_bss *bss; + const u8 *rsnie = NULL; +@@ -1682,8 +1706,19 @@ static void ath12k_peer_assoc_h_crypto(s + + lockdep_assert_held(&ar->conf_mutex); + +- if (WARN_ON(ath12k_mac_vif_chan(vif, &def, link_id))) ++ rcu_read_lock(); ++ info = ath12k_get_link_bss_conf(arvif); ++ ++ if (!info) { ++ rcu_read_unlock(); ++ ath12k_warn(ar->ab, "unable to access bss link conf for peer assoc send\n"); ++ return; ++ } ++ ++ if (WARN_ON(ath12k_mac_vif_chan(vif, &def, link_id))) { ++ rcu_read_unlock(); + return; ++ } + + hw = ar->ah->hw; + bss = cfg80211_get_bss(hw->wiphy, def.chan, info->bssid, NULL, 0, +@@ -1728,6 +1763,7 @@ static void ath12k_peer_assoc_h_crypto(s + } + + /* TODO: safe_mode_enabled (bypass 4-way handshake) flag req? */ ++ rcu_read_unlock(); + } + + static void ath12k_peer_assoc_h_rates(struct ath12k *ar, +@@ -2229,6 +2265,22 @@ static void ath12k_peer_assoc_h_he(struc + u8 link_id = arvif->link_id; + struct ath12k_sta *ahsta = arsta->ahsta; + struct ieee80211_sta *sta; ++ struct ieee80211_bss_conf* link_conf; ++ u32 peer_he_ops; ++ ++ rcu_read_lock(); ++ ++ link_conf = ath12k_get_link_bss_conf(arvif); ++ ++ if (!link_conf) { ++ rcu_read_unlock(); ++ ath12k_warn(ar->ab, "unable to access bss link conf in peer assoc\n"); ++ return; ++ } ++ ++ peer_he_ops = link_conf->he_oper.params; ++ ++ rcu_read_unlock(); + + sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + he_cap = &sta->deflink.he_cap; +@@ -2285,7 +2337,9 @@ static void ath12k_peer_assoc_h_he(struc + sizeof(arg->peer_he_cap_macinfo)); + memcpy(&arg->peer_he_cap_phyinfo, he_cap->he_cap_elem.phy_cap_info, + sizeof(arg->peer_he_cap_phyinfo)); +- arg->peer_he_ops = vif->bss_conf.he_oper.params; ++ ++ arg->peer_he_ops = peer_he_ops; ++ + + /* the top most byte is used to indicate BSS color info */ + arg->peer_he_ops &= 0xffffff; +@@ -2655,6 +2709,23 @@ static void ath12k_peer_assoc_h_eht(stru + u8 link_id = arvif->link_id; + struct ath12k_sta *ahsta = arsta->ahsta; + struct ieee80211_sta *sta; ++ struct ieee80211_bss_conf* link_conf; ++ u32 peer_eht_ops; ++ ++ rcu_read_lock(); ++ ++ link_conf = ath12k_get_link_bss_conf(arvif); ++ ++ if (!link_conf) { ++ rcu_read_unlock(); ++ ath12k_warn(ar->ab, "unable to access bss link conf in peer assoc\n"); ++ return; ++ } ++ ++ memcpy(&peer_eht_ops, &link_conf->eht_oper, ++ sizeof(link_conf->eht_oper)); ++ ++ rcu_read_unlock(); + + sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + +@@ -2690,8 +2761,7 @@ static void ath12k_peer_assoc_h_eht(stru + sizeof(eht_cap->eht_cap_elem.mac_cap_info)); + memcpy(arg->peer_eht_cap_phy, eht_cap->eht_cap_elem.phy_cap_info, + sizeof(eht_cap->eht_cap_elem.phy_cap_info)); +- memcpy(&arg->peer_eht_ops, &vif->bss_conf.eht_oper, +- sizeof(vif->bss_conf.eht_oper)); ++ arg->peer_eht_ops = peer_eht_ops;; + + eht_nss = ath12k_mac_max_eht_nss(eht_mcs_mask); + +@@ -3239,13 +3309,26 @@ static bool ath12k_mac_set_he_txbf_conf( + u32 param = WMI_VDEV_PARAM_SET_HEMU_MODE; + u32 value = 0; + int ret; ++ struct ieee80211_bss_conf* link_conf; ++ ++ rcu_read_lock(); + +- if (!ahvif->vif->bss_conf.he_support) ++ link_conf = ath12k_get_link_bss_conf(arvif); ++ ++ if (!link_conf) { ++ rcu_read_unlock(); ++ ath12k_warn(ar->ab, "unable to access bss link conf in txbf conf\n"); ++ return false; ++ } ++ ++ if (!link_conf->he_support) { ++ rcu_read_unlock(); + return true; ++ } + +- if (ahvif->vif->bss_conf.he_su_beamformer) { ++ if (link_conf->he_su_beamformer) { + value |= FIELD_PREP(HE_MODE_SU_TX_BFER, HE_SU_BFER_ENABLE); +- if (ahvif->vif->bss_conf.he_mu_beamformer && ++ if (link_conf->he_mu_beamformer && + ahvif->vdev_type == WMI_VDEV_TYPE_AP) + value |= FIELD_PREP(HE_MODE_MU_TX_BFER, HE_MU_BFER_ENABLE); + } +@@ -3254,13 +3337,14 @@ static bool ath12k_mac_set_he_txbf_conf( + value |= FIELD_PREP(HE_MODE_DL_OFDMA, HE_DL_MUOFDMA_ENABLE) | + FIELD_PREP(HE_MODE_UL_OFDMA, HE_UL_MUOFDMA_ENABLE); + +- if (ahvif->vif->bss_conf.he_full_ul_mumimo) ++ if (link_conf->he_full_ul_mumimo) + value |= FIELD_PREP(HE_MODE_UL_MUMIMO, HE_UL_MUMIMO_ENABLE); + +- if (ahvif->vif->bss_conf.he_su_beamformee) ++ if (link_conf->he_su_beamformee) + value |= FIELD_PREP(HE_MODE_SU_TX_BFEE, HE_SU_BFEE_ENABLE); + } + ++ rcu_read_unlock(); + 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", +@@ -3295,9 +3379,24 @@ static bool ath12k_mac_vif_recalc_sta_he + u32 hemode = 0; + int ret; + u8 link_id = arvif->link_id; ++ struct ieee80211_bss_conf* link_conf; ++ ++ rcu_read_lock(); + +- if (!vif->bss_conf.he_support) ++ link_conf = ath12k_get_link_bss_conf(arvif); ++ ++ if (!link_conf) { ++ rcu_read_unlock(); ++ ath12k_warn(ar->ab, "unable to access bss link conf in recalc txbf conf\n"); ++ return false; ++ } ++ ++ if (!link_conf->he_support) { ++ rcu_read_unlock(); + return true; ++ } ++ ++ rcu_read_unlock(); + + if (vif->type != NL80211_IFTYPE_STATION) + return false; +@@ -3357,13 +3456,26 @@ static bool ath12k_mac_set_eht_txbf_conf + u32 param = WMI_VDEV_PARAM_SET_EHT_MU_MODE; + u32 value = 0; + int ret; ++ struct ieee80211_bss_conf* link_conf; + +- if (!ahvif->vif->bss_conf.eht_support) ++ rcu_read_lock(); ++ ++ link_conf = ath12k_get_link_bss_conf(arvif); ++ ++ if (!link_conf) { ++ rcu_read_unlock(); ++ ath12k_warn(ar->ab, "unable to access bss link conf in eht txbf conf\n"); ++ return false; ++ } ++ ++ if (!link_conf->eht_support) { ++ rcu_read_unlock(); + return true; ++ } + +- if (ahvif->vif->bss_conf.eht_su_beamformer) { ++ if (link_conf->eht_su_beamformer) { + value |= FIELD_PREP(EHT_MODE_SU_TX_BFER, EHT_SU_BFER_ENABLE); +- if (ahvif->vif->bss_conf.eht_mu_beamformer && ++ if (link_conf->eht_mu_beamformer && + ahvif->vdev_type == WMI_VDEV_TYPE_AP) + value |= FIELD_PREP(EHT_MODE_MU_TX_BFER, EHT_MU_BFER_ENABLE) | + FIELD_PREP(EHT_MODE_DL_OFDMA_MUMIMO, EHT_DL_MUOFDMA_ENABLE) | +@@ -3374,13 +3486,15 @@ static bool ath12k_mac_set_eht_txbf_conf + value |= FIELD_PREP(EHT_MODE_DL_OFDMA, EHT_DL_MUOFDMA_ENABLE) | + FIELD_PREP(EHT_MODE_UL_OFDMA, EHT_UL_MUOFDMA_ENABLE); + +- if (ahvif->vif->bss_conf.eht_80mhz_full_bw_ul_mumimo) ++ if (link_conf->eht_80mhz_full_bw_ul_mumimo) + value |= FIELD_PREP(EHT_MODE_MUMIMO, EHT_UL_MUMIMO_ENABLE); + +- if (ahvif->vif->bss_conf.eht_su_beamformee) ++ if (link_conf->eht_su_beamformee) + value |= FIELD_PREP(EHT_MODE_SU_TX_BFEE, EHT_SU_BFEE_ENABLE); + } + ++ rcu_read_unlock(); ++ + 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", +@@ -3892,10 +4006,10 @@ static void ath12k_mac_bss_info_changed( + else + arvif->do_not_send_tmpl = false; + +- if (arvif->is_up && vif->bss_conf.he_support) { ++ if (arvif->is_up && info->he_support) { + param_id = WMI_VDEV_PARAM_BA_MODE; + +- if (vif->bss_conf.eht_support) ++ if (info->eht_support) + param_value = WMI_BA_MODE_BUFFER_SIZE_1024; + else + param_value = WMI_BA_MODE_BUFFER_SIZE_256; +@@ -3948,10 +4062,10 @@ static void ath12k_mac_bss_info_changed( + ath12k_control_beaconing(arvif, info); + + +- if (arvif->is_up && vif->bss_conf.he_support) { +- if (vif->bss_conf.he_oper.params) { ++ if (arvif->is_up && info->he_support) { ++ if (info->he_oper.params) { + param_id = WMI_VDEV_PARAM_HEOPS_0_31; +- param_value = vif->bss_conf.he_oper.params; ++ param_value = info->he_oper.params; + ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, + param_id, param_value); + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, +@@ -3963,8 +4077,8 @@ static void ath12k_mac_bss_info_changed( + param_value, arvif->vdev_id, ret); + + param_id = WMI_VDEV_PARAM_EHTOPS_0_31; +- memcpy(¶m_value, &vif->bss_conf.eht_oper, +- sizeof(vif->bss_conf.eht_oper)); ++ memcpy(¶m_value, &info->eht_oper, ++ sizeof(info->eht_oper)); + ret = ath12k_wmi_vdev_set_param_cmd(ar, + arvif->vdev_id, + param_id, +@@ -4074,12 +4188,12 @@ static void ath12k_mac_bss_info_changed( + if (changed & BSS_CHANGED_MCAST_RATE && + !ath12k_mac_vif_chan(ahvif->vif, &def, link_id)) { + band = def.chan->band; +- mcast_rate = vif->bss_conf.mcast_rate[band]; ++ mcast_rate = info->mcast_rate[band]; + + if (mcast_rate > 0) + rateidx = mcast_rate - 1; + else +- rateidx = ffs(vif->bss_conf.basic_rates) - 1; ++ rateidx = ffs(info->basic_rates) - 1; + + if (ar->pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP) + rateidx += ATH12K_MAC_FIRST_OFDM_RATE_IDX; +@@ -4137,7 +4251,7 @@ static void ath12k_mac_bss_info_changed( + arvif->vdev_id, + info->he_bss_color.color, + ATH12K_BSS_COLOR_AP_PERIODS, +- ahvif->vif->bss_conf.nontransmitted ? ++ info->nontransmitted ? + 0 : color_collision_detect); + if (ret) + ath12k_warn(ar->ab, "failed to set bss color collision on vdev %i: %d\n", +@@ -8322,33 +8436,48 @@ static int ath12k_mac_setup_vdev_params_ + struct ath12k *ar = arvif->ar; + struct ath12k_link_vif *tx_arvif; + struct ieee80211_vif *tx_vif; +- struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ieee80211_bss_conf *link_conf; ++ ++ rcu_read_lock(); ++ ++ link_conf = ath12k_get_link_bss_conf(arvif); ++ ++ if (!link_conf) { ++ rcu_read_unlock(); ++ ath12k_warn(ar->ab, "unable to access bss link conf in mbssid params setup\n"); ++ return -EINVAL; ++ } + + *tx_vdev_id = 0; + /* FIXME MBSSID with MLO */ + tx_vif = arvif->ahvif->vif->mbssid_tx_vif; + if (!tx_vif) { + *flags = WMI_HOST_VDEV_FLAGS_NON_MBSSID_AP; ++ rcu_read_unlock(); + return 0; + } + + tx_arvif = &ath12k_vif_to_ahvif(tx_vif)->deflink; + +- if (ahvif->vif->bss_conf.nontransmitted) { +- if (ar->ah->hw->wiphy != ieee80211_vif_to_wdev(tx_vif)->wiphy) ++ if (link_conf->nontransmitted) { ++ if (ar->ah->hw->wiphy != ieee80211_vif_to_wdev(tx_vif)->wiphy) { ++ rcu_read_unlock(); + return -EINVAL; ++ } + + *flags = WMI_HOST_VDEV_FLAGS_NON_TRANSMIT_AP; + *tx_vdev_id = tx_arvif->vdev_id; + } else if (tx_arvif == arvif) { + *flags = WMI_HOST_VDEV_FLAGS_TRANSMIT_AP; + } else { ++ rcu_read_unlock(); + return -EINVAL; + } + +- if (ahvif->vif->bss_conf.ema_ap) ++ if (link_conf->ema_ap) + *flags |= WMI_HOST_VDEV_FLAGS_EMA_MODE; + ++ rcu_read_unlock(); + return 0; + } + +@@ -9267,6 +9396,7 @@ static int ath12k_mac_set_6g_nonht_dup_c + struct ath12k_vif *ahvif = arvif->ahvif; + struct ieee80211_bss_conf *link_conf; + u8 link_addr[ETH_ALEN]; ++ bool nontransmitted; + + rcu_read_lock(); + +@@ -9278,10 +9408,11 @@ static int ath12k_mac_set_6g_nonht_dup_c + } + + memcpy(link_addr, link_conf->addr, ETH_ALEN); ++ nontransmitted = link_conf->nontransmitted; + rcu_read_unlock(); + + if ((ahvif->vdev_type == WMI_VDEV_TYPE_AP) && +- !ahvif->vif->bss_conf.nontransmitted && ++ !nontransmitted && + (chandef->chan->band == NL80211_BAND_6GHZ)) { + param_id = WMI_VDEV_PARAM_6GHZ_PARAMS; + if (mode > MODE_11AX_HE20 && !is_psc) { +@@ -10285,7 +10416,7 @@ void ath12k_mac_fill_reg_tpc_info(struct + struct ath12k_base *ab = ar->ab; + struct ath12k_vif *ahvif = arvif->ahvif; + struct ieee80211_vif *vif = ahvif->vif; +- struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; ++ struct ieee80211_bss_conf *bss_conf; + struct ath12k_reg_tpc_power_info *reg_tpc_info = &arvif->reg_tpc_info; + struct ieee80211_channel *chan, *temp_chan; + u8 pwr_lvl_idx, num_pwr_levels, pwr_reduction; +@@ -10295,12 +10426,22 @@ void ath12k_mac_fill_reg_tpc_info(struct + u16 oper_freq = 0, start_freq = 0, center_freq = 0; + u8 reg_6g_power_mode; + ++ rcu_read_lock(); ++ ++ bss_conf = ath12k_get_link_bss_conf(arvif); ++ ++ if (!bss_conf) { ++ rcu_read_unlock(); ++ ath12k_warn(ar->ab, "unable to access bss link conf in tpc reg fill\n"); ++ return; ++ } ++ + /* For STA, 6g power mode will be present in the beacon, but for AP, + * AP cant parse its own beacon. Hence, we get the 6g power mode + * from the wdev corresponding to the struct ieee80211_vif + */ + if (ahvif->vdev_type == WMI_VDEV_TYPE_STA) +- reg_6g_power_mode = vif->bss_conf.power_type; ++ reg_6g_power_mode = bss_conf->power_type; + else if (ahvif->vdev_type == WMI_VDEV_TYPE_AP) { + struct wireless_dev *wdev = ieee80211_vif_to_wdev(vif); + /* With respect to ieee80211, the 6G AP power mode starts from index +@@ -10319,6 +10460,8 @@ void ath12k_mac_fill_reg_tpc_info(struct + start_freq = ath12k_mac_get_6g_start_frequency(&ctx->def); + pwr_reduction = bss_conf->pwr_reduction; + ++ rcu_read_unlock(); ++ + if (ahvif->vdev_type == WMI_VDEV_TYPE_STA && + arvif->reg_tpc_info.num_pwr_levels) { + is_tpe_present = true; +@@ -10482,7 +10625,7 @@ static void ath12k_mac_parse_tx_pwr_env( + struct ath12k_base *ab = ar->ab; + struct ath12k_vif *ahvif = arvif->ahvif; + struct ieee80211_vif *vif = ahvif->vif; +- struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; ++ struct ieee80211_bss_conf *bss_conf; + struct ieee80211_tx_pwr_env *single_tpe; + enum wmi_reg_6g_client_type client_type; + int i; +@@ -10491,6 +10634,16 @@ static void ath12k_mac_parse_tx_pwr_env( + bool use_local_tpe, non_psd_set = false, psd_set = false; + struct wireless_dev *wdev = ieee80211_vif_to_wdev(vif); + ++ rcu_read_lock(); ++ ++ bss_conf = ath12k_get_link_bss_conf(arvif); ++ ++ if (!bss_conf) { ++ rcu_read_unlock(); ++ ath12k_warn(ar->ab, "unable to access bss link conf in tpc reg fill\n"); ++ return; ++ } ++ + if (wdev) + client_type = wdev->reg_6g_power_mode; + else +@@ -10514,6 +10667,7 @@ static void ath12k_mac_parse_tx_pwr_env( + } + + if (!reg_tpe_count && !local_tpe_count) { ++ rcu_read_unlock(); + ath12k_warn(ab, + "no transmit power envelope match client power type %d\n", + client_type); +@@ -10598,6 +10752,7 @@ static void ath12k_mac_parse_tx_pwr_env( + } + } + } ++ rcu_read_unlock(); + } + + static int +@@ -10688,7 +10843,7 @@ ath12k_mac_op_assign_vif_chanctx(struct + if (ar->supports_6ghz && ctx->def.chan->band == NL80211_BAND_6GHZ && + (ahvif->vdev_type == WMI_VDEV_TYPE_STA || + ahvif->vdev_type == WMI_VDEV_TYPE_AP)) { +- power_type = vif->bss_conf.power_type; ++ power_type = link_conf->power_type; + ath12k_dbg(ab, ATH12K_DBG_MAC, "mac chanctx power type %d\n", + power_type); + if (power_type == IEEE80211_REG_UNSET_AP) diff --git a/feeds/ipq95xx/mac80211/patches/qca/689-02-mac80211-get-link-information-of-associated-station.patch b/feeds/ipq95xx/mac80211/patches/qca/689-02-mac80211-get-link-information-of-associated-station.patch new file mode 100644 index 000000000..2193f766e --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/689-02-mac80211-get-link-information-of-associated-station.patch @@ -0,0 +1,50 @@ +From b9a62abc6fe3023fa5233286bdcb164f17c77694 Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Fri, 2 Dec 2022 14:46:29 +0530 +Subject: [PATCH] mac80211: get link information of associated station + +fill valid_link value for each interface. + +Signed-off-by: Aaradhana Sahu +--- + net/mac80211/sta_info.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -2423,8 +2423,9 @@ void sta_set_sinfo(struct sta_info *sta, + struct ieee80211_sub_if_data *sdata = sta->sdata; + struct ieee80211_local *local = sdata->local; + u32 thr = 0; +- int i, ac, cpu; ++ int i, ac, cpu, link_id = 0; + struct ieee80211_sta_rx_stats *last_rxstats; ++ struct link_sta_info *link_sta = NULL; + + last_rxstats = sta_get_last_rx_stats(sta); + +@@ -2455,6 +2456,24 @@ void sta_set_sinfo(struct sta_info *sta, + sinfo->assoc_at = sta->assoc_at; + sinfo->inactive_time = + jiffies_to_msecs(jiffies - ieee80211_sta_last_active(sta)); ++ /* bitmap of valid links for MLO or 0 for non MLO */ ++ sinfo->valid_links = sta->sta.valid_links; ++ ++ if (sinfo->valid_links) { ++ for_each_valid_link(sinfo, link_id) { ++ rcu_read_lock(); ++ link_sta = rcu_dereference(sta->link[link_id]); ++ ++ if (!link_sta) { ++ rcu_read_unlock(); ++ continue; ++ } ++ ++ memcpy(sinfo->links[link_id].addr, link_sta->addr, ++ ETH_ALEN); ++ rcu_read_unlock(); ++ } ++ } + + if (!(sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES64) | + BIT_ULL(NL80211_STA_INFO_TX_BYTES)))) { diff --git a/feeds/ipq95xx/mac80211/patches/qca/689-03-ath12k-use-link-sta-instead-of-deflink.patch b/feeds/ipq95xx/mac80211/patches/qca/689-03-ath12k-use-link-sta-instead-of-deflink.patch new file mode 100644 index 000000000..e4f69a324 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/689-03-ath12k-use-link-sta-instead-of-deflink.patch @@ -0,0 +1,817 @@ +From 5a2e9c701a1cc127a1868020c6d4858ed2bf476b Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Sat, 26 Nov 2022 13:43:32 +0530 +Subject: [PATCH] ath12k: use link sta instead of deflink + +Use the link sta corresponding to the arsta rather +than the deflink for all operations within ath12k mac. + +The fixed rate and power config settings needs to be +done separately after the mac ops is extended with link id. + +Signed-off-by: Sriram R +--- + drivers/net/wireless/ath/ath12k/mac.c | 350 ++++++++++++++++---------- + 1 file changed, 217 insertions(+), 133 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -600,6 +600,25 @@ ieee80211_bss_conf *ath12k_get_link_bss_ + return link_conf; + } + ++static struct ++ieee80211_link_sta *ath12k_get_link_sta(struct ath12k_link_sta *arsta) ++{ ++ struct ieee80211_sta *sta; ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_link_sta *link_sta; ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); ++ ++ WARN_ON(!rcu_read_lock_held()); ++ ++ if (arsta->link_id > IEEE80211_MLD_MAX_NUM_LINKS) ++ return NULL; ++ ++ link_sta = rcu_dereference(sta->link[arsta->link_id]); ++ ++ return link_sta; ++} ++ + static void ath12k_get_arvif_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) + { +@@ -1719,19 +1738,15 @@ static void ath12k_peer_assoc_h_crypto(s + + lockdep_assert_held(&ar->conf_mutex); + +- rcu_read_lock(); + info = ath12k_get_link_bss_conf(arvif); + + if (!info) { +- rcu_read_unlock(); + ath12k_warn(ar->ab, "unable to access bss link conf for peer assoc send\n"); + return; + } + +- if (WARN_ON(ath12k_mac_vif_chan(vif, &def, link_id))) { +- rcu_read_unlock(); ++ if (WARN_ON(ath12k_mac_vif_chan(vif, &def, link_id))) + return; +- } + + hw = ar->ah->hw; + bss = cfg80211_get_bss(hw->wiphy, def.chan, info->bssid, NULL, 0, +@@ -1744,7 +1759,6 @@ static void ath12k_peer_assoc_h_crypto(s + } else if (bss) { + const struct cfg80211_bss_ies *ies; + +- rcu_read_lock(); + rsnie = ieee80211_bss_get_ie(bss, WLAN_EID_RSN); + + ies = rcu_dereference(bss->ies); +@@ -1753,7 +1767,6 @@ static void ath12k_peer_assoc_h_crypto(s + WLAN_OUI_TYPE_MICROSOFT_WPA, + ies->data, + ies->len); +- rcu_read_unlock(); + cfg80211_put_bss(hw->wiphy, bss); + } + +@@ -1776,7 +1789,6 @@ static void ath12k_peer_assoc_h_crypto(s + } + + /* TODO: safe_mode_enabled (bypass 4-way handshake) flag req? */ +- rcu_read_unlock(); + } + + static void ath12k_peer_assoc_h_rates(struct ath12k *ar, +@@ -1796,6 +1808,7 @@ static void ath12k_peer_assoc_h_rates(st + u8 link_id = arvif->link_id; + struct ath12k_sta *ahsta = arsta->ahsta; + struct ieee80211_sta *sta; ++ struct ieee80211_link_sta *link_sta; + + sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + +@@ -1804,9 +1817,16 @@ static void ath12k_peer_assoc_h_rates(st + if (WARN_ON(ath12k_mac_vif_chan(vif, &def, link_id))) + return; + ++ link_sta = ath12k_get_link_sta(arsta); ++ ++ if (!link_sta) { ++ ath12k_warn(ar->ab, "unable to access link sta in peer assoc rate set\n"); ++ return; ++ } ++ + band = def.chan->band; + sband = ar->ah->hw->wiphy->bands[band]; +- ratemask = sta->deflink.supp_rates[band]; ++ ratemask = link_sta->supp_rates[band]; + ratemask &= arvif->bitrate_mask.control[band].legacy; + rates = sband->bitrates; + +@@ -1862,9 +1882,18 @@ static void ath12k_peer_assoc_h_ht(struc + u8 link_id = arvif->link_id; + struct ath12k_sta *ahsta = arsta->ahsta; + struct ieee80211_sta *sta; ++ struct ieee80211_link_sta *link_sta; + + sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); +- ht_cap = &sta->deflink.ht_cap; ++ ++ link_sta = ath12k_get_link_sta(arsta); ++ ++ if (!link_sta) { ++ ath12k_warn(ar->ab, "unable to access link sta in peer assoc ht set\n"); ++ return; ++ } ++ ++ ht_cap = &link_sta->ht_cap; + + lockdep_assert_held(&ar->conf_mutex); + +@@ -1894,7 +1923,7 @@ static void ath12k_peer_assoc_h_ht(struc + if (ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING) + arg->ldpc_flag = true; + +- if (sta->deflink.bandwidth >= IEEE80211_STA_RX_BW_40) { ++ if (link_sta->bandwidth >= IEEE80211_STA_RX_BW_40) { + arg->bw_40 = true; + arg->peer_rate_caps |= WMI_HOST_RC_CW40_FLAG; + } +@@ -1952,7 +1981,7 @@ static void ath12k_peer_assoc_h_ht(struc + arg->peer_ht_rates.rates[i] = i; + } else { + arg->peer_ht_rates.num_rates = n; +- arg->peer_nss = min(sta->deflink.rx_nss, max_nss); ++ arg->peer_nss = min(link_sta->rx_nss, max_nss); + } + + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac ht peer %pM mcs cnt %d nss %d\n", +@@ -2067,12 +2096,20 @@ static void ath12k_peer_assoc_h_vht(stru + u8 link_id = arvif->link_id; + struct ath12k_sta *ahsta = arsta->ahsta; + struct ieee80211_sta *sta; ++ struct ieee80211_link_sta *link_sta; + + sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + +- vht_cap = &sta->deflink.vht_cap; +- if (WARN_ON(ath12k_mac_vif_chan(vif, &def, link_id))) ++ link_sta = ath12k_get_link_sta(arsta); ++ ++ if (!link_sta) { ++ ath12k_warn(ar->ab, "unable to access link sta in peer assoc vht set\n"); ++ return; ++ } ++ vht_cap = &link_sta->vht_cap; ++ if (WARN_ON(ath12k_mac_vif_chan(vif, &def, link_id))) { + return; ++ } + + if (!vht_cap->vht_supported) + return; +@@ -2106,17 +2143,17 @@ static void ath12k_peer_assoc_h_vht(stru + (1U << (IEEE80211_HT_MAX_AMPDU_FACTOR + + ampdu_factor)) - 1); + +- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80) ++ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80) + arg->bw_80 = true; + +- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) ++ 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 > sta->deflink.rx_nss) { ++ if (vht_nss > link_sta->rx_nss) { + user_rate_valid = false; +- for (nss_idx = sta->deflink.rx_nss - 1; nss_idx >= 0; nss_idx--) { ++ for (nss_idx = link_sta->rx_nss - 1; nss_idx >= 0; nss_idx--) { + if (vht_mcs_mask[nss_idx]) { + user_rate_valid = true; + break; +@@ -2127,8 +2164,8 @@ static void ath12k_peer_assoc_h_vht(stru + 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", +- sta->deflink.rx_nss, arsta->addr); +- vht_mcs_mask[sta->deflink.rx_nss - 1] = vht_mcs_mask[vht_nss - 1]; ++ 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 +@@ -2142,7 +2179,7 @@ static void ath12k_peer_assoc_h_vht(stru + vht_mcs_mask[i]) + max_nss = i + 1; + } +- arg->peer_nss = min(sta->deflink.rx_nss, max_nss); ++ arg->peer_nss = min(link_sta->rx_nss, max_nss); + arg->rx_max_rate = __le16_to_cpu(vht_cap->vht_mcs.rx_highest); + arg->rx_mcs_set = __le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map); + arg->tx_max_rate = __le16_to_cpu(vht_cap->vht_mcs.tx_highest); +@@ -2279,24 +2316,27 @@ static void ath12k_peer_assoc_h_he(struc + struct ath12k_sta *ahsta = arsta->ahsta; + struct ieee80211_sta *sta; + struct ieee80211_bss_conf* link_conf; ++ struct ieee80211_link_sta *link_sta; + u32 peer_he_ops; + +- rcu_read_lock(); +- + link_conf = ath12k_get_link_bss_conf(arvif); + + if (!link_conf) { +- rcu_read_unlock(); + ath12k_warn(ar->ab, "unable to access bss link conf in peer assoc\n"); + return; + } + +- peer_he_ops = link_conf->he_oper.params; ++ link_sta = ath12k_get_link_sta(arsta); + +- rcu_read_unlock(); ++ if (!link_sta) { ++ ath12k_warn(ar->ab, "unable to access link sta in peer assoc he set\n"); ++ return; ++ } ++ ++ peer_he_ops = link_conf->he_oper.params; + + sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); +- he_cap = &sta->deflink.he_cap; ++ he_cap = &link_sta->he_cap; + + if (WARN_ON(ath12k_mac_vif_chan(vif, &def, link_id))) + return; +@@ -2344,7 +2384,7 @@ static void ath12k_peer_assoc_h_he(struc + else + max_nss = rx_mcs_80; + +- arg->peer_nss = min(sta->deflink.rx_nss, max_nss); ++ arg->peer_nss = min(link_sta->rx_nss, max_nss); + + memcpy(&arg->peer_he_cap_macinfo, he_cap->he_cap_elem.mac_cap_info, + sizeof(arg->peer_he_cap_macinfo)); +@@ -2373,10 +2413,10 @@ static void ath12k_peer_assoc_h_he(struc + IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK; + + if (ampdu_factor) { +- if (sta->deflink.vht_cap.vht_supported) ++ if (link_sta->vht_cap.vht_supported) + arg->peer_max_mpdu = (1 << (IEEE80211_HE_VHT_MAX_AMPDU_FACTOR + + ampdu_factor)) - 1; +- else if (sta->deflink.ht_cap.ht_supported) ++ else if (link_sta->ht_cap.ht_supported) + arg->peer_max_mpdu = (1 << (IEEE80211_HE_HT_MAX_AMPDU_FACTOR + + ampdu_factor)) - 1; + } +@@ -2419,9 +2459,9 @@ static void ath12k_peer_assoc_h_he(struc + + he_nss = ath12k_mac_max_he_nss(he_mcs_mask); + +- if (he_nss > sta->deflink.rx_nss) { ++ if (he_nss > link_sta->rx_nss) { + user_rate_valid = false; +- for (nss_idx = sta->deflink.rx_nss - 1; nss_idx >= 0; nss_idx--) { ++ for (nss_idx = link_sta->rx_nss - 1; nss_idx >= 0; nss_idx--) { + if (he_mcs_mask[nss_idx]) { + user_rate_valid = true; + break; +@@ -2432,11 +2472,11 @@ static void ath12k_peer_assoc_h_he(struc + 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", +- sta->deflink.rx_nss, arsta->addr); +- he_mcs_mask[sta->deflink.rx_nss - 1] = he_mcs_mask[he_nss - 1]; ++ link_sta->rx_nss, arsta->addr); ++ he_mcs_mask[link_sta->rx_nss - 1] = he_mcs_mask[he_nss - 1]; + } + +- switch (sta->deflink.bandwidth) { ++ 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) { +@@ -2488,14 +2528,14 @@ static void ath12k_peer_assoc_h_he(struc + he_mcs_mask[i]) + max_nss = i + 1; + } +- arg->peer_nss = min(sta->deflink.rx_nss, max_nss); ++ arg->peer_nss = min(link_sta->rx_nss, max_nss); + + if (arg->peer_phymode == MODE_11AX_HE160 || + arg->peer_phymode == MODE_11AX_HE80_80) { + tx_nss = ath12k_get_nss_160mhz(ar, ar->num_tx_chains); + rx_nss = min(arg->peer_nss, tx_nss); + +- arg->peer_nss = min(sta->deflink.rx_nss, ar->num_rx_chains); ++ 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) { +@@ -2531,25 +2571,33 @@ static void ath12k_peer_assoc_h_he_6ghz( + u8 link_id = arvif->link_id; + struct ath12k_sta *ahsta = arsta->ahsta; + struct ieee80211_sta *sta; ++ struct ieee80211_link_sta *link_sta; + + sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); +- he_cap = &sta->deflink.he_cap; ++ ++ link_sta = ath12k_get_link_sta(arsta); ++ ++ if (!link_sta) { ++ ath12k_warn(ar->ab, "unable to access link sta in peer assoc he-6ghz set\n"); ++ return; ++ } ++ he_cap = &link_sta->he_cap; + + if (WARN_ON(ath12k_mac_vif_chan(vif, &def, link_id))) + return; + + band = def.chan->band; + +- if (!arg->he_flag || band != NL80211_BAND_6GHZ || !sta->deflink.he_6ghz_capa.capa) ++ if (!arg->he_flag || band != NL80211_BAND_6GHZ || !link_sta->he_6ghz_capa.capa) + return; + +- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80) ++ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80) + arg->bw_80 = true; + +- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) ++ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160) + arg->bw_160 = true; + +- arg->peer_he_caps_6ghz = le16_to_cpu(sta->deflink.he_6ghz_capa.capa); ++ arg->peer_he_caps_6ghz = le16_to_cpu(link_sta->he_6ghz_capa.capa); + arg->peer_mpdu_density = + ath12k_parse_mpdudensity(FIELD_GET(IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START, + arg->peer_he_caps_6ghz)); +@@ -2723,26 +2771,29 @@ static void ath12k_peer_assoc_h_eht(stru + struct ath12k_sta *ahsta = arsta->ahsta; + struct ieee80211_sta *sta; + struct ieee80211_bss_conf* link_conf; ++ struct ieee80211_link_sta *link_sta; + u32 peer_eht_ops; + +- rcu_read_lock(); +- + link_conf = ath12k_get_link_bss_conf(arvif); + + if (!link_conf) { +- rcu_read_unlock(); + ath12k_warn(ar->ab, "unable to access bss link conf in peer assoc\n"); + return; + } + ++ link_sta = ath12k_get_link_sta(arsta); ++ ++ if (!link_sta) { ++ ath12k_warn(ar->ab, "unable to access link sta in peer assoc eht set\n"); ++ return; ++ } ++ + memcpy(&peer_eht_ops, &link_conf->eht_oper, + sizeof(link_conf->eht_oper)); + +- rcu_read_unlock(); +- + sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + +- eht_cap = &sta->deflink.eht_cap; ++ eht_cap = &link_sta->eht_cap; + mcs_nss = &eht_cap->eht_mcs_nss_supp; + mcs_nss_supp_bw = &mcs_nss->bw._80; + +@@ -2755,11 +2806,11 @@ static void ath12k_peer_assoc_h_eht(stru + if (ath12k_peer_assoc_h_eht_masked(eht_mcs_mask)) + return; + +- if (!sta->deflink.he_cap.has_he || !eht_cap->has_eht) ++ if (!link_sta->he_cap.has_he || !eht_cap->has_eht) + return; + + arg->eht_flag = true; +- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_320) { ++ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_320) { + arg->bw_40 = true; + arg->bw_80 = true; + arg->bw_160 = true; +@@ -2778,9 +2829,9 @@ static void ath12k_peer_assoc_h_eht(stru + + eht_nss = ath12k_mac_max_eht_nss(eht_mcs_mask); + +- if (eht_nss > sta->deflink.rx_nss) { ++ if (eht_nss > link_sta->rx_nss) { + user_rate_valid = false; +- for (nss_idx = (sta->deflink.rx_nss - 1); nss_idx >= 0; nss_idx--) { ++ for (nss_idx = (link_sta->rx_nss - 1); nss_idx >= 0; nss_idx--) { + if (eht_mcs_mask[nss_idx]) { + user_rate_valid = true; + break; +@@ -2791,11 +2842,11 @@ static void ath12k_peer_assoc_h_eht(stru + if (!user_rate_valid) { + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, + "Setting eht range MCS value to peer supported nss:%d for peer %pM\n", +- sta->deflink.rx_nss, arsta->addr); +- eht_mcs_mask[sta->deflink.rx_nss - 1] = eht_mcs_mask[eht_nss - 1]; ++ link_sta->rx_nss, arsta->addr); ++ eht_mcs_mask[link_sta->rx_nss - 1] = eht_mcs_mask[eht_nss - 1]; + } + +- switch (sta->deflink.bandwidth) { ++ switch (link_sta->bandwidth) { + case IEEE80211_STA_RX_BW_320: + mcs_nss_supp_bw = &mcs_nss->bw._320; + mcs_idx = WMI_EHTCAP_TXRX_MCS_NSS_IDX_320; +@@ -2835,7 +2886,7 @@ static void ath12k_peer_assoc_h_eht(stru + break; + } + +- if (!(sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] & ++ if (!(link_sta->he_cap.he_cap_elem.phy_cap_info[0] & + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK_ALL)) { + if (mcs_nss->only_20mhz.rx_tx_mcs13_max_nss) + max_nss = mcs_nss->only_20mhz.rx_tx_mcs13_max_nss; +@@ -2856,10 +2907,10 @@ static void ath12k_peer_assoc_h_eht(stru + + max_nss = max(max_nss, (uint8_t)eht_nss); + +- arg->peer_nss = min(sta->deflink.rx_nss, max_nss); ++ arg->peer_nss = min(link_sta->rx_nss, max_nss); + arg->ru_punct_bitmap = ~def.ru_punct_bitmap; +- if (ieee80211_vif_is_mesh(vif) && sta->deflink.ru_punct_bitmap) +- arg->ru_punct_bitmap = ~sta->deflink.ru_punct_bitmap; ++ if (ieee80211_vif_is_mesh(vif) && link_sta->ru_punct_bitmap) ++ arg->ru_punct_bitmap = ~link_sta->ru_punct_bitmap; + + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, + "mac he peer %pM nss %d mcs cnt %d ru_punct_bitmap 0x%x\n", +@@ -2873,11 +2924,21 @@ static void ath12k_peer_assoc_h_smps(str + int smps; + struct ath12k_sta *ahsta = arsta->ahsta; + struct ieee80211_sta *sta; ++ struct ieee80211_link_sta *link_sta; ++ struct ath12k *ar = arsta->arvif->ar; + + sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); +- ht_cap = &sta->deflink.ht_cap; + +- if (!ht_cap->ht_supported && !sta->deflink.he_6ghz_capa.capa) ++ link_sta = ath12k_get_link_sta(arsta); ++ ++ if (!link_sta) { ++ ath12k_warn(ar->ab, "unable to access link sta in peer assoc smps set\n"); ++ return; ++ } ++ ++ ht_cap = &link_sta->ht_cap; ++ ++ if (!ht_cap->ht_supported && !link_sta->he_6ghz_capa.capa) + return; + + if (ht_cap->ht_supported) { +@@ -2885,7 +2946,7 @@ static void ath12k_peer_assoc_h_smps(str + smps >>= IEEE80211_HT_CAP_SM_PS_SHIFT; + } else { + smps = FIELD_GET(IEEE80211_HE_6GHZ_CAP_SM_PS, +- le16_to_cpu(sta->deflink.he_6ghz_capa.capa)); ++ le16_to_cpu(link_sta->he_6ghz_capa.capa)); + } + + switch (smps) { +@@ -3061,21 +3122,25 @@ static bool ath12k_mac_sta_has_ofdm_only + { + struct ath12k_sta *ahsta = arsta->ahsta; + struct ieee80211_sta *sta; ++ struct ieee80211_link_sta *link_sta; ++ struct ath12k *ar = arsta->arvif->ar; + + sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); +- return sta->deflink.supp_rates[NL80211_BAND_2GHZ] >> ++ ++ link_sta = ath12k_get_link_sta(arsta); ++ ++ if (!link_sta) { ++ ath12k_warn(ar->ab, "unable to access link sta in ofdm rate check\n"); ++ return false; ++ } ++ return link_sta->supp_rates[NL80211_BAND_2GHZ] >> + ATH12K_MAC_FIRST_OFDM_RATE_IDX; + } + +-static enum wmi_phy_mode ath12k_mac_get_phymode_vht(struct ath12k *ar, +- struct ath12k_link_sta *arsta) ++static enum wmi_phy_mode ath12k_mac_get_phymode_vht(struct ieee80211_link_sta *link_sta) + { +- struct ath12k_sta *ahsta = arsta->ahsta; +- struct ieee80211_sta *sta; +- +- sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); +- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) { +- switch (sta->deflink.vht_cap.cap & ++ 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: + return MODE_11AC_VHT160; +@@ -3087,77 +3152,67 @@ static enum wmi_phy_mode ath12k_mac_get_ + } + } + +- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80) ++ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80) + return MODE_11AC_VHT80; + +- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40) ++ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_40) + return MODE_11AC_VHT40; + +- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20) ++ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_20) + return MODE_11AC_VHT20; + + return MODE_UNKNOWN; + } + +-static enum wmi_phy_mode ath12k_mac_get_phymode_he(struct ath12k *ar, +- struct ath12k_link_sta *arsta) ++static enum wmi_phy_mode ath12k_mac_get_phymode_he(struct ieee80211_link_sta *link_sta) + { +- struct ath12k_sta *ahsta = arsta->ahsta; +- struct ieee80211_sta *sta; +- +- sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); +- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) { +- if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] & ++ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160) { ++ 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 (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] & ++ 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; + } + +- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80) ++ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80) + return MODE_11AX_HE80; + +- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40) ++ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_40) + return MODE_11AX_HE40; + +- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20) ++ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_20) + return MODE_11AX_HE20; + + return MODE_UNKNOWN; + } + +-static enum wmi_phy_mode ath12k_mac_get_phymode_eht(struct ath12k *ar, +- struct ath12k_link_sta *arsta) ++static enum wmi_phy_mode ath12k_mac_get_phymode_eht(struct ieee80211_link_sta *link_sta) + { +- struct ath12k_sta *ahsta = arsta->ahsta; +- struct ieee80211_sta *sta; +- +- sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); +- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_320) +- if (sta->deflink.eht_cap.eht_cap_elem.phy_cap_info[0] & ++ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_320) ++ if (link_sta->eht_cap.eht_cap_elem.phy_cap_info[0] & + IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ) + return MODE_11BE_EHT320; +- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) { +- if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] & ++ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160) { ++ if (link_sta->he_cap.he_cap_elem.phy_cap_info[0] & + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G) + return MODE_11BE_EHT160; +- else if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] & ++ 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_11BE_EHT80_80; + /* not sure if this is a valid case? */ + return MODE_11BE_EHT160; + } + +- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80) ++ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80) + return MODE_11BE_EHT80; + +- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40) ++ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_40) + return MODE_11BE_EHT40; + +- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20) ++ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_20) + return MODE_11BE_EHT20; + + return MODE_UNKNOWN; +@@ -3179,12 +3234,20 @@ static void ath12k_peer_assoc_h_phymode( + u8 link_id = arvif->link_id; + struct ath12k_sta *ahsta = arsta->ahsta; + struct ieee80211_sta *sta; ++ struct ieee80211_link_sta *link_sta; + + sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + + if (WARN_ON(ath12k_mac_vif_chan(vif, &def, link_id))) + return; + ++ link_sta = ath12k_get_link_sta(arsta); ++ ++ if (!link_sta) { ++ ath12k_warn(ar->ab, "unable to access link sta in peer assoc phymode set\n"); ++ return; ++ } ++ + band = def.chan->band; + ht_mcs_mask = arvif->bitrate_mask.control[band].ht_mcs; + vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs; +@@ -3193,29 +3256,29 @@ static void ath12k_peer_assoc_h_phymode( + + switch (band) { + case NL80211_BAND_2GHZ: +- if (sta->deflink.eht_cap.has_eht && ++ if (link_sta->eht_cap.has_eht && + !ath12k_peer_assoc_h_eht_masked(eht_mcs_mask)) { +- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40) ++ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_40) + phymode = MODE_11BE_EHT40_2G; + else + phymode = MODE_11BE_EHT20_2G; +- } else if (sta->deflink.he_cap.has_he && ++ } else if (link_sta->he_cap.has_he && + !ath12k_peer_assoc_h_he_masked(he_mcs_mask)) { +- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80) ++ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80) + phymode = MODE_11AX_HE80_2G; +- else if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40) ++ else if (link_sta->bandwidth == IEEE80211_STA_RX_BW_40) + phymode = MODE_11AX_HE40_2G; + else + phymode = MODE_11AX_HE20_2G; +- } else if (sta->deflink.vht_cap.vht_supported && ++ } else if (link_sta->vht_cap.vht_supported && + !ath12k_peer_assoc_h_vht_masked(vht_mcs_mask)) { +- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40) ++ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_40) + phymode = MODE_11AC_VHT40; + else + phymode = MODE_11AC_VHT20; +- } else if (sta->deflink.ht_cap.ht_supported && ++ } else if (link_sta->ht_cap.ht_supported && + !ath12k_peer_assoc_h_ht_masked(ht_mcs_mask)) { +- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40) ++ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_40) + phymode = MODE_11NG_HT40; + else + phymode = MODE_11NG_HT20; +@@ -3228,18 +3291,18 @@ static void ath12k_peer_assoc_h_phymode( + case NL80211_BAND_5GHZ: + case NL80211_BAND_6GHZ: + /* Check EHT first */ +- if (sta->deflink.eht_cap.has_eht && ++ if (link_sta->eht_cap.has_eht && + !ath12k_peer_assoc_h_eht_masked(eht_mcs_mask)) { +- phymode = ath12k_mac_get_phymode_eht(ar, arsta); +- } else if (sta->deflink.he_cap.has_he && ++ phymode = ath12k_mac_get_phymode_eht(link_sta); ++ } else if (link_sta->he_cap.has_he && + !ath12k_peer_assoc_h_he_masked(he_mcs_mask)) { +- phymode = ath12k_mac_get_phymode_he(ar, arsta); +- } else if (sta->deflink.vht_cap.vht_supported && ++ phymode = ath12k_mac_get_phymode_he(link_sta); ++ } else if (link_sta->vht_cap.vht_supported && + !ath12k_peer_assoc_h_vht_masked(vht_mcs_mask)) { +- phymode = ath12k_mac_get_phymode_vht(ar, arsta); +- } else if (sta->deflink.ht_cap.ht_supported && ++ phymode = ath12k_mac_get_phymode_vht(link_sta); ++ } else if (link_sta->ht_cap.ht_supported && + !ath12k_peer_assoc_h_ht_masked(ht_mcs_mask)) { +- if (sta->deflink.bandwidth >= IEEE80211_STA_RX_BW_40) ++ if (link_sta->bandwidth >= IEEE80211_STA_RX_BW_40) + phymode = MODE_11NA_HT40; + else + phymode = MODE_11NA_HT20; +@@ -3271,6 +3334,7 @@ static void ath12k_peer_assoc_prepare(st + reinit_completion(&ar->peer_assoc_done); + + arg->peer_new_assoc = !reassoc; ++ + ath12k_peer_assoc_h_basic(ar, arvif, arsta, arg); + ath12k_peer_assoc_h_crypto(ar, arvif, arsta, arg); + ath12k_peer_assoc_h_rates(ar, arvif, arsta, arg); +@@ -5504,6 +5568,11 @@ static int ath12k_station_assoc(struct a + struct cfg80211_bitrate_mask *mask; + u8 num_vht_rates, num_he_rates, num_eht_rates, num_ht_rates; + u8 link_id = arvif->link_id; ++ bool ht_supp, vht_supp, has_he, has_eht; ++ struct ieee80211_sta_ht_cap ht_cap; ++ enum ieee80211_sta_rx_bandwidth bandwidth; ++ u16 he_6ghz_capa; ++ + + lockdep_assert_held(&ar->conf_mutex); + +@@ -5524,8 +5593,31 @@ static int ath12k_station_assoc(struct a + ahsta = (struct ath12k_sta *)sta->drv_priv; + arsta = ahsta->link[link_id]; + ++ if (WARN_ON(!arsta)) ++ return -EINVAL; ++ ++ rcu_read_lock(); ++ ++ link_sta = ath12k_get_link_sta(arsta); ++ ++ if (!link_sta) { ++ rcu_read_unlock(); ++ ath12k_warn(ar->ab, "unable to access link sta in station assoc\n"); ++ return -EINVAL; ++ } ++ ++ he_6ghz_capa = le16_to_cpu(link_sta->he_6ghz_capa.capa); ++ bandwidth = link_sta->bandwidth; ++ ht_cap = link_sta->ht_cap; ++ ht_supp = link_sta->ht_cap.ht_supported; ++ vht_supp = link_sta->vht_cap.vht_supported; ++ has_he = link_sta->he_cap.has_he; ++ has_eht = link_sta->eht_cap.has_eht; ++ bandwidth = link_sta->bandwidth; ++ + ath12k_peer_assoc_prepare(ar, arvif, arsta, &peer_arg, reassoc); + ++ rcu_read_unlock(); + peer_arg.is_assoc = true; + ret = ath12k_wmi_send_peer_assoc_cmd(ar, &peer_arg); + if (ret) { +@@ -5550,22 +5642,22 @@ static int ath12k_station_assoc(struct a + * specific fixed param. + * Note that all other rates and NSS will be disabled for this peer. + */ +- if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) { ++ if (vht_supp && num_vht_rates == 1) { + ret = ath12k_mac_set_peer_vht_fixed_rate(arvif, arsta, mask, + band); + if (ret) + return ret; +- } else if (sta->deflink.he_cap.has_he && num_he_rates == 1) { ++ } else if (has_he && num_he_rates == 1) { + ret = ath12k_mac_set_peer_he_fixed_rate(arvif, arsta, mask, + band); + if (ret) + return ret; +- } else if (sta->deflink.eht_cap.has_eht && num_eht_rates == 1) { ++ } else if (has_eht && num_eht_rates == 1) { + ret = ath12k_mac_set_peer_eht_fixed_rate(arvif, arsta, mask, + band); + if (ret) + return ret; +- } else if (sta->deflink.ht_cap.ht_supported && num_ht_rates == 1) { ++ } else if (ht_supp && num_ht_rates == 1) { + ret = ath12k_mac_set_peer_ht_fixed_rate(arvif, arsta, mask, + band); + if (ret) +@@ -5579,8 +5671,8 @@ static int ath12k_station_assoc(struct a + return 0; + + ret = ath12k_setup_peer_smps(ar, arvif, arsta->addr, +- &sta->deflink.ht_cap, +- le16_to_cpu(sta->deflink.he_6ghz_capa.capa)); ++ &ht_cap, ++ he_6ghz_capa); + if (ret) { + ath12k_warn(ar->ab, "failed to setup peer SMPS for vdev %d: %d\n", + arvif->vdev_id, ret); +@@ -5606,15 +5698,8 @@ static int ath12k_station_assoc(struct a + spin_lock_bh(&ar->data_lock); + + /* Set arsta bw and prev bw */ +- rcu_read_lock(); +- link_sta = rcu_dereference(sta->link[link_id]); +- if (link_sta) { +- arsta->bw = link_sta->bandwidth; +- arsta->bw_prev = link_sta->bandwidth; +- } else { +- ath12k_warn(ar->ab, "failed to get link sta to store bw"); +- } +- rcu_read_unlock(); ++ arsta->bw = bandwidth; ++ arsta->bw_prev = bandwidth; + + spin_unlock_bh(&ar->data_lock); + diff --git a/feeds/ipq95xx/mac80211/patches/qca/689-04-ath12k-use-link-for-ampdu-actions.patch b/feeds/ipq95xx/mac80211/patches/qca/689-04-ath12k-use-link-for-ampdu-actions.patch new file mode 100644 index 000000000..3e2ad7d7b --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/689-04-ath12k-use-link-for-ampdu-actions.patch @@ -0,0 +1,282 @@ +From 730447816c719660905e4b4d298139ef17663787 Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Sat, 26 Nov 2022 07:41:45 +0530 +Subject: [PATCH] ath12: extend link based operations for ampdu actions and wmi + mgmt + +Apply tid queue setup based on link id on receiving ampdu action +params. + +Also ensure right link vif is used for wmi based mgmt tx. + +Signed-off-by: Sriram R +--- + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/dp_rx.c | 32 ++++++++---- + drivers/net/wireless/ath/ath12k/dp_rx.h | 6 ++- + drivers/net/wireless/ath/ath12k/mac.c | 69 +++++++++++++++++++------ + 4 files changed, 81 insertions(+), 27 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -110,6 +110,7 @@ struct ath12k_skb_cb { + struct ath12k *ar; + struct ieee80211_vif *vif; + dma_addr_t paddr_ext_desc; ++ u8 link_id; + } __packed; + + struct ath12k_skb_rxcb { +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -1116,16 +1116,23 @@ err_mem_free: + } + + int ath12k_dp_rx_ampdu_start(struct ath12k *ar, +- struct ieee80211_ampdu_params *params) ++ struct ieee80211_ampdu_params *params, ++ u8 link_id) + { + struct ath12k_base *ab = ar->ab; + struct ath12k_sta *ahsta = (void *)params->sta->drv_priv; +- struct ath12k_link_sta *arsta = &ahsta->deflink; +- int vdev_id = arsta->arvif->vdev_id; ++ struct ath12k_link_sta *arsta; ++ int vdev_id; + int ret; + +- /* TODO Handle per link in ath12k_mac_op_ampdu_action() for ML STA */ +- ret = ath12k_dp_rx_peer_tid_setup(ar, params->sta->addr, vdev_id, ++ arsta = ahsta->link[link_id]; ++ ++ if (!arsta) ++ return -ENOENT; ++ ++ vdev_id = arsta->arvif->vdev_id; ++ ++ ret = ath12k_dp_rx_peer_tid_setup(ar, arsta->addr, vdev_id, + params->tid, params->buf_size, + params->ssn, ahsta->pn_type); + if (ret) +@@ -1135,19 +1142,26 @@ int ath12k_dp_rx_ampdu_start(struct ath1 + } + + int ath12k_dp_rx_ampdu_stop(struct ath12k *ar, +- struct ieee80211_ampdu_params *params) ++ struct ieee80211_ampdu_params *params, ++ u8 link_id) + { + struct ath12k_base *ab = ar->ab; + struct ath12k_peer *peer; + struct ath12k_sta *ahsta = (void *)params->sta->drv_priv; +- struct ath12k_link_sta *arsta = &ahsta->deflink; +- int vdev_id = arsta->arvif->vdev_id; ++ struct ath12k_link_sta *arsta; ++ int vdev_id; + bool active; + int ret; + ++ arsta = ahsta->link[link_id]; ++ ++ if (!arsta) ++ return -ENOENT; ++ ++ vdev_id = arsta->arvif->vdev_id; + spin_lock_bh(&ab->base_lock); + +- peer = ath12k_peer_find(ab, vdev_id, params->sta->addr); ++ peer = ath12k_peer_find(ab, vdev_id, arsta->addr); + if (!peer) { + ath12k_warn(ab, "failed to find the peer to stop rx aggregation\n"); + spin_unlock_bh(&ab->base_lock); +--- a/drivers/net/wireless/ath/ath12k/dp_rx.h ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.h +@@ -85,9 +85,11 @@ static inline u32 ath12k_he_gi_to_nl8021 + } + + int ath12k_dp_rx_ampdu_start(struct ath12k *ar, +- struct ieee80211_ampdu_params *params); ++ struct ieee80211_ampdu_params *params, ++ u8 link_id); + int ath12k_dp_rx_ampdu_stop(struct ath12k *ar, +- struct ieee80211_ampdu_params *params); ++ struct ieee80211_ampdu_params *params, ++ u8 link_id); + int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_link_vif *arvif, + const u8 *peer_addr, + enum set_key_cmd key_cmd, +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -7889,7 +7889,9 @@ static void ath12k_mgmt_over_wmi_tx_work + struct ath12k_link_vif *arvif; + struct sk_buff *skb; + int ret; ++ struct ath12k_hw *ah = ar->ah; + ++ mutex_lock(&ah->conf_mutex); + while ((skb = skb_dequeue(&ar->wmi_mgmt_tx_queue)) != NULL) { + skb_cb = ATH12K_SKB_CB(skb); + if (!skb_cb->vif) { +@@ -7899,8 +7901,23 @@ static void ath12k_mgmt_over_wmi_tx_work + } + + ahvif = ath12k_vif_to_ahvif(skb_cb->vif); +- /* TODO check this for extending link specific */ +- arvif = &ahvif->deflink; ++ if (!(ahvif->links_map & BIT(skb_cb->link_id))) { ++ ath12k_warn(ar->ab, ++ "invalid linkid 0x%X in mgmt over wmi tx with linkmap 0x%X\n", ++ skb_cb->link_id, ++ ahvif->links_map); ++ ath12k_mgmt_over_wmi_tx_drop(ar, skb); ++ continue; ++ } ++ ++ arvif = ahvif->link[skb_cb->link_id]; ++ if (!arvif) { ++ ath12k_warn(ar->ab, "invalid arvif for mgmt tx - link %d\n", ++ skb_cb->link_id); ++ ath12k_mgmt_over_wmi_tx_drop(ar, skb); ++ continue; ++ } ++ + mutex_lock(&ar->conf_mutex); + if (ar->allocated_vdev_map & (1LL << arvif->vdev_id) && + arvif->is_started) { +@@ -7916,13 +7933,15 @@ static void ath12k_mgmt_over_wmi_tx_work + } + } else { + ath12k_warn(ar->ab, +- "dropping mgmt frame for vdev %d, is_started %d\n", ++ "dropping mgmt frame for vdev %d, is_started %d link %d\n", + arvif->vdev_id, +- arvif->is_started); ++ arvif->is_started, ++ skb_cb->link_id); + ath12k_mgmt_over_wmi_tx_drop(ar, skb); + } + mutex_unlock(&ar->conf_mutex); + } ++ mutex_unlock(&ah->conf_mutex); + } + + static int ath12k_mac_mgmt_tx(struct ath12k *ar, struct sk_buff *skb, +@@ -8065,18 +8084,22 @@ static void ath12k_mac_op_tx(struct ieee + ieee80211_free_txskb(hw, skb); + return; + } +- if (WARN_ON(!ahvif->link[link])) { +- ieee80211_free_txskb(hw, skb); +- return; +- } +- arvif = ahvif->link[link]; +- ar = arvif->ar; ++ } else { ++ link = 0; ++ } ++ ++ arvif = ahvif->link[link]; ++ ++ if (!arvif || !arvif->ar) { ++ ieee80211_free_txskb(hw, skb); ++ return; + } + ++ ar = arvif->ar; + ah = ar->ah; + + if (unlikely(test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))) { +- ieee80211_free_txskb(ar->ah->hw, skb); ++ ieee80211_free_txskb(ah->hw, skb); + return; + } + +@@ -8090,6 +8113,7 @@ static void ath12k_mac_op_tx(struct ieee + } else if (ieee80211_is_mgmt(hdr->frame_control)) { + frm_type = FIELD_GET(IEEE80211_FCTL_STYPE, hdr->frame_control); + is_prb_rsp = ieee80211_is_probe_resp(hdr->frame_control); ++ skb_cb->link_id = link; + ret = ath12k_mac_mgmt_tx(ar, skb, is_prb_rsp); + if (ret) { + if (ret != -EBUSY) +@@ -9428,24 +9452,20 @@ static int ath12k_mac_op_set_antenna(str + return ret; + } + +-static int ath12k_mac_op_ampdu_action(struct ieee80211_hw *hw, +- struct ieee80211_vif *vif, +- struct ieee80211_ampdu_params *params) ++static int ath12k_mac_ampdu_action(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_ampdu_params *params, ++ u8 link_id) + { + struct ath12k_hw *ah = hw->priv; + struct ath12k *ar; + int ret = -EINVAL; + +- /* TODO handle for ML link vifs */ +- if (vif->valid_links) +- return 0; +- +- mutex_lock(&ah->conf_mutex); ++ lockdep_assert_held(&ah->conf_mutex); + +- ar = ath12k_get_ar_by_vif(hw, vif, 0); ++ ar = ath12k_get_ar_by_vif(hw, vif, link_id); + if (!ar) { + ath12k_err(NULL, "unable to determine device to set ampdu params\n"); +- mutex_unlock(&ah->conf_mutex); + return -EPERM; + } + +@@ -9453,10 +9473,10 @@ static int ath12k_mac_op_ampdu_action(st + + switch (params->action) { + case IEEE80211_AMPDU_RX_START: +- ret = ath12k_dp_rx_ampdu_start(ar, params); ++ ret = ath12k_dp_rx_ampdu_start(ar, params, link_id); + break; + case IEEE80211_AMPDU_RX_STOP: +- ret = ath12k_dp_rx_ampdu_stop(ar, params); ++ ret = ath12k_dp_rx_ampdu_stop(ar, params, link_id); + break; + case IEEE80211_AMPDU_TX_START: + case IEEE80211_AMPDU_TX_STOP_CONT: +@@ -9470,7 +9490,36 @@ static int ath12k_mac_op_ampdu_action(st + break; + } + ++ if (ret) ++ ath12k_warn(ar->ab, "unable to perform ampdu action %d ret %d\n", ++ params->action, ret); ++ + mutex_unlock(&ar->conf_mutex); ++ ++ return ret; ++} ++ ++static int ath12k_mac_op_ampdu_action(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_ampdu_params *params) ++{ ++ struct ieee80211_sta *sta = params->sta; ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_hw *ah = hw->priv; ++ int ret = -EINVAL; ++ u8 link_id; ++ ++ if (WARN_ON(!ahsta->links_map)) ++ return -EINVAL; ++ ++ mutex_lock(&ah->conf_mutex); ++ ++ for_each_set_bit(link_id, &ahsta->links_map, IEEE80211_MLD_MAX_NUM_LINKS) { ++ ret = ath12k_mac_ampdu_action(hw, vif, params, link_id); ++ if (ret) ++ break; ++ } ++ + mutex_unlock(&ah->conf_mutex); + + return ret; diff --git a/feeds/ipq95xx/mac80211/patches/qca/689-05-mac80211-Fix-address-translation-for-multiple-bss-ca.patch b/feeds/ipq95xx/mac80211/patches/qca/689-05-mac80211-Fix-address-translation-for-multiple-bss-ca.patch new file mode 100644 index 000000000..c8d852db9 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/689-05-mac80211-Fix-address-translation-for-multiple-bss-ca.patch @@ -0,0 +1,36 @@ +From cef13df873788d08a1f975df20332bf0d863d173 Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Mon, 28 Nov 2022 17:47:17 +0530 +Subject: [PATCH] mac80211: Fix address translation for multiple bss case + +When multiple interfaces are present in the local interface +list, new skb copy is taken before rx processing except for +the first interface. The address translation happens each +time only on the original skb since the hdr pointer is not +updated properly to the newly created skb. + +As a result frames start to drop in userspace when address +based checks or search fails. + +Signed-off-by: Sriram R +--- + net/mac80211/rx.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 8dcd67d..3206b42 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -5072,6 +5072,9 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx, + */ + shwt = skb_hwtstamps(rx->skb); + shwt->hwtstamp = skb_hwtstamps(skb)->hwtstamp; ++ ++ /* Update the hdr pointer to the new skb for translation below */ ++ hdr = (struct ieee80211_hdr *)rx->skb->data; + } + + if (unlikely(link_sta)) { +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/689-ath12k-update-CSA-counter-in-probe-resp.patch b/feeds/ipq95xx/mac80211/patches/qca/689-ath12k-update-CSA-counter-in-probe-resp.patch new file mode 100644 index 000000000..6762c9ba5 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/689-ath12k-update-CSA-counter-in-probe-resp.patch @@ -0,0 +1,62 @@ +From 293f928bb2139bdb6fdb5aca2630b60ba5e33591 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Thu, 24 Nov 2022 14:07:16 +0530 +Subject: [PATCH] ath12k: update CSA counter in probe response + frames + +Currently, driver only asks Channel Switch (CS) count event +from firmware during Channel Switch Annoucnement (CSA) when +the count goes to zero. But since probe response is handled +in upper layer, and driver is not updating the counter, +the CS count present in probe response frames doesn't change +during the whole CSA time. + +Fix this by asking CS count event from firmware for every count +and then accordingly decrementing the count in mac80211. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath12k/wmi.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c +index 44c8de9..e9f6158 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -1859,6 +1859,7 @@ int ath12k_wmi_bcn_tmpl(struct ath12k *ar, u32 vdev_id, + cmd->tim_ie_offset = cpu_to_le32(offs->tim_offset); + cmd->csa_switch_count_offset = cpu_to_le32(offs->cntdwn_counter_offs[0]); + cmd->ext_csa_switch_count_offset = cpu_to_le32(offs->cntdwn_counter_offs[1]); ++ cmd->csa_event_bitmap = cpu_to_le32(0xFFFFFFFF); + cmd->buf_len = cpu_to_le32(bcn->len); + cmd->mbssid_ie_offset = cpu_to_le32(offs->mbssid_off); + cmd->ema_params = cpu_to_le32(ema_params); +@@ -8017,10 +8018,6 @@ ath12k_wmi_process_csa_switch_count_event(struct ath12k_base *ab, + struct ath12k_link_vif *arvif; + struct ieee80211_bss_conf *link_conf; + +- /* Finish CSA once the switch count becomes NULL */ +- if (ev->current_switch_count) +- return; +- + rcu_read_lock(); + for (i = 0; i < ev->num_vdevs; i++) { + arvif = ath12k_mac_get_arvif_by_vdev_id(ab, vdev_ids[i]); +@@ -8036,8 +8033,12 @@ ath12k_wmi_process_csa_switch_count_event(struct ath12k_base *ab, + continue; + + /* FIXME some changes are expected for ML vifs */ +- if (arvif->is_up && link_conf->csa_active) +- ieee80211_csa_finish(arvif->ahvif->vif); ++ if (arvif->is_up && link_conf->csa_active) { ++ if (!ev->current_switch_count) ++ ieee80211_csa_finish(arvif->ahvif->vif); ++ else if (ev->current_switch_count > 1) ++ ieee80211_beacon_update_cntdwn(arvif->ahvif->vif); ++ } + } + rcu_read_unlock(); + } +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/689-wifi-ath12k-Fix-pci-register-read-write.patch b/feeds/ipq95xx/mac80211/patches/qca/689-wifi-ath12k-Fix-pci-register-read-write.patch new file mode 100644 index 000000000..8cec9aa23 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/689-wifi-ath12k-Fix-pci-register-read-write.patch @@ -0,0 +1,90 @@ +From 1540c9712699220722a08b1a9ad23912b6c2a686 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Fri, 11 Nov 2022 16:10:40 +0530 +Subject: [PATCH] wifi: ath12k: Fix pci register read/write + +Optimise the regsiter read/write + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/pci.c | 32 +++++---------------------- + 1 file changed, 6 insertions(+), 26 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c +index 45e4bd88c085..c2f4ef264271 100644 +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -184,12 +184,6 @@ static u32 ath12k_pci_get_window_start(struct ath12k_base *ab, + /* If offset lies within CE register range, use 2nd window */ + else if ((offset ^ HAL_CE_WFSS_CE_REG_BASE) < WINDOW_RANGE_MASK) + window_start = 2 * WINDOW_START; +- /* If offset lies within PCI_BAR_WINDOW0_BASE and within PCI_SOC_PCI_REG_BASE +- * use 0th window +- */ +- else if (((offset ^ PCI_BAR_WINDOW0_BASE) < WINDOW_RANGE_MASK) && +- !((offset ^ PCI_SOC_PCI_REG_BASE) < PCI_SOC_RANGE_MASK)) +- window_start = 0; + else + window_start = WINDOW_START; + +@@ -1105,13 +1099,11 @@ u32 ath12k_pci_read32(struct ath12k_base *ab, u32 offset) + + is_window0 = ((offset >= PCI_BAR_WINDOW0_BASE && + offset <= PCI_BAR_WINDOW0_END) && +- !(offset >= PCI_SOC_PCI_REG_BASE && +- offset <= PCI_PARF_END)); ++ (offset >= PCI_MHIREGLEN_REG && ++ offset <= PCI_MHI_REGION_END)); + + if (is_window0) { +- if (offset >= PCI_MHIREGLEN_REG && +- offset <= PCI_MHI_REGION_END) +- offset = offset - PCI_MHIREGLEN_REG; ++ offset = offset - PCI_MHIREGLEN_REG; + + val = ioread32(ab->mem + (offset & WINDOW_RANGE_MASK)); + +@@ -1121,11 +1113,6 @@ u32 ath12k_pci_read32(struct ath12k_base *ab, u32 offset) + } + spin_unlock_bh(&ab_pci->window_lock); + } else { +- if ((!window_start) && +- (offset >= PCI_MHIREGLEN_REG && +- offset <= PCI_MHI_REGION_END)) +- offset = offset - PCI_MHIREGLEN_REG; +- + val = ioread32(ab->mem + window_start + + (offset & WINDOW_RANGE_MASK)); + } +@@ -1165,13 +1152,11 @@ void ath12k_pci_write32(struct ath12k_base *ab, u32 offset, u32 value) + + is_window0 = ((offset >= PCI_BAR_WINDOW0_BASE && + offset <= PCI_BAR_WINDOW0_END) && +- !(offset >= PCI_SOC_PCI_REG_BASE && +- offset <= PCI_PARF_END)); ++ (offset >= PCI_MHIREGLEN_REG && ++ offset <= PCI_MHI_REGION_END)); + + if (is_window0) { +- if (offset >= PCI_MHIREGLEN_REG && +- offset <= PCI_MHI_REGION_END) +- offset = offset - PCI_MHIREGLEN_REG; ++ offset = offset - PCI_MHIREGLEN_REG; + + iowrite32(value, ab->mem + + (offset & WINDOW_RANGE_MASK)); +@@ -1181,11 +1166,6 @@ void ath12k_pci_write32(struct ath12k_base *ab, u32 offset, u32 value) + } + spin_unlock_bh(&ab_pci->window_lock); + } else { +- if ((!window_start) && +- (offset >= PCI_MHIREGLEN_REG && +- offset <= PCI_MHI_REGION_END)) +- offset = offset - PCI_MHIREGLEN_REG; +- + iowrite32(value, ab->mem + window_start + + (offset & WINDOW_RANGE_MASK)); + } +-- +2.37.0 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/690-0001-ath12k-refactor-vdev-configuration-related-functions.patch b/feeds/ipq95xx/mac80211/patches/qca/690-0001-ath12k-refactor-vdev-configuration-related-functions.patch new file mode 100644 index 000000000..bf64b3e2f --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/690-0001-ath12k-refactor-vdev-configuration-related-functions.patch @@ -0,0 +1,293 @@ +From 70ab6ca18864d0511e2f6cf3039c9160e592d8df Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Tue, 29 Nov 2022 16:12:26 +0530 +Subject: [PATCH 1/2] ath12k: refactor vdev configuration related functions + +During vdev start_restart, currently, there are operations +which needs to performed even if multi-vdev restart +optimization is in place. For example, after starting the +vdev, setting the Tx beamforming and setting non-HT duplicate +configruation for vdev. + +Similarly, after channel update, restarting the internal monitor +vdev and handling AWGN related data. + +Refactor below functions so that they can be used even when +optimization is also there + - ath12k_mac_vdev_start_restart() + - ath12k_mac_update_vif_chan() + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath12k/mac.c | 209 +++++++++++++++----------- + 1 file changed, 125 insertions(+), 84 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -9668,6 +9668,55 @@ ath12k_mac_mlo_get_vdev_args(struct ath1 + } + + static int ++ath12k_mac_vdev_config_after_start(struct ath12k_link_vif *arvif, ++ const struct cfg80211_chan_def *chandef) ++{ ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ath12k *ar = arvif->ar; ++ struct ath12k_base *ab = ar->ab; ++ int ret; ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ if (ar->supports_6ghz && ++ chandef->chan->band == NL80211_BAND_6GHZ && ++ (ahvif->vdev_type == WMI_VDEV_TYPE_STA || ahvif->vdev_type == WMI_VDEV_TYPE_AP) && ++ test_bit(WMI_TLV_SERVICE_EXT_TPC_REG_SUPPORT, ar->ab->wmi_ab.svc_map)) { ++ ath12k_mac_fill_reg_tpc_info(ar, arvif, &arvif->chanctx); ++ ath12k_wmi_send_vdev_set_tpc_power(ar, arvif->vdev_id, ++ &arvif->reg_tpc_info); ++ } ++ ++ /* Enable CAC Flag in the driver by checking the channel DFS cac time, ++ * i.e dfs_cac_ms value which will be valid only for radar channels ++ * and state as NL80211_DFS_USABLE which indicates CAC needs to be ++ * done before channel usage. This flags is used to drop rx packets. ++ * during CAC. ++ */ ++ /* TODO Set the flag for other interface types as required */ ++ if (ahvif->vdev_type == WMI_VDEV_TYPE_AP && ++ chandef->chan->dfs_cac_ms && ++ chandef->chan->dfs_state == NL80211_DFS_USABLE) { ++ set_bit(ATH12K_CAC_RUNNING, &ar->dev_flags); ++ ath12k_dbg(ab, ATH12K_DBG_MAC, ++ "CAC Started in chan_freq %d for vdev %d\n", ++ chandef->chan->center_freq, arvif->vdev_id); ++ } ++ ++ ret = ath12k_mac_set_txbf_conf(arvif); ++ if (ret) ++ ath12k_warn(ab, "failed to set txbf conf for vdev %d: %d\n", ++ arvif->vdev_id, ret); ++ ++ ret = ath12k_mac_set_6g_nonht_dup_conf(arvif, chandef); ++ if (ret) ++ ath12k_warn(ab, "failed to set 6G non-ht dup conf for vdev %d: %d\n", ++ arvif->vdev_id, ret); ++ ++ return ret; ++} ++ ++static int + ath12k_mac_vdev_start_restart(struct ath12k_link_vif *arvif, + const struct cfg80211_chan_def *chandef, + bool restart, bool radar_enabled) +@@ -9756,44 +9805,15 @@ ath12k_mac_vdev_start_restart(struct ath + return ret; + } + +- if (ar->supports_6ghz && +- chandef->chan->band == NL80211_BAND_6GHZ && +- (ahvif->vdev_type == WMI_VDEV_TYPE_STA || ahvif->vdev_type == WMI_VDEV_TYPE_AP) && +- test_bit(WMI_TLV_SERVICE_EXT_TPC_REG_SUPPORT, ar->ab->wmi_ab.svc_map)) { +- ath12k_mac_fill_reg_tpc_info(ar, arvif, &arvif->chanctx); +- ath12k_wmi_send_vdev_set_tpc_power(ar, arvif->vdev_id, +- &arvif->reg_tpc_info); +- } +- + ar->num_started_vdevs++; + ath12k_dbg(ab, ATH12K_DBG_MAC, "vdev %pM started, vdev_id %d\n", + arvif->addr, arvif->vdev_id); + +- /* Enable CAC Flag in the driver by checking the channel DFS cac time, +- * i.e dfs_cac_ms value which will be valid only for radar channels +- * and state as NL80211_DFS_USABLE which indicates CAC needs to be +- * done before channel usage. This flags is used to drop rx packets. +- * during CAC. +- */ +- /* TODO Set the flag for other interface types as required */ +- if (ahvif->vdev_type == WMI_VDEV_TYPE_AP && +- chandef->chan->dfs_cac_ms && +- chandef->chan->dfs_state == NL80211_DFS_USABLE) { +- set_bit(ATH12K_CAC_RUNNING, &ar->dev_flags); +- ath12k_dbg(ab, ATH12K_DBG_MAC, +- "CAC Started in chan_freq %d for vdev %d\n", +- arg.channel.freq, arg.vdev_id); +- } +- +- ret = ath12k_mac_set_txbf_conf(arvif); ++ ret = ath12k_mac_vdev_config_after_start(arvif, chandef); + if (ret) +- ath12k_warn(ab, "failed to set txbf conf for vdev %d: %d\n", +- arvif->vdev_id, ret); +- +- ret = ath12k_mac_set_6g_nonht_dup_conf(arvif, chandef); +- if (ret) +- ath12k_warn(ab, "failed to set 6G non-ht dup conf for vdev %d: %d\n", +- arvif->vdev_id, ret); ++ ath12k_warn(ab, "failed to configure vdev %d after %s: %d\n", ++ arvif->vdev_id, ++ restart ? "restart" : "start", ret); + + return 0; + } +@@ -10162,6 +10182,67 @@ static void ath12k_mac_update_rx_channel + } + + static void ++ath12k_mac_update_vif_chan_extras(struct ath12k *ar, ++ struct ieee80211_vif_chanctx_switch *vifs, ++ int n_vifs) ++{ ++ struct ath12k_base *ab = ar->ab; ++ bool monitor_vif = false; ++ struct cfg80211_chan_def *chandef; ++ int i; ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ for (i = 0; i < n_vifs; i++) { ++ if (vifs[i].vif->type == NL80211_IFTYPE_MONITOR) { ++ monitor_vif = true; ++ break; ++ } ++ } ++ ++ /* Restart the internal monitor vdev on new channel */ ++ if (!monitor_vif && ++ test_bit(MONITOR_VDEV_CREATED, &ar->monitor_flags)) { ++ if (!ath12k_mac_monitor_stop(ar)) ++ ath12k_mac_monitor_start(ar); ++ } ++ ++ chandef = &vifs[0].new_ctx->def; ++ ++ spin_lock_bh(&ar->data_lock); ++ if (ar->awgn_intf_handling_in_prog && chandef) { ++ if (!ar->chan_bw_interference_bitmap || ++ (ar->chan_bw_interference_bitmap & WMI_DCS_SEG_PRI20)) { ++ if (ar->awgn_chandef.chan->center_freq != ++ chandef->chan->center_freq) { ++ ar->awgn_intf_handling_in_prog = false; ++ ath12k_dbg(ab, ATH12K_DBG_MAC, ++ "AWGN : channel switch completed\n"); ++ } else { ++ ath12k_warn(ab, "AWGN : channel switch is not done, freq : %d\n", ++ ar->awgn_chandef.chan->center_freq); ++ } ++ } else { ++ if ((ar->awgn_chandef.chan->center_freq == ++ chandef->chan->center_freq) && ++ (ar->awgn_chandef.width != chandef->width)) { ++ ath12k_dbg(ab, ATH12K_DBG_MAC, ++ "AWGN : BW reduction is complete\n"); ++ ar->awgn_intf_handling_in_prog = false; ++ } else { ++ ath12k_warn(ab, "AWGN : awgn_freq : %d chan_freq %d" ++ " awgn_width %d chan_width %d\n", ++ ar->awgn_chandef.chan->center_freq, ++ chandef->chan->center_freq, ++ ar->awgn_chandef.width, ++ chandef->width); ++ } ++ } ++ } ++ spin_unlock_bh(&ar->data_lock); ++} ++ ++static void + ath12k_mac_update_vif_chan(struct ath12k *ar, + struct ieee80211_vif_chanctx_switch *vifs, + int n_vifs) +@@ -10169,10 +10250,8 @@ ath12k_mac_update_vif_chan(struct ath12k + struct ath12k_base *ab = ar->ab; + struct ath12k_link_vif *arvif, *tx_arvif; + struct ath12k_vif *ahvif; +- struct cfg80211_chan_def *chandef = NULL; + int ret; + int i, trans_vdev_index; +- bool monitor_vif = false; + u64 vif_down_failed_map = 0; + struct ieee80211_vif *tx_vif; + +@@ -10194,9 +10273,6 @@ ath12k_mac_update_vif_chan(struct ath12k + if (WARN_ON(!arvif)) + continue; + +- if (vifs[i].vif->type == NL80211_IFTYPE_MONITOR) +- monitor_vif = true; +- + ath12k_dbg(ab, ATH12K_DBG_MAC, + "mac chanctx switch vdev_id %i freq %u->%u width %d->%d\n", + arvif->vdev_id, +@@ -10205,7 +10281,7 @@ ath12k_mac_update_vif_chan(struct ath12k + vifs[i].old_ctx->def.width, + vifs[i].new_ctx->def.width); + +- if (WARN_ON(!arvif->is_started)) { ++ if (!arvif->is_started) { + memcpy(&arvif->chanctx, vifs[i].new_ctx, sizeof(*vifs[i].new_ctx)); + continue; + } +@@ -10230,8 +10306,6 @@ ath12k_mac_update_vif_chan(struct ath12k + } + } + +- chandef = &vifs[0].new_ctx->def; +- + ath12k_mac_update_rx_channel(ar, NULL, vifs, n_vifs); + + if (tx_arvif) { +@@ -10252,9 +10326,6 @@ ath12k_mac_update_vif_chan(struct ath12k + if (WARN_ON(!arvif)) + continue; + +- if (vifs[i].vif->type == NL80211_IFTYPE_MONITOR) +- monitor_vif = true; +- + if (ahvif->vif->mbssid_tx_vif && + arvif == tx_arvif) + continue; +@@ -10269,43 +10340,7 @@ ath12k_mac_update_vif_chan(struct ath12k + } + } + +- /* Restart the internal monitor vdev on new channel */ +- if (!monitor_vif && +- test_bit(MONITOR_VDEV_CREATED, &ar->monitor_flags)) { +- if (!ath12k_mac_monitor_stop(ar)) +- ath12k_mac_monitor_start(ar); +- } +- spin_lock_bh(&ar->data_lock); +- if (ar->awgn_intf_handling_in_prog && chandef) { +- if (!ar->chan_bw_interference_bitmap || +- (ar->chan_bw_interference_bitmap & WMI_DCS_SEG_PRI20)) { +- if (ar->awgn_chandef.chan->center_freq != +- chandef->chan->center_freq) { +- ar->awgn_intf_handling_in_prog = false; +- ath12k_dbg(ab, ATH12K_DBG_MAC, +- "AWGN : channel switch completed\n"); +- } else { +- ath12k_warn(ab, "AWGN : channel switch is not done, freq : %d\n", +- ar->awgn_chandef.chan->center_freq); +- } +- } else { +- if ((ar->awgn_chandef.chan->center_freq == +- chandef->chan->center_freq) && +- (ar->awgn_chandef.width != chandef->width)) { +- ath12k_dbg(ab, ATH12K_DBG_MAC, +- "AWGN : BW reduction is complete\n"); +- ar->awgn_intf_handling_in_prog = false; +- } else { +- ath12k_warn(ab, "AWGN : awgn_freq : %d chan_freq %d" +- " awgn_width %d chan_width %d\n", +- ar->awgn_chandef.chan->center_freq, +- chandef->chan->center_freq, +- ar->awgn_chandef.width, +- chandef->width); +- } +- } +- } +- spin_unlock_bh(&ar->data_lock); ++ ath12k_mac_update_vif_chan_extras(ar, vifs, n_vifs); + } + + static void diff --git a/feeds/ipq95xx/mac80211/patches/qca/690-0002-ath12k-add-multi-vdev-restart-support.patch b/feeds/ipq95xx/mac80211/patches/qca/690-0002-ath12k-add-multi-vdev-restart-support.patch new file mode 100644 index 000000000..aae79032d --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/690-0002-ath12k-add-multi-vdev-restart-support.patch @@ -0,0 +1,661 @@ +From 0b2c0e6cee6ea4770e32df4139b3a887dd49eb80 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Tue, 29 Nov 2022 16:16:13 +0530 +Subject: [PATCH 2/2] ath12k: add multi-vdev restart support + +Multi-vdev restart command is used to update the channel to all affected vdevs +at once. Among all vdev params, only channel could vary in this command. Hence, +during channel change, this command is useful. + +Currently, during channel change, each vdev is brought down first, then channel +is changed followed by bringing vdev up. In multi-vif scenario, this might lead +to FW buffer overflow. Instead, multi vdev restart comand could be used. + +Add support for multi vdev restart command and send it during channel switch. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath12k/core.h | 4 + + drivers/net/wireless/ath/ath12k/mac.c | 189 +++++++++++++++++++- + drivers/net/wireless/ath/ath12k/wmi.c | 235 ++++++++++++++++++++++--- + drivers/net/wireless/ath/ath12k/wmi.h | 47 +++++ + 4 files changed, 448 insertions(+), 27 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -362,6 +362,8 @@ struct ath12k_link_vif { + struct work_struct update_obss_color_notify_work; + u8 link_id; + struct ath12k_vif *ahvif; ++ ++ bool mvr_processing; + }; + + struct ath12k_vif { +@@ -870,6 +872,8 @@ struct ath12k { + bool fw_stats_done; + + unsigned long last_tx_power_update; ++ ++ struct completion mvr_complete; + }; + + struct ath12k_band_cap { +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -9941,12 +9941,19 @@ static int ath12k_vdev_restart_sequence( + memcpy(&arvif->chanctx, new_ctx, sizeof(*new_ctx)); + spin_unlock_bh(&ar->data_lock); + +- if (vif_down_failed_map & BIT_ULL(vdev_index)) ++ /* vdev is already restarted via mvr, need to setup ++ * certain config alone after restart */ ++ if (vdev_index == -1) { ++ ret = ath12k_mac_vdev_config_after_start(arvif, &new_ctx->def); ++ if (!ret) ++ goto beacon_tmpl_setup; ++ } else if (vif_down_failed_map & BIT_ULL(vdev_index)) { + ret = ath12k_mac_vdev_restart(arvif, &new_ctx->def, false, + new_ctx->radar_enabled); +- else ++ } else { + ret = ath12k_mac_vdev_restart(arvif, &new_ctx->def, true, + new_ctx->radar_enabled); ++ } + + if (ret) { + ath12k_warn(ar->ab, "failed to restart vdev %d: %d\n", +@@ -9957,6 +9964,7 @@ static int ath12k_vdev_restart_sequence( + return ret; + } + ++beacon_tmpl_setup: + if (!arvif->is_up) + return -EOPNOTSUPP; + +@@ -10211,6 +10219,45 @@ static void ath12k_mac_update_rx_channel + ar->chan_tx_pwr = ATH12K_PDEV_TX_POWER_INVALID; + } + ++static int ++ath12k_mac_multi_vdev_restart(struct ath12k *ar, ++ const struct cfg80211_chan_def *chandef, ++ u32 *vdev_id, int len, ++ bool radar_enabled) ++{ ++ struct ath12k_base *ab = ar->ab; ++ struct wmi_pdev_multiple_vdev_restart_req_arg arg = {}; ++ int ret, i; ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ arg.vdev_ids.id_len = len; ++ ++ for (i = 0; i < len; i++) ++ arg.vdev_ids.id[i] = vdev_id[i]; ++ ++ arg.channel.freq = chandef->chan->center_freq; ++ arg.channel.band_center_freq1 = chandef->center_freq1; ++ arg.channel.band_center_freq2 = chandef->center_freq2; ++ arg.channel.mode = ++ ath12k_phymodes[chandef->chan->band][chandef->width]; ++ ++ 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 * 2; ++ arg.channel.chan_radar = !!(chandef->chan->flags & IEEE80211_CHAN_RADAR); ++ arg.channel.passive = arg.channel.chan_radar; ++ arg.channel.freq2_radar = radar_enabled; ++ arg.channel.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR); ++ arg.ru_punct_bitmap = ~chandef->ru_punct_bitmap; ++ ret = ath12k_wmi_pdev_multiple_vdev_restart(ar, &arg); ++ if (ret) ++ ath12k_warn(ab, "mac failed to do mvr (%d)\n", ret); ++ ++ return ret; ++} ++ + static void + ath12k_mac_update_vif_chan_extras(struct ath12k *ar, + struct ieee80211_vif_chanctx_switch *vifs, +@@ -10369,6 +10416,148 @@ ath12k_mac_update_vif_chan(struct ath12k + arvif->vdev_id, ret); + } + } ++} ++ ++static void ++ath12k_mac_update_vif_chan_mvr(struct ath12k *ar, ++ struct ieee80211_vif_chanctx_switch *vifs, ++ int n_vifs) ++{ ++ struct ath12k_base *ab = ar->ab; ++ struct ath12k_link_vif *arvif, *tx_arvif; ++ struct ath12k_vif *ahvif; ++ struct cfg80211_chan_def *chandef; ++ struct ieee80211_vif *tx_vif; ++ int ret, i, time_left, trans_vdev_index, vdev_idx, n_vdevs = 0; ++ u32 vdev_ids[TARGET_NUM_VDEVS]; ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ chandef = &vifs[0].new_ctx->def; ++ tx_arvif = NULL; ++ ++ ath12k_dbg(ab, ATH12K_DBG_MAC, "mac chanctx switch via mvr"); ++ ++ ath12k_mac_update_rx_channel(ar, NULL, vifs, n_vifs); ++ ++ for (i = 0; i < n_vifs; i++) { ++ ahvif = (void *)vifs[i].vif->drv_priv; ++ arvif = ahvif->link[vifs[i].link_conf->link_id]; ++ ++ if (WARN_ON(!arvif)) ++ continue; ++ ++ ath12k_dbg(ab, ATH12K_DBG_MAC, ++ "mac chanctx switch vdev_id %i freq %u->%u width %d->%d\n", ++ arvif->vdev_id, ++ vifs[i].old_ctx->def.chan->center_freq, ++ vifs[i].new_ctx->def.chan->center_freq, ++ vifs[i].old_ctx->def.width, ++ vifs[i].new_ctx->def.width); ++ ++ if (!arvif->is_started) { ++ memcpy(&arvif->chanctx, vifs[i].new_ctx, sizeof(*vifs[i].new_ctx)); ++ continue; ++ } ++ ++ if (ahvif->vif->mbssid_tx_vif && ++ ahvif == (struct ath12k_vif *)ahvif->vif->mbssid_tx_vif->drv_priv) { ++ tx_vif = ahvif->vif->mbssid_tx_vif; ++ /* TODO ML mbssid changes */ ++ tx_arvif = &ath12k_vif_to_ahvif(tx_vif)->deflink; ++ trans_vdev_index = i; ++ } ++ ++ arvif->mvr_processing = true; ++ vdev_ids[n_vdevs++] = arvif->vdev_id; ++ } ++ ++ if (!n_vdevs) { ++ ath12k_dbg(ab, ATH12K_DBG_MAC, ++ "mac 0 vdevs available to switch chan ctx via mvr\n"); ++ return; ++ } ++ ++ reinit_completion(&ar->mvr_complete); ++ ++ ret = ath12k_mac_multi_vdev_restart(ar, chandef, vdev_ids, n_vdevs, ++ vifs[0].new_ctx->radar_enabled); ++ if (ret) { ++ ath12k_warn(ab, "mac failed to send mvr command (%d)\n", ret); ++ return; ++ } ++ ++ time_left = wait_for_completion_timeout(&ar->mvr_complete, ++ WMI_MVR_CMD_TIMEOUT_HZ); ++ if (!time_left) { ++ ath12k_err(ar->ab, "mac mvr cmd response timed out\n"); ++ /* fallback to restarting one-by-one */ ++ return ath12k_mac_update_vif_chan(ar, vifs, n_vifs); ++ } ++ ++ if (tx_arvif) { ++ vdev_idx = -1; ++ ++ if (tx_arvif->mvr_processing) { ++ /* failed to restart tx vif via mvr, fallback */ ++ arvif->mvr_processing = false; ++ vdev_idx = trans_vdev_index; ++ ath12k_err(ab, ++ "mac failed to restart mbssid tx vdev %d via mvr cmd\n", ++ tx_arvif->vdev_id); ++ } ++ ++ ret = ath12k_vdev_restart_sequence(tx_arvif, ++ vifs[trans_vdev_index].new_ctx, ++ BIT_ULL(trans_vdev_index), ++ vdev_idx); ++ if (ret) ++ ath12k_warn(ab, ++ "mac failed to bring up mbssid tx vdev %d after mvr (%d)\n", ++ tx_arvif->vdev_id, ret); ++ } ++ ++ for (i = 0; i < n_vifs; i++) { ++ ahvif = (void *)vifs[i].vif->drv_priv; ++ arvif = ahvif->link[vifs[i].link_conf->link_id]; ++ ++ if (WARN_ON(!arvif)) ++ continue; ++ ++ vdev_idx = -1; ++ ++ if (ahvif->vif->mbssid_tx_vif && arvif == tx_arvif) ++ continue; ++ ++ if (arvif->mvr_processing) { ++ /* failed to restart vdev via mvr, fallback */ ++ arvif->mvr_processing = false; ++ vdev_idx = i; ++ ath12k_err(ab, "mac failed to restart vdev %d via mvr cmd\n", ++ arvif->vdev_id); ++ } ++ ++ ret = ath12k_vdev_restart_sequence(arvif, vifs[i].new_ctx, ++ BIT_ULL(i), vdev_idx); ++ if (ret && ret != -EOPNOTSUPP) ++ ath12k_warn(ab, "mac failed to bring up vdev %d after mvr (%d)\n", ++ arvif->vdev_id, ret); ++ } ++} ++ ++static void ++ath12k_mac_process_update_vif_chan(struct ath12k *ar, ++ struct ieee80211_vif_chanctx_switch *vifs, ++ int n_vifs) ++{ ++ struct ath12k_base *ab = ar->ab; ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ if (ath12k_wmi_is_mvr_supported(ab)) ++ ath12k_mac_update_vif_chan_mvr(ar, vifs, n_vifs); ++ else ++ ath12k_mac_update_vif_chan(ar, vifs, n_vifs); + + ath12k_mac_update_vif_chan_extras(ar, vifs, n_vifs); + } +@@ -10400,7 +10589,7 @@ ath12k_mac_update_active_vif_chan(struct + ath12k_mac_change_chanctx_fill_iter, + &arg); + +- ath12k_mac_update_vif_chan(ar, arg.vifs, arg.n_vifs); ++ ath12k_mac_process_update_vif_chan(ar, arg.vifs, arg.n_vifs); + + kfree(arg.vifs); + out: +@@ -11321,7 +11510,7 @@ ath12k_mac_op_switch_vif_chanctx(struct + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, + "mac chanctx switch n_vifs %d mode %d\n", + n_vifs, mode); +- ath12k_mac_update_vif_chan(ar, vifs, n_vifs); ++ ath12k_mac_process_update_vif_chan(ar, vifs, n_vifs); + + mutex_unlock(&ar->conf_mutex); + +@@ -13616,6 +13805,7 @@ static int ath12k_mac_setup(struct ath12 + init_completion(&ar->scan.completed); + init_completion(&ar->thermal.wmi_sync); + init_completion(&ar->mlo_setup_done); ++ init_completion(&ar->mvr_complete); + + INIT_DELAYED_WORK(&ar->scan.timeout, ath12k_scan_timeout_work); + INIT_WORK(&ar->regd_update_work, ath12k_regd_update_work); +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -956,55 +956,55 @@ int ath12k_wmi_vdev_down(struct ath12k * + } + + static void ath12k_wmi_put_wmi_channel(struct wmi_channel *chan, +- struct wmi_vdev_start_req_arg *arg) ++ struct wmi_channel_arg chan_arg) + { +- u32 center_freq1 = arg->channel.band_center_freq1; ++ u32 center_freq1 = chan_arg.band_center_freq1; + + memset(chan, 0, sizeof(*chan)); + +- chan->mhz = arg->channel.freq; +- chan->band_center_freq1 = arg->channel.band_center_freq1; ++ chan->mhz = chan_arg.freq; ++ chan->band_center_freq1 = chan_arg.band_center_freq1; + +- if ((arg->channel.mode == MODE_11AX_HE160) || (arg->channel.mode == MODE_11BE_EHT160)) { +- if (arg->channel.freq > arg->channel.band_center_freq1) ++ if ((chan_arg.mode == MODE_11AX_HE160) || (chan_arg.mode == MODE_11BE_EHT160)) { ++ if (chan_arg.freq > chan_arg.band_center_freq1) + chan->band_center_freq1 = center_freq1 + 40; + else + chan->band_center_freq1 = center_freq1 - 40; + +- chan->band_center_freq2 = arg->channel.band_center_freq1; ++ chan->band_center_freq2 = chan_arg.band_center_freq1; + +- } else if (arg->channel.mode == MODE_11AC_VHT80_80) { +- chan->band_center_freq2 = arg->channel.band_center_freq2; ++ } else if (chan_arg.mode == MODE_11AC_VHT80_80) { ++ chan->band_center_freq2 = chan_arg.band_center_freq2; + } else { + chan->band_center_freq2 = 0; + } + +- chan->info |= u32_encode_bits(arg->channel.mode, WMI_CHAN_INFO_MODE); +- if (arg->channel.passive) ++ chan->info |= u32_encode_bits(chan_arg.mode, WMI_CHAN_INFO_MODE); ++ if (chan_arg.passive) + chan->info |= WMI_CHAN_INFO_PASSIVE; +- if (arg->channel.allow_ibss) ++ if (chan_arg.allow_ibss) + chan->info |= WMI_CHAN_INFO_ADHOC_ALLOWED; +- if (arg->channel.allow_ht) ++ if (chan_arg.allow_ht) + chan->info |= WMI_CHAN_INFO_ALLOW_HT; +- if (arg->channel.allow_vht) ++ if (chan_arg.allow_vht) + chan->info |= WMI_CHAN_INFO_ALLOW_VHT; +- if (arg->channel.allow_he) ++ if (chan_arg.allow_he) + chan->info |= WMI_CHAN_INFO_ALLOW_HE; +- if (arg->channel.ht40plus) ++ if (chan_arg.ht40plus) + chan->info |= WMI_CHAN_INFO_HT40_PLUS; +- if (arg->channel.chan_radar) ++ if (chan_arg.chan_radar) + chan->info |= WMI_CHAN_INFO_DFS; +- if (arg->channel.freq2_radar) ++ if (chan_arg.freq2_radar) + chan->info |= WMI_CHAN_INFO_DFS_FREQ2; + +- chan->reg_info_1 = u32_encode_bits(arg->channel.max_power, ++ chan->reg_info_1 = u32_encode_bits(chan_arg.max_power, + WMI_CHAN_REG_INFO1_MAX_PWR) | +- u32_encode_bits(arg->channel.max_reg_power, ++ u32_encode_bits(chan_arg.max_reg_power, + WMI_CHAN_REG_INFO1_MAX_REG_PWR); + +- chan->reg_info_2 = u32_encode_bits(arg->channel.max_antenna_gain, ++ chan->reg_info_2 = u32_encode_bits(chan_arg.max_antenna_gain, + WMI_CHAN_REG_INFO2_ANT_MAX) | +- u32_encode_bits(arg->channel.max_power, WMI_CHAN_REG_INFO2_MAX_TX_PWR); ++ u32_encode_bits(chan_arg.max_power, WMI_CHAN_REG_INFO2_MAX_TX_PWR); + } + + int ath12k_wmi_vdev_start(struct ath12k *ar, struct wmi_vdev_start_req_arg *arg, +@@ -1067,7 +1067,7 @@ int ath12k_wmi_vdev_start(struct ath12k + ptr = skb->data + sizeof(*cmd); + chan = ptr; + +- ath12k_wmi_put_wmi_channel(chan, arg); ++ ath12k_wmi_put_wmi_channel(chan, arg->channel); + + chan->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_CHANNEL, + sizeof(*chan)); +@@ -9471,6 +9471,108 @@ static void ath12k_wmi_event_teardown_co + kfree(tb); + } + ++static void ath12k_wmi_process_mvr_event(struct ath12k *ab, u32 *vdev_id_bm, ++ u32 num_vdev_bm) ++{ ++ struct ath12k *ar = NULL; ++ struct ath12k_link_vif *arvif = NULL; ++ u32 vdev_bitmap, bit_pos; ++ ++ ath12k_dbg(ab, ATH12K_DBG_WMI, ++ "wmi mvr resp num_vdev_bm %d vdev_id_bm[0]=0x%x vdev_id_bm[1]=0x%x\n", ++ num_vdev_bm, vdev_id_bm[0], ++ (num_vdev_bm == WMI_MVR_RESP_VDEV_BM_MAX_LEN ? ++ vdev_id_bm[1] : 0x00)); ++ ++ /* 31-0 bits processing */ ++ vdev_bitmap = vdev_id_bm[0]; ++ ++ for (bit_pos = 0; bit_pos < 32; bit_pos++) { ++ ++ if (!test_bit(bit_pos, &vdev_bitmap)) ++ continue; ++ ++ arvif = ath12k_mac_get_arvif_by_vdev_id(ab, bit_pos); ++ if (!arvif) { ++ ath12k_warn(ab, "wmi mvr resp for unknown vdev %d", bit_pos); ++ continue; ++ } ++ ++ arvif->mvr_processing = false; ++ ath12k_dbg(ab, ATH12K_DBG_WMI, ++ "wmi mvr vdev %d restarted\n", bit_pos); ++ } ++ ++ /* TODO: 63-32 bits processing ++ * Add support to parse bitmap once support for ++ * TARGET_NUM_VDEVS > 32 is added ++ */ ++ ++ if (arvif) ++ ar = arvif->ar; ++ ++ if (ar) ++ complete(&ar->mvr_complete); ++} ++ ++static int ath12k_wmi_tlv_mvr_event_parse(struct ath12k_base *ab, ++ u16 tag, u16 len, ++ const void *ptr, void *data) ++{ ++ struct wmi_pdev_mvr_resp_event_parse *parse = data; ++ struct wmi_pdev_mvr_resp_event_fixed_param *fixed_param; ++ ++ switch(tag) { ++ case WMI_TAG_MULTIPLE_VDEV_RESTART_RESPONSE_EVENT: ++ fixed_param = (struct wmi_pdev_mvr_resp_event_fixed_param *)ptr; ++ ++ if (fixed_param->status) { ++ ath12k_warn(ab, "wmi mvr resp event status %u\n", ++ fixed_param->status); ++ return -EINVAL; ++ } ++ ++ memcpy(&parse->fixed_param, fixed_param, ++ sizeof(struct wmi_pdev_mvr_resp_event_fixed_param)); ++ break; ++ case WMI_TAG_ARRAY_UINT32: ++ if ((len > WMI_MVR_RESP_VDEV_BM_MAX_LEN_BYTES) || (len == 0)) { ++ ath12k_warn(ab, "wmi invalid vdev id len in mvr resp %u\n", ++ len); ++ return -EINVAL; ++ } ++ ++ parse->num_vdevs_bm = len / sizeof(u32); ++ memcpy(parse->vdev_id_bm, ptr, len); ++ break; ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++static void ath12k_wmi_event_mvr_response(struct ath12k_base *ab, ++ struct sk_buff *skb) ++{ ++ struct wmi_pdev_mvr_resp_event_parse parse = {}; ++ int ret; ++ ++ ret = ath12k_wmi_tlv_iter(ab, skb->data, skb->len, ++ ath12k_wmi_tlv_mvr_event_parse, ++ &parse); ++ if (ret) { ++ ath12k_warn(ab, "wmi failed to parse mvr response tlv %d\n", ++ ret); ++ return; ++ } ++ ++ ath12k_dbg(ab, ATH12K_DBG_WMI, "wmi mvr resp for pdev %d\n", ++ parse.fixed_param.pdev_id); ++ ++ ath12k_wmi_process_mvr_event(ab, parse.vdev_id_bm, parse.num_vdevs_bm); ++} ++ + static void ath12k_wmi_tlv_op_rx(struct ath12k_base *ab, struct sk_buff *skb) + { + struct wmi_cmd_hdr *cmd_hdr; +@@ -9617,6 +9719,9 @@ static void ath12k_wmi_tlv_op_rx(struct + case WMI_MLO_TEARDOWN_COMPLETE_EVENTID: + ath12k_wmi_event_teardown_complete(ab, skb); + break; ++ case WMI_PDEV_MULTIPLE_VDEV_RESTART_RESP_EVENTID: ++ ath12k_wmi_event_mvr_response(ab, skb); ++ break; + /* TODO: Add remaining events */ + default: + ath12k_dbg(ab, ATH12K_DBG_WMI, "Unknown eventid: 0x%x\n", id); +@@ -10073,3 +10178,82 @@ int ath12k_wmi_mlo_teardown(struct ath12 + + return ret; + } ++ ++bool ath12k_wmi_is_mvr_supported(struct ath12k_base *ab) ++{ ++ struct ath12k_wmi_base *wmi_ab = &ab->wmi_ab; ++ ++ return test_bit(WMI_TLV_SERVICE_MULTIPLE_VDEV_RESTART, ++ wmi_ab->svc_map) && ++ test_bit(WMI_TLV_SERVICE_MULTIPLE_VDEV_RESTART_RESPONSE_SUPPORT, ++ wmi_ab->svc_map); ++} ++ ++int ath12k_wmi_pdev_multiple_vdev_restart(struct ath12k *ar, ++ struct wmi_pdev_multiple_vdev_restart_req_arg *arg) ++{ ++ struct ath12k_pdev_wmi *wmi = ar->wmi; ++ struct wmi_pdev_multiple_vdev_restart_request_cmd *cmd; ++ struct wmi_channel *chan; ++ struct wmi_tlv *tlv; ++ u32 num_vdev_ids; ++ __le32 *vdev_ids; ++ size_t vdev_ids_len; ++ struct sk_buff *skb; ++ void *ptr; ++ int ret, len, i; ++ ++ if (WARN_ON(arg->vdev_ids.id_len > TARGET_NUM_VDEVS)) ++ return -EINVAL; ++ ++ num_vdev_ids = arg->vdev_ids.id_len; ++ vdev_ids_len = num_vdev_ids * sizeof(__le32); ++ ++ len = sizeof(*cmd) + TLV_HDR_SIZE + vdev_ids_len + ++ sizeof(*chan); ++ ++ skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len); ++ if (!skb) ++ return -ENOMEM; ++ ++ cmd = (struct wmi_pdev_multiple_vdev_restart_request_cmd *)skb->data; ++ cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PDEV_MULTIPLE_VDEV_RESTART_REQUEST_CMD, ++ sizeof(*cmd)); ++ cmd->pdev_id = cpu_to_le32(ar->pdev->pdev_id); ++ cmd->num_vdevs = cpu_to_le32(arg->vdev_ids.id_len); ++ cmd->puncture_20mhz_bitmap = cpu_to_le32(arg->ru_punct_bitmap); ++ ++ cmd->flags = cpu_to_le32(WMI_MVR_RESPONSE_SUPPORT_EXPECTED); ++ ++ ptr = skb->data + sizeof(*cmd); ++ tlv = (struct wmi_tlv *)ptr; ++ ++ tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_UINT32, vdev_ids_len); ++ vdev_ids = (__le32 *)tlv->value; ++ ++ for (i = 0; i < num_vdev_ids; i++) ++ vdev_ids[i] = cpu_to_le32(arg->vdev_ids.id[i]); ++ ++ ptr += TLV_HDR_SIZE + vdev_ids_len; ++ chan = (struct wmi_channel *)ptr; ++ ++ ath12k_wmi_put_wmi_channel(chan, arg->channel); ++ ++ chan->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_CHANNEL, sizeof(*chan)); ++ ptr += sizeof(*chan); ++ ++ ret = ath12k_wmi_cmd_send(wmi, skb, ++ WMI_PDEV_MULTIPLE_VDEV_RESTART_REQUEST_CMDID); ++ if (ret) { ++ ath12k_warn(ar->ab, "wmi failed to send mvr command (%d)\n", ++ ret); ++ dev_kfree_skb(skb); ++ return ret; ++ } ++ ++ ath12k_dbg(ar->ab, ATH12K_DBG_WMI, ++ "wmi mvr cmd sent num_vdevs %d freq %d\n", ++ num_vdev_ids, arg->channel.freq); ++ ++ return ret; ++} +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -1919,6 +1919,7 @@ enum wmi_tlv_tag { + WMI_TAG_MUEDCA_PARAMS_CONFIG_EVENT = 0x32a, + WMI_TAG_SERVICE_READY_EXT2_EVENT = 0x334, + WMI_TAG_FILS_DISCOVERY_TMPL_CMD = 0x344, ++ WMI_TAG_MULTIPLE_VDEV_RESTART_RESPONSE_EVENT = 0x365, + WMI_TAG_MAC_PHY_CAPABILITIES_EXT = 0x36F, + WMI_TAG_PDEV_SRG_BSS_COLOR_BITMAP_CMD = 0x37b, + WMI_TAG_PDEV_SRG_PARTIAL_BSSID_BITMAP_CMD, +@@ -2176,6 +2177,7 @@ enum wmi_tlv_service { + WMI_TLV_SERVICE_PER_PEER_HTT_STATS_RESET = 213, + WMI_TLV_SERVICE_FREQINFO_IN_METADATA = 219, + WMI_TLV_SERVICE_EXT2_MSG = 220, ++ WMI_TLV_SERVICE_MULTIPLE_VDEV_RESTART_RESPONSE_SUPPORT = 235, + WMI_TLV_SERVICE_5_9GHZ_SUPPORT = 247, + WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT = 249, + +@@ -6354,6 +6356,47 @@ struct wmi_mlo_teardown_complete_fixed_p + u32 status; + } __packed; + ++/* Inform FW that host expects response for multi-vdev ++ * restart command */ ++#define WMI_MVR_RESPONSE_SUPPORT_EXPECTED 0x1 ++#define WMI_MVR_CMD_TIMEOUT_HZ (2 * HZ) ++#define WMI_MVR_RESP_VDEV_BM_MAX_LEN 2 ++#define WMI_MVR_RESP_VDEV_BM_MAX_LEN_BYTES (WMI_MVR_RESP_VDEV_BM_MAX_LEN * 4) ++ ++struct wmi_vdev_ids_arg { ++ u32 id_len; ++ u32 id[17]; /* TARGET_NUM_VDEVS */ ++}; ++ ++struct wmi_pdev_multiple_vdev_restart_req_arg { ++ struct wmi_vdev_ids_arg vdev_ids; ++ struct wmi_channel_arg channel; ++ u16 ru_punct_bitmap; ++}; ++ ++struct wmi_pdev_multiple_vdev_restart_request_cmd { ++ __le32 tlv_header; ++ __le32 pdev_id; ++ __le32 requestor_id; ++ __le32 disable_hw_ack; ++ __le32 cac_duration_ms; ++ __le32 num_vdevs; ++ __le32 flags; ++ __le32 puncture_20mhz_bitmap; ++} __packed; ++ ++struct wmi_pdev_mvr_resp_event_fixed_param { ++ u32 pdev_id; ++ u32 requestor_id; ++ u32 status; ++} __packed; ++ ++struct wmi_pdev_mvr_resp_event_parse { ++ struct wmi_pdev_mvr_resp_event_fixed_param fixed_param; ++ u32 num_vdevs_bm; ++ u32 vdev_id_bm[]; ++} __packed; ++ + #define ATH12K_FW_STATS_BUF_SIZE (1024 * 1024) + + void ath12k_wmi_init_qcn9274(struct ath12k_base *ab, +@@ -6522,4 +6565,7 @@ int ath12k_wmi_mlo_setup(struct ath12k * + struct wmi_mlo_setup_params *mlo_params); + int ath12k_wmi_mlo_ready(struct ath12k *ar); + int ath12k_wmi_mlo_teardown(struct ath12k *ar); ++bool ath12k_wmi_is_mvr_supported(struct ath12k_base *ab); ++int ath12k_wmi_pdev_multiple_vdev_restart(struct ath12k *ar, ++ struct wmi_pdev_multiple_vdev_restart_req_arg *arg); + #endif diff --git a/feeds/ipq95xx/mac80211/patches/qca/690-01-cfg80211-get-tx-power-for-each-link.patch b/feeds/ipq95xx/mac80211/patches/qca/690-01-cfg80211-get-tx-power-for-each-link.patch new file mode 100644 index 000000000..42bebec6c --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/690-01-cfg80211-get-tx-power-for-each-link.patch @@ -0,0 +1,109 @@ +From 6346b88a2efabf84fa41ef4e115c8c0b76d38816 Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Wed, 30 Nov 2022 16:46:56 +0530 +Subject: [PATCH] cfg80211: get tx power for each link + +Currently, we are getting tx power for each phy, but in +multi-link operation each phy has multiple links which +operate in different bands, so their tx power will +also be different. + +Add support to get tx power for each link + +Signed-off-by: Aaradhana Sahu +--- + include/net/cfg80211.h | 2 +- + net/wireless/nl80211.c | 5 ++--- + net/wireless/rdev-ops.h | 7 ++++--- + net/wireless/trace.h | 5 +++-- + net/wireless/wext-compat.c | 2 +- + 5 files changed, 11 insertions(+), 10 deletions(-) + +diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h +index f273b3b..c85bb18 100644 +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -4494,7 +4494,7 @@ struct cfg80211_ops { + int (*set_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev, + enum nl80211_tx_power_setting type, int mbm); + int (*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev, +- int *dbm); ++ unsigned int link_id, int *dbm); + + void (*rfkill_poll)(struct wiphy *wiphy); + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 7ba1e02..2af9865 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -3989,8 +3989,7 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag + } + if (rdev->ops->get_tx_power) { + int dbm, ret; +- /* TODO find tx_power according to link_id */ +- ret = rdev_get_tx_power(rdev, wdev, &dbm); ++ ret = rdev_get_tx_power(rdev, wdev, link_id, &dbm); + if (ret == 0 && + nla_put_u32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL, + DBM_TO_MBM(dbm))) +@@ -4017,7 +4016,7 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag + } + if (rdev->ops->get_tx_power) { + int dbm, ret; +- ret = rdev_get_tx_power(rdev, wdev, &dbm); ++ ret = rdev_get_tx_power(rdev, wdev, 0, &dbm); + if (ret == 0 && + nla_put_u32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL, + DBM_TO_MBM(dbm))) +diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h +index 3a1c3f8..f52bf0f 100644 +--- a/net/wireless/rdev-ops.h ++++ b/net/wireless/rdev-ops.h +@@ -579,11 +579,12 @@ static inline int rdev_set_tx_power(struct cfg80211_registered_device *rdev, + } + + static inline int rdev_get_tx_power(struct cfg80211_registered_device *rdev, +- struct wireless_dev *wdev, int *dbm) ++ struct wireless_dev *wdev, ++ unsigned int link_id, int *dbm) + { + int ret; +- trace_rdev_get_tx_power(&rdev->wiphy, wdev); +- ret = rdev->ops->get_tx_power(&rdev->wiphy, wdev, dbm); ++ trace_rdev_get_tx_power(&rdev->wiphy, wdev, link_id); ++ ret = rdev->ops->get_tx_power(&rdev->wiphy, wdev, link_id, dbm); + trace_rdev_return_int_int(&rdev->wiphy, ret, *dbm); + return ret; + } +diff --git a/net/wireless/trace.h b/net/wireless/trace.h +index f3e2ba7..5c47d7b 100644 +--- a/net/wireless/trace.h ++++ b/net/wireless/trace.h +@@ -1564,8 +1564,9 @@ TRACE_EVENT(rdev_set_wiphy_params, + ); + + DEFINE_EVENT(wiphy_wdev_evt, rdev_get_tx_power, +- TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev), +- TP_ARGS(wiphy, wdev) ++ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, ++ unsigned int link_id), ++ TP_ARGS(wiphy, wdev, link_id) + ); + + TRACE_EVENT(rdev_set_tx_power, +diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c +index a9767bf..42da984 100644 +--- a/net/wireless/wext-compat.c ++++ b/net/wireless/wext-compat.c +@@ -974,7 +974,7 @@ static int cfg80211_wext_giwtxpower(struct net_device *dev, + return -EOPNOTSUPP; + + wiphy_lock(&rdev->wiphy); +- err = rdev_get_tx_power(rdev, wdev, &val); ++ err = rdev_get_tx_power(rdev, wdev, 0, &val); + wiphy_unlock(&rdev->wiphy); + if (err) + return err; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/690-02-mac80211-get-tx-power-for-each-link.patch b/feeds/ipq95xx/mac80211/patches/qca/690-02-mac80211-get-tx-power-for-each-link.patch new file mode 100644 index 000000000..49496915a --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/690-02-mac80211-get-tx-power-for-each-link.patch @@ -0,0 +1,87 @@ +From 7c89a739ba3f25b0ba894c2e9990cddd16f2bf7e Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Wed, 30 Nov 2022 16:50:43 +0530 +Subject: [PATCH] mac80211: get tx power for each link + +Currently, we are getting tx power for each phy, but in +multi-link operation each phy has multiple links which +operate in different bands, so their tx power will +also be different. + +Add support to get tx power for each link. + +Signed-off-by: Aaradhana Sahu +--- + include/net/mac80211.h | 2 +- + net/mac80211/cfg.c | 3 ++- + net/mac80211/driver-ops.h | 5 +++-- + 3 files changed, 6 insertions(+), 4 deletions(-) + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -4557,7 +4557,7 @@ struct ieee80211_ops { + u32 (*get_expected_throughput)(struct ieee80211_hw *hw, + struct ieee80211_sta *sta); + int (*get_txpower)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, +- int *dbm); ++ unsigned int link_id, int *dbm); + + int (*tdls_channel_switch)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -3161,18 +3161,31 @@ static int ieee80211_set_tx_power(struct + + static int ieee80211_get_tx_power(struct wiphy *wiphy, + struct wireless_dev *wdev, ++ unsigned int link_id, + int *dbm) + { + struct ieee80211_local *local = wiphy_priv(wiphy); + struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); ++ struct ieee80211_bss_conf *link_conf = NULL; + + if (local->ops->get_txpower) +- return drv_get_txpower(local, sdata, dbm); ++ return drv_get_txpower(local, sdata, link_id, dbm); + + if (!local->use_chanctx) + *dbm = local->hw.conf.power_level; +- else +- *dbm = sdata->vif.bss_conf.txpower; ++ else { ++ rcu_read_lock(); ++ link_conf = rcu_dereference(sdata->vif.link_conf[link_id]); ++ ++ if (!link_conf) { ++ *dbm = 0; ++ rcu_read_unlock(); ++ return 0; ++ } ++ ++ *dbm = link_conf->txpower; ++ rcu_read_unlock(); ++ } + + return 0; + } +--- a/net/mac80211/driver-ops.h ++++ b/net/mac80211/driver-ops.h +@@ -1132,14 +1132,15 @@ static inline u32 drv_get_expected_throu + } + + static inline int drv_get_txpower(struct ieee80211_local *local, +- struct ieee80211_sub_if_data *sdata, int *dbm) ++ struct ieee80211_sub_if_data *sdata, ++ unsigned int link_id, int *dbm) + { + int ret; + + if (!local->ops->get_txpower) + return -EOPNOTSUPP; + +- ret = local->ops->get_txpower(&local->hw, &sdata->vif, dbm); ++ ret = local->ops->get_txpower(&local->hw, &sdata->vif, link_id, dbm); + trace_drv_get_txpower(local, sdata, *dbm, ret); + + return ret; diff --git a/feeds/ipq95xx/mac80211/patches/qca/690-03-ath11k-get-txpower-for-each-link.patch b/feeds/ipq95xx/mac80211/patches/qca/690-03-ath11k-get-txpower-for-each-link.patch new file mode 100644 index 000000000..208b5bdf4 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/690-03-ath11k-get-txpower-for-each-link.patch @@ -0,0 +1,28 @@ +From 94f8db3507ef6f6bcdfe9d93e291cb3ee759ed99 Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Wed, 30 Nov 2022 17:25:38 +0530 +Subject: [PATCH] ath11k: get txpower for each link + +To avoid compilation issue + +Signed-off-by: Aaradhana Sahu +--- + drivers/net/wireless/ath/ath11k/mac.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c +index a8323a9..fc2a4a6 100644 +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -11991,7 +11991,7 @@ static int ath11k_fw_stats_request(struct ath11k *ar, + + static int ath11k_mac_op_get_txpower(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, +- int *dbm) ++ unsigned int link_id, int *dbm) + { + struct ath11k *ar = hw->priv; + struct ath11k_base *ab = ar->ab; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/690-04-ath12k-get-txpower-for-each-link.patch b/feeds/ipq95xx/mac80211/patches/qca/690-04-ath12k-get-txpower-for-each-link.patch new file mode 100644 index 000000000..c4a01e46f --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/690-04-ath12k-get-txpower-for-each-link.patch @@ -0,0 +1,80 @@ +From 0bb78f7a97fe8ad3a70f8fdfdd5b56a2f887a59b Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Wed, 30 Nov 2022 17:24:03 +0530 +Subject: [PATCH] ath12k: get txpower for each link + +Currently, we are getting tx power for each phy, but in +multi-link operation each phy has multiple links which +operate in different bands, so their tx power will +also be different. + +Add support to get tx power for each link. + +Signed-off-by: Aaradhana Sahu +--- + drivers/net/wireless/ath/ath12k/mac.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -12748,7 +12748,7 @@ static int ath12k_fw_stats_request(struc + + static int ath12k_mac_op_get_txpower(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, +- int *dbm) ++ unsigned int link_id, int *dbm) + { + struct ath12k_hw *ah = hw->priv; + struct stats_request_params req_param; +@@ -12756,6 +12756,9 @@ static int ath12k_mac_op_get_txpower(str + struct ath12k *ar; + struct ath12k_base *ab; + int ret; ++ struct ieee80211_bss_conf *link_conf; ++ struct ath12k_vif *ahvif; ++ struct ath12k_link_vif *arvif; + + /* Final Tx power is minimum of Target Power, CTL power, Regulatory + * Power, PSD EIRP Power. We just know the Regulatory power from the +@@ -12765,7 +12768,7 @@ static int ath12k_mac_op_get_txpower(str + */ + mutex_lock(&ah->conf_mutex); + +- ar = ath12k_get_ar_by_vif(hw, vif, 0); ++ ar = ath12k_get_ar_by_vif(hw, vif, link_id); + if (!ar) { + goto err_fallback; + } +@@ -12805,9 +12808,30 @@ static int ath12k_mac_op_get_txpower(str + return 0; + + err_fallback: ++ ahvif = ath12k_vif_to_ahvif(vif); ++ arvif = ahvif->link[link_id]; ++ ++ if (!arvif) { ++ *dbm = 0; ++ mutex_unlock(&ah->conf_mutex); ++ return 0; ++ } ++ ++ rcu_read_lock(); ++ ++ /* We didn't get txpower from FW. Hence, relying on link_conf->txpower */ ++ link_conf = ath12k_get_link_bss_conf(arvif); ++ ++ if (!link_conf) { ++ *dbm = 0; ++ rcu_read_unlock(); ++ mutex_unlock(&ah->conf_mutex); ++ return 0; ++ } ++ ++ *dbm = link_conf->txpower; ++ rcu_read_unlock(); + mutex_unlock(&ah->conf_mutex); +- /* We didn't get txpower from FW. Hence, relying on vif->bss_conf.txpower */ +- *dbm = vif->bss_conf.txpower; + ath12k_dbg(NULL, ATH12K_DBG_MAC, "txpower from firmware NaN, reported %d dBm\n", + *dbm); + return 0; diff --git a/feeds/ipq95xx/mac80211/patches/qca/690-ath12k-board-id-read-from-OTP.patch b/feeds/ipq95xx/mac80211/patches/qca/690-ath12k-board-id-read-from-OTP.patch new file mode 100644 index 000000000..20611989b --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/690-ath12k-board-id-read-from-OTP.patch @@ -0,0 +1,79 @@ +From 0424026ba82bc63ba655a952f0633613b249b516 Mon Sep 17 00:00:00 2001 +From: Vishal Kumar +Date: Fri, 25 Nov 2022 14:17:59 +0530 +Subject: [PATCH] ath12k: board id read from OTP + +read board id from OTP + +Signed-off-by: Vishal Kumar +Signed-off-by: Ganesh Babu Jothiram +--- + drivers/net/wireless/ath/ath12k/mhi.c | 21 ++++++++++++++------- + drivers/net/wireless/ath/ath12k/pci.h | 3 +++ + 2 files changed, 17 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/mhi.c b/drivers/net/wireless/ath/ath12k/mhi.c +index 150ab43..0c369f8 100644 +--- a/drivers/net/wireless/ath/ath12k/mhi.c ++++ b/drivers/net/wireless/ath/ath12k/mhi.c +@@ -16,6 +16,8 @@ + #include "pci.h" + + #define MHI_TIMEOUT_DEFAULT_MS 90000 ++#define OTP_INVALID_BOARD_ID 0xFFFF ++#define OTP_VALID_BOARD_ID_MASK 0x1000 + + static struct mhi_channel_config ath12k_mhi_channels_qcn9274[] = { + { +@@ -378,7 +380,7 @@ int ath12k_mhi_register(struct ath12k_pci *ab_pci) + struct ath12k_base *ab = ab_pci->ab; + struct device *dev = ab->dev; + struct mhi_controller *mhi_ctrl; +- unsigned int board_id; ++ unsigned int board_id, otp_board_id; + const char *filename = ATH12K_AMSS_FILE; + int ret; + +@@ -386,14 +388,19 @@ int ath12k_mhi_register(struct ath12k_pci *ab_pci) + if (!mhi_ctrl) + return -ENOMEM; + +- if (!of_property_read_u32(dev->of_node, "qcom,board_id", &board_id)) { +- if (board_id & 0x1000) { +- filename = ATH12K_AMSS_DUALMAC_FILE; +- ath12k_dbg(ab, ATH12K_DBG_BOOT, +- "DUALMAC FW %s selected for Split PHY HW\n", +- filename); ++ otp_board_id = ath12k_pci_read32(ab, QCN9224_QFPROM_RAW_RFA_PDET_ROW13_LSB); ++ ++ board_id = FIELD_GET(OTP_BOARD_ID_MASK, otp_board_id); ++ if (!board_id || (board_id == OTP_INVALID_BOARD_ID)) { ++ if (of_property_read_u32(dev->of_node, "qcom,board_id", &board_id)) { ++ ath12k_warn(ab, "failed to read board id\n"); + } + } ++ if (board_id & OTP_VALID_BOARD_ID_MASK) { ++ filename = ATH12K_AMSS_DUALMAC_FILE; ++ ath12k_dbg(ab, ATH12K_DBG_BOOT, ++ "dualmac fw selected for board id: %x\n", board_id); ++ } + + ath12k_core_create_firmware_path(ab, filename, + ab_pci->amss_path, +diff --git a/drivers/net/wireless/ath/ath12k/pci.h b/drivers/net/wireless/ath/ath12k/pci.h +index 7697b54..9a5ec93 100644 +--- a/drivers/net/wireless/ath/ath12k/pci.h ++++ b/drivers/net/wireless/ath/ath12k/pci.h +@@ -53,6 +53,9 @@ + #define WLAON_QFPROM_PWR_CTRL_REG 0x01f8031c + #define QFPROM_PWR_CTRL_VDD4BLOW_MASK 0x4 + ++#define QCN9224_QFPROM_RAW_RFA_PDET_ROW13_LSB 0x1E20338 ++#define OTP_BOARD_ID_MASK GENMASK(15,0) ++ + #define PCI_BAR_WINDOW0_BASE 0x1E00000 + #define PCI_BAR_WINDOW0_END 0x1E7FFFC + #define PCI_SOC_RANGE_MASK 0x3FFF +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/690-ath12k-improve-iterations-over-channel-contexts.patch b/feeds/ipq95xx/mac80211/patches/qca/690-ath12k-improve-iterations-over-channel-contexts.patch new file mode 100644 index 000000000..dce5bb47e --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/690-ath12k-improve-iterations-over-channel-contexts.patch @@ -0,0 +1,158 @@ +From 9443cb736e3e2b8013991dd2152ec56754420109 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Wed, 21 Dec 2022 17:56:44 +0530 +Subject: [PATCH] ath12k: improve iterations over channel contexts for Singly Wiphy + +At various places, there is a need to iterate over channel contexts available +under the hardware. With Single Wiphy architecture, there will be multiple +channel contexts available from various underlying hardwares and hence, there +is a need to have the ar info in the iterator in order to decide whether the +current iterating channel context belongs to the ar under consideration or +not. + +Add modification in the iterator functions to support multi-link operation. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath12k/mac.c | 39 ++++++++++++++++----------- + 1 file changed, 24 insertions(+), 15 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -1225,14 +1225,20 @@ ath12k_mac_get_any_chandef_iter(struct i + struct ieee80211_chanctx_conf *conf, + void *data) + { +- struct cfg80211_chan_def **def = data; ++ struct ath12k_mac_any_chandef_arg *arg = ++ (struct ath12k_mac_any_chandef_arg *)data; ++ struct ath12k *ctx_ar, *ar = arg->ar; + +- *def = &conf->def; ++ ctx_ar = ath12k_get_ar_by_ctx(ar->ah->hw, conf); ++ ++ if (ctx_ar == ar) ++ arg->def = &conf->def; + } + + static int ath12k_mac_monitor_start(struct ath12k *ar) + { +- struct cfg80211_chan_def *chandef = NULL; ++ struct cfg80211_chan_def *chandef; ++ struct ath12k_mac_any_chandef_arg arg = { .ar = ar, .def = NULL}; + int ret; + + lockdep_assert_held(&ar->conf_mutex); +@@ -1242,7 +1248,8 @@ static int ath12k_mac_monitor_start(stru + + ieee80211_iter_chan_contexts_atomic(ar->ah->hw, + ath12k_mac_get_any_chandef_iter, +- &chandef); ++ &arg); ++ chandef = arg.def; + if (!chandef) + return 0; + +@@ -10105,20 +10112,25 @@ static void ath12k_mac_num_chanctxs_iter + struct ieee80211_chanctx_conf *conf, + void *data) + { +- int *num = data; ++ struct ath12k_mac_num_chanctxs_arg *arg = ++ (struct ath12k_mac_num_chanctxs_arg *)data; ++ struct ath12k *ctx_ar, *ar = arg->ar; ++ ++ ctx_ar = ath12k_get_ar_by_ctx(ar->ah->hw, conf); + +- (*num)++; ++ if (ctx_ar == ar) ++ arg->num++; + } + + static int ath12k_mac_num_chanctxs(struct ath12k *ar) + { +- int num = 0; ++ struct ath12k_mac_num_chanctxs_arg arg = { .ar = ar, .num = 0}; + + ieee80211_iter_chan_contexts_atomic(ar->ah->hw, + ath12k_mac_num_chanctxs_iter, +- &num); ++ &arg); + +- return num; ++ return arg.num; + } + + static void ath12k_mac_update_rx_channel(struct ath12k *ar, +@@ -10126,7 +10138,7 @@ static void ath12k_mac_update_rx_channel + struct ieee80211_vif_chanctx_switch *vifs, + int n_vifs) + { +- struct cfg80211_chan_def *def = NULL; ++ struct ath12k_mac_any_chandef_arg arg = { .ar = ar, .def = NULL}; + + /* Both locks are required because ar->rx_channel is modified. This + * allows readers to hold either lock. +@@ -10151,11 +10163,13 @@ static void ath12k_mac_update_rx_channel + if (!ctx && ath12k_mac_num_chanctxs(ar) == 1) { + ieee80211_iter_chan_contexts_atomic(ar->ah->hw, + ath12k_mac_get_any_chandef_iter, +- &def); ++ &arg); + if (vifs) +- def = &vifs[0].new_ctx->def; +- +- ar->rx_channel = def->chan; ++ ar->rx_channel = vifs[0].new_ctx->def.chan; ++ else if (arg.def) ++ ar->rx_channel = arg.def->chan; ++ else ++ ar->rx_channel = NULL; + } else if ((ctx && ath12k_mac_num_chanctxs(ar) == 0) || + (ctx && (ar->state == ATH12K_STATE_RESTARTED))) { + /* During driver restart due to firmware assert, since mac80211 +--- a/drivers/net/wireless/ath/ath12k/mac.h ++++ b/drivers/net/wireless/ath/ath12k/mac.h +@@ -20,6 +20,16 @@ struct ath12k_generic_iter { + int ret; + }; + ++struct ath12k_mac_any_chandef_arg { ++ struct ath12k *ar; ++ struct cfg80211_chan_def *def; ++}; ++ ++struct ath12k_mac_num_chanctxs_arg { ++ struct ath12k *ar; ++ int num; ++}; ++ + /* number of failed packets (20 packets with 16 sw reties each) */ + #define ATH12K_KICKOUT_THRESHOLD (20 * 16) + +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -8322,7 +8322,8 @@ ath12k_wmi_dcs_awgn_interference_event(s + { + const struct wmi_dcs_interference_ev *dcs_intf_ev; + struct wmi_dcs_awgn_info awgn_info = {}; +- struct cfg80211_chan_def *chandef = NULL; ++ struct cfg80211_chan_def *chandef; ++ struct ath12k_mac_any_chandef_arg arg; + struct ath12k *ar; + const struct wmi_tlv *tlv; + struct ath12k_hw *ah; +@@ -8400,8 +8401,12 @@ ath12k_wmi_dcs_awgn_interference_event(s + ath12k_info(ab, "Interface(pdev %d) : AWGN interference detected\n", + dcs_intf_ev->pdev_id); + ++ arg.ar = ar; ++ arg.def = NULL; ++ + ieee80211_iter_chan_contexts_atomic(ah->hw, ath12k_mac_get_any_chandef_iter, +- &chandef); ++ &arg); ++ chandef = arg.def; + if (!chandef) { + ath12k_warn(ab, "chandef is not available\n"); + goto exit; diff --git a/feeds/ipq95xx/mac80211/patches/qca/691-0001-cfg80211-mac80211-add-support-for-channel-switch-wit.patch b/feeds/ipq95xx/mac80211/patches/qca/691-0001-cfg80211-mac80211-add-support-for-channel-switch-wit.patch new file mode 100644 index 000000000..1cd01b7a7 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/691-0001-cfg80211-mac80211-add-support-for-channel-switch-wit.patch @@ -0,0 +1,648 @@ +From 0cc0eb793c13785f2dc7fcada2ad8ef159b67247 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Fri, 16 Dec 2022 14:29:47 +0530 +Subject: [PATCH 1/4] cfg80211/mac80211: add support for channel switch with + MLO + +With Multi-Link Operation (MLO), there is a need to handle link specific +data structres based on the operational link_id during channel switch +operations. + +Add support for the same. Non-MLO based operations will use link_id as +0 or deflink member as applicable. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath10k/mac.c | 2 +- + drivers/net/wireless/ath/ath10k/wmi.c | 2 +- + drivers/net/wireless/ath/ath11k/wmi.c | 2 +- + drivers/net/wireless/ath/ath12k/wmi.c | 2 +- + drivers/net/wireless/ath/ath9k/beacon.c | 2 +- + .../net/wireless/ath/ath9k/htc_drv_beacon.c | 2 +- + drivers/net/wireless/mac80211_hwsim.c | 2 +- + include/net/cfg80211.h | 3 +- + include/net/mac80211.h | 3 +- + net/mac80211/cfg.c | 137 +++++++++++------- + net/mac80211/ibss.c | 2 +- + net/mac80211/ieee80211_i.h | 3 +- + net/mac80211/mesh.c | 2 +- + net/wireless/nl80211.c | 2 +- + net/wireless/rdev-ops.h | 7 +- + net/wireless/trace.h | 12 +- + 16 files changed, 113 insertions(+), 72 deletions(-) + +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -2046,7 +2046,7 @@ static void ath10k_mac_vif_ap_csa_count_ + ath10k_warn(ar, "failed to update prb tmpl during csa: %d\n", + ret); + } else { +- ieee80211_csa_finish(vif); ++ ieee80211_csa_finish(vif, 0); + } + } + +--- a/drivers/net/wireless/ath/ath10k/wmi.c ++++ b/drivers/net/wireless/ath/ath10k/wmi.c +@@ -3884,7 +3884,7 @@ void ath10k_wmi_event_host_swba(struct a + */ + if (arvif->vif->bss_conf.csa_active && + ieee80211_beacon_cntdwn_is_complete(arvif->vif)) { +- ieee80211_csa_finish(arvif->vif); ++ ieee80211_csa_finish(arvif->vif, 0); + continue; + } + +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -9394,7 +9394,7 @@ ath11k_wmi_process_csa_switch_count_even + } + + if (arvif->is_up && arvif->vif->bss_conf.csa_active) +- ieee80211_csa_finish(arvif->vif); ++ ieee80211_csa_finish(arvif->vif, 0); + } + rcu_read_unlock(); + } +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -8052,7 +8052,7 @@ ath12k_wmi_process_csa_switch_count_even + /* FIXME some changes are expected for ML vifs */ + if (arvif->is_up && link_conf->csa_active) { + if (!ev->current_switch_count) +- ieee80211_csa_finish(arvif->ahvif->vif); ++ ieee80211_csa_finish(arvif->ahvif->vif, arvif->link_id); + else if (ev->current_switch_count > 1) + ieee80211_beacon_update_cntdwn(arvif->ahvif->vif); + } +--- a/drivers/net/wireless/ath/ath9k/beacon.c ++++ b/drivers/net/wireless/ath/ath9k/beacon.c +@@ -368,7 +368,7 @@ bool ath9k_csa_is_finished(struct ath_so + if (!ieee80211_beacon_cntdwn_is_complete(vif)) + return false; + +- ieee80211_csa_finish(vif); ++ ieee80211_csa_finish(vif, 0); + return true; + } + +--- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c ++++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +@@ -517,7 +517,7 @@ bool ath9k_htc_csa_is_finished(struct at + if (!ieee80211_beacon_cntdwn_is_complete(vif)) + return false; + +- ieee80211_csa_finish(vif); ++ ieee80211_csa_finish(vif, 0); + + priv->csa_vif = NULL; + return true; +--- a/drivers/net/wireless/mac80211_hwsim.c ++++ b/drivers/net/wireless/mac80211_hwsim.c +@@ -2080,7 +2080,7 @@ static void mac80211_hwsim_beacon_tx(voi + } + + if (link_conf->csa_active && ieee80211_beacon_cntdwn_is_complete(vif)) +- ieee80211_csa_finish(vif); ++ ieee80211_csa_finish(vif, link_id); + } + + static enum hrtimer_restart +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -4672,7 +4672,8 @@ struct cfg80211_ops { + + int (*channel_switch)(struct wiphy *wiphy, + struct net_device *dev, +- struct cfg80211_csa_settings *params); ++ struct cfg80211_csa_settings *params, ++ unsigned int link_id); + + int (*set_qos_map)(struct wiphy *wiphy, + struct net_device *dev, +@@ -6085,6 +6086,7 @@ struct wireless_dev { + struct { + unsigned int beacon_interval; + struct cfg80211_chan_def chandef; ++ bool is_going_down; + } ap; + struct { + struct cfg80211_internal_bss *current_bss; +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -5502,12 +5502,13 @@ void ieee80211_beacon_set_cntdwn(struct + /** + * ieee80211_csa_finish - notify mac80211 about channel switch + * @vif: &struct ieee80211_vif pointer from the add_interface callback. ++ * @link_id: valid link_id during MLO or 0 for non-MLO + * + * After a channel switch announcement was scheduled and the counter in this + * announcement hits 1, this function must be called by the driver to + * notify mac80211 that the channel can be changed. + */ +-void ieee80211_csa_finish(struct ieee80211_vif *vif); ++void ieee80211_csa_finish(struct ieee80211_vif *vif, unsigned int link_id); + + /** + * ieee80211_beacon_cntdwn_is_complete - find out if countdown reached 1 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1616,6 +1616,13 @@ static int ieee80211_stop_ap(struct wiph + + mutex_unlock(&local->mtx); + ++ /* The below work requires sdata lock which we have already acquired ++ * here. But before that, it will check whether link_conf->csa_active ++ * is true, which we have made false above. Hence, it will not proceed ++ * to acquire the sdata lock and deadlock will be avoided. ++ */ ++ cancel_work_sync(&link->csa_finalize_work); ++ + ieee80211_free_next_beacon(link); + + /* turn off carrier for this interface and dependent VLANs */ +@@ -3615,13 +3622,24 @@ error: + return NULL; + } + +-void ieee80211_csa_finish(struct ieee80211_vif *vif) ++void ieee80211_csa_finish(struct ieee80211_vif *vif, unsigned int link_id) + { + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); + struct ieee80211_local *local = sdata->local; ++ struct ieee80211_link_data *link; ++ ++ if (WARN_ON(link_id > IEEE80211_MLD_MAX_NUM_LINKS)) ++ return; + + rcu_read_lock(); + ++ link = rcu_dereference(sdata->link[link_id]); ++ if (WARN_ON(!link)) { ++ rcu_read_unlock(); ++ return; ++ } ++ ++ /* TODO: MBSSID with MLO changes */ + if (vif->mbssid_tx_vif == vif) { + /* Trigger ieee80211_csa_finish() on the non-transmitting + * interfaces when channel switch is received on +@@ -3640,7 +3658,7 @@ void ieee80211_csa_finish(struct ieee802 + &iter->deflink.csa_finalize_work); + } + } +- ieee80211_queue_work(&local->hw, &sdata->deflink.csa_finalize_work); ++ ieee80211_queue_work(&local->hw, &link->csa_finalize_work); + + rcu_read_unlock(); + } +@@ -3658,23 +3676,25 @@ void ieee80211_channel_switch_disconnect + } + EXPORT_SYMBOL(ieee80211_channel_switch_disconnect); + +-static int ieee80211_set_after_csa_beacon(struct ieee80211_sub_if_data *sdata, ++static int ieee80211_set_after_csa_beacon(struct ieee80211_link_data *link, + u32 *changed) + { ++ struct ieee80211_sub_if_data *sdata = link->sdata; + int err; + + switch (sdata->vif.type) { + case NL80211_IFTYPE_AP: +- if (!sdata->deflink.u.ap.next_beacon) ++ if (!link->u.ap.next_beacon) + return -EINVAL; + +- err = ieee80211_assign_beacon(sdata, &sdata->deflink, +- sdata->deflink.u.ap.next_beacon, ++ err = ieee80211_assign_beacon(sdata, link, ++ link->u.ap.next_beacon, + NULL, NULL); +- ieee80211_free_next_beacon(&sdata->deflink); ++ ieee80211_free_next_beacon(link); + + if (err < 0) + return err; ++ + *changed |= err; + break; + case NL80211_IFTYPE_ADHOC: +@@ -3699,9 +3719,11 @@ static int ieee80211_set_after_csa_beaco + return 0; + } + +-static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata) ++static int __ieee80211_csa_finalize(struct ieee80211_link_data *link) + { ++ struct ieee80211_sub_if_data *sdata = link->sdata; + struct ieee80211_local *local = sdata->local; ++ struct ieee80211_bss_conf *link_conf = link->conf; + u32 changed = 0; + int err; + +@@ -3716,49 +3738,54 @@ static int __ieee80211_csa_finalize(stru + * completed successfully + */ + +- if (sdata->deflink.reserved_chanctx) { ++ if (link->reserved_chanctx) { + /* + * with multi-vif csa driver may call ieee80211_csa_finish() + * many times while waiting for other interfaces to use their + * reservations + */ +- if (sdata->deflink.reserved_ready) ++ if (link->reserved_ready) + return 0; + +- return ieee80211_link_use_reserved_context(&sdata->deflink); ++ return ieee80211_link_use_reserved_context(link); + } + +- if (!cfg80211_chandef_identical(&sdata->vif.bss_conf.chandef, +- &sdata->deflink.csa_chandef)) ++ if (!cfg80211_chandef_identical(&link_conf->chandef, ++ &link->csa_chandef)) + return -EINVAL; + +- sdata->vif.bss_conf.csa_active = false; ++ link_conf->csa_active = false; + +- err = ieee80211_set_after_csa_beacon(sdata, &changed); ++ err = ieee80211_set_after_csa_beacon(link, &changed); + if (err) + return err; + +- ieee80211_link_info_change_notify(sdata, &sdata->deflink, changed); ++ ieee80211_link_info_change_notify(sdata, link, changed); + +- if (sdata->deflink.csa_block_tx) { ++ if (link->csa_block_tx) { + ieee80211_wake_vif_queues(local, sdata, + IEEE80211_QUEUE_STOP_REASON_CSA); +- sdata->deflink.csa_block_tx = false; ++ link->csa_block_tx = false; + } + ++ /* should we pass link_id here */ + err = drv_post_channel_switch(sdata); + if (err) + return err; + +- cfg80211_ch_switch_notify(sdata->dev, &sdata->deflink.csa_chandef, 0); ++ cfg80211_ch_switch_notify(sdata->dev, &link->csa_chandef, ++ link->link_id); + + return 0; + } + +-static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata) ++static void ieee80211_csa_finalize(struct ieee80211_link_data *link) + { +- if (__ieee80211_csa_finalize(sdata)) { +- sdata_info(sdata, "failed to finalize CSA, disconnecting\n"); ++ struct ieee80211_sub_if_data *sdata = link->sdata; ++ ++ if (__ieee80211_csa_finalize(link)) { ++ sdata_info(sdata, "failed to finalize CSA on link_id %d, disconnecting\n", ++ link->link_id); + cfg80211_stop_iface(sdata->local->hw.wiphy, &sdata->wdev, + GFP_KERNEL); + } +@@ -3766,23 +3793,32 @@ static void ieee80211_csa_finalize(struc + + void ieee80211_csa_finalize_work(struct work_struct *work) + { +- struct ieee80211_sub_if_data *sdata = +- container_of(work, struct ieee80211_sub_if_data, +- deflink.csa_finalize_work); ++ struct ieee80211_link_data *link = ++ container_of(work, struct ieee80211_link_data, ++ csa_finalize_work); ++ struct ieee80211_sub_if_data *sdata = link->sdata; + struct ieee80211_local *local = sdata->local; ++ struct ieee80211_bss_conf *link_conf = link->conf; ++ struct wireless_dev *wdev = &sdata->wdev; ++ ++ /* If is_going_down flag is set, this means that this link is going ++ * to get removed hence no point in proceeding further ++ */ ++ if (wdev->links[link->link_id].ap.is_going_down) ++ return; + + sdata_lock(sdata); + mutex_lock(&local->mtx); + mutex_lock(&local->chanctx_mtx); + + /* AP might have been stopped while waiting for the lock. */ +- if (!sdata->vif.bss_conf.csa_active) ++ if (!link_conf->csa_active) + goto unlock; + + if (!ieee80211_sdata_running(sdata)) + goto unlock; + +- ieee80211_csa_finalize(sdata); ++ ieee80211_csa_finalize(link); + + unlock: + mutex_unlock(&local->chanctx_mtx); +@@ -3790,18 +3826,19 @@ unlock: + sdata_unlock(sdata); + } + +-static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata, ++static int ieee80211_set_csa_beacon(struct ieee80211_link_data *link, + struct cfg80211_csa_settings *params, + u32 *changed) + { ++ struct ieee80211_sub_if_data *sdata = link->sdata; + struct ieee80211_csa_settings csa = {}; + int err; + + switch (sdata->vif.type) { + case NL80211_IFTYPE_AP: +- sdata->deflink.u.ap.next_beacon = ++ link->u.ap.next_beacon = + cfg80211_beacon_dup(¶ms->beacon_after); +- if (!sdata->deflink.u.ap.next_beacon) ++ if (!link->u.ap.next_beacon) + return -ENOMEM; + + /* +@@ -3827,7 +3864,7 @@ static int ieee80211_set_csa_beacon(stru + IEEE80211_MAX_CNTDWN_COUNTERS_NUM) || + (params->n_counter_offsets_presp > + IEEE80211_MAX_CNTDWN_COUNTERS_NUM)) { +- ieee80211_free_next_beacon(&sdata->deflink); ++ ieee80211_free_next_beacon(link); + return -EINVAL; + } + +@@ -3837,13 +3874,14 @@ static int ieee80211_set_csa_beacon(stru + csa.n_counter_offsets_presp = params->n_counter_offsets_presp; + csa.count = params->count; + +- err = ieee80211_assign_beacon(sdata, &sdata->deflink, ++ err = ieee80211_assign_beacon(sdata, link, + ¶ms->beacon_csa, &csa, + NULL); + if (err < 0) { +- ieee80211_free_next_beacon(&sdata->deflink); ++ ieee80211_free_next_beacon(link); + return err; + } ++ + *changed |= err; + + break; +@@ -3936,13 +3974,16 @@ static void ieee80211_color_change_abort + + static int + __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, +- struct cfg80211_csa_settings *params) ++ struct cfg80211_csa_settings *params, ++ unsigned int link_id) + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; + struct ieee80211_channel_switch ch_switch; + struct ieee80211_chanctx_conf *conf; + struct ieee80211_chanctx *chanctx; ++ struct ieee80211_bss_conf *link_conf; ++ struct ieee80211_link_data *link; + u32 changed = 0; + int err; + +@@ -3955,16 +3996,21 @@ __ieee80211_channel_switch(struct wiphy + if (sdata->wdev.cac_started) + return -EBUSY; + +- if (cfg80211_chandef_identical(¶ms->chandef, +- &sdata->vif.bss_conf.chandef)) ++ link = sdata_dereference(sdata->link[link_id], sdata); ++ if (!link) ++ return -ENOLINK; ++ ++ link_conf = link->conf; ++ ++ if (cfg80211_chandef_identical(¶ms->chandef, &link_conf->chandef)) + return -EINVAL; + + /* don't allow another channel switch if one is already active. */ +- if (sdata->vif.bss_conf.csa_active) ++ if (link_conf->csa_active) + return -EBUSY; + + mutex_lock(&local->chanctx_mtx); +- conf = rcu_dereference_protected(sdata->vif.bss_conf.chanctx_conf, ++ conf = rcu_dereference_protected(link_conf->chanctx_conf, + lockdep_is_held(&local->chanctx_mtx)); + if (!conf) { + err = -EBUSY; +@@ -3985,11 +4031,12 @@ __ieee80211_channel_switch(struct wiphy + ch_switch.chandef = params->chandef; + ch_switch.count = params->count; + ++ /* should we pass link_id here ? */ + err = drv_pre_channel_switch(sdata, &ch_switch); + if (err) + goto out; + +- err = ieee80211_link_reserve_chanctx(&sdata->deflink, ¶ms->chandef, ++ err = ieee80211_link_reserve_chanctx(link, ¶ms->chandef, + chanctx->mode, + params->radar_required); + if (err) +@@ -3998,39 +4045,40 @@ __ieee80211_channel_switch(struct wiphy + /* if reservation is invalid then this will fail */ + err = ieee80211_check_combinations(sdata, NULL, chanctx->mode, 0); + if (err) { +- ieee80211_link_unreserve_chanctx(&sdata->deflink); ++ ieee80211_link_unreserve_chanctx(link); + goto out; + } + + /* if there is a color change in progress, abort it */ +- if (sdata->vif.bss_conf.color_change_active) ++ if (link_conf->color_change_active) + ieee80211_color_change_abort(sdata); + +- err = ieee80211_set_csa_beacon(sdata, params, &changed); ++ err = ieee80211_set_csa_beacon(link, params, &changed); + if (err) { +- ieee80211_link_unreserve_chanctx(&sdata->deflink); ++ ieee80211_link_unreserve_chanctx(link); + goto out; + } + +- sdata->deflink.csa_chandef = params->chandef; +- sdata->deflink.csa_block_tx = params->block_tx; +- sdata->vif.bss_conf.csa_active = true; ++ link->csa_chandef = params->chandef; ++ link->csa_block_tx = params->block_tx; ++ link_conf->csa_active = true; + +- if (sdata->deflink.csa_block_tx) ++ if (link->csa_block_tx) + ieee80211_stop_vif_queues(local, sdata, + IEEE80211_QUEUE_STOP_REASON_CSA); + + cfg80211_ch_switch_started_notify(sdata->dev, +- &sdata->deflink.csa_chandef, 0, ++ &link->csa_chandef, link_id, + params->count, params->block_tx); + + if (changed) { +- ieee80211_link_info_change_notify(sdata, &sdata->deflink, ++ ieee80211_link_info_change_notify(sdata, link, + changed); ++ /* link_id to be passed here? */ + drv_channel_switch_beacon(sdata, ¶ms->chandef); + } else { + /* if the beacon didn't change, we can finalize immediately */ +- ieee80211_csa_finalize(sdata); ++ ieee80211_csa_finalize(link); + } + + out: +@@ -4039,14 +4087,15 @@ out: + } + + int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, +- struct cfg80211_csa_settings *params) ++ struct cfg80211_csa_settings *params, ++ unsigned int link_id) + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; + int err; + + mutex_lock(&local->mtx); +- err = __ieee80211_channel_switch(wiphy, dev, params); ++ err = __ieee80211_channel_switch(wiphy, dev, params, link_id); + mutex_unlock(&local->mtx); + + return err; +--- a/net/mac80211/ibss.c ++++ b/net/mac80211/ibss.c +@@ -882,7 +882,7 @@ ieee80211_ibss_process_chanswitch(struct + params.block_tx = !!csa_ie.mode; + + if (ieee80211_channel_switch(sdata->local->hw.wiphy, sdata->dev, +- ¶ms)) ++ ¶ms, 0)) + goto disconnect; + + ieee80211_ibss_csa_mark_radar(sdata); +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1944,7 +1944,8 @@ int ieee80211_mgmt_tx_cancel_wait(struct + /* channel switch handling */ + void ieee80211_csa_finalize_work(struct work_struct *work); + int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, +- struct cfg80211_csa_settings *params); ++ struct cfg80211_csa_settings *params, ++ unsigned int link_id); + /* awgn interference handling */ + void ieee80211_awgn_interference_detected_work(struct work_struct *work); + +--- a/net/mac80211/mesh.c ++++ b/net/mac80211/mesh.c +@@ -1337,7 +1337,7 @@ ieee80211_mesh_process_chnswitch(struct + ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_REPEATER; + + if (ieee80211_channel_switch(sdata->local->hw.wiphy, sdata->dev, +- ¶ms) < 0) ++ ¶ms, 0) < 0) + return false; + + return true; +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -6586,6 +6586,8 @@ static int nl80211_start_ap(struct sk_bu + + if (info->attrs[NL80211_ATTR_SOCKET_OWNER]) + wdev->conn_owner_nlportid = info->snd_portid; ++ ++ wdev->links[link_id].ap.is_going_down = false; + } + out_unlock: + wdev_unlock(wdev); +@@ -10699,7 +10701,7 @@ skip_beacons: + params.block_tx = true; + + wdev_lock(wdev); +- err = rdev_channel_switch(rdev, dev, ¶ms); ++ err = rdev_channel_switch(rdev, dev, ¶ms, link_id); + wdev_unlock(wdev); + + free: +--- a/net/wireless/rdev-ops.h ++++ b/net/wireless/rdev-ops.h +@@ -1087,12 +1087,13 @@ static inline void rdev_crit_proto_stop( + + static inline int rdev_channel_switch(struct cfg80211_registered_device *rdev, + struct net_device *dev, +- struct cfg80211_csa_settings *params) ++ struct cfg80211_csa_settings *params, ++ unsigned int link_id) + { + int ret; + +- trace_rdev_channel_switch(&rdev->wiphy, dev, params); +- ret = rdev->ops->channel_switch(&rdev->wiphy, dev, params); ++ trace_rdev_channel_switch(&rdev->wiphy, dev, params, link_id); ++ ret = rdev->ops->channel_switch(&rdev->wiphy, dev, params, link_id); + trace_rdev_return_int(&rdev->wiphy, ret); + return ret; + } +--- a/net/wireless/trace.h ++++ b/net/wireless/trace.h +@@ -2302,8 +2302,9 @@ TRACE_EVENT(rdev_crit_proto_stop, + + TRACE_EVENT(rdev_channel_switch, + TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, +- struct cfg80211_csa_settings *params), +- TP_ARGS(wiphy, netdev, params), ++ struct cfg80211_csa_settings *params, ++ unsigned int link_id), ++ TP_ARGS(wiphy, netdev, params, link_id), + TP_STRUCT__entry( + WIPHY_ENTRY + NETDEV_ENTRY +@@ -2313,6 +2314,7 @@ TRACE_EVENT(rdev_channel_switch, + __field(u8, count) + __dynamic_array(u16, bcn_ofs, params->n_counter_offsets_beacon) + __dynamic_array(u16, pres_ofs, params->n_counter_offsets_presp) ++ __field(unsigned int, link_id) + ), + TP_fast_assign( + WIPHY_ASSIGN; +@@ -2330,11 +2332,13 @@ TRACE_EVENT(rdev_channel_switch, + memcpy(__get_dynamic_array(pres_ofs), + params->counter_offsets_presp, + params->n_counter_offsets_presp * sizeof(u16)); ++ __entry->link_id = link_id; + ), + TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT +- ", block_tx: %d, count: %u, radar_required: %d", ++ ", block_tx: %d, count: %u, radar_required: %d link_id: %d", + WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG, +- __entry->block_tx, __entry->count, __entry->radar_required) ++ __entry->block_tx, __entry->count, __entry->radar_required, ++ __entry->link_id) + ); + + TRACE_EVENT(rdev_set_qos_map, +--- a/net/wireless/ap.c ++++ b/net/wireless/ap.c +@@ -20,6 +20,8 @@ static int ___cfg80211_stop_ap(struct cf + + ASSERT_WDEV_LOCK(wdev); + ++ wdev->links[link_id].ap.is_going_down = true; ++ + if (!rdev->ops->stop_ap) + return -EOPNOTSUPP; + diff --git a/feeds/ipq95xx/mac80211/patches/qca/691-0002-cfg80211-mac80211-update-beacon-counters-per-link-ba.patch b/feeds/ipq95xx/mac80211/patches/qca/691-0002-cfg80211-mac80211-update-beacon-counters-per-link-ba.patch new file mode 100644 index 000000000..e95d120f8 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/691-0002-cfg80211-mac80211-update-beacon-counters-per-link-ba.patch @@ -0,0 +1,124 @@ +From 3af2c38ed41122d10b576608d567b2b94b71ddcf Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Fri, 16 Dec 2022 14:52:42 +0530 +Subject: [PATCH 2/4] cfg80211/mac80211: update beacon counters per link basis + +Currently, function to update beacon counter uses deflink to fetch +the beacon and then update the counter. However, with MLO, there is +a need to update the counter for the beacon in a particular link. + +Add support to use link_id in order to fetch the beacon from a particular +sdata during beacon update counter. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath10k/mac.c | 2 +- + drivers/net/wireless/ath/ath11k/mac.c | 2 +- + drivers/net/wireless/ath/ath12k/mac.c | 2 +- + drivers/net/wireless/ath/ath12k/wmi.c | 3 ++- + include/net/mac80211.h | 3 ++- + net/mac80211/tx.c | 17 +++++++++++++---- + 6 files changed, 20 insertions(+), 9 deletions(-) + +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -2034,7 +2034,7 @@ static void ath10k_mac_vif_ap_csa_count_ + return; + + if (!ieee80211_beacon_cntdwn_is_complete(vif)) { +- ieee80211_beacon_update_cntdwn(vif); ++ ieee80211_beacon_update_cntdwn(vif, 0); + + ret = ath10k_mac_setup_bcn_tmpl(arvif); + if (ret) +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -1793,7 +1793,7 @@ void ath11k_mac_bcn_tx_event(struct ath1 + arvif->bcca_zero_sent = false; + + if (vif->bss_conf.color_change_active) +- ieee80211_beacon_update_cntdwn(vif); ++ ieee80211_beacon_update_cntdwn(vif, 0); + ath11k_mac_setup_bcn_tmpl(arvif); + } + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -1622,7 +1622,7 @@ void ath12k_mac_bcn_tx_event(struct ath1 + arvif->bcca_zero_sent = false; + + if (link_conf->color_change_active) +- ieee80211_beacon_update_cntdwn(vif); ++ ieee80211_beacon_update_cntdwn(vif, 0); + ieee80211_queue_work(ar->ah->hw, &arvif->update_bcn_template_work); + } + +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -8054,7 +8054,8 @@ ath12k_wmi_process_csa_switch_count_even + if (!ev->current_switch_count) + ieee80211_csa_finish(arvif->ahvif->vif, arvif->link_id); + else if (ev->current_switch_count > 1) +- ieee80211_beacon_update_cntdwn(arvif->ahvif->vif); ++ ieee80211_beacon_update_cntdwn(arvif->ahvif->vif, ++ arvif->link_id); + } + } + rcu_read_unlock(); +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -5475,6 +5475,7 @@ static inline struct sk_buff *ieee80211_ + /** + * ieee80211_beacon_update_cntdwn - request mac80211 to decrement the beacon countdown + * @vif: &struct ieee80211_vif pointer from the add_interface callback. ++ * @link_id: valid link_id during MLO or 0 for non-MLO + * + * The beacon counter should be updated after each beacon transmission. + * This function is called implicitly when +@@ -5484,7 +5485,7 @@ static inline struct sk_buff *ieee80211_ + * + * Return: new countdown value + */ +-u8 ieee80211_beacon_update_cntdwn(struct ieee80211_vif *vif); ++u8 ieee80211_beacon_update_cntdwn(struct ieee80211_vif *vif, unsigned int link_id); + + /** + * ieee80211_beacon_set_cntdwn - request mac80211 to set beacon countdown +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -5244,16 +5244,24 @@ static u8 __ieee80211_beacon_update_cntd + return beacon->cntdwn_current_counter; + } + +-u8 ieee80211_beacon_update_cntdwn(struct ieee80211_vif *vif) ++u8 ieee80211_beacon_update_cntdwn(struct ieee80211_vif *vif, unsigned int link_id) + { + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); ++ struct ieee80211_link_data *link; + struct beacon_data *beacon = NULL; + u8 count = 0; + ++ if (WARN_ON(link_id > IEEE80211_MLD_MAX_NUM_LINKS)) ++ return 0; ++ + rcu_read_lock(); + ++ link = rcu_dereference(sdata->link[link_id]); ++ if (!link) ++ goto unlock; ++ + if (sdata->vif.type == NL80211_IFTYPE_AP) +- beacon = rcu_dereference(sdata->deflink.u.ap.beacon); ++ beacon = rcu_dereference(link->u.ap.beacon); + else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) + beacon = rcu_dereference(sdata->u.ibss.presp); + else if (ieee80211_vif_is_mesh(&sdata->vif)) +@@ -5508,7 +5516,7 @@ ieee80211_beacon_get_ap(struct ieee80211 + + if (beacon->cntdwn_counter_offsets[0]) { + if (!is_template) +- ieee80211_beacon_update_cntdwn(vif); ++ ieee80211_beacon_update_cntdwn(vif, link->link_id); + + ieee80211_set_beacon_cntdwn(sdata, beacon, link); + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/691-0003-mac80211-add-Critical-Update-support.patch b/feeds/ipq95xx/mac80211/patches/qca/691-0003-mac80211-add-Critical-Update-support.patch new file mode 100644 index 000000000..843457dc6 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/691-0003-mac80211-add-Critical-Update-support.patch @@ -0,0 +1,137 @@ +From b16b014b15d9e25d62a75e684087ab4ac2085acf Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Fri, 16 Dec 2022 16:30:08 +0530 +Subject: [PATCH 3/4] mac80211: add Critical Update support + +Critical Update (CU) is the explicit signaling for STA to notify any change +in BSS parameters, so that other STAs which are part of the same BSS +can take the corresponding action. + +Add support to handle critical update and update the appropriate flags to +notify the driver about the same. + +Currently, CU support is added for Channel Switch Annoucnement (CSA). + +Signed-off-by: Aditya Kumar Singh +--- + include/linux/ieee80211.h | 66 +++++++++++++++++++++++++++++++++++++++ + include/net/mac80211.h | 5 +++ + net/mac80211/cfg.c | 6 ++++ + 3 files changed, 77 insertions(+) + +--- a/include/linux/ieee80211.h ++++ b/include/linux/ieee80211.h +@@ -4716,4 +4716,70 @@ struct ieee80211_mle_per_sta_profile { + _data + ieee80211_mle_common_size(_data),\ + _len - ieee80211_mle_common_size(_data)) + ++/** ++ * enum ieee80211_critical_updates - Critical Update (CU) flags ++ * ++ * These flags are used to indicate the type of critical update happening ++ * on a link in an interface. ++ * ++ * @IEEE80211_CU_INCLUDE_CSA_ELEM: critical update due to inclusion of a Channel ++ * Switch Announcement element. ++ * @IEEE80211_CU_INCLUDE_ECSA_ELEM: critical update due to inclusion of an ++ * Extended Channel Switch Announcement element. ++ * @IEEE80211_CU_MODIFY_EDCA_PARAM_ELEM: critical update due to modification of ++ * the EDCA parameters element. ++ * @IEEE80211_CU_INCLUDE_QUIET_ELEM: critical update due to inclusion of a Quiet ++ * element. ++ * @IEEE80211_CU_MODIFY_DSSS_PARAM_ELEM: critical update due to modification of ++ * the DSSS Parameter Set. ++ * @IEEE80211_CU_MODIFY_HT_OPER_ELEM: critical update due to modification of the ++ * HT Operation element ++ * @IEEE80211_CU_INCLUDE_WBCS_ELEM: critical update due to inclusion of a Wide ++ * Bandwidth Channel Switch element. ++ * @IEEE80211_CU_INCLUDE_CSW_ELEM: critical update due to inclusion of a Channel ++ * Switch Wrapper element. ++ * @IEEE80211_CU_INCLUDE_OMN_ELEM: critical update due to inclusion of an ++ * Operating Mode Notification element. ++ * @IEEE80211_CU_INCLUDE_Q_CHAN_ELEM: critical update due to inclusion of a ++ * Quiet Channel element. ++ * @IEEE80211_CU_MODIFY_VHT_OPER_ELEM: critical update due to modification of the ++ * VHT Operation element. ++ * @IEEE80211_CU_MODIFY_HE_OPER_ELEM: critical update due to modification of the ++ * HE Operation element. ++ * @IEEE80211_CU_INCLUDE_B_TWT_ELEM: critical update due to inclusion a ++ * Broadcast TWT element. ++ * @IEEE80211_CU_INCLUDE_B_TWT_EXIST_ELEM: critical update due to inclusion of a ++ * Broadcast TWT Parameter Set field in an existing Broadcast TWT element. ++ * @IEEE80211_CU_INCLUDE_BCCA_ELEM: critical update due to inclusion of the BSS ++ * Color Change Announcement element. ++ * @IEEE80211_CU_MODIFY_MU_EDCA_PARAM_ELEM: critical update due to modification ++ * of the MU EDCA Parameter Set element. ++ * @IEEE80211_CU_MODIFY_SR_PARAM_ELEM: critical update due to modification of the ++ * Spatial Reuse Parameter Set element. ++ * @IEEE80211_CU_MODIFY_UORA_PARAM_ELEM: critical update due to modification of ++ * the UORA Parameter Set element. ++ * @IEEE80211_CU_MODIFY_EHT_OPER_ELEM: critical update due to modification of the ++ * EHT Operation element. ++ */ ++enum ieee80211_critical_updates { ++ IEEE80211_CU_INCLUDE_CSA_ELEM = 1 << 0, ++ IEEE80211_CU_INCLUDE_ECSA_ELEM = 1 << 1, ++ IEEE80211_CU_MODIFY_EDCA_PARAM_ELEM = 1 << 2, ++ IEEE80211_CU_INCLUDE_QUIET_ELEM = 1 << 3, ++ IEEE80211_CU_MODIFY_DSSS_PARAM_ELEM = 1 << 4, ++ IEEE80211_CU_MODIFY_HT_OPER_ELEM = 1 << 5, ++ IEEE80211_CU_INCLUDE_WBCS_ELEM = 1 << 6, ++ IEEE80211_CU_INCLUDE_CSW_ELEM = 1 << 7, ++ IEEE80211_CU_INCLUDE_OMN_ELEM = 1 << 8, ++ IEEE80211_CU_INCLUDE_Q_CHAN_ELEM = 1 << 9, ++ IEEE80211_CU_MODIFY_VHT_OPER_ELEM = 1 << 10, ++ IEEE80211_CU_MODIFY_HE_OPER_ELEM = 1 << 11, ++ IEEE80211_CU_INCLUDE_B_TWT_ELEM = 1 << 12, ++ IEEE80211_CU_INCLUDE_B_TWT_EXIST_ELEM = 1 << 13, ++ IEEE80211_CU_INCLUDE_BCCA_ELEM = 1 << 14, ++ IEEE80211_CU_MODIFY_MU_EDCA_PARAM_ELEM = 1 << 15, ++ IEEE80211_CU_MODIFY_SR_PARAM_ELEM = 1 << 16, ++ IEEE80211_CU_MODIFY_UORA_PARAM_ELEM = 1 << 17, ++ IEEE80211_CU_MODIFY_EHT_OPER_ELEM = 1 << 18, ++}; + #endif /* LINUX_IEEE80211_H */ +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -690,6 +690,8 @@ struct ieee80211_fils_discovery { + * @beacon_tx_mode: Beacon Tx Mode setting. + * @eht_oper: EHT operation information of the BSS (AP/Mesh) or of the AP we + * are connected to (STA) ++ * @critical_update_flag: indicates any Critical update going on in the BSS. ++ * see &enum ieee80211_critical_updates + */ + struct ieee80211_bss_conf { + const u8 *bssid; +@@ -788,6 +790,9 @@ struct ieee80211_bss_conf { + u8 nss_offld_ttl; + bool nss_offld_mesh_forward_enabled; + u32 nss_offld_mpath_refresh_time; ++ ++ /* Critical Update flag*/ ++ u32 critical_update_flag; + }; + + /** +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -3676,6 +3676,9 @@ static int ieee80211_set_after_csa_beaco + if (err < 0) + return err; + ++ link->conf->critical_update_flag &= ++ ~(IEEE80211_CU_INCLUDE_CSA_ELEM | ++ IEEE80211_CU_INCLUDE_ECSA_ELEM); + *changed |= err; + break; + case NL80211_IFTYPE_ADHOC: +@@ -3856,6 +3859,9 @@ static int ieee80211_set_csa_beacon(stru + return err; + } + ++ link->conf->critical_update_flag |= ++ (IEEE80211_CU_INCLUDE_CSA_ELEM | ++ IEEE80211_CU_INCLUDE_ECSA_ELEM); + *changed |= err; + + break; diff --git a/feeds/ipq95xx/mac80211/patches/qca/691-0004-ath12k-add-critical-update-support-during-set-beacon.patch b/feeds/ipq95xx/mac80211/patches/qca/691-0004-ath12k-add-critical-update-support-during-set-beacon.patch new file mode 100644 index 000000000..c007ca2a8 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/691-0004-ath12k-add-critical-update-support-during-set-beacon.patch @@ -0,0 +1,313 @@ +From ad203b17b874e56df722af350423f26e27cb7a4e Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Fri, 16 Dec 2022 17:15:44 +0530 +Subject: [PATCH 4/4] ath12k: add critical update support during set beacon + template + +Critical Update (CU) is the explicit signaling for STA to notify any change +in BSS parameters, so that other STAs which are part of the same BSS +can take the corresponding action. + +To indicate Critical Update during beacon template formation, two new TLV +tags - WMI_TAG_BCN_TMPL_ML_INFO_CMD and WMI_TAG_BCN_TMPL_ML_PARAMS_CMD +are introduced via which driver can let the target know about it. + +WMI_TAG_BCN_TMPL_ML_PARAMS_CMD tag provides info about the partner links +where as WMI_TAG_BCN_TMPL_ML_INFO_CMD provides info about the impacted link. + +Add support fill these new TLV tags during send beacon template event in +order to indicate CU to the target. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath12k/mac.h | 23 ++++ + drivers/net/wireless/ath/ath12k/wmi.c | 148 +++++++++++++++++++++++++- + drivers/net/wireless/ath/ath12k/wmi.h | 35 ++++++ + 3 files changed, 205 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.h ++++ b/drivers/net/wireless/ath/ath12k/mac.h +@@ -138,6 +138,29 @@ struct ath12k_mac_num_chanctxs_arg { + #define ATH12K_OBSS_PD_SRG_EN BIT(30) + #define ATH12K_OBSS_PD_NON_SRG_EN BIT(31) + ++/* Critical Update Category 1 : Inclusion of new IEs */ ++#define ATH12K_CRITICAL_UPDATE_CAT_1 (IEEE80211_CU_INCLUDE_CSA_ELEM | \ ++ IEEE80211_CU_INCLUDE_ECSA_ELEM | \ ++ IEEE80211_CU_INCLUDE_QUIET_ELEM | \ ++ IEEE80211_CU_INCLUDE_WBCS_ELEM | \ ++ IEEE80211_CU_INCLUDE_CSW_ELEM | \ ++ IEEE80211_CU_INCLUDE_OMN_ELEM | \ ++ IEEE80211_CU_INCLUDE_Q_CHAN_ELEM | \ ++ IEEE80211_CU_INCLUDE_B_TWT_ELEM |\ ++ IEEE80211_CU_INCLUDE_B_TWT_EXIST_ELEM | \ ++ IEEE80211_CU_INCLUDE_BCCA_ELEM) ++ ++/* Critical Update Category 2 : Modification of existing IEs */ ++#define ATH12K_CRITICAL_UPDATE_CAT_2 (IEEE80211_CU_MODIFY_EDCA_PARAM_ELEM | \ ++ IEEE80211_CU_MODIFY_DSSS_PARAM_ELEM | \ ++ IEEE80211_CU_MODIFY_HT_OPER_ELEM | \ ++ IEEE80211_CU_MODIFY_VHT_OPER_ELEM | \ ++ IEEE80211_CU_MODIFY_HE_OPER_ELEM | \ ++ IEEE80211_CU_MODIFY_MU_EDCA_PARAM_ELEM | \ ++ IEEE80211_CU_MODIFY_SR_PARAM_ELEM | \ ++ IEEE80211_CU_MODIFY_UORA_PARAM_ELEM | \ ++ IEEE80211_CU_MODIFY_EHT_OPER_ELEM) ++ + extern const struct htt_rx_ring_tlv_filter ath12k_mac_mon_status_filter_default; + + void ath12k_mac_ap_ps_recalc(struct ath12k *ar); +@@ -182,5 +205,6 @@ struct ath12k *ath12k_get_ar_by_vif(stru + int ath12k_mac_mlo_setup(struct ath12k_hw *ah); + int ath12k_mac_mlo_ready(struct ath12k_hw *ah); + int ath12k_mac_mlo_teardown(struct ath12k_hw *ah); ++struct ieee80211_bss_conf *ath12k_get_link_bss_conf(struct ath12k_link_vif *arvif); + bool ath12k_mac_is_ml_arvif(struct ath12k_link_vif *arvif); + #endif +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -1833,6 +1833,134 @@ int ath12k_wmi_send_bcn_offload_control_ + return ret; + } + ++static void ath12k_wmi_bcn_fill_ml_info(struct ath12k_link_vif *arvif, ++ struct wmi_bcn_tmpl_ml_info *ml_info) ++{ ++ struct ath12k_base *ab = arvif->ar->ab; ++ struct ieee80211_bss_conf *link_conf; ++ u32 cu_flags; ++ u32 vdev_id = arvif->vdev_id; ++ u64 vdev_map_cat1 = 0; ++ u64 vdev_map_cat2 = 0; ++ ++ rcu_read_lock(); ++ ++ link_conf = ath12k_get_link_bss_conf(arvif); ++ if (!link_conf) { ++ rcu_read_unlock(); ++ goto err_fill_ml_info; ++ } ++ ++ cu_flags = link_conf->critical_update_flag; ++ rcu_read_unlock(); ++ ++ ml_info->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_BCN_TMPL_ML_INFO_CMD, ++ sizeof(*ml_info)); ++ ml_info->hw_link_id = cpu_to_le32(arvif->ar->pdev->hw_link_id); ++ ++ if (cu_flags & ATH12K_CRITICAL_UPDATE_CAT_1) ++ set_bit(vdev_id, &vdev_map_cat1); ++ ++ if (cu_flags & ATH12K_CRITICAL_UPDATE_CAT_2) ++ set_bit(vdev_id, &vdev_map_cat2); ++ ++err_fill_ml_info: ++ ml_info->cu_vdev_map_cat1_lo = ++ cpu_to_le32(ATH12K_GET_LOWER_32_BITS(vdev_map_cat1)); ++ ml_info->cu_vdev_map_cat1_hi = ++ cpu_to_le32(ATH12K_GET_UPPER_32_BITS(vdev_map_cat1)); ++ ml_info->cu_vdev_map_cat2_lo = ++ cpu_to_le32(ATH12K_GET_LOWER_32_BITS(vdev_map_cat2)); ++ ml_info->cu_vdev_map_cat2_hi = ++ cpu_to_le32(ATH12K_GET_UPPER_32_BITS(vdev_map_cat2)); ++ ++ ath12k_dbg(ab, ATH12K_DBG_WMI, ++ "wmi CU filled ml info cat1_lo=0x%x cat1_hi=0x%x cat2_lo=0x%x cat2_hi=0x%x\n", ++ ml_info->cu_vdev_map_cat1_lo, ml_info->cu_vdev_map_cat1_hi, ++ ml_info->cu_vdev_map_cat2_lo, ml_info->cu_vdev_map_cat2_hi); ++} ++ ++static void ath12k_wmi_fill_cu_arg(struct ath12k_link_vif *arvif, ++ struct wmi_critical_update_arg *cu_arg) ++{ ++ struct ath12k_base *ab = arvif->ar->ab; ++ struct wmi_bcn_tmpl_ml_info *ml_info; ++ int i; ++ ++ if (!ath12k_mac_is_ml_arvif(arvif)) ++ return; ++ ++ /* Fill ML params ++ * ML params should be filled for all partner links ++ */ ++ cu_arg->num_ml_params = 0; ++ /* TODO: Fill ML params. Will work without this info too */ ++ ++ /* Fill ML info ++ * ML info should be filled for impacted link only ++ */ ++ cu_arg->num_ml_info = 1; ++ cu_arg->ml_info = (struct wmi_bcn_tmpl_ml_info *) ++ kzalloc((cu_arg->num_ml_info * sizeof(*ml_info)), ++ GFP_KERNEL); ++ ++ if (!cu_arg->ml_info) { ++ ath12k_warn(ab, "wmi failed to get memory for ml info"); ++ cu_arg->num_ml_info = 0; ++ } else { ++ for (i = 0; i < cu_arg->num_ml_info; i++) { ++ ml_info = &cu_arg->ml_info[i]; ++ ath12k_wmi_bcn_fill_ml_info(arvif, ml_info); ++ } ++ } ++} ++ ++static void * ++ath12k_wmi_append_critical_update_params(struct ath12k *ar, u32 vdev_id, ++ void *ptr, ++ struct wmi_critical_update_arg *cu_arg) ++{ ++ struct wmi_bcn_tmpl_ml_params *ml_params; ++ struct wmi_bcn_tmpl_ml_info *ml_info; ++ void *start = ptr; ++ struct wmi_tlv *tlv; ++ size_t ml_params_len = cu_arg->num_ml_params * sizeof(*ml_params); ++ size_t ml_info_len = cu_arg->num_ml_info * sizeof(*ml_info); ++ int i; ++ ++ /* Add ML params */ ++ tlv = (struct wmi_tlv *)ptr; ++ tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, ml_params_len); ++ ml_params = (struct wmi_bcn_tmpl_ml_params *)tlv->value; ++ ++ for (i = 0; i < cu_arg->num_ml_params; i++) ++ memcpy(&ml_params[i], &cu_arg->ml_params[i], ++ sizeof(*ml_params)); ++ ++ if (cu_arg->num_ml_params) ++ kfree(cu_arg->ml_params); ++ ++ ptr += TLV_HDR_SIZE + ml_params_len; ++ ++ /* Add ML info */ ++ tlv = (struct wmi_tlv *)ptr; ++ tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, ml_info_len); ++ ml_info = (struct wmi_bcn_tmpl_ml_info *)tlv->value; ++ ++ for (i = 0; i < cu_arg->num_ml_info; i++) ++ memcpy(&ml_info[i], &cu_arg->ml_info[i], ++ sizeof(*ml_info)); ++ ++ if (cu_arg->num_ml_info) ++ kfree(cu_arg->ml_info); ++ ++ ptr += TLV_HDR_SIZE + ml_info_len; ++ ++ ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "wmi %ld bytes of additional data filled for CU\n", ++ (unsigned long)(ptr - start)); ++ return ptr; ++} ++ + int ath12k_wmi_bcn_tmpl(struct ath12k *ar, u32 vdev_id, + struct ieee80211_mutable_offsets *offs, + struct sk_buff *bcn, u32 ema_params) +@@ -1845,12 +1973,32 @@ int ath12k_wmi_bcn_tmpl(struct ath12k *a + void *ptr; + int ret, len; + size_t aligned_len = roundup(bcn->len, 4); +- +- len = sizeof(*cmd) + sizeof(*bcn_prb_info) + TLV_HDR_SIZE + aligned_len; ++ struct ath12k_link_vif *arvif = ath12k_mac_get_arvif(ar, vdev_id); ++ struct wmi_critical_update_arg cu_arg = { ++ .num_ml_params = 0, ++ .ml_params = NULL, ++ .num_ml_info = 0, ++ .ml_info = NULL, ++ }; ++ ++ if (WARN_ON(!arvif)) ++ return -EINVAL; ++ ++ ath12k_wmi_fill_cu_arg(arvif, &cu_arg); ++ ++ len = sizeof(*cmd) + sizeof(*bcn_prb_info) + TLV_HDR_SIZE + aligned_len + ++ TLV_HDR_SIZE + (sizeof(struct wmi_bcn_tmpl_ml_params) * cu_arg.num_ml_params) + ++ TLV_HDR_SIZE + (sizeof(struct wmi_bcn_tmpl_ml_info) * cu_arg.num_ml_info); + + skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len); +- if (!skb) ++ if (!skb) { ++ if (cu_arg.num_ml_params) ++ kfree(cu_arg.ml_params); ++ if (cu_arg.num_ml_info) ++ kfree(cu_arg.ml_info); ++ + return -ENOMEM; ++ } + + cmd = (struct wmi_bcn_tmpl_cmd *)skb->data; + cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_BCN_TMPL_CMD, +@@ -1879,6 +2027,11 @@ int ath12k_wmi_bcn_tmpl(struct ath12k *a + tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, aligned_len); + memcpy(tlv->value, bcn->data, bcn->len); + ++ ptr += (TLV_HDR_SIZE + aligned_len); ++ ++ ptr = ath12k_wmi_append_critical_update_params(ar, vdev_id, ptr, ++ &cu_arg); ++ + ret = ath12k_wmi_cmd_send(wmi, skb, WMI_BCN_TMPL_CMDID); + if (ret) { + ath12k_warn(ar->ab, "failed to send WMI_BCN_TMPL_CMDID\n"); +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -1952,6 +1952,8 @@ enum wmi_tlv_tag { + WMI_TAG_TPC_STATS_REG_PWR_ALLOWED, + WMI_TAG_TPC_STATS_RATES_ARRAY, + WMI_TAG_TPC_STATS_CTL_PWR_TABLE_EVENT, ++ WMI_TAG_BCN_TMPL_ML_PARAMS_CMD = 0x3E6, ++ WMI_TAG_BCN_TMPL_ML_INFO_CMD = 0x436, + WMI_TAG_CTRL_PATH_CMD_FIXED_PARAM = 0x442, + WMI_TAG_CTRL_PATH_EVENT_FIXED_PARAM, + WMI_TAG_MAX +@@ -6391,6 +6393,39 @@ struct wmi_pdev_mvr_resp_event_parse { + u32 vdev_id_bm[]; + } __packed; + ++struct wmi_bcn_tmpl_ml_params { ++ __le32 tlv_header; ++ __le32 vdev_id; ++ __le32 hw_link_id; ++ __le32 beacon_interval; ++ __le32 csa_switch_count_offset; ++ __le32 ext_csa_switch_count_offset; ++ __le32 per_sta_profile_offset; ++ __le32 quiet_ie_offset; ++ __le32 is_other_ie_present; ++} __packed; ++ ++struct wmi_bcn_tmpl_ml_info { ++ __le32 tlv_header; ++ __le32 hw_link_id; ++ __le32 cu_vdev_map_cat1_lo; ++ __le32 cu_vdev_map_cat1_hi; ++ __le32 cu_vdev_map_cat2_lo; ++ __le32 cu_vdev_map_cat2_hi; ++} __packed; ++ ++struct wmi_critical_update_arg { ++ u16 num_ml_params; ++ struct wmi_bcn_tmpl_ml_params *ml_params; ++ u16 num_ml_info; ++ struct wmi_bcn_tmpl_ml_info *ml_info; ++}; ++ ++#define ATH12K_LOWER_32_MASK GENMASK_ULL(31, 0) ++#define ATH12K_UPPER_32_MASK GENMASK_ULL(63, 32) ++#define ATH12K_GET_LOWER_32_BITS(val) (val & ATH12K_LOWER_32_MASK) ++#define ATH12K_GET_UPPER_32_BITS(val) ((val & ATH12K_UPPER_32_MASK) >> 32) ++ + #define ATH12K_FW_STATS_BUF_SIZE (1024 * 1024) + + void ath12k_wmi_init_qcn9274(struct ath12k_base *ab, +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -584,7 +584,7 @@ static u8 ath12k_mac_bitrate_to_rate(int + (ath12k_mac_bitrate_is_cck(bitrate) ? BIT(7) : 0); + } + +-static struct ++struct + ieee80211_bss_conf *ath12k_get_link_bss_conf(struct ath12k_link_vif *arvif) + { + struct ieee80211_vif *vif = arvif->ahvif->vif; diff --git a/feeds/ipq95xx/mac80211/patches/qca/691-ath12k-240MHz-Q-Q-vendor-IE-support.patch b/feeds/ipq95xx/mac80211/patches/qca/691-ath12k-240MHz-Q-Q-vendor-IE-support.patch index b8f990fe8..dfb053143 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/691-ath12k-240MHz-Q-Q-vendor-IE-support.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/691-ath12k-240MHz-Q-Q-vendor-IE-support.patch @@ -12,13 +12,11 @@ copied one during STA association. Signed-off-by: Ramya Gnanasekar -Index: b/include/linux/ieee80211.h -=================================================================== ---- a/include/linux/ieee80211.h 2022-11-02 00:01:29.523145700 +0530 -+++ b/include/linux/ieee80211.h 2022-11-02 00:04:34.589600780 +0530 -@@ -2045,6 +2045,14 @@ struct ieee80211_eht_operation { - - #define IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT 0x1 +--- a/include/linux/ieee80211.h ++++ b/include/linux/ieee80211.h +@@ -2108,6 +2108,14 @@ struct ieee80211_eht_operation_info { + u8 optional[]; + } __packed; +struct ieee80211_240mhz_vendor_oper { + u8 ccfs1; @@ -31,15 +29,15 @@ Index: b/include/linux/ieee80211.h /* 802.11ac VHT Capabilities */ #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000 #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x00000001 -@@ -2739,6 +2747,7 @@ ieee80211_he_spr_size(const u8 *he_spr_i +@@ -2829,6 +2837,7 @@ ieee80211_he_spr_size(const u8 *he_spr_i - /* EHT PHY capabilities as defined in P802.11be_D1.4 section 9.4.2.313.3 */ + /* EHT PHY capabilities as defined in P802.11be_D2.0 section 9.4.2.313.3 */ #define IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ 0x02 +#define IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ_MASK 0x1 #define IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ 0x04 #define IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI 0x08 #define IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO 0x10 -@@ -2801,6 +2810,13 @@ ieee80211_he_spr_size(const u8 *he_spr_i +@@ -2891,6 +2900,13 @@ ieee80211_he_spr_size(const u8 *he_spr_i #define IEEE80211_EHT_PHY_CAP8_RX_1024QAM_WIDER_BW_DL_OFDMA 0x01 #define IEEE80211_EHT_PHY_CAP8_RX_4096QAM_WIDER_BW_DL_OFDMA 0x02 @@ -53,11 +51,9 @@ Index: b/include/linux/ieee80211.h /* * EHT operation channel width as defined in P802.11be_D2.0 section 9.4.2.311 */ -Index: b/include/net/cfg80211.h -=================================================================== ---- a/include/net/cfg80211.h 2022-11-02 00:01:29.523145700 +0530 -+++ b/include/net/cfg80211.h 2022-11-02 00:01:29.499145902 +0530 -@@ -1609,6 +1609,8 @@ struct station_parameters { +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -1621,6 +1621,8 @@ struct link_station_parameters { const struct ieee80211_he_6ghz_capa *he_6ghz_capa; const struct ieee80211_eht_cap_elem *eht_capa; u8 eht_capa_len; @@ -66,19 +62,18 @@ Index: b/include/net/cfg80211.h }; /** -Index: b/include/uapi/linux/nl80211.h -=================================================================== ---- a/include/uapi/linux/nl80211.h 2022-11-02 00:01:29.523145700 +0530 -+++ b/include/uapi/linux/nl80211.h 2022-11-02 00:01:29.499145902 +0530 -@@ -3259,6 +3259,7 @@ enum nl80211_attrs { - - NL80211_ATTR_AP_PS, +--- a/include/uapi/linux/nl80211.h ++++ b/include/uapi/linux/nl80211.h +@@ -3378,6 +3378,8 @@ enum nl80211_attrs { + NL80211_ATTR_MULTI_HW_MACS, + NL80211_ATTR_RADAR_BITMAP, ++ + NL80211_ATTR_EHT_240MHZ_CAPABILITY, /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, -@@ -3316,6 +3317,7 @@ enum nl80211_attrs { +@@ -3440,6 +3442,7 @@ enum nl80211_attrs { #define NL80211_MAX_NR_AKM_SUITES 2 #define NL80211_EHT_MIN_CAPABILITY_LEN 12 #define NL80211_EHT_MAX_CAPABILITY_LEN 51 @@ -86,41 +81,34 @@ Index: b/include/uapi/linux/nl80211.h #define NL80211_MIN_REMAIN_ON_CHANNEL_TIME 10 -Index: b/net/mac80211/cfg.c -=================================================================== ---- a/net/mac80211/cfg.c 2022-11-02 00:01:29.523145700 +0530 -+++ b/net/mac80211/cfg.c 2022-11-02 00:01:29.499145902 +0530 -@@ -1965,6 +1965,8 @@ static int sta_apply_parameters(struct i +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1892,6 +1892,8 @@ static int sta_link_apply_parameters(str params->he_capa_len, params->eht_capa, params->eht_capa_len, + params->eht_240mhz_capa, + params->eht_240mhz_len, - sta); + link_sta); /* 802.11s mesh STA may have different eht punctruing pattern, * update it here so that drivers can use if needed. -Index: b/net/mac80211/eht.c -=================================================================== ---- a/net/mac80211/eht.c 2022-11-02 00:01:29.523145700 +0530 -+++ b/net/mac80211/eht.c 2022-11-02 00:01:29.503145867 +0530 -@@ -12,7 +12,10 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(stru - struct ieee80211_supported_band *sband, +--- a/net/mac80211/eht.c ++++ b/net/mac80211/eht.c +@@ -13,6 +13,8 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(stru const u8 *he_cap_ie, u8 he_cap_len, const struct ieee80211_eht_cap_elem *eht_cap_ie_elem, -- u8 eht_cap_len, struct sta_info *sta) -+ u8 eht_cap_len, + u8 eht_cap_len, + const struct ieee80211_240mhz_vendor_oper *eht_240mhz_cap, + u8 eht_240mhz_len, -+ struct sta_info *sta) + struct link_sta_info *link_sta) { - struct ieee80211_sta_eht_cap *eht_cap = &sta->sta.eht_cap; - u8 eht_ppe_size = 0; -@@ -72,6 +75,37 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(stru + struct ieee80211_sta_eht_cap *eht_cap = &link_sta->pub->eht_cap; +@@ -73,6 +75,37 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(stru &eht_cap_ie_elem->optional[mcs_nss_size], eht_ppe_size); + if (eht_240mhz_cap && -+ sta->sdata->vif.bss_conf.chandef.chan->band == NL80211_BAND_5GHZ) { ++ sband->band == NL80211_BAND_5GHZ) { + /* Override capabilities from QCN IE for 240MHz to EHT phy capab */ + if (eht_240mhz_cap->phy_cap_320mhz & + IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ_MASK) @@ -152,20 +140,18 @@ Index: b/net/mac80211/eht.c + eht_cap->has_eht = true; - sta->cur_max_bandwidth = ieee80211_sta_cap_rx_bw(sta); -Index: b/net/mac80211/ieee80211_i.h -=================================================================== ---- a/net/mac80211/ieee80211_i.h 2022-11-02 00:01:29.523145700 +0530 -+++ b/net/mac80211/ieee80211_i.h 2022-11-02 00:01:29.503145867 +0530 -@@ -1624,6 +1624,7 @@ struct ieee802_11_elems { + link_sta->cur_max_bandwidth = ieee80211_sta_cap_rx_bw(link_sta); +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1726,6 +1726,7 @@ struct ieee802_11_elems { const struct ieee80211_aid_response_ie *aid_resp; const struct ieee80211_eht_cap_elem *eht_cap; const struct ieee80211_eht_operation *eht_operation; + const struct ieee80211_240mhz_vendor_ope *eht_240mhz_capab; + const struct ieee80211_multi_link_elem *multi_link; /* length of them, respectively */ - u8 ext_capab_len; -@@ -1646,6 +1647,7 @@ struct ieee802_11_elems { +@@ -1749,6 +1750,7 @@ struct ieee802_11_elems { u8 tx_pwr_env_len[IEEE80211_TPE_MAX_IE_COUNT]; u8 tx_pwr_env_num; u8 eht_cap_len; @@ -173,51 +159,41 @@ Index: b/net/mac80211/ieee80211_i.h /* whether a parse error occurred while retrieving these elements */ bool parse_error; -@@ -2581,7 +2583,10 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(stru - struct ieee80211_supported_band *sband, +@@ -2603,6 +2605,8 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(stru const u8 *he_cap_ie, u8 he_cap_len, const struct ieee80211_eht_cap_elem *eht_cap_ie_elem, -- u8 eht_cap_len, struct sta_info *sta); -+ u8 eht_cap_len, + u8 eht_cap_len, + const struct ieee80211_240mhz_vendor_oper *eht_240mhz_cap, + u8 eht_240mhz_len, -+ struct sta_info *sta); - void ieee80211_eht_op_ie_to_bss_conf(struct ieee80211_vif *vif, - const struct ieee80211_eht_operation *eht_op); - #endif /* IEEE80211_I_H */ -Index: b/net/mac80211/mesh_plink.c -=================================================================== ---- a/net/mac80211/mesh_plink.c 2022-11-02 00:01:29.523145700 +0530 -+++ b/net/mac80211/mesh_plink.c 2022-11-02 00:01:29.503145867 +0530 -@@ -468,7 +468,7 @@ static void mesh_sta_info_init(struct ie - sta); + struct link_sta_info *link_sta); + void ieee80211_eht_op_ie_to_bss_conf(struct ieee80211_bss_conf *link_conf, + const struct ieee80211_eht_operation *op_ie); +--- a/net/mac80211/mesh_plink.c ++++ b/net/mac80211/mesh_plink.c +@@ -464,6 +464,7 @@ static void mesh_sta_info_init(struct ie + ieee80211_eht_cap_ie_to_sta_eht_cap(sdata, sband, elems->he_cap, + elems->he_cap_len, + elems->eht_cap, elems->eht_cap_len, ++ NULL, NULL, + &sta->deflink); - ieee80211_eht_cap_ie_to_sta_eht_cap(sdata, sband, elems->he_cap, elems->he_cap_len, -- elems->eht_cap, elems->eht_cap_len, -+ elems->eht_cap, elems->eht_cap_len, NULL, NULL, - sta); - - if (bw != sta->sta.bandwidth) -Index: b/net/mac80211/mlme.c -=================================================================== ---- a/net/mac80211/mlme.c 2022-11-02 00:01:29.523145700 +0530 -+++ b/net/mac80211/mlme.c 2022-11-02 00:01:29.503145867 +0530 -@@ -3588,6 +3588,7 @@ static bool ieee80211_assoc_success(stru + if (bw != sta->sta.deflink.bandwidth) +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -4092,6 +4092,7 @@ static bool ieee80211_assoc_config_link( elems->he_cap_len, elems->eht_cap, elems->eht_cap_len, + NULL, NULL, - sta); + link_sta); - bss_conf->eht_support = sta->sta.eht_cap.has_eht; -Index: b/net/wireless/nl80211.c -=================================================================== ---- a/net/wireless/nl80211.c 2022-11-02 00:01:29.523145700 +0530 -+++ b/net/wireless/nl80211.c 2022-11-02 00:02:19.974724110 +0530 -@@ -837,6 +837,16 @@ static const struct nla_policy nl80211_p - [NL80211_ATTR_RU_PUNCT_SUPP_HE] = { .type = NLA_FLAG }, + bss_conf->eht_support = link_sta->pub->eht_cap.has_eht; +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -860,6 +860,16 @@ static const struct nla_policy nl80211_p [NL80211_ATTR_RU_PUNCT_BITMAP] = { .type = NLA_U16 }, [NL80211_ATTR_AP_PS] = NLA_POLICY_MAX(NLA_U8, 1), + [NL80211_ATTR_RADAR_BITMAP] = { .type = NLA_U16 }, +#if LINUX_VERSION_IS_GEQ(5,10,0) + [NL80211_ATTR_EHT_240MHZ_CAPABILITY] = + NLA_POLICY_RANGE(NLA_BINARY, @@ -231,21 +207,21 @@ Index: b/net/wireless/nl80211.c }; /* policy for the key attributes */ -@@ -7082,6 +7092,13 @@ static int nl80211_set_station_tdls(stru - params->eht_capa_len)) +@@ -7502,6 +7512,13 @@ static int nl80211_set_station_tdls(stru + params->link_sta_params.eht_capa_len)) return -EINVAL; } + + if (info->attrs[NL80211_ATTR_EHT_240MHZ_CAPABILITY]) { -+ params->eht_240mhz_capa = ++ params->link_sta_params.eht_240mhz_capa = + nla_data(info->attrs[NL80211_ATTR_EHT_240MHZ_CAPABILITY]); -+ params->eht_240mhz_len = ++ params->link_sta_params.eht_240mhz_len = + nla_len(info->attrs[NL80211_ATTR_EHT_240MHZ_CAPABILITY]); + } } err = nl80211_parse_sta_channel_info(info, params); -@@ -7361,6 +7378,13 @@ static int nl80211_new_station(struct sk +@@ -16660,6 +16677,13 @@ nl80211_add_mod_link_station(struct sk_b params.eht_capa_len)) return -EINVAL; } diff --git a/feeds/ipq95xx/mac80211/patches/qca/691-ath12k-Add-support-for-ADFS.patch b/feeds/ipq95xx/mac80211/patches/qca/691-ath12k-Add-support-for-ADFS.patch new file mode 100644 index 000000000..316677efa --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/691-ath12k-Add-support-for-ADFS.patch @@ -0,0 +1,809 @@ +From 048387f242188b4bbb95a624f5bdaba8948cbb3c Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Fri, 25 Nov 2022 10:37:48 +0530 +Subject: [PATCH] ath12k: Add support for ADFS + +The following changes are added to support background DFS feature: + 1. add support for ADFS WMI command + 2. handle ADFS complete event from Firmware + 3. parse the firmware phy mac capabilties to + infer which chainmask supports ADFS + 4. During channel change abort ongoing CAC + 5. handle radar on agile detector + +Signed-off-by: Harshitha Prem +--- + drivers/net/wireless/ath/ath12k/core.h | 3 + + drivers/net/wireless/ath/ath12k/mac.c | 115 ++++++++++ + drivers/net/wireless/ath/ath12k/mac.h | 8 + + drivers/net/wireless/ath/ath12k/wmi.c | 284 ++++++++++++++++++++++++- + drivers/net/wireless/ath/ath12k/wmi.h | 88 ++++++++ + 5 files changed, 496 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -872,6 +872,7 @@ struct ath12k { + bool fw_stats_done; + + struct completion mvr_complete; ++ struct cfg80211_chan_def agile_chandef; + }; + + struct ath12k_band_cap { +@@ -903,6 +904,8 @@ struct ath12k_pdev_cap { + u32 rx_chain_mask; + u32 tx_chain_mask_shift; + u32 rx_chain_mask_shift; ++ u32 chainmask_table_id; ++ u32 adfs_chain_mask; + struct ath12k_band_cap band[NUM_NL80211_BANDS]; + bool nss_ratio_enabled; + u8 nss_ratio_info; +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -9745,6 +9745,23 @@ ath12k_mac_vdev_config_after_start(struc + if (ret) + ath12k_warn(ab, "failed to set 6G non-ht dup conf for vdev %d: %d\n", + arvif->vdev_id, ret); ++ /* In case of ADFS, we have to abort ongoing backgrorund CAC */ ++ if ((ar->pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP) && ++ test_bit(ar->cfg_rx_chainmask, &ar->pdev->cap.adfs_chain_mask) && ++ ar->agile_chandef.chan) { ++ ath12k_dbg(ab, ATH12K_DBG_MAC, ++ "Aborting ongoing Agile DFS on freq %d", ++ ar->agile_chandef.chan->center_freq); ++ ret = ath12k_wmi_vdev_adfs_ocac_abort_cmd_send(ar,arvif->vdev_id); ++ if (!ret) { ++ memset(&ar->agile_chandef, 0, sizeof(struct cfg80211_chan_def)); ++ ar->agile_chandef.chan = NULL; ++ ath12k_mac_background_dfs_event(ar, ATH12K_BGDFS_ABORT); ++ } else { ++ ath12k_warn(ab, "failed to abort agile CAC for vdev %d", ++ arvif->vdev_id); ++ } ++ } + + return ret; + } +@@ -12923,6 +12940,123 @@ err_fallback: + return 0; + } + ++/* Note: only half bandwidth agile is supported */ ++bool ath12k_is_supported_agile_bandwidth(enum nl80211_chan_width conf_bw, ++ enum nl80211_chan_width agile_bw) ++{ ++ bool is_supported = false; ++ ++ switch (conf_bw) { ++ case NL80211_CHAN_WIDTH_20_NOHT: ++ case NL80211_CHAN_WIDTH_20: ++ case NL80211_CHAN_WIDTH_40: ++ if (agile_bw <= conf_bw) ++ is_supported = true; ++ break; ++ case NL80211_CHAN_WIDTH_80: ++ if (agile_bw == conf_bw || ++ agile_bw == NL80211_CHAN_WIDTH_40) ++ is_supported = true; ++ break; ++ case NL80211_CHAN_WIDTH_160: ++ if (agile_bw == conf_bw || ++ agile_bw == NL80211_CHAN_WIDTH_80) ++ is_supported = true; ++ break; ++ case NL80211_CHAN_WIDTH_320: ++ if (agile_bw == conf_bw || ++ agile_bw == NL80211_CHAN_WIDTH_160) ++ is_supported = true; ++ break; ++ default: ++ break; ++ } ++ ++ return is_supported; ++} ++static int ath12k_mac_op_set_radar_background(struct ieee80211_hw *hw, ++ struct cfg80211_chan_def *def) ++{ ++ struct ath12k *ar; ++ struct ath12k_link_vif *arvif; ++ struct ath12k_vif *ahvif; ++ bool arvif_found = false; ++ int ret; ++ struct cfg80211_chan_def conf_def; ++ ++ ar = ath12k_mac_get_ar_by_band(hw, NL80211_BAND_5GHZ); ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ if (ar->ab->dfs_region == ATH12K_DFS_REG_UNSET) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ if (!test_bit(ar->cfg_rx_chainmask, &ar->pdev->cap.adfs_chain_mask)) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ list_for_each_entry(arvif, &ar->arvifs, list) { ++ ahvif = arvif->ahvif; ++ if (arvif->is_started && ahvif->vdev_type == WMI_VDEV_TYPE_AP) { ++ arvif_found = true; ++ break; ++ } ++ } ++ ++ if (!arvif_found) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ if (!def) { ++ ret = ath12k_wmi_vdev_adfs_ocac_abort_cmd_send(ar,arvif->vdev_id); ++ if (!ret) { ++ memset(&ar->agile_chandef, 0, sizeof(struct cfg80211_chan_def)); ++ ar->agile_chandef.chan = NULL; ++ } ++ } else { ++ if (!cfg80211_chandef_valid(def) || ++ !(def->chan->flags & IEEE80211_CHAN_RADAR)) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ if (WARN_ON(ath12k_mac_vif_chan(ahvif->vif, &conf_def, ++ arvif->link_id))) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ /* Note: Only Half width and full bandwidth is supported */ ++ ++ if(!(ath12k_is_supported_agile_bandwidth(conf_def.width, ++ def->width))) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ if (conf_def.center_freq1 == def->center_freq1) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ ret = ath12k_wmi_vdev_adfs_ch_cfg_cmd_send(ar, arvif->vdev_id, def); ++ if (!ret) { ++ memcpy(&ar->agile_chandef, def, sizeof(struct cfg80211_chan_def)); ++ } else { ++ memset(&ar->agile_chandef, 0, sizeof(struct cfg80211_chan_def)); ++ ar->agile_chandef.chan = NULL; ++ } ++ } ++ ++exit: ++ mutex_unlock(&ar->conf_mutex); ++ return ret; ++} ++ + static const struct ieee80211_ops ath12k_ops = { + .tx = ath12k_mac_op_tx, + .start = ath12k_mac_op_start, +@@ -12965,6 +13099,7 @@ static const struct ieee80211_ops ath12k + .sta_add_debugfs = ath12k_debugfs_sta_op_add, + #endif + .get_txpower = ath12k_mac_op_get_txpower, ++ .set_radar_background = ath12k_mac_op_set_radar_background, + }; + + static void ath12k_mac_update_ch_list(struct ath12k *ar, +@@ -13400,6 +13535,11 @@ static int __ath12k_mac_register(struct + NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP); + } + ++ if ((ar->pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP) && ++ test_bit(ar->cfg_rx_chainmask, &cap->adfs_chain_mask)) ++ wiphy_ext_feature_set(hw->wiphy, ++ NL80211_EXT_FEATURE_RADAR_BACKGROUND); ++ + return 0; + } + static int ath12k_setup_per_hw_if_comb(struct ath12k_hw *ah) { +@@ -14017,3 +14157,42 @@ u16 ath12k_calculate_subchannel_count(en + } + return width_num/20; + } ++ ++void ath12k_mac_background_dfs_event(struct ath12k *ar, ++ enum ath12k_background_dfs_events ev) ++{ ++ struct ath12k_vif *ahvif; ++ struct ath12k_link_vif *arvif; ++ bool arvif_found = false; ++ int ret = 0; ++ ++ list_for_each_entry(arvif, &ar->arvifs, list) { ++ ahvif = arvif->ahvif; ++ if (arvif->is_started && ++ ahvif->vdev_type == WMI_VDEV_TYPE_AP) { ++ arvif_found = true; ++ break; ++ } ++ } ++ ++ if (!arvif_found) ++ return; ++ ++ if (ev == ATH12K_BGDFS_RADAR) { ++ cfg80211_background_radar_event(ar->ah->hw->wiphy, &ar->agile_chandef, GFP_ATOMIC); ++ lockdep_assert_held(&ar->conf_mutex); ++ ret = ath12k_wmi_vdev_adfs_ocac_abort_cmd_send(ar, arvif->vdev_id); ++ } else if (ev == ATH12K_BGDFS_ABORT) { ++ cfg80211_background_cac_abort(ar->ah->hw->wiphy); ++ } ++ ++ if (!ret) { ++ memset(&ar->agile_chandef, 0, sizeof(struct cfg80211_chan_def)); ++ ar->agile_chandef.chan = NULL; ++ } else { ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, ++ "ADFS state can't be reset (ret=%d)\n", ++ ret); ++ } ++} ++ +--- a/drivers/net/wireless/ath/ath12k/mac.h ++++ b/drivers/net/wireless/ath/ath12k/mac.h +@@ -161,6 +161,12 @@ struct ath12k_mac_num_chanctxs_arg { + IEEE80211_CU_MODIFY_UORA_PARAM_ELEM | \ + IEEE80211_CU_MODIFY_EHT_OPER_ELEM) + ++enum ath12k_background_dfs_events { ++ ATH12K_BGDFS_SUCCESS, ++ ATH12K_BGDFS_ABORT, ++ ATH12K_BGDFS_RADAR, ++}; ++ + extern const struct htt_rx_ring_tlv_filter ath12k_mac_mon_status_filter_default; + + void ath12k_mac_ap_ps_recalc(struct ath12k *ar); +@@ -208,4 +214,6 @@ int ath12k_mac_mlo_teardown(struct ath12 + struct ieee80211_bss_conf *ath12k_get_link_bss_conf(struct ath12k_link_vif *arvif); + bool ath12k_mac_is_ml_arvif(struct ath12k_link_vif *arvif); + u16 ath12k_calculate_subchannel_count(enum nl80211_chan_width width); ++void ath12k_mac_background_dfs_event(struct ath12k *ar, ++ enum ath12k_background_dfs_events ev); + #endif +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -50,6 +50,7 @@ struct wmi_tlv_svc_rdy_ext_parse { + bool hw_mode_done; + bool mac_phy_done; + bool ext_hal_reg_done; ++ u32 n_mac_phy_chainmask_combo; + bool mac_phy_chainmask_combo_done; + bool mac_phy_chainmask_cap_done; + bool oem_dma_ring_cap_done; +@@ -274,6 +275,40 @@ static const int ath12k_hw_mode_pri_map[ + PRIMAP(WMI_HOST_HW_MODE_MAX), + }; + ++ ++enum wmi_host_channel_width ++ath12k_wmi_get_host_chan_width(u32 width) ++{ ++ enum wmi_host_channel_width host_width; ++ ++ switch (width) { ++ case NL80211_CHAN_WIDTH_20_NOHT: ++ case NL80211_CHAN_WIDTH_20: ++ host_width = WMI_HOST_CHAN_WIDTH_20; ++ break; ++ case NL80211_CHAN_WIDTH_40: ++ host_width = WMI_HOST_CHAN_WIDTH_40; ++ break; ++ case NL80211_CHAN_WIDTH_80: ++ host_width = WMI_HOST_CHAN_WIDTH_80; ++ break; ++ case NL80211_CHAN_WIDTH_160: ++ host_width = WMI_HOST_CHAN_WIDTH_160; ++ break; ++ case NL80211_CHAN_WIDTH_80P80: ++ host_width = WMI_HOST_CHAN_WIDTH_80P80; ++ break; ++ case NL80211_CHAN_WIDTH_320: ++ host_width = WMI_HOST_CHAN_WIDTH_320; ++ break; ++ default: ++ host_width = WMI_HOST_CHAN_WIDTH_MAX; ++ break; ++ } ++ ++ return host_width; ++} ++ + static int + ath12k_wmi_tlv_iter(struct ath12k_base *ab, const void *ptr, size_t len, + int (*iter)(struct ath12k_base *ab, u16 tag, u16 len, +@@ -491,6 +526,7 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(st + + pdev_cap->supported_bands |= mac_phy_caps->supported_bands; + pdev_cap->ampdu_density = mac_phy_caps->ampdu_density; ++ pdev_cap->chainmask_table_id = mac_phy_caps->chainmask_table_id; + + /* Take non-zero tx/rx chainmask. If tx/rx chainmask differs from + * band to band for a single radio, need to see how this should be +@@ -4677,6 +4713,102 @@ static void ath12k_wmi_pdev_dma_ring_buf + } + } + ++ ++static int ath12k_wmi_tlv_mac_phy_chainmask_caps(struct ath12k_base *soc, ++ u16 len, const void *ptr, void *data) ++{ ++ struct wmi_tlv_svc_rdy_ext_parse *svc_rdy_ext = data; ++ struct wmi_mac_phy_chainmask_caps *cmask_caps = (struct wmi_mac_phy_chainmask_caps *)ptr; ++ struct ath12k_chainmask_table *cmask_table; ++ struct ath12k_pdev_cap *pdev_cap; ++ u32 tag; ++ int i, j; ++ ++ if (!svc_rdy_ext->hw_mode_caps) ++ return -EINVAL; ++ ++ if ((!svc_rdy_ext->param.num_chainmask_tables) || ++ (svc_rdy_ext->param.num_chainmask_tables > ATH12K_MAX_CHAINMASK_TABLES)) ++ return -EINVAL; ++ ++ for (i = 0; i < svc_rdy_ext->param.num_chainmask_tables; i++) { ++ cmask_table = &svc_rdy_ext->param.chainmask_table[i]; ++ ++ for (j = 0; j < cmask_table->num_valid_chainmasks; j++) { ++ tag = FIELD_GET(WMI_TLV_TAG, cmask_caps->tlv_header); ++ ++ if (tag != WMI_TAG_MAC_PHY_CHAINMASK_CAPABILITY) ++ return -EPROTO; ++ ++ cmask_table->cap_list[j].chainmask = cmask_caps->chainmask; ++ cmask_table->cap_list[j].supported_caps = cmask_caps->supported_flags; ++ cmask_caps++; ++ ath12k_dbg(soc, ATH12K_DBG_WMI,"[id %d] chainmask %x supported_caps %x", ++ cmask_table->table_id, cmask_table->cap_list[j].chainmask, ++ cmask_table->cap_list[j].supported_caps); ++ } ++ } ++ ++ for (i = 0; i < soc->num_radios; i++) { ++ pdev_cap = &soc->pdevs[i].cap; ++ for (j = 0; j < svc_rdy_ext->n_mac_phy_chainmask_combo; j++) { ++ cmask_table = &svc_rdy_ext->param.chainmask_table[j]; ++ if (cmask_table->table_id == pdev_cap->chainmask_table_id) ++ break; ++ } ++ for (j = 0; j < cmask_table->num_valid_chainmasks; j++) { ++ if (cmask_table->cap_list[j].supported_caps & WMI_SUPPORT_CHAIN_MASK_ADFS) ++ pdev_cap->adfs_chain_mask |= (1 << cmask_table->cap_list[j].chainmask); ++ } ++ ath12k_dbg(soc, ATH12K_DBG_WMI, "updated adfs chain mask %x for pdev %d", ++ pdev_cap->adfs_chain_mask, i); ++ } ++ return 0; ++} ++ ++static void ath12k_wmi_free_chainmask_caps(struct wmi_tlv_svc_rdy_ext_parse *svc_rdy_ext) ++{ ++ int i; ++ ++ if (!svc_rdy_ext->param.num_chainmask_tables) ++ return; ++ ++ for (i = 0; i < svc_rdy_ext->param.num_chainmask_tables; i++) { ++ if (!svc_rdy_ext->param.chainmask_table[i].cap_list) ++ continue; ++ kfree(svc_rdy_ext->param.chainmask_table[i].cap_list); ++ svc_rdy_ext->param.chainmask_table[i].cap_list = NULL; ++ } ++} ++ ++static int ath12k_wmi_tlv_mac_phy_chainmask_combo_parse(struct ath12k_base *soc, ++ u16 tag, u16 len, ++ const void *ptr, void *data) ++{ ++ struct wmi_tlv_svc_rdy_ext_parse *svc_rdy_ext = data; ++ struct wmi_mac_phy_chainmask_combo *cmask_combo = (struct wmi_mac_phy_chainmask_combo *) ptr; ++ u32 i = svc_rdy_ext->n_mac_phy_chainmask_combo; ++ struct ath12k_chainmask_table *cmask_table; ++ ++ if (tag != WMI_TAG_MAC_PHY_CHAINMASK_COMBO) ++ return -EPROTO; ++ ++ if (svc_rdy_ext->n_mac_phy_chainmask_combo >= svc_rdy_ext->param.num_chainmask_tables) ++ return -ENOBUFS; ++ ++ cmask_table = &svc_rdy_ext->param.chainmask_table[i]; ++ cmask_table->table_id = cmask_combo->chainmask_table_id; ++ cmask_table->num_valid_chainmasks = cmask_combo->num_valid_chainmask; ++ cmask_table->cap_list = kcalloc(cmask_combo->num_valid_chainmask, ++ sizeof(struct ath12k_chainmask_caps), ++ GFP_ATOMIC); ++ if (!svc_rdy_ext->param.chainmask_table[i].cap_list) ++ return -ENOMEM; ++ ++ svc_rdy_ext->n_mac_phy_chainmask_combo++; ++ return 0; ++} ++ + static int ath12k_wmi_tlv_hw_mode_caps_parse(struct ath12k_base *soc, + u16 tag, u16 len, + const void *ptr, void *data) +@@ -4984,6 +5116,7 @@ static int ath12k_wmi_tlv_svc_rdy_ext_pa + case WMI_TAG_SOC_MAC_PHY_HW_MODE_CAPS: + svc_rdy_ext->hw_caps = (struct wmi_soc_mac_phy_hw_mode_caps *)ptr; + svc_rdy_ext->param.num_hw_modes = svc_rdy_ext->hw_caps->num_hw_modes; ++ svc_rdy_ext->param.num_chainmask_tables = svc_rdy_ext->hw_caps->num_chainmask_tables; + break; + + case WMI_TAG_SOC_HAL_REG_CAPABILITIES: +@@ -5020,8 +5153,21 @@ static int ath12k_wmi_tlv_svc_rdy_ext_pa + + svc_rdy_ext->ext_hal_reg_done = true; + } else if (!svc_rdy_ext->mac_phy_chainmask_combo_done) { ++ svc_rdy_ext->n_mac_phy_chainmask_combo = 0; ++ ret = ath12k_wmi_tlv_iter(ab, ptr, len, ++ ath12k_wmi_tlv_mac_phy_chainmask_combo_parse, ++ svc_rdy_ext); ++ if (ret) { ++ ath12k_warn(ab, "failed to parse chainmask combo tlv %d\n", ret); ++ return ret; ++ } + svc_rdy_ext->mac_phy_chainmask_combo_done = true; + } else if (!svc_rdy_ext->mac_phy_chainmask_cap_done) { ++ ret = ath12k_wmi_tlv_mac_phy_chainmask_caps(ab, len, ptr, svc_rdy_ext); ++ if (ret) { ++ ath12k_warn(ab, "failed to parse chainmask caps tlv %d\n", ret); ++ return ret; ++ } + svc_rdy_ext->mac_phy_chainmask_cap_done = true; + } else if (!svc_rdy_ext->oem_dma_ring_cap_done) { + svc_rdy_ext->oem_dma_ring_cap_done = true; +@@ -5059,9 +5205,12 @@ static int ath12k_service_ready_ext_even + complete(&ab->wmi_ab.service_ready); + + kfree(svc_rdy_ext.mac_phy_caps); ++ ath12k_wmi_free_chainmask_caps(&svc_rdy_ext); + return 0; + + err: ++ kfree(svc_rdy_ext.mac_phy_caps); ++ ath12k_wmi_free_chainmask_caps(&svc_rdy_ext); + ath12k_wmi_free_dbring_caps(ab); + return ret; + } +@@ -8264,10 +8413,15 @@ static void ath12k_dfs_calculate_subchan + + arg.ar = ar; + arg.def = NULL; +- ieee80211_iter_chan_contexts_atomic(ar->ah->hw, ath12k_mac_get_any_chandef_iter, ++ if (!radar->detector_id) { ++ ieee80211_iter_chan_contexts_atomic(ar->ah->hw, ath12k_mac_get_any_chandef_iter, + &arg); +- chandef = arg.def; +- if (!chandef) { ++ chandef = arg.def; ++ } else { ++ chandef = &ar->agile_chandef; ++ } ++ ++ if (!chandef || !chandef->chan) { + ath12k_err(ab, "Channel information not available\n"); + return; + } +@@ -8311,7 +8465,12 @@ static void ath12k_dfs_calculate_subchan + radar_bitmap,subchannel_count); + + mark_radar: +- ieee80211_radar_detected_bitmap(ar->ah->hw,radar_bitmap); ++ if (!radar->detector_id) { ++ ieee80211_radar_detected_bitmap(ar->ah->hw,radar_bitmap); ++ } else { ++ ar->agile_chandef.radar_bitmap = radar_bitmap; ++ ath12k_mac_background_dfs_event(ar, ATH12K_BGDFS_RADAR); ++ } + } + + static void +@@ -9732,6 +9891,58 @@ static void ath12k_wmi_event_mvr_respons + ath12k_wmi_process_mvr_event(ab, parse.vdev_id_bm, parse.num_vdevs_bm); + } + ++static void ath12k_process_ocac_complete_event(struct ath12k_base *ab, ++ struct sk_buff *skb) ++{ ++ const void **tb; ++ const struct wmi_vdev_adfs_ocac_complete_event_fixed_param *ev; ++ struct ath12k *ar; ++ int ret; ++ ++ tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); ++ if (IS_ERR(tb)) { ++ ret = PTR_ERR(tb); ++ ath12k_warn(ab, "failed to parse tlv: %d\n", ret); ++ return; ++ } ++ ++ ev = tb[WMI_TAG_VDEV_ADFS_OCAC_COMPLETE_EVENT]; ++ ++ if (!ev) { ++ ath12k_warn(ab, "failed to fetch ocac completed ev"); ++ kfree(tb); ++ return; ++ } ++ ++ ath12k_dbg(ab, ATH12K_DBG_WMI, ++ "pdev dfs ocac complete event on pdev %d, chan freq %d," ++ "chan_width %d, status %d freq %d, freq1 %d, freq2 %d", ++ ev->vdev_id, ev->chan_freq, ev->chan_width, ++ ev->status, ev->center_freq, ev->center_freq1, ++ ev->center_freq2); ++ ++ ar = ath12k_mac_get_ar_by_vdev_id(ab, ev->vdev_id); ++ ++ if (!ar) { ++ ath12k_warn(ab, "OCAC complete event in invalid vdev %d\n", ++ ev->vdev_id); ++ goto exit; ++ } ++ ++ ath12k_dbg(ar->ab, ATH12K_DBG_WMI,"aDFS ocac complete event in vdev %d\n", ++ ev->vdev_id); ++ ++ if (ev->status) { ++ ath12k_mac_background_dfs_event(ar, ATH12K_BGDFS_ABORT); ++ } else { ++ memset(&ar->agile_chandef, 0, sizeof(struct cfg80211_chan_def)); ++ ar->agile_chandef.chan = NULL; ++ } ++exit: ++ kfree(tb); ++} ++ ++ + static void ath12k_wmi_tlv_op_rx(struct ath12k_base *ab, struct sk_buff *skb) + { + struct wmi_cmd_hdr *cmd_hdr; +@@ -9881,6 +10092,9 @@ static void ath12k_wmi_tlv_op_rx(struct + case WMI_PDEV_MULTIPLE_VDEV_RESTART_RESP_EVENTID: + ath12k_wmi_event_mvr_response(ab, skb); + break; ++ case WMI_VDEV_ADFS_OCAC_COMPLETE_EVENTID: ++ ath12k_process_ocac_complete_event(ab, skb); ++ break; + /* TODO: Add remaining events */ + default: + ath12k_dbg(ab, ATH12K_DBG_WMI, "Unknown eventid: 0x%x\n", id); +@@ -10416,3 +10630,96 @@ int ath12k_wmi_pdev_multiple_vdev_restar + + return ret; + } ++ ++int ath12k_wmi_vdev_adfs_ch_cfg_cmd_send(struct ath12k *ar, ++ u32 vdev_id, ++ struct cfg80211_chan_def *def) ++{ ++ struct ath12k_pdev_wmi *wmi = ar->wmi; ++ struct wmi_vdev_adfs_ch_cfg_cmd *cmd; ++ struct sk_buff *skb; ++ int ret = 0; ++ ++ skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd)); ++ if (!skb) ++ return -ENOMEM; ++ ++ cmd = (struct wmi_vdev_adfs_ch_cfg_cmd *)skb->data; ++ cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_VDEV_ADFS_CH_CFG_CMD) | ++ FIELD_PREP(WMI_TLV_LEN, ++ sizeof(struct wmi_vdev_adfs_ch_cfg_cmd) - TLV_HDR_SIZE); ++ cmd->vdev_id = vdev_id; ++ ++ if (ar->ab->dfs_region == ATH12K_DFS_REG_ETSI) { ++ cmd->ocac_mode = WMI_ADFS_MODE_QUICK_OCAC; ++ cmd->min_duration_ms = cfg80211_chandef_dfs_cac_time(ar->ah->hw->wiphy, ++ def, ++ true); ++ ++ if (cmd->min_duration_ms == MIN_WEATHER_RADAR_CHAN_PRECAC_TIMEOUT) ++ cmd->max_duration_ms = MAX_WEATHER_RADAR_CHAN_PRECAC_TIMEOUT; ++ else ++ cmd->max_duration_ms = MAX_PRECAC_TIMEOUT; ++ } else if (ar->ab->dfs_region == ATH12K_DFS_REG_FCC) { ++ cmd->ocac_mode = WMI_ADFS_MODE_QUICK_RCAC; ++ cmd->min_duration_ms = MIN_RCAC_TIMEOUT; ++ cmd->max_duration_ms = MAX_RCAC_TIMEOUT; ++ } ++ ++ cmd->chan_freq = def->chan->center_freq; ++ cmd->chan_width = ath12k_wmi_get_host_chan_width(def->width); ++ cmd->center_freq1 = def->center_freq1; ++ cmd->center_freq2 = def->center_freq2; ++ ++ ath12k_dbg(ar->ab, ATH12K_DBG_WMI, ++ "Send adfs channel cfg command for vdev id %d " ++ "mode as %d min duration %d chan_freq %d chan_width %d\n" ++ "center_freq1 %d center_freq2 %d", cmd->vdev_id, ++ cmd->ocac_mode, cmd->min_duration_ms, cmd->chan_freq, ++ cmd->chan_width, cmd->center_freq1, cmd->center_freq2); ++ ++ ret = ath12k_wmi_cmd_send(wmi, skb, WMI_VDEV_ADFS_CH_CFG_CMDID); ++ if (ret) { ++ ath12k_warn(ar->ab, ++ "failed to send WMI_VDEV_ADFS_CH_CFG_CMDID\n"); ++ dev_kfree_skb(skb); ++ } ++ ++ return ret; ++} ++ ++int ath12k_wmi_vdev_adfs_ocac_abort_cmd_send(struct ath12k *ar, u32 vdev_id) ++{ ++ struct ath12k_pdev_wmi *wmi = ar->wmi; ++ struct wmi_vdev_adfs_ocac_abort_cmd *cmd; ++ struct sk_buff *skb; ++ int ret = 0; ++ ++ if (!ar->agile_chandef.chan) { ++ ath12k_dbg(ar->ab, ATH12K_DBG_WMI, ++ "Currently, agile CAC is not active on any channel." ++ "Ignore abort"); ++ return ret; ++ } ++ ++ skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd)); ++ if (!skb) ++ return -ENOMEM; ++ ++ cmd = (struct wmi_vdev_adfs_ocac_abort_cmd *)skb->data; ++ cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_VDEV_ADFS_OCAC_ABORT_CMD) | ++ FIELD_PREP(WMI_TLV_LEN, ++ sizeof(struct wmi_vdev_adfs_ocac_abort_cmd) - TLV_HDR_SIZE); ++ ++ cmd->vdev_id = vdev_id; ++ ret = ath12k_wmi_cmd_send(wmi, skb, WMI_VDEV_ADFS_OCAC_ABORT_CMDID); ++ ++ if (ret) { ++ ath12k_warn(ar->ab, ++ "failed to send WMI_VDEV_ADFS_ABORT_CMD\n"); ++ dev_kfree_skb(skb); ++ return ret; ++ } ++ return ret; ++} ++ +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -2304,6 +2304,19 @@ struct ath12k_ppe_threshold { + u32 ppet16_ppet8_ru3_ru0[PSOC_HOST_MAX_NUM_SS]; + }; + ++struct ath12k_chainmask_caps { ++ u32 supported_caps; ++ u32 chainmask; ++}; ++ ++struct ath12k_chainmask_table { ++ u32 table_id; ++ u32 num_valid_chainmasks; ++ struct ath12k_chainmask_caps *cap_list; ++}; ++ ++#define ATH12K_MAX_CHAINMASK_TABLES 5 ++ + struct ath12k_service_ext_param { + u32 default_conc_scan_config_bits; + u32 default_fw_config_bits; +@@ -2313,6 +2326,9 @@ struct ath12k_service_ext_param { + u32 max_bssid_rx_filters; + u32 num_hw_modes; + u32 num_phy; ++ u32 num_chainmask_tables; ++ struct ath12k_chainmask_table ++ chainmask_table[ATH12K_MAX_CHAINMASK_TABLES]; + }; + + struct ath12k_hw_mode_caps { +@@ -2321,6 +2337,18 @@ struct ath12k_hw_mode_caps { + u32 hw_mode_config_type; + }; + ++struct wmi_mac_phy_chainmask_combo { ++ u32 chainmask_table_id; ++ u32 num_valid_chainmask; ++} __packed; ++ ++struct wmi_mac_phy_chainmask_caps { ++ u32 tlv_header; ++ u32 supported_flags; ++ u32 chainmask; ++} __packed; ++ ++ + #define PSOC_HOST_MAX_MAC_SIZE (2) + #define PSOC_HOST_MAX_PHY_SIZE (3) + #define ATH12K_11B_SUPPORT BIT(0) +@@ -5026,6 +5054,9 @@ enum wmi_host_channel_width { + WMI_HOST_CHAN_WIDTH_80 = 2, + WMI_HOST_CHAN_WIDTH_160 = 3, + WMI_HOST_CHAN_WIDTH_80P80 = 4, ++ WMI_HOST_CHAN_WIDTH_320 = 7, ++ /*keep last */ ++ WMI_HOST_CHAN_WIDTH_MAX = 0xF, + }; + + enum wmi_dcs_interference_chan_segment { +@@ -6432,6 +6463,59 @@ struct wmi_critical_update_arg { + #define ATH12K_GET_LOWER_32_BITS(val) (val & ATH12K_LOWER_32_MASK) + #define ATH12K_GET_UPPER_32_BITS(val) ((val & ATH12K_UPPER_32_MASK) >> 32) + ++ ++#define WMI_ADFS_MODE_QUICK_OCAC 0 /* Agile preCAC */ ++#define WMI_ADFS_MODE_QUICK_RCAC 2 /* Agile Rolling CAC */ ++#define WMI_SUPPORT_CHAIN_MASK_ADFS BIT(31) ++ ++#define MIN_PRECAC_TIMEOUT (6 * 60 * 1000) /* 6 minutes */ ++#define MIN_WEATHER_RADAR_CHAN_PRECAC_TIMEOUT (6 * 10 * 60 * 1000) /* 1 hour */ ++#define MAX_PRECAC_TIMEOUT (4 * 60 * 60 * 1000) /* 4 hours */ ++#define MAX_WEATHER_RADAR_CHAN_PRECAC_TIMEOUT (24 * 60 * 60 * 1000) /* 24 hours */ ++#define MIN_RCAC_TIMEOUT (62 * 1000) /* 62 seconds */ ++#define MAX_RCAC_TIMEOUT 0xffffffff ++ ++struct wmi_vdev_adfs_ch_cfg_cmd { ++ u32 tlv_header; ++ u32 vdev_id; ++ u32 ocac_mode; ++ u32 min_duration_ms; ++ u32 max_duration_ms; ++ u32 chan_freq; ++ u32 chan_width; ++ /* ++ * Two center frequencies are required since agile channel switch ++ * has to support 160/165 MHz for products like Pine. ++ * For agile which supports only up to 80MHz (HK), ++ * freq2 will be 0 and ignored. ++ */ ++ union { ++ u32 center_freq; ++ u32 center_freq1; ++ }; ++ u32 center_freq2; ++} __packed; ++ ++struct wmi_vdev_adfs_ocac_abort_cmd { ++ u32 tlv_header; ++ u32 vdev_id; ++} __packed; ++ ++#define WMI_DFS_RADAR_DETECTED_IN_SERVICE_CHAN 0 ++#define WMI_DFS_RADAR_DETECTED_IN_OCAC_CHAN 1 ++ ++struct wmi_vdev_adfs_ocac_complete_event_fixed_param { ++ u32 vdev_id; ++ u32 chan_freq; ++ u32 chan_width; ++ union { ++ u32 center_freq; ++ u32 center_freq1; ++ }; ++ u32 status; ++ u32 center_freq2; ++} __packed; ++ + #define ATH12K_FW_STATS_BUF_SIZE (1024 * 1024) + + void ath12k_wmi_init_qcn9274(struct ath12k_base *ab, +@@ -6603,4 +6687,7 @@ int ath12k_wmi_mlo_teardown(struct ath12 + bool ath12k_wmi_is_mvr_supported(struct ath12k_base *ab); + int ath12k_wmi_pdev_multiple_vdev_restart(struct ath12k *ar, + struct wmi_pdev_multiple_vdev_restart_req_arg *arg); ++int ath12k_wmi_vdev_adfs_ch_cfg_cmd_send(struct ath12k *ar,u32 vdev_id, ++ struct cfg80211_chan_def *chandef); ++int ath12k_wmi_vdev_adfs_ocac_abort_cmd_send(struct ath12k *ar,u32 vdev_id); + #endif diff --git a/feeds/ipq95xx/mac80211/patches/qca/691-ath12k-Fix-client-connectivity-due-to-beacon-mode.patch b/feeds/ipq95xx/mac80211/patches/qca/691-ath12k-Fix-client-connectivity-due-to-beacon-mode.patch deleted file mode 100644 index e9caa32a2..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/691-ath12k-Fix-client-connectivity-due-to-beacon-mode.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 53ff5d3787c9e9649073b7a1f42c550e2320e07e Mon Sep 17 00:00:00 2001 -From: Ramya Gnanasekar -Date: Wed, 16 Nov 2022 00:47:33 +0530 -Subject: [PATCH] ath12k: Fix client connectivity due to beacon mode - -When beacon mode is set as BURST, facing client connectivity -failures with infra clients in AP + Mesh mode. -Configuring STAGGERED beacon mode as default. - -Signed-off-by: Ramya Gnanasekar - -diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index c703b1d..6fd6a50 100644 ---- a/drivers/net/wireless/ath/ath12k/mac.c -+++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -3614,7 +3614,10 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar, - - if (changed & BSS_CHANGED_BEACON) { - param_id = WMI_PDEV_PARAM_BEACON_TX_MODE; -- param_value = WMI_BEACON_BURST_MODE; -+ if (info->beacon_tx_mode == NL80211_BEACON_BURST_MODE) -+ param_value = WMI_BEACON_BURST_MODE; -+ else -+ param_value = WMI_BEACON_STAGGERED_MODE; - ret = ath12k_wmi_pdev_set_param(ar, param_id, - param_value, ar->pdev->pdev_id); - if (ret) -@@ -3622,8 +3625,8 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar, - arvif->vdev_id); - else - ath12k_dbg(ar->ab, ATH12K_DBG_MAC, -- "Set staggered beacon mode for VDEV: %d\n", -- arvif->vdev_id); -+ "Set %s beacon mode for VDEV: %d\n", -+ param_value ? "Burst" : "Staggered", arvif->vdev_id); - - if (!arvif->do_not_send_tmpl || !arvif->bcca_zero_sent) { - ret = ath12k_mac_setup_bcn_tmpl(arvif); --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/691-ath12k-Monitor-mode-bring-up-in-SLO.patch b/feeds/ipq95xx/mac80211/patches/qca/691-ath12k-Monitor-mode-bring-up-in-SLO.patch new file mode 100644 index 000000000..b7f6546df --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/691-ath12k-Monitor-mode-bring-up-in-SLO.patch @@ -0,0 +1,56 @@ +From 0ee9f6cc8bc156693f090b893a380c06ad9d88d2 Mon Sep 17 00:00:00 2001 +From: Rahul Bhattacharjee +Date: Tue, 13 Dec 2022 15:53:02 +0530 +Subject: [PATCH] ath12k: Monitor mode bring up in SLO + +Currently all the radios are sharing the same chandef, so during monitor +start wrong values are getting passed to FW, due to which we are seeing +FW assert. + +Fixed by adding a check, when ar is not compatible with the chandef, +it will stop the process. + +In addition, cfg80211 was not allowing to change the channels before +bringing up the interface, it needs at least one interface up to +change the channels. + +Hence, removing the check for number of running interfaces. + +Signed-off-by: Rahul Bhattacharjee +--- + drivers/net/wireless/ath/ath12k/mac.c | 4 ++++ + net/wireless/core.h | 3 +-- + 2 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index ef1218a..1b4bd09 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -1233,6 +1233,10 @@ static int ath12k_mac_monitor_start(struct ath12k *ar) + if (!chandef) + return 0; + ++ /* TODO 5G low high split changes */ ++ if (!ar->mac.sbands[chandef->chan->band].channels) ++ return -EINVAL; ++ + ret = ath12k_mac_monitor_vdev_start(ar, ar->monitor_vdev_id, chandef); + if (ret) { + ath12k_warn(ar->ab, "failed to start monitor vdev: %d\n", ret); +diff --git a/net/wireless/core.h b/net/wireless/core.h +index 55c535f..62101da 100644 +--- a/net/wireless/core.h ++++ b/net/wireless/core.h +@@ -239,8 +239,7 @@ static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device + { + lockdep_assert_held(&rdev->wiphy.mtx); + +- return rdev->num_running_ifaces == rdev->num_running_monitor_ifaces && +- rdev->num_running_ifaces > 0; ++ return rdev->num_running_ifaces == rdev->num_running_monitor_ifaces; + } + + enum cfg80211_event_type { +-- +2.38.0 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/691-ath12k-sub-channel-enable-for-dfs-channel-puncturing.patch b/feeds/ipq95xx/mac80211/patches/qca/691-ath12k-sub-channel-enable-for-dfs-channel-puncturing.patch new file mode 100644 index 000000000..7cf0c0104 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/691-ath12k-sub-channel-enable-for-dfs-channel-puncturing.patch @@ -0,0 +1,43 @@ +From 8ccb4cf61ea3439e234d747c87253d1ca7c7193d Mon Sep 17 00:00:00 2001 +From: Ramasamy Kaliappan +Date: Mon, 28 Nov 2022 11:53:02 +0530 +Subject: [PATCH] ath12k: sub channel enable for dfs channel puncturing feature + +The sub chan marking should be enabled in firmware to support +puncturing interference detected sub channel. + +Signed-off-by: Ramasamy Kaliappan +--- + drivers/net/wireless/ath/ath12k/mac.c | 8 ++++++++ + drivers/net/wireless/ath/ath12k/wmi.h | 1 + + 2 files changed, 9 insertions(+) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -8373,6 +8373,16 @@ static int ath12k_mac_radio_start(struct + goto err; + } + ++ /* Enable(1)/Disable(0) sub channel marking */ ++ if (pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP) { ++ ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_SUB_CHANNEL_MARKING, ++ 1, pdev->pdev_id); ++ if (ret) { ++ ath12k_err(ab, "failed to enable SUB CHANNEL MARKING: %d\n", ret); ++ goto err; ++ } ++ } ++ + __ath12k_set_antenna(ar, ar->cfg_tx_chainmask, ar->cfg_rx_chainmask); + + /* TODO: Do we need to enable ANI? */ +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -1004,6 +1004,7 @@ enum wmi_tlv_pdev_param { + WMI_PDEV_PARAM_RADIO_CHAN_STATS_ENABLE, + WMI_PDEV_PARAM_RADIO_DIAGNOSIS_ENABLE, + WMI_PDEV_PARAM_MESH_MCAST_ENABLE, ++ WMI_PDEV_PARAM_SUB_CHANNEL_MARKING = 0xb0, + WMI_PDEV_PARAM_SET_CMD_OBSS_PD_THRESHOLD = 0xbc, + WMI_PDEV_PARAM_SET_CMD_OBSS_PD_PER_AC = 0xbe, + WMI_PDEV_PARAM_ENABLE_SR_PROHIBIT = 0xc6, diff --git a/feeds/ipq95xx/mac80211/patches/qca/691-cfg80211-exported-cfg80211_chandef_dfs_cac_time-api.patch b/feeds/ipq95xx/mac80211/patches/qca/691-cfg80211-exported-cfg80211_chandef_dfs_cac_time-api.patch new file mode 100644 index 000000000..8d8de249b --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/691-cfg80211-exported-cfg80211_chandef_dfs_cac_time-api.patch @@ -0,0 +1,68 @@ +From 7458336bbfc4da894bdefc2621181000638d0afb Mon Sep 17 00:00:00 2001 +From: Karthik M +Date: Fri, 14 Apr 2023 19:46:32 +0530 +Subject: [PATCH] cfg80211 : exported cfg80211_chandef_dfs_cac_time api + +Driver needs this cfg80211_chandef_dfs_cac_time for calculating +the dfs_cac_time across the chandef + +Signed-off-by: Karthik M +--- + include/net/cfg80211.h | 12 ++++++++++++ + net/wireless/chan.c | 1 + + net/wireless/core.h | 4 ---- + 3 files changed, 13 insertions(+), 4 deletions(-) + +diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h +index a4ec6dd..614bb92 100644 +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -1028,6 +1028,18 @@ ieee80211_chandef_rate_flags(struct cfg80211_chan_def *chandef) + return ieee80211_chanwidth_rate_flags(chandef->width); + } + ++/** ++ * cfg80211_chandef_dfs_cac_time - get maximum dfs cac time traversing ++ * through the entire channel width ++ * @wiphy: the wiphy to validate against ++ * @chandef: the channel definition to check ++ * @is_bgcac: background cac state ++ * Returns: dfs cac time, or 0 is none found ++ */ ++unsigned int cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy, ++ const struct cfg80211_chan_def *chandef, ++ bool is_bgcac); ++ + /** + * ieee80211_chandef_max_power - maximum transmission power for the chandef + * +diff --git a/net/wireless/chan.c b/net/wireless/chan.c +index 4ca9bd0..b320d70 100644 +--- a/net/wireless/chan.c ++++ b/net/wireless/chan.c +@@ -1137,6 +1137,7 @@ exit: + + return dfs_cac_time; + } ++EXPORT_SYMBOL(cfg80211_chandef_dfs_cac_time); + + static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, + u32 center_freq, u32 bandwidth, +diff --git a/net/wireless/core.h b/net/wireless/core.h +index 55c535f..8f5c657 100644 +--- a/net/wireless/core.h ++++ b/net/wireless/core.h +@@ -478,10 +478,6 @@ void cfg80211_set_dfs_state(struct wiphy *wiphy, + + void cfg80211_dfs_channels_update_work(struct work_struct *work); + +-unsigned int +-cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy, +- const struct cfg80211_chan_def *chandef, bool is_bgcac); +- + void cfg80211_sched_dfs_chan_update(struct cfg80211_registered_device *rdev); + + int +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/691-mac80211-support-poll-sta-for-ML-clients.patch b/feeds/ipq95xx/mac80211/patches/qca/691-mac80211-support-poll-sta-for-ML-clients.patch new file mode 100644 index 000000000..b935c5ed8 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/691-mac80211-support-poll-sta-for-ML-clients.patch @@ -0,0 +1,96 @@ +From d4a49321b49feb70ae25c747e9acf368ebb67d66 Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Thu, 22 Dec 2022 05:46:29 +0530 +Subject: [PATCH] mac80211: support poll sta for ML clients + +Update the client probe handling which sends Null data +frames to check inactivity to support ML Stations as well. + +Replace the use of default bss conf with the link specific +conf and use the stations default link to send the probe +frame. Non ML Stations associated to the ML AP would use +its default link as well which is one of the active links. + +For Non ML AP, the default link id is 0 and it is taken care +as well. + +Signed-off-by: Sriram R +--- + net/mac80211/cfg.c | 35 +++++++++++++++++++++++++++-------- + 1 file changed, 27 insertions(+), 8 deletions(-) + +diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c +index c22dacb..280d2b1 100644 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -4184,17 +4184,13 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, + struct ieee80211_chanctx_conf *chanctx_conf; + enum nl80211_band band; + int ret; ++ u8 link_id; ++ struct ieee80211_bss_conf *conf; + + /* the lock is needed to assign the cookie later */ + mutex_lock(&local->mtx); + + rcu_read_lock(); +- chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf); +- if (WARN_ON(!chanctx_conf)) { +- ret = -EINVAL; +- goto unlock; +- } +- band = chanctx_conf->def.chan->band; + sta = sta_info_get_bss(sdata, peer); + if (sta) { + qos = sta->sta.wme; +@@ -4203,6 +4199,27 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, + goto unlock; + } + ++ /* In case of ML vif, we shall use the default sta link to ++ * send the probe frame. For non ML vif the link id 0 is ++ * the deflink ++ */ ++ link_id = sta->deflink.link_id; ++ ++ conf = rcu_dereference(sdata->vif.link_conf[link_id]); ++ ++ if (unlikely(!conf)) { ++ ret = -ENOLINK; ++ goto unlock; ++ } ++ ++ chanctx_conf = rcu_dereference(conf->chanctx_conf); ++ if (WARN_ON(!chanctx_conf)) { ++ ret = -EINVAL; ++ goto unlock; ++ } ++ ++ band = chanctx_conf->def.chan->band; ++ + if (qos) { + fc = cpu_to_le16(IEEE80211_FTYPE_DATA | + IEEE80211_STYPE_QOS_NULLFUNC | +@@ -4228,8 +4245,8 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, + 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, conf->addr, ETH_ALEN); ++ memcpy(nullfunc->addr3, conf->addr, ETH_ALEN); + nullfunc->seq_ctrl = 0; + + info = IEEE80211_SKB_CB(skb); +@@ -4238,6 +4255,8 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, + IEEE80211_TX_INTFL_NL80211_FRAME_TX; + info->band = band; + ++ info->control.flags |= u32_encode_bits(link_id, IEEE80211_TX_CTRL_MLO_LINK); ++ + skb_set_queue_mapping(skb, IEEE80211_AC_VO); + skb->priority = 7; + if (qos) +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/692-0001-cfg80211-mac80211-add-DFS-support-for-MLO.patch b/feeds/ipq95xx/mac80211/patches/qca/692-0001-cfg80211-mac80211-add-DFS-support-for-MLO.patch new file mode 100644 index 000000000..1dff3f41a --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/692-0001-cfg80211-mac80211-add-DFS-support-for-MLO.patch @@ -0,0 +1,792 @@ +From 3204c1c02d7e85b8dd02357d1f8bb5ae3cd429bd Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Mon, 12 Dec 2022 10:04:23 +0530 +Subject: [PATCH 1/2] cfg80211/mac80211: add DFS support for MLO + +Currently, Dynamic Frequency Selection (DFS) and its related radar +events was supported only for non-MLO case where deflink +(or link_id 0) was always considered. +However, with MLO in place, there is need to handle DFS in per-link +manner instead of always assuming link_id 0. + +Add support to handle DFS and radar related events per-link basis. + +Signed-off-by: Aditya Kumar Singh +--- + include/net/cfg80211.h | 23 +++++++++++--------- + net/mac80211/cfg.c | 47 +++++++++++++++++++++++++++++------------ + net/mac80211/iface.c | 4 ++-- + net/mac80211/link.c | 26 ++++++++++++++++++++++- + net/mac80211/mlme.c | 12 +++++------ + net/mac80211/scan.c | 3 ++- + net/mac80211/util.c | 34 +++++++++++++++++++++-------- + net/wireless/mlme.c | 20 ++++++++---------- + net/wireless/nl80211.c | 29 +++++++++++++++++++------ + net/wireless/rdev-ops.h | 12 ++++++----- + net/wireless/reg.c | 19 ++++++++++------- + net/wireless/trace.h | 29 +++++++++++++++---------- + 12 files changed, 173 insertions(+), 85 deletions(-) + +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -992,6 +992,16 @@ int cfg80211_chandef_dfs_required(struct + enum nl80211_iftype iftype); + + /** ++ * cfg80211_chandef_dfs_available - checks if radar is already available ++ * @wiphy: the wiphy to validate against ++ * @chandef: the channel definition to check ++ * Returns: ++ * true if all channels are radar available, false otherwise ++ */ ++bool cfg80211_chandef_dfs_available(struct wiphy *wiphy, ++ const struct cfg80211_chan_def *chandef); ++ ++/** + * ieee80211_chanwidth_rate_flags - return rate flags for channel width + * @width: the channel width of the channel + * +@@ -4657,10 +4667,12 @@ struct cfg80211_ops { + + int (*start_radar_detection)(struct wiphy *wiphy, + struct net_device *dev, ++ unsigned int link_id, + struct cfg80211_chan_def *chandef, + u32 cac_time_ms); + void (*end_cac)(struct wiphy *wiphy, +- struct net_device *dev); ++ struct net_device *dev, ++ unsigned int link_id); + int (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_update_ft_ies_params *ftie); + int (*crit_proto_start)(struct wiphy *wiphy, +@@ -5957,9 +5969,6 @@ static inline void wiphy_unlock(struct w + * @address: The address for this device, valid only if @netdev is %NULL + * @is_running: true if this is a non-netdev device that has been started, e.g. + * the P2P Device. +- * @cac_started: true if DFS channel availability check has been started +- * @cac_start_time: timestamp (jiffies) when the dfs state was entered. +- * @cac_time_ms: CAC time in ms + * @ps: powersave mode is enabled + * @ps_timeout: dynamic powersave timeout + * @ap_unexpected_nlportid: (private) netlink port ID of application +@@ -5982,6 +5991,9 @@ static inline void wiphy_unlock(struct w + * unprotected beacon report + * @links: array of %IEEE80211_MLD_MAX_NUM_LINKS elements containing @addr + * @ap and @client for each link ++ * @links[].cac_started: true if DFS channel availability check has been started ++ * @links[].cac_start_time: timestamp (jiffies) when the dfs state was entered. ++ * @links[].cac_time_ms: CAC time in ms + * @valid_links: bitmap describing what elements of @links are valid + */ + struct wireless_dev { +@@ -6025,11 +6037,6 @@ struct wireless_dev { + u32 owner_nlportid; + bool nl_owner_dead; + +- /* FIXME: need to rework radar detection for MLO */ +- bool cac_started; +- unsigned long cac_start_time; +- unsigned int cac_time_ms; +- + #ifdef CPTCFG_CFG80211_WEXT + /* wext data */ + struct { +@@ -6095,6 +6102,10 @@ struct wireless_dev { + struct cfg80211_internal_bss *current_bss; + } client; + }; ++ ++ bool cac_started; ++ unsigned long cac_start_time; ++ unsigned int cac_time_ms; + } links[IEEE80211_MLD_MAX_NUM_LINKS]; + u16 valid_links; + +@@ -8407,6 +8418,7 @@ void cfg80211_sta_opmode_change_notify(s + * @chandef: chandef for the current channel + * @event: type of event + * @gfp: context flags ++ * @link_id: valid link_id for MLO operation or 0 otherwise. + * + * This function is called when a Channel availability check (CAC) is finished + * or aborted. This must be called to notify the completion of a CAC process, +@@ -8414,7 +8426,8 @@ void cfg80211_sta_opmode_change_notify(s + */ + void cfg80211_cac_event(struct net_device *netdev, + const struct cfg80211_chan_def *chandef, +- enum nl80211_radar_event event, gfp_t gfp); ++ enum nl80211_radar_event event, gfp_t gfp, ++ unsigned int link_id); + + /** + * cfg80211_background_cac_abort - Channel Availability Check offchan abort event +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1658,12 +1658,12 @@ static int ieee80211_stop_ap(struct wiph + ieee80211_link_info_change_notify(sdata, link, + BSS_CHANGED_BEACON_ENABLED); + +- if (sdata->wdev.cac_started) { ++ if (sdata->wdev.links[link_id].cac_started) { + chandef = link_conf->chandef; + cancel_delayed_work_sync(&link->dfs_cac_timer_work); + cfg80211_cac_event(sdata->dev, &chandef, + NL80211_RADAR_CAC_ABORTED, +- GFP_KERNEL); ++ GFP_KERNEL, link_id); + } + + drv_stop_ap(sdata->local, sdata, link_conf); +@@ -3460,13 +3460,19 @@ static int ieee80211_set_bitrate_mask(st + + static int ieee80211_start_radar_detection(struct wiphy *wiphy, + struct net_device *dev, ++ unsigned int link_id, + struct cfg80211_chan_def *chandef, + u32 cac_time_ms) + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; ++ struct ieee80211_link_data *link; + int err; + ++ link = sdata_dereference(sdata->link[link_id], sdata); ++ if (!link) ++ return -ENOLINK; ++ + mutex_lock(&local->mtx); + if (!list_empty(&local->roc_list) || local->scanning) { + err = -EBUSY; +@@ -3474,16 +3480,16 @@ static int ieee80211_start_radar_detecti + } + + /* whatever, but channel contexts should not complain about that one */ +- sdata->deflink.smps_mode = IEEE80211_SMPS_OFF; +- sdata->deflink.needed_rx_chains = local->rx_chains; ++ link->smps_mode = IEEE80211_SMPS_OFF; ++ link->needed_rx_chains = local->rx_chains; + +- err = ieee80211_link_use_channel(&sdata->deflink, chandef, ++ err = ieee80211_link_use_channel(link, chandef, + IEEE80211_CHANCTX_SHARED); + if (err) + goto out_unlock; + + ieee80211_queue_delayed_work(&sdata->local->hw, +- &sdata->deflink.dfs_cac_timer_work, ++ &link->dfs_cac_timer_work, + msecs_to_jiffies(cac_time_ms)); + + out_unlock: +@@ -3492,22 +3498,30 @@ static int ieee80211_start_radar_detecti + } + + static void ieee80211_end_cac(struct wiphy *wiphy, +- struct net_device *dev) ++ struct net_device *dev, ++ unsigned int link_id) + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; ++ struct ieee80211_link_data *link; + + mutex_lock(&local->mtx); + list_for_each_entry(sdata, &local->interfaces, list) { + /* it might be waiting for the local->mtx, but then +- * by the time it gets it, sdata->wdev.cac_started +- * will no longer be true ++ * by the time it gets it, ++ * sdata->wdev.links[link_id].cac_started will no ++ * longer be true + */ +- cancel_delayed_work(&sdata->deflink.dfs_cac_timer_work); ++ link = sdata_dereference(sdata->link[link_id], sdata); ++ ++ if (!link) ++ continue; ++ ++ cancel_delayed_work(&link->dfs_cac_timer_work); + +- if (sdata->wdev.cac_started) { +- ieee80211_link_release_channel(&sdata->deflink); +- sdata->wdev.cac_started = false; ++ if (sdata->wdev.links[link_id].cac_started) { ++ ieee80211_link_release_channel(link); ++ sdata->wdev.links[link_id].cac_started = false; + } + } + mutex_unlock(&local->mtx); +@@ -3996,7 +4010,7 @@ __ieee80211_channel_switch(struct wiphy + if (!list_empty(&local->roc_list) || local->scanning) + return -EBUSY; + +- if (sdata->wdev.cac_started) ++ if (sdata->wdev.links[link_id].cac_started) + return -EBUSY; + + link = sdata_dereference(sdata->link[link_id], sdata); +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -487,7 +487,7 @@ static void ieee80211_do_stop(struct iee + + cancel_delayed_work_sync(&sdata->deflink.dfs_cac_timer_work); + +- if (sdata->wdev.cac_started) { ++ if (sdata->wdev.links[0].cac_started) { + chandef = sdata->vif.bss_conf.chandef; + WARN_ON(local->suspended); + mutex_lock(&local->mtx); +@@ -495,7 +495,7 @@ static void ieee80211_do_stop(struct iee + mutex_unlock(&local->mtx); + cfg80211_cac_event(sdata->dev, &chandef, + NL80211_RADAR_CAC_ABORTED, +- GFP_KERNEL); ++ GFP_KERNEL, 0); + } + + if (sdata->vif.type == NL80211_IFTYPE_AP) { +--- a/net/mac80211/link.c ++++ b/net/mac80211/link.c +@@ -101,9 +101,33 @@ static void ieee80211_free_links(struct + struct link_container **links) + { + unsigned int link_id; ++ struct ieee80211_link_data *link; ++ struct ieee80211_bss_conf *link_conf; ++ struct cfg80211_chan_def chandef; ++ ++ for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) { ++ link = &links[link_id]->data; ++ link_conf = &links[link_id]->conf; ++ ++ if (!link || !link_conf) ++ continue; ++ ++ cancel_delayed_work(&link->dfs_cac_timer_work); ++ ++ if (sdata->wdev.links[link_id].cac_started) { ++ chandef = link_conf->chandef; ++ WARN_ON(sdata->local->suspended); ++ mutex_lock(&sdata->local->mtx); ++ ieee80211_link_release_channel(link); ++ mutex_unlock(&sdata->local->mtx); ++ cfg80211_cac_event(sdata->dev, ++ &chandef, ++ NL80211_RADAR_CAC_ABORTED, ++ GFP_KERNEL, link_id); ++ } + +- for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) + kfree(links[link_id]); ++ } + } + + static int ieee80211_check_dup_link_addrs(struct ieee80211_sub_if_data *sdata) +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -2340,12 +2340,14 @@ void ieee80211_dfs_cac_timer_work(struct + struct ieee80211_sub_if_data *sdata = link->sdata; + + mutex_lock(&sdata->local->mtx); +- if (sdata->wdev.cac_started) { ++ ++ if (sdata->wdev.links[link->link_id].cac_started) { + ieee80211_link_release_channel(link); + cfg80211_cac_event(sdata->dev, &chandef, + NL80211_RADAR_CAC_FINISHED, +- GFP_KERNEL); ++ GFP_KERNEL, link->link_id); + } ++ + mutex_unlock(&sdata->local->mtx); + } + +--- a/net/mac80211/scan.c ++++ b/net/mac80211/scan.c +@@ -584,7 +584,8 @@ static bool __ieee80211_can_leave_ch(str + + mutex_lock(&local->iflist_mtx); + list_for_each_entry(sdata_iter, &local->interfaces, list) { +- if (sdata_iter->wdev.cac_started) { ++ /* TODO: link_id with MLO. */ ++ if (sdata_iter->wdev.links[0].cac_started) { + mutex_unlock(&local->iflist_mtx); + return false; + } +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -4238,6 +4238,9 @@ void ieee80211_dfs_cac_cancel(struct iee + { + struct ieee80211_sub_if_data *sdata; + struct cfg80211_chan_def chandef; ++ struct ieee80211_link_data *link; ++ struct ieee80211_bss_conf *link_conf; ++ unsigned int link_id; + + /* for interface list, to avoid linking iflist_mtx and chanctx_mtx */ + lockdep_assert_wiphy(local->hw.wiphy); +@@ -4248,15 +4251,28 @@ void ieee80211_dfs_cac_cancel(struct iee + * by the time it gets it, sdata->wdev.cac_started + * will no longer be true + */ +- cancel_delayed_work(&sdata->deflink.dfs_cac_timer_work); ++ for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) { ++ link = sdata_dereference(sdata->link[link_id], sdata); + +- if (sdata->wdev.cac_started) { +- chandef = sdata->vif.bss_conf.chandef; +- ieee80211_link_release_channel(&sdata->deflink); +- cfg80211_cac_event(sdata->dev, +- &chandef, ++ if (!link) ++ continue; ++ ++ cancel_delayed_work(&link->dfs_cac_timer_work); ++ ++ if (!sdata->wdev.links[link_id].cac_started) ++ continue; ++ ++ link_conf = ++ rcu_dereference(sdata->vif.link_conf[link_id]); ++ ++ if (!link_conf) ++ continue; ++ ++ chandef = link_conf->chandef; ++ ieee80211_link_release_channel(link); ++ cfg80211_cac_event(sdata->dev, &chandef, + NL80211_RADAR_CAC_ABORTED, +- GFP_KERNEL); ++ GFP_KERNEL, link_id); + } + } + mutex_unlock(&local->mtx); +@@ -4290,9 +4306,11 @@ void ieee80211_awgn_detected_work(struct + + static void + ieee80211_dfs_radar_detected_processing(struct ieee80211_local *local, +- u16 radar_bitmap) ++ u16 radar_bitmap, ++ struct ieee80211_channel *radar_channel) + { + struct cfg80211_chan_def chandef = local->hw.conf.chandef; ++ struct cfg80211_chan_def *radar_chandef = NULL; + struct ieee80211_chanctx *ctx; + int num_chanctx = 0; + +@@ -4303,6 +4321,10 @@ ieee80211_dfs_radar_detected_processing( + + num_chanctx++; + chandef = ctx->conf.def; ++ ++ if (radar_channel && ++ (chandef.chan == radar_channel)) ++ radar_chandef = &ctx->conf.def; + } + mutex_unlock(&local->chanctx_mtx); + +@@ -4310,13 +4332,24 @@ ieee80211_dfs_radar_detected_processing( + ieee80211_dfs_cac_cancel(local); + wiphy_unlock(local->hw.wiphy); + ++ if (radar_chandef) ++ radar_chandef->radar_bitmap = radar_bitmap; ++ + chandef.radar_bitmap = radar_bitmap; + +- if (num_chanctx > 1) +- /* XXX: multi-channel is not supported yet */ +- WARN_ON(1); +- else ++ if (num_chanctx > 1) { ++ if (local->hw.wiphy->flags & WIPHY_FLAG_SUPPORTS_MLO) { ++ if (WARN_ON(!radar_chandef)) ++ return; ++ ++ cfg80211_radar_event(local->hw.wiphy, radar_chandef, GFP_KERNEL); ++ } else { ++ /* XXX: multi-channel is not supported yet */ ++ WARN_ON(1); ++ } ++ } else { + cfg80211_radar_event(local->hw.wiphy, &chandef, GFP_KERNEL); ++ } + } + + void ieee80211_dfs_radar_detected_work(struct work_struct *work) +@@ -4325,14 +4358,18 @@ void ieee80211_dfs_radar_detected_work(s + container_of(work, struct ieee80211_local, radar_detected_work); + struct channel_radar_info *radar_info, *temp; + u16 radar_bitmap; ++ struct ieee80211_channel *radar_channel; + + if (list_empty(&local->radar_info_list)) +- return ieee80211_dfs_radar_detected_processing(local, 0); ++ return ieee80211_dfs_radar_detected_processing(local, 0, ++ radar_channel); + + list_for_each_entry_safe(radar_info, temp, &local->radar_info_list, list) { + radar_bitmap = radar_info->radar_bitmap; ++ radar_channel = radar_info->radar_channel; + +- ieee80211_dfs_radar_detected_processing(local, radar_bitmap); ++ ieee80211_dfs_radar_detected_processing(local, radar_bitmap, ++ radar_channel); + + list_del(&radar_info->list); + kfree(radar_info); +@@ -4349,17 +4386,23 @@ void ieee80211_radar_detected(struct iee + } + EXPORT_SYMBOL(ieee80211_radar_detected); + +-void ieee80211_radar_detected_bitmap(struct ieee80211_hw *hw, u16 radar_bitmap) ++void ieee80211_radar_detected_bitmap(struct ieee80211_hw *hw, u16 radar_bitmap, ++ struct ieee80211_channel *radar_channel) + { + struct ieee80211_local *local = hw_to_local(hw); + struct channel_radar_info *radar_info; + ++ if (WARN_ON(local->hw.wiphy->flags & WIPHY_FLAG_SUPPORTS_MLO && ++ !radar_channel)) ++ return; ++ + radar_info = kzalloc(sizeof(*radar_info), GFP_ATOMIC); + if (!radar_info) + return; + + INIT_LIST_HEAD(&radar_info->list); + radar_info->radar_bitmap = radar_bitmap; ++ radar_info->radar_channel = radar_channel; + + list_add_tail(&radar_info->list, &local->radar_info_list); + schedule_work(&local->radar_detected_work); +--- a/net/wireless/mlme.c ++++ b/net/wireless/mlme.c +@@ -974,26 +974,24 @@ EXPORT_SYMBOL(cfg80211_awgn_event); + + void cfg80211_cac_event(struct net_device *netdev, + const struct cfg80211_chan_def *chandef, +- enum nl80211_radar_event event, gfp_t gfp) ++ enum nl80211_radar_event event, gfp_t gfp, ++ unsigned int link_id) + { + struct wireless_dev *wdev = netdev->ieee80211_ptr; + struct wiphy *wiphy = wdev->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); + unsigned long timeout; + +- /* not yet supported */ +- if (wdev->valid_links) +- return; +- +- trace_cfg80211_cac_event(netdev, event); ++ trace_cfg80211_cac_event(netdev, link_id, event); + +- if (WARN_ON(!wdev->cac_started && event != NL80211_RADAR_CAC_STARTED)) ++ if (WARN_ON(!wdev->links[link_id].cac_started && ++ event != NL80211_RADAR_CAC_STARTED)) + return; + + switch (event) { + case NL80211_RADAR_CAC_FINISHED: +- timeout = wdev->cac_start_time + +- msecs_to_jiffies(wdev->cac_time_ms); ++ timeout = wdev->links[link_id].cac_start_time + ++ msecs_to_jiffies(wdev->links[link_id].cac_time_ms); + WARN_ON(!time_after_eq(jiffies, timeout)); + cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE); + memcpy(&rdev->cac_done_chandef, chandef, +@@ -1002,10 +1000,10 @@ void cfg80211_cac_event(struct net_devic + cfg80211_sched_dfs_chan_update(rdev); + fallthrough; + case NL80211_RADAR_CAC_ABORTED: +- wdev->cac_started = false; ++ wdev->links[link_id].cac_started = false; + break; + case NL80211_RADAR_CAC_STARTED: +- wdev->cac_started = true; ++ wdev->links[link_id].cac_started = true; + break; + default: + WARN_ON(1); +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -10392,6 +10392,7 @@ static int nl80211_start_radar_detection + struct net_device *dev = info->user_ptr[1]; + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct wiphy *wiphy = wdev->wiphy; ++ int link_id = nl80211_link_id(info->attrs); + struct cfg80211_chan_def chandef; + enum nl80211_dfs_regions dfs_region; + unsigned int cac_time_ms; +@@ -10400,6 +10401,7 @@ static int nl80211_start_radar_detection + flush_delayed_work(&rdev->dfs_update_channels_wk); + + wiphy_lock(wiphy); ++ wdev_lock(wdev); + + dfs_region = reg_get_dfs_region(wiphy); + if (dfs_region == NL80211_DFS_UNSET) +@@ -10434,7 +10436,7 @@ static int nl80211_start_radar_detection + goto unlock; + } + +- if (wdev->cac_started) { ++ if (wdev->links[link_id].cac_started) { + err = -EBUSY; + goto unlock; + } +@@ -10455,14 +10457,21 @@ static int nl80211_start_radar_detection + if (WARN_ON(!cac_time_ms)) + cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS; + +- err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms); ++ err = rdev_start_radar_detection(rdev, dev, link_id, ++ &chandef, cac_time_ms); + if (!err) { +- wdev->links[0].ap.chandef = chandef; +- wdev->cac_started = true; +- wdev->cac_start_time = jiffies; +- wdev->cac_time_ms = cac_time_ms; ++ if (wdev->iftype == NL80211_IFTYPE_MESH_POINT) ++ wdev->u.mesh.chandef = chandef; ++ else if (wdev->iftype == NL80211_IFTYPE_AP) ++ wdev->links[link_id].ap.chandef = chandef; ++ ++ wdev->links[link_id].cac_started = true; ++ wdev->links[link_id].cac_start_time = jiffies; ++ wdev->links[link_id].cac_time_ms = cac_time_ms; + } ++ + unlock: ++ wdev_unlock(wdev); + wiphy_unlock(wiphy); + + return err; +@@ -16795,6 +16804,10 @@ nl80211_remove_link_station(struct sk_bu + SELECTOR(__sel, NETDEV_UP_LINK, \ + NL80211_FLAG_NEED_NETDEV_UP | \ + NL80211_FLAG_MLO_VALID_LINK_ID) \ ++ SELECTOR(__sel, NETDEV_UP_LINK_NOMTX, \ ++ NL80211_FLAG_NEED_NETDEV_UP | \ ++ NL80211_FLAG_NO_WIPHY_MTX | \ ++ NL80211_FLAG_MLO_VALID_LINK_ID) \ + SELECTOR(__sel, NETDEV_UP_NO_MLO, \ + NL80211_FLAG_NEED_NETDEV_UP | \ + NL80211_FLAG_MLO_UNSUPPORTED) \ +@@ -17698,7 +17711,7 @@ static const struct genl_small_ops nl802 + .flags = GENL_UNS_ADMIN_PERM, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_NO_WIPHY_MTX | +- NL80211_FLAG_MLO_UNSUPPORTED), ++ NL80211_FLAG_MLO_VALID_LINK_ID), + }, + { + .cmd = NL80211_CMD_GET_PROTOCOL_FEATURES, +--- a/net/wireless/rdev-ops.h ++++ b/net/wireless/rdev-ops.h +@@ -1186,15 +1186,17 @@ rdev_tdls_cancel_channel_switch(struct c + static inline int + rdev_start_radar_detection(struct cfg80211_registered_device *rdev, + struct net_device *dev, ++ unsigned int link_id, + struct cfg80211_chan_def *chandef, + u32 cac_time_ms) + { + int ret = -ENOTSUPP; + +- trace_rdev_start_radar_detection(&rdev->wiphy, dev, chandef, +- cac_time_ms); ++ trace_rdev_start_radar_detection(&rdev->wiphy, dev, link_id, ++ chandef, cac_time_ms); + if (rdev->ops->start_radar_detection) + ret = rdev->ops->start_radar_detection(&rdev->wiphy, dev, ++ link_id, + chandef, cac_time_ms); + trace_rdev_return_int(&rdev->wiphy, ret); + return ret; +@@ -1202,11 +1204,11 @@ rdev_start_radar_detection(struct cfg802 + + static inline void + rdev_end_cac(struct cfg80211_registered_device *rdev, +- struct net_device *dev) ++ struct net_device *dev, unsigned int link_id) + { +- trace_rdev_end_cac(&rdev->wiphy, dev); ++ trace_rdev_end_cac(&rdev->wiphy, dev, link_id); + if (rdev->ops->end_cac) +- rdev->ops->end_cac(&rdev->wiphy, dev); ++ rdev->ops->end_cac(&rdev->wiphy, dev, link_id); + trace_rdev_return_void(&rdev->wiphy); + } + +--- a/net/wireless/reg.c ++++ b/net/wireless/reg.c +@@ -4267,6 +4267,8 @@ EXPORT_SYMBOL(regulatory_pre_cac_allowed + static void cfg80211_check_and_end_cac(struct cfg80211_registered_device *rdev) + { + struct wireless_dev *wdev; ++ unsigned int link_id; ++ + /* If we finished CAC or received radar, we should end any + * CAC running on the same channels. + * the check !cfg80211_chandef_dfs_usable contain 2 options: +@@ -4279,16 +4281,17 @@ static void cfg80211_check_and_end_cac(s + list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) { + struct cfg80211_chan_def *chandef; + +- if (!wdev->cac_started) +- continue; ++ for_each_valid_link(wdev, link_id) { ++ if (!wdev->links[link_id].cac_started) ++ continue; + +- /* FIXME: radar detection is tied to link 0 for now */ +- chandef = wdev_chandef(wdev, 0); +- if (!chandef) +- continue; ++ chandef = wdev_chandef(wdev, link_id); ++ if (!chandef) ++ continue; + +- if (!cfg80211_chandef_dfs_usable(&rdev->wiphy, chandef)) +- rdev_end_cac(rdev, wdev->netdev); ++ if (!cfg80211_chandef_dfs_usable(&rdev->wiphy, chandef)) ++ rdev_end_cac(rdev, wdev->netdev, link_id); ++ } + } + } + +--- a/net/wireless/trace.h ++++ b/net/wireless/trace.h +@@ -732,8 +732,9 @@ DEFINE_EVENT(wiphy_netdev_evt, rdev_flus + ); + + DEFINE_EVENT(wiphy_netdev_evt, rdev_end_cac, +- TP_PROTO(struct wiphy *wiphy, struct net_device *netdev), +- TP_ARGS(wiphy, netdev) ++ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, ++ unsigned int link_id), ++ TP_ARGS(wiphy, netdev, link_id) + ); + + DECLARE_EVENT_CLASS(station_add_change, +@@ -2553,25 +2554,28 @@ TRACE_EVENT(rdev_external_auth, + + TRACE_EVENT(rdev_start_radar_detection, + TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, ++ int link_id, + struct cfg80211_chan_def *chandef, + u32 cac_time_ms), +- TP_ARGS(wiphy, netdev, chandef, cac_time_ms), ++ TP_ARGS(wiphy, netdev, link_id, chandef, cac_time_ms), + TP_STRUCT__entry( + WIPHY_ENTRY + NETDEV_ENTRY ++ __field(u8, link_id) + CHAN_DEF_ENTRY + __field(u32, cac_time_ms) + ), + TP_fast_assign( + WIPHY_ASSIGN; + NETDEV_ASSIGN; ++ __entry->link_id = link_id; + CHAN_DEF_ASSIGN(chandef); + __entry->cac_time_ms = cac_time_ms; + ), +- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT +- ", cac_time_ms=%u", +- WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG, +- __entry->cac_time_ms) ++ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", link_id=%u," ++ CHAN_DEF_PR_FMT ", cac_time_ms=%u", ++ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->link_id, ++ CHAN_DEF_PR_ARG, __entry->cac_time_ms) + ); + + TRACE_EVENT(rdev_set_mcast_rate, +@@ -3308,18 +3312,21 @@ TRACE_EVENT(cfg80211_radar_event, + ); + + TRACE_EVENT(cfg80211_cac_event, +- TP_PROTO(struct net_device *netdev, enum nl80211_radar_event evt), +- TP_ARGS(netdev, evt), ++ TP_PROTO(struct net_device *netdev, unsigned int link_id, ++ enum nl80211_radar_event evt), ++ TP_ARGS(netdev, link_id, evt), + TP_STRUCT__entry( + NETDEV_ENTRY ++ __field(unsigned int, link_id) + __field(enum nl80211_radar_event, evt) + ), + TP_fast_assign( + NETDEV_ASSIGN; ++ __entry->link_id = link_id; + __entry->evt = evt; + ), +- TP_printk(NETDEV_PR_FMT ", event: %d", +- NETDEV_PR_ARG, __entry->evt) ++ TP_printk(NETDEV_PR_FMT ", link_id: %d event: %d", ++ NETDEV_PR_ARG, __entry->link_id, __entry->evt) + ); + + DECLARE_EVENT_CLASS(cfg80211_rx_evt, +--- a/net/wireless/chan.c ++++ b/net/wireless/chan.c +@@ -1022,8 +1022,8 @@ static bool cfg80211_get_chans_dfs_avail + return true; + } + +-static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy, +- const struct cfg80211_chan_def *chandef) ++bool cfg80211_chandef_dfs_available(struct wiphy *wiphy, ++ const struct cfg80211_chan_def *chandef) + { + int width; + int r; +@@ -1057,6 +1057,7 @@ static bool cfg80211_chandef_dfs_availab + + return r; + } ++EXPORT_SYMBOL(cfg80211_chandef_dfs_available); + + static unsigned int cfg80211_get_chans_dfs_cac_time(struct wiphy *wiphy, + u32 center_freq, +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -6576,8 +6576,11 @@ void ieee80211_radar_detected(struct iee + * with bitmap + * @hw: pointer as obtained from ieee80211_alloc_hw() + * @radar_bitmap: denotes the bitmap of radar. ++ * @radar_channel: Channel pointer on which radar is detected. Mandatory to pass ++ * for MLO drivers. For non-MLO %NULL can be passed + */ +-void ieee80211_radar_detected_bitmap(struct ieee80211_hw *hw, u16 radar_bitmap); ++void ieee80211_radar_detected_bitmap(struct ieee80211_hw *hw, u16 radar_bitmap, ++ struct ieee80211_channel *radar_channel); + + + /** +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1296,6 +1296,7 @@ struct mac80211_memory_stats { + struct channel_radar_info { + struct list_head list; + u16 radar_bitmap; ++ struct ieee80211_channel *radar_channel; + }; + + struct ieee80211_local { +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -8447,7 +8447,8 @@ static void ath12k_dfs_calculate_subchan + + mark_radar: + if (!radar->detector_id) { +- ieee80211_radar_detected_bitmap(ar->ah->hw,radar_bitmap); ++ ieee80211_radar_detected_bitmap(ar->ah->hw, radar_bitmap, ++ chandef->chan); + } else { + ar->agile_chandef.radar_bitmap = radar_bitmap; + ath12k_mac_background_dfs_event(ar, ATH12K_BGDFS_RADAR); diff --git a/feeds/ipq95xx/mac80211/patches/qca/692-0002-ath12k-add-initial-DFS-MLO-support.patch b/feeds/ipq95xx/mac80211/patches/qca/692-0002-ath12k-add-initial-DFS-MLO-support.patch new file mode 100644 index 000000000..6958ea3d4 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/692-0002-ath12k-add-initial-DFS-MLO-support.patch @@ -0,0 +1,103 @@ +From 7ea127667c219c9296b7e76b0b2cf78b9652d389 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Mon, 12 Dec 2022 10:15:51 +0530 +Subject: [PATCH 2/2] ath12k: add initial DFS MLO support + +For MLO case, there is need to let the vdev get created in order +to start the CAC even though the partner vdevs are not yet created. + +Add logic to create and start the vdev in MLO case. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath12k/mac.c | 49 +++++++++++++++++++++++++-- + 1 file changed, 47 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -10044,14 +10044,63 @@ static int ath12k_mac_mlo_vdev_start(str + int ret = 0; + u16 links_map; + bool radar_enabled = arvif->chanctx.radar_enabled; ++ bool radar_vdev_create = false; + + lockdep_assert_held(&ah->conf_mutex); +- /* TODO some changes are expected in this func wrt DFS statemachine */ + /* FIXME Note that this logic is temp and wont work for MBSSID cases + * There are two options, 1, the set link should have some pre channel info + * or FW should support dynamic partner add/remove support + */ + ++ /* check if we need to do CAC here and allow the link to start. ++ */ ++ ret = cfg80211_chandef_dfs_required(ah->hw->wiphy, ++ &arvif->chanctx.def, ++ NL80211_IFTYPE_AP); ++ if (ret > 0) { ++ ret = cfg80211_chandef_dfs_available(ah->hw->wiphy, ++ &arvif->chanctx.def); ++ if (!ret) { ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, ++ "mac mlo vdev %d radar required", ++ arvif->vdev_id); ++ radar_vdev_create = true; ++ } else { ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, ++ "mac mlo vdev %d radar available, wait for sync", ++ arvif->vdev_id); ++ radar_vdev_create = false; ++ ret = 0; ++ } ++ } else if (WARN_ON(ret < 0)) { ++ /* should not reach here */ ++ return -EINVAL; ++ } ++ ++ /* As per DFS state machine, vdev should be allowed to get created for ++ * CAC to happen even if other link's vdevs are not yet created ++ */ ++ if (radar_vdev_create && ++ (ahvif->num_vdev_created != hweight16(ahvif->vif->valid_links))) { ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac allowing MLO DFS vdev create"); ++ ++ mutex_lock(&ar->conf_mutex); ++ ret = ath12k_mac_vdev_start(arvif, &arvif->chanctx.def, ++ radar_enabled); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to start vdev %i on freq %d: %d\n", ++ arvif->vdev_id, arvif->chanctx.def.chan->center_freq, ret); ++ mutex_unlock(&ar->conf_mutex); ++ goto out; ++ } ++ ++ arvif->is_started = true; ++ mutex_unlock(&ar->conf_mutex); ++ ahvif->num_vdev_started++; ++ /* Beaconing not required in DFS channel assignment for CAC */ ++ return ret; ++ } ++ + /* we need to wait for all the link vdev in the vif to be created + * before we start + */ +@@ -10061,6 +10110,7 @@ static int ath12k_mac_mlo_vdev_start(str + links_map = ahvif->links_map; + for_each_set_bit(link_id, &links_map, IEEE80211_MLD_MAX_NUM_LINKS) { + arvif_p = ahvif->link[link_id]; ++ radar_enabled = arvif_p->chanctx.radar_enabled; + + if (!arvif_p->ar) { + ath12k_warn(ar->ab, "invalid ar in the arvif_p\n"); +@@ -11300,7 +11350,11 @@ ath12k_mac_op_assign_vif_chanctx(struct + return -EINVAL; + } + } else if (vif->valid_links){ +- /* not expected to be here */ ++ ar = arvif->ar; ++ if (WARN_ON(!ar)) { ++ mutex_unlock(&ah->conf_mutex); ++ return -EINVAL; ++ } + } else { + ar = ath12k_get_ar_by_ctx(hw, ctx); + if (!ar) { diff --git a/feeds/ipq95xx/mac80211/patches/qca/692-ath12k-enable-MLO-dump-collection.patch b/feeds/ipq95xx/mac80211/patches/qca/692-ath12k-enable-MLO-dump-collection.patch new file mode 100644 index 000000000..b23130854 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/692-ath12k-enable-MLO-dump-collection.patch @@ -0,0 +1,114 @@ +From 056e45ac613ba044c7ed7b01158e8b04e824d287 Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Mon, 12 Dec 2022 09:53:13 +0530 +Subject: [PATCH] ath12k: enable MLO dump collection + +Currently, we are collecting dump for one chip but with multi-link +operation there is a chance to receive rddm mhi callback for more +than one chip, in this condition struct ath12k_coredump_segment_info +overwrite data for each chip to avoid this we create new struct +ath12k_coredump_info which maintain number of dumped chip and +their segment information. + +Signed-off-by: Rajat Soni +Signed-off-by: Aaradhana Sahu +--- + drivers/net/wireless/ath/ath12k/coredump.c | 36 ++++++++++++++++------ + drivers/net/wireless/ath/ath12k/coredump.h | 5 +++ + 2 files changed, 31 insertions(+), 10 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/coredump.c ++++ b/drivers/net/wireless/ath/ath12k/coredump.c +@@ -16,8 +16,8 @@ + #include "mhi.h" + #include "debug.h" + +-struct ath12k_coredump_segment_info ath12k_coredump_seg_info; +-EXPORT_SYMBOL(ath12k_coredump_seg_info); ++struct ath12k_coredump_info ath12k_coredump_ram_info; ++EXPORT_SYMBOL(ath12k_coredump_ram_info); + + static void *ath12k_coredump_find_segment(loff_t user_offset, + struct ath12k_dump_segment *segment, +@@ -185,6 +185,8 @@ void ath12k_coredump_download_rddm(struc + int i, rem_seg_cnt = 0, len, num_seg, seg_sz, qdss_seg_cnt = 1; + int skip_count = 0; + enum ath12k_fw_crash_dump_type mem_type; ++ struct ath12k_coredump_segment_info *chip_seg; ++ int dump_count; + + ath12k_mhi_coredump(mhi_ctrl, false); + +@@ -277,18 +279,32 @@ void ath12k_coredump_download_rddm(struc + + num_seg = num_seg - skip_count; + if(!ab->fw_recovery_support) { +- ath12k_coredump_seg_info.chip_id = ar_pci->dev_id; +- ath12k_coredump_seg_info.qrtr_id = ar_pci->ab->qmi.service_ins_id; +- ath12k_coredump_seg_info.bus_id = pci_domain_nr(ar_pci->pdev->bus); +- ath12k_coredump_seg_info.num_seg = num_seg; +- ath12k_coredump_seg_info.seg = segment; +- +- BUG_ON(1); ++ dump_count = ath12k_coredump_ram_info.num_chip; ++ if (dump_count >= ATH12K_MAX_SOCS) { ++ ath12k_err(ab, "invalid chip number %d\n", dump_count); ++ return; ++ } else { ++ chip_seg = &ath12k_coredump_ram_info.chip_seg_info[dump_count]; ++ chip_seg->chip_id = ar_pci->dev_id; ++ chip_seg->qrtr_id = ar_pci->ab->qmi.service_ins_id; ++ chip_seg->bus_id = pci_domain_nr(ar_pci->pdev->bus); ++ chip_seg->num_seg = num_seg; ++ chip_seg->seg = segment; ++ ath12k_coredump_ram_info.num_chip++; ++ ++ if (ath12k_coredump_ram_info.num_chip >= ab->ag->num_started) ++ BUG_ON(1); ++ else ++ ath12k_info(ab, ++ "%d chip dump collected and waiting for partner chips\n", ++ ath12k_coredump_ram_info.num_chip); ++ } + } else { ++ /* TODO dump collection for MLO when fw_recovery set */ + ath12k_coredump_build_inline(ab, segment, num_seg); ++ vfree(segment); + } + +- vfree(segment); + } + + void ath12k_coredump_qdss_dump(struct ath12k_base *ab, +--- a/drivers/net/wireless/ath/ath12k/coredump.h ++++ b/drivers/net/wireless/ath/ath12k/coredump.h +@@ -76,6 +76,11 @@ struct ath12k_coredump_segment_info { + u8 bus_id; + }; + ++struct ath12k_coredump_info { ++ u32 num_chip; ++ struct ath12k_coredump_segment_info chip_seg_info[ATH12K_MAX_SOCS]; ++}; ++ + #ifdef CONFIG_WANT_DEV_COREDUMP + void ath12k_coredump_download_rddm(struct ath12k_base *ab); + void ath12k_coredump_build_inline(struct ath12k_base *ab, +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -1507,10 +1507,12 @@ static void ath12k_core_reset(struct wor + /* prepare coredump */ + ath12k_coredump_download_rddm(ab); + +- ath12k_hif_power_down(ab); +- ath12k_hif_power_up(ab); ++ if (ab->fw_recovery_support) { ++ ath12k_hif_power_down(ab); ++ ath12k_hif_power_up(ab); + +- ath12k_dbg(ab, ATH12K_DBG_BOOT, "reset started\n"); ++ ath12k_dbg(ab, ATH12K_DBG_BOOT, "reset started\n"); ++ } + } + + int ath12k_core_pre_init(struct ath12k_base *ab) diff --git a/feeds/ipq95xx/mac80211/patches/qca/693-ath12k-Clear-qdesc-array-on-peer-tid-update.patch b/feeds/ipq95xx/mac80211/patches/qca/693-ath12k-Clear-qdesc-array-on-peer-tid-update.patch deleted file mode 100644 index 7d54ddcd3..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/693-ath12k-Clear-qdesc-array-on-peer-tid-update.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 9b74c95ae9b74e423b00328100d404f2610aefac Mon Sep 17 00:00:00 2001 -From: Balamurugan S -Date: Mon, 14 Nov 2022 22:27:17 +0530 -Subject: [PATCH] ath12k: Clear qdesc array on peer tid update - -Setting CLEAR_DESC_ARRAY field of WCSS_UMAC_REO_R0_QDESC_ADDR_READ -and resetting back, to erase stale entries in reo storage during peer -tid update. - -Signed-off-by: Balamurugan S ---- - drivers/net/wireless/ath/ath12k/dp_rx.c | 2 ++ - drivers/net/wireless/ath/ath12k/hal.h | 2 ++ - drivers/net/wireless/ath/ath12k/hal_rx.c | 21 +++++++++++++++++++++ - 3 files changed, 25 insertions(+) - -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_rx.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/dp_rx.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -815,6 +815,8 @@ static void ath12k_peer_rx_tid_qref_setu - qref->info0 = FIELD_PREP(BUFFER_ADDR_INFO0_ADDR, lower_32_bits(paddr)); - qref->info1 = FIELD_PREP(BUFFER_ADDR_INFO1_ADDR, upper_32_bits(paddr)) | - FIELD_PREP(DP_REO_QREF_NUM, tid); -+ -+ ath12k_hal_reo_shared_qaddr_cache_clear(ab); - } - - static void ath12k_peer_rx_tid_qref_reset(struct ath12k_base *ab, u16 peer_id, u16 tid) -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/hal.h -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/hal.h -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/hal.h -@@ -339,6 +339,7 @@ struct ath12k_base; - #define HAL_REO1_SW_COOKIE_CFG_ENABLE BIT(19) - #define HAL_REO1_SW_COOKIE_CFG_GLOBAL_ENABLE BIT(20) - #define HAL_REO_QDESC_ADDR_READ_LUT_ENABLE BIT(7) -+#define HAL_REO_QDESC_ADDR_READ_CLEAR_QDESC_ARRAY BIT(6) - - /* CE ring bit field mask and shift */ - #define HAL_CE_DST_R0_DEST_CTRL_MAX_LEN GENMASK(15, 0) -@@ -1165,6 +1166,7 @@ void ath12k_hal_reo_ring_ctrl_hash_ix2_s - u32 ring_hash_map); - void ath12k_hal_srng_prefetch_desc(struct ath12k_base *ab, - struct hal_srng *srng); -+void ath12k_hal_reo_shared_qaddr_cache_clear(struct ath12k_base *ab); - - static inline - u32 *ath12k_hal_srng_src_get_next_entry_nolock(struct ath12k_base *ab, -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/hal_rx.c -=================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/hal_rx.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/hal_rx.c -@@ -906,3 +906,23 @@ void ath12k_hal_rx_reo_ent_buf_paddr_get - - *pp_buf_addr = (void *)buf_addr_info; - } -+ -+/* -+ * Setting CLEAR_DESC_ARRAY field of WCSS_UMAC_REO_R0_QDESC_ADDR_READ -+ * and resetting back, to erase stale entries in reo storage. -+ */ -+void ath12k_hal_reo_shared_qaddr_cache_clear(struct ath12k_base *ab) -+{ -+ u32 val; -+ -+ val = ath12k_hif_read32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + -+ HAL_REO1_QDESC_ADDR_READ(ab)); -+ -+ val |= u32_encode_bits(1, HAL_REO_QDESC_ADDR_READ_CLEAR_QDESC_ARRAY); -+ ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + -+ HAL_REO1_QDESC_ADDR_READ(ab), val); -+ -+ val &= ~HAL_REO_QDESC_ADDR_READ_CLEAR_QDESC_ARRAY; -+ ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + -+ HAL_REO1_QDESC_ADDR_READ(ab), val); -+} diff --git a/feeds/ipq95xx/mac80211/patches/qca/693-ath12k-incorrect-paging.bin-size.patch b/feeds/ipq95xx/mac80211/patches/qca/693-ath12k-incorrect-paging.bin-size.patch new file mode 100644 index 000000000..4f24e2cc4 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/693-ath12k-incorrect-paging.bin-size.patch @@ -0,0 +1,83 @@ +From 12a52402214d3ab0693b790e9e94bf5c96c16164 Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Tue, 20 Dec 2022 16:28:15 +0530 +Subject: [PATCH] ath12k: remove paging_dyn section from + paging.bin + +When firmware dumps are collected, paging.bin parsed +in rddm dumps is approximately 18MB but the expectation +from firmware is only 6MB. + +This difference in size is seen because of paging_dyn.bin +information being appended to paging.bin.Hence, add changes +to handle the same + +Signed-off-by: Harshitha Prem +--- + drivers/net/wireless/ath/ath12k/core.h | 3 --- + drivers/net/wireless/ath/ath12k/coredump.c | 19 ------------------- + drivers/net/wireless/ath/ath12k/qmi.c | 4 ---- + 3 files changed, 26 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h +index 5bd5584..931dcd1 100644 +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -1313,9 +1313,6 @@ void ath12k_core_halt(struct ath12k *ar); + int ath12k_core_resume(struct ath12k_base *ab); + int ath12k_core_suspend(struct ath12k_base *ab); + int ath12k_config_qdss(struct ath12k_base *ab); +-int ath12k_coredump_mhi_update_bhie_table(struct ath12k_base *ab, +- void __iomem *va, +- phys_addr_t pa, size_t size); + + void ath12k_core_put_hw_group(struct ath12k_base *ab); + +diff --git a/drivers/net/wireless/ath/ath12k/coredump.c b/drivers/net/wireless/ath/ath12k/coredump.c +index 56e7122..17e1e99 100644 +--- a/drivers/net/wireless/ath/ath12k/coredump.c ++++ b/drivers/net/wireless/ath/ath12k/coredump.c +@@ -375,25 +375,6 @@ out: + vfree(dump); + } + +-int ath12k_coredump_mhi_update_bhie_table(struct ath12k_base *ab, +- void __iomem *va, +- phys_addr_t pa, size_t size) +-{ +- struct ath12k_pci *ar_pci = (struct ath12k_pci *)ab->drv_priv; +- struct mhi_controller *mhi_ctrl = ar_pci->mhi_ctrl; +- int ret; +- +- /* Attach Pageable region to MHI buffer so that it is +- * included as part of pageable region in dumps +- */ +- ret = mhi_update_bhie_table_for_dyn_paging(mhi_ctrl, va, pa, size); +- if (ret) +- ath12k_dbg(ab, ATH12K_DBG_QMI, +- "failed to add Dynamic Paging region to MHI Buffer table %d\n", ret); +- +- return ret; +-} +- + void ath12k_coredump_m3_dump(struct ath12k_base *ab, + struct ath12k_qmi_m3_dump_upload_req_data *event_data) + { +diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c +index 962d88b..3f725a7 100644 +--- a/drivers/net/wireless/ath/ath12k/qmi.c ++++ b/drivers/net/wireless/ath/ath12k/qmi.c +@@ -3511,10 +3511,6 @@ skip_mlo_mem_init: + ab->qmi.target_mem[i].size; + ab->qmi.target_mem[idx].type = + ab->qmi.target_mem[i].type; +- ret = ath12k_coredump_mhi_update_bhie_table(ab, +- ab->qmi.target_mem[idx].v.ioaddr, +- ab->qmi.target_mem[idx].paddr, +- ab->qmi.target_mem[idx].size); + sz += ab->qmi.target_mem[i].size; + if (ret < 0) + ath12k_warn(ab, +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/693-mac80211-validate-link-status-before-deciding-on-off.patch b/feeds/ipq95xx/mac80211/patches/qca/693-mac80211-validate-link-status-before-deciding-on-off.patch new file mode 100644 index 000000000..49c8e7e8e --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/693-mac80211-validate-link-status-before-deciding-on-off.patch @@ -0,0 +1,93 @@ +From f6023273f0f240b3c8b32f6192259a37fa06a0f3 Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Thu, 22 Dec 2022 12:49:30 +0530 +Subject: [PATCH] mac80211: validate link status before deciding on offchan tx + +Currently we check the status of bss active flag to see if the +AP is active. But in case of a MLD AP, when some of the links +are getting teardown and some are active, mgmt Tx(like deauth) +can be sent on some links before they are brought down as well. + +In such cases, the bss active flag might not provide the exact +status of the MLD links. Hence check if any of the links can +be used for mgmt tx before returning error status. + +Signed-off-by: Sriram R +--- + net/mac80211/offchannel.c | 45 ++++++++++++++++++++++++++++++++++++++- + 1 file changed, 44 insertions(+), 1 deletion(-) + +--- a/net/mac80211/offchannel.c ++++ b/net/mac80211/offchannel.c +@@ -770,6 +770,43 @@ int ieee80211_cancel_remain_on_channel(s + return ieee80211_cancel_roc(local, cookie, false); + } + ++static bool ieee80211_is_link_bss_active(struct ieee80211_sub_if_data *sdata, ++ int link_id) ++{ ++ struct ieee80211_link_data *link; ++ ++ if (!sdata->bss) ++ return false; ++ ++ /* This is consolidated status of the MLD or non ML bss */ ++ if (sdata->bss->active) ++ return true; ++ ++ if (link_id < 0) ++ return false; ++ ++ if (!sdata->vif.valid_links) ++ return false; ++ ++ if (!(sdata->vif.valid_links & BIT(link_id))) ++ return false; ++ ++ sdata_lock(sdata); ++ link = sdata_dereference(sdata->link[link_id], sdata); ++ if (!link) { ++ sdata_unlock(sdata); ++ return false; ++ } ++ ++ if (sdata_dereference(link->u.ap.beacon, sdata)) { ++ sdata_unlock(sdata); ++ return true; ++ } ++ ++ sdata_unlock(sdata); ++ return false; ++} ++ + int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, u64 *cookie) + { +@@ -811,7 +848,7 @@ int ieee80211_mgmt_tx(struct wiphy *wiph + case NL80211_IFTYPE_P2P_GO: + if (sdata->vif.type != NL80211_IFTYPE_ADHOC && + !ieee80211_vif_is_mesh(&sdata->vif) && +- !sdata->bss->active) ++ !ieee80211_is_link_bss_active(sdata, params->link_id)) + need_offchan = true; + + rcu_read_lock(); +@@ -890,8 +927,17 @@ int ieee80211_mgmt_tx(struct wiphy *wiph + break; + } + +- if (ether_addr_equal(conf->addr, mgmt->sa)) ++ if (ether_addr_equal(conf->addr, mgmt->sa)) { ++ /* If userspace requested Tx on a specific link ++ * use the same link id if the link bss is matching ++ * the requested chan. ++ */ ++ if (sdata->vif.valid_links && ++ params->link_id >= 0 && params->link_id == i && ++ params->chan == chanctx_conf->def.chan) ++ link_id = i; + break; ++ } + + chanctx_conf = NULL; + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/694-ath12k-Update-reg_tpc_info-from-bss_conf-during-channel-switch.patch b/feeds/ipq95xx/mac80211/patches/qca/694-ath12k-Update-reg_tpc_info-from-bss_conf-during-channel-switch.patch index 5cd12f7fb..718e6fe3e 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/694-ath12k-Update-reg_tpc_info-from-bss_conf-during-channel-switch.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/694-ath12k-Update-reg_tpc_info-from-bss_conf-during-channel-switch.patch @@ -1,6 +1,6 @@ -From 60be4cb3c08bd27569911a5cc71bd18fc26154f8 Mon Sep 17 00:00:00 2001 +From 4be28a7887cfdc9821b7822decb9d033533cd563 Mon Sep 17 00:00:00 2001 From: Manish Dharanenthiran -Date: Fri, 18 Nov 2022 17:57:54 +0530 +Date: Wed, 14 Dec 2022 17:08:53 +0530 Subject: [PATCH] ath12k: Update reg_tpc_info from bss_conf during channel switch @@ -22,28 +22,28 @@ Signed-off-by: Manish Dharanenthiran 1 file changed, 7 insertions(+) diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index 0918768..222cc29 100644 +index 15ac559..39d6ac1 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -250,6 +250,9 @@ static const u32 ath12k_smps_map[] = { - static int ath12k_mac_vdev_create(struct ath12k *ar, struct ieee80211_vif *vif); + static int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif); static int ath12k_start_vdev_delay(struct ath12k *ar, struct ieee80211_vif *vif); +static void ath12k_mac_parse_tx_pwr_env(struct ath12k *ar, -+ struct ieee80211_vif *vif, ++ struct ath12k_link_vif *arvif, + struct ieee80211_chanctx_conf *ctx); + static void ath12k_update_bcn_template_work(struct work_struct *work); + static void ath12k_update_obss_color_notify_work(struct work_struct *work); - enum nl80211_he_ru_alloc ath12k_mac_phy_he_ru_to_nl80211_he_ru_alloc(u16 ru_phy) - { -@@ -8155,6 +8158,10 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif, +@@ -9650,6 +9653,10 @@ ath12k_mac_vdev_config_after_start(struct ath12k_link_vif *arvif, chandef->chan->band == NL80211_BAND_6GHZ && - (arvif->vdev_type == WMI_VDEV_TYPE_STA || arvif->vdev_type == WMI_VDEV_TYPE_AP) && + (ahvif->vdev_type == WMI_VDEV_TYPE_STA || ahvif->vdev_type == WMI_VDEV_TYPE_AP) && test_bit(WMI_TLV_SERVICE_EXT_TPC_REG_SUPPORT, ar->ab->wmi_ab.svc_map)) { + -+ if (arvif->vdev_type == WMI_VDEV_TYPE_STA) -+ ath12k_mac_parse_tx_pwr_env(ar, arvif->vif, &arvif->chanctx); ++ if (ahvif->vdev_type == WMI_VDEV_TYPE_STA) ++ ath12k_mac_parse_tx_pwr_env(ar, arvif, &arvif->chanctx); + - ath12k_mac_fill_reg_tpc_info(ar, arvif->vif, &arvif->chanctx); + ath12k_mac_fill_reg_tpc_info(ar, arvif, &arvif->chanctx); ath12k_wmi_send_vdev_set_tpc_power(ar, arvif->vdev_id, &arvif->reg_tpc_info); -- diff --git a/feeds/ipq95xx/mac80211/patches/qca/695-ath12k-monitor-vdev-create-validation.patch b/feeds/ipq95xx/mac80211/patches/qca/695-ath12k-monitor-vdev-create-validation.patch deleted file mode 100644 index b93b1e098..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/695-ath12k-monitor-vdev-create-validation.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 2578f59ab616a5a8aad89af0e3338e816c32d60d Mon Sep 17 00:00:00 2001 -From: Ramya Gnanasekar -Date: Tue, 22 Nov 2022 16:08:16 +0530 -Subject: [PATCH] ath12k: monitor vdev create validation - -When monitor vif is created through add interface, -monitor flags has to be updated. - -Without this validation, monitor vdev is created again -in ath12k_mac_op_assign_vif_chanctx() in race condition. - -Signed-off-by: Ramya Gnanasekar - -Index: b/drivers/net/wireless/ath/ath12k/mac.c -=================================================================== ---- a/drivers/net/wireless/ath/ath12k/mac.c 2022-11-23 12:06:58.538536996 +0530 -+++ b/drivers/net/wireless/ath/ath12k/mac.c 2022-11-23 12:41:00.759804423 +0530 -@@ -7685,6 +7685,7 @@ static int ath12k_mac_op_add_interface(s - struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); - struct ath12k_hw *ah = hw->priv; - int i; -+ struct ath12k *ar; - - /* The ar in which this vif will be assigned can be determined since - * it depends on the channel in which the vif is brought up. -@@ -7700,6 +7701,17 @@ static int ath12k_mac_op_add_interface(s - arvif->vdev_type = vif->type; - arvif->vif = vif; - -+ ar = ah->radio; -+ -+ /* WAR : -+ * Monitor flag is set for first radio from hw_group. -+ */ -+ if (ar && vif->type == NL80211_IFTYPE_MONITOR) { -+ mutex_lock(&ar->conf_mutex); -+ set_bit(MONITOR_VDEV_CREATED, &ar->monitor_flags); -+ mutex_unlock(&ar->conf_mutex); -+ } -+ - INIT_LIST_HEAD(&arvif->list); - arvif->key_cipher = INVALID_CIPHER; - -@@ -7728,6 +7740,9 @@ static int ath12k_mac_op_add_interface(s - - vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD; - mutex_unlock(&ah->conf_mutex); -+ -+ ath12k_dbg(NULL, ATH12K_DBG_MAC, "mac add interface (vdev %d), type: %d", -+ arvif->vdev_id, arvif->vdev_type); - return 0; - } - -@@ -7783,6 +7798,10 @@ static void ath12k_mac_op_remove_interfa - - mutex_lock(&ar->conf_mutex); - -+ if ((vif->type == NL80211_IFTYPE_MONITOR) && -+ (test_bit(MONITOR_VDEV_CREATED, &ar->monitor_flags))) -+ clear_bit(MONITOR_VDEV_CREATED, &ar->monitor_flags); -+ - ath12k_dbg(ab, ATH12K_DBG_MAC, "mac remove interface (vdev %d)\n", - arvif->vdev_id); - diff --git a/feeds/ipq95xx/mac80211/patches/qca/695-mac80211-Avoid-double-free-while-clearing-ifmesh-IE.patch b/feeds/ipq95xx/mac80211/patches/qca/695-mac80211-Avoid-double-free-while-clearing-ifmesh-IE.patch deleted file mode 100644 index 02daa1345..000000000 --- a/feeds/ipq95xx/mac80211/patches/qca/695-mac80211-Avoid-double-free-while-clearing-ifmesh-IE.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 60cf6b32eea4792913db2793fb471505d309eeb3 Mon Sep 17 00:00:00 2001 -From: Manish Dharanenthiran -Date: Sat, 19 Nov 2022 23:08:20 +0530 -Subject: [PATCH] mac80211: Avoid double free while clearing ifmesh IE - -While Mesh VAP is siwtched up, join_mesh will be -called to setup the IE. In this case, the old_ie -will be freed before assigning the new_ie to the -struct. But, Mesh IE will already be freed during -leave mesh which is called during VAP down cases, thus -leads to double free - -Fix this by removing free in copy setup and assign -NULL after free in leave_mesh caller. - -Signed-off-by: Manish Dharanenthiran ---- - net/mac80211/cfg.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - -diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c -index aae7f09..8fb8458 100644 ---- a/net/mac80211/cfg.c -+++ b/net/mac80211/cfg.c -@@ -2412,14 +2412,12 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, - const struct mesh_setup *setup) - { - u8 *new_ie; -- const u8 *old_ie; - struct ieee80211_sub_if_data *sdata = container_of(ifmsh, - struct ieee80211_sub_if_data, u.mesh); - int i; - - /* allocate information elements */ - new_ie = NULL; -- old_ie = ifmsh->ie; - - if (setup->ie_len) { - new_ie = kmemdup(setup->ie, setup->ie_len, -@@ -2429,7 +2427,6 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, - } - ifmsh->ie_len = setup->ie_len; - ifmsh->ie = new_ie; -- kfree(old_ie); - - /* now copy the rest of the setup parameters */ - ifmsh->mesh_id_len = setup->mesh_id_len; -@@ -2638,6 +2635,7 @@ static int ieee80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev) - mutex_lock(&sdata->local->mtx); - ieee80211_vif_release_channel(sdata); - kfree(sdata->u.mesh.ie); -+ sdata->u.mesh.ie = NULL; - mutex_unlock(&sdata->local->mtx); - - return 0; --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/696-01-wifi-ath12k-Refactor-the-MLO-global-memory-request.patch b/feeds/ipq95xx/mac80211/patches/qca/696-01-wifi-ath12k-Refactor-the-MLO-global-memory-request.patch new file mode 100644 index 000000000..9f7b69b2b --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/696-01-wifi-ath12k-Refactor-the-MLO-global-memory-request.patch @@ -0,0 +1,338 @@ +From e2b5ab5ff4ea3791567b855017386ac2358688a9 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Sun, 27 Nov 2022 10:22:22 +0530 +Subject: [PATCH 1/2] wifi: ath12k: Refactor the MLO global memory request + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/core.h | 7 +- + drivers/net/wireless/ath/ath12k/qmi.c | 232 +++++++++++++------------ + 2 files changed, 120 insertions(+), 119 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -1016,12 +1016,9 @@ struct ath12k_hw { + }; + + struct ath12k_mlo_memory { ++ struct target_mem_chunk chunk[ATH12K_QMI_WLANFW_MAX_NUM_MEM_SEG_V01]; + struct reserved_mem *rsv; +- union { +- void __iomem *ioaddr; +- void *addr; +- } v; +- u32 size; ++ bool init_done; + }; + + /* Holds info on the group of SOCs that are registered as a single wiphy +--- a/drivers/net/wireless/ath/ath12k/qmi.c ++++ b/drivers/net/wireless/ath/ath12k/qmi.c +@@ -3221,9 +3221,12 @@ out: + } + + static void ath12k_qmi_free_mlo_mem_chunk(struct ath12k_base *ab, +- struct target_mem_chunk *chunk) ++ struct target_mem_chunk *chunk, ++ int idx) + { + struct ath12k_hw_group *ag = ab->ag; ++ struct target_mem_chunk *mlo_chunk; ++ bool fixed_mem = ab->bus_params.fixed_mem_region; + + lockdep_assert_held(&ag->mutex_lock); + +@@ -3231,43 +3234,63 @@ static void ath12k_qmi_free_mlo_mem_chun + return; + + if (ag->num_started) +- goto skip_unmap; ++ goto out; ++ ++ if (idx >= ARRAY_SIZE(ag->mlo_mem.chunk)) { ++ ath12k_warn(ab, "invalid idx %d for MLO memory chunk free\n", idx); ++ return; ++ } ++ ++ mlo_chunk = &ag->mlo_mem.chunk[idx]; + +- iounmap(ag->mlo_mem.v.ioaddr); +- ag->mlo_mem.v.ioaddr = NULL; +- ag->mlo_mem.rsv = NULL; +- ag->mlo_mem.size = 0; ++ if (fixed_mem) { ++ iounmap(mlo_chunk->v.ioaddr); ++ mlo_chunk->v.ioaddr = NULL; ++ } + +-skip_unmap: ++ mlo_chunk->paddr = NULL; ++ mlo_chunk->size = 0; ++ ++out: + chunk->v.ioaddr = NULL; + chunk->paddr = NULL; ++ chunk->size = 0; + } + + void ath12k_qmi_free_target_mem_chunk(struct ath12k_base *ab) + { +- int i; ++ struct ath12k_hw_group *ag = ab->ag; ++ int i, mlo_idx; + +- for (i = 0; i < ab->qmi.mem_seg_count; i++) { +- if (ab->bus_params.fixed_mem_region) { +- if (!ab->qmi.target_mem[i].v.ioaddr) +- continue; ++ for (i = 0, mlo_idx = 0; i < ab->qmi.mem_seg_count; i++) { ++ if (ab->qmi.target_mem[i].type == MLO_GLOBAL_MEM_REGION_TYPE) { ++ ath12k_qmi_free_mlo_mem_chunk(ab, ++ &ab->qmi.target_mem[i], ++ mlo_idx); ++ } else { ++ if (ab->bus_params.fixed_mem_region) { ++ if (!ab->qmi.target_mem[i].v.ioaddr) ++ continue; + +- if (ab->qmi.target_mem[i].type == MLO_GLOBAL_MEM_REGION_TYPE) { +- ath12k_qmi_free_mlo_mem_chunk(ab, &ab->qmi.target_mem[i]); +- } else { + iounmap(ab->qmi.target_mem[i].v.ioaddr); + ab->qmi.target_mem[i].v.ioaddr = NULL; ++ } else { ++ if (!ab->qmi.target_mem[i].v.addr) ++ continue; ++ dma_free_coherent(ab->dev, ++ ab->qmi.target_mem[i].size, ++ ab->qmi.target_mem[i].v.addr, ++ ab->qmi.target_mem[i].paddr); ++ ab->qmi.target_mem[i].v.addr = NULL; + } +- } else { +- if (!ab->qmi.target_mem[i].v.addr) +- continue; +- dma_free_coherent(ab->dev, +- ab->qmi.target_mem[i].size, +- ab->qmi.target_mem[i].v.addr, +- ab->qmi.target_mem[i].paddr); +- ab->qmi.target_mem[i].v.addr = NULL; + } + } ++ ++ if (!ag->num_started && ag->mlo_mem.init_done) { ++ memset(ag->mlo_mem.chunk, 0, sizeof(ag->mlo_mem.chunk)); ++ ag->mlo_mem.rsv = NULL; ++ ag->mlo_mem.init_done = false; ++ } + } + + static int ath12k_qmi_alloc_target_mem_chunk(struct ath12k_base *ab) +@@ -3319,86 +3342,14 @@ static int ath12k_qmi_alloc_target_mem_c + return 0; + } + +-static int ath12k_qmi_assign_mlo_mem_chunk(struct ath12k_base *ab, +- struct target_mem_chunk *chunk) +-{ +- struct ath12k_hw_group *ag = ab->ag; +- struct device_node *mlo_global_mem_node; +- struct reserved_mem *mlo_mem; +- int ret = 0; +- +- mutex_lock(&ag->mutex_lock); +- +- if (ag->mlo_mem.rsv) { +- if (ag->mlo_mem.size != chunk->size) { +- ath12k_warn(ab, "MLO memory requested size %x is mismatch %x\n", +- chunk->size, ag->mlo_mem.size); +- ret = -EINVAL; +- goto out; +- } +- +- goto skip_remap; +- } +- +- mlo_global_mem_node = of_find_node_by_name(NULL, "mlo_global_mem_0"); +- if (!mlo_global_mem_node) { +- ath12k_warn(ab, "qmi fail to get MLO global memory node\n"); +- ret = -EINVAL; +- goto out; +- } +- +- mlo_mem = of_reserved_mem_lookup(mlo_global_mem_node); +- if (!mlo_mem) { +- of_node_put(mlo_global_mem_node); +- ath12k_warn(ab, "qmi fail to get MLO memory resource node %px\n", +- mlo_mem); +- ret = -EINVAL; +- goto out; +- } +- +- of_node_put(mlo_global_mem_node); +- +- if (chunk->size > mlo_mem->size) { +- ath12k_warn(ab, "MLO memory requested size %x is beyond %pa\n", +- chunk->size, &mlo_mem->size); +- ret = -ENOMEM; +- goto out; +- } +- +- ag->mlo_mem.v.ioaddr = ioremap(mlo_mem->base, chunk->size); +- if (!ag->mlo_mem.v.ioaddr) { +- ath12k_warn(ab, "failed to allocate MLO memory requested size %x\n", +- chunk->size); +- ret = -ENOMEM; +- goto out; +- } +- +- ag->mlo_mem.rsv = mlo_mem; +- ag->mlo_mem.size = chunk->size; +- +- memset_io(ag->mlo_mem.v.ioaddr, 0, ag->mlo_mem.size); +- +-skip_remap: +- ath12k_dbg(ab, ATH12K_DBG_QMI, "MLO mem node start 0x%llx size %llu ioaddr %p req size %u\n", +- (unsigned long long)ag->mlo_mem.rsv->base, +- (unsigned long long)ag->mlo_mem.rsv->size, +- ag->mlo_mem.v.ioaddr, +- chunk->size); +- +- chunk->paddr = ag->mlo_mem.rsv->base; +- chunk->v.ioaddr = ag->mlo_mem.v.ioaddr; +-out: +- mutex_unlock(&ag->mutex_lock); +- return ret; +-} +- + static int ath12k_qmi_assign_target_mem_chunk(struct ath12k_base *ab) + { + struct device *dev = ab->dev; +- struct device_node *hremote_node = NULL; ++ struct ath12k_hw_group *ag = ab->ag; ++ struct device_node *hremote_node = NULL, *mem_node; + struct resource res; +- int host_ddr_sz, sz; +- int i, idx, ret; ++ int host_ddr_sz, mlo_ddr_sz, sz, mlo_sz = 0; ++ int i, idx, mlo_idx, ret; + + sz = ab->host_ddr_fixed_mem_off; + hremote_node = of_parse_phandle(dev->of_node, "memory-region", 0); +@@ -3414,19 +3365,56 @@ static int ath12k_qmi_assign_target_mem_ + return ret; + } + ++ mutex_lock(&ag->mutex_lock); ++ ++ if (ag->mlo_mem.init_done) ++ goto skip_mlo_mem_init; ++ ++ mem_node = of_find_node_by_name(NULL, "mlo_global_mem_0"); ++ if (!mem_node) { ++ ath12k_warn(ab, "qmi fail to get MLO global memory node\n"); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ ag->mlo_mem.rsv = of_reserved_mem_lookup(mem_node); ++ of_node_put(mem_node); ++ if (!ag->mlo_mem.rsv) { ++ ath12k_warn(ab, "qmi fail to get MLO memory resource node %px\n", ++ ag->mlo_mem.rsv); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ memset(ag->mlo_mem.chunk, 0, sizeof(ag->mlo_mem.chunk)); ++ ag->mlo_mem.init_done = true; ++ ++skip_mlo_mem_init: ++ mlo_ddr_sz = ag->mlo_mem.rsv->size; + host_ddr_sz = (res.end - res.start) + 1; + +- for (i = 0, idx = 0; i < ab->qmi.mem_seg_count; i++) { +- if (ab->qmi.target_mem[i].type != MLO_GLOBAL_MEM_REGION_TYPE) { +- ab->qmi.target_mem[idx].paddr = res.start + sz; +- +- if (ab->qmi.target_mem[i].size > (host_ddr_sz - sz)) { +- ath12k_warn(ab, "No fixed mem to assign for type %d\n", +- ab->qmi.target_mem[i].type); +- return -EINVAL; +- } ++ for (i = 0, idx = 0, mlo_idx = 0; i < ab->qmi.mem_seg_count; i++) { ++ struct target_mem_chunk *mlo_chunk; ++ phys_addr_t paddr; ++ int remain_sz; ++ ++ if (ab->qmi.target_mem[i].type == MLO_GLOBAL_MEM_REGION_TYPE) { ++ paddr = ag->mlo_mem.rsv->base + mlo_sz; ++ remain_sz = mlo_ddr_sz - mlo_sz; ++ } else { ++ paddr = res.start + sz; ++ remain_sz = host_ddr_sz - sz; + } + ++ ab->qmi.target_mem[idx].paddr = paddr; ++ ++ if (ab->qmi.target_mem[i].size > remain_sz) { ++ ath12k_warn(ab, "No fixed mem to assign for type %d\n", ++ ab->qmi.target_mem[i].type); ++ ret = -EINVAL; ++ goto out; ++ } ++ + switch (ab->qmi.target_mem[i].type) { + case HOST_DDR_REGION_TYPE: + ab->qmi.target_mem[idx].v.ioaddr = +@@ -3487,16 +3475,23 @@ static int ath12k_qmi_assign_target_mem_ + idx++; + break; + case MLO_GLOBAL_MEM_REGION_TYPE: +- ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size; +- +- ret = ath12k_qmi_assign_mlo_mem_chunk(ab, &ab->qmi.target_mem[idx]); +- if (ret) { +- ath12k_warn(ab, "qmi failed to assign MLO target memory: %d\n", +- ret); +- return ret; ++ mlo_chunk = &ag->mlo_mem.chunk[mlo_idx]; ++ if (!mlo_chunk->paddr) { ++ mlo_chunk->size = ab->qmi.target_mem[i].size; ++ mlo_chunk->type = ab->qmi.target_mem[i].type; ++ mlo_chunk->paddr = paddr; ++ mlo_chunk->v.ioaddr = ioremap(mlo_chunk->paddr, ++ mlo_chunk->size); ++ memset_io(mlo_chunk->v.ioaddr, 0, mlo_chunk->size); + } +- ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type; ++ ++ ab->qmi.target_mem[idx].paddr = mlo_chunk->paddr; ++ ab->qmi.target_mem[idx].v.ioaddr = mlo_chunk->v.ioaddr; ++ ab->qmi.target_mem[idx].size = mlo_chunk->size; ++ ab->qmi.target_mem[idx].type = mlo_chunk->type; ++ mlo_sz += mlo_chunk->size; + idx++; ++ mlo_idx++; + break; + default: + ath12k_warn(ab, "qmi ignore invalid mem req type %d\n", +@@ -3507,10 +3502,18 @@ static int ath12k_qmi_assign_target_mem_ + ath12k_dbg(ab, ATH12K_DBG_QMI, "qmi target mem seg idx %d i %d type %d size %d\n", + idx, i, ab->qmi.target_mem[idx - 1].type, ab->qmi.target_mem[idx - 1].size); + } ++ ++ mutex_unlock(&ag->mutex_lock); ++ + ab->host_ddr_fixed_mem_off = sz; + ab->qmi.mem_seg_count = idx; + + return 0; ++ ++out: ++ ath12k_qmi_free_target_mem_chunk(ab); ++ mutex_unlock(&ag->mutex_lock); ++ return ret; + } + + static int ath12k_qmi_request_target_cap(struct ath12k_base *ab) diff --git a/feeds/ipq95xx/mac80211/patches/qca/696-02-wifi-ath12k-Add-MLO-global-memory-support-in-segment.patch b/feeds/ipq95xx/mac80211/patches/qca/696-02-wifi-ath12k-Add-MLO-global-memory-support-in-segment.patch new file mode 100644 index 000000000..fe4b3642a --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/696-02-wifi-ath12k-Add-MLO-global-memory-support-in-segment.patch @@ -0,0 +1,170 @@ +From 6a59bbc503199922e22ac2f1a188548737d9110f Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Sun, 27 Nov 2022 22:30:29 +0530 +Subject: [PATCH 2/2] wifi: ath12k: Add MLO global memory support in segmented + mode + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/qmi.c | 105 ++++++++++++++++++++------ + 1 file changed, 81 insertions(+), 24 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/qmi.c ++++ b/drivers/net/wireless/ath/ath12k/qmi.c +@@ -3230,7 +3230,7 @@ static void ath12k_qmi_free_mlo_mem_chun + + lockdep_assert_held(&ag->mutex_lock); + +- if (!ag->mlo_mem.rsv) ++ if (!ag->mlo_mem.init_done) + return; + + if (ag->num_started) +@@ -3244,15 +3244,28 @@ static void ath12k_qmi_free_mlo_mem_chun + mlo_chunk = &ag->mlo_mem.chunk[idx]; + + if (fixed_mem) { +- iounmap(mlo_chunk->v.ioaddr); +- mlo_chunk->v.ioaddr = NULL; ++ if (mlo_chunk->v.ioaddr) { ++ iounmap(mlo_chunk->v.ioaddr); ++ mlo_chunk->v.ioaddr = NULL; ++ } ++ } else { ++ if (mlo_chunk->v.addr) { ++ dma_free_coherent(ab->dev, ++ mlo_chunk->size, ++ mlo_chunk->v.addr, ++ mlo_chunk->paddr); ++ mlo_chunk->v.addr = NULL; ++ } + } + + mlo_chunk->paddr = NULL; + mlo_chunk->size = 0; + + out: +- chunk->v.ioaddr = NULL; ++ if (fixed_mem) ++ chunk->v.ioaddr = NULL; ++ else ++ chunk->v.addr = NULL; + chunk->paddr = NULL; + chunk->size = 0; + } +@@ -3293,14 +3306,47 @@ void ath12k_qmi_free_target_mem_chunk(st + } + } + ++static int ath12k_qmi_alloc_chunk(struct ath12k_base *ab, ++ struct target_mem_chunk *chunk) ++{ ++ chunk->v.addr = dma_alloc_coherent(ab->dev, ++ chunk->size, ++ &chunk->paddr, ++ GFP_KERNEL | __GFP_NOWARN); ++ if (!chunk->v.addr) { ++ if (chunk->size > ATH12K_QMI_MAX_CHUNK_SIZE) { ++ ab->qmi.target_mem_delayed = true; ++ ath12k_warn(ab, ++ "qmi dma allocation failed (%d B type %u), will try later with small size\n", ++ chunk->size, ++ chunk->type); ++ ath12k_qmi_free_target_mem_chunk(ab); ++ return -EAGAIN; ++ } ++ ath12k_warn(ab, "memory allocation failure for %u size: %d\n", ++ chunk->type, chunk->size); ++ return -ENOMEM; ++ } ++ ++ return 0; ++} ++ + static int ath12k_qmi_alloc_target_mem_chunk(struct ath12k_base *ab) + { +- int i; +- struct target_mem_chunk *chunk; ++ struct ath12k_hw_group *ag = ab->ag; ++ int i, mlo_idx, ret; ++ struct target_mem_chunk *chunk, *mlo_chunk; ++ ++ mutex_lock(&ag->mutex_lock); ++ ++ if (!ag->mlo_mem.init_done) { ++ memset(ag->mlo_mem.chunk, 0, sizeof(ag->mlo_mem.chunk)); ++ ag->mlo_mem.init_done = true; ++ } + + ab->qmi.target_mem_delayed = false; + +- for (i = 0; i < ab->qmi.mem_seg_count; i++) { ++ for (i = 0, mlo_idx = 0; i < ab->qmi.mem_seg_count; i++) { + chunk = &ab->qmi.target_mem[i]; + + /* Allocate memory for the region and the functionality supported +@@ -3308,27 +3354,32 @@ static int ath12k_qmi_alloc_target_mem_c + * allocate memory, assigns NULL and FW will handle this without crashing. + */ + switch (chunk->type) { ++ case MLO_GLOBAL_MEM_REGION_TYPE: ++ mlo_chunk = &ag->mlo_mem.chunk[mlo_idx]; ++ if (!mlo_chunk->paddr) { ++ mlo_chunk->size = chunk->size; ++ mlo_chunk->type = chunk->type; ++ ++ ret = ath12k_qmi_alloc_chunk(ab, mlo_chunk); ++ if (ret) { ++ ret = (ret == -EAGAIN) ? 0 : ret; ++ goto out; ++ } ++ ++ memset(mlo_chunk->v.addr, 0, mlo_chunk->size); ++ } ++ chunk->paddr = mlo_chunk->paddr; ++ chunk->v.addr = mlo_chunk->v.addr; ++ mlo_idx++; ++ break; + case HOST_DDR_REGION_TYPE: + case M3_DUMP_REGION_TYPE: + case PAGEABLE_MEM_REGION_TYPE: + case CALDB_MEM_REGION_TYPE: +- chunk->v.addr = dma_alloc_coherent(ab->dev, +- chunk->size, +- &chunk->paddr, +- GFP_KERNEL | __GFP_NOWARN); +- if (!chunk->v.addr) { +- if (chunk->size > ATH12K_QMI_MAX_CHUNK_SIZE) { +- ab->qmi.target_mem_delayed = true; +- ath12k_warn(ab, +- "qmi dma allocation failed (%d B type %u), will try later with small size\n", +- chunk->size, +- chunk->type); +- ath12k_qmi_free_target_mem_chunk(ab); +- return 0; +- } +- ath12k_warn(ab, "memory allocation failure for %u size: %d\n", +- chunk->type, chunk->size); +- return -ENOMEM; ++ ret = ath12k_qmi_alloc_chunk(ab, chunk); ++ if (ret) { ++ ret = (ret == -EAGAIN) ? 0 : ret; ++ goto out; + } + break; + default: +@@ -3339,7 +3390,14 @@ static int ath12k_qmi_alloc_target_mem_c + break; + } + } ++ ++ mutex_unlock(&ag->mutex_lock); + return 0; ++ ++out: ++ ath12k_qmi_free_target_mem_chunk(ab); ++ mutex_unlock(&ag->mutex_lock); ++ return ret; + } + + static int ath12k_qmi_assign_target_mem_chunk(struct ath12k_base *ab) diff --git a/feeds/ipq95xx/mac80211/patches/qca/698-02-cfg80211-fix-u8-overflow-in-cfg80211_update_notliste.patch b/feeds/ipq95xx/mac80211/patches/qca/696-UPSTREAM-cfg80211-fix-u8-overflow-in-cfg80211_update.patch similarity index 80% rename from feeds/ipq95xx/mac80211/patches/qca/698-02-cfg80211-fix-u8-overflow-in-cfg80211_update_notliste.patch rename to feeds/ipq95xx/mac80211/patches/qca/696-UPSTREAM-cfg80211-fix-u8-overflow-in-cfg80211_update.patch index d1a27f70b..79fdcdf95 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/698-02-cfg80211-fix-u8-overflow-in-cfg80211_update_notliste.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/696-UPSTREAM-cfg80211-fix-u8-overflow-in-cfg80211_update.patch @@ -1,17 +1,23 @@ +From 367066d93f9687d9a6274c7c02f1a607324f8115 Mon Sep 17 00:00:00 2001 From: Johannes Berg -Date: Thu, 13 Oct 2022 19:52:59 +0200 -Subject: [PATCH] cfg80211: fix u8 overflow in cfg80211_update_notlisted_nontrans() +Date: Tue, 29 Nov 2022 19:04:12 +0530 +Subject: [PATCH 1/6] UPSTREAM: cfg80211: fix u8 overflow in + cfg80211_update_notlisted_nontrans() In the copy code of the elements, we do the following calculation to reach the end of the MBSSID element: + /* copy the IEs after MBSSID */ cpy_len = mbssid[1] + 2; + This looks fine, however, cpy_len is a u8, the same as mbssid[1], so the addition of two can overflow. In this case the subsequent memcpy() will overflow the allocated buffer, since it copies 256 bytes too much due to the way the allocation and memcpy() sizes are calculated. + Fix this by using size_t for the cpy_len variable. + This fixes CVE-2022-41674. (Cherry picked from commit:aebe9f4639b13a1f4e9a6b42cdd2e38c617b442d) @@ -25,13 +31,15 @@ Fixes: 0b8fb8235be8 ("cfg80211: Parsing of Multiple BSSID information in scannin Reviewed-by: Kees Cook Signed-off-by: Johannes Berg Signed-off-by: Ganesh Babu Jothiram -Signed-off-by: Ramya Gnanasekar +--- + net/wireless/scan.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/wireless/scan.c b/net/wireless/scan.c -index 7103dd3..9510f01 100644 +index fcd9c2f..032cb6d 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c -@@ -2272,7 +2272,7 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy, +@@ -2279,7 +2279,7 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy, size_t new_ie_len; struct cfg80211_bss_ies *new_ies; const struct cfg80211_bss_ies *old; diff --git a/feeds/ipq95xx/mac80211/patches/qca/690-cfg80211-Skip-scan-entry-creation-for-duplicate-beac.patch b/feeds/ipq95xx/mac80211/patches/qca/696-cfg80211-Skip-scan-entry-creation-for-duplicate-beac.patch similarity index 85% rename from feeds/ipq95xx/mac80211/patches/qca/690-cfg80211-Skip-scan-entry-creation-for-duplicate-beac.patch rename to feeds/ipq95xx/mac80211/patches/qca/696-cfg80211-Skip-scan-entry-creation-for-duplicate-beac.patch index 602c33520..7db9db1bd 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/690-cfg80211-Skip-scan-entry-creation-for-duplicate-beac.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/696-cfg80211-Skip-scan-entry-creation-for-duplicate-beac.patch @@ -1,15 +1,13 @@ -From 717f57b2558a2bde1dfb5ceba0064429d535ce51 Mon Sep 17 00:00:00 2001 +From c7a8a4a96a6b15d2b500a13485c30abe72dbe508 Mon Sep 17 00:00:00 2001 From: Ramya Gnanasekar -Date: Mon, 14 Nov 2022 19:52:41 +0530 +Date: Mon, 28 Nov 2022 21:01:21 +0530 Subject: [PATCH] cfg80211: Skip scan entry creation for duplicate beacon An AP whose primary channel is non-PSC channel may transmit duplicate beacon in PSC channel. To determine duplicate beacon HE operation IE was used. - When validating the frequency, determined frequency was in KHZ and chandef frequency was on MHZ resulting in false positives. - Also maximum operating bandwidth is 320MHz in 6GHz, hence difference between operating frequency and PSC frequency can be more than 80Mhz. Changed the condtion to meet the same. @@ -17,10 +15,10 @@ Changed the condtion to meet the same. Signed-off-by: Ramya Gnanasekar diff --git a/net/wireless/scan.c b/net/wireless/scan.c -index d7199c8..7103dd3 100644 +index fcd9c2f..2720350 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c -@@ -1875,8 +1875,8 @@ cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen, +@@ -1882,8 +1882,8 @@ cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen, * beacons only. */ if (channel->band == NL80211_BAND_6GHZ && diff --git a/feeds/ipq95xx/mac80211/patches/qca/698-01-cfg80211-mac80211-reject-bad-MBSSID-elements.patch b/feeds/ipq95xx/mac80211/patches/qca/697-UPSTREAM-cfg80211-mac80211-reject-bad-MBSSID-element.patch similarity index 77% rename from feeds/ipq95xx/mac80211/patches/qca/698-01-cfg80211-mac80211-reject-bad-MBSSID-elements.patch rename to feeds/ipq95xx/mac80211/patches/qca/697-UPSTREAM-cfg80211-mac80211-reject-bad-MBSSID-element.patch index 4312d1e12..ce4b4927b 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/698-01-cfg80211-mac80211-reject-bad-MBSSID-elements.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/697-UPSTREAM-cfg80211-mac80211-reject-bad-MBSSID-element.patch @@ -1,15 +1,18 @@ -From 8fd6eb3f3260700fb698a754e33e150131f5233d Mon Sep 17 00:00:00 2001 +From 51bb9b2667d1cdf6641521dc143b6b16f511fce0 Mon Sep 17 00:00:00 2001 From: Johannes Berg -Date: Thu, 13 Oct 2022 19:53:00 +0200 -Subject: [PATCH] cfg80211/mac80211: reject bad MBSSID elements +Date: Tue, 29 Nov 2022 19:13:15 +0530 +Subject: [PATCH 2/6] UPSTREAM: cfg80211/mac80211: reject bad MBSSID elements Per spec, the maximum value for the MaxBSSID ('n') indicator is 8, and the minimum is 1 since a multiple BSSID set with just one BSSID doesn't make sense (the # of BSSIDs is limited by 2^n). + Limit this in the parsing in both cfg80211 and mac80211, rejecting any elements with an invalid value. + This fixes potentially bad shifts in the processing of these inside the cfg80211_gen_new_bssid() function later. + I found this during the investigation of CVE-2022-41674 fixed by the previous patch. @@ -20,33 +23,32 @@ wireless.git/commit/?id=8f033d2becc24aa6bfd2a5c104407963560caabc) Fixes: 0b8fb8235be8 ("cfg80211: Parsing of Multiple BSSID information in scanning") Fixes: 78ac51f81532 ("mac80211: support multi-bssid") - Reviewed-by: Kees Cook Signed-off-by: Johannes Berg Signed-off-by: Ganesh Babu Jothiram -Change-Id: Ie6f77d9475b52c7a98cfbeefb33630303c0ed307 - -Signed-off-by: Ramya Gnanasekar +--- + net/mac80211/util.c | 2 ++ + net/wireless/scan.c | 2 ++ + 2 files changed, 4 insertions(+) diff --git a/net/mac80211/util.c b/net/mac80211/util.c -index a941725..d46a999 100644 +index 2b74048..6070437 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c -@@ -1429,6 +1429,9 @@ static size_t ieee802_11_find_bssid_profile(const u8 *start, size_t len, +@@ -1443,6 +1443,8 @@ static size_t ieee802_11_find_bssid_profile(const u8 *start, size_t len, + for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID, start, len) { if (elem->datalen < 2) continue; - + if (elem->data[0] < 1 || elem->data[0] > 8) + continue; -+ + for_each_element(sub, elem->data + 1, elem->datalen - 1) { u8 new_bssid[ETH_ALEN]; - const u8 *index; diff --git a/net/wireless/scan.c b/net/wireless/scan.c -index 7103dd3..f64ad18 100644 +index 032cb6d..915cfb5 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c -@@ -2136,6 +2136,8 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy, +@@ -2143,6 +2143,8 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy, for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID, ie, ielen) { if (elem->datalen < 4) continue; diff --git a/feeds/ipq95xx/mac80211/patches/qca/697-ath12k-Propagate-ML-capabilities.patch b/feeds/ipq95xx/mac80211/patches/qca/697-ath12k-Propagate-ML-capabilities.patch new file mode 100644 index 000000000..9f41ba498 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/697-ath12k-Propagate-ML-capabilities.patch @@ -0,0 +1,104 @@ +From 0718dc5c6e2d180916e2188c08a6fb90533408df Mon Sep 17 00:00:00 2001 +From: Muna Sinada +Date: Tue, 31 May 2022 11:06:29 -0700 +Subject: [PATCH 3/3] ath12k: Propagate ML capabilities + +Pass ML capabilities from FW to userspace. + +Signed-off-by: Muna Sinada +--- + drivers/net/wireless/ath/ath12k/wmi.c | 47 +++++++++++++++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/wmi.h | 6 +++++ + 2 files changed, 53 insertions(+) + +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -4975,6 +4975,9 @@ static int ath12k_wmi_tlv_mac_phy_caps_e + cap_band->eht_cap_info_internal = caps->eht_cap_info_internal; + } + ++ pdev_cap->eml_cap = caps->eml_cap_u.eml_capability; ++ pdev_cap->mld_cap = caps->mld_cap_u.mld_capability; ++ + if (data) + pdev_cap->ru_punct_supp_bw = data->param.ru_punct_supp_bw; + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -905,6 +905,8 @@ struct ath12k_pdev_cap { + bool nss_ratio_enabled; + u8 nss_ratio_info; + u32 ru_punct_supp_bw; ++ u32 eml_cap; ++ u32 mld_cap; + }; + + struct mlo_timestamp { +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -13113,7 +13113,7 @@ static const u8 ath12k_if_types_ext_capa + [10] = WLAN_EXT_CAPA11_EMA_SUPPORT, + }; + +-static const struct wiphy_iftype_ext_capab ath12k_iftypes_ext_capa[] = { ++static struct wiphy_iftype_ext_capab ath12k_iftypes_ext_capa[] = { + { + .extended_capabilities = ath12k_if_types_ext_capa, + .extended_capabilities_mask = ath12k_if_types_ext_capa, +@@ -13130,6 +13130,8 @@ static const struct wiphy_iftype_ext_cap + .extended_capabilities_mask = ath12k_if_types_ext_capa_ap, + .extended_capabilities_len = + sizeof(ath12k_if_types_ext_capa_ap), ++ .eml_capabilities = 0, ++ .mld_capa_and_ops = 0, + }, + }; + +@@ -13390,6 +13392,13 @@ static int ath12k_mac_hw_register(struct + hw->wiphy->cipher_suites = cipher_suites; + hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); + ++ /* Copy over MLO related capabilities received from ++ * WMI_SERVICE_READY_EXT2_EVENT if mlo_capable is set ++ */ ++ if (ag->mlo_capable) { ++ ath12k_iftypes_ext_capa[2].eml_capabilities = cap->eml_cap; ++ ath12k_iftypes_ext_capa[2].mld_capa_and_ops = cap->mld_cap; ++ } + hw->wiphy->iftype_ext_capab = ath12k_iftypes_ext_capa; + hw->wiphy->num_iftype_ext_capab = ARRAY_SIZE(ath12k_iftypes_ext_capa); + +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -2764,8 +2764,29 @@ struct wmi_mac_phy_caps_ext { + u32 eht_cap_info_internal; + u32 eht_supp_mcs_ext_2G[WMI_MAX_EHT_SUPP_MCS_2G_SIZE]; + u32 eht_supp_mcs_ext_5G[WMI_MAX_EHT_SUPP_MCS_5G_SIZE]; +- u32 eml_info; +- u32 mld_info; ++ union { ++ struct { ++ u32 emlsr_support:1, ++ emlsr_padding_delay:3, ++ emlsr_transition_delay:3, ++ emlmr_support:1, ++ emlmr_delay:3, ++ transition_timeout:4, ++ reserved: 17; ++ }; ++ u32 eml_capability; ++ } eml_cap_u; ++ union { ++ struct { ++ u32 max_num_simultaneous_links:4, ++ srs_support:1, ++ tid_to_link_negotiation_support:2, ++ freq_separation_str:5, ++ aar_support:1, ++ reserved2: 19; ++ }; ++ u32 mld_capability; ++ } mld_cap_u; + } __packed; + + /* 2 word representation of MAC addr */ diff --git a/feeds/ipq95xx/mac80211/patches/qca/698-UPSTREAM-mac80211-fix-MBSSID-parsing-use-after-free.patch b/feeds/ipq95xx/mac80211/patches/qca/698-UPSTREAM-mac80211-fix-MBSSID-parsing-use-after-free.patch new file mode 100644 index 000000000..8556fe8d2 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/698-UPSTREAM-mac80211-fix-MBSSID-parsing-use-after-free.patch @@ -0,0 +1,110 @@ +From b9579c16128e6f53c344a5c0710f5d6bfb981e93 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Tue, 29 Nov 2022 19:24:09 +0530 +Subject: [PATCH 3/6] UPSTREAM: mac80211: fix MBSSID parsing use-after-free + +When we parse a multi-BSSID element, we might point some +element pointers into the allocated nontransmitted_profile. +However, we free this before returning, causing UAF when the +relevant pointers in the parsed elements are accessed. + +Fix this by not allocating the scratch buffer separately but +as part of the returned structure instead, that way, there +are no lifetime issues with it. + +The scratch buffer introduction as part of the returned data +here is taken from MLO feature work done by Ilan. + +This fixes CVE-2022-42719. + +(Cherry picked from commit:ff05d4b45dd89b922578dac497dcabf57cf771c6) +(Source:https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless.git) +(Link: https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless.git/ +commit/?id=ff05d4b45dd89b922578dac497dcabf57cf771c6) + +Fixes: 5023b14cf4df ("mac80211: support profile split between elements") +Co-developed-by: Ilan Peer +Signed-off-by: Ilan Peer +Reviewed-by: Kees Cook +Signed-off-by: Johannes Berg +Signed-off-by: Ganesh Babu Jothiram +--- + net/mac80211/ieee80211_i.h | 8 ++++++++ + net/mac80211/util.c | 29 +++++++++++++++-------------- + 2 files changed, 23 insertions(+), 14 deletions(-) + +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index 1faad33..2d09721 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1745,6 +1745,14 @@ struct ieee802_11_elems { + + /* whether a parse error occurred while retrieving these elements */ + bool parse_error; ++ ++ /* ++ * scratch buffer that can be used for various element parsing related ++ * tasks, e.g., element de-fragmentation etc. ++ */ ++ size_t scratch_len; ++ u8 *scratch_pos; ++ u8 scratch[]; + }; + + static inline struct ieee80211_local *hw_to_local( +diff --git a/net/mac80211/util.c b/net/mac80211/util.c +index 6070437..519ac75 100644 +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -1504,24 +1504,27 @@ ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params) + const struct element *non_inherit = NULL; + u8 *nontransmitted_profile; + int nontransmitted_profile_len = 0; ++ size_t scratch_len = params->len; + +- elems = kzalloc(sizeof(*elems), GFP_ATOMIC); ++ elems = kzalloc(sizeof(*elems) + scratch_len, GFP_ATOMIC); + if (!elems) + return NULL; + elems->ie_start = params->start; + elems->total_len = params->len; + +- nontransmitted_profile = kmalloc(params->len, GFP_ATOMIC); +- if (nontransmitted_profile) { +- nontransmitted_profile_len = +- ieee802_11_find_bssid_profile(params->start, params->len, +- elems, params->bss, +- nontransmitted_profile); +- non_inherit = +- cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE, +- nontransmitted_profile, +- nontransmitted_profile_len); +- } ++ elems->scratch_len = scratch_len; ++ elems->scratch_pos = elems->scratch; ++ ++ nontransmitted_profile = elems->scratch_pos; ++ nontransmitted_profile_len = ++ ieee802_11_find_bssid_profile(params->start, params->len, ++ elems, params->bss, ++ nontransmitted_profile); ++ elems->scratch_pos += nontransmitted_profile_len; ++ elems->scratch_len -= nontransmitted_profile_len; ++ non_inherit = cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE, ++ nontransmitted_profile, ++ nontransmitted_profile_len); + + elems->crc = _ieee802_11_parse_elems_full(params, elems, non_inherit); + +@@ -1555,8 +1558,6 @@ ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params) + offsetofend(struct ieee80211_bssid_index, dtim_count)) + elems->dtim_count = elems->bssid_index->dtim_count; + +- kfree(nontransmitted_profile); +- + return elems; + } + +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/698-03-cfg80211-fix-BSS-refcounting-bugs.patch b/feeds/ipq95xx/mac80211/patches/qca/699-UPSTREAM-cfg80211-fix-BSS-refcounting-bugs.patch similarity index 80% rename from feeds/ipq95xx/mac80211/patches/qca/698-03-cfg80211-fix-BSS-refcounting-bugs.patch rename to feeds/ipq95xx/mac80211/patches/qca/699-UPSTREAM-cfg80211-fix-BSS-refcounting-bugs.patch index bc671b6cd..603941359 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/698-03-cfg80211-fix-BSS-refcounting-bugs.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/699-UPSTREAM-cfg80211-fix-BSS-refcounting-bugs.patch @@ -1,7 +1,7 @@ -From 8f8c7020594b403d2a4a20173c03b00717ddedbe Mon Sep 17 00:00:00 2001 +From 577c9071561fe2e7d5050797bb1c83c7feeacb37 Mon Sep 17 00:00:00 2001 From: Johannes Berg -Date: Tue, 29 Nov 2022 14:27:15 +0530 -Subject: [PATCH] cfg80211: fix BSS refcounting bugs +Date: Tue, 29 Nov 2022 19:32:36 +0530 +Subject: [PATCH 4/6] UPSTREAM: cfg80211: fix BSS refcounting bugs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -20,23 +20,28 @@ There are multiple refcounting bugs related to multi-BSSID: return it, but this results in returning an entry without a reference. We shouldn't return it anyway if it was broken enough to not get added there. + This fixes CVE-2022-42720. + (Cherry picked from commit:0b7808818cb9df6680f98996b8e9a439fa7bcc2f) (Source:https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless.git) (Link: https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless.git/ commit/?id=0b7808818cb9df6680f98996b8e9a439fa7bcc2f) + Reported-by: Sönke Huster Tested-by: Sönke Huster Fixes: a3584f56de1c ("cfg80211: Properly track transmitting and non-transmitting BSS") Signed-off-by: Johannes Berg Signed-off-by: Ganesh Babu Jothiram -Signed-off-by: Ramya Gnanasekar +--- + net/wireless/scan.c | 26 +++++++++++++------------- + 1 file changed, 13 insertions(+), 13 deletions(-) -Index: b/net/wireless/scan.c -=================================================================== ---- a/net/wireless/scan.c 2022-11-29 15:01:51.547545259 +0530 -+++ b/net/wireless/scan.c 2022-11-29 15:04:38.126293905 +0530 -@@ -143,18 +143,11 @@ static inline void bss_ref_get(struct cf +diff --git a/net/wireless/scan.c b/net/wireless/scan.c +index 915cfb5..ea81141 100644 +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -143,18 +143,11 @@ static inline void bss_ref_get(struct cfg80211_registered_device *rdev, lockdep_assert_held(&rdev->bss_lock); bss->refcount++; @@ -60,7 +65,7 @@ Index: b/net/wireless/scan.c } static inline void bss_ref_put(struct cfg80211_registered_device *rdev, -@@ -1732,6 +1725,8 @@ cfg80211_bss_update(struct cfg80211_regi +@@ -1739,6 +1732,8 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev, new->refcount = 1; INIT_LIST_HEAD(&new->hidden_list); INIT_LIST_HEAD(&new->pub.nontrans_list); @@ -69,7 +74,7 @@ Index: b/net/wireless/scan.c if (rcu_access_pointer(tmp->pub.proberesp_ies)) { hidden = rb_find_bss(rdev, tmp, BSS_CMP_HIDE_ZLEN); -@@ -2014,10 +2009,15 @@ cfg80211_inform_single_bss_data(struct w +@@ -2021,10 +2016,15 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy, spin_lock_bh(&rdev->bss_lock); if (cfg80211_add_nontrans_list(non_tx_data->tx_bss, &res->pub)) { @@ -86,3 +91,6 @@ Index: b/net/wireless/scan.c } trace_cfg80211_return_bss(&res->pub); +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/698-03-cfg80211-avoid-nontransmitted-BSS-list-corruption.patch b/feeds/ipq95xx/mac80211/patches/qca/700-UPSTREAM-cfg80211-avoid-nontransmitted-BSS-list-corr.patch similarity index 83% rename from feeds/ipq95xx/mac80211/patches/qca/698-03-cfg80211-avoid-nontransmitted-BSS-list-corruption.patch rename to feeds/ipq95xx/mac80211/patches/qca/700-UPSTREAM-cfg80211-avoid-nontransmitted-BSS-list-corr.patch index 8bcc18391..a082be5bc 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/698-03-cfg80211-avoid-nontransmitted-BSS-list-corruption.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/700-UPSTREAM-cfg80211-avoid-nontransmitted-BSS-list-corr.patch @@ -1,7 +1,8 @@ -From 04d4ffd2659997b58dca7097d4b75eaa24e8331f Mon Sep 17 00:00:00 2001 +From d2d0c7e19a992981f9ae8e7a33710efda0ffd2ba Mon Sep 17 00:00:00 2001 From: Johannes Berg -Date: Tue, 29 Nov 2022 12:23:15 +0530 -Subject: [PATCH] cfg80211: avoid nontransmitted BSS list corruption +Date: Tue, 29 Nov 2022 19:36:23 +0530 +Subject: [PATCH 5/6] UPSTREAM: cfg80211: avoid nontransmitted BSS list + corruption MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -16,23 +17,28 @@ gets corrupted. Since this is an erroneous situation, simply fail the list insertion in this case and free the non-transmitted BSS. + This fixes CVE-2022-42721. + (Cherry picked from commit:bcca852027e5878aec911a347407ecc88d6fff7f) (Source:https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless.git) (Link: https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless.git/ commit/?id=bcca852027e5878aec911a347407ecc88d6fff7f) + Reported-by: Sönke Huster Tested-by: Sönke Huster Fixes: 0b8fb8235be8 ("cfg80211: Parsing of Multiple BSSID information in scanning") Signed-off-by: Johannes Berg Signed-off-by: Ganesh Babu Jothiram -Signed-off-by: Ramya Gnanasekar +--- + net/wireless/scan.c | 9 +++++++++ + 1 file changed, 9 insertions(+) diff --git a/net/wireless/scan.c b/net/wireless/scan.c -index 7103dd3..05eb706 100644 +index ea81141..56758f8 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c -@@ -427,6 +427,15 @@ cfg80211_add_nontrans_list(struct cfg80211_bss *trans_bss, +@@ -420,6 +420,15 @@ cfg80211_add_nontrans_list(struct cfg80211_bss *trans_bss, rcu_read_unlock(); diff --git a/feeds/ipq95xx/mac80211/patches/qca/701-UPSTREAM-mac80211-fix-crash-in-beacon-protection-for.patch b/feeds/ipq95xx/mac80211/patches/qca/701-UPSTREAM-mac80211-fix-crash-in-beacon-protection-for.patch new file mode 100644 index 000000000..6af35764f --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/701-UPSTREAM-mac80211-fix-crash-in-beacon-protection-for.patch @@ -0,0 +1,64 @@ +From c9202f9d72ef0ba6c74c08ada7652f77da4ca790 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Tue, 29 Nov 2022 19:44:39 +0530 +Subject: [PATCH 6/6] UPSTREAM: mac80211: fix crash in beacon protection for + P2P-device +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If beacon protection is active but the beacon cannot be +decrypted or is otherwise malformed, we call the cfg80211 +API to report this to userspace, but that uses a netdev +pointer, which isn't present for P2P-Device. Fix this to +call it only conditionally to ensure cfg80211 won't crash +in the case of P2P-Device. + +This fixes CVE-2022-42722. + +(Cherry picked from commit:b2d03cabe2b2e150ff5a381731ea0355459be09f) +(Source:https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless.git) +(Link: https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless.git/ +commit/?id=b2d03cabe2b2e150ff5a381731ea0355459be09f) + +Reported-by: Sönke Huster +Fixes: 9eaf183af741 ("mac80211: Report beacon protection failures to user space") +Signed-off-by: Johannes Berg +Signed-off-by: Ganesh Babu Jothiram +--- + net/mac80211/rx.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 8dcd67d..76bda0c 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2066,10 +2066,11 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) + + if (mmie_keyidx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS || + mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS + +- NUM_DEFAULT_BEACON_KEYS) { +- cfg80211_rx_unprot_mlme_mgmt(rx->sdata->dev, +- skb->data, +- skb->len); ++ NUM_DEFAULT_BEACON_KEYS) { ++ if (rx->sdata->dev) ++ cfg80211_rx_unprot_mlme_mgmt(rx->sdata->dev, ++ skb->data, ++ skb->len); + return RX_DROP_MONITOR; /* unexpected BIP keyidx */ + } + +@@ -2220,7 +2221,8 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) + /* either the frame has been decrypted or will be dropped */ + status->flag |= RX_FLAG_DECRYPTED; + +- if (unlikely(ieee80211_is_beacon(fc) && result == RX_DROP_UNUSABLE)) ++ if (unlikely(ieee80211_is_beacon(fc) && result == RX_DROP_UNUSABLE && ++ rx->sdata->dev)) + cfg80211_rx_unprot_mlme_mgmt(rx->sdata->dev, + skb->data, skb->len); + +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/702-ath11k-fix-memory-leak-in-dp-rx.patch b/feeds/ipq95xx/mac80211/patches/qca/702-ath11k-fix-memory-leak-in-dp-rx.patch new file mode 100644 index 000000000..3ca61c7c9 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/702-ath11k-fix-memory-leak-in-dp-rx.patch @@ -0,0 +1,53 @@ +From 9e4857cfe7f646c239fde030eb16b3d6520c34d8 Mon Sep 17 00:00:00 2001 +From: Hari Chandrakanthan +Date: Fri, 6 Jan 2023 12:49:44 +0530 +Subject: [PATCH] ath11k: fix memory leak in dp rx + +In dp rx path, by default, fast_rx is set as true. +And if peer supports fast rx, the frame is sent to upper layer +through napi_gro_receive. + +If peer doesn't support fast rx, the frames need to be processed in +ath11k_dp_rx_deliver_msdu and sent to mac80211 using ieee80211_rx_napi. +In dp rx path, the api ath11k_dp_rx_h_mpdu checks whether peer supports +fast rx. + +If peer find fails in ath11k_dp_rx_h_mpdu, the skb is not sent to network stack +as well as mac80211. Because the argument fast_rx is not set to false in ath11k_dp_rx_h_mpdu +when peer find fails. + +This can lead to memory leak. + +Fix it by setting argument fast_rx as false in ath11k_dp_rx_h_mpdu +so that the skb is sent to mac80211 through ath11k_dp_rx_deliver_msdu. + +Signed-off-by: Hari Chandrakanthan +--- + drivers/net/wireless/ath/ath11k/dp_rx.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c +index 1a09159..0547567 100644 +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -2863,8 +2863,6 @@ static void ath11k_dp_rx_h_mpdu(struct ath11k *ar, + } + } + +- *fast_rx = false; +- + if (rxcb->is_mcbc) + enctype = peer->sec_type_grp; + else +@@ -2874,6 +2872,8 @@ static void ath11k_dp_rx_h_mpdu(struct ath11k *ar, + } + spin_unlock_bh(&ar->ab->base_lock); + ++ *fast_rx = false; ++ + rx_attention = ath11k_dp_rx_get_attention(ar->ab, rx_desc); + err_bitmap = ath11k_dp_rx_h_attn_mpdu_err(rx_attention); + if (enctype != HAL_ENCRYPT_TYPE_OPEN && !err_bitmap) +-- +2.7.4 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/697-ath12k-fixed-rate-2G-fix.patch b/feeds/ipq95xx/mac80211/patches/qca/702-ath12k-fixed-rate-2G-fix.patch similarity index 73% rename from feeds/ipq95xx/mac80211/patches/qca/697-ath12k-fixed-rate-2G-fix.patch rename to feeds/ipq95xx/mac80211/patches/qca/702-ath12k-fixed-rate-2G-fix.patch index f8d4212eb..6a1f6c992 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/697-ath12k-fixed-rate-2G-fix.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/702-ath12k-fixed-rate-2G-fix.patch @@ -1,6 +1,6 @@ -From 838dbb88939d818c5f822a5d602520e2874172c5 Mon Sep 17 00:00:00 2001 +From 6dcd102b17d1c6c4fa9f743b5346bad66c4cd073 Mon Sep 17 00:00:00 2001 From: Karthik M -Date: Wed, 30 Nov 2022 18:04:16 +0530 +Date: Tue, 6 Dec 2022 17:34:27 +0530 Subject: [PATCH] ath12k: Fixed MCS rate setting fix for 2G radio The EHT capability is advertised as part of ieee80211_sta_eht_cap. @@ -9,18 +9,16 @@ We have recently added the check to verify MCS 14 and 15 for all radios. For 2G radio, MCS 14 capabilty is not supported. We need to handle the mcs mask accordingly to allow the bitrate setting. -Fixes: 8f6ec9906 (cfg80211: add checks for mcs 14 and 15) - Signed-off-by: Karthik M --- - net/wireless/ath/ath12k/mac.c | 1 + + drivers/net/wireless/ath/ath12k/mac.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index fe4be83..28585f7 100644 +index c550884..37677c7 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -10133,6 +10133,7 @@ ath12k_mac_eht_mcs_range_present(struct ath12k *ar, +@@ -12015,6 +12015,7 @@ ath12k_mac_eht_mcs_range_present(struct ath12k *ar, break; case BIT(15) - 1: case BIT(16) - 1: diff --git a/feeds/ipq95xx/mac80211/patches/qca/703-01-cfg80211-add-support-for-set-bit-rate.patch b/feeds/ipq95xx/mac80211/patches/qca/703-01-cfg80211-add-support-for-set-bit-rate.patch new file mode 100644 index 000000000..b8b568e2c --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/703-01-cfg80211-add-support-for-set-bit-rate.patch @@ -0,0 +1,38 @@ +From 05b0aee11700b1fe379c0a796c9e9ce653de4402 Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Wed, 4 Jan 2023 15:59:57 +0530 +Subject: [PATCH] cfg80211: add support for set bit rate + +Currently, we set bit rate form user space according to phy. +But, in multi-link operation each phy has more than one link +and each link is work on different bit rate. + +So, add support to set bit rate according to link id. + +Signed-off-by: Aaradhana Sahu +--- + net/wireless/nl80211.c | 61 ++++++++++++++++++++++++++++++++++-------- + 1 file changed, 50 insertions(+), 11 deletions(-) + +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -5592,13 +5592,17 @@ static int nl80211_parse_tx_bitrate_mask + */ + BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8); + nla_for_each_nested(tx_rates, attrs[attr], rem) { +- enum nl80211_band band = nla_type(tx_rates); ++ enum nl80211_band band_link, band = nla_type(tx_rates); + int err; ++ struct cfg80211_chan_def *chandef = wdev_chandef(wdev, link_id); + ++ if (!chandef || !chandef->chan) ++ return -EINVAL; ++ band_link = chandef->chan->band; + if (band < 0 || band >= NUM_NL80211_BANDS) + return -EINVAL; + sband = rdev->wiphy.bands[band]; +- if (sband == NULL) ++ if (sband == NULL || band_link != band) + return -EINVAL; + err = nla_parse_nested_deprecated(tb, NL80211_TXRATE_MAX, + tx_rates, diff --git a/feeds/ipq95xx/mac80211/patches/qca/703-01-cfg80211-add-support-for-set-link-specific-tx-power.patch b/feeds/ipq95xx/mac80211/patches/qca/703-01-cfg80211-add-support-for-set-link-specific-tx-power.patch new file mode 100644 index 000000000..807c53ea5 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/703-01-cfg80211-add-support-for-set-link-specific-tx-power.patch @@ -0,0 +1,162 @@ +From 923be8cd3d5d81390b76dd88f9b5c23852cf5339 Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Fri, 16 Dec 2022 15:44:23 +0530 +Subject: [PATCH] cfg80211: add support for set link specific tx power + +Currently, we set tx power form user space according to +phy and each phy has particular band and tx power,but +in multi-link operation each phy has more than one +link and each link is working on different band, tx power. + +So, add support set tx power according to link id. + +Signed-off-by: Aaradhana Sahu +--- + include/net/cfg80211.h | 3 ++- + net/wireless/nl80211.c | 28 ++++++++++++++++++++++++---- + net/wireless/rdev-ops.h | 10 +++++++--- + net/wireless/trace.h | 5 +++-- + net/wireless/wext-compat.c | 2 +- + 5 files changed, 37 insertions(+), 11 deletions(-) + +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -4562,7 +4562,8 @@ struct cfg80211_ops { + int (*set_wiphy_params)(struct wiphy *wiphy, u32 changed); + + int (*set_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev, +- enum nl80211_tx_power_setting type, int mbm); ++ enum nl80211_tx_power_setting type, int mbm, ++ unsigned int link_id); + int (*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev, + unsigned int link_id, int *dbm); + +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -3792,6 +3792,7 @@ static int nl80211_set_wiphy(struct sk_b + struct wireless_dev *txp_wdev = wdev; + enum nl80211_tx_power_setting type; + int idx, mbm = 0; ++ unsigned int link_id; + + if (!(rdev->wiphy.features & NL80211_FEATURE_VIF_TXPOWER)) + txp_wdev = NULL; +@@ -3814,10 +3815,52 @@ static int nl80211_set_wiphy(struct sk_b + idx = NL80211_ATTR_WIPHY_TX_POWER_LEVEL; + mbm = nla_get_u32(info->attrs[idx]); + } +- +- result = rdev_set_tx_power(rdev, txp_wdev, type, mbm); +- if (result) +- goto out; ++ if (txp_wdev && txp_wdev->valid_links) { ++ if (!info->attrs[NL80211_ATTR_MLO_LINK_ID]) { ++ result = -EINVAL; ++ goto out; ++ } ++ link_id = nla_get_u8(info->attrs[NL80211_ATTR_MLO_LINK_ID]); ++ if (!(txp_wdev->valid_links & BIT(link_id))) { ++ result = -ENOLINK; ++ goto out; ++ } ++ ++ wdev_lock(txp_wdev); ++ result = rdev_set_tx_power(rdev, txp_wdev, type, mbm, link_id); ++ if (result) { ++ wdev_unlock(txp_wdev); ++ goto out; ++ } ++ wdev_unlock(txp_wdev); ++ } else { ++ if (!info->attrs[NL80211_ATTR_MLO_LINK_ID]) { ++ if (txp_wdev) { ++ wdev_lock(txp_wdev); ++ result = rdev_set_tx_power(rdev, txp_wdev, ++ type, mbm, 0); ++ if (result) { ++ wdev_unlock(txp_wdev); ++ goto out; ++ } ++ wdev_unlock(txp_wdev); ++ } else { ++ if (!rdev->wiphy.num_hw) { ++ result = rdev_set_tx_power(rdev, NULL, ++ type, mbm, 0); ++ ++ if (result) ++ goto out; ++ } else { ++ result = -EOPNOTSUPP; ++ goto out; ++ } ++ } ++ } else { ++ result = -EINVAL; ++ goto out; ++ } ++ } + } + + if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] && +--- a/net/wireless/rdev-ops.h ++++ b/net/wireless/rdev-ops.h +@@ -575,11 +575,13 @@ rdev_set_wiphy_params(struct cfg80211_re + + static inline int rdev_set_tx_power(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev, +- enum nl80211_tx_power_setting type, int mbm) ++ enum nl80211_tx_power_setting type, ++ int mbm, unsigned int link_id) + { + int ret; +- trace_rdev_set_tx_power(&rdev->wiphy, wdev, type, mbm); +- ret = rdev->ops->set_tx_power(&rdev->wiphy, wdev, type, mbm); ++ ++ trace_rdev_set_tx_power(&rdev->wiphy, wdev, type, mbm, link_id); ++ ret = rdev->ops->set_tx_power(&rdev->wiphy, wdev, type, mbm, link_id); + trace_rdev_return_int(&rdev->wiphy, ret); + return ret; + } +--- a/net/wireless/trace.h ++++ b/net/wireless/trace.h +@@ -1590,22 +1590,25 @@ DEFINE_EVENT(wiphy_wdev_evt, rdev_get_tx + + TRACE_EVENT(rdev_set_tx_power, + TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, +- enum nl80211_tx_power_setting type, int mbm), +- TP_ARGS(wiphy, wdev, type, mbm), ++ enum nl80211_tx_power_setting type, int mbm, ++ unsigned int link_id), ++ TP_ARGS(wiphy, wdev, type, mbm, link_id), + TP_STRUCT__entry( + WIPHY_ENTRY + WDEV_ENTRY + __field(enum nl80211_tx_power_setting, type) + __field(int, mbm) ++ __field(unsigned int, link_id) + ), + TP_fast_assign( + WIPHY_ASSIGN; + WDEV_ASSIGN; + __entry->type = type; + __entry->mbm = mbm; ++ __entry->link_id = link_id + ), +- TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", type: %u, mbm: %d", +- WIPHY_PR_ARG, WDEV_PR_ARG,__entry->type, __entry->mbm) ++ TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", type: %u, mbm: %d, link_id: %d", ++ WIPHY_PR_ARG, WDEV_PR_ARG,__entry->type, __entry->mbm, __entry->link_id) + ); + + TRACE_EVENT(rdev_return_int_int, +--- a/net/wireless/wext-compat.c ++++ b/net/wireless/wext-compat.c +@@ -952,7 +952,7 @@ static int cfg80211_wext_siwtxpower(stru + } + + wiphy_lock(&rdev->wiphy); +- ret = rdev_set_tx_power(rdev, wdev, type, DBM_TO_MBM(dbm)); ++ ret = rdev_set_tx_power(rdev, wdev, type, DBM_TO_MBM(dbm), 0); + wiphy_unlock(&rdev->wiphy); + + return ret; diff --git a/feeds/ipq95xx/mac80211/patches/qca/703-02-mac80211-add-support-for-set-bit-rate.patch b/feeds/ipq95xx/mac80211/patches/qca/703-02-mac80211-add-support-for-set-bit-rate.patch new file mode 100644 index 000000000..54b3a974e --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/703-02-mac80211-add-support-for-set-bit-rate.patch @@ -0,0 +1,88 @@ +From 994697af6b74606178c8672fd51247d2019024c1 Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Wed, 4 Jan 2023 16:04:10 +0530 +Subject: [PATCH] mac80211: add support for set bit rate + +Currently, we set bit rate form user space according to phy. +But, in multi-link operation each phy has more than one link +and each link is work on different bit rate. + +So, add support to set bit rate according to link id. + +Signed-off-by: Aaradhana Sahu +--- + include/net/mac80211.h | 1 + + net/mac80211/cfg.c | 2 +- + net/mac80211/driver-ops.h | 5 +++-- + net/mac80211/trace.h | 3 ++- + 4 files changed, 7 insertions(+), 4 deletions(-) + +diff --git a/include/net/mac80211.h b/include/net/mac80211.h +index 550c294..a949d20 100644 +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -4474,6 +4474,7 @@ struct ieee80211_ops { + u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max); + bool (*tx_frames_pending)(struct ieee80211_hw *hw); + int (*set_bitrate_mask)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ++ unsigned int link_id, + const struct cfg80211_bitrate_mask *mask); + void (*event_callback)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, +diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c +index deb08a1..52055dd 100644 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -3398,7 +3398,7 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, + return -ENETDOWN; + + if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL)) { +- ret = drv_set_bitrate_mask(local, sdata, mask); ++ ret = drv_set_bitrate_mask(local, sdata, link_id, mask); + if (ret) + return ret; + } +diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h +index 7a3b7cc..52325f1 100644 +--- a/net/mac80211/driver-ops.h ++++ b/net/mac80211/driver-ops.h +@@ -748,6 +748,7 @@ static inline bool drv_tx_frames_pending(struct ieee80211_local *local) + + static inline int drv_set_bitrate_mask(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, ++ unsigned int link_id, + const struct cfg80211_bitrate_mask *mask) + { + int ret = -EOPNOTSUPP; +@@ -757,10 +758,10 @@ static inline int drv_set_bitrate_mask(struct ieee80211_local *local, + if (!check_sdata_in_driver(sdata)) + return -EIO; + +- trace_drv_set_bitrate_mask(local, sdata, mask); ++ trace_drv_set_bitrate_mask(local, sdata, link_id, mask); + if (local->ops->set_bitrate_mask) + ret = local->ops->set_bitrate_mask(&local->hw, +- &sdata->vif, mask); ++ &sdata->vif, link_id, mask); + trace_drv_return_int(local, ret); + + return ret; +diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h +index a7c98ac..c78ffad 100644 +--- a/net/mac80211/trace.h ++++ b/net/mac80211/trace.h +@@ -1426,9 +1426,10 @@ DEFINE_EVENT(local_only_evt, drv_offchannel_tx_cancel_wait, + TRACE_EVENT(drv_set_bitrate_mask, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, ++ unsigned int link_id, + const struct cfg80211_bitrate_mask *mask), + +- TP_ARGS(local, sdata, mask), ++ TP_ARGS(local, sdata, link_id, mask), + + TP_STRUCT__entry( + LOCAL_ENTRY +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/703-02-mac80211-add-support-for-set-link-specific-tx-power.patch b/feeds/ipq95xx/mac80211/patches/qca/703-02-mac80211-add-support-for-set-link-specific-tx-power.patch new file mode 100644 index 000000000..2440740a5 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/703-02-mac80211-add-support-for-set-link-specific-tx-power.patch @@ -0,0 +1,249 @@ +From f689bf1cf18b473e82deab670a04064c2ce0db32 Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Fri, 16 Dec 2022 15:58:50 +0530 +Subject: [PATCH] mac80211: add support for set link specific tx power + +Currently, we set tx power form user space according to +phy and each phy has particular band and tx power,but +in multi-link operation each phy has more than one +link and each link is working on different band, tx power. + +So, add support set tx power according to link id. + +Signed-off-by: Aaradhana Sahu +--- + net/mac80211/cfg.c | 24 ++++++++++++++--------- + net/mac80211/chan.c | 4 ++-- + net/mac80211/ieee80211_i.h | 5 +++-- + net/mac80211/iface.c | 39 +++++++++++++++++++++++++------------- + net/mac80211/link.c | 4 ++++ + net/mac80211/mlme.c | 2 +- + 6 files changed, 51 insertions(+), 27 deletions(-) + +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -3071,17 +3071,23 @@ static int ieee80211_set_wiphy_params(st + + static int ieee80211_set_tx_power(struct wiphy *wiphy, + struct wireless_dev *wdev, +- enum nl80211_tx_power_setting type, int mbm) ++ enum nl80211_tx_power_setting type, ++ int mbm, unsigned int link_id) + { + struct ieee80211_local *local = wiphy_priv(wiphy); + struct ieee80211_sub_if_data *sdata; + enum nl80211_tx_power_setting txp_type = type; + bool update_txp_type = false; + bool has_monitor = false; ++ struct ieee80211_link_data *link_data; + + if (wdev) { + sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); + ++ link_data = sdata_dereference(sdata->link[link_id], sdata); ++ if (!link_data) ++ return -ENOLINK; ++ + if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { + sdata = wiphy_dereference(local->hw.wiphy, + local->monitor_sdata); +@@ -3091,7 +3097,7 @@ static int ieee80211_set_tx_power(struct + + switch (type) { + case NL80211_TX_POWER_AUTOMATIC: +- sdata->deflink.user_power_level = ++ link_data->user_power_level = + IEEE80211_UNSET_POWER_LEVEL; + txp_type = NL80211_TX_POWER_LIMITED; + break; +@@ -3099,16 +3105,16 @@ static int ieee80211_set_tx_power(struct + case NL80211_TX_POWER_FIXED: + if (mbm < 0 || (mbm % 100)) + return -EOPNOTSUPP; +- sdata->deflink.user_power_level = MBM_TO_DBM(mbm); ++ link_data->user_power_level = MBM_TO_DBM(mbm); + break; + } + +- if (txp_type != sdata->vif.bss_conf.txpower_type) { ++ if (txp_type != link_data->conf->txpower_type) { + update_txp_type = true; +- sdata->vif.bss_conf.txpower_type = txp_type; ++ link_data->conf->txpower_type = txp_type; + } + +- ieee80211_recalc_txpower(sdata, update_txp_type); ++ ieee80211_recalc_txpower(sdata, update_txp_type, link_id); + + return 0; + } +@@ -3126,6 +3132,7 @@ static int ieee80211_set_tx_power(struct + break; + } + ++ /*TODO: monitor mode for MLO */ + mutex_lock(&local->iflist_mtx); + list_for_each_entry(sdata, &local->interfaces, list) { + if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { +@@ -3140,7 +3147,7 @@ static int ieee80211_set_tx_power(struct + list_for_each_entry(sdata, &local->interfaces, list) { + if (sdata->vif.type == NL80211_IFTYPE_MONITOR) + continue; +- ieee80211_recalc_txpower(sdata, update_txp_type); ++ ieee80211_recalc_txpower(sdata, update_txp_type, link_id); + } + mutex_unlock(&local->iflist_mtx); + +@@ -3153,7 +3160,7 @@ static int ieee80211_set_tx_power(struct + update_txp_type = true; + sdata->vif.bss_conf.txpower_type = txp_type; + +- ieee80211_recalc_txpower(sdata, update_txp_type); ++ ieee80211_recalc_txpower(sdata, update_txp_type, 0); + } + } + +--- a/net/mac80211/chan.c ++++ b/net/mac80211/chan.c +@@ -899,7 +899,7 @@ out: + } + + if (new_ctx && ieee80211_chanctx_num_assigned(local, new_ctx) > 0) { +- ieee80211_recalc_txpower(sdata, false); ++ ieee80211_recalc_txpower(sdata, false, link->link_id); + ieee80211_recalc_chanctx_min_def(local, new_ctx); + } + +@@ -1686,7 +1686,7 @@ static int ieee80211_vif_use_reserved_sw + link, + changed); + +- ieee80211_recalc_txpower(sdata, false); ++ ieee80211_recalc_txpower(sdata, false, link->link_id); + } + + ieee80211_recalc_chanctx_chantype(local, ctx); +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1983,9 +1983,10 @@ void ieee80211_sdata_stop(struct ieee802 + int ieee80211_add_virtual_monitor(struct ieee80211_local *local); + void ieee80211_del_virtual_monitor(struct ieee80211_local *local); + +-bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata); ++bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata, ++ unsigned int link_id); + void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata, +- bool update_bss); ++ bool update_bss, unsigned int link_id); + void ieee80211_recalc_offload(struct ieee80211_local *local); + + static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata) +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -57,13 +57,20 @@ MODULE_PARM_DESC(ppe_vp_accel, "module p + + static void ieee80211_iface_work(struct work_struct *work); + +-bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata) ++bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata, ++ unsigned int link_id) + { + struct ieee80211_chanctx_conf *chanctx_conf; + int power; ++ struct ieee80211_link_data *link_data; ++ ++ link_data = sdata_dereference(sdata->link[link_id], sdata); ++ if (!link_data) ++ return false; + + rcu_read_lock(); +- chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf); ++ ++ chanctx_conf = rcu_dereference(link_data->conf->chanctx_conf); + if (!chanctx_conf) { + rcu_read_unlock(); + return false; +@@ -72,14 +79,14 @@ bool __ieee80211_recalc_txpower(struct i + power = ieee80211_chandef_max_power(&chanctx_conf->def); + rcu_read_unlock(); + +- if (sdata->deflink.user_power_level != IEEE80211_UNSET_POWER_LEVEL) +- power = min(power, sdata->deflink.user_power_level); ++ if (link_data->user_power_level != IEEE80211_UNSET_POWER_LEVEL) ++ power = min(power, link_data->user_power_level); + +- if (sdata->deflink.ap_power_level != IEEE80211_UNSET_POWER_LEVEL) +- power = min(power, sdata->deflink.ap_power_level); ++ if (link_data->ap_power_level != IEEE80211_UNSET_POWER_LEVEL) ++ power = min(power, link_data->ap_power_level); + +- if (power != sdata->vif.bss_conf.txpower) { +- sdata->vif.bss_conf.txpower = power; ++ if (power != link_data->conf->txpower) { ++ link_data->conf->txpower = power; + ieee80211_hw_config(sdata->local, 0); + return true; + } +@@ -88,12 +95,19 @@ bool __ieee80211_recalc_txpower(struct i + } + + void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata, +- bool update_bss) ++ bool update_bss, unsigned int link_id) + { +- if (__ieee80211_recalc_txpower(sdata) || +- (update_bss && ieee80211_sdata_running(sdata))) +- ieee80211_link_info_change_notify(sdata, &sdata->deflink, ++ if (__ieee80211_recalc_txpower(sdata, link_id) || ++ (update_bss && ieee80211_sdata_running(sdata))) { ++ struct ieee80211_link_data *link_data; ++ ++ link_data = sdata_dereference(sdata->link[link_id], sdata); ++ if (!link_data) ++ return; ++ ++ ieee80211_link_info_change_notify(sdata, link_data, + BSS_CHANGED_TXPOWER); ++ } + } + + static u32 __ieee80211_idle_off(struct ieee80211_local *local) +@@ -2316,7 +2330,6 @@ int ieee80211_if_add(struct ieee80211_lo + + sdata->deflink.ap_power_level = IEEE80211_UNSET_POWER_LEVEL; + sdata->deflink.user_power_level = local->user_power_level; +- + /* setup type-dependent data */ + ieee80211_setup_sdata(sdata, type); + +--- a/net/mac80211/link.c ++++ b/net/mac80211/link.c +@@ -21,6 +21,7 @@ void ieee80211_link_init(struct ieee8021 + struct ieee80211_link_data *link, + struct ieee80211_bss_conf *link_conf) + { ++ struct ieee80211_local *local = sdata->local; + bool deflink = link_id < 0; + + if (link_id < 0) +@@ -43,6 +44,9 @@ void ieee80211_link_init(struct ieee8021 + INIT_DELAYED_WORK(&link->dfs_cac_timer_work, + ieee80211_dfs_cac_timer_work); + ++ link->ap_power_level = IEEE80211_UNSET_POWER_LEVEL; ++ link->user_power_level = local->user_power_level; ++ + if (!deflink) { + switch (sdata->vif.type) { + case NL80211_IFTYPE_AP: +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -2095,7 +2095,7 @@ static u32 ieee80211_handle_pwr_constr(s + } + + link->ap_power_level = new_ap_level; +- if (__ieee80211_recalc_txpower(sdata)) ++ if (__ieee80211_recalc_txpower(sdata, 0)) + return BSS_CHANGED_TXPOWER; + return 0; + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/703-03-ath12k-add-support-for-set-bit-rate.patch b/feeds/ipq95xx/mac80211/patches/qca/703-03-ath12k-add-support-for-set-bit-rate.patch new file mode 100644 index 000000000..2366ebe2f --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/703-03-ath12k-add-support-for-set-bit-rate.patch @@ -0,0 +1,204 @@ +From 8c8a55cd772bfa1d7b909152ddb0e0416c144b79 Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Wed, 4 Jan 2023 16:13:05 +0530 +Subject: [PATCH] ath12k: add support for set bit rate + +Currently, we set bit rate form user space according to phy. +But, in multi-link operation each phy has more than one link +and each link is work on different bit rate. + +So, add support to set bit rate according to link id. + +Signed-off-by: Aaradhana Sahu +--- + drivers/net/wireless/ath/ath12k/mac.c | 23 +++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -5367,6 +5367,7 @@ ath12k_mac_set_peer_vht_fixed_rate(struc + int ret, i; + struct ath12k_sta *ahsta = arsta->ahsta; + struct ieee80211_sta *sta; ++ struct ieee80211_link_sta *link_sta; + + sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + +@@ -5387,6 +5388,16 @@ ath12k_mac_set_peer_vht_fixed_rate(struc + return -EINVAL; + } + ++ /* Avoid updating invalid nss as fixed rate*/ ++ rcu_read_lock(); ++ link_sta = rcu_dereference(sta->link[arsta->link_id]); ++ ++ if (!link_sta || nss > link_sta->rx_nss) { ++ rcu_read_unlock(); ++ return -EINVAL; ++ } ++ ++ rcu_read_unlock(); + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, + "Setting Fixed VHT Rate for peer %pM. Device will not switch to any other selected rates", + arsta->addr); +@@ -5417,6 +5428,7 @@ ath12k_mac_set_peer_he_fixed_rate(struct + int ret, i; + struct ath12k_sta *ahsta = arsta->ahsta; + struct ieee80211_sta *sta; ++ struct ieee80211_link_sta *link_sta; + + sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + +@@ -5438,9 +5450,15 @@ ath12k_mac_set_peer_he_fixed_rate(struct + } + + /* Avoid updating invalid nss as fixed rate*/ +- if (nss > sta->deflink.rx_nss) ++ rcu_read_lock(); ++ link_sta = rcu_dereference(sta->link[arsta->link_id]); ++ ++ if (!link_sta || nss > link_sta->rx_nss) { ++ rcu_read_unlock(); + return -EINVAL; ++ } + ++ rcu_read_unlock(); + 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); +@@ -5472,6 +5490,7 @@ ath12k_mac_set_peer_ht_fixed_rate(struct + int ret, i; + struct ath12k_sta *ahsta = arsta->ahsta; + struct ieee80211_sta *sta; ++ struct ieee80211_link_sta *link_sta; + + sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + +@@ -5493,9 +5512,15 @@ ath12k_mac_set_peer_ht_fixed_rate(struct + } + + /* Avoid updating invalid nss as fixed rate*/ +- if (nss > sta->deflink.rx_nss) ++ rcu_read_lock(); ++ link_sta = rcu_dereference(sta->link[arsta->link_id]); ++ ++ if (!link_sta || nss > link_sta->rx_nss) { ++ rcu_read_unlock(); + return -EINVAL; ++ } + ++ rcu_read_unlock(); + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, + "Setting Fixed HT Rate for peer %pM. Device will not switch to any other selected rates", + sta->addr); +@@ -5527,6 +5552,7 @@ ath12k_mac_set_peer_eht_fixed_rate(struc + int ret, i; + struct ath12k_sta *ahsta = arsta->ahsta; + struct ieee80211_sta *sta; ++ struct ieee80211_link_sta *link_sta; + + sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + +@@ -5548,9 +5574,15 @@ ath12k_mac_set_peer_eht_fixed_rate(struc + } + + /* Avoid updating invalid nss as fixed rate*/ +- if (nss > sta->deflink.rx_nss) ++ rcu_read_lock(); ++ link_sta = rcu_dereference(sta->link[arsta->link_id]); ++ ++ if (!link_sta || nss > link_sta->rx_nss) { ++ rcu_read_unlock(); + return -EINVAL; ++ } + ++ rcu_read_unlock(); + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, + "Setting Fixed EHT Rate for peer %pM. Device will not switch to any other selected rates", + arsta->addr); +@@ -5832,6 +5864,8 @@ static void ath12k_sta_rc_update_wk(stru + struct peer_assoc_params peer_arg; + enum wmi_phy_mode peer_phymode; + struct ath12k_sta *ahsta; ++ struct ieee80211_link_sta *link_sta = NULL; ++ bool ht_supp, vht_supp, has_he, has_eht; + + arsta = container_of(wk, struct ath12k_link_sta, update_wk); + ahsta = arsta->ahsta; +@@ -5840,8 +5874,7 @@ static void ath12k_sta_rc_update_wk(stru + ahvif = arvif->ahvif; + ar = arvif->ar; + +- /* TODO get link_id and pass for ML - link STA */ +- if (WARN_ON(ath12k_mac_vif_chan(ahvif->vif, &def, 0))) ++ if (WARN_ON(ath12k_mac_vif_chan(ahvif->vif, &def, arsta->link_id))) + return; + + band = def.chan->band; +@@ -5962,16 +5995,31 @@ static void ath12k_sta_rc_update_wk(stru + * TODO: Check RATEMASK_CMDID to support auto rates selection + * across HT/VHT and for multiple VHT MCS support. + */ +- if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) { ++ rcu_read_lock(); ++ link_sta = rcu_dereference(sta->link[arsta->link_id]); ++ ++ if (!link_sta) { ++ rcu_read_unlock(); ++ goto err_rc_bw_changed; ++ } ++ ++ ht_supp = link_sta->ht_cap.ht_supported; ++ vht_supp = link_sta->vht_cap.vht_supported; ++ has_he = link_sta->he_cap.has_he; ++ has_eht = link_sta->eht_cap.has_eht; ++ rcu_read_unlock(); ++ ++ if (vht_supp && num_vht_rates == 1) { ++ + ath12k_mac_set_peer_vht_fixed_rate(arvif, arsta, mask, + band); +- } else if (sta->deflink.he_cap.has_he && num_he_rates == 1) { ++ } else if (has_he && num_he_rates == 1) { + ath12k_mac_set_peer_he_fixed_rate(arvif, arsta, mask, + band); +- } else if (sta->deflink.eht_cap.has_eht && num_eht_rates == 1) { ++ } else if (has_eht && num_eht_rates == 1) { + ath12k_mac_set_peer_eht_fixed_rate(arvif, arsta, mask, + band); +- } else if (sta->deflink.ht_cap.ht_supported && num_ht_rates == 1) { ++ } else if (ht_supp && num_ht_rates == 1) { + ath12k_mac_set_peer_ht_fixed_rate(arvif, arsta, mask, + band); + } else { +@@ -12449,7 +12497,7 @@ ath12k_mac_check_fixed_rate_settings_for + + static int + ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, +- struct ieee80211_vif *vif, ++ struct ieee80211_vif *vif, unsigned int link_id, + const struct cfg80211_bitrate_mask *mask) + { + struct ath12k_hw *ah = hw->priv; +@@ -12477,8 +12525,6 @@ ath12k_mac_op_set_bitrate_mask(struct ie + bool he_fixed_rate = false; + bool eht_fixed_rate = false; + struct ath12k_link_vif *arvif; +- /* TODO move after link id passed through this op */ +- u8 link_id = 0; + + if (ath12k_mac_vif_chan(vif, &def, link_id)) + return -EPERM; +@@ -12508,6 +12554,12 @@ ath12k_mac_op_set_bitrate_mask(struct ie + eht_mcs_mask = mask->control[band].eht_mcs; + ldpc = !!(ar->ht_cap_info & WMI_HT_CAP_LDPC); + ++ if (vif->valid_links && ath12k_peer_assoc_h_eht_masked(eht_mcs_mask)) { ++ ath12k_warn(ar->ab, "cannot disable EHT rates on a ML bss\n"); ++ ret = -EINVAL; ++ goto out; ++ } ++ + sgi = mask->control[band].gi; + if (sgi == NL80211_TXRATE_FORCE_LGI) { + ret = -EINVAL; diff --git a/feeds/ipq95xx/mac80211/patches/qca/703-04-ath11k-add-support-for-set-bit-rate.patch b/feeds/ipq95xx/mac80211/patches/qca/703-04-ath11k-add-support-for-set-bit-rate.patch new file mode 100644 index 000000000..c7003b05a --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/703-04-ath11k-add-support-for-set-bit-rate.patch @@ -0,0 +1,28 @@ +From 0a47f5662f788b5b5b4cbc634b3c7523ca0b2bcb Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Thu, 22 Dec 2022 10:08:16 +0530 +Subject: [PATCH] ath11k: add link id argument to ath11k_mac_op_set_bitrate_mask + +To avoid compilation issue. + +Signed-off-by: Aaradhana Sahu +--- + drivers/net/wireless/ath/ath11k/mac.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c +index 47c2f88..9fcf31c 100644 +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -11127,7 +11127,7 @@ ath11k_mac_check_fixed_rate_settings_for_mumimo(struct ath11k_vif *arvif, const + + static int + ath11k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, +- struct ieee80211_vif *vif, ++ struct ieee80211_vif *vif, unsigned int link_id, + const struct cfg80211_bitrate_mask *mask) + { + struct ath11k_vif *arvif = (void *)vif->drv_priv; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/703-ath11k-regdb-binary-support-removal.patch b/feeds/ipq95xx/mac80211/patches/qca/703-ath11k-regdb-binary-support-removal.patch new file mode 100644 index 000000000..3b2d633d3 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/703-ath11k-regdb-binary-support-removal.patch @@ -0,0 +1,65 @@ +From dad1a4c45dda747b6bb63b1a10daff4e816f5979 Mon Sep 17 00:00:00 2001 +From: Karthik M +Date: Thu, 8 Dec 2022 18:46:56 +0530 +Subject: [PATCH] ath11k : regdb separate binary support removal + +lithium architecture no longer needed support for download of +separate regdb.bin. It will be encoded as part of board-2.bin. + +Signed-off-by: Karthik M +--- + drivers/net/wireless/ath/ath11k/core.c | 12 +++--------- + drivers/net/wireless/ath/ath11k/qmi.c | 2 +- + 2 files changed, 4 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c +index 1db2334..49d514d 100644 +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -1554,7 +1554,6 @@ int ath11k_core_fetch_regdb(struct ath11k_base *ab, struct ath11k_board_data *bd + return ret; + } + +- ab->bd_api = 2; + ret = ath11k_core_fetch_board_data_api_n(ab, bd, regdbname, + ATH11K_BD_IE_REGDB, + ATH11K_BD_IE_REGDB_NAME, +@@ -1566,19 +1565,14 @@ int ath11k_core_fetch_regdb(struct ath11k_base *ab, struct ath11k_board_data *bd + ATH11K_BD_IE_REGDB, + ATH11K_BD_IE_REGDB_NAME, + ATH11K_BD_IE_REGDB_DATA); +- if (!ret) +- goto success; +- +- ab->bd_api = 1; +- ret = ath11k_core_fetch_board_data_api_1(ab, bd, ATH11K_REGDB_FILE_NAME); + if (ret) { +- ath11k_dbg(ab, ATH11K_DBG_BOOT, "failed to fetch %s from %s\n", +- ATH11K_REGDB_FILE_NAME, ab->hw_params.fw.dir); ++ ath11k_dbg(ab, ATH11K_DBG_BOOT, "failed to fetch %s from board-2.bin\n", ++ ATH11K_REGDB_FILE_NAME); + return ret; + } + + success: +- ath11k_dbg(ab, ATH11K_DBG_BOOT, "using board api %d\n", ab->bd_api); ++ ath11k_dbg(ab, ATH11K_DBG_BOOT, "using board-2.bin\n"); + return 0; + } + +diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c +index 64c05d9..6fc1159 100644 +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -4319,7 +4319,7 @@ static int ath11k_qmi_event_load_bdf(struct ath11k_qmi *qmi) + return ret; + } + +- if (ab->hw_params.supports_regdb) ++ if (ab->hw_params.supports_regdb && ab->qmi.target.regdb) + ath11k_qmi_load_bdf_qmi(ab, true); + + ret = ath11k_qmi_load_bdf_qmi(ab, false); +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/703-ath12k-11be-spectral-scan-support.patch b/feeds/ipq95xx/mac80211/patches/qca/703-ath12k-11be-spectral-scan-support.patch new file mode 100644 index 000000000..651fa026e --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/703-ath12k-11be-spectral-scan-support.patch @@ -0,0 +1,949 @@ +From 1838228b17c223ca6ae3f8ce2932329825f258eb Mon Sep 17 00:00:00 2001 +From: Rajat Soni +Date: Fri, 10 Feb 2023 17:06:43 +0530 +Subject: [PATCH] ath12k: 11be spectral scan support + +Add support for 11be spectral scan. IPQ9274 also support spectral +scan for 320 MHZ. + +Signed-off-by: Rajat Soni +--- + drivers/net/wireless/ath/ath12k/dbring.c | 32 ++- + drivers/net/wireless/ath/ath12k/dbring.h | 15 ++ + drivers/net/wireless/ath/ath12k/hw.c | 16 ++ + drivers/net/wireless/ath/ath12k/hw.h | 10 +- + drivers/net/wireless/ath/ath12k/mac.c | 4 + + drivers/net/wireless/ath/ath12k/spectral.c | 173 ++++++++++++--- + drivers/net/wireless/ath/ath12k/spectral.h | 3 + + drivers/net/wireless/ath/ath12k/wmi.c | 236 +++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/wmi.h | 82 +++++++ + drivers/net/wireless/ath/spectral_common.h | 3 +- + 10 files changed, 544 insertions(+), 30 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/dbring.c ++++ b/drivers/net/wireless/ath/ath12k/dbring.c +@@ -7,6 +7,34 @@ + #include "core.h" + #include "debug.h" + ++#define ATH12K_DB_MAGIC_VALUE 0xdeadbeaf ++ ++int ath12k_dbring_validate_buffer(struct ath12k *ar, void *buffer, u32 size) ++{ ++ u32 *temp; ++ int idx; ++ size = size >> 2; ++ ++ for (idx = 0, temp = buffer; idx < size; idx++, temp++) { ++ if (*temp == ATH12K_DB_MAGIC_VALUE) ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static void ath12k_dbring_fill_magic_value(struct ath12k *ar, ++ void *buffer, u32 size) ++{ ++ /* memset32 function fills buffer payload with the ATH12K_DB_MAGIC_VALUE ++ * and the variable size is expected to be the number of u32 values ++ * to be stored, not the number of bytes. ++ */ ++ size = size / sizeof(u32); ++ ++ memset32(buffer, ATH12K_DB_MAGIC_VALUE, size); ++} ++ + static int ath12k_dbring_bufs_replenish(struct ath12k *ar, + struct ath12k_dbring *ring, + struct ath12k_dbring_element *buff, +@@ -28,6 +56,7 @@ static int ath12k_dbring_bufs_replenish( + + ptr_unaligned = buff->payload; + ptr_aligned = PTR_ALIGN(ptr_unaligned, ring->buf_align); ++ ath12k_dbring_fill_magic_value(ar, ptr_aligned, ring->buf_sz); + paddr = dma_map_single(ab->dev, ptr_aligned, ring->buf_sz, + DMA_FROM_DEVICE); + +@@ -51,6 +80,7 @@ static int ath12k_dbring_bufs_replenish( + + buff->paddr = paddr; + ++ dma_sync_single_for_device(ab->dev, paddr, ring->buf_sz, DMA_FROM_DEVICE); + cookie = u32_encode_bits(ar->pdev_idx, DP_DIR_BUF_COOKIE_PDEV_ID) | + u32_encode_bits(buf_id, DP_DIR_BUF_COOKIE_BUF_ID); + +@@ -177,7 +207,7 @@ int ath12k_dbring_buf_setup(struct ath12 + ring->hp_addr = ath12k_hal_srng_get_hp_addr(ar->ab, srng); + ring->tp_addr = ath12k_hal_srng_get_tp_addr(ar->ab, srng); + +- ret = ath12k_dbring_fill_bufs(ar, ring, GFP_KERNEL); ++ ret = ath12k_dbring_fill_bufs(ar, ring, GFP_ATOMIC); + + return ret; + } +@@ -299,7 +329,7 @@ int ath12k_dbring_buffer_release_event(s + + ath12k_hal_rx_buf_addr_info_get(&desc, &paddr, &cookie, &rbm); + +- buf_id = u32_get_bits(cookie, DP_RXDMA_BUF_COOKIE_BUF_ID); ++ buf_id = u32_get_bits(cookie, DP_DIR_BUF_COOKIE_BUF_ID); + + spin_lock_bh(&ring->idr_lock); + buff = idr_find(&ring->bufs_idr, buf_id); +--- a/drivers/net/wireless/ath/ath12k/dbring.h ++++ b/drivers/net/wireless/ath/ath12k/dbring.h +@@ -31,6 +31,20 @@ struct ath12k_dbring_buf_release_event { + u32 num_meta; + }; + ++struct wmi_pdev_sscan_fw_param_event { ++ struct ath12k_wmi_pdev_sscan_fw_cmd_fixed_param fixed; ++ struct ath12k_wmi_pdev_sscan_fft_bin_index *bin; ++ struct ath12k_wmi_pdev_sscan_chan_info ch_info; ++ struct ath12k_wmi_pdev_sscan_per_detector_info *det_info; ++}; ++ ++struct wmi_spectral_capabilities_event { ++ struct ath12k_wmi_spectral_scan_bw_capabilities *sscan_bw_caps; ++ struct ath12k_wmi_spectral_fft_size_capabilities *fft_size_caps; ++ u32 num_bw_caps_entry; ++ u32 num_fft_size_caps_entry; ++}; ++ + struct ath12k_dbring_cap { + u32 pdev_id; + enum wmi_direct_buffer_module id; +@@ -77,4 +91,5 @@ int ath12k_dbring_get_cap(struct ath12k_ + struct ath12k_dbring_cap *db_cap); + void ath12k_dbring_srng_cleanup(struct ath12k *ar, struct ath12k_dbring *ring); + void ath12k_dbring_buf_cleanup(struct ath12k *ar, struct ath12k_dbring *ring); ++int ath12k_dbring_validate_buffer(struct ath12k *ar, void *data, u32 size); + #endif /* ATH12K_DBRING_H */ +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -1016,6 +1016,14 @@ static const struct ath12k_hw_params ath + .credit_flow = false, + .wakeup_mhi = false, + .alloc_cacheable_memory = true, ++ .spectral = { ++ .fft_sz = 0, ++ .fft_pad_sz = 0, ++ .summary_pad_sz = 0, ++ .fft_hdr_len = 0, ++ .max_fft_bins = 0, ++ .fragment_160mhz = false, ++ }, + .max_mlo_peer = ATH12K_MAX_MLO_PEER, + .num_local_link = 0, + }, +@@ -1146,6 +1154,14 @@ static const struct ath12k_hw_params ath + .credit_flow = false, + .wakeup_mhi = false, + .alloc_cacheable_memory = true, ++ .spectral = { ++ .fft_sz = 7, ++ .fft_pad_sz = 0, ++ .summary_pad_sz = 16, ++ .fft_hdr_len = 24, ++ .max_fft_bins = 512, ++ .fragment_160mhz = true, ++ }, + .max_mlo_peer = ATH12K_MAX_MLO_PEER, + .num_local_link = 0, + }, +--- a/drivers/net/wireless/ath/ath12k/hw.h ++++ b/drivers/net/wireless/ath/ath12k/hw.h +@@ -170,7 +170,15 @@ struct ath12k_hw_params { + int num_rxdma_dst_ring; + bool rx_mac_buf_ring; + bool vdev_start_delay; +- u8 spectral_fft_sz; ++ ++ struct { ++ u8 fft_sz; ++ u8 fft_pad_sz; ++ u8 summary_pad_sz; ++ u8 fft_hdr_len; ++ u16 max_fft_bins; ++ bool fragment_160mhz; ++ } spectral; + + u16 interface_modes; + bool supports_monitor; +--- a/drivers/net/wireless/ath/ath12k/spectral.c ++++ b/drivers/net/wireless/ath/ath12k/spectral.c +@@ -12,27 +12,28 @@ + #define ATH12K_SPECTRAL_EVENT_TIMEOUT_MS 1 + + #define ATH12K_SPECTRAL_DWORD_SIZE 4 +-/* HW bug, expected BIN size is 2 bytes but HW report as 4 bytes */ +-#define ATH12K_SPECTRAL_BIN_SIZE 4 ++#define ATH12K_SPECTRAL_BIN_SIZE 1 + #define ATH12K_SPECTRAL_ATH12K_MIN_BINS 64 +-#define ATH12K_SPECTRAL_ATH12K_MIN_IB_BINS 32 +-#define ATH12K_SPECTRAL_ATH12K_MAX_IB_BINS 256 ++#define ATH12K_SPECTRAL_ATH12K_MIN_IB_BINS (ATH12K_SPECTRAL_ATH12K_MIN_BINS>>1) ++#define ATH12K_SPECTRAL_ATH12K_MAX_IB_BINS(x) ((x)->hw_params->spectral.max_fft_bins >> 1) + + #define ATH12K_SPECTRAL_SCAN_COUNT_MAX 4095 + + /* Max channel computed by sum of 2g and 5g band channels */ + #define ATH12K_SPECTRAL_TOTAL_CHANNEL 41 + #define ATH12K_SPECTRAL_SAMPLES_PER_CHANNEL 70 +-#define ATH12K_SPECTRAL_PER_SAMPLE_SIZE (sizeof(struct fft_sample_ath12k) + \ +- ATH12K_SPECTRAL_ATH12K_MAX_IB_BINS) ++#define ATH12K_SPECTRAL_PER_SAMPLE_SIZE(x) (sizeof(struct fft_sample_ath12k) + \ ++ ATH12K_SPECTRAL_ATH12K_MAX_IB_BINS(x)) + #define ATH12K_SPECTRAL_TOTAL_SAMPLE (ATH12K_SPECTRAL_TOTAL_CHANNEL * \ + ATH12K_SPECTRAL_SAMPLES_PER_CHANNEL) +-#define ATH12K_SPECTRAL_SUB_BUFF_SIZE ATH12K_SPECTRAL_PER_SAMPLE_SIZE ++#define ATH12K_SPECTRAL_SUB_BUFF_SIZE(x) ATH12K_SPECTRAL_PER_SAMPLE_SIZE(x) + #define ATH12K_SPECTRAL_NUM_SUB_BUF ATH12K_SPECTRAL_TOTAL_SAMPLE + + #define ATH12K_SPECTRAL_20MHZ 20 + #define ATH12K_SPECTRAL_40MHZ 40 + #define ATH12K_SPECTRAL_80MHZ 80 ++#define ATH12K_SPECTRAL_160MHZ 160 ++#define ATH12K_SPECTRAL_320MHZ 320 + + #define ATH12K_SPECTRAL_SIGNATURE 0xFA + +@@ -149,7 +150,7 @@ static int remove_buf_file_handler(struc + return 0; + } + +-static const struct rchan_callbacks rfs_scan_cb = { ++static struct rchan_callbacks rfs_scan_cb = { + .create_buf_file = create_buf_file_handler, + .remove_buf_file = remove_buf_file_handler, + }; +@@ -186,6 +187,8 @@ static int ath12k_spectral_scan_trigger( + if (ar->spectral.mode == ATH12K_SPECTRAL_DISABLED) + return 0; + ++ ar->spectral.is_primary = true; ++ + ret = ath12k_wmi_vdev_spectral_enable(ar, arvif->vdev_id, + ATH12K_WMI_SPECTRAL_TRIGGER_CMD_CLEAR, + ATH12K_WMI_SPECTRAL_ENABLE_CMD_ENABLE); +@@ -238,7 +241,7 @@ static int ath12k_spectral_scan_config(s + + param.vdev_id = arvif->vdev_id; + param.scan_count = count; +- param.scan_fft_size = ar->spectral.fft_size; ++ param.scan_fft_size = ATH12K_WMI_SPECTRAL_FFT_SIZE_DEFAULT; + param.scan_period = ATH12K_WMI_SPECTRAL_PERIOD_DEFAULT; + param.scan_priority = ATH12K_WMI_SPECTRAL_PRIORITY_DEFAULT; + param.scan_gc_ena = ATH12K_WMI_SPECTRAL_GC_ENA_DEFAULT; +@@ -586,11 +589,16 @@ int ath12k_spectral_process_fft(struct a + int tlv_len, bin_len, num_bins; + u16 length, freq; + u8 chan_width_mhz; +- int ret; ++ int ret, i; ++ u32 check_length; ++ bool fragment_sample = false; ++ struct wmi_spectral_capabilities_event spectral_cap; ++ u32 supported_flags; ++ spectral_cap = ar->spectral.spectral_cap; + + lockdep_assert_held(&ar->spectral.lock); + +- if (!ab->hw_params->spectral_fft_sz) { ++ if (!ab->hw_params->spectral.fft_sz) { + ath12k_warn(ab, "invalid bin size type for hw rev %d\n", + ab->hw_rev); + return -EINVAL; +@@ -600,7 +608,7 @@ int ath12k_spectral_process_fft(struct a + tlv_len = FIELD_GET(SPECTRAL_TLV_HDR_LEN, __le32_to_cpu(tlv->header)); + /* convert Dword into bytes */ + tlv_len *= ATH12K_SPECTRAL_DWORD_SIZE; +- bin_len = tlv_len - (sizeof(*fft_report) - sizeof(*tlv)); ++ bin_len = tlv_len - ab->hw_params->spectral.fft_hdr_len; + + if (data_len < (bin_len + sizeof(*fft_report))) { + ath12k_warn(ab, "mismatch in expected bin len %d and data len %d\n", +@@ -613,25 +621,121 @@ int ath12k_spectral_process_fft(struct a + num_bins >>= 1; + + if (num_bins < ATH12K_SPECTRAL_ATH12K_MIN_IB_BINS || +- num_bins > ATH12K_SPECTRAL_ATH12K_MAX_IB_BINS || ++ num_bins > ATH12K_SPECTRAL_ATH12K_MAX_IB_BINS(ab) || + !is_power_of_2(num_bins)) { + ath12k_warn(ab, "Invalid num of bins %d\n", num_bins); + return -EINVAL; + } + ++ check_length = sizeof(*fft_report); ++ ret = ath12k_dbring_validate_buffer(ar, data, check_length); ++ if (ret) { ++ ath12k_warn(ar->ab, "found magic value in fft data, dropping\n"); ++ return ret; ++ } ++ + ret = ath12k_spectral_pull_search(ar, data, &search); + if (ret) { + ath12k_warn(ab, "failed to pull search report %d\n", ret); + return ret; + } + +- chan_width_mhz = summary->meta.ch_width; ++ chan_width_mhz = ar->spectral.ch_width; + + switch (chan_width_mhz) { +- case ATH12K_SPECTRAL_20MHZ: +- case ATH12K_SPECTRAL_40MHZ: +- case ATH12K_SPECTRAL_80MHZ: +- fft_sample->chan_width_mhz = chan_width_mhz; ++ case WMI_PEER_CHWIDTH_20MHZ: ++ for (i = 0; i < spectral_cap.num_fft_size_caps_entry; i++) { ++ if (spectral_cap.fft_size_caps->sscan_bw == chan_width_mhz) { ++ supported_flags = spectral_cap.fft_size_caps->supported_flags; ++ supported_flags >>= 6; ++ if (!(supported_flags & 1)) { ++ ath12k_warn(ab, "Spectral fft size %d is not supported", ar->spectral.fft_size); ++ return -EINVAL; ++ } ++ break; ++ } ++ spectral_cap.fft_size_caps++; ++ } ++ fft_sample->chan_width_mhz = ATH12K_SPECTRAL_20MHZ; ++ summary->meta.ch_width = ATH12K_SPECTRAL_20MHZ; ++ break; ++ case WMI_PEER_CHWIDTH_40MHZ: ++ for (i = 0; i < spectral_cap.num_fft_size_caps_entry; i++) { ++ if (spectral_cap.fft_size_caps->sscan_bw == chan_width_mhz) { ++ supported_flags = spectral_cap.fft_size_caps->supported_flags; ++ supported_flags >>= 7; ++ if (!(supported_flags & 1)) { ++ ath12k_warn(ab, "Spectral fft size %d is not supported", ar->spectral.fft_size); ++ return -EINVAL; ++ } else { ++ num_bins <<= 1; ++ ar->spectral.fft_size = 8; ++ } ++ break; ++ } ++ spectral_cap.fft_size_caps++; ++ } ++ fft_sample->chan_width_mhz = ATH12K_SPECTRAL_40MHZ; ++ summary->meta.ch_width = ATH12K_SPECTRAL_40MHZ; ++ break; ++ case WMI_PEER_CHWIDTH_80MHZ: ++ for (i = 0; i < spectral_cap.num_fft_size_caps_entry; i++) { ++ if (spectral_cap.fft_size_caps->sscan_bw == chan_width_mhz) { ++ supported_flags = spectral_cap.fft_size_caps->supported_flags; ++ supported_flags >>= 8; ++ if (!(supported_flags & 1)) { ++ ath12k_warn(ab, "Spectral fft size %d is not supported", ar->spectral.fft_size); ++ return -EINVAL; ++ } else { ++ num_bins <<= 2; ++ ar->spectral.fft_size = 9; ++ } ++ break; ++ } ++ spectral_cap.fft_size_caps++; ++ } ++ fft_sample->chan_width_mhz = ATH12K_SPECTRAL_80MHZ; ++ summary->meta.ch_width = ATH12K_SPECTRAL_80MHZ; ++ break; ++ case WMI_PEER_CHWIDTH_160MHZ: ++ for (i = 0; i < spectral_cap.num_fft_size_caps_entry; i++) { ++ if (spectral_cap.fft_size_caps->sscan_bw == chan_width_mhz) { ++ supported_flags = spectral_cap.fft_size_caps->supported_flags; ++ supported_flags >>= 8; ++ if (!(supported_flags & 1)) { ++ ath12k_warn(ab, "Spectral fft size %d is not supported", ar->spectral.fft_size); ++ return -EINVAL; ++ } else { ++ ar->spectral.fft_size = 9; ++ num_bins <<= 2; ++ } ++ break; ++ } ++ spectral_cap.fft_size_caps++; ++ } ++ fft_sample->chan_width_mhz = ATH12K_SPECTRAL_160MHZ; ++ summary->meta.ch_width = ATH12K_SPECTRAL_160MHZ; ++ if (ab->hw_params->spectral.fragment_160mhz) ++ fragment_sample = true; ++ break; ++ case WMI_PEER_CHWIDTH_MAX: ++ for (i = 0; i < spectral_cap.num_fft_size_caps_entry; i++) { ++ if (spectral_cap.fft_size_caps->sscan_bw == chan_width_mhz) { ++ supported_flags = spectral_cap.fft_size_caps->supported_flags; ++ supported_flags >>= 8; ++ if (!(supported_flags & 1)) { ++ ath12k_warn(ab, "Spectral fft size %d is not supported", ar->spectral.fft_size); ++ return -EINVAL; ++ } else { ++ ar->spectral.fft_size = 9; ++ num_bins <<= 2; ++ } ++ break; ++ } ++ spectral_cap.fft_size_caps++; ++ } ++ fft_sample->chan_width_mhz = ATH12K_SPECTRAL_320MHZ; ++ summary->meta.ch_width = ATH12K_SPECTRAL_320MHZ; + break; + default: + ath12k_warn(ab, "invalid channel width %d\n", chan_width_mhz); +@@ -657,8 +761,15 @@ int ath12k_spectral_process_fft(struct a + freq = summary->meta.freq2; + fft_sample->freq2 = __cpu_to_be16(freq); + ++ /* If freq2 is available then the spectral scan results are fragmented as primary and secondary */ ++ if (fragment_sample && freq) { ++ fft_sample->is_primary = ar->spectral.is_primary; ++ /* We have to toggle the is_primary to handle the next report */ ++ ar->spectral.is_primary = !ar->spectral.is_primary; ++ } ++ + ath12k_spectral_parse_fft(fft_sample->data, fft_report->bins, num_bins, +- ab->hw_params->spectral_fft_sz); ++ ar->spectral.fft_size); + + fft_sample->max_exp = ath12k_spectral_get_max_exp(fft_sample->max_index, + search.peak_mag, +@@ -694,7 +805,7 @@ static int ath12k_spectral_process_data( + goto unlock; + } + +- sample_sz = sizeof(*fft_sample) + ATH12K_SPECTRAL_ATH12K_MAX_IB_BINS; ++ sample_sz = sizeof(*fft_sample) + ATH12K_SPECTRAL_ATH12K_MAX_IB_BINS(ab); + fft_sample = kmalloc(sample_sz, GFP_ATOMIC); + if (!fft_sample) { + ret = -ENOBUFS; +@@ -716,8 +827,10 @@ static int ath12k_spectral_process_data( + sign = FIELD_GET(SPECTRAL_TLV_HDR_SIGN, + __le32_to_cpu(tlv->header)); + if (sign != ATH12K_SPECTRAL_SIGNATURE) { ++ /*TODO: Need to add this warn print back after resolving cpu cache issue ++ * + ath12k_warn(ab, "Invalid sign 0x%x at bytes %d\n", +- sign, i); ++ sign, i);*/ + ret = -EINVAL; + goto err; + } +@@ -742,7 +855,8 @@ static int ath12k_spectral_process_data( + * is 4 DWORD size (16 bytes). + * Need to remove this workaround once HW bug fixed + */ +- tlv_len = sizeof(*summary) - sizeof(*tlv); ++ tlv_len = sizeof(*summary) - sizeof(*tlv) + ++ ab->hw_params->spectral.summary_pad_sz; + + if (tlv_len < (sizeof(*summary) - sizeof(*tlv))) { + ath12k_warn(ab, "failed to parse spectral summary at bytes %d tlv_len:%d\n", +@@ -751,6 +865,12 @@ static int ath12k_spectral_process_data( + goto err; + } + ++ ret = ath12k_dbring_validate_buffer(ar, data, tlv_len); ++ if (ret) { ++ ath12k_warn(ar->ab, "found magic value in spectral summary, dropping\n"); ++ goto err; ++ } ++ + summary = (struct spectral_summary_fft_report *)tlv; + ath12k_spectral_pull_summary(ar, ¶m->meta, + summary, &summ_rpt); +@@ -776,7 +896,6 @@ static int ath12k_spectral_process_data( + quit = true; + break; + } +- + i += sizeof(*tlv) + tlv_len; + } + +@@ -854,7 +973,7 @@ static inline void ath12k_spectral_debug + } + } + +-int ath12k_spectral_vif_stop(struct ath12k_vif *arvif) ++int ath12k_spectral_vif_stop(struct ath12k_link_vif *arvif) + { + if (!arvif->spectral_enabled) + return 0; +@@ -881,10 +1000,18 @@ void ath12k_spectral_deinit(struct ath12 + ar = ab->pdevs[i].ar; + sp = &ar->spectral; + +- if (!sp->enabled) ++ mutex_lock(&ar->conf_mutex); ++ ++ if (sp->spectral_cap.fft_size_caps) { ++ kfree(sp->spectral_cap.fft_size_caps); ++ sp->spectral_cap.fft_size_caps = NULL; ++ } ++ ++ if (!sp->enabled) { ++ mutex_unlock(&ar->conf_mutex); + continue; ++ } + +- mutex_lock(&ar->conf_mutex); + ath12k_spectral_scan_config(ar, ATH12K_SPECTRAL_DISABLED); + mutex_unlock(&ar->conf_mutex); + +@@ -903,7 +1030,7 @@ static inline int ath12k_spectral_debug_ + + ar->spectral.rfs_scan = relay_open("spectral_scan", + ar->debug.debugfs_pdev, +- ATH12K_SPECTRAL_SUB_BUFF_SIZE, ++ ATH12K_SPECTRAL_SUB_BUFF_SIZE(ar->ab), + ATH12K_SPECTRAL_NUM_SUB_BUF, + &rfs_scan_cb, NULL); + if (!ar->spectral.rfs_scan) { +@@ -964,7 +1091,7 @@ int ath12k_spectral_init(struct ath12k_b + ab->wmi_ab.svc_map)) + return 0; + +- if (!ab->hw_params->spectral_fft_sz) ++ if (!ab->hw_params->spectral.fft_sz) + return 0; + + for (i = 0; i < ab->num_radios; i++) { +--- a/drivers/net/wireless/ath/ath12k/spectral.h ++++ b/drivers/net/wireless/ath/ath12k/spectral.h +@@ -36,6 +36,9 @@ struct ath12k_spectral { + u16 count; + u8 fft_size; + bool enabled; ++ bool is_primary; ++ u32 ch_width; ++ struct wmi_spectral_capabilities_event spectral_cap; + }; + + #ifdef CPTCFG_ATH12K_SPECTRAL +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -79,6 +79,25 @@ struct wmi_tlv_dma_buf_release_parse { + bool meta_data_done; + }; + ++struct wmi_pdev_sscan_fw_param_parse { ++ struct ath12k_wmi_pdev_sscan_fw_cmd_fixed_param fixed; ++ struct ath12k_wmi_pdev_sscan_fft_bin_index *bin; ++ struct ath12k_wmi_pdev_sscan_chan_info ch_info; ++ struct ath12k_wmi_pdev_sscan_per_detector_info *det_info; ++ bool bin_entry_done; ++ bool det_info_entry_done; ++ ++}; ++ ++struct wmi_spectral_capabilities_parse { ++ struct ath12k_wmi_spectral_scan_bw_capabilities *sscan_bw_caps; ++ struct ath12k_wmi_spectral_fft_size_capabilities *fft_size_caps; ++ bool sscan_bw_caps_entry_done; ++ bool fft_size_caps_entry_done; ++ u32 num_bw_caps_entry; ++ u32 num_fft_size_caps_entry; ++}; ++ + static const struct wmi_tlv_policy wmi_tlv_policies[] = { + [WMI_TAG_ARRAY_BYTE] = { .min_len = 0 }, + [WMI_TAG_ARRAY_UINT32] = { .min_len = 0 }, +@@ -320,6 +339,7 @@ ath12k_wmi_tlv_iter(struct ath12k_base * + u16 tlv_tag, tlv_len; + int ret; + ++ + while (len > 0) { + if (len < sizeof(*tlv)) { + ath12k_err(ab, "wmi tlv parse failure at byte %zd (%zu bytes left, %zu expected)\n", +@@ -4682,6 +4702,7 @@ static void ath12k_wmi_pdev_dma_ring_buf + struct ath12k_dbring_buf_release_event param; + int ret; + ++ + ret = ath12k_wmi_tlv_iter(ab, skb->data, skb->len, + ath12k_wmi_tlv_dma_buf_parse, + &parse); +@@ -9928,6 +9949,227 @@ exit: + } + + ++static int ath12k_wmi_pdev_sscan_fft_bin_index_parse(struct ath12k_base *soc, ++ u16 tag, u16 len, ++ const void *ptr, void *data) ++{ ++ if (tag != WMI_TAG_PDEV_SSCAN_FFT_BIN_INDEX) ++ return -EPROTO; ++ return 0; ++} ++ ++static int ath12k_wmi_pdev_sscan_per_detector_info_parse(struct ath12k_base *soc, ++ u16 tag, u16 len, ++ const void *ptr, void *data) ++{ ++ if (tag != WMI_TAG_PDEV_SSCAN_PER_DETECTOR_INFO) ++ return -EPROTO; ++ ++ return 0; ++} ++ ++static int ath12k_wmi_tlv_sscan_fw_parse(struct ath12k_base *ab, ++ u16 tag, u16 len, ++ const void *ptr, void *data) ++{ ++ struct wmi_pdev_sscan_fw_param_parse *parse = data; ++ int ret; ++ ++ switch (tag) { ++ ++ case WMI_TAG_PDEV_SSCAN_FW_CMD_FIXED_PARAM: ++ memcpy(&parse->fixed, ptr, ++ sizeof(struct ath12k_wmi_pdev_sscan_fw_cmd_fixed_param)); ++ parse->fixed.pdev_id = DP_HW2SW_MACID(parse->fixed.pdev_id); ++ break; ++ case WMI_TAG_ARRAY_STRUCT: ++ if (!parse->bin_entry_done) { ++ parse->bin = (struct ath12k_wmi_pdev_sscan_fft_bin_index *)ptr; ++ ++ ret = ath12k_wmi_tlv_iter(ab, ptr, len, ++ ath12k_wmi_pdev_sscan_fft_bin_index_parse, ++ parse); ++ ++ if (ret) { ++ ath12k_warn(ab, "failed to parse fft bin index %d\n", ++ ret); ++ return ret; ++ } ++ ++ parse->bin_entry_done = true; ++ } else if (!parse->det_info_entry_done) { ++ parse->det_info = (struct ath12k_wmi_pdev_sscan_per_detector_info *)ptr; ++ ++ ret = ath12k_wmi_tlv_iter(ab, ptr, len, ++ ath12k_wmi_pdev_sscan_per_detector_info_parse, ++ parse); ++ ++ if (ret) { ++ ath12k_warn(ab, "failed to parse detector info %d\n", ++ ret); ++ return ret; ++ } ++ parse->det_info_entry_done = true; ++ } ++ break; ++ case WMI_TAG_PDEV_SSCAN_CHAN_INFO: ++ memcpy(&parse->ch_info, ptr, ++ sizeof(struct ath12k_wmi_pdev_sscan_chan_info)); ++ parse->bin_entry_done = true; ++ break; ++ default: ++ break; ++ } ++ return 0; ++ ++} ++ ++static void ++ath12k_wmi_pdev_sscan_fw_param_event(struct ath12k_base *ab, ++ struct sk_buff *skb) ++{ ++ struct ath12k *ar; ++ struct wmi_pdev_sscan_fw_param_parse parse = { }; ++ struct wmi_pdev_sscan_fw_param_event param; ++ int ret; ++ u8 pdev_idx; ++ ++ ret = ath12k_wmi_tlv_iter(ab, skb->data, skb->len, ++ ath12k_wmi_tlv_sscan_fw_parse, ++ &parse); ++ ++ if (ret) { ++ ath12k_warn(ab, "failed to parse padev sscan fw tlv %d\n", ret); ++ return; ++ } ++ ++ param.fixed = parse.fixed; ++ param.bin = parse.bin; ++ param.ch_info = parse.ch_info; ++ param.det_info = parse.det_info; ++ ++ pdev_idx = param.fixed.pdev_id; ++ ar = ab->pdevs[pdev_idx].ar; ++ ar->spectral.ch_width = param.ch_info.operating_bw; ++} ++ ++static int ++ath12k_wmi_spectral_scan_bw_cap_parse(struct ath12k_base *soc, ++ u16 tag, u16 len, ++ const void *ptr, void *data) ++{ ++ struct wmi_spectral_capabilities_parse *parse = data; ++ if (tag != WMI_TAG_SPECTRAL_SCAN_BW_CAPABILITIES) ++ return -EPROTO; ++ parse->num_bw_caps_entry++; ++ return 0; ++} ++ ++static int ++ath12k_wmi_spectral_fft_size_cap_parse(struct ath12k_base *soc, ++ u16 tag, u16 len, ++ const void *ptr, void *data) ++{ ++ struct wmi_spectral_capabilities_parse *parse = data; ++ if (tag != WMI_TAG_SPECTRAL_FFT_SIZE_CAPABILITIES) ++ return -EPROTO; ++ ++ parse->num_fft_size_caps_entry++; ++ return 0; ++} ++ ++static int ++ath12k_wmi_tlv_spectral_cap_parse(struct ath12k_base *ab, ++ u16 tag, u16 len, ++ const void *ptr, void *data) ++{ ++ struct wmi_spectral_capabilities_parse *parse = data; ++ int ret; ++ ++ if (tag == WMI_TAG_ARRAY_STRUCT) { ++ if (!parse->sscan_bw_caps_entry_done) { ++ parse->num_bw_caps_entry = 0; ++ parse->sscan_bw_caps = (struct ath12k_wmi_spectral_scan_bw_capabilities *)ptr; ++ ret = ath12k_wmi_tlv_iter(ab, ptr, len, ++ ath12k_wmi_spectral_scan_bw_cap_parse, ++ parse); ++ if (ret) { ++ ath12k_warn(ab, "failed to parse scan bw cap %d\n", ++ ret); ++ return ret; ++ } ++ parse->sscan_bw_caps_entry_done = true; ++ } else if (!parse->fft_size_caps_entry_done) { ++ parse->num_fft_size_caps_entry = 0; ++ parse->fft_size_caps = (struct ath12k_wmi_spectral_fft_size_capabilities *)ptr; ++ ret = ath12k_wmi_tlv_iter(ab, ptr, len, ++ ath12k_wmi_spectral_fft_size_cap_parse, ++ parse); ++ if (ret) { ++ ath12k_warn(ab, "failed to parse fft size cap %d\n", ++ ret); ++ return ret; ++ } ++ parse->fft_size_caps_entry_done = true; ++ } ++ } ++ return 0; ++} ++ ++static void ++ath12k_wmi_spectral_capabilities_event(struct ath12k_base *ab, ++ struct sk_buff *skb) ++{ ++ struct wmi_spectral_capabilities_parse parse = { }; ++ struct wmi_spectral_capabilities_event param; ++ struct ath12k *ar = NULL; ++ int ret, size; ++ u8 pdev_id, i; ++ struct ath12k_pdev *pdev; ++ ++ ret = ath12k_wmi_tlv_iter(ab, skb->data, skb->len, ++ ath12k_wmi_tlv_spectral_cap_parse, ++ &parse); ++ if (ret) { ++ ath12k_warn(ab, "failed to parse spectral capabilities tlv %d\n", ret); ++ return; ++ } ++ ++ param.sscan_bw_caps = parse.sscan_bw_caps; ++ param.fft_size_caps = parse.fft_size_caps; ++ param.num_bw_caps_entry = parse.num_bw_caps_entry; ++ param.num_fft_size_caps_entry = parse.num_fft_size_caps_entry; ++ ++ pdev_id = param.sscan_bw_caps->pdev_id; ++ ++ for (i = 0; i < ab->num_radios; i++) { ++ pdev = &ab->pdevs[i]; ++ if (pdev && pdev->pdev_id == pdev_id) { ++ ar = pdev->ar; ++ break; ++ } ++ } ++ ++ if (!ar) { ++ ath12k_dbg(ab, ATH12K_DBG_WMI, ++ "ar is NULL for pdev_id %d use default spectral fft size 7", ++ pdev_id); ++ return; ++ } ++ size = sizeof(struct ath12k_wmi_spectral_fft_size_capabilities)* ++ param.num_fft_size_caps_entry; ++ ++ ar->spectral.spectral_cap.fft_size_caps = kzalloc(size, GFP_ATOMIC); ++ if (!ar->spectral.spectral_cap.fft_size_caps) { ++ ath12k_warn(ab, "Failed to allocate memory"); ++ return; ++ } ++ memcpy(ar->spectral.spectral_cap.fft_size_caps, ++ param.fft_size_caps, size); ++ ar->spectral.spectral_cap.num_bw_caps_entry = param.num_bw_caps_entry; ++ ar->spectral.spectral_cap.num_fft_size_caps_entry = param.num_fft_size_caps_entry; ++} ++ + static void ath12k_wmi_tlv_op_rx(struct ath12k_base *ab, struct sk_buff *skb) + { + struct wmi_cmd_hdr *cmd_hdr; +@@ -10023,6 +10265,12 @@ static void ath12k_wmi_tlv_op_rx(struct + case WMI_TWT_ADD_DIALOG_EVENTID: + ath12k_wmi_twt_add_dialog_event(ab, skb); + break; ++ case WMI_PDEV_SSCAN_FW_PARAM_EVENTID: ++ ath12k_wmi_pdev_sscan_fw_param_event(ab, skb); ++ break; ++ case WMI_SPECTRAL_CAPABILITIES_EVENTID: ++ ath12k_wmi_spectral_capabilities_event(ab, skb); ++ break; + /* add Unsupported events here */ + case WMI_TBTTOFFSET_EXT_UPDATE_EVENTID: + case WMI_PEER_OPER_MODE_CHANGE_EVENTID: +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -639,6 +639,9 @@ enum wmi_tlv_event_id { + WMI_READY_EVENTID, + WMI_SERVICE_AVAILABLE_EVENTID, + WMI_SCAN_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_SCAN), ++ WMI_PDEV_SSCAN_FW_PARAM_EVENTID, ++ WMI_SSCAN_EVT_MESSAGE_EVENTID, ++ WMI_SPECTRAL_CAPABILITIES_EVENTID, + WMI_PDEV_TPC_CONFIG_EVENTID = WMI_TLV_CMD(WMI_GRP_PDEV), + WMI_CHAN_INFO_EVENTID, + WMI_PHYERR_EVENTID, +@@ -1924,6 +1927,8 @@ enum wmi_tlv_tag { + WMI_TAG_MAC_PHY_CAPABILITIES_EXT = 0x36F, + WMI_TAG_PDEV_SRG_BSS_COLOR_BITMAP_CMD = 0x37b, + WMI_TAG_PDEV_SRG_PARTIAL_BSSID_BITMAP_CMD, ++ WMI_TAG_PDEV_SSCAN_FW_CMD_FIXED_PARAM = 0x37f, ++ WMI_TAG_PDEV_SSCAN_FFT_BIN_INDEX, + WMI_TAG_PDEV_SRG_OBSS_COLOR_ENABLE_BITMAP_CMD = 0x381, + WMI_TAG_PDEV_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD, + WMI_TAG_PDEV_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMD, +@@ -1947,6 +1952,10 @@ enum wmi_tlv_tag { + WMI_TAG_MLO_VDEV_START_PARAMS = 0x3D6, + WMI_TAG_MLO_VDEV_CREATE_PARAMS = 0x3D7, + WMI_TAG_PDEV_PKTLOG_DECODE_INFO = 0x414, ++ WMI_TAG_SPECTRAL_SCAN_BW_CAPABILITIES, ++ WMI_TAG_SPECTRAL_FFT_SIZE_CAPABILITIES, ++ WMI_TAG_PDEV_SSCAN_CHAN_INFO = 0X417, ++ WMI_TAG_PDEV_SSCAN_PER_DETECTOR_INFO, + WMI_TAG_TPC_STATS_GET_CMD = 0x38B, + WMI_TAG_TPC_STATS_EVENT_FIXED_PARAM, + WMI_TAG_TPC_STATS_CONFIG_EVENT, +@@ -2260,6 +2269,7 @@ enum wmi_peer_chwidth { + WMI_PEER_CHWIDTH_80MHZ = 2, + WMI_PEER_CHWIDTH_160MHZ = 3, + WMI_PEER_CHWIDTH_320MHZ = 4, ++ WMI_PEER_CHWIDTH_MAX = 9, + }; + + enum wmi_beacon_gen_mode { +@@ -2270,6 +2280,7 @@ enum wmi_beacon_gen_mode { + enum wmi_direct_buffer_module { + WMI_DIRECT_BUF_SPECTRAL = 0, + WMI_DIRECT_BUF_CFR = 1, ++ WMI_CONFIG_MODULE_CV_UPLOAD = 2, + + /* keep it last */ + WMI_DIRECT_BUF_MAX +@@ -5828,6 +5839,78 @@ struct wmi_dma_buf_release_entry { + u32 paddr_hi; + } __packed; + ++struct ath12k_wmi_pdev_sscan_fw_cmd_fixed_param { ++ u32 pdev_id; ++ u32 spectral_scan_mode; ++} __packed; ++ ++ ++struct ath12k_wmi_pdev_sscan_fft_bin_index { ++ u32 pri80_bins; ++ u32 sec80_bins; ++ u32 mid_5mhz_bins; ++} __packed; ++ ++struct ath12k_wmi_pdev_sscan_chan_info { ++ u32 operating_pri20_freq; ++ u32 operating_cfreq1; ++ u32 operating_cfreq2; ++ u32 operating_bw; ++ u32 operating_puncture_20mhz_bitmap; ++ u32 sscan_cfreq1; ++ u32 sscan_cfreq2; ++ u32 sscan_bw; ++ u32 sscan_puncture_20mhz_bitmap; ++} __packed; ++ ++struct ath12k_wmi_pdev_sscan_per_detector_info { ++ __le32 tlv_header; ++ u32 detector_id; ++ u32 start_freq; ++ u32 end_freq; ++} __packed; ++ ++struct ath12k_wmi_spectral_scan_bw_capabilities { ++ __le32 tlv_header; ++ u32 pdev_id; ++ u32 sscan_mode; ++ u32 operating_bw; ++ union { ++ struct { ++ u32 supports_sscan_bw_20:1, ++ supports_sscan_bw_40:1, ++ supports_sscan_bw_80:1, ++ supports_sscan_bw_160:1, ++ supports_sscan_bw_80p80:1, ++ supports_sscan_bw_320:1, ++ reserved:21; ++ }; ++ u32 supported_flags; ++ }; ++} __packed; ++ ++struct ath12k_wmi_spectral_fft_size_capabilities { ++ __le32 tlv_header; ++ u32 pdev_id; ++ u32 sscan_bw; ++ union { ++ struct { ++ u32 supports_fft_size_1:1, ++ supports_fft_size_2:1, ++ supports_fft_size_3:1, ++ supports_fft_size_4:1, ++ supports_fft_size_5:1, ++ supports_fft_size_6:1, ++ supports_fft_size_7:1, ++ supports_fft_size_8:1, ++ supports_fft_size_9:1, ++ supports_fft_size_10:1, ++ supports_fft_size_11:1, ++ reserved:21; ++ }; ++ u32 supported_flags; ++ }; ++} __packed; + #define WMI_SPECTRAL_META_INFO1_FREQ1 GENMASK(15, 0) + #define WMI_SPECTRAL_META_INFO1_FREQ2 GENMASK(31, 16) + +--- a/drivers/net/wireless/ath/spectral_common.h ++++ b/drivers/net/wireless/ath/spectral_common.h +@@ -132,9 +132,10 @@ struct fft_sample_ath11k { + + struct fft_sample_ath12k { + struct fft_sample_tlv tlv; +- u8 chan_width_mhz; ++ u16 chan_width_mhz; + s8 max_index; + u8 max_exp; ++ bool is_primary; + __be16 freq1; + __be16 freq2; + __be16 max_magnitude; diff --git a/feeds/ipq95xx/mac80211/patches/qca/703-ath12k-Avoid-multiple-beacon-countdown-update.patch b/feeds/ipq95xx/mac80211/patches/qca/703-ath12k-Avoid-multiple-beacon-countdown-update.patch new file mode 100644 index 000000000..c17d3d42d --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/703-ath12k-Avoid-multiple-beacon-countdown-update.patch @@ -0,0 +1,34 @@ +From d442478f26163219b24c3e0521e1ffa6075bcb78 Mon Sep 17 00:00:00 2001 +From: Sivashankari Madhavan +Date: Tue, 13 Dec 2022 11:45:05 +0530 +Subject: [PATCH] ath12k: Avoid multiple beacon countdown update + +During the Bss color change, unwantedly updating the beacon countdown two +times for every separate beacon template in 6G. Due to this, some of the time it +reaches the 0 countdown and throws the WARNON. + +[ 8393.129435] lr : ieee80211_beacon_update_cntdwn+0x5c/0x7c [mac80211] + +Fix it by avoiding the multiple beacon coundown update. + +Signed-off-by: Sivashankari Madhavan +--- + drivers/net/wireless/ath/ath12k/mac.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index 9dc0a3c..19276bc 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -1601,7 +1601,7 @@ void ath12k_mac_bcn_tx_event(struct ath12k_link_vif *arvif) + + arvif->bcca_zero_sent = false; + +- if (link_conf->color_change_active) ++ if (link_conf->color_change_active && !vif->bss_conf.ema_ap) + ieee80211_beacon_update_cntdwn(vif, 0); + ieee80211_queue_work(ar->ah->hw, &arvif->update_bcn_template_work); + } +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/703-ath12k-Clear-qdesc-array-on-peer-tid-update.patch b/feeds/ipq95xx/mac80211/patches/qca/703-ath12k-Clear-qdesc-array-on-peer-tid-update.patch new file mode 100644 index 000000000..064c4523d --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/703-ath12k-Clear-qdesc-array-on-peer-tid-update.patch @@ -0,0 +1,78 @@ +From b9bf7b1419280c5cb3cbe4b3105eb2d4ff07134d Mon Sep 17 00:00:00 2001 +From: Balamurugan S +Date: Thu, 15 Dec 2022 18:35:55 +0530 +Subject: [PATCH] ath12k: Clear qdesc array on peer tid update + +Setting CLEAR_DESC_ARRAY field of WCSS_UMAC_REO_R0_QDESC_ADDR_READ +and resetting back, to erase stale entries in reo storage during peer +tid update. + +Signed-off-by: Balamurugan S +--- + drivers/net/wireless/ath/ath12k/dp_rx.c | 2 ++ + drivers/net/wireless/ath/ath12k/hal.h | 2 ++ + drivers/net/wireless/ath/ath12k/hal_rx.c | 20 ++++++++++++++++++++ + 3 files changed, 24 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c +index a4eea49..77cfb5f 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -827,6 +827,8 @@ static void ath12k_peer_rx_tid_qref_setup(struct ath12k_base *ab, u16 peer_id, u + qref->info1 = u32_encode_bits(upper_32_bits(paddr), + BUFFER_ADDR_INFO1_ADDR) | + u32_encode_bits(tid, DP_REO_QREF_NUM); ++ ++ ath12k_hal_reo_shared_qaddr_cache_clear(ab); + } + + static void ath12k_peer_rx_tid_qref_reset(struct ath12k_base *ab, u16 peer_id, u16 tid) +diff --git a/drivers/net/wireless/ath/ath12k/hal.h b/drivers/net/wireless/ath/ath12k/hal.h +index 7cfef2e..ab32604 100644 +--- a/drivers/net/wireless/ath/ath12k/hal.h ++++ b/drivers/net/wireless/ath/ath12k/hal.h +@@ -341,6 +341,7 @@ struct ath12k_base; + #define HAL_REO1_SW_COOKIE_CFG_ENABLE BIT(19) + #define HAL_REO1_SW_COOKIE_CFG_GLOBAL_ENABLE BIT(20) + #define HAL_REO_QDESC_ADDR_READ_LUT_ENABLE BIT(7) ++#define HAL_REO_QDESC_ADDR_READ_CLEAR_QDESC_ARRAY BIT(6) + + /* CE ring bit field mask and shift */ + #define HAL_CE_DST_R0_DEST_CTRL_MAX_LEN GENMASK(15, 0) +@@ -1171,4 +1172,5 @@ void ath12k_hal_reo_ring_ctrl_hash_ix3_setup(struct ath12k_base *ab, + u32 ring_hash_map); + void ath12k_hal_reo_ring_ctrl_hash_ix2_setup(struct ath12k_base *ab, + u32 ring_hash_map); ++void ath12k_hal_reo_shared_qaddr_cache_clear(struct ath12k_base *ab); + #endif +diff --git a/drivers/net/wireless/ath/ath12k/hal_rx.c b/drivers/net/wireless/ath/ath12k/hal_rx.c +index 7dfcd0f..b9898e0 100644 +--- a/drivers/net/wireless/ath/ath12k/hal_rx.c ++++ b/drivers/net/wireless/ath/ath12k/hal_rx.c +@@ -914,3 +914,23 @@ void ath12k_hal_rx_reo_ent_buf_paddr_get(void *rx_desc, dma_addr_t *paddr, + + *pp_buf_addr = (void *)buf_addr_info; + } ++ ++/* ++ * Setting CLEAR_DESC_ARRAY field of WCSS_UMAC_REO_R0_QDESC_ADDR_READ ++ * and resetting back, to erase stale entries in reo storage. ++ */ ++void ath12k_hal_reo_shared_qaddr_cache_clear(struct ath12k_base *ab) ++{ ++ u32 val; ++ ++ val = ath12k_hif_read32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + ++ HAL_REO1_QDESC_ADDR_READ(ab)); ++ ++ val |= u32_encode_bits(1, HAL_REO_QDESC_ADDR_READ_CLEAR_QDESC_ARRAY); ++ ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + ++ HAL_REO1_QDESC_ADDR_READ(ab), val); ++ ++ val &= ~HAL_REO_QDESC_ADDR_READ_CLEAR_QDESC_ARRAY; ++ ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + ++ HAL_REO1_QDESC_ADDR_READ(ab), val); ++} +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/697-ath12k-Update-pending-desc-size-in-reo-cache-flush.patch b/feeds/ipq95xx/mac80211/patches/qca/703-ath12k-Update-pending-desc-size-in-reo-cache-flush.patch similarity index 64% rename from feeds/ipq95xx/mac80211/patches/qca/697-ath12k-Update-pending-desc-size-in-reo-cache-flush.patch rename to feeds/ipq95xx/mac80211/patches/qca/703-ath12k-Update-pending-desc-size-in-reo-cache-flush.patch index b1f44cf34..b02529c51 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/697-ath12k-Update-pending-desc-size-in-reo-cache-flush.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/703-ath12k-Update-pending-desc-size-in-reo-cache-flush.patch @@ -1,6 +1,6 @@ -From 42aadf67af03e1d7ccc64c876e07fb93c895f87b Mon Sep 17 00:00:00 2001 +From dc3e3547bae9181ddf2698e97b88b5ac2f3d225f Mon Sep 17 00:00:00 2001 From: Manish Dharanenthiran -Date: Tue, 29 Nov 2022 21:17:15 +0530 +Date: Wed, 14 Dec 2022 12:01:35 +0530 Subject: [PATCH] ath12k: Update pending desc size in reo cache flush During rx_tid_del, if the desc size is greater than @@ -23,14 +23,17 @@ send failure and drain cmd stats. Signed-off-by: Manish Dharanenthiran --- - drivers/net/wireless/ath/ath12k/core.h | 2 ++ - drivers/net/wireless/ath/ath12k/dp.h | 1 + - drivers/net/wireless/ath/ath12k/dp_rx.c | 20 +++++++++++++------- - 3 files changed, 16 insertions(+), 7 deletions(-) + drivers/net/wireless/ath/ath12k/core.h | 2 ++ + drivers/net/wireless/ath/ath12k/debugfs.c | 8 ++++++++ + drivers/net/wireless/ath/ath12k/dp_rx.c | 19 +++++++++---------- + drivers/net/wireless/ath/ath12k/dp_rx.h | 1 + + 4 files changed, 20 insertions(+), 10 deletions(-) +diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h +index 6d12cc5..4a9702f 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h -@@ -936,6 +936,8 @@ struct ath12k_soc_dp_stats { +@@ -981,6 +981,8 @@ struct ath12k_soc_dp_stats { u32 reo_error_drop[HAL_REO_DEST_RING_ERROR_CODE_MAX]; u32 hal_reo_error[DP_REO_DST_RING_MAX]; u32 mon_drop_desc; @@ -39,87 +42,11 @@ Signed-off-by: Manish Dharanenthiran struct ath12k_soc_dp_tx_err_stats tx_err; struct ath12k_dp_ring_bp_stats bp_stats; }; ---- a/drivers/net/wireless/ath/ath12k/dp.h -+++ b/drivers/net/wireless/ath/ath12k/dp.h -@@ -24,6 +24,7 @@ struct dp_rx_tid { - u32 *vaddr; - dma_addr_t paddr; - u32 size; -+ u32 pending_desc_size; - u32 ba_win_sz; - bool active; - ---- a/drivers/net/wireless/ath/ath12k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -700,7 +700,10 @@ static int ath12k_dp_reo_cache_flush(str - unsigned long tot_desc_sz, desc_sz; - int ret; - -- tot_desc_sz = rx_tid->size; -+ if (rx_tid->pending_desc_size) -+ tot_desc_sz = rx_tid->pending_desc_size; -+ else -+ tot_desc_sz = rx_tid->size; - desc_sz = ath12k_hal_reo_qdesc_size(0, HAL_DESC_REO_NON_QOS_TID); - - while (tot_desc_sz > desc_sz) { -@@ -712,18 +715,16 @@ static int ath12k_dp_reo_cache_flush(str - NULL); - if (ret) - { -- ath12k_warn(ab, -- "failed to send HAL_REO_CMD_FLUSH_CACHE, tid %d (%d) desc_sz(%ld)\n", -- rx_tid->tid, ret, desc_sz); -- - /* If this fails with ring full condition, then - * no need to retry below as it is expected to - * fail within short time */ -+ rx_tid->pending_desc_size = tot_desc_sz + desc_sz; - if (ret == -ENOBUFS) - goto exit; - } - } - -+ rx_tid->pending_desc_size = desc_sz; - memset(&cmd, 0, sizeof(cmd)); - cmd.addr_lo = lower_32_bits(rx_tid->paddr); - cmd.addr_hi = upper_32_bits(rx_tid->paddr); -@@ -731,9 +732,6 @@ static int ath12k_dp_reo_cache_flush(str - ret = ath12k_dp_tx_send_reo_cmd(ab, rx_tid, - HAL_REO_CMD_FLUSH_CACHE, - &cmd, ath12k_dp_reo_cmd_free); -- if (ret) -- ath12k_err(ab, "failed to send HAL_REO_CMD_FLUSH_CACHE cmd, tid %d (%d)\n", -- rx_tid->tid, ret); - - exit: - return ret; -@@ -747,6 +745,7 @@ static void ath12k_dp_rx_tid_del_func(st - struct dp_reo_cache_flush_elem *elem, *tmp; - - if (status == HAL_REO_CMD_DRAIN) { -+ ab->soc_stats.hal_reo_cmd_drain++; - goto free_desc; - } else if (status != HAL_REO_CMD_SUCCESS) { - /* Shouldn't happen! Cleanup in case of other failure? */ -@@ -779,12 +778,11 @@ static void ath12k_dp_rx_tid_del_func(st - if (ath12k_dp_reo_cache_flush(ab, &elem->data)) { - /* In failure case, just update the timestamp - * for flush cache elem and continue */ -+ ab->soc_stats.reo_cmd_cache_error++; - spin_lock_bh(&dp->reo_cmd_lock); - elem->ts = jiffies + - msecs_to_jiffies(DP_REO_DESC_FREE_TIMEOUT_MS); -- ath12k_err(ab, "Failed to send HAL_REO_CMD_FLUSH_CACHE cmd" -- "Updating timestamp (%ld) in the list\n", elem->ts); -- continue; -+ break; - } - spin_lock_bh(&dp->reo_cmd_lock); - list_del(&elem->list); +diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c +index 55924ec..f121252 100644 --- a/drivers/net/wireless/ath/ath12k/debugfs.c +++ b/drivers/net/wireless/ath/ath12k/debugfs.c -@@ -811,6 +811,14 @@ static ssize_t ath12k_debugfs_dump_soc_d +@@ -810,6 +810,14 @@ static ssize_t ath12k_debugfs_dump_soc_dp_stats(struct file *file, "\nMon drop descriptor: %u\n", soc_stats->mon_drop_desc); @@ -134,3 +61,86 @@ Signed-off-by: Manish Dharanenthiran len += ath12k_debugfs_dump_soc_ring_bp_stats(ab, buf + len, size - len); if (len > size) +diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c +index 31462e7..0a816ff 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -699,7 +699,10 @@ static int ath12k_dp_reo_cache_flush(struct ath12k_base *ab, + unsigned long tot_desc_sz, desc_sz; + int ret; + +- tot_desc_sz = rx_tid->size; ++ if (rx_tid->pending_desc_size) ++ tot_desc_sz = rx_tid->pending_desc_size; ++ else ++ tot_desc_sz = rx_tid->size; + desc_sz = ath12k_hal_reo_qdesc_size(0, HAL_DESC_REO_NON_QOS_TID); + + while (tot_desc_sz > desc_sz) { +@@ -711,9 +714,7 @@ static int ath12k_dp_reo_cache_flush(struct ath12k_base *ab, + NULL); + if (ret) + { +- ath12k_warn(ab, +- "failed to send HAL_REO_CMD_FLUSH_CACHE, tid %d (%d) desc_sz(%ld)\n", +- rx_tid->tid, ret, desc_sz); ++ rx_tid->pending_desc_size = tot_desc_sz + desc_sz; + /* If this fails with ring full condition, then + * no need to retry below as it is expected to + * fail within short time */ +@@ -722,6 +723,7 @@ static int ath12k_dp_reo_cache_flush(struct ath12k_base *ab, + } + } + ++ rx_tid->pending_desc_size = desc_sz; + memset(&cmd, 0, sizeof(cmd)); + cmd.addr_lo = lower_32_bits(rx_tid->paddr); + cmd.addr_hi = upper_32_bits(rx_tid->paddr); +@@ -729,9 +731,6 @@ static int ath12k_dp_reo_cache_flush(struct ath12k_base *ab, + ret = ath12k_dp_reo_cmd_send(ab, rx_tid, + HAL_REO_CMD_FLUSH_CACHE, + &cmd, ath12k_dp_reo_cmd_free); +- if (ret) +- ath12k_err(ab, "failed to send HAL_REO_CMD_FLUSH_CACHE cmd, tid %d (%d)\n", +- rx_tid->tid, ret); + + exit: + return ret; +@@ -745,6 +744,7 @@ static void ath12k_dp_rx_tid_del_func(struct ath12k_dp *dp, void *ctx, + struct ath12k_dp_rx_reo_cache_flush_elem *elem, *tmp; + + if (status == HAL_REO_CMD_DRAIN) { ++ ab->soc_stats.hal_reo_cmd_drain++; + goto free_desc; + } else if (status != HAL_REO_CMD_SUCCESS) { + /* Shouldn't happen! Cleanup in case of other failure? */ +@@ -777,12 +777,11 @@ static void ath12k_dp_rx_tid_del_func(struct ath12k_dp *dp, void *ctx, + if (ath12k_dp_reo_cache_flush(ab, &elem->data)) { + /* In failure case, just update the timestamp + * for flush cache elem and continue */ ++ ab->soc_stats.reo_cmd_cache_error++; + spin_lock_bh(&dp->reo_cmd_lock); + elem->ts = jiffies + + msecs_to_jiffies(ATH12K_DP_RX_REO_DESC_FREE_TIMEOUT_MS); +- ath12k_warn(ab, "Failed to send HAL_REO_CMD_FLUSH_CACHE cmd" +- "Updating timestamp (%ld) in the list\n", elem->ts); +- continue; ++ break; + } + spin_lock_bh(&dp->reo_cmd_lock); + list_del(&elem->list); +diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.h b/drivers/net/wireless/ath/ath12k/dp_rx.h +index e6095b8..9cecfff 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_rx.h ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.h +@@ -17,6 +17,7 @@ struct ath12k_dp_rx_tid { + u32 *vaddr; + dma_addr_t paddr; + u32 size; ++ u32 pending_desc_size; + u32 ba_win_sz; + bool active; + +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/703-ath12k-fix-cold-boot-sequence-for-SoC-grouping.patch b/feeds/ipq95xx/mac80211/patches/qca/703-ath12k-fix-cold-boot-sequence-for-SoC-grouping.patch new file mode 100644 index 000000000..51616373c --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/703-ath12k-fix-cold-boot-sequence-for-SoC-grouping.patch @@ -0,0 +1,173 @@ +From daddcfdd1ac6bccf78017b7f2a29d73c0d14412f Mon Sep 17 00:00:00 2001 +From: Karthikeyan Kathirvel +Date: Fri, 30 Dec 2022 14:15:16 +0530 +Subject: [PATCH] ath12k: fix cold boot sequence for SoC grouping + +With grouping of hardware(mlo_capable=1) host will power up the firmware +only after all the expected num of hardwares has been grouped, then host +has to do cold boot process but here in failure case cold boot process +is started before grouping of hardware completes and also before +firmware power up. + +In case of coldboot, boot the firmare without filling mlo details, fill +the mlo details only while booting the firmware in +mission mode. + +Also increase the coldboot timeout to 60secs since 5Ghz and 6Ghz radios +are taking more time than the current timeout which is 40secs (~ 5ghz +is taking 41secs, ~ 6ghz is taking 51secs) + +Signed-off-by: Karthikeyan Kathirvel +--- + drivers/net/wireless/ath/ath12k/core.c | 4 +++ + drivers/net/wireless/ath/ath12k/hw.c | 2 +- + drivers/net/wireless/ath/ath12k/pci.c | 2 -- + drivers/net/wireless/ath/ath12k/qmi.c | 47 ++++++++++++++++---------- + drivers/net/wireless/ath/ath12k/qmi.h | 2 ++ + 5 files changed, 36 insertions(+), 21 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -1568,6 +1568,9 @@ static int ath12k_core_hw_group_create(s + } + set_bit(ATH12K_FLAG_HW_GROUP_ATTACHED, &ab->dev_flags); + mutex_unlock(&ab->core_lock); ++ ++ ath12k_qmi_fwreset_from_cold_boot(ab); ++ + } + + out: +@@ -1779,6 +1782,7 @@ struct ath12k_base *ath12k_core_alloc(st + ab->dev = dev; + ab->bus_params = *bus_params; + ab->hif.bus = bus; ++ ab->qmi.num_radios = ATH12K_QMI_INVALID_RADIO; + + return ab; + +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -1122,7 +1122,7 @@ static const struct ath12k_hw_params ath + .supports_monitor = true, + + .idle_ps = false, +- .cold_boot_calib = false, ++ .cold_boot_calib = true, + .download_calib = true, + .supports_suspend = false, + .tcl_ring_retry = true, +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -1348,8 +1348,6 @@ static int ath12k_pci_probe(struct pci_d + goto err_free_irq; + } + +- ath12k_qmi_fwreset_from_cold_boot(ab); +- + return 0; + + err_free_irq: +--- a/drivers/net/wireless/ath/ath12k/qmi.c ++++ b/drivers/net/wireless/ath/ath12k/qmi.c +@@ -19,8 +19,6 @@ + #include + #include + +-#define ATH12K_QMI_INVALID_RADIO 0xFF +- + #define SLEEP_CLOCK_SELECT_INTERNAL_BIT 0x02 + #define HOST_CSTATE_BIT 0x04 + #define PLATFORM_CAP_PCIE_GLOBAL_RESET 0x08 +@@ -2842,6 +2840,15 @@ static int ath12k_qmi_fill_mlo_host_caps + return 0; + } + ++ if (ath12k_cold_boot_cal && ab->qmi.cal_done == 0 && ++ ab->hw_params->cold_boot_calib && ++ ab->qmi.cal_timeout == 0) { ++ ath12k_dbg(ab, ATH12K_DBG_QMI, "Skip MLO cap send for chip id %d since it's in cold_boot\n", ++ ab->chip_id); ++ mutex_unlock(&ag->mutex_lock); ++ return 0; ++ } ++ + if (ag->id == ATH12K_INVALID_GRP_ID || !ab->qmi.num_radios) { + ag->mlo_capable = false; + +@@ -4383,12 +4390,10 @@ void ath12k_qmi_trigger_host_cap(struct + + spin_unlock(&qmi->event_lock); + +- if (block) { +- ath12k_dbg(ab, ATH12K_DBG_QMI, "Trigger host cap for chip id %d\n", +- ab->chip_id); ++ ath12k_dbg(ab, ATH12K_DBG_QMI, "Trigger host cap for chip id %d\n", ++ ab->chip_id); + +- ath12k_qmi_driver_event_post(qmi, ATH12K_QMI_EVENT_HOST_CAP, NULL); +- } ++ ath12k_qmi_driver_event_post(qmi, ATH12K_QMI_EVENT_HOST_CAP, NULL); + } + + static bool ath12k_qmi_hw_group_host_cap_ready(struct ath12k_hw_group *ag) +@@ -4451,18 +4456,25 @@ static int ath12k_qmi_event_server_arriv + + ath12k_qmi_phy_cap_send(ab); + +- spin_lock(&qmi->event_lock); +- ath12k_qmi_set_event_block(&ab->qmi, true); +- spin_unlock(&qmi->event_lock); ++ if (ath12k_cold_boot_cal && ab->qmi.cal_done == 0 && ++ ab->hw_params->cold_boot_calib && ++ ab->qmi.cal_timeout == 0) { ++ /* Coldboot calibration mode */ ++ ath12k_qmi_trigger_host_cap(ab); ++ } else { ++ spin_lock(&qmi->event_lock); ++ ath12k_qmi_set_event_block(&ab->qmi, true); ++ spin_unlock(&qmi->event_lock); + +- mutex_lock(&ag->mutex_lock); +- host_cap_ready = ath12k_qmi_hw_group_host_cap_ready(ag); +- if (host_cap_ready) { +- block_ab = ath12k_qmi_hw_group_find_blocked_chip(ag); +- if (block_ab) +- ath12k_qmi_trigger_host_cap(block_ab); ++ mutex_lock(&ag->mutex_lock); ++ host_cap_ready = ath12k_qmi_hw_group_host_cap_ready(ag); ++ if (host_cap_ready) { ++ block_ab = ath12k_qmi_hw_group_find_blocked_chip(ag); ++ if (block_ab) ++ ath12k_qmi_trigger_host_cap(block_ab); ++ } ++ mutex_unlock(&ag->mutex_lock); + } +- mutex_unlock(&ag->mutex_lock); + + return ret; + } +@@ -5152,7 +5164,6 @@ int ath12k_qmi_init_service(struct ath12 + memset(&ab->qmi.target, 0, sizeof(struct target_info)); + memset(&ab->qmi.target_mem, 0, sizeof(struct target_mem_chunk)); + ab->qmi.ab = ab; +- ab->qmi.num_radios = ATH12K_QMI_INVALID_RADIO; + + ab->qmi.target_mem_mode = ATH12K_QMI_TARGET_MEM_MODE_DEFAULT; + ret = qmi_handle_init(&ab->qmi.handle, ATH12K_QMI_RESP_LEN_MAX, +--- a/drivers/net/wireless/ath/ath12k/qmi.h ++++ b/drivers/net/wireless/ath/ath12k/qmi.h +@@ -47,10 +47,12 @@ + #define QMI_WLANFW_MAX_DATA_SIZE_V01 6144 + #define ATH12K_FIRMWARE_MODE_OFF 4 + #define ATH12K_QMI_TARGET_MEM_MODE_DEFAULT 0 +-#define ATH12K_COLD_BOOT_FW_RESET_DELAY (40 * HZ) ++#define ATH12K_COLD_BOOT_FW_RESET_DELAY (60 * HZ) + + #define ATH12K_BOARD_ID_DEFAULT 0xFF + ++#define ATH12K_QMI_INVALID_RADIO 0xFF ++ + struct ath12k_base; + + enum ath12k_qmi_file_type { diff --git a/feeds/ipq95xx/mac80211/patches/qca/703-ath12k-handle-mac-op-scan-with-link-id.patch b/feeds/ipq95xx/mac80211/patches/qca/703-ath12k-handle-mac-op-scan-with-link-id.patch new file mode 100644 index 000000000..fe1f704eb --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/703-ath12k-handle-mac-op-scan-with-link-id.patch @@ -0,0 +1,211 @@ +From 2676762acf8a4480174e23df52a3b397986e5e4f Mon Sep 17 00:00:00 2001 +From: Karthikeyan Kathirvel +Date: Wed, 21 Dec 2022 15:44:18 +0530 +Subject: [PATCH] ath12k: handle mac op scan with link id + +Currently the hw scan will not be done based on link id, enabling the hw +scan based on link id specific. + +The link id is decided based on the scan freq, and the arvif is created +and stored based on the link_id in ahvif + +Signed-off-by: Karthikeyan Kathirvel +--- + drivers/net/wireless/ath/ath12k/core.h | 6 ++++ + drivers/net/wireless/ath/ath12k/mac.c | 47 ++++++++++++++++++++++++-- + 2 files changed, 50 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -715,6 +715,11 @@ enum ath12k_fw_recovery_option { + ATH12K_FW_RECOVERY_ENABLE_SSR_ONLY, + }; + ++struct ath12k_chan_info { ++ u32 low_freq; ++ u32 high_freq; ++}; ++ + #define ATH12K_FLUSH_TIMEOUT (5 * HZ) + #define ATH12K_VDEV_DELETE_TIMEOUT_HZ (5 * HZ) + +@@ -725,6 +730,7 @@ struct ath12k { + struct ath12k_pdev_wmi *wmi; + struct ath12k_pdev_dp dp; + u8 mac_addr[ETH_ALEN]; ++ struct ath12k_chan_info chan_info; + u32 ht_cap_info; + u32 vht_cap_info; + struct ath12k_he ar_he; +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -4502,6 +4502,33 @@ clean_up: + return ret; + } + ++static int ++ath12k_mac_find_link_id_by_freq(struct ieee80211_vif *vif, struct ath12k *ar, u32 freq) ++{ ++ struct ath12k_vif *ahvif = (void *)vif->drv_priv; ++ u16 link_id; ++ ++ lockdep_assert_held(&ahvif->ah->conf_mutex); ++ ++ if (!vif->valid_links) ++ return 0; ++ ++ for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) { ++ if (!(ahvif->links_map & BIT(link_id)) || ++ !ahvif->link[link_id]->ar) ++ continue; ++ if (freq >= ahvif->link[link_id]->ar->chan_info.low_freq && ++ freq <= ahvif->link[link_id]->ar->chan_info.high_freq) ++ return link_id; ++ } ++ ++ /* ++ * Valid ML case when channel is not assigned to any of the links ++ * so link id 0 can be used ++ */ ++ return 0; ++} ++ + static struct ath12k_link_vif * + ath12k_mac_assign_link_vif( struct ath12k_hw *ah, struct ieee80211_vif *vif, u8 link_id) + { +@@ -4768,7 +4795,7 @@ static int ath12k_mac_op_hw_scan(struct + struct ath12k *ar; + struct scan_req_params arg; + int ret = 0; +- int i; ++ int i, link_id; + bool create = true; + + mutex_lock(&ah->conf_mutex); +@@ -4783,8 +4810,10 @@ static int ath12k_mac_op_hw_scan(struct + return -EINVAL; + } + +- /* TODO ML vif handling */ +- arvif = ath12k_mac_assign_link_vif(ah, vif, 0); ++ link_id = ath12k_mac_find_link_id_by_freq(vif, ar, ++ hw_req->req.channels[0]->center_freq); ++ ++ arvif = ath12k_mac_assign_link_vif(ah, vif, link_id); + /* If the vif is already assigned to a specific vdev of an ar, + * check whether its already started, vdev which is started + * are not allowed to switch to a new radio. +@@ -13342,7 +13371,7 @@ static int ath12k_mac_setup_channels_rat + struct ieee80211_supported_band *band; + struct ath12k_hal_reg_capabilities_ext *reg_cap, *temp_reg_cap; + void *channels; +- u32 phy_id; ++ u32 phy_id, freq_low, freq_high; + struct ieee80211_6ghz_channel *chan_6g; + int i = 0; + +@@ -13378,7 +13407,14 @@ static int ath12k_mac_setup_channels_rat + temp_reg_cap->low_2ghz_chan, + temp_reg_cap->high_2ghz_chan); + ++ freq_low = max(temp_reg_cap->low_2ghz_chan, ++ ab->reg_freq_2g.start_freq); ++ freq_high = min(temp_reg_cap->high_2ghz_chan, ++ ab->reg_freq_2g.end_freq); ++ + ah->supported_band_mask |= BIT(NL80211_BAND_2GHZ); ++ ar->chan_info.low_freq = freq_low; ++ ar->chan_info.high_freq = freq_high; + } + + if (supported_bands & WMI_HOST_WLAN_5G_CAP) { +@@ -13417,7 +13453,14 @@ static int ath12k_mac_setup_channels_rat + + ath12k_mac_update_5_9_ch_list(ar, band); + ++ freq_low = max(temp_reg_cap->low_5ghz_chan, ++ ab->reg_freq_5g.start_freq); ++ freq_high = min(temp_reg_cap->high_5ghz_chan, ++ ab->reg_freq_5g.end_freq); ++ + ah->supported_band_mask |= BIT(NL80211_BAND_5GHZ); ++ ar->chan_info.low_freq = freq_low; ++ ar->chan_info.high_freq = freq_high; + } else if (reg_cap->low_5ghz_chan >= ATH12K_MIN_6G_FREQ && + reg_cap->high_5ghz_chan <= ATH12K_MAX_6G_FREQ) { + band = &ar->mac.sbands[NL80211_BAND_6GHZ]; +@@ -13466,10 +13509,20 @@ static int ath12k_mac_setup_channels_rat + band->n_channels = band->chan_6g[0]->n_channels; + band->channels = band->chan_6g[0]->channels; + ++ freq_low = max(temp_reg_cap->low_5ghz_chan, ++ ab->reg_freq_6g.start_freq); ++ freq_high = min(temp_reg_cap->high_5ghz_chan, ++ ab->reg_freq_6g.end_freq); ++ + ah->supported_band_mask |= BIT(NL80211_BAND_6GHZ); ++ ar->chan_info.low_freq = freq_low; ++ ar->chan_info.high_freq = freq_high; + } + } + ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac pdev %u freq limits %u->%u MHz\n", ++ ar->pdev->pdev_id, ar->chan_info.low_freq, ++ ar->chan_info.high_freq); + return 0; + } + +--- a/drivers/net/wireless/ath/ath12k/reg.c ++++ b/drivers/net/wireless/ath/ath12k/reg.c +@@ -275,13 +275,51 @@ int ath12k_regd_update(struct ath12k *ar + int ret, regd_len, pdev_id; + struct ath12k_base *ab; + struct ath12k_hw *ah; ++ struct ath12k_hal_reg_capabilities_ext *reg_cap; + int i; ++ u32 phy_id, freq_low, freq_high, supported_bands, band; + + ab = ar->ab; + ah = ar->ah; + + mutex_lock(&ah->conf_mutex); + ++ supported_bands = ar->pdev->cap.supported_bands; ++ if (supported_bands & WMI_HOST_WLAN_2G_CAP) ++ band = NL80211_BAND_2GHZ; ++ else if(supported_bands & WMI_HOST_WLAN_5G_CAP && !ar->supports_6ghz) ++ band = NL80211_BAND_5GHZ; ++ else if(supported_bands & WMI_HOST_WLAN_5G_CAP && ar->supports_6ghz) ++ band = NL80211_BAND_6GHZ; ++ ++ reg_cap = &ab->hal_reg_cap[ar->pdev_idx]; ++ ++ if (ab->hw_params->single_pdev_only && !ar->supports_6ghz) { ++ phy_id = ar->pdev->cap.band[band].phy_id; ++ reg_cap = &ab->hal_reg_cap[phy_id]; ++ } ++ ++ /* Possible that due to reg change, current limits for supported ++ * frequency changed. Update that ++ */ ++ if (supported_bands & WMI_HOST_WLAN_2G_CAP) { ++ freq_low = max(reg_cap->low_2ghz_chan, ab->reg_freq_2g.start_freq); ++ freq_high = min(reg_cap->high_2ghz_chan, ab->reg_freq_2g.end_freq); ++ } else if(supported_bands & WMI_HOST_WLAN_5G_CAP && !ar->supports_6ghz) { ++ freq_low = max(reg_cap->low_5ghz_chan, ab->reg_freq_5g.start_freq); ++ freq_high = min(reg_cap->high_5ghz_chan, ab->reg_freq_5g.end_freq); ++ } else if(supported_bands & WMI_HOST_WLAN_5G_CAP && ar->supports_6ghz) { ++ freq_low = max(reg_cap->low_5ghz_chan, ab->reg_freq_6g.start_freq); ++ freq_high = min(reg_cap->high_5ghz_chan, ab->reg_freq_6g.end_freq); ++ } ++ ++ ar->chan_info.low_freq = freq_low; ++ ar->chan_info.high_freq = freq_high; ++ ++ ath12k_dbg(ab, ATH12K_DBG_REG, "pdev %u reg updated freq limits %u->%u MHz\n", ++ ar->pdev->pdev_id, ar->chan_info.low_freq, ++ ar->chan_info.high_freq); ++ + if (ah->regd_updated) { + mutex_unlock(&ah->conf_mutex); + return 0; diff --git a/feeds/ipq95xx/mac80211/patches/qca/703-wifi-ath12k-fix-peer-id-and-non-primary-buffer-in-rx-dp.patch b/feeds/ipq95xx/mac80211/patches/qca/703-wifi-ath12k-fix-peer-id-and-non-primary-buffer-in-rx-dp.patch new file mode 100644 index 000000000..133c2822c --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/703-wifi-ath12k-fix-peer-id-and-non-primary-buffer-in-rx-dp.patch @@ -0,0 +1,146 @@ +From 641a5058caacadde6e559d37fe2c149aa6669db1 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Fri, 16 Dec 2022 12:31:00 +0530 +Subject: [PATCH] wifi: ath12k: fix non primary buffer in rx dp + +peer id decode from the peer meta data present in the REO ring decriptor +is wrong due to wrong field mask. So update the correct peer field mask. +Store the hw link id in the skb_cb to retrieve the correct radio for the +given pkt. Also mac_id is not needed since hw link id is enough to pick +mac_id. Due to wrong pdev selection for the given peer, peer lookup fails. +So now with the updated hw link id, the rx status chosen with correct +link id. + +Signed-off-by: Karthikeyan Periyasamy +--- +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -123,7 +123,7 @@ struct ath12k_skb_rxcb { + struct hal_rx_desc *rx_desc; + u8 err_rel_src; + u8 err_code; +- u8 mac_id; ++ u8 hw_link_id; + u8 unmapped; + u8 is_frag; + u8 tid; +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -3054,7 +3054,7 @@ static void ath12k_dp_rx_process_receive + struct ath12k_skb_rxcb *rxcb; + struct sk_buff *msdu; + struct ath12k *ar; +- u8 mac_id; ++ u8 mac_id, hw_link_id; + int ret; + bool fast_rx; + +@@ -3070,9 +3070,22 @@ static void ath12k_dp_rx_process_receive + fast_rx = true; + rxcb->napi = napi; + +- mac_id = rxcb->mac_id; +- ar = ab->pdevs[mac_id].ar; +- if (!rcu_dereference(ab->pdevs_active[mac_id])) { ++ hw_link_id = rxcb->hw_link_id; ++ if (hw_link_id >= ATH12K_GROUP_MAX_RADIO) { ++ dev_kfree_skb_any(msdu); ++ ath12k_warn(ab, "invalid hw link id %d\n", hw_link_id); ++ continue; ++ } ++ ++ ar = rcu_dereference(ab->ag->hw_links[hw_link_id]); ++ if (!ar) { ++ dev_kfree_skb_any(msdu); ++ ath12k_warn(ab, "invalid pdev for hw link id %d\n", hw_link_id); ++ continue; ++ } ++ ++ mac_id = ar->pdev_idx; ++ if (!rcu_dereference(ar->ab->pdevs_active[mac_id])) { + dev_kfree_skb_any(msdu); + continue; + } +@@ -3085,7 +3098,9 @@ static void ath12k_dp_rx_process_receive + ret = ath12k_dp_rx_process_msdu(ar, msdu, msdu_list, &rx_status, &fast_rx); + if (ret) { + ath12k_dbg(ab, ATH12K_DBG_DATA, +- "Unable to process msdu %d", ret); ++ "Unable to process %s chip_id %d msdu %d", ++ (ab != ar->ab) ? "partner" : "own", ++ ar->ab->chip_id, ret); + dev_kfree_skb_any(msdu); + continue; + } +@@ -3111,7 +3126,6 @@ int ath12k_dp_rx_process(struct ath12k_b + struct hal_srng *srng; + struct sk_buff *msdu; + bool done = false; +- int mac_id; + u32 *rx_desc; + u64 desc_va; + struct ath12k_sta *ahsta = NULL; +@@ -3163,7 +3177,6 @@ try_again: + continue; + } + +- mac_id = ar->pdev_idx; + src_ab = ar->ab; + rcu_read_unlock(); + +@@ -3208,7 +3221,7 @@ try_again: + RX_MSDU_DESC_INFO0_LAST_MSDU_IN_MPDU); + rxcb->is_continuation = !!(desc.rx_msdu_info.info0 & + RX_MSDU_DESC_INFO0_MSDU_CONTINUATION); +- rxcb->mac_id = mac_id; ++ rxcb->hw_link_id = hw_link_id; + rxcb->peer_id = u32_get_bits(desc.rx_mpdu_info.peer_meta_data, + RX_MPDU_DESC_META_DATA_PEER_ID); + rxcb->tid = u32_get_bits(desc.rx_mpdu_info.info0, +@@ -4024,6 +4037,11 @@ int ath12k_dp_rx_process_err(struct ath1 + for (i = 0; i < num_msdus; i++) { + mac_id = u32_get_bits(reo_desc->info0, + HAL_REO_DEST_RING_INFO0_SRC_LINK_ID); ++ if (mac_id >= ab->num_radios) { ++ tot_n_bufs_reaped++; ++ ath12k_warn(ab, "invalid mac id %d on err process\n", mac_id); ++ continue; ++ } + + ar = ab->pdevs[mac_id].ar; + +--- a/drivers/net/wireless/ath/ath12k/hal_desc.h ++++ b/drivers/net/wireless/ath/ath12k/hal_desc.h +@@ -606,8 +606,7 @@ struct hal_tlv_parsed_hdr { + #define RX_MPDU_DESC_INFO0_MPDU_QOS_CTRL_VALID BIT(27) + #define RX_MPDU_DESC_INFO0_TID GENMASK(31, 28) + +-/* TODO revisit after meta data is concluded */ +-#define RX_MPDU_DESC_META_DATA_PEER_ID GENMASK(15, 0) ++#define RX_MPDU_DESC_META_DATA_PEER_ID GENMASK(13, 0) + + struct rx_mpdu_desc { + u32 info0; /* %RX_MPDU_DESC_INFO */ +--- a/drivers/net/wireless/ath/ath12k/hal.c ++++ b/drivers/net/wireless/ath/ath12k/hal.c +@@ -351,7 +351,8 @@ static u8 ath12k_hw_qcn9274_rx_desc_get_ + + static u16 ath12k_hw_qcn9274_rx_desc_get_mpdu_peer_id(struct hal_rx_desc *desc) + { +- return __le16_to_cpu(desc->u.qcn9274.mpdu_start.sw_peer_id); ++ return le16_get_bits(desc->u.qcn9274.mpdu_start.sw_peer_id, ++ RX_MPDU_START_SW_PEER_ID_PEER); + } + + static void ath12k_hw_qcn9274_rx_desc_copy_end_tlv(struct hal_rx_desc *fdesc, +--- a/drivers/net/wireless/ath/ath12k/rx_desc.h ++++ b/drivers/net/wireless/ath/ath12k/rx_desc.h +@@ -59,6 +59,8 @@ enum rx_desc_decrypt_status_code { + #define RX_MPDU_START_INFO3_AST_LOOKUP_VALID BIT(13) + #define RX_MPDU_START_INFO3_RANGING BIT(14) + ++#define RX_MPDU_START_SW_PEER_ID_PEER GENMASK(13, 0) ++ + #define RX_MPDU_START_INFO4_MPDU_FCTRL_VALID BIT(0) + #define RX_MPDU_START_INFO4_MPDU_DUR_VALID BIT(1) + #define RX_MPDU_START_INFO4_MAC_ADDR1_VALID BIT(2) diff --git a/feeds/ipq95xx/mac80211/patches/qca/704-01-ath12k-fix-Factery-Test-Mode-crash-issue.patch b/feeds/ipq95xx/mac80211/patches/qca/704-01-ath12k-fix-Factery-Test-Mode-crash-issue.patch new file mode 100644 index 000000000..cf2d079a5 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/704-01-ath12k-fix-Factery-Test-Mode-crash-issue.patch @@ -0,0 +1,68 @@ +From 106db5f9b54d4e96917bc253bc432b6ab2ef0746 Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Thu, 22 Dec 2022 12:01:22 +0530 +Subject: [PATCH] ath12k: fix Factory Test Mode crash issue + +Currently we are getting ar by vif but for FTM vif is null +so we are getting null value for ar also and passing null +ar pointer in ath12k_tm_cmd. + +fix this issue by assigning ar value to ath12k_hw radio. + +Signed-off-by: Aaradhana Sahu +--- + drivers/net/wireless/ath/ath12k/core.c | 2 +- + drivers/net/wireless/ath/ath12k/testmode.c | 5 +++-- + drivers/net/wireless/ath/ath12k/wmi.c | 2 +- + 3 files changed, 5 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -152,7 +152,7 @@ static struct ath12k_hw_group *ath12k_co + * within the soc, all links are combined into a single wiphy. + */ + mlo = of_parse_phandle(dev->of_node, "qcom,wsi", 0); +- if (mlo && ath12k_mlo_capable) { ++ if (mlo && ath12k_mlo_capable && !ath12k_ftm_mode) { + ret = of_property_read_u32(mlo, "id", &group_id); + if (ret) + group_id = ATH12K_INVALID_GRP_ID; +@@ -1210,7 +1210,7 @@ int ath12k_core_qmi_firmware_ready(struc + struct ath12k_hw_group *ag; + int ret; + +- ret = ath12k_core_start_firmware(ab, ATH12K_FIRMWARE_MODE_NORMAL); ++ ret = ath12k_core_start_firmware(ab, ab->fw_mode); + if (ret) { + ath12k_err(ab, "failed to start firmware: %d\n", ret); + return ret; +--- a/drivers/net/wireless/ath/ath12k/testmode.c ++++ b/drivers/net/wireless/ath/ath12k/testmode.c +@@ -439,13 +439,13 @@ int ath12k_tm_cmd(struct ieee80211_hw *h + + mutex_lock(&ah->conf_mutex); + +- /* TODO cmd for all ML vifs */ +- ar = ath12k_get_ar_by_vif(hw, vif, 0); +- ab = ar->ab; ++ if (ah->num_radio) ++ ar = ah->radio; + if (!ar) { + mutex_unlock(&ah->conf_mutex); + return -EINVAL; + } ++ ab = ar->ab; + + mutex_unlock(&ah->conf_mutex); + +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -8432,7 +8432,7 @@ static void ath12k_wmi_tm_event_segmente + + length = skb->len - TLV_HDR_SIZE; + ret = ath12k_tm_process_event(ab, cmd_id, ev, length); +- if (!ret) ++ if (ret) + ath12k_warn(ab, "Failed to process ftm event\n"); + kfree(tb); + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/704-02-ath12k-fix-firmware-assert-issue-for-Tx-test-case-in.patch b/feeds/ipq95xx/mac80211/patches/qca/704-02-ath12k-fix-firmware-assert-issue-for-Tx-test-case-in.patch new file mode 100644 index 000000000..74df5ce78 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/704-02-ath12k-fix-firmware-assert-issue-for-Tx-test-case-in.patch @@ -0,0 +1,29 @@ +From 517096713fb1ae695c4720a479d64aa09497c9f5 Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Thu, 22 Dec 2022 12:12:43 +0530 +Subject: [PATCH] ath12k: fix firmware assert issue for Tx test case in FTM + +Currently, we are converting hardware cookies for FTM mode +but firmware is not handling such type of cookie conversion, +so it's trigger the firmware assert. + +Fix this issue by disabling hardware cookie conversion in +FTM mode. + +Signed-off-by: Aaradhana Sahu +--- + drivers/net/wireless/ath/ath12k/dp.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -1306,6 +1306,9 @@ void ath12k_dp_cc_config(struct ath12k_b + u32 wbm_base = HAL_SEQ_WCSS_UMAC_WBM_REG; + u32 val = 0; + ++ if (ath12k_ftm_mode) ++ return; ++ + ath12k_hif_write32(ab, reo_base + HAL_REO1_SW_COOKIE_CFG0(ab), cmem_base); + + val |= u32_encode_bits(ATH12K_CMEM_ADDR_MSB, diff --git a/feeds/ipq95xx/mac80211/patches/qca/704-a-ath12k-Add-support-for-new-htt_stats.patch b/feeds/ipq95xx/mac80211/patches/qca/704-a-ath12k-Add-support-for-new-htt_stats.patch new file mode 100644 index 000000000..43841aa4f --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/704-a-ath12k-Add-support-for-new-htt_stats.patch @@ -0,0 +1,662 @@ +From 7dab5ec52c6f450e37cca5306e9ca222a2a4b3a7 Mon Sep 17 00:00:00 2001 +From: Rajat Soni +Date: Tue, 27 Dec 2022 12:11:09 +0530 +Subject: [PATCH] ath12k: Add support for new htt_stats + +ATH12K_DBG_HTT_EXT_RX_RING_STATS +ATH12K_DBG_HTT_STRM_GEN_MPDUS_STATS +ATH12K_DBG_HTT_STRM_GEN_MPDUS_DETAILS_STATS +ATH12K_DBG_HTT_DBG_SOC_ERROR_STATS + +Signed-off-by: Rajat Soni +--- + drivers/net/wireless/ath/ath12k/debugfs.h | 4 + + .../wireless/ath/ath12k/debugfs_htt_stats.c | 482 +++++++++++++++++- + .../wireless/ath/ath12k/debugfs_htt_stats.h | 104 +++- + 3 files changed, 588 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/debugfs.h b/drivers/net/wireless/ath/ath12k/debugfs.h +index da4083a..f002387 100644 +--- a/drivers/net/wireless/ath/ath12k/debugfs.h ++++ b/drivers/net/wireless/ath/ath12k/debugfs.h +@@ -58,6 +58,10 @@ enum ath12k_dbg_htt_ext_stats_type { + ATH12K_DBG_HTT_EXT_VDEV_RTT_INITIATOR_STATS = 39, + ATH12K_DBG_HTT_EXT_PDEV_PER_STATS = 40, + ATH12K_DBG_HTT_EXT_AST_ENTRIES = 41, ++ ATH12K_DBG_HTT_EXT_RX_RING_STATS = 42, ++ ATH12K_DBG_HTT_STRM_GEN_MPDUS_STATS = 43, ++ ATH12K_DBG_HTT_STRM_GEN_MPDUS_DETAILS_STATS = 44, ++ ATH12K_DBG_HTT_DBG_SOC_ERROR_STATS = 45, + + /* keep this last */ + ATH12K_DBG_HTT_NUM_EXT_STATS, +diff --git a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c +index 726f021..2cf6689 100644 +--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c +@@ -5737,6 +5737,466 @@ htt_print_txbf_ofdma_ax_steer_stats_tlv(const void *tag_buf, + stats_req->buf_len = len; + } + ++static inline void ++htt_print_txbf_ofdma_be_ndpa_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_txbf_ofdma_be_ndpa_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ int i, null_output; ++ u32 num_elements = htt_stats_buf->num_elems_be_ndpa_arr; ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "HTT_TXBF_OFDMA_BE_NDPA_STATS_TLV:\n"); ++ ++ null_output = 1; ++ for (i = 0; i < num_elements; i++) { ++ if (htt_stats_buf->be_ndpa[i].be_ofdma_ndpa_queued) { ++ null_output = 0; ++ len += scnprintf(buf + len, buf_len - len, ++ " %u:%u,", i + 1, ++ htt_stats_buf->be_ndpa[i].be_ofdma_ndpa_queued); ++ } ++ } ++ if (null_output) { ++ len += scnprintf(buf + len, buf_len - len, ++ "be_ofdma_ndpa_queued = %s\n", "NONE"); ++ } ++ ++ null_output = 1; ++ ++ for (i = 0; i < num_elements; i++) { ++ if (htt_stats_buf->be_ndpa[i].be_ofdma_ndpa_tried) { ++ null_output = 0; ++ len += scnprintf(buf + len, buf_len - len, ++ " %u:%u,", i + 1, ++ htt_stats_buf->be_ndpa[i].be_ofdma_ndpa_tried); ++ } ++ } ++ if (null_output) { ++ len += scnprintf(buf + len, buf_len - len, ++ "be_ofdma_ndpa_tried = %s\n", "NONE"); ++ } ++ ++ null_output = 1; ++ ++ for (i = 0; i < num_elements; i++) { ++ if (htt_stats_buf->be_ndpa[i].be_ofdma_ndpa_flushed) { ++ null_output = 0; ++ len += scnprintf(buf + len, buf_len - len, ++ " %u:%u,", i + 1, ++ htt_stats_buf->be_ndpa[i].be_ofdma_ndpa_flushed); ++ } ++ } ++ if (null_output) { ++ len += scnprintf(buf + len, buf_len - len, ++ "be_ofdma_ndpa_flushed = %s\n", "NONE"); ++ } ++ ++ null_output = 1; ++ ++ for (i = 0; i < num_elements; i++) { ++ if (htt_stats_buf->be_ndpa[i].be_ofdma_ndpa_err) { ++ null_output = 0; ++ len += scnprintf(buf + len, buf_len - len, ++ " %u:%u,", i + 1, ++ htt_stats_buf->be_ndpa[i].be_ofdma_ndpa_err); ++ } ++ } ++ if (null_output) { ++ len += scnprintf(buf + len, buf_len - len, ++ "be_ofdma_ndpa_err = %s\n", "NONE"); ++ } ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_txbf_ofdma_be_ndp_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_txbf_ofdma_be_ndp_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ int i, null_output; ++ ++ u32 num_elements = htt_stats_buf->num_elems_be_ndp_arr; ++ ++ len += scnprintf(buf + len, buf_len - len, "HTT_TXBF_OFDMA_BE_NDP_STATS_TLV:\n"); ++ null_output = 1; ++ for (i = 0; i < num_elements; i++) { ++ if (htt_stats_buf->be_ndp[i].be_ofdma_ndp_queued) { ++ null_output = 0; ++ len += scnprintf(buf + len, buf_len - len, ++ " %u:%u,", i + 1, ++ htt_stats_buf->be_ndp[i].be_ofdma_ndp_queued); ++ } ++ } ++ if (null_output) { ++ len += scnprintf(buf + len, buf_len - len, ++ "be_ofdma_ndp_queued = %s\n", "NONE"); ++ } ++ ++ null_output = 1; ++ for (i = 0; i < num_elements; i++) { ++ if (htt_stats_buf->be_ndp[i].be_ofdma_ndp_flushed) { ++ null_output = 0; ++ len += scnprintf(buf + len, buf_len - len, ++ " %u:%u,", i + 1, ++ htt_stats_buf->be_ndp[i].be_ofdma_ndp_flushed); ++ } ++ } ++ if (null_output) { ++ len += scnprintf(buf + len, buf_len - len, ++ "be_ofdma_ndp_flushed = %s\n", "NONE"); ++ } ++ ++ null_output = 1; ++ for (i = 0; i < num_elements; i++) { ++ if (htt_stats_buf->be_ndp[i].be_ofdma_ndp_err) { ++ null_output = 0; ++ len += scnprintf(buf + len, buf_len - len, ++ " %u:%u,", i + 1, ++ htt_stats_buf->be_ndp[i].be_ofdma_ndp_err); ++ } ++ } ++ if (null_output) { ++ len += scnprintf(buf + len, buf_len - len, ++ "be_ofdma_ndp_err = %s\n", "NONE"); ++ } ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_txbf_ofdma_be_brp_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_txbf_ofdma_be_brp_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ int i, null_output; ++ ++ u32 num_elements = htt_stats_buf->num_elems_be_brp_arr; ++ ++ len += scnprintf(buf + len, buf_len - len, "HTT_TXBF_OFDMA_BE_BRP_STATS_TLV:\n"); ++ null_output = 1; ++ for (i = 0; i < num_elements; i++) { ++ if (htt_stats_buf->be_brp[i].be_ofdma_brpoll_queued) { ++ null_output = 0; ++ len += scnprintf(buf + len, buf_len - len, ++ " %u:%u,", i + 1, ++ htt_stats_buf->be_brp[i].be_ofdma_brpoll_queued); ++ } ++ } ++ if (null_output) { ++ len += scnprintf(buf + len, buf_len - len, ++ "be_ofdma_brpoll_queued = %s\n", "NONE"); ++ } ++ ++ null_output = 1; ++ for (i = 0; i < num_elements; i++) { ++ if (htt_stats_buf->be_brp[i].be_ofdma_brpoll_tried) { ++ null_output = 0; ++ len += scnprintf(buf + len, buf_len - len, ++ " %u:%u,", i + 1, ++ htt_stats_buf->be_brp[i].be_ofdma_brpoll_tried); ++ } ++ } ++ if (null_output) { ++ len += scnprintf(buf + len, buf_len - len, ++ "be_ofdma_brpoll_tried = %s\n", "NONE"); ++ } ++ ++ null_output = 1; ++ for (i = 0; i < num_elements; i++) { ++ if (htt_stats_buf->be_brp[i].be_ofdma_brpoll_flushed) { ++ null_output = 0; ++ len += scnprintf(buf + len, buf_len - len, ++ " %u:%u,", i + 1, ++ htt_stats_buf->be_brp[i].be_ofdma_brpoll_flushed); ++ } ++ } ++ if (null_output) { ++ len += scnprintf(buf + len, buf_len - len, ++ "be_ofdma_brpoll_flushed = %s\n", "NONE"); ++ } ++ ++ null_output = 1; ++ for (i = 0; i < num_elements; i++) { ++ if (htt_stats_buf->be_brp[i].be_ofdma_brp_err) { ++ null_output = 0; ++ len += scnprintf(buf + len, buf_len - len, ++ " %u:%u,", i + 1, ++ htt_stats_buf->be_brp[i].be_ofdma_brp_err); ++ } ++ } ++ if (null_output) { ++ len += scnprintf(buf + len, buf_len - len, ++ "be_ofdma_brp_err = %s\n", "NONE"); ++ } ++ null_output = 1; ++ for (i = 0; i < num_elements; i++) { ++ if (htt_stats_buf->be_brp[i].be_ofdma_brp_err_num_cbf_rcvd) { ++ null_output = 0; ++ len += scnprintf(buf + len, buf_len - len, ++ " %u:%u,", i + 1, ++ htt_stats_buf->be_brp[i].be_ofdma_brp_err_num_cbf_rcvd); ++ } ++ } ++ if (null_output) { ++ len += scnprintf(buf + len, buf_len - len, ++ "be_ofdma_brp_err_num_cbf_rcvd = %s\n", "NONE"); ++ } ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_txbf_ofdma_be_steer_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_txbf_ofdma_be_steer_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ int i, null_output; ++ ++ u32 num_elements = htt_stats_buf->num_elems_be_steer_arr; ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "HTT_TXBF_OFDMA_BE_STEER_STATS_TLV:\n"); ++ ++ null_output = 1; ++ for (i = 0; i < num_elements; i++) { ++ if (htt_stats_buf->be_steer[i].be_ofdma_num_ppdu_steer) { ++ null_output = 0; ++ len += scnprintf(buf + len, buf_len - len, ++ " %u:%u,", i + 1, ++ htt_stats_buf->be_steer[i].be_ofdma_num_ppdu_steer); ++ } ++ } ++ if (null_output) { ++ len += scnprintf(buf + len, buf_len - len, ++ "be_ofdma_num_ppdu_steer = %s\n", "NONE"); ++ } ++ ++ null_output = 1; ++ for (i = 0; i < num_elements; i++) { ++ if (htt_stats_buf->be_steer[i].be_ofdma_num_ppdu_ol) { ++ null_output = 0; ++ len += scnprintf(buf + len, buf_len - len, ++ " %u:%u,", i + 1, ++ htt_stats_buf->be_steer[i].be_ofdma_num_ppdu_ol); ++ } ++ } ++ if (null_output) { ++ len += scnprintf(buf + len, buf_len - len, ++ "be_ofdma_num_ppdu_ol = %s\n", "NONE"); ++ } ++ ++ null_output = 1; ++ for (i = 0; i < num_elements; i++) { ++ if (htt_stats_buf->be_steer[i].be_ofdma_num_usrs_prefetch) { ++ null_output = 0; ++ len += scnprintf(buf + len, buf_len - len, ++ " %u:%u,", i + 1, ++ htt_stats_buf->be_steer[i].be_ofdma_num_usrs_prefetch); ++ } ++ } ++ if (null_output) { ++ len += scnprintf(buf + len, buf_len - len, ++ "be_ofdma_num_usrs_prefetch = %s\n", "NONE"); ++ } ++ ++ null_output = 1; ++ for (i = 0; i < num_elements; i++) { ++ if (htt_stats_buf->be_steer[i].be_ofdma_num_usrs_sound) { ++ null_output = 0; ++ len += scnprintf(buf + len, buf_len - len, ++ " %u:%u,", i + 1, ++ htt_stats_buf->be_steer[i].be_ofdma_num_usrs_sound); ++ } ++ } ++ if (null_output) { ++ len += scnprintf(buf + len, buf_len - len, ++ "be_ofdma_num_usrs_sound = %s\n", "NONE"); ++ } ++ ++ null_output = 1; ++ for (i = 0; i < num_elements; i++) { ++ if (htt_stats_buf->be_steer[i].be_ofdma_num_usrs_force_sound) { ++ null_output = 0; ++ len += scnprintf(buf + len, buf_len - len, ++ " %u:%u,", i + 1, ++ htt_stats_buf->be_steer[i].be_ofdma_num_usrs_force_sound); ++ } ++ } ++ if (null_output) { ++ len += scnprintf(buf + len, buf_len - len, ++ "be_ofdma_num_usrs_force_sound = %s\n", "NONE"); ++ } ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_dmac_reset_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_dmac_reset_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += scnprintf(buf + len, buf_len - len, "HTT_DMAC_RESET_STATS_TLV:\n"); ++ len += scnprintf(buf + len, buf_len - len, "reset_count = %u\n", ++ htt_stats_buf->reset_count); ++ len += scnprintf(buf + len, buf_len - len, "reset_time_hi_ms = 0x%x\n", ++ htt_stats_buf->reset_time_hi_ms); ++ len += scnprintf(buf + len, buf_len - len, "reset_time_lo_ms = 0x%x\n", ++ htt_stats_buf->reset_time_lo_ms); ++ len += scnprintf(buf + len, buf_len - len, "disengage_time_hi_ms = 0x%x\n", ++ htt_stats_buf->disengage_time_hi_ms); ++ len += scnprintf(buf + len, buf_len - len, "disengage_time_lo_ms = 0x%x\n", ++ htt_stats_buf->disengage_time_lo_ms); ++ len += scnprintf(buf + len, buf_len - len, "engage_time_hi_ms = 0x%x\n", ++ htt_stats_buf->engage_time_hi_ms); ++ len += scnprintf(buf + len, buf_len - len, "engage_time_lo_ms = 0x%x\n", ++ htt_stats_buf->engage_time_lo_ms); ++ len += scnprintf(buf + len, buf_len - len, "disengage_count = %u\n", ++ htt_stats_buf->disengage_count); ++ len += scnprintf(buf + len, buf_len - len, "drain_dest_ring_mask = %u\n", ++ htt_stats_buf->drain_dest_ring_mask); ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_be_ul_ofdma_user_stats(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_rx_pdev_be_ul_ofdma_user_stats_tlv *htt_ul_user_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ if (htt_ul_user_stats_buf->user_index == 0) { ++ len += scnprintf(buf + len, buf_len - len, ++ "HTT_RX_PDEV_BE_UL_OFDMA_USER_STAS_TLV\n"); ++ } ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "be_rx_ulofdma_non_data_ppdu_%u = %u\n", ++ htt_ul_user_stats_buf->user_index, ++ htt_ul_user_stats_buf->be_rx_ulofdma_non_data_ppdu); ++ len += scnprintf(buf + len, buf_len - len, ++ "be_rx_ulofdma_data_ppdu_%u = %u\n", ++ htt_ul_user_stats_buf->user_index, ++ htt_ul_user_stats_buf->be_rx_ulofdma_data_ppdu); ++ len += scnprintf(buf + len, buf_len - len, ++ "be_rx_ulofdma_mpdu_ok_%u = %u\n", ++ htt_ul_user_stats_buf->user_index, ++ htt_ul_user_stats_buf->be_rx_ulofdma_mpdu_ok); ++ len += scnprintf(buf + len, buf_len - len, ++ "be_rx_ulofdma_mpdu_fail_%u = %u\n", ++ htt_ul_user_stats_buf->user_index, ++ htt_ul_user_stats_buf->be_rx_ulofdma_mpdu_fail); ++ len += scnprintf(buf + len, buf_len - len, ++ "be_rx_ulofdma_non_data_nusers_%u = %u\n", ++ htt_ul_user_stats_buf->user_index, ++ htt_ul_user_stats_buf->be_rx_ulofdma_non_data_nusers); ++ len += scnprintf(buf + len, buf_len - len, ++ "be_rx_ulofdma_data_nusers_%u = %u\n", ++ htt_ul_user_stats_buf->user_index, ++ htt_ul_user_stats_buf->be_rx_ulofdma_data_nusers); ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_phy_tpc_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_phy_tpc_stats_tlv *htt_stats_phy_tpc_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ int i; ++ ++ len += scnprintf(buf + len, buf_len - len, "HTT_PHY_TPC_STATS_TLV:\n"); ++ len += scnprintf(buf + len, buf_len - len, ++ "tpc_stats : pdev_id = %u\n", ++ htt_stats_phy_tpc_stats_buf->pdev_id); ++ len += scnprintf(buf + len, buf_len - len, ++ "tpc_stats : tx_power_scale = %u\n", ++ htt_stats_phy_tpc_stats_buf->tx_power_scale); ++ len += scnprintf(buf + len, buf_len - len, ++ "tpc_stats : tx_power_scale_db = %u\n", ++ htt_stats_phy_tpc_stats_buf->tx_power_scale_db); ++ len += scnprintf(buf + len, buf_len - len, ++ "tpc_stats : min_negative_tx_power = %d\n", ++ htt_stats_phy_tpc_stats_buf->min_negative_tx_power); ++ len += scnprintf(buf + len, buf_len - len, ++ "tpc_stats : reg_ctl_domain = %u\n", ++ htt_stats_phy_tpc_stats_buf->reg_ctl_domain); ++ len += scnprintf(buf + len, buf_len - len, ++ "tpc_stats : twice_max_rd_power = %u\n", ++ htt_stats_phy_tpc_stats_buf->twice_max_rd_power); ++ len += scnprintf(buf + len, buf_len - len, ++ "tpc_stats : max_tx_power = %u\n", ++ htt_stats_phy_tpc_stats_buf->max_tx_power); ++ len += scnprintf(buf + len, buf_len - len, ++ "tpc_stats : home_max_tx_power = %u\n", ++ htt_stats_phy_tpc_stats_buf->home_max_tx_power); ++ len += scnprintf(buf + len, buf_len - len, ++ "tpc_stats : psd_power = %d\n", ++ htt_stats_phy_tpc_stats_buf->psd_power); ++ len += scnprintf(buf + len, buf_len - len, ++ "tpc_stats : eirp_power = %u\n", ++ htt_stats_phy_tpc_stats_buf->eirp_power); ++ len += scnprintf(buf + len, buf_len - len, ++ "tpc_stats : power_type_6ghz = %u\n", ++ htt_stats_phy_tpc_stats_buf->power_type_6ghz); ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "tpc_stats : max_reg_allowed_power\n"); ++ for (i = 0; i < HTT_STATS_MAX_CHAINS; i++) { ++ len += scnprintf(buf + len, buf_len - len, ++ " %u:%d,", i, ++ htt_stats_phy_tpc_stats_buf->max_reg_allowed_power[i]); ++ } ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "tpc_stats : max_reg_allowed_power_6g\n"); ++ for (i = 0; i < HTT_STATS_MAX_CHAINS; i++) { ++ len += scnprintf(buf + len, buf_len - len, ++ " %u:%d,", i, ++ htt_stats_phy_tpc_stats_buf->max_reg_allowed_power_6g[i]); ++ } ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "tpc_stats : sub_band_cfreq\n"); ++ for (i = 0; i < HTT_MAX_CH_PWR_INFO_SIZE; i++) { ++ len += scnprintf(buf + len, buf_len - len, ++ " %u:%u,", i, ++ htt_stats_phy_tpc_stats_buf->sub_band_cfreq[i]); ++ } ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "tpc_stats : sub_band_txpower\n"); ++ for (i = 0; i < HTT_MAX_CH_PWR_INFO_SIZE; i++) { ++ len += scnprintf(buf + len, buf_len - len, ++ " %u:%u,", i, ++ htt_stats_phy_tpc_stats_buf->sub_band_txpower[i]); ++ } ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "\n=========================================== \n"); ++ stats_req->buf_len = len; ++} ++ + static inline void htt_print_phy_counters_tlv(const void *tag_buf, + struct debug_htt_stats_req *stats_req) + { +@@ -6984,7 +7444,27 @@ static int ath12k_dbg_htt_ext_stats_parse(struct ath12k_base *ab, + case HTT_STATS_TXBF_OFDMA_AX_STEER_STATS_TAG: + htt_print_txbf_ofdma_ax_steer_stats_tlv(tag_buf, stats_req); + break; +- ++ case HTT_STATS_TXBF_OFDMA_BE_NDPA_STATS_TAG: ++ htt_print_txbf_ofdma_be_ndpa_stats_tlv(tag_buf, stats_req); ++ break; ++ case HTT_STATS_TXBF_OFDMA_BE_NDP_STATS_TAG: ++ htt_print_txbf_ofdma_be_ndp_stats_tlv(tag_buf, stats_req); ++ break; ++ case HTT_STATS_TXBF_OFDMA_BE_BRP_STATS_TAG: ++ htt_print_txbf_ofdma_be_brp_stats_tlv(tag_buf, stats_req); ++ break; ++ case HTT_STATS_TXBF_OFDMA_BE_STEER_STATS_TAG: ++ htt_print_txbf_ofdma_be_steer_stats_tlv(tag_buf, stats_req); ++ break; ++ case HTT_STATS_DMAC_RESET_STATS_TAG: ++ htt_print_dmac_reset_stats_tlv(tag_buf, stats_req); ++ break; ++ case HTT_STATS_RX_PDEV_BE_UL_OFDMA_USER_STATS_TAG: ++ htt_print_be_ul_ofdma_user_stats(tag_buf, stats_req); ++ break; ++ case HTT_STATS_PHY_TPC_STATS_TAG: ++ htt_print_phy_tpc_stats_tlv(tag_buf, stats_req); ++ break; + default: + break; + } +diff --git a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h +index 5ebc892..c6bc306 100644 +--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h ++++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h +@@ -162,7 +162,13 @@ enum htt_tlv_tag_t { + HTT_STATS_TXBF_OFDMA_AX_NDP_STATS_TAG = 148, + HTT_STATS_TXBF_OFDMA_AX_BRP_STATS_TAG = 149, + HTT_STATS_TXBF_OFDMA_AX_STEER_STATS_TAG = 150, +- ++ HTT_STATS_TXBF_OFDMA_BE_NDPA_STATS_TAG = 151, ++ HTT_STATS_TXBF_OFDMA_BE_NDP_STATS_TAG = 152, ++ HTT_STATS_TXBF_OFDMA_BE_BRP_STATS_TAG = 153, ++ HTT_STATS_TXBF_OFDMA_BE_STEER_STATS_TAG = 154, ++ HTT_STATS_DMAC_RESET_STATS_TAG = 155, ++ HTT_STATS_RX_PDEV_BE_UL_OFDMA_USER_STATS_TAG = 156, ++ HTT_STATS_PHY_TPC_STATS_TAG = 157, + HTT_STATS_MAX_TAG, + }; + +@@ -2739,11 +2745,107 @@ struct htt_txbf_ofdma_ax_steer_stats_tlv { + struct htt_txbf_ofdma_ax_steer_stats_elem_t ax_steer[1]; + }; + ++struct htt_txbf_ofdma_be_ndpa_stats_elem_t { ++ u32 be_ofdma_ndpa_queued; ++ u32 be_ofdma_ndpa_tried; ++ u32 be_ofdma_ndpa_flushed; ++ u32 be_ofdma_ndpa_err; ++}; ++ ++struct htt_txbf_ofdma_be_ndpa_stats_tlv { ++ u32 num_elems_be_ndpa_arr; ++ u32 arr_elem_size_be_ndpa; ++ struct htt_txbf_ofdma_be_ndpa_stats_elem_t be_ndpa[1]; ++}; ++ ++struct htt_txbf_ofdma_be_ndp_stats_elem_t { ++ u32 be_ofdma_ndp_queued; ++ u32 be_ofdma_ndp_tried; ++ u32 be_ofdma_ndp_flushed; ++ u32 be_ofdma_ndp_err; ++}; ++ ++struct htt_txbf_ofdma_be_ndp_stats_tlv { ++ u32 num_elems_be_ndp_arr; ++ u32 arr_elem_size_be_ndp; ++ struct htt_txbf_ofdma_be_ndp_stats_elem_t be_ndp[1]; ++}; ++ ++struct htt_txbf_ofdma_be_brp_stats_elem_t { ++ u32 be_ofdma_brpoll_queued; ++ u32 be_ofdma_brpoll_tried; ++ u32 be_ofdma_brpoll_flushed; ++ u32 be_ofdma_brp_err; ++ u32 be_ofdma_brp_err_num_cbf_rcvd; ++}; ++ ++struct htt_txbf_ofdma_be_brp_stats_tlv { ++ u32 num_elems_be_brp_arr; ++ u32 arr_elem_size_be_brp; ++ struct htt_txbf_ofdma_be_brp_stats_elem_t be_brp[1]; ++}; ++ ++struct htt_txbf_ofdma_be_steer_stats_elem_t { ++ u32 be_ofdma_num_ppdu_steer; ++ u32 be_ofdma_num_ppdu_ol; ++ u32 be_ofdma_num_usrs_prefetch; ++ u32 be_ofdma_num_usrs_sound; ++ u32 be_ofdma_num_usrs_force_sound; ++}; ++ ++struct htt_txbf_ofdma_be_steer_stats_tlv { ++ u32 num_elems_be_steer_arr; ++ u32 arr_elem_size_be_steer; ++ struct htt_txbf_ofdma_be_steer_stats_elem_t be_steer[1]; ++}; ++ ++struct htt_dmac_reset_stats_tlv { ++ u32 reset_count; ++ u32 reset_time_lo_ms; ++ u32 reset_time_hi_ms; ++ u32 disengage_time_lo_ms; ++ u32 disengage_time_hi_ms; ++ u32 engage_time_lo_ms; ++ u32 engage_time_hi_ms; ++ u32 disengage_count; ++ u32 engage_count; ++ u32 drain_dest_ring_mask; ++}; ++ ++struct htt_rx_pdev_be_ul_ofdma_user_stats_tlv { ++ u32 user_index; ++ u32 be_rx_ulofdma_non_data_ppdu; ++ u32 be_rx_ulofdma_data_ppdu; ++ u32 be_rx_ulofdma_mpdu_ok; ++ u32 be_rx_ulofdma_mpdu_fail; ++ u32 be_rx_ulofdma_non_data_nusers; ++ u32 be_rx_ulofdma_data_nusers; ++}; ++ + #define HTT_MAX_RX_PKT_CNT 8 + #define HTT_MAX_RX_PKT_CRC_PASS_CNT 8 + #define HTT_MAX_PER_BLK_ERR_CNT 20 + #define HTT_MAX_RX_OTA_ERR_CNT 14 + #define HTT_STATS_MAX_CHAINS 8 ++#define HTT_MAX_CH_PWR_INFO_SIZE 16 ++ ++struct htt_phy_tpc_stats_tlv { ++ u32 pdev_id; ++ u32 tx_power_scale; ++ u32 tx_power_scale_db; ++ u32 min_negative_tx_power; ++ u32 reg_ctl_domain; ++ u32 max_reg_allowed_power[HTT_STATS_MAX_CHAINS]; ++ u32 max_reg_allowed_power_6g[HTT_STATS_MAX_CHAINS]; ++ u32 twice_max_rd_power; ++ u32 max_tx_power; ++ u32 home_max_tx_power; ++ u32 psd_power; ++ u32 eirp_power; ++ u32 power_type_6ghz; ++ u32 sub_band_cfreq[HTT_MAX_CH_PWR_INFO_SIZE]; ++ u32 sub_band_txpower[HTT_MAX_CH_PWR_INFO_SIZE]; ++}; + + struct htt_phy_counters_tlv { + u32 rx_ofdma_timing_err_cnt; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/704-ath12k-enable-backward-compatibility-to-support-lega.patch b/feeds/ipq95xx/mac80211/patches/qca/704-ath12k-enable-backward-compatibility-to-support-lega.patch new file mode 100644 index 000000000..ed5295ae1 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/704-ath12k-enable-backward-compatibility-to-support-lega.patch @@ -0,0 +1,111 @@ +From 3c4a011c43008e5b762abd7055dc96b00139815a Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Wed, 28 Dec 2022 14:38:08 +0530 +Subject: [PATCH] ath12k: enable backward compatibility to support legacy + architecture + +Currently, we are collecting dump through new structure +ath12k_coredump_ram_info, this structure is introduced for +MLO but it doesn't support legacy architecture. + +So, enable backward compatibility to support legacy architecture +in dump collection. + +Signed-off-by: Aaradhana Sahu +--- + drivers/net/wireless/ath/ath12k/coredump.c | 54 ++++++++++++++-------- + drivers/net/wireless/ath/ath12k/coredump.h | 2 +- + 2 files changed, 36 insertions(+), 20 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/coredump.c ++++ b/drivers/net/wireless/ath/ath12k/coredump.c +@@ -16,6 +16,8 @@ + #include "mhi.h" + #include "debug.h" + ++struct ath12k_coredump_segment_info ath12k_coredump_seg_info; ++EXPORT_SYMBOL(ath12k_coredump_seg_info); + struct ath12k_coredump_info ath12k_coredump_ram_info; + EXPORT_SYMBOL(ath12k_coredump_ram_info); + +@@ -187,6 +189,7 @@ void ath12k_coredump_download_rddm(struc + enum ath12k_fw_crash_dump_type mem_type; + struct ath12k_coredump_segment_info *chip_seg; + int dump_count; ++ struct ath12k_hw_group *ag = ab->ag; + + ath12k_mhi_coredump(mhi_ctrl, false); + +@@ -279,26 +282,49 @@ void ath12k_coredump_download_rddm(struc + + num_seg = num_seg - skip_count; + if(!ab->fw_recovery_support) { +- dump_count = ath12k_coredump_ram_info.num_chip; +- if (dump_count >= ATH12K_MAX_SOCS) { +- ath12k_err(ab, "invalid chip number %d\n", dump_count); +- return; ++ if (ag->mlo_capable) { ++ dump_count = atomic_read(&ath12k_coredump_ram_info.num_chip); ++ if (dump_count >= ATH12K_MAX_SOCS) { ++ ath12k_err(ab, "invalid chip number %d\n", ++ dump_count); ++ return; ++ } else { ++ chip_seg = &ath12k_coredump_ram_info.chip_seg_info[dump_count]; ++ chip_seg->chip_id = ar_pci->dev_id; ++ chip_seg->qrtr_id = ar_pci->ab->qmi.service_ins_id; ++ chip_seg->bus_id = pci_domain_nr(ar_pci->pdev->bus); ++ chip_seg->num_seg = num_seg; ++ chip_seg->seg = segment; ++ atomic_inc(&ath12k_coredump_ram_info.num_chip); ++ } + } else { ++ /* This part of code for 12.2 without mlo_capable=1 */ ++ dump_count = atomic_read(&ath12k_coredump_ram_info.num_chip); + chip_seg = &ath12k_coredump_ram_info.chip_seg_info[dump_count]; + chip_seg->chip_id = ar_pci->dev_id; + chip_seg->qrtr_id = ar_pci->ab->qmi.service_ins_id; + chip_seg->bus_id = pci_domain_nr(ar_pci->pdev->bus); + chip_seg->num_seg = num_seg; + chip_seg->seg = segment; +- ath12k_coredump_ram_info.num_chip++; +- +- if (ath12k_coredump_ram_info.num_chip >= ab->ag->num_started) +- BUG_ON(1); +- else +- ath12k_info(ab, +- "%d chip dump collected and waiting for partner chips\n", +- ath12k_coredump_ram_info.num_chip); ++ atomic_inc(&ath12k_coredump_ram_info.num_chip); + } ++ ++ chip_seg = &ath12k_coredump_seg_info; ++ chip_seg->chip_id = ar_pci->dev_id; ++ chip_seg->qrtr_id = ar_pci->ab->qmi.service_ins_id; ++ chip_seg->bus_id = pci_domain_nr(ar_pci->pdev->bus); ++ chip_seg->num_seg = num_seg; ++ chip_seg->seg = segment; ++ ++ if (ag->mlo_capable && ++ (atomic_read(&ath12k_coredump_ram_info.num_chip) >= ab->ag->num_started)) ++ BUG_ON(1); ++ else if (!ag->mlo_capable) ++ BUG_ON(1); ++ else ++ ath12k_info(ab, ++ "%d chip dump collected and waiting for partner chips\n", ++ atomic_read(&ath12k_coredump_ram_info.num_chip)); + } else { + /* TODO dump collection for MLO when fw_recovery set */ + ath12k_coredump_build_inline(ab, segment, num_seg); +--- a/drivers/net/wireless/ath/ath12k/coredump.h ++++ b/drivers/net/wireless/ath/ath12k/coredump.h +@@ -77,7 +77,7 @@ struct ath12k_coredump_segment_info { + }; + + struct ath12k_coredump_info { +- u32 num_chip; ++ atomic_t num_chip; + struct ath12k_coredump_segment_info chip_seg_info[ATH12K_MAX_SOCS]; + }; + diff --git a/feeds/ipq95xx/mac80211/patches/qca/672-ath12k-disable-HW-learning-intrabss-and-MEC-for-WDS.patch b/feeds/ipq95xx/mac80211/patches/qca/704-ath12k-remove-reserve-member-of-wbm-completion-struct.patch similarity index 85% rename from feeds/ipq95xx/mac80211/patches/qca/672-ath12k-disable-HW-learning-intrabss-and-MEC-for-WDS.patch rename to feeds/ipq95xx/mac80211/patches/qca/704-ath12k-remove-reserve-member-of-wbm-completion-struct.patch index 759467376..9beba905d 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/672-ath12k-disable-HW-learning-intrabss-and-MEC-for-WDS.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/704-ath12k-remove-reserve-member-of-wbm-completion-struct.patch @@ -1,6 +1,6 @@ -From 46885758e455725651182bdfa769b9a056bc9418 Mon Sep 17 00:00:00 2001 +From 841cb25c831e00535caf1d16f4cd53884a8ff9be Mon Sep 17 00:00:00 2001 From: Thiraviyam Mariyappan -Date: Thu, 15 Sep 2022 18:12:28 +0530 +Date: Tue, 20 Dec 2022 11:12:46 +0530 Subject: [PATCH] ath12k: disable HW learning, intrabss and MEC for WDS Host receives multiple peer map events from FW in the same peer id which @@ -17,10 +17,10 @@ Signed-off-by: Thiraviyam Mariyappan 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c -index 5fb1b57..415fb5e 100644 +index 734f57e..d5a52eb 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -3872,7 +3872,8 @@ ath12k_wmi_copy_resource_config(struct wmi_resource_config *wmi_cfg, +@@ -4050,7 +4050,8 @@ ath12k_wmi_copy_resource_config(struct wmi_resource_config *wmi_cfg, wmi_cfg->sched_params = tg_cfg->sched_params; wmi_cfg->twt_ap_pdev_count = tg_cfg->twt_ap_pdev_count; wmi_cfg->twt_ap_sta_count = tg_cfg->twt_ap_sta_count; @@ -31,17 +31,17 @@ index 5fb1b57..415fb5e 100644 wmi_cfg->host_service_flags |= 1 << WMI_RSRC_CFG_HOST_SVC_FLAG_REG_CC_EXT_SUPPORT_BIT; wmi_cfg->host_service_flags |= 1 << WMI_RSRC_CFG_HOST_SVC_FLAG_REO_QREF_SUPPORT_BIT; diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h -index d38610c..3a56cf0 100644 +index c85c7aa..22354db 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -2435,6 +2435,7 @@ struct wmi_init_cmd { +@@ -2479,6 +2479,7 @@ struct wmi_init_cmd { #define WMI_RSRC_CFG_HOST_SVC_FLAG_REG_CC_EXT_SUPPORT_BIT 4 #define WMI_RSRC_CFG_HOST_SVC_FLAG_REO_QREF_SUPPORT_BIT 12 #define WMI_RSRC_CFG_FLAGS2_CALC_NEXT_DTIM_COUNT_SET BIT(9) +#define WMI_RSRC_CFG_FLAGS2_INTRABSS_MEC_WDS_LEARNING_DISABLE BIT(15) + #define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5) struct wmi_resource_config { - u32 tlv_header; -- -2.7.4 +2.17.1 diff --git a/feeds/ipq95xx/mac80211/patches/qca/704-ath12k-subscribe-required-word-mask-from-rx-tlv.patch b/feeds/ipq95xx/mac80211/patches/qca/704-ath12k-subscribe-required-word-mask-from-rx-tlv.patch new file mode 100644 index 000000000..83a825f66 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/704-ath12k-subscribe-required-word-mask-from-rx-tlv.patch @@ -0,0 +1,276 @@ +From 7bd2a415c4ea574d4d49015572e1205971c26132 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Kathirvel +Date: Wed, 28 Dec 2022 16:49:11 +0530 +Subject: [PATCH] ath12k: subscribe required word mask from rx tlv + +Selectively subscribe to required qwords within msdu_end +and mpdu_start and modify rx_desc struct + +Configure the bit mask for Rx TLVs(msdu_end, mpdu_start, mpdu_end) +via registers. With these registers SW can configure to DMA the +partial TLV struct to Rx buffer. + +Each TLV type has its own register to configure the mask value. +The mask value configured in register will indicate if a particular +QWORD has to be written to rx buffer or not i.e., if Nth bit is enabled +in the mask Nth QWORD will be written and it will not be written if the +bit is disabled in mask. While 0th bit indicates weather TLV tag will be +written or not. + +Advantages of Qword subscription of TLVs +- Avoid multiple cache-line misses as the all the required fields +of the TLV are with 128 bytes. +- Memory optimization as TLVs + DATA + SHINFO can fit in 2k buffer +even for 64 bit kernel. + +Signed-off-by: Karthikeyan Kathirvel +--- + drivers/net/wireless/ath/ath12k/dp.h | 13 ++++++- + drivers/net/wireless/ath/ath12k/dp_rx.c | 19 +++++++--- + drivers/net/wireless/ath/ath12k/dp_tx.c | 19 ++++++++++ + drivers/net/wireless/ath/ath12k/hal.c | 15 ++++++++ + drivers/net/wireless/ath/ath12k/hal.h | 2 ++ + drivers/net/wireless/ath/ath12k/hw.c | 3 ++ + drivers/net/wireless/ath/ath12k/hw.h | 1 + + drivers/net/wireless/ath/ath12k/rx_desc.h | 42 +++++++++++++++++++++-- + 8 files changed, 106 insertions(+), 8 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -777,6 +777,11 @@ enum htt_stats_internal_ppdu_frametype { + #define HTT_RX_RING_SELECTION_CFG_RX_MSDU_START_OFFSET GENMASK(31, 16) + #define HTT_RX_RING_SELECTION_CFG_RX_ATTENTION_OFFSET GENMASK(15, 0) + ++#define HTT_RX_RING_SELECTION_CFG_WORD_MASK_COMPACTION_ENABLE_SET BIT(23) ++#define HTT_RX_RING_SELECTION_CFG_RX_MPDU_START_MASK GENMASK(15, 0) ++#define HTT_RX_RING_SELECTION_CFG_RX_MPDU_END_MASK GENMASK(18, 16) ++#define HTT_RX_RING_SELECTION_CFG_RX_MSDU_END_MASK GENMASK(16, 0) ++ + enum htt_rx_filter_tlv_flags { + HTT_RX_FILTER_TLV_FLAGS_MPDU_START = BIT(0), + HTT_RX_FILTER_TLV_FLAGS_MSDU_START = BIT(1), +@@ -1117,7 +1122,10 @@ struct htt_rx_ring_selection_cfg_cmd { + u32 rx_msdu_offset; + u32 rx_attn_offset; + u32 info2; +- u32 reserved[4]; ++ u32 reserved[2]; ++ u16 rx_mpdu_start_word_mask; ++ u16 rx_mpdu_end_word_mask; ++ u32 rx_msdu_end_word_mask; + u32 info3; + } __packed; + +@@ -1154,6 +1162,9 @@ struct htt_rx_ring_tlv_filter { + u32 info1; + bool drop_threshold_valid; + bool rxmon_disable; ++ u16 rx_mpdu_start_wmask; ++ u16 rx_mpdu_end_wmask; ++ u32 rx_msdu_end_wmask; + }; + + #define HTT_STATS_FRAME_CTRL_TYPE_MGMT 0x0 +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -4680,14 +4680,22 @@ int ath12k_dp_rxdma_ring_sel_config_qcn9 + tlv_filter.rx_packet_offset = hal_rx_desc_sz; + + tlv_filter.rx_mpdu_start_offset = +- ab->hw_params->hal_ops->rx_desc_get_mpdu_start_offset(); ++ ab->hw_params->hal_ops->rx_desc_get_mpdu_start_offset(); + tlv_filter.rx_msdu_end_offset = + ab->hw_params->hal_ops->rx_desc_get_msdu_end_offset(); + +- /*TODO Selectively subscribe to required qwords within msdu_end +- * and mpdu_start and setup the mask in below msg +- * and modify the rx_desc struct +- */ ++ if (ab->hw_params->compact_rx_tlv) { ++ if (ab->hw_params->hal_ops->rxdma_ring_wmask_rx_mpdu_start) ++ tlv_filter.rx_mpdu_start_wmask = ++ ab->hw_params->hal_ops->rxdma_ring_wmask_rx_mpdu_start(); ++ if (ab->hw_params->hal_ops->rxdma_ring_wmask_rx_msdu_end) ++ tlv_filter.rx_msdu_end_wmask = ++ ab->hw_params->hal_ops->rxdma_ring_wmask_rx_msdu_end(); ++ ath12k_dbg(ab, ATH12K_DBG_DATA, ++ "Configuring compact tlv masks rx_mpdu_start_wmask 0x%x rx_msdu_end_wmask 0x%x\n", ++ tlv_filter.rx_mpdu_start_wmask, tlv_filter.rx_msdu_end_wmask); ++ } ++ + ret = ath12k_dp_tx_htt_rx_filter_setup(ab, ring_id, 0, + HAL_RXDMA_BUF, + DP_RXDMA_REFILL_RING_SIZE, +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -1271,6 +1271,25 @@ int ath12k_dp_tx_htt_rx_filter_setup(str + HTT_RX_RING_SELECTION_CFG_RX_ATTENTION_OFFSET); + } + ++ if (tlv_filter->rx_mpdu_start_wmask > 0 && ++ tlv_filter->rx_msdu_end_wmask > 0) { ++ cmd->info2 |= ++ u32_encode_bits(true, ++ HTT_RX_RING_SELECTION_CFG_WORD_MASK_COMPACTION_ENABLE_SET); ++ cmd->rx_mpdu_start_word_mask = ++ u32_encode_bits(tlv_filter->rx_mpdu_start_wmask, ++ HTT_RX_RING_SELECTION_CFG_RX_MPDU_START_MASK); ++ /* mpdu_end is not used for any hardwares so far ++ * please assign it in future if any chip is ++ * using through hal ops ++ */ ++ cmd->rx_mpdu_end_word_mask = ++ u32_encode_bits(tlv_filter->rx_mpdu_end_wmask, ++ HTT_RX_RING_SELECTION_CFG_RX_MPDU_END_MASK); ++ cmd->rx_msdu_end_word_mask = ++ u32_encode_bits(tlv_filter->rx_msdu_end_wmask, ++ HTT_RX_RING_SELECTION_CFG_RX_MSDU_END_MASK); ++ } + ret = ath12k_htc_send(&ab->htc, ab->dp.eid, skb); + if (ret) + goto err_free; +--- a/drivers/net/wireless/ath/ath12k/hal.c ++++ b/drivers/net/wireless/ath/ath12k/hal.c +@@ -482,6 +482,19 @@ static u8 ath12k_hal_qcn9274_rx_desc_get + return (ipv4 || ipv6); + } + ++#define MPDU_START_WMASK 0x7FC ++#define MSDU_END_WMASK 0x13441 ++ ++static inline u16 ath12k_hal_rx_mpdu_start_wmask_get(void) ++{ ++ return MPDU_START_WMASK; ++} ++ ++static inline u32 ath12k_hal_rx_msdu_end_wmask_get(void) ++{ ++ return MSDU_END_WMASK; ++} ++ + static int ath12k_hal_srng_create_config_qcn9274(struct ath12k_base *ab) + { + struct ath12k_hal *hal = &ab->hal; +@@ -685,6 +698,8 @@ const struct hal_ops hal_qcn9274_ops = { + .dp_rx_h_is_decrypted = ath12k_hw_qcn9274_dp_rx_h_is_decrypted, + .dp_rx_h_mpdu_err = ath12k_hw_qcn9274_dp_rx_h_mpdu_err, + .rx_desc_get_ip_valid = ath12k_hal_qcn9274_rx_desc_get_ip_valid, ++ .rxdma_ring_wmask_rx_mpdu_start = ath12k_hal_rx_mpdu_start_wmask_get, ++ .rxdma_ring_wmask_rx_msdu_end = ath12k_hal_rx_msdu_end_wmask_get, + }; + + static bool ath12k_hw_wcn7850_rx_desc_get_first_msdu(struct hal_rx_desc *desc) +--- a/drivers/net/wireless/ath/ath12k/hal.h ++++ b/drivers/net/wireless/ath/ath12k/hal.h +@@ -1102,6 +1102,8 @@ struct hal_ops { + u32 (*dp_rx_h_mpdu_err)(struct hal_rx_desc *desc); + u8 (*rx_desc_get_ip_valid)(struct hal_rx_desc *desc); + const struct ath12k_hal_tcl_to_wbm_rbm_map *tcl_to_wbm_rbm_map; ++ u16 (*rxdma_ring_wmask_rx_mpdu_start)(void); ++ u32 (*rxdma_ring_wmask_rx_msdu_end)(void); + }; + + extern const struct hal_ops hal_qcn9274_ops; +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -1018,6 +1018,7 @@ static const struct ath12k_hw_params ath + .alloc_cacheable_memory = true, + .max_mlo_peer = ATH12K_MAX_MLO_PEER, + .num_local_link = 0, ++ .compact_rx_tlv = true, + }, + { + .name = "wcn7850 hw2.0", +@@ -1083,6 +1084,7 @@ static const struct ath12k_hw_params ath + .alloc_cacheable_memory = false, + .max_mlo_peer = 32, + .num_local_link = 2, ++ .compact_rx_tlv = false, + }, + { + .name = "qcn9274 hw2.0", +@@ -1148,6 +1150,7 @@ static const struct ath12k_hw_params ath + .alloc_cacheable_memory = true, + .max_mlo_peer = ATH12K_MAX_MLO_PEER, + .num_local_link = 0, ++ .compact_rx_tlv = true, + }, + }; + +--- a/drivers/net/wireless/ath/ath12k/hw.h ++++ b/drivers/net/wireless/ath/ath12k/hw.h +@@ -203,6 +203,7 @@ struct ath12k_hw_params { + bool alloc_cacheable_memory; + u16 max_mlo_peer; + u8 num_local_link; ++ bool compact_rx_tlv; + }; + + /* BRINGUP: move to dp.h */ +--- a/drivers/net/wireless/ath/ath12k/rx_desc.h ++++ b/drivers/net/wireless/ath/ath12k/rx_desc.h +@@ -119,6 +119,28 @@ enum rx_desc_decrypt_status_code { + #define RX_MPDU_START_INFO8_AUTH_TO_SEND_WDS BIT(0) + + struct rx_mpdu_start_qcn9274 { ++ __le32 info1; ++ __le32 pn[4]; ++ __le32 info2; ++ __le32 peer_meta_data; ++ __le16 info3; ++ __le16 phy_ppdu_id; ++ __le16 ast_index; ++ __le16 sw_peer_id; ++ __le32 info4; ++ __le32 info5; ++ __le32 info6; ++ __le16 frame_ctrl; ++ __le16 duration; ++ u8 addr1[ETH_ALEN]; ++ u8 addr2[ETH_ALEN]; ++ u8 addr3[ETH_ALEN]; ++ __le16 seq_ctrl; ++ u8 addr4[ETH_ALEN]; ++ __le16 qos_ctrl; ++} __packed; ++ ++struct rx_mpdu_start_wcn7850 { + __le32 info0; + __le32 reo_queue_desc_lo; + __le32 info1; +@@ -741,6 +763,22 @@ enum rx_msdu_start_reception_type { + #define RX_MSDU_END_INFO14_MSDU_DONE BIT(31) + + struct rx_msdu_end_qcn9274 { ++ __le64 msdu_end_tag; ++ __le16 sa_sw_peer_id; ++ __le16 info5; ++ __le16 sa_idx; ++ __le16 da_idx_or_sw_peer_id; ++ __le32 info10; ++ __le32 info11; ++ __le32 info12; ++ __le32 flow_id_toeplitz; ++ __le32 ppdu_start_timestamp_63_32; ++ __le32 phy_meta_data; ++ __le32 info13; ++ __le32 info14; ++} __packed; ++ ++struct rx_msdu_end_wcn7850 { + __le16 info0; + __le16 phy_ppdu_id; + __le16 ip_hdr_cksum; +@@ -1414,10 +1452,10 @@ struct rx_pkt_hdr_tlv { + + struct hal_rx_desc_wcn7850 { + __le64 msdu_end_tag; +- struct rx_msdu_end_qcn9274 msdu_end; ++ struct rx_msdu_end_wcn7850 msdu_end; + u8 rx_padding0[RX_BE_PADDING0_BYTES]; + __le64 mpdu_start_tag; +- struct rx_mpdu_start_qcn9274 mpdu_start; ++ struct rx_mpdu_start_wcn7850 mpdu_start; + struct rx_pkt_hdr_tlv pkt_hdr_tlv; + u8 msdu_payload[0]; + }; diff --git a/feeds/ipq95xx/mac80211/patches/qca/704-b-ath12k-Add-support-for-new-htt_stats.patch b/feeds/ipq95xx/mac80211/patches/qca/704-b-ath12k-Add-support-for-new-htt_stats.patch new file mode 100644 index 000000000..8121d20c5 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/704-b-ath12k-Add-support-for-new-htt_stats.patch @@ -0,0 +1,892 @@ +From 9267403c8e7384802d3e0d16a5d31182f87fdb41 Mon Sep 17 00:00:00 2001 +From: Rajat Soni +Date: Tue, 27 Dec 2022 12:15:34 +0530 +Subject: [PATCH] ath12k: Add support for new htt_stats + +ATH12K_DBG_HTT_DBG_PDEV_PUNCTURE_STATS +ATH12K_DBG_HTT_DBG_EXT_STATS_ML_PEERS_INFO +ATH12K_DBG_HTT_DBG_ODD_MANDATORY_STATS +ATH12K_DBG_HTT_DBG_PDEV_SCHED_ALGO_STATS +ATH12K_DBG_HTT_DBG_ODD_MANDATORY_MUMIMO_STATS +ATH12K_DBG_HTT_DBG_ODD_MANDATORY_MUOFDMA_STATS +ATH12K_DBG_HTT_DBG_EXT_PHY_PROF_CAL_STATS + +Signed-off-by: Rajat Soni +--- + drivers/net/wireless/ath/ath12k/debugfs.h | 7 + + .../wireless/ath/ath12k/debugfs_htt_stats.c | 320 ++++++++++++ + .../wireless/ath/ath12k/debugfs_htt_stats.h | 483 +++++++++++++++++- + 3 files changed, 809 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath12k/debugfs.h ++++ b/drivers/net/wireless/ath/ath12k/debugfs.h +@@ -62,6 +62,14 @@ enum ath12k_dbg_htt_ext_stats_type { + ATH12K_DBG_HTT_STRM_GEN_MPDUS_STATS = 43, + ATH12K_DBG_HTT_STRM_GEN_MPDUS_DETAILS_STATS = 44, + ATH12K_DBG_HTT_DBG_SOC_ERROR_STATS = 45, ++ ATH12K_DBG_HTT_DBG_PDEV_PUNCTURE_STATS = 46, ++ ATH12K_DBG_HTT_DBG_EXT_STATS_ML_PEERS_INFO = 47, ++ ATH12K_DBG_HTT_DBG_ODD_MANDATORY_STATS = 48, ++ ATH12K_DBG_HTT_DBG_PDEV_SCHED_ALGO_STATS = 49, ++ ATH12K_DBG_HTT_DBG_ODD_MANDATORY_MUMIMO_STATS = 50, ++ ATH12K_DBG_HTT_DBG_ODD_MANDATORY_MUOFDMA_STATS = 51, ++ ATH12K_DBG_HTT_DBG_EXT_PHY_PROF_CAL_STATS = 52, ++ ATH12K_DGB_HTT_DBG_EXT_STATS_PDEV_BW_MGR = 53, + + /* keep this last */ + ATH12K_DBG_HTT_NUM_EXT_STATS, +--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c +@@ -6191,6 +6191,298 @@ htt_print_phy_tpc_stats_tlv(const void * + stats_req->buf_len = len; + } + ++static const char *htt_stats_direction_abbrev(enum htt_stats_direction direction, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const char *direction_str = "unknown"; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ switch (direction) { ++ case HTT_STATS_DIRECTION_TX: ++ direction_str = "tx"; ++ break; ++ case HTT_STATS_DIRECTION_RX: ++ direction_str = "rx"; ++ break; ++ default: ++ len += scnprintf(buf + len, buf_len - len, ++ "warning: encountered unexpected HTT_STATS_DIRECTION: %d", ++ direction); ++ direction_str = "unknown"; ++ } ++ ++ stats_req->buf_len = len; ++ return direction_str; ++} ++ ++static const char *htt_stats_ppdu_type_abbrev(enum htt_stats_ppdu_type ppdu_type, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const char *ppdu_type_str = "unknown"; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ switch (ppdu_type) { ++ case HTT_STATS_PPDU_TYPE_MODE_SU: ++ ppdu_type_str = "su"; ++ break; ++ case HTT_STATS_PPDU_TYPE_DL_MU_MIMO: ++ ppdu_type_str = "dl_mu_mimo"; ++ break; ++ case HTT_STATS_PPDU_TYPE_UL_MU_MIMO: ++ ppdu_type_str = "ul_mu_mimo"; ++ break; ++ case HTT_STATS_PPDU_TYPE_DL_MU_OFDMA: ++ ppdu_type_str = "dl_mu_ofdma"; ++ break; ++ case HTT_STATS_PPDU_TYPE_UL_MU_OFDMA: ++ ppdu_type_str = "ul_mu_ofdma"; ++ break; ++ default: ++ len += scnprintf(buf + len, buf_len - len, ++ "warning: encountered unexpected HTT_STATS_PPDU_TYPE: %d", ++ ppdu_type); ++ } ++ ++ stats_req->buf_len = len; ++ return ppdu_type_str; ++} ++ ++static const char *htt_stats_pream_type_abbrev(enum htt_stats_param_type pream_type, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const char *pream_type_str = "unknown"; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ switch (pream_type) { ++ case HTT_STATS_PREAM_OFDM: ++ pream_type_str = "ofdm"; ++ break; ++ case HTT_STATS_PREAM_CCK: ++ pream_type_str = "cck"; ++ break; ++ case HTT_STATS_PREAM_HT: ++ pream_type_str = "ht"; ++ break; ++ case HTT_STATS_PREAM_VHT: ++ pream_type_str = "ac"; ++ break; ++ case HTT_STATS_PREAM_HE: ++ pream_type_str = "ax"; ++ break; ++ case HTT_STATS_PREAM_EHT: ++ pream_type_str = "be"; ++ break; ++ default: ++ len += scnprintf(buf + len, buf_len - len, ++ "warning: encountered unexpected HTT_STATS_PREAM_TYPE: %d", ++ pream_type); ++ } ++ ++ stats_req->buf_len = len; ++ return pream_type_str; ++} ++ ++static inline void ++htt_print_puncture_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_pdev_puncture_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ int i; ++ const char *direction_str = NULL; ++ const char *preamble_str = NULL; ++ const char *ppdu_type_str = NULL; ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "HTT_PDEV_PUNCTURE_STATS_TLV:\n"); ++ ++ direction_str = htt_stats_direction_abbrev(htt_stats_buf->direction, stats_req); ++ ppdu_type_str = htt_stats_ppdu_type_abbrev(htt_stats_buf->ppdu_type, stats_req); ++ preamble_str = htt_stats_pream_type_abbrev(htt_stats_buf->preamble, stats_req); ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "mac_id = %u\n", ++ HTT_PDEV_PUNCTURE_STATS_MAC_ID_GET(htt_stats_buf->mac_id__word)); ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "%s_%s_%s_last_used_pattern_mask: 0x%08x\n", ++ direction_str, preamble_str, ppdu_type_str, ++ htt_stats_buf->last_used_pattern_mask); ++ ++ for (i = 0; (i < HTT_PUNCTURE_STATS_MAX_SUBBAND_COUNT) && ++ (i < htt_stats_buf->subband_count); ++i) { ++ len += scnprintf(buf + len, buf_len - len, ++ "%s_%s_%s_num_subbands_used_cnt_%02d: %u\n", ++ direction_str, preamble_str, ppdu_type_str, ++ i + 1, htt_stats_buf->num_subbands_used_cnt[i]); ++ } ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_ml_peer_details_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_ml_peer_details_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "HTT_ML_PEER_DETAILS_TLV:\n"); ++ len += scnprintf(buf + len, buf_len - len, ++ "========================\n"); ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "remote_mld_mac_addr = %02x:%02x:%02x:%02x:%02x:%02x\n", ++ (htt_stats_buf->remote_mld_mac_addr.mac_addr_l32 & 0xFF), ++ (htt_stats_buf->remote_mld_mac_addr.mac_addr_l32 & 0xFF00) >> 8, ++ (htt_stats_buf->remote_mld_mac_addr.mac_addr_l32 & 0xFF0000) >> 16, ++ (htt_stats_buf->remote_mld_mac_addr.mac_addr_l32 & 0xFF000000) >> 24, ++ (htt_stats_buf->remote_mld_mac_addr.mac_addr_h16 & 0xFF), ++ (htt_stats_buf->remote_mld_mac_addr.mac_addr_h16 & 0xFF00) >> 8); ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "ml_peer_flags = 0x%x\n", ++ htt_stats_buf->ml_peer_flags); ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "num_links = %u\n", ++ HTT_ML_PEER_DETAILS_NUM_LINKS_GET(htt_stats_buf->msg_dword_1)); ++ len += scnprintf(buf + len, buf_len - len, ++ "ml_peer_id = %u\n", ++ HTT_ML_PEER_DETAILS_ML_PEER_ID_GET(htt_stats_buf->msg_dword_1)); ++ len += scnprintf(buf + len, buf_len - len, ++ "primary_link_idx = %u\n", ++ HTT_ML_PEER_DETAILS_PRIMARY_LINK_IDX_GET(htt_stats_buf->msg_dword_1)); ++ len += scnprintf(buf + len, buf_len - len, ++ "primary_chip_id = %u\n", ++ HTT_ML_PEER_DETAILS_PRIMARY_CHIP_ID_GET(htt_stats_buf->msg_dword_1)); ++ len += scnprintf(buf + len, buf_len - len, ++ "link_init_count = %u\n", ++ HTT_ML_PEER_DETAILS_LINK_INIT_COUNT_GET(htt_stats_buf->msg_dword_1)); ++ len += scnprintf(buf + len, buf_len - len, ++ "non_str = %u\n", ++ HTT_ML_PEER_DETAILS_NON_STR_GET(htt_stats_buf->msg_dword_1)); ++ len += scnprintf(buf + len, buf_len - len, ++ "emlsr = %u\n", ++ HTT_ML_PEER_DETAILS_EMLSR_GET(htt_stats_buf->msg_dword_1)); ++ len += scnprintf(buf + len, buf_len - len, ++ "is_stako = %u\n", ++ HTT_ML_PEER_DETAILS_IS_STA_KO_GET(htt_stats_buf->msg_dword_1)); ++ len += scnprintf(buf + len, buf_len - len, ++ "num_local_links = %u\n", ++ HTT_ML_PEER_DETAILS_NUM_LOCAL_LINKS_GET(htt_stats_buf->msg_dword_1)); ++ len += scnprintf(buf + len, buf_len - len, ++ "allocated = %u\n", ++ HTT_ML_PEER_DETAILS_ALLOCATED_GET(htt_stats_buf->msg_dword_1)); ++ len += scnprintf(buf + len, buf_len - len, ++ "participating_chips_bitmap = 0x%x\n", ++ HTT_ML_PEER_DETAILS_PARTICIPATING_CHIPS_BITMAP_GET( ++ htt_stats_buf->msg_dword_2)); ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "=========================================== \n"); ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_ml_peer_ext_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_ml_peer_ext_details_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += scnprintf(buf + len, buf_len - len, "HTT_ML_PEER_EXT_TLV:\n"); ++ len += scnprintf(buf + len, buf_len - len, "====================\n"); ++ len += scnprintf(buf + len, buf_len - len, ++ "peer_assoc_ipc_recvd = %u\n", ++ HTT_ML_PEER_EXT_DETAILS_PEER_ASSOC_IPC_RECVD_GET( ++ htt_stats_buf->msg_dword_1)); ++ len += scnprintf(buf + len, buf_len - len, ++ "sched_peer_delete_recvd = %u\n", ++ HTT_ML_PEER_EXT_DETAILS_SCHED_PEER_DELETE_RECVD_GET( ++ htt_stats_buf->msg_dword_1)); ++ len += scnprintf(buf + len, buf_len - len, ++ "mld_ast_index = %u\n", ++ HTT_ML_PEER_EXT_DETAILS_MLD_AST_INDEX_GET(htt_stats_buf->msg_dword_1)); ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "=========================================== \n"); ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_ml_link_info_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_ml_link_info_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += scnprintf(buf + len, buf_len - len, "HTT_ML_LINK_INFO_TLV:\n"); ++ len += scnprintf(buf + len, buf_len - len, "=====================\n"); ++ len += scnprintf(buf + len, buf_len - len, ++ "valid = %u\n", ++ HTT_ML_LINK_INFO_VALID_GET(htt_stats_buf->msg_dword_1)); ++ len += scnprintf(buf + len, buf_len - len, ++ "active = %u\n", ++ HTT_ML_LINK_INFO_ACTIVE_GET(htt_stats_buf->msg_dword_1)); ++ len += scnprintf(buf + len, buf_len - len, ++ "primary = %u\n", ++ HTT_ML_LINK_INFO_PRIMARY_GET(htt_stats_buf->msg_dword_1)); ++ len += scnprintf(buf + len, buf_len - len, ++ "assoc_link = %u\n", ++ HTT_ML_LINK_INFO_ASSOC_LINK_GET(htt_stats_buf->msg_dword_1)); ++ len += scnprintf(buf + len, buf_len - len, ++ "chip_id = %u\n", ++ HTT_ML_LINK_INFO_CHIP_ID_GET(htt_stats_buf->msg_dword_1)); ++ len += scnprintf(buf + len, buf_len - len, ++ "ieee_link_id = %u\n", ++ HTT_ML_LINK_INFO_IEEE_LINK_ID_GET(htt_stats_buf->msg_dword_1)); ++ len += scnprintf(buf + len, buf_len - len, ++ "hw_link_id = %u\n", ++ HTT_ML_LINK_INFO_HW_LINK_ID_GET(htt_stats_buf->msg_dword_1)); ++ len += scnprintf(buf + len, buf_len - len, ++ "logical_link_id = %u\n", ++ HTT_ML_LINK_INFO_LOGICAL_LINK_ID_GET(htt_stats_buf->msg_dword_1)); ++ len += scnprintf(buf + len, buf_len - len, ++ "master_link = %u\n", ++ HTT_ML_LINK_INFO_MASTER_LINK_GET(htt_stats_buf->msg_dword_1)); ++ len += scnprintf(buf + len, buf_len - len, ++ "anchor_link = %u\n", ++ HTT_ML_LINK_INFO_ANCHOR_LINK_GET(htt_stats_buf->msg_dword_1)); ++ len += scnprintf(buf + len, buf_len - len, ++ "initialized = %u\n", ++ HTT_ML_LINK_INFO_INITIALIZED_GET(htt_stats_buf->msg_dword_1)); ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "sw_peer_id = %u\n", ++ HTT_ML_LINK_INFO_SW_PEER_ID_GET(htt_stats_buf->msg_dword_2)); ++ len += scnprintf(buf + len, buf_len - len, ++ "vdev_id = %u\n", ++ HTT_ML_LINK_INFO_VDEV_ID_GET(htt_stats_buf->msg_dword_2)); ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "primary_tid_mask = 0x%x\n", ++ htt_stats_buf->primary_tid_mask); ++ len += scnprintf(buf + len, buf_len - len, ++ "=========================================== \n"); ++ stats_req->buf_len = len; ++} ++ + static inline void htt_print_phy_counters_tlv(const void *tag_buf, + struct debug_htt_stats_req *stats_req) + { +@@ -7459,6 +7751,18 @@ static int ath12k_dbg_htt_ext_stats_pars + case HTT_STATS_PHY_TPC_STATS_TAG: + htt_print_phy_tpc_stats_tlv(tag_buf, stats_req); + break; ++ case HTT_STATS_PDEV_PUNCTURE_STATS_TAG: ++ htt_print_puncture_stats_tlv(tag_buf, stats_req); ++ break; ++ case HTT_STATS_ML_PEER_DETAILS_TAG: ++ htt_print_ml_peer_details_stats_tlv(tag_buf, stats_req); ++ break; ++ case HTT_STATS_ML_PEER_EXT_DETAILS_TAG: ++ htt_print_ml_peer_ext_stats_tlv(tag_buf, stats_req); ++ break; ++ case HTT_STATS_ML_LINK_INFO_DETAILS_TAG: ++ htt_print_ml_link_info_stats_tlv(tag_buf, stats_req); ++ break; + default: + break; + } +--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h ++++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h +@@ -169,6 +169,24 @@ enum htt_tlv_tag_t { + HTT_STATS_DMAC_RESET_STATS_TAG = 155, + HTT_STATS_RX_PDEV_BE_UL_OFDMA_USER_STATS_TAG = 156, + HTT_STATS_PHY_TPC_STATS_TAG = 157, ++ HTT_STATS_PDEV_PUNCTURE_STATS_TAG = 158, ++ HTT_STATS_ML_PEER_DETAILS_TAG = 159, ++ HTT_STATS_ML_PEER_EXT_DETAILS_TAG = 160, ++ HTT_STATS_ML_LINK_INFO_DETAILS_TAG = 161, ++ HTT_STATS_TX_PDEV_PPDU_DUR_TAG = 162, ++ HTT_STATS_RX_PDEV_PPDU_DUR_TAG = 163, ++ HTT_STATS_ODD_PDEV_MANDATORY_TAG = 164, ++ HTT_STATS_PDEV_SCHED_ALGO_OFDMA_STATS_TAG = 165, ++ HTT_DBG_ODD_MANDATORY_MUMIMO_TAG = 166, ++ HTT_DBG_ODD_MANDATORY_MUOFDMA_TAG = 167, ++ HTT_STATS_LATENCY_PROF_CAL_STATS_TAG = 168, ++ HTT_STATS_TX_PDEV_MUEDCA_PARAMS_STATS_TAG = 169, ++ HTT_STATS_PDEV_BW_MGR_STATS_TAG = 170, ++ HTT_STATS_TX_PDEV_AP_EDCA_PARAMS_STATS_TAG = 171, ++ HTT_STATS_TXBF_OFDMA_AX_STEER_MPDU_STATS_TAG = 172, ++ HTT_STATS_TXBF_OFDMA_BE_STEER_MPDU_STATS_TAG = 173, ++ HTT_STATS_PEER_AX_OFDMA_STATS_TAG = 174, ++ HTT_STATS_TX_PDEV_MU_EDCA_PARAMS_STATS_TAG = 175, + HTT_STATS_MAX_TAG, + }; + +@@ -573,12 +591,25 @@ enum htt_stats_param_type { + HTT_STATS_PREAM_HT, + HTT_STATS_PREAM_VHT, + HTT_STATS_PREAM_HE, +- HTT_STATS_PREAM_RSVD, ++ HTT_STATS_PREAM_EHT, + HTT_STATS_PREAM_RSVD1, + + HTT_STATS_PREAM_COUNT, + }; + ++enum htt_stats_direction { ++ HTT_STATS_DIRECTION_TX, ++ HTT_STATS_DIRECTION_RX, ++}; ++ ++enum htt_stats_ppdu_type { ++ HTT_STATS_PPDU_TYPE_MODE_SU, ++ HTT_STATS_PPDU_TYPE_DL_MU_MIMO, ++ HTT_STATS_PPDU_TYPE_UL_MU_MIMO, ++ HTT_STATS_PPDU_TYPE_DL_MU_OFDMA, ++ HTT_STATS_PPDU_TYPE_UL_MU_OFDMA, ++}; ++ + #define HTT_TX_PEER_STATS_NUM_MCS_COUNTERS 12 + #define HTT_TX_PEER_STATS_NUM_EXTRA_MCS_COUNTERS 2 + #define HTT_TX_PEER_STATS_NUM_GI_COUNTERS 4 +@@ -2828,6 +2859,19 @@ struct htt_rx_pdev_be_ul_ofdma_user_stat + #define HTT_MAX_RX_OTA_ERR_CNT 14 + #define HTT_STATS_MAX_CHAINS 8 + #define HTT_MAX_CH_PWR_INFO_SIZE 16 ++#define HTT_PUNCTURE_STATS_MAX_SUBBAND_COUNT 32 ++ ++#define HTT_PDEV_PUNCTURE_STATS_MAC_ID_M 0x000000ff ++#define HTT_PDEV_PUNCTURE_STATS_MAC_ID_S 0 ++ ++#define HTT_PDEV_PUNCTURE_STATS_MAC_ID_GET(_var) \ ++ (((_var) & HTT_PDEV_PUNCTURE_STATS_MAC_ID_M) >> \ ++ HTT_PDEV_PUNCTURE_STATS_MAC_ID_S) ++#define HTT_PDEV_PUNCTURE_STATS_MAC_ID_SET(_var, _val) \ ++ do { \ ++ HTT_CHECK_SET_VAL(HTT_PDEV_PUNCTURE_STATS_MAC_ID, _val); \ ++ ((_var) |= ((_val) << HTT_PDEV_PUNCTURE_STATS_MAC_ID_S)); \ ++ } while (0) + + struct htt_phy_tpc_stats_tlv { + u32 pdev_id; +@@ -2847,6 +2891,449 @@ struct htt_phy_tpc_stats_tlv { + u32 sub_band_txpower[HTT_MAX_CH_PWR_INFO_SIZE]; + }; + ++struct htt_pdev_puncture_stats_tlv { ++ union { ++ struct { ++ u32 mac_id:8, ++ reserved:24; ++ }; ++ u32 mac_id__word; ++ }; ++ u32 direction; ++ u32 preamble; ++ u32 ppdu_type; ++ u32 subband_count; ++ u32 last_used_pattern_mask; ++ u32 num_subbands_used_cnt[HTT_PUNCTURE_STATS_MAX_SUBBAND_COUNT]; ++}; ++ ++#define HTT_ML_PEER_DETAILS_NUM_LINKS_M 0x00000003 ++#define HTT_ML_PEER_DETAILS_NUM_LINKS_S 0 ++#define HTT_ML_PEER_DETAILS_ML_PEER_ID_M 0x00003FFC ++#define HTT_ML_PEER_DETAILS_ML_PEER_ID_S 2 ++#define HTT_ML_PEER_DETAILS_PRIMARY_LINK_IDX_M 0x0001C000 ++#define HTT_ML_PEER_DETAILS_PRIMARY_LINK_IDX_S 14 ++#define HTT_ML_PEER_DETAILS_PRIMARY_CHIP_ID_M 0x00060000 ++#define HTT_ML_PEER_DETAILS_PRIMARY_CHIP_ID_S 17 ++#define HTT_ML_PEER_DETAILS_LINK_INIT_COUNT_M 0x00380000 ++#define HTT_ML_PEER_DETAILS_LINK_INIT_COUNT_S 19 ++#define HTT_ML_PEER_DETAILS_NON_STR_M 0x00400000 ++#define HTT_ML_PEER_DETAILS_NON_STR_S 22 ++#define HTT_ML_PEER_DETAILS_EMLSR_M 0x00800000 ++#define HTT_ML_PEER_DETAILS_EMLSR_S 23 ++#define HTT_ML_PEER_DETAILS_IS_STA_KO_M 0x01000000 ++#define HTT_ML_PEER_DETAILS_IS_STA_KO_S 24 ++#define HTT_ML_PEER_DETAILS_NUM_LOCAL_LINKS_M 0x06000000 ++#define HTT_ML_PEER_DETAILS_NUM_LOCAL_LINKS_S 25 ++#define HTT_ML_PEER_DETAILS_ALLOCATED_M 0x08000000 ++#define HTT_ML_PEER_DETAILS_ALLOCATED_S 27 ++ ++#define HTT_ML_PEER_DETAILS_PARTICIPATING_CHIPS_BITMAP_M 0x000000ff ++#define HTT_ML_PEER_DETAILS_PARTICIPATING_CHIPS_BITMAP_S 0 ++ ++#define HTT_ML_PEER_DETAILS_NUM_LINKS_GET(_var) \ ++ (((_var) & HTT_ML_PEER_DETAILS_NUM_LINKS_M) >> \ ++ HTT_ML_PEER_DETAILS_NUM_LINKS_S) ++ ++#define HTT_ML_PEER_DETAILS_NUM_LINKS_SET(_var, _val) \ ++ do { \ ++ HTT_CHECK_SET_VAL(HTT_ML_PEER_DETAILS_NUM_LINKS, _val); \ ++ ((_var) &= ~(HTT_ML_PEER_DETAILS_NUM_LINKS_M)); \ ++ ((_var) |= ((_val) << HTT_ML_PEER_DETAILS_NUM_LINKS_S)); \ ++ } while (0) ++ ++#define HTT_ML_PEER_DETAILS_ML_PEER_ID_GET(_var) \ ++ (((_var) & HTT_ML_PEER_DETAILS_ML_PEER_ID_M) >> \ ++ HTT_ML_PEER_DETAILS_ML_PEER_ID_S) ++ ++#define HTT_ML_PEER_DETAILS_ML_PEER_ID_SET(_var, _val) \ ++ do { \ ++ HTT_CHECK_SET_VAL(HTT_ML_PEER_DETAILS_ML_PEER_ID, _val); \ ++ ((_var) &= ~(HTT_ML_PEER_DETAILS_ML_PEER_ID_M)); \ ++ ((_var) |= ((_val) << HTT_ML_PEER_DETAILS_ML_PEER_ID_S)); \ ++ } while (0) ++ ++#define HTT_ML_PEER_DETAILS_PRIMARY_LINK_IDX_GET(_var) \ ++ (((_var) & HTT_ML_PEER_DETAILS_PRIMARY_LINK_IDX_M) >> \ ++ HTT_ML_PEER_DETAILS_PRIMARY_LINK_IDX_S) ++ ++#define HTT_ML_PEER_DETAILS_PRIMARY_LINK_IDX_SET(_var, _val) \ ++ do { \ ++ HTT_CHECK_SET_VAL(HTT_ML_PEER_DETAILS_PRIMARY_LINK_IDX, _val); \ ++ ((_var) &= ~(HTT_ML_PEER_DETAILS_PRIMARY_LINK_IDX_M)); \ ++ ((_var) |= ((_val) << HTT_ML_PEER_DETAILS_PRIMARY_LINK_IDX_S)); \ ++ } while (0) ++#define HTT_ML_PEER_DETAILS_PRIMARY_CHIP_ID_GET(_var) \ ++ (((_var) & HTT_ML_PEER_DETAILS_PRIMARY_CHIP_ID_M) >> \ ++ HTT_ML_PEER_DETAILS_PRIMARY_CHIP_ID_S) ++ ++#define HTT_ML_PEER_DETAILS_PRIMARY_CHIP_ID_SET(_var, _val) \ ++ do { \ ++ HTT_CHECK_SET_VAL(HTT_ML_PEER_DETAILS_PRIMARY_CHIP_ID, _val); \ ++ ((_var) &= ~(HTT_ML_PEER_DETAILS_PRIMARY_CHIP_ID_M)); \ ++ ((_var) |= ((_val) << HTT_ML_PEER_DETAILS_PRIMARY_CHIP_ID_S)); \ ++ } while (0) ++ ++#define HTT_ML_PEER_DETAILS_LINK_INIT_COUNT_GET(_var) \ ++ (((_var) & HTT_ML_PEER_DETAILS_LINK_INIT_COUNT_M) >> \ ++ HTT_ML_PEER_DETAILS_LINK_INIT_COUNT_S) ++ ++#define HTT_ML_PEER_DETAILS_LINK_INIT_COUNT_SET(_var, _val) \ ++ do { \ ++ HTT_CHECK_SET_VAL(HTT_ML_PEER_DETAILS_LINK_INIT_COUNT, _val); \ ++ ((_var) &= ~(HTT_ML_PEER_DETAILS_LINK_INIT_COUNT_M)); \ ++ ((_var) |= ((_val) << HTT_ML_PEER_DETAILS_LINK_INIT_COUNT_S)); \ ++ } while (0) ++ ++#define HTT_ML_PEER_DETAILS_NON_STR_GET(_var) \ ++ (((_var) & HTT_ML_PEER_DETAILS_NON_STR_M) >> \ ++ HTT_ML_PEER_DETAILS_NON_STR_S) ++ ++#define HTT_ML_PEER_DETAILS_NON_STR_SET(_var, _val) \ ++ do { \ ++ HTT_CHECK_SET_VAL(HTT_ML_PEER_DETAILS_NON_STR, _val); \ ++ ((_var) &= ~(HTT_ML_PEER_DETAILS_NON_STR_M)); \ ++ ((_var) |= ((_val) << HTT_ML_PEER_DETAILS_NON_STR_S)); \ ++ } while (0) ++ ++#define HTT_ML_PEER_DETAILS_EMLSR_GET(_var) \ ++ (((_var) & HTT_ML_PEER_DETAILS_EMLSR_M) >> \ ++ HTT_ML_PEER_DETAILS_EMLSR_S) ++ ++#define HTT_ML_PEER_DETAILS_EMLSR_SET(_var, _val) \ ++ do { \ ++ HTT_CHECK_SET_VAL(HTT_ML_PEER_DETAILS_EMLSR, _val); \ ++ ((_var) &= ~(HTT_ML_PEER_DETAILS_EMLSR_M)); \ ++ ((_var) |= ((_val) << HTT_ML_PEER_DETAILS_EMLSR_S)); \ ++ } while (0) ++ ++#define HTT_ML_PEER_DETAILS_IS_STA_KO_GET(_var) \ ++ (((_var) & HTT_ML_PEER_DETAILS_IS_STA_KO_M) >> \ ++ HTT_ML_PEER_DETAILS_IS_STA_KO_S) ++ ++#define HTT_ML_PEER_DETAILS_IS_STA_KO_SET(_var, _val) \ ++ do { \ ++ HTT_CHECK_SET_VAL(HTT_ML_PEER_DETAILS_IS_STA_KO, _val); \ ++ ((_var) &= ~(HTT_ML_PEER_DETAILS_IS_STA_KO_M)); \ ++ ((_var) |= ((_val) << HTT_ML_PEER_DETAILS_IS_STA_KO_S)); \ ++ } while (0) ++ ++#define HTT_ML_PEER_DETAILS_NUM_LOCAL_LINKS_GET(_var) \ ++ (((_var) & HTT_ML_PEER_DETAILS_NUM_LOCAL_LINKS_M) >> \ ++ HTT_ML_PEER_DETAILS_NUM_LOCAL_LINKS_S) ++#define HTT_ML_PEER_DETAILS_NUM_LOCAL_LINKS_SET(_var, _val) \ ++ do { \ ++ HTT_CHECK_SET_VAL(HTT_ML_PEER_DETAILS_NUM_LOCAL_LINKS, _val); \ ++ ((_var) &= ~(HTT_ML_PEER_DETAILS_NUM_LOCAL_LINKS_M)); \ ++ ((_var) |= ((_val) << HTT_ML_PEER_DETAILS_NUM_LOCAL_LINKS_S)); \ ++ } while (0) ++ ++#define HTT_ML_PEER_DETAILS_ALLOCATED_GET(_var) \ ++ (((_var) & HTT_ML_PEER_DETAILS_ALLOCATED_M) >> \ ++ HTT_ML_PEER_DETAILS_ALLOCATED_S) ++ ++#define HTT_ML_PEER_DETAILS_ALLOCATED_SET(_var, _val) \ ++ do { \ ++ HTT_CHECK_SET_VAL(HTT_ML_PEER_DETAILS_ALLOCATED, _val); \ ++ ((_var) &= ~(HTT_ML_PEER_DETAILS_ALLOCATED_M)); \ ++ ((_var) |= ((_val) << HTT_ML_PEER_DETAILS_ALLOCATED_S)); \ ++ } while (0) ++ ++#define HTT_ML_PEER_DETAILS_PARTICIPATING_CHIPS_BITMAP_GET(_var) \ ++ (((_var) & HTT_ML_PEER_DETAILS_PARTICIPATING_CHIPS_BITMAP_M) >> \ ++ HTT_ML_PEER_DETAILS_PARTICIPATING_CHIPS_BITMAP_S) ++ ++#define HTT_ML_PEER_DETAILS_PARTICIPATING_CHIPS_BITMAP_SET(_var, _val) \ ++ do { \ ++ HTT_CHECK_SET_VAL(HTT_ML_PEER_DETAILS_PARTICIPATING_CHIPS_BITMAP, _val); \ ++ ((_var) &= ~(HTT_ML_PEER_DETAILS_PARTICIPATING_CHIPS_BITMAP_M)); \ ++ ((_var) |= ((_val) << HTT_ML_PEER_DETAILS_PARTICIPATING_CHIPS_BITMAP_S)); \ ++ } while (0) ++ ++struct htt_ml_peer_details_tlv { ++ struct htt_mac_addr remote_mld_mac_addr; ++ union { ++ struct { ++ u32 num_links:2, ++ ml_peer_id:12, ++ primary_link_idx:3, ++ primary_chip_id:2, ++ link_init_count:3, ++ non_str:1, ++ emlsr:1, ++ is_sta_ko:1, ++ num_local_links:2, ++ allocated:1, ++ reserved:4; ++ }; ++ u32 msg_dword_1; ++ }; ++ ++ union { ++ struct { ++ u32 participating_chips_bitmap:8, ++ reserved1:24; ++ }; ++ u32 msg_dword_2; ++ }; ++ ++ u32 ml_peer_flags; ++}; ++ ++#define HTT_ML_PEER_EXT_DETAILS_PEER_ASSOC_IPC_RECVD_M 0x0000003F ++#define HTT_ML_PEER_EXT_DETAILS_PEER_ASSOC_IPC_RECVD_S 0 ++#define HTT_ML_PEER_EXT_DETAILS_SCHED_PEER_DELETE_RECVD_M 0x00000FC0 ++#define HTT_ML_PEER_EXT_DETAILS_SCHED_PEER_DELETE_RECVD_S 6 ++#define HTT_ML_PEER_EXT_DETAILS_MLD_AST_INDEX_M 0x0FFFF000 ++#define HTT_ML_PEER_EXT_DETAILS_MLD_AST_INDEX_S 12 ++ ++#define HTT_ML_PEER_EXT_DETAILS_PEER_ASSOC_IPC_RECVD_GET(_var) \ ++ (((_var) & HTT_ML_PEER_EXT_DETAILS_PEER_ASSOC_IPC_RECVD_M) >> \ ++ HTT_ML_PEER_EXT_DETAILS_PEER_ASSOC_IPC_RECVD_S) ++ ++#define HTT_ML_PEER_EXT_DETAILS_PEER_ASSOC_IPC_RECVD_SET(_var, _val) \ ++ do { \ ++ HTT_CHECK_SET_VAL(HTT_ML_PEER_EXT_DETAILS_PEER_ASSOC_IPC_RECVD, _val); \ ++ ((_var) &= ~(HTT_ML_PEER_EXT_DETAILS_PEER_ASSOC_IPC_RECVD_M)); \ ++ ((_var) |= ((_val) << HTT_ML_PEER_EXT_DETAILS_PEER_ASSOC_IPC_RECVD_S)); \ ++ } while (0) ++ ++#define HTT_ML_PEER_EXT_DETAILS_SCHED_PEER_DELETE_RECVD_GET(_var) \ ++ (((_var) & HTT_ML_PEER_EXT_DETAILS_SCHED_PEER_DELETE_RECVD_M) >> \ ++ HTT_ML_PEER_EXT_DETAILS_SCHED_PEER_DELETE_RECVD_S) ++ ++#define HTT_ML_PEER_EXT_DETAILS_SCHED_PEER_DELETE_RECVD_SET(_var, _val) \ ++ do { \ ++ HTT_CHECK_SET_VAL(HTT_ML_PEER_EXT_DETAILS_SCHED_PEER_DELETE_RECVD, _val); \ ++ ((_var) &= ~(HTT_ML_PEER_EXT_DETAILS_SCHED_PEER_DELETE_RECVD_M)); \ ++ ((_var) |= ((_val) << HTT_ML_PEER_EXT_DETAILS_SCHED_PEER_DELETE_RECVD_S)); \ ++ } while (0) ++ ++#define HTT_ML_PEER_EXT_DETAILS_MLD_AST_INDEX_GET(_var) \ ++ (((_var) & HTT_ML_PEER_EXT_DETAILS_MLD_AST_INDEX_M) >> \ ++ HTT_ML_PEER_EXT_DETAILS_MLD_AST_INDEX_S) ++ ++#define HTT_ML_PEER_EXT_DETAILS_MLD_AST_INDEX_SET(_var, _val) \ ++ do { \ ++ HTT_CHECK_SET_VAL(HTT_ML_PEER_EXT_DETAILS_MLD_AST_INDEX, _val); \ ++ ((_var) &= ~(HTT_ML_PEER_EXT_DETAILS_MLD_AST_INDEX_M)); \ ++ ((_var) |= ((_val) << HTT_ML_PEER_EXT_DETAILS_MLD_AST_INDEX_S)); \ ++ } while (0) ++ ++struct htt_ml_peer_ext_details_tlv { ++ union { ++ struct { ++ u32 peer_assoc_ipc_recvd:6, ++ sched_peer_delete_recvd:6, ++ mld_ast_index:16, ++ reserved:4; ++ }; ++ u32 msg_dword_1; ++ }; ++}; ++ ++#define HTT_ML_LINK_INFO_VALID_M 0x00000001 ++#define HTT_ML_LINK_INFO_VALID_S 0 ++#define HTT_ML_LINK_INFO_ACTIVE_M 0x00000002 ++#define HTT_ML_LINK_INFO_ACTIVE_S 1 ++#define HTT_ML_LINK_INFO_PRIMARY_M 0x00000004 ++#define HTT_ML_LINK_INFO_PRIMARY_S 2 ++#define HTT_ML_LINK_INFO_ASSOC_LINK_M 0x00000008 ++#define HTT_ML_LINK_INFO_ASSOC_LINK_S 3 ++#define HTT_ML_LINK_INFO_CHIP_ID_M 0x00000070 ++#define HTT_ML_LINK_INFO_CHIP_ID_S 4 ++#define HTT_ML_LINK_INFO_IEEE_LINK_ID_M 0x00007F80 ++#define HTT_ML_LINK_INFO_IEEE_LINK_ID_S 7 ++#define HTT_ML_LINK_INFO_HW_LINK_ID_M 0x00038000 ++#define HTT_ML_LINK_INFO_HW_LINK_ID_S 15 ++#define HTT_ML_LINK_INFO_LOGICAL_LINK_ID_M 0x000C0000 ++#define HTT_ML_LINK_INFO_LOGICAL_LINK_ID_S 18 ++#define HTT_ML_LINK_INFO_MASTER_LINK_M 0x00100000 ++#define HTT_ML_LINK_INFO_MASTER_LINK_S 20 ++#define HTT_ML_LINK_INFO_ANCHOR_LINK_M 0x00200000 ++#define HTT_ML_LINK_INFO_ANCHOR_LINK_S 21 ++#define HTT_ML_LINK_INFO_INITIALIZED_M 0x00400000 ++#define HTT_ML_LINK_INFO_INITIALIZED_S 22 ++ ++#define HTT_ML_LINK_INFO_SW_PEER_ID_M 0x0000ffff ++#define HTT_ML_LINK_INFO_SW_PEER_ID_S 0 ++#define HTT_ML_LINK_INFO_VDEV_ID_M 0x00ff0000 ++#define HTT_ML_LINK_INFO_VDEV_ID_S 16 ++ ++#define HTT_ML_LINK_INFO_VALID_GET(_var) \ ++ (((_var) & HTT_ML_LINK_INFO_VALID_M) >> \ ++ HTT_ML_LINK_INFO_VALID_S) ++ ++#define HTT_ML_LINK_INFO_VALID_SET(_var, _val) \ ++ do { \ ++ HTT_CHECK_SET_VAL(HTT_ML_LINK_INFO_VALID, _val); \ ++ ((_var) &= ~(HTT_ML_LINK_INFO_VALID_M)); \ ++ ((_var) |= ((_val) << HTT_ML_LINK_INFO_VALID_S)); \ ++ } while (0) ++ ++#define HTT_ML_LINK_INFO_ACTIVE_GET(_var) \ ++ (((_var) & HTT_ML_LINK_INFO_ACTIVE_M) >> \ ++ HTT_ML_LINK_INFO_ACTIVE_S) ++ ++#define HTT_ML_LINK_INFO_ACTIVE_SET(_var, _val) \ ++ do { \ ++ HTT_CHECK_SET_VAL(HTT_ML_LINK_INFO_ACTIVE, _val); \ ++ ((_var) &= ~(HTT_ML_LINK_INFO_ACTIVE_M)); \ ++ ((_var) |= ((_val) << HTT_ML_LINK_INFO_ACTIVE_S)); \ ++ } while (0) ++ ++#define HTT_ML_LINK_INFO_PRIMARY_GET(_var) \ ++ (((_var) & HTT_ML_LINK_INFO_PRIMARY_M) >> \ ++ HTT_ML_LINK_INFO_PRIMARY_S) ++ ++#define HTT_ML_LINK_INFO_PRIMARY_SET(_var, _val) \ ++ do { \ ++ HTT_CHECK_SET_VAL(HTT_ML_LINK_INFO_PRIMARY, _val); \ ++ ((_var) &= ~(HTT_ML_LINK_INFO_PRIMARY_M)); \ ++ ((_var) |= ((_val) << HTT_ML_LINK_INFO_PRIMARY_S)); \ ++ } while (0) ++ ++#define HTT_ML_LINK_INFO_ASSOC_LINK_GET(_var) \ ++ (((_var) & HTT_ML_LINK_INFO_ASSOC_LINK_M) >> \ ++ HTT_ML_LINK_INFO_ASSOC_LINK_S) ++ ++#define HTT_ML_LINK_INFO_ASSOC_LINK_SET(_var, _val) \ ++ do { \ ++ HTT_CHECK_SET_VAL(HTT_ML_LINK_INFO_ASSOC_LINK, _val); \ ++ ((_var) &= ~(HTT_ML_LINK_INFO_ASSOC_LINK_M)); \ ++ ((_var) |= ((_val) << HTT_ML_LINK_INFO_ASSOC_LINK_S)); \ ++ } while (0) ++ ++#define HTT_ML_LINK_INFO_CHIP_ID_GET(_var) \ ++ (((_var) & HTT_ML_LINK_INFO_CHIP_ID_M) >> \ ++ HTT_ML_LINK_INFO_CHIP_ID_S) ++ ++#define HTT_ML_LINK_INFO_CHIP_ID_SET(_var, _val) \ ++ do { \ ++ HTT_CHECK_SET_VAL(HTT_ML_LINK_INFO_CHIP_ID, _val); \ ++ ((_var) &= ~(HTT_ML_LINK_INFO_CHIP_ID_M)); \ ++ ((_var) |= ((_val) << HTT_ML_LINK_INFO_CHIP_ID_S)); \ ++ } while (0) ++ ++#define HTT_ML_LINK_INFO_IEEE_LINK_ID_GET(_var) \ ++ (((_var) & HTT_ML_LINK_INFO_IEEE_LINK_ID_M) >> \ ++ HTT_ML_LINK_INFO_IEEE_LINK_ID_S) ++ ++#define HTT_ML_LINK_INFO_IEEE_LINK_ID_SET(_var, _val) \ ++ do { \ ++ HTT_CHECK_SET_VAL(HTT_ML_LINK_INFO_IEEE_LINK_ID, _val); \ ++ ((_var) &= ~(HTT_ML_LINK_INFO_IEEE_LINK_ID_M)); \ ++ ((_var) |= ((_val) << HTT_ML_LINK_INFO_IEEE_LINK_ID_S)); \ ++ } while (0) ++ ++#define HTT_ML_LINK_INFO_HW_LINK_ID_GET(_var) \ ++ (((_var) & HTT_ML_LINK_INFO_HW_LINK_ID_M) >> \ ++ HTT_ML_LINK_INFO_HW_LINK_ID_S) ++ ++#define HTT_ML_LINK_INFO_HW_LINK_ID_SET(_var, _val) \ ++ do { \ ++ HTT_CHECK_SET_VAL(HTT_ML_LINK_INFO_HW_LINK_ID, _val); \ ++ ((_var) &= ~(HTT_ML_LINK_INFO_HW_LINK_ID_M)); \ ++ ((_var) |= ((_val) << HTT_ML_LINK_INFO_HW_LINK_ID_S)); \ ++ } while (0) ++ ++#define HTT_ML_LINK_INFO_LOGICAL_LINK_ID_GET(_var) \ ++ (((_var) & HTT_ML_LINK_INFO_LOGICAL_LINK_ID_M) >> \ ++ HTT_ML_LINK_INFO_LOGICAL_LINK_ID_S) ++ ++#define HTT_ML_LINK_INFO_LOGICAL_LINK_ID_SET(_var, _val) \ ++ do { \ ++ HTT_CHECK_SET_VAL(HTT_ML_LINK_INFO_LOGICAL_LINK_ID, _val); \ ++ ((_var) &= ~(HTT_ML_LINK_INFO_LOGICAL_LINK_ID_M)); \ ++ ((_var) |= ((_val) << HTT_ML_LINK_INFO_LOGICAL_LINK_ID_S)); \ ++ } while (0) ++ ++#define HTT_ML_LINK_INFO_MASTER_LINK_GET(_var) \ ++ (((_var) & HTT_ML_LINK_INFO_MASTER_LINK_M) >> \ ++ HTT_ML_LINK_INFO_MASTER_LINK_S) ++ ++#define HTT_ML_LINK_INFO_MASTER_LINK_SET(_var, _val) \ ++ do { \ ++ HTT_CHECK_SET_VAL(HTT_ML_LINK_INFO_MASTER_LINK, _val); \ ++ ((_var) &= ~(HTT_ML_LINK_INFO_MASTER_LINK_M)); \ ++ ((_var) |= ((_val) << HTT_ML_LINK_INFO_MASTER_LINK_S)); \ ++ } while (0) ++ ++#define HTT_ML_LINK_INFO_ANCHOR_LINK_GET(_var) \ ++ (((_var) & HTT_ML_LINK_INFO_ANCHOR_LINK_M) >> \ ++ HTT_ML_LINK_INFO_ANCHOR_LINK_S) ++ ++#define HTT_ML_LINK_INFO_ANCHOR_LINK_SET(_var, _val) \ ++ do { \ ++ HTT_CHECK_SET_VAL(HTT_ML_LINK_INFO_ANCHOR_LINK, _val); \ ++ ((_var) &= ~(HTT_ML_LINK_INFO_ANCHOR_LINK_M)); \ ++ ((_var) |= ((_val) << HTT_ML_LINK_INFO_ANCHOR_LINK_S)); \ ++ } while (0) ++ ++#define HTT_ML_LINK_INFO_INITIALIZED_GET(_var) \ ++ (((_var) & HTT_ML_LINK_INFO_INITIALIZED_M) >> \ ++ HTT_ML_LINK_INFO_INITIALIZED_S) ++ ++#define HTT_ML_LINK_INFO_INITIALIZED_SET(_var, _val) \ ++ do { \ ++ HTT_CHECK_SET_VAL(HTT_ML_LINK_INFO_INITIALIZED, _val); \ ++ ((_var) &= ~(HTT_ML_LINK_INFO_INITIALIZED_M)); \ ++ ((_var) |= ((_val) << HTT_ML_LINK_INFO_INITIALIZED_S)); \ ++ } while (0) ++ ++#define HTT_ML_LINK_INFO_SW_PEER_ID_GET(_var) \ ++ (((_var) & HTT_ML_LINK_INFO_SW_PEER_ID_M) >> \ ++ HTT_ML_LINK_INFO_SW_PEER_ID_S) ++ ++#define HTT_ML_LINK_INFO_SW_PEER_ID_SET(_var, _val) \ ++ do { \ ++ HTT_CHECK_SET_VAL(HTT_ML_LINK_INFO_SW_PEER_ID, _val); \ ++ ((_var) &= ~(HTT_ML_LINK_INFO_SW_PEER_ID_M)); \ ++ ((_var) |= ((_val) << HTT_ML_LINK_INFO_SW_PEER_ID_S)); \ ++ } while (0) ++ ++#define HTT_ML_LINK_INFO_VDEV_ID_GET(_var) \ ++ (((_var) & HTT_ML_LINK_INFO_VDEV_ID_M) >> \ ++ HTT_ML_LINK_INFO_VDEV_ID_S) ++ ++#define HTT_ML_LINK_INFO_VDEV_ID_SET(_var, _val) \ ++ do { \ ++ HTT_CHECK_SET_VAL(HTT_ML_LINK_INFO_VDEV_ID, _val); \ ++ ((_var) &= ~(HTT_ML_LINK_INFO_VDEV_ID_M)); \ ++ ((_var) |= ((_val) << HTT_ML_LINK_INFO_VDEV_ID_S)); \ ++ } while (0) ++ ++struct htt_ml_link_info_tlv { ++ union { ++ struct { ++ u32 valid:1, ++ active:1, ++ primary:1, ++ assoc_link:1, ++ chip_id:3, ++ ieee_link_id:8, ++ hw_link_id:3, ++ logical_link_id:2, ++ master_link:1, ++ anchor_link:1, ++ initialized:1, ++ reserved:9; ++ }; ++ u32 msg_dword_1; ++ }; ++ ++ union { ++ struct { ++ u32 sw_peer_id:16, ++ vdev_id:8, ++ reserved1:8; ++ }; ++ u32 msg_dword_2; ++ }; ++ ++ u32 primary_tid_mask; ++}; ++ + struct htt_phy_counters_tlv { + u32 rx_ofdma_timing_err_cnt; + u32 rx_cck_fail_cnt; +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -1156,7 +1156,7 @@ int ath12k_dp_tx_htt_h2t_ppdu_stats_req( + cmd->msg = u32_encode_bits(HTT_H2T_MSG_TYPE_PPDU_STATS_CFG, + HTT_PPDU_STATS_CFG_MSG_TYPE); + +- pdev_mask = 1 << (i + 1); ++ pdev_mask = DP_SW2HW_MACID(ar->pdev_idx) + i; + cmd->msg |= u32_encode_bits(pdev_mask, HTT_PPDU_STATS_CFG_PDEV_ID); + cmd->msg |= u32_encode_bits(mask, HTT_PPDU_STATS_CFG_TLV_TYPE_BITMASK); + diff --git a/feeds/ipq95xx/mac80211/patches/qca/705-ath12k-fix-hal_rx_desc-skb-corruption.patch b/feeds/ipq95xx/mac80211/patches/qca/705-ath12k-fix-hal_rx_desc-skb-corruption.patch new file mode 100644 index 000000000..d2803e210 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/705-ath12k-fix-hal_rx_desc-skb-corruption.patch @@ -0,0 +1,69 @@ +From 1c004194236b5fe564ca6f267bf8ea152a29f339 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Kathirvel +Date: Wed, 4 Jan 2023 12:17:19 +0530 +Subject: [PATCH] ath12k: fix hal_rx_desc skb corruption + +In dp_rx_process_msdu, the rx_desc is pulled out and moved the head +pointer to payload of a msdu but while in undecap the headroom is +modified to store the dot11 info. Eventually the dot11 info is filled +from rx_desc(skb->head) which already modified to accomodate the dot11 +header this inturn corrupts the original data from rx_desc and creates +high possibility of filling invalid info to dot11 hdr. This skb +corruption makes the msdu invalid. + +Fixed by storing rx_desc to a local variable and assigned it to +rxcb->rx_desc. + +Signed-off-by: Karthikeyan Kathirvel +--- + drivers/net/wireless/ath/ath12k/dp_rx.c | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -3029,10 +3029,11 @@ static int ath12k_dp_rx_process_msdu(str + struct sk_buff *msdu, + struct sk_buff_head *msdu_list, + struct ieee80211_rx_status *rx_status, ++ struct hal_rx_desc *rx_desc, + bool *fast_rx) + { + struct ath12k_base *ab = ar->ab; +- struct hal_rx_desc *rx_desc, *lrx_desc; ++ struct hal_rx_desc *lrx_desc; + struct ath12k_skb_rxcb *rxcb; + struct sk_buff *last_buf; + u8 l3_pad_bytes; +@@ -3048,7 +3049,12 @@ static int ath12k_dp_rx_process_msdu(str + goto free_out; + } + +- rx_desc = (struct hal_rx_desc *)msdu->data; ++ /* ++ * Store the hal_rx_desc into a local structure, ++ * further skb_push's will modify the headroom(rx_desc) in ++ * undecap ++ */ ++ *rx_desc = *(struct hal_rx_desc *)msdu->data; + lrx_desc = (struct hal_rx_desc *)last_buf->data; + if (!ath12k_dp_rx_h_msdu_done(ab, lrx_desc)) { + ath12k_warn(ab, "msdu_done bit in msdu_end is not set\n"); +@@ -3122,6 +3128,8 @@ static void ath12k_dp_rx_process_receive + rcu_read_lock(); + + while ((msdu = __skb_dequeue(msdu_list))) { ++ struct hal_rx_desc rx_desc = {0}; ++ + rxcb = ATH12K_SKB_RXCB(msdu); + /* Enable fast rx by default, the value will cahnge based on peer cap + * and packet type */ +@@ -3153,7 +3161,8 @@ static void ath12k_dp_rx_process_receive + continue; + } + +- ret = ath12k_dp_rx_process_msdu(ar, msdu, msdu_list, &rx_status, &fast_rx); ++ ret = ath12k_dp_rx_process_msdu(ar, msdu, msdu_list, &rx_status, ++ &rx_desc, &fast_rx); + if (ret) { + ath12k_dbg(ab, ATH12K_DBG_DATA, + "Unable to process %s chip_id %d msdu %d", diff --git a/feeds/ipq95xx/mac80211/patches/qca/705-mac80211-fetch-fils-unsol-presp-template-by-link.patch b/feeds/ipq95xx/mac80211/patches/qca/705-mac80211-fetch-fils-unsol-presp-template-by-link.patch new file mode 100644 index 000000000..9475adf57 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/705-mac80211-fetch-fils-unsol-presp-template-by-link.patch @@ -0,0 +1,186 @@ +From a756e6152a4cc4414f0317c2ff6916da7ea0d688 Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Wed, 28 Dec 2022 15:26:37 +0530 +Subject: [PATCH] mac80211: fetch fils/unsol probe resp template by link + +Currently the FILS and unsolicited probe response template +is fetched from default link for a vif. But with ML support, +we need to fetch this based on the link id from the corresponding +link data. + +Signed-off-by: Sriram R +--- + drivers/net/wireless/ath/ath11k/mac.c | 4 +-- + drivers/net/wireless/ath/ath12k/mac.c | 6 ++-- + include/net/mac80211.h | 10 +++++-- + net/mac80211/tx.c | 40 +++++++++++++++++++-------- + 4 files changed, 42 insertions(+), 18 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -3504,7 +3504,7 @@ static int ath11k_mac_fils_discovery(str + if (info->fils_discovery.max_interval) { + interval = info->fils_discovery.max_interval; + +- tmpl = ieee80211_get_fils_discovery_tmpl(ar->hw, arvif->vif); ++ tmpl = ieee80211_get_fils_discovery_tmpl(ar->hw, arvif->vif, 0); + if (tmpl) + ret = ath11k_wmi_fils_discovery_tmpl(ar, arvif->vdev_id, + tmpl); +@@ -3513,7 +3513,7 @@ static int ath11k_mac_fils_discovery(str + interval = info->unsol_bcast_probe_resp_interval; + + tmpl = ieee80211_get_unsol_bcast_probe_resp_tmpl(ar->hw, +- arvif->vif); ++ arvif->vif, 0); + if (tmpl) + ret = ath11k_wmi_probe_resp_tmpl(ar, arvif->vdev_id, + tmpl); +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -3822,7 +3822,8 @@ static int ath12k_mac_fils_discovery(str + if (info->fils_discovery.max_interval) { + interval = info->fils_discovery.max_interval; + +- tmpl = ieee80211_get_fils_discovery_tmpl(ah->hw, ahvif->vif); ++ tmpl = ieee80211_get_fils_discovery_tmpl(ah->hw, ahvif->vif, ++ info->link_id); + if (tmpl) + ret = ath12k_wmi_fils_discovery_tmpl(ar, arvif->vdev_id, + tmpl); +@@ -3831,7 +3832,8 @@ static int ath12k_mac_fils_discovery(str + interval = info->unsol_bcast_probe_resp_interval; + + tmpl = ieee80211_get_unsol_bcast_probe_resp_tmpl(ah->hw, +- ahvif->vif); ++ ahvif->vif, ++ info->link_id); + if (tmpl) + ret = ath12k_wmi_probe_resp_tmpl(ar, arvif->vdev_id, + tmpl); +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -7363,19 +7363,24 @@ bool ieee80211_set_hw_80211_encap(struct + * ieee80211_get_fils_discovery_tmpl - Get FILS discovery template. + * @hw: pointer obtained from ieee80211_alloc_hw(). + * @vif: &struct ieee80211_vif pointer from the add_interface callback. ++ * @link_id: Link for which the template is requested. link id 0 ++ * can be used for non ML vif or corresponding link id for ML vif + * + * The driver is responsible for freeing the returned skb. + * + * Return: FILS discovery template. %NULL on error. + */ + struct sk_buff *ieee80211_get_fils_discovery_tmpl(struct ieee80211_hw *hw, +- struct ieee80211_vif *vif); ++ struct ieee80211_vif *vif, ++ unsigned int link_id); + + /** + * ieee80211_get_unsol_bcast_probe_resp_tmpl - Get unsolicited broadcast + * probe response template. + * @hw: pointer obtained from ieee80211_alloc_hw(). + * @vif: &struct ieee80211_vif pointer from the add_interface callback. ++ * @link_id: Link for which the template is requested. link id 0 ++ * can be used for non ML vif or corresponding link id for ML vif + * + * The driver is responsible for freeing the returned skb. + * +@@ -7383,7 +7388,8 @@ struct sk_buff *ieee80211_get_fils_disco + */ + struct sk_buff * + ieee80211_get_unsol_bcast_probe_resp_tmpl(struct ieee80211_hw *hw, +- struct ieee80211_vif *vif); ++ struct ieee80211_vif *vif, ++ unsigned int link_id); + + /** + * ieeee80211_obss_color_collision_notify - notify userland about a BSS color +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -5834,21 +5834,28 @@ out: + EXPORT_SYMBOL(ieee80211_proberesp_get); + + struct sk_buff *ieee80211_get_fils_discovery_tmpl(struct ieee80211_hw *hw, +- struct ieee80211_vif *vif) ++ struct ieee80211_vif *vif, ++ unsigned int link_id) + { + struct sk_buff *skb = NULL; + struct fils_discovery_data *tmpl = NULL; + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); ++ struct ieee80211_link_data *link; + + if (sdata->vif.type != NL80211_IFTYPE_AP) + return NULL; + +- rcu_read_lock(); +- tmpl = rcu_dereference(sdata->deflink.u.ap.fils_discovery); +- if (!tmpl) { +- rcu_read_unlock(); ++ if (link_id >= IEEE80211_MLD_MAX_NUM_LINKS) + return NULL; +- } ++ ++ rcu_read_lock(); ++ link = rcu_dereference(sdata->link[link_id]); ++ if (!link) ++ goto out; ++ ++ tmpl = rcu_dereference(link->u.ap.fils_discovery); ++ if (!tmpl) ++ goto out; + + skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom + tmpl->len); + if (skb) { +@@ -5856,6 +5863,7 @@ struct sk_buff *ieee80211_get_fils_disco + skb_put_data(skb, tmpl->data, tmpl->len); + } + ++out: + rcu_read_unlock(); + return skb; + } +@@ -5863,21 +5871,28 @@ EXPORT_SYMBOL(ieee80211_get_fils_discove + + struct sk_buff * + ieee80211_get_unsol_bcast_probe_resp_tmpl(struct ieee80211_hw *hw, +- struct ieee80211_vif *vif) ++ struct ieee80211_vif *vif, ++ unsigned int link_id) + { + struct sk_buff *skb = NULL; + struct unsol_bcast_probe_resp_data *tmpl = NULL; + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); ++ struct ieee80211_link_data *link; + + if (sdata->vif.type != NL80211_IFTYPE_AP) + return NULL; + +- rcu_read_lock(); +- tmpl = rcu_dereference(sdata->deflink.u.ap.unsol_bcast_probe_resp); +- if (!tmpl) { +- rcu_read_unlock(); ++ if (link_id >= IEEE80211_MLD_MAX_NUM_LINKS) + return NULL; +- } ++ ++ rcu_read_lock(); ++ link = rcu_dereference(sdata->link[link_id]); ++ if (!link) ++ goto out; ++ ++ tmpl = rcu_dereference(link->u.ap.unsol_bcast_probe_resp); ++ if (!tmpl) ++ goto out; + + skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom + tmpl->len); + if (skb) { +@@ -5885,6 +5900,7 @@ ieee80211_get_unsol_bcast_probe_resp_tmp + skb_put_data(skb, tmpl->data, tmpl->len); + } + ++out: + rcu_read_unlock(); + return skb; + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/706-01-mac80211-add-debugfs-support-for-links.patch b/feeds/ipq95xx/mac80211/patches/qca/706-01-mac80211-add-debugfs-support-for-links.patch new file mode 100644 index 000000000..d0e866c47 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/706-01-mac80211-add-debugfs-support-for-links.patch @@ -0,0 +1,173 @@ +From f6d76117b3d8a4220b7f023789e705ecc068a6f0 Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Sat, 7 Jan 2023 10:40:37 +0530 +Subject: [PATCH 2/2] mac80211: add debugfs support for links + +Add changes to create a link folder under a vif +whenever a link is added or deleted + +by default create link0, as it would correspond to +deflink in case of non-mld vaps + +Signed-off-by: Harshitha Prem +--- + include/net/mac80211.h | 1 + + net/mac80211/debugfs_netdev.c | 65 +++++++++++++++++++++++++++++++++-- + net/mac80211/debugfs_netdev.h | 11 ++++++ + net/mac80211/link.c | 3 ++ + 4 files changed, 78 insertions(+), 2 deletions(-) + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -1954,6 +1954,7 @@ struct ieee80211_vif { + + #ifdef CPTCFG_MAC80211_DEBUGFS + struct dentry *debugfs_dir; ++ struct dentry *link_debugfs[IEEE80211_MLD_MAX_NUM_LINKS]; + #endif + + bool probe_req_reg; +--- a/net/mac80211/debugfs_netdev.c ++++ b/net/mac80211/debugfs_netdev.c +@@ -855,26 +855,88 @@ static void add_files(struct ieee80211_s + } + } + ++void ieee80211_debugfs_add_link(struct ieee80211_sub_if_data *sdata, ++ unsigned long add) ++{ ++ char buf[IFNAMSIZ]; ++ u8 id; ++ ++ if (!sdata->vif.valid_links) ++ return; ++ ++ for_each_set_bit(id, &add, IEEE80211_MLD_MAX_NUM_LINKS) { ++ if (sdata->vif.link_debugfs[id]) ++ continue; ++ ++ snprintf(buf, IFNAMSIZ, "link%d", id); ++ sdata->vif.link_debugfs[id] = debugfs_create_dir(buf, ++ sdata->vif.debugfs_dir); ++ } ++} ++ ++void ieee80211_debugfs_remove_link(struct ieee80211_sub_if_data *sdata, unsigned long rem) ++{ ++ u8 link_id; ++ ++ if (!sdata->vif.valid_links) ++ return; ++ ++ for_each_set_bit(link_id, &rem, IEEE80211_MLD_MAX_NUM_LINKS) { ++ if (!sdata->vif.link_debugfs[link_id]) ++ continue; ++ ++ debugfs_remove_recursive(sdata->vif.link_debugfs[link_id]); ++ sdata->vif.link_debugfs[link_id] = NULL; ++ } ++} ++ + void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata) + { +- char buf[10+IFNAMSIZ]; ++ char buf[10 + IFNAMSIZ]; ++ int i = 0; + +- sprintf(buf, "netdev:%s", sdata->name); ++ snprintf(buf, 10 + IFNAMSIZ, "netdev:%s", sdata->name); + sdata->vif.debugfs_dir = debugfs_create_dir(buf, + sdata->local->hw.wiphy->debugfsdir); + sdata->debugfs.subdir_stations = debugfs_create_dir("stations", + sdata->vif.debugfs_dir); ++ ++ for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) ++ sdata->vif.link_debugfs[i] = NULL; ++ + add_files(sdata); ++ ++ /* create default link if it does not exist */ ++ if (sdata->vif.link_debugfs[0]) ++ return; ++ ++ memset(buf, 0, 10 + IFNAMSIZ); ++ snprintf(buf, 10 + IFNAMSIZ, "link0"); ++ sdata->vif.link_debugfs[0] = debugfs_create_dir(buf, ++ sdata->vif.debugfs_dir); ++ + } + + void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata) + { ++ int i = 0; ++ + if (!sdata->vif.debugfs_dir) + return; + ++ if (!sdata->vif.valid_links && ++ sdata->vif.link_debugfs[0]) { ++ debugfs_remove_recursive(sdata->vif.link_debugfs[0]); ++ sdata->vif.link_debugfs[0] = NULL; ++ } ++ + debugfs_remove_recursive(sdata->vif.debugfs_dir); + sdata->vif.debugfs_dir = NULL; + sdata->debugfs.subdir_stations = NULL; ++ ++ for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) ++ sdata->vif.link_debugfs[i] = NULL; ++ + } + + void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata) +--- a/net/mac80211/debugfs_netdev.h ++++ b/net/mac80211/debugfs_netdev.h +@@ -10,6 +10,10 @@ + void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata); + void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata); + void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata); ++void ieee80211_debugfs_add_link(struct ieee80211_sub_if_data *sdata, ++ unsigned long add); ++void ieee80211_debugfs_remove_link(struct ieee80211_sub_if_data *sdata, ++ unsigned long rem); + #else + static inline void ieee80211_debugfs_add_netdev( + struct ieee80211_sub_if_data *sdata) +@@ -20,6 +24,13 @@ static inline void ieee80211_debugfs_rem + static inline void ieee80211_debugfs_rename_netdev( + struct ieee80211_sub_if_data *sdata) + {} ++static inline void ieee80211_debugfs_add_link(struct ieee80211_sub_if_data *sdata, ++ unsigned long add); ++{} ++static inline void ieee80211_debugfs_remove_link(struct ieee80211_sub_if_data *sdata, ++ unsigned long rem); ++{} ++ + #endif + + #endif /* __IEEE80211_DEBUGFS_NETDEV_H */ +--- a/net/mac80211/link.c ++++ b/net/mac80211/link.c +@@ -9,6 +9,7 @@ + #include + #include "ieee80211_i.h" + #include "driver-ops.h" ++#include "debugfs_netdev.h" + + void ieee80211_link_setup(struct ieee80211_link_data *link) + { +@@ -233,11 +234,13 @@ static int ieee80211_vif_update_links(st + + ret = ieee80211_check_dup_link_addrs(sdata); + if (!ret) { ++ ieee80211_debugfs_remove_link(sdata, rem); + /* for keys we will not be able to undo this */ + ieee80211_tear_down_links(sdata, to_free, rem); + + ieee80211_set_vif_links_bitmaps(sdata, new_links); + ++ ieee80211_debugfs_add_link(sdata, add); + /* tell the driver */ + ret = drv_change_vif_links(sdata->local, sdata, + old_links & old_active, diff --git a/feeds/ipq95xx/mac80211/patches/qca/706-02-ath12k-fix-single-wiphy-debugfs-issues.patch b/feeds/ipq95xx/mac80211/patches/qca/706-02-ath12k-fix-single-wiphy-debugfs-issues.patch new file mode 100644 index 000000000..7bc38dc1d --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/706-02-ath12k-fix-single-wiphy-debugfs-issues.patch @@ -0,0 +1,163 @@ +From fd116351844f9896b56ca7226637bddcfa5f8756 Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Sat, 7 Jan 2023 10:38:56 +0530 +Subject: [PATCH 1/2] ath12k: fix single wiphy debugfs issues +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In single wiphy design, when multiple hardware are registered +as one wiphy to mac80211, then we encounter following issues: + 1. Warning - "debugfs: File 'ath12k' in directory + 'phy0' already present!" + 2. Failed to create mld link because of vif debugfs failure + +To address the above change: +for #1: + Existing debugfs directory in non-single wiphy architecture: + /sys/kernel/debug/ieee80211/phyX/ath12k is symlink of + /sys/kernel/debug/ath12k/qcnXXX/mac0 + + Proposed debugfs directory for single wiphy architecture: + /sys/kernel/debug/ieee80211/phyX/ath12k_hwY is symlink of + /sys/kernel/debug/ath12k/qcnXXX/mac0 + + Where X is phy index and + Y is hw index fetched from - “iw phyX info | grep hw_idx” + +for #2: + Existing twt debugfs directory in non-single wiphy architecture: + /sys/kernel/debug/ieee80211/phyX/netdev:wlanY + + Proposed twt debugfs directory in single wiphy architecture: + /sys/kernel/debug/ieee80211/phyX/netdev:wlanY/linkZ + where Z is the links used in mld vap and 0 for non-mld vap + +Signed-off-by: Harshitha Prem +--- + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/debugfs.c | 67 ++++++++++++++++------- + drivers/net/wireless/ath/ath12k/mac.c | 1 + + 3 files changed, 49 insertions(+), 20 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -2440,7 +2440,15 @@ int ath12k_debugfs_register(struct ath12 + + /* Create a symlink under ieee80211/phy* */ + snprintf(buf, 100, "../../ath12k/%pd2", ar->debug.debugfs_pdev); +- debugfs_create_symlink("ath12k", hw->wiphy->debugfsdir, buf); ++ ++ if (!hw->wiphy->num_hw) { ++ debugfs_create_symlink("ath12k", hw->wiphy->debugfsdir, buf); ++ } else { ++ char dirname[32] = {0}; ++ ++ snprintf(dirname, 32, "ath12k_hw%d", ar->link_idx); ++ debugfs_create_symlink(dirname, hw->wiphy->debugfsdir, buf); ++ } + + ath12k_debugfs_htt_stats_init(ar); + +@@ -2459,7 +2467,7 @@ int ath12k_debugfs_register(struct ath12 + ar->debug.debugfs_pdev, ar, + &fops_pktlog_filter); + +- if (hw->wiphy->bands[NL80211_BAND_5GHZ]) { ++ if (ar->mac.sbands[NL80211_BAND_5GHZ].channels) { + debugfs_create_file("dfs_simulate_radar", 0200, + ar->debug.debugfs_pdev, ar, + &fops_simulate_radar); +@@ -2468,7 +2476,7 @@ int ath12k_debugfs_register(struct ath12 + &ar->dfs_block_radar_events); + } + +- if (hw->wiphy->bands[NL80211_BAND_6GHZ]) { ++ if (ar->mac.sbands[NL80211_BAND_6GHZ].channels) { + debugfs_create_file("simulate_awgn", 0200, + ar->debug.debugfs_pdev, ar, + &fops_simulate_awgn); +@@ -2705,35 +2713,63 @@ static const struct file_operations ath1 + int ath12k_debugfs_add_interface(struct ath12k_link_vif *arvif) + { + struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ieee80211_hw *hw = arvif->ar->ah->hw; ++ struct ieee80211_vif *vif = ahvif->vif; ++ u8 link_id = arvif->link_id; ++ int ret = 0; + +- if (ahvif->vif->type == NL80211_IFTYPE_AP && !arvif->debugfs_twt) { +- arvif->debugfs_twt = debugfs_create_dir("twt", +- ahvif->vif->debugfs_dir); +- if (!arvif->debugfs_twt || IS_ERR(arvif->debugfs_twt)) { +- ath12k_warn(arvif->ar->ab, +- "failed to create directory %p\n", +- arvif->debugfs_twt); +- arvif->debugfs_twt = NULL; +- return -1; +- } +- +- debugfs_create_file("add_dialog", 0200, arvif->debugfs_twt, +- arvif, &ath12k_fops_twt_add_dialog); ++ if (ahvif->vif->type != NL80211_IFTYPE_AP) ++ goto exit; + +- debugfs_create_file("del_dialog", 0200, arvif->debugfs_twt, +- arvif, &ath12k_fops_twt_del_dialog); ++ if (arvif->debugfs_twt) ++ goto exit; + +- debugfs_create_file("pause_dialog", 0200, arvif->debugfs_twt, +- arvif, &ath12k_fops_twt_pause_dialog); ++ if (!hw->wiphy->num_hw) ++ arvif->debugfs_twt = debugfs_create_dir("twt", ++ vif->debugfs_dir); ++ else ++ arvif->debugfs_twt = debugfs_create_dir("twt", ++ vif->link_debugfs[link_id]); + +- debugfs_create_file("resume_dialog", 0200, arvif->debugfs_twt, +- arvif, &ath12k_fops_twt_resume_dialog); ++ if (!arvif->debugfs_twt || IS_ERR(arvif->debugfs_twt)) { ++ ath12k_warn(arvif->ar->ab, ++ "failed to create directory %p\n", ++ arvif->debugfs_twt); ++ arvif->debugfs_twt = NULL; ++ ret = -1; ++ goto exit; + } +- return 0; ++ ++ debugfs_create_file("add_dialog", 0200, arvif->debugfs_twt, ++ arvif, &ath12k_fops_twt_add_dialog); ++ ++ debugfs_create_file("del_dialog", 0200, arvif->debugfs_twt, ++ arvif, &ath12k_fops_twt_del_dialog); ++ ++ debugfs_create_file("pause_dialog", 0200, arvif->debugfs_twt, ++ arvif, &ath12k_fops_twt_pause_dialog); ++ ++ debugfs_create_file("resume_dialog", 0200, arvif->debugfs_twt, ++ arvif, &ath12k_fops_twt_resume_dialog); ++ ++exit: ++ return ret; + } + + void ath12k_debugfs_remove_interface(struct ath12k_link_vif *arvif) + { ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ieee80211_vif *vif = ahvif->vif; ++ u8 link_id = arvif->link_id; ++ ++ if (!arvif->debugfs_twt) ++ return; ++ ++ if (!vif || !vif->link_debugfs[link_id]) { ++ arvif->debugfs_twt = NULL; ++ return; ++ } ++ + debugfs_remove_recursive(arvif->debugfs_twt); + arvif->debugfs_twt = NULL; + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/706-ath12k-Fix-search-flag-and-update-peer-map-event-for.patch b/feeds/ipq95xx/mac80211/patches/qca/706-ath12k-Fix-search-flag-and-update-peer-map-event-for.patch new file mode 100644 index 000000000..50f473552 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/706-ath12k-Fix-search-flag-and-update-peer-map-event-for.patch @@ -0,0 +1,88 @@ +From e120e517f50ba2f26977b03550915a66e65f9c06 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Kathirvel +Date: Tue, 17 Jan 2023 12:48:36 +0530 +Subject: [PATCH] ath12k: Fix search flag and update peer map event for sta + +During STA throughput measurement, majority of packets getting drop due +to tx ring full error and it reduces the performance. This is because +of filling the incorrect ast_idx/ast_hash value to the tx_desc and vdev +search type/flag. + +So that, add changes to correct the offset of ast_idx/ast_hash value +from peer map event and update vdev search type as ADDRX and enabled the +AST lookup in bank config to know the hw to use ast_idx/ast_hash from the +tx desc. + +Signed-off-by: Thiraviyam Mariyappan +Signed-off-by: Karthikeyan Kathirvel +--- + drivers/net/wireless/ath/ath12k/dp.c | 12 ++++++------ + drivers/net/wireless/ath/ath12k/dp.h | 2 ++ + drivers/net/wireless/ath/ath12k/dp_rx.c | 6 ++++-- + 3 files changed, 12 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c +index cb93fa4fa4e7..99246ab240d9 100644 +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -375,7 +375,10 @@ void ath12k_dp_tx_get_vdev_bank_config(struct ath12k_base *ab, struct ath12k_lin + u32_encode_bits(0, HAL_TX_BANK_CONFIG_EPD); + + /* only valid if idx_lookup_override is not set in tcl_data_cmd */ +- *bank_config |= u32_encode_bits(0, HAL_TX_BANK_CONFIG_INDEX_LOOKUP_EN); ++ if (ahvif->vdev_type == WMI_VDEV_TYPE_STA) ++ *bank_config |= u32_encode_bits(1, HAL_TX_BANK_CONFIG_INDEX_LOOKUP_EN); ++ else ++ *bank_config |= u32_encode_bits(0, HAL_TX_BANK_CONFIG_INDEX_LOOKUP_EN); + + *bank_config |= u32_encode_bits(arvif->hal_addr_search_flags & HAL_TX_ADDRX_EN, + HAL_TX_BANK_CONFIG_ADDRX_EN) | +@@ -1121,11 +1124,8 @@ static void ath12k_dp_update_vdev_search(struct ath12k_link_vif *arvif) + + switch (ahvif->vdev_type) { + case WMI_VDEV_TYPE_STA: +- /* TODO Verify the search type and flags since ast hash +- * is not part of peer mapv3 +- */ +- arvif->hal_addr_search_flags = HAL_TX_ADDRY_EN; +- arvif->search_type = HAL_TX_ADDR_SEARCH_DEFAULT; ++ arvif->hal_addr_search_flags = HAL_TX_ADDRX_EN; ++ arvif->search_type = HAL_TX_ADDR_SEARCH_INDEX; + break; + case WMI_VDEV_TYPE_AP: + case WMI_VDEV_TYPE_IBSS: +diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h +index 2914f8dc166f..ac17fe48d2db 100644 +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -1284,6 +1284,8 @@ struct htt_t2h_version_conf_msg { + #define HTT_T2H_PEER_MAP_INFO1_MAC_ADDR_H16 GENMASK(15, 0) + #define HTT_T2H_PEER_MAP_INFO1_HW_PEER_ID GENMASK(31, 16) + #define HTT_T2H_PEER_MAP_INFO2_AST_HASH_VAL GENMASK(15, 0) ++#define HTT_T2H_PEER_MAP3_INFO2_HW_PEER_ID GENMASK(15, 0) ++#define HTT_T2H_PEER_MAP3_INFO2_AST_HASH_VAL GENMASK(31, 16) + #define HTT_T2H_PEER_MAP_INFO2_NEXT_HOP_M BIT(16) + #define HTT_T2H_PEER_MAP_INFO2_NEXT_HOP_S 16 + +diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c +index 1c6c081f442e..2dad9b173505 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -2068,10 +2068,12 @@ void ath12k_dp_htt_htc_t2h_msg_handler(struct ath12k_base *ab, + HTT_T2H_PEER_MAP_INFO1_MAC_ADDR_H16); + ath12k_dp_get_mac_addr(resp->peer_map_ev.mac_addr_l32, + peer_mac_h16, mac_addr); +- ast_hash = FIELD_GET(HTT_T2H_PEER_MAP_INFO2_AST_HASH_VAL, ++ ast_hash = FIELD_GET(HTT_T2H_PEER_MAP3_INFO2_AST_HASH_VAL, ++ resp->peer_map_ev.info2); ++ hw_peer_id = FIELD_GET(HTT_T2H_PEER_MAP3_INFO2_HW_PEER_ID, + resp->peer_map_ev.info2); + ath12k_peer_map_event(ab, vdev_id, peer_id, mac_addr, ast_hash, +- peer_id); ++ hw_peer_id); + break; + case HTT_T2H_MSG_TYPE_PEER_UNMAP: + case HTT_T2H_MSG_TYPE_PEER_UNMAP2: +-- +2.38.0 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/706-ath12k-RDP454-split-phy-bringup-changes.patch b/feeds/ipq95xx/mac80211/patches/qca/706-ath12k-RDP454-split-phy-bringup-changes.patch new file mode 100644 index 000000000..9f7908d86 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/706-ath12k-RDP454-split-phy-bringup-changes.patch @@ -0,0 +1,505 @@ +From cbddf40ff4043e10b96ac2bd90372271e8c1e606 Mon Sep 17 00:00:00 2001 +From: Vishal Kumar +Date: Thu, 5 Jan 2023 10:57:00 +0530 +Subject: [PATCH] ath12k: RDP454 split phy bringup changes + +RDP454 having quad-band channel support with two chip +2.4GHz/2x2 + 5GHz Low band/2x2 and 5GHz High band/2x2 + 6GHz/2x2. + +For single wiphy, 5GHz Low band and 5GHz High bands channels combined +into wiphy->sband[NL80211_BAND_5GHZ]. + +Signed-off-by: Vishal Kumar +--- + drivers/net/wireless/ath/ath12k/core.h | 2 + + drivers/net/wireless/ath/ath12k/mac.c | 173 +++++++++++++++++++------ + drivers/net/wireless/ath/ath12k/reg.c | 13 ++ + 3 files changed, 150 insertions(+), 38 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -610,15 +610,21 @@ struct ath12k_sta { + u8 num_peer; + }; + #define ATH12K_HALF_20MHZ_BW 10 ++#define ATH12K_2G_MIN_CENTER 2412 ++#define ATH12K_2G_MAX_CENTER 2484 + #define ATH12K_5G_MIN_CENTER 4900 + #define ATH12K_5G_MAX_CENTER 5920 + #define ATH12K_6G_MIN_CENTER 5935 + #define ATH12K_6G_MAX_CENTER 7115 ++#define ATH12K_MIN_2G_FREQ (ATH12K_2G_MIN_CENTER - ATH12K_HALF_20MHZ_BW - 1) ++#define ATH12K_MAX_2G_FREQ (ATH12K_2G_MAX_CENTER + ATH12K_HALF_20MHZ_BW + 1) + #define ATH12K_MIN_5G_FREQ (ATH12K_5G_MIN_CENTER - ATH12K_HALF_20MHZ_BW) + #define ATH12K_MAX_5G_FREQ (ATH12K_5G_MAX_CENTER + ATH12K_HALF_20MHZ_BW) + #define ATH12K_MIN_6G_FREQ (ATH12K_6G_MIN_CENTER - ATH12K_HALF_20MHZ_BW) + #define ATH12K_MAX_6G_FREQ (ATH12K_6G_MAX_CENTER + ATH12K_HALF_20MHZ_BW) + ++#define ATH12K_MAX_5G_LOW_BAND_FREQ 5330 ++#define ATH12K_MIN_5G_HIGH_BAND_FREQ 5490 + + #define ATH12K_NUM_CHANS 102 + #define ATH12K_MIN_5G_CHAN 36 +@@ -718,6 +724,7 @@ enum ath12k_fw_recovery_option { + struct ath12k_chan_info { + u32 low_freq; + u32 high_freq; ++ u32 num_channels; + }; + + #define ATH12K_FLUSH_TIMEOUT (5 * HZ) +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -693,16 +693,39 @@ struct ath12k_link_vif *ath12k_mac_get_a + return NULL; + } + +-static struct ath12k *ath12k_mac_get_ar_by_band(struct ieee80211_hw *hw, +- enum nl80211_band band) ++static struct ath12k *ath12k_mac_get_ar_by_agile_chandef(struct ieee80211_hw *hw, ++ enum nl80211_band band) + { + struct ath12k_hw *ah = hw->priv; + struct ath12k *ar; + int i; + ++ if (band != NL80211_BAND_5GHZ) ++ return NULL; ++ + ar = ah->radio; + for (i = 0; i < ah->num_radio; i++) { +- if (ar->mac.sbands[band].channels) ++ if (!ar->agile_chandef.chan) ++ continue; ++ if (ar->agile_chandef.chan->center_freq > ar->chan_info.low_freq && ++ ar->agile_chandef.chan->center_freq < ar->chan_info.high_freq) ++ return ar; ++ ar++; ++ } ++ return NULL; ++} ++ ++static struct ath12k *ath12k_mac_get_ar_by_chan(struct ieee80211_hw *hw, ++ struct ieee80211_channel *channel) ++{ ++ struct ath12k_hw *ah = hw->priv; ++ struct ath12k *ar; ++ int i; ++ ++ ar = ah->radio; ++ for (i = 0; i < ah->num_radio; i++) { ++ if (channel->center_freq >= ar->chan_info.low_freq && ++ channel->center_freq <= ar->chan_info.high_freq) + return ar; + ar++; + } +@@ -715,9 +738,7 @@ static struct ath12k *ath12k_get_ar_by_c + if (!ctx) + return NULL; + +- /* TODO 5G low high split radio changes */ +- +- return ath12k_mac_get_ar_by_band(hw, ctx->def.chan->band); ++ return ath12k_mac_get_ar_by_chan(hw, ctx->def.chan); + } + + struct ath12k *ath12k_get_ar_by_vif(struct ieee80211_hw *hw, struct ieee80211_vif *vif, +@@ -4615,9 +4636,14 @@ ath12k_mac_select_scan_device(struct iee + ar = ah->radio; + + for (i = 0; i < ah->num_radio; i++) { +- /* TODO 5G low high split changes */ +- if (ar->mac.sbands[band].channels) ++ if (band == NL80211_BAND_5GHZ) { ++ if (req->req.channels[0]->center_freq > ar->chan_info.low_freq && ++ req->req.channels[0]->center_freq < ar->chan_info.high_freq) ++ if (ar->mac.sbands[band].channels) ++ return ar; ++ } else if (ar->mac.sbands[band].channels) { + return ar; ++ } + ar++; + } + +@@ -12811,9 +12837,6 @@ static int ath12k_mac_op_get_survey(stru + sband = NULL; + } + +- /* TODO: If 5G HB/LB are split across two radios then it requires +- * idx check as well +- */ + if (!sband) { + sband = hw->wiphy->bands[NL80211_BAND_5GHZ]; + band = NL80211_BAND_5GHZ; +@@ -12834,10 +12857,17 @@ static int ath12k_mac_op_get_survey(stru + goto exit; + } + +- ar = ath12k_mac_get_ar_by_band(hw, band); ++ ar = ath12k_mac_get_ar_by_chan(hw, &sband->channels[idx]); + if (!ar) { +- ret = -ENOENT; +- goto exit; ++ if (sband->channels[idx].flags & IEEE80211_CHAN_DISABLED) { ++ ret = 0; ++ /* Flushing out the old survey results if any */ ++ memset(survey, 0, sizeof(*survey)); ++ goto exit; ++ } else { ++ ret = -ENOENT; ++ goto exit; ++ } + } + + ar_survey = &ar->survey[idx]; +@@ -13099,7 +13129,13 @@ static int ath12k_mac_op_set_radar_backg + int ret; + struct cfg80211_chan_def conf_def; + +- ar = ath12k_mac_get_ar_by_band(hw, NL80211_BAND_5GHZ); ++ if (def) ++ ar = ath12k_mac_get_ar_by_chan(hw, def->chan); ++ else ++ ar = ath12k_mac_get_ar_by_agile_chandef(hw, NL80211_BAND_5GHZ); ++ ++ if (!ar) ++ return -EINVAL; + + mutex_lock(&ar->conf_mutex); + +@@ -13246,6 +13282,67 @@ static void ath12k_mac_update_ch_list(st + } + } + ++/* During MLO split mac scenario, both the supporting channel list of same band ++ * should be updated in same wiphy->band[] place. We update the later incoming ++ * pdev supported channel list (new_band) into wiphy->band[] (orig_band) ++ */ ++static int ath12k_mac_update_band(struct ath12k *ar, ++ struct ieee80211_supported_band *orig_band, ++ struct ieee80211_supported_band *new_band) ++{ ++ struct ath12k_base *ab = ar->ab; ++ struct ieee80211_6ghz_channel *chan_6g_old, *chan_6g_new; ++ int i, j; ++ ++ if (!orig_band || !new_band) ++ return -EINVAL; ++ ++ if (orig_band->band != new_band->band) ++ return -EINVAL; ++ ++ if (WARN_ON(!ab->ag->mlo_capable)) ++ return -EOPNOTSUPP; ++ ++ if (new_band->band == NL80211_BAND_6GHZ) { ++ for (i = 0; i < NL80211_REG_NUM_POWER_MODES; i++) { ++ chan_6g_new = new_band->chan_6g[i]; ++ chan_6g_old = orig_band->chan_6g[i]; ++ for (j = 0; j < chan_6g_new->n_channels; j++) { ++ if (chan_6g_new->channels[j].flags & ++ IEEE80211_CHAN_DISABLED) ++ continue; ++ ++ /* An enabled channel in chan_6g_new should not be ++ * already enabled in the chan_6g_old ++ */ ++ if (WARN_ON(!(chan_6g_old->channels[j].flags & ++ IEEE80211_CHAN_DISABLED))) ++ return -ENOTRECOVERABLE; ++ ++ chan_6g_old->channels[j].flags &= ++ ~IEEE80211_CHAN_DISABLED; ++ } ++ } ++ return 0; ++ } ++ ++ for (i = 0; i < new_band->n_channels; i++) { ++ if (new_band->channels[i].flags & IEEE80211_CHAN_DISABLED) ++ continue; ++ ++ /* An enabled channel in new_band should not be already enabled ++ * in the orig_band ++ */ ++ if (WARN_ON(!(orig_band->channels[i].flags & ++ IEEE80211_CHAN_DISABLED))) ++ return -ENOTRECOVERABLE; ++ ++ orig_band->channels[i].flags &= ~IEEE80211_CHAN_DISABLED; ++ } ++ ++ return 0; ++} ++ + #define ATH12K_5_9_MIN_FREQ 5845 + #define ATH12K_5_9_MAX_FREQ 5885 + +@@ -13294,7 +13391,7 @@ static int ath12k_mac_setup_channels_rat + void *channels; + u32 phy_id, freq_low, freq_high; + struct ieee80211_6ghz_channel *chan_6g; +- int i = 0; ++ int i = 0, ret; + + + BUILD_BUG_ON((ARRAY_SIZE(ath12k_2ghz_channels) + +@@ -13318,7 +13415,6 @@ static int ath12k_mac_setup_channels_rat + band->channels = channels; + band->n_bitrates = ath12k_g_rates_size; + band->bitrates = ath12k_g_rates; +- ah->hw->wiphy->bands[NL80211_BAND_2GHZ] = band; + + if (ab->hw_params->single_pdev_only) { + phy_id = ath12k_get_phy_id(ar, WMI_HOST_WLAN_2G_CAP); +@@ -13332,9 +13428,26 @@ static int ath12k_mac_setup_channels_rat + + ath12k_mac_update_ch_list(ar, band, freq_low, freq_high); + +- ah->supported_band_mask |= BIT(NL80211_BAND_2GHZ); + ar->chan_info.low_freq = freq_low; + ar->chan_info.high_freq = freq_high; ++ ar->chan_info.num_channels = ath12k_reg_get_num_chans_in_band(ar, band, ++ freq_low, ++ freq_high); ++ ++ if (!ah->hw->wiphy->bands[NL80211_BAND_2GHZ]) { ++ ah->hw->wiphy->bands[NL80211_BAND_2GHZ] = band; ++ ah->supported_band_mask |= BIT(NL80211_BAND_2GHZ); ++ } else { ++ /* Split mac in same band under same wiphy during MLO */ ++ ret = ath12k_mac_update_band(ar, ++ ah->hw->wiphy->bands[NL80211_BAND_2GHZ], ++ band); ++ if (ret) ++ return ret; ++ ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac pdev %u identified as 2 GHz split mac during MLO\n", ++ ar->pdev->pdev_id); ++ } + } + + if (supported_bands & WMI_HOST_WLAN_5G_CAP) { +@@ -13361,7 +13474,6 @@ static int ath12k_mac_setup_channels_rat + band->channels = channels; + band->n_bitrates = ath12k_a_rates_size; + band->bitrates = ath12k_a_rates; +- ah->hw->wiphy->bands[NL80211_BAND_5GHZ] = band; + + if (ar->ab->hw_params->single_pdev_only) { + phy_id = ath12k_get_phy_id(ar, WMI_HOST_WLAN_5G_CAP); +@@ -13377,9 +13489,27 @@ static int ath12k_mac_setup_channels_rat + + ath12k_mac_update_5_9_ch_list(ar, band); + +- ah->supported_band_mask |= BIT(NL80211_BAND_5GHZ); + ar->chan_info.low_freq = freq_low; + ar->chan_info.high_freq = freq_high; ++ ar->chan_info.num_channels = ++ ath12k_reg_get_num_chans_in_band(ar, band, ++ freq_low, ++ freq_high); ++ ++ if (!ah->hw->wiphy->bands[NL80211_BAND_5GHZ]) { ++ ah->hw->wiphy->bands[NL80211_BAND_5GHZ] = band; ++ ah->supported_band_mask |= BIT(NL80211_BAND_5GHZ); ++ } else { ++ /* Split mac in same band under same wiphy during MLO */ ++ ret = ath12k_mac_update_band(ar, ++ ah->hw->wiphy->bands[NL80211_BAND_5GHZ], ++ band); ++ if (ret) ++ return ret; ++ ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac pdev %u identified as 5 GHz split mac during MLO\n", ++ ar->pdev->pdev_id); ++ } + } else if (reg_cap->low_5ghz_chan >= ATH12K_MIN_6G_FREQ && + reg_cap->high_5ghz_chan <= ATH12K_MAX_6G_FREQ) { + band = &ar->mac.sbands[NL80211_BAND_6GHZ]; +@@ -13413,7 +13543,6 @@ static int ath12k_mac_setup_channels_rat + ar->supports_6ghz = true; + band->n_bitrates = ath12k_a_rates_size; + band->bitrates = ath12k_a_rates; +- ah->hw->wiphy->bands[NL80211_BAND_6GHZ] = band; + + freq_low = max(temp_reg_cap->low_5ghz_chan, + ab->reg_freq_6g.start_freq); +@@ -13431,15 +13560,33 @@ static int ath12k_mac_setup_channels_rat + band->n_channels = band->chan_6g[0]->n_channels; + band->channels = band->chan_6g[0]->channels; + +- ah->supported_band_mask |= BIT(NL80211_BAND_6GHZ); + ar->chan_info.low_freq = freq_low; + ar->chan_info.high_freq = freq_high; ++ ar->chan_info.num_channels = ++ ath12k_reg_get_num_chans_in_band(ar, band, ++ freq_low, ++ freq_high); ++ ++ if (!ah->hw->wiphy->bands[NL80211_BAND_6GHZ]) { ++ ah->hw->wiphy->bands[NL80211_BAND_6GHZ] = band; ++ ah->supported_band_mask |= BIT(NL80211_BAND_6GHZ); ++ } else { ++ /* Split mac in same band under same wiphy during MLO */ ++ ret = ath12k_mac_update_band(ar, ++ ah->hw->wiphy->bands[NL80211_BAND_6GHZ], ++ band); ++ if (ret) ++ return ret; ++ ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac pdev %u identified as 6 GHz split mac during MLO\n", ++ ar->pdev->pdev_id); ++ } + } + } + +- ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac pdev %u freq limits %u->%u MHz\n", ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac pdev %u freq limits %u->%u MHz no. of channels %u\n", + ar->pdev->pdev_id, ar->chan_info.low_freq, +- ar->chan_info.high_freq); ++ ar->chan_info.high_freq, ar->chan_info.num_channels); + return 0; + } + +@@ -13709,23 +13856,54 @@ ath12k_setup_per_hw_chan(struct ath12k * + struct ieee80211_chans_per_hw *chans; + struct ieee80211_supported_band *band; + struct ath12k_pdev *pdev = ar->pdev; +- int chan_sz; ++ int chan_sz, i, idx = 0; ++ u32 n_channels, freq_low, freq_high; + ++ /* TODO: Handle advertisement for split macs other than 5 GHz ++ * NOTE: For advertising the supported channels, we dont need to check ++ * for current supported frequencies as per hw/regulatory. We just ++ * need to advertise all possible channels as per the band and max ++ * what can be supported ++ */ + if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) { + band = &ar->mac.sbands[NL80211_BAND_2GHZ]; ++ freq_low = ATH12K_MIN_2G_FREQ; ++ freq_high = ATH12K_MAX_2G_FREQ; + } else if (pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP && !ar->supports_6ghz) { +- band = &ar->mac.sbands[NL80211_BAND_5GHZ]; ++ band = &ar->mac.sbands[NL80211_BAND_5GHZ]; ++ if (ar->chan_info.high_freq <= ATH12K_MIN_5G_HIGH_BAND_FREQ) { ++ /* 5 GHz low */ ++ freq_low = ATH12K_MIN_5G_FREQ; ++ freq_high = ATH12K_MAX_5G_LOW_BAND_FREQ; ++ } else if (ar->chan_info.low_freq >= ATH12K_MAX_5G_LOW_BAND_FREQ) { ++ /* 5 GHz High */ ++ freq_low = ATH12K_MIN_5G_HIGH_BAND_FREQ; ++ freq_high = ATH12K_MAX_5G_FREQ; ++ } else { ++ /* 5 GHz Full*/ ++ freq_low = ATH12K_MIN_5G_FREQ; ++ freq_high = ATH12K_MAX_5G_FREQ; ++ } + } else if (pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP && ar->supports_6ghz) { + band = &ar->mac.sbands[NL80211_BAND_6GHZ]; ++ freq_low = ATH12K_MIN_6G_FREQ; ++ freq_high = ATH12K_MAX_6G_FREQ; + } + +- chan_sz = struct_size(chans, chans, band->n_channels); ++ n_channels = ath12k_reg_get_num_chans_in_band(ar, band, freq_low, freq_high); ++ chan_sz = struct_size(chans, chans, n_channels); + chans = kzalloc(chan_sz, GFP_KERNEL); + if (!chans) + return NULL; +- memcpy(chans->chans, band->channels, sizeof(struct ieee80211_channel) * band->n_channels); + +- chans->n_chans = band->n_channels; ++ chans->n_chans = n_channels; ++ ++ for (i = 0; i < band->n_channels; i++) { ++ if (band->channels[i].center_freq >= freq_low && ++ band->channels[i].center_freq <= freq_high) ++ memcpy(&chans->chans[idx++], &band->channels[i], ++ sizeof(struct ieee80211_channel)); ++ } + return chans; + + +--- a/drivers/net/wireless/ath/ath12k/reg.c ++++ b/drivers/net/wireless/ath/ath12k/reg.c +@@ -181,6 +181,12 @@ int ath12k_reg_update_chan_list(struct a + IEEE80211_CHAN_DISABLED) + continue; + ++ if (band == NL80211_BAND_5GHZ) ++ if (bands[band]->channels[i].center_freq < ++ ar->chan_info.low_freq || ++ bands[band]->channels[i].center_freq > ++ ar->chan_info.high_freq) ++ continue; + num_channels++; + } + } +@@ -210,6 +216,13 @@ int ath12k_reg_update_chan_list(struct a + if (channel->flags & IEEE80211_CHAN_DISABLED) + continue; + ++ if (band == NL80211_BAND_5GHZ) ++ if (bands[band]->channels[i].center_freq < ++ ar->chan_info.low_freq || ++ bands[band]->channels[i].center_freq > ++ ar->chan_info.high_freq) ++ continue; ++ + /* TODO: Set to true/false based on some condition? */ + ch->allow_ht = true; + ch->allow_vht = true; +@@ -269,6 +282,24 @@ static void ath12k_copy_regd(struct ieee + sizeof(struct ieee80211_reg_rule)); + } + ++int ath12k_reg_get_num_chans_in_band(struct ath12k *ar, ++ struct ieee80211_supported_band *band, ++ u32 freq_low, u32 freq_high) ++{ ++ int i, count = 0; ++ ++ if (!(freq_low && freq_high) || !band) ++ return 0; ++ ++ for (i = 0; i < band->n_channels; i++) { ++ if (band->channels[i].center_freq >= freq_low && ++ band->channels[i].center_freq <= freq_high) ++ count++; ++ } ++ ++ return count; ++} ++ + int ath12k_regd_update(struct ath12k *ar, bool init) + { + struct ieee80211_regdomain *regd, *regd_copy = NULL; +@@ -315,10 +346,14 @@ int ath12k_regd_update(struct ath12k *ar + + ar->chan_info.low_freq = freq_low; + ar->chan_info.high_freq = freq_high; ++ ar->chan_info.num_channels = ath12k_reg_get_num_chans_in_band(ar, ++ &ar->mac.sbands[band], ++ freq_low, ++ freq_high); + +- ath12k_dbg(ab, ATH12K_DBG_REG, "pdev %u reg updated freq limits %u->%u MHz\n", ++ ath12k_dbg(ab, ATH12K_DBG_REG, "pdev %u reg updated freq limits %u->%u MHz no of channel %u\n", + ar->pdev->pdev_id, ar->chan_info.low_freq, +- ar->chan_info.high_freq); ++ ar->chan_info.high_freq, ar->chan_info.num_channels); + + if (ah->regd_updated) { + mutex_unlock(&ah->conf_mutex); +--- a/drivers/net/wireless/ath/ath12k/reg.h ++++ b/drivers/net/wireless/ath/ath12k/reg.h +@@ -38,4 +38,7 @@ enum wmi_reg_6g_ap_type + ath12k_ieee80211_ap_pwr_type_convert(enum ieee80211_ap_reg_power power_type); + int ath12k_regd_update(struct ath12k *ar, bool init); + int ath12k_reg_update_chan_list(struct ath12k *ar); ++int ath12k_reg_get_num_chans_in_band(struct ath12k *ar, ++ struct ieee80211_supported_band *band, ++ u32 freq_low, u32 freq_high); + #endif diff --git a/feeds/ipq95xx/mac80211/patches/qca/706-ath12k-move-config-caching-to-ahvif.patch b/feeds/ipq95xx/mac80211/patches/qca/706-ath12k-move-config-caching-to-ahvif.patch new file mode 100644 index 000000000..14f52d4e9 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/706-ath12k-move-config-caching-to-ahvif.patch @@ -0,0 +1,242 @@ +From e74f3066b2a9c961ca1cfc914623f674dd084838 Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Fri, 6 Jan 2023 22:24:50 +0530 +Subject: [PATCH] ath12k: move config caching to ahvif + +Currently the caching of arvif is done whenever the +arvif is not created, which happens during the channel +assignment time. But, the config can be cached since +arvif was preallocated and drv private of vif. But since +the drv priv is now ahvif and arvif is allocated dynamically +during channel assignement, the caching of parameters need +to be done at ahvif level for each link and the config +needs to be flushed to the vdev when arvif is binded to +the corresponding link. + +Signed-off-by: Sriram R +--- + drivers/net/wireless/ath/ath12k/core.h | 2 +- + drivers/net/wireless/ath/ath12k/mac.c | 115 +++++++++++++------------ + 2 files changed, 59 insertions(+), 58 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -353,7 +353,6 @@ struct ath12k_link_vif { + bool bcca_zero_sent; + bool do_not_send_tmpl; + u32 vht_cap; +- struct ath12k_vif_cache cache; + #ifdef CPTCFG_ATH12K_DEBUGFS + struct dentry *debugfs_twt; + #endif /* CPTCFG_ATH12K_DEBUGFS */ +@@ -400,6 +399,7 @@ struct ath12k_vif { + struct ath12k_mgmt_frame_stats mgmt_stats; + u8 num_vdev_created; + u8 num_vdev_started; ++ struct ath12k_vif_cache cache[IEEE80211_MLD_MAX_NUM_LINKS]; + }; + + struct ath12k_vif_iter { +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -4458,18 +4458,12 @@ static void ath12k_mac_op_bss_info_chang + mutex_lock(&ah->conf_mutex); + arvif = ahvif->link[link_id]; + +- if (arvif == NULL) { +- /* TODO handle link based ahvif caching */ +- mutex_unlock(&ah->conf_mutex); +- return; +- } +- +- if (!arvif->is_created) { ++ if (arvif == NULL || !arvif->is_created) { + ath12k_info(NULL, + "bss info parameter changes %llx cached to apply after vdev create on channel assign\n", + changed); + +- arvif->cache.bss_conf_changed |= changed; ++ ahvif->cache[link_id].bss_conf_changed |= changed; + mutex_unlock(&ah->conf_mutex); + return; + } +@@ -4581,7 +4575,6 @@ ath12k_mac_assign_link_vif( struct ath12 + return NULL; + + INIT_LIST_HEAD(&arvif->list); +- INIT_LIST_HEAD(&arvif->cache.key_conf.list); + INIT_WORK(&arvif->update_obss_color_notify_work, + ath12k_update_obss_color_notify_work); + INIT_WORK(&arvif->update_bcn_template_work, +@@ -5280,13 +5273,13 @@ static int ath12k_mac_op_set_key(struct + + if (key->link_id >= 0 && key->link_id < IEEE80211_MLD_MAX_NUM_LINKS) { + arvif = ahvif->link[key->link_id]; +- if (WARN_ON(!arvif)) +- goto out; ++ link_id = key->link_id; + } else { + arvif = &ahvif->deflink; ++ link_id = 0; + } + +- if (!arvif->is_created) { ++ if (!arvif || !arvif->is_created) { + key_conf = kzalloc(sizeof(*key_conf), GFP_ATOMIC); + + if (!key_conf) { +@@ -5298,7 +5291,8 @@ static int ath12k_mac_op_set_key(struct + key_conf->sta = sta; + key_conf->key = key; + +- list_add_tail(&key_conf->list, &arvif->cache.key_conf.list); ++ list_add_tail(&key_conf->list, ++ &ahvif->cache[link_id].key_conf.list); + + ath12k_info(NULL, "set key param cached since vif not assign to radio\n"); + mutex_unlock(&ah->conf_mutex); +@@ -7090,24 +7084,21 @@ static int ath12k_mac_op_conf_tx(struct + struct ath12k_link_vif *arvif; + int ret; + +- mutex_lock(&ah->conf_mutex); +- arvif = &ahvif->deflink; ++ if (link_id >= IEEE80211_MLD_MAX_NUM_LINKS) ++ return -EINVAL; + +- /* TODO replace arvif caching to link based ahvif caching */ +- if (arvif == NULL) { +- mutex_unlock(&ah->conf_mutex); +- return 0; +- } ++ mutex_lock(&ah->conf_mutex); ++ arvif = ahvif->link[link_id]; + + /* If the tx config is received before a vdev is assigned to vif + * cache the info to be updated once vdev is created + */ +- if (!arvif->is_created) { ++ if (arvif == NULL || !arvif->is_created) { + ath12k_dbg(NULL, ATH12K_DBG_MAC, + "tx queue params cached since vif is not assigned to radio\n"); +- arvif->cache.tx_conf.changed = true; +- arvif->cache.tx_conf.ac = ac; +- arvif->cache.tx_conf.tx_queue_params = *params; ++ ahvif->cache[link_id].tx_conf.changed = true; ++ ahvif->cache[link_id].tx_conf.ac = ac; ++ ahvif->cache[link_id].tx_conf.tx_queue_params = *params; + mutex_unlock(&ah->conf_mutex); + return 0; + } +@@ -9210,7 +9201,8 @@ err: + return ret; + } + +-static void ath12k_mac_vif_cache_flush(struct ath12k *ar, struct ieee80211_vif *vif) ++static void ath12k_mac_vif_cache_flush(struct ath12k *ar, struct ieee80211_vif *vif, ++ u8 link_id) + { + struct ath12k_hw *ah = ar->ah; + struct ath12k_vif *ahvif = (void *)vif->drv_priv; +@@ -9218,32 +9210,41 @@ static void ath12k_mac_vif_cache_flush(s + struct ath12k_key_conf *key_conf, *tmp; + struct ath12k_link_sta *arsta = NULL; + struct ath12k_sta *ahsta; ++ struct ath12k_vif_cache *cache; + int ret; + + lockdep_assert_held(&ah->conf_mutex); + +- /* TODO extend for all link vifs */ +- arvif = &ahvif->deflink; ++ arvif = ahvif->link[link_id]; ++ ++ if (WARN_ON(!arvif)) ++ return; ++ ++ if (WARN_ON(!arvif->is_created)) ++ return; ++ ++ cache = &ahvif->cache[link_id]; + +- if (arvif->cache.tx_conf.changed) { +- ret = ath12k_mac_conf_tx(ar, arvif, arvif->cache.tx_conf.ac, +- &arvif->cache.tx_conf.tx_queue_params); ++ if (cache->tx_conf.changed) { ++ ret = ath12k_mac_conf_tx(ar, arvif, cache->tx_conf.ac, ++ &cache->tx_conf.tx_queue_params); + if (ret) + ath12k_warn(ar->ab, + "unable to apply tx config parameters to vdev %d\n", ret); + +- memset(&arvif->cache.tx_conf, 0, sizeof(struct ath12k_tx_conf)); ++ memset(&cache->tx_conf, 0, sizeof(struct ath12k_tx_conf)); + } + +- if (arvif->cache.bss_conf_changed) { ++ if (cache->bss_conf_changed) { + ath12k_mac_bss_info_changed(ar, arvif, &vif->bss_conf, +- arvif->cache.bss_conf_changed); ++ cache->bss_conf_changed); + +- arvif->cache.bss_conf_changed = 0; ++ cache->bss_conf_changed = 0; + } + +- if (!list_empty(&arvif->cache.key_conf.list)) { +- list_for_each_entry_safe(key_conf, tmp, &arvif->cache.key_conf.list, list) { ++ ++ if (!list_empty(&cache->key_conf.list)) { ++ list_for_each_entry_safe(key_conf, tmp, &cache->key_conf.list, list) { + if (key_conf->sta) { + ahsta = (struct ath12k_sta *)key_conf->sta->drv_priv; + arsta = ahsta->link[link_id]; +@@ -9313,7 +9314,7 @@ static struct ath12k *ath12k_mac_assign_ + /* Apply any parameters for the vdev which were received after + * add_interface, corresponding to this vif + */ +- ath12k_mac_vif_cache_flush(ar, vif); ++ ath12k_mac_vif_cache_flush(ar, vif, arvif->link_id); + + unlock: + mutex_unlock(&ar->conf_mutex); +@@ -9346,7 +9347,6 @@ static int ath12k_mac_op_add_interface(s + ahvif->deflink.ahvif = ahvif; + ahvif->deflink.link_id = 0; + INIT_LIST_HEAD(&ahvif->deflink.list); +- INIT_LIST_HEAD(&ahvif->deflink.cache.key_conf.list); + INIT_WORK(&ahvif->deflink.update_obss_color_notify_work, + ath12k_update_obss_color_notify_work); + INIT_WORK(&ahvif->deflink.update_bcn_template_work, +@@ -9359,6 +9359,9 @@ static int ath12k_mac_op_add_interface(s + for (i = 0; i < ARRAY_SIZE(vif->hw_queue); i++) + vif->hw_queue[i] = ATH12K_HW_DEFAULT_QUEUE; + ++ for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) ++ INIT_LIST_HEAD(&ahvif->cache[i].key_conf.list); ++ + vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD; + mutex_unlock(&ah->conf_mutex); + return 0; +@@ -9396,7 +9399,7 @@ static void ath12k_mac_remove_link_inter + struct ath12k *ar; + struct ath12k_vif *ahvif = arvif->ahvif; + struct ieee80211_vif *vif = ahvif->vif; +- struct ath12k_key_conf *key_conf; ++ struct ath12k_key_conf *key_conf, *tmp; + struct ath12k_base *ab; + int ret; + +@@ -9465,8 +9468,10 @@ err_vdev_del: + + ath12k_debugfs_remove_interface(arvif); + +- if (!list_empty(&arvif->cache.key_conf.list)) { +- list_for_each_entry(key_conf, &arvif->cache.key_conf.list, list) { ++ if (!list_empty(&ahvif->cache[arvif->link_id].key_conf.list)) { ++ list_for_each_entry_safe(key_conf, tmp, ++ &ahvif->cache[arvif->link_id].key_conf.list, ++ list) { + list_del(&key_conf->list); + kfree(key_conf); + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/684-mac80211-Add-support-to-enable-disable-FILS-UBPR-fra.patch b/feeds/ipq95xx/mac80211/patches/qca/706-mac80211-Add-support-to-enable-disable-FILS-UBPR-fra.patch similarity index 68% rename from feeds/ipq95xx/mac80211/patches/qca/684-mac80211-Add-support-to-enable-disable-FILS-UBPR-fra.patch rename to feeds/ipq95xx/mac80211/patches/qca/706-mac80211-Add-support-to-enable-disable-FILS-UBPR-fra.patch index 9d012a3c4..2d69c2b08 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/684-mac80211-Add-support-to-enable-disable-FILS-UBPR-fra.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/706-mac80211-Add-support-to-enable-disable-FILS-UBPR-fra.patch @@ -1,10 +1,11 @@ -From 5b3719e1703286915d5db2b3825d029be16ef2fa Mon Sep 17 00:00:00 2001 +From 37fb59f9080a9afbccb875f6329327b41d645df1 Mon Sep 17 00:00:00 2001 From: Hari Chandrakanthan -Date: Thu, 17 Nov 2022 00:13:40 +0530 +Date: Tue, 10 Jan 2023 17:37:57 +0530 Subject: [PATCH] mac80211: Add support to enable/disable FILS/UBPR frames Add Support to enabled/disable the Fast initial Link Setup(FILS) ands Unsolicited Broadcast Probe response frames in run time. + Currently FILS or UBPR config with interval 0 is considered as invalid config, Allow user to set the fils max_interval and ubpr interval to be set to 0 in which is case it is disabled. @@ -14,26 +15,26 @@ a BSS restart. Signed-off-by: Hari Chandrakanthan Signed-off-by: Rameshkumar Sundaram --- - net/mac80211/cfg.c | 74 +++++++++++++++++++++++++++----------------------- - net/wireless/nl80211.c | 11 ++++++++ - 2 files changed, 51 insertions(+), 34 deletions(-) + net/mac80211/cfg.c | 82 +++++++++++++++++++++++++++----------------------- + net/wireless/nl80211.c | 11 +++++++ + 2 files changed, 55 insertions(+), 38 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c -index 2379448..e6e461f 100644 +index 69ccbf1..f3cad5d 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -901,21 +901,28 @@ static int ieee80211_set_fils_discovery(struct ieee80211_sub_if_data *sdata, +@@ -976,21 +976,28 @@ static int ieee80211_set_fils_discovery(struct ieee80211_sub_if_data *sdata, struct fils_discovery_data *new, *old = NULL; struct ieee80211_fils_discovery *fd; - if (!params->tmpl || !params->tmpl_len) - return -EINVAL; - - fd = &sdata->vif.bss_conf.fils_discovery; + fd = &link_conf->fils_discovery; fd->min_interval = params->min_interval; fd->max_interval = params->max_interval; - old = sdata_dereference(sdata->u.ap.fils_discovery, sdata); + old = sdata_dereference(link->u.ap.fils_discovery, sdata); + + if (!fd->max_interval) { + new = NULL; @@ -48,18 +49,18 @@ index 2379448..e6e461f 100644 return -ENOMEM; new->len = params->tmpl_len; memcpy(new->data, params->tmpl, params->tmpl_len); -- rcu_assign_pointer(sdata->u.ap.fils_discovery, new); +- rcu_assign_pointer(link->u.ap.fils_discovery, new); +notify_fils: -+ rcu_assign_pointer(sdata->u.ap.fils_discovery, new); ++ rcu_assign_pointer(link->u.ap.fils_discovery, new); if (old) kfree_rcu(old, rcu_head); -@@ -928,17 +935,24 @@ ieee80211_set_unsol_bcast_probe_resp(struct ieee80211_sub_if_data *sdata, +@@ -1005,17 +1012,24 @@ ieee80211_set_unsol_bcast_probe_resp(struct ieee80211_sub_if_data *sdata, { struct unsol_bcast_probe_resp_data *new, *old = NULL; -+ old = sdata_dereference(sdata->u.ap.unsol_bcast_probe_resp, sdata); ++ old = sdata_dereference(link->u.ap.unsol_bcast_probe_resp, sdata); + + if (!params->interval) { + new = NULL; @@ -69,88 +70,96 @@ index 2379448..e6e461f 100644 if (!params->tmpl || !params->tmpl_len) return -EINVAL; -- old = sdata_dereference(sdata->u.ap.unsol_bcast_probe_resp, sdata); +- old = sdata_dereference(link->u.ap.unsol_bcast_probe_resp, sdata); new = kzalloc(sizeof(*new) + params->tmpl_len, GFP_KERNEL); if (!new) return -ENOMEM; new->len = params->tmpl_len; memcpy(new->data, params->tmpl, params->tmpl_len); -- rcu_assign_pointer(sdata->u.ap.unsol_bcast_probe_resp, new); +- rcu_assign_pointer(link->u.ap.unsol_bcast_probe_resp, new); +notify_ubpr: -+ rcu_assign_pointer(sdata->u.ap.unsol_bcast_probe_resp, new); ++ rcu_assign_pointer(link->u.ap.unsol_bcast_probe_resp, new); if (old) kfree_rcu(old, rcu_head); -@@ -1420,21 +1434,17 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, +@@ -1445,23 +1459,19 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, goto error; changed |= err; - if (params->fils_discovery.max_interval) { - err = ieee80211_set_fils_discovery(sdata, -- ¶ms->fils_discovery); +- ¶ms->fils_discovery, +- link, link_conf); - if (err < 0) - goto error; - changed |= BSS_CHANGED_FILS_DISCOVERY; - } + err = ieee80211_set_fils_discovery(sdata, -+ ¶ms->fils_discovery); ++ ¶ms->fils_discovery, ++ link, link_conf); + if (err < 0) + goto error; + changed |= BSS_CHANGED_FILS_DISCOVERY; - if (params->unsol_bcast_probe_resp.interval) { - err = ieee80211_set_unsol_bcast_probe_resp(sdata, -- ¶ms->unsol_bcast_probe_resp); +- ¶ms->unsol_bcast_probe_resp, +- link, link_conf); - if (err < 0) - goto error; - changed |= BSS_CHANGED_UNSOL_BCAST_PROBE_RESP; - } + err = ieee80211_set_unsol_bcast_probe_resp(sdata, -+ ¶ms->unsol_bcast_probe_resp); ++ ¶ms->unsol_bcast_probe_resp, ++ link, link_conf); + if (err < 0) + goto error; + changed |= BSS_CHANGED_UNSOL_BCAST_PROBE_RESP; - err = drv_start_ap(sdata->local, sdata); + err = drv_start_ap(sdata->local, sdata, link_conf); if (err) { -@@ -1505,21 +1515,17 @@ static int ieee80211_update_ap(struct wiphy *wiphy, struct net_device *dev, +@@ -1544,23 +1554,19 @@ static int ieee80211_update_ap(struct wiphy *wiphy, struct net_device *dev, if (err > 0) changed = err; - if (params->fils_discovery.max_interval) { - err = ieee80211_set_fils_discovery(sdata, -- ¶ms->fils_discovery); +- ¶ms->fils_discovery, +- link, link_conf); - if (err < 0) - return err; - changed |= BSS_CHANGED_FILS_DISCOVERY; - } + err = ieee80211_set_fils_discovery(sdata, -+ ¶ms->fils_discovery); ++ ¶ms->fils_discovery, ++ link, link_conf); + if (err < 0) + return err; + changed |= BSS_CHANGED_FILS_DISCOVERY; - if (params->unsol_bcast_probe_resp.interval) { - err = ieee80211_set_unsol_bcast_probe_resp(sdata, -- ¶ms->unsol_bcast_probe_resp); +- ¶ms->unsol_bcast_probe_resp, +- link, link_conf); - if (err < 0) - return err; - changed |= BSS_CHANGED_UNSOL_BCAST_PROBE_RESP; - } + err = ieee80211_set_unsol_bcast_probe_resp(sdata, -+ ¶ms->unsol_bcast_probe_resp); ++ ¶ms->unsol_bcast_probe_resp, ++ link, link_conf); + if (err < 0) + return err; + changed |= BSS_CHANGED_UNSOL_BCAST_PROBE_RESP; - ieee80211_bss_info_change_notify(sdata, changed); + ieee80211_link_info_change_notify(sdata, link, changed); return 0; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c -index 80f20f9..602dfe0 100644 +index 5392de5..4b8a82a 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c -@@ -5739,6 +5739,12 @@ static int nl80211_parse_fils_discovery(struct cfg80211_registered_device *rdev, +@@ -6121,6 +6121,12 @@ static int nl80211_parse_fils_discovery(struct cfg80211_registered_device *rdev, if (ret) return ret; @@ -163,7 +172,7 @@ index 80f20f9..602dfe0 100644 if (!tb[NL80211_FILS_DISCOVERY_ATTR_INT_MIN] || !tb[NL80211_FILS_DISCOVERY_ATTR_INT_MAX] || !tb[NL80211_FILS_DISCOVERY_ATTR_TMPL]) -@@ -5771,6 +5777,11 @@ nl80211_parse_unsol_bcast_probe_resp(struct cfg80211_registered_device *rdev, +@@ -6153,6 +6159,11 @@ nl80211_parse_unsol_bcast_probe_resp(struct cfg80211_registered_device *rdev, if (ret) return ret; diff --git a/feeds/ipq95xx/mac80211/patches/qca/706-nl80211-Add-power-mode-support-for-6G.patch b/feeds/ipq95xx/mac80211/patches/qca/706-nl80211-Add-power-mode-support-for-6G.patch new file mode 100644 index 000000000..b7d29e9d5 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/706-nl80211-Add-power-mode-support-for-6G.patch @@ -0,0 +1,339 @@ +From 1ddc2a5498dd7bdfd2e86a231588351890e27ad9 Mon Sep 17 00:00:00 2001 +From: Amutha Ravikumar +Date: Wed, 15 Feb 2023 14:35:31 +0530 +Subject: nl80211: Add power mode support for 6 GHz + +During RRM link measurement testing, power mode of STA/AP +is not sent properly during 6G. Hence implemented the support +to calculate power mode of STA and AP from parsing wireless_dev +structure. + +Signed-off-by: Amutha Ravikumar +--- + include/net/cfg80211.h | 3 +++ + net/mac80211/cfg.c | 41 +++++++++++++++++++++++++++++++++++++++++ + net/wireless/nl80211.c | 2 ++ + net/wireless/rdev-ops.h | 11 +++++++++++ + 4 files changed, 57 insertions(+) + +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -4698,6 +4698,9 @@ struct cfg80211_ops { + unsigned int link_id, + struct cfg80211_chan_def *chandef); + ++ enum nl80211_regulatory_power_modes ++ (*get_ap_6ghz_pwr_mode)(struct wireless_dev *wdev); ++ + int (*add_tx_ts)(struct wiphy *wiphy, struct net_device *dev, + u8 tsid, const u8 *peer, u8 user_prio, + u16 admitted_time); +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -4444,6 +4444,46 @@ static int ieee80211_set_ap_chanwidth(st + return ret; + } + ++static enum nl80211_regulatory_power_modes ++ieee80211_get_ap_6ghz_pwr_mode(struct wireless_dev *wdev) ++{ ++ struct ieee80211_sub_if_data *sdata; ++ enum nl80211_regulatory_power_modes mode = NL80211_REG_AP_LPI; ++ enum ieee80211_ap_reg_power ap_power_type; ++ ++ if (!wdev) ++ return mode; ++ switch (wdev->iftype) { ++ case NL80211_IFTYPE_AP: ++ mode = wdev->reg_6g_power_mode; ++ break; ++ case NL80211_IFTYPE_STATION: ++ sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); ++ if (!ieee80211_sdata_running(sdata) || ++ !(sdata->flags & IEEE80211_SDATA_IN_DRIVER)) { ++ sdata_info(sdata, "sdata not running"); ++ return mode; ++ } ++ /* If STA is not yet associated then assign power type ++ * by default as IEEE80211_REG_LPI_AP */ ++ if (sdata->vif.bss_conf.power_type == ++ IEEE80211_REG_UNSET_AP) { ++ ap_power_type = IEEE80211_REG_LPI_AP; ++ } else { ++ ap_power_type = sdata->vif.bss_conf.power_type; ++ } ++ /* ieee80211_ap_reg_power starts with 0 since they used ++ * IEEE80211_REG_UNSET_AP as first parameter. Hence reduced ++ * ap_power_type by offset 1 to match with 6g_reg_power_mode */ ++ mode = GET_POWER_MODE_FOR_NON_AP_STA(wdev->reg_6g_power_mode, ap_power_type - 1); ++ break; ++ default: ++ /* do nothing */ ++ break; ++ } ++ return mode; ++} ++ + static int ieee80211_add_tx_ts(struct wiphy *wiphy, struct net_device *dev, + u8 tsid, const u8 *peer, u8 up, + u16 admitted_time) +@@ -5212,6 +5252,7 @@ const struct cfg80211_ops mac80211_confi + .channel_switch = ieee80211_channel_switch, + .set_qos_map = ieee80211_set_qos_map, + .set_ap_chanwidth = ieee80211_set_ap_chanwidth, ++ .get_ap_6ghz_pwr_mode = ieee80211_get_ap_6ghz_pwr_mode, + .add_tx_ts = ieee80211_add_tx_ts, + .del_tx_ts = ieee80211_del_tx_ts, + .start_nan = ieee80211_start_nan, +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -3419,7 +3419,8 @@ static int nl80211_parse_ru_punct_bitmap + + int nl80211_parse_chandef(struct cfg80211_registered_device *rdev, + struct genl_info *info, +- struct cfg80211_chan_def *chandef) ++ struct cfg80211_chan_def *chandef, ++ struct wireless_dev *wdev) + { + struct netlink_ext_ack *extack = genl_info_extack(info); + struct nlattr **attrs = info->attrs; +@@ -3438,6 +3439,8 @@ int nl80211_parse_chandef(struct cfg8021 + + if (info->attrs[NL80211_ATTR_6G_REG_POWER_MODE]) + mode = nla_get_u8(info->attrs[NL80211_ATTR_6G_REG_POWER_MODE]); ++ else if (wdev) ++ mode = rdev_get_ap_6ghz_pwr_mode(rdev, wdev); + + memset(chandef, 0, sizeof(*chandef)); + +@@ -3585,7 +3588,7 @@ static int __nl80211_set_channel(struct + link_id = 0; + } + +- result = nl80211_parse_chandef(rdev, info, &chandef); ++ result = nl80211_parse_chandef(rdev, info, &chandef, wdev); + if (result) + return result; + +@@ -6493,7 +6496,7 @@ static int nl80211_start_ap(struct sk_bu + } + + if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { +- err = nl80211_parse_chandef(rdev, info, ¶ms->chandef); ++ err = nl80211_parse_chandef(rdev, info, ¶ms->chandef, wdev); + if (err) + goto out; + } else if (wdev->valid_links) { +@@ -9628,7 +9631,7 @@ static int nl80211_trigger_scan(struct s + return -EBUSY; + + if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { +- if (nl80211_parse_chandef(rdev, info, &chandef)) { ++ if (nl80211_parse_chandef(rdev, info, &chandef, wdev)) { + return -EINVAL; + } + chandef_found = true; +@@ -10447,7 +10450,7 @@ static int nl80211_start_radar_detection + if (dfs_region == NL80211_DFS_UNSET) + goto unlock; + +- err = nl80211_parse_chandef(rdev, info, &chandef); ++ err = nl80211_parse_chandef(rdev, info, &chandef, wdev); + if (err) + goto unlock; + +@@ -10541,7 +10544,7 @@ static int nl80211_notify_radar_detectio + return -EINVAL; + } + +- err = nl80211_parse_chandef(rdev, info, &chandef); ++ err = nl80211_parse_chandef(rdev, info, &chandef, wdev); + if (err) { + GENL_SET_ERR_MSG(info, "Unable to extract chandef info"); + return err; +@@ -10740,7 +10743,7 @@ static int nl80211_channel_switch(struct + } + + skip_beacons: +- err = nl80211_parse_chandef(rdev, info, ¶ms.chandef); ++ err = nl80211_parse_chandef(rdev, info, ¶ms.chandef, wdev); + if (err) + goto free; + +@@ -11825,6 +11828,7 @@ static int nl80211_join_ibss(struct sk_b + struct cfg80211_ibss_params ibss; + struct wiphy *wiphy; + struct cfg80211_cached_keys *connkeys = NULL; ++ struct wireless_dev *wdev = dev->ieee80211_ptr; + int err; + + memset(&ibss, 0, sizeof(ibss)); +@@ -11847,7 +11851,7 @@ static int nl80211_join_ibss(struct sk_b + if (!rdev->ops->join_ibss) + return -EOPNOTSUPP; + +- if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) ++ if (wdev->iftype != NL80211_IFTYPE_ADHOC) + return -EOPNOTSUPP; + + wiphy = &rdev->wiphy; +@@ -11866,7 +11870,7 @@ static int nl80211_join_ibss(struct sk_b + ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); + } + +- err = nl80211_parse_chandef(rdev, info, &ibss.chandef); ++ err = nl80211_parse_chandef(rdev, info, &ibss.chandef, wdev); + if (err) + return err; + +@@ -12840,7 +12844,7 @@ static int nl80211_remain_on_channel(str + duration > rdev->wiphy.max_remain_on_channel_duration) + return -EINVAL; + +- err = nl80211_parse_chandef(rdev, info, &chandef); ++ err = nl80211_parse_chandef(rdev, info, &chandef, wdev); + if (err) + return err; + +@@ -13054,7 +13058,7 @@ static int nl80211_tx_mgmt(struct sk_buf + */ + chandef.chan = NULL; + if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { +- err = nl80211_parse_chandef(rdev, info, &chandef); ++ err = nl80211_parse_chandef(rdev, info, &chandef, wdev); + if (err) + return err; + } +@@ -13459,7 +13463,8 @@ static int nl80211_join_ocb(struct sk_bu + struct ocb_setup setup = {}; + int err; + +- err = nl80211_parse_chandef(rdev, info, &setup.chandef); ++ err = nl80211_parse_chandef(rdev, info, &setup.chandef, ++ dev->ieee80211_ptr); + if (err) + return err; + +@@ -13538,7 +13543,8 @@ static int nl80211_join_mesh(struct sk_b + cfg.auto_open_plinks = false; + + if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { +- err = nl80211_parse_chandef(rdev, info, &setup.chandef); ++ err = nl80211_parse_chandef(rdev, info, &setup.chandef, ++ dev->ieee80211_ptr); + if (err) + return err; + } else { +@@ -15873,7 +15879,7 @@ static int nl80211_tdls_channel_switch(s + !info->attrs[NL80211_ATTR_OPER_CLASS]) + return -EINVAL; + +- err = nl80211_parse_chandef(rdev, info, &chandef); ++ err = nl80211_parse_chandef(rdev, info, &chandef, wdev); + if (err) + return err; + +--- a/net/wireless/rdev-ops.h ++++ b/net/wireless/rdev-ops.h +@@ -1130,6 +1130,19 @@ rdev_set_ap_chanwidth(struct cfg80211_re + return ret; + } + ++static inline enum nl80211_regulatory_power_modes ++rdev_get_ap_6ghz_pwr_mode(struct cfg80211_registered_device *rdev, ++ struct wireless_dev *wdev) ++{ ++ enum nl80211_regulatory_power_modes ret = NL80211_REG_AP_LPI; ++ trace_rdev_get_ap_6ghz_pwr_mode(wdev); ++ if (rdev->ops->get_ap_6ghz_pwr_mode) ++ ret = rdev->ops->get_ap_6ghz_pwr_mode(wdev); ++ trace_rdev_return_enum(&rdev->wiphy, ret); ++ return ret; ++} ++ ++ + static inline int + rdev_add_tx_ts(struct cfg80211_registered_device *rdev, + struct net_device *dev, u8 tsid, const u8 *peer, +--- a/net/wireless/trace.h ++++ b/net/wireless/trace.h +@@ -292,6 +292,21 @@ TRACE_EVENT(rdev_return_int, + TP_printk(WIPHY_PR_FMT ", returned: %d", WIPHY_PR_ARG, __entry->ret) + ); + ++TRACE_EVENT(rdev_return_enum, ++ TP_PROTO(struct wiphy *wiphy, ++ enum nl80211_regulatory_power_modes ret), ++ TP_ARGS(wiphy, ret), ++ TP_STRUCT__entry( ++ WIPHY_ENTRY ++ __field(enum nl80211_regulatory_power_modes, ret) ++ ), ++ TP_fast_assign( ++ WIPHY_ASSIGN; ++ __entry->ret = ret; ++ ), ++ TP_printk(WIPHY_PR_FMT ", returned: %d", WIPHY_PR_ARG, __entry->ret) ++); ++ + TRACE_EVENT(rdev_scan, + TP_PROTO(struct wiphy *wiphy, struct cfg80211_scan_request *request), + TP_ARGS(wiphy, request), +@@ -2383,6 +2398,14 @@ TRACE_EVENT(rdev_set_ap_chanwidth, + __entry->link_id) + ); + ++TRACE_EVENT(rdev_get_ap_6ghz_pwr_mode, ++ TP_PROTO(struct wireless_dev *wdev), ++ TP_ARGS(wdev), ++ TP_STRUCT__entry(WDEV_ENTRY), ++ TP_fast_assign(WDEV_ASSIGN), ++ TP_printk(WDEV_PR_FMT, WDEV_PR_ARG) ++); ++ + TRACE_EVENT(rdev_add_tx_ts, + TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, + u8 tsid, const u8 *peer, u8 user_prio, u16 admitted_time), +--- a/net/wireless/pmsr.c ++++ b/net/wireless/pmsr.c +@@ -185,7 +185,8 @@ static int pmsr_parse_ftm(struct cfg8021 + static int pmsr_parse_peer(struct cfg80211_registered_device *rdev, + struct nlattr *peer, + struct cfg80211_pmsr_request_peer *out, +- struct genl_info *info) ++ struct genl_info *info, ++ struct wireless_dev *wdev) + { + struct nlattr *tb[NL80211_PMSR_PEER_ATTR_MAX + 1]; + struct nlattr *req[NL80211_PMSR_REQ_ATTR_MAX + 1]; +@@ -214,7 +215,7 @@ static int pmsr_parse_peer(struct cfg802 + if (err) + return err; + +- err = nl80211_parse_chandef(rdev, info, &out->chandef); ++ err = nl80211_parse_chandef(rdev, info, &out->chandef, wdev); + if (err) + return err; + +@@ -317,7 +318,8 @@ int nl80211_pmsr_start(struct sk_buff *s + idx = 0; + nla_for_each_nested(peer, peers, rem) { + /* NB: this reuses info->attrs, but we no longer need it */ +- err = pmsr_parse_peer(rdev, peer, &req->peers[idx], info); ++ err = pmsr_parse_peer(rdev, peer, &req->peers[idx], info, ++ wdev); + if (err) + goto out_err; + idx++; +--- a/net/wireless/nl80211.h ++++ b/net/wireless/nl80211.h +@@ -24,7 +24,8 @@ static inline u64 wdev_id(struct wireles + + int nl80211_parse_chandef(struct cfg80211_registered_device *rdev, + struct genl_info *info, +- struct cfg80211_chan_def *chandef); ++ struct cfg80211_chan_def *chandef, ++ struct wireless_dev *wdev); + int nl80211_parse_random_mac(struct nlattr **attrs, + u8 *mac_addr, u8 *mac_addr_mask); + diff --git a/feeds/ipq95xx/mac80211/patches/qca/707-01-mac80211-emlsr-capabalalites.patch b/feeds/ipq95xx/mac80211/patches/qca/707-01-mac80211-emlsr-capabalalites.patch new file mode 100644 index 000000000..5a9568bcd --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/707-01-mac80211-emlsr-capabalalites.patch @@ -0,0 +1,94 @@ +From c03f25d5c796633918371dbf24974e5496756b4c Mon Sep 17 00:00:00 2001 +From: Ramasamy Kaliappan +Date: Sun, 26 Feb 2023 11:25:39 +0530 +Subject: [PATCH] mac80211: Enable emlsr mode support in ap. + +This enables emlsr mode support in ap, add to read eml +capabilities on set station param in +mac80211/cfg80211, it store in the link sta +and sent to target driver. + +Signed-off-by: Ramasamy Kaliappan +--- + include/net/cfg80211.h | 2 ++ + include/net/mac80211.h | 3 +++ + net/mac80211/cfg.c | 4 ++++ + net/wireless/nl80211.c | 27 +++++++++++++++++++++++++++ + 4 files changed, 36 insertions(+) + +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -1612,6 +1612,8 @@ struct sta_txpwr { + * @he_6ghz_capa: HE 6 GHz Band capabilities of station + * @eht_capa: EHT capabilities of station + * @eht_capa_len: the length of the EHT capabilities ++ * @eml_cap: EML capabilities of station ++ * @mld_oper: MLD capabilites and operation field of station + */ + struct link_station_parameters { + const u8 *mld_mac; +@@ -1633,6 +1635,8 @@ struct link_station_parameters { + u8 eht_capa_len; + const struct ieee80211_240mhz_vendor_oper *eht_240mhz_capa; + u8 eht_240mhz_len; ++ u16 eml_cap; ++ u16 mld_oper; + }; + + /** +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -2344,6 +2344,8 @@ struct ieee80211_link_sta { + * would be assigned to link[link_id] where link_id is the id assigned + * by the AP. + * @valid_links: bitmap of valid links, or 0 for non-MLO ++ * @eml_cap: EML capabilities of station ++ * @mld_cap_op: MLD capabilites and operation field of station + */ + struct ieee80211_sta { + u8 addr[ETH_ALEN]; +@@ -2386,6 +2388,9 @@ struct ieee80211_sta { + struct ieee80211_link_sta deflink; + struct ieee80211_link_sta __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS]; + ++ u16 eml_cap; ++ u16 mld_cap_op; ++ + /* must be last */ + u8 drv_priv[] __aligned(sizeof(void *)); + }; +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1939,6 +1939,7 @@ static int sta_apply_parameters(struct i + + mask = params->sta_flags_mask; + set = params->sta_flags_set; ++ sta->sta.eml_cap = params->link_sta_params.eml_cap; + + if (ieee80211_vif_is_mesh(&sdata->vif)) { + /* +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -860,6 +860,8 @@ static const struct nla_policy nl80211_p + [NL80211_ATTR_RU_PUNCT_BITMAP] = { .type = NLA_U16 }, + [NL80211_ATTR_AP_PS] = NLA_POLICY_MAX(NLA_U8, 1), + [NL80211_ATTR_RADAR_BITMAP] = { .type = NLA_U16 }, ++ [NL80211_ATTR_EML_CAPABILITY] = { .type = NLA_U16 }, ++ [NL80211_ATTR_MLD_CAPA_AND_OPS] = { .type = NLA_U16 }, + #if LINUX_VERSION_IS_GEQ(5,10,0) + [NL80211_ATTR_EHT_240MHZ_CAPABILITY] = + NLA_POLICY_RANGE(NLA_BINARY, +@@ -7744,6 +7746,13 @@ static int nl80211_set_station(struct sk + if (err) + return err; + ++ if (info->attrs[NL80211_ATTR_EML_CAPABILITY]) ++ params.link_sta_params.eml_cap = ++ nla_get_u16(info->attrs[NL80211_ATTR_EML_CAPABILITY]); ++ ++ if (info->attrs[NL80211_ATTR_MLD_CAPA_AND_OPS]) ++ params.link_sta_params.mld_oper = ++ nla_data(info->attrs[NL80211_ATTR_MLD_CAPA_AND_OPS]); + /* Include parameters for TDLS peer (will check later) */ + err = nl80211_set_station_tdls(info, ¶ms); + if (err) diff --git a/feeds/ipq95xx/mac80211/patches/qca/707-02-ath12k-Enable-emlsr-mode-support.patch b/feeds/ipq95xx/mac80211/patches/qca/707-02-ath12k-Enable-emlsr-mode-support.patch new file mode 100644 index 000000000..73959c57a --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/707-02-ath12k-Enable-emlsr-mode-support.patch @@ -0,0 +1,179 @@ +From 2609565381834b793dea7591222dbf4716d2a15a Mon Sep 17 00:00:00 2001 +From: Ramasamy Kaliappan +Date: Sun, 26 Feb 2023 11:37:27 +0530 +Subject: [PATCH] wifi: ath12k: Enable emlsr mode support in ap + +Currently the emlsr feature is not supported in ap, + +This enables emlsr mode in ap, the eml capabilities stored +on set station param, it parse the emlsr params from +eml capability during WMI_PEER_ASSOC_CMD and send to firmware. + +Signed-off-by: Ramasamy Kaliappan +--- + drivers/net/wireless/ath/ath12k/core.h | 2 + + drivers/net/wireless/ath/ath12k/mac.c | 2 + + drivers/net/wireless/ath/ath12k/wmi.c | 85 ++++++++++++++++++++++++-- + drivers/net/wireless/ath/ath12k/wmi.h | 31 ++++++++++ + 4 files changed, 115 insertions(+), 5 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -3068,6 +3068,8 @@ static void ath12k_peer_assoc_h_mlo(stru + ml->ml_peer_id = ahsta->ml_peer_id; + ml->ieee_link_id = arsta->link_id; + ml->num_partner_links = 0; ++ /*emlsr */ ++ ml->eml_caps = sta->eml_cap; + + for_each_set_bit(link_id, &sta->valid_links, IEEE80211_MLD_MAX_NUM_LINKS) { + if (i > ATH12K_WMI_MLO_MAX_LINKS) +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -163,6 +163,20 @@ static const struct wmi_tlv_policy wmi_t + = { .min_len = sizeof(struct wmi_cp_stats_event_fixed_param) }, + }; + ++static const u32 eml_trans_timeout[EMLCAP_TIMEOUT_MAX] = { ++ EMLCAP_TRANSTIMEOUT_0, ++ EMLCAP_TRANSTIMEOUT_1, ++ EMLCAP_TRANSTIMEOUT_2, ++ EMLCAP_TRANSTIMEOUT_3, ++ EMLCAP_TRANSTIMEOUT_4, ++ EMLCAP_TRANSTIMEOUT_5, ++ EMLCAP_TRANSTIMEOUT_6, ++ EMLCAP_TRANSTIMEOUT_7, ++ EMLCAP_TRANSTIMEOUT_8, ++ EMLCAP_TRANSTIMEOUT_9, ++ EMLCAP_TRANSTIMEOUT_10, ++ EMLCAP_TRANSTIMEOUT_11}; ++ + static __le32 ath12k_wmi_tlv_hdr(u32 cmd, u32 len) + { + return le32_encode_bits(cmd, WMI_TLV_TAG) | +@@ -2234,6 +2248,36 @@ static void ath12k_wmi_copy_peer_flags(s + cmd->peer_flags &= cpu_to_le32(~WMI_PEER_HT); + } + ++static int ath12k_wmi_get_emlsr_pad_delay(u8 emlsr_pad_delay, ++ u16 *emlsr_pad_delay_us) ++{ ++ u16 pad_delay_us[EMLSR_DELAY_MAX] = {0, 32, 64, 128, 256}; ++ ++ if (!emlsr_pad_delay_us) ++ return -EINVAL; ++ ++ if (emlsr_pad_delay >= EMLSR_DELAY_MAX) ++ return -EINVAL; ++ ++ *emlsr_pad_delay_us = pad_delay_us[emlsr_pad_delay]; ++ return 0; ++} ++ ++static int ath12k_get_emlsr_tran_delay(u8 emlsr_trans_delay, ++ u16 *emlsr_trans_delay_us) ++{ ++ u16 delay_us[EMLSR_TRANS_DELAY_MAX] = {0, 16, 32, 64, 128, 256}; ++ ++ if (!emlsr_trans_delay_us) ++ return -EINVAL; ++ ++ if (emlsr_trans_delay >= EMLSR_TRANS_DELAY_MAX) ++ return -EINVAL; ++ ++ *emlsr_trans_delay_us = delay_us[emlsr_trans_delay]; ++ return 0; ++} ++ + int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar, + struct peer_assoc_params *param) + { +@@ -2251,6 +2295,7 @@ int ath12k_wmi_send_peer_assoc_cmd(struc + u32 peer_legacy_rates_align; + u32 peer_ht_rates_align; + int i, ret, len; ++ bool emlsr_support; + + peer_legacy_rates_align = roundup(param->peer_legacy_rates.num_rates, + sizeof(u32)); +@@ -2386,6 +2431,8 @@ int ath12k_wmi_send_peer_assoc_cmd(struc + } + + /* MLO params */ ++ emlsr_support = FIELD_GET(IEEE80211_EML_CAP_EMLSR_SUPP, param->ml.eml_caps); ++ + tlv = ptr; + tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_STRUCT) | + FIELD_PREP(WMI_TLV_LEN, sizeof(*ml_params)); +@@ -2404,13 +2451,35 @@ int ath12k_wmi_send_peer_assoc_cmd(struc + FIELD_PREP(ATH12K_WMI_FLAG_MLO_LOGICAL_LINK_IDX_VALID, + param->ml.logical_link_idx_valid) | + FIELD_PREP(ATH12K_WMI_FLAG_MLO_PEER_ID_VALID, +- param->ml.peer_id_valid); ++ param->ml.peer_id_valid) | ++ FIELD_PREP(ATH12K_WMI_FLAG_MLO_EMLSR_SUPPORT, ++ emlsr_support); + + ether_addr_copy(ml_params->mld_addr.addr, param->ml.mld_addr); + ml_params->logical_link_idx = param->ml.logical_link_idx; + ml_params->ml_peer_id = param->ml.ml_peer_id; + ml_params->ieee_link_id = param->ml.ieee_link_id; +- /* TODO emlsr params */ ++ ++ /* emlsr params */ ++ if (emlsr_support) { ++ u8 timeout; ++ /*get emlsr padding delay subfield, if invalid use 0us*/ ++ ath12k_wmi_get_emlsr_pad_delay( ++ FIELD_GET(IEEE80211_EML_CAP_EMLSR_PADDING_DELAY, ++ param->ml.eml_caps), ++ &ml_params->emlsr_padding_delay_us); ++ /*get emlsr trans delay subfield value, if invalid use 0us*/ ++ ath12k_get_emlsr_tran_delay(FIELD_GET(IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY, ++ param->ml.eml_caps), ++ &ml_params->emlsr_trans_delay_us); ++ ++ timeout = FIELD_GET(IEEE80211_EML_CAP_TRANSITION_TIMEOUT, ++ param->ml.eml_caps); ++ if (timeout < EMLCAP_TIMEOUT_MAX) ++ ml_params->emlsr_trans_timeout_us = eml_trans_timeout[timeout]; ++ else ++ ath12k_warn(ar->ab, "Invalid emlsr trans timeout \n"); ++ } + + ptr += sizeof(*ml_params); + +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -4075,6 +4075,23 @@ struct wmi_rate_set_arg { + u8 rates[WMI_MAX_SUPPORTED_RATES]; + }; + ++#define EMLSR_DELAY_MAX 5 ++#define EMLSR_TRANS_DELAY_MAX 6 ++#define EMLCAP_TIMEOUT_MAX 12 ++#define IEEE80211_TU_TO_USEC(x) ((x) << 10) /* (x)X1024 */ ++#define EMLCAP_TRANSTIMEOUT_0 0 ++#define EMLCAP_TRANSTIMEOUT_1 (1U << 7) ++#define EMLCAP_TRANSTIMEOUT_2 (1U << 8) ++#define EMLCAP_TRANSTIMEOUT_3 (1U << 9) ++#define EMLCAP_TRANSTIMEOUT_4 IEEE80211_TU_TO_USEC(1) ++#define EMLCAP_TRANSTIMEOUT_5 IEEE80211_TU_TO_USEC((1U << 1)) ++#define EMLCAP_TRANSTIMEOUT_6 IEEE80211_TU_TO_USEC((1U << 2)) ++#define EMLCAP_TRANSTIMEOUT_7 IEEE80211_TU_TO_USEC((1U << 3)) ++#define EMLCAP_TRANSTIMEOUT_8 IEEE80211_TU_TO_USEC((1U << 4)) ++#define EMLCAP_TRANSTIMEOUT_9 IEEE80211_TU_TO_USEC((1U << 5)) ++#define EMLCAP_TRANSTIMEOUT_10 IEEE80211_TU_TO_USEC((1U << 6)) ++#define EMLCAP_TRANSTIMEOUT_11 IEEE80211_TU_TO_USEC((1U << 7)) ++ + struct peer_assoc_mlo_params { + bool enabled; + bool assoc_link; +@@ -4087,6 +4104,7 @@ struct peer_assoc_mlo_params { + u32 ieee_link_id; + u8 num_partner_links; + struct wmi_ml_partner_info partner_info[ATH12K_WMI_MLO_MAX_LINKS]; ++ u32 eml_caps; + }; + + struct peer_assoc_params { diff --git a/feeds/ipq95xx/mac80211/patches/qca/707-a-mac80211-framework-to-support-MLO-recovery.patch b/feeds/ipq95xx/mac80211/patches/qca/707-a-mac80211-framework-to-support-MLO-recovery.patch new file mode 100644 index 000000000..e8cb367ed --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/707-a-mac80211-framework-to-support-MLO-recovery.patch @@ -0,0 +1,293 @@ +From 8ee049fcd08c9e98e374f63f1a003a334d128867 Mon Sep 17 00:00:00 2001 +From: Pradeep Kumar Chitrapu +Date: Thu, 12 Jan 2023 09:46:29 -0800 +Subject: [PATCH 1/3] mac80211: framework to support MLO recovery + +Extend current ieee80211_reconfig to account for multiple links +BSS reconfig. Currently supports only AP mode. + +Co-Developed-by: Ramanathan Choodamani +Signed-off-by: Ramanathan Choodamani +Signed-off-by: Pradeep Kumar Chitrapu +--- + net/mac80211/util.c | 230 ++++++++++++++++++++++++-------------------- + 1 file changed, 128 insertions(+), 102 deletions(-) + +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -2368,13 +2368,133 @@ static int ieee80211_reconfig_nan(struct + return 0; + } + ++static int ieee80211_reconfig_link_bss(struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_link_data *link, ++ struct ieee80211_bss_conf *link_conf) ++{ ++ struct ieee80211_local *local = sdata->local; ++ int i, res, changed = 0; ++ ++ switch (sdata->vif.type) { ++ case NL80211_IFTYPE_AP_VLAN: ++ case NL80211_IFTYPE_MONITOR: ++ break; ++ case NL80211_IFTYPE_ADHOC: ++ if (sdata->vif.cfg.ibss_joined) ++ WARN_ON(drv_join_ibss(local, sdata)); ++ fallthrough; ++ default: ++ ieee80211_reconfig_stations(sdata); ++ fallthrough; ++ case NL80211_IFTYPE_AP: /* AP stations are handled later */ ++ for (i = 0; i < IEEE80211_NUM_ACS; i++) ++ drv_conf_tx(local, link, i, ++ &link->tx_conf[i]); ++ break; ++ } ++ ++ /* common change flags for all interface types */ ++ changed = BSS_CHANGED_ERP_CTS_PROT | ++ BSS_CHANGED_ERP_PREAMBLE | ++ BSS_CHANGED_ERP_SLOT | ++ BSS_CHANGED_HT | ++ BSS_CHANGED_BASIC_RATES | ++ BSS_CHANGED_BEACON_INT | ++ BSS_CHANGED_BSSID | ++ BSS_CHANGED_CQM | ++ BSS_CHANGED_QOS | ++ BSS_CHANGED_IDLE | ++ BSS_CHANGED_TXPOWER | ++ BSS_CHANGED_MCAST_RATE; ++ ++ if (link_conf->mu_mimo_owner) ++ changed |= BSS_CHANGED_MU_GROUPS; ++ ++ switch (sdata->vif.type) { ++ case NL80211_IFTYPE_STATION: ++ changed |= BSS_CHANGED_PS; ++ changed &= ~BSS_CHANGED_IDLE; ++ ieee80211_link_info_change_notify(sdata, link, changed); ++ ++ changed = BSS_CHANGED_ASSOC | ++ BSS_CHANGED_ARP_FILTER | ++ BSS_CHANGED_IDLE; ++ ++ ieee80211_vif_cfg_change_notify(sdata, changed); ++ changed = 0; ++ /* Re-send beacon info report to the driver */ ++ if (link->u.mgd.have_beacon) ++ changed |= BSS_CHANGED_BEACON_INFO; ++ ++ if (link_conf->max_idle_period || ++ link_conf->protected_keep_alive) ++ changed |= BSS_CHANGED_KEEP_ALIVE; ++ ++ ieee80211_link_info_change_notify(sdata, link, changed); ++ break; ++ case NL80211_IFTYPE_OCB: ++ changed |= BSS_CHANGED_OCB; ++ ieee80211_link_info_change_notify(sdata, link, changed); ++ break; ++ case NL80211_IFTYPE_ADHOC: ++ changed |= BSS_CHANGED_IBSS; ++ fallthrough; ++ case NL80211_IFTYPE_AP: ++ changed |= BSS_CHANGED_P2P_PS; ++ ++ if (link_conf->ftm_responder == 1 && ++ wiphy_ext_feature_isset(sdata->local->hw.wiphy, ++ NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER)) ++ changed |= BSS_CHANGED_FTM_RESPONDER; ++ ++ if (sdata->vif.type == NL80211_IFTYPE_AP) { ++ changed |= BSS_CHANGED_AP_PROBE_RESP; ++ ++ if (rcu_access_pointer(link->u.ap.beacon)) ++ drv_start_ap(local, sdata, ++ link->conf); ++ ++ ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_SSID); ++ } ++ fallthrough; ++ case NL80211_IFTYPE_MESH_POINT: ++ if (link_conf->enable_beacon) { ++ changed |= BSS_CHANGED_BEACON | ++ BSS_CHANGED_BEACON_ENABLED; ++ ieee80211_link_info_change_notify(sdata, link, changed &~ BSS_CHANGED_IDLE); ++ } ++ break; ++ case NL80211_IFTYPE_NAN: ++ res = ieee80211_reconfig_nan(sdata); ++ if (res < 0) { ++ ieee80211_handle_reconfig_failure(local); ++ return res; ++ } ++ break; ++ case NL80211_IFTYPE_AP_VLAN: ++ case NL80211_IFTYPE_MONITOR: ++ case NL80211_IFTYPE_P2P_DEVICE: ++ /* nothing to do */ ++ break; ++ case NL80211_IFTYPE_UNSPECIFIED: ++ case NUM_NL80211_IFTYPES: ++ case NL80211_IFTYPE_P2P_CLIENT: ++ case NL80211_IFTYPE_P2P_GO: ++ case NL80211_IFTYPE_WDS: ++ WARN_ON(1); ++ break; ++ } ++ ++ return 0; ++} ++ + int ieee80211_reconfig(struct ieee80211_local *local) + { + struct ieee80211_hw *hw = &local->hw; + struct ieee80211_sub_if_data *sdata; + struct ieee80211_chanctx *ctx; + struct sta_info *sta; +- int res, i; ++ int res; + bool reconfig_due_to_wowlan = false; + struct ieee80211_sub_if_data *sched_scan_sdata; + struct cfg80211_sched_scan_request *sched_scan_req; +@@ -2508,6 +2628,7 @@ int ieee80211_reconfig(struct ieee80211_ + + sdata = wiphy_dereference(local->hw.wiphy, + local->monitor_sdata); ++ + if (sdata && ieee80211_sdata_running(sdata)) + ieee80211_assign_chanctx(local, sdata, &sdata->deflink); + } +@@ -2520,7 +2641,6 @@ int ieee80211_reconfig(struct ieee80211_ + /* Finally also reconfigure all the BSS information */ + list_for_each_entry(sdata, &local->interfaces, list) { + unsigned int link_id; +- u32 changed; + + if (!ieee80211_sdata_running(sdata)) + continue; +@@ -2535,111 +2655,23 @@ int ieee80211_reconfig(struct ieee80211_ + if (link) + ieee80211_assign_chanctx(local, sdata, link); + } +- sdata_unlock(sdata); + +- switch (sdata->vif.type) { +- case NL80211_IFTYPE_AP_VLAN: +- case NL80211_IFTYPE_MONITOR: +- break; +- case NL80211_IFTYPE_ADHOC: +- if (sdata->vif.cfg.ibss_joined) +- WARN_ON(drv_join_ibss(local, sdata)); +- fallthrough; +- default: +- ieee80211_reconfig_stations(sdata); +- fallthrough; +- case NL80211_IFTYPE_AP: /* AP stations are handled later */ +- for (i = 0; i < IEEE80211_NUM_ACS; i++) +- drv_conf_tx(local, &sdata->deflink, i, +- &sdata->deflink.tx_conf[i]); +- break; +- } ++ for (link_id = 0; ++ link_id < ARRAY_SIZE(sdata->vif.link_conf); ++ link_id++) { ++ struct ieee80211_link_data *link; ++ struct ieee80211_bss_conf *link_conf; + +- /* common change flags for all interface types */ +- changed = BSS_CHANGED_ERP_CTS_PROT | +- BSS_CHANGED_ERP_PREAMBLE | +- BSS_CHANGED_ERP_SLOT | +- BSS_CHANGED_HT | +- BSS_CHANGED_BASIC_RATES | +- BSS_CHANGED_BEACON_INT | +- BSS_CHANGED_BSSID | +- BSS_CHANGED_CQM | +- BSS_CHANGED_QOS | +- BSS_CHANGED_IDLE | +- BSS_CHANGED_TXPOWER | +- BSS_CHANGED_MCAST_RATE; +- +- if (sdata->vif.bss_conf.mu_mimo_owner) +- changed |= BSS_CHANGED_MU_GROUPS; +- +- switch (sdata->vif.type) { +- case NL80211_IFTYPE_STATION: +- changed |= BSS_CHANGED_ASSOC | +- BSS_CHANGED_ARP_FILTER | +- BSS_CHANGED_PS; +- +- /* Re-send beacon info report to the driver */ +- if (sdata->deflink.u.mgd.have_beacon) +- changed |= BSS_CHANGED_BEACON_INFO; +- +- if (sdata->vif.bss_conf.max_idle_period || +- sdata->vif.bss_conf.protected_keep_alive) +- changed |= BSS_CHANGED_KEEP_ALIVE; +- +- sdata_lock(sdata); +- ieee80211_bss_info_change_notify(sdata, changed); +- sdata_unlock(sdata); +- break; +- case NL80211_IFTYPE_OCB: +- changed |= BSS_CHANGED_OCB; +- ieee80211_bss_info_change_notify(sdata, changed); +- break; +- case NL80211_IFTYPE_ADHOC: +- changed |= BSS_CHANGED_IBSS; +- fallthrough; +- case NL80211_IFTYPE_AP: +- changed |= BSS_CHANGED_SSID | BSS_CHANGED_P2P_PS; +- +- if (sdata->vif.bss_conf.ftm_responder == 1 && +- wiphy_ext_feature_isset(sdata->local->hw.wiphy, +- NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER)) +- changed |= BSS_CHANGED_FTM_RESPONDER; +- +- if (sdata->vif.type == NL80211_IFTYPE_AP) { +- changed |= BSS_CHANGED_AP_PROBE_RESP; +- +- if (rcu_access_pointer(sdata->deflink.u.ap.beacon)) +- drv_start_ap(local, sdata, +- sdata->deflink.conf); +- } +- fallthrough; +- case NL80211_IFTYPE_MESH_POINT: +- if (sdata->vif.bss_conf.enable_beacon) { +- changed |= BSS_CHANGED_BEACON | +- BSS_CHANGED_BEACON_ENABLED; +- ieee80211_bss_info_change_notify(sdata, changed); +- } +- break; +- case NL80211_IFTYPE_NAN: +- res = ieee80211_reconfig_nan(sdata); +- if (res < 0) { +- ieee80211_handle_reconfig_failure(local); ++ link = sdata_dereference(sdata->link[link_id], sdata); ++ if (!link) ++ continue; ++ ++ link_conf = link->conf; ++ res = ieee80211_reconfig_link_bss(sdata, link, link_conf); ++ if (res < 0) + return res; +- } +- break; +- case NL80211_IFTYPE_AP_VLAN: +- case NL80211_IFTYPE_MONITOR: +- case NL80211_IFTYPE_P2P_DEVICE: +- /* nothing to do */ +- break; +- case NL80211_IFTYPE_UNSPECIFIED: +- case NUM_NL80211_IFTYPES: +- case NL80211_IFTYPE_P2P_CLIENT: +- case NL80211_IFTYPE_P2P_GO: +- case NL80211_IFTYPE_WDS: +- WARN_ON(1); +- break; + } ++ sdata_unlock(sdata); + } + + ieee80211_recalc_ps(local); diff --git a/feeds/ipq95xx/mac80211/patches/qca/707-ath12k-Add-HTT_TX_PDEV_MU_MIMO_SCH_STATS_TLV-stats.patch b/feeds/ipq95xx/mac80211/patches/qca/707-ath12k-Add-HTT_TX_PDEV_MU_MIMO_SCH_STATS_TLV-stats.patch new file mode 100644 index 000000000..780e850cb --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/707-ath12k-Add-HTT_TX_PDEV_MU_MIMO_SCH_STATS_TLV-stats.patch @@ -0,0 +1,134 @@ +From 70957d2b60f5121582432ca28861daf5153c2182 Mon Sep 17 00:00:00 2001 +From: Rajat Soni +Date: Mon, 23 Jan 2023 11:07:40 +0530 +Subject: [PATCH] ath12k: Add HTT_TX_PDEV_MU_MIMO_SCH_STATS_TLV stats + +Some stats of HTT_TX_PDEV_MU_MIMO_SCH_STATS_TLV is missing. +Add HTT_TX_PDEV_MU_MIMO_SCH_STATS_TLV mu_mimo_sch_posted_per_group_index +values. + +Signed-off-by: Rajat Soni +--- + .../wireless/ath/ath12k/debugfs_htt_stats.c | 71 ++++++++++++++++++- + .../wireless/ath/ath12k/debugfs_htt_stats.h | 11 +++ + 2 files changed, 80 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c +index 078e03c..e4a319a 100644 +--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c +@@ -1850,7 +1850,42 @@ htt_print_tx_pdev_mu_mimo_sch_stats_tlv(const void *tag_buf, + len += scnprintf(buf + len, buf_len - len, "mu_mimo_ppdu_posted = %u\n", + htt_stats_buf->mu_mimo_ppdu_posted); + +- len += scnprintf(buf + len, buf_len - len, "11ac MU_MIMO SCH STATS:\n"); ++ len += scnprintf(buf + len, buf_len - len, ++ "\nac_mu_mimo_sch_posted_per_group_index %u (SU) = %u,\n", ++ 0, htt_stats_buf->ac_mu_mimo_sch_posted_per_grp_sz[0]); ++ for (i = 1; i < HTT_TX_PDEV_STATS_NUM_AC_MUMIMO_USER_STATS; i++) { ++ len += scnprintf(buf + len, buf_len - len, ++ "ac_mu_mimo_sch_posted_per_group_index %u (TOTAL STREAMS = %u) = %u,\n", ++ i, i+1, htt_stats_buf->ac_mu_mimo_sch_posted_per_grp_sz[i]); ++ } ++ ++ for (i = 0; i < HTT_TX_PDEV_STATS_NUM_AC_MUMIMO_USER_STATS; i++) { ++ len += scnprintf(buf + len, buf_len - len, ++ "ac_mu_mimo_sch_posted_per_group_index %u (TOTAL STREAMS = %u) = %u,\n", ++ i+HTT_TX_PDEV_STATS_NUM_AC_MUMIMO_USER_STATS, ++ i+HTT_TX_PDEV_STATS_NUM_AC_MUMIMO_USER_STATS+1, ++ htt_stats_buf->ac_mu_mimo_sch_posted_per_grp_sz_ext[i]); ++ } ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "\nax_mu_mimo_sch_posted_per_group_index %u (SU) = %u,\n", ++ 0, htt_stats_buf->ax_mu_mimo_sch_posted_per_grp_sz[0]); ++ for (i = 1; i < HTT_TX_PDEV_STATS_NUM_AX_MUMIMO_USER_STATS; i++) { ++ len += scnprintf(buf + len, buf_len - len, ++ "ax_mu_mimo_sch_posted_per_group_index %u (TOTAL STREAMS = %u) = %u,\n", ++ i, i+1, htt_stats_buf->ax_mu_mimo_sch_posted_per_grp_sz[i]); ++ } ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "\nbe_mu_mimo_sch_posted_per_group_index %u (SU) = %u,\n", ++ 0, htt_stats_buf->be_mu_mimo_sch_posted_per_grp_sz[0]); ++ for (i = 1; i < HTT_TX_PDEV_STATS_NUM_BE_MUMIMO_USER_STATS; i++) { ++ len += scnprintf(buf + len, buf_len - len, ++ "be_mu_mimo_sch_posted_per_group_index %u (TOTAL STREAMS = %u) = %u,\n", ++ i, i+1, htt_stats_buf->be_mu_mimo_sch_posted_per_grp_sz[i]); ++ } ++ ++ len += scnprintf(buf + len, buf_len - len, "\n11ac MU_MIMO SCH STATS:\n"); + + for (i = 0; i < HTT_TX_PDEV_STATS_NUM_AC_MUMIMO_USER_STATS; i++) + len += scnprintf(buf + len, buf_len - len, +@@ -1864,12 +1899,44 @@ htt_print_tx_pdev_mu_mimo_sch_stats_tlv(const void *tag_buf, + "ax_mu_mimo_sch_nusers_%u = %u\n", + i, htt_stats_buf->ax_mu_mimo_sch_nusers[i]); + ++ len += scnprintf(buf + len, buf_len - len, "\n11be MU_MIMO SCH STATS:\n"); ++ for (i = 0; i < HTT_TX_PDEV_STATS_NUM_BE_MUMIMO_USER_STATS; i++) { ++ len += scnprintf(buf + len, buf_len - len, ++ "be_mu_mimo_sch_nusers_%u = %u\n", ++ i, htt_stats_buf->be_mu_mimo_sch_nusers[i]); ++ } ++ + len += scnprintf(buf + len, buf_len - len, "\n11ax OFDMA SCH STATS:\n"); + +- for (i = 0; i < HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS; i++) ++ for (i = 0; i < HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS; i++) { + len += scnprintf(buf + len, buf_len - len, + "ax_ofdma_sch_nusers_%u = %u\n", + i, htt_stats_buf->ax_ofdma_sch_nusers[i]); ++ len += scnprintf(buf + len, buf_len - len, ++ "ax_ul_ofdma_basic_sch_nusers_%u = %u\n", ++ i, htt_stats_buf->ax_ul_ofdma_basic_sch_nusers[i]); ++ len += scnprintf(buf + len, buf_len - len, ++ "ax_ul_ofdma_bsr_sch_nusers_%u = %u\n", ++ i, htt_stats_buf->ax_ul_ofdma_bsr_sch_nusers[i]); ++ len += scnprintf(buf + len, buf_len - len, ++ "ax_ul_ofdma_bar_sch_nusers_%u = %u\n", ++ i, htt_stats_buf->ax_ul_ofdma_bar_sch_nusers[i]); ++ len += scnprintf(buf + len, buf_len - len, ++ "ax_ul_ofdma_brp_sch_nusers_%u = %u\n", ++ i, htt_stats_buf->ax_ul_ofdma_brp_sch_nusers[i]); ++ } ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "\n11ax UL MUMIMO SCH STATS:"); ++ ++ for (i = 0; i < HTT_TX_PDEV_STATS_NUM_UL_MUMIMO_USER_STATS; i++) { ++ len += scnprintf(buf + len, buf_len - len, ++ "ax_ul_mumimo_basic_sch_nusers_%u = %u\n", i, ++ htt_stats_buf->ax_ul_mumimo_basic_sch_nusers[i]); ++ len += scnprintf(buf + len, buf_len - len, ++ "ax_ul_mumimo_brp_sch_nusers_%u = %u\n", i, ++ htt_stats_buf->ax_ul_mumimo_brp_sch_nusers[i]); ++ } + + stats_req->buf_len = len; + } +diff --git a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h +index 5ebc892..3209c41 100644 +--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h ++++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h +@@ -972,6 +972,17 @@ struct htt_tx_pdev_mu_mimo_sch_stats_tlv { + u32 ac_mu_mimo_sch_nusers[HTT_TX_PDEV_STATS_NUM_AC_MUMIMO_USER_STATS]; + u32 ax_mu_mimo_sch_nusers[HTT_TX_PDEV_STATS_NUM_AX_MUMIMO_USER_STATS]; + u32 ax_ofdma_sch_nusers[HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS]; ++ u32 ax_ul_ofdma_basic_sch_nusers[HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS]; ++ u32 ax_ul_ofdma_bsr_sch_nusers[HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS]; ++ u32 ax_ul_ofdma_bar_sch_nusers[HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS]; ++ u32 ax_ul_ofdma_brp_sch_nusers[HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS]; ++ u32 ax_ul_mumimo_basic_sch_nusers[HTT_TX_PDEV_STATS_NUM_UL_MUMIMO_USER_STATS]; ++ u32 ax_ul_mumimo_brp_sch_nusers[HTT_TX_PDEV_STATS_NUM_UL_MUMIMO_USER_STATS]; ++ u32 ac_mu_mimo_sch_posted_per_grp_sz[HTT_TX_PDEV_STATS_NUM_AC_MUMIMO_USER_STATS]; ++ u32 ax_mu_mimo_sch_posted_per_grp_sz[HTT_TX_PDEV_STATS_NUM_AX_MUMIMO_USER_STATS]; ++ u32 be_mu_mimo_sch_nusers[HTT_TX_PDEV_STATS_NUM_BE_MUMIMO_USER_STATS]; ++ u32 be_mu_mimo_sch_posted_per_grp_sz[HTT_TX_PDEV_STATS_NUM_BE_MUMIMO_USER_STATS]; ++ u32 ac_mu_mimo_sch_posted_per_grp_sz_ext[HTT_TX_PDEV_STATS_NUM_AC_MUMIMO_USER_STATS]; + }; + + struct htt_tx_pdev_mumimo_grp_stats_tlv { +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/680-ath12k-Add-support-to-read-caldata-from-EEPROM.patch b/feeds/ipq95xx/mac80211/patches/qca/707-ath12k-Add-support-to-read-caldata-from-EEPROM.patch similarity index 69% rename from feeds/ipq95xx/mac80211/patches/qca/680-ath12k-Add-support-to-read-caldata-from-EEPROM.patch rename to feeds/ipq95xx/mac80211/patches/qca/707-ath12k-Add-support-to-read-caldata-from-EEPROM.patch index d8fb29ed6..8773f9599 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/680-ath12k-Add-support-to-read-caldata-from-EEPROM.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/707-ath12k-Add-support-to-read-caldata-from-EEPROM.patch @@ -1,61 +1,44 @@ -From 1fb8d2165cfbacfcd314049e423732186b1f6ae9 Mon Sep 17 00:00:00 2001 +From f7b7740c19dc3ae5114ffe8b616ab734c3913b45 Mon Sep 17 00:00:00 2001 From: Dinesh Karthikeyan -Date: Fri, 23 Sep 2022 12:51:49 +0530 +Date: Thu, 19 Jan 2023 12:49:23 +0530 Subject: [PATCH] ath12k: Add support to read caldata from EEPROM -Define qmi elements to read calibrated data from EEPROM to improve -throughput. The improvement is in the range of 2-3% in TP numbers. +In current implementation, there is a overhead of maintaining caldata +in the filesystem manually.To eliminate this overhead, for pci based +chipsets, if calibration data is present in EEPROM, indicate firmware +to download and read caldata from EEPROM. If the caldata is present +in EEPROM, host is notified in the target capability. This also +improves the throughput in the range of 1-2%. Without EEPROM: Test Case TP(Mbps) -TCP_DL_6G :6575 -TCP_UL_6G :7192 -TCP_BiDi_6G :7372 -UDP_DL_6G :7165 -UDP_UL_6G :8600 -UDP_BiDi_6G :6338 +TCP_DL_6G :3513 +TCP_UL_6G :6860 +TCP_BiDi_6G :5476 +UDP_DL_6G :3957 +UDP_UL_6G :7683 +UDP_BiDi_6G :4985 With EEPROM: Test Case TP(Mbps) -TCP_DL_6G :6006 -TCP_UL_6G :7294 -TCP_BiDi_6G :7867 -UDP_DL_6G :6095 -UDP_UL_6G :8764 -UDP_BiDi_6G :7968 +TCP_DL_6G :3961 +TCP_UL_6G :7034 +TCP_BiDi_6G :5561 +UDP_DL_6G :3959 +UDP_UL_6G :7788 +UDP_BiDi_6G :5090 Signed-off-by: Dinesh Karthikeyan --- - drivers/net/wireless/ath/ath12k/qmi.c | 118 ++++++++++++-------------- + drivers/net/wireless/ath/ath12k/qmi.c | 115 +++++++++++--------------- drivers/net/wireless/ath/ath12k/qmi.h | 3 +- - 2 files changed, 57 insertions(+), 64 deletions(-) + 2 files changed, 52 insertions(+), 66 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c -index fd1b6a6..631d4db 100644 +index e2e1b2c..8d9121e 100644 --- a/drivers/net/wireless/ath/ath12k/qmi.c +++ b/drivers/net/wireless/ath/ath12k/qmi.c -@@ -3447,12 +3447,19 @@ static int ath12k_qmi_load_file_target_mem(struct ath12k_base *ab, - QMI_WLANFW_BDF_DOWNLOAD_REQ_V01, - QMI_WLANFW_BDF_DOWNLOAD_REQ_MSG_V01_MAX_LEN, - qmi_wlanfw_bdf_download_req_msg_v01_ei, req); -+ - if (ret < 0) { - qmi_txn_cancel(&txn); - goto out; - } - -- ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH12K_QMI_WLANFW_TIMEOUT_MS)); -+ if (type == ATH12K_QMI_FILE_TYPE_EEPROM) { -+ ret = qmi_txn_wait(&txn, msecs_to_jiffies(ab->qmi.target.eeprom_caldata * 1000)); -+ ath12k_info(ab, "EEPROM Read wait time:%d seconds\n", ab->qmi.target.eeprom_caldata); -+ } else { -+ ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH12K_QMI_WLANFW_TIMEOUT_MS)); -+ } -+ - if (ret < 0) - goto out; - -@@ -3463,7 +3470,7 @@ static int ath12k_qmi_load_file_target_mem(struct ath12k_base *ab, +@@ -3770,7 +3770,7 @@ static int ath12k_qmi_load_file_target_mem(struct ath12k_base *ab, goto out; } @@ -64,7 +47,7 @@ index fd1b6a6..631d4db 100644 remaining = 0; } else { remaining -= req->data_len; -@@ -3518,6 +3525,48 @@ static int ath12k_qmi_load_bdf_qmi(struct ath12k_base *ab, +@@ -3825,6 +3825,49 @@ static int ath12k_qmi_load_bdf_qmi(struct ath12k_base *ab, } type = ATH12K_QMI_BDF_TYPE_REGDB; break; @@ -73,6 +56,7 @@ index fd1b6a6..631d4db 100644 + file_type = ATH12K_QMI_FILE_TYPE_EEPROM; + tmp = filename; + fw_size = ATH12K_QMI_MAX_BDF_FILE_NAME_SIZE; ++ ath12k_info(ab, "qmi file type: %u - EEPROM\n", file_type); + } else { + file_type = ATH12K_QMI_FILE_TYPE_CALDATA; + @@ -93,7 +77,7 @@ index fd1b6a6..631d4db 100644 + } + +success: -+ fw_size = min_t(u32, ab->hw_params.fw.board_size, fw_entry->size); ++ fw_size = min_t(u32, ab->hw_params->fw.board_size, fw_entry->size); + tmp = fw_entry->data; + } + @@ -109,14 +93,17 @@ index fd1b6a6..631d4db 100644 +out_qmi_cal: + if (!ab->qmi.target.eeprom_caldata) + release_firmware(fw_entry); -+ break; ++ return ret; default: ath12k_warn(ab, "unknown file type for load %d", type); goto out; -@@ -3534,67 +3583,6 @@ static int ath12k_qmi_load_bdf_qmi(struct ath12k_base *ab, +@@ -3840,70 +3883,6 @@ static int ath12k_qmi_load_bdf_qmi(struct ath12k_base *ab, goto out; } +- if (!ab->hw_params->download_calib) +- goto out; +- - ret = 0; - goto out; - @@ -162,7 +149,7 @@ index fd1b6a6..631d4db 100644 - } - -success: -- fw_size = min_t(u32, ab->hw_params.fw.board_size, fw_entry->size); +- fw_size = min_t(u32, ab->hw_params->fw.board_size, fw_entry->size); - tmp = fw_entry->data; - } - @@ -181,22 +168,24 @@ index fd1b6a6..631d4db 100644 out: ath12k_core_free_bdf(ab, &bd); ath12k_dbg(ab, ATH12K_DBG_QMI, "qmi BDF download sequence completed\n"); -@@ -4302,6 +4290,10 @@ static int ath12k_qmi_event_load_bdf(struct ath12k_qmi *qmi) +@@ -4725,6 +4704,12 @@ static int ath12k_qmi_event_load_bdf(struct ath12k_qmi *qmi) return ret; } -+ ret = ath12k_qmi_load_bdf_qmi(ab, ATH12K_QMI_BDF_TYPE_CALIBRATION); -+ if (ret < 0) -+ ath12k_warn(ab, "qmi failed to load calibrated data :%d\n", ret); ++ if(ab->hw_params->download_calib) { ++ ret = ath12k_qmi_load_bdf_qmi(ab, ATH12K_QMI_BDF_TYPE_CALIBRATION); ++ if (ret < 0) ++ ath12k_warn(ab, "qmi failed to load calibrated data :%d\n", ret); ++ } + ret = ath12k_qmi_wlanfw_m3_info_send(ab); if (ret < 0) { ath12k_warn(ab, "qmi failed to send m3 info req:%d\n", ret); diff --git a/drivers/net/wireless/ath/ath12k/qmi.h b/drivers/net/wireless/ath/ath12k/qmi.h -index b82ae9d..c8d0fb9 100644 +index 01722bf..3007d3f 100644 --- a/drivers/net/wireless/ath/ath12k/qmi.h +++ b/drivers/net/wireless/ath/ath12k/qmi.h -@@ -51,7 +51,7 @@ struct ath12k_base; +@@ -57,7 +57,7 @@ struct ath12k_base; enum ath12k_qmi_file_type { ATH12K_QMI_FILE_TYPE_BDF_GOLDEN, @@ -205,7 +194,7 @@ index b82ae9d..c8d0fb9 100644 ATH12K_QMI_FILE_TYPE_EEPROM, ATH12K_QMI_MAX_FILE_TYPE, }; -@@ -60,6 +60,7 @@ enum ath12k_qmi_bdf_type { +@@ -66,6 +66,7 @@ enum ath12k_qmi_bdf_type { ATH12K_QMI_BDF_TYPE_BIN = 0, ATH12K_QMI_BDF_TYPE_ELF = 1, ATH12K_QMI_BDF_TYPE_REGDB = 4, diff --git a/feeds/ipq95xx/mac80211/patches/qca/707-ath12k-Add-wmi-control-path-stats.patch b/feeds/ipq95xx/mac80211/patches/qca/707-ath12k-Add-wmi-control-path-stats.patch new file mode 100644 index 000000000..acd2c9bb6 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/707-ath12k-Add-wmi-control-path-stats.patch @@ -0,0 +1,1089 @@ +From f0087e1598e566a150b82b2df5f93b32059e2ea6 Mon Sep 17 00:00:00 2001 +From: Rajat Soni +Date: Wed, 8 Feb 2023 10:11:21 +0530 +Subject: [PATCH] ath12k: Add wmi control path stats + +Add wmi control path stats in ath12k. + +Currently, ath12k HTT debugfs uses the HTT interface to send stats request +to target and response from target. Here HTT interface already overloaded +with the data path stats. To reduce the load from HTT, using WMI interface +to print the control path stats. This patch come up with framework for +control path stats using wmi interface. + +Add support for following stats: + +WMI_REQ_CTRL_PATH_PDEV_TX_STAT +WMI_REQ_CTRL_PATH_CAL_STAT +WMI_REQ_CTRL_PATH_BTCOEX_STAT + +Command: + +echo > sys/kernel/debug/ath12k/qcn9274\ hw2.0_0002:01:00.0/m +ac0/wmi_ctrl_stats +cat sys/kernel/debug/ath12k/qcn9274\ hw2.0_0002:01:00.0/mac0/wmi +_ctrl_stats + +stats_id = 1 or 5 or 8 + +1: WMI_REQ_CTRL_PATH_PDEV_TX_STAT +5: WMI_REQ_CTRL_PATH_CAL_STAT +8: WMI_REQ_CTRL_PATH_BTCOEX_STAT + +action = 1 or 2 + +1: WMI_REQUEST_CTRL_PATH_STAT_GET +2: WMI_REQUEST_CTRL_PATH_STAT_RESET + +echo 1 1 > sys/kernel/debug/ath12k/qcn9274\ hw2.0_0002:01:00.0/m +ac0/wmi_ctrl_stats + +cat sys/kernel/debug/ath12k/qcn9274\ hw2.0_0002:01:00.0/mac0/wmi +_ctrl_stats + +WMI_CTRL_PATH_PDEV_TX_STATS: +fw_tx_mgmt_subtype = 0:0, 1:0, 2:0, 3:0, 4:0, 5:1857, 6:0, 7:0, +8:5529, 9:0, 10:0, 11:0, 12:15, 13:0, 14:0, 15:0, +fw_rx_mgmt_subtype = 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, +9:0, 10:0, 11:0, 12:0, 13:0, 14:0, 15:0, +scan_fail_dfs_violation_time_ms = 0 +nol_chk_fail_last_chan_freq = 0 +nol_chk_fail_time_stamp_ms = 0 +tot_peer_create_cnt = 16 +tot_peer_del_cnt = 8 +tot_peer_del_resp_cnt = 8 +vdev_pause_fail_rt_to_sched_algo_fifo_full_cnt = 0 + +Signed-off-by: Thiraviyam Mariyappan +Signed-off-by: Rajat Soni +--- + drivers/net/wireless/ath/ath12k/core.h | 7 + + drivers/net/wireless/ath/ath12k/debugfs.c | 296 +++++++++++++++++++ + drivers/net/wireless/ath/ath12k/debugfs.h | 2 + + drivers/net/wireless/ath/ath12k/wmi.c | 342 ++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/wmi.h | 258 ++++++++++++++++ + 5 files changed, 905 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h +index b29a6c6..3e0a292 100644 +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -680,6 +680,9 @@ struct ath12k_debug { + bool is_pkt_logging; + #endif + u32 rx_filter; ++ struct list_head wmi_list; ++ struct completion wmi_ctrl_path_stats_rcvd; ++ u32 wmi_ctrl_path_stats_tagid; + }; + + int ath12k_pktlog_rx_filter_setting(struct ath12k *ar, +@@ -849,6 +852,10 @@ struct ath12k { + u32 cached_ppdu_id; + #ifdef CPTCFG_ATH12K_DEBUGFS + struct ath12k_debug debug; ++ struct dentry *wmi_ctrl_stat; ++ /* To protect wmi_list manipulation */ ++ struct mutex wmi_ctrl_path_stats_lock; ++ /* TODO: Add mac_filter, ampdu_aggr_size and wbm_tx_completion_stats stats*/ + #endif + #ifdef CPTCFG_ATH12K_SPECTRAL + struct ath12k_spectral spectral; +diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c +index 77f59ae..5bb7647 100644 +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -117,6 +117,297 @@ void ath12k_debugfs_fw_stats_process(struct ath12k *ar, + } + } + ++static ssize_t ath12k_write_wmi_ctrl_path_stats(struct file *file, ++ const char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ struct wmi_ctrl_path_stats_cmd_param param = {0}; ++ u8 buf[128] = {0}; ++ int ret; ++ ++ ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count); ++ if (ret < 0) ++ return ret; ++ ++ buf[ret] = '\0'; ++ ++ ret = sscanf(buf, "%u %u", ¶m.stats_id, ¶m.action); ++ if (ret != 2) ++ return -EINVAL; ++ ++ if (!param.action || param.action > WMI_REQUEST_CTRL_PATH_STAT_RESET) ++ return -EINVAL; ++ ++ ret = ath12k_wmi_send_wmi_ctrl_stats_cmd(ar, ¶m); ++ return ret ? ret : count; ++} ++ ++int wmi_ctrl_path_pdev_stat(struct ath12k *ar, const char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ const int size = 2048; ++ char *buf; ++ u8 i; ++ int len = 0, ret_val; ++ u16 index_tx = 0; ++ u16 index_rx = 0; ++ char fw_tx_mgmt_subtype[WMI_MAX_STRING_LEN] = {0}; ++ char fw_rx_mgmt_subtype[WMI_MAX_STRING_LEN] = {0}; ++ struct wmi_ctrl_path_stats_list *stats; ++ struct wmi_ctrl_path_pdev_stats *pdev_stats; ++ ++ buf = kzalloc(size, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ mutex_lock(&ar->wmi_ctrl_path_stats_lock); ++ list_for_each_entry(stats, &ar->debug.wmi_list, list) { ++ if (!stats) ++ break; ++ ++ pdev_stats = stats->stats_ptr; ++ ++ if (!pdev_stats) ++ break; ++ ++ for (i = 0; i < WMI_MGMT_FRAME_SUBTYPE_MAX; i++) { ++ index_tx += snprintf(&fw_tx_mgmt_subtype[index_tx], ++ WMI_MAX_STRING_LEN - index_tx, ++ " %u:%u,", i, ++ pdev_stats->tx_mgmt_subtype[i]); ++ index_rx += snprintf(&fw_rx_mgmt_subtype[index_rx], ++ WMI_MAX_STRING_LEN - index_rx, ++ " %u:%u,", i, ++ pdev_stats->rx_mgmt_subtype[i]); ++ } ++ ++ len += scnprintf(buf + len, size - len, ++ "WMI_CTRL_PATH_PDEV_TX_STATS:\n"); ++ len += scnprintf(buf + len, size - len, ++ "fw_tx_mgmt_subtype = %s\n", ++ fw_tx_mgmt_subtype); ++ len += scnprintf(buf + len, size - len, ++ "fw_rx_mgmt_subtype = %s\n", ++ fw_rx_mgmt_subtype); ++ len += scnprintf(buf + len, size - len, ++ "scan_fail_dfs_violation_time_ms = %u\n", ++ pdev_stats->scan_fail_dfs_violation_time_ms); ++ len += scnprintf(buf + len, size - len, ++ "nol_chk_fail_last_chan_freq = %u\n", ++ pdev_stats->nol_chk_fail_last_chan_freq); ++ len += scnprintf(buf + len, size - len, ++ "nol_chk_fail_time_stamp_ms = %u\n", ++ pdev_stats->nol_chk_fail_time_stamp_ms); ++ len += scnprintf(buf + len, size - len, ++ "tot_peer_create_cnt = %u\n", ++ pdev_stats->tot_peer_create_cnt); ++ len += scnprintf(buf + len, size - len, ++ "tot_peer_del_cnt = %u\n", ++ pdev_stats->tot_peer_del_cnt); ++ len += scnprintf(buf + len, size - len, ++ "tot_peer_del_resp_cnt = %u\n", ++ pdev_stats->tot_peer_del_resp_cnt); ++ len += scnprintf(buf + len, size - len, ++ "vdev_pause_fail_rt_to_sched_algo_fifo_full_cnt = %u\n", ++ pdev_stats->vdev_pause_fail_rt_to_sched_algo_fifo_full_cnt); ++ } ++ ++ ath12k_wmi_crl_path_stats_list_free(ar, &ar->debug.wmi_list); ++ mutex_unlock(&ar->wmi_ctrl_path_stats_lock); ++ ret_val = simple_read_from_buffer(ubuf, count, ppos, buf, len); ++ kfree(buf); ++ return ret_val; ++} ++ ++int wmi_ctrl_path_cal_stat(struct ath12k *ar, const char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ const int size = 4096; ++ char *buf; ++ u8 cal_type_mask, cal_prof_mask, is_periodic_cal; ++ int len = 0, ret_val; ++ struct wmi_ctrl_path_stats_list *stats; ++ struct wmi_ctrl_path_cal_stats *cal_stats; ++ ++ buf = kzalloc(size, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ len += scnprintf(buf + len, size - len, ++ "WMI_CTRL_PATH_CAL_STATS\n"); ++ len += scnprintf(buf + len, size - len, ++ "%-25s %-25s %-17s %-16s %-16s %-16s\n", ++ "cal_profile", "cal_type", ++ "cal_triggered_cnt", "cal_fail_cnt", ++ "cal_fcs_cnt", "cal_fcs_fail_cnt"); ++ ++ mutex_lock(&ar->wmi_ctrl_path_stats_lock); ++ list_for_each_entry(stats, &ar->debug.wmi_list, list) { ++ if (!stats) ++ break; ++ ++ cal_stats = stats->stats_ptr; ++ ++ if (!cal_stats) ++ break; ++ ++ cal_prof_mask = FIELD_GET(WMI_CTRL_PATH_CAL_PROF_MASK, ++ cal_stats->cal_info); ++ if (cal_prof_mask == WMI_CTRL_PATH_STATS_CAL_PROFILE_INVALID) ++ continue; ++ ++ cal_type_mask = FIELD_GET(WMI_CTRL_PATH_CAL_TYPE_MASK, ++ cal_stats->cal_info); ++ is_periodic_cal = FIELD_GET(WMI_CTRL_PATH_IS_PERIODIC_CAL, ++ cal_stats->cal_info); ++ ++ ++ if (!is_periodic_cal) { ++ len += scnprintf(buf + len, size - len, ++ "%-25s %-25s %-17d %-16d %-16d %-16d\n", ++ wmi_ctrl_path_cal_prof_id_to_name(cal_prof_mask), ++ wmi_ctrl_path_cal_type_id_to_name(cal_type_mask), ++ cal_stats->cal_triggered_cnt, ++ cal_stats->cal_fail_cnt, ++ cal_stats->cal_fcs_cnt, ++ cal_stats->cal_fcs_fail_cnt); ++ } else { ++ len += scnprintf(buf + len, size - len, ++ "%-25s %-25s %-17d %-16d %-16d %-16d\n", ++ "PERIODIC_CAL", ++ wmi_ctrl_path_periodic_cal_type_id_to_name(cal_type_mask), ++ cal_stats->cal_triggered_cnt, ++ cal_stats->cal_fail_cnt, ++ cal_stats->cal_fcs_cnt, ++ cal_stats->cal_fcs_fail_cnt); ++ } ++ ++ } ++ ++ ath12k_wmi_crl_path_stats_list_free(ar, &ar->debug.wmi_list); ++ mutex_unlock(&ar->wmi_ctrl_path_stats_lock); ++ ret_val = simple_read_from_buffer(ubuf, count, ppos, buf, len); ++ kfree(buf); ++ return ret_val; ++} ++ ++int wmi_ctrl_path_btcoex_stat(struct ath12k *ar, const char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct wmi_ctrl_path_stats_list *stats; ++ struct wmi_ctrl_path_btcoex_stats *btcoex_stats; ++ const int size = 2048; ++ int len = 0, ret_val; ++ char *buf; ++ ++ buf = kzalloc(size, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ mutex_lock(&ar->wmi_ctrl_path_stats_lock); ++ list_for_each_entry(stats, &ar->debug.wmi_list, list) { ++ if (!stats) ++ break; ++ ++ btcoex_stats = stats->stats_ptr; ++ ++ if (!btcoex_stats) ++ break; ++ ++ len += scnprintf(buf + len, size - len, ++ "WMI_CTRL_PATH_BTCOEX_STATS:\n"); ++ len += scnprintf(buf + len, size - len, ++ "pdev_id = %u\n", ++ btcoex_stats->pdev_id); ++ len += scnprintf(buf + len, size - len, ++ "bt_tx_req_cntr = %u\n", ++ btcoex_stats->bt_tx_req_cntr); ++ len += scnprintf(buf + len, size - len, ++ "bt_rx_req_cntr = %u\n", ++ btcoex_stats->bt_rx_req_cntr); ++ len += scnprintf(buf + len, size - len, ++ "bt_req_nack_cntr = %u\n", ++ btcoex_stats->bt_req_nack_cntr); ++ len += scnprintf(buf + len, size - len, ++ "wl_tx_req_nack_schd_bt_reason_cntr = %u\n", ++ btcoex_stats->wl_tx_req_nack_schd_bt_reason_cntr); ++ len += scnprintf(buf + len, size - len, ++ "wl_tx_req_nack_current_bt_reason_cntr = %u\n", ++ btcoex_stats->wl_tx_req_nack_current_bt_reason_cntr); ++ len += scnprintf(buf + len, size - len, ++ "wl_tx_req_nack_other_wlan_tx_reason_cntr = %u\n", ++ btcoex_stats->wl_tx_req_nack_other_wlan_tx_reason_cntr); ++ len += scnprintf(buf + len, size - len, ++ "wl_in_tx_abort_cntr = %u\n", ++ btcoex_stats->wl_in_tx_abort_cntr); ++ len += scnprintf(buf + len, size - len, ++ "wl_tx_auto_resp_req_cntr = %u\n", ++ btcoex_stats->wl_tx_auto_resp_req_cntr); ++ len += scnprintf(buf + len, size - len, ++ "wl_tx_req_ack_cntr = %u\n", ++ btcoex_stats->wl_tx_req_ack_cntr); ++ len += scnprintf(buf + len, size - len, ++ "wl_tx_req_cntr = %u\n", ++ btcoex_stats->wl_tx_req_cntr); ++ } ++ ++ ath12k_wmi_crl_path_stats_list_free(ar, &ar->debug.wmi_list); ++ mutex_unlock(&ar->wmi_ctrl_path_stats_lock); ++ ret_val = simple_read_from_buffer(ubuf, count, ppos, buf, len); ++ kfree(buf); ++ return ret_val; ++} ++ ++static ssize_t ath12k_read_wmi_ctrl_path_stats(struct file *file, ++ const char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ int ret_val = 0; ++ u32 tagid = 0; ++ ++ tagid = ar->debug.wmi_ctrl_path_stats_tagid; ++ ++ switch (tagid) { ++ case WMI_CTRL_PATH_PDEV_STATS: ++ ret_val = wmi_ctrl_path_pdev_stat(ar, ubuf, count, ppos); ++ break; ++ case WMI_CTRL_PATH_CAL_STATS: ++ ret_val = wmi_ctrl_path_cal_stat(ar, ubuf, count, ppos); ++ break; ++ case WMI_CTRL_PATH_BTCOEX_STATS: ++ ret_val = wmi_ctrl_path_btcoex_stat(ar, ubuf, count, ppos); ++ break; ++ /* Add case for newly wmi ctrl path added stats here */ ++ default: ++ /* Unsupported tag */ ++ ret_val = -EINVAL; ++ break; ++ } ++ ++ return ret_val; ++} ++ ++static const struct file_operations ath12k_fops_wmi_ctrl_stats = { ++ .write = ath12k_write_wmi_ctrl_path_stats, ++ .open = simple_open, ++ .read = ath12k_read_wmi_ctrl_path_stats, ++}; ++ ++void ath12k_debugfs_wmi_ctrl_stats(struct ath12k *ar) ++{ ++ ++ ar->wmi_ctrl_stat = debugfs_create_file("wmi_ctrl_stats", 0644, ++ ar->debug.debugfs_pdev, ++ ar, ++ &ath12k_fops_wmi_ctrl_stats); ++ ++ INIT_LIST_HEAD(&ar->debug.wmi_list); ++ mutex_init(&ar->wmi_ctrl_path_stats_lock); ++ init_completion(&ar->debug.wmi_ctrl_path_stats_rcvd); ++} ++ + static int ath12k_debugfs_fw_stats_request(struct ath12k *ar, + struct stats_request_params *req_param) + { +@@ -2489,6 +2780,7 @@ int ath12k_debugfs_register(struct ath12k *ar) + + ath12k_debugfs_htt_stats_init(ar); + ++ ath12k_debugfs_wmi_ctrl_stats(ar); + ath12k_debugfs_fw_stats_init(ar); + ath12k_init_pktlog(ar); + +@@ -2538,6 +2830,10 @@ int ath12k_debugfs_register(struct ath12k *ar) + void ath12k_debugfs_unregister(struct ath12k *ar) + { + ath12k_deinit_pktlog(ar); ++ ++ /* Remove wmi ctrl stats file */ ++ debugfs_remove(ar->wmi_ctrl_stat); ++ ar->wmi_ctrl_stat = NULL; + } + + int ath12k_debugfs_create(void) +diff --git a/drivers/net/wireless/ath/ath12k/debugfs.h b/drivers/net/wireless/ath/ath12k/debugfs.h +index da4083a..bec2a4e 100644 +--- a/drivers/net/wireless/ath/ath12k/debugfs.h ++++ b/drivers/net/wireless/ath/ath12k/debugfs.h +@@ -199,6 +199,8 @@ enum ath12k_dbg_aggr_mode { + ATH12K_DBG_AGGR_MODE_MAX, + }; + ++void ath12k_wmi_crl_path_stats_list_free(struct ath12k *ar, struct list_head *head); ++ + #ifdef CPTCFG_ATH12K_DEBUGFS + int ath12k_debugfs_soc_create(struct ath12k_base *ab); + void ath12k_debugfs_soc_destroy(struct ath12k_base *ab); +diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c +index 68d9cc3..7290dfe 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -3567,6 +3567,93 @@ int ath12k_wmi_send_twt_add_dialog_cmd(struct ath12k *ar, + return ret; + } + ++int ++ath12k_wmi_send_wmi_ctrl_stats_cmd(struct ath12k *ar, ++ struct wmi_ctrl_path_stats_cmd_param *param) ++{ ++ struct ath12k_pdev_wmi *wmi = ar->wmi; ++ struct ath12k_base *ab = wmi->wmi_ab->ab; ++ u32 pdev_id_array[2] = {0}; ++ int len, ret; ++ struct wmi_tlv *tlv; ++ struct sk_buff *skb; ++ struct wmi_ctrl_path_stats_cmd_param *cmd; ++ void *ptr; ++ u32 stats_id = 0; ++ unsigned long time_left; ++ ++ switch (param->stats_id) { ++ case WMI_REQ_CTRL_PATH_PDEV_TX_STAT: ++ case WMI_REQ_CTRL_PATH_CAL_STAT: ++ case WMI_REQ_CTRL_PATH_BTCOEX_STAT: ++ pdev_id_array[0] = ar->pdev->pdev_id; ++ stats_id = (1 << param->stats_id); ++ break; ++ /* Add case for newly wmi ctrl path stats here */ ++ default: ++ ath12k_warn(ab, "Unsupported stats id %d", param->stats_id); ++ return -EIO; ++ break; ++ } ++ ++ len = sizeof(*cmd) + ++ TLV_HDR_SIZE + sizeof(u32) + ++ TLV_HDR_SIZE + TLV_HDR_SIZE; ++ ++ skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len); ++ if (!skb) ++ return -ENOMEM; ++ ++ cmd = (void *)skb->data; ++ cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, ++ WMI_CTRL_PATH_STATS_CMD_FIXED_PARAM) | ++ FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); ++ cmd->stats_id = stats_id; ++ cmd->req_id = param->req_id; ++ cmd->action = param->action; ++ ++ ptr = skb->data + sizeof(*cmd); ++ ++ tlv = ptr; ++ tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_UINT32) | ++ FIELD_PREP(WMI_TLV_LEN, sizeof(u32)); ++ ptr += TLV_HDR_SIZE; ++ memcpy(ptr, pdev_id_array, sizeof(pdev_id_array)); ++ ptr += sizeof(u32); ++ ++ tlv = ptr; ++ tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_UINT32) | ++ FIELD_PREP(WMI_TLV_LEN, 0); ++ ptr += TLV_HDR_SIZE; ++ ++ tlv = ptr; ++ tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_FIXED_STRUCT) | ++ FIELD_PREP(WMI_TLV_LEN, 0); ++ ptr += TLV_HDR_SIZE; ++ ++ if (param->action == WMI_REQUEST_CTRL_PATH_STAT_GET) ++ reinit_completion(&ar->debug.wmi_ctrl_path_stats_rcvd); ++ ++ ret = ath12k_wmi_cmd_send(wmi, skb, ++ WMI_REQUEST_CTRL_PATH_STATS_CMDID); ++ if (ret) { ++ dev_kfree_skb(skb); ++ ath12k_warn(ab, "Failed to send WMI_REQUEST_CTRL_PATH_STATS_CMDID: %d", ret); ++ } else { ++ if (param->action == WMI_REQUEST_CTRL_PATH_STAT_GET) { ++ time_left = wait_for_completion_timeout( ++ &ar->debug.wmi_ctrl_path_stats_rcvd, ++ WMI_CTRL_STATS_READY_TIMEOUT_HZ * HZ); ++ if (time_left == 0) { ++ ath12k_warn(ab, "timeout in receiving wmi ctrl path stats\n"); ++ return -ETIMEDOUT; ++ } ++ } ++ } ++ ++ return ret; ++} ++ + int ath12k_wmi_send_twt_del_dialog_cmd(struct ath12k *ar, + struct wmi_twt_del_dialog_params *params) + { +@@ -3604,6 +3691,258 @@ int ath12k_wmi_send_twt_del_dialog_cmd(struct ath12k *ar, + return ret; + } + ++void ath12k_wmi_crl_path_stats_list_free(struct ath12k *ar, struct list_head *head) ++{ ++ struct wmi_ctrl_path_stats_list *stats, *tmp; ++ ++ lockdep_assert_held(&ar->wmi_ctrl_path_stats_lock); ++ list_for_each_entry_safe(stats, tmp, head, list) { ++ kfree(stats->stats_ptr); ++ list_del(&stats->list); ++ kfree(stats); ++ } ++} ++ ++int wmi_print_ctrl_path_pdev_tx_stats_tlv(struct ath12k_base *ab, u16 len, const void *ptr, void *data) ++{ ++ struct wmi_ctrl_path_stats_ev_parse_param *stats_buff = (struct wmi_ctrl_path_stats_ev_parse_param *)data; ++ struct wmi_ctrl_path_pdev_stats *pdev_stats_skb = (struct wmi_ctrl_path_pdev_stats *)ptr; ++ struct wmi_ctrl_path_pdev_stats *pdev_stats = NULL; ++ struct wmi_ctrl_path_stats_list *stats = kzalloc(sizeof(struct wmi_ctrl_path_stats_list), GFP_ATOMIC); ++ struct ath12k *ar = NULL; ++ ++ if (!stats) ++ return -ENOMEM; ++ ++ pdev_stats = kzalloc(sizeof(*pdev_stats), GFP_ATOMIC); ++ if (!pdev_stats) { ++ kfree(stats); ++ return -ENOMEM; ++ } ++ ++ memcpy(pdev_stats, pdev_stats_skb, sizeof(struct wmi_ctrl_path_pdev_stats)); ++ stats->stats_ptr = pdev_stats; ++ list_add_tail(&stats->list, &stats_buff->list); ++ ++ ar = ath12k_mac_get_ar_by_pdev_id(ab, pdev_stats_skb->pdev_id + 1); ++ if (!ar) { ++ ath12k_warn(ab, "Failed to get ar for wmi ctrl stats\n"); ++ kfree(pdev_stats); ++ kfree(stats); ++ return -EINVAL; ++ } ++ ++ mutex_lock(&ar->wmi_ctrl_path_stats_lock); ++ ath12k_wmi_crl_path_stats_list_free(ar, &ar->debug.wmi_list); ++ mutex_unlock(&ar->wmi_ctrl_path_stats_lock); ++ ar->debug.wmi_ctrl_path_stats_tagid = WMI_CTRL_PATH_PDEV_STATS; ++ stats_buff->ar = ar; ++ return 0; ++} ++ ++int wmi_print_ctrl_path_cal_stats_tlv(struct ath12k_base *ab, u16 len, ++ const void *ptr, void *data) ++{ ++ struct wmi_ctrl_path_stats_ev_parse_param *stats_buff = (struct wmi_ctrl_path_stats_ev_parse_param *)data; ++ struct wmi_ctrl_path_cal_stats *cal_stats_skb = (struct wmi_ctrl_path_cal_stats *)ptr; ++ struct wmi_ctrl_path_cal_stats *cal_stats = NULL; ++ struct wmi_ctrl_path_stats_list *stats = kzalloc(sizeof(struct wmi_ctrl_path_stats_list), GFP_ATOMIC); ++ struct ath12k *ar = NULL; ++ ++ if (!stats) ++ return -ENOMEM; ++ ++ cal_stats = kzalloc(sizeof(*cal_stats), GFP_ATOMIC); ++ if (!cal_stats) { ++ kfree(stats); ++ return -ENOMEM; ++ } ++ ++ memcpy(cal_stats, cal_stats_skb, sizeof(struct wmi_ctrl_path_cal_stats)); ++ stats->stats_ptr = cal_stats; ++ list_add_tail(&stats->list, &stats_buff->list); ++ ++ ar = ath12k_mac_get_ar_by_pdev_id(ab, cal_stats_skb->pdev_id + 1); ++ if (!ar) { ++ ath12k_warn(ab, "Failed to get ar for wmi ctrl cal stats\n"); ++ kfree(cal_stats); ++ kfree(stats); ++ return -EINVAL; ++ } ++ ++ mutex_lock(&ar->wmi_ctrl_path_stats_lock); ++ ath12k_wmi_crl_path_stats_list_free(ar, &ar->debug.wmi_list); ++ mutex_unlock(&ar->wmi_ctrl_path_stats_lock); ++ ar->debug.wmi_ctrl_path_stats_tagid = WMI_CTRL_PATH_CAL_STATS; ++ stats_buff->ar = ar; ++ return 0; ++} ++ ++int wmi_print_ctrl_path_btcoex_stats_tlv(struct ath12k_base *ab, u16 len, ++ const void *ptr, void *data) ++{ ++ struct wmi_ctrl_path_stats_ev_parse_param *stats_buff = ++ (struct wmi_ctrl_path_stats_ev_parse_param *)data; ++ struct wmi_ctrl_path_btcoex_stats *btcoex_stats_skb = ++ (struct wmi_ctrl_path_btcoex_stats *)ptr; ++ struct wmi_ctrl_path_btcoex_stats *btcoex_stats = NULL; ++ struct wmi_ctrl_path_stats_list *stats; ++ struct ath12k *ar = NULL; ++ ++ stats = kzalloc(sizeof(*stats), GFP_ATOMIC); ++ if (!stats) ++ return -ENOMEM; ++ ++ btcoex_stats = kzalloc(sizeof(*btcoex_stats), GFP_ATOMIC); ++ if (!btcoex_stats) { ++ kfree(stats); ++ return -ENOMEM; ++ } ++ ++ memcpy(btcoex_stats, btcoex_stats_skb, sizeof(*btcoex_stats)); ++ stats->stats_ptr = btcoex_stats; ++ list_add_tail(&stats->list, &stats_buff->list); ++ ++ ar = ath12k_mac_get_ar_by_pdev_id(ab, btcoex_stats_skb->pdev_id + 1); ++ if (!ar) { ++ ath12k_warn(ab, "Failed to get ar for wmi ctrl cal stats\n"); ++ kfree(btcoex_stats); ++ kfree(stats); ++ return -EINVAL; ++ } ++ ++ mutex_lock(&ar->wmi_ctrl_path_stats_lock); ++ ath12k_wmi_crl_path_stats_list_free(ar, &ar->debug.wmi_list); ++ mutex_unlock(&ar->wmi_ctrl_path_stats_lock); ++ ar->debug.wmi_ctrl_path_stats_tagid = WMI_CTRL_PATH_BTCOEX_STATS; ++ stats_buff->ar = ar; ++ return 0; ++} ++ ++static int ath12k_wmi_ctrl_stats_subtlv_parser(struct ath12k_base *ab, ++ u16 tag, u16 len, ++ const void *ptr, void *data) ++{ ++ int ret = 0; ++ ++ switch (tag) { ++ case WMI_CTRL_PATH_STATS_EV_FIXED_PARAM: ++ break; ++ case WMI_CTRL_PATH_PDEV_STATS: ++ ret = wmi_print_ctrl_path_pdev_tx_stats_tlv(ab, len, ptr, data); ++ break; ++ case WMI_CTRL_PATH_CAL_STATS: ++ ret = wmi_print_ctrl_path_cal_stats_tlv(ab, len, ptr, data); ++ break; ++ case WMI_CTRL_PATH_BTCOEX_STATS: ++ ret = wmi_print_ctrl_path_btcoex_stats_tlv(ab, len, ptr, data); ++ break; ++ /* Add case for newly wmi ctrl path added stats here */ ++ default: ++ ath12k_warn(ab, ++ "Received invalid tag for wmi ctrl path stats in subtlvs, tag : 0x%x\n", ++ tag); ++ return -EINVAL; ++ break; ++ } ++ ++ return ret; ++} ++ ++static int ath12k_wmi_ctrl_stats_event_parser(struct ath12k_base *ab, ++ u16 tag, u16 len, ++ const void *ptr, void *data) ++{ ++ int ret = 0; ++ ++ ath12k_dbg(ab, ATH12K_DBG_WMI, "wmi ctrl path stats tag 0x%x of len %d rcvd\n", ++ tag, len); ++ ++ switch (tag) { ++ case WMI_CTRL_PATH_STATS_EV_FIXED_PARAM: ++ /* Fixed param is already processed*/ ++ break; ++ case WMI_TAG_ARRAY_STRUCT: ++ /* len 0 is expected for array of struct when there ++ * is no content of that type to pack inside that tlv ++ */ ++ if (len == 0) ++ return 0; ++ ++ ret = ath12k_wmi_tlv_iter(ab, ptr, len, ++ ath12k_wmi_ctrl_stats_subtlv_parser, ++ data); ++ break; ++ default: ++ ath12k_warn(ab, "Received invalid tag for wmi ctrl path stats\n"); ++ ret = -EINVAL; ++ break; ++ } ++ ++ return ret; ++} ++ ++static void ath12k_wmi_ctrl_path_stats_event(struct ath12k_base *ab, struct sk_buff *skb) ++{ ++ int ret; ++ const struct wmi_tlv *tlv; ++ struct wmi_ctrl_path_stats_ev_param *fixed_param; ++ u16 tlv_tag; ++ u8 *ptr = skb->data; ++ struct ath12k *ar = NULL; ++ struct wmi_ctrl_path_stats_ev_parse_param param; ++ INIT_LIST_HEAD(¶m.list); ++ ++ if (!skb->data) { ++ ath12k_warn(ab, "No data present in wmi ctrl stats event\n"); ++ return; ++ } ++ ++ if (skb->len < (sizeof(*fixed_param) + TLV_HDR_SIZE)) { ++ ath12k_warn(ab, "wmi ctrl stats event size invalid\n"); ++ return; ++ } ++ ++ param.ar = NULL; ++ ++ tlv = (struct wmi_tlv *)ptr; ++ tlv_tag = FIELD_GET(WMI_TLV_TAG, tlv->header); ++ ptr += sizeof(*tlv); ++ ++ if (tlv_tag == WMI_CTRL_PATH_STATS_EV_FIXED_PARAM) ++ fixed_param = (struct wmi_ctrl_path_stats_ev_param *)ptr; ++ else ++ ath12k_warn(ab, "wmi ctrl Stats received without fixed param tlv at start\n"); ++ ++ if (!fixed_param) { ++ ath12k_warn(ab, "wmi ctrl Stats received fixed param is NULL\n"); ++ goto free; ++ } ++ ++ ret = ath12k_wmi_tlv_iter(ab, skb->data, skb->len, ++ ath12k_wmi_ctrl_stats_event_parser, ++ ¶m); ++ if (ret) { ++ ath12k_warn(ab, "failed to parse wmi_ctrl_path_stats tlv: %d\n", ret); ++ goto free; ++ } ++ ++ ar = param.ar; ++ if (!ar) ++ return; ++ ++ mutex_lock(&ar->wmi_ctrl_path_stats_lock); ++ list_splice_tail_init(¶m.list, &ar->debug.wmi_list); ++ mutex_unlock(&ar->wmi_ctrl_path_stats_lock); ++ ++ if (!fixed_param->more) { ++ complete(&ar->debug.wmi_ctrl_path_stats_rcvd); ++ ath12k_dbg(ab, ATH12K_DBG_WMI, "wmi ctrl path stats completed"); ++ } ++free: ++ ath12k_wmi_crl_path_stats_list_free(ar, ¶m.list); ++} ++ + int ath12k_wmi_send_twt_pause_dialog_cmd(struct ath12k *ar, + struct wmi_twt_pause_dialog_params *params) + { +@@ -10058,6 +10397,9 @@ static void ath12k_wmi_tlv_op_rx(struct ath12k_base *ab, struct sk_buff *skb) + case WMI_DCS_INTERFERENCE_EVENTID: + ath12k_wmi_dcs_awgn_interference_event(ab, skb); + break; ++ case WMI_CTRL_PATH_STATS_EVENTID: ++ ath12k_wmi_ctrl_path_stats_event(ab, skb); ++ break; + case WMI_PDEV_PKTLOG_DECODE_INFO_EVENTID: + ath12k_wmi_pktlog_decode_info(ab, skb); + break; +diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h +index 468c137..0f6f9ad 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -1928,10 +1928,17 @@ enum wmi_tlv_tag { + WMI_TAG_PDEV_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD, + WMI_TAG_PDEV_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMD, + WMI_TAG_PDEV_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD, ++ /* TODO add all the missing cmds */ ++ WMI_CTRL_PATH_STATS_CMD_FIXED_PARAM = ++ WMI_TAG_PDEV_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD + 4, ++ WMI_CTRL_PATH_STATS_EV_FIXED_PARAM, ++ WMI_CTRL_PATH_PDEV_STATS, + WMI_TAG_REGULATORY_RULE_EXT_STRUCT = 0x3A9, + WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT, + WMI_TAG_VDEV_SET_TPC_POWER_CMD = 0x3B5, + WMI_TAG_VDEV_CH_POWER_INFO, ++ WMI_CTRL_PATH_CAL_STATS = 0x3BC, ++ WMI_CTRL_PATH_BTCOEX_STATS = 0x3FD, + WMI_TAG_EHT_RATE_SET = 0x3C4, + WMI_TAG_DCS_AWGN_INT_TYPE = 0x3C5, + WMI_TAG_MLO_TX_SEND_PARAMS, +@@ -5681,6 +5688,254 @@ struct wmi_twt_resume_dialog_params_cmd { + u32 next_twt_size; + } __packed; + ++/** ++ * WMI arrays of length WMI_MGMT_FRAME_SUBTYPE_MAX use the ++ * IEEE802.11 standard's enumeration of mgmt frame subtypes: ++ * 0 -> IEEE80211_STYPE_FC0_SUBTYPE_ASSOC_REQ ++ * 1 -> IEEE80211_STYPE_FC0_SUBTYPE_ASSOC_RESP ++ * 2 -> IEEE80211_STYPE_FC0_SUBTYPE_REASSOC_REQ ++ * 3 -> IEEE80211_STYPE_FC0_SUBTYPE_REASSOC_RESP ++ * 4 -> IEEE80211_STYPE_FC0_SUBTYPE_PROBE_REQ ++ * 5 -> IEEE80211_STYPE_FC0_SUBTYPE_PROBE_RESP ++ * 6 -> Reserved ++ * 7 -> Reserved ++ * 8 -> IEEE80211_STYPE_FC0_SUBTYPE_BEACON ++ * 9 -> IEEE80211_STYPE_FC0_SUBTYPE_ATIM ++ * 10 -> IEEE80211_STYPE_FC0_SUBTYPE_DISASSOC ++ * 11 -> IEEE80211_STYPE_FC0_SUBTYPE_AUTH ++ * 12 -> IEEE80211_STYPE_FC0_SUBTYPE_DEAUTH ++ * 13 -> IEEE80211_STYPE_FCO_SUBTYPE_ACTION ++ * 14 -> IEEE80211_STYPE_FC0_SUBTYPE_ACTION_NOACK ++ * 15 -> IEEE80211_STYPE_FC0_SUBTYPE_RESERVED ++ */ ++#define WMI_MGMT_FRAME_SUBTYPE_MAX 16 ++#define WMI_MAX_STRING_LEN 256 ++ ++enum wmi_ctrl_path_cal_prof_id { ++ WMI_CTRL_PATH_STATS_CAL_PROF_COLD_BOOT_CAL = 0, ++ WMI_CTRL_PATH_STATS_CAL_PROF_FULL_CHAN_SWITCH, ++ WMI_CTRL_PATH_STATS_CAL_PROF_SCAN_CHAN_SWITCH, ++ WMI_CTRL_PATH_STATS_CAL_PROF_DPD_SPLIT_CAL, ++ WMI_CTRL_PATH_STATS_CAL_PROF_TEMP_TRIGEER_CAL, ++ WMI_CTRL_PATH_STATS_CAL_PROF_POWER_SAVE_WAKE_UP, ++ WMI_CTRL_PATH_STATS_CAL_PROF_TIMER_TRIGGER_CAL, ++ WMI_CTRL_PATH_STATS_CAL_PROF_FTM_TRIGGER_CAL, ++ WMI_CTRL_PATH_STATS_CAL_PROF_AGILE_OR_POWER_DOWN_DTIM, ++ WMI_CTRL_PATH_STATS_CAL_PROF_NOISY_ENV_RXDO, ++ /* IDs from 10 to 30 for future use*/ ++ WMI_CTRL_PATH_STATS_CAL_PROFILE_INVALID = 0x1F, ++}; ++ ++static inline const char * ++wmi_ctrl_path_cal_prof_id_to_name(u8 prof_id) { ++ switch (prof_id) { ++ case WMI_CTRL_PATH_STATS_CAL_PROF_COLD_BOOT_CAL: ++ return "COLD_BOOT_CAL"; ++ case WMI_CTRL_PATH_STATS_CAL_PROF_FULL_CHAN_SWITCH: ++ return "FULL_CHAN_SWITCH"; ++ case WMI_CTRL_PATH_STATS_CAL_PROF_SCAN_CHAN_SWITCH: ++ return "SCAN_CHAN_SWITCH"; ++ case WMI_CTRL_PATH_STATS_CAL_PROF_DPD_SPLIT_CAL: ++ return "DPD_SPLIT_CAL"; ++ case WMI_CTRL_PATH_STATS_CAL_PROF_TEMP_TRIGEER_CAL: ++ return "TEMP_TRIGEER_CAL"; ++ case WMI_CTRL_PATH_STATS_CAL_PROF_POWER_SAVE_WAKE_UP: ++ return "POWER_SAVE_WAKE_UP"; ++ case WMI_CTRL_PATH_STATS_CAL_PROF_TIMER_TRIGGER_CAL: ++ return "TIMER_TRIGGER_CAL"; ++ case WMI_CTRL_PATH_STATS_CAL_PROF_FTM_TRIGGER_CAL: ++ return "FTM_TRIGGER_CAL"; ++ case WMI_CTRL_PATH_STATS_CAL_PROF_AGILE_OR_POWER_DOWN_DTIM: ++ return "AGILE_OR_POWER_DOWN_DTIM"; ++ case WMI_CTRL_PATH_STATS_CAL_PROF_NOISY_ENV_RXDO: ++ return "NOISY_ENV_RXDO"; ++ case WMI_CTRL_PATH_STATS_CAL_PROFILE_INVALID: ++ break; ++ } ++ return "UNKOWN_CAL_PROFILE"; ++} ++ ++enum wmi_ctrl_path_cal_type_id { ++ WMI_CTRL_PATH_STATS_CAL_TYPE_ADC = 0, ++ WMI_CTRL_PATH_STATS_CAL_TYPE_DAC, ++ WMI_CTRL_PATH_STATS_CAL_TYPE_PROCESS, ++ WMI_CTRL_PATH_STATS_CAL_TYPE_NOISE_FLOOR, ++ WMI_CTRL_PATH_STATS_CAL_TYPE_RXDCO, ++ WMI_CTRL_PATH_STATS_CAL_TYPE_COMB_TXLO_TXIQ_RXIQ, ++ WMI_CTRL_PATH_STATS_CAL_TYPE_TXLO, ++ WMI_CTRL_PATH_STATS_CAL_TYPE_TXIQ, ++ WMI_CTRL_PATH_STATS_CAL_TYPE_RXIQ, ++ WMI_CTRL_PATH_STATS_CAL_TYPE_IM2, ++ WMI_CTRL_PATH_STATS_CAL_TYPE_LNA, ++ WMI_CTRL_PATH_STATS_CAL_TYPE_DPD_LP_RXDCO, ++ WMI_CTRL_PATH_STATS_CAL_TYPE_DPD_LP_RXIQ, ++ WMI_CTRL_PATH_STATS_CAL_TYPE_DPD_MEMORYLESS, ++ WMI_CTRL_PATH_STATS_CAL_TYPE_DPD_MEMORY, ++ WMI_CTRL_PATH_STATS_CAL_TYPE_IBF, ++ WMI_CTRL_PATH_STATS_CAL_TYPE_PDET_AND_PAL, ++ WMI_CTRL_PATH_STATS_CAL_TYPE_RXDCO_IQ, ++ WMI_CTRL_PATH_STATS_CAL_TYPE_RXDCO_DTIM, ++ WMI_CTRL_PATH_STATS_CAL_TYPE_TPC_CAL, ++ WMI_CTRL_PATH_STATS_CAL_TYPE_DPD_TIMEREQ, ++ WMI_CTRL_PATH_STATS_CAL_TYPE_BWFILTER, ++ WMI_CTRL_PATH_STATS_CAL_TYPE_PEF, ++ WMI_CTRL_PATH_STATS_CAL_TYPE_PADROOP, ++ WMI_CTRL_PATH_STATS_CAL_TYPE_SELFCALTPC, ++ /* IDs 25 to 254 for future use*/ ++ WMI_CTRL_PATH_STATS_CAL_TYPE_INVALID = 0xff, ++}; ++ ++static inline const char * ++wmi_ctrl_path_cal_type_id_to_name(u8 type_id) { ++ switch (type_id) { ++ case WMI_CTRL_PATH_STATS_CAL_TYPE_ADC: ++ return "ADC"; ++ case WMI_CTRL_PATH_STATS_CAL_TYPE_DAC: ++ return "DAC"; ++ case WMI_CTRL_PATH_STATS_CAL_TYPE_PROCESS: ++ return "PROCESS"; ++ case WMI_CTRL_PATH_STATS_CAL_TYPE_NOISE_FLOOR: ++ return "NOISE_FLOOR"; ++ case WMI_CTRL_PATH_STATS_CAL_TYPE_RXDCO: ++ return "RXDCO"; ++ case WMI_CTRL_PATH_STATS_CAL_TYPE_COMB_TXLO_TXIQ_RXIQ: ++ return "COMB_TXLO_TXIQ_RXIQ"; ++ case WMI_CTRL_PATH_STATS_CAL_TYPE_TXLO: ++ return "TXLO"; ++ case WMI_CTRL_PATH_STATS_CAL_TYPE_TXIQ: ++ return "TXIQ"; ++ case WMI_CTRL_PATH_STATS_CAL_TYPE_RXIQ: ++ return "RXIQ"; ++ case WMI_CTRL_PATH_STATS_CAL_TYPE_IM2: ++ return "IM2"; ++ case WMI_CTRL_PATH_STATS_CAL_TYPE_LNA: ++ return "LNA"; ++ case WMI_CTRL_PATH_STATS_CAL_TYPE_DPD_LP_RXDCO: ++ return "DPD_LP_RXDCO"; ++ case WMI_CTRL_PATH_STATS_CAL_TYPE_DPD_LP_RXIQ: ++ return "DPD_LP_RXIQ"; ++ case WMI_CTRL_PATH_STATS_CAL_TYPE_DPD_MEMORYLESS: ++ return "DPD_MEMORYLESS"; ++ case WMI_CTRL_PATH_STATS_CAL_TYPE_DPD_MEMORY: ++ return "DPD_MEMORY"; ++ case WMI_CTRL_PATH_STATS_CAL_TYPE_IBF: ++ return "IBF"; ++ case WMI_CTRL_PATH_STATS_CAL_TYPE_PDET_AND_PAL: ++ return "PDET_AND_PAL"; ++ case WMI_CTRL_PATH_STATS_CAL_TYPE_RXDCO_IQ: ++ return "RXDCO_IQ"; ++ case WMI_CTRL_PATH_STATS_CAL_TYPE_RXDCO_DTIM: ++ return "RXDCO_DTIM"; ++ case WMI_CTRL_PATH_STATS_CAL_TYPE_TPC_CAL: ++ return "TPC_CAL"; ++ case WMI_CTRL_PATH_STATS_CAL_TYPE_DPD_TIMEREQ: ++ return "DPD_TIMEREQ"; ++ case WMI_CTRL_PATH_STATS_CAL_TYPE_BWFILTER: ++ return "BWFILTER"; ++ case WMI_CTRL_PATH_STATS_CAL_TYPE_PEF: ++ return "PEF"; ++ case WMI_CTRL_PATH_STATS_CAL_TYPE_PADROOP: ++ return "PADROOP"; ++ case WMI_CTRL_PATH_STATS_CAL_TYPE_SELFCALTPC: ++ return "SELFCALTPC"; ++ case WMI_CTRL_PATH_STATS_CAL_TYPE_INVALID: ++ break; ++ } ++ return "UNKNOWN_CAL_TYPE"; ++} ++ ++enum wmi_ctrl_path_periodic_cal_type_id { ++ WMI_CTRL_PATH_STATS_PERIODIC_CAL_TYPE_NOISE_FLOOR, ++ WMI_CTRL_PATH_STATS_PERIODIC_CAL_TYPE_DPD_MEMORYLESS, ++ WMI_CTRL_PATH_STATS_PERIODIC_CAL_TYPE_DPD_MEMORY, ++ /* IDs 3 to 254 for future use*/ ++ WMI_CTRL_PATH_STATS_PERIODIC_CAL_TYPE_INVALID = 0xFF, ++}; ++ ++static inline const char * ++wmi_ctrl_path_periodic_cal_type_id_to_name(u8 type_id) { ++ switch (type_id) { ++ case WMI_CTRL_PATH_STATS_PERIODIC_CAL_TYPE_NOISE_FLOOR: ++ return "NOISE_FLOOR"; ++ case WMI_CTRL_PATH_STATS_PERIODIC_CAL_TYPE_DPD_MEMORYLESS: ++ return "DPD_MEMORYLESS"; ++ case WMI_CTRL_PATH_STATS_PERIODIC_CAL_TYPE_DPD_MEMORY: ++ return "DPD_MEMORY"; ++ case WMI_CTRL_PATH_STATS_PERIODIC_CAL_TYPE_INVALID: ++ break; ++ } ++ return "UNKNOWN_PERIODIC_CAL_TYPE"; ++} ++ ++#define WMI_CTRL_PATH_CAL_PROF_MASK GENMASK(12, 8) ++#define WMI_CTRL_PATH_CAL_TYPE_MASK GENMASK(7, 0) ++#define WMI_CTRL_PATH_IS_PERIODIC_CAL GENMASK(13, 13) ++ ++struct wmi_ctrl_path_pdev_stats { ++ u32 pdev_id; ++ u32 tx_mgmt_subtype[WMI_MGMT_FRAME_SUBTYPE_MAX]; ++ u32 rx_mgmt_subtype[WMI_MGMT_FRAME_SUBTYPE_MAX]; ++ u32 scan_fail_dfs_violation_time_ms; ++ u32 nol_chk_fail_last_chan_freq; ++ u32 nol_chk_fail_time_stamp_ms; ++ u32 tot_peer_create_cnt; ++ u32 tot_peer_del_cnt; ++ u32 tot_peer_del_resp_cnt; ++ u32 vdev_pause_fail_rt_to_sched_algo_fifo_full_cnt; ++} __packed; ++ ++struct wmi_ctrl_path_cal_stats { ++ u32 pdev_id; ++ u32 cal_info; ++ u32 cal_triggered_cnt; ++ u32 cal_fail_cnt; ++ u32 cal_fcs_cnt; ++ u32 cal_fcs_fail_cnt; ++} __packed; ++ ++struct wmi_ctrl_path_stats_cmd_param { ++ u32 tlv_header; ++ u32 stats_id; ++ u32 req_id; ++ /* get/reset/start/stop based on stats id is defined as ++ * a part of wmi_ctrl_path_stats_action ++ */ ++ u32 action; ++} __packed; ++ ++struct wmi_ctrl_path_stats_ev_param { ++ u32 req_id; ++ /* more flag ++ * 1 - More events sent after this event. ++ * 0 - no more events after this event. ++ */ ++ u32 more; ++} __packed; ++ ++struct wmi_ctrl_path_stats_list { ++ struct list_head list; ++ void *stats_ptr; ++} __packed; ++ ++struct wmi_ctrl_path_btcoex_stats { ++ u32 pdev_id; ++ u32 bt_tx_req_cntr; ++ u32 bt_rx_req_cntr; ++ u32 bt_req_nack_cntr; ++ u32 wl_tx_req_nack_schd_bt_reason_cntr; ++ u32 wl_tx_req_nack_current_bt_reason_cntr; ++ u32 wl_tx_req_nack_other_wlan_tx_reason_cntr; ++ u32 wl_in_tx_abort_cntr; ++ u32 wl_tx_auto_resp_req_cntr; ++ u32 wl_tx_req_ack_cntr; ++ u32 wl_tx_req_cntr; ++} __packed; ++ ++struct wmi_ctrl_path_stats_ev_parse_param { ++ struct list_head list; ++ struct ath12k *ar; ++} __packed; ++ + struct wmi_obss_spatial_reuse_params_cmd { + __le32 tlv_header; + __le32 pdev_id; +@@ -6197,6 +6452,7 @@ struct wmi_dbglog_config_cmd_fixed_param { + #define WMI_MLO_CMD_TIMEOUT_HZ (5 * HZ) + #define WMI_SERVICE_READY_TIMEOUT_HZ (5 * HZ) + #define WMI_SEND_TIMEOUT_HZ (3 * HZ) ++#define WMI_CTRL_STATS_READY_TIMEOUT_HZ (1 * HZ) + + struct ath12k_wmi_base { + struct ath12k_base *ab; +@@ -6711,6 +6967,8 @@ int ath12k_wmi_send_vdev_set_tpc_power(struct ath12k *ar, + int ath12k_wmi_pdev_m3_dump_enable(struct ath12k *ar, u32 enable); + int ath12k_wmi_pdev_get_tpc_table_cmdid(struct ath12k *ar); + void ath12k_wmi_free_tpc_stats_mem(struct ath12k *ar); ++int ath12k_wmi_send_wmi_ctrl_stats_cmd(struct ath12k *ar, ++ struct wmi_ctrl_path_stats_cmd_param *param); + int ath12k_wmi_mlo_setup(struct ath12k *ar, + struct wmi_mlo_setup_params *mlo_params); + int ath12k_wmi_mlo_ready(struct ath12k *ar); +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/672-ath12k-add-awgn-support-for-320MHz-in-6GHz-band.patch b/feeds/ipq95xx/mac80211/patches/qca/707-ath12k-add-awgn-support-for-320-MHz-in-6-GHz-band.patch similarity index 82% rename from feeds/ipq95xx/mac80211/patches/qca/672-ath12k-add-awgn-support-for-320MHz-in-6GHz-band.patch rename to feeds/ipq95xx/mac80211/patches/qca/707-ath12k-add-awgn-support-for-320-MHz-in-6-GHz-band.patch index 978c6aa39..65abef990 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/672-ath12k-add-awgn-support-for-320MHz-in-6GHz-band.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/707-ath12k-add-awgn-support-for-320-MHz-in-6-GHz-band.patch @@ -1,21 +1,21 @@ -From 55f787abfc35a52399d4fbb62f8ab2dca870623f Mon Sep 17 00:00:00 2001 +From 8baaf8d3f05f1c2bac31db7b820ed927cd306637 Mon Sep 17 00:00:00 2001 From: Hari Chandrakanthan -Date: Fri, 30 Sep 2022 19:40:26 +0530 -Subject: [PATCH] ath12k : add awgn support for 320MHz in 6GHz band +Date: Sun, 15 Jan 2023 21:39:59 +0530 +Subject: [PATCH] ath12k : add awgn support for 320 MHz in 6 GHz band -Add support for awgn handling of 320MHz bw in 6GHz band. +Add support for awgn handling of 320 MHz bw in 6 GHz band. Signed-off-by: Hari Chandrakanthan --- drivers/net/wireless/ath/ath12k/wmi.c | 9 +++++++ - drivers/net/wireless/ath/ath12k/wmi.h | 44 +++++++++++++++++++++++------------ - 2 files changed, 38 insertions(+), 15 deletions(-) + drivers/net/wireless/ath/ath12k/wmi.h | 45 ++++++++++++++++++++++------------- + 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c -index 7151338..b475340 100644 +index 42c27eb..fe3a0f4 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c -@@ -7961,6 +7961,14 @@ bool ath12k_wmi_validate_dcs_awgn_info(struct ath12k *ar, struct wmi_dcs_awgn_in +@@ -8612,6 +8612,14 @@ bool ath12k_wmi_validate_dcs_awgn_info(struct ath12k *ar, struct wmi_dcs_awgn_in return false; } break; @@ -30,7 +30,7 @@ index 7151338..b475340 100644 default: ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "dcs interference event received with unknown channel width %d", -@@ -7969,6 +7977,7 @@ bool ath12k_wmi_validate_dcs_awgn_info(struct ath12k *ar, struct wmi_dcs_awgn_in +@@ -8620,6 +8628,7 @@ bool ath12k_wmi_validate_dcs_awgn_info(struct ath12k *ar, struct wmi_dcs_awgn_in } return true; } @@ -39,10 +39,10 @@ index 7151338..b475340 100644 ath12k_wmi_dcs_awgn_interference_event(struct ath12k_base *ab, struct sk_buff *skb) diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h -index 3f54605..ad2ec8a 100644 +index f134e37..05ffd96 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h -@@ -4955,24 +4955,38 @@ struct wmi_dcs_interference_ev { +@@ -5066,27 +5066,40 @@ struct wmi_dcs_interference_ev { } __packed; enum wmi_host_channel_width { @@ -51,6 +51,7 @@ index 3f54605..ad2ec8a 100644 - WMI_HOST_CHAN_WIDTH_80 = 2, - WMI_HOST_CHAN_WIDTH_160 = 3, - WMI_HOST_CHAN_WIDTH_80P80 = 4, +- WMI_HOST_CHAN_WIDTH_320 = 7, + WMI_HOST_CHAN_WIDTH_20 = 0, + WMI_HOST_CHAN_WIDTH_40 = 1, + WMI_HOST_CHAN_WIDTH_80 = 2, @@ -60,7 +61,9 @@ index 3f54605..ad2ec8a 100644 + WMI_HOST_CHAN_WIDTH_10 = 6, + WMI_HOST_CHAN_WIDTH_165 = 7, + WMI_HOST_CHAN_WIDTH_160P160 = 8, -+ WMI_HOST_CHAN_WIDTH_320 = 9 ++ WMI_HOST_CHAN_WIDTH_320 = 9, + /*keep last */ + WMI_HOST_CHAN_WIDTH_MAX = 0xF, }; enum wmi_dcs_interference_chan_segment { diff --git a/feeds/ipq95xx/mac80211/patches/qca/707-ath12k-tx-and-rx-nss-changes-for-eht-mode.patch b/feeds/ipq95xx/mac80211/patches/qca/707-ath12k-tx-and-rx-nss-changes-for-eht-mode.patch new file mode 100644 index 000000000..fb7275920 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/707-ath12k-tx-and-rx-nss-changes-for-eht-mode.patch @@ -0,0 +1,88 @@ +From 69d5f20e4c472d431916fc8ef016ba641c73c9f2 Mon Sep 17 00:00:00 2001 +From: Vishal Kumar +Date: Fri, 13 Jan 2023 02:19:51 +0530 +Subject: [PATCH] ath12k: tx and rx nss changes for eht mode + +calculation of eht nss using intersection of link_sta and phy capability. +For example: + sta_nss = 4x4 and ap_nss = 2x2 then final nss will be 2x2. + +Signed-off-by: Vishal Kumar +--- + drivers/net/wireless/ath/ath12k/mac.c | 31 ++++++++++++++++++++++----- + 1 file changed, 26 insertions(+), 5 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -483,6 +483,18 @@ ath12k_mac_max_eht_nss(const u16 eht_mcs + return 1; + } + ++static u32 ++ath12k_mac_max_eht_mcs_nss(const u8 *eht_mcs, int eht_mcs_set_size) ++{ ++ int i; ++ u8 nss = 0; ++ ++ for (i = 0; i < eht_mcs_set_size; i++) ++ nss = max(nss, u8_get_bits(eht_mcs[i], IEEE80211_EHT_MCS_NSS_RX)); ++ ++ return nss; ++} ++ + static u8 ath12k_parse_mpdudensity(u8 mpdudensity) + { + /* 802.11n D2.0 defined values for "Minimum MPDU Start Spacing": +@@ -2810,6 +2822,8 @@ static void ath12k_peer_assoc_h_eht(stru + struct ieee80211_bss_conf* link_conf; + struct ieee80211_link_sta *link_sta; + u32 peer_eht_ops; ++ struct ieee80211_sta_eht_cap *own_eht_cap; ++ struct ieee80211_eht_mcs_nss_supp *own_eht_mcs_nss_supp; + + link_conf = ath12k_get_link_bss_conf(arvif); + +@@ -2840,6 +2854,9 @@ static void ath12k_peer_assoc_h_eht(stru + band = def.chan->band; + eht_mcs_mask = arvif->bitrate_mask.control[band].eht_mcs; + ++ own_eht_cap = &ar->mac.sbands[band].iftype_data->eht_cap; ++ own_eht_mcs_nss_supp = &own_eht_cap->eht_mcs_nss_supp; ++ + if (ath12k_peer_assoc_h_eht_masked(eht_mcs_mask)) + return; + +@@ -2864,7 +2881,8 @@ static void ath12k_peer_assoc_h_eht(stru + sizeof(eht_cap->eht_cap_elem.phy_cap_info)); + arg->peer_eht_ops = peer_eht_ops;; + +- eht_nss = ath12k_mac_max_eht_nss(eht_mcs_mask); ++ eht_nss = ath12k_mac_max_eht_mcs_nss((void *)own_eht_mcs_nss_supp, ++ sizeof(*own_eht_mcs_nss_supp)); + + if (eht_nss > link_sta->rx_nss) { + user_rate_valid = false; +@@ -2935,14 +2953,17 @@ static void ath12k_peer_assoc_h_eht(stru + max_nss = mcs_nss->only_20mhz.rx_tx_mcs7_max_nss; + } else { + if (mcs_nss_supp_bw->rx_tx_mcs13_max_nss) +- max_nss = mcs_nss_supp_bw->rx_tx_mcs13_max_nss; +- else if (mcs_nss_supp_bw->rx_tx_mcs11_max_nss) +- max_nss = mcs_nss_supp_bw->rx_tx_mcs11_max_nss; +- else +- max_nss = mcs_nss_supp_bw->rx_tx_mcs9_max_nss; ++ max_nss = u8_get_bits(mcs_nss_supp_bw->rx_tx_mcs13_max_nss, ++ IEEE80211_EHT_MCS_NSS_RX); ++ if (mcs_nss_supp_bw->rx_tx_mcs11_max_nss) ++ max_nss = max(max_nss, u8_get_bits(mcs_nss_supp_bw->rx_tx_mcs11_max_nss, ++ IEEE80211_EHT_MCS_NSS_RX)); ++ if (mcs_nss_supp_bw->rx_tx_mcs9_max_nss) ++ max_nss = max(max_nss, u8_get_bits(mcs_nss_supp_bw->rx_tx_mcs9_max_nss, ++ IEEE80211_EHT_MCS_NSS_RX)); + } + +- max_nss = max(max_nss, (uint8_t)eht_nss); ++ max_nss = min(max_nss, (uint8_t)eht_nss); + + arg->peer_nss = min(link_sta->rx_nss, max_nss); + arg->ru_punct_bitmap = ~def.ru_punct_bitmap; diff --git a/feeds/ipq95xx/mac80211/patches/qca/707-b-ath12k-add-support-for-MLO-SSR-Mode0.patch b/feeds/ipq95xx/mac80211/patches/qca/707-b-ath12k-add-support-for-MLO-SSR-Mode0.patch new file mode 100644 index 000000000..3adbf8047 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/707-b-ath12k-add-support-for-MLO-SSR-Mode0.patch @@ -0,0 +1,852 @@ +From 13e5eb33fe30e6d08d9167a180ed492f7489f569 Mon Sep 17 00:00:00 2001 +From: Pradeep Kumar Chitrapu +Date: Tue, 17 Jan 2023 17:05:28 -0800 +Subject: [PATCH 2/3] ath12k: add support for MLO SSR Mode0 + +When target asserts, firmware asserts all chips in MLO group. +Driver recovers all the chips by first cleaning the driver +context and finally calling iee80211_restart_hw to inform +mac80211 to reconfigure all the BSS information. This patch +assumes support from mac80211 for MLO target recovery. +currently supports only AP mode. + +Co-Developed-by: Ramanathan Choodamani +Signed-off-by: Ramanathan Choodamani +Co-Developed-By: Sidhanta Sahu +Signed-off-by: Sidhanta Sahu +Signed-off-by: Pradeep Kumar Chitrapu +--- + drivers/net/wireless/ath/ath12k/core.c | 296 ++++++++++++++------- + drivers/net/wireless/ath/ath12k/core.h | 14 +- + drivers/net/wireless/ath/ath12k/coredump.c | 1 + + drivers/net/wireless/ath/ath12k/debugfs.c | 52 +++- + drivers/net/wireless/ath/ath12k/mac.c | 25 +- + drivers/net/wireless/ath/ath12k/mhi.c | 4 +- + drivers/net/wireless/ath/ath12k/qmi.c | 36 ++- + drivers/net/wireless/ath/ath12k/wmi.c | 10 +- + drivers/net/wireless/ath/ath12k/wmi.h | 3 +- + 9 files changed, 309 insertions(+), 132 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c +index cd12abc..88de5ac 100644 +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -43,6 +43,8 @@ static unsigned int ath12k_en_fwlog = true; + module_param_named(en_fwlog, ath12k_en_fwlog, uint, 0644); + MODULE_PARM_DESC(en_fwlog, "fwlog: 0-disable, 1-enable"); + ++static unsigned int ath12k_recovery_mode = ATH12K_MLO_RECOVERY_MODE0; ++ + static DEFINE_MUTEX(ath12k_hw_lock); + static struct list_head ath12k_hw_groups = LIST_HEAD_INIT(ath12k_hw_groups); + +@@ -132,6 +134,7 @@ ath12k_core_hw_group_alloc(u8 id, u8 max_chip) + ag->mlo_capable = !!ath12k_mlo_capable; + list_add(&ag->list, &ath12k_hw_groups); + mutex_init(&ag->mutex_lock); ++ ag->hw_queues_stopped = false; + + return ag; + } +@@ -957,10 +960,8 @@ static int ath12k_core_start(struct ath12k_base *ab, + goto err_reo_cleanup; + } + +- if (!test_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags)) { +- /* Indicate the core start in the appropriate group */ +- ab->ag->num_started++; +- } ++ /* Indicate the core start in the appropriate group */ ++ ab->ag->num_started++; + + return 0; + +@@ -1189,9 +1190,16 @@ static void ath12k_core_trigger_partner(struct ath12k_base *ab) + if (!partner_ab) + continue; + +- if (found) +- ath12k_qmi_trigger_host_cap(partner_ab); ++ ath12k_dbg(ab, ATH12K_DBG_QMI, "QMI Trigger Host Cap AB:%p Partner AB:%p Found:%d Num Radios: %d ag->num_chip:%d\n", ++ ab, partner_ab, found, ++ ab->qmi.num_radios, ag->num_chip); + ++ if (found) { ++ if (ath12k_recovery_mode == ATH12K_MLO_RECOVERY_MODE0 && ++ !test_bit(ATH12K_FLAG_QMI_HOST_CAP_SENT, &partner_ab->dev_flags)) { ++ ath12k_qmi_trigger_host_cap(partner_ab); ++ } ++ } + found = (partner_ab == ab) ? true : false; + } + } +@@ -1310,8 +1318,6 @@ static int ath12k_core_reconfigure_on_crash(struct ath12k_base *ab) + if (ret) + goto err_hal_srng_deinit; + +- clear_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags); +- + return 0; + + err_hal_srng_deinit: +@@ -1319,106 +1325,101 @@ err_hal_srng_deinit: + return ret; + } + +-void ath12k_core_halt(struct ath12k *ar) ++static void ath12k_core_mlo_hw_queues_stop(struct ath12k_hw_group *ag) + { +- struct ath12k_base *ab = ar->ab; ++ struct ath12k_base *ab; ++ struct ath12k_hw *ah; ++ int i; + +- lockdep_assert_held(&ar->conf_mutex); ++ lockdep_assert_held(&ag->mutex_lock); + +- ar->num_created_vdevs = 0; +- ar->allocated_vdev_map = 0; ++ for (i = 0; i < ag->num_hw; i++) { ++ ah = ag->ah[i]; ++ if (!ah) ++ continue; + +- ath12k_mac_scan_finish(ar); +- ath12k_mac_peer_cleanup_all(ar); +- cancel_delayed_work_sync(&ar->scan.timeout); +- cancel_work_sync(&ar->regd_update_work); ++ ieee80211_stop_queues(ah->hw); ++ } ++ ag->hw_queues_stopped = true; + +- rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], NULL); +- synchronize_rcu(); +- INIT_LIST_HEAD(&ar->arvifs); +- idr_init(&ar->txmgmt_idr); ++ for (i = 0; i < ag->num_chip; i++) { ++ ab = ag->ab[i]; ++ ++ /* ++ * In Mode0, partner chips are expected to be asserted, hence reset ++ * qmi.num_radios count to ensure avoiding duplicate host cap triggers. ++ */ ++ if (ath12k_recovery_mode == ATH12K_MLO_RECOVERY_MODE0) { ++ ab->qmi.num_radios = ATH12K_QMI_INVALID_RADIO; ++ clear_bit(ATH12K_FLAG_QMI_HOST_CAP_SENT, &ab->dev_flags); ++ } ++ } + } + +-static void ath12k_core_restart(struct work_struct *work) ++static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab) + { +- struct ath12k_base *ab = container_of(work, struct ath12k_base, restart_work); +- struct ath12k_hw_group *ag = ab->ag; +- int ret; + struct ath12k *ar; + struct ath12k_pdev *pdev; + struct ath12k_link_vif *arvif; +- struct ath12k_hw *ah; +- int i, j; ++ int i; + + spin_lock_bh(&ab->base_lock); + ab->stats.fw_crash_counter++; + spin_unlock_bh(&ab->base_lock); + +- for (i = 0; i < ag->num_hw; i++) { +- ah = ag->ah[i]; +- if (!ah) ++ for (i = 0; i < ab->num_radios; i++) { ++ pdev = &ab->pdevs[i]; ++ ar = pdev->ar; ++ if (!ar || ar->state == ATH12K_STATE_OFF) + continue; + +- ieee80211_stop_queues(ah->hw); +- } +- +- for (i = 0; i < ag->num_chip; i++) { +- ab = ag->ab[i]; ++ list_for_each_entry(arvif, &ar->arvifs, list) ++ if (arvif->is_started) ++ ath12k_debugfs_remove_interface(arvif); + +- for (j = 0; j < ab->num_radios; j++) { +- pdev = &ab->pdevs[j]; +- ar = pdev->ar; +- if (!ar || ar->state == ATH12K_STATE_OFF) +- continue; ++ ath12k_mac_drain_tx(ar); ++ complete(&ar->scan.started); ++ complete(&ar->scan.completed); ++ complete(&ar->peer_assoc_done); ++ complete(&ar->peer_delete_done); ++ complete(&ar->install_key_done); ++ complete(&ar->vdev_setup_done); ++ complete(&ar->vdev_delete_done); ++ complete(&ar->bss_survey_done); ++ complete(&ar->thermal.wmi_sync); + +- list_for_each_entry(arvif, &ar->arvifs, list) { +- if (arvif->is_started) { +- ath12k_debugfs_remove_interface(arvif); +- } +- } ++ wake_up(&ar->dp.tx_empty_waitq); ++ idr_for_each(&ar->txmgmt_idr, ++ ath12k_mac_tx_mgmt_pending_free, ar); ++ idr_destroy(&ar->txmgmt_idr); ++ wake_up(&ar->txmgmt_empty_waitq); + +- ath12k_mac_drain_tx(ar); +- complete(&ar->scan.started); +- complete(&ar->scan.completed); +- complete(&ar->peer_assoc_done); +- complete(&ar->peer_delete_done); +- complete(&ar->install_key_done); +- complete(&ar->vdev_setup_done); +- complete(&ar->vdev_delete_done); +- complete(&ar->bss_survey_done); +- complete(&ar->thermal.wmi_sync); +- +- wake_up(&ar->dp.tx_empty_waitq); +- idr_for_each(&ar->txmgmt_idr, +- ath12k_mac_tx_mgmt_pending_free, ar); +- idr_destroy(&ar->txmgmt_idr); +- wake_up(&ar->txmgmt_empty_waitq); +- +- ar->monitor_vdev_id = -1; +- clear_bit(MONITOR_VDEV_STARTED, &ar->monitor_flags); +- clear_bit(MONITOR_VDEV_CREATED, &ar->monitor_flags); +- } ++ ar->monitor_vdev_id = -1; ++ clear_bit(MONITOR_VDEV_STARTED, &ar->monitor_flags); ++ clear_bit(MONITOR_VDEV_CREATED, &ar->monitor_flags); ++ } + +- wake_up(&ab->wmi_ab.tx_credits_wq); +- wake_up(&ab->peer_mapping_wq); ++ wake_up(&ab->wmi_ab.tx_credits_wq); ++ wake_up(&ab->peer_mapping_wq); + ++} + +- ret = ath12k_core_reconfigure_on_crash(ab); +- if (ret) { +- ath12k_err(ab, "failed to reconfigure driver on crash recovery\n"); +- return; +- } ++static void ath12k_core_post_reconfigure_recovery(struct ath12k_base *ab) ++{ ++ struct ath12k *ar; ++ struct ath12k_pdev *pdev; ++ int i; + +- for (j = 0; j < ab->num_radios; j++) { +- pdev = &ab->pdevs[j]; +- ar = pdev->ar; +- if (!ar || ar->state == ATH12K_STATE_OFF || +- ar->state == ATH12K_STATE_TM) +- continue; ++ for (i = 0; i < ab->num_radios; i++) { ++ pdev = &ab->pdevs[i]; ++ ar = pdev->ar; ++ if (!ar || ar->state == ATH12K_STATE_OFF || ++ ar->state == ATH12K_STATE_TM) ++ continue; + +- mutex_lock(&ar->conf_mutex); ++ mutex_lock(&ar->conf_mutex); + +- switch (ar->state) { ++ switch (ar->state) { + case ATH12K_STATE_ON: + ar->state = ATH12K_STATE_RESTARTING; + ath12k_core_halt(ar); +@@ -1426,50 +1427,108 @@ static void ath12k_core_restart(struct work_struct *work) + case ATH12K_STATE_OFF: + ath12k_warn(ab, + "cannot restart radio %d that hasn't been started\n", +- j); ++ i); + break; + case ATH12K_STATE_RESTARTING: ++ ar->state = ATH12K_STATE_RESTARTED; + break; + case ATH12K_STATE_RESTARTED: + ar->state = ATH12K_STATE_WEDGED; + fallthrough; + case ATH12K_STATE_WEDGED: + ath12k_warn(ab, +- "device is wedged, will not restart radio %d\n", j); ++ "device is wedged, will not restart radio %d\n", i); + break; + case ATH12K_STATE_TM: +- ath12k_warn(ab, "fw mode reset done radio %d\n", j); ++ ath12k_warn(ab, "fw mode reset done radio %d\n", i); + break; +- } +- mutex_unlock(&ar->conf_mutex); + } ++ mutex_unlock(&ar->conf_mutex); ++ } ++} + +- if (ab->is_reset) { +- atomic_dec(&ab->reset_count); +- complete(&ab->reset_complete); +- ab->is_reset = false; +- } ++void ath12k_core_halt(struct ath12k *ar) ++{ ++ struct ath12k_base *ab = ar->ab; ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ ar->num_created_vdevs = 0; ++ ar->allocated_vdev_map = 0; ++ ++ ath12k_mac_scan_finish(ar); ++ ath12k_mac_peer_cleanup_all(ar); ++ cancel_delayed_work_sync(&ar->scan.timeout); ++ cancel_work_sync(&ar->regd_update_work); ++ rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], NULL); ++ synchronize_rcu(); ++ INIT_LIST_HEAD(&ar->arvifs); ++ idr_init(&ar->txmgmt_idr); ++} ++ ++static void ath12k_core_restart(struct work_struct *work) ++{ ++ struct ath12k_base *ab = container_of(work, struct ath12k_base, restart_work); ++ struct ath12k_hw_group *ag = ab->ag; ++ int ret; ++ struct ath12k_hw *ah; ++ int i; ++ ++ if (!ab->is_reset) ++ ath12k_core_pre_reconfigure_recovery(ab); + +- complete(&ab->driver_recovery); ++ ret = ath12k_core_reconfigure_on_crash(ab); ++ if (ret) { ++ ath12k_err(ab, "failed to reconfigure driver on crash recovery\n"); ++ return; + } + +- for (i = 0; i < ag->num_hw; i++) { +- ah = ag->ah[i]; +- if (!ah) +- continue; ++ if (!ab->is_reset) ++ ath12k_core_post_reconfigure_recovery(ab); ++ ++ if (ath12k_core_hw_group_start_ready(ag) && ++ ath12k_recovery_mode == ATH12K_MLO_RECOVERY_MODE0) { ++ for (i = 0; i < ag->num_hw; i++) { ++ ah = ag->ah[i]; ++ if (!ah) ++ continue; + +- mutex_lock(&ah->conf_mutex); +- ieee80211_restart_hw(ah->hw); +- mutex_unlock(&ah->conf_mutex); ++ mutex_lock(&ah->conf_mutex); ++ ieee80211_restart_hw(ah->hw); ++ mutex_unlock(&ah->conf_mutex); ++ } + } ++ + } + + static void ath12k_core_reset(struct work_struct *work) + { + struct ath12k_base *ab = container_of(work, struct ath12k_base, reset_work); +- int reset_count; ++ struct ath12k_hw_group *ag = ab->ag; ++ struct ath12k_base *partner_ab; ++ int reset_count, fail_cont_count, i; + long time_left; + ++ /* Sometimes the recovery will fail and then the next all recovery fail, ++ * this is to avoid infinite recovery since it can not recovery success. ++ */ ++ fail_cont_count = atomic_read(&ab->fail_cont_count); ++ ++ if (fail_cont_count >= ATH12K_RESET_MAX_FAIL_COUNT_FINAL) { ++ ath12k_warn(ab, "Recovery Failed, Fail count:%d MAX_FAIL_COUNT final:%d\n", ++ fail_cont_count, ++ ATH12K_RESET_MAX_FAIL_COUNT_FINAL); ++ return; ++ } ++ ++ if (fail_cont_count >= ATH12K_RESET_MAX_FAIL_COUNT_FIRST && ++ time_before(jiffies, ab->reset_fail_timeout)) { ++ ath12k_warn(ab, "Recovery Failed, Fail count:%d MAX_FAIL_COUNT first:%d\n", ++ fail_cont_count, ++ ATH12K_RESET_MAX_FAIL_COUNT_FIRST); ++ return; ++ } ++ + reset_count = atomic_inc_return(&ab->reset_count); + + if (reset_count > 1) { +@@ -1488,11 +1547,45 @@ static void ath12k_core_reset(struct work_struct *work) + return; + } + ++ ab->reset_fail_timeout = jiffies + ATH12K_RESET_FAIL_TIMEOUT_HZ; ++ /* Record the continuous recovery fail count when recovery failed*/ ++ atomic_inc(&ab->fail_cont_count); + } + + ath12k_dbg(ab, ATH12K_DBG_BOOT, "reset starting\n"); ++ ab->recovery_start_time = jiffies; + ++ mutex_lock(&ag->mutex_lock); + ab->is_reset = true; ++ atomic_set(&ab->recovery_count, 0); ++ ++ for (i = 0; i < ag->num_chip; i++) { ++ partner_ab = ag->ab[i]; ++ if (ab == partner_ab) ++ continue; ++ ++ /* issue FW Hang command on partner chips for Mode0. This is a fool proof ++ * method to ensure recovery of all partner chips in MODE0 instead of ++ * relying on firmware to crash partner chips ++ */ ++ if (ath12k_recovery_mode == ATH12K_MLO_RECOVERY_MODE0 && ++ !test_bit(ATH12K_FLAG_RECOVERY, &partner_ab->dev_flags)) ++ ath12k_wmi_force_fw_hang_cmd(partner_ab->pdevs[0].ar, ++ ATH12K_WMI_FW_HANG_ASSERT_TYPE, ++ ATH12K_WMI_FW_HANG_DELAY, true); ++ } ++ ++ /* Incase recovery fails and FW asserts again, this is to prevent invalid operation. */ ++ if (ag->num_started && ab->fw_recovery_support) ++ ag->num_started--; ++ ++ if (!ag->hw_queues_stopped) ++ ath12k_core_mlo_hw_queues_stop(ag); ++ ++ ath12k_core_pre_reconfigure_recovery(ab); ++ ++ ath12k_core_post_reconfigure_recovery(ab); ++ + /* reset host fixed mem off to zero */ + ab->host_ddr_fixed_mem_off = 0; + /* prepare coredump */ +@@ -1504,6 +1597,7 @@ static void ath12k_core_reset(struct work_struct *work) + + ath12k_dbg(ab, ATH12K_DBG_BOOT, "reset started\n"); + } ++ mutex_unlock(&ag->mutex_lock); + } + + int ath12k_core_pre_init(struct ath12k_base *ab) +@@ -1746,8 +1840,6 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size, + if (!ab) + return NULL; + +- init_completion(&ab->driver_recovery); +- + ab->workqueue = create_singlethread_workqueue("ath12k_wq"); + if (!ab->workqueue) + goto err_sc_free; +diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h +index f2ebae0..c5dcdc8 100644 +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -42,7 +42,7 @@ + extern unsigned int ath12k_frame_mode; + + #define ATH12K_MON_TIMER_INTERVAL 10 +-#define ATH12K_RESET_TIMEOUT_HZ (20 * HZ) ++#define ATH12K_RESET_TIMEOUT_HZ (180 * HZ) + #define ATH12K_RESET_MAX_FAIL_COUNT_FIRST 3 + #define ATH12K_RESET_MAX_FAIL_COUNT_FINAL 5 + #define ATH12K_RESET_FAIL_TIMEOUT_HZ (20 * HZ) +@@ -226,6 +226,7 @@ enum ath12k_dev_flags { + ATH12K_FLAG_QMI_FAIL, + ATH12K_FLAG_HTC_SUSPEND_COMPLETE, + ATH12K_FLAG_QMI_FW_READY_COMPLETE, ++ ATH12K_FLAG_QMI_HOST_CAP_SENT, + ATH12K_FLAG_HW_GROUP_ATTACHED, + ATH12K_FLAG_FTM_SEGMENTED, + }; +@@ -1042,6 +1043,10 @@ struct ath12k_mlo_memory { + bool init_done; + }; + ++enum ath12k_mlo_recovery_mode { ++ ATH12K_MLO_RECOVERY_MODE0, ++}; ++ + /* Holds info on the group of SOCs that are registered as a single wiphy + * or single SOC where each radio registered as separate wiphy in non-MLO + */ +@@ -1054,6 +1059,7 @@ struct ath12k_hw_group { + u8 num_started; + u8 num_hw; + bool mlo_capable; ++ bool hw_queues_stopped; + unsigned long dev_flags; + struct ath12k_hw *ah[ATH12K_GROUP_MAX_RADIO]; + struct ath12k_base *ab[ATH12K_MAX_SOCS]; +@@ -1150,13 +1156,19 @@ struct ath12k_base { + struct work_struct restart_work; + struct workqueue_struct *workqueue_aux; + struct work_struct reset_work; ++ atomic_t recovery_count; + atomic_t reset_count; + bool is_reset; + struct completion reset_complete; ++ struct completion reconfigure_complete; + unsigned long reset_fail_timeout; ++ /* continuous recovery fail count */ ++ atomic_t fail_cont_count; ++ u32 recovery_start_time; + struct { + /* protected by data_lock */ + u32 fw_crash_counter; ++ u32 last_recovery_time; + } stats; + bool ftm_segment_handler; + struct ath12k_ftm_event_obj ftm_event_obj; +diff --git a/drivers/net/wireless/ath/ath12k/coredump.c b/drivers/net/wireless/ath/ath12k/coredump.c +index e2b6683..3096d9b 100644 +--- a/drivers/net/wireless/ath/ath12k/coredump.c ++++ b/drivers/net/wireless/ath/ath12k/coredump.c +@@ -327,6 +327,7 @@ void ath12k_coredump_download_rddm(struct ath12k_base *ab) + atomic_read(&ath12k_coredump_ram_info.num_chip)); + } else { + /* TODO dump collection for MLO when fw_recovery set */ ++ ath12k_info(ab, "WLAN target is restarting"); + ath12k_coredump_build_inline(ab, segment, num_seg); + vfree(segment); + } +diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c +index 437a711..e9c66a9 100644 +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -443,6 +443,40 @@ static const struct file_operations fops_vdev_stats_offload = { + .open = simple_open + }; + ++static ssize_t ath12k_debug_fw_reset_stats_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k_base *ab = file->private_data; ++ int ret; ++ size_t len = 0, buf_len = 500; ++ char *buf; ++ ++ buf = kmalloc(buf_len, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ spin_lock_bh(&ab->base_lock); ++ len += scnprintf(buf + len, buf_len - len, ++ "fw_crash_counter\t\t%d\n", ab->stats.fw_crash_counter); ++ len += scnprintf(buf + len, buf_len - len, ++ "last_recovery_time\t\t%d\n", ab->stats.last_recovery_time); ++ spin_unlock_bh(&ab->base_lock); ++ ++ ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ ++ kfree(buf); ++ ++ return ret; ++} ++ ++static const struct file_operations fops_fw_reset_stats = { ++ .open = simple_open, ++ .read = ath12k_debug_fw_reset_stats_read, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ + static ssize_t ath12k_read_simulate_fw_crash(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +@@ -502,7 +536,7 @@ static ssize_t ath12k_write_simulate_fw_crash(struct file *file, + ath12k_info(ab, "simulating firmware assert crash\n"); + ret = ath12k_wmi_force_fw_hang_cmd(ar, + ATH12K_WMI_FW_HANG_ASSERT_TYPE, +- ATH12K_WMI_FW_HANG_DELAY); ++ ATH12K_WMI_FW_HANG_DELAY, false); + } else { + ret = -EINVAL; + goto exit; +@@ -913,8 +947,10 @@ static ssize_t ath12k_debug_write_fw_recovery(struct file *file, + size_t count, loff_t *ppos) + { + struct ath12k_base *ab = file->private_data; ++ struct ath12k_hw_group *ag; + unsigned int value; + int ret; ++ int i; + + if (kstrtouint_from_user(user_buf, count, 0, &value)) + return -EINVAL; +@@ -927,7 +963,16 @@ static ssize_t ath12k_debug_write_fw_recovery(struct file *file, + goto exit; + } + +- ab->fw_recovery_support = value ? true : false; ++ ag = ab->ag; ++ if (ag->mlo_capable) { ++ for (i = 0; i < ag->num_chip; i++) { ++ ab = ag->ab[i]; ++ mutex_lock(&ab->core_lock); ++ ab->fw_recovery_support = value ? true : false; ++ mutex_unlock(&ab->core_lock); ++ } ++ } else ++ ab->fw_recovery_support = value ? true : false; + + ret = count; + +@@ -1209,6 +1254,9 @@ int ath12k_debugfs_pdev_create(struct ath12k_base *ab) + debugfs_create_file("rx_hash_ix3", 0600, ab->debugfs_soc, ab, + &fops_soc_rx_hash_ix3); + ++ debugfs_create_file("fw_reset_stats", 0400, ab->debugfs_soc, ab, ++ &fops_fw_reset_stats); ++ + return 0; + } + +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index 6d3556d..0155fab 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -12791,7 +12791,7 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw, + { + struct ath12k_hw *ah = hw->priv; + struct ath12k *ar; +- u8 restart_count = 0; ++ u8 restart_count = 0, recovery_count; + int i; + + if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART) +@@ -12811,6 +12811,28 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw, + restart_count++; + } + ++ if (ar->ab->is_reset) { ++ recovery_count = atomic_inc_return(&ar->ab->recovery_count); ++ ath12k_dbg(ar->ab, ATH12K_DBG_BOOT, ++ "recovery count %d\n", recovery_count); ++ /* When there are multiple radios in an SOC, ++ * the recovery has to be done for each radio ++ */ ++ if (recovery_count == ar->ab->num_radios) { ++ atomic_dec(&ar->ab->reset_count); ++ complete(&ar->ab->reset_complete); ++ ar->ab->is_reset = false; ++ atomic_set(&ar->ab->fail_cont_count, 0); ++ clear_bit(ATH12K_FLAG_RECOVERY, &ar->ab->dev_flags); ++ spin_lock_bh(&ar->ab->base_lock); ++ ar->ab->stats.last_recovery_time = ++ jiffies_to_msecs(jiffies - ++ ar->ab->recovery_start_time); ++ spin_unlock_bh(&ar->ab->base_lock); ++ ath12k_dbg(ar->ab, ATH12K_DBG_BOOT, "reset success\n"); ++ } ++ } ++ + mutex_unlock(&ar->conf_mutex); + ar++; + } +@@ -12819,6 +12841,7 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw, + ieee80211_wake_queues(ah->hw); + + mutex_unlock(&ah->conf_mutex); ++ ah->ag->hw_queues_stopped = false; + } + + static void +diff --git a/drivers/net/wireless/ath/ath12k/mhi.c b/drivers/net/wireless/ath/ath12k/mhi.c +index 0c369f8..e4895e2 100644 +--- a/drivers/net/wireless/ath/ath12k/mhi.c ++++ b/drivers/net/wireless/ath/ath12k/mhi.c +@@ -330,8 +330,10 @@ static void ath12k_mhi_op_status_cb(struct mhi_controller *mhi_cntrl, + ath12k_warn(ab, "firmware crashed: MHI_CB_SYS_ERROR\n"); + break; + case MHI_CB_EE_RDDM: +- if (!(test_bit(ATH12K_FLAG_UNREGISTERING, &ab->ag->dev_flags))) ++ if (!(test_bit(ATH12K_FLAG_UNREGISTERING, &ab->ag->dev_flags))) { ++ set_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags); + queue_work(ab->workqueue_aux, &ab->reset_work); ++ } + ath12k_hal_dump_srng_stats(ab); + break; + default: +diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c +index e2e1b2c..1b978d8 100644 +--- a/drivers/net/wireless/ath/ath12k/qmi.c ++++ b/drivers/net/wireless/ath/ath12k/qmi.c +@@ -3237,12 +3237,9 @@ static void ath12k_qmi_free_mlo_mem_chunk(struct ath12k_base *ab, + + lockdep_assert_held(&ag->mutex_lock); + +- if (!ag->mlo_mem.init_done) ++ if (!ag->mlo_mem.init_done || ag->num_started) + return; + +- if (ag->num_started) +- goto out; +- + if (idx >= ARRAY_SIZE(ag->mlo_mem.chunk)) { + ath12k_warn(ab, "invalid idx %d for MLO memory chunk free\n", idx); + return; +@@ -3268,7 +3265,6 @@ static void ath12k_qmi_free_mlo_mem_chunk(struct ath12k_base *ab, + mlo_chunk->paddr = NULL; + mlo_chunk->size = 0; + +-out: + if (fixed_mem) + chunk->v.ioaddr = NULL; + else +@@ -4413,10 +4409,10 @@ static bool ath12k_qmi_hw_group_host_cap_ready(struct ath12k_hw_group *ag) + return true; + } + +-static struct ath12k_base * +-ath12k_qmi_hw_group_find_blocked_chip(struct ath12k_hw_group *ag) ++static int ++ath12k_qmi_hw_grp_find_blocked_chip_n_send_host_cap(struct ath12k_hw_group *ag) + { +- struct ath12k_base *ab; ++ struct ath12k_base *blocked_ab; + struct ath12k_qmi *qmi; + bool block; + int i; +@@ -4424,26 +4420,28 @@ ath12k_qmi_hw_group_find_blocked_chip(struct ath12k_hw_group *ag) + lockdep_assert_held(&ag->mutex_lock); + + for (i = 0; i < ag->num_chip; i++) { +- ab = ag->ab[i]; +- if (!ab) ++ blocked_ab = ag->ab[i]; ++ ++ if (!blocked_ab) + continue; + +- qmi = &ab->qmi; ++ qmi = &blocked_ab->qmi; + + spin_lock(&qmi->event_lock); + block = ath12k_qmi_get_event_block(qmi); + spin_unlock(&qmi->event_lock); + +- if (block) +- return ab; ++ if (block) { ++ ath12k_qmi_trigger_host_cap(blocked_ab); ++ } + } + +- return NULL; ++ return 0; + } + + static int ath12k_qmi_event_server_arrive(struct ath12k_qmi *qmi) + { +- struct ath12k_base *ab = qmi->ab, *block_ab; ++ struct ath12k_base *ab = qmi->ab; + struct ath12k_hw_group *ag = ab->ag; + bool host_cap_ready; + int ret; +@@ -4455,7 +4453,6 @@ static int ath12k_qmi_event_server_arrive(struct ath12k_qmi *qmi) + } + + ath12k_qmi_phy_cap_send(ab); +- + if (ath12k_cold_boot_cal && ab->qmi.cal_done == 0 && + ab->hw_params->cold_boot_calib && + ab->qmi.cal_timeout == 0) { +@@ -4469,9 +4466,7 @@ static int ath12k_qmi_event_server_arrive(struct ath12k_qmi *qmi) + mutex_lock(&ag->mutex_lock); + host_cap_ready = ath12k_qmi_hw_group_host_cap_ready(ag); + if (host_cap_ready) { +- block_ab = ath12k_qmi_hw_group_find_blocked_chip(ag); +- if (block_ab) +- ath12k_qmi_trigger_host_cap(block_ab); ++ ret = ath12k_qmi_hw_grp_find_blocked_chip_n_send_host_cap(ag); + } + mutex_unlock(&ag->mutex_lock); + } +@@ -4486,9 +4481,11 @@ static int ath12k_qmi_event_host_cap(struct ath12k_qmi *qmi) + + ret = ath12k_qmi_host_cap_send(ab); + if (ret < 0) { ++ clear_bit(ATH12K_FLAG_QMI_HOST_CAP_SENT, &ab->dev_flags); + ath12k_warn(ab, "qmi failed to send host cap QMI:%d\n", ret); + return ret; + } ++ set_bit(ATH12K_FLAG_QMI_HOST_CAP_SENT, &ab->dev_flags); + + return ret; + } +@@ -5091,7 +5088,6 @@ static void ath12k_qmi_driver_event_work(struct work_struct *work) + break; + case ATH12K_QMI_EVENT_SERVER_EXIT: + set_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags); +- set_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags); + break; + case ATH12K_QMI_EVENT_REQUEST_MEM: + ret = ath12k_qmi_event_mem_request(qmi); +diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c +index 721f7d2..475e6d1 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -1745,12 +1745,12 @@ int ath12k_wmi_set_sta_ps_param(struct ath12k *ar, u32 vdev_id, + return ret; + } + +-int ath12k_wmi_force_fw_hang_cmd(struct ath12k *ar, u32 type, u32 delay_time_ms) ++int ath12k_wmi_force_fw_hang_cmd(struct ath12k *ar, u32 type, u32 delay_time_ms, bool nowait) + { + struct ath12k_pdev_wmi *wmi = ar->wmi; + struct wmi_force_fw_hang_cmd *cmd; + struct sk_buff *skb; +- int ret, len; ++ int ret = 0, len; + + len = sizeof(*cmd); + +@@ -1765,8 +1765,10 @@ int ath12k_wmi_force_fw_hang_cmd(struct ath12k *ar, u32 type, u32 delay_time_ms) + cmd->type = cpu_to_le32(type); + cmd->delay_time_ms = cpu_to_le32(delay_time_ms); + +- ret = ath12k_wmi_cmd_send(wmi, skb, WMI_FORCE_FW_HANG_CMDID); +- ++ if (nowait) ++ ath12k_wmi_cmd_send_nowait(wmi, skb, WMI_FORCE_FW_HANG_CMDID); ++ else ++ ret = ath12k_wmi_cmd_send(wmi, skb, WMI_FORCE_FW_HANG_CMDID); + if (ret) { + ath12k_warn(ar->ab, "Failed to send WMI_FORCE_FW_HANG_CMDID"); + dev_kfree_skb(skb); +diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h +index 773f7ff..f2046b8 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -6681,7 +6681,8 @@ int ath12k_wmi_vdev_set_param_cmd(struct ath12k *ar, u32 vdev_id, + + int ath12k_wmi_set_sta_ps_param(struct ath12k *ar, u32 vdev_id, + u32 param, u32 param_value); +-int ath12k_wmi_force_fw_hang_cmd(struct ath12k *ar, u32 type, u32 delay_time_ms); ++int ath12k_wmi_force_fw_hang_cmd(struct ath12k *ar, u32 type, u32 delay_time_ms, ++ bool nowait); + int ath12k_wmi_send_peer_delete_cmd(struct ath12k *ar, + const u8 *peer_addr, u8 vdev_id); + int ath12k_wmi_vdev_delete(struct ath12k *ar, u8 vdev_id); +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/707-c-ath12k-fix-incorrect-rates-sent-to-firmware.patch b/feeds/ipq95xx/mac80211/patches/qca/707-c-ath12k-fix-incorrect-rates-sent-to-firmware.patch new file mode 100644 index 000000000..c99dd9e33 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/707-c-ath12k-fix-incorrect-rates-sent-to-firmware.patch @@ -0,0 +1,71 @@ +From 5cb67ef86fb5c587ab1959a2bf2922fc2eee54e1 Mon Sep 17 00:00:00 2001 +From: Pradeep Kumar Chitrapu +Date: Tue, 17 Jan 2023 17:08:07 -0800 +Subject: [PATCH 3/3] ath12k: fix incorrect rates sent to firmware + +Sometimes when basic rates are zeros, ath12k is sening invalid +rate codes to firmware which cause firmware assert. Fix this by +sending rate code appropriately for basic rates being 0. + +Co-Developed-by: Ramanathan Choodamani +Signed-off-by: Ramanathan Choodamani +Signed-off-by: Pradeep Kumar Chitrapu +--- + drivers/net/wireless/ath/ath12k/mac.c | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index c2681c0f15de..d99cd06dc0ad 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -3786,7 +3786,9 @@ static void ath12k_recalculate_mgmt_rate(struct ath12k *ar, + lockdep_assert_held(&ar->conf_mutex); + + sband = ar->ah->hw->wiphy->bands[def->chan->band]; +- basic_rate_idx = ffs(link_conf->basic_rates) - 1; ++ basic_rate_idx = ffs(link_conf->basic_rates); ++ if (basic_rate_idx) ++ basic_rate_idx -= 1; + bitrate = sband->bitrates[basic_rate_idx].bitrate; + + hw_rate_code = ath12k_mac_get_rate_hw_value(bitrate); +@@ -4283,10 +4285,13 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar, + band = def.chan->band; + mcast_rate = info->mcast_rate[band]; + +- if (mcast_rate > 0) ++ if (mcast_rate > 0) { + rateidx = mcast_rate - 1; +- else +- rateidx = ffs(info->basic_rates) - 1; ++ } else { ++ rateidx = ffs(info->basic_rates); ++ if (rateidx) ++ rateidx -= 1; ++ } + + if (ar->pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP) + rateidx += ATH12K_MAC_FIRST_OFDM_RATE_IDX; +@@ -6097,7 +6102,9 @@ static void ath12k_mac_dec_num_stations(struct ath12k_link_vif *arvif, + if (ahvif->vdev_type == WMI_VDEV_TYPE_STA && !sta->tdls) + return; + +- ar->num_stations--; ++ WARN_ON(ar->num_stations == 0); ++ if (ar->num_stations) ++ ar->num_stations--; + } + + static void ath12k_mac_station_post_remove(struct ath12k *ar, +@@ -8364,7 +8371,7 @@ static int ath12k_mac_radio_start(struct ath12k *ar) + 1, pdev->pdev_id); + + if (ret) { +- ath12k_err(ab, "failed to enable PMF QOS: (%d\n", ret); ++ ath12k_err(ab, "failed to enable PMF QOS: (%d)\n", ret); + goto err; + } + +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/707-cfg80211-Allow-non-public-action-frames-to-be-transm.patch b/feeds/ipq95xx/mac80211/patches/qca/707-cfg80211-Allow-non-public-action-frames-to-be-transm.patch new file mode 100644 index 000000000..6139c06e1 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/707-cfg80211-Allow-non-public-action-frames-to-be-transm.patch @@ -0,0 +1,36 @@ +From 8313885b3c68c56695ea7e27f5c7652bcb9b096e Mon Sep 17 00:00:00 2001 +From: Rameshkumar Sundaram +Date: Mon, 23 Jan 2023 14:28:24 +0530 +Subject: [PATCH] cfg80211: Allow non public action frames to be transmitted + with link BSS + +In case of an MLD if User-space has provided a link_id to action frame +tx request, allow transmission of the frame in that link, Currently +action frames only with ML address as A3 are allowed, but tx for a +non-ml STA on any link of an ML BSS can happen with link address +as A3. + +Signed-off-by: Rameshkumar Sundaram +--- + net/wireless/mlme.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c +index 42576e8..5ad4a19 100644 +--- a/net/wireless/mlme.c ++++ b/net/wireless/mlme.c +@@ -739,7 +739,10 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, + case NL80211_IFTYPE_P2P_GO: + case NL80211_IFTYPE_AP_VLAN: + if (!ether_addr_equal(mgmt->bssid, wdev_address(wdev))) +- err = -EINVAL; ++ if (params->link_id < 0 || ++ !ether_addr_equal(mgmt->bssid, ++ wdev->links[params->link_id].addr)) ++ err = -EINVAL; + break; + case NL80211_IFTYPE_MESH_POINT: + if (!ether_addr_equal(mgmt->sa, mgmt->bssid)) { +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/707-mac80211-pass-channel-info-in-AWGN-event.patch b/feeds/ipq95xx/mac80211/patches/qca/707-mac80211-pass-channel-info-in-AWGN-event.patch new file mode 100644 index 000000000..01b8d75ea --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/707-mac80211-pass-channel-info-in-AWGN-event.patch @@ -0,0 +1,207 @@ +From 580cb5e6c0a0416062e30acd76a8ffb49f02555d Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Sat, 7 Jan 2023 22:56:24 +0530 +Subject: [PATCH] mac80211: pass channel info in AWGN event + +Currently during AWGN event, drivers only passes the +ieee80211_hw on which AWGN interference is detected and +the interference bitmap. The worker, iterates over each +channel contexts avaiable under the hardware and expects +only 1 channel contexts to be present. Then, with this +channel context it executes further steps. + +However, with MLO, there can be more than 1 channel contexts +available under the hardware hence while iterating, it is +important to know on which channel AWGN interference was +detected. + +Add logic to pass channel info as well in the AWGN detcted +event and use it properly to process further in the AWGN +event. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath11k/wmi.c | 3 ++- + drivers/net/wireless/ath/ath12k/wmi.c | 3 ++- + include/net/mac80211.h | 5 ++++- + net/mac80211/ieee80211_i.h | 1 + + net/mac80211/util.c | 28 ++++++++++++++++++++++----- + 5 files changed, 32 insertions(+), 8 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -9757,7 +9757,8 @@ ath11k_wmi_dcs_awgn_interference_event(s + } + ar->awgn_chandef = *chandef; + +- ieee80211_awgn_detected(ar->hw, awgn_info.chan_bw_interference_bitmap); ++ ieee80211_awgn_detected(ar->hw, awgn_info.chan_bw_interference_bitmap, ++ NULL); + + spin_lock_bh(&ar->data_lock); + /* Incase of mesh intf presence, dont set in prog as there will be no +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -9091,7 +9091,8 @@ ath12k_wmi_dcs_awgn_interference_event(s + } + ar->awgn_chandef = *chandef; + +- ieee80211_awgn_detected(ah->hw, awgn_info.chan_bw_interference_bitmap); ++ ieee80211_awgn_detected(ah->hw, awgn_info.chan_bw_interference_bitmap, ++ chandef->chan); + + spin_lock_bh(&ar->data_lock); + ar->awgn_intf_handling_in_prog = true; +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -6612,8 +6612,11 @@ void ieee80211_channel_switch_disconnect + * + * @hw: pointer as obtained from ieee80211_alloc_hw() + * @chan_bw_interference_bitmap : awgn interference bitmap ++ * @awgn_channel: Channel pointer on which AWGN is detected. Mandatory to pass ++ * for MLO drivers. For non-MLO %NULL can be passed + */ +-void ieee80211_awgn_detected(struct ieee80211_hw *hw, u32 chan_bw_interference_bitmap); ++void ieee80211_awgn_detected(struct ieee80211_hw *hw, u32 chan_bw_interference_bitmap, ++ struct ieee80211_channel *awgn_channel); + + /** + * ieee80211_request_smps - request SM PS transition +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1302,6 +1302,12 @@ struct channel_radar_info { + struct ieee80211_channel *radar_channel; + }; + ++struct channel_awgn_info { ++ struct list_head list; ++ struct ieee80211_channel *awgn_channel; ++ u32 chan_bw_interference_bitmap; ++}; ++ + struct ieee80211_local { + /* embed the driver visible part. + * don't cast (use the static inlines below), but we keep +@@ -1590,10 +1596,11 @@ struct ieee80211_local { + + struct mac80211_memory_stats memory_stats; + struct work_struct awgn_detected_work; +- u32 chan_bw_interference_bitmap; + + bool enable_tx_latency_stats; + ++ struct list_head awgn_info_list; ++ + /* extended capabilities provided by mac80211 */ + u8 ext_capa[8]; + }; +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -4307,11 +4307,12 @@ void ieee80211_dfs_cac_cancel(struct iee + mutex_unlock(&local->mtx); + } + +-void ieee80211_awgn_detected_work(struct work_struct *work) ++static void ieee80211_awgn_detected_processing(struct ieee80211_local *local, ++ u32 interference_bitmap, ++ struct ieee80211_channel *awgn_channel) + { +- struct ieee80211_local *local = +- container_of(work, struct ieee80211_local, awgn_detected_work); + struct cfg80211_chan_def chandef = local->hw.conf.chandef; ++ struct cfg80211_chan_def *awgn_chandef = NULL; + struct ieee80211_chanctx *ctx; + int num_chanctx = 0; + +@@ -4322,15 +4323,52 @@ void ieee80211_awgn_detected_work(struct + + num_chanctx++; + chandef = ctx->conf.def; ++ ++ if (awgn_channel && ++ (chandef.chan == awgn_channel)) ++ awgn_chandef = &ctx->conf.def; + } + mutex_unlock(&local->chanctx_mtx); + +- if (num_chanctx > 1) +- /* XXX: multi-channel is not supported yet */ +- WARN_ON_ONCE(1); +- else ++ if (num_chanctx > 1) { ++ if (local->hw.wiphy->flags & WIPHY_FLAG_SUPPORTS_MLO) { ++ if (WARN_ON(!awgn_chandef)) ++ return; ++ ++ cfg80211_awgn_event(local->hw.wiphy, awgn_chandef, ++ GFP_KERNEL, ++ interference_bitmap); ++ } else { ++ /* XXX: multi-channel is not supported yet */ ++ WARN_ON_ONCE(1); ++ } ++ } else { + cfg80211_awgn_event(local->hw.wiphy, &chandef, GFP_KERNEL, +- local->chan_bw_interference_bitmap); ++ interference_bitmap); ++ } ++} ++ ++void ieee80211_awgn_detected_work(struct work_struct *work) ++{ ++ struct ieee80211_local *local = ++ container_of(work, struct ieee80211_local, awgn_detected_work); ++ struct channel_awgn_info *awgn_info, *temp; ++ u32 chan_bw_interference_bitmap; ++ struct ieee80211_channel *awgn_channel; ++ ++ if (WARN_ON(list_empty(&local->awgn_info_list))) ++ return; ++ ++ list_for_each_entry_safe(awgn_info, temp, &local->awgn_info_list, list) { ++ chan_bw_interference_bitmap = awgn_info->chan_bw_interference_bitmap; ++ awgn_channel = awgn_info->awgn_channel; ++ ++ ieee80211_awgn_detected_processing(local, chan_bw_interference_bitmap, ++ awgn_channel); ++ ++ list_del(&awgn_info->list); ++ kfree(awgn_info); ++ } + } + + static void +@@ -4438,11 +4476,21 @@ void ieee80211_radar_detected_bitmap(str + } + EXPORT_SYMBOL(ieee80211_radar_detected_bitmap); + +-void ieee80211_awgn_detected(struct ieee80211_hw *hw, u32 chan_bw_interference_bitmap) ++void ieee80211_awgn_detected(struct ieee80211_hw *hw, u32 chan_bw_interference_bitmap, ++ struct ieee80211_channel *awgn_channel) + { + struct ieee80211_local *local = hw_to_local(hw); ++ struct channel_awgn_info *awgn_info; ++ ++ awgn_info = kzalloc(sizeof(*awgn_info), GFP_ATOMIC); ++ if (!awgn_info) ++ return; ++ ++ INIT_LIST_HEAD(&awgn_info->list); ++ awgn_info->chan_bw_interference_bitmap = chan_bw_interference_bitmap; ++ awgn_info->awgn_channel = awgn_channel; + +- local->chan_bw_interference_bitmap = chan_bw_interference_bitmap; ++ list_add_tail(&awgn_info->list, &local->awgn_info_list); + schedule_work(&local->awgn_detected_work); + } + EXPORT_SYMBOL(ieee80211_awgn_detected); +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -820,6 +820,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_ + ieee80211_dfs_radar_detected_work); + INIT_WORK(&local->awgn_detected_work, + ieee80211_awgn_detected_work); ++ INIT_LIST_HEAD(&local->awgn_info_list); + + INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter); + local->smps_mode = IEEE80211_SMPS_OFF; diff --git a/feeds/ipq95xx/mac80211/patches/qca/707-wifi-ath12k-add-link-id-support-in-wbm-error-path.patch b/feeds/ipq95xx/mac80211/patches/qca/707-wifi-ath12k-add-link-id-support-in-wbm-error-path.patch new file mode 100644 index 000000000..1ee503f1a --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/707-wifi-ath12k-add-link-id-support-in-wbm-error-path.patch @@ -0,0 +1,166 @@ +From 3626d9e220da44ce8e5a90151aa1454981ebbde7 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Thu, 12 Jan 2023 10:37:20 +0530 +Subject: [PATCH] wifi: ath12k: add link id support in wbm error path + +When more than one pdev supported in the chip/SoC, the Packet belong +to second pdev is given to first pdev due to not identify the mac id +in the wbm error path. So ping fails. + +In wbm error path, src link id information not available in the descriptor. +So we get this information from the msdu_end 64bit tag. It necessary to get +the src link id to identify the mac id in the given chip. Then only we can +pass the skb to the corresponding pdev. + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/dp_rx.c | 43 +++++++++++++---------- + drivers/net/wireless/ath/ath12k/hal.c | 7 ++++ + drivers/net/wireless/ath/ath12k/hal.h | 1 + + drivers/net/wireless/ath/ath12k/rx_desc.h | 4 +++ + 4 files changed, 37 insertions(+), 18 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -247,6 +247,16 @@ static inline u8 ath12k_dp_rx_h_msdu_end + return ab->hw_params->hal_ops->rx_desc_get_ip_valid(desc); + } + ++static inline u8 ath12k_dp_rx_get_msdu_src_link(struct ath12k_base *ab, ++ struct hal_rx_desc *desc) ++{ ++ /* If the ops unassigned, return the first pdev idx */ ++ if (!ab->hw_params->hal_ops->rx_desc_get_msdu_src_link_id) ++ return 0; ++ ++ return ab->hw_params->hal_ops->rx_desc_get_msdu_src_link_id(desc); ++} ++ + static void ath12k_dp_service_mon_ring(struct timer_list *t) + { + struct ath12k_base *ab = from_timer(ab, t, mon_reap_timer); +@@ -4446,17 +4456,17 @@ int ath12k_dp_rx_process_wbm_err(struct + struct hal_rx_wbm_rel_info err_info; + struct hal_srng *srng; + struct sk_buff *msdu; +- struct sk_buff_head msdu_list[MAX_RADIOS]; ++ struct sk_buff_head msdu_list; + struct ath12k_skb_rxcb *rxcb; + u32 *rx_desc; + int mac_id; + int num_buffs_reaped = 0; + int total_num_buffs_reaped = 0; + struct ath12k_rx_desc_info *desc_info; +- int ret, i; ++ int ret; ++ u8 src_link_id; + +- for (i = 0; i < ab->num_radios; i++) +- __skb_queue_head_init(&msdu_list[i]); ++ __skb_queue_head_init(&msdu_list); + + srng = &ab->hal.srng_list[dp->rx_rel_ring.ring_id]; + rx_ring = &dp->rx_refill_buf_ring; +@@ -4489,11 +4499,6 @@ int ath12k_dp_rx_process_wbm_err(struct + } + } + +- /* FIXME Extract mac id correctly. Since descs are not tied +- * to mac, we can extract from vdev id in ring desc. +- */ +- mac_id = 0; +- + if (desc_info->magic != ATH12K_DP_RX_DESC_MAGIC) + ath12k_warn(ab, "WBM RX err, Check HW CC implementation"); + +@@ -4524,7 +4529,8 @@ int ath12k_dp_rx_process_wbm_err(struct + rxcb->err_rel_src = err_info.err_rel_src; + rxcb->err_code = err_info.err_code; + rxcb->rx_desc = (struct hal_rx_desc *)msdu->data; +- __skb_queue_tail(&msdu_list[mac_id], msdu); ++ ++ __skb_queue_tail(&msdu_list, msdu); + + rxcb->is_first_msdu = err_info.first_msdu; + rxcb->is_last_msdu = err_info.last_msdu; +@@ -4542,21 +4548,26 @@ int ath12k_dp_rx_process_wbm_err(struct + ab->hw_params->hal_params->rx_buf_rbm, true); + + rcu_read_lock(); +- for (i = 0; i < ab->num_radios; i++) { +- if (!rcu_dereference(ab->pdevs_active[i])) { +- __skb_queue_purge(&msdu_list[i]); ++ while ((msdu = __skb_dequeue(&msdu_list)) != NULL) { ++ ++ src_link_id = ath12k_dp_rx_get_msdu_src_link(ab, msdu->data); ++ if (src_link_id < ATH12K_GROUP_MAX_RADIO) ++ ar = rcu_dereference(ab->ag->hw_links[src_link_id]); ++ else ++ ar = NULL; ++ ++ mac_id = ar ? ar->pdev_idx : 0; ++ if (!ar || !rcu_dereference(ar->ab->pdevs_active[mac_id])) { ++ dev_kfree_skb_any(msdu); + continue; + } + +- ar = ab->pdevs[i].ar; +- + if (test_bit(ATH12K_CAC_RUNNING, &ar->dev_flags)) { +- __skb_queue_purge(&msdu_list[i]); ++ dev_kfree_skb_any(msdu); + continue; + } + +- while ((msdu = __skb_dequeue(&msdu_list[i])) != NULL) +- ath12k_dp_rx_wbm_err(ar, napi, msdu, &msdu_list[i]); ++ ath12k_dp_rx_wbm_err(ar, napi, msdu, &msdu_list); + } + rcu_read_unlock(); + done: +--- a/drivers/net/wireless/ath/ath12k/hal.c ++++ b/drivers/net/wireless/ath/ath12k/hal.c +@@ -495,6 +495,12 @@ static inline u32 ath12k_hal_rx_msdu_end + return MSDU_END_WMASK; + } + ++static u8 ath12k_hw_qcn9274_rx_desc_get_msdu_src_link(struct hal_rx_desc *desc) ++{ ++ return le64_get_bits(desc->u.qcn9274.msdu_end.msdu_end_tag, ++ RX_MSDU_END_64_TLV_SRC_LINK_ID); ++} ++ + static int ath12k_hal_srng_create_config_qcn9274(struct ath12k_base *ab) + { + struct ath12k_hal *hal = &ab->hal; +@@ -700,6 +706,7 @@ const struct hal_ops hal_qcn9274_ops = { + .rx_desc_get_ip_valid = ath12k_hal_qcn9274_rx_desc_get_ip_valid, + .rxdma_ring_wmask_rx_mpdu_start = ath12k_hal_rx_mpdu_start_wmask_get, + .rxdma_ring_wmask_rx_msdu_end = ath12k_hal_rx_msdu_end_wmask_get, ++ .rx_desc_get_msdu_src_link_id = ath12k_hw_qcn9274_rx_desc_get_msdu_src_link, + }; + + static bool ath12k_hw_wcn7850_rx_desc_get_first_msdu(struct hal_rx_desc *desc) +--- a/drivers/net/wireless/ath/ath12k/hal.h ++++ b/drivers/net/wireless/ath/ath12k/hal.h +@@ -1104,6 +1104,7 @@ struct hal_ops { + const struct ath12k_hal_tcl_to_wbm_rbm_map *tcl_to_wbm_rbm_map; + u16 (*rxdma_ring_wmask_rx_mpdu_start)(void); + u32 (*rxdma_ring_wmask_rx_msdu_end)(void); ++ u8 (*rx_desc_get_msdu_src_link_id)(struct hal_rx_desc *desc); + }; + + extern const struct hal_ops hal_qcn9274_ops; +--- a/drivers/net/wireless/ath/ath12k/rx_desc.h ++++ b/drivers/net/wireless/ath/ath12k/rx_desc.h +@@ -634,6 +634,10 @@ enum rx_msdu_start_reception_type { + RX_MSDU_START_RECEPTION_TYPE_UL_MU_OFDMA_MIMO, + }; + ++#define RX_MSDU_END_64_TLV_TAG GENMASK(9, 1) ++#define RX_MSDU_END_64_TLV_LEN GENMASK(21, 10) ++#define RX_MSDU_END_64_TLV_SRC_LINK_ID GENMASK(24, 22) ++ + #define RX_MSDU_END_INFO0_RXPCU_MPDU_FITLER GENMASK(1, 0) + #define RX_MSDU_END_INFO0_SW_FRAME_GRP_ID GENMASK(8, 2) + diff --git a/feeds/ipq95xx/mac80211/patches/qca/708-ath12k-Add-support-to-set-tx-power-for-6G-via-iw.patch b/feeds/ipq95xx/mac80211/patches/qca/708-ath12k-Add-support-to-set-tx-power-for-6G-via-iw.patch new file mode 100644 index 000000000..53a16dfb1 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/708-ath12k-Add-support-to-set-tx-power-for-6G-via-iw.patch @@ -0,0 +1,78 @@ +From 54785cbf10629fa719fdeb7e8926041690a467ca Mon Sep 17 00:00:00 2001 +From: Thiraviyam Mariyappan +Date: Tue, 7 Feb 2023 09:52:10 +0530 +Subject: [PATCH] ath12k: Add support to set tx power for 6G via iw + +Add support to set the tx power for 6G radio with the wmi +pdev param WMI_PDEV_PARAM_TXPOWER_LIMIT5G via iw command. +iw dev wlanX set txpower fixed 1000 +TEST=With the above iw command and verified the tx power +value in the iw dev for 6G radio is set by the configured +value. + +Signed-off-by: Thiraviyam Mariyappan +Signed-off-by: Maharaja Kennadyrajan +--- + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/mac.c | 29 ++++++++++++-------------- + 2 files changed, 14 insertions(+), 16 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -771,6 +771,7 @@ struct ath12k { + u32 max_tx_power; + u32 txpower_limit_2g; + u32 txpower_limit_5g; ++ u32 txpower_limit_6g; + u32 txpower_scale; + u32 power_scale; + u32 chan_tx_pwr; +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -853,6 +853,7 @@ static void ath12k_pdev_caps_update(stru + + ar->txpower_limit_2g = ar->max_tx_power; + ar->txpower_limit_5g = ar->max_tx_power; ++ ar->txpower_limit_6g = ar->max_tx_power; + ar->txpower_scale = WMI_HOST_TP_SCALE_MAX; + } + +@@ -905,6 +906,16 @@ static int ath12k_mac_txpower_recalc(str + ar->txpower_limit_5g = txpower; + } + ++ if ((ar->ah->hw->wiphy->bands[NL80211_BAND_6GHZ]) && ++ ar->txpower_limit_6g != txpower) { ++ param = WMI_PDEV_PARAM_TXPOWER_LIMIT5G; ++ ret = ath12k_wmi_pdev_set_param(ar, param, ++ txpower, ar->pdev->pdev_id); ++ if (ret) ++ goto fail; ++ ar->txpower_limit_6g = txpower; ++ } ++ + return 0; + + fail: +@@ -4311,19 +4322,8 @@ static void ath12k_mac_bss_info_changed( + if (changed & BSS_CHANGED_TXPOWER) { + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev_id %i txpower %d\n", + arvif->vdev_id, info->txpower); +- +- if (ar->supports_6ghz && info->chandef.chan && +- info->chandef.chan->band == NL80211_BAND_6GHZ && +- (ahvif->vdev_type == WMI_VDEV_TYPE_STA || +- ahvif->vdev_type == WMI_VDEV_TYPE_AP) && +- test_bit(WMI_TLV_SERVICE_EXT_TPC_REG_SUPPORT, +- ar->ab->wmi_ab.svc_map)) { +- ath12k_dbg(ar->ab, ATH12K_DBG_MAC, +- "discard tx power, change to set TPC power\n"); +- } else { +- arvif->txpower = info->txpower; +- ath12k_mac_txpower_recalc(ar); +- } ++ arvif->txpower = info->txpower; ++ ath12k_mac_txpower_recalc(ar); + } + + if (changed & BSS_CHANGED_MCAST_RATE && diff --git a/feeds/ipq95xx/mac80211/patches/qca/708-ath12k-Fix-unbalance-mutex-lock-in-mac-ops.patch b/feeds/ipq95xx/mac80211/patches/qca/708-ath12k-Fix-unbalance-mutex-lock-in-mac-ops.patch new file mode 100644 index 000000000..8eb48767a --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/708-ath12k-Fix-unbalance-mutex-lock-in-mac-ops.patch @@ -0,0 +1,81 @@ +From 660f90db8c809a3ddc985f576effd37319612947 Mon Sep 17 00:00:00 2001 +From: Manish Dharanenthiran +Date: Thu, 19 Jan 2023 15:42:36 +0530 +Subject: [PATCH] ath12k: Fix unbalance mutex lock in mac ops + +Mutex lock/unlock is unbalanced in multipe +driver mac ops handlers during error cases. + +Fix this by adding proper mutex lock/unlock +statement. + +Signed-off-by: Manish Dharanenthiran +--- + drivers/net/wireless/ath/ath12k/mac.c | 23 +++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index 78e831f..1f5a381 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -6616,7 +6616,7 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, + ret = ath12k_mac_assign_link_sta(ah, ahsta, &ahsta->deflink, + ahvif, link_id); + if (ret) +- return ret; ++ goto exit; + } + } + +@@ -6624,8 +6624,10 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, + arvif = ahvif->link[link_id]; + arsta = ahsta->link[link_id]; + +- if (WARN_ON(arvif == NULL || arsta == NULL)) +- return -EINVAL; ++ if (WARN_ON(arvif == NULL || arsta == NULL)) { ++ ret = -EINVAL; ++ goto exit; ++ } + + ret = ath12k_mac_handle_link_sta_state(hw, arvif, arsta, + old_state, new_state); +@@ -6634,8 +6636,10 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, + } + + /* Support only AP for now */ +- if (vif->type != NL80211_IFTYPE_AP) +- return -EINVAL; ++ if (vif->type != NL80211_IFTYPE_AP) { ++ ret = -EINVAL; ++ goto exit; ++ } + + if (!sta->valid_links) + WARN_ON(1); +@@ -12511,7 +12515,8 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, + num_rates != 1) { + ath12k_warn(ar->ab, + "Setting HE UL MCS Fixed Rate range is not supported\n"); +- return -EINVAL; ++ ret = -EINVAL; ++ goto out; + } + + /* mac80211 doesn't support sending a fixed HT/VHT MCS alone, rather it +@@ -12546,8 +12551,10 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, + } else { + rate = WMI_FIXED_RATE_NONE; + +- if (!ath12k_mac_check_fixed_rate_settings_for_mumimo(arvif, vht_mcs_mask, he_mcs_mask)) +- return -EINVAL; ++ if (!ath12k_mac_check_fixed_rate_settings_for_mumimo(arvif, vht_mcs_mask, he_mcs_mask)) { ++ ret = -EINVAL; ++ goto out; ++ } + + if (!ath12k_mac_validate_fixed_rate_settings(ar, band, mask)) + ath12k_warn(ar->ab, +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/708-ath12k-fix-memory-leak-in-dp-rx.patch b/feeds/ipq95xx/mac80211/patches/qca/708-ath12k-fix-memory-leak-in-dp-rx.patch new file mode 100644 index 000000000..8c2faeb6c --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/708-ath12k-fix-memory-leak-in-dp-rx.patch @@ -0,0 +1,52 @@ +From 3dc80c963eeb4c7cc1aaa0dd3ddfc01d5fe96ab1 Mon Sep 17 00:00:00 2001 +From: Hari Chandrakanthan +Date: Thu, 19 Jan 2023 19:17:08 +0530 +Subject: [PATCH] ath12k: fix memory leak in dp rx + +In dp rx path, by default, fast_rx is set as true. +And if peer supports fast rx, the frame is sent to upper layer +through netif_receive_skb. + +If peer doesn't support fast rx, the frames need to be processed in +ath12k_dp_rx_deliver_msdu and sent to mac80211 using ieee80211_rx_napi. +In dp rx path, the api ath12k_dp_rx_h_mpdu checks whether peer supports +fast rx. + +If peer find fails in ath12k_dp_rx_h_mpdu, the skb is not sent to network stack +as well as mac80211. Because the argument fast_rx is not set to false in ath12k_dp_rx_h_mpdu +when peer find fails. + +This can lead to memory leak. + +Fix it by setting argument fast_rx as false in ath12k_dp_rx_h_mpdu +so that the skb is sent to mac80211 through ath12k_dp_rx_deliver_msdu. + +Signed-off-by: Hari Chandrakanthan +--- + drivers/net/wireless/ath/ath12k/dp_rx.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c +index 2806779..1644d07 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -2698,7 +2698,6 @@ static void ath12k_dp_rx_h_mpdu(struct ath12k *ar, + return; + } + } +- *fast_rx = false; + if (rxcb->is_mcbc) + enctype = peer->sec_type_grp; + else +@@ -2708,6 +2707,8 @@ static void ath12k_dp_rx_h_mpdu(struct ath12k *ar, + } + spin_unlock_bh(&ar->ab->base_lock); + ++ *fast_rx = false; ++ + err_bitmap = ath12k_dp_rx_h_mpdu_err(ab, rx_desc); + if (enctype != HAL_ENCRYPT_TYPE_OPEN && !err_bitmap) + is_decrypted = ath12k_dp_rx_h_is_decrypted(ab, rx_desc); +-- +2.7.4 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/708-nl80211-add-agile-DFS-support-for-MLO.patch b/feeds/ipq95xx/mac80211/patches/qca/708-nl80211-add-agile-DFS-support-for-MLO.patch new file mode 100644 index 000000000..3b619fb17 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/708-nl80211-add-agile-DFS-support-for-MLO.patch @@ -0,0 +1,81 @@ +From 300aaecb1583139cbd5b727fe01729f8bccfc3af Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Tue, 24 Jan 2023 11:57:23 +0530 +Subject: [PATCH] nl80211: add agile DFS support for MLO + +Currently, background cac start and stop related command only +supported for non MLO case, while for MLO command throws below error. + +command failed: Invalid argument (-22) + +Add changes to support background cac command for MLO vaps by parsing +link id. Also added changes to validate link band information so that +bgcac should be triggered only for 5G. + +Signed-off-by: Aaradhana Sahu +--- + net/wireless/nl80211.c | 30 ++++++++++++++++++++++++++++-- + 1 file changed, 28 insertions(+), 2 deletions(-) + +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -10424,7 +10424,7 @@ static int nl80211_start_radar_detection + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct wiphy *wiphy = wdev->wiphy; + int link_id = nl80211_link_id(info->attrs); +- struct cfg80211_chan_def chandef; ++ struct cfg80211_chan_def chandef, *chandef_link; + enum nl80211_dfs_regions dfs_region; + unsigned int cac_time_ms; + int err = -EINVAL; +@@ -10442,6 +10442,19 @@ static int nl80211_start_radar_detection + if (err) + goto unlock; + ++ chandef_link = wdev_chandef(wdev, link_id); ++ if (!chandef_link) { ++ err = -EINVAL; ++ goto unlock; ++ } ++ ++ if (chandef_link->chan) { ++ if (chandef_link->chan->band != chandef.chan->band) { ++ err = -EINVAL; ++ goto unlock; ++ } ++ } ++ + err = cfg80211_chandef_dfs_required(wiphy, &chandef, wdev->iftype); + if (err < 0) + goto unlock; +@@ -10509,6 +10522,21 @@ static int nl80211_stop_radar_detection( + { + struct net_device *dev = info->user_ptr[1]; + struct wireless_dev *wdev = dev->ieee80211_ptr; ++ struct cfg80211_registered_device *rdev = info->user_ptr[0]; ++ int link_id = nl80211_link_id(info->attrs); ++ struct cfg80211_chan_def *chandef_link, *chandef; ++ ++ if (!rdev->background_radar_wdev) ++ return -EINVAL; ++ ++ chandef = &rdev->background_radar_chandef; ++ chandef_link = wdev_chandef(wdev, link_id); ++ ++ if (!chandef_link) ++ return -EINVAL; ++ ++ if (chandef_link->chan->band != chandef->chan->band) ++ return -EINVAL; + + cfg80211_stop_background_radar_detection(wdev); + +@@ -17969,7 +17997,7 @@ static const struct genl_small_ops nl802 + .flags = GENL_UNS_ADMIN_PERM, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_NO_WIPHY_MTX | +- NL80211_FLAG_MLO_UNSUPPORTED), ++ NL80211_FLAG_MLO_VALID_LINK_ID), + }, + }; + diff --git a/feeds/ipq95xx/mac80211/patches/qca/708-wifi-ath12k-add-proper-link-stats-support.patch b/feeds/ipq95xx/mac80211/patches/qca/708-wifi-ath12k-add-proper-link-stats-support.patch new file mode 100644 index 000000000..551665674 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/708-wifi-ath12k-add-proper-link-stats-support.patch @@ -0,0 +1,286 @@ +From 5fb36a3a19a56956c397b2123c4f5747f20c48c1 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Mon, 16 Jan 2023 04:13:41 +0530 +Subject: [PATCH] wifi: ath12k: add proper link stats support + +Get proper link id if the peer is ML. Fetch the arsta from the proper link +id and update the statistics in the corresponding arsta instead of always +default link. + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/core.h | 2 ++ + drivers/net/wireless/ath/ath12k/debugfs.c | 3 +++ + drivers/net/wireless/ath/ath12k/dp_mon.c | 17 ++++++++++++++--- + drivers/net/wireless/ath/ath12k/dp_rx.c | 12 ++++++++++-- + drivers/net/wireless/ath/ath12k/dp_tx.c | 11 +++++++++-- + drivers/net/wireless/ath/ath12k/peer.c | 2 -- + 6 files changed, 38 insertions(+), 9 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/dp_mon.c ++++ b/drivers/net/wireless/ath/ath12k/dp_mon.c +@@ -3484,7 +3484,6 @@ ath12k_dp_mon_rx_update_user_stats(struc + struct hal_rx_mon_ppdu_info *ppdu_info, + u32 uid) + { +- struct ath12k_sta *ahsta = NULL; + struct ath12k_link_sta *arsta; + struct ath12k_rx_peer_stats *rx_stats = NULL; + struct hal_rx_user_status *user_stats = &ppdu_info->userstats[uid]; +@@ -3502,10 +3501,14 @@ ath12k_dp_mon_rx_update_user_stats(struc + return; + } + +- ahsta = (struct ath12k_sta *)peer->sta->drv_priv; +- arsta = &ahsta->deflink; +- rx_stats = arsta->rx_stats; ++ arsta = ath12k_peer_get_link_sta(ar->ab, peer); ++ if (!arsta) { ++ ath12k_warn(ar->ab, "link sta not found on peer %pM id %d\n", ++ peer->addr, peer->peer_id); ++ return; ++ } + ++ rx_stats = arsta->rx_stats; + if (!rx_stats) + return; + +@@ -3632,7 +3635,7 @@ int ath12k_dp_mon_srng_process(struct at + struct hal_rx_mon_ppdu_info *ppdu_info = &pmon->mon_ppdu_info; + struct sk_buff_head skb_list; + struct ath12k_peer *peer = NULL; +- struct ath12k_sta *ahsta = NULL; ++ struct ath12k_link_sta *arsta; + u64 cookie; + u32 hal_status, end_reason, ppdu_id, end_offset; + int num_buffs_reaped = 0, srng_id, buf_id; +@@ -3754,8 +3757,14 @@ move_next: + } + + if (ppdu_info->reception_type == HAL_RX_RECEPTION_TYPE_SU) { +- ahsta = (struct ath12k_sta *)peer->sta->drv_priv; +- ath12k_dp_mon_rx_update_peer_su_stats(ar, &ahsta->deflink, ++ arsta = ath12k_peer_get_link_sta(ar->ab, peer); ++ if (!arsta) { ++ ath12k_warn(ar->ab, "link sta not found on peer %pM id %d\n", ++ peer->addr, peer->peer_id); ++ goto next_skb; ++ } ++ ++ ath12k_dp_mon_rx_update_peer_su_stats(ar, arsta, + ppdu_info); + } else if ((ppdu_info->fc_valid) && + (ppdu_info->ast_index != HAL_AST_IDX_INVALID)) { +@@ -3789,7 +3798,7 @@ int ath12k_dp_mon_rx_process_stats(struc + struct dp_srng *mon_dst_ring; + struct hal_srng *srng; + struct dp_rxdma_ring *buf_ring; +- struct ath12k_sta *ahsta = NULL; ++ struct ath12k_link_sta *arsta = NULL; + struct ath12k_peer *peer; + struct sk_buff_head skb_list; + u64 cookie; +@@ -3911,9 +3920,14 @@ move_next: + } + + if (ppdu_info->reception_type == HAL_RX_RECEPTION_TYPE_SU) { +- ahsta = (struct ath12k_sta *)peer->sta->drv_priv; +- /* TODO Extend for Link STA */ +- ath12k_dp_mon_rx_update_peer_su_stats(ar, &ahsta->deflink, ++ arsta = ath12k_peer_get_link_sta(ar->ab, peer); ++ if (!arsta) { ++ ath12k_warn(ab, "link sta not found on peer %pM id %d\n", ++ peer->addr, peer->peer_id); ++ goto next_skb; ++ } ++ ++ ath12k_dp_mon_rx_update_peer_su_stats(ar, arsta, + ppdu_info); + } else if ((ppdu_info->fc_valid) && + (ppdu_info->ast_index != HAL_AST_IDX_INVALID)) { +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -1480,7 +1480,6 @@ ath12k_update_per_peer_tx_stats(struct a + struct ath12k_base *ab = ar->ab; + struct ath12k_peer *peer; + struct ieee80211_sta *sta; +- struct ath12k_sta *ahsta; + struct ath12k_link_sta *arsta; + struct htt_ppdu_stats_user_rate *user_rate; + struct htt_ppdu_stats *ppdu_stats = &ppdu_info->ppdu_stats; +@@ -1608,8 +1607,12 @@ ath12k_update_per_peer_tx_stats(struct a + } + + sta = peer->sta; +- ahsta = (struct ath12k_sta *)sta->drv_priv; +- arsta = &ahsta->deflink; ++ arsta = ath12k_peer_get_link_sta(ab, peer); ++ if (!arsta) { ++ spin_unlock_bh(&ab->base_lock); ++ rcu_read_unlock(); ++ return; ++ } + + memset(&arsta->txrate, 0, sizeof(arsta->txrate)); + +@@ -2925,7 +2928,6 @@ static void ath12k_dp_rx_deliver_msdu(st + bool is_mcbc = rxcb->is_mcbc; + bool is_eapol = rxcb->is_eapol; + struct ath12k_link_sta *arsta = NULL; +- struct ath12k_sta *ahsta = NULL; + + if (status->encoding == RX_ENC_HE && !(status->flag & RX_FLAG_RADIOTAP_HE) && + !(status->flag & RX_FLAG_SKIP_MONITOR)) { +@@ -3002,10 +3004,8 @@ exit: + if (ath12k_debugfs_is_extd_rx_stats_enabled(ar)) { + if (!(status->flag & RX_FLAG_ONLY_MONITOR)) { + spin_lock_bh(&ar->ab->base_lock); +- if (peer && peer->sta) { +- ahsta = (struct ath12k_sta *)peer->sta->drv_priv; +- arsta = &ahsta->deflink; +- } ++ if (peer && peer->sta) ++ arsta = ath12k_peer_get_link_sta(ar->ab, peer); + spin_unlock_bh(&ar->ab->base_lock); + if (arsta) + atomic_inc(&arsta->drv_rx_pkts.pkts_out); +@@ -3208,7 +3208,6 @@ int ath12k_dp_rx_process(struct ath12k_b + bool done = false; + u32 *rx_desc; + u64 desc_va; +- struct ath12k_sta *ahsta = NULL; + struct ath12k_link_sta *arsta = NULL; + struct ath12k_peer *peer = NULL; + struct ath12k *ar; +@@ -3311,10 +3310,8 @@ try_again: + rcu_read_lock(); + spin_lock_bh(&src_ab->base_lock); + peer = ath12k_peer_find_by_id(src_ab, rxcb->peer_id); +- if (peer && peer->sta) { +- ahsta = (struct ath12k_sta *)peer->sta->drv_priv; +- arsta = &ahsta->deflink; +- } ++ if (peer && peer->sta) ++ arsta = ath12k_peer_get_link_sta(src_ab, peer); + spin_unlock_bh(&src_ab->base_lock); + if (arsta) + atomic_inc(&arsta->drv_rx_pkts.pkts_frm_hw); +@@ -4186,7 +4183,6 @@ static int ath12k_dp_rx_h_null_q_desc(st + struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu); + u32 hal_rx_desc_sz = ar->ab->hw_params->hal_desc_sz; + bool fast_rx; +- struct ath12k_sta *ahsta = NULL; + struct ath12k_link_sta *arsta = NULL; + struct ath12k_peer *peer = NULL; + +@@ -4252,10 +4248,8 @@ static int ath12k_dp_rx_h_null_q_desc(st + spin_lock_bh(&ar->ab->base_lock); + if (peer_id) + peer = ath12k_peer_find_by_id(ar->ab, rxcb->peer_id); +- if (peer && peer->sta) { +- ahsta = (struct ath12k_sta *)peer->sta->drv_priv; +- arsta = &ahsta->deflink; +- } ++ if (peer && peer->sta) ++ arsta = ath12k_peer_get_link_sta(ar->ab, peer); + spin_unlock_bh(&ar->ab->base_lock); + if (arsta) + atomic_inc(&arsta->drv_rx_pkts.pkts_frm_hw); +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -526,9 +526,7 @@ void ath12k_dp_tx_update_txcompl(struct + enum hal_tx_rate_stats_sgi sgi; + enum hal_tx_rate_stats_bw bw; + struct ath12k_peer *peer; +- struct ath12k_sta *ahsta; + struct ath12k_link_sta *arsta; +- struct ieee80211_sta *sta; + u16 rate, ru_tones; + u8 mcs, rate_idx, ofdma; + int ret; +@@ -541,10 +539,12 @@ void ath12k_dp_tx_update_txcompl(struct + goto err_out; + } + +- /* TODO move to per link stats */ +- sta = peer->sta; +- ahsta = (struct ath12k_sta *)sta->drv_priv; +- arsta = &ahsta->deflink; ++ arsta = ath12k_peer_get_link_sta(ab, peer); ++ if (!arsta) { ++ ath12k_warn(ab, "link sta not found on peer %pM id %d\n", ++ peer->addr, peer->peer_id); ++ goto err_out; ++ } + + memset(&arsta->txrate, 0, sizeof(arsta->txrate)); + pkt_type = FIELD_GET(HAL_TX_RATE_STATS_INFO0_PKT_TYPE, +@@ -670,7 +670,6 @@ static void ath12k_dp_tx_complete_msdu(s + struct ieee80211_tx_info *info; + struct ath12k_skb_cb *skb_cb; + struct ath12k_peer *peer; +- struct ath12k_sta *ahsta; + struct ath12k_link_sta *arsta; + struct rate_info rate; + struct hal_tx_status ts = { 0 }; +@@ -786,8 +785,16 @@ static void ath12k_dp_tx_complete_msdu(s + return; + } + +- ahsta = (struct ath12k_sta *)peer->sta->drv_priv; +- arsta = &ahsta->deflink; ++ arsta = ath12k_peer_get_link_sta(ab, peer); ++ if (!arsta) { ++ ath12k_warn(ab, "link sta not found on peer %pM id %d\n", ++ peer->addr, peer->peer_id); ++ ++ spin_unlock_bh(&ab->base_lock); ++ dev_kfree_skb_any(msdu); ++ return; ++ } ++ + status.sta = peer->sta; + status.skb = msdu; + status.info = info; +--- a/drivers/net/wireless/ath/ath12k/peer.c ++++ b/drivers/net/wireless/ath/ath12k/peer.c +@@ -511,10 +511,8 @@ int ath12k_peer_create(struct ath12k *ar + peer->primary_link = true; + peer->mlo = false; + } +- + } + +- + ar->num_peers++; + + spin_unlock_bh(&ar->ab->base_lock); +--- a/drivers/net/wireless/ath/ath12k/peer.h ++++ b/drivers/net/wireless/ath/ath12k/peer.h +@@ -100,4 +100,26 @@ struct ath12k_peer *ath12k_peer_find_by_ + void ath12k_peer_mlo_map_event(struct ath12k_base *ab, struct sk_buff *skb); + void ath12k_peer_mlo_unmap_event(struct ath12k_base *ab, struct sk_buff *skb); + ++static inline ++struct ath12k_link_sta *ath12k_peer_get_link_sta(struct ath12k_base *ab, ++ struct ath12k_peer *peer) ++{ ++ struct ath12k_sta *ahsta; ++ ++ if (!peer->sta) ++ return NULL; ++ ++ ahsta = (struct ath12k_sta *)peer->sta->drv_priv; ++ if (peer->ml_peer_id & ATH12K_ML_PEER_ID_VALID) { ++ if (!(ahsta->links_map & BIT(peer->link_id))) { ++ ath12k_warn(ab, "peer %pM id %d link_id %d can't found in STA link_map 0x%x\n", ++ peer->addr, peer->peer_id, peer->link_id, ahsta->links_map); ++ return NULL; ++ } ++ ++ return ahsta->link[peer->link_id]; ++ } else { ++ return &ahsta->deflink; ++ } ++} + #endif /* _PEER_H_ */ diff --git a/feeds/ipq95xx/mac80211/patches/qca/709-UPSTREAM-mac80211-fix-init-rx-link-and-rx-link-sta.patch b/feeds/ipq95xx/mac80211/patches/qca/709-UPSTREAM-mac80211-fix-init-rx-link-and-rx-link-sta.patch new file mode 100644 index 000000000..c9f9708ac --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/709-UPSTREAM-mac80211-fix-init-rx-link-and-rx-link-sta.patch @@ -0,0 +1,438 @@ +From e66b7920aa5ac5b1a1997a454004ba9246a3c005 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Fri, 30 Dec 2022 21:07:47 +0100 +Subject: [PATCH] wifi: mac80211: fix initialization of rx->link and + rx->link_sta + +There are some codepaths that do not initialize rx->link_sta properly. This +causes a crash in places which assume that rx->link_sta is valid if rx->sta +is valid. +One known instance is triggered by __ieee80211_rx_h_amsdu being called from +fast-rx. It results in a crash like this one: + + BUG: kernel NULL pointer dereference, address: 00000000000000a8 + #PF: supervisor write access in kernel mode + #PF: error_code(0x0002) - not-present page PGD 0 P4D 0 + Oops: 0002 [#1] PREEMPT SMP PTI + CPU: 1 PID: 506 Comm: mt76-usb-rx phy Tainted: G E 6.1.0-debian64x+1.7 #3 + Hardware name: ZOTAC ZBOX-ID92/ZBOX-IQ01/ZBOX-ID92/ZBOX-IQ01, BIOS B220P007 05/21/2014 + RIP: 0010:ieee80211_deliver_skb+0x62/0x1f0 [mac80211] + Code: 00 48 89 04 24 e8 9e a7 c3 df 89 c0 48 03 1c c5 a0 ea 39 a1 4c 01 6b 08 48 ff 03 48 + 83 7d 28 00 74 11 48 8b 45 30 48 63 55 44 <48> 83 84 d0 a8 00 00 00 01 41 8b 86 c0 + 11 00 00 8d 50 fd 83 fa 01 + RSP: 0018:ffff999040803b10 EFLAGS: 00010286 + RAX: 0000000000000000 RBX: ffffb9903f496480 RCX: 0000000000000000 + RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000 + RBP: ffff999040803ce0 R08: 0000000000000000 R09: 0000000000000000 + R10: 0000000000000000 R11: 0000000000000000 R12: ffff8d21828ac900 + R13: 000000000000004a R14: ffff8d2198ed89c0 R15: ffff8d2198ed8000 + FS: 0000000000000000(0000) GS:ffff8d24afe80000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00000000000000a8 CR3: 0000000429810002 CR4: 00000000001706e0 + Call Trace: + + __ieee80211_rx_h_amsdu+0x1b5/0x240 [mac80211] + ? ieee80211_prepare_and_rx_handle+0xcdd/0x1320 [mac80211] + ? __local_bh_enable_ip+0x3b/0xa0 + ieee80211_prepare_and_rx_handle+0xcdd/0x1320 [mac80211] + ? prepare_transfer+0x109/0x1a0 [xhci_hcd] + ieee80211_rx_list+0xa80/0xda0 [mac80211] + mt76_rx_complete+0x207/0x2e0 [mt76] + mt76_rx_poll_complete+0x357/0x5a0 [mt76] + mt76u_rx_worker+0x4f5/0x600 [mt76_usb] + ? mt76_get_min_avg_rssi+0x140/0x140 [mt76] + __mt76_worker_fn+0x50/0x80 [mt76] + kthread+0xed/0x120 + ? kthread_complete_and_exit+0x20/0x20 + ret_from_fork+0x22/0x30 + +Since the initialization of rx->link and rx->link_sta is rather convoluted +and duplicated in many places, clean it up by using a helper function to +set it. + +Fixes: ccdde7c74ffd ("wifi: mac80211: properly implement MLO key handling") +Fixes: b320d6c456ff ("wifi: mac80211: use correct rx link_sta instead of default") +Signed-off-by: Felix Fietkau +Link: https://lore.kernel.org/r/20221230200747.19040-1-nbd@nbd.name +[remove unnecessary rx->sta->sta.mlo check] +Cc: stable@vger.kernel.org +Signed-off-by: Johannes Berg +--- + net/mac80211/rx.c | 222 +++++++++++++++++++++------------------------- + 1 file changed, 99 insertions(+), 123 deletions(-) + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -4266,6 +4266,55 @@ static void ieee80211_invoke_rx_handlers + #undef CALL_RXH + } + ++static bool ++ieee80211_rx_is_valid_sta_link_id(struct ieee80211_sta *sta, u8 link_id) ++{ ++ return !!(sta->valid_links & BIT(link_id)); ++} ++ ++static bool ieee80211_rx_data_set_link(struct ieee80211_rx_data *rx, ++ u8 link_id) ++{ ++ rx->link_id = link_id; ++ rx->link = rcu_dereference(rx->sdata->link[link_id]); ++ ++ if (!rx->sta) ++ return rx->link; ++ ++ if (!ieee80211_rx_is_valid_sta_link_id(&rx->sta->sta, link_id)) ++ return false; ++ ++ rx->link_sta = rcu_dereference(rx->sta->link[link_id]); ++ ++ return rx->link && rx->link_sta; ++} ++ ++static bool ieee80211_rx_data_set_sta(struct ieee80211_rx_data *rx, ++ struct ieee80211_sta *pubsta, ++ int link_id) ++{ ++ struct sta_info *sta; ++ ++ sta = container_of(pubsta, struct sta_info, sta); ++ ++ rx->link_id = link_id; ++ rx->sta = sta; ++ ++ if (sta) { ++ rx->local = sta->sdata->local; ++ if (!rx->sdata) ++ rx->sdata = sta->sdata; ++ rx->link_sta = &sta->deflink; ++ } ++ ++ if (link_id < 0) ++ rx->link = &rx->sdata->deflink; ++ else if (!ieee80211_rx_data_set_link(rx, link_id)) ++ return false; ++ ++ return true; ++} ++ + /* + * This function makes calls into the RX path, therefore + * it has to be invoked under RCU read lock. +@@ -4274,15 +4323,19 @@ void ieee80211_release_reorder_timeout(s + { + struct sk_buff_head frames; + struct ieee80211_rx_data rx = { +- .sta = sta, +- .sdata = sta->sdata, +- .local = sta->local, + /* This is OK -- must be QoS data frame */ + .security_idx = tid, + .seqno_idx = tid, +- .link_id = -1, + }; + struct tid_ampdu_rx *tid_agg_rx; ++ int link_id = -1; ++ ++ /* FIXME: statistics won't be right with this */ ++ if (sta->sta.valid_links) ++ link_id = ffs(sta->sta.valid_links) - 1; ++ ++ if (!ieee80211_rx_data_set_sta(&rx, &sta->sta, link_id)) ++ return; + + tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]); + if (!tid_agg_rx) +@@ -4317,7 +4370,6 @@ void ieee80211_mark_rx_ba_filtered_frame + /* This is OK -- must be QoS data frame */ + .security_idx = tid, + .seqno_idx = tid, +- .link_id = -1, + }; + int i, diff; + +@@ -4328,10 +4380,8 @@ void ieee80211_mark_rx_ba_filtered_frame + + sta = container_of(pubsta, struct sta_info, sta); + +- rx.sta = sta; +- rx.sdata = sta->sdata; +- rx.link = &rx.sdata->deflink; +- rx.local = sta->local; ++ if (!ieee80211_rx_data_set_sta(&rx, pubsta, -1)) ++ return; + + rcu_read_lock(); + tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]); +@@ -4728,15 +4778,6 @@ void ieee80211_check_fast_rx_iface(struc + mutex_unlock(&local->sta_mtx); + } + +-static bool +-ieee80211_rx_is_valid_sta_link_id(struct ieee80211_sta *sta, u8 link_id) +-{ +- if (!sta->mlo) +- return false; +- +- return !!(sta->valid_links & BIT(link_id)); +-} +- + static void ieee80211_rx_8023(struct ieee80211_rx_data *rx, + struct ieee80211_fast_rx *fast_rx, + int orig_len) +@@ -4855,7 +4896,6 @@ static bool ieee80211_invoke_fast_rx(str + struct sk_buff *skb = rx->skb; + struct ieee80211_hdr *hdr = (void *)skb->data; + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); +- struct sta_info *sta = rx->sta; + int orig_len = skb->len; + int hdrlen = ieee80211_hdrlen(hdr->frame_control); + int snap_offs = hdrlen; +@@ -4867,7 +4907,6 @@ static bool ieee80211_invoke_fast_rx(str + u8 da[ETH_ALEN]; + u8 sa[ETH_ALEN]; + } addrs __aligned(2); +- struct link_sta_info *link_sta; + struct ieee80211_sta_rx_stats *stats; + struct ieee80211s_hdr *mesh_hdr; + struct mesh_path *mppath; +@@ -5029,18 +5068,10 @@ static bool ieee80211_invoke_fast_rx(str + drop: + dev_kfree_skb(skb); + +- if (rx->link_id >= 0) { +- link_sta = rcu_dereference(sta->link[rx->link_id]); +- if (!link_sta) +- return true; +- } else { +- link_sta = &sta->deflink; +- } +- + if (fast_rx->uses_rss) +- stats = this_cpu_ptr(link_sta->pcpu_rx_stats); ++ stats = this_cpu_ptr(rx->link_sta->pcpu_rx_stats); + else +- stats = &link_sta->rx_stats; ++ stats = &rx->link_sta->rx_stats; + + stats->dropped++; + return true; +@@ -5058,8 +5089,8 @@ static bool ieee80211_prepare_and_rx_han + struct ieee80211_local *local = rx->local; + struct ieee80211_sub_if_data *sdata = rx->sdata; + struct ieee80211_hdr *hdr = (void *)skb->data; +- struct link_sta_info *link_sta = NULL; +- struct ieee80211_link_data *link; ++ struct link_sta_info *link_sta = rx->link_sta; ++ struct ieee80211_link_data *link = rx->link; + + rx->skb = skb; + +@@ -5081,35 +5112,6 @@ static bool ieee80211_prepare_and_rx_han + if (!ieee80211_accept_frame(rx)) + return false; + +- if (rx->link_id >= 0) { +- link = rcu_dereference(rx->sdata->link[rx->link_id]); +- +- /* we might race link removal */ +- if (!link) +- return true; +- rx->link = link; +- +- if (rx->sta) { +- rx->link_sta = +- rcu_dereference(rx->sta->link[rx->link_id]); +- if (!rx->link_sta) +- return true; +- } +- } else { +- if (rx->sta) +- rx->link_sta = &rx->sta->deflink; +- +- rx->link = &sdata->deflink; +- } +- +- if (unlikely(!is_multicast_ether_addr(hdr->addr1) && +- rx->link_id >= 0 && rx->sta && rx->sta->sta.mlo)) { +- link_sta = rcu_dereference(rx->sta->link[rx->link_id]); +- +- if (WARN_ON_ONCE(!link_sta)) +- return true; +- } +- + if (!consume) { + struct skb_shared_hwtstamps *shwt; + +@@ -5132,7 +5134,7 @@ static bool ieee80211_prepare_and_rx_han + hdr = (struct ieee80211_hdr *)rx->skb->data; + } + +- if (unlikely(link_sta)) { ++ if (unlikely(rx->sta && rx->sta->sta.mlo)) { + /* translate to MLD addresses */ + if (ether_addr_equal(link->conf->addr, hdr->addr1)) + ether_addr_copy(hdr->addr1, rx->sdata->vif.addr); +@@ -5166,6 +5168,7 @@ static void __ieee80211_rx_handle_8023(s + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); + struct ieee80211_fast_rx *fast_rx; + struct ieee80211_rx_data rx; ++ int link_id = -1; + + memset(&rx, 0, sizeof(rx)); + rx.skb = skb; +@@ -5182,12 +5185,8 @@ static void __ieee80211_rx_handle_8023(s + if (!pubsta) + goto drop; + +- rx.sta = container_of(pubsta, struct sta_info, sta); +- rx.sdata = rx.sta->sdata; +- +- if (status->link_valid && +- !ieee80211_rx_is_valid_sta_link_id(pubsta, status->link_id)) +- goto drop; ++ if (status->link_valid) ++ link_id = status->link_id; + + /* + * TODO: Should the frame be dropped if the right link_id is not +@@ -5196,19 +5195,8 @@ static void __ieee80211_rx_handle_8023(s + * link_id is used only for stats purpose and updating the stats on + * the deflink is fine? + */ +- if (status->link_valid) +- rx.link_id = status->link_id; +- +- if (rx.link_id >= 0) { +- struct ieee80211_link_data *link; +- +- link = rcu_dereference(rx.sdata->link[rx.link_id]); +- if (!link) +- goto drop; +- rx.link = link; +- } else { +- rx.link = &rx.sdata->deflink; +- } ++ if (!ieee80211_rx_data_set_sta(&rx, pubsta, link_id)) ++ goto drop; + + fast_rx = rcu_dereference(rx.sta->fast_rx); + if (!fast_rx) +@@ -5226,6 +5214,8 @@ static bool ieee80211_rx_for_interface(s + { + struct link_sta_info *link_sta; + struct ieee80211_hdr *hdr = (void *)skb->data; ++ struct sta_info *sta; ++ int link_id = -1; + + /* + * Look up link station first, in case there's a +@@ -5235,24 +5225,19 @@ static bool ieee80211_rx_for_interface(s + */ + link_sta = link_sta_info_get_bss(rx->sdata, hdr->addr2); + if (link_sta) { +- rx->sta = link_sta->sta; +- rx->link_id = link_sta->link_id; ++ sta = link_sta->sta; ++ link_id = link_sta->link_id; + } else { + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); + +- rx->sta = sta_info_get_bss(rx->sdata, hdr->addr2); +- if (rx->sta) { +- if (status->link_valid && +- !ieee80211_rx_is_valid_sta_link_id(&rx->sta->sta, +- status->link_id)) +- return false; +- +- rx->link_id = status->link_valid ? status->link_id : -1; +- } else { +- rx->link_id = -1; +- } ++ sta = sta_info_get_bss(rx->sdata, hdr->addr2); ++ if (status->link_valid) ++ link_id = status->link_id; + } + ++ if (!ieee80211_rx_data_set_sta(rx, &sta->sta, link_id)) ++ return false; ++ + return ieee80211_prepare_and_rx_handle(rx, skb, consume); + } + +@@ -5315,19 +5300,15 @@ static void __ieee80211_rx_handle_packet + + if (ieee80211_is_data(fc)) { + struct sta_info *sta, *prev_sta; +- u8 link_id = status->link_id; ++ int link_id = -1; + +- if (pubsta) { +- rx.sta = container_of(pubsta, struct sta_info, sta); +- rx.sdata = rx.sta->sdata; ++ if (status->link_valid) ++ link_id = status->link_id; + +- if (status->link_valid && +- !ieee80211_rx_is_valid_sta_link_id(pubsta, link_id)) ++ if (pubsta) { ++ if (!ieee80211_rx_data_set_sta(&rx, pubsta, link_id)) + goto out; + +- if (status->link_valid) +- rx.link_id = status->link_id; +- + /* + * In MLO connection, fetch the link_id using addr2 + * when the driver does not pass link_id in status. +@@ -5345,7 +5326,7 @@ static void __ieee80211_rx_handle_packet + if (!link_sta) + goto out; + +- rx.link_id = link_sta->link_id; ++ ieee80211_rx_data_set_link(&rx, link_sta->link_id); + } + + if (ieee80211_prepare_and_rx_handle(&rx, skb, true)) +@@ -5361,30 +5342,27 @@ static void __ieee80211_rx_handle_packet + continue; + } + +- if ((status->link_valid && +- !ieee80211_rx_is_valid_sta_link_id(&prev_sta->sta, +- link_id)) || +- (!status->link_valid && prev_sta->sta.mlo)) ++ rx.sdata = prev_sta->sdata; ++ if (!ieee80211_rx_data_set_sta(&rx, &prev_sta->sta, ++ link_id)) ++ goto out; ++ ++ if (!status->link_valid && prev_sta->sta.mlo) + continue; + +- rx.link_id = status->link_valid ? link_id : -1; +- rx.sta = prev_sta; +- rx.sdata = prev_sta->sdata; + ieee80211_prepare_and_rx_handle(&rx, skb, false); + + prev_sta = sta; + } + + if (prev_sta) { +- if ((status->link_valid && +- !ieee80211_rx_is_valid_sta_link_id(&prev_sta->sta, +- link_id)) || +- (!status->link_valid && prev_sta->sta.mlo)) ++ rx.sdata = prev_sta->sdata; ++ if (!ieee80211_rx_data_set_sta(&rx, &prev_sta->sta, ++ link_id)) + goto out; + +- rx.link_id = status->link_valid ? link_id : -1; +- rx.sta = prev_sta; +- rx.sdata = prev_sta->sdata; ++ if (!status->link_valid && prev_sta->sta.mlo) ++ goto out; + + if (ieee80211_prepare_and_rx_handle(&rx, skb, true)) + return; diff --git a/feeds/ipq95xx/mac80211/patches/qca/710-0001-ath12k-symmetrize-scan-vdev-create-and-delete-during.patch b/feeds/ipq95xx/mac80211/patches/qca/710-0001-ath12k-symmetrize-scan-vdev-create-and-delete-during.patch new file mode 100644 index 000000000..90faf6eee --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/710-0001-ath12k-symmetrize-scan-vdev-create-and-delete-during.patch @@ -0,0 +1,163 @@ +From 4e7cb831af505a7ca0daa5f625fa1f63b84ff096 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Tue, 24 Jan 2023 18:08:32 +0530 +Subject: [PATCH] ath12k: symmetrize scan vdev create and delete during hw scan + +Currently, hw scan is started in driver on link_id 0. After mapping +to proper ar based on the scan frequency, the vdev is created and scan +is started. However, the vdev is only deleted during MLO scenario when +after scan, channel assignent is going to happen. This unbalanced +scenario leads to various hw scan issues where non-ML plus ML combination +exists and the later tries to skip the scan and do a channel assignemnt +while the former is still scanning. This will ead to FW assert. + +Address this issue by symmetrizing the scan vdev create and delete +during hw scan operations itself. This means, create a vdev when scan +starts and delete it once scan is completed or aborted. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath12k/core.c | 1 + + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/mac.c | 76 ++++++++++++++++++++++---- + 3 files changed, 68 insertions(+), 10 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -1449,6 +1449,7 @@ void ath12k_core_halt(struct ath12k *ar) + ath12k_mac_scan_finish(ar); + ath12k_mac_peer_cleanup_all(ar); + cancel_delayed_work_sync(&ar->scan.timeout); ++ cancel_work_sync(&ar->scan.vdev_del_wk); + cancel_work_sync(&ar->regd_update_work); + rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], NULL); + synchronize_rcu(); +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -747,6 +747,7 @@ struct ath12k { + int vdev_id; + int roc_freq; + bool roc_notify; ++ struct work_struct vdev_del_wk; + } scan; + + struct { +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -255,7 +255,8 @@ static void ath12k_mac_parse_tx_pwr_env( + struct ieee80211_chanctx_conf *ctx); + static void ath12k_update_bcn_template_work(struct work_struct *work); + static void ath12k_update_obss_color_notify_work(struct work_struct *work); +- ++static void ath12k_mac_remove_link_interface(struct ieee80211_hw *hw, ++ struct ath12k_link_vif *arvif); + enum nl80211_he_ru_alloc ath12k_mac_phy_he_ru_to_nl80211_he_ru_alloc(u16 ru_phy) + { + enum nl80211_he_ru_alloc ret; +@@ -4691,6 +4692,7 @@ void __ath12k_mac_scan_finish(struct ath + ar->scan.roc_freq = 0; + cancel_delayed_work(&ar->scan.timeout); + complete(&ar->scan.completed); ++ ieee80211_queue_work(ah->hw, &ar->scan.vdev_del_wk); + break; + } + } +@@ -4790,6 +4792,46 @@ static void ath12k_scan_timeout_work(str + mutex_unlock(&ar->conf_mutex); + } + ++static void ath12k_scan_vdev_del_work(struct work_struct *work) ++{ ++ struct ath12k *ar = container_of(work, struct ath12k, ++ scan.vdev_del_wk); ++ struct ath12k_hw *ah = ar->ah; ++ struct ath12k_link_vif *arvif; ++ ++ mutex_lock(&ar->conf_mutex); ++ /* scan vdev got deleted already. This can happen when on same vif, new ++ * scan request was requested with different frequeny which leads to ++ * movement of scan arvif from one radio to another radio */ ++ if (ar->scan.vdev_id == -1) ++ goto work_complete; ++ ++ mutex_unlock(&ar->conf_mutex); ++ ++ arvif = ath12k_mac_get_arvif(ar, ar->scan.vdev_id); ++ /* should not happen */ ++ if (!arvif) { ++ ath12k_warn(ar->ab, "mac scan vdev del on unknow vdev_id %d\n", ++ ar->scan.vdev_id); ++ return; ++ } ++ ++ if (arvif->is_started) { ++ mutex_lock(&ar->conf_mutex); ++ ar->scan.vdev_id = -1; ++ goto work_complete; ++ } ++ ++ mutex_lock(&ah->conf_mutex); ++ ath12k_mac_remove_link_interface(ah->hw, arvif); ++ mutex_unlock(&ah->conf_mutex); ++ ++ mutex_lock(&ar->conf_mutex); ++ ar->scan.vdev_id = -1; ++work_complete: ++ mutex_unlock(&ar->conf_mutex); ++} ++ + static int ath12k_start_scan(struct ath12k *ar, + struct scan_req_params *arg) + { +@@ -4873,6 +4945,11 @@ static int ath12k_mac_op_hw_scan(struct + mutex_unlock(&ah->conf_mutex); + return -EINVAL; + } else if (ar != arvif->ar) { ++ mutex_lock(&arvif->ar->conf_mutex); ++ if (arvif->ar->scan.vdev_id != -1) ++ arvif->ar->scan.vdev_id = -1; ++ mutex_unlock(&arvif->ar->conf_mutex); ++ + ret = ath12k_mac_vdev_delete(arvif->ar, arvif); + if (ret) + ath12k_warn(arvif->ar->ab, "unable to delete scan vdev %d\n", ret); +@@ -4893,9 +4977,6 @@ static int ath12k_mac_op_hw_scan(struct + mutex_unlock(&ar->conf_mutex); + } + +- if (vif->valid_links) +- ah->scan_arvif = arvif; +- + mutex_unlock(&ah->conf_mutex); + + mutex_lock(&ar->conf_mutex); +@@ -8564,6 +8645,7 @@ static void ath12k_mac_radio_stop(struct + mutex_unlock(&ar->conf_mutex); + + cancel_delayed_work_sync(&ar->scan.timeout); ++ cancel_work_sync(&ar->scan.vdev_del_wk); + cancel_work_sync(&ar->regd_update_work); + + spin_lock_bh(&ar->data_lock); +@@ -11360,12 +11442,6 @@ ath12k_mac_op_assign_vif_chanctx(struct + + mutex_lock(&ah->conf_mutex); + +- /* clear any scan arvifs since its always attached to link 0 by default */ +- if (ah->scan_arvif && vif->valid_links) { +- ath12k_mac_remove_link_interface(hw, ah->scan_arvif); +- ah->scan_arvif = NULL; +- } +- + arvif = ath12k_mac_assign_link_vif(ah, vif, link_id); + if (!arvif) { + ath12k_err(NULL, "unable to allocate link vif\n"); +@@ -14149,6 +14225,8 @@ static int ath12k_mac_setup(struct ath12 + init_completion(&ar->mvr_complete); + + INIT_DELAYED_WORK(&ar->scan.timeout, ath12k_scan_timeout_work); ++ INIT_WORK(&ar->scan.vdev_del_wk, ath12k_scan_vdev_del_work); ++ ar->scan.vdev_id = -1; + INIT_WORK(&ar->regd_update_work, ath12k_regd_update_work); + + INIT_WORK(&ar->wmi_mgmt_tx_work, ath12k_mgmt_over_wmi_tx_work); diff --git a/feeds/ipq95xx/mac80211/patches/qca/710-0002-ath12k-do-not-return-invalid-link-id-for-scan-link.patch b/feeds/ipq95xx/mac80211/patches/qca/710-0002-ath12k-do-not-return-invalid-link-id-for-scan-link.patch new file mode 100644 index 000000000..e891f84c7 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/710-0002-ath12k-do-not-return-invalid-link-id-for-scan-link.patch @@ -0,0 +1,370 @@ +From a0677f9323b9886ab26599e07eff9b52ad341d02 Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Tue, 24 Jan 2023 16:49:05 +0530 +Subject: [PATCH] ath12k: do not return invalid link id for scan link + +When a scan request is received, driver selects a link id +for which the arvif can be mapped. Same link is also +used for getting the link conf address. Currently, we return +0 as link id for a non ML vif, which is correct since that is +the default link id. +Also when any of the link vif is active and the scan request +is for a channel in the active link we return its link id. +But, when we dont hit both of the above cases(i.e not a ML +vif or no active link vif for the channel is present) we +currently return 0 as the link id. +This might not work out always, ex, when only one +link(ex. linkid = 1) is added to vif, then we wont find any +link conf for link id 0 in the vif resulting in scan failure. + +During AP bringup, such scan failure can cause bringup issues. +Hence avoid sending link id 0 as default. Rather use a default +link for scan and default link address for the same. This scan +vdev will either be deleted if another scan is requested on same +vif or when AP is broughtup on same link or during interface cleanup + +Signed-off-by: Sriram R +--- + drivers/net/wireless/ath/ath12k/core.h | 4 +- + drivers/net/wireless/ath/ath12k/debugfs.c | 3 + + drivers/net/wireless/ath/ath12k/mac.c | 96 ++++++++++++++++------- + drivers/net/wireless/ath/ath12k/mac.h | 6 ++ + 4 files changed, 78 insertions(+), 31 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -391,7 +391,7 @@ struct ath12k_vif { + } u; + + struct ath12k_link_vif deflink; +- struct ath12k_link_vif *link[IEEE80211_MLD_MAX_NUM_LINKS]; ++ struct ath12k_link_vif *link[ATH12K_NUM_MAX_LINKS]; + /* indicates bitmap of link vdev created in FW */ + u16 links_map; + u32 aid; +@@ -399,6 +399,7 @@ struct ath12k_vif { + u8 num_vdev_created; + u8 num_vdev_started; + struct ath12k_vif_cache cache[IEEE80211_MLD_MAX_NUM_LINKS]; ++ u8 last_scan_link; + }; + + struct ath12k_vif_iter { +@@ -1026,7 +1027,6 @@ struct ath12k_hw { + bool regd_updated; + u8 supported_band_mask; + u8 num_radio; +- struct ath12k_link_vif *scan_arvif; + DECLARE_BITMAP(free_ml_peer_id_map, ATH12K_MAX_MLO_PEERS); + struct ath12k radio[0] __aligned(sizeof(void *)); + }; +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -2755,6 +2755,9 @@ int ath12k_debugfs_add_interface(struct + u8 link_id = arvif->link_id; + int ret = 0; + ++ if (link_id >= IEEE80211_MLD_MAX_NUM_LINKS) ++ goto exit; ++ + if (ahvif->vif->type != NL80211_IFTYPE_AP) + goto exit; + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -44,6 +44,8 @@ + .max_power = 30, \ + } + ++static void ath12k_mac_remove_link_interface(struct ieee80211_hw *hw, ++ struct ath12k_link_vif *arvif); + static const struct ieee80211_channel ath12k_2ghz_channels[] = { + CHAN2G(1, 2412, 0), + CHAN2G(2, 2417, 0), +@@ -650,7 +652,7 @@ static void ath12k_get_arvif_iter(void * + */ + links_map = ahvif->links_map; + +- for_each_set_bit(link_id, &links_map, IEEE80211_MLD_MAX_NUM_LINKS) { ++ for_each_set_bit(link_id, &links_map, ATH12K_NUM_MAX_LINKS) { + arvif = ahvif->link[link_id]; + + if (WARN_ON(arvif == NULL)) +@@ -4561,11 +4563,24 @@ ath12k_mac_find_link_id_by_freq(struct i + return link_id; + } + +- /* +- * Valid ML case when channel is not assigned to any of the links +- * so link id 0 can be used ++ /* Use a default link for scan purpose in driver if the request ++ * cannot be mapped to any of the active links(channel assigned) + */ +- return 0; ++ return ATH12K_DEFAULT_SCAN_LINK; ++} ++ ++void ath12k_mac_unassign_link_vif(struct ath12k_link_vif *arvif) ++{ ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ath12k_hw *ah = ahvif->ah; ++ ++ lockdep_assert_held(&ah->conf_mutex); ++ ++ ahvif->link[arvif->link_id] = NULL; ++ ahvif->links_map &= ~BIT(arvif->link_id); ++ ++ if (arvif != &ahvif->deflink) ++ kfree(arvif); + } + + static struct ath12k_link_vif * +@@ -4824,6 +4839,7 @@ static void ath12k_scan_vdev_del_work(st + + mutex_lock(&ah->conf_mutex); + ath12k_mac_remove_link_interface(ah->hw, arvif); ++ ath12k_mac_unassign_link_vif(arvif); + mutex_unlock(&ah->conf_mutex); + + mutex_lock(&ar->conf_mutex); +@@ -4873,6 +4889,7 @@ static int ath12k_mac_op_hw_scan(struct + struct ieee80211_vif *vif, + struct ieee80211_scan_request *hw_req) + { ++ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + struct ath12k_hw *ah = hw->priv; + struct ath12k_link_vif *arvif; + struct cfg80211_scan_request *req = &hw_req->req; +@@ -4920,15 +4937,15 @@ static int ath12k_mac_op_hw_scan(struct + arvif->ar->scan.vdev_id = -1; + mutex_unlock(&arvif->ar->conf_mutex); + +- ret = ath12k_mac_vdev_delete(arvif->ar, arvif); +- if (ret) +- ath12k_warn(arvif->ar->ab, "unable to delete scan vdev %d\n", ret); ++ ath12k_mac_remove_link_interface(hw, arvif); ++ ath12k_mac_unassign_link_vif(arvif); + } else { + create = false; + } + } + + if (create) { ++ arvif = ath12k_mac_assign_link_vif(ah, vif, link_id); + mutex_lock(&ar->conf_mutex); + ret = ath12k_mac_vdev_create(ar, arvif); + if (ret) { +@@ -5001,6 +5018,13 @@ static int ath12k_mac_op_hw_scan(struct + spin_unlock_bh(&ar->data_lock); + } + ++ /* As per cfg80211/mac80211 scan design, it allows only ++ * scan at a time. Hence last_scan link id is used for ++ * tracking the link id on which the scan is been done ++ * on this vif ++ */ ++ ahvif->last_scan_link = arvif->link_id; ++ + /* Add a 200ms margin to account for event/command processing */ + ieee80211_queue_delayed_work(ar->ah->hw, &ar->scan.timeout, + msecs_to_jiffies(arg.max_scan_time + +@@ -5021,11 +5045,7 @@ static void ath12k_mac_op_cancel_hw_scan + struct ath12k_link_vif *arvif; + struct ath12k_hw *ah = hw->priv; + struct ath12k *ar; +- /* TODO we currently use temp link id as 0, for runtime +- * force AP scan handle accordingly by identifying the +- * active scan link +- */ +- u8 link_id = 0; ++ u8 link_id = ahvif->last_scan_link; + + mutex_lock(&ah->conf_mutex); + +@@ -8950,12 +8970,22 @@ static int ath12k_mac_vdev_create(struct + int ret, vdev_id; + u8 link_addr[ETH_ALEN]; + int txpower; ++ u8 link_id; + + lockdep_assert_held(&ar->conf_mutex); + ++ /* If no link is active and scan vdev is requested ++ * use a default link conf for scan address purpose ++ */ ++ if (arvif->link_id == ATH12K_DEFAULT_SCAN_LINK && ++ vif->valid_links) ++ link_id = ffs(vif->valid_links) - 1; ++ else ++ link_id = arvif->link_id; ++ + rcu_read_lock(); + +- link_conf = rcu_dereference(vif->link_conf[arvif->link_id]); ++ link_conf = rcu_dereference(vif->link_conf[link_id]); + + if (!link_conf) { + rcu_read_unlock(); +@@ -9240,6 +9270,7 @@ static struct ath12k *ath12k_mac_assign_ + struct ath12k *ar; + struct ath12k_base *ab; + struct ieee80211_vif *vif = arvif->ahvif->vif; ++ struct ath12k_link_vif *scan_arvif; + u8 bit; + int ret; + +@@ -9256,6 +9287,21 @@ static struct ath12k *ath12k_mac_assign_ + goto out; + } + ++ /* cleanup the scan vdev if we are done scan on that ar ++ * and now we want to create for actual usage ++ */ ++ if (vif->valid_links) { ++ scan_arvif = arvif->ahvif->link[ATH12K_DEFAULT_SCAN_LINK]; ++ ++ if (scan_arvif && scan_arvif->ar == ar) { ++ mutex_lock(&ar->conf_mutex); ++ ar->scan.vdev_id = -1; ++ mutex_unlock(&ar->conf_mutex); ++ ath12k_mac_remove_link_interface(hw, scan_arvif); ++ ath12k_mac_unassign_link_vif(scan_arvif); ++ } ++ } ++ + ab = ar->ab; + + mutex_lock(&ar->conf_mutex); +@@ -9438,7 +9484,8 @@ err_vdev_del: + + ath12k_debugfs_remove_interface(arvif); + +- if (!list_empty(&ahvif->cache[arvif->link_id].key_conf.list)) { ++ if (arvif->link_id < IEEE80211_MLD_MAX_NUM_LINKS && ++ !list_empty(&ahvif->cache[arvif->link_id].key_conf.list)) { + list_for_each_entry_safe(key_conf, tmp, + &ahvif->cache[arvif->link_id].key_conf.list, + list) { +@@ -9449,9 +9496,6 @@ err_vdev_del: + + /* TODO: recal traffic pause state based on the available vdevs */ + +- ahvif->link[arvif->link_id] = NULL; +- ahvif->links_map &= ~BIT(arvif->link_id); +- + mutex_unlock(&ar->conf_mutex); + } + +@@ -9468,7 +9512,7 @@ static void ath12k_mac_op_remove_interfa + + links_map = ahvif->links_map; + +- for_each_set_bit(link_id, &links_map, IEEE80211_MLD_MAX_NUM_LINKS) { ++ for_each_set_bit(link_id, &links_map, ATH12K_NUM_MAX_LINKS) { + arvif = ahvif->link[link_id]; + + if (arvif == NULL) +@@ -9478,9 +9522,7 @@ static void ath12k_mac_op_remove_interfa + continue; + + ath12k_mac_remove_link_interface(hw, arvif); +- +- if (arvif != &ahvif->deflink) +- kfree(arvif); ++ ath12k_mac_unassign_link_vif(arvif); + } + + mutex_unlock(&ah->conf_mutex); +@@ -9728,7 +9770,7 @@ static int ath12k_mac_set_6g_nonht_dup_c + + rcu_read_lock(); + +- link_conf = rcu_dereference(ahvif->vif->link_conf[arvif->link_id]); ++ link_conf = ath12k_get_link_bss_conf(arvif); + + if (!link_conf) { + rcu_read_unlock(); +@@ -10278,7 +10320,7 @@ ath12k_mac_change_chanctx_cnt_iter(void + if (WARN_ON(arvif == NULL)) + continue; + +- link_conf = rcu_dereference(vif->link_conf[arvif->link_id]); ++ link_conf = ath12k_get_link_bss_conf(arvif); + + if (WARN_ON(link_conf == NULL)) + continue; +@@ -10314,7 +10356,7 @@ ath12k_mac_change_chanctx_fill_iter(void + if (WARN_ON(arvif == NULL)) + continue; + +- link_conf = rcu_dereference(vif->link_conf[arvif->link_id]); ++ link_conf = ath12k_get_link_bss_conf(arvif); + + if (WARN_ON(link_conf == NULL)) + continue; +@@ -11643,6 +11685,7 @@ ath12k_mac_op_unassign_vif_chanctx(struc + + mutex_unlock(&ar->conf_mutex); + ath12k_mac_remove_link_interface(hw, arvif); ++ ath12k_mac_unassign_link_vif(arvif); + goto unassign_exit; + out: + mutex_unlock(&ar->conf_mutex); +@@ -12004,7 +12047,6 @@ ath12k_mac_get_single_legacy_rate(struct + static int + ath12k_mac_set_fixed_rate_GI_LTF(struct ath12k_link_vif *arvif, u8 gi, u8 ltf) + { +- struct ieee80211_vif *vif = arvif->ahvif->vif; + struct ieee80211_bss_conf *link_conf; + struct ath12k *ar = arvif->ar; + int param, ret; +@@ -12016,7 +12058,7 @@ ath12k_mac_set_fixed_rate_GI_LTF(struct + + rcu_read_lock(); + +- link_conf = rcu_dereference(vif->link_conf[arvif->link_id]); ++ link_conf = ath12k_get_link_bss_conf(arvif); + + if (!link_conf) { + rcu_read_unlock(); +@@ -12118,7 +12160,6 @@ static int ath12k_mac_set_rate_params(st + bool eht_fixed_rate, + int he_ul_rate, u8 he_ul_nss) + { +- struct ieee80211_vif *vif = arvif->ahvif->vif; + struct ieee80211_bss_conf *link_conf; + struct ath12k *ar = arvif->ar; + u32 vdev_param, rate_code; +@@ -12129,7 +12170,7 @@ static int ath12k_mac_set_rate_params(st + + rcu_read_lock(); + +- link_conf = rcu_dereference(vif->link_conf[arvif->link_id]); ++ link_conf = ath12k_get_link_bss_conf(arvif); + + if (!link_conf) { + rcu_read_unlock(); +@@ -12470,7 +12511,7 @@ ath12k_mac_check_fixed_rate_settings_for + + rcu_read_lock(); + +- link_conf = rcu_dereference(arvif->ahvif->vif->link_conf[arvif->link_id]); ++ link_conf = ath12k_get_link_bss_conf(arvif); + + if (!link_conf) { + rcu_read_unlock(); +--- a/drivers/net/wireless/ath/ath12k/mac.h ++++ b/drivers/net/wireless/ath/ath12k/mac.h +@@ -30,6 +30,12 @@ struct ath12k_mac_num_chanctxs_arg { + int num; + }; + ++/* Default link after the IEEE802.11 defined Max link id limit ++ * for driver usage purpose ++ */ ++#define ATH12K_DEFAULT_SCAN_LINK IEEE80211_MLD_MAX_NUM_LINKS ++#define ATH12K_NUM_MAX_LINKS (IEEE80211_MLD_MAX_NUM_LINKS + 1) ++ + /* number of failed packets (20 packets with 16 sw reties each) */ + #define ATH12K_KICKOUT_THRESHOLD (20 * 16) + diff --git a/feeds/ipq95xx/mac80211/patches/qca/710-001-ath12k-Add-AHB-driver-support-for-ipq5332.patch b/feeds/ipq95xx/mac80211/patches/qca/710-001-ath12k-Add-AHB-driver-support-for-ipq5332.patch new file mode 100644 index 000000000..920a4b71e --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/710-001-ath12k-Add-AHB-driver-support-for-ipq5332.patch @@ -0,0 +1,1212 @@ +From 568e3438bf498d33cbd6a15656cd50fa73c39f35 Mon Sep 17 00:00:00 2001 +From: Balamurugan S +Date: Mon, 30 Jan 2023 23:42:29 +0530 +Subject: [PATCH 1/8] ath12k: Add AHB driver support for ipq5332 + +Add Initial AHB driver support for ipq5332. + +Signed-off-by: Balamurugan S +--- + drivers/net/wireless/ath/ath12k/ahb.c | 1105 +++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/ahb.h | 54 ++ + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/debug.h | 1 + + 4 files changed, 1161 insertions(+) + create mode 100644 drivers/net/wireless/ath/ath12k/ahb.c + create mode 100644 drivers/net/wireless/ath/ath12k/ahb.h + +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/ahb.c +@@ -0,0 +1,1115 @@ ++// SPDX-License-Identifier: BSD-3-Clause-Clear ++/* ++ * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "ahb.h" ++#include "debug.h" ++#include "hif.h" ++#include ++#include ++#include ++ ++static const struct of_device_id ath12k_ahb_of_match[] = { ++ { .compatible = "qcom,ipq5332-wifi", ++ .data = (void *)ATH12K_HW_IPQ5332_HW10, ++ }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(of, ath12k_ahb_of_match); ++ ++#define ATH12K_IRQ_CE0_OFFSET 4 ++ ++static const char *irq_name[ATH12K_IRQ_NUM_MAX] = { ++ "misc-pulse1", ++ "misc-latch", ++ "sw-exception", ++ "watchdog", ++ "ce0", ++ "ce1", ++ "ce2", ++ "ce3", ++ "ce4", ++ "ce5", ++ "ce6", ++ "ce7", ++ "ce8", ++ "ce9", ++ "ce10", ++ "ce11", ++ "host2wbm-desc-feed", ++ "host2reo-re-injection", ++ "host2reo-command", ++ "host2rxdma-monitor-ring3", ++ "host2rxdma-monitor-ring2", ++ "host2rxdma-monitor-ring1", ++ "reo2ost-exception", ++ "wbm2host-rx-release", ++ "reo2host-status", ++ "reo2host-destination-ring4", ++ "reo2host-destination-ring3", ++ "reo2host-destination-ring2", ++ "reo2host-destination-ring1", ++ "rxdma2host-monitor-destination-mac3", ++ "rxdma2host-monitor-destination-mac2", ++ "rxdma2host-monitor-destination-mac1", ++ "ppdu-end-interrupts-mac3", ++ "ppdu-end-interrupts-mac2", ++ "ppdu-end-interrupts-mac1", ++ "rxdma2host-monitor-status-ring-mac3", ++ "rxdma2host-monitor-status-ring-mac2", ++ "rxdma2host-monitor-status-ring-mac1", ++ "host2rxdma-host-buf-ring-mac3", ++ "host2rxdma-host-buf-ring-mac2", ++ "host2rxdma-host-buf-ring-mac1", ++ "rxdma2host-destination-ring-mac3", ++ "rxdma2host-destination-ring-mac2", ++ "rxdma2host-destination-ring-mac1", ++ "host2tcl-input-ring4", ++ "host2tcl-input-ring3", ++ "host2tcl-input-ring2", ++ "host2tcl-input-ring1", ++ "wbm2host-tx-completions-ring4", ++ "wbm2host-tx-completions-ring3", ++ "wbm2host-tx-completions-ring2", ++ "wbm2host-tx-completions-ring1", ++ "tcl2host-status-ring", ++}; ++ ++/* enum ext_irq_num - irq numbers that can be used by external modules ++ * like datapath ++ */ ++enum ext_irq_num { ++ host2wbm_desc_feed = 16, ++ host2reo_re_injection, ++ host2reo_command, ++ host2rxdma_monitor_ring3, ++ host2rxdma_monitor_ring2, ++ host2rxdma_monitor_ring1, ++ reo2host_exception, ++ wbm2host_rx_release, ++ reo2host_status, ++ reo2host_destination_ring4, ++ reo2host_destination_ring3, ++ reo2host_destination_ring2, ++ reo2host_destination_ring1, ++ rxdma2host_monitor_destination_mac3, ++ rxdma2host_monitor_destination_mac2, ++ rxdma2host_monitor_destination_mac1, ++ ppdu_end_interrupts_mac3, ++ ppdu_end_interrupts_mac2, ++ ppdu_end_interrupts_mac1, ++ rxdma2host_monitor_status_ring_mac3, ++ rxdma2host_monitor_status_ring_mac2, ++ rxdma2host_monitor_status_ring_mac1, ++ host2rxdma_host_buf_ring_mac3, ++ host2rxdma_host_buf_ring_mac2, ++ host2rxdma_host_buf_ring_mac1, ++ rxdma2host_destination_ring_mac3, ++ rxdma2host_destination_ring_mac2, ++ rxdma2host_destination_ring_mac1, ++ host2tcl_input_ring4, ++ host2tcl_input_ring3, ++ host2tcl_input_ring2, ++ host2tcl_input_ring1, ++ wbm2host_tx_completions_ring4, ++ wbm2host_tx_completions_ring3, ++ wbm2host_tx_completions_ring2, ++ wbm2host_tx_completions_ring1, ++ tcl2host_status_ring, ++}; ++ ++static inline u32 ath12k_ahb_cmem_read32(struct ath12k_base *ab, u32 offset) ++{ ++ offset = offset - HAL_IPQ5332_CMEM_BASE; ++ ath12k_dbg(ab, ATH12K_DBG_OFFSET, "Mem_cmem:%p offset:%x\n", ++ ab->mem_cmem, offset); ++ return ioread32(ab->mem_cmem + offset); ++ ++} ++ ++static inline void ath12k_ahb_cmem_write32(struct ath12k_base *ab, u32 offset, ++ u32 value) ++{ ++ offset = offset - HAL_IPQ5332_CMEM_BASE; ++ ath12k_dbg(ab, ATH12K_DBG_OFFSET, "Mem_cmem:%p offset:%x value:%x\n", ++ ab->mem_cmem, offset, value); ++ iowrite32(value, ab->mem_cmem + offset); ++} ++ ++static inline u32 ath12k_ahb_read32(struct ath12k_base *ab, u32 offset) ++{ ++ if (ab->ce_remap && (offset < HAL_SEQ_WCSS_UMAC_OFFSET)) { ++ offset = offset - HAL_CE_REMAP_REG_BASE; ++ ath12k_dbg(ab, ATH12K_DBG_OFFSET, "Mem_ce:%p offset:%x\n", ++ ab->mem_ce, offset); ++ return ioread32(ab->mem_ce + offset); ++ } else { ++ ath12k_dbg(ab, ATH12K_DBG_OFFSET, "Mem:%p offset:%x\n", ++ ab->mem, offset); ++ return ioread32(ab->mem + offset); ++ } ++} ++ ++static inline void ath12k_ahb_write32(struct ath12k_base *ab, u32 offset, ++ u32 value) ++{ ++ if (ab->ce_remap && (offset < HAL_SEQ_WCSS_UMAC_OFFSET)) { ++ offset = offset - HAL_CE_REMAP_REG_BASE; ++ ath12k_dbg(ab, ATH12K_DBG_OFFSET, "mem_ce:%p offset:%x value:%d\n", ++ ab->mem_ce, offset, value); ++ iowrite32(value, ab->mem_ce + offset); ++ } else { ++ ath12k_dbg(ab, ATH12K_DBG_OFFSET, "mem:%p offset:%x value:%d\n", ++ ab->mem, offset, value); ++ iowrite32(value, ab->mem + offset); ++ } ++} ++ ++static void ath12k_ahb_kill_tasklets(struct ath12k_base *ab) ++{ ++ int i; ++ ++ for (i = 0; i < ab->hw_params->ce_count; i++) { ++ struct ath12k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i]; ++ ++ if (ath12k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) ++ continue; ++ ++ tasklet_kill(&ce_pipe->intr_tq); ++ } ++} ++ ++static void ath12k_ahb_ext_grp_disable(struct ath12k_ext_irq_grp *irq_grp) ++{ ++ int i; ++ ++ for (i = 0; i < irq_grp->num_irq; i++) ++ disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]); ++} ++ ++static void __ath12k_ahb_ext_irq_disable(struct ath12k_base *ab) ++{ ++ int i; ++ ++ for (i = 0; i < ATH12K_EXT_IRQ_GRP_NUM_MAX; i++) { ++ struct ath12k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; ++ ++ ath12k_ahb_ext_grp_disable(irq_grp); ++ if (irq_grp->napi_enabled) { ++ napi_synchronize(&irq_grp->napi); ++ napi_disable(&irq_grp->napi); ++ irq_grp->napi_enabled = false; ++ } ++ } ++} ++ ++static void ath12k_ahb_ext_grp_enable(struct ath12k_ext_irq_grp *irq_grp) ++{ ++ int i; ++ ++ for (i = 0; i < irq_grp->num_irq; i++) ++ enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]); ++} ++ ++static void ath12k_ahb_setbit32(struct ath12k_base *ab, u8 bit, u32 offset) ++{ ++ u32 val; ++ ++ val = ath12k_ahb_read32(ab, offset); ++ ath12k_ahb_write32(ab, offset, val | BIT(bit)); ++} ++ ++static void ath12k_ahb_clearbit32(struct ath12k_base *ab, u8 bit, u32 offset) ++{ ++ u32 val; ++ ++ val = ath12k_ahb_read32(ab, offset); ++ ath12k_ahb_write32(ab, offset, val & ~BIT(bit)); ++} ++ ++static void ath12k_ahb_ce_irq_enable(struct ath12k_base *ab, u16 ce_id) ++{ ++ const struct ce_attr *ce_attr; ++ 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; ++ 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) ++ ath12k_ahb_setbit32(ab, ce_id, ie1_reg_addr); ++ ++ if (ce_attr->dest_nentries) { ++ ath12k_ahb_setbit32(ab, ce_id, ie2_reg_addr); ++ ath12k_ahb_setbit32(ab, ce_id + CE_HOST_IE_3_SHIFT, ++ ie3_reg_addr); ++ } ++} ++ ++static void ath12k_ahb_ce_irq_disable(struct ath12k_base *ab, u16 ce_id) ++{ ++ const struct ce_attr *ce_attr; ++ 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; ++ 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) ++ ath12k_ahb_clearbit32(ab, ce_id, ie1_reg_addr); ++ ++ if (ce_attr->dest_nentries) { ++ ath12k_ahb_clearbit32(ab, ce_id, ie2_reg_addr); ++ ath12k_ahb_clearbit32(ab, ce_id + CE_HOST_IE_3_SHIFT, ++ ie3_reg_addr); ++ } ++} ++ ++static void ath12k_ahb_sync_ce_irqs(struct ath12k_base *ab) ++{ ++ int i; ++ int irq_idx; ++ ++ for (i = 0; i < ab->hw_params->ce_count; i++) { ++ if (ath12k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) ++ continue; ++ ++ irq_idx = ATH12K_IRQ_CE0_OFFSET + i; ++ synchronize_irq(ab->irq_num[irq_idx]); ++ } ++} ++ ++static void ath12k_ahb_sync_ext_irqs(struct ath12k_base *ab) ++{ ++ int i, j; ++ int irq_idx; ++ ++ for (i = 0; i < ATH12K_EXT_IRQ_GRP_NUM_MAX; i++) { ++ struct ath12k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; ++ ++ for (j = 0; j < irq_grp->num_irq; j++) { ++ irq_idx = irq_grp->irqs[j]; ++ synchronize_irq(ab->irq_num[irq_idx]); ++ } ++ } ++} ++ ++static void ath12k_ahb_ce_irqs_enable(struct ath12k_base *ab) ++{ ++ int i; ++ ++ for (i = 0; i < ab->hw_params->ce_count; i++) { ++ if (ath12k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) ++ continue; ++ ath12k_ahb_ce_irq_enable(ab, i); ++ } ++} ++ ++static void ath12k_ahb_ce_irqs_disable(struct ath12k_base *ab) ++{ ++ int i; ++ ++ for (i = 0; i < ab->hw_params->ce_count; i++) { ++ if (ath12k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) ++ continue; ++ ath12k_ahb_ce_irq_disable(ab, i); ++ } ++} ++ ++static int ath12k_ahb_start(struct ath12k_base *ab) ++{ ++ ath12k_ahb_ce_irqs_enable(ab); ++ ath12k_ce_rx_post_buf(ab); ++ ++ return 0; ++} ++ ++static void ath12k_ahb_ext_irq_enable(struct ath12k_base *ab) ++{ ++ int i; ++ ++ for (i = 0; i < ATH12K_EXT_IRQ_GRP_NUM_MAX; i++) { ++ struct ath12k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; ++ if (!irq_grp->napi_enabled) { ++ napi_enable(&irq_grp->napi); ++ irq_grp->napi_enabled = true; ++ } ++ ath12k_ahb_ext_grp_enable(irq_grp); ++ } ++} ++ ++static void ath12k_ahb_ext_irq_disable(struct ath12k_base *ab) ++{ ++ __ath12k_ahb_ext_irq_disable(ab); ++ ath12k_ahb_sync_ext_irqs(ab); ++} ++ ++static void ath12k_ahb_stop(struct ath12k_base *ab) ++{ ++ if (!test_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags)) ++ ath12k_ahb_ce_irqs_disable(ab); ++ ath12k_ahb_sync_ce_irqs(ab); ++ ath12k_ahb_kill_tasklets(ab); ++ del_timer_sync(&ab->rx_replenish_retry); ++ ath12k_ce_cleanup_pipes(ab); ++} ++ ++static int ath12k_ahb_power_up(struct ath12k_base *ab) ++{ ++ struct ath12k_ahb *ab_ahb = ath12k_ahb_priv(ab); ++ int ret; ++ ++ ret = rproc_boot(ab_ahb->tgt_rproc); ++ if (ret) ++ ath12k_err(ab, "failed to boot the remote processor Q6\n"); ++ ++ return ret; ++} ++ ++static void ath12k_ahb_power_down(struct ath12k_base *ab) ++{ ++ struct ath12k_ahb *ab_ahb = ath12k_ahb_priv(ab); ++ ++ rproc_shutdown(ab_ahb->tgt_rproc); ++} ++ ++static void ath12k_ahb_init_qmi_ce_config(struct ath12k_base *ab) ++{ ++ struct ath12k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg; ++ ++ cfg->tgt_ce_len = ab->hw_params->target_ce_count; ++ cfg->tgt_ce = ab->hw_params->target_ce_config; ++ 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; ++} ++ ++static void ath12k_ahb_free_ext_irq(struct ath12k_base *ab) ++{ ++ int i, j; ++ ++ for (i = 0; i < ATH12K_EXT_IRQ_GRP_NUM_MAX; i++) { ++ struct ath12k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; ++ ++ for (j = 0; j < irq_grp->num_irq; j++) ++ free_irq(ab->irq_num[irq_grp->irqs[j]], irq_grp); ++ ++ netif_napi_del(&irq_grp->napi); ++ } ++} ++ ++static void ath12k_ahb_free_irq(struct ath12k_base *ab) ++{ ++ int irq_idx; ++ int i; ++ ++ for (i = 0; i < ab->hw_params->ce_count; i++) { ++ if (ath12k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) ++ continue; ++ irq_idx = ATH12K_IRQ_CE0_OFFSET + i; ++ free_irq(ab->irq_num[irq_idx], &ab->ce.ce_pipe[i]); ++ } ++ ++ ath12k_ahb_free_ext_irq(ab); ++} ++ ++static void ath12k_ahb_ce_tasklet(struct tasklet_struct *t) ++{ ++ struct ath12k_ce_pipe *ce_pipe = from_tasklet(ce_pipe, t, intr_tq); ++ ++ ath12k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num); ++ ++ ath12k_ahb_ce_irq_enable(ce_pipe->ab, ce_pipe->pipe_num); ++} ++ ++static irqreturn_t ath12k_ahb_ce_interrupt_handler(int irq, void *arg) ++{ ++ struct ath12k_ce_pipe *ce_pipe = arg; ++ ++ /* last interrupt received for this CE */ ++ ce_pipe->timestamp = jiffies; ++ ++ ath12k_ahb_ce_irq_disable(ce_pipe->ab, ce_pipe->pipe_num); ++ ++ tasklet_schedule(&ce_pipe->intr_tq); ++ ++ return IRQ_HANDLED; ++} ++ ++static int ath12k_ahb_ext_grp_napi_poll(struct napi_struct *napi, int budget) ++{ ++ struct ath12k_ext_irq_grp *irq_grp = container_of(napi, ++ struct ath12k_ext_irq_grp, ++ napi); ++ struct ath12k_base *ab = irq_grp->ab; ++ int work_done; ++ ++ work_done = ath12k_dp_service_srng(ab, irq_grp, budget); ++ if (work_done < budget) { ++ napi_complete_done(napi, work_done); ++ ath12k_ahb_ext_grp_enable(irq_grp); ++ } ++ ++ if (work_done > budget) ++ work_done = budget; ++ ++ return work_done; ++} ++ ++static irqreturn_t ath12k_ahb_ext_interrupt_handler(int irq, void *arg) ++{ ++ struct ath12k_ext_irq_grp *irq_grp = arg; ++ ++ /* last interrupt received for this group */ ++ irq_grp->timestamp = jiffies; ++ ++ ath12k_ahb_ext_grp_disable(irq_grp); ++ ++ napi_schedule(&irq_grp->napi); ++ ++ return IRQ_HANDLED; ++} ++ ++static int ath12k_ahb_config_ext_irq(struct ath12k_base *ab) ++{ ++ int i, j; ++ int irq; ++ int ret; ++ ++ for (i = 0; i < ATH12K_EXT_IRQ_GRP_NUM_MAX; i++) { ++ struct ath12k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; ++ u32 num_irq = 0; ++ ++ irq_grp->ab = ab; ++ irq_grp->grp_id = i; ++ init_dummy_netdev(&irq_grp->napi_ndev); ++ netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi, ++ ath12k_ahb_ext_grp_napi_poll, NAPI_POLL_WEIGHT); ++ ++ for (j = 0; j < ATH12K_EXT_IRQ_NUM_MAX; j++) { ++ if (ab->hw_params->ring_mask->tx[i] & BIT(j)) { ++ irq_grp->irqs[num_irq++] = ++ wbm2host_tx_completions_ring1 - j; ++ } ++ ++ if (ab->hw_params->ring_mask->rx[i] & BIT(j)) { ++ irq_grp->irqs[num_irq++] = ++ reo2host_destination_ring1 - j; ++ } ++ ++ if (ab->hw_params->ring_mask->rx_err[i] & BIT(j)) ++ irq_grp->irqs[num_irq++] = reo2host_exception; ++ ++ if (ab->hw_params->ring_mask->rx_wbm_rel[i] & BIT(j)) ++ irq_grp->irqs[num_irq++] = wbm2host_rx_release; ++ ++ if (ab->hw_params->ring_mask->reo_status[i] & BIT(j)) ++ irq_grp->irqs[num_irq++] = reo2host_status; ++ ++ if (ab->hw_params->ring_mask->rx_mon_dest[i] & BIT(j)) ++ irq_grp->irqs[num_irq++] = rxdma2host_monitor_destination_mac1; ++ ++ } ++ ++ irq_grp->num_irq = num_irq; ++ ++ for (j = 0; j < irq_grp->num_irq; j++) { ++ int irq_idx = irq_grp->irqs[j]; ++ ++ irq = platform_get_irq_byname(ab->pdev, ++ irq_name[irq_idx]); ++ ab->irq_num[irq_idx] = irq; ++ irq_set_status_flags(irq, IRQ_NOAUTOEN | IRQ_DISABLE_UNLAZY); ++ ret = request_irq(irq, ath12k_ahb_ext_interrupt_handler, ++ IRQF_TRIGGER_RISING, ++ irq_name[irq_idx], irq_grp); ++ if (ret) { ++ ath12k_err(ab, "failed request_irq for %d\n", ++ irq); ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++static int ath12k_ahb_config_irq(struct ath12k_base *ab) ++{ ++ int irq, irq_idx, i; ++ int ret; ++ ++ /* Configure CE irqs */ ++ for (i = 0; i < ab->hw_params->ce_count; i++) { ++ struct ath12k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i]; ++ ++ if (ath12k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) ++ continue; ++ ++ irq_idx = ATH12K_IRQ_CE0_OFFSET + i; ++ ++ tasklet_setup(&ce_pipe->intr_tq, ath12k_ahb_ce_tasklet); ++ irq = platform_get_irq_byname(ab->pdev, irq_name[irq_idx]); ++ ret = request_irq(irq, ath12k_ahb_ce_interrupt_handler, ++ IRQF_TRIGGER_RISING, irq_name[irq_idx], ++ ce_pipe); ++ if (ret) ++ return ret; ++ ++ ab->irq_num[irq_idx] = irq; ++ } ++ ++ /* Configure external interrupts */ ++ ret = ath12k_ahb_config_ext_irq(ab); ++ ++ return ret; ++} ++ ++static int ath12k_ahb_map_service_to_pipe(struct ath12k_base *ab, u16 service_id, ++ u8 *ul_pipe, u8 *dl_pipe) ++{ ++ const struct service_to_pipe *entry; ++ bool ul_set = false, dl_set = false; ++ int i; ++ ++ for (i = 0; i < ab->hw_params->svc_to_ce_map_len; i++) { ++ entry = &ab->hw_params->svc_to_ce_map[i]; ++ ++ if (__le32_to_cpu(entry->service_id) != service_id) ++ continue; ++ ++ switch (__le32_to_cpu(entry->pipedir)) { ++ case PIPEDIR_NONE: ++ break; ++ case PIPEDIR_IN: ++ WARN_ON(dl_set); ++ *dl_pipe = __le32_to_cpu(entry->pipenum); ++ dl_set = true; ++ break; ++ case PIPEDIR_OUT: ++ WARN_ON(ul_set); ++ *ul_pipe = __le32_to_cpu(entry->pipenum); ++ ul_set = true; ++ break; ++ case PIPEDIR_INOUT: ++ WARN_ON(dl_set); ++ WARN_ON(ul_set); ++ *dl_pipe = __le32_to_cpu(entry->pipenum); ++ *ul_pipe = __le32_to_cpu(entry->pipenum); ++ dl_set = true; ++ ul_set = true; ++ break; ++ } ++ } ++ ++ if (WARN_ON(!ul_set || !dl_set)) ++ return -ENOENT; ++ ++ return 0; ++} ++ ++static const struct ath12k_hif_ops ath12k_ahb_hif_ops_ipq5332 = { ++ .start = ath12k_ahb_start, ++ .stop = ath12k_ahb_stop, ++ .read32 = ath12k_ahb_read32, ++ .write32 = ath12k_ahb_write32, ++ .cmem_read32 = ath12k_ahb_cmem_read32, ++ .cmem_write32 = ath12k_ahb_cmem_write32, ++ .irq_enable = ath12k_ahb_ext_irq_enable, ++ .irq_disable = ath12k_ahb_ext_irq_disable, ++ .map_service_to_pipe = ath12k_ahb_map_service_to_pipe, ++ .power_down = ath12k_ahb_power_down, ++ .power_up = ath12k_ahb_power_up, ++}; ++ ++ ++static int ath12k_core_get_rproc(struct ath12k_base *ab) ++{ ++ struct ath12k_ahb *ab_ahb = ath12k_ahb_priv(ab); ++ struct device *dev = ab->dev; ++ struct rproc *prproc; ++ phandle rproc_phandle; ++ ++ if (of_property_read_u32(dev->of_node, "qcom,rproc", &rproc_phandle)) { ++ ath12k_err(ab, "failed to get q6_rproc handle\n"); ++ return -ENOENT; ++ } ++ ++ prproc = rproc_get_by_phandle(rproc_phandle); ++ if (!prproc) { ++ ath12k_err(ab, "failed to get rproc\n"); ++ return -EINVAL; ++ } ++ ab_ahb->tgt_rproc = prproc; ++ ++ return 0; ++} ++ ++static int ath12k_ahb_setup_smp2p_handle(struct ath12k_base *ab) ++{ ++ struct ath12k_ahb *ab_ahb = ath12k_ahb_priv(ab); ++ ++ if (!ab->hw_params->smp2p_wow_exit) { ++ return 0; ++ } ++ ++ ab_ahb->smp2p_info.smem_state = qcom_smem_state_get(ab->dev, "wlan-smp2p-out", ++ &ab_ahb->smp2p_info.smem_bit); ++ if (IS_ERR(ab_ahb->smp2p_info.smem_state)) { ++ ath12k_err(ab, "failed to fetch smem state: %ld\n", ++ PTR_ERR(ab_ahb->smp2p_info.smem_state)); ++ return PTR_ERR(ab_ahb->smp2p_info.smem_state); ++ } ++ ++ return 0; ++} ++ ++static void ath12k_ahb_release_smp2p_handle(struct ath12k_base *ab) ++{ ++ struct ath12k_ahb *ab_ahb = ath12k_ahb_priv(ab); ++ ++ if (!ab->hw_params->smp2p_wow_exit) ++ return; ++ ++ qcom_smem_state_put(ab_ahb->smp2p_info.smem_state); ++} ++ ++static int ath12k_ahb_setup_resources(struct ath12k_base *ab) ++{ ++ struct platform_device *pdev = ab->pdev; ++ struct resource *mem_res; ++ void __iomem *mem; ++ ++ ++ mem = devm_platform_get_and_ioremap_resource(pdev, 0, &mem_res); ++ if (IS_ERR(mem)) { ++ dev_err(&pdev->dev, "ioremap error\n"); ++ return PTR_ERR(mem); ++ } ++ ++ ab->mem = mem; ++ ab->mem_len = resource_size(mem_res); ++ ++ return 0; ++} ++ ++static int ath12k_ahb_setup_msa_resources(struct ath12k_base *ab) ++{ ++ struct ath12k_ahb *ab_ahb = ath12k_ahb_priv(ab); ++ struct device *dev = ab->dev; ++ struct device_node *node; ++ struct resource r; ++ int ret; ++ ++ node = of_parse_phandle(dev->of_node, "memory-region", 0); ++ if (!node) ++ return -ENOENT; ++ ++ ret = of_address_to_resource(node, 0, &r); ++ of_node_put(node); ++ if (ret) { ++ dev_err(dev, "failed to resolve msa fixed region\n"); ++ return ret; ++ } ++ ++ ab_ahb->fw.msa_paddr = r.start; ++ ab_ahb->fw.msa_size = resource_size(&r); ++ ++ node = of_parse_phandle(dev->of_node, "memory-region", 1); ++ if (!node) ++ return -ENOENT; ++ ++ ret = of_address_to_resource(node, 0, &r); ++ of_node_put(node); ++ if (ret) { ++ dev_err(dev, "failed to resolve ce fixed region\n"); ++ return ret; ++ } ++ ++ ab_ahb->fw.ce_paddr = r.start; ++ ab_ahb->fw.ce_size = resource_size(&r); ++ ++ return 0; ++} ++ ++static int ath12k_ahb_fw_resources_init(struct ath12k_base *ab) ++{ ++ struct ath12k_ahb *ab_ahb = ath12k_ahb_priv(ab); ++ struct device *host_dev = ab->dev; ++ struct platform_device_info info = {0}; ++ struct iommu_domain *iommu_dom; ++ struct platform_device *pdev; ++ struct device_node *node; ++ int ret; ++ ++ /* Chipsets not requiring MSA need not initialize ++ * MSA resources, return success in such cases. ++ */ ++ if (!ab->hw_params->fixed_fw_mem) ++ return 0; ++ ++ ret = ath12k_ahb_setup_msa_resources(ab); ++ if (ret) { ++ ath12k_err(ab, "failed to setup msa resources\n"); ++ return ret; ++ } ++ ++ node = of_get_child_by_name(host_dev->of_node, "wifi-firmware"); ++ if (!node) { ++ ab_ahb->fw.use_tz = true; ++ return 0; ++ } ++ ++ info.fwnode = &node->fwnode; ++ info.parent = host_dev; ++ info.name = node->name; ++ info.dma_mask = DMA_BIT_MASK(32); ++ ++ pdev = platform_device_register_full(&info); ++ if (IS_ERR(pdev)) { ++ of_node_put(node); ++ return PTR_ERR(pdev); ++ } ++ ++ ret = of_dma_configure(&pdev->dev, node, true); ++ if (ret) { ++ ath12k_err(ab, "dma configure fail: %d\n", ret); ++ goto err_unregister; ++ } ++ ++ ab_ahb->fw.dev = &pdev->dev; ++ ++ iommu_dom = iommu_domain_alloc(&platform_bus_type); ++ if (!iommu_dom) { ++ ath12k_err(ab, "failed to allocate iommu domain\n"); ++ ret = -ENOMEM; ++ goto err_unregister; ++ } ++ ++ ret = iommu_attach_device(iommu_dom, ab_ahb->fw.dev); ++ if (ret) { ++ ath12k_err(ab, "could not attach device: %d\n", ret); ++ goto err_iommu_free; ++ } ++ ++ ret = iommu_map(iommu_dom, ab_ahb->fw.msa_paddr, ++ ab_ahb->fw.msa_paddr, ab_ahb->fw.msa_size, ++ IOMMU_READ | IOMMU_WRITE); ++ if (ret) { ++ ath12k_err(ab, "failed to map firmware region: %d\n", ret); ++ goto err_iommu_detach; ++ } ++ ++ ret = iommu_map(iommu_dom, ab_ahb->fw.ce_paddr, ++ ab_ahb->fw.ce_paddr, ab_ahb->fw.ce_size, ++ IOMMU_READ | IOMMU_WRITE); ++ if (ret) { ++ ath12k_err(ab, "failed to map firmware CE region: %d\n", ret); ++ goto err_iommu_unmap; ++ } ++ ++ ab_ahb->fw.use_tz = false; ++ ab_ahb->fw.iommu_domain = iommu_dom; ++ of_node_put(node); ++ ++ return 0; ++ ++err_iommu_unmap: ++ iommu_unmap(iommu_dom, ab_ahb->fw.msa_paddr, ab_ahb->fw.msa_size); ++ ++err_iommu_detach: ++ iommu_detach_device(iommu_dom, ab_ahb->fw.dev); ++ ++err_iommu_free: ++ iommu_domain_free(iommu_dom); ++ ++err_unregister: ++ platform_device_unregister(pdev); ++ of_node_put(node); ++ ++ return ret; ++} ++ ++static int ath12k_ahb_fw_resource_deinit(struct ath12k_base *ab) ++{ ++ struct ath12k_ahb *ab_ahb = ath12k_ahb_priv(ab); ++ struct iommu_domain *iommu; ++ size_t unmapped_size; ++ ++ /* Chipsets not requiring MSA need not initialize ++ * MSA resources so, deinit of MSA resource is not required. ++ * return success in such cases. ++ */ ++ if (!ab->hw_params->fixed_fw_mem) ++ return 0; ++ ++ if (ab_ahb->fw.use_tz) ++ return 0; ++ ++ iommu = ab_ahb->fw.iommu_domain; ++ ++ unmapped_size = iommu_unmap(iommu, ab_ahb->fw.msa_paddr, ab_ahb->fw.msa_size); ++ if (unmapped_size != ab_ahb->fw.msa_size) ++ ath12k_err(ab, "failed to unmap firmware: %zu\n", ++ unmapped_size); ++ ++ unmapped_size = iommu_unmap(iommu, ab_ahb->fw.ce_paddr, ab_ahb->fw.ce_size); ++ if (unmapped_size != ab_ahb->fw.ce_size) ++ ath12k_err(ab, "failed to unmap firmware CE memory: %zu\n", ++ unmapped_size); ++ ++ iommu_detach_device(iommu, ab_ahb->fw.dev); ++ iommu_domain_free(iommu); ++ ++ platform_device_unregister(to_platform_device(ab_ahb->fw.dev)); ++ ++ return 0; ++} ++ ++static int ath12k_ahb_probe(struct platform_device *pdev) ++{ ++ struct ath12k_base *ab; ++ const struct of_device_id *of_id; ++ const struct ath12k_hif_ops *hif_ops; ++ enum ath12k_hw_rev hw_rev; ++ int ret; ++ ++ of_id = of_match_device(ath12k_ahb_of_match, &pdev->dev); ++ if (!of_id) { ++ dev_err(&pdev->dev, "Failed to find matching device tree id\n"); ++ return -EINVAL; ++ } ++ ++ hw_rev = (enum ath12k_hw_rev)of_id->data; ++ ++ switch (hw_rev) { ++ case ATH12K_HW_IPQ5332_HW10: ++ hif_ops = &ath12k_ahb_hif_ops_ipq5332; ++ break; ++ default: ++ dev_err(&pdev->dev, "Unsupported device type %d\n", hw_rev); ++ return -EOPNOTSUPP; ++ } ++ ++ 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"); ++ return ret; ++ } ++ ++ ab = ath12k_core_alloc(&pdev->dev, sizeof(struct ath12k_ahb), ++ ATH12K_BUS_AHB, &ath12k_ahb_bus_params); ++ if (!ab) { ++ dev_err(&pdev->dev, "failed to allocate ath11k base\n"); ++ return -ENOMEM; ++ } ++ ++ ab->hif.ops = hif_ops; ++ ab->pdev = pdev; ++ ab->hw_rev = hw_rev; ++ platform_set_drvdata(pdev, ab); ++ ++ ++ ret = ath12k_core_pre_init(ab); ++ if (ret) ++ goto err_core_free; ++ ++ if (ab->hw_params->ce_remap) { ++ const struct ce_remap *ce_remap = ab->hw_params->ce_remap; ++ /* ce register space is moved out of wcss unlike ipq8074 or ipq6018 ++ * and the space is not contiguous, hence remapping the CE registers ++ * to a new space for accessing them. ++ */ ++ ab->mem_ce = ioremap(ce_remap->base, ce_remap->size); ++ if (IS_ERR(ab->mem_ce)) { ++ dev_err(&pdev->dev, "ce ioremap error\n"); ++ ret = -ENOMEM; ++ goto err_core_free; ++ } ++ ab->ce_remap = true; ++ ab->ce_remap_base_addr = HAL_IPQ5332_CE_WFSS_REG_BASE; ++ } ++ if (ab->hw_params->cmem) { ++ const struct ce_remap *cmem = ab->hw_params->cmem; ++ /* ++ * In IPQ5332 CMEM region is outside WCSS block. ++ * Allocate separate I/O remap to access CMEM address. ++ */ ++ ab->mem_cmem = ioremap(cmem->base, cmem->size); ++ if (IS_ERR(ab->mem_cmem)) { ++ dev_err(&pdev->dev, "cmem ioremap error\n"); ++ ret = -ENOMEM; ++ goto err_core_free; ++ } ++ ab->cmem_remap = true; ++ ab->cmem_remap_base_addr = HAL_IPQ5332_CMEM_REG_BASE; ++ } ++ ++ ret = ath12k_ahb_setup_resources(ab); ++ if (ret) ++ goto err_core_free; ++ ++ ret = ath12k_ahb_fw_resources_init(ab); ++ if (ret) ++ goto err_core_free; ++ ++ ret = ath12k_ahb_setup_smp2p_handle(ab); ++ if (ret) ++ goto err_fw_deinit; ++ ++ ret = ath12k_hal_srng_init(ab); ++ if (ret) ++ goto err_release_smp2p_handle; ++ ++ ret = ath12k_ce_alloc_pipes(ab); ++ if (ret) { ++ ath12k_err(ab, "failed to allocate ce pipes: %d\n", ret); ++ goto err_hal_srng_deinit; ++ } ++ ++ ath12k_ahb_init_qmi_ce_config(ab); ++ ++ ret = ath12k_core_get_rproc(ab); ++ if (ret) { ++ ath12k_err(ab, "failed to get rproc: %d\n", ret); ++ goto err_ce_free; ++ } ++ ++ ret = ath12k_core_init(ab); ++ if (ret) { ++ ath12k_err(ab, "failed to init core: %d\n", ret); ++ goto err_ce_free; ++ } ++ ++ ret = ath12k_ahb_config_irq(ab); ++ if (ret) { ++ ath12k_err(ab, "failed to configure irq: %d\n", ret); ++ goto err_ce_free; ++ } ++ ++ return 0; ++ ++err_ce_free: ++ ath12k_ce_free_pipes(ab); ++ ++err_hal_srng_deinit: ++ ath12k_hal_srng_deinit(ab); ++ ++err_release_smp2p_handle: ++ ath12k_ahb_release_smp2p_handle(ab); ++ ++err_fw_deinit: ++ ath12k_ahb_fw_resource_deinit(ab); ++ ++err_core_free: ++ ath12k_core_free(ab); ++ platform_set_drvdata(pdev, NULL); ++ ++ return ret; ++} ++ ++static void ath12k_ahb_remove_prepare(struct ath12k_base *ab) ++{ ++ unsigned long left; ++ ++ if (test_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags)) { ++ left = wait_for_completion_timeout(&ab->driver_recovery, ++ ATH12K_AHB_RECOVERY_TIMEOUT); ++ if (!left) ++ ath12k_warn(ab, "failed to receive recovery response completion\n"); ++ } ++ ++ set_bit(ATH12K_FLAG_UNREGISTERING, &ab->dev_flags); ++ cancel_work_sync(&ab->restart_work); ++ cancel_work_sync(&ab->qmi.event_work); ++} ++ ++static void ath12k_ahb_free_resources(struct ath12k_base *ab) ++{ ++ struct platform_device *pdev = ab->pdev; ++ ++ ath12k_ahb_free_irq(ab); ++ ath12k_hal_srng_deinit(ab); ++ ath12k_ahb_release_smp2p_handle(ab); ++ ath12k_ahb_fw_resource_deinit(ab); ++ ath12k_ce_free_pipes(ab); ++ ++ if (ab->hw_params->ce_remap) ++ iounmap(ab->mem_ce); ++ ++ ath12k_core_free(ab); ++ platform_set_drvdata(pdev, NULL); ++} ++ ++static int ath12k_ahb_remove(struct platform_device *pdev) ++{ ++ struct ath12k_base *ab = platform_get_drvdata(pdev); ++ ++ if (test_bit(ATH12K_FLAG_QMI_FAIL, &ab->dev_flags)) { ++ ath12k_ahb_power_down(ab); ++ ath12k_debugfs_soc_destroy(ab); ++ ath12k_qmi_deinit_service(ab); ++ goto qmi_fail; ++ } ++ ++ ath12k_ahb_remove_prepare(ab); ++ ath12k_core_deinit(ab); ++ ++qmi_fail: ++ ath12k_ahb_free_resources(ab); ++ ++ return 0; ++} ++ ++static void ath12k_ahb_shutdown(struct platform_device *pdev) ++{ ++ struct ath12k_base *ab = platform_get_drvdata(pdev); ++ ++ /* platform shutdown() & remove() are mutually exclusive. ++ * remove() is invoked during rmmod & shutdown() during ++ * system reboot/shutdown. ++ */ ++ ath12k_ahb_remove_prepare(ab); ++ ++ if (!(test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags))) ++ goto free_resources; ++ ++ ath12k_core_deinit(ab); ++ ++free_resources: ++ ath12k_ahb_free_resources(ab); ++} ++ ++static struct platform_driver ath12k_ahb_driver = { ++ .driver = { ++ .name = "ath12k_ahb", ++ .of_match_table = ath12k_ahb_of_match, ++ }, ++ .probe = ath12k_ahb_probe, ++ .remove = ath12k_ahb_remove, ++ .shutdown = ath12k_ahb_shutdown, ++}; ++ ++int ath12k_ahb_init(void) ++{ ++ return platform_driver_register(&ath12k_ahb_driver); ++} ++ ++void ath12k_ahb_exit(void) ++{ ++ platform_driver_unregister(&ath12k_ahb_driver); ++} ++ +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/ahb.h +@@ -0,0 +1,54 @@ ++/* SPDX-License-Identifier: BSD-3-Clause-Clear */ ++/* ++ * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++#ifndef ATH12K_AHB_H ++#define ATH12K_AHB_H ++ ++#include "core.h" ++ ++#define ATH12K_AHB_RECOVERY_TIMEOUT (3 * HZ) ++ ++#define ATH12K_AHB_SMP2P_SMEM_MSG GENMASK(15, 0) ++#define ATH12K_AHB_SMP2P_SMEM_SEQ_NO GENMASK(31, 16) ++#define ATH12K_AHB_SMP2P_SMEM_VALUE_MASK 0xFFFFFFFF ++#define ATH12K_PCI_CE_WAKE_IRQ 2 ++#define ATH12K_PCI_IRQ_CE0_OFFSET 3 ++ ++enum ath12k_ahb_smp2p_msg_id { ++ ATH12K_AHB_POWER_SAVE_ENTER = 1, ++ ATH12K_AHB_POWER_SAVE_EXIT, ++}; ++ ++struct ath12k_base; ++ ++struct ath12k_ahb { ++ struct rproc *tgt_rproc; ++ struct { ++ struct device *dev; ++ struct iommu_domain *iommu_domain; ++ dma_addr_t msa_paddr; ++ u32 msa_size; ++ dma_addr_t ce_paddr; ++ u32 ce_size; ++ bool use_tz; ++ } fw; ++ struct { ++ unsigned short seq_no; ++ unsigned int smem_bit; ++ struct qcom_smem_state *smem_state; ++ } smp2p_info; ++}; ++ ++static inline struct ath12k_ahb *ath12k_ahb_priv(struct ath12k_base *ab) ++{ ++ return (struct ath12k_ahb *)ab->drv_priv; ++} ++ ++static const struct ath12k_bus_params ath12k_ahb_bus_params = { ++ .fixed_bdf_addr = false, ++ .fixed_mem_region = true, ++}; ++ ++#endif +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -162,6 +162,7 @@ struct ath12k_ext_irq_grp { + u32 num_irq; + u32 grp_id; + u64 timestamp; ++ bool napi_enabled; + struct napi_struct napi; + struct net_device napi_ndev; + }; +--- a/drivers/net/wireless/ath/ath12k/debug.h ++++ b/drivers/net/wireless/ath/ath12k/debug.h +@@ -26,6 +26,7 @@ enum ath12k_debug_mask { + ATH12K_DBG_PCI = 0x00001000, + ATH12K_DBG_DP_TX = 0x00002000, + ATH12K_DBG_DP_RX = 0x00004000, ++ ATH12K_DBG_OFFSET = 0x00008000, + ATH12K_DBG_ANY = 0xffffffff, + }; + diff --git a/feeds/ipq95xx/mac80211/patches/qca/710-002-ath12k-ath12k-Move-ath12k-module-initialization-to-c.patch b/feeds/ipq95xx/mac80211/patches/qca/710-002-ath12k-ath12k-Move-ath12k-module-initialization-to-c.patch new file mode 100644 index 000000000..279b41a8d --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/710-002-ath12k-ath12k-Move-ath12k-module-initialization-to-c.patch @@ -0,0 +1,148 @@ +From bc45a49360485b1d196253a48655d50645b7c831 Mon Sep 17 00:00:00 2001 +From: Balamurugan S +Date: Tue, 31 Jan 2023 00:09:11 +0530 +Subject: [PATCH 2/8] ath12k: Move module initialization to core.c + +Move ath12k module initialization to core.c file. PCIe and AHB +specific inits and functionality will be in respective driver files and both +driver is initialized from the ath12k module. + +Signed-off-by: Balamurugan S +Signed-off-by: Aloka Dixit +--- + drivers/net/wireless/ath/ath12k/core.c | 47 +++++++++++++++++++++++++- + drivers/net/wireless/ath/ath12k/core.h | 15 ++++++++ + drivers/net/wireless/ath/ath12k/pci.c | 20 ++--------- + 3 files changed, 63 insertions(+), 19 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -1857,5 +1857,49 @@ err_sc_free: + return NULL; + } + +-MODULE_DESCRIPTION("Core module for Qualcomm Atheros 802.11be wireless LAN cards."); ++static int ath12k_init(void) ++{ ++ int ret; ++ ++ ret = ath12k_debugfs_create(); ++ if (ret) { ++ pr_err("Failed to register debugfs ath12k driver: %d\n", ret); ++ return ret; ++ } ++ ++ ret = ath12k_ahb_init(); ++ if (ret) { ++ ret = -ENODEV; ++ pr_err("Failed to initialize ath12k AHB device: %d\n", ret); ++ goto error; ++ } ++ ++ ret = ath12k_pci_init(); ++ if (ret) { ++ ret = -ENODEV; ++ pr_err("Failed to initialize ath12k PCI device: %d\n", ret); ++ goto error_ahb; ++ } ++ ++ return 0; ++ ++error_ahb: ++ ath12k_ahb_exit(); ++error: ++ ath12k_debugfs_destroy(); ++ ++ return ret; ++} ++ ++static void ath12k_exit(void) ++{ ++ ath12k_pci_exit(); ++ ath12k_ahb_exit(); ++ ath12k_debugfs_destroy(); ++} ++ ++module_init(ath12k_init) ++module_exit(ath12k_exit) ++ ++MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11be WLAN PCIe/AHB devices"); + MODULE_LICENSE("Dual BSD/GPL"); +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -1407,4 +1407,19 @@ static inline const char *ath12k_bus_str + + return "unknown"; + } ++ ++int ath12k_pci_init(void); ++void ath12k_pci_exit(void); ++#ifdef CPTCFG_ATH12K_AHB ++int ath12k_ahb_init(void); ++void ath12k_ahb_exit(void); ++#else ++static inline int ath12k_ahb_init(void) ++{ ++ return 0; ++}; ++ ++static inline void ath12k_ahb_exit(void) {}; ++#endif ++ + #endif /* _CORE_H_ */ +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -1450,36 +1450,20 @@ static struct pci_driver ath12k_pci_driv + #endif + }; + +-static int ath12k_pci_init(void) ++int ath12k_pci_init(void) + { + int ret; + +- ret = ath12k_debugfs_create(); +- if (ret) +- pr_info("failed to register debugfs ath12k driver: %d\n", ret); +- + ret = pci_register_driver(&ath12k_pci_driver); + if (ret) { + pr_err("failed to register ath12k pci driver: %d\n", + ret); +- goto err; + } + +- return 0; +- +-err: +- ath12k_debugfs_destroy(); + return ret; + } +-module_init(ath12k_pci_init); + +-static void ath12k_pci_exit(void) ++void ath12k_pci_exit(void) + { + pci_unregister_driver(&ath12k_pci_driver); +- ath12k_debugfs_destroy(); + } +- +-module_exit(ath12k_pci_exit); +- +-MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11be WLAN PCIe devices"); +-MODULE_LICENSE("Dual BSD/GPL"); +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -1270,6 +1270,12 @@ int ath12k_debugfs_soc_create(struct ath + + void ath12k_debugfs_soc_destroy(struct ath12k_base *ab) + { ++ if (!debugfs_ath12k) { ++ /* ath12k_debugfs_destroy() already removed this directory */ ++ ab->debugfs_soc = NULL; ++ return; ++ } ++ + debugfs_remove_recursive(ab->debugfs_soc); + ab->debugfs_soc = NULL; + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/710-003-ath12k-Add-IPQ5332-CE-config-changes.patch b/feeds/ipq95xx/mac80211/patches/qca/710-003-ath12k-Add-IPQ5332-CE-config-changes.patch new file mode 100644 index 000000000..4d1ebf967 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/710-003-ath12k-Add-IPQ5332-CE-config-changes.patch @@ -0,0 +1,452 @@ +From d1b56c645568eca1911f50ef1a7323f7aff37ef9 Mon Sep 17 00:00:00 2001 +From: Balamurugan S +Date: Tue, 31 Jan 2023 00:22:06 +0530 +Subject: [PATCH 3/8] ath12k: Add IPQ5332 CE config changes + +Add copy engine (CE) configs for ipq5332. The total number of CE's for ipq5332 +is 12 and configurations of CE is defined below. + +CE0: host->target HTC control and raw streams +CE1: target->host HTT + HTC control +CE2: target->host WMI +CE3: host->target WMI +CE4: host->target HTT +CE5: target -> host PKTLOG +CE6: Target autonomous HIF_memcpy +CE7: CV Prefetch +CE8: Target HIF memcpy (Generic HIF memcypy) +CE9: WMI logging/CFR/Spectral/Radar +CE10: Unused +CE11: Unused + +Signed-off-by: Balamurugan S +--- + drivers/net/wireless/ath/ath12k/ce.c | 92 +++++++++++ + drivers/net/wireless/ath/ath12k/ce.h | 21 ++- + drivers/net/wireless/ath/ath12k/hal.h | 8 + + drivers/net/wireless/ath/ath12k/hw.c | 227 ++++++++++++++++++++++++++ + 4 files changed, 346 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/ce.c b/drivers/net/wireless/ath/ath12k/ce.c +index fd8f707..07e7136 100644 +--- a/drivers/net/wireless/ath/ath12k/ce.c ++++ b/drivers/net/wireless/ath/ath12k/ce.c +@@ -229,6 +229,98 @@ const struct ce_attr ath12k_host_ce_config_wcn7850[] = { + + }; + ++const struct ce_attr ath12k_host_ce_config_ipq5332[] = { ++ /* CE0: host->target HTC control and raw streams */ ++ { ++ .flags = CE_ATTR_FLAGS, ++ .src_nentries = 16, ++ .src_sz_max = 2048, ++ .dest_nentries = 0, ++ }, ++ /* CE1: target->host HTT + HTC control */ ++ { ++ .flags = CE_ATTR_FLAGS, ++ .src_nentries = 0, ++ .src_sz_max = 2048, ++ .dest_nentries = 512, ++ .recv_cb = ath12k_htc_rx_completion_handler, ++ }, ++ /* CE2: target->host WMI */ ++ { ++ .flags = CE_ATTR_FLAGS, ++ .src_nentries = 0, ++ .src_sz_max = 2048, ++ .dest_nentries = 128, ++ .recv_cb = ath12k_htc_rx_completion_handler, ++ }, ++ /* CE3: host->target WMI */ ++ { ++ .flags = CE_ATTR_FLAGS, ++ .src_nentries = 32, ++ .src_sz_max = 2048, ++ .dest_nentries = 0, ++ .send_cb = ath12k_htc_tx_completion_handler, ++ }, ++ /* CE4: host->target HTT */ ++ { ++ .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR, ++ .src_nentries = 2048, ++ .src_sz_max = 256, ++ .dest_nentries = 0, ++ }, ++ /* CE5: target -> host PKTLOG */ ++ { ++ .flags = CE_ATTR_FLAGS, ++ .src_nentries = 0, ++ .src_sz_max = 2048, ++ .dest_nentries = 512, ++ .recv_cb = ath12k_dp_htt_htc_t2h_msg_handler, ++ }, ++ /* CE6: Target autonomous HIF_memcpy */ ++ { ++ .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR, ++ .src_nentries = 0, ++ .src_sz_max = 0, ++ .dest_nentries = 0, ++ }, ++ /* CE7: CV Prefetch */ ++ { ++ .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR, ++ .src_nentries = 0, ++ .src_sz_max = 0, ++ .dest_nentries = 0, ++ .send_cb = ath12k_htc_tx_completion_handler, ++ }, ++ /* CE8: Target HIF memcpy (Generic HIF memcypy) */ ++ { ++ .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR, ++ .src_nentries = 0, ++ .src_sz_max = 0, ++ .dest_nentries = 0, ++ }, ++ /* CE9: WMI logging/CFR/Spectral/Radar */ ++ { ++ .flags = CE_ATTR_FLAGS, ++ .src_nentries = 0, ++ .src_sz_max = 2048, ++ .dest_nentries = 128, ++ }, ++ /* CE10: Unused */ ++ { ++ .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR, ++ .src_nentries = 0, ++ .src_sz_max = 0, ++ .dest_nentries = 0, ++ }, ++ /* CE11: Unused */ ++ { ++ .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR, ++ .src_nentries = 0, ++ .src_sz_max = 0, ++ .dest_nentries = 0, ++ }, ++}; ++ + static int ath12k_ce_rx_buf_enqueue_pipe(struct ath12k_ce_pipe *pipe, + struct sk_buff *skb, dma_addr_t paddr) + { +diff --git a/drivers/net/wireless/ath/ath12k/ce.h b/drivers/net/wireless/ath/ath12k/ce.h +index 4a74b39..e951736 100644 +--- a/drivers/net/wireless/ath/ath12k/ce.h ++++ b/drivers/net/wireless/ath/ath12k/ce.h +@@ -45,8 +45,8 @@ void ath12k_ce_byte_swap(void *mem, u32 len); + #define PIPEDIR_INOUT_H2H 4 /* bidirectional, host to host */ + + /* CE address/mask */ +-#define CE_HOST_IE_ADDRESS 0x00A1803C +-#define CE_HOST_IE_2_ADDRESS 0x00A18040 ++#define CE_HOST_IE_ADDRESS 0x75804c ++#define CE_HOST_IE_2_ADDRESS 0x758050 + #define CE_HOST_IE_3_ADDRESS CE_HOST_IE_ADDRESS + + #define CE_HOST_IE_3_SHIFT 0xC +@@ -82,6 +82,22 @@ struct ce_pipe_config { + __le32 reserved; + }; + ++struct ce_ie_addr { ++ u32 ie1_reg_addr; ++ u32 ie2_reg_addr; ++ u32 ie3_reg_addr; ++}; ++ ++struct ce_remap { ++ u32 base; ++ u32 size; ++}; ++ ++struct ath12k_cmem { ++ u32 base; ++ u32 size; ++}; ++ + struct ce_attr { + /* CE_ATTR_* values */ + unsigned int flags; +@@ -172,6 +188,7 @@ struct ath12k_ce { + + extern const struct ce_attr ath12k_host_ce_config_qcn9274[]; + extern const struct ce_attr ath12k_host_ce_config_wcn7850[]; ++extern const struct ce_attr ath12k_host_ce_config_ipq5332[]; + + void ath12k_ce_cleanup_pipes(struct ath12k_base *ab); + void ath12k_ce_rx_replenish_retry(struct timer_list *t); +diff --git a/drivers/net/wireless/ath/ath12k/hal.h b/drivers/net/wireless/ath/ath12k/hal.h +index d32090a..a843f38 100644 +--- a/drivers/net/wireless/ath/ath12k/hal.h ++++ b/drivers/net/wireless/ath/ath12k/hal.h +@@ -11,6 +11,7 @@ + #include "rx_desc.h" + + struct ath12k_base; ++#define HAL_CE_REMAP_REG_BASE (ab->ce_remap_base_addr) + + #define HAL_LINK_DESC_SIZE (32 << 2) + #define HAL_LINK_DESC_ALIGN 128 +@@ -388,6 +389,13 @@ struct ath12k_base; + * ath12k_hal_rx_desc_get_err(). + */ + ++#define HAL_IPQ5332_CE_WFSS_REG_BASE 0x740000 ++#define HAL_IPQ5332_CE_SIZE 0x200000 ++ ++#define HAL_IPQ5332_CMEM_REG_BASE 0xC100000 ++#define HAL_IPQ5332_CMEM_SIZE 0x40000 ++#define HAL_IPQ5332_CMEM_BASE 0x100000 ++ + enum hal_srng_ring_id { + HAL_SRNG_RING_ID_REO2SW0 = 0, + HAL_SRNG_RING_ID_REO2SW1, +diff --git a/drivers/net/wireless/ath/ath12k/hw.c b/drivers/net/wireless/ath/ath12k/hw.c +index ba55a02..7305baa 100644 +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -533,6 +533,217 @@ static const struct service_to_pipe ath12k_target_service_to_ce_map_wlan_wcn7850 + }, + }; + ++static const struct ce_pipe_config ath12k_target_ce_config_wlan_ipq5332[] = { ++ /* host->target HTC control and raw streams */ ++ { ++ .pipenum = __cpu_to_le32(0), ++ .pipedir = __cpu_to_le32(PIPEDIR_OUT), ++ .nentries = __cpu_to_le32(32), ++ .nbytes_max = __cpu_to_le32(2048), ++ .flags = __cpu_to_le32(CE_ATTR_FLAGS), ++ .reserved = __cpu_to_le32(0), ++ }, ++ /* target->host HTT */ ++ { ++ .pipenum = __cpu_to_le32(1), ++ .pipedir = __cpu_to_le32(PIPEDIR_IN), ++ .nentries = __cpu_to_le32(32), ++ .nbytes_max = __cpu_to_le32(2048), ++ .flags = __cpu_to_le32(CE_ATTR_FLAGS), ++ .reserved = __cpu_to_le32(0), ++ }, ++ /* target->host WMI + HTC control */ ++ { ++ .pipenum = __cpu_to_le32(2), ++ .pipedir = __cpu_to_le32(PIPEDIR_IN), ++ .nentries = __cpu_to_le32(32), ++ .nbytes_max = __cpu_to_le32(2048), ++ .flags = __cpu_to_le32(CE_ATTR_FLAGS), ++ .reserved = __cpu_to_le32(0), ++ }, ++ /* host->target WMI */ ++ { ++ .pipenum = __cpu_to_le32(3), ++ .pipedir = __cpu_to_le32(PIPEDIR_OUT), ++ .nentries = __cpu_to_le32(32), ++ .nbytes_max = __cpu_to_le32(2048), ++ .flags = __cpu_to_le32(CE_ATTR_FLAGS), ++ .reserved = __cpu_to_le32(0), ++ }, ++ /* host->target HTT */ ++ { ++ .pipenum = __cpu_to_le32(4), ++ .pipedir = __cpu_to_le32(PIPEDIR_OUT), ++ .nentries = __cpu_to_le32(256), ++ .nbytes_max = __cpu_to_le32(256), ++ .flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR), ++ .reserved = __cpu_to_le32(0), ++ }, ++ /* Target -> host PKTLOG */ ++ { ++ .pipenum = __cpu_to_le32(5), ++ .pipedir = __cpu_to_le32(PIPEDIR_IN), ++ .nentries = __cpu_to_le32(32), ++ .nbytes_max = __cpu_to_le32(2048), ++ .flags = __cpu_to_le32(CE_ATTR_FLAGS), ++ .reserved = __cpu_to_le32(0), ++ }, ++ /* Reserved for target autonomous HIF_memcpy */ ++ { ++ .pipenum = __cpu_to_le32(6), ++ .pipedir = __cpu_to_le32(PIPEDIR_INOUT), ++ .nentries = __cpu_to_le32(32), ++ .nbytes_max = __cpu_to_le32(16384), ++ .flags = __cpu_to_le32(CE_ATTR_FLAGS), ++ .reserved = __cpu_to_le32(0), ++ }, ++ /* CE7 Reserved for CV Prefetch */ ++ { ++ .pipenum = __cpu_to_le32(7), ++ .pipedir = __cpu_to_le32(PIPEDIR_OUT), ++ .nentries = __cpu_to_le32(32), ++ .nbytes_max = __cpu_to_le32(2048), ++ .flags = __cpu_to_le32(CE_ATTR_FLAGS), ++ .reserved = __cpu_to_le32(0), ++ }, ++ /* CE8 Reserved for target generic HIF memcpy */ ++ { ++ .pipenum = __cpu_to_le32(8), ++ .pipedir = __cpu_to_le32(PIPEDIR_INOUT), ++ .nentries = __cpu_to_le32(32), ++ .nbytes_max = __cpu_to_le32(16384), ++ .flags = __cpu_to_le32(CE_ATTR_FLAGS), ++ .reserved = __cpu_to_le32(0), ++ }, ++ /* CE9 WMI logging/CFR/Spectral/Radar/ */ ++ { ++ .pipenum = __cpu_to_le32(9), ++ .pipedir = __cpu_to_le32(PIPEDIR_IN), ++ .nentries = __cpu_to_le32(32), ++ .nbytes_max = __cpu_to_le32(2048), ++ .flags = __cpu_to_le32(CE_ATTR_FLAGS), ++ .reserved = __cpu_to_le32(0), ++ }, ++ /* Unused TBD */ ++ { ++ .pipenum = __cpu_to_le32(10), ++ .pipedir = __cpu_to_le32(PIPEDIR_NONE), ++ .nentries = __cpu_to_le32(0), ++ .nbytes_max = __cpu_to_le32(0), ++ .flags = __cpu_to_le32(0), ++ .reserved = __cpu_to_le32(0), ++ }, ++ /* Unused TBD */ ++ { ++ .pipenum = __cpu_to_le32(11), ++ .pipedir = __cpu_to_le32(PIPEDIR_NONE), ++ .nentries = __cpu_to_le32(0), ++ .nbytes_max = __cpu_to_le32(0), ++ .flags = __cpu_to_le32(0), ++ .reserved = __cpu_to_le32(0), ++ }, ++}; ++ ++static const struct service_to_pipe ath12k_target_service_to_ce_map_wlan_ipq5332[] = { ++ { ++ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VO), ++ __cpu_to_le32(PIPEDIR_OUT), ++ __cpu_to_le32(3), ++ }, ++ { ++ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VO), ++ __cpu_to_le32(PIPEDIR_IN), ++ __cpu_to_le32(2), ++ }, ++ { ++ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BK), ++ __cpu_to_le32(PIPEDIR_OUT), ++ __cpu_to_le32(3), ++ }, ++ { ++ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BK), ++ __cpu_to_le32(PIPEDIR_IN), ++ __cpu_to_le32(2), ++ }, ++ { ++ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BE), ++ __cpu_to_le32(PIPEDIR_OUT), ++ __cpu_to_le32(3), ++ }, ++ { ++ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_BE), ++ __cpu_to_le32(PIPEDIR_IN), ++ __cpu_to_le32(2), ++ }, ++ { ++ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VI), ++ __cpu_to_le32(PIPEDIR_OUT), ++ __cpu_to_le32(3), ++ }, ++ { ++ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_DATA_VI), ++ __cpu_to_le32(PIPEDIR_IN), ++ __cpu_to_le32(2), ++ }, ++ { ++ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_CONTROL), ++ __cpu_to_le32(PIPEDIR_OUT), ++ __cpu_to_le32(3), ++ }, ++ { ++ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_CONTROL), ++ __cpu_to_le32(PIPEDIR_IN), ++ __cpu_to_le32(2), ++ }, ++ { ++ __cpu_to_le32(ATH12K_HTC_SVC_ID_RSVD_CTRL), ++ __cpu_to_le32(PIPEDIR_OUT), ++ __cpu_to_le32(0), ++ }, ++ { ++ __cpu_to_le32(ATH12K_HTC_SVC_ID_RSVD_CTRL), ++ __cpu_to_le32(PIPEDIR_IN), ++ __cpu_to_le32(1), ++ }, ++ { ++ __cpu_to_le32(ATH12K_HTC_SVC_ID_TEST_RAW_STREAMS), ++ __cpu_to_le32(PIPEDIR_OUT), ++ __cpu_to_le32(0), ++ }, ++ { ++ __cpu_to_le32(ATH12K_HTC_SVC_ID_TEST_RAW_STREAMS), ++ __cpu_to_le32(PIPEDIR_IN), ++ __cpu_to_le32(1), ++ }, ++ { ++ __cpu_to_le32(ATH12K_HTC_SVC_ID_HTT_DATA_MSG), ++ __cpu_to_le32(PIPEDIR_OUT), ++ __cpu_to_le32(4), ++ }, ++ { ++ __cpu_to_le32(ATH12K_HTC_SVC_ID_HTT_DATA_MSG), ++ __cpu_to_le32(PIPEDIR_IN), ++ __cpu_to_le32(1), ++ }, ++ { ++ __cpu_to_le32(ATH12K_HTC_SVC_ID_PKT_LOG), ++ __cpu_to_le32(PIPEDIR_IN), ++ __cpu_to_le32(5), ++ }, ++ { ++ __cpu_to_le32(ATH12K_HTC_SVC_ID_WMI_CONTROL_DIAG), ++ __cpu_to_le32(PIPEDIR_IN), ++ __cpu_to_le32(9), ++ }, ++ /* (Additions here) */ ++ ++ { /* must be last */ ++ __cpu_to_le32(0), ++ __cpu_to_le32(0), ++ __cpu_to_le32(0), ++ }, ++}; ++ + static const struct ath12k_hw_ring_mask ath12k_hw_ring_mask_qcn9274 = { + .tx = { + ATH12K_TX_RING_MASK_0, +@@ -953,6 +1164,22 @@ static const char ath12k_hw_qdss_config_wcn7850[] = { + "seq_end;\n" + }; + ++const struct ce_ie_addr ath12k_ce_ie_addr_ipq5332 = { ++ .ie1_reg_addr = CE_HOST_IE_ADDRESS, ++ .ie2_reg_addr = CE_HOST_IE_2_ADDRESS, ++ .ie3_reg_addr = CE_HOST_IE_3_ADDRESS, ++}; ++ ++const struct ce_remap ath12k_ce_remap_ipq5332 = { ++ .base = HAL_IPQ5332_CE_WFSS_REG_BASE, ++ .size = HAL_IPQ5332_CE_SIZE, ++}; ++ ++const struct ath12k_cmem ath12k_cmem_ipq5332 = { ++ .base = HAL_IPQ5332_CMEM_REG_BASE, ++ .size = HAL_IPQ5332_CMEM_SIZE, ++}; ++ + static const struct ath12k_hw_params ath12k_hw_params[] = { + { + .name = "qcn9274 hw1.0", +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/710-004-ath12k-Add-and-initialize-hw-params-for-IPQ5332.patch b/feeds/ipq95xx/mac80211/patches/qca/710-004-ath12k-Add-and-initialize-hw-params-for-IPQ5332.patch new file mode 100644 index 000000000..77b74c44c --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/710-004-ath12k-Add-and-initialize-hw-params-for-IPQ5332.patch @@ -0,0 +1,479 @@ +From d24ba113bb7c92fd5c9e87facf5d423e0ce5fdf9 Mon Sep 17 00:00:00 2001 +From: Balamurugan S +Date: Tue, 31 Jan 2023 00:25:41 +0530 +Subject: [PATCH 4/8] ath12k: Add and initialize hw params for IPQ5332 + +Add and initialize hw params structure for IPQ5332. The hardware capabilities +and supported features are defined in this structure. + +Signed-off-by: Balamurugan S +Signed-off-by: Sidhanta Sahu +--- + drivers/net/wireless/ath/ath12k/core.h | 11 +- + drivers/net/wireless/ath/ath12k/dp_rx.c | 2 +- + drivers/net/wireless/ath/ath12k/hw.c | 178 +++++++++++++++++++++- + drivers/net/wireless/ath/ath12k/hw.h | 9 +- + drivers/net/wireless/ath/ath12k/qmi.h | 3 +- + drivers/net/wireless/ath/ath12k/rx_desc.h | 2 +- + drivers/net/wireless/ath/ath12k/wmi.c | 63 +++++++- + drivers/net/wireless/ath/ath12k/wmi.h | 4 +- + 8 files changed, 264 insertions(+), 8 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -1,7 +1,7 @@ + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ + /* + * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. +- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #ifndef ATH12K_CORE_H +@@ -136,6 +136,7 @@ enum ath12k_hw_rev { + ATH12K_HW_QCN9274_HW10 = 0, + ATH12K_HW_QCN9274_HW20, + ATH12K_HW_WCN7850_HW20, ++ ATH12K_HW_IPQ5332_HW10, + }; + + #define ATH12K_DIAG_HW_ID_OFFSET 16 +@@ -1097,6 +1098,12 @@ struct ath12k_base { + struct ath12k_dp dp; + + void __iomem *mem; ++ void __iomem *mem_ce; ++ void __iomem *mem_cmem; ++ u32 ce_remap_base_addr; ++ u32 cmem_remap_base_addr; ++ bool ce_remap; ++ bool cmem_remap; + unsigned long mem_len; + + struct { +@@ -1417,6 +1424,8 @@ static inline const char *ath12k_bus_str + switch (bus) { + case ATH12K_BUS_PCI: + return "pci"; ++ case ATH12K_BUS_AHB: ++ return "ahb"; + } + + return "unknown"; +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: BSD-3-Clause-Clear + /* + * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. +- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: BSD-3-Clause-Clear + /* + * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. +- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include +@@ -44,6 +44,37 @@ static bool ath12k_dp_srng_is_comp_ring_ + return false; + } + ++static u8 ath12k_hw_ipq5332_mac_from_pdev_id(int pdev_idx) ++{ ++ return pdev_idx; ++} ++ ++static int ath12k_hw_mac_id_to_pdev_id_ipq5332(const struct ath12k_hw_params *hw, ++ int mac_id) ++{ ++ return mac_id; ++} ++ ++static int ath12k_hw_mac_id_to_srng_id_ipq5332(const struct ath12k_hw_params *hw, ++ int mac_id) ++{ ++ return 0; ++} ++ ++static u8 ath12k_hw_get_ring_selector_ipq5332(struct sk_buff *skb) ++{ ++ return smp_processor_id(); ++} ++ ++static bool ath12k_dp_srng_is_comp_ring_ipq5332(int ring_num) ++{ ++ if (ring_num < 3 || ring_num == 4) ++ return true; ++ ++ return false; ++} ++ ++ + static int ath12k_hw_mac_id_to_pdev_id_wcn7850(const struct ath12k_hw_params *hw, + int mac_id) + { +@@ -87,9 +118,20 @@ static const struct ath12k_hw_ops wcn785 + .dp_srng_is_tx_comp_ring = ath12k_dp_srng_is_comp_ring_wcn7850, + }; + ++static const struct ath12k_hw_ops ipq5332_ops = { ++ .get_hw_mac_from_pdev_id = ath12k_hw_ipq5332_mac_from_pdev_id, ++ .mac_id_to_pdev_id = ath12k_hw_mac_id_to_pdev_id_ipq5332, ++ .mac_id_to_srng_id = ath12k_hw_mac_id_to_srng_id_ipq5332, ++ .rxdma_ring_sel_config = ath12k_dp_rxdma_ring_sel_config_qcn9274, ++ .get_ring_selector = ath12k_hw_get_ring_selector_ipq5332, ++ .dp_srng_is_tx_comp_ring = ath12k_dp_srng_is_comp_ring_ipq5332, ++}; ++ ++ + #define ATH12K_TX_RING_MASK_0 0x1 + #define ATH12K_TX_RING_MASK_1 0x2 + #define ATH12K_TX_RING_MASK_2 0x4 ++#define ATH12K_TX_RING_MASK_3 0x8 + /* ATH12K_TX_RING_MASK_4 corresponds to the interrupt mask + * for the 4th TX Data ring which uses WBM2SW4RELEASE and + * hence uses the mask with 4th bit set +@@ -794,6 +836,54 @@ static const struct ath12k_hw_ring_mask + }, + }; + ++static const struct ath12k_hw_ring_mask ath12k_hw_ring_mask_ipq5332 = { ++ .tx = { ++ ATH12K_TX_RING_MASK_0, ++ ATH12K_TX_RING_MASK_1, ++ ATH12K_TX_RING_MASK_2, ++ ATH12K_TX_RING_MASK_3, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ }, ++ .rx_mon_dest = { ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ ATH12K_RX_MON_RING_MASK_0, ++ 0, 0, 0, ++ }, ++ .rx = { ++ 0, 0, 0, 0, ++ ATH12K_RX_RING_MASK_0, ++ ATH12K_RX_RING_MASK_1, ++ ATH12K_RX_RING_MASK_2, ++ ATH12K_RX_RING_MASK_3, ++ 0, 0, 0, 0, ++ }, ++ .rx_err = { ++ 0, 0, 0, ++ ATH12K_RX_ERR_RING_MASK_0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ }, ++ .rx_wbm_rel = { ++ 0, 0, 0, ++ ATH12K_RX_WBM_REL_RING_MASK_0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ }, ++ .reo_status = { ++ 0, 0, 0, ++ ATH12K_REO_STATUS_RING_MASK_0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ }, ++ .host2rxdma = { ++ 0, 0, 0, ++ ATH12K_HOST2RXDMA_RING_MASK_0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ }, ++ .tx_mon_dest = { ++ ATH12K_TX_MON_RING_MASK_0, ++ ATH12K_TX_MON_RING_MASK_1, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ++ }, ++}; ++ + static const struct ath12k_hw_ring_mask ath12k_hw_ring_mask_wcn7850 = { + .tx = { + ATH12K_TX_RING_MASK_0, +@@ -1024,6 +1114,9 @@ static const struct ath12k_hw_regs wcn78 + .pcie_pcs_osc_dtct_config_base = 0x01e0f45c, + }; + ++const struct ath12k_hw_regs ipq5332_regs = { ++}; ++ + static const struct ath12k_hw_hal_params ath12k_hw_hal_params_qcn9274 = { + .rx_buf_rbm = HAL_RX_BUF_RBM_SW3_BM, + .wbm2sw_cc_enable = HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW0_EN | +@@ -1180,6 +1273,15 @@ const struct ath12k_cmem ath12k_cmem_ipq + .size = HAL_IPQ5332_CMEM_SIZE, + }; + ++static const struct ath12k_hw_hal_params ath12k_hw_hal_params_ipq5332 = { ++ .rx_buf_rbm = HAL_RX_BUF_RBM_SW3_BM, ++ .wbm2sw_cc_enable = HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW0_EN | ++ HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW1_EN | ++ HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW2_EN | ++ HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW3_EN | ++ HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW4_EN, ++}; ++ + static const struct ath12k_hw_params ath12k_hw_params[] = { + { + .name = "qcn9274 hw1.0", +@@ -1253,6 +1355,7 @@ static const struct ath12k_hw_params ath + }, + .max_mlo_peer = ATH12K_MAX_MLO_PEER, + .num_local_link = 0, ++ .m3_fw_support = true, + .compact_rx_tlv = true, + }, + { +@@ -1319,6 +1422,7 @@ static const struct ath12k_hw_params ath + .alloc_cacheable_memory = false, + .max_mlo_peer = 32, + .num_local_link = 2, ++ .m3_fw_support = true, + .compact_rx_tlv = false, + }, + { +@@ -1393,7 +1497,77 @@ static const struct ath12k_hw_params ath + }, + .max_mlo_peer = ATH12K_MAX_MLO_PEER, + .num_local_link = 0, ++ .m3_fw_support = true, ++ .compact_rx_tlv = true, ++ }, ++ { ++ .name = "ipq5332 hw1.0", ++ .hw_rev = ATH12K_HW_IPQ5332_HW10, ++ .bdf_addr = 0x4B500000, ++ .fw = { ++ .dir = "IPQ5332/hw1.0", ++ .board_size = 256 * 1024, ++ .cal_offset = 128 * 1024, ++ }, ++ .max_radios = 1, ++ .single_pdev_only = false, ++ .qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ5332, ++ .internal_sleep_clock = false, ++ ++ .hw_ops = &ipq5332_ops, ++ .regs = &ipq5332_regs, ++ .ring_mask = &ath12k_hw_ring_mask_ipq5332, ++ ++ .host_ce_config = ath12k_host_ce_config_ipq5332, ++ .ce_count = 12, ++ .target_ce_config = ath12k_target_ce_config_wlan_ipq5332, ++ .target_ce_count = 12, ++ .svc_to_ce_map = ath12k_target_service_to_ce_map_wlan_ipq5332, ++ .svc_to_ce_map_len = 19, ++ ++ .hal_params = &ath12k_hw_hal_params_ipq5332, ++ ++ .rxdma1_enable = true, ++ .num_rxmda_per_pdev = 1, ++ .num_rxdma_dst_ring = 0, ++ .rx_mac_buf_ring = false, ++ .vdev_start_delay = false, ++ .fixed_fw_mem = false, ++ .smp2p_wow_exit = false, ++ ++ .interface_modes = BIT(NL80211_IFTYPE_STATION) | ++ BIT(NL80211_IFTYPE_AP) | ++ BIT(NL80211_IFTYPE_MESH_POINT), ++ .supports_monitor = true, ++ ++ .idle_ps = false, ++ .cold_boot_calib = false, ++ .download_calib = true, ++ .supports_suspend = false, ++ .tcl_ring_retry = true, ++ .reoq_lut_support = true, ++ .supports_shadow_regs = false, ++ ++ .hal_desc_sz = sizeof(struct hal_rx_desc_qcn9274), ++ .num_tcl_banks = 48, ++ .max_tx_ring = 4, ++ ++ ++ .wmi_init = ath12k_wmi_init_ipq5332, ++ ++ .hal_ops = &hal_qcn9274_ops, ++ ++ .supports_ap_ps = true, ++ .credit_flow = false, ++ .wakeup_mhi = false, ++ .alloc_cacheable_memory = true, ++ .max_mlo_peer = ATH12K_MAX_MLO_PEER, ++ .num_local_link = 0, ++ .m3_fw_support = false, + .compact_rx_tlv = true, ++ .ce_ie_addr = &ath12k_ce_ie_addr_ipq5332, ++ .ce_remap = &ath12k_ce_remap_ipq5332, ++ .cmem = &ath12k_cmem_ipq5332, + }, + }; + +--- a/drivers/net/wireless/ath/ath12k/hw.h ++++ b/drivers/net/wireless/ath/ath12k/hw.h +@@ -1,7 +1,7 @@ + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ + /* + * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. +- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #ifndef ATH12K_HW_H +@@ -111,6 +111,7 @@ enum ath12k_hw_rate_ofdm { + + enum ath12k_bus { + ATH12K_BUS_PCI, ++ ATH12K_BUS_AHB, + }; + + #define ATH12K_EXT_IRQ_GRP_NUM_MAX 13 +@@ -211,6 +212,12 @@ struct ath12k_hw_params { + bool alloc_cacheable_memory; + u16 max_mlo_peer; + u8 num_local_link; ++ const struct ce_ie_addr *ce_ie_addr; ++ bool smp2p_wow_exit; ++ bool fixed_fw_mem; ++ bool m3_fw_support; ++ const struct ce_remap *ce_remap; ++ const struct cmem *cmem; + bool compact_rx_tlv; + }; + +--- a/drivers/net/wireless/ath/ath12k/qmi.h ++++ b/drivers/net/wireless/ath/ath12k/qmi.h +@@ -1,7 +1,7 @@ + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ + /* + * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. +- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #ifndef ATH12K_QMI_H +@@ -21,6 +21,7 @@ + #define ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_WCN7850 0x1 + + #define ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_QCN9274 0x07 ++#define ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ5332 0x2 + #define ATH12K_QMI_WLANFW_MAX_TIMESTAMP_LEN_V01 32 + #define ATH12K_QMI_RESP_LEN_MAX 8192 + #define ATH12K_QMI_WLANFW_MAX_NUM_MEM_SEG_V01 52 +--- a/drivers/net/wireless/ath/ath12k/rx_desc.h ++++ b/drivers/net/wireless/ath/ath12k/rx_desc.h +@@ -1,7 +1,7 @@ + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ + /* + * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. +- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + #ifndef ATH12K_RX_DESC_H + #define ATH12K_RX_DESC_H +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: BSD-3-Clause-Clear + /* + * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. +- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + #include + #include +@@ -248,6 +248,67 @@ void ath12k_wmi_init_qcn9274(struct ath1 + config->beacon_tx_offload_max_vdev += config->ema_max_vap_cnt; + } + ++void ath12k_wmi_init_ipq5332(struct ath12k_base *ab, ++ struct target_resource_config *config) ++{ ++ struct ath12k_hw_group *ag = ab->ag; ++ ++ config->num_vdevs = ab->num_radios * TARGET_NUM_VDEVS; ++ ++ if (ab->num_radios == 2) { ++ config->num_peers = TARGET_NUM_PEERS(DBS); ++ config->num_tids = TARGET_NUM_TIDS(DBS); ++ } else if (ab->num_radios == 3) { ++ config->num_peers = TARGET_NUM_PEERS(DBS_SBS); ++ config->num_tids = TARGET_NUM_TIDS(DBS_SBS); ++ } else { ++ /* Control should not reach here */ ++ config->num_peers = TARGET_NUM_PEERS(SINGLE); ++ config->num_tids = TARGET_NUM_TIDS(SINGLE); ++ } ++ config->num_offload_peers = TARGET_NUM_OFFLD_PEERS; ++ config->num_offload_reorder_buffs = TARGET_NUM_OFFLD_REORDER_BUFFS; ++ config->num_peer_keys = TARGET_NUM_PEER_KEYS; ++ config->ast_skid_limit = TARGET_AST_SKID_LIMIT; ++ config->tx_chain_mask = (1 << ab->target_caps.num_rf_chains) - 1; ++ config->rx_chain_mask = (1 << ab->target_caps.num_rf_chains) - 1; ++ config->rx_timeout_pri[0] = TARGET_RX_TIMEOUT_LO_PRI; ++ config->rx_timeout_pri[1] = TARGET_RX_TIMEOUT_LO_PRI; ++ config->rx_timeout_pri[2] = TARGET_RX_TIMEOUT_LO_PRI; ++ config->rx_timeout_pri[3] = TARGET_RX_TIMEOUT_HI_PRI; ++ ++ if (test_bit(ATH12K_FLAG_RAW_MODE, &ag->dev_flags)) ++ config->rx_decap_mode = TARGET_DECAP_MODE_RAW; ++ else ++ config->rx_decap_mode = TARGET_DECAP_MODE_NATIVE_WIFI; ++ ++ config->scan_max_pending_req = TARGET_SCAN_MAX_PENDING_REQS; ++ config->bmiss_offload_max_vdev = TARGET_BMISS_OFFLOAD_MAX_VDEV; ++ config->roam_offload_max_vdev = TARGET_ROAM_OFFLOAD_MAX_VDEV; ++ config->roam_offload_max_ap_profiles = TARGET_ROAM_OFFLOAD_MAX_AP_PROFILES; ++ config->num_mcast_groups = TARGET_NUM_MCAST_GROUPS; ++ config->num_mcast_table_elems = TARGET_NUM_MCAST_TABLE_ELEMS; ++ config->mcast2ucast_mode = TARGET_MCAST2UCAST_MODE; ++ config->tx_dbg_log_size = TARGET_TX_DBG_LOG_SIZE; ++ config->num_wds_entries = TARGET_NUM_WDS_ENTRIES; ++ config->dma_burst_size = TARGET_DMA_BURST_SIZE; ++ config->rx_skip_defrag_timeout_dup_detection_check = ++ TARGET_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK; ++ config->vow_config = TARGET_VOW_CONFIG; ++ config->gtk_offload_max_vdev = TARGET_GTK_OFFLOAD_MAX_VDEV; ++ config->num_msdu_desc = TARGET_NUM_MSDU_DESC; ++ config->beacon_tx_offload_max_vdev = ab->num_radios * TARGET_MAX_BCN_OFFLD; ++ config->rx_batchmode = TARGET_RX_BATCHMODE; ++ /* Indicates host supports peer map v3 and unmap v2 support */ ++ config->peer_map_unmap_version = 0x32; ++ config->twt_ap_pdev_count = ab->num_radios; ++ config->twt_ap_sta_count = 1000; ++ config->ema_max_vap_cnt = ab->num_radios; ++ config->ema_max_profile_period = TARGET_EMA_MAX_PROFILE_PERIOD; ++ config->beacon_tx_offload_max_vdev += config->ema_max_vap_cnt; ++} ++ ++ + void ath12k_wmi_init_wcn7850(struct ath12k_base *ab, + struct target_resource_config *config) + { +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -1,7 +1,7 @@ + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ + /* + * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. +- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #ifndef ATH12K_WMI_H +@@ -6909,6 +6909,8 @@ void ath12k_wmi_init_qcn9274(struct ath1 + struct target_resource_config *config); + void ath12k_wmi_init_wcn7850(struct ath12k_base *ab, + struct target_resource_config *config); ++void ath12k_wmi_init_ipq5332(struct ath12k_base *ab, ++ struct target_resource_config *config); + int ath12k_wmi_cmd_send(struct ath12k_pdev_wmi *wmi, struct sk_buff *skb, + u32 cmd_id); + struct sk_buff *ath12k_wmi_alloc_skb(struct ath12k_wmi_base *wmi_sc, u32 len); diff --git a/feeds/ipq95xx/mac80211/patches/qca/710-005-ath12k-IPQ5332-qmi-changes.patch b/feeds/ipq95xx/mac80211/patches/qca/710-005-ath12k-IPQ5332-qmi-changes.patch new file mode 100644 index 000000000..c1e5d3f26 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/710-005-ath12k-IPQ5332-qmi-changes.patch @@ -0,0 +1,208 @@ +From ebab0b8e2ce8b7d7ff58e22ea438cc2b0791d791 Mon Sep 17 00:00:00 2001 +From: Balamurugan S +Date: Tue, 31 Jan 2023 00:27:50 +0530 +Subject: [PATCH 5/8] ath12k: IPQ5332 qmi changes + +Host capabilities such as M3 firmware download, send platform model differs +between AHB and PCIe interfaces. Introduced hw param field to initialize +and skip M3 firmware download based on interface. + +Signed-off-by: Balamurugan S +--- + drivers/net/wireless/ath/ath12k/hw.c | 4 ++ + drivers/net/wireless/ath/ath12k/hw.h | 1 + + drivers/net/wireless/ath/ath12k/qmi.c | 75 ++++++++++++++++++++++----- + 3 files changed, 66 insertions(+), 14 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/hw.c b/drivers/net/wireless/ath/ath12k/hw.c +index fa8af0c..7e1e687 100644 +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -1355,6 +1355,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { + .num_local_link = 0, + .m3_fw_support = true, + .compact_rx_tlv = true, ++ .send_platform_model = false, + }, + { + .name = "wcn7850 hw2.0", +@@ -1422,6 +1423,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { + .num_local_link = 2, + .m3_fw_support = true, + .compact_rx_tlv = false, ++ .send_platform_model = false, + }, + { + .name = "qcn9274 hw2.0", +@@ -1489,6 +1491,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { + .num_local_link = 0, + .m3_fw_support = true, + .compact_rx_tlv = true, ++ .send_platform_model = false, + }, + { + .name = "ipq5332 hw1.0", +@@ -1557,6 +1560,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { + .ce_ie_addr = &ath12k_ce_ie_addr_ipq5332, + .ce_remap = &ath12k_ce_remap_ipq5332, + .cmem = &ath12k_cmem_ipq5332, ++ .send_platform_model = true, + }, + }; + +diff --git a/drivers/net/wireless/ath/ath12k/hw.h b/drivers/net/wireless/ath/ath12k/hw.h +index 3eb9ebf..5e61a69 100644 +--- a/drivers/net/wireless/ath/ath12k/hw.h ++++ b/drivers/net/wireless/ath/ath12k/hw.h +@@ -208,6 +208,7 @@ struct ath12k_hw_params { + bool smp2p_wow_exit; + bool fixed_fw_mem; + bool m3_fw_support; ++ bool send_platform_model; + const struct ce_remap *ce_remap; + const struct cmem *cmem; + bool compact_rx_tlv; +diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c +index f13fb5d..cbe6666 100644 +--- a/drivers/net/wireless/ath/ath12k/qmi.c ++++ b/drivers/net/wireless/ath/ath12k/qmi.c +@@ -2952,6 +2952,8 @@ static int ath12k_qmi_host_cap_send(struct ath12k_base *ab) + { + struct qmi_wlanfw_host_cap_req_msg_v01 req; + struct qmi_wlanfw_host_cap_resp_msg_v01 resp; ++ struct device_node *root; ++ const char *model = NULL; + struct qmi_txn txn = {}; + int ret = 0; + +@@ -2965,14 +2967,35 @@ static int ath12k_qmi_host_cap_send(struct ath12k_base *ab) + req.bdf_support_valid = 1; + req.bdf_support = 1; + +- req.m3_support_valid = 1; +- req.m3_support = 1; +- req.m3_cache_support_valid = 1; +- req.m3_cache_support = 1; ++ if (ab->hw_params->m3_fw_support) { ++ req.m3_support_valid = 1; ++ req.m3_support = 1; ++ req.m3_cache_support_valid = 1; ++ req.m3_cache_support = 1; ++ } else { ++ req.m3_support_valid = 0; ++ req.m3_support = 0; ++ req.m3_cache_support_valid = 0; ++ req.m3_cache_support = 0; ++ } + + req.cal_done_valid = 1; + req.cal_done = ab->qmi.cal_done; + ++ if (ab->hw_params->send_platform_model) { ++ root = of_find_node_by_path("/"); ++ if (root) { ++ model = of_get_property(root, "model", NULL); ++ if (model) { ++ req.platform_name_valid = 1; ++ strlcpy(req.platform_name, model, ++ QMI_WLANFW_MAX_PLATFORM_NAME_LEN_V01); ++ ath12k_info(ab, "Platform name: %s", req.platform_name); ++ } ++ of_node_put(root); ++ } ++ } ++ + /* BRINGUP: here we are piggybacking a lot of stuff using + * internal_sleep_clock, should it be split? + */ +@@ -3181,8 +3204,7 @@ static int ath12k_qmi_respond_fw_mem_request(struct ath12k_base *ab) + req->mem_seg[i].addr = ab->qmi.target_mem[i].paddr; + req->mem_seg[i].size = ab->qmi.target_mem[i].size; + req->mem_seg[i].type = ab->qmi.target_mem[i].type; +- ath12k_dbg(ab, ATH12K_DBG_QMI, +- "qmi req mem_seg[%d] %pad %u %u\n", i, ++ ath12k_info(ab, "qmi req mem_seg[%d] %pad %u %u\n", i, + &ab->qmi.target_mem[i].paddr, + ab->qmi.target_mem[i].size, + ab->qmi.target_mem[i].type); +@@ -3403,6 +3425,7 @@ out: + return ret; + } + ++#define MAX_TGT_MEM_MODES 5 + static int ath12k_qmi_assign_target_mem_chunk(struct ath12k_base *ab) + { + struct device *dev = ab->dev; +@@ -3411,6 +3434,7 @@ static int ath12k_qmi_assign_target_mem_chunk(struct ath12k_base *ab) + struct resource res; + int host_ddr_sz, mlo_ddr_sz, sz, mlo_sz = 0; + int i, idx, mlo_idx, ret; ++ unsigned int bdf_location[MAX_TGT_MEM_MODES]; + + sz = ab->host_ddr_fixed_mem_off; + hremote_node = of_parse_phandle(dev->of_node, "memory-region", 0); +@@ -3550,6 +3574,25 @@ skip_mlo_mem_init: + idx++; + mlo_idx++; + break; ++ case BDF_MEM_REGION_TYPE: ++ if (of_property_read_u32_array(dev->of_node, ++ "qcom,bdf-addr", bdf_location, ++ ARRAY_SIZE(bdf_location))) { ++ ath12k_err(ab, "BDF_MEM_REGION Not defined in device_tree\n"); ++ ret = -EINVAL; ++ goto out; ++ } ++ ab->qmi.target_mem[idx].paddr = bdf_location[0]; ++ ++ ab->qmi.target_mem[idx].v.ioaddr = ++ ioremap(ab->qmi.target_mem[idx].paddr, ++ ab->qmi.target_mem[i].size); ++ 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: + ath12k_warn(ab, "qmi ignore invalid mem req type %d\n", + ab->qmi.target_mem[i].type); +@@ -3947,7 +3990,7 @@ static void ath12k_qmi_m3_free(struct ath12k_base *ab) + { + struct m3_mem_region *m3_mem = &ab->qmi.m3_mem; + +- if (!m3_mem->vaddr) ++ if (!ab->hw_params->m3_fw_support || !m3_mem->vaddr) + return; + + dma_free_coherent(ab->dev, m3_mem->size, +@@ -3966,15 +4009,19 @@ static int ath12k_qmi_wlanfw_m3_info_send(struct ath12k_base *ab) + memset(&req, 0, sizeof(req)); + memset(&resp, 0, sizeof(resp)); + +- ret = ath12k_qmi_m3_load(ab); +- if (ret) { +- ath12k_err(ab, "failed to load m3 firmware: %d", ret); +- return ret; ++ if (ab->hw_params->m3_fw_support) { ++ ret = ath12k_qmi_m3_load(ab); ++ if (ret) { ++ ath12k_err(ab, "failed to load m3 firmware: %d", ret); ++ return ret; ++ } ++ req.addr = m3_mem->paddr; ++ req.size = m3_mem->size; ++ } else { ++ req.addr = 0; ++ req.size = 0; + } + +- req.addr = m3_mem->paddr; +- req.size = m3_mem->size; +- + ret = qmi_txn_init(&ab->qmi.handle, &txn, + qmi_wlanfw_m3_info_resp_msg_v01_ei, &resp); + if (ret < 0) +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/710-006-ath12k-callbacks-to-read-write-to-cmem-space.patch b/feeds/ipq95xx/mac80211/patches/qca/710-006-ath12k-callbacks-to-read-write-to-cmem-space.patch new file mode 100644 index 000000000..bb5c68b6f --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/710-006-ath12k-callbacks-to-read-write-to-cmem-space.patch @@ -0,0 +1,83 @@ +From 12c630f3147cd8c60314062128c39083ae4715c3 Mon Sep 17 00:00:00 2001 +From: Balamurugan S +Date: Tue, 31 Jan 2023 00:29:34 +0530 +Subject: [PATCH 6/8] ath12k: callbacks to read/write to cmem space + +In IPQ5332 CMEM region is outside WCSS block. To read/write to cmem space, +use the I/O remapped cmem memory. + +Signed-off-by: Balamurugan S +--- + drivers/net/wireless/ath/ath12k/dp.c | 16 ++++++++++++---- + drivers/net/wireless/ath/ath12k/hif.h | 14 ++++++++++++++ + 2 files changed, 26 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c +index 2e37b9f..6c35aab 100644 +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -1405,8 +1405,12 @@ static void ath12k_dp_tx_cmem_init(struct ath12k_base *ab, struct ath12k_dp *dp) + + for (i = 0; i < ATH12K_NUM_TX_SPT_PAGES; i++) { + /* Write to PPT in CMEM */ +- ath12k_hif_write32(ab, cmem_base + ATH12K_PPT_ADDR_OFFSET(i), +- dp->spt_info[i].paddr >> ATH12K_SPT_4K_ALIGN_OFFSET); ++ if (ab->hif.ops->cmem_write32) ++ ath12k_hif_cmem_write32(ab, cmem_base + ATH12K_PPT_ADDR_OFFSET(i), ++ dp->spt_info[i].paddr >> ATH12K_SPT_4K_ALIGN_OFFSET); ++ else ++ ath12k_hif_write32(ab, cmem_base + ATH12K_PPT_ADDR_OFFSET(i), ++ dp->spt_info[i].paddr >> ATH12K_SPT_4K_ALIGN_OFFSET); + } + } + +@@ -1421,8 +1425,12 @@ static void ath12k_dp_rx_cmem_init(struct ath12k_base *ab, struct ath12k_dp *dp) + for (i = ATH12K_RX_SPT_PAGE_OFFSET; + i < (ATH12K_RX_SPT_PAGE_OFFSET + ATH12K_NUM_RX_SPT_PAGES); i++) { + /* Write to PPT in CMEM */ +- ath12k_hif_write32(ab, cmem_base + ATH12K_PPT_ADDR_OFFSET(i), +- dp->spt_info[i].paddr >> ATH12K_SPT_4K_ALIGN_OFFSET); ++ if (ab->hif.ops->cmem_write32) ++ ath12k_hif_cmem_write32(ab, cmem_base + ATH12K_PPT_ADDR_OFFSET(i), ++ dp->spt_info[i].paddr >> ATH12K_SPT_4K_ALIGN_OFFSET); ++ else ++ ath12k_hif_write32(ab, cmem_base + ATH12K_PPT_ADDR_OFFSET(i), ++ dp->spt_info[i].paddr >> ATH12K_SPT_4K_ALIGN_OFFSET); + } + } + +diff --git a/drivers/net/wireless/ath/ath12k/hif.h b/drivers/net/wireless/ath/ath12k/hif.h +index 54490cd..8c12f24 100644 +--- a/drivers/net/wireless/ath/ath12k/hif.h ++++ b/drivers/net/wireless/ath/ath12k/hif.h +@@ -12,6 +12,8 @@ + struct ath12k_hif_ops { + u32 (*read32)(struct ath12k_base *sc, u32 address); + void (*write32)(struct ath12k_base *sc, u32 address, u32 data); ++ u32 (*cmem_read32)(struct ath12k_base *sc, u32 address); ++ void (*cmem_write32)(struct ath12k_base *sc, u32 address, u32 data); + void (*irq_enable)(struct ath12k_base *sc); + void (*irq_disable)(struct ath12k_base *sc); + int (*start)(struct ath12k_base *sc); +@@ -131,6 +133,18 @@ static inline void ath12k_hif_write32(struct ath12k_base *ab, u32 address, + ab->hif.ops->write32(ab, address, data); + } + ++static inline u32 ath12k_hif_cmem_read32(struct ath12k_base *ab, u32 address) ++{ ++ return ab->hif.ops->cmem_read32(ab, address); ++} ++ ++static inline void ath12k_hif_cmem_write32(struct ath12k_base *ab, u32 address, ++ u32 data) ++{ ++ ab->hif.ops->cmem_write32(ab, address, data); ++} ++ ++ + static inline int ath12k_hif_power_up(struct ath12k_base *ab) + { + return ab->hif.ops->power_up(ab); +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/710-007-ath12-Enable-AHB-driver-for-IPQ5332.patch b/feeds/ipq95xx/mac80211/patches/qca/710-007-ath12-Enable-AHB-driver-for-IPQ5332.patch new file mode 100644 index 000000000..91d2e6ef6 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/710-007-ath12-Enable-AHB-driver-for-IPQ5332.patch @@ -0,0 +1,56 @@ +From 96651e6579edfa98980c918d60693fd8acb7cdd1 Mon Sep 17 00:00:00 2001 +From: Balamurugan S +Date: Tue, 31 Jan 2023 00:36:24 +0530 +Subject: [PATCH 7/8] ath12: Enable AHB driver for IPQ5332 + +Enable AHB driver compilation for IPQ5332 in Makefile. + +Signed-off-by: Balamurugan S +--- + drivers/net/wireless/ath/ath12k/Kconfig | 7 +++++++ + drivers/net/wireless/ath/ath12k/Makefile | 1 + + local-symbols | 1 + + 3 files changed, 9 insertions(+) + +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/Kconfig +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/Kconfig ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/Kconfig +@@ -15,6 +15,13 @@ config ATH12K + + If you choose to build a module, it'll be called ath12k. + ++config ATH12K_AHB ++ bool "QTI ath12k AHB support" ++ depends on ATH12K ++ depends on REMOTEPROC ++ help ++ This module adds support for AHB bus ++ + config ATH12K_DEBUG + bool "QCA ath12k debugging" + depends on ATH12K +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/Makefile +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/Makefile ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/Makefile +@@ -29,6 +29,7 @@ ath12k-$(CONFIG_THERMAL) += thermal.o + ath12k-$(CPTCFG_ATH12K_SPECTRAL) += spectral.o + ath12k-$(CPTCFG_WANT_DEV_COREDUMP) += coredump.o + ath12k-$(CPTCFG_ATH12K_PKTLOG) += pktlog.o ++ath12k-$(CPTCFG_ATH12K_AHB) += ahb.o + + # for tracing framework to find trace.h + CFLAGS_trace.o := -I$(src) +Index: backports-20220822-5.4.213-ef7197996efe/local-symbols +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/local-symbols ++++ backports-20220822-5.4.213-ef7197996efe/local-symbols +@@ -137,6 +137,7 @@ ATH11K_PKTLOG= + ATH11K_CFR= + ATH11K_SMART_ANT_ALG= + ATH12K= ++ATH12K_AHB= + ATH12K_DEBUG= + ATH12K_DEBUGFS= + ATH12K_TRACING= diff --git a/feeds/ipq95xx/mac80211/patches/qca/710-008-ath12k-Disable-QDSS-firmware-log-for-ipq5332.patch b/feeds/ipq95xx/mac80211/patches/qca/710-008-ath12k-Disable-QDSS-firmware-log-for-ipq5332.patch new file mode 100644 index 000000000..9cc4d8cb8 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/710-008-ath12k-Disable-QDSS-firmware-log-for-ipq5332.patch @@ -0,0 +1,95 @@ +From a5b6008425565cae71a974b191a0b5c72fbbd10e Mon Sep 17 00:00:00 2001 +From: Balamurugan S +Date: Tue, 31 Jan 2023 00:40:29 +0530 +Subject: [PATCH 8/8] ath12k: Disable QDSS, firmware log for ipq5332 + +Disable qdss, firmware logging feature for ipq5332. Functionality will +be enabled separately. + +Signed-off-by: Balamurugan S +--- + drivers/net/wireless/ath/ath12k/hw.c | 8 ++++++++ + drivers/net/wireless/ath/ath12k/hw.h | 2 ++ + drivers/net/wireless/ath/ath12k/qmi.c | 6 ++++++ + 3 files changed, 16 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/hw.c b/drivers/net/wireless/ath/ath12k/hw.c +index 7e1e687..4e3deed 100644 +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -1356,6 +1356,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { + .m3_fw_support = true, + .compact_rx_tlv = true, + .send_platform_model = false, ++ .en_qdss = true, ++ .en_fwlog = true, + }, + { + .name = "wcn7850 hw2.0", +@@ -1424,6 +1426,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { + .m3_fw_support = true, + .compact_rx_tlv = false, + .send_platform_model = false, ++ .en_qdss = true, ++ .en_fwlog = true, + }, + { + .name = "qcn9274 hw2.0", +@@ -1492,6 +1496,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { + .m3_fw_support = true, + .compact_rx_tlv = true, + .send_platform_model = false, ++ .en_qdss = true, ++ .en_fwlog = true, + }, + { + .name = "ipq5332 hw1.0", +@@ -1561,6 +1567,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { + .ce_remap = &ath12k_ce_remap_ipq5332, + .cmem = &ath12k_cmem_ipq5332, + .send_platform_model = true, ++ .en_qdss = false, ++ .en_fwlog = false, + }, + }; + +diff --git a/drivers/net/wireless/ath/ath12k/hw.h b/drivers/net/wireless/ath/ath12k/hw.h +index 5e61a69..0f2480f 100644 +--- a/drivers/net/wireless/ath/ath12k/hw.h ++++ b/drivers/net/wireless/ath/ath12k/hw.h +@@ -209,6 +209,8 @@ struct ath12k_hw_params { + bool fixed_fw_mem; + bool m3_fw_support; + bool send_platform_model; ++ bool en_qdss; ++ bool en_fwlog; + const struct ce_remap *ce_remap; + const struct cmem *cmem; + bool compact_rx_tlv; +diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c +index cbe6666..e6a2f1c 100644 +--- a/drivers/net/wireless/ath/ath12k/qmi.c ++++ b/drivers/net/wireless/ath/ath12k/qmi.c +@@ -4198,6 +4198,9 @@ int ath12k_config_qdss(struct ath12k_base *ab) + + /* Disabling qdss trace for FTM as it causes hig evt latency in FW + */ ++ if (!ab->hw_params->en_qdss) ++ return 0; ++ + if (ab->fw_mode == ATH12K_FIRMWARE_MODE_FTM) + return 0; + +@@ -4970,6 +4973,9 @@ int ath12k_enable_fwlog(struct ath12k_base *ab) + struct qmi_txn txn = {}; + int ret = 0; + ++ if (!ab->hw_params->en_fwlog) ++ return 0; ++ + req = kzalloc(sizeof(*req), GFP_KERNEL); + if (!req) + return -ENOMEM; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/710-010-ath12k-add-ipq5332-data-path-register-changes.patch b/feeds/ipq95xx/mac80211/patches/qca/710-010-ath12k-add-ipq5332-data-path-register-changes.patch new file mode 100644 index 000000000..6f3877d0a --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/710-010-ath12k-add-ipq5332-data-path-register-changes.patch @@ -0,0 +1,413 @@ +From 5b94c4ffb56d60f915fbb3b7768fc75987b73dcb Mon Sep 17 00:00:00 2001 +From: P Praneesh +Date: Tue, 31 Jan 2023 22:36:43 +0530 +Subject: [PATCH] ath12k: add ipq5332 data path register changes + +Add register changes for ipq5332 data path related changes. + +Signed-off-by: P Praneesh +--- + drivers/net/wireless/ath/ath12k/ahb.c | 4 +- + drivers/net/wireless/ath/ath12k/hal.c | 80 ++++++++--------- + drivers/net/wireless/ath/ath12k/hal.h | 45 ++++++---- + drivers/net/wireless/ath/ath12k/hw.c | 120 ++++++++++++++++++++++++-- + drivers/net/wireless/ath/ath12k/hw.h | 9 +- + 5 files changed, 191 insertions(+), 67 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/hal.c ++++ b/drivers/net/wireless/ath/ath12k/hal.c +@@ -537,9 +537,9 @@ static int ath12k_hal_srng_create_config + s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_STATUS_HP; + + s = &hal->srng_config[HAL_TCL_DATA]; +- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_BASE_LSB; ++ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_BASE_LSB(ab); + s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_HP; +- s->reg_size[0] = HAL_TCL2_RING_BASE_LSB - HAL_TCL1_RING_BASE_LSB; ++ s->reg_size[0] = HAL_TCL2_RING_BASE_LSB(ab) - HAL_TCL1_RING_BASE_LSB(ab); + s->reg_size[1] = HAL_TCL2_RING_HP - HAL_TCL1_RING_HP; + + s = &hal->srng_config[HAL_TCL_CMD]; +@@ -551,29 +551,29 @@ static int ath12k_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 + HAL_CE_DST_RING_BASE_LSB; +- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG + HAL_CE_DST_RING_HP; +- s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG - +- HAL_SEQ_WCSS_UMAC_CE0_SRC_REG; +- s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG - +- HAL_SEQ_WCSS_UMAC_CE0_SRC_REG; ++ 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 + HAL_CE_DST_RING_BASE_LSB; +- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG + HAL_CE_DST_RING_HP; +- s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG - +- HAL_SEQ_WCSS_UMAC_CE0_DST_REG; +- s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG - +- HAL_SEQ_WCSS_UMAC_CE0_DST_REG; ++ 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) - ++ HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab); + + s = &hal->srng_config[HAL_CE_DST_STATUS]; +- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG + ++ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + + HAL_CE_DST_STATUS_RING_BASE_LSB; +- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG + HAL_CE_DST_STATUS_RING_HP; +- s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG - +- HAL_SEQ_WCSS_UMAC_CE0_DST_REG; +- s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG - +- HAL_SEQ_WCSS_UMAC_CE0_DST_REG; ++ 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) - ++ HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab); + + s = &hal->srng_config[HAL_WBM_IDLE_LINK]; + s->reg_start[0] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_IDLE_LINK_RING_BASE_LSB(ab); +@@ -980,9 +980,9 @@ static int ath12k_hal_srng_create_config + + s = &hal->srng_config[HAL_TCL_DATA]; + s->max_rings = 5; +- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_BASE_LSB; ++ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_BASE_LSB(ab); + s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_HP; +- s->reg_size[0] = HAL_TCL2_RING_BASE_LSB - HAL_TCL1_RING_BASE_LSB; ++ s->reg_size[0] = HAL_TCL2_RING_BASE_LSB(ab) - HAL_TCL1_RING_BASE_LSB(ab); + s->reg_size[1] = HAL_TCL2_RING_HP - HAL_TCL1_RING_HP; + + s = &hal->srng_config[HAL_TCL_CMD]; +@@ -995,31 +995,31 @@ static int ath12k_hal_srng_create_config + + s = &hal->srng_config[HAL_CE_SRC]; + s->max_rings = 12; +- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG + HAL_CE_DST_RING_BASE_LSB; +- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG + HAL_CE_DST_RING_HP; +- s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG - +- HAL_SEQ_WCSS_UMAC_CE0_SRC_REG; +- s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG - +- HAL_SEQ_WCSS_UMAC_CE0_SRC_REG; ++ 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->max_rings = 12; +- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG + HAL_CE_DST_RING_BASE_LSB; +- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG + HAL_CE_DST_RING_HP; +- s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG - +- HAL_SEQ_WCSS_UMAC_CE0_DST_REG; +- s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG - +- HAL_SEQ_WCSS_UMAC_CE0_DST_REG; ++ 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) - ++ HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab); + + s = &hal->srng_config[HAL_CE_DST_STATUS]; + s->max_rings = 12; +- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG + ++ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + + HAL_CE_DST_STATUS_RING_BASE_LSB; +- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG + HAL_CE_DST_STATUS_RING_HP; +- s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG - +- HAL_SEQ_WCSS_UMAC_CE0_DST_REG; +- s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG - +- HAL_SEQ_WCSS_UMAC_CE0_DST_REG; ++ 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) - ++ HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab); + + s = &hal->srng_config[HAL_WBM_IDLE_LINK]; + s->reg_start[0] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_IDLE_LINK_RING_BASE_LSB(ab); +--- a/drivers/net/wireless/ath/ath12k/hal.h ++++ b/drivers/net/wireless/ath/ath12k/hal.h +@@ -47,10 +47,16 @@ struct ath12k_base; + #define HAL_SEQ_WCSS_UMAC_OFFSET 0x00a00000 + #define HAL_SEQ_WCSS_UMAC_REO_REG 0x00a38000 + #define HAL_SEQ_WCSS_UMAC_TCL_REG 0x00a44000 +-#define HAL_SEQ_WCSS_UMAC_CE0_SRC_REG 0x01b80000 +-#define HAL_SEQ_WCSS_UMAC_CE0_DST_REG 0x01b81000 +-#define HAL_SEQ_WCSS_UMAC_CE1_SRC_REG 0x01b82000 +-#define HAL_SEQ_WCSS_UMAC_CE1_DST_REG 0x01b83000 ++ ++#define HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) \ ++ ((ab)->hw_params->regs->hal_umac_ce0_src_reg_base) ++#define HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) \ ++ ((ab)->hw_params->regs->hal_umac_ce0_dest_reg_base) ++#define HAL_SEQ_WCSS_UMAC_CE1_SRC_REG(ab) \ ++ ((ab)->hw_params->regs->hal_umac_ce1_src_reg_base) ++#define HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) \ ++ ((ab)->hw_params->regs->hal_umac_ce1_dest_reg_base) ++ + #define HAL_SEQ_WCSS_UMAC_WBM_REG 0x00a34000 + + #define HAL_CE_WFSS_CE_REG_BASE 0x01b80000 +@@ -60,8 +66,10 @@ struct ath12k_base; + /* SW2TCL(x) R0 ring configuration address */ + #define HAL_TCL1_RING_CMN_CTRL_REG 0x00000020 + #define HAL_TCL1_RING_DSCP_TID_MAP 0x00000240 +-#define HAL_TCL1_RING_BASE_LSB 0x00000900 +-#define HAL_TCL1_RING_BASE_MSB 0x00000904 ++#define HAL_TCL1_RING_BASE_LSB(ab) \ ++ ((ab)->hw_params->regs->hal_tcl1_ring_base_lsb) ++#define HAL_TCL1_RING_BASE_MSB(ab) \ ++ ((ab)->hw_params->regs->hal_tcl1_ring_base_msb) + #define HAL_TCL1_RING_ID(ab) ((ab)->hw_params->regs->hal_tcl1_ring_id) + #define HAL_TCL1_RING_MISC(ab) \ + ((ab)->hw_params->regs->hal_tcl1_ring_misc) +@@ -79,30 +87,31 @@ struct ath12k_base; + ((ab)->hw_params->regs->hal_tcl1_ring_msi1_base_msb) + #define HAL_TCL1_RING_MSI1_DATA(ab) \ + ((ab)->hw_params->regs->hal_tcl1_ring_msi1_data) +-#define HAL_TCL2_RING_BASE_LSB 0x00000978 ++#define HAL_TCL2_RING_BASE_LSB(ab) \ ++ ((ab)->hw_params->regs->hal_tcl2_ring_base_lsb) + #define HAL_TCL_RING_BASE_LSB(ab) \ + ((ab)->hw_params->regs->hal_tcl_ring_base_lsb) + + #define HAL_TCL1_RING_MSI1_BASE_LSB_OFFSET(ab) \ +- (HAL_TCL1_RING_MSI1_BASE_LSB(ab) - HAL_TCL1_RING_BASE_LSB) ++ (HAL_TCL1_RING_MSI1_BASE_LSB(ab) - HAL_TCL1_RING_BASE_LSB(ab)) + #define HAL_TCL1_RING_MSI1_BASE_MSB_OFFSET(ab) \ +- (HAL_TCL1_RING_MSI1_BASE_MSB(ab) - HAL_TCL1_RING_BASE_LSB) ++ (HAL_TCL1_RING_MSI1_BASE_MSB(ab) - HAL_TCL1_RING_BASE_LSB(ab)) + #define HAL_TCL1_RING_MSI1_DATA_OFFSET(ab) \ +- (HAL_TCL1_RING_MSI1_DATA(ab) - HAL_TCL1_RING_BASE_LSB) ++ (HAL_TCL1_RING_MSI1_DATA(ab) - HAL_TCL1_RING_BASE_LSB(ab)) + #define HAL_TCL1_RING_BASE_MSB_OFFSET \ +- (HAL_TCL1_RING_BASE_MSB - HAL_TCL1_RING_BASE_LSB) ++ (HAL_TCL1_RING_BASE_MSB(ab) - HAL_TCL1_RING_BASE_LSB(ab)) + #define HAL_TCL1_RING_ID_OFFSET(ab) \ +- (HAL_TCL1_RING_ID(ab) - HAL_TCL1_RING_BASE_LSB) ++ (HAL_TCL1_RING_ID(ab) - HAL_TCL1_RING_BASE_LSB(ab)) + #define HAL_TCL1_RING_CONSR_INT_SETUP_IX0_OFFSET(ab) \ +- (HAL_TCL1_RING_CONSUMER_INT_SETUP_IX0(ab) - HAL_TCL1_RING_BASE_LSB) ++ (HAL_TCL1_RING_CONSUMER_INT_SETUP_IX0(ab) - HAL_TCL1_RING_BASE_LSB(ab)) + #define HAL_TCL1_RING_CONSR_INT_SETUP_IX1_OFFSET(ab) \ +- (HAL_TCL1_RING_CONSUMER_INT_SETUP_IX1(ab) - HAL_TCL1_RING_BASE_LSB) ++ (HAL_TCL1_RING_CONSUMER_INT_SETUP_IX1(ab) - HAL_TCL1_RING_BASE_LSB(ab)) + #define HAL_TCL1_RING_TP_ADDR_LSB_OFFSET(ab) \ +- (HAL_TCL1_RING_TP_ADDR_LSB(ab) - HAL_TCL1_RING_BASE_LSB) ++ (HAL_TCL1_RING_TP_ADDR_LSB(ab) - HAL_TCL1_RING_BASE_LSB(ab)) + #define HAL_TCL1_RING_TP_ADDR_MSB_OFFSET(ab) \ +- (HAL_TCL1_RING_TP_ADDR_MSB(ab) - HAL_TCL1_RING_BASE_LSB) ++ (HAL_TCL1_RING_TP_ADDR_MSB(ab) - HAL_TCL1_RING_BASE_LSB(ab)) + #define HAL_TCL1_RING_MISC_OFFSET(ab) \ +- (HAL_TCL1_RING_MISC(ab) - HAL_TCL1_RING_BASE_LSB) ++ (HAL_TCL1_RING_MISC(ab) - HAL_TCL1_RING_BASE_LSB(ab)) + + /* SW2TCL(x) R2 ring pointers (head/tail) address */ + #define HAL_TCL1_RING_HP 0x00002000 +@@ -124,7 +133,7 @@ struct ath12k_base; + + /* WBM PPE Release Ring address */ + #define HAL_WBM_PPE_RELEASE_RING_BASE_LSB(ab) \ +- (ab)->hw_params->regs->hal_ppe_rel_ring_base ++ ((ab)->hw_params->regs->hal_ppe_rel_ring_base) + #define HAL_WBM_PPE_RELEASE_RING_HP 0x00003020 + + /* REO2SW(x) R0 ring configuration address */ +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -926,6 +926,10 @@ static const struct ath12k_hw_regs qcn92 + .hal_tcl1_ring_msi1_base_msb = 0x0000094c, + .hal_tcl1_ring_msi1_data = 0x00000950, + .hal_tcl_ring_base_lsb = 0x00000b58, ++ .hal_tcl1_ring_base_lsb = 0x00000900, ++ .hal_tcl1_ring_base_msb = 0x00000904, ++ .hal_tcl2_ring_base_lsb = 0x00000978, ++ + + /* TCL STATUS ring address */ + .hal_tcl_status_ring_base_lsb = 0x00000d38, +@@ -994,6 +998,12 @@ static const struct ath12k_hw_regs qcn92 + /* PCIe base address */ + .pcie_qserdes_sysclk_en_sel = 0x01e0c0a8, + .pcie_pcs_osc_dtct_config_base = 0x01e0d45c, ++ ++ /* CE base address */ ++ .hal_umac_ce0_src_reg_base = 0x01b80000, ++ .hal_umac_ce0_dest_reg_base = 0x01b81000, ++ .hal_umac_ce1_src_reg_base = 0x01b82000, ++ .hal_umac_ce1_dest_reg_base = 0x01b83000, + }; + + const struct ath12k_hw_regs qcn9274_v2_regs = { +@@ -1008,6 +1018,9 @@ const struct ath12k_hw_regs qcn9274_v2_r + .hal_tcl1_ring_msi1_base_msb = 0x0000094c, + .hal_tcl1_ring_msi1_data = 0x00000950, + .hal_tcl_ring_base_lsb = 0x00000b58, ++ .hal_tcl1_ring_base_lsb = 0x00000900, ++ .hal_tcl1_ring_base_msb = 0x00000904, ++ .hal_tcl2_ring_base_lsb = 0x00000978, + + /* TCL STATUS ring address */ + .hal_tcl_status_ring_base_lsb = 0x00000d38, +@@ -1076,6 +1089,99 @@ const struct ath12k_hw_regs qcn9274_v2_r + /* PCIe base address */ + .pcie_qserdes_sysclk_en_sel = 0x01e0c0a8, + .pcie_pcs_osc_dtct_config_base = 0x01e0d45c, ++ ++ /* CE base address */ ++ .hal_umac_ce0_src_reg_base = 0x01b80000, ++ .hal_umac_ce0_dest_reg_base = 0x01b81000, ++ .hal_umac_ce1_src_reg_base = 0x01b82000, ++ .hal_umac_ce1_dest_reg_base = 0x01b83000, ++}; ++ ++const struct ath12k_hw_regs ipq5332_regs = { ++ /* SW2TCL(x) R0 ring configuration address */ ++ .hal_tcl1_ring_id = 0x00000918, ++ .hal_tcl1_ring_misc = 0x00000920, ++ .hal_tcl1_ring_tp_addr_lsb = 0x0000092c, ++ .hal_tcl1_ring_tp_addr_msb = 0x00000930, ++ .hal_tcl1_ring_consumer_int_setup_ix0 = 0x00000940, ++ .hal_tcl1_ring_consumer_int_setup_ix1 = 0x00000944, ++ .hal_tcl1_ring_msi1_base_lsb = 0x00000958, ++ .hal_tcl1_ring_msi1_base_msb = 0x0000095c, ++ .hal_tcl1_ring_base_lsb = 0x00000910, ++ .hal_tcl1_ring_base_msb = 0x00000914, ++ .hal_tcl1_ring_msi1_data = 0x00000960, ++ .hal_tcl2_ring_base_lsb = 0x00000988, ++ .hal_tcl_ring_base_lsb = 0x00000b68, ++ ++ /* TCL STATUS ring address */ ++ .hal_tcl_status_ring_base_lsb = 0x00000d48, ++ ++ /* REO DEST ring address */ ++ .hal_reo2_ring_base = 0x00000578, ++ .hal_reo1_misc_ctrl_addr = 0x00000b9c, ++ .hal_reo1_sw_cookie_cfg0 = 0x0000006c, ++ .hal_reo1_sw_cookie_cfg1 = 0x00000070, ++ .hal_reo1_qdesc_lut_base0 = 0x00000074, ++ .hal_reo1_qdesc_lut_base1 = 0x00000078, ++ .hal_reo1_qdesc_addr_read = 0x0000007c, ++ .hal_reo1_qdesc_max_peerid = 0x00000088, ++ .hal_reo1_ring_base_lsb = 0x00000500, ++ .hal_reo1_ring_base_msb = 0x00000504, ++ .hal_reo1_ring_id = 0x00000508, ++ .hal_reo1_ring_misc = 0x00000510, ++ .hal_reo1_ring_hp_addr_lsb = 0x00000514, ++ .hal_reo1_ring_hp_addr_msb = 0x00000518, ++ .hal_reo1_ring_producer_int_setup = 0x00000524, ++ .hal_reo1_ring_msi1_base_lsb = 0x00000548, ++ .hal_reo1_ring_msi1_base_msb = 0x0000054C, ++ .hal_reo1_ring_msi1_data = 0x00000550, ++ .hal_reo1_aging_thres_ix0 = 0x00000B28, ++ .hal_reo1_aging_thres_ix1 = 0x00000B2C, ++ .hal_reo1_aging_thres_ix2 = 0x00000B30, ++ .hal_reo1_aging_thres_ix3 = 0x00000B34, ++ ++ /* REO Exception ring address */ ++ .hal_reo2_sw0_ring_base = 0x000008c0, ++ ++ /* REO Reinject ring address */ ++ .hal_sw2reo_ring_base = 0x00000320, ++ .hal_sw2reo1_ring_base = 0x00000398, ++ ++ /* REO cmd ring address */ ++ .hal_reo_cmd_ring_base = 0x000002A8, ++ ++ /* REO status ring address */ ++ .hal_reo_status_ring_base = 0x00000aa0, ++ ++ /* WBM idle link ring address */ ++ .hal_wbm_idle_ring_base_lsb = 0x00000d3c, ++ .hal_wbm_idle_ring_misc_addr = 0x00000d4c, ++ .hal_wbm_r0_idle_list_cntl_addr = 0x00000240, ++ .hal_wbm_r0_idle_list_size_addr = 0x00000244, ++ .hal_wbm_scattered_ring_base_lsb = 0x00000250, ++ .hal_wbm_scattered_ring_base_msb = 0x00000254, ++ .hal_wbm_scattered_desc_head_info_ix0 = 0x00000260, ++ .hal_wbm_scattered_desc_head_info_ix1 = 0x00000264, ++ .hal_wbm_scattered_desc_tail_info_ix0 = 0x00000270, ++ .hal_wbm_scattered_desc_tail_info_ix1 = 0x00000274, ++ .hal_wbm_scattered_desc_ptr_hp_addr = 0x0000027c, ++ ++ /* SW2WBM release ring address */ ++ .hal_wbm_sw_release_ring_base_lsb = 0x0000037c, ++ ++ /* WBM2SW release ring address */ ++ .hal_wbm0_release_ring_base_lsb = 0x00000e08, ++ .hal_wbm1_release_ring_base_lsb = 0x00000e80, ++ ++ /* PPE release ring address */ ++ .hal_ppe_rel_ring_base = 0x0000046c, ++ ++ /* CE base address */ ++ .hal_umac_ce0_src_reg_base = 0x00740000, ++ .hal_umac_ce0_dest_reg_base = 0x00741000, ++ .hal_umac_ce1_src_reg_base = 0x00742000, ++ .hal_umac_ce1_dest_reg_base = 0x00743000, ++ + }; + + static const struct ath12k_hw_regs wcn7850_regs = { +@@ -1090,6 +1196,9 @@ static const struct ath12k_hw_regs wcn78 + .hal_tcl1_ring_msi1_base_msb = 0x0000094c, + .hal_tcl1_ring_msi1_data = 0x00000950, + .hal_tcl_ring_base_lsb = 0x00000b58, ++ .hal_tcl1_ring_base_lsb = 0x00000900, ++ .hal_tcl1_ring_base_msb = 0x00000904, ++ .hal_tcl2_ring_base_lsb = 0x00000978, + + /* TCL STATUS ring address */ + .hal_tcl_status_ring_base_lsb = 0x00000d38, +@@ -1114,9 +1223,12 @@ static const struct ath12k_hw_regs wcn78 + /* PCIe base address */ + .pcie_qserdes_sysclk_en_sel = 0x01e0e0a8, + .pcie_pcs_osc_dtct_config_base = 0x01e0f45c, +-}; + +-const struct ath12k_hw_regs ipq5332_regs = { ++ /* CE base address */ ++ .hal_umac_ce0_src_reg_base = 0x01b80000, ++ .hal_umac_ce0_dest_reg_base = 0x01b81000, ++ .hal_umac_ce1_src_reg_base = 0x01b82000, ++ .hal_umac_ce1_dest_reg_base = 0x01b83000, + }; + + static const struct ath12k_hw_hal_params ath12k_hw_hal_params_qcn9274 = { +--- a/drivers/net/wireless/ath/ath12k/hw.h ++++ b/drivers/net/wireless/ath/ath12k/hw.h +@@ -306,6 +306,9 @@ struct ath12k_hw_regs { + u32 hal_tcl1_ring_msi1_base_msb; + u32 hal_tcl1_ring_msi1_data; + u32 hal_tcl_ring_base_lsb; ++ u32 hal_tcl1_ring_base_lsb; ++ u32 hal_tcl1_ring_base_msb; ++ u32 hal_tcl2_ring_base_lsb; + + u32 hal_tcl_status_ring_base_lsb; + +@@ -363,6 +366,11 @@ struct ath12k_hw_regs { + + u32 pcie_qserdes_sysclk_en_sel; + u32 pcie_pcs_osc_dtct_config_base; ++ ++ u32 hal_umac_ce0_src_reg_base; ++ u32 hal_umac_ce0_dest_reg_base; ++ u32 hal_umac_ce1_src_reg_base; ++ u32 hal_umac_ce1_dest_reg_base; + }; + + int ath12k_hw_init(struct ath12k_base *ab); diff --git a/feeds/ipq95xx/mac80211/patches/qca/710-ath12k-fix-sta-association-in-mbssid-case.patch b/feeds/ipq95xx/mac80211/patches/qca/710-ath12k-fix-sta-association-in-mbssid-case.patch new file mode 100644 index 000000000..ee3dc3441 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/710-ath12k-fix-sta-association-in-mbssid-case.patch @@ -0,0 +1,38 @@ +From 98b8f83febd45be97dc1b4583594ee5d555526ad Mon Sep 17 00:00:00 2001 +From: Hari Chandrakanthan +Date: Tue, 24 Jan 2023 14:55:31 +0530 +Subject: [PATCH] ath12k : fix sta association in mbssid case + +ath12k station is not able to associate to non-transmitting vif of mbss. +This is because wpa_supplicant does not receive the information about +non-transmitting vif as part of NL scan results. + +ath12k driver does not advertises its mbssid capability to mac80211. +So wiphy->support_mbssid is not set. + +Since support_mbssid is not set, the information about non-transmitting vif +is not parsed from the rx mgmt frame and it is not added as part of the scan +results. + +Fix this by advertising the MBSSID capabitlity of ath12k driver to mac80211. + +Signed-off-by: Hari Chandrakanthan +--- + drivers/net/wireless/ath/ath12k/mac.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index 0bd4f92..f30403e 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -13920,6 +13920,7 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah) + ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU); + ieee80211_hw_set(hw, USES_RSS); + ieee80211_hw_set(hw, SUPPORTS_TID_CLASS_OFFLOAD); ++ ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID); + + if (ath12k_frame_mode == ATH12K_HW_TXRX_ETHERNET) { + ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD); +-- +2.7.4 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/711-001-cfg80211-add-rts-threshold-support-for-MLO.patch b/feeds/ipq95xx/mac80211/patches/qca/711-001-cfg80211-add-rts-threshold-support-for-MLO.patch new file mode 100644 index 000000000..433abf3b6 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/711-001-cfg80211-add-rts-threshold-support-for-MLO.patch @@ -0,0 +1,154 @@ +From 912e8b685dee949c80f6ef6ce2a39dad627b3d16 Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Fri, 10 Feb 2023 15:28:42 +0530 +Subject: [PATCH] cfg80211: add rts threshold support for MLO + +Currently, all vaps rts threshold update when we run +"iw phy set rts " for MLO. +But, should be update only for one vap not for all vaps, +this is happen because in MLO case we have only one phy. + +So, add changes to support rts threshold by parsing link id +and moving iw phy command to iw dev command for MLO. + +command: +iw dev wlan# set rts -l + +Signed-off-by: Aaradhana Sahu +--- + include/net/cfg80211.h | 3 ++- + net/wireless/nl80211.c | 23 ++++++++++++++++++++++- + net/wireless/rdev-ops.h | 7 ++++--- + net/wireless/trace.h | 5 +++-- + net/wireless/wext-compat.c | 6 +++--- + 5 files changed, 34 insertions(+), 10 deletions(-) + +diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h +index 34e1e75..cd8d908 100644 +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -4559,7 +4559,8 @@ struct cfg80211_ops { + int (*set_mcast_rate)(struct wiphy *wiphy, struct net_device *dev, + int rate[NUM_NL80211_BANDS]); + +- int (*set_wiphy_params)(struct wiphy *wiphy, u32 changed); ++ int (*set_wiphy_params)(struct wiphy *wiphy, u32 changed, ++ struct wireless_dev *wdev, unsigned int link_id); + + int (*set_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev, + enum nl80211_tx_power_setting type, int mbm, +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 5bacebc..58a61a3 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -3978,6 +3978,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) + u32 old_frag_threshold, old_rts_threshold; + u8 old_coverage_class; + u32 old_txq_limit, old_txq_memory_limit, old_txq_quantum; ++ struct wireless_dev *rts_wdev = wdev; ++ unsigned int link; + + if (!rdev->ops->set_wiphy_params) { + result = -EOPNOTSUPP; +@@ -4010,7 +4012,26 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) + if (changed & WIPHY_PARAM_TXQ_QUANTUM) + rdev->wiphy.txq_quantum = txq_quantum; + +- result = rdev_set_wiphy_params(rdev, changed); ++ if (rts_wdev && rts_wdev->valid_links) { ++ if (!info->attrs[NL80211_ATTR_MLO_LINK_ID]) { ++ result = -EINVAL; ++ goto out; ++ } ++ ++ link = nla_get_u8(info->attrs[NL80211_ATTR_MLO_LINK_ID]); ++ ++ if (!(rts_wdev->valid_links & BIT(link))) { ++ result = -ENOLINK; ++ goto out; ++ } ++ result = rdev_set_wiphy_params(rdev, changed, rts_wdev, link); ++ } else { ++ if (!info->attrs[NL80211_ATTR_MLO_LINK_ID]) ++ result = rdev_set_wiphy_params(rdev, changed, rts_wdev, 0); ++ else ++ result = -EINVAL; ++ } ++ + if (result) { + rdev->wiphy.retry_short = old_retry_short; + rdev->wiphy.retry_long = old_retry_long; +diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h +index 66f5db4..3e78ceb 100644 +--- a/net/wireless/rdev-ops.h ++++ b/net/wireless/rdev-ops.h +@@ -560,15 +560,16 @@ static inline int rdev_leave_ibss(struct cfg80211_registered_device *rdev, + } + + static inline int +-rdev_set_wiphy_params(struct cfg80211_registered_device *rdev, u32 changed) ++rdev_set_wiphy_params(struct cfg80211_registered_device *rdev, u32 changed, ++ struct wireless_dev *wdev, unsigned int link_id) + { + int ret; + + if (!rdev->ops->set_wiphy_params) + return -EOPNOTSUPP; + +- trace_rdev_set_wiphy_params(&rdev->wiphy, changed); +- ret = rdev->ops->set_wiphy_params(&rdev->wiphy, changed); ++ trace_rdev_set_wiphy_params(&rdev->wiphy, changed, wdev, link_id); ++ ret = rdev->ops->set_wiphy_params(&rdev->wiphy, changed, wdev, link_id); + trace_rdev_return_int(&rdev->wiphy, ret); + return ret; + } +diff --git a/net/wireless/trace.h b/net/wireless/trace.h +index e125e61..ef8c0cd 100644 +--- a/net/wireless/trace.h ++++ b/net/wireless/trace.h +@@ -1568,8 +1568,9 @@ TRACE_EVENT(rdev_join_ocb, + ); + + TRACE_EVENT(rdev_set_wiphy_params, +- TP_PROTO(struct wiphy *wiphy, u32 changed), +- TP_ARGS(wiphy, changed), ++ TP_PROTO(struct wiphy *wiphy, u32 changed, struct wireless_dev *wdev, ++ unsigned int link_id), ++ TP_ARGS(wiphy, changed, wdev, link_id), + TP_STRUCT__entry( + WIPHY_ENTRY + __field(u32, changed) +diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c +index 627aff0..46eaccf 100644 +--- a/net/wireless/wext-compat.c ++++ b/net/wireless/wext-compat.c +@@ -268,7 +268,7 @@ int cfg80211_wext_siwrts(struct net_device *dev, + wdev->wiphy->rts_threshold = rts->value; + } + +- err = rdev_set_wiphy_params(rdev, WIPHY_PARAM_RTS_THRESHOLD); ++ err = rdev_set_wiphy_params(rdev, WIPHY_PARAM_RTS_THRESHOLD, wdev, 0); + + if (err) + wdev->wiphy->rts_threshold = orts; +@@ -313,7 +313,7 @@ int cfg80211_wext_siwfrag(struct net_device *dev, + wdev->wiphy->frag_threshold = frag->value & ~0x1; + } + +- err = rdev_set_wiphy_params(rdev, WIPHY_PARAM_FRAG_THRESHOLD); ++ err = rdev_set_wiphy_params(rdev, WIPHY_PARAM_FRAG_THRESHOLD, wdev, 0); + if (err) + wdev->wiphy->frag_threshold = ofrag; + out: +@@ -366,7 +366,7 @@ static int cfg80211_wext_siwretry(struct net_device *dev, + changed |= WIPHY_PARAM_RETRY_SHORT; + } + +- err = rdev_set_wiphy_params(rdev, changed); ++ err = rdev_set_wiphy_params(rdev, changed, wdev, 0); + if (err) { + wdev->wiphy->retry_short = oshort; + wdev->wiphy->retry_long = olong; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/711-002-mac80211-add-rts-threshold-support-for-MLO.patch b/feeds/ipq95xx/mac80211/patches/qca/711-002-mac80211-add-rts-threshold-support-for-MLO.patch new file mode 100644 index 000000000..275a1abea --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/711-002-mac80211-add-rts-threshold-support-for-MLO.patch @@ -0,0 +1,184 @@ +From 2966223bc67628725ef813e905336c8e69540f7e Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Fri, 17 Feb 2023 15:43:05 +0530 +Subject: [PATCH] mac80211: add rts threshold support for MLO + +Currently, all vaps rts threshold update when we run +"iw phy set rts " for MLO. +But, should be update only for one vap not for all vaps, +this is happen because in MLO case we have only one phy. + +So, add changes to support rts threshold by parsing link id +and moving iw phy command to iw dev command for MLO. + +command: +iw dev wlan# set rts -l + +Signed-off-by: Aaradhana Sahu +--- + include/net/mac80211.h | 4 +++- + net/mac80211/cfg.c | 45 +++++++++++++++++++++++++++++++++------ + net/mac80211/driver-ops.h | 11 ++++++---- + net/mac80211/link.c | 1 + + net/mac80211/trace.h | 4 ++-- + net/mac80211/util.c | 2 +- + 6 files changed, 53 insertions(+), 14 deletions(-) + +diff --git a/include/net/mac80211.h b/include/net/mac80211.h +index bfcf749..2708c5d 100644 +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -793,6 +793,7 @@ struct ieee80211_bss_conf { + + /* Critical Update flag*/ + u32 critical_update_flag; ++ u32 rts_threshold; + }; + + /** +@@ -4366,7 +4367,8 @@ struct ieee80211_ops { + struct ieee80211_key_conf *key, + struct ieee80211_key_seq *seq); + int (*set_frag_threshold)(struct ieee80211_hw *hw, u32 value); +- int (*set_rts_threshold)(struct ieee80211_hw *hw, u32 value); ++ int (*set_rts_threshold)(struct ieee80211_hw *hw, u32 value, ++ struct ieee80211_vif *vif, int link_id); + int (*sta_add)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); + int (*sta_remove)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, +diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c +index 4239a34..70171c1 100644 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -3026,10 +3026,14 @@ static int ieee80211_set_mcast_rate(struct wiphy *wiphy, struct net_device *dev, + return 0; + } + +-static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) ++static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed, ++ struct wireless_dev *wdev, unsigned int link_id) + { + struct ieee80211_local *local = wiphy_priv(wiphy); +- int err; ++ struct ieee80211_sub_if_data *sdata; ++ int err, old_rts_threshold = 0; ++ struct ieee80211_bss_conf *link_conf = NULL; ++ + + if (changed & WIPHY_PARAM_FRAG_THRESHOLD) { + ieee80211_check_fast_xmit_all(local); +@@ -3054,11 +3058,40 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) + return err; + } + +- if (changed & WIPHY_PARAM_RTS_THRESHOLD) { +- err = drv_set_rts_threshold(local, wiphy->rts_threshold); ++ if (wdev) { ++ sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); + +- if (err) +- return err; ++ rcu_read_lock(); ++ link_conf = rcu_dereference(sdata->vif.link_conf[link_id]); ++ ++ if (!link_conf) { ++ rcu_read_unlock(); ++ return -ENOLINK; ++ } ++ ++ old_rts_threshold = link_conf->rts_threshold; ++ ++ if (changed & WIPHY_PARAM_RTS_THRESHOLD) { ++ link_conf->rts_threshold = wiphy->rts_threshold; ++ err = drv_set_rts_threshold(local, wiphy->rts_threshold, sdata, link_id); ++ ++ if (err) { ++ link_conf->rts_threshold = old_rts_threshold; ++ rcu_read_unlock(); ++ return err; ++ } ++ } ++ ++ rcu_read_unlock(); ++ } else { ++ if (changed & WIPHY_PARAM_RTS_THRESHOLD && !wiphy->num_hw) { ++ err = drv_set_rts_threshold(local, wiphy->rts_threshold, NULL, link_id); ++ ++ if (err) ++ return err; ++ } else { ++ return -EOPNOTSUPP; ++ } + } + + if (changed & WIPHY_PARAM_RETRY_SHORT) { +diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h +index 6a38700..cc13b13 100644 +--- a/net/mac80211/driver-ops.h ++++ b/net/mac80211/driver-ops.h +@@ -399,15 +399,18 @@ static inline int drv_set_frag_threshold(struct ieee80211_local *local, + } + + static inline int drv_set_rts_threshold(struct ieee80211_local *local, +- u32 value) ++ u32 value, struct ieee80211_sub_if_data *sdata, ++ int link_id) + { + int ret = 0; + + might_sleep(); + +- trace_drv_set_rts_threshold(local, value); +- if (local->ops->set_rts_threshold) +- ret = local->ops->set_rts_threshold(&local->hw, value); ++ trace_drv_set_rts_threshold(local, value, &sdata->vif, link_id); ++ if (sdata && local->ops->set_rts_threshold) ++ ret = local->ops->set_rts_threshold(&local->hw, value, &sdata->vif, link_id); ++ else if (local->ops->set_rts_threshold) ++ ret = local->ops->set_rts_threshold(&local->hw, value, NULL, link_id); + trace_drv_return_int(local, ret); + return ret; + } +diff --git a/net/mac80211/link.c b/net/mac80211/link.c +index 5666540..b6c31b4 100644 +--- a/net/mac80211/link.c ++++ b/net/mac80211/link.c +@@ -35,6 +35,7 @@ void ieee80211_link_init(struct ieee80211_sub_if_data *sdata, + link->link_id = link_id; + link->conf = link_conf; + link_conf->link_id = link_id; ++ link_conf->rts_threshold = (u32) -1; + + INIT_WORK(&link->csa_finalize_work, + ieee80211_csa_finalize_work); +diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h +index c78ffad..4aacae2 100644 +--- a/net/mac80211/trace.h ++++ b/net/mac80211/trace.h +@@ -822,8 +822,8 @@ DEFINE_EVENT(local_u32_evt, drv_set_frag_threshold, + ); + + DEFINE_EVENT(local_u32_evt, drv_set_rts_threshold, +- TP_PROTO(struct ieee80211_local *local, u32 value), +- TP_ARGS(local, value) ++ TP_PROTO(struct ieee80211_local *local, u32 value, struct ieee80211_vif *vif, int link_id), ++ TP_ARGS(local, value, vif, link_id) + ); + + TRACE_EVENT(drv_set_coverage_class, +diff --git a/net/mac80211/util.c b/net/mac80211/util.c +index b627303..7eeec26 100644 +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -2563,7 +2563,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) + drv_set_frag_threshold(local, hw->wiphy->frag_threshold); + + /* setup RTS threshold */ +- drv_set_rts_threshold(local, hw->wiphy->rts_threshold); ++ drv_set_rts_threshold(local, hw->wiphy->rts_threshold, NULL, 0); + + /* reset coverage class */ + drv_set_coverage_class(local, hw->wiphy->coverage_class); +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/711-003-ath12k-add-rts-threshold-support-for-MLO.patch b/feeds/ipq95xx/mac80211/patches/qca/711-003-ath12k-add-rts-threshold-support-for-MLO.patch new file mode 100644 index 000000000..20319a2e1 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/711-003-ath12k-add-rts-threshold-support-for-MLO.patch @@ -0,0 +1,81 @@ +From 18604840b78e5557d4104a023f6e4ad6279cb867 Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Fri, 10 Feb 2023 15:43:25 +0530 +Subject: [PATCH] ath12k: add rts threshold support for MLO + +Currently, all vaps rts threshold update when we run +"iw phy set rts " for MLO. +But, should be update only for one vap not for all vaps, +this is happen because in MLO case we have only one phy. + +So, add changes to support rts threshold by parsing link id +and moving iw phy command to iw dev command for MLO. + +command: +iw dev wlan# set rts -l + +Signed-off-by: Aaradhana Sahu +--- + drivers/net/wireless/ath/ath12k/mac.c | 34 +++++++++++++++++++++------ + 1 file changed, 27 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index f30403e..8755ee5 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -11672,25 +11672,45 @@ ath12k_set_vdev_param_to_all_vifs(struct ath12k *ar, int param, u32 value) + * this is set interface specific to firmware from ath12k driver + * TODO Move to link specific config + */ +-static int ath12k_mac_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) ++static int ath12k_mac_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value, ++ struct ieee80211_vif *vif, int link_id) + { + struct ath12k_hw *ah = hw->priv; ++ struct ath12k_vif *ahvif; + struct ath12k *ar; +- int i, ret; ++ struct ath12k_link_vif *arvif; ++ int ret = -1; + int param_id = WMI_VDEV_PARAM_RTS_THRESHOLD; + +- ar = ah->radio; ++ if (vif) { ++ mutex_lock(&ah->conf_mutex); ++ ahvif = ath12k_vif_to_ahvif(vif); ++ arvif = ahvif->link[link_id]; + +- for (i = 0; i < ah->num_radio; i++) { ++ if (arvif == NULL || !arvif->is_created) { ++ ath12k_info(NULL, ++ "bss info parameter changes %d cached to apply after vdev create on channel assign\n", ++ param_id); ++ mutex_unlock(&ah->conf_mutex); ++ return ret; ++ } ++ ++ ar = arvif->ar; + ret = ath12k_set_vdev_param_to_all_vifs(ar, param_id, value); + if (ret) { + ath12k_warn(ar->ab, "failed to set RTS config for all vdevs of pdev %d", + ar->pdev->pdev_id); +- break; + } +- ar++; +- } + ++ mutex_unlock(&ah->conf_mutex); ++ } else { ++ ar = ah->radio; ++ ret = ath12k_set_vdev_param_to_all_vifs(ar, param_id, value); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to set RTS config for all vdevs of pdev %d", ++ ar->pdev->pdev_id); ++ } ++ } + return ret; + } + +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/711-004-ath11k-add-two-argument-to-ath11k_mac_op_set_rts_thr.patch b/feeds/ipq95xx/mac80211/patches/qca/711-004-ath11k-add-two-argument-to-ath11k_mac_op_set_rts_thr.patch new file mode 100644 index 000000000..f6311f274 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/711-004-ath11k-add-two-argument-to-ath11k_mac_op_set_rts_thr.patch @@ -0,0 +1,29 @@ +From 2454e35f38cc598dc6be25bb05be5020807f3380 Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Fri, 17 Feb 2023 15:50:57 +0530 +Subject: [PATCH] ath11k: add two argument to ath11k_mac_op_set_rts_threshold + +To avoid compilation issue + +Signed-off-by: Aaradhana Sahu +--- + drivers/net/wireless/ath/ath11k/mac.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c +index c5cf5c6..c1c0186 100644 +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -10016,7 +10016,8 @@ ath11k_set_vdev_param_to_all_vifs(struct ath11k *ar, int param, u32 value) + /* mac80211 stores device specific RTS/Fragmentation threshold value, + * this is set interface specific to firmware from ath11k driver + */ +-static int ath11k_mac_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) ++static int ath11k_mac_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value, ++ struct ieee80211_vif *vif, int link_id) + { + struct ath11k *ar = hw->priv; + int param_id = WMI_VDEV_PARAM_RTS_THRESHOLD; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/711-01-ath12k-fwtest-MLO-support.patch b/feeds/ipq95xx/mac80211/patches/qca/711-01-ath12k-fwtest-MLO-support.patch new file mode 100644 index 000000000..0ca6155c7 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/711-01-ath12k-fwtest-MLO-support.patch @@ -0,0 +1,97 @@ +From 05b7a8a4d7debcabb856f7df97a345144df0a136 Mon Sep 17 00:00:00 2001 +From: Karthik M +Date: Fri, 3 Feb 2023 20:25:29 +0530 +Subject: [PATCH] wifi: ath12k: MLO support for fwtest + +Add support to parse link id from the fwtest tool +and trigger the command on the corresponding +firmware + +Signed-off-by: Karthik M +--- + drivers/net/wireless/ath/ath12k/testmode.c | 13 +++++++++---- + drivers/net/wireless/ath/ath12k/testmode.h | 4 ++-- + 2 files changed, 11 insertions(+), 6 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/testmode.c ++++ b/drivers/net/wireless/ath/ath12k/testmode.c +@@ -429,35 +429,45 @@ out: + return ret; + } + int ath12k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, +- void *data, int len) ++ u8 link_id, void *data, int len) + { + struct ath12k_hw *ah = hw->priv; + struct ath12k *ar; + struct ath12k_base *ab; + struct nlattr *tb[ATH12K_TM_ATTR_MAX + 1]; +- int ret; ++ enum ath12k_tm_cmd cmd_type; ++ int ret = 0; + ++ ret = nla_parse(tb, ATH12K_TM_ATTR_MAX, data, len, ath12k_tm_policy, ++ NULL); ++ if (ret) ++ return ret; ++ ++ if (!tb[ATH12K_TM_ATTR_CMD]) ++ return -EINVAL; ++ ++ cmd_type = nla_get_u32(tb[ATH12K_TM_ATTR_CMD]); + mutex_lock(&ah->conf_mutex); + +- if (ah->num_radio) +- ar = ah->radio; ++ if (vif == NULL && (cmd_type == ATH12K_TM_CMD_WMI_FTM || ++ cmd_type == ATH12K_TM_CMD_TESTMODE_START)) { ++ if (ah->num_radio) ++ ar = ah->radio; ++ } else { ++ ar = ath12k_get_ar_by_vif(hw, vif, link_id); ++ } ++ + if (!ar) { ++ ath12k_err(NULL, ++ "unable to determine device\n"); + mutex_unlock(&ah->conf_mutex); + return -EINVAL; + } +- ab = ar->ab; + ++ ab = ar->ab; + mutex_unlock(&ah->conf_mutex); + +- ret = nla_parse(tb, ATH12K_TM_ATTR_MAX, data, len, ath12k_tm_policy, +- NULL); +- if (ret) +- return ret; +- +- if (!tb[ATH12K_TM_ATTR_CMD]) +- return -EINVAL; +- +- switch (nla_get_u32(tb[ATH12K_TM_ATTR_CMD])) { ++ switch (cmd_type) { + case ATH12K_TM_CMD_WMI: + return ath12k_tm_cmd_wmi(ar, tb); + case ATH12K_TM_CMD_TESTMODE_START: +--- a/drivers/net/wireless/ath/ath12k/testmode.h ++++ b/drivers/net/wireless/ath/ath12k/testmode.h +@@ -14,7 +14,7 @@ int ath12k_tm_process_event(struct ath12 + const struct wmi_ftm_event_msg *ftm_msg, + u16 length); + int ath12k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, +- void *data, int len); ++ u8 link_id, void *data, int len); + void ath12k_fwlog_write(struct ath12k_base *ab, u8 *data, int len); + #else + +@@ -32,7 +32,7 @@ static inline int ath12k_tm_process_even + } + static inline int ath12k_tm_cmd(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, +- void *data, int len) ++ u8 link_id, void *data, int len) + { + return 0; + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/711-02-cfg80211-fwtest-MLO-support.patch b/feeds/ipq95xx/mac80211/patches/qca/711-02-cfg80211-fwtest-MLO-support.patch new file mode 100644 index 000000000..e18354cd0 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/711-02-cfg80211-fwtest-MLO-support.patch @@ -0,0 +1,134 @@ +From a077230ffae9471ab9b1be8325be77f1a29ab982 Mon Sep 17 00:00:00 2001 +From: Karthik M +Date: Wed, 8 Feb 2023 00:41:04 +0530 +Subject: [PATCH] wifi: cfg80211: MLO support for fwtest + +Add support to parse link id from the fwtest tool +and trigger the command on the corresponding +firmware + +Signed-off-by: Karthik M +--- + include/net/cfg80211.h | 2 +- + include/net/mac80211.h | 2 +- + net/mac80211/cfg.c | 3 ++- + net/wireless/nl80211.c | 17 +++++++++++++++-- + net/wireless/rdev-ops.h | 5 +++-- + net/wireless/trace.h | 10 +++++++--- + 6 files changed, 29 insertions(+), 10 deletions(-) + +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -4571,7 +4571,7 @@ struct cfg80211_ops { + + #ifdef CPTCFG_NL80211_TESTMODE + int (*testmode_cmd)(struct wiphy *wiphy, struct wireless_dev *wdev, +- void *data, int len); ++ u8 link_id, void *data, int len); + int (*testmode_dump)(struct wiphy *wiphy, struct sk_buff *skb, + struct netlink_callback *cb, + void *data, int len); +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -4455,7 +4455,7 @@ struct ieee80211_ops { + void (*set_coverage_class)(struct ieee80211_hw *hw, s16 coverage_class); + #ifdef CPTCFG_NL80211_TESTMODE + int (*testmode_cmd)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, +- void *data, int len); ++ u8 link_id, void *data, int len); + int (*testmode_dump)(struct ieee80211_hw *hw, struct sk_buff *skb, + struct netlink_callback *cb, + void *data, int len); +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -3222,6 +3222,7 @@ static void ieee80211_rfkill_poll(struct + #ifdef CPTCFG_NL80211_TESTMODE + static int ieee80211_testmode_cmd(struct wiphy *wiphy, + struct wireless_dev *wdev, ++ u8 link_id, + void *data, int len) + { + struct ieee80211_local *local = wiphy_priv(wiphy); +@@ -3238,7 +3239,7 @@ static int ieee80211_testmode_cmd(struct + vif = &sdata->vif; + } + +- return local->ops->testmode_cmd(&local->hw, vif, data, len); ++ return local->ops->testmode_cmd(&local->hw, vif, link_id, data, len); + } + + static int ieee80211_testmode_dump(struct wiphy *wiphy, +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -12136,6 +12136,7 @@ static int nl80211_testmode_do(struct sk + struct cfg80211_registered_device *rdev = info->user_ptr[0]; + struct wireless_dev *wdev; + int err; ++ u8 link_id; + + lockdep_assert_held(&rdev->wiphy.mtx); + +@@ -12157,8 +12158,18 @@ static int nl80211_testmode_do(struct sk + if (!info->attrs[NL80211_ATTR_TESTDATA]) + return -EINVAL; + ++ link_id = nl80211_link_id(info->attrs); ++ ++ if(wdev) { ++ if (wdev->valid_links && !(wdev->valid_links & BIT(link_id))) ++ return -EINVAL; ++ ++ if (!wdev->valid_links && link_id) ++ return -EINVAL; ++ } ++ + rdev->cur_cmd_info = info; +- err = rdev_testmode_cmd(rdev, wdev, ++ err = rdev_testmode_cmd(rdev, wdev, link_id, + nla_data(info->attrs[NL80211_ATTR_TESTDATA]), + nla_len(info->attrs[NL80211_ATTR_TESTDATA])); + rdev->cur_cmd_info = NULL; +--- a/net/wireless/rdev-ops.h ++++ b/net/wireless/rdev-ops.h +@@ -632,11 +632,12 @@ static inline void rdev_rfkill_poll(stru + #ifdef CPTCFG_NL80211_TESTMODE + static inline int rdev_testmode_cmd(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev, ++ u8 link_id, + void *data, int len) + { + int ret; +- trace_rdev_testmode_cmd(&rdev->wiphy, wdev); +- ret = rdev->ops->testmode_cmd(&rdev->wiphy, wdev, data, len); ++ trace_rdev_testmode_cmd(&rdev->wiphy, wdev, link_id); ++ ret = rdev->ops->testmode_cmd(&rdev->wiphy, wdev, link_id, data, len); + trace_rdev_return_int(&rdev->wiphy, ret); + return ret; + } +--- a/net/wireless/trace.h ++++ b/net/wireless/trace.h +@@ -1628,17 +1628,21 @@ TRACE_EVENT(rdev_return_int_int, + + #ifdef CPTCFG_NL80211_TESTMODE + TRACE_EVENT(rdev_testmode_cmd, +- TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev), +- TP_ARGS(wiphy, wdev), ++ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, ++ u8 link_id), ++ TP_ARGS(wiphy, wdev, link_id), + TP_STRUCT__entry( + WIPHY_ENTRY + WDEV_ENTRY ++ __field(u8, link_id) + ), + TP_fast_assign( + WIPHY_ASSIGN; + WDEV_ASSIGN; ++ __entry->link_id = link_id; + ), +- TP_printk(WIPHY_PR_FMT WDEV_PR_FMT, WIPHY_PR_ARG, WDEV_PR_ARG) ++ TP_printk(WIPHY_PR_FMT "," WDEV_PR_FMT ", link_id: %u", ++ WIPHY_PR_ARG, WDEV_PR_ARG, __entry->link_id) + ); + + TRACE_EVENT(rdev_testmode_dump, diff --git a/feeds/ipq95xx/mac80211/patches/qca/711-03-ath11k-fwtest-dummy-link-id-support.patch b/feeds/ipq95xx/mac80211/patches/qca/711-03-ath11k-fwtest-dummy-link-id-support.patch new file mode 100644 index 000000000..882dbc505 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/711-03-ath11k-fwtest-dummy-link-id-support.patch @@ -0,0 +1,54 @@ +From 43d4cec7abc8267b65cb7390246d175ac9b77505 Mon Sep 17 00:00:00 2001 +From: Karthik M +Date: Fri, 10 Feb 2023 12:36:05 +0530 +Subject: [PATCH] wifi: ath11k: Add dummy link_id support for fwtest + +cfg80211 and mac80211 passes link_id in fw_test +command to support MLO architecture. +Add dummy link_id paramter for compatability. + +Signed-off-by: Karthik M +--- + drivers/net/wireless/ath/ath11k/testmode.c | 3 ++- + drivers/net/wireless/ath/ath11k/testmode.h | 4 ++-- + 2 files changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/testmode.c ++++ b/drivers/net/wireless/ath/ath11k/testmode.c +@@ -496,7 +496,7 @@ out: + } + + int ath11k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, +- void *data, int len) ++ u8 link_id, void *data, int len) + { + struct ath11k *ar = hw->priv; + struct ath11k_base *ab = ar->ab; +@@ -505,6 +505,7 @@ int ath11k_tm_cmd(struct ieee80211_hw *h + + ret = nla_parse(tb, ATH11K_TM_ATTR_MAX, data, len, ath11k_tm_policy, + NULL); ++ + if (ret) + return ret; + +--- a/drivers/net/wireless/ath/ath11k/testmode.h ++++ b/drivers/net/wireless/ath/ath11k/testmode.h +@@ -31,7 +31,7 @@ bool ath11k_process_tm_event(struct ath1 + u16 length); + + int ath11k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, +- void *data, int len); ++ u8 link_id, void *data, int len); + + void ath11k_fwlog_write(struct ath11k_base *ab, u8 *data, int len); + #else +@@ -51,7 +51,7 @@ static inline bool ath11k_process_tm_eve + + static inline int ath11k_tm_cmd(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, +- void *data, int len) ++ u8 link_id, void *data, int len) + { + return 0; + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/711-04-ath10k-fwtest-dummy-link-id-support.patch b/feeds/ipq95xx/mac80211/patches/qca/711-04-ath10k-fwtest-dummy-link-id-support.patch new file mode 100644 index 000000000..f823d9753 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/711-04-ath10k-fwtest-dummy-link-id-support.patch @@ -0,0 +1,46 @@ +From 2f47342990cc0f8993ad8a401677062ec7c6f206 Mon Sep 17 00:00:00 2001 +From: Karthik M +Date: Fri, 10 Feb 2023 11:43:34 +0530 +Subject: [PATCH] wifi: ath10k: Add dummy link_id support for fwtest + +cfg80211 and mac80211 passes link_id in fw_test +command to support MLO architecture. +Add dummy link_id paramter for compatability. + +Signed-off-by: Karthik M +--- + drivers/net/wireless/ath/ath10k/testmode.c | 2 +- + drivers/net/wireless/ath/ath10k/testmode.h | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/ath/ath10k/testmode.c ++++ b/drivers/net/wireless/ath/ath10k/testmode.c +@@ -425,7 +425,7 @@ out: + } + + int ath10k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, +- void *data, int len) ++ u8 link_id, void *data, int len) + { + struct ath10k *ar = hw->priv; + struct nlattr *tb[ATH10K_TM_ATTR_MAX + 1]; +--- a/drivers/net/wireless/ath/ath10k/testmode.h ++++ b/drivers/net/wireless/ath/ath10k/testmode.h +@@ -11,7 +11,7 @@ void ath10k_testmode_destroy(struct ath1 + + bool ath10k_tm_event_wmi(struct ath10k *ar, u32 cmd_id, struct sk_buff *skb); + int ath10k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, +- void *data, int len); ++ u8 link_id, void *data, int len); + + #else + +@@ -27,7 +27,7 @@ static inline bool ath10k_tm_event_wmi(s + + static inline int ath10k_tm_cmd(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, +- void *data, int len) ++ u8 link_id, void *data, int len) + { + return 0; + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/711-ath12k-athdiag-debugfs-support.patch b/feeds/ipq95xx/mac80211/patches/qca/711-ath12k-athdiag-debugfs-support.patch new file mode 100644 index 000000000..06d445dc1 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/711-ath12k-athdiag-debugfs-support.patch @@ -0,0 +1,138 @@ +From d523dea6236c50210aab18d23c8dcd2a8e9c71f3 Mon Sep 17 00:00:00 2001 +From: Karthik M +Date: Fri, 10 Feb 2023 15:00:10 +0530 +Subject: [PATCH] wifi: ath12k: athdiag debugfs support + +Add debugfs support to enable the athdiag feature + +Signed-off-by: Karthik M +--- + drivers/net/wireless/ath/ath12k/debugfs.c | 101 ++++++++++++++++++++++ + 1 file changed, 101 insertions(+) + +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -13,6 +13,7 @@ + #include "dp_tx.h" + #include "debugfs_htt_stats.h" + #include "peer.h" ++#include "qmi.h" + + static struct dentry *debugfs_ath12k; + +@@ -2462,6 +2463,104 @@ static const struct file_operations fops + .open = simple_open + }; + ++static ssize_t ath12k_athdiag_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ u8 *buf; ++ int ret; ++ ++ if (*ppos <= 0) ++ return -EINVAL; ++ ++ if (!count) ++ return 0; ++ ++ buf = vmalloc(count); ++ if (!buf) { ++ return -ENOMEM; ++ } ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ ret = ath12k_qmi_mem_read(ar->ab, *ppos, buf, count); ++ if (ret < 0) { ++ ath12k_warn(ar->ab, "failed to read address 0x%08x via diagnose window from debugfs: %d\n", ++ (u32)(*ppos), ret); ++ goto exit; ++ } ++ ++ ret = copy_to_user(user_buf, buf, count); ++ if (ret) { ++ ret = -EFAULT; ++ goto exit; ++ } ++ ++ count -= ret; ++ *ppos += count; ++ ret = count; ++ ++exit: ++ vfree(buf); ++ mutex_unlock(&ar->conf_mutex); ++ return ret; ++} ++ ++static ssize_t ath12k_athdiag_write(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ u8 *buf; ++ int ret; ++ ++ if (*ppos <= 0) ++ return -EINVAL; ++ ++ if (!count) ++ return 0; ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ buf = vmalloc(count); ++ if (!buf) { ++ ret = -ENOMEM; ++ goto error_unlock; ++ } ++ ++ ret = copy_from_user(buf, user_buf, count); ++ if (ret) { ++ ret = -EFAULT; ++ goto exit; ++ } ++ ++ ret = ath12k_qmi_mem_write(ar->ab, *ppos, buf, count); ++ if (ret < 0) { ++ ath12k_warn(ar->ab, "failed to write address 0x%08x via diagnose window from debugfs: %d\n", ++ (u32)(*ppos), ret); ++ goto exit; ++ } ++ ++ *ppos += count; ++ ret = count; ++ ++exit: ++ vfree(buf); ++ ++error_unlock: ++ mutex_unlock(&ar->conf_mutex); ++ return ret; ++} ++ ++static const struct file_operations fops_athdiag = { ++ .read = ath12k_athdiag_read, ++ .write = ath12k_athdiag_write, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ + int ath12k_debugfs_register(struct ath12k *ar) + { + struct ath12k_base *ab = ar->ab; +@@ -2532,6 +2631,10 @@ int ath12k_debugfs_register(struct ath12 + ar->debug.debugfs_pdev, ar, + &fops_dump_mgmt_stats); + ++ debugfs_create_file("athdiag", S_IRUSR | S_IWUSR, ++ ar->debug.debugfs_pdev, ar, ++ &fops_athdiag); ++ + return 0; + } + diff --git a/feeds/ipq95xx/mac80211/patches/qca/694-ath12k-drop-packets-with-invalid-peer-id-in-dp_tx-pa.patch b/feeds/ipq95xx/mac80211/patches/qca/711-ath12k-drop-packets-with-invalid-peer-id-in-dp_tx-pa.patch similarity index 68% rename from feeds/ipq95xx/mac80211/patches/qca/694-ath12k-drop-packets-with-invalid-peer-id-in-dp_tx-pa.patch rename to feeds/ipq95xx/mac80211/patches/qca/711-ath12k-drop-packets-with-invalid-peer-id-in-dp_tx-pa.patch index 20dc294d7..de6da4c1e 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/694-ath12k-drop-packets-with-invalid-peer-id-in-dp_tx-pa.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/711-ath12k-drop-packets-with-invalid-peer-id-in-dp_tx-pa.patch @@ -1,6 +1,6 @@ -From 8482caa4ec57477d57be5cb26a2380dda644746b Mon Sep 17 00:00:00 2001 +From 034ed9182124bec149ca85dd68fbd58d69487a43 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Chitrapu -Date: Fri, 18 Nov 2022 14:34:19 -0800 +Date: Thu, 2 Feb 2023 11:50:04 -0800 Subject: [PATCH] ath12k: drop packets with invalid peer id in dp_tx path Sometime DP might receive a packet with already deleted peer id. @@ -11,11 +11,9 @@ Signed-off-by: Pradeep Kumar Chitrapu drivers/net/wireless/ath/ath12k/dp_tx.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) -diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c -index d7ceaf3133cf..5937088003cc 100644 --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -245,6 +245,7 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif, +@@ -124,6 +124,7 @@ int ath12k_dp_tx(struct ath12k *ar, stru struct ath12k_base *ab = ar->ab; struct ath12k_hw_group *ag = ab->ag; struct ath12k_dp *dp = &ab->dp; @@ -23,33 +21,30 @@ index d7ceaf3133cf..5937088003cc 100644 struct hal_tx_info ti = {0}; struct ath12k_tx_desc_info *tx_desc = NULL; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); -@@ -257,6 +258,7 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif, - void *hal_tcl_desc; - u8 hal_ring_id; +@@ -138,6 +139,7 @@ int ath12k_dp_tx(struct ath12k *ar, stru int ret; + u8 ring_selector = 0, ring_map = 0; + bool tcl_ring_retry; + u16 peer_id; bool msdu_ext_desc = false; if (unlikely(test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))) -@@ -285,6 +287,18 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif, - arsta->use_4addr_set) { - ti.meta_data_flags = arsta->tcl_metadata; +@@ -184,6 +186,18 @@ tcl_ring_sel: + /* TODO set tcl metadata based on primary link sta ? */ + ti.meta_data_flags = ahsta->deflink.tcl_metadata; ti.flags0 |= FIELD_PREP(HAL_TCL_DATA_CMD_INFO2_TO_FW, 1); + spin_lock_bh(&ab->base_lock); + peer_id = FIELD_GET(HTT_TCL_META_DATA_PEER_ID, ti.meta_data_flags); + peer = ath12k_peer_find_by_id(ab, peer_id); + if (!peer || !peer->sta) { ++ spin_unlock_bh(&ab->base_lock); + ath12k_dbg(ab, ATH12K_DBG_DP_TX, + "Dropped packet with non existent peer id %u\n", peer_id); + ret = -EINVAL; -+ spin_unlock_bh(&ab->base_lock); -+ goto fail_unmap_dma; ++ goto fail_remove_tx_buf; + } + spin_unlock_bh(&ab->base_lock); + } else { ti.meta_data_flags = arvif->tcl_metadata; } --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/711-ath12k-fix-qmi-handler-terminator-entry.patch b/feeds/ipq95xx/mac80211/patches/qca/711-ath12k-fix-qmi-handler-terminator-entry.patch new file mode 100644 index 000000000..7933a5adf --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/711-ath12k-fix-qmi-handler-terminator-entry.patch @@ -0,0 +1,68 @@ +From 9afd783fd50685cbde82dce89d02edf781f26470 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Kathirvel +Date: Wed, 8 Feb 2023 15:03:02 +0530 +Subject: [PATCH] ath12k: fix qmi handler terminator entry + +Since there is no terminator entry for ath12k_qmi_msg_handlers facing +below KASAN warning, + +[ 20.006340] ================================================================== +[ 20.006385] BUG: KASAN: global-out-of-bounds in qmi_invoke_handler+0xa4/0x148 +[ 20.012453] Read of size 8 at addr ffffffd00a6428d8 by task kworker/u8:2/1273 +[ 20.019652] +[ 20.026773] CPU: 0 PID: 1273 Comm: kworker/u8:2 Not tainted 5.4.213 #0 +[ 20.028334] Hardware name: Qualcomm Technologies, Inc. IPQ9574/AP-AL02-C4 (DT) +[ 20.034681] Workqueue: qmi_msg_handler qmi_data_ready_work +[ 20.041873] Call trace: +[ 20.047347] dump_backtrace+0x0/0x20c +[ 20.049690] show_stack+0x14/0x1c +[ 20.053509] dump_stack+0xe0/0x138 +[ 20.056808] print_address_description.isra.5+0x30/0x330 +[ 20.060106] __kasan_report+0x16c/0x1bc +[ 20.065573] kasan_report+0xc/0x14 +[ 20.069132] __asan_load8+0xa8/0xb0 +[ 20.072605] qmi_invoke_handler+0xa4/0x148 +[ 20.075990] qmi_handle_message+0x18c/0x1bc +[ 20.080157] qmi_data_ready_work+0x4ec/0x528 +[ 20.084242] process_one_work+0x2c0/0x440 +[ 20.088753] worker_thread+0x324/0x4b8 +[ 20.092657] kthread+0x210/0x228 +[ 20.096302] ret_from_fork+0x10/0x18 +[ 20.099682] +[ 20.103246] The address belongs to the variable: +[ 20.104827] ath12k_mac_mon_status_filter_default+0x4bd8/0xfffffffffffe2300 [ath12k] +[ 20.109668] +[ 20.117563] Memory state around the address: +[ 20.119049] ffffffd00a642780: 00 00 00 00 00 00 02 fa fa fa fa fa 00 00 00 00 +[ 20.123650] ffffffd00a642800: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +[ 20.130856] >ffffffd00a642880: 00 00 00 00 00 00 00 00 fa fa fa fa 00 00 00 00 +[ 20.138056] ^ +[ 20.145264] ffffffd00a642900: 00 00 fa fa fa fa fa fa 00 00 00 00 01 fa fa fa +[ 20.151428] ffffffd00a642980: fa fa fa fa 00 00 00 fa fa fa fa fa 00 00 00 06 +[ 20.158542] ================================================================== + +Fixed by adding NULL terminator entry to help qmi_invoke_handler api to +traverse upto the terminator entry without accessing out-of-boundary +index + +Signed-off-by: Karthikeyan Kathirvel +--- + drivers/net/wireless/ath/ath12k/qmi.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c +index 78887dcfdb07..5abc899b6d96 100644 +--- a/drivers/net/wireless/ath/ath12k/qmi.c ++++ b/drivers/net/wireless/ath/ath12k/qmi.c +@@ -5001,6 +5001,8 @@ static const struct qmi_msg_handler ath12k_qmi_msg_handlers[] = { + sizeof(struct qmi_wlanfw_qdss_trace_save_ind_msg_v01), + .fn = ath12k_wlfw_qdss_trace_save_ind_cb, + }, ++ /* (Additions here) */ ++ { /* terminator entry */ } + }; + + static int ath12k_qmi_ops_new_server(struct qmi_handle *qmi_hdl, +-- +2.38.0 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/711-ath12k-fix-register-access-after-power-down-the-targ.patch b/feeds/ipq95xx/mac80211/patches/qca/711-ath12k-fix-register-access-after-power-down-the-targ.patch new file mode 100644 index 000000000..1b86e368d --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/711-ath12k-fix-register-access-after-power-down-the-targ.patch @@ -0,0 +1,81 @@ +From c81714b45e1ad026b4cd1765c78bc164a7be5ad2 Mon Sep 17 00:00:00 2001 +From: P Praneesh +Date: Fri, 3 Feb 2023 12:04:08 +0530 +Subject: [PATCH] ath12k: fix register access after power down the target + +During rmmod, REO QUEUE LUT base address is reset to 0 after +target power down which is invalid access. + +Fix it by reset the REO QUEUE LUT address before target power +down. + +Signed-off-by: P Praneesh +--- + drivers/net/wireless/ath/ath12k/core.c | 21 +++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/dp.c | 2 -- + 2 files changed, 21 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c +index 7a9993d..036b1bb 100644 +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -1724,6 +1724,8 @@ static void ath12k_core_hw_group_destroy(struct ath12k_hw_group *ag) + static void ath12k_core_hw_group_stop(struct ath12k_hw_group *ag) + { + struct ath12k_base *ab; ++ struct ath12k_dp *dp; ++ u32 address; + int i; + + lockdep_assert_held(&ag->mutex_lock); +@@ -1761,9 +1763,28 @@ static void ath12k_core_hw_group_stop(struct ath12k_hw_group *ag) + + for (i = ag->num_chip - 1; i >= 0; i--) { + ab = ag->ab[i]; ++ dp = &ab->dp; + + mutex_lock(&ab->core_lock); + ++ if (!ab->hw_params->reoq_lut_support) ++ break; ++ ++ if (!dp->reoq_lut.vaddr) ++ break; ++ ++ if (dp->reoq_lut.vaddr) { ++ address = HAL_SEQ_WCSS_UMAC_REO_REG +\ ++ HAL_REO1_QDESC_LUT_BASE0(ab); ++ ath12k_hif_write32(ab, address, 0); ++ } ++ ++ if (dp->ml_reoq_lut.vaddr) { ++ address = HAL_SEQ_WCSS_UMAC_REO_REG +\ ++ HAL_REO1_QDESC_LUT_BASE1(ab); ++ ath12k_hif_write32(ab, address, 0); ++ } ++ + ath12k_hif_power_down(ab); + + mutex_unlock(&ab->core_lock); +diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c +index 05169dd..ba3ebda 100644 +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -1263,14 +1263,12 @@ static void ath12k_dp_reoq_lut_cleanup(struct ath12k_base *ab) + return; + + if (dp->reoq_lut.vaddr) { +- ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_LUT_BASE0(ab), 0); + dma_free_coherent(ab->dev, DP_REOQ_LUT_SIZE, + dp->reoq_lut.vaddr, dp->reoq_lut.paddr); + dp->reoq_lut.vaddr = NULL; + } + + if (dp->ml_reoq_lut.vaddr) { +- ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_LUT_BASE1(ab), 0); + dma_free_coherent(ab->dev, DP_REOQ_LUT_SIZE, + dp->ml_reoq_lut.vaddr, dp->ml_reoq_lut.paddr); + dp->ml_reoq_lut.vaddr = NULL; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/711-wifi-mac80211-add-accumulated-statistics-for-Multi-lin.patch b/feeds/ipq95xx/mac80211/patches/qca/711-wifi-mac80211-add-accumulated-statistics-for-Multi-lin.patch new file mode 100644 index 000000000..5b415568b --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/711-wifi-mac80211-add-accumulated-statistics-for-Multi-lin.patch @@ -0,0 +1,328 @@ +From 57e6aa2970641b4f1490b7da1ac5fd362ef711bf Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Wed, 1 Feb 2023 11:47:27 +0530 +Subject: [PATCH] wifi: mac80211: add accumulated statistics for Multi link + +Add acummulated statistics for the below params in the ML STA, + 1. rx_pkt + 2. rx_byte + 3. tx_pkt + 4. tx_byte + 5. rx_drop_misc + 6. tx_retry + +Other params are report from the associated link in the station dump. + +Also avoid below call trace, due to the call of ieee80211_get_sband() in the +ML VAP. we fix it by get the sdata of that link by ieee80211_get_link_sband(). + +Trace: + +------------[ cut here ]------------ +WARNING: CPU: 1 PID: 19341 at /local/mnt/workspace/periyasa/ath12k_19Jan2023/qsdk/build_dir/target-aarch64_cortex-a73+neon-vfpv4_musl/linux-ipq95xx_generic/backports-20220822-5.4.213-ef7197 +Modules linked in: ath12k mac80211 nf_flow_table_ipv6 nf_flow_table_ipv4 nf_flow_table_inet ipt_REJECT cfg80211 xt_time xt_tcpudp xt_tcpmss xt_string xt_statistic xt_state xt_recent xt_quot + nf_conntrack_rtsp nf_conntrack_rtcache nf_conntrack_pptp nf_conntrack_netlink nf_conntrack_irc nf_conntrack_h323 nf_conntrack_ftp nf_conntrack_broadcast ts_kmp nf_conntrack_amanda iptable_ + qca_nss_ppe_pppoe_mgr qca_nss_ppe_lag qca_nss_ppe_bridge_mgr qca_nss_ppe_vlan libcomposite udc_core usb_common xt_sctp xt_set ip_set_list_set ip_set_hash_netportnet ip_set_hash_netport ip_ + qca_nss_ppe_rule qca_nss_ppe nat46 nf_conntrack pptp pppox ppp_generic slhc nf_defrag_ipv4 libcrc32c gre emesh_sp qca_ssdk nf_defrag_ipv6 md5 authenc bootconfig gpio_button_hotplug button_ +CPU: 1 PID: 19341 Comm: hostapd Tainted: G W 5.4.213 #0 +Hardware name: Qualcomm Technologies, Inc. IPQ9574/AP-AL02-C4 (DT) +pstate: 60400005 (nZCv daif +PAN -UAO) +pc : sta_set_rate_info_tx+0xc0/0x19c [mac80211] +lr : sta_set_rate_info_tx+0xb0/0x19c [mac80211] +sp : ffffff80336ab630 +x29: ffffff80336ab630 x28: ffffff8028f610e0 +x27: 0000000000000000 x26: 0000048111839e02 +x25: ffffff801b8736e8 x24: ffffff801b873680 +x23: ffffff8028f610e0 x22: ffffff80300048c0 +x21: 0000000000000000 x20: ffffff801b873968 +x19: ffffff802358a638 x18: 0000000000000000 +x17: 0000000000000000 x16: 0000000000000000 +x15: 0000000000000000 x14: 3030303030303020 +x13: 6174735f66656420 x12: 6639613639343864 +x11: 3030303030303030 x10: 206f666e695f6174 +x9 : ffffffc0109b6000 x8 : ffffffffffffffff +x7 : 0000000000000000 x6 : 0000000000000001 +x5 : 0000000000000000 x4 : 000000000000000f +x3 : ffffffc010aa8778 x2 : ffffff802358a638 +x1 : 0000000000000000 x0 : 0000000000000003 +Call trace: + sta_set_rate_info_tx+0xc0/0x19c [mac80211] + sta_set_sinfo+0x3f4/0x9a4 [mac80211] + __sta_info_destroy_part2+0xe4/0x13c [mac80211] + __sta_info_flush+0x110/0x164 [mac80211] + ieee80211_stop_ap+0x14c/0x2d0 [mac80211] + cfg80211_leave_mesh+0xc0/0x164 [cfg80211] + __cfg80211_stop_ap+0x78/0xa8 [cfg80211] + cfg80211_stop_ap+0x48/0x6c [cfg80211] + cfg80211_vendor_cmd_reply+0x204c/0x23b0 [cfg80211] + genl_family_rcv_msg+0x314/0x3b0 + genl_rcv_msg+0x58/0x84 + netlink_rcv_skb+0x94/0x10c + genl_rcv+0x34/0x48 + netlink_unicast+0x15c/0x248 + netlink_sendmsg+0x320/0x3bc + sock_sendmsg+0x18/0x2c + ____sys_sendmsg+0x2c4/0x350 + ___sys_sendmsg+0x7c/0xc4 + __sys_sendmsg+0x64/0xac + __arm64_sys_sendmsg+0x1c/0x24 + el0_svc_common.constprop.0+0x98/0x114 + el0_svc_handler+0x18/0x20 + el0_svc+0x8/0x500 +---[ end trace e15307d11438e309 ]--- + +Signed-off-by: Karthikeyan Periyasamy +--- + net/mac80211/cfg.c | 2 +- + net/mac80211/sta_info.c | 203 ++++++++++++++++++++++++++-------------- + 2 files changed, 133 insertions(+), 72 deletions(-) + +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -831,7 +831,7 @@ void sta_set_rate_info_tx(struct sta_inf + int shift = ieee80211_vif_get_shift(&sta->sdata->vif); + u16 brate; + +- sband = ieee80211_get_sband(sta->sdata); ++ sband = ieee80211_get_link_sband(&sta->sdata->deflink); + WARN_ON_ONCE(sband && !sband->bitrates); + if (sband && sband->bitrates) { + brate = sband->bitrates[rate->idx].bitrate; +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -2417,13 +2417,112 @@ static inline u64 sta_get_stats_bytes(st + return value; + } + ++static u64 link_sta_set_info(struct link_sta_info *link_sta, ++ struct station_info *sinfo, ++ bool init) ++{ ++ int ac, cpu; ++ u64 filled = 0; ++ ++ if (!(sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES64) | ++ BIT_ULL(NL80211_STA_INFO_TX_BYTES)))) { ++ if (init) ++ sinfo->tx_bytes = 0; ++ ++ for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) ++ sinfo->tx_bytes += link_sta->tx_stats.bytes[ac]; ++ ++ filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES64); ++ } ++ ++ if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_PACKETS))) { ++ if (init) ++ sinfo->tx_packets = 0; ++ ++ for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) ++ sinfo->tx_packets += link_sta->tx_stats.packets[ac]; ++ ++ filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS); ++ } ++ ++ if (!(sinfo->filled & (BIT_ULL(NL80211_STA_INFO_RX_BYTES64) | ++ BIT_ULL(NL80211_STA_INFO_RX_BYTES)))) { ++ if (init) ++ sinfo->rx_bytes = 0; ++ ++ sinfo->rx_bytes += sta_get_stats_bytes(&link_sta->rx_stats); ++ ++ if (link_sta->pcpu_rx_stats) { ++ for_each_possible_cpu(cpu) { ++ struct ieee80211_sta_rx_stats *cpurxs; ++ ++ cpurxs = per_cpu_ptr(link_sta->pcpu_rx_stats, ++ cpu); ++ sinfo->rx_bytes += sta_get_stats_bytes(cpurxs); ++ } ++ } ++ ++ filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES64); ++ } ++ ++ if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_PACKETS))) { ++ if (init) ++ sinfo->rx_packets = 0; ++ ++ sinfo->rx_packets += link_sta->rx_stats.packets; ++ if (link_sta->pcpu_rx_stats) { ++ for_each_possible_cpu(cpu) { ++ struct ieee80211_sta_rx_stats *cpurxs; ++ ++ cpurxs = per_cpu_ptr(link_sta->pcpu_rx_stats, ++ cpu); ++ sinfo->rx_packets += cpurxs->packets; ++ } ++ } ++ ++ filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS); ++ } ++ ++ if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_RETRIES))) { ++ if (init) ++ sinfo->tx_retries = 0; ++ ++ sinfo->tx_retries += link_sta->status_stats.retry_count; ++ ++ filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES); ++ } ++ ++ if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_FAILED))) { ++ if (init) ++ sinfo->tx_failed = 0; ++ ++ sinfo->tx_failed += link_sta->status_stats.retry_failed; ++ filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED); ++ } ++ ++ if (init) ++ sinfo->rx_dropped_misc = 0; ++ ++ sinfo->rx_dropped_misc += link_sta->rx_stats.dropped; ++ if (link_sta->pcpu_rx_stats) { ++ for_each_possible_cpu(cpu) { ++ struct ieee80211_sta_rx_stats *cpurxs; ++ ++ cpurxs = per_cpu_ptr(link_sta->pcpu_rx_stats, cpu); ++ sinfo->rx_dropped_misc += cpurxs->dropped; ++ } ++ } ++ ++ return filled; ++} ++ + void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo, + bool tidstats) + { + struct ieee80211_sub_if_data *sdata = sta->sdata; + struct ieee80211_local *local = sdata->local; + u32 thr = 0; +- int i, ac, cpu, link_id = 0; ++ int i, ac, link_id = 0; + struct ieee80211_sta_rx_stats *last_rxstats; + struct link_sta_info *link_sta = NULL; + +@@ -2460,10 +2559,12 @@ void sta_set_sinfo(struct sta_info *sta, + sinfo->valid_links = sta->sta.valid_links; + + if (sinfo->valid_links) { ++ u64 link_sta_filled = 0; ++ bool init = true; ++ + for_each_valid_link(sinfo, link_id) { + rcu_read_lock(); + link_sta = rcu_dereference(sta->link[link_id]); +- + if (!link_sta) { + rcu_read_unlock(); + continue; +@@ -2471,65 +2572,18 @@ void sta_set_sinfo(struct sta_info *sta, + + memcpy(sinfo->links[link_id].addr, link_sta->addr, + ETH_ALEN); +- rcu_read_unlock(); +- } +- } +- +- if (!(sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES64) | +- BIT_ULL(NL80211_STA_INFO_TX_BYTES)))) { +- sinfo->tx_bytes = 0; +- for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) +- sinfo->tx_bytes += sta->deflink.tx_stats.bytes[ac]; +- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES64); +- } +- +- if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_PACKETS))) { +- sinfo->tx_packets = 0; +- for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) +- sinfo->tx_packets += sta->deflink.tx_stats.packets[ac]; +- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS); +- } +- +- if (!(sinfo->filled & (BIT_ULL(NL80211_STA_INFO_RX_BYTES64) | +- BIT_ULL(NL80211_STA_INFO_RX_BYTES)))) { +- sinfo->rx_bytes += sta_get_stats_bytes(&sta->deflink.rx_stats); +- +- if (sta->deflink.pcpu_rx_stats) { +- for_each_possible_cpu(cpu) { +- struct ieee80211_sta_rx_stats *cpurxs; + +- cpurxs = per_cpu_ptr(sta->deflink.pcpu_rx_stats, +- cpu); +- sinfo->rx_bytes += sta_get_stats_bytes(cpurxs); +- } +- } +- +- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES64); +- } +- +- if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_PACKETS))) { +- sinfo->rx_packets = sta->deflink.rx_stats.packets; +- if (sta->deflink.pcpu_rx_stats) { +- for_each_possible_cpu(cpu) { +- struct ieee80211_sta_rx_stats *cpurxs; +- +- cpurxs = per_cpu_ptr(sta->deflink.pcpu_rx_stats, +- cpu); +- sinfo->rx_packets += cpurxs->packets; +- } ++ link_sta_filled |= link_sta_set_info(link_sta, sinfo, ++ init); ++ init = false; ++ rcu_read_unlock(); + } +- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS); +- } + +- if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_RETRIES))) { +- sinfo->tx_retries = sta->deflink.status_stats.retry_count; +- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES); ++ sinfo->filled |= link_sta_filled; ++ } else { ++ sinfo->filled |= link_sta_set_info(&sta->deflink, sinfo, true); + } + +- if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_FAILED))) { +- sinfo->tx_failed = sta->deflink.status_stats.retry_failed; +- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED); +- } + + if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_DURATION))) { + for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) +@@ -2548,16 +2602,6 @@ void sta_set_sinfo(struct sta_info *sta, + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_AIRTIME_WEIGHT); + } + +- sinfo->rx_dropped_misc = sta->deflink.rx_stats.dropped; +- if (sta->deflink.pcpu_rx_stats) { +- for_each_possible_cpu(cpu) { +- struct ieee80211_sta_rx_stats *cpurxs; +- +- cpurxs = per_cpu_ptr(sta->deflink.pcpu_rx_stats, cpu); +- sinfo->rx_dropped_misc += cpurxs->dropped; +- } +- } +- + if (sdata->vif.type == NL80211_IFTYPE_STATION && + !(sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER)) { + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_BEACON_RX) | +@@ -2601,15 +2645,13 @@ void sta_set_sinfo(struct sta_info *sta, + } + } + +- if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) && +- !sta->sta.valid_links) { ++ if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE))) { + sta_set_rate_info_tx(sta, &sta->deflink.tx_stats.last_rate, + &sinfo->txrate); + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); + } + +- if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE)) && +- !sta->sta.valid_links) { ++ if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE))) { + if (sta_set_rate_info_rx(sta, &sinfo->rxrate) == 0) + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE); + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/712-01-cfg80211-add-support-rts-threshold-readable-command-.patch b/feeds/ipq95xx/mac80211/patches/qca/712-01-cfg80211-add-support-rts-threshold-readable-command-.patch new file mode 100644 index 000000000..df9f128b1 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/712-01-cfg80211-add-support-rts-threshold-readable-command-.patch @@ -0,0 +1,37 @@ +From a917148f469be6cb8a8fbae888634bf2e75ce50d Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Fri, 17 Feb 2023 16:21:58 +0530 +Subject: [PATCH] cfg80211: add support rts threshold readable command for MLO + +To avoid creating rts_threshold file for MLO. + +Existing rts_threshold for non MLO case +cat /sys/kernel/debug/ieee80211/phyX/rts_threshold + +proposed solution for single wiphy architecture +SLO: cat /sys/kernel/debug/ieee80211/phy0/netdev:wlanX/link0/rts_threshold +MLO: cat /sys/kernel/debug/ieee80211/phy0/netdev:wlanX/linkY/rts_threshold + +Signed-off-by: Aaradhana Sahu +--- + net/wireless/debugfs.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c +index aab4346..701fcb6 100644 +--- a/net/wireless/debugfs.c ++++ b/net/wireless/debugfs.c +@@ -102,7 +102,9 @@ void cfg80211_debugfs_rdev_add(struct cfg80211_registered_device *rdev) + { + struct dentry *phyd = rdev->wiphy.debugfsdir; + +- DEBUGFS_ADD(rts_threshold); ++ if (!rdev->wiphy.num_hw) ++ DEBUGFS_ADD(rts_threshold); ++ + DEBUGFS_ADD(fragmentation_threshold); + DEBUGFS_ADD(short_retry_limit); + DEBUGFS_ADD(long_retry_limit); +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/712-02-ath12k-add-support-rts-threshold-readable-command-fo.patch b/feeds/ipq95xx/mac80211/patches/qca/712-02-ath12k-add-support-rts-threshold-readable-command-fo.patch new file mode 100644 index 000000000..eea9069b6 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/712-02-ath12k-add-support-rts-threshold-readable-command-fo.patch @@ -0,0 +1,145 @@ +From b00a94bd96573978940dc2c6932033b009d3a634 Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Fri, 17 Feb 2023 16:27:51 +0530 +Subject: [PATCH] ath12k: add support rts threshold readable command for MLO + +Currently, we are getting rts threshold for each phy. But, +in multi-link operation we have only one phy due to this +we are not able to get correct rts threshold value for +different vaps. + +So, Fix this issue by creating rts_threshold file per netdev +for MLO. + +Existing rts_threshold for non MLO case +cat /sys/kernel/debug/ieee80211/phyX/rts_threshold + +proposed solution for single wiphy architecture +SLO: cat /sys/kernel/debug/ieee80211/phy0/netdev:wlanX/link0/rts_threshold +MLO: cat /sys/kernel/debug/ieee80211/phy0/netdev:wlanX/linkY/rts_threshold + +Signed-off-by: Aaradhana Sahu +--- + drivers/net/wireless/ath/ath12k/debugfs.c | 48 ++++++++++++++++++++++- + 1 file changed, 46 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -3134,6 +3134,47 @@ static ssize_t ath12k_write_twt_resume_d + return count; + } + ++static ssize_t ath12k_read_rts_threshold(struct file *file, ++ const char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k_link_vif *arvif = file->private_data; ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ieee80211_vif *vif = ahvif->vif; ++ u8 link_id = arvif->link_id; ++ struct ieee80211_bss_conf *link_conf; ++ int ret, len = 0; ++ const int size = 20; ++ char *buf; ++ ++ rcu_read_lock(); ++ link_conf = rcu_dereference(vif->link_conf[link_id]); ++ ++ if (!link_conf) { ++ rcu_read_unlock(); ++ return -EINVAL; ++ } ++ ++ buf = kzalloc(size, GFP_KERNEL); ++ ++ if (!buf) { ++ rcu_read_unlock(); ++ return -ENOMEM; ++ } ++ ++ len = scnprintf(buf + len, size - len, ++ "%d\n", link_conf->rts_threshold); ++ rcu_read_unlock(); ++ ret = simple_read_from_buffer(ubuf, count, ppos, buf, len); ++ kfree(buf); ++ return ret; ++} ++ ++static const struct file_operations ath12k_fops_rts_threshold = { ++ .read = ath12k_read_rts_threshold, ++ .open = simple_open ++}; ++ + static const struct file_operations ath12k_fops_twt_add_dialog = { + .write = ath12k_write_twt_add_dialog, + .open = simple_open +@@ -3171,12 +3212,18 @@ int ath12k_debugfs_add_interface(struct + if (arvif->debugfs_twt) + goto exit; + +- if (!hw->wiphy->num_hw) ++ if (!hw->wiphy->num_hw) { + arvif->debugfs_twt = debugfs_create_dir("twt", + vif->debugfs_dir); +- else ++ } else { + arvif->debugfs_twt = debugfs_create_dir("twt", + vif->link_debugfs[link_id]); ++ arvif->debugfs_rtsthreshold = debugfs_create_file("rts_threshold", ++ 0200, ++ vif->link_debugfs[link_id], ++ arvif, ++ &ath12k_fops_rts_threshold); ++ } + + if (!arvif->debugfs_twt || IS_ERR(arvif->debugfs_twt)) { + ath12k_warn(arvif->ar->ab, +@@ -3199,6 +3246,19 @@ int ath12k_debugfs_add_interface(struct + debugfs_create_file("resume_dialog", 0200, arvif->debugfs_twt, + arvif, &ath12k_fops_twt_resume_dialog); + ++ if (hw->wiphy->num_hw) { ++ if (!arvif->debugfs_rtsthreshold || IS_ERR(arvif->debugfs_rtsthreshold)) { ++ ath12k_warn(arvif->ar->ab, ++ "failed to create file %p\n", ++ arvif->debugfs_rtsthreshold); ++ debugfs_remove_recursive(arvif->debugfs_twt); ++ arvif->debugfs_twt = NULL; ++ arvif->debugfs_rtsthreshold = NULL; ++ ret = -ENOMEM; ++ goto exit; ++ } ++ } ++ + exit: + return ret; + } +@@ -3212,11 +3272,18 @@ void ath12k_debugfs_remove_interface(str + if (!arvif->debugfs_twt) + return; + ++ if (!arvif->debugfs_rtsthreshold) ++ return; ++ + if (!vif || !vif->link_debugfs[link_id]) { + arvif->debugfs_twt = NULL; ++ arvif->debugfs_rtsthreshold = NULL; + return; + } + + debugfs_remove_recursive(arvif->debugfs_twt); + arvif->debugfs_twt = NULL; ++ ++ debugfs_remove(arvif->debugfs_rtsthreshold); ++ arvif->debugfs_rtsthreshold = NULL; + } +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -357,6 +357,7 @@ struct ath12k_link_vif { + u32 vht_cap; + #ifdef CPTCFG_ATH12K_DEBUGFS + struct dentry *debugfs_twt; ++ struct dentry *debugfs_rtsthreshold; + #endif /* CPTCFG_ATH12K_DEBUGFS */ + struct work_struct update_bcn_template_work; + u64 obss_color_bitmap; diff --git a/feeds/ipq95xx/mac80211/patches/qca/712-UPSTREAM-cfg80211-Fix-bitrates-overflow-issue.patch b/feeds/ipq95xx/mac80211/patches/qca/712-UPSTREAM-cfg80211-Fix-bitrates-overflow-issue.patch new file mode 100644 index 000000000..b6abc8427 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/712-UPSTREAM-cfg80211-Fix-bitrates-overflow-issue.patch @@ -0,0 +1,60 @@ +From: Paul Zhang +Subject: [PATCH v1] cfg80211: Fix bitrates overflow issue + +When invoking function cfg80211_calculate_bitrate_eht about +(320 MHz, EHT-MCS 13, EHT-NSS 2, EHT-GI 0), which means the +parameters as flags: 0x80, bw: 7, mcs: 13, eht_gi: 0, nss: 2, +this formula (result * rate->nss) will overflow and causes +the returned bitrate to be 3959 when it should be 57646. + +Here is the explanation: + u64 tmp; + u32 result; + … + /* tmp = result = 4 * rates_996[0] + * = 4 * 480388888 = 0x72889c60 + */ + tmp = result; + + /* tmp = 0x72889c60 * 6144 = 0xabccea90000 */ + tmp *= SCALE; + + /* tmp = 0xabccea90000 / mcs_divisors[13] + * = 0xabccea90000 / 5120 = 0x8970bba6 + */ + do_div(tmp, mcs_divisors[rate->mcs]); + + /* result = 0x8970bba6 */ + result = tmp; + + /* normally (result * rate->nss) = 0x8970bba6 * 2 = 0x112e1774c, + * but since result is u32, (result * rate->nss) = 0x12e1774c, + * overflow happens and it loses the highest bit. + * Then result = 0x12e1774c / 8 = 39595753, + */ + result = (result * rate->nss) / 8; + +Signed-off-by: Paul Zhang +--- + net/wireless/util.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/net/wireless/util.c b/net/wireless/util.c +index f09d528..59d4947 100644 +--- a/net/wireless/util.c ++++ b/net/wireless/util.c +@@ -1557,10 +1557,12 @@ static u32 cfg80211_calculate_bitrate_eht(struct rate_info *rate) + tmp = result; + tmp *= SCALE; + do_div(tmp, mcs_divisors[rate->mcs]); +- result = tmp; + + /* and take NSS */ +- result = (result * rate->nss) / 8; ++ tmp *= rate->nss; ++ do_div(tmp, 8); ++ ++ result = tmp; + + return result / 10000; + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/693-ath12k-Update-htt_stats-for-Rx-Tx-OFDMA-stats.patch b/feeds/ipq95xx/mac80211/patches/qca/712-ath12k-Update-htt_stats-for-Rx-Tx-OFDMA-stats.patch similarity index 81% rename from feeds/ipq95xx/mac80211/patches/qca/693-ath12k-Update-htt_stats-for-Rx-Tx-OFDMA-stats.patch rename to feeds/ipq95xx/mac80211/patches/qca/712-ath12k-Update-htt_stats-for-Rx-Tx-OFDMA-stats.patch index d02819431..bccf0ddc2 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/693-ath12k-Update-htt_stats-for-Rx-Tx-OFDMA-stats.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/712-ath12k-Update-htt_stats-for-Rx-Tx-OFDMA-stats.patch @@ -5,7 +5,8 @@ Subject: [PATCH] ath12k: Update htt_stats for Rx,Tx,OFDMA stats Add support to update the htt_stats for type 9-TX_PDEV_RATE_STATS and 10-RX_PDEV_RATE_STATS and TX_PDEV_BE_OFDMA_STATS. Modify the alignment -in the existing OFDMA stats. +in the existing OFDMA stats. Update the new stats in extended Rx +htt_stats. Signed-off-by: Dinesh Karthikeyan --- @@ -13,11 +14,11 @@ Signed-off-by: Dinesh Karthikeyan .../wireless/ath/ath12k/debugfs_htt_stats.h | 20 +++++ 2 files changed, 102 insertions(+), 6 deletions(-) -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c =================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c 2022-11-19 15:18:55.874265141 +0530 -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c 2022-11-19 15:26:32.207452844 +0530 -@@ -3237,12 +3237,64 @@ static inline void htt_print_tx_pdev_rat +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c 2023-02-02 15:27:24.948374081 +0530 ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c 2023-02-02 15:27:24.944374111 +0530 +@@ -3305,12 +3305,64 @@ static inline void htt_print_tx_pdev_rat NULL, HTT_TX_PDEV_STATS_NUM_EXTRA_MCS_COUNTERS, "\n"); } @@ -84,16 +85,16 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb stats_req->buf_len = len; fail: -@@ -3491,7 +3543,7 @@ static inline void htt_print_rx_pdev_rat - htt_stats_buf->rssi_mgmt_in_dbm); - - for (j = 0; j < HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS; j++) { -- len += scnprintf(buf + len, buf_len - len, "\nrssi_chain_ext[%u] = ", j); -+ len += scnprintf(buf + len, buf_len - len, "rssi_chain_ext[%u] = ", j); - PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rssi_chain_ext[j], - NULL, HTT_RX_PDEV_STATS_NUM_BW_EXT_COUNTERS, "\n"); +@@ -3575,7 +3627,7 @@ static inline void htt_print_rx_pdev_rat + "\nrx_per_chain_rssi_ext_in_dbm[%u] = ", j); + PRINT_ARRAY_TO_BUF(buf, len, + htt_stats_buf->rx_per_chain_rssi_ext_in_dbm[j], +- "NULL", HTT_RX_PDEV_STATS_NUM_BW_EXT_COUNTERS, "\n"); ++ NULL, HTT_RX_PDEV_STATS_NUM_BW_EXT_COUNTERS, "\n"); } -@@ -3515,7 +3567,7 @@ static inline void htt_print_rx_pdev_rat + + PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_mcs_ext, +@@ -3585,7 +3637,7 @@ static inline void htt_print_rx_pdev_rat "rx_stbc_ext", HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS_EXT, "\n"); for (j = 0; j < HTT_RX_PDEV_STATS_NUM_GI_COUNTERS; j++) { @@ -102,7 +103,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_gi_ext[j], NULL, HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS_EXT, "\n"); } -@@ -3526,7 +3578,7 @@ static inline void htt_print_rx_pdev_rat +@@ -3596,7 +3648,7 @@ static inline void htt_print_rx_pdev_rat for (j = 0; j < HTT_RX_PDEV_STATS_NUM_GI_COUNTERS; j++) { len += scnprintf(buf + len, buf_len - len, @@ -111,19 +112,23 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->ul_ofdma_rx_gi_ext[j], NULL, HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS_EXT, "\n"); } -@@ -3549,8 +3601,8 @@ static inline void htt_print_rx_pdev_rat +@@ -3613,9 +3665,38 @@ static inline void htt_print_rx_pdev_rat + "rx_11ax_dl_ofdma_mcs_ext", + HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS_EXT, "\n"); - for (j = 0; j < HTT_RX_PDEV_STATS_NUM_REDUCED_CHAN_TYPES; j++) { - len += scnprintf(buf + len, buf_len - len, j == 0 ? -- "\nhalf_rx_bw = " : -- "\nquarter_rx_bw = "); ++ PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_bw_ext, ++ "rx_bw_ext", ++ HTT_RX_PDEV_STATS_NUM_BW_EXT2_COUNTERS, "\n"); ++ ++ for (j = 0; j < HTT_RX_PDEV_STATS_NUM_REDUCED_CHAN_TYPES; j++) { ++ len += scnprintf(buf + len, buf_len - len, j == 0 ? + "half_rx_bw = " : + "quarter_rx_bw = "); - PRINT_ARRAY_TO_BUF(buf, len, - htt_stats_buf->reduced_rx_bw[j], - NULL, HTT_RX_PDEV_STATS_NUM_BW_COUNTERS, "\n"); -@@ -3558,7 +3610,23 @@ static inline void htt_print_rx_pdev_rat - ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->reduced_rx_bw[j], ++ NULL, HTT_RX_PDEV_STATS_NUM_BW_COUNTERS, "\n"); ++ } ++ PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_su_punctured_mode, "rx_su_punctured_mode", - HTT_RX_PDEV_STATS_NUM_PUNCTURED_MODE_COUNTERS, "\n\n"); @@ -147,7 +152,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb stats_req->buf_len = len; } -@@ -4269,7 +4337,7 @@ htt_print_tx_pdev_be_rate_stats_tlv(cons +@@ -4326,7 +4407,7 @@ htt_print_tx_pdev_be_rate_stats_tlv(cons len += scnprintf(buf + len, buf_len - len, "HTT_TX_PDEV_BE_RATE_STATS_TLV:\n"); @@ -156,7 +161,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb htt_stats_buf->be_mu_mimo_tx_ldpc); /* MCS -2 and -1 will be printed first */ -@@ -4279,21 +4347,21 @@ htt_print_tx_pdev_be_rate_stats_tlv(cons +@@ -4336,21 +4417,21 @@ htt_print_tx_pdev_be_rate_stats_tlv(cons PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->be_mu_mimo_tx_mcs, "be_mu_mimo_tx_mcs", @@ -183,7 +188,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb } if (len >= buf_len) -@@ -4382,7 +4450,7 @@ htt_print_ul_mumimo_trig_be_stats(const +@@ -4439,7 +4520,7 @@ htt_print_ul_mumimo_trig_be_stats(const htt_ul_mumimo_trig_be_stats_buf->be_ul_mumimo_rx_gi[j][HTT_RX_PDEV_STATS_NUM_BE_MCS_COUNTERS-1]); PRINT_ARRAY_TO_BUF(buf, len, htt_ul_mumimo_trig_be_stats_buf->be_ul_mumimo_rx_gi[j], @@ -192,7 +197,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb len += scnprintf(buf + len, buf_len - len, "be_ul_mumimo_rx_gi[%u] = %s ", j, rx_gi[j]); -@@ -4406,7 +4474,7 @@ htt_print_ul_mumimo_trig_be_stats(const +@@ -4463,7 +4544,7 @@ htt_print_ul_mumimo_trig_be_stats(const for (i = 0; i < HTT_RX_PDEV_STATS_ULMUMIMO_NUM_SPATIAL_STREAMS; i++) { PRINT_ARRAY_TO_BUF(buf, len, htt_ul_mumimo_trig_be_stats_buf->be_rx_ul_mumimo_chain_rssi_in_dbm[i], @@ -201,7 +206,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb len += scnprintf(buf + len, buf_len - len, "be_rx_ul_mumimo_rssi_in_dbm: chain[%u] = %s ", i, htt_ul_mumimo_trig_be_stats_buf->be_rx_ul_mumimo_chain_rssi_in_dbm[i]); -@@ -4415,7 +4483,7 @@ htt_print_ul_mumimo_trig_be_stats(const +@@ -4472,7 +4553,7 @@ htt_print_ul_mumimo_trig_be_stats(const for (i = 0; i < HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER; i++) { PRINT_ARRAY_TO_BUF(buf, len, htt_ul_mumimo_trig_be_stats_buf->be_rx_ul_mumimo_target_rssi[i], @@ -210,7 +215,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb len += scnprintf(buf + len, buf_len - len, "be_rx_ul_mumimo_target_rssi: user[%u] = %s ", i, htt_ul_mumimo_trig_be_stats_buf->be_rx_ul_mumimo_target_rssi[i]); -@@ -4424,7 +4492,7 @@ htt_print_ul_mumimo_trig_be_stats(const +@@ -4481,7 +4562,7 @@ htt_print_ul_mumimo_trig_be_stats(const for (i = 0; i < HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER; i++) { PRINT_ARRAY_TO_BUF(buf, len, htt_ul_mumimo_trig_be_stats_buf->be_rx_ul_mumimo_fd_rssi[i], @@ -219,7 +224,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb len += scnprintf(buf + len, buf_len - len, "be_rx_ul_mumimo_fd_rssi: user[%u] = %s ", i, htt_ul_mumimo_trig_be_stats_buf->be_rx_ul_mumimo_fd_rssi[i]); -@@ -4433,7 +4501,7 @@ htt_print_ul_mumimo_trig_be_stats(const +@@ -4490,7 +4571,7 @@ htt_print_ul_mumimo_trig_be_stats(const for (i = 0; i < HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER; i++) { PRINT_ARRAY_TO_BUF(buf, len, htt_ul_mumimo_trig_be_stats_buf->be_rx_ulmumimo_pilot_evm_dB_mean[i], @@ -228,7 +233,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb len += scnprintf(buf + len, buf_len - len, "be_rx_ulmumimo_pilot_evm_dB_mean: user [%u] = %s ", i, htt_ul_mumimo_trig_be_stats_buf->be_rx_ulmumimo_pilot_evm_dB_mean[i]); -@@ -4473,24 +4541,25 @@ htt_print_be_ul_ofdma_trigger_stats(cons +@@ -4530,24 +4611,25 @@ htt_print_be_ul_ofdma_trigger_stats(cons PRINT_ARRAY_TO_BUF(buf, len, htt_trigger_stats_buf->be_ul_ofdma_rx_mcs, "be_ul_ofdma_rx_mcs", @@ -260,7 +265,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb len += scnprintf(buf + len, buf_len - len, "be_ul_ofdma_rx_stbc = %u\n", htt_trigger_stats_buf->be_ul_ofdma_rx_stbc); -@@ -4499,27 +4568,27 @@ htt_print_be_ul_ofdma_trigger_stats(cons +@@ -4556,27 +4638,27 @@ htt_print_be_ul_ofdma_trigger_stats(cons PRINT_ARRAY_TO_BUF(buf, len, htt_trigger_stats_buf->be_rx_ulofdma_data_ru_size_ppdu, "be_rx_ulofdma_data_ru_size_ppdu", @@ -294,7 +299,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb len += scnprintf(buf + len, buf_len - len, "\n"); -@@ -4608,24 +4677,33 @@ htt_print_tx_pdev_rate_stats_be_ofdma_tl +@@ -4665,24 +4747,33 @@ htt_print_tx_pdev_rate_stats_be_ofdma_tl PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->be_ofdma_tx_mcs, "be_ofdma_tx_mcs", @@ -333,11 +338,11 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb } stats_req->buf_len = len; -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h =================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h 2022-11-19 15:18:55.874265141 +0530 -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h 2022-11-19 15:18:55.870265132 +0530 -@@ -1555,6 +1555,7 @@ enum HTT_TX_PDEV_STATS_NUM_PUNCTURED_MOD +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h 2023-02-02 15:27:24.948374081 +0530 ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h 2023-02-02 15:28:48.943723823 +0530 +@@ -1566,6 +1566,7 @@ enum HTT_TX_PDEV_STATS_NUM_PUNCTURED_MOD /* 11be related updates */ #define HTT_TX_PDEV_STATS_NUM_BE_MCS_COUNTERS 16 /* 0...13,-2,-1 */ #define HTT_TX_PDEV_STATS_NUM_BE_BW_COUNTERS 5 /* 20,40,80,160,320 MHz */ @@ -345,7 +350,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb #define HTT_TX_PDEV_STATS_NUM_HE_SIG_B_MCS_COUNTERS 6 #define HTT_TX_PDEV_STATS_NUM_EHT_SIG_MCS_COUNTERS 4 -@@ -1680,6 +1681,23 @@ struct htt_tx_pdev_rate_stats_tlv { +@@ -1691,6 +1692,23 @@ struct htt_tx_pdev_rate_stats_tlv { u32 tx_gi_ext_2[HTT_TX_PDEV_STATS_NUM_GI_COUNTERS] [HTT_TX_PDEV_STATS_NUM_EXTRA2_MCS_COUNTERS]; u32 tx_su_punctured_mode[HTT_TX_PDEV_STATS_NUM_PUNCTURED_MODE_COUNTERS]; @@ -369,7 +374,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb }; /* == PDEV RX RATE CTRL STATS == */ -@@ -1705,6 +1723,7 @@ struct htt_tx_pdev_rate_stats_tlv { +@@ -1716,6 +1734,7 @@ struct htt_tx_pdev_rate_stats_tlv { #define HTT_RX_PDEV_MAX_ULMUMIMO_NUM_USER 8 #define HTT_RX_PDEV_STATS_NUM_BE_MCS_COUNTERS 16 /* 0-13, -2, -1 */ #define HTT_RX_PDEV_STATS_NUM_BE_BW_COUNTERS 5 /* 20,40,80,160,320 MHz */ @@ -377,13 +382,31 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/deb /* HTT_RX_PDEV_STATS_NUM_RU_SIZE_COUNTERS: * RU size index 0: HTT_UL_OFDMA_V0_RU_SIZE_RU_26 -@@ -1874,6 +1893,9 @@ struct htt_rx_pdev_rate_ext_stats_tlv { +@@ -1737,6 +1756,8 @@ struct htt_tx_pdev_rate_stats_tlv { + */ + #define HTT_RX_PDEV_STATS_NUM_RU_SIZE_160MHZ_CNTRS 7 /* includes 996x2 */ + ++#define HTT_RX_PDEV_STATS_NUM_REDUCED_CHAN_TYPES 2 ++ + enum HTT_RX_PDEV_STATS_BE_RU_SIZE { + HTT_RX_PDEV_STATS_BE_RU_SIZE_26, + HTT_RX_PDEV_STATS_BE_RU_SIZE_52, +@@ -1882,6 +1903,10 @@ struct htt_rx_pdev_rate_ext_stats_tlv { + u32 rx_gi_ext_2[HTT_RX_PDEV_STATS_NUM_GI_COUNTERS] [HTT_RX_PDEV_STATS_NUM_EXTRA2_MCS_COUNTERS]; u32 rx_su_punctured_mode[HTT_RX_PDEV_STATS_NUM_PUNCTURED_MODE_COUNTERS]; - u32 reduced_rx_bw[HTT_RX_PDEV_STATS_NUM_REDUCED_CHAN_TYPES][HTT_RX_PDEV_STATS_NUM_BW_COUNTERS]; ++ u32 reduced_rx_bw[HTT_RX_PDEV_STATS_NUM_REDUCED_CHAN_TYPES][HTT_RX_PDEV_STATS_NUM_BW_COUNTERS]; + u8 rssi_chain_ext_2[HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS][HTT_RX_PDEV_STATS_NUM_BW_EXT_2_COUNTERS]; + s8 rx_per_chain_rssi_ext_2_in_dbm[HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS] + [HTT_RX_PDEV_STATS_NUM_BW_EXT_2_COUNTERS]; }; /* == RX PDEV/SOC STATS == */ +@@ -2516,7 +2541,6 @@ static inline int ath12k_debugfs_htt_sta + + #endif /* CPTCFG_ATH12K_DEBUGFS */ + +-#define HTT_RX_PDEV_STATS_NUM_REDUCED_CHAN_TYPES 2 + + struct htt_rx_pdev_ul_mumimo_trig_stats_tlv { + u32 mac_id__word; diff --git a/feeds/ipq95xx/mac80211/patches/qca/712-cfg80211-mac80211-add-MLO-support-for-HE-BSS-color-c.patch b/feeds/ipq95xx/mac80211/patches/qca/712-cfg80211-mac80211-add-MLO-support-for-HE-BSS-color-c.patch new file mode 100644 index 000000000..fe70a8bd7 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/712-cfg80211-mac80211-add-MLO-support-for-HE-BSS-color-c.patch @@ -0,0 +1,791 @@ +From 4db9e30bce4b0bfe14c9095195c660595622473a Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Mon, 6 Feb 2023 19:36:03 +0530 +Subject: [PATCH] cfg80211/mac80211: add MLO support for HE-BSS color change + events + +Currently, HE-BSS color change event is handled only for non-MLO case. + +Add support for HE-BSS color change event with MLO. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath10k/mac.c | 2 +- + drivers/net/wireless/ath/ath10k/wmi.c | 2 +- + drivers/net/wireless/ath/ath11k/mac.c | 4 +- + drivers/net/wireless/ath/ath11k/wmi.c | 2 +- + drivers/net/wireless/ath/ath12k/mac.c | 10 +- + drivers/net/wireless/ath/ath9k/beacon.c | 2 +- + .../net/wireless/ath/ath9k/htc_drv_beacon.c | 2 +- + drivers/net/wireless/mac80211_hwsim.c | 3 +- + include/net/cfg80211.h | 31 ++-- + include/net/mac80211.h | 14 +- + net/mac80211/cfg.c | 156 ++++++++++++------ + net/mac80211/rx.c | 3 +- + net/mac80211/tx.c | 16 +- + net/wireless/nl80211.c | 13 +- + net/wireless/rdev-ops.h | 7 +- + net/wireless/trace.h | 11 +- + 16 files changed, 190 insertions(+), 88 deletions(-) + +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -2033,7 +2033,7 @@ static void ath10k_mac_vif_ap_csa_count_ + if (!arvif->is_up) + return; + +- if (!ieee80211_beacon_cntdwn_is_complete(vif)) { ++ if (!ieee80211_beacon_cntdwn_is_complete(vif, 0)) { + ieee80211_beacon_update_cntdwn(vif, 0); + + ret = ath10k_mac_setup_bcn_tmpl(arvif); +--- a/drivers/net/wireless/ath/ath10k/wmi.c ++++ b/drivers/net/wireless/ath/ath10k/wmi.c +@@ -3883,7 +3883,7 @@ void ath10k_wmi_event_host_swba(struct a + * actual channel switch is done + */ + if (arvif->vif->bss_conf.csa_active && +- ieee80211_beacon_cntdwn_is_complete(arvif->vif)) { ++ ieee80211_beacon_cntdwn_is_complete(arvif->vif, 0)) { + ieee80211_csa_finish(arvif->vif, 0); + continue; + } +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -1786,9 +1786,9 @@ void ath11k_mac_bcn_tx_event(struct ath1 + return; + + if (vif->bss_conf.color_change_active && +- ieee80211_beacon_cntdwn_is_complete(vif)) { ++ ieee80211_beacon_cntdwn_is_complete(vif, 0)) { + arvif->bcca_zero_sent = true; +- ieee80211_color_change_finish(vif); ++ ieee80211_color_change_finish(vif, 0); + return; + } + +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -4603,7 +4603,7 @@ ath11k_wmi_obss_color_collision_event(st + switch (ev->evt_type) { + case WMI_BSS_COLOR_COLLISION_DETECTION: + ieeee80211_obss_color_collision_notify(arvif->vif, ev->obss_color_bitmap, +- GFP_KERNEL); ++ GFP_KERNEL, 0); + ath11k_dbg(ab, ATH11K_DBG_WMI, + "OBSS color collision detected vdev:%d, event:%d, bitmap:%08llx\n", + ev->vdev_id, ev->evt_type, ev->obss_color_bitmap); +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -1667,16 +1667,17 @@ void ath12k_mac_bcn_tx_event(struct ath1 + if (!link_conf->color_change_active && !arvif->bcca_zero_sent) + return; + +- if (link_conf->color_change_active && ieee80211_beacon_cntdwn_is_complete(vif)) { ++ if (link_conf->color_change_active && ++ ieee80211_beacon_cntdwn_is_complete(vif, arvif->link_id)) { + arvif->bcca_zero_sent = true; +- ieee80211_color_change_finish(vif); ++ ieee80211_color_change_finish(vif, arvif->link_id); + return; + } + + arvif->bcca_zero_sent = false; + + if (link_conf->color_change_active && !vif->bss_conf.ema_ap) +- ieee80211_beacon_update_cntdwn(vif, 0); ++ ieee80211_beacon_update_cntdwn(vif, arvif->link_id); + ieee80211_queue_work(ar->ah->hw, &arvif->update_bcn_template_work); + } + +@@ -9044,7 +9045,8 @@ static void ath12k_update_obss_color_not + if (arvif->is_created) + ieeee80211_obss_color_collision_notify(arvif->ahvif->vif, + arvif->obss_color_bitmap, +- GFP_KERNEL); ++ GFP_KERNEL, ++ arvif->link_id); + arvif->obss_color_bitmap = 0; + mutex_unlock(&ar->conf_mutex); + } +--- a/drivers/net/wireless/ath/ath9k/beacon.c ++++ b/drivers/net/wireless/ath/ath9k/beacon.c +@@ -365,7 +365,7 @@ bool ath9k_csa_is_finished(struct ath_so + if (!vif || !vif->bss_conf.csa_active) + return false; + +- if (!ieee80211_beacon_cntdwn_is_complete(vif)) ++ if (!ieee80211_beacon_cntdwn_is_complete(vif, 0)) + return false; + + ieee80211_csa_finish(vif, 0); +--- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c ++++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +@@ -514,7 +514,7 @@ bool ath9k_htc_csa_is_finished(struct at + if (!vif || !vif->bss_conf.csa_active) + return false; + +- if (!ieee80211_beacon_cntdwn_is_complete(vif)) ++ if (!ieee80211_beacon_cntdwn_is_complete(vif, 0)) + return false; + + ieee80211_csa_finish(vif, 0); +--- a/drivers/net/wireless/mac80211_hwsim.c ++++ b/drivers/net/wireless/mac80211_hwsim.c +@@ -2079,7 +2079,8 @@ static void mac80211_hwsim_beacon_tx(voi + rcu_dereference(link_conf->chanctx_conf)->def.chan); + } + +- if (link_conf->csa_active && ieee80211_beacon_cntdwn_is_complete(vif)) ++ if (link_conf->csa_active && ++ ieee80211_beacon_cntdwn_is_complete(vif, link_id)) + ieee80211_csa_finish(vif, link_id); + } + +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -4785,7 +4785,8 @@ struct cfg80211_ops { + struct cfg80211_sar_specs *sar); + int (*color_change)(struct wiphy *wiphy, + struct net_device *dev, +- struct cfg80211_color_change_settings *params); ++ struct cfg80211_color_change_settings *params, ++ unsigned int link_id); + int (*set_fils_aad)(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_fils_aad *fils_aad); + int (*set_radar_background)(struct wiphy *wiphy, +@@ -9201,64 +9202,74 @@ void cfg80211_bss_flush(struct wiphy *wi + * @cmd: the actual event we want to notify + * @count: the number of TBTTs until the color change happens + * @color_bitmap: representations of the colors that the local BSS is aware of ++ * @link_id: valid link_id in case of MLO or 0 for non-MLO. + */ + int cfg80211_bss_color_notify(struct net_device *dev, gfp_t gfp, + enum nl80211_commands cmd, u8 count, +- u64 color_bitmap); ++ u64 color_bitmap, ++ unsigned int link_id); + + /** + * cfg80211_obss_color_collision_notify - notify about bss color collision + * @dev: network device + * @color_bitmap: representations of the colors that the local BSS is aware of + * @gfp: allocation flags ++ * @link_id: valid link_id in case of MLO or 0 for non-MLO. + */ + static inline int cfg80211_obss_color_collision_notify(struct net_device *dev, +- u64 color_bitmap, gfp_t gfp) ++ u64 color_bitmap, gfp_t gfp, ++ unsigned int link_id) + { + return cfg80211_bss_color_notify(dev, gfp, + NL80211_CMD_OBSS_COLOR_COLLISION, +- 0, color_bitmap); ++ 0, color_bitmap, link_id); + } + + /** + * cfg80211_color_change_started_notify - notify color change start + * @dev: the device on which the color is switched + * @count: the number of TBTTs until the color change happens ++ * @link_id: valid link_id in case of MLO or 0 for non-MLO. + * + * Inform the userspace about the color change that has started. + */ + static inline int cfg80211_color_change_started_notify(struct net_device *dev, +- u8 count) ++ u8 count, ++ unsigned int link_id) + { + return cfg80211_bss_color_notify(dev, GFP_KERNEL, + NL80211_CMD_COLOR_CHANGE_STARTED, +- count, 0); ++ count, 0, link_id); + } + + /** + * cfg80211_color_change_aborted_notify - notify color change abort + * @dev: the device on which the color is switched ++ * @link_id: valid link_id in case of MLO or 0 for non-MLO. + * + * Inform the userspace about the color change that has aborted. + */ +-static inline int cfg80211_color_change_aborted_notify(struct net_device *dev) ++static inline int cfg80211_color_change_aborted_notify(struct net_device *dev, ++ unsigned int link_id) + { + return cfg80211_bss_color_notify(dev, GFP_KERNEL, + NL80211_CMD_COLOR_CHANGE_ABORTED, +- 0, 0); ++ 0, 0, link_id); + } + + /** + * cfg80211_color_change_notify - notify color change completion + * @dev: the device on which the color was switched ++ * @link_id: valid link_id in case of MLO or 0 for non-MLO. + * + * Inform the userspace about the color change that has completed. + */ +-static inline int cfg80211_color_change_notify(struct net_device *dev) ++static inline int cfg80211_color_change_notify(struct net_device *dev, ++ unsigned int link_id) + { + return cfg80211_bss_color_notify(dev, GFP_KERNEL, + NL80211_CMD_COLOR_CHANGE_COMPLETED, +- 0, 0); ++ 0, 0, link_id); + } + + /** +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -5528,20 +5528,24 @@ void ieee80211_csa_finish(struct ieee802 + /** + * ieee80211_beacon_cntdwn_is_complete - find out if countdown reached 1 + * @vif: &struct ieee80211_vif pointer from the add_interface callback. ++ * @link_id: valid link_id during MLO or 0 for non-MLO + * + * This function returns whether the countdown reached zero. +- */ +-bool ieee80211_beacon_cntdwn_is_complete(struct ieee80211_vif *vif); ++*/ ++bool ieee80211_beacon_cntdwn_is_complete(struct ieee80211_vif *vif, ++ unsigned int link_id); + + /** + * ieee80211_color_change_finish - notify mac80211 about color change + * @vif: &struct ieee80211_vif pointer from the add_interface callback. ++ * @link_id: valid link_id during MLO or 0 for non-MLO + * + * After a color change announcement was scheduled and the counter in this + * announcement hits 1, this function must be called by the driver to + * notify mac80211 that the color can be changed + */ +-void ieee80211_color_change_finish(struct ieee80211_vif *vif); ++void ieee80211_color_change_finish(struct ieee80211_vif *vif, ++ unsigned int link_id); + + /** + * ieee80211_proberesp_get - retrieve a Probe Response template +@@ -7414,10 +7418,12 @@ ieee80211_get_unsol_bcast_probe_resp_tmp + * @color_bitmap: a 64 bit bitmap representing the colors that the local BSS is + * aware of. + * @gfp: allocation flags ++ * @link_id: valid link_id during MLO or 0 for non-MLO + */ + void + ieeee80211_obss_color_collision_notify(struct ieee80211_vif *vif, +- u64 color_bitmap, gfp_t gfp); ++ u64 color_bitmap, gfp_t gfp, ++ unsigned int link_id); + + /** + * ieee80211_is_tx_data - check if frame is a data frame +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1620,6 +1620,9 @@ static int ieee80211_stop_ap(struct wiph + link->csa_block_tx = false; + } + ++ /* abort any running color change switch */ ++ link_conf->color_change_active = false; ++ + mutex_unlock(&local->mtx); + + /* The below work requires sdata lock which we have already acquired +@@ -1629,6 +1632,9 @@ static int ieee80211_stop_ap(struct wiph + */ + cancel_work_sync(&link->csa_finalize_work); + ++ /* see comment above */ ++ cancel_work_sync(&link->color_change_finalize_work); ++ + ieee80211_free_next_beacon(link); + + /* turn off carrier for this interface and dependent VLANs */ +@@ -4033,13 +4039,13 @@ static int ieee80211_set_csa_beacon(stru + return 0; + } + +-static void ieee80211_color_change_abort(struct ieee80211_sub_if_data *sdata) ++static void ieee80211_color_change_abort(struct ieee80211_link_data *link) + { +- sdata->vif.bss_conf.color_change_active = false; ++ link->conf->color_change_active = false; + +- ieee80211_free_next_beacon(&sdata->deflink); ++ ieee80211_free_next_beacon(link); + +- cfg80211_color_change_aborted_notify(sdata->dev); ++ cfg80211_color_change_aborted_notify(link->sdata->dev, link->link_id); + } + + static int +@@ -4121,7 +4127,7 @@ __ieee80211_channel_switch(struct wiphy + + /* if there is a color change in progress, abort it */ + if (link_conf->color_change_active) +- ieee80211_color_change_abort(sdata); ++ ieee80211_color_change_abort(link); + + err = ieee80211_set_csa_beacon(link, params, &changed); + if (err) { +@@ -4852,24 +4858,28 @@ static int ieee80211_set_sar_specs(struc + } + + static int +-ieee80211_set_after_color_change_beacon(struct ieee80211_sub_if_data *sdata, ++ieee80211_set_after_color_change_beacon(struct ieee80211_link_data *link, + u32 *changed) + { ++ struct ieee80211_sub_if_data *sdata = link->sdata; ++ + switch (sdata->vif.type) { + case NL80211_IFTYPE_AP: { + int ret; + +- if (!sdata->deflink.u.ap.next_beacon) ++ if (!link->u.ap.next_beacon) + return -EINVAL; + +- ret = ieee80211_assign_beacon(sdata, &sdata->deflink, +- sdata->deflink.u.ap.next_beacon, ++ ret = ieee80211_assign_beacon(sdata, link, ++ link->u.ap.next_beacon, + NULL, NULL); +- ieee80211_free_next_beacon(&sdata->deflink); ++ ieee80211_free_next_beacon(link); + + if (ret < 0) + return ret; + ++ link->conf->critical_update_flag &= ~IEEE80211_CU_INCLUDE_BCCA_ELEM; ++ + *changed |= ret; + break; + } +@@ -4882,18 +4892,19 @@ ieee80211_set_after_color_change_beacon( + } + + static int +-ieee80211_set_color_change_beacon(struct ieee80211_sub_if_data *sdata, ++ieee80211_set_color_change_beacon(struct ieee80211_link_data *link, + struct cfg80211_color_change_settings *params, + u32 *changed) + { ++ struct ieee80211_sub_if_data *sdata = link->sdata; + struct ieee80211_color_change_settings color_change = {}; + int err; + + switch (sdata->vif.type) { + case NL80211_IFTYPE_AP: +- sdata->deflink.u.ap.next_beacon = ++ link->u.ap.next_beacon = + cfg80211_beacon_dup(¶ms->beacon_next); +- if (!sdata->deflink.u.ap.next_beacon) ++ if (!link->u.ap.next_beacon) + return -ENOMEM; + + if (params->count <= 1) +@@ -4905,13 +4916,16 @@ ieee80211_set_color_change_beacon(struct + params->counter_offset_presp; + color_change.count = params->count; + +- err = ieee80211_assign_beacon(sdata, &sdata->deflink, ++ err = ieee80211_assign_beacon(sdata, link, + ¶ms->beacon_color_change, + NULL, &color_change); + if (err < 0) { +- ieee80211_free_next_beacon(&sdata->deflink); ++ ieee80211_free_next_beacon(link); + return err; + } ++ ++ link->conf->critical_update_flag |= IEEE80211_CU_INCLUDE_BCCA_ELEM; ++ + *changed |= err; + break; + default: +@@ -4922,16 +4936,20 @@ ieee80211_set_color_change_beacon(struct + } + + static void +-ieee80211_color_change_bss_config_notify(struct ieee80211_sub_if_data *sdata, ++ieee80211_color_change_bss_config_notify(struct ieee80211_link_data *link, + u8 color, int enable, u32 changed) + { +- sdata->vif.bss_conf.he_bss_color.color = color; +- sdata->vif.bss_conf.he_bss_color.enabled = enable; ++ struct ieee80211_sub_if_data *sdata = link->sdata; ++ ++ link->conf->he_bss_color.color = color; ++ link->conf->he_bss_color.enabled = enable; ++ + changed |= BSS_CHANGED_HE_BSS_COLOR; + +- ieee80211_link_info_change_notify(sdata, &sdata->deflink, changed); ++ ieee80211_link_info_change_notify(sdata, link, changed); + +- if (!sdata->vif.bss_conf.nontransmitted && sdata->vif.mbssid_tx_vif) { ++ /* handle bss color in mbssid case with MLO */ ++ if (!link->conf->nontransmitted && sdata->vif.mbssid_tx_vif) { + struct ieee80211_sub_if_data *child; + + mutex_lock(&sdata->local->iflist_mtx); +@@ -4948,8 +4966,9 @@ ieee80211_color_change_bss_config_notify + } + } + +-static int ieee80211_color_change_finalize(struct ieee80211_sub_if_data *sdata) ++static int ieee80211_color_change_finalize(struct ieee80211_link_data *link) + { ++ struct ieee80211_sub_if_data *sdata = link->sdata; + struct ieee80211_local *local = sdata->local; + u32 changed = 0; + int err; +@@ -4957,80 +4976,130 @@ static int ieee80211_color_change_finali + sdata_assert_lock(sdata); + lockdep_assert_held(&local->mtx); + +- sdata->vif.bss_conf.color_change_active = false; ++ link->conf->color_change_active = false; + +- err = ieee80211_set_after_color_change_beacon(sdata, &changed); ++ err = ieee80211_set_after_color_change_beacon(link, &changed); + if (err) { +- cfg80211_color_change_aborted_notify(sdata->dev); ++ cfg80211_color_change_aborted_notify(sdata->dev, link->link_id); + return err; + } + +- ieee80211_color_change_bss_config_notify(sdata, +- sdata->vif.bss_conf.color_change_color, ++ ieee80211_color_change_bss_config_notify(link, ++ link->conf->color_change_color, + 1, changed); +- cfg80211_color_change_notify(sdata->dev); ++ cfg80211_color_change_notify(sdata->dev, link->link_id); + + return 0; + } + + void ieee80211_color_change_finalize_work(struct work_struct *work) + { +- struct ieee80211_sub_if_data *sdata = +- container_of(work, struct ieee80211_sub_if_data, +- deflink.color_change_finalize_work); ++ struct ieee80211_link_data *link = ++ container_of(work, struct ieee80211_link_data, ++ color_change_finalize_work); ++ struct ieee80211_sub_if_data *sdata = link->sdata; + struct ieee80211_local *local = sdata->local; ++ struct ieee80211_bss_conf *link_conf = link->conf; ++ struct wireless_dev *wdev = &sdata->wdev; ++ ++ /* If is_going_down flag is set, this means that this link is going ++ * to get removed hence no point in proceeding further ++ */ ++ if (wdev->links[link->link_id].ap.is_going_down) ++ return; + + sdata_lock(sdata); + mutex_lock(&local->mtx); + + /* AP might have been stopped while waiting for the lock. */ +- if (!sdata->vif.bss_conf.color_change_active) ++ if (!link_conf->color_change_active) + goto unlock; + + if (!ieee80211_sdata_running(sdata)) + goto unlock; + +- ieee80211_color_change_finalize(sdata); ++ ieee80211_color_change_finalize(link); + + unlock: + mutex_unlock(&local->mtx); + sdata_unlock(sdata); + } + +-void ieee80211_color_change_finish(struct ieee80211_vif *vif) ++void ieee80211_color_change_finish(struct ieee80211_vif *vif, unsigned int link_id) + { + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); ++ struct ieee80211_link_data *link; ++ ++ if (WARN_ON(link_id > IEEE80211_MLD_MAX_NUM_LINKS)) ++ return; ++ ++ rcu_read_lock(); ++ ++ link = rcu_dereference(sdata->link[link_id]); ++ if (WARN_ON(!link)) { ++ rcu_read_unlock(); ++ return; ++ } + + ieee80211_queue_work(&sdata->local->hw, +- &sdata->deflink.color_change_finalize_work); ++ &link->color_change_finalize_work); ++ ++ rcu_read_unlock(); + } + EXPORT_SYMBOL_GPL(ieee80211_color_change_finish); + + void + ieeee80211_obss_color_collision_notify(struct ieee80211_vif *vif, +- u64 color_bitmap, gfp_t gfp) ++ u64 color_bitmap, gfp_t gfp, ++ unsigned int link_id) + { + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); ++ struct ieee80211_link_data *link; + +- if (sdata->vif.bss_conf.color_change_active || sdata->vif.bss_conf.csa_active) ++ if (WARN_ON(link_id > IEEE80211_MLD_MAX_NUM_LINKS)) + return; + +- cfg80211_obss_color_collision_notify(sdata->dev, color_bitmap, gfp); ++ rcu_read_lock(); ++ ++ link = rcu_dereference(sdata->link[link_id]); ++ if (WARN_ON(!link)) { ++ rcu_read_unlock(); ++ return; ++ } ++ ++ if (link->conf->color_change_active || link->conf->csa_active) { ++ rcu_read_unlock(); ++ return; ++ } ++ ++ rcu_read_unlock(); ++ ++ cfg80211_obss_color_collision_notify(sdata->dev, color_bitmap, gfp, ++ link_id); + } + EXPORT_SYMBOL_GPL(ieeee80211_obss_color_collision_notify); + + static int + ieee80211_color_change(struct wiphy *wiphy, struct net_device *dev, +- struct cfg80211_color_change_settings *params) ++ struct cfg80211_color_change_settings *params, ++ unsigned int link_id) + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; + u32 changed = 0; + int err; ++ struct ieee80211_bss_conf *link_conf; ++ struct ieee80211_link_data *link; + + sdata_assert_lock(sdata); + +- if (sdata->vif.bss_conf.nontransmitted) ++ link = sdata_dereference(sdata->link[link_id], sdata); ++ if (!link) ++ return -ENOLINK; ++ ++ link_conf = link->conf; ++ ++ if (link_conf->nontransmitted) + return -EINVAL; + + mutex_lock(&local->mtx); +@@ -5038,25 +5107,26 @@ ieee80211_color_change(struct wiphy *wip + /* don't allow another color change if one is already active or if csa + * is active + */ +- if (sdata->vif.bss_conf.color_change_active || sdata->vif.bss_conf.csa_active) { ++ if (link_conf->color_change_active || link_conf->csa_active) { + err = -EBUSY; + goto out; + } + +- err = ieee80211_set_color_change_beacon(sdata, params, &changed); ++ err = ieee80211_set_color_change_beacon(link, params, &changed); + if (err) + goto out; + +- sdata->vif.bss_conf.color_change_active = true; +- sdata->vif.bss_conf.color_change_color = params->color; ++ link_conf->color_change_active = true; ++ link_conf->color_change_color = params->color; + +- cfg80211_color_change_started_notify(sdata->dev, params->count); ++ cfg80211_color_change_started_notify(sdata->dev, params->count, ++ link_id); + + if (changed) +- ieee80211_color_change_bss_config_notify(sdata, sdata->vif.bss_conf.he_bss_color.color, 0, changed); ++ ieee80211_color_change_bss_config_notify(link, link_conf->he_bss_color.color, 0, changed); + else + /* if the beacon didn't change, we can finalize immediately */ +- ieee80211_color_change_finalize(sdata); ++ ieee80211_color_change_finalize(link); + + out: + mutex_unlock(&local->mtx); +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -3424,7 +3424,7 @@ ieee80211_rx_check_bss_color_collision(s + rx->skb->len - baselen); + if (ie && ie->datalen >= sizeof(struct ieee80211_he_operation) && + ie->datalen >= ieee80211_he_oper_size(ie->data + 1)) { +- struct ieee80211_bss_conf *bss_conf = &rx->sdata->vif.bss_conf; ++ struct ieee80211_bss_conf *bss_conf = rx->link->conf; + const struct ieee80211_he_operation *he_oper; + u8 color; + +@@ -3438,7 +3438,8 @@ ieee80211_rx_check_bss_color_collision(s + if (color == bss_conf->he_bss_color.color) + ieeee80211_obss_color_collision_notify(&rx->sdata->vif, + BIT_ULL(color), +- GFP_ATOMIC); ++ GFP_ATOMIC, ++ bss_conf->link_id); + } + } + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -5286,9 +5286,11 @@ unlock: + } + EXPORT_SYMBOL(ieee80211_beacon_set_cntdwn); + +-bool ieee80211_beacon_cntdwn_is_complete(struct ieee80211_vif *vif) ++bool ieee80211_beacon_cntdwn_is_complete(struct ieee80211_vif *vif, ++ unsigned int link_id) + { + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); ++ struct ieee80211_link_data *link; + struct beacon_data *beacon = NULL; + u8 *beacon_data; + size_t beacon_data_len; +@@ -5297,9 +5299,19 @@ bool ieee80211_beacon_cntdwn_is_complete + if (!ieee80211_sdata_running(sdata)) + return false; + ++ if (WARN_ON(link_id > IEEE80211_MLD_MAX_NUM_LINKS)) ++ return false; ++ + rcu_read_lock(); ++ ++ link = rcu_dereference(sdata->link[link_id]); ++ if (!link) { ++ ret = -ENOLINK; ++ goto out; ++ } ++ + if (vif->type == NL80211_IFTYPE_AP) { +- beacon = rcu_dereference(sdata->deflink.u.ap.beacon); ++ beacon = rcu_dereference(link->u.ap.beacon); + if (WARN_ON(!beacon || !beacon->tail)) + goto out; + beacon_data = beacon->tail; +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -16565,6 +16565,7 @@ static int nl80211_color_change(struct s + struct nlattr **tb; + u16 offset; + int err; ++ unsigned int link_id = nl80211_link_id(info->attrs); + + if (!rdev->ops->color_change) + return -EOPNOTSUPP; +@@ -16648,7 +16649,7 @@ static int nl80211_color_change(struct s + } + + wdev_lock(wdev); +- err = rdev_color_change(rdev, dev, ¶ms); ++ err = rdev_color_change(rdev, dev, ¶ms, link_id); + wdev_unlock(wdev); + + out: +@@ -18017,7 +18018,8 @@ static const struct genl_small_ops nl802 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = nl80211_color_change, + .flags = GENL_UNS_ADMIN_PERM, +- .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), ++ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP | ++ NL80211_FLAG_MLO_VALID_LINK_ID), + }, + { + .cmd = NL80211_CMD_SET_FILS_AAD, +@@ -19966,7 +19968,8 @@ EXPORT_SYMBOL(cfg80211_ch_switch_started + + int cfg80211_bss_color_notify(struct net_device *dev, gfp_t gfp, + enum nl80211_commands cmd, u8 count, +- u64 color_bitmap) ++ u64 color_bitmap, ++ unsigned int link_id) + { + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct wiphy *wiphy = wdev->wiphy; +@@ -19989,6 +19992,10 @@ int cfg80211_bss_color_notify(struct net + if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex)) + goto nla_put_failure; + ++ if (wdev->valid_links && ++ nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id)) ++ goto nla_put_failure; ++ + if (cmd == NL80211_CMD_COLOR_CHANGE_STARTED && + nla_put_u32(msg, NL80211_ATTR_COLOR_CHANGE_COUNT, count)) + goto nla_put_failure; +--- a/net/wireless/rdev-ops.h ++++ b/net/wireless/rdev-ops.h +@@ -1399,12 +1399,13 @@ static inline int rdev_set_sar_specs(str + + static inline int rdev_color_change(struct cfg80211_registered_device *rdev, + struct net_device *dev, +- struct cfg80211_color_change_settings *params) ++ struct cfg80211_color_change_settings *params, ++ unsigned int link_id) + { + int ret; + +- trace_rdev_color_change(&rdev->wiphy, dev, params); +- ret = rdev->ops->color_change(&rdev->wiphy, dev, params); ++ trace_rdev_color_change(&rdev->wiphy, dev, params, link_id); ++ ret = rdev->ops->color_change(&rdev->wiphy, dev, params, link_id); + trace_rdev_return_int(&rdev->wiphy, ret); + + return ret; +--- a/net/wireless/trace.h ++++ b/net/wireless/trace.h +@@ -2845,14 +2845,16 @@ TRACE_EVENT(rdev_set_sar_specs, + + TRACE_EVENT(rdev_color_change, + TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, +- struct cfg80211_color_change_settings *params), +- TP_ARGS(wiphy, netdev, params), ++ struct cfg80211_color_change_settings *params, ++ unsigned int link_id), ++ TP_ARGS(wiphy, netdev, params, link_id), + TP_STRUCT__entry( + WIPHY_ENTRY + NETDEV_ENTRY + __field(u8, count) + __field(u16, bcn_ofs) + __field(u16, pres_ofs) ++ __field(unsigned int, link_id) + ), + TP_fast_assign( + WIPHY_ASSIGN; +@@ -2860,11 +2862,12 @@ TRACE_EVENT(rdev_color_change, + __entry->count = params->count; + __entry->bcn_ofs = params->counter_offset_beacon; + __entry->pres_ofs = params->counter_offset_presp; ++ __entry->link_id = link_id; + ), + TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT +- ", count: %u", ++ ", count: %u link_id: %d", + WIPHY_PR_ARG, NETDEV_PR_ARG, +- __entry->count) ++ __entry->count, __entry->link_id) + ); + + TRACE_EVENT(rdev_set_radar_background, diff --git a/feeds/ipq95xx/mac80211/patches/qca/713-001-mac80211-update-sta-max-bandwith-during-peer-assoc-p.patch b/feeds/ipq95xx/mac80211/patches/qca/713-001-mac80211-update-sta-max-bandwith-during-peer-assoc-p.patch new file mode 100644 index 000000000..5487bc435 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/713-001-mac80211-update-sta-max-bandwith-during-peer-assoc-p.patch @@ -0,0 +1,106 @@ +From 00003561608c076c48cf7d22a7be907c6b86b286 Mon Sep 17 00:00:00 2001 +From: Manish Dharanenthiran +Date: Tue, 7 Feb 2023 16:26:01 +0530 +Subject: [PATCH 1/2] mac80211: update sta max bandwith during peer assoc + prepare + +Currently, mac80211 sends STA bandwidth which is minimum of AP +bandwidth and STA bandwidth during association. + +ath12k driver needs the details of maximum sta bandwidth supported +that was exchanged during association to set the nss & mcs rates which +would be used during channel expansion. + +Signed-off-by: Manish Dharanenthiran +--- + include/net/mac80211.h | 1 + + net/mac80211/eht.c | 1 + + net/mac80211/he.c | 1 + + net/mac80211/ht.c | 1 + + net/mac80211/rx.c | 1 + + net/mac80211/vht.c | 2 ++ + 6 files changed, 7 insertions(+) + +diff --git a/include/net/mac80211.h b/include/net/mac80211.h +index 787e85f..ed42dbb 100644 +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -2290,6 +2290,7 @@ struct ieee80211_link_sta { + + u8 rx_nss; + enum ieee80211_sta_rx_bandwidth bandwidth; ++ enum ieee80211_sta_rx_bandwidth sta_max_bandwidth; + struct ieee80211_sta_txpwr txpwr; + }; + +diff --git a/net/mac80211/eht.c b/net/mac80211/eht.c +index 4a30fe3..58d19bb 100644 +--- a/net/mac80211/eht.c ++++ b/net/mac80211/eht.c +@@ -110,6 +110,7 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(struct ieee80211_sub_if_data *sdata, + + link_sta->cur_max_bandwidth = ieee80211_sta_cap_rx_bw(link_sta); + link_sta->pub->bandwidth = ieee80211_sta_cur_vht_bw(link_sta); ++ link_sta->pub->sta_max_bandwidth = link_sta->cur_max_bandwidth; + } + + void ieee80211_eht_op_ie_to_bss_conf(struct ieee80211_bss_conf *link_conf, +diff --git a/net/mac80211/he.c b/net/mac80211/he.c +index 89d42cc..c5f7a5c 100644 +--- a/net/mac80211/he.c ++++ b/net/mac80211/he.c +@@ -163,6 +163,7 @@ ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata, + + link_sta->cur_max_bandwidth = ieee80211_sta_cap_rx_bw(link_sta); + link_sta->pub->bandwidth = ieee80211_sta_cur_vht_bw(link_sta); ++ link_sta->pub->sta_max_bandwidth = link_sta->cur_max_bandwidth; + + if (sband->band == NL80211_BAND_6GHZ && he_6ghz_capa) + ieee80211_update_from_he_6ghz_capa(he_6ghz_capa, link_sta); +diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c +index 45c4c8e..f826031 100644 +--- a/net/mac80211/ht.c ++++ b/net/mac80211/ht.c +@@ -281,6 +281,7 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, + link_sta->cur_max_bandwidth = + ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ? + IEEE80211_STA_RX_BW_40 : IEEE80211_STA_RX_BW_20; ++ link_sta->pub->sta_max_bandwidth = link_sta->cur_max_bandwidth; + + if (sta->sdata->vif.type == NL80211_IFTYPE_AP || + sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index de96d12..d1190e5 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -3638,6 +3638,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) + + /* set cur_max_bandwidth and recalc sta bw */ + rx->link_sta->cur_max_bandwidth = max_bw; ++ rx->link_sta->pub->sta_max_bandwidth = rx->link_sta->cur_max_bandwidth; + new_bw = ieee80211_sta_cur_vht_bw(rx->link_sta); + + if (rx->link_sta->pub->bandwidth == new_bw) +diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c +index 29ec31c..63b2181 100644 +--- a/net/mac80211/vht.c ++++ b/net/mac80211/vht.c +@@ -301,6 +301,7 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, + } + + link_sta->pub->bandwidth = ieee80211_sta_cur_vht_bw(link_sta); ++ link_sta->pub->sta_max_bandwidth = link_sta->cur_max_bandwidth; + + /* + * FIXME - should the amsdu len be per link? store per link +@@ -672,6 +673,7 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, + break; + } + ++ link_sta->pub->sta_max_bandwidth = link_sta->cur_max_bandwidth; + new_bw = ieee80211_sta_cur_vht_bw(link_sta); + if (new_bw != link_sta->pub->bandwidth) { + link_sta->pub->bandwidth = new_bw; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/713-002-ath12k-update-sta-max-bandwith-during-peer-assoc-pre.patch b/feeds/ipq95xx/mac80211/patches/qca/713-002-ath12k-update-sta-max-bandwith-during-peer-assoc-pre.patch new file mode 100644 index 000000000..55126819d --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/713-002-ath12k-update-sta-max-bandwith-during-peer-assoc-pre.patch @@ -0,0 +1,187 @@ +From 3292a654af69d9d8f050a88f995746a8a3218518 Mon Sep 17 00:00:00 2001 +From: Manish Dharanenthiran +Date: Tue, 7 Feb 2023 16:27:17 +0530 +Subject: [PATCH 2/2] ath12k: update sta max bandwith during peer assoc prepare + +Before sending peer_assoc command to firmware, nss & mcs +rates will be updated based on station bandwidth which +is minimum of AP maximum bandwidth or STA bandwidth's +maxmimu capability. During BW upgrade scenario, host will +send only channel_width and phy mode to firmware. Since, +during assoc, nss & mcs rates are cap'd to AP maximum +bandwidth, firmware will not have proper nss & mcs rates +to support that station which leads to firmware assert. + +Fix this by calculating STA mcs & nss rates based on +minimum of STA maximum capability width and AP max supported +bandwidth, instead of current channel def width. + +With this change, firmware will have proper mcs & nss rates +during bandwidth upgrade scenario. + +Signed-off-by: Manish Dharanenthiran +--- + drivers/net/wireless/ath/ath12k/mac.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -1852,6 +1852,94 @@ static void ath12k_peer_assoc_h_crypto(s + /* TODO: safe_mode_enabled (bypass 4-way handshake) flag req? */ + } + ++static enum ieee80211_sta_rx_bandwidth ++ath12k_get_radio_max_bw_caps(struct ath12k *ar, ++ enum nl80211_band band, ++ enum ieee80211_sta_rx_bandwidth sta_bw, ++ enum nl80211_iftype iftype) ++{ ++ struct ieee80211_supported_band *sband; ++ struct ieee80211_sband_iftype_data *iftype_data; ++ const struct ieee80211_sta_eht_cap *eht_cap; ++ const struct ieee80211_sta_he_cap *he_cap; ++ int i, idx = 0; ++ ++ sband = &ar->mac.sbands[band]; ++ iftype_data = ar->mac.iftype[band]; ++ ++ if (!sband || !iftype_data) { ++ WARN_ONCE(1, "Invalid band specified :%d\n", band); ++ return sta_bw; ++ } ++ ++ for (i = 0; i < NUM_NL80211_IFTYPES && i != iftype; i++) { ++ switch(i) { ++ case NL80211_IFTYPE_STATION: ++ case NL80211_IFTYPE_AP: ++ case NL80211_IFTYPE_MESH_POINT: ++ idx++; ++ break; ++ default: ++ break; ++ } ++ } ++ ++ eht_cap = &iftype_data[idx].eht_cap; ++ he_cap = &iftype_data[idx].he_cap; ++ ++ if (!eht_cap || !he_cap) ++ return sta_bw; ++ ++ /* EHT Caps */ ++ if (band != NL80211_BAND_2GHZ && eht_cap->has_eht && ++ (eht_cap->eht_cap_elem.phy_cap_info[0] & ++ IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ)) ++ return IEEE80211_STA_RX_BW_320; ++ ++ /* HE Caps */ ++ switch (band) { ++ case NL80211_BAND_5GHZ: ++ case NL80211_BAND_6GHZ: ++ if (he_cap->has_he) { ++ if (he_cap->he_cap_elem.phy_cap_info[0] & ++ (IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G | ++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)) { ++ return IEEE80211_STA_RX_BW_160; ++ } else if (he_cap->he_cap_elem.phy_cap_info[0] & ++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G) { ++ return IEEE80211_STA_RX_BW_80; ++ } ++ } ++ break; ++ case NL80211_BAND_2GHZ: ++ if (he_cap->has_he && ++ (he_cap->he_cap_elem.phy_cap_info[0] & ++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G)) ++ return IEEE80211_STA_RX_BW_40; ++ break; ++ default: ++ break; ++ } ++ ++ if (sband->vht_cap.vht_supported) { ++ switch (sband->vht_cap.cap & ++ IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) { ++ case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ: ++ case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ: ++ return IEEE80211_STA_RX_BW_160; ++ default: ++ return sta_bw; ++ } ++ } ++ ++ /* Keep Last */ ++ if (sband->ht_cap.ht_supported && ++ (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) ++ return IEEE80211_STA_RX_BW_40; ++ ++ return sta_bw; ++} ++ + static void ath12k_peer_assoc_h_rates(struct ath12k *ar, + struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta, +@@ -2379,6 +2467,7 @@ static void ath12k_peer_assoc_h_he(struc + struct ieee80211_bss_conf* link_conf; + struct ieee80211_link_sta *link_sta; + u32 peer_he_ops; ++ enum ieee80211_sta_rx_bandwidth radio_max_bw_caps; + + link_conf = ath12k_get_link_bss_conf(arvif); + +@@ -2407,6 +2496,8 @@ static void ath12k_peer_assoc_h_he(struc + + band = def.chan->band; + he_mcs_mask = arvif->bitrate_mask.control[band].he_mcs; ++ radio_max_bw_caps = ath12k_get_radio_max_bw_caps(ar, band, link_sta->bandwidth, ++ vif->type); + + if (ath12k_peer_assoc_h_he_masked(he_mcs_mask)) + return; +@@ -2537,7 +2628,7 @@ static void ath12k_peer_assoc_h_he(struc + he_mcs_mask[link_sta->rx_nss - 1] = he_mcs_mask[he_nss - 1]; + } + +- switch (link_sta->bandwidth) { ++ switch (min(link_sta->sta_max_bandwidth, radio_max_bw_caps)) { + 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) { +@@ -2836,6 +2927,7 @@ static void ath12k_peer_assoc_h_eht(stru + u32 peer_eht_ops; + struct ieee80211_sta_eht_cap *own_eht_cap; + struct ieee80211_eht_mcs_nss_supp *own_eht_mcs_nss_supp; ++ enum ieee80211_sta_rx_bandwidth radio_max_bw_caps; + + link_conf = ath12k_get_link_bss_conf(arvif); + +@@ -2866,6 +2958,9 @@ static void ath12k_peer_assoc_h_eht(stru + band = def.chan->band; + eht_mcs_mask = arvif->bitrate_mask.control[band].eht_mcs; + ++ radio_max_bw_caps = ath12k_get_radio_max_bw_caps(ar, band, link_sta->bandwidth, ++ vif->type); ++ + own_eht_cap = &ar->mac.sbands[band].iftype_data->eht_cap; + own_eht_mcs_nss_supp = &own_eht_cap->eht_mcs_nss_supp; + +@@ -2913,7 +3008,7 @@ static void ath12k_peer_assoc_h_eht(stru + eht_mcs_mask[link_sta->rx_nss - 1] = eht_mcs_mask[eht_nss - 1]; + } + +- switch (link_sta->bandwidth) { ++ switch (min(link_sta->sta_max_bandwidth, radio_max_bw_caps)) { + case IEEE80211_STA_RX_BW_320: + mcs_nss_supp_bw = &mcs_nss->bw._320; + mcs_idx = WMI_EHTCAP_TXRX_MCS_NSS_IDX_320; +@@ -2983,8 +3078,8 @@ static void ath12k_peer_assoc_h_eht(stru + arg->ru_punct_bitmap = ~link_sta->ru_punct_bitmap; + + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, +- "mac he peer %pM nss %d mcs cnt %d ru_punct_bitmap 0x%x\n", +- arsta->addr, arg->peer_nss, arg->peer_he_mcs_count, arg->ru_punct_bitmap); ++ "mac eht peer %pM nss %d mcs cnt %d ru_punct_bitmap 0x%x\n", ++ arsta->addr, arg->peer_nss, arg->peer_eht_mcs_count, arg->ru_punct_bitmap); + } + + static void ath12k_peer_assoc_h_smps(struct ath12k_link_sta *arsta, diff --git a/feeds/ipq95xx/mac80211/patches/qca/713-ath12k-Add-supoort-for-mlo-in-cnss-daig-debug.patch b/feeds/ipq95xx/mac80211/patches/qca/713-ath12k-Add-supoort-for-mlo-in-cnss-daig-debug.patch new file mode 100644 index 000000000..c6c043d7e --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/713-ath12k-Add-supoort-for-mlo-in-cnss-daig-debug.patch @@ -0,0 +1,61 @@ +From d090bf7eb47914550f17dfc143f968022187737b Mon Sep 17 00:00:00 2001 +From: Rajat Soni +Date: Tue, 14 Mar 2023 17:52:55 +0530 +Subject: [PATCH] ath12k: Add support for mlo in cnss diag debug + +Currently, when mlo is enabled when we run cnss_diag -p -c +radio index is always 0 (R0: FWMSG:...) due to this it is +not possible to identify radio and debugging is not possible. + +Add ATH12K_TM_ATTR_LINK_IDX attribute to send ar->link_idx that is +fetched by cnss diag to display correct radio number. + +Signed-off-by: Rajat Soni +--- + drivers/net/wireless/ath/ath12k/testmode.c | 10 ++++++++++ + drivers/net/wireless/ath/ath12k/testmode_i.h | 1 + + 2 files changed, 11 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/testmode.c b/drivers/net/wireless/ath/ath12k/testmode.c +index c2c24b8..2e16255 100644 +--- a/drivers/net/wireless/ath/ath12k/testmode.c ++++ b/drivers/net/wireless/ath/ath12k/testmode.c +@@ -25,6 +25,7 @@ static const struct nla_policy ath12k_tm_policy[ATH12K_TM_ATTR_MAX + 1] = { + [ATH12K_TM_ATTR_VERSION_MINOR] = { .type = NLA_U32 }, + [ATH12K_TM_ATTR_FWLOG] = { .type = NLA_BINARY, + .len = 2048 }, ++ [ATH12K_TM_ATTR_LINK_IDX] = { .type = NLA_U8 }, + }; + + void ath12k_fwlog_write(struct ath12k_base *ab, u8 *data, int len) +@@ -56,6 +57,15 @@ void ath12k_fwlog_write(struct ath12k_base *ab, u8 *data, int len) + return; + } + ++ if (ab->ag->mlo_capable) { ++ ret = nla_put_u8(nl_skb, ATH12K_TM_ATTR_LINK_IDX, ar->link_idx); ++ if (ret) { ++ ath12k_warn(ab, "failed to put link idx wmi event to nl: %d\n", ret); ++ kfree_skb(nl_skb); ++ return; ++ } ++ } ++ + cfg80211_testmode_event(nl_skb, GFP_ATOMIC); + } + +diff --git a/drivers/net/wireless/ath/ath12k/testmode_i.h b/drivers/net/wireless/ath/ath12k/testmode_i.h +index 709ba68..3c6f8d0 100644 +--- a/drivers/net/wireless/ath/ath12k/testmode_i.h ++++ b/drivers/net/wireless/ath/ath12k/testmode_i.h +@@ -26,6 +26,7 @@ enum ath12k_tm_attr { + ATH12K_TM_ATTR_VERSION_MINOR = 5, + ATH12K_TM_ATTR_WMI_OP_VERSION = 6, + ATH12K_TM_ATTR_FWLOG = 7, ++ ATH12K_TM_ATTR_LINK_IDX = 8, + + /* keep last */ + __ATH12K_TM_ATTR_AFTER_LAST, +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/674-ath12k-Performance-optimization-on-Rx-path.patch b/feeds/ipq95xx/mac80211/patches/qca/713-ath12k-Performance-optimization-in-Rx-path.patch similarity index 50% rename from feeds/ipq95xx/mac80211/patches/qca/674-ath12k-Performance-optimization-on-Rx-path.patch rename to feeds/ipq95xx/mac80211/patches/qca/713-ath12k-Performance-optimization-in-Rx-path.patch index be636873a..ff9128bfd 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/674-ath12k-Performance-optimization-on-Rx-path.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/713-ath12k-Performance-optimization-in-Rx-path.patch @@ -1,36 +1,31 @@ -From 21076c688f82c7fb5d36d1b92655450455d72fca Mon Sep 17 00:00:00 2001 -From: Balamurugan Selvarajan -Date: Tue, 4 Oct 2022 12:03:45 +0530 -Subject: [PATCH] ath12k: Performance optimization in Rx path +From 7ff35af5fef76c14c350d6327f8a6b86b3a3cbd4 Mon Sep 17 00:00:00 2001 +From: Balamurugan S +Date: Sat, 28 Jan 2023 10:57:05 +0530 +Subject: [PATCH 1/2] ath12k: Performance optimization in Rx path optimized dp_service_srng(). There was multiple de reference to check various mask. This has been optimized to read in one shot to avoid cache miss. Added branch predictions in Rx processing. - Changed napi_gro_recieve() to netif_receive_skb() in fast_rx path. Introduced cached entry to get the next descriptor in rx path. -With all the above changes, The CPU idle percentage is increased to 3 to 4% -and see a increase in TP of 100 to 150 Mbps in UDP uplink. - -Signed-off-by: Balamurugan Selvarajan +Signed-off-by: Balamurugan S --- - drivers/net/wireless/ath/ath12k/dp.c | 36 +++++++++++++++---------- - drivers/net/wireless/ath/ath12k/dp_rx.c | 33 ++++++++++++----------- - drivers/net/wireless/ath/ath12k/pci.c | 11 +++++++- - 3 files changed, 50 insertions(+), 30 deletions(-) + drivers/net/wireless/ath/ath12k/dp.c | 48 +++++++++++++++++-------- + drivers/net/wireless/ath/ath12k/dp_rx.c | 31 ++++++++-------- + 2 files changed, 50 insertions(+), 29 deletions(-) -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp.c +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/dp.c =================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/dp.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp.c -@@ -911,22 +911,37 @@ int ath12k_dp_service_srng(struct ath12k +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/dp.c ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/dp.c +@@ -927,15 +927,28 @@ int ath12k_dp_service_srng(struct ath12k int i = 0, j; int tot_work_done = 0; bool flag; -+ struct ath12k_hw_ring_mask *ring_mask = ab->hw_params.ring_mask; ++ struct ath12k_hw_ring_mask *ring_mask = ab->hw_params->ring_mask; + u8 tx_mask = ring_mask->tx[grp_id]; + u8 rx_err_mask = ring_mask->rx_err[grp_id]; + u8 rx_wbm_rel_mask = ring_mask->rx_wbm_rel[grp_id]; @@ -39,104 +34,101 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp. + u8 host2rxdma_mask = ring_mask->host2rxdma[grp_id]; + u8 rx_mon_dest_mask = ring_mask->rx_mon_dest[grp_id]; + u8 tx_mon_dest_mask = ring_mask->tx_mon_dest[grp_id]; -+ u8 misc_intr_mask = rx_err_mask | -+ rx_mon_dest_mask | ++ u8 misc_intr_mask = rx_mon_dest_mask | + tx_mon_dest_mask | + reo_status_mask | + host2rxdma_mask; + while (i < ab->hw_params->max_tx_ring) { +- if (ab->hw_params->ring_mask->tx[grp_id] & +- BIT(ab->hw_params->hal_ops->tcl_to_wbm_rbm_map[i].wbm_ring_num)) ++ if (tx_mask & ++ BIT(ab->hw_params->hal_ops->tcl_to_wbm_rbm_map[i].wbm_ring_num)) + ath12k_dp_tx_completion_handler(ab, i); + i++; + } - -- if (ab->hw_params.ring_mask->tx[grp_id]) { -- i = __fls(ab->hw_params.ring_mask->tx[grp_id]); -+ if (tx_mask) { -+ i = __fls(tx_mask); - ath12k_dp_tx_completion_handler(ab, (i == 4) ? 3 : i); - } - -- if (ab->hw_params.ring_mask->rx_err[grp_id]) { -- work_done = ath12k_dp_process_rx_err(ab, napi, budget); -+ if (rx_mask) { -+ i = fls(rx_mask) - 1; -+ work_done = ath12k_dp_process_rx(ab, i, napi, -+ budget); +- if (ab->hw_params->ring_mask->rx_err[grp_id]) { ++ ++ if (rx_err_mask) { + work_done = ath12k_dp_rx_process_err(ab, napi, budget); budget -= work_done; tot_work_done += work_done; - if (budget <= 0) +@@ -943,7 +956,7 @@ int ath12k_dp_service_srng(struct ath12k goto done; } -- if (ab->hw_params.ring_mask->rx_wbm_rel[grp_id]) { +- if (ab->hw_params->ring_mask->rx_wbm_rel[grp_id]) { + if (rx_wbm_rel_mask) { work_done = ath12k_dp_rx_process_wbm_err(ab, napi, budget); -@@ -937,24 +952,25 @@ int ath12k_dp_service_srng(struct ath12k +@@ -954,8 +967,8 @@ int ath12k_dp_service_srng(struct ath12k goto done; } -- if (ab->hw_params.ring_mask->rx[grp_id]) { -- i = fls(ab->hw_params.ring_mask->rx[grp_id]) - 1; -- work_done = ath12k_dp_process_rx(ab, i, napi, -- budget); +- if (ab->hw_params->ring_mask->rx[grp_id]) { +- i = fls(ab->hw_params->ring_mask->rx[grp_id]) - 1; ++ if (rx_mask) { ++ i = fls(rx_mask) - 1; + work_done = ath12k_dp_rx_process(ab, i, napi, + budget); + budget -= work_done; +@@ -964,14 +977,17 @@ int ath12k_dp_service_srng(struct ath12k + goto done; + } + +- if (ab->hw_params->ring_mask->rx_mon_dest[grp_id]) { + if (!misc_intr_mask) + goto done; + -+ if (rx_err_mask) { -+ work_done = ath12k_dp_process_rx_err(ab, napi, budget); - budget -= work_done; - tot_work_done += work_done; - if (budget <= 0) - goto done; - } - -- if (ab->hw_params.ring_mask->rx_mon_dest[grp_id]) { + if (rx_mon_dest_mask) { for (i = 0; i < ab->num_radios; i++) { - for (j = 0; j < ab->hw_params.num_rxmda_per_pdev; j++) { - int id = i * ab->hw_params.num_rxmda_per_pdev + j; + for (j = 0; j < ab->hw_params->num_rxmda_per_pdev; j++) { + int id = i * ab->hw_params->num_rxmda_per_pdev + j; flag = ATH12K_DP_RX_MONITOR_MODE; -- if (ab->hw_params.ring_mask->rx_mon_dest[grp_id] & +- if (ab->hw_params->ring_mask->rx_mon_dest[grp_id] & + if (rx_mon_dest_mask & BIT(id)) { work_done = ath12k_dp_mon_process_ring(ab, id, napi, budget, -@@ -969,14 +985,14 @@ int ath12k_dp_service_srng(struct ath12k +@@ -986,14 +1002,14 @@ int ath12k_dp_service_srng(struct ath12k } } -- if (ab->hw_params.ring_mask->tx_mon_dest[grp_id]) { +- if (ab->hw_params->ring_mask->tx_mon_dest[grp_id]) { + if (tx_mon_dest_mask) { for (i = 0; i < ab->num_radios; i++) { - for (j = 0; j < ab->hw_params.num_rxmda_per_pdev; j++) { - int id = i * ab->hw_params.num_rxmda_per_pdev + j; + for (j = 0; j < ab->hw_params->num_rxmda_per_pdev; j++) { + int id = i * ab->hw_params->num_rxmda_per_pdev + j; flag = ATH12K_DP_TX_MONITOR_MODE; -- if (ab->hw_params.ring_mask->tx_mon_dest[grp_id] & +- if (ab->hw_params->ring_mask->tx_mon_dest[grp_id] & + if (tx_mon_dest_mask & BIT(id)) { work_done = ath12k_dp_mon_process_ring(ab, id, napi, budget, -@@ -991,10 +1007,10 @@ int ath12k_dp_service_srng(struct ath12k +@@ -1008,10 +1024,10 @@ int ath12k_dp_service_srng(struct ath12k } } -- if (ab->hw_params.ring_mask->reo_status[grp_id]) +- if (ab->hw_params->ring_mask->reo_status[grp_id]) + if (reo_status_mask) - ath12k_dp_process_reo_status(ab); + ath12k_dp_rx_process_reo_status(ab); -- if (ab->hw_params.ring_mask->host2rxdma[grp_id]) { +- if (ab->hw_params->ring_mask->host2rxdma[grp_id]) { + if (host2rxdma_mask) { struct ath12k_dp *dp = &ab->dp; struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring; -Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_rx.c +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/dp_rx.c =================================================================== ---- backports-20220404-5.4.164-f40abb4788.orig/drivers/net/wireless/ath/ath12k/dp_rx.c -+++ backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_rx.c -@@ -342,7 +342,7 @@ int ath12k_dp_rxbufs_replenish(struct at +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -328,7 +328,7 @@ int ath12k_dp_rx_bufs_replenish(struct a while (num_remain > 0) { skb = dev_alloc_skb(DP_RX_BUFFER_SIZE + DP_RX_BUFFER_ALIGN_SIZE); @@ -145,16 +137,16 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_ break; if (!IS_ALIGNED((unsigned long)skb->data, -@@ -362,7 +362,7 @@ int ath12k_dp_rxbufs_replenish(struct at - * and check idr is working, later confirm hw cc is working by - * checking magic. remove all TODO's after testing - */ +@@ -344,7 +344,7 @@ int ath12k_dp_rx_bufs_replenish(struct a + if (dma_mapping_error(ab->dev, paddr)) + goto fail_free_skb; + - if (hw_cc) { + if (likely(hw_cc)) { spin_lock_bh(&dp->rx_desc_lock); /* Get desc from free list and store in used list -@@ -2534,7 +2534,6 @@ static void ath12k_dp_rx_h_mpdu(struct a +@@ -2671,7 +2671,6 @@ static void ath12k_dp_rx_h_mpdu(struct a u32 vp; #endif struct wireless_dev *wdev = NULL; @@ -162,7 +154,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_ /* PN for multicast packets will be checked in mac80211 */ rxcb = ATH12K_SKB_RXCB(msdu); -@@ -2568,11 +2567,7 @@ static void ath12k_dp_rx_h_mpdu(struct a +@@ -2705,11 +2704,7 @@ static void ath12k_dp_rx_h_mpdu(struct a } #endif msdu->protocol = eth_type_trans(msdu, msdu->dev); @@ -175,15 +167,15 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_ return; } } -@@ -3023,6 +3018,7 @@ int ath12k_dp_process_rx(struct ath12k_b - struct ath12k_sta *arsta = NULL; +@@ -3212,6 +3207,7 @@ int ath12k_dp_rx_process(struct ath12k_b struct ath12k_peer *peer = NULL; struct ath12k *ar; + u8 hw_link_id; + int valid_entries; __skb_queue_head_init(&msdu_list); -@@ -3032,8 +3028,15 @@ int ath12k_dp_process_rx(struct ath12k_b +@@ -3221,8 +3217,15 @@ int ath12k_dp_rx_process(struct ath12k_b try_again: ath12k_hal_srng_access_begin(ab, srng); @@ -200,23 +192,28 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_ struct hal_reo_dest_ring desc = *(struct hal_reo_dest_ring *)rx_desc; enum hal_reo_dest_ring_push_reason push_reason; u32 cookie; -@@ -3050,10 +3053,10 @@ try_again: - desc.buf_va_lo); +@@ -3260,7 +3263,7 @@ try_again: + rcu_read_unlock(); /* retry manual desc retrieval */ -- if (!desc_info) -+ if (unlikely(!desc_info)) - desc_info = ath12k_dp_get_rx_desc(ab, cookie); +- if (!desc_info) { ++ if (unlikely(!desc_info)) { + desc_info = ath12k_dp_get_rx_desc(src_ab, cookie); + if (!desc_info) { + ath12k_warn(ab, "Rx with invalid buf cookie 0x%x\n", cookie); +@@ -3268,7 +3271,7 @@ try_again: + } + } - if (desc_info->magic != ATH12K_DP_RX_DESC_MAGIC) + if (unlikely(desc_info->magic != ATH12K_DP_RX_DESC_MAGIC)) ath12k_warn(ab, "Check HW CC implementation"); msdu = desc_info->skb; -@@ -3072,8 +3075,8 @@ try_again: +@@ -3287,8 +3290,8 @@ try_again: - push_reason = FIELD_GET(HAL_REO_DEST_RING_INFO0_PUSH_REASON, - desc.info0); + push_reason = u32_get_bits(desc.info0, + HAL_REO_DEST_RING_INFO0_PUSH_REASON); - if (push_reason != - HAL_REO_DEST_RING_PUSH_REASON_ROUTING_INSTRUCTION) { + if (unlikely(push_reason != @@ -224,16 +221,7 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_ dev_kfree_skb_any(msdu); ab->soc_stats.hal_reo_error[dp->reo_dst_ring[ring_id].ring_id]++; continue; -@@ -3090,7 +3093,7 @@ try_again: - desc.rx_mpdu_info.peer_meta_data); - rxcb->tid = FIELD_GET(RX_MPDU_DESC_INFO0_TID, desc.rx_mpdu_info.info0); - -- if (ath12k_debugfs_is_extd_rx_stats_enabled(ar) && rxcb->peer_id) { -+ if (unlikely(ath12k_debugfs_is_extd_rx_stats_enabled(ar) && rxcb->peer_id)) { - rcu_read_lock(); - spin_lock_bh(&ab->base_lock); - peer = ath12k_peer_find_by_id(ab, rxcb->peer_id); -@@ -3131,7 +3134,7 @@ try_again: +@@ -3346,7 +3349,7 @@ try_again: spin_unlock_bh(&srng->lock); @@ -241,4 +229,4 @@ Index: backports-20220404-5.4.164-f40abb4788/drivers/net/wireless/ath/ath12k/dp_ + if (unlikely(!total_msdu_reaped)) goto exit; - //TODO Move to implicit BM? + for (i = 0; i < ab->ag->num_chip; i++) { diff --git a/feeds/ipq95xx/mac80211/patches/qca/713-ath12k-fix-firmware-assert-during-insmod-in-memory-s.patch b/feeds/ipq95xx/mac80211/patches/qca/713-ath12k-fix-firmware-assert-during-insmod-in-memory-s.patch new file mode 100644 index 000000000..7f20904e8 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/713-ath12k-fix-firmware-assert-during-insmod-in-memory-s.patch @@ -0,0 +1,41 @@ +From 3b5f6535791d14a17138e5e19d471657fa45459f Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Tue, 14 Feb 2023 15:51:59 +0530 +Subject: [PATCH] ath12k: fix firmware assert during insmod in memory segment + mode + +Firmware allocate each segment of size 2MB for memory segment mode +which is calculated via num peers value send by host to firmware +during wmi init. + +Currently, num peers value is 512+17 but in case of split phy this +value become 2*(512 + 17) which is 1058 due to this it's trigger +firmware assert. + +So, Fix this issue by reducing num_peers value from 512 to 128. + +Signed-off-by: Aaradhana Sahu +--- + drivers/net/wireless/ath/ath12k/hw.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath12k/hw.h ++++ b/drivers/net/wireless/ath/ath12k/hw.h +@@ -17,7 +17,7 @@ + /* Num VDEVS per radio */ + #define TARGET_NUM_VDEVS (16 + 1) + +-#define TARGET_NUM_PEERS_PDEV (512 + TARGET_NUM_VDEVS) ++#define TARGET_NUM_PEERS_PDEV (TARGET_NUM_STATIONS + TARGET_NUM_VDEVS) + + /* Num of peers for Single Radio mode */ + #define TARGET_NUM_PEERS_SINGLE (TARGET_NUM_PEERS_PDEV) +@@ -29,7 +29,7 @@ + #define TARGET_NUM_PEERS_DBS_SBS (3 * TARGET_NUM_PEERS_PDEV) + + /* Max num of stations (per radio) */ +-#define TARGET_NUM_STATIONS 512 ++#define TARGET_NUM_STATIONS 128 + + #define TARGET_NUM_PEERS(x) TARGET_NUM_PEERS_##x + #define TARGET_NUM_PEER_KEYS 2 diff --git a/feeds/ipq95xx/mac80211/patches/qca/714-01-UPSTREAM-wifi-mac80211-add-API-to-show-the-link-STAs-in-debug.patch b/feeds/ipq95xx/mac80211/patches/qca/714-01-UPSTREAM-wifi-mac80211-add-API-to-show-the-link-STAs-in-debug.patch new file mode 100644 index 000000000..c379d3217 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/714-01-UPSTREAM-wifi-mac80211-add-API-to-show-the-link-STAs-in-debug.patch @@ -0,0 +1,434 @@ +From b308db4196622e2656bc7c8afd1a7ed345a2ec6d Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Wed, 1 Feb 2023 16:53:02 +0530 +Subject: [PATCH] wifi: mac80211: add API to show the link STAs in debugfs + +Create debugfs data per-link. For drivers, there is a new operation +link_sta_add_debugfs which will always be called. + +For non-MLO, the station directory will be used directly rather than +creating a corresponding subdirectory. As such, non-MLO drivers can +simply continue to create the data from sta_debugfs_add. + +Signed-off-by: Benjamin Berg +[add missing inlines if !CONFIG_MAC80211_DEBUGFS] +Signed-off-by: Johannes Berg +Signed-off-by: Sriram R +--- + include/net/mac80211.h | 4 ++ + net/mac80211/debugfs_sta.c | 132 ++++++++++++++++++++++++++++++------- + net/mac80211/debugfs_sta.h | 12 ++++ + net/mac80211/driver-ops.c | 27 +++++++- + net/mac80211/driver-ops.h | 16 +++++ + net/mac80211/sta_info.c | 25 +++++++ + net/mac80211/sta_info.h | 5 ++ + 7 files changed, 196 insertions(+), 25 deletions(-) + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -4376,6 +4376,10 @@ struct ieee80211_ops { + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct dentry *dir); ++ void (*link_sta_add_debugfs)(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_link_sta *link_sta, ++ struct dentry *dir); + #endif + void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + enum sta_notify_cmd, struct ieee80211_sta *sta); +--- a/net/mac80211/debugfs_sta.c ++++ b/net/mac80211/debugfs_sta.c +@@ -5,7 +5,7 @@ + * Copyright 2007 Johannes Berg + * Copyright 2013-2014 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH +- * Copyright (C) 2018 - 2021 Intel Corporation ++ * Copyright (C) 2018 - 2022 Intel Corporation + */ + + #include +@@ -435,8 +435,16 @@ static ssize_t sta_agg_status_write(stru + } + STA_OPS_RW(agg_status); + +-static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, +- size_t count, loff_t *ppos) ++/* link sta attributes */ ++#define LINK_STA_OPS(name) \ ++static const struct file_operations link_sta_ ##name## _ops = { \ ++ .read = link_sta_##name##_read, \ ++ .open = simple_open, \ ++ .llseek = generic_file_llseek, \ ++} ++ ++static ssize_t link_sta_ht_capa_read(struct file *file, char __user *userbuf, ++ size_t count, loff_t *ppos) + { + #define PRINT_HT_CAP(_cond, _str) \ + do { \ +@@ -446,8 +454,8 @@ static ssize_t sta_ht_capa_read(struct f + char *buf, *p; + int i; + ssize_t bufsz = 512; +- struct sta_info *sta = file->private_data; +- struct ieee80211_sta_ht_cap *htc = &sta->sta.deflink.ht_cap; ++ struct link_sta_info *link_sta = file->private_data; ++ struct ieee80211_sta_ht_cap *htc = &link_sta->pub->ht_cap; + ssize_t ret; + + buf = kzalloc(bufsz, GFP_KERNEL); +@@ -524,7 +532,7 @@ static ssize_t sta_ht_capa_read(struct f + kfree(buf); + return ret; + } +-STA_OPS(ht_capa); ++LINK_STA_OPS(ht_capa); + + static ssize_t sta_tx_fail_cnt_read(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +@@ -569,12 +577,12 @@ static ssize_t sta_tx_fail_cnt_write(str + + STA_OPS_RW(tx_fail_cnt); + +-static ssize_t sta_vht_capa_read(struct file *file, char __user *userbuf, +- size_t count, loff_t *ppos) ++static ssize_t link_sta_vht_capa_read(struct file *file, char __user *userbuf, ++ size_t count, loff_t *ppos) + { + char *buf, *p; +- struct sta_info *sta = file->private_data; +- struct ieee80211_sta_vht_cap *vhtc = &sta->sta.deflink.vht_cap; ++ struct link_sta_info *link_sta = file->private_data; ++ struct ieee80211_sta_vht_cap *vhtc = &link_sta->pub->vht_cap; + ssize_t ret; + ssize_t bufsz = 512; + +@@ -681,15 +689,15 @@ static ssize_t sta_vht_capa_read(struct + kfree(buf); + return ret; + } +-STA_OPS(vht_capa); ++LINK_STA_OPS(vht_capa); + +-static ssize_t sta_he_capa_read(struct file *file, char __user *userbuf, +- size_t count, loff_t *ppos) ++static ssize_t link_sta_he_capa_read(struct file *file, char __user *userbuf, ++ size_t count, loff_t *ppos) + { + char *buf, *p; + size_t buf_sz = PAGE_SIZE; +- struct sta_info *sta = file->private_data; +- struct ieee80211_sta_he_cap *hec = &sta->sta.deflink.he_cap; ++ struct link_sta_info *link_sta = file->private_data; ++ struct ieee80211_sta_he_cap *hec = &link_sta->pub->he_cap; + struct ieee80211_he_mcs_nss_supp *nss = &hec->he_mcs_nss_supp; + u8 ppe_size; + u8 *cap; +@@ -1054,15 +1062,15 @@ out: + kfree(buf); + return ret; + } +-STA_OPS(he_capa); ++LINK_STA_OPS(he_capa); + +-static ssize_t sta_eht_capa_read(struct file *file, char __user *userbuf, ++static ssize_t link_sta_eht_capa_read(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) + { + char *buf, *p; + size_t buf_sz = PAGE_SIZE; +- struct sta_info *sta = file->private_data; +- struct ieee80211_sta_eht_cap *ehtc = &sta->sta.deflink.eht_cap; ++ struct link_sta_info *link_sta = file->private_data; ++ struct ieee80211_sta_eht_cap *ehtc = &link_sta->pub->eht_cap; + struct ieee80211_eht_mcs_nss_supp *nss = &ehtc->eht_mcs_nss_supp; + u8 ppe_size; + u8 *cap; +@@ -1263,7 +1271,7 @@ out: + kfree(buf); + return ret; + } +-STA_OPS(eht_capa); ++LINK_STA_OPS(eht_capa); + + static ssize_t + sta_reset_mac80211_tx_pkts_flow_read(struct file *file, +@@ -1470,10 +1478,6 @@ void ieee80211_sta_debugfs_add(struct st + DEBUGFS_ADD(num_ps_buf_frames); + DEBUGFS_ADD(last_seq_ctrl); + DEBUGFS_ADD(agg_status); +- DEBUGFS_ADD(ht_capa); +- DEBUGFS_ADD(vht_capa); +- DEBUGFS_ADD(he_capa); +- DEBUGFS_ADD(eht_capa); + DEBUGFS_ADD(reset_mac80211_tx_pkts_flow); + DEBUGFS_ADD(reset_mac80211_rx_pkts_flow); + DEBUGFS_ADD(mac80211_tx_pkts_flow); +@@ -1482,8 +1486,7 @@ void ieee80211_sta_debugfs_add(struct st + DEBUGFS_ADD(tx_fail_cnt); + #endif + +- DEBUGFS_ADD_COUNTER(rx_duplicates, deflink.rx_stats.num_duplicates); +- DEBUGFS_ADD_COUNTER(rx_fragments, deflink.rx_stats.fragments); ++ /* FIXME: Kept here as the statistics are only done on the deflink */ + DEBUGFS_ADD_COUNTER(tx_filtered, deflink.status_stats.filtered); + + if (local->ops->wake_tx_queue) { +@@ -1506,3 +1509,84 @@ void ieee80211_sta_debugfs_remove(struct + debugfs_remove_recursive(sta->debugfs_dir); + sta->debugfs_dir = NULL; + } ++ ++#undef DEBUGFS_ADD ++#undef DEBUGFS_ADD_COUNTER ++ ++#define DEBUGFS_ADD(name) \ ++ debugfs_create_file(#name, 0400, \ ++ link_sta->debugfs_dir, link_sta, &link_sta_ ##name## _ops) ++#define DEBUGFS_ADD_COUNTER(name, field) \ ++ debugfs_create_ulong(#name, 0400, link_sta->debugfs_dir, &link_sta->field) ++ ++void ieee80211_link_sta_debugfs_add(struct link_sta_info *link_sta) ++{ ++ if (WARN_ON(!link_sta->sta->debugfs_dir)) ++ return; ++ ++ /* For non-MLO, leave the files in the main directory. */ ++ if (link_sta->sta->sta.valid_links) { ++ char link_dir_name[10]; ++ ++ snprintf(link_dir_name, sizeof(link_dir_name), ++ "link-%d", link_sta->link_id); ++ ++ link_sta->debugfs_dir = ++ debugfs_create_dir(link_dir_name, ++ link_sta->sta->debugfs_dir); ++ } else { ++ if (WARN_ON(link_sta != &link_sta->sta->deflink)) ++ return; ++ ++ link_sta->debugfs_dir = link_sta->sta->debugfs_dir; ++ } ++ ++ DEBUGFS_ADD(ht_capa); ++ DEBUGFS_ADD(vht_capa); ++ DEBUGFS_ADD(he_capa); ++ DEBUGFS_ADD(eht_capa); ++ ++ DEBUGFS_ADD_COUNTER(rx_duplicates, rx_stats.num_duplicates); ++ DEBUGFS_ADD_COUNTER(rx_fragments, rx_stats.fragments); ++} ++ ++void ieee80211_link_sta_debugfs_remove(struct link_sta_info *link_sta) ++{ ++ if (!link_sta->debugfs_dir || !link_sta->sta->debugfs_dir) { ++ link_sta->debugfs_dir = NULL; ++ return; ++ } ++ ++ if (link_sta->debugfs_dir == link_sta->sta->debugfs_dir) { ++ WARN_ON(link_sta != &link_sta->sta->deflink); ++ link_sta->sta->debugfs_dir = NULL; ++ return; ++ } ++ ++ debugfs_remove_recursive(link_sta->debugfs_dir); ++ link_sta->debugfs_dir = NULL; ++} ++ ++void ieee80211_link_sta_debugfs_drv_add(struct link_sta_info *link_sta) ++{ ++ if (WARN_ON(!link_sta->debugfs_dir)) ++ return; ++ ++ drv_link_sta_add_debugfs(link_sta->sta->local, link_sta->sta->sdata, ++ link_sta->pub, link_sta->debugfs_dir); ++} ++ ++void ieee80211_link_sta_debugfs_drv_remove(struct link_sta_info *link_sta) ++{ ++ if (!link_sta->debugfs_dir) ++ return; ++ ++ if (WARN_ON(link_sta->debugfs_dir == link_sta->sta->debugfs_dir)) ++ return; ++ ++ /* Recreate the directory excluding the driver data */ ++ debugfs_remove_recursive(link_sta->debugfs_dir); ++ link_sta->debugfs_dir = NULL; ++ ++ ieee80211_link_sta_debugfs_add(link_sta); ++} +--- a/net/mac80211/debugfs_sta.h ++++ b/net/mac80211/debugfs_sta.h +@@ -7,9 +7,21 @@ + #ifdef CPTCFG_MAC80211_DEBUGFS + void ieee80211_sta_debugfs_add(struct sta_info *sta); + void ieee80211_sta_debugfs_remove(struct sta_info *sta); ++ ++void ieee80211_link_sta_debugfs_add(struct link_sta_info *link_sta); ++void ieee80211_link_sta_debugfs_remove(struct link_sta_info *link_sta); ++ ++void ieee80211_link_sta_debugfs_drv_add(struct link_sta_info *link_sta); ++void ieee80211_link_sta_debugfs_drv_remove(struct link_sta_info *link_sta); + #else + static inline void ieee80211_sta_debugfs_add(struct sta_info *sta) {} + static inline void ieee80211_sta_debugfs_remove(struct sta_info *sta) {} ++ ++static inline void ieee80211_link_sta_debugfs_add(struct link_sta_info *link_sta) {} ++static inline void ieee80211_link_sta_debugfs_remove(struct link_sta_info *link_sta) {} ++ ++static inline void ieee80211_link_sta_debugfs_drv_add(struct link_sta_info *link_sta) {} ++static inline void ieee80211_link_sta_debugfs_drv_remove(struct link_sta_info *link_sta) {} + #endif + + #endif /* __MAC80211_DEBUGFS_STA_H */ +--- a/net/mac80211/driver-ops.c ++++ b/net/mac80211/driver-ops.c +@@ -7,6 +7,7 @@ + #include "ieee80211_i.h" + #include "trace.h" + #include "driver-ops.h" ++#include "debugfs_sta.h" + + int drv_start(struct ieee80211_local *local) + { +@@ -541,6 +542,11 @@ int drv_change_sta_links(struct ieee8021 + struct ieee80211_sta *sta, + u16 old_links, u16 new_links) + { ++ struct sta_info *info = container_of(sta, struct sta_info, sta); ++ struct link_sta_info *link_sta; ++ unsigned long links_to_add; ++ unsigned long links_to_rem; ++ unsigned int link_id; + int ret = -EOPNOTSUPP; + + might_sleep(); +@@ -554,11 +560,30 @@ int drv_change_sta_links(struct ieee8021 + if (old_links == new_links) + return 0; + ++ links_to_add = ~old_links & new_links; ++ links_to_rem = old_links & ~new_links; ++ ++ for_each_set_bit(link_id, &links_to_rem, IEEE80211_MLD_MAX_NUM_LINKS) { ++ link_sta = rcu_dereference_protected(info->link[link_id], ++ lockdep_is_held(&local->sta_mtx)); ++ ++ ieee80211_link_sta_debugfs_drv_remove(link_sta); ++ } ++ + trace_drv_change_sta_links(local, sdata, sta, old_links, new_links); + if (local->ops->change_sta_links) + ret = local->ops->change_sta_links(&local->hw, &sdata->vif, sta, + old_links, new_links); + trace_drv_return_int(local, ret); + +- return ret; ++ if (ret) ++ return ret; ++ ++ for_each_set_bit(link_id, &links_to_add, IEEE80211_MLD_MAX_NUM_LINKS) { ++ link_sta = rcu_dereference_protected(info->link[link_id], ++ lockdep_is_held(&local->sta_mtx)); ++ ieee80211_link_sta_debugfs_drv_add(link_sta); ++ } ++ ++ return 0; + } +--- a/net/mac80211/driver-ops.h ++++ b/net/mac80211/driver-ops.h +@@ -497,6 +497,22 @@ static inline void drv_sta_add_debugfs(s + local->ops->sta_add_debugfs(&local->hw, &sdata->vif, + sta, dir); + } ++ ++static inline void drv_link_sta_add_debugfs(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_link_sta *link_sta, ++ struct dentry *dir) ++{ ++ might_sleep(); ++ ++ sdata = get_bss_sdata(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return; ++ ++ if (local->ops->link_sta_add_debugfs) ++ local->ops->link_sta_add_debugfs(&local->hw, &sdata->vif, ++ link_sta, dir); ++} + #endif + + static inline void drv_sta_pre_rcu_remove(struct ieee80211_local *local, +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -329,6 +329,9 @@ static void sta_remove_link(struct sta_i + if (unhash) + link_sta_info_hash_del(sta->local, link_sta); + ++ if (test_sta_flag(sta, WLAN_STA_INSERTED)) ++ ieee80211_link_sta_debugfs_remove(link_sta); ++ + if (link_sta != &sta->deflink) + alloc = container_of(link_sta, typeof(*alloc), info); + +@@ -847,6 +850,26 @@ static int sta_info_insert_finish(struct + + ieee80211_sta_debugfs_add(sta); + rate_control_add_sta_debugfs(sta); ++ if (sta->sta.valid_links) { ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(sta->link); i++) { ++ struct link_sta_info *link_sta; ++ ++ link_sta = rcu_dereference_protected(sta->link[i], ++ lockdep_is_held(&local->sta_mtx)); ++ ++ if (!link_sta) ++ continue; ++ ++ ieee80211_link_sta_debugfs_add(link_sta); ++ if (sdata->vif.active_links & BIT(i)) ++ ieee80211_link_sta_debugfs_drv_add(link_sta); ++ } ++ } else { ++ ieee80211_link_sta_debugfs_add(&sta->deflink); ++ ieee80211_link_sta_debugfs_drv_add(&sta->deflink); ++ } + + sinfo->generation = local->sta_generation; + cfg80211_new_sta(sdata->dev, sta->sta.addr, sinfo, GFP_KERNEL); +@@ -2788,6 +2811,8 @@ int ieee80211_sta_allocate_link(struct s + + sta_info_add_link(sta, link_id, &alloc->info, &alloc->sta); + ++ ieee80211_link_sta_debugfs_add(&alloc->info); ++ + return 0; + } + +--- a/net/mac80211/sta_info.h ++++ b/net/mac80211/sta_info.h +@@ -530,6 +530,7 @@ struct ieee80211_fragment_cache { + * @status_stats.avg_ack_signal: average ACK signal + * @cur_max_bandwidth: maximum bandwidth to use for TX to the station, + * taken from HT/VHT capabilities or VHT operating mode notification ++ * @debugfs_dir: debug filesystem directory dentry + * @pub: public (driver visible) link STA data + * TODO Move other link params from sta_info as required for MLD operation + */ +@@ -577,6 +578,10 @@ struct link_sta_info { + + enum ieee80211_sta_rx_bandwidth cur_max_bandwidth; + ++#ifdef CPTCFG_MAC80211_DEBUGFS ++ struct dentry *debugfs_dir; ++#endif ++ + struct ieee80211_link_sta *pub; + }; + diff --git a/feeds/ipq95xx/mac80211/patches/qca/714-02-wifi-mac80211-include-link-address-in-debugfs.patch b/feeds/ipq95xx/mac80211/patches/qca/714-02-wifi-mac80211-include-link-address-in-debugfs.patch new file mode 100644 index 000000000..c9f6f00e2 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/714-02-wifi-mac80211-include-link-address-in-debugfs.patch @@ -0,0 +1,51 @@ +From 4e3f8a549df71d47e05e195d9538316136ba1acc Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Wed, 1 Feb 2023 16:56:40 +0530 +Subject: [PATCH] wifi: mac80211: include link address in debugfs + +Add the link address to the per-link information, but only if we are +using MLO. + +Signed-off-by: Benjamin Berg +Signed-off-by: Johannes Berg +Signed-off-by: Sriram R +--- + net/mac80211/debugfs_sta.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c +index 25abff4..e4fb7ee 100644 +--- a/net/mac80211/debugfs_sta.c ++++ b/net/mac80211/debugfs_sta.c +@@ -443,6 +443,19 @@ static const struct file_operations link_sta_ ##name## _ops = { \ + .llseek = generic_file_llseek, \ + } + ++static ssize_t link_sta_addr_read(struct file *file, char __user *userbuf, ++ size_t count, loff_t *ppos) ++{ ++ struct link_sta_info *link_sta = file->private_data; ++ u8 mac[3 * ETH_ALEN + 1]; ++ ++ snprintf(mac, sizeof(mac), "%pM\n", link_sta->pub->addr); ++ ++ return simple_read_from_buffer(userbuf, count, ppos, mac, 3 * ETH_ALEN); ++} ++ ++LINK_STA_OPS(addr); ++ + static ssize_t link_sta_ht_capa_read(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) + { +@@ -1534,6 +1547,8 @@ void ieee80211_link_sta_debugfs_add(struct link_sta_info *link_sta) + link_sta->debugfs_dir = + debugfs_create_dir(link_dir_name, + link_sta->sta->debugfs_dir); ++ ++ DEBUGFS_ADD(addr); + } else { + if (WARN_ON(link_sta != &link_sta->sta->deflink)) + return; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/714-03-UPSTREAM-wifi-mac80211-add-pointer-from-link-STA-to-STA.patch b/feeds/ipq95xx/mac80211/patches/qca/714-03-UPSTREAM-wifi-mac80211-add-pointer-from-link-STA-to-STA.patch new file mode 100644 index 000000000..c5298c353 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/714-03-UPSTREAM-wifi-mac80211-add-pointer-from-link-STA-to-STA.patch @@ -0,0 +1,52 @@ +From 1d9e4c91db17c9bf6f94ac234a4d4f2bffd52b97 Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Tue, 6 Sep 2022 19:02:04 +0200 +Subject: [PATCH] wifi: mac80211: add pointer from link STA to STA + +While often not needed, this considerably simplifies going from a link +to the STA. This helps in cases such as debugfs where a single pointer +should allow accessing a specific link and the STA. + +Signed-off-by: Benjamin Berg +Signed-off-by: Johannes Berg +--- + include/net/mac80211.h | 3 +++ + net/mac80211/sta_info.c | 1 + + 2 files changed, 4 insertions(+) + +diff --git a/include/net/mac80211.h b/include/net/mac80211.h +index ac2bad57933f..7778a92d9582 100644 +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -2176,6 +2176,7 @@ struct ieee80211_sta_aggregates { + * All link specific info for a STA link for a non MLD STA(single) + * or a MLD STA(multiple entries) are stored here. + * ++ * @sta: reference to owning STA + * @addr: MAC address of the Link STA. For non-MLO STA this is same as the addr + * in ieee80211_sta. For MLO Link STA this addr can be same or different + * from addr in ieee80211_sta (representing MLD STA addr) +@@ -2196,6 +2197,8 @@ struct ieee80211_sta_aggregates { + * + */ + struct ieee80211_link_sta { ++ struct ieee80211_sta *sta; ++ + u8 addr[ETH_ALEN]; + u8 link_id; + enum ieee80211_smps_mode smps_mode; +diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c +index cebfd148bb40..71b1488bd390 100644 +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -511,6 +511,7 @@ static void sta_info_add_link(struct sta_info *sta, + link_info->sta = sta; + link_info->link_id = link_id; + link_info->pub = link_sta; ++ link_info->pub->sta = &sta->sta; + link_sta->link_id = link_id; + rcu_assign_pointer(sta->link[link_id], link_info); + rcu_assign_pointer(sta->sta.link[link_id], link_sta); +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/714-04-wifi-ath12k-move-link-sta-specific-stats.patch b/feeds/ipq95xx/mac80211/patches/qca/714-04-wifi-ath12k-move-link-sta-specific-stats.patch new file mode 100644 index 000000000..b469ab1b8 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/714-04-wifi-ath12k-move-link-sta-specific-stats.patch @@ -0,0 +1,758 @@ +From 8ea9a8f675d297d678b867eaa0f60bc447702a06 Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Thu, 9 Feb 2023 14:34:20 +0530 +Subject: [PATCH] ath12k: move link specific dp stats to link sta directory + +Move the following stats to link sta specific under ieee80211_link_sta +directory. + - ext_tx_stats + - ext_rx_stats + - driver rx packets flow + - htt peer stats + - peer pktlog + +Note: remaining stats such as addba, delba, aggr_mode are common but +needs to be applied to all link stations on a common command in the +ieee80211_sta directory. + +Signed-off-by: Sriram R +--- + drivers/net/wireless/ath/ath12k/debugfs_sta.c | 387 +++++++++++++++--- + drivers/net/wireless/ath/ath12k/debugfs_sta.h | 3 + + drivers/net/wireless/ath/ath12k/mac.c | 1 + + 3 files changed, 323 insertions(+), 68 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/debugfs_sta.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs_sta.c +@@ -199,10 +199,13 @@ static ssize_t ath12k_dbg_sta_dump_tx_st + char __user *user_buf, + size_t count, loff_t *ppos) + { +- struct ieee80211_sta *sta = file->private_data; ++ struct ieee80211_link_sta *link_sta = file->private_data; ++ struct ieee80211_sta *sta = link_sta->sta; ++ u8 link_id = link_sta->link_id; + struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; +- struct ath12k_link_sta *arsta = &ahsta->deflink; +- struct ath12k *ar = arsta->arvif->ar; ++ struct ath12k_hw *ah = ahsta->ahvif->ah; ++ struct ath12k_link_sta *arsta; ++ struct ath12k *ar; + struct ath12k_htt_data_stats *stats; + static const char *str_name[ATH12K_STATS_TYPE_MAX] = {"success", "fail", + "retry", "ampdu"}; +@@ -219,12 +222,32 @@ static ssize_t ath12k_dbg_sta_dump_tx_st + [HAL_WBM_REL_HTT_TX_COMP_STATUS_MEC_NOTIFY] = "MEC notify pkt count"}; + int idx; + +- if (!arsta->tx_stats || !arsta->wbm_tx_stats) ++ mutex_lock(&ah->conf_mutex); ++ ++ if (!(BIT(link_id) & ahsta->links_map)) { ++ mutex_unlock(&ah->conf_mutex); + return -ENOENT; ++ } ++ ++ arsta = ahsta->link[link_id]; ++ ++ if (!arsta || !arsta->arvif->ar) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } ++ ++ ar = arsta->arvif->ar; ++ ++ if (!arsta->tx_stats || !arsta->wbm_tx_stats) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } + + buf = kzalloc(size, GFP_KERNEL); +- if (!buf) ++ if (!buf) { ++ mutex_unlock(&ah->conf_mutex); + return -ENOMEM; ++ } + + mutex_lock(&ar->conf_mutex); + +@@ -377,6 +400,7 @@ static ssize_t ath12k_dbg_sta_dump_tx_st + kfree(buf); + + mutex_unlock(&ar->conf_mutex); ++ mutex_unlock(&ah->conf_mutex); + return retval; + } + +@@ -391,11 +415,14 @@ static ssize_t ath12k_dbg_sta_dump_rx_st + char __user *user_buf, + size_t count, loff_t *ppos) + { +- struct ieee80211_sta *sta = file->private_data; ++ struct ieee80211_link_sta *link_sta = file->private_data; ++ struct ieee80211_sta *sta = link_sta->sta; ++ u8 link_id = link_sta->link_id; + struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; +- struct ath12k_link_sta *arsta = &ahsta->deflink; +- struct ath12k *ar = arsta->arvif->ar; +- struct ath12k_rx_peer_stats *rx_stats = arsta->rx_stats; ++ struct ath12k_hw *ah = ahsta->ahvif->ah; ++ struct ath12k_link_sta *arsta; ++ struct ath12k *ar; ++ struct ath12k_rx_peer_stats *rx_stats; + int len = 0, i, retval = 0; + const int size = 4 * 4096; + char *buf; +@@ -404,12 +431,34 @@ static ssize_t ath12k_dbg_sta_dump_rx_st + "1Mbps", "2Mbps", "5.5Mbps", "6Mbps", + "9Mbps", "11Mbps", "12Mbps", "18Mbps", + "24Mbps", "36 Mbps", "48Mbps", "54Mbps"}; +- if (!rx_stats) ++ mutex_lock(&ah->conf_mutex); ++ ++ if (!(BIT(link_id) & ahsta->links_map)) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } ++ ++ arsta = ahsta->link[link_id]; ++ ++ if (!arsta || !arsta->arvif->ar) { ++ mutex_unlock(&ah->conf_mutex); + return -ENOENT; ++ } ++ ++ ar = arsta->arvif->ar; ++ ++ rx_stats = arsta->rx_stats; ++ ++ if (!rx_stats) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } + + buf = kzalloc(size, GFP_KERNEL); +- if (!buf) ++ if (!buf) { ++ mutex_unlock(&ah->conf_mutex); + return -ENOMEM; ++ } + + mutex_lock(&ar->conf_mutex); + spin_lock_bh(&ar->ab->base_lock); +@@ -649,6 +698,7 @@ static ssize_t ath12k_dbg_sta_dump_rx_st + kfree(buf); + + mutex_unlock(&ar->conf_mutex); ++ mutex_unlock(&ah->conf_mutex); + return retval; + } + +@@ -662,52 +712,97 @@ static const struct file_operations fops + static int + ath12k_dbg_sta_open_htt_peer_stats(struct inode *inode, struct file *file) + { +- struct ieee80211_sta *sta = inode->i_private; ++ struct ieee80211_link_sta *link_sta = inode->i_private; ++ struct ieee80211_sta *sta = link_sta->sta; ++ u8 link_id = link_sta->link_id; + struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; +- struct ath12k_link_sta *arsta = &ahsta->deflink; +- struct ath12k *ar = arsta->arvif->ar; ++ struct ath12k_hw *ah = ahsta->ahvif->ah; ++ struct ath12k_link_sta *arsta; ++ struct ath12k *ar; + struct debug_htt_stats_req *stats_req; +- int type = ar->debug.htt_stats.type; ++ int type; + int ret; + ++ mutex_lock(&ah->conf_mutex); ++ ++ if (!(BIT(link_id) & ahsta->links_map)) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } ++ ++ arsta = ahsta->link[link_id]; ++ ++ if (!arsta || !arsta->arvif->ar) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } ++ ++ ar = arsta->arvif->ar; ++ ++ type = ar->debug.htt_stats.type; + if ((type != ATH12K_DBG_HTT_EXT_STATS_PEER_INFO && + type != ATH12K_DBG_HTT_EXT_PEER_CTRL_PATH_TXRX_STATS) || +- type == ATH12K_DBG_HTT_EXT_STATS_RESET) ++ type == ATH12K_DBG_HTT_EXT_STATS_RESET) { ++ mutex_unlock(&ah->conf_mutex); + return -EPERM; ++ } + + stats_req = vzalloc(sizeof(*stats_req) + ATH12K_HTT_STATS_BUF_SIZE); +- if (!stats_req) ++ if (!stats_req) { ++ mutex_unlock(&ah->conf_mutex); + return -ENOMEM; ++ } + + mutex_lock(&ar->conf_mutex); + ar->debug.htt_stats.stats_req = stats_req; + stats_req->type = ATH12K_DBG_HTT_EXT_STATS_PEER_INFO; +- memcpy(stats_req->peer_addr, sta->addr, ETH_ALEN); ++ memcpy(stats_req->peer_addr, link_sta->addr, ETH_ALEN); + ret = ath12k_debugfs_htt_stats_req(ar); + mutex_unlock(&ar->conf_mutex); + if (ret < 0) + goto out; + + file->private_data = stats_req; ++ mutex_unlock(&ah->conf_mutex); + return 0; + out: + vfree(stats_req); + ar->debug.htt_stats.stats_req = NULL; ++ mutex_unlock(&ah->conf_mutex); + return ret; + } + + static int + ath12k_dbg_sta_release_htt_peer_stats(struct inode *inode, struct file *file) + { +- struct ieee80211_sta *sta = inode->i_private; ++ struct ieee80211_link_sta *link_sta = inode->i_private; ++ struct ieee80211_sta *sta = link_sta->sta; ++ u8 link_id = link_sta->link_id; + struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; +- struct ath12k_link_sta *arsta = &ahsta->deflink; +- struct ath12k *ar = arsta->arvif->ar; ++ struct ath12k_hw *ah = ahsta->ahvif->ah; ++ struct ath12k_link_sta *arsta; ++ struct ath12k *ar; ++ ++ mutex_lock(&ah->conf_mutex); ++ ++ if (!(BIT(link_id) & ahsta->links_map)) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } + ++ arsta = ahsta->link[link_id]; ++ ++ if (!arsta || !arsta->arvif->ar) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } ++ ++ ar = arsta->arvif->ar; + mutex_lock(&ar->conf_mutex); + vfree(file->private_data); + ar->debug.htt_stats.stats_req = NULL; + mutex_unlock(&ar->conf_mutex); ++ mutex_unlock(&ah->conf_mutex); + + return 0; + } +@@ -737,12 +832,31 @@ static ssize_t ath12k_dbg_sta_write_peer + const char __user *buf, + size_t count, loff_t *ppos) + { +- struct ieee80211_sta *sta = file->private_data; ++ struct ieee80211_link_sta *link_sta = file->private_data; ++ struct ieee80211_sta *sta = link_sta->sta; ++ u8 link_id = link_sta->link_id; + struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; +- struct ath12k_link_sta *arsta = &ahsta->deflink; +- struct ath12k *ar = arsta->arvif->ar; ++ struct ath12k_hw *ah = ahsta->ahvif->ah; ++ struct ath12k_link_sta *arsta; ++ struct ath12k *ar; + int ret, enable; + ++ mutex_lock(&ah->conf_mutex); ++ ++ if (!(BIT(link_id) & ahsta->links_map)) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } ++ ++ arsta = ahsta->link[link_id]; ++ ++ if (!arsta || !arsta->arvif->ar) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } ++ ++ ar = arsta->arvif->ar; ++ + mutex_lock(&ar->conf_mutex); + + if (ar->state != ATH12K_STATE_ON) { +@@ -755,10 +869,10 @@ static ssize_t ath12k_dbg_sta_write_peer + goto out; + + ar->debug.pktlog_peer_valid = enable; +- memcpy(ar->debug.pktlog_peer_addr, sta->addr, ETH_ALEN); ++ memcpy(ar->debug.pktlog_peer_addr, link_sta->addr, ETH_ALEN); + + /* Send peer based pktlog enable/disable */ +- ret = ath12k_wmi_pdev_peer_pktlog_filter(ar, sta->addr, enable); ++ ret = ath12k_wmi_pdev_peer_pktlog_filter(ar, link_sta->addr, enable); + if (ret) { + ath12k_warn(ar->ab, "failed to set peer pktlog filter %pM: %d\n", + sta->addr, ret); +@@ -771,6 +885,7 @@ static ssize_t ath12k_dbg_sta_write_peer + + out: + mutex_unlock(&ar->conf_mutex); ++ mutex_unlock(&ah->conf_mutex); + return ret; + } + +@@ -778,18 +893,38 @@ static ssize_t ath12k_dbg_sta_read_peer_ + char __user *ubuf, + size_t count, loff_t *ppos) + { +- struct ieee80211_sta *sta = file->private_data; ++ struct ieee80211_link_sta *link_sta = file->private_data; ++ struct ieee80211_sta *sta = link_sta->sta; ++ u8 link_id = link_sta->link_id; + struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; +- struct ath12k_link_sta *arsta = &ahsta->deflink; +- struct ath12k *ar = arsta->arvif->ar; ++ struct ath12k_hw *ah = ahsta->ahvif->ah; ++ struct ath12k_link_sta *arsta; ++ struct ath12k *ar; + char buf[32] = {0}; + int len; + ++ mutex_lock(&ah->conf_mutex); ++ ++ if (!(BIT(link_id) & ahsta->links_map)) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } ++ ++ arsta = ahsta->link[link_id]; ++ ++ if (!arsta || !arsta->arvif->ar) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } ++ ++ ar = arsta->arvif->ar; ++ + mutex_lock(&ar->conf_mutex); + len = scnprintf(buf, sizeof(buf), "%08x %pM\n", + ar->debug.pktlog_peer_valid, + ar->debug.pktlog_peer_addr); + mutex_unlock(&ar->conf_mutex); ++ mutex_unlock(&ah->conf_mutex); + + return simple_read_from_buffer(ubuf, count, ppos, buf, len); + } +@@ -1028,10 +1163,13 @@ ath12k_write_htt_peer_stats_reset(struct + const char __user *user_buf, + size_t count, loff_t *ppos) + { +- struct ieee80211_sta *sta = file->private_data; ++ struct ieee80211_link_sta *link_sta = file->private_data; ++ struct ieee80211_sta *sta = link_sta->sta; ++ u8 link_id = link_sta->link_id; + struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; +- struct ath12k_link_sta *arsta = &ahsta->deflink; +- struct ath12k *ar = arsta->arvif->ar; ++ struct ath12k_hw *ah = ahsta->ahvif->ah; ++ struct ath12k_link_sta *arsta; ++ struct ath12k *ar; + struct htt_ext_stats_cfg_params cfg_params = { 0 }; + int ret; + u8 type; +@@ -1043,6 +1181,22 @@ ath12k_write_htt_peer_stats_reset(struct + if (!type) + return ret; + ++ mutex_lock(&ah->conf_mutex); ++ ++ if (!(BIT(link_id) & ahsta->links_map)) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } ++ ++ arsta = ahsta->link[link_id]; ++ ++ if (!arsta || !arsta->arvif->ar) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } ++ ++ ar = arsta->arvif->ar; ++ + mutex_lock(&ar->conf_mutex); + cfg_params.cfg0 = HTT_STAT_PEER_INFO_MAC_ADDR; + cfg_params.cfg0 |= FIELD_PREP(GENMASK(15, 1), +@@ -1050,13 +1204,13 @@ ath12k_write_htt_peer_stats_reset(struct + + cfg_params.cfg1 = HTT_STAT_DEFAULT_PEER_REQ_TYPE; + +- cfg_params.cfg2 |= FIELD_PREP(GENMASK(7, 0), sta->addr[0]); +- cfg_params.cfg2 |= FIELD_PREP(GENMASK(15, 8), sta->addr[1]); +- cfg_params.cfg2 |= FIELD_PREP(GENMASK(23, 16), sta->addr[2]); +- cfg_params.cfg2 |= FIELD_PREP(GENMASK(31, 24), sta->addr[3]); ++ cfg_params.cfg2 |= FIELD_PREP(GENMASK(7, 0), link_sta->addr[0]); ++ cfg_params.cfg2 |= FIELD_PREP(GENMASK(15, 8), link_sta->addr[1]); ++ cfg_params.cfg2 |= FIELD_PREP(GENMASK(23, 16), link_sta->addr[2]); ++ cfg_params.cfg2 |= FIELD_PREP(GENMASK(31, 24), link_sta->addr[3]); + +- cfg_params.cfg3 |= FIELD_PREP(GENMASK(7, 0), sta->addr[4]); +- cfg_params.cfg3 |= FIELD_PREP(GENMASK(15, 8), sta->addr[5]); ++ cfg_params.cfg3 |= FIELD_PREP(GENMASK(7, 0), link_sta->addr[4]); ++ cfg_params.cfg3 |= FIELD_PREP(GENMASK(15, 8), link_sta->addr[5]); + + cfg_params.cfg3 |= ATH12K_HTT_PEER_STATS_RESET; + +@@ -1067,10 +1221,12 @@ ath12k_write_htt_peer_stats_reset(struct + if (ret) { + ath12k_warn(ar->ab, "failed to send htt peer stats request: %d\n", ret); + mutex_unlock(&ar->conf_mutex); ++ mutex_unlock(&ah->conf_mutex); + return ret; + } + + mutex_unlock(&ar->conf_mutex); ++ mutex_unlock(&ah->conf_mutex); + + ret = count; + +@@ -1089,20 +1245,43 @@ ath12k_dbg_sta_dump_driver_tx_pkts_flow( + const char __user *user_buf, + size_t count, loff_t *ppos) + { +- struct ieee80211_sta *sta = file->private_data; ++ struct ieee80211_link_sta *link_sta = file->private_data; ++ struct ieee80211_sta *sta = link_sta->sta; ++ u8 link_id = link_sta->link_id; + struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; +- struct ath12k_link_sta *arsta = &ahsta->deflink; +- struct ath12k *ar = arsta->arvif->ar; ++ struct ath12k_hw *ah = ahsta->ahvif->ah; ++ struct ath12k_link_sta *arsta; ++ struct ath12k *ar; + int len = 0, ret_val; + const int size = ATH12K_DRV_TX_STATS_SIZE; + char *buf; + +- if (!arsta->tx_stats) ++ mutex_lock(&ah->conf_mutex); ++ ++ if (!(BIT(link_id) & ahsta->links_map)) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } ++ ++ arsta = ahsta->link[link_id]; ++ ++ if (!arsta || !arsta->arvif->ar) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } ++ ++ ar = arsta->arvif->ar; ++ ++ if (!arsta->tx_stats) { ++ mutex_unlock(&ah->conf_mutex); + return -ENOENT; ++ } + + buf = kzalloc(ATH12K_DRV_TX_STATS_SIZE, GFP_KERNEL); +- if (!buf) ++ if (!buf) { ++ mutex_unlock(&ah->conf_mutex); + return -ENOMEM; ++ } + + mutex_lock(&ar->conf_mutex); + spin_lock_bh(&ar->ab->base_lock); +@@ -1121,6 +1300,7 @@ ath12k_dbg_sta_dump_driver_tx_pkts_flow( + kfree(buf); + + mutex_unlock(&ar->conf_mutex); ++ mutex_unlock(&ah->conf_mutex); + return ret_val; + } + +@@ -1135,15 +1315,15 @@ static ssize_t ath12k_dbg_sta_reset_tx_s + const char __user *buf, + size_t count, loff_t *ppos) + { +- struct ieee80211_sta *sta = file->private_data; ++ struct ieee80211_link_sta *link_sta = file->private_data; ++ struct ieee80211_sta *sta = link_sta->sta; ++ u8 link_id = link_sta->link_id; + struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; +- struct ath12k_link_sta *arsta = &ahsta->deflink; +- struct ath12k *ar = arsta->arvif->ar; ++ struct ath12k_hw *ah = ahsta->ahvif->ah; ++ struct ath12k_link_sta *arsta; ++ struct ath12k *ar; + int ret, reset; + +- if (!arsta->tx_stats || !arsta->wbm_tx_stats) +- return -ENOENT; +- + ret = kstrtoint_from_user(buf, count, 0, &reset); + if (ret) + return ret; +@@ -1151,6 +1331,26 @@ static ssize_t ath12k_dbg_sta_reset_tx_s + if (!reset || reset > 1) + return -EINVAL; + ++ mutex_lock(&ah->conf_mutex); ++ ++ if (!(BIT(link_id) & ahsta->links_map)) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } ++ ++ arsta = ahsta->link[link_id]; ++ ++ if (!arsta || !arsta->arvif->ar) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } ++ ++ ar = arsta->arvif->ar; ++ ++ if (!arsta->tx_stats || !arsta->wbm_tx_stats) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } + spin_lock_bh(&ar->ab->base_lock); + memset(arsta->tx_stats, 0, sizeof(*arsta->tx_stats)); + atomic_set(&arsta->drv_tx_pkts.pkts_in, 0); +@@ -1158,6 +1358,8 @@ static ssize_t ath12k_dbg_sta_reset_tx_s + memset(arsta->wbm_tx_stats->wbm_tx_comp_stats, 0, sizeof(*arsta->wbm_tx_stats)); + spin_unlock_bh(&ar->ab->base_lock); + ++ mutex_unlock(&ah->conf_mutex); ++ + ret = count; + return ret; + } +@@ -1174,21 +1376,45 @@ ath12k_dbg_sta_dump_driver_rx_pkts_flow( + char __user *user_buf, + size_t count, loff_t *ppos) + { +- struct ieee80211_sta *sta = file->private_data; ++ struct ieee80211_link_sta *link_sta = file->private_data; ++ struct ieee80211_sta *sta = link_sta->sta; ++ u8 link_id = link_sta->link_id; + struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; +- struct ath12k_link_sta *arsta = &ahsta->deflink; +- struct ath12k *ar = arsta->arvif->ar; +- struct ath12k_rx_peer_stats *rx_stats = arsta->rx_stats; ++ struct ath12k_hw *ah = ahsta->ahvif->ah; ++ struct ath12k_link_sta *arsta; ++ struct ath12k *ar; ++ struct ath12k_rx_peer_stats *rx_stats; + int len = 0, ret_val = 0; + const int size = 1024; + char *buf; + +- if (!rx_stats) ++ mutex_lock(&ah->conf_mutex); ++ ++ if (!(BIT(link_id) & ahsta->links_map)) { ++ mutex_unlock(&ah->conf_mutex); + return -ENOENT; ++ } ++ ++ arsta = ahsta->link[link_id]; ++ ++ if (!arsta || !arsta->arvif->ar) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } ++ ++ ar = arsta->arvif->ar; ++ ++ rx_stats = arsta->rx_stats; ++ if (!rx_stats) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } + + buf = kzalloc(size, GFP_KERNEL); +- if (!buf) ++ if (!buf) { ++ mutex_unlock(&ah->conf_mutex); + return -ENOMEM; ++ } + + mutex_lock(&ar->conf_mutex); + spin_lock_bh(&ar->ab->base_lock); +@@ -1211,6 +1437,7 @@ ath12k_dbg_sta_dump_driver_rx_pkts_flow( + kfree(buf); + + mutex_unlock(&ar->conf_mutex); ++ mutex_unlock(&ah->conf_mutex); + return ret_val; + } + +@@ -1225,15 +1452,15 @@ static ssize_t ath12k_dbg_sta_reset_rx_s + const char __user *buf, + size_t count, loff_t *ppos) + { +- struct ieee80211_sta *sta = file->private_data; ++ struct ieee80211_link_sta *link_sta = file->private_data; ++ struct ieee80211_sta *sta = link_sta->sta; ++ u8 link_id = link_sta->link_id; + struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; +- struct ath12k_link_sta *arsta = &ahsta->deflink; +- struct ath12k *ar = arsta->arvif->ar; ++ struct ath12k_hw *ah = ahsta->ahvif->ah; ++ struct ath12k_link_sta *arsta; ++ struct ath12k *ar; + int ret, reset; + +- if (!arsta->rx_stats) +- return -ENOENT; +- + ret = kstrtoint_from_user(buf, count, 0, &reset); + if (ret) + return ret; +@@ -1241,11 +1468,32 @@ static ssize_t ath12k_dbg_sta_reset_rx_s + if (!reset || reset > 1) + return -EINVAL; + ++ mutex_lock(&ah->conf_mutex); ++ ++ if (!(BIT(link_id) & ahsta->links_map)) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } ++ ++ arsta = ahsta->link[link_id]; ++ ++ if (!arsta || !arsta->arvif->ar) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } ++ ++ ar = arsta->arvif->ar; ++ if (!arsta->rx_stats) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } ++ + spin_lock_bh(&ar->ab->base_lock); + memset(arsta->rx_stats, 0, sizeof(*arsta->rx_stats)); + atomic_set(&arsta->drv_rx_pkts.pkts_frm_hw, 0); + atomic_set(&arsta->drv_rx_pkts.pkts_out, 0); + spin_unlock_bh(&ar->ab->base_lock); ++ mutex_unlock(&ah->conf_mutex); + + ret = count; + return ret; +@@ -1261,49 +1509,53 @@ static const struct file_operations fops + void ath12k_debugfs_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, struct dentry *dir) + { ++ debugfs_create_file("aggr_mode", 0644, dir, sta, &fops_aggr_mode); ++ debugfs_create_file("addba", 0200, dir, sta, &fops_addba); ++ debugfs_create_file("addba_resp", 0200, dir, sta, &fops_addba_resp); ++ debugfs_create_file("delba", 0200, dir, sta, &fops_delba); ++} ++ ++void ath12k_debugfs_link_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ++ struct ieee80211_link_sta *link_sta, struct dentry *dir) ++{ ++ u8 link_id = link_sta->link_id; + struct ath12k *ar; + struct ath12k_hw *ah = hw->priv; + + mutex_lock(&ah->conf_mutex); + +- /* TODO for ML vifs */ +- ar = ath12k_get_ar_by_vif(hw, vif, 0); ++ ar = ath12k_get_ar_by_vif(hw, vif, link_id); + if (!ar) { + mutex_unlock(&ah->conf_mutex); + return; + } + + if (ath12k_debugfs_is_extd_tx_stats_enabled(ar)) { +- debugfs_create_file("tx_stats", 0400, dir, sta, ++ debugfs_create_file("tx_stats", 0400, dir, link_sta, + &fops_tx_stats); +- debugfs_create_file("reset_tx_stats", 0600, dir, sta, ++ debugfs_create_file("reset_tx_stats", 0600, dir, link_sta, + &fops_reset_tx_stats); +- debugfs_create_file("driver_tx_pkts_flow", 0400, dir, sta, ++ debugfs_create_file("driver_tx_pkts_flow", 0400, dir, link_sta, + &fops_driver_tx_pkts_flow); + } + if (ath12k_debugfs_is_extd_rx_stats_enabled(ar)) { +- debugfs_create_file("rx_stats", 0400, dir, sta, ++ debugfs_create_file("rx_stats", 0400, dir, link_sta, + &fops_rx_stats); +- debugfs_create_file("reset_rx_stats", 0600, dir, sta, ++ debugfs_create_file("reset_rx_stats", 0600, dir, link_sta, + &fops_reset_rx_stats); +- debugfs_create_file("driver_rx_pkts_flow", 0400, dir, sta, ++ debugfs_create_file("driver_rx_pkts_flow", 0400, dir, link_sta, + &fops_driver_rx_pkts_flow); + } + +- debugfs_create_file("htt_peer_stats", 0400, dir, sta, ++ debugfs_create_file("htt_peer_stats", 0400, dir, link_sta, + &fops_htt_peer_stats); + +- debugfs_create_file("peer_pktlog", 0644, dir, sta, ++ debugfs_create_file("peer_pktlog", 0644, dir, link_sta, + &fops_peer_pktlog); + +- debugfs_create_file("aggr_mode", 0644, dir, sta, &fops_aggr_mode); +- debugfs_create_file("addba", 0200, dir, sta, &fops_addba); +- debugfs_create_file("addba_resp", 0200, dir, sta, &fops_addba_resp); +- debugfs_create_file("delba", 0200, dir, sta, &fops_delba); +- + if (test_bit(WMI_TLV_SERVICE_PER_PEER_HTT_STATS_RESET, + ar->ab->wmi_ab.svc_map)) +- debugfs_create_file("htt_peer_stats_reset", 0600, dir, sta, ++ debugfs_create_file("htt_peer_stats_reset", 0600, dir, link_sta, + &fops_htt_peer_stats_reset); + + mutex_unlock(&ah->conf_mutex); +--- a/drivers/net/wireless/ath/ath12k/debugfs_sta.h ++++ b/drivers/net/wireless/ath/ath12k/debugfs_sta.h +@@ -17,6 +17,8 @@ + + void ath12k_debugfs_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, struct dentry *dir); ++void ath12k_debugfs_link_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ++ struct ieee80211_link_sta *link_sta, struct dentry *dir); + void ath12k_debugfs_sta_add_tx_stats(struct ath12k_link_sta *arsta, + struct ath12k_per_peer_tx_stats *peer_stats, + u8 legacy_rate_idx); +@@ -26,6 +28,7 @@ void ath12k_debugfs_sta_update_txcompl(s + #else /* CPTCFG_ATH12K_DEBUGFS */ + + #define ath12k_debugfs_sta_op_add NULL ++#define ath12k_debugfs_link_sta_op_add NULL + + static inline void + ath12k_debugfs_sta_add_tx_stats(struct ath12k_link_sta *arsta, +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -13488,6 +13488,7 @@ static const struct ieee80211_ops ath12k + CFG80211_TESTMODE_CMD(ath12k_tm_cmd) + #ifdef CPTCFG_ATH12K_DEBUGFS + .sta_add_debugfs = ath12k_debugfs_sta_op_add, ++ .link_sta_add_debugfs = ath12k_debugfs_link_sta_op_add, + #endif + .get_txpower = ath12k_mac_op_get_txpower, + .set_radar_background = ath12k_mac_op_set_radar_background, diff --git a/feeds/ipq95xx/mac80211/patches/qca/675-ath12k-Introduce-module-param-for-NAPI-budget-proces.patch b/feeds/ipq95xx/mac80211/patches/qca/714-ath12k-Introduce-module-param-for-NAPI-budget-proces.patch similarity index 65% rename from feeds/ipq95xx/mac80211/patches/qca/675-ath12k-Introduce-module-param-for-NAPI-budget-proces.patch rename to feeds/ipq95xx/mac80211/patches/qca/714-ath12k-Introduce-module-param-for-NAPI-budget-proces.patch index 5a1ef104d..30ec5c311 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/675-ath12k-Introduce-module-param-for-NAPI-budget-proces.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/714-ath12k-Introduce-module-param-for-NAPI-budget-proces.patch @@ -1,19 +1,19 @@ -From 05ed238970765168765133c66733e869accdd95f Mon Sep 17 00:00:00 2001 -From: Balamurugan Selvarajan -Date: Thu, 6 Oct 2022 10:44:43 +0530 -Subject: [PATCH] ath12k: Introduce module param for NAPI budget processing +From 2ce0fc27d2c8814e53d9e02a1f8c65a0f68f04d9 Mon Sep 17 00:00:00 2001 +From: Balamurugan S +Date: Sat, 28 Jan 2023 11:01:24 +0530 +Subject: [PATCH 2/2] ath12k: Introduce module param for NAPI budget processing Increase NAPI poll budget to 0x7f. In rx frames processing by default 64 frames are processed per interrupt. This is increased to 127. -Signed-off-by: Balamurugan Selvarajan +Signed-off-by: Balamurugan S --- - drivers/net/wireless/ath/ath12k/pci.c | 11 ++++++++++- - 1 file changed, 10 insertions(+), 1 deletion(-) + drivers/net/wireless/ath/ath12k/pci.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) --- a/drivers/net/wireless/ath/ath12k/pci.c +++ b/drivers/net/wireless/ath/ath12k/pci.c -@@ -51,6 +51,11 @@ EXPORT_SYMBOL(ath12k_fw_mem_seg); +@@ -52,6 +52,11 @@ EXPORT_SYMBOL(ath12k_fw_mem_seg); module_param_named(fw_mem_seg, ath12k_fw_mem_seg, uint, 0644); MODULE_PARM_DESC(fw_mem_seg, "Enable/Disable FW segmentted memory"); @@ -23,9 +23,9 @@ Signed-off-by: Balamurugan Selvarajan +MODULE_PARM_DESC(napi_budget, "Napi budget processing per rx intr"); + static const struct pci_device_id ath12k_pci_id_table[] = { - { PCI_VDEVICE(QCOM, QCN92XX_DEVICE_ID) }, - {0} -@@ -559,7 +564,7 @@ static irqreturn_t ath12k_pci_ext_interr + { PCI_VDEVICE(QCOM, QCN9274_DEVICE_ID) }, + { PCI_VDEVICE(QCOM, WCN7850_DEVICE_ID) }, +@@ -492,7 +497,7 @@ static irqreturn_t ath12k_pci_ext_interr static int ath12k_pci_ext_irq_config(struct ath12k_base *ab) { int i, j, ret, num_vectors = 0; @@ -34,7 +34,7 @@ Signed-off-by: Balamurugan Selvarajan struct ath12k_pci *ar_pci = (struct ath12k_pci *)ab->drv_priv; base_idx = ATH12K_PCI_IRQ_CE0_OFFSET + CE_COUNT_MAX; -@@ -570,6 +575,9 @@ static int ath12k_pci_ext_irq_config(str +@@ -503,6 +508,9 @@ static int ath12k_pci_ext_irq_config(str if (ret < 0) return ret; @@ -44,12 +44,12 @@ Signed-off-by: Balamurugan Selvarajan for (i = 0; i < ATH12K_EXT_IRQ_GRP_NUM_MAX; i++) { struct ath12k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; u32 num_irq = 0; -@@ -577,8 +585,14 @@ static int ath12k_pci_ext_irq_config(str +@@ -510,8 +518,14 @@ static int ath12k_pci_ext_irq_config(str irq_grp->ab = ab; irq_grp->grp_id = i; init_dummy_netdev(&irq_grp->napi_ndev); + -+ if (ab->hw_params.ring_mask->rx_mon_dest[i]) ++ if (ab->hw_params->ring_mask->rx_mon_dest[i]) + budget = NAPI_POLL_WEIGHT; + else + budget = ath12k_napi_poll_budget; @@ -58,5 +58,5 @@ Signed-off-by: Balamurugan Selvarajan - ath12k_pci_ext_grp_napi_poll, NAPI_POLL_WEIGHT); + ath12k_pci_ext_grp_napi_poll, budget); - if (ab->hw_params.ring_mask->tx[i] || - ab->hw_params.ring_mask->rx[i] || + if (ab->hw_params->ring_mask->tx[i] || + ab->hw_params->ring_mask->rx[i] || diff --git a/feeds/ipq95xx/mac80211/patches/qca/714-ath12k-add-support-to-get-rssi-value-of-non-associat.patch b/feeds/ipq95xx/mac80211/patches/qca/714-ath12k-add-support-to-get-rssi-value-of-non-associat.patch new file mode 100644 index 000000000..212454dff --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/714-ath12k-add-support-to-get-rssi-value-of-non-associat.patch @@ -0,0 +1,622 @@ +From b483635554370f2be82106db486963fcd2708dfc Mon Sep 17 00:00:00 2001 +From: Suresh Krishna +Date: Fri, 13 Jan 2023 14:41:57 +0530 +Subject: [PATCH] ath12k: add support to get rssi value of non-associated + client + +Monitor the surrounding network to get RSSI of non-associated +client(i.e Neighbor-Peer associated to neighboring AP's). +Obtaining the RSSI it is useful for roaming between AP's in a +network and on deciding which AP the client should associate +with. +This is achieved through debugfs by providing the mac address +of a nrp which creates a neighbor-peer object to store's the +data associated with the nrp such as its mac, RSSI and timestamp. +Once the nrp is added a file with the mac-address of nrp as its +filename is created. +Each time the file is read a peer object is created for the +NRP and filter is set to get its ppdu_info for home channel +thereby obtaining the RSSI and a corresponding unix +timestamp is created, once the data collection is completed the +peer object is destroyed to free-up peer count. +Upto 6 NRPs can be created to keep the load and peer-count low. +Once the rssi and timestamp are obtained the peer object +created for NRP is deleted to free the peer id. +In case the NRP packets are unavailable during scan the +previous timestamped value is returned. + +Command to add a Neighbor-Peer: +echo "add," > +/sys/kernel/debug/ieee80211/phyX/ath12k_hwY/neighbor_peer + +Command to delete a Neighbor-Peer: +echo "del," > +/sys/kernel/debug/ieee80211/phyX/ath12k_hwY/neighbor_peer + +Command to display RSSI of Neighbor-Peer: +cat /sys/kernel/debug/ieee80211/phyX/ath12k_hwY/nrp_rssi/ + +Signed-off-by: Suresh Krishna +--- + drivers/net/wireless/ath/ath12k/core.c | 3 + + drivers/net/wireless/ath/ath12k/core.h | 4 + + drivers/net/wireless/ath/ath12k/debugfs.c | 348 ++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/debugfs.h | 30 ++ + drivers/net/wireless/ath/ath12k/dp_mon.c | 14 + + drivers/net/wireless/ath/ath12k/mac.c | 35 +++ + 6 files changed, 434 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c +index ce34b2e..7844274 100644 +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -1382,6 +1382,8 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab) + complete(&ar->scan.completed); + complete(&ar->peer_assoc_done); + complete(&ar->peer_delete_done); ++ if (!list_empty(&ab->neighbor_peers)) ++ ath12k_debugfs_nrp_cleanup_all(ar); + complete(&ar->install_key_done); + complete(&ar->vdev_setup_done); + complete(&ar->vdev_delete_done); +@@ -1867,6 +1869,7 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size, + init_completion(&ab->reset_complete); + + INIT_LIST_HEAD(&ab->peers); ++ INIT_LIST_HEAD(&ab->neighbor_peers); + init_waitqueue_head(&ab->peer_mapping_wq); + init_waitqueue_head(&ab->wmi_ab.tx_credits_wq); + init_waitqueue_head(&ab->qmi.cold_boot_waitq); +diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h +index d999a0b..179f3c3 100644 +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -685,6 +685,7 @@ struct ath12k_debug { + struct list_head wmi_list; + struct completion wmi_ctrl_path_stats_rcvd; + u32 wmi_ctrl_path_stats_tagid; ++ struct dentry *debugfs_nrp; + }; + + int ath12k_pktlog_rx_filter_setting(struct ath12k *ar, +@@ -1158,6 +1159,9 @@ struct ath12k_base { + #ifdef CPTCFG_ATH12K_DEBUGFS + struct dentry *debugfs_soc; + #endif ++ struct list_head neighbor_peers; ++ int num_nrps; ++ + struct ath12k_soc_dp_stats soc_stats; + + unsigned long dev_flags; +diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c +index 7ab5244..5b08f54 100644 +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -999,6 +999,351 @@ static const struct file_operations fops_extd_rx_stats = { + .open = simple_open, + }; + ++static int ath12k_reset_nrp_filter(struct ath12k *ar, ++ bool reset) ++{ ++ int i = 0; ++ int ret = 0; ++ u32 ring_id = 0; ++ u32 rx_filter = 0; ++ struct htt_rx_ring_tlv_filter tlv_filter = {0}; ++ ++ if (!reset) { ++ rx_filter = ar->debug.rx_filter; ++ rx_filter |= HTT_RX_FILTER_TLV_FLAGS_MPDU_START; ++ rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_START; ++ rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END; ++ rx_filter |= HTT_RX_FILTER_TLV_FLAGS_MPDU_END; ++ ++ tlv_filter.rx_filter = rx_filter; ++ tlv_filter.pkt_filter_flags0 = HTT_RX_MO_MGMT_FILTER_FLAGS0; ++ tlv_filter.pkt_filter_flags1 = HTT_RX_MO_MGMT_FILTER_FLAGS1; ++ tlv_filter.pkt_filter_flags2 = HTT_RX_MO_CTRL_FILTER_FLASG2; ++ tlv_filter.pkt_filter_flags3 = HTT_RX_MON_MO_CTRL_FILTER_FLASG3 | ++ HTT_RX_MON_MO_DATA_FILTER_FLASG3; ++ } else { ++ tlv_filter.rx_filter = ar->debug.rx_filter; ++ } ++ tlv_filter.offset_valid = false; ++ ++ for (i = 0; i < ar->ab->hw_params->num_rxmda_per_pdev; i++) { ++ ring_id = ar->dp.rxdma_mon_dst_ring[i].ring_id; ++ ret = ath12k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id + i, ++ HAL_RXDMA_MONITOR_DST, ++ DP_RXDMA_REFILL_RING_SIZE, ++ &tlv_filter); ++ if (ret) { ++ ath12k_err(ar->ab, ++ "failed to setup filter for monitor buf %d\n", ret); ++ return ret; ++ } ++ } ++ return ret; ++} ++ ++void ath12k_debugfs_nrp_cleanup_all(struct ath12k *ar) ++{ ++ struct ath12k_base *ab = ar->ab; ++ struct ath12k_neighbor_peer *nrp, *tmp; ++ ++ spin_lock_bh(&ab->base_lock); ++ list_for_each_entry_safe(nrp, tmp, &ab->neighbor_peers, list) { ++ if (nrp->is_filter_on) ++ complete(&nrp->filter_done); ++ list_del(&nrp->list); ++ kfree(nrp); ++ } ++ ++ ab->num_nrps = 0; ++ spin_unlock_bh(&ab->base_lock); ++ ++ debugfs_remove_recursive(ar->debug.debugfs_nrp); ++} ++ ++void ath12k_debugfs_nrp_clean(struct ath12k *ar, const u8 *addr) ++{ ++ int i, j; ++ char fname[MAC_UNIT_LEN * ETH_ALEN] = {0}; ++ ++ for (i = 0, j = 0; i < (MAC_UNIT_LEN * ETH_ALEN); i += MAC_UNIT_LEN, j++) { ++ if (j == ETH_ALEN - 1) { ++ snprintf(fname + i, sizeof(fname) - i, "%02x", *(addr + j)); ++ break; ++ } ++ snprintf(fname + i, sizeof(fname) - i, "%02x:", *(addr + j)); ++ } ++ ++ spin_lock_bh(&ar->ab->base_lock); ++ ar->ab->num_nrps--; ++ spin_unlock_bh(&ar->ab->base_lock); ++ ++ debugfs_lookup_and_remove(fname, ar->debug.debugfs_nrp); ++ if (!ar->ab->num_nrps) { ++ debugfs_remove_recursive(ar->debug.debugfs_nrp); ++ ath12k_reset_nrp_filter(ar, true); ++ } ++} ++ ++static ssize_t ath12k_read_nrp_rssi(struct file *file, ++ char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ struct ath12k_base *ab = ar->ab; ++ struct ath12k_link_vif *arvif = NULL; ++ struct ath12k_neighbor_peer *nrp = NULL, *tmp; ++ struct peer_create_params peer_param = {0}; ++ u8 macaddr[ETH_ALEN] = {0}; ++ loff_t file_pos = *ppos; ++ struct path *fpath = &file->f_path; ++ char *fname = fpath->dentry->d_iname; ++ char buf[128] = {0}; ++ int i = 0; ++ int j = 0; ++ int len = 0; ++ int vdev_id = -1; ++ bool nrp_found = false; ++ ++ mutex_lock(&ar->conf_mutex); ++ if (ar->state != ATH12K_STATE_ON) { ++ mutex_unlock(&ar->conf_mutex); ++ return -ENETDOWN; ++ } ++ mutex_unlock(&ar->conf_mutex); ++ ++ if (file_pos > 0) ++ return 0; ++ ++ list_for_each_entry(arvif, &ar->arvifs, list) { ++ if (arvif->ahvif->vdev_type == WMI_VDEV_TYPE_AP) { ++ vdev_id = arvif->vdev_id; ++ break; ++ } ++ } ++ if (vdev_id < 0) { ++ ath12k_warn(ab, "unable to get vdev for AP interface\n"); ++ return 0; ++ } ++ ++ for (i = 0, j = 0; i < MAC_UNIT_LEN * ETH_ALEN; i += MAC_UNIT_LEN, j++) { ++ if (sscanf(fname + i, "%hhX", &macaddr[j]) <= 0) ++ return -EINVAL; ++ } ++ ++ spin_lock_bh(&ab->base_lock); ++ list_for_each_entry(nrp, &ab->neighbor_peers, list) { ++ if (ether_addr_equal(macaddr, nrp->addr)) { ++ reinit_completion(&nrp->filter_done); ++ nrp->vdev_id = vdev_id; ++ nrp->is_filter_on = false; ++ break; ++ } ++ } ++ spin_unlock_bh(&ab->base_lock); ++ ++ peer_param.vdev_id = nrp->vdev_id; ++ peer_param.peer_addr = nrp->addr; ++ peer_param.peer_type = WMI_PEER_TYPE_DEFAULT; ++ ++ if (!ath12k_peer_create(ar, arvif, NULL, &peer_param)) { ++ spin_lock_bh(&ab->base_lock); ++ list_for_each_entry_safe(nrp, tmp, &ab->neighbor_peers, list) { ++ if (ether_addr_equal(nrp->addr, peer_param.peer_addr)) { ++ nrp_found = true; ++ break; ++ } ++ } ++ spin_unlock_bh(&ab->base_lock); ++ ++ if (nrp_found) { ++ spin_lock_bh(&ab->base_lock); ++ nrp->is_filter_on = true; ++ spin_unlock_bh(&ab->base_lock); ++ ++ wait_for_completion_interruptible_timeout(&nrp->filter_done, 5 * HZ); ++ ++ spin_lock_bh(&ab->base_lock); ++ nrp->is_filter_on = false; ++ spin_unlock_bh(&ab->base_lock); ++ ++ len = scnprintf(buf, sizeof(buf), ++ "Neighbor Peer MAC\t\tRSSI\t\tTime\n"); ++ len += scnprintf(buf + len, sizeof(buf) - len, "%pM\t\t%u\t\t%lld\n", ++ nrp->addr, nrp->rssi, nrp->timestamp); ++ } else { ++ ath12k_peer_delete(ar, vdev_id, macaddr); ++ ath12k_warn(ab, "%pM not found in nrp list\n", macaddr); ++ return -EINVAL; ++ } ++ ath12k_peer_delete(ar, vdev_id, macaddr); ++ } else { ++ ath12k_warn(ab, "unable to create peer for nrp[%pM]\n", macaddr); ++ return -EINVAL; ++ } ++ ++ return simple_read_from_buffer(ubuf, count, ppos, buf, len); ++} ++ ++static const struct file_operations fops_read_nrp_rssi = { ++ .read = ath12k_read_nrp_rssi, ++ .open = simple_open, ++}; ++ ++static ssize_t ath12k_write_nrp_mac(struct file *file, ++ const char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ struct ath12k_base *ab = ar->ab; ++ struct ath12k_peer *peer = NULL; ++ struct ath12k_neighbor_peer *nrp = NULL, *tmp = NULL; ++ u8 mac[ETH_ALEN] = {0}; ++ char fname[MAC_UNIT_LEN * ETH_ALEN] = {0}; ++ char *str = NULL; ++ char *buf = vmalloc(count); ++ char *ptr = buf; ++ int i = 0; ++ int j = 0; ++ int ret = count; ++ int action = 0; ++ ssize_t rc = 0; ++ bool del_nrp = false; ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ rc = simple_write_to_buffer(buf, count, ppos, ubuf, count); ++ if (rc <= 0) ++ goto exit; ++ ++ /* To remove '\n' at end of buffer */ ++ buf[count - 1] = '\0'; ++ ++ if (ar->state != ATH12K_STATE_ON) { ++ ret = -ENETDOWN; ++ goto exit; ++ } ++ ++ str = strsep(&buf, ","); ++ if (!strcmp(str, "add")) ++ action = NRP_ACTION_ADD; ++ else if (!strcmp(str, "del")) ++ action = NRP_ACTION_DEL; ++ else { ++ ath12k_err(ab, "error: invalid argument\n"); ++ goto exit; ++ } ++ ++ memset(mac, 0, sizeof(mac)); ++ while ((str = strsep(&buf, ":")) != NULL) { ++ if (i >= ETH_ALEN || kstrtou8(str, 16, mac + i)) { ++ ath12k_warn(ab, "error: invalid mac address\n"); ++ goto exit; ++ } ++ i++; ++ } ++ ++ if (i != ETH_ALEN) { ++ ath12k_warn(ab, "error: invalid mac address\n"); ++ goto exit; ++ } ++ ++ if (!is_valid_ether_addr(mac)) { ++ ath12k_err(ab, "error: invalid mac address\n"); ++ goto exit; ++ } ++ ++ for (i = 0, j = 0; i < (MAC_UNIT_LEN * ETH_ALEN); i += MAC_UNIT_LEN, j++) { ++ if (j == ETH_ALEN - 1) { ++ snprintf(fname + i, sizeof(fname) - i, "%02x", mac[j]); ++ break; ++ } ++ snprintf(fname + i, sizeof(fname) - i, "%02x:", mac[j]); ++ } ++ ++ switch (action) { ++ case NRP_ACTION_ADD: ++ if (ab->num_nrps == (ATH12K_MAX_NRPS - 1)) { ++ ath12k_warn(ab, "max nrp reached, cannot create more\n"); ++ goto exit; ++ } ++ ++ list_for_each_entry(nrp, &ab->neighbor_peers, list) { ++ if (ether_addr_equal(nrp->addr, mac)) { ++ ath12k_warn(ab, "cannot add existing neighbor peer\n"); ++ goto exit; ++ } ++ } ++ ++ spin_lock_bh(&ab->base_lock); ++ peer = ath12k_peer_find_by_addr(ab, mac); ++ if (peer) { ++ ath12k_warn(ab, "cannot add exisitng peer [%pM] as nrp\n", mac); ++ spin_unlock_bh(&ab->base_lock); ++ goto exit; ++ } ++ spin_unlock_bh(&ab->base_lock); ++ ++ nrp = kzalloc(sizeof(*nrp), GFP_KERNEL); ++ if (!nrp) ++ goto exit; ++ ++ init_completion(&nrp->filter_done); ++ ether_addr_copy(nrp->addr, mac); ++ ++ spin_lock_bh(&ab->base_lock); ++ list_add_tail(&nrp->list, &ab->neighbor_peers); ++ spin_unlock_bh(&ab->base_lock); ++ ++ if (!ab->num_nrps) { ++ ar->debug.debugfs_nrp = debugfs_create_dir("nrp_rssi", ++ ar->debug.debugfs_pdev); ++ ath12k_reset_nrp_filter(ar, false); ++ } ++ spin_lock_bh(&ab->base_lock); ++ ab->num_nrps++; ++ spin_unlock_bh(&ab->base_lock); ++ ++ debugfs_create_file(fname, 0644, ++ ar->debug.debugfs_nrp, ar, ++ &fops_read_nrp_rssi); ++ break; ++ case NRP_ACTION_DEL: ++ if (!ar->ab->num_nrps) { ++ ath12k_err(ab, "error: no nac added\n"); ++ goto exit; ++ } ++ ++ spin_lock_bh(&ab->base_lock); ++ list_for_each_entry_safe(nrp, tmp, &ab->neighbor_peers, list) { ++ if (ether_addr_equal(nrp->addr, mac)) { ++ list_del(&nrp->list); ++ kfree(nrp); ++ del_nrp = true; ++ break; ++ } ++ } ++ spin_unlock_bh(&ab->base_lock); ++ ++ if (!del_nrp) ++ ath12k_warn(ab, "cannot delete %pM not added to list\n", mac); ++ else ++ ath12k_debugfs_nrp_clean(ar, mac); ++ break; ++ default: ++ break; ++ } ++exit: ++ mutex_unlock(&ar->conf_mutex); ++ ++ vfree(ptr); ++ return ret; ++} ++ ++static const struct file_operations fops_write_nrp_mac = { ++ .write = ath12k_write_nrp_mac, ++ .open = simple_open, ++}; ++ + static int ath12k_fill_bp_stats(struct ath12k_base *ab, + struct ath12k_bp_stats *bp_stats, + char *buf, int len, int size) +@@ -2891,6 +3236,9 @@ int ath12k_debugfs_register(struct ath12k *ar) + + init_completion(&ar->tpc_complete); + ++ debugfs_create_file("neighbor_peer", 0644, ++ ar->debug.debugfs_pdev, ar, ++ &fops_write_nrp_mac); + debugfs_create_file("ext_tx_stats", 0644, + ar->debug.debugfs_pdev, ar, + &fops_extd_tx_stats); +diff --git a/drivers/net/wireless/ath/ath12k/debugfs.h b/drivers/net/wireless/ath/ath12k/debugfs.h +index 6cf1e58..7273deb 100644 +--- a/drivers/net/wireless/ath/ath12k/debugfs.h ++++ b/drivers/net/wireless/ath/ath12k/debugfs.h +@@ -14,6 +14,9 @@ + + #define ATH12K_DRV_TX_STATS_SIZE 1024 + ++#define ATH12K_MAX_NRPS 7 ++#define MAC_UNIT_LEN 3 ++ + /* htt_dbg_ext_stats_type */ + enum ath12k_dbg_htt_ext_stats_type { + ATH12K_DBG_HTT_EXT_STATS_RESET = 0, +@@ -211,6 +214,22 @@ enum ath12k_dbg_aggr_mode { + ATH12K_DBG_AGGR_MODE_MAX, + }; + ++enum { ++ NRP_ACTION_ADD, ++ NRP_ACTION_DEL, ++}; ++ ++struct ath12k_neighbor_peer { ++ struct list_head list; ++ struct completion filter_done; ++ bool is_filter_on; ++ int vdev_id; ++ u8 addr[ETH_ALEN]; ++ u8 rssi; ++ s64 timestamp; ++ bool rssi_valid; ++}; ++ + void ath12k_wmi_crl_path_stats_list_free(struct ath12k *ar, struct list_head *head); + + #ifdef CPTCFG_ATH12K_DEBUGFS +@@ -227,6 +246,9 @@ void ath12k_debugfs_fw_stats_process(struct ath12k *ar, + + void ath12k_debugfs_fw_stats_init(struct ath12k *ar); + ++void ath12k_debugfs_nrp_clean(struct ath12k *ar, const u8 *addr); ++void ath12k_debugfs_nrp_cleanup_all(struct ath12k *ar); ++ + static inline bool ath12k_debugfs_is_pktlog_lite_mode_enabled(struct ath12k *ar) + { + return (ar->debug.pktlog_mode == ATH12K_PKTLOG_MODE_LITE); +@@ -344,6 +366,14 @@ static inline int ath12k_debugfs_add_interface(struct ath12k_link_vif *arvif) + static inline void ath12k_debugfs_remove_interface(struct ath12k_link_vif *arvif) + { + } ++ ++static inline void ath12k_debugfs_nrp_clean(struct ath12k *ar, const u8 *addr) ++{ ++} ++ ++static inline void ath12k_debugfs_nrp_cleanup_all(struct ath12k *ar) ++{ ++} + #endif /* CPTCFG_MAC80211_DEBUGFS*/ + + #ifdef CPTCFG_ATH12K_PKTLOG +diff --git a/drivers/net/wireless/ath/ath12k/dp_mon.c b/drivers/net/wireless/ath/ath12k/dp_mon.c +index abd8ec5..0c5c074 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_mon.c ++++ b/drivers/net/wireless/ath/ath12k/dp_mon.c +@@ -3801,6 +3801,7 @@ int ath12k_dp_mon_rx_process_stats(struct ath12k *ar, int mac_id, + struct ath12k_link_sta *arsta = NULL; + struct ath12k_peer *peer; + struct sk_buff_head skb_list; ++ struct ath12k_neighbor_peer *nrp, *tmp; + u64 cookie; + int num_buffs_reaped = 0, srng_id, buf_id; + u32 hal_status, rx_buf_sz, end_reason, end_offset; +@@ -3912,6 +3913,19 @@ move_next: + rcu_read_lock(); + spin_lock_bh(&ab->base_lock); + peer = ath12k_peer_find_by_id(ab, ppdu_info->peer_id); ++ if (!list_empty(&ab->neighbor_peers)) { ++ if (peer && !peer->sta) { ++ list_for_each_entry_safe(nrp, tmp, &ab->neighbor_peers, list) { ++ if (nrp->is_filter_on && ether_addr_equal(nrp->addr, peer->addr)) { ++ nrp->rssi = ppdu_info->rssi_comb; ++ nrp->timestamp = ktime_to_ms(ktime_get_real()); ++ complete(&nrp->filter_done); ++ } ++ } ++ goto next_skb; ++ } ++ } ++ + if (!peer || !peer->sta) { + ath12k_dbg(ab, ATH12K_DBG_DATA, + "failed to find the peer with monitor peer_id %d\n", +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index 270f485..08ff4a0 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -1026,6 +1026,9 @@ void ath12k_mac_peer_cleanup_all(struct ath12k *ar) + } + spin_unlock_bh(&ab->base_lock); + ++ if (!list_empty(&ab->neighbor_peers)) ++ ath12k_debugfs_nrp_cleanup_all(ar); ++ + ar->num_peers = 0; + ar->num_stations = 0; + +@@ -6389,7 +6392,10 @@ static int ath12k_mac_station_add(struct ath12k *ar, + struct ath12k_sta *ahsta = arsta->ahsta; + struct ieee80211_sta *sta; + struct peer_create_params peer_param = {0}; ++ struct ath12k_neighbor_peer *nrp, *tmp; ++ int nvdev_id; + int ret; ++ bool del_nrp = false; + + lockdep_assert_held(&ar->conf_mutex); + +@@ -6416,6 +6422,32 @@ static int ath12k_mac_station_add(struct ath12k *ar, + peer_param.peer_type = WMI_PEER_TYPE_DEFAULT; + peer_param.ml_enabled = sta->mlo; + ++ /* ++ * When the neighbor peer associates with this AP and successfully ++ * becomes a station, check and clear the corresponding MAC from ++ * NRP list and failing to do so would inadvertently cause the ++ * STA association(peer creation for STA) to fail due to the NRP ++ * having created a peer already for the same MAC address ++ */ ++ if (!list_empty(&ab->neighbor_peers)) { ++ spin_lock_bh(&ab->base_lock); ++ list_for_each_entry_safe(nrp, tmp, &ab->neighbor_peers, list) { ++ if (ether_addr_equal(nrp->addr, arsta->addr)) { ++ nvdev_id = nrp->vdev_id; ++ list_del(&nrp->list); ++ kfree(nrp); ++ del_nrp = true; ++ break; ++ } ++ } ++ spin_unlock_bh(&ab->base_lock); ++ ++ if (del_nrp) { ++ ath12k_peer_delete(ar, nvdev_id, arsta->addr); ++ ath12k_debugfs_nrp_clean(ar, arsta->addr); ++ } ++ } ++ + ret = ath12k_peer_create(ar, arvif, sta, &peer_param); + if (ret) { + ath12k_warn(ab, "Failed to add peer: %pM for VDEV: %d\n", +@@ -8738,6 +8770,9 @@ static void ath12k_mac_radio_stop(struct ath12k *ar) + } + spin_unlock_bh(&ar->data_lock); + ++ if (!list_empty(&ab->neighbor_peers)) ++ ath12k_debugfs_nrp_cleanup_all(ar); ++ + rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], NULL); + + synchronize_rcu(); +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/715-01-wifi-ath12k-remove-the-local-rx_desc.patch b/feeds/ipq95xx/mac80211/patches/qca/715-01-wifi-ath12k-remove-the-local-rx_desc.patch new file mode 100644 index 000000000..21173328c --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/715-01-wifi-ath12k-remove-the-local-rx_desc.patch @@ -0,0 +1,472 @@ +From 89fb0526749002be7e04f43a52f1c5e8fe97ad5c Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Fri, 10 Feb 2023 12:22:22 +0530 +Subject: [PATCH 1/4] wifi: ath12k: remove the local rx_desc + +Also moved the ppdu handler before mpdu handler. +Since after undecap we should not access the hal_rx_desc since +its overwritten by undecap handler. +Introduce rx information structure to prefetch the information +from the hal rx descriptor to avoid access the hal rx dscriptor +access from skb after the undecap handler, since the undecap handler +overwrite make it invalid data. + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/dp_rx.c | 160 +++++++++++++----------- + drivers/net/wireless/ath/ath12k/dp_rx.h | 15 ++- + drivers/net/wireless/ath/ath12k/hal.c | 2 +- + 3 files changed, 99 insertions(+), 78 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -235,12 +235,6 @@ static void ath12k_dp_rx_desc_get_crypto + ab->hw_params->hal_ops->rx_desc_get_crypto_header(desc, crypto_hdr, enctype); + } + +-static u16 ath12k_dp_rxdesc_get_mpdu_frame_ctrl(struct ath12k_base *ab, +- struct hal_rx_desc *desc) +-{ +- return ab->hw_params->hal_ops->rx_desc_get_mpdu_frame_ctl(desc); +-} +- + static inline u8 ath12k_dp_rx_h_msdu_end_ip_valid(struct ath12k_base *ab, + struct hal_rx_desc *desc) + { +@@ -2456,11 +2450,10 @@ static void ath12k_get_dot11_hdr_from_rx + struct hal_rx_desc *rx_desc = rxcb->rx_desc; + struct ath12k_base *ab = ar->ab; + size_t hdr_len, crypto_len; +- struct ieee80211_hdr *hdr; ++ struct ieee80211_hdr hdr; + u16 qos_ctl = 0; +- __le16 fc; + int expand_by; +- u8 *crypto_hdr; ++ u8 *crypto_hdr, mesh_ctrl; + + if (!(status->flag & RX_FLAG_IV_STRIPPED)) { + crypto_len = ath12k_dp_rx_crypto_param_len(ar, enctype); +@@ -2473,27 +2466,28 @@ static void ath12k_get_dot11_hdr_from_rx + ath12k_dp_rx_desc_get_crypto_header(ab, rx_desc, crypto_hdr, enctype); + } + +- fc = cpu_to_le16(ath12k_dp_rxdesc_get_mpdu_frame_ctrl(ab, rx_desc)); +- hdr_len = ieee80211_hdrlen(fc); ++ /* Get wifi header from rx_desc */ ++ ath12k_dp_rx_desc_get_dot11_hdr(ab, rx_desc, &hdr); ++ ++ hdr_len = ieee80211_hdrlen(hdr.frame_control); + if (skb_headroom(msdu) < hdr_len) { + expand_by = hdr_len - skb_headroom(msdu); + if (WARN_ON_ONCE(pskb_expand_head(msdu, expand_by, 0, GFP_ATOMIC))) + return; + } +- skb_push(msdu, hdr_len); +- hdr = (struct ieee80211_hdr *)msdu->data; +- hdr->frame_control = fc; + +- /* Get wifi header from rx_desc */ +- ath12k_dp_rx_desc_get_dot11_hdr(ab, rx_desc, hdr); ++ mesh_ctrl = ath12k_dp_rx_h_mesh_ctl_present(ab, rx_desc); ++ ++ skb_push(msdu, hdr_len); ++ memcpy(msdu->data, &hdr, min(hdr_len, sizeof(hdr))); + + if (rxcb->is_mcbc) + status->flag &= ~RX_FLAG_PN_VALIDATED; + + /* Add QOS header */ +- if (ieee80211_is_data_qos(hdr->frame_control)) { ++ if (ieee80211_is_data_qos(hdr.frame_control)) { + qos_ctl = rxcb->tid; +- if (ath12k_dp_rx_h_mesh_ctl_present(ab, rx_desc)) ++ if (mesh_ctrl) + qos_ctl |= IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT; + + /* TODO Add other QoS ctl fields when required */ +@@ -2656,7 +2650,7 @@ static bool ath12k_dp_rx_check_fast_rx(s + static void ath12k_dp_rx_h_mpdu(struct ath12k *ar, + struct sk_buff *msdu, + struct hal_rx_desc *rx_desc, +- struct ieee80211_rx_status *rx_status, ++ struct ath12k_dp_rx_info *rx_info, + bool *fast_rx) + { + bool fill_crypto_hdr; +@@ -2666,6 +2660,7 @@ static void ath12k_dp_rx_h_mpdu(struct a + bool is_decrypted = false; + struct ieee80211_hdr *hdr; + struct ath12k_peer *peer; ++ struct ieee80211_rx_status *rx_status = rx_info->rx_status; + u32 err_bitmap; + #ifdef CPTCFG_MAC80211_PPE_SUPPORT + u32 vp; +@@ -2753,8 +2748,7 @@ static void ath12k_dp_rx_h_mpdu(struct a + if (!is_decrypted || fill_crypto_hdr) + return; + +- if (ath12k_dp_rx_h_decap_type(ar->ab, rx_desc) != +- DP_RX_DECAP_TYPE_ETHERNET2_DIX) { ++ if (rx_info->decap_type != DP_RX_DECAP_TYPE_ETHERNET2_DIX) { + hdr = (void *)msdu->data; + hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED); + } +@@ -2843,10 +2837,19 @@ static void ath12k_dp_rx_h_rate(struct a + } + } + ++static void ath12k_dp_rx_h_fetch_info(struct ath12k_base *ab, ++ struct hal_rx_desc *rx_desc, ++ struct ath12k_dp_rx_info *rx_info) ++{ ++ rx_info->decap_type = ath12k_dp_rx_h_decap_type(ab, rx_desc); ++ rx_info->filled |= BIT_ULL(ATH12K_RX_INFO_DECAP_TYPE); ++} ++ + void ath12k_dp_rx_h_ppdu(struct ath12k *ar, struct hal_rx_desc *rx_desc, +- struct ieee80211_rx_status *rx_status) ++ struct ath12k_dp_rx_info *rx_info) + { + struct ath12k_base *ab = ar->ab; ++ struct ieee80211_rx_status *rx_status = rx_info->rx_status; + u8 channel_num; + u32 center_freq, meta_data; + struct ieee80211_channel *channel; +@@ -3012,22 +3015,18 @@ static bool ath12k_dp_rx_check_max_nwifi + struct hal_rx_desc *rx_desc, + struct sk_buff *msdu) + { +- u8 decap_type; + struct ieee80211_hdr *hdr; + u32 hdr_len; + +- decap_type = ath12k_dp_rx_h_decap_type(ab, rx_desc); +- if (decap_type == DP_RX_DECAP_TYPE_NATIVE_WIFI) { +- hdr = (struct ieee80211_hdr *)msdu->data; +- hdr_len = ieee80211_hdrlen(hdr->frame_control); +- if (unlikely(hdr_len > DP_MAX_NWIFI_HDR_LEN)) { +- ab->soc_stats.invalid_rbm++; +- ath12k_dbg_dump(ab, ATH12K_DBG_DATA, NULL, "msdu_data", +- msdu->data, msdu->len); +- ath12k_dbg_dump(ab, ATH12K_DBG_DATA, NULL, "rx_desc", +- rx_desc, sizeof(*rx_desc)); +- return true; +- } ++ hdr = (struct ieee80211_hdr *)msdu->data; ++ hdr_len = ieee80211_hdrlen(hdr->frame_control); ++ if (unlikely(hdr_len > DP_MAX_NWIFI_HDR_LEN)) { ++ ab->soc_stats.invalid_rbm++; ++ ath12k_dbg_dump(ab, ATH12K_DBG_DATA, NULL, "msdu_data", ++ msdu->data, msdu->len); ++ ath12k_dbg_dump(ab, ATH12K_DBG_DATA, NULL, "rx_desc", ++ rx_desc, sizeof(*rx_desc)); ++ return true; + } + + return false; +@@ -3036,12 +3035,11 @@ static bool ath12k_dp_rx_check_max_nwifi + static int ath12k_dp_rx_process_msdu(struct ath12k *ar, + struct sk_buff *msdu, + struct sk_buff_head *msdu_list, +- struct ieee80211_rx_status *rx_status, +- struct hal_rx_desc *rx_desc, ++ struct ath12k_dp_rx_info *rx_info, + bool *fast_rx) + { + struct ath12k_base *ab = ar->ab; +- struct hal_rx_desc *lrx_desc; ++ struct hal_rx_desc *rx_desc, *lrx_desc; + struct ath12k_skb_rxcb *rxcb; + struct sk_buff *last_buf; + u8 l3_pad_bytes; +@@ -3057,12 +3055,7 @@ static int ath12k_dp_rx_process_msdu(str + goto free_out; + } + +- /* +- * Store the hal_rx_desc into a local structure, +- * further skb_push's will modify the headroom(rx_desc) in +- * undecap +- */ +- *rx_desc = *(struct hal_rx_desc *)msdu->data; ++ rx_desc = (struct hal_rx_desc *)msdu->data; + lrx_desc = (struct hal_rx_desc *)last_buf->data; + if (!ath12k_dp_rx_h_msdu_done(ab, lrx_desc)) { + ath12k_warn(ab, "msdu_done bit in msdu_end is not set\n"); +@@ -3098,18 +3091,21 @@ static int ath12k_dp_rx_process_msdu(str + } + } + +- if (ath12k_dp_rx_check_max_nwifi_hdr_len(ab, rx_desc, msdu)) { ++ ath12k_dp_rx_h_fetch_info(ab, rx_desc, rx_info); ++ ++ if (rx_info->decap_type == DP_RX_DECAP_TYPE_NATIVE_WIFI && ++ ath12k_dp_rx_check_max_nwifi_hdr_len(ab, rx_desc, msdu)) { + ret = -EINVAL; + goto free_out; + } + +- ath12k_dp_rx_h_mpdu(ar, msdu, rx_desc, rx_status, fast_rx); ++ ath12k_dp_rx_h_mpdu(ar, msdu, rx_desc, rx_info, fast_rx); + if (*fast_rx) + return 0; + +- ath12k_dp_rx_h_ppdu(ar, rx_desc, rx_status); ++ ath12k_dp_rx_h_ppdu(ar, rx_desc, rx_info); + +- rx_status->flag |= RX_FLAG_SKIP_MONITOR | RX_FLAG_DUP_VALIDATED; ++ rx_info->rx_status->flag |= RX_FLAG_SKIP_MONITOR | RX_FLAG_DUP_VALIDATED; + + return 0; + +@@ -3124,6 +3120,7 @@ static void ath12k_dp_rx_process_receive + { + struct ieee80211_rx_status rx_status = {0}; + struct ath12k_skb_rxcb *rxcb; ++ struct ath12k_dp_rx_info rx_info; + struct sk_buff *msdu; + struct ath12k *ar; + u8 mac_id, hw_link_id; +@@ -3133,11 +3130,12 @@ static void ath12k_dp_rx_process_receive + if (skb_queue_empty(msdu_list)) + return; + ++ rx_info.filled = 0; ++ rx_info.rx_status = &rx_status; ++ + rcu_read_lock(); + + while ((msdu = __skb_dequeue(msdu_list))) { +- struct hal_rx_desc rx_desc = {0}; +- + rxcb = ATH12K_SKB_RXCB(msdu); + /* Enable fast rx by default, the value will cahnge based on peer cap + * and packet type */ +@@ -3169,8 +3167,8 @@ static void ath12k_dp_rx_process_receive + continue; + } + +- ret = ath12k_dp_rx_process_msdu(ar, msdu, msdu_list, &rx_status, +- &rx_desc, &fast_rx); ++ ret = ath12k_dp_rx_process_msdu(ar, msdu, msdu_list, &rx_info, ++ &fast_rx); + if (ret) { + ath12k_dbg(ab, ATH12K_DBG_DATA, + "Unable to process %s chip_id %d msdu %d", +@@ -3478,6 +3476,7 @@ static int ath12k_dp_rx_h_verify_tkip_mi + struct ieee80211_key_conf *key_conf; + struct ieee80211_hdr *hdr; + u8 mic[IEEE80211_CCMP_MIC_LEN]; ++ struct ath12k_dp_rx_info rx_info; + int head_len, tail_len, ret; + size_t data_len; + u32 hdr_len, hal_rx_desc_sz = ar->ab->hw_params->hal_desc_sz; +@@ -3487,6 +3486,9 @@ static int ath12k_dp_rx_h_verify_tkip_mi + if (ath12k_dp_rx_h_enctype(ab, rx_desc) != HAL_ENCRYPT_TYPE_TKIP_MIC) + return 0; + ++ rx_info.filled = 0; ++ rx_info.rx_status = &rxs; ++ + hdr = (struct ieee80211_hdr *)(msdu->data + hal_rx_desc_sz); + hdr_len = ieee80211_hdrlen(hdr->frame_control); + head_len = hdr_len + hal_rx_desc_sz + IEEE80211_TKIP_IV_LEN; +@@ -3517,7 +3519,7 @@ mic_fail: + RX_FLAG_IV_STRIPPED | RX_FLAG_DECRYPTED; + skb_pull(msdu, hal_rx_desc_sz); + +- ath12k_dp_rx_h_ppdu(ar, rx_desc, rxs); ++ ath12k_dp_rx_h_ppdu(ar, rx_desc, &rx_info); + ath12k_dp_rx_h_undecap(ar, msdu, rx_desc, + HAL_ENCRYPT_TYPE_TKIP_MIC, rxs, true); + ieee80211_rx(ar->ah->hw, msdu); +@@ -4176,7 +4178,7 @@ static void ath12k_dp_rx_null_q_desc_sg_ + } + + static int ath12k_dp_rx_h_null_q_desc(struct ath12k *ar, struct sk_buff *msdu, +- struct ieee80211_rx_status *status, ++ struct ath12k_dp_rx_info *rx_info, + struct sk_buff_head *msdu_list) + { + struct ath12k_base *ab = ar->ab; +@@ -4233,12 +4235,16 @@ static int ath12k_dp_rx_h_null_q_desc(st + skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len); + skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes); + } +- if (ath12k_dp_rx_check_max_nwifi_hdr_len(ab, desc, msdu)) ++ ++ ath12k_dp_rx_h_fetch_info(ab, desc, rx_info); ++ ++ if (rx_info->decap_type == DP_RX_DECAP_TYPE_NATIVE_WIFI && ++ ath12k_dp_rx_check_max_nwifi_hdr_len(ab, desc, msdu)) + return -EINVAL; + +- ath12k_dp_rx_h_ppdu(ar, desc, status); ++ ath12k_dp_rx_h_ppdu(ar, desc, rx_info); + fast_rx = false; +- ath12k_dp_rx_h_mpdu(ar, msdu, desc, status, &fast_rx); ++ ath12k_dp_rx_h_mpdu(ar, msdu, desc, rx_info, &fast_rx); + + rxcb->tid = ath12k_dp_rx_h_tid(ab, desc); + +@@ -4262,7 +4268,7 @@ static int ath12k_dp_rx_h_null_q_desc(st + } + + static bool ath12k_dp_rx_h_reo_err(struct ath12k *ar, struct sk_buff *msdu, +- struct ieee80211_rx_status *status, ++ struct ath12k_dp_rx_info *rx_info, + struct sk_buff_head *msdu_list) + { + struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu); +@@ -4270,7 +4276,7 @@ static bool ath12k_dp_rx_h_reo_err(struc + + switch (rxcb->err_code) { + case HAL_REO_DEST_RING_ERROR_CODE_DESC_ADDR_ZERO: +- if (ath12k_dp_rx_h_null_q_desc(ar, msdu, status, msdu_list)) ++ if (ath12k_dp_rx_h_null_q_desc(ar, msdu, rx_info, msdu_list)) + drop = true; + break; + case HAL_REO_DEST_RING_ERROR_CODE_PN_CHECK_FAILED: +@@ -4296,7 +4302,7 @@ static bool ath12k_dp_rx_h_reo_err(struc + } + + static bool ath12k_dp_rx_h_tkip_mic_err(struct ath12k *ar, struct sk_buff *msdu, +- struct ieee80211_rx_status *status) ++ struct ath12k_dp_rx_info *rx_info) + { + struct ath12k_base *ab = ar->ab; + u16 msdu_len; +@@ -4321,18 +4327,19 @@ static bool ath12k_dp_rx_h_tkip_mic_err( + skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len); + skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes); + +- ath12k_dp_rx_h_ppdu(ar, desc, status); ++ ath12k_dp_rx_h_ppdu(ar, desc, rx_info); + +- status->flag |= (RX_FLAG_MMIC_STRIPPED | RX_FLAG_MMIC_ERROR | +- RX_FLAG_DECRYPTED); ++ rx_info->rx_status->flag |= (RX_FLAG_MMIC_STRIPPED | RX_FLAG_MMIC_ERROR | ++ RX_FLAG_DECRYPTED); + + ath12k_dp_rx_h_undecap(ar, msdu, desc, +- HAL_ENCRYPT_TYPE_TKIP_MIC, status, false); ++ HAL_ENCRYPT_TYPE_TKIP_MIC, rx_info->rx_status, false); + return false; + } + +-static bool ath12k_dp_rx_h_4addr_null_frame_handler(struct ath12k *ar, struct sk_buff *msdu, +- struct ieee80211_rx_status *status) ++static bool ath12k_dp_rx_h_4addr_null_frame_handler(struct ath12k *ar, ++ struct sk_buff *msdu, ++ struct ath12k_dp_rx_info *rx_info) + { + struct ath12k_base *ab = ar->ab; + u16 msdu_len, peer_id; +@@ -4362,12 +4369,13 @@ static bool ath12k_dp_rx_h_4addr_null_fr + skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len); + skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes); + +- if (ath12k_dp_rx_check_max_nwifi_hdr_len(ab, rx_desc, msdu)) ++ if (rx_info->decap_type == DP_RX_DECAP_TYPE_NATIVE_WIFI && ++ ath12k_dp_rx_check_max_nwifi_hdr_len(ab, rx_desc, msdu)) + return true; + +- ath12k_dp_rx_h_ppdu(ar, rx_desc, status); ++ ath12k_dp_rx_h_ppdu(ar, rx_desc, rx_info); + +- ath12k_dp_rx_h_mpdu(ar, msdu, rx_desc, status, &fast_rx); ++ ath12k_dp_rx_h_mpdu(ar, msdu, rx_desc, rx_info, &fast_rx); + + rxcb->tid = ath12k_dp_rx_h_tid(ab, rx_desc); + +@@ -4382,7 +4390,7 @@ static bool ath12k_dp_rx_h_4addr_null_fr + return drop; + } + static bool ath12k_dp_rx_h_rxdma_err(struct ath12k *ar, struct sk_buff *msdu, +- struct ieee80211_rx_status *status) ++ struct ath12k_dp_rx_info *rx_info) + { + struct ath12k_base *ab = ar->ab; + struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu); +@@ -4392,13 +4400,15 @@ static bool ath12k_dp_rx_h_rxdma_err(str + + switch (rxcb->err_code) { + case HAL_REO_ENTR_RING_RXDMA_ECODE_UNAUTH_WDS_ERR: +- drop = ath12k_dp_rx_h_4addr_null_frame_handler(ar, msdu, status); ++ ath12k_dp_rx_h_fetch_info(ab, rx_desc, rx_info); ++ ++ drop = ath12k_dp_rx_h_4addr_null_frame_handler(ar, msdu, rx_info); + break; + case HAL_REO_ENTR_RING_RXDMA_ECODE_DECRYPT_ERR: + case HAL_REO_ENTR_RING_RXDMA_ECODE_TKIP_MIC_ERR: + err_bitmap = ath12k_dp_rx_h_mpdu_err(ab, rx_desc); + if (err_bitmap & HAL_RX_MPDU_ERR_TKIP_MIC) { +- drop = ath12k_dp_rx_h_tkip_mic_err(ar, msdu, status); ++ drop = ath12k_dp_rx_h_tkip_mic_err(ar, msdu, rx_info); + break; + } + fallthrough; +@@ -4425,14 +4435,18 @@ static void ath12k_dp_rx_wbm_err(struct + { + struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu); + struct ieee80211_rx_status rxs = {0}; ++ struct ath12k_dp_rx_info rx_info; + bool drop = true; + ++ rx_info.filled = 0; ++ rx_info.rx_status = &rxs; ++ + switch (rxcb->err_rel_src) { + case HAL_WBM_REL_SRC_MODULE_REO: +- drop = ath12k_dp_rx_h_reo_err(ar, msdu, &rxs, msdu_list); ++ drop = ath12k_dp_rx_h_reo_err(ar, msdu, &rx_info, msdu_list); + break; + case HAL_WBM_REL_SRC_MODULE_RXDMA: +- drop = ath12k_dp_rx_h_rxdma_err(ar, msdu, &rxs); ++ drop = ath12k_dp_rx_h_rxdma_err(ar, msdu, &rx_info); + break; + default: + /* msdu will get freed */ +--- a/drivers/net/wireless/ath/ath12k/dp_rx.h ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.h +@@ -66,6 +66,19 @@ struct ath12k_dp_rx_rfc1042_hdr { + __be16 snap_type; + } __packed; + ++enum ath12k_dp_rx_info_type { ++ ATH12K_RX_INFO_DECAP_TYPE, ++ ++ /* keep last */ ++ ATH12K_RX_INFO_MAX ++}; ++ ++struct ath12k_dp_rx_info { ++ u64 filled; ++ u8 decap_type; ++ struct ieee80211_rx_status *rx_status; ++}; ++ + static inline u32 ath12k_he_gi_to_nl80211_he_gi(u8 sgi) + { + u32 ret = 0; +@@ -143,7 +156,7 @@ u8 ath12k_dp_rx_h_decap_type(struct ath1 + u32 ath12k_dp_rx_h_mpdu_err(struct ath12k_base *ab, + struct hal_rx_desc *desc); + void ath12k_dp_rx_h_ppdu(struct ath12k *ar, struct hal_rx_desc *rx_desc, +- struct ieee80211_rx_status *rx_status); ++ struct ath12k_dp_rx_info *rx_info); + struct ath12k_peer * + ath12k_dp_rx_h_find_peer(struct ath12k_base *ab, struct sk_buff *msdu); + #endif /* ATH12K_DP_RX_H */ +--- a/drivers/net/wireless/ath/ath12k/hal.c ++++ b/drivers/net/wireless/ath/ath12k/hal.c +@@ -418,7 +418,7 @@ static void ath12k_hw_qcn9274_rx_desc_ge + ether_addr_copy(hdr->addr2, desc->u.qcn9274.mpdu_start.addr2); + ether_addr_copy(hdr->addr3, desc->u.qcn9274.mpdu_start.addr3); + if (__le32_to_cpu(desc->u.qcn9274.mpdu_start.info4) & +- RX_MPDU_START_INFO4_MAC_ADDR4_VALID) { ++ RX_MPDU_START_INFO4_MAC_ADDR4_VALID) { + ether_addr_copy(hdr->addr4, desc->u.qcn9274.mpdu_start.addr4); + } + hdr->seq_ctrl = desc->u.qcn9274.mpdu_start.seq_ctrl; diff --git a/feeds/ipq95xx/mac80211/patches/qca/715-02-wifi-ath12k-avoid-hal-rx-descriptor-access-in-ath12k.patch b/feeds/ipq95xx/mac80211/patches/qca/715-02-wifi-ath12k-avoid-hal-rx-descriptor-access-in-ath12k.patch new file mode 100644 index 000000000..e00ffbaa2 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/715-02-wifi-ath12k-avoid-hal-rx-descriptor-access-in-ath12k.patch @@ -0,0 +1,254 @@ +From 11cd3fa507873a97437033356c477e594fd8fd62 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Sun, 12 Feb 2023 16:34:10 +0530 +Subject: [PATCH 2/4] wifi: ath12k: avoid hal rx descriptor access in + ath12k_dp_rx_h_find_peer + +After undecap, hal rx descriptor data invalid. so avoid access +by prefetch the required data in rx_info which is used by +ath12k_dp_rx_h_find_peer + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/dp_mon.c | 12 ++-- + drivers/net/wireless/ath/ath12k/dp_rx.c | 71 ++++++++++++++++++------ + drivers/net/wireless/ath/ath12k/dp_rx.h | 7 ++- + 3 files changed, 65 insertions(+), 25 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/dp_mon.c ++++ b/drivers/net/wireless/ath/ath12k/dp_mon.c +@@ -2140,14 +2140,14 @@ static void ath12k_dp_mon_update_radiota + static void ath12k_dp_mon_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *napi, + struct sk_buff *msdu, u32 mpdu_idx, + struct hal_rx_mon_ppdu_info *ppduinfo, +- struct ieee80211_rx_status *status) ++ struct ath12k_dp_rx_info *rx_info) + { + static const struct ieee80211_radiotap_he known = { + .data1 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN | + IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN), + .data2 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN), + }; +- struct ieee80211_rx_status *rx_status; ++ struct ieee80211_rx_status *rx_status, *status = rx_info->rx_status; + struct ieee80211_radiotap_he *he = NULL; + struct ieee80211_sta *pubsta = NULL; + struct ath12k_peer *peer; +@@ -2166,7 +2166,7 @@ static void ath12k_dp_mon_rx_deliver_msd + if (!(status->flag & RX_FLAG_ONLY_MONITOR)) + decap = ppduinfo->cmn_mpdu_info.mon_mpdu[mpdu_idx].msdu_info[0].decap_format; + spin_lock_bh(&ar->ab->base_lock); +- peer = ath12k_dp_rx_h_find_peer(ar->ab, msdu); ++ peer = ath12k_dp_rx_h_find_peer(ar->ab, msdu, rx_info); + if (peer && peer->sta) { + pubsta = peer->sta; + if (pubsta->valid_links) { +@@ -2227,8 +2227,12 @@ static int ath12k_dp_mon_rx_deliver(stru + struct ath12k_pdev_dp *dp = &ar->dp; + struct sk_buff *mon_skb, *skb_next, *header; + struct ieee80211_rx_status *rxs = &dp->rx_status; ++ struct ath12k_dp_rx_info rx_info; + bool fcs_err = false; + ++ rx_info.filled = 0; ++ rx_info.rx_status = rxs; ++ + mon_skb = ath12k_dp_mon_rx_merg_msdus(ar, mpdu_idx, head_msdu, + rxs, &fcs_err, ppduinfo); + if (!mon_skb) +@@ -2256,7 +2260,7 @@ static int ath12k_dp_mon_rx_deliver(stru + rxs->flag |= RX_FLAG_ONLY_MONITOR; + ath12k_dp_mon_update_radiotap(ar, ppduinfo, mon_skb, rxs); + ath12k_dp_mon_rx_deliver_msdu(ar, napi, mon_skb, mpdu_idx, +- ppduinfo, rxs); ++ ppduinfo, &rx_info); + mon_skb = skb_next; + } while (mon_skb); + rxs->flag = 0; +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -2575,7 +2575,8 @@ static void ath12k_dp_rx_h_undecap(struc + } + + struct ath12k_peer * +-ath12k_dp_rx_h_find_peer(struct ath12k_base *ab, struct sk_buff *msdu) ++ath12k_dp_rx_h_find_peer(struct ath12k_base *ab, struct sk_buff *msdu, ++ struct ath12k_dp_rx_info *rx_info) + { + struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu); + struct hal_rx_desc *rx_desc = rxcb->rx_desc; +@@ -2589,12 +2590,18 @@ ath12k_dp_rx_h_find_peer(struct ath12k_b + if (peer) + return peer; + +- if (!rx_desc || !(ath12k_dp_rxdesc_mac_addr2_valid(ab, rx_desc))) +- return NULL; +- +- peer = ath12k_peer_find_by_addr(ab, ++ if (!(rx_info->filled & BIT_ULL(ATH12K_RX_INFO_ADDR2))) { ++ if (rx_desc && ath12k_dp_rxdesc_mac_addr2_valid(ab, rx_desc)) { ++ ether_addr_copy(rx_info->addr2, + ath12k_dp_rxdesc_get_mpdu_start_addr2(ab, + rx_desc)); ++ rx_info->filled |= BIT_ULL(ATH12K_RX_INFO_ADDR2); ++ } else { ++ return NULL; ++ } ++ } ++ ++ peer = ath12k_peer_find_by_addr(ab, rx_info->addr2); + return peer; + } + +@@ -2676,7 +2683,7 @@ static void ath12k_dp_rx_h_mpdu(struct a + rxcb->peer_id = ath12k_dp_rx_h_peer_id(ar->ab, rx_desc); + + spin_lock_bh(&ar->ab->base_lock); +- peer = ath12k_dp_rx_h_find_peer(ar->ab, msdu); ++ peer = ath12k_dp_rx_h_find_peer(ar->ab, msdu, rx_info); + if (peer) { + /* If the pkt is a valid IP packet and peer supports + * fast rx, deliver directly to net, also note that +@@ -2843,6 +2850,12 @@ static void ath12k_dp_rx_h_fetch_info(st + { + rx_info->decap_type = ath12k_dp_rx_h_decap_type(ab, rx_desc); + rx_info->filled |= BIT_ULL(ATH12K_RX_INFO_DECAP_TYPE); ++ ++ if (ath12k_dp_rxdesc_mac_addr2_valid(ab, rx_desc)) { ++ ether_addr_copy(rx_info->addr2, ++ ath12k_dp_rxdesc_get_mpdu_start_addr2(ab, rx_desc)); ++ rx_info->filled |= BIT_ULL(ATH12K_RX_INFO_ADDR2); ++ } + } + + void ath12k_dp_rx_h_ppdu(struct ath12k *ar, struct hal_rx_desc *rx_desc, +@@ -2908,7 +2921,7 @@ void ath12k_dp_rx_h_ppdu(struct ath12k * + + static void ath12k_dp_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *napi, + struct sk_buff *msdu, +- struct ieee80211_rx_status *status) ++ struct ath12k_dp_rx_info *rx_info) + { + struct ath12k_base *ab = ar->ab; + static const struct ieee80211_radiotap_he known = { +@@ -2919,13 +2932,14 @@ static void ath12k_dp_rx_deliver_msdu(st + struct ieee80211_radiotap_he *he = NULL; + struct ieee80211_rx_status *rx_status; + struct ieee80211_sta *pubsta = NULL; +- struct ath12k_peer *peer; ++ struct ath12k_peer *peer = NULL; + struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu); + u8 decap = DP_RX_DECAP_TYPE_RAW; + int expand_by; + bool is_mcbc = rxcb->is_mcbc; + bool is_eapol = rxcb->is_eapol; + struct ath12k_link_sta *arsta = NULL; ++ struct ieee80211_rx_status *status = rx_info->rx_status; + + if (status->encoding == RX_ENC_HE && !(status->flag & RX_FLAG_RADIOTAP_HE) && + !(status->flag & RX_FLAG_SKIP_MONITOR)) { +@@ -2939,11 +2953,16 @@ static void ath12k_dp_rx_deliver_msdu(st + status->flag |= RX_FLAG_RADIOTAP_HE; + } + +- if (!(status->flag & RX_FLAG_ONLY_MONITOR)) +- decap = ath12k_dp_rx_h_decap_type(ab, rxcb->rx_desc); ++ if (!(status->flag & RX_FLAG_ONLY_MONITOR) && ++ rx_info->filled & BIT_ULL(ATH12K_RX_INFO_DECAP_TYPE)) ++ decap = rx_info->decap_type; + + spin_lock_bh(&ab->base_lock); +- peer = ath12k_dp_rx_h_find_peer(ab, msdu); ++ peer = ath12k_dp_rx_h_find_peer(ab, msdu, rx_info); ++ if (rxcb->peer_id) ++ peer = ath12k_peer_find_by_id(ab, rxcb->peer_id); ++ if (!peer && (rx_info->filled & BIT_ULL(ATH12K_RX_INFO_ADDR2))) ++ peer = ath12k_peer_find_by_addr(ab, rx_info->addr2); + if (peer && peer->sta) { + pubsta = peer->sta; + if (pubsta->valid_links) { +@@ -2954,13 +2973,12 @@ static void ath12k_dp_rx_deliver_msdu(st + spin_unlock_bh(&ab->base_lock); + + ath12k_dbg(ab, ATH12K_DBG_DATA, +- "rx skb %pK len %u peer %pM %d %s sn %u %s%s%s%s%s%s%s%s%s%s rate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n", ++ "rx skb %pK len %u peer %pM %d %s %s%s%s%s%s%s%s%s%s%s rate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n", + msdu, + msdu->len, + peer ? peer->addr : NULL, + rxcb->tid, + is_mcbc ? "mcast" : "ucast", +- ath12k_dp_rx_h_seq_no(ab, rxcb->rx_desc), + (status->encoding == RX_ENC_LEGACY) ? "legacy" : "", + (status->encoding == RX_ENC_HT) ? "ht" : "", + (status->encoding == RX_ENC_VHT) ? "vht" : "", +@@ -3179,7 +3197,7 @@ static void ath12k_dp_rx_process_receive + } + + if (!fast_rx) +- ath12k_dp_rx_deliver_msdu(ar, napi, msdu, &rx_status); ++ ath12k_dp_rx_deliver_msdu(ar, napi, msdu, &rx_info); + } + + rcu_read_unlock(); +@@ -3515,6 +3533,8 @@ mic_fail: + (ATH12K_SKB_RXCB(msdu))->is_first_msdu = true; + (ATH12K_SKB_RXCB(msdu))->is_last_msdu = true; + ++ ath12k_dp_rx_h_fetch_info(ab, rx_desc, &rx_info); ++ + rxs->flag |= RX_FLAG_MMIC_ERROR | RX_FLAG_MMIC_STRIPPED | + RX_FLAG_IV_STRIPPED | RX_FLAG_DECRYPTED; + skb_pull(msdu, hal_rx_desc_sz); +@@ -4408,6 +4428,8 @@ static bool ath12k_dp_rx_h_rxdma_err(str + case HAL_REO_ENTR_RING_RXDMA_ECODE_TKIP_MIC_ERR: + err_bitmap = ath12k_dp_rx_h_mpdu_err(ab, rx_desc); + if (err_bitmap & HAL_RX_MPDU_ERR_TKIP_MIC) { ++ ath12k_dp_rx_h_fetch_info(ab, rx_desc, rx_info); ++ + drop = ath12k_dp_rx_h_tkip_mic_err(ar, msdu, rx_info); + break; + } +@@ -4458,7 +4480,7 @@ static void ath12k_dp_rx_wbm_err(struct + return; + } + +- ath12k_dp_rx_deliver_msdu(ar, napi, msdu, &rxs); ++ ath12k_dp_rx_deliver_msdu(ar, napi, msdu, &rx_info); + } + + int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab, +--- a/drivers/net/wireless/ath/ath12k/dp_rx.h ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.h +@@ -68,6 +68,7 @@ struct ath12k_dp_rx_rfc1042_hdr { + + enum ath12k_dp_rx_info_type { + ATH12K_RX_INFO_DECAP_TYPE, ++ ATH12K_RX_INFO_ADDR2, + + /* keep last */ + ATH12K_RX_INFO_MAX +@@ -76,6 +77,7 @@ enum ath12k_dp_rx_info_type { + struct ath12k_dp_rx_info { + u64 filled; + u8 decap_type; ++ u8 addr2[ETH_ALEN]; + struct ieee80211_rx_status *rx_status; + }; + +@@ -150,13 +152,12 @@ int ath12k_dp_rx_pktlog_stop(struct ath1 + u8 ath12k_dp_rx_h_l3pad(struct ath12k_base *ab, + struct hal_rx_desc *desc); + struct ath12k_peer * +-ath12k_dp_rx_h_find_peer(struct ath12k_base *ab, struct sk_buff *msdu); ++ath12k_dp_rx_h_find_peer(struct ath12k_base *ab, struct sk_buff *msdu, ++ struct ath12k_dp_rx_info *rx_info); + u8 ath12k_dp_rx_h_decap_type(struct ath12k_base *ab, + struct hal_rx_desc *desc); + u32 ath12k_dp_rx_h_mpdu_err(struct ath12k_base *ab, + struct hal_rx_desc *desc); + void ath12k_dp_rx_h_ppdu(struct ath12k *ar, struct hal_rx_desc *rx_desc, + struct ath12k_dp_rx_info *rx_info); +-struct ath12k_peer * +-ath12k_dp_rx_h_find_peer(struct ath12k_base *ab, struct sk_buff *msdu); + #endif /* ATH12K_DP_RX_H */ diff --git a/feeds/ipq95xx/mac80211/patches/qca/715-03-wifi-ath12k-avoid-hal-rx-descriptor-access-in-rx-ppd.patch b/feeds/ipq95xx/mac80211/patches/qca/715-03-wifi-ath12k-avoid-hal-rx-descriptor-access-in-rx-ppd.patch new file mode 100644 index 000000000..3dcd6b238 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/715-03-wifi-ath12k-avoid-hal-rx-descriptor-access-in-rx-ppd.patch @@ -0,0 +1,213 @@ +From dfb71b79b8bcc958d3d3f3244d68cda0fc3e3c65 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Sun, 12 Feb 2023 19:28:50 +0530 +Subject: [PATCH 3/4] wifi: ath12k: avoid hal rx descriptor access in rx ppdu + and rx rate handler + +Introduce the helper function for fetch the rx info and avoid the +hal rx descriptor in pddu and rate handler. Since no need of hal_rx_desc, +removed this argument from the ppdu and rate handler. + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/dp_rx.c | 130 +++++++++++++----------- + drivers/net/wireless/ath/ath12k/dp_rx.h | 15 ++- + 2 files changed, 86 insertions(+), 59 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -2761,22 +2761,30 @@ static void ath12k_dp_rx_h_mpdu(struct a + } + } + +-static void ath12k_dp_rx_h_rate(struct ath12k *ar, struct hal_rx_desc *rx_desc, +- struct ieee80211_rx_status *rx_status) ++static void ath12k_dp_rx_h_rate(struct ath12k *ar, struct ath12k_dp_rx_info *rx_info) + { +- struct ath12k_base *ab = ar->ab; ++ struct ieee80211_rx_status *rx_status = rx_info->rx_status; + struct ieee80211_supported_band *sband; +- enum rx_msdu_start_pkt_type pkt_type; +- u8 bw; +- u8 rate_mcs, nss; +- u8 sgi; ++ enum rx_msdu_start_pkt_type pkt_type = RX_MSDU_START_PKT_TYPE_11A; ++ u8 bw = 0; ++ u8 rate_mcs = 0, nss = 0; ++ u8 sgi = 0; + bool is_cck; + +- pkt_type = ath12k_dp_rx_h_pkt_type(ab, rx_desc); +- bw = ath12k_dp_rx_h_rx_bw(ab, rx_desc); +- rate_mcs = ath12k_dp_rx_h_rate_mcs(ab, rx_desc); +- nss = ath12k_dp_rx_h_nss(ab, rx_desc); +- sgi = ath12k_dp_rx_h_sgi(ab, rx_desc); ++ if (rx_info->filled & BIT_ULL(ATH12K_RX_INFO_PKT_TYPE)) ++ pkt_type = rx_info->pkt_type; ++ ++ if (rx_info->filled & BIT_ULL(ATH12K_RX_INFO_BW)) ++ bw = rx_info->bw; ++ ++ if (rx_info->filled & BIT_ULL(ATH12K_RX_INFO_RATE_MCS)) ++ rate_mcs = rx_info->rate_mcs; ++ ++ if (rx_info->filled & BIT_ULL(ATH12K_RX_INFO_NSS)) ++ nss = rx_info->nss; ++ ++ if (rx_info->filled & BIT_ULL(ATH12K_RX_INFO_SGI)) ++ sgi = rx_info->sgi; + + switch (pkt_type) { + case RX_MSDU_START_PKT_TYPE_11A: +@@ -2851,6 +2859,24 @@ static void ath12k_dp_rx_h_fetch_info(st + rx_info->decap_type = ath12k_dp_rx_h_decap_type(ab, rx_desc); + rx_info->filled |= BIT_ULL(ATH12K_RX_INFO_DECAP_TYPE); + ++ rx_info->pkt_type = ath12k_dp_rx_h_pkt_type(ab, rx_desc); ++ rx_info->filled |= BIT_ULL(ATH12K_RX_INFO_PKT_TYPE); ++ ++ rx_info->sgi = ath12k_dp_rx_h_sgi(ab, rx_desc); ++ rx_info->filled |= BIT_ULL(ATH12K_RX_INFO_SGI); ++ ++ rx_info->rate_mcs = ath12k_dp_rx_h_rate_mcs(ab, rx_desc); ++ rx_info->filled |= BIT_ULL(ATH12K_RX_INFO_RATE_MCS); ++ ++ rx_info->bw = ath12k_dp_rx_h_rx_bw(ab, rx_desc); ++ rx_info->filled |= BIT_ULL(ATH12K_RX_INFO_BW); ++ ++ rx_info->nss = ath12k_dp_rx_h_nss(ab, rx_desc); ++ rx_info->filled |= BIT_ULL(ATH12K_RX_INFO_NSS); ++ ++ rx_info->phy_meta_data = ath12k_dp_rx_h_freq(ab, rx_desc); ++ rx_info->filled |= BIT_ULL(ATH12K_RX_INFO_PHY_META_DATA); ++ + if (ath12k_dp_rxdesc_mac_addr2_valid(ab, rx_desc)) { + ether_addr_copy(rx_info->addr2, + ath12k_dp_rxdesc_get_mpdu_start_addr2(ab, rx_desc)); +@@ -2858,13 +2884,11 @@ static void ath12k_dp_rx_h_fetch_info(st + } + } + +-void ath12k_dp_rx_h_ppdu(struct ath12k *ar, struct hal_rx_desc *rx_desc, +- struct ath12k_dp_rx_info *rx_info) ++void ath12k_dp_rx_h_ppdu(struct ath12k *ar, struct ath12k_dp_rx_info *rx_info) + { +- struct ath12k_base *ab = ar->ab; + struct ieee80211_rx_status *rx_status = rx_info->rx_status; + u8 channel_num; +- u32 center_freq, meta_data; ++ u32 center_freq, meta_data = 0; + struct ieee80211_channel *channel; + + rx_status->freq = 0; +@@ -2875,7 +2899,9 @@ void ath12k_dp_rx_h_ppdu(struct ath12k * + + rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL; + +- meta_data = ath12k_dp_rx_h_freq(ab, rx_desc); ++ if (rx_info->filled & BIT_ULL(ATH12K_RX_INFO_PHY_META_DATA)) ++ meta_data = rx_info->phy_meta_data; ++ + channel_num = meta_data; + center_freq = meta_data >> 16; + +@@ -2897,9 +2923,6 @@ void ath12k_dp_rx_h_ppdu(struct ath12k * + ath12k_err(ar->ab, "sband is NULL for status band %d channel_num %d center_freq %d pdev_id %d\n", + rx_status->band, channel_num, center_freq, ar->pdev_idx); + +- ath12k_dbg_dump(ar->ab, ATH12K_DBG_DATA, NULL, "rx_desc: ", +- rx_desc, sizeof(struct hal_rx_desc)); +- + spin_lock_bh(&ar->data_lock); + channel = ar->rx_channel; + if (channel) { +@@ -2916,7 +2939,7 @@ void ath12k_dp_rx_h_ppdu(struct ath12k * + rx_status->freq = ieee80211_channel_to_frequency(channel_num, + rx_status->band); + +- ath12k_dp_rx_h_rate(ar, rx_desc, rx_status); ++ ath12k_dp_rx_h_rate(ar, rx_info); + } + + static void ath12k_dp_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *napi, +@@ -3121,7 +3144,7 @@ static int ath12k_dp_rx_process_msdu(str + if (*fast_rx) + return 0; + +- ath12k_dp_rx_h_ppdu(ar, rx_desc, rx_info); ++ ath12k_dp_rx_h_ppdu(ar, rx_info); + + rx_info->rx_status->flag |= RX_FLAG_SKIP_MONITOR | RX_FLAG_DUP_VALIDATED; + +@@ -3539,7 +3562,7 @@ mic_fail: + RX_FLAG_IV_STRIPPED | RX_FLAG_DECRYPTED; + skb_pull(msdu, hal_rx_desc_sz); + +- ath12k_dp_rx_h_ppdu(ar, rx_desc, &rx_info); ++ ath12k_dp_rx_h_ppdu(ar, &rx_info); + ath12k_dp_rx_h_undecap(ar, msdu, rx_desc, + HAL_ENCRYPT_TYPE_TKIP_MIC, rxs, true); + ieee80211_rx(ar->ah->hw, msdu); +@@ -4262,7 +4285,7 @@ static int ath12k_dp_rx_h_null_q_desc(st + ath12k_dp_rx_check_max_nwifi_hdr_len(ab, desc, msdu)) + return -EINVAL; + +- ath12k_dp_rx_h_ppdu(ar, desc, rx_info); ++ ath12k_dp_rx_h_ppdu(ar, rx_info); + fast_rx = false; + ath12k_dp_rx_h_mpdu(ar, msdu, desc, rx_info, &fast_rx); + +@@ -4347,7 +4370,7 @@ static bool ath12k_dp_rx_h_tkip_mic_err( + skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len); + skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes); + +- ath12k_dp_rx_h_ppdu(ar, desc, rx_info); ++ ath12k_dp_rx_h_ppdu(ar, rx_info); + + rx_info->rx_status->flag |= (RX_FLAG_MMIC_STRIPPED | RX_FLAG_MMIC_ERROR | + RX_FLAG_DECRYPTED); +@@ -4393,7 +4416,7 @@ static bool ath12k_dp_rx_h_4addr_null_fr + ath12k_dp_rx_check_max_nwifi_hdr_len(ab, rx_desc, msdu)) + return true; + +- ath12k_dp_rx_h_ppdu(ar, rx_desc, rx_info); ++ ath12k_dp_rx_h_ppdu(ar, rx_info); + + ath12k_dp_rx_h_mpdu(ar, msdu, rx_desc, rx_info, &fast_rx); + +--- a/drivers/net/wireless/ath/ath12k/dp_rx.h ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.h +@@ -68,6 +68,12 @@ struct ath12k_dp_rx_rfc1042_hdr { + + enum ath12k_dp_rx_info_type { + ATH12K_RX_INFO_DECAP_TYPE, ++ ATH12K_RX_INFO_PKT_TYPE, ++ ATH12K_RX_INFO_SGI, ++ ATH12K_RX_INFO_RATE_MCS, ++ ATH12K_RX_INFO_BW, ++ ATH12K_RX_INFO_NSS, ++ ATH12K_RX_INFO_PHY_META_DATA, + ATH12K_RX_INFO_ADDR2, + + /* keep last */ +@@ -77,6 +83,12 @@ enum ath12k_dp_rx_info_type { + struct ath12k_dp_rx_info { + u64 filled; + u8 decap_type; ++ u8 pkt_type; ++ u8 sgi; ++ u8 rate_mcs; ++ u8 bw; ++ u8 nss; ++ u32 phy_meta_data; + u8 addr2[ETH_ALEN]; + struct ieee80211_rx_status *rx_status; + }; +@@ -158,6 +170,5 @@ u8 ath12k_dp_rx_h_decap_type(struct ath1 + struct hal_rx_desc *desc); + u32 ath12k_dp_rx_h_mpdu_err(struct ath12k_base *ab, + struct hal_rx_desc *desc); +-void ath12k_dp_rx_h_ppdu(struct ath12k *ar, struct hal_rx_desc *rx_desc, +- struct ath12k_dp_rx_info *rx_info); ++void ath12k_dp_rx_h_ppdu(struct ath12k *ar, struct ath12k_dp_rx_info *rx_info); + #endif /* ATH12K_DP_RX_H */ diff --git a/feeds/ipq95xx/mac80211/patches/qca/715-04-wifi-ath12k-remove-the-unused-hal_ops-rx_desc_get_mp.patch b/feeds/ipq95xx/mac80211/patches/qca/715-04-wifi-ath12k-remove-the-unused-hal_ops-rx_desc_get_mp.patch new file mode 100644 index 000000000..798bb1a30 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/715-04-wifi-ath12k-remove-the-unused-hal_ops-rx_desc_get_mp.patch @@ -0,0 +1,64 @@ +From 03b915be046b9f5e3866239ecbdcdfc822cd65fb Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Sun, 12 Feb 2023 19:44:46 +0530 +Subject: [PATCH 4/4] wifi: ath12k: remove the unused hal_ops + rx_desc_get_mpdu_frame_ctl + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/hal.c | 18 ------------------ + drivers/net/wireless/ath/ath12k/hal.h | 1 - + 2 files changed, 19 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/hal.c ++++ b/drivers/net/wireless/ath/ath12k/hal.c +@@ -467,11 +467,6 @@ static void ath12k_hw_qcn9274_rx_desc_ge + crypto_hdr[7] = HAL_RX_MPDU_INFO_PN_GET_BYTE2(desc->u.qcn9274.mpdu_start.pn[1]); + } + +-static u16 ath12k_hw_qcn9274_rx_desc_get_mpdu_frame_ctl(struct hal_rx_desc *desc) +-{ +- return __le16_to_cpu(desc->u.qcn9274.mpdu_start.frame_ctrl); +-} +- + static u8 ath12k_hal_qcn9274_rx_desc_get_ip_valid(struct hal_rx_desc *desc) + { + bool ipv4, ipv6; +@@ -695,7 +690,6 @@ const struct hal_ops hal_qcn9274_ops = { + .rx_desc_is_mcbc = ath12k_hw_qcn9274_rx_desc_is_mcbc, + .rx_desc_get_dot11_hdr = ath12k_hw_qcn9274_rx_desc_get_dot11_hdr, + .rx_desc_get_crypto_header = ath12k_hw_qcn9274_rx_desc_get_crypto_hdr, +- .rx_desc_get_mpdu_frame_ctl = ath12k_hw_qcn9274_rx_desc_get_mpdu_frame_ctl, + .create_srng_config = ath12k_hal_srng_create_config_qcn9274, + .tcl_to_wbm_rbm_map = ath12k_hal_qcn9274_tcl_to_wbm_rbm_map, + .dp_rx_h_msdu_done = ath12k_hw_qcn9274_dp_rx_h_msdu_done, +@@ -939,11 +933,6 @@ static void ath12k_hw_wcn7850_rx_desc_ge + crypto_hdr[7] = HAL_RX_MPDU_INFO_PN_GET_BYTE2(desc->u.wcn7850.mpdu_start.pn[1]); + } + +-static u16 ath12k_hw_wcn7850_rx_desc_get_mpdu_frame_ctl(struct hal_rx_desc *desc) +-{ +- return __le16_to_cpu(desc->u.wcn7850.mpdu_start.frame_ctrl); +-} +- + static int ath12k_hal_srng_create_config_wcn7850(struct ath12k_base *ab) + { + struct ath12k_hal *hal = &ab->hal; +@@ -1154,7 +1143,6 @@ const struct hal_ops hal_wcn7850_ops = { + .rx_desc_is_mcbc = ath12k_hw_wcn7850_rx_desc_is_mcbc, + .rx_desc_get_dot11_hdr = ath12k_hw_wcn7850_rx_desc_get_dot11_hdr, + .rx_desc_get_crypto_header = ath12k_hw_wcn7850_rx_desc_get_crypto_hdr, +- .rx_desc_get_mpdu_frame_ctl = ath12k_hw_wcn7850_rx_desc_get_mpdu_frame_ctl, + .create_srng_config = ath12k_hal_srng_create_config_wcn7850, + .tcl_to_wbm_rbm_map = ath12k_hal_wcn7850_tcl_to_wbm_rbm_map, + .dp_rx_h_msdu_done = ath12k_hw_wcn7850_dp_rx_h_msdu_done, +--- a/drivers/net/wireless/ath/ath12k/hal.h ++++ b/drivers/net/wireless/ath/ath12k/hal.h +@@ -1107,7 +1107,6 @@ struct hal_ops { + bool (*rx_desc_is_mcbc)(struct hal_rx_desc *desc); + void (*rx_desc_get_dot11_hdr)(struct hal_rx_desc *desc, + struct ieee80211_hdr *hdr); +- u16 (*rx_desc_get_mpdu_frame_ctl)(struct hal_rx_desc *desc); + void (*rx_desc_get_crypto_header)(struct hal_rx_desc *desc, + u8 *crypto_hdr, + enum hal_encrypt_type enctype); diff --git a/feeds/ipq95xx/mac80211/patches/qca/715-a-mac80211-Add-link-id-support-for-op-sta-rc-update.patch b/feeds/ipq95xx/mac80211/patches/qca/715-a-mac80211-Add-link-id-support-for-op-sta-rc-update.patch new file mode 100644 index 000000000..0bdd0bce7 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/715-a-mac80211-Add-link-id-support-for-op-sta-rc-update.patch @@ -0,0 +1,173 @@ +From 281b6cb98d5374af63b666eb332cc28e76256169 Mon Sep 17 00:00:00 2001 +From: Rajat Soni +Date: Fri, 24 Feb 2023 14:31:59 +0530 +Subject: [PATCH] mac80211: Add link id support for op sta rc update + +Currently only link id 0 is hardcoded in ath12k driver that is +causing crash because when multiple interfaces are up. mac has +proper link id information. + +To resolve this issue send proper link id to ath12k driver +through sta_rc_update. + +Signed-off-by: Rajat Soni +--- + include/net/mac80211.h | 2 +- + net/mac80211/driver-ops.c | 10 +++++++--- + net/mac80211/driver-ops.h | 3 ++- + net/mac80211/ibss.c | 4 ++-- + net/mac80211/mlme.c | 1 - + net/mac80211/rate.c | 4 +--- + net/mac80211/rx.c | 7 +++++-- + net/mac80211/trace.h | 4 ++-- + 8 files changed, 20 insertions(+), 15 deletions(-) + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -4403,7 +4403,7 @@ struct ieee80211_ops { + void (*sta_rc_update)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, +- u32 changed); ++ u32 changed, u8 link_id); + void (*sta_rate_tbl_update)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +--- a/net/mac80211/driver-ops.c ++++ b/net/mac80211/driver-ops.c +@@ -187,20 +187,24 @@ int drv_sta_set_mgmt_rts_cts(struct ieee + + void drv_sta_rc_update(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, +- struct ieee80211_sta *sta, u32 changed) ++ struct ieee80211_sta *sta, u32 changed, ++ int link_id) + { + sdata = get_bss_sdata(sdata); + if (!check_sdata_in_driver(sdata)) + return; + ++ if (link_id < 0 || link_id >= IEEE80211_MLD_MAX_NUM_LINKS) ++ link_id = 0; ++ + WARN_ON(changed & IEEE80211_RC_SUPP_RATES_CHANGED && + (sdata->vif.type != NL80211_IFTYPE_ADHOC && + sdata->vif.type != NL80211_IFTYPE_MESH_POINT)); + +- trace_drv_sta_rc_update(local, sdata, sta, changed); ++ trace_drv_sta_rc_update(local, sdata, sta, changed, link_id); + if (local->ops->sta_rc_update) + local->ops->sta_rc_update(&local->hw, &sdata->vif, +- sta, changed); ++ sta, changed, (u8) link_id); + + trace_drv_return_void(local); + } +--- a/net/mac80211/driver-ops.h ++++ b/net/mac80211/driver-ops.h +@@ -551,7 +551,8 @@ int drv_sta_set_mgmt_rts_cts(struct ieee + + void drv_sta_rc_update(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, +- struct ieee80211_sta *sta, u32 changed); ++ struct ieee80211_sta *sta, u32 changed, ++ int link_id); + + static inline void drv_sta_rate_tbl_update(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, +--- a/net/mac80211/ibss.c ++++ b/net/mac80211/ibss.c +@@ -981,6 +981,12 @@ static void ieee80211_update_sta_info(st + struct ieee80211_supported_band *sband; + bool rates_updated = false; + u32 supp_rates = 0; ++ int link_id; ++ ++ if (!rx_status->link_valid) ++ link_id = -1; ++ else ++ link_id = rx_status->link_id; + + if (sdata->vif.type != NL80211_IFTYPE_ADHOC) + return; +@@ -1088,7 +1094,7 @@ static void ieee80211_update_sta_info(st + if (sta->sta.deflink.rx_nss != rx_nss) + changed |= IEEE80211_RC_NSS_CHANGED; + +- drv_sta_rc_update(local, sdata, &sta->sta, changed); ++ drv_sta_rc_update(local, sdata, &sta->sta, changed, link_id); + } + + rcu_read_unlock(); +@@ -1110,7 +1116,6 @@ static void ieee80211_rx_bss_info(struct + channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq); + if (!channel) + return; +- + ieee80211_update_sta_info(sdata, mgmt, len, rx_status, elems, channel); + + bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, channel); +--- a/net/mac80211/rate.c ++++ b/net/mac80211/rate.c +@@ -101,8 +101,6 @@ void rate_control_rate_update(struct iee + void *priv_sta = sta->rate_ctrl_priv; + struct ieee80211_chanctx_conf *chanctx_conf; + +- WARN_ON(link_id != 0); +- + if (ref && ref->ops->rate_update) { + rcu_read_lock(); + +@@ -119,7 +117,7 @@ void rate_control_rate_update(struct iee + rcu_read_unlock(); + } + +- drv_sta_rc_update(local, sta->sdata, &sta->sta, changed); ++ drv_sta_rc_update(local, sta->sdata, &sta->sta, changed, link_id); + } + + int ieee80211_rate_control_register(const struct rate_control_ops *ops) +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -3547,6 +3547,7 @@ ieee80211_rx_h_action(struct ieee80211_r + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); + int len = rx->skb->len; ++ int link_id; + + if (!ieee80211_is_action(mgmt->frame_control)) + return RX_CONTINUE; +@@ -3612,7 +3613,8 @@ ieee80211_rx_h_action(struct ieee80211_r + + sband = rx->local->hw.wiphy->bands[status->band]; + +- rate_control_rate_update(local, sband, rx->sta, 0, ++ link_id = rx->link_sta->link_id; ++ rate_control_rate_update(local, sband, rx->sta, link_id, + IEEE80211_RC_SMPS_CHANGED); + cfg80211_sta_opmode_change_notify(sdata->dev, + rx->sta->addr, +@@ -3650,7 +3652,8 @@ ieee80211_rx_h_action(struct ieee80211_r + ieee80211_sta_rx_bw_to_chan_width(rx->link_sta); + sta_opmode.changed = STA_OPMODE_MAX_BW_CHANGED; + +- rate_control_rate_update(local, sband, rx->sta, 0, ++ link_id = rx->link_sta->link_id; ++ rate_control_rate_update(local, sband, rx->sta, link_id, + IEEE80211_RC_BW_CHANGED); + cfg80211_sta_opmode_change_notify(sdata->dev, + rx->sta->addr, +--- a/net/mac80211/trace.h ++++ b/net/mac80211/trace.h +@@ -969,9 +969,9 @@ TRACE_EVENT(drv_sta_rc_update, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct ieee80211_sta *sta, +- u32 changed), ++ u32 changed, int link_id), + +- TP_ARGS(local, sdata, sta, changed), ++ TP_ARGS(local, sdata, sta, changed, link_id), + + TP_STRUCT__entry( + LOCAL_ENTRY diff --git a/feeds/ipq95xx/mac80211/patches/qca/715-ath12k-add-support-for-peer-meta-data-version.patch b/feeds/ipq95xx/mac80211/patches/qca/715-ath12k-add-support-for-peer-meta-data-version.patch new file mode 100644 index 000000000..3aa955da5 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/715-ath12k-add-support-for-peer-meta-data-version.patch @@ -0,0 +1,104 @@ +From 3bcb7eb3a92e7ffffe6f7ebb7dfc0534f0f528e1 Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Wed, 22 Feb 2023 13:06:00 +0530 +Subject: [PATCH] ath12k: add support for peer meta data version + +Add new WMI Service command - WMI_TLV_SERVICE_PEER_METADATA_V1A_V1B_SUPPORT +to support multiple FW PeerMetaData Versions + +if WMI_SERVICE_V1A_V1B_SUPPORTED service bit is set by FW,then from host +it will set rx_peer_meta_data_ver in wmi_resource_config's flags2 with +value 2 for WCN7850 to indicate as V1A and value 3 for QCN9274, IPQ5332 to +indicate as V1B meta version. Otherwise, no need to send it. + +Signed-off-by: Harshitha Prem +--- + drivers/net/wireless/ath/ath12k/hw.c | 4 ++++ + drivers/net/wireless/ath/ath12k/hw.h | 1 + + drivers/net/wireless/ath/ath12k/wmi.c | 6 +++++- + drivers/net/wireless/ath/ath12k/wmi.h | 2 ++ + 4 files changed, 12 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -232,6 +232,10 @@ void ath12k_wmi_init_qcn9274(struct ath1 + config->ema_max_vap_cnt = ab->num_radios; + config->ema_max_profile_period = TARGET_EMA_MAX_PROFILE_PERIOD; + config->beacon_tx_offload_max_vdev += config->ema_max_vap_cnt; ++ ++ if (test_bit(WMI_TLV_SERVICE_PEER_METADATA_V1A_V1B_SUPPORT, ab->wmi_ab.svc_map)) ++ config->dp_peer_meta_data_ver = TARGET_RX_PEER_METADATA_VER_V1B; ++ + } + + void ath12k_wmi_init_ipq5332(struct ath12k_base *ab, +@@ -292,6 +296,10 @@ void ath12k_wmi_init_ipq5332(struct ath1 + config->ema_max_vap_cnt = ab->num_radios; + config->ema_max_profile_period = TARGET_EMA_MAX_PROFILE_PERIOD; + config->beacon_tx_offload_max_vdev += config->ema_max_vap_cnt; ++ ++ if (test_bit(WMI_TLV_SERVICE_PEER_METADATA_V1A_V1B_SUPPORT, ab->wmi_ab.svc_map)) ++ config->dp_peer_meta_data_ver = TARGET_RX_PEER_METADATA_VER_V1B; ++ + } + + +@@ -339,6 +347,10 @@ void ath12k_wmi_init_wcn7850(struct ath1 + config->num_multicast_filter_entries = 0x20; + config->num_wow_filters = 0x16; + config->num_keep_alive_pattern = 0; ++ ++ if (test_bit(WMI_TLV_SERVICE_PEER_METADATA_V1A_V1B_SUPPORT, ab->wmi_ab.svc_map)) ++ config->dp_peer_meta_data_ver = TARGET_RX_PEER_METADATA_VER_V1A; ++ + } + + #define PRIMAP(_hw_mode_) \ +@@ -4661,7 +4673,9 @@ ath12k_wmi_copy_resource_config(struct w + wmi_cfg->twt_ap_pdev_count = tg_cfg->twt_ap_pdev_count; + wmi_cfg->twt_ap_sta_count = tg_cfg->twt_ap_sta_count; + wmi_cfg->flags2 = WMI_RSRC_CFG_FLAGS2_CALC_NEXT_DTIM_COUNT_SET | +- WMI_RSRC_CFG_FLAGS2_INTRABSS_MEC_WDS_LEARNING_DISABLE; ++ WMI_RSRC_CFG_FLAGS2_INTRABSS_MEC_WDS_LEARNING_DISABLE | ++ u32_encode_bits(tg_cfg->dp_peer_meta_data_ver, ++ WMI_RSRC_CFG_FLAGS2_RX_PEER_METADATA_VERSION); + wmi_cfg->host_service_flags &= ~(1 << WMI_RSRC_CFG_HOST_SVC_FLAG_REG_CC_EXT_SUPPORT_BIT); + wmi_cfg->host_service_flags |= 1 << WMI_RSRC_CFG_HOST_SVC_FLAG_REG_CC_EXT_SUPPORT_BIT; + wmi_cfg->host_service_flags |= 1 << WMI_RSRC_CFG_HOST_SVC_FLAG_REO_QREF_SUPPORT_BIT; +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -2208,6 +2208,7 @@ enum wmi_tlv_service { + WMI_TLV_SERVICE_DCS_AWGN_INT_SUPPORT = 286, + WMI_TLV_SERVICE_BE = 289, + WMI_TLV_SERVICE_PKTLOG_DECODE_INFO_SUPPORT = 320, ++ WMI_TLV_SERVICE_PEER_METADATA_V1A_V1B_SUPPORT = 365, + WMI_MAX_EXT2_SERVICE, + }; + +@@ -2526,6 +2527,7 @@ struct wmi_init_cmd { + + #define WMI_RSRC_CFG_HOST_SVC_FLAG_REG_CC_EXT_SUPPORT_BIT 4 + #define WMI_RSRC_CFG_HOST_SVC_FLAG_REO_QREF_SUPPORT_BIT 12 ++#define WMI_RSRC_CFG_FLAGS2_RX_PEER_METADATA_VERSION GENMASK(5,4) + #define WMI_RSRC_CFG_FLAGS2_CALC_NEXT_DTIM_COUNT_SET BIT(9) + #define WMI_RSRC_CFG_FLAGS2_INTRABSS_MEC_WDS_LEARNING_DISABLE BIT(15) + #define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5) +@@ -6282,6 +6284,7 @@ struct target_resource_config { + bool is_reg_cc_ext_event_supported; + u32 ema_max_vap_cnt; + u32 ema_max_profile_period; ++ u8 dp_peer_meta_data_ver; + }; + + enum wmi_tpc_pream_bw { +--- a/drivers/net/wireless/ath/ath12k/hw.h ++++ b/drivers/net/wireless/ath/ath12k/hw.h +@@ -67,6 +67,8 @@ + #define TARGET_DMA_BURST_SIZE 1 + #define TARGET_RX_BATCHMODE 1 + #define TARGET_EMA_MAX_PROFILE_PERIOD 8 ++#define TARGET_RX_PEER_METADATA_VER_V1A 2 ++#define TARGET_RX_PEER_METADATA_VER_V1B 3 + + #define ATH12K_HW_DEFAULT_QUEUE 0 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/715-ath12k-btcoex-support.patch b/feeds/ipq95xx/mac80211/patches/qca/715-ath12k-btcoex-support.patch new file mode 100644 index 000000000..6d7a3842c --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/715-ath12k-btcoex-support.patch @@ -0,0 +1,1119 @@ +From 8355c5620951eb63d67af5abc1c7dd9ab2f758d3 Mon Sep 17 00:00:00 2001 +From: Karthik M +Date: Thu, 16 Feb 2023 00:03:37 +0530 +Subject: [PATCH] wifi: ath12k: BT-Coex feature support + +Fetch the default parameters from DTS during boot-up. +Add debugfs commands for configuring up the BT-Coex feature. + +Syntax: +echo " " > + /sys/kernel/debug/ath12k/qcn9274\hw2.0_0002:01:00.0/mac0/btcoex +echo " + " > + /sys/kernel/debug/ath12k/qcn9274\hw2.0_0002:01:00.0/mac0/btcoex_algorithm +echo " " > + /sys/kernel/debug/ath12k/qcn9274\hw2.0_0002:01:00.0/mac0/btcoex_duty_cycle +echo " + " > + /sys/kernel/debug/ath12k/qcn9274\ hw2.0_0002:01:00.0/mac0/btcoex_priority + +Example: +echo "1 4 255" > /sys/kernel/debug/ath12k/qcn9274\ hw2.0_0002:01:00.0/mac0/btcoex +echo "1 2 10 10 2 2" > + /sys/kernel/debug/ath12k/qcn9274\ hw2.0_0002:01:00.0/mac0/btcoex_algorithm +echo "100 20" > /sys/kernel/debug/ath12k/qcn9274\ hw2.0_0002:01:00.0/mac0/btcoex_duty_cycle +echo "3 0 255 255" > /sys/kernel/debug/ath12k/qcn9274\ hw2.0_0002:01:00.0/mac0/btcoex_priority + +Signed-off-by: Karthik M +--- + drivers/net/wireless/ath/ath12k/core.h | 29 ++ + drivers/net/wireless/ath/ath12k/debugfs.c | 512 ++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/debugfs.h | 29 ++ + drivers/net/wireless/ath/ath12k/mac.c | 148 +++++++ + drivers/net/wireless/ath/ath12k/mac.h | 5 + + drivers/net/wireless/ath/ath12k/wmi.c | 104 +++++ + drivers/net/wireless/ath/ath12k/wmi.h | 119 +++++ + 7 files changed, 946 insertions(+) + +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -3203,6 +3203,505 @@ static const struct file_operations fops + .llseek = default_llseek, + }; + ++static ssize_t ath12k_write_btcoex(struct file *file, ++ const char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k_link_vif *arvif = NULL; ++ struct ath12k *ar = file->private_data; ++ char buf[256] = {0}; ++ size_t buf_size; ++ int ret = 0,coex = BTCOEX_CONFIGURE_DEFAULT, wlan_weight = 0, ++ wlan_prio_mask_value = 0; ++ enum qca_wlan_priority_type wlan_prio_mask = QCA_WLAN_PRIORITY_BE; ++ ++ if (!ar) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ buf_size = min(count, (sizeof(buf) - 1)); ++ ++ if (copy_from_user(buf, ubuf, buf_size)) { ++ ret = -EFAULT; ++ goto exit; ++ } ++ ++ buf[buf_size] = '\0'; ++ ret = sscanf(buf, "%d %d %d" , &coex, &wlan_prio_mask_value, &wlan_weight); ++ ++ if (!ret) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ if (coex != BTCOEX_ENABLE && coex != BTCOEX_CONFIGURE_DEFAULT && coex) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ switch (coex) { ++ case BTCOEX_ENABLE: ++ if (!test_bit(ATH12K_FLAG_BTCOEX, &ar->dev_flags)) ++ set_bit(ATH12K_FLAG_BTCOEX, &ar->dev_flags); ++ break; ++ case BTCOEX_CONFIGURE_DEFAULT: ++ if (!test_bit(ATH12K_FLAG_BTCOEX, &ar->dev_flags)) { ++ ret = -EINVAL; ++ goto error_unlock; ++ } ++ break; ++ case BTCOEX_DISABLE: ++ clear_bit(ATH12K_FLAG_BTCOEX, &ar->dev_flags); ++ break; ++ default: ++ ret = -EINVAL; ++ goto error_unlock; ++ } ++ ++ if ((wlan_weight < BTCOEX_CONFIGURE_DEFAULT) || ++ (wlan_prio_mask_value < BTCOEX_CONFIGURE_DEFAULT) || ++ (wlan_weight > BTCOEX_MAX_PKT_WEIGHT) || ++ (wlan_prio_mask_value > QCA_WLAN_PRIORITY_MGMT)) { ++ ret = -EINVAL; ++ goto error_unlock; ++ } ++ ++ if (wlan_weight == BTCOEX_CONFIGURE_DEFAULT) ++ wlan_weight = ar->coex.wlan_weight; ++ ++ wlan_prio_mask = ((wlan_prio_mask_value == BTCOEX_CONFIGURE_DEFAULT)? ++ ar->coex.wlan_prio_mask : wlan_prio_mask_value); ++ ++ if (ar->state != ATH12K_STATE_ON && ++ ar->state != ATH12K_STATE_RESTARTED) { ++ ath12k_warn(ar->ab, "pdev %d not in ON state\n", ar->pdev->pdev_id); ++ ret = -ENETDOWN; ++ goto error_unlock; ++ } ++ ++ arvif = list_first_entry(&ar->arvifs, typeof(*arvif), list); ++ ++ if (!arvif->is_started) { ++ ret = -EINVAL; ++ goto error_unlock; ++ } ++ ++ ret = ath12k_mac_btcoex_config(ar, arvif, coex, wlan_prio_mask, wlan_weight); ++ ++ if (ret) { ++ ath12k_warn(ar->ab, ++ "failed to enable coex vdev_id %d ret %d\n", ++ arvif->vdev_id, ret); ++ goto error_unlock; ++ } ++ ++ ar->coex.wlan_prio_mask = wlan_prio_mask; ++ ar->coex.wlan_weight = wlan_weight; ++ ret = count; ++ ++error_unlock: ++ mutex_unlock(&ar->conf_mutex); ++ ++exit: ++ return ret; ++} ++ ++static ssize_t ath12k_read_btcoex(struct file *file, char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ char buf[256] = {0}; ++ int len = 0; ++ ++ if (!ar) ++ return -EINVAL; ++ ++ mutex_lock(&ar->conf_mutex); ++ len = scnprintf(buf, sizeof(buf) - len, "%u %u %u\n", ++ test_bit(ATH12K_FLAG_BTCOEX, &ar->dev_flags), ++ ar->coex.wlan_prio_mask, ++ ar->coex.wlan_weight); ++ mutex_unlock(&ar->conf_mutex); ++ ++ return simple_read_from_buffer(ubuf, count, ppos, buf, len); ++} ++ ++static const struct file_operations fops_btcoex = { ++ .read = ath12k_read_btcoex, ++ .write = ath12k_write_btcoex, ++ .open = simple_open ++}; ++ ++static ssize_t ath12k_write_btcoex_duty_cycle(struct file *file, ++ const char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k_link_vif *arvif = NULL; ++ struct ath12k *ar = file->private_data; ++ struct coex_config_arg coex_config; ++ char buf[256] = {0}; ++ size_t buf_size; ++ u32 duty_cycle = 0, wlan_duration = 0; ++ int ret = 0; ++ ++ if (!ar) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ buf_size = min(count, (sizeof(buf) - 1)); ++ ++ if (copy_from_user(buf, ubuf, buf_size)) { ++ ret = -EFAULT; ++ goto exit; ++ } ++ ++ buf[buf_size] = '\0'; ++ ret = sscanf(buf, "%u %u", &duty_cycle, &wlan_duration); ++ ++ if (!ret) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ /*Maximum duty_cycle period allowed is 100 Miliseconds*/ ++ if (duty_cycle < wlan_duration || !duty_cycle || !wlan_duration || duty_cycle > 100000) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ if (ar->state != ATH12K_STATE_ON && ++ ar->state != ATH12K_STATE_RESTARTED) { ++ ath12k_warn(ar->ab, "pdev %d not in ON state\n", ar->pdev->pdev_id); ++ ret = -ENETDOWN; ++ goto error_unlock; ++ } ++ ++ if (!test_bit(ATH12K_FLAG_BTCOEX, &ar->dev_flags)) { ++ ret = -EINVAL; ++ goto error_unlock; ++ } ++ ++ if (ar->coex.coex_algo_type != COEX_ALGO_OCS) { ++ ath12k_err(ar->ab,"duty cycle algo is not enabled"); ++ ret = -EINVAL; ++ goto error_unlock; ++ } ++ ++ arvif = list_first_entry(&ar->arvifs, typeof(*arvif), list); ++ ++ if (!arvif->is_started) { ++ ret = -EINVAL; ++ goto error_unlock; ++ } ++ ++ coex_config.vdev_id = arvif->vdev_id; ++ coex_config.config_type = WMI_COEX_CONFIG_AP_TDM; ++ coex_config.duty_cycle = duty_cycle; ++ coex_config.wlan_duration = wlan_duration; ++ mutex_unlock(&ar->conf_mutex); ++ ++ ret = ath12k_send_coex_config_cmd(ar, &coex_config); ++ ++ if (ret) { ++ ath12k_warn(ar->ab, ++ "failed to set duty cycle vdev_id %d ret %d\n", ++ coex_config.vdev_id, ret); ++ goto exit; ++ } ++ ++ mutex_lock(&ar->conf_mutex); ++ ar->coex.duty_cycle = duty_cycle; ++ ar->coex.wlan_duration = wlan_duration; ++ ret = count; ++ ++error_unlock: ++ mutex_unlock(&ar->conf_mutex); ++ ++exit: ++ return ret; ++} ++ ++static ssize_t ath12k_read_btcoex_duty_cycle(struct file *file, char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ char buf[256] = {0}; ++ int len = 0; ++ ++ if (!ar) ++ return -EINVAL; ++ ++ mutex_lock(&ar->conf_mutex); ++ len = scnprintf(buf, sizeof(buf) - len, "%d %d\n", ++ ar->coex.duty_cycle,ar->coex.wlan_duration); ++ mutex_unlock(&ar->conf_mutex); ++ ++ return simple_read_from_buffer(ubuf, count, ppos, buf, len); ++} ++ ++static const struct file_operations fops_btcoex_duty_cycle = { ++ .read = ath12k_read_btcoex_duty_cycle, ++ .write = ath12k_write_btcoex_duty_cycle, ++ .open = simple_open ++}; ++ ++static ssize_t ath12k_write_btcoex_algo(struct file *file, ++ const char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k_link_vif *arvif = NULL; ++ struct ath12k *ar = file->private_data; ++ struct coex_config_arg coex_config; ++ char buf[256] = {0}; ++ size_t buf_size; ++ u32 pta_num = 0, coex_mode = 0, bt_txrx_time = 0, ++ bt_priority_time = 0, pta_algorithm = 0, ++ pta_priority = 0; ++ int ret = 0; ++ ++ if (!ar) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ buf_size = min(count, (sizeof(buf) - 1)); ++ ++ if (copy_from_user(buf, ubuf, buf_size)) { ++ ret = -EFAULT; ++ goto exit; ++ } ++ ++ buf[buf_size] = '\0'; ++ ret = sscanf(buf, "%u 0x%x 0x%x 0x%x 0x%x 0x%x" , &pta_num, &coex_mode, ++ &bt_txrx_time, &bt_priority_time, ++ &pta_algorithm, &pta_priority); ++ ++ if (!ret) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ if (coex_mode > BTCOEX_PTA_MODE || ++ coex_mode < BTCOEX_THREE_WIRE_MODE || ++ pta_algorithm >= COEX_ALGO_MAX_SUPPORTED) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ if (ar->state != ATH12K_STATE_ON && ++ ar->state != ATH12K_STATE_RESTARTED) { ++ ath12k_warn(ar->ab, "pdev %d not in ON state\n", ar->pdev->pdev_id); ++ ret = -ENETDOWN; ++ goto error_unlock; ++ } ++ ++ if (!test_bit(ATH12K_FLAG_BTCOEX, &ar->dev_flags)) { ++ ret = -EINVAL; ++ goto error_unlock; ++ } ++ ++ arvif = list_first_entry(&ar->arvifs, typeof(*arvif), list); ++ ++ if (!arvif->is_started) { ++ ret = -EINVAL; ++ goto error_unlock; ++ } ++ ++ coex_config.vdev_id = arvif->vdev_id; ++ coex_config.config_type = WMI_COEX_CONFIG_PTA_INTERFACE; ++ coex_config.pta_num = pta_num; ++ coex_config.coex_mode = coex_mode; ++ coex_config.bt_txrx_time = bt_txrx_time; ++ coex_config.bt_priority_time = bt_priority_time; ++ coex_config.pta_algorithm = pta_algorithm; ++ coex_config.pta_priority = pta_priority; ++ mutex_unlock(&ar->conf_mutex); ++ ++ ret = ath12k_send_coex_config_cmd(ar, &coex_config); ++ ++ if (ret) { ++ ath12k_warn(ar->ab, ++ "failed to set coex algorithm vdev_id %d ret %d\n", ++ coex_config.vdev_id, ret); ++ goto exit; ++ } ++ ++ mutex_lock(&ar->conf_mutex); ++ ar->coex.pta_num = pta_num; ++ ar->coex.coex_mode = coex_mode; ++ ar->coex.bt_active_time_slot = bt_txrx_time; ++ ar->coex.bt_priority_time_slot = bt_priority_time; ++ ar->coex.pta_algorithm = pta_algorithm; ++ ar->coex.pta_priority = pta_priority; ++ ret = count; ++ ++error_unlock: ++ mutex_unlock(&ar->conf_mutex); ++ ++exit: ++ return ret; ++} ++ ++static ssize_t ath12k_read_btcoex_algo(struct file *file, char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ char buf[256] = {0}; ++ int len = 0; ++ ++ if (!ar) ++ return -EINVAL; ++ ++ mutex_lock(&ar->conf_mutex); ++ len = scnprintf(buf, sizeof(buf) - len, "%u %u %u %u %u %u\n", ++ ar->coex.pta_num, ar->coex.coex_mode, ++ ar->coex.bt_active_time_slot, ++ ar->coex.bt_priority_time_slot, ++ ar->coex.pta_algorithm, ar->coex.pta_priority); ++ mutex_unlock(&ar->conf_mutex); ++ ++ return simple_read_from_buffer(ubuf, count, ppos, buf, len); ++} ++ ++static const struct file_operations fops_btcoex_algo = { ++ .read = ath12k_read_btcoex_algo, ++ .write = ath12k_write_btcoex_algo, ++ .open = simple_open ++}; ++ ++static ssize_t ath12k_btcoex_pkt_priority_write(struct file *file, ++ const char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ struct ath12k_link_vif *arvif = NULL; ++ struct coex_config_arg coex_config; ++ char buf[128] = {0}; ++ size_t buf_size; ++ enum qca_wlan_priority_type wlan_pkt_type = 0; ++ u32 wlan_pkt_type_continued = 0, wlan_pkt_weight = 0, ++ bt_pkt_weight = 0; ++ int ret; ++ ++ if (!ar) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ buf_size = min(count, (sizeof(buf) - 1)); ++ ++ if (copy_from_user(buf, ubuf, buf_size)) { ++ ret = -EFAULT; ++ goto exit; ++ } ++ ++ buf[buf_size] = '\0'; ++ ret = sscanf(buf, "%u %u %u %u" , &wlan_pkt_type, ++ &wlan_pkt_type_continued, &wlan_pkt_weight, ++ &bt_pkt_weight); ++ ++ if (!ret) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ if (wlan_pkt_type > QCA_WLAN_PRIORITY_MGMT || ++ wlan_pkt_weight > BTCOEX_MAX_PKT_WEIGHT || ++ bt_pkt_weight > BTCOEX_MAX_PKT_WEIGHT) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ if (ar->state != ATH12K_STATE_ON && ++ ar->state != ATH12K_STATE_RESTARTED) { ++ ath12k_warn(ar->ab, "pdev %d not in ON state\n", ar->pdev->pdev_id); ++ ret = -ENETDOWN; ++ goto error_unlock; ++ } ++ ++ if (!test_bit(ATH12K_FLAG_BTCOEX, &ar->dev_flags)) { ++ ret = -EINVAL; ++ goto error_unlock; ++ } ++ ++ arvif = list_first_entry(&ar->arvifs, typeof(*arvif), list); ++ ++ if (!arvif->is_started) { ++ ret = -EINVAL; ++ goto error_unlock; ++ } ++ ++ coex_config.vdev_id = arvif->vdev_id; ++ coex_config.config_type = WMI_COEX_CONFIG_WLAN_PKT_PRIORITY; ++ coex_config.wlan_pkt_type = wlan_pkt_type; ++ coex_config.wlan_pkt_type_continued = wlan_pkt_type_continued; ++ coex_config.wlan_pkt_weight = wlan_pkt_weight; ++ coex_config.bt_pkt_weight = bt_pkt_weight; ++ mutex_unlock(&ar->conf_mutex); ++ ++ ret = ath12k_send_coex_config_cmd(ar, &coex_config); ++ ++ if (ret) { ++ ath12k_warn(ar->ab, ++ "failed to set coex pkt priority vdev_id %d ret %d\n", ++ coex_config.vdev_id, ret); ++ goto exit; ++ } ++ ++ mutex_lock(&ar->conf_mutex); ++ ar->coex.wlan_pkt_type = wlan_pkt_type; ++ ar->coex.wlan_pkt_type_continued = wlan_pkt_type_continued; ++ ar->coex.wlan_weight = wlan_pkt_weight; ++ ar->coex.bt_weight = bt_pkt_weight; ++ ++ ret = count; ++ ++error_unlock: ++ mutex_unlock(&ar->conf_mutex); ++ ++exit: ++ return ret; ++} ++ ++static ssize_t ath12k_btcoex_pkt_priority_read(struct file *file, ++ char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ u8 buf[128] = {0}; ++ size_t len = 0; ++ ++ if (!ar) ++ return -EINVAL; ++ ++ mutex_lock(&ar->conf_mutex); ++ len = scnprintf(buf, sizeof(buf) - len, ++ "%u %u %u %u\n",ar->coex.wlan_pkt_type, ++ ar->coex.wlan_pkt_type_continued, ar->coex.wlan_weight, ++ ar->coex.bt_weight); ++ mutex_unlock(&ar->conf_mutex); ++ ++ return simple_read_from_buffer(ubuf, count, ppos, buf, len); ++} ++ ++static const struct file_operations fops_btcoex_priority = { ++ .read = ath12k_btcoex_pkt_priority_read, ++ .write = ath12k_btcoex_pkt_priority_write, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ + int ath12k_debugfs_register(struct ath12k *ar) + { + struct ath12k_base *ab = ar->ab; +@@ -3281,6 +3780,22 @@ int ath12k_debugfs_register(struct ath12 + ar->debug.debugfs_pdev, ar, + &fops_athdiag); + ++ debugfs_create_file("btcoex", 0644, ++ ar->debug.debugfs_pdev, ar, ++ &fops_btcoex); ++ ++ debugfs_create_file("btcoex_duty_cycle", 0644, ++ ar->debug.debugfs_pdev, ar, ++ &fops_btcoex_duty_cycle); ++ ++ debugfs_create_file("btcoex_algorithm", 0644, ++ ar->debug.debugfs_pdev, ar, ++ &fops_btcoex_algo); ++ ++ debugfs_create_file("btcoex_priority", 0600, ++ ar->debug.debugfs_pdev, ar, ++ &fops_btcoex_priority); ++ + return 0; + } + +--- a/drivers/net/wireless/ath/ath12k/debugfs.h ++++ b/drivers/net/wireless/ath/ath12k/debugfs.h +@@ -230,6 +230,35 @@ struct ath12k_neighbor_peer { + bool rssi_valid; + }; + ++/* ++ * enum qca_wlan_priority_type - priority mask ++ * This enum defines priority mask that user can configure ++ * over BT traffic type which can be passed through ++ * QCA_WLAN_VENDOR_ATTR_BTCOEX_CONFIG_WLAN_PRIORITY attribute. ++ * ++ * @QCA_WLAN_PRIORITY_BE: Bit mask for WLAN Best effort traffic ++ * @QCA_WLAN_PRIORITY_BK: Bit mask for WLAN Background traffic ++ * @QCA_WLAN_PRIORITY_VI: Bit mask for WLAN Video traffic ++ * @QCA_WLAN_PRIORITY_VO: Bit mask for WLAN Voice traffic ++ * @QCA_WLAN_PRIORITY_BEACON: Bit mask for WLAN BEACON frame ++ * @QCA_WLAN_PRIORITY_MGMT: Bit mask for WLAN Management frame ++*/ ++enum qca_wlan_priority_type { ++ QCA_WLAN_PRIORITY_BE = BIT(0), ++ QCA_WLAN_PRIORITY_BK = BIT(1), ++ QCA_WLAN_PRIORITY_VI = BIT(2), ++ QCA_WLAN_PRIORITY_VO = BIT(3), ++ QCA_WLAN_PRIORITY_BEACON = BIT(4), ++ QCA_WLAN_PRIORITY_MGMT = BIT(5), ++}; ++ ++#define BTCOEX_ENABLE 1 ++#define BTCOEX_DISABLE 0 ++#define BTCOEX_CONFIGURE_DEFAULT -1 ++#define BTCOEX_THREE_WIRE_MODE 1 ++#define BTCOEX_PTA_MODE 2 ++#define BTCOEX_MAX_PKT_WEIGHT 255 ++ + void ath12k_wmi_crl_path_stats_list_free(struct ath12k *ar, struct list_head *head); + + #ifdef CPTCFG_ATH12K_DEBUGFS +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -6,6 +6,13 @@ + + #include + #include ++#include ++#include ++#include ++#include ++#include ++#include ++ + #include "mac.h" + #include "core.h" + #include "debug.h" +@@ -13207,6 +13214,70 @@ static void ath12k_mac_op_sta_statistics + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL); + } + ++int ath12k_mac_btcoex_config(struct ath12k *ar, struct ath12k_link_vif *arvif, ++ int coex, u32 wlan_prio_mask, u8 wlan_weight) ++{ ++ struct coex_config_arg coex_config; ++ int ret; ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ if (coex == BTCOEX_CONFIGURE_DEFAULT || (test_bit(ATH12K_FLAG_BTCOEX, &ar->dev_flags) ^ coex)) { ++ goto next; ++ } ++ ++ coex_config.vdev_id = arvif->vdev_id; ++ if (coex == BTCOEX_ENABLE) { ++ coex_config.config_type = WMI_COEX_CONFIG_PTA_INTERFACE; ++ coex_config.pta_num = ar->coex.pta_num; ++ coex_config.coex_mode = ar->coex.coex_mode; ++ coex_config.bt_txrx_time = ar->coex.bt_active_time_slot; ++ coex_config.bt_priority_time = ar->coex.bt_priority_time_slot; ++ coex_config.pta_algorithm = ar->coex.coex_algo_type; ++ coex_config.pta_priority = ar->coex.pta_priority; ++ ret = ath12k_send_coex_config_cmd(ar, &coex_config); ++ if (ret) { ++ ath12k_warn(ar->ab, ++ "failed to set coex config vdev_id %d ret %d\n", ++ coex_config.vdev_id, ret); ++ goto out; ++ } ++ } ++ ++ memset(&coex_config, 0, sizeof(struct coex_config_arg)); ++ coex_config.vdev_id = arvif->vdev_id; ++ coex_config.config_type = WMI_COEX_CONFIG_BTC_ENABLE; ++ coex_config.coex_enable = coex; ++ ret = ath12k_send_coex_config_cmd(ar, &coex_config); ++ if (ret) { ++ ath12k_warn(ar->ab, ++ "failed to set coex config vdev_id %d ret %d\n", ++ coex_config.vdev_id, ret); ++ goto out; ++ } ++ ++next: ++ if (!coex) { ++ ret = 0; ++ goto out; ++ } ++ ++ memset(&coex_config, 0, sizeof(struct coex_config_arg)); ++ coex_config.vdev_id = arvif->vdev_id; ++ coex_config.config_type = WMI_COEX_CONFIG_WLAN_PKT_PRIORITY; ++ coex_config.wlan_pkt_type = wlan_prio_mask; ++ coex_config.wlan_pkt_weight = wlan_weight; ++ ret = ath12k_send_coex_config_cmd(ar, &coex_config); ++ if (ret) { ++ ath12k_warn(ar->ab, ++ "failed to set coex config vdev_id %d ret %d\n", ++ coex_config.vdev_id, ret); ++ } ++ ++out: ++ return ret; ++} ++ + static int ath12k_fw_stats_request(struct ath12k *ar, + struct stats_request_params *req_param) + { +@@ -13843,6 +13914,61 @@ static int ath12k_mac_setup_iface_combin + return 0; + } + ++static void ath12k_mac_fetch_coex_info(struct ath12k *ar) ++{ ++ struct ath12k_pdev_cap *cap = &ar->pdev->cap; ++ struct ath12k_base *ab = ar->ab; ++ struct device *dev = ab->dev; ++ ++ ar->coex.coex_support = false; ++ ++ if (!(cap->supported_bands & WMI_HOST_WLAN_2G_CAP)) ++ return; ++ ++ if (of_property_read_u32(dev->of_node, "qcom,pta-num", ++ &ar->coex.pta_num)) { ++ ath12k_err(ab, "No qcom,pta_num entry in dev-tree.\n"); ++ } ++ ++ if (of_property_read_u32(dev->of_node, "qcom,coex-mode", ++ &ar->coex.coex_mode)) { ++ ath12k_err(ab, "No qcom,coex_mode entry in dev-tree.\n"); ++ } ++ ++ if (of_property_read_u32(dev->of_node, "qcom,bt-active-time", ++ &ar->coex.bt_active_time_slot)) { ++ ath12k_err(ab, "No qcom,bt-active-time entry in dev-tree.\n"); ++ } ++ ++ if (of_property_read_u32(dev->of_node, "qcom,bt-priority-time", ++ &ar->coex.bt_priority_time_slot)) { ++ ath12k_err(ab, "No qcom,bt-priority-time entry in dev-tree.\n"); ++ } ++ ++ if (of_property_read_u32(dev->of_node, "qcom,coex-algo", ++ &ar->coex.coex_algo_type)) { ++ ath12k_err(ab, "No qcom,coex-algo entry in dev-tree.\n"); ++ } ++ ++ if (of_property_read_u32(dev->of_node, "qcom,pta-priority", ++ &ar->coex.pta_priority)) { ++ ath12k_err(ab, "No qcom,pta-priority entry in dev-tree.\n"); ++ } ++ ++ if (ar->coex.coex_algo_type == COEX_ALGO_OCS) { ++ ar->coex.duty_cycle = 100000; ++ ar->coex.wlan_duration = 80000; ++ } ++ ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "coex pta_num %u coex_mode %u" ++ " bt_active_time_slot %u bt_priority_time_slot %u" ++ " coex_algorithm %u pta_priority %u\n", ar->coex.pta_num, ++ ar->coex.coex_mode, ar->coex.bt_active_time_slot, ++ ar->coex.bt_priority_time_slot, ar->coex.coex_algo_type, ++ ar->coex.pta_priority); ++ ar->coex.coex_support = true; ++} ++ + static const u8 ath12k_if_types_ext_capa[] = { + [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING, + [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT, +@@ -14428,6 +14554,8 @@ static int ath12k_mac_setup(struct ath12 + */ + ath12k_wmi_pdev_attach(ab, mac_id); + ++ ath12k_mac_fetch_coex_info(ar); ++ + ar->cfg_tx_chainmask = pdev->cap.tx_chain_mask; + ar->cfg_rx_chainmask = pdev->cap.rx_chain_mask; + ar->num_tx_chains = get_num_chains(pdev->cap.tx_chain_mask); +--- a/drivers/net/wireless/ath/ath12k/mac.h ++++ b/drivers/net/wireless/ath/ath12k/mac.h +@@ -173,6 +173,9 @@ enum ath12k_background_dfs_events { + ATH12K_BGDFS_RADAR, + }; + ++#define ATH12K_WLAN_PRIO_MAX 0x63 ++#define ATH12K_WLAN_PRIO_WEIGHT 0xff ++ + extern const struct htt_rx_ring_tlv_filter ath12k_mac_mon_status_filter_default; + + void ath12k_mac_ap_ps_recalc(struct ath12k *ar); +@@ -193,6 +196,8 @@ void ath12k_mac_scan_finish(struct ath12 + struct ath12k_link_vif *ath12k_mac_get_arvif(struct ath12k *ar, u32 vdev_id); + struct ath12k_link_vif *ath12k_mac_get_arvif_by_vdev_id(struct ath12k_base *ab, + u32 vdev_id); ++int ath12k_mac_btcoex_config(struct ath12k *ar, struct ath12k_link_vif *arvif, ++ int coex, u32 wlan_prio_mask, u8 wlan_weight); + struct ath12k *ath12k_mac_get_ar_by_vdev_id(struct ath12k_base *ab, u32 vdev_id); + struct ath12k *ath12k_mac_get_ar_by_pdev_id(struct ath12k_base *ab, u32 pdev_id); + +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -1857,6 +1857,109 @@ int ath12k_wmi_vdev_set_param_cmd(struct + return ret; + } + ++static void ath12k_wmi_copy_coex_config(struct ath12k *ar, struct wmi_coex_config_cmd *cmd, ++ struct coex_config_arg *coex_config) ++{ ++ switch (coex_config->config_type) { ++ case WMI_COEX_CONFIG_BTC_ENABLE: ++ cmd->coex_enable = coex_config->coex_enable; ++ ath12k_dbg(ar->ab, ATH12K_DBG_WMI, ++ "WMI coex config type %u vdev id %d" ++ " coex_enable %u\n", ++ coex_config->config_type, ++ coex_config->vdev_id, ++ coex_config->coex_enable); ++ break; ++ case WMI_COEX_CONFIG_WLAN_PKT_PRIORITY: ++ cmd->wlan_pkt_type = coex_config->wlan_pkt_type; ++ cmd->wlan_pkt_weight = coex_config->wlan_pkt_weight; ++ cmd->bt_pkt_weight = coex_config->bt_pkt_weight; ++ ath12k_dbg(ar->ab, ATH12K_DBG_WMI, ++ "WMI coex config type %u vdev id %d" ++ " wlan pkt type 0x%x wlan pkt weight %u" ++ " bt pkt weight %u\n", ++ coex_config->config_type, ++ coex_config->vdev_id, ++ coex_config->wlan_pkt_type, ++ coex_config->wlan_pkt_weight, ++ coex_config->bt_pkt_weight); ++ break; ++ case WMI_COEX_CONFIG_PTA_INTERFACE: ++ cmd->pta_num = coex_config->pta_num; ++ cmd->coex_mode = coex_config->coex_mode; ++ cmd->bt_txrx_time = coex_config->bt_txrx_time; ++ cmd->bt_priority_time = coex_config->bt_priority_time; ++ cmd->pta_algorithm = coex_config->pta_algorithm; ++ cmd->pta_priority = coex_config->pta_priority; ++ ath12k_dbg(ar->ab, ATH12K_DBG_WMI, ++ "WMI coex config type %u vdev id %d" ++ " pta num %u coex mode 0x%x" ++ " bt_txrx_time 0x%x" ++ " bt_priority_time 0x%x pta alogrithm 0x%x" ++ " pta priority 0x%x\n", ++ coex_config->config_type, ++ coex_config->vdev_id, ++ coex_config->pta_num, ++ coex_config->coex_mode, ++ coex_config->bt_txrx_time, ++ coex_config->bt_priority_time, ++ coex_config->pta_algorithm, ++ coex_config->pta_priority); ++ break; ++ case WMI_COEX_CONFIG_AP_TDM: ++ cmd->duty_cycle = coex_config->duty_cycle; ++ cmd->wlan_duration = coex_config->wlan_duration; ++ ath12k_dbg(ar->ab, ATH12K_DBG_WMI, ++ "WMI coex config type %u vdev id %d" ++ " duty_cycle %u wlan_duration %u\n", ++ coex_config->config_type, ++ coex_config->vdev_id, ++ coex_config->duty_cycle, ++ coex_config->wlan_duration); ++ break; ++ case WMI_COEX_CONFIG_FORCED_ALGO: ++ cmd->coex_algo = coex_config->coex_algo; ++ ath12k_dbg(ar->ab, ATH12K_DBG_WMI, ++ "WMI coex config type %u vdev id %d" ++ " coex_algorithm %u\n", ++ coex_config->config_type, ++ coex_config->vdev_id, ++ coex_config->coex_algo); ++ break; ++ default: ++ break; ++ } ++} ++ ++int ath12k_send_coex_config_cmd(struct ath12k *ar, ++ struct coex_config_arg *coex_config) ++{ ++ struct ath12k_pdev_wmi *wmi = ar->wmi; ++ struct wmi_coex_config_cmd *cmd; ++ struct sk_buff *skb; ++ int ret; ++ ++ skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd)); ++ if (!skb) ++ return -ENOMEM; ++ ++ cmd = (struct wmi_coex_config_cmd *)skb->data; ++ cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_COEX_CONFIG_CMD) | ++ FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); ++ ++ cmd->vdev_id = coex_config->vdev_id; ++ cmd->config_type = coex_config->config_type; ++ ath12k_wmi_copy_coex_config(ar, cmd, coex_config); ++ ++ ret = ath12k_wmi_cmd_send(wmi, skb, WMI_COEX_CONFIG_CMDID); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to send WMI_COEX_CONFIG_CMD cmd\n"); ++ dev_kfree_skb(skb); ++ } ++ ++ return ret; ++} ++ + int ath12k_wmi_send_stats_request_cmd(struct ath12k *ar, + struct stats_request_params *param) + { +@@ -4680,6 +4783,8 @@ static int ath12k_init_cmd_send(struct a + struct wmi_pdev_band_to_mac *band_to_mac; + struct wlan_host_mem_chunk *host_mem_chunks; + struct wmi_tlv *tlv; ++ struct device *dev = ab->dev; ++ bool three_way_coex_enabled = false; + size_t ret, len; + void *ptr; + u32 hw_mode_len = 0; +@@ -4704,6 +4809,10 @@ static int ath12k_init_cmd_send(struct a + ptr = skb->data + sizeof(*cmd); + cfg = ptr; + ++ three_way_coex_enabled = of_property_read_bool(dev->of_node, "qcom,btcoex"); ++ if (three_way_coex_enabled) ++ cfg->flag1 |= WMI_RSRC_CFG_FLAG1_THREE_WAY_COEX_CONFIG_OVERRIDE_SUPPORT; ++ + ath12k_wmi_copy_resource_config(cfg, param->res_cfg); + + cfg->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_RESOURCE_CONFIG, +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -2528,6 +2528,7 @@ struct wmi_init_cmd { + #define WMI_RSRC_CFG_HOST_SVC_FLAG_REO_QREF_SUPPORT_BIT 12 + #define WMI_RSRC_CFG_FLAGS2_CALC_NEXT_DTIM_COUNT_SET BIT(9) + #define WMI_RSRC_CFG_FLAGS2_INTRABSS_MEC_WDS_LEARNING_DISABLE BIT(15) ++#define WMI_RSRC_CFG_FLAG1_THREE_WAY_COEX_CONFIG_OVERRIDE_SUPPORT BIT(25) + #define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5) + + struct wmi_resource_config { +@@ -5517,6 +5518,119 @@ enum ath12k_hw_txrx_mode { + ATH12K_HW_TXRX_ETHERNET = 2, + }; + ++enum wmi_coex_config_type { ++ WMI_COEX_CONFIG_PAGE_P2P_TDM = 1, ++ WMI_COEX_CONFIG_PAGE_STA_TDM = 2, ++ WMI_COEX_CONFIG_PAGE_SAP_TDM = 3, ++ WMI_COEX_CONFIG_DURING_WLAN_CONN = 4, ++ WMI_COEX_CONFIG_BTC_ENABLE = 5, ++ WMI_COEX_CONFIG_COEX_DBG = 6, ++ WMI_COEX_CONFIG_PAGE_P2P_STA_TDM = 7, ++ WMI_COEX_CONFIG_INQUIRY_P2P_TDM = 8, ++ WMI_COEX_CONFIG_INQUIRY_STA_TDM = 9, ++ WMI_COEX_CONFIG_INQUIRY_SAP_TDM = 10, ++ WMI_COEX_CONFIG_INQUIRY_P2P_STA_TDM = 11, ++ WMI_COEX_CONFIG_TX_POWER = 12, ++ WMI_COEX_CONFIG_PTA_CONFIG = 13, ++ WMI_COEX_CONFIG_AP_TDM = 14, ++ WMI_COEX_CONFIG_WLAN_SCAN_PRIORITY = 15, ++ WMI_COEX_CONFIG_WLAN_PKT_PRIORITY = 16, ++ WMI_COEX_CONFIG_PTA_INTERFACE = 17, ++ WMI_COEX_CONFIG_THREE_WAY_COEX_RESET = 32, ++ WMI_COEX_CONFIG_THREE_WAY_COEX_START = 34, ++ /* WMI_COEX_CONFIG_FORCED_ALGO ++ * config to select coex algorithm ++ * coex_algo: select fixed coex algorithm ++ */ ++ WMI_COEX_CONFIG_FORCED_ALGO = 47, ++}; ++ ++struct coex_config_arg { ++ u32 vdev_id; ++ u32 config_type; ++ union { ++ struct { ++ u32 coex_enable; ++ }; ++ ++ struct { ++ u32 pta_num; ++ u32 coex_mode; ++ u32 bt_txrx_time; ++ u32 bt_priority_time; ++ u32 pta_algorithm; ++ u32 pta_priority; ++ }; ++ ++ struct { ++ u32 wlan_pkt_type; ++ u32 wlan_pkt_type_continued; ++ u32 wlan_pkt_weight; ++ u32 bt_pkt_weight; ++ }; ++ struct { ++ u32 duty_cycle; ++ u32 wlan_duration; ++ }; ++ struct { ++ u32 coex_algo; ++ }; ++ struct { ++ u32 priority0; ++ u32 priority1; ++ u32 priority2; ++ u32 config_arg4; ++ u32 config_arg5; ++ u32 config_arg6; ++ }; ++ }; ++}; ++ ++struct wmi_coex_config_cmd { ++ u32 tlv_header; ++ u32 vdev_id; ++ u32 config_type; ++ union { ++ struct { ++ u32 coex_enable; ++ } __packed; ++ ++ struct { ++ u32 pta_num; ++ u32 coex_mode; ++ u32 bt_txrx_time; ++ u32 bt_priority_time; ++ u32 pta_algorithm; ++ u32 pta_priority; ++ } __packed; ++ ++ struct { ++ u32 wlan_pkt_type; ++ u32 wlan_pkt_type_continued; ++ u32 wlan_pkt_weight; ++ u32 bt_pkt_weight; ++ } __packed; ++ ++ struct { ++ u32 duty_cycle; ++ u32 wlan_duration; ++ } __packed; ++ ++ struct { ++ u32 coex_algo; ++ } __packed; ++ ++ struct { ++ u32 priority0; ++ u32 priority1; ++ u32 priority2; ++ u32 config_arg4; ++ u32 config_arg5; ++ u32 config_arg6; ++ } __packed; ++ } __packed; ++} __packed; ++ + struct wmi_wmm_params { + __le32 tlv_header; + u32 cwmin; +@@ -7021,6 +7135,11 @@ int ath12k_wmi_pdev_non_srg_obss_color_e + u32 *bitmap); + int ath12k_wmi_pdev_non_srg_obss_bssid_enable_bitmap(struct ath12k *ar, + u32 *bitmap); ++int ath12k_send_coex_config_cmd(struct ath12k *ar, ++ struct coex_config_arg *coex_config); ++int ath12k_wmi_obss_color_cfg_cmd(struct ath12k *ar, u32 vdev_id, ++ u8 bss_color, u32 period, ++ bool enable); + int ath12k_wmi_obss_color_cfg_cmd(struct ath12k *ar, u32 vdev_id, + u8 bss_color, u32 period, + bool enable); +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -667,6 +667,8 @@ struct ath12k_dbg_htt_stats { + spinlock_t lock; + }; + ++#define ATH12K_MAX_COEX_PRIORITY_LEVEL 3 ++ + struct ath12k_debug { + struct dentry *debugfs_pdev; + struct ath12k_dbg_htt_stats htt_stats; +@@ -686,6 +688,7 @@ struct ath12k_debug { + struct completion wmi_ctrl_path_stats_rcvd; + u32 wmi_ctrl_path_stats_tagid; + struct dentry *debugfs_nrp; ++ u32 coex_priority_level[ATH12K_MAX_COEX_PRIORITY_LEVEL]; + }; + + int ath12k_pktlog_rx_filter_setting(struct ath12k *ar, +@@ -709,6 +712,31 @@ struct ath12k_per_peer_tx_stats { + bool is_ampdu; + }; + ++struct ath12k_btcoex_info { ++ bool coex_support; ++ u32 pta_num; ++ u32 coex_mode; ++ u32 bt_active_time_slot; ++ u32 bt_priority_time_slot; ++ u32 coex_algo_type; ++ u32 pta_priority; ++ u32 pta_algorithm; ++ u32 wlan_prio_mask; ++ u32 wlan_weight; ++ u32 bt_weight; ++ u32 duty_cycle; ++ u32 wlan_duration; ++ u32 wlan_pkt_type; ++ u32 wlan_pkt_type_continued; ++}; ++ ++enum btcoex_algo { ++ COEX_ALGO_UNCONS_FREERUN = 0, ++ COEX_ALGO_FREERUN, ++ COEX_ALGO_OCS, ++ COEX_ALGO_MAX_SUPPORTED, ++}; ++ + enum ath12k_ap_ps_state { + ATH12K_AP_PS_STATE_OFF, + ATH12K_AP_PS_STATE_ON, +@@ -860,6 +888,7 @@ struct ath12k { + /* To protect wmi_list manipulation */ + struct mutex wmi_ctrl_path_stats_lock; + /* TODO: Add mac_filter, ampdu_aggr_size and wbm_tx_completion_stats stats*/ ++ struct ath12k_btcoex_info coex; + #endif + #ifdef CPTCFG_ATH12K_SPECTRAL + struct ath12k_spectral spectral; diff --git a/feeds/ipq95xx/mac80211/patches/qca/715-ath12k-ipq5332-SSR-Recovery-Support.patch b/feeds/ipq95xx/mac80211/patches/qca/715-ath12k-ipq5332-SSR-Recovery-Support.patch new file mode 100644 index 000000000..531083db9 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/715-ath12k-ipq5332-SSR-Recovery-Support.patch @@ -0,0 +1,395 @@ +From f7fff85cada6ef82b18e707aba39e95698385cc7 Mon Sep 17 00:00:00 2001 +From: Sidhanta Sahu +Date: Fri, 24 Feb 2023 11:42:16 -0800 +Subject: [PATCH] ath12k: ipq5332 SSR Recovery Support. + +1. Implement the changes to support SSR Recovery for ipq5332 chipset. The +changes are made to support ssr recovery for ahb interfaced targets. +2. Disbaling ext_irq in core reset when the first crash is detected and avoid +disabling the irq on repeating firmware crashes. Disabling multiple +times in core reset may put the system in uninterruptible state. + +Signed-off-by: Sidhanta Sahu +--- + drivers/net/wireless/ath/ath12k/ahb.c | 23 +++- + drivers/net/wireless/ath/ath12k/ahb.h | 24 +++++ + drivers/net/wireless/ath/ath12k/core.c | 141 ++++++++++++++++++++++++- + drivers/net/wireless/ath/ath12k/core.h | 7 ++ + drivers/net/wireless/ath/ath12k/hif.h | 18 ++++ + 5 files changed, 209 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/ahb.c b/drivers/net/wireless/ath/ath12k/ahb.c +index 09adb3b..4f9f3ea 100644 +--- a/drivers/net/wireless/ath/ath12k/ahb.c ++++ b/drivers/net/wireless/ath/ath12k/ahb.c +@@ -384,6 +384,7 @@ static void ath12k_ahb_power_down(struct ath12k_base *ab) + { + struct ath12k_ahb *ab_ahb = ath12k_ahb_priv(ab); + ++ ath12k_core_wait_dump_collect(ab); + rproc_shutdown(ab_ahb->tgt_rproc); + } + +@@ -621,6 +622,24 @@ static int ath12k_ahb_map_service_to_pipe(struct ath12k_base *ab, u16 service_id + return 0; + } + ++static int ath12k_ahb_ssr_notifier_reg(struct ath12k_base *ab) ++{ ++ struct ath12k_ahb *ab_ahb = ath12k_ahb_priv(ab); ++ ++ return ath12k_rproc_register_subsys_notifier(ab_ahb->tgt_rproc->name, ++ &ab->ssr_nb, ++ &ab->atomic_ssr_nb); ++} ++ ++static int ath12k_ahb_ssr_notifier_unreg(struct ath12k_base *ab) ++{ ++ struct ath12k_ahb *ab_ahb = ath12k_ahb_priv(ab); ++ ++ return ath12k_rproc_unregister_subsys_notifier(ab_ahb->tgt_rproc->name, ++ &ab->ssr_nb, ++ &ab->atomic_ssr_nb); ++} ++ + static const struct ath12k_hif_ops ath12k_ahb_hif_ops_ipq5332 = { + .start = ath12k_ahb_start, + .stop = ath12k_ahb_stop, +@@ -633,6 +652,8 @@ static const struct ath12k_hif_ops ath12k_ahb_hif_ops_ipq5332 = { + .map_service_to_pipe = ath12k_ahb_map_service_to_pipe, + .power_down = ath12k_ahb_power_down, + .power_up = ath12k_ahb_power_up, ++ .ssr_notifier_reg = ath12k_ahb_ssr_notifier_reg, ++ .ssr_notifier_unreg = ath12k_ahb_ssr_notifier_unreg, + }; + + +@@ -913,7 +934,7 @@ static int ath12k_ahb_probe(struct platform_device *pdev) + ab = ath12k_core_alloc(&pdev->dev, sizeof(struct ath12k_ahb), + ATH12K_BUS_AHB, &ath12k_ahb_bus_params); + if (!ab) { +- dev_err(&pdev->dev, "failed to allocate ath11k base\n"); ++ dev_err(&pdev->dev, "failed to allocate ath12k base\n"); + return -ENOMEM; + } + +diff --git a/drivers/net/wireless/ath/ath12k/ahb.h b/drivers/net/wireless/ath/ath12k/ahb.h +index 9fcaf85..5efe1c4 100644 +--- a/drivers/net/wireless/ath/ath12k/ahb.h ++++ b/drivers/net/wireless/ath/ath12k/ahb.h +@@ -6,6 +6,8 @@ + #ifndef ATH12K_AHB_H + #define ATH12K_AHB_H + ++#include ++ + #include "core.h" + + #define ATH12K_AHB_RECOVERY_TIMEOUT (3 * HZ) +@@ -46,6 +48,28 @@ static inline struct ath12k_ahb *ath12k_ahb_priv(struct ath12k_base *ab) + return (struct ath12k_ahb *)ab->drv_priv; + } + ++static inline int ath12k_rproc_register_subsys_notifier(const char *name, ++ struct notifier_block *nb, ++ struct notifier_block *atomic_nb) ++{ ++#ifdef CONFIG_REMOTEPROC ++ return rproc_register_subsys_notifier(name, nb, atomic_nb); ++#else ++ return -ENODEV; ++#endif ++} ++ ++static inline int ath12k_rproc_unregister_subsys_notifier(const char *name, ++ struct notifier_block *nb, ++ struct notifier_block *atomic_nb) ++{ ++#ifdef CONFIG_REMOTEPROC ++ return rproc_unregister_subsys_notifier(name, nb, atomic_nb); ++#else ++ return -ENODEV; ++#endif ++} ++ + static const struct ath12k_bus_params ath12k_ahb_bus_params = { + .fixed_bdf_addr = false, + .fixed_mem_region = true, +diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c +index 56e3892..b98036e 100644 +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -9,6 +9,8 @@ + #include + #include + #include ++#include ++ + #include "core.h" + #include "coredump.h" + #include "dp_tx.h" +@@ -1290,13 +1292,115 @@ err_firmware_stop: + return ret; + } + ++#define ATH12K_COLLECT_DUMP_TIMEOUT (90 * HZ) ++ ++void ath12k_core_wait_dump_collect(struct ath12k_base *ab) ++{ ++ int timeout; ++ ++ if (ab->collect_dump) { ++ timeout = wait_event_timeout(ab->ssr_dump_wq, ++ (ab->collect_dump == false), ++ ATH12K_COLLECT_DUMP_TIMEOUT); ++ if (timeout <= 0) ++ ath12k_warn(ab, "dump collection timed out\n"); ++ } ++ return; ++} ++EXPORT_SYMBOL(ath12k_core_wait_dump_collect); ++ ++/* Print the driver stats and crash the system on receiving this notification */ ++static int ath12k_core_ssr_notifier_cb(struct notifier_block *nb, ++ const unsigned long event, ++ void *data) ++{ ++ struct ath12k_base *ab = container_of(nb, struct ath12k_base, ssr_nb); ++ ++ if (ab->collect_dump && (event == SUBSYS_AFTER_POWERUP)) { ++ ab->collect_dump = false; ++ wake_up(&ab->ssr_dump_wq); ++ return NOTIFY_OK; ++ } ++ ++ return NOTIFY_DONE; ++} ++ ++/* Print the driver stats and crash the system on receiving this notification */ ++static int ath12k_core_atomic_ssr_notifier_cb(struct notifier_block *nb, ++ const unsigned long event, ++ void *data) ++{ ++ struct ath12k_base *ab = container_of(nb, struct ath12k_base, atomic_ssr_nb); ++ struct device *dev = ab->dev; ++ bool multi_pd_arch = false; ++ phandle rproc_phandle; ++ struct device_node *rproc_node = NULL; ++ struct platform_device *pdev = NULL; ++ struct platform_device *ssr_pdev = (struct platform_device *)data; ++ ++ if (event != SUBSYS_PREPARE_FOR_FATAL_SHUTDOWN) ++ return NOTIFY_DONE; ++ ++ ab->collect_dump = true; ++ ++ if (!test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags)) ++ return NOTIFY_DONE; ++ ++ /* Print the stats and do recover only if notification is received ++ * for expected PD. Currently, there's only one PD for which below code ++ * may not necessary. It's just added as a sanity check incase ++ * core-BSP code base is modified and impacted this function. ++ * However, below code will needed review when there will be ++ * multi pd architecture. ++ */ ++ multi_pd_arch = of_property_read_bool(dev->of_node, "qcom,multipd_arch"); ++ if (multi_pd_arch) { ++ if (of_property_read_u32(dev->of_node, "qcom,rproc", ++ &rproc_phandle)) ++ return NOTIFY_DONE; ++ rproc_node = of_find_node_by_phandle(rproc_phandle); ++ if (!rproc_node) { ++ ath12k_warn(ab, "ssr notification failed to get rproc_node\n"); ++ return NOTIFY_DONE; ++ } ++ pdev = of_find_device_by_node(rproc_node); ++ if (!pdev) { ++ ath12k_warn(ab, "Failed to get pdev from device node\n"); ++ return NOTIFY_DONE; ++ } ++ if (strcmp(ssr_pdev->name, pdev->name) != 0) { ++ ath12k_warn(ab, "SSR notification mismatch %s pdev name:%s\n", ++ (char *)data, pdev->name); ++ return NOTIFY_DONE; ++ } ++ } ++ ++ if (!(test_bit(ATH12K_FLAG_UNREGISTERING, &ab->ag->dev_flags))) { ++ set_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags); ++ set_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags); ++ queue_work(ab->workqueue_aux, &ab->reset_work); ++ } ++ ++ ath12k_hal_dump_srng_stats(ab); ++ /* TODO Add more driver stats */ ++ ++ ath12k_qmi_free_target_mem_chunk(ab); ++ ++ /* Crash the system once all the stats are dumped */ ++ if (!ab->fw_recovery_support) ++ BUG_ON(1); ++ ++ ath12k_dbg(ab, ATH12K_DBG_BOOT, "reset started\n"); ++ ++ return NOTIFY_OK; ++} ++ + static int ath12k_core_reconfigure_on_crash(struct ath12k_base *ab) + { + int ret; + + mutex_lock(&ab->core_lock); + ath12k_core_pdev_deinit(ab); +- ath12k_hif_irq_disable(ab); + ath12k_dp_pdev_free(ab); + ath12k_hif_stop(ab); + ath12k_wmi_detach(ab); +@@ -1307,6 +1411,7 @@ static int ath12k_core_reconfigure_on_crash(struct ath12k_base *ab) + ath12k_hal_srng_deinit(ab); + + ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS)) - 1; ++ ab->num_db_cap = 0; + + ret = ath12k_hal_srng_init(ab); + if (ret) +@@ -1559,6 +1664,10 @@ static void ath12k_core_reset(struct work_struct *work) + ab->recovery_start_time = jiffies; + + mutex_lock(&ag->mutex_lock); ++ ++ if (!ab->is_reset) ++ ath12k_hif_irq_disable(ab); ++ + ab->is_reset = true; + atomic_set(&ab->recovery_count, 0); + +@@ -1591,8 +1700,13 @@ static void ath12k_core_reset(struct work_struct *work) + + /* reset host fixed mem off to zero */ + ab->host_ddr_fixed_mem_off = 0; +- /* prepare coredump */ +- ath12k_coredump_download_rddm(ab); ++ ++ /* prepare coredump when bus is PCI ++ * In case of AHB, the coredump occurs in rproc module ++ */ ++ if (ab->hif.bus == ATH12K_BUS_PCI) { ++ ath12k_coredump_download_rddm(ab); ++ } + + if (ab->fw_recovery_support) { + ath12k_hif_power_down(ab); +@@ -1673,6 +1787,17 @@ int ath12k_core_init(struct ath12k_base *ab) + u8 num_ab; + int ret; + ++ /* Register a notifier after core init ++ * to be called on fw crash ++ */ ++ ab->ssr_nb.notifier_call = ath12k_core_ssr_notifier_cb; ++ ab->atomic_ssr_nb.notifier_call = ath12k_core_atomic_ssr_notifier_cb; ++ ret = ath12k_hif_ssr_notifier_reg(ab); ++ if (ret) { ++ ath12k_err(ab, "failed to register ssr notifier callback\n"); ++ return ret; ++ } ++ + ret = ath12k_debugfs_soc_create(ab); + if (ret) { + ath12k_err(ab, "failed to create debugfs\n"); +@@ -1820,6 +1945,7 @@ static void ath12k_core_hw_group_stop(struct ath12k_hw_group *ag) + void ath12k_core_deinit(struct ath12k_base *ab) + { + struct ath12k_hw_group *ag = ab->ag; ++ int ret; + + mutex_lock(&ag->mutex_lock); + +@@ -1837,6 +1963,14 @@ void ath12k_core_deinit(struct ath12k_base *ab) + } + + ath12k_debugfs_soc_destroy(ab); ++ ++ /* Unregister the ssr notifier as we are not intersted ++ * in receving these notifications after mac is unregistered. ++ */ ++ ret = ath12k_hif_ssr_notifier_unreg(ab); ++ if (ret) ++ ath12k_err(ab, "failed to un-register ssr notifier callback\n"); ++ + __ath12k_core_put_hw_group(ab); + + mutex_unlock(&ag->mutex_lock); +@@ -1881,6 +2015,7 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size, + init_waitqueue_head(&ab->peer_mapping_wq); + init_waitqueue_head(&ab->wmi_ab.tx_credits_wq); + init_waitqueue_head(&ab->qmi.cold_boot_waitq); ++ init_waitqueue_head(&ab->ssr_dump_wq); + INIT_WORK(&ab->restart_work, ath12k_core_restart); + INIT_WORK(&ab->reset_work, ath12k_core_reset); + timer_setup(&ab->rx_replenish_retry, ath12k_ce_rx_replenish_retry, 0); +diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h +index e9413bc..6f29879 100644 +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -1211,6 +1211,10 @@ struct ath12k_base { + atomic_t reset_count; + bool is_reset; + struct completion reset_complete; ++ wait_queue_head_t ssr_dump_wq; ++ bool collect_dump; ++ struct notifier_block ssr_nb; ++ struct notifier_block atomic_ssr_nb; + struct completion reconfigure_complete; + unsigned long reset_fail_timeout; + /* continuous recovery fail count */ +@@ -1400,6 +1404,9 @@ void ath12k_core_put_hw_group(struct ath12k_base *ab); + + const struct firmware *ath12k_core_firmware_request(struct ath12k_base *ab, + const char *filename); ++ ++void ath12k_core_wait_dump_collect(struct ath12k_base *ab); ++ + void ath12k_fw_stats_init(struct ath12k *ar); + void ath12k_fw_stats_pdevs_free(struct list_head *head); + void ath12k_fw_stats_bcn_free(struct list_head *head); +diff --git a/drivers/net/wireless/ath/ath12k/hif.h b/drivers/net/wireless/ath/ath12k/hif.h +index 8c12f24..805b139 100644 +--- a/drivers/net/wireless/ath/ath12k/hif.h ++++ b/drivers/net/wireless/ath/ath12k/hif.h +@@ -32,6 +32,8 @@ struct ath12k_hif_ops { + void (*ce_irq_enable)(struct ath12k_base *ab); + void (*ce_irq_disable)(struct ath12k_base *ab); + void (*get_ce_msi_idx)(struct ath12k_base *ab, u32 ce_id, u32 *msi_idx); ++ int (*ssr_notifier_reg)(struct ath12k_base *ab); ++ int (*ssr_notifier_unreg)(struct ath12k_base *ab); + }; + + static inline int ath12k_hif_map_service_to_pipe(struct ath12k_base *ab, u16 service_id, +@@ -74,6 +76,22 @@ static inline void ath12k_hif_get_ce_msi_idx(struct ath12k_base *ab, u32 ce_id, + *msi_data_idx = ce_id; + } + ++static inline int ath12k_hif_ssr_notifier_reg(struct ath12k_base *ab) ++{ ++ if (!ab->hif.ops->ssr_notifier_reg) ++ return 0; ++ ++ return ab->hif.ops->ssr_notifier_reg(ab); ++} ++ ++static inline int ath12k_hif_ssr_notifier_unreg(struct ath12k_base *ab) ++{ ++ if (!ab->hif.ops->ssr_notifier_unreg) ++ return 0; ++ ++ return ab->hif.ops->ssr_notifier_unreg(ab); ++} ++ + static inline void ath12k_hif_ce_irq_enable(struct ath12k_base *ab) + { + if (ab->hif.ops->ce_irq_enable) +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/715-b-ath12k-Update-link-id-after-op-supports.patch b/feeds/ipq95xx/mac80211/patches/qca/715-b-ath12k-Update-link-id-after-op-supports.patch new file mode 100644 index 000000000..1c437a966 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/715-b-ath12k-Update-link-id-after-op-supports.patch @@ -0,0 +1,47 @@ +From 5216a85658a0076cfc35d59449afba548c3b042c Mon Sep 17 00:00:00 2001 +From: Rajat Soni +Date: Fri, 24 Feb 2023 14:10:07 +0530 +Subject: [PATCH] ath12k: Update link id after op supports + +arsta ptr is NULL within ath12k_mac_op_sta_rc_update() +though sta and arvif is valid. + +The station is associated on link1 and link id 0 is +hardcoded in ath12k_mac_op_sta_rc_update. + +Handling rc update for STA based on link id needs to be supported. + +Signed-off-by: Rajat Soni +--- + drivers/net/wireless/ath/ath12k/mac.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -7019,7 +7019,7 @@ static void ath12k_mac_op_sta_set_4addr( + static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, +- u32 changed) ++ u32 changed, u8 link_id) + { + struct ath12k *ar; + struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; +@@ -7028,12 +7028,15 @@ static void ath12k_mac_op_sta_rc_update( + struct ath12k_link_sta *arsta; + struct ath12k_peer *peer; + u32 bw, smps; +- /* TODO update link id after op supports */ +- u8 link_id = 0; + + arvif = ahvif->link[link_id]; + arsta = ahsta->link[link_id]; + ++ if (!arsta) { ++ ath12k_err(NULL, "unable to determine arsta\n"); ++ return; ++ } ++ + if (!arvif) { + ath12k_err(NULL, "unable to determine device for sta update\n"); + return; diff --git a/feeds/ipq95xx/mac80211/patches/qca/715-c-ath11k-Add-link-id-argument.patch b/feeds/ipq95xx/mac80211/patches/qca/715-c-ath11k-Add-link-id-argument.patch new file mode 100644 index 000000000..d7f79a9a1 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/715-c-ath11k-Add-link-id-argument.patch @@ -0,0 +1,23 @@ +From 201cbb47c39fb1780c0dc61974171289b1d1497f Mon Sep 17 00:00:00 2001 +From: Rajat Soni +Date: Fri, 24 Feb 2023 14:28:03 +0530 +Subject: [PATCH] ath11k: Add link id argument + +Add link id argument to avoid compilation issue. + +Signed-off-by: Rajat Soni +--- + drivers/net/wireless/ath/ath11k/mac.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -6362,7 +6362,7 @@ static void ath11k_mac_op_sta_set_4addr( + static void ath11k_mac_op_sta_rc_update(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, +- u32 changed) ++ u32 changed, u8 link_id) + { + struct ath11k *ar = hw->priv; + struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv; diff --git a/feeds/ipq95xx/mac80211/patches/qca/715-d-ath10k-Add-link-id-argument.patch b/feeds/ipq95xx/mac80211/patches/qca/715-d-ath10k-Add-link-id-argument.patch new file mode 100644 index 000000000..7ce3b0f71 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/715-d-ath10k-Add-link-id-argument.patch @@ -0,0 +1,23 @@ +From 0fcc4c87830b391806ce6f9e4e278f0c324cd3ca Mon Sep 17 00:00:00 2001 +From: Rajat Soni +Date: Fri, 24 Feb 2023 14:29:11 +0530 +Subject: [PATCH] ath10k: Add link id argument + +Add link id argument to avoid compilation issue. + +Signed-off-by: Rajat Soni +--- + drivers/net/wireless/ath/ath10k/mac.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -8501,7 +8501,7 @@ exit: + static void ath10k_sta_rc_update(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, +- u32 changed) ++ u32 changed, u8 link_id) + { + struct ath10k *ar = hw->priv; + struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; diff --git a/feeds/ipq95xx/mac80211/patches/qca/715-e-ath9k-Add-link-id-argument.patch b/feeds/ipq95xx/mac80211/patches/qca/715-e-ath9k-Add-link-id-argument.patch new file mode 100644 index 000000000..358380979 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/715-e-ath9k-Add-link-id-argument.patch @@ -0,0 +1,24 @@ +From 79e54694b8c8f33a32b7c0a7d891f5310e7bb2a4 Mon Sep 17 00:00:00 2001 +From: Rajat Soni +Date: Fri, 24 Feb 2023 14:30:27 +0530 +Subject: [PATCH] ath9k: Add link id argument + +Add link id argument to avoid compilation issue. + +Signed-off-by: Rajat Soni +--- + drivers/net/wireless/ath/ath9k/htc_drv_main.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c ++++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c +@@ -1358,7 +1358,8 @@ static int ath9k_htc_sta_remove(struct i + + static void ath9k_htc_sta_rc_update(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, +- struct ieee80211_sta *sta, u32 changed) ++ struct ieee80211_sta *sta, u32 changed, ++ u8 link_id) + { + struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv; + diff --git a/feeds/ipq95xx/mac80211/patches/qca/715-wifi-ath12k-Add-Dynamic-VLAN-support.patch b/feeds/ipq95xx/mac80211/patches/qca/715-wifi-ath12k-Add-Dynamic-VLAN-support.patch new file mode 100644 index 000000000..e171d76ea --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/715-wifi-ath12k-Add-Dynamic-VLAN-support.patch @@ -0,0 +1,413 @@ +From 3fe2ac33f0d0f7a9c305943f127eb11c6f871ba8 Mon Sep 17 00:00:00 2001 +From: Muna Sinada +Date: Tue, 7 Feb 2023 07:38:58 -0800 +Subject: [PATCH] wifi: ath12k: Add Dynamic VLAN support + +Add support for dynamic VLAN. VLAN group traffic is encrypted in +mac80211 and driver needs to add metadata for the SW encrypted vlan group +traffic. + +Signed-off-by: Muna Sinada +--- + drivers/net/wireless/ath/ath12k/dp_tx.c | 71 +++++++++++- + drivers/net/wireless/ath/ath12k/dp_tx.h | 198 ++++++++++++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/mac.c | 3 + + 3 files changed, 270 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -117,6 +117,43 @@ static void ath12k_hal_tx_cmd_ext_desc_s + HAL_TX_MSDU_EXT_INFO1_ENCRYPT_TYPE); + } + ++#define HTT_META_DATA_ALIGNMENT 0x8 ++ ++static int ath12k_dp_metadata_align_skb(struct sk_buff *skb, u8 align_len) ++{ ++ if (unlikely(skb_cow_head(skb, align_len))) ++ return -ENOMEM; ++ ++ skb_push(skb, align_len); ++ memset(skb->data, 0, align_len); ++ return 0; ++} ++ ++static int ath12k_dp_prepare_htt_metadata(struct sk_buff *skb, ++ u8 *htt_metadata_size) ++{ ++ u8 htt_desc_size; ++ /* Size rounded of multiple of 8 bytes */ ++ u8 htt_desc_size_aligned; ++ int ret; ++ struct htt_tx_msdu_desc_ext *desc_ext; ++ ++ htt_desc_size = sizeof(struct htt_tx_msdu_desc_ext); ++ htt_desc_size_aligned = ALIGN(htt_desc_size, HTT_META_DATA_ALIGNMENT); ++ ++ ret = ath12k_dp_metadata_align_skb(skb, htt_desc_size_aligned); ++ if (unlikely(ret)) ++ return ret; ++ ++ desc_ext = (struct htt_tx_msdu_desc_ext *)skb->data; ++ desc_ext->valid_encrypt_type = 1; ++ desc_ext->encrypt_type = HAL_ENCRYPT_TYPE_WEP_40; ++ desc_ext->host_tx_desc_pool = 1; ++ *htt_metadata_size = htt_desc_size_aligned; ++ ++ return 0; ++} ++ + int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif, + struct ath12k_sta *ahsta, struct sk_buff *skb) + { +@@ -141,6 +178,8 @@ int ath12k_dp_tx(struct ath12k *ar, stru + bool tcl_ring_retry; + u16 peer_id; + bool msdu_ext_desc = false; ++ bool is_diff_encap = false; ++ u8 align_pad, htt_meta_size = 0; + + if (unlikely(test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))) + return -ESHUTDOWN; +@@ -224,7 +263,11 @@ tcl_ring_sel: + + switch (ti.encap_type) { + case HAL_TCL_ENCAP_TYPE_NATIVE_WIFI: +- ath12k_dp_tx_encap_nwifi(skb); ++ if ((ahvif->vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED) && ++ skb->protocol == cpu_to_be16(ETH_P_PAE)) ++ is_diff_encap = true; ++ else ++ ath12k_dp_tx_encap_nwifi(skb); + break; + case HAL_TCL_ENCAP_TYPE_RAW: + if (!test_bit(ATH12K_FLAG_RAW_MODE, &ag->dev_flags)) { +@@ -243,14 +286,6 @@ tcl_ring_sel: + goto fail_remove_tx_buf; + } + +- ti.paddr = dma_map_single(ab->dev, skb->data, skb->len, DMA_TO_DEVICE); +- if (unlikely(dma_mapping_error(ab->dev, ti.paddr))) { +- atomic_inc(&ab->soc_stats.tx_err.misc_fail); +- ath12k_warn(ab, "failed to DMA map data Tx buffer\n"); +- ret = -ENOMEM; +- goto fail_remove_tx_buf; +- } +- + if (unlikely((ahvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_ETHERNET && + !(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)))) { + msdu_ext_desc = true; +@@ -279,10 +314,40 @@ tcl_ring_sel: + } + } + ++ /* Add metadata for sw encrypted vlan group traffic */ ++ if ((!test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->ag->dev_flags) && ++ !(info->control.flags & IEEE80211_TX_CTL_HW_80211_ENCAP) && ++ !info->control.hw_key && ieee80211_has_protected(hdr->frame_control)) || ++ is_diff_encap) { ++ align_pad = ((unsigned long)skb->data) & (HTT_META_DATA_ALIGNMENT - 1); ++ ret = ath12k_dp_metadata_align_skb(skb, align_pad); ++ if (unlikely(ret)) ++ goto fail_remove_tx_buf; ++ ++ ti.pkt_offset += align_pad; ++ ret = ath12k_dp_prepare_htt_metadata(skb, &htt_meta_size); ++ if (unlikely(ret)) ++ goto fail_remove_tx_buf; ++ ++ ti.pkt_offset += htt_meta_size; ++ ti.meta_data_flags |= HTT_TCL_META_DATA_VALID_HTT; ++ ti.flags0 |= FIELD_PREP(HAL_TCL_DATA_CMD_INFO2_TO_FW, 1); ++ ti.encap_type = HAL_TCL_ENCAP_TYPE_RAW; ++ ti.encrypt_type = HAL_ENCRYPT_TYPE_OPEN; ++ } ++ ++ ti.paddr = dma_map_single(ab->dev, skb->data, skb->len, DMA_TO_DEVICE); ++ if (unlikely(dma_mapping_error(ab->dev, ti.paddr))) { ++ atomic_inc(&ab->soc_stats.tx_err.misc_fail); ++ ath12k_warn(ab, "failed to DMA map data Tx buffer\n"); ++ ret = -ENOMEM; ++ goto fail_remove_tx_buf; ++ } ++ + tx_desc->skb = skb; + tx_desc->mac_id = ar->pdev_idx; + ti.desc_id = tx_desc->desc_id; +- ti.data_len = skb->len; ++ ti.data_len = skb->len - ti.pkt_offset; + skb_cb->paddr = ti.paddr; + skb_cb->vif = ahvif->vif; + skb_cb->ar = ar; +@@ -373,6 +438,9 @@ fail_unmap_dma: + + fail_remove_tx_buf: + ath12k_dp_tx_release_txbuf(dp, tx_desc, ti.ring_id); ++ if (ti.pkt_offset) ++ skb_pull(skb, ti.pkt_offset); ++ + if (tcl_ring_retry) + goto tcl_ring_sel; + +--- a/drivers/net/wireless/ath/ath12k/dp_tx.h ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.h +@@ -15,6 +15,204 @@ struct ath12k_dp_htt_wbm_tx_status { + int ack_rssi; + }; + ++/* htt_tx_msdu_desc_ext ++ * ++ * valid_pwr ++ * if set, tx pwr spec is valid ++ * ++ * valid_mcs_mask ++ * if set, tx MCS mask is valid ++ * ++ * valid_nss_mask ++ * if set, tx Nss mask is valid ++ * ++ * valid_preamble_type ++ * if set, tx preamble spec is valid ++ * ++ * valid_retries ++ * if set, tx retries spec is valid ++ * ++ * valid_bw_info ++ * if set, tx dyn_bw and bw_mask are valid ++ * ++ * valid_guard_interval ++ * if set, tx guard intv spec is valid ++ * ++ * valid_chainmask ++ * if set, tx chainmask is valid ++ * ++ * valid_encrypt_type ++ * if set, encrypt type is valid ++ * ++ * valid_key_flags ++ * if set, key flags is valid ++ * ++ * valid_expire_tsf ++ * if set, tx expire TSF spec is valid ++ * ++ * valid_chanfreq ++ * if set, chanfreq is valid ++ * ++ * is_dsrc ++ * if set, MSDU is a DSRC frame ++ * ++ * guard_interval ++ * 0.4us, 0.8us, 1.6us, 3.2us ++ * ++ * encrypt_type ++ * 0 = NO_ENCRYPT, ++ * 1 = ENCRYPT, ++ * 2 ~ 3 - Reserved ++ * ++ * retry_limit ++ * Specify the maximum number of transmissions, including the ++ * initial transmission, to attempt before giving up if no ack ++ * is received. ++ * If the tx rate is specified, then all retries shall use the ++ * same rate as the initial transmission. ++ * If no tx rate is specified, the target can choose whether to ++ * retain the original rate during the retransmissions, or to ++ * fall back to a more robust rate. ++ * ++ * use_dcm_11ax ++ * If set, Use Dual subcarrier modulation. ++ * Valid only for 11ax preamble types HE_SU ++ * and HE_EXT_SU ++ * ++ * ltf_subtype_11ax ++ * Takes enum values of htt_11ax_ltf_subtype_t ++ * Valid only for 11ax preamble types HE_SU ++ * and HE_EXT_SU ++ * ++ * dyn_bw ++ * 0 = static bw, 1 = dynamic bw ++ * ++ * bw_mask ++ * Valid only if dyn_bw == 0 (static bw). ++ * ++ * host_tx_desc_pool ++ * If set, Firmware allocates tx_descriptors ++ * in WAL_BUFFERID_TX_HOST_DATA_EXP,instead ++ * of WAL_BUFFERID_TX_TCL_DATA_EXP. ++ * Use cases: ++ * Any time firmware uses TQM-BYPASS for Data ++ * TID, firmware expect host to set this bit. ++ * ++ * power ++ * unit of the power field is 0.5 dbm ++ * signed value ranging from -64dbm to 63.5 dbm ++ * ++ * mcs_mask ++ * mcs bit mask of 0 ~ 11 ++ * Setting more than one MCS isn't currently ++ * supported by the target (but is supported ++ * in the interface in case in the future ++ * the target supports specifications of ++ * a limited set of MCS values. ++ * ++ * nss_mask ++ * Nss bit mask 0 ~ 7 ++ * Setting more than one Nss isn't currently ++ * supported by the target (but is supported ++ * in the interface in case in the future ++ * the target supports specifications of ++ * a limited set of Nss values. ++ * ++ * pream_type ++ * Preamble types ++ * ++ * update_peer_cache ++ * When set these custom values will be ++ * used for all packets, until the next ++ * update via this ext header. ++ * This is to make sure not all packets ++ * need to include this header. ++ * ++ * chain_mask ++ * specify which chains to transmit from ++ * ++ * key_flags ++ * Key Index and related flags - used in mesh mode ++ * ++ * chanfreq ++ * Channel frequency: This identifies the desired channel ++ * frequency (in MHz) for tx frames. This is used by FW to help ++ * determine when it is safe to transmit or drop frames for ++ * off-channel operation. ++ * The default value of zero indicates to FW that the corresponding ++ * VDEV's home channel (if there is one) is the desired channel ++ * frequency. ++ * ++ * expire_tsf_lo ++ * tx expiry time (TSF) LSBs ++ * ++ * expire_tsf_hi ++ * tx expiry time (TSF) MSBs ++ * ++ * learning_frame ++ * When this flag is set, this frame will be dropped by FW ++ * rather than being enqueued to the Transmit Queue Manager (TQM) HW. ++ * ++ * send_as_standalone ++ * This will indicate if the msdu needs to be sent as a singleton PPDU, ++ * i.e. with no A-MSDU or A-MPDU aggregation. ++ * The scope is extended to other use-cases. ++ * ++ * is_host_opaque_valid ++ * set this bit to 1 if the host_opaque_cookie is populated ++ * with valid information. ++ * ++ * host_opaque_cookie ++ * Host opaque cookie for special frames ++ */ ++ ++struct htt_tx_msdu_desc_ext { ++ u32 ++ valid_pwr : 1, ++ valid_mcs_mask : 1, ++ valid_nss_mask : 1, ++ valid_preamble_type : 1, ++ valid_retries : 1, ++ valid_bw_info : 1, ++ valid_guard_interval : 1, ++ valid_chainmask : 1, ++ valid_encrypt_type : 1, ++ valid_key_flags : 1, ++ valid_expire_tsf : 1, ++ valid_chanfreq : 1, ++ is_dsrc : 1, ++ guard_interval : 2, ++ encrypt_type : 2, ++ retry_limit : 4, ++ use_dcm_11ax : 1, ++ ltf_subtype_11ax : 2, ++ dyn_bw : 1, ++ bw_mask : 6, ++ host_tx_desc_pool : 1; ++ u32 ++ power : 8, ++ mcs_mask : 12, ++ nss_mask : 8, ++ pream_type : 3, ++ update_peer_cache : 1; ++ u32 ++ chain_mask : 8, ++ key_flags : 8, ++ chanfreq : 16; ++ ++ u32 expire_tsf_lo; ++ u32 expire_tsf_hi; ++ ++ u32 ++ learning_frame : 1, ++ send_as_standalone : 1, ++ is_host_opaque_valid : 1, ++ rsvd0 : 29; ++ u32 ++ host_opaque_cookie : 16, ++ rsvd1 : 16; ++} __packed; ++ + void ath12k_dp_tx_update_txcompl(struct ath12k *ar, struct hal_tx_status *ts); + int ath12k_dp_tx_htt_h2t_ver_req_msg(struct ath12k_base *ab); + int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif, +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -14266,6 +14266,9 @@ static int __ath12k_mac_register(struct + ar->max_num_stations = TARGET_NUM_STATIONS; + ar->max_num_peers = TARGET_NUM_PEERS_PDEV; + ++ hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); ++ hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN); ++ + if (cap->nss_ratio_enabled) + ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW); + +--- a/net/mac80211/chan.c ++++ b/net/mac80211/chan.c +@@ -2049,6 +2049,9 @@ void ieee80211_link_vlan_copy_chanctx(st + conf = rcu_dereference_protected(ap_conf->chanctx_conf, + lockdep_is_held(&local->chanctx_mtx)); + rcu_assign_pointer(link_conf->chanctx_conf, conf); ++ memcpy(&sdata->vif.link_conf[link_id]->chandef, ++ &ap->vif.link_conf[link_id]->chandef, ++ sizeof(struct cfg80211_chan_def)); + rcu_read_unlock(); + mutex_unlock(&local->chanctx_mtx); + } +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -2692,8 +2692,15 @@ static struct sk_buff *ieee80211_build_h + ap_sdata = container_of(sdata->bss, + struct ieee80211_sub_if_data, + u.ap); +- chanctx_conf = +- rcu_dereference(ap_sdata->vif.bss_conf.chanctx_conf); ++ ++ /* TODO: change index of link_conf[] to link id of corresponding ++ * AP for MLO cases */ ++ if (ap_sdata->vif.valid_links) ++ chanctx_conf = ++ rcu_dereference(ap_sdata->vif.link_conf[0]->chanctx_conf); ++ else ++ chanctx_conf = ++ rcu_dereference(ap_sdata->vif.bss_conf.chanctx_conf); + } + if (sdata->wdev.use_4addr) + break; +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -4737,7 +4737,7 @@ static int nl80211_validate_key_link_id( + GENL_SET_ERR_MSG(info, "invalid link ID for MLO group key"); + return -EINVAL; + } +- } else if (link_id != -1) { ++ } else if (link_id != -1 && wdev->iftype != NL80211_IFTYPE_AP_VLAN) { + GENL_SET_ERR_MSG(info, "link ID not allowed for non-MLO group key"); + return -EINVAL; + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/715-wifi-ath12k-Modified-the-peer-id-bit-mask-in-monitor.patch b/feeds/ipq95xx/mac80211/patches/qca/715-wifi-ath12k-Modified-the-peer-id-bit-mask-in-monitor.patch new file mode 100644 index 000000000..d5ffd02de --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/715-wifi-ath12k-Modified-the-peer-id-bit-mask-in-monitor.patch @@ -0,0 +1,75 @@ +From 7b0df439f96415c1cd72f3dad5a32492df254d96 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Fri, 17 Feb 2023 16:18:45 +0530 +Subject: [PATCH] wifi: ath12k: Modified the peer id bit mask in monitor path + +In Rx monitor path, the sw peer id treats as peer id. Which is causing +peer id lookup fail in PPDU user stats processing. So not able to +show the ext_rx_stats to user. sw peer id has both chip id and peer id +values. In non-ML case, the chip id report as zero always. so no issue. +But in ML case, it has valid chip id information which casuing the peer +lookup fail. So fix this issue by extracting only peer id information +from the sw peer id. + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/dp_mon.c | 30 ++++++++++++++++++------ + drivers/net/wireless/ath/ath12k/hal_rx.h | 8 ++++--- + drivers/net/wireless/ath/ath12k/peer.c | 9 +++++++ + 3 files changed, 37 insertions(+), 10 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/dp_mon.c ++++ b/drivers/net/wireless/ath/ath12k/dp_mon.c +@@ -3751,8 +3751,8 @@ move_next: + peer = ath12k_peer_find_by_id(ab, ppdu_info->peer_id); + if (!peer || !peer->sta) { + ath12k_dbg(ab, ATH12K_DBG_DATA, +- "failed to find the peer with peer_id %d\n", +- ppdu_info->peer_id); ++ "failed to find the peer with link id %d peer_id %d\n", ++ peer ? peer->link_id : -1, ppdu_info->peer_id); + goto next_skb; + } + +@@ -3914,8 +3914,8 @@ move_next: + peer = ath12k_peer_find_by_id(ab, ppdu_info->peer_id); + if (!peer || !peer->sta) { + ath12k_dbg(ab, ATH12K_DBG_DATA, +- "failed to find the peer with monitor peer_id %d\n", +- ppdu_info->peer_id); ++ "failed to find the peer with monitor link id %d peer_id %d\n", ++ peer ? peer->link_id : -1, ppdu_info->peer_id); + goto next_skb; + } + +--- a/drivers/net/wireless/ath/ath12k/hal_rx.h ++++ b/drivers/net/wireless/ath/ath12k/hal_rx.h +@@ -19,7 +19,7 @@ struct hal_rx_wbm_rel_info { + bool hw_cc_done; + }; + +-#define HAL_INVALID_PEERID 0xffff ++#define HAL_INVALID_PEERID 0x3fff + #define VHT_SIG_SU_NSS_MASK 0x7 + + #define HAL_RX_MAX_MCS 12 +@@ -303,7 +303,8 @@ struct hal_rx_ppdu_start { + __le32 reserverd[2]; + } __packed; + +-#define HAL_RX_PPDU_END_USER_STATS_INFO0_PEER_ID GENMASK(15, 0) ++#define HAL_RX_PPDU_END_USER_STATS_INFO0_PEER_ID GENMASK(13, 0) ++#define HAL_RX_PPDU_END_USER_STATS_INFO0_CHIP_ID GENMASK(15, 14) + #define HAL_RX_PPDU_END_USER_STATS_INFO0_MPDU_CNT_FCS_ERR GENMASK(26, 16) + + #define HAL_RX_PPDU_END_USER_STATS_INFO1_MPDU_CNT_FCS_OK GENMASK(10, 0) +@@ -510,7 +511,8 @@ struct hal_rx_phyrx_rssi_legacy_info { + } __packed; + + #define HAL_RX_MPDU_START_INFO0_PPDU_ID GENMASK(31, 16) +-#define HAL_RX_MPDU_START_INFO1_PEERID GENMASK(31, 16) ++#define HAL_RX_MPDU_START_INFO1_PEERID GENMASK(29, 16) ++#define HAL_RX_MPDU_START_INFO1_CHIPID GENMASK(31, 30) + #define HAL_RX_MPDU_START_INFO2_MPDU_LEN GENMASK(13, 0) + struct hal_rx_mpdu_start { + __le32 rsvd0[9]; diff --git a/feeds/ipq95xx/mac80211/patches/qca/716-001-wifi-cfg80211-Add-new-attribute-to-pass-TX-link-id-of-MLO.patch b/feeds/ipq95xx/mac80211/patches/qca/716-001-wifi-cfg80211-Add-new-attribute-to-pass-TX-link-id-of-MLO.patch new file mode 100644 index 000000000..426d6ff99 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/716-001-wifi-cfg80211-Add-new-attribute-to-pass-TX-link-id-of-MLO.patch @@ -0,0 +1,109 @@ +From 0994588eeb523f375745c2b5189ea82f1e6df6e3 Mon Sep 17 00:00:00 2001 +From: Rameshkumar Sundaram +Date: Sat, 4 Mar 2023 11:44:34 +0530 +Subject: [PATCH 1/4] wifi : cfg80211 : Add new attribute to pass TX link id of + MLO MBSSID + +For MLD if transmitting link of an MBSSID group is part of MLD then +link id of TX link BSS along with TX interface index has +to be specified to map non-tx link with right tx link of tx MLD. +Add new MBSSID NL attribute to get link id of transmitting vap link in case +TX vap is and MLD. + +Signed-off-by: Rameshkumar Sundaram +--- + include/net/cfg80211.h | 2 ++ + include/uapi/linux/nl80211.h | 6 ++++++ + net/wireless/nl80211.c | 13 +++++++++++++ + 3 files changed, 21 insertions(+) + +diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h +index 0c62d08..25367da 100644 +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -1209,11 +1209,13 @@ struct cfg80211_crypto_settings { + * struct cfg80211_mbssid_config - AP settings for multi bssid + * + * @tx_wdev: pointer to the transmitted interface in the MBSSID set ++ * @tx_link_id: linkid of transmitting link if @tx_wdev is an MLD. + * @index: index of this AP in the multi bssid group. + * @ema: set to true if the beacons should be sent out in EMA mode. + */ + struct cfg80211_mbssid_config { + struct wireless_dev *tx_wdev; ++ int tx_link_id; + u8 index; + bool ema; + }; +diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h +index 40917db..cb637e3 100644 +--- a/include/uapi/linux/nl80211.h ++++ b/include/uapi/linux/nl80211.h +@@ -7919,6 +7919,11 @@ enum nl80211_sar_specs_attrs { + * Setting this flag is permitted only if the driver advertises EMA support + * by setting wiphy->ema_max_profile_periodicity to non-zero. + * ++ * @NL80211_MBSSID_CONFIG_ATTR_TX_LINK_ID: Mandatory parameter for a non-transmitted profile ++ * which provides the interface index (u32) of the transmitted profile which ++ * is an MLD. The link id must be valid in the wdev of given Transmitting interface ++ * index. ++ * + * @__NL80211_MBSSID_CONFIG_ATTR_LAST: Internal + * @NL80211_MBSSID_CONFIG_ATTR_MAX: highest attribute + */ +@@ -7930,6 +7935,7 @@ enum nl80211_mbssid_config_attributes { + NL80211_MBSSID_CONFIG_ATTR_INDEX, + NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX, + NL80211_MBSSID_CONFIG_ATTR_EMA, ++ NL80211_MBSSID_CONFIG_ATTR_TX_LINK_ID, + + /* keep last */ + __NL80211_MBSSID_CONFIG_ATTR_LAST, +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 06cbfba..2fac612 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -476,6 +476,8 @@ nl80211_mbssid_config_policy[NL80211_MBSSID_CONFIG_ATTR_MAX + 1] = { + [NL80211_MBSSID_CONFIG_ATTR_INDEX] = { .type = NLA_U8 }, + [NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX] = { .type = NLA_U32 }, + [NL80211_MBSSID_CONFIG_ATTR_EMA] = { .type = NLA_FLAG }, ++ [NL80211_MBSSID_CONFIG_ATTR_TX_LINK_ID] = NLA_POLICY_RANGE(NLA_U8, 0, ++ IEEE80211_MLD_MAX_NUM_LINKS), + }; + + static const struct nla_policy +@@ -5855,6 +5857,7 @@ static int nl80211_parse_mbssid_config(struct wiphy *wiphy, + u8 num_elems) + { + struct nlattr *tb[NL80211_MBSSID_CONFIG_ATTR_MAX + 1]; ++ struct nlattr *tx_link_id; + + if (!wiphy->mbssid_max_interfaces) + return -EOPNOTSUPP; +@@ -5864,6 +5867,7 @@ static int nl80211_parse_mbssid_config(struct wiphy *wiphy, + !tb[NL80211_MBSSID_CONFIG_ATTR_INDEX]) + return -EINVAL; + ++ tx_link_id = tb[NL80211_MBSSID_CONFIG_ATTR_TX_LINK_ID]; + config->ema = nla_get_flag(tb[NL80211_MBSSID_CONFIG_ATTR_EMA]); + if (config->ema) { + if (!wiphy->ema_max_profile_periodicity) +@@ -5908,6 +5912,15 @@ static int nl80211_parse_mbssid_config(struct wiphy *wiphy, + return -EINVAL; + } + ++ if (!config->tx_wdev->valid_links && tx_link_id) ++ return -EINVAL; ++ ++ if (config->tx_wdev->valid_links && ++ (!tx_link_id || ++ !(config->tx_wdev->valid_links & BIT(nla_get_u8(tx_link_id))))) ++ return -ENOLINK; ++ ++ config->tx_link_id = tx_link_id ? nla_get_u8(tx_link_id) : 0; + return 0; + } + +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/716-002-wifi-mac80211-restructure-vif-and-link-conf-for-mlo-mbssi.patch b/feeds/ipq95xx/mac80211/patches/qca/716-002-wifi-mac80211-restructure-vif-and-link-conf-for-mlo-mbssi.patch new file mode 100644 index 000000000..bf018269a --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/716-002-wifi-mac80211-restructure-vif-and-link-conf-for-mlo-mbssi.patch @@ -0,0 +1,373 @@ +From 56ca5515aac22cddfbabdf2ef8ce5debf619903c Mon Sep 17 00:00:00 2001 +From: Rameshkumar Sundaram +Date: Sat, 4 Mar 2023 11:48:05 +0530 +Subject: [PATCH 2/4] mac80211: restructure vif and link conf for mlo mbssid + support + +For MLD, if Transmitting interface is MLD then tx link inside that MLD +has to be saved inside non-tx MLD's link. +Currently mbssid_tx_vif is inside vif structure which won't suffice for +finding tx link for any non-tx link. +Move mbssid_tx_vif to ieee80211_bss_conf and add mbssid_tx_vif_linkid to +the same to find TX vif and Tx link inside the TX vif for any non-tx +link. + +Modify CSA completion and BCCA event notifier routines to fetch +non-tx vdev links based on mbssid_tx_vif and mbssid_tx_vif_linkid. + +Signed-off-by: Rameshkumar Sundaram +--- + include/net/mac80211.h | 4 +-- + net/mac80211/cfg.c | 79 ++++++++++++++++++++++++++++++++++-------- + net/mac80211/iface.c | 18 +++++++--- + 3 files changed, 79 insertions(+), 22 deletions(-) + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -739,6 +739,8 @@ struct ieee80211_bss_conf { + struct ieee80211_ftm_responder_params *ftmr_params; + /* Multiple BSSID data */ + bool nontransmitted; ++ struct ieee80211_vif *mbssid_tx_vif; ++ int mbssid_tx_vif_linkid; + u8 transmitter_bssid[ETH_ALEN]; + u8 bssid_index; + u8 bssid_indicator; +@@ -1964,8 +1966,6 @@ struct ieee80211_vif { + bool txqs_stopped[IEEE80211_NUM_ACS]; + bool noqueue_enable; + +- struct ieee80211_vif *mbssid_tx_vif; +- + #ifdef CPTCFG_MAC80211_PPE_SUPPORT + u32 ppe_vp_num; + #endif +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -142,8 +142,10 @@ static int ieee80211_set_ap_mbssid_optio + struct ieee80211_bss_conf *link_conf) + { + struct ieee80211_sub_if_data *tx_sdata; ++ struct ieee80211_link_data *tx_link; + +- sdata->vif.mbssid_tx_vif = NULL; ++ link_conf->mbssid_tx_vif = NULL; ++ link_conf->mbssid_tx_vif_linkid = -1; + link_conf->bssid_index = 0; + link_conf->nontransmitted = false; + link_conf->ema_ap = false; +@@ -156,9 +158,25 @@ static int ieee80211_set_ap_mbssid_optio + return -EINVAL; + + if (tx_sdata == sdata) { +- sdata->vif.mbssid_tx_vif = &sdata->vif; ++ link_conf->mbssid_tx_vif = &sdata->vif; ++ link_conf->mbssid_tx_vif_linkid = link_conf->link_id; + } else { +- sdata->vif.mbssid_tx_vif = &tx_sdata->vif; ++ rcu_read_lock(); ++ tx_link = rcu_dereference(tx_sdata->link[params.tx_link_id]); ++ if (!tx_link || !tx_link->conf) { ++ rcu_read_unlock(); ++ return -ENOLINK; ++ } ++ /* Make sure input tx vif from user is really configured as a ++ * transmitting vif as per our internal data before referring it. ++ */ ++ if (tx_link->conf->mbssid_tx_vif != &tx_sdata->vif) { ++ rcu_read_unlock(); ++ return -EINVAL; ++ } ++ link_conf->mbssid_tx_vif = &tx_sdata->vif; ++ link_conf->mbssid_tx_vif_linkid = tx_link->link_id; ++ rcu_read_unlock(); + link_conf->nontransmitted = true; + link_conf->bssid_index = params.index; + } +@@ -1604,8 +1622,12 @@ static int ieee80211_stop_ap(struct wiph + struct cfg80211_chan_def chandef; + struct ieee80211_link_data *link = + sdata_dereference(sdata->link[link_id], sdata); +- struct ieee80211_bss_conf *link_conf = link->conf; ++ struct ieee80211_bss_conf *link_conf; + ++ if (WARN_ON(!link)) ++ return -ENOLINK; ++ ++ link_conf = link->conf; + sdata_assert_lock(sdata); + + old_beacon = sdata_dereference(link->u.ap.beacon, sdata); +@@ -1671,7 +1693,10 @@ static int ieee80211_stop_ap(struct wiph + __sta_info_flush(sdata, true); + ieee80211_free_keys(sdata, true); + ++ ieee80211_stop_mbssid(sdata); + link_conf->enable_beacon = false; ++ link_conf->mbssid_tx_vif = NULL; ++ link_conf->mbssid_tx_vif_linkid = -1; + sdata->beacon_rate_set = false; + sdata->vif.cfg.ssid_len = 0; + clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); +@@ -3717,23 +3742,41 @@ void ieee80211_csa_finish(struct ieee802 + return; + } + +- /* TODO: MBSSID with MLO changes */ +- if (vif->mbssid_tx_vif == vif) { ++ if (link->conf->mbssid_tx_vif == vif && ++ link->conf->mbssid_tx_vif_linkid == link->conf->link_id) { + /* Trigger ieee80211_csa_finish() on the non-transmitting + * interfaces when channel switch is received on + * transmitting interface + */ ++ unsigned int link_id_iter; ++ u16 valid_links; + struct ieee80211_sub_if_data *iter; ++ struct ieee80211_link_data *link_iter; + + list_for_each_entry_rcu(iter, &local->interfaces, list) { + if (!ieee80211_sdata_running(iter)) + continue; + +- if (iter == sdata || iter->vif.mbssid_tx_vif != vif) ++ if (iter == sdata) + continue; + +- ieee80211_queue_work(&iter->local->hw, +- &iter->deflink.csa_finalize_work); ++ /* check link 0 by default for Non-ML non-tx vif's deflinks */ ++ valid_links = iter->vif.valid_links | BIT(0); ++ for_each_set_bit(link_id_iter, &valid_links, ++ IEEE80211_MLD_MAX_NUM_LINKS) { ++ link_iter = rcu_dereference(iter->link[link_id_iter]); ++ if (!link_iter) ++ continue; ++ /* Check if any of link of iterator sdata belongs ++ * to same mbssid group as the tx link ++ */ ++ if (link_iter->conf->mbssid_tx_vif != vif || ++ link_iter->conf->mbssid_tx_vif_linkid != link->link_id) ++ continue; ++ ++ ieee80211_queue_work(&iter->local->hw, ++ &link_iter->csa_finalize_work); ++ } + } + } + ieee80211_queue_work(&local->hw, &link->csa_finalize_work); +@@ -4949,6 +4992,7 @@ ieee80211_color_change_bss_config_notify + { + struct ieee80211_sub_if_data *sdata = link->sdata; + ++ sdata_assert_lock(sdata); + link->conf->he_bss_color.color = color; + link->conf->he_bss_color.enabled = enable; + +@@ -4956,19 +5000,38 @@ ieee80211_color_change_bss_config_notify + + ieee80211_link_info_change_notify(sdata, link, changed); + +- /* handle bss color in mbssid case with MLO */ +- if (!link->conf->nontransmitted && sdata->vif.mbssid_tx_vif) { ++ if (!link->conf->nontransmitted && link->conf->mbssid_tx_vif) { ++ unsigned int link_id_iter; ++ u16 valid_links; + struct ieee80211_sub_if_data *child; ++ struct ieee80211_link_data *link_iter; + + mutex_lock(&sdata->local->iflist_mtx); + list_for_each_entry(child, &sdata->local->interfaces, list) { +- if (child != sdata && child->vif.mbssid_tx_vif == &sdata->vif) { +- child->vif.bss_conf.he_bss_color.color = color; +- child->vif.bss_conf.he_bss_color.enabled = enable; +- ieee80211_link_info_change_notify(child, +- &child->deflink, ++ if (child == sdata) ++ continue; ++ sdata_lock(child); ++ /* check deflink by default */ ++ valid_links = child->vif.valid_links | BIT(0); ++ for_each_set_bit(link_id_iter, &valid_links, ++ IEEE80211_MLD_MAX_NUM_LINKS) { ++ link_iter = sdata_dereference(child->link[link_id_iter], ++ child); ++ if (!link_iter) ++ continue; ++ /* Check if any of link of iterator sdata belongs ++ * to same mbssid group as the tx link ++ */ ++ if (link_iter->conf->mbssid_tx_vif != &sdata->vif || ++ link_iter->conf->mbssid_tx_vif_linkid != link->link_id) ++ continue; ++ ++ link_iter->conf->he_bss_color.color = color; ++ link_iter->conf->he_bss_color.enabled = enable; ++ ieee80211_link_info_change_notify(child, link_iter, + BSS_CHANGED_HE_BSS_COLOR); + } ++ sdata_unlock(child); + } + mutex_unlock(&sdata->local->iflist_mtx); + } +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -670,46 +670,95 @@ static void ieee80211_do_stop(struct iee + ieee80211_add_virtual_monitor(local); + } + +-static void ieee80211_stop_mbssid(struct ieee80211_sub_if_data *sdata) ++void ieee80211_stop_mbssid(struct ieee80211_sub_if_data *sdata) + { + struct ieee80211_sub_if_data *tx_sdata, *non_tx_sdata, *tmp_sdata; +- struct ieee80211_vif *tx_vif = sdata->vif.mbssid_tx_vif; +- +- if (!tx_vif) +- return; +- +- tx_sdata = vif_to_sdata(tx_vif); +- sdata->vif.mbssid_tx_vif = NULL; +- +- list_for_each_entry_safe(non_tx_sdata, tmp_sdata, +- &tx_sdata->local->interfaces, list) { +- if (non_tx_sdata != sdata && non_tx_sdata != tx_sdata && +- non_tx_sdata->vif.mbssid_tx_vif == tx_vif && +- ieee80211_sdata_running(non_tx_sdata)) { +- non_tx_sdata->vif.mbssid_tx_vif = NULL; +- dev_close(non_tx_sdata->wdev.netdev); ++ struct ieee80211_vif *tx_vif; ++ unsigned int valid_links, link_id, tx_link_id, iter_valid_links, iter_link_id; ++ struct ieee80211_link_data *link_iter, *link; ++ ++ lockdep_assert_wiphy(sdata->local->hw.wiphy); ++ sdata_assert_lock(sdata); ++ /* Check link 0 by default for non MLO. */ ++ iter_valid_links = sdata->vif.valid_links | BIT(0); ++ /* Check if any of the links of current sdata is an MBSSID. */ ++ for_each_set_bit(iter_link_id, &iter_valid_links, ++ IEEE80211_MLD_MAX_NUM_LINKS) { ++ link_iter = sdata_dereference(sdata->link[iter_link_id], sdata); ++ if (!link_iter) ++ continue; ++ tx_vif = link_iter->conf->mbssid_tx_vif; ++ tx_link_id = link_iter->conf->mbssid_tx_vif_linkid; ++ if (!tx_vif) ++ continue; ++ tx_sdata = vif_to_sdata(tx_vif); ++ link_iter->conf->mbssid_tx_vif = NULL; ++ /* If we are not tx sdata reset tx sdata's tx_vif to avoid recusrion while ++ * closing tx sdata at the end of outer loop below. ++ */ ++ if (sdata != tx_sdata) { ++ sdata_lock(tx_sdata); ++ link = sdata_dereference(tx_sdata->link[tx_link_id], tx_sdata); ++ if (!link) { ++ sdata_unlock(tx_sdata); ++ continue; ++ } ++ link->conf->mbssid_tx_vif = NULL; ++ sdata_unlock(tx_sdata); ++ } ++ /* loop through sdatas to find if any of their links ++ * belong to same mbssid group as the one getting deleted. ++ */ ++ list_for_each_entry_safe(non_tx_sdata, tmp_sdata, ++ &tx_sdata->local->interfaces, list) { ++ if (non_tx_sdata != sdata && non_tx_sdata != tx_sdata && ++ ieee80211_sdata_running(non_tx_sdata)) { ++ sdata_lock(non_tx_sdata); ++ valid_links = non_tx_sdata->vif.valid_links | BIT(0); ++ for_each_set_bit(link_id, &valid_links, ++ IEEE80211_MLD_MAX_NUM_LINKS) { ++ link = sdata_dereference(non_tx_sdata->link[link_id], non_tx_sdata); ++ if (!link) ++ continue; ++ /* If both tx vif and tx linkid is matching then it belongs to ++ * same MBSSID group. ++ */ ++ if (link->conf->mbssid_tx_vif != tx_vif || ++ link->conf->mbssid_tx_vif_linkid != tx_link_id) ++ continue; ++ link->conf->mbssid_tx_vif = NULL; ++ /* Remove all links of matching MLD untill dynamic link removal ++ * can be supported. ++ */ ++ cfg80211_stop_iface(non_tx_sdata->wdev.wiphy, ++ &non_tx_sdata->wdev, GFP_KERNEL); ++ } ++ sdata_unlock(non_tx_sdata); ++ } ++ } ++ /* If we are not tx sdata, remove links of tx sdata and proceed. ++ */ ++ if (sdata != tx_sdata && ieee80211_sdata_running(tx_sdata)) { ++ sdata_lock(tx_sdata); ++ cfg80211_stop_iface(tx_sdata->wdev.wiphy, ++ &tx_sdata->wdev, GFP_KERNEL); ++ sdata_unlock(tx_sdata); + } + } +- +- if (sdata != tx_sdata && ieee80211_sdata_running(tx_sdata)) { +- tx_sdata->vif.mbssid_tx_vif = NULL; +- dev_close(tx_sdata->wdev.netdev); +- } ++ return; + } + + static int ieee80211_stop(struct net_device *dev) + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + +- /* close dependent VLAN and MBSSID interfaces before locking wiphy */ ++ /* close dependent VLAN interfaces before locking wiphy */ + if (sdata->vif.type == NL80211_IFTYPE_AP) { + struct ieee80211_sub_if_data *vlan, *tmpsdata; + + list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, + u.vlan.list) + dev_close(vlan->dev); +- +- ieee80211_stop_mbssid(sdata); + } + + #ifdef CPTCFG_MAC80211_NSS_SUPPORT +@@ -730,6 +779,14 @@ static int ieee80211_stop(struct net_dev + #endif + + wiphy_lock(sdata->local->hw.wiphy); ++ /* Close the dependent MBSSID interfaces with wiphy lock as we may be terminating ++ * its partner links too in case of MLD. ++ */ ++ if (sdata->vif.type == NL80211_IFTYPE_AP) { ++ sdata_lock(sdata); ++ ieee80211_stop_mbssid(sdata); ++ sdata_unlock(sdata); ++ } + ieee80211_do_stop(sdata, true); + wiphy_unlock(sdata->local->hw.wiphy); + +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -2624,4 +2624,5 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(stru + struct link_sta_info *link_sta); + void ieee80211_eht_op_ie_to_bss_conf(struct ieee80211_bss_conf *link_conf, + const struct ieee80211_eht_operation *op_ie); ++void ieee80211_stop_mbssid(struct ieee80211_sub_if_data *sdata); + #endif /* IEEE80211_I_H */ +--- a/net/wireless/sme.c ++++ b/net/wireless/sme.c +@@ -1514,6 +1514,7 @@ void cfg80211_autodisconnect_wk(struct w + container_of(work, struct wireless_dev, disconnect_wk); + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); + ++ wiphy_lock(&rdev->wiphy); + wdev_lock(wdev); + + if (wdev->conn_owner_nlportid) { +@@ -1552,4 +1553,5 @@ void cfg80211_autodisconnect_wk(struct w + } + + wdev_unlock(wdev); ++ wiphy_unlock(&rdev->wiphy); + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/716-003-wifi-ath12k-MLO-MBSSID-Support.patch b/feeds/ipq95xx/mac80211/patches/qca/716-003-wifi-ath12k-MLO-MBSSID-Support.patch new file mode 100644 index 000000000..993dcb2af --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/716-003-wifi-ath12k-MLO-MBSSID-Support.patch @@ -0,0 +1,501 @@ +From 2cf8da1bdedcacb42cd9edb9b22f83ac974c97c0 Mon Sep 17 00:00:00 2001 +From: Rameshkumar Sundaram +Date: Tue, 28 Feb 2023 00:49:14 +0530 +Subject: [PATCH 3/4] wifi: ath12k: MLO MBSSID Support + +Add changes to fetch transmitting links BSS of and MBSSID +group bases on mbssid_tx_vif and mbssid_tx_vif_linkid information +stored in every link. + +Fetch beacons based on Tx vif and tx vif linkid for any non-tx +vdev's link BSS. + +Save vdev id of transmitting vdev for non-tx vdevs in +local structure and use the same to update CU cat1 flag +for all non-tx mld vif as part of TX vdev BCN_TMP, +if it occurs for a TX vif link BSS (Since they are on same radio). +FW will take care of updating CU for partner link. + +ToDo: Handle Vdev synchronization for Multi Link MLO+MBSSID. + +Signed-off-by: Rameshkumar Sundaram +--- + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/mac.c | 208 +++++++++++++++++-------- + drivers/net/wireless/ath/ath12k/wmi.c | 26 +++- + 3 files changed, 165 insertions(+), 70 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h +index 235a5d9..0f4c09a 100644 +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -360,6 +360,7 @@ struct ath12k_link_vif { + struct work_struct update_bcn_template_work; + u64 obss_color_bitmap; + struct work_struct update_obss_color_notify_work; ++ u32 tx_vdev_id; + u8 link_id; + struct ath12k_vif *ahvif; + +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index 3c63fd0..ce5923c 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -1550,20 +1550,37 @@ static int ath12k_mac_setup_bcn_tmpl_ema(struct ath12k_link_vif *arvif) + struct ath12k_link_vif *tx_arvif; + struct ath12k_vif *tx_ahvif, *ahvif = arvif->ahvif; + struct ieee80211_ema_beacons *beacons; ++ struct ieee80211_bss_conf *link; + u8 i = 0; + int ret = 0; + bool found_vdev = false; + +- if (!ahvif->vif->mbssid_tx_vif) ++ rcu_read_lock(); ++ link = ath12k_get_link_bss_conf(arvif); ++ if (!link->mbssid_tx_vif) { ++ rcu_read_unlock(); + return -1; +- +- /* FIXME there could be multiple tx link vifs, so this basically +- * requires change for MLO ++ } ++ tx_ahvif = (void *)link->mbssid_tx_vif->drv_priv; ++ if (!tx_ahvif) { ++ rcu_read_unlock(); ++ return -ENOLINK; ++ } ++ /* both TX an NON_TX arvif's should be under same ar and hw ++ * hence current acquired lock's should suffice for opertaing ++ * with tx arvif also + */ +- tx_ahvif = (void *) ahvif->vif->mbssid_tx_vif->drv_priv; +- tx_arvif = &tx_ahvif->deflink; ++ lockdep_assert_held(&tx_ahvif->ah->conf_mutex); ++ tx_arvif = tx_ahvif->link[link->mbssid_tx_vif_linkid]; ++ if (!tx_arvif) { ++ rcu_read_unlock(); ++ return -ENOLINK; ++ } ++ lockdep_assert_held(&tx_arvif->ar->conf_mutex); + beacons = ieee80211_beacon_get_template_ema_list(tx_arvif->ar->ah->hw, +- tx_ahvif->vif, 0); ++ tx_ahvif->vif, ++ tx_arvif->link_id); ++ rcu_read_unlock(); + if (!beacons || !beacons->cnt) { + ath12k_warn(arvif->ar->ab, + "failed to get ema beacon templates from mac80211\n"); +@@ -1604,21 +1621,36 @@ static int ath12k_mac_setup_bcn_tmpl_non_ema(struct ath12k_link_vif *arvif) + { + struct ath12k_link_vif *tx_arvif = arvif; + struct ath12k_vif *tx_ahvif = arvif->ahvif; +- struct ath12k_vif *ahvif = arvif->ahvif; + struct ieee80211_mutable_offsets offs = {}; + struct sk_buff *bcn; ++ struct ieee80211_bss_conf *link; + int ret; + +- /* FIXME there could be multiple tx link vifs, so this basically +- * requires change for MLO +- */ +- if (ahvif->vif->mbssid_tx_vif) { +- tx_ahvif = (void *) ahvif->vif->mbssid_tx_vif->drv_priv; +- tx_arvif = &tx_ahvif->deflink; ++ rcu_read_lock(); ++ link = ath12k_get_link_bss_conf(arvif); ++ if (!link) { ++ rcu_read_unlock(); ++ return -ENOLINK; + } + +- bcn = ieee80211_beacon_get_template(tx_arvif->ar->ah->hw, ahvif->vif, +- &offs, arvif->link_id); ++ if (link->mbssid_tx_vif) { ++ tx_ahvif = (void *)link->mbssid_tx_vif->drv_priv; ++ if (!tx_ahvif) { ++ rcu_read_unlock(); ++ return -ENOLINK; ++ } ++ lockdep_assert_held(&tx_ahvif->ah->conf_mutex); ++ tx_arvif = tx_ahvif->link[link->mbssid_tx_vif_linkid]; ++ } ++ ++ if (!tx_arvif) { ++ rcu_read_unlock(); ++ return -ENOLINK; ++ } ++ lockdep_assert_held(&tx_arvif->ar->conf_mutex); ++ bcn = ieee80211_beacon_get_template(tx_arvif->ar->ah->hw, tx_ahvif->vif, ++ &offs, tx_arvif->link_id); ++ rcu_read_unlock(); + if (!bcn) { + ath12k_warn(arvif->ar->ab, + "failed to get beacon template from mac80211\n"); +@@ -1634,7 +1666,7 @@ static int ath12k_mac_setup_bcn_tmpl_non_ema(struct ath12k_link_vif *arvif) + + ret = __ath12k_mac_setup_bcn_tmpl(tx_arvif, bcn, offs, 0, 0); + if (ret) +- ath12k_warn(arvif->ar->ab, ++ ath12k_warn(tx_arvif->ar->ab, + "failed to submit beacon template command: %d\n", + ret); + +@@ -1644,21 +1676,30 @@ static int ath12k_mac_setup_bcn_tmpl_non_ema(struct ath12k_link_vif *arvif) + + static int ath12k_mac_setup_bcn_tmpl(struct ath12k_link_vif *arvif) + { +- struct ath12k_vif *ahvif = arvif->ahvif; +- struct ieee80211_vif *vif = ahvif->vif; ++ struct ath12k_vif *tx_ahvif, *ahvif = arvif->ahvif; ++ struct ieee80211_bss_conf *link; ++ bool is_ema; + + if (ahvif->vdev_type != WMI_VDEV_TYPE_AP) + return 0; + +- /* FIXME there could be multiple tx link vifs, so this basically +- * requires change for MLO. For simpler case mbssid_tx_vif is NULL +- */ +- if (vif->mbssid_tx_vif && +- ahvif != (void *)vif->mbssid_tx_vif->drv_priv && +- arvif->is_up) +- return 0; ++ rcu_read_lock(); ++ link = ath12k_get_link_bss_conf(arvif); ++ if (!link) { ++ rcu_read_unlock(); ++ return -ENOLINK; ++ } ++ if (link->mbssid_tx_vif) { ++ tx_ahvif = (void *)link->mbssid_tx_vif->drv_priv; ++ if (ahvif != tx_ahvif && arvif->is_up) { ++ rcu_read_unlock(); ++ return 0; ++ } ++ } ++ is_ema = link->ema_ap; ++ rcu_read_unlock(); + +- if (vif->bss_conf.ema_ap) ++ if (is_ema) + return ath12k_mac_setup_bcn_tmpl_ema(arvif); + else + return ath12k_mac_setup_bcn_tmpl_non_ema(arvif); +@@ -1690,7 +1731,7 @@ void ath12k_mac_bcn_tx_event(struct ath12k_link_vif *arvif) + + arvif->bcca_zero_sent = false; + +- if (link_conf->color_change_active && !vif->bss_conf.ema_ap) ++ if (link_conf->color_change_active && !link_conf->ema_ap) + ieee80211_beacon_update_cntdwn(vif, arvif->link_id); + ieee80211_queue_work(ar->ah->hw, &arvif->update_bcn_template_work); + } +@@ -1702,17 +1743,28 @@ static void ath12k_control_beaconing(struct ath12k_link_vif *arvif, + struct ath12k_vif *ahvif = arvif->ahvif; + struct ath12k_vif *tx_ahvif = NULL; + struct ath12k_link_vif *tx_arvif = NULL; ++ struct ieee80211_bss_conf *link; + int ret = 0; + struct vdev_up_params params = { 0 }; + +- /* FIXME there could be multiple tx link vifs, so this basically +- * requires change for MLO. For Non MLO no change in behavior +- */ +- if (ahvif->vif->mbssid_tx_vif) { +- tx_ahvif = (void *) ahvif->vif->mbssid_tx_vif->drv_priv; +- tx_arvif = &tx_ahvif->deflink; ++ rcu_read_lock(); ++ link = ath12k_get_link_bss_conf(arvif); ++ if (!link) { ++ rcu_read_unlock(); ++ return; ++ } ++ ++ if (link->mbssid_tx_vif) { ++ tx_ahvif = (void *)link->mbssid_tx_vif->drv_priv; ++ if (tx_ahvif) { ++ lockdep_assert_held(&tx_ahvif->ah->conf_mutex); ++ tx_arvif = tx_ahvif->link[link->mbssid_tx_vif_linkid]; ++ if (tx_arvif) ++ lockdep_assert_held(&tx_arvif->ar->conf_mutex); ++ } + } + ++ rcu_read_unlock(); + lockdep_assert_held(&arvif->ar->conf_mutex); + + if (!info->enable_beacon) { +@@ -3886,9 +3938,9 @@ static void ath12k_bss_assoc(struct ath12k *ar, + static void ath12k_bss_disassoc(struct ath12k *ar, + struct ath12k_link_vif *arvif) + { +- struct ath12k_vif *ahvif = arvif->ahvif; + struct ath12k_vif *tx_ahvif; + struct ath12k_link_vif *tx_arvif; ++ struct ieee80211_bss_conf *link; + int ret; + + lockdep_assert_held(&ar->conf_mutex); +@@ -3903,15 +3955,26 @@ static void ath12k_bss_disassoc(struct ath12k *ar, + + arvif->is_up = false; + +- /* FIXME mbssid for MLO */ +- if (ahvif->vif->mbssid_tx_vif) { +- tx_ahvif = (void *) ahvif->vif->mbssid_tx_vif->drv_priv; +- tx_arvif = &tx_ahvif->deflink; +- if (tx_arvif != arvif) +- tx_arvif->nontransmitting_vif_count--; ++ rcu_read_lock(); ++ link = ath12k_get_link_bss_conf(arvif); ++ if (!link) ++ goto unlock; ++ ++ if (link->mbssid_tx_vif) { ++ tx_ahvif = (void *)link->mbssid_tx_vif->drv_priv; ++ if (!tx_ahvif) ++ goto unlock; ++ lockdep_assert_held(&tx_ahvif->ah->conf_mutex); ++ tx_arvif = tx_ahvif->link[link->mbssid_tx_vif_linkid]; ++ if (!tx_arvif) ++ goto unlock; ++ lockdep_assert_held(&tx_arvif->ar->conf_mutex); ++ tx_arvif->nontransmitting_vif_count--; + } + + /* TODO: cancel connection_loss_work */ ++unlock: ++ rcu_read_unlock(); + } + + static u32 ath12k_mac_get_rate_hw_value(int bitrate) +@@ -8938,6 +9001,7 @@ static int ath12k_mac_setup_vdev_params_mbssid(struct ath12k_link_vif *arvif, + { + struct ath12k *ar = arvif->ar; + struct ath12k_link_vif *tx_arvif; ++ struct ath12k_vif *tx_ahvif; + struct ieee80211_vif *tx_vif; + struct ieee80211_bss_conf *link_conf; + +@@ -8952,15 +9016,25 @@ static int ath12k_mac_setup_vdev_params_mbssid(struct ath12k_link_vif *arvif, + } + + *tx_vdev_id = 0; +- /* FIXME MBSSID with MLO */ +- tx_vif = arvif->ahvif->vif->mbssid_tx_vif; ++ tx_vif = link_conf->mbssid_tx_vif; + if (!tx_vif) { + *flags = WMI_HOST_VDEV_FLAGS_NON_MBSSID_AP; + rcu_read_unlock(); + return 0; + } + +- tx_arvif = &ath12k_vif_to_ahvif(tx_vif)->deflink; ++ tx_ahvif = ath12k_vif_to_ahvif(tx_vif); ++ if (!tx_ahvif) { ++ rcu_read_unlock(); ++ return -EINVAL; ++ } ++ lockdep_assert_held(&tx_ahvif->ah->conf_mutex); ++ tx_arvif = tx_ahvif->link[link_conf->mbssid_tx_vif_linkid]; ++ if (!tx_arvif) { ++ rcu_read_unlock(); ++ return -EINVAL; ++ } ++ lockdep_assert_held(&tx_arvif->ar->conf_mutex); + + if (link_conf->nontransmitted) { + if (ar->ah->hw->wiphy != ieee80211_vif_to_wdev(tx_vif)->wiphy) { +@@ -8976,6 +9050,7 @@ static int ath12k_mac_setup_vdev_params_mbssid(struct ath12k_link_vif *arvif, + rcu_read_unlock(); + return -EINVAL; + } ++ arvif->tx_vdev_id = *tx_vdev_id; + + if (link_conf->ema_ap) + *flags |= WMI_HOST_VDEV_FLAGS_EMA_MODE; +@@ -9206,6 +9281,9 @@ static int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arv + vdev_id = __ffs64(ab->free_vdev_map); + + arvif->vdev_id = vdev_id; ++ /* Assume it as non-mbssid initially, well overwrite it later. ++ */ ++ arvif->tx_vdev_id = vdev_id; + ahvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE; + arvif->ar = ar; + +@@ -10304,6 +10382,7 @@ static int ath12k_vdev_restart_sequence(struct ath12k_link_vif *arvif, + struct ath12k *ar = arvif->ar; + struct ath12k_link_vif *tx_arvif; + struct ath12k_vif *tx_ahvif; ++ struct ieee80211_bss_conf *link; + struct ieee80211_chanctx_conf old_chanctx; + struct vdev_up_params params = { 0 }; + int ret = -EINVAL; +@@ -10350,15 +10429,16 @@ beacon_tmpl_setup: + params.vdev_id = arvif->vdev_id; + params.aid = ahvif->aid; + params.bssid = arvif->bssid; +- if (ahvif->vif->mbssid_tx_vif) { +- tx_ahvif = (void *) ahvif->vif->mbssid_tx_vif->drv_priv; +- /* TODO ML mbssid changes */ +- tx_arvif = &tx_ahvif->deflink; ++ rcu_read_lock(); ++ link = rcu_dereference(ahvif->vif->link_conf[arvif->link_id]); ++ if (link->mbssid_tx_vif) { ++ tx_ahvif = (void *)link->mbssid_tx_vif->drv_priv; ++ tx_arvif = tx_ahvif->link[link->mbssid_tx_vif_linkid]; + params.tx_bssid = tx_arvif->bssid; + params.profile_idx = ahvif->vif->bss_conf.bssid_index; + params.profile_count = tx_arvif->nontransmitting_vif_count; + } +- ++ rcu_read_unlock(); + ret = ath12k_wmi_vdev_up(arvif->ar, ¶ms); + if (ret) { + ath12k_warn(ar->ab, "failed to bring vdev up %d: %d\n", +@@ -10756,7 +10836,7 @@ ath12k_mac_update_vif_chan(struct ath12k *ar, + { + struct ath12k_base *ab = ar->ab; + struct ath12k_link_vif *arvif, *tx_arvif; +- struct ath12k_vif *ahvif; ++ struct ath12k_vif *ahvif, *tx_ahvif = NULL; + int ret; + int i, trans_vdev_index; + u64 vif_down_failed_map = 0; +@@ -10794,11 +10874,11 @@ ath12k_mac_update_vif_chan(struct ath12k *ar, + if (!arvif->is_up) + continue; + +- if (ahvif->vif->mbssid_tx_vif && +- ahvif == (struct ath12k_vif *)ahvif->vif->mbssid_tx_vif->drv_priv) { +- tx_vif = ahvif->vif->mbssid_tx_vif; +- /* TODO ML mbssid changes */ +- tx_arvif = &ath12k_vif_to_ahvif(tx_vif)->deflink; ++ if (vifs[i].link_conf->mbssid_tx_vif && ++ ahvif == (struct ath12k_vif *)vifs[i].link_conf->mbssid_tx_vif->drv_priv) { ++ tx_vif = vifs[i].link_conf->mbssid_tx_vif; ++ tx_ahvif = ath12k_vif_to_ahvif(tx_vif); ++ tx_arvif = tx_ahvif->link[vifs[i].link_conf->mbssid_tx_vif_linkid]; + trans_vdev_index = i; + } + +@@ -10831,7 +10911,7 @@ ath12k_mac_update_vif_chan(struct ath12k *ar, + if (WARN_ON(!arvif)) + continue; + +- if (ahvif->vif->mbssid_tx_vif && ++ if (vifs[i].link_conf->mbssid_tx_vif && + arvif == tx_arvif) + continue; + +@@ -10852,8 +10932,8 @@ ath12k_mac_update_vif_chan_mvr(struct ath12k *ar, + int n_vifs) + { + struct ath12k_base *ab = ar->ab; +- struct ath12k_link_vif *arvif, *tx_arvif; +- struct ath12k_vif *ahvif; ++ struct ath12k_link_vif *arvif, *tx_arvif = NULL; ++ struct ath12k_vif *ahvif, *tx_ahvif = NULL; + struct cfg80211_chan_def *chandef; + struct ieee80211_vif *tx_vif; + int ret, i, time_left, trans_vdev_index, vdev_idx, n_vdevs = 0; +@@ -10886,11 +10966,11 @@ ath12k_mac_update_vif_chan_mvr(struct ath12k *ar, + if (!arvif->is_started) + continue; + +- if (ahvif->vif->mbssid_tx_vif && +- ahvif == (struct ath12k_vif *)ahvif->vif->mbssid_tx_vif->drv_priv) { +- tx_vif = ahvif->vif->mbssid_tx_vif; +- /* TODO ML mbssid changes */ +- tx_arvif = &ath12k_vif_to_ahvif(tx_vif)->deflink; ++ if (vifs[i].link_conf->mbssid_tx_vif && ++ ahvif == (struct ath12k_vif *)vifs[i].link_conf->mbssid_tx_vif->drv_priv) { ++ tx_vif = vifs[i].link_conf->mbssid_tx_vif; ++ tx_ahvif = ath12k_vif_to_ahvif(tx_vif); ++ tx_arvif = tx_ahvif->link[vifs[i].link_conf->mbssid_tx_vif_linkid]; + trans_vdev_index = i; + } + +@@ -10952,7 +11032,7 @@ ath12k_mac_update_vif_chan_mvr(struct ath12k *ar, + + vdev_idx = -1; + +- if (ahvif->vif->mbssid_tx_vif && arvif == tx_arvif) ++ if (vifs[i].link_conf->mbssid_tx_vif && arvif == tx_arvif) + continue; + + if (arvif->mvr_processing) { +diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c +index 97288a3..0e25cc7 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -2081,7 +2081,8 @@ int ath12k_wmi_send_bcn_offload_control_cmd(struct ath12k *ar, + } + + static void ath12k_wmi_bcn_fill_ml_info(struct ath12k_link_vif *arvif, +- struct wmi_bcn_tmpl_ml_info *ml_info) ++ struct wmi_bcn_tmpl_ml_info *ml_info, ++ u64 non_tx_ml_vdev_bmap) + { + struct ath12k_base *ab = arvif->ar->ab; + struct ieee80211_bss_conf *link_conf; +@@ -2105,8 +2106,13 @@ static void ath12k_wmi_bcn_fill_ml_info(struct ath12k_link_vif *arvif, + sizeof(*ml_info)); + ml_info->hw_link_id = cpu_to_le32(arvif->ar->pdev->hw_link_id); + +- if (cu_flags & ATH12K_CRITICAL_UPDATE_CAT_1) ++ /* if this is cu cat 1 for tx vdev, then it applies to all ++ * non-tx vdevs as well set all non-tx mld's vdev id in bitmap ++ */ ++ if (cu_flags & ATH12K_CRITICAL_UPDATE_CAT_1) { + set_bit(vdev_id, &vdev_map_cat1); ++ vdev_map_cat1 |= non_tx_ml_vdev_bmap; ++ } + + if (cu_flags & ATH12K_CRITICAL_UPDATE_CAT_2) + set_bit(vdev_id, &vdev_map_cat2); +@@ -2122,19 +2128,27 @@ err_fill_ml_info: + cpu_to_le32(ATH12K_GET_UPPER_32_BITS(vdev_map_cat2)); + + ath12k_dbg(ab, ATH12K_DBG_WMI, +- "wmi CU filled ml info cat1_lo=0x%x cat1_hi=0x%x cat2_lo=0x%x cat2_hi=0x%x\n", ++ "wmi CU filled ml info cat1_lo=0x%x cat1_hi=0x%x cat2_lo=0x%x cat2_hi=0x%x non_tx_ml_bmap=%llu\n", + ml_info->cu_vdev_map_cat1_lo, ml_info->cu_vdev_map_cat1_hi, +- ml_info->cu_vdev_map_cat2_lo, ml_info->cu_vdev_map_cat2_hi); ++ ml_info->cu_vdev_map_cat2_lo, ml_info->cu_vdev_map_cat2_hi, ++ non_tx_ml_vdev_bmap); + } + + static void ath12k_wmi_fill_cu_arg(struct ath12k_link_vif *arvif, + struct wmi_critical_update_arg *cu_arg) + { + struct ath12k_base *ab = arvif->ar->ab; ++ struct ath12k_link_vif *arvif_iter; + struct wmi_bcn_tmpl_ml_info *ml_info; + int i; ++ u64 non_tx_ml_vdev_bmap = 0; + +- if (!ath12k_mac_is_ml_arvif(arvif)) ++ list_for_each_entry(arvif_iter, &arvif->ar->arvifs, list) { ++ if (arvif_iter != arvif && arvif_iter->tx_vdev_id == arvif->vdev_id && ++ ath12k_mac_is_ml_arvif(arvif_iter)) ++ set_bit(arvif_iter->vdev_id, &non_tx_ml_vdev_bmap); ++ } ++ if (!ath12k_mac_is_ml_arvif(arvif) && !non_tx_ml_vdev_bmap) + return; + + /* Fill ML params +@@ -2157,7 +2171,7 @@ static void ath12k_wmi_fill_cu_arg(struct ath12k_link_vif *arvif, + } else { + for (i = 0; i < cu_arg->num_ml_info; i++) { + ml_info = &cu_arg->ml_info[i]; +- ath12k_wmi_bcn_fill_ml_info(arvif, ml_info); ++ ath12k_wmi_bcn_fill_ml_info(arvif, ml_info, non_tx_ml_vdev_bmap); + } + } + } +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/716-004-wifi-ath11k-fetch-mbssid-tx-vif-from-deflink.patch b/feeds/ipq95xx/mac80211/patches/qca/716-004-wifi-ath11k-fetch-mbssid-tx-vif-from-deflink.patch new file mode 100644 index 000000000..8c1cc3b8a --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/716-004-wifi-ath11k-fetch-mbssid-tx-vif-from-deflink.patch @@ -0,0 +1,97 @@ +From 07c8cbc636fe81fbc1f61d68400e16b0db313783 Mon Sep 17 00:00:00 2001 +From: Rameshkumar Sundaram +Date: Tue, 28 Feb 2023 00:43:54 +0530 +Subject: [PATCH 4/4] wifi : ath11k : fetch mbssid tx vif from deflink + +Make changes to fetch mbssid tx vif from vifs->deflink +which is restructured as part of MLO MBSSID Support. + +Signed-off-by: Rameshkumar Sundaram +--- + drivers/net/wireless/ath/ath11k/mac.c | 26 +++++++++++++------------- + 1 file changed, 13 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c +index a753846..34d0c4b 100644 +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -1675,10 +1675,10 @@ static int ath11k_mac_setup_bcn_tmpl_ema(struct ath11k_vif *arvif) + int ret = 0; + bool found_vdev = false; + +- if (!arvif->vif->mbssid_tx_vif) ++ if (!arvif->vif->bss_conf.mbssid_tx_vif) + return -1; + +- tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv; ++ tx_arvif = (void *)arvif->vif->bss_conf.mbssid_tx_vif->drv_priv; + beacons = ieee80211_beacon_get_template_ema_list(tx_arvif->ar->hw, + tx_arvif->vif, 0); + if (!beacons || !beacons->cnt) { +@@ -1725,8 +1725,8 @@ static int ath11k_mac_setup_bcn_tmpl_non_ema(struct ath11k_vif *arvif) + struct sk_buff *bcn; + int ret; + +- if (arvif->vif->mbssid_tx_vif) +- tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv; ++ if (arvif->vif->bss_conf.mbssid_tx_vif) ++ tx_arvif = (void *)arvif->vif->bss_conf.mbssid_tx_vif->drv_priv; + + bcn = ieee80211_beacon_get_template(tx_arvif->ar->hw, tx_arvif->vif, + &offs, 0); +@@ -1762,8 +1762,8 @@ static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif) + if (arvif->vdev_type != WMI_VDEV_TYPE_AP) + return 0; + +- if (vif->mbssid_tx_vif && +- arvif != (void *)vif->mbssid_tx_vif->drv_priv && ++ if (vif->bss_conf.mbssid_tx_vif && ++ arvif != (void *)vif->bss_conf.mbssid_tx_vif->drv_priv && + arvif->is_up) + return 0; + +@@ -1802,8 +1802,8 @@ static void ath11k_control_beaconing(struct ath11k_vif *arvif, + int ret = 0; + struct vdev_up_params params = { 0 }; + +- if (arvif->vif->mbssid_tx_vif) +- tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv; ++ if (arvif->vif->bss_conf.mbssid_tx_vif) ++ tx_arvif = (void *)arvif->vif->bss_conf.mbssid_tx_vif->drv_priv; + + lockdep_assert_held(&arvif->ar->conf_mutex); + +@@ -3414,8 +3414,8 @@ static void ath11k_bss_disassoc(struct ieee80211_hw *hw, + arvif->vdev_id, ret); + + arvif->is_up = false; +- if (arvif->vif->mbssid_tx_vif) { +- tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv; ++ if (arvif->vif->bss_conf.mbssid_tx_vif) { ++ tx_arvif = (void *)arvif->vif->bss_conf.mbssid_tx_vif->drv_priv; + if (tx_arvif != arvif) + tx_arvif->nontransmitting_vif_count--; + } +@@ -7797,7 +7797,7 @@ static int ath11k_mac_setup_vdev_params_mbssid(struct ath11k_vif *arvif, + struct ieee80211_vif *tx_vif; + + *tx_vdev_id = 0; +- tx_vif = arvif->vif->mbssid_tx_vif; ++ tx_vif = arvif->vif->bss_conf.mbssid_tx_vif; + if (!tx_vif) { + *flags = WMI_HOST_VDEV_FLAGS_NON_MBSSID_AP; + return 0; +@@ -9081,8 +9081,8 @@ ath11k_mac_update_vif_chan(struct ath11k *ar, + params.vdev_id = arvif->vdev_id; + params.aid = arvif->aid; + params.bssid = arvif->bssid; +- if (arvif->vif->mbssid_tx_vif) { +- tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv; ++ if (arvif->vif->bss_conf.mbssid_tx_vif) { ++ tx_arvif = (void *)arvif->vif->bss_conf.mbssid_tx_vif->drv_priv; + params.tx_bssid = tx_arvif->bssid; + params.profile_idx = arvif->vif->bss_conf.bssid_index; + params.profile_count = tx_arvif->nontransmitting_vif_count; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/716-a-ath12k-Add-tx-datapath-related-soc-and-link-stats.patch b/feeds/ipq95xx/mac80211/patches/qca/716-a-ath12k-Add-tx-datapath-related-soc-and-link-stats.patch new file mode 100644 index 000000000..70230d01d --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/716-a-ath12k-Add-tx-datapath-related-soc-and-link-stats.patch @@ -0,0 +1,596 @@ +From 9e1755c16893db73dbfcfa30c3636ea8d76b701d Mon Sep 17 00:00:00 2001 +From: Balamurugan Mahalingam +Date: Mon, 27 Feb 2023 02:02:52 -0800 +Subject: [PATCH 1/2] ath12k: Add tx datapath related soc and link stats + +The soc and link related transmit datapath stats helps +understand the different metrics and helps in debug + +Signed-off-by: Balamurugan Mahalingam +Signed-off-by: Sidhanta Sahu +--- + drivers/net/wireless/ath/ath12k/core.h | 12 ++ + drivers/net/wireless/ath/ath12k/debugfs.c | 217 ++++++++++++++++++++- + drivers/net/wireless/ath/ath12k/dp.h | 16 +- + drivers/net/wireless/ath/ath12k/dp_tx.c | 53 +++-- + drivers/net/wireless/ath/ath12k/hal_desc.h | 5 + + drivers/net/wireless/ath/ath12k/mac.c | 2 +- + 6 files changed, 285 insertions(+), 20 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h +index 1d3a4f0..e21d360 100644 +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -351,6 +351,7 @@ struct ath12k_link_vif { + struct ath12k_reg_tpc_power_info reg_tpc_info; + u8 vdev_stats_id; + struct ath12k_fw_vdev_ol_stats vdev_stats; ++ struct host_link_stats link_stats; + u8 nontransmitting_vif_count; + bool bcca_zero_sent; + bool do_not_send_tmpl; +@@ -405,6 +406,9 @@ struct ath12k_vif { + u8 num_vdev_started; + struct ath12k_vif_cache cache[IEEE80211_MLD_MAX_NUM_LINKS]; + u8 last_scan_link; ++#ifdef CPTCFG_ATH12K_DEBUGFS ++ struct dentry *debugfs_linkstats; ++#endif /* CPTCFG_ATH12K_DEBUGFS */ + }; + + struct ath12k_vif_iter { +@@ -1046,6 +1050,14 @@ struct ath12k_soc_dp_stats { + u32 mon_drop_desc; + u32 hal_reo_cmd_drain; + u32 reo_cmd_cache_error; ++ u32 mcast_enqueued; ++ u32 ucast_enqueued; ++ u32 mcast_reinject; ++ u32 wbm_rel_source[HAL_WBM_REL_SRC_MODULE_MAX]; ++ u32 tqm_rel_reason[MAX_TQM_RELEASE_REASON]; ++ u32 fw_tx_status[MAX_FW_TX_STATUS]; ++ u32 tx_enqueued[MAX_TCL_RING]; ++ u32 tx_completed[MAX_TCL_RING]; + struct ath12k_soc_dp_tx_err_stats tx_err; + struct ath12k_dp_ring_bp_stats bp_stats; + }; +diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c +index cabb64d..a7b2e8c 100644 +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -1489,6 +1489,59 @@ static ssize_t ath12k_debugfs_dump_soc_dp_stats(struct file *file, + "\nREO_CMD_CACHE_FLUSH Failure: %u\n", + soc_stats->reo_cmd_cache_error); + ++ len += scnprintf(buf + len, size - len, ++ "\nmcast reinject: %u\n", ++ soc_stats->mcast_reinject); ++ ++ len += scnprintf(buf + len, size - len, ++ "\nwbm_rel_source: 0:%u 1:%u 2:%u 3:%u 4:%u\n", ++ soc_stats->wbm_rel_source[0], ++ soc_stats->wbm_rel_source[1], ++ soc_stats->wbm_rel_source[2], ++ soc_stats->wbm_rel_source[3], ++ soc_stats->wbm_rel_source[4]); ++ ++ len += scnprintf(buf + len, size - len, ++ "\ntqm_rel_reason: 0:%u 1:%u 2:%u 3:%u 4:%u 5:%u 6:%u 7:%u 8:%u 9:%u 10:%u 11:%u 12:%u 13:%u\n", ++ soc_stats->tqm_rel_reason[0], ++ soc_stats->tqm_rel_reason[1], ++ soc_stats->tqm_rel_reason[2], ++ soc_stats->tqm_rel_reason[3], ++ soc_stats->tqm_rel_reason[4], ++ soc_stats->tqm_rel_reason[5], ++ soc_stats->tqm_rel_reason[6], ++ soc_stats->tqm_rel_reason[7], ++ soc_stats->tqm_rel_reason[8], ++ soc_stats->tqm_rel_reason[9], ++ soc_stats->tqm_rel_reason[10], ++ soc_stats->tqm_rel_reason[11], ++ soc_stats->tqm_rel_reason[12], ++ soc_stats->tqm_rel_reason[13]); ++ ++ len += scnprintf(buf + len, size - len, ++ "\nfw_tx_status: 0:%u 1:%u 2:%u 3:%u 4:%u 5:%u 6:%u\n", ++ soc_stats->fw_tx_status[0], ++ soc_stats->fw_tx_status[1], ++ soc_stats->fw_tx_status[2], ++ soc_stats->fw_tx_status[3], ++ soc_stats->fw_tx_status[4], ++ soc_stats->fw_tx_status[5], ++ soc_stats->fw_tx_status[6]); ++ ++ len += scnprintf(buf + len, size - len, ++ "\ntx_enqueued: 0:%u 1:%u 2:%u 3:%u\n", ++ soc_stats->tx_enqueued[0], ++ soc_stats->tx_enqueued[1], ++ soc_stats->tx_enqueued[2], ++ soc_stats->tx_enqueued[3]); ++ ++ len += scnprintf(buf + len, size - len, ++ "\ntx_completed: 0:%u 1:%u 2:%u 3:%u\n", ++ soc_stats->tx_completed[0], ++ soc_stats->tx_completed[1], ++ soc_stats->tx_completed[2], ++ soc_stats->tx_completed[3]); ++ + len += ath12k_debugfs_dump_soc_ring_bp_stats(ab, buf + len, size - len); + + if (len > size) +@@ -1499,8 +1552,32 @@ static ssize_t ath12k_debugfs_dump_soc_dp_stats(struct file *file, + return retval; + } + ++static ssize_t ++ath12k_debugfs_write_soc_dp_stats(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k_base *ab = file->private_data; ++ struct ath12k_soc_dp_stats *soc_stats = &ab->soc_stats; ++ char buf[20] = {0}; ++ int ret; ++ ++ if (count > 20) ++ return -EFAULT; ++ ++ ret = copy_from_user(buf, user_buf, count); ++ if (ret) ++ return -EFAULT; ++ ++ if (strstr(buf, "reset")) ++ memset(soc_stats, 0, sizeof(struct ath12k_soc_dp_stats)); ++ ++ return count; ++} ++ + static const struct file_operations fops_soc_dp_stats = { + .read = ath12k_debugfs_dump_soc_dp_stats, ++ .write = ath12k_debugfs_write_soc_dp_stats, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +@@ -4058,6 +4135,105 @@ static const struct file_operations ath12k_fops_twt_resume_dialog = { + .open = simple_open + }; + ++static int ath12k_open_link_stats(struct inode *inode, struct file *file) ++{ ++ struct ath12k_vif *ahvif = inode->i_private; ++ struct ath12k_hw *ah = ahvif->ah; ++ struct host_link_stats *linkstat = NULL; ++ size_t len = 0, buf_len = PAGE_SIZE * 2; ++ char *buf; ++ int link_id; ++ ++ if (!ahvif) ++ return -EINVAL; ++ ++ buf = kzalloc(buf_len, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ file->private_data = buf; ++ ++ mutex_lock(&ah->conf_mutex); ++ for_each_set_bit(link_id, &ahvif->links_map, ++ IEEE80211_MLD_MAX_NUM_LINKS) { ++ if (ahvif->link[link_id]) ++ linkstat = &ahvif->link[link_id]->link_stats; ++ else ++ break; ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "link[%d] tx_enqueued = %d\n", ++ link_id, linkstat->tx_enqueued); ++ len += scnprintf(buf + len, buf_len - len, ++ "link[%d] tx_completed = %d\n", ++ link_id, linkstat->tx_completed); ++ len += scnprintf(buf + len, buf_len - len, ++ "link[%d] tx_bcast_mcast = %d\n", ++ link_id, linkstat->tx_bcast_mcast); ++ len += scnprintf(buf + len, buf_len - len, ++ "link[%d] tx_dropped = %d\n", ++ link_id, linkstat->tx_dropped); ++ len += scnprintf(buf + len, buf_len - len, ++ "link[%d] tx_encap_type = 0:%d 1:%d 2:%d 3:%d\n", ++ link_id, linkstat->tx_encap_type[0], ++ linkstat->tx_encap_type[1], ++ linkstat->tx_encap_type[2], ++ linkstat->tx_encap_type[3]); ++ len += scnprintf(buf + len, buf_len - len, ++ "link[%d] tx_encrypt_type = 0:%d 1:%d 2:%d " \ ++ "3:%d 4:%d 5:%d 6:%d 7:%d 8:%d 9:%d 10:%d 11:%d\n", ++ link_id, linkstat->tx_encrypt_type[0], ++ linkstat->tx_encrypt_type[1], ++ linkstat->tx_encrypt_type[2], ++ linkstat->tx_encrypt_type[3], ++ linkstat->tx_encrypt_type[4], ++ linkstat->tx_encrypt_type[5], ++ linkstat->tx_encrypt_type[6], ++ linkstat->tx_encrypt_type[7], ++ linkstat->tx_encrypt_type[8], ++ linkstat->tx_encrypt_type[9], ++ linkstat->tx_encrypt_type[10], ++ linkstat->tx_encrypt_type[11]); ++ len += scnprintf(buf + len, buf_len - len, ++ "link[%d] tx_desc_type = 0:%d 1:%d\n", ++ link_id, linkstat->tx_desc_type[0], ++ linkstat->tx_desc_type[1]); ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "------------------------------------------------------\n"); ++ } ++ mutex_unlock(&ah->conf_mutex); ++ return 0; ++} ++ ++static int ath12k_release_link_stats(struct inode *inode, struct file *file) ++{ ++ char *buf = file->private_data; ++ ++ kfree(buf); ++ return 0; ++} ++ ++static ssize_t ath12k_read_link_stats(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ const char *buf = file->private_data; ++ size_t len = strlen(buf); ++ int ret; ++ ++ ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ return ret; ++} ++ ++static const struct file_operations ath12k_fops_link_stats = { ++ .open = ath12k_open_link_stats, ++ .release = ath12k_release_link_stats, ++ .read = ath12k_read_link_stats, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ + int ath12k_debugfs_add_interface(struct ath12k_link_vif *arvif) + { + struct ath12k_vif *ahvif = arvif->ahvif; +@@ -4122,6 +4298,29 @@ int ath12k_debugfs_add_interface(struct ath12k_link_vif *arvif) + } + } + ++ if (ahvif->debugfs_linkstats) ++ goto exit; ++ ++ ahvif->debugfs_linkstats = debugfs_create_file("link_stats", ++ 0200, ++ vif->debugfs_dir, ++ ahvif, ++ &ath12k_fops_link_stats); ++ if (!ahvif->debugfs_linkstats || ++ IS_ERR(ahvif->debugfs_linkstats)) { ++ ath12k_warn(arvif->ar->ab, ++ "failed to create link_stats file"); ++ debugfs_remove_recursive(arvif->debugfs_twt); ++ arvif->debugfs_twt = NULL; ++ ++ if (hw->wiphy->num_hw) { ++ debugfs_remove(arvif->debugfs_rtsthreshold); ++ arvif->debugfs_rtsthreshold = NULL; ++ } ++ ++ ahvif->debugfs_linkstats = NULL; ++ } ++ + exit: + return ret; + } +@@ -4132,21 +4331,27 @@ void ath12k_debugfs_remove_interface(struct ath12k_link_vif *arvif) + struct ieee80211_vif *vif = ahvif->vif; + u8 link_id = arvif->link_id; + +- if (!arvif->debugfs_twt) +- return; +- +- if (!arvif->debugfs_rtsthreshold) +- return; +- + if (!vif || !vif->link_debugfs[link_id]) { + arvif->debugfs_twt = NULL; + arvif->debugfs_rtsthreshold = NULL; ++ ahvif->debugfs_linkstats = NULL; + return; + } + ++ if (ahvif->debugfs_linkstats) { ++ debugfs_remove(ahvif->debugfs_linkstats); ++ ahvif->debugfs_linkstats = NULL; ++ } ++ ++ if (!arvif->debugfs_twt) ++ return; ++ + debugfs_remove_recursive(arvif->debugfs_twt); + arvif->debugfs_twt = NULL; + ++ if (!arvif->debugfs_rtsthreshold) ++ return; ++ + debugfs_remove(arvif->debugfs_rtsthreshold); + arvif->debugfs_rtsthreshold = NULL; + } +diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h +index 3409c35..2c23c1f 100644 +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -6,7 +6,7 @@ + + #ifndef ATH12K_DP_H + #define ATH12K_DP_H +- ++#include "core.h" + #include "hal_rx.h" + #include "hw.h" + +@@ -258,6 +258,10 @@ struct ath12k_pdev_dp { + /* Invalid TX Bank ID value */ + #define DP_INVALID_BANK_ID -1 + ++#define MAX_TQM_RELEASE_REASON 14 ++#define MAX_FW_TX_STATUS 7 ++#define MAX_TCL_RING 4 ++ + struct ath12k_dp_tx_bank_profile { + u8 is_configured; + u32 num_users; +@@ -308,6 +312,16 @@ struct ath12k_reo_q_addr_lut { + u32 *vaddr; + }; + ++struct host_link_stats { ++ u32 tx_enqueued; ++ u32 tx_completed; ++ u32 tx_bcast_mcast; ++ u32 tx_dropped; ++ u32 tx_encap_type[HAL_TCL_ENCAP_TYPE_MAX]; ++ u32 tx_encrypt_type[HAL_ENCRYPT_TYPE_MAX]; ++ u32 tx_desc_type[HAL_TCL_DESC_TYPE_MAX]; ++}; ++ + struct ath12k_dp { + struct ath12k_base *ab; + u8 num_bank_profiles; +diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c +index e150831..6628e5e 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -412,6 +412,10 @@ tcl_ring_sel: + goto fail_unmap_dma_ext_desc; + } + ++ ab->soc_stats.tx_enqueued[ti.ring_id]++; ++ arvif->link_stats.tx_encap_type[ti.encap_type]++; ++ arvif->link_stats.tx_encrypt_type[ti.encrypt_type]++; ++ arvif->link_stats.tx_desc_type[ti.type]++; + ath12k_hal_tx_cmd_desc_setup(ab, hal_tcl_desc, &ti); + + ath12k_hal_srng_access_end(ab, tcl_ring); +@@ -420,7 +424,7 @@ tcl_ring_sel: + + ath12k_dbg_dump(ab, ATH12K_DBG_DP_TX, NULL, "dp tx msdu: ", + skb->data, skb->len); +- ++ arvif->link_stats.tx_enqueued++; + atomic_inc(&ar->dp.num_tx_pending); + + return 0; +@@ -440,6 +444,7 @@ fail_remove_tx_buf: + if (ti.pkt_offset) + skb_pull(skb, ti.pkt_offset); + ++ arvif->link_stats.tx_dropped++; + if (tcl_ring_retry) + goto tcl_ring_sel; + +@@ -483,12 +488,14 @@ ath12k_dp_tx_htt_tx_complete_buf(struct ath12k_base *ab, + struct ath12k_skb_cb *skb_cb; + struct ath12k *ar; + struct ieee80211_vif *vif; ++ struct ath12k_vif *ahvif; + u8 flags = 0; + + skb_cb = ATH12K_SKB_CB(msdu); + info = IEEE80211_SKB_CB(msdu); + + ar = skb_cb->ar; ++ ab->soc_stats.tx_completed[tx_ring->tcl_data_ring_id]++; + + if (atomic_dec_and_test(&ar->dp.num_tx_pending)) + wake_up(&ar->dp.tx_empty_waitq); +@@ -522,6 +529,14 @@ ath12k_dp_tx_htt_tx_complete_buf(struct ath12k_base *ab, + } + + vif = skb_cb->vif; ++ ahvif = (void *)vif->drv_priv; ++ if (ahvif->links_map & BIT(skb_cb->link_id)) ++ ahvif->link[skb_cb->link_id]->link_stats.tx_completed++; ++ else ++ ath12k_warn(ab, ++ "invalid linkid 0x%X in htt tx complete buf linkmap 0x%X\n", ++ skb_cb->link_id, ++ ahvif->links_map); + + memset(&info->status, 0, sizeof(info->status)); + +@@ -551,18 +566,20 @@ ath12k_dp_tx_process_htt_tx_complete(struct ath12k_base *ab, + { + struct htt_tx_wbm_completion *status_desc; + struct ath12k_dp_htt_wbm_tx_status ts = {0}; +- enum hal_wbm_htt_tx_comp_status wbm_status; ++ int htt_status; + + status_desc = desc + HTT_TX_WBM_COMP_STATUS_OFFSET; + +- wbm_status = u32_get_bits(status_desc->info0, ++ htt_status = u32_get_bits(status_desc->info0, + HTT_TX_WBM_COMP_INFO0_STATUS); + +- switch (wbm_status) { +- case HAL_WBM_REL_HTT_TX_COMP_STATUS_OK: ++ ab->soc_stats.fw_tx_status[htt_status]++; ++ ++ switch (htt_status) { + case HAL_WBM_REL_HTT_TX_COMP_STATUS_DROP: + case HAL_WBM_REL_HTT_TX_COMP_STATUS_TTL: +- ts.acked = (wbm_status == HAL_WBM_REL_HTT_TX_COMP_STATUS_OK); ++ case HAL_WBM_REL_HTT_TX_COMP_STATUS_OK: ++ ts.acked = (htt_status == HAL_WBM_REL_HTT_TX_COMP_STATUS_OK); + ts.ack_rssi = u32_get_bits(status_desc->info2, + HTT_TX_WBM_COMP_INFO2_ACK_RSSI); + ath12k_dp_tx_htt_tx_complete_buf(ab, msdu, tx_ring, &ts, skb_ext_desc); +@@ -577,7 +594,7 @@ ath12k_dp_tx_process_htt_tx_complete(struct ath12k_base *ab, + */ + break; + default: +- ath12k_warn(ab, "Unknown htt tx status %d\n", wbm_status); ++ ath12k_warn(ab, "Unknown htt tx status %d\n", htt_status); + break; + } + } +@@ -743,10 +760,9 @@ static void ath12k_dp_tx_complete_msdu(struct ath12k *ar, + struct sk_buff *msdu, + struct hal_wbm_release_ring *tx_status, + enum hal_wbm_rel_src_module buf_rel_source, +- struct sk_buff *skb_ext_desc) ++ struct sk_buff *skb_ext_desc, int ring) + { + struct ieee80211_tx_status status = { 0 }; +- + struct ath12k_base *ab = ar->ab; + struct ieee80211_tx_info *info; + struct ath12k_skb_cb *skb_cb; +@@ -757,6 +773,7 @@ static void ath12k_dp_tx_complete_msdu(struct ath12k *ar, + enum hal_wbm_tqm_rel_reason rel_status; + enum hal_wbm_htt_tx_comp_status wbm_status; + struct ieee80211_vif *vif; ++ struct ath12k_vif *ahvif; + u8 flags = 0; + + +@@ -766,7 +783,7 @@ static void ath12k_dp_tx_complete_msdu(struct ath12k *ar, + } + + skb_cb = ATH12K_SKB_CB(msdu); +- ++ ab->soc_stats.tx_completed[ring]++; + dma_unmap_single_attrs(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE, + DMA_ATTR_SKIP_CPU_SYNC); + if (unlikely(skb_cb->paddr_ext_desc)) { +@@ -812,6 +829,14 @@ static void ath12k_dp_tx_complete_msdu(struct ath12k *ar, + tx_status->info0); + + vif = skb_cb->vif; ++ ahvif = (void *)vif->drv_priv; ++ if (ahvif->links_map & BIT(skb_cb->link_id)) ++ ahvif->link[skb_cb->link_id]->link_stats.tx_completed++; ++ else ++ ath12k_warn(ar->ab, ++ "invalid linkid 0x%X in tx complete msdu linkmap 0x%X\n", ++ skb_cb->link_id, ++ ahvif->links_map); + + info = IEEE80211_SKB_CB(msdu); + memset(&info->status, 0, sizeof(info->status)); +@@ -985,11 +1010,13 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id) + ath12k_dp_tx_release_txbuf(dp, tx_desc, tx_desc->pool_id); + buf_rel_source = FIELD_GET(HAL_WBM_RELEASE_INFO0_REL_SRC_MODULE, + tx_status->info0); ++ ab->soc_stats.wbm_rel_source[buf_rel_source]++; + if (unlikely(buf_rel_source == HAL_WBM_REL_SRC_MODULE_FW)) { + ath12k_dp_tx_process_htt_tx_complete(ab, + (void *)tx_status, + mac_id, msdu, +- tx_ring, skb_ext_desc); ++ tx_ring, ++ skb_ext_desc); + continue; + } + +@@ -998,7 +1025,9 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id) + if (atomic_dec_and_test(&ar->dp.num_tx_pending)) + wake_up(&ar->dp.tx_empty_waitq); + +- ath12k_dp_tx_complete_msdu(ar, msdu, tx_status, buf_rel_source, skb_ext_desc); ++ ath12k_dp_tx_complete_msdu(ar, msdu, tx_status, ++ buf_rel_source, skb_ext_desc, ++ tx_ring->tcl_data_ring_id); + } + } + +diff --git a/drivers/net/wireless/ath/ath12k/hal_desc.h b/drivers/net/wireless/ath/ath12k/hal_desc.h +index fc02e06..21ea8fc 100644 +--- a/drivers/net/wireless/ath/ath12k/hal_desc.h ++++ b/drivers/net/wireless/ath/ath12k/hal_desc.h +@@ -1251,6 +1251,7 @@ struct hal_reo_flush_cache { + + #define HAL_TCL_DATA_CMD_INFO5_RING_ID GENMASK(27, 20) + #define HAL_TCL_DATA_CMD_INFO5_LOOPING_COUNT GENMASK(31, 28) ++#define HAL_ENCRYPT_TYPE_MAX 12 + + enum hal_encrypt_type { + HAL_ENCRYPT_TYPE_WEP_40, +@@ -1272,11 +1273,13 @@ enum hal_tcl_encap_type { + HAL_TCL_ENCAP_TYPE_NATIVE_WIFI, + HAL_TCL_ENCAP_TYPE_ETHERNET, + HAL_TCL_ENCAP_TYPE_802_3 = 3, ++ HAL_TCL_ENCAP_TYPE_MAX + }; + + enum hal_tcl_desc_type { + HAL_TCL_DESC_TYPE_BUFFER, + HAL_TCL_DESC_TYPE_EXT_DESC, ++ HAL_TCL_DESC_TYPE_MAX, + }; + + enum hal_wbm_htt_tx_comp_status { +@@ -1286,6 +1289,7 @@ enum hal_wbm_htt_tx_comp_status { + HAL_WBM_REL_HTT_TX_COMP_STATUS_REINJ, + HAL_WBM_REL_HTT_TX_COMP_STATUS_INSPECT, + HAL_WBM_REL_HTT_TX_COMP_STATUS_MEC_NOTIFY, ++ HAL_WBM_REL_HTT_TX_COMP_STATUS_VDEVID_MISMATCH, + HAL_WBM_REL_HTT_TX_COMP_STATUS_MAX, + }; + +@@ -1794,6 +1798,7 @@ enum hal_wbm_rel_src_module { + HAL_WBM_REL_SRC_MODULE_REO, + HAL_WBM_REL_SRC_MODULE_FW, + HAL_WBM_REL_SRC_MODULE_SW, ++ HAL_WBM_REL_SRC_MODULE_MAX, + }; + + enum hal_wbm_rel_desc_type { +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index ed5c470..f8652df 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -8498,6 +8498,7 @@ static void ath12k_mac_op_tx(struct ieee80211_hw *hw, + } + + arvif = ahvif->link[link]; ++ skb_cb->link_id = link; + + if (!arvif || !arvif->ar) { + ieee80211_free_txskb(hw, skb); +@@ -8522,7 +8523,6 @@ static void ath12k_mac_op_tx(struct ieee80211_hw *hw, + } else if (ieee80211_is_mgmt(hdr->frame_control)) { + frm_type = FIELD_GET(IEEE80211_FCTL_STYPE, hdr->frame_control); + is_prb_rsp = ieee80211_is_probe_resp(hdr->frame_control); +- skb_cb->link_id = link; + ret = ath12k_mac_mgmt_tx(ar, skb, is_prb_rsp); + if (ret) { + if (ret != -EBUSY) +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/716-ath12k-AP-bringup-with-5G-Low-5G-High-in-dfs-channel.patch b/feeds/ipq95xx/mac80211/patches/qca/716-ath12k-AP-bringup-with-5G-Low-5G-High-in-dfs-channel.patch new file mode 100644 index 000000000..f27739f6c --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/716-ath12k-AP-bringup-with-5G-Low-5G-High-in-dfs-channel.patch @@ -0,0 +1,401 @@ +From e856bbceb4c8ca1af0f5384d12670a5b691ab55a Mon Sep 17 00:00:00 2001 +From: Vishal Kumar +Date: Fri, 24 Feb 2023 19:07:13 +0530 +Subject: [PATCH] ath12k: AP bringup with 5G Low + 5G High in dfs channel + within same mld + +when one of the 5G low or high interface up with dfs channel, +link->radar_required flag gets true and causing channel scan failure +for another 5G interface. its because link->radar_required check is +not based on hw_idx. now added hw_idx check with link->radar_required so +only specific hw_idx used for link->radar_required. + +Signed-off-by: Vishal Kumar +--- + include/net/cfg80211.h | 6 +++--- + net/mac80211/chan.c | 30 ++++++++++++++++++++---------- + net/mac80211/ieee80211_i.h | 3 ++- + net/mac80211/offchannel.c | 3 ++- + net/mac80211/scan.c | 20 +++++++++++++------- + net/mac80211/util.c | 28 +++++++++++++++++----------- + net/wireless/chan.c | 3 +++ + net/wireless/nl80211.c | 11 +++++++++++ + net/wireless/util.c | 23 +++++++++-------------- + 9 files changed, 80 insertions(+), 47 deletions(-) + +diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h +index 25367da..3a76af9 100644 +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -2602,6 +2602,7 @@ struct cfg80211_scan_request { + bool scan_6ghz; + u32 n_6ghz_params; + struct cfg80211_scan_6ghz_params *scan_6ghz_params; ++ u8 hw_idx; + + /* keep last */ + struct ieee80211_channel *channels[]; +@@ -8904,14 +8905,13 @@ bool cfg80211_per_hw_iface_comb_advertised(struct wiphy *wiphy); + * cfg80211_get_hw_idx_by_chan - get the hw index by the channel + * + * @wiphy: the wiphy +- * @chandef: channel definition for which the supported hw index is +- * required ++ * @chan: channel for which the supported hw index is required + * + * returns -1 in case the channel is not supported by any of the constituent + * hw + */ + int cfg80211_get_hw_idx_by_chan(struct wiphy *wiphy, +- const struct cfg80211_chan_def *chandef); ++ const struct ieee80211_channel *chan); + + /* + * cfg80211_stop_iface - trigger interface disconnection +diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c +index 9020088..7d26313 100644 +--- a/net/mac80211/chan.c ++++ b/net/mac80211/chan.c +@@ -52,21 +52,23 @@ static int ieee80211_num_chanctx(struct ieee80211_local *local, + { + struct ieee80211_chanctx *ctx; + int num = 0; +- int hw_idx, ctx_idx; ++ int hw_idx = -1, ctx_idx; + + lockdep_assert_held(&local->chanctx_mtx); + +- hw_idx = cfg80211_get_hw_idx_by_chan(local->hw.wiphy, chandef); ++ if (cfg80211_chandef_valid(chandef)) ++ hw_idx = cfg80211_get_hw_idx_by_chan(local->hw.wiphy, chandef->chan); + + list_for_each_entry(ctx, &local->chanctx_list, list) { + if (hw_idx < 0) + num++; + else { +- ctx_idx = +- cfg80211_get_hw_idx_by_chan(local->hw.wiphy, +- &ctx->conf.def); +- if (ctx_idx == hw_idx) +- num++; ++ if (cfg80211_chandef_valid(&ctx->conf.def)) { ++ ctx_idx = cfg80211_get_hw_idx_by_chan(local->hw.wiphy, ++ ctx->conf.def.chan); ++ if (ctx_idx == hw_idx) ++ num++; ++ } + } + } + +@@ -567,9 +569,12 @@ ieee80211_find_chanctx(struct ieee80211_local *local, + return NULL; + } + +-bool ieee80211_is_radar_required(struct ieee80211_local *local) ++bool ieee80211_is_radar_required(struct ieee80211_local *local, ++ struct cfg80211_scan_request *req) + { + struct ieee80211_sub_if_data *sdata; ++ struct wiphy *wiphy = local->hw.wiphy; ++ s8 hw_idx; + + lockdep_assert_held(&local->mtx); + +@@ -583,8 +588,13 @@ bool ieee80211_is_radar_required(struct ieee80211_local *local) + link = rcu_dereference(sdata->link[link_id]); + + if (link && link->radar_required) { +- rcu_read_unlock(); +- return true; ++ struct ieee80211_channel *chan = link->conf->chandef.chan; ++ ++ hw_idx = cfg80211_get_hw_idx_by_chan(wiphy, chan); ++ if (hw_idx == req->hw_idx) { ++ rcu_read_unlock(); ++ return true; ++ } + } + } + } +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index 6eaa5f8..c525789 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -2543,7 +2543,8 @@ void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, + struct ieee80211_chanctx *chanctx); + void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local, + struct ieee80211_chanctx *ctx); +-bool ieee80211_is_radar_required(struct ieee80211_local *local); ++bool ieee80211_is_radar_required(struct ieee80211_local *local, ++ struct cfg80211_scan_request *req); + + void ieee80211_dfs_cac_timer(unsigned long data); + void ieee80211_dfs_cac_timer_work(struct work_struct *work); +diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c +index 2b51e9c..e61d867 100644 +--- a/net/mac80211/offchannel.c ++++ b/net/mac80211/offchannel.c +@@ -539,6 +539,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, + struct ieee80211_roc_work *roc, *tmp; + bool queued = false, combine_started = true; + int ret; ++ struct cfg80211_scan_request *req; + + lockdep_assert_held(&local->mtx); + +@@ -587,7 +588,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, + + /* if there's no need to queue, handle it immediately */ + if (list_empty(&local->roc_list) && +- !local->scanning && !ieee80211_is_radar_required(local)) { ++ !local->scanning && !ieee80211_is_radar_required(local, req)) { + /* if not HW assist, just queue & schedule work */ + if (!local->ops->remain_on_channel) { + list_add_tail(&roc->list, &local->roc_list); +diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c +index 55ed333..d35c1bb 100644 +--- a/net/mac80211/scan.c ++++ b/net/mac80211/scan.c +@@ -571,12 +571,13 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local, + return 0; + } + +-static bool __ieee80211_can_leave_ch(struct ieee80211_sub_if_data *sdata) ++static bool __ieee80211_can_leave_ch(struct ieee80211_sub_if_data *sdata, ++ struct cfg80211_scan_request *req) + { + struct ieee80211_local *local = sdata->local; + struct ieee80211_sub_if_data *sdata_iter; + +- if (!ieee80211_is_radar_required(local)) ++ if (!ieee80211_is_radar_required(local, req)) + return true; + + if (!regulatory_pre_cac_allowed(local->hw.wiphy)) +@@ -596,9 +597,10 @@ static bool __ieee80211_can_leave_ch(struct ieee80211_sub_if_data *sdata) + } + + static bool ieee80211_can_scan(struct ieee80211_local *local, +- struct ieee80211_sub_if_data *sdata) ++ struct ieee80211_sub_if_data *sdata, ++ struct cfg80211_scan_request *req) + { +- if (!__ieee80211_can_leave_ch(sdata)) ++ if (!__ieee80211_can_leave_ch(sdata, req)) + return false; + + if (!list_empty(&local->roc_list)) +@@ -613,15 +615,19 @@ static bool ieee80211_can_scan(struct ieee80211_local *local, + + void ieee80211_run_deferred_scan(struct ieee80211_local *local) + { ++ struct cfg80211_scan_request *req; ++ + lockdep_assert_held(&local->mtx); + + if (!local->scan_req || local->scanning) + return; + ++ req = local->scan_req; ++ + if (!ieee80211_can_scan(local, + rcu_dereference_protected( + local->scan_sdata, +- lockdep_is_held(&local->mtx)))) ++ lockdep_is_held(&local->mtx)), req)) + return; + + ieee80211_queue_delayed_work(&local->hw, &local->scan_work, +@@ -713,10 +719,10 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, + if (local->scan_req) + return -EBUSY; + +- if (!__ieee80211_can_leave_ch(sdata)) ++ if (!__ieee80211_can_leave_ch(sdata, req)) + return -EBUSY; + +- if (!ieee80211_can_scan(local, sdata)) { ++ if (!ieee80211_can_scan(local, sdata, req)) { + /* wait for the work to finish/time out */ + rcu_assign_pointer(local->scan_req, req); + rcu_assign_pointer(local->scan_sdata, sdata); +diff --git a/net/mac80211/util.c b/net/mac80211/util.c +index 06006d9..0902c83 100644 +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -4984,9 +4984,9 @@ ieee80211_get_per_hw_sdata_active_iface(struct ieee80211_sub_if_data *sdata, + ctx = ctx->replace_ctx; + + idx = -1; +- if (ctx) ++ if (ctx && cfg80211_chandef_valid(&ctx->conf.def)) + idx = cfg80211_get_hw_idx_by_chan(local->hw.wiphy, +- &ctx->conf.def); ++ ctx->conf.def.chan); + + if (idx >= 0) + params->per_hw[idx].iftype_num[sdata->wdev.iftype]++; +@@ -5009,7 +5009,7 @@ ieee80211_prepare_per_hw_iface_combination(struct ieee80211_sub_if_data *sdata, + struct ieee80211_sub_if_data *sdata_iter; + enum nl80211_iftype iftype = sdata->wdev.iftype; + struct ieee80211_chanctx *ctx; +- int hchan_idx; ++ int hchan_idx = -1; + size_t size; + bool sdata_included = false; + +@@ -5021,20 +5021,24 @@ ieee80211_prepare_per_hw_iface_combination(struct ieee80211_sub_if_data *sdata, + if (!params->per_hw) + return -ENOMEM; + +- hchan_idx = cfg80211_get_hw_idx_by_chan(local->hw.wiphy, chandef); +- if (hchan_idx >= 0) { +- params->per_hw[hchan_idx].num_different_channels = 1; +- if (iftype != NL80211_IFTYPE_UNSPECIFIED) { +- params->per_hw[hchan_idx].iftype_num[iftype] = 1; +- sdata_included = true; ++ if (cfg80211_chandef_valid(chandef)) { ++ hchan_idx = cfg80211_get_hw_idx_by_chan(local->hw.wiphy, chandef->chan); ++ if (hchan_idx >= 0) { ++ params->per_hw[hchan_idx].num_different_channels = 1; ++ if (iftype != NL80211_IFTYPE_UNSPECIFIED) { ++ params->per_hw[hchan_idx].iftype_num[iftype] = 1; ++ sdata_included = true; ++ } + } + } + + list_for_each_entry(ctx, &local->chanctx_list, list) { + if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED) + continue; ++ if (WARN_ON(!cfg80211_chandef_valid(&ctx->conf.def))) ++ continue; + hchan_idx = cfg80211_get_hw_idx_by_chan(local->hw.wiphy, +- &ctx->conf.def); ++ ctx->conf.def.chan); + if (WARN_ON(hchan_idx < 0)) + continue; + +@@ -5193,8 +5197,10 @@ ieee80211_max_num_channels_hw_list(struct ieee80211_local *local, + list_for_each_entry(ctx, &local->chanctx_list, list) { + if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED) + continue; ++ if (WARN_ON(!cfg80211_chandef_valid(&ctx->conf.def))) ++ continue; + hchan_idx = cfg80211_get_hw_idx_by_chan(local->hw.wiphy, +- &ctx->conf.def); ++ ctx->conf.def.chan); + if (WARN_ON(hchan_idx < 0)) + continue; + +diff --git a/net/wireless/chan.c b/net/wireless/chan.c +index 5a10c34..d97663a 100644 +--- a/net/wireless/chan.c ++++ b/net/wireless/chan.c +@@ -310,6 +310,9 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef) + u32 control_freq, oper_freq; + int oper_width, control_width; + ++ if (!chandef) ++ return false; ++ + if (!chandef->chan) + return false; + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 2fac612..cbfd823 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -9642,6 +9642,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) + struct nlattr *attr; + struct wiphy *wiphy; + int err, tmp, n_ssids = 0, n_channels = 0, i; ++ s8 hw_idx = -1; + size_t ie_len; + bool chandef_found = false; + +@@ -9740,6 +9741,11 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) + continue; + + request->channels[i] = chan; ++ ++ hw_idx = cfg80211_get_hw_idx_by_chan(wiphy, chan); ++ if (hw_idx >= 0) ++ request->hw_idx = hw_idx; ++ + i++; + } + } else if (!chandef_found) { +@@ -9760,6 +9766,11 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) + continue; + + request->channels[i] = chan; ++ ++ hw_idx = cfg80211_get_hw_idx_by_chan(wiphy, chan); ++ if (hw_idx >= 0) ++ request->hw_idx = hw_idx; ++ + i++; + } + } +diff --git a/net/wireless/util.c b/net/wireless/util.c +index 514ccfe..6e5d7c2 100644 +--- a/net/wireless/util.c ++++ b/net/wireless/util.c +@@ -2250,13 +2250,12 @@ EXPORT_SYMBOL(cfg80211_per_hw_iface_comb_advertised); + + static bool + cfg80211_chan_supported_by_sub_hw(struct ieee80211_chans_per_hw *hw_chans, +- const struct cfg80211_chan_def *chandef) ++ const struct ieee80211_channel *chan) + { + int i; + + for (i = 0; i < hw_chans->n_chans; i++) +- if (chandef->chan->center_freq == +- hw_chans->chans[i].center_freq) ++ if (chan->center_freq == hw_chans->chans[i].center_freq) + return true; + + return false; +@@ -2264,21 +2263,16 @@ cfg80211_chan_supported_by_sub_hw(struct ieee80211_chans_per_hw *hw_chans, + + int + cfg80211_get_hw_idx_by_chan(struct wiphy *wiphy, +- const struct cfg80211_chan_def *chandef) ++ const struct ieee80211_channel *chan) + { + int i; + +- if (!chandef) ++ if (!chan) + return -1; + +- if (!cfg80211_chandef_valid(chandef)) +- return -1; +- +- for (i = 0; i < wiphy->num_hw; i++) { +- if (cfg80211_chan_supported_by_sub_hw(wiphy->hw_chans[i], +- chandef)) ++ for (i = 0; i < wiphy->num_hw; i++) ++ if (cfg80211_chan_supported_by_sub_hw(wiphy->hw_chans[i], chan)) + return i; +- } + + return -1; + } +@@ -2330,8 +2324,9 @@ int cfg80211_iter_combinations(struct wiphy *wiphy, + if (!num_per_hw_ifaces) + return -ENOMEM; + +- hw_chan_idx = cfg80211_get_hw_idx_by_chan(wiphy, +- params->chandef); ++ if (cfg80211_chandef_valid(params->chandef)) ++ hw_chan_idx = cfg80211_get_hw_idx_by_chan(wiphy, ++ params->chandef->chan); + } + + for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) { +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/716-ath12k-sent-pkts.patch b/feeds/ipq95xx/mac80211/patches/qca/716-ath12k-sent-pkts.patch new file mode 100644 index 000000000..854599697 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/716-ath12k-sent-pkts.patch @@ -0,0 +1,142 @@ +From fc17dd03d183b6adf177103c8add19f14c3a0cff Mon Sep 17 00:00:00 2001 +From: saleemuddin shaik +Date: Sat, 4 Mar 2023 13:56:17 +0530 +Subject: ath12k: add statistic support for counting wmm sent packets + +Segregated wmm types for rx path and tx path introduced to +handle bidirectional traffic flow. This will avoid misplaced +piling of the wmm buckets. + +Signed-off-by: saleemuddin shaik +--- + drivers/net/wireless/ath/ath12k/core.h | 8 ++++ + drivers/net/wireless/ath/ath12k/debugfs.c | 52 +++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/dp_rx.c | 2 + + drivers/net/wireless/ath/ath12k/mac.c | 2 + + 4 files changed, 64 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h +index 179f3c3..becfc2a 100644 +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -728,6 +728,13 @@ struct ath12k_chan_info { + u32 num_channels; + }; + ++struct ath12k_wmm_stats { ++ int tx_type; ++ u64 total_wmm_tx_pkts[WME_NUM_AC]; ++}; ++ ++#define ATH12K_DSCP_PRIORITY 7 ++ + #define ATH12K_FLUSH_TIMEOUT (5 * HZ) + #define ATH12K_VDEV_DELETE_TIMEOUT_HZ (5 * HZ) + +@@ -813,6 +820,7 @@ struct ath12k { + int last_wmi_vdev_start_status; + struct completion vdev_setup_done; + struct completion vdev_delete_done; ++ struct ath12k_wmm_stats wmm_stats; + + int num_peers; + int max_num_peers; +diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c +index 877baee..3918aac 100644 +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -1344,6 +1344,53 @@ static const struct file_operations fops_write_nrp_mac = { + .open = simple_open, + }; + ++static ssize_t ath12k_read_wmm_stats(struct file *file, ++ char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ int len = 0; ++ int size = 2048; ++ char *buf; ++ ssize_t retval; ++ u64 total_wmm_sent_pkts = 0; ++ ++ buf = kzalloc(size, GFP_KERNEL); ++ if (!buf) { ++ ath12k_warn("failed to allocate the buffer%s\n", __func__); ++ return -ENOMEM; ++ } ++ ++ mutex_lock(&ar->conf_mutex); ++ for (count = 0; count < WME_NUM_AC; count++) ++ total_wmm_sent_pkts += ar->wmm_stats.total_wmm_tx_pkts[count]; ++ ++ len += scnprintf(buf + len, size - len, "Total number of wmm_sent: %llu\n", ++ total_wmm_sent_pkts); ++ len += scnprintf(buf + len, size - len, "Num of BE wmm_sent: %llu\n", ++ ar->wmm_stats.total_wmm_tx_pkts[WME_AC_BE]); ++ len += scnprintf(buf + len, size - len, "Num of BK wmm_sent: %llu\n", ++ ar->wmm_stats.total_wmm_tx_pkts[WME_AC_BK]); ++ len += scnprintf(buf + len, size - len, "Num of VI wmm_sent: %llu\n", ++ ar->wmm_stats.total_wmm_tx_pkts[WME_AC_VI]); ++ len += scnprintf(buf + len, size - len, "Num of VO wmm_sent: %llu\n", ++ ar->wmm_stats.total_wmm_tx_pkts[WME_AC_VO]); ++ ++ mutex_unlock(&ar->conf_mutex); ++ ++ if (len > size) ++ len = size; ++ retval = simple_read_from_buffer(ubuf, count, ppos, buf, len); ++ kfree(buf); ++ ++ return retval; ++} ++ ++static const struct file_operations fops_wmm_stats = { ++ .read = ath12k_read_wmm_stats, ++ .open = simple_open, ++}; ++ + static int ath12k_fill_bp_stats(struct ath12k_base *ab, + struct ath12k_bp_stats *bp_stats, + char *buf, int len, int size) +@@ -3236,6 +3283,11 @@ int ath12k_debugfs_register(struct ath12k *ar) + + init_completion(&ar->tpc_complete); + ++ memset(&ar->wmm_stats, 0, sizeof(struct ath12k_wmm_stats)); ++ ++ debugfs_create_file("wmm_stats", 0644, ++ ar->debug.debugfs_pdev, ar, ++ &fops_wmm_stats); + debugfs_create_file("neighbor_peer", 0644, + ar->debug.debugfs_pdev, ar, + &fops_write_nrp_mac); +diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c +index 4df469b..a3d1ed8 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -1511,6 +1511,8 @@ ath12k_update_per_peer_tx_stats(struct ath12k *ar, + HTT_PPDU_STATS_ACK_BA_INFO_NUM_MSDU_M); + tid = u32_get_bits(usr_stats->ack_ba.info, + HTT_PPDU_STATS_ACK_BA_INFO_TID_NUM); ++ ar->wmm_stats.tx_type = ath12k_tid_to_ac(tid > ATH12K_DSCP_PRIORITY ? 0: tid); ++ ar->wmm_stats.total_wmm_tx_pkts[ar->wmm_stats.tx_type]++; + } + + if (common->fes_duration_us) +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index 5728982..a46199a 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -10217,6 +10217,8 @@ static int ath12k_mac_vdev_stop(struct ath12k_link_vif *arvif) + + reinit_completion(&ar->vdev_setup_done); + ++ memset(&ar->wmm_stats, 0, sizeof(struct ath12k_wmm_stats)); ++ + ret = ath12k_wmi_vdev_stop(ar, arvif->vdev_id); + if (ret) { + ath12k_warn(ar->ab, "failed to stop WMI vdev %i: %d\n", +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/716-b-ath12k-Multicast-support-for-MLO.patch b/feeds/ipq95xx/mac80211/patches/qca/716-b-ath12k-Multicast-support-for-MLO.patch new file mode 100644 index 000000000..426b69d33 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/716-b-ath12k-Multicast-support-for-MLO.patch @@ -0,0 +1,561 @@ +From a07c45bb1f5a6d9063c146803a6d0fe750d2d2fd Mon Sep 17 00:00:00 2001 +From: Balamurugan Mahalingam +Date: Mon, 27 Feb 2023 02:26:27 -0800 +Subject: [PATCH 2/2] ath12k: Multicast support for MLO + +Deliver the Multicast/Broadcast frames on links of an MLD AP +with a unique sequence number + +Signed-off-by: Balamurugan Mahalingam +--- + drivers/net/wireless/ath/ath12k/core.h | 2 + + drivers/net/wireless/ath/ath12k/dp.h | 28 ++++-- + drivers/net/wireless/ath/ath12k/dp_tx.c | 24 ++++- + drivers/net/wireless/ath/ath12k/dp_tx.h | 3 +- + drivers/net/wireless/ath/ath12k/mac.c | 124 ++++++++++++++++++------ + 5 files changed, 141 insertions(+), 40 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -405,6 +405,8 @@ struct ath12k_vif { + struct ath12k_mgmt_frame_stats mgmt_stats; + u8 num_vdev_created; + u8 num_vdev_started; ++ u16 mcbc_gsn; ++ spinlock_t mcbc_gsn_lock; /* Protect mcbc_gsn */ + struct ath12k_vif_cache cache[IEEE80211_MLD_MAX_NUM_LINKS]; + u8 last_scan_link; + #ifdef CPTCFG_ATH12K_DEBUGFS +@@ -1045,6 +1047,8 @@ struct ath12k_soc_dp_tx_err_stats { + /* TCL Ring Buffers unavailable */ + u32 txbuf_na[DP_TCL_NUM_RING_MAX]; + ++ u32 peers_not_present; ++ + /* Other failures during dp_tx due to mem allocation failure + * idr unavailable etc. + */ +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -381,21 +381,42 @@ struct ath12k_dp { + }; + + /* HTT definitions */ ++#define HTT_TAG_TCL_METADATA_VERSION 5 + +-#define HTT_TCL_META_DATA_TYPE BIT(0) +-#define HTT_TCL_META_DATA_VALID_HTT BIT(1) ++#define HTT_TCL_META_DATA_TYPE_FTM BIT(0) ++#define HTT_TCL_META_DATA_TYPE_MISSION GENMASK(1, 0) + ++#define HTT_TCL_META_DATA_VALID_HTT_FTM BIT(1) ++#define HTT_TCL_META_DATA_VALID_HTT_MISSION BIT(2) ++ ++#define HTT_TCL_META_DATA_VALID_HTT \ ++ (ath12k_ftm_mode ? HTT_TCL_META_DATA_VALID_HTT_FTM : \ ++ HTT_TCL_META_DATA_VALID_HTT_MISSION) + /* vdev meta data */ +-#define HTT_TCL_META_DATA_VDEV_ID GENMASK(9, 2) +-#define HTT_TCL_META_DATA_PDEV_ID GENMASK(11, 10) +-#define HTT_TCL_META_DATA_HOST_INSPECTED BIT(12) ++#define HTT_TCL_META_DATA_VDEV_ID_FTM GENMASK(9, 2) ++#define HTT_TCL_META_DATA_PDEV_ID_FTM GENMASK(11, 10) ++#define HTT_TCL_META_DATA_HOST_INSPECTED_FTM BIT(12) ++#define HTT_TCL_META_DATA_VDEV_ID_MISSION GENMASK(10, 3) ++#define HTT_TCL_META_DATA_PDEV_ID_MISSION GENMASK(12, 11) ++#define HTT_TCL_META_DATA_HOST_INSPECTED_MISSION BIT(13) + + /* peer meta data */ +-#define HTT_TCL_META_DATA_PEER_ID GENMASK(15, 2) ++#define HTT_TCL_META_DATA_PEER_ID_FTM GENMASK(15, 2) ++#define HTT_TCL_META_DATA_PEER_ID_MISSION GENMASK(15, 3) ++ ++#define HTT_TCL_META_DATA_GET(_val, _mask) \ ++ (ath12k_ftm_mode ? u32_encode_bits(_val, _mask##_FTM) : \ ++ u32_encode_bits(_val, _mask##_MISSION)) + + #define HTT_TX_WBM_COMP_STATUS_OFFSET 8 + +-/* HTT tx completion is overlayed in wbm_release_ring */ ++/* Global sequence number */ ++#define HTT_TCL_META_DATA_TYPE_GLOBAL_SEQ_NUM 3 ++#define HTT_TCL_META_DATA_GLOBAL_SEQ_HOST_INSPECTED BIT(2) ++#define HTT_TCL_META_DATA_GLOBAL_SEQ_NUM GENMASK(14, 3) ++#define HTT_TX_MLO_MCAST_HOST_REINJECT_BASE_VDEV_ID 128 ++ ++/* HTT tx completion is overlayed in wbm_release_ring v3 version */ + #define HTT_TX_WBM_COMP_INFO0_STATUS GENMASK(16, 13) + #define HTT_TX_WBM_COMP_INFO1_REINJECT_REASON GENMASK(3, 0) + #define HTT_TX_WBM_COMP_INFO1_EXCEPTION_FRAME BIT(4) +@@ -423,9 +444,15 @@ enum htt_h2t_msg_type { + }; + + #define HTT_VER_REQ_INFO_MSG_ID GENMASK(7, 0) ++#define HTT_OPTION_TCL_METADATA_VER_V2 2 ++#define HTT_OPTION_TAG GENMASK(7, 0) ++#define HTT_OPTION_LEN GENMASK(15, 8) ++#define HTT_OPTION_VALUE GENMASK(31, 16) ++#define HTT_TCL_METADATA_VER_SZ 4 + + struct htt_ver_req_cmd { + u32 ver_reg_info; ++ u32 tcl_metadata_version; + } __packed; + + enum htt_srng_ring_type { +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -155,7 +155,8 @@ static int ath12k_dp_prepare_htt_metadat + } + + int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif, +- struct ath12k_sta *ahsta, struct sk_buff *skb) ++ struct ath12k_sta *ahsta, struct sk_buff *skb, ++ bool gsn_valid, int mcbc_gsn) + { + struct ath12k_vif *ahvif = arvif->ahvif; + struct ath12k_base *ab = ar->ab; +@@ -226,7 +227,8 @@ tcl_ring_sel: + ti.meta_data_flags = ahsta->deflink.tcl_metadata; + ti.flags0 |= FIELD_PREP(HAL_TCL_DATA_CMD_INFO2_TO_FW, 1); + spin_lock_bh(&ab->base_lock); +- peer_id = FIELD_GET(HTT_TCL_META_DATA_PEER_ID, ti.meta_data_flags); ++ peer_id = FIELD_GET(HTT_TCL_META_DATA_PEER_ID_MISSION, ++ ti.meta_data_flags); + peer = ath12k_peer_find_by_id(ab, peer_id); + if (!peer || !peer->sta) { + spin_unlock_bh(&ab->base_lock); +@@ -241,13 +243,23 @@ tcl_ring_sel: + ti.meta_data_flags = arvif->tcl_metadata; + } + ++ if (gsn_valid) { ++ ti.meta_data_flags = u32_encode_bits(HTT_TCL_META_DATA_TYPE_GLOBAL_SEQ_NUM, ++ HTT_TCL_META_DATA_TYPE_MISSION) | ++ u32_encode_bits(mcbc_gsn, HTT_TCL_META_DATA_GLOBAL_SEQ_NUM); ++ } ++ + ti.encap_type = ath12k_dp_tx_get_encap_type(arvif, skb); + ti.addr_search_flags = arvif->hal_addr_search_flags; + ti.search_type = arvif->search_type; + ti.type = HAL_TCL_DESC_TYPE_BUFFER; + ti.pkt_offset = 0; + ti.lmac_id = ar->lmac_id; +- ti.vdev_id = arvif->vdev_id; ++ if (gsn_valid) ++ ti.vdev_id = arvif->vdev_id + ++ HTT_TX_MLO_MCAST_HOST_REINJECT_BASE_VDEV_ID; ++ else ++ ti.vdev_id = arvif->vdev_id; + ti.bss_ast_hash = arvif->ast_hash; + ti.bss_ast_idx = arvif->ast_idx; + ti.dscp_tid_tbl_idx = 0; +@@ -425,7 +437,12 @@ tcl_ring_sel: + + ath12k_dbg_dump(ab, ATH12K_DBG_DP_TX, NULL, "dp tx msdu: ", + skb->data, skb->len); +- arvif->link_stats.tx_enqueued++; ++ ++ if (gsn_valid) ++ arvif->link_stats.tx_bcast_mcast++; ++ else ++ arvif->link_stats.tx_enqueued++; ++ + atomic_inc(&ar->dp.num_tx_pending); + + return 0; +@@ -1229,7 +1246,16 @@ int ath12k_dp_tx_htt_h2t_ver_req_msg(str + skb_put(skb, len); + cmd = (struct htt_ver_req_cmd *)skb->data; + cmd->ver_reg_info = u32_encode_bits(HTT_H2T_MSG_TYPE_VERSION_REQ, +- HTT_VER_REQ_INFO_MSG_ID); ++ HTT_OPTION_TAG); ++ ++ if (!ath12k_ftm_mode) { ++ cmd->tcl_metadata_version = u32_encode_bits(HTT_TAG_TCL_METADATA_VERSION, ++ HTT_OPTION_TAG); ++ cmd->tcl_metadata_version |= u32_encode_bits(HTT_TCL_METADATA_VER_SZ, ++ HTT_OPTION_LEN); ++ cmd->tcl_metadata_version |= u32_encode_bits(HTT_OPTION_TCL_METADATA_VER_V2, ++ HTT_OPTION_VALUE); ++ } + + ret = ath12k_htc_send(&ab->htc, dp->eid, skb); + if (ret) { +--- a/drivers/net/wireless/ath/ath12k/dp_tx.h ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.h +@@ -216,7 +216,8 @@ struct htt_tx_msdu_desc_ext { + void ath12k_dp_tx_update_txcompl(struct ath12k *ar, struct hal_tx_status *ts); + int ath12k_dp_tx_htt_h2t_ver_req_msg(struct ath12k_base *ab); + int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif, +- struct ath12k_sta *ahsta, struct sk_buff *skb); ++ struct ath12k_sta *ahsta, struct sk_buff *skb, ++ bool gsn_valid, int mcbc_gsn); + void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id); + + int ath12k_dp_tx_htt_h2t_ppdu_stats_req(struct ath12k *ar, u32 mask); +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -8385,6 +8385,21 @@ static int ath12k_mac_mgmt_tx(struct ath + return 0; + } + ++static void ath12k_mlo_mcast_update_tx_link_address(struct ieee80211_vif *vif, ++ u8 link, struct sk_buff *skb, ++ u32 info_flags) ++{ ++ struct ieee80211_bss_conf *bss_conf; ++ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; ++ ++ if (info_flags & IEEE80211_TX_CTL_HW_80211_ENCAP) ++ return; ++ ++ bss_conf = rcu_dereference(vif->link_conf[link]); ++ if (bss_conf) ++ ether_addr_copy(hdr->addr2, bss_conf->addr); ++} ++ + static u8 ath12k_mac_get_tx_link(struct ieee80211_sta *sta, struct ieee80211_vif *vif, + u8 link, struct sk_buff *skb, u32 info_flags) + { +@@ -8404,54 +8419,76 @@ static u8 ath12k_mac_get_tx_link(struct + + ahsta = (struct ath12k_sta *)sta->drv_priv; + +- /* use default */ +- if (!sta->mlo) +- return ahsta->deflink.link_id; ++ /* Below translation ensures we pass proper A2 & A3 for non ML clients. ++ * Also it assumes for now support only for MLO AP in this path ++ */ ++ if (!sta->mlo) { ++ link = ahsta->deflink.link_id; ++ ++ if (info_flags & IEEE80211_TX_CTL_HW_80211_ENCAP) ++ return link; ++ ++ bss_conf = rcu_dereference(vif->link_conf[link]); ++ if (bss_conf) { ++ ether_addr_copy(hdr->addr2, bss_conf->addr); ++ if (!ieee80211_has_tods(hdr->frame_control) && ++ !ieee80211_has_fromds(hdr->frame_control)) ++ ether_addr_copy(hdr->addr3, bss_conf->addr); ++ } ++ return link; ++ } + + /* enqueue eth data frames on assoc link */ + if (info_flags & IEEE80211_TX_CTL_HW_80211_ENCAP) + return ahsta->assoc_link_id; ++ else if (ieee80211_is_data(hdr->frame_control)) ++ return ahsta->assoc_link_id; + + /* 802.11 frame cases */ + if (link == IEEE80211_LINK_UNSPECIFIED) + link = ahsta->deflink.link_id; + +- /* Perform address conversion for ML STA Tx */ +- bss_conf = rcu_dereference(vif->link_conf[link]); +- link_sta = rcu_dereference(sta->link[link]); +- if (bss_conf && link_sta) { +- ether_addr_copy(hdr->addr1, link_sta->addr); +- ether_addr_copy(hdr->addr2, bss_conf->addr); +- } else if (bss_conf) { +- /* In certain cases where a ML sta associated and added subset of links +- * on which the ML AP is active, but now sends some frame (ex Probe request) +- * on a different link which is active in our MLD but was not added during +- * previous association, we can still honor the Tx to that ML STA via the +- * requested link. +- * The control would reach here in such case only when that link address +- * is same as the MLD address or in worst case clients used MLD address at TA wrongly +- * which would have helped identify the ML sta object and pass it here. +- * If the link address of that STA is different from MLD address, then +- * the sta object would be NULL and control wont reach here but return at the +- * start of the function itself with !sta check. Also this would not need any +- * translation at hdr->addr1 from MLD to link address since the RA is the +- * MLD address (same as that link address ideally) already. +- */ +- ether_addr_copy(hdr->addr2, bss_conf->addr); +- +- ath12k_dbg(NULL, ATH12K_DBG_MAC, +- "unable to determine link sta addr for translation - Frame control %x link %d sta links %x ahsta links %x\n", +- hdr->frame_control, link, sta->valid_links, ahsta->links_map); +- } else { +- ath12k_err(NULL, "unable to determine Tx link for frame %x link %d\n vif links %x sta links %x ahvif links %x ahsta links %x", +- hdr->frame_control, link, vif->valid_links, +- sta->valid_links, ahvif->links_map, ahsta->links_map); +- link = IEEE80211_MLD_MAX_NUM_LINKS; ++ if (ieee80211_is_mgmt(hdr->frame_control)) { ++ /* Perform address conversion for ML STA Tx */ ++ bss_conf = rcu_dereference(vif->link_conf[link]); ++ link_sta = rcu_dereference(sta->link[link]); ++ if (bss_conf && link_sta) { ++ ether_addr_copy(hdr->addr1, link_sta->addr); ++ ether_addr_copy(hdr->addr2, bss_conf->addr); ++ if (vif->type == NL80211_IFTYPE_STATION && bss_conf->bssid) ++ ether_addr_copy(hdr->addr3, bss_conf->bssid); ++ } else if (bss_conf) { ++ /* In certain cases where a ML sta associated and added subset of links ++ * on which the ML AP is active, but now sends some frame (ex. Probe request) ++ * on a different link which is active in our MLD but was not added during ++ * previous association, we can still honor the Tx to that ML STA via the ++ * requested link. ++ * The control would reach here in such case only when that link address ++ * is same as the MLD address or in worst case clients used MLD address at TA wrongly ++ * which would have helped identify the ML sta object and pass it here. ++ * If the link address of that STA is different from MLD address, then ++ * the sta object would be NULL and control wont reach here but return at the ++ * start of the function itself with !sta check. Also this would not need any ++ * translation at hdr->addr1 from MLD to link address since the RA is the ++ * MLD address (same as that link address ideally) already. ++ */ ++ ether_addr_copy(hdr->addr2, bss_conf->addr); ++ if (vif->type == NL80211_IFTYPE_STATION && bss_conf->bssid) ++ ether_addr_copy(hdr->addr3, bss_conf->bssid); ++ ++ ath12k_dbg(NULL, ATH12K_DBG_MAC, ++ "unable to determine link sta addr for translation - Frame control %x link %d sta links %x ahsta links %x\n", ++ hdr->frame_control, link, sta->valid_links, ++ ahsta->links_map); ++ } else { ++ ath12k_err(NULL, "unable to determine Tx link for frame %x link %d\n vif links %x sta links %x ahvif links %x ahsta links %x", ++ hdr->frame_control, link, vif->valid_links, ++ sta->valid_links, ahvif->links_map, ahsta->links_map); ++ link = IEEE80211_MLD_MAX_NUM_LINKS; ++ } + } + +- /* todo nwifi/raw data frames */ + return link; +- + } + + static void ath12k_mac_op_tx(struct ieee80211_hw *hw, +@@ -8462,18 +8499,24 @@ static void ath12k_mac_op_tx(struct ieee + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_vif *vif = info->control.vif; + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); +- struct ath12k_link_vif *arvif; +- struct ath12k *ar; ++ struct ath12k_link_vif *arvif, *tmp_arvif; ++ struct ath12k *ar, *tmp_ar; + struct ath12k_hw *ah; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; ++ struct ethhdr *eth = (struct ethhdr *)skb->data; + struct ieee80211_key_conf *key = info->control.hw_key; + struct ath12k_mgmt_frame_stats *mgmt_stats = &ahvif->mgmt_stats; + struct ath12k_sta *ahsta = NULL; ++ struct sk_buff *msdu_copied; + struct ath12k_link_sta *arsta = NULL; + struct ieee80211_sta *sta = control->sta; ++ struct ath12k_peer *peer; + u32 info_flags = info->flags; + bool is_prb_rsp; ++ bool is_mcast = false; + u16 frm_type = 0; ++ u8 link_id; ++ u16 mcbc_gsn; + int ret; + u8 link = u32_get_bits(info->control.flags, IEEE80211_TX_CTRL_MLO_LINK); + +@@ -8520,6 +8563,7 @@ static void ath12k_mac_op_tx(struct ieee + + if (info_flags & IEEE80211_TX_CTL_HW_80211_ENCAP) { + skb_cb->flags |= ATH12K_SKB_HW_80211_ENCAP; ++ is_mcast = is_multicast_ether_addr(eth->h_dest); + } else if (ieee80211_is_mgmt(hdr->frame_control)) { + frm_type = FIELD_GET(IEEE80211_FCTL_STYPE, hdr->frame_control); + is_prb_rsp = ieee80211_is_probe_resp(hdr->frame_control); +@@ -8538,7 +8582,9 @@ static void ath12k_mac_op_tx(struct ieee + spin_unlock_bh(&ar->data_lock); + } + return; +- } ++ } else ++ is_mcast = is_multicast_ether_addr(hdr->addr1); ++ + if (sta) + ahsta = (struct ath12k_sta *)control->sta->drv_priv; + +@@ -8552,23 +8598,102 @@ static void ath12k_mac_op_tx(struct ieee + test_bit(MONITOR_VDEV_CREATED, &ar->monitor_flags)) + skb_cb->flags |= ATH12K_SKB_TX_STATUS; + +- ret = ath12k_dp_tx(ar, arvif, ahsta, skb); +- if (unlikely(ret)) { +- if (ret == -ENOMEM) +- ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "failed to transmit frame %d\n", +- ret); +- else +- ath12k_warn(ar->ab, "failed to transmit frame %d\n", +- ret); ++ if (!vif->valid_links || !is_mcast || ++ test_bit(ATH12K_FLAG_RAW_MODE, &ar->ab->ag->dev_flags)) { ++ ret = ath12k_dp_tx(ar, arvif, ahsta, skb, false, 0); ++ if (unlikely(ret)) { ++ if (ret == -ENOMEM) ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, ++ "failed to transmit frame %d\n", ret); ++ else ++ ath12k_warn(ar->ab, "failed to transmit frame %d\n", ret); ++ ++ ieee80211_free_txskb(ah->hw, skb); ++ } ++ if (ath12k_debugfs_is_extd_tx_stats_enabled(ar) && ahsta) { ++ arsta = &ahsta->deflink; ++ atomic_inc(&arsta->drv_tx_pkts.pkts_in); ++ if (!ret) ++ atomic_inc(&arsta->drv_tx_pkts.pkts_out); ++ } ++ } else { ++ spin_lock(&ahvif->mcbc_gsn_lock); ++ mcbc_gsn = ahvif->mcbc_gsn++; ++ if (ahvif->mcbc_gsn > 0xFFF) ++ ahvif->mcbc_gsn = 0; ++ spin_unlock(&ahvif->mcbc_gsn_lock); ++ ++ for_each_set_bit(link_id, &ahvif->links_map, ++ IEEE80211_MLD_MAX_NUM_LINKS) { ++ tmp_arvif = ahvif->link[link_id]; ++ if (!(tmp_arvif && tmp_arvif->is_up)) ++ continue; ++ ++ tmp_ar = tmp_arvif->ar; ++ msdu_copied = skb_copy(skb, GFP_ATOMIC); ++ if (!msdu_copied) { ++ ath12k_err(ar->ab, ++ "skb copy failure link_id 0x%X vdevid 0x%X\n", ++ link_id, tmp_arvif->vdev_id); ++ continue; ++ } ++ ++ ath12k_mlo_mcast_update_tx_link_address(vif, link_id, ++ msdu_copied, ++ info_flags); ++ /* upper layer would not have handled the keys so ++ * handle it here */ ++ skb_cb = ATH12K_SKB_CB(msdu_copied); ++ info = IEEE80211_SKB_CB(msdu_copied); ++ skb_cb->link_id = link_id; ++ ++ /* For open mode, skip peer find logic */ ++ if (ahvif->key_cipher == INVALID_CIPHER) ++ goto skip_peer_find; ++ ++ spin_lock_bh(&tmp_ar->ab->base_lock); ++ peer = ath12k_peer_find_by_addr(tmp_ar->ab, tmp_arvif->addr); ++ if (!peer) { ++ spin_unlock_bh(&tmp_ar->ab->base_lock); ++ ath12k_warn(tmp_ar->ab, ++ "failed to find peer for vdev_id 0x%X addr %pM link_map 0x%X\n", ++ tmp_arvif->vdev_id, tmp_arvif->addr, ++ ahvif->links_map); ++ tmp_ar->ab->soc_stats.tx_err.peers_not_present++; ++ ieee80211_free_txskb(ah->hw, msdu_copied); ++ continue; ++ } ++ ++ key = peer->keys[peer->mcast_keyidx]; ++ if (key) { ++ skb_cb->cipher = key->cipher; ++ skb_cb->flags |= ATH12K_SKB_CIPHER_SET; ++ info->control.hw_key = key; ++ ++ hdr = (struct ieee80211_hdr *)msdu_copied->data; ++ if (!ieee80211_has_protected(hdr->frame_control)) ++ hdr->frame_control |= ++ cpu_to_le16(IEEE80211_FCTL_PROTECTED); ++ } ++ spin_unlock_bh(&tmp_ar->ab->base_lock); ++skip_peer_find: ++ ret = ath12k_dp_tx(tmp_ar, tmp_arvif, ahsta, ++ msdu_copied, true, mcbc_gsn); ++ ++ if (unlikely(ret)) { ++ if (ret == -ENOMEM) ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "failed to transmit frame %d\n", ++ ret); ++ else ++ ath12k_warn(ar->ab, "failed to transmit frame %d\n", ++ ret); ++ ++ ieee80211_free_txskb(ah->hw, msdu_copied); ++ } ++ } + ieee80211_free_txskb(ah->hw, skb); + } + +- if (ath12k_debugfs_is_extd_tx_stats_enabled(ar) && ahsta) { +- arsta = &ahsta->deflink; +- atomic_inc(&arsta->drv_tx_pkts.pkts_in); +- if (!ret) +- atomic_inc(&arsta->drv_tx_pkts.pkts_out); +- } + } + + void ath12k_mac_drain_tx(struct ath12k *ar) +@@ -9683,6 +9808,7 @@ static int ath12k_mac_op_add_interface(s + + ahvif->deflink.ahvif = ahvif; + ahvif->deflink.link_id = 0; ++ ahvif->mcbc_gsn = 0; + INIT_LIST_HEAD(&ahvif->deflink.list); + INIT_WORK(&ahvif->deflink.update_obss_color_notify_work, + ath12k_update_obss_color_notify_work); +@@ -14693,6 +14819,8 @@ static int ath12k_mac_hw_register(struct + if (ag->mlo_capable) { + ath12k_iftypes_ext_capa[2].eml_capabilities = cap->eml_cap; + ath12k_iftypes_ext_capa[2].mld_capa_and_ops = cap->mld_cap; ++ if (!test_bit(ATH12K_FLAG_RAW_MODE, &ag->dev_flags)) ++ ieee80211_hw_set(hw, MLO_MCAST_MULTI_LINK_TX); + } + hw->wiphy->iftype_ext_capab = ath12k_iftypes_ext_capa; + hw->wiphy->num_iftype_ext_capab = ARRAY_SIZE(ath12k_iftypes_ext_capa); +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -1159,11 +1159,11 @@ void ath12k_dp_vdev_tx_attach(struct ath + { + struct ath12k_base *ab = ar->ab; + +- arvif->tcl_metadata |= u32_encode_bits(1, HTT_TCL_META_DATA_TYPE) | +- u32_encode_bits(arvif->vdev_id, +- HTT_TCL_META_DATA_VDEV_ID) | +- u32_encode_bits(ar->pdev->pdev_id, +- HTT_TCL_META_DATA_PDEV_ID); ++ arvif->tcl_metadata |= HTT_TCL_META_DATA_GET(1, HTT_TCL_META_DATA_TYPE) | ++ HTT_TCL_META_DATA_GET(arvif->vdev_id, ++ HTT_TCL_META_DATA_VDEV_ID) | ++ HTT_TCL_META_DATA_GET(ar->pdev->pdev_id, ++ HTT_TCL_META_DATA_PDEV_ID); + + /* set HTT extension valid bit to 0 by default */ + arvif->tcl_metadata &= ~HTT_TCL_META_DATA_VALID_HTT; +--- a/drivers/net/wireless/ath/ath12k/peer.c ++++ b/drivers/net/wireless/ath/ath12k/peer.c +@@ -502,9 +502,10 @@ int ath12k_peer_create(struct ath12k *ar + if (sta) { + ahsta = (struct ath12k_sta *)sta->drv_priv; + arsta = ahsta->link[link_id]; +- arsta->tcl_metadata |= FIELD_PREP(HTT_TCL_META_DATA_TYPE, 0) | +- FIELD_PREP(HTT_TCL_META_DATA_PEER_ID, +- peer->peer_id); ++ arsta->tcl_metadata |= HTT_TCL_META_DATA_GET(0, ++ HTT_TCL_META_DATA_TYPE) | ++ HTT_TCL_META_DATA_GET(peer->peer_id, ++ HTT_TCL_META_DATA_PEER_ID); + peer->link_id = arsta->link_id; + + /* set HTT extension valid bit to 0 by default */ +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -1583,6 +1583,10 @@ static ssize_t ath12k_debugfs_dump_soc_d + soc_stats->tx_enqueued[3]); + + len += scnprintf(buf + len, size - len, ++ "\nTx Peers Not Present: %d\n", ++ soc_stats->tx_err.peers_not_present); ++ ++ len += scnprintf(buf + len, size - len, + "\ntx_completed: 0:%u 1:%u 2:%u 3:%u\n", + soc_stats->tx_completed[0], + soc_stats->tx_completed[1], diff --git a/feeds/ipq95xx/mac80211/patches/qca/717-ath12k-fix-firmware-crash-issue-in-raw-mode-with-sof.patch b/feeds/ipq95xx/mac80211/patches/qca/717-ath12k-fix-firmware-crash-issue-in-raw-mode-with-sof.patch new file mode 100644 index 000000000..10c72ca84 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/717-ath12k-fix-firmware-crash-issue-in-raw-mode-with-sof.patch @@ -0,0 +1,56 @@ +From 8080ce176dce38c5b2ca41a0e6485a6d901b2b3e Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Fri, 3 Mar 2023 15:15:03 +0530 +Subject: [PATCH] ath12k: fix firmware crash issue in raw mode with software + encryption + +Currently, we are not setting "WMI_UNIFIED_VDEV_START_HW_ENCRYPTION_DISABLED" +flag during vdev start. this will trigger firmware assert because in SW +encryption encrypt/decrypt should be done by software. + +So, Fix this issue by setting "WMI_UNIFIED_VDEV_START_HW_ENCRYPTION_DISABLED" +flag to avoid hardware encryption/decryption. + +Signed-off-by: Aaradhana Sahu +--- + drivers/net/wireless/ath/ath12k/wmi.c | 4 ++++ + drivers/net/wireless/ath/ath12k/wmi.h | 1 + + 2 files changed, 5 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c +index f57d926..f39066f 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -1148,6 +1148,7 @@ int ath12k_wmi_vdev_start(struct ath12k *ar, struct wmi_vdev_start_req_arg *arg, + void *ptr; + int ret, len, ml_arg_size = 0; + u8 i; ++ struct ath12k_hw_group *ag = ar->ab->ag; + + if (WARN_ON(arg->ssid_len > sizeof(cmd->ssid.ssid))) + return -EINVAL; +@@ -1192,6 +1193,9 @@ int ath12k_wmi_vdev_start(struct ath12k *ar, struct wmi_vdev_start_req_arg *arg, + + cmd->flags |= cpu_to_le32(WMI_VDEV_START_LDPC_RX_ENABLED); + ++ if (test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ag->dev_flags)) ++ cmd->flags |= cpu_to_le32(WMI_VDEV_START_HW_ENCRYPTION_DISABLED); ++ + ptr = skb->data + sizeof(*cmd); + chan = ptr; + +diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h +index 9257720..3fa2a7c 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -2991,6 +2991,7 @@ struct wmi_vdev_down_cmd { + #define WMI_VDEV_START_HIDDEN_SSID BIT(0) + #define WMI_VDEV_START_PMF_ENABLED BIT(1) + #define WMI_VDEV_START_LDPC_RX_ENABLED BIT(3) ++#define WMI_VDEV_START_HW_ENCRYPTION_DISABLED BIT(4) + + struct wmi_ssid { + u32 ssid_len; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/717-ath12k-fix-tcl_metadata-vdev_id-info.patch b/feeds/ipq95xx/mac80211/patches/qca/717-ath12k-fix-tcl_metadata-vdev_id-info.patch new file mode 100644 index 000000000..ff5b51b9f --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/717-ath12k-fix-tcl_metadata-vdev_id-info.patch @@ -0,0 +1,47 @@ +From 7400aa0f6bb945806c7aca0b07001ef1011e1c79 Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Tue, 7 Mar 2023 23:36:13 +0530 +Subject: [PATCH] ath12k: fix tcl_metadata vdev_id info + +During AP-STA repeater scenario, initially, +AP interface is brought up with vdev_id 0 and +in parallel, STA interface is brought up with +vdev_id 1 and scan is initiated for STA interface. +While the scan is on going, AP interface is disabled +as the STA is not yet associated. Hence, vdev_id 0 is +deleted. + +Once STA scan is completed, vdev (vdev_id 1) is deleted +and during association again STA interface is created with +vdev_id 0. During this, the vdev_id information is appended +in tcl_metadata which results in incorrect configuration of +vdev_id because the ahvif's deflink still had the old vdev_id +in the tcl_metadata information. + +Hence, add changes to write tcl_metadata config instead of +appending it. + +Signed-off-by: Harshitha Prem +--- + drivers/net/wireless/ath/ath12k/dp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -1159,11 +1159,11 @@ void ath12k_dp_vdev_tx_attach(struct ath + { + struct ath12k_base *ab = ar->ab; + +- arvif->tcl_metadata |= HTT_TCL_META_DATA_GET(1, HTT_TCL_META_DATA_TYPE) | +- HTT_TCL_META_DATA_GET(arvif->vdev_id, +- HTT_TCL_META_DATA_VDEV_ID) | +- HTT_TCL_META_DATA_GET(ar->pdev->pdev_id, +- HTT_TCL_META_DATA_PDEV_ID); ++ arvif->tcl_metadata = HTT_TCL_META_DATA_GET(1, HTT_TCL_META_DATA_TYPE) | ++ HTT_TCL_META_DATA_GET(arvif->vdev_id, ++ HTT_TCL_META_DATA_VDEV_ID) | ++ HTT_TCL_META_DATA_GET(ar->pdev->pdev_id, ++ HTT_TCL_META_DATA_PDEV_ID); + + /* set HTT extension valid bit to 0 by default */ + arvif->tcl_metadata &= ~HTT_TCL_META_DATA_VALID_HTT; diff --git a/feeds/ipq95xx/mac80211/patches/qca/717-ath12k-received-pkts.patch b/feeds/ipq95xx/mac80211/patches/qca/717-ath12k-received-pkts.patch new file mode 100644 index 000000000..76236cbb8 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/717-ath12k-received-pkts.patch @@ -0,0 +1,126 @@ +From bf9281b1bbdaec35efa2d666008b7255b26f17d4 Mon Sep 17 00:00:00 2001 +From: saleemuddin shaik +Date: Sat, 4 Mar 2023 13:59:52 +0530 +Subject: ath12k: add statistic support for counting wmm received packets + +Taken tid value from the reo dest ring and +the packets are counted based on WMM categories. + +Signed-off-by: saleemuddin shaik +--- + drivers/net/wireless/ath/ath12k/core.h | 2 ++ + drivers/net/wireless/ath/ath12k/debugfs.c | 15 ++++++++++++++- + drivers/net/wireless/ath/ath12k/dp_rx.c | 12 +++++++++++- + 3 files changed, 27 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h +index becfc2a..1b03d46 100644 +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -730,7 +730,9 @@ struct ath12k_chan_info { + + struct ath12k_wmm_stats { + int tx_type; ++ int rx_type; + u64 total_wmm_tx_pkts[WME_NUM_AC]; ++ u64 total_wmm_rx_pkts[WME_NUM_AC]; + }; + + #define ATH12K_DSCP_PRIORITY 7 +diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c +index 3918aac..6509567 100644 +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -1354,6 +1354,7 @@ static ssize_t ath12k_read_wmm_stats(struct file *file, + char *buf; + ssize_t retval; + u64 total_wmm_sent_pkts = 0; ++ u64 total_wmm_received_pkts = 0; + + buf = kzalloc(size, GFP_KERNEL); + if (!buf) { +@@ -1362,11 +1363,15 @@ static ssize_t ath12k_read_wmm_stats(struct file *file, + } + + mutex_lock(&ar->conf_mutex); +- for (count = 0; count < WME_NUM_AC; count++) ++ for (count = 0; count < WME_NUM_AC; count++) { + total_wmm_sent_pkts += ar->wmm_stats.total_wmm_tx_pkts[count]; ++ total_wmm_received_pkts += ar->wmm_stats.total_wmm_rx_pkts[count]; ++ } + + len += scnprintf(buf + len, size - len, "Total number of wmm_sent: %llu\n", + total_wmm_sent_pkts); ++ len += scnprintf(buf + len, size - len, "total number of wmm_received: %llu\n", ++ total_wmm_received_pkts); + len += scnprintf(buf + len, size - len, "Num of BE wmm_sent: %llu\n", + ar->wmm_stats.total_wmm_tx_pkts[WME_AC_BE]); + len += scnprintf(buf + len, size - len, "Num of BK wmm_sent: %llu\n", +@@ -1375,6 +1380,14 @@ static ssize_t ath12k_read_wmm_stats(struct file *file, + ar->wmm_stats.total_wmm_tx_pkts[WME_AC_VI]); + len += scnprintf(buf + len, size - len, "Num of VO wmm_sent: %llu\n", + ar->wmm_stats.total_wmm_tx_pkts[WME_AC_VO]); ++ len += scnprintf(buf + len, size - len, "num of be wmm_received: %llu\n", ++ ar->wmm_stats.total_wmm_rx_pkts[WME_AC_BE]); ++ len += scnprintf(buf + len, size - len, "num of bk wmm_received: %llu\n", ++ ar->wmm_stats.total_wmm_rx_pkts[WME_AC_BK]); ++ len += scnprintf(buf + len, size - len, "num of vi wmm_received: %llu\n", ++ ar->wmm_stats.total_wmm_rx_pkts[WME_AC_VI]); ++ len += scnprintf(buf + len, size - len, "num of vo wmm_received: %llu\n", ++ ar->wmm_stats.total_wmm_rx_pkts[WME_AC_VO]); + + mutex_unlock(&ar->conf_mutex); + +diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c +index a3d1ed8..21fce33 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -2574,6 +2574,7 @@ static void ath12k_dp_rx_h_undecap(struct ath12k *ar, struct sk_buff *msdu, + /* TODO: Handle undecap for these formats */ + break; + } ++ ar->wmm_stats.total_wmm_rx_pkts[ar->wmm_stats.rx_type]++; + } + + struct ath12k_peer * +@@ -2670,12 +2671,15 @@ static void ath12k_dp_rx_h_mpdu(struct ath12k *ar, + struct ieee80211_hdr *hdr; + struct ath12k_peer *peer; + struct ieee80211_rx_status *rx_status = rx_info->rx_status; ++ struct ath12k_dp_rx_tid *rx_tid; + u32 err_bitmap; ++ u8 tid; + #ifdef CPTCFG_MAC80211_PPE_SUPPORT + u32 vp; + #endif + struct wireless_dev *wdev = NULL; + ++ tid = ath12k_dp_rx_h_tid(ab, rx_desc); + /* PN for multicast packets will be checked in mac80211 */ + rxcb = ATH12K_SKB_RXCB(msdu); + fill_crypto_hdr = ath12k_dp_rx_h_is_mcbc(ar->ab, rx_desc); +@@ -2693,7 +2697,11 @@ static void ath12k_dp_rx_h_mpdu(struct ath12k *ar, + * path, so its safe to skip checking errors here */ + if (*fast_rx && + ath12k_dp_rx_check_fast_rx(ar, msdu, rx_desc, peer)) { +- wdev = ieee80211_vif_to_wdev(peer->vif); ++ rx_tid = &peer->rx_tid[tid]; ++ ar->wmm_stats.rx_type = ++ ath12k_tid_to_ac(rx_tid->tid > ATH12K_DSCP_PRIORITY ? 0: rx_tid->tid); ++ ar->wmm_stats.total_wmm_rx_pkts[ar->wmm_stats.rx_type]++; ++ wdev = ieee80211_vif_to_wdev(peer->vif); + if (wdev) { + #ifdef CPTCFG_MAC80211_PPE_SUPPORT + vp = peer->vif->ppe_vp_num; +@@ -3350,6 +3358,8 @@ try_again: + rxcb->tid = u32_get_bits(desc.rx_mpdu_info.info0, + RX_MPDU_DESC_INFO0_TID); + ++ ar->wmm_stats.rx_type = ath12k_tid_to_ac(rxcb->tid > ATH12K_DSCP_PRIORITY ? 0: rxcb->tid); ++ + if (ath12k_debugfs_is_extd_rx_stats_enabled(ar) && rxcb->peer_id) { + rcu_read_lock(); + spin_lock_bh(&src_ab->base_lock); +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/717-ath12k-update-unsupported-bandwidth-flags.patch b/feeds/ipq95xx/mac80211/patches/qca/717-ath12k-update-unsupported-bandwidth-flags.patch new file mode 100644 index 000000000..433d8c441 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/717-ath12k-update-unsupported-bandwidth-flags.patch @@ -0,0 +1,121 @@ +From 953ac7fc97a36807f021877425199a9ea9ebc2bd Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Thu, 9 Mar 2023 22:49:05 +0530 +Subject: [PATCH] ath12k: update unsupported bandwidth flags + +Some of the countries like TG, WS and CF are able to +operate on unsupported bandwidth. This is because, +the NL80211 flags are not updated with no support flag. + +Hence, add changes to update the unsupported bandwith flag +based on the max bandwidth received from firmware + +Signed-off-by: Harshitha Prem +--- + drivers/net/wireless/ath/ath12k/reg.c | 56 ++++++++++++++++++++------- + 1 file changed, 43 insertions(+), 13 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/reg.c ++++ b/drivers/net/wireless/ath/ath12k/reg.c +@@ -410,6 +410,35 @@ ath12k_map_fw_dfs_region(enum ath12k_dfs + } + } + ++static u32 ath12k_update_bw_reg_flags(u16 max_bw) ++{ ++ u32 flags = 0; ++ switch (max_bw) { ++ case 20: ++ flags = (NL80211_RRF_NO_HT40 | ++ NL80211_RRF_NO_80MHZ | ++ NL80211_RRF_NO_160MHZ | ++ NL80211_RRF_NO_320MHZ); ++ break; ++ case 40: ++ flags = (NL80211_RRF_NO_80MHZ | ++ NL80211_RRF_NO_160MHZ | ++ NL80211_RRF_NO_320MHZ ); ++ break; ++ case 80: ++ flags = (NL80211_RRF_NO_160MHZ | ++ NL80211_RRF_NO_320MHZ); ++ break; ++ case 160: ++ flags = NL80211_RRF_NO_320MHZ; ++ break; ++ default: ++ break; ++ } ++ ++ return flags; ++} ++ + static u32 ath12k_map_fw_reg_flags(u16 reg_flags) + { + u32 flags = 0; +@@ -578,7 +607,7 @@ ath12k_reg_build_regd(struct ath12k_base + u8 i = 0, j = 0, k = 0, max_elements = 0; + u8 num_rules; + u16 max_bw; +- u32 flags, reg_6g_number = 0, max_bw_6g = 0; ++ u32 flags = 0, reg_6g_number = 0, max_bw_6g = 0; + char alpha2[3]; + bool reg_6g_itr_set = false; + enum nl80211_regulatory_power_modes pwr_mode; +@@ -633,7 +662,7 @@ ath12k_reg_build_regd(struct ath12k_base + reg_rule = reg_info->reg_rules_2g_ptr + i; + max_bw = min_t(u16, reg_rule->max_bw, + reg_info->max_bw_2g); +- flags = NL80211_RRF_NO_320MHZ; ++ flags = ath12k_update_bw_reg_flags(reg_info->max_bw_2g); + pwr_mode = 0; + ath12k_copy_reg_rule(&ab->reg_freq_2g, reg_rule); + } else if (reg_info->num_5g_reg_rules && +@@ -641,7 +670,7 @@ ath12k_reg_build_regd(struct ath12k_base + reg_rule = reg_info->reg_rules_5g_ptr + j++; + max_bw = min_t(u16, reg_rule->max_bw, + reg_info->max_bw_5g); +- ++ flags = NL80211_RRF_AUTO_BW | ath12k_update_bw_reg_flags(reg_info->max_bw_5g); + /* FW doesn't pass NL80211_RRF_AUTO_BW flag for + * BW Auto correction, we can enable this by default + * for all 5G rules here. The regulatory core performs +@@ -650,8 +679,7 @@ ath12k_reg_build_regd(struct ath12k_base + */ + if ((reg_rule->start_freq == 5490) && (reg_rule->end_freq == 5730)) + flags &= ~NL80211_RRF_NO_320MHZ; +- else +- flags = NL80211_RRF_AUTO_BW | NL80211_RRF_NO_320MHZ; ++ + pwr_mode = 0; + if (reg_rule->end_freq <= ATH12K_MAX_5G_FREQ) + ath12k_copy_reg_rule(&ab->reg_freq_5g, reg_rule); +@@ -672,17 +700,17 @@ ath12k_reg_build_regd(struct ath12k_base + reg_6g_itr_set = true; + } + if (reg_6g_itr_set && k < max_elements) { +- reg_rule = reg_rule_6g + k++; +- max_bw = min_t(u16, reg_rule->max_bw, max_bw_6g); +- flags = NL80211_RRF_AUTO_BW; +- +- if (reg_rule->psd_flag) +- flags |= NL80211_RRF_PSD; +- +- if (reg_rule->end_freq <= ATH12K_MAX_6G_FREQ) +- ath12k_copy_reg_rule(&ab->reg_freq_6g, reg_rule); +- else if (reg_rule->start_freq >= ATH12K_MIN_6G_FREQ) +- ath12k_copy_reg_rule(&ab->reg_freq_6g, reg_rule); ++ reg_rule = reg_rule_6g + k++; ++ max_bw = min_t(u16, reg_rule->max_bw, max_bw_6g); ++ flags = NL80211_RRF_AUTO_BW | ath12k_update_bw_reg_flags(max_bw_6g); ++ ++ if (reg_rule->psd_flag) ++ flags |= NL80211_RRF_PSD; ++ ++ if (reg_rule->end_freq <= ATH12K_MAX_6G_FREQ) ++ ath12k_copy_reg_rule(&ab->reg_freq_6g, reg_rule); ++ else if (reg_rule->start_freq >= ATH12K_MIN_6G_FREQ) ++ ath12k_copy_reg_rule(&ab->reg_freq_6g, reg_rule); + } + + if (reg_6g_itr_set && k >= max_elements) { diff --git a/feeds/ipq95xx/mac80211/patches/qca/717-cfg80211-precac-check-for-self-managed-wiphy.patch b/feeds/ipq95xx/mac80211/patches/qca/717-cfg80211-precac-check-for-self-managed-wiphy.patch new file mode 100644 index 000000000..64bb83089 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/717-cfg80211-precac-check-for-self-managed-wiphy.patch @@ -0,0 +1,33 @@ +From 5dbddc3d4ac81d707b347e74f2700f58e5644e4f Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Mon, 6 Mar 2023 20:57:17 +0530 +Subject: [PATCH] cfg80211: precac check for self-managed wiphy + +Currently, precac regulatory domain is inferred based +on the wiphy regulatory domain and cfg80211 regulatory +database. + +Some of the countries has some mismatch between these two +domains for self-managed driver, e.g., LK. + +Hence, add changes to determine precac regulatory domain +based on the wiphy regulatory settings if it is self-managed +wiphy. + +Signed-off-by: Harshitha Prem +--- + net/wireless/reg.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/net/wireless/reg.c ++++ b/net/wireless/reg.c +@@ -4254,7 +4254,8 @@ bool regulatory_pre_cac_allowed(struct w + return pre_cac_allowed; + } + +- if (regd->dfs_region == wiphy_regd->dfs_region && ++ if ((regd->dfs_region == wiphy_regd->dfs_region || ++ wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) && + wiphy_regd->dfs_region == NL80211_DFS_ETSI) + pre_cac_allowed = true; + diff --git a/feeds/ipq95xx/mac80211/patches/qca/676-a-ath12k-introduce-APIs-to-access-rings-without-locks.patch b/feeds/ipq95xx/mac80211/patches/qca/718-a-ath12k-introduce-APIs-to-access-rings-without-locks.patch similarity index 73% rename from feeds/ipq95xx/mac80211/patches/qca/676-a-ath12k-introduce-APIs-to-access-rings-without-locks.patch rename to feeds/ipq95xx/mac80211/patches/qca/718-a-ath12k-introduce-APIs-to-access-rings-without-locks.patch index 29d36a05e..109c381af 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/676-a-ath12k-introduce-APIs-to-access-rings-without-locks.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/718-a-ath12k-introduce-APIs-to-access-rings-without-locks.patch @@ -1,22 +1,23 @@ -From d233d4b3ee478f93277b4ae3d8b6cf9772c7bdbb Mon Sep 17 00:00:00 2001 -From: Balamurugan Mahalingam -Date: Mon, 17 Oct 2022 11:19:50 -0700 -Subject: [PATCH 1/7] ath12k: introduce APIs to access rings without locks +From aa3a414286147ff22842e0872a5365698deb7d77 Mon Sep 17 00:00:00 2001 +From: Ramanathan Choodamani +Date: Sat, 4 Mar 2023 19:58:40 -0800 +Subject: [PATCH] ath12k: introduce APIs to access rings without locks -Use these APIs to access transmit and transmit completion rings -without locks in the datapath +Use these APIs to access transmit and transmit completion rings without +locks in the datapath Signed-off-by: Balamurugan Mahalingam +Signed-off-by: Ramanathan Choodamani --- - drivers/net/wireless/ath/ath12k/dp_tx.c | 54 ++++++++++-------------- - drivers/net/wireless/ath/ath12k/hal.h | 56 +++++++++++++++++++++++++ - 2 files changed, 77 insertions(+), 33 deletions(-) + drivers/net/wireless/ath/ath12k/dp_tx.c | 57 +++++++++++++-------------------- + drivers/net/wireless/ath/ath12k/hal.h | 56 ++++++++++++++++++++++++++++++++ + 2 files changed, 79 insertions(+), 34 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c -index e356f03..ac954d1 100644 +index 0224a67..a461c7d 100644 --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -73,6 +73,25 @@ static void ath12k_dp_tx_release_txbuf(struct ath12k_dp *dp, +@@ -77,6 +77,25 @@ static void ath12k_dp_tx_release_txbuf(struct ath12k_dp *dp, spin_unlock_bh(&dp->tx_desc_lock[ring_id]); } @@ -42,16 +43,16 @@ index e356f03..ac954d1 100644 static struct ath12k_tx_desc_info *ath12k_dp_tx_assign_buffer(struct ath12k_dp *dp, u8 ring_id) { -@@ -128,8 +147,6 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif, +@@ -175,8 +194,6 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif, void *hal_tcl_desc; u8 hal_ring_id; int ret; - u8 ring_selector = 0, ring_map = 0; - bool tcl_ring_retry; + u16 peer_id; bool msdu_ext_desc = false; - - if (unlikely(test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))) -@@ -139,20 +156,8 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif, + bool is_diff_encap = false; +@@ -189,20 +206,10 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif, !ieee80211_is_data(hdr->frame_control))) return -ENOTSUPP; @@ -60,20 +61,22 @@ index e356f03..ac954d1 100644 - * the smp_processor_id(). In case that ring - * is full/busy, we resort to other available rings. - * If all rings are full, we drop the packet. -- * //TODO Add throttling logic when all rings are full +- * TODO: Add throttling logic when all rings are full - */ -- ring_selector = smp_processor_id(); +- ring_selector = ab->hw_params->hw_ops->get_ring_selector(skb); - -tcl_ring_sel: - tcl_ring_retry = false; -- ti.ring_id = ring_selector % DP_TCL_NUM_RING_MAX; -+ ti.ring_id = smp_processor_id() % DP_TCL_NUM_RING_MAX; +- ti.ring_id = ring_selector % ab->hw_params->max_tx_ring; ++ ti.ring_id = ++ ab->hw_params->hw_ops->get_ring_selector(skb) % ++ ab->hw_params->max_tx_ring; - ring_map |= BIT(ti.ring_id); - ti.rbm_id = ab->hal.ops->tcl_to_wbm_rbm_map[ti.ring_id].rbm_id; + ti.rbm_id = ab->hw_params->hal_ops->tcl_to_wbm_rbm_map[ti.ring_id].rbm_id; tx_ring = &dp->tx_ring[ti.ring_id]; -@@ -160,12 +165,7 @@ tcl_ring_sel: +@@ -210,12 +217,7 @@ tcl_ring_sel: tx_desc = ath12k_dp_tx_assign_buffer(dp, ti.ring_id); if (unlikely(!tx_desc)) { ab->soc_stats.tx_err.txbuf_na[ti.ring_id]++; @@ -87,7 +90,7 @@ index e356f03..ac954d1 100644 } ti.bank_id = arvif->bank_id; -@@ -301,16 +301,6 @@ tcl_ring_sel: +@@ -409,17 +411,6 @@ tcl_ring_sel: spin_unlock_bh(&tcl_ring->lock); ret = -ENOMEM; @@ -96,7 +99,8 @@ index e356f03..ac954d1 100644 - * checking this ring earlier for each pkt tx. - * Restart ring selection if some rings are not checked yet. - */ -- if (unlikely(ring_map != (BIT(DP_TCL_NUM_RING_MAX) - 1))) { +- if (unlikely(ring_map != (BIT(ab->hw_params->max_tx_ring) - 1) && +- ab->hw_params->tcl_ring_retry)) { - tcl_ring_retry = true; - ring_selector++; - } @@ -104,17 +108,17 @@ index e356f03..ac954d1 100644 goto fail_unmap_dma_ext_desc; } -@@ -339,8 +329,6 @@ fail_unmap_dma: +@@ -456,8 +447,6 @@ fail_remove_tx_buf: + skb_pull(skb, ti.pkt_offset); - fail_remove_tx_buf: - ath12k_dp_tx_release_txbuf(dp, tx_desc, ti.ring_id); + arvif->link_stats.tx_dropped++; - if (tcl_ring_retry) - goto tcl_ring_sel; return ret; } diff --git a/drivers/net/wireless/ath/ath12k/hal.h b/drivers/net/wireless/ath/ath12k/hal.h -index e644d48..f1525ed 100644 +index ae7c54c..75f01a6 100644 --- a/drivers/net/wireless/ath/ath12k/hal.h +++ b/drivers/net/wireless/ath/ath12k/hal.h @@ -9,6 +9,7 @@ @@ -124,8 +128,8 @@ index e644d48..f1525ed 100644 +#include "core.h" struct ath12k_base; - -@@ -53,6 +54,7 @@ struct ath12k_base; + #define HAL_CE_REMAP_REG_BASE (ab->ce_remap_base_addr) +@@ -60,6 +61,7 @@ struct ath12k_base; #define HAL_SEQ_WCSS_UMAC_WBM_REG 0x00a34000 #define HAL_CE_WFSS_CE_REG_BASE 0x01b80000 @@ -133,7 +137,7 @@ index e644d48..f1525ed 100644 #define HAL_TCL_SW_CONFIG_BANK_ADDR 0x00a4408c -@@ -555,6 +557,7 @@ enum hal_ring_type { +@@ -575,6 +577,7 @@ enum hal_ring_type { HAL_MAX_RING_TYPES, }; @@ -141,10 +145,10 @@ index e644d48..f1525ed 100644 #define HAL_RX_MAX_BA_WINDOW 256 #define HAL_DEFAULT_BE_BK_VI_REO_TIMEOUT_USEC (100 * 1000) -@@ -1160,4 +1163,57 @@ void ath12k_hal_reo_ring_ctrl_hash_ix3_setup(struct ath12k_base *ab, - u32 ring_hash_map); +@@ -1192,4 +1195,57 @@ void ath12k_hal_reo_ring_ctrl_hash_ix3_setup(struct ath12k_base *ab, void ath12k_hal_reo_ring_ctrl_hash_ix2_setup(struct ath12k_base *ab, u32 ring_hash_map); + void ath12k_hal_reo_shared_qaddr_cache_clear(struct ath12k_base *ab); + +static inline +u32 *ath12k_hal_srng_src_get_next_entry_nolock(struct ath12k_base *ab, @@ -200,5 +204,5 @@ index e644d48..f1525ed 100644 + #endif -- -2.17.1 +2.7.4 diff --git a/feeds/ipq95xx/mac80211/patches/qca/718-ath12k-Add-support-to-enable-QDSS-in-IPQ5332.patch b/feeds/ipq95xx/mac80211/patches/qca/718-ath12k-Add-support-to-enable-QDSS-in-IPQ5332.patch new file mode 100644 index 000000000..7049b43ec --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/718-ath12k-Add-support-to-enable-QDSS-in-IPQ5332.patch @@ -0,0 +1,245 @@ +From df886e4a6cf98d71288c92b40f90e38393311135 Mon Sep 17 00:00:00 2001 +From: Dinesh Karthikeyan +Date: Tue, 21 Feb 2023 12:32:03 +0530 +Subject: [PATCH] ath12k: Add support to enable QDSS in IPQ5332 + +Handle QDSS memory allocation separately for ahb chipset separately +and fill the chip info in coredump based on the bus type. + +Signed-off-by: Dinesh Karthikeyan +--- + drivers/net/wireless/ath/ath12k/coredump.c | 13 +++++++++---- + drivers/net/wireless/ath/ath12k/hw.c | 4 ---- + drivers/net/wireless/ath/ath12k/hw.h | 1 - + drivers/net/wireless/ath/ath12k/qmi.c | 14 +++++++++----- + drivers/net/wireless/ath/ath12k/qmi.h | 2 +- + 5 files changed, 19 insertions(+), 15 deletions(-) + +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/coredump.c +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/coredump.c 2023-03-03 10:20:29.501148015 +0530 ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/coredump.c 2023-03-03 10:20:29.493148079 +0530 +@@ -118,11 +118,16 @@ void ath12k_coredump_build_inline(struct + sizeof(file_data->df_magic)); + file_data->len = cpu_to_le32(header_size); + file_data->version = cpu_to_le32(ATH12K_FW_CRASH_DUMP_V2); +- file_data->chip_id = cpu_to_le32(ar_pci->dev_id); +- file_data->qrtr_id = cpu_to_le32(ar_pci->ab->qmi.service_ins_id); +- file_data->bus_id = pci_domain_nr(ar_pci->pdev->bus); ++ if (ab->hif.bus == ATH12K_BUS_AHB) { ++ file_data->chip_id = ab->qmi.target.chip_id; ++ file_data->qrtr_id = ab->qmi.service_ins_id; ++ file_data->bus_id = ab->userpd_id; ++ } else { ++ file_data->chip_id = cpu_to_le32(ar_pci->dev_id); ++ file_data->qrtr_id = cpu_to_le32(ar_pci->ab->qmi.service_ins_id); ++ file_data->bus_id = pci_domain_nr(ar_pci->pdev->bus); ++ } + dev = ab->dev; +- + guid_gen(&file_data->guid); + ktime_get_real_ts64(×tamp); + file_data->tv_sec = cpu_to_le64(timestamp.tv_sec); +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/hw.c +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/hw.c 2023-03-03 10:20:29.501148015 +0530 ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/hw.c 2023-03-03 10:20:29.497148047 +0530 +@@ -1472,7 +1472,6 @@ static const struct ath12k_hw_params ath + .m3_fw_support = true, + .compact_rx_tlv = true, + .send_platform_model = false, +- .en_qdss = true, + .en_fwlog = true, + }, + { +@@ -1542,7 +1541,6 @@ static const struct ath12k_hw_params ath + .m3_fw_support = true, + .compact_rx_tlv = false, + .send_platform_model = false, +- .en_qdss = true, + .en_fwlog = true, + }, + { +@@ -1620,7 +1618,6 @@ static const struct ath12k_hw_params ath + .m3_fw_support = true, + .compact_rx_tlv = true, + .send_platform_model = false, +- .en_qdss = true, + .en_fwlog = true, + }, + { +@@ -1692,7 +1689,6 @@ static const struct ath12k_hw_params ath + .ce_remap = &ath12k_ce_remap_ipq5332, + .cmem = &ath12k_cmem_ipq5332, + .send_platform_model = true, +- .en_qdss = false, + .en_fwlog = false, + }, + }; +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/hw.h +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/hw.h 2023-03-03 10:20:29.501148015 +0530 ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/hw.h 2023-03-03 10:20:29.497148047 +0530 +@@ -219,7 +219,6 @@ struct ath12k_hw_params { + bool fixed_fw_mem; + bool m3_fw_support; + bool send_platform_model; +- bool en_qdss; + bool en_fwlog; + const struct ce_remap *ce_remap; + const struct cmem *cmem; +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/qmi.c +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/qmi.c 2023-03-03 10:20:29.501148015 +0530 ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/qmi.c 2023-03-03 10:22:40.328113795 +0530 +@@ -4177,9 +4177,6 @@ int ath12k_config_qdss(struct ath12k_bas + + /* Disabling qdss trace for FTM as it causes hig evt latency in FW + */ +- if (!ab->hw_params->en_qdss) +- return 0; +- + if (ab->fw_mode == ATH12K_FIRMWARE_MODE_FTM) + return 0; + +@@ -4599,16 +4596,18 @@ int ath12k_qmi_qdss_mem_alloc(struct ath + struct device_node *dev_node = NULL; + struct resource q6_etr; + +- if (ab->bus_params.fixed_bdf_addr) { ++ switch (ab->hif.bus) { ++ case ATH12K_BUS_AHB: + dev_node = of_find_node_by_name(NULL, "q6_etr_dump"); + if (!dev_node) { + ath12k_err(ab, "No q6_etr_dump available in dts\n"); +- return -ENOMEM; ++ return -ENODEV; + } + ret = of_address_to_resource(dev_node, 0, &q6_etr); ++ of_node_put(dev_node); + if (ret) { + ath12k_err(ab, "Failed to get resource for q6_etr_dump\n"); +- return -EINVAL; ++ return ret; + } + for (i = 0; i < ab->qmi.qdss_mem_seg_len; i++) { + ab->qmi.qdss_mem[i].paddr = q6_etr.start; +@@ -4627,8 +4626,14 @@ int ath12k_qmi_qdss_mem_alloc(struct ath + ab->qmi.qdss_mem[i].v.ioaddr, + (unsigned int)ab->qmi.qdss_mem[i].size); + } +- } else { ++ break; ++ case ATH12K_BUS_PCI: + ret = ath12k_qmi_pci_alloc_qdss_mem(qmi); ++ break; ++ default: ++ ath12k_warn(ab, "invalid bus type: %d", ab->hif.bus); ++ ret = -EINVAL; ++ break; + } + return ret; + } +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/qmi.h +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/qmi.h 2023-03-03 10:20:29.501148015 +0530 ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/qmi.h 2023-03-03 10:20:29.497148047 +0530 +@@ -54,6 +54,13 @@ + + #define ATH12K_QMI_INVALID_RADIO 0xFF + ++/* userpd_id in multi pd arch */ ++enum userpd_id { ++ USERPD_0 = 0, ++ USERPD_1, ++ USERPD_2, ++}; ++ + struct ath12k_base; + + enum ath12k_qmi_file_type { +@@ -210,7 +217,7 @@ struct qmi_wlanfw_qdss_trace_config_down + #define QMI_WLANFW_QDSS_TRACE_MODE_REQ_MSG_V01_MAX_LEN 18 + #define QMI_WLANFW_QDSS_TRACE_MODE_RESP_MSG_V01_MAX_LEN 7 + #define QMI_WLANFW_QDSS_TRACE_MODE_RESP_V01 0x0045 +-#define QMI_WLANFW_QDSS_STOP_ALL_TRACE 0x3f ++#define QMI_WLANFW_QDSS_STOP_ALL_TRACE 0x01 + + enum qmi_wlanfw_qdss_trace_mode_enum_v01 { + WLFW_QDSS_TRACE_MODE_ENUM_MIN_VAL_V01 = INT_MIN, +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/core.h +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/core.h 2023-03-03 10:20:29.501148015 +0530 ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/core.h 2023-03-03 10:20:29.497148047 +0530 +@@ -1238,6 +1238,8 @@ struct ath12k_base { + + struct vendor_info id; + ++ int userpd_id; ++ + /* must be last */ + u8 drv_priv[0] __aligned(sizeof(void *)); + }; +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/ahb.c +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/ahb.c 2023-03-03 10:20:29.501148015 +0530 ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/ahb.c 2023-03-03 10:20:29.497148047 +0530 +@@ -867,13 +867,39 @@ static int ath12k_ahb_fw_resource_deinit + return 0; + } + ++static int ath12k_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) { ++ dev_err(dev, "Not multipd architecture"); ++ return 0; ++ } ++ ++ if (strcmp(subsys_name, "q6v5_wcss_userpd1") == 0) { ++ userpd_id = USERPD_0; ++ } else if (strcmp(subsys_name, "q6v5_wcss_userpd2") == 0) { ++ userpd_id = USERPD_1; ++ } else if (strcmp(subsys_name, "q6v5_wcss_userpd3") == 0) { ++ userpd_id = USERPD_2; ++ } ++ ++ return userpd_id; ++} ++ + static int ath12k_ahb_probe(struct platform_device *pdev) + { + struct ath12k_base *ab; + const struct of_device_id *of_id; + const struct ath12k_hif_ops *hif_ops; ++ struct device *dev = &pdev->dev; + enum ath12k_hw_rev hw_rev; +- int ret; ++ int ret, userpd_id; + + of_id = of_match_device(ath12k_ahb_of_match, &pdev->dev); + if (!of_id) { +@@ -881,6 +907,8 @@ static int ath12k_ahb_probe(struct platf + return -EINVAL; + } + ++ userpd_id = ath12k_get_userpd_id(dev); ++ + hw_rev = (enum ath12k_hw_rev)of_id->data; + + switch (hw_rev) { +@@ -909,7 +937,7 @@ static int ath12k_ahb_probe(struct platf + ab->pdev = pdev; + ab->hw_rev = hw_rev; + platform_set_drvdata(pdev, ab); +- ++ ab->userpd_id = userpd_id; + + ret = ath12k_core_pre_init(ab); + if (ret) diff --git a/feeds/ipq95xx/mac80211/patches/qca/718-ath12k-failed-sent-pkts.patch b/feeds/ipq95xx/mac80211/patches/qca/718-ath12k-failed-sent-pkts.patch new file mode 100644 index 000000000..2ad0b36ae --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/718-ath12k-failed-sent-pkts.patch @@ -0,0 +1,99 @@ +From 8bb73e12be5be1bce24275631e4ee37886edf051 Mon Sep 17 00:00:00 2001 +From: saleemuddin shaik +Date: Sat, 4 Mar 2023 14:03:08 +0530 +Subject: ath12k: add statistic support for counting wmm failed sent + packets. + +if the acknowledgement is not received for the packets sent in the air, +then incrementing the drop packets are counted based on WMM categories. + +Signed-off-by: saleemuddin shaik +--- + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/debugfs.c | 12 ++++++++++++ + drivers/net/wireless/ath/ath12k/dp_tx.c | 7 +++++++ + 3 files changed, 20 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h +index 1b03d46..8443f46 100644 +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -733,6 +733,7 @@ struct ath12k_wmm_stats { + int rx_type; + u64 total_wmm_tx_pkts[WME_NUM_AC]; + u64 total_wmm_rx_pkts[WME_NUM_AC]; ++ u64 total_wmm_tx_drop[WME_NUM_AC]; + }; + + #define ATH12K_DSCP_PRIORITY 7 +diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c +index 6509567..e6056ba 100644 +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -1355,6 +1355,7 @@ static ssize_t ath12k_read_wmm_stats(struct file *file, + ssize_t retval; + u64 total_wmm_sent_pkts = 0; + u64 total_wmm_received_pkts = 0; ++ u64 total_wmm_fail_sent = 0; + + buf = kzalloc(size, GFP_KERNEL); + if (!buf) { +@@ -1366,12 +1367,15 @@ static ssize_t ath12k_read_wmm_stats(struct file *file, + for (count = 0; count < WME_NUM_AC; count++) { + total_wmm_sent_pkts += ar->wmm_stats.total_wmm_tx_pkts[count]; + total_wmm_received_pkts += ar->wmm_stats.total_wmm_rx_pkts[count]; ++ total_wmm_fail_sent += ar->wmm_stats.total_wmm_tx_drop[count]; + } + + len += scnprintf(buf + len, size - len, "Total number of wmm_sent: %llu\n", + total_wmm_sent_pkts); + len += scnprintf(buf + len, size - len, "total number of wmm_received: %llu\n", + total_wmm_received_pkts); ++ len += scnprintf(buf + len, size - len, "total number of wmm_fail_sent: %llu\n", ++ total_wmm_fail_sent); + len += scnprintf(buf + len, size - len, "Num of BE wmm_sent: %llu\n", + ar->wmm_stats.total_wmm_tx_pkts[WME_AC_BE]); + len += scnprintf(buf + len, size - len, "Num of BK wmm_sent: %llu\n", +@@ -1388,6 +1392,14 @@ static ssize_t ath12k_read_wmm_stats(struct file *file, + ar->wmm_stats.total_wmm_rx_pkts[WME_AC_VI]); + len += scnprintf(buf + len, size - len, "num of vo wmm_received: %llu\n", + ar->wmm_stats.total_wmm_rx_pkts[WME_AC_VO]); ++ len += scnprintf(buf + len, size - len, "num of be wmm_tx_dropped: %llu\n", ++ ar->wmm_stats.total_wmm_tx_drop[WME_AC_BE]); ++ len += scnprintf(buf + len, size - len, "num of bk wmm_tx_dropped: %llu\n", ++ ar->wmm_stats.total_wmm_tx_drop[WME_AC_BK]); ++ len += scnprintf(buf + len, size - len, "num of vi wmm_tx_dropped: %llu\n", ++ ar->wmm_stats.total_wmm_tx_drop[WME_AC_VI]); ++ len += scnprintf(buf + len, size - len, "num of vo wmm_tx_dropped: %llu\n", ++ ar->wmm_stats.total_wmm_tx_drop[WME_AC_VO]); + + mutex_unlock(&ar->conf_mutex); + +diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c +index d79007b..a80662a 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -733,6 +733,7 @@ static inline void ath12k_dp_tx_status_parse(struct ath12k_base *ab, + ts->rate_stats = desc->rate_stats.info0; + else + ts->rate_stats = 0; ++ ts->tid = FIELD_GET(HAL_WBM_RELEASE_TX_INFO3_TID, desc->info3); + + ts->peer_id = FIELD_GET(HAL_WBM_RELEASE_TX_INFO3_PEER_ID, desc->info3); + ts->flags = FIELD_GET(HAL_WBM_RELEASE_TX_INFO2_FIRST_MSDU, desc->info2) | +@@ -798,6 +799,12 @@ static void ath12k_dp_tx_complete_msdu(struct ath12k *ar, + + ath12k_dp_tx_status_parse(ab, tx_status, &ts); + ++ ar->wmm_stats.tx_type = ath12k_tid_to_ac(ts.tid > ATH12K_DSCP_PRIORITY ? 0:ts.tid); ++ if (ar->wmm_stats.tx_type) { ++ if (ts.status != HAL_WBM_TQM_REL_REASON_FRAME_ACKED) ++ ar->wmm_stats.total_wmm_tx_drop[ar->wmm_stats.tx_type]++; ++ } ++ + if (unlikely(!rcu_access_pointer(ab->pdevs_active[ar->pdev_idx]))) { + dev_kfree_skb_any(msdu); + return; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/676-b-ath12k-Update-iowrite32-to-write_relaxed-to-boost-pe.patch b/feeds/ipq95xx/mac80211/patches/qca/718-b-ath12k-Update-iowrite32-to-write_relaxed-to-boost-pe.patch similarity index 66% rename from feeds/ipq95xx/mac80211/patches/qca/676-b-ath12k-Update-iowrite32-to-write_relaxed-to-boost-pe.patch rename to feeds/ipq95xx/mac80211/patches/qca/718-b-ath12k-Update-iowrite32-to-write_relaxed-to-boost-pe.patch index 65b672e59..f9678b1f5 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/676-b-ath12k-Update-iowrite32-to-write_relaxed-to-boost-pe.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/718-b-ath12k-Update-iowrite32-to-write_relaxed-to-boost-pe.patch @@ -1,23 +1,24 @@ -From 96c7d66f7fac7628067dd9a6ac62589ae571f0fa Mon Sep 17 00:00:00 2001 -From: Balamurugan Mahalingam -Date: Thu, 13 Oct 2022 17:33:02 -0700 -Subject: [PATCH 2/7] ath12k: Update iowrite32 to write_relaxed to boost - performance +From 14bdf1487a0bfdc9c1f31c2387aa6e4eb71d7bbb Mon Sep 17 00:00:00 2001 +From: Ramanathan Choodamani +Date: Fri, 17 Feb 2023 01:50:42 -0800 +Subject: [PATCH 2/7] ath12k: Update iowrite32 to + write_relaxed to boost performance Use writel_relaxed instead iowrite32 to avoid the memory barrier instuction and slowdown the cpu execution performance. This helps improve the throughput by 150Mbps Signed-off-by: Balamurugan Mahalingam +Signed-off-by: Ramanathan Choodamani --- drivers/net/wireless/ath/ath12k/hal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath12k/hal.h b/drivers/net/wireless/ath/ath12k/hal.h -index f1525ed..4922ead 100644 +index a195115..c75b66a 100644 --- a/drivers/net/wireless/ath/ath12k/hal.h +++ b/drivers/net/wireless/ath/ath12k/hal.h -@@ -1211,7 +1211,7 @@ void ath12k_hal_srng_access_umac_src_ring_end_nolock(void *mem, +@@ -1245,7 +1245,7 @@ void ath12k_hal_srng_access_umac_src_ring_end_nolock(void *mem, srng->u.src_ring.last_tp = *(volatile u32 *)srng->u.src_ring.tp_addr; @@ -27,5 +28,5 @@ index f1525ed..4922ead 100644 srng->timestamp = jiffies; } -- -2.17.1 +2.7.4 diff --git a/feeds/ipq95xx/mac80211/patches/qca/676-c-ath12k-optimize-datapath-tx-completion-routine.patch b/feeds/ipq95xx/mac80211/patches/qca/718-c-ath12k-optimize-datapath-tx-completion-routine.patch similarity index 61% rename from feeds/ipq95xx/mac80211/patches/qca/676-c-ath12k-optimize-datapath-tx-completion-routine.patch rename to feeds/ipq95xx/mac80211/patches/qca/718-c-ath12k-optimize-datapath-tx-completion-routine.patch index 38cde3ccf..13a397cdc 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/676-c-ath12k-optimize-datapath-tx-completion-routine.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/718-c-ath12k-optimize-datapath-tx-completion-routine.patch @@ -1,24 +1,26 @@ -From 0e61c67c914efd88130e5af49d4aa9dbb3829141 Mon Sep 17 00:00:00 2001 -From: Balamurugan Mahalingam -Date: Mon, 17 Oct 2022 11:27:49 -0700 -Subject: [PATCH 3/7] ath12k: optimize datapath tx completion routine +From 5ef626578252e8ee8dfdbd08f9cdbca1ab557f27 Mon Sep 17 00:00:00 2001 +From: Ramanathan Choodamani +Date: Sat, 4 Mar 2023 20:31:42 -0800 +Subject: [PATCH] ath12k: optimize datapath tx completion routine Avoid copying all descriptors to a cached memory list and then processing it again. Avoid two loops to process it. Use a single loop to process the tx completion Signed-off-by: Balamurugan Mahalingam + +Signed-off-by: Ramanathan Choodamani --- - drivers/net/wireless/ath/ath12k/dp.c | 17 +---------- - drivers/net/wireless/ath/ath12k/dp.h | 3 -- - drivers/net/wireless/ath/ath12k/dp_tx.c | 38 ++++++++++--------------- - 3 files changed, 16 insertions(+), 42 deletions(-) + drivers/net/wireless/ath/ath12k/dp.c | 19 +---------------- + drivers/net/wireless/ath/ath12k/dp.h | 3 --- + drivers/net/wireless/ath/ath12k/dp_tx.c | 36 +++++++++++++-------------------- + 3 files changed, 15 insertions(+), 43 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c -index 9f6be7a..a671cda 100644 +index 0af711b..5aa0147 100644 --- a/drivers/net/wireless/ath/ath12k/dp.c +++ b/drivers/net/wireless/ath/ath12k/dp.c -@@ -248,9 +248,9 @@ int ath12k_dp_srng_setup(struct ath12k_base *ab, struct dp_srng *ring, +@@ -247,9 +247,9 @@ int ath12k_dp_srng_setup(struct ath12k_base *ab, struct dp_srng *ring, /* Allocate the reo dst and tx completion rings from cacheable memory */ switch (type) { case HAL_REO_DST: @@ -29,7 +31,7 @@ index 9f6be7a..a671cda 100644 default: cached = false; } -@@ -1273,7 +1273,6 @@ static void ath12k_dp_reoq_lut_cleanup(struct ath12k_base *ab) +@@ -1295,7 +1295,6 @@ static void ath12k_dp_reoq_lut_cleanup(struct ath12k_base *ab) void ath12k_dp_free(struct ath12k_base *ab) { struct ath12k_dp *dp = &ab->dp; @@ -37,19 +39,19 @@ index 9f6be7a..a671cda 100644 ath12k_dp_link_desc_cleanup(ab, dp->link_desc_banks, HAL_WBM_IDLE_LINK, &dp->wbm_idle_ring); -@@ -1285,9 +1284,6 @@ void ath12k_dp_free(struct ath12k_base *ab) +@@ -1307,9 +1306,6 @@ void ath12k_dp_free(struct ath12k_base *ab) - ath12k_dp_reo_cmd_list_cleanup(ab); + ath12k_dp_rx_reo_cmd_list_cleanup(ab); -- for (i = 0; i < DP_TCL_NUM_RING_MAX; i++) +- for (i = 0; i < ab->hw_params->max_tx_ring; i++) - kfree(dp->tx_ring[i].tx_status); - ath12k_dp_rx_free(ab); /* Deinit any SOC level resource */ } -@@ -1603,15 +1599,6 @@ int ath12k_dp_alloc(struct ath12k_base *ab) +@@ -1723,17 +1719,6 @@ int ath12k_dp_alloc(struct ath12k_base *ab) - for (i = 0; i < DP_TCL_NUM_RING_MAX; i++) { + for (i = 0; i < ab->hw_params->max_tx_ring; i++) { dp->tx_ring[i].tcl_data_ring_id = i; - - dp->tx_ring[i].tx_status_head = 0; @@ -57,13 +59,15 @@ index 9f6be7a..a671cda 100644 - dp->tx_ring[i].tx_status = kmalloc(size, GFP_KERNEL); - if (!dp->tx_ring[i].tx_status) { - ret = -ENOMEM; -- //FIXME The allocated tx status is not freed properly here +- /* FIXME The allocated tx status is not freed +- * properly here +- */ - goto fail_cmn_reoq_cleanup; - } } for (i = 0; i < HAL_DSCP_TID_MAP_TBL_NUM_ENTRIES_MAX; i++) -@@ -1627,8 +1614,6 @@ int ath12k_dp_alloc(struct ath12k_base *ab) +@@ -1749,8 +1734,6 @@ int ath12k_dp_alloc(struct ath12k_base *ab) fail_dp_rx_free: ath12k_dp_rx_free(ab); @@ -73,10 +77,10 @@ index 9f6be7a..a671cda 100644 fail_cmn_srng_cleanup: diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h -index 97193f0..9008b70 100644 +index 3726c61..d994767 100644 --- a/drivers/net/wireless/ath/ath12k/dp.h +++ b/drivers/net/wireless/ath/ath12k/dp.h -@@ -81,9 +81,6 @@ struct dp_tx_ring { +@@ -44,9 +44,6 @@ struct dp_tx_ring { u8 tcl_data_ring_id; struct dp_srng tcl_data_ring; struct dp_srng tcl_comp_ring; @@ -87,13 +91,13 @@ index 97193f0..9008b70 100644 struct ath12k_pdev_mon_stats { diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c -index ac954d1..509e64e 100644 +index a461c7d..e4a67fb 100644 --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -794,8 +794,8 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id) - struct dp_tx_ring *tx_ring = &dp->tx_ring[ring_id]; +@@ -932,8 +932,8 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id) u32 *desc, desc_id; u8 mac_id; + u64 desc_va; - int valid_entries, count = 0, i = 0; - struct hal_wbm_completion_ring_tx *tx_status; + int valid_entries; @@ -101,7 +105,7 @@ index ac954d1..509e64e 100644 enum hal_wbm_rel_src_module buf_rel_source; spin_lock_bh(&status_ring->lock); -@@ -815,30 +815,18 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id) +@@ -953,29 +953,18 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id) if (!ath12k_dp_tx_completion_valid(desc)) continue; @@ -109,7 +113,7 @@ index ac954d1..509e64e 100644 - desc, sizeof(struct hal_wbm_release_ring)); - count++; + memcpy(&tx_status, desc, -+ sizeof(struct hal_wbm_completion_ring_tx)); ++ sizeof(struct hal_wbm_completion_ring_tx)); - if (count == DP_TX_COMP_RING_SIZE) - break; @@ -118,53 +122,54 @@ index ac954d1..509e64e 100644 - ath12k_hal_srng_access_end(ab, status_ring); - - spin_unlock_bh(&status_ring->lock); -- + - while (count--) { - tx_status = &tx_ring->tx_status[i++]; - -- if (likely(FIELD_GET(HAL_WBM_COMPL_TX_INFO0_CC_DONE, tx_status->info0))) { +- if (likely(u32_get_bits(tx_status->info0, HAL_WBM_COMPL_TX_INFO0_CC_DONE))) { + if (likely(FIELD_GET(HAL_WBM_COMPL_TX_INFO0_CC_DONE, tx_status.info0))) { /* HW done cookie conversion */ - tx_desc = (struct ath12k_tx_desc_info *)(uintptr_t) -- (tx_status->buf_va_lo | -- (((u64)tx_status->buf_va_hi) << 32)); -+ (tx_status.buf_va_lo | -+ (((u64)tx_status.buf_va_hi) << 32)); +- desc_va = ((u64)tx_status->buf_va_hi << 32 | +- tx_status->buf_va_lo); ++ desc_va = ((u64)tx_status.buf_va_hi << 32 | ++ tx_status.buf_va_lo); + tx_desc = (struct ath12k_tx_desc_info *)((unsigned long)desc_va); } else { /* SW does cookie conversion to VA */ - desc_id = FIELD_GET(BUFFER_ADDR_INFO1_SW_COOKIE, -- tx_status->buf_va_hi); -+ tx_status.buf_va_hi); +- desc_id = u32_get_bits(tx_status->buf_va_hi, ++ desc_id = u32_get_bits(tx_status.buf_va_hi, + BUFFER_ADDR_INFO1_SW_COOKIE); tx_desc = ath12k_dp_get_tx_desc(ab, desc_id); - } -@@ -855,10 +843,10 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id) +@@ -993,11 +982,11 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id) */ ath12k_dp_tx_release_txbuf(dp, tx_desc, tx_desc->pool_id); buf_rel_source = FIELD_GET(HAL_WBM_RELEASE_INFO0_REL_SRC_MODULE, - tx_status->info0); + tx_status.info0); + ab->soc_stats.wbm_rel_source[buf_rel_source]++; if (unlikely(buf_rel_source == HAL_WBM_REL_SRC_MODULE_FW)) { ath12k_dp_tx_process_htt_tx_complete(ab, - (void *)tx_status, + (void *)&tx_status, mac_id, msdu, - tx_ring, skb_ext_desc); - continue; -@@ -869,8 +857,12 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id) + tx_ring, + skb_ext_desc, +@@ -1010,10 +999,13 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id) if (atomic_dec_and_test(&ar->dp.num_tx_pending)) wake_up(&ar->dp.tx_empty_waitq); -- ath12k_dp_tx_complete_msdu(ar, msdu, tx_status, buf_rel_source, skb_ext_desc); -+ ath12k_dp_tx_complete_msdu(ar, msdu, &tx_status, buf_rel_source, skb_ext_desc); +- ath12k_dp_tx_complete_msdu(ar, msdu, tx_status, ++ ath12k_dp_tx_complete_msdu(ar, msdu, &tx_status, + buf_rel_source, skb_ext_desc, + tx_ring->tcl_data_ring_id); } -+ + ath12k_hal_srng_access_end(ab, status_ring); + + spin_unlock_bh(&status_ring->lock); } - int ath12k_dp_tx_send_reo_cmd(struct ath12k_base *ab, struct dp_rx_tid *rx_tid, + static int -- -2.17.1 +2.7.4 diff --git a/feeds/ipq95xx/mac80211/patches/qca/718-cfg80211-fix-6GHz-AP-STA-concurrency-issue.patch b/feeds/ipq95xx/mac80211/patches/qca/718-cfg80211-fix-6GHz-AP-STA-concurrency-issue.patch new file mode 100644 index 000000000..0623a4568 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/718-cfg80211-fix-6GHz-AP-STA-concurrency-issue.patch @@ -0,0 +1,74 @@ +From b8dff8e9730b4ac9ec6e2542c3e841ff842888a8 Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Tue, 14 Mar 2023 13:01:41 +0530 +Subject: [PATCH] cfg80211: fix 6GHz AP-STA concurrency issue + +Currently, for 6 GHz band, 9 different channel pools are maintained +based on the various 6G regulatory power mode a device can be +configured in. Due to this, chandef chan pointer will not be same +for AP and STA. During, AP-STA concurrency, chandef compatibility is +matched and for 6 GHz it fails which ultimately leads to nl80211_start_ap +returning EBUSY. + +This changes were removed as part of refactoring the cfg80211 to handle +multiple hw abstraction. Hence, add a new api to check to channels for 6 GHz bands + +Fixes: 830c2dd38c0f ("capability advertisement infra for multi-hw abstraction under one wiphy") + +Change-Id: Iae5c344765fe9f748fa848b25b4a9fa80b617497 +Signed-off-by: Aditya Kumar Singh +Signed-off-by: Harshitha Prem +--- + include/net/cfg80211.h | 33 +++++++++++++++++++++++++++++++-- + 1 file changed, 31 insertions(+), 2 deletions(-) + +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -908,6 +908,37 @@ void cfg80211_chandef_create(struct cfg8 + enum nl80211_channel_type chantype); + + /** ++ * cfg80211_channel_identical - check if two channel definitions are identical ++ * for 6 GHz band alone check center_freq as they have ++ * different power modes. ++ * @channel1: first channel definition ++ * @channel2: second channel definition ++ * ++ * Return: %true if the channels defined by the channel definitions are ++ * identical except power related settings, %false otherwise. ++ */ ++ ++static inline bool ++cfg80211_channel_identical(struct ieee80211_channel *channel1, ++ struct ieee80211_channel *channel2) ++{ ++ if (channel1 == channel2) ++ return true; ++ ++ if (!channel1 || !channel2) ++ return false; ++ ++ if (channel1->band != channel2->band) ++ return false; ++ ++ if (channel1->band != NL80211_BAND_6GHZ) ++ return false; ++ ++ return (channel1->center_freq == channel2->center_freq && ++ channel1->freq_offset == channel2->freq_offset); ++} ++ ++/** + * cfg80211_chandef_identical - check if two channel definitions are identical + * @chandef1: first channel definition + * @chandef2: second channel definition +@@ -919,7 +950,8 @@ static inline bool + cfg80211_chandef_identical(const struct cfg80211_chan_def *chandef1, + const struct cfg80211_chan_def *chandef2) + { +- return (chandef1->chan == chandef2->chan && ++ return (cfg80211_channel_identical(chandef1->chan, ++ chandef2->chan) && + chandef1->width == chandef2->width && + chandef1->center_freq1 == chandef2->center_freq1 && + chandef1->freq1_offset == chandef2->freq1_offset && diff --git a/feeds/ipq95xx/mac80211/patches/qca/676-d-ath12k-remove-locks-and-optimize-tx-completion-path.patch b/feeds/ipq95xx/mac80211/patches/qca/718-d-ath12k-remove-locks-and-optimize-tx-completion-path.patch similarity index 78% rename from feeds/ipq95xx/mac80211/patches/qca/676-d-ath12k-remove-locks-and-optimize-tx-completion-path.patch rename to feeds/ipq95xx/mac80211/patches/qca/718-d-ath12k-remove-locks-and-optimize-tx-completion-path.patch index 8cf4b1a8e..88d642685 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/676-d-ath12k-remove-locks-and-optimize-tx-completion-path.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/718-d-ath12k-remove-locks-and-optimize-tx-completion-path.patch @@ -1,7 +1,7 @@ -From 4259383e2decfbff254fd2a10dd4ebd6515958ec Mon Sep 17 00:00:00 2001 -From: Balamurugan Mahalingam -Date: Mon, 17 Oct 2022 11:29:38 -0700 -Subject: [PATCH 4/7] ath12k: remove locks and optimize tx completion path +From c7f71aa364633e3a28a1a5506b12819c64c3424a Mon Sep 17 00:00:00 2001 +From: Ramanathan Choodamani +Date: Sat, 4 Mar 2023 20:36:53 -0800 +Subject: [PATCH] ath12k: remove locks and optimize tx completion path Avoid taking locks while processing the tx completion. The rings are accessed associated with specific cores for processing. There @@ -15,6 +15,7 @@ specific irq smp affinity and process the tx completions on a specific core Signed-off-by: Balamurugan Mahalingam +Signed-off-by: Ramanathan Choodamani --- drivers/net/wireless/ath/ath12k/dp_tx.c | 11 +++-------- drivers/net/wireless/ath/ath12k/hal.c | 5 ++--- @@ -23,10 +24,10 @@ Signed-off-by: Balamurugan Mahalingam 4 files changed, 29 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c -index 509e64e..dd71f9b 100644 +index e4a67fb..9fd274f 100644 --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -66,11 +66,9 @@ static void ath12k_dp_tx_release_txbuf(struct ath12k_dp *dp, +@@ -70,11 +70,9 @@ static void ath12k_dp_tx_release_txbuf(struct ath12k_dp *dp, struct ath12k_tx_desc_info *tx_desc, u8 ring_id) { @@ -38,7 +39,7 @@ index 509e64e..dd71f9b 100644 } static inline -@@ -798,14 +796,12 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id) +@@ -936,14 +934,12 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id) struct hal_wbm_completion_ring_tx tx_status = { 0 }; enum hal_wbm_rel_src_module buf_rel_source; @@ -55,22 +56,22 @@ index 509e64e..dd71f9b 100644 return; } -@@ -860,9 +856,8 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id) - ath12k_dp_tx_complete_msdu(ar, msdu, &tx_status, buf_rel_source, skb_ext_desc); +@@ -1003,9 +999,8 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id) + buf_rel_source, skb_ext_desc, + tx_ring->tcl_data_ring_id); } - - ath12k_hal_srng_access_end(ab, status_ring); + ath12k_hal_srng_access_umac_dst_ring_end_nolock(ab->mem, status_ring); - spin_unlock_bh(&status_ring->lock); } - int ath12k_dp_tx_send_reo_cmd(struct ath12k_base *ab, struct dp_rx_tid *rx_tid, + static int diff --git a/drivers/net/wireless/ath/ath12k/hal.c b/drivers/net/wireless/ath/ath12k/hal.c -index 7dd00e0..2912627 100644 +index 2fb931f..cea5562 100644 --- a/drivers/net/wireless/ath/ath12k/hal.c +++ b/drivers/net/wireless/ath/ath12k/hal.c -@@ -936,8 +936,8 @@ u32 *ath12k_hal_srng_dst_peek(struct ath12k_base *ab, struct hal_srng *srng) +@@ -1580,8 +1580,8 @@ u32 *ath12k_hal_srng_dst_peek(struct ath12k_base *ab, struct hal_srng *srng) return NULL; } @@ -81,7 +82,7 @@ index 7dd00e0..2912627 100644 { u32 *desc; -@@ -1008,7 +1008,6 @@ void ath12k_hal_srng_dst_invalidate_entry(struct ath12k_base *ab, +@@ -1652,7 +1652,6 @@ void ath12k_hal_srng_dst_invalidate_entry(struct ath12k_base *ab, u32 *desc; u32 tp, hp; @@ -90,23 +91,22 @@ index 7dd00e0..2912627 100644 if (!(srng->flags & HAL_SRNG_FLAGS_CACHED) || !entries) return; diff --git a/drivers/net/wireless/ath/ath12k/hal.h b/drivers/net/wireless/ath/ath12k/hal.h -index 4922ead..d0e444d 100644 +index 542c3ac..74f5984 100644 --- a/drivers/net/wireless/ath/ath12k/hal.h +++ b/drivers/net/wireless/ath/ath12k/hal.h -@@ -1163,6 +1163,8 @@ void ath12k_hal_reo_ring_ctrl_hash_ix3_setup(struct ath12k_base *ab, - u32 ring_hash_map); +@@ -1195,6 +1195,8 @@ void ath12k_hal_reo_ring_ctrl_hash_ix3_setup(struct ath12k_base *ab, void ath12k_hal_reo_ring_ctrl_hash_ix2_setup(struct ath12k_base *ab, u32 ring_hash_map); + void ath12k_hal_reo_shared_qaddr_cache_clear(struct ath12k_base *ab); +void ath12k_hal_srng_prefetch_desc(struct ath12k_base *ab, + struct hal_srng *srng); static inline u32 *ath12k_hal_srng_src_get_next_entry_nolock(struct ath12k_base *ab, -@@ -1203,6 +1205,16 @@ void ath12k_hal_srng_access_src_ring_begin_nolock(void *mem, - srng->u.src_ring.cached_tp = *(volatile u32 *)srng->u.src_ring.tp_addr; +@@ -1236,6 +1238,16 @@ void ath12k_hal_srng_access_src_ring_begin_nolock(void *mem, } -+static inline + static inline +void ath12k_hal_srng_access_dst_ring_begin_nolock(struct ath12k_base *ab, + struct hal_srng *srng) +{ @@ -116,10 +116,11 @@ index 4922ead..d0e444d 100644 + ath12k_hal_srng_prefetch_desc(ab, srng); +} + - static inline ++static inline void ath12k_hal_srng_access_umac_src_ring_end_nolock(void *mem, struct hal_srng *srng) -@@ -1216,4 +1228,15 @@ void ath12k_hal_srng_access_umac_src_ring_end_nolock(void *mem, + { +@@ -1248,4 +1260,15 @@ void ath12k_hal_srng_access_umac_src_ring_end_nolock(void *mem, srng->timestamp = jiffies; } @@ -143,12 +144,12 @@ index 45f5aef..ce7c0a0 100644 ATH12K_TX_RING_MASK_0, ATH12K_TX_RING_MASK_1, ATH12K_TX_RING_MASK_2, -- ATH12K_TX_RING_MASK_3, +- ATH12K_TX_RING_MASK_4, 0, 0, 0, 0, 0, 0, 0, 0, -+ ATH12K_TX_RING_MASK_3, ++ ATH12K_TX_RING_MASK_4, }, .rx_mon_dest = { 0, 0, 0, 0, 0, 0, 0, 0, -- -2.17.1 +2.7.4 diff --git a/feeds/ipq95xx/mac80211/patches/qca/718-e-mac80211-Deliver-the-frame-to-driver-tx-ops-directly.patch b/feeds/ipq95xx/mac80211/patches/qca/718-e-mac80211-Deliver-the-frame-to-driver-tx-ops-directly.patch new file mode 100644 index 000000000..dedc191fe --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/718-e-mac80211-Deliver-the-frame-to-driver-tx-ops-directly.patch @@ -0,0 +1,77 @@ +From f37e9b4a68d32d03346cbfc3cb4178b186c8f2a4 Mon Sep 17 00:00:00 2001 +From: Ramanathan Choodamani +Date: Fri, 17 Feb 2023 03:08:29 -0800 +Subject: [PATCH 5/7] mac80211: Deliver the frame to driver tx ops + directly + +Deliver the frame to driver directly in the forwarding path +to improve the throughput performance. + +Reset the fast xmit flag in ieee80211 datapath to ensure +other features handled as normal through the ath12k_dp_tx +function + +Signed-off-by: Balamurugan Mahalingam +Signed-off-by: Ramanathan Choodamani +Signed-off-by: Aloka Dixit +--- + net/mac80211/tx.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -4630,6 +4630,7 @@ netdev_tx_t ieee80211_subif_start_xmit(s + #ifdef CPTCFG_MAC80211_NSS_SUPPORT + ieee80211_xmit_nss_fixup(skb, dev); + #endif ++ skb->fast_xmit = 0; + + if (likely(!is_multicast_ether_addr(eth->h_dest))) + goto normal; +@@ -4878,7 +4879,45 @@ void ieee80211_8023_xmit_ap(struct ieee8 + netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb, + struct net_device *dev) + { +- return __ieee80211_subif_start_xmit_8023(skb, dev, 0, 0, NULL); ++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); ++ struct ieee80211_tx_control control = {}; ++ struct sta_info *sta; ++ struct ieee80211_sta *pubsta = NULL; ++ ++ info->control.vif = &sdata->vif; ++ ++ if (skb->fast_xmit) { ++ info->control.flags = u32_encode_bits(IEEE80211_LINK_UNSPECIFIED, ++ IEEE80211_TX_CTRL_MLO_LINK); ++ info->flags = IEEE80211_TX_CTL_HW_80211_ENCAP; ++ ++ if (hweight16(sdata->vif.valid_links) > 1) { ++ rcu_read_lock(); ++ ++ if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) { ++ kfree_skb(skb); ++ goto out; ++ } ++ ++ if (!IS_ERR_OR_NULL(sta) && sta->uploaded) ++ pubsta = &sta->sta; ++ ++ control.sta = pubsta; ++ ieee80211_tx_stats(dev, skb->len); ++ drv_tx(sdata->local, &control, skb); ++out: ++ rcu_read_unlock(); ++ } else { ++ control.sta = NULL; ++ ieee80211_tx_stats(dev, skb->len); ++ drv_tx(sdata->local, &control, skb); ++ } ++ ++ return NETDEV_TX_OK; ++ } else { ++ return __ieee80211_subif_start_xmit_8023(skb, dev, 0, 0, NULL); ++ } + } + + netdev_tx_t __ieee80211_subif_start_xmit_8023(struct sk_buff *skb, diff --git a/feeds/ipq95xx/mac80211/patches/qca/676-f-ath12k-Add-ath12k_dp_tx_direct-for-faster-tx-process.patch b/feeds/ipq95xx/mac80211/patches/qca/718-f-ath12k-Add-ath12k_dp_tx_direct-for-faster-tx-process.patch similarity index 66% rename from feeds/ipq95xx/mac80211/patches/qca/676-f-ath12k-Add-ath12k_dp_tx_direct-for-faster-tx-process.patch rename to feeds/ipq95xx/mac80211/patches/qca/718-f-ath12k-Add-ath12k_dp_tx_direct-for-faster-tx-process.patch index e3a015d53..a4f86aa39 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/676-f-ath12k-Add-ath12k_dp_tx_direct-for-faster-tx-process.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/718-f-ath12k-Add-ath12k_dp_tx_direct-for-faster-tx-process.patch @@ -1,7 +1,8 @@ -From 17a15b2a0de6a92fc331ca878ac07f5675905fc6 Mon Sep 17 00:00:00 2001 -From: Balamurugan Mahalingam -Date: Mon, 17 Oct 2022 11:30:47 -0700 -Subject: [PATCH 6/7] ath12k: Add ath12k_dp_tx_direct for faster tx processing +From 5e81f421752af5dcb22d61de60e9091ee2268d16 Mon Sep 17 00:00:00 2001 +From: Ramanathan Choodamani +Date: Wed, 8 Mar 2023 07:05:09 -0800 +Subject: [PATCH 4/6] ath12k: Add ath12k_dp_tx_direct for + faster tx processing Add a new routine to process the packets in the forwarding path faster and increase the throughput. Frame delivered to this function @@ -13,19 +14,18 @@ Initialize the descriptor memory once during init and avoid initializing the unused fields to 0 on a per packet basis Signed-off-by: Balamurugan Mahalingam +Signed-off-by: Ramanathan Choodamani --- drivers/net/wireless/ath/ath12k/dp.c | 1 + - drivers/net/wireless/ath/ath12k/dp_tx.c | 92 ++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/dp_tx.c | 92 ++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath12k/dp_tx.h | 1 + drivers/net/wireless/ath/ath12k/hal_desc.h | 6 ++ - drivers/net/wireless/ath/ath12k/mac.c | 15 +++- - 5 files changed, 114 insertions(+), 1 deletion(-) + drivers/net/wireless/ath/ath12k/mac.c | 15 ++++- + 5 files changed, 113 insertions(+), 2 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c -index a671cda..8b8365e 100644 --- a/drivers/net/wireless/ath/ath12k/dp.c +++ b/drivers/net/wireless/ath/ath12k/dp.c -@@ -267,6 +267,7 @@ int ath12k_dp_srng_setup(struct ath12k_base *ab, struct dp_srng *ring, +@@ -266,6 +266,7 @@ int ath12k_dp_srng_setup(struct ath12k_b if (!ring->vaddr_unaligned) return -ENOMEM; @@ -33,15 +33,13 @@ index a671cda..8b8365e 100644 ring->vaddr = PTR_ALIGN(ring->vaddr_unaligned, HAL_RING_BASE_ALIGN); ring->paddr = ring->paddr_unaligned + ((unsigned long)ring->vaddr - (unsigned long)ring->vaddr_unaligned); -diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c -index dd71f9b..d71559a 100644 --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -127,6 +127,98 @@ static void ath12k_hal_tx_cmd_ext_desc_setup(struct ath12k_base *ab, void *cmd, - ti->encrypt_type); +@@ -171,6 +171,100 @@ static int ath12k_dp_prepare_htt_metadat + return 0; } -+int ath12k_dp_tx_direct(struct ath12k_vif *arvif, struct sk_buff *skb) ++int ath12k_dp_tx_direct(struct ath12k_link_vif *arvif, struct sk_buff *skb) +{ + struct ath12k *ar = arvif->ar; + struct ath12k_base *ab = arvif->ar->ab; @@ -77,7 +75,7 @@ index dd71f9b..d71559a 100644 + + tx_desc->skb = skb; + tx_desc->mac_id = ar->pdev_idx; -+ skb_cb->vif = arvif->vif; ++ skb_cb->vif = arvif->ahvif->vif; + skb_cb->ar = ar; + + hal_ring_id = tx_ring->tcl_data_ring.ring_id; @@ -96,6 +94,8 @@ index dd71f9b..d71559a 100644 + goto fail_unmap_dma; + } + ++ ab->soc_stats.tx_enqueued[ring_id]++; ++ + tcl_desc.buf_addr_info.info0 = FIELD_PREP(BUFFER_ADDR_INFO0_ADDR, skb_cb->paddr); + tcl_desc.buf_addr_info.info1 = FIELD_PREP(BUFFER_ADDR_INFO1_ADDR, + ((uint64_t)skb_cb->paddr >> HAL_ADDR_MSB_REG_SHIFT)); @@ -133,24 +133,20 @@ index dd71f9b..d71559a 100644 +} +EXPORT_SYMBOL(ath12k_dp_tx_direct); + - int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif, - struct ath12k_sta *arsta, struct sk_buff *skb) - { -diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.h b/drivers/net/wireless/ath/ath12k/dp_tx.h -index 98f7704..430fa35 100644 + int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif, + struct ath12k_sta *ahsta, struct sk_buff *skb, + bool gsn_valid, int mcbc_gsn) --- a/drivers/net/wireless/ath/ath12k/dp_tx.h +++ b/drivers/net/wireless/ath/ath12k/dp_tx.h -@@ -45,4 +45,5 @@ int ath12k_dp_tx_htt_tx_filter_setup(struct ath12k_base *ab, u32 ring_id, +@@ -239,4 +239,5 @@ int ath12k_dp_tx_htt_tx_filter_setup(str int ath12k_dp_tx_htt_tx_monitor_mode_ring_config(struct ath12k *ar, bool reset); int ath12k_dp_tx_htt_monitor_mode_ring_config(struct ath12k *ar, bool reset); int ath12k_dp_tx_htt_h2t_vdev_stats_ol_req(struct ath12k *ar, u64 reset_bitmask); -+int ath12k_dp_tx_direct(struct ath12k_vif *arvif, struct sk_buff *skb); ++int ath12k_dp_tx_direct(struct ath12k_link_vif *arvif, struct sk_buff *skb); #endif -diff --git a/drivers/net/wireless/ath/ath12k/hal_desc.h b/drivers/net/wireless/ath/ath12k/hal_desc.h -index cb0e9ad..c0f8b72 100644 --- a/drivers/net/wireless/ath/ath12k/hal_desc.h +++ b/drivers/net/wireless/ath/ath12k/hal_desc.h -@@ -1290,6 +1290,12 @@ enum hal_wbm_htt_tx_comp_status { +@@ -1292,6 +1292,12 @@ enum hal_wbm_htt_tx_comp_status { HAL_WBM_REL_HTT_TX_COMP_STATUS_MAX, }; @@ -163,45 +159,62 @@ index cb0e9ad..c0f8b72 100644 struct hal_tcl_data_cmd { struct ath12k_buffer_addr buf_addr_info; u32 info0; -diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index 6d47feb..c5df666 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -6802,12 +6802,25 @@ static void ath12k_mac_op_tx(struct ieee80211_hw *hw, - struct ieee80211_key_conf *key = info->control.hw_key; - struct ath12k_mgmt_frame_stats *mgmt_stats = &arvif->mgmt_stats; - struct ath12k_sta *arsta = NULL; +@@ -8474,7 +8474,7 @@ static void ath12k_mac_op_tx(struct ieee + struct ath12k_sta *ahsta = NULL; + struct sk_buff *msdu_copied; + struct ath12k_link_sta *arsta = NULL; - struct ieee80211_sta *sta = control->sta; + struct ieee80211_sta *sta = NULL; + struct ath12k_peer *peer; u32 info_flags = info->flags; bool is_prb_rsp; - u16 frm_type = 0; +@@ -8486,6 +8486,9 @@ static void ath12k_mac_op_tx(struct ieee int ret; + u8 link = u32_get_bits(info->control.flags, IEEE80211_TX_CTRL_MLO_LINK); ++ if (control) ++ sta = control->sta; ++ + if (ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { + ieee80211_free_txskb(hw, skb); + return; +@@ -8493,7 +8496,6 @@ static void ath12k_mac_op_tx(struct ieee + + memset(skb_cb, 0, sizeof(*skb_cb)); + skb_cb->vif = vif; +- + /* handle only for MLO case, use deflink for non MLO case */ + if (vif->valid_links) { + link = ath12k_mac_get_tx_link(sta, vif, link, skb, info_flags); +@@ -8512,6 +8514,15 @@ static void ath12k_mac_op_tx(struct ieee + ieee80211_free_txskb(hw, skb); + return; + } + if (skb->fast_xmit) { + ret = ath12k_dp_tx_direct(arvif, skb); + if (unlikely(ret)) { + ath12k_warn(ar->ab, "failed to transmit frame %d\n", + ret); -+ dev_kfree_skb_any(skb); ++ ieee80211_free_txskb(hw, skb); + } + return; + } -+ -+ if (control) -+ sta = control->sta; -+ - if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { - ieee80211_free_txskb(ah->hw, skb); - return; --- -2.17.1 - -diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c -index 4f9a553..0c5bfe4 100644 + + ar = arvif->ar; + ah = ar->ah; --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -7432,6 +7432,9 @@ static void ath11k_mac_op_tx(struct ieee80211_hw *hw, +@@ -7408,7 +7408,6 @@ static void ath11k_mac_op_tx(struct ieee + struct ath11k_sta *arsta = NULL; + struct ieee80211_mgmt *mgmt; + u32 info_flags = info->flags; +- struct ieee80211_sta *sta = control->sta; + bool is_prb_rsp; + u16 frm_type = 0; + u8 tid, *qos_ctl; +@@ -7416,6 +7415,9 @@ static void ath11k_mac_op_tx(struct ieee int ret; u64 adjusted_tsf; @@ -211,7 +224,7 @@ index 4f9a553..0c5bfe4 100644 if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { ieee80211_free_txskb(ar->hw, skb); return; -@@ -7492,13 +7495,13 @@ static void ath11k_mac_op_tx(struct ieee80211_hw *hw, +@@ -7476,13 +7478,13 @@ static void ath11k_mac_op_tx(struct ieee return; } @@ -227,12 +240,43 @@ index 4f9a553..0c5bfe4 100644 info->ack_frame_id || vif->type == NL80211_IFTYPE_MESH_POINT || test_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags)) skb_cb->flags |= ATH11K_SKB_TX_STATUS; -@@ -7532,7 +7535,7 @@ static void ath11k_mac_op_tx(struct ieee80211_hw *hw, +@@ -7497,8 +7499,7 @@ static void ath11k_mac_op_tx(struct ieee + /* sta specific config has high precedence over vif specific config + * Hence overwrite sta specific config if it is present + */ +- if (sta) { +- arsta = (struct ath11k_sta *)sta->drv_priv; ++ if (arsta) { + if (arsta->tid_cfg[tid].noack == WMI_PEER_TID_CONFIG_NOACK) + noack = true; + +@@ -7512,9 +7513,8 @@ static void ath11k_mac_op_tx(struct ieee if (ar->ab->nss.enabled) ret = ath11k_nss_tx(arvif, skb); - else if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) +- ret = ath11k_dp_tx_simple(ar, arvif, skb, +- (control->sta) ? control->sta->drv_priv : NULL); + else if (info_flags & IEEE80211_TX_CTL_HW_80211_ENCAP) - ret = ath11k_dp_tx_simple(ar, arvif, skb, - (control->sta) ? control->sta->drv_priv : NULL); ++ ret = ath11k_dp_tx_simple(ar, arvif, skb, arsta); else + ret = ath11k_dp_tx(ar, arvif, arsta, skb); + +@@ -7525,13 +7525,10 @@ static void ath11k_mac_op_tx(struct ieee + return; + } + +- if (ath11k_debugfs_is_extd_tx_stats_enabled(ar) && sta) { +- arsta = (struct ath11k_sta *)sta->drv_priv; +- if (arsta) { +- atomic_inc(&arsta->drv_tx_pkts.pkts_in); +- if (!ret) +- atomic_inc(&arsta->drv_tx_pkts.pkts_out); +- } ++ if (ath11k_debugfs_is_extd_tx_stats_enabled(ar) && arsta) { ++ atomic_inc(&arsta->drv_tx_pkts.pkts_in); ++ if (!ret) ++ atomic_inc(&arsta->drv_tx_pkts.pkts_out); + } + } + diff --git a/feeds/ipq95xx/mac80211/patches/qca/676-g-ath12k-Avoid-too-many-dereference-to-find-the-rbm-id.patch b/feeds/ipq95xx/mac80211/patches/qca/718-g-ath12k-Avoid-too-many-dereference-to-find-the-rbm-id.patch similarity index 69% rename from feeds/ipq95xx/mac80211/patches/qca/676-g-ath12k-Avoid-too-many-dereference-to-find-the-rbm-id.patch rename to feeds/ipq95xx/mac80211/patches/qca/718-g-ath12k-Avoid-too-many-dereference-to-find-the-rbm-id.patch index a48ca682e..6ecd81350 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/676-g-ath12k-Avoid-too-many-dereference-to-find-the-rbm-id.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/718-g-ath12k-Avoid-too-many-dereference-to-find-the-rbm-id.patch @@ -1,23 +1,25 @@ -From 0e623311ad867bc1a6af443609fb96d0a2380bb7 Mon Sep 17 00:00:00 2001 -From: Balamurugan Mahalingam -Date: Mon, 17 Oct 2022 11:31:52 -0700 -Subject: [PATCH 7/7] ath12k: Avoid too many dereference to find the rbm id +From 467ca38fabebd77e263b0fb63b7f01a1231688ff Mon Sep 17 00:00:00 2001 +From: Ramanathan Choodamani +Date: Fri, 17 Feb 2023 03:17:00 -0800 +Subject: [PATCH 7/7] ath12k: Avoid too many dereference to find the + rbm id Use a local structure to do the lookup and find the rbm id. Avoid too many dereference as it increases the instructions and brings down the throughput by 400Mbps Signed-off-by: Balamurugan Mahalingam +Signed-off-by: Ramanathan Choodamani --- drivers/net/wireless/ath/ath12k/dp_tx.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c -index d71559a..4b14059 100644 +index 90f90c1..97f4c85 100644 --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -127,6 +127,26 @@ static void ath12k_hal_tx_cmd_ext_desc_setup(struct ath12k_base *ab, void *cmd, - ti->encrypt_type); +@@ -134,6 +134,26 @@ static void ath12k_hal_tx_cmd_ext_desc_setup(struct ath12k_base *ab, void *cmd, + HAL_TX_MSDU_EXT_INFO1_ENCRYPT_TYPE); } +static const struct ath12k_hal_tcl_to_wbm_rbm_map @@ -40,10 +42,10 @@ index d71559a..4b14059 100644 + } +}; + - int ath12k_dp_tx_direct(struct ath12k_vif *arvif, struct sk_buff *skb) + int ath12k_dp_tx_direct(struct ath12k_link_vif *arvif, struct sk_buff *skb) { struct ath12k *ar = arvif->ar; -@@ -143,7 +163,7 @@ int ath12k_dp_tx_direct(struct ath12k_vif *arvif, struct sk_buff *skb) +@@ -150,7 +170,7 @@ int ath12k_dp_tx_direct(struct ath12k_link_vif *arvif, struct sk_buff *skb) ring_id = smp_processor_id(); @@ -53,5 +55,5 @@ index d71559a..4b14059 100644 tx_ring = &dp->tx_ring[ring_id]; -- -2.17.1 +2.7.4 diff --git a/feeds/ipq95xx/mac80211/patches/qca/694-a-ath12k-Use-precomputed-SW-TCL-descriptor.patch b/feeds/ipq95xx/mac80211/patches/qca/719-a-ath12k-Use-precomputed-SW-TCL-descriptor.patch similarity index 63% rename from feeds/ipq95xx/mac80211/patches/qca/694-a-ath12k-Use-precomputed-SW-TCL-descriptor.patch rename to feeds/ipq95xx/mac80211/patches/qca/719-a-ath12k-Use-precomputed-SW-TCL-descriptor.patch index a6b6961d2..67513f93f 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/694-a-ath12k-Use-precomputed-SW-TCL-descriptor.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/719-a-ath12k-Use-precomputed-SW-TCL-descriptor.patch @@ -1,6 +1,6 @@ -From 5e9dbc6d2feaca6468b6b1f88e8a9cfe552f1a7a Mon Sep 17 00:00:00 2001 -From: Balamurugan Mahalingam -Date: Thu, 10 Nov 2022 06:02:13 -0800 +From d20bb0d5efdd9004c1fe1501990cf9df7444ce48 Mon Sep 17 00:00:00 2001 +From: Ramanathan Choodamani +Date: Sat, 4 Mar 2023 20:55:46 -0800 Subject: [PATCH 1/4] ath12k: Use precomputed SW TCL descriptor Precompute and store all tx desc values that won't change @@ -10,13 +10,20 @@ helps save CPU cycles on the mesh transmit enqueue path and improve throughput. Signed-off-by: Balamurugan Mahalingam +Signed-off-by: Ramanathan Choodamani +--- + drivers/net/wireless/ath/ath12k/core.h | 9 ++++++ + drivers/net/wireless/ath/ath12k/dp.c | 15 +++++++++ + drivers/net/wireless/ath/ath12k/dp_tx.c | 55 +++++++++++++++++--------------- + drivers/net/wireless/ath/ath12k/hal_tx.c | 37 --------------------- + drivers/net/wireless/ath/ath12k/hal_tx.h | 2 -- + drivers/net/wireless/ath/ath12k/peer.c | 2 ++ + 6 files changed, 55 insertions(+), 65 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h -index 6104300..e02a7ee 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h -@@ -302,7 +302,16 @@ struct ath12k_vif_cache { - u32 bss_conf_changed; +@@ -317,7 +317,16 @@ struct ath12k_vif_cache { + u64 bss_conf_changed; }; +struct ath12k_vif_tcl_desc_template { @@ -27,16 +34,14 @@ index 6104300..e02a7ee 100644 + u32 info4; +}; + - struct ath12k_vif { + struct ath12k_link_vif { + struct ath12k_vif_tcl_desc_template desc; u32 vdev_id; - enum wmi_vdev_type vdev_type; - enum wmi_vdev_subtype vdev_subtype; -diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c -index 8b8365e..075efaf 100644 + u32 beacon_interval; + u32 dtim_period; --- a/drivers/net/wireless/ath/ath12k/dp.c +++ b/drivers/net/wireless/ath/ath12k/dp.c -@@ -449,6 +449,8 @@ void ath12k_dp_tx_update_bank_profile(struct ath12k_vif *arvif) +@@ -459,6 +459,8 @@ void ath12k_dp_tx_update_bank_profile(st ath12k_dp_tx_put_bank_profile(dp, arvif->bank_id); arvif->bank_id = ath12k_dp_tx_get_bank_profile(ab, arvif, dp); @@ -45,7 +50,7 @@ index 8b8365e..075efaf 100644 } static void ath12k_dp_deinit_bank_profiles(struct ath12k_base *ab) -@@ -1157,6 +1159,19 @@ void ath12k_dp_vdev_tx_attach(struct ath12k *ar, struct ath12k_vif *arvif) +@@ -1173,6 +1175,19 @@ void ath12k_dp_vdev_tx_attach(struct ath arvif->vdev_id_check_en = true; arvif->bank_id = ath12k_dp_tx_get_bank_profile(ab, arvif, &ab->dp); @@ -65,11 +70,9 @@ index 8b8365e..075efaf 100644 /* TODO: error path for bank id failure */ if (arvif->bank_id == DP_INVALID_BANK_ID) { ath12k_err(ar->ab, "Failed to initialize DP TX Banks"); -diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c -index d7ceaf3..39a24f2 100644 --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -208,19 +208,15 @@ int ath12k_dp_tx_direct(struct ath12k_vif *arvif, struct sk_buff *skb) +@@ -252,19 +252,15 @@ int ath12k_dp_tx_direct(struct ath12k_li tcl_desc.buf_addr_info.info1 |= FIELD_PREP(BUFFER_ADDR_INFO1_RET_BUF_MGR, rbm_id) | FIELD_PREP(BUFFER_ADDR_INFO1_SW_COOKIE, tx_desc->desc_id); @@ -95,40 +98,54 @@ index d7ceaf3..39a24f2 100644 memcpy(hal_tcl_desc, &tcl_desc, sizeof(tcl_desc)); dsb(st); ath12k_hal_srng_access_umac_src_ring_end_nolock(ab->mem, tcl_ring); -@@ -255,6 +251,7 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif, +@@ -302,6 +298,7 @@ int ath12k_dp_tx(struct ath12k *ar, stru struct ieee80211_hdr *hdr = (void *)skb->data; struct dp_tx_ring *tx_ring; void *hal_tcl_desc; + struct hal_tcl_data_cmd *tcl_cmd; u8 hal_ring_id; int ret; - bool msdu_ext_desc = false; -@@ -293,20 +290,10 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif, + u16 peer_id; +@@ -359,30 +356,20 @@ int ath12k_dp_tx(struct ath12k *ar, stru + ti.meta_data_flags = u32_encode_bits(HTT_TCL_META_DATA_TYPE_GLOBAL_SEQ_NUM, + HTT_TCL_META_DATA_TYPE_MISSION) | + u32_encode_bits(mcbc_gsn, HTT_TCL_META_DATA_GLOBAL_SEQ_NUM); ++ ti.vdev_id = arvif->vdev_id + ++ HTT_TX_MLO_MCAST_HOST_REINJECT_BASE_VDEV_ID; ++ } else { ++ ti.vdev_id = arvif->vdev_id; + } + + ti.encap_type = ath12k_dp_tx_get_encap_type(arvif, skb); ti.addr_search_flags = arvif->hal_addr_search_flags; ti.search_type = arvif->search_type; ti.type = HAL_TCL_DESC_TYPE_BUFFER; - ti.pkt_offset = 0; - ti.lmac_id = ar->lmac_id; -- ti.vdev_id = arvif->vdev_id; +- if (gsn_valid) +- ti.vdev_id = arvif->vdev_id + +- HTT_TX_MLO_MCAST_HOST_REINJECT_BASE_VDEV_ID; +- else +- ti.vdev_id = arvif->vdev_id; - ti.bss_ast_hash = arvif->ast_hash; - ti.bss_ast_idx = arvif->ast_idx; - ti.dscp_tid_tbl_idx = 0; if (likely(skb->ip_summed == CHECKSUM_PARTIAL && - ti.encap_type != HAL_TCL_ENCAP_TYPE_RAW)) { -- ti.flags0 |= FIELD_PREP(HAL_TCL_DATA_CMD_INFO2_IP4_CKSUM_EN, 1) | -- FIELD_PREP(HAL_TCL_DATA_CMD_INFO2_UDP4_CKSUM_EN, 1) | -- FIELD_PREP(HAL_TCL_DATA_CMD_INFO2_UDP6_CKSUM_EN, 1) | -- FIELD_PREP(HAL_TCL_DATA_CMD_INFO2_TCP4_CKSUM_EN, 1) | -- FIELD_PREP(HAL_TCL_DATA_CMD_INFO2_TCP6_CKSUM_EN, 1); + ti.encap_type != HAL_TCL_ENCAP_TYPE_RAW)) { +- ti.flags0 |= u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_IP4_CKSUM_EN) | +- u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_UDP4_CKSUM_EN) | +- u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_UDP6_CKSUM_EN) | +- u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_TCP4_CKSUM_EN) | +- u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_TCP6_CKSUM_EN); + ti.flags0 |= TX_IP_CHECKSUM; } switch (ti.encap_type) { -@@ -414,7 +401,27 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif, - goto fail_unmap_dma_ext_desc; - } - +@@ -529,7 +516,31 @@ int ath12k_dp_tx(struct ath12k *ar, stru + arvif->link_stats.tx_encap_type[ti.encap_type]++; + arvif->link_stats.tx_encrypt_type[ti.encrypt_type]++; + arvif->link_stats.tx_desc_type[ti.type]++; - ath12k_hal_tx_cmd_desc_setup(ab, hal_tcl_desc, &ti); + tcl_cmd = (struct hal_tcl_data_cmd *)hal_tcl_desc; + @@ -148,17 +165,19 @@ index d7ceaf3..39a24f2 100644 + ti.meta_data_flags); + tcl_cmd->info2 = ti.flags0 | + FIELD_PREP(HAL_TCL_DATA_CMD_INFO2_DATA_LEN, ti.data_len); -+ tcl_cmd->info3 = arvif->desc.info3; ++ ++ /* In tcl_cmd->info3, Bit 24 to 31 represents vdev_id ++ * LSH 24 times to add updated vdev_id to info3 ++ */ ++ tcl_cmd->info3 = (ti.vdev_id << 24) | arvif->desc.info3; + tcl_cmd->info4 = arvif->desc.info4; + tcl_cmd->info5 = 0; ath12k_hal_srng_access_end(ab, tcl_ring); -diff --git a/drivers/net/wireless/ath/ath12k/hal_tx.c b/drivers/net/wireless/ath/ath12k/hal_tx.c -index 81c087d..5b8dab3 100644 --- a/drivers/net/wireless/ath/ath12k/hal_tx.c +++ b/drivers/net/wireless/ath/ath12k/hal_tx.c -@@ -34,44 +34,6 @@ static const u8 dscp_tid_map[DSCP_TID_MAP_TBL_ENTRY_SIZE] = { +@@ -34,43 +34,6 @@ static const u8 dscp_tid_map[DSCP_TID_MA 7, 7, 7, 7, 7, 7, 7, 7, }; @@ -168,46 +187,43 @@ index 81c087d..5b8dab3 100644 - struct hal_tcl_data_cmd *tcl_cmd = (struct hal_tcl_data_cmd *)cmd; - - tcl_cmd->buf_addr_info.info0 = -- FIELD_PREP(BUFFER_ADDR_INFO0_ADDR, ti->paddr); +- u32_encode_bits(ti->paddr, BUFFER_ADDR_INFO0_ADDR); - tcl_cmd->buf_addr_info.info1 = -- FIELD_PREP(BUFFER_ADDR_INFO1_ADDR, -- ((uint64_t)ti->paddr >> HAL_ADDR_MSB_REG_SHIFT)); +- u32_encode_bits(((uint64_t)ti->paddr >> HAL_ADDR_MSB_REG_SHIFT), +- BUFFER_ADDR_INFO1_ADDR); - tcl_cmd->buf_addr_info.info1 |= -- FIELD_PREP(BUFFER_ADDR_INFO1_RET_BUF_MGR, -- (ti->rbm_id)) | -- FIELD_PREP(BUFFER_ADDR_INFO1_SW_COOKIE, ti->desc_id); +- u32_encode_bits((ti->rbm_id), BUFFER_ADDR_INFO1_RET_BUF_MGR) | +- u32_encode_bits(ti->desc_id, BUFFER_ADDR_INFO1_SW_COOKIE); - - tcl_cmd->info0 = -- FIELD_PREP(HAL_TCL_DATA_CMD_INFO0_DESC_TYPE, ti->type) | -- FIELD_PREP(HAL_TCL_DATA_CMD_INFO0_BANK_ID, ti->bank_id); +- u32_encode_bits(ti->type, HAL_TCL_DATA_CMD_INFO0_DESC_TYPE) | +- u32_encode_bits(ti->bank_id, HAL_TCL_DATA_CMD_INFO0_BANK_ID); - - tcl_cmd->info1 = -- FIELD_PREP(HAL_TCL_DATA_CMD_INFO1_CMD_NUM, -- ti->meta_data_flags); +- u32_encode_bits(ti->meta_data_flags, +- HAL_TCL_DATA_CMD_INFO1_CMD_NUM); - - tcl_cmd->info2 = ti->flags0 | -- FIELD_PREP(HAL_TCL_DATA_CMD_INFO2_DATA_LEN, ti->data_len) | -- FIELD_PREP(HAL_TCL_DATA_CMD_INFO2_PKT_OFFSET, ti->pkt_offset); +- u32_encode_bits(ti->data_len, HAL_TCL_DATA_CMD_INFO2_DATA_LEN) | +- u32_encode_bits(ti->pkt_offset, HAL_TCL_DATA_CMD_INFO2_PKT_OFFSET); - - tcl_cmd->info3 = ti->flags1 | -- FIELD_PREP(HAL_TCL_DATA_CMD_INFO3_PMAC_ID, ti->lmac_id) | -- FIELD_PREP(HAL_TCL_DATA_CMD_INFO3_VDEV_ID, ti->vdev_id); +- u32_encode_bits(ti->lmac_id, HAL_TCL_DATA_CMD_INFO3_PMAC_ID) | +- u32_encode_bits(ti->vdev_id, HAL_TCL_DATA_CMD_INFO3_VDEV_ID); - -- tcl_cmd->info4 = FIELD_PREP(HAL_TCL_DATA_CMD_INFO4_SEARCH_INDEX, -- ti->bss_ast_idx) | -- FIELD_PREP(HAL_TCL_DATA_CMD_INFO4_CACHE_SET_NUM, -- ti->bss_ast_hash); +- tcl_cmd->info4 = u32_encode_bits(ti->bss_ast_idx, +- HAL_TCL_DATA_CMD_INFO4_SEARCH_INDEX) | +- u32_encode_bits(ti->bss_ast_hash, +- HAL_TCL_DATA_CMD_INFO4_CACHE_SET_NUM); - tcl_cmd->info5 = 0; -} - void ath12k_hal_tx_set_dscp_tid_map(struct ath12k_base *ab, int id) { u32 ctrl_reg_val; -diff --git a/drivers/net/wireless/ath/ath12k/hal_tx.h b/drivers/net/wireless/ath/ath12k/hal_tx.h -index f7be6f2..eca577b 100644 --- a/drivers/net/wireless/ath/ath12k/hal_tx.h +++ b/drivers/net/wireless/ath/ath12k/hal_tx.h -@@ -80,8 +80,6 @@ struct hal_tx_status { +@@ -182,8 +182,6 @@ struct hal_tx_fes_status_end { /* STA mode will have MCAST_PKT_CTRL instead of DSCP_TID_MAP bitfield */ #define HAL_TX_BANK_CONFIG_DSCP_TIP_MAP_ID GENMASK(22, 17) @@ -216,12 +232,10 @@ index f7be6f2..eca577b 100644 void ath12k_hal_tx_set_dscp_tid_map(struct ath12k_base *ab, int id); int ath12k_hal_reo_cmd_send(struct ath12k_base *ab, struct hal_srng *srng, enum hal_reo_cmd_type type, -diff --git a/drivers/net/wireless/ath/ath12k/peer.c b/drivers/net/wireless/ath/ath12k/peer.c -index 19e7da4..a68b8e1 100644 --- a/drivers/net/wireless/ath/ath12k/peer.c +++ b/drivers/net/wireless/ath/ath12k/peer.c -@@ -333,6 +333,8 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_vif *arvif, - if (arvif->vif->type == NL80211_IFTYPE_STATION) { +@@ -493,6 +493,8 @@ int ath12k_peer_create(struct ath12k *ar + if (vif->type == NL80211_IFTYPE_STATION) { arvif->ast_hash = peer->ast_hash; arvif->ast_idx = peer->hw_peer_id; + arvif->desc.info4 = FIELD_PREP(HAL_TCL_DATA_CMD_INFO4_SEARCH_INDEX, arvif->ast_idx) | @@ -229,6 +243,3 @@ index 19e7da4..a68b8e1 100644 } peer->sec_type = HAL_ENCRYPT_TYPE_OPEN; --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/719-ath12k-failed-received-pkts.patch b/feeds/ipq95xx/mac80211/patches/qca/719-ath12k-failed-received-pkts.patch new file mode 100644 index 000000000..09fde4ebc --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/719-ath12k-failed-received-pkts.patch @@ -0,0 +1,99 @@ +From 96f1f818ba1d2650797a5764530f7b8112284af6 Mon Sep 17 00:00:00 2001 +From: saleemuddin shaik +Date: Sat, 4 Mar 2023 14:05:28 +0530 +Subject: ath12k: add statistic support for counting wmm failed received + packets. + +if the desc bit is not set and num_msdu is greater then one, +then increment the drop packets are counted based on WMM categories. + +Signed-off-by: saleemuddin shaik +--- + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/debugfs.c | 12 ++++++++++++ + drivers/net/wireless/ath/ath12k/dp_rx.c | 1 + + 3 files changed, 14 insertions(+) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -785,6 +785,7 @@ struct ath12k_wmm_stats { + u64 total_wmm_tx_pkts[WME_NUM_AC]; + u64 total_wmm_rx_pkts[WME_NUM_AC]; + u64 total_wmm_tx_drop[WME_NUM_AC]; ++ u64 total_wmm_rx_drop[WME_NUM_AC]; + }; + + #define ATH12K_DSCP_PRIORITY 7 +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -1356,6 +1356,7 @@ static ssize_t ath12k_read_wmm_stats(str + u64 total_wmm_sent_pkts = 0; + u64 total_wmm_received_pkts = 0; + u64 total_wmm_fail_sent = 0; ++ u64 total_wmm_fail_received = 0; + + buf = kzalloc(size, GFP_KERNEL); + if (!buf) { +@@ -1368,6 +1369,7 @@ static ssize_t ath12k_read_wmm_stats(str + total_wmm_sent_pkts += ar->wmm_stats.total_wmm_tx_pkts[count]; + total_wmm_received_pkts += ar->wmm_stats.total_wmm_rx_pkts[count]; + total_wmm_fail_sent += ar->wmm_stats.total_wmm_tx_drop[count]; ++ total_wmm_fail_received += ar->wmm_stats.total_wmm_rx_drop[count]; + } + + len += scnprintf(buf + len, size - len, "Total number of wmm_sent: %llu\n", +@@ -1376,6 +1378,8 @@ static ssize_t ath12k_read_wmm_stats(str + total_wmm_received_pkts); + len += scnprintf(buf + len, size - len, "total number of wmm_fail_sent: %llu\n", + total_wmm_fail_sent); ++ len += scnprintf(buf + len, size - len, "total number of wmm_fail_received: %llu\n", ++ total_wmm_fail_received); + len += scnprintf(buf + len, size - len, "Num of BE wmm_sent: %llu\n", + ar->wmm_stats.total_wmm_tx_pkts[WME_AC_BE]); + len += scnprintf(buf + len, size - len, "Num of BK wmm_sent: %llu\n", +@@ -1400,6 +1404,14 @@ static ssize_t ath12k_read_wmm_stats(str + ar->wmm_stats.total_wmm_tx_drop[WME_AC_VI]); + len += scnprintf(buf + len, size - len, "num of vo wmm_tx_dropped: %llu\n", + ar->wmm_stats.total_wmm_tx_drop[WME_AC_VO]); ++ len += scnprintf(buf + len, size - len, "num of be wmm_rx_dropped: %llu\n", ++ ar->wmm_stats.total_wmm_rx_drop[WME_AC_BE]); ++ len += scnprintf(buf + len, size - len, "num of bk wmm_rx_dropped: %llu\n", ++ ar->wmm_stats.total_wmm_rx_drop[WME_AC_BK]); ++ len += scnprintf(buf + len, size - len, "num of vi wmm_rx_dropped: %llu\n", ++ ar->wmm_stats.total_wmm_rx_drop[WME_AC_VI]); ++ len += scnprintf(buf + len, size - len, "num of vo wmm_rx_dropped: %llu\n", ++ ar->wmm_stats.total_wmm_rx_drop[WME_AC_VO]); + + mutex_unlock(&ar->conf_mutex); + +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -4121,8 +4121,7 @@ int ath12k_dp_rx_process_err(struct ath1 + struct ath12k *ar; + dma_addr_t paddr; + u32 *desc; +- bool is_frag; +- u8 drop = 0; ++ bool is_frag, drop = false; + + tot_n_bufs_reaped = 0; + quota = budget; +@@ -4169,7 +4168,7 @@ int ath12k_dp_rx_process_err(struct ath1 + * msdu's indicated due to error reasons. + */ + if (!is_frag || num_msdus > 1) { +- drop = 1; ++ drop = true; + /* Return the link desc back to wbm idle list */ + ath12k_dp_rx_link_desc_return(ab, desc, + HAL_WBM_REL_BM_ACT_PUT_IN_IDLE); +@@ -4186,6 +4185,9 @@ int ath12k_dp_rx_process_err(struct ath1 + + ar = ab->pdevs[mac_id].ar; + ++ if (drop) ++ ar->wmm_stats.total_wmm_rx_drop[ar->wmm_stats.rx_type]++; ++ + if (!ath12k_dp_process_rx_err_buf(ar, desc, drop, + msdu_cookies[i])) + tot_n_bufs_reaped++; diff --git a/feeds/ipq95xx/mac80211/patches/qca/694-b-ath12k-Remove-locks-while-accessing-descriptors.patch b/feeds/ipq95xx/mac80211/patches/qca/719-b-ath12k-Remove-locks-while-accessing-descriptors.patch similarity index 67% rename from feeds/ipq95xx/mac80211/patches/qca/694-b-ath12k-Remove-locks-while-accessing-descriptors.patch rename to feeds/ipq95xx/mac80211/patches/qca/719-b-ath12k-Remove-locks-while-accessing-descriptors.patch index fb1f12b65..17355ef64 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/694-b-ath12k-Remove-locks-while-accessing-descriptors.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/719-b-ath12k-Remove-locks-while-accessing-descriptors.patch @@ -1,6 +1,6 @@ -From 912b4850b080c013dd8df6439b6a3d1a4446065a Mon Sep 17 00:00:00 2001 -From: Balamurugan Mahalingam -Date: Fri, 18 Nov 2022 04:38:02 -0800 +From c85cdbb7cb0a534cb1dfcba626fdc89591150153 Mon Sep 17 00:00:00 2001 +From: Ramanathan Choodamani +Date: Fri, 17 Feb 2023 04:38:22 -0800 Subject: [PATCH 2/4] ath12k: Remove locks while accessing descriptors Each core has its own tx sw descriptors pools. No locks are needed to @@ -9,10 +9,16 @@ access sw descriptor pools Optimize ring selection operation Signed-off-by: Balamurugan Mahalingam +Signed-off-by: Ramanathan Choodamani +--- + drivers/net/wireless/ath/ath12k/dp_tx.c | 37 +++++---------------------------- + 1 file changed, 5 insertions(+), 32 deletions(-) +diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c +index 1a167ff..b3acce9 100644 --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -90,26 +90,6 @@ struct ath12k_tx_desc_info *ath12k_dp_tx +@@ -94,26 +94,6 @@ struct ath12k_tx_desc_info *ath12k_dp_tx_assign_buffer_nolock(struct ath12k_dp * return desc; } @@ -39,14 +45,15 @@ Signed-off-by: Balamurugan Mahalingam static void ath12k_hal_tx_cmd_ext_desc_setup(struct ath12k_base *ab, void *cmd, struct hal_tx_info *ti) -@@ -265,13 +245,13 @@ int ath12k_dp_tx(struct ath12k *ar, stru - !ieee80211_is_data(hdr->frame_control))) +@@ -274,14 +254,13 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif, return -ENOTSUPP; -- ti.ring_id = smp_processor_id() % DP_TCL_NUM_RING_MAX; -+ ti.ring_id = smp_processor_id(); + ti.ring_id = +- ab->hw_params->hw_ops->get_ring_selector(skb) % +- ab->hw_params->max_tx_ring; ++ ab->hw_params->hw_ops->get_ring_selector(skb); - ti.rbm_id = ab->hal.ops->tcl_to_wbm_rbm_map[ti.ring_id].rbm_id; + ti.rbm_id = ab->hw_params->hal_ops->tcl_to_wbm_rbm_map[ti.ring_id].rbm_id; tx_ring = &dp->tx_ring[ti.ring_id]; @@ -55,7 +62,7 @@ Signed-off-by: Balamurugan Mahalingam if (unlikely(!tx_desc)) { ab->soc_stats.tx_err.txbuf_na[ti.ring_id]++; return -ENOSPC; -@@ -398,18 +378,14 @@ int ath12k_dp_tx(struct ath12k *ar, stru +@@ -419,18 +398,14 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif, hal_ring_id = tx_ring->tcl_data_ring.ring_id; tcl_ring = &ab->hal.srng_list[hal_ring_id]; @@ -64,7 +71,7 @@ Signed-off-by: Balamurugan Mahalingam - ath12k_hal_srng_access_begin(ab, tcl_ring); - + ath12k_hal_srng_access_src_ring_begin_nolock(ab, tcl_ring); - hal_tcl_desc = (void *)ath12k_hal_srng_src_get_next_entry(ab, tcl_ring); + hal_tcl_desc = ath12k_hal_srng_src_get_next_entry(ab, tcl_ring); if (unlikely(!hal_tcl_desc)) { /* NOTE: It is highly unlikely we'll be running out of tcl_ring * desc because the desc is directly enqueued onto hw queue. @@ -76,7 +83,7 @@ Signed-off-by: Balamurugan Mahalingam ret = -ENOMEM; goto fail_unmap_dma_ext_desc; -@@ -437,9 +413,7 @@ int ath12k_dp_tx(struct ath12k *ar, stru +@@ -458,9 +433,7 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif, tcl_cmd->info4 = arvif->desc.info4; tcl_cmd->info5 = 0; @@ -87,3 +94,6 @@ Signed-off-by: Balamurugan Mahalingam ath12k_dbg_dump(ab, ATH12K_DBG_DP_TX, NULL, "dp tx msdu: ", skb->data, skb->len); +-- +2.7.4 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/694-c-ath12k-Program-the-RBM-ID-values-in-TCL-RBM-map-regi.patch b/feeds/ipq95xx/mac80211/patches/qca/719-c-ath12k-Program-the-RBM-ID-values-in-TCL-RBM-map-regi.patch similarity index 60% rename from feeds/ipq95xx/mac80211/patches/qca/694-c-ath12k-Program-the-RBM-ID-values-in-TCL-RBM-map-regi.patch rename to feeds/ipq95xx/mac80211/patches/qca/719-c-ath12k-Program-the-RBM-ID-values-in-TCL-RBM-map-regi.patch index b0778e84d..5538c5580 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/694-c-ath12k-Program-the-RBM-ID-values-in-TCL-RBM-map-regi.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/719-c-ath12k-Program-the-RBM-ID-values-in-TCL-RBM-map-regi.patch @@ -1,16 +1,27 @@ -From d95a8e1f4d42374508a326636a329e009d8bea6a Mon Sep 17 00:00:00 2001 -From: Balamurugan Mahalingam -Date: Fri, 18 Nov 2022 05:20:19 -0800 -Subject: [PATCH 3/4] ath12k: Program the RBM ID values in TCL RBM map register +From 2238894a12b2cbb4693eced8fd046415967c2a82 Mon Sep 17 00:00:00 2001 +From: Ramanathan Choodamani +Date: Fri, 17 Feb 2023 04:44:56 -0800 +Subject: [PATCH 3/4] ath12k: Program the RBM ID values in TCL RBM map + register Program the RBM ID values during TCL init and avoid providing the rbm id values on a per packet basis Signed-off-by: Balamurugan Mahalingam +Signed-off-by: Ramanathan Choodamani +--- + drivers/net/wireless/ath/ath12k/dp.c | 3 +++ + drivers/net/wireless/ath/ath12k/dp_tx.c | 28 +--------------------------- + drivers/net/wireless/ath/ath12k/hal.h | 6 ++++++ + drivers/net/wireless/ath/ath12k/hal_tx.c | 23 +++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/hal_tx.h | 2 ++ + 5 files changed, 35 insertions(+), 27 deletions(-) +diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c +index e9121fa..af7da38 100644 --- a/drivers/net/wireless/ath/ath12k/dp.c +++ b/drivers/net/wireless/ath/ath12k/dp.c -@@ -508,6 +508,7 @@ static int ath12k_dp_srng_common_setup(s +@@ -519,6 +519,7 @@ static int ath12k_dp_srng_common_setup(struct ath12k_base *ab) struct hal_srng *srng; int i, ret, tx_comp_ring_num; u32 ring_hash_map; @@ -18,26 +29,28 @@ Signed-off-by: Balamurugan Mahalingam ret = ath12k_dp_srng_setup(ab, &dp->wbm_desc_rel_ring, HAL_SW2WBM_RELEASE, 0, 0, -@@ -534,6 +535,7 @@ static int ath12k_dp_srng_common_setup(s - - for (i = 0; i < DP_TCL_NUM_RING_MAX; i++) { - tx_comp_ring_num = ab->hal.ops->tcl_to_wbm_rbm_map[i].wbm_ring_num; -+ rbm_id = ab->hal.ops->tcl_to_wbm_rbm_map[i].rbm_id; +@@ -546,6 +547,7 @@ static int ath12k_dp_srng_common_setup(struct ath12k_base *ab) + for (i = 0; i < ab->hw_params->max_tx_ring; i++) { + map = ab->hw_params->hal_ops->tcl_to_wbm_rbm_map; + tx_comp_ring_num = map[i].wbm_ring_num; ++ rbm_id = ab->hw_params->hal_ops->tcl_to_wbm_rbm_map[i].rbm_id; ret = ath12k_dp_srng_setup(ab, &dp->tx_ring[i].tcl_data_ring, HAL_TCL_DATA, i, 0, -@@ -552,6 +554,7 @@ static int ath12k_dp_srng_common_setup(s - tx_comp_ring_num, ret); +@@ -555,6 +557,7 @@ static int ath12k_dp_srng_common_setup(struct ath12k_base *ab) + i, ret); goto err; } + ath12k_hal_tx_config_rbm_mapping(ab, i, rbm_id, HAL_TCL_DATA); - srng = &ab->hal.srng_list[dp->tx_ring[i].tcl_data_ring.ring_id]; - } + ret = ath12k_dp_srng_setup(ab, &dp->tx_ring[i].tcl_comp_ring, + HAL_WBM2SW_RELEASE, tx_comp_ring_num, 0, +diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c +index b3acce9..d791921 100644 --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -107,25 +107,6 @@ static void ath12k_hal_tx_cmd_ext_desc_s - ti->encrypt_type); +@@ -114,25 +114,6 @@ static void ath12k_hal_tx_cmd_ext_desc_setup(struct ath12k_base *ab, void *cmd, + HAL_TX_MSDU_EXT_INFO1_ENCRYPT_TYPE); } -static const struct ath12k_hal_tcl_to_wbm_rbm_map @@ -60,9 +73,9 @@ Signed-off-by: Balamurugan Mahalingam - } -}; - int ath12k_dp_tx_direct(struct ath12k_vif *arvif, struct sk_buff *skb) + int ath12k_dp_tx_direct(struct ath12k_link_vif *arvif, struct sk_buff *skb) { -@@ -138,13 +119,11 @@ int ath12k_dp_tx_direct(struct ath12k_vi +@@ -145,13 +126,11 @@ int ath12k_dp_tx_direct(struct ath12k_link_vif *arvif, struct sk_buff *skb) struct dp_tx_ring *tx_ring; void *hal_tcl_desc; struct hal_tcl_data_cmd tcl_desc = { 0 }; @@ -77,7 +90,7 @@ Signed-off-by: Balamurugan Mahalingam tx_ring = &dp->tx_ring[ring_id]; tx_desc = ath12k_dp_tx_assign_buffer_nolock(dp, ring_id); -@@ -186,7 +165,6 @@ int ath12k_dp_tx_direct(struct ath12k_vi +@@ -193,7 +172,6 @@ int ath12k_dp_tx_direct(struct ath12k_link_vif *arvif, struct sk_buff *skb) tcl_desc.buf_addr_info.info1 = FIELD_PREP(BUFFER_ADDR_INFO1_ADDR, ((uint64_t)skb_cb->paddr >> HAL_ADDR_MSB_REG_SHIFT)); tcl_desc.buf_addr_info.info1 |= @@ -85,16 +98,16 @@ Signed-off-by: Balamurugan Mahalingam FIELD_PREP(BUFFER_ADDR_INFO1_SW_COOKIE, tx_desc->desc_id); tcl_desc.info0 = FIELD_PREP(HAL_TCL_DATA_CMD_INFO0_DESC_TYPE, HAL_TCL_DESC_TYPE_BUFFER) | arvif->desc.info0; -@@ -247,8 +225,6 @@ int ath12k_dp_tx(struct ath12k *ar, stru +@@ -256,8 +234,6 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif, + ti.ring_id = + ab->hw_params->hw_ops->get_ring_selector(skb); - ti.ring_id = smp_processor_id(); - -- ti.rbm_id = ab->hal.ops->tcl_to_wbm_rbm_map[ti.ring_id].rbm_id; +- ti.rbm_id = ab->hw_params->hal_ops->tcl_to_wbm_rbm_map[ti.ring_id].rbm_id; - tx_ring = &dp->tx_ring[ti.ring_id]; tx_desc = ath12k_dp_tx_assign_buffer_nolock(dp, ti.ring_id); -@@ -400,8 +376,6 @@ int ath12k_dp_tx(struct ath12k *ar, stru +@@ -419,8 +395,6 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif, FIELD_PREP(BUFFER_ADDR_INFO1_ADDR, ((uint64_t)ti.paddr >> HAL_ADDR_MSB_REG_SHIFT)); tcl_cmd->buf_addr_info.info1 |= @@ -103,9 +116,11 @@ Signed-off-by: Balamurugan Mahalingam FIELD_PREP(BUFFER_ADDR_INFO1_SW_COOKIE, ti.desc_id); tcl_cmd->info0 = FIELD_PREP(HAL_TCL_DATA_CMD_INFO0_DESC_TYPE, +diff --git a/drivers/net/wireless/ath/ath12k/hal.h b/drivers/net/wireless/ath/ath12k/hal.h +index 4a685ae..ff772c6 100644 --- a/drivers/net/wireless/ath/ath12k/hal.h +++ b/drivers/net/wireless/ath/ath12k/hal.h -@@ -112,6 +112,12 @@ struct ath12k_base; +@@ -124,6 +124,12 @@ struct ath12k_base; #define HAL_TCL1_RING_TP_OFFSET \ (HAL_TCL1_RING_TP - HAL_TCL1_RING_HP) @@ -117,10 +132,12 @@ Signed-off-by: Balamurugan Mahalingam + /* TCL STATUS ring address */ #define HAL_TCL_STATUS_RING_BASE_LSB(ab) \ - (ab)->hw_params.regs->hal_tcl_status_ring_base_lsb + ((ab)->hw_params->regs->hal_tcl_status_ring_base_lsb) +diff --git a/drivers/net/wireless/ath/ath12k/hal_tx.c b/drivers/net/wireless/ath/ath12k/hal_tx.c +index cd0f872..688b329 100644 --- a/drivers/net/wireless/ath/ath12k/hal_tx.c +++ b/drivers/net/wireless/ath/ath12k/hal_tx.c -@@ -97,3 +97,26 @@ void ath12k_hal_tx_configure_bank_regist +@@ -98,3 +98,26 @@ void ath12k_hal_tx_configure_bank_register(struct ath12k_base *ab, u32 bank_conf ath12k_hif_write32(ab, HAL_TCL_SW_CONFIG_BANK_ADDR + 4 * bank_id, bank_config); } @@ -147,12 +164,17 @@ Signed-off-by: Balamurugan Mahalingam + ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_TCL_REG + + HAL_TCL_RBM_MAPPING0_ADDR_OFFSET, new_map); +} +diff --git a/drivers/net/wireless/ath/ath12k/hal_tx.h b/drivers/net/wireless/ath/ath12k/hal_tx.h +index 61cdd34..54fba8c 100644 --- a/drivers/net/wireless/ath/ath12k/hal_tx.h +++ b/drivers/net/wireless/ath/ath12k/hal_tx.h -@@ -86,4 +86,6 @@ int ath12k_hal_reo_cmd_send(struct ath12 +@@ -188,4 +188,6 @@ int ath12k_hal_reo_cmd_send(struct ath12k_base *ab, struct hal_srng *srng, struct ath12k_hal_reo_cmd *cmd); void ath12k_hal_tx_configure_bank_register(struct ath12k_base *ab, u32 bank_config, u8 bank_id); +void ath12k_hal_tx_config_rbm_mapping(struct ath12k_base *ab,u8 ring_num, + u8 rbm_id, int ring_type); #endif +-- +2.7.4 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/694-d-ath12k-Optimize-tx-descriptor-updates.-Avoid-FIELD_P.patch b/feeds/ipq95xx/mac80211/patches/qca/719-d-ath12k-Optimize-tx-descriptor-updates.-Avoid-FIELD_P.patch similarity index 76% rename from feeds/ipq95xx/mac80211/patches/qca/694-d-ath12k-Optimize-tx-descriptor-updates.-Avoid-FIELD_P.patch rename to feeds/ipq95xx/mac80211/patches/qca/719-d-ath12k-Optimize-tx-descriptor-updates.-Avoid-FIELD_P.patch index 455f03a50..72b78a068 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/694-d-ath12k-Optimize-tx-descriptor-updates.-Avoid-FIELD_P.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/719-d-ath12k-Optimize-tx-descriptor-updates.-Avoid-FIELD_P.patch @@ -1,18 +1,23 @@ -From 010db2eda6957ee678f446b51c6289dd0c81f3b7 Mon Sep 17 00:00:00 2001 -From: Balamurugan Mahalingam -Date: Fri, 18 Nov 2022 07:16:22 -0800 -Subject: [PATCH 4/4] ath12k: Optimize tx descriptor updates. Avoid FIELD_PREP +From 6faebb8869308ec142bed9987e26fda1fdbcabd7 Mon Sep 17 00:00:00 2001 +From: Ramanathan Choodamani +Date: Fri, 17 Feb 2023 04:46:52 -0800 +Subject: [PATCH 4/4] ath12k: Optimize tx descriptor updates. Avoid + FIELD_PREP FIELD_PREP macros does a few sanity checks as part of field updates. Use a simple method to update fields as it helps improve throughput Signed-off-by: Balamurugan Mahalingam +Signed-off-by: Ramanathan Choodamani +--- + drivers/net/wireless/ath/ath12k/dp_tx.c | 32 ++++++++++---------------------- + 1 file changed, 10 insertions(+), 22 deletions(-) --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -161,18 +161,14 @@ int ath12k_dp_tx_direct(struct ath12k_vi - goto fail_unmap_dma; - } +@@ -207,18 +207,15 @@ int ath12k_dp_tx_direct(struct ath12k_li + + ab->soc_stats.tx_enqueued[ring_id]++; - tcl_desc.buf_addr_info.info0 = FIELD_PREP(BUFFER_ADDR_INFO0_ADDR, skb_cb->paddr); - tcl_desc.buf_addr_info.info1 = FIELD_PREP(BUFFER_ADDR_INFO1_ADDR, @@ -25,16 +30,17 @@ Signed-off-by: Balamurugan Mahalingam + tcl_desc.buf_addr_info.info1 = (tx_desc->desc_id << 12); + tcl_desc.info0 = arvif->desc.info0; tcl_desc.info1 = arvif->desc.info1; - + tcl_desc.info2 = skb->len; + if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) tcl_desc.info2 |= TX_IP_CHECKSUM; - tcl_desc.info2 |= FIELD_PREP(HAL_TCL_DATA_CMD_INFO2_DATA_LEN, skb->len); ++ tcl_desc.info3 = arvif->desc.info3; tcl_desc.info4 = arvif->desc.info4; memcpy(hal_tcl_desc, &tcl_desc, sizeof(tcl_desc)); -@@ -369,24 +365,16 @@ int ath12k_dp_tx(struct ath12k *ar, stru - +@@ -471,20 +468,12 @@ int ath12k_dp_tx(struct ath12k *ar, stru + arvif->link_stats.tx_desc_type[ti.type]++; tcl_cmd = (struct hal_tcl_data_cmd *)hal_tcl_desc; - tcl_cmd->buf_addr_info.info0 = @@ -57,11 +63,6 @@ Signed-off-by: Balamurugan Mahalingam + tcl_cmd->info0 = (ti.type << 1) | arvif->desc.info0; + tcl_cmd->info1 = ti.meta_data_flags << 16; + tcl_cmd->info2 = ti.flags0 | ti.data_len; - tcl_cmd->info3 = arvif->desc.info3; - tcl_cmd->info4 = arvif->desc.info4; - tcl_cmd->info5 = 0; -- -+ dsb(st); - ath12k_hal_srng_access_umac_src_ring_end_nolock(ab->mem, tcl_ring); - ath12k_dbg_dump(ab, ATH12K_DBG_DP_TX, NULL, "dp tx msdu: ", + /* In tcl_cmd->info3, Bit 24 to 31 represents vdev_id + * LSH 24 times to add updated vdev_id to info3 diff --git a/feeds/ipq95xx/mac80211/patches/qca/696-a-ath12k-Process-tx-completions-using-the-napi-budget.patch b/feeds/ipq95xx/mac80211/patches/qca/720-a-ath12k-Process-tx-completions-using-the-napi-budget.patch similarity index 56% rename from feeds/ipq95xx/mac80211/patches/qca/696-a-ath12k-Process-tx-completions-using-the-napi-budget.patch rename to feeds/ipq95xx/mac80211/patches/qca/720-a-ath12k-Process-tx-completions-using-the-napi-budget.patch index 90204ffef..da5735bec 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/696-a-ath12k-Process-tx-completions-using-the-napi-budget.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/720-a-ath12k-Process-tx-completions-using-the-napi-budget.patch @@ -1,44 +1,46 @@ -From 67d18d5f7d15ed6bfe5afc0cb6f2e975b8f485c3 Mon Sep 17 00:00:00 2001 -From: Balamurugan Mahalingam -Date: Tue, 22 Nov 2022 00:11:40 -0800 -Subject: [PATCH 1/6] ath12k: Process tx completions using the napi budget +From 3a96baddcdd8f1ac37a75b531c93abd314afad60 Mon Sep 17 00:00:00 2001 +From: Ramanathan Choodamani +Date: Tue, 7 Mar 2023 01:23:49 -0800 +Subject: [PATCH 1/6] ath12k: Process tx completions using the napi budget Limit the number of tx completions processing in a loop and prioritize the transmit enqueue operation -Signed-off-by: Balamurugan Mahalingam +Signed-off-by: Balamurugan Mahalingam +Signed-off-by: Ramanathan Choodamani --- - drivers/net/wireless/ath/ath12k/dp.c | 13 +++++++++---- + drivers/net/wireless/ath/ath12k/dp.c | 16 ++++++++++------ drivers/net/wireless/ath/ath12k/dp_tx.c | 12 ++++++++---- drivers/net/wireless/ath/ath12k/dp_tx.h | 3 ++- - drivers/net/wireless/ath/ath12k/pci.c | 5 +++++ - 4 files changed, 24 insertions(+), 9 deletions(-) + drivers/net/wireless/ath/ath12k/pci.c | 18 ++++++++++++++++-- + 4 files changed, 36 insertions(+), 13 deletions(-) --- a/drivers/net/wireless/ath/ath12k/dp.c +++ b/drivers/net/wireless/ath/ath12k/dp.c -@@ -933,10 +933,15 @@ int ath12k_dp_service_srng(struct ath12k - reo_status_mask | - host2rxdma_mask; +@@ -949,11 +949,17 @@ int ath12k_dp_service_srng(struct ath12k -- if (tx_mask) { -- i = __fls(tx_mask); -- ath12k_dp_tx_completion_handler(ab, (i == 4) ? 3 : i); -- } -+ if (tx_mask) { -+ i = __fls(tx_mask); -+ work_done = ath12k_dp_tx_completion_handler(ab, (i == 4) ? 3 : i, budget); + while (i < ab->hw_params->max_tx_ring) { + if (tx_mask & +- BIT(ab->hw_params->hal_ops->tcl_to_wbm_rbm_map[i].wbm_ring_num)) +- ath12k_dp_tx_completion_handler(ab, i); ++ BIT(ab->hw_params->hal_ops->tcl_to_wbm_rbm_map[i].wbm_ring_num)) { ++ work_done = ath12k_dp_tx_completion_handler(ab, i, ++ budget); ++ budget -= work_done; ++ tot_work_done += work_done; ++ if (budget <= 0) ++ goto done; ++ } + i++; + } +- + -+ budget -= work_done; -+ tot_work_done += work_done; -+ if (budget <= 0) -+ goto done; -+ } - - if (rx_mask) { - i = fls(rx_mask) - 1; + if (rx_err_mask) { + work_done = ath12k_dp_rx_process_err(ab, napi, budget); + budget -= work_done; --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -839,7 +839,8 @@ static inline bool ath12k_dp_tx_completi +@@ -975,7 +975,8 @@ static inline bool ath12k_dp_tx_completi return true; } @@ -48,15 +50,15 @@ Signed-off-by: Balamurugan Mahalingam { struct ath12k *ar; struct ath12k_dp *dp = &ab->dp; -@@ -851,6 +852,7 @@ void ath12k_dp_tx_completion_handler(str - u32 *desc, desc_id; +@@ -988,6 +989,7 @@ void ath12k_dp_tx_completion_handler(str u8 mac_id; + u64 desc_va; int valid_entries; + int workdone = 0; struct hal_wbm_completion_ring_tx tx_status = { 0 }; enum hal_wbm_rel_src_module buf_rel_source; -@@ -860,12 +862,12 @@ void ath12k_dp_tx_completion_handler(str +@@ -997,12 +999,12 @@ void ath12k_dp_tx_completion_handler(str valid_entries = ath12k_hal_srng_dst_num_free(ab, status_ring, false); if (!valid_entries) { ath12k_hal_srng_access_umac_dst_ring_end_nolock(ab->mem, status_ring); @@ -71,8 +73,8 @@ Signed-off-by: Balamurugan Mahalingam if (!ath12k_dp_tx_completion_valid(desc)) continue; -@@ -905,17 +907,19 @@ void ath12k_dp_tx_completion_handler(str - tx_ring, skb_ext_desc); +@@ -1046,7 +1048,7 @@ void ath12k_dp_tx_completion_handler(str + tx_desc); continue; } - @@ -80,33 +82,33 @@ Signed-off-by: Balamurugan Mahalingam ar = ab->pdevs[mac_id].ar; if (atomic_dec_and_test(&ar->dp.num_tx_pending)) - wake_up(&ar->dp.tx_empty_waitq); - - ath12k_dp_tx_complete_msdu(ar, msdu, &tx_status, buf_rel_source, skb_ext_desc); +@@ -1055,9 +1057,11 @@ void ath12k_dp_tx_completion_handler(str + ath12k_dp_tx_complete_msdu(ar, msdu, &tx_status, + buf_rel_source, skb_ext_desc, + tx_ring->tcl_data_ring_id); + budget--; } - ath12k_hal_srng_access_umac_dst_ring_end_nolock(ab->mem, status_ring); + return workdone; } - int ath12k_dp_tx_send_reo_cmd(struct ath12k_base *ab, struct dp_rx_tid *rx_tid, + static int --- a/drivers/net/wireless/ath/ath12k/dp_tx.h +++ b/drivers/net/wireless/ath/ath12k/dp_tx.h -@@ -19,7 +19,8 @@ void ath12k_dp_tx_update_txcompl(struct - int ath12k_dp_tx_htt_h2t_ver_req_msg(struct ath12k_base *ab); - int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif, - struct ath12k_sta *arsta, struct sk_buff *skb); +@@ -218,7 +218,8 @@ int ath12k_dp_tx_htt_h2t_ver_req_msg(str + int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif, + struct ath12k_sta *ahsta, struct sk_buff *skb, + bool gsn_valid, int mcbc_gsn); -void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id); +int ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id, + int tx_comp_budget); - int ath12k_dp_tx_send_reo_cmd(struct ath12k_base *ab, struct dp_rx_tid *rx_tid, - enum hal_reo_cmd_type type, - struct ath12k_hal_reo_cmd *cmd, + + int ath12k_dp_tx_htt_h2t_ppdu_stats_req(struct ath12k *ar, u32 mask); + int --- a/drivers/net/wireless/ath/ath12k/pci.c +++ b/drivers/net/wireless/ath/ath12k/pci.c -@@ -44,6 +44,10 @@ +@@ -45,6 +45,10 @@ #define ATH12K_MAX_PCI_DOMAINS 0x5 #define DP_IRQ_NAME_LEN 20 @@ -117,13 +119,13 @@ Signed-off-by: Balamurugan Mahalingam char dp_irq_name[ATH12K_MAX_PCI_DOMAINS + 1][ATH12K_EXT_IRQ_GRP_NUM_MAX][DP_IRQ_NAME_LEN] = {}; unsigned int ath12k_fw_mem_seg; -@@ -591,6 +595,11 @@ static int ath12k_pci_ext_irq_config(str +@@ -524,6 +528,11 @@ static int ath12k_pci_ext_irq_config(str else budget = ath12k_napi_poll_budget; + /* Apply a reduced budget for tx completion to prioritize tx + * enqueue operation */ -+ if (ab->hw_params.ring_mask->tx[i]) ++ if (ab->hw_params->ring_mask->tx[i]) + budget = ATH12K_TX_COMP_NAPI_BUDGET; + netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi, diff --git a/feeds/ipq95xx/mac80211/patches/qca/720-ath12k-add-mac-address-for-monitor-mode-vdev.patch b/feeds/ipq95xx/mac80211/patches/qca/720-ath12k-add-mac-address-for-monitor-mode-vdev.patch new file mode 100644 index 000000000..27024430b --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/720-ath12k-add-mac-address-for-monitor-mode-vdev.patch @@ -0,0 +1,64 @@ +From 5eaac5d27f7448eb05d36fe900850182b334ecd9 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Kathirvel +Date: Fri, 17 Mar 2023 13:30:36 +0530 +Subject: [PATCH] ath12k: add mac address for monitor mode vdev + +Fix below firmware assertion + +[ 633.757080] QC Image Version: QC_IMAGE_VERSION_STRING=WLAN.WBE.1.1-01766-QCAHKSWPL_SILICONZ-1 +[ 633.757080] Image Variant : IMAGE_VARIANT_STRING=9224.wlanfw.eval_v2Q +[ 633.757080] Oem Image Version: OEM_IMAGE_VERSION_STRING=CRM +[ 633.757080] Oem Image UUID: OEM_IMAGE_UUID_STRING=Q_SENTINEL_{7B924967-D38F-4ACC-9145-3083E0338DB6}_20230214_215848 +[ 633.757080] +[ 633.757080] wlan_peer.c:567 Assertion !((!node_addr[0]) && (!node_addr[1]) && (!node_addr[2]) && (!node_addparam0 :zero, param1 :zero, param2 :zero. +[ 633.757080] Thread ID : 0x0000001c Thread name : WLAN RT0 Process ID : 255 +[ 633.757080] Register: +[ 633.757080] SP : 0x01658d78 +[ 633.757080] FP : 0x01658d80 +[ 633.757080] PC : 0x0122fe5c +[ 633.757080] SSR : 0x00000008 +[ 633.757080] BADVA : 0x0207f1d8 +[ 633.757080] LR : 0x0122ff04 +[ 633.757080] +[ 633.757080] Stack Dump +[ 633.757080] from : 0x01658d78 +[ 633.757080] to : 0x01659398 + +Currently firmware expects non-null vdev mac address, so fill monitor +vdev address with radio mac address. + +Signed-off-by: Karthikeyan Kathirvel +--- + drivers/net/wireless/ath/ath12k/mac.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -1181,7 +1181,6 @@ static int ath12k_mac_monitor_vdev_creat + struct ath12k_pdev *pdev = ar->pdev; + struct vdev_create_params param; + int bit, ret = 0; +- u8 tmp_addr[6] = {0}; + u16 nss = 0; + + lockdep_assert_held(&ar->conf_mutex); +@@ -1216,7 +1215,7 @@ static int ath12k_mac_monitor_vdev_creat + param.chains[NL80211_BAND_5GHZ].rx = ar->num_rx_chains; + } + +- ret = ath12k_wmi_vdev_create(ar, tmp_addr, ¶m); ++ ret = ath12k_wmi_vdev_create(ar, ar->mac_addr, ¶m); + if (ret) { + ath12k_warn(ar->ab, "failed to request monitor vdev %i creation: %d\n", + ar->monitor_vdev_id, ret); +@@ -9389,7 +9388,9 @@ static int ath12k_mac_vdev_create(struct + goto err; + } + +- ret = ath12k_wmi_vdev_create(ar, link_addr, &vdev_param); ++ ret = ath12k_wmi_vdev_create(ar, vdev_param.type == WMI_VDEV_TYPE_MONITOR ? ++ ar->mac_addr : link_addr, ++ &vdev_param); + if (ret) { + ath12k_warn(ab, "failed to create WMI vdev %d: %d\n", + arvif->vdev_id, ret); diff --git a/feeds/ipq95xx/mac80211/patches/qca/696-b-ath12k-Optimize-the-tx-completion-routine.patch b/feeds/ipq95xx/mac80211/patches/qca/720-b-ath12k-Optimize-the-tx-completion-routine.patch similarity index 52% rename from feeds/ipq95xx/mac80211/patches/qca/696-b-ath12k-Optimize-the-tx-completion-routine.patch rename to feeds/ipq95xx/mac80211/patches/qca/720-b-ath12k-Optimize-the-tx-completion-routine.patch index 877761c79..f85ffe272 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/696-b-ath12k-Optimize-the-tx-completion-routine.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/720-b-ath12k-Optimize-the-tx-completion-routine.patch @@ -1,20 +1,25 @@ -From d39daef4871488f4cd604c9a9987daebf0965746 Mon Sep 17 00:00:00 2001 -From: Balamurugan Mahalingam -Date: Tue, 22 Nov 2022 00:39:54 -0800 -Subject: [PATCH 2/6] ath12k: Optimize the tx completion routine +From 4ef4904e460d4d4896f5fa20266d932e7d26b1b6 Mon Sep 17 00:00:00 2001 +From: Ramanathan Choodamani +Date: Tue, 7 Mar 2023 01:52:02 -0800 +Subject: [PATCH 2/6] ath12k: Optimize the tx completion + routine Use cached descriptor for WBM2SW completion and avoid unnecessary if checks Signed-off-by: Balamurugan Mahalingam +Signed-off-by: Ramanathan Choodamani --- - drivers/net/wireless/ath/ath12k/dp.c | 2 +- - drivers/net/wireless/ath/ath12k/dp_tx.c | 35 ++++++++----------------- - 2 files changed, 12 insertions(+), 25 deletions(-) + drivers/net/wireless/ath/ath12k/dp.c | 2 +- + drivers/net/wireless/ath/ath12k/dp_tx.c | 21 ++++++++++----------- + drivers/net/wireless/ath/ath12k/hal_desc.h | 3 ++- + 3 files changed, 13 insertions(+), 13 deletions(-) +diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c +index 9db59ae..b662a99 100644 --- a/drivers/net/wireless/ath/ath12k/dp.c +++ b/drivers/net/wireless/ath/ath12k/dp.c -@@ -248,9 +248,9 @@ int ath12k_dp_srng_setup(struct ath12k_b +@@ -247,9 +247,9 @@ int ath12k_dp_srng_setup(struct ath12k_base *ab, struct dp_srng *ring, /* Allocate the reo dst and tx completion rings from cacheable memory */ switch (type) { case HAL_REO_DST: @@ -25,10 +30,12 @@ Signed-off-by: Balamurugan Mahalingam default: cached = false; } +diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c +index 6af847d..bd6f220 100644 --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -866,7 +866,7 @@ int ath12k_dp_tx_completion_handler(stru - u8 mac_id; +@@ -983,7 +983,7 @@ int ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id, + u64 desc_va; int valid_entries; int workdone = 0; - struct hal_wbm_completion_ring_tx tx_status = { 0 }; @@ -36,31 +43,31 @@ Signed-off-by: Balamurugan Mahalingam enum hal_wbm_rel_src_module buf_rel_source; -@@ -884,18 +884,17 @@ int ath12k_dp_tx_completion_handler(stru +@@ -1001,18 +1001,17 @@ int ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id, if (!ath12k_dp_tx_completion_valid(desc)) continue; - memcpy(&tx_status, desc, -- sizeof(struct hal_wbm_completion_ring_tx)); +- sizeof(struct hal_wbm_completion_ring_tx)); + tx_status = desc; + - if (likely(FIELD_GET(HAL_WBM_COMPL_TX_INFO0_CC_DONE, tx_status.info0))) { + if (likely(HAL_WBM_COMPL_TX_INFO0_CC_DONE & tx_status->info0)) { /* HW done cookie conversion */ - tx_desc = (struct ath12k_tx_desc_info *)(uintptr_t) -- (tx_status.buf_va_lo | -- (((u64)tx_status.buf_va_hi) << 32)); -+ (tx_status->buf_va_lo | -+ (((u64)tx_status->buf_va_hi) << 32)); +- desc_va = ((u64)tx_status.buf_va_hi << 32 | +- tx_status.buf_va_lo); ++ desc_va = ((u64)tx_status->buf_va_hi << 32 | ++ tx_status->buf_va_lo); + tx_desc = (struct ath12k_tx_desc_info *)((unsigned long)desc_va); } else { /* SW does cookie conversion to VA */ - desc_id = FIELD_GET(BUFFER_ADDR_INFO1_SW_COOKIE, -- tx_status.buf_va_hi); -+ tx_status->buf_va_hi); +- desc_id = u32_get_bits(tx_status.buf_va_hi, ++ desc_id = u32_get_bits(tx_status->buf_va_hi, + BUFFER_ADDR_INFO1_SW_COOKIE); tx_desc = ath12k_dp_get_tx_desc(ab, desc_id); - } -@@ -911,11 +910,11 @@ int ath12k_dp_tx_completion_handler(stru +@@ -1029,12 +1028,12 @@ int ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id, * to reduce contention */ ath12k_dp_tx_release_txbuf(dp, tx_desc, tx_desc->pool_id); @@ -68,26 +75,28 @@ Signed-off-by: Balamurugan Mahalingam - tx_status.info0); + /* Find the HAL_WBM_RELEASE_INFO0_REL_SRC_MODULE value */ + buf_rel_source = tx_status->info0 & HAL_WBM_RELEASE_INFO0_REL_SRC_MASK; + ab->soc_stats.wbm_rel_source[buf_rel_source]++; if (unlikely(buf_rel_source == HAL_WBM_REL_SRC_MODULE_FW)) { ath12k_dp_tx_process_htt_tx_complete(ab, - (void *)&tx_status, + (void *)tx_status, mac_id, msdu, - tx_ring, skb_ext_desc); - continue; -@@ -926,7 +925,8 @@ int ath12k_dp_tx_completion_handler(stru + tx_ring, + skb_ext_desc, +@@ -1047,7 +1046,7 @@ int ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id, if (atomic_dec_and_test(&ar->dp.num_tx_pending)) wake_up(&ar->dp.tx_empty_waitq); -- ath12k_dp_tx_complete_msdu(ar, msdu, &tx_status, buf_rel_source, skb_ext_desc); -+ ath12k_dp_tx_complete_msdu(ar, msdu, tx_status, buf_rel_source, -+ skb_ext_desc); +- ath12k_dp_tx_complete_msdu(ar, msdu, &tx_status, ++ ath12k_dp_tx_complete_msdu(ar, msdu, tx_status, + buf_rel_source, skb_ext_desc, + tx_ring->tcl_data_ring_id); budget--; - } - +diff --git a/drivers/net/wireless/ath/ath12k/hal_desc.h b/drivers/net/wireless/ath/ath12k/hal_desc.h +index 8f04d10..8e5eaae 100644 --- a/drivers/net/wireless/ath/ath12k/hal_desc.h +++ b/drivers/net/wireless/ath/ath12k/hal_desc.h -@@ -1883,7 +1883,7 @@ struct hal_wbm_completion_ring_rx { +@@ -1885,7 +1885,7 @@ struct hal_wbm_completion_ring_rx { #define HAL_WBM_COMPL_TX_INFO0_TQM_RELEASE_REASON GENMASK(16, 13) #define HAL_WBM_COMPL_TX_INFO0_RBM_OVERRIDE_VLD BIT(17) #define HAL_WBM_COMPL_TX_INFO0_SW_COOKIE_LO GENMASK(29, 18) @@ -96,11 +105,14 @@ Signed-off-by: Balamurugan Mahalingam #define HAL_WBM_COMPL_TX_INFO0_WBM_INTERNAL_ERROR BIT(31) #define HAL_WBM_COMPL_TX_INFO1_TQM_STATUS_NUMBER GENMASK(23, 0) -@@ -1980,6 +1980,7 @@ struct hal_wbm_release_ring_cc_rx { +@@ -1982,6 +1982,7 @@ struct hal_wbm_release_ring_cc_rx { u32 info1; } __packed; +#define HAL_WBM_RELEASE_INFO0_REL_SRC_MASK 0x7 #define HAL_WBM_RELEASE_INFO0_REL_SRC_MODULE GENMASK(2, 0) + #define HAL_WBM_RELEASE_INFO0_BM_ACTION GENMASK(5, 3) #define HAL_WBM_RELEASE_INFO0_DESC_TYPE GENMASK(8, 6) - #define HAL_WBM_RELEASE_INFO0_RXDMA_PUSH_REASON GENMASK(18, 17) +-- +2.7.4 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/696-c-ath12k-Optimize-the-tx-completion-routine-by-avoid-a.patch b/feeds/ipq95xx/mac80211/patches/qca/720-c-ath12k-Optimize-the-tx-completion-routine-by-avoid-a.patch similarity index 70% rename from feeds/ipq95xx/mac80211/patches/qca/696-c-ath12k-Optimize-the-tx-completion-routine-by-avoid-a.patch rename to feeds/ipq95xx/mac80211/patches/qca/720-c-ath12k-Optimize-the-tx-completion-routine-by-avoid-a.patch index e31b46e13..afbe70673 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/696-c-ath12k-Optimize-the-tx-completion-routine-by-avoid-a.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/720-c-ath12k-Optimize-the-tx-completion-routine-by-avoid-a.patch @@ -1,25 +1,36 @@ -From 623cd822a5a470dbf10b5793b56bfdae2f3b13aa Mon Sep 17 00:00:00 2001 -From: Balamurugan Mahalingam -Date: Tue, 22 Nov 2022 03:51:30 -0800 -Subject: [PATCH 3/6] ath12k: Optimize the tx completion routine by avoid a +From 93d245dc2e34d85a559bcc85fcdd1322b7f434c3 Mon Sep 17 00:00:00 2001 +From: Ramanathan Choodamani +Date: Tue, 7 Mar 2023 02:00:58 -0800 +Subject: [PATCH 3/6] ath12k: Optimize the tx completion routine by avoid a function call context switch. Optimize the workdone calculation Signed-off-by: Balamurugan Mahalingam +Signed-off-by: Ramanathan Choodamani --- - drivers/net/wireless/ath/ath12k/dp_tx.c | 92 ++++++++++++------------- - 1 file changed, 44 insertions(+), 48 deletions(-) + drivers/net/wireless/ath/ath12k/dp_tx.c | 96 ++++++++++++++++----------------- + 1 file changed, 46 insertions(+), 50 deletions(-) --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -704,48 +704,13 @@ static void ath12k_dp_tx_complete_msdu(s - struct ath12k_sta *arsta; +@@ -827,7 +827,7 @@ static void ath12k_dp_tx_complete_msdu(s + struct sk_buff *msdu, + struct hal_wbm_release_ring *tx_status, + enum hal_wbm_rel_src_module buf_rel_source, +- struct sk_buff *skb_ext_desc, int ring) ++ int ring) + { + struct ieee80211_tx_status status = { 0 }; + struct ath12k_base *ab = ar->ab; +@@ -837,49 +837,16 @@ static void ath12k_dp_tx_complete_msdu(s + struct ath12k_link_sta *arsta; struct rate_info rate; struct hal_tx_status ts = { 0 }; - enum hal_wbm_tqm_rel_reason rel_status; enum hal_wbm_htt_tx_comp_status wbm_status; struct ieee80211_vif *vif; + struct ath12k_vif *ahvif; u8 flags = 0; - @@ -29,7 +40,7 @@ Signed-off-by: Balamurugan Mahalingam - } - skb_cb = ATH12K_SKB_CB(msdu); -- + ab->soc_stats.tx_completed[ring]++; - dma_unmap_single_attrs(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE, - DMA_ATTR_SKIP_CPU_SYNC); - if (unlikely(skb_cb->paddr_ext_desc)) { @@ -38,7 +49,7 @@ Signed-off-by: Balamurugan Mahalingam - DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); - dev_kfree_skb_any(skb_ext_desc); - } -- + flags = skb_cb->flags; - rel_status = FIELD_GET(HAL_WBM_COMPL_TX_INFO0_TQM_RELEASE_REASON, @@ -61,17 +72,19 @@ Signed-off-by: Balamurugan Mahalingam - ath12k_dp_tx_status_parse(ab, tx_status, &ts); - if (unlikely(!rcu_access_pointer(ab->pdevs_active[ar->pdev_idx]))) { -@@ -861,13 +826,16 @@ int ath12k_dp_tx_completion_handler(stru + ar->wmm_stats.tx_type = ath12k_tid_to_ac(ts.tid > ATH12K_DSCP_PRIORITY ? 0:ts.tid); +@@ -1018,14 +985,18 @@ int ath12k_dp_tx_completion_handler(stru struct hal_srng *status_ring = &ab->hal.srng_list[hal_ring_id]; struct ath12k_tx_desc_info *tx_desc = NULL; struct sk_buff *msdu, *skb_ext_desc; + struct ath12k_skb_cb *skb_cb; struct dp_tx_ring *tx_ring = &dp->tx_ring[ring_id]; - u32 *desc, desc_id; ++ struct ath12k_vif *ahvif; + u32 desc_id; + u8 flags = 0; u8 mac_id; + u64 desc_va; int valid_entries; - int workdone = 0; + int orig_budget = budget; @@ -81,7 +94,7 @@ Signed-off-by: Balamurugan Mahalingam ath12k_hal_srng_access_dst_ring_begin_nolock(ab, status_ring); -@@ -875,17 +843,15 @@ int ath12k_dp_tx_completion_handler(stru +@@ -1033,18 +1004,15 @@ int ath12k_dp_tx_completion_handler(stru valid_entries = ath12k_hal_srng_dst_num_free(ab, status_ring, false); if (!valid_entries) { ath12k_hal_srng_access_umac_dst_ring_end_nolock(ab->mem, status_ring); @@ -98,12 +111,13 @@ Signed-off-by: Balamurugan Mahalingam continue; - tx_status = desc; +- - if (likely(HAL_WBM_COMPL_TX_INFO0_CC_DONE & tx_status->info0)) { /* HW done cookie conversion */ - tx_desc = (struct ath12k_tx_desc_info *)(uintptr_t) -@@ -919,20 +885,51 @@ int ath12k_dp_tx_completion_handler(stru - tx_ring, skb_ext_desc); + desc_va = ((u64)tx_status->buf_va_hi << 32 | +@@ -1081,20 +1049,63 @@ int ath12k_dp_tx_completion_handler(stru + tx_desc); continue; } - workdone++; @@ -113,8 +127,9 @@ Signed-off-by: Balamurugan Mahalingam if (atomic_dec_and_test(&ar->dp.num_tx_pending)) wake_up(&ar->dp.tx_empty_waitq); -- ath12k_dp_tx_complete_msdu(ar, msdu, tx_status, buf_rel_source, -- skb_ext_desc); +- ath12k_dp_tx_complete_msdu(ar, msdu, tx_status, +- buf_rel_source, skb_ext_desc, +- tx_ring->tcl_data_ring_id); - budget--; + if (unlikely(WARN_ON_ONCE(buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM))) { + /* Must not happen */ @@ -133,6 +148,19 @@ Signed-off-by: Balamurugan Mahalingam + } + /* Free skb here if stats is disabled */ + if (ab->stats_disable && !(flags & ATH12K_SKB_TX_STATUS)) { ++ ar->ab->soc_stats.tx_completed[tx_ring->tcl_data_ring_id]++; ++ ++ if (skb_cb->vif) { ++ ahvif = (void *)skb_cb->vif->drv_priv; ++ if (ahvif->links_map & BIT(skb_cb->link_id)) ++ ahvif->link[skb_cb->link_id]->link_stats.tx_completed++; ++ else ++ ath12k_warn(ab, ++ "invalid linkid 0x%X in tx completion handler for linkmap 0x%X\n", ++ skb_cb->link_id, ++ ahvif->links_map); ++ } ++ + if (unlikely(msdu->destructor)) { + msdu->wifi_acked_valid = 1; + rel_status = FIELD_GET(HAL_WBM_COMPL_TX_INFO0_TQM_RELEASE_REASON, @@ -149,14 +177,13 @@ Signed-off-by: Balamurugan Mahalingam + + ath12k_dp_tx_complete_msdu(ar, msdu, tx_status, + buf_rel_source, -+ skb_ext_desc); ++ tx_ring->tcl_data_ring_id); + } } - ath12k_hal_srng_access_umac_dst_ring_end_nolock(ab->mem, status_ring); - return workdone; + return (orig_budget - budget); } - int ath12k_dp_tx_send_reo_cmd(struct ath12k_base *ab, struct dp_rx_tid *rx_tid, + static int diff --git a/feeds/ipq95xx/mac80211/patches/qca/696-d-ath12k-Avoid-initialization-of-all-the-variables-ear.patch b/feeds/ipq95xx/mac80211/patches/qca/720-d-ath12k-Avoid-initialization-of-all-the-variables-ear.patch similarity index 58% rename from feeds/ipq95xx/mac80211/patches/qca/696-d-ath12k-Avoid-initialization-of-all-the-variables-ear.patch rename to feeds/ipq95xx/mac80211/patches/qca/720-d-ath12k-Avoid-initialization-of-all-the-variables-ear.patch index 64939d02c..38fa20cf4 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/696-d-ath12k-Avoid-initialization-of-all-the-variables-ear.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/720-d-ath12k-Avoid-initialization-of-all-the-variables-ear.patch @@ -1,23 +1,24 @@ -From 7d770f00cd71b6619d798194dc2105a3a1234f14 Mon Sep 17 00:00:00 2001 -From: Balamurugan Mahalingam -Date: Tue, 22 Nov 2022 01:03:29 -0800 -Subject: [PATCH 4/6] ath12k: Avoid initialization of all the variables early - in the function +From 7a5c34b80622fc7003228ff8b0ce0c09b389c60f Mon Sep 17 00:00:00 2001 +From: Ramanathan Choodamani +Date: Wed, 8 Mar 2023 09:19:50 -0800 +Subject: [PATCH 4/6] ath12k: Avoid initialization of all the + variables early in the function Intializing all the variables takes cpu. Avoid it earlier in the function and initialize it just before use. All the variables do not need to be initialized to enter fast xmit path Signed-off-by: Balamurugan Mahalingam +Signed-off-by: Ramanathan Choodamani --- - drivers/net/wireless/ath/ath12k/dp_tx.c | 7 ++--- - drivers/net/wireless/ath/ath12k/mac.c | 35 ++++++++++++++++++------- - 2 files changed, 29 insertions(+), 13 deletions(-) + drivers/net/wireless/ath/ath12k/dp_tx.c | 7 ++++--- + drivers/net/wireless/ath/ath12k/mac.c | 30 +++++++++++++++++++++--------- + 2 files changed, 25 insertions(+), 12 deletions(-) --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -111,14 +111,14 @@ static void ath12k_hal_tx_cmd_ext_desc_s - int ath12k_dp_tx_direct(struct ath12k_vif *arvif, struct sk_buff *skb) +@@ -155,14 +155,14 @@ static int ath12k_dp_prepare_htt_metadat + int ath12k_dp_tx_direct(struct ath12k_link_vif *arvif, struct sk_buff *skb) { struct ath12k *ar = arvif->ar; - struct ath12k_base *ab = arvif->ar->ab; @@ -33,8 +34,8 @@ Signed-off-by: Balamurugan Mahalingam u8 hal_ring_id, ring_id; int ret; -@@ -171,6 +171,7 @@ int ath12k_dp_tx_direct(struct ath12k_vi - tcl_desc.info2 |= TX_IP_CHECKSUM; +@@ -218,6 +218,7 @@ int ath12k_dp_tx_direct(struct ath12k_li + tcl_desc.info3 = arvif->desc.info3; tcl_desc.info4 = arvif->desc.info4; + tcl_desc.info5 = 0; @@ -43,58 +44,54 @@ Signed-off-by: Balamurugan Mahalingam ath12k_hal_srng_access_umac_src_ring_end_nolock(ab->mem, tcl_ring); --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -6844,25 +6844,30 @@ static void ath12k_mac_op_tx(struct ieee +@@ -8465,23 +8465,23 @@ static void ath12k_mac_op_tx(struct ieee struct ieee80211_tx_control *control, struct sk_buff *skb) { - struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB(skb); - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_vif *vif = info->control.vif; -- struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); -- struct ath12k *ar = arvif->ar; -- struct ath12k_hw *ah = ar->ah; -- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; -- struct ieee80211_key_conf *key = info->control.hw_key; -- struct ath12k_mgmt_frame_stats *mgmt_stats = &arvif->mgmt_stats; +- struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + struct ath12k_skb_cb *skb_cb; + struct ieee80211_tx_info *info; + struct ieee80211_vif *vif; -+ struct ath12k_vif *arvif; -+ struct ath12k *ar; -+ struct ath12k_hw *ah; ++ struct ath12k_vif *ahvif; + struct ath12k_link_vif *arvif, *tmp_arvif; + struct ath12k *ar, *tmp_ar; + struct ath12k_hw *ah; +- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_hdr *hdr; + struct ethhdr *eth = (struct ethhdr *)skb->data; +- struct ieee80211_key_conf *key = info->control.hw_key; +- struct ath12k_mgmt_frame_stats *mgmt_stats = &ahvif->mgmt_stats; + struct ieee80211_key_conf *key; + struct ath12k_mgmt_frame_stats *mgmt_stats; - struct ath12k_sta *arsta = NULL; + struct ath12k_sta *ahsta = NULL; + struct sk_buff *msdu_copied; + struct ath12k_link_sta *arsta = NULL; struct ieee80211_sta *sta = NULL; + struct ath12k_peer *peer; - u32 info_flags = info->flags; + u32 info_flags; bool is_prb_rsp; - u16 frm_type = 0; + bool is_mcast = false; + bool gsn_valid; +@@ -8489,7 +8489,13 @@ static void ath12k_mac_op_tx(struct ieee + u8 link_id; + u16 mcbc_gsn; int ret; - +- u8 link = u32_get_bits(info->control.flags, IEEE80211_TX_CTRL_MLO_LINK); ++ u8 link; ++ + info = IEEE80211_SKB_CB(skb); + vif = info->control.vif; -+ arvif = ath12k_vif_to_arvif(vif); -+ - if (skb->fast_xmit) { - ret = ath12k_dp_tx_direct(arvif, skb); - if (unlikely(ret)) { -+ ar = arvif->ar; - ath12k_warn(ar->ab, "failed to transmit frame %d\n", - ret); - dev_kfree_skb_any(skb); -@@ -6873,6 +6878,9 @@ static void ath12k_mac_op_tx(struct ieee ++ ahvif = ath12k_vif_to_ahvif(vif); ++ link = u32_get_bits(info->control.flags, IEEE80211_TX_CTRL_MLO_LINK); ++ info_flags = info->flags; + if (control) sta = control->sta; - -+ ar = arvif->ar; -+ ah = ar->ah; -+ - if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { - ieee80211_free_txskb(ah->hw, skb); - return; -@@ -6883,6 +6891,8 @@ static void ath12k_mac_op_tx(struct ieee +@@ -8499,6 +8505,8 @@ static void ath12k_mac_op_tx(struct ieee return; } @@ -102,21 +99,20 @@ Signed-off-by: Balamurugan Mahalingam + key = info->control.hw_key; memset(skb_cb, 0, sizeof(*skb_cb)); skb_cb->vif = vif; - -@@ -6891,11 +6901,16 @@ static void ath12k_mac_op_tx(struct ieee + /* handle only for MLO case, use deflink for non MLO case */ +@@ -8543,12 +8551,15 @@ static void ath12k_mac_op_tx(struct ieee skb_cb->flags |= ATH12K_SKB_CIPHER_SET; } + hdr = (struct ieee80211_hdr *)skb->data; + -+ info_flags = info->flags; if (info_flags & IEEE80211_TX_CTL_HW_80211_ENCAP) { skb_cb->flags |= ATH12K_SKB_HW_80211_ENCAP; + is_mcast = is_multicast_ether_addr(eth->h_dest); } else if (ieee80211_is_mgmt(hdr->frame_control)) { frm_type = FIELD_GET(IEEE80211_FCTL_STYPE, hdr->frame_control); is_prb_rsp = ieee80211_is_probe_resp(hdr->frame_control); -+ -+ mgmt_stats = &arvif->mgmt_stats; ++ mgmt_stats = &ahvif->mgmt_stats; ret = ath12k_mac_mgmt_tx(ar, skb, is_prb_rsp); if (ret) { if (ret != -EBUSY) diff --git a/feeds/ipq95xx/mac80211/patches/qca/696-e-ath12k-Optimize-Tx-direct-path-variable-init.patch b/feeds/ipq95xx/mac80211/patches/qca/720-e-ath12k-Optimize-Tx-direct-path-variable-init.patch similarity index 65% rename from feeds/ipq95xx/mac80211/patches/qca/696-e-ath12k-Optimize-Tx-direct-path-variable-init.patch rename to feeds/ipq95xx/mac80211/patches/qca/720-e-ath12k-Optimize-Tx-direct-path-variable-init.patch index bd2a5a7a1..f2a094210 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/696-e-ath12k-Optimize-Tx-direct-path-variable-init.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/720-e-ath12k-Optimize-Tx-direct-path-variable-init.patch @@ -1,6 +1,6 @@ -From fcde9f5d01bd57ec0b0d486577448cb8ca672d56 Mon Sep 17 00:00:00 2001 -From: Balamurugan Mahalingam -Date: Tue, 22 Nov 2022 04:20:01 -0800 +From 209d8138a305d81977481ebf1c7479d35c3495ef Mon Sep 17 00:00:00 2001 +From: Ramanathan Choodamani +Date: Tue, 7 Mar 2023 01:40:23 -0800 Subject: [PATCH 5/6] ath12k: Optimize Tx direct path variable init Group all the pointers used in the tx path in arvif and try to use @@ -8,20 +8,19 @@ all value from arvif. This could help avoid multiple locations being referred Signed-off-by: Balamurugan Mahalingam +Signed-off-by: Ramanathan Choodamani --- - drivers/net/wireless/ath/ath12k/core.h | 10 ++++---- - drivers/net/wireless/ath/ath12k/dp_tx.c | 32 ++++++++++++++----------- + drivers/net/wireless/ath/ath12k/core.h | 9 ++++++--- + drivers/net/wireless/ath/ath12k/dp_tx.c | 33 +++++++++++++++++++-------------- drivers/net/wireless/ath/ath12k/mac.c | 4 ++++ - 3 files changed, 28 insertions(+), 18 deletions(-) + 3 files changed, 29 insertions(+), 17 deletions(-) -diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h -index 848e01d..928e493 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h -@@ -316,7 +316,13 @@ struct ath12k_vif_tcl_desc_template { +@@ -326,7 +326,13 @@ struct ath12k_vif_tcl_desc_template { }; - struct ath12k_vif { + struct ath12k_link_vif { + struct ath12k_base *ab; + struct ath12k_dp *dp; struct ath12k_vif_tcl_desc_template desc; @@ -30,25 +29,22 @@ index 848e01d..928e493 100644 + struct ath12k *ar; + u8 pdev_idx; u32 vdev_id; - enum wmi_vdev_type vdev_type; - enum wmi_vdev_subtype vdev_subtype; -@@ -327,10 +333,6 @@ struct ath12k_vif { + u32 beacon_interval; + u32 dtim_period; +@@ -336,9 +342,6 @@ struct ath12k_link_vif { u16 tcl_metadata; u8 hal_addr_search_flags; u8 search_type; - - struct ath12k *ar; -- struct ieee80211_vif *vif; - int bank_id; u8 vdev_id_check_en; -diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c -index 17a8d4e..f02264e 100644 --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -111,15 +111,18 @@ static void ath12k_hal_tx_cmd_ext_desc_setup(struct ath12k_base *ab, void *cmd, - int ath12k_dp_tx_direct(struct ath12k_vif *arvif, struct sk_buff *skb) +@@ -155,15 +155,18 @@ static int ath12k_dp_prepare_htt_metadat + int ath12k_dp_tx_direct(struct ath12k_link_vif *arvif, struct sk_buff *skb) { struct ath12k *ar = arvif->ar; - struct ath12k_base *ab = ar->ab; @@ -68,7 +64,7 @@ index 17a8d4e..f02264e 100644 int ret; ring_id = smp_processor_id(); -@@ -131,9 +134,9 @@ int ath12k_dp_tx_direct(struct ath12k_vif *arvif, struct sk_buff *skb) +@@ -175,9 +178,9 @@ int ath12k_dp_tx_direct(struct ath12k_li ab->soc_stats.tx_err.txbuf_na[ring_id]++; return -ENOSPC; } @@ -81,14 +77,14 @@ index 17a8d4e..f02264e 100644 atomic_inc(&ab->soc_stats.tx_err.misc_fail); ath12k_warn(ab, "failed to DMA map data Tx buffer\n"); ret = -ENOMEM; -@@ -141,11 +144,12 @@ int ath12k_dp_tx_direct(struct ath12k_vif *arvif, struct sk_buff *skb) +@@ -185,11 +188,12 @@ int ath12k_dp_tx_direct(struct ath12k_li } tx_desc->skb = skb; - tx_desc->mac_id = ar->pdev_idx; + tx_desc->mac_id = arvif->pdev_idx; + - skb_cb->vif = arvif->vif; + skb_cb->vif = arvif->ahvif->vif; - skb_cb->ar = ar; + skb_cb->paddr = paddr; @@ -97,7 +93,7 @@ index 17a8d4e..f02264e 100644 tcl_ring = &ab->hal.srng_list[hal_ring_id]; ath12k_hal_srng_access_src_ring_begin_nolock(ab, tcl_ring); -@@ -155,13 +159,13 @@ int ath12k_dp_tx_direct(struct ath12k_vif *arvif, struct sk_buff *skb) +@@ -199,7 +203,7 @@ int ath12k_dp_tx_direct(struct ath12k_li /* NOTE: It is highly unlikely we'll be running out of tcl_ring * desc because the desc is directly enqueued onto hw queue. */ @@ -106,14 +102,16 @@ index 17a8d4e..f02264e 100644 ab->soc_stats.tx_err.desc_na[ring_id]++; ret = -ENOMEM; goto fail_unmap_dma; - } +@@ -207,7 +211,7 @@ int ath12k_dp_tx_direct(struct ath12k_li + + ab->soc_stats.tx_enqueued[ring_id]++; - tcl_desc.buf_addr_info.info0 = (u32)skb_cb->paddr; + tcl_desc.buf_addr_info.info0 = (u32)paddr; tcl_desc.buf_addr_info.info1 = (tx_desc->desc_id << 12); tcl_desc.info0 = arvif->desc.info0; tcl_desc.info1 = arvif->desc.info1; -@@ -174,7 +178,7 @@ int ath12k_dp_tx_direct(struct ath12k_vif *arvif, struct sk_buff *skb) +@@ -220,7 +224,7 @@ int ath12k_dp_tx_direct(struct ath12k_li tcl_desc.info5 = 0; memcpy(hal_tcl_desc, &tcl_desc, sizeof(tcl_desc)); dsb(st); @@ -122,7 +120,7 @@ index 17a8d4e..f02264e 100644 atomic_inc(&ar->dp.num_tx_pending); -@@ -432,7 +436,7 @@ ath12k_dp_tx_htt_tx_complete_buf(struct ath12k_base *ab, +@@ -547,7 +551,7 @@ ath12k_dp_tx_htt_tx_complete_buf(struct struct sk_buff *msdu, struct dp_tx_ring *tx_ring, struct ath12k_dp_htt_wbm_tx_status *ts, @@ -131,31 +129,30 @@ index 17a8d4e..f02264e 100644 { struct ieee80211_tx_info *info; struct ath12k_skb_cb *skb_cb; -@@ -443,7 +447,7 @@ ath12k_dp_tx_htt_tx_complete_buf(struct ath12k_base *ab, +@@ -559,7 +563,7 @@ ath12k_dp_tx_htt_tx_complete_buf(struct skb_cb = ATH12K_SKB_CB(msdu); info = IEEE80211_SKB_CB(msdu); - ar = skb_cb->ar; + ar = ab->pdevs[mac_id].ar; + ab->soc_stats.tx_completed[tx_ring->tcl_data_ring_id]++; if (atomic_dec_and_test(&ar->dp.num_tx_pending)) - wake_up(&ar->dp.tx_empty_waitq); -@@ -519,7 +523,7 @@ ath12k_dp_tx_process_htt_tx_complete(struct ath12k_base *ab, - ts.acked = (wbm_status == HAL_WBM_REL_HTT_TX_COMP_STATUS_OK); - ts.ack_rssi = FIELD_GET(HTT_TX_WBM_COMP_INFO2_ACK_RSSI, - status_desc->info2); +@@ -642,7 +646,8 @@ ath12k_dp_tx_process_htt_tx_complete(str + ts.acked = (htt_status == HAL_WBM_REL_HTT_TX_COMP_STATUS_OK); + ts.ack_rssi = u32_get_bits(status_desc->info2, + HTT_TX_WBM_COMP_INFO2_ACK_RSSI); - ath12k_dp_tx_htt_tx_complete_buf(ab, msdu, tx_ring, &ts, skb_ext_desc); + ath12k_dp_tx_htt_tx_complete_buf(ab, msdu, tx_ring, &ts, skb_ext_desc, mac_id); ++ break; case HAL_WBM_REL_HTT_TX_COMP_STATUS_REINJ: case HAL_WBM_REL_HTT_TX_COMP_STATUS_INSPECT: -diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c -index bd96072..2ac4afb 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -7451,6 +7451,10 @@ static int ath12k_mac_vdev_create(struct ath12k *ar, struct ieee80211_vif *vif) - arvif->vdev_id = vdev_id; - arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE; +@@ -9442,6 +9442,10 @@ static int ath12k_mac_vdev_create(struct + arvif->tx_vdev_id = vdev_id; + ahvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE; arvif->ar = ar; + arvif->ab = ab; + arvif->dp = &ab->dp; @@ -164,6 +161,3 @@ index bd96072..2ac4afb 100644 switch (vif->type) { case NL80211_IFTYPE_UNSPECIFIED: --- -2.17.1 - diff --git a/feeds/ipq95xx/mac80211/patches/qca/696-f-ath12k-Enable-fast-recycling-the-skbs-for-performanc.patch b/feeds/ipq95xx/mac80211/patches/qca/720-f-ath12k-Enable-fast-recycling-the-skbs-for-performanc.patch similarity index 71% rename from feeds/ipq95xx/mac80211/patches/qca/696-f-ath12k-Enable-fast-recycling-the-skbs-for-performanc.patch rename to feeds/ipq95xx/mac80211/patches/qca/720-f-ath12k-Enable-fast-recycling-the-skbs-for-performanc.patch index 0f518c62e..c4d8bce3f 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/696-f-ath12k-Enable-fast-recycling-the-skbs-for-performanc.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/720-f-ath12k-Enable-fast-recycling-the-skbs-for-performanc.patch @@ -1,7 +1,7 @@ -From 2109b3b94031d414446ef0bc7672f86a663edfb0 Mon Sep 17 00:00:00 2001 -From: Balamurugan Mahalingam -Date: Wed, 23 Nov 2022 20:08:21 -0800 -Subject: [PATCH] ath12k: Enable fast recycling the skbs for performance and +From 65180a508b669fe6c7dc09a72528513bba10e0ac Mon Sep 17 00:00:00 2001 +From: Ramanathan Choodamani +Date: Tue, 7 Mar 2023 02:14:19 -0800 +Subject: [PATCH] ath12k: Enable fast recycling the skbs for performance and desc prefetch The SKB fast recycling features reduces the cpu overhead by quickly @@ -10,14 +10,15 @@ provides information to driver for handling dma cache invalidation operations in a efficient way Signed-off-by: Balamurugan Mahalingam +Signed-off-by: Ramanathan Choodamani --- drivers/net/wireless/ath/ath12k/dp.h | 1 + - drivers/net/wireless/ath/ath12k/dp_tx.c | 20 ++++++++++++++++++-- - 2 files changed, 19 insertions(+), 2 deletions(-) + drivers/net/wireless/ath/ath12k/dp_tx.c | 23 ++++++++++++++++++++--- + 2 files changed, 21 insertions(+), 3 deletions(-) --- a/drivers/net/wireless/ath/ath12k/dp.h +++ b/drivers/net/wireless/ath/ath12k/dp.h -@@ -321,6 +321,7 @@ struct ath12k_tx_desc_info { +@@ -290,6 +290,7 @@ struct ath12k_tx_desc_info { u32 desc_id; /* Cookie */ u8 mac_id; u8 pool_id; @@ -27,15 +28,15 @@ Signed-off-by: Balamurugan Mahalingam struct ath12k_spt_info { --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -86,6 +86,7 @@ struct ath12k_tx_desc_info *ath12k_dp_tx +@@ -89,6 +89,7 @@ struct ath12k_tx_desc_info *ath12k_dp_tx + return NULL; } - list_move_tail(&desc->list, &dp->tx_desc_used_list[pool_id]); + prefetch(desc); + list_move_tail(&desc->list, &dp->tx_desc_used_list[pool_id]); return desc; - } -@@ -145,6 +146,12 @@ int ath12k_dp_tx_direct(struct ath12k_vi +@@ -189,6 +190,12 @@ int ath12k_dp_tx_direct(struct ath12k_li tx_desc->skb = skb; tx_desc->mac_id = arvif->pdev_idx; @@ -46,17 +47,17 @@ Signed-off-by: Balamurugan Mahalingam + if (skb->is_from_recycler) + tx_desc->recycler_fast_xmit = 1; - skb_cb->vif = arvif->vif; + skb_cb->vif = arvif->ahvif->vif; skb_cb->paddr = paddr; -@@ -320,6 +327,7 @@ int ath12k_dp_tx(struct ath12k *ar, stru +@@ -416,6 +423,7 @@ int ath12k_dp_tx(struct ath12k *ar, stru tx_desc->skb = skb; tx_desc->mac_id = ar->pdev_idx; + tx_desc->recycler_fast_xmit = 0; ti.desc_id = tx_desc->desc_id; - ti.data_len = skb->len; + ti.data_len = skb->len - ti.pkt_offset; skb_cb->paddr = ti.paddr; -@@ -841,6 +849,8 @@ int ath12k_dp_tx_completion_handler(stru +@@ -1003,6 +1011,8 @@ int ath12k_dp_tx_completion_handler(stru struct hal_wbm_completion_ring_tx *tx_status; enum hal_wbm_rel_src_module buf_rel_source; enum hal_wbm_tqm_rel_reason rel_status; @@ -65,7 +66,7 @@ Signed-off-by: Balamurugan Mahalingam ath12k_hal_srng_access_dst_ring_begin_nolock(ab, status_ring); -@@ -852,6 +862,7 @@ int ath12k_dp_tx_completion_handler(stru +@@ -1014,6 +1024,7 @@ int ath12k_dp_tx_completion_handler(stru } ath12k_hal_srng_dst_invalidate_entry(ab, status_ring, valid_entries); @@ -73,7 +74,7 @@ Signed-off-by: Balamurugan Mahalingam while (budget && (tx_status = ath12k_hal_srng_dst_get_next_cache_entry(ab, status_ring))) { if (!ath12k_dp_tx_completion_valid(tx_status)) -@@ -876,6 +887,7 @@ int ath12k_dp_tx_completion_handler(stru +@@ -1038,6 +1049,7 @@ int ath12k_dp_tx_completion_handler(stru msdu = tx_desc->skb; mac_id = tx_desc->mac_id; @@ -81,7 +82,7 @@ Signed-off-by: Balamurugan Mahalingam skb_ext_desc = tx_desc->skb_ext_desc; /* Release descriptor as soon as extracting necessary info * to reduce contention -@@ -892,6 +904,7 @@ int ath12k_dp_tx_completion_handler(stru +@@ -1056,6 +1068,7 @@ int ath12k_dp_tx_completion_handler(stru } budget--; @@ -89,7 +90,7 @@ Signed-off-by: Balamurugan Mahalingam if (atomic_dec_and_test(&ar->dp.num_tx_pending)) wake_up(&ar->dp.tx_empty_waitq); -@@ -922,9 +935,12 @@ int ath12k_dp_tx_completion_handler(stru +@@ -1099,9 +1112,12 @@ int ath12k_dp_tx_completion_handler(stru kfree_skb_list(skb_shinfo(msdu)->frag_list); skb_shinfo(msdu)->frag_list = NULL; } @@ -104,9 +105,9 @@ Signed-off-by: Balamurugan Mahalingam ath12k_dp_tx_complete_msdu(ar, msdu, tx_status, buf_rel_source, -@@ -933,6 +949,7 @@ int ath12k_dp_tx_completion_handler(stru +@@ -1109,6 +1125,7 @@ int ath12k_dp_tx_completion_handler(stru + } } - ath12k_hal_srng_access_umac_dst_ring_end_nolock(ab->mem, status_ring); + dev_kfree_skb_list_fast(&free_list_head); diff --git a/feeds/ipq95xx/mac80211/patches/qca/696-g-ath12k-Introduce-a-module_param-to-change-the-tx-com.patch b/feeds/ipq95xx/mac80211/patches/qca/720-g-ath12k-Introduce-a-module_param-to-change-the-tx-com.patch similarity index 65% rename from feeds/ipq95xx/mac80211/patches/qca/696-g-ath12k-Introduce-a-module_param-to-change-the-tx-com.patch rename to feeds/ipq95xx/mac80211/patches/qca/720-g-ath12k-Introduce-a-module_param-to-change-the-tx-com.patch index e48c17850..72c1795fe 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/696-g-ath12k-Introduce-a-module_param-to-change-the-tx-com.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/720-g-ath12k-Introduce-a-module_param-to-change-the-tx-com.patch @@ -1,22 +1,24 @@ -From 9b74bfde9cac18ac043dc6a52009bc441ba0eeff Mon Sep 17 00:00:00 2001 -From: Balamurugan Mahalingam -Date: Mon, 28 Nov 2022 01:12:00 -0800 -Subject: [PATCH 1/2] ath12k: Introduce a module_param to change the tx - completion budget on demand +From 0ab9fe790ac5992c537256e6162bda522ecc3c92 Mon Sep 17 00:00:00 2001 +From: Ramanathan Choodamani +Date: Tue, 7 Mar 2023 02:21:23 -0800 +Subject: [PATCH 1/2] ath12k: Introduce a module_param to + change the completion budget on demand -Add module param support to change the tx completion budget on demand. +Add module param support to change the tx completion budget +on demand. Signed-off-by: Balamurugan Mahalingam +Signed-off-by: Ramanathan Choodamani --- - drivers/net/wireless/ath/ath12k/dp_tx.c | 5 ++++- + drivers/net/wireless/ath/ath12k/dp_tx.c | 6 ++++-- drivers/net/wireless/ath/ath12k/pci.c | 7 +++++-- - 2 files changed, 9 insertions(+), 3 deletions(-) + 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c -index be4ac0f..48faf51 100644 +index 7d33296..4e9b45b 100644 --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -861,10 +861,14 @@ int ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id, +@@ -980,10 +980,14 @@ int ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id, return 0; } @@ -31,19 +33,20 @@ index be4ac0f..48faf51 100644 if (!ath12k_dp_tx_completion_valid(tx_status)) continue; -@@ -902,7 +906,6 @@ int ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id, - tx_ring, skb_ext_desc); +@@ -1024,8 +1028,6 @@ int ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id, + tx_desc); continue; } - budget--; - +- ar = ab->pdevs[mac_id].ar; if (atomic_dec_and_test(&ar->dp.num_tx_pending)) + wake_up(&ar->dp.tx_empty_waitq); diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c -index e8fc804..7762544 100644 +index 68f11b4..5badd39 100644 --- a/drivers/net/wireless/ath/ath12k/pci.c +++ b/drivers/net/wireless/ath/ath12k/pci.c -@@ -46,7 +46,10 @@ +@@ -47,7 +47,10 @@ /* choose a little lower value for tx completion processing * to give priority for enqueue */ @@ -55,15 +58,15 @@ index e8fc804..7762544 100644 char dp_irq_name[ATH12K_MAX_PCI_DOMAINS + 1][ATH12K_EXT_IRQ_GRP_NUM_MAX][DP_IRQ_NAME_LEN] = {}; -@@ -598,7 +601,7 @@ static int ath12k_pci_ext_irq_config(struct ath12k_base *ab) +@@ -530,7 +533,7 @@ static int ath12k_pci_ext_irq_config(struct ath12k_base *ab) /* Apply a reduced budget for tx completion to prioritize tx * enqueue operation */ - if (ab->hw_params.ring_mask->tx[i]) + if (ab->hw_params->ring_mask->tx[i]) - budget = ATH12K_TX_COMP_NAPI_BUDGET; + budget = tx_comp_budget; netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi, ath12k_pci_ext_grp_napi_poll, budget); -- -2.17.1 +2.7.4 diff --git a/feeds/ipq95xx/mac80211/patches/qca/696-h-ath12k-Avoid-register-address-caculations-on-a-per-p.patch b/feeds/ipq95xx/mac80211/patches/qca/720-h-ath12k-Avoid-register-address-caculations-on-a-per-p.patch similarity index 55% rename from feeds/ipq95xx/mac80211/patches/qca/696-h-ath12k-Avoid-register-address-caculations-on-a-per-p.patch rename to feeds/ipq95xx/mac80211/patches/qca/720-h-ath12k-Avoid-register-address-caculations-on-a-per-p.patch index 78cfda1ba..9550bba77 100644 --- a/feeds/ipq95xx/mac80211/patches/qca/696-h-ath12k-Avoid-register-address-caculations-on-a-per-p.patch +++ b/feeds/ipq95xx/mac80211/patches/qca/720-h-ath12k-Avoid-register-address-caculations-on-a-per-p.patch @@ -1,23 +1,26 @@ -From 1b74b4ffff02c1f824b5b26ed0576770d07a9605 Mon Sep 17 00:00:00 2001 -From: Balamurugan Mahalingam -Date: Mon, 28 Nov 2022 01:22:18 -0800 -Subject: [PATCH 2/2] ath12k: Avoid register address caculations on a per - packet basis +From a337a9e12b60667eb4f40e249b150053110f33f8 Mon Sep 17 00:00:00 2001 +From: Ramanathan Choodamani +Date: Sun, 5 Mar 2023 19:28:43 -0800 +Subject: [PATCH 2/2] ath12k: Avoid register address caculations on a per packet + basis Precompute the datapath registers addresses and use it directly to save cpu time. Do not compute the addresses on a per packet basis. Signed-off-by: Balamurugan Mahalingam +Signed-off-by: Ramanathan Choodamani --- - drivers/net/wireless/ath/ath12k/dp_tx.c | 4 ++-- - drivers/net/wireless/ath/ath12k/hal.c | 13 +++++++++++++ - drivers/net/wireless/ath/ath12k/hal.h | 11 ++++------- - drivers/net/wireless/ath/ath12k/mac.c | 5 ++--- - 4 files changed, 21 insertions(+), 12 deletions(-) + drivers/net/wireless/ath/ath12k/dp_tx.c | 21 +++++++-------- + drivers/net/wireless/ath/ath12k/hal.c | 47 ++++++++++++++++++++++----------- + drivers/net/wireless/ath/ath12k/hal.h | 20 +++++--------- + drivers/net/wireless/ath/ath12k/mac.c | 4 +-- + 4 files changed, 50 insertions(+), 42 deletions(-) +diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c +index 5974191..816418b 100644 --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c -@@ -81,7 +81,7 @@ struct ath12k_tx_desc_info *ath12k_dp_tx +@@ -85,7 +85,7 @@ struct ath12k_tx_desc_info *ath12k_dp_tx_assign_buffer_nolock(struct ath12k_dp * struct ath12k_tx_desc_info, list); if (!desc) { @@ -26,7 +29,7 @@ Signed-off-by: Balamurugan Mahalingam return NULL; } -@@ -120,7 +120,6 @@ int ath12k_dp_tx_direct(struct ath12k_vi +@@ -164,7 +164,6 @@ int ath12k_dp_tx_direct(struct ath12k_link_vif *arvif, struct sk_buff *skb) struct dp_tx_ring *tx_ring; struct device *dev = arvif->dev; void *hal_tcl_desc; @@ -34,7 +37,7 @@ Signed-off-by: Balamurugan Mahalingam struct hal_tcl_data_cmd tcl_desc; u8 hal_ring_id, ring_id; dma_addr_t paddr; -@@ -159,14 +158,14 @@ int ath12k_dp_tx_direct(struct ath12k_vi +@@ -203,14 +202,14 @@ int ath12k_dp_tx_direct(struct ath12k_link_vif *arvif, struct sk_buff *skb) hal_ring_id = ring_id + HAL_SRNG_RING_ID_SW2TCL1; tcl_ring = &ab->hal.srng_list[hal_ring_id]; @@ -51,7 +54,7 @@ Signed-off-by: Balamurugan Mahalingam ab->soc_stats.tx_err.desc_na[ring_id]++; ret = -ENOMEM; goto fail_unmap_dma; -@@ -185,7 +184,7 @@ int ath12k_dp_tx_direct(struct ath12k_vi +@@ -229,7 +228,7 @@ int ath12k_dp_tx_direct(struct ath12k_link_vif *arvif, struct sk_buff *skb) tcl_desc.info5 = 0; memcpy(hal_tcl_desc, &tcl_desc, sizeof(tcl_desc)); dsb(st); @@ -60,7 +63,7 @@ Signed-off-by: Balamurugan Mahalingam atomic_inc(&ar->dp.num_tx_pending); -@@ -238,7 +237,7 @@ int ath12k_dp_tx(struct ath12k *ar, stru +@@ -287,7 +286,7 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif, tx_desc = ath12k_dp_tx_assign_buffer_nolock(dp, ti.ring_id); if (unlikely(!tx_desc)) { ab->soc_stats.tx_err.txbuf_na[ti.ring_id]++; @@ -69,13 +72,13 @@ Signed-off-by: Balamurugan Mahalingam } ti.bank_id = arvif->bank_id; -@@ -363,13 +362,13 @@ int ath12k_dp_tx(struct ath12k *ar, stru +@@ -454,13 +453,13 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif, hal_ring_id = tx_ring->tcl_data_ring.ring_id; tcl_ring = &ab->hal.srng_list[hal_ring_id]; - ath12k_hal_srng_access_src_ring_begin_nolock(ab, tcl_ring); + ath12k_hal_srng_access_src_ring_begin_nolock(tcl_ring); - hal_tcl_desc = (void *)ath12k_hal_srng_src_get_next_entry(ab, tcl_ring); + hal_tcl_desc = ath12k_hal_srng_src_get_next_entry(ab, tcl_ring); if (unlikely(!hal_tcl_desc)) { /* NOTE: It is highly unlikely we'll be running out of tcl_ring * desc because the desc is directly enqueued onto hw queue. @@ -85,16 +88,16 @@ Signed-off-by: Balamurugan Mahalingam ab->soc_stats.tx_err.desc_na[ti.ring_id]++; ret = -ENOMEM; -@@ -388,7 +387,7 @@ int ath12k_dp_tx(struct ath12k *ar, stru +@@ -483,7 +482,7 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif, tcl_cmd->info4 = arvif->desc.info4; tcl_cmd->info5 = 0; - dsb(st); + - ath12k_hal_srng_access_umac_src_ring_end_nolock(ab->mem, tcl_ring); + ath12k_hal_srng_access_umac_src_ring_end_nolock(tcl_ring); ath12k_dbg_dump(ab, ATH12K_DBG_DP_TX, NULL, "dp tx msdu: ", skb->data, skb->len); -@@ -857,7 +856,7 @@ int ath12k_dp_tx_completion_handler(stru +@@ -976,7 +975,7 @@ int ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id, valid_entries = ath12k_hal_srng_dst_num_free(ab, status_ring, false); if (!valid_entries) { @@ -103,47 +106,90 @@ Signed-off-by: Balamurugan Mahalingam return 0; } -@@ -951,7 +950,7 @@ int ath12k_dp_tx_completion_handler(stru +@@ -1072,7 +1071,7 @@ int ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id, + skb_ext_desc, tx_ring->tcl_data_ring_id); } } - - ath12k_hal_srng_access_umac_dst_ring_end_nolock(ab->mem, status_ring); + ath12k_hal_srng_access_umac_dst_ring_end_nolock(status_ring); dev_kfree_skb_list_fast(&free_list_head); return (orig_budget - budget); +diff --git a/drivers/net/wireless/ath/ath12k/hal.c b/drivers/net/wireless/ath/ath12k/hal.c +index cea5562..98b6aa2 100644 --- a/drivers/net/wireless/ath/ath12k/hal.c +++ b/drivers/net/wireless/ath/ath12k/hal.c -@@ -1371,6 +1371,12 @@ int ath12k_hal_srng_setup(struct ath12k_ +@@ -2024,16 +2024,23 @@ int ath12k_hal_srng_setup(struct ath12k_base *ab, enum hal_ring_type type, + srng->u.src_ring.low_threshold = params->low_threshold * + srng->entry_size; if (srng_config->mac_type == ATH12K_HAL_SRNG_UMAC) { - srng->u.src_ring.hp_addr = - (u32 *)((unsigned long)ab->mem + reg_base); -+ if (type == HAL_TCL_DATA) { -+ srng->u.src_ring.hp_addr_direct = -+ (u32 *)((unsigned long)ab->mem + -+ HAL_DP_REG_WINDOW_OFFSET + -+ (reg_base & WINDOW_RANGE_MASK)); +- if (!ab->hw_params->supports_shadow_regs) ++ if (!ab->hw_params->supports_shadow_regs) { + srng->u.src_ring.hp_addr = + (u32 *)((unsigned long)ab->mem + reg_base); +- else +- ath12k_dbg(ab, ATH12K_DBG_HAL, +- "hal type %d ring_num %d reg_base 0x%x shadow 0x%lx\n", +- type, ring_num, +- reg_base, +- (unsigned long)srng->u.src_ring.hp_addr - +- (unsigned long)ab->mem); ++ if (type == HAL_TCL_DATA) { ++ srng->u.src_ring.hp_addr_direct = ++ (u32 *)((unsigned long)ab->mem + ++ HAL_DP_REG_WINDOW_OFFSET + ++ (reg_base & WINDOW_RANGE_MASK)); ++ } ++ } else { ++ ath12k_dbg(ab, ATH12K_DBG_HAL, ++ "hal type %d ring_num %d reg_base 0x%x shadow 0x%lx\n", ++ type, ring_num, ++ reg_base, ++ (unsigned long)srng->u.src_ring.hp_addr - ++ (unsigned long)ab->mem); + } } else { idx = ring_id - HAL_SRNG_RING_ID_DMAC_CMN_ID_START; srng->u.src_ring.hp_addr = (void *)(hal->wrp.vaddr + -@@ -1394,6 +1400,13 @@ int ath12k_hal_srng_setup(struct ath12k_ - srng->u.dst_ring.tp_addr = - (u32 *)((unsigned long)ab->mem + reg_base + - (HAL_REO1_RING_TP - HAL_REO1_RING_HP)); -+ if (type == HAL_WBM2SW_RELEASE) { -+ srng->u.dst_ring.tp_addr_direct = -+ (u32 *)((unsigned long)ab->mem + -+ (reg_base & WINDOW_RANGE_MASK) + -+ HAL_DP_REG_WINDOW_OFFSET + -+ (HAL_REO1_RING_TP - HAL_REO1_RING_HP)); +@@ -2054,17 +2061,25 @@ int ath12k_hal_srng_setup(struct ath12k_base *ab, enum hal_ring_type type, + srng->u.dst_ring.cached_hp = 0; + srng->u.dst_ring.hp_addr = (void *)(hal->rdp.vaddr + ring_id); + if (srng_config->mac_type == ATH12K_HAL_SRNG_UMAC) { +- if (!ab->hw_params->supports_shadow_regs) ++ if (!ab->hw_params->supports_shadow_regs) { + srng->u.dst_ring.tp_addr = + (u32 *)((unsigned long)ab->mem + reg_base + + (HAL_REO1_RING_TP - HAL_REO1_RING_HP)); +- else +- ath12k_dbg(ab, ATH12K_DBG_HAL, +- "type %d ring_num %d target_reg 0x%x shadow 0x%lx\n", +- type, ring_num, +- reg_base + HAL_REO1_RING_TP - HAL_REO1_RING_HP, +- (unsigned long)srng->u.dst_ring.tp_addr - +- (unsigned long)ab->mem); ++ if (type == HAL_WBM2SW_RELEASE) { ++ srng->u.dst_ring.tp_addr_direct = ++ (u32 *)((unsigned long)ab->mem + ++ (reg_base & WINDOW_RANGE_MASK) + ++ HAL_DP_REG_WINDOW_OFFSET + ++ (HAL_REO1_RING_TP - HAL_REO1_RING_HP)); ++ } ++ } else { ++ ath12k_dbg(ab, ATH12K_DBG_HAL, ++ "type %d ring_num %d target_reg 0x%x shadow 0x%lx\n", ++ type, ring_num, ++ reg_base + HAL_REO1_RING_TP - HAL_REO1_RING_HP, ++ (unsigned long)srng->u.dst_ring.tp_addr - ++ (unsigned long)ab->mem); + } } else { /* For PMAC & DMAC rings, tail pointer updates will be done * through FW by writing to a shared memory location +diff --git a/drivers/net/wireless/ath/ath12k/hal.h b/drivers/net/wireless/ath/ath12k/hal.h +index aeebf1d..4702ee2 100644 --- a/drivers/net/wireless/ath/ath12k/hal.h +++ b/drivers/net/wireless/ath/ath12k/hal.h -@@ -728,6 +728,7 @@ struct hal_srng { +@@ -749,6 +749,7 @@ struct hal_srng { * accessed through SW structure */ u32 *tp_addr; @@ -151,7 +197,7 @@ Signed-off-by: Balamurugan Mahalingam /* Current SW loop cnt */ u32 loop_cnt; -@@ -757,6 +758,7 @@ struct hal_srng { +@@ -778,6 +779,7 @@ struct hal_srng { * through SW structure */ u32 *hp_addr; @@ -159,7 +205,7 @@ Signed-off-by: Balamurugan Mahalingam /* Low threshold - in number of ring entries */ u32 low_threshold; -@@ -1207,8 +1209,7 @@ u32 *ath12k_hal_srng_src_get_next_entry_ +@@ -1237,8 +1239,7 @@ u32 *ath12k_hal_srng_src_get_next_entry_nolock(struct ath12k_base *ab, } static inline @@ -169,7 +215,7 @@ Signed-off-by: Balamurugan Mahalingam { srng->u.src_ring.cached_tp = *(volatile u32 *)srng->u.src_ring.tp_addr; } -@@ -1224,26 +1225,19 @@ void ath12k_hal_srng_access_dst_ring_beg +@@ -1254,26 +1255,19 @@ void ath12k_hal_srng_access_dst_ring_begin_nolock(struct ath12k_base *ab, } static inline @@ -200,17 +246,21 @@ Signed-off-by: Balamurugan Mahalingam srng->timestamp = jiffies; } +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index 2d86b08..950a29a 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c -@@ -6867,9 +6867,8 @@ static void ath12k_mac_op_tx(struct ieee +@@ -8425,8 +8425,8 @@ static void ath12k_mac_op_tx(struct ieee80211_hw *hw, if (skb->fast_xmit) { ret = ath12k_dp_tx_direct(arvif, skb); if (unlikely(ret)) { -- ar = arvif->ar; - ath12k_warn(ar->ab, "failed to transmit frame %d\n", - ret); + ath12k_dbg(arvif->ar->ab, ATH12K_DBG_MAC, + "failed to transmit frame %d\n", ret); - dev_kfree_skb_any(skb); + ieee80211_free_txskb(hw, skb); } return; +-- +2.7.4 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/720-mac80211-update-radar_required-in-channel-context-af.patch b/feeds/ipq95xx/mac80211/patches/qca/720-mac80211-update-radar_required-in-channel-context-af.patch new file mode 100644 index 000000000..026866228 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/720-mac80211-update-radar_required-in-channel-context-af.patch @@ -0,0 +1,35 @@ +From ee01c944e997bd3fcd4c9796a83647bdffe0dd12 Mon Sep 17 00:00:00 2001 +From: Ramya Gnanasekar +Date: Tue, 14 Mar 2023 14:23:31 +0530 +Subject: [PATCH] mac80211: update radar_required in channel context after + channel switch + +When the channel switch has been made, a vif will use the +channel context which was reserved. Channel context and channel +definition in sdata will also be updated accordingly. +In this case, radar required parameter passed from NL stored as +reserved_radar_required should also be updated to sdata. + +When channel is switched from 80 MHz to 160 MHz where primary 80 MHz +is non DFS and secondary 80 MHz channels are DFS channels, radar +required in channel switch parameters will be true but it is not +updated to sdata when using reserved channel context. + +This flag is used by ath12k driver to inform that the channel is radar +enabled to firmware during vdev start/restart. +Update the radar required flag to fix the same. + +Signed-off-by: Ramya Gnanasekar + +Index: b/net/mac80211/chan.c +=================================================================== +--- a/net/mac80211/chan.c 2023-03-15 10:01:10.452997998 +0530 ++++ b/net/mac80211/chan.c 2023-03-15 10:02:12.820479698 +0530 +@@ -1301,6 +1301,7 @@ ieee80211_link_use_reserved_reassign(str + + list_del(&link->reserved_chanctx_list); + link->reserved_chanctx = NULL; ++ link->radar_required = link->reserved_radar_required; + + err = drv_switch_vif_chanctx(local, vif_chsw, 1, + CHANCTX_SWMODE_REASSIGN_VIF); diff --git a/feeds/ipq95xx/mac80211/patches/qca/721-UPSTREAM-wifi-nl80211-fix-NULL-ptr-deref-in-offchan-check.patch b/feeds/ipq95xx/mac80211/patches/qca/721-UPSTREAM-wifi-nl80211-fix-NULL-ptr-deref-in-offchan-check.patch new file mode 100644 index 000000000..e8c56978c --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/721-UPSTREAM-wifi-nl80211-fix-NULL-ptr-deref-in-offchan-check.patch @@ -0,0 +1,33 @@ +From ed041cbe7220e73537d21f483ffe0bf6a3e5d9f6 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Wed, 22 Mar 2023 14:28:08 +0530 +Subject: [PATCH] wifi: nl80211: fix NULL-ptr deref in offchan check + +If, e.g. in AP mode, the link was already created by userspace +but not activated yet, it has a chandef but the chandef isn't +valid and has no channel. Check for this and ignore this link. + +Fixes: 7b0a0e3c3a88 ("wifi: cfg80211: do some rework towards MLO link APIs") +Signed-off-by: Johannes Berg +Signed-off-by: Gregory Greenman +Signed-off-by: Aditya Kumar Singh +--- + net/wireless/nl80211.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 6e532c518242..ee88a2f2ac1d 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -9534,7 +9534,7 @@ static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev, + struct cfg80211_chan_def *chandef; + + chandef = wdev_chandef(wdev, link_id); +- if (!chandef) ++ if (!chandef || !chandef->chan) + continue; + + /* +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/721-a-ath12k-Add-locks-while-processing-Tx-completion.patch b/feeds/ipq95xx/mac80211/patches/qca/721-a-ath12k-Add-locks-while-processing-Tx-completion.patch new file mode 100644 index 000000000..7df107876 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/721-a-ath12k-Add-locks-while-processing-Tx-completion.patch @@ -0,0 +1,65 @@ +From f5fe62d5eb40ecb54c6a55fc60bd42e9c345ce5a Mon Sep 17 00:00:00 2001 +From: Ramanathan Choodamani +Date: Wed, 8 Mar 2023 00:18:44 -0800 +Subject: [PATCH] ath12k: Add locks while processing Tx completion + +Adding the locks back while processing the tx completion path, to +avoid race. + +Signed-off-by: Ramanathan Choodamani +--- + drivers/net/wireless/ath/ath12k/dp_tx.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -72,25 +72,30 @@ static void ath12k_dp_tx_release_txbuf(s + { + tx_desc->skb = NULL; + tx_desc->skb_ext_desc = NULL; ++ spin_lock_bh(&dp->tx_desc_lock[ring_id]); + list_move_tail(&tx_desc->list, &dp->tx_desc_free_list[ring_id]); ++ spin_unlock_bh(&dp->tx_desc_lock[ring_id]); + } + + static inline +-struct ath12k_tx_desc_info *ath12k_dp_tx_assign_buffer_nolock(struct ath12k_dp *dp, ++struct ath12k_tx_desc_info *ath12k_dp_tx_assign_buffer(struct ath12k_dp *dp, + u8 pool_id) + { + struct ath12k_tx_desc_info *desc = NULL; + ++ spin_lock_bh(&dp->tx_desc_lock[pool_id]); + desc = list_first_entry_or_null(&dp->tx_desc_free_list[pool_id], + struct ath12k_tx_desc_info, + list); + if (!desc) { + ath12k_dbg(dp->ab, ATH12K_DBG_DP_TX, "failed to allocate data Tx desc\n"); ++ spin_unlock_bh(&dp->tx_desc_lock[pool_id]); + return NULL; + } + + prefetch(desc); + list_move_tail(&desc->list, &dp->tx_desc_used_list[pool_id]); ++ spin_unlock_bh(&dp->tx_desc_lock[pool_id]); + + return desc; + } +@@ -173,7 +178,7 @@ int ath12k_dp_tx_direct(struct ath12k_li + + tx_ring = &dp->tx_ring[ring_id]; + +- tx_desc = ath12k_dp_tx_assign_buffer_nolock(dp, ring_id); ++ tx_desc = ath12k_dp_tx_assign_buffer(dp, ring_id); + if (unlikely(!tx_desc)) { + ab->soc_stats.tx_err.txbuf_na[ring_id]++; + return -ENOSPC; +@@ -286,7 +291,7 @@ int ath12k_dp_tx(struct ath12k *ar, stru + + tx_ring = &dp->tx_ring[ti.ring_id]; + +- tx_desc = ath12k_dp_tx_assign_buffer_nolock(dp, ti.ring_id); ++ tx_desc = ath12k_dp_tx_assign_buffer(dp, ti.ring_id); + if (unlikely(!tx_desc)) { + ab->soc_stats.tx_err.txbuf_na[ti.ring_id]++; + return -ENOMEM; diff --git a/feeds/ipq95xx/mac80211/patches/qca/721-b-ath12k-Set-correct-tx-bw-when-EHT-op-present.patch b/feeds/ipq95xx/mac80211/patches/qca/721-b-ath12k-Set-correct-tx-bw-when-EHT-op-present.patch new file mode 100644 index 000000000..9126aad44 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/721-b-ath12k-Set-correct-tx-bw-when-EHT-op-present.patch @@ -0,0 +1,29 @@ +From a8fc83929f07981a3b0e853e3cf45178a07b59a0 Mon Sep 17 00:00:00 2001 +From: Ramanathan Choodamani +Date: Wed, 8 Mar 2023 00:28:09 -0800 +Subject: [PATCH] ath12k: Set correct tx_bw when EHT OP is present + +Allow correct phymode to be set when +EHT320 is present. + +Signed-off-by: Ramanathan Choodamani +--- + net/mac80211/vht.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c +index 63b2181..001b533 100644 +--- a/net/mac80211/vht.c ++++ b/net/mac80211/vht.c +@@ -345,7 +345,7 @@ ieee80211_sta_cap_rx_bw(struct link_sta_info *link_sta) + * specific check for now. + */ + if (eht_cap->has_eht && +- link_conf->chandef.chan->band != NL80211_BAND_6GHZ) { ++ link_conf->chandef.chan->band != NL80211_BAND_2GHZ) { + info = eht_cap->eht_cap_elem.phy_cap_info[0]; + + if (info & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ) { +-- +2.7.4 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/722-ath12k-fix-usage-of-same-vdev_id-for-same-soc.patch b/feeds/ipq95xx/mac80211/patches/qca/722-ath12k-fix-usage-of-same-vdev_id-for-same-soc.patch new file mode 100644 index 000000000..eca58817b --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/722-ath12k-fix-usage-of-same-vdev_id-for-same-soc.patch @@ -0,0 +1,139 @@ +From 9d666eda50b8623af32e6724e34644e63721afb6 Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Tue, 21 Mar 2023 21:07:03 +0530 +Subject: [PATCH] wifi: ath12k: fix usage of same vdev_id for same soc + +when stability test is ran with multiple combination of +mesh interfaces, monitor interfaces and virtual AP interfaces, +firmware assert is seen with the reason of same vdev_id used +for two interfaces in same soc. + +This is because, whenever vdev_id is assigned it is protected +by ar locks and the updation of free vdev is done only after wmi +command successful which are not sufficient in case of split mac cases, +where more than one radio is present in an soc, and it does not protect +under race condition where two interface simultaneously fetch the same +vdev id when one of the interface is still processing its wmi command. + +To handle the same, add changes to protect the free_vdev_map with +ab locks as well as update the free_vdev_map as soon as fetched for +assignment without waiting for wmi command result. + +Signed-off-by: Harshitha Prem +--- + drivers/net/wireless/ath/ath12k/mac.c | 25 +++++++++++++++++++++++-- + 1 file changed, 23 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -1191,7 +1191,10 @@ static int ath12k_mac_monitor_vdev_creat + return -ENOMEM; + } + ++ spin_lock_bh(&ar->ab->base_lock); + bit = __ffs64(ar->ab->free_vdev_map); ++ ar->ab->free_vdev_map &= ~(1LL << bit); ++ spin_unlock_bh(&ar->ab->base_lock); + + ar->monitor_vdev_id = bit; + +@@ -1215,6 +1218,9 @@ static int ath12k_mac_monitor_vdev_creat + if (ret) { + ath12k_warn(ar->ab, "failed to request monitor vdev %i creation: %d\n", + ar->monitor_vdev_id, ret); ++ spin_lock_bh(&ar->ab->base_lock); ++ ar->ab->free_vdev_map |= 1LL << (ar->monitor_vdev_id); ++ spin_unlock_bh(&ar->ab->base_lock); + ar->monitor_vdev_id = -1; + return ret; + } +@@ -1233,7 +1239,6 @@ static int ath12k_mac_monitor_vdev_creat + return ret; + + ar->allocated_vdev_map |= 1LL << ar->monitor_vdev_id; +- ar->ab->free_vdev_map &= ~(1LL << ar->monitor_vdev_id); + ar->num_created_vdevs++; + set_bit(MONITOR_VDEV_CREATED, &ar->monitor_flags); + +@@ -1268,9 +1273,11 @@ static int ath12k_mac_monitor_vdev_delet + ath12k_warn(ar->ab, "Timeout in receiving vdev delete response\n"); + } else { + ar->allocated_vdev_map &= ~(1LL << ar->monitor_vdev_id); ++ spin_lock_bh(&ar->ab->base_lock); + ar->ab->free_vdev_map |= 1LL << (ar->monitor_vdev_id); + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac monitor vdev %d deleted\n", + ar->monitor_vdev_id); ++ spin_unlock_bh(&ar->ab->base_lock); + ar->num_created_vdevs--; + ar->monitor_vdev_id = -1; + clear_bit(MONITOR_VDEV_CREATED, &ar->monitor_flags); +@@ -4701,7 +4708,10 @@ static int ath12k_mac_vdev_delete(struct + goto clean_up; + } + ++ spin_lock_bh(&ar->ab->base_lock); + ar->ab->free_vdev_map |= 1LL << arvif->vdev_id; ++ spin_unlock_bh(&ar->ab->base_lock); ++ + ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id); + ar->ab->free_vdev_stats_id_map &= ~(1LL << arvif->vdev_stats_id); + ar->num_created_vdevs--; +@@ -9461,13 +9471,18 @@ static int ath12k_mac_vdev_create(struct + } + } + ++ spin_lock_bh(&ar->ab->base_lock); ++ + if (!ab->free_vdev_map) { ++ spin_unlock_bh(&ar->ab->base_lock); + ath12k_warn(ar->ab, "failed to create vdev. No free vdev id left.\n"); + ret = -EINVAL; + goto err; + } + + vdev_id = __ffs64(ab->free_vdev_map); ++ ab->free_vdev_map &= ~(1LL << vdev_id); ++ spin_unlock_bh(&ar->ab->base_lock); + + arvif->vdev_id = vdev_id; + /* Assume it as non-mbssid initially, well overwrite it later. +@@ -9522,6 +9537,10 @@ static int ath12k_mac_vdev_create(struct + if (ret) { + ath12k_warn(ab, "failed to create WMI vdev %d: %d\n", + arvif->vdev_id, ret); ++ spin_lock_bh(&ar->ab->base_lock); ++ ab->free_vdev_map |= 1LL << arvif->vdev_id; ++ spin_unlock_bh(&ar->ab->base_lock); ++ + goto err; + } + +@@ -9532,7 +9551,6 @@ static int ath12k_mac_vdev_create(struct + link_addr, arvif->vdev_id); + + ar->allocated_vdev_map |= 1LL << arvif->vdev_id; +- ab->free_vdev_map &= ~(1LL << arvif->vdev_id); + + spin_lock_bh(&ar->data_lock); + list_add(&arvif->list, &ar->arvifs); +@@ -9666,7 +9684,9 @@ err_vdev_del: + ar->num_created_vdevs--; + arvif->is_created = false; + ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id); ++ spin_lock_bh(&ar->ab->base_lock); + ab->free_vdev_map |= 1LL << arvif->vdev_id; ++ spin_unlock_bh(&ar->ab->base_lock); + ab->free_vdev_stats_id_map &= ~(1LL << arvif->vdev_stats_id); + spin_lock_bh(&ar->data_lock); + list_del(&arvif->list); +@@ -15095,7 +15115,10 @@ int ath12k_mac_allocate(struct ath12k_hw + + /* Initialize channel counters frequency value in hertz */ + ab->cc_freq_hz = 320000; ++ ++ spin_lock_bh(&ab->base_lock); + ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS)) - 1; ++ spin_unlock_bh(&ab->base_lock); + + ath12k_dp_pdev_pre_alloc(ab); + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/722-cfg80211-add-support-for-mlo-mon-to-set-add-del-chan.patch b/feeds/ipq95xx/mac80211/patches/qca/722-cfg80211-add-support-for-mlo-mon-to-set-add-del-chan.patch new file mode 100644 index 000000000..d8f2150eb --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/722-cfg80211-add-support-for-mlo-mon-to-set-add-del-chan.patch @@ -0,0 +1,283 @@ +From 642959241c8e5830ce68b0cb8a0ad818d8550e0c Mon Sep 17 00:00:00 2001 +From: Karthikeyan Kathirvel +Date: Sun, 26 Mar 2023 00:38:33 +0530 +Subject: [PATCH] cfg80211: add support for mlo mon to set/add/del channel + +This change is to add support for mlo monitor with set, add, and +del. + +To capture multiple channels in a single netdev execute following cmd +iw phy0 interface add mon0 type monitor + +Either the channel can be set before IFUP or default channel will be +configured. + +To stop capturing on a channel in mlo mode, set the current channel +again to stop capturing it. + +For instance, if mon0 is capturing 2ghz(Channel : 6) and 5ghz (Channel : +36), to stop capturing on 5ghz set channel 36 on mon0 to stop capturing +it. + +Signed-off-by: Karthikeyan Kathirvel +--- + include/net/cfg80211.h | 17 +++++++++++++++++ + include/uapi/linux/nl80211.h | 9 +++++++++ + net/wireless/chan.c | 22 ++++++++++++++++++++++ + net/wireless/core.h | 6 ++++++ + net/wireless/nl80211.c | 9 ++++++++- + net/wireless/rdev-ops.h | 22 ++++++++++++++++++++++ + net/wireless/trace.h | 32 ++++++++++++++++++++++++++++++++ + net/wireless/util.c | 20 ++++++++++++++++++++ + 8 files changed, 136 insertions(+), 1 deletion(-) + +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -4581,6 +4581,12 @@ struct cfg80211_ops { + int (*set_monitor_channel)(struct wiphy *wiphy, + struct cfg80211_chan_def *chandef); + ++ int (*add_monitor_channel)(struct wiphy *wiphy, ++ struct cfg80211_chan_def *chandef); ++ ++ int (*del_monitor_channel)(struct wiphy *wiphy, ++ struct cfg80211_chan_def *chandef); ++ + int (*scan)(struct wiphy *wiphy, + struct cfg80211_scan_request *request); + void (*abort_scan)(struct wiphy *wiphy, struct wireless_dev *wdev); +@@ -8956,6 +8962,17 @@ bool cfg80211_per_hw_iface_comb_advertis + int cfg80211_get_hw_idx_by_chan(struct wiphy *wiphy, + const struct ieee80211_channel *chan); + ++/** ++ * cfg80211_get_hw_idx_by_freq - get the hw index by the frequency ++ * ++ * @wiphy: the wiphy ++ * @freq: Frequency for which the matching hw idx is required ++ * ++ * returns -1 in case the freq is not supported by any of the constituent ++ * hw ++ */ ++int cfg80211_get_hw_idx_by_freq(struct wiphy *wiphy, int freq); ++ + /* + * cfg80211_stop_iface - trigger interface disconnection + * +--- a/include/uapi/linux/nl80211.h ++++ b/include/uapi/linux/nl80211.h +@@ -2820,6 +2820,12 @@ enum nl80211_commands { + * corresponds to the lowest 20MHZ channel. Each bit set to 1 + * indicates that radar is detected in that sub-channel. + * ++ * @NL80211_ATTR_ADD_MULTI_CHAN: Add channel to the radio, this is used ++ * for monitor interface (u32). ++ * ++ * @NL80211_ATTR_DEL_MULTI_CHAN: Delete channel from the radio, this is used ++ * for monitor interface (u32). ++ * + * @NUM_NL80211_ATTR: total number of nl80211_attrs available + * @NL80211_ATTR_MAX: highest attribute number currently defined + * @__NL80211_ATTR_AFTER_LAST: internal use +@@ -3375,6 +3381,9 @@ enum nl80211_attrs { + NL80211_ATTR_RADAR_BITMAP, + + NL80211_ATTR_EHT_240MHZ_CAPABILITY, ++ ++ NL80211_ATTR_ADD_MULTI_CHAN, ++ NL80211_ATTR_DEL_MULTI_CHAN, + /* add attributes here, update the policy in nl80211.c */ + + __NL80211_ATTR_AFTER_LAST, +--- a/net/wireless/chan.c ++++ b/net/wireless/chan.c +@@ -1585,6 +1585,28 @@ int cfg80211_set_monitor_channel(struct + return rdev_set_monitor_channel(rdev, chandef); + } + ++int cfg80211_add_monitor_channel(struct cfg80211_registered_device *rdev, ++ struct cfg80211_chan_def *chandef) ++{ ++ if (!rdev->ops->add_monitor_channel) ++ return -EOPNOTSUPP; ++ if (!cfg80211_has_monitors_only(rdev)) ++ return -EBUSY; ++ ++ return rdev_add_monitor_channel(rdev, chandef); ++} ++ ++int cfg80211_del_monitor_channel(struct cfg80211_registered_device *rdev, ++ struct cfg80211_chan_def *chandef) ++{ ++ if (!rdev->ops->del_monitor_channel) ++ return -EOPNOTSUPP; ++ if (!cfg80211_has_monitors_only(rdev)) ++ return -EBUSY; ++ ++ return rdev_del_monitor_channel(rdev, chandef); ++} ++ + bool cfg80211_any_usable_channels(struct wiphy *wiphy, + unsigned long sband_mask, + u32 prohibited_flags) +--- a/net/wireless/core.h ++++ b/net/wireless/core.h +@@ -515,6 +515,12 @@ static inline unsigned int elapsed_jiffi + int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, + struct cfg80211_chan_def *chandef); + ++int cfg80211_add_monitor_channel(struct cfg80211_registered_device *rdev, ++ struct cfg80211_chan_def *chandef); ++ ++int cfg80211_del_monitor_channel(struct cfg80211_registered_device *rdev, ++ struct cfg80211_chan_def *chandef); ++ + int ieee80211_get_ratemask(struct ieee80211_supported_band *sband, + const u8 *rates, unsigned int n_rates, + u32 *mask); +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -873,6 +873,8 @@ static const struct nla_policy nl80211_p + { .type = NLA_BINARY, + .len = NL80211_EHT240_MAX_CAPABILITY_LEN }, + #endif ++ [NL80211_ATTR_ADD_MULTI_CHAN] = { .type = NLA_U32 }, ++ [NL80211_ATTR_DEL_MULTI_CHAN] = { .type = NLA_U32 }, + }; + + /* policy for the key attributes */ +@@ -3633,7 +3635,12 @@ static int __nl80211_set_channel(struct + case NL80211_IFTYPE_MESH_POINT: + return cfg80211_set_mesh_channel(rdev, wdev, &chandef); + case NL80211_IFTYPE_MONITOR: +- return cfg80211_set_monitor_channel(rdev, &chandef); ++ if (info->attrs[NL80211_ATTR_ADD_MULTI_CHAN]) ++ return cfg80211_add_monitor_channel(rdev, &chandef); ++ else if (info->attrs[NL80211_ATTR_DEL_MULTI_CHAN]) ++ return cfg80211_del_monitor_channel(rdev, &chandef); ++ else ++ return cfg80211_set_monitor_channel(rdev, &chandef); + default: + break; + } +--- a/net/wireless/rdev-ops.h ++++ b/net/wireless/rdev-ops.h +@@ -442,6 +442,28 @@ rdev_set_monitor_channel(struct cfg80211 + return ret; + } + ++static inline int ++rdev_add_monitor_channel(struct cfg80211_registered_device *rdev, ++ struct cfg80211_chan_def *chandef) ++{ ++ int ret; ++ trace_rdev_add_monitor_channel(&rdev->wiphy, chandef); ++ ret = rdev->ops->add_monitor_channel(&rdev->wiphy, chandef); ++ trace_rdev_return_int(&rdev->wiphy, ret); ++ return ret; ++} ++ ++static inline int ++rdev_del_monitor_channel(struct cfg80211_registered_device *rdev, ++ struct cfg80211_chan_def *chandef) ++{ ++ int ret; ++ trace_rdev_del_monitor_channel(&rdev->wiphy, chandef); ++ ret = rdev->ops->del_monitor_channel(&rdev->wiphy, chandef); ++ trace_rdev_return_int(&rdev->wiphy, ret); ++ return ret; ++} ++ + static inline int rdev_scan(struct cfg80211_registered_device *rdev, + struct cfg80211_scan_request *request) + { +--- a/net/wireless/trace.h ++++ b/net/wireless/trace.h +@@ -1244,6 +1244,38 @@ TRACE_EVENT(rdev_set_monitor_channel, + WIPHY_PR_ARG, CHAN_DEF_PR_ARG) + ); + ++TRACE_EVENT(rdev_add_monitor_channel, ++ TP_PROTO(struct wiphy *wiphy, ++ struct cfg80211_chan_def *chandef), ++ TP_ARGS(wiphy, chandef), ++ TP_STRUCT__entry( ++ WIPHY_ENTRY ++ CHAN_DEF_ENTRY ++ ), ++ TP_fast_assign( ++ WIPHY_ASSIGN; ++ CHAN_DEF_ASSIGN(chandef); ++ ), ++ TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT, ++ WIPHY_PR_ARG, CHAN_DEF_PR_ARG) ++); ++ ++TRACE_EVENT(rdev_del_monitor_channel, ++ TP_PROTO(struct wiphy *wiphy, ++ struct cfg80211_chan_def *chandef), ++ TP_ARGS(wiphy, chandef), ++ TP_STRUCT__entry( ++ WIPHY_ENTRY ++ CHAN_DEF_ENTRY ++ ), ++ TP_fast_assign( ++ WIPHY_ASSIGN; ++ CHAN_DEF_ASSIGN(chandef); ++ ), ++ TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT, ++ WIPHY_PR_ARG, CHAN_DEF_PR_ARG) ++); ++ + TRACE_EVENT(rdev_auth, + TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, + struct cfg80211_auth_request *req), +--- a/net/wireless/util.c ++++ b/net/wireless/util.c +@@ -2278,6 +2278,26 @@ cfg80211_get_hw_idx_by_chan(struct wiphy + } + EXPORT_SYMBOL(cfg80211_get_hw_idx_by_chan); + ++int ++cfg80211_get_hw_idx_by_freq(struct wiphy *wiphy, int freq) ++{ ++ int i; ++ struct ieee80211_chans_per_hw *hw_chans; ++ ++ if (freq <= 0) ++ return -1; ++ ++ for (i = 0; i < wiphy->num_hw; i++) { ++ hw_chans = wiphy->hw_chans[i]; ++ if (hw_chans->n_chans && (freq >= hw_chans->chans[0].center_freq) && ++ (freq <= hw_chans->chans[hw_chans->n_chans - 1].center_freq)) ++ return i; ++ } ++ ++ return -1; ++} ++EXPORT_SYMBOL(cfg80211_get_hw_idx_by_freq); ++ + int cfg80211_iter_combinations(struct wiphy *wiphy, + struct iface_combination_params *params, + void (*iter)(const struct ieee80211_iface_combination *c, +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -103,6 +103,7 @@ static const struct ieee80211_channel at + + static const struct ieee80211_channel ath12k_6ghz_channels[] = { + CHAN6G(1, 5955, 0), ++ CHAN6G(2, 5935, 0), + CHAN6G(5, 5975, 0), + CHAN6G(9, 5995, 0), + CHAN6G(13, 6015, 0), +@@ -161,9 +162,6 @@ static const struct ieee80211_channel at + CHAN6G(225, 7075, 0), + CHAN6G(229, 7095, 0), + CHAN6G(233, 7115, 0), +- +- /* new addition in IEEE Std 802.11ax-2021 */ +- CHAN6G(2, 5935, 0), + }; + + static struct ieee80211_rate ath12k_legacy_rates[] = { diff --git a/feeds/ipq95xx/mac80211/patches/qca/723-mac80211-add-mlo-monitor-support.patch b/feeds/ipq95xx/mac80211/patches/qca/723-mac80211-add-mlo-monitor-support.patch new file mode 100644 index 000000000..6bf0072bc --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/723-mac80211-add-mlo-monitor-support.patch @@ -0,0 +1,912 @@ +From f09803a38e857400355e005681b68a7303202303 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Kathirvel +Date: Sat, 25 Mar 2023 22:53:27 +0530 +Subject: [PATCH 1/2] mac80211: add mlo monitor support + +Add support to capture packets from multiple channels concurrently, +this will be capturing all the packets in a single netdev + +To capture multiple channels in a single netdev execute following cmd +iw phy0 interface add mon0 type monitor + +Either the channel can be set before IFUP or default channel will be +configured. + +The below command helps to add multiple channels to monitor interface +iw dev mon0 add channel 11 +iw dev mon0 add channel 36 +iw dev mon0 add channel 49 6G + +To stop capturing on a channel in mlo mode, + +Channel can be deleted from the monitor interface using below command +iw dev mon0 del channel 36 + +Signed-off-by: Karthikeyan Kathirvel +--- + net/mac80211/cfg.c | 169 ++++++++++++++++++++++++++++++------- + net/mac80211/chan.c | 22 ++++- + net/mac80211/ieee80211_i.h | 5 +- + net/mac80211/iface.c | 158 +++++++++++++++++++++------------- + net/mac80211/main.c | 88 +++++++++++++------ + net/mac80211/rx.c | 16 +++- + net/mac80211/tx.c | 9 +- + net/mac80211/util.c | 55 +++++++----- + 8 files changed, 372 insertions(+), 150 deletions(-) + +diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c +index 6caf3a7a3f06..bfc8f2110c86 100644 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -86,6 +86,7 @@ static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata, + { + struct ieee80211_local *local = sdata->local; + struct ieee80211_sub_if_data *monitor_sdata; ++ int i; + + /* check flags first */ + if (params->flags && ieee80211_sdata_running(sdata)) { +@@ -104,18 +105,21 @@ static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata, + return -EBUSY; + } + +- /* also validate MU-MIMO change */ +- monitor_sdata = wiphy_dereference(local->hw.wiphy, +- local->monitor_sdata); ++ i = 0; ++ do { ++ /* also validate MU-MIMO change */ ++ monitor_sdata = wiphy_dereference(local->hw.wiphy, ++ local->monitor_sdata[i]); + +- if (!monitor_sdata && +- (params->vht_mumimo_groups || params->vht_mumimo_follow_addr)) +- return -EOPNOTSUPP; ++ if (!monitor_sdata && ++ (params->vht_mumimo_groups || params->vht_mumimo_follow_addr)) ++ return -EOPNOTSUPP; + +- /* apply all changes now - no failures allowed */ ++ /* apply all changes now - no failures allowed */ + +- if (monitor_sdata) +- ieee80211_set_mu_mimo_follow(monitor_sdata, params); ++ if (monitor_sdata) ++ ieee80211_set_mu_mimo_follow(monitor_sdata, params); ++ } while (++i < local->hw.wiphy->num_hw); + + if (params->flags) { + if (ieee80211_sdata_running(sdata)) { +@@ -917,15 +921,66 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy, + { + struct ieee80211_local *local = wiphy_priv(wiphy); + struct ieee80211_sub_if_data *sdata; +- int ret = 0; ++ int ret = 0, i, def_idx = 0, hw_idx; + +- if (cfg80211_chandef_identical(&local->monitor_chandef, chandef)) ++ if (wiphy->num_hw) { ++ hw_idx = cfg80211_get_hw_idx_by_chan(local->hw.wiphy, chandef->chan); ++ if (hw_idx >= 0) ++ def_idx = hw_idx; ++ } else if (cfg80211_chandef_identical(&local->monitor_chandef[def_idx], chandef)) + return 0; + + mutex_lock(&local->mtx); + if (local->use_chanctx) { ++ /* Clear all chanctx set only the user chandef */ ++ i = 0; ++ do { ++ sdata = wiphy_dereference(local->hw.wiphy, ++ local->monitor_sdata[i]); ++ if (sdata) ++ ieee80211_link_release_channel(&sdata->deflink); ++ memset(&local->monitor_chandef[i], 0, sizeof(struct cfg80211_chan_def)); ++ } while (++i < local->hw.wiphy->num_hw); + sdata = wiphy_dereference(local->hw.wiphy, +- local->monitor_sdata); ++ local->monitor_sdata[def_idx]); ++ if (sdata) ++ ret = ieee80211_link_use_channel(&sdata->deflink, ++ chandef, ++ IEEE80211_CHANCTX_EXCLUSIVE); ++ } else if (local->open_count == local->monitors) { ++ local->_oper_chandef = *chandef; ++ ieee80211_hw_config(local, 0); ++ } ++ ++ if (ret == 0) ++ local->monitor_chandef[def_idx] = *chandef; ++ mutex_unlock(&local->mtx); ++ ++ return ret; ++} ++ ++static int ieee80211_add_monitor_channel(struct wiphy *wiphy, ++ struct cfg80211_chan_def *chandef) ++{ ++ struct ieee80211_local *local = wiphy_priv(wiphy); ++ struct ieee80211_sub_if_data *sdata; ++ int ret = 0, hw_idx = 0; ++ ++ if (wiphy->num_hw) { ++ hw_idx = cfg80211_get_hw_idx_by_chan(local->hw.wiphy, chandef->chan); ++ if (hw_idx < 0) ++ return -EINVAL; ++ } else { ++ return -ENOTSUPP; ++ } ++ ++ if (cfg80211_chandef_identical(&local->monitor_chandef[hw_idx], chandef)) ++ return 0; ++ ++ mutex_lock(&local->mtx); ++ if (local->use_chanctx) { ++ sdata = wiphy_dereference(local->hw.wiphy, ++ local->monitor_sdata[hw_idx]); + if (sdata) { + ieee80211_link_release_channel(&sdata->deflink); + ret = ieee80211_link_use_channel(&sdata->deflink, +@@ -938,12 +993,49 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy, + } + + if (ret == 0) +- local->monitor_chandef = *chandef; ++ local->monitor_chandef[hw_idx] = *chandef; + mutex_unlock(&local->mtx); + + return ret; + } + ++static int ieee80211_del_monitor_channel(struct wiphy *wiphy, ++ struct cfg80211_chan_def *chandef) ++{ ++ struct ieee80211_local *local = wiphy_priv(wiphy); ++ struct ieee80211_sub_if_data *sdata; ++ int hw_idx = 0; ++ ++ if (wiphy->num_hw) { ++ hw_idx = cfg80211_get_hw_idx_by_chan(local->hw.wiphy, chandef->chan); ++ if (hw_idx < 0) ++ return -EINVAL; ++ } else { ++ return -ENOTSUPP; ++ } ++ ++ /* check only channel and delete it, unlike ++ * add channel checks for chandef ++ */ ++ if (!cfg80211_channel_identical(&local->monitor_chandef[hw_idx].chan, chandef->chan)) ++ return -EINVAL; ++ ++ mutex_lock(&local->mtx); ++ if (local->use_chanctx) { ++ sdata = wiphy_dereference(local->hw.wiphy, ++ local->monitor_sdata[hw_idx]); ++ if (sdata) { ++ ieee80211_link_release_channel(&sdata->deflink); ++ memset(&local->monitor_chandef[hw_idx], 0, sizeof(struct cfg80211_chan_def)); ++ mutex_unlock(&local->mtx); ++ return 0; ++ } ++ } ++ mutex_unlock(&local->mtx); ++ ++ return 0; ++} ++ + static int + ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, + const u8 *resp, size_t resp_len, +@@ -3112,6 +3204,7 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy, + bool update_txp_type = false; + bool has_monitor = false; + struct ieee80211_link_data *link_data; ++ int i, hw_idx = 0; + + if (wdev) { + sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); +@@ -3121,8 +3214,14 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy, + return -ENOLINK; + + if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { ++ if (wiphy->num_hw) { ++ hw_idx = cfg80211_get_hw_idx_by_chan(wiphy, link_data->conf->chandef.chan); ++ if (hw_idx < 0) ++ return -EINVAL; ++ } ++ + sdata = wiphy_dereference(local->hw.wiphy, +- local->monitor_sdata); ++ local->monitor_sdata[hw_idx]); + if (!sdata) + return -EOPNOTSUPP; + } +@@ -3164,7 +3263,6 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy, + break; + } + +- /*TODO: monitor mode for MLO */ + mutex_lock(&local->iflist_mtx); + list_for_each_entry(sdata, &local->interfaces, list) { + if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { +@@ -3184,16 +3282,19 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy, + mutex_unlock(&local->iflist_mtx); + + if (has_monitor) { +- sdata = wiphy_dereference(local->hw.wiphy, +- local->monitor_sdata); +- if (sdata) { +- sdata->deflink.user_power_level = local->user_power_level; +- if (txp_type != sdata->vif.bss_conf.txpower_type) +- update_txp_type = true; +- sdata->vif.bss_conf.txpower_type = txp_type; +- +- ieee80211_recalc_txpower(sdata, update_txp_type, 0); +- } ++ i = 0; ++ do { ++ sdata = wiphy_dereference(local->hw.wiphy, ++ local->monitor_sdata[i]); ++ if (sdata) { ++ sdata->deflink.user_power_level = local->user_power_level; ++ if (txp_type != sdata->vif.bss_conf.txpower_type) ++ update_txp_type = true; ++ sdata->vif.bss_conf.txpower_type = txp_type; ++ ++ ieee80211_recalc_txpower(sdata, update_txp_type, link_id); ++ } ++ } while (++i < local->hw.wiphy->num_hw); + } + + return 0; +@@ -4402,7 +4503,7 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy, + struct ieee80211_local *local = wiphy_priv(wiphy); + struct ieee80211_chanctx_conf *chanctx_conf; + struct ieee80211_link_data *link; +- int ret = -ENODATA; ++ int ret = -ENODATA, i; + + rcu_read_lock(); + link = rcu_dereference(sdata->link[link_id]); +@@ -4418,10 +4519,18 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy, + } else if (local->open_count > 0 && + local->open_count == local->monitors && + sdata->vif.type == NL80211_IFTYPE_MONITOR) { +- if (local->use_chanctx) +- *chandef = local->monitor_chandef; +- else ++ if (local->use_chanctx) { ++ i = 0; ++ do { ++ if (local->monitor_chandef[i].chan) { ++ /* Get a valid chan and return */ ++ *chandef = local->monitor_chandef[i]; ++ break; ++ } ++ } while (++i < local->hw.wiphy->num_hw); ++ } else { + *chandef = local->_oper_chandef; ++ } + ret = 0; + } + out: +@@ -5316,6 +5425,8 @@ const struct cfg80211_ops mac80211_config_ops = { + .change_bss = ieee80211_change_bss, + .set_txq_params = ieee80211_set_txq_params, + .set_monitor_channel = ieee80211_set_monitor_channel, ++ .add_monitor_channel = ieee80211_add_monitor_channel, ++ .del_monitor_channel = ieee80211_del_monitor_channel, + .suspend = ieee80211_suspend, + .resume = ieee80211_resume, + .scan = ieee80211_scan, +diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c +index 7d2631354a92..2354d38c1228 100644 +--- a/net/mac80211/chan.c ++++ b/net/mac80211/chan.c +@@ -337,6 +337,7 @@ ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local, + { + struct ieee80211_sub_if_data *sdata; + enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT; ++ int hw_idx = 0; + + rcu_read_lock(); + list_for_each_entry_rcu(sdata, &local->interfaces, list) { +@@ -350,8 +351,16 @@ ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local, + max_bw = max(max_bw, width); + } + ++ if (local->hw.wiphy->num_hw) { ++ hw_idx = cfg80211_get_hw_idx_by_chan(local->hw.wiphy, conf->def.chan); ++ if (hw_idx < 0) { ++ rcu_read_unlock(); ++ return max_bw; ++ } ++ } ++ + /* use the configured bandwidth in case of monitor interface */ +- sdata = rcu_dereference(local->monitor_sdata); ++ sdata = rcu_dereference(local->monitor_sdata[hw_idx]); + if (sdata && + rcu_access_pointer(sdata->vif.bss_conf.chanctx_conf) == conf) + max_bw = max(max_bw, conf->def.width); +@@ -927,6 +936,7 @@ void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, + { + struct ieee80211_sub_if_data *sdata; + u8 rx_chains_static, rx_chains_dynamic; ++ int hw_idx = 0; + + lockdep_assert_held(&local->chanctx_mtx); + +@@ -990,8 +1000,16 @@ void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, + } + } + ++ if (local->hw.wiphy->num_hw) { ++ hw_idx = cfg80211_get_hw_idx_by_chan(local->hw.wiphy, chanctx->conf.def.chan); ++ if (hw_idx < 0) { ++ rcu_read_unlock(); ++ return; ++ } ++ } ++ + /* Disable SMPS for the monitor interface */ +- sdata = rcu_dereference(local->monitor_sdata); ++ sdata = rcu_dereference(local->monitor_sdata[hw_idx]); + if (sdata && + rcu_access_pointer(sdata->vif.bss_conf.chanctx_conf) == &chanctx->conf) + rx_chains_dynamic = rx_chains_static = local->rx_chains; +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index c525789f808a..1400946c8e08 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1588,8 +1588,9 @@ struct ieee80211_local { + struct ieee80211_sub_if_data __rcu *p2p_sdata; + + /* virtual monitor interface */ +- struct ieee80211_sub_if_data __rcu *monitor_sdata; +- struct cfg80211_chan_def monitor_chandef; ++ struct ieee80211_sub_if_data __rcu **monitor_sdata; ++ struct cfg80211_chan_def *monitor_chandef; ++ bool monitor_sdata_created; + + struct mac80211_memory_stats memory_stats; + struct work_struct awgn_detected_work; +diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c +index 90fad651777d..1a342fb5a154 100644 +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -400,7 +400,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do + unsigned long flags; + struct sk_buff *skb, *tmp; + u32 hw_reconf_flags = 0; +- int i, flushed; ++ int i, flushed, hw_idx = 0; + struct ps_data *ps; + struct cfg80211_chan_def chandef; + bool cancel_scan; +@@ -623,7 +623,14 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do + */ + if (local->suspended) { + WARN_ON(local->wowlan); +- WARN_ON(rcu_access_pointer(local->monitor_sdata)); ++ ++ if (local->hw.wiphy->num_hw) { ++ hw_idx = cfg80211_get_hw_idx_by_chan(local->hw.wiphy, sdata->deflink.conf->chandef.chan); ++ if (hw_idx < 0) ++ return; ++ } ++ ++ WARN_ON(rcu_access_pointer(local->monitor_sdata[hw_idx])); + return; + } + +@@ -1065,7 +1072,7 @@ static void ieee80211_sdata_init(struct ieee80211_local *local, + int ieee80211_add_virtual_monitor(struct ieee80211_local *local) + { + struct ieee80211_sub_if_data *sdata; +- int ret; ++ int ret, i = 0; + + if (!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF)) + return 0; +@@ -1073,99 +1080,128 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local) + ASSERT_RTNL(); + lockdep_assert_wiphy(local->hw.wiphy); + +- if (local->monitor_sdata) ++ if (local->monitor_sdata_created) + return 0; + +- sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL); +- if (!sdata) +- return -ENOMEM; ++ do { ++ mutex_lock(&local->mtx); ++ if (!local->monitor_chandef[i].chan) { ++ if (i < local->hw.wiphy->num_hw) { ++ mutex_unlock(&local->mtx); ++ continue; ++ } ++ } ++ mutex_unlock(&local->mtx); + +- /* set up data */ +- sdata->vif.type = NL80211_IFTYPE_MONITOR; +- snprintf(sdata->name, IFNAMSIZ, "%s-monitor", +- wiphy_name(local->hw.wiphy)); +- sdata->wdev.iftype = NL80211_IFTYPE_MONITOR; ++ sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL); ++ if (!sdata) ++ return -ENOMEM; + +- ieee80211_sdata_init(local, sdata); ++ /* set up data */ ++ sdata->vif.type = NL80211_IFTYPE_MONITOR; ++ snprintf(sdata->name, IFNAMSIZ, "%s-monitor", ++ wiphy_name(local->hw.wiphy)); ++ sdata->wdev.iftype = NL80211_IFTYPE_MONITOR; + +- ieee80211_set_default_queues(sdata); ++ ieee80211_sdata_init(local, sdata); + +- ret = drv_add_interface(local, sdata); +- if (WARN_ON(ret)) { +- /* ok .. stupid driver, it asked for this! */ +- kfree(sdata); +- return ret; +- } ++ ieee80211_set_default_queues(sdata); + +- set_bit(SDATA_STATE_RUNNING, &sdata->state); ++ ret = drv_add_interface(local, sdata); ++ if (WARN_ON(ret)) ++ /* ok .. stupid driver, it asked for this! */ ++ goto free; + +- ret = ieee80211_check_queues(sdata, NL80211_IFTYPE_MONITOR); +- if (ret) { +- kfree(sdata); +- return ret; +- } ++ set_bit(SDATA_STATE_RUNNING, &sdata->state); + +- mutex_lock(&local->iflist_mtx); +- rcu_assign_pointer(local->monitor_sdata, sdata); +- mutex_unlock(&local->iflist_mtx); ++ ret = ieee80211_check_queues(sdata, NL80211_IFTYPE_MONITOR); ++ if (ret) ++ goto free; + +- mutex_lock(&local->mtx); +- ret = ieee80211_link_use_channel(&sdata->deflink, &local->monitor_chandef, +- IEEE80211_CHANCTX_EXCLUSIVE); +- mutex_unlock(&local->mtx); +- if (ret) { + mutex_lock(&local->iflist_mtx); +- RCU_INIT_POINTER(local->monitor_sdata, NULL); ++ rcu_assign_pointer(local->monitor_sdata[i], sdata); ++ local->monitor_sdata_created = true; + mutex_unlock(&local->iflist_mtx); +- synchronize_net(); +- drv_remove_interface(local, sdata); +- kfree(sdata); +- return ret; +- } + +- atomic_add(sizeof(*sdata) + local->hw.vif_data_size, +- &local->memory_stats.malloc_size); ++ mutex_lock(&local->mtx); ++ ret = ieee80211_link_use_channel(&sdata->deflink, &local->monitor_chandef[i], ++ IEEE80211_CHANCTX_EXCLUSIVE); ++ mutex_unlock(&local->mtx); ++ if (ret) ++ goto free; + +- skb_queue_head_init(&sdata->skb_queue); +- skb_queue_head_init(&sdata->status_queue); +- INIT_WORK(&sdata->work, ieee80211_iface_work); ++ atomic_add(sizeof(*sdata) + local->hw.vif_data_size, ++ &local->memory_stats.malloc_size); ++ ++ skb_queue_head_init(&sdata->skb_queue); ++ skb_queue_head_init(&sdata->status_queue); ++ INIT_WORK(&sdata->work, ieee80211_iface_work); ++ } while (++i < local->hw.wiphy->num_hw); + + return 0; ++ ++free: ++ mutex_lock(&local->iflist_mtx); ++ do { ++ RCU_INIT_POINTER(local->monitor_sdata[i], NULL); ++ synchronize_net(); ++ ++ ++ sdata = rcu_dereference_protected(local->monitor_sdata[i], ++ lockdep_is_held(&local->iflist_mtx)); ++ if (!sdata) ++ continue; ++ ++ drv_remove_interface(local, sdata); ++ kfree(sdata); ++ } while (--i >= 0); ++ mutex_unlock(&local->iflist_mtx); ++ local->monitor_sdata_created = false; ++ return ret; + } + + void ieee80211_del_virtual_monitor(struct ieee80211_local *local) + { + struct ieee80211_sub_if_data *sdata; ++ int i; + + if (!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF)) + return; + ++ if (!local->monitor_sdata_created) ++ return; ++ + ASSERT_RTNL(); + lockdep_assert_wiphy(local->hw.wiphy); + +- mutex_lock(&local->iflist_mtx); + +- sdata = rcu_dereference_protected(local->monitor_sdata, +- lockdep_is_held(&local->iflist_mtx)); +- if (!sdata) { ++ i = 0; ++ do { ++ mutex_lock(&local->iflist_mtx); ++ sdata = rcu_dereference_protected(local->monitor_sdata[i], ++ lockdep_is_held(&local->iflist_mtx)); ++ if (!sdata) { ++ mutex_unlock(&local->iflist_mtx); ++ continue; ++ } ++ ++ RCU_INIT_POINTER(local->monitor_sdata[i], NULL); + mutex_unlock(&local->iflist_mtx); +- return; +- } + +- RCU_INIT_POINTER(local->monitor_sdata, NULL); +- mutex_unlock(&local->iflist_mtx); ++ synchronize_net(); + +- synchronize_net(); ++ mutex_lock(&local->mtx); ++ ieee80211_link_release_channel(&sdata->deflink); ++ mutex_unlock(&local->mtx); + +- mutex_lock(&local->mtx); +- ieee80211_link_release_channel(&sdata->deflink); +- mutex_unlock(&local->mtx); ++ drv_remove_interface(local, sdata); + +- drv_remove_interface(local, sdata); ++ atomic_sub(sizeof(*sdata) + local->hw.vif_data_size, ++ &local->memory_stats.malloc_size); ++ kfree(sdata); ++ } while (++i < local->hw.wiphy->num_hw); + +- atomic_sub(sizeof(*sdata) + local->hw.vif_data_size, +- &local->memory_stats.malloc_size); +- kfree(sdata); ++ local->monitor_sdata_created = false; + } + + #ifdef CPTCFG_MAC80211_NSS_SUPPORT +diff --git a/net/mac80211/main.c b/net/mac80211/main.c +index bf8802fe60f1..8a12504fbfce 100644 +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -987,7 +987,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) + enum nl80211_band band; + int channels, max_bitrates; + bool supp_ht, supp_vht, supp_he, supp_eht; +- struct cfg80211_chan_def dflt_chandef = {}; ++ size_t size = 0; ++ int hw_idx = 0, num_hw; + + if (ieee80211_hw_check(hw, QUEUE_CONTROL) && + (local->hw.offchannel_tx_hw_queue == IEEE80211_INVAL_HW_QUEUE || +@@ -1133,35 +1134,56 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) + supp_vht = false; + supp_he = false; + supp_eht = false; ++ ++ if (local->hw.wiphy->num_hw) ++ num_hw = local->hw.wiphy->num_hw; ++ else ++ num_hw = 1; ++ size = sizeof(*local->monitor_chandef) * num_hw; ++ local->monitor_chandef = kzalloc(size, GFP_KERNEL); ++ if (!local->monitor_chandef) ++ return -ENOMEM; ++ ++ size = sizeof(**local->monitor_sdata) * num_hw; ++ local->monitor_sdata = kzalloc(size, GFP_KERNEL); ++ if (!local->monitor_sdata) { ++ kfree(local->monitor_chandef); ++ return -ENOMEM; ++ } ++ + for (band = 0; band < NUM_NL80211_BANDS; band++) { + struct ieee80211_supported_band *sband; ++ struct cfg80211_chan_def dflt_chandef = {}; + + sband = local->hw.wiphy->bands[band]; + if (!sband) + continue; + +- if (!dflt_chandef.chan) { +- /* +- * Assign the first enabled channel to dflt_chandef +- * from the list of channels +- */ +- for (i = 0; i < sband->n_channels; i++) +- if (!(sband->channels[i].flags & ++ /* ++ * Assign the first enabled channel to dflt_chandef ++ * from the list of channels ++ */ ++ for (i = 0; i < sband->n_channels; i++) ++ if (!(sband->channels[i].flags & + IEEE80211_CHAN_DISABLED)) +- break; +- /* if none found then use the first anyway */ +- if (i == sband->n_channels) +- i = 0; +- cfg80211_chandef_create(&dflt_chandef, +- &sband->channels[i], +- NL80211_CHAN_NO_HT); +- /* init channel we're on */ +- if (!local->use_chanctx && !local->_oper_chandef.chan) { +- local->hw.conf.chandef = dflt_chandef; +- local->_oper_chandef = dflt_chandef; +- } +- local->monitor_chandef = dflt_chandef; ++ break; ++ /* if none found then use the first anyway */ ++ if (i == sband->n_channels) ++ i = 0; ++ cfg80211_chandef_create(&dflt_chandef, ++ &sband->channels[i], ++ NL80211_CHAN_NO_HT); ++ /* init channel we're on */ ++ if (!local->use_chanctx && !local->_oper_chandef.chan) { ++ local->hw.conf.chandef = dflt_chandef; ++ local->_oper_chandef = dflt_chandef; + } ++ hw_idx = cfg80211_get_hw_idx_by_chan(local->hw.wiphy, dflt_chandef.chan); ++ if (hw_idx < 0) ++ /* Resetting to use first index for non-MLO case */ ++ hw_idx = 0; ++ ++ local->monitor_chandef[hw_idx] = dflt_chandef; + + channels += sband->n_channels; + +@@ -1181,12 +1203,16 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) + + /* HT, VHT, HE, EHT require QoS, thus >= 4 queues */ + if (WARN_ON(local->hw.queues < IEEE80211_NUM_ACS && +- (supp_ht || supp_vht || supp_he || supp_eht))) +- return -EINVAL; ++ (supp_ht || supp_vht || supp_he || supp_eht))) { ++ result = -EINVAL; ++ goto fail_monitor_chan; ++ } + + /* EHT requires HE support */ +- if (WARN_ON(supp_eht && !supp_he)) +- return -EINVAL; ++ if (WARN_ON(supp_eht && !supp_he)) { ++ result = -EINVAL; ++ goto fail_monitor_chan; ++ } + + if (!sband->ht_cap.ht_supported) + continue; +@@ -1220,8 +1246,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) + + for (j = 0; j < c->n_limits; j++) + if ((c->limits[j].types & BIT(NL80211_IFTYPE_ADHOC)) && +- c->limits[j].max > 1) +- return -EINVAL; ++ c->limits[j].max > 1) { ++ result = -EINVAL; ++ goto fail_monitor_chan; ++ } + } + + local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) + +@@ -1516,6 +1544,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) + if (local->wiphy_ciphers_allocated) + kfree(local->hw.wiphy->cipher_suites); + kfree(local->int_scan_req); ++fail_monitor_chan: ++ kfree(local->monitor_chandef); ++ kfree(local->monitor_sdata); + return result; + } + EXPORT_SYMBOL(ieee80211_register_hw); +@@ -1565,6 +1596,9 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) + destroy_workqueue(local->workqueue); + ieee80211_led_exit(local); + kfree(local->int_scan_req); ++ ++ kfree(local->monitor_chandef); ++ kfree(local->monitor_sdata); + } + EXPORT_SYMBOL(ieee80211_unregister_hw); + +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 3053db03f6e5..227c323f663b 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -866,10 +866,9 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(origskb); + struct ieee80211_sub_if_data *sdata; + struct sk_buff *monskb = NULL; +- int present_fcs_len = 0; ++ int present_fcs_len = 0, hw_idx = 0; + unsigned int rtap_space = 0; +- struct ieee80211_sub_if_data *monitor_sdata = +- rcu_dereference(local->monitor_sdata); ++ struct ieee80211_sub_if_data *monitor_sdata; + bool only_monitor = false; + unsigned int min_head_len; + +@@ -941,6 +940,17 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, + rtap_space); + } + ++ if (local->hw.wiphy->num_hw) { ++ hw_idx = cfg80211_get_hw_idx_by_freq(local->hw.wiphy, status->freq); ++ if (hw_idx < 0) { ++ WARN_ON_ONCE(1); ++ dev_kfree_skb(origskb); ++ return NULL; ++ } ++ } ++ ++ monitor_sdata = rcu_dereference(local->monitor_sdata[hw_idx]); ++ + ieee80211_handle_mu_mimo_mon(monitor_sdata, origskb, rtap_space); + + list_for_each_entry_rcu(sdata, &local->mon_list, u.mntr.list) { +diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c +index 94a8785c9976..0e8988fa9768 100644 +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -1823,7 +1823,10 @@ static bool __ieee80211_tx(struct ieee80211_local *local, + vif = &sdata->vif; + break; + } +- sdata = rcu_dereference(local->monitor_sdata); ++ /* Here we wont know the chan to tx except the band info ++ * so tx in first hw_idx ++ */ ++ sdata = rcu_dereference(local->monitor_sdata[0]); + if (sdata) { + vif = &sdata->vif; + info->hw_queue = +@@ -2427,7 +2430,7 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, + + chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf); + if (!chanctx_conf) { +- tmp_sdata = rcu_dereference(local->monitor_sdata); ++ tmp_sdata = rcu_dereference(local->monitor_sdata[0]); + if (tmp_sdata) + chanctx_conf = + rcu_dereference(tmp_sdata->vif.bss_conf.chanctx_conf); +@@ -3984,7 +3987,7 @@ begin: + vif = &tx.sdata->vif; + break; + } +- tx.sdata = rcu_dereference(local->monitor_sdata); ++ tx.sdata = rcu_dereference(local->monitor_sdata[0]); + if (tx.sdata) { + vif = &tx.sdata->vif; + info->hw_queue = +diff --git a/net/mac80211/util.c b/net/mac80211/util.c +index 0902c8319ed0..e5095f8153ab 100644 +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -759,6 +759,7 @@ static void __iterate_interfaces(struct ieee80211_local *local, + { + struct ieee80211_sub_if_data *sdata; + bool active_only = iter_flags & IEEE80211_IFACE_ITER_ACTIVE; ++ int i; + + list_for_each_entry_rcu(sdata, &local->interfaces, list) { + switch (sdata->vif.type) { +@@ -782,13 +783,16 @@ static void __iterate_interfaces(struct ieee80211_local *local, + &sdata->vif); + } + +- sdata = rcu_dereference_check(local->monitor_sdata, +- lockdep_is_held(&local->iflist_mtx) || +- lockdep_is_held(&local->hw.wiphy->mtx)); +- if (sdata && +- (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL || !active_only || +- sdata->flags & IEEE80211_SDATA_IN_DRIVER)) +- iterator(data, sdata->vif.addr, &sdata->vif); ++ i = 0; ++ do { ++ sdata = rcu_dereference_check(local->monitor_sdata[i], ++ lockdep_is_held(&local->iflist_mtx) || ++ lockdep_is_held(&local->hw.wiphy->mtx)); ++ if (sdata && ++ (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL || !active_only || ++ sdata->flags & IEEE80211_SDATA_IN_DRIVER)) ++ iterator(data, sdata->vif.addr, &sdata->vif); ++ } while (++i < local->hw.wiphy->num_hw); + } + + void ieee80211_iterate_interfaces( +@@ -2488,7 +2492,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) + struct ieee80211_sub_if_data *sdata; + struct ieee80211_chanctx *ctx; + struct sta_info *sta; +- int res; ++ int res, i; + bool reconfig_due_to_wowlan = false; + struct ieee80211_sub_if_data *sched_scan_sdata; + struct cfg80211_sched_scan_request *sched_scan_req; +@@ -2572,18 +2576,21 @@ int ieee80211_reconfig(struct ieee80211_local *local) + ieee80211_mod_tpt_led_trig(local, + IEEE80211_TPT_LEDTRIG_FL_RADIO, 0); + +- /* add interfaces */ +- sdata = wiphy_dereference(local->hw.wiphy, local->monitor_sdata); +- if (sdata) { +- /* in HW restart it exists already */ +- WARN_ON(local->resuming); +- res = drv_add_interface(local, sdata); +- if (WARN_ON(res)) { +- RCU_INIT_POINTER(local->monitor_sdata, NULL); +- synchronize_net(); +- kfree(sdata); ++ i = 0; ++ do { ++ /* add interfaces */ ++ sdata = wiphy_dereference(local->hw.wiphy, local->monitor_sdata[i]); ++ if (sdata) { ++ /* in HW restart it exists already */ ++ WARN_ON(local->resuming); ++ res = drv_add_interface(local, sdata); ++ if (WARN_ON(res)) { ++ RCU_INIT_POINTER(local->monitor_sdata[i], NULL); ++ synchronize_net(); ++ kfree(sdata); ++ } + } +- } ++ } while (++i < local->hw.wiphy->num_hw);; + + list_for_each_entry(sdata, &local->interfaces, list) { + if ((sdata->vif.type != NL80211_IFTYPE_AP_VLAN || +@@ -2620,11 +2627,13 @@ int ieee80211_reconfig(struct ieee80211_local *local) + WARN_ON(drv_add_chanctx(local, ctx)); + mutex_unlock(&local->chanctx_mtx); + +- sdata = wiphy_dereference(local->hw.wiphy, +- local->monitor_sdata); ++ do { ++ sdata = wiphy_dereference(local->hw.wiphy, ++ local->monitor_sdata[i]); + +- if (sdata && ieee80211_sdata_running(sdata)) +- ieee80211_assign_chanctx(local, sdata, &sdata->deflink); ++ if (sdata && ieee80211_sdata_running(sdata)) ++ ieee80211_assign_chanctx(local, sdata, &sdata->deflink); ++ } while (++i < local->hw.wiphy->num_hw); + } + + /* reconfigure hardware */ +-- +2.38.0 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/724-ath12k-avoid-deadlock-during-regulatory-update-.patch b/feeds/ipq95xx/mac80211/patches/qca/724-ath12k-avoid-deadlock-during-regulatory-update-.patch new file mode 100644 index 000000000..cc2eb6afc --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/724-ath12k-avoid-deadlock-during-regulatory-update-.patch @@ -0,0 +1,75 @@ +From 4f0a565b8305a7f689bed22fd4b5055d7abe942b Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Thu, 6 Apr 2023 21:39:33 +0530 +Subject: [PATCH] wifi: ath12k: avoid deadlock during regulatory update in + ath12k_regd_update() + +Running this test in a loop it is easy to reproduce an rtnl deadlock: + +iw reg set FI +ifconfig wlan0 down + +What happens is that thread A (workqueue) tries to update the regulatory by +acquiring the rtnl_lock of ar->regd_update_work and thread B (ifconfig) +tries to stop the interface via cancel_work_sync(&ar->regd_update_work) +in ath12k_mac_op_stop(). + +The sequence of deadlock is: + +1. Thread B calls rtnl_lock(). + +2. Thread A starts to run and calls rtnl_lock() from within + ath12k_regd_update_work(), then enters wait state because the lock is owned by + thread B. + +3. Thread B continues to run and tries to call + cancel_work_sync(&ar->regd_update_work), but thread A is in + ath12k_regd_update_work() waiting for rtnl_lock(). So cancel_work_sync() + forever waits for ath12k_regd_update_work() to finish and we have a deadlock. + +Fix this by switching from using regulatory_set_wiphy_regd_sync() to +regulatory_set_wiphy_regd(). Now cfg80211 will schedule another workqueue which +handles the locking on it's own. So the ath12k workqueue can simply exit without +taking any locks, avoiding the deadlock. + +Signed-off-by: Wen Gong +Signed-off-by: Harshitha Prem +--- + drivers/net/wireless/ath/ath12k/reg.c | 6 +----- + drivers/net/wireless/ath/ath12k/wmi.c | 2 +- + 2 files changed, 2 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/reg.c b/drivers/net/wireless/ath/ath12k/reg.c +index 5e45a0f..4332c27 100644 +--- a/drivers/net/wireless/ath/ath12k/reg.c ++++ b/drivers/net/wireless/ath/ath12k/reg.c +@@ -414,11 +414,7 @@ int ath12k_regd_update(struct ath12k *ar, bool init) + goto err; + } + +- rtnl_lock(); +- wiphy_lock(ah->hw->wiphy); +- ret = regulatory_set_wiphy_regd_sync(ah->hw->wiphy, regd_copy); +- wiphy_unlock(ah->hw->wiphy); +- rtnl_unlock(); ++ ret = regulatory_set_wiphy_regd(ah->hw->wiphy, regd_copy); + + kfree(regd_copy); + +diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c +index 2118b82..d3bf7ce 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -7988,8 +7988,8 @@ static int ath12k_reg_handle_chan_list(struct ath12k_base *ab, + ar = ab->pdevs[pdev_idx].ar; + kfree(ab->new_regd[pdev_idx]); + ab->new_regd[pdev_idx] = regd; ++ queue_work(ab->workqueue, &ar->regd_update_work); + +- ieee80211_queue_work(ar->ah->hw, &ar->regd_update_work); + } else { + /* Multiple events for the same *ar is not expected. But we + * can still clear any previously stored default_regd if we +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/725-ath12k-fix-incorrect-beacon-template-update-during-C.patch b/feeds/ipq95xx/mac80211/patches/qca/725-ath12k-fix-incorrect-beacon-template-update-during-C.patch new file mode 100644 index 000000000..047b6669a --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/725-ath12k-fix-incorrect-beacon-template-update-during-C.patch @@ -0,0 +1,205 @@ +From 64434af4f02ad71c7e9402cd680fa8fc73c6ae4a Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Fri, 21 Apr 2023 13:21:00 +0530 +Subject: [PATCH] ath12k: fix incorrect beacon template update during CSA + +Once CSA finish is called, mac80211 changes the channel context via +reserved switch first and then schedules the CSA finish work which +then updates the link's CSA active state as well as the beacon. While +the reserved switch is hapenning, mac80211 calls the driver callback. +In this callback, ath12k performs the vdev restart and since it was +already up, it tries to install the beacon template again. However +this is wrong since at this point the beacon is not yet updated and +hence the beacon update will be the older beacon only. + +Fix this issue by not installing the beacon template if CSA active +state is present in the link. When the beacon template is actually +updated, bss link info changed notify will take care to update the +beacon and also bring the vdev up. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/mac.c | 66 +++++++++++++++++++++++++- + 2 files changed, 65 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -380,6 +380,7 @@ struct ath12k_link_vif { + struct ath12k_vif *ahvif; + + bool mvr_processing; ++ bool pending_csa_up; + }; + + struct ath12k_vif { +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -4278,9 +4278,11 @@ static void ath12k_mac_bss_info_changed( + struct ieee80211_bss_conf *info, + u64 changed) + { +- struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ath12k_vif *ahvif = arvif->ahvif, *tx_ahvif; ++ struct ath12k_link_vif *tx_arvif; + struct ieee80211_vif *vif = ahvif->vif; + struct cfg80211_chan_def def; ++ struct vdev_up_params params = { 0 }; + u32 param_id, param_value; + enum nl80211_band band; + u32 vdev_param; +@@ -4327,12 +4329,67 @@ static void ath12k_mac_bss_info_changed( + + if ((!arvif->do_not_send_tmpl || !arvif->bcca_zero_sent) && + arvif->is_started) { ++ /* need to install Transmitting vif's template first */ ++ + ret = ath12k_mac_setup_bcn_tmpl(arvif); + if (ret) + ath12k_warn(ar->ab, "failed to update bcn template: %d\n", + ret); +- } + ++ if (!arvif->pending_csa_up) ++ goto skip_pending_cs_up; ++ ++ memset(¶ms, 0, sizeof(params)); ++ params.vdev_id = arvif->vdev_id; ++ params.aid = ahvif->aid; ++ params.bssid = arvif->bssid; ++ ++ if (info->mbssid_tx_vif) { ++ tx_ahvif = (void *)info->mbssid_tx_vif->drv_priv; ++ tx_arvif = tx_ahvif->link[info->mbssid_tx_vif_linkid]; ++ params.tx_bssid = tx_arvif->bssid; ++ params.profile_idx = ahvif->vif->bss_conf.bssid_index; ++ params.profile_count = tx_arvif->nontransmitting_vif_count; ++ } ++ ++ if (info->mbssid_tx_vif && arvif != tx_arvif && ++ tx_arvif->pending_csa_up) { ++ /* skip non tx vif's */ ++ goto skip_pending_cs_up; ++ } ++ ++ ret = ath12k_wmi_vdev_up(arvif->ar, ¶ms); ++ if (ret) ++ ath12k_warn(ar->ab, "failed to bring vdev up %d: %d\n", ++ arvif->vdev_id, ret); ++ ++ arvif->pending_csa_up = false; ++ ++ if (info->mbssid_tx_vif && arvif == tx_arvif) { ++ struct ath12k_link_vif *arvif_itr; ++ list_for_each_entry(arvif_itr, &ar->arvifs, list) { ++ if (!arvif_itr->pending_csa_up) ++ continue; ++ ++ memset(¶ms, 0, sizeof(params)); ++ params.vdev_id = arvif_itr->vdev_id; ++ params.aid = ahvif->aid; ++ params.bssid = arvif_itr->bssid; ++ params.tx_bssid = tx_arvif->bssid; ++ params.profile_idx = ++ ahvif->vif->bss_conf.bssid_index; ++ params.profile_count = ++ tx_arvif->nontransmitting_vif_count; ++ ++ ret = ath12k_wmi_vdev_up(arvif_itr->ar, ¶ms); ++ if (ret) ++ ath12k_warn(ar->ab, "failed to bring vdev up %d: %d\n", ++ arvif_itr->vdev_id, ret); ++ arvif_itr->pending_csa_up = false; ++ } ++ } ++ } ++skip_pending_cs_up: + if (arvif->bcca_zero_sent) + arvif->do_not_send_tmpl = true; + else +@@ -10590,6 +10647,9 @@ static int ath12k_vdev_restart_sequence( + } + + beacon_tmpl_setup: ++ if (arvif->pending_csa_up) ++ return 0; ++ + if (!arvif->is_up) + return -EOPNOTSUPP; + +@@ -11013,6 +11073,7 @@ ath12k_mac_update_vif_chan(struct ath12k + int i, trans_vdev_index; + u64 vif_down_failed_map = 0; + struct ieee80211_vif *tx_vif; ++ struct ieee80211_bss_conf *link; + + /* Each vif is mapped to each bit of vif_down_failed_map. */ + if (n_vifs > sizeof(vif_down_failed_map)*__CHAR_BIT__) { +@@ -11068,6 +11129,14 @@ ath12k_mac_update_vif_chan(struct ath12k + ath12k_mac_update_rx_channel(ar, NULL, vifs, n_vifs); + + if (tx_arvif) { ++ rcu_read_lock(); ++ link = rcu_dereference(ahvif->vif->link_conf[tx_arvif->link_id]); ++ ++ if (link->csa_active && tx_arvif->ahvif->vdev_type == WMI_VDEV_TYPE_AP) ++ tx_arvif->pending_csa_up = true; ++ ++ rcu_read_unlock(); ++ + ret = ath12k_vdev_restart_sequence(tx_arvif, + vifs[trans_vdev_index].new_ctx, + vif_down_failed_map, +@@ -11089,6 +11158,14 @@ ath12k_mac_update_vif_chan(struct ath12k + arvif == tx_arvif) + continue; + ++ rcu_read_lock(); ++ link = rcu_dereference(ahvif->vif->link_conf[arvif->link_id]); ++ ++ if (link->csa_active && arvif->ahvif->vdev_type == WMI_VDEV_TYPE_AP) ++ arvif->pending_csa_up = true; ++ ++ rcu_read_unlock(); ++ + ret = ath12k_vdev_restart_sequence(arvif, + vifs[i].new_ctx, + vif_down_failed_map, i); +@@ -11112,6 +11189,7 @@ ath12k_mac_update_vif_chan_mvr(struct at + struct ieee80211_vif *tx_vif; + int ret, i, time_left, trans_vdev_index, vdev_idx, n_vdevs = 0; + u32 vdev_ids[TARGET_NUM_VDEVS]; ++ struct ieee80211_bss_conf *link; + + lockdep_assert_held(&ar->conf_mutex); + +@@ -11189,6 +11267,14 @@ ath12k_mac_update_vif_chan_mvr(struct at + tx_arvif->vdev_id); + } + ++ rcu_read_lock(); ++ link = rcu_dereference(ahvif->vif->link_conf[tx_arvif->link_id]); ++ ++ if (link->csa_active && tx_arvif->ahvif->vdev_type == WMI_VDEV_TYPE_AP) ++ tx_arvif->pending_csa_up = true; ++ ++ rcu_read_unlock(); ++ + ret = ath12k_vdev_restart_sequence(tx_arvif, + vifs[trans_vdev_index].new_ctx, + BIT_ULL(trans_vdev_index), +@@ -11219,6 +11305,14 @@ ath12k_mac_update_vif_chan_mvr(struct at + arvif->vdev_id); + } + ++ rcu_read_lock(); ++ link = rcu_dereference(ahvif->vif->link_conf[arvif->link_id]); ++ ++ if (link->csa_active && arvif->ahvif->vdev_type == WMI_VDEV_TYPE_AP) ++ arvif->pending_csa_up = true; ++ ++ rcu_read_unlock(); ++ + ret = ath12k_vdev_restart_sequence(arvif, vifs[i].new_ctx, + BIT_ULL(i), vdev_idx); + if (ret && ret != -EOPNOTSUPP) diff --git a/feeds/ipq95xx/mac80211/patches/qca/725-mac80211-fix-null-pointer-access-for-AP-VLAN.patch b/feeds/ipq95xx/mac80211/patches/qca/725-mac80211-fix-null-pointer-access-for-AP-VLAN.patch new file mode 100644 index 000000000..ed40b9f9d --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/725-mac80211-fix-null-pointer-access-for-AP-VLAN.patch @@ -0,0 +1,81 @@ +From 7ace85ca706b96cc58b95e29b4ecb875212bc075 Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Tue, 25 Apr 2023 09:54:11 +0530 +Subject: [PATCH] mac80211: fix null pointer access for AP/VLAN + +During wds bring up on EHT mode, following null pointer +crash is seen randomly. + +ieee80211_sta_cap_rx_bw+0x48/0xf4 [mac80211] +ieee80211_set_qos_hdr+0x124/0x1ac [mac80211] +ieee80211_iter_chan_contexts_atomic+0x48c/0x95c [mac80211] +ieee80211_recalc_chanctx_min_def+0x50/0x418 [mac80211] +ieee80211_recalc_min_chandef+0x94/0xa4 [mac80211] +sta_info_move_state+0x17c/0x250 [mac80211] +ieee80211_channel_switch+0xdc8/0x1fe4 [mac80211] +ieee80211_channel_switch+0x12fc/0x1fe4 [mac80211] +ieee80211_channel_switch+0x15b4/0x1fe4 [mac80211] +__cfg80211_send_event_skb+0x23ac/0x43c8 [cfg80211] +genl_family_rcv_msg+0x314/0x3b0 +genl_rcv_msg+0x58/0x84 +netlink_rcv_skb+0x94/0x10c +genl_rcv+0x34/0x48 +netlink_unicast+0x15c/0x248 +netlink_sendmsg+0x320/0x3bc +sock_sendmsg+0x18/0x2c +____sys_sendmsg+0x2c4/0x350 +___sys_sendmsg+0x7c/0xc4 +__sys_sendmsg+0x64/0xac +__arm64_sys_sendmsg+0x1c/0x24 +el0_svc_common.constprop.0+0x98/0x114 +el0_svc_handler+0x18/0x20 + +When analyzed further, we could see that the channel info was null +for AP/VLAN interface as it was accessed from link id. Currently, +in SLO WDS, we are not creating the AP/VLAN interface as per link +and the link_conf did not have valid data. + +Hence, add changes to get the link_conf based on the valid links +check. + +Signed-off-by: Harshitha Prem +--- + net/mac80211/vht.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c +index 001b533..d5f0d5b 100644 +--- a/net/mac80211/vht.c ++++ b/net/mac80211/vht.c +@@ -338,13 +338,16 @@ ieee80211_sta_cap_rx_bw(struct link_sta_info *link_sta) + u8 info; + + rcu_read_lock(); +- link_conf = rcu_dereference(sdata->vif.link_conf[link_id]); ++ if (sdata->vif.valid_links) ++ link_conf = rcu_dereference(sdata->vif.link_conf[link_id]); ++ else ++ link_conf = &sdata->vif.bss_conf; + + /* TODO: 5GHz is reusing the same PHY capability + * to advertise the 320MHz support. Removind band + * specific check for now. + */ +- if (eht_cap->has_eht && ++ if (eht_cap->has_eht && link_conf->chandef.chan && + link_conf->chandef.chan->band != NL80211_BAND_2GHZ) { + info = eht_cap->eht_cap_elem.phy_cap_info[0]; + +@@ -356,7 +359,8 @@ ieee80211_sta_cap_rx_bw(struct link_sta_info *link_sta) + + info = he_cap->he_cap_elem.phy_cap_info[0]; + +- if (link_conf->chandef.chan->band == NL80211_BAND_2GHZ) { ++ if (link_conf->chandef.chan && ++ link_conf->chandef.chan->band == NL80211_BAND_2GHZ) { + if (info & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G) + ret = IEEE80211_STA_RX_BW_40; + else +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/726-ath12k-add-beacon-protection-support-for-ath12k.patch b/feeds/ipq95xx/mac80211/patches/qca/726-ath12k-add-beacon-protection-support-for-ath12k.patch new file mode 100644 index 000000000..e05e9ea30 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/726-ath12k-add-beacon-protection-support-for-ath12k.patch @@ -0,0 +1,85 @@ +From a5eb6c8b1358083577d84f8bae9f3e6177ae0e29 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Kathirvel +Date: Fri, 21 Apr 2023 23:06:50 +0530 +Subject: [PATCH] ath12k: add beacon protection support for ath12k +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +AP provisions its clients with the AP’s Beacon Integrity Key during +security association setup and adds a message integrity check (MIC) +element to Beacon frames that covers all but the timestamp field of +the Beacon frame contents. This allows clients that are associated +with the AP to verify the Beacon frame integrity, and detect active +attacks that forge or modify Beacon frames. This prevents active +attacks in which the Beacon frame IEs are altered to cause client +devices to, for example, consume more power, use lower data rates, +or incorrectly switch channels. + +Sample IE format in beacon: + + Tag: Management MIC + Tag Number: Management MIC (76) + Tag length: 16 + KeyID: 6 + IPN: 010000000000 + MIC: 581e118108cccf9f + +Signed-off-by: Karthikeyan Kathirvel +--- + drivers/net/wireless/ath/ath12k/mac.c | 7 +++++-- + drivers/net/wireless/ath/ath12k/wmi.h | 2 +- + 2 files changed, 6 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -5307,6 +5307,16 @@ static int ath12k_install_key(struct ath + case WLAN_CIPHER_SUITE_GCMP_256: + arg.key_cipher = WMI_CIPHER_AES_GCM; + break; ++ case WLAN_CIPHER_SUITE_AES_CMAC: ++ arg.key_cipher = WMI_CIPHER_AES_CMAC; ++ break; ++ case WLAN_CIPHER_SUITE_BIP_GMAC_128: ++ case WLAN_CIPHER_SUITE_BIP_GMAC_256: ++ arg.key_cipher = WMI_CIPHER_AES_GMAC; ++ break; ++ case WLAN_CIPHER_SUITE_BIP_CMAC_256: ++ arg.key_cipher = WMI_CIPHER_NONE; ++ break; + default: + ath12k_warn(ar->ab, "cipher %d is not supported\n", key->cipher); + return -EOPNOTSUPP; +@@ -5520,11 +5530,8 @@ static int ath12k_mac_op_set_key(struct + + mutex_lock(&ah->conf_mutex); + +- /* BIP needs to be done in software */ +- if (key->cipher == WLAN_CIPHER_SUITE_AES_CMAC || +- key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 || +- key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 || +- key->cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256) { ++ /* IGTK needs to be done in host software */ ++ if (key->keyidx == 4 || key->keyidx == 5) { + ret = 1; + goto out; + } +@@ -14778,6 +14785,7 @@ static int ath12k_mac_hw_register(struct + wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); + wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_STA_TX_PWR); + wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT); ++ wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_BEACON_PROTECTION); + + if (test_bit(WMI_TLV_SERVICE_BSS_COLOR_OFFLOAD, ab->wmi_ab.svc_map)) + wiphy_ext_feature_set(hw->wiphy, +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -5439,7 +5439,7 @@ enum wmi_ap_ps_peer_param { + + #define DISABLE_SIFS_RESPONSE_TRIGGER 0 + +-#define WMI_MAX_KEY_INDEX 3 ++#define WMI_MAX_KEY_INDEX 7 + #define WMI_MAX_KEY_LEN 32 + + #define WMI_KEY_PAIRWISE 0x00 diff --git a/feeds/ipq95xx/mac80211/patches/qca/726-cfg80211-mac80211-SLO-WDS-link-add.patch b/feeds/ipq95xx/mac80211/patches/qca/726-cfg80211-mac80211-SLO-WDS-link-add.patch new file mode 100644 index 000000000..eabf29d1c --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/726-cfg80211-mac80211-SLO-WDS-link-add.patch @@ -0,0 +1,189 @@ +From d26647b6f536034cb5c55d1142f514bc5cee0d4b Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Wed, 26 Apr 2023 11:15:54 +0530 +Subject: [PATCH] cfg80211/mac80211: SLO WDS link add + +Currently,when EHT WDS virtual ap interface is +brought up multiple crashes and warn ons are seen +as it is not fully supported yet. + +In order to handle this, link id information on which +WDS STA was trying to associate should be passed from hostapd +to create the AP/VLAN interface which is part of +MLO+WDS feature (yet to be supported). + +Until then, use master VAP's link for creating AP/VLAN +interface regardless of the WDS STA associated link. + +Signed-off-by: Harshitha Prem +--- + net/mac80211/chan.c | 6 ++++++ + net/mac80211/iface.c | 23 ++++++++++++++++++++++- + net/wireless/util.c | 3 ++- + 3 files changed, 30 insertions(+), 2 deletions(-) + +--- a/net/mac80211/chan.c ++++ b/net/mac80211/chan.c +@@ -1072,6 +1072,9 @@ __ieee80211_link_copy_chanctx_to_vlans(s + if (WARN_ON(!vlan_conf)) + continue; + ++ if (rcu_access_pointer(sdata->vif.link_conf[link_id]) == vlan_conf) ++ continue; ++ + rcu_assign_pointer(vlan_conf->chanctx_conf, conf); + } + rcu_read_unlock(); +@@ -2069,6 +2072,14 @@ void ieee80211_link_vlan_copy_chanctx(st + if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->bss)) + return; + ++ /* TODO: This check would help only for SLO WDS VAP. For MLO WDS VAP, ++ we have to extend the logic for all the links ++ */ ++ if (sdata->vif.valid_links) { ++ link_id = ffs(sdata->vif.valid_links) - 1; ++ link_conf = rcu_dereference(sdata->vif.link_conf[link_id]); ++ } ++ + ap = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap); + + mutex_lock(&local->chanctx_mtx); +@@ -2078,9 +2089,6 @@ void ieee80211_link_vlan_copy_chanctx(st + conf = rcu_dereference_protected(ap_conf->chanctx_conf, + lockdep_is_held(&local->chanctx_mtx)); + rcu_assign_pointer(link_conf->chanctx_conf, conf); +- memcpy(&sdata->vif.link_conf[link_id]->chandef, +- &ap->vif.link_conf[link_id]->chandef, +- sizeof(struct cfg80211_chan_def)); + rcu_read_unlock(); + mutex_unlock(&local->chanctx_mtx); + } +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -405,6 +405,7 @@ static void ieee80211_do_stop(struct iee + struct cfg80211_chan_def chandef; + bool cancel_scan; + struct cfg80211_nan_func *func; ++ int link_id; + + clear_bit(SDATA_STATE_RUNNING, &sdata->state); + synchronize_rcu(); /* flush _ieee80211_wake_txqs() */ +@@ -433,6 +434,13 @@ static void ieee80211_do_stop(struct iee + break; + list_del_rcu(&sdata->u.mntr.list); + break; ++ case NL80211_IFTYPE_AP_VLAN: ++ for_each_set_bit(link_id, &sdata->vif.valid_links, IEEE80211_MLD_MAX_NUM_LINKS) { ++ rcu_assign_pointer(sdata->vif.link_conf[link_id], NULL); ++ rcu_assign_pointer(sdata->link[link_id], NULL); ++ } ++ sdata->vif.valid_links = 0; ++ break; + default: + break; + } +@@ -1381,7 +1389,30 @@ int ieee80211_do_open(struct wireless_de + memcpy(sdata->vif.hw_queue, master->vif.hw_queue, + sizeof(sdata->vif.hw_queue)); + sdata->vif.bss_conf.chandef = master->vif.bss_conf.chandef; ++ if (master->vif.valid_links) { ++ int link_id; ++ unsigned long add = master->vif.valid_links; ++ unsigned long rem = 0xffff & ~master->vif.valid_links; ++ ++ for_each_set_bit(link_id, &add, ++ IEEE80211_MLD_MAX_NUM_LINKS) { ++ wdev->valid_links |= BIT(link_id); ++ ether_addr_copy(wdev->links[link_id].addr, ++ master->wdev.links[link_id].addr); ++ rcu_assign_pointer(sdata->vif.link_conf[link_id], ++ master->vif.link_conf[link_id]); ++ rcu_assign_pointer(sdata->link[link_id], ++ master->link[link_id]); ++ } + ++ for_each_set_bit(link_id, &rem, ++ IEEE80211_MLD_MAX_NUM_LINKS) { ++ rcu_assign_pointer(sdata->vif.link_conf[link_id], NULL); ++ rcu_assign_pointer(sdata->link[link_id], NULL); ++ } ++ ++ sdata->vif.valid_links = master->vif.valid_links; ++ } + mutex_lock(&local->key_mtx); + sdata->crypto_tx_tailroom_needed_cnt += + master->crypto_tx_tailroom_needed_cnt; +--- a/net/wireless/util.c ++++ b/net/wireless/util.c +@@ -2781,7 +2781,8 @@ void cfg80211_remove_link(struct wireles + + wdev->valid_links &= ~BIT(link_id); + +- rdev_del_intf_link(rdev, wdev, link_id); ++ if (wdev->iftype != NL80211_IFTYPE_AP_VLAN) ++ rdev_del_intf_link(rdev, wdev, link_id); + + eth_zero_addr(wdev->links[link_id].addr); + } +--- a/net/mac80211/link.c ++++ b/net/mac80211/link.c +@@ -17,6 +17,36 @@ void ieee80211_link_setup(struct ieee802 + ieee80211_mgd_setup_link(link); + } + ++static void ieee80211_update_apvlan_links(struct ieee80211_sub_if_data *sdata) ++{ ++ struct ieee80211_sub_if_data *vlan; ++ ++ list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) { ++ int link_id; ++ unsigned long add = sdata->vif.valid_links; ++ unsigned long rem = 0xffff & ~sdata->vif.valid_links; ++ ++ if (!vlan) ++ continue; ++ ++ for_each_set_bit(link_id, &add, ++ IEEE80211_MLD_MAX_NUM_LINKS) { ++ rcu_assign_pointer(vlan->vif.link_conf[link_id], ++ sdata->vif.link_conf[link_id]); ++ rcu_assign_pointer(vlan->link[link_id], ++ sdata->link[link_id]); ++ } ++ ++ for_each_set_bit(link_id, &rem, ++ IEEE80211_MLD_MAX_NUM_LINKS) { ++ rcu_assign_pointer(vlan->vif.link_conf[link_id], NULL); ++ rcu_assign_pointer(vlan->link[link_id], NULL); ++ } ++ ++ vlan->vif.valid_links = sdata->vif.valid_links; ++ } ++} ++ + void ieee80211_link_init(struct ieee80211_sub_if_data *sdata, + int link_id, + struct ieee80211_link_data *link, +@@ -49,6 +79,9 @@ void ieee80211_link_init(struct ieee8021 + link->ap_power_level = IEEE80211_UNSET_POWER_LEVEL; + link->user_power_level = local->user_power_level; + ++ if (sdata->vif.type == NL80211_IFTYPE_AP) ++ ieee80211_update_apvlan_links(sdata); ++ + if (!deflink) { + switch (sdata->vif.type) { + case NL80211_IFTYPE_AP: +@@ -207,6 +240,11 @@ static int ieee80211_vif_update_links(st + + memset(to_free, 0, sizeof(links)); + ++ /* TODO: currently, SLO wds AP/VLAN's link pointer is same as master VAP ++ hence, skip update link for AP_VLAN */ ++ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) ++ return 0; ++ + if (old_links == new_links) + return 0; + diff --git a/feeds/ipq95xx/mac80211/patches/qca/726-mac80211-fix-crash-when-accessing-null-pointer.patch b/feeds/ipq95xx/mac80211/patches/qca/726-mac80211-fix-crash-when-accessing-null-pointer.patch new file mode 100644 index 000000000..3a849e09a --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/726-mac80211-fix-crash-when-accessing-null-pointer.patch @@ -0,0 +1,92 @@ +From 376306e1018974ded893d8fefb91fe69676392d9 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Kathirvel +Date: Mon, 1 May 2023 15:15:56 +0530 +Subject: [PATCH] mac80211: fix crash when accessing null pointer + +During MLD transmission, band will be zero, fetching 0th sband will be an +invalid accessing of sband information and also facing crash when 2ghz +radio is in different phy and other bands are in a single phy, this is +due to 2.4 Ghz sband will be NULL for the phy which is having sbands other +than 2.4 Ghz. + +Fix this by adding sband NULL check. + +[ 2125.764601] Unable to handle kernel read from unreadable memory at virtual address 0000000000000050 +[ 2125.764631] Mem abort info: +[ 2125.772445] ESR = 0x96000005 +[ 2125.775221] EC = 0x25: DABT (current EL), IL = 32 bits +[ 2125.778339] SET = 0, FnV = 0 +[ 2125.783804] EA = 0, S1PTW = 0 +[ 2125.786669] Data abort info: +[ 2125.789707] ISV = 0, ISS = 0x00000005 +[ 2125.792833] CM = 0, WnR = 0 +[ 2125.796394] user pgtable: 4k pages, 39-bit VAs, pgdp=000000006432b000 +[ 2125.799520] [0000000000000050] pgd=0000000000000000, pud=0000000000000000 +[ 2125.805946] Internal error: Oops: 96000005 [#1] PREEMPT SMP +[ 2126.082240] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.4.213 #0 +[ 2126.110546] pstate: 40400005 (nZcv daif +PAN -UAO) +[ 2126.117591] pc : ieee80211_tx_monitor+0x1ac/0x5d0 [mac80211] +[ 2126.122360] lr : ieee80211_tx_monitor+0x14c/0x5d0 [mac80211] +[ 2126.128163] sp : ffffff803e14ecc0 +[ 2126.133803] x29: ffffff803e14ecc0 x28: 000000000000000d +[ 2126.137016] x27: 0000000000000000 x26: ffffff803892aa40 +[ 2126.142398] x25: 0000000000000009 x24: 0000000000000000 +[ 2126.147694] x23: 0000000000000001 x22: ffffff80250210e0 +[ 2126.152988] x21: ffffff803a0a5800 x20: ffffff803a0a5828 +[ 2126.158284] x19: ffffff803892aa33 x18: 0000000000000000 +[ 2126.163579] x17: 0000000000000000 x16: 0000000000000000 +[ 2126.168873] x15: 0000000000000000 x14: 020101f0fd8c13dd +[ 2126.174169] x13: 00c0bf3d2d200706 x12: 3809ff36b83b03ff +[ 2126.179464] x11: 0a5802c3fe1802c3 x10: 002f3262005e4342 +[ 2126.184759] x9 : 0000a4270000a403 x8 : ffffff803892aa3f +[ 2126.190055] x7 : 0000000000000000 x6 : 0000000000000001 +[ 2126.195349] x5 : ffffff803e14edd8 x4 : 0000000000000001 +[ 2126.200644] x3 : 000000000000000c x2 : 0000000000000000 +[ 2126.205939] x1 : ffffff803892aa3b x0 : 0000000000000040 +[ 2126.211235] Call trace: +[ 2126.216542] ieee80211_tx_monitor+0x1ac/0x5d0 [mac80211] +[ 2126.218714] ieee80211_tx_status_ext+0x78c/0x7d0 [mac80211] +[ 2126.224269] ieee80211_tx_status+0x78/0xa0 [mac80211] +[ 2126.229564] ieee80211_restart_hw+0xe0/0x26c [mac80211] +[ 2126.234763] tasklet_action_common.isra.2+0xa4/0x11c +[ 2126.239795] tasklet_action+0x24/0x2c +[ 2126.245002] __do_softirq+0x10c/0x244 +[ 2126.248561] irq_exit+0x64/0xb4 +[ 2126.252207] __handle_domain_irq+0x88/0xac +[ 2126.255158] gic_handle_irq+0x74/0xbc +[ 2126.259325] el1_irq+0xf0/0x1c0 +[ 2126.263058] arch_cpu_idle+0x10/0x18 +[ 2126.266009] do_idle+0x104/0x248 +[ 2126.269827] cpu_startup_entry+0x20/0x64 +[ 2126.273041] rest_init+0xd0/0xdc +[ 2126.276947] arch_call_rest_init+0xc/0x14 +[ 2126.280159] start_kernel+0x46c/0x4a4 +[ 2126.284070] Code: d37d0863 8b030042 52800183 f9449c42 (f9402842) +[ 2126.287713] ---[ end trace 04f5d203895d53da ]--- + +Signed-off-by: Karthikeyan Kathirvel +--- + net/mac80211/status.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/net/mac80211/status.c b/net/mac80211/status.c +index 2002578f572e..29a0041b931c 100644 +--- a/net/mac80211/status.c ++++ b/net/mac80211/status.c +@@ -336,8 +336,11 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local, + struct ieee80211_supported_band *sband; + + sband = local->hw.wiphy->bands[info->band]; +- legacy_rate = +- sband->bitrates[info->status.rates[0].idx].bitrate; ++ //TODO: Incase of MLD, band will be 0 for tx pkts ++ //this has to be taken care during TX monitor support. ++ if (sband) ++ legacy_rate = ++ sband->bitrates[info->status.rates[0].idx].bitrate; + } + + if (legacy_rate) { +-- +2.38.0 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/727-ath12k-rate-info-is-not-properly-updated-for-tx-pkts.patch b/feeds/ipq95xx/mac80211/patches/qca/727-ath12k-rate-info-is-not-properly-updated-for-tx-pkts.patch new file mode 100644 index 000000000..224cc112e --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/727-ath12k-rate-info-is-not-properly-updated-for-tx-pkts.patch @@ -0,0 +1,57 @@ +From 7e8dc7b3fbb4acea3f0238cad2ef851a67fad3b2 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Kathirvel +Date: Thu, 8 Jun 2023 21:01:57 +0530 +Subject: [PATCH] ath12k: rate info is not properly updated for tx cmpl pkts + +The rate info is not properly set in tx complete handler and so the tx +status is not properly updated to the mac80211, which fails updating +mesh metric calculation. + +Fix the rate info by updating driver rate status from tx completion +feedback. + +Below commit caused the rate info update failure for ath12k and hence +updated the rate in tx completion + +commit 44fa75f207d8a106bc75e6230db61e961fdbf8a8 +Author: Jonas Jelonek +Date: Mon May 9 19:39:57 2022 +0200 + mac80211: extend current rate control tx status API +Link: +https://lore.kernel.org/r/20220509173958.1398201-2-jelonek.jonas@gmail.com + +Signed-off-by: Karthikeyan Kathirvel +--- + drivers/net/wireless/ath/ath12k/dp_tx.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c +index d03194737deb..f8b8d77cbf74 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -1007,6 +1007,7 @@ static void ath12k_dp_tx_complete_msdu(struct ath12k *ar, + int ring) + { + struct ieee80211_tx_status status = { 0 }; ++ struct ieee80211_rate_status status_rate = { 0 }; + struct ath12k_base *ab = ar->ab; + struct ieee80211_tx_info *info; + struct ath12k_skb_cb *skb_cb; +@@ -1122,7 +1123,13 @@ static void ath12k_dp_tx_complete_msdu(struct ath12k *ar, + status.skb = msdu; + status.info = info; + rate = arsta->last_txrate; +- status.rates = &rate; ++ ++ status_rate.rate_idx = rate; ++ status_rate.try_count = 1; ++ ++ status.rates = &status_rate; ++ status.n_rates = 1; ++ + + if (unlikely(ath12k_debugfs_is_extd_tx_stats_enabled(ar))) { + if(arsta->wbm_tx_stats && wbm_status < HAL_WBM_REL_HTT_TX_COMP_STATUS_MAX) +-- +2.38.0 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/728-ath12k-drop-the-non-transmitted-failure-tx-frames.patch b/feeds/ipq95xx/mac80211/patches/qca/728-ath12k-drop-the-non-transmitted-failure-tx-frames.patch new file mode 100644 index 000000000..c5b938543 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/728-ath12k-drop-the-non-transmitted-failure-tx-frames.patch @@ -0,0 +1,40 @@ +From 63f7d32eed37e56c5de7b0140b81f70388d15d69 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Kathirvel +Date: Tue, 13 Jun 2023 11:43:25 +0530 +Subject: [PATCH] ath12k: drop the non transmitted failure tx frames + +In mesh node traffic, internal fw tx failures are reported as a +transmitted failure to mesh metric calculation and hence mesh link is +broken. + +Fix the issue by dropping the internal fw tx failures at driver which +prevents false failure averaging of mesh metric calculation. + +Signed-off-by: Karthikeyan Kathirvel +--- + drivers/net/wireless/ath/ath12k/dp_tx.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -915,6 +915,20 @@ static void ath12k_dp_tx_complete_msdu(s + (info->flags & IEEE80211_TX_CTL_NO_ACK)) + info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; + ++ if (ts.status != HAL_WBM_TQM_REL_REASON_FRAME_ACKED) { ++ switch (ts.status) { ++ case HAL_WBM_TQM_REL_REASON_CMD_REMOVE_MPDU: ++ case HAL_WBM_TQM_REL_REASON_DROP_THRESHOLD: ++ case HAL_WBM_TQM_REL_REASON_CMD_REMOVE_AGED_FRAMES: ++ case HAL_WBM_TQM_REL_REASON_CMD_REMOVE_TX: ++ dev_kfree_skb_any(msdu); ++ return; ++ default: ++ //TODO: Remove this print and add as a stats ++ ath12k_dbg(ab, ATH12K_DBG_DP_TX, "tx frame is not acked status %d\n", ts.status); ++ } ++ } ++ + if (unlikely(ath12k_debugfs_is_extd_tx_stats_enabled(ar)) || + ab->hw_params->single_pdev_only) { + if (ts.flags & HAL_TX_STATUS_FLAGS_FIRST_MSDU) { diff --git a/feeds/ipq95xx/mac80211/patches/qca/746-ath12k-parse-the-mlo-mem-and-get-the-reo-snapshot-de.patch b/feeds/ipq95xx/mac80211/patches/qca/746-ath12k-parse-the-mlo-mem-and-get-the-reo-snapshot-de.patch new file mode 100644 index 000000000..1270e6b2d --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/746-ath12k-parse-the-mlo-mem-and-get-the-reo-snapshot-de.patch @@ -0,0 +1,957 @@ +From 1e5af18b38348548fc6b40c508d83b6669606f1a Mon Sep 17 00:00:00 2001 +From: Karthikeyan Kathirvel +Date: Mon, 6 Feb 2023 12:20:31 +0530 +Subject: [PATCH 1/3] ath12k: parse the mlo mem and get the reo snapshot + details + +Parse the shared mlo memory between host and firmware to get the snapshot +details without any delay. This snapshot information is used to compute +the reo rx reordering process accurately. + +Signed-off-by: Karthikeyan Kathirvel +--- + drivers/net/wireless/ath/ath12k/core.c | 1 + + drivers/net/wireless/ath/ath12k/core.h | 2 + + drivers/net/wireless/ath/ath12k/qmi.c | 534 +++++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/wmi.h | 270 +++++++++++++ + 4 files changed, 807 insertions(+) + +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -136,6 +136,7 @@ ath12k_core_hw_group_alloc(u8 id, u8 max + ag->mlo_capable = !!ath12k_mlo_capable; + list_add(&ag->list, &ath12k_hw_groups); + mutex_init(&ag->mutex_lock); ++ mutex_init(&ag->mlomem_arena.mutex_lock); + ag->hw_queues_stopped = false; + + return ag; +@@ -1269,6 +1270,8 @@ int ath12k_core_qmi_firmware_ready(struc + + mutex_unlock(&ag->mutex_lock); + ++ ath12k_qmi_mlo_global_snapshot_mem_init(ab); ++ + /* Add code here carefully */ + return 0; + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -1120,6 +1120,7 @@ struct ath12k_mlo_memory { + struct target_mem_chunk chunk[ATH12K_QMI_WLANFW_MAX_NUM_MEM_SEG_V01]; + struct reserved_mem *rsv; + bool init_done; ++ bool is_mlo_mem_avail; + }; + + enum ath12k_mlo_recovery_mode { +@@ -1145,6 +1146,7 @@ struct ath12k_hw_group { + struct ath12k __rcu *hw_links[ATH12K_GROUP_MAX_RADIO]; + struct ath12k_mlo_memory mlo_mem; + struct mutex mutex_lock; ++ struct ath12k_host_mlo_mem_arena mlomem_arena; + }; + + /* Master structure to hold the hw data which may be used in core module */ +@@ -1262,6 +1264,7 @@ struct ath12k_base { + u32 fw_crash_counter; + u32 last_recovery_time; + } stats; ++ bool mgmt_rx_reorder; + bool ftm_segment_handler; + struct ath12k_ftm_event_obj ftm_event_obj; + u32 pktlog_defs_checksum; +--- a/drivers/net/wireless/ath/ath12k/qmi.c ++++ b/drivers/net/wireless/ath/ath12k/qmi.c +@@ -3249,6 +3249,21 @@ out: + return ret; + } + ++/** ++ * ath12k_free_mlo_mgmt_rx_reo_per_link_info() - Free Rx REO per-link info ++ * @snapshot_info: Pointer to MGMT Rx REO snapshot info ++ * ++ * Return: None ++ */ ++void ath12k_free_mlo_mgmt_rx_reo_per_link_info ++ (struct ath12k_host_mlo_glb_rx_reo_snapshot_info *snapshot_info) ++{ ++ if (snapshot_info && snapshot_info->link_info) { ++ kfree(snapshot_info->link_info); ++ snapshot_info->link_info = NULL; ++ } ++} ++ + static void ath12k_qmi_free_mlo_mem_chunk(struct ath12k_base *ab, + struct target_mem_chunk *chunk, + int idx) +@@ -3256,6 +3271,8 @@ static void ath12k_qmi_free_mlo_mem_chun + struct ath12k_hw_group *ag = ab->ag; + struct target_mem_chunk *mlo_chunk; + bool fixed_mem = ab->bus_params.fixed_mem_region; ++ struct ath12k_host_mlo_mem_arena ++ *mlomem_arena_ctx = &ab->ag->mlomem_arena; + + lockdep_assert_held(&ag->mutex_lock); + +@@ -3293,6 +3310,19 @@ static void ath12k_qmi_free_mlo_mem_chun + chunk->v.addr = NULL; + chunk->paddr = NULL; + chunk->size = 0; ++ ++ ag->mlo_mem.is_mlo_mem_avail = false; ++ ++ /* We need to de-initialize when mlo memory is cleaned */ ++ mutex_lock(&mlomem_arena_ctx->mutex_lock); ++ if (mlomem_arena_ctx->init_done) { ++ mlomem_arena_ctx->init_done = false; ++ ath12k_free_mlo_mgmt_rx_reo_per_link_info ++ (&mlomem_arena_ctx->rx_reo_snapshot_info); ++ } ++ mutex_unlock(&mlomem_arena_ctx->mutex_lock); ++ ++ return; + } + + void ath12k_qmi_free_target_mem_chunk(struct ath12k_base *ab) +@@ -3395,6 +3425,7 @@ static int ath12k_qmi_alloc_target_mem_c + } + chunk->paddr = mlo_chunk->paddr; + chunk->v.addr = mlo_chunk->v.addr; ++ ag->mlo_mem.is_mlo_mem_avail = true; + mlo_idx++; + break; + case HOST_DDR_REGION_TYPE: +@@ -3425,6 +3456,518 @@ out: + return ret; + } + ++/** ++ * ath12k_mgmt_rx_reo_process_tlv_header() - Process a given TLV header ++ * @data: Pointer to start of the TLV ++ * @remaining_len: Length (in bytes) remaining in the arena from @data pointer ++ * @expected_tag: Expected TLV tag ++ * @tlv_len: Address of TLV length variable to be populated. This API populates ++ * the entire length(payload + header) of the TLV into @tlv_len ++ * @tlv_tag: Address of TLV Tag variable to be populated. ++ * ++ * Return: 0 on success, -1 on failure ++ */ ++static int ++ath12k_mgmt_rx_reo_process_tlv_header(struct ath12k_base *ab, ++ const u8 *data, size_t remaining_len, ++ u32 expected_tag, u32 *tlv_len, ++ u32 *tlv_tag) ++{ ++ if (remaining_len < MLO_SHMEM_TLV_HDR_SIZE) { ++ ath12k_err(ab, "Not enough space(%zu) to read TLV header(%u)\n", ++ remaining_len, (u32)MLO_SHMEM_TLV_HDR_SIZE); ++ return -EINVAL; ++ } ++ *tlv_len = MLO_SHMEMTLV_GET_TLVLEN(MLO_SHMEMTLV_GET_HDR(data)); ++ *tlv_len += MLO_SHMEM_TLV_HDR_SIZE; ++ if (remaining_len < *tlv_len) { ++ ath12k_err(ab, "Not enough space(%zu) to read TLV payload(%u)\n", ++ remaining_len, *tlv_len); ++ return -EINVAL; ++ } ++ ++ *tlv_tag = MLO_SHMEMTLV_GET_TLVTAG(MLO_SHMEMTLV_GET_HDR(data)); ++ if (*tlv_tag != expected_tag) { ++ ath12k_err(ab, "Unexpected TLV tag: %u is seen. Expected: %u\n", ++ *tlv_tag, ++ expected_tag); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++/** ++ * ath12k_mgmt_rx_reo_extract_ath12k_mlo_glb_shmem_tlv() - extract ATH12K_MLO_SHMEM_TLV_STRUCT_MLO_GLB_H_SHMEM ++ * TLV ++ * @data: Pointer to start of the TLV ++ * @remaining_len: Length (in bytes) remaining in the arena from @data pointer ++ * @shmem_params: Pointer to MLO Global shared memory parameters. Extracted ++ * information will be populated in this data structure. ++ * ++ * Return: On success, the number of bytes parsed. On failure, errno is returned. ++ */ ++static int ++ath12k_mgmt_rx_reo_extract_ath12k_mlo_glb_shmem_tlv(struct ath12k_base *ab, ++ u8 *data, size_t remaining_len, ++ struct ath12k_host_ath12k_mlo_glb_shmem_params *shmem_params) ++{ ++ struct ath12k_mlo_glb_shmem *ptlv; ++ u32 tlv_len, tlv_tag; ++ u32 major_minor_version; ++ ++ if (ath12k_mgmt_rx_reo_process_tlv_header(ab, data, remaining_len, ++ ATH12K_MLO_SHMEM_TLV_STRUCT_MLO_GLB_H_SHMEM, ++ &tlv_len, &tlv_tag) < 0) { ++ ath12k_err(ab, "%s:process tlv hdr failed\n", __func__); ++ return -EINVAL; ++ } ++ ++ ptlv = (struct ath12k_mlo_glb_shmem *)data; ++ major_minor_version = get_field_value_in_tlv(ptlv, major_minor_version, ++ tlv_len); ++ shmem_params->major_version = ++ MLO_SHMEM_GLB_H_SHMEM_PARAM_MAJOR_VERSION_GET( ++ major_minor_version); ++ shmem_params->minor_version = ++ MLO_SHMEM_GLB_H_SHMEM_PARAM_MINOR_VERSION_GET( ++ major_minor_version); ++ ++ return tlv_len; ++} ++ ++/** ++ * ath12k_mgmt_rx_reo_extract_mlo_glb_link_info_tlv() - extract lobal link info from shmem ++ * @data: Pointer to the first TLV in the arena ++ * @remaining_len: Length (in bytes) remaining in the arena from @data pointer ++ * @link_info: Pointer to which link info needs to be copied ++ * ++ * Return: On success, the number of bytes parsed. On failure, errno is returned. ++ */ ++static int ++ath12k_mgmt_rx_reo_extract_mlo_glb_link_info_tlv(struct ath12k_base *ab, ++ u8 *data, ++ size_t remaining_len, ++ u32 *link_info) ++{ ++ struct mlo_glb_link_info *ptlv; ++ u32 tlv_len, tlv_tag; ++ ++ if (ath12k_mgmt_rx_reo_process_tlv_header(ab, data, remaining_len, ++ ATH12K_MLO_SHMEM_TLV_STRUCT_MLO_GLB_LINK_INFO, ++ &tlv_len, &tlv_tag) < 0) { ++ ath12k_err(ab, "%s:process tlv hdr failed\n", __func__); ++ return -EPERM; ++ } ++ ++ ptlv = (struct mlo_glb_link_info *)data; ++ ++ *link_info = get_field_value_in_tlv(ptlv, link_info, tlv_len); ++ ++ return tlv_len; ++} ++ ++/** ++ * ath12k_mgmt_rx_reo_process_mlo_glb_per_link_status_tlv() - process per link info ++ * @data: Pointer to the first TLV in the arena ++ * @remaining_len: Length (in bytes) remaining in the arena from @data pointer ++ * ++ * Return: On success, the number of bytes parsed. On failure, errno is returned. ++ */ ++static int ++ath12k_mgmt_rx_reo_process_mlo_glb_per_link_status_tlv(struct ath12k_base *ab, ++ u8 *data, size_t remaining_len) ++{ ++ u32 tlv_len, tlv_tag; ++ ++ if (ath12k_mgmt_rx_reo_process_tlv_header(ab, data, remaining_len, ++ ATH12K_MLO_SHMEM_TLV_STRUCT_MLO_GLB_LINK, ++ &tlv_len, &tlv_tag) < 0) { ++ ath12k_err(ab, "%s:process tlv hdr failed\n", __func__); ++ return -EPERM; ++ } ++ ++ return tlv_len; ++} ++ ++/** ++ * ath12k_mgmt_rx_reo_parse_global_link_info() - parse lobal link info ++ * @data: Pointer to the first TLV in the arena ++ * @remaining_len: Length (in bytes) remaining in the arena from @data pointer ++ * ++ * Return: On success, the number of bytes parsed. On failure, errno is returned. ++ */ ++static int ++ath12k_mgmt_rx_reo_parse_global_link_info(struct ath12k_base *ab, u8 *data, size_t remaining_len) ++{ ++ int parsed_bytes, len; ++ u8 link; ++ u32 link_info; ++ u8 num_links; ++ ++ /* Extract ATH12K_MLO_SHMEM_TLV_STRUCT_MLO_GLB_LINK_INFO_TLV */ ++ len = ath12k_mgmt_rx_reo_extract_mlo_glb_link_info_tlv(ab, data, remaining_len, &link_info); ++ ATH12K_VALIDATE_PARSED_DATA_POINTER(len, data, remaining_len); ++ parsed_bytes = len; ++ ++ num_links = MLO_SHMEM_GLB_LINK_INFO_PARAM_NO_OF_LINKS_GET(link_info); ++ ++ for (link = 0; link < num_links; link++) { ++ len = ath12k_mgmt_rx_reo_process_mlo_glb_per_link_status_tlv(ab, data, remaining_len); ++ ATH12K_VALIDATE_PARSED_DATA_POINTER(len, data, ++ remaining_len); ++ parsed_bytes += len; ++ } ++ ++ return parsed_bytes; ++} ++ ++/** ++ * ath12k_mgmt_rx_reo_get_num_links_from_valid_link_bitmap() - Get the number of valid links ++ * @valid_link_bmap: Link bit map where the valid links are set to 1 ++ * ++ * Return: Number of valid links ++ */ ++static u8 ++ath12k_mgmt_rx_reo_get_num_links_from_valid_link_bitmap(u16 valid_link_bmap) ++{ ++ u8 num_links = 0; ++ ++ /* Find the number of set bits */ ++ while (valid_link_bmap) { ++ num_links++; ++ valid_link_bmap &= (valid_link_bmap - 1); ++ } ++ ++ return num_links; ++} ++ ++/** ++ * ath12k_mgmt_rx_reo_extract_mlo_glb_rx_reo_snapshot_info_tlv() - extract ++ * ATH12K_MLO_SHMEM_TLV_STRUCT_MLO_GLB_RX_REO_SNAPSHOT_INFO TLV ++ * @data: Pointer to start of the TLV ++ * @remaining_len: Length (in bytes) remaining in the arena from @data pointer ++ * @snapshot_info: Pointer to MGMT Rx REO snapshot info. Extracted information ++ * will be populated in this data structure. ++ * ++ * Return: On success, the number of bytes parsed. On failure, errno is returned. ++ */ ++static int ++ath12k_mgmt_rx_reo_extract_mlo_glb_rx_reo_snapshot_info_tlv(struct ath12k_base *ab, ++ u8 *data, size_t remaining_len, ++ struct ath12k_host_mlo_glb_rx_reo_snapshot_info *snapshot_info) ++{ ++ struct mlo_glb_rx_reo_snapshot_info *ptlv; ++ u32 tlv_len, tlv_tag; ++ u32 link_info; ++ u16 valid_link_bmap; ++ ++ /* process ATH12K_MLO_SHMEM_TLV_STRUCT_MLO_GLB_RX_REO_SNAPSHOT_INFO TLV */ ++ if (ath12k_mgmt_rx_reo_process_tlv_header(ab, data, remaining_len, ++ ATH12K_MLO_SHMEM_TLV_STRUCT_MLO_GLB_RX_REO_SNAPSHOT_INFO, ++ &tlv_len, &tlv_tag) < 0) { ++ ath12k_err(ab, "%s:process tlv hdr failed\n", __func__); ++ return -EINVAL; ++ } ++ ++ ptlv = (struct mlo_glb_rx_reo_snapshot_info *)data; ++ link_info = get_field_value_in_tlv(ptlv, link_info, tlv_len); ++ valid_link_bmap = ++ MLO_SHMEM_GLB_LINK_INFO_PARAM_VALID_LINK_BMAP_GET(link_info); ++ snapshot_info->valid_link_bmap = valid_link_bmap; ++ ++ if (is_field_present_in_tlv(ptlv, snapshot_ver_info, tlv_len)) { ++ u32 snapshot_ver_info; ++ ++ snapshot_ver_info = get_field_value_in_tlv ++ (ptlv, snapshot_ver_info, tlv_len); ++ snapshot_info->hw_forwarded_snapshot_ver = ++ MLO_SHMEM_GLB_RX_REO_SNAPSHOT_PARAM_HW_FWD_SNAPSHOT_VER_GET ++ (snapshot_ver_info); ++ snapshot_info->fw_forwarded_snapshot_ver = ++ MLO_SHMEM_GLB_RX_REO_SNAPSHOT_PARAM_FW_FWD_SNAPSHOT_VER_GET ++ (snapshot_ver_info); ++ snapshot_info->fw_consumed_snapshot_ver = ++ MLO_SHMEM_GLB_RX_REO_SNAPSHOT_PARAM_FW_CONSUMED_SNAPSHOT_VER_GET ++ (snapshot_ver_info); ++ } ++ ++ snapshot_info->num_links = ++ ath12k_mgmt_rx_reo_get_num_links_from_valid_link_bitmap(valid_link_bmap); ++ snapshot_info->link_info = kmalloc_array(snapshot_info->num_links, ++ sizeof(*snapshot_info->link_info), ++ GFP_KERNEL); ++ if (!snapshot_info->link_info) { ++ ath12k_err(ab, "Couldn't allocate memory for rx_reo_per_link_info\n"); ++ return -EINVAL; ++ } ++ ++ return tlv_len; ++} ++ ++/** ++ * ath12k_mgmt_rx_reo_get_next_valid_link_id() - Get next valid link ID ++ * @valid_link_bmap: Link bit map where the valid links are set to 1 ++ * @prev_link_id: Previous link ID ++ * ++ * Return: Next valid link ID if there are valid links after @prev_link_id, ++ * else -1 ++ */ ++static int ++ath12k_mgmt_rx_reo_get_next_valid_link_id(u16 valid_link_bmap, int prev_link_id) ++{ ++ int cur_link_id; ++ u16 mask; ++ u8 maxbits = sizeof(valid_link_bmap) * 8; ++ ++ cur_link_id = prev_link_id + 1; ++ mask = 1 << cur_link_id; ++ ++ while (!(valid_link_bmap & mask)) { ++ cur_link_id++; ++ if (cur_link_id == maxbits) ++ return -EINVAL; ++ mask = mask << 1; ++ } ++ ++ return cur_link_id; ++} ++ ++/** ++ * ath12k_mgmt_rx_reo_extract_mgmt_rx_reo_snapshot_tlv() - extract MGMT_RX_REO_SNAPSHOT TLV ++ * @data: Pointer to start of the TLV ++ * @remaining_len: Length (in bytes) remaining in the arena from @data pointer ++ * @address_ptr: Pointer to the snapshot address. This API will populate the ++ * snapshot address into the variable pointed by @address_ptr ++ * ++ * Return: On success, the number of bytes parsed. On failure, errno is returned. ++ */ ++static int ++ath12k_mgmt_rx_reo_extract_mgmt_rx_reo_snapshot_tlv(struct ath12k_base *ab, ++ u8 *data, size_t remaining_len, ++ void **address_ptr) ++{ ++ struct mgmt_rx_reo_snapshot *ptlv; ++ u32 tlv_len, tlv_tag; ++ ++ /* process ATH12K_MLO_SHMEM_TLV_STRUCT_MGMT_RX_REO_SNAPSHOT TLV */ ++ if (ath12k_mgmt_rx_reo_process_tlv_header(ab, data, remaining_len, ++ ATH12K_MLO_SHMEM_TLV_STRUCT_MGMT_RX_REO_SNAPSHOT, ++ &tlv_len, &tlv_tag) < 0) { ++ ath12k_err(ab, "%s:process tlv hdr failed\n", __func__); ++ return -EINVAL; ++ } ++ ++ ptlv = (struct mgmt_rx_reo_snapshot *)data; ++ *address_ptr = get_field_pointer_in_tlv(ptlv, mgmt_rx_reo_snapshot_low, ++ tlv_len); ++ ++ return tlv_len; ++} ++ ++/** ++ * ath12k_mgmt_rx_reo_extract_mlo_glb_rx_reo_per_link_info_tlv() - extract ++ * RX_REO_PER_LINK_SNAPSHOT_INFO TLV ++ * @data: Pointer to start of the TLV ++ * @remaining_len: Length (in bytes) remaining in the arena from @data pointer ++ * @link_info: Pointer to MGMT Rx REO per link info. Extracted information ++ * will be populated in this data structure. ++ * ++ * Return: On success, the number of bytes parsed. On failure, errno is returned. ++ */ ++static int ++ath12k_mgmt_rx_reo_extract_mlo_glb_rx_reo_per_link_info_tlv(struct ath12k_base *ab, ++ u8 *data, size_t remaining_len, u8 link_id, ++ struct ath12k_host_mlo_glb_rx_reo_per_link_info *link_info) ++{ ++ struct mlo_glb_rx_reo_per_link_snapshot_info *ptlv; ++ u32 tlv_len, tlv_tag; ++ int len; ++ u8 *fw_consumed; ++ int parsed_bytes; ++ ++ /* process ATH12K_MLO_SHMEM_TLV_STRUCT_MLO_GLB_RX_REO_PER_LINK_SNAPSHOT_INFO TLV */ ++ if (ath12k_mgmt_rx_reo_process_tlv_header(ab, data, remaining_len, ++ ATH12K_MLO_SHMEM_TLV_STRUCT_MLO_GLB_RX_REO_PER_LINK_SNAPSHOT_INFO, ++ &tlv_len, &tlv_tag) < 0) { ++ ath12k_err(ab, "%s:process tlv hdr failed\n", __func__); ++ return -EINVAL; ++ } ++ ++ ptlv = (struct mlo_glb_rx_reo_per_link_snapshot_info *)data; ++ ++ link_info->link_id = link_id; ++ ++ /** ++ * Get the pointer to the fw_consumed snapshot with in the TLV. ++ * Note that snapshots are nested TLVs within link_sanpshot_info TLV. ++ */ ++ data += offsetof(struct mlo_glb_rx_reo_per_link_snapshot_info, ++ fw_consumed); ++ fw_consumed = (u8 *)get_field_pointer_in_tlv(ptlv, fw_consumed, ++ tlv_len); ++ remaining_len -= offsetof(struct mlo_glb_rx_reo_per_link_snapshot_info, ++ fw_consumed); ++ parsed_bytes = offsetof(struct mlo_glb_rx_reo_per_link_snapshot_info, ++ fw_consumed); ++ ++ /* extract fw_consumed snapshot */ ++ len = ath12k_mgmt_rx_reo_extract_mgmt_rx_reo_snapshot_tlv(ab, data, remaining_len, ++ &link_info->fw_consumed); ++ ATH12K_VALIDATE_PARSED_DATA_POINTER(len, data, remaining_len); ++ parsed_bytes += len; ++ ++ /* extract fw_forwarded snapshot */ ++ len = ath12k_mgmt_rx_reo_extract_mgmt_rx_reo_snapshot_tlv(ab, data, remaining_len, ++ &link_info->fw_forwarded); ++ ATH12K_VALIDATE_PARSED_DATA_POINTER(len, data, remaining_len); ++ parsed_bytes += len; ++ ++ /* extract hw_forwarded snapshot */ ++ len = ath12k_mgmt_rx_reo_extract_mgmt_rx_reo_snapshot_tlv(ab, data, remaining_len, ++ &link_info->hw_forwarded); ++ ATH12K_VALIDATE_PARSED_DATA_POINTER(len, data, remaining_len); ++ parsed_bytes += len; ++ ++ /** ++ * Return the length of link_sanpshot_info TLV itself as the snapshots ++ * are nested inside link_sanpshot_info TLV and hence no need to add ++ * their lengths separately. ++ */ ++ return tlv_len; ++} ++ ++/** ++ * ath12k_mgmt_rx_reo_extract_mlo_glb_rx_reo_snapshot_info() - extract MGMT Rx REO snapshot info ++ * @data: Pointer to start of ATH12K_MLO_SHMEM_TLV_STRUCT_MLO_GLB_RX_REO_SNAPSHOT_INFO ++ * TLV ++ * @remaining_len: Length (in bytes) remaining in the arena from @data pointer ++ * @snapshot_info: Pointer to MGMT Rx REO snapshot info. Extracted information ++ * will be populated in this data structure. ++ * ++ * Return: On success, the number of bytes parsed. On failure, errno is returned. ++ */ ++static int ++ath12k_mgmt_rx_reo_extract_mlo_glb_rx_reo_snapshot_info(struct ath12k_base *ab, ++ u8 *data, size_t remaining_len, ++ struct ath12k_host_mlo_glb_rx_reo_snapshot_info *snapshot_info) ++{ ++ int parsed_bytes, len; ++ u8 link; ++ int cur_link_id, prev_link_id = -1; ++ u16 valid_link_bmap; ++ ++ /* Extract ATH12K_MLO_SHMEM_TLV_STRUCT_MLO_GLB_RX_REO_SNAPSHOT_INFO TLV */ ++ len = ath12k_mgmt_rx_reo_extract_mlo_glb_rx_reo_snapshot_info_tlv(ab, data, remaining_len, ++ snapshot_info); ++ ATH12K_VALIDATE_PARSED_DATA_POINTER(len, data, remaining_len); ++ parsed_bytes = len; ++ ++ valid_link_bmap = snapshot_info->valid_link_bmap; ++ /* Foreach valid link */ ++ for (link = 0; link < snapshot_info->num_links; ++link) { ++ cur_link_id = ath12k_mgmt_rx_reo_get_next_valid_link_id(valid_link_bmap, ++ prev_link_id); ++ ++ WARN_ON(!(cur_link_id >= 0)); ++ ++ /* Extract per_link_info */ ++ len = ath12k_mgmt_rx_reo_extract_mlo_glb_rx_reo_per_link_info_tlv(ab, ++ data, remaining_len, cur_link_id, ++ &snapshot_info->link_info[link]); ++ ATH12K_VALIDATE_PARSED_DATA_POINTER(len, data, ++ remaining_len); ++ parsed_bytes += len; ++ prev_link_id = cur_link_id; ++ } ++ ++ return parsed_bytes; ++} ++ ++/** ++ * ath12k_qmi_parse_mlo_mem_arena() - Parse MLO Global shared memory arena ++ * @data: Pointer to the first TLV in the arena ++ * @remaining_len: Length (in bytes) remaining in the arena from @data pointer ++ * @mlomem_arena_ctx: Pointer to MLO Global shared memory arena context. ++ * Extracted information will be populated in this data structure. ++ * ++ * Return: On success, the number of bytes parsed. On failure, errno is returned. ++ */ ++static int ath12k_qmi_parse_mlo_mem_arena(struct ath12k_base *ab, ++ u8 *data, size_t remaining_len, ++ struct ath12k_host_mlo_mem_arena *mlomem_arena_ctx) ++{ ++ int parsed_bytes; ++ int len; ++ ++ if (!data) ++ return -EINVAL; ++ ++ len = ath12k_mgmt_rx_reo_extract_ath12k_mlo_glb_shmem_tlv(ab, data, remaining_len, ++ &mlomem_arena_ctx->shmem_params); ++ ATH12K_VALIDATE_PARSED_DATA_POINTER(len, data, remaining_len); ++ parsed_bytes = len; ++ ++ len = ath12k_mgmt_rx_reo_extract_mlo_glb_rx_reo_snapshot_info(ab, ++ data, remaining_len, &mlomem_arena_ctx->rx_reo_snapshot_info); ++ ATH12K_VALIDATE_PARSED_DATA_POINTER(len, data, remaining_len); ++ parsed_bytes += len; ++ ++ len = ath12k_mgmt_rx_reo_parse_global_link_info(ab, data, remaining_len); ++ ATH12K_VALIDATE_PARSED_DATA_POINTER(len, data, remaining_len); ++ parsed_bytes += len; ++ ++ return parsed_bytes; ++} ++ ++int ath12k_qmi_mlo_global_snapshot_mem_init(struct ath12k_base *ab) ++{ ++ struct ath12k_host_mlo_mem_arena *mlomem_arena_ctx = &ab->ag->mlomem_arena; ++ struct ath12k_hw_group *ag = ab->ag; ++ struct target_mem_chunk *mlo_chunk; ++ int ret = 0, mlo_idx = 0; ++ ++ if (!ab->mgmt_rx_reorder) ++ return 0; ++ ++ if (!ag->mlo_mem.is_mlo_mem_avail) ++ return 0; ++ ++ mlo_chunk = &ab->ag->mlo_mem.chunk[mlo_idx]; ++ ++ /* We need to initialize only for the first invocation */ ++ mutex_lock(&mlomem_arena_ctx->mutex_lock); ++ if (mlomem_arena_ctx->init_done) { ++ mutex_unlock(&mlomem_arena_ctx->mutex_lock); ++ return 0; ++ } ++ ++ if (ab->bus_params.fixed_mem_region) ++ ret = ath12k_qmi_parse_mlo_mem_arena(ab, ++ mlo_chunk->v.ioaddr, ++ mlo_chunk->size, ++ mlomem_arena_ctx); ++ else ++ ret = ath12k_qmi_parse_mlo_mem_arena(ab, ++ mlo_chunk->v.addr, ++ mlo_chunk->size, ++ mlomem_arena_ctx); ++ ++ if (ret < 0) { ++ ath12k_err(ab, "parsing of mlo shared memory failed ret %d\n", ret); ++ ath12k_free_mlo_mgmt_rx_reo_per_link_info( ++ &mlomem_arena_ctx->rx_reo_snapshot_info); ++ mutex_unlock(&mlomem_arena_ctx->mutex_lock); ++ return ret; ++ } ++ ++ mlomem_arena_ctx->init_done = true; ++ ++ mutex_unlock(&mlomem_arena_ctx->mutex_lock); ++ ++ return 0; ++} ++ + #define MAX_TGT_MEM_MODES 5 + static int ath12k_qmi_assign_target_mem_chunk(struct ath12k_base *ab) + { +@@ -3571,6 +4114,7 @@ skip_mlo_mem_init: + ab->qmi.target_mem[idx].size = mlo_chunk->size; + ab->qmi.target_mem[idx].type = mlo_chunk->type; + mlo_sz += mlo_chunk->size; ++ ag->mlo_mem.is_mlo_mem_avail = true; + idx++; + mlo_idx++; + break; +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -71,6 +71,57 @@ struct wmi_tlv { + #define WMI_BA_MODE_BUFFER_SIZE_256 3 + #define WMI_BA_MODE_BUFFER_SIZE_1024 6 + ++#define ATH12K_VALIDATE_PARSED_DATA_POINTER(parsed_bytes, data, \ ++ remaining_len) \ ++do { \ ++ if ((parsed_bytes) < 0 || (parsed_bytes > remaining_len)) { \ ++ ath12k_err(ab, "TLV extraction failed\n"); \ ++ return -EINVAL; \ ++ } \ ++ (data) += (parsed_bytes); \ ++ (remaining_len) -= (parsed_bytes); \ ++} while (0) ++ ++/** ++ * is_field_present_in_tlv() - Check whether a given field is present ++ * in a given TLV ++ * @ptlv: Pointer to start of the TLV ++ * @field_name: name of the field in the TLV structure ++ * @tlv_len: Length of the TLV ++ * ++ * Return: true if the field is present within the TLV, ++ * else false ++ */ ++#define is_field_present_in_tlv(ptlv, field_name, tlv_len) \ ++ (offsetof(typeof(*(ptlv)), field_name) < (tlv_len) ? \ ++ true : false) ++ ++/** ++ * get_field_value_in_tlv() - Get the value of a given field in a given TLV ++ * @ptlv: Pointer to start of the TLV ++ * @field_name: name of the field in the TLV structure ++ * @tlv_len: Length of the TLV ++ * ++ * Return: Value of the given field if the offset of the field with in the TLV ++ * structure is less than the TLV length, else 0. ++ */ ++#define get_field_value_in_tlv(ptlv, field_name, tlv_len) \ ++ (offsetof(typeof(*(ptlv)), field_name) < (tlv_len) ? \ ++ (ptlv)->field_name : 0) ++ ++/** ++ * get_field_pointer_in_tlv() - Get the address of a given field in a given TLV ++ * @ptlv: Pointer to start of the TLV ++ * @field_name: name of the field in the TLV structure ++ * @tlv_len: Length of the TLV ++ * ++ * Return: Address of the given field if the offset of the field with in the ++ * TLV structure is less than the TLV length, else NULL. ++ */ ++#define get_field_pointer_in_tlv(ptlv, field_name, tlv_len) \ ++ (offsetof(typeof(*(ptlv)), field_name) < (tlv_len) ? \ ++ &(ptlv)->field_name : NULL) ++ + /* HW mode config type replicated from FW header + * @WMI_HOST_HW_MODE_SINGLE: Only one PHY is active. + * @WMI_HOST_HW_MODE_DBS: Both PHYs are active in different bands, +@@ -5172,6 +5223,225 @@ struct wmi_pdev_update_muedca_event { + + #define WLAN_MGMT_TXRX_HOST_MAX_ANTENNA 4 + ++/** ++ * ath12k_host_mlo_glb_rx_reo_snapshot_info - MGMT Rx REO information in MLO ++ * global shared memory ++ * @num_links: Number of valid links ++ * @valid_link_bmap: Valid link bitmap ++ * @link_info: pointer to an array of Rx REO per-link information ++ * @hw_forwarded_snapshot_ver: HW forwarded snapshot version ++ * @fw_forwarded_snapshot_ver: FW forwarded snapshot version ++ * @fw_consumed_snapshot_ver: FW consumed snapshot version ++ */ ++struct ath12k_host_mlo_glb_rx_reo_snapshot_info { ++ u8 num_links; ++ u16 valid_link_bmap; ++ struct ath12k_host_mlo_glb_rx_reo_per_link_info *link_info; ++ u8 hw_forwarded_snapshot_ver; ++ u8 fw_forwarded_snapshot_ver; ++ u8 fw_consumed_snapshot_ver; ++}; ++ ++/** ++ * ath12k_host_ath12k_mlo_glb_shmem_params - MLO global shared memory parameters ++ * @major_version: Major version ++ * @minor_version: Minor version ++ */ ++struct ath12k_host_ath12k_mlo_glb_shmem_params { ++ u16 major_version; ++ u16 minor_version; ++}; ++ ++/** ++ * ath12k_host_mlo_mem_arena - MLO Global shared memory arena context ++ * @shmem_params: shared memory parameters ++ * @rx_reo_snapshot_info: MGMT Rx REO snapshot information ++ * @init_done: Initialized snapshot info ++ */ ++struct ath12k_host_mlo_mem_arena { ++ struct ath12k_host_ath12k_mlo_glb_shmem_params shmem_params; ++ struct ath12k_host_mlo_glb_rx_reo_snapshot_info rx_reo_snapshot_info; ++ bool init_done; ++ /* Protect the parallel initialization */ ++ struct mutex mutex_lock; ++}; ++ ++/** Helper Macros for tlv header of the given tlv buffer */ ++/* Size of the TLV Header which is the Tag and Length fields */ ++#define MLO_SHMEM_TLV_HDR_SIZE (1 * sizeof(u32)) ++ ++/* TLV Helper macro to get the TLV Header given the pointer to the TLV buffer. */ ++#define MLO_SHMEMTLV_GET_HDR(tlv_buf) (((u32 *)(tlv_buf))[0]) ++ ++/* TLV Helper macro to set the TLV Header given the pointer to the TLV buffer. */ ++#define MLO_SHMEMTLV_SET_HDR(tlv_buf, tag, len) \ ++ ((((u32 *)(tlv_buf))[0]) = ((tag << 16) | (len & 0x0000FFFF))) ++ ++/* TLV Helper macro to get the TLV Tag given the TLV header. */ ++#define MLO_SHMEMTLV_GET_TLVTAG(tlv_header) ((u32)((tlv_header) >> 16)) ++ ++/* TLV Helper macro to get the TLV Buffer Length (minus TLV header size) ++ * given the TLV header. ++ */ ++#define MLO_SHMEMTLV_GET_TLVLEN(tlv_header) \ ++ ((u32)((tlv_header) & 0x0000FFFF)) ++/* TLV Helper macro to get the TLV length from TLV structure size ++ * by removing TLV header size. ++ */ ++#define MLO_SHMEMTLV_GET_STRUCT_TLVLEN(tlv_struct) \ ++ ((u32)(sizeof(tlv_struct) - MLO_SHMEM_TLV_HDR_SIZE)) ++ ++/* Definition of Global H SHMEM Arena */ ++struct ath12k_mlo_glb_shmem { ++ /* TLV tag and len; tag equals ATH12K_MLO_SHMEM_TLV_STRUCT_MLO_GLB_H_SHMEM */ ++ u32 tlv_header; ++ /** ++ * major_minor_version ++ * ++ * [15:0]: minor version ++ * [31:16]: major version ++ */ ++ u32 major_minor_version; ++ /* This TLV is followed by TLVs ++ * mlo_glb_rx_reo_snapshot_info reo_snapshot; ++ * struct mlo_glb_link_info glb_info; ++ */ ++}; ++ ++#define MLO_SHMEM_GLB_H_SHMEM_PARAM_MAJOR_VERSION_MASK GENMASK(31, 16) ++#define MLO_SHMEM_GLB_H_SHMEM_PARAM_MINOR_VERSION_MASK GENMASK(15, 0) ++#define MLO_SHMEM_GLB_LINK_INFO_PARAM_VALID_LINK_BMAP_MASK GENMASK(19, 4) ++#define MLO_SHMEM_GLB_LINK_INFO_PARAM_NO_OF_LINKS_MASK GENMASK(3, 0) ++#define MLO_SHMEM_GLB_RX_REO_SNAPSHOT_PARAM_HW_FWD_SNAPSHOT_VER_MASK GENMASK(2, 0) ++#define MLO_SHMEM_GLB_RX_REO_SNAPSHOT_PARAM_FW_FWD_SNAPSHOT_VER_MASK GENMASK(5, 3) ++#define MLO_SHMEM_GLB_RX_REO_SNAPSHOT_PARAM_FW_CONSUMED_SNAPSHOT_VER_MASK GENMASK(8, 6) ++#define MLO_SHMEM_CHIP_CRASH_INFO_PARAM_NO_OF_CHIPS_MASK GENMASK(1, 0) ++#define MLO_SHMEM_CHIP_CRASH_INFO_PARAM_VALID_CHIP_BMAP_MASK GENMASK(4, 2) ++ ++#define MLO_SHMEM_GLB_H_SHMEM_PARAM_MAJOR_VERSION_GET(major_minor_version) \ ++ FIELD_GET(MLO_SHMEM_GLB_H_SHMEM_PARAM_MAJOR_VERSION_MASK, major_minor_version) ++#define MLO_SHMEM_GLB_H_SHMEM_PARAM_MINOR_VERSION_GET(major_minor_version) \ ++ FIELD_GET(MLO_SHMEM_GLB_H_SHMEM_PARAM_MINOR_VERSION_MASK, major_minor_version) ++ ++#define MLO_SHMEM_GLB_LINK_INFO_PARAM_VALID_LINK_BMAP_GET(link_info) \ ++ FIELD_GET(MLO_SHMEM_GLB_LINK_INFO_PARAM_VALID_LINK_BMAP_MASK, link_info) ++#define MLO_SHMEM_GLB_LINK_INFO_PARAM_NO_OF_LINKS_GET(link_info) \ ++ FIELD_GET(MLO_SHMEM_GLB_LINK_INFO_PARAM_NO_OF_LINKS_MASK, link_info) ++#define MLO_SHMEM_GLB_RX_REO_SNAPSHOT_PARAM_HW_FWD_SNAPSHOT_VER_GET(snapshot_ver_info) \ ++ FIELD_GET(MLO_SHMEM_GLB_RX_REO_SNAPSHOT_PARAM_HW_FWD_SNAPSHOT_VER_MASK, snapshot_ver_info) ++#define MLO_SHMEM_GLB_RX_REO_SNAPSHOT_PARAM_FW_FWD_SNAPSHOT_VER_GET(snapshot_ver_info) \ ++ FIELD_GET(MLO_SHMEM_GLB_RX_REO_SNAPSHOT_PARAM_FW_FWD_SNAPSHOT_VER_MASK, snapshot_ver_info) ++#define MLO_SHMEM_GLB_RX_REO_SNAPSHOT_PARAM_FW_CONSUMED_SNAPSHOT_VER_GET(snapshot_ver_info) \ ++ FIELD_GET(MLO_SHMEM_GLB_RX_REO_SNAPSHOT_PARAM_FW_CONSUMED_SNAPSHOT_VER_MASK, snapshot_ver_info) ++ ++#define MLO_SHMEM_CHIP_CRASH_INFO_PARAM_NO_OF_CHIPS_GET(chip_info) \ ++ FIELD_GET(MLO_SHMEM_CHIP_CRASH_INFO_PARAM_NO_OF_CHIPS_MASK, chip_info) ++#define MLO_SHMEM_CHIP_CRASH_INFO_PARAM_VALID_CHIP_BMAP_GET(chip_info) \ ++ FIELD_GET(MLO_SHMEM_CHIP_CRASH_INFO_PARAM_VALID_CHIP_BMAP_MASK, chip_info) ++ ++/** Definition of the GLB_H_SHMEM arena tlv structures */ ++enum { ++ ATH12K_MLO_SHMEM_TLV_STRUCT_MGMT_RX_REO_SNAPSHOT, ++ ATH12K_MLO_SHMEM_TLV_STRUCT_MLO_GLB_RX_REO_PER_LINK_SNAPSHOT_INFO, ++ ATH12K_MLO_SHMEM_TLV_STRUCT_MLO_GLB_RX_REO_SNAPSHOT_INFO, ++ ATH12K_MLO_SHMEM_TLV_STRUCT_MLO_GLB_LINK, ++ ATH12K_MLO_SHMEM_TLV_STRUCT_MLO_GLB_LINK_INFO, ++ ATH12K_MLO_SHMEM_TLV_STRUCT_MLO_GLB_H_SHMEM, ++ ATH12K_MLO_SHMEM_TLV_STRUCT_MLO_GLB_CHIP_CRASH_INFO, ++ ATH12K_MLO_SHMEM_TLV_STRUCT_MLO_GLB_PER_CHIP_CRASH_INFO, ++}; ++ ++struct mlo_glb_link_info { ++ /* TLV tag and len; tag equals ATH12K_MLO_SHMEM_TLV_STRUCT_MLO_GLB_LINK_INFO */ ++ u32 tlv_header; ++ ++ /** ++ * link_info ++ * ++ * [3:0]: no_of_links ++ * [19:4]: valid_link_bmap ++ * [31:20]: reserved ++ */ ++ u32 link_info; ++ /* This TLV is followed by array of mlo_glb_link: ++ * mlo_glb_link will have multiple instances equal to num of hw links ++ * received by no_of_link ++ * mlo_glb_link glb_link_info[]; ++ */ ++}; ++ ++/* Definition of the complete REO snapshot info */ ++struct mlo_glb_rx_reo_snapshot_info { ++ /* TLV tag and len; tag equals ATH12K_MLO_SHMEM_TLV_STRUCT_MLO_GLB_RX_REO_SNAPSHOT_INFO */ ++ u32 tlv_header; ++ ++ /** ++ * link_info ++ * ++ * [3:0]: no_of_links ++ * [19:4]: valid_link_bmap ++ * [31:20]: reserved ++ */ ++ u32 link_info; ++ ++ /** ++ * snapshot_ver_info ++ * ++ * [2:0]: hw_forwarded snapshot version ++ * [5:3]: fw_forwarded snapshot version ++ * [8:6]: fw_consumed snapshot version ++ * [31:9]: reserved ++ */ ++ u32 snapshot_ver_info; ++ u32 reserved_alignment_padding; ++ ++ /* This TLV is followed by array of mlo_glb_rx_reo_per_link_snapshot_info: ++ * mlo_glb_rx_reo_per_link_snapshot_info will have multiple instances ++ * equal to num of hw links received by no_of_link ++ * mlo_glb_rx_reo_per_link_snapshot_info per_link_info[]; ++ */ ++}; ++ ++struct ath12k_host_mlo_glb_rx_reo_per_link_info { ++ u8 link_id; ++ void *fw_consumed; ++ void *fw_forwarded; ++ void *hw_forwarded; ++}; ++ ++/* REO snapshot structure */ ++struct mgmt_rx_reo_snapshot { ++ /* TLV tag and len; tag equals ATH12K_MLO_SHMEM_TLV_STRUCT_MGMT_RX_REO_SNAPSHOT */ ++ u32 tlv_header; ++ u32 reserved_alignment_padding; ++ /** ++ * mgmt_rx_reo_snapshot_low ++ * ++ * [0]: valid ++ * [16:1]: mgmt_pkt_ctr ++ * [31:17]: global_timestamp_low ++ */ ++ u32 mgmt_rx_reo_snapshot_low; ++ ++ /** ++ * mgmt_rx_reo_snapshot_high ++ * ++ * [16:0]: global_timestamp_high ++ * [31:17]: mgmt_pkt_ctr_redundant ++ */ ++ u32 mgmt_rx_reo_snapshot_high; ++ ++}; ++ ++struct mlo_glb_rx_reo_per_link_snapshot_info { ++ /* TLV tag and len; tag equals ATH12K_MLO_SHMEM_TLV_STRUCT_MLO_GLB_RX_REO_PER_LINK_SNAPSHOT_INFO */ ++ u32 tlv_header; ++ u32 reserved_alignment_padding; ++ struct mgmt_rx_reo_snapshot fw_consumed; ++ struct mgmt_rx_reo_snapshot fw_forwarded; ++ struct mgmt_rx_reo_snapshot hw_forwarded; ++}; ++ + struct mgmt_rx_event_params { + u32 chan_freq; + u32 channel; +--- a/drivers/net/wireless/ath/ath12k/qmi.h ++++ b/drivers/net/wireless/ath/ath12k/qmi.h +@@ -62,6 +62,7 @@ enum userpd_id { + }; + + struct ath12k_base; ++struct ath12k_host_mlo_glb_rx_reo_snapshot_info; + + enum ath12k_qmi_file_type { + ATH12K_QMI_FILE_TYPE_BDF_GOLDEN, +@@ -782,6 +783,9 @@ int ath12k_qmi_m3_dump_upload_done_ind_s + u32 pdev_id, int status); + void ath12k_qmi_free_target_mem_chunk(struct ath12k_base *ab); + void ath12k_qmi_trigger_host_cap(struct ath12k_base *ab); ++int ath12k_qmi_mlo_global_snapshot_mem_init(struct ath12k_base *ab); ++void ath12k_free_mlo_mgmt_rx_reo_per_link_info( ++ struct ath12k_host_mlo_glb_rx_reo_snapshot_info *snapshot_info); + + static inline void ath12k_qmi_set_event_block(struct ath12k_qmi *qmi, bool block) + { diff --git a/feeds/ipq95xx/mac80211/patches/qca/747-ath12k-add-support-for-Mgmt-Rx-re-ordering.patch b/feeds/ipq95xx/mac80211/patches/qca/747-ath12k-add-support-for-Mgmt-Rx-re-ordering.patch new file mode 100644 index 000000000..ac4b24831 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/747-ath12k-add-support-for-Mgmt-Rx-re-ordering.patch @@ -0,0 +1,3885 @@ +From c3778eb2e89c5af6528710e17d2dd5526c0de593 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Kathirvel +Date: Mon, 6 Feb 2023 12:31:24 +0530 +Subject: [PATCH 2/3] ath12k: add support for Mgmt Rx re-ordering + +Consider an MLD formed by multiple SoCs. Management frames received +on individual links will be forwarded or consumed by the firmware +running on that SoC. Each link could have variable delay in FW->Host +messaging. Host can receive these management frames in an order +different from that in which the frames were received over the air. This +problem could be there in single-SoC MLD case also due to race +between FW threads that are handling management frames. + +Consider a scenario of client sending deauth followed back-to-back by +auth req. If they are sent on different links, deauth could arrive at AP +host after auth req though deauth ACK’ed by AP HW first, and then auth +req ACK’ed by AP HW. This can lead to issues. We need to process the +management frames received across all the links in the order in which HW +ACK’ed them. + +The reordering of frames is done based on the packet sequence number and +timestamp of a frame, this info is sent by hw through +WMI_MGMT_RX_EVENTID in tag WMI_TAG_MLO_MGMT_RX_REO_PARAMS. +To enable this feature execute below command +insmod ath12k mgmt_rx_reorder=1 + +Signed-off-by: Karthikeyan Kathirvel +--- + drivers/net/wireless/ath/ath12k/core.c | 249 +++ + drivers/net/wireless/ath/ath12k/core.h | 2 + + drivers/net/wireless/ath/ath12k/debug.h | 1 + + drivers/net/wireless/ath/ath12k/pci.c | 11 + + drivers/net/wireless/ath/ath12k/wmi.c | 2665 +++++++++++++++++++++-- + drivers/net/wireless/ath/ath12k/wmi.h | 742 +++++++ + 6 files changed, 3515 insertions(+), 155 deletions(-) + +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/core.c +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/core.c ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/core.c +@@ -47,6 +47,10 @@ MODULE_PARM_DESC(en_fwlog, "fwlog: 0-dis + + static unsigned int ath12k_recovery_mode = ATH12K_MLO_RECOVERY_MODE0; + ++bool ath12k_mgmt_rx_reordering = false; ++module_param_named(mgmt_rx_reorder, ath12k_mgmt_rx_reordering, bool, 0644); ++MODULE_PARM_DESC(mgmt_rx_reorder, "Mgmt Rx Re-Ordering (0 - disable, 1 - enable)"); ++ + static DEFINE_MUTEX(ath12k_hw_lock); + static struct list_head ath12k_hw_groups = LIST_HEAD_INIT(ath12k_hw_groups); + +@@ -765,6 +769,7 @@ static void ath12k_core_stop(struct ath1 + if (!test_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags)) + ath12k_qmi_firmware_stop(ab); + ++ ath12k_mgmt_rx_reo_deinit_context(ab); + ath12k_hif_stop(ab); + ath12k_wmi_detach(ab); + ath12k_dp_rx_pdev_reo_cleanup(ab); +@@ -807,6 +812,248 @@ static void ath12k_core_soc_destroy(stru + ath12k_qmi_deinit_service(ab); + } + ++/** ++ * ath12k_core_mgmt_rx_reo_init_ss_params() - Initialize a given snapshot ++ * params object ++ * @snapshot_params: Pointer to snapshot params object ++ * ++ * Return: void ++ */ ++static void ++ath12k_core_mgmt_rx_reo_init_ss_params( ++ struct ath12k_mgmt_rx_reo_snapshot_params *snapshot_params) ++{ ++ snapshot_params->valid = false; ++ snapshot_params->mgmt_pkt_ctr = 0; ++ snapshot_params->global_timestamp = 0; ++} ++ ++/** ++ * ath12k_core_rx_reo_init_ss_value() - Initialize management Rx reorder ++ * snapshot values for a given pdev ++ * @pdev: pointer to pdev object ++ * ++ * Return: 0 for success, non-zero for failure ++ */ ++static int ++ath12k_core_rx_reo_init_ss_value(struct ath12k *ar) ++{ ++ enum ath12k_mgmt_rx_reo_shared_snapshot_id snapshot_id; ++ struct ath12k_mgmt_rx_reo_pdev_info *mgmt_rx_reo_pdev_ctx; ++ ++ mgmt_rx_reo_pdev_ctx = &ar->rx_reo_pdev_ctx; ++ snapshot_id = 0; ++ while (snapshot_id < ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_MAX) { ++ ath12k_core_mgmt_rx_reo_init_ss_params ++ (&mgmt_rx_reo_pdev_ctx->last_valid_shared_snapshot ++ [snapshot_id]); ++ snapshot_id++; ++ } ++ ++ /* Initialize Host snapshot params */ ++ ath12k_core_mgmt_rx_reo_init_ss_params ++ (&mgmt_rx_reo_pdev_ctx->host_snapshot); ++ ++ return 0; ++} ++ ++void *ath12k_core_mgmt_rx_reo_get_ss_address( ++ struct ath12k_base *ab, ++ u8 link_id, ++ enum ath12k_mgmt_rx_reo_shared_snapshot_id snapshot_id) ++{ ++ struct ath12k_host_mlo_mem_arena *mlomem_arena_ctx; ++ struct ath12k_host_mlo_glb_rx_reo_snapshot_info *snapshot_info; ++ struct ath12k_host_mlo_glb_rx_reo_per_link_info *snapshot_link_info; ++ u8 link; ++ ++ if (snapshot_id >= ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_MAX) { ++ ath12k_err(ab, "Invalid snapshot ID: %d\n", snapshot_id); ++ return NULL; ++ } ++ ++ mlomem_arena_ctx = &ab->ag->mlomem_arena; ++ snapshot_info = &mlomem_arena_ctx->rx_reo_snapshot_info; ++ ++ for (link = 0; link < snapshot_info->num_links; ++link) { ++ snapshot_link_info = &snapshot_info->link_info[link]; ++ ++ if (link_id == snapshot_link_info->link_id) ++ break; ++ } ++ ++ if (link == snapshot_info->num_links) { ++ ath12k_err(ab, "Couldn't find the snapshot link info corresponding to the link %d\n", ++ link_id); ++ return NULL; ++ } ++ ++ switch (snapshot_id) { ++ case ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_MAC_HW: ++ return snapshot_link_info->hw_forwarded; ++ ++ case ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_FW_CONSUMED: ++ return snapshot_link_info->fw_consumed; ++ ++ case ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_FW_FORWARDED: ++ return snapshot_link_info->fw_forwarded; ++ ++ default: ++ WARN_ON(1); ++ } ++ ++ return NULL; ++} ++ ++static int ath12k_mgmt_rx_reo_get_snapshot_version(struct ath12k_base *ab, ++ enum ath12k_mgmt_rx_reo_shared_snapshot_id id) ++{ ++ struct ath12k_host_mlo_mem_arena *mlomem_arena_ctx; ++ struct ath12k_host_mlo_glb_rx_reo_snapshot_info *snapshot_info; ++ int snapshot_version; ++ ++ if (id >= ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_MAX) { ++ ath12k_err(ab, "Invalid snapshot ID: %d\n", id); ++ return ATH12K_MGMT_RX_REO_INVALID_SNAPSHOT_VERSION; ++ } ++ ++ mlomem_arena_ctx = &ab->ag->mlomem_arena; ++ snapshot_info = &mlomem_arena_ctx->rx_reo_snapshot_info; ++ ++ switch (id) { ++ case ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_MAC_HW: ++ snapshot_version = snapshot_info->hw_forwarded_snapshot_ver; ++ break; ++ ++ case ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_FW_CONSUMED: ++ snapshot_version = snapshot_info->fw_consumed_snapshot_ver; ++ break; ++ ++ case ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_FW_FORWARDED: ++ snapshot_version = snapshot_info->fw_forwarded_snapshot_ver; ++ break; ++ ++ default: ++ snapshot_version = ATH12K_MGMT_RX_REO_INVALID_SNAPSHOT_VERSION; ++ break; ++ } ++ ++ return snapshot_version; ++} ++ ++static int ++ath12k_core_mgmt_rx_reo_get_snapshot_info ++ (struct ath12k *ar, ++ enum ath12k_mgmt_rx_reo_shared_snapshot_id id, ++ struct ath12k_mgmt_rx_reo_snapshot_info *snapshot_info) ++{ ++ u8 link_id; ++ u8 snapshot_version; ++ struct ath12k_base *ab; ++ ++ ab = ar->ab; ++ ++ if (id >= ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_MAX) { ++ ath12k_err(ab, "Mgmt RX REO snapshot id invalid %d\n", id); ++ return -EINVAL; ++ } ++ ++ if (!snapshot_info) { ++ ath12k_err(ab, "Ref to mgmt RX REO snapshot info is null\n"); ++ return -EINVAL; ++ } ++ ++ link_id = ar->pdev->hw_link_id; ++ ++ snapshot_info->address = ++ ath12k_core_mgmt_rx_reo_get_ss_address(ab, link_id, id); ++ if (!snapshot_info->address) { ++ ath12k_err(ab, "NULL snapshot address\n"); ++ return -EINVAL; ++ } ++ ++ snapshot_version = ath12k_mgmt_rx_reo_get_snapshot_version(ab, id); ++ if (snapshot_version < 0) { ++ ath12k_err(ab, "Invalid snapshot version %d\n", ++ snapshot_version); ++ return -EINVAL; ++ } ++ ++ snapshot_info->version = snapshot_version; ++ ++ return 0; ++} ++ ++/** ++ * ath12k_mgmt_rx_reo_initialize_snapshot_address() - Initialize management Rx reorder ++ * snapshot addresses for a given pdev ++ * @pdev: pointer to pdev object ++ * ++ * Return: 0 for success, non-zero for failure ++ */ ++static int ++ath12k_core_mgmt_rx_reo_init_ss_address(struct ath12k *ar) ++{ ++ enum ath12k_mgmt_rx_reo_shared_snapshot_id snapshot_id; ++ struct ath12k_mgmt_rx_reo_pdev_info *mgmt_rx_reo_pdev_ctx; ++ int status; ++ ++ mgmt_rx_reo_pdev_ctx = &ar->rx_reo_pdev_ctx; ++ snapshot_id = 0; ++ while (snapshot_id < ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_MAX) { ++ struct ath12k_mgmt_rx_reo_snapshot_info *snapshot_info; ++ ++ snapshot_info = ++ &mgmt_rx_reo_pdev_ctx->host_target_shared_snapshot_info ++ [snapshot_id]; ++ status = ath12k_core_mgmt_rx_reo_get_snapshot_info ++ (ar, snapshot_id, snapshot_info); ++ if (status) { ++ ath12k_err(ar->ab, "Get snapshot info failed, id = %u\n", ++ snapshot_id); ++ return status; ++ } ++ ++ snapshot_id++; ++ } ++ ++ return 0; ++} ++ ++static int ath12k_core_mgmt_rx_reordering_init(struct ath12k_base *ab) ++{ ++ int i, ret; ++ struct ath12k *ar; ++ struct ath12k_pdev *pdev; ++ struct ath12k_hw_group *ag = ab->ag; ++ ++ if (!(ag->mlo_mem.is_mlo_mem_avail && ag->mgmt_rx_reorder)) ++ return 0; ++ ++ for (i = 0; i < ab->num_radios; i++) { ++ pdev = &ab->pdevs[i]; ++ ar = pdev->ar; ++ if (!ar) ++ continue; ++ ret = ath12k_core_rx_reo_init_ss_value(ar); ++ if (ret) { ++ ath12k_err(ab, "Failed to initialize snapshot value\n"); ++ return ret; ++ } ++ ++ ret = ath12k_core_mgmt_rx_reo_init_ss_address(ar); ++ if (ret) { ++ ath12k_err(ab, "Failed to initialize snapshot address\n"); ++ return ret; ++ } ++ ++ ar->rx_reo_pdev_ctx.init_complete = true; ++ } ++ ++ ++ return 0; ++} ++ + static int ath12k_core_pdev_init(struct ath12k_base *ab) + { + int ret; +@@ -824,8 +1071,16 @@ static int ath12k_core_pdev_init(struct + goto err_thermal_unregister; + } + ++ ret = ath12k_core_mgmt_rx_reordering_init(ab); ++ if (ret) { ++ ath12k_err(ab, "failed to rx reo reordering %d\n", ret); ++ goto err_spectral_deinit; ++ } ++ + return 0; + ++err_spectral_deinit: ++ ath12k_spectral_deinit(ab); + err_thermal_unregister: + ath12k_thermal_unregister(ab); + return ret; +@@ -1264,6 +1519,11 @@ int ath12k_core_qmi_firmware_ready(struc + mutex_unlock(&ab->core_lock); + + if (ath12k_core_hw_group_start_ready(ag)) { ++ /* initialize the mgmt rx re-order after ++ * mlo mem is available ++ */ ++ ath12k_mgmt_rx_reo_init_context(ab); ++ ath12k_qmi_mlo_global_snapshot_mem_init(ab); + ret = ath12k_core_hw_group_start(ag); + if (ret) { + ath12k_warn(ab, "unable to start hw group\n"); +@@ -1277,8 +1537,6 @@ int ath12k_core_qmi_firmware_ready(struc + + mutex_unlock(&ag->mutex_lock); + +- ath12k_qmi_mlo_global_snapshot_mem_init(ab); +- + /* Add code here carefully */ + return 0; + +@@ -1842,6 +2100,8 @@ int ath12k_core_init(struct ath12k_base + } + } + ++ ag->mgmt_rx_reorder = ath12k_mgmt_rx_reordering; ++ + return 0; + + err_hw_group: +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/core.h +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/core.h ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/core.h +@@ -964,6 +964,7 @@ struct ath12k { + + struct completion mvr_complete; + struct cfg80211_chan_def agile_chandef; ++ struct ath12k_mgmt_rx_reo_pdev_info rx_reo_pdev_ctx; + }; + + struct ath12k_band_cap { +@@ -1146,12 +1147,14 @@ struct ath12k_hw_group { + u8 num_hw; + bool mlo_capable; + bool hw_queues_stopped; ++ bool mgmt_rx_reorder; + unsigned long dev_flags; + struct ath12k_hw *ah[ATH12K_GROUP_MAX_RADIO]; + struct ath12k_base *ab[ATH12K_MAX_SOCS]; + struct ath12k __rcu *hw_links[ATH12K_GROUP_MAX_RADIO]; + struct ath12k_mlo_memory mlo_mem; + struct mutex mutex_lock; ++ struct ath12k_mgmt_rx_reo_context rx_reo; + struct ath12k_host_mlo_mem_arena mlomem_arena; + }; + +@@ -1270,7 +1273,6 @@ struct ath12k_base { + u32 fw_crash_counter; + u32 last_recovery_time; + } stats; +- bool mgmt_rx_reorder; + bool ftm_segment_handler; + struct ath12k_ftm_event_obj ftm_event_obj; + u32 pktlog_defs_checksum; +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/debug.h +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/debug.h ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/debug.h +@@ -27,6 +27,7 @@ enum ath12k_debug_mask { + ATH12K_DBG_DP_TX = 0x00002000, + ATH12K_DBG_DP_RX = 0x00004000, + ATH12K_DBG_OFFSET = 0x00008000, ++ ATH12K_DBG_RX_REO = 0x00010000, + ATH12K_DBG_ANY = 0xffffffff, + }; + +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/wmi.c +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/wmi.c ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/wmi.c +@@ -6741,10 +6741,60 @@ static int ath12k_wmi_tlv_mgmt_rx_parse( + parse->frame_buf_done = true; + } + break; ++ case WMI_TAG_MLO_MGMT_RX_REO_PARAMS: ++ parse->reo_params = (struct ath12k_wmi_mgmt_rx_reo_params *)ptr; ++ break; ++ case WMI_TAG_MLO_MGMT_RX_FW_CONSUMED_HDR: ++ parse->fw_consumed_reo_params = (struct ath12k_wmi_mgmt_rx_fw_consumed_hdr *)ptr; ++ break; + } + return 0; + } + ++static int ath12k_pull_fw_consumed_mgmt_rx_params_tlv(struct ath12k_base *ab, ++ struct sk_buff *skb, ++ struct mgmt_rx_event_params *hdr) ++{ ++ struct wmi_tlv_mgmt_rx_parse parse = { }; ++ int ret; ++ struct ath12k_wmi_mgmt_rx_fw_consumed_hdr *fw_con_reo_params_tlv = NULL; ++ ++ ret = ath12k_wmi_tlv_iter(ab, skb->data, skb->len, ++ ath12k_wmi_tlv_mgmt_rx_parse, ++ &parse); ++ if (ret) { ++ ath12k_warn(ab, "failed to parse mgmt rx tlv %d\n", ret); ++ return ret; ++ } ++ ++ ++ fw_con_reo_params_tlv = parse.fw_consumed_reo_params; ++ ++ if (!fw_con_reo_params_tlv) { ++ ret = -EINVAL; ++ ath12k_warn(ab, "no fw_consumed_reo_params\n"); ++ return ret; ++ } ++ ++ hdr->pdev_id = fw_con_reo_params_tlv->pdev_id; ++ hdr->reo_params.valid = FIELD_GET(WMI_MGMT_RX_FW_CONSUMED_PARAM_MGMT_PKT_CTR_VALID_GET, ++ fw_con_reo_params_tlv->mgmt_pkt_ctr_info); ++ hdr->reo_params.global_timestamp = fw_con_reo_params_tlv->global_timestamp; ++ hdr->reo_params.mgmt_pkt_ctr = FIELD_GET(WMI_MGMT_RX_FW_CONSUMED_PARAM_MGMT_PKT_CTR_GET, ++ fw_con_reo_params_tlv->mgmt_pkt_ctr_info); ++ hdr->reo_params.duration_us = fw_con_reo_params_tlv->rx_ppdu_duration_us; ++ hdr->reo_params.start_timestamp = hdr->reo_params.global_timestamp; ++ hdr->reo_params.end_timestamp = hdr->reo_params.start_timestamp + ++ hdr->reo_params.duration_us; ++ ++ ath12k_dbg(ab, ATH12K_DBG_RX_REO, "FW Consumed : Mgmt Re-order ingress: valid %u global_ts %u pkt_ctr %u\n", ++ hdr->reo_params.valid, ++ hdr->reo_params.global_timestamp, ++ hdr->reo_params.mgmt_pkt_ctr); ++ ++ return 0; ++} ++ + static int ath12k_pull_mgmt_rx_params_tlv(struct ath12k_base *ab, + struct sk_buff *skb, + struct mgmt_rx_event_params *hdr) +@@ -6753,6 +6803,7 @@ static int ath12k_pull_mgmt_rx_params_tl + const struct wmi_mgmt_rx_hdr *ev; + const u8 *frame; + int ret; ++ struct ath12k_wmi_mgmt_rx_reo_params *reo_params_tlv = NULL; + + ret = ath12k_wmi_tlv_iter(ab, skb->data, skb->len, + ath12k_wmi_tlv_mgmt_rx_parse, +@@ -6765,6 +6816,13 @@ static int ath12k_pull_mgmt_rx_params_tl + ev = parse.fixed; + frame = parse.frame_buf; + ++ reo_params_tlv = parse.reo_params; ++ if (!reo_params_tlv) { ++ ret = -EINVAL; ++ ath12k_warn(ab, "no reo_params_tlv\n"); ++ return ret; ++ } ++ + if (!ev || !frame) { + ath12k_warn(ab, "failed to fetch mgmt rx hdr"); + return -EPROTO; +@@ -6783,6 +6841,24 @@ static int ath12k_pull_mgmt_rx_params_tl + hdr->tsf_delta = ev->tsf_delta; + memcpy(hdr->rssi_ctl, ev->rssi_ctl, sizeof(hdr->rssi_ctl)); + ++ hdr->reo_params.pdev_id = ev->pdev_id; ++ ++ hdr->reo_params.valid = FIELD_GET(WMI_MGMT_RX_REO_PARAM_MGMT_PKT_CTR_VALID_GET, ++ reo_params_tlv->mgmt_pkt_ctr_link_info); ++ hdr->reo_params.global_timestamp = reo_params_tlv->global_timestamp; ++ hdr->reo_params.mgmt_pkt_ctr = FIELD_GET(WMI_MGMT_RX_REO_PARAM_MGMT_PKT_CTR_GET, ++ reo_params_tlv->mgmt_pkt_ctr_link_info); ++ hdr->reo_params.duration_us = reo_params_tlv->rx_ppdu_duration_us; ++ hdr->reo_params.start_timestamp = hdr->reo_params.global_timestamp; ++ hdr->reo_params.end_timestamp = hdr->reo_params.start_timestamp + ++ hdr->reo_params.duration_us; ++ ++ ath12k_dbg(ab, ATH12K_DBG_RX_REO, "Mgmt Re-order ingress: channel %d valid %u global_ts %u pkt_ctr %u\n", ++ hdr->channel, ++ hdr->reo_params.valid, ++ hdr->reo_params.global_timestamp, ++ hdr->reo_params.mgmt_pkt_ctr); ++ + if (skb->len < (frame - skb->data) + hdr->buf_len) { + ath12k_warn(ab, "invalid length in mgmt rx hdr ev"); + return -EPROTO; +@@ -8243,9 +8319,2329 @@ static void ath12k_vdev_stopped_event(st + ath12k_dbg(ab, ATH12K_DBG_WMI, "vdev stopped for vdev id %d", vdev_id); + } + ++/** ++ * ath12k_mgmt_rx_reo_compare_pkt_ctrs_gte() - Compare given mgmt packet counters ++ * @ctr1: Management packet counter1 ++ * @ctr2: Management packet counter2 ++ * ++ * We can't directly use the comparison operator here because the counters can ++ * overflow. But these counters have a property that the difference between ++ * them can never be greater than half the range of the data type. ++ * We can make use of this condition to detect which one is actually greater. ++ * ++ * Return: true if @ctr1 is greater than or equal to @ctr2, else false ++ */ ++static inline bool ++ath12k_mgmt_rx_reo_compare_pkt_ctrs_gte(u16 ctr1, u16 ctr2) ++{ ++ u16 delta = ctr1 - ctr2; ++ ++ return delta <= ATH12K_MGMT_RX_REO_PKT_CTR_HALF_RANGE; ++} ++ ++/** ++ * ath12k_mgmt_rx_reo_subtract_pkt_ctrs() - Subtract given mgmt packet counters ++ * @ctr1: Management packet counter1 ++ * @ctr2: Management packet counter2 ++ * ++ * We can't directly use the subtract operator here because the counters can ++ * overflow. But these counters have a property that the difference between ++ * them can never be greater than half the range of the data type. ++ * We can make use of this condition to detect whichone is actually greater and ++ * return the difference accordingly. ++ * ++ * Return: Difference between @ctr1 and @crt2 ++ */ ++static inline int ++ath12k_mgmt_rx_reo_subtract_pkt_ctrs(u16 ctr1, u16 ctr2) ++{ ++ u16 delta = ctr1 - ctr2; ++ ++ /** ++ * if delta is greater than half the range (i.e, ctr1 is actually ++ * smaller than ctr2), then the result should be a negative number. ++ * subtracting the entire range should give the correct value. ++ */ ++ if (delta > ATH12K_MGMT_RX_REO_PKT_CTR_HALF_RANGE) ++ return delta - ATH12K_MGMT_RX_REO_PKT_CTR_FULL_RANGE; ++ ++ return delta; ++} ++ ++#define ATH12K_MGMT_RX_REO_GLOBAL_TS_HALF_RANGE (0x80000000) ++/** ++ * ath12k_mgmt_rx_reo_compare_global_timestamps_gte()-Compare given global timestamps ++ * @ts1: Global timestamp1 ++ * @ts2: Global timestamp2 ++ * ++ * We can't directly use the comparison operator here because the timestamps can ++ * overflow. But these timestamps have a property that the difference between ++ * them can never be greater than half the range of the data type. ++ * We can make use of this condition to detect which one is actually greater. ++ * ++ * Return: true if @ts1 is greater than or equal to @ts2, else false ++ */ ++static inline bool ++ath12k_mgmt_rx_reo_compare_global_timestamps_gte(u32 ts1, u32 ts2) ++{ ++ u32 delta = ts1 - ts2; ++ ++ return delta <= ATH12K_MGMT_RX_REO_GLOBAL_TS_HALF_RANGE; ++} ++ ++#define ATH12K_RX_REO_REORD_MAX_DELTA 0xFFFF ++/** ++ * ath12k_wlan_mgmt_rx_reo_update_host_snapshot() - Update Host snapshot with the MGMT ++ * Rx REO parameters. ++ * @desc: pointer to frame descriptor ++ * ++ * Return: 0 on Success, Error value on failure of operation ++ */ ++static int ++ath12k_wlan_mgmt_rx_reo_update_host_snapshot(struct ath12k *ar, ++ struct ath12k_mgmt_rx_reo_frame_descriptor *desc) ++{ ++ struct ath12k_base *ab = ar->ab; ++ struct ath12k_mgmt_rx_reo_pdev_info *rx_reo_pdev_ctx; ++ struct ath12k_mgmt_rx_reo_snapshot_params *host_ss; ++ struct ath12k_mgmt_rx_reo_params *reo_params; ++ int pkt_ctr_delta; ++ ++ if (!desc) { ++ ath12k_err(ab, "Mgmt Rx REO frame descriptor null\n"); ++ return -EINVAL; ++ } ++ ++ if (!desc->rx_params) { ++ ath12k_err(ab, "Mgmt Rx params NULL\n"); ++ return -EINVAL; ++ } ++ ++ reo_params = &desc->rx_params->reo_params; ++ ++ rx_reo_pdev_ctx = &ar->rx_reo_pdev_ctx; ++ if (!rx_reo_pdev_ctx) { ++ ath12k_err(ab, "Mgmt Rx REO context empty for pdev\n"); ++ return -EINVAL; ++ } ++ ++ /* FW should send valid REO parameters */ ++ if (!reo_params->valid) { ++ ath12k_err(ab, "Mgmt Rx REO params is invalid\n"); ++ return -EINVAL; ++ } ++ ++ host_ss = &rx_reo_pdev_ctx->host_snapshot; ++ ++ if (!host_ss->valid) { ++ desc->pkt_ctr_delta = 1; ++ goto update_host_ss; ++ } ++ ++ if (ath12k_mgmt_rx_reo_compare_pkt_ctrs_gte(host_ss->mgmt_pkt_ctr, ++ reo_params->mgmt_pkt_ctr)) { ++ ath12k_err(ab, "Cur frame ctr < last frame ctr for link = %u", ++ reo_params->link_id); ++ goto failure_debug; ++ } ++ ++ pkt_ctr_delta = ath12k_mgmt_rx_reo_subtract_pkt_ctrs(reo_params->mgmt_pkt_ctr, ++ host_ss->mgmt_pkt_ctr); ++ WARN_ON(!(pkt_ctr_delta > 0)); ++ desc->pkt_ctr_delta = pkt_ctr_delta; ++ ++ if (pkt_ctr_delta == 1) ++ goto update_host_ss; ++ ++ /* Under back pressure scenarios, FW may drop management Rx frame ++ * WMI events. So holes in the management packet counter is expected. ++ * Add a debug print and optional assert to track the holes. ++ */ ++ ath12k_dbg(ab, ATH12K_DBG_RX_REO, "---- Rx reo reordering(this info is seen since pkt_ctr_delta > 0) ----\n"); ++ ath12k_dbg(ab, ATH12K_DBG_RX_REO, "pkt_ctr_delta = %u\n", pkt_ctr_delta); ++ ath12k_dbg(ab, ATH12K_DBG_RX_REO, "Cur frame valid = %u, pkt_ctr = %u, ts =%u\n", ++ reo_params->valid, reo_params->mgmt_pkt_ctr, ++ reo_params->global_timestamp); ++ ath12k_dbg(ab, ATH12K_DBG_RX_REO, "Last frame valid = %u, pkt_ctr = %u, ts =%u\n", ++ host_ss->valid, host_ss->mgmt_pkt_ctr, ++ host_ss->global_timestamp); ++ ++ if (pkt_ctr_delta > ATH12K_RX_REO_REORD_MAX_DELTA) { ++ ath12k_err(ab, "pkt ctr delta %u > thresh %u for link %u", ++ pkt_ctr_delta, ATH12K_RX_REO_REORD_MAX_DELTA, ++ reo_params->link_id); ++ goto failure_debug; ++ } ++ ++update_host_ss: ++ ath12k_dbg(ab, ATH12K_DBG_RX_REO, "Last frame valid = %u, pkt_ctr = %u, ts =%u\n", ++ host_ss->valid, host_ss->mgmt_pkt_ctr, ++ host_ss->global_timestamp); ++ ++ host_ss->valid = true; ++ host_ss->global_timestamp = reo_params->global_timestamp; ++ host_ss->mgmt_pkt_ctr = reo_params->mgmt_pkt_ctr; ++ ++ return 0; ++ ++failure_debug: ++ ath12k_err(ab, "Cur frame valid = %u, pkt_ctr = %u, ts =%u\n", ++ reo_params->valid, reo_params->mgmt_pkt_ctr, ++ reo_params->global_timestamp); ++ ath12k_err(ab, "Last frame valid = %u, pkt_ctr = %u, ts =%u\n", ++ host_ss->valid, host_ss->mgmt_pkt_ctr, ++ host_ss->global_timestamp); ++ WARN_ON(1); ++ ++ return -EINVAL; ++} ++ ++/** ++ * ath12k_wmi_mgmt_rx_reo_read_snapshot_raw() - Read raw value of management ++ * rx-reorder snapshot ++ * @snapshot_address: snapshot address ++ * @ath12k_mgmt_rx_reo_snapshot_low: Pointer to lower 32 bits of snapshot value ++ * @ath12k_mgmt_rx_reo_snapshot_high: Pointer to higher 32 bits of snapshot value ++ * @snapshot_version: snapshot version ++ * ++ * Read raw value of management rx-reorder snapshots. ++ * ++ * Return: 0 on Success, Error value on failure ++ */ ++static int ++ath12k_wmi_mgmt_rx_reo_read_snapshot_raw ++ (struct ath12k_mgmt_rx_reo_shared_snapshot *snapshot_address, ++ u32 *ath12k_mgmt_rx_reo_snapshot_low, ++ u32 *ath12k_mgmt_rx_reo_snapshot_high, ++ u8 snapshot_version, ++ struct ath12k_mgmt_rx_reo_shared_snapshot *raw_snapshot) ++{ ++ u32 prev_snapshot_low; ++ u32 prev_snapshot_high; ++ u32 cur_snapshot_low; ++ u32 cur_snapshot_high; ++ u8 retry_count = 0; ++ ++ if (snapshot_version == 1) { ++ *ath12k_mgmt_rx_reo_snapshot_low = ++ snapshot_address->u_low.ath12k_mgmt_rx_reo_snapshot_low; ++ *ath12k_mgmt_rx_reo_snapshot_high = ++ snapshot_address->u_high.ath12k_mgmt_rx_reo_snapshot_high; ++ raw_snapshot->u_low.ath12k_mgmt_rx_reo_snapshot_low = ++ *ath12k_mgmt_rx_reo_snapshot_low; ++ raw_snapshot->u_high.ath12k_mgmt_rx_reo_snapshot_high = ++ *ath12k_mgmt_rx_reo_snapshot_high; ++ return 0; ++ } ++ ++ prev_snapshot_low = snapshot_address->u_low.ath12k_mgmt_rx_reo_snapshot_low; ++ prev_snapshot_high = snapshot_address->u_high.ath12k_mgmt_rx_reo_snapshot_high; ++ raw_snapshot->u_low.ath12k_mgmt_rx_reo_snapshot_low = prev_snapshot_low; ++ raw_snapshot->u_high.ath12k_mgmt_rx_reo_snapshot_high = prev_snapshot_high; ++ ++ for (; retry_count < (ATH12K_MGMT_RX_REO_SNAPSHOT_B2B_READ_SWAR_RETRY_LIMIT - 1); ++ retry_count++) { ++ cur_snapshot_low = snapshot_address->u_low.ath12k_mgmt_rx_reo_snapshot_low; ++ cur_snapshot_high = snapshot_address->u_high.ath12k_mgmt_rx_reo_snapshot_high; ++ ++ raw_snapshot[retry_count + 1].u_low.ath12k_mgmt_rx_reo_snapshot_low = ++ cur_snapshot_low; ++ raw_snapshot[retry_count + 1].u_high.ath12k_mgmt_rx_reo_snapshot_high = ++ cur_snapshot_high; ++ ++ if (prev_snapshot_low == cur_snapshot_low && ++ prev_snapshot_high == cur_snapshot_high) ++ break; ++ ++ prev_snapshot_low = cur_snapshot_low; ++ prev_snapshot_high = cur_snapshot_high; ++ } ++ ++ WARN_ON(retry_count == ++ (ATH12K_MGMT_RX_REO_SNAPSHOT_B2B_READ_SWAR_RETRY_LIMIT - 1)); ++ ++ *ath12k_mgmt_rx_reo_snapshot_low = cur_snapshot_low; ++ *ath12k_mgmt_rx_reo_snapshot_high = cur_snapshot_high; ++ ++ return 0; ++} ++ ++/** ++ * Helper macros/functions for params GET/SET of different hw version ++ * of the mgmt_rx_reo_snapshot ++ */ ++ ++static inline u8 ++ath12k_mlo_shmem_mgmt_rx_reo_snapshot_valid_get(struct ath12k_base *ab, ++ u32 ath12k_mgmt_rx_reo_snapshot_low, ++ u8 snapshot_ver) ++{ ++ if ((snapshot_ver != ATH12K_MGMT_RX_REO_SNAPSHOT_VERSION_TIMESTAMP_REDUNDANCY) && ++ (snapshot_ver != ATH12K_MGMT_RX_REO_SNAPSHOT_VERSION_PKT_CTR_REDUNDANCY)) { ++ ath12k_err(ab, "Check this error snapshot ver %d\n", snapshot_ver); ++ WARN_ON(1); ++ } ++ ++ return ATH12K_MLO_SHMEM_GET_BITS(ath12k_mgmt_rx_reo_snapshot_low, 31, 1); ++} ++ ++static inline u32 ++ath12k_mlo_shmem_mgmt_rx_reo_snapshot_global_timestamp_get( ++ struct ath12k_base *ab, ++ u32 ath12k_mgmt_rx_reo_snapshot_low, ++ u32 ath12k_mgmt_rx_reo_snapshot_high, ++ u8 snapshot_ver) ++{ ++ if (snapshot_ver == ATH12K_MGMT_RX_REO_SNAPSHOT_VERSION_TIMESTAMP_REDUNDANCY) { ++ return ath12k_mgmt_rx_reo_snapshot_high; ++ } else if (snapshot_ver == ATH12K_MGMT_RX_REO_SNAPSHOT_VERSION_PKT_CTR_REDUNDANCY) { ++ return ++ ((ATH12K_MLO_SHMEM_GET_BITS(ath12k_mgmt_rx_reo_snapshot_high, 15, 17) << 15) | ++ ATH12K_MLO_SHMEM_GET_BITS(ath12k_mgmt_rx_reo_snapshot_low, 0, 15)); ++ } else { ++ ath12k_err(ab, "Check this error snapshot ver %d\n", snapshot_ver); ++ WARN_ON(1); ++ return 0; ++ } ++} ++ ++static inline u16 ++mlo_shmem_mgmt_rx_reo_snapshot_mgmt_pkt_ctr_get( ++ struct ath12k_base *ab, ++ u32 ath12k_mgmt_rx_reo_snapshot_low, u8 snapshot_ver) ++{ ++ if (snapshot_ver == ATH12K_MGMT_RX_REO_SNAPSHOT_VERSION_TIMESTAMP_REDUNDANCY) { ++ return ATH12K_MLO_SHMEM_GET_BITS(ath12k_mgmt_rx_reo_snapshot_low, 0, 16); ++ } else if (snapshot_ver == ATH12K_MGMT_RX_REO_SNAPSHOT_VERSION_PKT_CTR_REDUNDANCY) { ++ return ATH12K_MLO_SHMEM_GET_BITS(ath12k_mgmt_rx_reo_snapshot_low, 15, 16); ++ } else { ++ ath12k_err(ab, "Check this error snapshot ver %d\n", snapshot_ver); ++ WARN_ON(1); ++ return 0; ++ } ++} ++ ++#define ATH12K_MLO_SHMEM_MGMT_RX_REO_SNAPSHOT_MGMT_PKT_CTR_REDUNDANT_GET( \ ++ ath12k_mgmt_rx_reo_snapshot_high) \ ++ ATH12K_MLO_SHMEM_GET_BITS(ath12k_mgmt_rx_reo_snapshot_high, 0, 15) ++ ++#define ATH12K_MLO_SHMEM_MGMT_RX_REO_SNAPSHOT_GLOBAL_TIMESTAMP_REDUNDANT_GET( \ ++ ath12k_mgmt_rx_reo_snapshot_low) \ ++ ATH12K_MLO_SHMEM_GET_BITS(ath12k_mgmt_rx_reo_snapshot_low, 16, 15) ++ ++static inline bool ++ath12k_mlo_shmem_mgmt_rx_reo_snapshot_check_consistency( ++ struct ath12k_base *ab, ++ u32 ath12k_mgmt_rx_reo_snapshot_low, ++ u32 ath12k_mgmt_rx_reo_snapshot_high, ++ u8 snapshot_ver) ++{ ++ if (snapshot_ver == ATH12K_MGMT_RX_REO_SNAPSHOT_VERSION_TIMESTAMP_REDUNDANCY) { ++ u32 global_timestamp; ++ u32 global_timestamp_redundant; ++ ++ global_timestamp = ++ ath12k_mlo_shmem_mgmt_rx_reo_snapshot_global_timestamp_get(ab, ++ ath12k_mgmt_rx_reo_snapshot_low, ++ ath12k_mgmt_rx_reo_snapshot_high, ++ snapshot_ver); ++ global_timestamp_redundant = ++ ATH12K_MLO_SHMEM_MGMT_RX_REO_SNAPSHOT_GLOBAL_TIMESTAMP_REDUNDANT_GET( ++ ath12k_mgmt_rx_reo_snapshot_low); ++ ++ return ++ (ATH12K_MLO_SHMEM_GET_BITS(global_timestamp, 0, 15) == ++ ATH12K_MLO_SHMEM_GET_BITS(global_timestamp_redundant, 0, 15)); ++ } else if (snapshot_ver == ATH12K_MGMT_RX_REO_SNAPSHOT_VERSION_PKT_CTR_REDUNDANCY) { ++ u16 mgmt_pkt_ctr; ++ u16 mgmt_pkt_ctr_redundant; ++ ++ mgmt_pkt_ctr = mlo_shmem_mgmt_rx_reo_snapshot_mgmt_pkt_ctr_get(ab, ++ ath12k_mgmt_rx_reo_snapshot_low, snapshot_ver); ++ mgmt_pkt_ctr_redundant = ++ ATH12K_MLO_SHMEM_MGMT_RX_REO_SNAPSHOT_MGMT_PKT_CTR_REDUNDANT_GET( ++ ath12k_mgmt_rx_reo_snapshot_high); ++ ++ return ++ (ATH12K_MLO_SHMEM_GET_BITS(mgmt_pkt_ctr, 0, 15) == ++ ATH12K_MLO_SHMEM_GET_BITS(mgmt_pkt_ctr_redundant, 0, 15)); ++ } else { ++ ath12k_err(ab, "Check this error snapshot ver %d\n", snapshot_ver); ++ WARN_ON(1); ++ return 0; ++ } ++} ++ ++/** ++ * ath12k_mgmt_rx_reo_snapshot_get_mgmt_pkt_ctr() - Get the management packet counter ++ * from an MGMT Rx REO snapshot ++ * @snapshot_low: lower 32-bits of the snapshot ++ * @snapshot_version: snapshot version ++ * ++ * Return: Management packet counter of the snapshot ++ */ ++static u16 ath12k_mgmt_rx_reo_snapshot_get_mgmt_pkt_ctr( ++ struct ath12k_base *ab, ++ u32 mgmt_rx_reo_snapshot_low, ++ u8 snapshot_version) ++{ ++ if (snapshot_version == MGMT_RX_REO_SNAPSHOT_VERSION_TIMESTAMP_REDUNDANCY) { ++ return ATH12K_MLO_SHMEM_GET_BITS(mgmt_rx_reo_snapshot_low, 0, 16); ++ } else if (snapshot_version == MGMT_RX_REO_SNAPSHOT_VERSION_PKT_CTR_REDUNDANCY) { ++ return ATH12K_MLO_SHMEM_GET_BITS(mgmt_rx_reo_snapshot_low, 15, 16); ++ } else { ++ ath12k_err(ab, "Check this error snapshot ver %d\n", snapshot_version); ++ WARN_ON(1); ++ return 0; ++ } ++} ++ ++/** ++ * ath12k_wmi_mgmt_rx_reo_read_snapshot() - Read management rx-reorder snapshot ++ * @pdev: pdev pointer ++ * @snapshot_info: Snapshot info ++ * @id: Snapshot ID ++ * @snapshot_value: Pointer to snapshot value ++ * ++ * Read management rx-reorder snapshots from target. ++ * ++ * Return: 0 on Success, Error value on failure ++ */ ++static int ++ath12k_wmi_mgmt_rx_reo_read_snapshot( ++ struct ath12k *ar, ++ struct ath12k_mgmt_rx_reo_snapshot_info *snapshot_info, ++ enum ath12k_mgmt_rx_reo_shared_snapshot_id id, ++ struct ath12k_mgmt_rx_reo_snapshot_params *snapshot_value, ++ struct ath12k_mgmt_rx_reo_shared_snapshot (*raw_snapshot) ++ [ATH12K_MGMT_RX_REO_SNAPSHOT_B2B_READ_SWAR_RETRY_LIMIT]) ++{ ++ struct ath12k_base *ab = ar->ab; ++ bool snapshot_valid; ++ u16 mgmt_pkt_ctr; ++ u32 global_timestamp; ++ u32 ath12k_mgmt_rx_reo_snapshot_low; ++ u32 ath12k_mgmt_rx_reo_snapshot_high; ++ u8 retry_count; ++ int status; ++ struct ath12k_mgmt_rx_reo_shared_snapshot *snapshot_address; ++ u8 snapshot_version; ++ ++ if (!snapshot_info) { ++ ath12k_err(ab, "Mgmt Rx REO snapshot info null\n"); ++ return -EINVAL; ++ } ++ ++ snapshot_address = snapshot_info->address; ++ if (!snapshot_address) { ++ ath12k_err(ab, "Mgmt Rx REO snapshot address null\n"); ++ return -EINVAL; ++ } ++ ++ snapshot_version = snapshot_info->version; ++ ++ if (!snapshot_value) { ++ ath12k_err(ab, "Mgmt Rx REO snapshot null\n"); ++ return -EINVAL; ++ } ++ ++ memset(snapshot_value, 0, sizeof(*snapshot_value)); ++ ++ switch (id) { ++ case ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_MAC_HW: ++ case ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_FW_CONSUMED: ++ case ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_FW_FORWARDED: ++ retry_count = 0; ++ for (; retry_count < ATH12K_MGMT_RX_REO_SNAPSHOT_READ_RETRY_LIMIT; ++ retry_count++) { ++ status = ath12k_wmi_mgmt_rx_reo_read_snapshot_raw ++ (snapshot_address, ++ &ath12k_mgmt_rx_reo_snapshot_low, ++ &ath12k_mgmt_rx_reo_snapshot_high, ++ snapshot_version, ++ raw_snapshot[retry_count]); ++ ++ if (status) { ++ ath12k_err(ab, "Failed to read snapshot %d status %d\n", ++ id, status); ++ return -EINVAL; ++ } ++ ++ snapshot_valid = ath12k_mlo_shmem_mgmt_rx_reo_snapshot_valid_get(ab, ++ ath12k_mgmt_rx_reo_snapshot_low, ++ snapshot_version); ++ ++ if (!snapshot_valid) { ++ ath12k_dbg(ab, ATH12K_DBG_RX_REO, "Invalid REO snapshot value"); ++ snapshot_value->valid = false; ++ snapshot_value->mgmt_pkt_ctr = ++ ath12k_mgmt_rx_reo_snapshot_get_mgmt_pkt_ctr ++ (ab, ath12k_mgmt_rx_reo_snapshot_low, ++ snapshot_version); ++ snapshot_value->global_timestamp = ++ ath12k_mlo_shmem_mgmt_rx_reo_snapshot_global_timestamp_get ++ (ab, ath12k_mgmt_rx_reo_snapshot_low, ++ ath12k_mgmt_rx_reo_snapshot_high, ++ snapshot_version); ++ snapshot_value->retry_count = retry_count + 1; ++ return 0; ++ } ++ ++ if (ath12k_mlo_shmem_mgmt_rx_reo_snapshot_check_consistency ++ (ar->ab, ath12k_mgmt_rx_reo_snapshot_low, ++ ath12k_mgmt_rx_reo_snapshot_high, ++ snapshot_version)) { ++ global_timestamp = ++ ath12k_mlo_shmem_mgmt_rx_reo_snapshot_global_timestamp_get ++ (ab, ath12k_mgmt_rx_reo_snapshot_low, ++ ath12k_mgmt_rx_reo_snapshot_high, ++ snapshot_version); ++ mgmt_pkt_ctr = ++ mlo_shmem_mgmt_rx_reo_snapshot_mgmt_pkt_ctr_get ++ (ab, ath12k_mgmt_rx_reo_snapshot_low, ++ snapshot_version); ++ break; ++ } ++ ath12k_info(ab, "Inconsistent snapshot %d, version=%u, low=0x%x, high=0x%x, retry=%u\n", ++ id, snapshot_version, ++ ath12k_mgmt_rx_reo_snapshot_low, ++ ath12k_mgmt_rx_reo_snapshot_high, ++ retry_count); ++ } ++ ++ if (retry_count == ATH12K_MGMT_RX_REO_SNAPSHOT_READ_RETRY_LIMIT) { ++ ath12k_err(ab, "Read retry limit, id = %d, ver = %u\n", ++ id, snapshot_version); ++ WARN_ON(1); ++ return -EINVAL; ++ } ++ ++ snapshot_value->valid = true; ++ snapshot_value->mgmt_pkt_ctr = mgmt_pkt_ctr; ++ snapshot_value->global_timestamp = global_timestamp; ++ snapshot_value->retry_count = retry_count + 1; ++ status = 0; ++ break; ++ ++ default: ++ ath12k_err(ab, "Invalid snapshot id %d\n", id); ++ status = -EINVAL; ++ break; ++ } ++ ++ return status; ++} ++ ++/** ++ * ath12k_mgmt_rx_reo_print_snapshots() - Print all snapshots related ++ * to management Rx reorder module ++ * @mac_hw_ss: MAC HW snapshot ++ * @fw_forwarded_ss: FW forwarded snapshot ++ * @fw_consumed_ss: FW consumed snapshot ++ * @host_ss: Host snapshot ++ * ++ * return: int ++ */ ++static int ++ath12k_mgmt_rx_reo_print_snapshots ++ (struct ath12k_base *ab, ++ struct ath12k_mgmt_rx_reo_snapshot_params *mac_hw_ss, ++ struct ath12k_mgmt_rx_reo_snapshot_params *fw_forwarded_ss, ++ struct ath12k_mgmt_rx_reo_snapshot_params *fw_consumed_ss, ++ struct ath12k_mgmt_rx_reo_snapshot_params *host_ss) ++{ ++ ath12k_dbg(ab, ATH12K_DBG_RX_REO, "HW SS: valid = %u, ctr = %u, ts = %u\n", ++ mac_hw_ss->valid, mac_hw_ss->mgmt_pkt_ctr, ++ mac_hw_ss->global_timestamp); ++ ath12k_dbg(ab, ATH12K_DBG_RX_REO, "FW forwarded SS: valid = %u, ctr = %u, ts = %u\n", ++ fw_forwarded_ss->valid, ++ fw_forwarded_ss->mgmt_pkt_ctr, ++ fw_forwarded_ss->global_timestamp); ++ ath12k_dbg(ab, ATH12K_DBG_RX_REO, "FW consumed SS: valid = %u, ctr = %u, ts = %u\n", ++ fw_consumed_ss->valid, ++ fw_consumed_ss->mgmt_pkt_ctr, ++ fw_consumed_ss->global_timestamp); ++ ath12k_dbg(ab, ATH12K_DBG_RX_REO, "HOST SS: valid = %u, ctr = %u, ts = %u\n", ++ host_ss->valid, host_ss->mgmt_pkt_ctr, ++ host_ss->global_timestamp); ++ ++ return 0; ++} ++ ++/** ++ * ath12k_wmi_mgmt_rx_reo_invalidate_stale_snapshots() - Invalidate stale management ++ * Rx REO snapshots ++ * @mac_hw_ss: MAC HW snapshot ++ * @fw_forwarded_ss: FW forwarded snapshot ++ * @fw_consumed_ss: FW consumed snapshot ++ * @host_ss: Host snapshot ++ * @link: link ID ++ * ++ * return: int ++ */ ++static int ++ath12k_wmi_mgmt_rx_reo_invalidate_stale_snapshots ++ (struct ath12k *ar, ++ struct ath12k_mgmt_rx_reo_snapshot_params *mac_hw_ss, ++ struct ath12k_mgmt_rx_reo_snapshot_params *fw_forwarded_ss, ++ struct ath12k_mgmt_rx_reo_snapshot_params *fw_consumed_ss, ++ struct ath12k_mgmt_rx_reo_snapshot_params *host_ss, ++ u8 link) ++{ ++ struct ath12k_base *ab = ar->ab; ++ ++ if (!mac_hw_ss->valid) ++ return 0; ++ ++ if (host_ss->valid) { ++ if (!ath12k_mgmt_rx_reo_compare_global_timestamps_gte ++ (mac_hw_ss->global_timestamp, ++ host_ss->global_timestamp) || ++ !ath12k_mgmt_rx_reo_compare_pkt_ctrs_gte ++ (mac_hw_ss->mgmt_pkt_ctr, ++ host_ss->mgmt_pkt_ctr)) { ++ ath12k_mgmt_rx_reo_print_snapshots(ab, mac_hw_ss, fw_forwarded_ss, ++ fw_consumed_ss, host_ss); ++ ath12k_dbg(ab, ATH12K_DBG_RX_REO, "Invalidate host snapshot, link %u", ++ link); ++ host_ss->valid = false; ++ } ++ } ++ ++ if (fw_forwarded_ss->valid) { ++ if (!ath12k_mgmt_rx_reo_compare_global_timestamps_gte ++ (mac_hw_ss->global_timestamp, ++ fw_forwarded_ss->global_timestamp) || ++ !ath12k_mgmt_rx_reo_compare_pkt_ctrs_gte ++ (mac_hw_ss->mgmt_pkt_ctr, ++ fw_forwarded_ss->mgmt_pkt_ctr)) { ++ ath12k_mgmt_rx_reo_print_snapshots(ab, mac_hw_ss, fw_forwarded_ss, ++ fw_consumed_ss, host_ss); ++ ath12k_dbg(ab, ATH12K_DBG_RX_REO, "Invalidate FW forwarded SS, link %u\n", ++ link); ++ fw_forwarded_ss->valid = false; ++ } ++ } ++ ++ if (host_ss->valid && fw_forwarded_ss->valid && ++ (ath12k_mgmt_rx_reo_compare_global_timestamps_gte ++ (host_ss->global_timestamp, ++ fw_forwarded_ss->global_timestamp) != ++ ath12k_mgmt_rx_reo_compare_pkt_ctrs_gte ++ (host_ss->mgmt_pkt_ctr, ++ fw_forwarded_ss->mgmt_pkt_ctr))) { ++ ath12k_mgmt_rx_reo_print_snapshots(ab, mac_hw_ss, fw_forwarded_ss, ++ fw_consumed_ss, host_ss); ++ ath12k_dbg(ab, ATH12K_DBG_RX_REO, "Invalidate FW forwarded SS, link %u", ++ link); ++ fw_forwarded_ss->valid = false; ++ } ++ ++ if (fw_consumed_ss->valid) { ++ if (!ath12k_mgmt_rx_reo_compare_global_timestamps_gte ++ (mac_hw_ss->global_timestamp, ++ fw_consumed_ss->global_timestamp) || ++ !ath12k_mgmt_rx_reo_compare_pkt_ctrs_gte ++ (mac_hw_ss->mgmt_pkt_ctr, ++ fw_consumed_ss->mgmt_pkt_ctr)) { ++ ath12k_mgmt_rx_reo_print_snapshots(ab, mac_hw_ss, fw_forwarded_ss, ++ fw_consumed_ss, host_ss); ++ ath12k_dbg(ab, ATH12K_DBG_RX_REO, "Invalidate FW consumed SS, link %u\n", ++ link); ++ fw_consumed_ss->valid = false; ++ } ++ if (host_ss->valid && fw_consumed_ss->valid && ++ (ath12k_mgmt_rx_reo_compare_global_timestamps_gte ++ (host_ss->global_timestamp, ++ fw_consumed_ss->global_timestamp) != ++ ath12k_mgmt_rx_reo_compare_pkt_ctrs_gte ++ (host_ss->mgmt_pkt_ctr, ++ fw_consumed_ss->mgmt_pkt_ctr))) { ++ ath12k_mgmt_rx_reo_print_snapshots(ab, mac_hw_ss, fw_forwarded_ss, ++ fw_consumed_ss, host_ss); ++ ath12k_dbg(ab, ATH12K_DBG_RX_REO, "Invalidate FW consumed SS, link %u", ++ link); ++ fw_consumed_ss->valid = false; ++ } ++ } ++ ++ return 0; ++} ++ ++/** ++ * mgmt_rx_reo_snapshots_check_sanity() - Check the sanity of management ++ * Rx REO snapshots ++ * @mac_hw_ss: MAC HW snapshot ++ * @fw_forwarded_ss: FW forwarded snapshot ++ * @fw_consumed_ss: FW consumed snapshot ++ * @host_ss: Host snapshot ++ * ++ * return: int ++ */ ++static int ++mgmt_rx_reo_snapshots_check_sanity ++ (struct ath12k *ar, ++ struct ath12k_mgmt_rx_reo_snapshot_params *mac_hw_ss, ++ struct ath12k_mgmt_rx_reo_snapshot_params *fw_forwarded_ss, ++ struct ath12k_mgmt_rx_reo_snapshot_params *fw_consumed_ss, ++ struct ath12k_mgmt_rx_reo_snapshot_params *host_ss) ++{ ++ int status; ++ struct ath12k_base *ab = ar->ab; ++ ++ if (!mac_hw_ss->valid) { ++ if (fw_forwarded_ss->valid || fw_consumed_ss->valid || ++ host_ss->valid) { ++ ath12k_err(ab, "MAC HW SS is invalid\n"); ++ status = -EINVAL; ++ goto fail; ++ } ++ ++ return 0; ++ } ++ ++ if (!fw_forwarded_ss->valid && !fw_consumed_ss->valid) { ++ if (host_ss->valid) { ++ ath12k_err(ab, "FW forwarded and consumed SS invalid\n"); ++ status = -EINVAL; ++ goto fail; ++ } ++ ++ return 0; ++ } ++ ++ if (fw_forwarded_ss->valid) { ++ if (!ath12k_mgmt_rx_reo_compare_global_timestamps_gte ++ (mac_hw_ss->global_timestamp, ++ fw_forwarded_ss->global_timestamp)) { ++ ath12k_err(ab, "TS: MAC HW SS < FW forwarded SS\n"); ++ status = -EINVAL; ++ goto fail; ++ } ++ ++ if (!ath12k_mgmt_rx_reo_compare_pkt_ctrs_gte ++ (mac_hw_ss->mgmt_pkt_ctr, ++ fw_forwarded_ss->mgmt_pkt_ctr)) { ++ ath12k_err(ab, "PKT CTR: MAC HW SS < FW forwarded SS\n"); ++ status = -EINVAL; ++ goto fail; ++ } ++ } ++ ++ if (fw_consumed_ss->valid) { ++ if (!ath12k_mgmt_rx_reo_compare_global_timestamps_gte ++ (mac_hw_ss->global_timestamp, ++ fw_consumed_ss->global_timestamp)) { ++ ath12k_err(ab, "TS: MAC HW SS < FW consumed SS\n"); ++ status = -EINVAL; ++ goto fail; ++ } ++ ++ if (!ath12k_mgmt_rx_reo_compare_pkt_ctrs_gte ++ (mac_hw_ss->mgmt_pkt_ctr, ++ fw_consumed_ss->mgmt_pkt_ctr)) { ++ ath12k_err(ab, "PKT CTR: MAC HW SS < FW consumed SS\n"); ++ status = -EINVAL; ++ goto fail; ++ } ++ } ++ ++ if (host_ss->valid) { ++ if (!ath12k_mgmt_rx_reo_compare_global_timestamps_gte ++ (mac_hw_ss->global_timestamp, ++ host_ss->global_timestamp)) { ++ ath12k_err(ab, "TS: MAC HW SS < host SS\n"); ++ status = -EINVAL; ++ goto fail; ++ } ++ ++ if (!ath12k_mgmt_rx_reo_compare_pkt_ctrs_gte ++ (mac_hw_ss->mgmt_pkt_ctr, ++ host_ss->mgmt_pkt_ctr)) { ++ ath12k_err(ab, "PKT CTR: MAC HW SS < host SS\n"); ++ status = -EINVAL; ++ goto fail; ++ } ++ ++ if (fw_forwarded_ss->valid && !fw_consumed_ss->valid) { ++ if (!ath12k_mgmt_rx_reo_compare_global_timestamps_gte ++ (fw_forwarded_ss->global_timestamp, ++ host_ss->global_timestamp)) { ++ ath12k_err(ab, "TS: FW forwarded < host SS\n"); ++ status = -EINVAL; ++ goto fail; ++ } ++ ++ if (!ath12k_mgmt_rx_reo_compare_pkt_ctrs_gte ++ (fw_forwarded_ss->mgmt_pkt_ctr, ++ host_ss->mgmt_pkt_ctr)) { ++ ath12k_err(ab, "CTR: FW forwarded < host SS\n"); ++ status = -EINVAL; ++ goto fail; ++ } ++ } ++ ++ if (fw_consumed_ss->valid && !fw_forwarded_ss->valid) { ++ if (!ath12k_mgmt_rx_reo_compare_global_timestamps_gte ++ (fw_consumed_ss->global_timestamp, ++ host_ss->global_timestamp)) { ++ ath12k_err(ab, "TS: FW consumed < host SS\n"); ++ status = -EINVAL; ++ goto fail; ++ } ++ ++ if (!ath12k_mgmt_rx_reo_compare_pkt_ctrs_gte ++ (fw_consumed_ss->mgmt_pkt_ctr, ++ host_ss->mgmt_pkt_ctr)) { ++ ath12k_err(ab, "CTR: FW consumed < host SS\n"); ++ status = -EINVAL; ++ goto fail; ++ } ++ } ++ ++ if (fw_forwarded_ss->valid && fw_consumed_ss->valid) { ++ if (!ath12k_mgmt_rx_reo_compare_global_timestamps_gte ++ (fw_consumed_ss->global_timestamp, ++ host_ss->global_timestamp) && ++ !ath12k_mgmt_rx_reo_compare_global_timestamps_gte ++ (fw_forwarded_ss->global_timestamp, ++ host_ss->global_timestamp)) { ++ ath12k_err(ab, "TS: FW consumed/forwarded < host\n"); ++ status = -EINVAL; ++ goto fail; ++ } ++ ++ if (!ath12k_mgmt_rx_reo_compare_pkt_ctrs_gte ++ (fw_consumed_ss->mgmt_pkt_ctr, ++ host_ss->mgmt_pkt_ctr) && ++ !ath12k_mgmt_rx_reo_compare_pkt_ctrs_gte ++ (fw_forwarded_ss->mgmt_pkt_ctr, ++ host_ss->mgmt_pkt_ctr)) { ++ ath12k_err(ab, "CTR: FW consumed/forwarded < host\n"); ++ status = -EINVAL; ++ goto fail; ++ } ++ } ++ } ++ ++ return 0; ++ ++fail: ++ ath12k_dbg(ab, ATH12K_DBG_RX_REO, "HW SS: valid = %u, ctr = %u, ts = %u", ++ mac_hw_ss->valid, mac_hw_ss->mgmt_pkt_ctr, ++ mac_hw_ss->global_timestamp); ++ ath12k_dbg(ab, ATH12K_DBG_RX_REO, "FW forwarded SS: valid = %u, ctr = %u, ts = %u", ++ fw_forwarded_ss->valid, ++ fw_forwarded_ss->mgmt_pkt_ctr, ++ fw_forwarded_ss->global_timestamp); ++ ath12k_dbg(ab, ATH12K_DBG_RX_REO, "FW consumed SS: valid = %u, ctr = %u, ts = %u", ++ fw_consumed_ss->valid, ++ fw_consumed_ss->mgmt_pkt_ctr, ++ fw_consumed_ss->global_timestamp); ++ ath12k_dbg(ab, ATH12K_DBG_RX_REO, "HOST SS: valid = %u, ctr = %u, ts = %u", ++ host_ss->valid, host_ss->mgmt_pkt_ctr, ++ host_ss->global_timestamp); ++ ++ return status; ++} ++ ++/** ++ * ath12k_wmi_mgmt_rx_reorder_process_calculate_wait_count() - Calculates the number of ++ * frames an incoming frame should wait for before it gets delivered. ++ * @in_frame_pdev: pdev on which this frame is received ++ * @desc: frame Descriptor ++ * ++ * Each frame carrys a MGMT pkt number which is local to that link, and a ++ * timestamp which is global across all the links. MAC HW and FW also captures ++ * the same details of the last frame that they have seen. Host also maintains ++ * the details of the last frame it has seen. In total, there are 4 snapshots. ++ * 1. MAC HW snapshot - latest frame seen at MAC HW ++ * 2. FW forwarded snapshot- latest frame forwarded to the Host ++ * 3. FW consumed snapshot - latest frame consumed by the FW ++ * 4. Host/FW consumed snapshot - latest frame seen by the Host ++ * By using all these snapshots, this function tries to compute the wait count ++ * for a given incoming frame on all links. ++ * ++ * Return: 1 on success otherwise -1 on failure ++ */ ++static int ++ath12k_wmi_mgmt_rx_reorder_process_calculate_wait_count( ++ struct ath12k *ar, ++ struct ath12k_mgmt_rx_reo_frame_descriptor *desc) ++{ ++ int status; ++ u8 hw_link_id; ++ s8 in_frame_link; ++ int frames_pending, delta_fwd_host; ++ u8 snapshot_id; ++ struct ath12k_base *ab = ar->ab; ++ struct ath12k *hw_link; ++ struct ath12k_mgmt_rx_reo_pdev_info *rx_reo_pdev_ctx; ++ struct ath12k_mgmt_rx_reo_pdev_info *in_frame_rx_reo_pdev_ctx; ++ struct ath12k_mgmt_rx_reo_snapshot_info *snapshot_info; ++ struct ath12k_mgmt_rx_reo_snapshot_params snapshot_params ++ [ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_MAX]; ++ struct ath12k_mgmt_rx_reo_snapshot_params *mac_hw_ss, *fw_forwarded_ss, ++ *fw_consumed_ss, *host_ss; ++ struct ath12k_mgmt_rx_reo_params *in_frame_params; ++ struct ath12k_mgmt_rx_reo_wait_count *wait_count; ++ ++ in_frame_params = &desc->rx_params->reo_params; ++ ++ wait_count = &desc->wait_count; ++ ++ /* Get the hw link ID of incoming frame */ ++ in_frame_link = ar->pdev->hw_link_id; ++ in_frame_rx_reo_pdev_ctx = &ar->rx_reo_pdev_ctx; ++ ++ if (!in_frame_rx_reo_pdev_ctx) { ++ ath12k_err(ab, "Reo context null for incoming frame\n"); ++ return -EINVAL; ++ } ++ memset(in_frame_rx_reo_pdev_ctx->raw_snapshots, 0, ++ sizeof(in_frame_rx_reo_pdev_ctx->raw_snapshots)); ++ ++ /* Iterate over all the valid hw links */ ++ for (hw_link_id = 0; hw_link_id < ATH12K_WMI_MLO_MAX_LINKS; hw_link_id++) { ++ /* No need wait for any frames on an invalid hw_link_id */ ++ if (!ab->ag->hw_links[hw_link_id]) { ++ frames_pending = 0; ++ goto update_pending_frames; ++ } ++ ++ hw_link = ab->ag->hw_links[hw_link_id]; ++ ++ /* No need to wait for any frames if the pdev is not found */ ++ if (!hw_link) { ++ ath12k_dbg(ab, ATH12K_DBG_RX_REO, "pdev is null for hw_link_id %d\n", hw_link_id); ++ frames_pending = 0; ++ goto update_pending_frames; ++ } ++ ++ rx_reo_pdev_ctx = &hw_link->rx_reo_pdev_ctx; ++ if (!rx_reo_pdev_ctx) { ++ ath12k_err(ab, "Mgmt reo context empty for hw_link %pK\n", ++ hw_link); ++ return -EINVAL; ++ } ++ ++ if (!rx_reo_pdev_ctx->init_complete) { ++ ath12k_dbg(ab, ATH12K_DBG_RX_REO, "REO init in progress for hw_link_id %d", ++ hw_link_id); ++ frames_pending = 0; ++ goto update_pending_frames; ++ } ++ ++ host_ss = &rx_reo_pdev_ctx->host_snapshot; ++ ++ desc->host_snapshot[hw_link_id] = rx_reo_pdev_ctx->host_snapshot; ++ ++ ath12k_dbg(ab, ATH12K_DBG_RX_REO, ++ "hw_link_id = %u HOST SS: valid = %u, ctr = %u, ts = %u", ++ hw_link_id, host_ss->valid, host_ss->mgmt_pkt_ctr, ++ host_ss->global_timestamp); ++ ++ snapshot_id = 0; ++ /* Read all the shared snapshots */ ++ while (snapshot_id < ++ ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_MAX) { ++ snapshot_info = &rx_reo_pdev_ctx-> ++ host_target_shared_snapshot_info[snapshot_id]; ++ ++ memset(&snapshot_params[snapshot_id], 0, ++ sizeof(snapshot_params[snapshot_id])); ++ ++ status = ath12k_wmi_mgmt_rx_reo_read_snapshot( ++ hw_link, snapshot_info, snapshot_id, ++ &snapshot_params[snapshot_id], ++ in_frame_rx_reo_pdev_ctx->raw_snapshots ++ [hw_link_id][snapshot_id]); ++ ++ /* Read operation shouldn't fail */ ++ if (status) { ++ ath12k_err(ab, "snapshot(%d) read failed on hw_link_id (%d) status %d\n", ++ snapshot_id, hw_link_id, status); ++ return status; ++ } ++ ++ /* If snapshot is valid, save it in the pdev context */ ++ if (snapshot_params[snapshot_id].valid) { ++ rx_reo_pdev_ctx-> ++ last_valid_shared_snapshot[snapshot_id] = ++ snapshot_params[snapshot_id]; ++ } ++ desc->shared_snapshots[hw_link_id][snapshot_id] = ++ snapshot_params[snapshot_id]; ++ ++ snapshot_id++; ++ } ++ ++ mac_hw_ss = &snapshot_params ++ [ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_MAC_HW]; ++ fw_forwarded_ss = &snapshot_params ++ [ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_FW_FORWARDED]; ++ fw_consumed_ss = &snapshot_params ++ [ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_FW_CONSUMED]; ++ ++ status = ath12k_wmi_mgmt_rx_reo_invalidate_stale_snapshots(ar, mac_hw_ss, ++ fw_forwarded_ss, ++ fw_consumed_ss, ++ host_ss, hw_link_id); ++ if (status) { ++ ath12k_err(ab, "Failed to invalidate SS for hw_link_id %u\n", ++ hw_link_id); ++ return status; ++ } ++ ++ desc->shared_snapshots[hw_link_id][ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_MAC_HW] = ++ *mac_hw_ss; ++ desc->shared_snapshots[hw_link_id][ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_FW_FORWARDED] = ++ *fw_forwarded_ss; ++ desc->shared_snapshots[hw_link_id][ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_FW_CONSUMED] = ++ *fw_consumed_ss; ++ desc->host_snapshot[hw_link_id] = *host_ss; ++ ++ status = mgmt_rx_reo_snapshots_check_sanity ++ (ar, mac_hw_ss, fw_forwarded_ss, fw_consumed_ss, host_ss); ++ if (status) { ++ ath12k_err(ab, "Snapshot sanity for hw_link_id %u failed\n", ++ hw_link_id); ++ return status; ++ } ++ ++ ath12k_dbg(ab, ATH12K_DBG_RX_REO, "hw_link_id = %u HW SS: valid = %u, ctr = %u, ts = %u", ++ hw_link_id, mac_hw_ss->valid, ++ mac_hw_ss->mgmt_pkt_ctr, ++ mac_hw_ss->global_timestamp); ++ ath12k_dbg(ab, ATH12K_DBG_RX_REO, "hw_link_id = %u FW forwarded SS: valid = %u, ctr = %u, ts = %u", ++ hw_link_id, fw_forwarded_ss->valid, ++ fw_forwarded_ss->mgmt_pkt_ctr, ++ fw_forwarded_ss->global_timestamp); ++ ath12k_dbg(ab, ATH12K_DBG_RX_REO, "hw_link_id = %u FW consumed SS: valid = %u, ctr = %u, ts = %u", ++ hw_link_id, fw_consumed_ss->valid, ++ fw_consumed_ss->mgmt_pkt_ctr, ++ fw_consumed_ss->global_timestamp); ++ ++ /* No need wait for any frames on the same hw_link_id */ ++ if (hw_link_id == in_frame_link) { ++ frames_pending = 0; ++ goto update_pending_frames; ++ } ++ ++ /** ++ * If MAC HW snapshot is invalid, the hw_link_id has not started ++ * receiving management frames. Set wait count to zero. ++ */ ++ if (!mac_hw_ss->valid) { ++ frames_pending = 0; ++ goto update_pending_frames; ++ } ++ ++ /** ++ * If host snapshot is invalid, wait for MAX number of frames. ++ * When any frame in this hw_link_id arrives at host, actual wait ++ * counts will be updated. ++ */ ++ if (!host_ss->valid) { ++ wait_count->per_link_count[hw_link_id] = UINT_MAX; ++ wait_count->total_count += UINT_MAX; ++ goto print_wait_count; ++ } ++ ++ /** ++ * If MAC HW snapshot sequence number and host snapshot ++ * sequence number are same, all the frames received by ++ * this hw_link_id are processed by host. No need to wait for ++ * any frames from this hw_link_id. ++ */ ++ if (!ath12k_mgmt_rx_reo_subtract_pkt_ctrs(mac_hw_ss->mgmt_pkt_ctr, ++ host_ss->mgmt_pkt_ctr)) { ++ frames_pending = 0; ++ goto update_pending_frames; ++ } ++ ++ /** ++ * Ideally, the incoming frame has to wait for only those frames ++ * (on other links) which meet all the below criterion. ++ * 1. Frame's timestamp is less than incoming frame's ++ * 2. Frame is supposed to be consumed by the Host ++ * 3. Frame is not yet seen by the Host. ++ * We may not be able to compute the exact optimal wait count ++ * because HW/FW provides a limited assist. ++ * This reorder process tries to get the best estimate of wait ++ * count by not waiting for those frames where we have a conclusive ++ * evidence that we don't have to wait for those frames. ++ */ ++ ++ /** ++ * If this link has already seen a frame whose timestamp is ++ * greater than or equal to incoming frame's timestamp, ++ * then no need to wait for any frames on this link. ++ * If the total wait count becomes zero, then the policy on ++ * whether to deliver such a frame to upper layers is handled ++ * separately. ++ */ ++ if (ath12k_mgmt_rx_reo_compare_global_timestamps_gte( ++ host_ss->global_timestamp, ++ in_frame_params->global_timestamp)) { ++ frames_pending = 0; ++ goto update_pending_frames; ++ } ++ ++ /** ++ * For starters, we only have to wait for the frames that are ++ * seen by MAC HW but not yet seen by Host. The frames which ++ * reach MAC HW later are guaranteed to have a timestamp ++ * greater than incoming frame's timestamp. ++ */ ++ frames_pending = ath12k_mgmt_rx_reo_subtract_pkt_ctrs( ++ mac_hw_ss->mgmt_pkt_ctr, ++ host_ss->mgmt_pkt_ctr); ++ WARN_ON(!(frames_pending >= 0)); ++ ++ if (frames_pending && ++ ath12k_mgmt_rx_reo_compare_global_timestamps_gte ++ (mac_hw_ss->global_timestamp, ++ in_frame_params->global_timestamp)) { ++ /** ++ * Last frame seen at MAC HW has timestamp greater than ++ * or equal to incoming frame's timestamp. So no need to ++ * wait for that last frame, but we can't conclusively ++ * say anything about timestamp of frames before the ++ * last frame, so try to wait for all of those frames. ++ */ ++ frames_pending--; ++ WARN_ON(!(frames_pending >= 0)); ++ ++ if (fw_consumed_ss->valid && ++ ath12k_mgmt_rx_reo_compare_global_timestamps_gte( ++ fw_consumed_ss->global_timestamp, ++ in_frame_params->global_timestamp)) { ++ /** ++ * Last frame consumed by the FW has timestamp ++ * greater than or equal to incoming frame's. ++ * That means all the frames from ++ * fw_consumed_ss->mgmt_pkt_ctr to ++ * mac_hw->mgmt_pkt_ctr will have timestamp ++ * greater than or equal to incoming frame's and ++ * hence, no need to wait for those frames. ++ * We just need to wait for frames from ++ * host_ss->mgmt_pkt_ctr to ++ * fw_consumed_ss->mgmt_pkt_ctr-1. This is a ++ * better estimate over the above estimate, ++ * so update frames_pending. ++ */ ++ frames_pending = ++ ath12k_mgmt_rx_reo_subtract_pkt_ctrs( ++ fw_consumed_ss->mgmt_pkt_ctr, ++ host_ss->mgmt_pkt_ctr) - 1; ++ ++ WARN_ON(!(frames_pending >= 0)); ++ ++ /** ++ * Last frame forwarded to Host has timestamp ++ * less than incoming frame's. That means all ++ * the frames starting from ++ * fw_forwarded_ss->mgmt_pkt_ctr+1 to ++ * fw_consumed_ss->mgmt_pkt_ctr are consumed by ++ * the FW and hence, no need to wait for those ++ * frames. We just need to wait for frames ++ * from host_ss->mgmt_pkt_ctr to ++ * fw_forwarded_ss->mgmt_pkt_ctr. This is a ++ * better estimate over the above estimate, ++ * so update frames_pending. ++ */ ++ if (fw_forwarded_ss->valid && ++ !ath12k_mgmt_rx_reo_compare_global_timestamps_gte( ++ fw_forwarded_ss->global_timestamp, ++ in_frame_params->global_timestamp)) { ++ frames_pending = ++ ath12k_mgmt_rx_reo_subtract_pkt_ctrs( ++ fw_forwarded_ss->mgmt_pkt_ctr, ++ host_ss->mgmt_pkt_ctr); ++ ++ /** ++ * frames_pending can be negative in ++ * cases whene there are no frames ++ * getting forwarded to the Host. No ++ * need to wait for any frames in that ++ * case. ++ */ ++ if (frames_pending < 0) ++ frames_pending = 0; ++ } ++ } ++ ++ /** ++ * Last frame forwarded to Host has timestamp greater ++ * than or equal to incoming frame's. That means all the ++ * frames from fw_forwarded->mgmt_pkt_ctr to ++ * mac_hw->mgmt_pkt_ctr will have timestamp greater than ++ * or equal to incoming frame's and hence, no need to ++ * wait for those frames. We may have to just wait for ++ * frames from host_ss->mgmt_pkt_ctr to ++ * fw_forwarded_ss->mgmt_pkt_ctr-1 ++ */ ++ if (fw_forwarded_ss->valid && ++ ath12k_mgmt_rx_reo_compare_global_timestamps_gte( ++ fw_forwarded_ss->global_timestamp, ++ in_frame_params->global_timestamp)) { ++ delta_fwd_host = ++ ath12k_mgmt_rx_reo_subtract_pkt_ctrs( ++ fw_forwarded_ss->mgmt_pkt_ctr, ++ host_ss->mgmt_pkt_ctr) - 1; ++ ++ WARN_ON(!(delta_fwd_host >= 0)); ++ ++ /** ++ * This will be a better estimate over the one ++ * we computed using mac_hw_ss but this may or ++ * may not be a better estimate over the ++ * one we computed using fw_consumed_ss. ++ * When timestamps of both fw_consumed_ss and ++ * fw_forwarded_ss are greater than incoming ++ * frame's but timestamp of fw_consumed_ss is ++ * smaller than fw_forwarded_ss, then ++ * frames_pending will be smaller than ++ * delta_fwd_host, the reverse will be true in ++ * other cases. Instead of checking for all ++ * those cases, just waiting for the minimum ++ * among these two should be sufficient. ++ */ ++ frames_pending = min(frames_pending, ++ delta_fwd_host); ++ WARN_ON(!(frames_pending >= 0)); ++ } ++ } ++ ++update_pending_frames: ++ WARN_ON(!(frames_pending >= 0)); ++ ++ wait_count->per_link_count[hw_link_id] = frames_pending; ++ wait_count->total_count += frames_pending; ++ ++print_wait_count: ++ ath12k_dbg(ab, ATH12K_DBG_RX_REO, ++ "hw_link_id = %u wait count: per link = 0x%x, total = 0x%llx", ++ hw_link_id, wait_count->per_link_count[hw_link_id], ++ wait_count->total_count); ++ } ++ return 0; ++} ++ ++/** ++ * mgmt_rx_reo_prepare_list_entry() - Prepare a list entry from the management ++ * frame received. ++ * @frame_desc: Pointer to the frame descriptor ++ * @entry: Pointer to the list entry ++ * ++ * This API prepares the reorder list entry corresponding to a management frame ++ * to be consumed by host. This entry would be inserted at the appropriate ++ * position in the reorder list. ++ * ++ * Return: 0 on success, non-zero on failure ++ */ ++static int ++ath12k_mgmt_rx_reo_prepare_list_entry(struct ath12k_base *ab, ++ const struct ath12k_mgmt_rx_reo_frame_descriptor *frame_desc, ++ struct mgmt_rx_reo_list_entry **entry) ++{ ++ struct mgmt_rx_reo_list_entry *list_entry; ++ struct ath12k_mgmt_rx_reo_params *reo_params = ++ &frame_desc->rx_params->reo_params; ++ struct ath12k *ar; ++ u8 link_id; ++ ++ link_id = reo_params->link_id; ++ ++ if (link_id >= ATH12K_GROUP_MAX_RADIO) { ++ ath12k_warn(ab, "%s:invalid hw link id %d\n", __func__, link_id); ++ return -EINVAL; ++ } ++ ++ ar = rcu_dereference(ab->ag->hw_links[link_id]); ++ if (!ar) { ++ ath12k_err(ab, "ar corresponding to link %u is null\n", ++ link_id); ++ return -EINVAL; ++ } ++ ++ list_entry = kmalloc(sizeof(*list_entry), GFP_ATOMIC); ++ if (!list_entry) ++ return -ENOMEM; ++ ++ list_entry->ar = ar; ++ list_entry->nbuf = frame_desc->nbuf; ++ list_entry->rx_params = frame_desc->rx_params; ++ list_entry->wait_count = frame_desc->wait_count; ++ list_entry->initial_wait_count = frame_desc->wait_count; ++ memcpy(list_entry->shared_snapshots, frame_desc->shared_snapshots, ++ min(sizeof(list_entry->shared_snapshots), ++ sizeof(frame_desc->shared_snapshots))); ++ memcpy(list_entry->host_snapshot, frame_desc->host_snapshot, ++ min(sizeof(list_entry->host_snapshot), ++ sizeof(frame_desc->host_snapshot))); ++ list_entry->status = 0; ++ if (list_entry->wait_count.total_count) ++ list_entry->status |= ++ ATH12K_MGMT_RX_REO_STATUS_WAIT_FOR_FRAME_ON_OTHER_LINKS; ++ ++ *entry = list_entry; ++ ++ return 0; ++} ++ ++/** ++ * ath12k_mgmt_rx_reo_is_stale_frame()- API to check whether the given management frame ++ * is stale ++ * @ts_last_released_frame: pointer to global time stamp of the last frame ++ * removed from the reorder list ++ * @frame_desc: pointer to frame descriptor ++ * ++ * This API checks whether the current management frame under processing is ++ * stale. Any frame older than the last frame delivered to upper layer is a ++ * stale frame. This could happen when we have to deliver frames out of order ++ * due to time out or list size limit. The frames which arrive late at host and ++ * with time stamp lesser than the last delivered frame are stale frames and ++ * they need to be handled differently. ++ * ++ * Return: 0 on success, non-zero on failure. On success "is_stale" and ++ * "is_parallel_rx" members of ++ * @frame_desc will be filled with proper values. ++ */ ++static int ++ath12k_mgmt_rx_reo_is_stale_frame(struct ath12k_base *ab, ++ struct ath12k_mgmt_rx_reo_global_ts_info *ts_last_released_frame, ++ struct ath12k_mgmt_rx_reo_frame_descriptor *frame_desc) ++{ ++ struct ath12k_mgmt_rx_reo_params *reo_params ++ = &frame_desc->rx_params->reo_params; ++ u32 cur_frame_start_ts; ++ u32 cur_frame_end_ts; ++ ++ if (!ts_last_released_frame) { ++ ath12k_err(ab, "Last released frame time stamp info is null\n"); ++ return -EINVAL; ++ } ++ ++ if (!frame_desc) { ++ ath12k_err(ab, "Frame descriptor is null\n"); ++ return -EINVAL; ++ } ++ ++ frame_desc->is_stale = false; ++ frame_desc->is_parallel_rx = false; ++ ++ if (!ts_last_released_frame->valid) ++ return 0; ++ ++ cur_frame_start_ts = reo_params->start_timestamp; ++ cur_frame_end_ts = reo_params->end_timestamp; ++ ++ frame_desc->is_stale = ++ !ath12k_mgmt_rx_reo_compare_global_timestamps_gte(cur_frame_start_ts, ++ ts_last_released_frame->start_ts); ++ ++ if (ath12k_mgmt_rx_reo_compare_global_timestamps_gte ++ (ts_last_released_frame->start_ts, cur_frame_start_ts) && ++ ath12k_mgmt_rx_reo_compare_global_timestamps_gte ++ (cur_frame_end_ts, ts_last_released_frame->end_ts)) { ++ frame_desc->is_parallel_rx = true; ++ frame_desc->is_stale = false; ++ } ++ ++ return 0; ++} ++ ++/** ++ * ath12k_mgmt_rx_reo_update_wait_count() - Update the wait count for a frame based ++ * on the wait count of a frame received after that on air. ++ * @wait_count_old_frame: Pointer to the wait count structure for the old frame. ++ * @wait_count_new_frame: Pointer to the wait count structure for the new frame. ++ * ++ * This API optimizes the wait count of a frame based on the wait count of ++ * a frame received after that on air. Old frame refers to the frame received ++ * first on the air and new frame refers to the frame received after that. ++ * We use the following fundamental idea. Wait counts for old frames can't be ++ * more than wait counts for the new frame. Use this to optimize the wait count ++ * for the old frames. Per link wait count of an old frame is minimum of the ++ * per link wait count of the old frame and new frame. ++ * ++ * Return: 0 on success, non-zero on failure ++ */ ++static int ++ath12k_mgmt_rx_reo_update_wait_count( ++ struct ath12k_mgmt_rx_reo_wait_count *wait_count_old_frame, ++ const struct ath12k_mgmt_rx_reo_wait_count *wait_count_new_frame) ++{ ++ u8 link_id; ++ ++ for (link_id = 0; link_id < ATH12K_WMI_MLO_MAX_LINKS; link_id++) { ++ if (wait_count_old_frame->per_link_count[link_id]) { ++ u32 temp_wait_count; ++ u32 wait_count_diff; ++ ++ temp_wait_count = ++ wait_count_old_frame->per_link_count[link_id]; ++ wait_count_old_frame->per_link_count[link_id] = ++ min(wait_count_old_frame-> ++ per_link_count[link_id], ++ wait_count_new_frame-> ++ per_link_count[link_id]); ++ wait_count_diff = temp_wait_count - ++ wait_count_old_frame->per_link_count[link_id]; ++ ++ wait_count_old_frame->total_count -= wait_count_diff; ++ } ++ } ++ ++ return 0; ++} ++ ++/** ++ * ath12k_mgmt_rx_reo_update_list() - Modify the reorder list when a frame is received ++ * @reo_list: Pointer to reorder list ++ * @frame_desc: Pointer to frame descriptor ++ * @is_queued: Whether this frame is queued in the REO list ++ * ++ * API to update the reorder list on every management frame reception. ++ * This API does the following things. ++ * a) Update the wait counts for all the frames in the reorder list with ++ * global time stamp <= current frame's global time stamp. We use the ++ * following principle for updating the wait count in this case. ++ * Let A and B be two management frames with global time stamp of A <= ++ * global time stamp of B. Let WAi and WBi be the wait count of A and B ++ * for link i, then WAi <= WBi. Hence we can optimize WAi as ++ * min(WAi, WBi). ++ * b) If the current frame is to be consumed by host, insert it in the ++ * reorder list such that the list is always sorted in the increasing order ++ * of global time stamp. Update the wait count of the current frame based ++ * on the frame next to it in the reorder list (if any). ++ * c) Update the wait count of the frames in the reorder list with global ++ * time stamp > current frame's global time stamp. Let the current frame ++ * belong to link "l". Then link "l"'s wait count can be reduced by one for ++ * all the frames in the reorder list with global time stamp > current ++ * frame's global time stamp. ++ * ++ * Return: 0 on success, non-zero on failure ++ */ ++static int ++ath12k_mgmt_rx_reo_update_list( ++ struct ath12k_base *ab, ++ struct mgmt_rx_reo_list *reo_list, ++ struct ath12k_mgmt_rx_reo_frame_descriptor *frame_desc, ++ bool *is_queued) ++{ ++ struct mgmt_rx_reo_list_entry *cur_entry; ++ struct mgmt_rx_reo_list_entry *least_greater_entry = NULL; ++ bool least_greater_entry_found = false; ++ int status; ++ u32 new_frame_global_ts; ++ struct mgmt_rx_reo_list_entry *new_entry = NULL; ++ u16 list_insertion_pos = 0; ++ struct ath12k_mgmt_rx_reo_params *reo_params; ++ ++ if (!is_queued) ++ return -EINVAL; ++ ++ *is_queued = false; ++ ++ if (!reo_list) { ++ ath12k_err(ab, "Mgmt Rx reo list is null\n"); ++ return -EINVAL; ++ } ++ ++ if (!frame_desc) { ++ ath12k_err(ab, "Mgmt frame descriptor is null\n"); ++ return -EINVAL; ++ } ++ ++ if (frame_desc->rx_params) { ++ reo_params = &frame_desc->rx_params->reo_params; ++ new_frame_global_ts = reo_params->global_timestamp; ++ } else { ++ ath12k_err(ab, "null rx_param %p\n", frame_desc->rx_params); ++ return -EINVAL; ++ } ++ ++ /* Prepare the list entry before acquiring lock */ ++ if (frame_desc->type == ATH12K_MGMT_RX_REO_FRAME_DESC_HOST_CONSUMED_FRAME && ++ frame_desc->reo_required) { ++ status = ath12k_mgmt_rx_reo_prepare_list_entry(ab, frame_desc, &new_entry); ++ if (status) { ++ ath12k_err(ab, "Failed to prepare list entry %d\n", status); ++ return -EINVAL; ++ } ++ } ++ ++ spin_lock_bh(&reo_list->list_lock); ++ ++ frame_desc->list_size_rx = reo_list->count; ++ ++ status = ath12k_mgmt_rx_reo_is_stale_frame(ab, &reo_list->ts_last_released_frame, ++ frame_desc); ++ if (status) ++ goto exit_free_entry; ++ ++ list_for_each_entry(cur_entry, &reo_list->list, node) { ++ u32 cur_entry_global_ts; ++ struct ath12k_mgmt_rx_reo_params *cur_reo_params = ++ &cur_entry->rx_params->reo_params; ++ ++ cur_entry_global_ts = cur_reo_params->global_timestamp; ++ ++ if (!ath12k_mgmt_rx_reo_compare_global_timestamps_gte( ++ new_frame_global_ts, cur_entry_global_ts)) { ++ least_greater_entry = cur_entry; ++ least_greater_entry_found = true; ++ break; ++ } ++ ++ /* if it is stale entry at this point and gts seems to be valid ++ * then the reordering didn't properly happened please check the ++ * reordering ++ */ ++ WARN_ON(!(!frame_desc->is_stale || cur_entry->is_parallel_rx)); ++ ++ list_insertion_pos++; ++ ++ status = ath12k_mgmt_rx_reo_update_wait_count( ++ &cur_entry->wait_count, ++ &frame_desc->wait_count); ++ if (status) ++ goto exit_free_entry; ++ ++ if (cur_entry->wait_count.total_count == 0) ++ cur_entry->status &= ++ ~ATH12K_MGMT_RX_REO_STATUS_WAIT_FOR_FRAME_ON_OTHER_LINKS; ++ } ++ ++ if (frame_desc->type == ATH12K_MGMT_RX_REO_FRAME_DESC_HOST_CONSUMED_FRAME && ++ !frame_desc->is_stale && frame_desc->reo_required) { ++ if (least_greater_entry_found) { ++ status = ath12k_mgmt_rx_reo_update_wait_count( ++ &new_entry->wait_count, ++ &least_greater_entry->wait_count); ++ ++ if (status) ++ goto exit_free_entry; ++ ++ frame_desc->wait_count = new_entry->wait_count; ++ ++ if (new_entry->wait_count.total_count == 0) ++ new_entry->status &= ++ ~ATH12K_MGMT_RX_REO_STATUS_WAIT_FOR_FRAME_ON_OTHER_LINKS; ++ } ++ ++ new_entry->insertion_ts = ktime_to_us(ktime_get()); ++ new_entry->ingress_timestamp = frame_desc->ingress_timestamp; ++ new_entry->is_parallel_rx = frame_desc->is_parallel_rx; ++ frame_desc->list_insertion_pos = list_insertion_pos; ++ ++ if (least_greater_entry_found) ++ list_add_tail(&new_entry->node, &least_greater_entry->node); ++ else ++ list_add_tail(&new_entry->node, &reo_list->list); ++ ++ reo_list->count++; ++ ++ *is_queued = true; ++ ++ if (new_entry->wait_count.total_count == 0) ++ frame_desc->zero_wait_count_rx = true; ++ ++ if (frame_desc->zero_wait_count_rx && ++ list_first_entry_or_null(&reo_list->list, ++ struct mgmt_rx_reo_list_entry, ++ node) == new_entry) ++ frame_desc->immediate_delivery = true; ++ } ++ ++ if (least_greater_entry_found) { ++ cur_entry = least_greater_entry; ++ ++ list_for_each_entry_from(cur_entry, &reo_list->list, node) { ++ u8 frame_link_id; ++ struct ath12k_mgmt_rx_reo_wait_count *wait_count; ++ ++ frame_link_id = reo_params->link_id; ++ wait_count = &cur_entry->wait_count; ++ if (wait_count->per_link_count[frame_link_id]) { ++ u32 old_wait_count; ++ u32 new_wait_count; ++ u32 wait_count_diff; ++ u16 pkt_ctr_delta; ++ ++ pkt_ctr_delta = frame_desc->pkt_ctr_delta; ++ old_wait_count = ++ wait_count->per_link_count[frame_link_id]; ++ ++ if (old_wait_count >= pkt_ctr_delta) ++ new_wait_count = old_wait_count - ++ pkt_ctr_delta; ++ else ++ new_wait_count = 0; ++ ++ wait_count_diff = old_wait_count - ++ new_wait_count; ++ ++ wait_count->per_link_count[frame_link_id] = ++ new_wait_count; ++ wait_count->total_count -= wait_count_diff; ++ ++ if (wait_count->total_count == 0) ++ cur_entry->status &= ++ ~ATH12K_MGMT_RX_REO_STATUS_WAIT_FOR_FRAME_ON_OTHER_LINKS; ++ } ++ } ++ } ++ ++ status = 0; ++ ++exit_free_entry: ++ /* Cleanup the entry if it is not queued */ ++ if (new_entry && !*is_queued) { ++ /** ++ * New entry created is not inserted to reorder list, free ++ * the entry and release the reference ++ */ ++ kfree(new_entry); ++ } ++ ++ spin_unlock_bh(&reo_list->list_lock); ++ ++ return status; ++} ++ ++/** ++ * ath12k_mgmt_rx_reo_list_is_ready_to_send_up_entry() - API to check whether the ++ * list entry can be send to upper layers. ++ * @reo_list: Pointer to reorder list ++ * @entry: List entry ++ * ++ * Return: 0 on success, non-zero on failure ++ */ ++static bool ++ath12k_mgmt_rx_reo_list_is_ready_to_send_up_entry(struct mgmt_rx_reo_list *reo_list, ++ struct mgmt_rx_reo_list_entry *entry) ++{ ++ if (!reo_list || !entry) ++ return false; ++ ++ return (reo_list->count > reo_list->max_list_size) || ++ !ATH12K_MGMT_RX_REO_LIST_ENTRY_IS_WAITING_FOR_FRAME_ON_OTHER_LINK( ++ entry) || ATH12K_MGMT_RX_REO_LIST_ENTRY_IS_AGED_OUT(entry) || ++ ATH12K_MGMT_RX_REO_LIST_ENTRY_IS_OLDER_THAN_LATEST_AGED_OUT_FRAME ++ (entry); ++} ++ ++/** ++ * ath12k_mgmt_rx_reo_list_entry_get_release_reason() - Helper API to get the reason ++ * for releasing the reorder list entry to upper layer. ++ * reorder list. ++ * @entry: List entry ++ * ++ * This API expects the caller to acquire the spin lock protecting the reorder ++ * list. ++ * ++ * Return: Reason for releasing the frame. ++ */ ++static u8 ++ath12k_mgmt_rx_reo_list_entry_get_release_reason(struct mgmt_rx_reo_list_entry *entry) ++{ ++ u8 release_reason = 0; ++ ++ if (!entry) ++ return 0; ++ ++ if (ATH12K_MGMT_RX_REO_LIST_ENTRY_IS_MAX_SIZE_EXCEEDED(entry)) ++ release_reason |= ++ MGMT_RX_REO_LIST_ENTRY_RELEASE_REASON_LIST_MAX_SIZE_EXCEEDED; ++ ++ if (!ATH12K_MGMT_RX_REO_LIST_ENTRY_IS_WAITING_FOR_FRAME_ON_OTHER_LINK(entry)) ++ release_reason |= ++ MGMT_RX_REO_LIST_ENTRY_RELEASE_REASON_ZERO_WAIT_COUNT; ++ ++ if (ATH12K_MGMT_RX_REO_LIST_ENTRY_IS_AGED_OUT(entry)) ++ release_reason |= ++ MGMT_RX_REO_LIST_ENTRY_RELEASE_REASON_AGED_OUT; ++ ++ if (ATH12K_MGMT_RX_REO_LIST_ENTRY_IS_OLDER_THAN_LATEST_AGED_OUT_FRAME(entry)) ++ release_reason |= ++ MGMT_RX_REO_LIST_ENTRY_RELEASE_REASON_OLDER_THAN_AGED_OUT_FRAME; ++ ++ return release_reason; ++} ++ ++/** ++ * mgmt_rx_reo_is_potential_premature_delivery() - Helper API to check ++ * whether the current frame getting delivered to upper layer is a premature ++ * delivery ++ * @release_reason: release reason ++ * ++ * Return: true for a premature delivery ++ */ ++static bool ++ath12k_mgmt_rx_reo_is_potential_premature_delivery(u8 release_reason) ++{ ++ return !(release_reason & ++ MGMT_RX_REO_LIST_ENTRY_RELEASE_REASON_ZERO_WAIT_COUNT); ++} ++ ++/** ++ * ath12k_mgmt_rx_reo_list_entry_send_up() - API to send the frame to the upper layer. ++ * @reo_list: Pointer to reorder list ++ * @entry: List entry ++ * ++ * API to send the frame to the upper layer. This API has to be called only ++ * for entries which can be released to upper layer. It is the caller's ++ * responsibility to ensure that entry can be released (by using API ++ * mgmt_rx_reo_list_is_ready_to_send_up_entry). This API is called after ++ * acquiring the lock which serializes the frame delivery to the upper layers. ++ * ++ * Return: 0 on success, non-zero on failure ++ */ ++static int ++ath12k_mgmt_rx_reo_list_entry_send_up(struct mgmt_rx_reo_list *reo_list, ++ struct mgmt_rx_reo_list_entry *entry) ++{ ++ struct ath12k *ar = entry->ar; ++ u8 release_reason; ++ u8 link_id; ++ u32 entry_global_ts; ++ int status; ++ struct ath12k_mgmt_rx_reo_context *reo_context; ++ struct ath12k_mgmt_rx_reo_params *reo_params = ++ &entry->rx_params->reo_params; ++ ++ if (unlikely(!rcu_access_pointer(ar->ab->pdevs_active[ar->pdev_idx]))) { ++ dev_kfree_skb(entry->nbuf); ++ goto free; ++ } ++ ++ reo_context = container_of(reo_list, struct ath12k_mgmt_rx_reo_context, ++ reo_list); ++ ++ link_id = reo_params->link_id; ++ entry_global_ts = reo_params->global_timestamp; ++ ++ release_reason = ath12k_mgmt_rx_reo_list_entry_get_release_reason(entry); ++ ++ //TODO remove WARN_ON once the implementation is stablized ++ WARN_ON(!release_reason != 0); ++ ++ entry->is_delivered = false; ++ entry->is_premature_delivery = false; ++ entry->release_reason = release_reason; ++ ++ if (ath12k_mgmt_rx_reo_is_potential_premature_delivery(release_reason)) ++ entry->is_premature_delivery = true; ++ ++ ath12k_dbg(ar->ab, ATH12K_DBG_RX_REO, ++ "Mgmt Re-order egress: channel %d valid %u global_ts %u pkt_ctr %u is_parallel_rx %d\n", ++ entry->rx_params->channel, ++ entry->rx_params->reo_params.valid, ++ entry->rx_params->reo_params.global_timestamp, ++ entry->rx_params->reo_params.mgmt_pkt_ctr, ++ entry->is_parallel_rx); ++ ++ ieee80211_rx_ni(entry->ar->ah->hw, entry->nbuf); ++ /* believing rx stack takes care of skb */ ++ entry->is_delivered = true; ++ ++free: ++ kfree(entry->rx_params); ++ /*Above ieee80211_rx_ni call frees nbuf and rx_params, make it null explicitly */ ++ entry->nbuf = NULL; ++ entry->rx_params = NULL; ++ status = 0; ++ ++ return status; ++} ++ ++/** ++ * ath12k_mgmt_rx_reo_list_release_entries() - Release entries from the reorder list ++ * @reo_context: Pointer to management Rx reorder context ++ * ++ * This API releases the entries from the reorder list based on the following ++ * conditions. ++ * a) Entries with total wait count equal to 0 ++ * b) Entries which are timed out or entries with global time stamp <= global ++ * time stamp of the latest frame which is timed out. We can only release ++ * the entries in the increasing order of the global time stamp. ++ * So all the entries with global time stamp <= global time stamp of the ++ * latest timed out frame has to be released. ++ * ++ * Return: 0 on success, non-zero on failure ++ */ ++static int ++ath12k_mgmt_rx_reo_list_release_entries(struct ath12k_base *ab, ++ struct ath12k_mgmt_rx_reo_context *reo_context) ++{ ++ struct mgmt_rx_reo_list *reo_list; ++ struct ath12k_mgmt_rx_reo_params *reo_params; ++ int status; ++ ++ if (!reo_context) { ++ ath12k_err(ab, "reo context is null\n"); ++ return -EINVAL; ++ } ++ ++ reo_list = &reo_context->reo_list; ++ ++ spin_lock(&reo_context->frame_release_lock); ++ ++ while (1) { ++ struct mgmt_rx_reo_list_entry *first_entry; ++ /* TODO yield if release_count > THRESHOLD */ ++ u16 release_count = 0; ++ struct ath12k_mgmt_rx_reo_global_ts_info *ts_last_released_frame = ++ &reo_list->ts_last_released_frame; ++ u32 entry_global_ts; ++ ++ spin_lock_bh(&reo_list->list_lock); ++ ++ first_entry = list_first_entry_or_null( ++ &reo_list->list, struct mgmt_rx_reo_list_entry, node); ++ ++ if (!first_entry) { ++ status = 0; ++ goto exit_unlock_list_lock; ++ } ++ ++ if (!ath12k_mgmt_rx_reo_list_is_ready_to_send_up_entry(reo_list, ++ first_entry)) { ++ status = 0; ++ goto exit_unlock_list_lock; ++ } ++ ++ if (reo_list->count > reo_list->max_list_size) ++ first_entry->status |= ++ ATH12K_MGMT_RX_REO_STATUS_LIST_MAX_SIZE_EXCEEDED; ++ ++ list_del_init(&first_entry->node); ++ reo_list->count--; ++ ++ if (status) { ++ status = -EINVAL; ++ goto exit_unlock_list_lock; ++ } ++ first_entry->removal_ts = ktime_to_us(ktime_get()); ++ ++ /** ++ * Last released frame global time stamp is invalid means that ++ * current frame is the first frame to be released to the ++ * upper layer from the reorder list. Blindly update the last ++ * released frame global time stamp to the current frame's ++ * global time stamp and set the valid to true. ++ * If the last released frame global time stamp is valid and ++ * current frame's global time stamp is >= last released frame ++ * global time stamp, deliver the current frame to upper layer ++ * and update the last released frame global time stamp. ++ */ ++ reo_params = &first_entry->rx_params->reo_params; ++ entry_global_ts = reo_params->global_timestamp; ++ ++ if (!ts_last_released_frame->valid || ++ ath12k_mgmt_rx_reo_compare_global_timestamps_gte( ++ entry_global_ts, ts_last_released_frame->global_ts)) { ++ ts_last_released_frame->global_ts = entry_global_ts; ++ ts_last_released_frame->start_ts = ++ reo_params->start_timestamp; ++ ts_last_released_frame->end_ts = ++ reo_params->end_timestamp; ++ ts_last_released_frame->valid = true; ++ ts_last_released_frame->expiry_time = jiffies + ATH12K_MGMT_RX_REO_GLOBAL_MGMT_RX_INACTIVITY_TIMEOUT; ++ ++ } else { ++ /** ++ * This should never happen. All the frames older than ++ * the last frame released from the reorder list will be ++ * discarded at the entry to reorder process itself. ++ */ ++ WARN_ON(!first_entry->is_parallel_rx); ++ } ++ ++ spin_unlock_bh(&reo_list->list_lock); ++ ++ status = ath12k_mgmt_rx_reo_list_entry_send_up(reo_list, ++ first_entry); ++ if (status) { ++ status = -EINVAL; ++ kfree(first_entry); ++ goto exit_unlock_frame_release_lock; ++ } ++ ++ kfree(first_entry); ++ release_count++; ++ } ++ ++ status = 0; ++ goto exit_unlock_frame_release_lock; ++ ++exit_unlock_list_lock: ++ spin_unlock_bh(&reo_list->list_lock); ++exit_unlock_frame_release_lock: ++ spin_unlock(&reo_context->frame_release_lock); ++ ++ return status; ++} ++ ++static int ++ath12k_wmi_mgmt_rx_reorder_process_entry(struct ath12k *ar, ++ struct ath12k_mgmt_rx_reo_frame_descriptor *desc, ++ bool *is_queued) ++{ ++ struct ath12k_base *ab = ar->ab; ++ struct ath12k_mgmt_rx_reo_context *reo_ctx; ++ int ret; ++ ++ if (!is_queued) ++ return -EINVAL; ++ ++ *is_queued = false; ++ ++ if (!desc || !desc->rx_params) { ++ ath12k_err(ab, "MGMT Rx REO descriptor or rx params are null\n"); ++ return -EINVAL; ++ } ++ ++ reo_ctx = &ab->ag->rx_reo; ++ if (!reo_ctx) { ++ ath12k_err(ab, "REO context is NULL\n"); ++ return -EINVAL; ++ } ++ ++ if (!reo_ctx->init_done || !reo_ctx->timer_init_done) { ++ ath12k_err(ab, "MGMT Rx REO timer is not initialised\n"); ++ return -EINVAL; ++ } ++ ++ /** ++ * Critical Section = Host snapshot update + Calculation of wait ++ * counts + Update reorder list. Following section describes the ++ * motivation for making this a critical section. ++ * Lets take an example of 2 links (Link A & B) and each has received ++ * a management frame A1 and B1 such that MLO global time stamp of A1 < ++ * MLO global time stamp of B1. Host is concurrently executing ++ * "ath12k_wmi_mgmt_rx_reorder_process_entry" for A1 and B1 in 2 different CPUs. ++ * ++ * A lock less version of this API("ath12k_wmi_mgmt_rx_reorder_process_entry_v1") is ++ * as follows. ++ * ++ * ath12k_wmi_mgmt_rx_reorder_process_entry() ++ * { ++ * Host snapshot update ++ * Calculation of wait counts ++ * Update reorder list ++ * Release to upper layer ++ * } ++ * ++ * We may run into race conditions under the following sequence of ++ * operations. ++ * ++ * 1. Host snapshot update for link A in context of frame A1 ++ * 2. Host snapshot update for link B in context of frame B1 ++ * 3. Calculation of wait count for frame B1 ++ * link A wait count = 0 ++ * link B wait count = 0 ++ * 4. Update reorder list with frame B1 ++ * 5. Release B1 to upper layer ++ * 6. Calculation of wait count for frame A1 ++ * link A wait count = 0 ++ * link B wait count = 0 ++ * 7. Update reorder list with frame A1 ++ * 8. Release A1 to upper layer ++ * ++ * This leads to incorrect behaviour as B1 goes to upper layer before ++ * A1. ++ * ++ * To prevent this lets make Host snapshot update + Calculate wait count ++ * a critical section by adding locks. The updated version of the API ++ * ("ath12k_wmi_mgmt_rx_reorder_process_entry_v2") is as follows. ++ * ++ * ath12k_wmi_mgmt_rx_reorder_process_entry() ++ * { ++ * LOCK ++ * Host snapshot update ++ * Calculation of wait counts ++ * UNLOCK ++ * Update reorder list ++ * Release to upper layer ++ * } ++ * ++ * With this API also We may run into race conditions under the ++ * following sequence of operations. ++ * ++ * 1. Host snapshot update for link A in context of frame A1 + ++ * Calculation of wait count for frame A1 ++ * link A wait count = 0 ++ * link B wait count = 0 ++ * 2. Host snapshot update for link B in context of frame B1 + ++ * Calculation of wait count for frame B1 ++ * link A wait count = 0 ++ * link B wait count = 0 ++ * 4. Update reorder list with frame B1 ++ * 5. Release B1 to upper layer ++ * 7. Update reorder list with frame A1 ++ * 8. Release A1 to upper layer ++ * ++ * This also leads to incorrect behaviour as B1 goes to upper layer ++ * before A1. ++ * ++ * ++ * To prevent this, let's make Host snapshot update + Calculate wait ++ * count + Update reorder list a critical section by adding locks. ++ * The updated version of the API ("ath12k_wmi_mgmt_rx_reorder_process_entry_final") ++ * is as follows. ++ * ++ * ath12k_wmi_mgmt_rx_reorder_process_entry() ++ * { ++ * LOCK ++ * Host snapshot update ++ * Calculation of wait counts ++ * Update reorder list ++ * UNLOCK ++ * Release to upper layer ++ * } ++ */ ++ spin_lock_bh(&reo_ctx->rx_reorder_entry_lock); ++ ++ if (unlikely(!desc->rx_params->reo_params.valid)) { ++ ath12k_warn(ab, "Valid bit is not set for mgmt frame\n"); ++ goto failure; ++ } ++ ++ if ((desc->type == ATH12K_MGMT_RX_REO_FRAME_DESC_HOST_CONSUMED_FRAME || ++ desc->type == ATH12K_MGMT_RX_REO_FRAME_DESC_FW_CONSUMED_FRAME) && ++ !desc->rx_params->reo_params.duration_us) { ++ ath12k_warn(ab, "Rx reo duration of the frame is not valid %d\n", ++ desc->rx_params->reo_params.duration_us); ++ goto failure; ++ } ++ ++ /* Update the Host snapshot */ ++ ret = ath12k_wlan_mgmt_rx_reo_update_host_snapshot(ar, desc); ++ if (ret) ++ goto failure; ++ ++ /* Compute wait count for this frame/event */ ++ ret = ath12k_wmi_mgmt_rx_reorder_process_calculate_wait_count(ar, desc); ++ if (ret) ++ goto failure; ++ ++ /* Update the REO list */ ++ ret = ath12k_mgmt_rx_reo_update_list(ab, &reo_ctx->reo_list, desc, is_queued); ++ if (ret) ++ goto failure; ++ ++ spin_unlock_bh(&reo_ctx->rx_reorder_entry_lock); ++ /* Finally, release the entries for which pending frame is received */ ++ return ath12k_mgmt_rx_reo_list_release_entries(ab, reo_ctx); ++ ++failure: ++ spin_unlock_bh(&reo_ctx->rx_reorder_entry_lock); ++ return ret; ++} ++ ++/** ++ * ath12k_mgmt_rx_reo_list_ageout_timer_handler() - Periodic ageout timer handler ++ * @arg: Argument to timer handler ++ * ++ * This is the handler for periodic ageout timer used to timeout entries in the ++ * reorder list. ++ * ++ * Return: void ++ */ ++static void ++ath12k_mgmt_rx_reo_list_ageout_timer_handler(struct timer_list *timer) ++{ ++ struct mgmt_rx_reo_list *reo_list = from_timer(reo_list, timer, ageout_timer); ++ struct ath12k_base *ab = reo_list->ab; ++ struct mgmt_rx_reo_list_entry *cur_entry; ++ u64 cur_ts; ++ int status; ++ struct mgmt_rx_reo_context *reo_context = &ab->ag->rx_reo; ++ /** ++ * Stores the pointer to the entry in reorder list for the latest aged ++ * out frame. Latest aged out frame is the aged out frame in reorder ++ * list which has the largest global time stamp value. ++ */ ++ struct mgmt_rx_reo_list_entry *latest_aged_out_entry = NULL; ++ ++ spin_lock_bh(&reo_list->list_lock); ++ ++ cur_ts = ktime_to_us(ktime_get()); ++ ++ if (list_empty(&reo_list->list)) ++ goto out; ++ ++ list_for_each_entry(cur_entry, &reo_list->list, node) { ++ if (cur_ts - cur_entry->insertion_ts >= ++ reo_list->list_entry_timeout_us) { ++ latest_aged_out_entry = cur_entry; ++ cur_entry->status |= ATH12K_MGMT_RX_REO_STATUS_AGED_OUT; ++ } ++ } ++ ++ if (latest_aged_out_entry) { ++ list_for_each_entry(cur_entry, &reo_list->list, node) { ++ if (cur_entry == latest_aged_out_entry) ++ break; ++ cur_entry->status |= ATH12K_MGMT_RX_REO_STATUS_OLDER_THAN_LATEST_AGED_OUT_FRAME; ++ } ++ } ++ ++out: ++ spin_unlock_bh(&reo_list->list_lock); ++ ++ if (latest_aged_out_entry) { ++ status = ath12k_mgmt_rx_reo_list_release_entries(ab, reo_context); ++ if (status) { ++ ath12k_err(ab, "Failed to release entries, ret = %d\n", ++ status); ++ return; ++ } ++ } ++ ++ mod_timer(&reo_list->ageout_timer, jiffies + ++ msecs_to_jiffies(ATH12K_MGMT_RX_REO_AGEOUT_TIMER_PERIOD_MS)); ++} ++ ++/** ++ * ath12k_mgmt_rx_reo_global_mgmt_rx_inactivity_timer_handler() - Timer handler ++ * for global management Rx inactivity timer ++ * @arg: Argument to timer handler ++ * ++ * This is the timer handler for tracking management Rx inactivity across ++ * links. ++ * ++ * Return: void ++ */ ++static void ++ath12k_mgmt_rx_reo_global_mgmt_rx_inactivity_timer_handler(struct timer_list *timer) ++{ ++ struct mgmt_rx_reo_list *reo_list = from_timer(reo_list, timer, global_mgmt_rx_inactivity_timer); ++ struct ath12k_base *ab = reo_list->ab; ++ struct ath12k_mgmt_rx_reo_context *reo_context = &ab->ag->rx_reo; ++ struct ath12k_mgmt_rx_reo_global_ts_info *ts_last_released_frame; ++ ++ ts_last_released_frame = &reo_list->ts_last_released_frame; ++ ++ spin_lock(&reo_context->frame_release_lock); ++ spin_lock_bh(&reo_list->list_lock); ++ ++ if (time_after(jiffies, ts_last_released_frame->expiry_time)) ++ memset(ts_last_released_frame, 0, sizeof(*ts_last_released_frame)); ++ ++ spin_unlock_bh(&reo_list->list_lock); ++ spin_unlock(&reo_context->frame_release_lock); ++ ++ mod_timer(&reo_list->global_mgmt_rx_inactivity_timer, jiffies + ++ ATH12K_MGMT_RX_REO_GLOBAL_MGMT_RX_INACTIVITY_TIMEOUT); ++} ++ ++/** ++ * mgmt_rx_reo_list_init() - Initialize the management rx-reorder list ++ * @reo_list: Pointer to reorder list ++ * ++ * API to initialize the management rx-reorder list. ++ * ++ * Return: 0 on success, non-zero on failure ++ */ ++static int ++ath12k_mgmt_rx_reo_list_init(struct ath12k_base *ab, struct mgmt_rx_reo_list *reo_list) ++{ ++ reo_list->max_list_size = ATH12K_MGMT_RX_REO_LIST_MAX_SIZE; ++ reo_list->list_entry_timeout_us = ATH12K_MGMT_RX_REO_LIST_TIMEOUT_US; ++ reo_list->count = 0; ++ reo_list->ab = ab; ++ INIT_LIST_HEAD(&reo_list->list); ++ spin_lock_init(&reo_list->list_lock); ++ ++ timer_setup(&reo_list->ageout_timer, ++ ath12k_mgmt_rx_reo_list_ageout_timer_handler, 0); ++ ++ reo_list->ts_last_released_frame.valid = false; ++ ++ timer_setup(&reo_list->global_mgmt_rx_inactivity_timer, ++ ath12k_mgmt_rx_reo_global_mgmt_rx_inactivity_timer_handler, 0); ++ ++ return 0; ++} ++ ++/** ++ * ath12k_mgmt_rx_reo_flush_reorder_list() - Flush all entries in the reorder list ++ * @reo_list: Pointer to reorder list ++ * ++ * API to flush all the entries of the reorder list. This API would acquire ++ * the lock protecting the list. ++ * ++ * Return: 0 on success, non-zero on failure ++ */ ++static int ++ath12k_mgmt_rx_reo_flush_reorder_list(struct ath12k_base *ab, struct mgmt_rx_reo_list *reo_list) ++{ ++ struct mgmt_rx_reo_list_entry *cur_entry, *temp; ++ ++ if (!reo_list) { ++ ath12k_err(ab, "reorder list is null\n"); ++ return -EINVAL; ++ } ++ ++ spin_lock_bh(&reo_list->list_lock); ++ ++ list_for_each_entry_safe(cur_entry, temp, &reo_list->list, node) { ++ list_del(&cur_entry->node); ++ dev_kfree_skb(cur_entry->nbuf); ++ kfree(cur_entry->rx_params); ++ kfree(cur_entry); ++ } ++ ++ spin_unlock_bh(&reo_list->list_lock); ++ ++ return 0; ++} ++ ++/** ++ * mgmt_rx_reo_list_deinit() - De initialize the management rx-reorder list ++ * @reo_list: Pointer to reorder list ++ * ++ * API to de initialize the management rx-reorder list. ++ * ++ * Return: 0 on success, non-zero on failure ++ */ ++static int ++ath12k_mgmt_rx_reo_list_deinit(struct ath12k_base *ab, struct mgmt_rx_reo_list *reo_list) ++{ ++ int status; ++ ++ status = ath12k_mgmt_rx_reo_flush_reorder_list(ab, reo_list); ++ if (status) { ++ ath12k_err(ab, "Failed to flush the reorder list\n"); ++ return status; ++ } ++ ++ return 0; ++} ++ ++int ath12k_mgmt_rx_reo_init_context(struct ath12k_base *ab) ++{ ++ struct ath12k_hw_group *ag = ab->ag; ++ struct ath12k_mgmt_rx_reo_context *reo_context = &ag->rx_reo; ++ ++ if (!(ag->mlo_mem.is_mlo_mem_avail && ag->mgmt_rx_reorder)) ++ return 0; ++ ++ if (reo_context->init_done) ++ return 0; ++ ++ spin_lock_init(&reo_context->rx_reorder_entry_lock); ++ spin_lock_init(&reo_context->frame_release_lock); ++ ++ ath12k_mgmt_rx_reo_list_init(ab, &reo_context->reo_list); ++ ++ reo_context->init_done = true; ++ ++ return 0; ++} ++ ++int ++ath12k_mgmt_rx_reo_deinit_context(struct ath12k_base *ab) ++{ ++ int status; ++ struct ath12k_mgmt_rx_reo_context *reo_context = &ab->ag->rx_reo; ++ struct ath12k_hw_group *ag = ab->ag; ++ ++ if (!(ag->mlo_mem.is_mlo_mem_avail && ag->mgmt_rx_reorder)) ++ return 0; ++ ++ if (!reo_context->init_done) ++ return 0; ++ ++ status = ath12k_mgmt_rx_reo_list_deinit(ab, &reo_context->reo_list); ++ if (status) { ++ ath12k_err(ab, "Failed to de-initialize mgmt Rx reo list\n"); ++ return status; ++ } ++ ++ reo_context->init_done = false; ++ ++ return status; ++} ++ ++static void ath12k_fw_consumed_mgmt_rx_event(struct ath12k_base *ab, struct sk_buff *skb) ++{ ++ struct ath12k_hw_group *ag = ab->ag; ++ struct mgmt_rx_event_params *rx_ev; ++ struct ath12k *ar; ++ struct ath12k_mgmt_rx_reo_frame_descriptor desc = {0}; ++ bool is_queued = false; ++ int ret; ++ ++ if (!(ag->mlo_mem.is_mlo_mem_avail && ag->mgmt_rx_reorder)) ++ return; ++ ++ rx_ev = kmalloc(sizeof(*rx_ev), GFP_ATOMIC); ++ if (!rx_ev) { ++ ath12k_err(ab, "failed to allocate rx event\n"); ++ return; ++ } ++ ++ if (ath12k_pull_fw_consumed_mgmt_rx_params_tlv(ab, skb, rx_ev) != 0) { ++ ath12k_warn(ab, "failed to extract mgmt rx event"); ++ kfree(rx_ev); ++ return; ++ } ++ ++ rcu_read_lock(); ++ ar = ath12k_mac_get_ar_by_pdev_id(ab, rx_ev->pdev_id); ++ ++ if (!ar) { ++ ath12k_warn(ab, "invalid pdev_id %d in mgmt_rx_event\n", ++ rx_ev->pdev_id); ++ goto exit; ++ } ++ ++ rx_ev->reo_params.link_id = rx_ev->pdev_id; ++ ++ /* Populate frame descriptor */ ++ desc.type = ATH12K_MGMT_RX_REO_FRAME_DESC_HOST_CONSUMED_FRAME; ++ desc.nbuf = NULL; /* No frame buffer */ ++ desc.rx_params = rx_ev; ++ desc.ingress_timestamp = ktime_to_us(ktime_get()); ++ desc.list_size_rx = -1; ++ desc.list_insertion_pos = -1; ++ ++ desc.frame_type = IEEE80211_FTYPE_MGMT; ++ desc.frame_subtype = 0xFF; ++ ++ desc.reo_required = false; ++ ++ ret = ath12k_wmi_mgmt_rx_reorder_process_entry(ar, &desc, &is_queued); ++ if (ret) { ++ ath12k_warn(ab, "Failed to execute MGMT REO reorder process\n"); ++ goto exit; ++ } ++ ++ if (is_queued) ++ WARN_ON(1); ++ ++exit: ++ /* if the frame is queued dont free it here ++ * it will be taken care by the mgmt rx reorder ++ * process ++ */ ++ if (!is_queued) ++ kfree(rx_ev); ++ ++ rcu_read_unlock(); ++} ++ + static void ath12k_mgmt_rx_event(struct ath12k_base *ab, struct sk_buff *skb) + { +- struct mgmt_rx_event_params rx_ev = {0}; ++ struct ath12k_hw_group *ag = ab->ag; ++ struct mgmt_rx_event_params *rx_ev; + struct ath12k *ar; + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); + struct ieee80211_hdr *hdr; +@@ -8256,45 +10652,56 @@ static void ath12k_mgmt_rx_event(struct + struct ath12k_vif *ahvif; + struct ath12k_mgmt_frame_stats *mgmt_stats; + u16 frm_type = 0; ++ struct ath12k_mgmt_rx_reo_frame_descriptor desc = {0}; ++ bool is_queued = false; ++ int ret; + +- if (ath12k_pull_mgmt_rx_params_tlv(ab, skb, &rx_ev) != 0) { ++ rx_ev = kmalloc(sizeof(*rx_ev), GFP_ATOMIC); ++ if (!rx_ev) { ++ dev_kfree_skb(skb); ++ ath12k_err(ab, "failed to allocate rx event\n"); ++ return; ++ } ++ ++ if (ath12k_pull_mgmt_rx_params_tlv(ab, skb, rx_ev) != 0) { + ath12k_warn(ab, "failed to extract mgmt rx event"); + dev_kfree_skb(skb); ++ kfree(rx_ev); + return; + } + + memset(status, 0, sizeof(*status)); + + ath12k_dbg(ab, ATH12K_DBG_MGMT, "mgmt rx event status %08x\n", +- rx_ev.status); ++ rx_ev->status); + + rcu_read_lock(); +- ar = ath12k_mac_get_ar_by_pdev_id(ab, rx_ev.pdev_id); ++ ar = ath12k_mac_get_ar_by_pdev_id(ab, rx_ev->pdev_id); + + if (!ar) { + ath12k_warn(ab, "invalid pdev_id %d in mgmt_rx_event\n", +- rx_ev.pdev_id); ++ rx_ev->pdev_id); + dev_kfree_skb(skb); + goto exit; + } + + if ((test_bit(ATH12K_CAC_RUNNING, &ar->dev_flags)) || +- (rx_ev.status & (WMI_RX_STATUS_ERR_DECRYPT | ++ (rx_ev->status & (WMI_RX_STATUS_ERR_DECRYPT | + WMI_RX_STATUS_ERR_KEY_CACHE_MISS | WMI_RX_STATUS_ERR_CRC))) { + dev_kfree_skb(skb); + goto exit; + } + +- if (rx_ev.status & WMI_RX_STATUS_ERR_MIC) ++ if (rx_ev->status & WMI_RX_STATUS_ERR_MIC) + status->flag |= RX_FLAG_MMIC_ERROR; + +- if (rx_ev.chan_freq >= ATH12K_MIN_6G_FREQ && +- rx_ev.chan_freq <= ATH12K_MAX_6G_FREQ) { ++ if (rx_ev->chan_freq >= ATH12K_MIN_6G_FREQ && ++ rx_ev->chan_freq <= ATH12K_MAX_6G_FREQ) { + status->band = NL80211_BAND_6GHZ; +- status->freq = rx_ev.chan_freq; +- } else if (rx_ev.channel >= 1 && rx_ev.channel <= 14) { ++ status->freq = rx_ev->chan_freq; ++ } else if (rx_ev->channel >= 1 && rx_ev->channel <= 14) { + status->band = NL80211_BAND_2GHZ; +- } else if (rx_ev.channel >= 36 && rx_ev.channel <= ATH12K_MAX_5G_CHAN) { ++ } else if (rx_ev->channel >= 36 && rx_ev->channel <= ATH12K_MAX_5G_CHAN) { + status->band = NL80211_BAND_5GHZ; + } else { + /* Shouldn't happen unless list of advertised channels to +@@ -8305,7 +10712,7 @@ static void ath12k_mgmt_rx_event(struct + goto exit; + } + +- if (rx_ev.phy_mode == MODE_11B && ++ if (rx_ev->phy_mode == MODE_11B && + (status->band == NL80211_BAND_5GHZ || status->band == NL80211_BAND_6GHZ)) + ath12k_dbg(ab, ATH12K_DBG_WMI, + "wmi mgmt rx 11b (CCK) on 5/6GHz, band = %d\n", status->band); +@@ -8313,11 +10720,11 @@ static void ath12k_mgmt_rx_event(struct + sband = &ar->mac.sbands[status->band]; + + if (status->band != NL80211_BAND_6GHZ) +- status->freq = ieee80211_channel_to_frequency(rx_ev.channel, ++ status->freq = ieee80211_channel_to_frequency(rx_ev->channel, + status->band); + +- status->signal = rx_ev.snr + ATH12K_DEFAULT_NOISE_FLOOR; +- status->rate_idx = ath12k_mac_bitrate_to_idx(sband, rx_ev.rate / 100); ++ status->signal = rx_ev->snr + ATH12K_DEFAULT_NOISE_FLOOR; ++ status->rate_idx = ath12k_mac_bitrate_to_idx(sband, rx_ev->rate / 100); + + hdr = (struct ieee80211_hdr *)skb->data; + fc = le16_to_cpu(hdr->frame_control); +@@ -8375,6 +10782,43 @@ skip_mgmt_stats: + * ath12k_mac_handle_beacon(ar, skb); + */ + ++ if (!(ag->mlo_mem.is_mlo_mem_avail && ag->mgmt_rx_reorder)) ++ goto pass_up; ++ ++ if (!rx_ev->reo_params.valid) { ++ ath12k_warn(ab, "Invalid MGMT rx REO param for link %u\n", ++ ar->pdev->hw_link_id); ++ goto pass_up; ++ } ++ ++ rx_ev->reo_params.link_id = ar->pdev->hw_link_id; ++ ++ /* Populate frame descriptor */ ++ desc.type = ATH12K_MGMT_RX_REO_FRAME_DESC_HOST_CONSUMED_FRAME; ++ desc.nbuf = skb; ++ desc.rx_params = rx_ev; ++ desc.ingress_timestamp = ktime_to_us(ktime_get()); ++ desc.list_size_rx = -1; ++ desc.list_insertion_pos = -1; ++ ++ desc.frame_type = FIELD_GET(IEEE80211_FCTL_FTYPE, fc); ++ desc.frame_subtype = frm_type; ++ ++ desc.reo_required = true; ++ ret = ath12k_wmi_mgmt_rx_reorder_process_entry(ar, &desc, &is_queued); ++ if (ret) { ++ ath12k_warn(ab, "Failed to execute MGMT REO reorder process\n"); ++ dev_kfree_skb(skb); ++ goto exit; ++ } ++ ++ /** ++ * If frame is queued, we shouldn't free up rx params ++ */ ++ if (is_queued) ++ goto exit; ++ ++pass_up: + ath12k_dbg(ab, ATH12K_DBG_MGMT, + "event mgmt rx skb %pK len %d ftype %02x stype %02x\n", + skb, skb->len, +@@ -8388,6 +10832,13 @@ skip_mgmt_stats: + ieee80211_rx_ni(ar->ah->hw, skb); + + exit: ++ /* if the frame is queued dont free it here ++ * it will be taken care by the mgmt rx reorder ++ * process ++ */ ++ if (!is_queued) ++ kfree(rx_ev); ++ + rcu_read_unlock(); + } + +@@ -10973,6 +13424,9 @@ static void ath12k_wmi_tlv_op_rx(struct + case WMI_VDEV_ADFS_OCAC_COMPLETE_EVENTID: + ath12k_process_ocac_complete_event(ab, skb); + break; ++ case WMI_MGMT_RX_FW_CONSUMED_EVENTID: ++ ath12k_fw_consumed_mgmt_rx_event(ab, skb); ++ break; + /* TODO: Add remaining events */ + default: + ath12k_dbg(ab, ATH12K_DBG_WMI, "Unknown eventid: 0x%x\n", id); +@@ -11600,4 +14054,3 @@ int ath12k_wmi_vdev_adfs_ocac_abort_cmd_ + } + return ret; + } +- +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/wmi.h +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/wmi.h ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/wmi.h +@@ -428,6 +428,9 @@ enum wmi_tlv_cmd_id { + WMI_BSS_COLOR_CHANGE_ENABLE_CMDID, + WMI_VDEV_BCN_OFFLOAD_QUIET_CONFIG_CMDID, + WMI_FILS_DISCOVERY_TMPL_CMDID, ++ WMI_QOS_NULL_FRAME_TX_SEND_CMDID, ++ /** WMI CMD to receive the management filter criteria from the host for RX REO */ ++ WMI_MGMT_RX_REO_FILTER_CONFIGURATION_CMDID, + WMI_ADDBA_CLEAR_RESP_CMDID = WMI_TLV_CMD(WMI_GRP_BA_NEG), + WMI_ADDBA_SEND_CMDID, + WMI_ADDBA_STATUS_CMDID, +@@ -776,6 +779,9 @@ enum wmi_tlv_event_id { + WMI_TBTTOFFSET_EXT_UPDATE_EVENTID, + WMI_OFFCHAN_DATA_TX_COMPLETION_EVENTID, + WMI_HOST_FILS_DISCOVERY_EVENTID, ++ WMI_HOST_FILS_V2_DISCOVERY_EVENTID, ++ WMI_QOS_NULL_FRAME_TX_COMPLETION_EVENTID, ++ WMI_MGMT_RX_FW_CONSUMED_EVENTID, + WMI_TX_DELBA_COMPLETE_EVENTID = WMI_TLV_CMD(WMI_GRP_BA_NEG), + WMI_TX_ADDBA_COMPLETE_EVENTID, + WMI_BA_RSP_SSN_EVENTID, +@@ -2006,6 +2012,9 @@ enum wmi_tlv_tag { + WMI_TAG_MLO_TEARDOWN_CMD, + WMI_TAG_MLO_TEARDOWN_COMPLETE, + WMI_TAG_MLO_PEER_ASSOC_PARAMS = 0x3D0, ++ WMI_TAG_MLO_MGMT_RX_REO_PARAMS = 0x3D2, ++ WMI_TAG_MLO_MGMT_RX_FW_CONSUMED_HDR = 0x3D3, ++ WMI_TAG_MLO_MGMT_RX_REO_FILTER_CFG_CMD = 0x3D4, + WMI_TAG_MLO_PEER_CREATE_PARAMS = 0x3D5, + WMI_TAG_MLO_VDEV_START_PARAMS = 0x3D6, + WMI_TAG_MLO_VDEV_CREATE_PARAMS = 0x3D7, +@@ -5448,6 +5457,676 @@ struct mlo_glb_rx_reo_per_link_snapshot_ + struct mgmt_rx_reo_snapshot hw_forwarded; + }; + ++/** ++ * Enum which defines different versions of management Rx reorder snapshots. ++ */ ++enum { ++ /** ++ * DWORD Lower: ++ * [15:0] : Management packet counter ++ * [30:16] : Redundant global time stamp = Global time stamp[14:0] ++ * [31] : Valid ++ * ++ * DWORD Upper: ++ * [31:0] : Global time stamp ++ * ++ */ ++ ATH12K_MGMT_RX_REO_SNAPSHOT_VERSION_TIMESTAMP_REDUNDANCY = 0, ++ ++ /** ++ * DWORD Lower: ++ * [14:0] : Global time stamp[14:0] ++ * [30:15] : Management packet counter ++ * [31] : Valid ++ * ++ * DWORD Upper: ++ * [14:0] : Redundant management packet counter = Management packet ++ * counter[14:0] ++ * [31:15] : Global time stamp[31:15] ++ */ ++ ATH12K_MGMT_RX_REO_SNAPSHOT_VERSION_PKT_CTR_REDUNDANCY = 1, ++}; ++ ++/** ++ * Macros for getting and setting the required number of bits ++ * from the TLV params. ++ */ ++#define ATH12K_MLO_SHMEM_GET_BITS(_val, _index, _num_bits) \ ++ (((_val) >> (_index)) & ((1 << (_num_bits)) - 1)) ++ ++/* WMI CMD to receive the management filter criteria from the host */ ++struct ath12k_wmi_mgmt_rx_reo_filter_config_cmd_fixed_param { ++ u32 tlv_header; ++ u32 pdev_id; /* pdev_id for identifying the MAC */ ++ /* filter: ++ * Each bit represents the possible combination of frame type (2 bits) ++ * and subtype (4 bits) ++ * There would be 64 such combinations as per the 802.11 standard ++ * For Exp : We have beacon frame, we will take the type and subtype ++ * of this frame and concatenate the bits, it will give 6 bits ++ * number. We need to go to that bit position in the below ++ * 2 filter_low and filter_high bitmap and set the bit. ++ */ ++ u32 filter_low; ++ u32 filter_high; ++}; ++ ++#define WMI_MGMT_RX_FW_CONSUMED_PARAM_MGMT_PKT_CTR_VALID_GET GENMASK(15, 15) ++#define WMI_MGMT_RX_FW_CONSUMED_PARAM_MGMT_PKT_CTR_GET GENMASK(31, 16) ++ ++struct ath12k_wmi_mgmt_rx_fw_consumed_hdr { ++ u32 rx_tsf_l32; /* h/w assigned timestamp of the rx frame in micro sec */ ++ u32 rx_tsf_u32 ;/* h/w assigned timestamp of the rx frame in micro sec */ ++ u32 pdev_id; /* pdev_id for identifying the MAC the rx mgmt frame was received by */ ++ /** ++ * peer_info_subtype ++ * ++ * [15:0]: ml_peer_id, ML peer_id unique across chips ++ * [18:16]: ieee_link_id, protocol link id on which the rx frame is received ++ * [27:19]: reserved ++ * [31:28]: subtype, subtype of the received MGMT frame ++ */ ++ u32 peer_info_subtype; ++ u32 chan_freq; /* frequency in MHz of the channel on which this frame was received */ ++ /* Timestamp (in micro sec) of the last fw consumed/dropped mgmt. frame, same across chips */ ++ u32 global_timestamp; ++ /** ++ * mgmt_pkt_ctr_info ++ * ++ * [14:0]: reserved ++ * [15]: mgmt_pkt_ctr_valid ++ * [31:16]: mgmt_pkt_ctr, Sequence number of the last fw consumed mgmt frame ++ */ ++ u32 mgmt_pkt_ctr_info; ++ u32 rx_ppdu_duration_us; /* receive duration in us */ ++ u32 mpdu_end_timestamp; /* mpdu end timestamp in us (based on HWMLO timer) */ ++}; ++ ++#define WMI_MGMT_RX_REO_PARAM_IEEE_LINK_ID_GET GENMASK(14, 12) ++#define WMI_MGMT_RX_REO_PARAM_MGMT_PKT_CTR_VALID_GET GENMASK(15, 15) ++#define WMI_MGMT_RX_REO_PARAM_MGMT_PKT_CTR_GET GENMASK(31, 16) ++ ++/** Data structure of the TLV to add in RX EVENTID for providing REO params ++ * like global_timestamp and mgmt_pkt_ctr ++ */ ++struct ath12k_wmi_mgmt_rx_reo_params { ++ /* Timestamp (in micro sec) of the last fw forwarded mgmt. frame, same across chips */ ++ u32 global_timestamp; ++ /** ++ * mgmt_pkt_ctr_link_info ++ * ++ * [11:0]: reserved ++ * [14:12]: ieee_link_id, protocol link id on which the rx frame is received ++ * [15]: mgmt_pkt_ctr_valid ++ * [31:16]: mgmt_pkt_ctr, Sequence number of the last fw forwarded mgmt frame ++ */ ++ ++ u32 mgmt_pkt_ctr_link_info; ++ u32 rx_ppdu_duration_us; /* receive duration in us */ ++ u32 mpdu_end_timestamp; /* mpdu end timestamp in us (based on HWMLO timer) */ ++}; ++ ++/* struct ath12k_mgmt_rx_reo_params - MGMT Rx REO parameters ++ * @valid: Whether these params are valid ++ * @pdev_id: pdev ID for which FW consumed event is received ++ * @link_id: link ID for which FW consumed event is received ++ * @mgmt_pkt_ctr: MGMT packet counter of the frame that is consumed ++ * @global_timestamp: Global timestamp of the frame that is consumed ++ * @duration_us: duration in us ++ * @start_timestamp: start time stamp ++ * @end_timestamp: end time stamp ++ */ ++struct ath12k_mgmt_rx_reo_params { ++ bool valid; ++ u8 pdev_id; ++ u8 link_id; ++ u8 mlo_grp_id; ++ u16 mgmt_pkt_ctr; ++ u32 global_timestamp; ++ u16 duration_us; ++ u32 start_timestamp; ++ u32 end_timestamp; ++}; ++ ++/* struct ath12k_mgmt_rx_reo_filter - MGMT Rx REO filter ++ * @filter_low: Least significant 32-bits of the filter ++ * @filter_high: Most significant 32-bits of the filter ++ */ ++struct ath12k_mgmt_rx_reo_filter { ++ u32 low; ++ u32 high; ++}; ++ ++/* struct ath12k_mgmt_rx_reo_wait_count - Wait count for a mgmt frame ++ * @per_link_count: Array of wait counts for all MLO links. Each array entry ++ * holds the number of frames this mgmt frame should wait for on that ++ * particular link. ++ * @total_count: Sum of entries in @per_link_count ++ */ ++struct ath12k_mgmt_rx_reo_wait_count { ++ unsigned int per_link_count[ATH12K_WMI_MLO_MAX_LINKS]; ++ unsigned long long total_count; ++}; ++ ++/* struct ath12k_mgmt_rx_reo_snapshot_params - Represents the simplified version of ++ * Management Rx Frame snapshot for Host use. Note that this is different from ++ * the structure shared between the Host and FW/HW ++ * @valid: Whether this snapshot is valid ++ * @retry_count: snapshot read retry count ++ * @mgmt_pkt_ctr: MGMT packet counter. This will be local to a particular ++ * HW link ++ * @global_timestamp: Global timestamp.This is taken from a clock which is ++ * common across all the HW links ++ */ ++struct ath12k_mgmt_rx_reo_snapshot_params { ++ bool valid; ++ u8 retry_count; ++ u16 mgmt_pkt_ctr; ++ u32 global_timestamp; ++}; ++ ++/* struct ath12k_mgmt_rx_reo_shared_snapshot - Represents the management rx-reorder ++ * shared snapshots ++ * @ath12k_mgmt_rx_reo_snapshot_low: Lower 32 bits of the reo snapshot ++ * @ath12k_mgmt_rx_reo_snapshot_high: Higher 32 bits of the reo snapshot ++ */ ++struct ath12k_mgmt_rx_reo_shared_snapshot { ++ union { ++ u32 ath12k_mgmt_rx_reo_snapshot_low; ++ u32 mgmt_pkt_ctr_ver_a:16, ++ global_timestamp_redundant_ver_a:15, ++ valid_ver_a:1; ++ u32 global_timestamp_low_ver_b:15, ++ mgmt_pkt_ctr_ver_b:16, ++ valid_ver_b:1; ++ } u_low; ++ ++ union { ++ u32 ath12k_mgmt_rx_reo_snapshot_high; ++ u32 global_timestamp_ver_a; ++ u32 mgmt_pkt_ctr_redundant_ver_b:15, ++ global_timestamp_high_ver_b:17; ++ } u_high; ++}; ++ ++/* struct ath12k_mgmt_rx_reo_snapshot_info - Information related to management Rx ++ * reorder snapshot ++ * @address: Snapshot address ++ * @version: Snapshot version ++ */ ++struct ath12k_mgmt_rx_reo_snapshot_info { ++ struct ath12k_mgmt_rx_reo_shared_snapshot *address; ++ u8 version; ++}; ++ ++#define ATH12K_MGMT_RX_REO_SNAPSHOT_B2B_READ_SWAR_RETRY_LIMIT (11) ++#define ATH12K_MGMT_RX_REO_SNAPSHOT_READ_RETRY_LIMIT (25) ++ ++/* enum ath12k_mgmt_rx_reo_shared_snapshot_id - Represents the management ++ * rx-reorder snapshots shared between host and target in the host DDR. ++ * These snapshots are written by FW/HW and read by Host. ++ * @ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_FW_CONSUMED: FW consumed snapshot ++ * @ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_FW_FORWARDED: FW forwarded snapshot ++ * @ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_MAC_HW: MAC HW snapshot ++ * @ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_MAX: Max number of snapshots ++ * @ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_INVALID: Invalid snapshot ++ */ ++enum ath12k_mgmt_rx_reo_shared_snapshot_id { ++ ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_FW_CONSUMED = 0, ++ ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_FW_FORWARDED = 1, ++ ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_MAC_HW = 2, ++ ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_MAX = 3, ++ ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_INVALID, ++}; ++ ++/* struct ath12k_mgmt_rx_reo_pdev_info - Pdev information required by the Management ++ * Rx REO module ++ * @host_snapshot: Latest snapshot seen at the Host. ++ * It considers both MGMT Rx and MGMT FW consumed. ++ * @last_valid_shared_snapshot: Array of last valid snapshots(for snapshots ++ * shared between host and target) ++ * @host_target_shared_snapshot_info: Array of meta information related to ++ * snapshots(for snapshots shared between host and target) ++ * @filter: MGMT Rx REO filter ++ * @init_complete: Flag to indicate initialization completion of the ++ * ath12k_mgmt_rx_reo_pdev_info object ++ */ ++struct ath12k_mgmt_rx_reo_pdev_info { ++ struct ath12k_mgmt_rx_reo_snapshot_params host_snapshot; ++ struct ath12k_mgmt_rx_reo_snapshot_params last_valid_shared_snapshot ++ [ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_MAX]; ++ struct ath12k_mgmt_rx_reo_snapshot_info host_target_shared_snapshot_info ++ [ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_MAX]; ++ struct ath12k_mgmt_rx_reo_filter filter; ++ struct ath12k_mgmt_rx_reo_shared_snapshot raw_snapshots[ATH12K_WMI_MLO_MAX_LINKS] ++ [ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_MAX] ++ [ATH12K_MGMT_RX_REO_SNAPSHOT_READ_RETRY_LIMIT] ++ [ATH12K_MGMT_RX_REO_SNAPSHOT_B2B_READ_SWAR_RETRY_LIMIT]; ++ bool init_complete; ++}; ++ ++/* enum ath12k_mgmt_rx_reo_frame_descriptor_type - Enumeration for management frame ++ * descriptor type. ++ * @ATH12K_MGMT_RX_REO_FRAME_DESC_HOST_CONSUMED_FRAME: Management frame to be consumed ++ * by host. ++ * @ATH12K_MGMT_RX_REO_FRAME_DESC_FW_CONSUMED_FRAME: Management frame consumed by FW ++ * @ATH12K_MGMT_RX_REO_FRAME_DESC_ERROR_FRAME: Management frame which got dropped ++ * at host due to any error ++ * @ATH12K_MGMT_RX_REO_FRAME_DESC_TYPE_MAX: Maximum number of frame types ++ */ ++enum ath12k_mgmt_rx_reo_frame_descriptor_type { ++ ATH12K_MGMT_RX_REO_FRAME_DESC_HOST_CONSUMED_FRAME = 0, ++ ATH12K_MGMT_RX_REO_FRAME_DESC_FW_CONSUMED_FRAME, ++ ATH12K_MGMT_RX_REO_FRAME_DESC_ERROR_FRAME, ++ ATH12K_MGMT_RX_REO_FRAME_DESC_TYPE_MAX, ++}; ++ ++/* struct ath12k_mgmt_rx_reo_global_ts_info - This structure holds the global time ++ * stamp information of a frame. ++ * @valid: Indicates whether global time stamp is valid ++ * @global_ts: Global time stamp value ++ * @start_ts: Start time stamp value ++ * @end_ts: End time stamp value ++ * @expiry_time: information in the structure is valid until expiry_time ++ */ ++struct ath12k_mgmt_rx_reo_global_ts_info { ++ bool valid; ++ u32 global_ts; ++ u32 start_ts; ++ u32 end_ts; ++ unsigned long expiry_time; ++}; ++ ++/* struct ath12k_reo_ingress_debug_frame_info - Debug information about a frame ++ * entering reorder process ++ * @link_id: link id ++ * @mgmt_pkt_ctr: management packet counter ++ * @global_timestamp: MLO global time stamp ++ * @start_timestamp: start time stamp of the frame ++ * @end_timestamp: end time stamp of the frame ++ * @duration_us: duration of the frame in us ++ * @desc_type: Type of the frame descriptor ++ * @frame_type: frame type ++ * @frame_subtype: frame sub type ++ * @ingress_timestamp: Host time stamp when the frames enters the reorder ++ * process ++ * @ingress_duration: Duration in us for processing the incoming frame. ++ * ingress_duration = Time stamp at which reorder list update is done - ++ * Time stamp at which frame has entered the reorder module ++ * @wait_count: Wait count calculated for the current frame ++ * @is_queued: Indicates whether this frame is queued to reorder list ++ * @is_stale: Indicates whether this frame is stale. ++ * @is_parallel_rx: Indicates that this frame is received in parallel to the ++ * last frame which is delivered to the upper layer. ++ * @zero_wait_count_rx: Indicates whether this frame's wait count was ++ * zero when received by host ++ * @immediate_delivery: Indicates whether this frame can be delivered ++ * immediately to the upper layers ++ * @is_error: Indicates whether any error occurred during processing this frame ++ * @ts_last_released_frame: Stores the global time stamp for the last frame ++ * removed from the reorder list ++ * @list_size_rx: Size of the reorder list when this frame is received (before ++ * updating the list based on this frame). ++ * @list_insertion_pos: Position in the reorder list where this frame is going ++ * to get inserted (Applicable for only host consumed frames) ++ * @shared_snapshots: snapshots shared b/w host and target ++ * @host_snapshot: host snapshot ++ * @cpu_id: CPU index ++ * @reo_required: Indicates whether reorder is required for the current frame. ++ * If reorder is not required, current frame will just be used for updating the ++ * wait count of frames already part of the reorder list. ++ */ ++struct ath12k_reo_ingress_debug_frame_info { ++ u8 link_id; ++ u16 mgmt_pkt_ctr; ++ u32 global_timestamp; ++ u32 start_timestamp; ++ u32 end_timestamp; ++ u32 duration_us; ++ enum ath12k_mgmt_rx_reo_frame_descriptor_type desc_type; ++ u8 frame_type; ++ u8 frame_subtype; ++ u64 ingress_timestamp; ++ u64 ingress_duration; ++ struct ath12k_mgmt_rx_reo_wait_count wait_count; ++ bool is_queued; ++ bool is_stale; ++ bool is_parallel_rx; ++ bool zero_wait_count_rx; ++ bool immediate_delivery; ++ bool is_error; ++ struct ath12k_mgmt_rx_reo_global_ts_info ts_last_released_frame; ++ s16 list_size_rx; ++ s16 list_insertion_pos; ++ struct ath12k_mgmt_rx_reo_snapshot_params shared_snapshots ++ [ATH12K_WMI_MLO_MAX_LINKS][ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_MAX]; ++ struct ath12k_mgmt_rx_reo_snapshot_params host_snapshot[ATH12K_WMI_MLO_MAX_LINKS]; ++ int cpu_id; ++ bool reo_required; ++}; ++ ++/* struct ath12k_reo_ingress_frame_stats - Structure to store statistics related to ++ * incoming frames ++ * @ingress_count: Number of frames entering reo module ++ * @queued_count: Number of frames queued to reorder list ++ * @zero_wait_count_rx_count: Number of frames for which wait count is ++ * zero when received at host ++ * @immediate_delivery_count: Number of frames which can be delivered ++ * immediately to the upper layers without reordering. A frame can be ++ * immediately delivered if it has wait count of zero on reception at host ++ * and the global time stamp is less than or equal to the global time ++ * stamp of all the frames in the reorder list. Such frames would get ++ * inserted to the head of the reorder list and gets delivered immediately ++ * to the upper layers. ++ * @stale_count: Number of stale frames. Any frame older than the ++ * last frame delivered to upper layer is a stale frame. ++ * @error_count: Number of frames dropped due to error occurred ++ * within the reorder module ++ */ ++struct ath12k_reo_ingress_frame_stats { ++ u64 ingress_count ++ [ATH12K_WMI_MLO_MAX_LINKS][ATH12K_MGMT_RX_REO_FRAME_DESC_TYPE_MAX]; ++ u64 queued_count[ATH12K_WMI_MLO_MAX_LINKS]; ++ u64 zero_wait_count_rx_count[ATH12K_WMI_MLO_MAX_LINKS]; ++ u64 immediate_delivery_count[ATH12K_WMI_MLO_MAX_LINKS]; ++ u64 stale_count[ATH12K_WMI_MLO_MAX_LINKS] ++ [ATH12K_MGMT_RX_REO_FRAME_DESC_TYPE_MAX]; ++ u64 error_count[ATH12K_WMI_MLO_MAX_LINKS] ++ [ATH12K_MGMT_RX_REO_FRAME_DESC_TYPE_MAX]; ++}; ++ ++#define ATH12K_MGMT_RX_REO_INGRESS_FRAME_DEBUG_INFO_BOARDER_MAX_SIZE (785) ++ ++/* struct reo_ingress_debug_info - Circular array to store the ++ * debug information about the frames entering the reorder process. ++ * @frame_list: Circular array to store the debug info about frames ++ * @frame_list_size: Size of circular array @frame_list ++ * @next_index: The index at which information about next frame will be logged ++ * @wrap_aroud: Flag to indicate whether wrap around occurred when logging ++ * debug information to @frame_list ++ * @stats: Stats related to incoming frames ++ * @boarder: boarder string ++ */ ++struct reo_ingress_debug_info { ++ struct ath12k_reo_ingress_debug_frame_info *frame_list; ++ u16 frame_list_size; ++ int next_index; ++ bool wrap_aroud; ++ struct ath12k_reo_ingress_frame_stats stats; ++ char boarder[ATH12K_MGMT_RX_REO_INGRESS_FRAME_DEBUG_INFO_BOARDER_MAX_SIZE + 1]; ++}; ++ ++/* struct ath12k_reo_egress_debug_frame_info - Debug information about a frame ++ * leaving the reorder module ++ * @is_delivered: Indicates whether the frame is delivered to upper layers ++ * @is_premature_delivery: Indicates whether the frame is delivered ++ * prematurely ++ * @link_id: link id ++ * @mgmt_pkt_ctr: management packet counter ++ * @global_timestamp: MLO global time stamp ++ * @ingress_timestamp: Host time stamp when the frame enters the reorder module ++ * @insertion_ts: Host time stamp when the frame is inserted into the reorder ++ * list ++ * @egress_timestamp: Host time stamp just before delivery of the frame to upper ++ * layer ++ * @egress_duration: Duration in us taken by the upper layer to process ++ * the frame. ++ * @removal_ts: Host time stamp when this entry is removed from the list ++ * @initial_wait_count: Wait count when the frame is queued ++ * @final_wait_count: Wait count when frame is released to upper layer ++ * @release_reason: Reason for delivering the frame to upper layers ++ * @shared_snapshots: snapshots shared b/w host and target ++ * @host_snapshot: host snapshot ++ * @cpu_id: CPU index ++ */ ++struct ath12k_reo_egress_debug_frame_info { ++ bool is_delivered; ++ bool is_premature_delivery; ++ u8 link_id; ++ u16 mgmt_pkt_ctr; ++ u32 global_timestamp; ++ u64 ingress_timestamp; ++ u64 insertion_ts; ++ u64 egress_timestamp; ++ u64 egress_duration; ++ u64 removal_ts; ++ struct ath12k_mgmt_rx_reo_wait_count initial_wait_count; ++ struct ath12k_mgmt_rx_reo_wait_count final_wait_count; ++ u8 release_reason; ++ struct ath12k_mgmt_rx_reo_snapshot_params shared_snapshots ++ [ATH12K_WMI_MLO_MAX_LINKS][ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_MAX]; ++ struct ath12k_mgmt_rx_reo_snapshot_params host_snapshot[ATH12K_WMI_MLO_MAX_LINKS]; ++ int cpu_id; ++}; ++ ++/* Reason to release an entry from the reorder list */ ++#define MGMT_RX_REO_LIST_ENTRY_RELEASE_REASON_ZERO_WAIT_COUNT (BIT(0)) ++#define MGMT_RX_REO_LIST_ENTRY_RELEASE_REASON_AGED_OUT (BIT(1)) ++#define MGMT_RX_REO_LIST_ENTRY_RELEASE_REASON_OLDER_THAN_AGED_OUT_FRAME (BIT(2)) ++#define MGMT_RX_REO_LIST_ENTRY_RELEASE_REASON_LIST_MAX_SIZE_EXCEEDED (BIT(3)) ++#define MGMT_RX_REO_RELEASE_REASON_MAX \ ++ (MGMT_RX_REO_LIST_ENTRY_RELEASE_REASON_LIST_MAX_SIZE_EXCEEDED << 1) ++ ++/** ++ * struct reo_egress_frame_stats - Structure to store statistics related to ++ * outgoing frames ++ * @delivery_attempts_count: Number of attempts to deliver management ++ * frames to upper layers ++ * @delivery_success_count: Number of successful management frame ++ * deliveries to upper layer ++ * @premature_delivery_count: Number of frames delivered ++ * prematurely. Premature delivery is the delivery of a management frame ++ * to the upper layers even before its wait count is reaching zero. ++ * @delivery_count: Number frames delivered successfully for ++ * each link and release reason. ++ */ ++struct reo_egress_frame_stats { ++ u64 delivery_attempts_count[ATH12K_WMI_MLO_MAX_LINKS]; ++ u64 delivery_success_count[ATH12K_WMI_MLO_MAX_LINKS]; ++ u64 premature_delivery_count[ATH12K_WMI_MLO_MAX_LINKS]; ++ u64 delivery_count[ATH12K_WMI_MLO_MAX_LINKS] ++ [MGMT_RX_REO_RELEASE_REASON_MAX]; ++}; ++ ++#define ATH12K_MGMT_RX_REO_EGRESS_FRAME_DEBUG_INFO_BOARDER_MAX_SIZE (816) ++ ++/** ++ * struct ath12k_reo_egress_debug_info - Circular array to store the ++ * debug information about the frames leaving the reorder module. ++ * @frame_list: Circular array to store the debug info ++ * @frame_list_size: Size of circular array @frame_list ++ * @next_index: The index at which information about next frame will be logged ++ * @wrap_aroud: Flag to indicate whether wrap around occurred when logging ++ * debug information to @frame_list ++ * @stats: Stats related to outgoing frames ++ * @boarder: boarder string ++ */ ++struct ath12k_reo_egress_debug_info { ++ struct ath12k_reo_egress_debug_frame_info *frame_list; ++ u16 frame_list_size; ++ int next_index; ++ bool wrap_aroud; ++ struct reo_egress_frame_stats stats; ++ char boarder[ATH12K_MGMT_RX_REO_EGRESS_FRAME_DEBUG_INFO_BOARDER_MAX_SIZE + 1]; ++}; ++ ++/** ++ * struct mgmt_rx_reo_list – Linked list used to reorder the management frames ++ * received. Each list entry would correspond to a management frame. List ++ * entries would be sorted in the same order in which they are received by MAC ++ * HW. ++ * @list: List used for reordering ++ * @list_lock: Lock to protect the list ++ * @max_list_size: Maximum size of the reorder list ++ * @list_entry_timeout_us: Time out value(microsecond) for the reorder list ++ * entries ++ * @ageout_timer: Periodic timer to age-out the list entries ++ * @global_mgmt_rx_inactivity_timer: Global management Rx inactivity timer ++ * @ts_last_released_frame: Stores the global time stamp for the last frame ++ * removed from the reorder list ++ */ ++struct mgmt_rx_reo_list { ++ struct ath12k_base *ab; ++ struct list_head list; ++ int count; ++ /* protects the list used for reordering */ ++ spinlock_t list_lock; ++ u32 max_list_size; ++ u32 list_entry_timeout_us; ++ struct timer_list ageout_timer; ++ struct timer_list global_mgmt_rx_inactivity_timer; ++ struct ath12k_mgmt_rx_reo_global_ts_info ts_last_released_frame; ++}; ++ ++/** ++ * struct ath12k_mgmt_rx_reo_context - This structure holds the info required for ++ * management rx-reordering. Reordering is done across all the psocs. ++ * So there should be only one instance of this structure defined. ++ * @reo_list: Linked list used for reordering ++ * @rx_reorder_entry_lock: Spin lock to protect rx reorder process entry critical ++ * section execution ++ * @frame_release_lock: Spin lock to serialize the frame delivery to the ++ * upper layers. This could prevent race conditions like the one given in ++ * the following example. ++ * Lets take an example of 2 links (Link A & B) and each has received ++ * a management frame A1(deauth) and B1(auth) such that MLO global time ++ * stamp of A1 < MLO global time stamp of B1. Host is concurrently ++ * executing "mgmt_rx_reo_list_release_entries" for A1 and B1 in ++ * 2 different CPUs. It is possible that frame B1 gets processed by ++ * upper layers before frame A1 and this could result in unwanted ++ * disconnection. Hence it is required to serialize the delivery ++ * of management frames to upper layers in the strict order of MLO ++ * global time stamp. ++ * @sim_context: Management rx-reorder simulation context ++ * @ingress_debug_info_init_count: Initialization count of ++ * object @ingress_frame_debug_info ++ * @ingress_frame_debug_info: Debug object to log incoming frames ++ * @egress_frame_debug_info: Debug object to log outgoing frames ++ * @egress_debug_info_init_count: Initialization count of ++ * object @egress_frame_debug_info ++ * @simulation_in_progress: Flag to indicate whether simulation is ++ * in progress ++ * @init_done: This will indicate intialization of management rx-reorder list. ++ * @timer_init_done: This will indicate firing of management rx-reorder timer. ++ */ ++struct ath12k_mgmt_rx_reo_context { ++ struct mgmt_rx_reo_list reo_list; ++ /* Protects the rx reorder process entry critical section exec */ ++ spinlock_t rx_reorder_entry_lock; ++ /* Lock to Serialize the frame delivery */ ++ spinlock_t frame_release_lock; ++ atomic_t ingress_debug_info_init_count; ++ struct reo_ingress_debug_info ingress_frame_debug_info; ++ atomic_t egress_debug_info_init_count; ++ struct ath12k_reo_egress_debug_info egress_frame_debug_info; ++ bool init_done; ++ bool timer_init_done; ++}; ++ ++/** MGMT RX REO Changes */ ++/* Macros for having versioning info for compatibility check between host and firmware */ ++#define MLO_SHMEM_MAJOR_VERSION 2 ++#define MLO_SHMEM_MINOR_VERSION 1 ++ ++/** ++ * Enum which defines different versions of management Rx reorder snapshots. ++ */ ++enum { ++ /** ++ * DWORD Lower: ++ * [15:0] : Management packet counter ++ * [30:16] : Redundant global time stamp = Global time stamp[14:0] ++ * [31] : Valid ++ * ++ * DWORD Upper: ++ * [31:0] : Global time stamp ++ * ++ */ ++ MGMT_RX_REO_SNAPSHOT_VERSION_TIMESTAMP_REDUNDANCY = 0, ++ ++ /** ++ * DWORD Lower: ++ * [14:0] : Global time stamp[14:0] ++ * [30:15] : Management packet counter ++ * [31] : Valid ++ * ++ * DWORD Upper: ++ * [14:0] : Redundant management packet counter = Management packet ++ * counter[14:0] ++ * [31:15] : Global time stamp[31:15] ++ */ ++ MGMT_RX_REO_SNAPSHOT_VERSION_PKT_CTR_REDUNDANCY = 1, ++}; ++ ++#define ATH12K_MGMT_RX_REO_INVALID_SNAPSHOT_VERSION (-1) ++ ++/** ++ * struct mgmt_rx_reo_list_entry - Entry in the Management reorder list ++ * @node: List node ++ * @nbuf: nbuf corresponding to this frame ++ * @rx_params: Management rx event parameters ++ * @wait_count: Wait counts for the frame ++ * @initial_wait_count: Wait count when the frame is queued ++ * @insertion_ts: Host time stamp when this entry is inserted to the list. ++ * @removal_ts: Host time stamp when this entry is removed from the list ++ * @ingress_timestamp: Host time stamp when this frame has arrived reorder ++ * module ++ * @egress_timestamp: Host time stamp when this frame has exited reorder ++ * module ++ * @status: Status for this entry ++ * @pdev: Pointer to pdev object corresponding to this frame ++ * @release_reason: Release reason ++ * @is_delivered: Indicates whether the frame is delivered successfully ++ * @is_premature_delivery: Indicates whether the frame is delivered ++ * prematurely ++ * @is_parallel_rx: Indicates that this frame is received in parallel to the ++ * last frame which is delivered to the upper layer. ++ * @shared_snapshots: snapshots shared b/w host and target ++ * @host_snapshot: host snapshot ++ */ ++struct mgmt_rx_reo_list_entry { ++ struct list_head node; ++ struct sk_buff *nbuf; ++ struct mgmt_rx_event_params *rx_params; ++ struct ath12k_mgmt_rx_reo_wait_count wait_count; ++ struct ath12k_mgmt_rx_reo_wait_count initial_wait_count; ++ u64 insertion_ts; ++ u64 removal_ts; ++ u64 ingress_timestamp; ++ u64 egress_timestamp; ++ u32 status; ++ struct ath12k *ar; ++ u8 release_reason; ++ bool is_delivered; ++ bool is_premature_delivery; ++ bool is_parallel_rx; ++ struct ath12k_mgmt_rx_reo_snapshot_params shared_snapshots ++ [ATH12K_WMI_MLO_MAX_LINKS][ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_MAX]; ++ struct ath12k_mgmt_rx_reo_snapshot_params host_snapshot[ATH12K_WMI_MLO_MAX_LINKS]; ++}; ++ ++#define ATH12K_MGMT_RX_REO_STATUS_WAIT_FOR_FRAME_ON_OTHER_LINKS (BIT(0)) ++#define ATH12K_MGMT_RX_REO_STATUS_AGED_OUT (BIT(1)) ++#define ATH12K_MGMT_RX_REO_STATUS_OLDER_THAN_LATEST_AGED_OUT_FRAME (BIT(2)) ++#define ATH12K_MGMT_RX_REO_STATUS_LIST_MAX_SIZE_EXCEEDED (BIT(3)) ++ ++#define ATH12K_MGMT_RX_REO_LIST_ENTRY_IS_WAITING_FOR_FRAME_ON_OTHER_LINK(entry) \ ++ ((entry)->status & ATH12K_MGMT_RX_REO_STATUS_WAIT_FOR_FRAME_ON_OTHER_LINKS) ++#define ATH12K_MGMT_RX_REO_LIST_ENTRY_IS_AGED_OUT(entry) \ ++ ((entry)->status & ATH12K_MGMT_RX_REO_STATUS_AGED_OUT) ++#define ATH12K_MGMT_RX_REO_LIST_ENTRY_IS_OLDER_THAN_LATEST_AGED_OUT_FRAME(entry) \ ++ ((entry)->status & ATH12K_MGMT_RX_REO_STATUS_OLDER_THAN_LATEST_AGED_OUT_FRAME) ++#define ATH12K_MGMT_RX_REO_LIST_ENTRY_IS_MAX_SIZE_EXCEEDED(entry) \ ++ ((entry)->status & ATH12K_MGMT_RX_REO_STATUS_LIST_MAX_SIZE_EXCEEDED) ++ ++#define ATH12K_MGMT_RX_REO_GLOBAL_MGMT_RX_INACTIVITY_TIMEOUT (600 * HZ) ++#define ATH12K_MGMT_RX_REO_LIST_MAX_SIZE (100) ++#define ATH12K_MGMT_RX_REO_LIST_TIMEOUT_US (500000) ++#define ATH12K_MGMT_RX_REO_AGEOUT_TIMER_PERIOD_MS (250) ++ ++#define ATH12K_MGMT_RX_REO_PKT_CTR_HALF_RANGE (0x8000) ++#define ATH12K_MGMT_RX_REO_PKT_CTR_FULL_RANGE (ATH12K_MGMT_RX_REO_PKT_CTR_HALF_RANGE << 1) ++ + struct mgmt_rx_event_params { + u32 chan_freq; + u32 channel; +@@ -5461,6 +6140,61 @@ struct mgmt_rx_event_params { + int rssi; + u32 tsf_delta; + u8 pdev_id; ++ struct ath12k_mgmt_rx_reo_params reo_params; ++}; ++ ++/** ++ * struct ath12k_mgmt_rx_reo_frame_descriptor - Frame Descriptor used to describe ++ * a management frame in mgmt rx reo module. ++ * @type: Frame descriptor type ++ * @frame_type: frame type ++ * @frame_subtype: frame subtype ++ * @nbuf: nbuf corresponding to this frame ++ * @rx_params: Management rx event parameters ++ * @wait_count: Wait counts for the frame ++ * @ingress_timestamp: Host time stamp when the frames enters the reorder ++ * process ++ * @is_stale: Indicates whether this frame is stale. Any frame older than the ++ * last frame delivered to upper layer is a stale frame. Stale frames should not ++ * be delivered to the upper layers. These frames can be discarded after ++ * updating the host snapshot and wait counts of entries currently residing in ++ * the reorder list. ++ * @zero_wait_count_rx: Indicates whether this frame's wait count was ++ * zero when received by host ++ * @immediate_delivery: Indicates whether this frame can be delivered ++ * immediately to the upper layers ++ * @list_size_rx: Size of the reorder list when this frame is received (before ++ * updating the list based on this frame). ++ * @list_insertion_pos: Position in the reorder list where this frame is going ++ * to get inserted (Applicable for only host consumed frames) ++ * @shared_snapshots: snapshots shared b/w host and target ++ * @host_snapshot: host snapshot ++ * @is_parallel_rx: Indicates that this frame is received in parallel to the ++ * last frame which is delivered to the upper layer. ++ * @pkt_ctr_delta: Packet counter delta of the current and last frame ++ * @reo_required: Indicates whether reorder is required for the current frame. ++ * If reorder is not required, current frame will just be used for updating the ++ * wait count of frames already part of the reorder list. ++ */ ++struct ath12k_mgmt_rx_reo_frame_descriptor { ++ enum ath12k_mgmt_rx_reo_frame_descriptor_type type; ++ u8 frame_type; ++ u8 frame_subtype; ++ struct sk_buff *nbuf; ++ struct mgmt_rx_event_params *rx_params; ++ struct ath12k_mgmt_rx_reo_wait_count wait_count; ++ u64 ingress_timestamp; ++ bool is_stale; ++ bool zero_wait_count_rx; ++ bool immediate_delivery; ++ s16 list_size_rx; ++ s16 list_insertion_pos; ++ struct ath12k_mgmt_rx_reo_snapshot_params shared_snapshots ++ [ATH12K_WMI_MLO_MAX_LINKS][ATH12K_MGMT_RX_REO_SHARED_SNAPSHOT_MAX]; ++ struct ath12k_mgmt_rx_reo_snapshot_params host_snapshot[ATH12K_WMI_MLO_MAX_LINKS]; ++ bool is_parallel_rx; ++ int pkt_ctr_delta; ++ bool reo_required; + }; + + #define ATH_MAX_ANTENNA 4 +@@ -5486,6 +6220,8 @@ struct wmi_tlv_mgmt_rx_parse { + struct wmi_mgmt_rx_hdr *fixed; + u8 *frame_buf; + bool frame_buf_done; ++ struct ath12k_wmi_mgmt_rx_reo_params *reo_params; ++ struct ath12k_wmi_mgmt_rx_fw_consumed_hdr *fw_consumed_reo_params; + }; + + #define MAX_ANTENNA_EIGHT 8 +@@ -7481,4 +8217,10 @@ int ath12k_wmi_pdev_multiple_vdev_restar + int ath12k_wmi_vdev_adfs_ch_cfg_cmd_send(struct ath12k *ar,u32 vdev_id, + struct cfg80211_chan_def *chandef); + int ath12k_wmi_vdev_adfs_ocac_abort_cmd_send(struct ath12k *ar,u32 vdev_id); ++int ath12k_wmi_mgmt_rx_reo_filter_config(struct ath12k *ar, ++ struct ath12k_mgmt_rx_reo_filter *filter); ++int ++ath12k_mgmt_rx_reo_init_context(struct ath12k_base *ab); ++int ++ath12k_mgmt_rx_reo_deinit_context(struct ath12k_base *ab); + #endif +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/mac.c +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/mac.c ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/mac.c +@@ -9163,14 +9163,52 @@ static void ath12k_mac_radio_stop(struct + spin_unlock_bh(&ar->data_lock); + } + ++static void ath12k_mgmt_rx_reo_init_timer(struct ath12k_hw_group *ag) ++{ ++ struct ath12k_mgmt_rx_reo_context *reo_context = &ag->rx_reo; ++ ++ if (!(ag->mlo_mem.is_mlo_mem_avail && ag->mgmt_rx_reorder)) ++ return; ++ ++ if (reo_context->timer_init_done) ++ return; ++ ++ mod_timer(&reo_context->reo_list.ageout_timer, jiffies + ++ msecs_to_jiffies(ATH12K_MGMT_RX_REO_AGEOUT_TIMER_PERIOD_MS)); ++ ++ mod_timer(&reo_context->reo_list.global_mgmt_rx_inactivity_timer, jiffies + ++ ATH12K_MGMT_RX_REO_GLOBAL_MGMT_RX_INACTIVITY_TIMEOUT); ++ ++ reo_context->timer_init_done = true; ++} ++ ++static void ath12k_mgmt_rx_reo_deinit_timer(struct ath12k_hw_group *ag) ++{ ++ struct ath12k_mgmt_rx_reo_context *reo_context = &ag->rx_reo; ++ ++ if (!(ag->mlo_mem.is_mlo_mem_avail && ag->mgmt_rx_reorder)) ++ return; ++ ++ if (!reo_context->timer_init_done) ++ return; ++ ++ del_timer_sync(&reo_context->reo_list.global_mgmt_rx_inactivity_timer); ++ del_timer_sync(&reo_context->reo_list.ageout_timer); ++ ++ reo_context->timer_init_done = false; ++} ++ + static int ath12k_mac_op_start(struct ieee80211_hw *hw) + { + struct ath12k_hw *ah = hw->priv; + struct ath12k *ar; + struct ath12k_base *ab; ++ struct ath12k_hw_group *ag = ah->ag; + int i; + int ret; + ++ ath12k_mgmt_rx_reo_init_timer(ag); ++ + mutex_lock(&ah->conf_mutex); + ar = ah->radio; + ab = ar->ab; +@@ -9211,8 +9249,11 @@ static void ath12k_mac_op_stop(struct ie + { + struct ath12k_hw *ah = hw->priv; + struct ath12k *ar; ++ struct ath12k_hw_group *ag = ah->ag; + int i; + ++ ath12k_mgmt_rx_reo_deinit_timer(ag); ++ + mutex_lock(&ah->conf_mutex); + ar = ah->radio; + +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/qmi.c +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/qmi.c ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/qmi.c +@@ -3927,7 +3927,7 @@ int ath12k_qmi_mlo_global_snapshot_mem_i + struct target_mem_chunk *mlo_chunk; + int ret = 0, mlo_idx = 0; + +- if (!ab->mgmt_rx_reorder) ++ if (!ag->mgmt_rx_reorder) + return 0; + + if (!ag->mlo_mem.is_mlo_mem_avail) diff --git a/feeds/ipq95xx/mac80211/patches/qca/748-ath12k-add-BUG_ONs-for-debugging-purpose.patch b/feeds/ipq95xx/mac80211/patches/qca/748-ath12k-add-BUG_ONs-for-debugging-purpose.patch new file mode 100644 index 000000000..f90b24b95 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/748-ath12k-add-BUG_ONs-for-debugging-purpose.patch @@ -0,0 +1,191 @@ +From 9ea5e86b135849595d47ab07aafd2cf50e1973ea Mon Sep 17 00:00:00 2001 +From: Karthikeyan Kathirvel +Date: Thu, 2 Mar 2023 12:14:24 +0530 +Subject: [PATCH 3/3] ath12k: add BUG_ONs for debugging purpose + +WARN_ONs of Mgmt Rx Re-ordering will be treated as BUG_ONs to debug and +stabilize the code. + +These BUG_ONs will be removed or reverted back to WARN_ON once after the +code stabilization. + +Signed-off-by: Karthikeyan Kathirvel +--- + drivers/net/wireless/ath/ath12k/qmi.c | 2 +- + drivers/net/wireless/ath/ath12k/wmi.c | 38 +++++++++++++-------------- + 2 files changed, 20 insertions(+), 20 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/qmi.c ++++ b/drivers/net/wireless/ath/ath12k/qmi.c +@@ -3868,7 +3868,7 @@ ath12k_mgmt_rx_reo_extract_mlo_glb_rx_re + cur_link_id = ath12k_mgmt_rx_reo_get_next_valid_link_id(valid_link_bmap, + prev_link_id); + +- WARN_ON(!(cur_link_id >= 0)); ++ BUG_ON(!(cur_link_id >= 0)); + + /* Extract per_link_info */ + len = ath12k_mgmt_rx_reo_extract_mlo_glb_rx_reo_per_link_info_tlv(ab, +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -8378,7 +8378,7 @@ ath12k_wlan_mgmt_rx_reo_update_host_snap + + pkt_ctr_delta = ath12k_mgmt_rx_reo_subtract_pkt_ctrs(reo_params->mgmt_pkt_ctr, + host_ss->mgmt_pkt_ctr); +- WARN_ON(!(pkt_ctr_delta > 0)); ++ BUG_ON(!(pkt_ctr_delta > 0)); + desc->pkt_ctr_delta = pkt_ctr_delta; + + if (pkt_ctr_delta == 1) +@@ -8422,7 +8422,7 @@ failure_debug: + ath12k_err(ab, "Last frame valid = %u, pkt_ctr = %u, ts =%u\n", + host_ss->valid, host_ss->mgmt_pkt_ctr, + host_ss->global_timestamp); +- WARN_ON(1); ++ BUG_ON(1); + + return -EINVAL; + } +@@ -8488,7 +8488,7 @@ ath12k_wmi_mgmt_rx_reo_read_snapshot_raw + prev_snapshot_high = cur_snapshot_high; + } + +- WARN_ON(retry_count == ++ BUG_ON(retry_count == + (ATH12K_MGMT_RX_REO_SNAPSHOT_B2B_READ_SWAR_RETRY_LIMIT - 1)); + + *ath12k_mgmt_rx_reo_snapshot_low = cur_snapshot_low; +@@ -8510,7 +8510,7 @@ ath12k_mlo_shmem_mgmt_rx_reo_snapshot_va + if ((snapshot_ver != ATH12K_MGMT_RX_REO_SNAPSHOT_VERSION_TIMESTAMP_REDUNDANCY) && + (snapshot_ver != ATH12K_MGMT_RX_REO_SNAPSHOT_VERSION_PKT_CTR_REDUNDANCY)) { + ath12k_err(ab, "Check this error snapshot ver %d\n", snapshot_ver); +- WARN_ON(1); ++ BUG_ON(1); + } + + return ATH12K_MLO_SHMEM_GET_BITS(ath12k_mgmt_rx_reo_snapshot_low, 31, 1); +@@ -8531,7 +8531,7 @@ ath12k_mlo_shmem_mgmt_rx_reo_snapshot_gl + ATH12K_MLO_SHMEM_GET_BITS(ath12k_mgmt_rx_reo_snapshot_low, 0, 15)); + } else { + ath12k_err(ab, "Check this error snapshot ver %d\n", snapshot_ver); +- WARN_ON(1); ++ BUG_ON(1); + return 0; + } + } +@@ -8547,7 +8547,7 @@ mlo_shmem_mgmt_rx_reo_snapshot_mgmt_pkt_ + return ATH12K_MLO_SHMEM_GET_BITS(ath12k_mgmt_rx_reo_snapshot_low, 15, 16); + } else { + ath12k_err(ab, "Check this error snapshot ver %d\n", snapshot_ver); +- WARN_ON(1); ++ BUG_ON(1); + return 0; + } + } +@@ -8598,7 +8598,7 @@ ath12k_mlo_shmem_mgmt_rx_reo_snapshot_ch + ATH12K_MLO_SHMEM_GET_BITS(mgmt_pkt_ctr_redundant, 0, 15)); + } else { + ath12k_err(ab, "Check this error snapshot ver %d\n", snapshot_ver); +- WARN_ON(1); ++ BUG_ON(1); + return 0; + } + } +@@ -8622,7 +8622,7 @@ static u16 ath12k_mgmt_rx_reo_snapshot_g + return ATH12K_MLO_SHMEM_GET_BITS(mgmt_rx_reo_snapshot_low, 15, 16); + } else { + ath12k_err(ab, "Check this error snapshot ver %d\n", snapshot_version); +- WARN_ON(1); ++ BUG_ON(1); + return 0; + } + } +@@ -8743,7 +8743,7 @@ ath12k_wmi_mgmt_rx_reo_read_snapshot( + if (retry_count == ATH12K_MGMT_RX_REO_SNAPSHOT_READ_RETRY_LIMIT) { + ath12k_err(ab, "Read retry limit, id = %d, ver = %u\n", + id, snapshot_version); +- WARN_ON(1); ++ BUG_ON(1); + return -EINVAL; + } + +@@ -9328,7 +9328,7 @@ ath12k_wmi_mgmt_rx_reorder_process_calcu + frames_pending = ath12k_mgmt_rx_reo_subtract_pkt_ctrs( + mac_hw_ss->mgmt_pkt_ctr, + host_ss->mgmt_pkt_ctr); +- WARN_ON(!(frames_pending >= 0)); ++ BUG_ON(!(frames_pending >= 0)); + + if (frames_pending && + ath12k_mgmt_rx_reo_compare_global_timestamps_gte +@@ -9342,7 +9342,7 @@ ath12k_wmi_mgmt_rx_reorder_process_calcu + * last frame, so try to wait for all of those frames. + */ + frames_pending--; +- WARN_ON(!(frames_pending >= 0)); ++ BUG_ON(!(frames_pending >= 0)); + + if (fw_consumed_ss->valid && + ath12k_mgmt_rx_reo_compare_global_timestamps_gte( +@@ -9367,7 +9367,7 @@ ath12k_wmi_mgmt_rx_reorder_process_calcu + fw_consumed_ss->mgmt_pkt_ctr, + host_ss->mgmt_pkt_ctr) - 1; + +- WARN_ON(!(frames_pending >= 0)); ++ BUG_ON(!(frames_pending >= 0)); + + /** + * Last frame forwarded to Host has timestamp +@@ -9422,7 +9422,7 @@ ath12k_wmi_mgmt_rx_reorder_process_calcu + fw_forwarded_ss->mgmt_pkt_ctr, + host_ss->mgmt_pkt_ctr) - 1; + +- WARN_ON(!(delta_fwd_host >= 0)); ++ BUG_ON(!(delta_fwd_host >= 0)); + + /** + * This will be a better estimate over the one +@@ -9441,12 +9441,12 @@ ath12k_wmi_mgmt_rx_reorder_process_calcu + */ + frames_pending = min(frames_pending, + delta_fwd_host); +- WARN_ON(!(frames_pending >= 0)); ++ BUG_ON(!(frames_pending >= 0)); + } + } + + update_pending_frames: +- WARN_ON(!(frames_pending >= 0)); ++ BUG_ON(!(frames_pending >= 0)); + + wait_count->per_link_count[hw_link_id] = frames_pending; + wait_count->total_count += frames_pending; +@@ -9732,7 +9732,7 @@ ath12k_mgmt_rx_reo_update_list( + * then the reordering didn't properly happened please check the + * reordering + */ +- WARN_ON(!(!frame_desc->is_stale || cur_entry->is_parallel_rx)); ++ BUG_ON(!(!frame_desc->is_stale || cur_entry->is_parallel_rx)); + + list_insertion_pos++; + +@@ -9953,8 +9953,8 @@ ath12k_mgmt_rx_reo_list_entry_send_up(st + + release_reason = ath12k_mgmt_rx_reo_list_entry_get_release_reason(entry); + +- //TODO remove WARN_ON once the implementation is stablized +- WARN_ON(!release_reason != 0); ++ //TODO remove BUG_ON once the implementation is stablized ++ BUG_ON(!release_reason != 0); + + entry->is_delivered = false; + entry->is_premature_delivery = false; +@@ -10083,7 +10083,7 @@ ath12k_mgmt_rx_reo_list_release_entries( + * the last frame released from the reorder list will be + * discarded at the entry to reorder process itself. + */ +- WARN_ON(!first_entry->is_parallel_rx); ++ BUG_ON(!first_entry->is_parallel_rx); + } + + spin_unlock_bh(&reo_list->list_lock); diff --git a/feeds/ipq95xx/mac80211/patches/qca/749-ath12k-Map-to-cmem_remap-structure-when-parsing-ab-h.patch b/feeds/ipq95xx/mac80211/patches/qca/749-ath12k-Map-to-cmem_remap-structure-when-parsing-ab-h.patch new file mode 100644 index 000000000..24276ebff --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/749-ath12k-Map-to-cmem_remap-structure-when-parsing-ab-h.patch @@ -0,0 +1,105 @@ +From 0b02a6a7accc39c0f617858d4cc9710967bed0ad Mon Sep 17 00:00:00 2001 +From: Balamurugan S +Date: Tue, 14 Mar 2023 22:07:14 +0530 +Subject: [PATCH] ath12k: Map to cmem_remap structure when parsing + ab->hw_params->cmem + +Assign to cmem_remap structure when parsing cmem from hw params for +remapping the cmem memory. Initially this was assigned to ce_remap +since both structures had same variable did not cause any issues. +So, fix this by mapping to the cmem_remap structure. + +Signed-off-by: Balamurugan S +--- + drivers/net/wireless/ath/ath12k/ahb.c | 4 ++-- + drivers/net/wireless/ath/ath12k/ce.h | 5 ----- + drivers/net/wireless/ath/ath12k/core.h | 5 +++++ + drivers/net/wireless/ath/ath12k/hw.c | 4 ++-- + drivers/net/wireless/ath/ath12k/hw.h | 2 +- + 5 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/ahb.c b/drivers/net/wireless/ath/ath12k/ahb.c +index 13d5ce8..fbc998a 100644 +--- a/drivers/net/wireless/ath/ath12k/ahb.c ++++ b/drivers/net/wireless/ath/ath12k/ahb.c +@@ -967,8 +967,8 @@ static int ath12k_ahb_probe(struct platform_device *pdev) + ab->ce_remap = true; + ab->ce_remap_base_addr = HAL_IPQ5332_CE_WFSS_REG_BASE; + } +- if (ab->hw_params->cmem) { +- const struct ce_remap *cmem = ab->hw_params->cmem; ++ if (ab->hw_params->cmem_remap) { ++ const struct cmem_remap *cmem = ab->hw_params->cmem_remap; + /* + * In IPQ5332 CMEM region is outside WCSS block. + * Allocate separate I/O remap to access CMEM address. +diff --git a/drivers/net/wireless/ath/ath12k/ce.h b/drivers/net/wireless/ath/ath12k/ce.h +index e951736..f709167 100644 +--- a/drivers/net/wireless/ath/ath12k/ce.h ++++ b/drivers/net/wireless/ath/ath12k/ce.h +@@ -93,11 +93,6 @@ struct ce_remap { + u32 size; + }; + +-struct ath12k_cmem { +- u32 base; +- u32 size; +-}; +- + struct ce_attr { + /* CE_ATTR_* values */ + unsigned int flags; +diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h +index 997ed75..27e61b3 100644 +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -999,6 +999,11 @@ struct ath12k_pdev { + struct mlo_timestamp timestamp; + }; + ++struct cmem_remap { ++ u32 base; ++ u32 size; ++}; ++ + #define BOARD_NAME_SIZE 100 + #define REGDB_NAME_SIZE 100 + +diff --git a/drivers/net/wireless/ath/ath12k/hw.c b/drivers/net/wireless/ath/ath12k/hw.c +index 117ce58..8665d55 100644 +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -1382,7 +1382,7 @@ const struct ce_remap ath12k_ce_remap_ipq5332 = { + .size = HAL_IPQ5332_CE_SIZE, + }; + +-const struct ath12k_cmem ath12k_cmem_ipq5332 = { ++const struct cmem_remap ath12k_cmem_ipq5332 = { + .base = HAL_IPQ5332_CMEM_REG_BASE, + .size = HAL_IPQ5332_CMEM_SIZE, + }; +@@ -1687,7 +1687,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { + .compact_rx_tlv = true, + .ce_ie_addr = &ath12k_ce_ie_addr_ipq5332, + .ce_remap = &ath12k_ce_remap_ipq5332, +- .cmem = &ath12k_cmem_ipq5332, ++ .cmem_remap = &ath12k_cmem_ipq5332, + .send_platform_model = true, + .en_fwlog = false, + }, +diff --git a/drivers/net/wireless/ath/ath12k/hw.h b/drivers/net/wireless/ath/ath12k/hw.h +index 279184e..3e9a577 100644 +--- a/drivers/net/wireless/ath/ath12k/hw.h ++++ b/drivers/net/wireless/ath/ath12k/hw.h +@@ -221,7 +221,7 @@ struct ath12k_hw_params { + bool send_platform_model; + bool en_fwlog; + const struct ce_remap *ce_remap; +- const struct cmem *cmem; ++ const struct cmem_remap *cmem_remap; + bool compact_rx_tlv; + }; + +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/749-ath12k-Modify-request_firmware_nowarn-to-request_fir.patch b/feeds/ipq95xx/mac80211/patches/qca/749-ath12k-Modify-request_firmware_nowarn-to-request_fir.patch new file mode 100644 index 000000000..143e7fdfe --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/749-ath12k-Modify-request_firmware_nowarn-to-request_fir.patch @@ -0,0 +1,33 @@ +From adfb19c24e39a006048000672c61b573a8559d5a Mon Sep 17 00:00:00 2001 +From: Dinesh Karthikeyan +Date: Tue, 14 Mar 2023 11:20:07 +0530 +Subject: [PATCH] ath12k: Modify request_firmware_nowarn to + request_firmware_direct + +The request_firmware_nowarn searches for the requested file in the +/lib/firmware path and performs additional fall back check to sysfs +to check for the firmware. This takes additional bootup time with +IPQ5332 yocto since the calibration file is not present. +Use request_firmware_direct to reduce the delay in boot. + +Signed-off-by: Dinesh Karthikeyan +--- + drivers/net/wireless/ath/ath12k/core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c +index 9dc848f..a61ebe7 100644 +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -442,7 +442,7 @@ const struct firmware *ath12k_core_firmware_request(struct ath12k_base *ab, + + ath12k_core_create_firmware_path(ab, file, path, sizeof(path)); + +- ret = firmware_request_nowarn(&fw, path, ab->dev); ++ ret = request_firmware_direct(&fw, path, ab->dev); + if (ret) + return ERR_PTR(ret); + +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/749-ath12k-add-support-avg-signal-in-station-dump.patch b/feeds/ipq95xx/mac80211/patches/qca/749-ath12k-add-support-avg-signal-in-station-dump.patch new file mode 100644 index 000000000..7476f9b31 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/749-ath12k-add-support-avg-signal-in-station-dump.patch @@ -0,0 +1,165 @@ +From 869495108cdcfba908a123cadb6b9976b1b78064 Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Wed, 15 Mar 2023 13:13:11 +0530 +Subject: [PATCH] ath12k: add support avg signal in station dump + +Currently, avg signal attribute "NL80211_STA_INFO_SIGNAL_AVG" +is not filling when RSS(Receive side scaling) is enabled from +the driver, so average signal isn't printed in the station dump. + +Fix this issue, by calculating the average signal from RSSI and +appropriate bandwidth offset within driver and display in the +station dump. + +Tag: FIX_ATH11K_TO_ATH12K + +Signed-off-by: Thiraviyam Mariyappan +Signed-off-by: Sowmiya Sree Elavalagan +Signed-off-by: Aaradhana Sahu +--- + drivers/net/wireless/ath/ath12k/core.h | 6 ++++++ + drivers/net/wireless/ath/ath12k/dp_mon.c | 4 ++++ + drivers/net/wireless/ath/ath12k/mac.c | 12 ++++++++++++ + drivers/net/wireless/ath/ath12k/wmi.c | 9 +++++++-- + 4 files changed, 29 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + #include "qmi.h" + #include "htc.h" + #include "wmi.h" +@@ -563,6 +564,8 @@ struct ath12k_per_ppdu_tx_stats { + u32 retry_bytes; + }; + ++DECLARE_EWMA(avg_rssi, 10, 8) ++ + struct ath12k_wbm_tx_stats { + u64 wbm_tx_comp_stats[HAL_WBM_REL_HTT_TX_COMP_STATUS_MAX]; + }; +@@ -597,6 +600,7 @@ struct ath12k_link_sta { + u64 rx_duration; + u64 tx_duration; + u8 rssi_comb; ++ struct ewma_avg_rssi avg_rssi; + + struct ath12k_htt_tx_stats *tx_stats; + struct ath12k_rx_peer_stats *rx_stats; +@@ -608,6 +612,7 @@ struct ath12k_link_sta { + u32 bw_prev; + u8 link_id; /* IEEE link id */ + u8 link_idx; /* for fw use only */ ++ u32 last_tx_pkt_bw; + + /* For now the assoc link will be considered primary */ + bool is_assoc_link; +@@ -833,6 +838,7 @@ struct ath12k { + u32 txpower_scale; + u32 power_scale; + u32 chan_tx_pwr; ++ s32 chan_noise_floor; + u32 num_stations; + u32 max_num_stations; + bool monitor_present; +--- a/drivers/net/wireless/ath/ath12k/dp_mon.c ++++ b/drivers/net/wireless/ath/ath12k/dp_mon.c +@@ -3328,11 +3328,15 @@ static void ath12k_dp_mon_rx_update_peer + { + struct ath12k_rx_peer_stats *rx_stats = arsta->rx_stats; + u32 num_msdu; ++ u32 bw_offset; + + if (!rx_stats) + return; + ++ arsta->last_tx_pkt_bw = ppdu_info->bw; ++ bw_offset = arsta->last_tx_pkt_bw * 3; + arsta->rssi_comb = ppdu_info->rssi_comb; ++ ewma_avg_rssi_add(&arsta->avg_rssi, ppdu_info->rssi_comb + bw_offset); + + if (!ath12k_debugfs_is_extd_rx_stats_enabled(ar)) + return; +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -6630,6 +6630,7 @@ static int ath12k_mac_station_add(struct + INIT_WORK(&arsta->update_wk, ath12k_sta_rc_update_wk); + + ahsta->ahvif = ahvif; ++ ewma_avg_rssi_init(&arsta->avg_rssi); + return 0; + + free_tx_stats: +@@ -13429,6 +13430,7 @@ static void ath12k_mac_op_sta_statistics + { + struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; + struct ath12k_link_sta *arsta = &ahsta->deflink; ++ struct ath12k *ar = arsta->arvif->ar; + + /* TODO accumulate link sta stats here? */ + +@@ -13457,6 +13459,16 @@ static void ath12k_mac_op_sta_statistics + /* TODO: Use real NF instead of default one. */ + sinfo->signal = arsta->rssi_comb + ATH12K_DEFAULT_NOISE_FLOOR; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL); ++ ++ if (ar->chan_noise_floor) { ++ sinfo->signal_avg = ewma_avg_rssi_read(&arsta->avg_rssi) + ++ ar->chan_noise_floor; ++ } else { ++ sinfo->signal_avg = ewma_avg_rssi_read(&arsta->avg_rssi) + ++ ATH12K_DEFAULT_NOISE_FLOOR; ++ } ++ ++ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG); + } + + int ath12k_mac_btcoex_config(struct ath12k *ar, struct ath12k_link_vif *arvif, +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -7323,9 +7323,11 @@ static int ath12k_pull_peer_assoc_conf_e + } + + static void ath12k_wmi_pull_pdev_stats_base(const struct wmi_pdev_stats_base *src, +- struct ath12k_fw_stats_pdev *dst) ++ struct ath12k_fw_stats_pdev *dst, ++ struct ath12k *ar) + { + dst->ch_noise_floor = src->chan_nf; ++ ar->chan_noise_floor = src->chan_nf; + dst->tx_frame_count = src->tx_frame_count; + dst->rx_frame_count = src->rx_frame_count; + dst->rx_clear_count = src->rx_clear_count; +@@ -7430,6 +7432,7 @@ int ath12k_wmi_pull_fw_stats(struct ath1 + const struct wmi_stats_event *ev; + const void *data; + int i, ret; ++ struct ath12k *ar; + u32 len = skb->len; + + tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, len, GFP_ATOMIC); +@@ -7456,6 +7459,11 @@ int ath12k_wmi_pull_fw_stats(struct ath1 + stats->pdev_id = ev->pdev_id; + stats->stats_id = 0; + ++ ar = ath12k_mac_get_ar_by_pdev_id(ab, ev->pdev_id); ++ ++ if (!ar) ++ return -EPROTO; ++ + for (i = 0; i < ev->num_pdev_stats; i++) { + const struct wmi_pdev_stats *src; + struct ath12k_fw_stats_pdev *dst; +@@ -7475,7 +7483,7 @@ int ath12k_wmi_pull_fw_stats(struct ath1 + if (!dst) + continue; + +- ath12k_wmi_pull_pdev_stats_base(&src->base, dst); ++ ath12k_wmi_pull_pdev_stats_base(&src->base, dst, ar); + ath12k_wmi_pull_pdev_stats_tx(&src->tx, dst); + ath12k_wmi_pull_pdev_stats_rx(&src->rx, dst); + list_add_tail(&dst->list, &stats->pdevs); diff --git a/feeds/ipq95xx/mac80211/patches/qca/749-wifi-ath12k-refactor-peer-delete.patch b/feeds/ipq95xx/mac80211/patches/qca/749-wifi-ath12k-refactor-peer-delete.patch new file mode 100644 index 000000000..95f9a9e62 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/749-wifi-ath12k-refactor-peer-delete.patch @@ -0,0 +1,108 @@ +From bdc43856d6fc81d3c9140eab8c6fcd19f1314d5a Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Tue, 7 Mar 2023 14:55:26 +0530 +Subject: [PATCH] wifi: ath12k: Refactor peer delete + +In mac vdev create, the error handler call the wmi peer delete procedure +which already take care in separate peer delete call. So refactor the +error path to call the peer delete instead of WMI peer delete call. + +Also refactor the peer delete to handle the error path in peer create. + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/mac.c | 20 +++++--------------- + 1 file changed, 5 insertions(+), 15 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -9304,7 +9304,7 @@ static int ath12k_mac_vdev_create(struct + u32 param_id, param_value; + u16 nss; + int i; +- int ret, vdev_id; ++ int ret, fbret, vdev_id; + u8 link_addr[ETH_ALEN]; + int txpower; + u8 link_id; +@@ -9514,22 +9514,12 @@ static int ath12k_mac_vdev_create(struct + + err_peer_del: + if (ahvif->vdev_type == WMI_VDEV_TYPE_AP) { +- reinit_completion(&ar->peer_delete_done); +- +- ret = ath12k_wmi_send_peer_delete_cmd(ar, link_addr, +- arvif->vdev_id); +- if (ret) { +- ath12k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n", +- arvif->vdev_id, link_addr); ++ fbret = ath12k_peer_delete(ar, arvif->vdev_id, link_addr); ++ if (fbret) { ++ ath12k_warn(ar->ab, "failed to delete peer %pM vdev_id %d ret %d\n", ++ link_addr, arvif->vdev_id, fbret); + goto err; + } +- +- ret = ath12k_wait_for_peer_delete_done(ar, arvif->vdev_id, +- link_addr); +- if (ret) +- goto err; +- +- ar->num_peers--; + } + + err_vdev_del: +--- a/drivers/net/wireless/ath/ath12k/peer.c ++++ b/drivers/net/wireless/ath/ath12k/peer.c +@@ -327,7 +327,7 @@ static int ath12k_peer_delete_send(struc + return 0; + } + +-int ath12k_peer_delete(struct ath12k *ar, u32 vdev_id, u8 *addr) ++static int __ath12k_peer_delete(struct ath12k *ar, u32 vdev_id, u8 *addr) + { + int ret; + +@@ -341,6 +341,19 @@ int ath12k_peer_delete(struct ath12k *ar + if (ret) + return ret; + ++ return 0; ++} ++ ++int ath12k_peer_delete(struct ath12k *ar, u32 vdev_id, u8 *addr) ++{ ++ int ret; ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ ret = __ath12k_peer_delete(ar, vdev_id, addr); ++ if (ret) ++ return ret; ++ + ar->num_peers--; + + return 0; +@@ -469,20 +482,10 @@ int ath12k_peer_create(struct ath12k *ar + ath12k_warn(ar->ab, "failed to find peer %pM on vdev %i after creation\n", + param->peer_addr, param->vdev_id); + +- reinit_completion(&ar->peer_delete_done); +- +- ret = ath12k_wmi_send_peer_delete_cmd(ar, param->peer_addr, +- param->vdev_id); +- if (ret) { ++ ret = __ath12k_peer_delete(ar, param->vdev_id, param->peer_addr); ++ if (ret) + ath12k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n", + param->vdev_id, param->peer_addr); +- return ret; +- } +- +- ret = ath12k_wait_for_peer_delete_done(ar, param->vdev_id, +- param->peer_addr); +- if (ret) +- return ret; + + return -ENOENT; + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/750-01-ath12k-Add-SAWF-support.patch b/feeds/ipq95xx/mac80211/patches/qca/750-01-ath12k-Add-SAWF-support.patch new file mode 100644 index 000000000..4acf7c7f6 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/750-01-ath12k-Add-SAWF-support.patch @@ -0,0 +1,558 @@ +From 51176d1d0dcbf244b331a3e104811f66f292dcde Mon Sep 17 00:00:00 2001 +From: Nagarajan Maran +Date: Mon, 7 Nov 2022 16:11:54 +0530 +Subject: [PATCH] ath12k: Add SAWF support + +SAWF - Service Aware WiFi Framework +Adding SAW support. + +Add support to initialize and maintain service classes +sent from userspace. These service classes are stored +in a global context since same service classes should +be maintained across all the WiFi socs. + +Module param "sawf" will be used to enable this feature +from driver side. By default SAWF will be disabled. +Add support to enable and disable SAW in firmware during +bootup using target resource configs. + +Signed-off-by: Nagarajan Maran +--- + drivers/net/wireless/ath/ath12k/Makefile | 3 +- + drivers/net/wireless/ath/ath12k/sawf.c | 214 +++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/sawf.h | 140 +++++++++++++++ + 3 files changed, 356 insertions(+), 1 deletion(-) + create mode 100644 drivers/net/wireless/ath/ath12k/sawf.c + create mode 100644 drivers/net/wireless/ath/ath12k/sawf.h + +--- a/drivers/net/wireless/ath/ath12k/Makefile ++++ b/drivers/net/wireless/ath/ath12k/Makefile +@@ -20,7 +20,8 @@ ath12k-y += core.o \ + wow.o \ + mhi.o \ + pci.o \ +- dp_mon.o ++ dp_mon.o \ ++ sawf.o + + ath12k-$(CPTCFG_ATH12K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o + ath12k-$(CPTCFG_NL80211_TESTMODE) += testmode.o +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/sawf.c +@@ -0,0 +1,244 @@ ++// SPDX-License-Identifier: BSD-3-Clause-Clear ++/* ++ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include "core.h" ++#include "debug.h" ++#include "wmi.h" ++#include "sawf.h" ++#include ++ ++#define SVC_INDEX(svc_id) svc_id - 1 ++ ++bool ath12k_sawf_enable; ++module_param_named(sawf, ath12k_sawf_enable, bool, 0444); ++MODULE_PARM_DESC(sawf, "Enable SAWF feature (Default: false)"); ++ ++static struct ath12k_sawf_ctx *sawf_ctx; ++ ++void ath12k_sawf_init(struct ath12k_base *ab) ++{ ++ if (!ath12k_sawf_enable) ++ return; ++ ++ if (!test_bit(WMI_TLV_SERVICE_SAWF_LEVEL0, ab->wmi_ab.svc_map)) ++ return; ++ ++ if (!sawf_ctx) { ++ sawf_ctx = kzalloc(sizeof(*sawf_ctx), GFP_KERNEL); ++ if (!sawf_ctx) { ++ ath12k_err(NULL, "SAWF context failed to initialize\n"); ++ return; ++ } ++ sawf_ctx->max_msduq_per_tid = ab->max_msduq_per_tid; ++ sawf_ctx->default_msduq_per_tid = ab->default_msduq_per_tid; ++ spin_lock_init(&sawf_ctx->sawf_svc_lock); ++ } else {/* Already initialized */ ++ return; ++ } ++ ++ ath12k_info(NULL, "SAWF context initialized\n"); ++} ++ ++void ath12k_sawf_deinit(struct ath12k_base *ab) ++{ ++ if (!ath12k_sawf_enable) ++ return; ++ ++ /* During firmware crash recovery scenario, the SAWF context ++ * will be retained. ++ */ ++ if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags)) ++ return; ++ ++ if (!sawf_ctx) ++ return; ++ ++ kfree(sawf_ctx); ++ sawf_ctx = NULL; ++ ath12k_info(NULL, "SAWF context freed\n"); ++ return; ++} ++ ++struct ath12k_sawf_ctx *ath12k_get_sawf_context(void) ++{ ++ if (!sawf_ctx) { ++ ath12k_err(NULL, "SAWF context not initialized\n"); ++ return NULL; ++ } ++ ++ return sawf_ctx; ++} ++ ++void ath12k_update_svc_class(struct ath12k_sawf_svc_params *sawf_params) ++{ ++ struct ath12k_sawf_svc_params *new_param; ++ ++ if (!sawf_ctx) { ++ ath12k_err(NULL, "SAWF context unavailable\n"); ++ return; ++ } ++ ++ spin_lock_bh(&sawf_ctx->sawf_svc_lock); ++ new_param = &sawf_ctx->svc_classes[SVC_INDEX(sawf_params->svc_id)]; ++ new_param->svc_id = sawf_params->svc_id; ++ memcpy(new_param->app_name, sawf_params->app_name, ATH12K_MAX_APP_NAME); ++ new_param->min_throughput_rate = sawf_params->min_throughput_rate; ++ new_param->max_throughput_rate = sawf_params->max_throughput_rate; ++ new_param->burst_size = sawf_params->burst_size; ++ new_param->service_interval = sawf_params->service_interval; ++ new_param->delay_bound = sawf_params->delay_bound; ++ new_param->msdu_ttl = sawf_params->msdu_ttl; ++ new_param->priority = sawf_params->priority; ++ new_param->tid = sawf_params->tid; ++ new_param->msdu_rate_loss = sawf_params->msdu_rate_loss; ++ new_param->configured = sawf_params->configured; ++ spin_unlock_bh(&sawf_ctx->sawf_svc_lock); ++} ++ ++bool ath12k_validate_sawf_param(struct ath12k_sawf_svc_params *params) ++{ ++ u32 value; ++ ++ value = params->min_throughput_rate; ++ if (value != SAWF_SVC_PARAM_DEFAULT_MIN_THRUPUT && ++ (value < ATH12K_SAWF_MIN_MIN_THROUGHPUT || ++ value > ATH12K_SAWF_MAX_MIN_THROUGHPUT)) { ++ ath12k_err(NULL, "Invalid Min throughput: %d\n", value); ++ return false; ++ } ++ ++ value = params->max_throughput_rate; ++ if (value != SAWF_SVC_PARAM_DEFAULT_MAX_THRUPUT && ++ (value < ATH12K_SAWF_MIN_MAX_THROUGHPUT || ++ value > ATH12K_SAWF_MAX_MAX_THROUGHPUT)) { ++ ath12k_err(NULL, "Invalid Max througput: %d", value); ++ return false; ++ } ++ ++ value = params->burst_size; ++ if (value != SAWF_SVC_PARAM_DEFAULT_BURST_SIZE && ++ (value < ATH12K_SAWF_MIN_BURST_SIZE || ++ value > ATH12K_SAWF_MAX_BURST_SIZE)) { ++ ath12k_err(NULL, "Invalid Burst Size: %d", value); ++ return false; ++ } ++ ++ value = params->delay_bound; ++ if (value != SAWF_SVC_PARAM_DEFAULT_DELAY_BOUND && ++ (value < ATH12K_SAWF_MIN_DELAY_BOUND || ++ value > ATH12K_SAWF_MAX_DELAY_BOUND)) { ++ ath12k_err(NULL, "Invalid Delay Bound: %d", value); ++ return false; ++ } ++ ++ value = params->service_interval; ++ if (value != SAWF_SVC_PARAM_DEFAULT_SVC_INTERVAL && ++ (value < ATH12K_SAWF_MIN_SVC_INTERVAL || ++ value > ATH12K_SAWF_MAX_SVC_INTERVAL)) { ++ ath12k_err(NULL, "Invalid Service Interval: %d", value); ++ return false; ++ } ++ ++ value = params->msdu_ttl; ++ if (value != SAWF_SVC_PARAM_DEFAULT_TIME_TO_LIVE && ++ (value < ATH12K_SAWF_MIN_MSDU_TTL || ++ value > ATH12K_SAWF_MAX_MSDU_TTL)) { ++ ath12k_err(NULL, "Invalid MSDU TTL: %d", value); ++ return false; ++ } ++ ++ value = params->priority; ++ if (value != SAWF_SVC_PARAM_DEFAULT_PRIORITY && ++ (value < ATH12K_SAWF_MIN_PRIORITY || ++ value > ATH12K_SAWF_MAX_PRIORITY)) { ++ ath12k_err(NULL, "Invalid Priority: %d", value); ++ return false; ++ } ++ ++ value = params->tid; ++ if (value != SAWF_SVC_PARAM_DEFAULT_TID && ++ (value < ATH12K_SAWF_MIN_TID || ++ value > ATH12K_SAWF_MAX_TID)) { ++ ath12k_err(NULL, "Invalid TID: %d", value); ++ return false; ++ } ++ ++ value = params->msdu_rate_loss; ++ if (value != SAWF_SVC_PARAM_DEFAULT_MSDU_LOSS_RATE && ++ (value < ATH12K_SAWF_MIN_MSDU_LOSS_RATE || ++ value > ATH12K_SAWF_MAX_MSDU_LOSS_RATE)) { ++ ath12k_err(NULL, "Invalid MSDU Loss rate: %d", value); ++ return false; ++ } ++ ++ return true; ++} ++ ++bool ath12k_svc_id_configured(u8 svc_id) ++{ ++ if (!sawf_ctx) { ++ ath12k_err(NULL, "SAWF context unavailable\n"); ++ return false; ++ } ++ ++ spin_lock_bh(&sawf_ctx->sawf_svc_lock); ++ if (sawf_ctx->svc_classes[SVC_INDEX(svc_id)].configured) { ++ spin_unlock_bh(&sawf_ctx->sawf_svc_lock); ++ return true; ++ } ++ ++ spin_unlock_bh(&sawf_ctx->sawf_svc_lock); ++ return false; ++} ++ ++int ath12k_get_tid(u8 svc_id) ++{ ++ u32 tid; ++ ++ if (!sawf_ctx) { ++ ath12k_err(NULL, "SAWF context unavailable\n"); ++ return -ENODATA; ++ } ++ ++ if (ath12k_svc_id_configured(svc_id)) { ++ spin_lock_bh(&sawf_ctx->sawf_svc_lock); ++ tid = sawf_ctx->svc_classes[SVC_INDEX(svc_id)].tid; ++ spin_unlock_bh(&sawf_ctx->sawf_svc_lock); ++ return tid; ++ } ++ ++ return -EINVAL; ++} ++ ++bool ath12k_svc_id_valid(u8 svc_id) ++{ ++ if (svc_id < ATH12K_SAWF_SVC_CLASS_MIN || ++ svc_id > ATH12K_SAWF_SVC_CLASS_MAX) ++ return false; ++ else ++ return true; ++} ++ ++bool ath12k_disable_svc_class(u8 svc_id) ++{ ++ struct ath12k_sawf_svc_params *sawf_svc_class; ++ ++ if (!sawf_ctx) { ++ ath12k_err(NULL, "SAWF context unavailable\n"); ++ return false; ++ } ++ ++ if (!ath12k_svc_id_configured(svc_id)) { ++ ath12k_warn(NULL, "Serive id not available\n"); ++ return false; ++ } ++ ++ spin_lock_bh(&sawf_ctx->sawf_svc_lock); ++ sawf_svc_class = &sawf_ctx->svc_classes[SVC_INDEX(svc_id)]; ++ memset(sawf_svc_class, 0, sizeof(*sawf_svc_class)); ++ spin_unlock_bh(&sawf_ctx->sawf_svc_lock); ++ ++ return true; ++} +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/sawf.h +@@ -0,0 +1,138 @@ ++// SPDX-License-Identifier: BSD-3-Clause-Clear ++/* ++ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef ATH12K_SAWF_H ++#define ATH12K_SAWF_H ++ ++#define ATH12K_SAWF_SVC_CLASS_MIN 1 ++#define ATH12K_SAWF_SVC_CLASS_MAX 128 ++#define ATH12K_MAX_APP_NAME 64 ++ ++/* ++ * Min throughput limit 0 - 10 Gb/s ++ * Granularity: 1 Kb/s ++ */ ++#define ATH12K_SAWF_MIN_MIN_THROUGHPUT 0 ++#define ATH12K_SAWF_MAX_MIN_THROUGHPUT (10 * 1024 * 1024) ++ ++/* ++ * Max throughput limit 0 - 10 Gb/s. ++ * Granularity: 1 Kb/s ++ */ ++#define ATH12K_SAWF_MIN_MAX_THROUGHPUT 0 ++#define ATH12K_SAWF_MAX_MAX_THROUGHPUT (10 * 1024 * 1024) ++ ++/* ++ * Service interval limit 0 - 10 secs. ++ * Granularity: 100 µs ++ */ ++#define ATH12K_SAWF_MIN_SVC_INTERVAL 0 ++#define ATH12K_SAWF_MAX_SVC_INTERVAL (10 * 100 * 100) ++ ++/* ++ * Burst size 0 - 16 MB. ++ * Granularity: 1 Byte. ++ */ ++#define ATH12K_SAWF_MIN_BURST_SIZE 0 ++#define ATH12K_SAWF_MAX_BURST_SIZE (16 * 1024 * 1024) ++/* ++ * Delay bound limit 0 - 10 secs ++ * Granularity: 100 µs ++ */ ++#define ATH12K_SAWF_MIN_DELAY_BOUND 0 ++#define ATH12K_SAWF_MAX_DELAY_BOUND (10 * 100 * 100) ++ ++/* ++ * Msdu TTL limit 0 - 10 secs. ++ * Granularity: 100 µs ++ */ ++#define ATH12K_SAWF_MIN_MSDU_TTL 0 ++#define ATH12K_SAWF_MAX_MSDU_TTL (10 * 100 * 100) ++ ++/* ++ * Priority limit 0 - 127. ++ * Higher the numerical value, higher is the priority. ++ */ ++#define ATH12K_SAWF_MIN_PRIORITY 0 ++#define ATH12K_SAWF_MAX_PRIORITY 127 ++ ++/* ++ * TID limit 0 - 7 ++ */ ++#define ATH12K_SAWF_MIN_TID 0 ++#define ATH12K_SAWF_MAX_TID 7 ++/* ++ * MSDU Loss Rate limit 0 - 100%. ++ * Granularity: 0.01% ++ */ ++#define ATH12K_SAWF_MIN_MSDU_LOSS_RATE 0 ++#define ATH12K_SAWF_MAX_MSDU_LOSS_RATE 10000 ++ ++enum SAWF_SVC_PARAM_DEFAULTS { ++ SAWF_SVC_PARAM_DEFAULT_MIN_THRUPUT = 0, ++ SAWF_SVC_PARAM_DEFAULT_MAX_THRUPUT = 0xffffffff, ++ SAWF_SVC_PARAM_DEFAULT_BURST_SIZE = 0, ++ SAWF_SVC_PARAM_DEFAULT_SVC_INTERVAL = 0xffffffff, ++ SAWF_SVC_PARAM_DEFAULT_DELAY_BOUND = 0xffffffff, ++ SAWF_SVC_PARAM_DEFAULT_TIME_TO_LIVE = 0xffffffff, ++ SAWF_SVC_PARAM_DEFAULT_PRIORITY = 0, ++ SAWF_SVC_PARAM_DEFAULT_TID = 0xffffffff, ++ SAWF_SVC_PARAM_DEFAULT_MSDU_LOSS_RATE = 0, ++}; ++ ++/** ++ * struct ath12k_sawf_svc_params - Service Class Parameters ++ * @svc_id: Service ID ++ * @app_name: Service class name ++ * @min_throughput_rate: min throughput in kilobits per second ++ * @max_throughput_rate: max throughput in kilobits per second ++ * @burst_size: burst size in bytes ++ * @service_interval: service interval ++ * @delay_bound: delay bound in milli seconds ++ * @msdu_ttl: MSDU Time-To-Live ++ * @priority: Priority ++ * @tid: TID ++ * @msdu_rate_loss: MSDU loss rate in parts per million ++ * @configured: indicating if the serivice class is configured. ++ */ ++ ++struct ath12k_sawf_svc_params { ++ u8 svc_id; ++ char app_name[ATH12K_MAX_APP_NAME]; ++ u32 min_throughput_rate; ++ u32 max_throughput_rate; ++ u32 burst_size; ++ u32 service_interval; ++ u32 delay_bound; ++ u32 msdu_ttl; ++ u32 priority; ++ u32 tid; ++ u32 msdu_rate_loss; ++ bool configured; ++}; ++ ++/** ++ * struct ath12k_sawf_ctx- SAWF context ++ * @svc_classes: List of all service classes ++ */ ++struct ath12k_sawf_ctx { ++ struct ath12k_sawf_svc_params svc_classes[ATH12K_SAWF_SVC_CLASS_MAX]; ++ u32 max_msduq_per_tid; ++ u32 default_msduq_per_tid; ++ spinlock_t sawf_svc_lock; ++}; ++ ++extern bool ath12k_sawf_enable; ++struct ath12k_sawf_ctx *ath12k_get_sawf_context(void); ++void ath12k_sawf_init(struct ath12k_base *ab); ++void ath12k_sawf_deinit(struct ath12k_base *ab); ++bool ath12k_validate_sawf_param(struct ath12k_sawf_svc_params *params); ++bool ath12k_svc_id_configured(u8 svc_id); ++bool ath12k_svc_id_valid(u8 svc_id); ++void ath12k_update_svc_class(struct ath12k_sawf_svc_params *sawf_params); ++bool ath12k_disable_svc_class(u8 svc_id); ++int ath12k_get_tid(u8 svc_id); ++ ++#endif /* ATH11K_SAWF_H */ +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -1077,6 +1077,8 @@ static int ath12k_core_pdev_init(struct + goto err_spectral_deinit; + } + ++ ath12k_sawf_init(ab); ++ + return 0; + + err_spectral_deinit: +@@ -1090,6 +1092,7 @@ static void ath12k_core_pdev_deinit(stru + { + ath12k_spectral_deinit(ab); + ath12k_thermal_unregister(ab); ++ ath12k_sawf_deinit(ab); + } + + static int ath12k_core_pdev_create(struct ath12k_base *ab) +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -26,6 +26,7 @@ + #include "dbring.h" + #include "spectral.h" + #include "pktlog.h" ++#include "sawf.h" + + #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK) + +@@ -1308,6 +1309,8 @@ struct ath12k_base { + u32 rx_hash_ix3; + + struct vendor_info id; ++ u32 max_msduq_per_tid; ++ u32 default_msduq_per_tid; + + int userpd_id; + +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -247,6 +247,8 @@ void ath12k_wmi_init_qcn9274(struct ath1 + config->ema_max_profile_period = TARGET_EMA_MAX_PROFILE_PERIOD; + config->beacon_tx_offload_max_vdev += config->ema_max_vap_cnt; + ++ if (test_bit(WMI_TLV_SERVICE_SAWF_LEVEL0, ab->wmi_ab.svc_map)) ++ config->sawf = true; + if (test_bit(WMI_TLV_SERVICE_PEER_METADATA_V1A_V1B_SUPPORT, ab->wmi_ab.svc_map)) + config->dp_peer_meta_data_ver = TARGET_RX_PEER_METADATA_VER_V1B; + +@@ -314,6 +316,8 @@ void ath12k_wmi_init_ipq5332(struct ath1 + if (test_bit(WMI_TLV_SERVICE_PEER_METADATA_V1A_V1B_SUPPORT, ab->wmi_ab.svc_map)) + config->dp_peer_meta_data_ver = TARGET_RX_PEER_METADATA_VER_V1B; + ++ if (test_bit(WMI_TLV_SERVICE_SAWF_LEVEL0, ab->wmi_ab.svc_map)) ++ config->sawf = true; + } + + +@@ -4876,6 +4880,8 @@ ath12k_wmi_copy_resource_config(struct w + WMI_RSRC_CFG_FLAGS2_INTRABSS_MEC_WDS_LEARNING_DISABLE | + u32_encode_bits(tg_cfg->dp_peer_meta_data_ver, + WMI_RSRC_CFG_FLAGS2_RX_PEER_METADATA_VERSION); ++ wmi_cfg->flags2 |= (tg_cfg->sawf & ath12k_sawf_enable) ? ++ (WMI_RSRC_CFG_FLAGS2_SAWF_CONFIG_ENABLE_SET) : (0); + wmi_cfg->host_service_flags &= ~(1 << WMI_RSRC_CFG_HOST_SVC_FLAG_REG_CC_EXT_SUPPORT_BIT); + wmi_cfg->host_service_flags |= 1 << WMI_RSRC_CFG_HOST_SVC_FLAG_REG_CC_EXT_SUPPORT_BIT; + wmi_cfg->host_service_flags |= 1 << WMI_RSRC_CFG_HOST_SVC_FLAG_REO_QREF_SUPPORT_BIT; +@@ -5866,6 +5872,8 @@ static int ath12k_pull_svc_ready_ext2(st + param->max_user_per_ppdu_ofdma = ev->max_user_per_ppdu_ofdma; + param->max_user_per_ppdu_mumimo = ev->max_user_per_ppdu_mumimo; + param->target_cap_flags = ev->target_cap_flags; ++ param->max_msduq_per_tid = ev->max_num_msduq_supported_per_tid; ++ param->default_msduq_per_tid = ev->default_num_msduq_supported_per_tid; + return 0; + } + +@@ -5974,6 +5982,8 @@ static int ath12k_wmi_tlv_svc_rdy_ext2_p + ath12k_warn(ab, "unable to extract ext params\n"); + return ret; + } ++ ab->max_msduq_per_tid = parse->param.max_msduq_per_tid; ++ ab->default_msduq_per_tid = parse->param.default_msduq_per_tid; + break; + + case WMI_TAG_ARRAY_STRUCT: +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -2267,6 +2267,7 @@ enum wmi_tlv_service { + WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281, + WMI_TLV_SERVICE_DCS_AWGN_INT_SUPPORT = 286, + WMI_TLV_SERVICE_BE = 289, ++ WMI_TLV_SERVICE_SAWF_LEVEL0 = 311, + WMI_TLV_SERVICE_PKTLOG_DECODE_INFO_SUPPORT = 320, + WMI_TLV_SERVICE_PEER_METADATA_V1A_V1B_SUPPORT = 365, + WMI_MAX_EXT2_SERVICE, +@@ -2518,7 +2519,8 @@ struct ath12k_service_ext2_param { + u32 target_cap_flags; + u32 eht_cap_mac_info[WMI_MAX_EHTCAP_MAC_SIZE]; + u32 max_num_linkview_peers; +- u32 max_num_msduq_supported_per_tid; ++ u32 max_msduq_per_tid; ++ u32 default_msduq_per_tid; + }; + + #define WMI_HOST_MAX_PDEV 3 +@@ -2593,6 +2595,7 @@ struct wmi_init_cmd { + #define WMI_RSRC_CFG_FLAGS2_INTRABSS_MEC_WDS_LEARNING_DISABLE BIT(15) + #define WMI_RSRC_CFG_FLAG1_THREE_WAY_COEX_CONFIG_OVERRIDE_SUPPORT BIT(25) + #define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5) ++#define WMI_RSRC_CFG_FLAGS2_SAWF_CONFIG_ENABLE_SET BIT(13) + + struct wmi_resource_config { + __le32 tlv_header; +@@ -7431,6 +7434,7 @@ struct target_resource_config { + u32 ema_max_vap_cnt; + u32 ema_max_profile_period; + u8 dp_peer_meta_data_ver; ++ bool sawf; + }; + + enum wmi_tpc_pream_bw { +--- a/drivers/net/wireless/ath/ath12k/debug.h ++++ b/drivers/net/wireless/ath/ath12k/debug.h +@@ -28,6 +28,7 @@ enum ath12k_debug_mask { + ATH12K_DBG_DP_RX = 0x00004000, + ATH12K_DBG_OFFSET = 0x00008000, + ATH12K_DBG_RX_REO = 0x00010000, ++ ATH12K_DBG_SAWF = 0x80000000, + ATH12K_DBG_ANY = 0xffffffff, + }; + diff --git a/feeds/ipq95xx/mac80211/patches/qca/750-02-ath12k-Add-vendor-command-support-for-SAWF.patch b/feeds/ipq95xx/mac80211/patches/qca/750-02-ath12k-Add-vendor-command-support-for-SAWF.patch new file mode 100644 index 000000000..69cf3f5ee --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/750-02-ath12k-Add-vendor-command-support-for-SAWF.patch @@ -0,0 +1,548 @@ +From 40ea68f9c184368f1d6ca18283040368b4304f30 Mon Sep 17 00:00:00 2001 +From: Nagarajan Maran +Date: Mon, 7 Nov 2022 18:26:49 +0530 +Subject: [PATCH] ath12: Add vendor command support for SAWF + +Add vendor command support for SAWF configure/reconfigure, +disable and view the service classes. + +Signed-off-by: Nagarajan Maran +Signed-off-by: Karthikeyan Kathirvel +--- + drivers/net/wireless/ath/ath12k/Makefile | 3 +- + drivers/net/wireless/ath/ath12k/vendor.c | 121 +++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/vendor.h | 46 +++++++++ + 3 files changed, 169 insertions(+), 1 deletion(-) + create mode 100644 drivers/net/wireless/ath/ath12k/vendor.c + create mode 100644 drivers/net/wireless/ath/ath12k/vendor.h + +--- a/drivers/net/wireless/ath/ath12k/Makefile ++++ b/drivers/net/wireless/ath/ath12k/Makefile +@@ -21,7 +21,8 @@ ath12k-y += core.o \ + mhi.o \ + pci.o \ + dp_mon.o \ +- sawf.o ++ sawf.o \ ++ vendor.o + + ath12k-$(CPTCFG_ATH12K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o + ath12k-$(CPTCFG_NL80211_TESTMODE) += testmode.o +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/vendor.c +@@ -0,0 +1,275 @@ ++// SPDX-License-Identifier: BSD-3-Clause-Clear ++/* ++ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved ++ */ ++#include ++#include ++#include "core.h" ++#include "debug.h" ++#include "mac.h" ++ ++static const struct nla_policy ++ath12k_vendor_sawf_config_policy[QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX + 1] = { ++ [QCN_WLAN_VENDOR_ATTR_SAWF_SERVICE_CLASSES] = {.type = NLA_NESTED}, ++ [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_ID] = {.type = NLA_U8}, ++ [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_APP_NAME] = {.type = NLA_STRING}, ++ [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MIN_TP] = {.type = NLA_U32}, ++ [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MAX_TP] = {.type = NLA_U32}, ++ [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_BURST_SIZE] = {.type = NLA_U32}, ++ [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_INTERVAL] = {.type = NLA_U32}, ++ [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_DELAY_BOUND] = {.type = NLA_U32}, ++ [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_TTL] = {.type = NLA_U32}, ++ [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_PRIO] = {.type = NLA_U32}, ++ [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_TID] = {.type = NLA_U32}, ++ [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_RATE_LOSS] = {.type = NLA_U32}, ++}; ++ ++static void ath12k_set_default_values(struct ath12k_sawf_svc_params *param) ++{ ++ param->min_throughput_rate = SAWF_SVC_PARAM_DEFAULT_MIN_THRUPUT; ++ param->max_throughput_rate = SAWF_SVC_PARAM_DEFAULT_MAX_THRUPUT; ++ param->burst_size = SAWF_SVC_PARAM_DEFAULT_BURST_SIZE; ++ param->service_interval = SAWF_SVC_PARAM_DEFAULT_SVC_INTERVAL; ++ param->delay_bound = SAWF_SVC_PARAM_DEFAULT_DELAY_BOUND; ++ param->msdu_ttl = SAWF_SVC_PARAM_DEFAULT_TIME_TO_LIVE; ++ param->priority = SAWF_SVC_PARAM_DEFAULT_PRIORITY; ++ param->tid = SAWF_SVC_PARAM_DEFAULT_TID; ++ param->msdu_rate_loss = SAWF_SVC_PARAM_DEFAULT_MSDU_LOSS_RATE; ++} ++ ++static int ath12k_vendor_set_sawf_config(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ const void *data, ++ int data_len) ++{ ++ struct nlattr *tb[QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX + 1]; ++ struct ath12k_sawf_svc_params sawf_param; ++ char *app_name = NULL; ++ int ret = 0; ++ ++ if (!ath12k_sawf_enable) ++ return -EOPNOTSUPP; ++ ++ memset(&sawf_param, 0, sizeof(struct ath12k_sawf_svc_params)); ++ ++ ret = nla_parse(tb, QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX, data, data_len, ++ ath12k_vendor_sawf_config_policy, NULL); ++ if (ret) { ++ ath12k_err(NULL, "Invalid attributes with SAWF configure command\n"); ++ return ret; ++ } ++ ++ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_ID] && ++ tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_APP_NAME]) { ++ sawf_param.svc_id = nla_get_u8(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_ID]); ++ app_name = nla_data(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_APP_NAME]); ++ memcpy(sawf_param.app_name, app_name, ATH12K_MAX_APP_NAME); ++ } else { ++ ath12k_err(NULL, "Mandatory attributes not available\n"); ++ return -EINVAL; ++ } ++ ++ ath12k_set_default_values(&sawf_param); ++ ++ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MIN_TP]) ++ sawf_param.min_throughput_rate = nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MIN_TP]); ++ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MAX_TP]) ++ sawf_param.max_throughput_rate = nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MAX_TP]); ++ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_BURST_SIZE]) ++ sawf_param.burst_size = nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_BURST_SIZE]); ++ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_INTERVAL]) ++ sawf_param.service_interval = nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_INTERVAL]); ++ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_DELAY_BOUND]) ++ sawf_param.delay_bound = nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_DELAY_BOUND]); ++ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_TTL]) ++ sawf_param.msdu_ttl = nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_TTL]); ++ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_PRIO]) ++ sawf_param.priority = nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_PRIO]); ++ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_TID]) ++ sawf_param.tid = nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_TID]); ++ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_RATE_LOSS]) ++ sawf_param.msdu_rate_loss = nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_RATE_LOSS]); ++ ++ ret = ath12k_create_send_svc_params(&sawf_param); ++ ++ return ret; ++} ++ ++static int ath12k_vendor_disable_sawf_config(struct wiphy *wihpy, ++ struct wireless_dev *wdev, ++ const void *data, ++ int data_len) ++{ ++ struct nlattr *tb[QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX + 1]; ++ u8 svc_id = 0; ++ int ret = 0; ++ ++ if (!ath12k_sawf_enable) ++ return -EOPNOTSUPP; ++ ++ ret = nla_parse(tb, QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX, data, data_len, ++ ath12k_vendor_sawf_config_policy, NULL); ++ if (ret) { ++ ath12k_err(NULL, "Invalid attribute with SAWF disable command\n"); ++ return ret; ++ } ++ ++ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_ID]) { ++ svc_id = nla_get_u8(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_ID]); ++ } else { ++ ath12k_err(NULL, "Mandatory attribute not available\n"); ++ return -EINVAL; ++ } ++ ++ ret = ath12k_sawf_disable_config(svc_id); ++ ++ return ret; ++} ++ ++static int ath12k_vendor_view_sawf_config(struct wiphy *wihpy, ++ struct wireless_dev *wdev, ++ struct sk_buff *msg, ++ const void *data, ++ int data_len, ++ unsigned long *storage) ++{ ++ struct nlattr *tb[QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX + 1]; ++ struct ath12k_sawf_ctx *sawf_ctx; ++ struct ath12k_sawf_svc_params *svc_class; ++ struct nlattr *sawf_svc_classes, *sawf_svc_class; ++ int ret = 0, i, j = 0; ++ int tailroom = 0, nest_start_length = 0, nest_end_length = 0, nested_range = 0; ++ u8 svc_id = 0; ++ ++ if (!ath12k_sawf_enable) ++ return -EOPNOTSUPP; ++ ++ ret = nla_parse(tb, QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX, data, data_len, ++ ath12k_vendor_sawf_config_policy, NULL); ++ ++ if (ret) { ++ ath12k_warn(NULL, "Invalid attribute with SAWF view command \n"); ++ return ret; ++ } ++ ++ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_ID]) { ++ svc_id = nla_get_u8(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_ID]); ++ if (!ath12k_svc_id_valid(svc_id)) { ++ ath12k_err(NULL, "Invalid Service ID: %u\n", svc_id); ++ return -EINVAL; ++ } ++ if (!ath12k_svc_id_configured(svc_id)) ++ return -EINVAL; ++ } ++ ++ /* return 0 to end the dump */ ++ if (storage && (*storage == ATH12K_SAWF_SVC_CLASS_MAX)) ++ return 0; ++ ++ sawf_ctx = ath12k_get_sawf_context(); ++ ++ if (!sawf_ctx) { ++ ath12k_err(NULL, "SAWF context not available\n"); ++ return -ENODATA; ++ } ++ ++ sawf_svc_classes = nla_nest_start(msg, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SERVICE_CLASSES); ++ ++ if (!sawf_svc_classes) ++ return -ENOBUFS; ++ ++ tailroom = skb_tailroom(msg); ++ spin_lock_bh(&sawf_ctx->sawf_svc_lock); ++ for (i = (svc_id) ? (svc_id - 1) : (*storage); ++ i < ATH12K_SAWF_SVC_CLASS_MAX && tailroom > nested_range; ++ i += (svc_id) ? (ATH12K_SAWF_SVC_CLASS_MAX) : (1)) { ++ if (!sawf_ctx->svc_classes[i].configured) ++ continue; ++ ++ svc_class = &sawf_ctx->svc_classes[i]; ++ nest_start_length = msg->len; ++ sawf_svc_class = nla_nest_start(msg, j); ++ if (nla_put_u8(msg, QCN_WLAN_VENDOR_ATTR_SAWF_SVC_ID, ++ svc_class->svc_id) || ++ nla_put(msg, QCN_WLAN_VENDOR_ATTR_SAWF_SVC_APP_NAME, ++ sizeof(svc_class->app_name), ++ svc_class->app_name) || ++ nla_put_u32(msg, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MIN_TP, ++ svc_class->min_throughput_rate) || ++ nla_put_u32(msg, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MAX_TP, ++ svc_class->max_throughput_rate) || ++ nla_put_u32(msg, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_BURST_SIZE, ++ svc_class->burst_size) || ++ nla_put_u32(msg, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_INTERVAL, ++ svc_class->service_interval) || ++ nla_put_u32(msg, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_DELAY_BOUND, ++ svc_class->delay_bound) || ++ nla_put_u32(msg, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_TTL, ++ svc_class->msdu_ttl) || ++ nla_put_u32(msg, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_PRIO, ++ svc_class->priority) || ++ nla_put_u32(msg, QCN_WLAN_VENDOR_ATTR_SAWF_SVC_TID, ++ svc_class->tid) || ++ nla_put_u32(msg, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_RATE_LOSS, ++ svc_class->msdu_rate_loss)) ++ goto nla_put_failure; ++ ++ nest_end_length = nla_nest_end(msg, sawf_svc_class); ++ nested_range = nest_end_length - nest_start_length; ++ tailroom -= nested_range; ++ j++; ++ } ++ spin_unlock_bh(&sawf_ctx->sawf_svc_lock); ++ nla_nest_end(msg, sawf_svc_classes); ++ ++ *storage = (svc_id) ? (ATH12K_SAWF_SVC_CLASS_MAX) : (i); ++ ++ if (!j) ++ return 0; ++ ++ return msg->len; ++ ++nla_put_failure: ++ spin_unlock_bh(&sawf_ctx->sawf_svc_lock); ++ return -ENOBUFS; ++} ++ ++static struct wiphy_vendor_command ath12k_vendor_commands[] = { ++ { ++ .info.vendor_id = QCA_NL80211_VENDOR_ID, ++ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SVC_CREATE, ++ .doit = ath12k_vendor_set_sawf_config, ++ .policy = ath12k_vendor_sawf_config_policy, ++ .maxattr = QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX, ++ }, ++ { ++ .info.vendor_id = QCA_NL80211_VENDOR_ID, ++ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SVC_DISABLE, ++ .doit = ath12k_vendor_disable_sawf_config, ++ .policy = ath12k_vendor_sawf_config_policy, ++ .maxattr = QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX, ++ }, ++ { ++ .info.vendor_id = QCA_NL80211_VENDOR_ID, ++ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SVC_VIEW, ++ .dumpit = ath12k_vendor_view_sawf_config, ++ .policy = ath12k_vendor_sawf_config_policy, ++ .maxattr = QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX, ++ }, ++}; ++ ++int ath12k_vendor_register(struct ath12k_hw *ah) ++{ ++ ah->hw->wiphy->vendor_commands = ath12k_vendor_commands; ++ ah->hw->wiphy->n_vendor_commands = ARRAY_SIZE(ath12k_vendor_commands); ++ return 0; ++} +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/vendor.h +@@ -0,0 +1,40 @@ ++// SPDX-License-Identifier: BSD-3-Clause-Clear ++/* ++ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved ++ */ ++#ifndef ATH12K_VENDOR_H ++#define ATH12K_VENDOR_H ++ ++#define QCA_NL80211_VENDOR_ID 0x001374 ++ ++enum qca_nl80211_vendor_subcmds { ++ /* Wi-Fi configuration subcommand */ ++ QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION = 74, ++ ++ QCA_NL80211_VENDOR_SUBCMD_SVC_CREATE = 204, ++ QCA_NL80211_VENDOR_SUBCMD_SVC_DISABLE = 205, ++ QCA_NL80211_VENDOR_SUBCMD_SVC_VIEW = 206, ++}; ++ ++enum qca_wlan_vendor_sawf_attr_config { ++ QCN_WLAN_VENDOR_ATTR_SAWF_SERVICE_CLASSES = 1, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_ID, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_APP_NAME, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MIN_TP, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MAX_TP, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_BURST_SIZE, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_INTERVAL, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_DELAY_BOUND, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_TTL, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_PRIO, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_TID, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_RATE_LOSS, ++ ++ /* keep last */ ++ QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_AFTER_LAST, ++ QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX = ++ QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_AFTER_LAST - 1, ++}; ++ ++int ath12k_vendor_register(struct ath12k_hw *ah); ++#endif /* QCA_VENDOR_H */ +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -27,6 +27,7 @@ + #include "spectral.h" + #include "pktlog.h" + #include "sawf.h" ++#include "vendor.h" + + #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -15021,6 +15021,8 @@ static int ath12k_mac_hw_register(struct + ah->hw->wiphy->regulatory_flags = REGULATORY_WIPHY_SELF_MANAGED; + ah->hw->wiphy->reg_notifier = ath12k_reg_notifier; + ++ ath12k_vendor_register(ah); ++ + if (!test_bit(ATH12K_FLAG_RAW_MODE, &ag->dev_flags)) { + hw->netdev_features = NETIF_F_HW_CSUM; + ieee80211_hw_set(hw, SW_CRYPTO_CONTROL); +--- a/drivers/net/wireless/ath/ath12k/sawf.c ++++ b/drivers/net/wireless/ath/ath12k/sawf.c +@@ -242,3 +242,145 @@ bool ath12k_disable_svc_class(u8 svc_id) + + return true; + } ++ ++/* When fimware crash occurs/simulated with firmware recovery ++ * enabled, the service class records in the driver will be sent ++ * to the crashed chip for configuring in the firmware. ++ */ ++int ath12k_sawf_reconfigure_on_crash(struct ath12k_base *ab) ++{ ++ struct ath12k_sawf_svc_params svc_class = {}; ++ struct ath12k *ar; ++ int i; ++ ++ if (!ath12k_sawf_enable) ++ return 0; ++ ++ if (!sawf_ctx) ++ return -ENODATA; ++ ++ ar = ab->pdevs[0].ar; ++ if (!ar) { ++ ath12k_err(NULL, "Radio not initialized\n"); ++ return -ENODATA; ++ } ++ ++ for (i = 0; i < ATH12K_SAWF_SVC_CLASS_MAX; i++) { ++ if (!sawf_ctx->svc_classes[i].configured) ++ continue; ++ svc_class = sawf_ctx->svc_classes[i]; ++ ath12k_wmi_svc_config_send(ar, &svc_class); ++ } ++ return 0; ++} ++ ++/* TID which is an optional parameter, when not given during ++ * service class configuration, is calulated based on the ++ * other service class parameters. ++ */ ++static u32 ath12k_sawf_tid_calc(struct ath12k_sawf_svc_params *cmd) ++{ ++ u32 delay_bound_present, time_to_live_present, svc_interval_present, tid; ++ ++ delay_bound_present = ++ cmd->delay_bound != SAWF_SVC_PARAM_DEFAULT_DELAY_BOUND; ++ time_to_live_present = ++ cmd->msdu_ttl != SAWF_SVC_PARAM_DEFAULT_TIME_TO_LIVE; ++ svc_interval_present = ++ cmd->service_interval != SAWF_SVC_PARAM_DEFAULT_SVC_INTERVAL; ++ ++ tid = 0; /* default */ ++ if (delay_bound_present) { ++ if (cmd->delay_bound < DELAY_BOUND_ULTRA_LOW) { ++ tid = 7; ++ } else if (cmd->delay_bound < DELAY_BOUND_LOW) { ++ tid = 6; ++ } else if (cmd->delay_bound < DELAY_BOUND_MID) { ++ tid = 4; ++ if (time_to_live_present && ++ (cmd->msdu_ttl < TIME_TO_LIVE_MID)) ++ tid = 5; ++ } else if (cmd->delay_bound < DELAY_BOUND_HIGH) { ++ tid = 4; ++ if (svc_interval_present) { ++ if (cmd->service_interval < SVC_INTERVAL_ULTRA_LOW) ++ tid = 7; ++ else if (cmd->service_interval < SVC_INTERVAL_LOW) ++ tid = 6; ++ } ++ } ++ } else if (svc_interval_present) { ++ if (cmd->service_interval < SVC_INTERVAL_ULTRA_LOW) ++ tid = 7; ++ else if (cmd->service_interval < SVC_INTERVAL_LOW) ++ tid = 6; ++ } else if (time_to_live_present) { ++ if (cmd->msdu_ttl < TIME_TO_LIVE_ULTRA_LOW) ++ tid = 7; ++ else if (cmd->msdu_ttl < TIME_TO_LIVE_LOW) ++ tid = 6; ++ } ++ return tid; ++} ++ ++int ath12k_create_send_svc_params(struct ath12k_sawf_svc_params *param) ++{ ++ int ret = 0; ++ ++ if (!ath12k_svc_id_valid(param->svc_id)) { ++ ath12k_warn(NULL, "svc_id: %u is invalid, Service ID range: %d - %d\n", ++ param->svc_id, ATH12K_SAWF_SVC_CLASS_MIN, ++ ATH12K_SAWF_SVC_CLASS_MAX); ++ return -EINVAL; ++ } ++ ++ if (ath12k_svc_id_configured(param->svc_id)) { ++ if (ath12k_get_tid(param->svc_id) != param->tid) { ++ ath12k_err(NULL, "Updating service class failed for TID ID:%u", ++ param->tid); ++ return -EINVAL; ++ } ++ } ++ ++ if (param->tid == SAWF_SVC_PARAM_DEFAULT_TID) ++ param->tid = ath12k_sawf_tid_calc(param); ++ ++ if (!ath12k_validate_sawf_param(param)) { ++ ath12k_err(NULL, "Service class parameters validation failed\n"); ++ return -EINVAL; ++ } ++ ++ ret = ath12k_send_sawf_configs_soc(param); ++ if (ret) { ++ ath12k_err(NULL, "service class configuration failed\n"); ++ return ret; ++ } ++ ++ param->configured = true; ++ ath12k_update_svc_class(param); ++ return ret; ++} ++ ++int ath12k_sawf_disable_config(u8 svc_id) ++{ ++ int ret; ++ ++ if (!ath12k_svc_id_valid(svc_id)) { ++ ath12k_err(NULL, "svc_id: %u is invalid\n", svc_id); ++ return -EINVAL; ++ } ++ ++ if (!ath12k_svc_id_configured(svc_id)) { ++ ath12k_err(NULL, "svc_id: %u is not configured\n", svc_id); ++ return -EINVAL; ++ } ++ ++ ret = ath12k_sawf_send_disable_soc(svc_id); ++ if (ret) { ++ ath12k_err(NULL, "svc_id: %u disabling failed\n", svc_id); ++ return ret; ++ } ++ ++ ath12k_disable_svc_class(svc_id); ++ return ret; ++} +--- a/drivers/net/wireless/ath/ath12k/sawf.h ++++ b/drivers/net/wireless/ath/ath12k/sawf.h +@@ -82,6 +82,16 @@ enum SAWF_SVC_PARAM_DEFAULTS { + SAWF_SVC_PARAM_DEFAULT_MSDU_LOSS_RATE = 0, + }; + ++#define DELAY_BOUND_ULTRA_LOW 10 ++#define DELAY_BOUND_LOW 100 ++#define DELAY_BOUND_MID 200 ++#define DELAY_BOUND_HIGH 300 ++#define SVC_INTERVAL_ULTRA_LOW 20 ++#define SVC_INTERVAL_LOW 50 ++#define TIME_TO_LIVE_ULTRA_LOW 20 ++#define TIME_TO_LIVE_LOW 200 ++#define TIME_TO_LIVE_MID 250 ++ + /** + * struct ath12k_sawf_svc_params - Service Class Parameters + * @svc_id: Service ID +@@ -134,5 +144,7 @@ bool ath12k_svc_id_valid(u8 svc_id); + void ath12k_update_svc_class(struct ath12k_sawf_svc_params *sawf_params); + bool ath12k_disable_svc_class(u8 svc_id); + int ath12k_get_tid(u8 svc_id); +- ++int ath12k_sawf_reconfigure_on_crash(struct ath12k_base *ab); ++int ath12k_create_send_svc_params(struct ath12k_sawf_svc_params *param); ++int ath12k_sawf_disable_config(u8 svc_id); + #endif /* ATH11K_SAWF_H */ diff --git a/feeds/ipq95xx/mac80211/patches/qca/750-03-ath12k-Add-support-to-send-service-class-params.patch b/feeds/ipq95xx/mac80211/patches/qca/750-03-ath12k-Add-support-to-send-service-class-params.patch new file mode 100644 index 000000000..3dcb6b33d --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/750-03-ath12k-Add-support-to-send-service-class-params.patch @@ -0,0 +1,120 @@ +From ba2da215e8896375b83a16e6e05bff8fbadc83fe Mon Sep 17 00:00:00 2001 +From: Nagarajan Maran +Date: Mon, 7 Nov 2022 18:40:12 +0530 +Subject: [PATCH] ath12k: Adding support to send service class params for all + SOC + +Each service class will be sent to all the socs since they +need to be identical across all the chips and so are stored +globally too. + +Signed-off-by: Nagarajan Maran +--- + drivers/net/wireless/ath/ath12k/core.c | 66 ++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/core.h | 4 ++ + drivers/net/wireless/ath/ath12k/mac.c | 85 ++++++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/mac.h | 3 + + 4 files changed, 158 insertions(+) + +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -1872,6 +1872,8 @@ static void ath12k_core_restart(struct w + } + } + ++ if (ath12k_sawf_reconfigure_on_crash(ab)) ++ ath12k_warn(ab, "SAWF SLA reconfiguring failed\n"); + } + + static void ath12k_core_reset(struct work_struct *work) +@@ -2303,6 +2305,72 @@ err_sc_free: + return NULL; + } + ++int ath12k_send_sawf_configs_soc(struct ath12k_sawf_svc_params *new_param) ++{ ++ struct ath12k_hw_group *ag; ++ struct ath12k_base *ab; ++ struct ath12k *ar; ++ int soc, ret = 0; ++ ++ mutex_lock(&ath12k_hw_lock); ++ list_for_each_entry(ag, &ath12k_hw_groups, list) { ++ if (!ag) { ++ ath12k_warn(NULL, "unable to fetch hw group\n"); ++ mutex_unlock(&ath12k_hw_lock); ++ return -ENODEV; ++ } ++ for (soc = ag->num_probed; soc > 0; soc--) { ++ ab = ag->ab[soc - 1]; ++ ar = ab->pdevs[0].ar; ++ if (!ar) { ++ /* Control should not reach here */ ++ ath12k_info(ab, "Radio not initialized in the SOC\n"); ++ continue; ++ } ++ ret = ath12k_wmi_svc_config_send(ar, new_param); ++ if (ret) { ++ mutex_unlock(&ath12k_hw_lock); ++ return ret; ++ } ++ } ++ } ++ mutex_unlock(&ath12k_hw_lock); ++ return ret; ++} ++ ++int ath12k_sawf_send_disable_soc(u8 svc_id) ++{ ++ struct ath12k_hw_group *ag; ++ struct ath12k_base *ab; ++ struct ath12k *ar; ++ int soc, ret = 0; ++ ++ mutex_lock(&ath12k_hw_lock); ++ list_for_each_entry(ag, &ath12k_hw_groups, list) { ++ if (!ag) { ++ ath12k_warn(NULL, "unable to fetch hw group\n"); ++ mutex_unlock(&ath12k_hw_lock); ++ return -ENODEV; ++ } ++ for (soc = ag->num_probed; soc > 0; soc--) { ++ ab = ag->ab[soc - 1]; ++ ar = ab->pdevs[0].ar; ++ if (!ar) { ++ /* Control should not reach here */ ++ ath12k_info(ab, "Radio not initialized in the SOC\n"); ++ continue; ++ } ++ ret = ath12k_wmi_svc_send_disable(ar, svc_id); ++ if (ret) { ++ mutex_unlock(&ath12k_hw_lock); ++ return ret; ++ } ++ } ++ } ++ mutex_unlock(&ath12k_hw_lock); ++ return ret; ++} ++ + static int ath12k_init(void) + { + int ret; +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -15390,4 +15390,3 @@ void ath12k_mac_background_dfs_event(str + ret); + } + } +- +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -1474,6 +1474,8 @@ void ath12k_fw_stats_pdevs_free(struct l + void ath12k_fw_stats_bcn_free(struct list_head *head); + void ath12k_fw_stats_reset(struct ath12k *ar); + void ath12k_fw_stats_free(struct ath12k_fw_stats *stats); ++int ath12k_send_sawf_configs_soc(struct ath12k_sawf_svc_params *new_param); ++int ath12k_sawf_send_disable_soc(u8 svc_id); + + static inline const char *ath12k_scan_state_str(enum ath12k_scan_state state) + { diff --git a/feeds/ipq95xx/mac80211/patches/qca/750-04-ath12k-Add-WMI-support-for-SAWF.patch b/feeds/ipq95xx/mac80211/patches/qca/750-04-ath12k-Add-WMI-support-for-SAWF.patch new file mode 100644 index 000000000..6bc9c087f --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/750-04-ath12k-Add-WMI-support-for-SAWF.patch @@ -0,0 +1,250 @@ +From fe31b34a75c991249b448ca36c54015582daed5c Mon Sep 17 00:00:00 2001 +From: Nagarajan Maran +Date: Mon, 7 Nov 2022 18:51:52 +0530 +Subject: [PATCH] ath12k: Add WMI support for SAWF + +Add Service class configure and disable WMI support. + +Signed-off-by: Nagarajan Maran +--- + drivers/net/wireless/ath/ath12k/wmi.c | 150 ++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/wmi.h | 150 ++++++++++++++++++++++ + 3 files changed, 376 insertions(+) + +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -14,6 +14,7 @@ struct ath12k_base; + struct ath12k; + struct ath12k_fw_stats; + struct ath12k_reg_tpc_power_info; ++struct ath12k_sawf_svc_params; + + #define PSOC_HOST_MAX_NUM_SS (8) + +@@ -254,6 +255,7 @@ enum wmi_cmd_group { + WMI_GRP_MOTION_DET = 0x3f, + WMI_GRP_SPATIAL_REUSE = 0x40, + WMI_GRP_MLO = 0x48, ++ WMI_GRP_SAWF = 0x49, + }; + + #define WMI_CMD_GRP(grp_id) (((grp_id) << 12) | 0x1) +@@ -686,6 +688,12 @@ enum wmi_tlv_cmd_id { + WMI_MLO_READY_CMDID, + WMI_MLO_TEARDOWN_CMDID, + WMI_MLO_PEER_TID_TO_LINK_MAP_CMDID, ++ /** Service Aware WiFi (SAWF) **/ ++ /** configure or reconfigure the parameters for a service class **/ ++ WMI_SAWF_SERVICE_CLASS_CFG_CMDID = WMI_TLV_CMD(WMI_GRP_SAWF), ++ /** disable a service class **/ ++ WMI_SAWF_SERVICE_CLASS_DISABLE_CMDID, ++ + }; + + enum wmi_tlv_event_id { +@@ -2027,6 +2035,8 @@ enum wmi_tlv_tag { + WMI_TAG_TPC_STATS_RATES_ARRAY, + WMI_TAG_TPC_STATS_CTL_PWR_TABLE_EVENT, + WMI_TAG_BCN_TMPL_ML_PARAMS_CMD = 0x3E6, ++ WMI_TAG_SAWF_SERVICE_CLASS_CFG_CMD_FIXED_PARAM = 0x40A, ++ WMI_TAG_SAWF_SERVICE_CLASS_DISABLE_CMD_FIXED_PARAM = 0x40B, + WMI_TAG_BCN_TMPL_ML_INFO_CMD = 0x436, + WMI_TAG_CTRL_PATH_CMD_FIXED_PARAM = 0x442, + WMI_TAG_CTRL_PATH_EVENT_FIXED_PARAM, +@@ -6840,6 +6850,95 @@ struct wmi_twt_resume_dialog_params_cmd + u32 next_twt_size; + } __packed; + ++struct wmi_sawf_svc_cfg_cmd_fixed_param { ++ u32 tlv_header; /* TLV tag and len */ ++ /* Tag equals WMI_TAG_SAWF_SERVICE_CLASS_CFG_CMD_FIXED_PARAM */ ++ u32 svc_class_id; /* which service class is being configured */ ++ /*----- ++ * The below fields specify the values for the parameters of the ++ * service class being configured. ++ * Each such service class parameter has a default value specified in the ++ * above WMI_SAWF_SVC_CLASS_PARAM_DEFAULTS enum. ++ * This default value shall be specified for service classes where ++ * the parameter in question is not applicable. ++ * For example, for service classes that have no minimum throughput ++ * requirement, the min_thruput_kbps field should be set to ++ * WMI_SAWF_SVC_CLASS_PARAM_DEFAULT_MIN_THRUPUT, i.e. 0. ++ *----- ++ */ ++ /* min_thruput_kbps: ++ * How much throughput should be "guaranteed" for each MSDU queue ++ * belonging to this service class. ++ * Units are kilobits per second. ++ */ ++ u32 min_thruput_kbps; ++ /* max_thruput_kbps: ++ * What upper limit on throughput shall be applied to MSDU queues beloning ++ * to this service class, if other peer-TIDs are not meeting their QoS ++ * service goals. ++ * Units are kilobits per second. ++ */ ++ u32 max_thruput_kbps; ++ /* burst_size_bytes: ++ * How much data (i.e. how many MSDUs) should be pulled from a ++ * MSDU queue belonging to this service class to be formed into MPDUs ++ * and enqueued for transmission. ++ * Similarly, how long should a tx op be for MPDUs containing MSDUs from ++ * this service class, to ensure that the necessary amount of data gets ++ * delivered to the peer. ++ * Units are bytes. ++ */ ++ u32 burst_size_bytes; ++ /* svc_interval_ms: ++ * How frequently MSDUs belonging to this service class should be ++ * formed into MPDUs and enqueued for transmission. ++ * The svc_interval_ms parameter is expected to be <= the delay_bound_ms ++ * parameter. ++ * Units are milliseconds. ++ */ ++ u32 svc_interval_ms; ++ /* delay_bound_ms: ++ * How promptly the MSDUs belonging to this service class need to be ++ * delivered to the recipient peer. ++ * Units are milliseconds. ++ */ ++ u32 delay_bound_ms; ++ /* time_to_live_ms: ++ * How long MSDUs belonging to this service class remain valid. ++ * If the MSDU has not been successfully transmitted before this ++ * time-to-live time has elapsed, the MSDU should be discarded. ++ * The time_to_live_ms parameter is expected to be >= the delay_bound_ms ++ * parameter. ++ * Units are milliseconds. ++ */ ++ u32 time_to_live_ms; ++ /* priority: ++ * What degree of precedence shall the WLAN FW's tx scheduler use ++ * when considering whether to transmit MPDUs generated from MSDUs ++ * belonging to this service class. ++ */ ++ u32 priority; ++ /* tid: ++ * Which WLAN TID shall be used for delivering traffic of this ++ * service class. ++ */ ++ u32 tid; ++ /* msdu_loss_rate_ppm: ++ * This parameter indicates the acceptable rate of MSDU loss. ++ * Units are parts per million. ++ * E.g. if it is acceptable for 1 MSDU of every 10000 to be lost, ++ * the msdu_loss_rate_ppm value would be 100, ++ * since 100 / 1000000 = 1 / 10000. ++ */ ++ u32 msdu_loss_rate_ppm; ++} __packed; ++ ++struct wmi_sawf_svc_disable_cmd_fixed_param { ++ u32 tlv_header; /* TLV tag and len*/ ++ /* Tag equals WMI_TAG_SAWF_SERVICE_CLASS_DISABLE_CMD_FIXED_PARAM*/ ++ u32 svc_class_id; /* which service class is being disabled */ ++} __packed; ++ + /** + * WMI arrays of length WMI_MGMT_FRAME_SUBTYPE_MAX use the + * IEEE802.11 standard's enumeration of mgmt frame subtypes: +@@ -8212,6 +8311,9 @@ int ath12k_wmi_pdev_multiple_vdev_restar + int ath12k_wmi_vdev_adfs_ch_cfg_cmd_send(struct ath12k *ar,u32 vdev_id, + struct cfg80211_chan_def *chandef); + int ath12k_wmi_vdev_adfs_ocac_abort_cmd_send(struct ath12k *ar,u32 vdev_id); ++int ath12k_wmi_svc_config_send(struct ath12k *ar, ++ struct ath12k_sawf_svc_params *param); ++int ath12k_wmi_svc_send_disable(struct ath12k *ar, u32 svc_id); + int ath12k_wmi_mgmt_rx_reo_filter_config(struct ath12k *ar, + struct ath12k_mgmt_rx_reo_filter *filter); + int +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -13935,3 +13935,88 @@ int ath12k_wmi_vdev_adfs_ocac_abort_cmd_ + } + return ret; + } ++ ++int ath12k_wmi_svc_config_send(struct ath12k *ar, struct ath12k_sawf_svc_params *param) ++{ ++ struct ath12k_pdev_wmi *wmi = ar->wmi; ++ struct wmi_sawf_svc_cfg_cmd_fixed_param *cmd; ++ struct sk_buff *skb; ++ int len, ret; ++ ++ len = sizeof(*cmd); ++ skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len); ++ if (!skb) ++ return -ENOMEM; ++ ++ cmd = (struct wmi_sawf_svc_cfg_cmd_fixed_param *)skb->data; ++ cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_SAWF_SERVICE_CLASS_CFG_CMD_FIXED_PARAM, ++ sizeof(*cmd)); ++ ++ /* Valid svc_id advertized to user is in the range of 1 to 128. ++ * However, firmware is maintaining svc_id range from 0 to 127. ++ * So sending svc_id - 1, to address this firmware limitation. ++ */ ++ cmd->svc_class_id = cpu_to_le32(param->svc_id - 1); ++ cmd->min_thruput_kbps = cpu_to_le32(param->min_throughput_rate); ++ cmd->max_thruput_kbps = cpu_to_le32(param->max_throughput_rate); ++ cmd->burst_size_bytes = cpu_to_le32(param->burst_size); ++ cmd->svc_interval_ms = cpu_to_le32(param->service_interval); ++ cmd->delay_bound_ms = cpu_to_le32(param->delay_bound); ++ cmd->time_to_live_ms = cpu_to_le32(param->msdu_ttl); ++ cmd->priority = cpu_to_le32(param->priority); ++ cmd->tid = cpu_to_le32(param->tid); ++ cmd->msdu_loss_rate_ppm = cpu_to_le32(param->msdu_rate_loss); ++ ++ ath12k_dbg(ar->ab, ATH12K_DBG_WMI, ++ "Service class configure: svc_id: %u, min_throughput: %u, " ++ "max_throughput: %u, burst_size: %u, svc_interval: %u, " ++ "delay_bound: %u, TTL: %u, priority: %u, tid: %u, msdu_loss_rate: %u", ++ cmd->svc_class_id, cmd->min_thruput_kbps, cmd->max_thruput_kbps, ++ cmd->burst_size_bytes, cmd->svc_interval_ms, cmd->delay_bound_ms, ++ cmd->time_to_live_ms, cmd->priority, cmd->tid, ++ cmd->msdu_loss_rate_ppm); ++ ++ ret = ath12k_wmi_cmd_send(wmi, skb, WMI_SAWF_SERVICE_CLASS_CFG_CMDID); ++ if (ret) { ++ ath12k_err(ar->ab, ++ "failed to config/reconfig the service class param\n"); ++ dev_kfree_skb(skb); ++ } ++ ++ return ret; ++} ++ ++int ath12k_wmi_svc_send_disable(struct ath12k *ar, u32 svc_id) ++{ ++ struct ath12k_pdev_wmi *wmi = ar->wmi; ++ struct wmi_sawf_svc_disable_cmd_fixed_param *cmd; ++ struct sk_buff *skb; ++ int len, ret; ++ ++ len = sizeof(*cmd); ++ skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len); ++ if (!skb) ++ return -ENOMEM; ++ ++ cmd = (struct wmi_sawf_svc_disable_cmd_fixed_param *)skb->data; ++ cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_SAWF_SERVICE_CLASS_DISABLE_CMD_FIXED_PARAM, ++ sizeof(*cmd)); ++ ++ /* Valid svc_id advertized to user is in the range of 1 to 128. ++ * However, firmware is maintaining svc_id range from 0 to 127. ++ * So sending svc_id - 1, to address this firmware limitation. ++ */ ++ cmd->svc_class_id = cpu_to_le32(svc_id - 1); ++ ++ ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "Service class disable: svc_id: %u", ++ cmd->svc_class_id); ++ ++ ret = ath12k_wmi_cmd_send(wmi, skb, WMI_SAWF_SERVICE_CLASS_DISABLE_CMDID); ++ if (ret) { ++ ath12k_err(ar->ab, ++ "failed to disable service class: %u\n", svc_id); ++ dev_kfree_skb(skb); ++ } ++ ++ return ret; ++} diff --git a/feeds/ipq95xx/mac80211/patches/qca/750-ath12k-Add-retry-mechanism-for-update_rx_queue-reo-cmd.patch b/feeds/ipq95xx/mac80211/patches/qca/750-ath12k-Add-retry-mechanism-for-update_rx_queue-reo-cmd.patch new file mode 100644 index 000000000..db6d2d644 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/750-ath12k-Add-retry-mechanism-for-update_rx_queue-reo-cmd.patch @@ -0,0 +1,551 @@ +From 26c6f2a11c7a2ed8bfd265d630a1ab700397f4f3 Mon Sep 17 00:00:00 2001 +From: Manish Dharanenthiran +Date: Thu, 16 Mar 2023 18:24:03 +0530 +Subject: [PATCH] ath12k: Add retry mechanism for update_rx_queue reo cmd + +While reo_cmd ring is full, peer delete update rx queue +will be failed as there is no space to send the command +in ring. During the failure scenario, host will do +dma_unmap and free the allocated address but the HW +still have that particular vaddr. So, on next alloc +cycle kernel will allocated the freed addr but HW will +still have the address. This will result in memory +corruption as the host will try to access/write that +memory which is already in-use. + +To avoid this corruption, added new retry mechanism +for HAL_REO_CMD_UPDATE_RX_QUEUE by adding new list to +dp struct and protecting with new lock for access. +This avoids the host free in failure case and will +be freed only when HW freed that particular vaddr. + +Also, updated below changes + 1) reo_flush command for sending 1K desc in one + command instead of sending 11 command for single + TID. + 2) Set FWD_MPDU and valid bit flag so that reo + flush will happen soon instead of waiting to + flush the queue. + 3) memset reo lut addr after successful allocation. + 4) Clear qdesc cache clear after qref reset and before + freeing qdesc addr. + +Signed-off-by: Manish Dharanenthiran +--- + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/debugfs.c | 4 + + drivers/net/wireless/ath/ath12k/dp.c | 3 + + drivers/net/wireless/ath/ath12k/dp.h | 6 + + drivers/net/wireless/ath/ath12k/dp_rx.c | 315 +++++++++++++-------- + drivers/net/wireless/ath/ath12k/dp_rx.h | 10 + + drivers/net/wireless/ath/ath12k/hal.h | 1 + + drivers/net/wireless/ath/ath12k/hal_desc.h | 1 + + drivers/net/wireless/ath/ath12k/hal_rx.c | 3 + + 9 files changed, 223 insertions(+), 121 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -1067,6 +1067,7 @@ struct ath12k_soc_dp_stats { + u32 mon_drop_desc; + u32 hal_reo_cmd_drain; + u32 reo_cmd_cache_error; ++ u32 reo_cmd_update_rx_queue_error; + u32 mcast_enqueued; + u32 ucast_enqueued; + u32 mcast_reinject; +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -1574,6 +1574,10 @@ static ssize_t ath12k_debugfs_dump_soc_d + soc_stats->reo_cmd_cache_error); + + len += scnprintf(buf + len, size - len, ++ "\nREO_CMD_UPDATE_RX_QUEUE Failure: %u\n", ++ soc_stats->reo_cmd_update_rx_queue_error); ++ ++ len += scnprintf(buf + len, size - len, + "\nmcast reinject: %u\n", + soc_stats->mcast_reinject); + +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -1697,7 +1697,9 @@ int ath12k_dp_alloc(struct ath12k_base * + + INIT_LIST_HEAD(&dp->reo_cmd_list); + INIT_LIST_HEAD(&dp->reo_cmd_cache_flush_list); ++ INIT_LIST_HEAD(&dp->reo_cmd_update_rx_queue_list); + spin_lock_init(&dp->reo_cmd_lock); ++ spin_lock_init(&dp->reo_cmd_update_rx_queue_lock); + + dp->reo_cmd_cache_flush_count = 0; + chip_id = (ab->ag->mlo_capable) ? ab->chip_id : 0; +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -354,6 +354,12 @@ struct ath12k_dp { + * - reo_cmd_cache_flush_count + */ + spinlock_t reo_cmd_lock; ++ struct list_head reo_cmd_update_rx_queue_list; ++ /** ++ * protects access to below field, ++ * - reo_cmd_update_rx_queue_list ++ */ ++ spinlock_t reo_cmd_update_rx_queue_lock; + struct ath12k_hp_update_timer reo_cmd_timer; + struct ath12k_hp_update_timer tx_ring_timer[DP_TCL_NUM_RING_MAX]; + struct ath12k_spt_info *spt_info; +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -28,6 +28,9 @@ + + #define ATH12K_DP_RX_FRAGMENT_TIMEOUT_MS (2 * HZ) + ++static void ath12k_dp_rx_tid_del_func(struct ath12k_dp *dp, void *ctx, ++ enum hal_reo_cmd_status status); ++ + static enum hal_encrypt_type ath12k_dp_rx_h_enctype(struct ath12k_base *ab, + struct hal_rx_desc *desc) + { +@@ -596,56 +599,29 @@ static int ath12k_dp_rx_pdev_srng_alloc( + return 0; + } + +-void ath12k_dp_rx_reo_cmd_list_cleanup(struct ath12k_base *ab) ++static void ath12k_peer_rx_tid_qref_reset(struct ath12k_base *ab, u16 peer_id, u16 tid) + { ++ struct ath12k_reo_queue_ref *qref; + struct ath12k_dp *dp = &ab->dp; +- struct ath12k_dp_rx_reo_cmd *cmd, *tmp; +- struct ath12k_dp_rx_reo_cache_flush_elem *cmd_cache, *tmp_cache; +- struct ath12k_dp_rx_tid *rx_tid; ++ bool ml_peer = false; + +- spin_lock_bh(&dp->reo_cmd_lock); +- list_for_each_entry_safe(cmd, tmp, &dp->reo_cmd_list, list) { +- list_del(&cmd->list); +- rx_tid = &cmd->data; +- if (rx_tid->vaddr) { +- dma_unmap_single(ab->dev, rx_tid->paddr, +- rx_tid->size, DMA_BIDIRECTIONAL); +- kfree(rx_tid->vaddr); +- rx_tid->vaddr = NULL; +- } +- kfree(cmd); +- } ++ if (!ab->hw_params->reoq_lut_support) ++ return; + +- list_for_each_entry_safe(cmd_cache, tmp_cache, +- &dp->reo_cmd_cache_flush_list, list) { +- list_del(&cmd_cache->list); +- dp->reo_cmd_cache_flush_count--; +- rx_tid = &cmd_cache->data; +- if (rx_tid->vaddr) { +- dma_unmap_single(ab->dev, rx_tid->paddr, +- rx_tid->size, DMA_BIDIRECTIONAL); +- kfree(rx_tid->vaddr); +- rx_tid->vaddr = NULL; +- } +- kfree(cmd_cache); ++ if (peer_id & ATH12K_ML_PEER_ID_VALID) { ++ peer_id &= ~ATH12K_ML_PEER_ID_VALID; ++ ml_peer = true; + } +- spin_unlock_bh(&dp->reo_cmd_lock); +-} + +-static void ath12k_dp_reo_cmd_free(struct ath12k_dp *dp, void *ctx, +- enum hal_reo_cmd_status status) +-{ +- struct ath12k_dp_rx_tid *rx_tid = ctx; ++ if (ml_peer) ++ qref = (struct ath12k_reo_queue_ref *)dp->ml_reoq_lut.vaddr + ++ (peer_id * (IEEE80211_NUM_TIDS + 1) + tid); ++ else ++ qref = (struct ath12k_reo_queue_ref *)dp->reoq_lut.vaddr + ++ (peer_id * (IEEE80211_NUM_TIDS + 1) + tid); + +- if (status != HAL_REO_CMD_SUCCESS) +- ath12k_warn(dp->ab, "failed to flush rx tid hw desc, tid %d status %d\n", +- rx_tid->tid, status); +- if (rx_tid->vaddr) { +- dma_unmap_single(dp->ab->dev, rx_tid->paddr, rx_tid->size, +- DMA_BIDIRECTIONAL); +- kfree(rx_tid->vaddr); +- rx_tid->vaddr = NULL; +- } ++ qref->info0 = u32_encode_bits(0, BUFFER_ADDR_INFO0_ADDR); ++ qref->info1 = u32_encode_bits(0, BUFFER_ADDR_INFO1_ADDR); + } + + static int ath12k_dp_reo_cmd_send(struct ath12k_base *ab, struct ath12k_dp_rx_tid *rx_tid, +@@ -696,47 +672,124 @@ static int ath12k_dp_reo_cmd_send(struct + return 0; + } + +-static int ath12k_dp_reo_cache_flush(struct ath12k_base *ab, +- struct ath12k_dp_rx_tid *rx_tid) ++static int ath12k_peer_rx_tid_delete_handler(struct ath12k_base *ab, ++ struct ath12k_dp_rx_tid *rx_tid, u8 tid) + { + struct ath12k_hal_reo_cmd cmd = {0}; +- unsigned long tot_desc_sz, desc_sz; +- int ret; ++ struct ath12k_dp *dp = &ab->dp; + +- if (rx_tid->pending_desc_size) +- tot_desc_sz = rx_tid->pending_desc_size; +- else +- tot_desc_sz = rx_tid->size; +- desc_sz = ath12k_hal_reo_qdesc_size(0, HAL_DESC_REO_NON_QOS_TID); ++ lockdep_assert_held(&dp->reo_cmd_update_rx_queue_lock); ++ ++ rx_tid->active = false; ++ cmd.flag = HAL_REO_CMD_FLG_NEED_STATUS; ++ cmd.addr_lo = lower_32_bits(rx_tid->paddr); ++ cmd.addr_hi = upper_32_bits(rx_tid->paddr); ++ cmd.upd0 |= HAL_REO_CMD_UPD0_VLD; ++ cmd.upd0 |= HAL_REO_CMD_UPD0_BA_WINDOW_SIZE; ++ cmd.ba_window_size = (tid == HAL_DESC_REO_NON_QOS_TID) ? ++ rx_tid->ba_win_sz : DP_BA_WIN_SZ_MAX; ++ cmd.upd1 |= HAL_REO_CMD_UPD1_VLD; ++ ++ return ath12k_dp_reo_cmd_send(ab, rx_tid, ++ HAL_REO_CMD_UPDATE_RX_QUEUE, &cmd, ++ ath12k_dp_rx_tid_del_func); ++} + +- while (tot_desc_sz > desc_sz) { +- tot_desc_sz -= desc_sz; +- cmd.addr_lo = lower_32_bits(rx_tid->paddr + tot_desc_sz); +- cmd.addr_hi = upper_32_bits(rx_tid->paddr); +- ret = ath12k_dp_reo_cmd_send(ab, rx_tid, +- HAL_REO_CMD_FLUSH_CACHE, &cmd, +- NULL); +- if (ret) +- { +- rx_tid->pending_desc_size = tot_desc_sz + desc_sz; +- /* If this fails with ring full condition, then +- * no need to retry below as it is expected to +- * fail within short time */ +- if (ret == -ENOBUFS) +- goto exit; ++void ath12k_dp_rx_reo_cmd_list_cleanup(struct ath12k_base *ab) ++{ ++ struct ath12k_dp *dp = &ab->dp; ++ struct ath12k_dp_rx_reo_cmd *cmd, *tmp; ++ struct ath12k_dp_rx_reo_cache_flush_elem *cmd_cache, *tmp_cache; ++ struct dp_reo_update_rx_queue_elem *cmd_queue, *tmp_queue; ++ struct ath12k_dp_rx_tid *rx_tid; ++ ++ spin_lock_bh(&dp->reo_cmd_update_rx_queue_lock); ++ list_for_each_entry_safe(cmd_queue, tmp_queue, &dp->reo_cmd_update_rx_queue_list, ++ list) { ++ list_del(&cmd_queue->list); ++ rx_tid = &cmd_queue->data; ++ if (rx_tid->vaddr) { ++ dma_unmap_single(ab->dev, rx_tid->paddr, ++ rx_tid->size, DMA_BIDIRECTIONAL); ++ kfree(rx_tid->vaddr); ++ rx_tid->vaddr = NULL; ++ } ++ kfree(cmd_queue); ++ } ++ spin_unlock_bh(&dp->reo_cmd_update_rx_queue_lock); ++ ++ spin_lock_bh(&dp->reo_cmd_lock); ++ list_for_each_entry_safe(cmd, tmp, &dp->reo_cmd_list, list) { ++ list_del(&cmd->list); ++ rx_tid = &cmd->data; ++ if (rx_tid->vaddr) { ++ dma_unmap_single(ab->dev, rx_tid->paddr, ++ rx_tid->size, DMA_BIDIRECTIONAL); ++ kfree(rx_tid->vaddr); ++ rx_tid->vaddr = NULL; + } ++ kfree(cmd); ++ } ++ ++ list_for_each_entry_safe(cmd_cache, tmp_cache, ++ &dp->reo_cmd_cache_flush_list, list) { ++ list_del(&cmd_cache->list); ++ dp->reo_cmd_cache_flush_count--; ++ rx_tid = &cmd_cache->data; ++ if (rx_tid->vaddr) { ++ dma_unmap_single(ab->dev, rx_tid->paddr, ++ rx_tid->size, DMA_BIDIRECTIONAL); ++ kfree(rx_tid->vaddr); ++ rx_tid->vaddr = NULL; ++ } ++ kfree(cmd_cache); ++ } ++ spin_unlock_bh(&dp->reo_cmd_lock); ++} ++ ++static void ath12k_dp_reo_cmd_free(struct ath12k_dp *dp, void *ctx, ++ enum hal_reo_cmd_status status) ++{ ++ struct ath12k_dp_rx_tid *rx_tid = ctx; ++ ++ if (status != HAL_REO_CMD_SUCCESS) ++ ath12k_warn(dp->ab, "failed to flush rx tid hw desc, tid %d status %d\n", ++ rx_tid->tid, status); ++ ++ ath12k_hal_reo_shared_qaddr_cache_clear(dp->ab); ++ ++ if (rx_tid->vaddr) { ++ dma_unmap_single(dp->ab->dev, rx_tid->paddr, rx_tid->size, ++ DMA_BIDIRECTIONAL); ++ kfree(rx_tid->vaddr); ++ rx_tid->vaddr = NULL; + } ++} ++ ++static int ath12k_dp_reo_cache_flush(struct ath12k_base *ab, ++ struct ath12k_dp_rx_tid *rx_tid) ++{ ++ struct ath12k_hal_reo_cmd cmd = {0}; ++ int ret; + +- rx_tid->pending_desc_size = desc_sz; + memset(&cmd, 0, sizeof(cmd)); + cmd.addr_lo = lower_32_bits(rx_tid->paddr); + cmd.addr_hi = upper_32_bits(rx_tid->paddr); +- cmd.flag |= HAL_REO_CMD_FLG_NEED_STATUS; ++ cmd.flag |= HAL_REO_CMD_FLG_NEED_STATUS | ++ HAL_REO_CMD_FLG_FLUSH_FWD_ALL_MPDUS; ++ ++ /* For all NON_QOS tid, driver allocates max window ++ * size of 1024. For this, driver can send flush 1K Desc ++ * in one command instead of sending 11 cmd for ++ * single NON_QOS tid(s). ++ */ ++ if (rx_tid->tid != HAL_DESC_REO_NON_QOS_TID) ++ cmd.flag |= HAL_REO_CMD_FLG_FLUSH_QUEUE_1K_DESC; ++ + ret = ath12k_dp_reo_cmd_send(ab, rx_tid, + HAL_REO_CMD_FLUSH_CACHE, + &cmd, ath12k_dp_reo_cmd_free); + +-exit: + return ret; + } + +@@ -744,8 +797,9 @@ static void ath12k_dp_rx_tid_del_func(st + enum hal_reo_cmd_status status) + { + struct ath12k_base *ab = dp->ab; +- struct ath12k_dp_rx_tid *rx_tid = ctx; ++ struct ath12k_dp_rx_tid *rx_tid = ctx, *update_rx_tid; + struct ath12k_dp_rx_reo_cache_flush_elem *elem, *tmp; ++ struct dp_reo_update_rx_queue_elem *qelem, *qtmp; + + if (status == HAL_REO_CMD_DRAIN) { + ab->soc_stats.hal_reo_cmd_drain++; +@@ -757,6 +811,33 @@ static void ath12k_dp_rx_tid_del_func(st + return; + } + ++ /* Check if there is any pending rx_queue, if yes then update it */ ++ spin_lock_bh(&dp->reo_cmd_update_rx_queue_lock); ++ list_for_each_entry_safe(qelem, qtmp, &dp->reo_cmd_update_rx_queue_list, ++ list) { ++ if (qelem->reo_cmd_update_rx_queue_resend_flag && ++ qelem->data.active) { ++ update_rx_tid = &qelem->data; ++ ++ if (ath12k_peer_rx_tid_delete_handler(ab, update_rx_tid, qelem->tid)) { ++ update_rx_tid->active = true; ++ break; ++ } ++ ath12k_peer_rx_tid_qref_reset(ab, ++ qelem->is_ml_peer ? qelem->ml_peer_id : qelem->peer_id, ++ qelem->tid); ++ ath12k_hal_reo_shared_qaddr_cache_clear(ab); ++ update_rx_tid->vaddr = NULL; ++ update_rx_tid->paddr = 0; ++ update_rx_tid->size = 0; ++ update_rx_tid->pending_desc_size = 0; ++ ++ list_del(&qelem->list); ++ kfree(qelem); ++ } ++ } ++ spin_unlock_bh(&dp->reo_cmd_update_rx_queue_lock); ++ + elem = kzalloc(sizeof(*elem), GFP_ATOMIC); + if (!elem) { + ath12k_warn(ab, "failed to alloc reo_cache_flush_elem, rx tid %d\n", +@@ -779,12 +860,11 @@ static void ath12k_dp_rx_tid_del_func(st + spin_unlock_bh(&dp->reo_cmd_lock); + + if (ath12k_dp_reo_cache_flush(ab, &elem->data)) { ++ ab->soc_stats.reo_cmd_cache_error++; + /* In failure case, just update the timestamp + * for flush cache elem and continue */ +- ab->soc_stats.reo_cmd_cache_error++; + spin_lock_bh(&dp->reo_cmd_lock); +- elem->ts = jiffies + +- msecs_to_jiffies(ATH12K_DP_RX_REO_DESC_FREE_TIMEOUT_MS); ++ elem->ts = jiffies; + break; + } + spin_lock_bh(&dp->reo_cmd_lock); +@@ -834,66 +914,59 @@ static void ath12k_peer_rx_tid_qref_setu + ath12k_hal_reo_shared_qaddr_cache_clear(ab); + } + +-static void ath12k_peer_rx_tid_qref_reset(struct ath12k_base *ab, u16 peer_id, u16 tid) ++void ath12k_dp_rx_peer_tid_delete(struct ath12k *ar, ++ struct ath12k_peer *peer, u8 tid) + { +- struct ath12k_reo_queue_ref *qref; ++ struct ath12k_dp_rx_tid *rx_tid = &peer->rx_tid[tid]; ++ struct dp_reo_update_rx_queue_elem *elem, *tmp; ++ struct ath12k_base *ab = ar->ab; + struct ath12k_dp *dp = &ab->dp; +- bool ml_peer = false; + +- if (!ab->hw_params->reoq_lut_support) ++ if (!rx_tid->active) + return; + +- if (peer_id & ATH12K_ML_PEER_ID_VALID) { +- peer_id &= ~ATH12K_ML_PEER_ID_VALID; +- ml_peer = true; ++ elem = kzalloc(sizeof(*elem), GFP_ATOMIC); ++ if (!elem) { ++ ath12k_warn(ar->ab, "failed to alloc reo_update_rx_queue_elem, rx tid %d\n", ++ rx_tid->tid); ++ return; + } ++ elem->reo_cmd_update_rx_queue_resend_flag = false; ++ elem->peer_id = peer->peer_id; ++ elem->tid = tid; ++ elem->is_ml_peer = peer->mlo ? true : false; ++ elem->ml_peer_id = peer->ml_peer_id; + +- if (ml_peer) +- qref = (struct ath12k_reo_queue_ref *)dp->ml_reoq_lut.vaddr + +- (peer_id * (IEEE80211_NUM_TIDS + 1) + tid); +- else +- qref = (struct ath12k_reo_queue_ref *)dp->reoq_lut.vaddr + +- (peer_id * (IEEE80211_NUM_TIDS + 1) + tid); +- +- qref->info0 = u32_encode_bits(0, BUFFER_ADDR_INFO0_ADDR); +- qref->info1 = u32_encode_bits(0, BUFFER_ADDR_INFO1_ADDR) | +- u32_encode_bits(tid, DP_REO_QREF_NUM); +-} ++ memcpy(&elem->data, rx_tid, sizeof(*rx_tid)); + +-void ath12k_dp_rx_peer_tid_delete(struct ath12k *ar, +- struct ath12k_peer *peer, u8 tid) +-{ +- struct ath12k_hal_reo_cmd cmd = {0}; +- struct ath12k_dp_rx_tid *rx_tid = &peer->rx_tid[tid]; +- int ret; ++ spin_lock_bh(&dp->reo_cmd_update_rx_queue_lock); ++ list_add_tail(&elem->list, &dp->reo_cmd_update_rx_queue_list); + +- if (!rx_tid->active) +- return; ++ list_for_each_entry_safe(elem, tmp, &dp->reo_cmd_update_rx_queue_list, ++ list) { ++ rx_tid = &elem->data; ++ ++ if (ath12k_peer_rx_tid_delete_handler(ab, rx_tid, elem->tid)) { ++ rx_tid->active = true; ++ ab->soc_stats.reo_cmd_update_rx_queue_error++; ++ elem->reo_cmd_update_rx_queue_resend_flag = true; ++ break; ++ } ++ ath12k_peer_rx_tid_qref_reset(ab, ++ elem->is_ml_peer ? elem->ml_peer_id : elem->peer_id, ++ elem->tid); ++ ath12k_hal_reo_shared_qaddr_cache_clear(ab); ++ rx_tid->vaddr = NULL; ++ rx_tid->paddr = 0; ++ rx_tid->size = 0; ++ rx_tid->pending_desc_size = 0; + +- rx_tid->active = false; +- cmd.flag = HAL_REO_CMD_FLG_NEED_STATUS; +- cmd.addr_lo = lower_32_bits(rx_tid->paddr); +- cmd.addr_hi = upper_32_bits(rx_tid->paddr); +- cmd.upd0 |= HAL_REO_CMD_UPD0_VLD; +- ret = ath12k_dp_reo_cmd_send(ar->ab, rx_tid, +- HAL_REO_CMD_UPDATE_RX_QUEUE, &cmd, +- ath12k_dp_rx_tid_del_func); +- if (ret) { +- ath12k_err(ar->ab, "failed to send HAL_REO_CMD_UPDATE_RX_QUEUE cmd, tid %d (%d)\n", +- tid, ret); +- dma_unmap_single(ar->ab->dev, rx_tid->paddr, rx_tid->size, +- DMA_BIDIRECTIONAL); +- kfree(rx_tid->vaddr); ++ list_del(&elem->list); ++ kfree(elem); + } ++ spin_unlock_bh(&dp->reo_cmd_update_rx_queue_lock); + +- if (peer->mlo) +- ath12k_peer_rx_tid_qref_reset(ar->ab, peer->ml_peer_id, tid); +- else +- ath12k_peer_rx_tid_qref_reset(ar->ab, peer->peer_id, tid); +- +- rx_tid->vaddr = NULL; +- rx_tid->paddr = 0; +- rx_tid->size = 0; ++ return; + } + + static int ath12k_dp_rx_link_desc_return(struct ath12k_base *ab, +--- a/drivers/net/wireless/ath/ath12k/dp_rx.h ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.h +@@ -40,6 +40,16 @@ struct ath12k_dp_rx_reo_cache_flush_elem + unsigned long ts; + }; + ++struct dp_reo_update_rx_queue_elem { ++ struct list_head list; ++ struct ath12k_dp_rx_tid data; ++ int peer_id; ++ u8 tid; ++ bool reo_cmd_update_rx_queue_resend_flag; ++ bool is_ml_peer; ++ u16 ml_peer_id; ++}; ++ + struct ath12k_dp_rx_reo_cmd { + struct list_head list; + struct ath12k_dp_rx_tid data; +--- a/drivers/net/wireless/ath/ath12k/hal.h ++++ b/drivers/net/wireless/ath/ath12k/hal.h +@@ -864,6 +864,7 @@ enum hal_rx_buf_return_buf_manager { + #define HAL_REO_CMD_FLG_FLUSH_ALL BIT(6) + #define HAL_REO_CMD_FLG_UNBLK_RESOURCE BIT(7) + #define HAL_REO_CMD_FLG_UNBLK_CACHE BIT(8) ++#define HAL_REO_CMD_FLG_FLUSH_QUEUE_1K_DESC BIT(9) + + /* Should be matching with HAL_REO_UPD_RX_QUEUE_INFO0_UPD_* feilds */ + #define HAL_REO_CMD_UPD0_RX_QUEUE_NUM BIT(8) +--- a/drivers/net/wireless/ath/ath12k/hal_desc.h ++++ b/drivers/net/wireless/ath/ath12k/hal_desc.h +@@ -1209,6 +1209,7 @@ struct hal_reo_flush_queue { + #define HAL_REO_FLUSH_CACHE_INFO0_FLUSH_WO_INVALIDATE BIT(12) + #define HAL_REO_FLUSH_CACHE_INFO0_BLOCK_CACHE_USAGE BIT(13) + #define HAL_REO_FLUSH_CACHE_INFO0_FLUSH_ALL BIT(14) ++#define HAL_REO_FLUSH_CACHE_INFO0_FLUSH_QUEUE_1K_DESC BIT(15) + + struct hal_reo_flush_cache { + struct hal_reo_cmd_hdr cmd; +--- a/drivers/net/wireless/ath/ath12k/hal_rx.c ++++ b/drivers/net/wireless/ath/ath12k/hal_rx.c +@@ -91,6 +91,9 @@ static int ath12k_hal_reo_cmd_flush_cach + if (cmd->flag & HAL_REO_CMD_FLG_FLUSH_ALL) + desc->info0 |= HAL_REO_FLUSH_CACHE_INFO0_FLUSH_ALL; + ++ if (cmd->flag & HAL_REO_CMD_FLG_FLUSH_QUEUE_1K_DESC) ++ desc->info0 |= HAL_REO_FLUSH_CACHE_INFO0_FLUSH_QUEUE_1K_DESC; ++ + return u32_get_bits(desc->cmd.info0, HAL_REO_CMD_HDR_INFO0_CMD_NUMBER); + } + diff --git a/feeds/ipq95xx/mac80211/patches/qca/750-ath12k-fix-memory-leak-in-ath12k_mac_setup_channels_.patch b/feeds/ipq95xx/mac80211/patches/qca/750-ath12k-fix-memory-leak-in-ath12k_mac_setup_channels_.patch new file mode 100644 index 000000000..18a348f0c --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/750-ath12k-fix-memory-leak-in-ath12k_mac_setup_channels_.patch @@ -0,0 +1,85 @@ +From 15e56dc534430e6b9e4b57300f410439e5616a71 Mon Sep 17 00:00:00 2001 +From: Hari Chandrakanthan +Date: Wed, 29 Mar 2023 13:37:24 +0530 +Subject: [PATCH] ath12k: fix memory leak in ath12k_mac_setup_channels_rates + +memory allocated in ath12k_mac_setup_channels_rates and +referenced by ar->mac.sbands[NL80211_BAND_6GHZ].chan_6g[] +is not freed during rmmod of ath12k. + +Fix it by freeing it in __ath12k_mac_post_unregister. + +Signed-off-by: Hari Chandrakanthan +--- + drivers/net/wireless/ath/ath12k/mac.c | 29 ++++++++++++++++++++++------- + 1 file changed, 22 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index 5d5d36c..df0c19d 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -13970,9 +13970,11 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar, + GFP_KERNEL); + if (!channels) { + kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels); +- for (i = 0; i < NL80211_REG_NUM_POWER_MODES; i++) +- kfree(ar->mac.sbands[NL80211_BAND_6GHZ].chan_6g[i]); +- ++ ar->mac.sbands[NL80211_BAND_2GHZ].channels = NULL; ++ for (i = 0; i < NL80211_REG_NUM_POWER_MODES; i++) { ++ kfree(ar->mac.sbands[NL80211_BAND_6GHZ].chan_6g[i]); ++ ar->mac.sbands[NL80211_BAND_6GHZ].chan_6g[i] = NULL; ++ } + return -ENOMEM; + } + +@@ -14033,6 +14035,7 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar, + + if (!channels || !chan_6g) { + kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels); ++ ar->mac.sbands[NL80211_BAND_2GHZ].channels = NULL; + break; + } + +@@ -14045,9 +14048,9 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar, + + if (i < NL80211_REG_NUM_POWER_MODES) { + for (i = i - 1; i >= 0; i--) { +- chan_6g = band->chan_6g[i]; +- kfree(chan_6g->channels); +- kfree(chan_6g); ++ kfree(band->chan_6g[i]->channels); ++ kfree(band->chan_6g[i]); ++ band->chan_6g[i] = NULL; + } + return -ENOMEM; + } +@@ -14254,12 +14257,24 @@ static void __ath12k_mac_pre_unregister(struct ath12k *ar) + + static void __ath12k_mac_post_unregister(struct ath12k *ar) + { ++ int i; ++ + idr_for_each(&ar->txmgmt_idr, ath12k_mac_tx_mgmt_pending_free, ar); + idr_destroy(&ar->txmgmt_idr); + + kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels); + kfree(ar->mac.sbands[NL80211_BAND_5GHZ].channels); +- kfree(ar->mac.sbands[NL80211_BAND_6GHZ].channels); ++ ++ ar->mac.sbands[NL80211_BAND_2GHZ].channels = NULL; ++ ar->mac.sbands[NL80211_BAND_5GHZ].channels = NULL; ++ ++ for (i = 0; i < NL80211_REG_NUM_POWER_MODES; i++) { ++ if (!ar->mac.sbands[NL80211_BAND_6GHZ].chan_6g[i]) ++ continue; ++ kfree(ar->mac.sbands[NL80211_BAND_6GHZ].chan_6g[i]->channels); ++ kfree(ar->mac.sbands[NL80211_BAND_6GHZ].chan_6g[i]); ++ ar->mac.sbands[NL80211_BAND_6GHZ].chan_6g[i] = NULL; ++ } + } + + static void __ath12k_mac_unregister(struct ath12k *ar) +-- +2.7.4 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/750-wifi-ath12k-Skip-CPU-sync-for-REO-in-unmap-DMA-memor.patch b/feeds/ipq95xx/mac80211/patches/qca/750-wifi-ath12k-Skip-CPU-sync-for-REO-in-unmap-DMA-memor.patch new file mode 100644 index 000000000..b98addb18 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/750-wifi-ath12k-Skip-CPU-sync-for-REO-in-unmap-DMA-memor.patch @@ -0,0 +1,43 @@ +From 13609c70dac0f54baaf54c492391fc2b5364b352 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Thu, 16 Mar 2023 11:37:21 +0530 +Subject: [PATCH] wifi: ath12k: Skip CPU sync for REO in unmap DMA memory + +DMA unmap sync take more cpu cycle compare to ARM asm sync operation. +So avoid dma_unmap with sync and added ARM asm sync before dma_unmap +in REO processing. + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/dp_rx.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c +index acf284d58338..05501b0f03f5 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include "core.h" + #include "debug.h" + #include "debugfs_htt_stats.h" +@@ -3331,9 +3332,10 @@ try_again: + spin_unlock_bh(&src_ab->dp.rx_desc_lock); + + rxcb = ATH12K_SKB_RXCB(msdu); +- dma_unmap_single(src_ab->dev, rxcb->paddr, +- msdu->len + skb_tailroom(msdu), +- DMA_FROM_DEVICE); ++ dmac_inv_range_no_dsb(msdu->data, msdu->data + (msdu->len + skb_tailroom(msdu))); ++ dma_unmap_single_attrs(src_ab->dev, rxcb->paddr, ++ msdu->len + skb_tailroom(msdu), ++ DMA_FROM_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); + + num_buffs_reaped[src_ab->chip_id]++; + +-- +2.37.0 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/751-ath12k-Add-framework-to-use-different-hashmap-for-ML.patch b/feeds/ipq95xx/mac80211/patches/qca/751-ath12k-Add-framework-to-use-different-hashmap-for-ML.patch new file mode 100644 index 000000000..e5e88c609 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/751-ath12k-Add-framework-to-use-different-hashmap-for-ML.patch @@ -0,0 +1,194 @@ +From 6c058117bdd85caa6ad5e4e842e1cc869bd478da Mon Sep 17 00:00:00 2001 +From: P Praneesh +Date: Sun, 19 Mar 2023 13:19:02 +0530 +Subject: [PATCH] ath12k: Add framework to use different hashmap for + MLO/NON-MLO peers + +Currently driver specifies the same rx hash value in +HAL_REO1_DEST_RING_CTRL_IX_2 and HAL_REO1_DEST_RING_CTRL_IX_3 +registers. Based on this value, driver's rx reo destination rings are +utilised by the HW. Using same rx ring mask across the ML and non ML +peer degrades the performance. + +To handle both type of peers, adding framework to optimise the +performance of a system that includes both ML and Non ML peers. +For non ML peers, value written in IX2 registers are used and for ML +peers, value wirtten in IX3 registers are used. + +Default routing configuration inside the ath12k_dp_peer_setup() doesnt +help to detect the ML peer due to sta->valid_links missed to have other links +in the first link STA state change from NONE to AUTH state. so it failed to +configure ATH12K_DP_LMAC_PEER_ID_MLO instead it configured as +ATH12K_DP_LMAC_PEER_ID_LEGACY. which lead to fetch the ix2 register for REO +indication. so low throughput seen in ML KPI testcases. So fix this issue by +configuring the same peer default routing configuration again when the STA +move from AUTH to ASSOC state. Now we able to get the correct valid links +from sta->valid_links. + +With this change, Observed 400Mbps improvement with SLO clients. + +Signed-off-by: P Praneesh +--- + drivers/net/wireless/ath/ath12k/dp.c | 39 +++++++++++++++++++++++---- + drivers/net/wireless/ath/ath12k/dp.h | 3 ++- + drivers/net/wireless/ath/ath12k/mac.c | 2 +- + 3 files changed, 37 insertions(+), 7 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -14,6 +14,10 @@ + #include "peer.h" + #include "dp_mon.h" + ++#define ATH12K_DP_LMAC_PEER_ID_LEGACY 2 ++#define ATH12K_DP_LMAC_PEER_ID_MLO 3 ++#define ATH12K_DP_PEER_ROUTING_LMAC_ID_MASK GENMASK(7,6) ++ + static void ath12k_dp_htt_htc_tx_complete(struct ath12k_base *ab, + struct sk_buff *skb) + { +@@ -47,30 +51,55 @@ void ath12k_dp_peer_cleanup(struct ath12 + spin_unlock_bh(&ab->base_lock); + } + +-int ath12k_dp_peer_setup(struct ath12k *ar, int vdev_id, const u8 *addr) ++int ath12k_dp_peer_default_route_setup(struct ath12k *ar, struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta) + { + struct ath12k_base *ab = ar->ab; +- struct ath12k_peer *peer; +- u32 reo_dest; +- int ret = 0, tid; ++ struct ieee80211_sta *sta; ++ u32 reo_dest, param_value; ++ u32 lmac_peer_routing_id = ATH12K_DP_LMAC_PEER_ID_LEGACY; ++ int ret; + +- /* TODO setup resources only for primary link peer for ML case */ ++ sta = container_of((void *)arsta->ahsta, struct ieee80211_sta, drv_priv); + + /* NOTE: reo_dest ring id starts from 1 unlike mac_id which starts from 0 */ + reo_dest = ar->dp.mac_id + 1; +- ret = ath12k_wmi_set_peer_param(ar, addr, vdev_id, +- WMI_PEER_SET_DEFAULT_ROUTING, +- DP_RX_HASH_ENABLE | (reo_dest << 1)); ++ param_value = (reo_dest << 1 | DP_RX_HASH_ENABLE); ++ ++ /* For MLO supported peers and it has multi link capablity, use MLO conf */ ++ if (hweight16(sta->valid_links) > 1) ++ lmac_peer_routing_id = ATH12K_DP_LMAC_PEER_ID_MLO; + ++ param_value |= FIELD_PREP(ATH12K_DP_PEER_ROUTING_LMAC_ID_MASK, ++ lmac_peer_routing_id); ++ ++ ret = ath12k_wmi_set_peer_param(ar, arsta->addr, arvif->vdev_id, ++ WMI_PEER_SET_DEFAULT_ROUTING, param_value); + if (ret) { + ath12k_warn(ab, "failed to set default routing %d peer :%pM vdev_id :%d\n", +- ret, addr, vdev_id); ++ ret, arsta->addr, arvif->vdev_id); + return ret; + } + ++ ath12k_dbg(ab, ATH12K_DBG_DP_RX, "peer %pM set def route id %d sta_link %d\n", ++ arsta->addr, lmac_peer_routing_id, ++ hweight16(sta->valid_links)); ++ ++ return 0; ++} ++ ++int ath12k_dp_peer_setup(struct ath12k *ar, struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta) ++{ ++ struct ath12k_base *ab = ar->ab; ++ struct ath12k_peer *peer; ++ int ret = 0, tid; ++ ++ /* TODO setup resources only for primary link peer for ML case */ ++ + for (tid = 0; tid <= IEEE80211_NUM_TIDS; tid++) { +- ret = ath12k_dp_rx_peer_tid_setup(ar, addr, vdev_id, tid, 1, 0, +- HAL_PN_TYPE_NONE); ++ ret = ath12k_dp_rx_peer_tid_setup(ar, arsta->addr, arvif->vdev_id, ++ tid, 1, 0, HAL_PN_TYPE_NONE); + if (ret) { + ath12k_warn(ab, "failed to setup rxd tid queue for tid %d: %d\n", + tid, ret); +@@ -78,7 +107,7 @@ int ath12k_dp_peer_setup(struct ath12k * + } + } + +- ret = ath12k_dp_rx_peer_frag_setup(ar, addr, vdev_id); ++ ret = ath12k_dp_rx_peer_frag_setup(ar, arsta->addr, arvif->vdev_id); + if (ret) { + ath12k_warn(ab, "failed to setup rx defrag context\n"); + tid--; +@@ -92,7 +121,7 @@ int ath12k_dp_peer_setup(struct ath12k * + peer_clean: + spin_lock_bh(&ab->base_lock); + +- peer = ath12k_peer_find(ab, vdev_id, addr); ++ peer = ath12k_peer_find(ab, arvif->vdev_id, arsta->addr); + if (!peer) { + ath12k_warn(ab, "failed to find the peer to del rx tid\n"); + spin_unlock_bh(&ab->base_lock); +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -16,6 +16,7 @@ struct ath12k_base; + struct ath12k_peer; + struct ath12k_dp; + struct ath12k_link_vif; ++struct ath12k_link_sta; + struct hal_tcl_status_ring; + struct ath12k_ext_irq_grp; + +@@ -2172,7 +2173,11 @@ void ath12k_dp_pdev_pre_alloc(struct ath + void ath12k_dp_pdev_free(struct ath12k_base *ab); + int ath12k_dp_tx_htt_srng_setup(struct ath12k_base *ab, u32 ring_id, + int mac_id, enum hal_ring_type ring_type); +-int ath12k_dp_peer_setup(struct ath12k *ar, int vdev_id, const u8 *addr); ++int ath12k_dp_peer_default_route_setup(struct ath12k *ar, ++ struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta); ++int ath12k_dp_peer_setup(struct ath12k *ar, struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta); + void ath12k_dp_peer_cleanup(struct ath12k *ar, int vdev_id, const u8 *addr); + void ath12k_dp_srng_cleanup(struct ath12k_base *ab, struct dp_srng *ring); + int ath12k_dp_srng_setup(struct ath12k_base *ab, struct dp_srng *ring, +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -6620,7 +6620,7 @@ static int ath12k_mac_station_add(struct + } + } + +- ret = ath12k_dp_peer_setup(ar, arvif->vdev_id, arsta->addr); ++ ret = ath12k_dp_peer_setup(ar, arvif, arsta); + if (ret) { + ath12k_warn(ab, "failed to setup dp for peer %pM on vdev %i (%d)\n", + arsta->addr, arvif->vdev_id, ret); +@@ -6871,14 +6871,18 @@ static int ath12k_mac_handle_link_sta_st + ath12k_mac_free_unassign_link_sta(arvif->ahvif->ah, + arsta->ahsta, arsta->link_id); + } else if (old_state == IEEE80211_STA_AUTH && +- new_state == IEEE80211_STA_ASSOC && +- (vif->type == NL80211_IFTYPE_AP || ++ new_state == IEEE80211_STA_ASSOC) { ++ ++ ath12k_dp_peer_default_route_setup(ar, arvif, arsta); ++ ++ if (vif->type == NL80211_IFTYPE_AP || + vif->type == NL80211_IFTYPE_MESH_POINT || +- vif->type == NL80211_IFTYPE_ADHOC)) { +- ret = ath12k_station_assoc(ar, arvif, arsta, false); +- if (ret) +- ath12k_warn(ar->ab, "Failed to associate station: %pM\n", +- arsta->addr); ++ vif->type == NL80211_IFTYPE_ADHOC) { ++ ret = ath12k_station_assoc(ar, arvif, arsta, false); ++ if (ret) ++ ath12k_warn(ar->ab, "Failed to associate station: %pM\n", ++ arsta->addr); ++ } + } else if (old_state == IEEE80211_STA_ASSOC && + new_state == IEEE80211_STA_AUTHORIZED) { + ret = ath12k_station_authorize(ar, arvif, arsta); diff --git a/feeds/ipq95xx/mac80211/patches/qca/751-ath12k-Add-support-for-new-htt_stats.patch b/feeds/ipq95xx/mac80211/patches/qca/751-ath12k-Add-support-for-new-htt_stats.patch new file mode 100644 index 000000000..d9a27a3f3 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/751-ath12k-Add-support-for-new-htt_stats.patch @@ -0,0 +1,1234 @@ +From 141961f03032bd858e25353e6ee7eb19965148bf Mon Sep 17 00:00:00 2001 +From: Sidhanta Sahu +Date: Thu, 23 Mar 2023 20:21:38 -0700 +Subject: [PATCH] ath12k: Add support for new htt_stats + +Type: + ATH12K_DGB_HTT_DBG_PDEV_MBSSID_CTRL_FRAME_STATS + +Tags Added: + HTT_STATS_TX_PDEV_PPDU_DUR_TAG + HTT_STATS_RX_PDEV_PPDU_DUR_TAG + HTT_STATS_PDEV_SCHED_ALGO_OFDMA_STATS_TAG + HTT_STATS_LATENCY_PROF_CAL_STATS_TAG + HTT_STATS_TX_PDEV_AP_EDCA_PARAMS_STATS_TAG + HTT_STATS_TXBF_OFDMA_AX_STEER_MPDU_STATS_TAG + HTT_STATS_TXBF_OFDMA_BE_STEER_MPDU_STATS_TAG + HTT_STATS_PEER_AX_OFDMA_STATS_TAG + HTT_STATS_TX_PDEV_MU_EDCA_PARAMS_STATS_TAG + HTT_STATS_ODD_PDEV_MANDATORY_TAG + HTT_STATS_PDEV_MBSSID_CTRL_FRAME_STATS_TAG + HTT_STATS_TX_PDEV_MLO_ABORT_TAG + HTT_STATS_TX_PDEV_MLO_TXOP_ABORT_TAG + +Signed-off-by: Sidhanta Sahu +--- + drivers/net/wireless/ath/ath12k/debugfs.h | 2 +- + .../wireless/ath/ath12k/debugfs_htt_stats.c | 737 ++++++++++++++++++ + .../wireless/ath/ath12k/debugfs_htt_stats.h | 329 +++++++- + 3 files changed, 1065 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/debugfs.h ++++ b/drivers/net/wireless/ath/ath12k/debugfs.h +@@ -73,7 +73,7 @@ enum ath12k_dbg_htt_ext_stats_type { + ATH12K_DBG_HTT_DBG_ODD_MANDATORY_MUOFDMA_STATS = 51, + ATH12K_DBG_HTT_DBG_EXT_PHY_PROF_CAL_STATS = 52, + ATH12K_DGB_HTT_DBG_EXT_STATS_PDEV_BW_MGR = 53, +- ++ ATH12K_DGB_HTT_DBG_PDEV_MBSSID_CTRL_FRAME_STATS = 54, + /* keep this last */ + ATH12K_DBG_HTT_NUM_EXT_STATS, + }; +--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c +@@ -6641,6 +6641,738 @@ htt_print_ml_link_info_stats_tlv(const v + stats_req->buf_len = len; + } + ++static inline void ++htt_print_tx_pdev_ppdu_dur_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_pdev_ppdu_dur_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ u8 i, j; ++ u16 index = 0; ++ char data[HTT_MAX_STRING_LEN] = {0}; ++ ++ len += scnprintf(buf + len, buf_len - len, "HTT_TX_PDEV_PPDU_DUR_STATS_TLV:\n"); ++ len += scnprintf(buf + len, buf_len - len, "pdev_up_time_us_low = %u\n", ++ htt_stats_buf->pdev_up_time_us_low); ++ len += scnprintf(buf + len, buf_len - len, "pdev_up_time_us_high = %u\n", ++ htt_stats_buf->pdev_up_time_us_high); ++ len += scnprintf(buf + len, buf_len - len, "tx_success_time_us_low = %u\n", ++ htt_stats_buf->tx_success_time_us_low); ++ len += scnprintf(buf + len, buf_len - len, "tx_success_time_us_high = %u\n", ++ htt_stats_buf->tx_success_time_us_high); ++ len += scnprintf(buf + len, buf_len - len, "tx_fail_time_us_low = %u\n", ++ htt_stats_buf->tx_fail_time_us_low); ++ len += scnprintf(buf + len, buf_len - len, "tx_fail_time_us_high = %u\n", ++ htt_stats_buf->tx_fail_time_us_high); ++ ++ /* Split the buffer store mechanism into two to avoid data buffer overflow ++ */ ++ for (i = 0; i < HTT_PDEV_STATS_PPDU_DUR_HIST_BINS >> 1; i++) { ++ index += snprintf(&data[index], ++ HTT_MAX_STRING_LEN - index, ++ " %u-%u : %u,", ++ i * HTT_PDEV_STATS_PPDU_DUR_HIST_INTERVAL_US, ++ (i + 1) * HTT_PDEV_STATS_PPDU_DUR_HIST_INTERVAL_US, ++ htt_stats_buf->tx_ppdu_dur_hist[i]); ++ } ++ ++ len += scnprintf(buf + len, buf_len - len, "tx_ppdu_dur_hist_us_0 = %s\n", data); ++ memset(data, '\0', sizeof(char) * HTT_MAX_STRING_LEN); ++ index = 0; ++ ++ for (j = i; j < HTT_PDEV_STATS_PPDU_DUR_HIST_BINS; j++) { ++ index += snprintf(&data[index], ++ HTT_MAX_STRING_LEN - index, ++ " %u-%u : %u,", ++ j * HTT_PDEV_STATS_PPDU_DUR_HIST_INTERVAL_US, ++ (j + 1) * HTT_PDEV_STATS_PPDU_DUR_HIST_INTERVAL_US, ++ htt_stats_buf->tx_ppdu_dur_hist[j]); ++ } ++ ++ len += scnprintf(buf + len, buf_len - len, "tx_ppdu_dur_hist_us_1 = %s\n", data); ++ len += scnprintf(buf + len, buf_len - len, ++ "=========================================== \n"); ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_rx_pdev_ppdu_dur_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_rx_pdev_ppdu_dur_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ u8 i, j; ++ u16 index = 0; ++ char data[HTT_MAX_STRING_LEN] = {0}; ++ ++ len += scnprintf(buf + len, buf_len - len, "HTT_RX_PDEV_PPDU_DUR_STATS_TLV:\n"); ++ ++ /* Split the buffer store mechanism into two to avoid data buffer overflow ++ */ ++ for (i = 0; i < HTT_PDEV_STATS_PPDU_DUR_HIST_BINS >> 1; i++) { ++ index += snprintf(&data[index], ++ HTT_MAX_STRING_LEN - index, ++ " %u-%u : %u,", ++ i * HTT_PDEV_STATS_PPDU_DUR_HIST_INTERVAL_US, ++ (i + 1) * HTT_PDEV_STATS_PPDU_DUR_HIST_INTERVAL_US, ++ htt_stats_buf->rx_ppdu_dur_hist[i]); ++ } ++ ++ len += scnprintf(buf + len, buf_len - len, "rx_ppdu_dur_hist_us_0 = %s\n", data); ++ memset(data, '\0', sizeof(char) * HTT_MAX_STRING_LEN); ++ index = 0; ++ ++ for (j = i; j < HTT_PDEV_STATS_PPDU_DUR_HIST_BINS; j++) { ++ index += snprintf(&data[index], ++ HTT_MAX_STRING_LEN - index, ++ " %u-%u : %u,", ++ j * HTT_PDEV_STATS_PPDU_DUR_HIST_INTERVAL_US, ++ (j + 1) * HTT_PDEV_STATS_PPDU_DUR_HIST_INTERVAL_US, ++ htt_stats_buf->rx_ppdu_dur_hist[j]); ++ } ++ ++ len += scnprintf(buf + len, buf_len - len, "rx_ppdu_dur_hist_us_1 = %s\n", data); ++ len += scnprintf(buf + len, buf_len - len, ++ "=========================================== \n"); ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_pdev_sched_algo_ofdma_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_pdev_sched_algo_ofdma_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->rate_based_dlofdma_enabled_count, ++ "rate_based_dlofdma_enabled_count", ++ HTT_NUM_AC_WMM, "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->rate_based_dlofdma_disabled_count, ++ "rate_based_dlofdma_disabled_count", ++ HTT_NUM_AC_WMM, "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->rate_based_dlofdma_probing_count, ++ "rate_based_dlofdma_probing_count", ++ HTT_NUM_AC_WMM, "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->rate_based_dlofdma_monitoring_count, ++ "rate_based_dlofdma_monitoring_count", ++ HTT_NUM_AC_WMM, "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->chan_acc_lat_based_dlofdma_enabled_count, ++ "chan_acc_lat_based_dlofdma_enabled_count", ++ HTT_NUM_AC_WMM, "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->chan_acc_lat_based_dlofdma_disabled_count, ++ "chan_acc_lat_based_dlofdma_disabled_count", ++ HTT_NUM_AC_WMM, "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->chan_acc_lat_based_dlofdma_monitoring_count, ++ "chan_acc_lat_based_dlofdma_monitoring_count", ++ HTT_NUM_AC_WMM, "\n"); ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "=========================================== \n"); ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_latency_prof_cal_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_latency_prof_cal_stats_tlv *htt_stats_buf = tag_buf; ++ char latency_prof_stat_name[HTT_STATS_MAX_PROF_STATS_NAME_LEN + 1] = {0}; ++ u32 i, j; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += scnprintf(buf + len, buf_len - len, "HTT_STATS_LATENCY_PROF_CAL_TLV:\n"); ++ for (i = 1; i < HTT_STATS_MAX_PROF_CAL; i++) { ++ memcpy(latency_prof_stat_name, ++ (htt_stats_buf->latency_prof_name[i]), ++ HTT_STATS_MAX_PROF_STATS_NAME_LEN); ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "%-32s", ++ htt_stats_buf->latency_prof_name[i]); ++ len += scnprintf(buf + len, buf_len - len, ++ "|%9s|%8s|%8s|%8s|%8s|%8s|%10s|%14s|%8s|%8s|%8s|\n", ++ "cal_index", "cnt", "min", "max", "last", "tot", ++ "hist_intvl", "hist", "pf_last", "pf_tot", ++ "pf_max"); ++ ++ for (j = 0; j < htt_stats_buf->CalCnt[i]; j++) { ++ len += scnprintf(buf + len, buf_len - len, ++ "|%9u|%8u|%8u|%8u|%8u|%8u|%10u|%4u:%4u:%4u|%8u|%8u|%8u|\n", ++ htt_stats_buf->enabledCalIdx[i][j], ++ htt_stats_buf->cnt[i][j], ++ htt_stats_buf->min[i][j], ++ htt_stats_buf->max[i][j], ++ htt_stats_buf->last[i][j], ++ htt_stats_buf->tot[i][j], ++ htt_stats_buf->hist_intvl[i][j], ++ htt_stats_buf->hist[i][j][0], ++ htt_stats_buf->hist[i][j][1], ++ htt_stats_buf->hist[i][j][2], ++ htt_stats_buf->pf_last[i][j], ++ htt_stats_buf->pf_tot[i][j], ++ htt_stats_buf->pf_max[i][j]); ++ } ++ } ++ len += scnprintf(buf + len, buf_len - len, ++ "=========================================== \n"); ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_pdev_ap_edca_params_stats_tlv_v(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_pdev_ap_edca_params_stats_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ int i; ++ ++ len += scnprintf(buf + len, buf_len - len, "\nAP EDCA PARAMETERS FOR UL MUMIMO:\n"); ++ for (i = 0; i < HTT_NUM_AC_WMM; i++) { ++ len += scnprintf(buf + len, buf_len - len, "ul_mumimo_less_aggressive[%u] = %u\n", ++ i, htt_stats_buf->ul_mumimo_less_aggressive[i]); ++ len += scnprintf(buf + len, buf_len - len, "ul_mumimo_medium_aggressive[%u] = %u\n", ++ i, htt_stats_buf->ul_mumimo_medium_aggressive[i]); ++ len += scnprintf(buf + len, buf_len - len, "ul_mumimo_highly_aggressive[%u] = %u\n", ++ i, htt_stats_buf->ul_mumimo_highly_aggressive[i]); ++ len += scnprintf(buf + len, buf_len - len, "ul_mumimo_default_relaxed[%u] = %u\n", ++ i, htt_stats_buf->ul_mumimo_default_relaxed[i]); ++ } ++ ++ len += scnprintf(buf + len, buf_len - len, "AP EDCA PARAMETERS FOR UL OFDMA:\n"); ++ for (i = 0; i < HTT_NUM_AC_WMM; i++) { ++ len += scnprintf(buf + len, buf_len - len, "ul_muofdma_less_aggressive[%u] = %u\n", ++ i, htt_stats_buf->ul_muofdma_less_aggressive[i]); ++ len += scnprintf(buf + len, buf_len - len, "ul_muofdma_medium_aggressive[%u] = %u\n", ++ i, htt_stats_buf->ul_muofdma_medium_aggressive[i]); ++ len += scnprintf(buf + len, buf_len - len, "ul_muofdma_highly_aggressive[%u] = %u\n", ++ i, htt_stats_buf->ul_muofdma_highly_aggressive[i]); ++ len += scnprintf(buf + len, buf_len - len, "ul_muofdma_default_relaxed[%u] = %u\n", ++ i, htt_stats_buf->ul_muofdma_default_relaxed[i]); ++ } ++ len += scnprintf(buf + len, buf_len - len, ++ "=========================================== \n"); ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_txbf_ofdma_ax_steer_mpdu_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_txbf_ofdma_ax_steer_mpdu_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += scnprintf(buf + len, buf_len - len, "HTT_TXBF_OFDMA_AX_STEER_MPDU_STATS_TLV:\n"); ++ ++ len += scnprintf(buf + len, buf_len - len, "rbo_steer_mpdus_tried = %u\n", ++ htt_stats_buf->ax_ofdma_rbo_steer_mpdus_tried); ++ len += scnprintf(buf + len, buf_len - len, "rbo_steer_mpdus_failed = %u\n", ++ htt_stats_buf->ax_ofdma_rbo_steer_mpdus_failed); ++ len += scnprintf(buf + len, buf_len - len, "sifs_steer_mpdus_tried = %u\n", ++ htt_stats_buf->ax_ofdma_sifs_steer_mpdus_tried); ++ len += scnprintf(buf + len, buf_len - len, "sifs_steer_mpdus_failed = %u\n", ++ htt_stats_buf->ax_ofdma_sifs_steer_mpdus_failed); ++ len += scnprintf(buf + len, buf_len - len, ++ "=========================================== \n"); ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_txbf_ofdma_be_steer_mpdu_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_txbf_ofdma_be_steer_mpdu_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += scnprintf(buf + len, buf_len - len, "HTT_TXBF_OFDMA_BE_STEER_MPDU_STATS_TLV:\n"); ++ ++ len += scnprintf(buf + len, buf_len - len, "rbo_steer_mpdus_tried = %u\n", ++ htt_stats_buf->be_ofdma_rbo_steer_mpdus_tried); ++ len += scnprintf(buf + len, buf_len - len, "rbo_steer_mpdus_failed = %u\n", ++ htt_stats_buf->be_ofdma_rbo_steer_mpdus_failed); ++ len += scnprintf(buf + len, buf_len - len, "sifs_steer_mpdus_tried = %u\n", ++ htt_stats_buf->be_ofdma_sifs_steer_mpdus_tried); ++ len += scnprintf(buf + len, buf_len - len, "sifs_steer_mpdus_failed = %u\n", ++ htt_stats_buf->be_ofdma_sifs_steer_mpdus_failed); ++ len += scnprintf(buf + len, buf_len - len, ++ "=========================================== \n"); ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_peer_ax_ofdma_stats(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_peer_ax_ofdma_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += scnprintf(buf + len, buf_len - len, "HTT_PEER_AX_OFDMA_STATS_TLV:\n"); ++ len += scnprintf(buf + len, buf_len - len, "peer_id = %u\n", ++ htt_stats_buf->peer_id); ++ len += scnprintf(buf + len, buf_len - len, "ax_basic_trig_count = %u\n", ++ htt_stats_buf->ax_basic_trig_count); ++ len += scnprintf(buf + len, buf_len - len, "ax_basic_trig_err = %u\n", ++ htt_stats_buf->ax_basic_trig_err); ++ len += scnprintf(buf + len, buf_len - len, "ax_bsr_trig_count = %u\n", ++ htt_stats_buf->ax_bsr_trig_count); ++ len += scnprintf(buf + len, buf_len - len, "ax_bsr_trig_err = %u\n", ++ htt_stats_buf->ax_bsr_trig_err); ++ len += scnprintf(buf + len, buf_len - len, "ax_mu_bar_trig_count = %u\n", ++ htt_stats_buf->ax_mu_bar_trig_count); ++ len += scnprintf(buf + len, buf_len - len, "ax_mu_bar_trig_err = %u\n", ++ htt_stats_buf->ax_mu_bar_trig_err); ++ len += scnprintf(buf + len, buf_len - len, "ax_basic_trig_with_per = %u\n", ++ htt_stats_buf->ax_basic_trig_with_per); ++ len += scnprintf(buf + len, buf_len - len, "ax_bsr_trig_with_per = %u\n", ++ htt_stats_buf->ax_bsr_trig_with_per); ++ len += scnprintf(buf + len, buf_len - len, "ax_mu_bar_trig_with_per = %u\n", ++ htt_stats_buf->ax_mu_bar_trig_with_per); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->is_airtime_large_for_dl_ofdma, ++ "is_airtime_large_for_dl_ofdma", 2, "\n"); ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->is_airtime_large_for_ul_ofdma, ++ "is_airtime_large_for_ul_ofdma", 2, "\n"); ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->last_updated_dl_qdepth, ++ "last_updated_dl_qdepth", HTT_NUM_AC_WMM, "\n"); ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->last_updated_ul_qdepth, ++ "last_updated_ul_qdepth", HTT_NUM_AC_WMM, "\n"); ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "=========================================== \n"); ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_pdev_mu_edca_params_stats_tlv_v(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_pdev_mu_edca_params_stats_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char *edca_buf = NULL; ++ ++ edca_buf = kmalloc(HTT_MAX_STRING_LEN, GFP_ATOMIC); ++ if (!edca_buf) ++ goto fail; ++ ++ len += scnprintf(buf + len, buf_len - len, "HTT_TX_PDEV_MU_EDCA_PARAMS_STATS_TLV:\n"); ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->relaxed_mu_edca, ++ "irelaxed_mu_edca", ++ HTT_NUM_AC_WMM, "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->mumimo_aggressive_mu_edca, ++ "mumimo_aggressive_mu_edca", ++ HTT_NUM_AC_WMM, "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->muofdma_relaxed_mu_edca, ++ "muofdma_relaxed_mu_edca", ++ HTT_NUM_AC_WMM, "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->latency_mu_edca, ++ "latency_mu_edca", ++ HTT_NUM_AC_WMM, "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->psd_boost_mu_edca, ++ "psd_boost_mu_edca", ++ HTT_NUM_AC_WMM, "\n"); ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "=========================================== \n"); ++ stats_req->buf_len = len; ++fail: ++ kfree(edca_buf); ++} ++ ++static inline void ++htt_print_odd_pdev_mandatory_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_odd_mandatory_pdev_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += scnprintf(buf + len, buf_len - len, "HTT_ODD_PDEV_MANDATORY_TLV:\n"); ++ len += scnprintf(buf + len, buf_len - len, "hw_queued = %u\n", ++ htt_stats_buf->hw_queued); ++ len += scnprintf(buf + len, buf_len - len, "hw_reaped = %u\n", ++ htt_stats_buf->hw_reaped); ++ len += scnprintf(buf + len, buf_len - len, "hw_paused = %u\n", ++ htt_stats_buf->hw_paused); ++ len += scnprintf(buf + len, buf_len - len, "hw_filt = %u\n", ++ htt_stats_buf->hw_filt); ++ len += scnprintf(buf + len, buf_len - len, "seq_posted = %u\n", ++ htt_stats_buf->seq_posted); ++ len += scnprintf(buf + len, buf_len - len, "seq_completed = %u\n", ++ htt_stats_buf->seq_completed); ++ len += scnprintf(buf + len, buf_len - len, "underrun = %u\n", ++ htt_stats_buf->underrun); ++ len += scnprintf(buf + len, buf_len - len, "hw_flush = %u\n", ++ htt_stats_buf->hw_flush); ++ len += scnprintf(buf + len, buf_len - len, "next_seq_posted_dsr = %u\n", ++ htt_stats_buf->next_seq_posted_dsr); ++ len += scnprintf(buf + len, buf_len - len, "seq_posted_isr = %u\n", ++ htt_stats_buf->seq_posted_isr); ++ len += scnprintf(buf + len, buf_len - len, "mpdu_cnt_fcs_ok = %u\n", ++ htt_stats_buf->mpdu_cnt_fcs_ok); ++ len += scnprintf(buf + len, buf_len - len, "mpdu_cnt_fcs_err = %u\n", ++ htt_stats_buf->mpdu_cnt_fcs_err); ++ len += scnprintf(buf + len, buf_len - len, "msdu_count_tqm = %u\n", ++ htt_stats_buf->msdu_count_tqm); ++ len += scnprintf(buf + len, buf_len - len, "mpdu_count_tqm = %u\n", ++ htt_stats_buf->mpdu_count_tqm); ++ len += scnprintf(buf + len, buf_len - len, "mpdus_ack_failed = %u\n", ++ htt_stats_buf->mpdus_ack_failed); ++ len += scnprintf(buf + len, buf_len - len, "num_data_ppdus_tried_ota = %u\n", ++ htt_stats_buf->num_data_ppdus_tried_ota); ++ len += scnprintf(buf + len, buf_len - len, "ppdu_ok = %u\n", ++ htt_stats_buf->ppdu_ok); ++ len += scnprintf(buf + len, buf_len - len, "num_total_ppdus_tried_ota = %u\n", ++ htt_stats_buf->num_total_ppdus_tried_ota); ++ len += scnprintf(buf + len, buf_len - len, "thermal_suspend_cnt = %u\n", ++ htt_stats_buf->thermal_suspend_cnt); ++ len += scnprintf(buf + len, buf_len - len, "dfs_suspend_cnt = %u\n", ++ htt_stats_buf->dfs_suspend_cnt); ++ len += scnprintf(buf + len, buf_len - len, "tx_abort_suspend_cnt = %u\n", ++ htt_stats_buf->tx_abort_suspend_cnt); ++ len += scnprintf(buf + len, buf_len - len, "suspended_txq_mask = %u\n", ++ htt_stats_buf->suspended_txq_mask); ++ len += scnprintf(buf + len, buf_len - len, "last_suspend_reason = %u\n", ++ htt_stats_buf->last_suspend_reason); ++ len += scnprintf(buf + len, buf_len - len, "seq_failed_queueing = %u\n", ++ htt_stats_buf->seq_failed_queueing); ++ len += scnprintf(buf + len, buf_len - len, "seq_restarted = %u\n", ++ htt_stats_buf->seq_restarted); ++ len += scnprintf(buf + len, buf_len - len, "seq_txop_repost_stop = %u\n", ++ htt_stats_buf->seq_txop_repost_stop); ++ len += scnprintf(buf + len, buf_len - len, "next_seq_cancel = %u\n", ++ htt_stats_buf->next_seq_cancel); ++ len += scnprintf(buf + len, buf_len - len, "seq_min_msdu_repost_stop = %u\n", ++ htt_stats_buf->seq_min_msdu_repost_stop); ++ len += scnprintf(buf + len, buf_len - len, "total_phy_err_cnt = %u\n", ++ htt_stats_buf->total_phy_err_cnt); ++ len += scnprintf(buf + len, buf_len - len, "ppdu_recvd = %u\n", ++ htt_stats_buf->ppdu_recvd); ++ len += scnprintf(buf + len, buf_len - len, "tcp_msdu_cnt = %u\n", ++ htt_stats_buf->tcp_msdu_cnt); ++ len += scnprintf(buf + len, buf_len - len, "tcp_ack_msdu_cnt = %u\n", ++ htt_stats_buf->tcp_ack_msdu_cnt); ++ len += scnprintf(buf + len, buf_len - len, "udp_msdu_cnt = %u \n", ++ htt_stats_buf->udp_msdu_cnt); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->fw_tx_mgmt_subtype, ++ "fw_tx_mgmt_subtype", ++ HTT_STATS_SUBTYPE_MAX, "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->fw_rx_mgmt_subtype, ++ "fw_rx_mgmt_subtype", ++ HTT_STATS_SUBTYPE_MAX, "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->fw_ring_mpdu_err, ++ "fw_ring_mpdu_err", ++ HTT_STATS_SUBTYPE_MAX, "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->fw_rx_mgmt_subtype, ++ "fw_rx_mgmt_subtype", ++ HTT_RX_STATS_RXDMA_MAX_ERR, "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->urrn_stats, ++ "urrn_stats", ++ HTT_TX_PDEV_MAX_URRN_STATS, "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->sifs_status, ++ "sifs_status", ++ HTT_TX_PDEV_MAX_SIFS_BURST_STATS, "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->fw_rx_mgmt_subtype, ++ "sifs_hist_status", ++ HTT_TX_PDEV_SIFS_BURST_HIST_STATS, "\n"); ++ ++ len += scnprintf(buf + len, buf_len - len, "rx_suspend_cnt = %u\n", ++ htt_stats_buf->rx_suspend_cnt); ++ len += scnprintf(buf + len, buf_len - len, "rx_suspend_fail_cnt = %u\n", ++ htt_stats_buf->rx_suspend_fail_cnt); ++ len += scnprintf(buf + len, buf_len - len, "rx_resume_cnt = %u\n", ++ htt_stats_buf->rx_resume_cnt); ++ len += scnprintf(buf + len, buf_len - len, "rx_resume_fail_cnt = %u \n", ++ htt_stats_buf->rx_resume_fail_cnt); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->hwq_beacon_cmd_result, ++ "hwq_beacon_cmd_result", ++ HTT_TX_HWQ_MAX_CMD_RESULT_STATS, "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->hwq_voice_cmd_result, ++ "hwq_voice_cmd_result", ++ HTT_TX_HWQ_MAX_CMD_RESULT_STATS, "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->hwq_video_cmd_result, ++ "hwq_video_cmd_result", ++ HTT_TX_HWQ_MAX_CMD_RESULT_STATS, "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->hwq_best_effort_cmd_result, ++ "hwq_best_effort_cmd_result", ++ HTT_TX_HWQ_MAX_CMD_RESULT_STATS, "\n"); ++ ++ len += scnprintf(buf + len, buf_len - len, "hwq_beacon_mpdu_tried_cnt = %u\n", ++ htt_stats_buf->hwq_beacon_mpdu_tried_cnt); ++ len += scnprintf(buf + len, buf_len - len, "hwq_voice_mpdu_tried_cnt = %u\n", ++ htt_stats_buf->hwq_voice_mpdu_tried_cnt); ++ len += scnprintf(buf + len, buf_len - len, "hwq_video_mpdu_tried_cnt = %u\n", ++ htt_stats_buf->hwq_video_mpdu_tried_cnt); ++ len += scnprintf(buf + len, buf_len - len, "hwq_best_effort_mpdu_tried_cnt = %u\n", ++ htt_stats_buf->hwq_best_effort_mpdu_tried_cnt); ++ len += scnprintf(buf + len, buf_len - len, "hwq_beacon_mpdu_queued_cnt = %u\n", ++ htt_stats_buf->hwq_beacon_mpdu_queued_cnt); ++ len += scnprintf(buf + len, buf_len - len, "hwq_voice_mpdu_queued_cnt = %u\n", ++ htt_stats_buf->hwq_voice_mpdu_queued_cnt); ++ len += scnprintf(buf + len, buf_len - len, "hwq_video_mpdu_queued_cnt = %u\n", ++ htt_stats_buf->hwq_video_mpdu_queued_cnt); ++ len += scnprintf(buf + len, buf_len - len, "hwq_best_effort_mpdu_queued_cnt = %u\n", ++ htt_stats_buf->hwq_best_effort_mpdu_queued_cnt); ++ len += scnprintf(buf + len, buf_len - len, "hwq_beacon_mpdu_ack_fail_cnt = %u\n", ++ htt_stats_buf->hwq_beacon_mpdu_ack_fail_cnt); ++ len += scnprintf(buf + len, buf_len - len, "hwq_voice_mpdu_ack_fail_cnt = %u\n", ++ htt_stats_buf->hwq_voice_mpdu_ack_fail_cnt); ++ len += scnprintf(buf + len, buf_len - len, "hwq_video_mpdu_ack_fail_cnt = %u\n", ++ htt_stats_buf->hwq_video_mpdu_ack_fail_cnt); ++ len += scnprintf(buf + len, buf_len - len, "hwq_best_effort_mpdu_ack_fail_cnt = %u\n", ++ htt_stats_buf->hwq_best_effort_mpdu_ack_fail_cnt); ++ len += scnprintf(buf + len, buf_len - len, "pdev_resets = %u\n", ++ htt_stats_buf->pdev_resets); ++ len += scnprintf(buf + len, buf_len - len, "phy_warm_reset = %u\n", ++ htt_stats_buf->phy_warm_reset); ++ len += scnprintf(buf + len, buf_len - len, "hwsch_reset_count = %u\n", ++ htt_stats_buf->hwsch_reset_count); ++ len += scnprintf(buf + len, buf_len - len, "phy_warm_reset_ucode_trig = %u\n", ++ htt_stats_buf->phy_warm_reset_ucode_trig); ++ len += scnprintf(buf + len, buf_len - len, "mac_cold_reset = %u\n", ++ htt_stats_buf->mac_cold_reset); ++ len += scnprintf(buf + len, buf_len - len, "mac_warm_reset = %u\n", ++ htt_stats_buf->mac_warm_reset); ++ len += scnprintf(buf + len, buf_len - len, "mac_warm_reset_restore_cal = %u\n", ++ htt_stats_buf->mac_warm_reset_restore_cal); ++ len += scnprintf(buf + len, buf_len - len, "phy_warm_reset_m3_ssr = %u\n", ++ htt_stats_buf->phy_warm_reset_m3_ssr); ++ len += scnprintf(buf + len, buf_len - len, "fw_rx_rings_reset = %u\n", ++ htt_stats_buf->fw_rx_rings_reset); ++ len += scnprintf(buf + len, buf_len - len, "tx_flush = %u\n", ++ htt_stats_buf->tx_flush); ++ len += scnprintf(buf + len, buf_len - len, "hwsch_dev_reset_war = %u\n", ++ htt_stats_buf->hwsch_dev_reset_war); ++ len += scnprintf(buf + len, buf_len - len, "mac_cold_reset_restore_cal = %u\n", ++ htt_stats_buf->mac_cold_reset_restore_cal); ++ len += scnprintf(buf + len, buf_len - len, "mac_only_reset = %u\n", ++ htt_stats_buf->mac_only_reset); ++ len += scnprintf(buf + len, buf_len - len, "mac_sfm_reset = %u\n", ++ htt_stats_buf->mac_sfm_reset); ++ len += scnprintf(buf + len, buf_len - len, "rx_ldpc = %u\n", ++ htt_stats_buf->rx_ldpc); ++ len += scnprintf(buf + len, buf_len - len, "tx_ldpc = %u \n", ++ htt_stats_buf->tx_ldpc); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->gen_mpdu_end_reason, ++ "gen_mpdu_end_reason", ++ HTT_TX_TQM_MAX_GEN_MPDU_END_REASON, "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->list_mpdu_end_reason, ++ "list_mpdu_end_reason", ++ HTT_TX_TQM_MAX_GEN_MPDU_END_REASON, "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->tx_mcs, ++ "tx_mcs", ++ (HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS + ++ HTT_TX_PDEV_STATS_NUM_EXTRA_MCS_COUNTERS + ++ HTT_TX_PDEV_STATS_NUM_EXTRA2_MCS_COUNTERS), "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->tx_nss, ++ "tx_nss", ++ HTT_TX_PDEV_STATS_NUM_SPATIAL_STREAMS, "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->tx_bw, ++ "tx_bw", ++ HTT_TX_PDEV_STATS_NUM_BW_COUNTERS, "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->half_tx_bw, ++ "half_tx_bw", ++ HTT_TX_PDEV_STATS_NUM_BW_COUNTERS, "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->quarter_tx_bw, ++ "quarter_tx_bw", ++ HTT_TX_PDEV_STATS_NUM_BW_COUNTERS, "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->tx_su_punctured_mode, ++ "tx_su_punctured_mode", ++ HTT_TX_PDEV_STATS_NUM_PUNCTURED_MODE_COUNTERS, "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->rx_mcs, ++ "rx_mcs", ++ (HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS + ++ HTT_RX_PDEV_STATS_NUM_EXTRA_MCS_COUNTERS + ++ HTT_RX_PDEV_STATS_NUM_EXTRA2_MCS_COUNTERS), "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->rx_nss, ++ "rx_nss", ++ HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS, "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->rx_bw, ++ "rx_bw", ++ HTT_RX_PDEV_STATS_NUM_BW_COUNTERS, "\n"); ++ ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->rx_stbc, ++ "rx_stbc", ++ (HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS + ++ HTT_RX_PDEV_STATS_NUM_EXTRA_MCS_COUNTERS + ++ HTT_RX_PDEV_STATS_NUM_EXTRA2_MCS_COUNTERS), "\n"); ++ ++ len += scnprintf(buf + len, buf_len - len, "rts_cnt = %u\n", ++ htt_stats_buf->rts_cnt); ++ len += scnprintf(buf + len, buf_len - len, "rts_success = %u\n", ++ htt_stats_buf->rts_success); ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "=================================================\n"); ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_pdev_mbssid_ctrl_frame_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_pdev_mbssid_ctrl_frame_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ ++ len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n", ++ HTT_STATS_CMN_MAC_ID_GET(htt_stats_buf->mac_id__word)); ++ ++ len += scnprintf(buf + len, buf_len - len, "basic_trigger_across_bss_count = %u\n", ++ htt_stats_buf->basic_trigger_across_bss); ++ len += scnprintf(buf + len, buf_len - len, "basic_trigger_within_bss_count = %u\n", ++ htt_stats_buf->basic_trigger_within_bss); ++ len += scnprintf(buf + len, buf_len - len, "bsr_trigger_across_bss_count = %u\n", ++ htt_stats_buf->bsr_trigger_across_bss); ++ len += scnprintf(buf + len, buf_len - len, "bsr_trigger_within_bss_count = %u\n", ++ htt_stats_buf->bsr_trigger_within_bss); ++ len += scnprintf(buf + len, buf_len - len, "MU_RTS_across_bss_count = %u\n", ++ htt_stats_buf->mu_rts_across_bss); ++ len += scnprintf(buf + len, buf_len - len, "MU_RTS_within_bss_count = %u\n", ++ htt_stats_buf->mu_rts_within_bss); ++ len += scnprintf(buf + len, buf_len - len, "UL_MUMIMO_trigger_across_bss_count = %u\n", ++ htt_stats_buf->ul_mumimo_trigger_across_bss); ++ len += scnprintf(buf + len, buf_len - len, "UL_MUMIMO_trigger_within_bss_count = %u\n", ++ htt_stats_buf->ul_mumimo_trigger_within_bss); ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "=================================================\n"); ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_pdev_stats_mlo_abort_tlv_v(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_pdev_stats_mlo_abort_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ u32 num_elements = tag_len >> 2; ++ ++ len += scnprintf(buf + len, buf_len - len, "HTT_TX_PDEV_STATS_MLO_ABORT_TLV_V:\n"); ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->mlo_abort_cnt, ++ "mlo_abort_cnt", ++ num_elements, "\n"); ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "=================================================\n"); ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_tx_pdev_stats_mlo_txop_abort_tlv_v(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_pdev_stats_mlo_txop_abort_tlv_v *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ u32 num_elements = tag_len >> 2; ++ ++ len += scnprintf(buf + len, buf_len - len, "HTT_TX_PDEV_STATS_MLO_TXOP_ABORT_TLV_V:\n"); ++ PRINT_ARRAY_TO_BUF(buf, len, ++ htt_stats_buf->mlo_txop_abort_cnt, ++ "mlo_txop_abort_cnt", ++ num_elements, "\n"); ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "=================================================\n"); ++ stats_req->buf_len = len; ++} ++ + static inline void htt_print_phy_counters_tlv(const void *tag_buf, + struct debug_htt_stats_req *stats_req) + { +@@ -7921,6 +8653,45 @@ static int ath12k_dbg_htt_ext_stats_pars + case HTT_STATS_ML_LINK_INFO_DETAILS_TAG: + htt_print_ml_link_info_stats_tlv(tag_buf, stats_req); + break; ++ case HTT_STATS_TX_PDEV_PPDU_DUR_TAG: ++ htt_print_tx_pdev_ppdu_dur_stats_tlv(tag_buf, stats_req); ++ break; ++ case HTT_STATS_RX_PDEV_PPDU_DUR_TAG: ++ htt_print_rx_pdev_ppdu_dur_stats_tlv(tag_buf, stats_req); ++ break; ++ case HTT_STATS_PDEV_SCHED_ALGO_OFDMA_STATS_TAG: ++ htt_print_pdev_sched_algo_ofdma_stats_tlv(tag_buf, stats_req); ++ break; ++ case HTT_STATS_LATENCY_PROF_CAL_STATS_TAG: ++ htt_print_latency_prof_cal_stats_tlv(tag_buf, stats_req); ++ break; ++ case HTT_STATS_TX_PDEV_AP_EDCA_PARAMS_STATS_TAG: ++ htt_print_tx_pdev_ap_edca_params_stats_tlv_v(tag_buf, stats_req); ++ break; ++ case HTT_STATS_TXBF_OFDMA_AX_STEER_MPDU_STATS_TAG: ++ htt_print_txbf_ofdma_ax_steer_mpdu_stats_tlv(tag_buf, stats_req); ++ break; ++ case HTT_STATS_TXBF_OFDMA_BE_STEER_MPDU_STATS_TAG: ++ htt_print_txbf_ofdma_be_steer_mpdu_stats_tlv(tag_buf, stats_req); ++ break; ++ case HTT_STATS_PEER_AX_OFDMA_STATS_TAG: ++ htt_print_peer_ax_ofdma_stats(tag_buf, stats_req); ++ break; ++ case HTT_STATS_TX_PDEV_MU_EDCA_PARAMS_STATS_TAG: ++ htt_print_tx_pdev_mu_edca_params_stats_tlv_v(tag_buf, stats_req); ++ break; ++ case HTT_STATS_ODD_PDEV_MANDATORY_TAG: ++ htt_print_odd_pdev_mandatory_tlv(tag_buf, stats_req); ++ break; ++ case HTT_STATS_PDEV_MBSSID_CTRL_FRAME_STATS_TAG: ++ htt_print_pdev_mbssid_ctrl_frame_stats_tlv(tag_buf, stats_req); ++ break; ++ case HTT_STATS_TX_PDEV_MLO_ABORT_TAG: ++ htt_print_tx_pdev_stats_mlo_abort_tlv_v(tag_buf, len, stats_req); ++ break; ++ case HTT_STATS_TX_PDEV_MLO_TXOP_ABORT_TAG: ++ htt_print_tx_pdev_stats_mlo_txop_abort_tlv_v(tag_buf, len, stats_req); ++ break; + default: + break; + } +--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h ++++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h +@@ -158,6 +158,9 @@ enum htt_tlv_tag_t { + HTT_STATS_RX_PDEV_BE_UL_MIMO_USER_STATS_TAG = 141, + HTT_STATS_RX_RING_STATS_TAG = 142, + HTT_STATS_RX_PDEV_BE_UL_TRIG_STATS_TAG = 143, ++ HTT_STATS_TX_PDEV_SAWF_RATE_STATS_TAG = 144, ++ HTT_STATS_STRM_GEN_MPDUS_TAG = 145, ++ HTT_STATS_STRM_GEN_MPDUS_DETAILS_TAG = 146, + HTT_STATS_TXBF_OFDMA_AX_NDPA_STATS_TAG = 147, + HTT_STATS_TXBF_OFDMA_AX_NDP_STATS_TAG = 148, + HTT_STATS_TXBF_OFDMA_AX_BRP_STATS_TAG = 149, +@@ -187,6 +190,9 @@ enum htt_tlv_tag_t { + HTT_STATS_TXBF_OFDMA_BE_STEER_MPDU_STATS_TAG = 173, + HTT_STATS_PEER_AX_OFDMA_STATS_TAG = 174, + HTT_STATS_TX_PDEV_MU_EDCA_PARAMS_STATS_TAG = 175, ++ HTT_STATS_PDEV_MBSSID_CTRL_FRAME_STATS_TAG = 176, ++ HTT_STATS_TX_PDEV_MLO_ABORT_TAG = 177, ++ HTT_STATS_TX_PDEV_MLO_TXOP_ABORT_TAG = 178, + HTT_STATS_MAX_TAG, + }; + +@@ -196,6 +202,8 @@ enum htt_tlv_tag_t { + #define HTT_TX_HWQ_MAX_CMD_RESULT_STATS 13 + #define HTT_TX_HWQ_MAX_CMD_STALL_STATS 5 + #define HTT_TX_HWQ_MAX_FES_RESULT_STATS 10 ++#define HTT_PDEV_STATS_PPDU_DUR_HIST_BINS 16 ++#define HTT_PDEV_STATS_PPDU_DUR_HIST_INTERVAL_US 250 + + enum htt_tx_pdev_underrun_enum { + HTT_STATS_TX_PDEV_NO_DATA_UNDERRUN = 0, +@@ -328,6 +336,18 @@ struct htt_tx_pdev_stats_flush_tlv_v { + u32 flush_errs[0]; /* HTT_TX_PDEV_MAX_FLUSH_REASON_STATS */ + }; + ++#define HTT_TX_PDEV_STATS_MLO_ABORT_TLV_SZ(_num_elems) (sizeof(u32) * (_num_elems)) ++/* NOTE: Variable length TLV, use length spec to infer array size */ ++struct htt_tx_pdev_stats_mlo_abort_tlv_v { ++ u32 mlo_abort_cnt[0]; /* HTT_TX_PDEV_MAX_MLO_ABORT_REASON_STATS */ ++}; ++ ++#define HTT_TX_PDEV_STATS_MLO_TXOP_ABORT_TLV_SZ(_num_elems) (sizeof(u32) * (_num_elems)) ++/* NOTE: Variable length TLV, use length spec to infer array size */ ++struct htt_tx_pdev_stats_mlo_txop_abort_tlv_v { ++ u32 mlo_txop_abort_cnt[0]; /* HTT_TX_PDEV_MAX_MLO_ABORT_REASON_STATS */ ++}; ++ + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_tx_pdev_stats_sifs_tlv_v { + u32 sifs_status[0]; /* HTT_TX_PDEV_MAX_SIFS_BURST_STATS */ +@@ -1946,6 +1966,21 @@ struct htt_rx_pdev_rate_ext_stats_tlv { + [HTT_RX_PDEV_STATS_NUM_BW_EXT_2_COUNTERS]; + }; + ++#define HTT_STATS_CMN_MAC_ID_M 0x000000ff ++#define HTT_STATS_CMN_MAC_ID_S 0 ++ ++#define HTT_STATS_CMN_MAC_ID_GET(_var) \ ++ (((_var) & HTT_STATS_CMN_MAC_ID_M) >> \ ++ HTT_STATS_CMN_MAC_ID_S) ++ ++#define HTT_STATS_CMN_MAC_ID_SET(_var, _val) \ ++ do { \ ++ HTT_CHECK_SET_VAL(HTT_STATS_CMN_MAC_ID, _val); \ ++ ((_var) |= ((_val) << HTT_STATS_CMN_MAC_ID_S)); \ ++ } while (0) ++ ++#define HTT_RX_UL_MAX_UPLINK_RSSI_TRACK 5 ++ + /* == RX PDEV/SOC STATS == */ + struct htt_rx_soc_fw_stats_tlv { + u32 fw_reo_ring_data_msdu; +@@ -2645,8 +2680,9 @@ struct htt_rx_pdev_ul_trigger_stats_tlv + [HTT_RX_PDEV_STATS_NUM_BW_COUNTERS]; + }; + +-#define HTT_LATENCY_PROFILE_MAX_HIST 3 +-#define HTT_STATS_MAX_PROF_STATS_NAME_LEN 32 ++#define HTT_LATENCY_PROFILE_MAX_HIST 3 ++#define HTT_STATS_MAX_PROF_STATS_NAME_LEN 32 ++#define HTT_INTERRUPTS_LATENCY_PROFILE_MAX_HIST 3 + struct htt_latency_prof_stats_tlv { + u32 print_header; + u8 latency_prof_name[HTT_STATS_MAX_PROF_STATS_NAME_LEN]; +@@ -2811,6 +2847,17 @@ struct htt_txbf_ofdma_ax_steer_stats_tlv + struct htt_txbf_ofdma_ax_steer_stats_elem_t ax_steer[1]; + }; + ++struct htt_txbf_ofdma_ax_steer_mpdu_stats_tlv { ++ /* 11AX HE OFDMA MPDUs tried in rbo steering */ ++ u32 ax_ofdma_rbo_steer_mpdus_tried; ++ /* 11AX HE OFDMA MPDUs failed in rbo steering */ ++ u32 ax_ofdma_rbo_steer_mpdus_failed; ++ /* 11AX HE OFDMA MPDUs tried in sifs steering */ ++ u32 ax_ofdma_sifs_steer_mpdus_tried; ++ /* 11AX HE OFDMA MPDUs failed in sifs steering */ ++ u32 ax_ofdma_sifs_steer_mpdus_failed; ++}; ++ + struct htt_txbf_ofdma_be_ndpa_stats_elem_t { + u32 be_ofdma_ndpa_queued; + u32 be_ofdma_ndpa_tried; +@@ -2865,6 +2912,17 @@ struct htt_txbf_ofdma_be_steer_stats_tlv + struct htt_txbf_ofdma_be_steer_stats_elem_t be_steer[1]; + }; + ++struct htt_txbf_ofdma_be_steer_mpdu_stats_tlv { ++ /* 11BE EHT OFDMA MPDUs tried in rbo steering */ ++ u32 be_ofdma_rbo_steer_mpdus_tried; ++ /* 11BE EHT OFDMA MPDUs failed in rbo steering */ ++ u32 be_ofdma_rbo_steer_mpdus_failed; ++ /* 11BE EHT OFDMA MPDUs tried in sifs steering */ ++ u32 be_ofdma_sifs_steer_mpdus_tried; ++ /* 11BE EHT OFDMA MPDUs failed in sifs steering */ ++ u32 be_ofdma_sifs_steer_mpdus_failed; ++}; ++ + struct htt_dmac_reset_stats_tlv { + u32 reset_count; + u32 reset_time_lo_ms; +@@ -2942,6 +3000,71 @@ struct htt_pdev_puncture_stats_tlv { + u32 num_subbands_used_cnt[HTT_PUNCTURE_STATS_MAX_SUBBAND_COUNT]; + }; + ++enum { ++ HTT_STATS_CAL_PROF_COLD_BOOT = 0, ++ HTT_STATS_CAL_PROF_FULL_CHAN_SWITCH = 1, ++ HTT_STATS_CAL_PROF_SCAN_CHAN_SWITCH = 2, ++ HTT_STATS_CAL_PROF_DPD_SPLIT_CAL = 3, ++ ++ HTT_STATS_MAX_PROF_CAL = 4, ++}; ++ ++#define HTT_STATS_MAX_CAL_IDX_CNT 8 ++struct htt_latency_prof_cal_stats_tlv { ++ ++ u8 latency_prof_name[HTT_STATS_MAX_PROF_CAL][HTT_STATS_MAX_PROF_STATS_NAME_LEN]; ++ ++ /** To verify whether prof cal is enabled or not */ ++ u32 enable; ++ ++ /** current pdev_id */ ++ u32 pdev_id; ++ ++ /** The cnt is incremented when each time the calindex takes place */ ++ u32 cnt[HTT_STATS_MAX_PROF_CAL][HTT_STATS_MAX_CAL_IDX_CNT]; ++ ++ /** Minimum time taken to complete the calibration - in us */ ++ u32 min[HTT_STATS_MAX_PROF_CAL][HTT_STATS_MAX_CAL_IDX_CNT]; ++ ++ /** Maximum time taken to complete the calibration -in us */ ++ u32 max[HTT_STATS_MAX_PROF_CAL][HTT_STATS_MAX_CAL_IDX_CNT]; ++ ++ /** Time taken by the cal for its final time execution - in us */ ++ u32 last[HTT_STATS_MAX_PROF_CAL][HTT_STATS_MAX_CAL_IDX_CNT]; ++ ++ /** Total time taken - in us */ ++ u32 tot[HTT_STATS_MAX_PROF_CAL][HTT_STATS_MAX_CAL_IDX_CNT]; ++ ++ /** hist_intvl - by default will be set to 2000 us */ ++ u32 hist_intvl[HTT_STATS_MAX_PROF_CAL][HTT_STATS_MAX_CAL_IDX_CNT]; ++ ++ /** ++ * If last is less than hist_intvl, then hist[0]++, ++ * If last is less than hist_intvl << 1, then hist[1]++, ++ * otherwise hist[2]++. ++ */ ++ u32 hist[HTT_STATS_MAX_PROF_CAL][HTT_STATS_MAX_CAL_IDX_CNT][HTT_INTERRUPTS_LATENCY_PROFILE_MAX_HIST]; ++ ++ /** Pf_last will log the current no of page faults */ ++ u32 pf_last[HTT_STATS_MAX_PROF_CAL][HTT_STATS_MAX_CAL_IDX_CNT]; ++ ++ /** Sum of all page faults happened */ ++ u32 pf_tot[HTT_STATS_MAX_PROF_CAL][HTT_STATS_MAX_CAL_IDX_CNT]; ++ ++ /** If pf_last > pf_max then pf_max = pf_last */ ++ u32 pf_max[HTT_STATS_MAX_PROF_CAL][HTT_STATS_MAX_CAL_IDX_CNT]; ++ ++ /** ++ * For each cal profile, only certain no of cal indices were invoked, ++ * this member will store what all the indices got invoked per each ++ * cal profile ++ */ ++ u32 enabledCalIdx[HTT_STATS_MAX_PROF_CAL][HTT_STATS_MAX_CAL_IDX_CNT]; ++ ++ /** No of indices invoked per each cal profile */ ++ u32 CalCnt[HTT_STATS_MAX_PROF_CAL]; ++}; ++ + #define HTT_ML_PEER_DETAILS_NUM_LINKS_M 0x00000003 + #define HTT_ML_PEER_DETAILS_NUM_LINKS_S 0 + #define HTT_ML_PEER_DETAILS_ML_PEER_ID_M 0x00003FFC +@@ -3369,6 +3492,135 @@ struct htt_ml_link_info_tlv { + u32 primary_tid_mask; + }; + ++struct htt_tx_pdev_ppdu_dur_stats_tlv { ++ /** Tx PPDU duration histogram **/ ++ u32 tx_ppdu_dur_hist[HTT_PDEV_STATS_PPDU_DUR_HIST_BINS]; ++ u32 tx_success_time_us_low; ++ u32 tx_success_time_us_high; ++ u32 tx_fail_time_us_low; ++ u32 tx_fail_time_us_high; ++ u32 pdev_up_time_us_low; ++ u32 pdev_up_time_us_high; ++}; ++ ++struct htt_rx_pdev_ppdu_dur_stats_tlv { ++ /** Tx PPDU duration histogram **/ ++ u32 rx_ppdu_dur_hist[HTT_PDEV_STATS_PPDU_DUR_HIST_BINS]; ++}; ++ ++#define HTT_TX_PDEV_SIFS_BURST_HIST_STATS 10 ++#define HTT_TX_PDEV_STATS_SIFS_HIST_TLV_SZ(_num_elems) (sizeof(u32) * (_num_elems)) ++ ++struct htt_pdev_mbssid_ctrl_frame_stats_tlv { ++ /** mac_id__word: ++ * BIT [ 7 : 0] :- mac_id ++ * Use the HTT_STATS_CMN_MAC_ID_GET,_SET macros to ++ * read/write this bitfield. ++ * BIT [31 : 8] :- reserved ++ */ ++ u32 mac_id__word; ++ u32 basic_trigger_across_bss; ++ u32 basic_trigger_within_bss; ++ u32 bsr_trigger_across_bss; ++ u32 bsr_trigger_within_bss; ++ u32 mu_rts_across_bss; ++ u32 mu_rts_within_bss; ++ u32 ul_mumimo_trigger_across_bss; ++ u32 ul_mumimo_trigger_within_bss; ++}; ++ ++struct htt_odd_mandatory_pdev_stats_tlv { ++ u32 hw_queued; ++ u32 hw_reaped; ++ u32 hw_paused; ++ u32 hw_filt; ++ u32 seq_posted; ++ u32 seq_completed; ++ u32 underrun; ++ u32 hw_flush; ++ u32 next_seq_posted_dsr; ++ u32 seq_posted_isr; ++ u32 mpdu_cnt_fcs_ok; ++ u32 mpdu_cnt_fcs_err; ++ u32 msdu_count_tqm; ++ u32 mpdu_count_tqm; ++ u32 mpdus_ack_failed; ++ u32 num_data_ppdus_tried_ota; ++ u32 ppdu_ok; ++ u32 num_total_ppdus_tried_ota; ++ u32 thermal_suspend_cnt; ++ u32 dfs_suspend_cnt; ++ u32 tx_abort_suspend_cnt; ++ u32 suspended_txq_mask; ++ u32 last_suspend_reason; ++ u32 seq_failed_queueing; ++ u32 seq_restarted; ++ u32 seq_txop_repost_stop; ++ u32 next_seq_cancel; ++ u32 seq_min_msdu_repost_stop; ++ u32 total_phy_err_cnt; ++ u32 ppdu_recvd; ++ u32 tcp_msdu_cnt; ++ u32 tcp_ack_msdu_cnt; ++ u32 udp_msdu_cnt; ++ u32 fw_tx_mgmt_subtype[HTT_STATS_SUBTYPE_MAX]; ++ u32 fw_rx_mgmt_subtype[HTT_STATS_SUBTYPE_MAX]; ++ u32 fw_ring_mpdu_err[HTT_RX_STATS_RXDMA_MAX_ERR]; ++ u32 urrn_stats[HTT_TX_PDEV_MAX_URRN_STATS]; ++ u32 sifs_status[HTT_TX_PDEV_MAX_SIFS_BURST_STATS]; ++ u32 sifs_hist_status[HTT_TX_PDEV_SIFS_BURST_HIST_STATS]; ++ u32 rx_suspend_cnt; ++ u32 rx_suspend_fail_cnt; ++ u32 rx_resume_cnt; ++ u32 rx_resume_fail_cnt; ++ u32 hwq_beacon_cmd_result[HTT_TX_HWQ_MAX_CMD_RESULT_STATS]; ++ u32 hwq_voice_cmd_result[HTT_TX_HWQ_MAX_CMD_RESULT_STATS]; ++ u32 hwq_video_cmd_result[HTT_TX_HWQ_MAX_CMD_RESULT_STATS]; ++ u32 hwq_best_effort_cmd_result[HTT_TX_HWQ_MAX_CMD_RESULT_STATS]; ++ u32 hwq_beacon_mpdu_tried_cnt; ++ u32 hwq_voice_mpdu_tried_cnt; ++ u32 hwq_video_mpdu_tried_cnt; ++ u32 hwq_best_effort_mpdu_tried_cnt; ++ u32 hwq_beacon_mpdu_queued_cnt; ++ u32 hwq_voice_mpdu_queued_cnt; ++ u32 hwq_video_mpdu_queued_cnt; ++ u32 hwq_best_effort_mpdu_queued_cnt; ++ u32 hwq_beacon_mpdu_ack_fail_cnt; ++ u32 hwq_voice_mpdu_ack_fail_cnt; ++ u32 hwq_video_mpdu_ack_fail_cnt; ++ u32 hwq_best_effort_mpdu_ack_fail_cnt; ++ u32 pdev_resets; ++ u32 phy_warm_reset; ++ u32 hwsch_reset_count; ++ u32 phy_warm_reset_ucode_trig; ++ u32 mac_cold_reset; ++ u32 mac_warm_reset; ++ u32 mac_warm_reset_restore_cal; ++ u32 phy_warm_reset_m3_ssr; ++ u32 fw_rx_rings_reset; ++ u32 tx_flush; ++ u32 hwsch_dev_reset_war; ++ u32 mac_cold_reset_restore_cal; ++ u32 mac_only_reset; ++ u32 mac_sfm_reset; ++ u32 tx_ldpc; /* Number of tx PPDUs with LDPC coding */ ++ u32 rx_ldpc; /* Number of rx PPDUs with LDPC coding */ ++ u32 gen_mpdu_end_reason[HTT_TX_TQM_MAX_GEN_MPDU_END_REASON]; ++ u32 list_mpdu_end_reason[HTT_TX_TQM_MAX_LIST_MPDU_END_REASON]; ++ u32 tx_mcs[HTT_TX_PDEV_STATS_NUM_MCS_COUNTERS + HTT_TX_PDEV_STATS_NUM_EXTRA_MCS_COUNTERS + HTT_TX_PDEV_STATS_NUM_EXTRA2_MCS_COUNTERS]; ++ u32 tx_nss[HTT_TX_PDEV_STATS_NUM_SPATIAL_STREAMS]; ++ u32 tx_bw[HTT_TX_PDEV_STATS_NUM_BW_COUNTERS]; ++ u32 half_tx_bw[HTT_TX_PDEV_STATS_NUM_BW_COUNTERS]; ++ u32 quarter_tx_bw[HTT_TX_PDEV_STATS_NUM_BW_COUNTERS]; ++ u32 tx_su_punctured_mode[HTT_TX_PDEV_STATS_NUM_PUNCTURED_MODE_COUNTERS]; ++ u32 rx_mcs[HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS + HTT_RX_PDEV_STATS_NUM_EXTRA_MCS_COUNTERS + HTT_RX_PDEV_STATS_NUM_EXTRA2_MCS_COUNTERS]; ++ u32 rx_nss[HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS]; ++ u32 rx_bw[HTT_RX_PDEV_STATS_NUM_BW_COUNTERS]; ++ u32 rx_stbc[HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS + HTT_RX_PDEV_STATS_NUM_EXTRA_MCS_COUNTERS + HTT_RX_PDEV_STATS_NUM_EXTRA2_MCS_COUNTERS]; ++ u32 rts_cnt; ++ u32 rts_success; ++}; ++ + struct htt_phy_counters_tlv { + u32 rx_ofdma_timing_err_cnt; + u32 rx_cck_fail_cnt; +@@ -3904,4 +4156,77 @@ struct htt_print_sta_ul_ofdma_stats_tlv + [HTT_STA_UL_OFDMA_NUM_BW_COUNTERS]; + }; + ++struct htt_tx_pdev_mu_edca_params_stats_tlv_v { ++ u32 relaxed_mu_edca[HTT_NUM_AC_WMM]; ++ u32 mumimo_aggressive_mu_edca[HTT_NUM_AC_WMM]; ++ u32 mumimo_relaxed_mu_edca[HTT_NUM_AC_WMM]; ++ u32 muofdma_aggressive_mu_edca[HTT_NUM_AC_WMM]; ++ u32 muofdma_relaxed_mu_edca[HTT_NUM_AC_WMM]; ++ u32 latency_mu_edca[HTT_NUM_AC_WMM]; ++ u32 psd_boost_mu_edca[HTT_NUM_AC_WMM]; ++}; ++ ++struct htt_tx_pdev_ap_edca_params_stats_tlv_v { ++ u32 ul_mumimo_less_aggressive[HTT_NUM_AC_WMM]; ++ u32 ul_mumimo_medium_aggressive[HTT_NUM_AC_WMM]; ++ u32 ul_mumimo_highly_aggressive[HTT_NUM_AC_WMM]; ++ u32 ul_mumimo_default_relaxed[HTT_NUM_AC_WMM]; ++ u32 ul_muofdma_less_aggressive[HTT_NUM_AC_WMM]; ++ u32 ul_muofdma_medium_aggressive[HTT_NUM_AC_WMM]; ++ u32 ul_muofdma_highly_aggressive[HTT_NUM_AC_WMM]; ++ u32 ul_muofdma_default_relaxed[HTT_NUM_AC_WMM]; ++}; ++ ++struct htt_peer_ax_ofdma_stats_tlv { ++ u32 peer_id; ++ u32 ax_basic_trig_count; ++ u32 ax_basic_trig_err; ++ u32 ax_bsr_trig_count; ++ u32 ax_bsr_trig_err; ++ u32 ax_mu_bar_trig_count; ++ u32 ax_mu_bar_trig_err; ++ u32 ax_basic_trig_with_per; ++ u32 ax_bsr_trig_with_per; ++ u32 ax_mu_bar_trig_with_per; ++ /* is_airtime_large_for_dl_ofdma, is_airtime_large_for_ul_ofdma ++ * These fields contain 2 counters each. The first element in each ++ * array counts how many times the airtime is short enough to use ++ * OFDMA, and the second element in each array counts how many times the ++ * airtime is too large to select OFDMA for the PPDUs involving the peer. ++ */ ++ u32 is_airtime_large_for_dl_ofdma[2]; ++ u32 is_airtime_large_for_ul_ofdma[2]; ++ /* Last updated value of DL and UL queue depths for each peer per AC */ ++ u32 last_updated_dl_qdepth[HTT_NUM_AC_WMM]; ++ u32 last_updated_ul_qdepth[HTT_NUM_AC_WMM]; ++}; ++ ++struct htt_pdev_sched_algo_ofdma_stats_tlv { ++ /** ++ * BIT [ 7 : 0] :- mac_id ++ * BIT [31 : 8] :- reserved ++ */ ++ union { ++ struct { ++ u32 mac_id:8, ++ reserved:24; ++ }; ++ u32 mac_id__word; ++ }; ++ u32 rate_based_dlofdma_enabled_count[HTT_NUM_AC_WMM]; ++ u32 rate_based_dlofdma_disabled_count[HTT_NUM_AC_WMM]; ++ u32 rate_based_dlofdma_probing_count[HTT_NUM_AC_WMM]; ++ u32 rate_based_dlofdma_monitoring_count[HTT_NUM_AC_WMM]; ++ u32 chan_acc_lat_based_dlofdma_enabled_count[HTT_NUM_AC_WMM]; ++ u32 chan_acc_lat_based_dlofdma_disabled_count[HTT_NUM_AC_WMM]; ++ u32 chan_acc_lat_based_dlofdma_monitoring_count[HTT_NUM_AC_WMM]; ++ u32 downgrade_to_dl_su_ru_alloc_fail[HTT_NUM_AC_WMM]; ++ u32 candidate_list_single_user_disable_ofdma[HTT_NUM_AC_WMM]; ++ u32 dl_cand_list_dropped_high_ul_qos_weight[HTT_NUM_AC_WMM]; ++ u32 ax_dlofdma_disabled_due_to_pipelining[HTT_NUM_AC_WMM]; ++ u32 dlofdma_disabled_su_only_eligible[HTT_NUM_AC_WMM]; ++ u32 dlofdma_disabled_consec_no_mpdus_tried[HTT_NUM_AC_WMM]; ++ u32 dlofdma_disabled_consec_no_mpdus_success[HTT_NUM_AC_WMM]; ++}; ++ + #endif diff --git a/feeds/ipq95xx/mac80211/patches/qca/751-ath12k-Fix-incorrect-value-of-rx_per_chain_rssi.patch b/feeds/ipq95xx/mac80211/patches/qca/751-ath12k-Fix-incorrect-value-of-rx_per_chain_rssi.patch new file mode 100644 index 000000000..999f22de5 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/751-ath12k-Fix-incorrect-value-of-rx_per_chain_rssi.patch @@ -0,0 +1,56 @@ +From c55d9569b3f006783a66897bd6d7d16702fefeb0 Mon Sep 17 00:00:00 2001 +From: Rajat Soni +Date: Tue, 28 Mar 2023 16:19:06 +0530 +Subject: [PATCH] ath12k: Fix incorrect value of rx_per_chain_rssi + +Currently while using PRINT_ARRAY_TO_BUF to print values +of rx_per_chain_rssi_ext_in_dbm, values are currupted +because rx_per_chain_rssi_ext_in_dbm variable requires %d +to be printed correctly. + +Using CHAIN_ARRAY_TO_BUF macro to print +rx_per_chain_rssi_ext_in_dbm. + +Signed-off-by: Rajat Soni +--- + .../net/wireless/ath/ath12k/debugfs_htt_stats.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c +index 01d7f67..fc4cbb9 100644 +--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c +@@ -3595,6 +3595,17 @@ fail: + kfree(rx_gi[i]); + } + ++#define CHAIN_ARRAY_TO_BUF(out, buflen, arr, len) \ ++ do { \ ++ int index = 0; u8 i; \ ++ for (i = 0; i < len; i++) { \ ++ index += scnprintf((out + buflen) + index, \ ++ (ATH12K_HTT_STATS_BUF_SIZE - buflen) - index, \ ++ " %u:%d,", i, arr[i]); \ ++ } \ ++ buflen += index; \ ++ } while (0) ++ + static inline void htt_print_rx_pdev_rate_ext_stats_tlv(const void *tag_buf, + struct debug_htt_stats_req *stats_req) + { +@@ -3625,9 +3636,10 @@ static inline void htt_print_rx_pdev_rate_ext_stats_tlv(const void *tag_buf, + for (j = 0; j < HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS; j++) { + len += scnprintf(buf + len, buf_len - len, + "\nrx_per_chain_rssi_ext_in_dbm[%u] = ", j); +- PRINT_ARRAY_TO_BUF(buf, len, ++ CHAIN_ARRAY_TO_BUF(buf, len, + htt_stats_buf->rx_per_chain_rssi_ext_in_dbm[j], +- NULL, HTT_RX_PDEV_STATS_NUM_BW_EXT_COUNTERS, "\n"); ++ HTT_RX_PDEV_STATS_NUM_BW_EXT_COUNTERS); ++ len += scnprintf(buf + len, buf_len - len, "\n"); + } + + PRINT_ARRAY_TO_BUF(buf, len, htt_stats_buf->rx_mcs_ext, +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/751-ath12k-Fixed-reboot-assert-issue-when-MLO-enabled.patch b/feeds/ipq95xx/mac80211/patches/qca/751-ath12k-Fixed-reboot-assert-issue-when-MLO-enabled.patch new file mode 100644 index 000000000..ecaa31632 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/751-ath12k-Fixed-reboot-assert-issue-when-MLO-enabled.patch @@ -0,0 +1,88 @@ +From 2b4e9b201abb859e8bf6717ce206d51efccf91e3 Mon Sep 17 00:00:00 2001 +From: Aishwarya R +Date: Tue, 28 Mar 2023 18:53:40 +0530 +Subject: [PATCH] ath12k: Fixed reboot assert issue when MLO enabled + +Facing firware assert issue as pci shutdown not +happening properly. ath12k_hif_power_down is responsible +for sending mhi_power_off state to firmware by this +it's power off one chip while the core does not stop +for other parallel running chips. calling core_deinit +during shutdown to fix this issue + +Signed-off-by: Aishwarya R +--- + drivers/net/wireless/ath/ath12k/pci.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -1434,7 +1434,9 @@ static void ath12k_pci_shutdown(struct p + { + struct ath12k_base *ab = pci_get_drvdata(pdev); + +- ath12k_pci_power_down(ab); ++ set_bit(ATH12K_FLAG_UNREGISTERING, &ab->ag->dev_flags); ++ cancel_work_sync(&ab->reset_work); ++ ath12k_core_deinit(ab); + } + + static __maybe_unused int ath12k_pci_pm_suspend(struct device *dev) +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -807,8 +807,6 @@ err_qmi_deinit: + + static void ath12k_core_soc_destroy(struct ath12k_base *ab) + { +- ath12k_dp_free(ab); +- ath12k_reg_free(ab); + ath12k_qmi_deinit_service(ab); + } + +@@ -1509,6 +1507,7 @@ int ath12k_core_qmi_firmware_ready(struc + goto err_dp_free; + } + ++ set_bit(ATH12K_FLAG_CORE_REGISTERED, &ab->dev_flags); + mutex_unlock(&ab->core_lock); + + if (ath12k_core_hw_group_start_ready(ag)) { +@@ -1537,6 +1536,7 @@ int ath12k_core_qmi_firmware_ready(struc + err_core_stop: + mutex_lock(&ab->core_lock); + ath12k_core_stop(ab); ++ clear_bit(ATH12K_FLAG_CORE_REGISTERED, &ab->dev_flags); + err_dp_free: + ath12k_dp_free(ab); + mutex_unlock(&ab->core_lock); +@@ -2116,6 +2116,8 @@ static void ath12k_core_hw_group_destroy + mutex_lock(&ab->core_lock); + if (test_bit(ATH12K_FLAG_HW_GROUP_ATTACHED, &ab->dev_flags)) { + clear_bit(ATH12K_FLAG_HW_GROUP_ATTACHED, &ab->dev_flags); ++ ath12k_reg_free(ab); ++ ath12k_dp_free(ab); + ath12k_core_soc_destroy(ab); + } + mutex_unlock(&ab->core_lock); +@@ -2158,6 +2160,7 @@ static void ath12k_core_hw_group_stop(st + ath12k_hif_irq_disable(ab); + ath12k_core_pdev_destroy(ab); + ath12k_core_stop(ab); ++ clear_bit(ATH12K_FLAG_CORE_REGISTERED, &ab->dev_flags); + + mutex_unlock(&ab->core_lock); + } +@@ -2208,7 +2211,12 @@ void ath12k_core_deinit(struct ath12k_ba + mutex_lock(&ab->core_lock); + + clear_bit(ATH12K_FLAG_HW_GROUP_ATTACHED, &ab->dev_flags); +- ath12k_core_stop(ab); ++ if (test_bit(ATH12K_FLAG_CORE_REGISTERED, &ab->dev_flags)) { ++ ath12k_core_stop(ab); ++ ath12k_reg_free(ab); ++ ath12k_dp_free(ab); ++ clear_bit(ATH12K_FLAG_CORE_REGISTERED, &ab->dev_flags); ++ } + ath12k_hif_power_down(ab); + ath12k_core_soc_destroy(ab); + diff --git a/feeds/ipq95xx/mac80211/patches/qca/751-mac80211-Get-valid-last_rate-for-rx_bitrate-from-cpu.patch b/feeds/ipq95xx/mac80211/patches/qca/751-mac80211-Get-valid-last_rate-for-rx_bitrate-from-cpu.patch new file mode 100644 index 000000000..a0a558c80 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/751-mac80211-Get-valid-last_rate-for-rx_bitrate-from-cpu.patch @@ -0,0 +1,73 @@ +From eac6bea547505fc6545014755e8e529fd804df42 Mon Sep 17 00:00:00 2001 +From: Maharaja Kennadyrajan +Date: Tue, 18 Apr 2023 14:41:05 +0530 +Subject: [PATCH 1/3] mac80211: Get valid last_rate for rx_bitrate from cpu + stats + +Get the valid last_rate from the cpu rx_stats while filling the +rx_bitrate in the station dump. This helps to avoid the missing +rx bitrate field in the iw station dump. + +Signed-off-by: Tamizh Chelvam Raja +Signed-off-by: Maharaja Kennadyrajan +--- + net/mac80211/sta_info.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c +index 4ad622f..36f5568 100644 +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -2265,7 +2265,7 @@ int sta_info_move_state(struct sta_info *sta, + } + + static struct ieee80211_sta_rx_stats * +-sta_get_last_rx_stats(struct sta_info *sta) ++sta_get_last_rx_stats(struct sta_info *sta, bool is_rx_bitrate) + { + struct ieee80211_sta_rx_stats *stats = &sta->deflink.rx_stats; + int cpu; +@@ -2278,8 +2278,13 @@ sta_get_last_rx_stats(struct sta_info *sta) + + for_each_possible_cpu(cpu) { + struct ieee80211_sta_rx_stats *cpustats; ++ u16 rate; + + cpustats = per_cpu_ptr(sta->deflink.pcpu_rx_stats, cpu); ++ rate = READ_ONCE(cpustats->last_rate); ++ ++ if(!cpustats->last_rx || (is_rx_bitrate && (rate == STA_STATS_RATE_INVALID))) ++ continue; + + if (time_after(cpustats->last_rx, stats->last_rx)) + stats = cpustats; +@@ -2350,7 +2355,7 @@ static void sta_stats_decode_rate(struct ieee80211_local *local, u32 rate, + + static int sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo) + { +- u16 rate = READ_ONCE(sta_get_last_rx_stats(sta)->last_rate); ++ u16 rate = READ_ONCE(sta_get_last_rx_stats(sta, true)->last_rate); + + if (rate == STA_STATS_RATE_INVALID) + return -EINVAL; +@@ -2550,7 +2555,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo, + struct ieee80211_sta_rx_stats *last_rxstats; + struct link_sta_info *link_sta = NULL; + +- last_rxstats = sta_get_last_rx_stats(sta); ++ last_rxstats = sta_get_last_rx_stats(sta, false); + + sinfo->generation = sdata->local->sta_generation; + +@@ -2794,7 +2799,7 @@ u32 sta_get_expected_throughput(struct sta_info *sta) + + unsigned long ieee80211_sta_last_active(struct sta_info *sta) + { +- struct ieee80211_sta_rx_stats *stats = sta_get_last_rx_stats(sta); ++ struct ieee80211_sta_rx_stats *stats = sta_get_last_rx_stats(sta, false); + + if (!sta->deflink.status_stats.last_ack || + time_after(stats->last_rx, sta->deflink.status_stats.last_ack)) +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/751-wifi-01-ath11k-Fix-missing-duplicate-beacons-in-PSC-channels.patch b/feeds/ipq95xx/mac80211/patches/qca/751-wifi-01-ath11k-Fix-missing-duplicate-beacons-in-PSC-channels.patch new file mode 100644 index 000000000..a4eb4df6f --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/751-wifi-01-ath11k-Fix-missing-duplicate-beacons-in-PSC-channels.patch @@ -0,0 +1,44 @@ +From c0ef213d0aae66143743055fccdee22440762fec Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Fri, 24 Mar 2023 22:43:43 +0530 +Subject: [PATCH 1/2] ath11k: Fix missing duplicate beacons in PSC channels + +When an 6GHz AP is brought up in a non PSC channels, +duplicate beacons and FD/Probe response are sent in +remaining 20MHz channels (including PSC channels) to +aid the clients in faster scanning of the AP. + +Currently, these duplicate beacons are not transmitted +by FW due to misconfiguration of the Tx vdev flag in +vdev start. FW expects VDEV_FLAGS_TRANSMIT_AP mbssid flag +in vdev start by default for a 6GHz AP irrespective of +single or multi bssid case since a 6GHz AP is expected to +be MBSS capable. + +Hence set VDEV_FLAGS_TRANSMIT_AP in mbssid flags arg of +Vdev start WMI command. + +Signed-off-by: Sriram R +--- + drivers/net/wireless/ath/ath11k/mac.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -7828,7 +7828,15 @@ static int ath11k_mac_setup_vdev_params_ + *tx_vdev_id = 0; + tx_vif = arvif->vif->bss_conf.mbssid_tx_vif; + if (!tx_vif) { +- *flags = WMI_HOST_VDEV_FLAGS_NON_MBSSID_AP; ++ /* Since a 6GHz AP is MBSS capable by default, FW expects ++ * Tx vdev flag to be set even in case of single bss case ++ * WMI_HOST_VDEV_FLAGS_NON_MBSSID_AP is to be used for non 6GHz ++ * cases ++ */ ++ if (ar->supports_6ghz && arvif->vif->type == NL80211_IFTYPE_AP) ++ *flags = WMI_HOST_VDEV_FLAGS_TRANSMIT_AP; ++ else ++ *flags = WMI_HOST_VDEV_FLAGS_NON_MBSSID_AP; + return 0; + } + diff --git a/feeds/ipq95xx/mac80211/patches/qca/751-wifi-02-ath12k-Fix-missing-duplicate-beacons-in-PSC-channels.patch b/feeds/ipq95xx/mac80211/patches/qca/751-wifi-02-ath12k-Fix-missing-duplicate-beacons-in-PSC-channels.patch new file mode 100644 index 000000000..0a9fa6c85 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/751-wifi-02-ath12k-Fix-missing-duplicate-beacons-in-PSC-channels.patch @@ -0,0 +1,44 @@ +From 114638e5b2cd1912145af0f9dc53ae683acf0e36 Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Fri, 24 Mar 2023 22:48:21 +0530 +Subject: [PATCH 2/2] ath12k: Fix missing duplicate beacons in PSC channels + +When an 6GHz AP is brought up in a non PSC channels, +duplicate beacons and FD/Probe response are sent in +remaining 20MHz channels (including PSC channels) to +aid the clients in faster scanning of the AP. + +Currently, these duplicate beacons are not transmitted +by FW due to misconfiguration of the Tx vdev flag in +vdev start. FW expects VDEV_FLAGS_TRANSMIT_AP mbssid flag +in vdev start by default for a 6GHz AP irrespective of +single or multi bssid case since a 6GHz AP is expected to +be MBSS capable. + +Hence set VDEV_FLAGS_TRANSMIT_AP in mbssid flags arg of +Vdev start WMI command. + +Signed-off-by: Sriram R +--- + drivers/net/wireless/ath/ath12k/mac.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -9173,7 +9173,15 @@ static int ath12k_mac_setup_vdev_params_ + *tx_vdev_id = 0; + tx_vif = link_conf->mbssid_tx_vif; + if (!tx_vif) { +- *flags = WMI_HOST_VDEV_FLAGS_NON_MBSSID_AP; ++ /* Since a 6GHz AP is MBSS capable by default, FW expects ++ * Tx vdev flag to be set even in case of single bss case ++ * WMI_HOST_VDEV_FLAGS_NON_MBSSID_AP is to be used for non 6GHz ++ * cases ++ */ ++ if (ar->supports_6ghz && arvif->ahvif->vif->type == NL80211_IFTYPE_AP) ++ *flags = WMI_HOST_VDEV_FLAGS_TRANSMIT_AP; ++ else ++ *flags = WMI_HOST_VDEV_FLAGS_NON_MBSSID_AP; + rcu_read_unlock(); + return 0; + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/751-wifi-ath12k-Enable-lock-less-tx-netdevice-flag.patch b/feeds/ipq95xx/mac80211/patches/qca/751-wifi-ath12k-Enable-lock-less-tx-netdevice-flag.patch new file mode 100644 index 000000000..99eaf230c --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/751-wifi-ath12k-Enable-lock-less-tx-netdevice-flag.patch @@ -0,0 +1,48 @@ +From 171174b661ba16b570e818688fa6398806844164 Mon Sep 17 00:00:00 2001 +From: P Praneesh +Date: Tue, 28 Mar 2023 22:06:15 +0530 +Subject: [PATCH 1/2] wifi: ath12k: Enable lock less tx netdevice flag + +dev_fast_xmit spends more CPU cylces on spinlock before calling +ieee80211_subif_start_xmit_8023. Avoid the lock by enabling +NETIF_F_LLTX flag in netdev feature flag. + +This lock less netdev tx provides 1GB throughput improvement +incase of 2link MLO. + +Signed-off-by: P Praneesh +--- + drivers/net/wireless/ath/ath12k/mac.c | 2 ++ + net/mac80211/ieee80211_i.h | 3 ++- + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index 9b6de75..505e224 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -14602,6 +14602,8 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah) + ieee80211_hw_set(hw, SUPPORTS_TID_CLASS_OFFLOAD); + ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID); + ++ hw->netdev_features |= NETIF_F_LLTX; ++ + if (ath12k_frame_mode == ATH12K_HW_TXRX_ETHERNET) { + ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD); + ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD); +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index c525789..1a83b70 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1973,7 +1973,8 @@ void ieee80211_color_change_finalize_work(struct work_struct *work); + /* interface handling */ + #define MAC80211_SUPPORTED_FEATURES_TX (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \ + NETIF_F_HW_CSUM | NETIF_F_SG | \ +- NETIF_F_HIGHDMA | NETIF_F_GSO_SOFTWARE) ++ NETIF_F_HIGHDMA | NETIF_F_GSO_SOFTWARE | \ ++ NETIF_F_LLTX) + #define MAC80211_SUPPORTED_FEATURES_RX (NETIF_F_RXCSUM) + #define MAC80211_SUPPORTED_FEATURES (MAC80211_SUPPORTED_FEATURES_TX | \ + MAC80211_SUPPORTED_FEATURES_RX) +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/751-wifi-ath12k-avoid-dma-sync-cpu-during-dp_tx.patch b/feeds/ipq95xx/mac80211/patches/qca/751-wifi-ath12k-avoid-dma-sync-cpu-during-dp_tx.patch new file mode 100644 index 000000000..c1da9b501 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/751-wifi-ath12k-avoid-dma-sync-cpu-during-dp_tx.patch @@ -0,0 +1,84 @@ +From 72d09c249a454f0007c744a46956316af0075f4e Mon Sep 17 00:00:00 2001 +From: P Praneesh +Date: Tue, 28 Mar 2023 22:14:37 +0530 +Subject: wifi: ath12k: avoid dma sync cpu during dp_tx + +dma_map_single performs sync cpu which consumes more CPU +cycles. Avoid this unnecessary dma_direct_map_page call +by passing DMA_ATTR_SKIP_CPU_SYNC parameter to dma_map_single_attrs. +Before this function call, dma range is cleaned to avoid stale +value in cache. + +With this change, observed 500MBPS improvement in 2 link MLO UDP DL. + +Signed-off-by: P Praneesh +--- + drivers/net/wireless/ath/ath12k/dp_tx.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -11,6 +11,7 @@ + #include "hw.h" + #include "peer.h" + #include ++#include + + static enum hal_tcl_encap_type + ath12k_dp_tx_get_encap_type(struct ath12k_link_vif *arvif, struct sk_buff *skb) +@@ -183,8 +184,10 @@ int ath12k_dp_tx_direct(struct ath12k_li + ab->soc_stats.tx_err.txbuf_na[ring_id]++; + return -ENOSPC; + } +- paddr = dma_map_single(dev, skb->data, 256, +- DMA_TO_DEVICE); ++ ++ dmac_clean_range_no_dsb(skb->data, skb->data + 256); ++ paddr = dma_map_single_attrs(dev, skb->data, 256, ++ DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); + if (unlikely(dma_mapping_error(dev, paddr))) { + atomic_inc(&ab->soc_stats.tx_err.misc_fail); + ath12k_warn(ab, "failed to DMA map data Tx buffer\n"); +@@ -564,8 +567,10 @@ ath12k_dp_tx_htt_tx_complete_buf(struct + struct ath12k_skb_cb *skb_cb; + struct ath12k *ar; + struct ieee80211_vif *vif; ++ unsigned long attrs = 0; + struct ath12k_vif *ahvif; + u8 flags = 0; ++ bool drop_disable = false; + + skb_cb = ATH12K_SKB_CB(msdu); + info = IEEE80211_SKB_CB(msdu); +@@ -579,17 +584,25 @@ ath12k_dp_tx_htt_tx_complete_buf(struct + if (atomic_dec_and_test(&ar->dp.num_tx_pending)) + wake_up(&ar->dp.tx_empty_waitq); + +- dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); ++ flags = skb_cb->flags; ++ drop_disable = (ab->stats_disable && !(flags & ATH12K_SKB_TX_STATUS)); ++ ++ /* If drop disable case, avoid cpu_sync since we are not passed ++ * the skb to mac80211 ++ */ ++ if (drop_disable) ++ attrs |= DMA_ATTR_SKIP_CPU_SYNC; ++ ++ dma_unmap_single_attrs(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE, attrs); ++ + if (unlikely(skb_ext_desc)) { +- dma_unmap_single(ab->dev, skb_cb->paddr_ext_desc, +- skb_ext_desc->len, DMA_TO_DEVICE); ++ dma_unmap_single_attrs(ab->dev, skb_cb->paddr_ext_desc, ++ skb_ext_desc->len, DMA_TO_DEVICE, attrs); + dev_kfree_skb_any(skb_ext_desc); + } + +- flags = skb_cb->flags; +- + /* Free skb here if stats is disabled */ +- if (ab->stats_disable && !(flags & ATH12K_SKB_TX_STATUS)) { ++ if (drop_disable) { + if (msdu->destructor) { + msdu->wifi_acked_valid = 1; + msdu->wifi_acked = ts->acked; diff --git a/feeds/ipq95xx/mac80211/patches/qca/752-wifi-ath12k-added-soc-stats-for-REO-Rx-data-path-deb.patch b/feeds/ipq95xx/mac80211/patches/qca/752-wifi-ath12k-added-soc-stats-for-REO-Rx-data-path-deb.patch new file mode 100644 index 000000000..5f28b6e4d --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/752-wifi-ath12k-added-soc-stats-for-REO-Rx-data-path-deb.patch @@ -0,0 +1,196 @@ +From 9780162653ef8571a88ea797169e103dd3dbf281 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Tue, 21 Mar 2023 10:33:33 +0530 +Subject: [PATCH] wifi: ath12k: added soc stats for REO Rx data path debug + +Enabled the counter for below statistics + 1. REO Rx chip wise + 2. REO Fast Rx chip wise + 3. REO Non Fast Rx chip wise + 4. WBM Release Src module wise error + +Chip wise data useful for MLO scenario. + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/core.h | 6 ++- + drivers/net/wireless/ath/ath12k/debugfs.c | 50 ++++++++++++++++++++--- + drivers/net/wireless/ath/ath12k/dp_rx.c | 17 ++++++-- + drivers/net/wireless/ath/ath12k/dp_tx.c | 2 +- + 4 files changed, 64 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h +index 8efd75fb257a..3a2a9082a489 100644 +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -1079,11 +1079,15 @@ struct ath12k_soc_dp_stats { + u32 mcast_enqueued; + u32 ucast_enqueued; + u32 mcast_reinject; +- u32 wbm_rel_source[HAL_WBM_REL_SRC_MODULE_MAX]; ++ u32 tx_wbm_rel_source[HAL_WBM_REL_SRC_MODULE_MAX]; + u32 tqm_rel_reason[MAX_TQM_RELEASE_REASON]; + u32 fw_tx_status[MAX_FW_TX_STATUS]; + u32 tx_enqueued[MAX_TCL_RING]; + u32 tx_completed[MAX_TCL_RING]; ++ u32 reo_rx[DP_REO_DST_RING_MAX] [ATH12K_MAX_SOCS]; ++ u32 fast_rx[DP_REO_DST_RING_MAX] [ATH12K_MAX_SOCS]; ++ u32 non_fast_rx[DP_REO_DST_RING_MAX] [ATH12K_MAX_SOCS]; ++ u32 rx_wbm_rel_source[HAL_WBM_REL_SRC_MODULE_MAX] [ATH12K_MAX_SOCS]; + struct ath12k_soc_dp_tx_err_stats tx_err; + struct ath12k_dp_ring_bp_stats bp_stats; + }; +diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c +index f117c435c524..6ed3e86008cf 100644 +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -1514,6 +1514,8 @@ static ssize_t ath12k_debugfs_dump_soc_dp_stats(struct file *file, + "Frame SN equal SSN", "PN check fail", "2k err", + "PN err", "Desc blocked"}; + ++ static const char *wbm_rel_src[HAL_WBM_REL_SRC_MODULE_MAX] = { ++ "TQM", "Rxdma", "Reo", "FW", "SW" }; + char *buf; + + buf = kzalloc(size, GFP_KERNEL); +@@ -1578,12 +1580,12 @@ static ssize_t ath12k_debugfs_dump_soc_dp_stats(struct file *file, + soc_stats->mcast_reinject); + + len += scnprintf(buf + len, size - len, +- "\nwbm_rel_source: 0:%u 1:%u 2:%u 3:%u 4:%u\n", +- soc_stats->wbm_rel_source[0], +- soc_stats->wbm_rel_source[1], +- soc_stats->wbm_rel_source[2], +- soc_stats->wbm_rel_source[3], +- soc_stats->wbm_rel_source[4]); ++ "\ntx_wbm_rel_source: 0:%u 1:%u 2:%u 3:%u 4:%u\n", ++ soc_stats->tx_wbm_rel_source[0], ++ soc_stats->tx_wbm_rel_source[1], ++ soc_stats->tx_wbm_rel_source[2], ++ soc_stats->tx_wbm_rel_source[3], ++ soc_stats->tx_wbm_rel_source[4]); + + len += scnprintf(buf + len, size - len, + "\ntqm_rel_reason: 0:%u 1:%u 2:%u 3:%u 4:%u 5:%u 6:%u 7:%u 8:%u 9:%u 10:%u 11:%u 12:%u 13:%u\n", +@@ -1626,6 +1628,42 @@ static ssize_t ath12k_debugfs_dump_soc_dp_stats(struct file *file, + soc_stats->tx_completed[2], + soc_stats->tx_completed[3]); + ++ len += scnprintf(buf + len, size - len, "\nREO Rx Received:\n"); ++ for (i = 0; i < DP_REO_DST_RING_MAX; i++) ++ len += scnprintf(buf + len, size - len, ++ "Ring%d: 0:%u\t1:%u\t2:%u\n", ++ i + 1, ++ soc_stats->reo_rx[i][0], ++ soc_stats->reo_rx[i][1], ++ soc_stats->reo_rx[i][2]); ++ ++ len += scnprintf(buf + len, size - len, "\nREO Fast Rx:\n"); ++ for (i = 0; i < DP_REO_DST_RING_MAX; i++) ++ len += scnprintf(buf + len, size - len, ++ "Ring%d: 0:%u\t1:%u\t2:%u\n", ++ i + 1, ++ soc_stats->fast_rx[i][0], ++ soc_stats->fast_rx[i][1], ++ soc_stats->fast_rx[i][2]); ++ ++ len += scnprintf(buf + len, size - len, "\nREO Non-Fast Rx:\n"); ++ for (i = 0; i < DP_REO_DST_RING_MAX; i++) ++ len += scnprintf(buf + len, size - len, ++ "Ring%d: 0:%u\t1:%u\t2:%u\n", ++ i + 1, ++ soc_stats->non_fast_rx[i][0], ++ soc_stats->non_fast_rx[i][1], ++ soc_stats->non_fast_rx[i][2]); ++ ++ len += scnprintf(buf + len, size - len, "\nRx WBM REL SRC Errors:\n"); ++ for (i = 0; i < HAL_WBM_REL_SRC_MODULE_MAX; i++) ++ len += scnprintf(buf + len, size - len, ++ "%s\t:0:%u\t1:%u\t2:%u\n", ++ wbm_rel_src[i], ++ soc_stats->rx_wbm_rel_source[i][0], ++ soc_stats->rx_wbm_rel_source[i][1], ++ soc_stats->rx_wbm_rel_source[i][2]); ++ + len += ath12k_debugfs_dump_soc_ring_bp_stats(ab, buf + len, size - len); + + if (len > size) +diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c +index 05501b0f03f5..5fa88738e02b 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -3230,8 +3230,12 @@ static void ath12k_dp_rx_process_received_packets(struct ath12k_base *ab, + continue; + } + +- if (!fast_rx) ++ if (!fast_rx) { ++ ab->soc_stats.non_fast_rx[ring_id][ar->ab->chip_id]++; + ath12k_dp_rx_deliver_msdu(ar, napi, msdu, &rx_info); ++ } else { ++ ab->soc_stats.fast_rx[ring_id][ar->ab->chip_id]++; ++ } + } + + rcu_read_unlock(); +@@ -3299,7 +3303,7 @@ try_again: + if (!ar) { + rcu_read_unlock(); + +- ab->soc_stats.hal_reo_error[dp->reo_dst_ring[ring_id].ring_id]++; ++ ab->soc_stats.hal_reo_error[ring_id]++; + ath12k_warn(ab, "Rx with invalid/inactive hw_link_id %d cookie 0x%x\n", hw_link_id, cookie); + + if (desc_info) { +@@ -3338,13 +3342,14 @@ try_again: + DMA_FROM_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); + + num_buffs_reaped[src_ab->chip_id]++; ++ ab->soc_stats.reo_rx[ring_id][src_ab->chip_id]++; + + push_reason = u32_get_bits(desc.info0, + HAL_REO_DEST_RING_INFO0_PUSH_REASON); + if (unlikely(push_reason != + HAL_REO_DEST_RING_PUSH_REASON_ROUTING_INSTRUCTION)) { + dev_kfree_skb_any(msdu); +- ab->soc_stats.hal_reo_error[dp->reo_dst_ring[ring_id].ring_id]++; ++ ab->soc_stats.hal_reo_error[ring_id]++; + continue; + } + +@@ -4537,6 +4542,7 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab, + int num_buffs_reaped = 0; + int total_num_buffs_reaped = 0; + struct ath12k_rx_desc_info *desc_info; ++ struct ath12k_soc_dp_stats *soc_stats = &ab->soc_stats; + int ret; + u8 src_link_id; + +@@ -4641,6 +4647,11 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab, + continue; + } + ++ rxcb = ATH12K_SKB_RXCB(msdu); ++ ++ if (rxcb->err_rel_src < HAL_WBM_REL_SRC_MODULE_MAX) ++ soc_stats->rx_wbm_rel_source[rxcb->err_rel_src][ar->ab->chip_id]++; ++ + ath12k_dp_rx_wbm_err(ar, napi, msdu, &msdu_list); + } + rcu_read_unlock(); +diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c +index ed20b568dbbe..8da71658e419 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -1029,7 +1029,7 @@ int ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id, + ath12k_dp_tx_release_txbuf(dp, tx_desc, tx_desc->pool_id); + /* Find the HAL_WBM_RELEASE_INFO0_REL_SRC_MODULE value */ + buf_rel_source = tx_status->info0 & HAL_WBM_RELEASE_INFO0_REL_SRC_MASK; +- ab->soc_stats.wbm_rel_source[buf_rel_source]++; ++ ab->soc_stats.tx_wbm_rel_source[buf_rel_source]++; + if (unlikely(buf_rel_source == HAL_WBM_REL_SRC_MODULE_FW)) { + ath12k_dp_tx_process_htt_tx_complete(ab, + (void *)tx_status, +-- +2.37.0 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/753-01-ath12k-sawf-update-the-TCL-Data-command-when-SKB-has.patch b/feeds/ipq95xx/mac80211/patches/qca/753-01-ath12k-sawf-update-the-TCL-Data-command-when-SKB-has.patch new file mode 100644 index 000000000..73e6057bd --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/753-01-ath12k-sawf-update-the-TCL-Data-command-when-SKB-has.patch @@ -0,0 +1,320 @@ +From 8ef5660948078fe9a17574412e232a5b199da054 Mon Sep 17 00:00:00 2001 +From: Ganesh Babu Jothiram +Date: Tue, 4 Apr 2023 14:54:54 +0530 +Subject: [PATCH 1/3] ath12k: sawf: update the TCL Data command when + datapacket's Skb->mark field has valid SAWF TAG. + +The SFE module fetch the five tuple information from datapacket while routing and +forward it to ECM. +ECM will check with SPM to find any matching rule available. +Once the rule is matched, ECM will allocate MSDUQ from the host driver and provide +MSDUQ ID, Peer Id and Service class ID(SVC_ID) details to SFE. SFE Then update packet Skb->mark +with follwing details, + +MSDUQ_ID BIT_MASK(5, 0) +PEER_ID BIT_MASK(16, 6) +SVC_ID BIT_MASK(17, 23) +SAWF_VALIDITY_TAG BIT_MASK(24, 31) + +SAWF_VALID_TAG_VALUE = 0xAA + +The TCL Data command will be updated with Flow override details +when the Skb->mark's SAWF_VALIDITY_TAG contains 0xAA + +Signed-off-by: Ganesh Babu Jothiram +--- + drivers/net/wireless/ath/ath12k/dp.h | 75 +++++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/dp_rx.c | 44 +++++++++++++++ + drivers/net/wireless/ath/ath12k/dp_tx.c | 66 +++++++++++++++++++++- + drivers/net/wireless/ath/ath12k/sawf.h | 15 +++++ + 4 files changed, 199 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h +index ceb4ff7..8091125 100644 +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -421,6 +421,11 @@ struct ath12k_dp { + #define HTT_TCL_META_DATA_GLOBAL_SEQ_NUM GENMASK(14, 3) + #define HTT_TX_MLO_MCAST_HOST_REINJECT_BASE_VDEV_ID 128 + ++/* Service Class meta data */ ++#define HTT_TCL_META_DATA_TYPE_SVC_ID_BASED 2 ++#define HTT_TCL_META_DATA_SAWF_SVC_ID GENMASK(10, 3) ++#define HTT_TCL_META_DATA_SAWF_TID_OVERRIDE BIT(12) ++ + /* HTT tx completion is overlayed in wbm_release_ring v3 version */ + #define HTT_TX_WBM_COMP_INFO0_STATUS GENMASK(16, 13) + #define HTT_TX_WBM_COMP_INFO1_REINJECT_REASON GENMASK(3, 0) +@@ -1313,6 +1318,7 @@ enum htt_t2h_msg_type { + HTT_T2H_MSG_TYPE_MLO_RX_PEER_UNMAP = 0x2a, + HTT_T2H_MSG_TYPE_PEER_MAP3 = 0x2b, + HTT_T2H_MSG_TYPE_VDEV_TXRX_STATS_PERIODIC_IND = 0x2c, ++ HTT_T2H_MSG_TYPE_SAWF_MSDUQ_INFO_IND = 0x2e, + }; + + #define HTT_TARGET_VERSION_MAJOR 3 +@@ -1449,6 +1455,75 @@ enum htt_backpressure_lmac_ringid { + HTT_SW_LMAC_RING_IDX_MAX, + }; + ++/* MSG_TYPE => HTT_T2H_SAWF_MSDUQ_INFO_IND ++ * ++ * @details ++ * When SAWF is enabled and a flow is mapped to a policy during the traffic ++ * flow if the flow is seen the associated service class is conveyed to the ++ * target via TCL Data Command. Target on the other hand internally creates the ++ * MSDUQ. Once the target creates the MSDUQ the target sends the information ++ * of the newly created MSDUQ and some other identifiers to uniquely identity ++ * the newly created MSDUQ ++ * ++ * |31 27| 24|23 16|15|14 11|10|9 8|7 4|3 0| ++ * |------------------------------+------------------------+--------------| ++ * | peer ID | HTT qtype | msg type | ++ * |---------------------------------+--------------+--+---+-------+------| ++ * | reserved |AST list index|FO|WC | HLOS | remap| ++ * | | | | | TID | TID | ++ * |---------------------+------------------------------------------------| ++ * | reserved1 | tgt_opaque_id | ++ * |---------------------+------------------------------------------------| ++ * ++ * Header fields: ++ * ++ * info0 - b'7:0 - msg_type: This will be set to ++ * 0x2e (HTT_T2H_SAWF_MSDUQ_INFO_IND) ++ * b'15:8 - HTT qtype ++ * b'31:16 - peer ID ++ * ++ * info1 - b'3:0 - remap TID, as assigned in firmware ++ * b'7:4 - HLOS TID, as sent by host in TCL Data Command ++ * hlos_tid : Common to Lithium and Beryllium ++ * b'9:8 - who_classify_info_sel (WC), as sent by host in ++ * TCL Data Command : Beryllium ++ * b10 - flow_override (FO), as sent by host in ++ * TCL Data Command: Beryllium ++ * b11:14 - ast_list_idx ++ * Array index into the list of extension AST entries ++ * (not the actual AST 16-bit index). ++ * The ast_list_idx is one-based, with the following ++ * range of values: ++ * - legacy targets supporting 16 user-defined ++ * MSDU queues: 1-2 ++ * - legacy targets supporting 48 user-defined ++ * MSDU queues: 1-6 ++ * - new targets: 0 (peer_id is used instead) ++ * Note that since ast_list_idx is one-based, ++ * the host will need to subtract 1 to use it as an ++ * index into a list of extension AST entries. ++ * b15:31 - reserved ++ * ++ * info2 - b'23:0 - tgt_opaque_id Opaque Tx flow number which is a ++ * unique MSDUQ id in firmware ++ * b'24:31 - reserved1 ++ */ ++ ++#define HTT_T2H_SAWF_MSDUQ_INFO_0_IND_HTT_QTYPE_ID GENMASK(15, 8) ++#define HTT_T2H_SAWF_MSDUQ_INFO_0_IND_PEER_ID GENMASK(31, 16) ++#define HTT_T2H_SAWF_MSDUQ_INFO_1_IND_REMAP_TID_ID GENMASK(3, 0) ++#define HTT_T2H_SAWF_MSDUQ_INFO_1_IND_HLOS_TID_ID GENMASK(7, 4) ++#define HTT_T2H_SAWF_MSDUQ_INFO_1_IND_WHO_CLSFY_INFO_SEL_ID GENMASK(9, 8) ++#define HTT_T2H_SAWF_MSDUQ_INFO_1_IND_FLOW_OVERRIDE_ID BIT(10) ++#define HTT_T2H_SAWF_MSDUQ_INFO_1_IND_AST_INDEX_ID GENMASK(14, 11) ++#define HTT_T2H_SAWF_MSDUQ_INFO_2_IND_TGT_OPAQUE_ID GENMASK(23, 0) ++ ++struct htt_t2h_sawf_info_ind { ++ __le32 info0; ++ __le32 info1; ++ __le32 info2; ++} __packed; ++ + /* ppdu stats + * + * @details +diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c +index 97d1475..3e40982 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -2091,6 +2091,47 @@ next: + } + } + ++static void ath12k_htt_sawf_info_ind_handler(struct ath12k_base *ab, ++ struct sk_buff *skb) ++{ ++ struct htt_t2h_sawf_info_ind *resp = (struct htt_t2h_sawf_info_ind *)skb->data; ++ u32 htt_qtype, remapped_tid, peer_id; ++ u32 hlos_tid, flow_or, ast_idx, who_cl, tgt_opaque_id; ++ ++ htt_qtype = u32_get_bits(__le32_to_cpu(resp->info0), ++ HTT_T2H_SAWF_MSDUQ_INFO_0_IND_HTT_QTYPE_ID); ++ peer_id = u32_get_bits(__le32_to_cpu(resp->info0), ++ HTT_T2H_SAWF_MSDUQ_INFO_0_IND_PEER_ID); ++ ++ remapped_tid = u32_get_bits(__le32_to_cpu(resp->info1), ++ HTT_T2H_SAWF_MSDUQ_INFO_1_IND_REMAP_TID_ID); ++ hlos_tid = u32_get_bits(__le32_to_cpu(resp->info1), ++ HTT_T2H_SAWF_MSDUQ_INFO_1_IND_HLOS_TID_ID); ++ who_cl = u32_get_bits(__le32_to_cpu(resp->info1), ++ HTT_T2H_SAWF_MSDUQ_INFO_1_IND_WHO_CLSFY_INFO_SEL_ID); ++ flow_or = u32_get_bits(__le32_to_cpu(resp->info1), ++ HTT_T2H_SAWF_MSDUQ_INFO_1_IND_FLOW_OVERRIDE_ID); ++ ast_idx = u32_get_bits(__le32_to_cpu(resp->info1), ++ HTT_T2H_SAWF_MSDUQ_INFO_1_IND_AST_INDEX_ID); ++ ++ tgt_opaque_id = u32_get_bits(__le32_to_cpu(resp->info2), ++ HTT_T2H_SAWF_MSDUQ_INFO_2_IND_TGT_OPAQUE_ID); ++ ++ ath12k_dbg(ab, ATH12K_DBG_SAWF, "Sawf Info ind:\n"); ++ ath12k_dbg(ab, ATH12K_DBG_SAWF, ++ "htt_qtype[0x%x]Peer_Id[0x%x]Remp_Tid[0x%x]Hlos_Tid[0x%x]\n", ++ htt_qtype, ++ peer_id, ++ remapped_tid, ++ hlos_tid); ++ ath12k_dbg(ab, ATH12K_DBG_SAWF, ++ "who_cl[0x%x]flow_or[0x%x]Ast[0x%x]Op[0x%x]\n", ++ who_cl, ++ flow_or, ++ ast_idx, ++ tgt_opaque_id); ++} ++ + void ath12k_dp_htt_htc_t2h_msg_handler(struct ath12k_base *ab, + struct sk_buff *skb) + { +@@ -2188,6 +2229,9 @@ void ath12k_dp_htt_htc_t2h_msg_handler(struct ath12k_base *ab, + case HTT_T2H_MSG_TYPE_VDEV_TXRX_STATS_PERIODIC_IND: + ath12k_htt_vdev_txrx_stats_handler(ab, skb); + break; ++ case HTT_T2H_MSG_TYPE_SAWF_MSDUQ_INFO_IND: ++ ath12k_htt_sawf_info_ind_handler(ab, skb); ++ break; + default: + ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "dp_htt event %d not handled\n", + type); +diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c +index 12e4f7d..7ff41b4 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -13,6 +13,37 @@ + #include + #include + ++static inline u32 ath12k_sawf_get_tcl_metadata_update(u32 sk_buff_mark) ++{ ++ u32 tcl_metadata = 0; ++ u32 svc_id = u32_get_bits(sk_buff_mark, SAWF_SERVICE_CLASS_ID); ++ ++ tcl_metadata = u32_encode_bits(HTT_TCL_META_DATA_TYPE_SVC_ID_BASED, ++ HTT_TCL_META_DATA_TYPE_MISSION) | ++ u32_encode_bits(1, HTT_TCL_META_DATA_SAWF_TID_OVERRIDE) | ++ u32_encode_bits(svc_id - 1, HTT_TCL_META_DATA_SAWF_SVC_ID); ++ return tcl_metadata; ++} ++ ++static inline u32 ath12k_sawf_get_tcl_cmd_info3_update(u32 msduq_id) ++{ ++ u32 tid, flow_override, who_classify_info_sel, update = 0; ++ ++ tid = u32_get_bits(msduq_id, TID_FROM_Q_ID); ++ flow_override = u32_get_bits(msduq_id, FLOW_OVERRIDE_FROM_Q_ID); ++ who_classify_info_sel = u32_get_bits(msduq_id, WHO_CLASSIFY_INFO_FROM_Q_ID); ++ ++ update = u32_encode_bits(tid, HAL_TCL_DATA_CMD_INFO3_TID) | ++ u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO3_TID_OVERWRITE) | ++ u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO3_FLOW_OVERRIDE_EN) | ++ u32_encode_bits(who_classify_info_sel, ++ HAL_TCL_DATA_CMD_INFO3_CLASSIFY_INFO_SEL) | ++ u32_encode_bits(flow_override, ++ HAL_TCL_DATA_CMD_INFO3_FLOW_OVERRIDE); ++ ++ return update; ++} ++ + static enum hal_tcl_encap_type + ath12k_dp_tx_get_encap_type(struct ath12k_link_vif *arvif, struct sk_buff *skb) + { +@@ -234,6 +265,19 @@ int ath12k_dp_tx_direct(struct ath12k_link_vif *arvif, struct sk_buff *skb) + tcl_desc.info3 = arvif->desc.info3; + tcl_desc.info4 = arvif->desc.info4; + tcl_desc.info5 = 0; ++ /* SAWF */ ++ if (u32_get_bits(skb->mark, SAWF_TAG_ID) == SAWF_VALID_TAG) { ++ u32 msduq_id = u32_get_bits(skb->mark, SAWF_MSDUQ_ID); ++ ++ if (msduq_id < (ab->max_msduq_per_tid * ATH12K_SAWF_MAX_TID_SUPPORT)) { ++ u32 meta_data_flags; ++ tcl_desc.info3 |= ath12k_sawf_get_tcl_cmd_info3_update(msduq_id); ++ meta_data_flags = ++ ath12k_sawf_get_tcl_metadata_update(skb->mark); ++ tcl_desc.info1 = u32_encode_bits(meta_data_flags, ++ HAL_TCL_DATA_CMD_INFO1_CMD_NUM); ++ } ++ } + memcpy(hal_tcl_desc, &tcl_desc, sizeof(tcl_desc)); + dsb(st); + ath12k_hal_srng_access_umac_src_ring_end_nolock(tcl_ring); +@@ -322,7 +366,17 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif, + ti.meta_data_flags = arvif->tcl_metadata; + } + +- if (gsn_valid) { ++ /* TCL Meta data flags are shared for both SAWF and Global Seq Number updates. ++ * SAWF and Global Seq Number are mutually exclusive. ++ * Global Seq Number - Multicast, SAWF - Unicast ++ */ ++ if (u32_get_bits(skb->mark, SAWF_TAG_ID) == SAWF_VALID_TAG) { ++ u32 msduq_id = u32_get_bits(skb->mark, SAWF_MSDUQ_ID); ++ if (msduq_id < (ab->max_msduq_per_tid * ATH12K_SAWF_MAX_TID_SUPPORT)) { ++ ti.meta_data_flags = ++ ath12k_sawf_get_tcl_metadata_update(skb->mark); ++ } ++ } else if (gsn_valid) { + ti.meta_data_flags = u32_encode_bits(HTT_TCL_META_DATA_TYPE_GLOBAL_SEQ_NUM, + HTT_TCL_META_DATA_TYPE_MISSION) | + u32_encode_bits(mcbc_gsn, HTT_TCL_META_DATA_GLOBAL_SEQ_NUM); +@@ -491,6 +545,16 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif, + tcl_cmd->info4 = arvif->desc.info4; + tcl_cmd->info5 = 0; + ++ /* SAWF */ ++ if (u32_get_bits(skb->mark, SAWF_TAG_ID) == SAWF_VALID_TAG) { ++ u32 msduq_id = u32_get_bits(skb->mark, SAWF_MSDUQ_ID); ++ ++ if (msduq_id < (ab->max_msduq_per_tid * ATH12K_SAWF_MAX_TID_SUPPORT)) { ++ tcl_cmd->info3 |= ++ ath12k_sawf_get_tcl_cmd_info3_update(msduq_id); ++ } ++ } ++ + ath12k_hal_srng_access_umac_src_ring_end_nolock(tcl_ring); + + ath12k_dbg_dump(ab, ATH12K_DBG_DP_TX, NULL, "dp tx msdu: ", +diff --git a/drivers/net/wireless/ath/ath12k/sawf.h b/drivers/net/wireless/ath/ath12k/sawf.h +index 162ba5a..35b7f86 100644 +--- a/drivers/net/wireless/ath/ath12k/sawf.h ++++ b/drivers/net/wireless/ath/ath12k/sawf.h +@@ -9,6 +9,21 @@ + #define ATH12K_SAWF_SVC_CLASS_MIN 1 + #define ATH12K_SAWF_SVC_CLASS_MAX 128 + #define ATH12K_MAX_APP_NAME 64 ++#define ATH12K_SAWF_MAX_TID_SUPPORT 8 ++/** ++ ** SAWF_metadata related information. ++ **/ ++#define SAWF_VALID_TAG 0xAA ++ ++/* Skb mark for SAWF */ ++#define SAWF_MSDUQ_ID GENMASK(5, 0) ++#define SAWF_PEER_ID GENMASK(15, 6) ++#define SAWF_SERVICE_CLASS_ID GENMASK(23, 16) ++#define SAWF_TAG_ID GENMASK(31, 24) ++ ++#define TID_FROM_Q_ID GENMASK(2, 0) ++#define FLOW_OVERRIDE_FROM_Q_ID BIT(3) ++#define WHO_CLASSIFY_INFO_FROM_Q_ID GENMASK(5, 4) + + /* + * Min throughput limit 0 - 10 Gb/s +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/753-01-cfg80211-Fix-firmware-assert-during-set-bitrate-comm.patch b/feeds/ipq95xx/mac80211/patches/qca/753-01-cfg80211-Fix-firmware-assert-during-set-bitrate-comm.patch new file mode 100644 index 000000000..dad2b6fc8 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/753-01-cfg80211-Fix-firmware-assert-during-set-bitrate-comm.patch @@ -0,0 +1,42 @@ +From 004a04c391c7ec97b027d569f8b12c036451f6db Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Tue, 18 Apr 2023 11:55:42 +0530 +Subject: [PATCH] cfg80211: Fix firmware assert during set bitrate command + +eht_set_mcs_mask/he_set_mcs_mask function update mcs mask according +to user input value. When we are running set bitrate command without +giving MCS NSS in this condition mcs mask value is zero due to this +driver not able to find correct phymode and trigger firmware assert. + +Fix this issue by returning default value of mcs_mask (which is filling +in nl80211_parse_tx_bitrate_mask function) for 6G band while running +following command: + iw dev wlanx set bitrates eht-mcs-6/he-mcs-6 + +Signed-off-by: Aaradhana Sahu +--- + net/wireless/nl80211.c | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -5465,6 +5465,7 @@ static int eht_build_mcs_mask(struct gen + struct wireless_dev *wdev = dev->ieee80211_ptr; + u8 mcs_nss_len, nss, mcs_7 = 0, mcs_9 = 0, mcs_11 = 0, mcs_13 = 0; + bool mcs_14 = false, mcs_15 = false; ++ unsigned int link_id = nl80211_link_id(info->attrs); + + mcs_nss_len = ieee80211_eht_mcs_nss_size(&he_cap->he_cap_elem, + &eht_cap->eht_cap_elem); +@@ -5491,7 +5492,10 @@ static int eht_build_mcs_mask(struct gen + + switch (wdev->iftype) { + case NL80211_IFTYPE_AP: +- width = wdev->u.ap.preset_chandef.width; ++ if (wdev->valid_links) ++ width = wdev->links[link_id].ap.chandef.width; ++ else ++ width = wdev->u.ap.preset_chandef.width; + break; + case NL80211_IFTYPE_MESH_POINT: + width = wdev->u.mesh.chandef.width; diff --git a/feeds/ipq95xx/mac80211/patches/qca/753-02-ath12k-add-link_sta-in-ath12k_mac_validate_fixed_rat.patch b/feeds/ipq95xx/mac80211/patches/qca/753-02-ath12k-add-link_sta-in-ath12k_mac_validate_fixed_rat.patch new file mode 100644 index 000000000..8f357a223 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/753-02-ath12k-add-link_sta-in-ath12k_mac_validate_fixed_rat.patch @@ -0,0 +1,92 @@ +From 142bb07525786d2ed1ab40c093884d3399d575f0 Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Tue, 18 Apr 2023 11:41:41 +0530 +Subject: [PATCH] ath12k: add link_sta in + ath12k_mac_validate_fixed_rate_settings + +Currently, we are using legacy sta in ath12k_mac_validate_fixed_rate_setting +which is not working in multi-link operation. + +So add link_sta in ath12k_mac_validate_fixed_rate_setting. + +Signed-off-by: Aaradhana Sahu +--- + drivers/net/wireless/ath/ath12k/mac.c | 29 ++++++++++++++++++--------- + 1 file changed, 19 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index 80e5fa3..8382d1c 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -12936,7 +12936,8 @@ static void ath12k_mac_disable_peer_fixed_rate(void *data, + + static bool + ath12k_mac_validate_fixed_rate_settings(struct ath12k *ar, enum nl80211_band band, +- const struct cfg80211_bitrate_mask *mask) ++ const struct cfg80211_bitrate_mask *mask, ++ unsigned int link_id) + { + bool eht_fixed_rate = false, he_fixed_rate = false, vht_fixed_rate = false; + bool he_ul_fixed_rate = false; +@@ -12944,6 +12945,7 @@ ath12k_mac_validate_fixed_rate_settings(struct ath12k *ar, enum nl80211_band ban + const u16 *vht_mcs_mask, *he_mcs_mask, *eht_mcs_mask, *he_ul_mcs_mask; + u8 vht_nss, he_nss, eht_nss, he_ul_nss; + bool ret = true; ++ struct ieee80211_link_sta *link_sta; + + vht_mcs_mask = mask->control[band].vht_mcs; + he_mcs_mask = mask->control[band].he_mcs; +@@ -12974,26 +12976,33 @@ ath12k_mac_validate_fixed_rate_settings(struct ath12k *ar, enum nl80211_band ban + spin_lock_bh(&ar->ab->base_lock); + list_for_each_entry_safe(peer, tmp, &ar->ab->peers, list) { + if (peer->sta) { +- if (vht_fixed_rate && (!peer->sta->deflink.vht_cap.vht_supported || +- peer->sta->deflink.rx_nss < vht_nss)) { ++ 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 && (!peer->sta->deflink.he_cap.has_he || +- peer->sta->deflink.rx_nss < he_nss)) { ++ if (he_fixed_rate && (!link_sta->he_cap.has_he || ++ link_sta->rx_nss < he_nss)) { + ret = false; + goto exit; + } +- if (eht_fixed_rate && (!peer->sta->deflink.eht_cap.has_eht || +- peer->sta->deflink.rx_nss < eht_nss)) { ++ if (eht_fixed_rate && (!link_sta->eht_cap.has_eht || ++ link_sta->rx_nss < eht_nss)) { + ret = false; + goto exit; + } + /* TODO: + * check when UL is valid + */ +- if (he_ul_fixed_rate && (!peer->sta->deflink.he_cap.has_he || +- peer->sta->deflink.rx_nss < he_ul_nss)) { ++ if (he_ul_fixed_rate && (!link_sta->he_cap.has_he || ++ link_sta->rx_nss < he_ul_nss)) { + ret = false; + goto exit; + } +@@ -13197,7 +13206,7 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, + goto out; + } + +- if (!ath12k_mac_validate_fixed_rate_settings(ar, band, mask)) ++ if (!ath12k_mac_validate_fixed_rate_settings(ar, band, mask, link_id)) + ath12k_warn(ar->ab, + "could not update fixed rate settings to all peers due to mcs/nss incompaitiblity\n"); + nss = min_t(u32, ar->num_tx_chains, +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/753-02-ath12k-sawf-add-callback-operation-for-dynamic-msduq.patch b/feeds/ipq95xx/mac80211/patches/qca/753-02-ath12k-sawf-add-callback-operation-for-dynamic-msduq.patch new file mode 100644 index 000000000..493e7680c --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/753-02-ath12k-sawf-add-callback-operation-for-dynamic-msduq.patch @@ -0,0 +1,534 @@ +From 1f85424185149a7db850e77644c35959ba0e0889 Mon Sep 17 00:00:00 2001 +From: Ganesh Babu Jothiram +Date: Tue, 4 Apr 2023 15:12:23 +0530 +Subject: [PATCH 2/3] ath12k: sawf: add callback operation for dynamic msduq + allocation. + +Host driver supports the call back to allocate a MSDUQ per peer and map with service +class details i.e service class ID. The MSDUQ allocation is peer specific and +mapped with a service class ID. + +Host manages the allocation of user defined MSDUQs based on the detaild of number of user +defined MSDUQ support from firmware during bootup. + +The ECM module received with five tuple inforation from SFE post routing. +ECM will check with SPM, to find any matching rule with the five tuple inforation. +Once the matching found, ECM will call to host driver to allocate a MSDUQ provided +with service class ID, peer mac addr. + +Signed-off-by: Ganesh Babu Jothiram +--- + drivers/net/wireless/ath/ath12k/peer.h | 2 + + drivers/net/wireless/ath/ath12k/sawf.c | 262 +++++++++++++++++++++-- + drivers/net/wireless/ath/ath12k/sawf.h | 34 +++ + drivers/net/wireless/ath/ath12k/vendor.c | 19 +- + 4 files changed, 291 insertions(+), 26 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/peer.h ++++ b/drivers/net/wireless/ath/ath12k/peer.h +@@ -8,6 +8,7 @@ + #define ATH12K_PEER_H + + #include "dp_rx.h" ++#include "sawf.h" + + struct ppdu_user_delayba { + u8 reserved0; +@@ -30,6 +31,7 @@ struct ath12k_peer { + struct list_head list; + struct ieee80211_sta *sta; + struct ieee80211_vif *vif; ++ struct ath12k_sawf_peer_ctx sawf_ctx_peer; + int vdev_id; + u8 addr[ETH_ALEN]; + int peer_id; +--- a/drivers/net/wireless/ath/ath12k/sawf.c ++++ b/drivers/net/wireless/ath/ath12k/sawf.c +@@ -7,7 +7,9 @@ + #include "debug.h" + #include "wmi.h" + #include "sawf.h" ++#include "peer.h" + #include ++#include + + #define SVC_INDEX(svc_id) svc_id - 1 + +@@ -15,6 +17,10 @@ bool ath12k_sawf_enable; + module_param_named(sawf, ath12k_sawf_enable, bool, 0444); + MODULE_PARM_DESC(sawf, "Enable SAWF feature (Default: false)"); + ++static struct ecm_classifier_emesh_sawf_callbacks ecm_wifi_sawf_callback = { ++ .update_service_id_get_msduq = ath12k_sawf_get_msduq, ++}; ++ + static struct ath12k_sawf_ctx *sawf_ctx; + + void ath12k_sawf_init(struct ath12k_base *ab) +@@ -38,6 +44,11 @@ void ath12k_sawf_init(struct ath12k_base + return; + } + ++ if (ecm_classifier_emesh_sawf_msduq_callback_register(&ecm_wifi_sawf_callback)) ++ ath12k_err(NULL, "ECM msduq cb reg fail\n"); ++ else ++ ath12k_dbg(ab, ATH12K_DBG_SAWF, "ECM msduq callback register success\n"); ++ + ath12k_info(NULL, "SAWF context initialized\n"); + } + +@@ -55,6 +66,9 @@ void ath12k_sawf_deinit(struct ath12k_ba + if (!sawf_ctx) + return; + ++ ecm_classifier_emesh_sawf_msduq_callback_unregister(); ++ ath12k_dbg(ab, ATH12K_DBG_SAWF, "ECM msduq callback unregister success\n"); ++ + kfree(sawf_ctx); + sawf_ctx = NULL; + ath12k_info(NULL, "SAWF context freed\n"); +@@ -80,7 +94,6 @@ void ath12k_update_svc_class(struct ath1 + return; + } + +- spin_lock_bh(&sawf_ctx->sawf_svc_lock); + new_param = &sawf_ctx->svc_classes[SVC_INDEX(sawf_params->svc_id)]; + new_param->svc_id = sawf_params->svc_id; + memcpy(new_param->app_name, sawf_params->app_name, ATH12K_MAX_APP_NAME); +@@ -94,7 +107,6 @@ void ath12k_update_svc_class(struct ath1 + new_param->tid = sawf_params->tid; + new_param->msdu_rate_loss = sawf_params->msdu_rate_loss; + new_param->configured = sawf_params->configured; +- spin_unlock_bh(&sawf_ctx->sawf_svc_lock); + } + + bool ath12k_validate_sawf_param(struct ath12k_sawf_svc_params *params) +@@ -183,13 +195,10 @@ bool ath12k_svc_id_configured(u8 svc_id) + return false; + } + +- spin_lock_bh(&sawf_ctx->sawf_svc_lock); +- if (sawf_ctx->svc_classes[SVC_INDEX(svc_id)].configured) { +- spin_unlock_bh(&sawf_ctx->sawf_svc_lock); ++ lockdep_assert_held(&sawf_ctx->sawf_svc_lock); ++ if (sawf_ctx->svc_classes[SVC_INDEX(svc_id)].configured) + return true; +- } + +- spin_unlock_bh(&sawf_ctx->sawf_svc_lock); + return false; + } + +@@ -202,10 +211,9 @@ int ath12k_get_tid(u8 svc_id) + return -ENODATA; + } + ++ lockdep_assert_held(&sawf_ctx->sawf_svc_lock); + if (ath12k_svc_id_configured(svc_id)) { +- spin_lock_bh(&sawf_ctx->sawf_svc_lock); + tid = sawf_ctx->svc_classes[SVC_INDEX(svc_id)].tid; +- spin_unlock_bh(&sawf_ctx->sawf_svc_lock); + return tid; + } + +@@ -235,10 +243,8 @@ bool ath12k_disable_svc_class(u8 svc_id) + return false; + } + +- spin_lock_bh(&sawf_ctx->sawf_svc_lock); + sawf_svc_class = &sawf_ctx->svc_classes[SVC_INDEX(svc_id)]; + memset(sawf_svc_class, 0, sizeof(*sawf_svc_class)); +- spin_unlock_bh(&sawf_ctx->sawf_svc_lock); + + return true; + } +@@ -333,6 +339,10 @@ static u32 ath12k_sawf_tid_calc(struct a + int ath12k_create_send_svc_params(struct ath12k_sawf_svc_params *param) + { + int ret = 0; ++ if (!sawf_ctx) { ++ ath12k_err(NULL, "SAWF context unavailable\n"); ++ return -EINVAL; ++ } + + if (!ath12k_svc_id_valid(param->svc_id)) { + ath12k_warn(NULL, "svc_id: %u is invalid, Service ID range: %d - %d\n", +@@ -341,13 +351,16 @@ int ath12k_create_send_svc_params(struct + return -EINVAL; + } + ++ spin_lock_bh(&sawf_ctx->sawf_svc_lock); + if (ath12k_svc_id_configured(param->svc_id)) { + if (ath12k_get_tid(param->svc_id) != param->tid) { + ath12k_err(NULL, "Updating service class failed for TID ID:%u", + param->tid); ++ spin_unlock_bh(&sawf_ctx->sawf_svc_lock); + return -EINVAL; + } + } ++ spin_unlock_bh(&sawf_ctx->sawf_svc_lock); + + if (param->tid == SAWF_SVC_PARAM_DEFAULT_TID) + param->tid = ath12k_sawf_tid_calc(param); +@@ -358,36 +371,247 @@ int ath12k_create_send_svc_params(struct + } + + ret = ath12k_send_sawf_configs_soc(param); +- if (ret) { ++ if (!ret) { ++ param->configured = true; ++ spin_lock_bh(&sawf_ctx->sawf_svc_lock); ++ ath12k_update_svc_class(param); ++ spin_unlock_bh(&sawf_ctx->sawf_svc_lock); ++ } else { + ath12k_err(NULL, "service class configuration failed\n"); +- return ret; + } + +- param->configured = true; +- ath12k_update_svc_class(param); + return ret; + } + + int ath12k_sawf_disable_config(u8 svc_id) + { + int ret; ++ if (!sawf_ctx) { ++ ath12k_err(NULL, "SAWF context unavailable\n"); ++ return -EINVAL; ++ } + + if (!ath12k_svc_id_valid(svc_id)) { + ath12k_err(NULL, "svc_id: %u is invalid\n", svc_id); + return -EINVAL; + } + ++ spin_lock_bh(&sawf_ctx->sawf_svc_lock); + if (!ath12k_svc_id_configured(svc_id)) { + ath12k_err(NULL, "svc_id: %u is not configured\n", svc_id); ++ spin_unlock_bh(&sawf_ctx->sawf_svc_lock); + return -EINVAL; + } ++ spin_unlock_bh(&sawf_ctx->sawf_svc_lock); + + ret = ath12k_sawf_send_disable_soc(svc_id); + if (ret) { + ath12k_err(NULL, "svc_id: %u disabling failed\n", svc_id); +- return ret; ++ return -EINVAL; + } + ++ spin_lock_bh(&sawf_ctx->sawf_svc_lock); + ath12k_disable_svc_class(svc_id); ++ spin_unlock_bh(&sawf_ctx->sawf_svc_lock); ++ + return ret; + } ++ ++struct ath12k_base *ath12k_sawf_get_ab_from_netdev(struct net_device *dev, ++ u8 *peer_mac, ++ u16 *peer_id) ++{ ++ struct wireless_dev *wdev; ++ struct ieee80211_vif *vif; ++ struct ath12k_base *ab = NULL; ++ struct ath12k_peer *peer; ++ struct ath12k_vif *ahvif; ++ struct ath12k_link_vif *arvif; ++ u16 links_map; ++ u8 link_id; ++ ++ if (!dev) ++ return NULL; ++ ++ wdev = dev->ieee80211_ptr; ++ if (!wdev) ++ return NULL; ++ ++ vif = wdev_to_ieee80211_vif(wdev); ++ if (!vif) ++ return NULL; ++ ++ ahvif = (struct ath12k_vif *)vif->drv_priv; ++ if (!ahvif) ++ return NULL; ++ ++ /* ToDo: Instead of mutex_lock, rcu locking will be used ++ to access the ahvif->link ++ */ ++ links_map = ahvif->links_map; ++ /* Look into all the links, find the matching peer and ++ * return with ab and peer_id detail */ ++ for_each_set_bit(link_id, &links_map, IEEE80211_MLD_MAX_NUM_LINKS) { ++ arvif = ahvif->link[link_id]; ++ ++ if (WARN_ON(!arvif)) ++ continue; ++ ++ ab = arvif->ar->ab; ++ spin_lock_bh(&ab->base_lock); ++ peer = ath12k_peer_find_by_addr(ab, peer_mac); ++ spin_unlock_bh(&ab->base_lock); ++ if (peer) { ++ *peer_id = peer->peer_id; ++ break; ++ } ++ ++ ab = NULL; ++ } ++ return ab; ++} ++ ++u8 ath12k_sawf_get_msduq_of_tid(struct ath12k_base *ab, ++ u8 tid, ++ u8 svc_id, ++ struct ath12k_peer *peer) ++{ ++ struct ath12k_sawf_peer_ctx *peer_ctx = NULL; ++ struct ath12k_sawf_ctx *sawf_ctx; ++ u8 max_usr_def_q_sawf, def_msduq_max, q; ++ u8 msduq_id = SAWF_MSDUQ_ID_INVALID; ++ ++ sawf_ctx = ath12k_get_sawf_context(); ++ if (!sawf_ctx) ++ return SAWF_MSDUQ_ID_INVALID; ++ ++ max_usr_def_q_sawf = sawf_ctx->max_msduq_per_tid - ++ sawf_ctx->default_msduq_per_tid; ++ def_msduq_max = sawf_ctx->default_msduq_per_tid * ++ ATH12K_SAWF_MAX_TID_SUPPORT; ++ ++ peer_ctx = &peer->sawf_ctx_peer; ++ /* Find matching msduq with svc_id in the reserved pool*/ ++ for (q = 0; q < max_usr_def_q_sawf; ++q) { ++ if (peer_ctx->msduq_table[tid][q].is_reserved && ++ peer_ctx->msduq_table[tid][q].svc_id == svc_id) { ++ msduq_id = peer_ctx->msduq_table[tid][q].msduq_id; ++ ath12k_dbg(ab, ATH12K_DBG_SAWF, ++ "Resrv:msduq_id 0x%x:tid %u usrdefq %u\n", ++ msduq_id, tid, q); ++ break; ++ } ++ } ++ ++ if (msduq_id == SAWF_MSDUQ_ID_INVALID) { ++ /* Reserve a new one */ ++ for (q = 0; q < max_usr_def_q_sawf; ++q) { ++ if (!peer_ctx->msduq_table[tid][q].is_reserved) { ++ peer_ctx->msduq_table[tid][q].is_reserved = true; ++ peer_ctx->msduq_table[tid][q].svc_id = svc_id; ++ peer_ctx->msduq_table[tid][q].msduq_id = ++ u16_encode_bits(q, MSDUQID_Q_MASK) | ++ u16_encode_bits(tid, MSDUQID_TID_MASK); ++ peer_ctx->msduq_table[tid][q].msduq_id += ++ def_msduq_max; ++ msduq_id = peer_ctx->msduq_table[tid][q].msduq_id; ++ ath12k_dbg(ab, ATH12K_DBG_SAWF, ++ "New:msduq_id 0x%x:tid %u usrdefq %u\n", ++ msduq_id, tid, q); ++ break; ++ } ++ } ++ } ++ ++ return msduq_id; ++} ++ ++u16 ath12k_sawf_alloc_msduq(struct ath12k_base *ab, ++ u8 svc_id, ++ u16 peer_id) ++{ ++ u8 msduq_id; ++ u8 svc_tid; ++ u16 ret_peer_msduq = SAWF_PEER_MSDUQ_INVALID; ++ struct ath12k_sawf_ctx *sawf_ctx; ++ struct ath12k_peer *peer; ++ ++ sawf_ctx = ath12k_get_sawf_context(); ++ if (!sawf_ctx) ++ return SAWF_PEER_MSDUQ_INVALID; ++ ++ spin_lock_bh(&sawf_ctx->sawf_svc_lock); ++ if (!ath12k_svc_id_configured(svc_id)) { ++ spin_unlock_bh(&sawf_ctx->sawf_svc_lock); ++ return SAWF_PEER_MSDUQ_INVALID; ++ } ++ ++ svc_tid = ath12k_get_tid(svc_id); ++ spin_unlock_bh(&sawf_ctx->sawf_svc_lock); ++ ++ if ((svc_tid < 0) || (svc_tid >= ATH12K_SAWF_MAX_TID_SUPPORT)) ++ return SAWF_PEER_MSDUQ_INVALID; ++ ++ spin_lock_bh(&ab->base_lock); ++ peer = ath12k_peer_find_by_id(ab, peer_id); ++ if (!peer) { ++ spin_unlock_bh(&ab->base_lock); ++ return SAWF_PEER_MSDUQ_INVALID; ++ } ++ ++ /* Allocate msduq from TID specified in SVC */ ++ msduq_id = ath12k_sawf_get_msduq_of_tid(ab, svc_tid, svc_id, peer); ++ ++ if (msduq_id == SAWF_MSDUQ_ID_INVALID) { ++ /* Look into lower TID */ ++ u8 tid = svc_tid - 1; ++ ++ while (tid >= 0 && tid < svc_tid) { ++ msduq_id = ath12k_sawf_get_msduq_of_tid(ab, tid, svc_id, peer); ++ ++ if (msduq_id != SAWF_MSDUQ_ID_INVALID) ++ break; ++ ++ --tid; ++ } ++ } ++ ++ if (msduq_id == SAWF_MSDUQ_ID_INVALID) { ++ /* Look into Higher TID */ ++ u8 tid = svc_tid + 1; ++ ++ while (tid < ATH12K_SAWF_MAX_TID_SUPPORT) { ++ msduq_id = ath12k_sawf_get_msduq_of_tid(ab, tid, svc_id, peer); ++ ++ if (msduq_id != SAWF_MSDUQ_ID_INVALID) ++ break; ++ ++ ++tid; ++ } ++ } ++ spin_unlock_bh(&ab->base_lock); ++ ++ if (msduq_id != SAWF_MSDUQ_ID_INVALID) ++ ret_peer_msduq = FIELD_PREP(SAWF_PEER_ID, peer_id) | ++ FIELD_PREP(SAWF_MSDUQ_ID, msduq_id); ++ ++ return ret_peer_msduq; ++} ++ ++u16 ath12k_sawf_get_msduq(struct net_device *dev, u8 *peer_mac, u32 service_id, ++ u32 dscp, u32 rule_id) ++{ ++ struct ath12k_base *ab; ++ u16 peer_id; ++ u16 peer_msduq; ++ ++ ab = ath12k_sawf_get_ab_from_netdev(dev, peer_mac, &peer_id); ++ if (!ab) ++ return SAWF_PEER_MSDUQ_INVALID; ++ ++ peer_msduq = ath12k_sawf_alloc_msduq(ab, service_id, peer_id); ++ ath12k_dbg(ab, ATH12K_DBG_SAWF, ++ "SAWF get msduq:peer %pM SvcId %u:msduq id 0x%x allocated\n", ++ peer_mac, service_id, peer_msduq); ++ return peer_msduq; ++} +--- a/drivers/net/wireless/ath/ath12k/sawf.h ++++ b/drivers/net/wireless/ath/ath12k/sawf.h +@@ -10,6 +10,7 @@ + #define ATH12K_SAWF_SVC_CLASS_MAX 128 + #define ATH12K_MAX_APP_NAME 64 + #define ATH12K_SAWF_MAX_TID_SUPPORT 8 ++#define MAX_Q_PER_TID 8 + /** + ** SAWF_metadata related information. + **/ +@@ -25,6 +26,13 @@ + #define FLOW_OVERRIDE_FROM_Q_ID BIT(3) + #define WHO_CLASSIFY_INFO_FROM_Q_ID GENMASK(5, 4) + ++#define SAWF_PEER_MSDUQ_INVALID 0xFFFF ++#define SAWF_MSDUQ_ID_INVALID 0x3F ++#define SAWF_MSDUQ_ID GENMASK(5, 0) ++#define SAWF_PEER_ID GENMASK(15, 6) ++ ++#define MSDUQID_TID_MASK GENMASK(2, 0) ++#define MSDUQID_Q_MASK GENMASK(5, 3) + /* + * Min throughput limit 0 - 10 Gb/s + * Granularity: 1 Kb/s +@@ -149,6 +157,29 @@ struct ath12k_sawf_ctx { + spinlock_t sawf_svc_lock; + }; + ++/** ++ * struct ath12k_msduq_map- MSDU Q Map struct ++ * mapping of MSDUQ with service class ID ++ * @svc_id: Service Class ID ++ * @is_reserved: Flag to hold the allocaiton status. ++ * @msduq_id: unique id of the MSDUQ. ++ */ ++struct ath12k_msduq_map { ++ u8 svc_id; ++ bool is_reserved; ++ u16 msduq_id; ++}; ++ ++/** ++ * struct ath12k_sawf_peer_ctx ++ * A Data base to maintain the allocation status of user deined MSDUQ. ++ * The allocation is mapped with the service class ID. ++ * @msduq_table: map table of msduq and svc id per peer ++ */ ++struct ath12k_sawf_peer_ctx { ++ struct ath12k_msduq_map msduq_table[ATH12K_SAWF_MAX_TID_SUPPORT][MAX_Q_PER_TID]; ++}; ++ + extern bool ath12k_sawf_enable; + struct ath12k_sawf_ctx *ath12k_get_sawf_context(void); + void ath12k_sawf_init(struct ath12k_base *ab); +@@ -162,4 +193,7 @@ int ath12k_get_tid(u8 svc_id); + int ath12k_sawf_reconfigure_on_crash(struct ath12k_base *ab); + int ath12k_create_send_svc_params(struct ath12k_sawf_svc_params *param); + int ath12k_sawf_disable_config(u8 svc_id); ++u16 ath12k_sawf_get_msduq(struct net_device *netdev, ++ u8 *peer_mac, u32 service_id, ++ u32 dscp, u32 rule_id); + #endif /* ATH11K_SAWF_H */ +--- a/drivers/net/wireless/ath/ath12k/vendor.c ++++ b/drivers/net/wireless/ath/ath12k/vendor.c +@@ -144,6 +144,12 @@ static int ath12k_vendor_view_sawf_confi + if (!ath12k_sawf_enable) + return -EOPNOTSUPP; + ++ sawf_ctx = ath12k_get_sawf_context(); ++ if (!sawf_ctx) { ++ ath12k_err(NULL, "SAWF context not available\n"); ++ return -ENODATA; ++ } ++ + ret = nla_parse(tb, QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX, data, data_len, + ath12k_vendor_sawf_config_policy, NULL); + +@@ -153,12 +159,16 @@ static int ath12k_vendor_view_sawf_confi + } + + if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_ID]) { ++ bool isconfigured; + svc_id = nla_get_u8(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_ID]); + if (!ath12k_svc_id_valid(svc_id)) { + ath12k_err(NULL, "Invalid Service ID: %u\n", svc_id); + return -EINVAL; + } +- if (!ath12k_svc_id_configured(svc_id)) ++ spin_lock_bh(&sawf_ctx->sawf_svc_lock); ++ isconfigured = ath12k_svc_id_configured(svc_id); ++ spin_unlock_bh(&sawf_ctx->sawf_svc_lock); ++ if (!isconfigured) + return -EINVAL; + } + +@@ -166,13 +176,6 @@ static int ath12k_vendor_view_sawf_confi + if (storage && (*storage == ATH12K_SAWF_SVC_CLASS_MAX)) + return 0; + +- sawf_ctx = ath12k_get_sawf_context(); +- +- if (!sawf_ctx) { +- ath12k_err(NULL, "SAWF context not available\n"); +- return -ENODATA; +- } +- + sawf_svc_classes = nla_nest_start(msg, + QCN_WLAN_VENDOR_ATTR_SAWF_SERVICE_CLASSES); + diff --git a/feeds/ipq95xx/mac80211/patches/qca/753-03-ath12k-sawf-add-default-q-mapping-support.patch b/feeds/ipq95xx/mac80211/patches/qca/753-03-ath12k-sawf-add-default-q-mapping-support.patch new file mode 100644 index 000000000..1ed34caeb --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/753-03-ath12k-sawf-add-default-q-mapping-support.patch @@ -0,0 +1,733 @@ +From 014a5facd4e3bc2d5adf1794e5f947d8b0ed23bd Mon Sep 17 00:00:00 2001 +From: Ganesh Babu Jothiram +Date: Tue, 4 Apr 2023 15:26:31 +0530 +Subject: [PATCH 3/3] ath12k: sawf: add default msduq mapping support. + +add support for mapping of service class ID to its default msduq. +support for map, unmap and report via NL vendor command. + +Signed-off-by: Ganesh Babu Jothiram +--- + drivers/net/wireless/ath/ath12k/dp.h | 4 + + drivers/net/wireless/ath/ath12k/dp_rx.c | 4 + + drivers/net/wireless/ath/ath12k/sawf.c | 263 +++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/sawf.h | 132 ++++++++++++ + drivers/net/wireless/ath/ath12k/vendor.c | 172 +++++++++++++++ + drivers/net/wireless/ath/ath12k/vendor.h | 13 ++ + 6 files changed, 588 insertions(+) + +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -451,6 +451,9 @@ enum htt_h2t_msg_type { + HTT_H2T_MSG_TYPE_PPDU_STATS_CFG = 0x11, + HTT_H2T_MSG_TYPE_VDEV_TXRX_STATS_CFG = 0x1a, + HTT_H2T_MSG_TYPE_TX_MONITOR_CFG = 0x1b, ++ HTT_H2T_MSG_TYPE_SAWF_DEF_Q_MAP_REQ = 0x1c, ++ HTT_H2T_MSG_TYPE_SAWF_DEF_Q_UNMAP_REQ = 0x1d, ++ HTT_H2T_MSG_TYPE_SAWF_DEF_Q_MAP_REPORT_REQ = 0x1e, + }; + + #define HTT_VER_REQ_INFO_MSG_ID GENMASK(7, 0) +@@ -1318,6 +1321,7 @@ enum htt_t2h_msg_type { + HTT_T2H_MSG_TYPE_MLO_RX_PEER_UNMAP = 0x2a, + HTT_T2H_MSG_TYPE_PEER_MAP3 = 0x2b, + HTT_T2H_MSG_TYPE_VDEV_TXRX_STATS_PERIODIC_IND = 0x2c, ++ HTT_T2H_MSG_TYPE_SAWF_DEF_QUEUES_MAP_REPORT_CONF = 0x2d, + HTT_T2H_MSG_TYPE_SAWF_MSDUQ_INFO_IND = 0x2e, + }; + +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -21,6 +21,7 @@ + #include "peer.h" + #include "dp_mon.h" + #include "hif.h" ++#include "sawf.h" + #ifdef CPTCFG_MAC80211_PPE_SUPPORT + #include + #include +@@ -2236,6 +2237,9 @@ void ath12k_dp_htt_htc_t2h_msg_handler(s + case HTT_T2H_MSG_TYPE_SAWF_MSDUQ_INFO_IND: + ath12k_htt_sawf_info_ind_handler(ab, skb); + break; ++ case HTT_T2H_MSG_TYPE_SAWF_DEF_QUEUES_MAP_REPORT_CONF: ++ ath12k_htt_sawf_def_q_map_report_handler(ab, skb); ++ break; + default: + ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "dp_htt event %d not handled\n", + type); +--- a/drivers/net/wireless/ath/ath12k/sawf.c ++++ b/drivers/net/wireless/ath/ath12k/sawf.c +@@ -12,6 +12,7 @@ + #include + + #define SVC_INDEX(svc_id) svc_id - 1 ++#define DRV_TO_FW_SVC_ID(svc_id) (svc_id - 1) + + bool ath12k_sawf_enable; + module_param_named(sawf, ath12k_sawf_enable, bool, 0444); +@@ -602,9 +603,14 @@ u16 ath12k_sawf_get_msduq(struct net_dev + u32 dscp, u32 rule_id) + { + struct ath12k_base *ab; ++ struct ath12k_sawf_ctx *sawf_ctx; + u16 peer_id; + u16 peer_msduq; + ++ sawf_ctx = ath12k_get_sawf_context(); ++ if (!sawf_ctx) ++ return SAWF_PEER_MSDUQ_INVALID; ++ + ab = ath12k_sawf_get_ab_from_netdev(dev, peer_mac, &peer_id); + if (!ab) + return SAWF_PEER_MSDUQ_INVALID; +@@ -618,3 +624,257 @@ u16 ath12k_sawf_get_msduq(struct net_dev + peer_mac, service_id, peer_msduq); + return peer_msduq; + } ++ ++int ath12k_sawf_htt_h2t_def_q_map_req(struct ath12k_base *ab, ++ u8 svc_id, ++ u16 peer_id) ++{ ++ struct ath12k_dp *dp = &ab->dp; ++ struct sk_buff *skb; ++ struct ath12k_htt_h2t_sawf_def_q_map_req *cmd; ++ int len = sizeof(*cmd); ++ int ret; ++ ++ skb = ath12k_htc_alloc_skb(ab, len); ++ if (!skb) { ++ ath12k_err(ab, "Def Q Map Req:alloc skb fails\n"); ++ return -ENOMEM; ++ } ++ ++ skb_put(skb, len); ++ cmd = (struct htt_h2t_sawf_def_q_map_req *)skb->data; ++ cmd->info = u32_encode_bits(HTT_H2T_MSG_TYPE_SAWF_DEF_Q_MAP_REQ, ++ HTT_H2T_MSG_TYPE_ID) | ++ u32_encode_bits(DRV_TO_FW_SVC_ID(svc_id), ++ HTT_H2T_SAWF_DEF_Q_MAP_SVC_ID) | ++ u32_encode_bits(peer_id, ++ HTT_H2T_SAWF_DEF_Q_MAP_PEER_ID); ++ ++ ath12k_dbg(ab, ATH12K_DBG_SAWF, "Def Q Map req:0x%x\n", cmd->info); ++ ++ ret = ath12k_htc_send(&ab->htc, dp->eid, skb); ++ if (ret) { ++ dev_kfree_skb_any(skb); ++ return ret; ++ } ++ return 0; ++} ++ ++int ath12k_sawf_htt_h2t_def_q_unmap_req(struct ath12k_base *ab, ++ u8 svc_id, ++ u16 peer_id) ++{ ++ struct ath12k_dp *dp = &ab->dp; ++ struct sk_buff *skb; ++ struct ath12k_htt_h2t_sawf_def_q_unmap_req *cmd; ++ int len = sizeof(*cmd); ++ int ret; ++ ++ skb = ath12k_htc_alloc_skb(ab, len); ++ if (!skb) { ++ ath12k_err(ab, "Def Q unmap Req:alloc skb fails\n"); ++ return -ENOMEM; ++ } ++ ++ skb_put(skb, len); ++ cmd = (struct ath12k_htt_h2t_sawf_def_q_umap_req *)skb->data; ++ cmd->info = u32_encode_bits(HTT_H2T_MSG_TYPE_SAWF_DEF_Q_UNMAP_REQ, ++ HTT_H2T_MSG_TYPE_ID) | ++ u32_encode_bits(DRV_TO_FW_SVC_ID(svc_id), ++ HTT_H2T_SAWF_DEF_Q_UMAP_SVC_ID) | ++ u32_encode_bits(peer_id, ++ HTT_H2T_SAWF_DEF_Q_UMAP_PEER_ID); ++ ++ ath12k_dbg(ab, ATH12K_DBG_SAWF, "Def Q UnMap req:0x%x\n", cmd->info); ++ ++ ret = ath12k_htc_send(&ab->htc, dp->eid, skb); ++ if (ret) { ++ dev_kfree_skb_any(skb); ++ return ret; ++ } ++ return 0; ++} ++ ++int ath12k_sawf_htt_h2t_def_q_map_report_req(struct ath12k_base *ab, ++ u8 tid_mask, ++ u16 peer_id) ++{ ++ struct ath12k_dp *dp = &ab->dp; ++ struct sk_buff *skb; ++ struct ath12k_htt_h2t_sawf_def_q_map_report_req *cmd; ++ int len = sizeof(*cmd); ++ int ret; ++ ++ skb = ath12k_htc_alloc_skb(ab, len); ++ if (!skb) { ++ ath12k_err(ab, "Def Q map Report Req:alloc skb fails\n"); ++ return -ENOMEM; ++ } ++ ++ skb_put(skb, len); ++ cmd = (struct htt_h2c_sawf_def_q_map_req_report *)skb->data; ++ ++ cmd->info = u32_encode_bits(HTT_H2T_MSG_TYPE_SAWF_DEF_Q_MAP_REPORT_REQ, ++ HTT_H2T_MSG_TYPE_ID) | ++ u32_encode_bits(tid_mask, ++ HTT_H2T_SAWF_DEF_Q_MAP_TID_MASK_ID) | ++ u32_encode_bits(peer_id, ++ HTT_H2T_SAWF_DEF_Q_MAP_PEER_ID); ++ ++ cmd->info1 = u32_encode_bits(0, HTT_H2T_SAWF_DEF_Q_MAP_ETO_ID); ++ ++ ath12k_dbg(ab, ATH12K_DBG_SAWF, "Def Q Map Report req:0x%x, 0x%x\n", ++ cmd->info, cmd->info1); ++ ++ ret = ath12k_htc_send(&ab->htc, dp->eid, skb); ++ if (ret) { ++ dev_kfree_skb_any(skb); ++ return ret; ++ } ++ return 0; ++} ++ ++int ath12k_sawf_def_qmap_req(struct ath12k_base *ab, ++ u8 svc_id, u16 peer_id) ++{ ++ int ret; ++ struct ath12k_sawf_ctx *sawf_ctx; ++ ++ if (!ab) ++ return DP_SAWF_INVALID_PARAM; ++ ++ sawf_ctx = ath12k_get_sawf_context(); ++ if (!sawf_ctx) ++ return -EINVAL; ++ ++ spin_lock_bh(&sawf_ctx->sawf_svc_lock); ++ if (!ath12k_svc_id_configured(svc_id)) { ++ spin_unlock_bh(&sawf_ctx->sawf_svc_lock); ++ return -EINVAL; ++ } ++ spin_unlock_bh(&sawf_ctx->sawf_svc_lock); ++ ++ ret = ath12k_sawf_htt_h2t_def_q_map_req(ab, svc_id, peer_id); ++ if (ret) { ++ ath12k_dbg(ab, ATH12K_DBG_SAWF, "Def Q Map Req fail %d\n", ret); ++ return ret; ++ } ++ ++ ret = ath12k_sawf_htt_h2t_def_q_map_report_req(ab, 0xFF, peer_id); ++ ++ return ret; ++} ++ ++int ath12k_sawf_def_qunmap_req(struct ath12k_base *ab, ++ u8 svc_id, u16 peer_id) ++{ ++ int ret; ++ struct ath12k_sawf_ctx *sawf_ctx; ++ ++ if (!ab) ++ return DP_SAWF_INVALID_PARAM; ++ ++ sawf_ctx = ath12k_get_sawf_context(); ++ if (!sawf_ctx) ++ return -EINVAL; ++ ++ spin_lock_bh(&sawf_ctx->sawf_svc_lock); ++ if (!ath12k_svc_id_configured(svc_id)) { ++ spin_unlock_bh(&sawf_ctx->sawf_svc_lock); ++ return -EINVAL; ++ } ++ spin_unlock_bh(&sawf_ctx->sawf_svc_lock); ++ ++ ret = ath12k_sawf_htt_h2t_def_q_unmap_req(ab, svc_id, peer_id); ++ if (ret) { ++ ath12k_dbg(ab, ATH12K_DBG_SAWF, "Def Q Unmap req fail ret %d\n", ret); ++ return ret; ++ } ++ ++ ret = ath12k_sawf_htt_h2t_def_q_map_report_req(ab, 0xFF, peer_id); ++ return ret; ++} ++ ++int ath12k_sawf_def_qmap_report_req(struct ath12k_base *ab, ++ u16 peer_id) ++{ ++ struct ath12k_sawf_def_queue_report def_q_map_report[ATH12K_SAWF_MAX_TID_SUPPORT] = {0}; ++ struct ath12k_peer *peer; ++ int ret = -1; ++ ++ if (!ab) ++ return DP_SAWF_INVALID_PARAM; ++ ++ spin_lock_bh(&ab->base_lock); ++ peer = ath12k_peer_find_by_id(ab, peer_id); ++ if (peer) ++ memcpy(def_q_map_report, ++ peer->sawf_ctx_peer.def_q_map, ++ sizeof(def_q_map_report)); ++ ++ spin_unlock_bh(&ab->base_lock); ++ if (peer) { ++ int i; ++ ++ ret = 0; ++ ath12k_dbg(ab, ATH12K_DBG_SAWF, "peer %pM map report\n", peer->addr); ++ ath12k_dbg(ab, ATH12K_DBG_SAWF, "TID: Active: Svc_Id\n"); ++ for (i = 0; i < ATH12K_SAWF_MAX_TID_SUPPORT; ++i) { ++ bool tid_active; ++ u8 svc_id; ++ ++ svc_id = def_q_map_report[i].svc_class_id; ++ tid_active = (svc_id && svc_id != 0xFF); ++ ath12k_dbg(ab, ATH12K_DBG_SAWF, ++ "%u :\t %u :\t %u\n", ++ i, ++ tid_active, ++ svc_id); ++ } ++ } ++ return ret; ++} ++ ++void ath12k_htt_sawf_def_q_map_report_handler(struct ath12k_base *ab, ++ struct sk_buff *skb) ++{ ++ struct ath12k_htt_t2h_sawf_q_map_report *resp = ++ (struct ath12k_htt_t2h_sawf_q_map_report *)skb->data; ++ struct ath12k_peer *peer; ++ unsigned int data_len = skb->len; ++ u16 peer_id; ++ int i; ++ ++ peer_id = FIELD_GET(HTT_T2H_SAWF_Q_MAP_REPORT_INFO0_PEER_ID, ++ resp->info); ++ data_len -= sizeof(resp->info); ++ ++ rcu_read_lock(); ++ spin_lock_bh(&ab->base_lock); ++ ++ peer = ath12k_peer_find_by_id(ab, peer_id); ++ /* Default queue map report received on reqest,Hence peer should be valid */ ++ if (WARN_ON_ONCE(!peer)) ++ goto unlock_ab_base; ++ ++ for (i = 0; ++ data_len > 0 && i < ATH12K_SAWF_MAX_TID_SUPPORT; ++ data_len -= sizeof(resp->tid_report[i]), ++i) { ++ u8 tid, svc_id; ++ ++ tid = FIELD_GET(HTT_T2H_SAWF_Q_MAP_REPORT_TID_ID, ++ resp->tid_report[i]); ++ svc_id = FIELD_GET(HTT_T2H_SAWF_Q_MAP_REPORT_SVC_ID, ++ resp->tid_report[i]); ++ svc_id += 1; ++ ath12k_dbg(ab, ATH12K_DBG_SAWF, ++ "idx %d:MapReport:Tid[%u]Svc[%u]\n", ++ i, tid, svc_id); ++ if (tid < ATH12K_SAWF_MAX_TID_SUPPORT) ++ peer->sawf_ctx_peer.def_q_map[tid].svc_class_id = svc_id; ++ } ++ ++unlock_ab_base: ++ spin_unlock_bh(&ab->base_lock); ++ rcu_read_unlock(); ++} +--- a/drivers/net/wireless/ath/ath12k/sawf.h ++++ b/drivers/net/wireless/ath/ath12k/sawf.h +@@ -6,6 +6,9 @@ + #ifndef ATH12K_SAWF_H + #define ATH12K_SAWF_H + ++#define ATH12K_MAC_ADDR_SIZE 6 ++#define DP_SAWF_INVALID_PARAM -1 ++ + #define ATH12K_SAWF_SVC_CLASS_MIN 1 + #define ATH12K_SAWF_SVC_CLASS_MAX 128 + #define ATH12K_MAX_APP_NAME 64 +@@ -171,15 +174,131 @@ struct ath12k_msduq_map { + }; + + /** ++ * struct ath12k_sawf_def_queue_report : default Q map report ++ */ ++struct ath12k_sawf_def_queue_report { ++ u8 svc_class_id; ++}; ++ ++/** + * struct ath12k_sawf_peer_ctx + * A Data base to maintain the allocation status of user deined MSDUQ. + * The allocation is mapped with the service class ID. + * @msduq_table: map table of msduq and svc id per peer ++ * @def_q_map: default q map report + */ + struct ath12k_sawf_peer_ctx { + struct ath12k_msduq_map msduq_table[ATH12K_SAWF_MAX_TID_SUPPORT][MAX_Q_PER_TID]; ++ struct ath12k_sawf_def_queue_report def_q_map[ATH12K_SAWF_MAX_TID_SUPPORT]; ++}; ++ ++/* MSG_TYPE => HTT_H2T_SAWF_DEF_QUEUES_MAP_REQ ++ * ++ * @details ++ * The SAWF_DEF_QUEUES_MAP_REQ message is sent by the host to link ++ * the default MSDU queues for one of the TIDs within the specified peer ++ * to the specified service class. ++ * The TID is indirectly specified - each service class is associated ++ * with a TID. All default MSDU queues for this peer-TID will be ++ * linked to the service class in question. ++ * ++ * |31 16|15 8|7 0| ++ * |------------------------------+--------------+--------------| ++ * | peer ID | svc class ID | msg type | ++ * |------------------------------------------------------------| ++ * Header fields: ++ * dword0 - b'7:0 - msg_type: This will be set to ++ * 0x1c (HTT_H2T_SAWF_DEF_QUEUES_MAP_REQ) ++ * b'15:8 - service class ID ++ * b'31:16 - peer ID ++ */ ++struct ath12k_htt_h2t_sawf_def_q_map_req { ++ u32 info; + }; + ++#define HTT_H2T_MSG_TYPE_ID GENMASK(7, 0) ++#define HTT_H2T_SAWF_DEF_Q_MAP_SVC_ID GENMASK(15, 8) ++#define HTT_H2T_SAWF_DEF_Q_UMAP_SVC_ID GENMASK(15, 8) ++#define HTT_H2T_SAWF_DEF_Q_MAP_PEER_ID GENMASK(31, 16) ++#define HTT_H2T_SAWF_DEF_Q_UMAP_PEER_ID GENMASK(31, 16) ++#define HTT_H2T_SAWF_DEF_Q_MAP_TID_MASK_ID GENMASK(15, 8) ++#define HTT_H2T_SAWF_DEF_Q_MAP_ETO_ID BIT(0) ++/* MSG_TYPE => HTT_H2T_SAWF_DEF_QUEUES_UNMAP_REQ ++ * ++ * @details ++ * The SAWF_DEF_QUEUES_UNMAP_REQ message is sent by the host to ++ * remove the linkage of the specified peer-TID's MSDU queues to ++ * service classes. ++ * ++ * |31 16|15 8|7 0| ++ * |------------------------------+--------------+--------------| ++ * | peer ID | svc class ID | msg type | ++ * |------------------------------------------------------------| ++ * Header fields: ++ * dword0 - b'7:0 - msg_type: This will be set to ++ * 0x1d (HTT_H2T_SAWF_DEF_QUEUES_UNMAP_REQ) ++ * b'15:8 - service class ID ++ * b'31:16 - peer ID ++ * A HTT_H2T_SAWF_DEF_QUEUES_UNMAP_PEER_ID_WILDCARD ++ * value for peer ID indicates that the target should ++ * apply the UNMAP_REQ to all peers. ++ */ ++struct ath12k_htt_h2t_sawf_def_q_unmap_req { ++ u32 info; ++}; ++ ++/* MSG_TYPE => HTT_H2T_SAWF_DEF_QUEUES_MAP_REPORT_REQ ++ * ++ * @details ++ * The SAWF_DEF_QUEUES_MAP_REPORT_REQ message is sent by the host to ++ * request the target to report what service class the default MSDU queues ++ * of the specified TIDs within the peer are linked to. ++ * The target will respond with a SAWF_DEF_QUEUES_MAP_REPORT_CONF message ++ * to report what service class (if any) the default MSDU queues for ++ * each of the specified TIDs are linked to. ++ * ++ * |31 16|15 8|7 1| 0| ++ * |------------------------------+--------------+--------------| ++ * | peer ID | TID mask | msg type | ++ * |------------------------------------------------------------| ++ * | reserved |ETO| ++ * |------------------------------------------------------------| ++ * Header fields: ++ * dword0 - b'7:0 - msg_type: This will be set to ++ * 0x1e (HTT_H2T_SAWF_DEF_QUEUES_MAP_REPORT_REQ) ++ * b'15:8 - TID mask ++ * b'31:16 - peer ID ++ * dword1 - b'0 - "Existing Tids Only" flag ++ * If this flag is set, the DEF_QUEUES_MAP_REPORT_CONF ++ * message generated by this REQ will only show the ++ * mapping for TIDs that actually exist in the target's ++ * peer object. ++ * Any TIDs that are covered by a MAP_REQ but which ++ * do not actually exist will be shown as being ++ * unmapped (i.e. svc class ID 0xff). ++ * If this flag is cleared, the MAP_REPORT_CONF message ++ * will consider not only the mapping of TIDs currently ++ * existing in the peer, but also the mapping that will ++ * be applied for any TID objects created within this ++ * peer in the future. ++ * b'31:1 - reserved for future use ++ */ ++struct ath12k_htt_h2t_sawf_def_q_map_report_req { ++ u32 info; ++ u32 info1; ++}; ++ ++#define HTT_T2H_SAWF_Q_MAP_REPORT_INFO0_PEER_ID GENMASK(31, 16) ++#define HTT_T2H_SAWF_Q_MAP_REPORT_TID_ID GENMASK(7, 0) ++#define HTT_T2H_SAWF_Q_MAP_REPORT_SVC_ID GENMASK(15, 8) ++ ++#define HTT_SAWF_SVC_CLASS_INVALID_ID 0xff ++ ++struct ath12k_htt_t2h_sawf_q_map_report { ++ u32 info; ++ u32 tid_report[ATH12K_SAWF_MAX_TID_SUPPORT]; //MAX_TIDT ++} __packed; ++ + extern bool ath12k_sawf_enable; + struct ath12k_sawf_ctx *ath12k_get_sawf_context(void); + void ath12k_sawf_init(struct ath12k_base *ab); +@@ -196,4 +315,17 @@ int ath12k_sawf_disable_config(u8 svc_id + u16 ath12k_sawf_get_msduq(struct net_device *netdev, + u8 *peer_mac, u32 service_id, + u32 dscp, u32 rule_id); ++struct ath12k_base *ath12k_sawf_get_ab_from_netdev(struct net_device *dev, ++ u8 *peer_mac, ++ u16 *peer_id); ++ ++int ath12k_sawf_def_qmap_req(struct ath12k_base *ab, ++ u8 svc_id, u16 peer_id); ++int ath12k_sawf_def_qunmap_req(struct ath12k_base *ab, ++ u8 svc_id, u16 peer_id); ++int ath12k_sawf_def_qmap_report_req(struct ath12k_base *ab, ++ u16 peer_id); ++ ++void ath12k_htt_sawf_def_q_map_report_handler(struct ath12k_base *ab, ++ struct sk_buff *skb); + #endif /* ATH11K_SAWF_H */ +--- a/drivers/net/wireless/ath/ath12k/vendor.c ++++ b/drivers/net/wireless/ath/ath12k/vendor.c +@@ -7,6 +7,7 @@ + #include "core.h" + #include "debug.h" + #include "mac.h" ++#include "sawf.h" + + static const struct nla_policy + ath12k_vendor_sawf_config_policy[QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX + 1] = { +@@ -24,6 +25,17 @@ ath12k_vendor_sawf_config_policy[QCA_WLA + [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_RATE_LOSS] = {.type = NLA_U32}, + }; + ++static const struct nla_policy ++ath12k_vendor_sawf_def_qmap_req_policy[QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_MAX + 1] = { ++ [QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_SVC_ID] = {.type = NLA_U8}, ++ [QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_MAC_ADDR] = {.type = NLA_STRING, .len = 18}, ++}; ++ ++static const struct nla_policy ++ath12k_vendor_sawf_def_qmap_rep_req_policy[QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_MAX + 1] = { ++ [QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_MAC_ADDR] = {.type = NLA_STRING, .len = 18}, ++}; ++ + static void ath12k_set_default_values(struct ath12k_sawf_svc_params *param) + { + param->min_throughput_rate = SAWF_SVC_PARAM_DEFAULT_MIN_THRUPUT; +@@ -246,6 +258,142 @@ nla_put_failure: + return -ENOBUFS; + } + ++static int ath12k_vendor_sawf_def_qmap_req(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ const void *data, ++ int data_len) ++{ ++ struct nlattr *tb[QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_MAX + 1]; ++ struct ath12k_base *ab = NULL; ++ u8 svc_id; ++ u8 *mac_addr_p = NULL; ++ u16 peer_id = 0xFFFF; ++ u8 mac_addr[ATH12K_MAC_ADDR_SIZE] = { 0 }; ++ int ret = 0; ++ ++ ret = nla_parse(tb, QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_MAX, data, data_len, ++ ath12k_vendor_sawf_def_qmap_req_policy, NULL); ++ if (ret) { ++ ath12k_warn(NULL, "invalid sawf def q map policy attribute\n"); ++ return ret; ++ } ++ ++ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_MAC_ADDR]) { ++ mac_addr_p = nla_data(tb[QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_MAC_ADDR]); ++ if (sscanf(mac_addr_p, ++ "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", ++ &mac_addr[0], ++ &mac_addr[1], ++ &mac_addr[2], ++ &mac_addr[3], ++ &mac_addr[4], ++ &mac_addr[5]) != ATH12K_MAC_ADDR_SIZE) { ++ ath12k_warn(NULL, "invalid Macaddr %s\n", mac_addr_p); ++ return -1; ++ } ++ } ++ svc_id = nla_get_u8(tb[QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_SVC_ID]); ++ ++ ath12k_dbg(NULL, ATH12K_DBG_SAWF, ++ "Default Q map:svcid[%u]macaddr[%pM]\n", svc_id, mac_addr); ++ ++ ab = ath12k_sawf_get_ab_from_netdev(wdev->netdev, mac_addr, &peer_id); ++ if (ab) ++ ret = ath12k_sawf_def_qmap_req(ab, svc_id, peer_id); ++ ++ return ret; ++} ++ ++static int ath12k_vendor_sawf_def_qunmap_req(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ const void *data, ++ int data_len) ++{ ++ struct nlattr *tb[QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_MAX + 1]; ++ struct ath12k_base *ab; ++ u8 svc_id; ++ u16 peer_id = 0xFFFF; ++ u8 *mac_addr_p = NULL; ++ u8 mac_addr[ATH12K_MAC_ADDR_SIZE] = { 0 }; ++ int ret = 0; ++ ++ ret = nla_parse(tb, QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_MAX, data, data_len, ++ ath12k_vendor_sawf_def_qmap_req_policy, NULL); ++ if (ret) { ++ ath12k_warn(NULL, "invalid sawf def q unmap policy attribute\n"); ++ return ret; ++ } ++ ++ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_MAC_ADDR]) { ++ mac_addr_p = nla_data(tb[QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_MAC_ADDR]); ++ if (sscanf(mac_addr_p, ++ "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", ++ &mac_addr[0], ++ &mac_addr[1], ++ &mac_addr[2], ++ &mac_addr[3], ++ &mac_addr[4], ++ &mac_addr[5]) != ATH12K_MAC_ADDR_SIZE) { ++ ath12k_warn(NULL, "invalid Macaddr %s\n", mac_addr_p); ++ return -1; ++ } ++ } ++ svc_id = nla_get_u8(tb[QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_SVC_ID]); ++ ++ ath12k_dbg(NULL, ATH12K_DBG_SAWF, ++ "Default Q unmap:svcid[%u]macaddr[%pM]\n", svc_id, mac_addr); ++ ++ ab = ath12k_sawf_get_ab_from_netdev(wdev->netdev, mac_addr, &peer_id); ++ ++ if (ab) ++ ret = ath12k_sawf_def_qunmap_req(ab, svc_id, peer_id); ++ ++ return ret; ++} ++ ++static int ath12k_vendor_sawf_def_qmap_report_req(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ const void *data, ++ int data_len) ++{ ++ struct nlattr *tb[QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_MAX + 1]; ++ struct ath12k_base *ab = NULL; ++ u16 peer_id = 0xFFFF; ++ u8 *mac_addr_p = NULL; ++ u8 mac_addr[ATH12K_MAC_ADDR_SIZE] = { 0 }; ++ int ret = 0; ++ ++ ret = nla_parse(tb, QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_MAX, data, data_len, ++ ath12k_vendor_sawf_def_qmap_rep_req_policy, NULL); ++ if (ret) { ++ ath12k_warn(NULL, "invalid sawf def q map report req policy attribute\n"); ++ return ret; ++ } ++ ++ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_MAC_ADDR]) { ++ mac_addr_p = nla_data(tb[QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_MAC_ADDR]); ++ if (sscanf(mac_addr_p, ++ "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", ++ &mac_addr[0], ++ &mac_addr[1], ++ &mac_addr[2], ++ &mac_addr[3], ++ &mac_addr[4], ++ &mac_addr[5]) != ATH12K_MAC_ADDR_SIZE) { ++ ath12k_warn(NULL, "invalid Macaddr %s\n", mac_addr_p); ++ return -1; ++ } ++ } ++ ath12k_dbg(NULL, ATH12K_DBG_SAWF, ++ "Default Q map report:macaddr[%pM]\n", mac_addr); ++ ++ ab = ath12k_sawf_get_ab_from_netdev(wdev->netdev, mac_addr, &peer_id); ++ if (ab) ++ ret = ath12k_sawf_def_qmap_report_req(ab, peer_id); ++ ++ return ret; ++} ++ + static struct wiphy_vendor_command ath12k_vendor_commands[] = { + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, +@@ -268,6 +416,30 @@ static struct wiphy_vendor_command ath12 + .policy = ath12k_vendor_sawf_config_policy, + .maxattr = QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX, + }, ++ { ++ .info.vendor_id = QCA_NL80211_VENDOR_ID, ++ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SAWF_DEF_Q_MAP, ++ .doit = ath12k_vendor_sawf_def_qmap_req, ++ .policy = ath12k_vendor_sawf_def_qmap_req_policy, ++ .maxattr = QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_MAX, ++ .flags = WIPHY_VENDOR_CMD_NEED_NETDEV, ++ }, ++ { ++ .info.vendor_id = QCA_NL80211_VENDOR_ID, ++ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SAWF_DEF_Q_UNMAP, ++ .doit = ath12k_vendor_sawf_def_qunmap_req, ++ .policy = ath12k_vendor_sawf_def_qmap_req_policy, ++ .maxattr = QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_MAX, ++ .flags = WIPHY_VENDOR_CMD_NEED_NETDEV, ++ }, ++ { ++ .info.vendor_id = QCA_NL80211_VENDOR_ID, ++ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SAWF_DEF_Q_MAP_REP, ++ .doit = ath12k_vendor_sawf_def_qmap_report_req, ++ .policy = ath12k_vendor_sawf_def_qmap_rep_req_policy, ++ .maxattr = QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_MAX, ++ .flags = WIPHY_VENDOR_CMD_NEED_NETDEV, ++ }, + }; + + int ath12k_vendor_register(struct ath12k_hw *ah) +--- a/drivers/net/wireless/ath/ath12k/vendor.h ++++ b/drivers/net/wireless/ath/ath12k/vendor.h +@@ -14,6 +14,9 @@ enum qca_nl80211_vendor_subcmds { + QCA_NL80211_VENDOR_SUBCMD_SVC_CREATE = 204, + QCA_NL80211_VENDOR_SUBCMD_SVC_DISABLE = 205, + QCA_NL80211_VENDOR_SUBCMD_SVC_VIEW = 206, ++ QCA_NL80211_VENDOR_SUBCMD_SAWF_DEF_Q_MAP = 207, ++ QCA_NL80211_VENDOR_SUBCMD_SAWF_DEF_Q_UNMAP = 208, ++ QCA_NL80211_VENDOR_SUBCMD_SAWF_DEF_Q_MAP_REP = 209, + }; + + enum qca_wlan_vendor_sawf_attr_config { +@@ -36,5 +39,15 @@ enum qca_wlan_vendor_sawf_attr_config { + QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_AFTER_LAST - 1, + }; + ++enum ath12k_vendor_attr_sawf_def_q_map { ++ QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_INVALID = 0, ++ QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_SVC_ID = 1, ++ QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_MAC_ADDR = 2, ++ /* keep last */ ++ QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_AFTER_LAST, ++ QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_MAX = ++ QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_AFTER_LAST - 1, ++}; ++ + int ath12k_vendor_register(struct ath12k_hw *ah); + #endif /* QCA_VENDOR_H */ diff --git a/feeds/ipq95xx/mac80211/patches/qca/754-01-ath12k-sawf-add-uplink-configuration-paraeters-in-se.patch b/feeds/ipq95xx/mac80211/patches/qca/754-01-ath12k-sawf-add-uplink-configuration-paraeters-in-se.patch new file mode 100644 index 000000000..611c40031 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/754-01-ath12k-sawf-add-uplink-configuration-paraeters-in-se.patch @@ -0,0 +1,179 @@ +From 5089a48ada309dc6669556835d7c5f1f5dddcf11 Mon Sep 17 00:00:00 2001 +From: Ganesh Babu Jothiram +Date: Tue, 4 Apr 2023 17:47:17 +0530 +Subject: [PATCH 1/2] ath12k: sawf: add uplink configuration parameters in + service class paramters. + +extend support for uplink configuration parameter in service class creation. + +Signed-off-by: Ganesh Babu Jothiram +--- + drivers/net/wireless/ath/ath12k/sawf.c | 6 +++ + drivers/net/wireless/ath/ath12k/sawf.h | 18 +++++++++ + drivers/net/wireless/ath/ath12k/vendor.c | 51 +++++++++++++++++++++++- + drivers/net/wireless/ath/ath12k/vendor.h | 6 +++ + 4 files changed, 80 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath12k/sawf.c b/drivers/net/wireless/ath/ath12k/sawf.c +index a2f5acf..bfb30dd 100644 +--- a/drivers/net/wireless/ath/ath12k/sawf.c ++++ b/drivers/net/wireless/ath/ath12k/sawf.c +@@ -108,6 +108,12 @@ void ath12k_update_svc_class(struct ath12k_sawf_svc_params *sawf_params) + new_param->tid = sawf_params->tid; + new_param->msdu_rate_loss = sawf_params->msdu_rate_loss; + new_param->configured = sawf_params->configured; ++ new_param->ul_service_interval = sawf_params->ul_service_interval; ++ new_param->ul_burst_size = sawf_params->ul_burst_size; ++ new_param->ul_min_tput = sawf_params->ul_min_tput; ++ new_param->ul_max_latency = sawf_params->ul_max_latency; ++ new_param->ul_ofdma_disable = sawf_params->ul_ofdma_disable; ++ new_param->ul_mu_mimo_disable = sawf_params->ul_mu_mimo_disable; + } + + bool ath12k_validate_sawf_param(struct ath12k_sawf_svc_params *params) +diff --git a/drivers/net/wireless/ath/ath12k/sawf.h b/drivers/net/wireless/ath/ath12k/sawf.h +index 7824357..0eaa573 100644 +--- a/drivers/net/wireless/ath/ath12k/sawf.h ++++ b/drivers/net/wireless/ath/ath12k/sawf.h +@@ -106,6 +106,12 @@ enum SAWF_SVC_PARAM_DEFAULTS { + SAWF_SVC_PARAM_DEFAULT_PRIORITY = 0, + SAWF_SVC_PARAM_DEFAULT_TID = 0xffffffff, + SAWF_SVC_PARAM_DEFAULT_MSDU_LOSS_RATE = 0, ++ SAWF_SVC_PARAM_DEFAULT_UL_BURST_SIZE = 0, ++ SAWF_SVC_PARAM_DEFAULT_UL_MIN_TPUT = 0, ++ SAWF_SVC_PARAM_DEFAULT_UL_MAX_LATENCY = 0xffffffff, ++ SAWF_SVC_PARAM_DEFAULT_UL_SVC_INTERVAL = 0xffffffff, ++ SAWF_SVC_PARAM_DEFAULT_UL_OFDMA_DISABLE = 0, ++ SAWF_SVC_PARAM_DEFAULT_UL_MU_MIMO_DISABLE = 0, + }; + + #define DELAY_BOUND_ULTRA_LOW 10 +@@ -131,6 +137,12 @@ enum SAWF_SVC_PARAM_DEFAULTS { + * @priority: Priority + * @tid: TID + * @msdu_rate_loss: MSDU loss rate in parts per million ++ * @ul_service_interval: Uplink service interval ++ * @ul_burst_size: Uplink Burst Size ++ * @ul_min_tput: Uplink min_throughput ++ * @ul_max_latency: Uplink max latency ++ * @ul_ofdma_disable: Disable ofdma ++ * @ul_mu_mimo_disable: Disale MU MIMO + * @configured: indicating if the serivice class is configured. + */ + +@@ -146,6 +158,12 @@ struct ath12k_sawf_svc_params { + u32 priority; + u32 tid; + u32 msdu_rate_loss; ++ u32 ul_service_interval; ++ u32 ul_burst_size; ++ u32 ul_min_tput; ++ u32 ul_max_latency; ++ bool ul_ofdma_disable; ++ bool ul_mu_mimo_disable; + bool configured; + }; + +diff --git a/drivers/net/wireless/ath/ath12k/vendor.c b/drivers/net/wireless/ath/ath12k/vendor.c +index e64307a..eb7df8d 100644 +--- a/drivers/net/wireless/ath/ath12k/vendor.c ++++ b/drivers/net/wireless/ath/ath12k/vendor.c +@@ -23,6 +23,12 @@ ath12k_vendor_sawf_config_policy[QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX + 1] = { + [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_PRIO] = {.type = NLA_U32}, + [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_TID] = {.type = NLA_U32}, + [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_RATE_LOSS] = {.type = NLA_U32}, ++ [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_SVC_INTERVAL] = {.type = NLA_U32}, ++ [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MIN_TPUT] = {.type = NLA_U32}, ++ [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MAX_LATENCY] = {.type = NLA_U32}, ++ [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_BURST_SIZE] = {.type = NLA_U32}, ++ [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_OFDMA_DISABLE] = {.type = NLA_U8}, ++ [QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MU_MIMO_DISABLE] = {.type = NLA_U8}, + }; + + static const struct nla_policy +@@ -47,6 +53,12 @@ static void ath12k_set_default_values(struct ath12k_sawf_svc_params *param) + param->priority = SAWF_SVC_PARAM_DEFAULT_PRIORITY; + param->tid = SAWF_SVC_PARAM_DEFAULT_TID; + param->msdu_rate_loss = SAWF_SVC_PARAM_DEFAULT_MSDU_LOSS_RATE; ++ param->ul_burst_size = SAWF_SVC_PARAM_DEFAULT_UL_BURST_SIZE; ++ param->ul_min_tput = SAWF_SVC_PARAM_DEFAULT_UL_MIN_TPUT; ++ param->ul_max_latency = SAWF_SVC_PARAM_DEFAULT_UL_MAX_LATENCY; ++ param->ul_service_interval = SAWF_SVC_PARAM_DEFAULT_UL_SVC_INTERVAL; ++ param->ul_ofdma_disable = SAWF_SVC_PARAM_DEFAULT_UL_OFDMA_DISABLE; ++ param->ul_mu_mimo_disable = SAWF_SVC_PARAM_DEFAULT_UL_MU_MIMO_DISABLE; + } + + static int ath12k_vendor_set_sawf_config(struct wiphy *wiphy, +@@ -101,6 +113,24 @@ static int ath12k_vendor_set_sawf_config(struct wiphy *wiphy, + sawf_param.tid = nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_TID]); + if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_RATE_LOSS]) + sawf_param.msdu_rate_loss = nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_RATE_LOSS]); ++ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_SVC_INTERVAL]) ++ sawf_param.ul_service_interval = ++ nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_SVC_INTERVAL]); ++ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_BURST_SIZE]) ++ sawf_param.ul_burst_size = ++ nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_BURST_SIZE]); ++ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MIN_TPUT]) ++ sawf_param.ul_min_tput = ++ nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MIN_TPUT]); ++ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MAX_LATENCY]) ++ sawf_param.ul_max_latency = ++ nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MAX_LATENCY]); ++ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_OFDMA_DISABLE]) ++ sawf_param.ul_ofdma_disable = ++ nla_get_u8(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_OFDMA_DISABLE]); ++ if (tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MU_MIMO_DISABLE]) ++ sawf_param.ul_mu_mimo_disable = ++ nla_get_u8(tb[QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MU_MIMO_DISABLE]); + + ret = ath12k_create_send_svc_params(&sawf_param); + +@@ -235,7 +265,26 @@ static int ath12k_vendor_view_sawf_config(struct wiphy *wihpy, + svc_class->tid) || + nla_put_u32(msg, + QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_RATE_LOSS, +- svc_class->msdu_rate_loss)) ++ svc_class->msdu_rate_loss) || ++ nla_put_u32(msg, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_SVC_INTERVAL, ++ svc_class->ul_service_interval) || ++ nla_put_u32(msg, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MIN_TPUT, ++ svc_class->ul_min_tput) || ++ nla_put_u32(msg, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MAX_LATENCY, ++ svc_class->ul_max_latency) || ++ nla_put_u32(msg, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_BURST_SIZE, ++ svc_class->ul_burst_size) || ++ nla_put_u8(msg, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_OFDMA_DISABLE, ++ svc_class->ul_ofdma_disable) || ++ nla_put_u8(msg, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MU_MIMO_DISABLE, ++ svc_class->ul_mu_mimo_disable)) ++ + goto nla_put_failure; + + nest_end_length = nla_nest_end(msg, sawf_svc_class); +diff --git a/drivers/net/wireless/ath/ath12k/vendor.h b/drivers/net/wireless/ath/ath12k/vendor.h +index 855e72f..6a793d7 100644 +--- a/drivers/net/wireless/ath/ath12k/vendor.h ++++ b/drivers/net/wireless/ath/ath12k/vendor.h +@@ -32,6 +32,12 @@ enum qca_wlan_vendor_sawf_attr_config { + QCN_WLAN_VENDOR_ATTR_SAWF_SVC_PRIO, + QCN_WLAN_VENDOR_ATTR_SAWF_SVC_TID, + QCN_WLAN_VENDOR_ATTR_SAWF_SVC_MSDU_RATE_LOSS, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_SVC_INTERVAL, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MIN_TPUT, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MAX_LATENCY, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_BURST_SIZE, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_OFDMA_DISABLE, ++ QCN_WLAN_VENDOR_ATTR_SAWF_SVC_UL_MU_MIMO_DISABLE, + + /* keep last */ + QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_AFTER_LAST, +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/754-02-ath12k-sawf-uplink-configuration-support.patch b/feeds/ipq95xx/mac80211/patches/qca/754-02-ath12k-sawf-uplink-configuration-support.patch new file mode 100644 index 000000000..38cfc0700 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/754-02-ath12k-sawf-uplink-configuration-support.patch @@ -0,0 +1,600 @@ +From 4cd05a8f61ed39c747e63d91ef649c3b2d228529 Mon Sep 17 00:00:00 2001 +From: Ganesh Babu Jothiram +Date: Thu, 6 Apr 2023 00:22:59 +0530 +Subject: [PATCH 2/2] ath12k: sawf: add uplink configuration support. + +Driver shall register to ECM to provide uplink configuration support. +The uplink configuration routine fetches the uplink configuration +parameters from service class configuration and send peer tid letency +configuration to firmware via wmi command WMI_PEER_TID_LATENCY_CONFIG_CMDID. + +Signed-off-by: Ganesh Babu Jothiram +--- + drivers/net/wireless/ath/ath12k/core.c | 33 ++++ + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/sawf.c | 202 +++++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/sawf.h | 149 ++++++++++++++++++ + drivers/net/wireless/ath/ath12k/wmi.h | 8 + + 5 files changed, 393 insertions(+) + +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -18,6 +18,7 @@ + #include "debug.h" + #include "hif.h" + #include "wow.h" ++#include "sawf.h" + + unsigned int ath12k_debug_mask; + module_param_named(debug_mask, ath12k_debug_mask, uint, 0644); +@@ -2378,6 +2379,21 @@ int ath12k_sawf_send_disable_soc(u8 svc_ + return ret; + } + ++int ath12k_core_sawf_ul_config(struct net_device *dev, struct ath12k_sawf_wmi_peer_latency_param *latency_info) ++{ ++ struct ath12k_base *ab; ++ u16 peer_id; ++ int ret = -EOPNOTSUPP; ++ ++ if (!latency_info) ++ return -EINVAL; ++ ++ ab = ath12k_sawf_get_ab_from_netdev(dev, latency_info->peer_mac, &peer_id); ++ if (ab) ++ ret = ath12k_sawf_wmi_config_ul(ab, latency_info); ++ return ret; ++} ++ + static int ath12k_init(void) + { + int ret; +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -1484,6 +1484,7 @@ void ath12k_fw_stats_reset(struct ath12k + void ath12k_fw_stats_free(struct ath12k_fw_stats *stats); + int ath12k_send_sawf_configs_soc(struct ath12k_sawf_svc_params *new_param); + int ath12k_sawf_send_disable_soc(u8 svc_id); ++int ath12k_core_sawf_ul_config(struct net_device *dev, struct ath12k_sawf_wmi_peer_latency_param *latency_info); + + static inline const char *ath12k_scan_state_str(enum ath12k_scan_state state) + { +--- a/drivers/net/wireless/ath/ath12k/sawf.c ++++ b/drivers/net/wireless/ath/ath12k/sawf.c +@@ -20,6 +20,7 @@ MODULE_PARM_DESC(sawf, "Enable SAWF feat + + static struct ecm_classifier_emesh_sawf_callbacks ecm_wifi_sawf_callback = { + .update_service_id_get_msduq = ath12k_sawf_get_msduq, ++ .sawf_conn_sync = ath12k_sawf_config_ul, + }; + + static struct ath12k_sawf_ctx *sawf_ctx; +@@ -41,6 +42,9 @@ void ath12k_sawf_init(struct ath12k_base + sawf_ctx->max_msduq_per_tid = ab->max_msduq_per_tid; + sawf_ctx->default_msduq_per_tid = ab->default_msduq_per_tid; + spin_lock_init(&sawf_ctx->sawf_svc_lock); ++ sawf_ctx->workqueue = create_singlethread_workqueue("sawf_wq"); ++ INIT_WORK(&sawf_ctx->ul_configure, ath12k_send_ul_configs); ++ INIT_LIST_HEAD(&sawf_ctx->list); + } else {/* Already initialized */ + return; + } +@@ -50,6 +54,12 @@ void ath12k_sawf_init(struct ath12k_base + else + ath12k_dbg(ab, ATH12K_DBG_SAWF, "ECM msduq callback register success\n"); + ++ if (ecm_classifier_emesh_sawf_conn_sync_callback_register(&ecm_wifi_sawf_callback)) ++ ath12k_err(NULL, "ECM uplink cfg cb reg fail\n"); ++ else ++ ath12k_dbg(ab, ATH12K_DBG_SAWF, ++ "ECM uplink cfg callback register success\n"); ++ + ath12k_info(NULL, "SAWF context initialized\n"); + } + +@@ -58,18 +68,25 @@ void ath12k_sawf_deinit(struct ath12k_ba + if (!ath12k_sawf_enable) + return; + ++ if (!sawf_ctx) ++ return; ++ + /* During firmware crash recovery scenario, the SAWF context + * will be retained. + */ +- if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags)) +- return; +- +- if (!sawf_ctx) ++ if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags)) { ++ cancel_work_sync(&sawf_ctx->ul_configure); + return; ++ } + + ecm_classifier_emesh_sawf_msduq_callback_unregister(); + ath12k_dbg(ab, ATH12K_DBG_SAWF, "ECM msduq callback unregister success\n"); + ++ ecm_classifier_emesh_sawf_conn_sync_callback_unregister(); ++ ath12k_dbg(ab, ATH12K_DBG_SAWF, "ECM uplink cfg callback unregister success\n"); ++ ++ cancel_work_sync(&sawf_ctx->ul_configure); ++ destroy_workqueue(sawf_ctx->workqueue); + kfree(sawf_ctx); + sawf_ctx = NULL; + ath12k_info(NULL, "SAWF context freed\n"); +@@ -881,3 +898,247 @@ unlock_ab_base: + spin_unlock_bh(&ab->base_lock); + rcu_read_unlock(); + } ++ ++static void ath12k_sawf_core_send_ul_config(struct net_device *dev, u8 svc_id, u8 *mac_addr, u8 add_or_sub) ++{ ++ struct ath12k_sawf_svc_params *svc_param; ++ struct ath12k_sawf_wmi_peer_latency_param latency_info; ++ struct ath12k_sawf_ctx *sawf; ++ int ret; ++ ++ sawf = ath12k_get_sawf_context(); ++ if (!sawf || !mac_addr) ++ return; ++ ++ spin_lock_bh(&sawf->sawf_svc_lock); ++ if (!ath12k_svc_id_valid(svc_id) || ++ !ath12k_svc_id_configured(svc_id)) { ++ spin_unlock_bh(&sawf->sawf_svc_lock); ++ return; ++ } ++ ++ svc_param = &sawf->svc_classes[SVC_INDEX(svc_id)]; ++ ++ if (!svc_param->ul_service_interval || ++ !svc_param->ul_burst_size) { ++ spin_unlock_bh(&sawf->sawf_svc_lock); ++ return; ++ } ++ ++ latency_info.svc_id = svc_id; ++ latency_info.ul_enable = 1; ++ latency_info.sawf_ul_param = 1; ++ latency_info.ac = ath12k_tid_to_ac(svc_param->tid); ++ latency_info.latency_tid = svc_param->tid; ++ latency_info.service_interval = svc_param->ul_service_interval; ++ latency_info.burst_size = svc_param->ul_burst_size; ++ latency_info.min_throughput = svc_param->ul_min_tput; ++ latency_info.max_latency = svc_param->ul_max_latency; ++ latency_info.add_or_sub = add_or_sub; ++ latency_info.ofdma_disable = svc_param->ul_ofdma_disable ? 1 : 0; ++ latency_info.mu_mimo_disable = svc_param->ul_mu_mimo_disable ? 1 : 0; ++ ++ spin_unlock_bh(&sawf->sawf_svc_lock); ++ ether_addr_copy(latency_info.peer_mac, mac_addr); ++ ++ ret = ath12k_core_sawf_ul_config(dev, &latency_info); ++ if (ret) ++ ath12k_err(NULL, ++ "SAWF:ul cfg fail for src peer %pM ret %d\n", ++ mac_addr, ret); ++} ++ ++void ath12k_send_ul_configs(struct work_struct *work) ++{ ++ struct ath12k_sawf_ctx *sawf; ++ struct ath_ul_params *ul_params, *tmp; ++ ++ sawf = ath12k_get_sawf_context(); ++ if (!sawf) { ++ ath12k_err(NULL, "SAWF ctx is invalid\n"); ++ return; ++ } ++ ++ spin_lock_bh(&sawf->sawf_svc_lock); ++ list_for_each_entry_safe(ul_params, tmp, &sawf->list, list) { ++ list_del(&ul_params->list); ++ spin_unlock_bh(&sawf->sawf_svc_lock); ++ ++ ath12k_sawf_core_send_ul_config(ul_params->src_dev, ++ ul_params->fw_service_id, ++ ul_params->src_mac, ++ ul_params->add_or_sub); ++ ath12k_sawf_core_send_ul_config(ul_params->dest_dev, ++ ul_params->rv_service_id, ++ ul_params->dst_mac, ++ ul_params->add_or_sub); ++ kfree(ul_params); ++ spin_lock_bh(&sawf->sawf_svc_lock); ++ } ++ spin_unlock_bh(&sawf->sawf_svc_lock); ++} ++ ++void ath12k_sawf_config_ul(struct net_device *dest_dev, u8 *dst_mac, struct net_device *src_dev, u8 *src_mac, ++ u8 fw_service_id, u8 rv_service_id, ++ u8 add_or_sub) ++{ ++ struct ath12k_sawf_ctx *sawf; ++ struct ath_ul_params *ul_params; ++ ++ sawf = ath12k_get_sawf_context(); ++ if (!sawf) { ++ ath12k_err(NULL, "SAWF ctx is invalid\n"); ++ return; ++ } ++ ++ ul_params = kzalloc(sizeof(*ul_params), GFP_NOWAIT); ++ if (!ul_params) { ++ ath12k_err(NULL,"Failed to allocate memory during SAWF UL configuration\n"); ++ return; ++ } ++ ul_params->dest_dev = dest_dev; ++ ul_params->src_dev = src_dev; ++ ether_addr_copy(ul_params->dst_mac, dst_mac); ++ ether_addr_copy(ul_params->src_mac, src_mac); ++ ul_params->fw_service_id = fw_service_id; ++ ul_params->rv_service_id = rv_service_id; ++ ul_params->add_or_sub = add_or_sub; ++ spin_lock_bh(&sawf->sawf_svc_lock); ++ list_add_tail(&ul_params->list, &sawf->list); ++ spin_unlock_bh(&sawf->sawf_svc_lock); ++ ++ queue_work(sawf->workqueue, &sawf->ul_configure); ++} ++ ++int ath12k_sawf_wmi_config_peer_latency(struct ath12k *ar, ++ struct ath12k_sawf_wmi_peer_latency_param *latency_info) ++{ ++ struct ath12k_pdev_wmi *wmi = ar->wmi; ++ struct wmi_tid_latency_info *tid_latency_info; ++ struct wmi_peer_tid_latency_config_fixed_param *cmd; ++ struct sk_buff *skb; ++ struct wmi_tlv *tlv; ++ u32 len; ++ u32 num_peer = 1; ++ int ret; ++ ++ if (!latency_info) ++ return -EINVAL; ++ ++ len = sizeof(*cmd) + TLV_HDR_SIZE + (num_peer * sizeof(*tid_latency_info)); ++ skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len); ++ if (!skb) { ++ ath12k_warn(ar->ab, "wmi cfg peer latency fail-Outof Memory\n"); ++ return -ENOMEM; ++ } ++ ++ cmd = (struct wmi_peer_tid_latency_config_fixed_param *)skb->data; ++ cmd->tlv_header = ++ le32_encode_bits(WMI_TAG_PEER_TID_LATENCY_CONFIG_FIXED_PARAM, ++ WMI_TLV_TAG) | ++ le32_encode_bits((sizeof(*cmd) - TLV_HDR_SIZE), ++ WMI_TLV_LEN); ++ ++ cmd->pdev_id = cpu_to_le32(ar->pdev->pdev_id); ++ ++ tlv = (struct wmi_tlv *)(skb->data + sizeof(*cmd)); ++ len = sizeof(*tid_latency_info) * num_peer; ++ ++ tlv->header = le32_encode_bits(WMI_TAG_ARRAY_STRUCT, WMI_TLV_TAG) | ++ le32_encode_bits(len, WMI_TLV_LEN); ++ ++ tid_latency_info = ++ (struct wmi_tid_latency_info *)(skb->data + sizeof(*cmd) + TLV_HDR_SIZE); ++ ++ tid_latency_info->tlv_header = ++ le32_encode_bits(WMI_TAG_TID_LATENCY_INFO, ++ WMI_TLV_TAG) | ++ le32_encode_bits((sizeof(*tid_latency_info) - TLV_HDR_SIZE), ++ WMI_TLV_LEN); ++ ++ tid_latency_info->service_interval = cpu_to_le32(latency_info->service_interval); ++ tid_latency_info->burst_size_diff = cpu_to_le32(latency_info->burst_size); ++ tid_latency_info->max_latency = cpu_to_le32(latency_info->max_latency); ++ tid_latency_info->min_tput = cpu_to_le32(latency_info->min_throughput); ++ ++ ether_addr_copy(tid_latency_info->destmac.addr, latency_info->peer_mac); ++ ++ tid_latency_info->latency_tid_info = ++ le32_encode_bits(latency_info->latency_tid, LATENCY_TID_INFO_TID_NUM) | ++ le32_encode_bits(latency_info->ac, LATENCY_TID_INFO_AC) | ++ le32_encode_bits(latency_info->dl_enable, LATENCY_TID_INFO_DL_EN) | ++ le32_encode_bits(latency_info->ul_enable, LATENCY_TID_INFO_UL_EN) | ++ le32_encode_bits(latency_info->add_or_sub, LATENCY_TID_INFO_BURST_SZ_SUM) | ++ le32_encode_bits(latency_info->sawf_ul_param, LATENCY_TID_INFO_SAWF_UL_PARAM)| ++ le32_encode_bits(latency_info->ofdma_disable, ++ LATENCY_TID_INFO_UL_OFDMA_DISABLE)| ++ le32_encode_bits(latency_info->mu_mimo_disable, ++ LATENCY_TID_INFO_UL_MU_MIMO_DISABLE); ++ ++ ret = ath12k_wmi_cmd_send(wmi, skb, WMI_PEER_TID_LATENCY_CONFIG_CMDID); ++ if (ret) { ++ ath12k_warn(ar->ab, ++ "failed to submit WMI_PEER_TID_LATENCY_CONFIG_CMDID cmd %d\n", ++ ret); ++ dev_kfree_skb(skb); ++ } ++ ++ return ret; ++} ++ ++int ath12k_sawf_wmi_config_ul(struct ath12k_base *ab, ++ struct ath12k_sawf_wmi_peer_latency_param *latency_info) ++{ ++ struct ath12k *ar; ++ struct ath12k_peer *peer; ++ int ret = -EOPNOTSUPP; ++ ++ if (!ab || ++ !latency_info) ++ return -EINVAL; ++ ++ spin_lock_bh(&ab->base_lock); ++ ++ peer = ath12k_peer_find_by_addr(ab, latency_info->peer_mac); ++ if (!peer) ++ goto unlock_base_lock; ++ ath12k_dbg(ab, ATH12K_DBG_SAWF, ++ "SAWF:Peer Found:config uplink:MAC %pM:svc_id %u\n", ++ latency_info->peer_mac, ++ latency_info->svc_id); ++ ++ ath12k_dbg(ab, ATH12K_DBG_SAWF, ++ "AC %u,TID %u,SVC interval %u,min_tput %u,max_latency %u", ++ latency_info->ac, ++ latency_info->latency_tid, ++ latency_info->service_interval, ++ latency_info->min_throughput, ++ latency_info->max_latency); ++ ++ ath12k_dbg(ab, ATH12K_DBG_SAWF, ++ "Burst Sz %u,add_or_sub %u dl_en %d ul_en %d sawf_ul %d\n", ++ latency_info->burst_size, ++ latency_info->add_or_sub, ++ latency_info->dl_enable, ++ latency_info->ul_enable, ++ latency_info->sawf_ul_param); ++ ++ ath12k_dbg(ab, ATH12K_DBG_SAWF, ++ "ofdma disable %d mu mimo disable %d\n", ++ latency_info->ofdma_disable, ++ latency_info->mu_mimo_disable); ++ ++ ar = ab->pdevs[peer->pdev_idx].ar; ++ if (ar) { ++ spin_unlock_bh(&ab->base_lock); ++ ret = ath12k_sawf_wmi_config_peer_latency(ar, latency_info); ++ return ret; ++ } else { ++ ath12k_err(ab,"SAWF UL Cfg fail, pdev_idx %d ar NULL \n", ++ peer->pdev_idx); ++ } ++ ++unlock_base_lock: ++ spin_unlock_bh(&ab->base_lock); ++ return ret; ++} +--- a/drivers/net/wireless/ath/ath12k/sawf.h ++++ b/drivers/net/wireless/ath/ath12k/sawf.h +@@ -167,6 +167,17 @@ struct ath12k_sawf_svc_params { + bool configured; + }; + ++struct ath_ul_params { ++ struct list_head list; ++ struct net_device *dest_dev; ++ struct net_device *src_dev; ++ u8 dst_mac[ETH_ALEN]; ++ u8 src_mac[ETH_ALEN]; ++ u8 fw_service_id; ++ u8 rv_service_id; ++ u8 add_or_sub; ++}; ++ + /** + * struct ath12k_sawf_ctx- SAWF context + * @svc_classes: List of all service classes +@@ -176,6 +187,9 @@ struct ath12k_sawf_ctx { + u32 max_msduq_per_tid; + u32 default_msduq_per_tid; + spinlock_t sawf_svc_lock; ++ struct workqueue_struct *workqueue; ++ struct work_struct ul_configure; ++ struct list_head list; + }; + + /** +@@ -317,6 +331,150 @@ struct ath12k_htt_t2h_sawf_q_map_report + u32 tid_report[ATH12K_SAWF_MAX_TID_SUPPORT]; //MAX_TIDT + } __packed; + ++/** ++ * struct wmi_peer_latency_info_params - peer latency info params ++ * @peer_mac: peer mac address ++ * @service_interval: service interval in miliseconds ++ * @burst_size: burst size in bytes ++ * @latency_tid: tid associated with this latency information ++ * @ac: Access Category associated with this tid ++ * @ul_enable: Bit to indicate ul latency enable ++ * @dl_enable: Bit to indicate dl latency enable ++ * @flow_id: Flow id associated with tid ++ * @add_or_sub: Bit to indicate add/delete of latency params ++ * @sawf_ul_param: Bit to indicate if UL params are for SAWF/SCS ++ * @max_latency: Maximum latency in milliseconds ++ * @min_throughput: Minimum throughput in Kbps ++ */ ++struct ath12k_sawf_wmi_peer_latency_param { ++ u8 svc_id; ++ u8 peer_mac[ETH_ALEN]; ++ u32 service_interval; ++ u32 burst_size; ++ u32 latency_tid :8, ++ ac :2, ++ ul_enable :1, ++ dl_enable :1, ++ flow_id :4, ++ add_or_sub :2, ++ sawf_ul_param :1, ++ ofdma_disable :1, ++ mu_mimo_disable :1, ++ reserved :11; ++ u32 max_latency; ++ u32 min_throughput; ++}; ++ ++#define LATENCY_TID_INFO_TID_NUM GENMASK(7, 0) ++#define LATENCY_TID_INFO_AC GENMASK(9, 8) ++#define LATENCY_TID_INFO_DL_EN BIT(10) ++#define LATENCY_TID_INFO_UL_EN BIT(11) ++#define LATENCY_TID_INFO_BURST_SZ_SUM GENMASK(13, 12) ++#define LATENCY_TID_INFO_MSDUQ_ID GENMASK(17, 14) ++#define LATENCY_TID_INFO_UL_OFDMA_DISABLE BIT(18) ++#define LATENCY_TID_INFO_UL_MU_MIMO_DISABLE BIT(19) ++#define LATENCY_TID_INFO_SAWF_UL_PARAM BIT(20) ++ ++/* struct wmi_peer_tid_latency_config_fixed_param: ++ * Currently wmi_peer_tid_set_latency_request_fixed_param will be sent ++ * per TID per latency configured client. ++ * In future this command might come for multiple latency configured ++ * clients together. ++ * The clients are expected to be associated while receiving this command. ++ * @tlv_header ++ * TLV tag and len; ++ * @pdev_id ++ * device ID ++ */ ++struct wmi_peer_tid_latency_config_fixed_param { ++ __le32 tlv_header; ++ __le32 pdev_id; ++} __packed; ++ ++/** struct wmi_tid_latency_info ++ * @tlv_header: ++ * TLV Tag and Len ++ * @wmi_mac_addr destmac ++ * Mac address of end client ++ * @service_interval ++ * Maximum expected average delay between 2 schedules in milliseconds ++ * of given TID type when it has active traffic. ++ * 0x0 is considered as invalid service interval. ++ * @burst_size_diff ++ * Cumulative number of bytes are expected to be transmitted or ++ * received in the service interval when this specific Peer-TID ++ * has active traffic. ++ * If cumulative number of bytes is 0x0, it is considered as ++ * invalid burst size. In that case, firmware would try to transmit ++ * and receive as many bytes as it can for this specific Peer-TID. ++ * This burst size will be added or subtracted from vdev burst size ++ * based on burst size sum bit in latency tid info. ++ * The VDEV burst size will be considered to be 0 when no VDEV latency ++ * command is received. ++ * If host needs to set burst size for a peer then they can use the ++ * peer cmd and set burst size sum bit to 1. ++ * @max_latency ++ * The maximum end to end latency expectation, in milliseconds. ++ * If this value is 0x0, it shall be ignored. ++ * @max_per ++ * The maximum PER (as a percent) for the peer-TID, in range 1 - 100 ++ * If this value is 0x0, it shall be ignored. ++ * @min_tput ++ * The minimum guaranteed throughput to the peer-TID, in Kbps. ++ * If this value is 0x0, it shall be ignored. ++ * @latency_tid_info ++ * Bits 21-31 - Reserved (Shall be zero) ++ * Bit 20 - Flag to indicate SAWF UL params (and not mesh latenc ++ * Bit 19 - Disable UL MU-MIMO. If set, UL MU-MIMO is disabled ++ * for the specified AC. Note that TID level control is ++ * not possible for UL MU-MIMO (the granularity is AC). ++ * Bit 18 - Disable UL OFDMA. If set, UL OFDMA is disabled for ++ * the specified AC. Note that TID level control is not ++ * possible for UL OFDMA (the granularity is AC). ++ * Bits 14-17 - MSDU queue flow id within the TID for configuring ++ * latency info per MSDU flow queue ++ * Bit 12-13 - burst size sum. Bit to indicate whether to add or ++ * subtract burst_size_diff from vdev cmd burst size: ++ * 1 -> addition ++ * 2 -> subtraction ++ * Bit 11 - UL latency config indication. ++ * If this bit is set then this latency info will ++ * be used when triggering UL traffic. Until the ++ * AC specified in bits 8-9 has transferred at least ++ * burst_size amount of UL data within the service ++ * period, the AP will continue sending UL triggers ++ * when the STA has data of the specified access ++ * category ready to transmit. ++ * Note that the TID specified in bits 0-7 does not ++ * apply to UL; the TID-to-AC mapping applied to DL ++ * data that can be adjusted by the TID specified ++ * in bits 0-7 and the AC specified in bits 8-9 is ++ * distinct from the TID-to-AC mapping applied to ++ * UL data. ++ * Bit 10 - DL latency config indication. If the bit is set ++ * then DL TID will use this latency config. ++ * Bits 8 - 9 - This bit has info on the custom AC of DL TID. ++ * Also if bit 11 is set, the AP will apply some ++ * of these latency specs (in particular, burst_size) ++ * to UL traffic for this AC, by sending UL triggers ++ * until the desired amount of data has been received ++ * within the service period. ++ * Bits 0 - 7 - Specifies the TID of interest that corresponds ++ * to the AC specified in bits 8-9. This can be ++ * used to adjust the TID-to-AC mapping applied to ++ * DL data (if bit 10 is set). ++ */ ++struct wmi_tid_latency_info { ++ __le32 tlv_header; ++ struct wmi_mac_addr destmac; ++ __le32 service_interval; ++ __le32 burst_size_diff; ++ __le32 max_latency; ++ __le32 max_per; ++ __le32 min_tput; ++ __le32 latency_tid_info; ++} __packed; ++ + extern bool ath12k_sawf_enable; + struct ath12k_sawf_ctx *ath12k_get_sawf_context(void); + void ath12k_sawf_init(struct ath12k_base *ab); +@@ -330,9 +488,15 @@ int ath12k_get_tid(u8 svc_id); + int ath12k_sawf_reconfigure_on_crash(struct ath12k_base *ab); + int ath12k_create_send_svc_params(struct ath12k_sawf_svc_params *param); + int ath12k_sawf_disable_config(u8 svc_id); ++void ath12k_send_ul_configs(struct work_struct *work); + u16 ath12k_sawf_get_msduq(struct net_device *netdev, + u8 *peer_mac, u32 service_id, + u32 dscp, u32 rule_id); ++void ath12k_sawf_config_ul(struct net_device *dest_dev, u8 *dst_mac, struct net_device *src_dev, u8 *src_mac, ++ u8 fw_service_id, u8 rv_service_id, ++ u8 add_or_sub); ++int ath12k_sawf_wmi_config_ul(struct ath12k_base *ab, ++ struct ath12k_sawf_wmi_peer_latency_param *latency_info); + struct ath12k_base *ath12k_sawf_get_ab_from_netdev(struct net_device *dev, + u8 *peer_mac, + u16 *peer_id); +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -254,6 +254,7 @@ enum wmi_cmd_group { + WMI_GRP_TWT = 0x3e, + WMI_GRP_MOTION_DET = 0x3f, + WMI_GRP_SPATIAL_REUSE = 0x40, ++ WMI_GRP_LATENCY = 0x47, + WMI_GRP_MLO = 0x48, + WMI_GRP_SAWF = 0x49, + }; +@@ -683,6 +684,11 @@ enum wmi_tlv_cmd_id { + WMI_PDEV_OBSS_PD_SPATIAL_REUSE_CMDID = + WMI_TLV_CMD(WMI_GRP_SPATIAL_REUSE), + WMI_PDEV_OBSS_PD_SPATIAL_REUSE_SET_DEF_OBSS_THRESH_CMDID, ++ /** WMI commands specific to Tid level Latency config **/ ++ /** VDEV Latency Config command */ ++ WMI_VDEV_TID_LATENCY_CONFIG_CMDID = WMI_TLV_CMD(WMI_GRP_LATENCY), ++ /** TID Latency Request command */ ++ WMI_PEER_TID_LATENCY_CONFIG_CMDID, + WMI_MLO_LINK_SET_ACTIVE_CMDID = WMI_TLV_CMD(WMI_GRP_MLO), + WMI_MLO_SETUP_CMDID, + WMI_MLO_READY_CMDID, +@@ -2007,6 +2013,8 @@ enum wmi_tlv_tag { + WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT, + WMI_TAG_VDEV_SET_TPC_POWER_CMD = 0x3B5, + WMI_TAG_VDEV_CH_POWER_INFO, ++ WMI_TAG_PEER_TID_LATENCY_CONFIG_FIXED_PARAM = 0x3B9, ++ WMI_TAG_TID_LATENCY_INFO, + WMI_CTRL_PATH_CAL_STATS = 0x3BC, + WMI_CTRL_PATH_BTCOEX_STATS = 0x3FD, + WMI_TAG_EHT_RATE_SET = 0x3C4, diff --git a/feeds/ipq95xx/mac80211/patches/qca/755-mac80211-Fix-6-GHz-Band-capabilities-IE-advertisemen.patch b/feeds/ipq95xx/mac80211/patches/qca/755-mac80211-Fix-6-GHz-Band-capabilities-IE-advertisemen.patch new file mode 100644 index 000000000..e17bf25da --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/755-mac80211-Fix-6-GHz-Band-capabilities-IE-advertisemen.patch @@ -0,0 +1,43 @@ +From 2c6f115a508be7a8052baa1c2a39e3ff820a6bf7 Mon Sep 17 00:00:00 2001 +From: Ramya Gnanasekar +Date: Thu, 6 Apr 2023 22:52:34 +0530 +Subject: [PATCH] mac80211: Fix 6 GHz Band capabilities IE advertisement + +While adding 6GHz band capabilities, interface support and channel +is list is validated to confirm whether 6GHz is supported. +But in single wiphy, all the interfaces will have all the supported +channels. Due to this validation, mesh beacons adds +6 GHZ Band capabilities in beacon for 5GHz as well. + +Fix it by adding 6 GHz band check before adding the IE. + +Signed-off-by: Ramya Gnanasekar + +Index: b/net/mac80211/mesh.c +=================================================================== +--- a/net/mac80211/mesh.c 2023-04-13 15:27:33.052959371 +0530 ++++ b/net/mac80211/mesh.c 2023-04-13 15:35:09.385450821 +0530 +@@ -645,7 +645,8 @@ int mesh_add_he_6ghz_cap_ie(struct ieee8 + if (!iftd) + return 0; + +- ieee80211_ie_build_he_6ghz_cap(sdata, skb); ++ if (sband->band == NL80211_BAND_6GHZ) ++ ieee80211_ie_build_he_6ghz_cap(sdata, skb); + return 0; + } + +Index: b/net/mac80211/mlme.c +=================================================================== +--- a/net/mac80211/mlme.c 2023-04-13 15:27:33.052959371 +0530 ++++ b/net/mac80211/mlme.c 2023-04-13 15:28:46.452399833 +0530 +@@ -721,7 +721,8 @@ static void ieee80211_add_he_ie(struct i + /* trim excess if any */ + skb_trim(skb, skb->len - (pre_he_pos + he_cap_size - pos)); + +- ieee80211_ie_build_he_6ghz_cap(sdata, skb); ++ if (sband->band == NL80211_BAND_6GHZ) ++ ieee80211_ie_build_he_6ghz_cap(sdata, skb); + } + + static void ieee80211_add_eht_ie(struct ieee80211_sub_if_data *sdata, diff --git a/feeds/ipq95xx/mac80211/patches/qca/760-ath12k-Use-correct-offsets-for-handling-pci-and-ahb-.patch b/feeds/ipq95xx/mac80211/patches/qca/760-ath12k-Use-correct-offsets-for-handling-pci-and-ahb-.patch new file mode 100755 index 000000000..797e7c5f1 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/760-ath12k-Use-correct-offsets-for-handling-pci-and-ahb-.patch @@ -0,0 +1,64 @@ +From dc6aae5eb6b1f431a645dd792c6d7de248215f35 Mon Sep 17 00:00:00 2001 +From: Ramanathan Choodamani +Date: Mon, 3 Apr 2023 13:03:15 -0700 +Subject: [PATCH] ath12k: Use correct offsets for handling pci and ahb + interrupts during tx completion + +Using static pci interrupt offset handling functions while accessing tx +completion rings, +will not work for ahb interrupts. +This change makes provision for ahb interrupt handling as +well. + +Signed-off-by: Ramanathan Choodamani +--- + drivers/net/wireless/ath/ath12k/hal.c | 26 +++++++++++++++++--------- + 1 file changed, 17 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/hal.c b/drivers/net/wireless/ath/ath12k/hal.c +index 98b6aa2..4ce98b4 100644 +--- a/drivers/net/wireless/ath/ath12k/hal.c ++++ b/drivers/net/wireless/ath/ath12k/hal.c +@@ -2028,10 +2028,14 @@ int ath12k_hal_srng_setup(struct ath12k_base *ab, enum hal_ring_type type, + srng->u.src_ring.hp_addr = + (u32 *)((unsigned long)ab->mem + reg_base); + if (type == HAL_TCL_DATA) { +- srng->u.src_ring.hp_addr_direct = +- (u32 *)((unsigned long)ab->mem + +- HAL_DP_REG_WINDOW_OFFSET + +- (reg_base & WINDOW_RANGE_MASK)); ++ if (ab->hif.bus == ATH12K_BUS_PCI) ++ srng->u.src_ring.hp_addr_direct = ++ (u32 *)((unsigned long)ab->mem + ++ HAL_DP_REG_WINDOW_OFFSET + ++ (reg_base & WINDOW_RANGE_MASK)); ++ else ++ srng->u.src_ring.hp_addr_direct = ++ srng->u.src_ring.hp_addr; + } + } else { + ath12k_dbg(ab, ATH12K_DBG_HAL, +@@ -2066,11 +2070,15 @@ int ath12k_hal_srng_setup(struct ath12k_base *ab, enum hal_ring_type type, + (u32 *)((unsigned long)ab->mem + reg_base + + (HAL_REO1_RING_TP - HAL_REO1_RING_HP)); + if (type == HAL_WBM2SW_RELEASE) { +- srng->u.dst_ring.tp_addr_direct = +- (u32 *)((unsigned long)ab->mem + +- (reg_base & WINDOW_RANGE_MASK) + +- HAL_DP_REG_WINDOW_OFFSET + +- (HAL_REO1_RING_TP - HAL_REO1_RING_HP)); ++ if (ab->hif.bus == ATH12K_BUS_PCI) ++ srng->u.dst_ring.tp_addr_direct = ++ (u32 *)((unsigned long)ab->mem + ++ (reg_base & WINDOW_RANGE_MASK) + ++ HAL_DP_REG_WINDOW_OFFSET + ++ (HAL_REO1_RING_TP - HAL_REO1_RING_HP)); ++ else ++ srng->u.dst_ring.tp_addr_direct = ++ srng->u.dst_ring.tp_addr; + } + } else { + ath12k_dbg(ab, ATH12K_DBG_HAL, +-- +2.7.4 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/761-ath12k-Add-correct-RING_MASK_4-and-handle-irq-config.patch b/feeds/ipq95xx/mac80211/patches/qca/761-ath12k-Add-correct-RING_MASK_4-and-handle-irq-config.patch new file mode 100755 index 000000000..0db94fac9 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/761-ath12k-Add-correct-RING_MASK_4-and-handle-irq-config.patch @@ -0,0 +1,84 @@ +From 1f06a75fd5b53ca9281df8486af4ccc18f2725c2 Mon Sep 17 00:00:00 2001 +From: Ramanathan Choodamani +Date: Mon, 3 Apr 2023 21:52:35 -0700 +Subject: [PATCH] ath12k: Fix the transmit completion mask and handle irq +configuration properly + +Fix the transmit completion ring4 with the right mask ATH12K_TX_RING_MASK_4, +instead of ATH12K_TX_RING_MASK_3. ATH12K_TX_RING_MASK_3 is used for error +rx release ring. +Flush cache entries before updating the ring indexes + +Signed-off-by: Ramanathan Choodamani +--- + drivers/net/wireless/ath/ath12k/ahb.c | 7 +++++-- + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/dp_tx.c | 1 + + drivers/net/wireless/ath/ath12k/hw.c | 2 +- + 4 files changed, 8 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/ahb.c b/drivers/net/wireless/ath/ath12k/ahb.c +index c50f2c8..3ed7fb0 100644 +--- a/drivers/net/wireless/ath/ath12k/ahb.c ++++ b/drivers/net/wireless/ath/ath12k/ahb.c +@@ -169,7 +169,7 @@ static inline void ath12k_ahb_write32(struct ath12k_base *ab, u32 offset, + ab->mem_ce, offset, value); + iowrite32(value, ab->mem_ce + offset); + } else { +- ath12k_dbg(ab, ATH12K_DBG_OFFSET, "mem:%p offset:%x value:%d\n", ++ ath12k_dbg(ab, ATH12K_DBG_OFFSET, "dp mem:%p offset:%x value:%d\n", + ab->mem, offset, value); + iowrite32(value, ab->mem + offset); + } +@@ -502,7 +502,10 @@ static int ath12k_ahb_config_ext_irq(struct ath12k_base *ab) + ath12k_ahb_ext_grp_napi_poll, NAPI_POLL_WEIGHT); + + for (j = 0; j < ATH12K_EXT_IRQ_NUM_MAX; j++) { +- if (ab->hw_params->ring_mask->tx[i] & BIT(j)) { ++ if (ab->hw_params->ring_mask->tx[i] && ++ (j <= ATH12K_MAX_TCL_RING_NUM) && ++ (ab->hw_params->ring_mask->tx[i] & ++ BIT(ab->hw_params->hal_ops->tcl_to_wbm_rbm_map[j].wbm_ring_num))) { + irq_grp->irqs[num_irq++] = + wbm2host_tx_completions_ring1 - j; + } +diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h +index 60b96a0..34a30d9 100644 +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -157,6 +157,7 @@ extern bool ath12k_cold_boot_cal; + + #define ATH12K_IRQ_NUM_MAX 57 + #define ATH12K_EXT_IRQ_NUM_MAX 16 ++#define ATH12K_MAX_TCL_RING_NUM 3 + + struct ath12k_ext_irq_grp { + struct ath12k_base *ab; +diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c +index 12e4f7d..47f284a 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -491,6 +491,7 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif, + tcl_cmd->info4 = arvif->desc.info4; + tcl_cmd->info5 = 0; + ++ dsb(st); + ath12k_hal_srng_access_umac_src_ring_end_nolock(tcl_ring); + + ath12k_dbg_dump(ab, ATH12K_DBG_DP_TX, NULL, "dp tx msdu: ", +diff --git a/drivers/net/wireless/ath/ath12k/hw.c b/drivers/net/wireless/ath/ath12k/hw.c +index 8809454..012d43b 100644 +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -841,7 +841,7 @@ static const struct ath12k_hw_ring_mask ath12k_hw_ring_mask_ipq5332 = { + ATH12K_TX_RING_MASK_0, + ATH12K_TX_RING_MASK_1, + ATH12K_TX_RING_MASK_2, +- ATH12K_TX_RING_MASK_3, ++ ATH12K_TX_RING_MASK_4, + 0, 0, 0, 0, 0, 0, 0, 0, + }, + .rx_mon_dest = { +-- +2.7.4 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/762-ath12k-Fix-memory-leak-during-peer-frag-setup.patch b/feeds/ipq95xx/mac80211/patches/qca/762-ath12k-Fix-memory-leak-during-peer-frag-setup.patch new file mode 100644 index 000000000..3480d20f4 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/762-ath12k-Fix-memory-leak-during-peer-frag-setup.patch @@ -0,0 +1,298 @@ +From 7ff6bbe962cbf2ff69e834e73d8a451dc7546729 Mon Sep 17 00:00:00 2001 +From: P Praneesh +Date: Thu, 6 Apr 2023 22:01:21 +0530 +Subject: [PATCH] ath12k: Fix memory leak during peer frag setup + +For 2-link MLO, peer frag setup is expected to set for primary link alone. +So, for the non primary link, crypto_alloc_shash allocates memory through +kmalloc which is not getting released before returning from the function. +Similarly, if peer find fails, needs to handle the memory allocated through +crypto_alloc_shash should be released. + +Fix it by moving the peer find logic out of ath12k_dp_rx_peer_frag_setup. +So that it can be called only for the primary link. Also it avoids +unnecessary peer look up and crypto allocation. + +Fixes: Id27da363fd12 (ath12k: Fixes for Multi link bringup and handling) + +Signed-off-by: P Praneesh +--- + drivers/net/wireless/ath/ath12k/dp.c | 34 ++++++++------- + drivers/net/wireless/ath/ath12k/dp_rx.c | 55 +++++++++---------------- + drivers/net/wireless/ath/ath12k/dp_rx.h | 5 ++- + 3 files changed, 42 insertions(+), 52 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -93,44 +93,53 @@ int ath12k_dp_peer_setup(struct ath12k * + { + struct ath12k_base *ab = ar->ab; + struct ath12k_peer *peer; ++ struct crypto_shash *tfm; + int ret = 0, tid; + +- /* TODO setup resources only for primary link peer for ML case */ ++ tfm = crypto_alloc_shash("michael_mic", 0, 0); ++ if (IS_ERR(tfm)) ++ return PTR_ERR(tfm); ++ ++ spin_lock_bh(&ab->base_lock); ++ peer = ath12k_peer_find(ab, arvif->vdev_id, arsta->addr); ++ if (!peer) { ++ ath12k_warn(ab, "failed to lookup peer %pM on vdev %d\n", ++ arsta->addr, arvif->vdev_id); ++ ret = -ENOENT; ++ goto free_shash; ++ } ++ ++ if (!peer->primary_link) { ++ ret = 0; ++ goto free_shash; ++ } + + for (tid = 0; tid <= IEEE80211_NUM_TIDS; tid++) { +- ret = ath12k_dp_rx_peer_tid_setup(ar, arsta->addr, arvif->vdev_id, +- tid, 1, 0, HAL_PN_TYPE_NONE); ++ ret = ath12k_dp_rx_peer_tid_setup(ar, tid, 1, 0, HAL_PN_TYPE_NONE, peer); + if (ret) { + ath12k_warn(ab, "failed to setup rxd tid queue for tid %d: %d\n", + tid, ret); +- goto peer_clean; ++ goto peer_tid_clean; + } + } + +- ret = ath12k_dp_rx_peer_frag_setup(ar, arsta->addr, arvif->vdev_id); ++ ret = ath12k_dp_rx_peer_frag_setup(ar, peer, tfm); + if (ret) { + ath12k_warn(ab, "failed to setup rx defrag context\n"); +- tid--; +- goto peer_clean; ++ goto peer_tid_clean; + } + ++ spin_unlock_bh(&ab->base_lock); + /* TODO: Setup other peer specific resource used in data path */ + + return 0; + +-peer_clean: +- spin_lock_bh(&ab->base_lock); +- +- peer = ath12k_peer_find(ab, arvif->vdev_id, arsta->addr); +- if (!peer) { +- ath12k_warn(ab, "failed to find the peer to del rx tid\n"); +- spin_unlock_bh(&ab->base_lock); +- return -ENOENT; +- } +- +- for (; tid >= 0; tid--) ++peer_tid_clean: ++ for (tid--; tid >= 0; tid--) + ath12k_dp_rx_peer_tid_delete(ar, peer, tid); + ++free_shash: ++ crypto_free_shash(tfm); + spin_unlock_bh(&ab->base_lock); + + return ret; +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -1075,13 +1075,11 @@ static int ath12k_peer_rx_tid_reo_update + return 0; + } + +-int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_id, +- u8 tid, u32 ba_win_sz, u16 ssn, +- enum hal_pn_type pn_type) ++int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, u8 tid, u32 ba_win_sz, u16 ssn, ++ enum hal_pn_type pn_type, struct ath12k_peer *peer) + { + struct ath12k_base *ab = ar->ab; + struct ath12k_dp *dp = &ab->dp; +- struct ath12k_peer *peer; + struct ath12k_dp_rx_tid *rx_tid; + u32 hw_desc_sz; + u32 *addr_aligned; +@@ -1089,22 +1087,7 @@ int ath12k_dp_rx_peer_tid_setup(struct a + dma_addr_t paddr; + int ret; + +- spin_lock_bh(&ab->base_lock); +- +- peer = ath12k_peer_find(ab, vdev_id, peer_mac); +- if (!peer) { +- spin_unlock_bh(&ab->base_lock); +- ath12k_warn(ab, "failed to find the peer to set up rx tid\n"); +- return -ENOENT; +- } +- +- if (!peer->primary_link) { +- spin_unlock_bh(&ab->base_lock); +- return 0; +- } +- + if (ab->hw_params->reoq_lut_support && (!dp->reoq_lut.vaddr || !dp->ml_reoq_lut.vaddr)) { +- spin_unlock_bh(&ab->base_lock); + ath12k_warn(ab, "reo qref table is not setup\n"); + return -EINVAL; + } +@@ -1112,7 +1095,6 @@ int ath12k_dp_rx_peer_tid_setup(struct a + if (peer->peer_id > DP_MAX_PEER_ID || tid > IEEE80211_NUM_TIDS) { + ath12k_warn(ab, "peer id of peer %d or tid %d doesn't allow reoq setup\n", + peer->peer_id, tid); +- spin_unlock_bh(&ab->base_lock); + return -EINVAL; + } + +@@ -1122,10 +1104,9 @@ int ath12k_dp_rx_peer_tid_setup(struct a + paddr = rx_tid->paddr; + ret = ath12k_peer_rx_tid_reo_update(ar, peer, rx_tid, + ba_win_sz, ssn, true); +- spin_unlock_bh(&ab->base_lock); + if (ret) { + ath12k_warn(ab, "failed to update reo for peer %pM rx tid %d\n", +- peer_mac, tid); ++ peer->addr, tid); + return ret; + } + +@@ -1146,7 +1127,6 @@ int ath12k_dp_rx_peer_tid_setup(struct a + + vaddr = kzalloc(hw_desc_sz + HAL_LINK_DESC_ALIGN - 1, GFP_ATOMIC); + if (!vaddr) { +- spin_unlock_bh(&ab->base_lock); + return -ENOMEM; + } + +@@ -1160,9 +1140,8 @@ int ath12k_dp_rx_peer_tid_setup(struct a + + ret = dma_mapping_error(ab->dev, paddr); + if (ret) { +- spin_unlock_bh(&ab->base_lock); + ath12k_warn(ab, "failed to dma map for peer %pM rx tid :%d setup\n", +- peer_mac, tid); ++ peer->addr, tid); + goto err_mem_free; + } + +@@ -1179,11 +1158,11 @@ int ath12k_dp_rx_peer_tid_setup(struct a + ath12k_peer_rx_tid_qref_setup(ab, peer->ml_peer_id, tid, paddr); + else + ath12k_peer_rx_tid_qref_setup(ab, peer->peer_id, tid, paddr); +- spin_unlock_bh(&ab->base_lock); + } else { + spin_unlock_bh(&ab->base_lock); +- ret = ath12k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id, peer_mac, ++ ret = ath12k_wmi_peer_rx_reorder_queue_setup(ar, peer->vdev_id, peer->addr, + paddr, tid, 1, ba_win_sz); ++ spin_lock_bh(&ab->base_lock); + } + + return ret; +@@ -1201,6 +1180,7 @@ int ath12k_dp_rx_ampdu_start(struct ath1 + struct ath12k_base *ab = ar->ab; + struct ath12k_sta *ahsta = (void *)params->sta->drv_priv; + struct ath12k_link_sta *arsta; ++ struct ath12k_peer *peer; + int vdev_id; + int ret; + +@@ -1211,12 +1191,26 @@ int ath12k_dp_rx_ampdu_start(struct ath1 + + vdev_id = arsta->arvif->vdev_id; + +- ret = ath12k_dp_rx_peer_tid_setup(ar, arsta->addr, vdev_id, +- params->tid, params->buf_size, +- params->ssn, ahsta->pn_type); ++ spin_lock_bh(&ab->base_lock); ++ peer = ath12k_peer_find(ab, vdev_id, arsta->addr); ++ if (!peer) { ++ ath12k_warn(ab, "failed to lookup peer %pM on vdev %d\n", ++ arsta->addr, vdev_id); ++ spin_unlock_bh(&ab->base_lock); ++ return -ENOENT; ++ } ++ ++ if (!peer->primary_link) { ++ spin_unlock_bh(&ab->base_lock); ++ return 0; ++ } ++ ++ ret = ath12k_dp_rx_peer_tid_setup(ar, params->tid, params->buf_size, ++ params->ssn, ahsta->pn_type, peer); + if (ret) + ath12k_warn(ab, "failed to setup rx tid %d\n", ret); + ++ spin_unlock_bh(&ab->base_lock); + return ret; + } + +@@ -3519,32 +3513,13 @@ static void ath12k_dp_rx_frag_timer(stru + spin_unlock_bh(&rx_tid->ab->base_lock); + } + +-int ath12k_dp_rx_peer_frag_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_id) ++int ath12k_dp_rx_peer_frag_setup(struct ath12k *ar, struct ath12k_peer *peer, ++ struct crypto_shash *tfm) + { + struct ath12k_base *ab = ar->ab; +- struct crypto_shash *tfm; +- struct ath12k_peer *peer; + struct ath12k_dp_rx_tid *rx_tid; + int i; + +- tfm = crypto_alloc_shash("michael_mic", 0, 0); +- if (IS_ERR(tfm)) +- return PTR_ERR(tfm); +- +- spin_lock_bh(&ab->base_lock); +- +- peer = ath12k_peer_find(ab, vdev_id, peer_mac); +- if (!peer) { +- ath12k_warn(ab, "failed to find the peer to set up fragment info\n"); +- spin_unlock_bh(&ab->base_lock); +- return -ENOENT; +- } +- +- if (!peer->primary_link) { +- spin_unlock_bh(&ab->base_lock); +- return 0; +- } +- + for (i = 0; i <= IEEE80211_NUM_TIDS; i++) { + rx_tid = &peer->rx_tid[i]; + rx_tid->ab = ab; +@@ -3554,7 +3529,6 @@ int ath12k_dp_rx_peer_frag_setup(struct + + peer->tfm_mmic = tfm; + peer->dp_setup_done = true; +- spin_unlock_bh(&ab->base_lock); + + return 0; + } +--- a/drivers/net/wireless/ath/ath12k/dp_rx.h ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.h +@@ -135,9 +135,8 @@ int ath12k_dp_rx_peer_pn_replay_config(s + void ath12k_dp_rx_peer_tid_cleanup(struct ath12k *ar, struct ath12k_peer *peer); + void ath12k_dp_rx_peer_tid_delete(struct ath12k *ar, + struct ath12k_peer *peer, u8 tid); +-int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_id, +- u8 tid, u32 ba_win_sz, u16 ssn, +- enum hal_pn_type pn_type); ++int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, u8 tid, u32 ba_win_sz, u16 ssn, ++ enum hal_pn_type pn_type, struct ath12k_peer *peer); + void ath12k_dp_htt_htc_t2h_msg_handler(struct ath12k_base *ab, + struct sk_buff *skb); + int ath12k_dp_rx_pdev_reo_setup(struct ath12k_base *ab); +@@ -167,8 +166,8 @@ int ath12k_dp_htt_tlv_iter(struct ath12k + void *data); + int ath12k_dp_rx_pdev_mon_attach(struct ath12k *ar); + void ath12k_dp_rx_pdev_mon_detach(struct ath12k_base *ab, const int pdev_idx); +-int ath12k_dp_rx_peer_frag_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_id); +- ++int ath12k_dp_rx_peer_frag_setup(struct ath12k *ar, struct ath12k_peer *peer, ++ struct crypto_shash *tfm); + int ath12k_dp_rx_pktlog_start(struct ath12k_base *ab); + int ath12k_dp_rx_pktlog_stop(struct ath12k_base *ab, bool stop_timer); + u8 ath12k_dp_rx_h_l3pad(struct ath12k_base *ab, diff --git a/feeds/ipq95xx/mac80211/patches/qca/763-a-wifi-mac80211-add-framework-to-support-PPE-DS.patch b/feeds/ipq95xx/mac80211/patches/qca/763-a-wifi-mac80211-add-framework-to-support-PPE-DS.patch new file mode 100644 index 000000000..b9544e5d8 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/763-a-wifi-mac80211-add-framework-to-support-PPE-DS.patch @@ -0,0 +1,230 @@ +From ef5442225618d964142af51ea3abd899d071d921 Mon Sep 17 00:00:00 2001 +From: Pradeep Kumar Chitrapu +Date: Mon, 27 Mar 2023 11:23:22 -0700 +Subject: [PATCH 1/2] wifi: mac80211: add framework to support PPE DS + +Add framework to support PPE DS. Introduce new mac80211 ops +to attach or detach ppe ds. BY default ppe ds is disabled. This +can be enabled through writing 1 to module params +(/sys/module/mac80211/parameters/ppe_vp_accel) and wifi restart. +mac80211 tries to invoke driver ops for enabling direct +switching(DS). If this fails, it will try to enable ppe without +DS. + +Signed-off-by: Balamurugan Mahalingam +Signed-off-by: Ramanathan Choodamani +Signed-off-by: Pradeep Kumar Chitrapu +--- + include/net/mac80211.h | 16 +++++++++++++++- + net/mac80211/driver-ops.h | 28 ++++++++++++++++++++++++++++ + net/mac80211/ieee80211_i.h | 3 --- + net/mac80211/iface.c | 36 ++++++++++++++++++++++++++---------- + net/mac80211/rx.c | 4 ++-- + 5 files changed, 71 insertions(+), 16 deletions(-) + +diff --git a/include/net/mac80211.h b/include/net/mac80211.h +index 0ce9009d3ce9..032fb7b97f69 100644 +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -1966,7 +1966,8 @@ struct ieee80211_vif { + bool noqueue_enable; + + #ifdef CPTCFG_MAC80211_PPE_SUPPORT +- u32 ppe_vp_num; ++ int ppe_vp_num; ++ unsigned long ppe_vp_type; + #endif + /* must be last */ + u8 drv_priv[] __aligned(sizeof(void *)); +@@ -3683,6 +3684,11 @@ struct ieee80211_prep_tx_info { + u8 success:1; + }; + ++struct ieee80211_ppe_vp_ds_params { ++ struct net_device *dev; ++ int ppe_vp_profile_idx; ++ unsigned long ppe_vp_type; ++}; + /** + * struct ieee80211_ops - callbacks from mac80211 to the driver + * +@@ -4656,6 +4662,14 @@ struct ieee80211_ops { + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + u16 old_links, u16 new_links); ++ /*TODO: explore if this can be moved completely under ath12k driver */ ++ int (*ppeds_attach_vdev)(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ void *vp_arg, int *ppe_vp_num, ++ struct ieee80211_ppe_vp_ds_params *vp_params); ++ int (*ppeds_detach_vdev)(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_ppe_vp_ds_params *vp_params); + }; + + /** +diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h +index 6586a91dc0ee..eeddafd7f0e1 100644 +--- a/net/mac80211/driver-ops.h ++++ b/net/mac80211/driver-ops.h +@@ -1491,6 +1491,34 @@ static inline void drv_twt_teardown_request(struct ieee80211_local *local, + trace_drv_return_void(local); + } + ++static inline int drv_ppeds_attach_vdev(struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_vif *vif, void *vp_arg, ++ int *ppe_vp_num, ++ struct ieee80211_ppe_vp_ds_params *vp_params) ++{ ++ ++ struct ieee80211_local *local = sdata->local; ++ ++ if (!local->ops->ppeds_attach_vdev) ++ return -EINVAL; ++ ++ return local->ops->ppeds_attach_vdev(&local->hw, vif, vp_arg, ++ ppe_vp_num, vp_params); ++} ++ ++static inline int drv_ppeds_detach_vdev(struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_vif *vif, ++ struct ieee80211_ppe_vp_ds_params *vp_params) ++{ ++ struct ieee80211_local *local = sdata->local; ++ ++ if (!local->ops->ppeds_detach_vdev) ++ return -EINVAL; ++ ++ return local->ops->ppeds_detach_vdev(&local->hw, vif, vp_params); ++ ++} ++ + int drv_change_vif_links(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + u16 old_links, u16 new_links, +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index 5f6c7d83dc49..966283693a3f 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1109,9 +1109,6 @@ struct ieee80211_sub_if_data { + #ifdef CPTCFG_MAC80211_NSS_SUPPORT + struct nss_virt_if_handle *nssctx; + #endif +-#ifdef CPTCFG_MAC80211_PPE_SUPPORT +- u32 ppe_vp_num; +-#endif + + /* must be last, dynamically sized area in this! */ + struct ieee80211_vif vif; +diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c +index 1a342fb5a154..bf693a969e5a 100644 +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -715,6 +715,7 @@ static void ieee80211_stop_mbssid(struct ieee80211_sub_if_data *sdata) + static int ieee80211_stop(struct net_device *dev) + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ struct ieee80211_ppe_vp_ds_params vp_params = {0}; + + /* close dependent VLAN and MBSSID interfaces before locking wiphy */ + if (sdata->vif.type == NL80211_IFTYPE_AP) { +@@ -735,12 +736,14 @@ static int ieee80211_stop(struct net_device *dev) + #endif + + #ifdef CPTCFG_MAC80211_PPE_SUPPORT +- if (sdata->ppe_vp_num) { +- ppe_vp_free(sdata->ppe_vp_num); ++ if (sdata->vif.ppe_vp_num != -1) { ++ drv_ppeds_detach_vdev(sdata, &sdata->vif, &vp_params); ++ if (sdata->vif.ppe_vp_type != PPE_VP_USER_TYPE_DS) ++ ppe_vp_free(sdata->vif.ppe_vp_num); ++ + sdata_info(sdata, "Destroyed PPE VP port no:%d for dev:%s\n", +- sdata->ppe_vp_num, dev->name); +- sdata->ppe_vp_num = 0; +- sdata->vif.ppe_vp_num = 0; ++ sdata->vif.ppe_vp_num, dev->name); ++ sdata->vif.ppe_vp_num = -1; + } + #endif + +@@ -1260,8 +1263,9 @@ static bool ieee80211_process_dst_ppe_vp(struct net_device *dev, + static int ieee80211_ppe_vp_802_3_redir_vap(struct ieee80211_sub_if_data *sdata, + struct net_device *dev) + { +- int vp; + struct ppe_vp_ai vpai; ++ struct ieee80211_ppe_vp_ds_params vp_params = {0}; ++ int vp = -1, ret; + + memset(&vpai, 0, sizeof(struct ppe_vp_ai)); + +@@ -1271,7 +1275,19 @@ static int ieee80211_ppe_vp_802_3_redir_vap(struct ieee80211_sub_if_data *sdata, + vpai.src_cb = NULL; + vpai.src_cb_data = NULL; + vpai.queue_num = 0; ++ vpai.usr_type = PPE_VP_USER_TYPE_DS; ++ vpai.net_dev_type = PPE_VP_NET_DEV_TYPE_WIFI; ++ ++ vp_params.dev = dev; ++ ret = drv_ppeds_attach_vdev(sdata, &sdata->vif, (void *)&vpai, &vp, &vp_params); ++ if (!ret) { ++ sdata->vif.ppe_vp_type = PPE_VP_USER_TYPE_DS; ++ return vp; ++ } + ++ sdata_info(sdata, "PPE-DS attach failed falling back to passive vp\n"); ++ /* when PPE-DS attach fails, fall back to passive vp support */ ++ vpai.usr_type = 0; + vp = ppe_vp_alloc(dev, &vpai); + if (vp <= 0) + return -1; +@@ -1539,12 +1555,11 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) + if (ppe_vp_accel) { + vp = ieee80211_ppe_vp_802_3_redir_vap(sdata, dev); + if (vp > 0) { +- sdata->ppe_vp_num = vp; +- sdata->vif.ppe_vp_num = sdata->ppe_vp_num; ++ sdata->vif.ppe_vp_num = vp; + sdata_info(sdata, "Allocated vp:%d for device:%s\n", +- sdata->ppe_vp_num, dev->name); ++ sdata->vif.ppe_vp_num, dev->name); + } else { +- sdata->ppe_vp_num = 0; ++ sdata->vif.ppe_vp_num = -1; + sdata_err(sdata, "Failed to register with PPE VP\n"); + } + } +@@ -1851,6 +1866,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, + /* and set some type-dependent values */ + sdata->vif.type = type; + sdata->vif.p2p = false; ++ sdata->vif.ppe_vp_num = -1; + sdata->wdev.iftype = type; + + sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE); +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 227c323f663b..716b93139183 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2721,7 +2721,7 @@ static void ieee80211_netif_rx_ppe(struct ieee80211_rx_data *rx, + if (unlikely(skb_shared(skb))) + goto out; + +- if (likely(ppe_vp_tx_to_ppe(sdata->ppe_vp_num, skb))) ++ if (likely(ppe_vp_tx_to_ppe(sdata->vif.ppe_vp_num, skb))) + return; + + out: +@@ -4894,7 +4894,7 @@ static void ieee80211_rx_8023(struct ieee80211_rx_data *rx, + } + + #ifdef CPTCFG_MAC80211_PPE_SUPPORT +- if (rx->sdata->ppe_vp_num) { ++ if (rx->sdata->vif.ppe_vp_num) { + ieee80211_netif_rx_ppe(rx, skb); + atomic_inc(&sta->rx_netif_pkts); + return; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/763-b-wifi-ath12k-add-framework-to-support-PPE-DS.patch b/feeds/ipq95xx/mac80211/patches/qca/763-b-wifi-ath12k-add-framework-to-support-PPE-DS.patch new file mode 100644 index 000000000..740cee954 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/763-b-wifi-ath12k-add-framework-to-support-PPE-DS.patch @@ -0,0 +1,3624 @@ +From e6bab678d9958a961b8d46354dd51e58d1f1a926 Mon Sep 17 00:00:00 2001 +From: Ramanathan Choodamani +Date: Wed, 12 Apr 2023 16:09:58 -0700 +Subject: [PATCH] wifi: ath12k: add framework to support PPE DS + +Add framework to support PPE DS. By default ppe ds is disabled. +This can be enabled through writing 1 to module params +(/sys/module/ath12k/parameters/ppe_ds_enable) and wifi restart. +mac80211 tries to invoke driver ops for enabling direct +switching(DS). New rings are used for PPE DS TX and RX path. +Once setup, packet is directly handled by PPE engine skipping +network stack for both TX and RX. + +Add compilation flag for PPE_DS_SUPPORT enabling all the +DS specific APIs to be compiled whenever that flag is enabled. + +Bring DS related changes under PPE_DS_SUPPORT +compile flag check and fix compilation errors +in DS disabled case + +Also additional WMI config is added to route EAPOL packets to +WBM release ring. + +Signed-off-by: Balamurugan Mahalingam +Signed-off-by: Ramanathan Choodamani +Signed-off-by: Pradeep Kumar Chitrapu +Signed-off-by: Aloka Dixit +Signed-off-by: Sidhanta Sahu +--- + drivers/net/wireless/ath/ath12k/Kconfig | 8 + + drivers/net/wireless/ath/ath12k/Makefile | 1 + + drivers/net/wireless/ath/ath12k/core.c | 40 +- + drivers/net/wireless/ath/ath12k/core.h | 45 +- + drivers/net/wireless/ath/ath12k/debug.h | 5 +- + drivers/net/wireless/ath/ath12k/debugfs.c | 93 ++ + drivers/net/wireless/ath/ath12k/dp.c | 256 +++++- + drivers/net/wireless/ath/ath12k/dp.h | 125 ++- + drivers/net/wireless/ath/ath12k/dp_rx.c | 78 +- + drivers/net/wireless/ath/ath12k/dp_rx.h | 35 + + drivers/net/wireless/ath/ath12k/dp_tx.c | 189 ++++ + drivers/net/wireless/ath/ath12k/dp_tx.h | 6 +- + drivers/net/wireless/ath/ath12k/hal.c | 65 +- + drivers/net/wireless/ath/ath12k/hal.h | 29 +- + drivers/net/wireless/ath/ath12k/hal_desc.h | 62 +- + drivers/net/wireless/ath/ath12k/hal_rx.c | 15 + + drivers/net/wireless/ath/ath12k/hal_rx.h | 4 + + drivers/net/wireless/ath/ath12k/hal_tx.c | 10 + + drivers/net/wireless/ath/ath12k/hal_tx.h | 16 + + drivers/net/wireless/ath/ath12k/hif.h | 49 + + drivers/net/wireless/ath/ath12k/hw.c | 43 +- + drivers/net/wireless/ath/ath12k/hw.h | 30 +- + drivers/net/wireless/ath/ath12k/mac.c | 15 + + drivers/net/wireless/ath/ath12k/pci.c | 92 +- + drivers/net/wireless/ath/ath12k/pci.h | 13 + + drivers/net/wireless/ath/ath12k/ppe.c | 989 +++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/ppe.h | 43 + + drivers/net/wireless/ath/ath12k/wmi.c | 82 ++ + drivers/net/wireless/ath/ath12k/wmi.h | 68 ++ + local-symbols | 1 + + net/mac80211/iface.c | 4 + + 31 files changed, 2406 insertions(+), 105 deletions(-) + create mode 100644 drivers/net/wireless/ath/ath12k/ppe.c + create mode 100644 drivers/net/wireless/ath/ath12k/ppe.h + +--- a/drivers/net/wireless/ath/ath12k/Kconfig ++++ b/drivers/net/wireless/ath/ath12k/Kconfig +@@ -62,3 +62,11 @@ config ATH12K_PKTLOG + log uses ring buffer to dump the data. The buffer size, + frame filters can be altered by debugfs entries. + ++config ATH12K_PPE_DS_SUPPORT ++ bool "QTI ath12k ppe-ds support" ++ depends on ATH12K_DEBUGFS ++ depends on RELAY ++ help ++ Enable ath12k PPE-DS support ++ ++ Say Y to enable PPE DS Support. If unsure, say N. +--- a/drivers/net/wireless/ath/ath12k/Makefile ++++ b/drivers/net/wireless/ath/ath12k/Makefile +@@ -32,6 +32,7 @@ ath12k-$(CPTCFG_ATH12K_SPECTRAL) += spec + ath12k-$(CPTCFG_WANT_DEV_COREDUMP) += coredump.o + ath12k-$(CPTCFG_ATH12K_PKTLOG) += pktlog.o + ath12k-$(CPTCFG_ATH12K_AHB) += ahb.o ++ath12k-$(CPTCFG_ATH12K_PPE_DS_SUPPORT) += ppe.o + + # for tracing framework to find trace.h + CFLAGS_trace.o := -I$(src) +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -19,6 +19,7 @@ + #include "hif.h" + #include "wow.h" + #include "sawf.h" ++#include "ppe.h" + + unsigned int ath12k_debug_mask; + module_param_named(debug_mask, ath12k_debug_mask, uint, 0644); +@@ -46,6 +47,10 @@ static unsigned int ath12k_en_fwlog = tr + module_param_named(en_fwlog, ath12k_en_fwlog, uint, 0644); + MODULE_PARM_DESC(en_fwlog, "fwlog: 0-disable, 1-enable"); + ++unsigned int ath12k_ppe_ds_enabled = false; ++module_param_named(ppe_ds_enable, ath12k_ppe_ds_enabled, uint, 0644); ++MODULE_PARM_DESC(ppe_ds_enable, "ppe_ds_enable: 0-disable, 1-enable"); ++ + static unsigned int ath12k_recovery_mode = ATH12K_MLO_RECOVERY_MODE0; + + bool ath12k_mgmt_rx_reordering = false; +@@ -1078,8 +1083,19 @@ static int ath12k_core_pdev_init(struct + + ath12k_sawf_init(ab); + ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++ ret = ath12k_dp_ppeds_start(ab); ++ if (ret) { ++ ath12k_err(ab, "failed to start DP PPEDS \n"); ++ goto err_dp_ppeds_stop; ++ } ++#endif + return 0; + ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++err_dp_ppeds_stop: ++ ath12k_dp_ppeds_stop(ab); ++#endif + err_spectral_deinit: + ath12k_spectral_deinit(ab); + err_thermal_unregister: +@@ -1089,6 +1105,9 @@ err_thermal_unregister: + + static void ath12k_core_pdev_deinit(struct ath12k_base *ab) + { ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++ ath12k_dp_ppeds_stop(ab); ++#endif + ath12k_spectral_deinit(ab); + ath12k_thermal_unregister(ab); + ath12k_sawf_deinit(ab); +@@ -1368,7 +1387,11 @@ static int ath12k_core_hw_group_start(st + goto pdev_cleanup; + } + ath12k_hif_irq_enable(ab); +- ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++ ath12k_hif_ppeds_irq_enable(ab, PPEDS_IRQ_PPE2TCL); ++ ath12k_hif_ppeds_irq_enable(ab, PPEDS_IRQ_REO2PPE); ++ ath12k_hif_ppeds_irq_enable(ab, PPEDS_IRQ_PPE_WBM2SW_REL); ++#endif + ath12k_config_qdss(ab); + + if (ath12k_en_fwlog == true) { +@@ -1478,6 +1501,21 @@ int ath12k_core_qmi_firmware_ready(struc + goto err_firmware_stop; + } + ++ if (ath12k_ppe_ds_enabled) { ++ if (ath12k_frame_mode != ATH12K_HW_TXRX_ETHERNET) { ++ ath12k_warn(ab, ++ "Force enabling Ethernet frame mode in PPE DS for" \ ++ " AP and STA modes.\n"); ++ /* MESH and WDS VAPs will still use NATIVE_WIFI mode ++ * @ath12k_mac_update_vif_offload() ++ * TODO: add device capability check ++ */ ++ ath12k_frame_mode = ATH12K_HW_TXRX_ETHERNET; ++ } ++ if (ab->hif.bus == ATH12K_BUS_PCI) ++ set_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ab->dev_flags); ++ } ++ + ret = ath12k_dp_alloc(ab); + if (ret) { + ath12k_err(ab, "failed to init DP: %d\n", ret); +@@ -2301,6 +2339,9 @@ struct ath12k_base *ath12k_core_alloc(st + ab->hif.bus = bus; + ab->qmi.num_radios = ATH12K_QMI_INVALID_RADIO; + ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++ ab->ppeds_node_idx = -1; ++#endif + return ab; + + err_free_wq: +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -28,6 +28,10 @@ + #include "pktlog.h" + #include "sawf.h" + #include "vendor.h" ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++#include ++#include ++#endif + + #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK) + +@@ -235,6 +239,7 @@ enum ath12k_dev_flags { + ATH12K_FLAG_QMI_HOST_CAP_SENT, + ATH12K_FLAG_HW_GROUP_ATTACHED, + ATH12K_FLAG_FTM_SEGMENTED, ++ ATH12K_FLAG_PPE_DS_ENABLED, + }; + + enum ath12k_monitor_flags { +@@ -1115,6 +1120,30 @@ struct ath12k_soc_dp_stats { + struct ath12k_dp_ring_bp_stats bp_stats; + }; + ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++struct ath12k_ppeds_stats { ++ u32 tcl_prod_cnt; ++ u32 tcl_cons_cnt; ++ u32 reo_prod_cnt; ++ u32 reo_cons_cnt; ++ u32 get_tx_desc_cnt; ++ u32 tx_desc_allocated; ++ u32 tx_desc_freed; ++ u32 fw2wbm_pkt_drops; ++ u32 enable_intr_cnt; ++ u32 disable_intr_cnt; ++ u32 release_tx_single_cnt; ++ u32 release_rx_desc_cnt; ++ u32 num_rx_desc_freed; ++ u32 num_rx_desc_reused; ++}; ++ ++struct ath12k_ppeds_napi { ++ struct napi_struct napi; ++ struct net_device ndev; ++}; ++#endif ++ + struct ath12k_reg_freq { + u32 start_freq; + u32 end_freq; +@@ -1234,7 +1263,7 @@ struct ath12k_base { + bool wmi_ready; + u32 wlan_init_status; + int irq_num[ATH12K_IRQ_NUM_MAX]; +- struct ath12k_ext_irq_grp ext_irq_grp[ATH12K_EXT_IRQ_GRP_NUM_MAX]; ++ struct ath12k_ext_irq_grp ext_irq_grp[ATH12K_EXT_IRQ_DP_NUM_VECTORS]; + struct napi_struct *napi; + struct ath12k_targ_cap target_caps; + u32 ext_service_bitmap[WMI_SERVICE_EXT_BM_SIZE]; +@@ -1321,6 +1350,22 @@ struct ath12k_base { + u32 max_msduq_per_tid; + u32 default_msduq_per_tid; + ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++ ppe_ds_wlan_handle_t *ppeds_handle; ++ /* used for per node enumeration*/ ++ int ppeds_node_idx; ++ int ppe_vp_tbl_registered[PPE_VP_ENTRIES_MAX]; ++ int ppe_vp_search_idx_tbl_set[PPE_VP_ENTRIES_MAX]; ++ struct ath12k_ppeds_napi ppeds_napi_ctxt; ++ struct mutex ppe_vp_tbl_lock; ++ u8 num_ppe_vp_profiles; ++ u8 num_ppe_vp_search_idx_entries; ++ u8 num_ppe_vp_entries; ++ u8 ppeds_int_mode_enabled; ++ u8 ppeds_stopped; ++ struct ath12k_ppeds_stats ppeds_stats; ++#endif ++ + int userpd_id; + + /* must be last */ +--- a/drivers/net/wireless/ath/ath12k/debug.h ++++ b/drivers/net/wireless/ath/ath12k/debug.h +@@ -28,7 +28,10 @@ enum ath12k_debug_mask { + ATH12K_DBG_DP_RX = 0x00004000, + ATH12K_DBG_OFFSET = 0x00008000, + ATH12K_DBG_RX_REO = 0x00010000, +- ATH12K_DBG_SAWF = 0x80000000, ++ ++ /* keep last*/ ++ ATH12K_DBG_SAWF = 0x40000000, ++ ATH12K_DBG_PPE = 0x80000000, + ATH12K_DBG_ANY = 0xffffffff, + }; + +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -2069,6 +2069,94 @@ static const struct file_operations fops + .write = ath12k_write_rx_hash_ix3, + }; + ++ ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++static ssize_t ath12k_debugfs_dump_ppeds_stats(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k_base *ab = file->private_data; ++ struct ath12k_ppeds_stats *ppeds_stats = &ab->ppeds_stats; ++ int len = 0, retval; ++ const int size = 4096; ++ char *buf; ++ ++ buf = kzalloc(size, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ len += scnprintf(buf + len, size - len, "PPEDS STATS\n"); ++ len += scnprintf(buf + len, size - len, "-----------\n"); ++ len += scnprintf(buf + len, size - len, "tcl_prod_cnt %u\n", ++ ppeds_stats->tcl_prod_cnt); ++ len += scnprintf(buf + len, size - len, "tcl_cons_cnt %u\n", ++ ppeds_stats->tcl_cons_cnt); ++ len += scnprintf(buf + len, size - len, "reo_prod_cnt %u\n", ++ ppeds_stats->reo_prod_cnt); ++ len += scnprintf(buf + len, size - len, "reo_cons_cnt %u\n", ++ ppeds_stats->reo_cons_cnt); ++ len += scnprintf(buf + len, size - len, "get_tx_desc_cnt %u\n", ++ ppeds_stats->get_tx_desc_cnt); ++ len += scnprintf(buf + len, size - len, "enable_intr_cnt %u\n", ++ ppeds_stats->enable_intr_cnt); ++ len += scnprintf(buf + len, size - len, "disable_intr_cnt %u\n", ++ ppeds_stats->disable_intr_cnt); ++ len += scnprintf(buf + len, size - len, "release_tx_single_cnt %u\n", ++ ppeds_stats->release_tx_single_cnt); ++ len += scnprintf(buf + len, size - len, "release_rx_desc_cnt %u\n", ++ ppeds_stats->release_rx_desc_cnt); ++ len += scnprintf(buf + len, size - len, "tx_desc_allocated %u\n", ++ ppeds_stats->tx_desc_allocated); ++ len += scnprintf(buf + len, size - len, "tx_desc_freed %u\n", ++ ppeds_stats->tx_desc_freed); ++ len += scnprintf(buf + len, size - len, "fw2wbm_pkt_drops %u\n", ++ ppeds_stats->fw2wbm_pkt_drops); ++ len += scnprintf(buf + len, size - len, "num_rx_desc_reused %u\n", ++ ppeds_stats->num_rx_desc_reused); ++ len += scnprintf(buf + len, size - len, "num_rx_desc_freed %u\n", ++ ppeds_stats->num_rx_desc_freed); ++ ++ if (len > size) ++ len = size; ++ ++ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ kfree(buf); ++ ++ return retval; ++} ++ ++static ssize_t ++ath12k_debugfs_write_ppeds_stats(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k_base *ab = file->private_data; ++ struct ath12k_ppeds_stats *ppeds_stats = &ab->ppeds_stats; ++ char buf[20] = {0}; ++ int ret; ++ ++ if (count > sizeof(buf)) ++ return -EFAULT; ++ ++ ret = copy_from_user(buf, user_buf, count); ++ if (ret) ++ return -EFAULT; ++ ++ if (strstr(buf, "reset")) ++ memset(ppeds_stats, 0, sizeof(struct ath12k_ppeds_stats)); ++ ++ return count; ++} ++ ++static const struct file_operations fops_ppeds_stats = { ++ .read = ath12k_debugfs_dump_ppeds_stats, ++ .write = ath12k_debugfs_write_ppeds_stats, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++#endif ++ + int ath12k_debugfs_pdev_create(struct ath12k_base *ab) + { + if (test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags)) +@@ -2101,6 +2189,11 @@ int ath12k_debugfs_pdev_create(struct at + debugfs_create_file("fw_reset_stats", 0400, ab->debugfs_soc, ab, + &fops_fw_reset_stats); + ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++ if (test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ab->dev_flags)) ++ debugfs_create_file("ppeds_stats", 0600, ab->debugfs_soc, ab, ++ &fops_ppeds_stats); ++#endif + return 0; + } + +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -13,6 +13,9 @@ + #include "dp_rx.h" + #include "peer.h" + #include "dp_mon.h" ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++#include "ppe.h" ++#endif + + #define ATH12K_DP_LMAC_PEER_ID_LEGACY 2 + #define ATH12K_DP_LMAC_PEER_ID_MLO 3 +@@ -84,6 +87,10 @@ int ath12k_dp_peer_default_route_setup(s + ath12k_dbg(ab, ATH12K_DBG_DP_RX, "peer %pM set def route id %d sta_link %d\n", + arsta->addr, lmac_peer_routing_id, + hweight16(sta->valid_links)); ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++ /* keep last - override any PPE DS specific routing config */ ++ ath12k_dp_peer_ppeds_route_setup(ar, arvif, arsta); ++#endif + + return 0; + } +@@ -129,9 +136,10 @@ int ath12k_dp_peer_setup(struct ath12k * + goto peer_tid_clean; + } + +- spin_unlock_bh(&ab->base_lock); + /* TODO: Setup other peer specific resource used in data path */ + ++ spin_unlock_bh(&ab->base_lock); ++ + return 0; + + peer_tid_clean: +@@ -164,7 +172,7 @@ static int ath12k_dp_srng_find_ring_in_m + int ext_group_num; + u8 mask = 1 << ring_num; + +- for (ext_group_num = 0; ext_group_num < ATH12K_EXT_IRQ_GRP_NUM_MAX; ++ for (ext_group_num = 0; ext_group_num < ATH12K_EXT_IRQ_DP_NUM_VECTORS; + ext_group_num++) { + if (mask & grp_mask[ext_group_num]) + return ext_group_num; +@@ -183,6 +191,11 @@ static int ath12k_dp_srng_calculate_msi_ + if (ring_num == HAL_WBM2SW_REL_ERR_RING_NUM) { + grp_mask = &ab->hw_params->ring_mask->rx_wbm_rel[0]; + ring_num = 0; ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++ } else if (ring_num == HAL_WBM2SW_PPEDS_TX_CMPLN_RING_NUM) { ++ grp_mask = &ab->hw_params->ring_mask->wbm2sw6_ppeds_tx_cmpln[0]; ++ ring_num = 0; ++#endif + } else { + grp_mask = &ab->hw_params->ring_mask->tx[0]; + } +@@ -206,6 +219,12 @@ static int ath12k_dp_srng_calculate_msi_ + case HAL_RXDMA_BUF: + grp_mask = &ab->hw_params->ring_mask->host2rxdma[0]; + break; ++ case HAL_PPE2TCL: ++ grp_mask = &ab->hw_params->ring_mask->ppe2tcl[0]; ++ break; ++ case HAL_REO2PPE: ++ grp_mask = &ab->hw_params->ring_mask->reo2ppe[0]; ++ break; + case HAL_RXDMA_MONITOR_BUF: + case HAL_TCL_DATA: + case HAL_TCL_CMD: +@@ -231,6 +250,7 @@ static void ath12k_dp_srng_msi_setup(str + int msi_group_number, msi_data_count; + u32 msi_data_start, msi_irq_start, addr_lo, addr_hi; + int ret; ++ int vector; + + ret = ath12k_hif_get_user_msi_vector(ab, "DP", + &msi_data_count, &msi_data_start, +@@ -262,6 +282,12 @@ static void ath12k_dp_srng_msi_setup(str + ring_params->msi_data = (msi_group_number % msi_data_count) + + msi_data_start; + ring_params->flags |= HAL_SRNG_FLAGS_MSI_INTR; ++ ++ vector = msi_irq_start + (msi_group_number % msi_data_count); ++ ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++ ath12k_hif_ppeds_register_interrupts(ab, type, vector, ring_num); ++#endif + } + + int ath12k_dp_srng_setup(struct ath12k_base *ab, struct dp_srng *ring, +@@ -316,6 +342,7 @@ int ath12k_dp_srng_setup(struct ath12k_b + + switch (type) { + case HAL_REO_DST: ++ case HAL_REO2PPE: + params.intr_batch_cntr_thres_entries = + HAL_SRNG_INT_BATCH_THRESHOLD_RX; + params.intr_timer_thres_us = HAL_SRNG_INT_TIMER_THRESHOLD_RX; +@@ -345,6 +372,12 @@ int ath12k_dp_srng_setup(struct ath12k_b + params.intr_timer_thres_us = + HAL_SRNG_INT_TIMER_THRESHOLD_TX; + break; ++ } else if (ring_num == HAL_WBM2SW_PPEDS_TX_CMPLN_RING_NUM) { ++ params.intr_batch_cntr_thres_entries = ++ HAL_SRNG_INT_BATCH_THRESHOLD_PPE_WBM2SW_REL; ++ params.intr_timer_thres_us = HAL_SRNG_INT_TIMER_THRESHOLD_TX; ++ ++ break; + } + /* follow through when ring_num != HAL_WBM2SW_REL_ERR_RING_NUM */ + fallthrough; +@@ -365,6 +398,11 @@ int ath12k_dp_srng_setup(struct ath12k_b + break; + case HAL_RXDMA_DIR_BUF: + break; ++ case HAL_PPE2TCL: ++ params.intr_batch_cntr_thres_entries = ++ HAL_SRNG_INT_BATCH_THRESHOLD_PPE2TCL; ++ params.intr_timer_thres_us = HAL_SRNG_INT_TIMER_THRESHOLD_PPE2TCL; ++ break; + default: + ath12k_warn(ab, "Not a valid ring type in dp :%d\n", type); + return -EINVAL; +@@ -548,6 +586,10 @@ static void ath12k_dp_srng_common_cleanu + ath12k_dp_srng_cleanup(ab, &dp->reo_except_ring); + ath12k_dp_srng_cleanup(ab, &dp->reo_cmd_ring); + ath12k_dp_srng_cleanup(ab, &dp->reo_status_ring); ++ ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++ ath12k_dp_srng_ppeds_cleanup(ab); ++#endif + } + + static int ath12k_dp_srng_common_setup(struct ath12k_base *ab) +@@ -665,6 +707,14 @@ static int ath12k_dp_srng_common_setup(s + + ath12k_hal_reo_hw_setup(ab, ring_hash_map); + ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++ ret = ath12k_dp_srng_ppeds_setup(ab); ++ if (ret) { ++ ath12k_warn(ab, "failed to set up ppe-ds srngs :%d\n", ret); ++ goto err; ++ } ++#endif ++ + return 0; + + err: +@@ -1124,12 +1174,41 @@ void ath12k_dp_pdev_pre_alloc(struct ath + } + } + ++static int ath12k_dp_ppe_rxole_rxdma_cfg(struct ath12k_base *ab) ++{ ++ struct ath12k_dp_htt_rxdma_ppe_cfg_param param = {0}; ++ int ret; ++ ++ param.override = 1; ++ param.reo_dst_ind = HAL_REO2PPE_DST_IND; ++ param.multi_buffer_msdu_override_en = 0; ++ ++ /* Override use_ppe to 0 in RxOLE for the following cases */ ++ param.intra_bss_override = 1; ++ param.decap_raw_override = 1; ++ param.decap_nwifi_override = 1; ++ param.ip_frag_override = 1; ++ ++ ret = ath12k_dp_rx_htt_rxdma_rxole_ppe_cfg_set(ab, ¶m); ++ if (ret) ++ ath12k_err(ab, "RxOLE and RxDMA PPE config failed %d\n", ret); ++ ++ return ret; ++} ++ + int ath12k_dp_pdev_alloc(struct ath12k_base *ab) + { + struct ath12k *ar; + int ret; + int i; + ++ ret = ath12k_dp_ppe_rxole_rxdma_cfg(ab); ++ if (ret) { ++ ath12k_err(ab, "Failed to send htt RxOLE and RxDMA messages to target :%d\n", ++ ret); ++ goto out; ++ } ++ + ret = ath12k_dp_rx_htt_setup(ab); + if (ret) + goto out; +@@ -1269,6 +1348,18 @@ static void ath12k_dp_cc_cleanup(struct + dev_kfree_skb_any(skb); + } + ++ list_for_each_entry_safe(desc_info, tmp, &dp->rx_ppeds_reuse_list, list) { ++ list_del(&desc_info->list); ++ skb = desc_info->skb; ++ ++ if (!skb) ++ continue; ++ ++ dma_unmap_single(ab->dev, ATH12K_SKB_RXCB(skb)->paddr, ++ skb->len + skb_tailroom(skb), DMA_FROM_DEVICE); ++ dev_kfree_skb_any(skb); ++ } ++ + for (i = 0; i < ATH12K_NUM_RX_SPT_PAGES; i++) { + if (!dp->spt_info->rxbaddr[i]) + continue; +@@ -1319,6 +1410,11 @@ static void ath12k_dp_cc_cleanup(struct + spin_unlock_bh(&dp->tx_desc_lock[pool_id]); + } + ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++ if (test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ab->dev_flags)) ++ ath12k_ppeds_detach(ab); ++#endif ++ + /* unmap SPT pages */ + for (i = 0; i < dp->num_spt_pages; i++) { + if (!dp->spt_info[i].vaddr) +@@ -1470,6 +1566,17 @@ struct ath12k_tx_desc_info *ath12k_dp_ge + return *(struct ath12k_tx_desc_info **)desc_addr_ptr; + } + ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++struct ath12k_ppeds_tx_desc_info *ath12k_dp_get_ppeds_tx_desc(struct ath12k_base *ab, ++ u32 desc_id) ++{ ++ u8 *desc_addr_ptr; ++ ++ desc_addr_ptr = ath12k_dp_cc_find_desc(ab, desc_id, false); ++ return *(struct ath12k_ppeds_tx_desc_info **)desc_addr_ptr; ++} ++#endif ++ + static void ath12k_dp_tx_cmem_init(struct ath12k_base *ab, struct ath12k_dp *dp) + { + u32 cmem_base; +@@ -1477,7 +1584,8 @@ static void ath12k_dp_tx_cmem_init(struc + + cmem_base = ab->qmi.dev_mem[ATH12K_QMI_DEVMEM_CMEM_INDEX].start; + +- for (i = 0; i < ATH12K_NUM_TX_SPT_PAGES; i++) { ++ for (i = ATH12K_TX_SPT_PAGE_OFFSET; ++ i < (ATH12K_TX_SPT_PAGE_OFFSET + ATH12K_NUM_TX_SPT_PAGES); i++) { + /* Write to PPT in CMEM */ + if (ab->hif.ops->cmem_write32) + ath12k_hif_cmem_write32(ab, cmem_base + ATH12K_PPT_ADDR_OFFSET(i), +@@ -1508,6 +1616,139 @@ static void ath12k_dp_rx_cmem_init(struc + } + } + ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++void ath12k_dp_ppeds_tx_cmem_init(struct ath12k_base *ab, struct ath12k_dp *dp) ++{ ++ u32 cmem_base; ++ int i; ++ ++ cmem_base = ab->qmi.dev_mem[ATH12K_QMI_DEVMEM_CMEM_INDEX].start; ++ ++ for (i = ATH12K_PPEDS_TX_SPT_PAGE_OFFSET; ++ i < (ATH12K_PPEDS_TX_SPT_PAGE_OFFSET + ATH12K_NUM_PPEDS_TX_SPT_PAGES); i++) { ++ /* Write to PPT in CMEM */ ++ if (ab->hif.ops->cmem_write32) ++ ath12k_hif_cmem_write32(ab, cmem_base + ATH12K_PPT_ADDR_OFFSET(i), ++ dp->spt_info[i].paddr >> ATH12K_SPT_4K_ALIGN_OFFSET); ++ else ++ ath12k_hif_write32(ab, cmem_base + ATH12K_PPT_ADDR_OFFSET(i), ++ dp->spt_info[i].paddr >> ATH12K_SPT_4K_ALIGN_OFFSET); ++ } ++} ++ ++int ath12k_dp_cc_ppeds_desc_cleanup(struct ath12k_base *ab) ++{ ++ struct ath12k_ppeds_tx_desc_info *ppeds_tx_desc_info, *tmp2; ++ struct ath12k_dp *dp = &ab->dp; ++ struct sk_buff *skb; ++ int i; ++ u32 pool_id, ppeds_tx_spt_page; ++ ++ if (!dp->spt_info) { ++ ath12k_err(ab,"ath12k_dp_cc_ppeds_desc_cleanup failed"); ++ return -EINVAL; ++ } ++ ++ /* PPEDS TX Descriptor cleanup */ ++ for (i = 0; i < ATH12K_HW_MAX_QUEUES_PPEDS; i++) { ++ spin_lock_bh(&dp->ppeds_tx_desc_lock[i]); ++ ++ /* clean up used desc list */ ++ list_for_each_entry_safe(ppeds_tx_desc_info, tmp2, ++ &dp->ppeds_tx_desc_used_list[i], ++ list) { ++ list_del(&ppeds_tx_desc_info->list); ++ skb = ppeds_tx_desc_info->skb; ++ if (!skb) ++ continue; ++ ++ dma_unmap_single(ab->dev, ATH12K_SKB_CB(skb)->paddr, ++ skb->len, DMA_TO_DEVICE); ++ dev_kfree_skb_any(skb); ++ } ++ ++ /* clean up descriptors and skbs from reuse list */ ++ list_for_each_entry_safe(ppeds_tx_desc_info, tmp2, ++ &dp->ppeds_tx_desc_reuse_list[i], ++ list) { ++ list_del(&ppeds_tx_desc_info->list); ++ skb = ppeds_tx_desc_info->skb; ++ if (!skb) ++ continue; ++ ++ dma_unmap_single(ab->dev, ppeds_tx_desc_info->paddr, ++ skb->len, DMA_TO_DEVICE); ++ dev_kfree_skb_any(skb); ++ } ++ ++ spin_unlock_bh(&dp->ppeds_tx_desc_lock[i]); ++ } ++ ++ for (pool_id = 0; pool_id < ATH12K_HW_MAX_QUEUES_PPEDS; pool_id++) { ++ spin_lock_bh(&dp->ppeds_tx_desc_lock[pool_id]); ++ ++ for (i = 0; i < ATH12K_PPEDS_TX_SPT_PAGES_PER_POOL; i++) { ++ ppeds_tx_spt_page = i + pool_id * ATH12K_PPEDS_TX_SPT_PAGES_PER_POOL; ++ if (!dp->spt_info->ppedstxbaddr[ppeds_tx_spt_page]) ++ continue; ++ ++ kfree(dp->spt_info->ppedstxbaddr[ppeds_tx_spt_page]); ++ } ++ ++ spin_unlock_bh(&dp->ppeds_tx_desc_lock[pool_id]); ++ } ++ ath12k_dbg(ab, ATH12K_DBG_PPE, "ath12k_dp_cc_ppeds_desc_cleanup success\n"); ++ ++ return 0; ++} ++ ++int ath12k_dp_cc_ppeds_desc_init(struct ath12k_base *ab) ++{ ++ struct ath12k_dp *dp = &ab->dp; ++ struct ath12k_ppeds_tx_desc_info *ppeds_tx_descs; ++ struct ath12k_spt_info *ppeds_tx_spt_pages; ++ u32 i, j, pool_id, ppeds_tx_spt_page; ++ u32 ppt_idx; ++ ++ /* pointer to start of TX pages */ ++ ppeds_tx_spt_pages = &dp->spt_info[ATH12K_PPEDS_TX_SPT_PAGE_OFFSET]; ++ ++ for (pool_id = 0; pool_id < ATH12K_HW_MAX_QUEUES_PPEDS; pool_id++) { ++ spin_lock_bh(&dp->ppeds_tx_desc_lock[pool_id]); ++ for (i = 0; i < ATH12K_PPEDS_TX_SPT_PAGES_PER_POOL; i++) { ++ ppeds_tx_descs = kcalloc(ATH12K_MAX_SPT_ENTRIES, sizeof(*ppeds_tx_descs), ++ GFP_ATOMIC); ++ ++ if (!ppeds_tx_descs) { ++ spin_unlock_bh(&dp->ppeds_tx_desc_lock[pool_id]); ++ ath12k_dp_cc_ppeds_desc_cleanup(ab); ++ return -ENOMEM; ++ } ++ ++ ppeds_tx_spt_page = i + pool_id * ATH12K_PPEDS_TX_SPT_PAGES_PER_POOL; ++ dp->spt_info->ppedstxbaddr[ppeds_tx_spt_page] = &ppeds_tx_descs[0]; ++ ++ for (j = 0; j < ATH12K_MAX_SPT_ENTRIES; j++) { ++ ppt_idx = ATH12K_PPEDS_TX_SPT_PAGE_OFFSET + ppeds_tx_spt_page; ++ ppeds_tx_descs[j].desc_id = ath12k_dp_cc_cookie_gen(ppt_idx, j); ++ ppeds_tx_descs[j].pool_id = pool_id; ++ list_add_tail(&ppeds_tx_descs[j].list, ++ &dp->ppeds_tx_desc_free_list[pool_id]); ++ ++ /* Update descriptor VA in SPT */ ++ *(struct ath12k_ppeds_tx_desc_info **) ++ ((u8 *)ppeds_tx_spt_pages[ppeds_tx_spt_page].vaddr + ++ (j * sizeof(u64))) = &ppeds_tx_descs[j]; ++ } ++ } ++ spin_unlock_bh(&dp->ppeds_tx_desc_lock[pool_id]); ++ } ++ ath12k_dbg(ab, ATH12K_DBG_PPE, "ath12k_dp_cc_ppeds_desc_init success\n"); ++ ++ return 0; ++} ++#endif ++ + static int ath12k_dp_cc_desc_init(struct ath12k_base *ab) + { + struct ath12k_dp *dp = &ab->dp; +@@ -1572,6 +1813,7 @@ static int ath12k_dp_cc_desc_init(struct + for (j = 0; j < ATH12K_MAX_SPT_ENTRIES; j++) { + rx_descs[j].cookie = ath12k_dp_cc_cookie_gen(ppt_idx, j); + rx_descs[j].magic = ATH12K_DP_RX_DESC_MAGIC; ++ rx_descs[j].ab = ab; + list_add_tail(&rx_descs[j].list, &dp->rx_desc_free_list); + + /* Update descriptor VA in SPT */ +@@ -1610,6 +1852,7 @@ static int ath12k_dp_cc_init(struct ath1 + + INIT_LIST_HEAD(&dp->rx_desc_free_list); + INIT_LIST_HEAD(&dp->rx_desc_used_list); ++ INIT_LIST_HEAD(&dp->rx_ppeds_reuse_list); + spin_lock_init(&dp->rx_desc_lock); + + for (i = 0; i < ATH12K_HW_MAX_QUEUES; i++) { +@@ -1661,6 +1904,19 @@ static int ath12k_dp_cc_init(struct ath1 + goto free; + } + ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++ if (test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ab->dev_flags)) { ++ for (i = 0; i < ATH12K_HW_MAX_QUEUES_PPEDS; i++) { ++ INIT_LIST_HEAD(&dp->ppeds_tx_desc_free_list[i]); ++ INIT_LIST_HEAD(&dp->ppeds_tx_desc_reuse_list[i]); ++ INIT_LIST_HEAD(&dp->ppeds_tx_desc_used_list[i]); ++ spin_lock_init(&dp->ppeds_tx_desc_lock[i]); ++ dp->ppeds_tx_desc_reuse_list_len[i] = 0; ++ } ++ ath12k_ppeds_attach(ab); ++ } ++#endif ++ + return 0; + free: + ath12k_dp_cc_cleanup(ab); +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -41,6 +41,15 @@ struct dp_rxdma_ring { + int bufs_max; + }; + ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++struct dp_ppeds_tx_comp_ring { ++ struct dp_srng ppe_wbm2sw_ring; ++ struct hal_wbm_completion_ring_tx *tx_status; ++ int tx_status_head; ++ int tx_status_tail; ++}; ++#endif ++ + struct dp_tx_ring { + u8 tcl_data_ring_id; + struct dp_srng tcl_data_ring; +@@ -180,6 +189,11 @@ struct ath12k_pdev_dp { + #define DP_RX_BUFFER_SIZE_LITE 1024 + #define DP_RX_BUFFER_ALIGN_SIZE 128 + ++#define DP_REO2PPE_RING_SIZE 8192 ++#define DP_PPE2TCL_RING_SIZE 2048 ++#define DP_PPE_WBM2SW_RING_SIZE 8192 ++#define HAL_REO2PPE_DST_IND 6 ++ + #define DP_DIR_BUF_COOKIE_BUF_ID GENMASK(17, 0) + #define DP_DIR_BUF_COOKIE_PDEV_ID GENMASK(19, 18) + +@@ -197,6 +211,12 @@ struct ath12k_pdev_dp { + + #define ATH12K_NUM_POOL_TX_DESC 32768 + ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++#define ATH12K_NUM_POOL_PPEDS_TX_DESC 0x10000 ++#else ++#define ATH12K_NUM_POOL_PPEDS_TX_DESC 0 ++#endif ++ + /* TODO revisit this count during testing */ + #define ATH12K_RX_DESC_COUNT (12288) + +@@ -215,9 +235,19 @@ struct ath12k_pdev_dp { + #define ATH12K_TX_SPT_PAGES_PER_POOL (ATH12K_NUM_POOL_TX_DESC / \ + ATH12K_MAX_SPT_ENTRIES) + #define ATH12K_NUM_TX_SPT_PAGES (ATH12K_TX_SPT_PAGES_PER_POOL * ATH12K_HW_MAX_QUEUES) +-#define ATH12K_TX_SPT_PAGE_OFFSET 0 +-#define ATH12K_RX_SPT_PAGE_OFFSET ATH12K_NUM_TX_SPT_PAGES +-#define ATH12K_NUM_SPT_PAGES (ATH12K_NUM_TX_SPT_PAGES + ATH12K_NUM_RX_SPT_PAGES) ++ ++#define ATH12K_PPEDS_TX_SPT_PAGE_OFFSET 0 ++#define ATH12K_TX_SPT_PAGE_OFFSET ATH12K_NUM_PPEDS_TX_SPT_PAGES ++#define ATH12K_RX_SPT_PAGE_OFFSET ATH12K_NUM_PPEDS_TX_SPT_PAGES + ATH12K_NUM_TX_SPT_PAGES ++ ++ ++#define ATH12K_PPEDS_TX_SPT_PAGES_PER_POOL (ATH12K_NUM_POOL_PPEDS_TX_DESC / \ ++ ATH12K_MAX_SPT_ENTRIES) ++#define ATH12K_NUM_PPEDS_TX_SPT_PAGES (ATH12K_PPEDS_TX_SPT_PAGES_PER_POOL *\ ++ ATH12K_HW_MAX_QUEUES_PPEDS) ++ ++#define ATH12K_NUM_SPT_PAGES (ATH12K_NUM_TX_SPT_PAGES + ATH12K_NUM_RX_SPT_PAGES + \ ++ ATH12K_NUM_PPEDS_TX_SPT_PAGES) + + /* The SPT pages are divided for RX and TX, first block for RX + * and remaining for TX +@@ -282,6 +312,7 @@ struct ath12k_rx_desc_info { + struct sk_buff *skb; + u32 cookie; + u32 magic; ++ struct ath12k_base *ab; + }; + + struct ath12k_tx_desc_info { +@@ -294,11 +325,24 @@ struct ath12k_tx_desc_info { + u8 recycler_fast_xmit; + }; + ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++struct ath12k_ppeds_tx_desc_info { ++ struct list_head list; ++ struct sk_buff *skb; ++ dma_addr_t paddr; ++ u32 desc_id; /* Cookie */ ++ u8 mac_id; ++ u8 pool_id; ++ u8 flags; ++}; ++#endif ++ + struct ath12k_spt_info { + dma_addr_t paddr; + u32 *vaddr; + struct ath12k_rx_desc_info *rxbaddr[ATH12K_NUM_RX_SPT_PAGES]; + struct ath12k_tx_desc_info *txbaddr[ATH12K_NUM_TX_SPT_PAGES]; ++ struct ath12k_ppeds_tx_desc_info *ppedstxbaddr[ATH12K_NUM_PPEDS_TX_SPT_PAGES]; + }; + + struct ath12k_reo_queue_ref { +@@ -321,6 +365,21 @@ struct host_link_stats { + u32 tx_desc_type[HAL_TCL_DESC_TYPE_MAX]; + }; + ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++#define PPE_VP_ENTRIES_MAX 32 ++#define MAX_PPEDS_IRQ_NAME_LEN 20 ++#define MAX_PPEDS_IRQS 3 ++struct dp_ppe_vp_profile { ++ bool is_configured; ++ u8 vp_num; ++ u8 ppe_vp_num_idx; ++ u8 search_idx_reg_num; ++ u8 drop_prec_enable; ++ u8 to_fw; ++ u8 use_ppe_int_pri; ++}; ++#endif ++ + struct ath12k_dp { + struct ath12k_base *ab; + u8 num_bank_profiles; +@@ -341,6 +400,11 @@ struct ath12k_dp { + struct dp_srng rx_rel_ring; + struct dp_srng reo_except_ring; + struct dp_srng reo_cmd_ring; ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++ struct dp_srng reo2ppe_ring; ++ struct dp_srng ppe2tcl_ring; ++ struct dp_ppeds_tx_comp_ring ppeds_comp_ring; ++#endif + struct dp_srng reo_status_ring; + struct dp_srng reo_dst_ring[DP_REO_DST_RING_MAX]; + struct dp_tx_ring tx_ring[DP_TCL_NUM_RING_MAX]; +@@ -368,6 +432,7 @@ struct ath12k_dp { + u32 rx_spt_base; + struct list_head rx_desc_free_list; + struct list_head rx_desc_used_list; ++ struct list_head rx_ppeds_reuse_list; + /* protects the free and used desc list */ + spinlock_t rx_desc_lock; + +@@ -376,6 +441,19 @@ struct ath12k_dp { + /* protects the free and used desc lists */ + spinlock_t tx_desc_lock[ATH12K_HW_MAX_QUEUES]; + ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++ struct list_head ppeds_tx_desc_free_list[ATH12K_HW_MAX_QUEUES_PPEDS]; ++ struct list_head ppeds_tx_desc_reuse_list[ATH12K_HW_MAX_QUEUES_PPEDS]; ++ struct list_head ppeds_tx_desc_used_list[ATH12K_HW_MAX_QUEUES_PPEDS]; ++ int ppeds_tx_desc_reuse_list_len[ATH12K_HW_MAX_QUEUES_PPEDS]; ++ /* protects the free and used desc lists */ ++ spinlock_t ppeds_tx_desc_lock[ATH12K_HW_MAX_QUEUES_PPEDS]; ++ ++ struct dp_ppe_vp_profile ppe_vp_profile[PPE_VP_ENTRIES_MAX]; ++ char ppeds_irq_name[MAX_PPEDS_IRQS][MAX_PPEDS_IRQ_NAME_LEN]; ++ int ppeds_irq[MAX_PPEDS_IRQS]; ++#endif ++ + struct dp_rxdma_ring rx_refill_buf_ring; + struct dp_srng rx_mac_buf_ring[MAX_RXDMA_PER_PDEV]; + struct dp_srng rxdma_err_dst_ring[MAX_RXDMA_PER_PDEV]; +@@ -449,6 +527,7 @@ enum htt_h2t_msg_type { + HTT_H2T_MSG_TYPE_RX_RING_SELECTION_CFG = 0xc, + HTT_H2T_MSG_TYPE_EXT_STATS_CFG = 0x10, + HTT_H2T_MSG_TYPE_PPDU_STATS_CFG = 0x11, ++ HTT_H2T_MSG_TYPE_RXDMA_RXOLE_PPE_CFG = 0x19, + HTT_H2T_MSG_TYPE_VDEV_TXRX_STATS_CFG = 0x1a, + HTT_H2T_MSG_TYPE_TX_MONITOR_CFG = 0x1b, + HTT_H2T_MSG_TYPE_SAWF_DEF_Q_MAP_REQ = 0x1c, +@@ -2099,6 +2178,19 @@ struct htt_h2t_msg_type_vdev_txrx_stats_ + u32 vdev_id_hi_bitmask; + }; + ++#define HTT_H2T_RXOLE_PPE_CFG_MSG_TYPE GENMASK(7, 0) ++#define HTT_H2T_RXOLE_PPE_CFG_OVERRIDE BIT(8) ++#define HTT_H2T_RXOLE_PPE_CFG_REO_DST_IND GENMASK(13, 9) ++#define HTT_H2T_RXOLE_PPE_CFG_MULTI_BUF_MSDU_OVRD_EN BIT(14) ++#define HTT_H2T_RXOLE_PPE_CFG_INTRA_BUS_OVRD BIT(15) ++#define HTT_H2T_RXOLE_PPE_CFG_DECAP_RAW_OVRD BIT(16) ++#define HTT_H2T_RXOLE_PPE_CFG_NWIFI_OVRD BIT(17) ++#define HTT_H2T_RXOLE_PPE_CFG_IP_FRAG_OVRD BIT(18) ++ ++struct htt_h2t_msg_type_rxdma_rxole_ppe_cfg { ++ u32 info0; ++}; ++ + /* @brief target -> host extended statistics upload + * + * @details +@@ -2239,6 +2331,26 @@ struct ath11k_htt_mlo_peer_unmap_msg { + u32 info0; + } __packed; + ++/** ++ * struct ath12k_dp_htt_rxdma_ppe_cfg_param - Rx DMA and RxOLE PPE config ++ * @override: RxDMA override to override the reo_destinatoin_indication ++ * @reo_dst_ind: REO destination indication value ++ * @multi_buffer_msdu_override_en: Override the indication for SG ++ * @intra_bss_override: Rx OLE IntraBSS override ++ * @decap_raw_override: Rx Decap Raw override ++ * @decap_nwifi_override: Rx Native override ++ * @ip_frag_override: IP fragments override ++ */ ++struct ath12k_dp_htt_rxdma_ppe_cfg_param { ++ u8 override; ++ u8 reo_dst_ind; ++ u8 multi_buffer_msdu_override_en; ++ u8 intra_bss_override; ++ u8 decap_raw_override; ++ u8 decap_nwifi_override; ++ u8 ip_frag_override; ++}; ++ + int ath12k_dp_service_srng(struct ath12k_base *ab, + struct ath12k_ext_irq_grp *irq_grp, + int budget); +@@ -2275,4 +2387,11 @@ struct ath12k_rx_desc_info *ath12k_dp_ge + struct ath12k_tx_desc_info *ath12k_dp_get_tx_desc(struct ath12k_base *ab, + u32 desc_id); + void ath12k_dp_tx_update_bank_profile(struct ath12k_link_vif *arvif); ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++struct ath12k_ppeds_tx_desc_info *ath12k_dp_get_ppeds_tx_desc(struct ath12k_base *ab, ++ u32 desc_id); ++int ath12k_dp_cc_ppeds_desc_init(struct ath12k_base *ab); ++int ath12k_dp_cc_ppeds_desc_cleanup(struct ath12k_base *ab); ++void ath12k_dp_ppeds_tx_cmem_init(struct ath12k_base *ab, struct ath12k_dp *dp); ++#endif + #endif +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -2795,7 +2795,7 @@ static void ath12k_dp_rx_h_mpdu(struct a + u32 err_bitmap; + u8 tid; + #ifdef CPTCFG_MAC80211_PPE_SUPPORT +- u32 vp; ++ int vp; + #endif + struct wireless_dev *wdev = NULL; + +@@ -2830,7 +2830,7 @@ static void ath12k_dp_rx_h_mpdu(struct a + ath12k_dp_rx_h_csum_offload(ar, msdu); + msdu->dev = wdev->netdev; + #ifdef CPTCFG_MAC80211_PPE_SUPPORT +- if (vp) { ++ if (vp > 0) { + if (likely(ppe_vp_tx_to_ppe(vp, msdu))) + return; + } +@@ -3360,6 +3360,31 @@ static void ath12k_dp_rx_process_receive + rcu_read_unlock(); + } + ++/* Sends WMI config to filter packets to route packets to WBM release ring */ ++int ath12k_dp_rx_pkt_type_filter(struct ath12k *ar, ++ enum ath12k_routing_pkt_type pkt_type, ++ u32 meta_data) ++{ ++ struct ath12k_wmi_pkt_route_param param; ++ int ret; ++ ++ /* Routing Eapol packets to CCE is only allowed now */ ++ if (pkt_type != ATH12K_PKT_TYPE_EAP) ++ return -EINVAL; ++ ++ param.opcode = ATH12K_WMI_PKTROUTE_ADD; ++ param.meta_data = meta_data; ++ param.dst_ring = ATH12K_ROUTE_WBM_RELEASE; ++ param.dst_ring_handler = ATH12K_WMI_PKTROUTE_USE_CCE; ++ param.route_type_bmap = 1 << pkt_type; ++ ++ ret = ath12k_wmi_send_pdev_pkt_route(ar, ¶m); ++ if (ret) ++ ath12k_warn(ar->ab, "failed to configure pkt route %d", ret); ++ ++ return ret; ++} ++ + int ath12k_dp_rx_process(struct ath12k_base *ab, int ring_id, + struct napi_struct *napi, int budget) + { +@@ -4954,6 +4979,55 @@ int ath12k_dp_rxdma_ring_sel_config_wcn7 + return ret; + } + ++int ++ath12k_dp_rx_htt_rxdma_rxole_ppe_cfg_set(struct ath12k_base *ab, ++ struct ath12k_dp_htt_rxdma_ppe_cfg_param *param) ++{ ++ struct htt_h2t_msg_type_rxdma_rxole_ppe_cfg *cmd; ++ struct ath12k_dp *dp = &ab->dp; ++ struct sk_buff *skb; ++ int len = sizeof(*cmd), ret, val; ++ ++ skb = ath12k_htc_alloc_skb(ab, len); ++ if (!skb) ++ return -ENOMEM; ++ ++ skb_put(skb, len); ++ ++ cmd = (struct htt_h2t_msg_type_rxdma_rxole_ppe_cfg *)skb->data; ++ memset(cmd, 0, sizeof(*cmd)); ++ ++ cmd->info0 = ++ u32_encode_bits(HTT_H2T_MSG_TYPE_RXDMA_RXOLE_PPE_CFG, ++ HTT_H2T_RXOLE_PPE_CFG_MSG_TYPE) | ++ u32_encode_bits(param->override, HTT_H2T_RXOLE_PPE_CFG_OVERRIDE) | ++ u32_encode_bits(param->reo_dst_ind, ++ HTT_H2T_RXOLE_PPE_CFG_REO_DST_IND) | ++ u32_encode_bits(param->multi_buffer_msdu_override_en, ++ HTT_H2T_RXOLE_PPE_CFG_MULTI_BUF_MSDU_OVRD_EN) | ++ u32_encode_bits(param->intra_bss_override, ++ HTT_H2T_RXOLE_PPE_CFG_INTRA_BUS_OVRD) | ++ u32_encode_bits(param->decap_raw_override, ++ HTT_H2T_RXOLE_PPE_CFG_DECAP_RAW_OVRD) | ++ u32_encode_bits(param->decap_nwifi_override, ++ HTT_H2T_RXOLE_PPE_CFG_NWIFI_OVRD) | ++ u32_encode_bits(param->ip_frag_override, ++ HTT_H2T_RXOLE_PPE_CFG_IP_FRAG_OVRD); ++ ++ val = cmd->info0; ++ ret = ath12k_htc_send(&ab->htc, dp->eid, skb); ++ if(ret) { ++ ath12k_warn(ab, "failed to send htt type H2T rx ole ppe config request: %d", ++ ret); ++ dev_kfree_skb_any(skb); ++ return ret; ++ } ++ ++ ath12k_dbg(ab, ATH12K_DBG_PPE, "RXOLE ppe config request sent val 0x%x\n", val); ++ ++ return 0; ++} ++ + int ath12k_dp_rx_htt_setup(struct ath12k_base *ab) + { + struct ath12k_dp *dp = &ab->dp; +--- a/drivers/net/wireless/ath/ath12k/dp_rx.h ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.h +@@ -12,6 +12,35 @@ + + #define DP_MAX_NWIFI_HDR_LEN 30 + ++ ++/* different supported pkt types for routing */ ++enum ath12k_routing_pkt_type { ++ ATH12K_PKT_TYPE_ARP_IPV4, ++ ATH12K_PKT_TYPE_NS_IPV6, ++ ATH12K_PKT_TYPE_IGMP_IPV4, ++ ATH12K_PKT_TYPE_MLD_IPV6, ++ ATH12K_PKT_TYPE_DHCP_IPV4, ++ ATH12K_PKT_TYPE_DHCP_IPV6, ++ ATH12K_PKT_TYPE_DNS_TCP_IPV4, ++ ATH12K_PKT_TYPE_DNS_TCP_IPV6, ++ ATH12K_PKT_TYPE_DNS_UDP_IPV4, ++ ATH12K_PKT_TYPE_DNS_UDP_IPV6, ++ ATH12K_PKT_TYPE_ICMP_IPV4, ++ ATH12K_PKT_TYPE_ICMP_IPV6, ++ ATH12K_PKT_TYPE_TCP_IPV4, ++ ATH12K_PKT_TYPE_TCP_IPV6, ++ ATH12K_PKT_TYPE_UDP_IPV4, ++ ATH12K_PKT_TYPE_UDP_IPV6, ++ ATH12K_PKT_TYPE_IPV4, ++ ATH12K_PKT_TYPE_IPV6, ++ ATH12K_PKT_TYPE_EAP, ++ ATH12K_PKT_TYPE_MAX ++}; ++ ++#define ATH12K_RX_PROTOCOL_TAG_START_OFFSET 128 ++#define ATH12K_ROUTE_WBM_RELEASE 3 ++#define ATH12K_ROUTE_EAP_METADATA (ATH12K_RX_PROTOCOL_TAG_START_OFFSET + ATH12K_PKT_TYPE_EAP) ++ + struct ath12k_dp_rx_tid { + u8 tid; + u32 *vaddr; +@@ -180,4 +209,10 @@ u8 ath12k_dp_rx_h_decap_type(struct ath1 + u32 ath12k_dp_rx_h_mpdu_err(struct ath12k_base *ab, + struct hal_rx_desc *desc); + void ath12k_dp_rx_h_ppdu(struct ath12k *ar, struct ath12k_dp_rx_info *rx_info); ++int ++ath12k_dp_rx_htt_rxdma_rxole_ppe_cfg_set(struct ath12k_base *ab, ++ struct ath12k_dp_htt_rxdma_ppe_cfg_param *param); ++int ath12k_dp_rx_pkt_type_filter(struct ath12k *ar, ++ enum ath12k_routing_pkt_type pkt_type, ++ u32 meta_data); + #endif /* ATH12K_DP_RX_H */ +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -10,6 +10,7 @@ + #include "debugfs_sta.h" + #include "hw.h" + #include "peer.h" ++#include "ppe.h" + #include + #include + +@@ -98,6 +99,73 @@ enum hal_encrypt_type ath12k_dp_tx_get_e + } + } + ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++#define ATH12K_PPEDS_HOTLIST_LEN_MAX 1024 ++struct sk_buff * ++ath12k_dp_ppeds_tx_release_desc_nolock(struct ath12k_dp *dp, ++ struct ath12k_ppeds_tx_desc_info *tx_desc, ++ u8 ring_id) ++{ ++ struct sk_buff *skb = NULL; ++ ++ lockdep_assert_held(&dp->ppeds_tx_desc_lock[ATH12K_PPEDS_DEFAULT_POOL_ID]); ++ if (dp->ppeds_tx_desc_reuse_list_len[ring_id] < ATH12K_PPEDS_HOTLIST_LEN_MAX && ++ tx_desc->skb) { ++ list_move_tail(&tx_desc->list, &dp->ppeds_tx_desc_reuse_list[ring_id]); ++ dp->ppeds_tx_desc_reuse_list_len[ring_id]++; ++ } else { ++ skb = tx_desc->skb; ++ tx_desc->skb = NULL; ++ list_move_tail(&tx_desc->list, &dp->ppeds_tx_desc_free_list[ring_id]); ++ } ++ ++ return skb; ++} ++ ++struct ath12k_ppeds_tx_desc_info * ++ath12k_dp_ppeds_tx_assign_desc_nolock(struct ath12k_dp *dp, ++ u8 ring_id) ++{ ++ struct ath12k_ppeds_tx_desc_info *desc, *next; ++ ++ lockdep_assert_held(&dp->ppeds_tx_desc_lock[ATH12K_PPEDS_DEFAULT_POOL_ID]); ++ /* first try to fetch descriptor from hotlist if not use free list */ ++ desc = list_first_entry_or_null(&dp->ppeds_tx_desc_reuse_list[ring_id], ++ struct ath12k_ppeds_tx_desc_info, ++ list); ++ if (desc) { ++ list_move_tail(&desc->list, &dp->ppeds_tx_desc_used_list[ring_id]); ++ dp->ppeds_tx_desc_reuse_list_len[ring_id]--; ++ /* Prefetch next hotlist descriptor */ ++ if (dp->ppeds_tx_desc_reuse_list_len[ring_id]) ++ next = list_first_entry_or_null(&dp->ppeds_tx_desc_reuse_list[ring_id], ++ struct ath12k_ppeds_tx_desc_info, ++ list); ++ else ++ next = list_first_entry_or_null(&dp->ppeds_tx_desc_free_list[ring_id], ++ struct ath12k_ppeds_tx_desc_info, ++ list); ++ prefetch(next); ++ ++ return desc; ++ } ++ ++ /* Fetch desc from Freelist if hotlist is empty */ ++ desc = list_first_entry_or_null(&dp->ppeds_tx_desc_free_list[ring_id], ++ struct ath12k_ppeds_tx_desc_info, ++ list); ++ if (unlikely(!desc)) { ++ ath12k_warn(dp->ab, "failed to allocate data Tx buffer\n"); ++ return NULL; ++ } ++ ++ list_move_tail(&desc->list, &dp->ppeds_tx_desc_used_list[ring_id]); ++ ++ return desc; ++} ++ ++#endif ++ + static void ath12k_dp_tx_release_txbuf(struct ath12k_dp *dp, + struct ath12k_tx_desc_info *tx_desc, + u8 ring_id) +@@ -1093,6 +1161,143 @@ static inline bool ath12k_dp_tx_completi + return true; + } + ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++static inline ++void ath12k_dp_ppeds_tx_comp_get_desc(struct ath12k_base *ab, ++ struct hal_wbm_completion_ring_tx *tx_status, ++ struct ath12k_ppeds_tx_desc_info **tx_desc) ++{ ++ u64 desc_va = 0; ++ u32 desc_id; ++ ++ if (likely(HAL_WBM_COMPL_TX_INFO0_CC_DONE & tx_status->info0)) { ++ /* HW done cookie conversion */ ++ desc_va = ((u64)tx_status->buf_va_hi << 32 | ++ tx_status->buf_va_lo); ++ *tx_desc = (struct ath12k_ppeds_tx_desc_info *)((unsigned long)desc_va); ++ } else { ++ /* SW does cookie conversion to VA */ ++ desc_id = u32_get_bits(tx_status->buf_va_hi, ++ BUFFER_ADDR_INFO1_SW_COOKIE); ++ ++ *tx_desc = ath12k_dp_get_ppeds_tx_desc(ab, desc_id); ++ } ++} ++ ++int ath12k_ppeds_tx_completion_handler(struct ath12k_base *ab, int budget) ++{ ++ struct ath12k_dp *dp = &ab->dp; ++ struct dp_ppeds_tx_comp_ring *tx_ring = &dp->ppeds_comp_ring.ppe_wbm2sw_ring; ++ int hal_ring_id = tx_ring->ppe_wbm2sw_ring.ring_id; ++ struct hal_srng *status_ring = &ab->hal.srng_list[hal_ring_id]; ++ struct ath12k_ppeds_tx_desc_info *tx_desc = NULL; ++ struct sk_buff *msdu; ++ u32 *desc; ++ u8 mac_id; ++ int valid_entries, count = 0, i = 0; ++ struct hal_wbm_completion_ring_tx *tx_status; ++ struct htt_tx_wbm_completion *status_desc; ++ enum hal_wbm_rel_src_module buf_rel_source; ++ struct sk_buff_head free_list_head; ++ int work_done = 0, htt_status; ++ size_t stat_size; ++ ++ if (likely(ab->stats_disable)) ++ /* only need buf_addr_info and info0 */ ++ stat_size = 3 * sizeof(u32); ++ else ++ stat_size = sizeof(struct hal_wbm_release_ring); ++ ++ spin_lock_bh(&status_ring->lock); ++ ++ ath12k_hal_srng_access_dst_ring_begin_nolock(ab, status_ring); ++ ++ valid_entries = ath12k_hal_srng_dst_num_free(ab, status_ring, false); ++ if (!valid_entries) { ++ ath12k_hal_srng_access_dst_ring_end_nolock(status_ring); ++ spin_unlock_bh(&status_ring->lock); ++ return work_done; ++ } ++ ++ if (valid_entries >= budget) ++ valid_entries = budget; ++ ++ ath12k_hal_srng_ppeds_dst_inv_entry(ab, status_ring, valid_entries); ++ skb_queue_head_init(&free_list_head); ++ ++ while (likely(valid_entries--)) { ++ desc = ath12k_hal_srng_dst_get_next_cache_entry(ab, status_ring); ++ if (!desc || !ath12k_dp_tx_completion_valid(desc)) ++ continue; ++ ++ memcpy(&tx_ring->tx_status[count], desc, stat_size); ++ count++; ++ ++ if (count == valid_entries) ++ break; ++ } ++ ++ ath12k_hal_srng_access_dst_ring_end_nolock(status_ring); ++ ++ spin_unlock_bh(&status_ring->lock); ++ ++ spin_lock_bh(&dp->ppeds_tx_desc_lock[ATH12K_PPEDS_DEFAULT_POOL_ID]); ++ while (count--) { ++ tx_status = &tx_ring->tx_status[i++]; ++ ++ ath12k_dp_ppeds_tx_comp_get_desc(ab, tx_status, &tx_desc); ++ if (unlikely(!tx_desc)) { ++ ath12k_warn(ab, "unable to retrieve ppe ds tx_desc!"); ++ continue; ++ } ++ ++ mac_id = tx_desc->mac_id; ++ ++ /* Release descriptor as soon as extracting necessary info ++ * to reduce contention ++ */ ++ msdu = ath12k_dp_ppeds_tx_release_desc_nolock(dp, tx_desc, ++ ATH12K_PPEDS_DEFAULT_POOL_ID); ++ buf_rel_source = FIELD_GET(HAL_WBM_RELEASE_INFO0_REL_SRC_MODULE, ++ tx_status->info0); ++ if (unlikely(buf_rel_source == HAL_WBM_REL_SRC_MODULE_FW)) { ++ status_desc = ((void *)tx_status) + HTT_TX_WBM_COMP_STATUS_OFFSET; ++ htt_status = u32_get_bits(status_desc->info0, ++ HTT_TX_WBM_COMP_INFO0_STATUS); ++ if (htt_status != HAL_WBM_REL_HTT_TX_COMP_STATUS_OK && ++ !ab->stats_disable) { ++ ab->ppeds_stats.fw2wbm_pkt_drops++; ++ } ++ dev_kfree_skb_any(msdu); ++ ath12k_warn(ab, "ath12k: Frame received from unexpected source %d status %d!\n", ++ buf_rel_source, htt_status); ++ continue; ++ } ++ ++ /* is skb is being reused, avoid freeing it */ ++ if (!msdu) ++ continue; ++ ++ if (skb_has_frag_list(msdu)) { ++ kfree_skb_list(skb_shinfo(msdu)->frag_list); ++ skb_shinfo(msdu)->frag_list = NULL; ++ } ++ ++ if (likely(msdu->is_from_recycler)) { ++ __skb_queue_head(&free_list_head, msdu); ++ } else { ++ dev_kfree_skb(msdu); ++ } ++ ++ work_done++; ++ } ++ spin_unlock_bh(&dp->ppeds_tx_desc_lock[ATH12K_PPEDS_DEFAULT_POOL_ID]); ++ dev_kfree_skb_list_fast(&free_list_head); ++ ++ return work_done; ++} ++#endif ++ + int ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id, + int budget) + { +@@ -1122,7 +1327,7 @@ int ath12k_dp_tx_completion_handler(stru + + valid_entries = ath12k_hal_srng_dst_num_free(ab, status_ring, false); + if (!valid_entries) { +- ath12k_hal_srng_access_umac_dst_ring_end_nolock(status_ring); ++ ath12k_hal_srng_access_dst_ring_end_nolock(status_ring); + return 0; + } + +@@ -1229,7 +1434,7 @@ int ath12k_dp_tx_completion_handler(stru + tx_ring->tcl_data_ring_id); + } + } +- ath12k_hal_srng_access_umac_dst_ring_end_nolock(status_ring); ++ ath12k_hal_srng_access_dst_ring_end_nolock(status_ring); + dev_kfree_skb_list_fast(&free_list_head); + + return (orig_budget - budget); +--- a/drivers/net/wireless/ath/ath12k/dp_tx.h ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.h +@@ -220,7 +220,12 @@ int ath12k_dp_tx(struct ath12k *ar, stru + bool gsn_valid, int mcbc_gsn); + int ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id, + int tx_comp_budget); +- ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++int ath12k_ppeds_tx_completion_handler(struct ath12k_base *ab, int ring_id); ++struct ath12k_ppeds_tx_desc_info * ++ath12k_dp_ppeds_tx_assign_desc_nolock(struct ath12k_dp *dp, ++ u8 ring_id); ++#endif + int ath12k_dp_tx_htt_h2t_ppdu_stats_req(struct ath12k *ar, u32 mask); + int + ath12k_dp_tx_htt_h2t_ext_stats_req(struct ath12k *ar, u8 type, +--- a/drivers/net/wireless/ath/ath12k/hal.c ++++ b/drivers/net/wireless/ath/ath12k/hal.c +@@ -4,6 +4,7 @@ + * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + #include ++#include + #include "hal_tx.h" + #include "hal_rx.h" + #include "debug.h" +@@ -57,6 +58,14 @@ static const struct hal_srng_config hw_s + .ring_dir = HAL_SRNG_DIR_DST, + .max_size = HAL_REO_STATUS_RING_BASE_MSB_RING_SIZE, + }, ++ [HAL_REO2PPE] = { ++ .start_ring_id = HAL_SRNG_RING_ID_REO2PPE, ++ .max_rings = 1, ++ .entry_size = sizeof(struct hal_reo_dest_ring) >> 2, ++ .mac_type = ATH12K_HAL_SRNG_UMAC, ++ .ring_dir = HAL_SRNG_DIR_DST, ++ .max_size = HAL_REO2PPE_RING_BASE_MSB_RING_SIZE, ++ }, + [HAL_TCL_DATA] = { + .start_ring_id = HAL_SRNG_RING_ID_SW2TCL1, + .max_rings = 6, +@@ -168,15 +177,15 @@ static const struct hal_srng_config hw_s + .start_ring_id = HAL_SRNG_RING_ID_PPE2TCL1, + .max_rings = 1, + .entry_size = sizeof(struct hal_tcl_entrance_from_ppe_ring) >> 2, +- .mac_type = ATH12K_HAL_SRNG_PMAC, ++ .mac_type = ATH12K_HAL_SRNG_UMAC, + .ring_dir = HAL_SRNG_DIR_SRC, +- .max_size = HAL_SW2TCL1_RING_BASE_MSB_RING_SIZE, ++ .max_size = HAL_PPE2TCL_RING_BASE_MSB_RING_SIZE, + }, + [HAL_PPE_RELEASE] = { + .start_ring_id = HAL_SRNG_RING_ID_WBM_PPE_RELEASE, + .max_rings = 1, + .entry_size = sizeof(struct hal_wbm_release_ring) >> 2, +- .mac_type = ATH12K_HAL_SRNG_PMAC, ++ .mac_type = ATH12K_HAL_SRNG_UMAC, + .ring_dir = HAL_SRNG_DIR_SRC, + .max_size = HAL_WBM2PPE_RELEASE_RING_BASE_MSB_RING_SIZE, + }, +@@ -531,6 +540,12 @@ static int ath12k_hal_srng_create_config + s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_STATUS_RING_BASE_LSB(ab); + s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_STATUS_HP; + ++ s = &hal->srng_config[HAL_REO2PPE]; ++ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO2PPE_RING_BASE_LSB(ab); ++ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO2PPE_HP; ++ s->reg_size[0] = HAL_REO2_RING_BASE_LSB(ab) - HAL_REO1_RING_BASE_LSB(ab); ++ s->reg_size[1] = HAL_REO2_RING_HP - HAL_REO1_RING_HP; ++ + s = &hal->srng_config[HAL_TCL_DATA]; + s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_BASE_LSB(ab); + s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_HP; +@@ -598,10 +613,6 @@ static int ath12k_hal_srng_create_config + s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_PPE2TCL1_RING_BASE_LSB; + s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_PPE2TCL1_RING_HP; + +- s = &hal->srng_config[HAL_PPE_RELEASE]; +- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_PPE_RELEASE_RING_BASE_LSB(ab); +- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_PPE_RELEASE_RING_HP; +- + return 0; + } + +@@ -1646,6 +1657,38 @@ u32 *ath12k_hal_srng_dst_get_next_cache_ + return desc; + } + ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++void ath12k_hal_srng_ppeds_dst_inv_entry(struct ath12k_base *ab, ++ struct hal_srng *srng, int entries) ++{ ++ u32 *desc, *last_desc; ++ u32 tp, hp; ++ u32 remaining_entries; ++ ++ if (!(srng->flags & HAL_SRNG_FLAGS_CACHED) || !entries) ++ return; ++ ++ tp = srng->u.dst_ring.tp; ++ hp = srng->u.dst_ring.cached_hp; ++ ++ desc = srng->ring_base_vaddr + tp; ++ if (hp > tp) { ++ last_desc = ((void *)desc + entries * srng->entry_size * sizeof(u32)); ++ dmac_inv_range_no_dsb((void *)desc, ++ (void *)last_desc); ++ } else { ++ remaining_entries = srng->ring_size - tp; ++ last_desc = ((void *)desc + remaining_entries * sizeof(u32)); ++ dmac_inv_range_no_dsb((void *)desc, (void *)last_desc); ++ ++ last_desc = ((void *)srng->ring_base_vaddr + hp * sizeof(u32)); ++ dmac_inv_range_no_dsb((void *)srng->ring_base_vaddr, (void *)last_desc); ++ } ++ ++ dsb(st); ++} ++#endif ++ + void ath12k_hal_srng_dst_invalidate_entry(struct ath12k_base *ab, + struct hal_srng *srng, int entries) + { +@@ -2197,6 +2240,15 @@ void ath12k_hal_srng_shadow_config(struc + } + } + ++void ath12k_hal_reo_config_reo2ppe_dest_info(struct ath12k_base *ab) ++{ ++ u32 reo_base = HAL_SEQ_WCSS_UMAC_REO_REG; ++ u32 val = HAL_REO1_REO2PPE_DST_VAL; ++ ++ ath12k_hif_write32(ab, reo_base + HAL_REO1_REO2PPE_DST_INFO, ++ val); ++} ++ + void ath12k_hal_srng_get_shadow_config(struct ath12k_base *ab, + u32 **cfg, u32 *len) + { +--- a/drivers/net/wireless/ath/ath12k/hal.h ++++ b/drivers/net/wireless/ath/ath12k/hal.h +@@ -139,11 +139,6 @@ struct ath12k_base; + #define HAL_TCL_PPE2TCL1_RING_BASE_LSB 0x00000c48 + #define HAL_TCL_PPE2TCL1_RING_HP 0x00002038 + +-/* WBM PPE Release Ring address */ +-#define HAL_WBM_PPE_RELEASE_RING_BASE_LSB(ab) \ +- ((ab)->hw_params->regs->hal_ppe_rel_ring_base) +-#define HAL_WBM_PPE_RELEASE_RING_HP 0x00003020 +- + /* REO2SW(x) R0 ring configuration address */ + #define HAL_REO1_GEN_ENABLE 0x00000000 + #define HAL_REO1_MISC_CTRL_ADDR(ab) \ +@@ -194,6 +189,9 @@ struct ath12k_base; + #define HAL_REO1_RING_MISC_OFFSET \ + (HAL_REO1_RING_MISC(ab) - HAL_REO1_RING_BASE_LSB(ab)) + ++#define HAL_REO1_REO2PPE_DST_VAL 0x2000 ++#define HAL_REO1_REO2PPE_DST_INFO 0x00000cf0 ++ + /* REO2SW(x) R2 ring pointers (head/tail) address */ + #define HAL_REO1_RING_HP 0x00003048 + #define HAL_REO1_RING_TP 0x0000304c +@@ -240,6 +238,12 @@ struct ath12k_base; + ((ab)->hw_params->regs->hal_reo_status_ring_base) + #define HAL_REO_STATUS_HP 0x000030a8 + ++ ++/* REO2PPE address */ ++#define HAL_REO2PPE_RING_BASE_LSB(ab) \ ++ ((ab)->hw_params->regs->hal_reo2ppe_ring_base) ++#define HAL_REO2PPE_HP 0x00003090 ++ + /* WBM Idle R0 address */ + #define HAL_WBM_IDLE_LINK_RING_BASE_LSB(ab) \ + ((ab)->hw_params->regs->hal_wbm_idle_ring_base_lsb) +@@ -307,6 +311,7 @@ struct ath12k_base; + #define HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW2_EN BIT(3) + #define HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW3_EN BIT(4) + #define HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW4_EN BIT(5) ++#define HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW6_EN BIT(7) + #define HAL_WBM_SW_COOKIE_CONV_CFG_GLOBAL_EN BIT(8) + + /* TCL ring feild mask and offset */ +@@ -388,6 +393,8 @@ struct ath12k_base; + #define HAL_REO_SW2REO_RING_BASE_MSB_RING_SIZE 0x0000ffff + #define HAL_REO_CMD_RING_BASE_MSB_RING_SIZE 0x0000ffff + #define HAL_REO_STATUS_RING_BASE_MSB_RING_SIZE 0x0000ffff ++#define HAL_REO2PPE_RING_BASE_MSB_RING_SIZE 0xffffffff ++#define HAL_PPE2TCL_RING_BASE_MSB_RING_SIZE 0x000fffff + #define HAL_SW2TCL1_RING_BASE_MSB_RING_SIZE 0x000fffff + #define HAL_SW2TCL1_CMD_RING_BASE_MSB_RING_SIZE 0x000fffff + #define HAL_TCL_STATUS_RING_BASE_MSB_RING_SIZE 0x0000ffff +@@ -399,9 +406,11 @@ struct ath12k_base; + #define HAL_WBM2SW_RELEASE_RING_BASE_MSB_RING_SIZE 0x000fffff + #define HAL_RXDMA_RING_MAX_SIZE 0x0000ffff + #define HAL_RXDMA_RING_MAX_SIZE_BE 0x000fffff +-#define HAL_WBM2PPE_RELEASE_RING_BASE_MSB_RING_SIZE 0x000fffff ++#define HAL_WBM2PPE_RELEASE_RING_BASE_MSB_RING_SIZE 0x0000ffff + + #define HAL_WBM2SW_REL_ERR_RING_NUM 3 ++#define HAL_WBM2SW_PPEDS_TX_CMPLN_MAP_ID 11 ++#define HAL_WBM2SW_PPEDS_TX_CMPLN_RING_NUM 6 + /* Add any other errors here and return them in + * ath12k_hal_rx_desc_get_err(). + */ +@@ -560,6 +569,7 @@ enum hal_ring_type { + HAL_REO_REINJECT, + HAL_REO_CMD, + HAL_REO_STATUS, ++ HAL_REO2PPE, + HAL_TCL_DATA, + HAL_TCL_CMD, + HAL_TCL_STATUS, +@@ -791,13 +801,16 @@ struct hal_srng { + }; + + /* Interrupt mitigation - Batch threshold in terms of numer of frames */ ++#define HAL_SRNG_INT_BATCH_THRESHOLD_PPE_WBM2SW_REL 256 + #define HAL_SRNG_INT_BATCH_THRESHOLD_TX 64 + #define HAL_SRNG_INT_BATCH_THRESHOLD_RX 128 ++#define HAL_SRNG_INT_BATCH_THRESHOLD_PPE2TCL 0 + #define HAL_SRNG_INT_BATCH_THRESHOLD_OTHER 1 + + /* Interrupt mitigation - timer threshold in us */ + #define HAL_SRNG_INT_TIMER_THRESHOLD_TX 200 + #define HAL_SRNG_INT_TIMER_THRESHOLD_RX 500 ++#define HAL_SRNG_INT_TIMER_THRESHOLD_PPE2TCL 30 + #define HAL_SRNG_INT_TIMER_THRESHOLD_OTHER 256 + + enum hal_srng_mac_type { +@@ -1197,6 +1210,10 @@ void ath12k_hal_srng_shadow_update_hp_tp + struct hal_srng *srng); + u32 *ath12k_hal_srng_dst_get_next_cache_entry(struct ath12k_base *ab, + struct hal_srng *srng); ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++void ath12k_hal_srng_ppeds_dst_inv_entry(struct ath12k_base *ab, ++ struct hal_srng *srng, int entries); ++#endif + void ath12k_hal_srng_dst_invalidate_entry(struct ath12k_base *ab, + struct hal_srng *srng, int entries); + void ath12k_hal_reo_ring_ctrl_hash_ix3_setup(struct ath12k_base *ab, +@@ -1206,6 +1223,7 @@ void ath12k_hal_reo_ring_ctrl_hash_ix2_s + void ath12k_hal_reo_shared_qaddr_cache_clear(struct ath12k_base *ab); + void ath12k_hal_srng_prefetch_desc(struct ath12k_base *ab, + struct hal_srng *srng); ++void ath12k_hal_reo_config_reo2ppe_dest_info(struct ath12k_base *ab); + + static inline + u32 *ath12k_hal_srng_src_get_next_entry_nolock(struct ath12k_base *ab, +@@ -1265,7 +1283,7 @@ void ath12k_hal_srng_access_umac_src_rin + } + + static inline +-void ath12k_hal_srng_access_umac_dst_ring_end_nolock(struct hal_srng *srng) ++void ath12k_hal_srng_access_dst_ring_end_nolock(struct hal_srng *srng) + { + srng->u.dst_ring.last_hp = *srng->u.dst_ring.hp_addr; + writel_relaxed(srng->u.dst_ring.tp, srng->u.dst_ring.tp_addr_direct); +--- a/drivers/net/wireless/ath/ath12k/hal_desc.h ++++ b/drivers/net/wireless/ath/ath12k/hal_desc.h +@@ -923,53 +923,6 @@ struct hal_reo_dest_ring { + * this ring has looped around the ring. + */ + +-#define HAL_REO_TO_PPE_RING_INFO0_DATA_LENGTH GENMASK(15, 0) +-#define HAL_REO_TO_PPE_RING_INFO0_DATA_OFFSET GENMASK(23, 16) +-#define HAL_REO_TO_PPE_RING_INFO0_POOL_ID GENMASK(28, 24) +-#define HAL_REO_TO_PPE_RING_INFO0_PREHEADER BIT(29) +-#define HAL_REO_TO_PPE_RING_INFO0_TSO_EN BIT(30) +-#define HAL_REO_TO_PPE_RING_INFO0_MORE BIT(31) +- +-struct hal_reo_to_ppe_ring { +- u32 buffer_addr; +- u32 info0; /* %HAL_REO_TO_PPE_RING_INFO0_ */ +-} __packed; +- +-/* hal_reo_to_ppe_ring +- * +- * Producer: REO +- * Consumer: PPE +- * +- * buf_addr_info +- * Details of the physical address of a buffer or MSDU +- * link descriptor. +- * +- * data_length +- * Length of valid data in bytes +- * +- * data_offset +- * Offset to the data from buffer pointer. Can be used to +- * strip header in the data for tunnel termination etc. +- * +- * pool_id +- * REO has global configuration register for this field. +- * It may have several free buffer pools, each +- * RX-Descriptor ring can fetch free buffer from specific +- * buffer pool; pool id will indicate which pool the buffer +- * will be released to; POOL_ID Zero returned to SW +- * +- * preheader +- * Disabled: 0 (Default) +- * Enabled: 1 +- * +- * tso_en +- * Disabled: 0 (Default) +- * Enabled: 1 +- * +- * more +- * More Segments followed +- */ +- + enum hal_reo_entr_rxdma_push_reason { + HAL_REO_ENTR_RING_RXDMA_PUSH_REASON_ERR_DETECTED, + HAL_REO_ENTR_RING_RXDMA_PUSH_REASON_ROUTING_INSTRUCTION, +@@ -2936,18 +2889,15 @@ struct hal_reo_desc_thresh_reached_statu + * entries into this Ring has looped around the ring. + */ + +-#define HAL_TCL_ENTRANCE_FROM_PPE_RING_INFO0_DATA_LENGTH GENMASK(13, 0) +-#define HAL_TCL_ENTRANCE_FROM_PPE_RING_INFO0_L4_CSUM_STATUS BIT(14) +-#define HAL_TCL_ENTRANCE_FROM_PPE_RING_INFO0_L3_CSUM_STATUS BIT(15) +-#define HAL_TCL_ENTRANCE_FROM_PPE_RING_INFO0_PID GENMASK(27, 24) +-#define HAL_TCL_ENTRANCE_FROM_PPE_RING_INFO0_QDISC BIT(28) +-#define HAL_TCL_ENTRANCE_FROM_PPE_RING_INFO0_MULTICAST BIT(29) +-#define HAL_TCL_ENTRANCE_FROM_PPE_RING_INFO0_MORE BIT(30) +-#define HAL_TCL_ENTRANCE_FROM_PPE_RING_INFO0_VALID_TOGGLE BIT(31) +- + struct hal_tcl_entrance_from_ppe_ring { + u32 buffer_addr; + u32 info0; ++ u32 opaque_lo; ++ u32 opaque_hi; ++ u32 info1; ++ u32 info2; ++ u32 info3; ++ u32 info4; + } __packed; + + struct hal_mon_buf_ring { +--- a/drivers/net/wireless/ath/ath12k/hal_rx.c ++++ b/drivers/net/wireless/ath/ath12k/hal_rx.c +@@ -835,6 +835,20 @@ void ath12k_hal_reo_init_cmd_ring(struct + } + } + ++void ath12k_hal_reo_ring_ctrl_hash_ix0_setup(struct ath12k_base *ab) ++{ ++ u32 reo_base = HAL_SEQ_WCSS_UMAC_REO_REG; ++ u32 curr, val; ++ ++ curr = ath12k_hif_read32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_0); ++ val = curr & ~(REO_DEST_CTRL_IX_0_RING6_MAP_MASK << ++ REO_DEST_CTRL_IX_0_RING6_MAP_SHFT); ++ val |= (REO2PPE_DST_RING_MAP << REO_DEST_CTRL_IX_0_RING6_MAP_SHFT); ++ ++ ath12k_hif_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_0, ++ val); ++} ++ + void ath12k_hal_reo_ring_ctrl_hash_ix2_setup(struct ath12k_base *ab, + u32 ring_hash_map) + { +@@ -883,6 +897,7 @@ void ath12k_hal_reo_hw_setup(struct ath1 + ath12k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_3(ab), + HAL_DEFAULT_VO_REO_TIMEOUT_USEC); + ++ ath12k_hal_reo_ring_ctrl_hash_ix0_setup(ab); + ath12k_hal_reo_ring_ctrl_hash_ix2_setup(ab, ring_hash_map); + ath12k_hal_reo_ring_ctrl_hash_ix3_setup(ab, ring_hash_map); + +--- a/drivers/net/wireless/ath/ath12k/hal_rx.h ++++ b/drivers/net/wireless/ath/ath12k/hal_rx.h +@@ -959,6 +959,10 @@ enum ath12k_eht_ru_size { + ATH12K_EHT_RU_INVALID, + }; + ++#define REO2PPE_DST_RING_MAP 11 ++#define REO_DEST_CTRL_IX_0_RING6_MAP_MASK 0xF ++#define REO_DEST_CTRL_IX_0_RING6_MAP_SHFT 24 ++ + void ath12k_hal_reo_status_queue_stats(struct ath12k_base *ab, u32 *reo_desc, + struct hal_reo_status *status); + void ath12k_hal_reo_flush_queue_status(struct ath12k_base *ab, u32 *reo_desc, +--- a/drivers/net/wireless/ath/ath12k/hal_tx.c ++++ b/drivers/net/wireless/ath/ath12k/hal_tx.c +@@ -99,6 +99,16 @@ void ath12k_hal_tx_configure_bank_regist + bank_config); + } + ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++void ath12k_hal_tx_set_ppe_vp_entry(struct ath12k_base *ab, u32 ppe_vp_config, ++ u32 ppe_vp_idx) ++{ ++ ath12k_hif_write32(ab, HAL_TX_PPE_VP_CONFIG_TABLE_ADDR + ++ HAL_TX_PPE_VP_CONFIG_TABLE_OFFSET * ppe_vp_idx, ++ ppe_vp_config); ++} ++#endif ++ + void ath12k_hal_tx_config_rbm_mapping(struct ath12k_base *ab,u8 ring_num, + u8 rbm_id, int ring_type) + { +--- a/drivers/net/wireless/ath/ath12k/hal_tx.h ++++ b/drivers/net/wireless/ath/ath12k/hal_tx.h +@@ -182,6 +182,22 @@ struct hal_tx_fes_status_end { + /* STA mode will have MCAST_PKT_CTRL instead of DSCP_TID_MAP bitfield */ + #define HAL_TX_BANK_CONFIG_DSCP_TIP_MAP_ID GENMASK(22, 17) + ++#define HAL_TX_PPE_VP_CONFIG_TABLE_ADDR 0x00a44194 ++#define HAL_TX_PPE_VP_CONFIG_TABLE_OFFSET 4 ++ ++#define HAL_TX_PPE_VP_CFG_VP_NUM GENMASK(7, 0) ++#define HAL_TX_PPE_VP_CFG_PMAC_ID GENMASK(9, 8) ++#define HAL_TX_PPE_VP_CFG_BANK_ID GENMASK(15, 10) ++#define HAL_TX_PPE_VP_CFG_VDEV_ID GENMASK(23, 16) ++#define HAL_TX_PPE_VP_CFG_SRCH_IDX_REG_NUM GENMASK(26, 24) ++#define HAL_TX_PPE_VP_CFG_USE_PPE_INT_PRI BIT(27) ++#define HAL_TX_PPE_VP_CFG_TO_FW BIT(28) ++#define HAL_TX_PPE_VP_CFG_DROP_PREC_EN BIT(29) ++ ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++void ath12k_hal_tx_set_ppe_vp_entry(struct ath12k_base *ab, u32 ppe_vp_config, ++ u32 ppe_vp_index); ++#endif + void ath12k_hal_tx_set_dscp_tid_map(struct ath12k_base *ab, int id); + int ath12k_hal_reo_cmd_send(struct ath12k_base *ab, struct hal_srng *srng, + enum hal_reo_cmd_type type, +--- a/drivers/net/wireless/ath/ath12k/hif.h ++++ b/drivers/net/wireless/ath/ath12k/hif.h +@@ -8,6 +8,7 @@ + #define ATH12K_HIF_H + + #include "core.h" ++#include "pci.h" + + struct ath12k_hif_ops { + u32 (*read32)(struct ath12k_base *sc, u32 address); +@@ -34,8 +35,56 @@ struct ath12k_hif_ops { + void (*get_ce_msi_idx)(struct ath12k_base *ab, u32 ce_id, u32 *msi_idx); + int (*ssr_notifier_reg)(struct ath12k_base *ab); + int (*ssr_notifier_unreg)(struct ath12k_base *ab); ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++ int (*ppeds_register_interrupts)(struct ath12k_base *ab, int type, int vector, ++ int ring_num); ++ void (*ppeds_free_interrupts)(struct ath12k_base *ab); ++ void (*ppeds_irq_enable)(struct ath12k_base *ab, enum ppeds_irq_type type); ++ void (*ppeds_irq_disable)(struct ath12k_base *ab, enum ppeds_irq_type type); ++#endif + }; + ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++static inline int ath12k_hif_ppeds_register_interrupts(struct ath12k_base *ab, int type, int vector, ++ int ring_num) ++{ ++ if (!test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ab->dev_flags)) ++ return 0; ++ ++ if (ab->hif.ops->ppeds_register_interrupts) ++ return ab->hif.ops->ppeds_register_interrupts(ab, type, vector, ++ ring_num); ++ return 0; ++} ++ ++static inline void ath12k_hif_ppeds_free_interrupts(struct ath12k_base *ab) ++{ ++ if (!test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ab->dev_flags)) ++ return; ++ ++ if (ab->hif.ops->ppeds_register_interrupts) ++ ab->hif.ops->ppeds_free_interrupts(ab); ++} ++ ++static inline void ath12k_hif_ppeds_irq_enable(struct ath12k_base *ab, enum ppeds_irq_type type) ++{ ++ if (!test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ab->dev_flags)) ++ return; ++ ++ if (ab->hif.ops->ppeds_irq_enable) ++ ab->hif.ops->ppeds_irq_enable(ab, type); ++} ++ ++static inline void ath12k_hif_ppeds_irq_disable(struct ath12k_base *ab, enum ppeds_irq_type type) ++{ ++ if (!test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ab->dev_flags)) ++ return; ++ ++ if (ab->hif.ops->ppeds_irq_disable) ++ ab->hif.ops->ppeds_irq_disable(ab, type); ++} ++#endif ++ + static inline int ath12k_hif_map_service_to_pipe(struct ath12k_base *ab, u16 service_id, + u8 *ul_pipe, u8 *dl_pipe) + { +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -158,6 +158,10 @@ static const struct ath12k_hw_ops ipq533 + #define ATH12K_TX_MON_RING_MASK_0 0x1 + #define ATH12K_TX_MON_RING_MASK_1 0x2 + ++#define ATH12K_PPE2TCL_RING_MASK_0 0x1 ++#define ATH12K_REO2PPE_RING_MASK_0 0x1 ++#define ATH12K_PPE_WBM2SW_RELEASE_RING_MASK_0 0x1 ++ + /* Target firmware's Copy Engine configuration. */ + static const struct ce_pipe_config ath12k_target_ce_config_wlan_qcn9274[] = { + /* CE0: host->target HTC control and raw streams */ +@@ -793,13 +797,14 @@ static const struct ath12k_hw_ring_mask + ATH12K_TX_RING_MASK_2, + 0, 0, 0, 0, 0, 0, 0, 0, + ATH12K_TX_RING_MASK_4, ++ 0, 0, 0 + }, + .rx_mon_dest = { + 0, 0, 0, 0, 0, 0, 0, 0, + ATH12K_RX_MON_RING_MASK_0, + ATH12K_RX_MON_RING_MASK_1, + ATH12K_RX_MON_RING_MASK_2, +- 0, ++ 0, 0, 0, 0 + }, + .rx = { + 0, 0, 0, 0, +@@ -808,32 +813,52 @@ static const struct ath12k_hw_ring_mask + ATH12K_RX_RING_MASK_2, + ATH12K_RX_RING_MASK_3, + 0, 0, 0, 0, ++ 0, 0, 0 + }, + .rx_err = { + 0, 0, 0, + ATH12K_RX_ERR_RING_MASK_0, + 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0 + }, + .rx_wbm_rel = { + 0, 0, 0, + ATH12K_RX_WBM_REL_RING_MASK_0, + 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0 + }, + .reo_status = { + 0, 0, 0, + ATH12K_REO_STATUS_RING_MASK_0, + 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0 + }, + .host2rxdma = { + 0, 0, 0, + ATH12K_HOST2RXDMA_RING_MASK_0, + 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0 + }, + .tx_mon_dest = { + ATH12K_TX_MON_RING_MASK_0, + ATH12K_TX_MON_RING_MASK_1, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0 + }, ++ .ppe2tcl = { ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ ATH12K_PPE2TCL_RING_MASK_0, 0, 0 ++ }, ++ .reo2ppe = { ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, ATH12K_REO2PPE_RING_MASK_0, 0 ++ }, ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++ .wbm2sw6_ppeds_tx_cmpln = { ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, ATH12K_PPE_WBM2SW_RELEASE_RING_MASK_0 ++ }, ++#endif + }; + + static const struct ath12k_hw_ring_mask ath12k_hw_ring_mask_ipq5332 = { +@@ -990,8 +1015,8 @@ static const struct ath12k_hw_regs qcn92 + .hal_wbm0_release_ring_base_lsb = 0x00000dd8, + .hal_wbm1_release_ring_base_lsb = 0x00000e50, + +- /* PPE release ring address */ +- .hal_ppe_rel_ring_base = 0x0000043c, ++ /* reo2ppe ring address */ ++ .hal_reo2ppe_ring_base = 0x00000938, + + /* PCIe base address */ + .pcie_qserdes_sysclk_en_sel = 0x01e0c0a8, +@@ -1081,8 +1106,8 @@ const struct ath12k_hw_regs qcn9274_v2_r + .hal_wbm0_release_ring_base_lsb = 0x00000e08, + .hal_wbm1_release_ring_base_lsb = 0x00000e80, + +- /* PPE release ring address */ +- .hal_ppe_rel_ring_base = 0x0000046c, ++ /* reo2ppe ring base address */ ++ .hal_reo2ppe_ring_base = 0x00000938, + + /* PCIe base address */ + .pcie_qserdes_sysclk_en_sel = 0x01e0c0a8, +@@ -1171,9 +1196,6 @@ const struct ath12k_hw_regs ipq5332_regs + .hal_wbm0_release_ring_base_lsb = 0x00000e08, + .hal_wbm1_release_ring_base_lsb = 0x00000e80, + +- /* PPE release ring address */ +- .hal_ppe_rel_ring_base = 0x0000046c, +- + /* CE base address */ + .hal_umac_ce0_src_reg_base = 0x00740000, + .hal_umac_ce0_dest_reg_base = 0x00741000, +@@ -1235,7 +1257,8 @@ static const struct ath12k_hw_hal_params + HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW1_EN | + HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW2_EN | + HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW3_EN | +- HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW4_EN, ++ HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW4_EN | ++ HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW6_EN, + }; + + static const struct ath12k_hw_hal_params ath12k_hw_hal_params_wcn7850 = { +--- a/drivers/net/wireless/ath/ath12k/hw.h ++++ b/drivers/net/wireless/ath/ath12k/hw.h +@@ -73,6 +73,7 @@ + #define ATH12K_HW_DEFAULT_QUEUE 0 + + #define ATH12K_HW_MAX_QUEUES 4 ++#define ATH12K_HW_MAX_QUEUES_PPEDS 1 + #define ATH12K_QUEUE_LEN 4096 + + #define ATH11k_HW_RATECODE_CCK_SHORT_PREAM_MASK 0x4 +@@ -116,22 +117,28 @@ enum ath12k_bus { + ATH12K_BUS_AHB, + }; + +-#define ATH12K_EXT_IRQ_GRP_NUM_MAX 13 +- ++/* Regular 12 Host DP interrupts + 3 PPEDS interrupts */ ++#define ATH12K_EXT_IRQ_DP_NUM_VECTORS 15 ++#define ATH12K_EXT_IRQ_GRP_NUM_MAX 12 + struct hal_rx_desc; + struct hal_tcl_data_cmd; + struct htt_rx_ring_tlv_filter; + enum hal_encrypt_type; + + struct ath12k_hw_ring_mask { +- u8 tx[ATH12K_EXT_IRQ_GRP_NUM_MAX]; +- u8 rx_mon_dest[ATH12K_EXT_IRQ_GRP_NUM_MAX]; +- u8 rx[ATH12K_EXT_IRQ_GRP_NUM_MAX]; +- u8 rx_err[ATH12K_EXT_IRQ_GRP_NUM_MAX]; +- u8 rx_wbm_rel[ATH12K_EXT_IRQ_GRP_NUM_MAX]; +- u8 reo_status[ATH12K_EXT_IRQ_GRP_NUM_MAX]; +- u8 host2rxdma[ATH12K_EXT_IRQ_GRP_NUM_MAX]; +- u8 tx_mon_dest[ATH12K_EXT_IRQ_GRP_NUM_MAX]; ++ u8 tx[ATH12K_EXT_IRQ_DP_NUM_VECTORS]; ++ u8 rx_mon_dest[ATH12K_EXT_IRQ_DP_NUM_VECTORS]; ++ u8 rx[ATH12K_EXT_IRQ_DP_NUM_VECTORS]; ++ u8 rx_err[ATH12K_EXT_IRQ_DP_NUM_VECTORS]; ++ u8 rx_wbm_rel[ATH12K_EXT_IRQ_DP_NUM_VECTORS]; ++ u8 reo_status[ATH12K_EXT_IRQ_DP_NUM_VECTORS]; ++ u8 host2rxdma[ATH12K_EXT_IRQ_DP_NUM_VECTORS]; ++ u8 tx_mon_dest[ATH12K_EXT_IRQ_DP_NUM_VECTORS]; ++ u8 ppe2tcl[ATH12K_EXT_IRQ_DP_NUM_VECTORS]; ++ u8 reo2ppe[ATH12K_EXT_IRQ_DP_NUM_VECTORS]; ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++ u8 wbm2sw6_ppeds_tx_cmpln[ATH12K_EXT_IRQ_DP_NUM_VECTORS]; ++#endif + }; + + struct ath12k_hw_hal_params { +@@ -321,6 +328,7 @@ struct ath12k_hw_regs { + u32 hal_tcl_status_ring_base_lsb; + + u32 hal_reo2_ring_base; ++ u32 hal_reo2ppe_ring_base; + u32 hal_reo1_misc_ctrl_addr; + u32 hal_reo1_sw_cookie_cfg0; + u32 hal_reo1_sw_cookie_cfg1; +@@ -370,8 +378,6 @@ struct ath12k_hw_regs { + u32 hal_wbm0_release_ring_base_lsb; + u32 hal_wbm1_release_ring_base_lsb; + +- u32 hal_ppe_rel_ring_base; +- + u32 pcie_qserdes_sysclk_en_sel; + u32 pcie_pcs_osc_dtct_config_base; + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -23,6 +23,7 @@ + #include "testmode.h" + #include "peer.h" + #include "debugfs_sta.h" ++#include "ppe.h" + + #define CHAN2G(_channel, _freq, _flags) { \ + .band = NL80211_BAND_2GHZ, \ +@@ -9053,6 +9054,16 @@ static int ath12k_mac_radio_start(struct + } + } + ++ /* PPE DS requires eapol packets to be routed to wbm release ring */ ++ if (test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ar->ab->dev_flags)) { ++ ret = ath12k_dp_rx_pkt_type_filter(ar, ATH12K_PKT_TYPE_EAP, ++ ATH12K_ROUTE_EAP_METADATA); ++ if (ret) { ++ ath12k_err(ar->ab, "failed to configure EAP pkt route: %d\n", ret); ++ goto err; ++ } ++ } ++ + __ath12k_set_antenna(ar, ar->cfg_tx_chainmask, ar->cfg_rx_chainmask); + + /* TODO: Do we need to enable ANI? */ +@@ -14122,6 +14133,10 @@ static const struct ieee80211_ops ath12k + #endif + .get_txpower = ath12k_mac_op_get_txpower, + .set_radar_background = ath12k_mac_op_set_radar_background, ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++ .ppeds_attach_vdev = ath12k_mac_op_ppeds_attach_vdev, ++ .ppeds_detach_vdev = ath12k_mac_op_ppeds_detach_vdev, ++#endif + }; + + static void ath12k_mac_update_ch_list(struct ath12k *ar, +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -14,6 +14,7 @@ + #include "hif.h" + #include "mhi.h" + #include "debug.h" ++#include "ppe.h" + + #define ATH12K_PCI_BAR_NUM 0 + #define ATH12K_PCI_DMA_MASK 32 +@@ -52,7 +53,7 @@ EXPORT_SYMBOL(tx_comp_budget); + module_param_named(tx_comp_budget, tx_comp_budget, uint, 0644); + MODULE_PARM_DESC(tx_comp_budget, "tx_comp_budget"); + +-char dp_irq_name[ATH12K_MAX_PCI_DOMAINS + 1][ATH12K_EXT_IRQ_GRP_NUM_MAX][DP_IRQ_NAME_LEN] = {}; ++char dp_irq_name[ATH12K_MAX_PCI_DOMAINS + 1][ATH12K_EXT_IRQ_DP_NUM_VECTORS][DP_IRQ_NAME_LEN] = {}; + + unsigned int ath12k_fw_mem_seg; + EXPORT_SYMBOL(ath12k_fw_mem_seg); +@@ -85,7 +86,7 @@ static const struct ath12k_msi_config at + .users = (struct ath12k_msi_user[]) { + { .name = "MHI", .num_vectors = 3, .base_vector = 0 }, + { .name = "CE", .num_vectors = 5, .base_vector = 3 }, +- { .name = "DP", .num_vectors = 12, .base_vector = 8 }, ++ { .name = "DP", .num_vectors = 15, .base_vector = 8 }, + }, + }, + }; +@@ -545,6 +546,11 @@ static int ath12k_pci_ext_irq_config(str + ab->hw_params->ring_mask->rx_wbm_rel[i] || + ab->hw_params->ring_mask->reo_status[i] || + ab->hw_params->ring_mask->host2rxdma[i] || ++ ab->hw_params->ring_mask->ppe2tcl[i] || ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++ ab->hw_params->ring_mask->wbm2sw6_ppeds_tx_cmpln[i] || ++#endif ++ ab->hw_params->ring_mask->reo2ppe[i] || + ab->hw_params->ring_mask->rx_mon_dest[i]) { + num_irq = 1; + } +@@ -590,6 +596,88 @@ static int ath12k_pci_ext_irq_config(str + return 0; + } + ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++int ath12k_pci_ppeds_register_interrupts(struct ath12k_base *ab, int type, int vector, ++ int ring_num) ++{ ++ struct ath12k_pci *ar_pci = (struct ath12k_pci *)ab->drv_priv; ++ int irq; ++ u8 bus_id = pci_domain_nr(ar_pci->pdev->bus); ++ int ret; ++ ++ if (type != HAL_REO2PPE && type != HAL_PPE2TCL && ++ !(type == HAL_WBM2SW_RELEASE && ++ ring_num == HAL_WBM2SW_PPEDS_TX_CMPLN_RING_NUM)) { ++ return 0; ++ } ++ ++ if (ab->ppeds_node_idx == -1) { ++ ath12k_err(ab, "invalid ppeds_node_idx in ppeds_register_interrupts\n"); ++ return -EINVAL; ++ } ++ ++ irq = ath12k_pci_get_msi_irq(ab->dev, vector); ++ ++ irq_set_status_flags(irq, IRQ_DISABLE_UNLAZY); ++ if (type == HAL_PPE2TCL) { ++ snprintf(&ab->dp.ppeds_irq_name[PPEDS_IRQ_PPE2TCL], sizeof(ab->dp.ppeds_irq_name), ++ "pci%d_ppe2tcl_%d", bus_id, ab->ppeds_node_idx); ++ ret = request_irq(irq, ath12k_ds_ppe2tcl_irq_handler, ++ IRQF_SHARED, ++ ab->dp.ppeds_irq_name[PPEDS_IRQ_PPE2TCL], (void *)ath12k_dp_get_ppe_ds_ctxt(ab)); ++ if (ret) ++ goto irq_fail; ++ ab->dp.ppeds_irq[PPEDS_IRQ_PPE2TCL] = irq; ++ } else if (type == HAL_REO2PPE) { ++ snprintf(&ab->dp.ppeds_irq_name[PPEDS_IRQ_REO2PPE], sizeof(ab->dp.ppeds_irq_name), ++ "pci%d_reo2ppe_%d", bus_id, ab->ppeds_node_idx); ++ ret = request_irq(irq, ath12k_ds_reo2ppe_irq_handler, ++ IRQF_SHARED, ++ ab->dp.ppeds_irq_name[PPEDS_IRQ_REO2PPE], (void *)ath12k_dp_get_ppe_ds_ctxt(ab)); ++ if (ret) ++ goto irq_fail; ++ ab->dp.ppeds_irq[PPEDS_IRQ_REO2PPE] = irq; ++ } else if (type == HAL_WBM2SW_RELEASE && ring_num == HAL_WBM2SW_PPEDS_TX_CMPLN_RING_NUM) { ++ snprintf(&ab->dp.ppeds_irq_name[PPEDS_IRQ_PPE_WBM2SW_REL], sizeof(ab->dp.ppeds_irq_name), ++ "pci%d_ppe_wbm_rel_%d", bus_id, ab->ppeds_node_idx); ++ ret = request_irq(irq, ath12k_dp_ppeds_handle_tx_comp, ++ IRQF_SHARED, ++ ab->dp.ppeds_irq_name[PPEDS_IRQ_PPE_WBM2SW_REL],(void *)ab); ++ if (ret) ++ goto irq_fail; ++ ab->dp.ppeds_irq[PPEDS_IRQ_PPE_WBM2SW_REL] = irq; ++ } ++ disable_irq_nosync(irq); ++ ++ return 0; ++ ++irq_fail: ++ return ret; ++} ++ ++void ath12k_pci_ppeds_irq_disable(struct ath12k_base *ab, enum ppeds_irq_type type) ++{ ++ disable_irq_nosync(ab->dp.ppeds_irq[type]); ++} ++ ++void ath12k_pci_ppeds_irq_enable(struct ath12k_base *ab, enum ppeds_irq_type type) ++{ ++ enable_irq(ab->dp.ppeds_irq[type]); ++} ++ ++void ath12k_pci_ppeds_free_interrupts(struct ath12k_base *ab) ++{ ++ disable_irq_nosync(ab->dp.ppeds_irq[PPEDS_IRQ_PPE2TCL]); ++ free_irq(ab->dp.ppeds_irq[PPEDS_IRQ_PPE2TCL], ath12k_dp_get_ppe_ds_ctxt(ab)); ++ ++ disable_irq_nosync(ab->dp.ppeds_irq[PPEDS_IRQ_REO2PPE]); ++ free_irq(ab->dp.ppeds_irq[PPEDS_IRQ_REO2PPE], ath12k_dp_get_ppe_ds_ctxt(ab)); ++ ++ disable_irq_nosync(ab->dp.ppeds_irq[PPEDS_IRQ_PPE_WBM2SW_REL]); ++ free_irq(ab->dp.ppeds_irq[PPEDS_IRQ_PPE_WBM2SW_REL], ab); ++} ++#endif ++ + static int ath12k_pci_config_irq(struct ath12k_base *ab) + { + struct ath12k_ce_pipe *ce_pipe; +@@ -1266,6 +1354,12 @@ static const struct ath12k_hif_ops ath12 + .ce_irq_enable = ath12k_pci_hif_ce_irq_enable, + .ce_irq_disable = ath12k_pci_hif_ce_irq_disable, + .get_ce_msi_idx = ath12k_pci_get_ce_msi_idx, ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++ .ppeds_register_interrupts = ath12k_pci_ppeds_register_interrupts, ++ .ppeds_free_interrupts = ath12k_pci_ppeds_free_interrupts, ++ .ppeds_irq_enable = ath12k_pci_ppeds_irq_enable, ++ .ppeds_irq_disable = ath12k_pci_ppeds_irq_disable, ++#endif + }; + + static int ath12k_pci_probe(struct pci_dev *pdev, +--- a/drivers/net/wireless/ath/ath12k/pci.h ++++ b/drivers/net/wireless/ath/ath12k/pci.h +@@ -68,6 +68,12 @@ + #define QRTR_PCI_DOMAIN_NR_MASK GENMASK(7, 4) + #define QRTR_PCI_BUS_NUMBER_MASK GENMASK(3, 0) + ++enum ppeds_irq_type { ++ PPEDS_IRQ_PPE2TCL, ++ PPEDS_IRQ_REO2PPE, ++ PPEDS_IRQ_PPE_WBM2SW_REL, ++}; ++ + struct ath12k_msi_user { + char *name; + int num_vectors; +@@ -133,4 +139,11 @@ void ath12k_pci_stop(struct ath12k_base + int ath12k_pci_start(struct ath12k_base *ab); + int ath12k_pci_power_up(struct ath12k_base *ab); + void ath12k_pci_power_down(struct ath12k_base *ab); ++void ath12k_pci_ppeds_free_interrupts(struct ath12k_base *ab); ++int ath12k_pci_ppeds_register_interrupts(struct ath12k_base *ab, int type, ++ int vector, int ring_num); ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++void ath12k_pci_ppeds_irq_enable(struct ath12k_base *ab, enum ppeds_irq_type type); ++void ath12k_pci_ppeds_irq_disable(struct ath12k_base *ab, enum ppeds_irq_type type); ++#endif + #endif /* ATH12K_PCI_H */ +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/ppe.c +@@ -0,0 +1,997 @@ ++// SPDX-License-Identifier: BSD-3-Clause-Clear ++/* ++ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++#include "core.h" ++#include "dp_tx.h" ++#include "debug.h" ++#include "debugfs_sta.h" ++#include "hw.h" ++#include "peer.h" ++#include ++#include ++#include ++#include ++#include ++#include "hif.h" ++#include "ppe.h" ++ ++static atomic_t num_ppeds_nodes; ++extern struct sk_buff * ++ath12k_dp_ppeds_tx_release_desc_nolock(struct ath12k_dp *dp, ++ struct ath12k_ppeds_tx_desc_info *tx_desc, ++ u8 ring_id); ++ ++irqreturn_t ath12k_ds_ppe2tcl_irq_handler(int irq, void *ctxt) ++{ ++ ppe_ds_ppe2tcl_wlan_handle_intr(ctxt); ++ ++ return IRQ_HANDLED; ++} ++ ++irqreturn_t ath12k_ds_reo2ppe_irq_handler(int irq, void *ctxt) ++{ ++ ppe_ds_reo2ppe_wlan_handle_intr(ctxt); ++ ++ return IRQ_HANDLED; ++} ++ ++void *ath12k_dp_get_ppe_ds_ctxt(struct ath12k_base *ab) ++{ ++ if (!ab || !ab->ppeds_handle) ++ return NULL; ++ ++ return ppe_ds_wlan_get_intr_ctxt(ab->ppeds_handle); ++} ++ ++static void ath12k_ppeds_set_tcl_prod_idx(ppe_ds_wlan_handle_t *ppeds_handle, u16 tcl_prod_idx) ++{ ++ struct ath12k_base *ab = *(struct ath12k_base **)ppe_ds_wlan_priv(ppeds_handle); ++ struct ath12k_dp *dp = &ab->dp; ++ struct hal_srng *srng; ++ ++ srng = &ab->hal.srng_list[dp->ppe2tcl_ring.ring_id]; ++ if (!ab->stats_disable) ++ ab->ppeds_stats.tcl_prod_cnt++; ++ ++ srng->u.src_ring.hp = tcl_prod_idx * srng->entry_size; ++ ath12k_hal_srng_access_end(ab, srng); ++} ++ ++static u16 ath12k_ppeds_get_tcl_cons_idx(ppe_ds_wlan_handle_t *ppeds_handle) ++{ ++ struct ath12k_base *ab = *(struct ath12k_base **)ppe_ds_wlan_priv(ppeds_handle); ++ struct ath12k_dp *dp = &ab->dp; ++ struct hal_srng *srng; ++ u32 tp; ++ ++ if (!ab->stats_disable) ++ ab->ppeds_stats.tcl_cons_cnt++; ++ ++ srng = &ab->hal.srng_list[dp->ppe2tcl_ring.ring_id]; ++ tp = *(volatile u32 *)(srng->u.src_ring.tp_addr); ++ ++ return tp / srng->entry_size; ++} ++ ++static void ath12k_ppeds_set_reo_cons_idx(ppe_ds_wlan_handle_t *ppeds_handle, ++ u16 reo_cons_idx) ++{ ++ struct ath12k_base *ab = *(struct ath12k_base **)ppe_ds_wlan_priv(ppeds_handle); ++ struct ath12k_dp *dp = &ab->dp; ++ struct hal_srng *srng; ++ ++ srng = &ab->hal.srng_list[dp->reo2ppe_ring.ring_id]; ++ if (!ab->stats_disable) ++ ab->ppeds_stats.reo_cons_cnt++; ++ ++ srng->u.src_ring.hp = reo_cons_idx * srng->entry_size; ++ ath12k_hal_srng_access_end(ab, srng); ++} ++ ++static u16 ath12k_ppeds_get_reo_prod_idx(ppe_ds_wlan_handle_t *ppeds_handle) ++{ ++ struct ath12k_base *ab = *(struct ath12k_base **)ppe_ds_wlan_priv(ppeds_handle); ++ struct ath12k_dp *dp = &ab->dp; ++ struct hal_srng *srng; ++ u32 hp; ++ ++ srng = &ab->hal.srng_list[dp->reo2ppe_ring.ring_id]; ++ hp = *(volatile u32 *)(srng->u.dst_ring.hp_addr); ++ if (!ab->stats_disable) ++ ab->ppeds_stats.reo_prod_cnt++; ++ return hp / srng->entry_size; ++} ++ ++/* enable/disable PPE2TCL irq */ ++static inline void ath12k_ppeds_enable_srng_intr(ppe_ds_wlan_handle_t *ppeds_handle, bool enable) ++{ ++ struct ath12k_base *ab = *(struct ath12k_base **)ppe_ds_wlan_priv(ppeds_handle); ++ ++ if (enable) { ++ if (!ab->stats_disable) ++ ab->ppeds_stats.enable_intr_cnt++; ++ ++ ath12k_hif_ppeds_irq_enable(ab, PPEDS_IRQ_PPE2TCL); ++ } ++ else { ++ if (!ab->stats_disable) ++ ab->ppeds_stats.disable_intr_cnt++; ++ ++ ath12k_hif_ppeds_irq_disable(ab, PPEDS_IRQ_PPE2TCL); ++ } ++} ++ ++int ath12k_dp_rx_bufs_replenish_ppeds(struct ath12k_base *ab, ++ struct dp_rxdma_ring *rx_ring, ++ int req_entries, ++ enum hal_rx_buf_return_buf_manager mgr) ++{ ++ struct hal_srng *rxdma_srng; ++ u32 *rxdma_desc; ++ u32 cookie; ++ dma_addr_t paddr; ++ struct sk_buff *skb; ++ struct ath12k_rx_desc_info *rx_desc, *cur; ++ int count = 0, num_remain; ++ ++ rxdma_srng = &ab->hal.srng_list[rx_ring->refill_buf_ring.ring_id]; ++ ++ spin_lock_bh(&rxdma_srng->lock); ++ ath12k_hal_srng_access_begin(ab, rxdma_srng); ++ ++ num_remain = req_entries; ++ while (num_remain > 0) { ++ spin_lock_bh(&ab->dp.rx_desc_lock); ++ ++ rx_desc = list_first_entry_or_null(&ab->dp.rx_ppeds_reuse_list, ++ struct ath12k_rx_desc_info, ++ list); ++ if (!rx_desc) { ++ spin_unlock_bh(&ab->dp.rx_desc_lock); ++ break; ++ } ++ ++ skb = rx_desc->skb; ++ if (!skb) { ++ ath12k_err(ab, "ppeds rx desc with no skb when reusing!\n"); ++ spin_unlock_bh(&ab->dp.rx_desc_lock); ++ break; ++ } ++ cookie = rx_desc->cookie; ++ list_move_tail(&rx_desc->list, &ab->dp.rx_desc_used_list); ++ spin_unlock_bh(&ab->dp.rx_desc_lock); ++ ++ rxdma_desc = ath12k_hal_srng_src_get_next_entry(ab, rxdma_srng); ++ if (!rxdma_desc) { ++ /* Remove desc from used list when no rxdma entry is available */ ++ spin_lock_bh(&ab->dp.rx_desc_lock); ++ list_move_tail(&rx_desc->list, &ab->dp.rx_ppeds_reuse_list); ++ spin_unlock_bh(&ab->dp.rx_desc_lock); ++ break; ++ } ++ ++ paddr = ATH12K_SKB_RXCB(skb)->paddr; ++ ath12k_hal_rx_buf_addr_info_set(rxdma_desc, paddr, cookie, mgr); ++ ++ num_remain--; ++ count++; ++ } ++ ath12k_hal_srng_access_end(ab, rxdma_srng); ++ spin_unlock_bh(&rxdma_srng->lock); ++ ++ if (!ab->stats_disable) ++ ab->ppeds_stats.num_rx_desc_reused += count; ++ ++ if (count == req_entries) ++ return 0; ++ ++ /* move any remaining descriptors to free list */ ++ count = 0; ++ while (num_remain) { ++ spin_lock_bh(&ab->dp.rx_desc_lock); ++ cur = list_first_entry_or_null(&ab->dp.rx_ppeds_reuse_list, ++ struct ath12k_rx_desc_info, ++ list); ++ if (!cur) { ++ /* break the loop as soon as list is empty */ ++ spin_unlock_bh(&ab->dp.rx_desc_lock); ++ break; ++ } ++ ++ skb = cur->skb; ++ cur->skb= NULL; ++ list_move_tail(&cur->list, &ab->dp.rx_desc_free_list); ++ spin_unlock_bh(&ab->dp.rx_desc_lock); ++ num_remain--; ++ count++; ++ ++ if (!skb) { ++ ath12k_err(ab, "ppeds rx desc with no skb when freeing\n"); ++ continue; ++ } ++ ++ /* When recycled_for_ds is set, packet is used by DS rings and never has ++ * touched by host. So, buffer unmap can be skipped. */ ++ if (!skb->recycled_for_ds) { ++ dmac_inv_range_no_dsb(skb->data, skb->data + (skb->len + ++ skb_tailroom(skb))); ++ dma_unmap_single_attrs(ab->dev, ATH12K_SKB_RXCB(skb)->paddr, ++ skb->len + skb_tailroom(skb), ++ DMA_FROM_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); ++ } ++ ++ skb->recycled_for_ds = 0; ++ skb->fast_recycled = 0; ++ dev_kfree_skb_any(skb); ++ } ++ ++ if (!ab->stats_disable) ++ ab->ppeds_stats.num_rx_desc_freed += count; ++ ++ return 0; ++} ++ ++static void ath12k_ppeds_release_rx_desc(ppe_ds_wlan_handle_t *ppeds_handle, ++ struct ppe_ds_wlan_rxdesc_elem *arr, u16 count) ++{ ++ struct ath12k_base *ab = *(struct ath12k_base **)ppe_ds_wlan_priv(ppeds_handle); ++ struct ath12k_base *src_ab = NULL; ++ u32 rx_bufs_reaped[ATH12K_MAX_SOCS] = {0}; ++ struct ath12k_rx_desc_info *rx_desc; ++ struct dp_rxdma_ring *rx_ring; ++ int chip_id; ++ int i = 0; ++ ++ if (!ab->stats_disable) ++ ab->ppeds_stats.release_rx_desc_cnt += count; ++ ++ for (i = 0; i < count; i++) { ++ rx_desc = (struct ath12k_rx_desc_info *)arr[i].cookie; ++ if (rx_desc == NULL) { ++ ath12k_err(ab,"error: rx desc is null\n"); ++ continue; ++ } ++ src_ab = rx_desc->ab; ++ /* TODO: review split phy */ ++ rx_bufs_reaped[src_ab->chip_id]++; ++ ++ spin_lock_bh(&src_ab->dp.rx_desc_lock); ++ list_move_tail(&rx_desc->list, &src_ab->dp.rx_ppeds_reuse_list); ++ spin_unlock_bh(&src_ab->dp.rx_desc_lock); ++ } ++ ++ for (chip_id = 0; chip_id < ATH12K_MAX_SOCS; chip_id++) { ++ if (!rx_bufs_reaped[chip_id]) ++ continue; ++ ++ src_ab = ab->ag->ab[chip_id]; ++ rx_ring = &src_ab->dp.rx_refill_buf_ring; ++ ath12k_dp_rx_bufs_replenish_ppeds(src_ab, rx_ring, ++ rx_bufs_reaped[chip_id], ++ src_ab->hw_params->hal_params->rx_buf_rbm); ++ } ++ ++ return; ++} ++ ++static ++void ath12k_ppeds_release_tx_desc_single(ppe_ds_wlan_handle_t *ppeds_handle, ++ u32 cookie) ++{ ++ struct ath12k_base *ab = *(struct ath12k_base **)ppe_ds_wlan_priv(ppeds_handle); ++ ++ if (!ab->stats_disable) ++ ab->ppeds_stats.release_tx_single_cnt++; ++ ++ return; ++} ++ ++static u32 ath12k_ppeds_get_batched_tx_desc(ppe_ds_wlan_handle_t *ppeds_handle, ++ struct ppe_ds_wlan_txdesc_elem *arr, ++ u32 num_buff_req, ++ u32 buff_size, ++ u32 headroom) ++{ ++ struct ath12k_base *ab = *(struct ath12k_base **)ppe_ds_wlan_priv(ppeds_handle); ++ struct ath12k_dp *dp = &ab->dp; ++ int i; ++ int allocated = 0; ++ struct sk_buff *skb = NULL; ++ int flags = GFP_ATOMIC; ++ dma_addr_t paddr; ++ struct ath12k_ppeds_tx_desc_info *tx_desc = NULL; ++ ++#if LINUX_VERSION_IS_GEQ(4,4,0) ++ flags = flags & ~__GFP_KSWAPD_RECLAIM; ++#endif ++ ++ spin_lock_bh(&dp->ppeds_tx_desc_lock[ATH12K_PPEDS_DEFAULT_POOL_ID]); ++ for (i = 0; i < num_buff_req; i++) { ++ tx_desc = ath12k_dp_ppeds_tx_assign_desc_nolock(dp, ATH12K_PPEDS_DEFAULT_POOL_ID); ++ if (unlikely(!tx_desc)) { ++ ath12k_err(ab, "ran out of ppeds tx desc!\n"); ++ dsb(st); ++ break; ++ } ++ ++ /* allocate new skb only if one was not already found from reuse list */ ++ if (!tx_desc->skb) { ++ /* In skb recycler, if recyler module allocates the buffers ++ * already used by DS module to DS, then memzero, shinfo ++ * reset can be avoided, since the DS packets were not ++ * processed by SW ++ */ ++ skb = __netdev_alloc_skb_no_skb_reset(NULL, buff_size, flags); ++ if (unlikely(!skb)) { ++ ath12k_dp_ppeds_tx_release_desc_nolock(dp, tx_desc, ++ ATH12K_PPEDS_DEFAULT_POOL_ID); ++ break; ++ } ++ ++ skb_reserve(skb, headroom); ++ if (!skb->recycled_for_ds) { ++ dmac_inv_range_no_dsb((void *)skb->data, ++ (void *)skb->data + buff_size - headroom); ++ skb->recycled_for_ds = 1; ++ } ++ ++ paddr = virt_to_phys(skb->data); ++ ++ tx_desc->skb = skb; ++ tx_desc->paddr = paddr; ++ } ++ ++ arr[i].opaque_lo = tx_desc->desc_id; ++ arr[i].opaque_hi = 0; ++ arr[i].buff_addr = tx_desc->paddr; ++ allocated++; ++ } ++ spin_unlock_bh(&dp->ppeds_tx_desc_lock[ATH12K_PPEDS_DEFAULT_POOL_ID]); ++ ++ dsb(st); ++ ++ if (!ab->stats_disable) { ++ ab->ppeds_stats.get_tx_desc_cnt++; ++ ab->ppeds_stats.tx_desc_allocated += allocated; ++ } ++ ++ return allocated; ++} ++ ++static int ath12k_dp_ppeds_tx_comp_poll(struct napi_struct *napi, int budget) ++{ ++ struct ath12k_base *ab = container_of(napi, struct ath12k_base, ppeds_napi_ctxt.napi); ++ int total_budget = (budget << 2) - 1; ++ int work_done; ++ ++ work_done = ath12k_ppeds_tx_completion_handler(ab, total_budget); ++ if (!ab->stats_disable) ++ ab->ppeds_stats.tx_desc_freed += work_done; ++ ++ work_done = (work_done + 1) >> 2; ++ ++ if ( budget > work_done){ ++ napi_complete(napi); ++ ath12k_hif_ppeds_irq_enable(ab, PPEDS_IRQ_PPE_WBM2SW_REL); ++ } ++ ++ return (work_done > budget) ? budget : work_done; ++} ++ ++/* PPE-DS release interrupt */ ++irqreturn_t ath12k_dp_ppeds_handle_tx_comp(int irq, void *ctxt) ++{ ++ struct ath12k_base *ab = (struct ath12k_base *)ctxt; ++ struct ath12k_ppeds_napi *napi_ctxt = &ab->ppeds_napi_ctxt; ++ ++ ath12k_hif_ppeds_irq_disable(ab, PPEDS_IRQ_PPE_WBM2SW_REL); ++ napi_schedule(&napi_ctxt->napi); ++ return IRQ_HANDLED; ++} ++ ++int ath12k_ppe_napi_budget = NAPI_POLL_WEIGHT; ++static int ath12k_dp_ppeds_add_napi_ctxt(struct ath12k_base *ab) ++{ ++ struct ath12k_ppeds_napi *napi_ctxt = &ab->ppeds_napi_ctxt; ++ int ret; ++ ++ ret = init_dummy_netdev((struct net_device *)&napi_ctxt->ndev); ++ if (ret){ ++ ath12k_err(ab,"dummy netdev init fail\n"); ++ return -ENOSR; ++ } ++ netif_napi_add(&napi_ctxt->ndev, &napi_ctxt->napi, ++ ath12k_dp_ppeds_tx_comp_poll, ath12k_ppe_napi_budget); ++ ++ return 0; ++} ++ ++static void ath12k_dp_ppeds_del_napi_ctxt(struct ath12k_base *ab) ++{ ++ struct ath12k_ppeds_napi *napi_ctxt = &ab->ppeds_napi_ctxt; ++ ++ netif_napi_del(&napi_ctxt->napi); ++ ath12k_dbg(ab, ATH12K_DBG_PPE, " ath12k_dp_ppeds_del_napi_ctxt success\n"); ++} ++ ++static struct ppe_ds_wlan_ops ppeds_ops = { ++ .get_tx_desc_many = ath12k_ppeds_get_batched_tx_desc, ++ .release_tx_desc_single = ath12k_ppeds_release_tx_desc_single, ++ .enable_tx_consume_intr = ath12k_ppeds_enable_srng_intr, ++ .set_tcl_prod_idx = ath12k_ppeds_set_tcl_prod_idx, ++ .set_reo_cons_idx = ath12k_ppeds_set_reo_cons_idx, ++ .get_tcl_cons_idx = ath12k_ppeds_get_tcl_cons_idx, ++ .get_reo_prod_idx = ath12k_ppeds_get_reo_prod_idx, ++ .release_rx_desc = ath12k_ppeds_release_rx_desc, ++}; ++ ++void ath12k_dp_peer_ppeds_route_setup(struct ath12k *ar, struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta) ++{ ++ struct ath12k_base *ab = ar->ab; ++ u32 service_code = PPE_DRV_SC_SPF_BYPASS; ++ int ppe_routing_enable = 1; ++ u32 priority_valid = 0, src_info = arvif->vif->ppe_vp_num; ++ ++ if (!test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ab->dev_flags) || ++ src_info == -1) ++ return; ++ ++ ath12k_wmi_config_peer_ppeds_routing(ar, arsta->addr, arvif->vdev_id, ++ service_code, priority_valid, src_info, ++ ppe_routing_enable); ++} ++ ++static int ath12k_dp_ppeds_alloc_ppe_vp_profile(struct ath12k_base *ab, ++ struct ath12k_dp_ppe_vp_profile **vp_profile) ++{ ++ int i; ++ ++ mutex_lock(&ab->ppe_vp_tbl_lock); ++ if (ab->num_ppe_vp_profiles == PPE_VP_ENTRIES_MAX) { ++ mutex_unlock(&ab->ppe_vp_tbl_lock); ++ ath12k_err(ab, "Maximum ppe_vp count reached for soc\n"); ++ return -ENOSR; ++ } ++ ++ ab->num_ppe_vp_profiles++; ++ ++ for (i = 0; i < PPE_VP_ENTRIES_MAX; i++) { ++ if (!ab->dp.ppe_vp_profile[i].is_configured) ++ break; ++ } ++ ++ if (i == PPE_VP_ENTRIES_MAX) { ++ WARN_ONCE(1, "All ppe vp profile entries are in use!"); ++ return -ENOSR; ++ } ++ ++ ab->dp.ppe_vp_profile[i].is_configured = true; ++ *vp_profile = &ab->dp.ppe_vp_profile[i]; ++ mutex_unlock(&ab->ppe_vp_tbl_lock); ++ ++ return i; ++} ++ ++static void ++ath12k_dp_ppeds_dealloc_ppe_vp_profile(struct ath12k_base *ab, ++ int ppe_vp_profile_idx) ++{ ++ if (ppe_vp_profile_idx < 0 || ppe_vp_profile_idx >= PPE_VP_ENTRIES_MAX) { ++ ath12k_err(ab, "Invalid PPE VP profile free index"); ++ return; ++ } ++ ++ mutex_lock(&ab->ppe_vp_tbl_lock); ++ if (!ab->dp.ppe_vp_profile[ppe_vp_profile_idx].is_configured) { ++ mutex_unlock(&ab->ppe_vp_tbl_lock); ++ ath12k_err(ab, "PPE VP profile is not configured at idx:%d", ppe_vp_profile_idx); ++ return; ++ } ++ ++ ab->dp.ppe_vp_profile[ppe_vp_profile_idx].is_configured = false; ++ ab->num_ppe_vp_profiles--; ++ mutex_unlock(&ab->ppe_vp_tbl_lock); ++ ath12k_dbg(ab, ATH12K_DBG_PPE, "ath12k_dp_ppeds_dealloc_ppe_vp_profile success\n"); ++} ++ ++static int ath12k_dp_ppeds_alloc_vp_tbl_entry(struct ath12k_base *ab) ++{ ++ int i; ++ ++ mutex_lock(&ab->ppe_vp_tbl_lock); ++ if (ab->num_ppe_vp_profiles == PPE_VP_ENTRIES_MAX) { ++ mutex_unlock(&ab->ppe_vp_tbl_lock); ++ ath12k_err(ab, "Maximum ppe_vp count reached for soc\n"); ++ return -ENOSR; ++ } ++ ++ ab->num_ppe_vp_entries++; ++ ++ for (i = 0; i < PPE_VP_ENTRIES_MAX; i++) { ++ if (!ab->ppe_vp_tbl_registered[i]) ++ break; ++ } ++ ++ if (i == PPE_VP_ENTRIES_MAX) { ++ WARN_ONCE(1, "All ppe vp table entries are in use!"); ++ return -ENOSR; ++ } ++ ++ ab->ppe_vp_tbl_registered[i] = true; ++ mutex_unlock(&ab->ppe_vp_tbl_lock); ++ ++ return i; ++} ++ ++static void ath12k_dp_ppeds_dealloc_vp_tbl_entry(struct ath12k_base *ab, ++ int ppe_vp_num_idx) ++{ ++ u32 vp_cfg = 0; ++ ++ if (ppe_vp_num_idx < 0 || ppe_vp_num_idx >= PPE_VP_ENTRIES_MAX) { ++ ath12k_err(ab, "Invalid PPE VP free index"); ++ return; ++ } ++ ++ ath12k_hal_tx_set_ppe_vp_entry(ab, vp_cfg, ppe_vp_num_idx); ++ ++ mutex_lock(&ab->ppe_vp_tbl_lock); ++ if (!ab->ppe_vp_tbl_registered[ppe_vp_num_idx]) { ++ mutex_unlock(&ab->ppe_vp_tbl_lock); ++ ath12k_err(ab, "PPE VP is not configured at idx:%d", ppe_vp_num_idx); ++ return; ++ } ++ ++ ab->ppe_vp_tbl_registered[ppe_vp_num_idx] = false; ++ ab->num_ppe_vp_entries--; ++ mutex_unlock(&ab->ppe_vp_tbl_lock); ++} ++ ++static int ath12k_dp_ppeds_alloc_vp_search_idx_tbl_entry(struct ath12k_base *ab) ++{ ++ int i; ++ ++ mutex_lock(&ab->ppe_vp_tbl_lock); ++ if (ab->num_ppe_vp_profiles == PPE_VP_ENTRIES_MAX) { ++ mutex_unlock(&ab->ppe_vp_tbl_lock); ++ ath12k_err(ab, "Maximum ppe_vp count reached for soc\n"); ++ return -ENOSR; ++ } ++ ++ ab->num_ppe_vp_search_idx_entries++; ++ ++ for (i = 0; i < PPE_VP_ENTRIES_MAX; i++) { ++ if (!ab->ppe_vp_search_idx_tbl_set[i]) ++ break; ++ } ++ ++ if (i == PPE_VP_ENTRIES_MAX) { ++ WARN_ONCE(1, "All ppe vp table entries are in use!"); ++ return -ENOSR; ++ } ++ ++ ab->ppe_vp_search_idx_tbl_set[i] = true; ++ mutex_unlock(&ab->ppe_vp_tbl_lock); ++ ++ return i; ++} ++ ++static void ++ath12k_dp_ppeds_dealloc_vp_search_idx_tbl_entry(struct ath12k_base *ab, ++ int ppe_vp_search_idx) ++{ ++ if (ppe_vp_search_idx < 0 || ppe_vp_search_idx >= PPE_VP_ENTRIES_MAX) { ++ ath12k_err(ab,"Invalid PPE VP search table free index"); ++ return; ++ } ++ ++ ath12k_dbg(ab, ATH12K_DBG_PPE, "dealloc ppe_vp_search_idx %d\n", ppe_vp_search_idx); ++ ++ mutex_lock(&ab->ppe_vp_tbl_lock); ++ if (!ab->ppe_vp_search_idx_tbl_set[ppe_vp_search_idx]) { ++ mutex_unlock(&ab->ppe_vp_tbl_lock); ++ ath12k_err(ab,"PPE VP search idx table is not configured at idx:%d", ppe_vp_search_idx); ++ return; ++ } ++ ++ ab->ppe_vp_search_idx_tbl_set[ppe_vp_search_idx] = false; ++ ab->num_ppe_vp_search_idx_entries--; ++ mutex_unlock(&ab->ppe_vp_tbl_lock); ++ ++ return; ++} ++ ++static void ath12k_dp_ppeds_setup_vp_entry(struct ath12k_base *ab, ++ struct ath12k *ar, ++ struct ath12k_link_vif *arvif, ++ struct ath12k_dp_ppe_vp_profile *ppe_vp_profile) ++{ ++ u32 ppe_vp_config = 0; ++ ++ ppe_vp_config |= ++ u32_encode_bits(ppe_vp_profile->vp_num, ++ HAL_TX_PPE_VP_CFG_VP_NUM) | ++ u32_encode_bits(ppe_vp_profile->search_idx_reg_num, ++ HAL_TX_PPE_VP_CFG_SRCH_IDX_REG_NUM) | ++ u32_encode_bits(ppe_vp_profile->use_ppe_int_pri, ++ HAL_TX_PPE_VP_CFG_USE_PPE_INT_PRI) | ++ u32_encode_bits(ppe_vp_profile->to_fw, ++ HAL_TX_PPE_VP_CFG_TO_FW) | ++ u32_encode_bits(ppe_vp_profile->drop_prec_enable, ++ HAL_TX_PPE_VP_CFG_DROP_PREC_EN) | ++ u32_encode_bits(arvif->bank_id, HAL_TX_PPE_VP_CFG_BANK_ID) | ++ u32_encode_bits(ar->lmac_id, HAL_TX_PPE_VP_CFG_PMAC_ID) | ++ u32_encode_bits(arvif->vdev_id, HAL_TX_PPE_VP_CFG_VDEV_ID); ++ ++ ath12k_hal_tx_set_ppe_vp_entry(ab, ppe_vp_config, ++ ppe_vp_profile->ppe_vp_num_idx); ++ ++ ath12k_dbg(ab, ATH12K_DBG_PPE, ++ "ppeds_setup_vp_entry vp_num %d search_idx_reg_num %d" \ ++ " use_ppe_int_pri %d to_fw %d drop_prec_enable %d bank_id %d" \ ++ " lmac_id %d vdev_id %d ppe_vp_num_idx %d\n", ++ ppe_vp_profile->vp_num, ppe_vp_profile->search_idx_reg_num, ++ ppe_vp_profile->use_ppe_int_pri, ppe_vp_profile->to_fw, ++ ppe_vp_profile->drop_prec_enable, arvif->bank_id, ar->lmac_id, ++ arvif->vdev_id, ppe_vp_profile->ppe_vp_num_idx); ++ return; ++} ++ ++int ath12k_mac_op_ppeds_attach_vdev(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ void *vp_arg, int *ppe_vp_num, ++ struct ieee80211_ppe_vp_ds_params *vp_params) ++{ ++ struct ath12k_hw *ah = hw->priv; ++ struct ath12k_vif *ahvif = (void *)vif->drv_priv; ++ //TODO: handle MLO ++ struct ath12k_link_vif *arvif = &ahvif->link[0]; ++ struct ath12k *ar = ah->radio; ++ //TODO: Handle split phy ++ struct ath12k_base *ab = ar->ab; ++ struct ath12k_dp_ppe_vp_profile *vp_profile = NULL; ++ int ppe_vp_profile_idx, ppe_vp_idx, vp_num; ++ int ppe_vp_search_tbl_idx = -1; ++ int vdev_id = arvif->vdev_id; ++ int ret; ++ ++ if (!test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ab->dev_flags)) { ++ ppe_vp_num = -1; ++ return -ENOSR; ++ } ++ ++ if (!ab->ppeds_handle) { ++ ath12k_err(ab, "DS not enabled on this chip\n"); ++ return -EINVAL; ++ } ++ ++ if (vif->type != NL80211_IFTYPE_AP) { ++ return -EINVAL; ++ } ++ ++ vp_num = ppe_ds_wlan_vp_alloc(ab->ppeds_handle, vp_params->dev, vp_arg); ++ if (vp_num < 0) { ++ ath12k_err(ab," vp alloc failed\n"); ++ return -EFAULT; ++ } ++ ++ /*Allocate a ppe vp profile for a vap */ ++ ppe_vp_profile_idx = ath12k_dp_ppeds_alloc_ppe_vp_profile(ab, &vp_profile); ++ if (!vp_profile) { ++ ath12k_err(ab, "Failed to allocate PPE VP idx for vdev_id:%d", vdev_id); ++ ret = -ENOSR; ++ goto vp_free; ++ } ++ ++ ppe_vp_idx = ath12k_dp_ppeds_alloc_vp_tbl_entry(ab); ++ if (ppe_vp_idx < 0) { ++ ath12k_err(ab, "Failed to allocate PPE VP idx for vdev_id:%d", vdev_id); ++ ret = -ENOSR; ++ goto dealloc_vp_profile; ++ } ++ ++ if (vif->type == NL80211_IFTYPE_STATION) { ++ ppe_vp_search_tbl_idx = ath12k_dp_ppeds_alloc_vp_search_idx_tbl_entry(ab); ++ if (ppe_vp_search_tbl_idx < 0) { ++ ath12k_err(ab, ++ "Failed to allocate PPE VP search table idx for vdev_id:%d", vdev_id); ++ ret = -ENOSR; ++ goto dealloc_vp_tbl_entry; ++ } ++ vp_profile->search_idx_reg_num = ppe_vp_search_tbl_idx; ++ } ++ ++ vp_profile->vp_num = vp_num; ++ vp_profile->ppe_vp_num_idx = ppe_vp_idx; ++ vp_profile->to_fw = 0; ++ vp_profile->use_ppe_int_pri = 0; ++ vp_profile->drop_prec_enable = 0; ++ ++ /* For the sta mode fill up the index reg number */ ++ ath12k_dp_ppeds_setup_vp_entry(ab, ar, arvif, vp_profile); ++ ++ vp_params->ppe_vp_profile_idx = ppe_vp_profile_idx; ++ *ppe_vp_num = vp_num; ++ ath12k_dbg(ab, ATH12K_DBG_PPE, ++ "PPEDS vdev attach success vpnum %d ppe_vp_idx %d ppe_vp_profile_idx %d\n", ++ vp_num, ppe_vp_idx, ppe_vp_profile_idx); ++ ++ return 0; ++ ++dealloc_vp_tbl_entry: ++ ath12k_dp_ppeds_dealloc_vp_tbl_entry(ab, vp_profile->ppe_vp_num_idx); ++dealloc_vp_profile: ++ ath12k_dp_ppeds_dealloc_ppe_vp_profile(ab, ppe_vp_profile_idx); ++vp_free: ++ ppe_ds_wlan_vp_free(ab->ppeds_handle, vp_num); ++ ++ return ret; ++} ++ ++void ath12k_mac_op_ppeds_detach_vdev(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_ppe_vp_ds_params *vp_params) ++{ ++ struct ath12k_hw *ah = hw->priv; ++ struct ath12k *ar = ah->radio; ++ struct ath12k_base *ab = ar->ab; ++ struct ath12k_vif *ahvif = (void *)vif->drv_priv; ++ struct ath12k_link_vif *arvif = &ahvif->link[0]; ++ struct ath12k_dp_ppe_vp_profile *vp_profile; ++ int ppe_vp_profile_idx = -1; ++ ++ if (!test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ab->dev_flags)) ++ return; ++ ++ ath12k_dbg(ab, ATH12K_DBG_PPE, "PPEDS vdev detach\n"); ++ ppe_vp_profile_idx = vp_params->ppe_vp_profile_idx; ++ ++ vp_profile = &ab->dp.ppe_vp_profile[ppe_vp_profile_idx]; ++ if (!vp_profile->is_configured) { ++ ath12k_err(ab, "Invalid PPE VP profile for vdev_id:%d", ++ arvif->vdev_id); ++ return; ++ } ++ ++ ppe_ds_wlan_vp_free(ab->ppeds_handle, vp_profile->vp_num); ++ ath12k_dbg(ab, ATH12K_DBG_PPE, "ppe_ds_wlan_vp_free\n"); ++ ++ /* For STA mode ast index table reg also needs to be cleaned */ ++ if (vif->type == NL80211_IFTYPE_STATION) ++ ath12k_dp_ppeds_dealloc_vp_search_idx_tbl_entry(ab, vp_profile->search_idx_reg_num); ++ ++ ath12k_dp_ppeds_dealloc_vp_tbl_entry(ab, vp_profile->ppe_vp_num_idx); ++ ath12k_dp_ppeds_dealloc_ppe_vp_profile(ab, ppe_vp_profile_idx); ++ ath12k_dbg(ab, ATH12K_DBG_PPE, ++ "PPEDS vdev detach success vpnum %d ppe_vp_profile_idx %d\n", ++ vp_profile->vp_num, ppe_vp_profile_idx); ++} ++ ++int ath12k_ppeds_attach(struct ath12k_base *ab) ++{ ++ struct ath12k_base **abptr; ++ int i, ret; ++ ++ if (!test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ab->dev_flags)) ++ return 0; ++ ++ ath12k_dp_ppeds_tx_cmem_init(ab, &ab->dp); ++ ret = ath12k_dp_cc_ppeds_desc_init(ab); ++ if (ret) { ++ ath12k_err(ab, "Failed to allocate ppe-ds descriptors\n"); ++ return -ENOMEM; ++ } ++ ++ for (i = 0; i < PPE_VP_ENTRIES_MAX; i++) { ++ ab->ppe_vp_tbl_registered[i] = 0; ++ ab->ppe_vp_search_idx_tbl_set[i] = 0; ++ ab->dp.ppe_vp_profile[i].is_configured = false; ++ } ++ ++ ab->ppeds_handle = ppe_ds_wlan_inst_alloc(&ppeds_ops, sizeof(struct ath12k_base *)); ++ if (!ab->ppeds_handle) { ++ ath12k_err(ab, "Failed to allocate ppeds soc instance\n"); ++ ath12k_ppeds_detach(ab); ++ return -1; ++ } ++ ++ WARN_ON(ab->ppeds_node_idx != -1); ++ /* dec ppeds_node_idx to start from 0 */ ++ ab->ppeds_node_idx = atomic_inc_return(&num_ppeds_nodes) - 1; ++ ++ ath12k_dbg(ab, ATH12K_DBG_PPE, ++ "PPEDS attach ab %px ppeds_handle %px ppeds_node_idx %d num_ppeds_nodes %d\n", ++ ab, ab->ppeds_handle, ab->ppeds_node_idx, atomic_read(&num_ppeds_nodes)); ++ ++ ret = ath12k_dp_ppeds_add_napi_ctxt(ab); ++ if (ret) ++ return -ENOSR; ++ ++ abptr = (struct ath12k_base **)ppe_ds_wlan_priv(ab->ppeds_handle); ++ *abptr = ab; ++ ath12k_dbg(ab, ATH12K_DBG_PPE, "PPEDS attach success\n"); ++ ++ return 0; ++} ++ ++int ath12k_ppeds_detach(struct ath12k_base *ab) ++{ ++ int i; ++ ++ if (!test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ab->dev_flags)) ++ return 0; ++ ++ if (!ab->ppeds_handle) ++ return 0; ++ ++ ath12k_dp_ppeds_del_napi_ctxt(ab); ++ ath12k_dp_cc_ppeds_desc_cleanup(ab); ++ ++ /* free ppe-ds interrupts before freeing the instance */ ++ ath12k_hif_ppeds_free_interrupts(ab); ++ ppe_ds_wlan_inst_free(ab->ppeds_handle); ++ ab->ppeds_handle = NULL; ++ ab->ppeds_node_idx = -1; ++ atomic_dec(&num_ppeds_nodes); ++ ++ for (i = 0; i < PPE_VP_ENTRIES_MAX; i++) { ++ ab->ppe_vp_tbl_registered[i] = 0; ++ ab->ppe_vp_search_idx_tbl_set[i] = 0; ++ ab->dp.ppe_vp_profile[i].is_configured = false; ++ } ++ ++ ath12k_dbg(ab, ATH12K_DBG_PPE, "PPEDS detach success\n"); ++ ++ return 0; ++} ++ ++int ath12k_dp_ppeds_start(struct ath12k_base *ab) ++{ ++ struct ath12k_ppeds_napi *napi_ctxt = &ab->ppeds_napi_ctxt; ++ ++ if (!test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ab->dev_flags)) ++ return 0; ++ ++ if (!ab->ppeds_handle) { ++ ath12k_err(ab, "ppeds_handle is null"); ++ return -EINVAL; ++ } ++ ++ napi_enable(&napi_ctxt->napi); ++ ++ ab->ppeds_stopped = 0; ++ ++ if (ppe_ds_wlan_inst_start(ab->ppeds_handle) != 0) ++ return -EINVAL; ++ ++ ath12k_dbg(ab, ATH12K_DBG_PPE, "PPEDS start success\n"); ++ return 0; ++} ++ ++void ath12k_dp_ppeds_stop(struct ath12k_base *ab) ++{ ++ struct ath12k_ppeds_napi *napi_ctxt = &ab->ppeds_napi_ctxt; ++ ++ if (!test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ab->dev_flags)) ++ return; ++ ++ if (!ab->ppeds_handle || ab->ppeds_stopped) { ++ ath12k_warn(ab, "PPE DS aleady stopped!\n"); ++ return; ++ } ++ ++ ab->ppeds_stopped = 1; ++ napi_disable(&napi_ctxt->napi); ++ ++ ppe_ds_wlan_inst_stop(ab->ppeds_handle); ++ ath12k_dbg(ab, ATH12K_DBG_PPE, "PPEDS stop success\n"); ++ ++} ++ ++int ath12k_dp_ppeds_register_soc(struct ath12k_dp *dp) ++{ ++ struct ath12k_base *ab = dp->ab; ++ struct hal_srng *ppe2tcl_ring, *reo2ppe_ring; ++ struct ppe_ds_wlan_reg_info reg_info = {0}; ++ ++ if (!test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ab->dev_flags)) ++ return 0; ++ ++ if (!ab->ppeds_handle) { ++ ath12k_err(ab, "ppeds not attached"); ++ return -EINVAL; ++ } ++ ++ ppe2tcl_ring = &ab->hal.srng_list[dp->ppe2tcl_ring.ring_id]; ++ reo2ppe_ring = &ab->hal.srng_list[dp->reo2ppe_ring.ring_id]; ++ ++ reg_info.ppe2tcl_ba = dp->ppe2tcl_ring.paddr; ++ reg_info.reo2ppe_ba = dp->reo2ppe_ring.paddr; ++ reg_info.ppe2tcl_num_desc = ppe2tcl_ring->num_entries; ++ reg_info.reo2ppe_num_desc = reo2ppe_ring->num_entries; ++ if (ppe_ds_wlan_inst_register(ab->ppeds_handle, ®_info) != true) { ++ ath12k_err(ab, "ppeds not attached"); ++ return -EINVAL; ++ } ++ ++ ab->ppeds_int_mode_enabled = reg_info.ppe_ds_int_mode_enabled; ++ ++ ath12k_dbg(ab, ATH12K_DBG_PPE, "PPEDS register soc-success"); ++ ++ return 0; ++} ++ ++int ath12k_dp_srng_ppeds_setup(struct ath12k_base *ab) ++{ ++ struct ath12k_dp *dp = &ab->dp; ++ int ret, size; ++ ++ if (!test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ab->dev_flags)) ++ return 0; ++ ++ /* TODO: retain and use ring idx fetched from ppe for avoiding edma hang during SSR */ ++ ret = ath12k_dp_srng_setup(ab, &dp->reo2ppe_ring, HAL_REO2PPE, ++ 0, 0, DP_REO2PPE_RING_SIZE); ++ if (ret) { ++ ath12k_warn(ab, "failed to set up reo2ppe ring :%d\n", ret); ++ goto err; ++ } ++ ++ ath12k_hal_reo_config_reo2ppe_dest_info(ab); ++ ++ /* TODO: retain and use ring idx fetched from ppe for avoiding edma hang during SSR */ ++ ret = ath12k_dp_srng_setup(ab, &dp->ppe2tcl_ring, HAL_PPE2TCL, ++ 0, 0, DP_PPE2TCL_RING_SIZE); ++ if (ret) { ++ ath12k_warn(ab, "failed to set up ppe2tcl ring :%d\n", ret); ++ goto err; ++ } ++ ++ /* TODO: retain and use ring idx fetched from ppe for avoiding edma hang during SSR */ ++ ret = ath12k_dp_srng_setup(ab, &dp->ppeds_comp_ring.ppe_wbm2sw_ring, ++ HAL_WBM2SW_RELEASE, ++ HAL_WBM2SW_PPEDS_TX_CMPLN_RING_NUM, 0, ++ DP_PPE_WBM2SW_RING_SIZE); ++ if (ret) { ++ ath12k_warn(ab, ++ "failed to set up wbm2sw ippeds tx completion ring :%d\n", ++ ret); ++ goto err; ++ } ++ ath12k_hal_tx_config_rbm_mapping(ab, 0, ++ HAL_WBM2SW_PPEDS_TX_CMPLN_MAP_ID, ++ HAL_PPE2TCL); ++ ++ size = sizeof(struct hal_wbm_release_ring_tx) * DP_TX_COMP_RING_SIZE; ++ dp->ppeds_comp_ring.tx_status_head = 0; ++ dp->ppeds_comp_ring.tx_status_tail = DP_TX_COMP_RING_SIZE - 1; ++ dp->ppeds_comp_ring.tx_status = kmalloc(size, GFP_KERNEL); ++ if (!dp->ppeds_comp_ring.tx_status) { ++ ath12k_err(ab, "PPE tx status completion buffer alloc failed\n"); ++ goto err; ++ } ++ ++ ret = ath12k_dp_ppeds_register_soc(dp); ++ if (ret) { ++ ath12k_err(ab, "ppeds registration failed\n"); ++ goto err; ++ } ++ ++err: ++ /* caller takes care of calling ath12k_dp_srng_ppeds_cleanup */ ++ return ret; ++} ++ ++void ath12k_dp_srng_ppeds_cleanup(struct ath12k_base *ab) ++{ ++ struct ath12k_dp *dp = &ab->dp; ++ ++ if (!test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ab->dev_flags)) ++ return; ++ ++ ath12k_dp_srng_cleanup(ab, &dp->ppe2tcl_ring); ++ ath12k_dp_srng_cleanup(ab, &dp->reo2ppe_ring); ++ ath12k_dp_srng_cleanup(ab, &dp->ppeds_comp_ring.ppe_wbm2sw_ring); ++} +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/ppe.h +@@ -0,0 +1,43 @@ ++/* SPDX-License-Identifier: BSD-3-Clause-Clear */ ++/* ++ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef ATH12K_PPE_H ++#define ATH12K_PPE_H ++ ++struct ath12k_dp_ppe_vp_profile { ++ bool is_configured; ++ u8 vp_num; ++ u8 ppe_vp_num_idx; ++ u8 search_idx_reg_num; ++ u8 drop_prec_enable; ++ u8 to_fw; ++ u8 use_ppe_int_pri; ++}; ++ ++#define ATH12K_PPEDS_DEFAULT_POOL_ID 0 ++ ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++void ath12k_dp_srng_ppeds_cleanup(struct ath12k_base *ab); ++int ath12k_dp_srng_ppeds_setup(struct ath12k_base *ab); ++int ath12k_dp_ppeds_register_soc(struct ath12k_dp *dp); ++void ath12k_dp_ppeds_stop(struct ath12k_base *ab); ++int ath12k_dp_ppeds_start(struct ath12k_base *ab); ++int ath12k_ppeds_detach( struct ath12k_base *ab); ++int ath12k_ppeds_attach( struct ath12k_base *ab); ++int ath12k_mac_op_ppeds_attach_vdev(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ void *vp_arg, int *ppe_vp_num, ++ struct ieee80211_ppe_vp_ds_params *vp_params); ++void ath12k_mac_op_ppeds_detach_vdev(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_ppe_vp_ds_params *vp_params); ++void ath12k_dp_peer_ppeds_route_setup(struct ath12k *ar, struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta); ++void *ath12k_dp_get_ppe_ds_ctxt(struct ath12k_base *ab); ++irqreturn_t ath12k_ds_ppe2tcl_irq_handler(int irq, void *ctxt); ++irqreturn_t ath12k_ds_reo2ppe_irq_handler(int irq, void *ctxt); ++irqreturn_t ath12k_dp_ppeds_handle_tx_comp(int irq, void *ctxt); ++#endif ++#endif +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -1414,6 +1414,88 @@ int ath12k_wmi_send_peer_delete_cmd(stru + return ret; + } + ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++int ath12k_wmi_config_peer_ppeds_routing(struct ath12k *ar, ++ const u8 *peer_addr, u8 vdev_id, ++ u32 service_code, u32 priority_valid, ++ u32 src_info, bool ppe_routing_enable) ++{ ++ struct ath12k_pdev_wmi *wmi = ar->wmi; ++ struct sk_buff *skb; ++ struct wmi_peer_config_ppeds_cmd *cmd; ++ int ret; ++ ++ skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd)); ++ if (!skb) ++ return -ENOMEM; ++ ++ cmd =(struct wmi_peer_config_ppeds_cmd *)skb->data; ++ cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PEER_CONFIG_PPEDS_ROUTING, ++ sizeof(*cmd)); ++ ++ ether_addr_copy(cmd->peer_macaddr.addr, peer_addr); ++ cmd->vdev_id = cpu_to_le32(vdev_id); ++ cmd->ppe_routing_enable = cpu_to_le32(ppe_routing_enable); ++ cmd->service_code = cpu_to_le32(service_code); ++ cmd->priority_valid = cpu_to_le32(priority_valid); ++ cmd->src_info = cpu_to_le32(src_info); ++ ++ ret = ath12k_wmi_cmd_send(wmi, skb, WMI_PEER_CONFIG_PPE_DS_CMDID); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to send WMI_PEER_CONFIG_PPE_DS cmd" ++ " peer_addr %pM num_peer : %d\n", ++ peer_addr, ar->num_peers); ++ dev_kfree_skb(skb); ++ } ++ ath12k_dbg(ar->ab, ATH12K_DBG_PPE, ++ "ppe ds routing cmd peer_addr %pM vdev_id %d service_code %d " \ ++ "priority_valid %d src_info %d ppe_routing_enable %d \n", ++ peer_addr, vdev_id, service_code, priority_valid, ++ src_info, ppe_routing_enable); ++ ++ return ret; ++} ++#endif ++ ++int ath12k_wmi_send_pdev_pkt_route(struct ath12k *ar, ++ struct ath12k_wmi_pkt_route_param *param) ++{ ++ struct ath12k_pdev_wmi *wmi = ar->wmi; ++ struct wmi_pdev_pkt_route_cmd *cmd; ++ struct sk_buff *skb; ++ int ret; ++ ++ skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd)); ++ if (!skb) ++ return -ENOMEM; ++ ++ cmd = (struct wmi_pdev_pkt_route_cmd *)skb->data; ++ cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, ++ WMI_TAG_PDEV_UPDATE_PKT_ROUTING_CMD) | ++ FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); ++ ++ cmd->pdev_id = ar->pdev->pdev_id; ++ cmd->opcode = param->opcode; ++ cmd->route_type_bmap = param->route_type_bmap; ++ cmd->dst_ring = param->dst_ring; ++ cmd->meta_data = param->meta_data; ++ cmd->dst_ring_handler = param->dst_ring_handler; ++ ++ ath12k_dbg(ar->ab, ATH12K_DBG_WMI, ++ "CCE PPE WMI pdev pkt route opcode %d route_bmap %d dst_ring %d meta_data %d" \ ++ "dst_ring_handler %d\n", param->opcode, param->route_type_bmap, ++ param->dst_ring, param->meta_data, param->dst_ring_handler); ++ ++ ret = ath12k_wmi_cmd_send(wmi, skb, WMI_PDEV_UPDATE_PKT_ROUTING_CMDID); ++ if (ret) { ++ ath12k_warn(ar->ab, ++ "failed to send WMI_PDEV_UPDATE_PKT_ROUTING cmd\n"); ++ dev_kfree_skb(skb); ++ } ++ ++ return ret; ++} ++ + int ath12k_wmi_send_pdev_set_regdomain(struct ath12k *ar, + struct pdev_set_regdomain_params *param) + { +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -417,6 +417,15 @@ enum wmi_tlv_cmd_id { + WMI_PEER_REORDER_QUEUE_REMOVE_CMDID, + WMI_PEER_SET_RX_BLOCKSIZE_CMDID, + WMI_PEER_ANTDIV_INFO_REQ_CMDID, ++ WMI_PEER_RESERVED0_CMDID, ++ WMI_PEER_TID_MSDUQ_QDEPTH_THRESH_UPDATE_CMDID, ++ WMI_PEER_TID_CONFIGURATIONS_CMDID, ++ WMI_PEER_CFR_CAPTURE_CMDID, ++ WMI_PEER_CHAN_WIDTH_SWITCH_CMDID, ++ WMI_PEER_TX_PN_REQUEST_CMDID, ++ WMI_PEER_UNMAP_RESPONSE_CMDID, ++ WMI_PEER_CONFIG_VLAN_CMDID, ++ WMI_PEER_CONFIG_PPE_DS_CMDID, + WMI_BCN_TX_CMDID = WMI_TLV_CMD(WMI_GRP_MGMT), + WMI_PDEV_SEND_BCN_CMDID, + WMI_BCN_TMPL_CMDID, +@@ -2046,6 +2055,7 @@ enum wmi_tlv_tag { + WMI_TAG_TPC_STATS_RATES_ARRAY, + WMI_TAG_TPC_STATS_CTL_PWR_TABLE_EVENT, + WMI_TAG_BCN_TMPL_ML_PARAMS_CMD = 0x3E6, ++ WMI_TAG_PEER_CONFIG_PPEDS_ROUTING = 0x3EA, + WMI_TAG_SAWF_SERVICE_CLASS_CFG_CMD_FIXED_PARAM = 0x40A, + WMI_TAG_SAWF_SERVICE_CLASS_DISABLE_CMD_FIXED_PARAM = 0x40B, + WMI_TAG_BCN_TMPL_ML_INFO_CMD = 0x436, +@@ -3145,6 +3155,25 @@ struct channel_param { + u8 reg_class_id; + } __packed; + ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++struct wmi_peer_config_ppeds_cmd { ++ __le32 tlv_header; ++ struct wmi_mac_addr peer_macaddr; ++ __le32 ppe_routing_enable; ++ __le32 service_code; ++ __le32 priority_valid; ++ __le32 src_info; ++ __le32 vdev_id; ++}; ++ ++enum wmi_ppeds_routing_type { ++ WMI_PPE_ROUTING_DISABLED = 0, ++ WMI_AST_USE_PPE_ENABLED = 1, ++ WMI_AST_USE_PPE_DISABLED = 2, ++ WMI_PPE_ROUTING_TYPE_MAX, ++}; ++#endif ++ + enum wmi_phy_mode { + MODE_11A = 0, + MODE_11G = 1, /* 11b/g Mode */ +@@ -3354,6 +3383,27 @@ struct pdev_set_regdomain_params { + u32 pdev_id; + }; + ++/* Defines various options for routing policy */ ++enum wmi_pdev_dest_ring_handler_type { ++ ATH12K_WMI_PKTROUTE_USE_CCE = 0, ++ ATH12K_WMI_PKTROUTE_USE_ASPT = 1, ++ ATH12K_WMI_PKTROUTE_USE_FSE = 2, ++ ATH12K_WMI_PKTROUTE_USE_CCE2 = 3, ++}; ++ ++enum ath12k_wmi_pkt_route_opcode { ++ ATH12K_WMI_PKTROUTE_ADD, ++ ATH12K_WMI_PKTROUTE_DEL, ++}; ++ ++struct ath12k_wmi_pkt_route_param { ++ enum ath12k_wmi_pkt_route_opcode opcode; ++ u32 route_type_bmap; ++ u32 dst_ring_handler; ++ u32 dst_ring; ++ u32 meta_data; ++}; ++ + struct rx_reorder_queue_remove_params { + u8 *peer_macaddr; + u16 vdev_id; +@@ -3603,6 +3653,16 @@ struct wmi_pdev_set_regdomain_cmd { + __le32 dfs_domain; + } __packed; + ++struct wmi_pdev_pkt_route_cmd { ++ u32 tlv_header; ++ u32 pdev_id; ++ u32 opcode; ++ u32 route_type_bmap; ++ u32 dst_ring; ++ u32 meta_data; ++ u32 dst_ring_handler; ++} __packed; ++ + struct wmi_peer_set_param_cmd { + __le32 tlv_header; + __le32 vdev_id; +@@ -8247,6 +8307,8 @@ int ath12k_wmi_peer_rx_reorder_queue_set + int + ath12k_wmi_rx_reord_queue_remove(struct ath12k *ar, + struct rx_reorder_queue_remove_params *param); ++int ath12k_wmi_send_pdev_pkt_route(struct ath12k *ar, ++ struct ath12k_wmi_pkt_route_param *param); + int ath12k_wmi_send_pdev_set_regdomain(struct ath12k *ar, + struct pdev_set_regdomain_params *param); + int ath12k_wmi_pull_fw_stats(struct ath12k_base *ab, struct sk_buff *skb, +@@ -8337,4 +8399,10 @@ int + ath12k_mgmt_rx_reo_init_context(struct ath12k_base *ab); + int + ath12k_mgmt_rx_reo_deinit_context(struct ath12k_base *ab); ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++int ath12k_wmi_config_peer_ppeds_routing(struct ath12k *ar, ++ const u8 *peer_addr, u8 vdev_id, ++ u32 service_code, u32 priority_valid, ++ u32 src_info, bool ppe_routing_enable); ++#endif + #endif +--- a/local-symbols ++++ b/local-symbols +@@ -143,3 +143,4 @@ ATH12K_DEBUGFS= + ATH12K_TRACING= + ATH12K_SPECTRAL= + ATH12K_PKTLOG= ++ATH12K_PPE_DS_SUPPORT= +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -766,7 +766,9 @@ void ieee80211_stop_mbssid(struct ieee80 + static int ieee80211_stop(struct net_device *dev) + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++#ifdef CPTCFG_MAC80211_PPE_SUPPORT + struct ieee80211_ppe_vp_ds_params vp_params = {0}; ++#endif + + /* close dependent VLAN interfaces before locking wiphy */ + if (sdata->vif.type == NL80211_IFTYPE_AP) { +@@ -1946,7 +1948,9 @@ static void ieee80211_setup_sdata(struct + /* and set some type-dependent values */ + sdata->vif.type = type; + sdata->vif.p2p = false; ++#ifdef CPTCFG_MAC80211_PPE_SUPPORT + sdata->vif.ppe_vp_num = -1; ++#endif + sdata->wdev.iftype = type; + + sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE); diff --git a/feeds/ipq95xx/mac80211/patches/qca/764-ath12k-Add-support-to-identify-dual-mac.patch b/feeds/ipq95xx/mac80211/patches/qca/764-ath12k-Add-support-to-identify-dual-mac.patch new file mode 100644 index 000000000..b4c9d0172 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/764-ath12k-Add-support-to-identify-dual-mac.patch @@ -0,0 +1,61 @@ +From 222b80dbb7ece7bd298e06f612156592f60a8efe Mon Sep 17 00:00:00 2001 +From: Rajat Soni +Date: Fri, 14 Apr 2023 15:02:11 +0530 +Subject: [PATCH] ath12k: Add support to identify dual mac + +While debugging using cnss diag for dual mac device, we are using Data.msc +file to get the logs. Instead we should be using Data_dual.msc file for dual +mac devices to get the logs. + +Add a check if the device is dual mac and send it through nl command to be +sure that correct .msc file is used. + +Signed-off-by: Rajat Soni +--- + drivers/net/wireless/ath/ath12k/testmode.c | 10 ++++++++++ + drivers/net/wireless/ath/ath12k/testmode_i.h | 1 + + 2 files changed, 11 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/testmode.c b/drivers/net/wireless/ath/ath12k/testmode.c +index 2e16255..96e8d19 100644 +--- a/drivers/net/wireless/ath/ath12k/testmode.c ++++ b/drivers/net/wireless/ath/ath12k/testmode.c +@@ -26,6 +26,7 @@ static const struct nla_policy ath12k_tm_policy[ATH12K_TM_ATTR_MAX + 1] = { + [ATH12K_TM_ATTR_FWLOG] = { .type = NLA_BINARY, + .len = 2048 }, + [ATH12K_TM_ATTR_LINK_IDX] = { .type = NLA_U8 }, ++ [ATH12K_TM_ATTR_DUAL_MAC] = { .type = NLA_U8 }, + }; + + void ath12k_fwlog_write(struct ath12k_base *ab, u8 *data, int len) +@@ -66,6 +67,15 @@ void ath12k_fwlog_write(struct ath12k_base *ab, u8 *data, int len) + } + } + ++ if (ab->num_radios == 2) ++ ret = nla_put_u8(nl_skb, ATH12K_TM_ATTR_DUAL_MAC, ab->num_radios); ++ ++ if (ret) { ++ ath12k_warn(ab, "failed to put dual mac wmi event to nl: %d\n", ret); ++ kfree_skb(nl_skb); ++ return; ++ } ++ + cfg80211_testmode_event(nl_skb, GFP_ATOMIC); + } + +diff --git a/drivers/net/wireless/ath/ath12k/testmode_i.h b/drivers/net/wireless/ath/ath12k/testmode_i.h +index 3c6f8d0..0064770 100644 +--- a/drivers/net/wireless/ath/ath12k/testmode_i.h ++++ b/drivers/net/wireless/ath/ath12k/testmode_i.h +@@ -27,6 +27,7 @@ enum ath12k_tm_attr { + ATH12K_TM_ATTR_WMI_OP_VERSION = 6, + ATH12K_TM_ATTR_FWLOG = 7, + ATH12K_TM_ATTR_LINK_IDX = 8, ++ ATH12K_TM_ATTR_DUAL_MAC = 9, + + /* keep last */ + __ATH12K_TM_ATTR_AFTER_LAST, +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/764-ath12k-Add-the-cold-boot-calibration-support.patch b/feeds/ipq95xx/mac80211/patches/qca/764-ath12k-Add-the-cold-boot-calibration-support.patch new file mode 100644 index 000000000..6a8842487 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/764-ath12k-Add-the-cold-boot-calibration-support.patch @@ -0,0 +1,89 @@ +From aeda9eed1f7800a01651e76b5521abcb4878c599 Mon Sep 17 00:00:00 2001 +From: Sivashankari Madhavan +Date: Thu, 16 Mar 2023 15:34:39 +0530 +Subject: [PATCH] ath12k: Add the cold boot calibration support + +While enabling the cold boot calibration faced a firmware crash issue. +From the triage, the caldb mem chunk address differed from QCN9274 and +IPQ5332. Due to this, in bootup system referring to the invalid memory +address. + +Now adds the changes to support the cold boot calibration and caldb +memory parsing for AHB. + +Signed-off-by: Sivashankari Madhavan +--- + drivers/net/wireless/ath/ath12k/hw.c | 2 +- + drivers/net/wireless/ath/ath12k/qmi.c | 40 +++++++++++++++++++++++---- + 2 files changed, 35 insertions(+), 7 deletions(-) + +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/hw.c +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/hw.c ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/hw.c +@@ -1674,7 +1674,7 @@ static const struct ath12k_hw_params ath + .supports_monitor = true, + + .idle_ps = false, +- .cold_boot_calib = false, ++ .cold_boot_calib = true, + .download_calib = true, + .supports_suspend = false, + .tcl_ring_retry = true, +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/qmi.c +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/qmi.c ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/qmi.c +@@ -3977,7 +3977,9 @@ static int ath12k_qmi_assign_target_mem_ + struct resource res; + int host_ddr_sz, mlo_ddr_sz, sz, mlo_sz = 0; + int i, idx, mlo_idx, ret; +- unsigned int bdf_location[MAX_TGT_MEM_MODES]; ++ unsigned int bdf_location[MAX_TGT_MEM_MODES], ++ caldb_location[MAX_TGT_MEM_MODES], ++ caldb_size[1]; + + sz = ab->host_ddr_fixed_mem_off; + hremote_node = of_parse_phandle(dev->of_node, "memory-region", 0); +@@ -4057,11 +4059,36 @@ skip_mlo_mem_init: + break; + case CALDB_MEM_REGION_TYPE: + if (ath12k_cold_boot_cal && +- ab->hw_params->cold_boot_calib) { +- ab->qmi.target_mem[idx].v.ioaddr = +- ioremap(ab->qmi.target_mem[idx].paddr, +- ab->qmi.target_mem[i].size); +- sz += ab->qmi.target_mem[i].size; ++ ab->hw_params->cold_boot_calib) { ++ if (ab->hif.bus == ATH12K_BUS_AHB) { ++ if (of_property_read_u32_array(dev->of_node, ++ "qcom,caldb-addr", caldb_location, ++ ARRAY_SIZE(caldb_location))) { ++ ath12k_err(ab, "CALDB_MEM_REGION Not defined in device_tree\n"); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ if (of_property_read_u32_array(dev->of_node, ++ "qcom,caldb-size", caldb_size, ++ ARRAY_SIZE(caldb_size))) { ++ ath12k_err(ab, "CALDB_SIZE Not defined in device_tree\n"); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ ab->qmi.target_mem[idx].paddr = caldb_location[0]; ++ ab->qmi.target_mem[i].size = caldb_size[0]; ++ ++ ab->qmi.target_mem[idx].v.ioaddr = ++ ioremap(ab->qmi.target_mem[idx].paddr, ++ ab->qmi.target_mem[i].size); ++ } else { ++ ab->qmi.target_mem[idx].v.ioaddr = ++ ioremap(ab->qmi.target_mem[idx].paddr, ++ ab->qmi.target_mem[i].size); ++ sz += ab->qmi.target_mem[i].size; ++ } + } else { + ab->qmi.target_mem[idx].paddr = 0; + ab->qmi.target_mem[idx].v.ioaddr = NULL; diff --git a/feeds/ipq95xx/mac80211/patches/qca/764-ath12k-Fix-the-wrong-regdomain-update-for-KR-country.patch b/feeds/ipq95xx/mac80211/patches/qca/764-ath12k-Fix-the-wrong-regdomain-update-for-KR-country.patch new file mode 100644 index 000000000..db2e513d1 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/764-ath12k-Fix-the-wrong-regdomain-update-for-KR-country.patch @@ -0,0 +1,36 @@ +From 892af6e817ee349f502bb6d451c4ffffcf7febd9 Mon Sep 17 00:00:00 2001 +From: Karthik M +Date: Mon, 17 Apr 2023 15:48:31 +0530 +Subject: [PATCH] ath12k: Fix the wrong regdomain update for KR country + +KR country should follow JP regulatory domain instead it +was assigned ETSI domain wrongly. + +This issue got exposed after the change +5dbddc3d4ac ("cfg80211: precac check for self-managed wiphy") +got merged. + +Signed-off-by: Karthik M +--- + drivers/net/wireless/ath/ath12k/reg.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath12k/reg.c b/drivers/net/wireless/ath/ath12k/reg.c +index 4332c27..b210281 100644 +--- a/drivers/net/wireless/ath/ath12k/reg.c ++++ b/drivers/net/wireless/ath/ath12k/reg.c +@@ -456,10 +456,10 @@ ath12k_map_fw_dfs_region(enum ath12k_dfs_region dfs_region) + case ATH12K_DFS_REG_CN: + return NL80211_DFS_FCC; + case ATH12K_DFS_REG_ETSI: +- case ATH12K_DFS_REG_KR: + return NL80211_DFS_ETSI; + case ATH12K_DFS_REG_MKK: + case ATH12K_DFS_REG_MKK_N: ++ case ATH12K_DFS_REG_KR: + return NL80211_DFS_JP; + default: + return NL80211_DFS_UNSET; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/765-ath12k-Add-full-dump-support-for-IPQ5322.patch b/feeds/ipq95xx/mac80211/patches/qca/765-ath12k-Add-full-dump-support-for-IPQ5322.patch new file mode 100644 index 000000000..bc4031195 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/765-ath12k-Add-full-dump-support-for-IPQ5322.patch @@ -0,0 +1,399 @@ +From e294e31ab8bbd4e12f561d6304fe55164689357f Mon Sep 17 00:00:00 2001 +From: Dinesh Karthikeyan +Date: Wed, 31 May 2023 09:58:45 -0700 +Subject: [PATCH] ath12k: Add full dump support for IPQ5322 + +Handle the full dump collection support for IPQ5322 in MLO +capable condition. + +Signed-off-by: Dinesh Karthikeyan +Signed-off-by: Sidhanta Sahu +--- + drivers/net/wireless/ath/ath12k/ahb.c | 20 +- + drivers/net/wireless/ath/ath12k/ahb.h | 2 +- + drivers/net/wireless/ath/ath12k/core.c | 206 ++++++++++++++++----- + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/coredump.c | 11 +- + 5 files changed, 181 insertions(+), 59 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/ahb.c b/drivers/net/wireless/ath/ath12k/ahb.c +index be32336..6aff66d 100644 +--- a/drivers/net/wireless/ath/ath12k/ahb.c ++++ b/drivers/net/wireless/ath/ath12k/ahb.c +@@ -629,7 +629,7 @@ static int ath12k_ahb_ssr_notifier_reg(struct ath12k_base *ab) + { + struct ath12k_ahb *ab_ahb = ath12k_ahb_priv(ab); + +- return ath12k_rproc_register_subsys_notifier(ab_ahb->tgt_rproc->name, ++ return ath12k_rproc_register_subsys_notifier(ab_ahb->tgt_rrproc->name, + &ab->ssr_nb, + &ab->atomic_ssr_nb); + } +@@ -638,7 +638,7 @@ static int ath12k_ahb_ssr_notifier_unreg(struct ath12k_base *ab) + { + struct ath12k_ahb *ab_ahb = ath12k_ahb_priv(ab); + +- return ath12k_rproc_unregister_subsys_notifier(ab_ahb->tgt_rproc->name, ++ return ath12k_rproc_unregister_subsys_notifier(ab_ahb->tgt_rrproc->name, + &ab->ssr_nb, + &ab->atomic_ssr_nb); + } +@@ -664,8 +664,8 @@ static int ath12k_core_get_rproc(struct ath12k_base *ab) + { + struct ath12k_ahb *ab_ahb = ath12k_ahb_priv(ab); + struct device *dev = ab->dev; +- struct rproc *prproc; +- phandle rproc_phandle; ++ struct rproc *prproc, *rrproc; ++ phandle rproc_phandle, rproc_rpd_node; + + if (of_property_read_u32(dev->of_node, "qcom,rproc", &rproc_phandle)) { + ath12k_err(ab, "failed to get q6_rproc handle\n"); +@@ -679,6 +679,18 @@ static int ath12k_core_get_rproc(struct ath12k_base *ab) + } + ab_ahb->tgt_rproc = prproc; + ++ if (of_property_read_u32(dev->of_node, "qcom,rproc_rpd", &rproc_rpd_node)) { ++ ath12k_err(ab, "failed to get q6_root_pd_rproc handle\n"); ++ return -ENOENT; ++ } ++ ++ rrproc = rproc_get_by_phandle(rproc_rpd_node); ++ if (!rrproc) { ++ ath12k_err(ab, "failed to get root pd rproc\n"); ++ return -EINVAL; ++ } ++ ab_ahb->tgt_rrproc = rrproc; ++ + return 0; + } + +diff --git a/drivers/net/wireless/ath/ath12k/ahb.h b/drivers/net/wireless/ath/ath12k/ahb.h +index 5efe1c4..f682434 100644 +--- a/drivers/net/wireless/ath/ath12k/ahb.h ++++ b/drivers/net/wireless/ath/ath12k/ahb.h +@@ -26,7 +26,7 @@ enum ath12k_ahb_smp2p_msg_id { + struct ath12k_base; + + struct ath12k_ahb { +- struct rproc *tgt_rproc; ++ struct rproc *tgt_rproc, *tgt_rrproc; + struct { + struct device *dev; + struct iommu_domain *iommu_domain; +diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c +index d03de4e..beacee0 100644 +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -20,6 +20,7 @@ + #include "wow.h" + #include "sawf.h" + #include "ppe.h" ++#include "ahb.h" + + unsigned int ath12k_debug_mask; + module_param_named(debug_mask, ath12k_debug_mask, uint, 0644); +@@ -60,6 +61,8 @@ MODULE_PARM_DESC(mgmt_rx_reorder, "Mgmt Rx Re-Ordering (0 - disable, 1 - enable) + static DEFINE_MUTEX(ath12k_hw_lock); + static struct list_head ath12k_hw_groups = LIST_HEAD_INIT(ath12k_hw_groups); + ++extern struct ath12k_coredump_info ath12k_coredump_ram_info; ++ + /* This function needs to be used only when dt has multi chip grouping information */ + static struct ath12k_hw_group *ath12k_core_hw_group_find_by_id(u8 group_id) + { +@@ -1613,6 +1616,43 @@ void ath12k_core_wait_dump_collect(struct ath12k_base *ab) + } + EXPORT_SYMBOL(ath12k_core_wait_dump_collect); + ++void ath12k_core_issue_bug_on(struct ath12k_base *ab) ++{ ++ struct ath12k_hw_group *ag = ab->ag; ++ ++ if ((ag->mlo_capable && ++ (atomic_read(&ath12k_coredump_ram_info.num_chip) >= ab->ag->num_started)) || ++ (!ag->mlo_capable)) ++ BUG_ON(1); ++ else ++ ath12k_info(ab, ++ "%d chip dump collected and waiting for partner chips\n", ++ atomic_read(&ath12k_coredump_ram_info.num_chip)); ++} ++ ++static void ath12k_coredump_download_ahb(struct ath12k_base *ab) ++{ ++ struct ath12k_hw_group *ag = ab->ag; ++ int dump_count; ++ ++ /* Crash the system once all the stats are dumped */ ++ if (ab->fw_recovery_support) ++ return; ++ ++ if (ag->mlo_capable ) { ++ dump_count = atomic_read(&ath12k_coredump_ram_info.num_chip); ++ if (dump_count >= ATH12K_MAX_SOCS) { ++ ath12k_err(ab, "invalid chip number %d\n", ++ dump_count); ++ return; ++ } ++ } ++ ++ atomic_inc(&ath12k_coredump_ram_info.num_chip); ++ ++ ath12k_core_issue_bug_on(ab); ++} ++ + /* Print the driver stats and crash the system on receiving this notification */ + static int ath12k_core_ssr_notifier_cb(struct notifier_block *nb, + const unsigned long event, +@@ -1636,11 +1676,12 @@ static int ath12k_core_atomic_ssr_notifier_cb(struct notifier_block *nb, + { + struct ath12k_base *ab = container_of(nb, struct ath12k_base, atomic_ssr_nb); + struct device *dev = ab->dev; +- bool multi_pd_arch = false; +- phandle rproc_phandle; +- struct device_node *rproc_node = NULL; ++ phandle rrproc_phandle; + struct platform_device *pdev = NULL; ++ struct device_node *rrproc_node = NULL; + struct platform_device *ssr_pdev = (struct platform_device *)data; ++ struct ath12k_ahb *ab_ahb = ath12k_ahb_priv(ab); ++ + + if (event != SUBSYS_PREPARE_FOR_FATAL_SHUTDOWN) + return NOTIFY_DONE; +@@ -1650,34 +1691,30 @@ static int ath12k_core_atomic_ssr_notifier_cb(struct notifier_block *nb, + if (!test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags)) + return NOTIFY_DONE; + +- /* Print the stats and do recover only if notification is received +- * for expected PD. Currently, there's only one PD for which below code +- * may not necessary. It's just added as a sanity check incase +- * core-BSP code base is modified and impacted this function. +- * However, below code will needed review when there will be +- * multi pd architecture. +- */ +- multi_pd_arch = of_property_read_bool(dev->of_node, "qcom,multipd_arch"); +- if (multi_pd_arch) { +- if (of_property_read_u32(dev->of_node, "qcom,rproc", +- &rproc_phandle)) +- return NOTIFY_DONE; +- rproc_node = of_find_node_by_phandle(rproc_phandle); +- if (!rproc_node) { +- ath12k_warn(ab, "ssr notification failed to get rproc_node\n"); +- return NOTIFY_DONE; +- } +- pdev = of_find_device_by_node(rproc_node); +- if (!pdev) { +- ath12k_warn(ab, "Failed to get pdev from device node\n"); +- return NOTIFY_DONE; +- } +- if (strcmp(ssr_pdev->name, pdev->name) != 0) { +- ath12k_warn(ab, "SSR notification mismatch %s pdev name:%s\n", +- (char *)data, pdev->name); +- return NOTIFY_DONE; +- } ++ if (of_property_read_u32(dev->of_node, "qcom,rproc_rpd", ++ &rrproc_phandle)) ++ return NOTIFY_DONE; ++ rrproc_node = of_find_node_by_phandle(rrproc_phandle); ++ if (!rrproc_node) { ++ ath12k_warn(ab, "ssr notification failed to get rproc_node\n"); ++ return NOTIFY_DONE; + } ++ pdev = of_find_device_by_node(rrproc_node); ++ if (!pdev) { ++ ath12k_warn(ab, "Failed to get pdev from device node\n"); ++ return NOTIFY_DONE; ++ } ++ if (strcmp(ssr_pdev->name, pdev->name) != 0) { ++ ath12k_warn(ab, "SSR notification mismatch %s pdev name:%s\n", ++ (char *)data, pdev->name); ++ return NOTIFY_DONE; ++ } ++ ++ /* Changing the rrpoc->state to crashed disabled the ++ * remoteproc module to do the recovery process. ++ * This module will take care of the rrproc recovery process. ++ */ ++ ab_ahb->tgt_rrproc->state = RPROC_CRASHED; + + if (!(test_bit(ATH12K_FLAG_UNREGISTERING, &ab->ag->dev_flags))) { + set_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags); +@@ -1688,14 +1725,6 @@ static int ath12k_core_atomic_ssr_notifier_cb(struct notifier_block *nb, + ath12k_hal_dump_srng_stats(ab); + /* TODO Add more driver stats */ + +- ath12k_qmi_free_target_mem_chunk(ab); +- +- /* Crash the system once all the stats are dumped */ +- if (!ab->fw_recovery_support) +- BUG_ON(1); +- +- ath12k_dbg(ab, ATH12K_DBG_BOOT, "reset started\n"); +- + return NOTIFY_OK; + } + +@@ -1915,6 +1944,85 @@ static void ath12k_core_restart(struct work_struct *work) + ath12k_warn(ab, "SAWF SLA reconfiguring failed\n"); + } + ++static void ath12k_rproc_recovery_do_coredump(struct rproc *rproc) ++{ ++ if (rproc) { ++ rproc->ops->coredump(rproc); ++ } ++} ++ ++static int ath12k_rproc_recovery_stop_coredump(struct ath12k_base *ab) ++{ ++ int ret; ++ struct ath12k_ahb *ab_ahb = ath12k_ahb_priv(ab); ++ ++ if (ab_ahb->tgt_rproc) { ++ ab_ahb->tgt_rproc->state = RPROC_CRASHED; ++ ret = rproc_stop(ab_ahb->tgt_rproc, true); ++ if (ret < 0) { ++ ath12k_err(ab, "userpd rproc stop failed\n"); ++ return ret; ++ } ++ ab_ahb->tgt_rproc->state = RPROC_SUSPENDED; ++ } ++ if (ab_ahb->tgt_rrproc) { ++ ab_ahb->tgt_rrproc->state = RPROC_RUNNING; ++ ret = rproc_stop(ab_ahb->tgt_rrproc, true); ++ if (ret < 0) { ++ ath12k_err(ab, "rootpd rproc stop failed\n"); ++ return ret; ++ } ++ ath12k_rproc_recovery_do_coredump(ab_ahb->tgt_rrproc); ++ } ++ ++ return 0; ++} ++ ++static int ath12k_rproc_recovery_power_up(struct ath12k_base *ab) ++{ ++ struct ath12k_ahb *ab_ahb = ath12k_ahb_priv(ab); ++ struct rproc *rproc_rpd; ++ const struct firmware *firmware_p = NULL; ++ struct rproc *rproc; ++ struct device *dev; ++ int ret; ++ ++ rproc = ab_ahb->tgt_rproc; ++ rproc_rpd = ab_ahb->tgt_rrproc; ++ ++ if (rproc_rpd) { ++ dev = &rproc_rpd->dev; ++ ret = request_firmware(&firmware_p, rproc_rpd->firmware, dev); ++ if (ret < 0) { ++ ath12k_err(ab, "request_firmware failed: %d\n", ret); ++ return ret; ++ } ++ ret = rproc_start(rproc_rpd, firmware_p); ++ if (ret < 0) { ++ ath12k_err(ab, "Root pd rproc_start failed: %d\n", ret); ++ return ret; ++ } ++ } else { ++ if (rproc) { ++ dev = &rproc->dev; ++ ret = request_firmware(&firmware_p, ++ rproc->firmware, dev); ++ if (ret < 0) { ++ ath12k_err(ab, "request_firmware failed: %d\n", ++ ret); ++ return ret; ++ } ++ ret = rproc_start(rproc, firmware_p); ++ if (ret < 0) { ++ ath12k_err(ab, "User pd rproc_start failed: %d\n", ret); ++ return ret; ++ } ++ } ++ } ++ ++ return 0; ++} ++ + static void ath12k_core_reset(struct work_struct *work) + { + struct ath12k_base *ab = container_of(work, struct ath12k_base, reset_work); +@@ -1993,10 +2101,6 @@ static void ath12k_core_reset(struct work_struct *work) + ATH12K_WMI_FW_HANG_DELAY, true); + } + +- /* Incase recovery fails and FW asserts again, this is to prevent invalid operation. */ +- if (ag->num_started && ab->fw_recovery_support) +- ag->num_started--; +- + if (!ag->hw_queues_stopped) + ath12k_core_mlo_hw_queues_stop(ag); + +@@ -2012,12 +2116,24 @@ static void ath12k_core_reset(struct work_struct *work) + */ + if (ab->hif.bus == ATH12K_BUS_PCI) { + ath12k_coredump_download_rddm(ab); ++ } else if (ab->hif.bus == ATH12K_BUS_AHB) { ++ ath12k_coredump_download_ahb(ab); + } + +- if (ab->fw_recovery_support) { +- ath12k_hif_power_down(ab); +- ath12k_hif_power_up(ab); ++ /* Incase recovery fails and FW asserts again, this is to prevent invalid operation. */ ++ if (ag->num_started && ab->fw_recovery_support) ++ ag->num_started--; + ++ if (ab->fw_recovery_support) { ++ if (ab->hif.bus == ATH12K_BUS_PCI) { ++ ath12k_hif_power_down(ab); ++ ath12k_hif_power_up(ab); ++ } else if (ab->hif.bus == ATH12K_BUS_AHB) { ++ ath12k_rproc_recovery_stop_coredump(ab); ++ ath12k_qmi_free_target_mem_chunk(ab); ++ ath12k_rproc_recovery_power_up(ab); ++ ath12k_core_wait_dump_collect(ab); ++ } + ath12k_dbg(ab, ATH12K_DBG_BOOT, "reset started\n"); + } + mutex_unlock(&ag->mutex_lock); +diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h +index 549e402..32ece80 100644 +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -1515,6 +1515,7 @@ const struct firmware *ath12k_core_firmware_request(struct ath12k_base *ab, + const char *filename); + + void ath12k_core_wait_dump_collect(struct ath12k_base *ab); ++void ath12k_core_issue_bug_on(struct ath12k_base *ab); + + void ath12k_fw_stats_init(struct ath12k *ar); + void ath12k_fw_stats_pdevs_free(struct list_head *head); +diff --git a/drivers/net/wireless/ath/ath12k/coredump.c b/drivers/net/wireless/ath/ath12k/coredump.c +index 874e8a9..04321f6 100644 +--- a/drivers/net/wireless/ath/ath12k/coredump.c ++++ b/drivers/net/wireless/ath/ath12k/coredump.c +@@ -321,15 +321,8 @@ void ath12k_coredump_download_rddm(struct ath12k_base *ab) + chip_seg->num_seg = num_seg; + chip_seg->seg = segment; + +- if (ag->mlo_capable && +- (atomic_read(&ath12k_coredump_ram_info.num_chip) >= ab->ag->num_started)) +- BUG_ON(1); +- else if (!ag->mlo_capable) +- BUG_ON(1); +- else +- ath12k_info(ab, +- "%d chip dump collected and waiting for partner chips\n", +- atomic_read(&ath12k_coredump_ram_info.num_chip)); ++ ath12k_core_issue_bug_on(ab); ++ + } else { + /* TODO dump collection for MLO when fw_recovery set */ + ath12k_info(ab, "WLAN target is restarting"); +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/765-ath12k-Add-support-for-AWGN-wmi-control-stats.patch b/feeds/ipq95xx/mac80211/patches/qca/765-ath12k-Add-support-for-AWGN-wmi-control-stats.patch new file mode 100644 index 000000000..1c277d821 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/765-ath12k-Add-support-for-AWGN-wmi-control-stats.patch @@ -0,0 +1,274 @@ +From 02860e2962d83053dd1e7defc3ce9afa4251faa8 Mon Sep 17 00:00:00 2001 +From: Rajat Soni +Date: Thu, 20 Apr 2023 15:56:23 +0530 +Subject: [PATCH] ath12k: Add support for AWGN wmi control stats + +Add support for AWGN wmi control stats. AWGN stats are only supported for 6Ghz. + +Use below command: +Make sure you are requesting stats for 6GHz. + +echo > sys/kernel/debug/ath12k/ +qcn9274\ hw2.0_0003:01:00.0/mac0/wmi_ctrl_stats + +stats_id = 7 = WMI_REQ_CTRL_PATH_AWGN_STAT + +action = 1 or 2 + +1: WMI_REQUEST_CTRL_PATH_STAT_GET +2: WMI_REQUEST_CTRL_PATH_STAT_RESET + +To display stats: +cat sys/kernel/debug/ath12k/qcn9274\ hw2.0_0003:01:00.0/mac0/wmi_ctrl_stats + +Signed-off-by: Rajat Soni +--- + drivers/net/wireless/ath/ath12k/debugfs.c | 87 +++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/wmi.c | 61 ++++++++++++++++ + drivers/net/wireless/ath/ath12k/wmi.h | 18 +++++ + 3 files changed, 166 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c +index 9b2142d..ed43193 100644 +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -293,6 +293,90 @@ int wmi_ctrl_path_cal_stat(struct ath12k *ar, const char __user *ubuf, + return ret_val; + } + ++int wmi_ctrl_path_awgn_stat(struct ath12k *ar, const char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct wmi_ctrl_path_stats_list *stats; ++ struct wmi_ctrl_path_awgn_stats *awgn_stats; ++ const int size = 2048; ++ int len = 0, ret_val; ++ char *buf; ++ ++ buf = kzalloc(size, GFP_KERNEL); ++ ++ if (!buf) ++ return -ENOMEM; ++ ++ mutex_lock(&ar->wmi_ctrl_path_stats_lock); ++ ++ list_for_each_entry(stats, &ar->debug.wmi_list, list) { ++ ++ if (!stats) ++ break; ++ awgn_stats = stats->stats_ptr; ++ ++ if (!awgn_stats) ++ break; ++ ++ len += scnprintf(buf + len, size - len, ++ "WMI_CTRL_PATH_AWGN_STATS_TLV:\n"); ++ len += scnprintf(buf + len, size - len, ++ "awgn_send_evt_cnt = %u\n", ++ awgn_stats->awgn_send_evt_cnt); ++ len += scnprintf(buf + len, size - len, ++ "awgn_pri_int_cnt = %u\n", ++ awgn_stats->awgn_pri_int_cnt); ++ len += scnprintf(buf + len, size - len, ++ "awgn_sec_int_cnt = %u\n", ++ awgn_stats->awgn_sec_int_cnt); ++ len += scnprintf(buf + len, size - len, ++ "awgn_pkt_drop_trigger_cnt = %u\n", ++ awgn_stats->awgn_pkt_drop_trigger_cnt); ++ len += scnprintf(buf + len, size - len, ++ "awgn_pkt_drop_trigger_reset_cnt = %u\n", ++ awgn_stats->awgn_pkt_drop_trigger_reset_cnt); ++ len += scnprintf(buf + len, size - len, ++ "awgn_bw_drop_cnt = %u\n", ++ awgn_stats->awgn_bw_drop_cnt); ++ len += scnprintf(buf + len, size - len, ++ "awgn_bw_drop_reset_cnt = %u\n", ++ awgn_stats->awgn_bw_drop_reset_cnt); ++ len += scnprintf(buf + len, size - len, ++ "awgn_cca_int_cnt = %u\n", ++ awgn_stats->awgn_cca_int_cnt); ++ len += scnprintf(buf + len, size - len, ++ "awgn_cca_int_reset_cnt = %u\n", ++ awgn_stats->awgn_cca_int_reset_cnt); ++ len += scnprintf(buf + len, size - len, ++ "awgn_cca_ack_blk_cnt = %u\n", ++ awgn_stats->awgn_cca_ack_blk_cnt); ++ len += scnprintf(buf + len, size - len, ++ "awgn_cca_ack_reset_cnt = %u\n", ++ awgn_stats->awgn_cca_ack_reset_cnt); ++ len += scnprintf(buf + len, size - len, ++ "awgn_int_bw_cnt-AWGN_20[0]: %u\n", ++ awgn_stats->awgn_int_bw_cnt[0]); ++ len += scnprintf(buf + len, size - len, ++ "AWGN_40[1]: %u\n", ++ awgn_stats->awgn_int_bw_cnt[1]); ++ len += scnprintf(buf + len, size - len, ++ "AWGN_80[2]: %u\n", ++ awgn_stats->awgn_int_bw_cnt[2]); ++ len += scnprintf(buf + len, size - len, ++ "AWGN_160[3]: %u\n", ++ awgn_stats->awgn_int_bw_cnt[3]); ++ len += scnprintf(buf + len, size - len, ++ "AWGN_320[5]: %u\n", ++ awgn_stats->awgn_int_bw_cnt[5]); ++ } ++ ath12k_wmi_crl_path_stats_list_free(ar, &ar->debug.wmi_list); ++ mutex_unlock(&ar->wmi_ctrl_path_stats_lock); ++ ret_val = simple_read_from_buffer(ubuf, count, ppos, buf, len); ++ kfree(buf); ++ ++ return ret_val; ++} ++ + int wmi_ctrl_path_btcoex_stat(struct ath12k *ar, const char __user *ubuf, + size_t count, loff_t *ppos) + { +@@ -380,6 +464,9 @@ static ssize_t ath12k_read_wmi_ctrl_path_stats(struct file *file, + case WMI_CTRL_PATH_BTCOEX_STATS: + ret_val = wmi_ctrl_path_btcoex_stat(ar, ubuf, count, ppos); + break; ++ case WMI_CTRL_PATH_AWGN_STATS: ++ ret_val = wmi_ctrl_path_awgn_stat(ar, ubuf, count, ppos); ++ break; + /* Add case for newly wmi ctrl path added stats here */ + default: + /* Unsupported tag */ +diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c +index 5e66fbd..b321733 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -3954,6 +3954,17 @@ ath12k_wmi_send_wmi_ctrl_stats_cmd(struct ath12k *ar, + pdev_id_array[0] = ar->pdev->pdev_id; + stats_id = (1 << param->stats_id); + break; ++ case WMI_REQ_CTRL_PATH_AWGN_STAT: ++ if (ar->supports_6ghz) { ++ pdev_id_array[0] = ar->pdev->pdev_id; ++ stats_id = (1 << param->stats_id); ++ } else { ++ ath12k_warn(ab, ++ "Stats id %d awgn stats are only supported for 6GHz", ++ param->stats_id); ++ return -EIO; ++ } ++ break; + /* Add case for newly wmi ctrl path stats here */ + default: + ath12k_warn(ab, "Unsupported stats id %d", param->stats_id); +@@ -4184,6 +4195,53 @@ int wmi_print_ctrl_path_btcoex_stats_tlv(struct ath12k_base *ab, u16 len, + return 0; + } + ++int wmi_print_ctrl_path_awgn_stats_tlv(struct ath12k_base *ab, u16 len, ++ const void *ptr, void *data) ++{ ++ struct wmi_ctrl_path_stats_ev_parse_param *stats_buff = ++ (struct wmi_ctrl_path_stats_ev_parse_param *)data; ++ struct wmi_ctrl_path_awgn_stats *awgn_stats_skb, *awgn_stats = NULL; ++ struct wmi_ctrl_path_stats_list *stats; ++ struct ath12k *ar = NULL; ++ int i; ++ ++ awgn_stats_skb = (struct wmi_ctrl_path_awgn_stats *)ptr; ++ ++ for (i = 0; i < ATH12K_GROUP_MAX_RADIO; i++) { ++ ar = ab->ag->hw_links[i]; ++ if (!ar) { ++ ath12k_warn(ab, "Failed to get ar for wmi ctrl awgn stats\n"); ++ return -EINVAL; ++ } ++ ++ if (ar->supports_6ghz) ++ break; ++ } ++ ++ stats = kzalloc(sizeof(*stats), GFP_ATOMIC); ++ if (!stats) ++ return -ENOMEM; ++ ++ awgn_stats = kzalloc(sizeof(*awgn_stats), GFP_ATOMIC); ++ ++ if (!awgn_stats) { ++ kfree(stats); ++ return -ENOMEM; ++ } ++ ++ memcpy(awgn_stats, awgn_stats_skb, sizeof(*awgn_stats)); ++ stats->stats_ptr = awgn_stats; ++ list_add_tail(&stats->list, &stats_buff->list); ++ ++ mutex_lock(&ar->wmi_ctrl_path_stats_lock); ++ ath12k_wmi_crl_path_stats_list_free(ar, &ar->debug.wmi_list); ++ mutex_unlock(&ar->wmi_ctrl_path_stats_lock); ++ ar->debug.wmi_ctrl_path_stats_tagid = WMI_CTRL_PATH_AWGN_STATS; ++ stats_buff->ar = ar; ++ ++ return 0; ++} ++ + static int ath12k_wmi_ctrl_stats_subtlv_parser(struct ath12k_base *ab, + u16 tag, u16 len, + const void *ptr, void *data) +@@ -4202,6 +4260,9 @@ static int ath12k_wmi_ctrl_stats_subtlv_parser(struct ath12k_base *ab, + case WMI_CTRL_PATH_BTCOEX_STATS: + ret = wmi_print_ctrl_path_btcoex_stats_tlv(ab, len, ptr, data); + break; ++ case WMI_CTRL_PATH_AWGN_STATS: ++ ret = wmi_print_ctrl_path_awgn_stats_tlv(ab, len, ptr, data); ++ break; + /* Add case for newly wmi ctrl path added stats here */ + default: + ath12k_warn(ab, +diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h +index 0496fdd..f18d27e 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -2010,6 +2010,7 @@ enum wmi_tlv_tag { + WMI_TAG_VDEV_CH_POWER_INFO, + WMI_CTRL_PATH_CAL_STATS = 0x3BC, + WMI_CTRL_PATH_BTCOEX_STATS = 0x3FD, ++ WMI_CTRL_PATH_AWGN_STATS = 0x3F9, + WMI_TAG_EHT_RATE_SET = 0x3C4, + WMI_TAG_DCS_AWGN_INT_TYPE = 0x3C5, + WMI_TAG_MLO_TX_SEND_PARAMS, +@@ -7082,6 +7083,7 @@ wmi_ctrl_path_periodic_cal_type_id_to_name(u8 type_id) { + #define WMI_CTRL_PATH_CAL_PROF_MASK GENMASK(12, 8) + #define WMI_CTRL_PATH_CAL_TYPE_MASK GENMASK(7, 0) + #define WMI_CTRL_PATH_IS_PERIODIC_CAL GENMASK(13, 13) ++#define WMI_AWGN_MAX_BW 6 + + struct wmi_ctrl_path_pdev_stats { + u32 pdev_id; +@@ -7143,6 +7145,21 @@ struct wmi_ctrl_path_btcoex_stats { + u32 wl_tx_req_cntr; + } __packed; + ++struct wmi_ctrl_path_awgn_stats { ++ u32 awgn_send_evt_cnt; ++ u32 awgn_pri_int_cnt; ++ u32 awgn_sec_int_cnt; ++ u32 awgn_pkt_drop_trigger_cnt; ++ u32 awgn_pkt_drop_trigger_reset_cnt; ++ u32 awgn_bw_drop_cnt; ++ u32 awgn_bw_drop_reset_cnt; ++ u32 awgn_cca_int_cnt; ++ u32 awgn_cca_int_reset_cnt; ++ u32 awgn_cca_ack_blk_cnt; ++ u32 awgn_cca_ack_reset_cnt; ++ u32 awgn_int_bw_cnt[WMI_AWGN_MAX_BW]; ++} __packed; ++ + struct wmi_ctrl_path_stats_ev_parse_param { + struct list_head list; + struct ath12k *ar; +@@ -7712,6 +7729,7 @@ enum wmi_ctrl_path_stats_id { + WMI_REQ_CTRL_PATH_VDEV_EXTD_STAT = 2, + WMI_REQ_CTRL_PATH_MEM_STAT = 3, + WMI_REQ_CTRL_PATH_CAL_STAT = 5, ++ WMI_REQ_CTRL_PATH_AWGN_STAT = 7, + WMI_REQ_CTRL_PATH_BTCOEX_STAT = 8, + }; + +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/765-ath12k-Bonded-interface-working.-Traffic-tested.patch b/feeds/ipq95xx/mac80211/patches/qca/765-ath12k-Bonded-interface-working.-Traffic-tested.patch new file mode 100644 index 000000000..9d2d29ef5 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/765-ath12k-Bonded-interface-working.-Traffic-tested.patch @@ -0,0 +1,3544 @@ +From ac0d3754703e11e054269e05650a2fd59bec0070 Mon Sep 17 00:00:00 2001 +From: Ramanathan Choodamani +Date: Wed, 26 Apr 2023 16:37:13 -0700 +Subject: [PATCH] ath12k: Add support for Bond interface + +Add support for bonded interface to represent each wifi link with a separate +netdevice. With the new code changes, there will be new interfaces in the system. +Add support to collect statistics for the bonded devices. + +wlan0 - Original netdevice that gets created as per ath12k control path + This netdevice will continue to exist and will be used for all + control path communications. All NL messages from userspace applications + are processed on the context of this device. This device will not be + exposed to the bridge anymore +wlan0_b - This represents the bonded interface. No NL messages will be processed + on the context of this device. This device is purely meant for only + datapath. This device will be exposed to the bridge layer +link0 - wlan_l0 (link netdevice) + Will be used for registering with PPE module during MLO DS operation +link1 - wlan_l1 (link netdevice) + Will be used for registering with PPE module during MLO DS operation + +Signed-off-by: Ramanathan Choodamani +Signed-off-by: Balamurugan Mahalingam +Signed-off-by: Pradeep Kumar Chitrapu +Signed-off-by: Aloka Dixit +Signed-off-by: Shivani Tambatkar +Signed-off-by: Sidhanta Sahu +--- + drivers/net/wireless/ath/ath12k/Kconfig | 9 + + drivers/net/wireless/ath/ath12k/Makefile | 1 + + drivers/net/wireless/ath/ath12k/bondif.c | 783 +++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/bondif.h | 43 ++ + drivers/net/wireless/ath/ath12k/core.h | 18 + + drivers/net/wireless/ath/ath12k/dp.c | 7 + + drivers/net/wireless/ath/ath12k/dp_rx.c | 15 +- + drivers/net/wireless/ath/ath12k/dp_tx.c | 5 +- + drivers/net/wireless/ath/ath12k/mac.c | 80 ++- + drivers/net/wireless/ath/ath12k/pci.c | 23 + + drivers/net/wireless/ath/ath12k/ppe.c | 82 ++- + drivers/net/wireless/ath/ath12k/ppe.h | 15 +- + drivers/net/wireless/ath/ath6kl/cfg80211.c | 2 +- + drivers/net/wireless/ath/wil6210/netdev.c | 2 +- + include/net/cfg80211.h | 3 +- + include/net/mac80211.h | 6 +- + include/uapi/linux/nl80211.h | 3 + + local-symbols | 2 + + net/mac80211/Kconfig | 18 + + net/mac80211/cfg.c | 30 +- + net/mac80211/chan.c | 8 + + net/mac80211/ieee80211_i.h | 5 +- + net/mac80211/iface.c | 24 +- + net/mac80211/main.c | 8 +- + net/mac80211/mlme.c | 3 +- + net/mac80211/rx.c | 18 +- + net/mac80211/util.c | 4 + + net/wireless/chan.c | 8 + + net/wireless/core.c | 50 +- + net/wireless/nl80211.c | 29 +- + net/wireless/util.c | 4 + + 32 files changed, 1268 insertions(+), 89 deletions(-) + create mode 100644 drivers/net/wireless/ath/ath12k/bondif.c + create mode 100644 drivers/net/wireless/ath/ath12k/bondif.h + +--- a/drivers/net/wireless/ath/ath12k/Kconfig ++++ b/drivers/net/wireless/ath/ath12k/Kconfig +@@ -70,3 +70,12 @@ config ATH12K_PPE_DS_SUPPORT + Enable ath12k PPE-DS support + + Say Y to enable PPE DS Support. If unsure, say N. ++ ++config ATH12K_BONDED_DS_SUPPORT ++ bool "QTI ath12k bonded-ds support" ++ depends on ATH12K_DEBUGFS ++ depends on RELAY ++ help ++ Enable ath12k Bonded-DS support ++ ++ Say Y to enable Bonded DS Support. If unsure, say N. +--- a/drivers/net/wireless/ath/ath12k/Makefile ++++ b/drivers/net/wireless/ath/ath12k/Makefile +@@ -33,6 +33,7 @@ ath12k-$(CPTCFG_WANT_DEV_COREDUMP) += co + ath12k-$(CPTCFG_ATH12K_PKTLOG) += pktlog.o + ath12k-$(CPTCFG_ATH12K_AHB) += ahb.o + ath12k-$(CPTCFG_ATH12K_PPE_DS_SUPPORT) += ppe.o ++ath12k-$(CPTCFG_ATH12K_BONDED_DS_SUPPORT) += bondif.o + + # for tracing framework to find trace.h + CFLAGS_trace.o := -I$(src) +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/bondif.c +@@ -0,0 +1,967 @@ ++// SPDX-License-Identifier: BSD-3-Clause-Clear ++/* ++ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include "core.h" ++#include "ppe.h" ++#include "bondif.h" ++#include "debug.h" ++#include "dp_tx.h" ++ ++static const struct net_device_ops ieee80211_link_dataif_8023_ops; ++extern struct ath12k_link_vif *ath12k_mac_assign_link_vif( struct ath12k_hw *ah, ++ struct ieee80211_vif *vif, u8 link_id); ++extern int g_bonded_interface_model; ++extern bool ath12k_mac_tx_check_max_limit(struct ath12k *ar, struct sk_buff *skb); ++ ++static void ath12k_ieee80211_if_free(struct net_device *dev) ++{ ++ free_percpu(dev->tstats); ++} ++ ++static void ath12k_ieee80211_if_setup(struct net_device *dev) ++{ ++ ether_setup(dev); ++ dev->priv_flags &= ~IFF_TX_SKB_SHARING; ++ dev->netdev_ops = &ieee80211_link_dataif_8023_ops; ++ netdev_set_priv_destructor(dev, ath12k_ieee80211_if_free); ++} ++ ++static bool ath12k_ppe_vp_set_mtu(struct net_device *dev, struct ath12k_link_vif *arvif, ++ const int mtu) ++{ ++ if (!arvif->ndev_pvt->vp_num) ++ return true; ++ ++ if (ppe_vp_mtu_set(arvif->ndev_pvt->vp_num, mtu) != PPE_VP_STATUS_SUCCESS) { ++ ath12k_err(NULL, "Setting mtu to %d for link_ndev:%s (vp num:%d) failed\n", ++ mtu, arvif->ndev_pvt->link_ndev->name, ++ arvif->ndev_pvt->vp_num); ++ return false; ++ } ++ ++ return true; ++} ++ ++static bool ath12k_dst_ppe_vp(struct net_device *dev, ++ struct sk_buff *skb, void *cb_data) ++{ ++ if (unlikely(dev == NULL)) { ++ dev_kfree_skb_any(skb); ++ return false; ++ } ++ ++ skb->dev = dev; ++ dev_queue_xmit(skb); ++ ++ return true; ++} ++ ++int ath12k_bond_link_enslave(struct ath12k_link_vif *arvif, struct net_device *link_dev) ++{ ++ struct ath12k_link_vif_pvt *link_ndev_pvt = NULL; ++ int ret; ++ ++ if (!g_bonded_interface_model) ++ return 0; ++ ++ link_ndev_pvt = netdev_priv(link_dev); ++ ++ ath12k_info(NULL, "Enslave bond_dev %px link_ndev %px\n", link_ndev_pvt->bond_dev, link_dev); ++ ret = bond_enslave(link_ndev_pvt->bond_dev, link_dev, NULL); ++ if (ret) { ++ ath12k_err(NULL, "Error bond enslave error\n"); ++ return -EINVAL; ++ } ++ else { ++ ath12k_info(NULL, "Successfully enslaved link_ndev %s %px\n", ++ link_dev->name, link_dev); ++ } ++ ++ return 0; ++} ++ ++void ath12k_bond_link_release(struct ath12k_link_vif *arvif) ++{ ++ struct ath12k_link_vif_pvt *link_ndev_pvt = NULL; ++ int err; ++ ++ if (!g_bonded_interface_model) ++ return; ++ ++ if (!arvif->ndev_pvt || !arvif->ndev_pvt->link_ndev) { ++ ath12k_err(NULL, "ERR no link dev for this vif to release from bond\n"); ++ return; ++ } ++ ++ link_ndev_pvt = netdev_priv(arvif->ndev_pvt->link_ndev); ++ if (link_ndev_pvt && link_ndev_pvt->bond_dev) { ++ ath12k_info(NULL, "Bond_release link netdevice %s link ndev %px \n", ++ arvif->ndev_pvt->link_ndev->name, arvif->ndev_pvt->link_ndev); ++ ++ /* bond_release expects slave netdevices to be in down state */ ++ link_ndev_pvt->link_ndev->flags &= ~IFF_UP; ++ err = bond_release(link_ndev_pvt->bond_dev, link_ndev_pvt->link_ndev); ++ if (err) { ++ ath12k_err(NULL, "Error bond release link ndev:%s from bond ndev:%s: due to err: %d\n", ++ link_ndev_pvt->link_ndev->name, ++ link_ndev_pvt->bond_dev->name, err); ++ return; ++ } ++ } else { ++ ath12k_err(NULL, "ERR unable to release Bond %s link ndev %px \n", ++ arvif->ndev_pvt->link_ndev->name, arvif->ndev_pvt->link_ndev); ++ } ++} ++ ++static bool ath12k_stats_update_ppe_vp(struct net_device *dev, ppe_vp_hw_stats_t *vp_stats) ++{ ++ struct pcpu_sw_netstats *tstats = this_cpu_ptr(netdev_tstats(dev)); ++ ++ u64_stats_update_begin(&tstats->syncp); ++ tstats->tx_packets += vp_stats->tx_pkt_cnt; ++ tstats->tx_bytes += vp_stats->tx_byte_cnt; ++ tstats->rx_packets += vp_stats->rx_pkt_cnt; ++ tstats->rx_bytes += vp_stats->rx_byte_cnt; ++ u64_stats_update_end(&tstats->syncp); ++ ++ return true; ++} ++ ++void ath12k_enable_ppe_for_link_netdev(struct ath12k_link_vif *arvif, ++ struct net_device *link_dev) ++{ ++ struct ppe_vp_ai vpai; ++ struct ieee80211_ppe_vp_ds_params vp_params = {0}; ++ struct ath12k_link_vif_pvt *link_ndev_pvt = NULL; ++ int ret; ++ int ppe_vp_num = -1; ++ ++ arvif->ppe_vp_num = -1; ++ arvif->ppe_vp_type = -1; ++ if (!g_bonded_interface_model) ++ return; ++ ++ memset(&vpai, 0, sizeof(struct ppe_vp_ai)); ++ ++ vpai.type = PPE_VP_TYPE_SW_L2; ++ vpai.dst_cb = ath12k_dst_ppe_vp; ++ vpai.dst_cb_data = arvif; ++ vpai.src_cb = NULL; ++ vpai.src_cb_data = NULL; ++ vpai.stats_cb = ath12k_stats_update_ppe_vp; ++ vpai.queue_num = 0; ++ vpai.net_dev_type = PPE_VP_NET_DEV_TYPE_WIFI; ++ link_ndev_pvt = netdev_priv(link_dev); ++ ++ vpai.core_mask = ATH12K_PPE_DS_DEFAULT_CORE_MASK; ++ vp_params.dev = link_dev; ++ ++ if (test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &arvif->ar->ab->dev_flags)) { ++ vpai.usr_type = PPE_VP_USER_TYPE_DS; ++ ++ ret = ath12k_mac_op_ppeds_attach_vdev(arvif, &vpai, ++ &ppe_vp_num, &vp_params); ++ if (ret) { ++ ath12k_err(NULL, "Error in enabling DS for arvif %pM\n", arvif->addr); ++ return; ++ } ++ arvif->ppe_vp_type = PPE_VP_USER_TYPE_DS; ++ link_ndev_pvt->ppe_vp_profile_idx = vp_params.ppe_vp_profile_idx; ++ link_ndev_pvt->vp_num = ppe_vp_num; ++ arvif->ppe_vp_num = ppe_vp_num; ++ ath12k_dbg(arvif->ar->ab, ATH12K_DBG_PPE, ++ "Enabling DS index %d vp %d link_id %d %pM core_mask 0x%x\n", ++ vp_params.ppe_vp_profile_idx, ppe_vp_num, ++ arvif->link_id, arvif->addr, vpai.core_mask); ++ } else { ++ vpai.usr_type = PPE_VP_USER_TYPE_ACTIVE; ++ ++ ppe_vp_num = ppe_vp_alloc(vp_params.dev, &vpai); ++ if (ppe_vp_num <= 0) { ++ ath12k_err(NULL, "Error in enabling Active VP for arvif %pM\n", arvif->addr); ++ return; ++ } ++ link_ndev_pvt->vp_num = ppe_vp_num; ++ arvif->ppe_vp_num = ppe_vp_num; ++ arvif->ppe_vp_type = vpai.usr_type; ++ ath12k_dbg(ab, ATH12K_DBG_PPE, ++ "Enabling Active VP for arvif %pM dev %s vp_num %d core_mask 0x%x\n", ++ arvif->addr, vp_params.dev->name, ++ arvif->ppe_vp_num, vpai.core_mask); ++ } ++ ++ return; ++} ++ ++void ath12k_disable_ppe_for_link_netdev(struct ath12k_link_vif *arvif, struct net_device *link_dev) ++{ ++ struct ieee80211_ppe_vp_ds_params vp_params = {0}; ++ struct ath12k_link_vif_pvt *link_ndev_pvt = NULL; ++ ++ if (!g_bonded_interface_model) ++ return; ++ ++ if (!arvif->ndev_pvt || !arvif->ndev_pvt->link_ndev) { ++ ath12k_err(NULL, "ERR no link dev for this vif to disable DS.\n"); ++ return; ++ } ++ ++ link_ndev_pvt = netdev_priv(link_dev); ++ vp_params.ppe_vp_profile_idx = link_ndev_pvt->ppe_vp_profile_idx; ++ if (arvif->ppe_vp_num == -1) ++ return; ++ ++ if (test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ab->dev_flags)) { ++ ath12k_mac_op_ppeds_detach_vdev (arvif, &vp_params); ++ if (arvif->ppe_vp_type != PPE_VP_USER_TYPE_DS) ++ ppe_vp_free(arvif->ppe_vp_num); ++ ++ } else { ++ ppe_vp_free(arvif->ppe_vp_num); ++ } ++ ++ ath12k_dbg(arvif->ar->ab, ATH12K_DBG_PPE, ++ "Destroyed PPE VP port type %d no:%d for dev:%s\n", ++ arvif->ppe_vp_type, arvif->ppe_vp_num, link_dev->name); ++ arvif->ppe_vp_num = -1; ++ arvif->ppe_vp_type = -1; ++} ++ ++int ath12k_mac_op_change_vif_links(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ u16 old_links, u16 new_links, ++ struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS]) ++{ ++ u16 new_link_id; ++ struct wireless_dev *wdev = ieee80211_vif_to_wdev(vif); ++ struct net_device *cp_netdev = wdev->netdev; ++ struct ath12k_link_vif_pvt *link_ndev_pvt = NULL; ++ struct net_device *link_ndev; ++ struct ath12k_mld_dev *mldev = NULL; ++ u16 link_num; ++ struct net_device *bond_dev = NULL; ++ char name[20] = {0}; ++ int ret = 0, chip_id = 0, pdev_id = 0; ++ ++ if (!g_bonded_interface_model) ++ return 0; ++ ++ bond_dev = wdev->bond_netdev; ++ if (!bond_dev) ++ return 0; ++ mldev = bond_get_mlo_ctx(bond_dev); ++ ++ new_link_id = new_links ^ old_links; ++ link_num = ffs(new_link_id) - 1; ++ /* TODO: Do this assignment only for the Add link case */ ++ ++ if (new_links > old_links) { ++ /* Add Link operation */ ++ snprintf(name, sizeof(name), "%s_l%d", cp_netdev->name, link_num); ++ link_ndev = alloc_netdev_mqs(sizeof (struct ath12k_link_vif_pvt), name, NET_NAME_ENUM, ath12k_ieee80211_if_setup, 1, 1); ++ if (!link_ndev) { ++ ath12k_err(NULL, "ERR: link netdev allocation failed\n"); ++ //TODO: Graceful cleanup ++ return -EINVAL; ++ } ++ ++ memcpy(&link_ndev->perm_addr, wdev->links[link_num].addr, ETH_ALEN); ++ link_ndev->dev_addr = &link_ndev->perm_addr; ++ link_ndev_pvt = netdev_priv(link_ndev); ++ memset(link_ndev_pvt, 0, sizeof(*link_ndev_pvt)); ++ link_ndev->netdev_ops = &ieee80211_link_dataif_8023_ops; ++ link_ndev_pvt->hw = hw; ++ link_ndev_pvt->link_ndev = link_ndev; ++ link_ndev_pvt->bond_dev = bond_dev; ++ link_ndev_pvt->is_started = false; ++ mldev->vif = vif; ++ mutex_lock(&vif->bond_mutex); ++ vif->link_ndev[link_num] = link_ndev; ++ mutex_unlock(&vif->bond_mutex); ++ link_ndev->max_mtu = IEEE80211_MAX_DATA_LEN; ++ link_ndev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); ++ ret = register_netdevice(link_ndev); ++ if (ret) { ++ ath12k_err(NULL, "Error register link netdevice\n"); ++ //TODO: Graceful cleanup ++ return -EINVAL; ++ } ++ ++ memcpy(&bond_dev->perm_addr, vif->addr, ETH_ALEN); ++ bond_dev->dev_addr = &bond_dev->perm_addr; ++ ++ if (mldev && !mldev->mcast_dev_set) { ++ mldev->mcast_dev_set = true; ++ mldev->primary_chipid = chip_id; ++ mldev->primary_pdevid = pdev_id; ++ } ++ if (mldev) ++ mldev->link_dev[chip_id][pdev_id] = link_ndev; ++ ++ } else { ++ /* Delete Link operation */ ++ mutex_lock(&vif->bond_mutex); ++ link_ndev = vif->link_ndev[link_num]; ++ link_ndev_pvt = netdev_priv(link_ndev); ++ if (link_ndev) { ++ ath12k_info(NULL, "Unregister link netdevice %s link ndev %px link_num %d\n", link_ndev->name, link_ndev, link_num); ++ unregister_netdevice(link_ndev); ++ link_ndev_pvt->link_ndev = NULL; ++ vif->link_ndev[link_num] = NULL; ++ } else { ++ ath12k_err(NULL, "ERR Unregister link netdevice %s link ndev %px link_num %d\n", link_ndev->name, link_ndev, link_num); ++ } ++ mutex_unlock(&vif->bond_mutex); ++ } ++ ath12k_info(NULL, "%s:%d link changed for MLD %pM old 0x%x new 0x%x\n", __func__, __LINE__, vif->addr, old_links, new_links); ++ return 0; ++} ++ ++ ++static struct net_device *ath12k_mac_get_tx_link_netdev(struct ath12k_mld_dev *mldev, u8 *dst_mac_addr) ++{ ++ struct net_device *ndev = NULL, *dvlan_ndev = NULL; ++ struct ieee80211_sta *sta= NULL; ++ struct ath12k_sta *ahsta; ++ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(mldev->vif); ++ ++ rcu_read_lock(); ++ sta = ieee80211_find_sta(mldev->vif, dst_mac_addr); ++ ++ if (!sta) { ++ rcu_read_unlock(); ++ ndev = mldev->vif->link_ndev[ahvif->deflink.link_id]; ++ ath12k_dbg(NULL, ATH12K_DBG_DP_TX, "(%s,%d) PPE %s:%d ahvif->deflink.link_id %d dev %s\n", ++ current->comm, current->pid, __func__, __LINE__, ++ ahvif->deflink.link_id, ndev->name); ++ return ndev; ++ } ++ ++ ahsta = (struct ath12k_sta *)sta->drv_priv; ++ ++ if (!sta->mlo) { ++ ndev = mldev->vif->link_ndev[ahsta->deflink.link_id]; ++ //todo: check changing addr3 needed as in ath12k_mac_get_tx_link ++ ++ ath12k_dbg(NULL, ATH12K_DBG_DP_TX, "(%s,%d) PPE %s:%d pkt delivered to sta.deflink.link_id %d dev %s\n", ++ current->comm, current->pid, __func__, __LINE__, ++ ahsta->deflink.link_id, ndev->name); ++ goto dvlan_check; ++ } ++ ++ if (sta) { ++ /* TODO: Use Primary Link */ ++ ndev = mldev->vif->link_ndev[ahsta->assoc_link_id]; ++ ath12k_dbg(NULL, ATH12K_DBG_DP_TX, "[%s] %s:%d deliver packets for sta %pM ahsta->assoc_link_id %d ndev %s\n", ++ current->comm, __func__, __LINE__, ++ sta, ahsta->assoc_link_id, ndev->name); ++ } ++ ++dvlan_check: ++ dvlan_ndev = ieee80211_sta_get_dvlan_iface(sta); ++ if (dvlan_ndev) ++ ndev = dvlan_ndev; ++ ++ rcu_read_unlock(); ++ ++ /* TODO: Verify what happens with NULL. Understand what is the fall back*/ ++ return ndev; ++} ++ ++static void ath12k_dp_tx_release_txbuf(struct ath12k_dp *dp, ++ struct ath12k_tx_desc_info *tx_desc, ++ u8 ring_id) ++{ ++ tx_desc->skb = NULL; ++ tx_desc->skb_ext_desc = NULL; ++ spin_lock_bh(&dp->tx_desc_lock[ring_id]); ++ list_move_tail(&tx_desc->list, &dp->tx_desc_free_list[ring_id]); ++ spin_unlock_bh(&dp->tx_desc_lock[ring_id]); ++} ++ ++static inline ++struct ath12k_tx_desc_info *ath12k_dp_tx_assign_buffer(struct ath12k_dp *dp, ++ u8 pool_id) ++{ ++ struct ath12k_tx_desc_info *desc = NULL; ++ ++ spin_lock_bh(&dp->tx_desc_lock[pool_id]); ++ desc = list_first_entry_or_null(&dp->tx_desc_free_list[pool_id], ++ struct ath12k_tx_desc_info, ++ list); ++ if (!desc) { ++ ath12k_dbg(dp->ab, ATH12K_DBG_DP_TX, "failed to allocate data Tx desc\n"); ++ spin_unlock_bh(&dp->tx_desc_lock[pool_id]); ++ return NULL; ++ } ++ ++ prefetch(desc); ++ list_move_tail(&desc->list, &dp->tx_desc_used_list[pool_id]); ++ spin_unlock_bh(&dp->tx_desc_lock[pool_id]); ++ ++ return desc; ++} ++ ++int ath12k_mcast_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif, ++ struct sk_buff *skb, bool gsn_valid, int mcbc_gsn) ++{ ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ath12k_base *ab = ar->ab; ++ struct ath12k_dp *dp = &ab->dp; ++ struct hal_tx_info ti = {0}; ++ struct ath12k_tx_desc_info *tx_desc = NULL; ++ struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB(skb); ++ struct hal_srng *tcl_ring; ++ struct dp_tx_ring *tx_ring; ++ void *hal_tcl_desc; ++ struct hal_tcl_data_cmd *tcl_cmd; ++ u8 hal_ring_id; ++ int ret; ++ ++ if (unlikely(test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))) { ++ return -ESHUTDOWN; ++ } ++ ++ ti.ring_id = ++ ab->hw_params->hw_ops->get_ring_selector(skb); ++ ++ tx_ring = &dp->tx_ring[ti.ring_id]; ++ ++ tx_desc = ath12k_dp_tx_assign_buffer(dp, ti.ring_id); ++ if (unlikely(!tx_desc)) { ++ ab->soc_stats.tx_err.txbuf_na[ti.ring_id]++; ++ return -ENOMEM; ++ } ++ ++ ATH12K_SKB_CB(skb)->link_id = arvif->link_id; ++ ti.bank_id = arvif->bank_id; ++ ti.meta_data_flags = arvif->tcl_metadata; ++ ++ if (gsn_valid) { ++ ti.meta_data_flags = u32_encode_bits(HTT_TCL_META_DATA_TYPE_GLOBAL_SEQ_NUM, ++ HTT_TCL_META_DATA_TYPE_MISSION) | ++ u32_encode_bits(mcbc_gsn, HTT_TCL_META_DATA_GLOBAL_SEQ_NUM); ++ ti.vdev_id = arvif->vdev_id + ++ HTT_TX_MLO_MCAST_HOST_REINJECT_BASE_VDEV_ID; ++ } else { ++ ti.vdev_id = arvif->vdev_id; ++ } ++ ++ ti.encap_type = HAL_TCL_ENCAP_TYPE_ETHERNET; ++ ti.addr_search_flags = arvif->hal_addr_search_flags; ++ ti.search_type = arvif->search_type; ++ ti.type = HAL_TCL_DESC_TYPE_BUFFER; ++ ++ if (likely(skb->ip_summed == CHECKSUM_PARTIAL && ++ ti.encap_type != HAL_TCL_ENCAP_TYPE_RAW)) { ++ ti.flags0 |= TX_IP_CHECKSUM; ++ } ++ ++ ti.paddr = dma_map_single(ab->dev, skb->data, skb->len, DMA_TO_DEVICE); ++ if (unlikely(dma_mapping_error(ab->dev, ti.paddr))) { ++ atomic_inc(&ab->soc_stats.tx_err.misc_fail); ++ ath12k_warn(ab, "failed to DMA map data Tx buffer\n"); ++ ret = -ENOMEM; ++ goto fail_remove_tx_buf; ++ } ++ ++ ++ /* Add metadata for sw encrypted vlan group traffic */ ++ ++ tx_desc->skb = skb; ++ tx_desc->mac_id = ar->pdev_idx; ++ tx_desc->recycler_fast_xmit = 0; ++ ti.desc_id = tx_desc->desc_id; ++ ti.data_len = skb->len - ti.pkt_offset; ++ skb_cb->paddr = ti.paddr; ++ skb_cb->vif = ahvif->vif; ++ skb_cb->ar = ar; ++ ++ hal_ring_id = tx_ring->tcl_data_ring.ring_id; ++ tcl_ring = &ab->hal.srng_list[hal_ring_id]; ++ ++ spin_lock_bh(&tcl_ring->lock); ++ ath12k_hal_srng_access_src_ring_begin_nolock(tcl_ring); ++ hal_tcl_desc = ath12k_hal_srng_src_get_next_entry(ab, tcl_ring); ++ if (unlikely(!hal_tcl_desc)) { ++ /* NOTE: It is highly unlikely we'll be running out of tcl_ring ++ * desc because the desc is directly enqueued onto hw queue. ++ */ ++ ath12k_hal_srng_access_umac_src_ring_end_nolock(tcl_ring); ++ spin_unlock_bh(&tcl_ring->lock); ++ ab->soc_stats.tx_err.desc_na[ti.ring_id]++; ++ ret = -ENOMEM; ++ ++ goto fail_unmap_dma; ++ } ++ ++ ab->soc_stats.tx_enqueued[ti.ring_id]++; ++ arvif->link_stats.tx_encap_type[ti.encap_type]++; ++ arvif->link_stats.tx_encrypt_type[ti.encrypt_type]++; ++ arvif->link_stats.tx_desc_type[ti.type]++; ++ tcl_cmd = (struct hal_tcl_data_cmd *)hal_tcl_desc; ++ ++ tcl_cmd->buf_addr_info.info0 = (u32)ti.paddr; ++ /* TODO: Copy the upper 8 bits here */ ++ tcl_cmd->buf_addr_info.info1 = (ti.desc_id << 12); ++ tcl_cmd->info0 = (ti.type << 1) | arvif->desc.info0; ++ tcl_cmd->info1 = ti.meta_data_flags << 16; ++ tcl_cmd->info2 = ti.flags0 | ti.data_len; ++ ++ /* In tcl_cmd->info3, Bit 24 to 31 represents vdev_id ++ * LSH 24 times to add updated vdev_id to info3 ++ */ ++ tcl_cmd->info3 = (ti.vdev_id << 24) | arvif->desc.info3; ++ tcl_cmd->info4 = arvif->desc.info4; ++ tcl_cmd->info5 = 0; ++ ++ dsb(st); ++ ath12k_hal_srng_access_umac_src_ring_end_nolock(tcl_ring); ++ spin_unlock_bh(&tcl_ring->lock); ++ ++ ath12k_dbg_dump(ab, ATH12K_DBG_DP_TX, NULL, "dp tx msdu: ", skb->data, skb->len); ++ arvif->link_stats.tx_enqueued++; ++ atomic_inc(&ar->dp.num_tx_pending); ++ ++ return 0; ++ ++fail_unmap_dma: ++ dma_unmap_single(ab->dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE); ++ ++fail_remove_tx_buf: ++ ath12k_dp_tx_release_txbuf(dp, tx_desc, ti.ring_id); ++ if (ti.pkt_offset) ++ skb_pull(skb, ti.pkt_offset); ++ ++ arvif->link_stats.tx_dropped++; ++ ++ return ret; ++} ++ ++int ath12k_dp_mlo_xmit_netdev(struct sk_buff *skb, struct net_device *bond_dev) ++{ ++ struct net_device *link_dev = NULL; ++ struct ethhdr *eh = NULL; ++ struct ath12k_mld_dev *mldev = bond_get_mlo_ctx(bond_dev); ++ struct ath12k_link_vif_pvt *arvif_pvt = NULL; ++ struct ath12k_link_vif *arvif, *tmp_arvif; ++ struct ath12k_vif *ahvif = NULL; ++ struct sk_buff *msdu_copied; ++ struct ath12k *tmp_ar; ++ int is_mcast; ++ u16 mcbc_gsn; ++ int ret; ++ int link_id, ring_id = 0; ++ struct ath12k_skb_cb *skb_cb; ++ struct ieee80211_tx_info *info; ++ ++ if (!(bond_dev->flags & IFF_UP)) { ++ dev_kfree_skb(skb); ++ return NETDEV_TX_OK; ++ } ++ ++ eh = (struct ethhdr *)skb->data; ++ is_mcast = is_multicast_ether_addr(eh->h_dest); ++ skb_cb = ATH12K_SKB_CB(skb); ++ skb_cb->flags |= ATH12K_SKB_HW_80211_ENCAP; ++ info = IEEE80211_SKB_CB(skb); ++ info->flags |= IEEE80211_TX_CTL_HW_80211_ENCAP; ++ ++ if (is_mcast) { ++ uint8_t chip_id = mldev->primary_chipid; ++ uint8_t pdev_id = mldev->primary_pdevid; ++ ++ link_dev = mldev->link_dev[chip_id][pdev_id]; ++ arvif_pvt = netdev_priv(link_dev); ++ arvif = arvif_pvt->arvif; ++ if (!arvif) { ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_OK; ++ } ++ ++ ahvif = arvif->ahvif; ++ if (!ahvif) { ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_OK; ++ } ++ ++ spin_lock(&ahvif->mcbc_gsn_lock); ++ mcbc_gsn = ahvif->mcbc_gsn++; ++ if (ahvif->mcbc_gsn > 0xFFF) ++ ahvif->mcbc_gsn = 0; ++ spin_unlock(&ahvif->mcbc_gsn_lock); ++ ++ for_each_set_bit(link_id, &ahvif->links_map, ++ IEEE80211_MLD_MAX_NUM_LINKS) { ++ tmp_arvif = ahvif->link[link_id]; ++ if (tmp_arvif && tmp_arvif->ar) ++ tmp_ar = tmp_arvif->ar; ++ else ++ break; ++ ++ ret = ath12k_mac_tx_check_max_limit(tmp_ar, skb); ++ if (ret) { ++ ath12k_dbg(tmp_ar->ab, ATH12K_DBG_MAC, ++ "failed fast tx due to limit check pdev idx %d\n", ++ tmp_ar->pdev_idx); ++ continue; ++ } ++ ++ ring_id = tmp_arvif->ar->ab->hw_params->hw_ops->get_ring_selector(skb); ++ ++ if (test_bit(ATH12K_FLAG_RECOVERY, &tmp_ar->ab->dev_flags)) { ++ tmp_ar->ab->soc_stats.bond_tx_mcast_dropped[ring_id]++; ++ break; ++ } ++ ++ tmp_ar->ab->soc_stats.bond_tx_mcast_enqueued[ring_id]++; ++ msdu_copied = skb_copy(skb, GFP_ATOMIC); ++ if (!msdu_copied) { ++ tmp_ar->ab->soc_stats.bond_tx_mcast_dropped[ring_id]++; ++ continue; ++ } ++ ++ ret = ath12k_mcast_dp_tx(tmp_ar, tmp_arvif, msdu_copied, true, mcbc_gsn); ++ if (ret) { ++ tmp_ar->ab->soc_stats.bond_tx_mcast_dropped[ring_id]++; ++ dev_kfree_skb_any(msdu_copied); ++ continue; ++ } ++ } ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_OK; ++ } else { ++ link_dev = ath12k_mac_get_tx_link_netdev( mldev, eh->h_dest); ++ } ++ ++ if (!link_dev) { ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_OK; ++ } ++ ++ skb->fast_xmit = 0; ++ return link_dev->netdev_ops->ndo_start_xmit(skb, link_dev); ++} ++ ++struct net_device *ath12k_dp_get_mlo_tx_netdev(void *bondctx, u8 *dst_mac_addr) ++{ ++ struct ath12k_mld_dev *mldev = (struct ath12k_mld_dev *)bondctx; ++ ++ return ath12k_mac_get_tx_link_netdev(mldev, dst_mac_addr); ++} ++ ++int ieee80211_link_open(struct net_device *dev) ++{ ++ struct ath12k_link_vif_pvt *arvif_pvt = netdev_priv(dev); ++ arvif_pvt->is_started = true; ++ return 0; ++} ++ ++int ieee80211_link_stop(struct net_device *dev) ++{ ++ struct ath12k_link_vif_pvt *arvif_pvt = netdev_priv(dev); ++ arvif_pvt->is_started = false; ++ return 0; ++} ++ ++void ieee80211_link_uninit(struct net_device *dev) ++{ ++ return; ++} ++ ++static inline void ieee80211_tx_stats_bonded_if(struct net_device *dev, u32 len) ++{ ++ struct pcpu_sw_netstats *tstats = this_cpu_ptr(netdev_tstats(dev)); ++ ++ u64_stats_update_begin(&tstats->syncp); ++ tstats->tx_packets++; ++ tstats->tx_bytes += len; ++ u64_stats_update_end(&tstats->syncp); ++} ++ ++netdev_tx_t ieee80211_link_subif_start_xmit_8023(struct sk_buff *skb, ++ struct net_device *dev) ++{ ++ struct ath12k_link_vif_pvt *arvif_pvt = netdev_priv(dev); ++ struct ath12k_link_vif *arvif = arvif_pvt->arvif; ++ struct ath12k_base *ab; ++ int ret; ++ int is_mcast, ring_id = 0; ++ struct ethhdr *eh = NULL; ++ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); ++ ++ ieee80211_tx_stats_bonded_if(dev, skb->len); ++ ++ if (!(dev->flags & IFF_UP)) { ++ dev_kfree_skb(skb); ++ return NETDEV_TX_OK; ++ } ++ ++ eh = (struct ethhdr *)skb->data; ++ is_mcast = is_multicast_ether_addr(eh->h_dest); ++ info->flags |= IEEE80211_TX_CTL_HW_80211_ENCAP; ++ ATH12K_SKB_CB(skb)->link_id = arvif->link_id; ++ ++ if (!arvif_pvt->is_started) { ++ ath12k_dbg(NULL, ATH12K_DBG_PPE, "Dropping frames as arvif is not started\n"); ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_OK; ++ } ++ if (!arvif || !arvif->is_started) { ++ ath12k_dbg(NULL, ATH12K_DBG_PPE, "Dropping frames as arvif is not started\n"); ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_OK; ++ } ++ ++ ab = arvif->ar->ab; ++ ring_id = ab->hw_params->hw_ops->get_ring_selector(skb); ++ ++ if (test_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags)) { ++ ath12k_dbg(NULL, ATH12K_DBG_PPE, "Dropping frames as radio is in recovery\n"); ++ ab->soc_stats.bond_tx_ucast_dropped[ring_id]++; ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_OK; ++ } ++ ++ ++ ab->soc_stats.bond_tx_ucast_enqueued[ring_id]++; ++ /* TODO: debug why queue is always 15 */ ++ info->hw_queue = 0; ++ ++ ret = ath12k_mac_tx_check_max_limit(arvif->ar, skb); ++ if (ret) { ++ ath12k_dbg(arvif->ar->ab, ATH12K_DBG_MAC, ++ "failed fast tx due to limit check pdev idx %d\n", ++ arvif->ar->pdev_idx); ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_OK; ++ } ++ ++ ret = ath12k_dp_tx_direct(arvif, skb); ++ if (unlikely(ret)) { ++ ath12k_dbg(ab, ATH12K_DBG_PPE, ++ "failed to transmit frame %d\n", ret); ++ dev_kfree_skb_any(skb); ++ ab->soc_stats.bond_tx_ucast_dropped[ring_id]++; ++ return NETDEV_TX_OK; ++ } ++ return NETDEV_TX_OK; ++} ++ ++void ieee80211_link_set_multicast_list(struct net_device *dev) ++{ ++ return; ++} ++ ++static int ieee80211_link_set_mtu(struct net_device *dev, int mtu) ++{ ++ struct ath12k_link_vif_pvt *arvif_pvt = netdev_priv(dev); ++ struct ath12k_link_vif *arvif = arvif_pvt->arvif; ++ ++ if (!arvif) ++ return -EINVAL; ++ ++ if (!(IEEE80211_MTU_MIN < mtu && mtu < IEEE80211_MTU_MAX)) ++ return -EINVAL; ++ ++ if (!ath12k_ppe_vp_set_mtu(dev, arvif, mtu)) ++ return -EINVAL; ++ ++ dev->mtu = mtu; ++ ++ return 0; ++} ++ ++int ieee80211_link_change_mac(struct net_device *dev, void *addr) ++{ ++ return 0; ++} ++ ++#if LINUX_VERSION_IS_GEQ(5,2,0) ++u16 ieee80211_link_netdev_select_queue(struct net_device *dev, ++ struct sk_buff *skb, ++ struct net_device *sb_dev) ++#elif LINUX_VERSION_IS_GEQ(4,19,0) ++u16 ieee80211_link_netdev_select_queue(struct net_device *dev, ++ struct sk_buff *skb, ++ struct net_device *sb_dev, ++ select_queue_fallback_t fallback) ++#else ++u16 ieee80211_link_netdev_select_queue(struct net_device *dev, ++ struct sk_buff *skb, ++ void *accel_priv, ++ select_queue_fallback_t fallback) ++#endif ++{ ++ return smp_processor_id(); ++} ++ ++void ++ieee80211_link_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) ++{ ++ dev_fetch_sw_netstats(stats, dev->tstats); ++} ++static const struct net_device_ops ieee80211_link_dataif_8023_ops = { ++ .ndo_open = ieee80211_link_open, ++ .ndo_stop = ieee80211_link_stop, ++ .ndo_uninit = ieee80211_link_uninit, ++ .ndo_start_xmit = ieee80211_link_subif_start_xmit_8023, ++ .ndo_set_rx_mode = ieee80211_link_set_multicast_list, ++ .ndo_change_mtu = ieee80211_link_set_mtu, ++ .ndo_set_mac_address = ieee80211_link_change_mac, ++ .ndo_select_queue = ieee80211_link_netdev_select_queue, ++ .ndo_get_stats64 = ieee80211_link_get_stats64, ++}; ++ ++int ath12k_free_bonddev_for_sfe(struct wireless_dev *wdev, struct ieee80211_vif *vif, int link_num) ++{ ++ struct ath12k_mld_dev *mldev = NULL; ++ struct wireless_dev *dummywdev = NULL; ++ struct wiphy *dummywiphy = NULL; ++ struct net_device *link_ndev = NULL; ++ int ret; ++ ++ mutex_lock(&vif->bond_mutex); ++ link_ndev = vif->link_ndev[link_num]; ++ if (link_ndev) { ++ ath12k_info(NULL, "Bond_release and Unregister link netdevice %s link ndev %px link_num %d\n", link_ndev->name, link_ndev, link_num); ++ bond_release(wdev->bond_netdev, link_ndev); ++ unregister_netdevice(link_ndev); ++ vif->link_ndev[link_num] = NULL; ++ } else { ++ ath12k_err(NULL, "ERR Free Bond dev for SFE. Unregister link netdevice %s link ndev %px link_num %d\n", link_ndev->name, link_ndev, link_num); ++ } ++ mutex_unlock(&vif->bond_mutex); ++ if (!wdev->bond_netdev) { ++ ath12k_info(NULL, "No bond device exists in the ath12k driver for device. SFE\n"); ++ return 0; ++ } ++ mldev = bond_get_mlo_ctx(wdev->bond_netdev); ++ if (!test_bit(ATH12K_BOND_REGISTERED, &mldev->bond_state)) { ++ ath12k_err(NULL, "Bond interface destroyed already. Called for the second time.\n"); ++ return 0; ++ } ++ ++ dummywiphy = mldev->wdev->wiphy; ++ dummywdev = mldev->wdev; ++ ++ /* Returns true on success */ ++ ret = bond_destroy_mlo(wdev->bond_netdev); ++ if (ret) { ++ wdev->bond_netdev = NULL; ++ ath12k_info(NULL,"Successfully destroyed bond device\n"); ++ } else { ++ ath12k_err(NULL, "Not able destroy bond device %s ret %d\n", wdev->bond_netdev->name, ret); ++ return -EINVAL; ++ } ++ kfree(dummywdev); ++ wiphy_free(dummywiphy); ++ clear_bit(ATH12K_BOND_REGISTERED, &mldev->bond_state); ++ kfree(mldev); ++ return 0; ++} ++ ++extern const struct cfg80211_ops mac80211_dummy_config_ops; ++int ath12k_bond_dev_cb(struct wireless_dev *wdev, struct net_device *dev, bool is_register) ++{ ++ struct mlo_bond_info *mlo_info = NULL; ++ struct ath12k_mld_dev *mldev = NULL; ++ struct wireless_dev *dummywdev = NULL; ++ int priv_size = 100; ++ char name[20] = {0}; ++ struct wiphy *dummywiphy = NULL; ++ bool ret; ++ ++ if (!g_bonded_interface_model) ++ return 0; ++ ++ if (is_register) { ++ if (wdev->bond_netdev && test_bit(ATH12K_BOND_REGISTERED, &mldev->bond_state)) { ++ ath12k_info(NULL, "Bond device already registered\n"); ++ return 0; ++ } ++ mlo_info = kmalloc(sizeof(struct mlo_bond_info), GFP_KERNEL); //TODO: Free ++ if (!mlo_info) { ++ ath12k_err(NULL, "ERR: Couldn't allocate mlo_info\n"); ++ return -ENOMEM; ++ } ++ memset(mlo_info, 0, sizeof(struct mlo_bond_info)); ++ mldev = kmalloc(sizeof(struct ath12k_mld_dev), GFP_KERNEL); ++ if (!mldev) { ++ ath12k_err(NULL, "ERR: Couldn't allocate mld_dev\n"); ++ kfree(mlo_info); ++ return -ENOMEM; ++ } ++ memset(mldev, 0, sizeof(struct ath12k_mld_dev)); ++ dummywdev = kmalloc(sizeof(struct wireless_dev), GFP_KERNEL); ++ if (!mldev) { ++ ath12k_err(NULL, "ERR: Couldn't allocate mld_dev\n"); ++ kfree(mlo_info); ++ kfree(mldev); ++ return -ENOMEM; ++ } ++ memset(dummywdev, 0, sizeof(struct wireless_dev)); ++ dummywiphy = wiphy_new_nm(&mac80211_dummy_config_ops, priv_size, NULL); ++ if (!dummywiphy) { ++ kfree(mlo_info); ++ kfree(mldev); ++ kfree(dummywdev); ++ return -EINVAL; ++ } ++ dummywiphy->interface_modes = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_DUMMY); ++ mlo_info->wdev = dummywdev; ++ mldev->wdev = dummywdev; ++ mlo_info->wdev->wiphy = dummywiphy; ++ mlo_info->wdev->iftype = NL80211_IFTYPE_DUMMY; ++ mlo_info->bond_mlo_ctx = (void *)mldev; ++ mlo_info->bond_mlo_xmit_netdev = ath12k_dp_mlo_xmit_netdev; ++ mlo_info->bond_get_mlo_tx_netdev = ath12k_dp_get_mlo_tx_netdev ; ++ snprintf(name, sizeof(name), "%s_b", dev->name); ++ wdev->bond_netdev = bond_create_mlo(&init_net, name, mlo_info); ++ ++ if (wdev->bond_netdev) { ++ wdev->bond_netdev->max_mtu = IEEE80211_MAX_DATA_LEN; ++ set_bit(ATH12K_BOND_REGISTERED, &mldev->bond_state); ++ ath12k_info(NULL, "Successfully registered bond_netdev %s for netdevice %s\n", wdev->bond_netdev->name, dev->name); ++ } else { ++ ath12k_err(NULL, "ERR: Unnable to register Bonded interface\n"); ++ } ++ kfree(mlo_info); ++ } else { ++ //TODO: Cleanup all objects in the allocation path. dummy wdev, wiphy, mldev ++ if (!wdev->bond_netdev) { ++ ath12k_info(NULL, "No bond device exists in the ath12k driver for device %s\n", dev->name); ++ return 0; ++ } ++ mldev = bond_get_mlo_ctx(wdev->bond_netdev); ++ if (!test_bit(ATH12K_BOND_REGISTERED, &mldev->bond_state)) { ++ ath12k_err(NULL, "bond interface destroyed already. Called for the second time.\n"); ++ return 0; ++ } ++ ++ dummywiphy = mldev->wdev->wiphy; ++ dummywdev = mldev->wdev; ++ ++ /* Returns true on success */ ++ ret = bond_destroy_mlo(wdev->bond_netdev); ++ if (ret) { ++ wdev->bond_netdev = NULL; ++ ath12k_info(NULL,"Successfully destroyed bond device\n"); ++ } else { ++ ath12k_err(NULL, "Not able destroy bond device %s ret %d\n", wdev->bond_netdev->name, ret); ++ return -EINVAL; ++ } ++ //TODO: Free mlo_info ++ kfree(dummywdev); ++ wiphy_free(dummywiphy); ++ clear_bit(ATH12K_BOND_REGISTERED, &mldev->bond_state); ++ kfree(mldev); ++ } ++ return 0; ++} +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/bondif.h +@@ -0,0 +1,44 @@ ++// SPDX-License-Identifier: BSD-3-Clause-Clear ++/* ++ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef __BONDIF_H ++#define __BONDIF_H ++ ++#define MAX_MLO_CHIPS 3 ++#define MAX_PDEV_PER_SOC 3 ++ ++#define ATH12K_PPE_DS_2G_CORE_MASK 0x1 ++#define ATH12K_PPE_DS_5G_CORE_MASK 0x2 ++#define ATH12K_PPE_DS_6G_CORE_MASK 0x4 ++#define ATH12K_PPE_DS_DEFAULT_CORE_MASK 0x7 ++ ++void ath12k_disable_ppe_for_link_netdev(struct ath12k_link_vif *arvif, ++ struct net_device *link_dev); ++void ath12k_enable_ppe_for_link_netdev(struct ath12k_link_vif *arvif, ++ struct net_device *link_dev); ++int ath12k_free_bonddev_for_sfe(struct wireless_dev *wdev, ++ struct ieee80211_vif *vif, ++ int link_num); ++int ath12k_bond_link_enslave(struct ath12k_link_vif *arvif, struct net_device *link_dev); ++void ath12k_bond_link_release(struct ath12k_link_vif *arvif); ++enum ath12k_bond_state { ++ ATH12K_BOND_SETUP_INPROGRESS, ++ ATH12K_BOND_REGISTERED, ++ ATH12K_BOND_LINK0_REGISTERED, ++ ATH12K_BOND_LINK1_REGISTERED, ++ ATH12K_BOND_LINK2_REGISTERED, ++ ++}; ++struct ath12k_mld_dev { ++ struct net_device *netdev; ++ struct ieee80211_vif *vif; ++ struct wireless_dev *wdev; //dummy one for bond registration. Optimize Bond MLO API. ++ struct net_device *link_dev[MAX_MLO_CHIPS][MAX_PDEV_PER_SOC]; ++ u8 primary_chipid, primary_pdevid; ++ bool mcast_dev_set; ++ unsigned long bond_state; ++}; ++ ++#endif //__BONDIF_H +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -335,6 +335,18 @@ struct ath12k_vif_tcl_desc_template { + u32 info4; + }; + ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++struct ath12k_link_vif_pvt { ++ struct ath12k_link_vif *arvif; ++ struct net_device *link_ndev; ++ struct net_device *bond_dev; ++ struct ieee80211_hw *hw; ++ bool is_started; ++ int ppe_vp_profile_idx; ++ int vp_num; ++}; ++#endif ++ + struct ath12k_link_vif { + struct ath12k_base *ab; + struct ath12k_dp *dp; +@@ -388,6 +400,12 @@ struct ath12k_link_vif { + u32 tx_vdev_id; + u8 link_id; + struct ath12k_vif *ahvif; ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++ struct ath12k_link_vif_pvt *ndev_pvt; ++ struct net_device *link_ndev; ++ int ppe_vp_type; ++ int ppe_vp_num; ++#endif + + bool mvr_processing; + bool pending_csa_up; +@@ -1112,6 +1130,10 @@ struct ath12k_soc_dp_stats { + u32 fw_tx_status[MAX_FW_TX_STATUS]; + u32 tx_enqueued[MAX_TCL_RING]; + u32 tx_completed[MAX_TCL_RING]; ++ u32 bond_tx_ucast_enqueued[MAX_TCL_RING]; ++ u32 bond_tx_mcast_enqueued[MAX_TCL_RING]; ++ u32 bond_tx_ucast_dropped[MAX_TCL_RING]; ++ u32 bond_tx_mcast_dropped[MAX_TCL_RING]; + u32 reo_rx[DP_REO_DST_RING_MAX] [ATH12K_MAX_SOCS]; + u32 fast_rx[DP_REO_DST_RING_MAX] [ATH12K_MAX_SOCS]; + u32 non_fast_rx[DP_REO_DST_RING_MAX] [ATH12K_MAX_SOCS]; +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -21,6 +21,10 @@ + #define ATH12K_DP_LMAC_PEER_ID_MLO 3 + #define ATH12K_DP_PEER_ROUTING_LMAC_ID_MASK GENMASK(7,6) + ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++extern int g_bonded_interface_model; ++#endif ++ + static void ath12k_dp_htt_htc_tx_complete(struct ath12k_base *ab, + struct sk_buff *skb) + { +@@ -62,6 +66,9 @@ int ath12k_dp_peer_default_route_setup(s + u32 reo_dest, param_value; + u32 lmac_peer_routing_id = ATH12K_DP_LMAC_PEER_ID_LEGACY; + int ret; ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++ struct ath12k_vif *ahvif = arvif->ahvif; ++#endif + + sta = container_of((void *)arsta->ahsta, struct ieee80211_sta, drv_priv); + +@@ -89,7 +96,8 @@ int ath12k_dp_peer_default_route_setup(s + hweight16(sta->valid_links)); + #ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT + /* keep last - override any PPE DS specific routing config */ +- ath12k_dp_peer_ppeds_route_setup(ar, arvif, arsta); ++ if ((ahvif->vdev_type == WMI_VDEV_TYPE_AP) && !((ahvif->vdev_type == WMI_VDEV_TYPE_AP) && (ahvif->vdev_subtype == WMI_VDEV_SUBTYPE_MESH_11S))) ++ ath12k_dp_peer_ppeds_route_setup(ar, arvif, arsta); + #endif + + return 0; +@@ -537,6 +545,9 @@ void ath12k_dp_tx_update_bank_profile(st + arvif->bank_id = ath12k_dp_tx_get_bank_profile(ab, arvif, dp); + arvif->desc.info0 = FIELD_PREP(HAL_TCL_DATA_CMD_INFO0_BANK_ID, + arvif->bank_id); ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++ ath12k_dp_ppeds_update_vp_entry(arvif->ar, arvif); ++#endif + } + + static void ath12k_dp_deinit_bank_profiles(struct ath12k_base *ab) +@@ -1174,11 +1185,15 @@ void ath12k_dp_pdev_pre_alloc(struct ath + } + } + ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT + static int ath12k_dp_ppe_rxole_rxdma_cfg(struct ath12k_base *ab) + { + struct ath12k_dp_htt_rxdma_ppe_cfg_param param = {0}; + int ret; + ++ if (!g_bonded_interface_model) ++ return 0; ++ + param.override = 1; + param.reo_dst_ind = HAL_REO2PPE_DST_IND; + param.multi_buffer_msdu_override_en = 0; +@@ -1195,6 +1210,7 @@ static int ath12k_dp_ppe_rxole_rxdma_cfg + + return ret; + } ++#endif + + int ath12k_dp_pdev_alloc(struct ath12k_base *ab) + { +@@ -1202,12 +1218,14 @@ int ath12k_dp_pdev_alloc(struct ath12k_b + int ret; + int i; + ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT + ret = ath12k_dp_ppe_rxole_rxdma_cfg(ab); + if (ret) { + ath12k_err(ab, "Failed to send htt RxOLE and RxDMA messages to target :%d\n", + ret); + goto out; + } ++#endif + + ret = ath12k_dp_rx_htt_setup(ab); + if (ret) +@@ -1319,6 +1337,10 @@ void ath12k_dp_vdev_tx_attach(struct ath + ath12k_err(ar->ab, "Failed to initialize DP TX Banks"); + return; + } ++ ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++ ath12k_dp_ppeds_update_vp_entry(ar, arvif); ++#endif + } + + static void ath12k_dp_cc_cleanup(struct ath12k_base *ab) +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -2767,6 +2767,10 @@ static bool ath12k_dp_rx_check_fast_rx(s + if (is_multicast_ether_addr(ehdr->h_dest)) + return false; + ++ /* TODO: make use of hw assisted intra-bss bit in msdu_end ++ * to skip peer lookup and forward frames directly. ++ */ ++ + /* check if the msdu needs to be bridged to our connected peer */ + f_peer = ath12k_peer_find_by_addr(ar->ab, ehdr->h_dest); + +@@ -2794,10 +2798,12 @@ static void ath12k_dp_rx_h_mpdu(struct a + struct ath12k_dp_rx_tid *rx_tid; + u32 err_bitmap; + u8 tid; +-#ifdef CPTCFG_MAC80211_PPE_SUPPORT ++#if defined(CPTCFG_MAC80211_PPE_SUPPORT) || defined(CPTCFG_ATH12K_BONDED_DS_SUPPORT) + int vp; + #endif + struct wireless_dev *wdev = NULL; ++ struct ath12k_vif *ahvif; ++ struct ath12k_link_vif *arvif; + + tid = ath12k_dp_rx_h_tid(ab, rx_desc); + /* PN for multicast packets will be checked in mac80211 */ +@@ -2828,8 +2834,16 @@ static void ath12k_dp_rx_h_mpdu(struct a + #endif + spin_unlock_bh(&ar->ab->base_lock); + ath12k_dp_rx_h_csum_offload(ar, msdu); +- msdu->dev = wdev->netdev; +-#ifdef CPTCFG_MAC80211_PPE_SUPPORT ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++ ahvif = (struct ath12k_vif *)peer->vif->drv_priv; ++ arvif = ahvif->link[peer->link_id]; ++ vp = arvif->ppe_vp_num; ++ if (wdev->bond_netdev) ++ msdu->dev = wdev->bond_netdev; ++ else ++#endif ++ msdu->dev = wdev->netdev; ++#if defined(CPTCFG_MAC80211_PPE_SUPPORT) || defined(CPTCFG_ATH12K_BONDED_DS_SUPPORT) + if (vp > 0) { + if (likely(ppe_vp_tx_to_ppe(vp, msdu))) + return; +@@ -2849,6 +2863,14 @@ static void ath12k_dp_rx_h_mpdu(struct a + } + spin_unlock_bh(&ar->ab->base_lock); + ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++ if (peer) { ++ wdev = ieee80211_vif_to_wdev(peer->vif); ++ if (wdev && wdev->bond_netdev) ++ msdu->dev = wdev->bond_netdev; ++ } ++#endif ++ + *fast_rx = false; + + err_bitmap = ath12k_dp_rx_h_mpdu_err(ab, rx_desc); +@@ -3368,8 +3390,9 @@ int ath12k_dp_rx_pkt_type_filter(struct + struct ath12k_wmi_pkt_route_param param; + int ret; + +- /* Routing Eapol packets to CCE is only allowed now */ +- if (pkt_type != ATH12K_PKT_TYPE_EAP) ++ /* Routing Eapol/ARP packets to CCE is only allowed now */ ++ if (pkt_type != ATH12K_PKT_TYPE_EAP && ++ pkt_type != ATH12K_PKT_TYPE_ARP_IPV4) + return -EINVAL; + + param.opcode = ATH12K_WMI_PKTROUTE_ADD; +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -273,6 +273,7 @@ int ath12k_dp_tx_direct(struct ath12k_li + u8 hal_ring_id, ring_id; + dma_addr_t paddr; + int ret; ++ int len = skb->fast_xmit ? 256 : skb->len; + + ring_id = smp_processor_id(); + +@@ -284,8 +285,8 @@ int ath12k_dp_tx_direct(struct ath12k_li + return -ENOSPC; + } + +- dmac_clean_range_no_dsb(skb->data, skb->data + 256); +- paddr = dma_map_single_attrs(dev, skb->data, 256, ++ dmac_clean_range_no_dsb(skb->data, skb->data + len); ++ paddr = dma_map_single_attrs(dev, skb->data, len, + DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); + if (unlikely(dma_mapping_error(dev, paddr))) { + atomic_inc(&ab->soc_stats.tx_err.misc_fail); +@@ -308,7 +309,7 @@ int ath12k_dp_tx_direct(struct ath12k_li + + hal_ring_id = ring_id + HAL_SRNG_RING_ID_SW2TCL1; + tcl_ring = &ab->hal.srng_list[hal_ring_id]; +- ++ spin_lock_bh(&tcl_ring->lock); + ath12k_hal_srng_access_src_ring_begin_nolock(tcl_ring); + + hal_tcl_desc = (void *)ath12k_hal_srng_src_get_next_entry_nolock(ab, tcl_ring); +@@ -317,6 +318,7 @@ int ath12k_dp_tx_direct(struct ath12k_li + * desc because the desc is directly enqueued onto hw queue. + */ + ath12k_hal_srng_access_umac_src_ring_end_nolock(tcl_ring); ++ spin_unlock_bh(&tcl_ring->lock); + ab->soc_stats.tx_err.desc_na[ring_id]++; + ret = -ENOMEM; + goto fail_unmap_dma; +@@ -352,6 +354,7 @@ int ath12k_dp_tx_direct(struct ath12k_li + memcpy(hal_tcl_desc, &tcl_desc, sizeof(tcl_desc)); + dsb(st); + ath12k_hal_srng_access_umac_src_ring_end_nolock(tcl_ring); ++ spin_unlock_bh(&tcl_ring->lock); + + atomic_inc(&ar->dp.num_tx_pending); + +@@ -591,7 +594,7 @@ int ath12k_dp_tx(struct ath12k *ar, stru + + hal_ring_id = tx_ring->tcl_data_ring.ring_id; + tcl_ring = &ab->hal.srng_list[hal_ring_id]; +- ++ spin_lock_bh(&tcl_ring->lock); + ath12k_hal_srng_access_src_ring_begin_nolock(tcl_ring); + hal_tcl_desc = ath12k_hal_srng_src_get_next_entry(ab, tcl_ring); + if (unlikely(!hal_tcl_desc)) { +@@ -599,6 +602,7 @@ int ath12k_dp_tx(struct ath12k *ar, stru + * desc because the desc is directly enqueued onto hw queue. + */ + ath12k_hal_srng_access_umac_src_ring_end_nolock(tcl_ring); ++ spin_unlock_bh(&tcl_ring->lock); + ab->soc_stats.tx_err.desc_na[ti.ring_id]++; + ret = -ENOMEM; + +@@ -637,6 +641,7 @@ int ath12k_dp_tx(struct ath12k *ar, stru + + dsb(st); + ath12k_hal_srng_access_umac_src_ring_end_nolock(tcl_ring); ++ spin_unlock_bh(&tcl_ring->lock); + + ath12k_dbg_dump(ab, ATH12K_DBG_DP_TX, NULL, "dp tx msdu: ", + skb->data, skb->len); +@@ -1184,6 +1189,70 @@ void ath12k_dp_ppeds_tx_comp_get_desc(st + } + } + ++static void ath12k_ppeds_tx_update_stats(struct ath12k *ar, struct sk_buff *msdu, ++ struct hal_wbm_release_ring *tx_status) ++{ ++ struct ath12k_base *ab = ar->ab; ++ struct ieee80211_tx_info *info; ++ struct ath12k_peer *peer; ++ struct ath12k_link_sta *arsta; ++ struct hal_tx_status ts = { 0 }; ++ ++ info = IEEE80211_SKB_CB(msdu); ++ memset(&info->status, 0, sizeof(info->status)); ++ info->status.rates[0].idx = -1; ++ ++ ath12k_dp_tx_status_parse(ab, tx_status, &ts); ++ if (ts.status == HAL_WBM_TQM_REL_REASON_FRAME_ACKED && ++ !(info->flags & IEEE80211_TX_CTL_NO_ACK)) { ++ info->flags |= IEEE80211_TX_STAT_ACK; ++ info->status.ack_signal = ATH12K_DEFAULT_NOISE_FLOOR + ++ ts.ack_rssi; ++ info->status.flags = IEEE80211_TX_STATUS_ACK_SIGNAL_VALID; ++ } ++ ++ if (ts.status == HAL_WBM_TQM_REL_REASON_CMD_REMOVE_TX && ++ (info->flags & IEEE80211_TX_CTL_NO_ACK)) ++ info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; ++ ++ if (ts.status != HAL_WBM_TQM_REL_REASON_FRAME_ACKED) { ++ switch (ts.status) { ++ case HAL_WBM_TQM_REL_REASON_CMD_REMOVE_MPDU: ++ case HAL_WBM_TQM_REL_REASON_DROP_THRESHOLD: ++ case HAL_WBM_TQM_REL_REASON_CMD_REMOVE_AGED_FRAMES: ++ case HAL_WBM_TQM_REL_REASON_CMD_REMOVE_TX: ++ return; ++ default: ++ //TODO: Remove this print and add as a stats ++ ath12k_dbg(ab, ATH12K_DBG_DP_TX, "tx frame is not acked status %d\n", ts.status); ++ } ++ } ++ ++ spin_lock_bh(&ab->base_lock); ++ ++ peer = ath12k_peer_find_by_id(ab, ts.peer_id); ++ if (unlikely(!peer || !peer->sta)) { ++ ath12k_dbg(ab, ATH12K_DBG_DATA, ++ "dp_tx: failed to find the peer with peer_id %d\n", ++ ts.peer_id); ++ spin_unlock_bh(&ab->base_lock); ++ return; ++ } ++ ++ arsta = ath12k_peer_get_link_sta(ab, peer); ++ if (!arsta) { ++ ath12k_warn(ab, "link sta not found on peer %pM id %d\n", ++ peer->addr, peer->peer_id); ++ spin_unlock_bh(&ab->base_lock); ++ return; ++ } ++ ++ ieee80211_ppeds_tx_update_stats(ar->ah->hw, peer->sta, info, arsta->txrate, ++ peer->link_id, msdu->len); ++ ++ spin_unlock_bh(&ab->base_lock); ++} ++ + int ath12k_ppeds_tx_completion_handler(struct ath12k_base *ab, int budget) + { + struct ath12k_dp *dp = &ab->dp; +@@ -1253,6 +1322,10 @@ int ath12k_ppeds_tx_completion_handler(s + + mac_id = tx_desc->mac_id; + ++ if (unlikely(!ab->stats_disable)) ++ ath12k_ppeds_tx_update_stats(ab->pdevs[mac_id].ar, tx_desc->skb, ++ tx_status); ++ + /* Release descriptor as soon as extracting necessary info + * to reduce contention + */ +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -23,7 +23,9 @@ + #include "testmode.h" + #include "peer.h" + #include "debugfs_sta.h" +-#include "ppe.h" ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++#include "bondif.h" ++#endif + + #define CHAN2G(_channel, _freq, _flags) { \ + .band = NL80211_BAND_2GHZ, \ +@@ -54,6 +56,14 @@ + + static void ath12k_mac_remove_link_interface(struct ieee80211_hw *hw, + struct ath12k_link_vif *arvif); ++ ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++int ath12k_mac_op_change_vif_links(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ u16 old_links, u16 new_links, ++ struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS]); ++extern int g_bonded_interface_model; ++#endif + static const struct ieee80211_channel ath12k_2ghz_channels[] = { + CHAN2G(1, 2412, 0), + CHAN2G(2, 2417, 0), +@@ -4775,8 +4785,14 @@ static int ath12k_mac_vdev_delete(struct + arvif->is_created = false; + + clean_up: +- arvif->ar = NULL; ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++ if (arvif->link_id != ATH12K_DEFAULT_SCAN_LINK && arvif->ndev_pvt) { ++ ath12k_bond_link_release(arvif); ++ ath12k_disable_ppe_for_link_netdev(arvif, arvif->ndev_pvt->link_ndev); ++ } ++#endif + ++ arvif->ar = NULL; + spin_lock_bh(&ar->data_lock); + list_del(&arvif->list); + spin_unlock_bh(&ar->data_lock); +@@ -4824,7 +4840,7 @@ void ath12k_mac_unassign_link_vif(struct + kfree(arvif); + } + +-static struct ath12k_link_vif * ++struct ath12k_link_vif * + ath12k_mac_assign_link_vif( struct ath12k_hw *ah, struct ieee80211_vif *vif, u8 link_id) + { + struct ath12k_vif *ahvif = (void *)vif->drv_priv; +@@ -5165,8 +5181,10 @@ static int ath12k_mac_op_hw_scan(struct + * delete-create vdev's for the same ar, in case the request is + * always on the same band for the vif + */ +- if (!arvif) ++ if (!arvif) { ++ mutex_unlock(&ah->conf_mutex); + return -ENOMEM; ++ } + + if (arvif->is_created) { + if (ar != arvif->ar && arvif->is_started) { +@@ -6114,6 +6132,15 @@ static int ath12k_station_assoc(struct a + return ret; + } + ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++ ret = ath12k_wmi_set_peer_intra_bss_cmd(ar, arvif->vdev_id, arsta->addr, 1); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to set vdev %i intra bss enable: %d\n", ++ arvif->vdev_id, ret); ++ return ret; ++ } ++#endif ++ + if (!sta->wme) { + arvif->num_legacy_stations++; + ret = ath12k_recalc_rtscts_prot(arvif); +@@ -8404,6 +8431,18 @@ static void ath12k_mgmt_over_wmi_tx_work + continue; + } + ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++ if (arvif->ndev_pvt && arvif->ndev_pvt->link_ndev) { ++ if (skb->dev->flags & IFF_SLAVE) { ++ ath12k_warn(ar->ab, "invalid mgmt pkt rcvd for bonded slave iface %s\n", ++ skb->dev->name); ++ ath12k_dbg_dump(ar->ab, ATH12K_DBG_PPE, NULL, "Invalid skb: ", ++ skb->data, skb->len); ++ ath12k_mgmt_over_wmi_tx_drop(ar, skb); ++ continue; ++ } ++ } ++#endif + mutex_lock(&ar->conf_mutex); + if (ar->allocated_vdev_map & (1LL << arvif->vdev_id) && + arvif->is_started) { +@@ -8815,6 +8854,16 @@ static int ath12k_mac_config_mon_status_ + tlv_filter = ath12k_mac_mon_status_filter_default; + if (ath12k_debugfs_rx_filter(ar)) + tlv_filter.rx_filter = ath12k_debugfs_rx_filter(ar); ++ ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++ if (g_bonded_interface_model && ++ test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ar->ab->dev_flags)) ++ tlv_filter.rx_filter |= (HTT_RX_FILTER_TLV_FLAGS_PPDU_START | ++ HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS | ++ HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT | ++ HTT_RX_FILTER_TLV_FLAGS_PPDU_START_USER_INFO); ++#endif /* CPTCFG_ATH12K_BONDED_DS_SUPPORT */ ++ + } + + tlv_filter.offset_valid = false; +@@ -9054,15 +9103,24 @@ static int ath12k_mac_radio_start(struct + } + } + +- /* PPE DS requires eapol packets to be routed to wbm release ring */ +- if (test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ar->ab->dev_flags)) { ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++ /* program CCE rule for eapol packets to be routed to wbm release ring */ ++ if (g_bonded_interface_model) { + ret = ath12k_dp_rx_pkt_type_filter(ar, ATH12K_PKT_TYPE_EAP, + ATH12K_ROUTE_EAP_METADATA); + if (ret) { + ath12k_err(ar->ab, "failed to configure EAP pkt route: %d\n", ret); + goto err; + } ++ ++ ret = ath12k_dp_rx_pkt_type_filter(ar, ATH12K_PKT_TYPE_ARP_IPV4, ++ ATH12K_ROUTE_ARP_METADATA); ++ if (ret) { ++ ath12k_err(ar->ab, "failed to configure ARP pkt route: %d\n", ret); ++ goto err; ++ } + } ++#endif + + __ath12k_set_antenna(ar, ar->cfg_tx_chainmask, ar->cfg_rx_chainmask); + +@@ -9450,6 +9508,13 @@ static void ath12k_mac_update_vif_offloa + vif->offload_flags &= ~(IEEE80211_OFFLOAD_ENCAP_ENABLED | + IEEE80211_OFFLOAD_DECAP_ENABLED); + ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++ if (vif->type == NL80211_IFTYPE_AP && arvif->ndev_pvt ++ && (hweight16(vif->valid_links) > 1)) ++ vif->offload_flags |= (IEEE80211_OFFLOAD_ENCAP_ENABLED | ++ IEEE80211_OFFLOAD_DECAP_ENABLED); ++#endif ++ + if (vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED) + ahvif->tx_encap_type = ATH12K_HW_TXRX_ETHERNET; + else if (test_bit(ATH12K_FLAG_RAW_MODE, &ag->dev_flags)) +@@ -9560,6 +9625,11 @@ static int ath12k_mac_vdev_create(struct + struct peer_create_params peer_param = {0}; + struct ieee80211_bss_conf *link_conf; + u32 param_id, param_value; ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++ struct wireless_dev *wdev = ieee80211_vif_to_wdev(vif); ++ struct net_device *link_ndev = NULL; ++ struct ath12k_link_vif_pvt *link_ndev_pvt = NULL; ++#endif + u16 nss; + int i; + int ret, fbret, vdev_id; +@@ -9626,6 +9696,16 @@ static int ath12k_mac_vdev_create(struct + arvif->dp = &ab->dp; + arvif->dev = ab->dev; + arvif->pdev_idx = ar->pdev_idx; ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++ if (arvif->link_id != ATH12K_DEFAULT_SCAN_LINK) { ++ link_ndev = vif->link_ndev[link_id]; ++ if (link_ndev) { ++ link_ndev_pvt = netdev_priv(link_ndev); ++ link_ndev_pvt->arvif = arvif; ++ arvif->ndev_pvt = link_ndev_pvt; ++ } ++ } ++#endif + + switch (vif->type) { + case NL80211_IFTYPE_UNSPECIFIED: +@@ -9717,6 +9797,20 @@ static int ath12k_mac_vdev_create(struct + arvif->vdev_id, ret); + goto err_peer_del; + } ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++ if (arvif->link_id != ATH12K_DEFAULT_SCAN_LINK) { ++ if (hweight16(vif->valid_links) <= 1) { ++ ath12k_free_bonddev_for_sfe(wdev, vif, link_id); ++ arvif->ndev_pvt = NULL; ++ arvif->ppe_vp_num = -1; ++ } ++ else if (link_ndev) { ++ ath12k_enable_ppe_for_link_netdev(arvif, ++ arvif->ndev_pvt->link_ndev); ++ ath12k_bond_link_enslave(arvif, arvif->ndev_pvt->link_ndev); ++ } ++ } ++#endif + break; + case WMI_VDEV_TYPE_STA: + param_id = WMI_STA_PS_PARAM_RX_WAKE_POLICY; +@@ -9785,6 +9879,16 @@ static int ath12k_mac_vdev_create(struct + test_bit(MONITOR_CONF_ENABLED, &ar->monitor_flags)) + ath12k_mac_monitor_vdev_create(ar); + ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++ ret = ath12k_wmi_send_vdev_set_intra_bss_cmd(ar, arvif->vdev_id, ++ 1); ++ if (ret) { ++ ath12k_warn(ab, "failed to set vdev %d intra bss enable :%d\n", ++ arvif->vdev_id, ret); ++ goto err_peer_del; ++ } ++#endif ++ + ret = ath12k_debugfs_add_interface(arvif); + if (ret) + goto err_peer_del; +@@ -10304,15 +10408,17 @@ static int ath12k_mac_op_ampdu_action(st + return ret; + } + +-static int ath12k_mac_op_change_vif_links(struct ieee80211_hw *hw, +- struct ieee80211_vif *vif, +- u16 old_links, u16 new_links, +- struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS]) ++#ifndef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++int ath12k_mac_op_change_vif_links(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ u16 old_links, u16 new_links, ++ struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS]) + { + ath12k_info(NULL, + "link changed for MLD %pM old %d new %d\n", vif->addr, old_links, new_links); + return 0; + } ++#endif + + static int ath12k_mac_op_add_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *ctx) +@@ -12137,6 +12243,7 @@ ath12k_mac_op_assign_vif_chanctx(struct + arvif = ath12k_mac_assign_link_vif(ah, vif, link_id); + if (!arvif) { + ath12k_err(NULL, "unable to allocate link vif\n"); ++ mutex_unlock(&ah->conf_mutex); + return -ENOMEM; + } + +@@ -14133,10 +14240,6 @@ static const struct ieee80211_ops ath12k + #endif + .get_txpower = ath12k_mac_op_get_txpower, + .set_radar_background = ath12k_mac_op_set_radar_background, +-#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT +- .ppeds_attach_vdev = ath12k_mac_op_ppeds_attach_vdev, +- .ppeds_detach_vdev = ath12k_mac_op_ppeds_detach_vdev, +-#endif + }; + + static void ath12k_mac_update_ch_list(struct ath12k *ar, +@@ -15320,6 +15423,9 @@ int ath12k_mac_allocate(struct ath12k_hw + goto err_mac_destroy; + } + ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ ieee80211_enable_bond_dev(hw); ++#endif + ah = hw->priv; + ah->hw = hw; + ah->ops = ops; +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -65,6 +65,15 @@ EXPORT_SYMBOL(ath12k_napi_poll_budget); + module_param_named(napi_budget, ath12k_napi_poll_budget, uint, 0644); + MODULE_PARM_DESC(napi_budget, "Napi budget processing per rx intr"); + ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++extern int ath12k_mlo_capable; ++extern int g_bonded_interface_model; ++extern unsigned int ath12k_ppe_ds_enabled; ++ ++extern int ath12k_bond_dev_cb(struct wireless_dev *wdev, struct net_device *dev, bool is_register); ++extern int (*driver_bond_dev_cb)(struct wireless_dev *wdev, struct net_device *dev, bool is_register); ++#endif ++ + static const struct pci_device_id ath12k_pci_id_table[] = { + { PCI_VDEVICE(QCOM, QCN9274_DEVICE_ID) }, + { PCI_VDEVICE(QCOM, WCN7850_DEVICE_ID) }, +@@ -1369,7 +1378,24 @@ static int ath12k_pci_probe(struct pci_d + struct ath12k_pci *ab_pci; + u32 soc_hw_version_major, soc_hw_version_minor, addr; + int ret; ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++ if (ath12k_frame_mode == ATH12K_HW_TXRX_RAW || ++ ath12k_frame_mode == ATH12K_HW_TXRX_NATIVE_WIFI) { ++ ath12k_mlo_capable = 1; ++ } ++ ++ if (ath12k_mlo_capable == 2) { ++ ath12k_mlo_capable = 1; ++ g_bonded_interface_model = ath12k_mlo_capable; ++ ath12k_ppe_ds_enabled = 1; ++ driver_bond_dev_cb = ath12k_bond_dev_cb; ++ } else if (ath12k_mlo_capable == 1 && g_bonded_interface_model != 1){ ++ g_bonded_interface_model = 0; ++ driver_bond_dev_cb = NULL; ++ } + ++ ath12k_info(NULL, "g_bonded_interface_model %d ath12k_mlo_capable %d \n", g_bonded_interface_model, ath12k_mlo_capable); ++#endif + ab = ath12k_core_alloc(&pdev->dev, sizeof(*ab_pci), ATH12K_BUS_PCI, + &ath12k_pci_bus_params); + if (!ab) { +@@ -1588,4 +1614,8 @@ int ath12k_pci_init(void) + void ath12k_pci_exit(void) + { + pci_unregister_driver(&ath12k_pci_driver); ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++ g_bonded_interface_model = 0; ++ driver_bond_dev_cb = NULL; ++#endif + } +--- a/drivers/net/wireless/ath/ath12k/ppe.c ++++ b/drivers/net/wireless/ath/ath12k/ppe.c +@@ -13,10 +13,15 @@ + #include + #include + #include ++#include + #include "hif.h" + #include "ppe.h" + ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++extern int g_bonded_interface_model; ++#endif + static atomic_t num_ppeds_nodes; ++ + extern struct sk_buff * + ath12k_dp_ppeds_tx_release_desc_nolock(struct ath12k_dp *dp, + struct ath12k_ppeds_tx_desc_info *tx_desc, +@@ -430,14 +435,49 @@ void ath12k_dp_peer_ppeds_route_setup(st + struct ath12k_link_sta *arsta) + { + struct ath12k_base *ab = ar->ab; ++ struct ath12k_link_vif *primary_link_arvif; ++ struct ath12k_vif *ahvif = arvif->ahvif; + u32 service_code = PPE_DRV_SC_SPF_BYPASS; + int ppe_routing_enable = 1; +- u32 priority_valid = 0, src_info = arvif->vif->ppe_vp_num; ++ u32 priority_valid = 0, src_info = arvif->ppe_vp_num; ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; ++ ++ if (!g_bonded_interface_model) ++ return; ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + +- if (!test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ab->dev_flags) || +- src_info == -1) ++ /* In SLO AP, DS is not supported */ ++ if (hweight16(ahvif->vif->valid_links) <= 1) + return; + ++ /* When SLO STA is associated to AP link vif which does not have DS rings, ++ * do not enable DS. ++ */ ++ if (!sta->mlo && !test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ab->dev_flags)) ++ return; ++ ++ /* If STA is MLO capable but primary link does not support DS, ++ * disable DS routing on RX. ++ */ ++ if (sta->mlo) { ++ primary_link_arvif = arvif->ahvif->link[ahsta->assoc_link_id]; ++ ++ if (primary_link_arvif->ppe_vp_num == -1 || ++ primary_link_arvif->ppe_vp_type != PPE_VP_USER_TYPE_DS) { ++ ath12k_info(ab, ++ "Primary link %d does not support DS " ++ "Disabling DS routing on RX for peer %pM\n", ++ ahsta->assoc_link_id, arsta->addr); ++ return; ++ } ++ ++ if (arvif->ppe_vp_num == -1 || ++ arvif->ppe_vp_type != PPE_VP_USER_TYPE_DS) ++ src_info = primary_link_arvif->ppe_vp_num; ++ } ++ + ath12k_wmi_config_peer_ppeds_routing(ar, arsta->addr, arvif->vdev_id, + service_code, priority_valid, src_info, + ppe_routing_enable); +@@ -455,8 +495,6 @@ static int ath12k_dp_ppeds_alloc_ppe_vp_ + return -ENOSR; + } + +- ab->num_ppe_vp_profiles++; +- + for (i = 0; i < PPE_VP_ENTRIES_MAX; i++) { + if (!ab->dp.ppe_vp_profile[i].is_configured) + break; +@@ -464,8 +502,10 @@ static int ath12k_dp_ppeds_alloc_ppe_vp_ + + if (i == PPE_VP_ENTRIES_MAX) { + WARN_ONCE(1, "All ppe vp profile entries are in use!"); ++ mutex_unlock(&ab->ppe_vp_tbl_lock); + return -ENOSR; + } ++ ab->num_ppe_vp_profiles++; + + ab->dp.ppe_vp_profile[i].is_configured = true; + *vp_profile = &ab->dp.ppe_vp_profile[i]; +@@ -507,8 +547,6 @@ static int ath12k_dp_ppeds_alloc_vp_tbl_ + return -ENOSR; + } + +- ab->num_ppe_vp_entries++; +- + for (i = 0; i < PPE_VP_ENTRIES_MAX; i++) { + if (!ab->ppe_vp_tbl_registered[i]) + break; +@@ -519,7 +557,8 @@ static int ath12k_dp_ppeds_alloc_vp_tbl_ + return -ENOSR; + } + +- ab->ppe_vp_tbl_registered[i] = true; ++ ab->num_ppe_vp_entries++; ++ ab->ppe_vp_tbl_registered[i] = 1; + mutex_unlock(&ab->ppe_vp_tbl_lock); + + return i; +@@ -544,7 +583,7 @@ static void ath12k_dp_ppeds_dealloc_vp_t + return; + } + +- ab->ppe_vp_tbl_registered[ppe_vp_num_idx] = false; ++ ab->ppe_vp_tbl_registered[ppe_vp_num_idx] = 0; + ab->num_ppe_vp_entries--; + mutex_unlock(&ab->ppe_vp_tbl_lock); + } +@@ -560,7 +599,6 @@ static int ath12k_dp_ppeds_alloc_vp_sear + return -ENOSR; + } + +- ab->num_ppe_vp_search_idx_entries++; + + for (i = 0; i < PPE_VP_ENTRIES_MAX; i++) { + if (!ab->ppe_vp_search_idx_tbl_set[i]) +@@ -572,7 +610,8 @@ static int ath12k_dp_ppeds_alloc_vp_sear + return -ENOSR; + } + +- ab->ppe_vp_search_idx_tbl_set[i] = true; ++ ab->num_ppe_vp_search_idx_entries++; ++ ab->ppe_vp_search_idx_tbl_set[i] = 1; + mutex_unlock(&ab->ppe_vp_tbl_lock); + + return i; +@@ -596,7 +635,7 @@ ath12k_dp_ppeds_dealloc_vp_search_idx_tb + return; + } + +- ab->ppe_vp_search_idx_tbl_set[ppe_vp_search_idx] = false; ++ ab->ppe_vp_search_idx_tbl_set[ppe_vp_search_idx] = 0; + ab->num_ppe_vp_search_idx_entries--; + mutex_unlock(&ab->ppe_vp_tbl_lock); + +@@ -639,38 +678,65 @@ static void ath12k_dp_ppeds_setup_vp_ent + return; + } + +-int ath12k_mac_op_ppeds_attach_vdev(struct ieee80211_hw *hw, +- struct ieee80211_vif *vif, ++void ath12k_dp_ppeds_update_vp_entry(struct ath12k *ar, ++ struct ath12k_link_vif *arvif) ++{ ++ struct ath12k_base *ab = ar->ab; ++ struct ath12k_link_vif_pvt *link_ndev_pvt = arvif->ndev_pvt; ++ struct ath12k_dp_ppe_vp_profile *vp_profile; ++ int ppe_vp_profile_idx; ++ ++ if (!test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ab->dev_flags)) ++ return; ++ ++ if (!ab->ppeds_handle) { ++ ath12k_dbg(ab, ATH12K_DBG_PPE, "DS not enabled on this chip\n"); ++ return; ++ } ++ ++ if (!link_ndev_pvt) { ++ ath12k_dbg(ab, ATH12K_DBG_PPE, "link netdevice not present for arvif\n"); ++ return; ++ } ++ ++ ppe_vp_profile_idx = link_ndev_pvt->ppe_vp_profile_idx; ++ vp_profile = &ab->dp.ppe_vp_profile[ppe_vp_profile_idx]; ++ if (!vp_profile) { ++ ath12k_dbg(ab, ATH12K_DBG_PPE, "vp profile not present for arvif\n"); ++ return; ++ } ++ ++ ath12k_dp_ppeds_setup_vp_entry(ab, arvif->ar, arvif, vp_profile); ++} ++ ++int ath12k_mac_op_ppeds_attach_vdev(struct ath12k_link_vif *arvif, + void *vp_arg, int *ppe_vp_num, + struct ieee80211_ppe_vp_ds_params *vp_params) + { +- struct ath12k_hw *ah = hw->priv; +- struct ath12k_vif *ahvif = (void *)vif->drv_priv; + //TODO: handle MLO +- struct ath12k_link_vif *arvif = &ahvif->link[0]; +- struct ath12k *ar = ah->radio; ++ struct ath12k *ar = arvif->ar; + //TODO: Handle split phy + struct ath12k_base *ab = ar->ab; + struct ath12k_dp_ppe_vp_profile *vp_profile = NULL; +- int ppe_vp_profile_idx, ppe_vp_idx, vp_num; ++ struct ath12k_link_vif_pvt *link_ndev_pvt = NULL; ++ int ppe_vp_profile_idx, ppe_vp_tbl_idx, vp_num; + int ppe_vp_search_tbl_idx = -1; + int vdev_id = arvif->vdev_id; + int ret; + +- if (!test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ab->dev_flags)) { +- ppe_vp_num = -1; ++ if (!test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ab->dev_flags)) + return -ENOSR; +- } + + if (!ab->ppeds_handle) { + ath12k_err(ab, "DS not enabled on this chip\n"); + return -EINVAL; + } + +- if (vif->type != NL80211_IFTYPE_AP) { ++ if (arvif->ahvif->vif->type != NL80211_IFTYPE_AP) { + return -EINVAL; + } + ++ link_ndev_pvt = netdev_priv(vp_params->dev); + vp_num = ppe_ds_wlan_vp_alloc(ab->ppeds_handle, vp_params->dev, vp_arg); + if (vp_num < 0) { + ath12k_err(ab," vp alloc failed\n"); +@@ -685,14 +751,14 @@ int ath12k_mac_op_ppeds_attach_vdev(stru + goto vp_free; + } + +- ppe_vp_idx = ath12k_dp_ppeds_alloc_vp_tbl_entry(ab); +- if (ppe_vp_idx < 0) { ++ ppe_vp_tbl_idx = ath12k_dp_ppeds_alloc_vp_tbl_entry(ab); ++ if (ppe_vp_tbl_idx < 0) { + ath12k_err(ab, "Failed to allocate PPE VP idx for vdev_id:%d", vdev_id); + ret = -ENOSR; + goto dealloc_vp_profile; + } + +- if (vif->type == NL80211_IFTYPE_STATION) { ++ if (arvif->ahvif->vif->type == NL80211_IFTYPE_STATION) { + ppe_vp_search_tbl_idx = ath12k_dp_ppeds_alloc_vp_search_idx_tbl_entry(ab); + if (ppe_vp_search_tbl_idx < 0) { + ath12k_err(ab, +@@ -704,19 +770,23 @@ int ath12k_mac_op_ppeds_attach_vdev(stru + } + + vp_profile->vp_num = vp_num; +- vp_profile->ppe_vp_num_idx = ppe_vp_idx; ++ vp_profile->ppe_vp_num_idx = ppe_vp_tbl_idx; + vp_profile->to_fw = 0; + vp_profile->use_ppe_int_pri = 0; + vp_profile->drop_prec_enable = 0; ++ vp_profile->arvif = arvif; + + /* For the sta mode fill up the index reg number */ + ath12k_dp_ppeds_setup_vp_entry(ab, ar, arvif, vp_profile); + + vp_params->ppe_vp_profile_idx = ppe_vp_profile_idx; + *ppe_vp_num = vp_num; +- ath12k_dbg(ab, ATH12K_DBG_PPE, +- "PPEDS vdev attach success vpnum %d ppe_vp_idx %d ppe_vp_profile_idx %d\n", +- vp_num, ppe_vp_idx, ppe_vp_profile_idx); ++ ath12k_info(ab, ++ "PPEDS vdev attach success chip_id %d vdev_id %d vpnum %d ppe_vp_profile_idx %d" ++ "ppe_vp_tbl_idx %d to_fw %d int_pri %d prec_en %d search_idx_reg_num %d\n", ++ ab->chip_id, vdev_id, vp_num, ppe_vp_profile_idx, ppe_vp_tbl_idx, vp_profile->to_fw, ++ vp_profile->use_ppe_int_pri, vp_profile->drop_prec_enable, ++ vp_profile->search_idx_reg_num); + + return 0; + +@@ -730,22 +800,17 @@ vp_free: + return ret; + } + +-void ath12k_mac_op_ppeds_detach_vdev(struct ieee80211_hw *hw, +- struct ieee80211_vif *vif, ++void ath12k_mac_op_ppeds_detach_vdev(struct ath12k_link_vif *arvif, + struct ieee80211_ppe_vp_ds_params *vp_params) + { +- struct ath12k_hw *ah = hw->priv; +- struct ath12k *ar = ah->radio; ++ struct ath12k *ar = arvif->ar; + struct ath12k_base *ab = ar->ab; +- struct ath12k_vif *ahvif = (void *)vif->drv_priv; +- struct ath12k_link_vif *arvif = &ahvif->link[0]; + struct ath12k_dp_ppe_vp_profile *vp_profile; + int ppe_vp_profile_idx = -1; + + if (!test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ab->dev_flags)) + return; + +- ath12k_dbg(ab, ATH12K_DBG_PPE, "PPEDS vdev detach\n"); + ppe_vp_profile_idx = vp_params->ppe_vp_profile_idx; + + vp_profile = &ab->dp.ppe_vp_profile[ppe_vp_profile_idx]; +@@ -759,7 +824,7 @@ void ath12k_mac_op_ppeds_detach_vdev(str + ath12k_dbg(ab, ATH12K_DBG_PPE, "ppe_ds_wlan_vp_free\n"); + + /* For STA mode ast index table reg also needs to be cleaned */ +- if (vif->type == NL80211_IFTYPE_STATION) ++ if (arvif->ahvif->vif->type == NL80211_IFTYPE_STATION) + ath12k_dp_ppeds_dealloc_vp_search_idx_tbl_entry(ab, vp_profile->search_idx_reg_num); + + ath12k_dp_ppeds_dealloc_vp_tbl_entry(ab, vp_profile->ppe_vp_num_idx); +--- a/drivers/net/wireless/ath/ath12k/ppe.h ++++ b/drivers/net/wireless/ath/ath12k/ppe.h +@@ -6,16 +6,6 @@ + #ifndef ATH12K_PPE_H + #define ATH12K_PPE_H + +-struct ath12k_dp_ppe_vp_profile { +- bool is_configured; +- u8 vp_num; +- u8 ppe_vp_num_idx; +- u8 search_idx_reg_num; +- u8 drop_prec_enable; +- u8 to_fw; +- u8 use_ppe_int_pri; +-}; +- + #define ATH12K_PPEDS_DEFAULT_POOL_ID 0 + + #ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT +@@ -26,18 +16,18 @@ void ath12k_dp_ppeds_stop(struct ath12k_ + int ath12k_dp_ppeds_start(struct ath12k_base *ab); + int ath12k_ppeds_detach( struct ath12k_base *ab); + int ath12k_ppeds_attach( struct ath12k_base *ab); +-int ath12k_mac_op_ppeds_attach_vdev(struct ieee80211_hw *hw, +- struct ieee80211_vif *vif, +- void *vp_arg, int *ppe_vp_num, +- struct ieee80211_ppe_vp_ds_params *vp_params); +-void ath12k_mac_op_ppeds_detach_vdev(struct ieee80211_hw *hw, +- struct ieee80211_vif *vif, +- struct ieee80211_ppe_vp_ds_params *vp_params); ++int ath12k_mac_op_ppeds_attach_vdev(struct ath12k_link_vif *arvif, ++ void *vp_arg, int *ppe_vp_num, ++ struct ieee80211_ppe_vp_ds_params *vp_params); ++void ath12k_mac_op_ppeds_detach_vdev(struct ath12k_link_vif *arvif, ++ struct ieee80211_ppe_vp_ds_params *vp_params); + void ath12k_dp_peer_ppeds_route_setup(struct ath12k *ar, struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta); + void *ath12k_dp_get_ppe_ds_ctxt(struct ath12k_base *ab); + irqreturn_t ath12k_ds_ppe2tcl_irq_handler(int irq, void *ctxt); + irqreturn_t ath12k_ds_reo2ppe_irq_handler(int irq, void *ctxt); + irqreturn_t ath12k_dp_ppeds_handle_tx_comp(int irq, void *ctxt); ++void ath12k_dp_ppeds_update_vp_entry(struct ath12k *ar, ++ struct ath12k_link_vif *arvif); + #endif + #endif +--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c ++++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c +@@ -3824,7 +3824,7 @@ struct wireless_dev *ath6kl_interface_ad + + netdev_set_default_ethtool_ops(ndev, &ath6kl_ethtool_ops); + +- if (cfg80211_register_netdevice(ndev)) ++ if (cfg80211_register_netdevice(ndev, 0)) + goto err; + + ar->avail_idx_map &= ~BIT(fw_vif_idx); +--- a/drivers/net/wireless/ath/wil6210/netdev.c ++++ b/drivers/net/wireless/ath/wil6210/netdev.c +@@ -432,7 +432,7 @@ int wil_vif_add(struct wil6210_priv *wil + if (rc) + return rc; + } +- rc = cfg80211_register_netdevice(ndev); ++ rc = cfg80211_register_netdevice(ndev, 0); + if (rc < 0) { + dev_err(&ndev->dev, "Failed to register netdev: %d\n", rc); + if (any_active && vif->mid != 0) +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -6064,6 +6064,7 @@ struct wireless_dev { + /* the remainder of this struct should be private to cfg80211 */ + struct list_head list; + struct net_device *netdev; ++ struct net_device *bond_netdev; + + u32 identifier; + +@@ -8748,7 +8749,7 @@ void cfg80211_unregister_wdev(struct wir + * + * Requires the RTNL and wiphy mutex to be held. + */ +-int cfg80211_register_netdevice(struct net_device *dev); ++int cfg80211_register_netdevice(struct net_device *dev, bool mlo_bond_dev); + + /** + * cfg80211_unregister_netdevice - unregister the given netdev +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -1965,7 +1965,11 @@ struct ieee80211_vif { + + bool txqs_stopped[IEEE80211_NUM_ACS]; + bool noqueue_enable; +- ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ bool bond_init; ++ struct mutex bond_mutex; ++ struct net_device *link_ndev[IEEE80211_MLD_MAX_NUM_LINKS]; ++#endif + #ifdef CPTCFG_MAC80211_PPE_SUPPORT + int ppe_vp_num; + unsigned long ppe_vp_type; +@@ -4715,6 +4719,10 @@ struct ieee80211_hw *ieee80211_alloc_hw( + return ieee80211_alloc_hw_nm(priv_data_len, ops, NULL); + } + ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++void ieee80211_enable_bond_dev(struct ieee80211_hw *hw); ++#endif ++ + /** + * ieee80211_register_hw - Register hardware device + * +@@ -4936,6 +4944,11 @@ void ieee80211_rx_list(struct ieee80211_ + struct sk_buff *skb, struct sk_buff_head *list); + #endif + ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++void ieee80211_rx_update_stats(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, ++ int link_id, u32 len, struct ieee80211_rx_status *status); ++#endif /* CPTCFG_MAC80211_BONDED_SUPPORT */ ++ + /** + * ieee80211_rx_napi - receive frame from NAPI context + * +@@ -5314,6 +5327,32 @@ void ieee80211_tx_status_8023(struct iee + struct ieee80211_vif *vif, + struct sk_buff *skb); + ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++/** ++ * ieee80211_ppeds_tx_update_stats - update tx stats for PPE DS path ++ * ++ * Call this function for all transmitted data frames after their transmit ++ * completion. This callback should only be called for data frames which ++ * are using driver's (or hardware's) offload capability of encap/decap ++ * 802.11 frames. ++ * ++ * This function may not be called in IRQ context. Calls to this function ++ * for a single hardware must be synchronized against each other and all ++ * calls in the same tx status family. ++ * ++ * @hw: the hardware the frame was transmitted by ++ * @pubsta: the station to update the tx rate for. ++ * @info: tx status information ++ * @rate: tx rate information ++ * @link_id: link id ++ * @len: length ++ */ ++void ieee80211_ppeds_tx_update_stats(struct ieee80211_hw *hw, ++ struct ieee80211_sta *pubsta, ++ struct ieee80211_tx_info *info, ++ struct rate_info rate, int link_id, u32 len); ++#endif /* CPTCFG_MAC80211_BONDED_SUPPORT */ ++ + /** + * ieee80211_report_low_ack - report non-responding station + * +@@ -6294,6 +6333,15 @@ struct ieee80211_sta *ieee80211_find_sta + const u8 *localaddr); + + /** ++ * ieee80211_sta_get_dvlan_iface - get dynamic vlan interface ++ * ++ * @pubsta: the station ++ * ++ * Return: The interface if found. %NULL otherwire. ++ */ ++struct net_device *ieee80211_sta_get_dvlan_iface(struct ieee80211_sta *pubsta); ++ ++/** + * ieee80211_sta_block_awake - block station from waking up + * @hw: the hardware + * @pubsta: the station +--- a/include/uapi/linux/nl80211.h ++++ b/include/uapi/linux/nl80211.h +@@ -3498,6 +3498,9 @@ enum nl80211_iftype { + NL80211_IFTYPE_P2P_DEVICE, + NL80211_IFTYPE_OCB, + NL80211_IFTYPE_NAN, ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ NL80211_IFTYPE_DUMMY, ++#endif + + /* keep last */ + NUM_NL80211_IFTYPES, +--- a/local-symbols ++++ b/local-symbols +@@ -67,6 +67,7 @@ MAC80211_DEBUG_COUNTERS= + MAC80211_STA_HASH_MAX_SIZE= + MAC80211_NSS_SUPPORT= + MAC80211_PPE_SUPPORT= ++MAC80211_BONDED_SUPPORT= + WLAN= + PCMCIA_RAYCS= + PCMCIA_WL3501= +@@ -144,3 +145,4 @@ ATH12K_TRACING= + ATH12K_SPECTRAL= + ATH12K_PKTLOG= + ATH12K_PPE_DS_SUPPORT= ++ATH12K_BONDED_DS_SUPPORT= +--- a/net/mac80211/Kconfig ++++ b/net/mac80211/Kconfig +@@ -122,6 +122,24 @@ config MAC80211_PPE_SUPPORT + + If unsure, say N. + ++config MAC80211_BONDED_SUPPORT ++ bool "QTI mac80211 bonded support" ++ depends on ATH12K ++ default n ++ ---help--- ++ Enables Bonded support for ATH12K driver ++ ++ If unsure, say N. ++ ++config MAC80211_BONDED_SUPPORT ++ bool "QTI mac80211 bonded support" ++ depends on ATH12K ++ default n ++ ---help--- ++ Enables Bonded support for ATH12K driver ++ ++ If unsure, say N. ++ + config MAC80211_NOINLINE + bool "Do not inline TX/RX handlers" + depends on MAC80211_DEBUG_MENU +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -201,7 +201,11 @@ static struct wireless_dev *ieee80211_ad + struct ieee80211_sub_if_data *sdata; + int err; + +- err = ieee80211_if_add(local, name, name_assign_type, &wdev, type, params); ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ err = ieee80211_if_add(local, name, name_assign_type, &wdev, type, params, true); ++#else ++ err = ieee80211_if_add(local, name, name_assign_type, &wdev, type, params, false); ++#endif + if (err) + return ERR_PTR(err); + +@@ -225,6 +229,26 @@ static int ieee80211_del_iface(struct wi + return 0; + } + ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++static struct wireless_dev *ieee80211_dummy_add_iface(struct wiphy *wiphy, ++ const char *name, ++ unsigned char name_assign_type, ++ enum nl80211_iftype type, ++ struct vif_params *params) ++{ ++ return NULL; ++} ++static int ieee80211_dummy_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev) ++{ ++ return -EINVAL; ++} ++const struct cfg80211_ops mac80211_dummy_config_ops = { ++ .add_virtual_intf = ieee80211_dummy_add_iface, ++ .del_virtual_intf = ieee80211_dummy_del_iface, ++}; ++EXPORT_SYMBOL(mac80211_dummy_config_ops); ++#endif ++ + static int ieee80211_change_iface(struct wiphy *wiphy, + struct net_device *dev, + enum nl80211_iftype type, +@@ -549,6 +573,10 @@ static int ieee80211_add_key(struct wiph + } + + switch (sdata->vif.type) { ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ case NL80211_IFTYPE_DUMMY: ++ return 0; ++#endif + case NL80211_IFTYPE_STATION: + if (sdata->u.mgd.mfp != IEEE80211_MFP_DISABLED) + key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT; +@@ -1759,9 +1787,23 @@ static int ieee80211_stop_ap(struct wiph + + ieee80211_free_next_beacon(link); + ++ #ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ if (sdata->wdev.bond_netdev && sdata->wdev.bond_netdev->flags & IFF_UP) { ++ netif_stop_queue(sdata->wdev.bond_netdev); ++ netif_carrier_off(sdata->wdev.bond_netdev); ++ sdata->wdev.bond_netdev->flags &= ~IFF_UP; ++ } ++ ++ if (sdata->vif.link_ndev[link_id]) { ++ netif_stop_queue(sdata->vif.link_ndev[link_id]); ++ netif_carrier_off(sdata->vif.link_ndev[link_id]); ++ } ++#endif ++ + /* turn off carrier for this interface and dependent VLANs */ + list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) + netif_carrier_off(vlan->dev); ++ + netif_carrier_off(dev); + + /* remove beacon and probe response */ +--- a/net/mac80211/chan.c ++++ b/net/mac80211/chan.c +@@ -294,6 +294,10 @@ ieee80211_get_chanctx_vif_max_required_b + continue; + + switch (vif->type) { ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ case NL80211_IFTYPE_DUMMY: ++ return 0; ++#endif + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_AP_VLAN: + width = ieee80211_get_max_required_bw(sdata, link_id); +@@ -1231,6 +1235,10 @@ ieee80211_link_chanctx_reservation_compl + struct ieee80211_sub_if_data *sdata = link->sdata; + + switch (sdata->vif.type) { ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ case NL80211_IFTYPE_DUMMY: ++ return; ++#endif + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_MESH_POINT: +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -26,6 +26,9 @@ + #include + #include + #include ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++#include ++#endif + #include + #include + #include +@@ -1982,7 +1985,7 @@ void ieee80211_iface_exit(void); + int ieee80211_if_add(struct ieee80211_local *local, const char *name, + unsigned char name_assign_type, + struct wireless_dev **new_wdev, enum nl80211_iftype type, +- struct vif_params *params); ++ struct vif_params *params, bool mlo_bond_dev); + int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, + enum nl80211_iftype type); + void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata); +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -417,6 +417,16 @@ static void ieee80211_do_stop(struct iee + /* + * Stop TX on this interface first. + */ ++ #ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ for_each_set_bit(link_id, &sdata->vif.valid_links, IEEE80211_MLD_MAX_NUM_LINKS) { ++ if (sdata->vif.link_ndev[link_id]) ++ netif_tx_stop_all_queues(sdata->vif.link_ndev[link_id]); ++ } ++ ++ if (sdata->wdev.bond_netdev) ++ netif_tx_stop_all_queues(sdata->wdev.bond_netdev); ++ #endif ++ + if (sdata->dev) + netif_tx_stop_all_queues(sdata->dev); + +@@ -769,10 +779,24 @@ static int ieee80211_stop(struct net_dev + #ifdef CPTCFG_MAC80211_PPE_SUPPORT + struct ieee80211_ppe_vp_ds_params vp_params = {0}; + #endif ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ int link_id; ++#endif + + /* close dependent VLAN interfaces before locking wiphy */ + if (sdata->vif.type == NL80211_IFTYPE_AP) { + struct ieee80211_sub_if_data *vlan, *tmpsdata; ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ for_each_set_bit(link_id, &sdata->vif.valid_links, IEEE80211_MLD_MAX_NUM_LINKS) { ++ if (sdata->vif.link_ndev[link_id]) ++ dev_close(sdata->vif.link_ndev[link_id]); ++ } ++ ++ if (sdata->wdev.bond_netdev) { ++ if (sdata->wdev.bond_netdev) ++ dev_close(sdata->wdev.bond_netdev); ++ } ++#endif + + list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, + u.vlan.list) +@@ -787,7 +811,7 @@ static int ieee80211_stop(struct net_dev + #endif + + #ifdef CPTCFG_MAC80211_PPE_SUPPORT +- if (sdata->vif.ppe_vp_num != -1) { ++ if (ppe_vp_accel && sdata->vif.ppe_vp_num != -1) { + drv_ppeds_detach_vdev(sdata, &sdata->vif, &vp_params); + if (sdata->vif.ppe_vp_type != PPE_VP_USER_TYPE_DS) + ppe_vp_free(sdata->vif.ppe_vp_num); +@@ -1448,6 +1472,11 @@ int ieee80211_do_open(struct wireless_de + /* cannot happen */ + WARN_ON(1); + break; ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ case NL80211_IFTYPE_DUMMY: ++ return 0; ++ break; ++#endif + } + + if (local->open_count == 0) { +@@ -1947,6 +1976,11 @@ static void ieee80211_setup_sdata(struct + + /* and set some type-dependent values */ + sdata->vif.type = type; ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ mutex_init(&sdata->vif.bond_mutex); ++ sdata->vif.bond_init = true; ++#endif ++ + sdata->vif.p2p = false; + #ifdef CPTCFG_MAC80211_PPE_SUPPORT + sdata->vif.ppe_vp_num = -1; +@@ -2025,6 +2059,10 @@ static void ieee80211_setup_sdata(struct + case NUM_NL80211_IFTYPES: + WARN_ON(1); + break; ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ case NL80211_IFTYPE_DUMMY: ++ return; ++#endif + } + + /* need to do this after the switch so vif.type is correct */ +@@ -2288,7 +2326,7 @@ static void ieee80211_assign_perm_addr(s + int ieee80211_if_add(struct ieee80211_local *local, const char *name, + unsigned char name_assign_type, + struct wireless_dev **new_wdev, enum nl80211_iftype type, +- struct vif_params *params) ++ struct vif_params *params, bool mlo_bond_dev) + { + struct net_device *ndev = NULL; + struct ieee80211_sub_if_data *sdata = NULL; +@@ -2461,7 +2499,7 @@ int ieee80211_if_add(struct ieee80211_lo + #endif + } + +- ret = cfg80211_register_netdevice(ndev); ++ ret = cfg80211_register_netdevice(ndev, mlo_bond_dev); + if (ret) { + free_netdev(ndev); + return ret; +@@ -2492,7 +2530,9 @@ void ieee80211_if_remove(struct ieee8021 + synchronize_rcu(); + + cfg80211_unregister_wdev(&sdata->wdev); +- ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ mutex_destroy(&sdata->vif.bond_mutex); ++#endif + if (!sdata->dev) { + ieee80211_teardown_sdata(sdata); + kfree(sdata); +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -630,6 +630,17 @@ static const struct ieee80211_vht_cap ma + }, + }; + ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++void cfg80211_enable_bond_dev(struct wiphy *wiphy); ++void ieee80211_enable_bond_dev(struct ieee80211_hw *hw) ++{ ++ struct wiphy *wiphy = hw->wiphy; ++ cfg80211_enable_bond_dev(wiphy); ++ ++} ++EXPORT_SYMBOL(ieee80211_enable_bond_dev); ++#endif ++ + struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len, + const struct ieee80211_ops *ops, + const char *requested_name) +@@ -1494,8 +1505,14 @@ int ieee80211_register_hw(struct ieee802 + !ieee80211_hw_check(hw, NO_AUTO_VIF)) { + struct vif_params params = {0}; + ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ result = ieee80211_if_add(local, "wlan%d", NET_NAME_ENUM, NULL, ++ NL80211_IFTYPE_STATION, ¶ms, true); ++#else + result = ieee80211_if_add(local, "wlan%d", NET_NAME_ENUM, NULL, +- NL80211_IFTYPE_STATION, ¶ms); ++ NL80211_IFTYPE_STATION, ¶ms, false); ++#endif ++ + if (result) + wiphy_warn(local->hw.wiphy, + "Failed to add default virtual iface\n"); +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -2354,7 +2354,7 @@ void ieee80211_dfs_cac_timer_work(struct + dfs_cac_timer_work); + struct cfg80211_chan_def chandef = link->conf->chandef; + struct ieee80211_sub_if_data *sdata = link->sdata; +- ++ rtnl_lock(); + mutex_lock(&sdata->local->mtx); + + if (sdata->wdev.links[link->link_id].cac_started) { +@@ -2365,6 +2365,7 @@ void ieee80211_dfs_cac_timer_work(struct + } + + mutex_unlock(&sdata->local->mtx); ++ rtnl_unlock(); + } + + static bool +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2727,6 +2727,9 @@ static void ieee80211_netif_rx_ppe(struc + out: + skb->protocol = eth_type_trans(skb, sdata->dev); + skb->dev = sdata->dev; ++ if (sdata->wdev.bond_netdev) ++ skb->dev = sdata->wdev.bond_netdev; ++ + if (rx->napi) + napi_gro_receive(rx->napi, skb); + else +@@ -4793,6 +4796,59 @@ void ieee80211_check_fast_rx_iface(struc + mutex_unlock(&local->sta_mtx); + } + ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++void ieee80211_rx_update_stats(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, ++ int link_id, u32 len, struct ieee80211_rx_status *status) ++{ ++ struct sta_info *sta = container_of(pubsta, struct sta_info, sta); ++ struct link_sta_info *link_sta; ++ struct ieee80211_sta_rx_stats *stats; ++ ++ rcu_read_lock(); ++ if (link_id >= 0) { ++ link_sta = rcu_dereference(sta->link[link_id]); ++ if (WARN_ON_ONCE(!link_sta)) { ++ rcu_read_unlock(); ++ return; ++ } ++ } else { ++ link_sta = &sta->deflink; ++ } ++ ++ stats = &link_sta->rx_stats; ++ ++ if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) { ++ stats->last_signal = status->signal; ++ } ++ ++ if (status->chains) { ++ int i; ++ ++ stats->chains = status->chains; ++ for (i = 0; i < ARRAY_SIZE(status->chain_signal); i++) { ++ int signal = status->chain_signal[i]; ++ ++ if (!(status->chains & BIT(i))) ++ continue; ++ ++ stats->chain_signal_last[i] = signal; ++ } ++ } ++ ++ stats->last_rx = jiffies; ++ stats->last_rate = sta_stats_encode_rate(status); ++ ++ stats->fragments++; ++ stats->packets++; ++ ++ u64_stats_update_begin(&stats->syncp); ++ stats->bytes += len; ++ u64_stats_update_end(&stats->syncp); ++ rcu_read_unlock(); ++} ++EXPORT_SYMBOL(ieee80211_rx_update_stats); ++#endif /* CPTCFG_MAC80211_BONDED_SUPPORT */ ++ + static void ieee80211_rx_8023(struct ieee80211_rx_data *rx, + struct ieee80211_fast_rx *fast_rx, + int orig_len) +@@ -4802,6 +4858,9 @@ static void ieee80211_rx_8023(struct iee + struct sta_info *sta = rx->sta; + struct link_sta_info *link_sta; + struct sk_buff *skb = rx->skb; ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ struct wireless_dev *wdev = NULL; ++#endif + void *sa = skb->data + ETH_ALEN; + void *da = skb->data; + +@@ -4852,6 +4911,12 @@ static void ieee80211_rx_8023(struct iee + stats->packets++; + + skb->dev = fast_rx->dev; ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ wdev = (struct wireless_dev *)fast_rx->dev->ieee80211_ptr; ++ if (wdev && wdev->bond_netdev) { ++ skb->dev = wdev->bond_netdev; ++ } ++#endif + + ieee80211_rx_stats(fast_rx->dev, skb->len); + +@@ -4894,7 +4959,7 @@ static void ieee80211_rx_8023(struct iee + } + + #ifdef CPTCFG_MAC80211_PPE_SUPPORT +- if (rx->sdata->vif.ppe_vp_num) { ++ if (rx->sdata->vif.ppe_vp_num != -1) { + ieee80211_netif_rx_ppe(rx, skb); + atomic_inc(&sta->rx_netif_pkts); + return; +@@ -4902,6 +4967,10 @@ static void ieee80211_rx_8023(struct iee + #endif + /* deliver to local stack */ + skb->protocol = eth_type_trans(skb, fast_rx->dev); ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ if (wdev->bond_netdev) ++ skb->dev = wdev->bond_netdev; ++#endif + ieee80211_deliver_skb_to_local_stack(skb, rx); + } + +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -2415,6 +2415,10 @@ static int ieee80211_reconfig_link_bss(s + changed |= BSS_CHANGED_MU_GROUPS; + + switch (sdata->vif.type) { ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ case NL80211_IFTYPE_DUMMY: ++ return 0; ++#endif + case NL80211_IFTYPE_STATION: + changed |= BSS_CHANGED_PS; + changed &= ~BSS_CHANGED_IDLE; +@@ -4410,9 +4414,11 @@ ieee80211_dfs_radar_detected_processing( + } + mutex_unlock(&local->chanctx_mtx); + ++ rtnl_lock(); + wiphy_lock(local->hw.wiphy); + ieee80211_dfs_cac_cancel(local); + wiphy_unlock(local->hw.wiphy); ++ rtnl_unlock(); + + if (radar_chandef) + radar_chandef->radar_bitmap = radar_bitmap; +--- a/net/wireless/chan.c ++++ b/net/wireless/chan.c +@@ -683,6 +683,10 @@ int cfg80211_chandef_dfs_required(struct + return -EINVAL; + + switch (iftype) { ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ case NL80211_IFTYPE_DUMMY: ++ return 0; ++#endif + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_P2P_GO: +@@ -865,6 +869,10 @@ bool cfg80211_beaconing_iface_active(str + ASSERT_WDEV_LOCK(wdev); + + switch (wdev->iftype) { ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ case NL80211_IFTYPE_DUMMY: ++ return true; ++#endif + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_P2P_GO: + for_each_valid_link(wdev, link) { +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -22,6 +22,9 @@ + #include + #include + #include ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++#include ++#endif + #include + #include + #include "nl80211.h" +@@ -54,6 +57,16 @@ module_param(cfg80211_disable_40mhz_24gh + MODULE_PARM_DESC(cfg80211_disable_40mhz_24ghz, + "Disable 40MHz support in the 2.4GHz band"); + ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++int g_bonded_interface_model = 0; ++module_param(g_bonded_interface_model, bool, 0644); ++MODULE_PARM_DESC(g_bonded_interface_model, "g_bonded_interface_model"); ++EXPORT_SYMBOL(g_bonded_interface_model); ++ ++int (*driver_bond_dev_cb)(struct wireless_dev *wdev, struct net_device *dev, bool is_register); ++EXPORT_SYMBOL(driver_bond_dev_cb); ++#endif ++ + struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx) + { + struct cfg80211_registered_device *result = NULL, *rdev; +@@ -70,6 +83,15 @@ struct cfg80211_registered_device *cfg80 + return result; + } + ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++void cfg80211_enable_bond_dev(struct wiphy *wiphy) ++{ ++ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); ++ rdev->enable_bond_dev = 1; ++} ++EXPORT_SYMBOL(cfg80211_enable_bond_dev); ++#endif ++ + int get_wiphy_idx(struct wiphy *wiphy) + { + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); +@@ -1322,6 +1344,9 @@ static void _cfg80211_unregister_wdev(st + { + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); + unsigned int link_id; ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ bool skip_bond_netdev = false; ++#endif + + ASSERT_RTNL(); + lockdep_assert_held(&rdev->wiphy.mtx); +@@ -1336,6 +1361,19 @@ static void _cfg80211_unregister_wdev(st + sysfs_remove_link(&wdev->netdev->dev.kobj, "phy80211"); + if (unregister_netdev) + unregister_netdevice(wdev->netdev); ++ ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ if (wdev->bond_netdev) { ++ if (wdev->iftype == NL80211_IFTYPE_MESH_POINT || ++ wdev->iftype == NL80211_IFTYPE_MONITOR || ++ rdev->enable_bond_dev == 0 || wdev->iftype == NL80211_IFTYPE_STATION) ++ skip_bond_netdev = true; ++ if (!skip_bond_netdev && ++ g_bonded_interface_model && driver_bond_dev_cb) { ++ (*driver_bond_dev_cb)(wdev, wdev->netdev, false); ++ } ++ } ++#endif + } + + list_del_rcu(&wdev->list); +@@ -1423,6 +1461,10 @@ void __cfg80211_leave(struct cfg80211_re + cfg80211_stop_background_radar_detection(wdev); + + switch (wdev->iftype) { ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ case NL80211_IFTYPE_DUMMY: ++ return; ++#endif + case NL80211_IFTYPE_ADHOC: + __cfg80211_leave_ibss(rdev, dev, true); + break; +@@ -1556,22 +1598,29 @@ void cfg80211_register_wdev(struct cfg80 + if (wdev->netdev && + sysfs_create_link(&wdev->netdev->dev.kobj, &rdev->wiphy.dev.kobj, + "phy80211")) +- pr_err("failed to add phy80211 symlink to netdev!\n"); ++ pr_err("failed to add phy80211 symlink to netdev! name %s\n", wdev->netdev->name); + + nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE); + } + +-int cfg80211_register_netdevice(struct net_device *dev) ++int cfg80211_register_netdevice(struct net_device *dev, bool create_bond_dev) + { + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_registered_device *rdev; + int ret; ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ bool skip_bond_netdev = false; ++#endif + + ASSERT_RTNL(); + + if (WARN_ON(!wdev)) + return -EINVAL; + ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ if (wdev->iftype == NL80211_IFTYPE_DUMMY && !wdev->wiphy) ++ return 0; ++#endif + rdev = wiphy_to_rdev(wdev->wiphy); + + lockdep_assert_held(&rdev->wiphy.mtx); +@@ -1584,6 +1633,18 @@ int cfg80211_register_netdevice(struct n + goto out; + + cfg80211_register_wdev(rdev, wdev); ++ ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ if (wdev->iftype == NL80211_IFTYPE_MESH_POINT || ++ wdev->iftype == NL80211_IFTYPE_MONITOR || ++ rdev->enable_bond_dev == 0 || wdev->iftype == NL80211_IFTYPE_STATION) ++ skip_bond_netdev = true; ++ ++ if (!skip_bond_netdev && g_bonded_interface_model && ++ create_bond_dev && driver_bond_dev_cb) { ++ (*driver_bond_dev_cb)(wdev, dev, true); ++ } ++#endif + ret = 0; + out: + wdev->registering = false; +@@ -1604,6 +1665,11 @@ static int cfg80211_netdev_notifier_call + if (!wdev) + return NOTIFY_DONE; + ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ if (wdev->iftype == NL80211_IFTYPE_DUMMY && !wdev->wiphy) ++ return 0; ++#endif ++ + rdev = wiphy_to_rdev(wdev->wiphy); + + WARN_ON(wdev->iftype == NL80211_IFTYPE_UNSPECIFIED); +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -1608,6 +1608,10 @@ static int nl80211_key_allowed(struct wi + ASSERT_WDEV_LOCK(wdev); + + switch (wdev->iftype) { ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ case NL80211_IFTYPE_DUMMY: ++ return 0; ++#endif + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_AP_VLAN: + case NL80211_IFTYPE_P2P_GO: +@@ -10528,6 +10532,7 @@ static int nl80211_start_radar_detection + + flush_delayed_work(&rdev->dfs_update_channels_wk); + ++ rtnl_lock(); + wiphy_lock(wiphy); + wdev_lock(wdev); + +@@ -10614,6 +10619,7 @@ static int nl80211_start_radar_detection + unlock: + wdev_unlock(wdev); + wiphy_unlock(wiphy); ++ rtnl_unlock(); + + return err; + } +@@ -16972,9 +16978,16 @@ nl80211_remove_link_station(struct sk_bu + NL80211_FLAG_NEED_RTNL) \ + SELECTOR(__sel, NETDEV_UP, \ + NL80211_FLAG_NEED_NETDEV_UP) \ ++ SELECTOR(__sel, NETDEV_UP_RTNL, \ ++ NL80211_FLAG_NEED_RTNL | \ ++ NL80211_FLAG_NEED_NETDEV_UP) \ + SELECTOR(__sel, NETDEV_UP_LINK, \ + NL80211_FLAG_NEED_NETDEV_UP | \ + NL80211_FLAG_MLO_VALID_LINK_ID) \ ++ SELECTOR(__sel, NETDEV_UP_LINK_RTNL, \ ++ NL80211_FLAG_NEED_NETDEV_UP | \ ++ NL80211_FLAG_NEED_RTNL | \ ++ NL80211_FLAG_MLO_VALID_LINK_ID) \ + SELECTOR(__sel, NETDEV_UP_LINK_NOMTX, \ + NL80211_FLAG_NEED_NETDEV_UP | \ + NL80211_FLAG_NO_WIPHY_MTX | \ +@@ -17006,7 +17019,13 @@ nl80211_remove_link_station(struct sk_bu + NL80211_FLAG_NEED_RTNL) \ + SELECTOR(__sel, WIPHY_CLEAR, \ + NL80211_FLAG_NEED_WIPHY | \ +- NL80211_FLAG_CLEAR_SKB) ++ NL80211_FLAG_CLEAR_SKB) \ ++ SELECTOR(__sel, NETDEV_UP_LINK_NOMTX_RTNL, \ ++ NL80211_FLAG_NEED_NETDEV_UP | \ ++ NL80211_FLAG_NEED_RTNL | \ ++ NL80211_FLAG_NO_WIPHY_MTX | \ ++ NL80211_FLAG_MLO_VALID_LINK_ID) ++ + + enum nl80211_internal_flags_selector { + #define SELECTOR(_, name, value) NL80211_IFL_SEL_##name, +@@ -17369,6 +17388,7 @@ static const struct genl_small_ops nl802 + .flags = GENL_UNS_ADMIN_PERM, + .doit = nl80211_start_ap, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP | ++ NL80211_FLAG_NEED_RTNL | + NL80211_FLAG_MLO_VALID_LINK_ID), + }, + { +@@ -17377,6 +17397,7 @@ static const struct genl_small_ops nl802 + .flags = GENL_UNS_ADMIN_PERM, + .doit = nl80211_stop_ap, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP | ++ NL80211_FLAG_NEED_RTNL | + NL80211_FLAG_MLO_VALID_LINK_ID), + }, + { +@@ -17498,7 +17519,7 @@ static const struct genl_small_ops nl802 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = nl80211_trigger_scan, + .flags = GENL_UNS_ADMIN_PERM, +- .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP), ++ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP | NL80211_FLAG_NEED_RTNL), + }, + { + .cmd = NL80211_CMD_ABORT_SCAN, +@@ -18077,13 +18098,15 @@ static const struct genl_small_ops nl802 + .cmd = NL80211_CMD_ADD_LINK, + .doit = nl80211_add_link, + .flags = GENL_UNS_ADMIN_PERM, +- .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), ++ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP | ++ NL80211_FLAG_NEED_RTNL), + }, + { + .cmd = NL80211_CMD_REMOVE_LINK, + .doit = nl80211_remove_link, + .flags = GENL_UNS_ADMIN_PERM, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP | ++ NL80211_FLAG_NEED_RTNL | + NL80211_FLAG_MLO_VALID_LINK_ID), + }, + { +@@ -18091,6 +18114,7 @@ static const struct genl_small_ops nl802 + .doit = nl80211_add_link_station, + .flags = GENL_UNS_ADMIN_PERM, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP | ++ NL80211_FLAG_NEED_RTNL | + NL80211_FLAG_MLO_VALID_LINK_ID), + }, + { +--- a/net/wireless/util.c ++++ b/net/wireless/util.c +@@ -1113,6 +1113,10 @@ int cfg80211_change_iface(struct cfg8021 + if (!err) { + dev->priv_flags &= ~IFF_DONT_BRIDGE; + switch (ntype) { ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ case NL80211_IFTYPE_DUMMY: ++ return 0; ++#endif + case NL80211_IFTYPE_STATION: + if (dev->ieee80211_ptr->use_4addr) + break; +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -369,7 +369,7 @@ struct host_link_stats { + #define PPE_VP_ENTRIES_MAX 32 + #define MAX_PPEDS_IRQ_NAME_LEN 20 + #define MAX_PPEDS_IRQS 3 +-struct dp_ppe_vp_profile { ++struct ath12k_dp_ppe_vp_profile { + bool is_configured; + u8 vp_num; + u8 ppe_vp_num_idx; +@@ -377,6 +377,7 @@ struct dp_ppe_vp_profile { + u8 drop_prec_enable; + u8 to_fw; + u8 use_ppe_int_pri; ++ struct ath12k_link_vif *arvif; + }; + #endif + +@@ -449,7 +450,7 @@ struct ath12k_dp { + /* protects the free and used desc lists */ + spinlock_t ppeds_tx_desc_lock[ATH12K_HW_MAX_QUEUES_PPEDS]; + +- struct dp_ppe_vp_profile ppe_vp_profile[PPE_VP_ENTRIES_MAX]; ++ struct ath12k_dp_ppe_vp_profile ppe_vp_profile[PPE_VP_ENTRIES_MAX]; + char ppeds_irq_name[MAX_PPEDS_IRQS][MAX_PPEDS_IRQ_NAME_LEN]; + int ppeds_irq[MAX_PPEDS_IRQS]; + #endif +--- a/drivers/net/wireless/ath/ath12k/dp_rx.h ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.h +@@ -40,6 +40,7 @@ enum ath12k_routing_pkt_type { + #define ATH12K_RX_PROTOCOL_TAG_START_OFFSET 128 + #define ATH12K_ROUTE_WBM_RELEASE 3 + #define ATH12K_ROUTE_EAP_METADATA (ATH12K_RX_PROTOCOL_TAG_START_OFFSET + ATH12K_PKT_TYPE_EAP) ++#define ATH12K_ROUTE_ARP_METADATA (ATH12K_RX_PROTOCOL_TAG_START_OFFSET + ATH12K_PKT_TYPE_ARP_IPV4) + + struct ath12k_dp_rx_tid { + u8 tid; +--- a/drivers/net/wireless/ath/ath12k/hal.c ++++ b/drivers/net/wireless/ath/ath12k/hal.c +@@ -358,6 +358,13 @@ static u8 ath12k_hw_qcn9274_rx_desc_get_ + RX_MSDU_END_INFO5_TID); + } + ++static u8 ath12k_hw_qcn9274_rx_desc_get_msdu_intra_bss_bit(struct hal_rx_desc *desc) ++{ ++ /* TODO - msdu_end info9 */ ++ return 0; ++} ++ ++ + static u16 ath12k_hw_qcn9274_rx_desc_get_mpdu_peer_id(struct hal_rx_desc *desc) + { + return le16_get_bits(desc->u.qcn9274.mpdu_start.sw_peer_id, +@@ -696,6 +703,7 @@ const struct hal_ops hal_qcn9274_ops = { + .rx_desc_get_msdu_payload = ath12k_hw_qcn9274_rx_desc_get_msdu_payload, + .rx_desc_get_mpdu_start_offset = ath12k_hw_qcn9274_rx_desc_get_mpdu_start_offset, + .rx_desc_get_msdu_end_offset = ath12k_hw_qcn9274_rx_desc_get_msdu_end_offset, ++ .rx_desc_get_msdu_intra_bss_bit = ath12k_hw_qcn9274_rx_desc_get_msdu_intra_bss_bit, + .rx_desc_mac_addr2_valid = ath12k_hw_qcn9274_rx_desc_mac_addr2_valid, + .rx_desc_mpdu_start_addr2 = ath12k_hw_qcn9274_rx_desc_mpdu_start_addr2, + .rx_desc_is_mcbc = ath12k_hw_qcn9274_rx_desc_is_mcbc, +--- a/drivers/net/wireless/ath/ath12k/hal.h ++++ b/drivers/net/wireless/ath/ath12k/hal.h +@@ -1127,6 +1127,7 @@ struct hal_ops { + u8 *(*rx_desc_get_msdu_payload)(struct hal_rx_desc *desc); + u32 (*rx_desc_get_mpdu_start_offset)(void); + u32 (*rx_desc_get_msdu_end_offset)(void); ++ u8 (*rx_desc_get_msdu_intra_bss_bit)(struct hal_rx_desc *desc); + bool (*rx_desc_mac_addr2_valid)(struct hal_rx_desc *desc); + u8* (*rx_desc_mpdu_start_addr2)(struct hal_rx_desc *desc); + bool (*rx_desc_is_mcbc)(struct hal_rx_desc *desc); +--- a/drivers/net/wireless/ath/ath12k/rx_desc.h ++++ b/drivers/net/wireless/ath/ath12k/rx_desc.h +@@ -691,7 +691,7 @@ enum rx_msdu_start_reception_type { + + #define RX_MSDU_END_INFO9_SERVICE_CODE GENMASK(14, 6) + #define RX_MSDU_END_INFO9_PRIORITY_VALID BIT(15) +-#define RX_MSDU_END_INFO9_INRA_BSS BIT(16) ++#define RX_MSDU_END_INFO9_INTRA_BSS BIT(16) + #define RX_MSDU_END_INFO9_DEST_CHIP_ID GENMASK(18, 17) + #define RX_MSDU_END_INFO9_MCAST_ECHO BIT(19) + #define RX_MSDU_END_INFO9_WDS_LEARN_EVENT BIT(20) +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -1455,7 +1455,72 @@ int ath12k_wmi_config_peer_ppeds_routing + + return ret; + } +-#endif ++ ++int ++ath12k_wmi_send_vdev_set_intra_bss_cmd(struct ath12k *ar, ++ u32 vdev_id, u32 enable) ++{ ++ struct ath12k_pdev_wmi *wmi = ar->wmi; ++ struct ath12k_vdev_set_intra_bss_cmd *cmd; ++ struct sk_buff *skb; ++ int ret; ++ ++ skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(struct ath12k_vdev_set_intra_bss_cmd)); ++ if (!skb) ++ return -ENOMEM; ++ ++ cmd = (struct ath12k_vdev_set_intra_bss_cmd *)skb->data; ++ cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_VDEV_SET_INTRA_BSS_PARAMS, ++ sizeof(*cmd)); ++ cmd->vdev_id = vdev_id; ++ cmd->enable = enable; ++ ++ ret = ath12k_wmi_cmd_send(wmi, skb, WMI_VDEV_SET_INTRA_BSS_CMDID); ++ if (ret) { ++ ath12k_warn(ar->ab, ++ "failed to send WMI_VDEV_SET_INTRA_BSS_CMDID\n"); ++ dev_kfree_skb(skb); ++ } ++ ++ ath12k_dbg(ar->ab, ATH12K_DBG_WMI, ++ "WMI vdev id 0x%x set inra bss %s\n", ++ vdev_id, enable?"enable":"disable"); ++ ++ return ret; ++} ++ ++int ath12k_wmi_set_peer_intra_bss_cmd(struct ath12k *ar, u32 vdev_id, const u8 *peer_addr, ++ u32 enable) ++{ ++ struct ath12k_pdev_wmi *wmi = ar->wmi; ++ struct wmi_peer_set_intra_bss_cmd *cmd; ++ struct sk_buff *skb; ++ int ret; ++ ++ skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd)); ++ if (!skb) ++ return -ENOMEM; ++ ++ cmd = (struct wmi_peer_set_intra_bss_param_cmd *)skb->data; ++ cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PEER_SET_INTRA_BSS_PARAMS, ++ sizeof(*cmd)); ++ ether_addr_copy(cmd->peer_macaddr.addr, peer_addr); ++ cmd->vdev_id = cpu_to_le32(vdev_id); ++ cmd->enable = cpu_to_le32(enable); ++ ++ ret = ath12k_wmi_cmd_send(wmi, skb, WMI_PEER_SET_INTRA_BSS_CMDID); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to send WMI_PEER_SET_INTRA_BSS_CMD\n"); ++ dev_kfree_skb(skb); ++ } ++ ++ ath12k_dbg(ar->ab, ATH12K_DBG_WMI, ++ "WMI vdev %d peer 0x%pM set intra_bss %s\n", ++ vdev_id, peer_addr, enable ? "enable" : "disable"); ++ ++ return ret; ++} ++#endif /* CPTCFG_ATH12K_PPE_DS_SUPPORT */ + + int ath12k_wmi_send_pdev_pkt_route(struct ath12k *ar, + struct ath12k_wmi_pkt_route_param *param) +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -395,6 +395,8 @@ enum wmi_tlv_cmd_id { + WMI_VDEV_GET_BIG_DATA_P2_CMDID, + /** set TPC PSD/non-PSD power */ + WMI_VDEV_SET_TPC_POWER_CMDID, ++ WMI_VDEV_IGMP_OFFLOAD_CMDID, ++ WMI_VDEV_SET_INTRA_BSS_CMDID, + WMI_PEER_CREATE_CMDID = WMI_TLV_CMD(WMI_GRP_PEER), + WMI_PEER_DELETE_CMDID, + WMI_PEER_FLUSH_TIDS_CMDID, +@@ -426,6 +428,7 @@ enum wmi_tlv_cmd_id { + WMI_PEER_UNMAP_RESPONSE_CMDID, + WMI_PEER_CONFIG_VLAN_CMDID, + WMI_PEER_CONFIG_PPE_DS_CMDID, ++ WMI_PEER_SET_INTRA_BSS_CMDID, + WMI_BCN_TX_CMDID = WMI_TLV_CMD(WMI_GRP_MGMT), + WMI_PDEV_SEND_BCN_CMDID, + WMI_BCN_TMPL_CMDID, +@@ -2044,6 +2047,8 @@ enum wmi_tlv_tag { + WMI_TAG_MLO_PEER_CREATE_PARAMS = 0x3D5, + WMI_TAG_MLO_VDEV_START_PARAMS = 0x3D6, + WMI_TAG_MLO_VDEV_CREATE_PARAMS = 0x3D7, ++ WMI_TAG_VDEV_SET_INTRA_BSS_PARAMS = 0x3EE, ++ WMI_TAG_PEER_SET_INTRA_BSS_PARAMS, + WMI_TAG_PDEV_PKTLOG_DECODE_INFO = 0x414, + WMI_TAG_SPECTRAL_SCAN_BW_CAPABILITIES, + WMI_TAG_SPECTRAL_FFT_SIZE_CAPABILITIES, +@@ -3672,6 +3677,21 @@ struct wmi_peer_set_param_cmd { + __le32 param_value; + } __packed; + ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++struct wmi_peer_set_intra_bss_cmd { ++ __le32 tlv_header; ++ struct wmi_mac_addr peer_macaddr; ++ __le32 vdev_id; ++ __le32 enable; ++} __packed; ++ ++struct ath12k_vdev_set_intra_bss_cmd { ++ u32 tlv_header; ++ u32 vdev_id; ++ u32 enable; ++} __packed; ++#endif ++ + struct wmi_peer_flush_tids_cmd { + __le32 tlv_header; + __le32 vdev_id; +@@ -8417,6 +8437,13 @@ int + ath12k_mgmt_rx_reo_init_context(struct ath12k_base *ab); + int + ath12k_mgmt_rx_reo_deinit_context(struct ath12k_base *ab); ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++int ++ath12k_wmi_send_vdev_set_intra_bss_cmd(struct ath12k *ar, ++ u32 vdev_id, u32 enable); ++int ath12k_wmi_set_peer_intra_bss_cmd(struct ath12k *ar, u32 vdev_id, const u8 *peer_addr, ++ u32 enable); ++#endif + #ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT + int ath12k_wmi_config_peer_ppeds_routing(struct ath12k *ar, + const u8 *peer_addr, u8 vdev_id, +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -1581,12 +1581,14 @@ static ssize_t ath12k_debugfs_dump_soc_r + return len; + } + ++extern struct ath12k *ath12k_mac_get_ar_by_pdev_id(struct ath12k_base *ab, u32 pdev_id); + static ssize_t ath12k_debugfs_dump_soc_dp_stats(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) + { + struct ath12k_base *ab = file->private_data; + struct ath12k_soc_dp_stats *soc_stats = &ab->soc_stats; ++ struct ath12k *ar; + int len = 0, i, retval; + const int size = 4096; + static const char *rxdma_err[HAL_REO_ENTR_RING_RXDMA_ECODE_MAX] = { +@@ -1723,6 +1725,17 @@ static ssize_t ath12k_debugfs_dump_soc_d + soc_stats->tx_completed[2], + soc_stats->tx_completed[3]); + ++ for (i = 0; i < 3; i++) { ++ ++ ar = ath12k_mac_get_ar_by_pdev_id(ab, i); ++ if (ar) { ++ len += scnprintf(buf + len, size - len, ++ "\ntx_pending [%d]: 0:%d\n", ++ i, ++ atomic_read(&ar->dp.num_tx_pending)); ++ } ++ } ++ + len += scnprintf(buf + len, size - len, "\nREO Rx Received:\n"); + for (i = 0; i < DP_REO_DST_RING_MAX; i++) + len += scnprintf(buf + len, size - len, +--- a/net/wireless/core.h ++++ b/net/wireless/core.h +@@ -108,6 +108,9 @@ struct cfg80211_registered_device { + /* lock for all wdev lists */ + spinlock_t mgmt_registrations_lock; + ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++ bool enable_bond_dev; ++#endif + /* must be last because of the way we do wiphy_priv(), + * and it should at least be aligned to NETDEV_ALIGN */ + struct wiphy wiphy __aligned(NETDEV_ALIGN); +--- a/drivers/net/wireless/ath/ath12k/dp_mon.c ++++ b/drivers/net/wireless/ath/ath12k/dp_mon.c +@@ -10,6 +10,10 @@ + #include "dp_tx.h" + #include "peer.h" + ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++extern int g_bonded_interface_model; ++#endif ++ + static void ath12k_dp_mon_rx_handle_ofdma_info(void *rx_tlv, + struct hal_rx_user_status *rx_user_status) + { +@@ -3323,6 +3327,78 @@ ath12k_dp_mon_rx_update_peer_rate_table_ + rx_stats->byte_stats.rx_rate[bw_idx][gi_idx][nss_idx][mcs_idx] += ppdu_info->mpdu_len; + } + ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++static void ath12k_dp_mon_rx_update_peer_stats_bonded(struct ath12k *ar, ++ struct ath12k_link_sta *arsta, ++ struct hal_rx_mon_ppdu_info *ppdu_info, ++ struct ieee80211_rx_status *rx_status) ++{ ++ struct ieee80211_rx_status status; ++ struct ieee80211_sta *sta; ++ u32 uid; ++ ++ if (ar->ab->stats_disable || !g_bonded_interface_model || ++ !test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ar->ab->dev_flags)) ++ return; ++ ++ memset(&status, 0 , sizeof(status)); ++ if (arsta) { // SU stats ++ if (arsta->arvif && (arsta->arvif->ppe_vp_num == -1 || ++ (arsta->arvif->ahvif && ++ hweight16(arsta->arvif->ahvif->links_map) <= 1))) ++ return; ++ ++ if (!rx_status) { ++ ath12k_dp_mon_fill_rx_stats(ar, ppdu_info, &status); ++ rx_status = &status; ++ } ++ ++ sta = container_of((void *)arsta->ahsta, struct ieee80211_sta, drv_priv); ++ ieee80211_rx_update_stats(ar->ah->hw, sta, arsta->link_id, ++ ppdu_info->mpdu_len, rx_status); ++ return; ++ } ++ ++ for (uid = 0; uid < ppdu_info->num_users; uid++) { // MU stats ++ struct ath12k_peer *peer; ++ ++ if (uid == HAL_MAX_UL_MU_USERS) ++ break; ++ ++ if (ppdu_info->peer_id == HAL_INVALID_PEERID) ++ return; ++ peer = ath12k_peer_find_by_id(ar->ab, ppdu_info->peer_id); ++ ++ if (!peer) { ++ ath12k_warn(ar->ab, "peer with peer id %d can't be found\n", ++ ppdu_info->peer_id); ++ continue; ++ } ++ ++ arsta = ath12k_peer_get_link_sta(ar->ab, peer); ++ if (!arsta) { ++ ath12k_warn(ar->ab, "link sta not found on peer %pM id %d\n", ++ peer->addr, peer->peer_id); ++ continue; ++ } ++ ++ if (arsta->arvif && (arsta->arvif->ppe_vp_num == -1 || ++ (arsta->arvif->ahvif && ++ hweight16(arsta->arvif->ahvif->links_map) <= 1))) ++ continue; ++ ++ if (!rx_status) { ++ ath12k_dp_mon_fill_rx_stats(ar, ppdu_info, &status); ++ rx_status = &status; ++ } ++ ++ sta = container_of((void *)arsta->ahsta, struct ieee80211_sta, drv_priv); ++ ieee80211_rx_update_stats(ar->ah->hw, sta, arsta->link_id, ++ ppdu_info->mpdu_len, rx_status); ++ } ++} ++#endif /* CPTCFG_ATH12K_BONDED_DS_SUPPORT */ ++ + static void ath12k_dp_mon_rx_update_peer_su_stats(struct ath12k *ar, + struct ath12k_link_sta *arsta, + struct hal_rx_mon_ppdu_info *ppdu_info) +@@ -3775,10 +3851,18 @@ move_next: + + ath12k_dp_mon_rx_update_peer_su_stats(ar, arsta, + ppdu_info); ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++ ath12k_dp_mon_rx_update_peer_stats_bonded(ar, arsta, ppdu_info, ++ &ar->dp.rx_status); ++#endif /* CPTCFG_ATH12K_BONDED_DS_SUPPORT */ + } else if ((ppdu_info->fc_valid) && + (ppdu_info->ast_index != HAL_AST_IDX_INVALID)) { + ath12k_dp_mon_rx_process_ulofdma(ppdu_info); + ath12k_dp_mon_rx_update_peer_mu_stats(ar, ppdu_info); ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++ ath12k_dp_mon_rx_update_peer_stats_bonded(ar, NULL, ppdu_info, ++ &ar->dp.rx_status); ++#endif /* CPTCFG_ATH12K_BONDED_DS_SUPPORT */ + } + + next_skb: +@@ -3952,10 +4036,18 @@ move_next: + + ath12k_dp_mon_rx_update_peer_su_stats(ar, arsta, + ppdu_info); ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++ ath12k_dp_mon_rx_update_peer_stats_bonded(ar, arsta, ppdu_info, ++ NULL); ++#endif /* CPTCFG_ATH12K_BONDED_DS_SUPPORT */ + } else if ((ppdu_info->fc_valid) && + (ppdu_info->ast_index != HAL_AST_IDX_INVALID)) { + ath12k_dp_mon_rx_process_ulofdma(ppdu_info); + ath12k_dp_mon_rx_update_peer_mu_stats(ar, ppdu_info); ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++ ath12k_dp_mon_rx_update_peer_stats_bonded(ar, NULL, ppdu_info, ++ NULL); ++#endif /* CPTCFG_ATH12K_BONDED_DS_SUPPORT */ + } + + if (ath12k_debugfs_is_pktlog_peer_valid(ar, peer->addr)) { +--- a/net/mac80211/status.c ++++ b/net/mac80211/status.c +@@ -1279,6 +1279,39 @@ void ieee80211_tx_status_8023(struct iee + } + EXPORT_SYMBOL(ieee80211_tx_status_8023); + ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++void ieee80211_ppeds_tx_update_stats(struct ieee80211_hw *hw, ++ struct ieee80211_sta *pubsta, ++ struct ieee80211_tx_info *info, ++ struct rate_info rate, int link_id, u32 len) ++{ ++ struct sta_info *sta = container_of(pubsta, struct sta_info, sta); ++ struct link_sta_info *link_sta; ++ int rates_idx, retry_count; ++ ++ rcu_read_lock(); ++ if (link_id >= 0) { ++ link_sta = rcu_dereference(sta->link[link_id]); ++ if (WARN_ON_ONCE(!link_sta)) { ++ rcu_read_unlock(); ++ return; ++ } ++ } else { ++ link_sta = &sta->deflink; ++ } ++ ++ link_sta->tx_stats.packets[0]++; ++ link_sta->tx_stats.bytes[0] += len; ++ rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count); ++ link_sta->tx_stats.last_rate = info->status.rates[rates_idx]; ++ link_sta->tx_stats.last_rate_info = rate; ++ ++ rcu_read_unlock(); ++} ++EXPORT_SYMBOL(ieee80211_ppeds_tx_update_stats); ++#endif /* CPTCFG_MAC80211_BONDED_SUPPORT */ ++ ++ + void ieee80211_report_low_ack(struct ieee80211_sta *pubsta, u32 num_packets) + { + struct sta_info *sta = container_of(pubsta, struct sta_info, sta); +--- a/include/linux/ieee80211.h ++++ b/include/linux/ieee80211.h +@@ -216,6 +216,17 @@ static inline u16 ieee80211_sn_sub(u16 s + #define IEEE80211_MAX_AID_S1G 8191 + #define IEEE80211_MAX_TIM_LEN 251 + #define IEEE80211_MAX_MESH_PEERINGS 63 ++ ++/* ++ * Maximum acceptable MTU is: ++ * IEEE80211_MAX_LEN - WEP overhead - CRC - ++ * QoS overhead - RSN/WPA overhead ++ * Min is arbitrarily chosen > IEEE80211_MIN_LEN. The default ++ * mtu is Ethernet-compatible; it's set by ether_ifattach. ++ */ ++#define IEEE80211_MTU_MAX 2290 ++#define IEEE80211_MTU_MIN 32 ++ + /* Maximum size for the MA-UNITDATA primitive, 802.11 standard section + 6.2.1.1.2. + +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -217,6 +217,20 @@ struct sta_info *sta_info_get(struct iee + return NULL; + } + ++struct net_device *ieee80211_sta_get_dvlan_iface(struct ieee80211_sta *pubsta) ++{ ++ struct sta_info *sta = container_of(pubsta, struct sta_info, sta); ++ ++ if (!sta) ++ return NULL; ++ ++ if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) ++ return sta->sdata->dev; ++ else ++ return NULL; ++} ++EXPORT_SYMBOL(ieee80211_sta_get_dvlan_iface); ++ + /* + * Get sta info either from the specified interface + * or from one of its vlans diff --git a/feeds/ipq95xx/mac80211/patches/qca/766-ath12k-Add-ATH12K_DBG_PEER-for-serviceability.patch b/feeds/ipq95xx/mac80211/patches/qca/766-ath12k-Add-ATH12K_DBG_PEER-for-serviceability.patch new file mode 100644 index 000000000..568b7366f --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/766-ath12k-Add-ATH12K_DBG_PEER-for-serviceability.patch @@ -0,0 +1,228 @@ +From f660ffed8b15ab3ca7ae822dc1d5159c25836102 Mon Sep 17 00:00:00 2001 +From: Ramya Gnanasekar +Date: Mon, 20 Feb 2023 20:30:46 +0530 +Subject: [PATCH] ath12k: Add ATH12K_DBG_PEER for serviceability + +Peer create, removal is scrattered across ATH12K_DBG_MAC +and ATH12K_DBG_WMI. Both has to be enable to debug client +connectivity related issues which in turn logs additional +MAC/WMI debug log. + +Converging client connectivity debug logs under ATH12K_DBG_PEER +debug mask for better serviceability. + +Signed-off-by: Ramya Gnanasekar + +Index: b/drivers/net/wireless/ath/ath12k/debug.h +=================================================================== +--- a/drivers/net/wireless/ath/ath12k/debug.h 2023-04-18 20:04:38.796340287 +0530 ++++ b/drivers/net/wireless/ath/ath12k/debug.h 2023-04-18 20:12:37.300899604 +0530 +@@ -28,6 +28,7 @@ enum ath12k_debug_mask { + ATH12K_DBG_DP_RX = 0x00004000, + ATH12K_DBG_OFFSET = 0x00008000, + ATH12K_DBG_RX_REO = 0x00010000, ++ ATH12K_DBG_PEER = 0x00020000, + + /* keep last*/ + ATH12K_DBG_PPE = 0x80000000, +Index: b/drivers/net/wireless/ath/ath12k/mac.c +=================================================================== +--- a/drivers/net/wireless/ath/ath12k/mac.c 2023-04-18 20:04:38.796340287 +0530 ++++ b/drivers/net/wireless/ath/ath12k/mac.c 2023-04-18 20:04:38.792340316 +0530 +@@ -6242,7 +6242,7 @@ static void ath12k_sta_rc_update_wk(stru + /* BW is upgraded. In this case we send WMI_PEER_PHYMODE + * followed by WMI_PEER_CHWIDTH + */ +- ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac BW upgrade for sta %pM new BW %d, old BW %d\n", ++ ath12k_dbg(ar->ab, ATH12K_DBG_PEER, "mac BW upgrade for sta %pM new BW %d, old BW %d\n", + arsta->addr, bw, bw_prev); + err = ath12k_wmi_set_peer_param(ar, arsta->addr, + arvif->vdev_id, WMI_PEER_PHYMODE, +@@ -6262,7 +6262,7 @@ static void ath12k_sta_rc_update_wk(stru + /* BW is downgraded. In this case we send + * WMI_PEER_CHWIDTH followed by WMI_PEER_PHYMODE + */ +- ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac BW downgrade for sta %pM new BW %d,old BW %d\n", ++ ath12k_dbg(ar->ab, ATH12K_DBG_PEER, "mac BW downgrade for sta %pM new BW %d,old BW %d\n", + arsta->addr, bw, bw_prev); + err = ath12k_wmi_set_peer_param(ar, arsta->addr, + arvif->vdev_id, WMI_PEER_CHWIDTH, +@@ -6282,7 +6282,7 @@ static void ath12k_sta_rc_update_wk(stru + } + + if (changed & IEEE80211_RC_NSS_CHANGED) { +- ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac update sta %pM nss %d\n", ++ ath12k_dbg(ar->ab, ATH12K_DBG_PEER, "mac update sta %pM nss %d\n", + arsta->addr, nss); + + err = ath12k_wmi_set_peer_param(ar, arsta->addr, arvif->vdev_id, +@@ -6293,7 +6293,7 @@ static void ath12k_sta_rc_update_wk(stru + } + + if (changed & IEEE80211_RC_SMPS_CHANGED) { +- ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac update sta %pM smps %d\n", ++ ath12k_dbg(ar->ab, ATH12K_DBG_PEER, "mac update sta %pM smps %d\n", + arsta->addr, smps); + + err = ath12k_wmi_set_peer_param(ar, arsta->addr, arvif->vdev_id, +@@ -6407,7 +6407,7 @@ static void ath12k_sta_set_4addr_wk(stru + arvif = arsta->arvif; + ar = arvif->ar; + +- ath12k_dbg(ar->ab, ATH12K_DBG_MAC, ++ ath12k_dbg(ar->ab, ATH12K_DBG_PEER, + "setting USE_4ADDR for peer %pM\n", arsta->addr); + + ret = ath12k_wmi_set_peer_param(ar, arsta->addr, +@@ -6518,7 +6518,7 @@ static int ath12k_mac_station_remove(str + ath12k_warn(ar->ab, "Failed to delete peer: %pM for VDEV: %d\n", + arsta->addr, arvif->vdev_id); + else +- ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "Removed peer: %pM for VDEV: %d\n", ++ ath12k_dbg(ar->ab, ATH12K_DBG_PEER, "Removed peer: %pM for VDEV: %d\n", + arsta->addr, arvif->vdev_id); + + ath12k_mac_station_post_remove(ar, arvif, arsta); +@@ -6601,7 +6601,7 @@ static int ath12k_mac_station_add(struct + goto free_rx_stats; + } + +- ath12k_dbg(ab, ATH12K_DBG_MAC, "Added peer: %pM for VDEV: %d num_stations : %d\n", ++ ath12k_dbg(ab, ATH12K_DBG_PEER, "Added peer: %pM for VDEV: %d num_stations : %d\n", + arsta->addr, arvif->vdev_id, ar->num_stations); + + if (ath12k_debugfs_is_extd_tx_stats_enabled(ar) && (!arsta->tx_stats)) { +@@ -6692,6 +6692,8 @@ static u16 ath12k_mac_alloc_ml_peer_id(s + if (ml_peer_id == ATH12K_MAX_MLO_PEERS) + ml_peer_id = ATH12K_MLO_PEER_ID_INVALID; + ++ ath12k_dbg(NULL, ATH12K_DBG_PEER, "Allocated ml_peer_id:%d", ml_peer_id); ++ + return ml_peer_id; + } + +@@ -6916,6 +6918,10 @@ static int ath12k_mac_handle_link_sta_st + } + + mutex_unlock(&ar->conf_mutex); ++ ++ ath12k_dbg(ar->ab, ATH12K_DBG_PEER, "mac sta %pM old state %d new state :%d\n", ++ arsta->addr, old_state, new_state); ++ + return ret; + } + +Index: b/drivers/net/wireless/ath/ath12k/peer.c +=================================================================== +--- a/drivers/net/wireless/ath/ath12k/peer.c 2023-04-18 20:04:38.796340287 +0530 ++++ b/drivers/net/wireless/ath/ath12k/peer.c 2023-04-18 20:04:38.792340316 +0530 +@@ -142,7 +142,7 @@ void ath12k_peer_unmap_event(struct ath1 + goto exit; + } + +- ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "htt peer unmap vdev %d peer %pM id %d\n", ++ ath12k_dbg(ab, ATH12K_DBG_PEER, "htt peer unmap vdev %d peer %pM id %d\n", + peer->vdev_id, peer->addr, peer_id); + + list_del(&peer->list); +@@ -174,7 +174,7 @@ void ath12k_peer_map_event(struct ath12k + wake_up(&ab->peer_mapping_wq); + } + +- ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "htt peer map vdev %d peer %pM id %d\n", ++ ath12k_dbg(ab, ATH12K_DBG_PEER, "htt peer map vdev %d peer %pM id %d\n", + vdev_id, mac_addr, peer_id); + + exit: +@@ -215,7 +215,7 @@ void ath12k_peer_mlo_map_event(struct at + + spin_unlock_bh(&ab->base_lock); + +- ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "htt MLO peer map peer %pM id %d\n", ++ ath12k_dbg(ab, ATH12K_DBG_PEER, "htt MLO peer map peer %pM id %d\n", + mld_addr, ml_peer_id); + + /* TODO rx queue setup for the ML peer */ +@@ -232,7 +232,7 @@ void ath12k_peer_mlo_unmap_event(struct + + ml_peer_id |= ATH12K_ML_PEER_ID_VALID; + +- ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "htt MLO peer unmap peer ml id %d\n", ml_peer_id); ++ ath12k_dbg(ab, ATH12K_DBG_PEER, "htt MLO peer unmap peer ml id %d\n", ml_peer_id); + } + + static int ath12k_wait_for_peer_common(struct ath12k_base *ab, int vdev_id, +@@ -532,6 +532,8 @@ int ath12k_peer_create(struct ath12k *ar + + ar->num_peers++; + ++ ath12k_dbg(ar->ab, ATH12K_DBG_PEER, "peer created %pM\n", param->peer_addr); ++ + spin_unlock_bh(&ar->ab->base_lock); + + return 0; +Index: b/drivers/net/wireless/ath/ath12k/wmi.c +=================================================================== +--- a/drivers/net/wireless/ath/ath12k/wmi.c 2023-04-18 20:04:38.796340287 +0530 ++++ b/drivers/net/wireless/ath/ath12k/wmi.c 2023-04-18 20:04:38.792340316 +0530 +@@ -1368,7 +1368,7 @@ int ath12k_wmi_send_peer_create_cmd(stru + dev_kfree_skb(skb); + } + +- ath12k_dbg(ar->ab, ATH12K_DBG_WMI, ++ ath12k_dbg(ar->ab, ATH12K_DBG_PEER, + "WMI peer create vdev_id %d peer_addr %pM ml_enabled %d\n", + param->vdev_id, param->peer_addr, param->ml_enabled); + +@@ -1394,7 +1394,7 @@ int ath12k_wmi_send_peer_delete_cmd(stru + ether_addr_copy(cmd->peer_macaddr.addr, peer_addr); + cmd->vdev_id = cpu_to_le32(vdev_id); + +- ath12k_dbg(ar->ab, ATH12K_DBG_WMI, ++ ath12k_dbg(ar->ab, ATH12K_DBG_PEER, + "WMI peer delete vdev_id %d peer_addr %pM num_peer : %d\n", + vdev_id, peer_addr, ar->num_peers); + +@@ -2805,8 +2805,8 @@ int ath12k_wmi_send_peer_assoc_cmd(struc + dev_kfree_skb(skb); + } + +- ath12k_dbg(ar->ab, ATH12K_DBG_WMI, +- "wmi peer assoc vdev id %d assoc id %d peer mac %pM peer_flags %x rate_caps %x peer_caps %x listen_intval %d ht_caps %x max_mpdu %d nss %d phymode %d peer_mpdu_density %d vht_caps %x he cap_info %x he ops %x he cap_info_ext %x he phy %x %x %x peer_bw_rxnss_override %x peer_flags_ext %x eht mac_cap %x %x eht phy_cap %x %x %x eht ops %x ml flags %x ml peer id %d num_partner_links %d\n", ++ ath12k_dbg(ar->ab, ATH12K_DBG_PEER, ++ "wmi peer assoc vdev id %d assoc id %d peer mac %pM peer_flags %x rate_caps %x peer_caps %x listen_intval %d ht_caps %x max_mpdu %d nss %d phymode %d peer_mpdu_density %d vht_caps %x he cap_info %x he ops %x he cap_info_ext %x he phy %x %x %x peer_bw_rxnss_override %x peer_flags_ext %x eht mac_cap %x %x eht phy_cap %x %x %x eht ops %x ml flags %x mld_addr %pM logical_link_idx %u ml peer id %d ieee_link_id %u num_partner_links %d\n", + cmd->vdev_id, cmd->peer_associd, param->peer_mac, + cmd->peer_flags, cmd->peer_rate_caps, cmd->peer_caps, + cmd->peer_listen_intval, cmd->peer_ht_caps, +@@ -2820,9 +2820,10 @@ int ath12k_wmi_send_peer_assoc_cmd(struc + cmd->peer_eht_cap_mac[0], cmd->peer_eht_cap_mac[1], + cmd->peer_eht_cap_phy[0], cmd->peer_eht_cap_phy[1], + cmd->peer_eht_cap_phy[2], cmd->peer_eht_ops, +- ml_params->flags, ml_params->ml_peer_id, +- param->ml.num_partner_links +- ); ++ ml_params->flags, ml_params->mld_addr.addr, ++ ml_params->logical_link_idx, ml_params->ml_peer_id, ++ ml_params->ieee_link_id, ++ param->ml.num_partner_links); + + return ret; + } +@@ -8254,7 +8255,7 @@ static void ath12k_peer_delete_resp_even + + complete(&ar->peer_delete_done); + rcu_read_unlock(); +- ath12k_dbg(ab, ATH12K_DBG_WMI, "peer delete resp for vdev id %d addr %pM\n", ++ ath12k_dbg(ab, ATH12K_DBG_PEER, "peer delete resp for vdev id %d addr %pM\n", + peer_del_resp.vdev_id, peer_del_resp.peer_macaddr.addr); + } + +@@ -11076,7 +11077,7 @@ static void ath12k_peer_sta_kickout_even + goto exit; + } + +- ath12k_dbg(ab, ATH12K_DBG_WMI, "peer sta kickout event %pM", ++ ath12k_dbg(ab, ATH12K_DBG_PEER, "peer sta kickout event %pM", + arg.mac_addr); + + ieee80211_report_low_ack(sta, 10); diff --git a/feeds/ipq95xx/mac80211/patches/qca/766-ath12k-Fix-get-peer-from-peer-id-instead-of-ast-inde.patch b/feeds/ipq95xx/mac80211/patches/qca/766-ath12k-Fix-get-peer-from-peer-id-instead-of-ast-inde.patch new file mode 100644 index 000000000..ee9f6e240 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/766-ath12k-Fix-get-peer-from-peer-id-instead-of-ast-inde.patch @@ -0,0 +1,87 @@ +From 366d0b9ce31b13190a3abde567e2299faeca5b81 Mon Sep 17 00:00:00 2001 +From: Rajat Soni +Date: Thu, 20 Apr 2023 16:35:05 +0530 +Subject: [PATCH] ath12k: Fix get peer from peer id instead of ast index + +Currently in function ath12k_dp_mon_rx_update_user_stats, we are fetching peer +by ast index look up. But in monitor mode the ast index is maped to 0 to 15 bits +and in latest HTT_T2H_MSG_TYPE_PEER_MAP3 ast hash is mapped to 16 to 19 bits. +Due to this when multiple clients are connected we are not able to fetch peer +from ast index look up. + +Peer ID is better way to access peer istead of ast index. + +To fix this issue get peer from peer id. + +Fixes: cd2d4e2d270a ("ath12k: Fix search flag and update peer map event for sta") + +Signed-off-by: Rajat Soni +--- + drivers/net/wireless/ath/ath12k/dp_mon.c | 8 ++++---- + drivers/net/wireless/ath/ath12k/peer.c | 14 -------------- + drivers/net/wireless/ath/ath12k/peer.h | 1 - + 3 files changed, 4 insertions(+), 19 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/dp_mon.c b/drivers/net/wireless/ath/ath12k/dp_mon.c +index 2e83a23..845a258 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_mon.c ++++ b/drivers/net/wireless/ath/ath12k/dp_mon.c +@@ -3498,14 +3498,14 @@ ath12k_dp_mon_rx_update_user_stats(struct ath12k *ar, + struct ath12k_peer *peer; + u32 num_msdu; + +- if (user_stats->ast_index == 0 || user_stats->ast_index == 0xFFFF) ++ if (ppdu_info->peer_id == HAL_INVALID_PEERID) + return; + +- peer = ath12k_peer_find_by_ast(ar->ab, user_stats->ast_index); ++ peer = ath12k_peer_find_by_id(ar->ab, ppdu_info->peer_id); + + if (!peer) { +- ath12k_warn(ar->ab, "peer ast idx %d can't be found\n", +- user_stats->ast_index); ++ ath12k_warn(ar->ab, "peer with peer id %d can't be found\n", ++ ppdu_info->peer_id); + return; + } + +diff --git a/drivers/net/wireless/ath/ath12k/peer.c b/drivers/net/wireless/ath/ath12k/peer.c +index 4e34edb..9cb807d 100644 +--- a/drivers/net/wireless/ath/ath12k/peer.c ++++ b/drivers/net/wireless/ath/ath12k/peer.c +@@ -115,20 +115,6 @@ struct ath12k_peer *ath12k_peer_find_by_vdev_id(struct ath12k_base *ab, + return NULL; + } + +-struct ath12k_peer *ath12k_peer_find_by_ast(struct ath12k_base *ab, +- int ast_hash) +-{ +- struct ath12k_peer *peer; +- +- lockdep_assert_held(&ab->base_lock); +- +- list_for_each_entry(peer, &ab->peers, list) +- if (ast_hash == peer->ast_hash) +- return peer; +- +- return NULL; +-} +- + void ath12k_peer_unmap_event(struct ath12k_base *ab, u16 peer_id) + { + struct ath12k_peer *peer; +diff --git a/drivers/net/wireless/ath/ath12k/peer.h b/drivers/net/wireless/ath/ath12k/peer.h +index 0048feb..0ff84ef 100644 +--- a/drivers/net/wireless/ath/ath12k/peer.h ++++ b/drivers/net/wireless/ath/ath12k/peer.h +@@ -96,7 +96,6 @@ int ath12k_wait_for_peer_delete_done(struct ath12k *ar, u32 vdev_id, + const u8 *addr); + struct ath12k_peer *ath12k_peer_find_by_vdev_id(struct ath12k_base *ab, + int vdev_id); +-struct ath12k_peer *ath12k_peer_find_by_ast(struct ath12k_base *ab, int ast_hash); + void ath12k_peer_mlo_map_event(struct ath12k_base *ab, struct sk_buff *skb); + void ath12k_peer_mlo_unmap_event(struct ath12k_base *ab, struct sk_buff *skb); + +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/766-ath12k-fix-firmware-assert-during-channel-switch-for.patch b/feeds/ipq95xx/mac80211/patches/qca/766-ath12k-fix-firmware-assert-during-channel-switch-for.patch new file mode 100644 index 000000000..a6405ce52 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/766-ath12k-fix-firmware-assert-during-channel-switch-for.patch @@ -0,0 +1,94 @@ +From 37bd7feaabae73112ca8b4c3bdd03af258ec3f30 Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Thu, 4 May 2023 21:26:31 +0530 +Subject: [PATCH] ath12k: fix firmware assert during channel switch for + multiple peer station + +Currently, we are using deflink station instead of link_sta in +ath12k_mac_op_sta_rc_update function due to this firmware assert +is triggered when we perform channel switch for multiple peer +station in MLO. + +Fix this issue by using link_sta in ath12k_mac_op_sta_rc_update. + +Signed-off-by: Aaradhana Sahu +--- + drivers/net/wireless/ath/ath12k/mac.c | 22 ++++++++++++++++------ + 1 file changed, 16 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index 5501931..dad6646 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -7181,6 +7181,7 @@ static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw, + struct ath12k_link_sta *arsta; + struct ath12k_peer *peer; + u32 bw, smps; ++ struct ieee80211_link_sta *link_sta; + + arvif = ahvif->link[link_id]; + arsta = ahsta->link[link_id]; +@@ -7215,17 +7216,25 @@ static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw, + + spin_unlock_bh(&ar->ab->base_lock); + ++ rcu_read_lock(); ++ link_sta = rcu_dereference(sta->link[link_id]); ++ ++ if (!link_sta) { ++ rcu_read_unlock(); ++ return; ++ } ++ + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, + "mac sta rc update for %pM changed %08x bw %d nss %d smps %d\n", +- arsta->addr, changed, sta->deflink.bandwidth, sta->deflink.rx_nss, +- sta->deflink.smps_mode); ++ arsta->addr, changed, link_sta->bandwidth, link_sta->rx_nss, ++ link_sta->smps_mode); + + spin_lock_bh(&ar->data_lock); + + if (changed & IEEE80211_RC_BW_CHANGED) { + bw = WMI_PEER_CHWIDTH_20MHZ; + +- switch (sta->deflink.bandwidth) { ++ switch (link_sta->bandwidth) { + case IEEE80211_STA_RX_BW_20: + bw = WMI_PEER_CHWIDTH_20MHZ; + break; +@@ -7253,12 +7262,12 @@ static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw, + } + + if (changed & IEEE80211_RC_NSS_CHANGED) +- arsta->nss = sta->deflink.rx_nss; ++ arsta->nss = link_sta->rx_nss; + + if (changed & IEEE80211_RC_SMPS_CHANGED) { + smps = WMI_PEER_SMPS_PS_NONE; + +- switch (sta->deflink.smps_mode) { ++ switch (link_sta->smps_mode) { + case IEEE80211_SMPS_AUTOMATIC: + case IEEE80211_SMPS_OFF: + smps = WMI_PEER_SMPS_PS_NONE; +@@ -7271,7 +7280,7 @@ static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw, + break; + default: + ath12k_warn(ar->ab, "Invalid smps %d in sta rc update for %pM\n", +- sta->deflink.smps_mode, arsta->addr); ++ link_sta->smps_mode, arsta->addr); + smps = WMI_PEER_SMPS_PS_NONE; + break; + } +@@ -7282,6 +7291,7 @@ static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw, + arsta->changed |= changed; + + spin_unlock_bh(&ar->data_lock); ++ rcu_read_unlock(); + + ieee80211_queue_work(hw, &arsta->update_wk); + } +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/767-Fix-the-incorrect-value-of-station-dump-fields-in-SL.patch b/feeds/ipq95xx/mac80211/patches/qca/767-Fix-the-incorrect-value-of-station-dump-fields-in-SL.patch new file mode 100644 index 000000000..2496b60bb --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/767-Fix-the-incorrect-value-of-station-dump-fields-in-SL.patch @@ -0,0 +1,129 @@ +From 53164decc4f113ce948944c28d4e138fcba7ff54 Mon Sep 17 00:00:00 2001 +From: Sivashankari Madhavan +Date: Fri, 21 Apr 2023 15:43:37 +0530 +Subject: [PATCH] Fix the incorrect value of station dump fields in SLO/MLO + mode + +While connecting the AP with a station in SLO/MLO mode observe +the Dtim period and Beacon Interval as 0 in the station dump. + +During the start AP, these fields are updated in the specific +link config. But when setting the station info, it's referring +to the sdata bss config. Due to this, observing the issue. + +Fix it by updating these fields with corresponding link config data +per link. + +Signed-off-by: Sivashankari Madhavan +--- + net/mac80211/sta_info.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +Index: backports-20220822-5.4.213-ef7197996efe/net/mac80211/sta_info.c +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/net/mac80211/sta_info.c ++++ backports-20220822-5.4.213-ef7197996efe/net/mac80211/sta_info.c +@@ -2547,8 +2547,12 @@ void sta_set_sinfo(struct sta_info *sta, + struct ieee80211_local *local = sdata->local; + u32 thr = 0; + int i, ac, link_id = 0; ++ u16 beacon_interval; ++ u8 dtim_period; + struct ieee80211_sta_rx_stats *last_rxstats; + struct link_sta_info *link_sta = NULL; ++ struct ieee80211_link_data *link; ++ struct ieee80211_bss_conf *link_conf; + + last_rxstats = sta_get_last_rx_stats(sta); + +@@ -2600,11 +2604,22 @@ void sta_set_sinfo(struct sta_info *sta, + link_sta_filled |= link_sta_set_info(link_sta, sinfo, + init); + init = false; ++ ++ link = sdata_dereference(sdata->link[link_id], sdata); ++ ++ if (link) { ++ link_conf = link->conf; ++ ++ sinfo->links[link_id].dtim_period = link_conf->dtim_period; ++ sinfo->links[link_id].beacon_interval = link_conf->beacon_int; ++ } + rcu_read_unlock(); + } + + sinfo->filled |= link_sta_filled; + } else { ++ dtim_period = sdata->deflink.conf->dtim_period; ++ beacon_interval = sdata->deflink.conf->beacon_int; + sinfo->filled |= link_sta_set_info(&sta->deflink, sinfo, true); + } + +@@ -2718,8 +2733,8 @@ void sta_set_sinfo(struct sta_info *sta, + sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE; + if (sdata->vif.bss_conf.use_short_slot) + sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME; +- sinfo->bss_param.dtim_period = sdata->vif.bss_conf.dtim_period; +- sinfo->bss_param.beacon_interval = sdata->vif.bss_conf.beacon_int; ++ sinfo->bss_param.dtim_period = dtim_period; ++ sinfo->bss_param.beacon_interval = beacon_interval; + + sinfo->sta_flags.set = 0; + sinfo->sta_flags.mask = BIT(NL80211_STA_FLAG_AUTHORIZED) | +Index: backports-20220822-5.4.213-ef7197996efe/include/net/cfg80211.h +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/include/net/cfg80211.h ++++ backports-20220822-5.4.213-ef7197996efe/include/net/cfg80211.h +@@ -1994,6 +1994,8 @@ struct cfg80211_tid_stats { + + struct link_station_info { + u8 addr[ETH_ALEN] __aligned(2); ++ u8 dtim_period; ++ u16 beacon_interval; + /* TODO: packet stats */ + }; + +Index: backports-20220822-5.4.213-ef7197996efe/net/wireless/nl80211.c +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/net/wireless/nl80211.c ++++ backports-20220822-5.4.213-ef7197996efe/net/wireless/nl80211.c +@@ -7170,16 +7170,34 @@ static int nl80211_send_station(struct s + if (!bss_param) + goto nla_put_failure; + ++ link_id = 0; ++ if (sinfo->valid_links) { ++ for_each_valid_link(sinfo, link_id) { ++ link = nla_nest_start(msg, link_id + 1); ++ if (nla_put_u8(msg, NL80211_STA_BSS_PARAM_DTIM_PERIOD, ++ sinfo->links[link_id].dtim_period)) ++ goto nla_put_failure; ++ if (nla_put_u16(msg, NL80211_STA_BSS_PARAM_BEACON_INTERVAL, ++ sinfo->links[link_id].beacon_interval)) ++ goto nla_put_failure; ++ ++ nla_nest_end(msg, link); ++ } ++ } else { ++ if (nla_put_u8(msg, NL80211_STA_BSS_PARAM_DTIM_PERIOD, ++ sinfo->bss_param.dtim_period) || ++ nla_put_u16(msg, NL80211_STA_BSS_PARAM_BEACON_INTERVAL, ++ sinfo->bss_param.beacon_interval)) { ++ goto nla_put_failure; ++ } ++ } ++ + if (((sinfo->bss_param.flags & BSS_PARAM_FLAGS_CTS_PROT) && + nla_put_flag(msg, NL80211_STA_BSS_PARAM_CTS_PROT)) || + ((sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_PREAMBLE) && + nla_put_flag(msg, NL80211_STA_BSS_PARAM_SHORT_PREAMBLE)) || + ((sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_SLOT_TIME) && +- nla_put_flag(msg, NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME)) || +- nla_put_u8(msg, NL80211_STA_BSS_PARAM_DTIM_PERIOD, +- sinfo->bss_param.dtim_period) || +- nla_put_u16(msg, NL80211_STA_BSS_PARAM_BEACON_INTERVAL, +- sinfo->bss_param.beacon_interval)) ++ nla_put_flag(msg, NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME))) + goto nla_put_failure; + + nla_nest_end(msg, bss_param); diff --git a/feeds/ipq95xx/mac80211/patches/qca/767-ath12k-Check-if-ar-is-down-before-handling-mac-opera.patch b/feeds/ipq95xx/mac80211/patches/qca/767-ath12k-Check-if-ar-is-down-before-handling-mac-opera.patch new file mode 100755 index 000000000..48d428918 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/767-ath12k-Check-if-ar-is-down-before-handling-mac-opera.patch @@ -0,0 +1,77 @@ +From 63a86b3cf7b466bd5fdc2bbeb63592c7681b448f Mon Sep 17 00:00:00 2001 +From: Ramanathan Choodamani +Date: Mon, 24 Apr 2023 16:47:24 -0700 +Subject: [PATCH] ath12k: Check if ar is down before handling mac operations + +Usually when the chip goes for a crash, upper layers might +not be aware of it. Hence, we need to handle scenarios when +the upper layers require some actions to be done and the chip +is down. + +Check for FLUSH flags and then decide whether the ar context +has to be handled or not + +Signed-off-by: Ramanathan Choodamani +--- + drivers/net/wireless/ath/ath12k/mac.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index 397efdb..86ffe13 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -4303,6 +4303,9 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar, + + lockdep_assert_held(&ar->conf_mutex); + ++ if (unlikely(test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))) ++ return; ++ + if (changed & BSS_CHANGED_BEACON_INT) { + arvif->beacon_interval = info->beacon_int; + +@@ -5105,6 +5108,11 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw, + return -EINVAL; + } + ++ if (unlikely(test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ESHUTDOWN; ++ } ++ + link_id = ath12k_mac_find_link_id_by_freq(vif, ar, + hw_req->req.channels[0]->center_freq); + +@@ -6858,6 +6866,9 @@ static int ath12k_mac_handle_link_sta_state(struct ieee80211_hw *hw, + return -EINVAL; + } + ++ if (unlikely(test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))) ++ return -ESHUTDOWN; ++ + sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + + /* cancel must be done outside the ar mutex to avoid deadlock */ +@@ -10164,6 +10175,9 @@ static int ath12k_mac_ampdu_action(struct ieee80211_hw *hw, + return -EPERM; + } + ++ if (unlikely(test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))) ++ return -ESHUTDOWN; ++ + mutex_lock(&ar->conf_mutex); + + switch (params->action) { +@@ -12190,6 +12204,9 @@ ath12k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw, + + mutex_lock(&ar->conf_mutex); + ++ if (unlikely(test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))) ++ goto out; ++ + ath12k_dbg(ab, ATH12K_DBG_MAC, + "mac chanctx unassign ptr %pK vdev_id %i\n", + ctx, arvif->vdev_id); +-- +2.7.4 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/767-ath12k-Modify-the-M3-SSR-Dump-address.patch b/feeds/ipq95xx/mac80211/patches/qca/767-ath12k-Modify-the-M3-SSR-Dump-address.patch new file mode 100644 index 000000000..31d26f97c --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/767-ath12k-Modify-the-M3-SSR-Dump-address.patch @@ -0,0 +1,48 @@ +From 17a11b2640901eafe863707645088b4907d18304 Mon Sep 17 00:00:00 2001 +From: Dinesh Karthikeyan +Date: Fri, 21 Apr 2023 13:50:03 +0530 +Subject: [PATCH] ath12k: Modify the M3 SSR Dump address + +Add changes to fetch the M3 dump address for IPQ5322 from +dtsi. + +Signed-off-by: Dinesh Karthikeyan +--- + drivers/net/wireless/ath/ath12k/qmi.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c +index 302edfd..4b0f576 100644 +--- a/drivers/net/wireless/ath/ath12k/qmi.c ++++ b/drivers/net/wireless/ath/ath12k/qmi.c +@@ -3973,8 +3973,8 @@ static int ath12k_qmi_assign_target_mem_chunk(struct ath12k_base *ab) + { + struct device *dev = ab->dev; + struct ath12k_hw_group *ag = ab->ag; +- struct device_node *hremote_node = NULL, *mem_node; +- struct resource res; ++ struct device_node *hremote_node = NULL, *mem_node, *dev_node = NULL; ++ struct resource res, m3_dump; + int host_ddr_sz, mlo_ddr_sz, sz, mlo_sz = 0; + int i, idx, mlo_idx, ret; + unsigned int bdf_location[MAX_TGT_MEM_MODES], +@@ -4115,6 +4115,16 @@ skip_mlo_mem_init: + idx++; + break; + case M3_DUMP_REGION_TYPE: ++ if (ab->hif.bus == ATH12K_BUS_AHB) { ++ dev_node = of_find_node_by_name(NULL, "m3_dump"); ++ if (of_address_to_resource(dev_node, 0, &m3_dump)) { ++ ath12k_err(ab, "M3_MEM_REGION Not defined in device_tree\n"); ++ ret = -EINVAL; ++ goto out; ++ } else { ++ ab->qmi.target_mem[idx].paddr = m3_dump.start; ++ } ++ } + ab->qmi.target_mem[idx].v.ioaddr = + ioremap(ab->qmi.target_mem[idx].paddr, + ab->qmi.target_mem[i].size); +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/767-ath12k-disable-pdev-for-non-supported-country.patch b/feeds/ipq95xx/mac80211/patches/qca/767-ath12k-disable-pdev-for-non-supported-country.patch new file mode 100644 index 000000000..514ada8a3 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/767-ath12k-disable-pdev-for-non-supported-country.patch @@ -0,0 +1,89 @@ +From 1cfd433b649b963e0c526fb61cca8d02cdd32f02 Mon Sep 17 00:00:00 2001 +From: Karthik M +Date: Mon, 24 Apr 2023 19:13:36 +0530 +Subject: [PATCH] ath12k: disable pdev for non supported country + +Following WARN_ON is thrown for LK/CN country, + +[ 1574.376739] Call trace: +[ 1574.382042] ath12k_reg_update_chan_list+0xac/0x2c8 [ath12k] +[ 1574.384215] ath12k_mac_drain_tx+0x4d0/0x690 [ath12k] +[ 1574.390122] drv_start+0x44/0x54 [mac80211] +[ 1574.395066] ieee80211_do_open+0x154/0x860 [mac80211] +[ 1574.399060] ieee80211_do_open+0x838/0x860 [mac80211] +[ 1574.404261] __dev_open+0xe4/0x164 +[ 1574.409291] __dev_change_flags+0xec/0x19c +[ 1574.412590] dev_change_flags+0x20/0x5c +[ 1574.416671] devinet_ioctl+0x258/0x580 +[ 1574.420402] inet_ioctl+0x678/0x6ac +[ 1574.424223] sock_do_ioctl+0x4c/0x61c +[ 1574.427607] sock_ioctl+0x80c/0x870 +[ 1574.431427] vfs_ioctl+0x24/0x48 +[ 1574.434724] do_vfs_ioctl+0xa3c/0xaa8 +[ 1574.438197] ksys_ioctl+0x44/0x74 +[ 1574.441756] __arm64_sys_ioctl+0x18/0x2c8 +[ 1574.445057] el0_svc_common.constprop.0+0x98/0x114 +[ 1574.449048] el0_svc_handler+0x18/0x20 +[ 1574.453735] el0_svc+0x8/0x500 +[ 1574.457466] ---[ end trace 90f7e1ac33aba033 ]--- + +In MLO configuration, ath12k_mac_radio_start iterates through all the +radio’s and makes the ar state 'ON'. Eventhough some bands are not +supported in certain countries, ath12k_reg_update_chan_list tries to update +the channel list for all the active pdev's and ends up in the warn_on +for non-supported band. + +To fix this, disabling the pdev when the num of channels +in a band for a particular country is zero. + +Signed-off-by: Karthik M +--- + drivers/net/wireless/ath/ath12k/reg.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath12k/reg.c ++++ b/drivers/net/wireless/ath/ath12k/reg.c +@@ -191,8 +191,10 @@ int ath12k_reg_update_chan_list(struct a + } + } + +- if (WARN_ON(!num_channels)) +- return -EINVAL; ++ if (!num_channels) { ++ ath12k_warn(ar->ab, "pdev is not supported for this country\n"); ++ return -ENOTSUPP; ++ } + + params_len = sizeof(struct scan_chan_list_params) + + num_channels * sizeof(struct channel_param); +@@ -434,7 +436,9 @@ int ath12k_regd_update(struct ath12k *ar + + if (ar->state == ATH12K_STATE_ON) { + ret = ath12k_reg_update_chan_list(ar); +- if (ret) ++ if (ret && ret == -ENOTSUPP) ++ continue; ++ else if (ret) + goto err; + } + ar++; +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -8991,7 +8991,16 @@ static int ath12k_mac_radio_start(struct + + /* TODO: Do we need to enable ANI? */ + +- ath12k_reg_update_chan_list(ar); ++ ret = ath12k_reg_update_chan_list(ar); ++ ++ /* the ar state alone can be turned off for non supported country without ++ * returning the error value. As we need to update the channel for the next ar ++ */ ++ if (ret) { ++ if (ret == -ENOTSUPP) ++ ret = 0; ++ goto err; ++ } + + ar->num_started_vdevs = 0; + ar->num_created_vdevs = 0; diff --git a/feeds/ipq95xx/mac80211/patches/qca/768-001-wifi-ath12k-Modify-the-threshold-param-for-Rx.patch b/feeds/ipq95xx/mac80211/patches/qca/768-001-wifi-ath12k-Modify-the-threshold-param-for-Rx.patch new file mode 100644 index 000000000..db4264be9 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/768-001-wifi-ath12k-Modify-the-threshold-param-for-Rx.patch @@ -0,0 +1,58 @@ +From 82f0565c3c4922727fe3ff33e606d00e32b2da03 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Wed, 22 Mar 2023 12:29:43 +0530 +Subject: [PATCH] wifi: ath12k: Modify the threshold param for Rx + +BATCH_THRESHOLD and TIMER_THRESHOLD are modified to 64 and 200 +for Rx. + +Avoid HAL_SRNG_FLAGS_LOW_THRESH_INTR_EN for the RXDMA BUFFER ring type. + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/dp.c | 11 ++++++++--- + drivers/net/wireless/ath/ath12k/hal.h | 4 ++-- + 2 files changed, 10 insertions(+), 5 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -358,13 +358,18 @@ int ath12k_dp_srng_setup(struct ath12k_b + params.intr_timer_thres_us = HAL_SRNG_INT_TIMER_THRESHOLD_RX; + break; + case HAL_RXDMA_BUF: ++ params.intr_batch_cntr_thres_entries = 0; ++ params.intr_timer_thres_us = HAL_SRNG_INT_TIMER_THRESHOLD_RX; ++ break; + case HAL_RXDMA_MONITOR_BUF: + case HAL_RXDMA_MONITOR_STATUS: +- params.low_threshold = num_entries >> 3; +- if (type == HAL_RXDMA_MONITOR_BUF) { ++ if (type == HAL_RXDMA_MONITOR_BUF) + params.low_threshold = DP_RX_MONITOR_BUF_LOW_TH; +- } ++ else ++ params.low_threshold = num_entries >> 3; ++ + params.flags |= HAL_SRNG_FLAGS_LOW_THRESH_INTR_EN; ++ + params.intr_batch_cntr_thres_entries = 0; + params.intr_timer_thres_us = HAL_SRNG_INT_TIMER_THRESHOLD_RX; + break; +--- a/drivers/net/wireless/ath/ath12k/hal.h ++++ b/drivers/net/wireless/ath/ath12k/hal.h +@@ -802,13 +802,13 @@ struct hal_srng { + + /* Interrupt mitigation - Batch threshold in terms of numer of frames */ + #define HAL_SRNG_INT_BATCH_THRESHOLD_TX 64 +-#define HAL_SRNG_INT_BATCH_THRESHOLD_RX 128 ++#define HAL_SRNG_INT_BATCH_THRESHOLD_RX 64 + #define HAL_SRNG_INT_BATCH_THRESHOLD_PPE2TCL 0 + #define HAL_SRNG_INT_BATCH_THRESHOLD_OTHER 1 + + /* Interrupt mitigation - timer threshold in us */ + #define HAL_SRNG_INT_TIMER_THRESHOLD_TX 200 +-#define HAL_SRNG_INT_TIMER_THRESHOLD_RX 500 ++#define HAL_SRNG_INT_TIMER_THRESHOLD_RX 200 + #define HAL_SRNG_INT_TIMER_THRESHOLD_PPE2TCL 30 + #define HAL_SRNG_INT_TIMER_THRESHOLD_OTHER 256 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/768-mac80211-RU-puncturing-support-for-STA.patch b/feeds/ipq95xx/mac80211/patches/qca/768-mac80211-RU-puncturing-support-for-STA.patch new file mode 100644 index 000000000..42edd09f6 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/768-mac80211-RU-puncturing-support-for-STA.patch @@ -0,0 +1,119 @@ +From 86f50e585592c075c1e29521d1fdcb8461b33456 Mon Sep 17 00:00:00 2001 +From: Rajat Soni +Date: Fri, 28 Apr 2023 11:57:48 +0530 +Subject: [PATCH] mac80211: RU puncturing support for STA + +Currently, when AP detects an radar in dfs channel then channels are punctured +in which radar is detected but STA is downgrading its bandwidth instead of +handling this puncturing. + +For example if AP is in EHT80 mode channel 100 and radar is detected, channel +puncturing takes place. Observed that STA reduces its bandwidth to 40 MHz. This +should not happen, STA should remain in 80Mhz bandwidth. + +We are not handling puncturing bitmap on STA side. When AP advertises puncturing +bitmap, STA should handle this puncturing. + +To resolve this issue, we should parse EHT operational IE and update chandef +with puncturing bitmap for EHT sta. + +Signed-off-by: Ramya Gnanasekar +Signed-off-by: Rajat Soni +--- + net/mac80211/mlme.c | 38 ++++++++++++++++++++++++++++++-------- + net/mac80211/util.c | 14 ++++++++++++++ + 2 files changed, 44 insertions(+), 8 deletions(-) + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index b46c80a..906edbc 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -160,6 +160,9 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, + struct ieee80211_sta_ht_cap sta_ht_cap; + ieee80211_conn_flags_t ret; + u32 ht_cfreq; ++ const struct ieee80211_sta_eht_cap *eht_cap; ++ const struct ieee80211_sta_he_cap *he_cap; ++ enum nl80211_iftype iftype = ieee80211_vif_type_p2p(&sdata->vif); + + memset(chandef, 0, sizeof(struct cfg80211_chan_def)); + chandef->chan = channel; +@@ -291,11 +294,6 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, + goto out; + } + +- if (cfg80211_chandef_identical(chandef, &vht_chandef)) { +- ret = 0; +- goto out; +- } +- + if (!cfg80211_chandef_compatible(chandef, &vht_chandef)) { + if (!(conn_flags & IEEE80211_CONN_DISABLE_VHT)) + sdata_info(sdata, +@@ -313,11 +311,35 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, + */ + if (eht_oper && (eht_oper->params & IEEE80211_EHT_OPER_INFO_PRESENT)) { + struct cfg80211_chan_def eht_chandef = *chandef; ++ bool support_160, support_320; ++ u8 he_phy_cap, eht_phy_cap; ++ ++ he_cap = ieee80211_get_he_iftype_cap(sband, iftype); ++ if (!he_cap) { ++ sdata_info(sdata, "Missing iftype sband data/HE cap, disabling HE/EHT"); ++ ret = IEEE80211_CONN_DISABLE_HE | IEEE80211_CONN_DISABLE_EHT; ++ goto out; ++ } ++ ++ eht_cap = ieee80211_get_eht_iftype_cap(sband, iftype); ++ if (!eht_cap) { ++ sdata_info(sdata, "Missing iftype sband data/EHT cap, disabling EHT"); ++ ret = IEEE80211_CONN_DISABLE_EHT; ++ goto out; ++ } ++ ++ eht_phy_cap = eht_cap->eht_cap_elem.phy_cap_info[0]; ++ he_phy_cap = he_cap->he_cap_elem.phy_cap_info[0]; ++ support_320 = ++ eht_phy_cap & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ; ++ support_160 = ++ he_phy_cap & ++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G; + + ieee80211_chandef_eht_oper(sdata, eht_oper, +- eht_chandef.width == +- NL80211_CHAN_WIDTH_160, +- false, &eht_chandef); ++ support_160, ++ support_320, ++ &eht_chandef); + + if (!cfg80211_chandef_valid(&eht_chandef)) { + if (!(conn_flags & IEEE80211_CONN_DISABLE_EHT)) +diff --git a/net/mac80211/util.c b/net/mac80211/util.c +index 4da3eae..11cce4b 100644 +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -3698,6 +3698,20 @@ void ieee80211_chandef_eht_oper(struct ieee80211_sub_if_data *sdata, + } + break; + } ++ ++ if (chandef->width >= NL80211_CHAN_WIDTH_80 && ++ eht_oper->params & ++ IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT) { ++ chandef->ru_punct_bitmap = (eht_oper->optional[4] << 8) | ++ eht_oper->optional[3]; ++ ++ if (!cfg80211_ru_punct_bitmap_valid(chandef)) { ++ sdata_info(sdata, "Received invalid puncturing bitmap 0x%x", ++ chandef->ru_punct_bitmap); ++ chandef->ru_punct_bitmap = 0; ++ return; ++ } ++ } + } + + struct ieee80211_channel +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/770-ath12k-Fill-vdev_id-for-fwtest-command.patch b/feeds/ipq95xx/mac80211/patches/qca/770-ath12k-Fill-vdev_id-for-fwtest-command.patch new file mode 100644 index 000000000..900f36a30 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/770-ath12k-Fill-vdev_id-for-fwtest-command.patch @@ -0,0 +1,89 @@ +From 51bc17c4164720e632a2cf2ad78d91fd55a591a9 Mon Sep 17 00:00:00 2001 +From: Dinesh Karthikeyan +Date: Thu, 27 Apr 2023 14:32:42 +0530 +Subject: [PATCH] ath12k: Fill vdev_id for fwtest command + +Fill vdev id in the fwtest command so that respective valid vdev id +for the interface is sent properly. + +Signed-off-by: Dinesh Karthikeyan +--- + drivers/net/wireless/ath/ath12k/testmode.c | 22 ++++++++++++++++++++-- + 1 file changed, 20 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/testmode.c ++++ b/drivers/net/wireless/ath/ath12k/testmode.c +@@ -303,10 +303,14 @@ err: + mutex_unlock(&ar->conf_mutex); + return ret; + } +-static int ath12k_tm_cmd_wmi(struct ath12k *ar, struct nlattr *tb[]) ++static int ath12k_tm_cmd_wmi(struct ath12k *ar, struct nlattr *tb[], ++ struct ieee80211_vif *vif, u8 link_id) + { + struct ath12k_pdev_wmi *wmi = ar->wmi; + struct sk_buff *skb; ++ struct ath12k_vif *ahvif; ++ struct ath12k_link_vif *arvif; ++ struct ath12k_hw *ah = ar->ah; + u32 cmd_id, buf_len; + int ret, tag; + void *buf; +@@ -340,6 +344,29 @@ static int ath12k_tm_cmd_wmi(struct ath1 + if (tag == WMI_TAG_PDEV_SET_PARAM_CMD) + *ptr = ar->pdev->pdev_id; + ++ if (ar->ab->fw_mode != ATH12K_FIRMWARE_MODE_FTM && ++ (tag == WMI_TAG_VDEV_SET_PARAM_CMD || tag == WMI_TAG_UNIT_TEST_CMD)) { ++ if (vif) { ++ mutex_lock(&ah->conf_mutex); ++ ahvif = (struct ath12k_vif *)vif->drv_priv; ++ arvif = ahvif->link[link_id]; ++ if (!arvif) { ++ ath12k_warn(ar->ab, "failed to find link interface\n"); ++ mutex_unlock(&ah->conf_mutex); ++ ret = -EINVAL; ++ goto out; ++ } ++ *ptr = arvif->vdev_id; ++ mutex_unlock(&ah->conf_mutex); ++ } ++ else { ++ ret = -EINVAL; ++ ath12k_warn(ar->ab, "vdev is not up for given vdev id, so failed to send wmi command (testmode): %d\n", ++ ret); ++ goto out; ++ } ++ } ++ + ath12k_dbg(ar->ab, ATH12K_DBG_TESTMODE, + "testmode cmd wmi cmd_id %d buf length %d\n", + cmd_id, buf_len); +@@ -458,6 +485,7 @@ int ath12k_tm_cmd(struct ieee80211_hw *h + enum ath12k_tm_cmd cmd_type; + int ret = 0; + ++ + ret = nla_parse(tb, ATH12K_TM_ATTR_MAX, data, len, ath12k_tm_policy, + NULL); + if (ret) +@@ -484,12 +512,18 @@ int ath12k_tm_cmd(struct ieee80211_hw *h + return -EINVAL; + } + ++ if (link_id >= IEEE80211_MLD_MAX_NUM_LINKS) { ++ ath12k_warn(ar->ab, "invalid link id specified\n"); ++ mutex_unlock(&ah->conf_mutex); ++ return -EINVAL; ++ } ++ + ab = ar->ab; + mutex_unlock(&ah->conf_mutex); + + switch (cmd_type) { + case ATH12K_TM_CMD_WMI: +- return ath12k_tm_cmd_wmi(ar, tb); ++ return ath12k_tm_cmd_wmi(ar, tb, vif, link_id); + case ATH12K_TM_CMD_TESTMODE_START: + return ath12k_tm_cmd_testmode_start(ar, tb); + case ATH12K_TM_CMD_GET_VERSION: diff --git a/feeds/ipq95xx/mac80211/patches/qca/771-ath12k-IPQ5332-spectral-scan-support.patch b/feeds/ipq95xx/mac80211/patches/qca/771-ath12k-IPQ5332-spectral-scan-support.patch new file mode 100644 index 000000000..c86fe7c68 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/771-ath12k-IPQ5332-spectral-scan-support.patch @@ -0,0 +1,34 @@ +From 38ab977647ab6b0415fd94af3d3d3b19a7d01b43 Mon Sep 17 00:00:00 2001 +From: Sivashankari Madhavan +Date: Tue, 9 May 2023 12:27:14 +0530 +Subject: [PATCH] ath12k: IPQ5332 spectral scan support + +Add the support for IPQ5332 spectral scan. + +Signed-off-by: Sivashankari Madhavan +--- + drivers/net/wireless/ath/ath12k/hw.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/hw.c b/drivers/net/wireless/ath/ath12k/hw.c +index c4c1211..40a384e 100644 +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -1694,6 +1694,14 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { + .credit_flow = false, + .wakeup_mhi = false, + .alloc_cacheable_memory = true, ++ .spectral = { ++ .fft_sz = 7, ++ .fft_pad_sz = 0, ++ .summary_pad_sz = 16, ++ .fft_hdr_len = 24, ++ .max_fft_bins = 512, ++ .fragment_160mhz = false, ++ }, + .max_mlo_peer = ATH12K_MAX_MLO_PEER, + .num_local_link = 0, + .m3_fw_support = false, +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/771-ath12k-add-ring-descriptor-and-srng-dump-prints.patch b/feeds/ipq95xx/mac80211/patches/qca/771-ath12k-add-ring-descriptor-and-srng-dump-prints.patch new file mode 100644 index 000000000..025fa12c8 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/771-ath12k-add-ring-descriptor-and-srng-dump-prints.patch @@ -0,0 +1,215 @@ +From 2f15a450cff5918f2f1c5d8be92c2930d0aacd5e Mon Sep 17 00:00:00 2001 +From: P Praneesh +Date: Sun, 7 May 2023 23:05:14 +0530 +Subject: [PATCH] ath12k: add ring descriptor and srng dump prints + +When the destination ring descriptors are not valid, print the ring descriptor +content and crash the host rather than reaping next descriptor. +This helps hardware to debug the exact problematic descriptor +from the crash dump. + +Signed-off-by: P Praneesh +--- + drivers/net/wireless/ath/ath12k/debug.c | 31 +++++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/debug.h | 17 ++++++++++++++ + drivers/net/wireless/ath/ath12k/dp_rx.c | 8 +++++-- + drivers/net/wireless/ath/ath12k/hw.c | 4 ++++ + drivers/net/wireless/ath/ath12k/hw.h | 1 + + 5 files changed, 59 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/debug.c ++++ b/drivers/net/wireless/ath/ath12k/debug.c +@@ -112,4 +112,35 @@ void ath12k_dbg_dump(struct ath12k_base + } + } + ++void ath12k_err_dump(struct ath12k_base *ab, const char *msg, ++ const char *prefix, const void *buf, ++ size_t len, struct hal_srng *srng) ++{ ++ char linebuf[512]; ++ size_t linebuflen; ++ const void *ptr; ++ ++ if (msg) ++ ath12k_err(ab, msg); ++ ++ for (ptr = buf; (ptr - buf) < len; ptr += 16) { ++ linebuflen = 0; ++ linebuflen += scnprintf(linebuf + linebuflen, ++ sizeof(linebuf) - linebuflen, ++ "%s%08x: ", ++ (prefix ? prefix : ""), ++ (unsigned int)(ptr - buf)); ++ hex_dump_to_buffer(ptr, len - (ptr - buf), 16, 1, ++ linebuf + linebuflen, ++ sizeof(linebuf) - linebuflen, true); ++ dev_err(ab->dev, "%s\n", linebuf); ++ } ++ ++ if (srng->ring_dir == HAL_SRNG_DIR_DST) ++ dev_err(ab->dev, "ring_base_vaddr=%px tp=0x%X size=0x%X cached_hp=0x%X", ++ srng->ring_base_vaddr, ++ srng->u.dst_ring.tp, ++ srng->ring_size, ++ srng->u.dst_ring.cached_hp); ++} + #endif /* CPTCFG_ATH12K_DEBUG */ +--- a/drivers/net/wireless/ath/ath12k/debug.h ++++ b/drivers/net/wireless/ath/ath12k/debug.h +@@ -51,6 +51,9 @@ void ath12k_dbg_dump(struct ath12k_base + enum ath12k_debug_mask mask, + const char *msg, const char *prefix, + const void *buf, size_t len); ++void ath12k_err_dump(struct ath12k_base *ab, const char *msg, ++ const char *prefix, const void *buf, ++ size_t len, struct hal_srng *srng); + #else /* CPTCFG_ATH12K_DEBUG */ + static inline int __ath12k_dbg(struct ath12k_base *ab, + enum ath12k_debug_mask dbg_mask, +@@ -65,6 +68,12 @@ static inline void ath12k_dbg_dump(struc + const void *buf, size_t len) + { + } ++ ++static inline void ath12k_err_dump(struct ath12k_base *ab, const char *msg, ++ const char *prefix, const void *buf, ++ size_t len, struct hal_srng *srng) ++{ ++} + #endif /* CPTCFG_ATH12K_DEBUG */ + + #define ath12k_dbg(ar, dbg_mask, fmt, ...) \ +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -4214,6 +4214,7 @@ int ath12k_dp_rx_process_err(struct ath1 + dma_addr_t paddr; + u32 *desc; + bool is_frag, drop = false; ++ char buf[64] = {0}; + + tot_n_bufs_reaped = 0; + quota = budget; +@@ -4236,9 +4237,10 @@ int ath12k_dp_rx_process_err(struct ath1 + ret = ath12k_hal_desc_reo_parse_err(ab, desc, &paddr, + &desc_bank); + if (ret) { +- ath12k_warn(ab, "failed to parse error reo desc %d\n", +- ret); +- continue; ++ scnprintf(buf, sizeof(buf), "failed to parse error reo desc %d\n", ret); ++ ath12k_err_dump(ab, buf, "rx err desc: ", reo_desc, ++ sizeof(*reo_desc), srng); ++ BUG_ON(1); + } + link_desc_va = link_desc_banks[desc_bank].vaddr + + (paddr - link_desc_banks[desc_bank].paddr); +@@ -4635,6 +4637,7 @@ int ath12k_dp_rx_process_wbm_err(struct + struct ath12k_soc_dp_stats *soc_stats = &ab->soc_stats; + int ret; + u8 src_link_id; ++ char buf[64] = {0}; + + __skb_queue_head_init(&msdu_list); + +@@ -4652,10 +4655,10 @@ int ath12k_dp_rx_process_wbm_err(struct + + ret = ath12k_hal_wbm_desc_parse_err(ab, rx_desc, &err_info); + if (ret) { +- ath12k_warn(ab, +- "failed to parse rx error in wbm_rel ring desc %d\n", +- ret); +- continue; ++ scnprintf(buf, sizeof(buf), "failed to parse rx error in wbm_rel ring desc %d\n", ret); ++ ath12k_err_dump(ab, buf, "wbm err desc: ", rx_desc, ++ sizeof(struct hal_wbm_release_ring), srng); ++ BUG_ON(1); + } + + desc_info = (struct ath12k_rx_desc_info *)err_info.rx_desc; +--- a/drivers/net/wireless/ath/ath12k/dp_mon.c ++++ b/drivers/net/wireless/ath/ath12k/dp_mon.c +@@ -2552,6 +2552,7 @@ int ath12k_dp_mon_buf_replenish(struct a + mon_buf->paddr_lo = lower_32_bits(paddr); + mon_buf->paddr_hi = upper_32_bits(paddr); + mon_buf->cookie = cookie; ++ mon_buf->magic = DP_MON_MAGIC_VALUE; + + req_entries--; + } +@@ -3648,6 +3649,7 @@ int ath12k_dp_mon_srng_process(struct at + u64 cookie; + u32 hal_status, end_reason, ppdu_id, end_offset; + int num_buffs_reaped = 0, srng_id, buf_id; ++ char buf[64] = {0}; + + __skb_queue_head_init(&skb_list); + +@@ -3676,6 +3678,13 @@ int ath12k_dp_mon_srng_process(struct at + goto move_next; + } + ++ if (unlikely(mon_dst_desc->magic != DP_MON_MAGIC_VALUE)) { ++ scnprintf(buf, sizeof(buf), "invalid mon dest desc in mon srng process\n"); ++ ath12k_err_dump(ab, buf, "mon dest desc: ", mon_dst_desc, ++ sizeof(*mon_dst_desc), srng); ++ BUG_ON(1); ++ } ++ + cookie = mon_dst_desc->cookie; + ppdu_id = mon_dst_desc->ppdu_id; + buf_id = u32_get_bits(cookie, DP_RXDMA_BUF_COOKIE_BUF_ID); +@@ -3815,6 +3824,7 @@ int ath12k_dp_mon_rx_process_stats(struc + int num_buffs_reaped = 0, srng_id, buf_id; + u32 hal_status, rx_buf_sz, end_reason, end_offset; + u16 log_type = 0; ++ char buf[64] = {0}; + + __skb_queue_head_init(&skb_list); + +@@ -3837,6 +3847,13 @@ int ath12k_dp_mon_rx_process_stats(struc + goto move_next; + } + ++ if (unlikely(mon_dst_desc->magic != DP_MON_MAGIC_VALUE)) { ++ scnprintf(buf, sizeof(buf), "invalid mon dest desc in mon stats process\n"); ++ ath12k_err_dump(ab, buf, "mon dest desc: ", mon_dst_desc, ++ sizeof(*mon_dst_desc), srng); ++ BUG_ON(1); ++ } ++ + cookie = mon_dst_desc->cookie; + buf_id = u32_get_bits(cookie, DP_RXDMA_BUF_COOKIE_BUF_ID); + +--- a/drivers/net/wireless/ath/ath12k/dp_mon.h ++++ b/drivers/net/wireless/ath/ath12k/dp_mon.h +@@ -15,6 +15,8 @@ + + #define ATH12K_WIFIRX_DOT11_OFFSET 5 + ++#define DP_MON_MAGIC_VALUE 0xDECAFEED ++ + enum dp_mon_tx_ppdu_info_type { + DP_MON_TX_PROT_PPDU_INFO, + DP_MON_TX_DATA_PPDU_INFO +--- a/drivers/net/wireless/ath/ath12k/hal_desc.h ++++ b/drivers/net/wireless/ath/ath12k/hal_desc.h +@@ -2903,7 +2903,8 @@ struct hal_tcl_entrance_from_ppe_ring { + struct hal_mon_buf_ring { + u32 paddr_lo; + u32 paddr_hi; +- u64 cookie; ++ u32 cookie; ++ u32 magic; + }; + + /* hal_mon_buf_ring +@@ -2930,7 +2931,7 @@ struct hal_mon_buf_ring { + + struct hal_mon_dest_desc { + u32 cookie; +- u32 reserved; ++ u32 magic; + u32 ppdu_id; + u32 info0; + }; diff --git a/feeds/ipq95xx/mac80211/patches/qca/771-ath12k-pass-center-freq-and-center-freq2-to-FW-for-E.patch b/feeds/ipq95xx/mac80211/patches/qca/771-ath12k-pass-center-freq-and-center-freq2-to-FW-for-E.patch new file mode 100644 index 000000000..d215e2bd5 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/771-ath12k-pass-center-freq-and-center-freq2-to-FW-for-E.patch @@ -0,0 +1,41 @@ +From a8543d9a9a95f4ab4912c987e60a9c26b4a8dc77 Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Wed, 10 May 2023 18:01:40 +0530 +Subject: [PATCH] ath12k: pass center freq and center freq2 to FW for EHT320 + mode + +When vdev start is sent to FW for bringup in 320MHz BW, the center +freq1 and fre2 are not passed properly. The center freq1 is the +center freq of the primary 160MHz and center freq2 is the center +frequency of the whole 320MHz BW. Update this info in the channel +arg before passing to FW in vdev start/restart command + +Signed-off-by: Sriram R +--- + drivers/net/wireless/ath/ath12k/wmi.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c +index a9be0f0..a1ef9f2 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -1107,7 +1107,15 @@ static void ath12k_wmi_put_wmi_channel(struct wmi_channel *chan, + chan->mhz = chan_arg.freq; + chan->band_center_freq1 = chan_arg.band_center_freq1; + +- if ((chan_arg.mode == MODE_11AX_HE160) || (chan_arg.mode == MODE_11BE_EHT160)) { ++ if (chan_arg.mode == MODE_11BE_EHT320) { ++ if (chan_arg.freq > chan_arg.band_center_freq1) ++ chan->band_center_freq1 = center_freq1 + 80; ++ else ++ chan->band_center_freq1 = center_freq1 - 80; ++ ++ chan->band_center_freq2 = chan_arg.band_center_freq1; ++ ++ } else if ((chan_arg.mode == MODE_11AX_HE160) || (chan_arg.mode == MODE_11BE_EHT160)) { + if (chan_arg.freq > chan_arg.band_center_freq1) + chan->band_center_freq1 = center_freq1 + 40; + else +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/772-001-ath12k-remove-ieee80211-tx-info-reference-in-tx-data.patch b/feeds/ipq95xx/mac80211/patches/qca/772-001-ath12k-remove-ieee80211-tx-info-reference-in-tx-data.patch new file mode 100644 index 000000000..0b421daf5 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/772-001-ath12k-remove-ieee80211-tx-info-reference-in-tx-data.patch @@ -0,0 +1,99 @@ +From cfa18812d2ff9c488ef6c736fd852a04f98a9461 Mon Sep 17 00:00:00 2001 +From: P Praneesh +Date: Fri, 12 May 2023 14:25:09 +0530 +Subject: [PATCH 2/3] ath12k: remove ieee80211_tx_info reference in tx data + path + +Driver specific tx path such as ath12k_dp_tx() and ath12k_mac_mgmt_tx_wmi +currently uses ieee80211_tx_info struct which is a mac80211 skb private +data structure. This is overwritten by ath12k_mac_op_tx(). +Also, the same data is already available in ath12k's skb private data +structure. Fix it by replacing the info by ath12k skb private data structure. + +Signed-off-by: Karthikeyan Periyasamy +Signed-off-by: P Praneesh +--- + drivers/net/wireless/ath/ath12k/dp_tx.c | 9 ++++----- + drivers/net/wireless/ath/ath12k/mac.c | 10 +++++----- + 2 files changed, 9 insertions(+), 10 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -382,7 +382,6 @@ int ath12k_dp_tx(struct ath12k *ar, stru + struct ath12k_peer *peer; + struct hal_tx_info ti = {0}; + struct ath12k_tx_desc_info *tx_desc = NULL; +- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB(skb); + struct hal_tx_msdu_ext_desc *msg; + struct sk_buff *skb_ext_desc; +@@ -401,7 +400,7 @@ int ath12k_dp_tx(struct ath12k *ar, stru + if (unlikely(test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))) + return -ESHUTDOWN; + +- if (unlikely(!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) && ++ if (unlikely(!(skb_cb->flags & ATH12K_SKB_HW_80211_ENCAP) && + !ieee80211_is_data(hdr->frame_control))) + return -ENOTSUPP; + +@@ -497,7 +496,7 @@ int ath12k_dp_tx(struct ath12k *ar, stru + } + + if (unlikely((ahvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_ETHERNET && +- !(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)))) { ++ !(skb_cb->flags & ATH12K_SKB_HW_80211_ENCAP)))) { + msdu_ext_desc = true; + + if (skb->protocol == cpu_to_be16(ETH_P_PAE)) { +@@ -526,8 +525,8 @@ int ath12k_dp_tx(struct ath12k *ar, stru + + /* Add metadata for sw encrypted vlan group traffic */ + if ((!test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->ag->dev_flags) && +- !(info->control.flags & IEEE80211_TX_CTL_HW_80211_ENCAP) && +- !info->control.hw_key && ieee80211_has_protected(hdr->frame_control)) || ++ !(skb_cb->flags & ATH12K_SKB_HW_80211_ENCAP) && ++ !(skb_cb->flags & ATH12K_SKB_CIPHER_SET) && ieee80211_has_protected(hdr->frame_control)) || + is_diff_encap) { + align_pad = ((unsigned long)skb->data) & (HTT_META_DATA_ALIGNMENT - 1); + ret = ath12k_dp_metadata_align_skb(skb, align_pad); +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -8353,8 +8353,8 @@ static int ath12k_mac_mgmt_tx_wmi(struct + { + struct ath12k_base *ab = ar->ab; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; +- struct ieee80211_tx_info *info; + dma_addr_t paddr; ++ struct ath12k_skb_cb *skb_cb; + int buf_id; + int ret; + +@@ -8367,8 +8367,8 @@ static int ath12k_mac_mgmt_tx_wmi(struct + if (buf_id < 0) + return -ENOSPC; + +- info = IEEE80211_SKB_CB(skb); +- if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)) { ++ skb_cb = ATH12K_SKB_CB(skb); ++ if (!(skb_cb->flags & ATH12K_SKB_HW_80211_ENCAP)) { + if ((ieee80211_is_action(hdr->frame_control) || + ieee80211_is_deauth(hdr->frame_control) || + ieee80211_is_disassoc(hdr->frame_control)) && +@@ -8384,7 +8384,7 @@ static int ath12k_mac_mgmt_tx_wmi(struct + goto err_free_idr; + } + +- ATH12K_SKB_CB(skb)->paddr = paddr; ++ skb_cb->paddr = paddr; + + ret = ath12k_wmi_mgmt_send(ar, arvif->vdev_id, buf_id, skb); + if (ret) { +@@ -8395,7 +8395,7 @@ static int ath12k_mac_mgmt_tx_wmi(struct + return 0; + + err_unmap_buf: +- dma_unmap_single(ab->dev, ATH12K_SKB_CB(skb)->paddr, ++ dma_unmap_single(ab->dev, skb_cb->paddr, + skb->len, DMA_TO_DEVICE); + err_free_idr: + spin_lock_bh(&ar->txmgmt_idr_lock); diff --git a/feeds/ipq95xx/mac80211/patches/qca/772-002-ath12k-fix-skb_cb-corruption-in-tx-data.patch b/feeds/ipq95xx/mac80211/patches/qca/772-002-ath12k-fix-skb_cb-corruption-in-tx-data.patch new file mode 100644 index 000000000..eb729dd6a --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/772-002-ath12k-fix-skb_cb-corruption-in-tx-data.patch @@ -0,0 +1,42 @@ +From cfb4240a1b690867f9c0495ce0c267a77d7195a3 Mon Sep 17 00:00:00 2001 +From: P Praneesh +Date: Fri, 12 May 2023 15:21:36 +0530 +Subject: [PATCH 3/3] ath12k: fix skb_cb corruption in tx data path + +skb_cb memory shared across mac80211 and ath12k in tx path. In MLO multicast tx path, +mac80211 skb private data struture get written after populating the link_id information +in ath12k skb private data structure. + +Fix it by avoid the mac80211 skb private access. + +Fixes: I0ef93dc0ca8458 (ath12k: fix encrypted MLO Tx multicast issue) + +Signed-off-by: Karthikeyan Periyasamy +Signed-off-by: P Praneesh +--- + drivers/net/wireless/ath/ath12k/mac.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index bb0bccb..ca8f7fe 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -8761,7 +8761,6 @@ static void ath12k_mac_op_tx(struct ieee80211_hw *hw, + /* upper layer would not have handled the keys so + * handle it here */ + skb_cb = ATH12K_SKB_CB(msdu_copied); +- info = IEEE80211_SKB_CB(msdu_copied); + skb_cb->link_id = link_id; + + spin_lock_bh(&tmp_ar->ab->base_lock); +@@ -8776,7 +8775,6 @@ static void ath12k_mac_op_tx(struct ieee80211_hw *hw, + if (key) { + skb_cb->cipher = key->cipher; + skb_cb->flags |= ATH12K_SKB_CIPHER_SET; +- info->control.hw_key = key; + + hdr = (struct ieee80211_hdr *)msdu_copied->data; + if (!ieee80211_has_protected(hdr->frame_control)) +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/773-000-01-ath12k-use-max-sta-bandwidth-during-peer-assoc.patch b/feeds/ipq95xx/mac80211/patches/qca/773-000-01-ath12k-use-max-sta-bandwidth-during-peer-assoc.patch new file mode 100644 index 000000000..205c1fef1 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/773-000-01-ath12k-use-max-sta-bandwidth-during-peer-assoc.patch @@ -0,0 +1,142 @@ +From 2253f41b57e3a74b0cedfaa4b2f3fa7124a09a86 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Wed, 31 May 2023 20:48:47 +0530 +Subject: [PATCH] ath12k: use max sta bandwidth during peer assoc + +Currently, during peer assoc, host sets the bandwidth argument +based on the sta's current operating bandwidth. During bandwidth +upgrade, this leads to host sending peer phymode again along +with the bandwidth. In multi client cases, this can lead to firmware +buffer overflow. + +However, if host sets the bandwidth argument based on sta's max bandwidth +then durong bandwidth upgrade, there is no need to send the phymode +again. This will help in optimizing the number of commands sent to +the firmware. + +Modify the logic to take sta's max bandwidth into consideration while +forming the bandwodth argument. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath12k/mac.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -3390,7 +3390,7 @@ static bool ath12k_mac_sta_has_ofdm_only + + static enum wmi_phy_mode ath12k_mac_get_phymode_vht(struct ieee80211_link_sta *link_sta) + { +- if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160) { ++ if (link_sta->sta_max_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: +@@ -3403,13 +3403,13 @@ static enum wmi_phy_mode ath12k_mac_get_ + } + } + +- if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80) ++ if (link_sta->sta_max_bandwidth == IEEE80211_STA_RX_BW_80) + return MODE_11AC_VHT80; + +- if (link_sta->bandwidth == IEEE80211_STA_RX_BW_40) ++ if (link_sta->sta_max_bandwidth == IEEE80211_STA_RX_BW_40) + return MODE_11AC_VHT40; + +- if (link_sta->bandwidth == IEEE80211_STA_RX_BW_20) ++ if (link_sta->sta_max_bandwidth == IEEE80211_STA_RX_BW_20) + return MODE_11AC_VHT20; + + return MODE_UNKNOWN; +@@ -3417,7 +3417,7 @@ static enum wmi_phy_mode ath12k_mac_get_ + + static enum wmi_phy_mode ath12k_mac_get_phymode_he(struct ieee80211_link_sta *link_sta) + { +- if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160) { ++ if (link_sta->sta_max_bandwidth == IEEE80211_STA_RX_BW_160) { + 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; +@@ -3428,13 +3428,13 @@ static enum wmi_phy_mode ath12k_mac_get_ + return MODE_11AX_HE160; + } + +- if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80) ++ if (link_sta->sta_max_bandwidth == IEEE80211_STA_RX_BW_80) + return MODE_11AX_HE80; + +- if (link_sta->bandwidth == IEEE80211_STA_RX_BW_40) ++ if (link_sta->sta_max_bandwidth == IEEE80211_STA_RX_BW_40) + return MODE_11AX_HE40; + +- if (link_sta->bandwidth == IEEE80211_STA_RX_BW_20) ++ if (link_sta->sta_max_bandwidth == IEEE80211_STA_RX_BW_20) + return MODE_11AX_HE20; + + return MODE_UNKNOWN; +@@ -3442,11 +3442,11 @@ static enum wmi_phy_mode ath12k_mac_get_ + + static enum wmi_phy_mode ath12k_mac_get_phymode_eht(struct ieee80211_link_sta *link_sta) + { +- if (link_sta->bandwidth == IEEE80211_STA_RX_BW_320) ++ if (link_sta->sta_max_bandwidth == IEEE80211_STA_RX_BW_320) + if (link_sta->eht_cap.eht_cap_elem.phy_cap_info[0] & + IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ) + return MODE_11BE_EHT320; +- if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160) { ++ if (link_sta->sta_max_bandwidth == IEEE80211_STA_RX_BW_160) { + if (link_sta->he_cap.he_cap_elem.phy_cap_info[0] & + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G) + return MODE_11BE_EHT160; +@@ -3457,13 +3457,13 @@ static enum wmi_phy_mode ath12k_mac_get_ + return MODE_11BE_EHT160; + } + +- if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80) ++ if (link_sta->sta_max_bandwidth == IEEE80211_STA_RX_BW_80) + return MODE_11BE_EHT80; + +- if (link_sta->bandwidth == IEEE80211_STA_RX_BW_40) ++ if (link_sta->sta_max_bandwidth == IEEE80211_STA_RX_BW_40) + return MODE_11BE_EHT40; + +- if (link_sta->bandwidth == IEEE80211_STA_RX_BW_20) ++ if (link_sta->sta_max_bandwidth == IEEE80211_STA_RX_BW_20) + return MODE_11BE_EHT20; + + return MODE_UNKNOWN; +@@ -3509,27 +3509,27 @@ static void ath12k_peer_assoc_h_phymode( + case NL80211_BAND_2GHZ: + if (link_sta->eht_cap.has_eht && + !ath12k_peer_assoc_h_eht_masked(eht_mcs_mask)) { +- if (link_sta->bandwidth == IEEE80211_STA_RX_BW_40) ++ if (link_sta->sta_max_bandwidth == IEEE80211_STA_RX_BW_40) + phymode = MODE_11BE_EHT40_2G; + else + phymode = MODE_11BE_EHT20_2G; + } 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) ++ if (link_sta->sta_max_bandwidth == IEEE80211_STA_RX_BW_80) + phymode = MODE_11AX_HE80_2G; +- else if (link_sta->bandwidth == IEEE80211_STA_RX_BW_40) ++ else if (link_sta->sta_max_bandwidth == IEEE80211_STA_RX_BW_40) + phymode = MODE_11AX_HE40_2G; + else + phymode = MODE_11AX_HE20_2G; + } else if (link_sta->vht_cap.vht_supported && + !ath12k_peer_assoc_h_vht_masked(vht_mcs_mask)) { +- if (link_sta->bandwidth == IEEE80211_STA_RX_BW_40) ++ if (link_sta->sta_max_bandwidth == IEEE80211_STA_RX_BW_40) + phymode = MODE_11AC_VHT40; + else + phymode = MODE_11AC_VHT20; + } else if (link_sta->ht_cap.ht_supported && + !ath12k_peer_assoc_h_ht_masked(ht_mcs_mask)) { +- if (link_sta->bandwidth == IEEE80211_STA_RX_BW_40) ++ if (link_sta->sta_max_bandwidth == IEEE80211_STA_RX_BW_40) + phymode = MODE_11NG_HT40; + else + phymode = MODE_11NG_HT20; diff --git a/feeds/ipq95xx/mac80211/patches/qca/773-000-02-ath12k-Revert-fix-target-assert-during-channel-switch.patch b/feeds/ipq95xx/mac80211/patches/qca/773-000-02-ath12k-Revert-fix-target-assert-during-channel-switch.patch new file mode 100644 index 000000000..ecb3bd69d --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/773-000-02-ath12k-Revert-fix-target-assert-during-channel-switch.patch @@ -0,0 +1,150 @@ +From 9f34492dda8ce6b09eb98ccea3ed49eaa6aedb49 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Thu, 1 June 2023 11:50:32 +0530 +Subject: [PATCH] ath12k: Revert fix target assert during channel switch + +If peer flags during peer assoc are updated as per the max peer bandwidth, +then there is no need to send phymode along width channel width whenever +peer channel width is changed. + +This reverts all the changes made in order to send peer phymode during +peer channel width change. + +Revert: 346a12b097ea ("ath12k: fix target assert during channel switch") + +Signed-off-by: Aditya Kumar Singh +--- +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -637,7 +637,6 @@ struct ath12k_link_sta { + struct ath12k_wbm_tx_stats *wbm_tx_stats; + + u16 tcl_metadata; +- u32 bw_prev; + u8 link_id; /* IEEE link id */ + u8 link_idx; /* for fw use only */ + u32 last_tx_pkt_bw; +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -6157,14 +6157,6 @@ static int ath12k_station_assoc(struct a + } + } + +- spin_lock_bh(&ar->data_lock); +- +- /* Set arsta bw and prev bw */ +- arsta->bw = bandwidth; +- arsta->bw_prev = bandwidth; +- +- spin_unlock_bh(&ar->data_lock); +- + return 0; + } + +@@ -6269,11 +6261,10 @@ static void ath12k_sta_rc_update_wk(stru + const u16 *vht_mcs_mask; + const u16 *he_mcs_mask; + const u16 *eht_mcs_mask; +- u32 changed, bw, nss, smps, bw_prev; ++ u32 changed, bw, nss, smps; + int err, num_vht_rates, num_he_rates, num_eht_rates, num_ht_rates; + const struct cfg80211_bitrate_mask *mask; + struct peer_assoc_params peer_arg; +- enum wmi_phy_mode peer_phymode; + struct ath12k_sta *ahsta; + struct ieee80211_link_sta *link_sta = NULL; + bool ht_supp, vht_supp, has_he, has_eht; +@@ -6300,7 +6291,6 @@ static void ath12k_sta_rc_update_wk(stru + arsta->changed = 0; + + bw = arsta->bw; +- bw_prev = arsta->bw_prev; + nss = arsta->nss; + smps = arsta->smps; + +@@ -6315,51 +6305,14 @@ static void ath12k_sta_rc_update_wk(stru + ath12k_mac_max_eht_nss(eht_mcs_mask))); + + if (changed & IEEE80211_RC_BW_CHANGED) { +- /* Get the the peer phymode */ +- ath12k_peer_assoc_h_phymode(ar, arvif, arsta, &peer_arg); +- peer_phymode = peer_arg.peer_phymode; +- +- if (bw > bw_prev) { +- /* BW is upgraded. In this case we send WMI_PEER_PHYMODE +- * followed by WMI_PEER_CHWIDTH +- */ +- ath12k_dbg(ar->ab, ATH12K_DBG_PEER, "mac BW upgrade for sta %pM new BW %d, old BW %d\n", +- arsta->addr, bw, bw_prev); +- err = ath12k_wmi_set_peer_param(ar, arsta->addr, +- arvif->vdev_id, WMI_PEER_PHYMODE, +- peer_phymode); +- if (err) { +- ath12k_warn(ar->ab, "failed to update STA %pM peer phymode %d: %d\n", +- arsta->addr, peer_phymode, err); +- goto err_rc_bw_changed; +- } +- err = ath12k_wmi_set_peer_param(ar, arsta->addr, +- arvif->vdev_id, WMI_PEER_CHWIDTH, +- bw); +- if (err) +- ath12k_warn(ar->ab, "failed to update STA %pM peer bw %d: %d\n", +- arsta->addr, bw, err); +- } else { +- /* BW is downgraded. In this case we send +- * WMI_PEER_CHWIDTH followed by WMI_PEER_PHYMODE +- */ +- ath12k_dbg(ar->ab, ATH12K_DBG_PEER, "mac BW downgrade for sta %pM new BW %d,old BW %d\n", +- arsta->addr, bw, bw_prev); +- err = ath12k_wmi_set_peer_param(ar, arsta->addr, +- arvif->vdev_id, WMI_PEER_CHWIDTH, +- bw); +- if (err) { +- ath12k_warn(ar->ab, "failed to update STA %pM peer bw %d: %d\n", +- arsta->addr, bw, err); +- goto err_rc_bw_changed; +- } +- err = ath12k_wmi_set_peer_param(ar, arsta->addr, +- arvif->vdev_id, WMI_PEER_PHYMODE, +- peer_phymode); +- if (err) +- ath12k_warn(ar->ab, "failed to update STA %pM peer phymode %d: %d\n", +- arsta->addr, peer_phymode, err); +- } ++ ath12k_dbg(ar->ab, ATH12K_DBG_PEER, "mac BW change for sta %pM new BW %d\n", ++ arsta->addr, bw); ++ ++ err = ath12k_wmi_set_peer_param(ar, arsta->addr, arvif->vdev_id, ++ WMI_PEER_CHWIDTH, bw); ++ if (err) ++ ath12k_warn(ar->ab, "failed to update STA %pM peer bw %d: %d\n", ++ arsta->addr, bw, err); + } + + if (changed & IEEE80211_RC_NSS_CHANGED) { +@@ -6411,7 +6364,7 @@ static void ath12k_sta_rc_update_wk(stru + + if (!link_sta) { + rcu_read_unlock(); +- goto err_rc_bw_changed; ++ goto err_unlock; + } + + ht_supp = link_sta->ht_cap.ht_supported; +@@ -6463,7 +6416,7 @@ static void ath12k_sta_rc_update_wk(stru + arsta->addr, arvif->vdev_id); + } + } +-err_rc_bw_changed: ++err_unlock: + mutex_unlock(&ar->conf_mutex); + } + +@@ -7345,7 +7298,6 @@ static void ath12k_mac_op_sta_rc_update( + break; + } + +- arsta->bw_prev = arsta->bw; + arsta->bw = bw; + } + diff --git a/feeds/ipq95xx/mac80211/patches/qca/773-001-ath12k-add-num_stations-counter-for-each-interface.patch b/feeds/ipq95xx/mac80211/patches/qca/773-001-ath12k-add-num_stations-counter-for-each-interface.patch new file mode 100644 index 000000000..debbac839 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/773-001-ath12k-add-num_stations-counter-for-each-interface.patch @@ -0,0 +1,84 @@ +From b19575e3cbc749aab98192a45be084f8cce52888 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Thu, 11 May 2023 10:18:23 +0530 +Subject: [PATCH] ath12k: add num_stations counter for each interface + +Currently ath12k maintains number of stations connected to each radio. +However, at certain times it is useful to know number of stations +connected to any one of the interface under that radio. + +Add support to maintain a counter for number of stations connected to +each interface. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/mac.c | 14 ++++++++++++++ + 2 files changed, 15 insertions(+) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -408,6 +408,7 @@ struct ath12k_link_vif { + + bool mvr_processing; + bool pending_csa_up; ++ int num_stations; + }; + + struct ath12k_vif { +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -4877,6 +4877,7 @@ ath12k_mac_assign_link_vif( struct ath12 + ath12k_update_obss_color_notify_work); + INIT_WORK(&arvif->update_bcn_template_work, + ath12k_update_bcn_template_work); ++ arvif->num_stations = 0; + } + } + +@@ -6157,6 +6158,15 @@ static int ath12k_station_assoc(struct a + } + } + ++ spin_lock_bh(&ar->data_lock); ++ ++ arvif->num_stations++; ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, ++ "mac station %pM connected to vdev %u. num_stations=%u\n", ++ arsta->addr, arvif->vdev_id, arvif->num_stations); ++ ++ spin_unlock_bh(&ar->data_lock); ++ + return 0; + } + +@@ -6175,6 +6185,21 @@ static int ath12k_station_disassoc(struc + + sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + ++ spin_lock_bh(&arvif->ar->data_lock); ++ ++ if (!arvif->num_stations) { ++ ath12k_warn(ar->ab, ++ "mac station disassoc for vdev %u which does not have any station connected\n", ++ arvif->vdev_id); ++ } else { ++ arvif->num_stations--; ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, ++ "mac station %pM disconnected from vdev %u. num_stations=%u\n", ++ arsta->addr, arvif->vdev_id, arvif->num_stations); ++ } ++ ++ spin_unlock_bh(&arvif->ar->data_lock); ++ + if (!sta->wme) { + arvif->num_legacy_stations--; + ret = ath12k_recalc_rtscts_prot(arvif); +@@ -10002,6 +10027,7 @@ static int ath12k_mac_op_add_interface(s + ath12k_update_obss_color_notify_work); + INIT_WORK(&ahvif->deflink.update_bcn_template_work, + ath12k_update_bcn_template_work); ++ ahvif->deflink.num_stations = 0; + + ahvif->key_cipher = INVALID_CIPHER; + diff --git a/feeds/ipq95xx/mac80211/patches/qca/773-002-ath12k-add-peer-channel-width-switch-command-support.patch b/feeds/ipq95xx/mac80211/patches/qca/773-002-ath12k-add-peer-channel-width-switch-command-support.patch new file mode 100644 index 000000000..067c8d08f --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/773-002-ath12k-add-peer-channel-width-switch-command-support.patch @@ -0,0 +1,424 @@ +From e2a727bd1d752b315b15decd1312e0bd7e536050 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Thu, 11 May 2023 16:29:28 +0530 +Subject: [PATCH] ath12k: add peer channel width switch command support + +Currently, separate set peer param command for each peer is being sent +for changing channel width. However this leads to firmware buffer overflow +during multi-client testing. + +This can be optimised by using WMI_PEER_CHAN_WIDTH_SWITCH_CMDID. This command +clubs N number of peers into single command. The value of N is advertised +by firmware in service ready event 2. + +Add support to form and send WMI_PEER_CHAN_WIDTH_SWITCH_CMDID during peer +channel width change. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath12k/core.h | 11 ++ + drivers/net/wireless/ath/ath12k/mac.c | 94 +++++++++++ + drivers/net/wireless/ath/ath12k/wmi.c | 225 +++++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/wmi.h | 33 ++++ + 4 files changed, 363 insertions(+) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -347,6 +347,11 @@ struct ath12k_link_vif_pvt { + }; + #endif + ++struct ath12k_peer_ch_width_switch_data { ++ int count; ++ struct wmi_chan_width_peer_arg peer_arg[]; ++}; ++ + struct ath12k_link_vif { + struct ath12k_base *ab; + struct ath12k_dp *dp; +@@ -410,6 +415,10 @@ struct ath12k_link_vif { + bool mvr_processing; + bool pending_csa_up; + int num_stations; ++ ++ struct completion peer_ch_width_switch_send; ++ struct work_struct peer_ch_width_switch_work; ++ struct ath12k_peer_ch_width_switch_data *peer_ch_width_switch_data; + }; + + struct ath12k_vif { +@@ -1386,6 +1395,8 @@ struct ath12k_base { + + int userpd_id; + ++ u32 chwidth_num_peer_caps; ++ + /* must be last */ + u8 drv_priv[0] __aligned(sizeof(void *)); + }; +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -4877,6 +4877,9 @@ ath12k_mac_assign_link_vif( struct ath12 + INIT_WORK(&arvif->update_bcn_template_work, + ath12k_update_bcn_template_work); + arvif->num_stations = 0; ++ init_completion(&arvif->peer_ch_width_switch_send); ++ INIT_WORK(&arvif->peer_ch_width_switch_work, ++ ath12k_wmi_peer_chan_width_switch_work); + } + } + +@@ -6168,6 +6171,7 @@ static int ath12k_station_assoc(struct a + + spin_lock_bh(&ar->data_lock); + ++ arsta->bw = bandwidth; + arvif->num_stations++; + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, + "mac station %pM connected to vdev %u. num_stations=%u\n", +@@ -6281,6 +6285,73 @@ static int ath12k_station_unauthorize(st + return ret; + } + ++static int ath12k_mac_set_peer_ch_switch_data(struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta) ++{ ++ struct ath12k *ar = arvif->ar; ++ struct ath12k_peer_ch_width_switch_data *peer_data; ++ struct wmi_chan_width_peer_arg *peer_arg; ++ struct ieee80211_link_sta *link_sta; ++ struct ieee80211_vif *vif = arvif->ahvif->vif; ++ struct cfg80211_chan_def def; ++ u16 ru_punct_bitmap; ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ if (!ar->ab->chwidth_num_peer_caps) ++ return -EOPNOTSUPP; ++ ++ if (WARN_ON(ath12k_mac_vif_chan(vif, &def, arvif->link_id))) ++ return -EINVAL; ++ ++ peer_data = arvif->peer_ch_width_switch_data; ++ ++ if (!peer_data) { ++ peer_data = kzalloc(struct_size(peer_data, peer_arg, ++ arvif->num_stations), ++ GFP_KERNEL); ++ if (!peer_data) ++ return -ENOMEM; ++ ++ peer_data->count = 0; ++ arvif->peer_ch_width_switch_data = peer_data; ++ } ++ ++ peer_arg = &peer_data->peer_arg[peer_data->count++]; ++ ++ ++ ru_punct_bitmap = 0; ++ ++ rcu_read_lock(); ++ link_sta = ath12k_get_link_sta(arsta); ++ ++ if (link_sta) { ++ if (link_sta->he_cap.has_he && link_sta->eht_cap.has_eht) ++ ru_punct_bitmap = def.ru_punct_bitmap; ++ ++ if (ieee80211_vif_is_mesh(vif) && link_sta->ru_punct_bitmap) ++ ru_punct_bitmap = link_sta->ru_punct_bitmap; ++ } ++ ++ rcu_read_unlock(); ++ ++ spin_lock_bh(&ar->data_lock); ++ ether_addr_copy(peer_arg->mac_addr.addr, arsta->addr); ++ peer_arg->chan_width = arsta->bw; ++ peer_arg->puncture_20mhz_bitmap = ~ru_punct_bitmap; ++ spin_unlock_bh(&ar->data_lock); ++ ++ if (peer_data->count == 1) { ++ reinit_completion(&arvif->peer_ch_width_switch_send); ++ ieee80211_queue_work(ar->ah->hw, &arvif->peer_ch_width_switch_work); ++ } ++ ++ if (peer_data->count == arvif->num_stations) ++ complete(&arvif->peer_ch_width_switch_send); ++ ++ return 0; ++} ++ + static void ath12k_sta_rc_update_wk(struct work_struct *wk) + { + struct ath12k *ar; +@@ -6341,6 +6412,10 @@ static void ath12k_sta_rc_update_wk(stru + ath12k_dbg(ar->ab, ATH12K_DBG_PEER, "mac BW change for sta %pM new BW %d\n", + arsta->addr, bw); + ++ err = ath12k_mac_set_peer_ch_switch_data(arvif, arsta); ++ if (!err || err == -EINVAL) ++ goto err_unlock; ++ + err = ath12k_wmi_set_peer_param(ar, arsta->addr, arvif->vdev_id, + WMI_PEER_CHWIDTH, bw); + if (err) +@@ -10082,6 +10157,9 @@ static int ath12k_mac_op_add_interface(s + INIT_WORK(&ahvif->deflink.update_bcn_template_work, + ath12k_update_bcn_template_work); + ahvif->deflink.num_stations = 0; ++ init_completion(&ahvif->deflink.peer_ch_width_switch_send); ++ INIT_WORK(&ahvif->deflink.peer_ch_width_switch_work, ++ ath12k_wmi_peer_chan_width_switch_work); + + ahvif->key_cipher = INVALID_CIPHER; + +@@ -10136,6 +10214,7 @@ static void ath12k_mac_remove_link_inter + + cancel_work_sync(&arvif->update_obss_color_notify_work); + cancel_work_sync(&arvif->update_bcn_template_work); ++ cancel_work_sync(&arvif->peer_ch_width_switch_work); + + lockdep_assert_held(&ah->conf_mutex); + +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -6201,6 +6201,7 @@ static int ath12k_wmi_tlv_svc_rdy_ext2_p + } + ab->max_msduq_per_tid = parse->param.max_msduq_per_tid; + ab->default_msduq_per_tid = parse->param.default_msduq_per_tid; ++ ab->chwidth_num_peer_caps = parse->param.chwidth_num_peer_caps; + break; + + case WMI_TAG_ARRAY_STRUCT: +@@ -14374,3 +14375,187 @@ int ath12k_wmi_svc_send_disable(struct a + + return ret; + } ++ ++static void ath12k_wmi_put_peer_list(struct ath12k_base *ab, ++ struct wmi_chan_width_peer_list *peer_list, ++ struct wmi_chan_width_peer_arg *peer_arg, ++ u32 num_peers, int start_idx) ++{ ++ struct wmi_chan_width_peer_list *itr; ++ struct wmi_chan_width_peer_arg *arg_itr; ++ int i; ++ ++ ath12k_dbg(ab, ATH12K_DBG_WMI, ++ "wmi peer channel width switch command peer list\n"); ++ ++ for (i = 0; i < num_peers; i++) { ++ itr = &peer_list[i]; ++ arg_itr = &peer_arg[start_idx + i]; ++ ++ itr->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_CHAN_WIDTH_PEER_LIST, ++ sizeof(*itr)); ++ ether_addr_copy(itr->mac_addr.addr, arg_itr->mac_addr.addr); ++ itr->chan_width = cpu_to_le32(arg_itr->chan_width); ++ itr->puncture_20mhz_bitmap = cpu_to_le32(arg_itr->puncture_20mhz_bitmap); ++ ++ ath12k_dbg(ab, ATH12K_DBG_WMI, ++ " (%u) width %u addr %pM punct_bitmap 0x%x\n", ++ i + 1, arg_itr->chan_width, arg_itr->mac_addr.addr, ++ arg_itr->puncture_20mhz_bitmap); ++ } ++} ++ ++static int ath12k_wmi_peer_chan_width_switch(struct ath12k *ar, ++ struct wmi_peer_chan_width_switch_arg *arg) ++{ ++ struct ath12k_base *ab = ar->ab; ++ struct ath12k_pdev_wmi *wmi = ar->wmi; ++ struct wmi_peer_chan_width_switch_req_cmd *cmd; ++ struct wmi_chan_width_peer_list *peer_list; ++ struct wmi_tlv *tlv; ++ u32 num_peers; ++ size_t peer_list_len; ++ struct sk_buff *skb; ++ void *ptr; ++ int ret, len; ++ ++ num_peers = arg->num_peers; ++ ++ if (WARN_ON(num_peers > ab->chwidth_num_peer_caps)) ++ return -EINVAL; ++ ++ peer_list_len = num_peers * sizeof(*peer_list); ++ ++ len = sizeof(*cmd) + TLV_HDR_SIZE + peer_list_len; ++ ++ skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len); ++ if (!skb) ++ return -ENOMEM; ++ ++ cmd = (struct wmi_peer_chan_width_switch_req_cmd *)skb->data; ++ cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PEER_CHAN_WIDTH_SWITCH_CMD, ++ sizeof(*cmd)); ++ cmd->num_peers = cpu_to_le32(num_peers); ++ cmd->vdev_var = cpu_to_le32(arg->vdev_var); ++ ++ ptr = skb->data + sizeof(*cmd); ++ tlv = (struct wmi_tlv *)ptr; ++ ++ tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, peer_list_len); ++ peer_list = (struct wmi_chan_width_peer_list *)tlv->value; ++ ++ ath12k_wmi_put_peer_list(ab, peer_list, arg->peer_arg, num_peers, ++ arg->start_idx); ++ ++ ptr += peer_list_len; ++ ++ ret = ath12k_wmi_cmd_send(wmi, skb, WMI_PEER_CHAN_WIDTH_SWITCH_CMDID); ++ if (ret) { ++ ath12k_warn(ab, "wmi failed to send peer chan width switch command (%d)\n", ++ ret); ++ dev_kfree_skb(skb); ++ return ret; ++ } ++ ++ ath12k_dbg(ab, ATH12K_DBG_WMI, ++ "wmi peer chan width switch cmd sent num_peers %d \n", ++ num_peers); ++ ++ return ret; ++} ++ ++void ath12k_wmi_set_peers_chan_width(struct ath12k_link_vif *arvif, ++ struct wmi_chan_width_peer_arg *peer_arg, ++ int num, u8 start_idx) ++{ ++ struct ath12k *ar = arvif->ar; ++ struct wmi_chan_width_peer_arg *arg; ++ int i, err; ++ ++ for (i = 0; i < num; i++) { ++ arg = &peer_arg[start_idx + i]; ++ ++ err = ath12k_wmi_set_peer_param(ar, arg->mac_addr.addr, ++ arvif->vdev_id, WMI_PEER_CHWIDTH, ++ arg->chan_width); ++ if (err) { ++ ath12k_warn(ar->ab, "failed to update STA %pM peer bw %d: %d\n", ++ arg->mac_addr.addr, arg->chan_width, err); ++ continue; ++ } ++ } ++} ++ ++void ath12k_wmi_peer_chan_width_switch_work(struct work_struct *work) ++{ ++ struct ath12k_link_vif *arvif = container_of(work, struct ath12k_link_vif, ++ peer_ch_width_switch_work); ++ struct ath12k *ar = arvif->ar; ++ struct ath12k_peer_ch_width_switch_data *data; ++ struct wmi_peer_chan_width_switch_arg arg; ++ unsigned long time_left = 0; ++ int count_left, curr_count, max_count_per_cmd = ar->ab->chwidth_num_peer_caps; ++ int cmd_num = 0, ret; ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ /* possible that the worker got scheduled after complete was triggered. In ++ * this case we don't wait for timeout */ ++ if (arvif->peer_ch_width_switch_data->count == arvif->num_stations) ++ goto send_cmd; ++ ++ mutex_unlock(&ar->conf_mutex); ++ ++ time_left = wait_for_completion_timeout(&arvif->peer_ch_width_switch_send, ++ ATH12K_PEER_CH_WIDTH_SWITCH_TIMEOUT_HZ); ++ if (time_left == 0) { ++ /* Even though timeout occured, we would send the command for the peers ++ * for which we received sta rc update event, hence not returning */ ++ ath12k_dbg(ar->ab, ATH12K_DBG_WMI, ++ "timed out waiting for all peers in peer channel width switch\n"); ++ } ++ ++ mutex_lock(&ar->conf_mutex); ++ ++send_cmd: ++ ++ data = arvif->peer_ch_width_switch_data; ++ ++ spin_lock_bh(&ar->data_lock); ++ arg.vdev_var = arvif->vdev_id; ++ spin_unlock_bh(&ar->data_lock); ++ ++ arg.vdev_var |= ATH12K_PEER_VALID_VDEV_ID | ATH12K_PEER_PUNCT_BITMAP_VALID; ++ arg.peer_arg = data->peer_arg; ++ ++ count_left = data->count; ++ ++ while (count_left > 0) { ++ if (count_left <= max_count_per_cmd) ++ curr_count = count_left; ++ else ++ curr_count = max_count_per_cmd; ++ ++ count_left -= curr_count; ++ ++ cmd_num++; ++ ++ arg.num_peers = curr_count; ++ arg.start_idx = (cmd_num - 1) * max_count_per_cmd; ++ ++ ath12k_dbg(ar->ab, ATH12K_DBG_WMI, ++ "wmi peer channel width switch command num %u\n", ++ cmd_num); ++ ++ ret = ath12k_wmi_peer_chan_width_switch(ar, &arg); ++ if (ret) { ++ /* fallback */ ++ ath12k_wmi_set_peers_chan_width(arvif, arg.peer_arg, arg.num_peers, ++ arg.start_idx); ++ } ++ } ++ ++ kfree(arvif->peer_ch_width_switch_data); ++ arvif->peer_ch_width_switch_data = NULL; ++ mutex_unlock(&ar->conf_mutex); ++} +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -8242,6 +8242,36 @@ struct wmi_vdev_adfs_ocac_complete_event + u32 center_freq2; + } __packed; + ++#define ATH12K_PEER_VALID_VDEV_ID (1 << 31) ++#define ATH12K_PEER_PUNCT_BITMAP_VALID (1 << 30) ++#define ATH12K_PEER_CH_WIDTH_SWITCH_TIMEOUT_HZ (5 * HZ) ++ ++struct wmi_chan_width_peer_arg { ++ struct wmi_mac_addr mac_addr; ++ u32 chan_width; ++ u32 puncture_20mhz_bitmap; ++}; ++ ++struct wmi_peer_chan_width_switch_arg { ++ u32 num_peers; ++ u32 vdev_var; ++ u32 start_idx; ++ struct wmi_chan_width_peer_arg *peer_arg; ++}; ++ ++struct wmi_peer_chan_width_switch_req_cmd { ++ __le32 tlv_header; ++ __le32 num_peers; ++ __le32 vdev_var; ++} __packed; ++ ++struct wmi_chan_width_peer_list { ++ __le32 tlv_header; ++ struct wmi_mac_addr mac_addr; ++ __le32 chan_width; ++ __le32 puncture_20mhz_bitmap; ++} __packed; ++ + #define ATH12K_FW_STATS_BUF_SIZE (1024 * 1024) + + void ath12k_wmi_init_qcn9274(struct ath12k_base *ab, +@@ -8450,4 +8480,5 @@ int ath12k_wmi_config_peer_ppeds_routing + u32 service_code, u32 priority_valid, + u32 src_info, bool ppe_routing_enable); + #endif ++void ath12k_wmi_peer_chan_width_switch_work(struct work_struct *work); + #endif diff --git a/feeds/ipq95xx/mac80211/patches/qca/773-ath12k-handle-the-vdev-id-mismatch-HTT.patch b/feeds/ipq95xx/mac80211/patches/qca/773-ath12k-handle-the-vdev-id-mismatch-HTT.patch new file mode 100644 index 000000000..6e42b2d65 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/773-ath12k-handle-the-vdev-id-mismatch-HTT.patch @@ -0,0 +1,31 @@ +From 5bc2ee6d9dbaa49ec1b80fcb4537d02c0eff2c8a Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Wed, 10 May 2023 19:59:39 +0530 +Subject: [PATCH] wifi: ath12k: Handle the vdev id mismatch HTT Tx complete + +Unhandled HTT Tx completion status skb are not freed in Tx completion +procedure. When vdev id mismatch HTT Tx status recieved, we leak the +skb memory due to unhandled situation. Over the period it leads to +memory unavailable situation in the system which end up in crash. + +Signed-off-by: Karthikeyan Periyasamy +Signed-off-by: P Praneesh +--- + drivers/net/wireless/ath/ath12k/dp_tx.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c +index 2055b47d0b08..9ae218390027 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -708,6 +708,7 @@ ath12k_dp_tx_process_htt_tx_complete(struct ath12k_base *ab, + break; + case HAL_WBM_REL_HTT_TX_COMP_STATUS_REINJ: + case HAL_WBM_REL_HTT_TX_COMP_STATUS_INSPECT: ++ case HAL_WBM_REL_HTT_TX_COMP_STATUS_VDEVID_MISMATCH: + ath12k_dp_tx_free_txbuf(ab, msdu, mac_id, tx_ring, skb_ext_desc); + break; + case HAL_WBM_REL_HTT_TX_COMP_STATUS_MEC_NOTIFY: +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/773-ath12k-perform-address-validation-during-ML-peer-cre.patch b/feeds/ipq95xx/mac80211/patches/qca/773-ath12k-perform-address-validation-during-ML-peer-cre.patch new file mode 100644 index 000000000..5239e40a8 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/773-ath12k-perform-address-validation-during-ML-peer-cre.patch @@ -0,0 +1,412 @@ +From f54fefe63c059acebcddd2fa3da4dbd33dd80330 Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Fri, 12 May 2023 02:02:57 +0530 +Subject: [PATCH] ath12k: perform address validation during ML peer creation + +Add address validation to ensure we are not creating link +peers (belonging to different clients) with same MLD address. +Also, validate if the link peer getting added does not have +its address same as any of the MLD address. +To aid in this validation for faster lookup, add a new list +of ML peers at ah level and use the same for parsing for +the above address validation use cases. + +Signed-off-by: Sriram R +--- + drivers/net/wireless/ath/ath12k/core.h | 6 ++ + drivers/net/wireless/ath/ath12k/mac.c | 68 ++++++------ + drivers/net/wireless/ath/ath12k/peer.c | 137 ++++++++++++++++++++++++- + drivers/net/wireless/ath/ath12k/peer.h | 16 +-- + 4 files changed, 178 insertions(+), 49 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -1193,6 +1193,12 @@ struct ath12k_hw { + u8 supported_band_mask; + u8 num_radio; + DECLARE_BITMAP(free_ml_peer_id_map, ATH12K_MAX_MLO_PEERS); ++ ++ /* Used for protecting objects used at ah level, ex. ath12k_ml_peer */ ++ spinlock_t data_lock; ++ ++ /* protected by ah->data_lock */ ++ struct list_head ml_peers; + struct ath12k radio[0] __aligned(sizeof(void *)); + }; + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -6872,29 +6872,6 @@ exit: + return ret; + } + +-static u16 ath12k_mac_alloc_ml_peer_id(struct ath12k_hw *ah) +-{ +- +- u16 ml_peer_id; +- +- lockdep_assert_held(&ah->conf_mutex); +- +- for (ml_peer_id = 0; ml_peer_id < ATH12K_MAX_MLO_PEERS; ml_peer_id++) { +- if (test_bit(ml_peer_id, ah->free_ml_peer_id_map)) +- continue; +- +- set_bit(ml_peer_id, ah->free_ml_peer_id_map); +- break; +- } +- +- if (ml_peer_id == ATH12K_MAX_MLO_PEERS) +- ml_peer_id = ATH12K_MLO_PEER_ID_INVALID; +- +- ath12k_dbg(NULL, ATH12K_DBG_PEER, "Allocated ml_peer_id:%d", ml_peer_id); +- +- return ml_peer_id; +-} +- + static int ath12k_mac_assign_link_sta(struct ath12k_hw *ah, + struct ath12k_sta *ahsta, + struct ath12k_link_sta *arsta, +@@ -7017,14 +6994,14 @@ static void ath12k_mac_ml_station_remove + + sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + +- ath12k_ml_peer_delete(ahvif, ahsta); ++ ath12k_ml_link_peers_delete(ahvif, ahsta); + + /* validate link station removal and clear arsta links */ + for_each_set_bit(link_id, &sta->valid_links, IEEE80211_MLD_MAX_NUM_LINKS) { + arvif = ahvif->link[link_id]; + arsta = ahsta->link[link_id]; + +- if (WARN_ON(!arvif || !arsta)) ++ if (!arvif || !arsta) + continue; + + ar = arvif->ar; +@@ -7035,8 +7012,7 @@ static void ath12k_mac_ml_station_remove + + ath12k_mac_free_unassign_link_sta(ah, ahsta, link_id); + } +- clear_bit(ahsta->ml_peer_id, ah->free_ml_peer_id_map); +- ahsta->ml_peer_id = ATH12K_MLO_PEER_ID_INVALID; ++ ath12k_ml_peer_delete(ah, sta); + } + + static int ath12k_mac_handle_link_sta_state(struct ieee80211_hw *hw, +@@ -7257,12 +7233,11 @@ static int ath12k_mac_op_sta_state(struc + /* assign default link to the first link sta */ + if (!ahsta->links_map && hweight16(sta->valid_links) == 1 && + new_state == IEEE80211_STA_NONE && old_state == IEEE80211_STA_NOTEXIST) { +- ahsta->ml_peer_id = ath12k_mac_alloc_ml_peer_id(ah); +- +- if (ahsta->ml_peer_id == ATH12K_MLO_PEER_ID_INVALID) { +- ath12k_err(NULL, "unable to allocate ml peer id for sta %pM", sta->addr); ++ ret = ath12k_ml_peer_create(ah, sta); ++ if (ret) { ++ ath12k_err(NULL, "unable to create ML peer for sta %pM", sta->addr); + mutex_unlock(&ah->conf_mutex); +- return -ENOSPC; ++ return ret; + } + + ath12k_mac_assign_link_sta(ah, ahsta, &ahsta->deflink, +@@ -7290,6 +7265,16 @@ static int ath12k_mac_op_sta_state(struc + if (ret) { + ath12k_err(NULL, "unable to move link sta %d of sta %pM from state %d to %d", + link_id, arsta->addr, old_state, new_state); ++ ++ if (old_state == IEEE80211_STA_NOTEXIST && new_state == IEEE80211_STA_NONE) { ++ ++ /* Unassign this link sta which couldnt be added to FW and ++ * cleanup the other link stations added earlier ++ */ ++ ath12k_mac_free_unassign_link_sta(ah, ahsta, link_id); ++ ath12k_mac_ml_station_remove(ahvif, ahsta); ++ } ++ + mutex_unlock(&ah->conf_mutex); + return ret; + } +@@ -7319,11 +7304,17 @@ static int ath12k_mac_op_change_sta_link + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; + u8 link_id; +- int ret; ++ int ret = 0; + + if (!sta->valid_links) + return -EINVAL; + ++ /* FW doesnt support removal of one of link stas. All sta would be removed during ML STA ++ * delete in sta_state(), hence link sta removal is not handled here. ++ */ ++ if (new_links < old_links) ++ return 0; ++ + mutex_lock(&ah->conf_mutex); + + if (ahsta->ml_peer_id == ATH12K_MLO_PEER_ID_INVALID) { +@@ -7351,18 +7342,19 @@ static int ath12k_mac_op_change_sta_link + + mutex_lock(&ar->conf_mutex); + ret = ath12k_mac_station_add(ar, arvif, arsta); +- if (ret) ++ if (ret) { ++ mutex_unlock(&ar->conf_mutex); + ath12k_warn(ar->ab, "Failed to add station: %pM for VDEV: %d\n", + arsta->addr, arvif->vdev_id); ++ ath12k_mac_free_unassign_link_sta(ah, ahsta, link_id); ++ break; ++ } + mutex_unlock(&ar->conf_mutex); + } + +- /* FW doesnt support removal of one of link stas. All sta would be removed during ML STA +- * delete in sta_state(), hence link sta removal is not handled here. +- */ + mutex_unlock(&ah->conf_mutex); + +- return 0; ++ return ret; + } + + static void ath12k_mac_op_sta_set_4addr(struct ieee80211_hw *hw, +@@ -15502,6 +15494,8 @@ int ath12k_mac_allocate(struct ath12k_hw + ah->num_radio, ag->id, ag->num_chip); + + mutex_init(&ah->conf_mutex); ++ INIT_LIST_HEAD(&ah->ml_peers); ++ spin_lock_init(&ah->data_lock); + + link_id = 0; + for (j = 0; j < num_radios; j++) { +--- a/drivers/net/wireless/ath/ath12k/peer.c ++++ b/drivers/net/wireless/ath/ath12k/peer.c +@@ -8,9 +8,22 @@ + #include "peer.h" + #include "debug.h" + +-/* TODO extend peer search apis for ml addr either combined or separately +- * based on dp needs +- */ ++static struct ath12k_ml_peer *ath12k_ml_peer_find(struct ath12k_hw *ah, ++ const u8 *addr) ++{ ++ struct ath12k_ml_peer *ml_peer; ++ ++ lockdep_assert_held(&ah->data_lock); ++ ++ list_for_each_entry(ml_peer, &ah->ml_peers, list) { ++ if (!ether_addr_equal(ml_peer->addr, addr)) ++ continue; ++ ++ return ml_peer; ++ } ++ ++ return NULL; ++} + + struct ath12k_peer *ath12k_peer_find(struct ath12k_base *ab, int vdev_id, + const u8 *addr) +@@ -345,7 +358,7 @@ int ath12k_peer_delete(struct ath12k *ar + return 0; + } + +-int ath12k_ml_peer_delete(struct ath12k_vif *ahvif, struct ath12k_sta *ahsta) ++int ath12k_ml_link_peers_delete(struct ath12k_vif *ahvif, struct ath12k_sta *ahsta) + { + struct ath12k_link_vif *arvif; + struct ath12k_link_sta *arsta; +@@ -369,7 +382,7 @@ int ath12k_ml_peer_delete(struct ath12k_ + arvif = ahvif->link[link_id]; + arsta = ahsta->link[link_id]; + +- if (WARN_ON(!arvif || !arsta)) ++ if (!arvif || !arsta) + continue; + + ar = arvif->ar; +@@ -396,7 +409,7 @@ int ath12k_ml_peer_delete(struct ath12k_ + arvif = ahvif->link[link_id]; + arsta = ahsta->link[link_id]; + +- if (WARN_ON(!arvif || !arsta)) ++ if (!arvif || !arsta) + continue; + + ar = arvif->ar; +@@ -428,7 +441,7 @@ int ath12k_peer_create(struct ath12k *ar + struct ath12k_link_sta *arsta; + u8 link_id = arvif->link_id; + struct ieee80211_vif *vif = arvif->ahvif->vif; +- ++ struct ath12k_ml_peer *ml_peer; + int ret; + + lockdep_assert_held(&ar->conf_mutex); +@@ -439,6 +452,24 @@ int ath12k_peer_create(struct ath12k *ar + return -ENOBUFS; + } + ++ /* Check if a ML peer with same address as this link peer already ++ * exists ++ */ ++ if (sta) { ++ ahsta = (struct ath12k_sta *)sta->drv_priv; ++ spin_lock_bh(&ar->ah->data_lock); ++ ml_peer = ath12k_ml_peer_find(ar->ah, param->peer_addr); ++ if (ml_peer && (!sta->mlo || ml_peer->id != ahsta->ml_peer_id)) { ++ spin_unlock_bh(&ar->ah->data_lock); ++ ath12k_warn(ar->ab, ++ "failed to create link peer %pM due to conflicting address with already associated ML peer %pM with ml peer id %d\n", ++ param->peer_addr, ml_peer->addr, ++ ml_peer->id); ++ return -EINVAL; ++ } ++ spin_unlock_bh(&ar->ah->data_lock); ++ } ++ + spin_lock_bh(&ar->ab->base_lock); + peer = ath12k_peer_find_by_pdev_idx(ar->ab, ar->pdev_idx, param->peer_addr); + if (peer) { +@@ -524,3 +555,101 @@ int ath12k_peer_create(struct ath12k *ar + + return 0; + } ++ ++static u16 ath12k_mac_alloc_ml_peer_id(struct ath12k_hw *ah) ++{ ++ ++ u16 ml_peer_id; ++ ++ lockdep_assert_held(&ah->conf_mutex); ++ ++ for (ml_peer_id = 0; ml_peer_id < ATH12K_MAX_MLO_PEERS; ml_peer_id++) { ++ if (test_bit(ml_peer_id, ah->free_ml_peer_id_map)) ++ continue; ++ ++ set_bit(ml_peer_id, ah->free_ml_peer_id_map); ++ break; ++ } ++ ++ if (ml_peer_id == ATH12K_MAX_MLO_PEERS) ++ ml_peer_id = ATH12K_MLO_PEER_ID_INVALID; ++ ++ ath12k_dbg(NULL, ATH12K_DBG_PEER, "Allocated ml_peer_id:%d", ml_peer_id); ++ ++ return ml_peer_id; ++} ++ ++int ath12k_ml_peer_create(struct ath12k_hw *ah, struct ieee80211_sta *sta) ++{ ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_ml_peer *ml_peer; ++ ++ lockdep_assert_held(&ah->conf_mutex); ++ ++ if (!sta->mlo) ++ return -EINVAL; ++ ++ spin_lock_bh(&ah->data_lock); ++ ml_peer = ath12k_ml_peer_find(ah, sta->addr); ++ if (ml_peer) { ++ spin_unlock_bh(&ah->data_lock); ++ ath12k_err(NULL, "ML peer(id=%d) exists already, unable to add new entry for %pM", ++ ml_peer->id, sta->addr); ++ return -EEXIST; ++ } ++ ++ ml_peer = kzalloc(sizeof(*ml_peer), GFP_ATOMIC); ++ if (!ml_peer) { ++ spin_unlock_bh(&ah->data_lock); ++ ath12k_err(NULL, "unable to allocate new ML peer for %pM", ++ sta->addr); ++ return -ENOMEM; ++ } ++ ++ ahsta->ml_peer_id = ath12k_mac_alloc_ml_peer_id(ah); ++ ++ if (ahsta->ml_peer_id == ATH12K_MLO_PEER_ID_INVALID) { ++ kfree(ml_peer); ++ spin_unlock_bh(&ah->data_lock); ++ ath12k_err(NULL, "unable to allocate ml peer id for sta %pM", sta->addr); ++ return -ENOMEM; ++ } ++ ++ ether_addr_copy(ml_peer->addr, sta->addr); ++ ml_peer->id = ahsta->ml_peer_id; ++ list_add(&ml_peer->list, &ah->ml_peers); ++ spin_unlock_bh(&ah->data_lock); ++ ++ ath12k_dbg(NULL, ATH12K_DBG_PEER, "ML peer created for %pM id %d\n", ++ sta->addr, ahsta->ml_peer_id); ++ return 0; ++} ++ ++int ath12k_ml_peer_delete(struct ath12k_hw *ah, struct ieee80211_sta *sta) ++{ ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_ml_peer *ml_peer; ++ ++ lockdep_assert_held(&ah->conf_mutex); ++ if (!sta->mlo) ++ return -EINVAL; ++ ++ clear_bit(ahsta->ml_peer_id, ah->free_ml_peer_id_map); ++ ahsta->ml_peer_id = ATH12K_MLO_PEER_ID_INVALID; ++ ++ spin_lock_bh(&ah->data_lock); ++ ml_peer = ath12k_ml_peer_find(ah, sta->addr); ++ if (!ml_peer) { ++ spin_unlock_bh(&ah->data_lock); ++ ath12k_err(NULL, "ML peer for %pM not found", sta->addr); ++ return -EINVAL; ++ } ++ ++ list_del(&ml_peer->list); ++ kfree(ml_peer); ++ spin_unlock_bh(&ah->data_lock); ++ ++ ath12k_dbg(NULL, ATH12K_DBG_PEER, "ML peer deleted for %pM\n", ++ sta->addr); ++ return 0; ++} +--- a/drivers/net/wireless/ath/ath12k/peer.h ++++ b/drivers/net/wireless/ath/ath12k/peer.h +@@ -21,12 +21,6 @@ struct ppdu_user_delayba { + u32 resp_rate_flags; + } __packed; + +-/* Note: The ml info is embedded into the link peer +- * objects, based on hot dp requirements to fetch link peer +- * or ml peer based on ml peer id and ml address separate +- * ml peer list maintained in ah can be done. For now it +- * doesnt seem to be needed +- */ + struct ath12k_peer { + struct list_head list; + struct ieee80211_sta *sta; +@@ -81,6 +75,12 @@ struct ath12k_peer { + u8 ml_addr[ETH_ALEN]; + }; + ++struct ath12k_ml_peer { ++ struct list_head list; ++ u8 addr[ETH_ALEN]; ++ u16 id; ++}; ++ + void ath12k_peer_unmap_event(struct ath12k_base *ab, u16 peer_id); + void ath12k_peer_map_event(struct ath12k_base *ab, u8 vdev_id, u16 peer_id, + u8 *mac_addr, u16 ast_hash, u16 hw_peer_id); +@@ -91,7 +91,9 @@ struct ath12k_peer *ath12k_peer_find_by_ + struct ath12k_peer *ath12k_peer_find_by_id(struct ath12k_base *ab, int peer_id); + void ath12k_peer_cleanup(struct ath12k *ar, u32 vdev_id); + int ath12k_peer_delete(struct ath12k *ar, u32 vdev_id, u8 *addr); +-int ath12k_ml_peer_delete(struct ath12k_vif *ahvif, struct ath12k_sta *ahsta); ++int ath12k_ml_link_peers_delete(struct ath12k_vif *ahvif, struct ath12k_sta *ahsta); ++int ath12k_ml_peer_create(struct ath12k_hw *ah, struct ieee80211_sta *sta); ++int ath12k_ml_peer_delete(struct ath12k_hw *ah, struct ieee80211_sta *sta); + int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif, + struct ieee80211_sta *sta, struct peer_create_params *param); + int ath12k_wait_for_peer_delete_done(struct ath12k *ar, u32 vdev_id, diff --git a/feeds/ipq95xx/mac80211/patches/qca/774-ath12k-Change-DMA_FROM_DEVICE-to-DMA_TO_DEVICE-when-.patch b/feeds/ipq95xx/mac80211/patches/qca/774-ath12k-Change-DMA_FROM_DEVICE-to-DMA_TO_DEVICE-when-.patch new file mode 100644 index 000000000..075f7c228 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/774-ath12k-Change-DMA_FROM_DEVICE-to-DMA_TO_DEVICE-when-.patch @@ -0,0 +1,46 @@ +From dd85c0f8eb75752faf0315324ca94cc1586fac98 Mon Sep 17 00:00:00 2001 +From: P Praneesh +Date: Mon, 15 May 2023 21:43:04 +0530 +Subject: [PATCH] ath12k: Change DMA_FROM_DEVICE to DMA_TO_DEVICE when map + reinjected packets + +For fragmented packets, ath12k reassembles each fragment as a normal +packet and then reinjects it into HW ring. In this case, the DMA +direction should be DMA_TO_DEVICE, not DMA_FROM_DEVICE, otherwise +invalid payload will be reinjected to HW and then delivered to host. + +since arbitrary memory could be allocated to the frame, we +don't know what kind of data is contained in the buffer reinjected. +Thus, as a bad result, private info may be leaked. + +Signed-off-by: Baochen Qiang +Signed-off-by: P Praneesh +--- + drivers/net/wireless/ath/ath12k/dp_rx.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c +index c93d3c9..5c83992 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -3827,7 +3827,7 @@ static int ath12k_dp_rx_h_defrag_reo_reinject(struct ath12k *ar, + + buf_paddr = dma_map_single(ab->dev, defrag_skb->data, + defrag_skb->len + skb_tailroom(defrag_skb), +- DMA_FROM_DEVICE); ++ DMA_TO_DEVICE); + if (dma_mapping_error(ab->dev, buf_paddr)) + return -ENOMEM; + +@@ -3907,7 +3907,7 @@ err_free_desc: + spin_unlock_bh(&dp->rx_desc_lock); + err_unmap_dma: + dma_unmap_single(ab->dev, buf_paddr, defrag_skb->len + skb_tailroom(defrag_skb), +- DMA_FROM_DEVICE); ++ DMA_TO_DEVICE); + return ret; + } + +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/774-ath12k-set-bw_40-flag-in-case-of-EHT40-in-6Ghz.patch b/feeds/ipq95xx/mac80211/patches/qca/774-ath12k-set-bw_40-flag-in-case-of-EHT40-in-6Ghz.patch new file mode 100644 index 000000000..cc50df31c --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/774-ath12k-set-bw_40-flag-in-case-of-EHT40-in-6Ghz.patch @@ -0,0 +1,31 @@ +From 57de227347eecb45f9fbedb8ad30afe4d24185a2 Mon Sep 17 00:00:00 2001 +From: Avula Sri Charan +Date: Mon, 15 May 2023 18:30:55 +0530 +Subject: [PATCH 1/1] ath12k set bw_40 flag in case of EHT40 in 6GHz + +Currently for 2GHz & 5Gz we are setting the bw_40 if +IEEE80211_STA_RX_BW_40 is set in ath12k_peer_assoc_h_ht() +where as for 6GHz this case IEEE80211_STA_RX_BW_40 is +not handled in ath12k_peer_assoc_h_he_6ghz because of +which Tx traffic is going in 20MHz when configured in +40MHz. + +Fixed it by setting bw_40 flag in case of IEEE80211_STA_RX_BW_40. + +Signed-off-by: Avula Sri Charan +--- + drivers/net/wireless/ath/ath12k/mac.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -2823,6 +2823,9 @@ static void ath12k_peer_assoc_h_he_6ghz( + if (!arg->he_flag || band != NL80211_BAND_6GHZ || !link_sta->he_6ghz_capa.capa) + return; + ++ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_40) ++ arg->bw_40 = true; ++ + if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80) + arg->bw_80 = true; + diff --git a/feeds/ipq95xx/mac80211/patches/qca/775-ath12k-Add-locks-for-setting-and-testing-flush-flags.patch b/feeds/ipq95xx/mac80211/patches/qca/775-ath12k-Add-locks-for-setting-and-testing-flush-flags.patch new file mode 100644 index 000000000..c71f829e0 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/775-ath12k-Add-locks-for-setting-and-testing-flush-flags.patch @@ -0,0 +1,596 @@ +From 06f0ae6ee1707698a11f76a10a7e4e64ce563914 Mon Sep 17 00:00:00 2001 +From: Ramanathan Choodamani +Date: Thu, 15 Jun 2023 10:13:46 -0700 +Subject: [PATCH] ath12k: Clear the flush flags after ce init and add few more + checks for checking flush flags + + Usually when work threads carry out the process of + reconfiguring the chip which was asserted, a lot of other + things can happen from upper layers, requesting some + actions especially when the chip is down. Adding a check + for chip recovery might help at times, but it need not + always work because of this worker thread async. + + This change will be checking the chip recovery flag in the mac_op functions. + If the flag ATH12K_FLAG_CRASH_FLUSH is set then return -ESTUTDOWN. + + This will ensure, when the restart_work and reset_work threads + take care of the chip recovery and reset work respectively, they set and + clear the FLUSH bits at the right places, when the FW is fully down and when + the FW has been initialized properly and the upper layers such as mac80211 + get failure messages when they send out WMI commands when the chip is + still down. + + Also, add BUG_ON, in case SSR fails to recover the chip. This is + because the chip will not be in UP state and it is better to crash + the system in this case. The goal here is to keep the system in a + usable state, when an external event disrupts the recovery + process. + + Disable ds link netdev before setting arvif->ar to NULL. + Ideally it is better to avoid external operations like scan + which involves kworker threads like vdev_scan_del_wk running parallelly + with the fw recovery threads, which might lead to unwanted race + conditions. + + Use appropriate flags to ensure upper layer initiated scan operations + are not entertained and do a core halt op after ensuring the already + triggered scan is either aborted or completed + +Signed-off-by: Ramanathan Choodamani +Signed-off-by: Sidhanta Sahu +--- + drivers/net/wireless/ath/ath12k/bondif.c | 31 +++++++--- + drivers/net/wireless/ath/ath12k/bondif.h | 8 ++- + drivers/net/wireless/ath/ath12k/core.c | 16 +++++- + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/htc.c | 2 + + drivers/net/wireless/ath/ath12k/mac.c | 72 +++++++++++++++++++++--- + drivers/net/wireless/ath/ath12k/mhi.c | 1 + + drivers/net/wireless/ath/ath12k/pci.c | 2 + + drivers/net/wireless/ath/ath12k/peer.c | 8 +++ + drivers/net/wireless/ath/ath12k/qmi.c | 1 + + drivers/net/wireless/ath/ath12k/wmi.c | 5 ++ + 11 files changed, 127 insertions(+), 20 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/bondif.c ++++ b/drivers/net/wireless/ath/ath12k/bondif.c +@@ -133,8 +133,9 @@ static bool ath12k_stats_update_ppe_vp(s + return true; + } + +-void ath12k_enable_ppe_for_link_netdev(struct ath12k_link_vif *arvif, +- struct net_device *link_dev) ++void ath12k_enable_ppe_for_link_netdev(struct ath12k_base *ab, ++ struct ath12k_link_vif *arvif, ++ struct net_device *link_dev) + { + struct ppe_vp_ai vpai; + struct ieee80211_ppe_vp_ds_params vp_params = {0}; +@@ -147,6 +148,12 @@ void ath12k_enable_ppe_for_link_netdev(s + if (!g_bonded_interface_model) + return; + ++ if (!arvif->ar) { ++ ath12k_warn(ab, "failed to enable ds for link id %d \n", ++ arvif->link_id); ++ return; ++ } ++ + memset(&vpai, 0, sizeof(struct ppe_vp_ai)); + + vpai.type = PPE_VP_TYPE_SW_L2; +@@ -175,7 +182,7 @@ void ath12k_enable_ppe_for_link_netdev(s + link_ndev_pvt->ppe_vp_profile_idx = vp_params.ppe_vp_profile_idx; + link_ndev_pvt->vp_num = ppe_vp_num; + arvif->ppe_vp_num = ppe_vp_num; +- ath12k_dbg(arvif->ar->ab, ATH12K_DBG_PPE, ++ ath12k_dbg(ab, ATH12K_DBG_PPE, + "Enabling DS index %d vp %d link_id %d %pM core_mask 0x%x\n", + vp_params.ppe_vp_profile_idx, ppe_vp_num, + arvif->link_id, arvif->addr, vpai.core_mask); +@@ -199,7 +206,9 @@ void ath12k_enable_ppe_for_link_netdev(s + return; + } + +-void ath12k_disable_ppe_for_link_netdev(struct ath12k_link_vif *arvif, struct net_device *link_dev) ++void ath12k_disable_ppe_for_link_netdev(struct ath12k_base *ab, ++ struct ath12k_link_vif *arvif, ++ struct net_device *link_dev) + { + struct ieee80211_ppe_vp_ds_params vp_params = {0}; + struct ath12k_link_vif_pvt *link_ndev_pvt = NULL; +@@ -207,6 +216,12 @@ void ath12k_disable_ppe_for_link_netdev( + if (!g_bonded_interface_model) + return; + ++ if (!arvif->ar) { ++ ath12k_warn(ab, "failed to disable ds for link id %d \n", ++ arvif->link_id); ++ return; ++ } ++ + if (!arvif->ndev_pvt || !arvif->ndev_pvt->link_ndev) { + ath12k_err(NULL, "ERR no link dev for this vif to disable DS.\n"); + return; +@@ -226,7 +241,7 @@ void ath12k_disable_ppe_for_link_netdev( + ppe_vp_free(arvif->ppe_vp_num); + } + +- ath12k_dbg(arvif->ar->ab, ATH12K_DBG_PPE, ++ ath12k_dbg(ab, ATH12K_DBG_PPE, + "Destroyed PPE VP port type %d no:%d for dev:%s\n", + arvif->ppe_vp_type, arvif->ppe_vp_num, link_dev->name); + arvif->ppe_vp_num = -1; +--- a/drivers/net/wireless/ath/ath12k/bondif.h ++++ b/drivers/net/wireless/ath/ath12k/bondif.h +@@ -14,10 +14,12 @@ + #define ATH12K_PPE_DS_6G_CORE_MASK 0x4 + #define ATH12K_PPE_DS_DEFAULT_CORE_MASK 0x7 + +-void ath12k_disable_ppe_for_link_netdev(struct ath12k_link_vif *arvif, ++void ath12k_disable_ppe_for_link_netdev(struct ath12k_base *ab, ++ struct ath12k_link_vif *arvif, + struct net_device *link_dev); +-void ath12k_enable_ppe_for_link_netdev(struct ath12k_link_vif *arvif, +- struct net_device *link_dev); ++void ath12k_enable_ppe_for_link_netdev(struct ath12k_base *ab, ++ struct ath12k_link_vif *arvif, ++ struct net_device *link_dev); + int ath12k_free_bonddev_for_sfe(struct wireless_dev *wdev, + struct ieee80211_vif *vif, + int link_num); +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -53,6 +53,9 @@ module_param_named(ppe_ds_enable, ath12k + MODULE_PARM_DESC(ppe_ds_enable, "ppe_ds_enable: 0-disable, 1-enable"); + + static unsigned int ath12k_recovery_mode = ATH12K_MLO_RECOVERY_MODE0; ++unsigned int ath12k_ssr_failsafe_mode = false; ++module_param_named(ssr_failsafe_mode, ath12k_ssr_failsafe_mode, uint, 0644); ++MODULE_PARM_DESC(ssr_failsafe_mode, "ssr failsafe mode: 0-disable, 1-enable"); + + bool ath12k_mgmt_rx_reordering = false; + module_param_named(mgmt_rx_reorder, ath12k_mgmt_rx_reordering, bool, 0644); +@@ -1226,6 +1229,8 @@ static int ath12k_core_start(struct ath1 + goto err_reo_cleanup; + } + ++ WARN_ON(test_bit(ATH12K_FLAG_WMI_INIT_DONE, &ab->dev_flags)); ++ set_bit(ATH12K_FLAG_WMI_INIT_DONE, &ab->dev_flags); + /* put hardware to DBS mode */ + if (ab->hw_params->single_pdev_only) { + ret = ath12k_wmi_set_hw_mode(ab, WMI_HOST_HW_MODE_DBS); +@@ -1749,8 +1754,6 @@ static int ath12k_core_reconfigure_on_cr + if (ret) + return ret; + +- clear_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags); +- + ret = ath12k_core_qmi_firmware_ready(ab); + if (ret) + goto err_hal_srng_deinit; +@@ -1861,6 +1864,14 @@ static void ath12k_core_post_reconfigure + switch (ar->state) { + case ATH12K_STATE_ON: + ar->state = ATH12K_STATE_RESTARTING; ++ if (ar->scan.state == ATH12K_SCAN_RUNNING || ++ ar->scan.state == ATH12K_SCAN_STARTING) ++ ar->scan.state = ATH12K_SCAN_ABORTING; ++ ath12k_mac_scan_finish(ar); ++ mutex_unlock(&ar->conf_mutex); ++ cancel_delayed_work_sync(&ar->scan.timeout); ++ cancel_work_sync(&ar->scan.vdev_del_wk); ++ mutex_lock(&ar->conf_mutex); + ath12k_core_halt(ar); + break; + case ATH12K_STATE_OFF: +@@ -1895,10 +1906,7 @@ void ath12k_core_halt(struct ath12k *ar) + ar->num_created_vdevs = 0; + ar->allocated_vdev_map = 0; + +- ath12k_mac_scan_finish(ar); + ath12k_mac_peer_cleanup_all(ar); +- cancel_delayed_work_sync(&ar->scan.timeout); +- cancel_work_sync(&ar->scan.vdev_del_wk); + cancel_work_sync(&ar->regd_update_work); + rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], NULL); + synchronize_rcu(); +@@ -1920,6 +1928,12 @@ static void ath12k_core_restart(struct w + ret = ath12k_core_reconfigure_on_crash(ab); + if (ret) { + ath12k_err(ab, "failed to reconfigure driver on crash recovery\n"); ++ /* ++ * If for any reason, reconfiguration fails, issue bug on for ++ * Mode 0 ++ */ ++ if (ath12k_ssr_failsafe_mode && ath12k_recovery_mode == ATH12K_MLO_RECOVERY_MODE0) ++ BUG_ON(1); + return; + } + +@@ -2059,6 +2073,9 @@ static void ath12k_core_reset(struct wor + */ + ath12k_warn(ab, "already resetting count %d\n", reset_count); + ++ if (ath12k_ssr_failsafe_mode && ath12k_recovery_mode == ATH12K_MLO_RECOVERY_MODE0) ++ BUG_ON(1); ++ + reinit_completion(&ab->reset_complete); + time_left = wait_for_completion_timeout(&ab->reset_complete, + ATH12K_RESET_TIMEOUT_HZ); +@@ -2118,6 +2135,8 @@ static void ath12k_core_reset(struct wor + } else if (ab->hif.bus == ATH12K_BUS_AHB) { + ath12k_coredump_download_ahb(ab); + } ++ if (ab->is_qdss_tracing) ++ ab->is_qdss_tracing = false; + + /* Incase recovery fails and FW asserts again, this is to prevent invalid operation. */ + if (ag->num_started && ab->fw_recovery_support) +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -240,6 +240,7 @@ enum ath12k_dev_flags { + ATH12K_FLAG_HW_GROUP_ATTACHED, + ATH12K_FLAG_FTM_SEGMENTED, + ATH12K_FLAG_PPE_DS_ENABLED, ++ ATH12K_FLAG_WMI_INIT_DONE, + }; + + enum ath12k_monitor_flags { +--- a/drivers/net/wireless/ath/ath12k/htc.c ++++ b/drivers/net/wireless/ath/ath12k/htc.c +@@ -643,6 +643,8 @@ int ath12k_htc_connect_service(struct at + + reinit_completion(&htc->ctl_resp); + ++ if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags)) ++ clear_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags); + status = ath12k_htc_send(htc, ATH12K_HTC_EP_0, skb); + if (status) { + kfree_skb(skb); +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -4714,7 +4714,12 @@ static void ath12k_mac_op_vif_cfg_change + if (changed & BSS_CHANGED_ASSOC) { + /* TODO Handle STA ML assoc */ + arvif = &ahvif->deflink; ++ if (!(arvif && arvif->ar)) { ++ ath12k_err(NULL, "unable to change vif config\n"); ++ return; ++ } + ar = arvif->ar; ++ + if (vif->cfg.assoc) + ath12k_bss_assoc(ar, arvif, &vif->bss_conf); + else +@@ -4747,6 +4752,15 @@ static void ath12k_mac_op_bss_info_chang + } + ar = arvif->ar; + ++ if (!ar) { ++ ath12k_info(NULL, ++ "bss info parameter changes %llx cached to apply after vdev create on channel assign\n", ++ changed); ++ ahvif->cache[link_id].bss_conf_changed |= changed; ++ mutex_unlock(&ah->conf_mutex); ++ return; ++ } ++ + mutex_lock(&ar->conf_mutex); + + ath12k_mac_bss_info_changed(ar, arvif, info, changed); +@@ -4784,21 +4798,22 @@ static int ath12k_mac_vdev_delete(struct + ar->ab->free_vdev_map |= 1LL << arvif->vdev_id; + spin_unlock_bh(&ar->ab->base_lock); + ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++ if (arvif->link_id != ATH12K_DEFAULT_SCAN_LINK && arvif->ndev_pvt) { ++ ath12k_bond_link_release(arvif); ++ if (ahvif->vdev_type == WMI_VDEV_TYPE_AP) ++ ath12k_disable_ppe_for_link_netdev(ar->ab, arvif, ++ arvif->ndev_pvt->link_ndev); ++ } ++#endif + ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id); + ar->ab->free_vdev_stats_id_map &= ~(1LL << arvif->vdev_stats_id); + ar->num_created_vdevs--; + arvif->ahvif->num_vdev_created--; + arvif->is_created = false; ++ arvif->ar = NULL; + + clean_up: +-#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT +- if (arvif->link_id != ATH12K_DEFAULT_SCAN_LINK && arvif->ndev_pvt) { +- ath12k_bond_link_release(arvif); +- ath12k_disable_ppe_for_link_netdev(arvif, arvif->ndev_pvt->link_ndev); +- } +-#endif +- +- arvif->ar = NULL; + spin_lock_bh(&ar->data_lock); + list_del(&arvif->list); + spin_unlock_bh(&ar->data_lock); +@@ -5081,6 +5096,10 @@ static void ath12k_scan_vdev_del_work(st + struct ath12k_hw *ah = ar->ah; + struct ath12k_link_vif *arvif; + ++ if (unlikely(test_bit(ATH12K_FLAG_RECOVERY, &ar->ab->dev_flags))) ++ return; ++ ++ mutex_lock(&ah->conf_mutex); + mutex_lock(&ar->conf_mutex); + /* scan vdev got deleted already. This can happen when on same vif, new + * scan request was requested with different frequeny which leads to +@@ -5095,6 +5114,7 @@ static void ath12k_scan_vdev_del_work(st + if (!arvif) { + ath12k_warn(ar->ab, "mac scan vdev del on unknow vdev_id %d\n", + ar->scan.vdev_id); ++ mutex_unlock(&ah->conf_mutex); + return; + } + +@@ -5104,15 +5124,14 @@ static void ath12k_scan_vdev_del_work(st + goto work_complete; + } + +- mutex_lock(&ah->conf_mutex); + ath12k_mac_remove_link_interface(ah->hw, arvif); + ath12k_mac_unassign_link_vif(arvif); +- mutex_unlock(&ah->conf_mutex); + + mutex_lock(&ar->conf_mutex); + ar->scan.vdev_id = -1; + work_complete: + mutex_unlock(&ar->conf_mutex); ++ mutex_unlock(&ah->conf_mutex); + } + + static int ath12k_start_scan(struct ath12k *ar, +@@ -5178,7 +5197,7 @@ static int ath12k_mac_op_hw_scan(struct + return -EINVAL; + } + +- if (unlikely(test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))) { ++ if (unlikely(test_bit(ATH12K_FLAG_RECOVERY, &ar->ab->dev_flags))) { + mutex_unlock(&ah->conf_mutex); + return -ESHUTDOWN; + } +@@ -5206,6 +5225,10 @@ static int ath12k_mac_op_hw_scan(struct + mutex_unlock(&ah->conf_mutex); + return -EINVAL; + } else if (ar != arvif->ar) { ++ if (!arvif->ar) { ++ mutex_unlock(&ah->conf_mutex); ++ return -EINVAL; ++ } + mutex_lock(&arvif->ar->conf_mutex); + if (arvif->ar->scan.vdev_id != -1) + arvif->ar->scan.vdev_id = -1; +@@ -5338,6 +5361,11 @@ static void ath12k_mac_op_cancel_hw_scan + } + + ar = arvif->ar; ++ if (!ar) { ++ mutex_unlock(&ah->conf_mutex); ++ ath12k_err(NULL, "unable to select device to cancel scan\n"); ++ return; ++ } + mutex_unlock(&ah->conf_mutex); + + mutex_lock(&ar->conf_mutex); +@@ -5669,6 +5697,17 @@ static int ath12k_mac_op_set_key(struct + return 0; + } + ++ if (!(arvif && arvif->ar)) { ++ ath12k_err(NULL, "Failed to set key.\n"); ++ mutex_unlock(&ah->conf_mutex); ++ return -EINVAL; ++ } ++ ++ if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &arvif->ar->ab->dev_flags)) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ESHUTDOWN; ++ } ++ + if (sta) { + ahsta = (struct ath12k_sta *)sta->drv_priv; + if (sta->mlo) { +@@ -6595,6 +6634,10 @@ static void ath12k_mac_dec_num_stations( + struct ath12k_sta *ahsta = arsta->ahsta; + struct ieee80211_sta *sta; + ++ if (ar && !ar->num_stations && ++ test_bit(ATH12K_FLAG_RECOVERY, &ar->ab->dev_flags)) ++ return; ++ + sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + + lockdep_assert_held(&ar->conf_mutex); +@@ -6950,6 +6993,7 @@ static void ath12k_mac_ml_station_remove + ar = arvif->ar; + + mutex_lock(&ar->conf_mutex); ++ + ath12k_mac_station_post_remove(ar, arvif, arsta); + mutex_unlock(&ar->conf_mutex); + +@@ -7160,6 +7204,10 @@ static int ath12k_mac_op_sta_state(struc + + ret = ath12k_mac_handle_link_sta_state(hw, arvif, arsta, + old_state, new_state); ++ if (arvif->ar && ++ test_bit(ATH12K_FLAG_RECOVERY, &arvif->ar->ab->dev_flags)) ++ ret = 0; ++ + mutex_unlock(&ah->conf_mutex); + return ret; + } +@@ -7209,6 +7257,18 @@ static int ath12k_mac_op_sta_state(struc + ath12k_err(NULL, "unable to move link sta %d of sta %pM from state %d to %d", + link_id, arsta->addr, old_state, new_state); + ++ /* If FW recovery is ongoing, no need to move down sta states ++ * as FW will wake up with a clean slate. Hence we set the ++ * return value to 0, so that upper layers are not aware ++ * of the FW being in recovery state. ++ */ ++ if (old_state > new_state) { ++ if (!arvif->ar) ++ continue; ++ if (test_bit(ATH12K_FLAG_RECOVERY, &arvif->ar->ab->dev_flags)) ++ ret = 0; ++ } ++ + if (old_state == IEEE80211_STA_NOTEXIST && new_state == IEEE80211_STA_NONE) { + + /* Unassign this link sta which couldnt be added to FW and +@@ -7282,6 +7342,11 @@ static int ath12k_mac_op_change_sta_link + } + + ar = arvif->ar; ++ if (!ar) { ++ ath12k_err(NULL, ++ "Failed to get ar to change sta links\n"); ++ continue; ++ } + + mutex_lock(&ar->conf_mutex); + ret = ath12k_mac_station_add(ar, arvif, arsta); +@@ -7582,6 +7647,10 @@ static int ath12k_mac_op_conf_tx(struct + mutex_unlock(&ah->conf_mutex); + + ar = arvif->ar; ++ if (!ar) { ++ ath12k_err(NULL, "Failed to config tx\n"); ++ return -EINVAL; ++ } + + mutex_lock(&ar->conf_mutex); + ret = ath12k_mac_conf_tx(ar, arvif, ac, params); +@@ -9886,7 +9955,7 @@ static int ath12k_mac_vdev_create(struct + arvif->ppe_vp_num = -1; + } + else if (link_ndev) { +- ath12k_enable_ppe_for_link_netdev(arvif, ++ ath12k_enable_ppe_for_link_netdev(ab, arvif, + arvif->ndev_pvt->link_ndev); + ath12k_bond_link_enslave(arvif, arvif->ndev_pvt->link_ndev); + } +@@ -10000,6 +10069,7 @@ err_vdev_del: + spin_unlock_bh(&ar->data_lock); + + err: ++ arvif->is_created = false; + arvif->ar = NULL; + return ret; + } +@@ -12663,6 +12733,14 @@ static int ath12k_mac_op_set_rts_thresho + } + + ar = arvif->ar; ++ if (!ar) { ++ ath12k_err(NULL, ++ "Failed to set rts threshold for link: %d\n", ++ link_id); ++ mutex_unlock(&ah->conf_mutex); ++ return ret; ++ } ++ + ret = ath12k_set_vdev_param_to_all_vifs(ar, param_id, value); + if (ret) { + ath12k_warn(ar->ab, "failed to set RTS config for all vdevs of pdev %d", +@@ -13911,6 +13989,11 @@ static void ath12k_mac_op_sta_statistics + + /* TODO accumulate link sta stats here? */ + ++ if (!ar) { ++ ath12k_err(NULL, ++ "unable to determine sta statistics \n"); ++ return; ++ } + sinfo->rx_duration = arsta->rx_duration; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION); + +--- a/drivers/net/wireless/ath/ath12k/mhi.c ++++ b/drivers/net/wireless/ath/ath12k/mhi.c +@@ -331,6 +331,7 @@ static void ath12k_mhi_op_status_cb(stru + break; + case MHI_CB_EE_RDDM: + if (!(test_bit(ATH12K_FLAG_UNREGISTERING, &ab->ag->dev_flags))) { ++ set_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags); + set_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags); + queue_work(ab->workqueue_aux, &ab->reset_work); + } +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -1549,6 +1549,8 @@ static void ath12k_pci_shutdown(struct p + struct ath12k_base *ab = pci_get_drvdata(pdev); + + set_bit(ATH12K_FLAG_UNREGISTERING, &ab->ag->dev_flags); ++ if (test_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags)) ++ return; + cancel_work_sync(&ab->reset_work); + ath12k_core_deinit(ab); + } +--- a/drivers/net/wireless/ath/ath12k/peer.c ++++ b/drivers/net/wireless/ath/ath12k/peer.c +@@ -387,8 +387,13 @@ int ath12k_ml_link_peers_delete(struct a + + ar = arvif->ar; + ++ if (!ar) ++ continue; + cancel_work_sync(&arsta->update_wk); + ++ if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags) || ++ test_bit(ATH12K_FLAG_RECOVERY, &ar->ab->dev_flags)) ++ continue; + mutex_lock(&ar->conf_mutex); + ath12k_dp_peer_cleanup(ar, arvif->vdev_id, arsta->addr); + +@@ -414,6 +419,12 @@ int ath12k_ml_link_peers_delete(struct a + + ar = arvif->ar; + ++ if (!ar) ++ continue; ++ ++ if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags) || ++ test_bit(ATH12K_FLAG_RECOVERY, &ar->ab->dev_flags)) ++ continue; + mutex_lock(&ar->conf_mutex); + ret = ath12k_wait_for_peer_delete_done(ar, arvif->vdev_id, arsta->addr); + if (ret) { +--- a/drivers/net/wireless/ath/ath12k/qmi.c ++++ b/drivers/net/wireless/ath/ath12k/qmi.c +@@ -5714,6 +5714,7 @@ static void ath12k_qmi_driver_event_work + break; + case ATH12K_QMI_EVENT_SERVER_EXIT: + set_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags); ++ clear_bit(ATH12K_FLAG_WMI_INIT_DONE, &ab->dev_flags); + break; + case ATH12K_QMI_EVENT_REQUEST_MEM: + ret = ath12k_qmi_event_mem_request(qmi); +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -542,6 +542,10 @@ int ath12k_wmi_cmd_send(struct ath12k_pd + int ret = -EOPNOTSUPP; + struct ath12k_base *ab = wmi_sc->ab; + ++ if (!(test_bit(ATH12K_FLAG_WMI_INIT_DONE, &wmi_sc->ab->dev_flags)) && ++ cmd_id != WMI_INIT_CMDID) ++ return -ESHUTDOWN; ++ + might_sleep(); + + if (ab->hw_params->credit_flow) { +@@ -13946,6 +13950,7 @@ void ath12k_wmi_detach(struct ath12k_bas + for (i = 0; i < ab->htc.wmi_ep_count; i++) + ath12k_wmi_pdev_detach(ab, i); + ++ clear_bit(ATH12K_FLAG_WMI_INIT_DONE, &ab->dev_flags); + ath12k_wmi_free_dbring_caps(ab); + } + diff --git a/feeds/ipq95xx/mac80211/patches/qca/775-ath12k-Schedule-reset_work-queue-for-cold_boot-calib.patch b/feeds/ipq95xx/mac80211/patches/qca/775-ath12k-Schedule-reset_work-queue-for-cold_boot-calib.patch new file mode 100644 index 000000000..1889547c3 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/775-ath12k-Schedule-reset_work-queue-for-cold_boot-calib.patch @@ -0,0 +1,28 @@ +From f2467a6042d3defbf139e58d10ef52b299e15d1d Mon Sep 17 00:00:00 2001 +From: Dinesh Karthikeyan +Date: Tue, 16 May 2023 11:58:48 +0530 +Subject: [PATCH] ath12k: Invoke BUG_ON during bootup FW crash + +When Q6 crash occurs while the board is in coldboot calibration, the +coldboot calibration gets timed out and dev flags for the radio is not +set to schedule reset work. Invoked BUG_ON to reboot the device. + +Signed-off-by: Dinesh Karthikeyan +--- + drivers/net/wireless/ath/ath12k/mhi.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/mhi.c +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/mhi.c 2023-05-23 12:13:12.886830583 +0530 ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/mhi.c 2023-05-23 12:15:57.575287939 +0530 +@@ -334,6 +334,9 @@ static void ath12k_mhi_op_status_cb(stru + set_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags); + queue_work(ab->workqueue_aux, &ab->reset_work); + } ++ else { ++ BUG_ON(1); ++ } + ath12k_hal_dump_srng_stats(ab); + break; + default: diff --git a/feeds/ipq95xx/mac80211/patches/qca/775-ath12k-add-support-to-enqueue-mgmt-frame-at-MLD-leve.patch b/feeds/ipq95xx/mac80211/patches/qca/775-ath12k-add-support-to-enqueue-mgmt-frame-at-MLD-leve.patch new file mode 100644 index 000000000..c2fad7493 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/775-ath12k-add-support-to-enqueue-mgmt-frame-at-MLD-leve.patch @@ -0,0 +1,207 @@ +From b8df97c3d80d790830653f82c3566e8e03636c6d Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Sun, 7 May 2023 08:06:42 +0530 +Subject: [PATCH] ath12k: add support to enqueue mgmt frame at MLD level + +Currently, unicast management frames to a certain link station +gets transmitted by FW or dropped due to retransmissions if that +link station is inactive or in power save state. A ML client can +decide to use only one of its links or can decide to put it in +power save for longer periods while listening on the other link +as per MLD listen interval. In such cases allow FW to decide on +which link a certain management frame needs to be transmitted on. + +Initially we add support for only SA query action frames. But, this +can be extended to all action frames except the ones which are not +bufferable. + +Signed-off-by: Sriram R +--- + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/mac.c | 35 +++++++++++++++++++++++- + drivers/net/wireless/ath/ath12k/wmi.c | 37 +++++++++++++++++++++++--- + drivers/net/wireless/ath/ath12k/wmi.h | 15 ++++++++++- + 4 files changed, 83 insertions(+), 5 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -107,6 +107,7 @@ enum ath12k_skb_flags { + ATH12K_SKB_HW_80211_ENCAP = BIT(0), + ATH12K_SKB_CIPHER_SET = BIT(1), + ATH12K_SKB_TX_STATUS = BIT(2), ++ ATH12K_SKB_MGMT_LINK_AGNOSTIC = BIT(3), + }; + + struct ath12k_skb_cb { +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -8473,6 +8473,7 @@ static int ath12k_mac_mgmt_tx_wmi(struct + struct ath12k_skb_cb *skb_cb; + int buf_id; + int ret; ++ bool link_agnostic; + + ATH12K_SKB_CB(skb)->ar = ar; + spin_lock_bh(&ar->txmgmt_idr_lock); +@@ -8502,7 +8503,10 @@ static int ath12k_mac_mgmt_tx_wmi(struct + + skb_cb->paddr = paddr; + +- ret = ath12k_wmi_mgmt_send(ar, arvif->vdev_id, buf_id, skb); ++ link_agnostic = ATH12K_SKB_CB(skb)->flags & ATH12K_SKB_MGMT_LINK_AGNOSTIC; ++ ++ ret = ath12k_wmi_mgmt_send(ar, arvif->vdev_id, buf_id, skb, ++ link_agnostic); + if (ret) { + ath12k_warn(ar->ab, "failed to send mgmt frame: %d\n", ret); + goto err_unmap_buf; +@@ -8639,6 +8643,22 @@ static void ath12k_mlo_mcast_update_tx_l + ether_addr_copy(hdr->addr2, bss_conf->addr); + } + ++/* This function should be called only for a mgmt frame to a ML STA, ++ * hence, such sanity checks are skipped ++ */ ++static bool ath12k_mac_is_mgmt_link_agnostic(struct sk_buff *skb) ++{ ++ struct ieee80211_mgmt *mgmt; ++ mgmt = (struct ieee80211_mgmt *)skb->data; ++ ++ if (ieee80211_is_deauth(mgmt->frame_control) || ++ ieee80211_is_disassoc(mgmt->frame_control)) ++ return true; ++ ++ /* TODO Extend as per requirement */ ++ return false; ++} ++ + static u8 ath12k_mac_get_tx_link(struct ieee80211_sta *sta, struct ieee80211_vif *vif, + u8 link, struct sk_buff *skb, u32 info_flags) + { +@@ -8721,6 +8741,19 @@ static u8 ath12k_mac_get_tx_link(struct + sta->valid_links, ahvif->links_map, ahsta->links_map); + link = IEEE80211_MLD_MAX_NUM_LINKS; + } ++ ++ /* Check if this mgmt frame can be queued at MLD level, in that ++ * case the FW can decide on which link it needs to be finally ++ * transmitted based on the power state of that link. ++ * The link param returned by this function still needs ++ * to be valid to get queued to one of the valid link FW ++ */ ++ if (ath12k_mac_is_mgmt_link_agnostic(skb)) { ++ ATH12K_SKB_CB(skb)->flags |= ATH12K_SKB_MGMT_LINK_AGNOSTIC; ++ ath12k_dbg(NULL, ATH12K_DBG_MGMT, ++ "Sending Mgmt Frame (fc %x) as link agnostic to ML STA %pM \n", ++ hdr->frame_control, sta->addr); ++ } + } + + return link; +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -867,19 +867,26 @@ struct sk_buff *ath12k_wmi_alloc_skb(str + } + + int ath12k_wmi_mgmt_send(struct ath12k *ar, u32 vdev_id, u32 buf_id, +- struct sk_buff *frame) ++ struct sk_buff *frame, bool link_agnostic) + { + struct ath12k_pdev_wmi *wmi = ar->wmi; + struct wmi_mgmt_send_cmd *cmd; ++ struct wmi_mlo_mgmt_send_params *ml_params; + struct wmi_tlv *frame_tlv; + struct sk_buff *skb; + u32 buf_len; + int ret, len; ++ void *ptr; ++ struct wmi_tlv *tlv; + + buf_len = frame->len < WMI_MGMT_SEND_DOWNLD_LEN ? + frame->len : WMI_MGMT_SEND_DOWNLD_LEN; + +- len = sizeof(*cmd) + sizeof(*frame_tlv) + roundup(buf_len, 4); ++ len = sizeof(*cmd) + sizeof(*frame_tlv) + roundup(buf_len, sizeof(u32)); ++ ++ if (link_agnostic) ++ len += sizeof(struct wmi_mgmt_send_params) + ++ TLV_HDR_SIZE + sizeof(*ml_params); + + skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len); + if (!skb) +@@ -898,12 +905,36 @@ int ath12k_wmi_mgmt_send(struct ath12k * + cmd->tx_params_valid = 0; + + frame_tlv = (struct wmi_tlv *)(skb->data + sizeof(*cmd)); +- frame_tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, buf_len); ++ frame_tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, roundup(buf_len, sizeof(u32))); + + memcpy(frame_tlv->value, frame->data, buf_len); + + ath12k_ce_byte_swap(frame_tlv->value, buf_len); + ++ if (!link_agnostic) ++ goto send; ++ ++ ptr = skb->data + sizeof(*cmd) + sizeof(*frame_tlv) + roundup(buf_len, sizeof(u32)); ++ ++ tlv = ptr; ++ ++ /* Tx params not used currently */ ++ tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_TX_SEND_PARAMS) | ++ FIELD_PREP(WMI_TLV_LEN, sizeof(struct wmi_mgmt_send_params) - TLV_HDR_SIZE); ++ ptr += sizeof(struct wmi_mgmt_send_params); ++ ++ tlv = ptr; ++ tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_STRUCT) | ++ FIELD_PREP(WMI_TLV_LEN, sizeof(*ml_params)); ++ ptr += TLV_HDR_SIZE; ++ ++ ml_params = ptr; ++ ml_params->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_MLO_TX_SEND_PARAMS) | ++ FIELD_PREP(WMI_TLV_LEN, sizeof(*ml_params) - TLV_HDR_SIZE); ++ ++ ml_params->hw_link_id = WMI_MLO_MGMT_TID; ++ ++send: + ret = ath12k_wmi_cmd_send(wmi, skb, WMI_MGMT_TX_SEND_CMDID); + if (ret) { + ath12k_warn(ar->ab, +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -4409,6 +4409,7 @@ struct wmi_scan_chan_list_cmd { + __le32 pdev_id; + } __packed; + ++#define WMI_MLO_MGMT_TID 0xFFFFFFFF + #define WMI_MGMT_SEND_DOWNLD_LEN 64 + + #define WMI_TX_PARAMS_DWORD0_POWER GENMASK(7, 0) +@@ -4436,6 +4437,18 @@ struct wmi_mgmt_send_cmd { + /* This TLV is followed by struct wmi_mgmt_frame */ + + /* Followed by struct wmi_mgmt_send_params */ ++ /* Followed by struct wmi_mlo_mgmt_send_params */ ++} __packed; ++ ++struct wmi_mlo_mgmt_send_params { ++ u32 tlv_header; ++ u32 hw_link_id; ++} __packed; ++ ++struct wmi_mgmt_send_params { ++ u32 tlv_header; ++ u32 tx_param_dword0; ++ u32 tx_param_dword1; + } __packed; + + struct wmi_sta_powersave_mode_cmd { +@@ -8258,7 +8271,7 @@ int ath12k_wmi_cmd_send(struct ath12k_pd + u32 cmd_id); + struct sk_buff *ath12k_wmi_alloc_skb(struct ath12k_wmi_base *wmi_sc, u32 len); + int ath12k_wmi_mgmt_send(struct ath12k *ar, u32 vdev_id, u32 buf_id, +- struct sk_buff *frame); ++ struct sk_buff *frame, bool link_agnostic); + int ath12k_wmi_bcn_tmpl(struct ath12k *ar, u32 vdev_id, + struct ieee80211_mutable_offsets *offs, + struct sk_buff *bcn, u32 ema_param); diff --git a/feeds/ipq95xx/mac80211/patches/qca/775-ath12k-fix-memory-leak-in-WMI-firmware-stats.patch b/feeds/ipq95xx/mac80211/patches/qca/775-ath12k-fix-memory-leak-in-WMI-firmware-stats.patch new file mode 100644 index 000000000..6d7cd08f3 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/775-ath12k-fix-memory-leak-in-WMI-firmware-stats.patch @@ -0,0 +1,62 @@ +From 392382a44c27135bfd0b02bf441b4f9582324bd7 Mon Sep 17 00:00:00 2001 +From: P Praneesh +Date: Fri, 19 May 2023 14:12:33 +0530 +Subject: [PATCH] ath12k: fix memory leak in WMI firmware stats + +Memory allocated for firmware pdev, vdev and beacon statistics +are not released during rmmod. Fix it by calling ath12k_fw_stats_free +before hardware unregister. Also, while processing the firmware +stats received in the WMI event, the local list is getting spliced +and reinitialised. Avoid calling ath12k_fw_stats_free because there +are no elements in the list after splicing. + +Signed-off-by: P Praneesh +--- + drivers/net/wireless/ath/ath12k/dp.c | 1 + + drivers/net/wireless/ath/ath12k/mac.c | 1 + + drivers/net/wireless/ath/ath12k/wmi.c | 5 +++++ + 3 files changed, 7 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c +index 5eb322d..50985b0 100644 +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -1169,6 +1169,7 @@ void ath12k_dp_pdev_free(struct ath12k_base *ab) + ar = ab->pdevs[i].ar; + ath12k_dp_rx_pdev_free(ab, i); + ath12k_dp_rx_pdev_mon_detach(ab, i); ++ ath12k_fw_stats_free(&ar->fw_stats); + ath12k_debugfs_unregister(ar); + } + } +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index beab1c7..88d804d 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -15146,6 +15146,7 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah) + err_unregister_hw: + ar = ah->radio; + for (j = 0; j < i; j++) { ++ ath12k_fw_stats_free(&ar->fw_stats); + ath12k_debugfs_unregister(ar); + ar++; + } +diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c +index 5921ab2..2bd0c7c 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -11532,6 +11532,11 @@ complete: + rcu_read_unlock(); + spin_unlock_bh(&ar->data_lock); + ++ /* Since the stats's pdev, vdev and beacon list are spliced and reinitialised ++ * at this point, no need to free the individual list. ++ */ ++ return; ++ + free: + ath12k_fw_stats_free(&stats); + } +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/775-mac80211-Fix-client-connection-issue-on-repeater-AP.patch b/feeds/ipq95xx/mac80211/patches/qca/775-mac80211-Fix-client-connection-issue-on-repeater-AP.patch new file mode 100644 index 000000000..a5545db74 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/775-mac80211-Fix-client-connection-issue-on-repeater-AP.patch @@ -0,0 +1,56 @@ +From 8b4385c68917b12da4c11548083239b8600f56f8 Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Tue, 23 May 2023 15:41:32 +0530 +Subject: [PATCH] mac80211: Fix client connection issue on repeater AP + +During AP-STA configuration, repeater AP sends packet to client +then it compares param and chandef channel compatibility but in 6G +band different channels pool maintain due to this chandef chan pointer +not compatible with param chan pointer and return EBUSY from +ieee80211_mgmt_tx. + +Fix this issue by using cfg80211_chandef_identical API. + +Signed-off-by: Aaradhana Sahu +--- + net/mac80211/offchannel.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c +index e61d867..777b71d 100644 +--- a/net/mac80211/offchannel.c ++++ b/net/mac80211/offchannel.c +@@ -922,7 +922,8 @@ int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, + if (!chanctx_conf) + continue; + +- if (mlo_sta && params->chan == chanctx_conf->def.chan && ++ if (mlo_sta && cfg80211_channel_identical(params->chan, ++ chanctx_conf->def.chan) && + ether_addr_equal(sdata->vif.addr, mgmt->sa)) { + link_id = i; + break; +@@ -935,7 +936,8 @@ int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, + */ + if (sdata->vif.valid_links && + params->link_id >= 0 && params->link_id == i && +- params->chan == chanctx_conf->def.chan) ++ cfg80211_channel_identical(params->chan, ++ chanctx_conf->def.chan)) + link_id = i; + break; + } +@@ -945,8 +947,8 @@ int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, + + if (chanctx_conf) { + need_offchan = params->chan && +- (params->chan != +- chanctx_conf->def.chan); ++ !cfg80211_channel_identical(params->chan, ++ chanctx_conf->def.chan); + } else { + need_offchan = true; + } +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/775-wifi-mac80211-Changes-for-WDS-MLD.patch b/feeds/ipq95xx/mac80211/patches/qca/775-wifi-mac80211-Changes-for-WDS-MLD.patch new file mode 100644 index 000000000..b3a27a440 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/775-wifi-mac80211-Changes-for-WDS-MLD.patch @@ -0,0 +1,208 @@ +From abd9e23af3835b9d21b9e0b9d885142dff73d741 Mon Sep 17 00:00:00 2001 +From: Ramasamy Kaliappan +Date: Wed, 17 May 2023 16:26:23 +0530 +Subject: [PATCH] cfg80211/mac80211: Changes for WDS MLD + +Add link id attributes for NL80211_CMD_UNEXPECTED_4ADDR_FRAME. + +Based on the station's link, add links to the vlan interface + +Signed-off-by: Ramasamy Kaliappan +--- + include/net/cfg80211.h | 4 +++- + net/mac80211/cfg.c | 37 +++++++++++++++++++++++++++++++++++++ + net/mac80211/rx.c | 8 +++++--- + net/wireless/nl80211.c | 13 +++++++++---- + 4 files changed, 54 insertions(+), 8 deletions(-) + +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -8544,6 +8544,7 @@ bool cfg80211_rx_spurious_frame(struct n + * @dev: The device the frame matched to + * @addr: the transmitter address + * @gfp: context flags ++ * @link_id: link id + * + * This function is used in AP mode (only!) to inform userspace that + * an associated station sent a 4addr frame but that wasn't expected. +@@ -8553,7 +8554,8 @@ bool cfg80211_rx_spurious_frame(struct n + * for a reason other than not having a subscription.) + */ + bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev, +- const u8 *addr, gfp_t gfp); ++ const u8 *addr, gfp_t gfp, ++ const int link_id); + + /** + * cfg80211_probe_status - notify userspace about probe status +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -2394,11 +2394,18 @@ static int ieee80211_change_station(stru + vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); + + if (params->vlan->ieee80211_ptr->use_4addr) { ++ struct ieee80211_sub_if_data *master; ++ struct wireless_dev *wdev; ++ + if (vlansdata->u.vlan.sta) { + err = -EBUSY; + goto out_err; + } + ++ wdev = &vlansdata->wdev; ++ master = container_of(vlansdata->bss, ++ struct ieee80211_sub_if_data, u.ap); ++ + rcu_assign_pointer(vlansdata->u.vlan.sta, sta); + __ieee80211_check_fast_rx_iface(vlansdata); + +@@ -2408,6 +2415,38 @@ static int ieee80211_change_station(stru + else + drv_sta_set_4addr(local, sta->sdata, &sta->sta, + true); ++ if (sta->sta.valid_links) { ++ int link_id; ++ for_each_set_bit(link_id, ++ &master->vif.valid_links, ++ IEEE80211_MLD_MAX_NUM_LINKS) { ++ if (!(sta->sta.valid_links & BIT(link_id))) { ++ rcu_assign_pointer( ++ vlansdata->vif.link_conf[link_id], ++ NULL); ++ rcu_assign_pointer( ++ vlansdata->link[link_id], ++ NULL); ++ memset(wdev->links[link_id].addr, ++ 0, ETH_ALEN); ++ vlansdata->vif.valid_links &= ++ ~BIT(link_id); ++ wdev->valid_links &= ~BIT(link_id); ++ } ++ else { ++ rcu_assign_pointer( ++ vlansdata->vif.link_conf[link_id], ++ master->vif.link_conf[link_id]); ++ rcu_assign_pointer(vlansdata->link[link_id], ++ master->link[link_id]); ++ memcpy(wdev->links[link_id].addr, ++ vlansdata->vif.link_conf[link_id]->bssid, ++ ETH_ALEN); ++ vlansdata->vif.valid_links |= BIT(link_id); ++ wdev->valid_links |= BIT(link_id); ++ } ++ } ++ } + } + + if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -1781,7 +1781,7 @@ EXPORT_SYMBOL(ieee80211_sta_uapsd_trigge + + void ieee80211_rx_nss_notify_4addr(struct net_device *dev, u8 *sta_addr) + { +- cfg80211_rx_unexpected_4addr_frame(dev, sta_addr, GFP_ATOMIC); ++ cfg80211_rx_unexpected_4addr_frame(dev, sta_addr, GFP_ATOMIC, -1); + } + EXPORT_SYMBOL(ieee80211_rx_nss_notify_4addr); + +@@ -1956,7 +1956,8 @@ ieee80211_rx_h_sta_process(struct ieee80 + if (!test_and_set_sta_flag(sta, WLAN_STA_4ADDR_EVENT)) + cfg80211_rx_unexpected_4addr_frame( + rx->sdata->dev, sta->sta.addr, +- GFP_ATOMIC); ++ GFP_ATOMIC, ++ rx->link_id); + return RX_DROP_MONITOR; + } + /* +@@ -3244,7 +3245,8 @@ ieee80211_rx_h_data(struct ieee80211_rx_ + if (rx->sta && + !test_and_set_sta_flag(rx->sta, WLAN_STA_4ADDR_EVENT)) + cfg80211_rx_unexpected_4addr_frame( +- rx->sdata->dev, rx->sta->sta.addr, GFP_ATOMIC); ++ rx->sdata->dev, rx->sta->sta.addr, GFP_ATOMIC, ++ rx->link_id); + return RX_DROP_MONITOR; + } + +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -19324,7 +19324,8 @@ void cfg80211_conn_failed(struct net_dev + EXPORT_SYMBOL(cfg80211_conn_failed); + + static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd, +- const u8 *addr, gfp_t gfp) ++ const u8 *addr, gfp_t gfp, ++ const int link_id) + { + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); +@@ -19350,6 +19351,9 @@ static bool __nl80211_unexpected_frame(s + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) + goto nla_put_failure; + ++ if (link_id != -1) ++ nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id); ++ + genlmsg_end(msg, hdr); + genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid); + return true; +@@ -19373,14 +19377,15 @@ bool cfg80211_rx_spurious_frame(struct n + return false; + } + ret = __nl80211_unexpected_frame(dev, NL80211_CMD_UNEXPECTED_FRAME, +- addr, gfp); ++ addr, gfp, -1); + trace_cfg80211_return_bool(ret); + return ret; + } + EXPORT_SYMBOL(cfg80211_rx_spurious_frame); + + bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev, +- const u8 *addr, gfp_t gfp) ++ const u8 *addr, gfp_t gfp, ++ const int link_id) + { + struct wireless_dev *wdev = dev->ieee80211_ptr; + bool ret; +@@ -19395,7 +19400,7 @@ bool cfg80211_rx_unexpected_4addr_frame( + } + ret = __nl80211_unexpected_frame(dev, + NL80211_CMD_UNEXPECTED_4ADDR_FRAME, +- addr, gfp); ++ addr, gfp, link_id); + trace_cfg80211_return_bool(ret); + return ret; + } +--- a/net/mac80211/chan.c ++++ b/net/mac80211/chan.c +@@ -1072,6 +1072,8 @@ __ieee80211_link_copy_chanctx_to_vlans(s + list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) { + struct ieee80211_bss_conf *vlan_conf; + ++ if (!(vlan->vif.valid_links & BIT(link_id))) ++ continue; + vlan_conf = rcu_dereference(vlan->vif.link_conf[link_id]); + if (WARN_ON(!vlan_conf)) + continue; +@@ -1281,6 +1283,8 @@ ieee80211_link_update_chandef(struct iee + list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) { + struct ieee80211_bss_conf *vlan_conf; + ++ if (!(vlan->vif.valid_links & BIT(link_id))) ++ continue; + vlan_conf = rcu_dereference(vlan->vif.link_conf[link_id]); + if (WARN_ON(!vlan_conf)) + continue; +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -1283,7 +1283,7 @@ ieee80211_tx_prepare(struct ieee80211_su + tx->sta = sta_info_get_bss(sdata, hdr->addr1); + } + if (!tx->sta && !is_multicast_ether_addr(hdr->addr1)) { +- tx->sta = sta_info_get(sdata, hdr->addr1); ++ tx->sta = sta_info_get_bss(sdata, hdr->addr1); + aggr_check = true; + } + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/776-ath12k-Enable-fwlog-support-for-IPQ5332.patch b/feeds/ipq95xx/mac80211/patches/qca/776-ath12k-Enable-fwlog-support-for-IPQ5332.patch new file mode 100644 index 000000000..23e37d4d7 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/776-ath12k-Enable-fwlog-support-for-IPQ5332.patch @@ -0,0 +1,29 @@ +From 90d984c8ee72b4076edc40f3243ec215ac1baa8c Mon Sep 17 00:00:00 2001 +From: Dinesh Karthikeyan +Date: Tue, 16 May 2023 17:11:06 +0530 +Subject: [PATCH] ath12k: Enable fwlog support for IPQ5332 + +Enable fwlog support for IPQ5332 by setting the hw_param en_fwlog to +true. + +Signed-off-by: Dinesh Karthikeyan +--- + drivers/net/wireless/ath/ath12k/hw.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath12k/hw.c b/drivers/net/wireless/ath/ath12k/hw.c +index 3b7039e..c039ee9 100644 +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -1700,7 +1700,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { + .ce_remap = &ath12k_ce_remap_ipq5332, + .cmem_remap = &ath12k_cmem_ipq5332, + .send_platform_model = true, +- .en_fwlog = false, ++ .en_fwlog = true, + }, + }; + +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/776-ath12k-add-support-for-Tx-Power-insertion.patch b/feeds/ipq95xx/mac80211/patches/qca/776-ath12k-add-support-for-Tx-Power-insertion.patch new file mode 100644 index 000000000..9fb0e0a92 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/776-ath12k-add-support-for-Tx-Power-insertion.patch @@ -0,0 +1,240 @@ +From 910f60037c90cb131499d5d2d510b08c91b7e3ec Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Mon, 22 May 2023 11:11:02 +0530 +Subject: [PATCH 2/2] ath12k: add support for Tx Power insertion + +For certain action frames like the TPC Report IE in the spectrum management +TPC Report action frame, and in the Radio Measurement Link Measurement +Report action frame there is a requirement to fill in the current +and Max Tx power of the device in the packet. + +Add support to fill in these in the above packets. Driver advertises this +capability support via NL80211_FEATURE_TX_POWER_INSERTION feature flag. + +For software encrypted case, PMF packets will be encrypted already hence +driver can't add value in this particular case. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath12k/mac.c | 183 ++++++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/mac.h | 3 + + 2 files changed, 186 insertions(+) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -273,6 +273,9 @@ static void ath12k_update_bcn_template_w + static void ath12k_update_obss_color_notify_work(struct work_struct *work); + static void ath12k_mac_remove_link_interface(struct ieee80211_hw *hw, + struct ath12k_link_vif *arvif); ++static int ath12k_fw_stats_request(struct ath12k *ar, ++ struct stats_request_params *req_param); ++ + enum nl80211_he_ru_alloc ath12k_mac_phy_he_ru_to_nl80211_he_ru_alloc(u16 ru_phy) + { + enum nl80211_he_ru_alloc ret; +@@ -8529,6 +8532,175 @@ static void ath12k_mgmt_over_wmi_tx_purg + ath12k_mgmt_over_wmi_tx_drop(ar, skb); + } + ++static int ath12k_mac_mgmt_action_frame_fill_elem(struct ath12k_link_vif *arvif, ++ struct sk_buff *skb) ++{ ++ struct ath12k *ar = arvif->ar; ++ struct ath12k_skb_cb *skb_cb; ++ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; ++ struct ieee80211_mgmt *mgmt; ++ struct ieee80211_bss_conf *link_conf; ++ struct stats_request_params req_param; ++ struct ath12k_fw_stats_pdev *pdev; ++ int ret, cur_tx_power, max_tx_power; ++ bool has_protected; ++ u8 category, *buf, iv_len; ++ u8 action_code, dialog_token; ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ /* make sure category field is present */ ++ if (skb->len < IEEE80211_MIN_ACTION_SIZE) ++ return -EINVAL; ++ ++ has_protected = ieee80211_has_protected(hdr->frame_control); ++ ++ /* SW_CRYPTO and hdr protected case (PMF), packet will be encrypted, ++ * we can't put in data in this case ++ */ ++ if (test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->ag->dev_flags) && ++ has_protected) ++ return -EOPNOTSUPP; ++ ++ mgmt = (struct ieee80211_mgmt *)hdr; ++ buf = &mgmt->u.action; ++ ++ /* FCTL_PROTECTED frame might have extra space added for HDR_LEN. Offset that ++ * many bytes if it is there ++ */ ++ if (has_protected) { ++ skb_cb = ATH12K_SKB_CB(skb); ++ ++ switch (skb_cb->cipher) { ++ /* Currently only for CCMP cipher suite, we asked for it via ++ * setting %IEEE80211_KEY_FLAG_GENERATE_IV_MGMT in key. Check ++ * ath12k_install_key() ++ */ ++ case WLAN_CIPHER_SUITE_CCMP: ++ iv_len = IEEE80211_CCMP_HDR_LEN; ++ break; ++ case WLAN_CIPHER_SUITE_TKIP: ++ case WLAN_CIPHER_SUITE_CCMP_256: ++ case WLAN_CIPHER_SUITE_GCMP: ++ case WLAN_CIPHER_SUITE_GCMP_256: ++ case WLAN_CIPHER_SUITE_AES_CMAC: ++ case WLAN_CIPHER_SUITE_BIP_GMAC_128: ++ case WLAN_CIPHER_SUITE_BIP_GMAC_256: ++ case WLAN_CIPHER_SUITE_BIP_CMAC_256: ++ iv_len = 0; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ buf = buf + iv_len; ++ } ++ ++ category = *buf++; ++ ++ switch (category) { ++ case WLAN_CATEGORY_RADIO_MEASUREMENT: ++ /* Packet Format: ++ * Action Code | Dialog Token | Variable Len (based on Action Code) ++ */ ++ action_code = *buf++; ++ dialog_token = *buf++; ++ ++ rcu_read_lock(); ++ ++ link_conf = ath12k_get_link_bss_conf(arvif); ++ ++ if (!link_conf) { ++ rcu_read_unlock(); ++ ath12k_warn(ar->ab, "unable to access bss link conf\n"); ++ return -EINVAL; ++ } ++ ++ cur_tx_power = link_conf->txpower; ++ max_tx_power = min(link_conf->chanctx_conf->def.chan->max_reg_power, ++ (int)ar->max_tx_power / 2); ++ ++ rcu_read_unlock(); ++ ++ /* fetch current tx power from FW pdev stats */ ++ req_param.pdev_id = ar->pdev->pdev_id; ++ req_param.vdev_id = 0; ++ req_param.stats_id = WMI_REQUEST_PDEV_STAT; ++ ++ ret = ath12k_fw_stats_request(ar, &req_param); ++ if (ret) { ++ ath12k_warn(ar->ab, "failed to request fw pdev stats: %d\n", ret); ++ goto check_rm_action_frame; ++ } ++ ++ spin_lock_bh(&ar->data_lock); ++ pdev = list_first_entry_or_null(&ar->fw_stats.pdevs, ++ struct ath12k_fw_stats_pdev, ++ list); ++ if (!pdev) { ++ spin_unlock_bh(&ar->data_lock); ++ goto check_rm_action_frame; ++ } ++ ++ /* Tx power is set as 2 units per dBm in FW. */ ++ cur_tx_power = pdev->chan_tx_power / 2; ++ spin_unlock_bh(&ar->data_lock); ++ ++check_rm_action_frame: ++ switch (action_code) { ++ case WLAN_ACTION_RADIO_MSR_LINK_MSR_REQ: ++ /* Variable Len Format: ++ * Transmit Power | Max Tx Power ++ * We fill both of these. ++ */ ++ *buf++ = cur_tx_power; ++ *buf = max_tx_power; ++ ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, ++ "RRM: Link Measurement Req dialog_token=%u, cur_tx_power=%d, max_tx_power=%d\n", ++ dialog_token, cur_tx_power, max_tx_power); ++ break; ++ case WLAN_ACTION_RADIO_MSR_LINK_MSR_REP: ++ /* Variable Len Format: ++ * TPC Report | Variable Fields ++ * ++ * TPC Report Format: ++ * Element ID | Len | Tx Power | Link Margin ++ * ++ * We fill Tx power in the TPC Report (2nd index) ++ */ ++ buf[2] = cur_tx_power; ++ ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, ++ "RRM: Link Measurement Resp dialog_token=%u, cur_tx_power=%d\n", ++ dialog_token, cur_tx_power); ++ break; ++ default: ++ return -EINVAL; ++ } ++ break; ++ default: ++ /* nothing to fill */ ++ return 0; ++ } ++ ++ return 0; ++} ++ ++static int ath12k_mac_mgmt_frame_fill_elem(struct ath12k_link_vif *arvif, ++ struct sk_buff *skb) ++{ ++ struct ath12k *ar = arvif->ar; ++ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ if (!ieee80211_is_action(hdr->frame_control)) ++ return 0; ++ ++ return ath12k_mac_mgmt_action_frame_fill_elem(arvif, skb); ++} ++ + static void ath12k_mgmt_over_wmi_tx_work(struct work_struct *work) + { + struct ath12k *ar = container_of(work, struct ath12k, wmi_mgmt_tx_work); +@@ -8569,6 +8741,20 @@ static void ath12k_mgmt_over_wmi_tx_work + mutex_lock(&ar->conf_mutex); + if (ar->allocated_vdev_map & (1LL << arvif->vdev_id) && + arvif->is_started) { ++ /* Fill the data which is required to be filled in by the driver ++ * Example: Max Tx power in Link Measurement Request/Report ++ */ ++ ret = ath12k_mac_mgmt_frame_fill_elem(arvif, skb); ++ if (ret) { ++ /* If we couldn't fill the data due to any reason, let's not discard ++ * transmitting the packet. ++ * For ex: SW crypto and PMF case ++ */ ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, ++ "Cant't fill in the required data for the mgmt packet. err=%d\n", ++ ret); ++ } ++ + ret = ath12k_mac_mgmt_tx_wmi(ar, arvif, skb); + if (ret) { + ath12k_warn(ar->ab, "failed to tx mgmt frame, vdev_id %d :%d\n", +@@ -15193,6 +15379,8 @@ static int ath12k_mac_hw_register(struct + hw->wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE | + NL80211_FEATURE_AP_SCAN; + ++ hw->wiphy->features |= NL80211_FEATURE_TX_POWER_INSERTION; ++ + if (ag->mlo_capable) + hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_MLO; + diff --git a/feeds/ipq95xx/mac80211/patches/qca/777-01-wifi-ath12k-Fix-tqm-release-reason-stats.patch b/feeds/ipq95xx/mac80211/patches/qca/777-01-wifi-ath12k-Fix-tqm-release-reason-stats.patch new file mode 100644 index 000000000..bd530abc9 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/777-01-wifi-ath12k-Fix-tqm-release-reason-stats.patch @@ -0,0 +1,107 @@ +From cf90e3a685be7f2697a5510bd6dd7454239b550d Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Sun, 21 May 2023 20:26:22 +0530 +Subject: [PATCH] wifi: ath12k: Fix tqm release reason stats + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/debugfs.c | 5 +++-- + drivers/net/wireless/ath/ath12k/dp.h | 2 +- + drivers/net/wireless/ath/ath12k/dp_tx.c | 7 +++++-- + drivers/net/wireless/ath/ath12k/hal_desc.h | 23 ++++++++++++++++++++++ + 4 files changed, 32 insertions(+), 5 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -1679,7 +1679,7 @@ static ssize_t ath12k_debugfs_dump_soc_d + soc_stats->tx_wbm_rel_source[4]); + + len += scnprintf(buf + len, size - len, +- "\ntqm_rel_reason: 0:%u 1:%u 2:%u 3:%u 4:%u 5:%u 6:%u 7:%u 8:%u 9:%u 10:%u 11:%u 12:%u 13:%u\n", ++ "\ntqm_rel_reason: 0:%u 1:%u 2:%u 3:%u 4:%u 5:%u 6:%u 7:%u 8:%u 9:%u 10:%u 11:%u 12:%u 13:%u 14:%u\n", + soc_stats->tqm_rel_reason[0], + soc_stats->tqm_rel_reason[1], + soc_stats->tqm_rel_reason[2], +@@ -1693,7 +1693,8 @@ static ssize_t ath12k_debugfs_dump_soc_d + soc_stats->tqm_rel_reason[10], + soc_stats->tqm_rel_reason[11], + soc_stats->tqm_rel_reason[12], +- soc_stats->tqm_rel_reason[13]); ++ soc_stats->tqm_rel_reason[13], ++ soc_stats->tqm_rel_reason[14]); + + len += scnprintf(buf + len, size - len, + "\nfw_tx_status: 0:%u 1:%u 2:%u 3:%u 4:%u 5:%u 6:%u\n", +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -286,7 +286,7 @@ struct ath12k_pdev_dp { + /* Invalid TX Bank ID value */ + #define DP_INVALID_BANK_ID -1 + +-#define MAX_TQM_RELEASE_REASON 14 ++#define MAX_TQM_RELEASE_REASON 15 + #define MAX_FW_TX_STATUS 7 + #define MAX_TCL_RING 4 + +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -1332,6 +1332,11 @@ int ath12k_dp_tx_completion_handler(stru + /* Find the HAL_WBM_RELEASE_INFO0_REL_SRC_MODULE value */ + buf_rel_source = tx_status->info0 & HAL_WBM_RELEASE_INFO0_REL_SRC_MASK; + ab->soc_stats.tx_wbm_rel_source[buf_rel_source]++; ++ ++ rel_status = FIELD_GET(HAL_WBM_COMPL_TX_INFO0_TQM_RELEASE_REASON, ++ tx_status->info0); ++ ab->soc_stats.tqm_rel_reason[rel_status]++; ++ + if (unlikely(buf_rel_source == HAL_WBM_REL_SRC_MODULE_FW)) { + ath12k_dp_tx_process_htt_tx_complete(ab, + (void *)tx_status, +@@ -1376,8 +1381,6 @@ int ath12k_dp_tx_completion_handler(stru + + if (unlikely(msdu->destructor)) { + msdu->wifi_acked_valid = 1; +- rel_status = FIELD_GET(HAL_WBM_COMPL_TX_INFO0_TQM_RELEASE_REASON, +- tx_status->info0); + msdu->wifi_acked = rel_status == HAL_WBM_TQM_REL_REASON_FRAME_ACKED; + } + if (unlikely(skb_has_frag_list(msdu))) { +--- a/drivers/net/wireless/ath/ath12k/hal_desc.h ++++ b/drivers/net/wireless/ath/ath12k/hal_desc.h +@@ -2026,6 +2026,19 @@ struct hal_wbm_release_ring { + * fw with fw_reason2. + * @HAL_WBM_TQM_REL_REASON_CMD_REMOVE_RESEAON3: Remove command initiated by + * fw with fw_reason3. ++ * @HAL_WBM_TQM_REL_REASON_CMD_DISABLE_QUEUE: Remove command initiated by ++ * fw with disable queue. ++ * @HAL_WBM_TQM_REL_REASON_CMD_TILL_NONMATCHING: Remove command initiated by ++ * fw to remove all mpdu until 1st non-match. ++ * @HAL_WBM_TQM_REL_REASON_DROP_THRESHOLD: Dropped due to drop threshold ++ * criteria ++ * @HAL_WBM_TQM_REL_REASON_DROP_LINK_DESC_UNAVAIL: Dropped due to link desc ++ * not available ++ * @HAL_WBM_TQM_REL_REASON_DROP_OR_INVALID_MSDU: Dropped due drop bit set or ++ * null flow ++ * @HAL_WBM_TQM_REL_REASON_MULTICAST_DROP: Dropped due mcast drop set for VDEV ++ * @HAL_WBM_TQM_REL_REASON_VDEV_MISMATCH_DROP: Dropped due to being set with ++ * 'TCL_drop_reason' + */ + enum hal_wbm_tqm_rel_reason { + HAL_WBM_TQM_REL_REASON_FRAME_ACKED, +@@ -2036,6 +2049,16 @@ enum hal_wbm_tqm_rel_reason { + HAL_WBM_TQM_REL_REASON_CMD_REMOVE_RESEAON1, + HAL_WBM_TQM_REL_REASON_CMD_REMOVE_RESEAON2, + HAL_WBM_TQM_REL_REASON_CMD_REMOVE_RESEAON3, ++ HAL_WBM_TQM_REL_REASON_CMD_DISABLE_QUEUE, ++ HAL_WBM_TQM_REL_REASON_CMD_TILL_NONMATCHING, ++ HAL_WBM_TQM_REL_REASON_DROP_THRESHOLD, ++ HAL_WBM_TQM_REL_REASON_DROP_LINK_DESC_UNAVAIL, ++ HAL_WBM_TQM_REL_REASON_DROP_OR_INVALID_MSDU, ++ HAL_WBM_TQM_REL_REASON_MULTICAST_DROP, ++ HAL_WBM_TQM_REL_REASON_VDEV_MISMATCH_DROP, ++ ++ /* Keep Last */ ++ HAL_WBM_TQM_REL_REASON_MAX, + }; + + struct hal_wbm_buffer_ring { diff --git a/feeds/ipq95xx/mac80211/patches/qca/777-02-wifi-ath12k-fix-ath12k-link-stats-missed-for-complet.patch b/feeds/ipq95xx/mac80211/patches/qca/777-02-wifi-ath12k-fix-ath12k-link-stats-missed-for-complet.patch new file mode 100644 index 000000000..a879ef0aa --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/777-02-wifi-ath12k-fix-ath12k-link-stats-missed-for-complet.patch @@ -0,0 +1,89 @@ +From 15fc9619f3983a265966266348f621aeafa5bf19 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Tue, 23 May 2023 10:10:58 +0530 +Subject: [PATCH] wifi: ath12k: fix ath12k link stats missed for completed + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/dp_tx.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -743,6 +743,19 @@ ath12k_dp_tx_htt_tx_complete_buf(struct + + /* Free skb here if stats is disabled */ + if (drop_disable) { ++ if (skb_cb->vif) { ++ ahvif = (void *)skb_cb->vif->drv_priv; ++ if (ahvif->links_map & BIT(skb_cb->link_id)) { ++ if (ahvif->link[skb_cb->link_id]) ++ ahvif->link[skb_cb->link_id]->link_stats.tx_completed++; ++ } else { ++ ath12k_warn(ab, ++ "invalid linkid 0x%X in htt tx complete buf linkmap 0x%X\n", ++ skb_cb->link_id, ++ ahvif->links_map); ++ } ++ } ++ + if (msdu->destructor) { + msdu->wifi_acked_valid = 1; + msdu->wifi_acked = ts->acked; +@@ -762,13 +775,15 @@ ath12k_dp_tx_htt_tx_complete_buf(struct + + vif = skb_cb->vif; + ahvif = (void *)vif->drv_priv; +- if (ahvif->links_map & BIT(skb_cb->link_id)) +- ahvif->link[skb_cb->link_id]->link_stats.tx_completed++; +- else ++ if (ahvif->links_map & BIT(skb_cb->link_id)) { ++ if (ahvif->link[skb_cb->link_id]) ++ ahvif->link[skb_cb->link_id]->link_stats.tx_completed++; ++ } else { + ath12k_warn(ab, + "invalid linkid 0x%X in htt tx complete buf linkmap 0x%X\n", + skb_cb->link_id, + ahvif->links_map); ++ } + + memset(&info->status, 0, sizeof(info->status)); + +@@ -1039,13 +1054,15 @@ static void ath12k_dp_tx_complete_msdu(s + + vif = skb_cb->vif; + ahvif = (void *)vif->drv_priv; +- if (ahvif->links_map & BIT(skb_cb->link_id)) +- ahvif->link[skb_cb->link_id]->link_stats.tx_completed++; +- else ++ if (ahvif->links_map & BIT(skb_cb->link_id)) { ++ if (ahvif->link[skb_cb->link_id]) ++ ahvif->link[skb_cb->link_id]->link_stats.tx_completed++; ++ } else { + ath12k_warn(ar->ab, + "invalid linkid 0x%X in tx complete msdu linkmap 0x%X\n", + skb_cb->link_id, + ahvif->links_map); ++ } + + info = IEEE80211_SKB_CB(msdu); + memset(&info->status, 0, sizeof(info->status)); +@@ -1393,13 +1410,15 @@ int ath12k_dp_tx_completion_handler(stru + + if (skb_cb->vif) { + ahvif = (void *)skb_cb->vif->drv_priv; +- if (ahvif->links_map & BIT(skb_cb->link_id)) +- ahvif->link[skb_cb->link_id]->link_stats.tx_completed++; +- else ++ if (ahvif->links_map & BIT(skb_cb->link_id)) { ++ if (ahvif->link[skb_cb->link_id]) ++ ahvif->link[skb_cb->link_id]->link_stats.tx_completed++; ++ } else { + ath12k_warn(ab, + "invalid linkid 0x%X in tx completion handler for linkmap 0x%X\n", + skb_cb->link_id, + ahvif->links_map); ++ } + } + + if (unlikely(msdu->destructor)) { diff --git a/feeds/ipq95xx/mac80211/patches/qca/777-ath12k-Add-soc_dp_stats-for-incorrect-reo-desc-first-and-last-msdu.patch b/feeds/ipq95xx/mac80211/patches/qca/777-ath12k-Add-soc_dp_stats-for-incorrect-reo-desc-first-and-last-msdu.patch new file mode 100644 index 000000000..7180be0b5 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/777-ath12k-Add-soc_dp_stats-for-incorrect-reo-desc-first-and-last-msdu.patch @@ -0,0 +1,65 @@ +From 121a3493ffb2db869ade34bad6f33e90e7ce0cd4 Mon Sep 17 00:00:00 2001 +From: Rajat Soni +Date: Wed, 7 Jun 2023 11:49:23 +0530 +Subject: [PATCH] ath12k: Add soc_dp_stats for incorrect reo desc first and last msdu + +Currently we are receiving a ppdu that is not having first/last msdu bit set in +reo desc i.e hal_reo_dest_ring this causes this warning. + +Due to this no functionality is impacted, so moving this warning to stats to get +how many times first/last msdu bit is not set. + +Note: This is a workaround need to revert this change. + +Signed-off-by: Rajat Soni +--- + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/debugfs.c | 4 ++++ + drivers/net/wireless/ath/ath12k/dp_rx.c | 4 +++- + 3 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h +index 61bf541..b160162 100644 +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -1138,6 +1138,7 @@ struct ath12k_soc_dp_stats { + u32 rx_wbm_rel_source[HAL_WBM_REL_SRC_MODULE_MAX] [ATH12K_MAX_SOCS]; + struct ath12k_soc_dp_tx_err_stats tx_err; + struct ath12k_dp_ring_bp_stats bp_stats; ++ u32 first_and_last_msdu_bit_miss; + }; + + #ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT +diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c +index 7d6c33f..a88c9ce 100644 +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -1755,6 +1755,10 @@ static ssize_t ath12k_debugfs_dump_soc_dp_stats(struct file *file, + soc_stats->rx_wbm_rel_source[i][1], + soc_stats->rx_wbm_rel_source[i][2]); + ++ len += scnprintf(buf + len, size - len, ++ "\nFIRST/LAST MSDU BIT MISSING COUNT: %u\n", ++ soc_stats->first_and_last_msdu_bit_miss); ++ + len += ath12k_debugfs_dump_soc_ring_bp_stats(ab, buf + len, size - len); + + if (len > size) +diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c +index 1625805..7b0b932 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -2543,7 +2543,9 @@ static void ath12k_dp_rx_h_undecap_raw(struct ath12k *ar, struct sk_buff *msdu, + + if (!rxcb->is_first_msdu || + !(rxcb->is_first_msdu && rxcb->is_last_msdu)) { +- WARN_ON_ONCE(1); ++ /* TODO: Change below stats increment back to WARN_ON_ONCE(1) ++ */ ++ ar->ab->soc_stats.first_and_last_msdu_bit_miss++; + return; + } + +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/777-wifi-ath12k-Rx-data-path-optimizations.patch b/feeds/ipq95xx/mac80211/patches/qca/777-wifi-ath12k-Rx-data-path-optimizations.patch new file mode 100644 index 000000000..4a5c2b8ff --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/777-wifi-ath12k-Rx-data-path-optimizations.patch @@ -0,0 +1,497 @@ +From 8ca602964a46846ac942c7f5e7eeb84fceb5c9f3 Mon Sep 17 00:00:00 2001 +From: Balamurugan S +Date: Thu, 25 May 2023 22:54:24 +0530 +Subject: [PATCH] wifi: ath12k: Rx data path optimizations + +1) Optimized ath12k_dp_rx_h_fetch_info(). Multiple de reference were made +to fetch descriptor fields. This has been optimized to read the desc info +field once and operate on the same to avoid cache miss. + +2) Introduced unlikely condition check in ath12k_dp_rx_check_fast_rx() for +branch optimizations. + +3) Introduced prefetch logic while processing msdu's in +ath12k_dp_rx_process_received_packets() + +With all the above changes UDP uplink max throughput could reach +up to 6800Mbps for ipq5322. + +Signed-off-by: Balamurugan S +--- + drivers/net/wireless/ath/ath12k/dp_rx.c | 168 +++++++++--------------- + drivers/net/wireless/ath/ath12k/dp_rx.h | 12 ++ + drivers/net/wireless/ath/ath12k/hal.c | 57 ++++++++ + drivers/net/wireless/ath/ath12k/hal.h | 7 + + 4 files changed, 139 insertions(+), 105 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -96,18 +96,6 @@ static bool ath12k_dp_rx_h_msdu_done(str + return ab->hw_params->hal_ops->dp_rx_h_msdu_done(desc); + } + +-static bool ath12k_dp_rx_h_l4_cksum_fail(struct ath12k_base *ab, +- struct hal_rx_desc *desc) +-{ +- return ab->hw_params->hal_ops->dp_rx_h_l4_cksum_fail(desc); +-} +- +-static bool ath12k_dp_rx_h_ip_cksum_fail(struct ath12k_base *ab, +- struct hal_rx_desc *desc) +-{ +- return ab->hw_params->hal_ops->dp_rx_h_ip_cksum_fail(desc); +-} +- + static bool ath12k_dp_rx_h_is_decrypted(struct ath12k_base *ab, + struct hal_rx_desc *desc) + { +@@ -126,42 +114,6 @@ static u16 ath12k_dp_rx_h_msdu_len(struc + return ab->hw_params->hal_ops->rx_desc_get_msdu_len(desc); + } + +-static u8 ath12k_dp_rx_h_sgi(struct ath12k_base *ab, +- struct hal_rx_desc *desc) +-{ +- return ab->hw_params->hal_ops->rx_desc_get_msdu_sgi(desc); +-} +- +-static u8 ath12k_dp_rx_h_rate_mcs(struct ath12k_base *ab, +- struct hal_rx_desc *desc) +-{ +- return ab->hw_params->hal_ops->rx_desc_get_msdu_rate_mcs(desc); +-} +- +-static u8 ath12k_dp_rx_h_rx_bw(struct ath12k_base *ab, +- struct hal_rx_desc *desc) +-{ +- return ab->hw_params->hal_ops->rx_desc_get_msdu_rx_bw(desc); +-} +- +-static u32 ath12k_dp_rx_h_freq(struct ath12k_base *ab, +- struct hal_rx_desc *desc) +-{ +- return ab->hw_params->hal_ops->rx_desc_get_msdu_freq(desc); +-} +- +-static u8 ath12k_dp_rx_h_pkt_type(struct ath12k_base *ab, +- struct hal_rx_desc *desc) +-{ +- return ab->hw_params->hal_ops->rx_desc_get_msdu_pkt_type(desc); +-} +- +-static u8 ath12k_dp_rx_h_nss(struct ath12k_base *ab, +- struct hal_rx_desc *desc) +-{ +- return hweight8(ab->hw_params->hal_ops->rx_desc_get_msdu_nss(desc)); +-} +- + static u8 ath12k_dp_rx_h_tid(struct ath12k_base *ab, + struct hal_rx_desc *desc) + { +@@ -206,12 +158,6 @@ static void ath12k_dp_rxdesc_set_msdu_le + ab->hw_params->hal_ops->rx_desc_set_msdu_len(desc, len); + } + +-static bool ath12k_dp_rx_h_is_mcbc(struct ath12k_base *ab, +- struct hal_rx_desc *desc) +-{ +- return (ath12k_dp_rx_h_first_msdu(ab, desc) && +- ab->hw_params->hal_ops->rx_desc_is_mcbc(desc)); +-} + + static bool ath12k_dp_rxdesc_mac_addr2_valid(struct ath12k_base *ab, + struct hal_rx_desc *desc) +@@ -2246,7 +2192,8 @@ void ath12k_dp_htt_htc_t2h_msg_handler(s + static int ath12k_dp_rx_msdu_coalesce(struct ath12k *ar, + struct sk_buff_head *msdu_list, + struct sk_buff *first, struct sk_buff *last, +- u8 l3pad_bytes, int msdu_len) ++ u8 l3pad_bytes, int msdu_len, ++ struct ath12k_dp_rx_info *rx_info) + { + struct ath12k_base *ab = ar->ab; + struct sk_buff *skb; +@@ -2270,8 +2217,9 @@ static int ath12k_dp_rx_msdu_coalesce(st + } + + ldesc = (struct hal_rx_desc *)last->data; +- rxcb->is_first_msdu = ath12k_dp_rx_h_first_msdu(ab, ldesc); +- rxcb->is_last_msdu = ath12k_dp_rx_h_last_msdu(ab, ldesc); ++ ab->hw_params->hal_ops->rx_desc_get_first_last_msdu(ldesc, rx_info); ++ rxcb->is_first_msdu = rx_info->is_first_msdu; ++ rxcb->is_last_msdu = rx_info->is_last_msdu; + + /* MSDU spans over multiple buffers because the length of the MSDU + * exceeds DP_RX_BUFFER_SIZE - HAL_RX_DESC_SIZE. So assume the data +@@ -2323,6 +2271,13 @@ static int ath12k_dp_rx_msdu_coalesce(st + rem_len -= buf_len; + if (!rxcb->is_continuation) + break; ++ ++ skb = msdu_list->next; ++ if (likely(skb)) { ++ prefetch(skb); ++ prefetch(skb->data + 64); ++ prefetch(skb->data + 128); ++ } + } + + return 0; +@@ -2346,14 +2301,13 @@ static struct sk_buff *ath12k_dp_rx_get_ + return NULL; + } + +-static void ath12k_dp_rx_h_csum_offload(struct ath12k *ar, struct sk_buff *msdu) ++static void ath12k_dp_rx_h_csum_offload(struct ath12k *ar, struct sk_buff *msdu, ++ struct ath12k_dp_rx_info *rx_info) + { +- struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu); +- struct ath12k_base *ab = ar->ab; + bool ip_csum_fail, l4_csum_fail; + +- ip_csum_fail = ath12k_dp_rx_h_ip_cksum_fail(ab, rxcb->rx_desc); +- l4_csum_fail = ath12k_dp_rx_h_l4_cksum_fail(ab, rxcb->rx_desc); ++ ip_csum_fail = rx_info->ip_csum_fail; ++ l4_csum_fail = rx_info->l4_csum_fail; + + msdu->ip_summed = (ip_csum_fail || l4_csum_fail) ? + CHECKSUM_NONE : CHECKSUM_UNNECESSARY; +@@ -2733,31 +2687,35 @@ ath12k_dp_rx_h_find_peer(struct ath12k_b + static bool ath12k_dp_rx_check_fast_rx(struct ath12k *ar, + struct sk_buff *msdu, + struct hal_rx_desc *rx_desc, +- struct ath12k_peer *peer) ++ struct ath12k_peer *peer, ++ struct ath12k_dp_rx_info *rx_info) + { + struct ethhdr *ehdr; + struct ath12k_peer *f_peer; + struct ath12k_skb_rxcb *rxcb; + u8 decap; ++ bool ip_is_valid; + + lockdep_assert_held(&ar->ab->base_lock); + +- decap = ath12k_dp_rx_h_decap_type(ar->ab, rx_desc); ++ decap = rx_info->decap_type; ++ ip_is_valid = rx_info->ip_is_valid; ++ + rxcb = ATH12K_SKB_RXCB(msdu); + +- if (!ar->ab->stats_disable || ++ if (unlikely(!ar->ab->stats_disable || + decap != DP_RX_DECAP_TYPE_ETHERNET2_DIX || +- peer->vif->type != NL80211_IFTYPE_AP) ++ peer->vif->type != NL80211_IFTYPE_AP)) + return false; + + /* mcbc packets go through mac80211 for PN validation */ +- if (rxcb->is_mcbc) ++ if (unlikely(rxcb->is_mcbc)) + return false; + +- if (!peer->is_authorized) ++ if (unlikely(!peer->is_authorized)) + return false; + +- if (!ath12k_dp_rx_h_msdu_end_ip_valid(ar->ab, rx_desc)) ++ if (unlikely(!ip_is_valid)) + return false; + + /* fast rx is supported only on ethernet decap, so +@@ -2797,8 +2755,8 @@ static void ath12k_dp_rx_h_mpdu(struct a + struct ieee80211_hdr *hdr; + struct ath12k_peer *peer; + struct ieee80211_rx_status *rx_status = rx_info->rx_status; +- struct ath12k_dp_rx_tid *rx_tid; + u32 err_bitmap; ++ struct ath12k_dp_rx_tid *rx_tid; + u8 tid; + #if defined(CPTCFG_MAC80211_PPE_SUPPORT) || defined(CPTCFG_ATH12K_BONDED_DS_SUPPORT) + int vp; +@@ -2807,14 +2765,13 @@ static void ath12k_dp_rx_h_mpdu(struct a + struct ath12k_vif *ahvif; + struct ath12k_link_vif *arvif; + +- tid = ath12k_dp_rx_h_tid(ab, rx_desc); + /* PN for multicast packets will be checked in mac80211 */ + rxcb = ATH12K_SKB_RXCB(msdu); +- fill_crypto_hdr = ath12k_dp_rx_h_is_mcbc(ar->ab, rx_desc); ++ fill_crypto_hdr = rx_info->is_mcbc; + rxcb->is_mcbc = fill_crypto_hdr; + + if (rxcb->is_mcbc) +- rxcb->peer_id = ath12k_dp_rx_h_peer_id(ar->ab, rx_desc); ++ rxcb->peer_id = rx_info->peer_id; + + spin_lock_bh(&ar->ab->base_lock); + peer = ath12k_dp_rx_h_find_peer(ar->ab, msdu, rx_info); +@@ -2824,20 +2781,16 @@ static void ath12k_dp_rx_h_mpdu(struct a + * pkts with crypto error are not expected to arrive in this + * path, so its safe to skip checking errors here */ + if (*fast_rx && +- ath12k_dp_rx_check_fast_rx(ar, msdu, rx_desc, peer)) { +- rx_tid = &peer->rx_tid[tid]; +- ar->wmm_stats.rx_type = +- ath12k_tid_to_ac(rx_tid->tid > ATH12K_DSCP_PRIORITY ? 0: rx_tid->tid); +- ar->wmm_stats.total_wmm_rx_pkts[ar->wmm_stats.rx_type]++; ++ ath12k_dp_rx_check_fast_rx(ar, msdu, rx_desc, peer, rx_info)) { + wdev = ieee80211_vif_to_wdev(peer->vif); + if (wdev) { + #ifdef CPTCFG_MAC80211_PPE_SUPPORT + vp = peer->vif->ppe_vp_num; + #endif + spin_unlock_bh(&ar->ab->base_lock); +- ath12k_dp_rx_h_csum_offload(ar, msdu); ++ ath12k_dp_rx_h_csum_offload(ar, msdu, rx_info); + #ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT +- ahvif = (struct ath12k_vif *)peer->vif->drv_priv; ++ ahvif = ath12k_vif_to_ahvif(peer->vif); + arvif = ahvif->link[peer->link_id]; + vp = arvif->ppe_vp_num; + if (wdev->bond_netdev) +@@ -2856,6 +2809,13 @@ static void ath12k_dp_rx_h_mpdu(struct a + return; + } + } ++ ++ tid = rx_info->tid; ++ rx_tid = &peer->rx_tid[tid]; ++ ar->wmm_stats.rx_type = ++ ath12k_tid_to_ac(rx_tid->tid > ATH12K_DSCP_PRIORITY ? 0: rx_tid->tid); ++ ar->wmm_stats.total_wmm_rx_pkts[ar->wmm_stats.rx_type]++; ++ + if (rxcb->is_mcbc) + enctype = peer->sec_type_grp; + else +@@ -2902,7 +2862,7 @@ static void ath12k_dp_rx_h_mpdu(struct a + RX_FLAG_PN_VALIDATED; + } + +- ath12k_dp_rx_h_csum_offload(ar, msdu); ++ ath12k_dp_rx_h_csum_offload(ar, msdu, rx_info); + ath12k_dp_rx_h_undecap(ar, msdu, rx_desc, + enctype, rx_status, is_decrypted); + +@@ -3010,26 +2970,17 @@ static void ath12k_dp_rx_h_fetch_info(st + struct hal_rx_desc *rx_desc, + struct ath12k_dp_rx_info *rx_info) + { +- rx_info->decap_type = ath12k_dp_rx_h_decap_type(ab, rx_desc); +- rx_info->filled |= BIT_ULL(ATH12K_RX_INFO_DECAP_TYPE); +- +- rx_info->pkt_type = ath12k_dp_rx_h_pkt_type(ab, rx_desc); +- rx_info->filled |= BIT_ULL(ATH12K_RX_INFO_PKT_TYPE); +- +- rx_info->sgi = ath12k_dp_rx_h_sgi(ab, rx_desc); +- rx_info->filled |= BIT_ULL(ATH12K_RX_INFO_SGI); ++ ab->hw_params->hal_ops->rx_get_desc_info(rx_desc, rx_info); ++ rx_info->filled |= BIT_ULL(ATH12K_RX_INFO_PHY_META_DATA) | ++ BIT_ULL(ATH12K_RX_INFO_DECAP_TYPE) | ++ BIT_ULL(ATH12K_RX_INFO_PKT_TYPE) | ++ BIT_ULL(ATH12K_RX_INFO_SGI) | ++ BIT_ULL(ATH12K_RX_INFO_RATE_MCS) | ++ BIT_ULL(ATH12K_RX_INFO_BW) | ++ BIT_ULL(ATH12K_RX_INFO_NSS); + +- rx_info->rate_mcs = ath12k_dp_rx_h_rate_mcs(ab, rx_desc); +- rx_info->filled |= BIT_ULL(ATH12K_RX_INFO_RATE_MCS); +- +- rx_info->bw = ath12k_dp_rx_h_rx_bw(ab, rx_desc); +- rx_info->filled |= BIT_ULL(ATH12K_RX_INFO_BW); +- +- rx_info->nss = ath12k_dp_rx_h_nss(ab, rx_desc); +- rx_info->filled |= BIT_ULL(ATH12K_RX_INFO_NSS); +- +- rx_info->phy_meta_data = ath12k_dp_rx_h_freq(ab, rx_desc); +- rx_info->filled |= BIT_ULL(ATH12K_RX_INFO_PHY_META_DATA); ++ if (ab->stats_disable) ++ return; + + if (ath12k_dp_rxdesc_mac_addr2_valid(ab, rx_desc)) { + ether_addr_copy(rx_info->addr2, +@@ -3252,7 +3203,8 @@ static int ath12k_dp_rx_process_msdu(str + + rx_desc = (struct hal_rx_desc *)msdu->data; + lrx_desc = (struct hal_rx_desc *)last_buf->data; +- if (!ath12k_dp_rx_h_msdu_done(ab, lrx_desc)) { ++ ab->hw_params->hal_ops->rx_get_desc_msdulen_l3pad(lrx_desc, rx_info); ++ if (!rx_info->msdu_done) { + ath12k_warn(ab, "msdu_done bit in msdu_end is not set\n"); + ret = -EIO; + goto free_out; +@@ -3260,8 +3212,8 @@ static int ath12k_dp_rx_process_msdu(str + + rxcb = ATH12K_SKB_RXCB(msdu); + rxcb->rx_desc = rx_desc; +- msdu_len = ath12k_dp_rx_h_msdu_len(ab, lrx_desc); +- l3_pad_bytes = ath12k_dp_rx_h_l3pad(ab, lrx_desc); ++ msdu_len = rx_info->msdu_len; ++ l3_pad_bytes = rx_info->l3_pad_bytes; + + if (rxcb->is_frag) { + skb_pull(msdu, hal_rx_desc_sz); +@@ -3278,7 +3230,8 @@ static int ath12k_dp_rx_process_msdu(str + } else { + ret = ath12k_dp_rx_msdu_coalesce(ar, msdu_list, + msdu, last_buf, +- l3_pad_bytes, msdu_len); ++ l3_pad_bytes, msdu_len, ++ rx_info); + if (ret) { + ath12k_warn(ab, + "failed to coalesce msdu rx buffer%d\n", ret); +@@ -3321,6 +3274,7 @@ static void ath12k_dp_rx_process_receive + u8 mac_id, hw_link_id; + int ret; + bool fast_rx; ++ struct sk_buff *skb; + + if (skb_queue_empty(msdu_list)) + return; +@@ -3331,6 +3285,12 @@ static void ath12k_dp_rx_process_receive + rcu_read_lock(); + + while ((msdu = __skb_dequeue(msdu_list))) { ++ skb = msdu_list->next; ++ if (likely(skb)) { ++ prefetch(skb); ++ prefetch(skb->data + 64); ++ prefetch(skb->data + 128); ++ } + rxcb = ATH12K_SKB_RXCB(msdu); + /* Enable fast rx by default, the value will cahnge based on peer cap + * and packet type */ +@@ -3357,7 +3317,7 @@ static void ath12k_dp_rx_process_receive + continue; + } + +- if (test_bit(ATH12K_CAC_RUNNING, &ar->dev_flags)) { ++ if (unlikely(test_bit(ATH12K_CAC_RUNNING, &ar->dev_flags))) { + dev_kfree_skb_any(msdu); + continue; + } +--- a/drivers/net/wireless/ath/ath12k/dp_rx.h ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.h +@@ -130,6 +130,18 @@ struct ath12k_dp_rx_info { + u8 nss; + u32 phy_meta_data; + u8 addr2[ETH_ALEN]; ++ bool ip_csum_fail; ++ bool l4_csum_fail; ++ u8 ip_is_valid; ++ u8 decap; ++ u16 peer_id; ++ bool is_mcbc; ++ u8 l3_pad_bytes; ++ u16 msdu_len; ++ u8 tid; ++ bool msdu_done; ++ bool is_first_msdu; ++ bool is_last_msdu; + struct ieee80211_rx_status *rx_status; + }; + +--- a/drivers/net/wireless/ath/ath12k/hal.c ++++ b/drivers/net/wireless/ath/ath12k/hal.c +@@ -10,6 +10,7 @@ + #include "debug.h" + #include "hal_desc.h" + #include "hif.h" ++#include "dp_rx.h" + + static const struct hal_srng_config hw_srng_config_template[] = { + /* TODO: max_rings can populated by querying HW capabilities */ +@@ -677,6 +678,59 @@ static u32 ath12k_hw_qcn9274_dp_rx_h_mpd + return errmap; + } + ++static void ath12k_hw_qcn9274_get_rx_first_last_msdu(struct hal_rx_desc *desc, ++ struct ath12k_dp_rx_info *rx_info) ++{ ++ rx_info->is_first_msdu = !!le16_get_bits(desc->u.qcn9274.msdu_end.info5, ++ RX_MSDU_END_INFO5_FIRST_MSDU); ++ rx_info->is_last_msdu = !!le16_get_bits(desc->u.qcn9274.msdu_end.info5, ++ RX_MSDU_END_INFO5_LAST_MSDU); ++} ++ ++static void ath12k_hw_qcn9274_get_rx_msdulen_l3pad(struct hal_rx_desc *desc, ++ struct ath12k_dp_rx_info *rx_info) ++{ ++ ++ rx_info->msdu_done = !!le32_get_bits(desc->u.qcn9274.msdu_end.info14, ++ RX_MSDU_END_INFO14_MSDU_DONE); ++ rx_info->msdu_len = le32_get_bits(desc->u.qcn9274.msdu_end.info10, ++ RX_MSDU_END_INFO10_MSDU_LENGTH); ++ rx_info->l3_pad_bytes = le16_get_bits(desc->u.qcn9274.msdu_end.info5, ++ RX_MSDU_END_INFO5_L3_HDR_PADDING); ++} ++ ++static void ath12k_hw_qcn9274_get_rx_desc_info(struct hal_rx_desc *desc, ++ struct ath12k_dp_rx_info *rx_info) ++{ ++ __le32 info12 = desc->u.qcn9274.msdu_end.info12; ++ __le32 info13 = desc->u.qcn9274.msdu_end.info13; ++ __le32 info11 = desc->u.qcn9274.msdu_end.info11; ++ ++ rx_info->pkt_type = le32_get_bits(info12, RX_MSDU_END_INFO12_PKT_TYPE); ++ rx_info->sgi = le32_get_bits(info12, RX_MSDU_END_INFO12_SGI); ++ rx_info->rate_mcs = le32_get_bits(info12, RX_MSDU_END_INFO12_RATE_MCS); ++ rx_info->bw = le32_get_bits(info12, RX_MSDU_END_INFO12_RECV_BW); ++ rx_info->nss = hweight8(le32_get_bits(info12, RX_MSDU_END_INFO12_MIMO_SS_BITMAP)); ++ rx_info->phy_meta_data = __le32_to_cpu(desc->u.qcn9274.msdu_end.phy_meta_data); ++ ++ rx_info->ip_csum_fail = !!le32_get_bits(info13, RX_MSDU_END_INFO13_IP_CKSUM_FAIL); ++ rx_info->l4_csum_fail = !!le32_get_bits(info13, RX_MSDU_END_INFO13_TCP_UDP_CKSUM_FAIL); ++ rx_info->ip_is_valid = (le32_get_bits(__le32_to_cpu(info11), RX_MSDU_END_INFO11_IPV4) || ++ le32_get_bits(__le32_to_cpu(info11), RX_MSDU_END_INFO11_IPV6)); ++ ++ rx_info->decap_type = le32_get_bits(info11, RX_MSDU_END_INFO11_DECAP_FORMAT); ++ ++ rx_info->is_mcbc = ((!!le16_get_bits(desc->u.qcn9274.msdu_end.info5, ++ RX_MSDU_END_INFO5_FIRST_MSDU)) && ++ (__le32_to_cpu(desc->u.qcn9274.mpdu_start.info6) & ++ RX_MPDU_START_INFO6_MCAST_BCAST)); ++ ++ rx_info->peer_id = le16_get_bits(desc->u.qcn9274.mpdu_start.sw_peer_id, ++ RX_MPDU_START_SW_PEER_ID_PEER); ++ rx_info->tid = le16_get_bits(desc->u.qcn9274.msdu_end.info5, ++ RX_MSDU_END_INFO5_TID); ++} ++ + const struct hal_ops hal_qcn9274_ops = { + .rx_desc_get_first_msdu = ath12k_hw_qcn9274_rx_desc_get_first_msdu, + .rx_desc_get_last_msdu = ath12k_hw_qcn9274_rx_desc_get_last_msdu, +@@ -720,6 +774,9 @@ const struct hal_ops hal_qcn9274_ops = { + .rxdma_ring_wmask_rx_mpdu_start = ath12k_hal_rx_mpdu_start_wmask_get, + .rxdma_ring_wmask_rx_msdu_end = ath12k_hal_rx_msdu_end_wmask_get, + .rx_desc_get_msdu_src_link_id = ath12k_hw_qcn9274_rx_desc_get_msdu_src_link, ++ .rx_get_desc_info = ath12k_hw_qcn9274_get_rx_desc_info, ++ .rx_get_desc_msdulen_l3pad = ath12k_hw_qcn9274_get_rx_msdulen_l3pad, ++ .rx_desc_get_first_last_msdu = ath12k_hw_qcn9274_get_rx_first_last_msdu, + }; + + static bool ath12k_hw_wcn7850_rx_desc_get_first_msdu(struct hal_rx_desc *desc) +--- a/drivers/net/wireless/ath/ath12k/hal.h ++++ b/drivers/net/wireless/ath/ath12k/hal.h +@@ -12,6 +12,7 @@ + #include "core.h" + + struct ath12k_base; ++struct ath12k_dp_rx_info; + #define HAL_CE_REMAP_REG_BASE (ab->ce_remap_base_addr) + + #define HAL_LINK_DESC_SIZE (32 << 2) +@@ -1147,6 +1148,12 @@ struct hal_ops { + u16 (*rxdma_ring_wmask_rx_mpdu_start)(void); + u32 (*rxdma_ring_wmask_rx_msdu_end)(void); + u8 (*rx_desc_get_msdu_src_link_id)(struct hal_rx_desc *desc); ++ void (*rx_get_desc_info)(struct hal_rx_desc *desc, ++ struct ath12k_dp_rx_info *info); ++ void (*rx_get_desc_msdulen_l3pad)(struct hal_rx_desc *desc, ++ struct ath12k_dp_rx_info *info); ++ void (*rx_desc_get_first_last_msdu)(struct hal_rx_desc *desc, ++ struct ath12k_dp_rx_info *info); + }; + + extern const struct hal_ops hal_qcn9274_ops; diff --git a/feeds/ipq95xx/mac80211/patches/qca/778-ath12k-Validate-tx-arvif-start-status-before-non-Tx-.patch b/feeds/ipq95xx/mac80211/patches/qca/778-ath12k-Validate-tx-arvif-start-status-before-non-Tx-.patch new file mode 100644 index 000000000..f280a9c6f --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/778-ath12k-Validate-tx-arvif-start-status-before-non-Tx-.patch @@ -0,0 +1,52 @@ +From 399cdac1a36470f38ae74797125b28e9adcc43e1 Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Tue, 30 May 2023 17:05:47 +0530 +Subject: [PATCH] ath12k: Validate tx arvif start status before non Tx beacon + setup + +Currently, In rare cases of MLO combination failures, there could be cases +when a non Tx vap can be setup though the Tx vap setup is pending (due +to failure in partner setup). Since hostapd couldnt identify the failure +and avoid non Tx vap and partner bringup(to be added for safety), always +have a protection in drive to prevent setup of non Tx vap if Tx vap is +not started yet + +Signed-off-by: Sriram R +--- + drivers/net/wireless/ath/ath12k/mac.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -1588,6 +1588,15 @@ static int ath12k_mac_setup_bcn_tmpl_ema + rcu_read_unlock(); + return -ENOLINK; + } ++ ++ if (arvif != tx_arvif && !tx_arvif->is_started) { ++ rcu_read_unlock(); ++ ath12k_warn(arvif->ar->ab, ++ "Transmit vif is not started before this non Tx beacon setup for vdev %d\n", ++ arvif->vdev_id); ++ return -EINVAL; ++ } ++ + lockdep_assert_held(&tx_arvif->ar->conf_mutex); + beacons = ieee80211_beacon_get_template_ema_list(tx_arvif->ar->ah->hw, + tx_ahvif->vif, +@@ -1659,6 +1668,15 @@ static int ath12k_mac_setup_bcn_tmpl_non + rcu_read_unlock(); + return -ENOLINK; + } ++ ++ if (arvif != tx_arvif && !tx_arvif->is_started) { ++ rcu_read_unlock(); ++ ath12k_warn(arvif->ar->ab, ++ "Transmit vif is not started before this non Tx beacon setup for vdev %d\n", ++ arvif->vdev_id); ++ return -EINVAL; ++ } ++ + lockdep_assert_held(&tx_arvif->ar->conf_mutex); + bcn = ieee80211_beacon_get_template(tx_arvif->ar->ah->hw, tx_ahvif->vif, + &offs, tx_arvif->link_id); diff --git a/feeds/ipq95xx/mac80211/patches/qca/778-cfg80211-Increase-grace-period-for-PRE-CAC-timeout.patch b/feeds/ipq95xx/mac80211/patches/qca/778-cfg80211-Increase-grace-period-for-PRE-CAC-timeout.patch new file mode 100644 index 000000000..abd81dee2 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/778-cfg80211-Increase-grace-period-for-PRE-CAC-timeout.patch @@ -0,0 +1,26 @@ +From 7a49f8e3650580613e2ca6f5ab8b7b08e6685966 Mon Sep 17 00:00:00 2001 +From: Dinesh Karthikeyan +Date: Wed, 24 May 2023 20:13:32 +0530 +Subject: [PATCH] cfg80211: Increase grace period for PRE CAC timeout + +Increase the grace period for PRE CAC timeout to 8 seconds to bring up +5G vap in DFS channel to handle MAX number of MLDs case. + +Signed-off-by: Dinesh Karthikeyan +--- + net/wireless/reg.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: backports-20220822-5.4.213-ef7197996efe/net/wireless/reg.h +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/net/wireless/reg.h 2023-05-30 12:44:20.539353585 +0530 ++++ backports-20220822-5.4.213-ef7197996efe/net/wireless/reg.h 2023-05-30 12:44:38.699413210 +0530 +@@ -152,7 +152,7 @@ bool regulatory_indoor_allowed(void); + * value is used for Non-ETSI domain. + * TODO: May be make this timeout available through regdb? + */ +-#define REG_PRE_CAC_EXPIRY_GRACE_MS 2000 ++#define REG_PRE_CAC_EXPIRY_GRACE_MS 8000 + + #define REG_BG_PRE_CAC_EXPIRY_GRACE_MS 2000 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/778-wifi-ath12k-Add-Tx-limit-for-data-packets.patch b/feeds/ipq95xx/mac80211/patches/qca/778-wifi-ath12k-Add-Tx-limit-for-data-packets.patch new file mode 100644 index 000000000..1937ca34d --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/778-wifi-ath12k-Add-Tx-limit-for-data-packets.patch @@ -0,0 +1,137 @@ +From 8ff1dcb57da132e32e3db9be63992ca93433aaae Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Wed, 24 May 2023 15:46:32 +0530 +Subject: [PATCH] wifi: ath12k: Add Tx limit for data packets + +Limit the Tx data packet per pdev based on the threshold of 0x8000 +by reserving 1k for EAPOL frames. Which helps memory usage in Multiclient +setup with heavy traffic. Without the Tx limit check Multicast frames +send lead to out of memory in the system where HW capable of processing +more than the system memory profile. + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/core.h | 2 ++ + drivers/net/wireless/ath/ath12k/debugfs.c | 4 +++ + drivers/net/wireless/ath/ath12k/dp.h | 3 ++ + drivers/net/wireless/ath/ath12k/mac.c | 43 ++++++++++++++++++++++- + 4 files changed, 51 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -1106,6 +1106,8 @@ struct ath12k_soc_dp_tx_err_stats { + /* TCL Ring Buffers unavailable */ + u32 txbuf_na[DP_TCL_NUM_RING_MAX]; + ++ u32 threshold_limit; ++ + /* Other failures during dp_tx due to mem allocation failure + * idr unavailable etc. + */ +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -1647,6 +1647,10 @@ static ssize_t ath12k_debugfs_dump_soc_d + i, soc_stats->tx_err.txbuf_na[i]); + + len += scnprintf(buf + len, size - len, ++ "\nThreshold limit: %d\n", ++ soc_stats->tx_err.threshold_limit); ++ ++ len += scnprintf(buf + len, size - len, + "\nMisc Transmit Failures: %d\n", + atomic_read(&soc_stats->tx_err.misc_fail)); + +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -277,6 +277,9 @@ struct ath12k_pdev_dp { + #define DP_REO_QREF_NUM GENMASK(31, 16) + #define DP_MAX_PEER_ID 2047 + ++#define ATH12K_NUM_EAPOL_RESERVE 1024 ++#define ATH12K_DP_PDEV_TX_LIMIT (ATH12K_NUM_POOL_TX_DESC - ATH12K_NUM_EAPOL_RESERVE) ++ + /* Total size of the LUT is based on 2K peers, each having reference + * for 17tids, note each entry is of type ath12k_reo_queue_ref + * hence total size is 2048 * 17 * 8 = 278528 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -8912,6 +8912,19 @@ static u8 ath12k_mac_get_tx_link(struct + return link; + } + ++static bool ath12k_mac_tx_check_max_limit(struct ath12k *ar, struct sk_buff *skb) ++{ ++ if (atomic_read(&ar->dp.num_tx_pending) > ATH12K_DP_PDEV_TX_LIMIT) { ++ /* Allow EAPOL */ ++ if (!(skb->protocol == cpu_to_be16(ETH_P_PAE))) { ++ ar->ab->soc_stats.tx_err.threshold_limit++; ++ return true; ++ } ++ } ++ ++ return false; ++} ++ + static void ath12k_mac_op_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) +@@ -8978,7 +8991,19 @@ static void ath12k_mac_op_tx(struct ieee + ieee80211_free_txskb(hw, skb); + return; + } ++ ++ ar = arvif->ar; ++ + if (skb->fast_xmit) { ++ ret = ath12k_mac_tx_check_max_limit(ar, skb); ++ if (ret) { ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, ++ "failed fast tx due to limit check pdev idx %d\n", ++ ar->pdev_idx); ++ ieee80211_free_txskb(hw, skb); ++ return; ++ } ++ + ret = ath12k_dp_tx_direct(arvif, skb); + if (unlikely(ret)) { + ath12k_dbg(arvif->ar->ab, ATH12K_DBG_MAC, +@@ -8988,7 +9013,6 @@ static void ath12k_mac_op_tx(struct ieee + return; + } + +- ar = arvif->ar; + ah = ar->ah; + + if (unlikely(test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))) { +@@ -9043,6 +9067,15 @@ static void ath12k_mac_op_tx(struct ieee + + if (!vif->valid_links || !is_mcast || + test_bit(ATH12K_FLAG_RAW_MODE, &ar->ab->ag->dev_flags)) { ++ ret = ath12k_mac_tx_check_max_limit(ar, skb); ++ if (ret) { ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, ++ "failed due to limit check pdev idx %d\n", ++ ar->pdev_idx); ++ ieee80211_free_txskb(hw, skb); ++ return; ++ } ++ + ret = ath12k_dp_tx(ar, arvif, ahsta, skb, false, 0); + if (unlikely(ret)) { + if (ret == -ENOMEM) +@@ -9073,6 +9106,15 @@ static void ath12k_mac_op_tx(struct ieee + continue; + + tmp_ar = tmp_arvif->ar; ++ ++ ret = ath12k_mac_tx_check_max_limit(tmp_ar, skb); ++ if (ret) { ++ ath12k_dbg(tmp_ar->ab, ATH12K_DBG_MAC, ++ "failed mcast tx due to limit check pdev idx %d\n", ++ tmp_ar->pdev_idx); ++ continue; ++ } ++ + msdu_copied = skb_copy(skb, GFP_ATOMIC); + if (!msdu_copied) { + ath12k_err(ar->ab, diff --git a/feeds/ipq95xx/mac80211/patches/qca/779-01-wifi-ath12k-optimize-the-mgmt-and-data-tx-pending-wa.patch b/feeds/ipq95xx/mac80211/patches/qca/779-01-wifi-ath12k-optimize-the-mgmt-and-data-tx-pending-wa.patch new file mode 100644 index 000000000..154cc5130 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/779-01-wifi-ath12k-optimize-the-mgmt-and-data-tx-pending-wa.patch @@ -0,0 +1,156 @@ +From 88daecb31cf8efffe7b945725bc9ad83ac6850a6 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Thu, 18 May 2023 11:27:36 +0530 +Subject: [PATCH 1/2] wifi: ath12k: optimize the mgmt and data tx pending + wait/wake call + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/core.c | 1 - + drivers/net/wireless/ath/ath12k/dp.c | 1 - + drivers/net/wireless/ath/ath12k/dp.h | 1 - + drivers/net/wireless/ath/ath12k/dp_tx.c | 6 +++--- + drivers/net/wireless/ath/ath12k/mac.c | 18 ++++++------------ + 5 files changed, 9 insertions(+), 18 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -1814,11 +1814,10 @@ static void ath12k_core_pre_reconfigure_ + complete(&ar->bss_survey_done); + complete(&ar->thermal.wmi_sync); + +- wake_up(&ar->dp.tx_empty_waitq); + idr_for_each(&ar->txmgmt_idr, + ath12k_mac_tx_mgmt_pending_free, ar); + idr_destroy(&ar->txmgmt_idr); +- wake_up(&ar->txmgmt_empty_waitq); ++ wake_up(&ar->tx_empty_waitq); + + ar->monitor_vdev_id = -1; + clear_bit(MONITOR_VDEV_STARTED, &ar->monitor_flags); +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -1168,7 +1168,6 @@ void ath12k_dp_pdev_pre_alloc(struct ath + dp = &ar->dp; + dp->mac_id = i; + atomic_set(&dp->num_tx_pending, 0); +- init_waitqueue_head(&dp->tx_empty_waitq); + + /*TODO Add any RXDMA setup required per pdev*/ + } +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -133,7 +133,6 @@ struct ath12k_mon_data { + struct ath12k_pdev_dp { + u32 mac_id; + atomic_t num_tx_pending; +- wait_queue_head_t tx_empty_waitq; + struct dp_srng rxdma_mon_dst_ring[MAX_RXDMA_PER_PDEV]; + struct dp_srng tx_mon_dst_ring[MAX_RXDMA_PER_PDEV]; + +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -694,7 +694,7 @@ static void ath12k_dp_tx_free_txbuf(stru + + ar = ab->pdevs[mac_id].ar; + if (atomic_dec_and_test(&ar->dp.num_tx_pending)) +- wake_up(&ar->dp.tx_empty_waitq); ++ wake_up(&ar->tx_empty_waitq); + } + + static void +@@ -720,7 +720,7 @@ ath12k_dp_tx_htt_tx_complete_buf(struct + ab->soc_stats.tx_completed[tx_ring->tcl_data_ring_id]++; + + if (atomic_dec_and_test(&ar->dp.num_tx_pending)) +- wake_up(&ar->dp.tx_empty_waitq); ++ wake_up(&ar->tx_empty_waitq); + + flags = skb_cb->flags; + drop_disable = (ab->stats_disable && !(flags & ATH12K_SKB_TX_STATUS)); +@@ -1358,7 +1358,7 @@ int ath12k_dp_tx_completion_handler(stru + } + ar = ab->pdevs[mac_id].ar; + if (atomic_dec_and_test(&ar->dp.num_tx_pending)) +- wake_up(&ar->dp.tx_empty_waitq); ++ wake_up(&ar->tx_empty_waitq); + + if (unlikely(WARN_ON_ONCE(buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM))) { + /* Must not happen */ +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -8421,7 +8421,7 @@ static void ath12k_mgmt_over_wmi_tx_drop + WARN_ON_ONCE(1); + + if (!num_mgmt) +- wake_up(&ar->txmgmt_empty_waitq); ++ wake_up(&ar->tx_empty_waitq); + } + + static void ath12k_mac_tx_mgmt_free(struct ath12k *ar, int buf_id) +@@ -12950,22 +12950,21 @@ static void ath12k_mac_flush(struct ath1 + + lockdep_assert_held(&ar->ah->conf_mutex); + +- time_left = wait_event_timeout(ar->dp.tx_empty_waitq, +- (atomic_read(&ar->dp.num_tx_pending) == 0), ++ time_left = wait_event_timeout(ar->tx_empty_waitq, ++ ((atomic_read(&ar->dp.num_tx_pending) == 0) && ++ (atomic_read(&ar->num_pending_mgmt_tx) == 0)), + ATH12K_FLUSH_TIMEOUT); +- if (time_left == 0) +- ath12k_warn(ab, "failed to flush transmit queue %ld\n", time_left); +- +- time_left = wait_event_timeout(ar->txmgmt_empty_waitq, +- (atomic_read(&ar->num_pending_mgmt_tx) == 0), +- ATH12K_FLUSH_TIMEOUT); +- if (time_left == 0) +- ath12k_warn(ab, "failed to flush mgmt transmit queue %ld\n", +- time_left); ++ if (time_left == 0) { ++ ath12k_warn(ab, "failed to flush transmit queue pending mgmt %d data %d\n", ++ atomic_read(&ar->num_pending_mgmt_tx), ++ atomic_read(&ar->dp.num_tx_pending)); ++ return; ++ } + + ath12k_dbg(ab, ATH12K_DBG_MAC, +- "mac mgmt tx flush mgmt pending %d\n", +- atomic_read(&ar->num_pending_mgmt_tx)); ++ "mac tx flush pending mgmt %d data %d\n", ++ atomic_read(&ar->num_pending_mgmt_tx), ++ atomic_read(&ar->dp.num_tx_pending)); + } + + static void ath12k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, +@@ -15150,7 +15149,7 @@ static int __ath12k_mac_register(struct + u32 ht_cap = 0; + + hw = ar->ah->hw; +- init_waitqueue_head(&ar->txmgmt_empty_waitq); ++ init_waitqueue_head(&ar->tx_empty_waitq); + idr_init(&ar->txmgmt_idr); + spin_lock_init(&ar->txmgmt_idr_lock); + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -934,7 +934,7 @@ struct ath12k { + /* protects txmgmt_idr data */ + spinlock_t txmgmt_idr_lock; + atomic_t num_pending_mgmt_tx; +- wait_queue_head_t txmgmt_empty_waitq; ++ wait_queue_head_t tx_empty_waitq; + + /* cycle count is reported twice for each visited channel during scan. + * access protected by data_lock +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -7129,7 +7129,7 @@ skip_mgmt_stats: + + + if (!num_mgmt) +- wake_up(&ar->txmgmt_empty_waitq); ++ wake_up(&ar->tx_empty_waitq); + + return 0; + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/779-02-wifi-ath12k-Wake-the-tx-pending-wait-only-its-in-wai.patch b/feeds/ipq95xx/mac80211/patches/qca/779-02-wifi-ath12k-Wake-the-tx-pending-wait-only-its-in-wai.patch new file mode 100644 index 000000000..7814a1c84 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/779-02-wifi-ath12k-Wake-the-tx-pending-wait-only-its-in-wai.patch @@ -0,0 +1,177 @@ +From 123e25ff6c0cf6cca9d87088bcb9dc959bf57eb4 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Sat, 20 May 2023 14:28:18 +0530 +Subject: [PATCH 2/2] wifi: ath12k: Wake the tx pending wait only its in wait + state + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/dp.c | 1 + + drivers/net/wireless/ath/ath12k/dp_tx.c | 27 ++++++++++++++----------- + drivers/net/wireless/ath/ath12k/mac.c | 7 ++++++- + drivers/net/wireless/ath/ath12k/wmi.c | 6 ++++-- + 5 files changed, 27 insertions(+), 15 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -934,6 +934,7 @@ struct ath12k { + struct idr txmgmt_idr; + /* protects txmgmt_idr data */ + spinlock_t txmgmt_idr_lock; ++ atomic_t flush_request; + atomic_t num_pending_mgmt_tx; + wait_queue_head_t tx_empty_waitq; + +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -1175,6 +1175,7 @@ void ath12k_dp_pdev_pre_alloc(struct ath + dp = &ar->dp; + dp->mac_id = i; + atomic_set(&dp->num_tx_pending, 0); ++ atomic_set(&ar->flush_request, 0); + + /*TODO Add any RXDMA setup required per pdev*/ + } +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -677,12 +677,21 @@ fail_remove_tx_buf: + return ret; + } + ++static inline void ath12k_dp_tx_decrement(struct ath12k *ar) ++{ ++ if (atomic_read(&ar->flush_request)) { ++ if (atomic_dec_and_test(&ar->dp.num_tx_pending)) ++ wake_up(&ar->tx_empty_waitq); ++ } else { ++ atomic_dec(&ar->dp.num_tx_pending); ++ } ++} ++ + static void ath12k_dp_tx_free_txbuf(struct ath12k_base *ab, + struct sk_buff *msdu, u8 mac_id, + struct dp_tx_ring *tx_ring, + struct sk_buff *skb_ext_desc) + { +- struct ath12k *ar; + struct ath12k_skb_cb *skb_cb; + + skb_cb = ATH12K_SKB_CB(msdu); +@@ -698,9 +707,7 @@ static void ath12k_dp_tx_free_txbuf(stru + + dev_kfree_skb_any(msdu); + +- ar = ab->pdevs[mac_id].ar; +- if (atomic_dec_and_test(&ar->dp.num_tx_pending)) +- wake_up(&ar->tx_empty_waitq); ++ ath12k_dp_tx_decrement(ab->pdevs[mac_id].ar); + } + + static void +@@ -725,8 +732,7 @@ ath12k_dp_tx_htt_tx_complete_buf(struct + ar = ab->pdevs[mac_id].ar; + ab->soc_stats.tx_completed[tx_ring->tcl_data_ring_id]++; + +- if (atomic_dec_and_test(&ar->dp.num_tx_pending)) +- wake_up(&ar->tx_empty_waitq); ++ ath12k_dp_tx_decrement(ar); + + flags = skb_cb->flags; + drop_disable = (ab->stats_disable && !(flags & ATH12K_SKB_TX_STATUS)); +@@ -1390,8 +1396,8 @@ int ath12k_dp_tx_completion_handler(stru + continue; + } + ar = ab->pdevs[mac_id].ar; +- if (atomic_dec_and_test(&ar->dp.num_tx_pending)) +- wake_up(&ar->tx_empty_waitq); ++ ++ ath12k_dp_tx_decrement(ar); + + if (unlikely(WARN_ON_ONCE(buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM))) { + /* Must not happen */ +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -8442,7 +8442,7 @@ static void ath12k_mgmt_over_wmi_tx_drop + if (num_mgmt < 0) + WARN_ON_ONCE(1); + +- if (!num_mgmt) ++ if (atomic_read(&ar->flush_request) && !num_mgmt) + wake_up(&ar->tx_empty_waitq); + } + +@@ -9644,6 +9644,7 @@ static void ath12k_mac_radio_stop(struct + synchronize_rcu(); + + atomic_set(&ar->num_pending_mgmt_tx, 0); ++ atomic_set(&ar->flush_request, 0); + + spin_lock_bh(&ar->data_lock); + ar->awgn_intf_handling_in_prog = false; +@@ -13026,10 +13027,12 @@ static void ath12k_mac_flush(struct ath1 + + lockdep_assert_held(&ar->ah->conf_mutex); + ++ atomic_inc(&ar->flush_request); + time_left = wait_event_timeout(ar->tx_empty_waitq, + ((atomic_read(&ar->dp.num_tx_pending) == 0) && + (atomic_read(&ar->num_pending_mgmt_tx) == 0)), + ATH12K_FLUSH_TIMEOUT); ++ atomic_dec(&ar->flush_request); + if (time_left == 0) { + ath12k_warn(ab, "failed to flush transmit queue pending mgmt %d data %d\n", + atomic_read(&ar->num_pending_mgmt_tx), +@@ -13048,7 +13051,9 @@ static void ath12k_mac_op_flush(struct i + { + struct ath12k_hw *ah = hw->priv; + struct ath12k *ar; ++ struct ath12k_vif *ahvif; + int i; ++ u8 link_id; + + if (drop) + return; +@@ -13065,16 +13070,23 @@ static void ath12k_mac_op_flush(struct i + ar++; + } + } else { +- /* TODO in case of ML links, flush all link vif */ +- ar = ath12k_get_ar_by_vif(hw, vif, 0); +- if (!ar) { +- ath12k_err(NULL, +- "unable to determine device for tx flush\n"); +- goto out; ++ ahvif = (void *)vif->drv_priv; ++ ++ for_each_set_bit(link_id, &ahvif->links_map, ATH12K_NUM_MAX_LINKS) { ++ if (!ahvif->link[link_id]) ++ continue; ++ ++ ar = ath12k_get_ar_by_vif(hw, vif, link_id); ++ if (!ar) { ++ ath12k_err(NULL, ++ "unable to determine device for link_id %d tx flush\n", ++ link_id); ++ continue; ++ } ++ ath12k_mac_flush(ar); + } +- ath12k_mac_flush(ar); + } +-out: ++ + mutex_unlock(&ah->conf_mutex); + } + +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -7209,7 +7209,7 @@ skip_mgmt_stats: + WARN_ON_ONCE(1); + + +- if (!num_mgmt) ++ if (atomic_read(&ar->flush_request) && !num_mgmt) + wake_up(&ar->tx_empty_waitq); + + return 0; diff --git a/feeds/ipq95xx/mac80211/patches/qca/779-ath12k-sawf-add-telemetry-configurations.patch b/feeds/ipq95xx/mac80211/patches/qca/779-ath12k-sawf-add-telemetry-configurations.patch new file mode 100644 index 000000000..3d34f0ba9 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/779-ath12k-sawf-add-telemetry-configurations.patch @@ -0,0 +1,652 @@ +From 93307a43f24632b79706b1f7ac0a18713261f481 Mon Sep 17 00:00:00 2001 +From: Mahendran P +Date: Mon, 29 May 2023 10:16:32 +0530 +Subject: [PATCH] ath12k: sawf: add telemetry configurations. + +Add below listed telemetry configurations + sla samples configuration + sla thershold configuration + sla detection configuration + +sla samples configuration +These configurations helps to take samples for the sla calculation. +Four configuration parameters are provided + Number of packets per window for moving average calculation + Number of windows for moving average calculation + Number of packets for sla calculation + Number of seconds for sla calculation + +sla thershold configuration +These configurations define the thershold in percentage for each +of the given configuration. If the thershold is crossed, then it +is considered as breach. For each service class id, the corresponding +parameter thershold percentages are configured. + +sla detection configuration +These configurations defines the sla breach detection options and its +corresponding configurations +There are four detection options provided + 1. Sla detection based on number of packets + 2. Sla detection based on per second + 3. Sla detection based on moving average + 4. Sla detection based on number of seconds + +Signed-off-by: Mahendran P +--- + drivers/net/wireless/ath/ath12k/Makefile | 3 +- + drivers/net/wireless/ath/ath12k/core.c | 3 + + drivers/net/wireless/ath/ath12k/telemetry.c | 193 ++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/telemetry.h | 111 +++++++++++ + drivers/net/wireless/ath/ath12k/vendor.c | 182 ++++++++++++++++++ + drivers/net/wireless/ath/ath12k/vendor.h | 48 +++++ + 6 files changed, 539 insertions(+), 1 deletion(-) + create mode 100644 drivers/net/wireless/ath/ath12k/telemetry.c + create mode 100644 drivers/net/wireless/ath/ath12k/telemetry.h + +--- a/drivers/net/wireless/ath/ath12k/Makefile ++++ b/drivers/net/wireless/ath/ath12k/Makefile +@@ -22,7 +22,8 @@ ath12k-y += core.o \ + pci.o \ + dp_mon.o \ + sawf.o \ +- vendor.o ++ vendor.o \ ++ telemetry.o + + ath12k-$(CPTCFG_ATH12K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o + ath12k-$(CPTCFG_NL80211_TESTMODE) += testmode.o +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -21,6 +21,7 @@ + #include "sawf.h" + #include "ppe.h" + #include "ahb.h" ++#include "telemetry.h" + + unsigned int ath12k_debug_mask; + module_param_named(debug_mask, ath12k_debug_mask, uint, 0644); +@@ -1085,6 +1086,7 @@ static int ath12k_core_pdev_init(struct + } + + ath12k_sawf_init(ab); ++ ath12k_telemetry_init(ab); + + #ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT + ret = ath12k_dp_ppeds_start(ab); +@@ -1113,6 +1115,7 @@ static void ath12k_core_pdev_deinit(stru + #endif + ath12k_spectral_deinit(ab); + ath12k_thermal_unregister(ab); ++ ath12k_telemetry_deinit(ab); + ath12k_sawf_deinit(ab); + } + +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/telemetry.c +@@ -0,0 +1,184 @@ ++// SPDX-License-Identifier: BSD-3-Clause-Clear ++/* ++ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include "core.h" ++#include "debug.h" ++#include "sawf.h" ++#include "vendor.h" ++#include "telemetry.h" ++#include ++ ++ ++#define MIN_THERSHOLD_PERCENTAGE 0 ++#define MAX_THERSHOLD_PERCENTAGE 100 ++ ++static struct ath12k_telemetry_ctx *telemetry_ctx; ++ ++void ath12k_telemetry_init(struct ath12k_base *ab) ++{ ++ if (!ath12k_sawf_enable) ++ return; ++ ++ if (telemetry_ctx) ++ return; ++ ++ telemetry_ctx = kzalloc(sizeof(struct ath12k_telemetry_ctx), GFP_KERNEL); ++ if (!telemetry_ctx) { ++ ath12k_err(NULL, "telemetry context failed to initialize\n"); ++ return; ++ } ++ ath12k_info(NULL, "telemetry context initialized\n"); ++ return; ++} ++ ++void ath12k_telemetry_deinit(struct ath12k_base *ab) ++{ ++ if (!ath12k_sawf_enable) ++ return; ++ ++ if (!telemetry_ctx) ++ return; ++ ++ kfree(telemetry_ctx); ++ telemetry_ctx = NULL; ++ ath12k_info(NULL, "telemetry context freed\n"); ++ return; ++} ++ ++struct ath12k_telemetry_ctx *get_telemetry_context(void) ++{ ++ if (!telemetry_ctx) { ++ ath12k_err(NULL, "telemetry context not initialized\n"); ++ return NULL; ++ } ++ return telemetry_ctx; ++} ++ ++int ath12k_telemetry_sawf_sla_samples_config(struct ath12k_sla_samples_cfg param) ++{ ++ struct ath12k_sla_samples_cfg* telemetry_param; ++ int ret = 0; ++ ++ if (param.moving_avg_pkt == 0 || param.moving_avg_win == 0 || ++ param.sla_num_pkt == 0 || param.sla_time_sec == 0) { ++ ath12k_err(NULL, "invalid telemetry sla samples configuration \n"); ++ return -EINVAL; ++ } ++ ++ telemetry_param = &telemetry_ctx->sla_samples_params; ++ telemetry_param->moving_avg_pkt = param.moving_avg_pkt; ++ telemetry_param->moving_avg_win = param.moving_avg_win; ++ telemetry_param->sla_num_pkt = param.sla_num_pkt; ++ telemetry_param->sla_time_sec = param.sla_time_sec; ++ ++ ath12k_info(NULL, "telemetry sla samples configuration done, " ++ "movavgpkt:%d movavgwin:%d slanumpkt:%d slatimesec:%d \n", ++ telemetry_param->moving_avg_pkt,telemetry_param->moving_avg_win, ++ telemetry_param->sla_num_pkt, telemetry_param->sla_time_sec); ++ ++ return ret; ++} ++ ++int ath12k_telemetry_sawf_sla_thershold_config(struct ath12k_sla_thershold_cfg param) ++{ ++ struct ath12k_sla_thershold_cfg* sla_thershold_param; ++ int ret = 0; ++ ++ if (param.min_throughput_rate < MIN_THERSHOLD_PERCENTAGE || ++ param.min_throughput_rate > MAX_THERSHOLD_PERCENTAGE || ++ param.max_throughput_rate < MIN_THERSHOLD_PERCENTAGE || ++ param.max_throughput_rate > MAX_THERSHOLD_PERCENTAGE || ++ param.burst_size < MIN_THERSHOLD_PERCENTAGE || ++ param.burst_size > MAX_THERSHOLD_PERCENTAGE || ++ param.service_interval < MIN_THERSHOLD_PERCENTAGE || ++ param.service_interval > MAX_THERSHOLD_PERCENTAGE || ++ param.delay_bound < MIN_THERSHOLD_PERCENTAGE || ++ param.delay_bound > MAX_THERSHOLD_PERCENTAGE || ++ param.msdu_ttl < MIN_THERSHOLD_PERCENTAGE || ++ param.msdu_ttl > MAX_THERSHOLD_PERCENTAGE || ++ param.msdu_rate_loss < MIN_THERSHOLD_PERCENTAGE || ++ param.msdu_rate_loss > MAX_THERSHOLD_PERCENTAGE) { ++ ath12k_err(NULL, "invalid telemetry sla thershold configuration \n"); ++ return -EINVAL; ++ } ++ ++ sla_thershold_param = &telemetry_ctx->sla_thershold_params; ++ sla_thershold_param->svc_id = param.svc_id; ++ sla_thershold_param->min_throughput_rate = param.min_throughput_rate; ++ sla_thershold_param->max_throughput_rate = param.max_throughput_rate; ++ sla_thershold_param->burst_size = param.burst_size; ++ sla_thershold_param->service_interval = param.service_interval; ++ sla_thershold_param->delay_bound = param.delay_bound; ++ sla_thershold_param->msdu_ttl = param.msdu_ttl; ++ sla_thershold_param->msdu_rate_loss = param.msdu_rate_loss; ++ ++ ath12k_info(NULL, "telemetry sla thershold configuration done, " ++ "svcid: %d MinThrRate:%d MaxThrRate:%d BurstSize:%d " ++ "serviceInt:%d \n DelayBound: %d MsduTtl:%d " ++ "msdurateloss:%d \n", sla_thershold_param->svc_id, ++ sla_thershold_param->min_throughput_rate, ++ sla_thershold_param->max_throughput_rate, ++ sla_thershold_param->burst_size, ++ sla_thershold_param->service_interval, ++ sla_thershold_param->delay_bound, ++ sla_thershold_param->msdu_ttl, ++ sla_thershold_param->msdu_rate_loss); ++ return ret; ++} ++ ++int ath12k_telemetry_sawf_sla_detection_config(struct ath12k_sla_detect_cfg param) ++{ ++ struct ath12k_sla_detect_cfg* telemetry_param; ++ int ret = 0; ++ ++ if ((param.sla_detect == SLA_DETECT_NUM_PACKET) && ++ (param.min_throughput_rate || param.max_throughput_rate || ++ param.burst_size || param.service_interval)) { ++ ath12k_info(NULL, "unsupported sla detect config for number of packets.\n"); ++ return -1; ++ } ++ ++ if (((param.sla_detect == SLA_DETECT_PER_SECOND)) && ++ (param.burst_size || param.service_interval || param.delay_bound || ++ param.msdu_ttl || param.msdu_rate_loss)) { ++ ath12k_info(NULL,"unsupported sla detect config for per second.\n"); ++ return -1; ++ } ++ ++ if ((param.sla_detect == SLA_DETECT_MOV_AVG) && ++ (param.min_throughput_rate || param.max_throughput_rate || ++ param.burst_size || param.service_interval || param.msdu_ttl || ++ param.msdu_rate_loss)) { ++ ath12k_info(NULL, "unsupported sla detect config for moving average.\n"); ++ return -1; ++ } ++ ++ if ((param.sla_detect == SLA_DETECT_NUM_SECOND) && ++ (param.min_throughput_rate || param.max_throughput_rate || ++ param.delay_bound)) { ++ ath12k_info(NULL, "unsupported sla detect config for number of seconds.\n"); ++ return -1; ++ } ++ ++ telemetry_param = &telemetry_ctx->sla_detect_params; ++ telemetry_param->sla_detect = param.sla_detect; ++ telemetry_param->min_throughput_rate = param.min_throughput_rate; ++ telemetry_param->max_throughput_rate = param.max_throughput_rate; ++ telemetry_param->burst_size = param.burst_size; ++ telemetry_param->service_interval = param.service_interval; ++ telemetry_param->delay_bound = param.delay_bound; ++ telemetry_param->msdu_ttl = param.msdu_ttl; ++ telemetry_param->msdu_rate_loss = param.msdu_rate_loss; ++ ++ ath12k_info(NULL, "telemetry sla detection configuration done, detect option: %d " ++ "MinThrRate:%d MaxThrRate:%d BurstSize:%d ServiceInt:%d \n DelayBound: %d " ++ "MsduTtl:%d MsduRateLoss:%d \n", telemetry_param->sla_detect, ++ telemetry_param->min_throughput_rate, ++ telemetry_param->max_throughput_rate, telemetry_param->burst_size, ++ telemetry_param->service_interval, telemetry_param->delay_bound, ++ telemetry_param->msdu_ttl, telemetry_param->msdu_rate_loss); ++ ++ return ret; ++} +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/telemetry.h +@@ -0,0 +1,104 @@ ++/* SPDX-License-Identifier: BSD-3-Clause-Clear */ ++/* ++ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef ATH12K_TELEMETRY_H ++#define ATH12K_TELEMETRY_H ++ ++ ++/** ++ * struct ath12k_sla_samples_cfg- telemetry sawf sla samples configuration ++ * @moving_avg_pkt: Number of packets per window to calculate moving average ++ * @moving_avg_win: Number of windows to calculate moving average ++ * @sla_num_pkt: Number of packets for SLA detection ++ * @sla_time_sec: Number of seconds for SLA detection ++ */ ++struct ath12k_sla_samples_cfg { ++ u32 moving_avg_pkt; ++ u32 moving_avg_win; ++ u32 sla_num_pkt; ++ u32 sla_time_sec; ++}; ++ ++/** ++ * struct ath12k_sla_thershold_cfg- telemetry sawf sla ++ * thershold configuration ++ * @svc_id: service class id ++ * @min_throughput_rate: min throughput thershold percentage ++ * @max_throughput_rate: max throughput thershold percentage ++ * @burst_size: burst size thershold percentage ++ * @service_interval: service interval thershold percentage ++ * @delay_bound: delay bound thershold percentage ++ * @msdu_ttl: MSDU Time-To-Live thershold percentage ++ * @msdu_rate_loss: MSDU loss rate thershold percentage ++ */ ++struct ath12k_sla_thershold_cfg { ++ u8 svc_id; ++ u32 min_throughput_rate; ++ u32 max_throughput_rate; ++ u32 burst_size; ++ u32 service_interval; ++ u32 delay_bound; ++ u32 msdu_ttl; ++ u32 msdu_rate_loss; ++}; ++ ++ ++/** ++ * struct ath12k_sla_detect- telemetry sawf sla ++ * sla breach detection option ++ * @SLA_DETECT_NUM_PACKET: Number of packets per window ++ * @SLA_DETECT_PER_SECOND: Number of windows ++ * @SLA_DETECT_MOV_AVG: Number of packets to calculate ++ * moving average for SLA detection ++ * @SLA_DETECT_NUM_SECOND: Number of seconds for SLA detection ++ */ ++enum ath12k_sla_detect { ++ SLA_DETECT_NUM_PACKET, ++ SLA_DETECT_PER_SECOND, ++ SLA_DETECT_MOV_AVG, ++ SLA_DETECT_NUM_SECOND, ++ SLA_DETECT_MAX, ++}; ++ ++/** ++ * struct ath12k_sla_detect_cfg- telemetry sawf sla ++ * breach detection configuration ++ * @sla_detect: sla detection option ++ * @min_throughput_rate: min throughput thershold percentage ++ * @max_throughput_rate: max throughput thershold percentage ++ * @burst_size: burst size thershold percentage ++ * @service_interval: service interval thershold percentage ++ * @delay_bound: delay bound thershold percentage ++ * @msdu_ttl: MSDU Time-To-Live thershold percentage ++ * @msdu_rate_loss: MSDU loss rate thershold percentage ++ */ ++struct ath12k_sla_detect_cfg { ++ enum ath12k_sla_detect sla_detect; ++ u32 min_throughput_rate; ++ u32 max_throughput_rate; ++ u32 burst_size; ++ u32 service_interval; ++ u32 delay_bound; ++ u32 msdu_ttl; ++ u32 msdu_rate_loss; ++}; ++ ++/** ++ * struct ath12k_telemetry_ctx- Telemetry context ++ */ ++struct ath12k_telemetry_ctx { ++ struct ath12k_sla_samples_cfg sla_samples_params; ++ struct ath12k_sla_thershold_cfg sla_thershold_params; ++ struct ath12k_sla_detect_cfg sla_detect_params; ++}; ++ ++void ath12k_telemetry_init(struct ath12k_base *ab); ++void ath12k_telemetry_deinit(struct ath12k_base *ab); ++struct ath12k_telemetry_ctx *get_telemetry_context(void); ++int ath12k_telemetry_sawf_sla_samples_config(struct ath12k_sla_samples_cfg param); ++int ath12k_telemetry_sawf_sla_thershold_config(struct ath12k_sla_thershold_cfg param); ++int ath12k_telemetry_sawf_sla_detection_config(struct ath12k_sla_detect_cfg param); ++ ++#endif /* ATH12K_TELEMETRY_H */ +--- a/drivers/net/wireless/ath/ath12k/vendor.c ++++ b/drivers/net/wireless/ath/ath12k/vendor.c +@@ -8,6 +8,7 @@ + #include "debug.h" + #include "mac.h" + #include "sawf.h" ++#include "telemetry.h" + + static const struct nla_policy + ath12k_vendor_sawf_config_policy[QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX + 1] = { +@@ -42,6 +43,39 @@ ath12k_vendor_sawf_def_qmap_rep_req_poli + [QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_MAC_ADDR] = {.type = NLA_STRING, .len = 18}, + }; + ++static const struct nla_policy ++ath12k_vendor_telemetry_sawf_sla_thershold_config_policy[QCA_WLAN_VENDOR_TELEMETRY_SLA_THERSHOLD_CFG_ATTR_CONFIG_MAX + 1] = { ++ [QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_SVC_ID] = {.type = NLA_U8}, ++ [QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_MIN_TP] = {.type = NLA_U32}, ++ [QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_MAX_TP] = {.type = NLA_U32}, ++ [QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_BURST_SIZE] = {.type = NLA_U32}, ++ [QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_INTERVAL] = {.type = NLA_U32}, ++ [QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_DELAY_BOUND] = {.type = NLA_U32}, ++ [QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_MSDU_TTL] = {.type = NLA_U32}, ++ [QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_MSDU_RATE_LOSS] = {.type = NLA_U32}, ++}; ++ ++ ++static const struct nla_policy ++ath12k_vendor_telemetry_sawf_sla_detect_config_policy[QCA_WLAN_VENDOR_TELEMETRY_SLA_DETECT_ATTR_CONFIG_MAX + 1] = { ++ [QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECTION_PARAM] = {.type = NLA_U8}, ++ [QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_MIN_TP] = {.type = NLA_U32}, ++ [QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_MAX_TP] = {.type = NLA_U32}, ++ [QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_BURST_SIZE] = {.type = NLA_U32}, ++ [QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_INTERVAL] = {.type = NLA_U32}, ++ [QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_DELAY_BOUND] = {.type = NLA_U32}, ++ [QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_MSDU_TTL] = {.type = NLA_U32}, ++ [QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_MSDU_RATE_LOSS] = {.type = NLA_U32}, ++}; ++ ++static const struct nla_policy ++ath12k_vendor_telemetry_sawf_sla_samples_config_policy[QCA_WLAN_VENDOR_TELEMETRY_SLA_SAMPLES_CFG_ATTR_CONFIG_MAX + 1] = { ++ [QCN_WLAN_VENDOR_ATTR_TELEMETRY_MOVING_AVG_PKT] = {.type = NLA_U32}, ++ [QCN_WLAN_VENDOR_ATTR_TELEMETRY_MOVING_AVG_WIN] = {.type = NLA_U32}, ++ [QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_NUM_PKT] = {.type = NLA_U32}, ++ [QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_TIME_SEC] = {.type = NLA_U32}, ++}; ++ + static void ath12k_set_default_values(struct ath12k_sawf_svc_params *param) + { + param->min_throughput_rate = SAWF_SVC_PARAM_DEFAULT_MIN_THRUPUT; +@@ -443,6 +477,133 @@ static int ath12k_vendor_sawf_def_qmap_r + return ret; + } + ++static int ath12k_vendor_telemetry_sawf_sla_samples_config(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ const void *data, ++ int data_len) ++{ ++ struct nlattr *tb[QCA_WLAN_VENDOR_TELEMETRY_SLA_SAMPLES_CFG_ATTR_CONFIG_MAX + 1]; ++ struct ath12k_sla_samples_cfg t_param; ++ int ret = 0; ++ ++ if (!ath12k_sawf_enable) { ++ ath12k_warn(NULL, "sawf is not enabled \n"); ++ return -ENOSYS; ++ } ++ ++ memset(&t_param, 0, sizeof(struct ath12k_sla_samples_cfg)); ++ ++ ret = nla_parse(tb, QCA_WLAN_VENDOR_TELEMETRY_SLA_SAMPLES_CFG_ATTR_CONFIG_MAX, ++ data, data_len, ath12k_vendor_telemetry_sawf_sla_samples_config_policy, NULL); ++ if (ret) { ++ ath12k_warn(NULL, "invalid set telemetry sla samples config policy attribute\n"); ++ return ret; ++ } ++ ++ t_param.moving_avg_pkt = ++ nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_TELEMETRY_MOVING_AVG_PKT]); ++ t_param.moving_avg_win = ++ nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_TELEMETRY_MOVING_AVG_WIN]); ++ t_param.sla_num_pkt = ++ nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_NUM_PKT]); ++ t_param.sla_time_sec = ++ nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_TIME_SEC]); ++ ++ ret = ath12k_telemetry_sawf_sla_samples_config(t_param); ++ return ret; ++} ++ ++static int ath12k_vendor_telemetry_sawf_sla_thershold_config(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ const void *data, ++ int data_len) ++{ ++ struct nlattr *tb[QCA_WLAN_VENDOR_TELEMETRY_SLA_THERSHOLD_CFG_ATTR_CONFIG_MAX + 1]; ++ struct ath12k_sla_thershold_cfg t_param; ++ int ret = 0; ++ ++ if (!ath12k_sawf_enable) { ++ ath12k_warn(NULL, "sawf is not enabled \n"); ++ return -ENOSYS; ++ } ++ ++ memset(&t_param, 0, sizeof(struct ath12k_sla_thershold_cfg)); ++ ++ ret = nla_parse(tb, QCA_WLAN_VENDOR_TELEMETRY_SLA_THERSHOLD_CFG_ATTR_CONFIG_MAX, ++ data, data_len, ath12k_vendor_telemetry_sawf_sla_thershold_config_policy, ++ NULL); ++ if (ret) { ++ ath12k_warn(NULL, "invalid telemetry sla thershold config policy attribute\n"); ++ return ret; ++ } ++ ++ t_param.svc_id = ++ nla_get_u8(tb[QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_SVC_ID]); ++ t_param.min_throughput_rate = ++ nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_MIN_TP]); ++ t_param.max_throughput_rate = ++ nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_MAX_TP]); ++ t_param.burst_size = ++ nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_BURST_SIZE]); ++ t_param.service_interval = ++ nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_INTERVAL]); ++ t_param.delay_bound = ++ nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_DELAY_BOUND]); ++ t_param.msdu_ttl = ++ nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_MSDU_TTL]); ++ t_param.msdu_rate_loss = ++ nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_MSDU_RATE_LOSS]); ++ ++ ret = ath12k_telemetry_sawf_sla_thershold_config(t_param); ++ ++ return ret; ++} ++ ++static int ath12k_vendor_telemetry_sawf_sla_detection_config(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ const void *data, ++ int data_len) ++{ ++ struct nlattr *tb[QCA_WLAN_VENDOR_TELEMETRY_SLA_DETECT_ATTR_CONFIG_MAX + 1]; ++ struct ath12k_sla_detect_cfg t_param; ++ int ret = 0; ++ ++ if (!ath12k_sawf_enable) { ++ ath12k_warn(NULL, "sawf is not enabled \n"); ++ return -ENOSYS; ++ } ++ ++ memset(&t_param, 0, sizeof(struct ath12k_sla_detect_cfg)); ++ ++ ret = nla_parse(tb, QCA_WLAN_VENDOR_TELEMETRY_SLA_DETECT_ATTR_CONFIG_MAX, data, data_len, ++ ath12k_vendor_telemetry_sawf_sla_detect_config_policy, NULL); ++ if (ret) { ++ ath12k_warn(NULL, "invalid telemetry sawf sla detection config policy attribute\n"); ++ return ret; ++ } ++ ++ t_param.sla_detect = ++ nla_get_u8(tb[QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECTION_PARAM]); ++ t_param.min_throughput_rate = ++ nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_MIN_TP]); ++ t_param.max_throughput_rate = ++ nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_MAX_TP]); ++ t_param.burst_size = ++ nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_BURST_SIZE]); ++ t_param.service_interval = ++ nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_INTERVAL]); ++ t_param.delay_bound = ++ nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_DELAY_BOUND]); ++ t_param.msdu_ttl = ++ nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_MSDU_TTL]); ++ t_param.msdu_rate_loss = ++ nla_get_u32(tb[QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_MSDU_RATE_LOSS]); ++ ++ ret = ath12k_telemetry_sawf_sla_detection_config(t_param); ++ ++ return ret; ++} ++ + static struct wiphy_vendor_command ath12k_vendor_commands[] = { + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, +@@ -489,6 +650,27 @@ static struct wiphy_vendor_command ath12 + .maxattr = QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_MAX, + .flags = WIPHY_VENDOR_CMD_NEED_NETDEV, + }, ++ { ++ .info.vendor_id = QCA_NL80211_VENDOR_ID, ++ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TELEMETRY_SLA_SAMPLES_CFG, ++ .doit = ath12k_vendor_telemetry_sawf_sla_samples_config, ++ .policy = ath12k_vendor_telemetry_sawf_sla_samples_config_policy, ++ .maxattr = QCA_WLAN_VENDOR_TELEMETRY_SLA_SAMPLES_CFG_ATTR_CONFIG_MAX, ++ }, ++ { ++ .info.vendor_id = QCA_NL80211_VENDOR_ID, ++ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TELEMETRY_SLA_THERSHOLD_CFG, ++ .doit = ath12k_vendor_telemetry_sawf_sla_thershold_config, ++ .policy = ath12k_vendor_telemetry_sawf_sla_thershold_config_policy, ++ .maxattr = QCA_WLAN_VENDOR_TELEMETRY_SLA_THERSHOLD_CFG_ATTR_CONFIG_MAX, ++ }, ++ { ++ .info.vendor_id = QCA_NL80211_VENDOR_ID, ++ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TELEMETRY_SLA_BREACH_DETECTION_CFG, ++ .doit = ath12k_vendor_telemetry_sawf_sla_detection_config, ++ .policy = ath12k_vendor_telemetry_sawf_sla_detect_config_policy, ++ .maxattr = QCA_WLAN_VENDOR_TELEMETRY_SLA_DETECT_ATTR_CONFIG_MAX, ++ }, + }; + + int ath12k_vendor_register(struct ath12k_hw *ah) +--- a/drivers/net/wireless/ath/ath12k/vendor.h ++++ b/drivers/net/wireless/ath/ath12k/vendor.h +@@ -17,6 +17,9 @@ enum qca_nl80211_vendor_subcmds { + QCA_NL80211_VENDOR_SUBCMD_SAWF_DEF_Q_MAP = 207, + QCA_NL80211_VENDOR_SUBCMD_SAWF_DEF_Q_UNMAP = 208, + QCA_NL80211_VENDOR_SUBCMD_SAWF_DEF_Q_MAP_REP = 209, ++ QCA_NL80211_VENDOR_SUBCMD_TELEMETRY_SLA_THERSHOLD_CFG = 210, ++ QCA_NL80211_VENDOR_SUBCMD_TELEMETRY_SLA_SAMPLES_CFG = 211, ++ QCA_NL80211_VENDOR_SUBCMD_TELEMETRY_SLA_BREACH_DETECTION_CFG = 212, + }; + + enum qca_wlan_vendor_sawf_attr_config { +@@ -55,5 +58,50 @@ enum ath12k_vendor_attr_sawf_def_q_map { + QCN_WLAN_VENDOR_ATTR_SAWF_DEF_Q_MAP_AFTER_LAST - 1, + }; + ++enum qca_wlan_vendor_attr_telemetry_sawf_sla_samples_config { ++ QCN_WLAN_VENDOR_ATTR_TELEMETRY_MOVING_AVG_PKT = 1, ++ QCN_WLAN_VENDOR_ATTR_TELEMETRY_MOVING_AVG_WIN, ++ QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_NUM_PKT, ++ QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_TIME_SEC, ++ ++ /* keep last */ ++ QCN_WLAN_VENDOR_TELEMETRY_SLA_SAMPLES_CFG_ATTR_AFTER_LAST, ++ QCA_WLAN_VENDOR_TELEMETRY_SLA_SAMPLES_CFG_ATTR_CONFIG_MAX = ++ QCN_WLAN_VENDOR_TELEMETRY_SLA_SAMPLES_CFG_ATTR_AFTER_LAST - 1, ++}; ++ ++enum qca_wlan_vendor_attr_telemetry_sawf_sla_detect_config { ++ QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECTION_PARAM = 1, ++ QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_MIN_TP, ++ QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_MAX_TP, ++ QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_BURST_SIZE, ++ QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_INTERVAL, ++ QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_DELAY_BOUND, ++ QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_MSDU_TTL, ++ QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_DETECT_MSDU_RATE_LOSS, ++ ++ /* keep last */ ++ QCA_WLAN_VENDOR_TELEMETRY_SLA_DETECT_AFTER_LAST, ++ QCA_WLAN_VENDOR_TELEMETRY_SLA_DETECT_ATTR_CONFIG_MAX = ++ QCA_WLAN_VENDOR_TELEMETRY_SLA_DETECT_AFTER_LAST - 1, ++ ++}; ++ ++enum qca_wlan_vendor_attr_telemetry_sawf_sla_thershold_config { ++ QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_SVC_ID = 1, ++ QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_MIN_TP, ++ QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_MAX_TP, ++ QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_BURST_SIZE, ++ QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_INTERVAL, ++ QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_DELAY_BOUND, ++ QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_MSDU_TTL, ++ QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_THERSHOLD_MSDU_RATE_LOSS, ++ ++ /* keep last */ ++ QCA_WLAN_VENDOR_TELEMETRY_SLA_THERSHOLD_CFG_AFTER_LAST, ++ QCA_WLAN_VENDOR_TELEMETRY_SLA_THERSHOLD_CFG_ATTR_CONFIG_MAX = ++ QCA_WLAN_VENDOR_TELEMETRY_SLA_THERSHOLD_CFG_AFTER_LAST - 1, ++}; ++ + int ath12k_vendor_register(struct ath12k_hw *ah); + #endif /* QCA_VENDOR_H */ diff --git a/feeds/ipq95xx/mac80211/patches/qca/779-wifi-ath12k-Assign-pci-device-id-during-mhi-register.patch b/feeds/ipq95xx/mac80211/patches/qca/779-wifi-ath12k-Assign-pci-device-id-during-mhi-register.patch new file mode 100644 index 000000000..e54a53d90 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/779-wifi-ath12k-Assign-pci-device-id-during-mhi-register.patch @@ -0,0 +1,24 @@ +From 1c7a3c8c709de9dbe9cbb03fa88acbca1b0644d6 Mon Sep 17 00:00:00 2001 +From: Balamurugan S +Date: Tue, 30 May 2023 12:45:30 +0530 +Subject: [PATCH] wifi: ath12k: Assign pci device id during mhi register + +Assign pci device id while registering to mhi module. + +Signed-off-by: Balamurugan S +--- + drivers/net/wireless/ath/ath12k/mhi.c | 2 ++ + 1 file changed, 2 insertions(+) + +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/mhi.c +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/mhi.c ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/mhi.c +@@ -447,6 +447,7 @@ int ath12k_mhi_register(struct ath12k_pc + mhi_ctrl->status_cb = ath12k_mhi_op_status_cb; + mhi_ctrl->read_reg = ath12k_mhi_op_read_reg; + mhi_ctrl->write_reg = ath12k_mhi_op_write_reg; ++ mhi_ctrl->dev_id = ab_pci->dev_id; + + ret = mhi_register_controller(mhi_ctrl, ab->hw_params->mhi_config); + if (ret) { diff --git a/feeds/ipq95xx/mac80211/patches/qca/779-wifi-ath12k-netdev-perlink-debugfs.patch b/feeds/ipq95xx/mac80211/patches/qca/779-wifi-ath12k-netdev-perlink-debugfs.patch new file mode 100644 index 000000000..2eb019146 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/779-wifi-ath12k-netdev-perlink-debugfs.patch @@ -0,0 +1,552 @@ +From 5670c880488b363b9dd907e601c5179f974da84f Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Thu, 1 Jun 2023 12:46:33 +0530 +Subject: [PATCH] UPSTREAM: wifi: mac80211: add netdev per-link debugfs data and driver + hook + +This adds the infrastructure to have netdev specific per-link data both +for mac80211 and the driver in debugfs. For the driver, a new callback +is added which is only used if MLO is supported. + +Cherry-picked from: https://patchwork.kernel.org/project/linux-wireless/patch/20230301115906.fb4c947e4df8.I69b3516ddf4c8a7501b395f652d6063444ecad63@changeid/ + +Signed-off-by: Benjamin Berg +Signed-off-by: Gregory Greenman +Signed-off-by: Karthik M +--- + include/net/mac80211.h | 10 ++ + net/mac80211/debugfs_netdev.c | 245 ++++++++++++++++++++++------------ + net/mac80211/debugfs_netdev.h | 21 +-- + net/mac80211/driver-ops.c | 27 +++- + net/mac80211/driver-ops.h | 16 +++ + net/mac80211/ieee80211_i.h | 4 + + net/mac80211/link.c | 5 +- + 7 files changed, 234 insertions(+), 94 deletions(-) + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -3919,6 +3919,12 @@ struct ieee80211_ppe_vp_ds_params { + * the station. See @sta_pre_rcu_remove if needed. + * This callback can sleep. + * ++ * @link_add_debugfs: Drivers can use this callback to add debugfs files ++ * when a link is added to a mac80211 vif. This callback should be within ++ * a CPTCFG_MAC80211_DEBUGFS conditional. This callback can sleep. ++ * For non-MLO the callback will be called once for the default bss_conf ++ * with the vif's directory rather than a separate subdirectory. ++ * + * @sta_add_debugfs: Drivers can use this callback to add debugfs files + * when a station is added to mac80211's station list. This callback + * should be within a CPTCFG_MAC80211_DEBUGFS conditional. This +@@ -4393,6 +4399,10 @@ struct ieee80211_ops { + int (*sta_remove)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); + #ifdef CPTCFG_MAC80211_DEBUGFS ++ void (*link_add_debugfs)(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_bss_conf *link_conf, ++ struct dentry *dir); + void (*sta_add_debugfs)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, +--- a/net/mac80211/debugfs_netdev.c ++++ b/net/mac80211/debugfs_netdev.c +@@ -23,16 +23,16 @@ + #include "driver-ops.h" + + static ssize_t ieee80211_if_read( +- struct ieee80211_sub_if_data *sdata, ++ void *data, + char __user *userbuf, + size_t count, loff_t *ppos, +- ssize_t (*format)(const struct ieee80211_sub_if_data *, char *, int)) ++ ssize_t (*format)(const void *, char *, int)) + { + char buf[200]; + ssize_t ret = -EINVAL; + + read_lock(&dev_base_lock); +- ret = (*format)(sdata, buf, sizeof(buf)); ++ ret = (*format)(data, buf, sizeof(buf)); + read_unlock(&dev_base_lock); + + if (ret >= 0) +@@ -42,10 +42,10 @@ static ssize_t ieee80211_if_read( + } + + static ssize_t ieee80211_if_write( +- struct ieee80211_sub_if_data *sdata, ++ void *data, + const char __user *userbuf, + size_t count, loff_t *ppos, +- ssize_t (*write)(struct ieee80211_sub_if_data *, const char *, int)) ++ ssize_t (*write)(void *, const char *, int)) + { + char buf[64]; + ssize_t ret; +@@ -58,64 +58,64 @@ static ssize_t ieee80211_if_write( + buf[count] = '\0'; + + rtnl_lock(); +- ret = (*write)(sdata, buf, count); ++ ret = (*write)(data, buf, count); + rtnl_unlock(); + + return ret; + } + +-#define IEEE80211_IF_FMT(name, field, format_string) \ ++#define IEEE80211_IF_FMT(name, type, field, format_string) \ + static ssize_t ieee80211_if_fmt_##name( \ +- const struct ieee80211_sub_if_data *sdata, char *buf, \ ++ const type *data, char *buf, \ + int buflen) \ + { \ +- return scnprintf(buf, buflen, format_string, sdata->field); \ ++ return scnprintf(buf, buflen, format_string, data->field); \ + } +-#define IEEE80211_IF_FMT_DEC(name, field) \ +- IEEE80211_IF_FMT(name, field, "%d\n") +-#define IEEE80211_IF_FMT_HEX(name, field) \ +- IEEE80211_IF_FMT(name, field, "%#x\n") +-#define IEEE80211_IF_FMT_LHEX(name, field) \ +- IEEE80211_IF_FMT(name, field, "%#lx\n") ++#define IEEE80211_IF_FMT_DEC(name, type, field) \ ++ IEEE80211_IF_FMT(name, type, field, "%d\n") ++#define IEEE80211_IF_FMT_HEX(name, type, field) \ ++ IEEE80211_IF_FMT(name, type, field, "%#x\n") ++#define IEEE80211_IF_FMT_LHEX(name, type, field) \ ++ IEEE80211_IF_FMT(name, type, field, "%#lx\n") + +-#define IEEE80211_IF_FMT_HEXARRAY(name, field) \ ++#define IEEE80211_IF_FMT_HEXARRAY(name, type, field) \ + static ssize_t ieee80211_if_fmt_##name( \ +- const struct ieee80211_sub_if_data *sdata, \ ++ const type *data, \ + char *buf, int buflen) \ + { \ + char *p = buf; \ + int i; \ +- for (i = 0; i < sizeof(sdata->field); i++) { \ ++ for (i = 0; i < sizeof(data->field); i++) { \ + p += scnprintf(p, buflen + buf - p, "%.2x ", \ +- sdata->field[i]); \ ++ data->field[i]); \ + } \ + p += scnprintf(p, buflen + buf - p, "\n"); \ + return p - buf; \ + } + +-#define IEEE80211_IF_FMT_ATOMIC(name, field) \ ++#define IEEE80211_IF_FMT_ATOMIC(name, type, field) \ + static ssize_t ieee80211_if_fmt_##name( \ +- const struct ieee80211_sub_if_data *sdata, \ ++ const type *data, \ + char *buf, int buflen) \ + { \ +- return scnprintf(buf, buflen, "%d\n", atomic_read(&sdata->field));\ ++ return scnprintf(buf, buflen, "%d\n", atomic_read(&data->field));\ + } + +-#define IEEE80211_IF_FMT_MAC(name, field) \ ++#define IEEE80211_IF_FMT_MAC(name, type, field) \ + static ssize_t ieee80211_if_fmt_##name( \ +- const struct ieee80211_sub_if_data *sdata, char *buf, \ ++ const type *data, char *buf, \ + int buflen) \ + { \ +- return scnprintf(buf, buflen, "%pM\n", sdata->field); \ ++ return scnprintf(buf, buflen, "%pM\n", data->field); \ + } + +-#define IEEE80211_IF_FMT_JIFFIES_TO_MS(name, field) \ ++#define IEEE80211_IF_FMT_JIFFIES_TO_MS(name, type, field) \ + static ssize_t ieee80211_if_fmt_##name( \ +- const struct ieee80211_sub_if_data *sdata, \ ++ const type *data, \ + char *buf, int buflen) \ + { \ + return scnprintf(buf, buflen, "%d\n", \ +- jiffies_to_msecs(sdata->field)); \ ++ jiffies_to_msecs(data->field)); \ + } + + #define _IEEE80211_IF_FILE_OPS(name, _read, _write) \ +@@ -126,43 +126,67 @@ static const struct file_operations name + .llseek = generic_file_llseek, \ + } + +-#define _IEEE80211_IF_FILE_R_FN(name) \ ++#define _IEEE80211_IF_FILE_R_FN(name, type) \ + static ssize_t ieee80211_if_read_##name(struct file *file, \ + char __user *userbuf, \ + size_t count, loff_t *ppos) \ + { \ ++ ssize_t (*fn)(const void *, char *, int) = (void *) \ ++ ((ssize_t (*)(const type, char *, int)) \ ++ ieee80211_if_fmt_##name); \ + return ieee80211_if_read(file->private_data, \ +- userbuf, count, ppos, \ +- ieee80211_if_fmt_##name); \ ++ userbuf, count, ppos, fn); \ + } + +-#define _IEEE80211_IF_FILE_W_FN(name) \ ++#define _IEEE80211_IF_FILE_W_FN(name, type) \ + static ssize_t ieee80211_if_write_##name(struct file *file, \ + const char __user *userbuf, \ + size_t count, loff_t *ppos) \ + { \ ++ ssize_t (*fn)(void *, const char *, int) = (void *) \ ++ ((ssize_t (*)(type, const char *, int)) \ ++ ieee80211_if_parse_##name); \ + return ieee80211_if_write(file->private_data, userbuf, count, \ +- ppos, ieee80211_if_parse_##name); \ ++ ppos, fn); \ + } + + #define IEEE80211_IF_FILE_R(name) \ +- _IEEE80211_IF_FILE_R_FN(name) \ ++ _IEEE80211_IF_FILE_R_FN(name, struct ieee80211_sub_if_data *) \ + _IEEE80211_IF_FILE_OPS(name, ieee80211_if_read_##name, NULL) + + #define IEEE80211_IF_FILE_W(name) \ +- _IEEE80211_IF_FILE_W_FN(name) \ ++ _IEEE80211_IF_FILE_W_FN(name, struct ieee80211_sub_if_data *) \ + _IEEE80211_IF_FILE_OPS(name, NULL, ieee80211_if_write_##name) + + #define IEEE80211_IF_FILE_RW(name) \ +- _IEEE80211_IF_FILE_R_FN(name) \ +- _IEEE80211_IF_FILE_W_FN(name) \ ++ _IEEE80211_IF_FILE_R_FN(name, struct ieee80211_sub_if_data *) \ ++ _IEEE80211_IF_FILE_W_FN(name, struct ieee80211_sub_if_data *) \ + _IEEE80211_IF_FILE_OPS(name, ieee80211_if_read_##name, \ + ieee80211_if_write_##name) + + #define IEEE80211_IF_FILE(name, field, format) \ +- IEEE80211_IF_FMT_##format(name, field) \ ++ IEEE80211_IF_FMT_##format(name, struct ieee80211_sub_if_data, field)\ + IEEE80211_IF_FILE_R(name) + ++/* Same but with a link_ prefix in the ops variable name and different type */ ++#define IEEE80211_IF_LINK_FILE_R(name) \ ++ _IEEE80211_IF_FILE_R_FN(name, struct ieee80211_link_data *) \ ++ _IEEE80211_IF_FILE_OPS(link_##name, ieee80211_if_read_##name, NULL) ++ ++#define IEEE80211_IF_LINK_FILE_W(name) \ ++ _IEEE80211_IF_FILE_W_FN(name) \ ++ _IEEE80211_IF_FILE_OPS(link_##name, NULL, ieee80211_if_write_##name) ++ ++#define IEEE80211_IF_LINK_FILE_RW(name) \ ++ _IEEE80211_IF_FILE_R_FN(name, struct ieee80211_link_data *) \ ++ _IEEE80211_IF_FILE_W_FN(name, struct ieee80211_link_data *) \ ++ _IEEE80211_IF_FILE_OPS(link_##name, ieee80211_if_read_##name, \ ++ ieee80211_if_write_##name) ++ ++#define IEEE80211_IF_LINK_FILE(name, field, format) \ ++ IEEE80211_IF_FMT_##format(name, struct ieee80211_link_data, field) \ ++ IEEE80211_IF_LINK_FILE_R(name) ++ + /* common attributes */ + IEEE80211_IF_FILE(rc_rateidx_mask_2ghz, rc_rateidx_mask[NL80211_BAND_2GHZ], + HEX); +@@ -204,12 +228,11 @@ static ssize_t ieee80211_if_fmt_rc_ratei + } + + IEEE80211_IF_FILE_R(rc_rateidx_vht_mcs_mask_5ghz); +- + IEEE80211_IF_FILE(flags, flags, HEX); + IEEE80211_IF_FILE(state, state, LHEX); +-IEEE80211_IF_FILE(txpower, vif.bss_conf.txpower, DEC); +-IEEE80211_IF_FILE(ap_power_level, deflink.ap_power_level, DEC); +-IEEE80211_IF_FILE(user_power_level, deflink.user_power_level, DEC); ++IEEE80211_IF_LINK_FILE(txpower, conf->txpower, DEC); ++IEEE80211_IF_LINK_FILE(ap_power_level, ap_power_level, DEC); ++IEEE80211_IF_LINK_FILE(user_power_level, user_power_level, DEC); + + static ssize_t + ieee80211_if_fmt_hw_queues(const struct ieee80211_sub_if_data *sdata, +@@ -622,6 +645,7 @@ static ssize_t ieee80211_if_parse_tsf( + } + IEEE80211_IF_FILE_RW(tsf); + ++IEEE80211_IF_LINK_FILE(addr, conf->addr, MAC); + + #ifdef CPTCFG_MAC80211_MESH + IEEE80211_IF_FILE(estab_plinks, u.mesh.estab_plinks, ATOMIC); +@@ -823,9 +847,6 @@ static void add_files(struct ieee80211_s + + DEBUGFS_ADD(flags); + DEBUGFS_ADD(state); +- DEBUGFS_ADD(txpower); +- DEBUGFS_ADD(user_power_level); +- DEBUGFS_ADD(ap_power_level); + + if (sdata->vif.type != NL80211_IFTYPE_MONITOR) + add_common_files(sdata); +@@ -890,6 +911,23 @@ void ieee80211_debugfs_remove_link(struc + } + } + ++#undef DEBUGFS_ADD_MODE ++#undef DEBUGFS_ADD ++ ++#define DEBUGFS_ADD_MODE(dentry, name, mode) \ ++ debugfs_create_file(#name, mode, dentry, \ ++ link, &link_##name##_ops) ++ ++#define DEBUGFS_ADD(dentry, name) DEBUGFS_ADD_MODE(dentry, name, 0400) ++ ++static void add_link_files(struct ieee80211_link_data *link, ++ struct dentry *dentry) ++{ ++ DEBUGFS_ADD(dentry, txpower); ++ DEBUGFS_ADD(dentry, user_power_level); ++ DEBUGFS_ADD(dentry, ap_power_level); ++} ++ + void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata) + { + char buf[10 + IFNAMSIZ]; +@@ -905,11 +943,23 @@ void ieee80211_debugfs_add_netdev(struct + sdata->vif.link_debugfs[i] = NULL; + + add_files(sdata); ++ /* Removed the following condition check, ++ * if (!(sdata->local->hw.wiphy->flags & WIPHY_FLAG_SUPPORTS_MLO)) ++ * This condition is not valid for HT,VHT modes and it will not allow ++ * to create debugfs files. ++ * In case of EHT mode, debugfs files will be created in both ++ * netdev:wlan0 directory as well as in link-0 directory ++ * TODO : Need to revisit and change the condition. ++ */ ++ add_link_files(&sdata->deflink, sdata->vif.debugfs_dir); + + /* create default link if it does not exist */ + if (sdata->vif.link_debugfs[0]) + return; + ++ /*TODO : Need to revamp the contents of link0 directory to link-0 ++ * directory ++ */ + memset(buf, 0, 10 + IFNAMSIZ); + snprintf(buf, 10 + IFNAMSIZ, "link0"); + sdata->vif.link_debugfs[0] = debugfs_create_dir(buf, +@@ -939,6 +989,74 @@ void ieee80211_debugfs_remove_netdev(str + + } + ++#ifdef CPTCFG_MAC80211_DEBUGFS ++void ieee80211_link_debugfs_add(struct ieee80211_link_data *link) ++{ ++ char link_dir_name[10]; ++ ++ if (WARN_ON(!link->sdata->vif.debugfs_dir)) ++ return; ++ ++ /* For now, this should not be called for non-MLO capable drivers */ ++ if (WARN_ON(!(link->sdata->local->hw.wiphy->flags & WIPHY_FLAG_SUPPORTS_MLO))) ++ return; ++ ++ if (link->debugfs_dir) ++ return; ++ ++ snprintf(link_dir_name, sizeof(link_dir_name), ++ "link-%d", link->link_id); ++ ++ link->debugfs_dir = ++ debugfs_create_dir(link_dir_name, ++ link->sdata->vif.debugfs_dir); ++ ++ DEBUGFS_ADD(link->debugfs_dir, addr); ++ add_link_files(link, link->debugfs_dir); ++} ++ ++void ieee80211_link_debugfs_remove(struct ieee80211_link_data *link) ++{ ++ if (!link->sdata->vif.debugfs_dir || !link->debugfs_dir) { ++ link->debugfs_dir = NULL; ++ return; ++ } ++ ++ if (link->debugfs_dir == link->sdata->vif.debugfs_dir) { ++ WARN_ON(link != &link->sdata->deflink); ++ link->debugfs_dir = NULL; ++ return; ++ } ++ ++ debugfs_remove_recursive(link->debugfs_dir); ++ link->debugfs_dir = NULL; ++} ++ ++void ieee80211_link_debugfs_drv_add(struct ieee80211_link_data *link) ++{ ++ if (WARN_ON(!link->debugfs_dir)) ++ return; ++ ++ drv_link_add_debugfs(link->sdata->local, link->sdata, ++ link->conf, link->debugfs_dir); ++} ++ ++void ieee80211_link_debugfs_drv_remove(struct ieee80211_link_data *link) ++{ ++ if (!link || !link->debugfs_dir) ++ return; ++ ++ if (WARN_ON(link->debugfs_dir == link->sdata->vif.debugfs_dir)) ++ return; ++ ++ /* Recreate the directory excluding the driver data */ ++ debugfs_remove_recursive(link->debugfs_dir); ++ link->debugfs_dir = NULL; ++ ++ ieee80211_link_debugfs_add(link); ++} ++#endif ++ + void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata) + { + struct dentry *dir; +--- a/net/mac80211/debugfs_netdev.h ++++ b/net/mac80211/debugfs_netdev.h +@@ -14,6 +14,12 @@ void ieee80211_debugfs_add_link(struct i + unsigned long add); + void ieee80211_debugfs_remove_link(struct ieee80211_sub_if_data *sdata, + unsigned long rem); ++ ++void ieee80211_link_debugfs_add(struct ieee80211_link_data *link); ++void ieee80211_link_debugfs_remove(struct ieee80211_link_data *link); ++ ++void ieee80211_link_debugfs_drv_add(struct ieee80211_link_data *link); ++void ieee80211_link_debugfs_drv_remove(struct ieee80211_link_data *link); + #else + static inline void ieee80211_debugfs_add_netdev( + struct ieee80211_sub_if_data *sdata) +@@ -30,7 +36,15 @@ static inline void ieee80211_debugfs_add + static inline void ieee80211_debugfs_remove_link(struct ieee80211_sub_if_data *sdata, + unsigned long rem); + {} ++static inline void ieee80211_link_debugfs_add(struct ieee80211_link_data *link) ++{} ++static inline void ieee80211_link_debugfs_remove(struct ieee80211_link_data *link) ++{} + ++static inline void ieee80211_link_debugfs_drv_add(struct ieee80211_link_data *link) ++{} ++static inline void ieee80211_link_debugfs_drv_remove(struct ieee80211_link_data *link) ++{} + #endif + + #endif /* __IEEE80211_DEBUGFS_NETDEV_H */ +--- a/net/mac80211/driver-ops.c ++++ b/net/mac80211/driver-ops.c +@@ -8,6 +8,7 @@ + #include "trace.h" + #include "driver-ops.h" + #include "debugfs_sta.h" ++#include "debugfs_netdev.h" + + int drv_start(struct ieee80211_local *local) + { +@@ -522,6 +523,10 @@ int drv_change_vif_links(struct ieee8021 + u16 old_links, u16 new_links, + struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS]) + { ++ struct ieee80211_link_data *link; ++ unsigned long links_to_add; ++ unsigned long links_to_rem; ++ unsigned int link_id; + int ret = -EOPNOTSUPP; + + might_sleep(); +@@ -532,13 +537,33 @@ int drv_change_vif_links(struct ieee8021 + if (old_links == new_links) + return 0; + ++ links_to_add = ~old_links & new_links; ++ links_to_rem = old_links & ~new_links; ++ ++ for_each_set_bit(link_id, &links_to_rem, IEEE80211_MLD_MAX_NUM_LINKS) { ++ link = rcu_access_pointer(sdata->link[link_id]); ++ ++ ieee80211_link_debugfs_drv_remove(link); ++ } ++ + trace_drv_change_vif_links(local, sdata, old_links, new_links); + if (local->ops->change_vif_links) + ret = local->ops->change_vif_links(&local->hw, &sdata->vif, + old_links, new_links, old); + trace_drv_return_int(local, ret); + +- return ret; ++ if (ret) ++ return ret; ++ ++ for_each_set_bit(link_id, &links_to_add, IEEE80211_MLD_MAX_NUM_LINKS) { ++ link = rcu_access_pointer(sdata->link[link_id]); ++ ++#ifdef CPTCFG_MAC80211_DEBUGFS ++ ieee80211_link_debugfs_drv_add(link); ++#endif ++ } ++ ++ return 0; + } + + int drv_change_sta_links(struct ieee80211_local *local, +--- a/net/mac80211/driver-ops.h ++++ b/net/mac80211/driver-ops.h +@@ -485,6 +485,22 @@ static inline void drv_sta_remove(struct + } + + #ifdef CPTCFG_MAC80211_DEBUGFS ++static inline void drv_link_add_debugfs(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_bss_conf *link_conf, ++ struct dentry *dir) ++{ ++ might_sleep(); ++ ++ sdata = get_bss_sdata(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return; ++ ++ if (local->ops->link_add_debugfs) ++ local->ops->link_add_debugfs(&local->hw, &sdata->vif, ++ link_conf, dir); ++} ++ + static inline void drv_sta_add_debugfs(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct ieee80211_sta *sta, +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1014,6 +1014,10 @@ struct ieee80211_link_data { + struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS]; + + struct ieee80211_bss_conf *conf; ++ ++#ifdef CPTCFG_MAC80211_DEBUGFS ++ struct dentry *debugfs_dir; ++#endif + }; + + struct ieee80211_sub_if_data { +--- a/net/mac80211/link.c ++++ b/net/mac80211/link.c +@@ -63,6 +63,7 @@ void ieee80211_link_init(struct ieee8021 + default: + WARN_ON(1); + } ++ ieee80211_link_debugfs_add(link); + } + } + +@@ -95,6 +96,7 @@ static void ieee80211_tear_down_links(st + if (WARN_ON(!link)) + continue; + ieee80211_remove_link_keys(link, &keys); ++ ieee80211_link_debugfs_remove(link); + ieee80211_link_stop(link); + } + diff --git a/feeds/ipq95xx/mac80211/patches/qca/780-ath12k-Fix-WARN-ON-during-bit-rate-command.patch b/feeds/ipq95xx/mac80211/patches/qca/780-ath12k-Fix-WARN-ON-during-bit-rate-command.patch new file mode 100644 index 000000000..d826a099c --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/780-ath12k-Fix-WARN-ON-during-bit-rate-command.patch @@ -0,0 +1,108 @@ +From ebc59ec753ad0e682a80f440dc5933108eaaab6c Mon Sep 17 00:00:00 2001 +From: Aaradhana Sahu +Date: Fri, 9 Jun 2023 13:44:37 +0530 +Subject: [PATCH] ath12k: Fix WARN ON during bit rate command + +Currently, we are calling ath12k_mac_disable_peer_fixed_rate with +holding rcu read lock and this function called wmi_set_peer_param +function which may sleep, due to this following call trace are +observed: + + 244.124345: <2> Call trace: + 244.131462: <2> dump_backtrace+0x0/0x19c + 244.133805: <2> show_stack+0x14/0x1c + 244.137624: <2> dump_stack+0xb4/0xf8 + 244.140923: <2> panic+0x164/0x350 + 244.144222: <2> __warn+0xb4/0xf8 + 244.147172: <2> report_bug+0x9c/0xec + 244.150210: <2> bug_handler+0x1c/0x64 + 244.153508: <2> brk_handler+0x7c/0xb0 + 244.156806: <2> do_debug_exception+0xfc/0x160 + 244.160193: <2> el1_dbg+0x18/0xbc + 244.164274: <2> rcu_note_context_switch+0x38/0x284 + 244.167311: <2> __schedule+0x90/0x520 + 244.171737: <2> schedule+0x8c/0xbc + 244.175210: <2> schedule_timeout+0x2e4/0x34c + 244.178263: <2> ath12k_wmi_cmd_send+0x1bc/0x254 [ath12k] + 244.182429: <2> ath12k_wmi_set_peer_param+0x7c/0xf0 [ath12k] + 244.187466: <2> ath12k_mac_tx_mgmt_pending_free+0x2cc/0x219c [ath12k] + 244.192846: <2> ieee80211_iterate_active_interfaces_mtx+0x50/0x6c [mac80211] + 244.198924: <2> ieee80211_iterate_stations_atomic+0x30/0x44 [mac80211] + 244.205778: <2> ath12k_get_ar_by_vif+0xc84/0x1348 [ath12k] + 244.211855: <2> ieee80211_channel_switch_disconnect+0x4bc/0x66c [mac80211] + 244.217062: <2> __cfg80211_send_event_skb+0x42b0/0x42fc [cfg80211] + 244.223653: <2> genl_family_rcv_msg+0x314/0x3b0 + 244.229552: <2> genl_rcv_msg+0x58/0x84 + +Fix this issue by calling wmi_set_peer_param function through worker. + +Signed-off-by: Aaradhana Sahu +--- + drivers/net/wireless/ath/ath12k/core.h | 3 +++ + drivers/net/wireless/ath/ath12k/mac.c | 26 ++++++++++++++++---------- + 2 files changed, 19 insertions(+), 10 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -656,6 +656,9 @@ struct ath12k_link_sta { + + /* For now the assoc link will be considered primary */ + bool is_assoc_link; ++ ++ /* For check disable fixed rate check for peer */ ++ bool disable_fixed_rate; + }; + + struct ath12k_sta { +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -6547,6 +6547,20 @@ static void ath12k_sta_rc_update_wk(stru + arsta->addr, arvif->vdev_id); + } + } ++ ++ if (arsta->disable_fixed_rate) { ++ 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); ++ ++ arsta->disable_fixed_rate = false; ++ } ++ + err_unlock: + mutex_unlock(&ar->conf_mutex); + } +@@ -13525,7 +13539,6 @@ static void ath12k_mac_disable_peer_fixe + struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; + struct ath12k_link_vif *arvif = data; + struct ath12k *ar; +- int ret; + u8 link_id = arvif->link_id; + + if (ahsta->ahvif != arvif->ahvif) +@@ -13539,15 +13552,11 @@ static void ath12k_mac_disable_peer_fixe + + ar = arvif->ar; + +- /* TODO move to sta->link addr */ +- ret = ath12k_wmi_set_peer_param(ar, arsta->addr, +- arvif->vdev_id, +- WMI_PEER_PARAM_FIXED_RATE, +- WMI_FIXED_RATE_NONE); +- if (ret) +- ath12k_warn(ar->ab, +- "failed to disable peer fixed rate for STA %pM ret %d\n", +- arsta->addr, ret); ++ spin_lock_bh(&ar->data_lock); ++ arsta->disable_fixed_rate = true; ++ spin_unlock_bh(&ar->data_lock); ++ ++ ieee80211_queue_work(ar->ah->hw, &arsta->update_wk); + } + + static bool diff --git a/feeds/ipq95xx/mac80211/patches/qca/780-ath12k-Update-the-number-of-tx_desc-used-to-FW.patch b/feeds/ipq95xx/mac80211/patches/qca/780-ath12k-Update-the-number-of-tx_desc-used-to-FW.patch new file mode 100644 index 000000000..2e53f7e09 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/780-ath12k-Update-the-number-of-tx_desc-used-to-FW.patch @@ -0,0 +1,44 @@ +From 75bff90b43ad0711efb8c854a8e189771c84f041 Mon Sep 17 00:00:00 2001 +From: Thiraviyam Mariyappan +Date: Tue, 6 Jun 2023 22:49:13 +0530 +Subject: [PATCH] ath12k: Update the number of tx_desc used to FW + +With 128 client test,observed low throughput in UDP DL. This is because max +msdu allocated size set as default size(16k) by the FW. So,packet aggregated +in lower rate. +Fixing this issue by setting max msdu allocated size as num of desc size(32k) +through wmi cmd. As a result, Threshold drop reason count reduced and 500mbps +Tput improvement observed from ingress 2400mbps on 5G radio. + +Signed-off-by: Thiraviyam Mariyappan +--- + drivers/net/wireless/ath/ath12k/mac.c | 7 +++++++ + drivers/net/wireless/ath/ath12k/wmi.h | 1 + + 2 files changed, 8 insertions(+) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -9490,6 +9490,13 @@ static int ath12k_mac_radio_start(struct + goto err; + } + ++ ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_SET_CONG_CTRL_MAX_MSDUS, ++ ATH12K_NUM_POOL_TX_DESC, pdev->pdev_id); ++ ++ if (ret) { ++ ath12k_err(ab, "failed to set congestion control MAX MSDUS: %d\n", ret); ++ goto err; ++ } + /* Enable(1)/Disable(0) sub channel marking */ + if (pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP) { + ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_SUB_CHANNEL_MARKING, +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -1087,6 +1087,7 @@ enum wmi_tlv_pdev_param { + WMI_PDEV_PARAM_RADIO_CHAN_STATS_ENABLE, + WMI_PDEV_PARAM_RADIO_DIAGNOSIS_ENABLE, + WMI_PDEV_PARAM_MESH_MCAST_ENABLE, ++ WMI_PDEV_PARAM_SET_CONG_CTRL_MAX_MSDUS = 0xa6, + WMI_PDEV_PARAM_SUB_CHANNEL_MARKING = 0xb0, + WMI_PDEV_PARAM_SET_CMD_OBSS_PD_THRESHOLD = 0xbc, + WMI_PDEV_PARAM_SET_CMD_OBSS_PD_PER_AC = 0xbe, diff --git a/feeds/ipq95xx/mac80211/patches/qca/780-mac80211-Advertise-HW-checksum-offload-only-for-ethm.patch b/feeds/ipq95xx/mac80211/patches/qca/780-mac80211-Advertise-HW-checksum-offload-only-for-ethm.patch new file mode 100644 index 000000000..f049dbf05 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/780-mac80211-Advertise-HW-checksum-offload-only-for-ethm.patch @@ -0,0 +1,74 @@ +From d4ddaebe2132dbb169f78da3666b11a21f645ea0 Mon Sep 17 00:00:00 2001 +From: Tamizh Chelvam Raja +Date: Fri, 21 Apr 2023 12:28:21 +0530 +Subject: [PATCH] mac80211: Advertise HW checksum offload only for ethmode + +Upper(NSS/SFE) layer might remove checksum offset from a skb +for the net device which advertise HW checksum offload +feature. This would create an issue if any software encrypted +packet or for the netdev which don't support IEEE80211_OFFLOAD_*. +Avoid this by advertising the HW checksum offload feature +only for the netdev which supports IEEE80211_OFFLOAD_* +and have an check before checking checksum offset for the +exceptional packets getting called from 8023_xmit API. + +Signed-off-by: Tamizh Chelvam Raja +--- + net/mac80211/ieee80211_i.h | 3 ++- + net/mac80211/iface.c | 4 ++++ + net/mac80211/tdls.c | 2 +- + net/mac80211/tx.c | 19 ++++++++++--------- + 4 files changed, 17 insertions(+), 11 deletions(-) + +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -2425,6 +2425,10 @@ int ieee80211_if_add(struct ieee80211_lo + sdata->u.mgd.use_4addr = params->use_4addr; + + ndev->features |= local->hw.netdev_features; ++ if ((type == NL80211_IFTYPE_AP || type == NL80211_IFTYPE_STATION) && ++ ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD) && !params->use_4addr) ++ ndev->features |= NETIF_F_HW_CSUM; ++ + ndev->hw_features |= ndev->features & + MAC80211_SUPPORTED_FEATURES_TX; + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -36,6 +36,8 @@ + #include "wme.h" + #include "rate.h" + ++#define IS_HW_CSUM_NOT_ENABLED(dev) (!((dev)->features & NETIF_F_HW_CSUM)) ++ + static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata, + struct net_device *dev, struct sta_info *sta, + struct ieee80211_key *key, struct sk_buff *skb, +@@ -3688,7 +3690,7 @@ static bool ieee80211_mesh_xmit_fast(str + /* if frame is software encrypted, checksum offloaded to + * hardware can not be handled. Handle it in software instead + */ +- if (skb->ip_summed == CHECKSUM_PARTIAL) { ++ if (skb->ip_summed == CHECKSUM_PARTIAL && IS_HW_CSUM_NOT_ENABLED(sdata->dev)) { + skb_set_transport_header(skb, + skb_checksum_start_offset(skb)); + if (skb_checksum_help(skb)) +@@ -4403,7 +4405,7 @@ void __ieee80211_subif_start_xmit(struct + * things so we cannot really handle checksum offload with it - + * fix it up in software before we handle anything else. + */ +- if (skb->ip_summed == CHECKSUM_PARTIAL) { ++ if (skb->ip_summed == CHECKSUM_PARTIAL && IS_HW_CSUM_NOT_ENABLED(dev)) { + skb_set_transport_header(skb, + skb_checksum_start_offset(skb)); + if (skb_checksum_help(skb)) +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -15046,7 +15046,6 @@ static int ath12k_mac_hw_register(struct + ah->hw->wiphy->reg_notifier = ath12k_reg_notifier; + + if (!test_bit(ATH12K_FLAG_RAW_MODE, &ag->dev_flags)) { +- hw->netdev_features = NETIF_F_HW_CSUM; + ieee80211_hw_set(hw, SW_CRYPTO_CONTROL); + ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/781-01-wifi-ath12k-refactor-the-mac-tx-mgmt-pending-free.patch b/feeds/ipq95xx/mac80211/patches/qca/781-01-wifi-ath12k-refactor-the-mac-tx-mgmt-pending-free.patch new file mode 100644 index 000000000..8fbdff0d2 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/781-01-wifi-ath12k-refactor-the-mac-tx-mgmt-pending-free.patch @@ -0,0 +1,146 @@ +From 7d3e91eb70470c5c82c8e337ae2e9d30a1167b7c Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Wed, 7 Jun 2023 21:51:16 +0530 +Subject: [PATCH 1/2] wifi: ath12k: refactor the mac tx mgmt pending free + +Remove the ath12k_mac_vif_txmgmt_idr_remove() by make use of +ath12k_mac_tx_mgmt_pending_free() through the argument context +type as a scalable to free the tx mgmt pending. + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/core.c | 6 +++- + drivers/net/wireless/ath/ath12k/mac.c | 42 +++++++++++++++++--------- + drivers/net/wireless/ath/ath12k/mac.h | 9 ++++++ + 3 files changed, 42 insertions(+), 15 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c +index 95fff0784a22..0053e2fb84ad 100644 +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -1799,6 +1799,7 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab) + struct ath12k *ar; + struct ath12k_pdev *pdev; + struct ath12k_link_vif *arvif; ++ struct ath12k_mac_tx_mgmt_free_arg arg; + int i; + + spin_lock_bh(&ab->base_lock); +@@ -1828,8 +1829,11 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab) + complete(&ar->bss_survey_done); + complete(&ar->thermal.wmi_sync); + ++ memset(&arg, 0, sizeof(arg)); ++ arg.ar = ar; ++ arg.type = u8_encode_bits(true, ATH12K_MAC_TX_MGMT_FREE_TYPE_PDEV); + idr_for_each(&ar->txmgmt_idr, +- ath12k_mac_tx_mgmt_pending_free, ar); ++ ath12k_mac_tx_mgmt_pending_free, &arg); + idr_destroy(&ar->txmgmt_idr); + wake_up(&ar->tx_empty_waitq); + +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index 6403f3d67c93..491d672ef8fa 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -8476,23 +8476,26 @@ static void ath12k_mac_tx_mgmt_free(struct ath12k *ar, int buf_id) + + int ath12k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx) + { +- struct ath12k *ar = ctx; ++ struct ath12k_mac_tx_mgmt_free_arg *arg = ctx; ++ struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB((struct sk_buff *)skb); ++ struct ath12k *ar = NULL; + +- ath12k_mac_tx_mgmt_free(ar, buf_id); +- +- return 0; +-} ++ if (u8_get_bits(arg->type, ATH12K_MAC_TX_MGMT_FREE_TYPE_PDEV)) ++ ar = arg->ar; + +-static int ath12k_mac_vif_txmgmt_idr_remove(int buf_id, void *skb, void *ctx) +-{ +- struct ieee80211_vif *vif = ctx; +- struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB((struct sk_buff *)skb); +- struct ath12k *ar = skb_cb->ar; ++ /* If radio invalid, dont proceed */ ++ if (!ar) ++ goto out; + +- if (skb_cb->vif == vif) { +- ath12k_mac_tx_mgmt_free(ar, buf_id); ++ /* If vif valid, then free the match vif alone */ ++ if (u8_get_bits(arg->type, ATH12K_MAC_TX_MGMT_FREE_TYPE_VIF)) { ++ if (skb_cb->vif != arg->vif) ++ goto out; + } + ++ ath12k_mac_tx_mgmt_free(arg->ar, buf_id); ++ ++out: + return 0; + } + +@@ -10511,6 +10514,7 @@ static void ath12k_mac_remove_link_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif = ahvif->vif; + struct ath12k_key_conf *key_conf, *tmp; + struct ath12k_base *ab; ++ struct ath12k_mac_tx_mgmt_free_arg arg = { }; + int ret; + + cancel_work_sync(&arvif->update_obss_color_notify_work); +@@ -10564,8 +10568,15 @@ err_vdev_del: + ath12k_peer_cleanup(ar, arvif->vdev_id); + + spin_lock_bh(&ar->data_lock); ++ ++ arg.ar = ar; ++ arg.vif = vif; ++ arg.type = u8_encode_bits(true, ATH12K_MAC_TX_MGMT_FREE_TYPE_PDEV) | ++ u8_encode_bits(true, ATH12K_MAC_TX_MGMT_FREE_TYPE_VIF); ++ + idr_for_each(&ar->txmgmt_idr, +- ath12k_mac_vif_txmgmt_idr_remove, vif); ++ ath12k_mac_tx_mgmt_pending_free, &arg); ++ + spin_unlock_bh(&ar->data_lock); + + ath12k_mac_vif_unref(&ab->dp, vif); +@@ -15113,9 +15124,12 @@ static void __ath12k_mac_pre_unregister(struct ath12k *ar) + + static void __ath12k_mac_post_unregister(struct ath12k *ar) + { ++ struct ath12k_mac_tx_mgmt_free_arg arg = { }; + int i; + +- idr_for_each(&ar->txmgmt_idr, ath12k_mac_tx_mgmt_pending_free, ar); ++ arg.ar = ar; ++ arg.type = u8_encode_bits(true, ATH12K_MAC_TX_MGMT_FREE_TYPE_PDEV); ++ idr_for_each(&ar->txmgmt_idr, ath12k_mac_tx_mgmt_pending_free, &arg); + idr_destroy(&ar->txmgmt_idr); + + kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels); +diff --git a/drivers/net/wireless/ath/ath12k/mac.h b/drivers/net/wireless/ath/ath12k/mac.h +index 0fdd9bd8dc49..4339bf8154e8 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.h ++++ b/drivers/net/wireless/ath/ath12k/mac.h +@@ -30,6 +30,15 @@ struct ath12k_mac_num_chanctxs_arg { + int num; + }; + ++#define ATH12K_MAC_TX_MGMT_FREE_TYPE_PDEV BIT(0) ++#define ATH12K_MAC_TX_MGMT_FREE_TYPE_VIF BIT(1) ++ ++struct ath12k_mac_tx_mgmt_free_arg { ++ u8 type; ++ struct ath12k *ar; ++ struct ieee80211_vif *vif; ++}; ++ + /* Default link after the IEEE802.11 defined Max link id limit + * for driver usage purpose + */ +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/781-02-wifi-ath12k-fix-link-specific-tx-mgmt-pending-free.patch b/feeds/ipq95xx/mac80211/patches/qca/781-02-wifi-ath12k-fix-link-specific-tx-mgmt-pending-free.patch new file mode 100644 index 000000000..f6fa80224 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/781-02-wifi-ath12k-fix-link-specific-tx-mgmt-pending-free.patch @@ -0,0 +1,67 @@ +From 85029a43e536d324d2cf96d57ba9bfe3fb3735fa Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Wed, 7 Jun 2023 22:14:12 +0530 +Subject: [PATCH 2/2] wifi: ath12k: fix link specific tx mgmt pending free + +When the link get removed, we wrongly remove the tx mgmt pending belong to +the vif. we have to remove only the link specific tx mgmt pending. So +added the link type in the mac tx mgmt pending free and pass the correct +link type from link remove procedure. + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/mac.c | 11 ++++++++++- + drivers/net/wireless/ath/ath12k/mac.h | 2 ++ + 2 files changed, 12 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index 491d672ef8fa..cea85c9b02ba 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -8493,6 +8493,13 @@ int ath12k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx) + goto out; + } + ++ /* If link_id valid, then free the match link_id alone */ ++ if (u8_get_bits(arg->type, ATH12K_MAC_TX_MGMT_FREE_TYPE_LINK)) { ++ if ((skb_cb->link_id != arg->link_id) && ++ (skb_cb->link_id != IEEE80211_MLD_MAX_NUM_LINKS)) ++ goto out; ++ } ++ + ath12k_mac_tx_mgmt_free(arg->ar, buf_id); + + out: +@@ -10571,8 +10578,10 @@ err_vdev_del: + + arg.ar = ar; + arg.vif = vif; ++ arg.link_id = arvif->link_id; + arg.type = u8_encode_bits(true, ATH12K_MAC_TX_MGMT_FREE_TYPE_PDEV) | +- u8_encode_bits(true, ATH12K_MAC_TX_MGMT_FREE_TYPE_VIF); ++ u8_encode_bits(true, ATH12K_MAC_TX_MGMT_FREE_TYPE_VIF) | ++ u8_encode_bits(true, ATH12K_MAC_TX_MGMT_FREE_TYPE_LINK); + + idr_for_each(&ar->txmgmt_idr, + ath12k_mac_tx_mgmt_pending_free, &arg); +diff --git a/drivers/net/wireless/ath/ath12k/mac.h b/drivers/net/wireless/ath/ath12k/mac.h +index 4339bf8154e8..f96d82fe3e65 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.h ++++ b/drivers/net/wireless/ath/ath12k/mac.h +@@ -32,11 +32,13 @@ struct ath12k_mac_num_chanctxs_arg { + + #define ATH12K_MAC_TX_MGMT_FREE_TYPE_PDEV BIT(0) + #define ATH12K_MAC_TX_MGMT_FREE_TYPE_VIF BIT(1) ++#define ATH12K_MAC_TX_MGMT_FREE_TYPE_LINK BIT(2) + + struct ath12k_mac_tx_mgmt_free_arg { + u8 type; + struct ath12k *ar; + struct ieee80211_vif *vif; ++ u8 link_id; + }; + + /* Default link after the IEEE802.11 defined Max link id limit +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/781-03-wifi-ath12k-remove-radio-structure-reference-from-th.patch b/feeds/ipq95xx/mac80211/patches/qca/781-03-wifi-ath12k-remove-radio-structure-reference-from-th.patch new file mode 100644 index 000000000..156b3cc98 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/781-03-wifi-ath12k-remove-radio-structure-reference-from-th.patch @@ -0,0 +1,57 @@ +From 9091e497e4824145f6cd4362dbabddd9527c1997 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Thu, 8 Jun 2023 09:56:03 +0530 +Subject: [PATCH] wifi: ath12k: remove radio structure reference from the skb + tx control buffer + +Current Tx skb control buffer not has enough to accomodate new member, so +removed the unused radio structure reference. Also if we need radio reference, +we can achieve through the link id reference. + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/bondif.c | 1 - + drivers/net/wireless/ath/ath12k/core.h | 1 - + drivers/net/wireless/ath/ath12k/mac.c | 1 - + 3 files changed, 3 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/bondif.c ++++ b/drivers/net/wireless/ath/ath12k/bondif.c +@@ -345,7 +345,6 @@ int ath12k_mcast_dp_tx(struct ath12k *ar + ti.data_len = skb->len - ti.pkt_offset; + skb_cb->paddr = ti.paddr; + skb_cb->vif = ahvif->vif; +- skb_cb->ar = ar; + + hal_ring_id = tx_ring->tcl_data_ring.ring_id; + tcl_ring = &ab->hal.srng_list[hal_ring_id]; +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -115,7 +115,6 @@ struct ath12k_skb_cb { + u8 eid; + u8 flags; + u32 cipher; +- struct ath12k *ar; + struct ieee80211_vif *vif; + dma_addr_t paddr_ext_desc; + u8 link_id; +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -8517,7 +8517,6 @@ static int ath12k_mac_mgmt_tx_wmi(struct + int ret; + bool link_agnostic; + +- ATH12K_SKB_CB(skb)->ar = ar; + spin_lock_bh(&ar->txmgmt_idr_lock); + buf_id = idr_alloc(&ar->txmgmt_idr, skb, 0, + ATH12K_TX_MGMT_NUM_PENDING_MAX, GFP_ATOMIC); +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -558,7 +558,6 @@ int ath12k_dp_tx(struct ath12k *ar, stru + ti.data_len = skb->len - ti.pkt_offset; + skb_cb->paddr = ti.paddr; + skb_cb->vif = ahvif->vif; +- skb_cb->ar = ar; + + if (unlikely(msdu_ext_desc)) { + skb_ext_desc = dev_alloc_skb(sizeof(struct hal_tx_msdu_ext_desc)); diff --git a/feeds/ipq95xx/mac80211/patches/qca/781-04-wifi-ath12k-fix-the-skb-data-when-pkt-offset-present.patch b/feeds/ipq95xx/mac80211/patches/qca/781-04-wifi-ath12k-fix-the-skb-data-when-pkt-offset-present.patch new file mode 100644 index 000000000..06bac6c71 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/781-04-wifi-ath12k-fix-the-skb-data-when-pkt-offset-present.patch @@ -0,0 +1,51 @@ +From e2d12daea395fcefe1f1b63af53517515598e428 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Thu, 8 Jun 2023 10:33:25 +0530 +Subject: [PATCH] wifi: ath12k: fix the skb data when pkt offset present + +when HTT metadata added in the skb data, the tx completion need +to remove this metadata and point the skb data to the actual payload +when its given to mac80211. Otherwise when this packet go through monitor +tx path then it face insufficient headroom and the packet get drops with +below warn_on(). + +Warn_on: +======= +WARNING: CPU: 3 PID: 2760 at net/mac80211/status.c:879 ieee80211_tx_monitor+0xf8/0x5d4 [mac80211] + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/dp_tx.c | 5 ++++- + 2 files changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -118,6 +118,7 @@ struct ath12k_skb_cb { + struct ieee80211_vif *vif; + dma_addr_t paddr_ext_desc; + u8 link_id; ++ u16 pkt_offset; + } __packed; + + struct ath12k_skb_rxcb { +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -556,6 +556,7 @@ int ath12k_dp_tx(struct ath12k *ar, stru + tx_desc->recycler_fast_xmit = 0; + ti.desc_id = tx_desc->desc_id; + ti.data_len = skb->len - ti.pkt_offset; ++ skb_cb->pkt_offset = ti.pkt_offset; + skb_cb->paddr = ti.paddr; + skb_cb->vif = ahvif->vif; + +@@ -783,6 +784,9 @@ ath12k_dp_tx_htt_tx_complete_buf(struct + skb_cb->link_id, + ahvif->links_map); + ++ if (skb_cb->pkt_offset) ++ skb_pull(msdu, skb_cb->pkt_offset); ++ + memset(&info->status, 0, sizeof(info->status)); + + if (ts->acked) { diff --git a/feeds/ipq95xx/mac80211/patches/qca/781-cfg80211-mac80211-fix-scan-issue-due-to-single-wiphy.patch b/feeds/ipq95xx/mac80211/patches/qca/781-cfg80211-mac80211-fix-scan-issue-due-to-single-wiphy.patch new file mode 100644 index 000000000..9bdb4f3ba --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/781-cfg80211-mac80211-fix-scan-issue-due-to-single-wiphy.patch @@ -0,0 +1,158 @@ +From 98d89963f8f8ae25bd7973f8069cfcf73a7f12ab Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Fri, 9 Jun 2023 14:27:22 +0530 +Subject: [PATCH] cfg80211/mac80211: fix scan issue due to single wiphy + architecture + +Currently, irrespective of the links active in an interface, if frequency +info is not provided in the scan request, all channels across all the +available bands under the wiphy are selected. This leads to huge scan request +as well as long time to complete the scan. + +However, if an interface is active on a certain num of links, then there +is no point in scanning for all the bands and their channels. + +Add fix to select channels only from bands which are currently active on +the requested scanning interface. + +Channels are freed when the pdev bring up is failed during recovery due to +firmware crash. Need to do sanity check if the channel is freed for a +particular band. + +Signed-off-by: Aditya Kumar Singh +Signed-off-by: Sidhanta Sahu +--- + include/net/cfg80211.h | 1 + + net/mac80211/scan.c | 59 ++++++++++++++++++++++++++++++++++++++++++ + net/wireless/nl80211.c | 5 ++++ + 3 files changed, 65 insertions(+) + +diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h +index 076cf22..5b94d5b 100644 +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -2649,6 +2649,7 @@ struct cfg80211_scan_request { + u32 n_6ghz_params; + struct cfg80211_scan_6ghz_params *scan_6ghz_params; + u8 hw_idx; ++ bool scan_with_freq_info; + + /* keep last */ + struct ieee80211_channel *channels[]; +diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c +index d35c1bb..69ca037 100644 +--- a/net/mac80211/scan.c ++++ b/net/mac80211/scan.c +@@ -707,6 +707,63 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, + local->next_scan_state = SCAN_DECISION; + } + ++static void __ieee80211_validate_scan_freqs(struct ieee80211_sub_if_data *sdata, ++ struct cfg80211_scan_request *req) ++{ ++ struct ieee80211_vif *vif = &sdata->vif; ++ unsigned long links = vif->valid_links; ++ struct ieee80211_bss_conf *link_conf; ++ int n_chans = 0, i; ++ u8 link_id, bands_active = 0, band; ++ ++ if (req->scan_with_freq_info) ++ return; ++ ++ /* In case of single wiphy, if req is without freq info, then it will have all ++ * possible enabled channels from all bands. Parse and only keep ++ * those who are active on the given interface ++ */ ++ mutex_lock(&sdata->local->chanctx_mtx); ++ ++ if (!vif->valid_links) { ++ link_conf = &vif->bss_conf; ++ ++ if (!link_conf->chanctx_conf) { ++ mutex_unlock(&sdata->local->chanctx_mtx); ++ return; ++ } ++ ++ band = link_conf->chanctx_conf->def.chan->band; ++ bands_active |= BIT(band); ++ } else { ++ rcu_read_lock(); ++ for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) { ++ link_conf = vif->link_conf[link_id]; ++ ++ if (!link_conf || !link_conf->chanctx_conf) ++ continue; ++ ++ band = link_conf->chanctx_conf->def.chan->band; ++ bands_active |= BIT(band); ++ } ++ rcu_read_unlock(); ++ } ++ ++ mutex_unlock(&sdata->local->chanctx_mtx); ++ ++ if (!bands_active) ++ return; ++ ++ for (i = 0; i < req->n_channels; i++) { ++ if (!(bands_active & BIT(req->channels[i]->band))) ++ continue; ++ ++ req->channels[n_chans++] = req->channels[i]; ++ } ++ ++ req->n_channels = n_chans; ++} ++ + static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, + struct cfg80211_scan_request *req) + { +@@ -747,6 +804,8 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, + } + + local->hw_scan_ies_bufsize *= n_bands; ++ } else { ++ __ieee80211_validate_scan_freqs(sdata, req); + } + + local->hw_scan_req = kmalloc( +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index ca7d006..4275b68 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -9730,6 +9730,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) + s8 hw_idx = -1; + size_t ie_len; + bool chandef_found = false; ++ bool freq_info_provided = true; + + wiphy = &rdev->wiphy; + +@@ -9764,6 +9765,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) + n_channels = 1; + } else { + n_channels = ieee80211_get_num_supported_channels(wiphy); ++ freq_info_provided = false; + } + + if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) +@@ -9846,6 +9848,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) + struct ieee80211_channel *chan; + + chan = &wiphy->bands[band]->channels[j]; ++ if (!chan) ++ continue; + + if (chan->flags & IEEE80211_CHAN_DISABLED) + continue; +@@ -9867,6 +9871,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) + } + + request->n_channels = i; ++ request->scan_with_freq_info = freq_info_provided; + + wdev_lock(wdev); + for (i = 0; i < request->n_channels; i++) { +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/782-ath12k-PPEDS-SSR-Recovery-Fixes.patch b/feeds/ipq95xx/mac80211/patches/qca/782-ath12k-PPEDS-SSR-Recovery-Fixes.patch new file mode 100644 index 000000000..e694a9029 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/782-ath12k-PPEDS-SSR-Recovery-Fixes.patch @@ -0,0 +1,854 @@ +From b798493ac1c60558863ffd98c3717790bc3c1811 Mon Sep 17 00:00:00 2001 +From: Sidhanta Sahu +Date: Tue, 27 Jun 2023 22:35:43 -0700 +Subject: [PATCH] ath12k: PPEDS SSR Recovery Fixes + +Fixes SSR recovery when PPE-DS is enabled. +Changes: + Disabled ppeds interrupts in core reset. + Do proper clean up related to ppeds components in core restart. + Restore ppe2tcl and reo2ppe start indices during ssr recovery. + Re-init restored start indices during dp hal srng hw init. + +Signed-off-by: Sidhanta Sahu +--- + drivers/net/wireless/ath/ath12k/ce.c | 2 +- + drivers/net/wireless/ath/ath12k/core.c | 34 ++++- + drivers/net/wireless/ath/ath12k/dp.c | 175 +++++++++++++++++++++++- + drivers/net/wireless/ath/ath12k/dp.h | 6 + + drivers/net/wireless/ath/ath12k/dp_tx.c | 3 + + drivers/net/wireless/ath/ath12k/hal.c | 103 ++++++++++++-- + drivers/net/wireless/ath/ath12k/hal.h | 14 +- + drivers/net/wireless/ath/ath12k/mac.c | 10 +- + drivers/net/wireless/ath/ath12k/ppe.c | 72 ++++++---- + drivers/net/wireless/ath/ath12k/ppe.h | 8 +- + 10 files changed, 376 insertions(+), 51 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/ce.c ++++ b/drivers/net/wireless/ath/ath12k/ce.c +@@ -644,7 +644,7 @@ static int ath12k_ce_init_ring(struct at + + /* TODO: Init other params needed by HAL to init the ring */ + +- ret = ath12k_hal_srng_setup(ab, type, ce_id, 0, ¶ms); ++ ret = ath12k_hal_srng_setup_idx(ab, type, ce_id, 0, ¶ms, 0); + if (ret < 0) { + ath12k_warn(ab, "failed to setup srng: %d ring_id %d\n", + ret, ce_id); +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -23,6 +23,11 @@ + #include "ahb.h" + #include "telemetry.h" + ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++#include ++#include "bondif.h" ++#endif ++ + unsigned int ath12k_debug_mask; + module_param_named(debug_mask, ath12k_debug_mask, uint, 0644); + MODULE_PARM_DESC(debug_mask, "Debugging mask"); +@@ -2042,6 +2047,46 @@ static int ath12k_rproc_recovery_power_u + return 0; + } + ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++static void ath12k_core_disable_ds_rtnl_bond_release(struct ath12k_base *ab) ++{ ++ struct ath12k *ar; ++ struct ath12k_pdev *pdev; ++ struct ath12k_link_vif *arvif; ++ int i; ++ ++ rtnl_lock(); ++ ++ for (i = 0; i < ab->num_radios; i++) { ++ pdev = &ab->pdevs[i]; ++ ar = pdev->ar; ++ ++ if (!ar || ar->state == ATH12K_STATE_OFF) ++ continue; ++ ++ mutex_lock(&ar->conf_mutex); ++ list_for_each_entry(arvif, &ar->arvifs, list) { ++ if (arvif->ndev_pvt) { ++ if (arvif->ndev_pvt->bond_dev && ++ arvif->ndev_pvt->bond_dev->flags & IFF_UP) { ++ netif_tx_stop_all_queues(arvif->ndev_pvt->bond_dev); ++ arvif->ndev_pvt->bond_dev->flags &= ~IFF_UP; ++ } ++ ++ if (arvif->ndev_pvt->link_ndev) { ++ netif_tx_stop_all_queues(arvif->ndev_pvt->link_ndev); ++ ath12k_bond_link_release(arvif); ++ ath12k_disable_ppe_for_link_netdev(ab, arvif, arvif->ndev_pvt->link_ndev); ++ } ++ } ++ } ++ mutex_unlock(&ar->conf_mutex); ++ } ++ ++ rtnl_unlock(); ++} ++#endif ++ + static void ath12k_core_reset(struct work_struct *work) + { + struct ath12k_base *ab = container_of(work, struct ath12k_base, reset_work); +@@ -2050,6 +2095,14 @@ static void ath12k_core_reset(struct wor + int reset_count, fail_cont_count, i; + long time_left; + ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++ if (!ab->is_reset) { ++ ath12k_hif_ppeds_irq_disable(ab, PPEDS_IRQ_PPE2TCL); ++ ath12k_hif_ppeds_irq_disable(ab, PPEDS_IRQ_REO2PPE); ++ ath12k_hif_ppeds_irq_disable(ab, PPEDS_IRQ_PPE_WBM2SW_REL); ++ ath12k_core_disable_ds_rtnl_bond_release(ab); ++ } ++#endif + /* Sometimes the recovery will fail and then the next all recovery fail, + * this is to avoid infinite recovery since it can not recovery success. + */ +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -298,6 +298,179 @@ static void ath12k_dp_srng_msi_setup(str + #endif + } + ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++static int ath12k_dp_srng_alloc(struct ath12k_base *ab, struct dp_srng *ring, ++ enum hal_ring_type type, int ring_num, ++ int num_entries) ++{ ++ int entry_sz = ath12k_hal_srng_get_entrysize(ab, type); ++ int max_entries = ath12k_hal_srng_get_max_entries(ab, type); ++ bool cached = false; ++ ++ if (max_entries < 0 || entry_sz < 0) ++ return -EINVAL; ++ ++ if (num_entries > max_entries) ++ num_entries = max_entries; ++ ++ ring->size = (num_entries * entry_sz) + HAL_RING_BASE_ALIGN - 1; ++ if (ab->hw_params->alloc_cacheable_memory) { ++ /* Allocate the reo dst and tx completion rings from cacheable memory */ ++ switch (type) { ++ case HAL_REO_DST: ++ case HAL_WBM2SW_RELEASE: ++ cached = true; ++ break; ++ default: ++ cached = false; ++ } ++ ++ if (cached) { ++ ring->vaddr_unaligned = kzalloc(ring->size, GFP_KERNEL); ++ ring->paddr_unaligned = virt_to_phys(ring->vaddr_unaligned); ++ } ++ } ++ if (!cached) ++ ring->vaddr_unaligned = dma_alloc_coherent(ab->dev, ring->size, ++ &ring->paddr_unaligned, ++ GFP_KERNEL); ++ if (!ring->vaddr_unaligned) ++ return -ENOMEM; ++ ++ memset(ring->vaddr_unaligned, 0, ring->size); ++ ring->vaddr = PTR_ALIGN(ring->vaddr_unaligned, HAL_RING_BASE_ALIGN); ++ ring->paddr = ring->paddr_unaligned + ((unsigned long)ring->vaddr - ++ (unsigned long)ring->vaddr_unaligned); ++ ++ return 0; ++} ++ ++static int ath12k_dp_srng_init_idx(struct ath12k_base *ab, struct dp_srng *ring, ++ enum hal_ring_type type, int ring_num, ++ int mac_id, ++ int num_entries, u32 idx) ++{ ++ struct hal_srng_params params = { 0 }; ++ bool cached = false; ++ int ret; ++ ++ params.ring_base_vaddr = ring->vaddr; ++ params.ring_base_paddr = ring->paddr; ++ params.num_entries = num_entries; ++ ath12k_dp_srng_msi_setup(ab, ¶ms, type, ring_num + mac_id); ++ ++ switch (type) { ++ case HAL_REO_DST: ++ case HAL_REO2PPE: ++ params.intr_batch_cntr_thres_entries = ++ HAL_SRNG_INT_BATCH_THRESHOLD_RX; ++ params.intr_timer_thres_us = HAL_SRNG_INT_TIMER_THRESHOLD_RX; ++ break; ++ case HAL_RXDMA_BUF: ++ params.intr_batch_cntr_thres_entries = 0; ++ params.intr_timer_thres_us = HAL_SRNG_INT_TIMER_THRESHOLD_RX; ++ break; ++ case HAL_RXDMA_MONITOR_BUF: ++ case HAL_RXDMA_MONITOR_STATUS: ++ if (type == HAL_RXDMA_MONITOR_BUF) ++ params.low_threshold = DP_RX_MONITOR_BUF_LOW_TH; ++ else ++ params.low_threshold = num_entries >> 3; ++ ++ params.flags |= HAL_SRNG_FLAGS_LOW_THRESH_INTR_EN; ++ ++ params.intr_batch_cntr_thres_entries = 0; ++ params.intr_timer_thres_us = HAL_SRNG_INT_TIMER_THRESHOLD_RX; ++ break; ++ case HAL_TX_MONITOR_BUF: ++ case HAL_TX_MONITOR_DST: ++ params.low_threshold = DP_TX_MONITOR_BUF_SIZE_MAX >> 3; ++ params.flags |= HAL_SRNG_FLAGS_LOW_THRESH_INTR_EN; ++ params.intr_batch_cntr_thres_entries = 0; ++ params.intr_timer_thres_us = HAL_SRNG_INT_TIMER_THRESHOLD_RX; ++ break; ++ case HAL_WBM2SW_RELEASE: ++ if (ab->hw_params->hw_ops->dp_srng_is_tx_comp_ring(ring_num)) { ++ params.intr_batch_cntr_thres_entries = ++ HAL_SRNG_INT_BATCH_THRESHOLD_TX; ++ params.intr_timer_thres_us = ++ HAL_SRNG_INT_TIMER_THRESHOLD_TX; ++ break; ++ } ++ /* follow through when ring_num != HAL_WBM2SW_REL_ERR_RING_NUM */ ++ fallthrough; ++ case HAL_REO_EXCEPTION: ++ case HAL_REO_REINJECT: ++ case HAL_REO_CMD: ++ case HAL_REO_STATUS: ++ case HAL_TCL_DATA: ++ case HAL_TCL_CMD: ++ case HAL_TCL_STATUS: ++ case HAL_WBM_IDLE_LINK: ++ case HAL_SW2WBM_RELEASE: ++ case HAL_RXDMA_DST: ++ case HAL_RXDMA_MONITOR_DST: ++ params.intr_batch_cntr_thres_entries = ++ HAL_SRNG_INT_BATCH_THRESHOLD_OTHER; ++ params.intr_timer_thres_us = HAL_SRNG_INT_TIMER_THRESHOLD_OTHER; ++ break; ++ case HAL_RXDMA_DIR_BUF: ++ break; ++ case HAL_PPE2TCL: ++ params.intr_batch_cntr_thres_entries = ++ HAL_SRNG_INT_BATCH_THRESHOLD_PPE2TCL; ++ params.intr_timer_thres_us = HAL_SRNG_INT_TIMER_THRESHOLD_PPE2TCL; ++ break; ++ default: ++ ath12k_warn(ab, "Not a valid ring type in dp :%d\n", type); ++ return -EINVAL; ++ } ++ ++ if (cached) { ++ params.flags |= HAL_SRNG_FLAGS_CACHED; ++ ring->cached = 1; ++ } ++ ++ ret = ath12k_hal_srng_setup_idx(ab, type, ring_num, mac_id, ¶ms, idx); ++ if (ret < 0) { ++ ath12k_warn(ab, "failed to setup srng: %d ring_id %d\n", ++ ret, ring_num); ++ return ret; ++ } ++ ++ ring->ring_id = ret; ++ ++ return 0; ++ ++} ++ ++int ath12k_ppeds_dp_srng_alloc(struct ath12k_base *ab, struct dp_srng *ring, ++ enum hal_ring_type type, int ring_num, ++ int num_entries) ++{ ++ int ret; ++ ++ ret = ath12k_dp_srng_alloc(ab, ring, type, ring_num, num_entries); ++ if (ret != 0) ++ ath12k_warn(ab, "Failed to allocate dp srng ring.\n"); ++ ++ return 0; ++} ++ ++int ath12k_ppeds_dp_srng_init(struct ath12k_base *ab, struct dp_srng *ring, ++ enum hal_ring_type type, int ring_num, ++ int mac_id, int num_entries, u32 idx) ++{ ++ int ret; ++ ++ ret = ath12k_dp_srng_init_idx(ab, ring, type, ring_num, mac_id, num_entries, idx); ++ if (ret != 0) ++ ath12k_warn(ab, "Failed to initialize dp srng ring.\n"); ++ ++ return 0; ++} ++#endif ++ + int ath12k_dp_srng_setup(struct ath12k_base *ab, struct dp_srng *ring, + enum hal_ring_type type, int ring_num, + int mac_id, int num_entries) +@@ -426,7 +599,7 @@ int ath12k_dp_srng_setup(struct ath12k_b + ring->cached = 1; + } + +- ret = ath12k_hal_srng_setup(ab, type, ring_num, mac_id, ¶ms); ++ ret = ath12k_hal_srng_setup_idx(ab, type, ring_num, mac_id, ¶ms, 0); + if (ret < 0) { + ath12k_warn(ab, "failed to setup srng: %d ring_id %d\n", + ret, ring_num); +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -2391,6 +2391,12 @@ struct ath12k_tx_desc_info *ath12k_dp_ge + u32 desc_id); + void ath12k_dp_tx_update_bank_profile(struct ath12k_link_vif *arvif); + #ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++int ath12k_ppeds_dp_srng_alloc(struct ath12k_base *ab, struct dp_srng *ring, ++ enum hal_ring_type type, int ring_num, ++ int num_entries); ++int ath12k_ppeds_dp_srng_init(struct ath12k_base *ab, struct dp_srng *ring, ++ enum hal_ring_type type, int ring_num, ++ int mac_id, int num_entries, u32 idx); + struct ath12k_ppeds_tx_desc_info *ath12k_dp_get_ppeds_tx_desc(struct ath12k_base *ab, + u32 desc_id); + int ath12k_dp_cc_ppeds_desc_init(struct ath12k_base *ab); +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -275,6 +275,9 @@ int ath12k_dp_tx_direct(struct ath12k_li + int ret; + int len = skb->fast_xmit ? 256 : skb->len; + ++ if (unlikely(test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))) ++ return -ESHUTDOWN; ++ + ring_id = smp_processor_id(); + + tx_ring = &dp->tx_ring[ring_id]; +--- a/drivers/net/wireless/ath/ath12k/hal.c ++++ b/drivers/net/wireless/ath/ath12k/hal.c +@@ -1303,7 +1303,8 @@ static void ath12k_hal_ce_dst_setup(stru + } + + static void ath12k_hal_srng_dst_hw_init(struct ath12k_base *ab, +- struct hal_srng *srng) ++ struct hal_srng *srng, ++ u32 idx) + { + struct ath12k_hal *hal = &ab->hal; + u32 val; +@@ -1312,6 +1313,12 @@ static void ath12k_hal_srng_dst_hw_init( + + reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R0]; + ++ val = ath12k_hif_read32(ab, reg_base + HAL_REO1_RING_MISC_OFFSET) & ++ ~HAL_REO1_RING_MISC_SRNG_ENABLE; ++ ++ ath12k_hif_write32(ab, reg_base + HAL_REO1_RING_MISC_OFFSET, val); ++ val = 0; ++ + if (srng->flags & HAL_SRNG_FLAGS_MSI_INTR) { + ath12k_hif_write32(ab, reg_base + + HAL_REO1_RING_MSI1_BASE_LSB_OFFSET, +@@ -1361,9 +1368,10 @@ static void ath12k_hal_srng_dst_hw_init( + + /* Initialize head and tail pointers to indicate ring is empty */ + reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R2]; +- ath12k_hif_write32(ab, reg_base, 0); +- ath12k_hif_write32(ab, reg_base + HAL_REO1_RING_TP_OFFSET, 0); +- *srng->u.dst_ring.hp_addr = 0; ++ ath12k_hif_write32(ab, reg_base, idx * srng->entry_size); ++ ath12k_hif_write32(ab, reg_base + HAL_REO1_RING_TP_OFFSET, idx * srng->entry_size); ++ *srng->u.dst_ring.hp_addr = idx * srng->entry_size; ++ srng->u.dst_ring.tp = idx * srng->entry_size; + + reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R0]; + val = 0; +@@ -1379,7 +1387,8 @@ static void ath12k_hal_srng_dst_hw_init( + } + + static void ath12k_hal_srng_src_hw_init(struct ath12k_base *ab, +- struct hal_srng *srng) ++ struct hal_srng *srng, ++ u32 idx) + { + struct ath12k_hal *hal = &ab->hal; + u32 val; +@@ -1388,6 +1397,12 @@ static void ath12k_hal_srng_src_hw_init( + + reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R0]; + ++ val = ath12k_hif_read32(ab, reg_base + HAL_TCL1_RING_MISC_OFFSET(ab)) & ++ ~HAL_TCL1_RING_MISC_SRNG_ENABLE; ++ ++ ath12k_hif_write32(ab, reg_base + HAL_TCL1_RING_MISC_OFFSET(ab), val); ++ val = 0; ++ + if (srng->flags & HAL_SRNG_FLAGS_MSI_INTR) { + ath12k_hif_write32(ab, reg_base + + HAL_TCL1_RING_MSI1_BASE_LSB_OFFSET(ab), +@@ -1453,9 +1468,10 @@ static void ath12k_hal_srng_src_hw_init( + + /* Initialize head and tail pointers to indicate ring is empty */ + reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R2]; +- ath12k_hif_write32(ab, reg_base, 0); +- ath12k_hif_write32(ab, reg_base + HAL_TCL1_RING_TP_OFFSET, 0); +- *srng->u.src_ring.tp_addr = 0; ++ ath12k_hif_write32(ab, reg_base, idx * srng->entry_size); ++ ath12k_hif_write32(ab, reg_base + HAL_TCL1_RING_TP_OFFSET, idx * srng->entry_size); ++ *srng->u.src_ring.tp_addr = idx * srng->entry_size; ++ srng->u.src_ring.hp = idx * srng->entry_size; + + reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R0]; + val = 0; +@@ -1478,12 +1494,13 @@ static void ath12k_hal_srng_src_hw_init( + } + + static void ath12k_hal_srng_hw_init(struct ath12k_base *ab, +- struct hal_srng *srng) ++ struct hal_srng *srng, ++ u32 idx) + { + if (srng->ring_dir == HAL_SRNG_DIR_SRC) +- ath12k_hal_srng_src_hw_init(ab, srng); ++ ath12k_hal_srng_src_hw_init(ab, srng, idx); + else +- ath12k_hal_srng_dst_hw_init(ab, srng); ++ ath12k_hal_srng_dst_hw_init(ab, srng, idx); + } + + static int ath12k_hal_srng_get_ring_id(struct ath12k_base *ab, +@@ -2072,9 +2089,53 @@ void ath12k_hal_setup_link_idle_list(str + val); + } + +-int ath12k_hal_srng_setup(struct ath12k_base *ab, enum hal_ring_type type, ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++static void hal_tx_ppe2tcl_ring_halt_set_9224(struct ath12k_base *ab) ++{ ++ u32 cmn_reg_addr; ++ u32 regval; ++ ++ cmn_reg_addr = HWIO_TCL_R0_CONS_RING_CMN_CTRL_REG_ADDR(MAC_TCL_REG_REG_BASE); ++ regval = ath12k_hif_read32(ab, cmn_reg_addr); ++ ++ regval |= (1 << HWIO_TCL_R0_CONS_RING_CMN_CTRL_REG_PPE2TCL1_RNG_HALT_SHFT); ++ ++ /* Enable ring halt for the ppe2tcl ring */ ++ ath12k_hif_write32(ab, cmn_reg_addr, regval); ++} ++ ++static void hal_tx_ppe2tcl_ring_halt_reset_9224(struct ath12k_base *ab) ++{ ++ u32 cmn_reg_addr; ++ u32 regval; ++ ++ cmn_reg_addr = HWIO_TCL_R0_CONS_RING_CMN_CTRL_REG_ADDR(MAC_TCL_REG_REG_BASE); ++ regval = ath12k_hif_read32(ab, cmn_reg_addr); ++ ++ regval &= ~(1 << HWIO_TCL_R0_CONS_RING_CMN_CTRL_REG_PPE2TCL1_RNG_HALT_SHFT); ++ ++ /* Disable ring halt for the ppe2tcl ring */ ++ ath12k_hif_write32(ab, cmn_reg_addr, regval); ++} ++ ++static bool hal_tx_ppe2tcl_ring_halt_done_9224(struct ath12k_base *ab) ++{ ++ u32 cmn_reg_addr; ++ u32 regval; ++ ++ cmn_reg_addr = HWIO_TCL_R0_CONS_RING_CMN_CTRL_REG_ADDR(MAC_TCL_REG_REG_BASE); ++ ++ regval = ath12k_hif_read32(ab, cmn_reg_addr); ++ ++ regval &= (1 << HWIO_TCL_R0_CONS_RING_CMN_CTRL_REG_PPE2TCL1_RNG_HALT_STAT_SHFT); ++ ++ return !!regval; ++} ++#endif ++ ++int ath12k_hal_srng_setup_idx(struct ath12k_base *ab, enum hal_ring_type type, + int ring_num, int mac_id, +- struct hal_srng_params *params) ++ struct hal_srng_params *params, u32 res_idx) + { + struct ath12k_hal *hal = &ab->hal; + struct hal_srng_config *srng_config = &ab->hal.srng_config[type]; +@@ -2083,6 +2144,9 @@ int ath12k_hal_srng_setup(struct ath12k_ + u32 idx; + int i; + u32 reg_base; ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++ u32 retry_count = 0; ++#endif + + ring_id = ath12k_hal_srng_get_ring_id(ab, type, ring_num, mac_id); + if (ring_id < 0) +@@ -2210,8 +2274,29 @@ int ath12k_hal_srng_setup(struct ath12k_ + if (srng_config->mac_type != ATH12K_HAL_SRNG_UMAC) + return ring_id; + +- ath12k_hal_srng_hw_init(ab, srng); ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++ if (res_idx) { ++ hal_tx_ppe2tcl_ring_halt_set_9224(ab); ++ do { ++ ath12k_warn(ab, "Waiting for ring reset, retried count: %d\n", ++ retry_count); ++ msleep(10); ++ retry_count++; ++ } while (!(hal_tx_ppe2tcl_ring_halt_done_9224(ab)) && ++ (retry_count < RNG_HALT_STAT_RETRY_COUNT)); ++ ++ if (retry_count >= RNG_HALT_STAT_RETRY_COUNT) ++ ath12k_err(ab, "Ring halt is failed, retried count: %d\n", ++ retry_count); + ++ ath12k_hal_srng_hw_init(ab, srng, res_idx); ++ hal_tx_ppe2tcl_ring_halt_reset_9224(ab); ++ } ++ else ++ ath12k_hal_srng_hw_init(ab, srng, 0); ++#else ++ ath12k_hal_srng_hw_init(ab, srng, 0); ++#endif + if (type == HAL_CE_DST) { + srng->u.dst_ring.max_buffer_length = params->max_buffer_len; + ath12k_hal_ce_dst_setup(ab, srng, ring_num); +--- a/drivers/net/wireless/ath/ath12k/hal.h ++++ b/drivers/net/wireless/ath/ath12k/hal.h +@@ -45,6 +45,17 @@ struct ath12k_dp_rx_info; + + #define HAL_REO_QDESC_MAX_PEERID 8191 + ++#ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++/* WCSS_UMAC_TCL_R0_CONS_RING_CMN_CTRL_REG */ ++#define UMAC_BASE 0x00a00000 ++#define MAC_TCL_REG_REG_BASE (UMAC_BASE + 0x00044000) ++#define HWIO_TCL_R0_CONS_RING_CMN_CTRL_REG_ADDR(x) ((x) + 0x20) ++ ++#define HWIO_TCL_R0_CONS_RING_CMN_CTRL_REG_PPE2TCL1_RNG_HALT_SHFT 10 ++#define HWIO_TCL_R0_CONS_RING_CMN_CTRL_REG_PPE2TCL1_RNG_HALT_STAT_SHFT 18 ++#define RNG_HALT_STAT_RETRY_COUNT 10 ++#endif ++ + /* WCSS Relative address */ + #define HAL_SEQ_WCSS_UMAC_OFFSET 0x00a00000 + #define HAL_SEQ_WCSS_UMAC_REO_REG 0x00a38000 +@@ -1202,9 +1213,9 @@ int ath12k_hal_srng_src_num_free(struct + void ath12k_hal_srng_access_begin(struct ath12k_base *ab, + struct hal_srng *srng); + void ath12k_hal_srng_access_end(struct ath12k_base *ab, struct hal_srng *srng); +-int ath12k_hal_srng_setup(struct ath12k_base *ab, enum hal_ring_type type, ++int ath12k_hal_srng_setup_idx(struct ath12k_base *ab, enum hal_ring_type type, + int ring_num, int mac_id, +- struct hal_srng_params *params); ++ struct hal_srng_params *params, u32 idx); + int ath12k_hal_srng_init(struct ath12k_base *ath12k); + void ath12k_hal_srng_deinit(struct ath12k_base *ath12k); + void ath12k_hal_dump_srng_stats(struct ath12k_base *ab); +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -4821,7 +4821,8 @@ static int ath12k_mac_vdev_delete(struct + + #ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT + if (arvif->link_id != ATH12K_DEFAULT_SCAN_LINK && arvif->ndev_pvt) { +- ath12k_bond_link_release(arvif); ++ if (arvif->ndev_pvt->is_bond_enslaved) ++ ath12k_bond_link_release(arvif); + if (ahvif->vdev_type == WMI_VDEV_TYPE_AP) + ath12k_disable_ppe_for_link_netdev(ar->ab, arvif, + arvif->ndev_pvt->link_ndev); +<<<<<<< HEAD (3ac06c Merge "ath12k: add support for low_latency_rate_cnt") +@@ -10244,7 +10245,7 @@ static int ath12k_mac_vdev_create(struct +======= + } +@@ -10314,7 +10315,7 @@ static int ath12k_mac_vdev_create(struct +>>>>>>> CHANGE (16beae ath12k: PPE DS tx optimizations) + } + #ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT + if (arvif->link_id != ATH12K_DEFAULT_SCAN_LINK) { +- if (hweight16(vif->valid_links) <= 1) { ++ if (hweight16(vif->valid_links) <= 1 && link_ndev) { + ath12k_free_bonddev_for_sfe(wdev, vif, link_id); + arvif->ndev_pvt = NULL; + arvif->ppe_vp_num = -1; +<<<<<<< HEAD (3ac06c Merge "ath12k: add support for low_latency_rate_cnt") +@@ -10252,6 +10253,9 @@ static int ath12k_mac_vdev_create(struct +======= +@@ -10322,6 +10323,9 @@ static int ath12k_mac_vdev_create(struct +>>>>>>> CHANGE (16beae ath12k: PPE DS tx optimizations) + else if (link_ndev) { + ath12k_enable_ds_for_link_netdev(ab, arvif, + arvif->ndev_pvt->link_ndev); ++ netif_tx_start_all_queues(arvif->ndev_pvt->bond_dev); ++ netif_tx_start_all_queues(arvif->ndev_pvt->link_ndev); ++ arvif->ndev_pvt->bond_dev->flags |= IFF_UP; + ath12k_bond_link_enslave(arvif, arvif->ndev_pvt->link_ndev); + } + } +--- a/drivers/net/wireless/ath/ath12k/ppe.c ++++ b/drivers/net/wireless/ath/ath12k/ppe.c +@@ -85,7 +85,7 @@ static void ath12k_ppeds_set_reo_cons_id + if (!ab->stats_disable) + ab->ppeds_stats.reo_cons_cnt++; + +- srng->u.src_ring.hp = reo_cons_idx * srng->entry_size; ++ srng->u.dst_ring.tp = reo_cons_idx * srng->entry_size; + ath12k_hal_srng_access_end(ab, srng); + } + +@@ -955,7 +955,8 @@ void ath12k_dp_ppeds_stop(struct ath12k_ + + } + +-int ath12k_dp_ppeds_register_soc(struct ath12k_dp *dp) ++int ath12k_dp_ppeds_register_soc(struct ath12k_dp *dp, ++ struct dp_ppe_ds_idxs *idx) + { + struct ath12k_base *ab = dp->ab; + struct hal_srng *ppe2tcl_ring, *reo2ppe_ring; +@@ -974,13 +975,16 @@ int ath12k_dp_ppeds_register_soc(struct + + reg_info.ppe2tcl_ba = dp->ppe2tcl_ring.paddr; + reg_info.reo2ppe_ba = dp->reo2ppe_ring.paddr; +- reg_info.ppe2tcl_num_desc = ppe2tcl_ring->num_entries; +- reg_info.reo2ppe_num_desc = reo2ppe_ring->num_entries; ++ reg_info.ppe2tcl_num_desc = DP_PPE2TCL_RING_SIZE; ++ reg_info.reo2ppe_num_desc = DP_REO2PPE_RING_SIZE; ++ + if (ppe_ds_wlan_inst_register(ab->ppeds_handle, ®_info) != true) { + ath12k_err(ab, "ppeds not attached"); + return -EINVAL; + } + ++ idx->ppe2tcl_start_idx = reg_info.ppe2tcl_start_idx; ++ idx->reo2ppe_start_idx = reg_info.reo2ppe_start_idx; + ab->ppeds_int_mode_enabled = reg_info.ppe_ds_int_mode_enabled; + + ath12k_dbg(ab, ATH12K_DBG_PPE, "PPEDS register soc-success"); +@@ -991,44 +995,28 @@ int ath12k_dp_ppeds_register_soc(struct + int ath12k_dp_srng_ppeds_setup(struct ath12k_base *ab) + { + struct ath12k_dp *dp = &ab->dp; ++ struct dp_ppe_ds_idxs restore_idx = {0}; + int ret, size; + + if (!test_bit(ATH12K_FLAG_PPE_DS_ENABLED, &ab->dev_flags)) + return 0; + + /* TODO: retain and use ring idx fetched from ppe for avoiding edma hang during SSR */ +- ret = ath12k_dp_srng_setup(ab, &dp->reo2ppe_ring, HAL_REO2PPE, +- 0, 0, DP_REO2PPE_RING_SIZE); ++ ret = ath12k_ppeds_dp_srng_alloc(ab, &dp->reo2ppe_ring, HAL_REO2PPE, ++ 0, DP_REO2PPE_RING_SIZE); + if (ret) { + ath12k_warn(ab, "failed to set up reo2ppe ring :%d\n", ret); + goto err; + } + +- ath12k_hal_reo_config_reo2ppe_dest_info(ab); +- + /* TODO: retain and use ring idx fetched from ppe for avoiding edma hang during SSR */ +- ret = ath12k_dp_srng_setup(ab, &dp->ppe2tcl_ring, HAL_PPE2TCL, +- 0, 0, DP_PPE2TCL_RING_SIZE); ++ ret = ath12k_ppeds_dp_srng_alloc(ab, &dp->ppe2tcl_ring, HAL_PPE2TCL, ++ 0, DP_PPE2TCL_RING_SIZE); + if (ret) { + ath12k_warn(ab, "failed to set up ppe2tcl ring :%d\n", ret); + goto err; + } + +- /* TODO: retain and use ring idx fetched from ppe for avoiding edma hang during SSR */ +- ret = ath12k_dp_srng_setup(ab, &dp->ppeds_comp_ring.ppe_wbm2sw_ring, +- HAL_WBM2SW_RELEASE, +- HAL_WBM2SW_PPEDS_TX_CMPLN_RING_NUM, 0, +- DP_PPE_WBM2SW_RING_SIZE); +- if (ret) { +- ath12k_warn(ab, +- "failed to set up wbm2sw ippeds tx completion ring :%d\n", +- ret); +- goto err; +- } +- ath12k_hal_tx_config_rbm_mapping(ab, 0, +- HAL_WBM2SW_PPEDS_TX_CMPLN_MAP_ID, +- HAL_PPE2TCL); +- + size = sizeof(struct hal_wbm_release_ring_tx) * DP_TX_COMP_RING_SIZE; + dp->ppeds_comp_ring.tx_status_head = 0; + dp->ppeds_comp_ring.tx_status_tail = DP_TX_COMP_RING_SIZE - 1; +@@ -1038,11 +1026,42 @@ int ath12k_dp_srng_ppeds_setup(struct at + goto err; + } + +- ret = ath12k_dp_ppeds_register_soc(dp); ++ ret = ath12k_dp_ppeds_register_soc(dp, &restore_idx); + if (ret) { + ath12k_err(ab, "ppeds registration failed\n"); + goto err; + } ++ ret = ath12k_ppeds_dp_srng_init(ab, &dp->reo2ppe_ring, HAL_REO2PPE, ++ 0, 0, DP_REO2PPE_RING_SIZE, restore_idx.reo2ppe_start_idx); ++ if (ret != 0) { ++ ath12k_warn(ab, "failed to initialize reo2ppe ring :%d\n", ret); ++ goto err; ++ } ++ ++ ath12k_hal_reo_config_reo2ppe_dest_info(ab); ++ ++ ret = ath12k_ppeds_dp_srng_init(ab, &dp->ppe2tcl_ring, HAL_PPE2TCL, ++ 0, 0, DP_PPE2TCL_RING_SIZE, restore_idx.ppe2tcl_start_idx); ++ if (ret) { ++ ath12k_warn(ab, "failed to initialize ppe2tcl ring :%d\n", ret); ++ goto err; ++ } ++ ++ ath12k_hal_tx_config_rbm_mapping(ab, 0, ++ HAL_WBM2SW_PPEDS_TX_CMPLN_MAP_ID, ++ HAL_PPE2TCL); ++ ++ /* TODO: retain and use ring idx fetched from ppe for avoiding edma hang during SSR */ ++ ret = ath12k_dp_srng_setup(ab, &dp->ppeds_comp_ring.ppe_wbm2sw_ring, ++ HAL_WBM2SW_RELEASE, ++ HAL_WBM2SW_PPEDS_TX_CMPLN_RING_NUM, 0, ++ DP_PPE_WBM2SW_RING_SIZE); ++ if (ret) { ++ ath12k_warn(ab, ++ "failed to set up wbm2sw ippeds tx completion ring :%d\n", ++ ret); ++ goto err; ++ } + + err: + /* caller takes care of calling ath12k_dp_srng_ppeds_cleanup */ +@@ -1058,5 +1077,6 @@ void ath12k_dp_srng_ppeds_cleanup(struct + + ath12k_dp_srng_cleanup(ab, &dp->ppe2tcl_ring); + ath12k_dp_srng_cleanup(ab, &dp->reo2ppe_ring); ++ kfree(dp->ppeds_comp_ring.tx_status); + ath12k_dp_srng_cleanup(ab, &dp->ppeds_comp_ring.ppe_wbm2sw_ring); + } +--- a/drivers/net/wireless/ath/ath12k/ppe.h ++++ b/drivers/net/wireless/ath/ath12k/ppe.h +@@ -9,9 +9,15 @@ + #define ATH12K_PPEDS_DEFAULT_POOL_ID 0 + + #ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT ++struct dp_ppe_ds_idxs { ++ u32 ppe2tcl_start_idx; ++ u32 reo2ppe_start_idx; ++}; ++ + void ath12k_dp_srng_ppeds_cleanup(struct ath12k_base *ab); + int ath12k_dp_srng_ppeds_setup(struct ath12k_base *ab); +-int ath12k_dp_ppeds_register_soc(struct ath12k_dp *dp); ++int ath12k_dp_ppeds_register_soc(struct ath12k_dp *dp, ++ struct dp_ppe_ds_idxs *idx); + void ath12k_dp_ppeds_stop(struct ath12k_base *ab); + int ath12k_dp_ppeds_start(struct ath12k_base *ab); + int ath12k_ppeds_detach( struct ath12k_base *ab); +--- a/drivers/net/wireless/ath/ath12k/ahb.c ++++ b/drivers/net/wireless/ath/ath12k/ahb.c +@@ -1087,13 +1087,9 @@ err_core_free: + + static void ath12k_ahb_remove_prepare(struct ath12k_base *ab) + { +- unsigned long left; +- + if (test_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags)) { +- left = wait_for_completion_timeout(&ab->driver_recovery, +- ATH12K_AHB_RECOVERY_TIMEOUT); +- if (!left) +- ath12k_warn(ab, "failed to receive recovery response completion\n"); ++ ath12k_warn(ab, "SSR recovery in progress, interrupting ssr recovery due to shutdown request\n"); ++ return; + } + + set_bit(ATH12K_FLAG_UNREGISTERING, &ab->dev_flags); +--- a/drivers/net/wireless/ath/ath12k/bondif.c ++++ b/drivers/net/wireless/ath/ath12k/bondif.c +@@ -75,10 +75,12 @@ int ath12k_bond_link_enslave(struct ath1 + ath12k_info(NULL, "Enslave bond_dev %px link_ndev %px\n", link_ndev_pvt->bond_dev, link_dev); + ret = bond_enslave(link_ndev_pvt->bond_dev, link_dev, NULL); + if (ret) { ++ arvif->ndev_pvt->is_bond_enslaved = false; + ath12k_err(NULL, "Error bond enslave error\n"); + return -EINVAL; + } + else { ++ arvif->ndev_pvt->is_bond_enslaved = true; + ath12k_info(NULL, "Successfully enslaved link_ndev %s %px\n", + link_dev->name, link_dev); + } +@@ -113,6 +115,7 @@ void ath12k_bond_link_release(struct ath + link_ndev_pvt->bond_dev->name, err); + return; + } ++ arvif->ndev_pvt->is_bond_enslaved = false; + } else { + ath12k_err(NULL, "ERR unable to release Bond %s link ndev %px \n", + arvif->ndev_pvt->link_ndev->name, arvif->ndev_pvt->link_ndev); +@@ -263,6 +266,8 @@ int ath12k_mac_op_change_vif_links(struc + struct net_device *bond_dev = NULL; + char name[20] = {0}; + int ret = 0, chip_id = 0, pdev_id = 0; ++ struct ath12k_link_vif *arvif = NULL; ++ struct ath12k_base *ab = NULL; + + if (!g_bonded_interface_model) + return 0; +@@ -295,6 +300,7 @@ int ath12k_mac_op_change_vif_links(struc + link_ndev_pvt->link_ndev = link_ndev; + link_ndev_pvt->bond_dev = bond_dev; + link_ndev_pvt->is_started = false; ++ link_ndev_pvt->is_bond_enslaved = false; + mldev->vif = vif; + mutex_lock(&vif->bond_mutex); + vif->link_ndev[link_num] = link_ndev; +@@ -323,8 +329,16 @@ int ath12k_mac_op_change_vif_links(struc + /* Delete Link operation */ + mutex_lock(&vif->bond_mutex); + link_ndev = vif->link_ndev[link_num]; +- link_ndev_pvt = netdev_priv(link_ndev); + if (link_ndev) { ++ link_ndev_pvt = netdev_priv(link_ndev); ++ if (link_ndev_pvt->is_bond_enslaved) { ++ arvif = link_ndev_pvt->arvif; ++ ab = arvif->ab; ++ ath12k_bond_link_release(link_ndev_pvt->arvif); ++ if (link_ndev_pvt->vp_num) ++ ath12k_disable_ppe_for_link_netdev(ab, arvif, ++ arvif->ndev_pvt->link_ndev); ++ } + ath12k_info(NULL, "Unregister link netdevice %s link ndev %px link_num %d\n", link_ndev->name, link_ndev, link_num); + unregister_netdevice(link_ndev); + link_ndev_pvt->link_ndev = NULL; +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -1555,8 +1555,10 @@ static void ath12k_pci_shutdown(struct p + struct ath12k_base *ab = pci_get_drvdata(pdev); + + set_bit(ATH12K_FLAG_UNREGISTERING, &ab->ag->dev_flags); +- if (test_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags)) +- return; ++ if (test_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags)) { ++ ath12k_warn(ab, "SSR recovery in progress, interrupting ssr recovery due to shutdown request\n"); ++ return; ++ } + cancel_work_sync(&ab->reset_work); + ath12k_core_deinit(ab); + } +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -344,6 +344,7 @@ struct ath12k_link_vif_pvt { + struct net_device *bond_dev; + struct ieee80211_hw *hw; + bool is_started; ++ bool is_bond_enslaved; + int ppe_vp_profile_idx; + int vp_num; + }; diff --git a/feeds/ipq95xx/mac80211/patches/qca/782-ath12k-add-MLO-group-descriptor-limit-check-in-dp-tx.patch b/feeds/ipq95xx/mac80211/patches/qca/782-ath12k-add-MLO-group-descriptor-limit-check-in-dp-tx.patch new file mode 100644 index 000000000..f7ed4e39c --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/782-ath12k-add-MLO-group-descriptor-limit-check-in-dp-tx.patch @@ -0,0 +1,187 @@ +From 1b566d8fccb4c4d499c4e4c597ebd4c5474daa7c Mon Sep 17 00:00:00 2001 +From: P Praneesh +Date: Tue, 13 Jun 2023 16:17:20 +0530 +Subject: [PATCH] ath12k: add MLO group descriptor limit check in dp tx + +Limit the tx data packet for per MLO group with the threshold +limit of 0xC000. Without the Tx limit check Multicast frames +send lead to out of memory in the system where HW capable of processing +more than the system memory profile. + +Remove ATH12K_NUM_EAPOL_RESERVE from the ATH12K_DP_PDEV_TX_LIMIT calculation +because driver tx limit check allows all the EAPOL frames irrespective of the +pdev/group limit threshold. + +Rename Threshold limit as Pdev tx threshold limit to make it relevant to the +functionality. Add member in soc dp stats to capture the group threshold limit. + +Signed-off-by: Balamurugan Mahalingam +Signed-off-by: P Praneesh +--- + drivers/net/wireless/ath/ath12k/bondif.c | 14 ++------------ + drivers/net/wireless/ath/ath12k/core.c | 1 + + drivers/net/wireless/ath/ath12k/core.h | 4 +++- + drivers/net/wireless/ath/ath12k/debugfs.c | 19 +++++++++++++++---- + drivers/net/wireless/ath/ath12k/dp.h | 4 ++-- + drivers/net/wireless/ath/ath12k/dp_tx.c | 4 ++++ + drivers/net/wireless/ath/ath12k/mac.c | 20 ++++++++++++++------ + 7 files changed, 41 insertions(+), 25 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/bondif.c ++++ b/drivers/net/wireless/ath/ath12k/bondif.c +@@ -505,6 +505,7 @@ int ath12k_mcast_dp_tx(struct ath12k *ar + ath12k_dbg_dump(ab, ATH12K_DBG_DP_TX, NULL, "dp tx msdu: ", skb->data, skb->len); + arvif->link_stats.tx_enqueued++; + atomic_inc(&ar->dp.num_tx_pending); ++ atomic_inc(&ab->ag->num_dp_tx_pending); + + return 0; + +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -156,6 +156,7 @@ ath12k_core_hw_group_alloc(u8 id, u8 max + ag->id = id; + ag->num_chip = max_chip; + ag->mlo_capable = !!ath12k_mlo_capable; ++ atomic_set(&ag->num_dp_tx_pending, 0); + list_add(&ag->list, &ath12k_hw_groups); + mutex_init(&ag->mutex_lock); + mutex_init(&ag->mlomem_arena.mutex_lock); +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -1118,7 +1118,8 @@ struct ath12k_soc_dp_tx_err_stats { + /* TCL Ring Buffers unavailable */ + u32 txbuf_na[DP_TCL_NUM_RING_MAX]; + +- u32 threshold_limit; ++ u32 pdev_threshold_limit; ++ u32 group_threshold_limit; + + /* Other failures during dp_tx due to mem allocation failure + * idr unavailable etc. +@@ -1251,6 +1252,7 @@ struct ath12k_hw_group { + struct mutex mutex_lock; + struct ath12k_mgmt_rx_reo_context rx_reo; + struct ath12k_host_mlo_mem_arena mlomem_arena; ++ atomic_t num_dp_tx_pending; + }; + + /* Master structure to hold the hw data which may be used in core module */ +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -1649,8 +1649,12 @@ static ssize_t ath12k_debugfs_dump_soc_d + i, soc_stats->tx_err.txbuf_na[i]); + + len += scnprintf(buf + len, size - len, +- "\nThreshold limit: %d\n", +- soc_stats->tx_err.threshold_limit); ++ "\nTx Threshold limit: %d\n", ++ soc_stats->tx_err.pdev_threshold_limit); ++ ++ len += scnprintf(buf + len, size - len, ++ "\nGroup Tx Threshold limit: %u\n", ++ soc_stats->tx_err.group_threshold_limit); + + len += scnprintf(buf + len, size - len, + "\nMisc Transmit Failures: %d\n", +@@ -1726,14 +1730,17 @@ static ssize_t ath12k_debugfs_dump_soc_d + soc_stats->tx_completed[2], + soc_stats->tx_completed[3]); + +- for (i = 0; i < 3; i++) { + ++ len += scnprintf(buf + len, size - len, ++ "\nag tx_pending: %u\n", ++ atomic_read(&ab->ag->num_dp_tx_pending)); ++ ++ for (i = 1; i <= ab->num_radios; i++) { + ar = ath12k_mac_get_ar_by_pdev_id(ab, i); + if (ar) { + len += scnprintf(buf + len, size - len, +- "\ntx_pending [%d]: 0:%d\n", +- i, +- atomic_read(&ar->dp.num_tx_pending)); ++ "\nar tx_pending [%d]: %u\n", i, ++ atomic_read(&ar->dp.num_tx_pending)); + } + } + +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -276,8 +276,8 @@ struct ath12k_pdev_dp { + #define DP_REO_QREF_NUM GENMASK(31, 16) + #define DP_MAX_PEER_ID 2047 + +-#define ATH12K_NUM_EAPOL_RESERVE 1024 +-#define ATH12K_DP_PDEV_TX_LIMIT (ATH12K_NUM_POOL_TX_DESC - ATH12K_NUM_EAPOL_RESERVE) ++#define ATH12K_DP_PDEV_TX_LIMIT ATH12K_NUM_POOL_TX_DESC ++#define ATH12K_DP_GROUP_TX_LIMIT 49152 + + /* Total size of the LUT is based on 2K peers, each having reference + * for 17tids, note each entry is of type ath12k_reo_queue_ref +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -363,6 +363,7 @@ int ath12k_dp_tx_direct(struct ath12k_li + spin_unlock_bh(&tcl_ring->lock); + + atomic_inc(&ar->dp.num_tx_pending); ++ atomic_inc(&ab->ag->num_dp_tx_pending); + + return 0; + +@@ -657,6 +658,7 @@ int ath12k_dp_tx(struct ath12k *ar, stru + arvif->link_stats.tx_enqueued++; + + atomic_inc(&ar->dp.num_tx_pending); ++ atomic_inc(&ab->ag->num_dp_tx_pending); + + return 0; + +@@ -682,6 +684,8 @@ fail_remove_tx_buf: + + static inline void ath12k_dp_tx_decrement(struct ath12k *ar) + { ++ atomic_dec(&ar->ab->ag->num_dp_tx_pending); ++ + if (atomic_read(&ar->flush_request)) { + if (atomic_dec_and_test(&ar->dp.num_tx_pending)) + wake_up(&ar->tx_empty_waitq); +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -9062,14 +9062,22 @@ static u8 ath12k_mac_get_tx_link(struct + return link; + } + +-static bool ath12k_mac_tx_check_max_limit(struct ath12k *ar, struct sk_buff *skb) ++bool ath12k_mac_tx_check_max_limit(struct ath12k *ar, struct sk_buff *skb) + { ++ struct ath12k_base *ab = ar->ab; ++ ++ /* Allow EAPOL */ ++ if (skb->protocol == cpu_to_be16(ETH_P_PAE)) ++ return false; ++ ++ if (atomic_read(&ab->ag->num_dp_tx_pending) > ATH12K_DP_GROUP_TX_LIMIT) { ++ ab->soc_stats.tx_err.group_threshold_limit++; ++ return true; ++ } ++ + if (atomic_read(&ar->dp.num_tx_pending) > ATH12K_DP_PDEV_TX_LIMIT) { +- /* Allow EAPOL */ +- if (!(skb->protocol == cpu_to_be16(ETH_P_PAE))) { +- ar->ab->soc_stats.tx_err.threshold_limit++; +- return true; +- } ++ ar->ab->soc_stats.tx_err.pdev_threshold_limit++; ++ return true; + } + + return false; +--- a/drivers/net/wireless/ath/ath12k/mac.h ++++ b/drivers/net/wireless/ath/ath12k/mac.h +@@ -241,4 +241,5 @@ bool ath12k_mac_is_ml_arvif(struct ath12 + u16 ath12k_calculate_subchannel_count(enum nl80211_chan_width width); + void ath12k_mac_background_dfs_event(struct ath12k *ar, + enum ath12k_background_dfs_events ev); ++bool ath12k_mac_tx_check_max_limit(struct ath12k *ar, struct sk_buff *skb); + #endif diff --git a/feeds/ipq95xx/mac80211/patches/qca/782-wifi-ath12k-Move-SAWF-and-Telemetry-under-conditiona.patch b/feeds/ipq95xx/mac80211/patches/qca/782-wifi-ath12k-Move-SAWF-and-Telemetry-under-conditiona.patch new file mode 100644 index 000000000..ce0859b4d --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/782-wifi-ath12k-Move-SAWF-and-Telemetry-under-conditiona.patch @@ -0,0 +1,376 @@ +From e2a1660fada3d633d3a8a43d0ac45691262bfc05 Mon Sep 17 00:00:00 2001 +From: Nagarajan Maran +Date: Tue, 13 Jun 2023 17:22:10 +0530 +Subject: [PATCH] wifi: ath12k: Move SAWF and Telemetry under conditional + enabling + +Move SAWF and Telemetry code under the flag "CPTCFG_ATH12K_SAWF" +since openwrt-23 project is facing build issues as NSS modules +are not present in that project. + +Signed-off-by: Nagarajan Maran +--- + drivers/net/wireless/ath/ath12k/Kconfig | 7 +++++++ + drivers/net/wireless/ath/ath12k/Makefile | 5 ++--- + drivers/net/wireless/ath/ath12k/core.c | 11 ++++++++++- + drivers/net/wireless/ath/ath12k/core.h | 2 ++ + drivers/net/wireless/ath/ath12k/dp_rx.c | 5 ++++- + drivers/net/wireless/ath/ath12k/dp_tx.c | 10 ++++++++++ + drivers/net/wireless/ath/ath12k/peer.h | 2 ++ + drivers/net/wireless/ath/ath12k/sawf.h | 3 +++ + drivers/net/wireless/ath/ath12k/telemetry.h | 2 ++ + drivers/net/wireless/ath/ath12k/vendor.c | 7 +++++-- + drivers/net/wireless/ath/ath12k/vendor.h | 6 +++++- + drivers/net/wireless/ath/ath12k/wmi.c | 6 ++++++ + local-symbols | 1 + + 13 files changed, 59 insertions(+), 8 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/Kconfig ++++ b/drivers/net/wireless/ath/ath12k/Kconfig +@@ -79,3 +79,10 @@ config ATH12K_BONDED_DS_SUPPORT + Enable ath12k Bonded-DS support + + Say Y to enable Bonded DS Support. If unsure, say N. ++ ++config ATH12K_SAWF ++ bool "ath12k Service Aware WiFi Framework and Telemetry support" ++ depends on ATH12K ++ help ++ Enable ath12k SAWF and telemetry support ++ Say Y to enable. If unsure, say N. +--- a/drivers/net/wireless/ath/ath12k/Makefile ++++ b/drivers/net/wireless/ath/ath12k/Makefile +@@ -21,9 +21,7 @@ ath12k-y += core.o \ + mhi.o \ + pci.o \ + dp_mon.o \ +- sawf.o \ +- vendor.o \ +- telemetry.o ++ vendor.o + + ath12k-$(CPTCFG_ATH12K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o + ath12k-$(CPTCFG_NL80211_TESTMODE) += testmode.o +@@ -35,6 +33,7 @@ ath12k-$(CPTCFG_ATH12K_PKTLOG) += pktlog + ath12k-$(CPTCFG_ATH12K_AHB) += ahb.o + ath12k-$(CPTCFG_ATH12K_PPE_DS_SUPPORT) += ppe.o + ath12k-$(CPTCFG_ATH12K_BONDED_DS_SUPPORT) += bondif.o ++ath12k-$(CPTCFG_ATH12K_SAWF) += sawf.o telemetry.o + + # for tracing framework to find trace.h + CFLAGS_trace.o := -I$(src) +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -1954,9 +1954,10 @@ static void ath12k_core_restart(struct w + mutex_unlock(&ah->conf_mutex); + } + } +- ++#ifdef CPTCFG_ATH12K_SAWF + if (ath12k_sawf_reconfigure_on_crash(ab)) + ath12k_warn(ab, "SAWF SLA reconfiguring failed\n"); ++#endif /* CPTCFG_ATH12K_SAWF */ + } + + static void ath12k_rproc_recovery_do_coredump(struct rproc *rproc) +@@ -2486,6 +2487,8 @@ err_sc_free: + return NULL; + } + ++#ifdef CPTCFG_ATH12K_SAWF ++ + int ath12k_send_sawf_configs_soc(struct ath12k_sawf_svc_params *new_param) + { + struct ath12k_hw_group *ag; +@@ -2567,6 +2570,8 @@ int ath12k_core_sawf_ul_config(struct ne + return ret; + } + ++#endif /* CPTCFG_ATH12K_SAWF */ ++ + static int ath12k_init(void) + { + int ret; +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -1568,9 +1568,11 @@ void ath12k_fw_stats_pdevs_free(struct l + void ath12k_fw_stats_bcn_free(struct list_head *head); + void ath12k_fw_stats_reset(struct ath12k *ar); + void ath12k_fw_stats_free(struct ath12k_fw_stats *stats); ++#ifdef CPTCFG_ATH12K_SAWF + int ath12k_send_sawf_configs_soc(struct ath12k_sawf_svc_params *new_param); + int ath12k_sawf_send_disable_soc(u8 svc_id); + int ath12k_core_sawf_ul_config(struct net_device *dev, struct ath12k_sawf_wmi_peer_latency_param *latency_info); ++#endif /* CPTCFG_ATH12K_SAWF */ + + static inline const char *ath12k_scan_state_str(enum ath12k_scan_state state) + { +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -2036,6 +2036,7 @@ next: + } + } + ++#ifdef CPTCFG_ATH12K_SAWF + static void ath12k_htt_sawf_info_ind_handler(struct ath12k_base *ab, + struct sk_buff *skb) + { +@@ -2076,7 +2077,7 @@ static void ath12k_htt_sawf_info_ind_han + ast_idx, + tgt_opaque_id); + } +- ++#endif /* CPTCFG_ATH12K_SAWF */ + void ath12k_dp_htt_htc_t2h_msg_handler(struct ath12k_base *ab, + struct sk_buff *skb) + { +@@ -2174,12 +2175,14 @@ void ath12k_dp_htt_htc_t2h_msg_handler(s + case HTT_T2H_MSG_TYPE_VDEV_TXRX_STATS_PERIODIC_IND: + ath12k_htt_vdev_txrx_stats_handler(ab, skb); + break; ++#ifdef CPTCFG_ATH12K_SAWF + case HTT_T2H_MSG_TYPE_SAWF_MSDUQ_INFO_IND: + ath12k_htt_sawf_info_ind_handler(ab, skb); + break; + case HTT_T2H_MSG_TYPE_SAWF_DEF_QUEUES_MAP_REPORT_CONF: + ath12k_htt_sawf_def_q_map_report_handler(ab, skb); + break; ++#endif /* CPTCFG_ATH12K_SAWF */ + default: + ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "dp_htt event %d not handled\n", + type); +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -14,6 +14,7 @@ + #include + #include + ++#ifdef CPTCFG_ATH12K_SAWF + static inline u32 ath12k_sawf_get_tcl_metadata_update(u32 sk_buff_mark) + { + u32 tcl_metadata = 0; +@@ -45,6 +46,7 @@ static inline u32 ath12k_sawf_get_tcl_cm + return update; + } + ++#endif /* CPTCFG_ATH12K_SAWF */ + static enum hal_tcl_encap_type + ath12k_dp_tx_get_encap_type(struct ath12k_link_vif *arvif, struct sk_buff *skb) + { +@@ -340,6 +342,7 @@ int ath12k_dp_tx_direct(struct ath12k_li + tcl_desc.info3 = arvif->desc.info3; + tcl_desc.info4 = arvif->desc.info4; + tcl_desc.info5 = 0; ++#ifdef CPTCFG_ATH12K_SAWF + /* SAWF */ + if (u32_get_bits(skb->mark, SAWF_TAG_ID) == SAWF_VALID_TAG) { + u32 msduq_id = u32_get_bits(skb->mark, SAWF_MSDUQ_ID); +@@ -353,6 +356,7 @@ int ath12k_dp_tx_direct(struct ath12k_li + HAL_TCL_DATA_CMD_INFO1_CMD_NUM); + } + } ++#endif + memcpy(hal_tcl_desc, &tcl_desc, sizeof(tcl_desc)); + dsb(st); + ath12k_hal_srng_access_umac_src_ring_end_nolock(tcl_ring); +@@ -444,6 +448,7 @@ int ath12k_dp_tx(struct ath12k *ar, stru + * SAWF and Global Seq Number are mutually exclusive. + * Global Seq Number - Multicast, SAWF - Unicast + */ ++#ifdef CPTCFG_ATH12K_SAWF + if (u32_get_bits(skb->mark, SAWF_TAG_ID) == SAWF_VALID_TAG) { + u32 msduq_id = u32_get_bits(skb->mark, SAWF_MSDUQ_ID); + if (msduq_id < (ab->max_msduq_per_tid * ATH12K_SAWF_MAX_TID_SUPPORT)) { +@@ -451,6 +456,9 @@ int ath12k_dp_tx(struct ath12k *ar, stru + ath12k_sawf_get_tcl_metadata_update(skb->mark); + } + } else if (gsn_valid) { ++#else ++ if (gsn_valid) { ++#endif /* CPTCFG_ATH12K_SAWF */ + ti.meta_data_flags = u32_encode_bits(HTT_TCL_META_DATA_TYPE_GLOBAL_SEQ_NUM, + HTT_TCL_META_DATA_TYPE_MISSION) | + u32_encode_bits(mcbc_gsn, HTT_TCL_META_DATA_GLOBAL_SEQ_NUM); +@@ -628,6 +636,7 @@ int ath12k_dp_tx(struct ath12k *ar, stru + tcl_cmd->info4 = arvif->desc.info4; + tcl_cmd->info5 = 0; + ++#ifdef CPTCFG_ATH12K_SAWF + /* SAWF */ + if (u32_get_bits(skb->mark, SAWF_TAG_ID) == SAWF_VALID_TAG) { + u32 msduq_id = u32_get_bits(skb->mark, SAWF_MSDUQ_ID); +@@ -637,6 +646,7 @@ int ath12k_dp_tx(struct ath12k *ar, stru + ath12k_sawf_get_tcl_cmd_info3_update(msduq_id); + } + } ++#endif /* CPTCFG_ATH12K_SAWF */ + + dsb(st); + ath12k_hal_srng_access_umac_src_ring_end_nolock(tcl_ring); +--- a/drivers/net/wireless/ath/ath12k/peer.h ++++ b/drivers/net/wireless/ath/ath12k/peer.h +@@ -25,7 +25,9 @@ struct ath12k_peer { + struct list_head list; + struct ieee80211_sta *sta; + struct ieee80211_vif *vif; ++#ifdef CPTCFG_ATH12K_SAWF + struct ath12k_sawf_peer_ctx sawf_ctx_peer; ++#endif /* CPTCFG_ATH12K_SAWF */ + int vdev_id; + u8 addr[ETH_ALEN]; + int peer_id; +--- a/drivers/net/wireless/ath/ath12k/sawf.h ++++ b/drivers/net/wireless/ath/ath12k/sawf.h +@@ -6,6 +6,8 @@ + #ifndef ATH12K_SAWF_H + #define ATH12K_SAWF_H + ++#ifdef CPTCFG_ATH12K_SAWF ++ + #define ATH12K_MAC_ADDR_SIZE 6 + #define DP_SAWF_INVALID_PARAM -1 + +@@ -495,4 +497,16 @@ int ath12k_sawf_def_qmap_report_req(stru + + void ath12k_htt_sawf_def_q_map_report_handler(struct ath12k_base *ab, + struct sk_buff *skb); ++ ++#else /* CPTCFG_ATH12K_SAWF */ ++ ++static inline void ath12k_sawf_init(struct ath12k_base *ab) { ++ return; ++} ++ ++static inline void ath12k_sawf_deinit(struct ath12k_base *ab) { ++ return; ++} ++ ++#endif /* CPTCFG_ATH12K_SAWF */ + #endif /* ATH11K_SAWF_H */ +--- a/drivers/net/wireless/ath/ath12k/telemetry.h ++++ b/drivers/net/wireless/ath/ath12k/telemetry.h +@@ -6,6 +6,7 @@ + #ifndef ATH12K_TELEMETRY_H + #define ATH12K_TELEMETRY_H + ++#ifdef CPTCFG_ATH12K_SAWF + + /** + * struct ath12k_sla_samples_cfg- telemetry sawf sla samples configuration +@@ -101,4 +102,15 @@ int ath12k_telemetry_sawf_sla_samples_co + int ath12k_telemetry_sawf_sla_thershold_config(struct ath12k_sla_thershold_cfg param); + int ath12k_telemetry_sawf_sla_detection_config(struct ath12k_sla_detect_cfg param); + ++#else /* CPTCFG_ATH12K_SAWF */ ++ ++static inline void ath12k_telemetry_init(struct ath12k_base *ab) { ++ return; ++} ++ ++static inline void ath12k_telemetry_deinit(struct ath12k_base *ab) { ++ return; ++} ++ ++#endif /* CPTCFG_ATH12K_SAWF */ + #endif /* ATH12K_TELEMETRY_H */ +--- a/drivers/net/wireless/ath/ath12k/vendor.c ++++ b/drivers/net/wireless/ath/ath12k/vendor.c +@@ -7,9 +7,10 @@ + #include "core.h" + #include "debug.h" + #include "mac.h" +-#include "sawf.h" + #include "telemetry.h" ++#include "sawf.h" + ++#ifdef CPTCFG_ATH12K_SAWF + static const struct nla_policy + ath12k_vendor_sawf_config_policy[QCA_WLAN_VENDOR_SAWF_ATTR_CONFIG_MAX + 1] = { + [QCN_WLAN_VENDOR_ATTR_SAWF_SERVICE_CLASSES] = {.type = NLA_NESTED}, +@@ -603,8 +604,9 @@ static int ath12k_vendor_telemetry_sawf_ + + return ret; + } +- ++#endif /* CPTCFG_ATH12K_SAWF */ + static struct wiphy_vendor_command ath12k_vendor_commands[] = { ++#ifdef CPTCFG_ATH12K_SAWF + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SVC_CREATE, +@@ -671,6 +673,7 @@ static struct wiphy_vendor_command ath12 + .policy = ath12k_vendor_telemetry_sawf_sla_detect_config_policy, + .maxattr = QCA_WLAN_VENDOR_TELEMETRY_SLA_DETECT_ATTR_CONFIG_MAX, + }, ++#endif + }; + + int ath12k_vendor_register(struct ath12k_hw *ah) +--- a/drivers/net/wireless/ath/ath12k/vendor.h ++++ b/drivers/net/wireless/ath/ath12k/vendor.h +@@ -10,7 +10,7 @@ + enum qca_nl80211_vendor_subcmds { + /* Wi-Fi configuration subcommand */ + QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION = 74, +- ++#ifdef CPTCFG_ATH12K_SAWF + QCA_NL80211_VENDOR_SUBCMD_SVC_CREATE = 204, + QCA_NL80211_VENDOR_SUBCMD_SVC_DISABLE = 205, + QCA_NL80211_VENDOR_SUBCMD_SVC_VIEW = 206, +@@ -20,8 +20,10 @@ enum qca_nl80211_vendor_subcmds { + QCA_NL80211_VENDOR_SUBCMD_TELEMETRY_SLA_THERSHOLD_CFG = 210, + QCA_NL80211_VENDOR_SUBCMD_TELEMETRY_SLA_SAMPLES_CFG = 211, + QCA_NL80211_VENDOR_SUBCMD_TELEMETRY_SLA_BREACH_DETECTION_CFG = 212, ++#endif /* CPTCFG_ATH12K_SAWF */ + }; + ++#ifdef CPTCFG_ATH12K_SAWF + enum qca_wlan_vendor_sawf_attr_config { + QCN_WLAN_VENDOR_ATTR_SAWF_SERVICE_CLASSES = 1, + QCN_WLAN_VENDOR_ATTR_SAWF_SVC_ID, +@@ -103,5 +105,7 @@ enum qca_wlan_vendor_attr_telemetry_sawf + QCA_WLAN_VENDOR_TELEMETRY_SLA_THERSHOLD_CFG_AFTER_LAST - 1, + }; + ++#endif /* CPTCFG_ATH12K_SAWF */ ++ + int ath12k_vendor_register(struct ath12k_hw *ah); + #endif /* QCA_VENDOR_H */ +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -5066,8 +5066,10 @@ ath12k_wmi_copy_resource_config(struct w + WMI_RSRC_CFG_FLAGS2_INTRABSS_MEC_WDS_LEARNING_DISABLE | + u32_encode_bits(tg_cfg->dp_peer_meta_data_ver, + WMI_RSRC_CFG_FLAGS2_RX_PEER_METADATA_VERSION); ++#ifdef CPTCFG_ATH12K_SAWF + wmi_cfg->flags2 |= (tg_cfg->sawf & ath12k_sawf_enable) ? + (WMI_RSRC_CFG_FLAGS2_SAWF_CONFIG_ENABLE_SET) : (0); ++#endif /* CPTCFG_ATH12K_SAWF */ + wmi_cfg->host_service_flags &= ~(1 << WMI_RSRC_CFG_HOST_SVC_FLAG_REG_CC_EXT_SUPPORT_BIT); + wmi_cfg->host_service_flags |= 1 << WMI_RSRC_CFG_HOST_SVC_FLAG_REG_CC_EXT_SUPPORT_BIT; + wmi_cfg->host_service_flags |= 1 << WMI_RSRC_CFG_HOST_SVC_FLAG_REO_QREF_SUPPORT_BIT; +@@ -14257,6 +14259,8 @@ int ath12k_wmi_vdev_adfs_ocac_abort_cmd_ + return ret; + } + ++#ifdef CPTCFG_ATH12K_SAWF ++ + int ath12k_wmi_svc_config_send(struct ath12k *ar, struct ath12k_sawf_svc_params *param) + { + struct ath12k_pdev_wmi *wmi = ar->wmi; +@@ -14342,6 +14346,8 @@ int ath12k_wmi_svc_send_disable(struct a + return ret; + } + ++#endif /* CPTCFG_ATH12K_SAWF */ ++ + static void ath12k_wmi_put_peer_list(struct ath12k_base *ab, + struct wmi_chan_width_peer_list *peer_list, + struct wmi_chan_width_peer_arg *peer_arg, +--- a/local-symbols ++++ b/local-symbols +@@ -146,3 +146,4 @@ ATH12K_SPECTRAL= + ATH12K_PKTLOG= + ATH12K_PPE_DS_SUPPORT= + ATH12K_BONDED_DS_SUPPORT= ++ATH12K_SAWF= diff --git a/feeds/ipq95xx/mac80211/patches/qca/783-001-wifi-ath11k-Fix-BCCA-counter-for-EMA.patch b/feeds/ipq95xx/mac80211/patches/qca/783-001-wifi-ath11k-Fix-BCCA-counter-for-EMA.patch new file mode 100644 index 000000000..b95d643ef --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/783-001-wifi-ath11k-Fix-BCCA-counter-for-EMA.patch @@ -0,0 +1,125 @@ +From ea4988df80e62204c411a60bafadfbff23eaa773 Mon Sep 17 00:00:00 2001 +From: Rameshkumar Sundaram +Date: Thu, 15 Jun 2023 14:33:55 +0530 +Subject: [PATCH] wifi: ath11k: Fix BCCA counter for EMA + +Currently BCCA counter is updated to FW via csa counter offs and +beacon with new countdown is updated for every beacon tx completion event. +For EMA, all EMA beacons are updated in one shot, and counter update for +every tx event will mess up the actual sequence of countdown sent over the air. + +Allow FW to update the countdown till 1 and finalize the color +change. + +Signed-off-by: Rameshkumar Sundaram +--- + drivers/net/wireless/ath/ath11k/mac.c | 21 --------------------- + drivers/net/wireless/ath/ath11k/mac.h | 1 - + drivers/net/wireless/ath/ath11k/wmi.c | 23 +++++++++++++++-------- + 3 files changed, 15 insertions(+), 30 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c +index 28c9908..9822c75 100644 +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -1778,27 +1778,6 @@ static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif) + return ath11k_mac_setup_bcn_tmpl_non_ema(arvif); + } + +-void ath11k_mac_bcn_tx_event(struct ath11k_vif *arvif) +-{ +- struct ieee80211_vif *vif = arvif->vif; +- +- if (!vif->bss_conf.color_change_active && !arvif->bcca_zero_sent) +- return; +- +- if (vif->bss_conf.color_change_active && +- ieee80211_beacon_cntdwn_is_complete(vif, 0)) { +- arvif->bcca_zero_sent = true; +- ieee80211_color_change_finish(vif, 0); +- return; +- } +- +- arvif->bcca_zero_sent = false; +- +- if (vif->bss_conf.color_change_active) +- ieee80211_beacon_update_cntdwn(vif, 0); +- ath11k_mac_setup_bcn_tmpl(arvif); +-} +- + static void ath11k_control_beaconing(struct ath11k_vif *arvif, + struct ieee80211_bss_conf *info) + { +diff --git a/drivers/net/wireless/ath/ath11k/mac.h b/drivers/net/wireless/ath/ath11k/mac.h +index 4f27d05..bfc3e2e 100644 +--- a/drivers/net/wireless/ath/ath11k/mac.h ++++ b/drivers/net/wireless/ath/ath11k/mac.h +@@ -182,7 +182,6 @@ void ath11k_mac_handle_beacon_miss(struct ath11k *ar, u32 vdev_id); + void ath11k_mac_fill_reg_tpc_info(struct ath11k *ar, + struct ieee80211_vif *vif, + struct ieee80211_chanctx_conf *ctx); +-void ath11k_mac_bcn_tx_event(struct ath11k_vif *arvif); + int ath11k_mac_wait_tx_complete(struct ath11k *ar); + int ath11k_mac_vif_set_keepalive(struct ath11k_vif *arvif, + enum wmi_sta_keepalive_method method, +diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c +index a070170..4cc284e 100644 +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -2075,9 +2075,10 @@ int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id, + cmd->vdev_id = vdev_id; + cmd->tim_ie_offset = offs->tim_offset; + +- if (vif->bss_conf.csa_active) { ++ if (vif->bss_conf.csa_active || vif->bss_conf.color_change_active) { + cmd->csa_switch_count_offset = offs->cntdwn_counter_offs[0]; + cmd->ext_csa_switch_count_offset = offs->cntdwn_counter_offs[1]; ++ cmd->csa_event_bitmap = cpu_to_le32(0xFFFFFFFF); + } + + cmd->buf_len = bcn->len; +@@ -8345,7 +8346,6 @@ static void ath11k_bcn_tx_status_event(struct ath11k_base *ab, struct sk_buff *s + rcu_read_unlock(); + return; + } +- ath11k_mac_bcn_tx_event(arvif); + rcu_read_unlock(); + } + +@@ -9378,10 +9378,7 @@ ath11k_wmi_process_csa_switch_count_event(struct ath11k_base *ab, + { + int i; + struct ath11k_vif *arvif; +- +- /* Finish CSA once the switch count becomes NULL */ +- if (ev->current_switch_count) +- return; ++ struct ieee80211_bss_conf *bss_conf; + + rcu_read_lock(); + for (i = 0; i < ev->num_vdevs; i++) { +@@ -9392,9 +9389,19 @@ ath11k_wmi_process_csa_switch_count_event(struct ath11k_base *ab, + vdev_ids[i]); + continue; + } ++ bss_conf = &arvif->vif->bss_conf; ++ if (arvif->is_up && (bss_conf->csa_active || bss_conf->color_change_active)) { ++ if (!ev->current_switch_count) { ++ if (bss_conf->csa_active) ++ ieee80211_csa_finish(arvif->vif, 0); ++ } else if (ev->current_switch_count > 1) { ++ ieee80211_beacon_update_cntdwn(arvif->vif, 0); ++ } else { ++ if (bss_conf->color_change_active) ++ ieee80211_color_change_finish(arvif->vif, 0); ++ } ++ } + +- if (arvif->is_up && arvif->vif->bss_conf.csa_active) +- ieee80211_csa_finish(arvif->vif, 0); + } + rcu_read_unlock(); + } +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/783-002-wifi-ath12k-Fix-BCCA-counter-for-EMA.patch b/feeds/ipq95xx/mac80211/patches/qca/783-002-wifi-ath12k-Fix-BCCA-counter-for-EMA.patch new file mode 100644 index 000000000..dac266f93 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/783-002-wifi-ath12k-Fix-BCCA-counter-for-EMA.patch @@ -0,0 +1,111 @@ +From 2717fe6fd7f54cb2d21074c5e88b12f962762ed2 Mon Sep 17 00:00:00 2001 +From: Rameshkumar Sundaram +Date: Thu, 15 Jun 2023 12:30:15 +0530 +Subject: [PATCH] wifi: ath12k: Fix BCCA counter for EMA + +Currently BCCA counter is updated to FW via csa counter offs and +beacon with new countdown is updated for every beacon tx completion event. +For EMA, all EMA beacons are updated in one shot, and counter update for +every tx event will mess up the actual sequence of countdown sent over the air. + +Allow FW to update the countdown till 1 and finalize the color +change. + +Signed-off-by: Rameshkumar Sundaram +--- + drivers/net/wireless/ath/ath12k/mac.c | 31 --------------------------- + drivers/net/wireless/ath/ath12k/mac.h | 1 - + drivers/net/wireless/ath/ath12k/wmi.c | 14 +++++++----- + 3 files changed, 9 insertions(+), 37 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index f8953e3..2d4b3f1 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -1735,37 +1735,6 @@ static int ath12k_mac_setup_bcn_tmpl(struct ath12k_link_vif *arvif) + return ath12k_mac_setup_bcn_tmpl_non_ema(arvif); + } + +- +-void ath12k_mac_bcn_tx_event(struct ath12k_link_vif *arvif) +-{ +- struct ieee80211_vif *vif = arvif->ahvif->vif; +- struct ath12k *ar = arvif->ar; +- struct ieee80211_bss_conf* link_conf; +- +- link_conf = ath12k_get_link_bss_conf(arvif); +- +- if (!link_conf) { +- ath12k_warn(ar->ab, "unable to access bss link conf in bcn tx event\n"); +- return; +- } +- +- if (!link_conf->color_change_active && !arvif->bcca_zero_sent) +- return; +- +- if (link_conf->color_change_active && +- ieee80211_beacon_cntdwn_is_complete(vif, arvif->link_id)) { +- arvif->bcca_zero_sent = true; +- ieee80211_color_change_finish(vif, arvif->link_id); +- return; +- } +- +- arvif->bcca_zero_sent = false; +- +- if (link_conf->color_change_active && !link_conf->ema_ap) +- ieee80211_beacon_update_cntdwn(vif, arvif->link_id); +- ieee80211_queue_work(ar->ah->hw, &arvif->update_bcn_template_work); +-} +- + static void ath12k_control_beaconing(struct ath12k_link_vif *arvif, + struct ieee80211_bss_conf *info) + { +diff --git a/drivers/net/wireless/ath/ath12k/mac.h b/drivers/net/wireless/ath/ath12k/mac.h +index f96d82f..aa11846 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.h ++++ b/drivers/net/wireless/ath/ath12k/mac.h +@@ -227,7 +227,6 @@ enum hal_encrypt_type ath12k_dp_tx_get_encrypt_type(u32 cipher); + void ath12k_mac_get_any_chandef_iter(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *conf, + void *data); +-void ath12k_mac_bcn_tx_event(struct ath12k_link_vif *arvif); + struct ath12k *ath12k_get_ar_by_vif(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u8 link_id); + int ath12k_mac_mlo_setup(struct ath12k_hw *ah); +diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c +index a4457d5..f6de095 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -8483,7 +8483,6 @@ static void ath12k_bcn_tx_status_event(struct ath12k_base *ab, struct sk_buff *s + rcu_read_unlock(); + return; + } +- ath12k_mac_bcn_tx_event(arvif); + rcu_read_unlock(); + } + +@@ -11639,12 +11638,17 @@ ath12k_wmi_process_csa_switch_count_event(struct ath12k_base *ab, + continue; + + /* FIXME some changes are expected for ML vifs */ +- if (arvif->is_up && link_conf->csa_active) { +- if (!ev->current_switch_count) +- ieee80211_csa_finish(arvif->ahvif->vif, arvif->link_id); +- else if (ev->current_switch_count > 1) ++ if (arvif->is_up && (link_conf->csa_active || link_conf->color_change_active)) { ++ if (!ev->current_switch_count) { ++ if (link_conf->csa_active) ++ ieee80211_csa_finish(arvif->ahvif->vif, arvif->link_id); ++ } else if (ev->current_switch_count > 1) { + ieee80211_beacon_update_cntdwn(arvif->ahvif->vif, + arvif->link_id); ++ } else { ++ if (link_conf->color_change_active) ++ ieee80211_color_change_finish(arvif->ahvif->vif, arvif->link_id); ++ } + } + } + rcu_read_unlock(); +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/783-During-OBSS-collision-detection-firmware-sets-the-sc.patch b/feeds/ipq95xx/mac80211/patches/qca/783-During-OBSS-collision-detection-firmware-sets-the-sc.patch new file mode 100644 index 000000000..91ddc6c22 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/783-During-OBSS-collision-detection-firmware-sets-the-sc.patch @@ -0,0 +1,31 @@ +From 19e161093670cfa2bfb7142efac69946975bafce Mon Sep 17 00:00:00 2001 +From: Aishwarya R +Date: Wed, 12 Jul 2023 16:24:15 +0530 +Subject: [PATCH] ath12k: Set scan priority to medium + + During OBSS collision detection firmware sets the scan + priority to medium. As ath12k scan priority is low, OBSS scan results are + getting aborted due to priority mismatch. As per the firmware recommendation + setting the priority to medium. + +Signed-off-by: Aishwarya R +--- + drivers/net/wireless/ath/ath12k/wmi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c +index ca71791..9f5742a 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -2852,7 +2852,7 @@ void ath12k_wmi_start_scan_init(struct ath12k *ar, + { + /* setup commonly used values */ + arg->scan_req_id = 1; +- arg->scan_priority = WMI_SCAN_PRIORITY_LOW; ++ arg->scan_priority = WMI_SCAN_PRIORITY_MEDIUM; + arg->dwell_time_active = 50; + arg->dwell_time_active_2g = 0; + arg->dwell_time_passive = 150; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/783-ath12k-Add-peer-rhash-table-support.patch b/feeds/ipq95xx/mac80211/patches/qca/783-ath12k-Add-peer-rhash-table-support.patch new file mode 100644 index 000000000..f9545e9fe --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/783-ath12k-Add-peer-rhash-table-support.patch @@ -0,0 +1,696 @@ +From a6e92e6fa3bbfedf264e5304c01660a9863ad0a3 Mon Sep 17 00:00:00 2001 +From: Avula Sri Charan +Date: Thu, 18 May 2023 16:43:58 +0530 +Subject: [Patch] wifi: ath12k: Add peer rhash table support + +When more clients (128) are connected, the UL data traffic +KPI measurement is low compared to single client. This issue +is due to more CPU cycles spent on the peer lookup operation +with more clients. So reduce the peer lookup operation by +modifying the linear based lookup operation into the rhash +based lookup operation. + +Cherry-picked from : https://patchwork.kernel.org/project/linux-wireless/patch/20220603164559.27769-1-ansuelsmth@gmail.com/ +Cherry-picked from : https://patchwork.kernel.org/project/linux-wireless/patch/20230209222622.1751-1-ansuelsmth@gmail.com/ + +Signed-off-by: Christian Marangi +Signed-off-by: Avula Sri Charan +--- + drivers/net/wireless/ath/ath12k/core.c | 1 + + drivers/net/wireless/ath/ath12k/core.h | 13 + + drivers/net/wireless/ath/ath12k/mac.c | 10 + + drivers/net/wireless/ath/ath12k/peer.c | 407 ++++++++++++++++++++++--- + drivers/net/wireless/ath/ath12k/peer.h | 10 + + 5 files changed, 392 insertions(+), 49 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -2518,6 +2518,7 @@ struct ath12k_base *ath12k_core_alloc(st + goto err_free_wq; + + mutex_init(&ab->core_lock); ++ mutex_init(&ab->tbl_mtx_lock); + spin_lock_init(&ab->base_lock); + init_completion(&ab->reset_complete); + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + #include "qmi.h" + #include "htc.h" + #include "wmi.h" +@@ -1306,6 +1307,18 @@ struct ath12k_base { + struct ath12k_hal_reg_capabilities_ext hal_reg_cap[MAX_RADIOS]; + unsigned long long free_vdev_map; + unsigned long long free_vdev_stats_id_map; ++ ++ /* To synchronize rhash tbl write operation */ ++ struct mutex tbl_mtx_lock; ++ ++ /* The rhashtable containing struct ath12k_peer keyed by mac addr */ ++ struct rhashtable *rhead_peer_addr; ++ struct rhashtable_params rhash_peer_addr_param; ++ ++ /* The rhashtable containing struct ath12k_peer keyed by id */ ++ struct rhashtable *rhead_peer_id; ++ struct rhashtable_params rhash_peer_id_param; ++ + struct list_head peers; + wait_queue_head_t peer_mapping_wq; + u8 mac_addr[ETH_ALEN]; +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -1033,13 +1033,16 @@ void ath12k_mac_peer_cleanup_all(struct + + lockdep_assert_held(&ar->conf_mutex); + ++ mutex_lock(&ab->tbl_mtx_lock); + spin_lock_bh(&ab->base_lock); + list_for_each_entry_safe(peer, tmp, &ab->peers, list) { + ath12k_dp_rx_peer_tid_cleanup(ar, peer); ++ ath12k_peer_rhash_delete(ab, peer); + list_del(&peer->list); + kfree(peer); + } + spin_unlock_bh(&ab->base_lock); ++ mutex_unlock(&ab->tbl_mtx_lock); + + if (!list_empty(&ab->neighbor_peers)) + ath12k_debugfs_nrp_cleanup_all(ar); +@@ -6667,17 +6670,20 @@ static void ath12k_mac_station_post_remo + + ath12k_mac_dec_num_stations(arvif, arsta); + ++ mutex_lock(&ar->ab->tbl_mtx_lock); + spin_lock_bh(&ar->ab->base_lock); + peer = ath12k_peer_find(ar->ab, arvif->vdev_id, arsta->addr); + if (peer && peer->sta == sta) { + ath12k_warn(ar->ab, "Found peer entry %pM n vdev %i after it was supposedly removed\n", + arsta->addr, arvif->vdev_id); ++ ath12k_peer_rhash_delete(ar->ab, peer); + peer->sta = NULL; + list_del(&peer->list); + kfree(peer); + ar->num_peers--; + } + spin_unlock_bh(&ar->ab->base_lock); ++ mutex_unlock(&ar->ab->tbl_mtx_lock); + + kfree(arsta->tx_stats); + arsta->tx_stats = NULL; +@@ -15950,6 +15956,9 @@ int ath12k_mac_allocate(struct ath12k_hw + spin_lock_bh(&ab->base_lock); + ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS)) - 1; + spin_unlock_bh(&ab->base_lock); ++ ret = ath12k_peer_rhash_tbl_init(ab); ++ if (ret) ++ goto err_mac_destroy; + + ath12k_dp_pdev_pre_alloc(ab); + } +@@ -15998,6 +16007,7 @@ void ath12k_mac_destroy(struct ath12k_hw + + pdev->ar = NULL; + } ++ ath12k_peer_rhash_tbl_destroy(ab); + } + + for (i = 0; i < ag->num_hw; i++) { +--- a/drivers/net/wireless/ath/ath12k/peer.c ++++ b/drivers/net/wireless/ath/ath12k/peer.c +@@ -66,18 +66,15 @@ static struct ath12k_peer *ath12k_peer_f + struct ath12k_peer *ath12k_peer_find_by_addr(struct ath12k_base *ab, + const u8 *addr) + { +- struct ath12k_peer *peer; + + lockdep_assert_held(&ab->base_lock); + +- list_for_each_entry(peer, &ab->peers, list) { +- if (!ether_addr_equal(peer->addr, addr)) +- continue; ++ if (!ab->rhead_peer_addr) ++ return NULL; + +- return peer; +- } ++ return rhashtable_lookup_fast(ab->rhead_peer_addr, addr, ++ ab->rhash_peer_addr_param); + +- return NULL; + } + + static struct ath12k_peer *ath12k_peer_find_by_ml_id(struct ath12k_base *ab, +@@ -94,21 +91,39 @@ static struct ath12k_peer *ath12k_peer_f + return NULL; + } + +-struct ath12k_peer *ath12k_peer_find_by_id(struct ath12k_base *ab, +- int peer_id) ++struct ath12k_peer *ath12k_peer_find_list_by_id(struct ath12k_base *ab, ++ int peer_id) + { + struct ath12k_peer *peer; + + lockdep_assert_held(&ab->base_lock); + +- if (peer_id & ATH12K_ML_PEER_ID_VALID) ++ if (peer_id & ATH12K_ML_PEER_ID_VALID) { + return ath12k_peer_find_by_ml_id(ab, peer_id); ++ } else { ++ list_for_each_entry(peer, &ab->peers, list) { ++ if (peer->peer_id == peer_id) ++ return peer; ++ } + +- list_for_each_entry(peer, &ab->peers, list) +- if (peer_id == peer->peer_id) +- return peer; ++ return NULL; ++ } ++} + +- return NULL; ++struct ath12k_peer *ath12k_peer_find_by_id(struct ath12k_base *ab, ++ int peer_id) ++{ ++ lockdep_assert_held(&ab->base_lock); ++ ++ if (peer_id & ATH12K_ML_PEER_ID_VALID) { ++ return ath12k_peer_find_by_ml_id(ab, peer_id); ++ } else { ++ if (!ab->rhead_peer_id) ++ return NULL; ++ ++ return rhashtable_lookup_fast(ab->rhead_peer_id, &peer_id, ++ ab->rhash_peer_id_param); ++ } + } + + struct ath12k_peer *ath12k_peer_find_by_vdev_id(struct ath12k_base *ab, +@@ -134,7 +149,7 @@ void ath12k_peer_unmap_event(struct ath1 + + spin_lock_bh(&ab->base_lock); + +- peer = ath12k_peer_find_by_id(ab, peer_id); ++ peer = ath12k_peer_find_list_by_id(ab, peer_id); + if (!peer) { + ath12k_warn(ab, "peer-unmap-event: unknown peer id %d\n", + peer_id); +@@ -195,7 +210,7 @@ void ath12k_peer_mlo_map_event(struct at + ml_peer_id |= ATH12K_ML_PEER_ID_VALID; + + spin_lock_bh(&ab->base_lock); +- peer = ath12k_peer_find_by_id(ab, ml_peer_id); ++ peer = ath12k_peer_find_list_by_id(ab, ml_peer_id); + + /* TODO a sync wait to check ml peer map success or delete + * ml peer info in all link peers and make peer assoc failure +@@ -256,6 +271,80 @@ static int ath12k_wait_for_peer_common(s + return 0; + } + ++static inline int ath12k_peer_rhash_insert(struct ath12k_base *ab, ++ struct rhashtable *rtbl, ++ struct rhash_head *rhead, ++ struct rhashtable_params *params, ++ void *key) ++{ ++ struct ath12k_peer *tmp; ++ ++ lockdep_assert_held(&ab->tbl_mtx_lock); ++ ++ tmp = rhashtable_lookup_get_insert_fast(rtbl, rhead, *params); ++ ++ if (!tmp) ++ return 0; ++ else if (IS_ERR(tmp)) ++ return PTR_ERR(tmp); ++ else ++ return -EEXIST; ++} ++static inline int ath12k_peer_rhash_remove(struct ath12k_base *ab, ++ struct rhashtable *rtbl, ++ struct rhash_head *rhead, ++ struct rhashtable_params *params) ++{ ++ int ret; ++ ++ lockdep_assert_held(&ab->tbl_mtx_lock); ++ ++ ret = rhashtable_remove_fast(rtbl, rhead, *params); ++ if (ret && ret != -ENOENT) ++ return ret; ++ ++ return 0; ++} ++ ++static int ath12k_peer_rhash_add(struct ath12k_base *ab, struct ath12k_peer *peer) ++{ ++ int ret; ++ ++ lockdep_assert_held(&ab->base_lock); ++ lockdep_assert_held(&ab->tbl_mtx_lock); ++ ++ if (!ab->rhead_peer_id || !ab->rhead_peer_addr) ++ return -EPERM; ++ ++ if (peer->rhash_done) ++ return 0; ++ ++ ret = ath12k_peer_rhash_insert(ab, ab->rhead_peer_id, &peer->rhash_id, ++ &ab->rhash_peer_id_param, &peer->peer_id); ++ if (ret) { ++ ath12k_warn(ab, "failed to add peer %pM with id %d in rhash_id ret %d\n", ++ peer->addr, peer->peer_id, ret); ++ return ret; ++ } ++ ++ ret = ath12k_peer_rhash_insert(ab, ab->rhead_peer_addr, &peer->rhash_addr, ++ &ab->rhash_peer_addr_param, &peer->addr); ++ if (ret) { ++ ath12k_warn(ab, "failed to add peer %pM with id %d in rhash_addr ret %d\n", ++ peer->addr, peer->peer_id, ret); ++ goto err_clean; ++ } ++ ++ peer->rhash_done = true; ++ return 0; ++ ++err_clean: ++ ath12k_peer_rhash_remove(ab, ab->rhead_peer_id, &peer->rhash_id, ++ &ab->rhash_peer_id_param); ++ return ret; ++} ++ ++ + void ath12k_peer_cleanup(struct ath12k *ar, u32 vdev_id) + { + struct ath12k_peer *peer, *tmp; +@@ -263,6 +352,7 @@ void ath12k_peer_cleanup(struct ath12k * + + lockdep_assert_held(&ar->conf_mutex); + ++ mutex_lock(&ab->tbl_mtx_lock); + spin_lock_bh(&ab->base_lock); + list_for_each_entry_safe(peer, tmp, &ab->peers, list) { + if (peer->vdev_id != vdev_id) +@@ -270,13 +360,14 @@ void ath12k_peer_cleanup(struct ath12k * + + ath12k_warn(ab, "removing stale peer %pM from vdev_id %d\n", + peer->addr, vdev_id); +- ++ ath12k_peer_rhash_delete(ab, peer); + list_del(&peer->list); + kfree(peer); + ar->num_peers--; + } + + spin_unlock_bh(&ab->base_lock); ++ mutex_unlock(&ab->tbl_mtx_lock); + } + + static int ath12k_wait_for_peer_deleted(struct ath12k *ar, int vdev_id, const u8 *addr) +@@ -309,15 +400,41 @@ int ath12k_wait_for_peer_delete_done(str + + static int ath12k_peer_delete_send(struct ath12k *ar, u32 vdev_id, u8 *addr) + { ++ struct ath12k_peer *peer; ++ struct ath12k_base *ab = ar->ab; + int ret; + + lockdep_assert_held(&ar->conf_mutex); + ++ mutex_lock(&ab->tbl_mtx_lock); ++ spin_lock_bh(&ab->base_lock); ++ ++ peer = ath12k_peer_find_by_addr(ab, addr); ++ if (peer && peer->vdev_id == vdev_id) ++ ath12k_peer_rhash_delete(ab, peer); ++ ++ if (!peer) ++ peer = ath12k_peer_find(ab, vdev_id, addr); ++ ++ if (!peer) { ++ spin_unlock_bh(&ab->base_lock); ++ mutex_unlock(&ab->tbl_mtx_lock); ++ ++ ath12k_warn(ab, ++ "failed to find peer vdev_id %d addr %pM in delete\n", ++ vdev_id, addr); ++ return -EINVAL; ++ } ++ ++ spin_unlock_bh(&ab->base_lock); ++ mutex_unlock(&ab->tbl_mtx_lock); ++ ++ + reinit_completion(&ar->peer_delete_done); + + ret = ath12k_wmi_send_peer_delete_cmd(ar, addr, vdev_id); + if (ret) { +- ath12k_warn(ar->ab, ++ ath12k_warn(ab, + "failed to delete peer vdev_id %d addr %pM ret %d\n", + vdev_id, addr, ret); + return ret; +@@ -453,7 +570,7 @@ int ath12k_peer_create(struct ath12k *ar + u8 link_id = arvif->link_id; + struct ieee80211_vif *vif = arvif->ahvif->vif; + struct ath12k_ml_peer *ml_peer; +- int ret; ++ int ret, fbret; + + lockdep_assert_held(&ar->conf_mutex); + +@@ -481,13 +598,28 @@ int ath12k_peer_create(struct ath12k *ar + spin_unlock_bh(&ar->ah->data_lock); + } + ++ mutex_lock(&ar->ab->tbl_mtx_lock); + spin_lock_bh(&ar->ab->base_lock); + peer = ath12k_peer_find_by_pdev_idx(ar->ab, ar->pdev_idx, param->peer_addr); + if (peer) { ++ ath12k_warn(ar->ab, "Peer %pM already found in pdev_idx %d vdev %d\n", ++ param->peer_addr, ar->pdev_idx, peer->vdev_id); + spin_unlock_bh(&ar->ab->base_lock); ++ mutex_unlock(&ar->ab->tbl_mtx_lock); + return -EINVAL; + } ++ ++ /* In case of Split PHY and roaming scenario, pdev idx ++ * might differ but both the pdev will share same rhash ++ * table. In that case update the rhash table if peer is ++ * already present ++ */ ++ peer = ath12k_peer_find_by_addr(ar->ab, param->peer_addr); ++ if (peer) ++ ath12k_peer_rhash_delete(ar->ab, peer); ++ + spin_unlock_bh(&ar->ab->base_lock); ++ mutex_unlock(&ar->ab->tbl_mtx_lock); + + ret = ath12k_wmi_send_peer_create_cmd(ar, param); + if (ret) { +@@ -502,21 +634,24 @@ int ath12k_peer_create(struct ath12k *ar + if (ret) + return ret; + ++ mutex_lock(&ar->ab->tbl_mtx_lock); + spin_lock_bh(&ar->ab->base_lock); + + peer = ath12k_peer_find(ar->ab, param->vdev_id, param->peer_addr); + if (!peer) { + spin_unlock_bh(&ar->ab->base_lock); ++ mutex_unlock(&ar->ab->tbl_mtx_lock); + ath12k_warn(ar->ab, "failed to find peer %pM on vdev %i after creation\n", + param->peer_addr, param->vdev_id); + +- ret = __ath12k_peer_delete(ar, param->vdev_id, param->peer_addr); +- if (ret) +- ath12k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n", +- param->vdev_id, param->peer_addr); +- +- return -ENOENT; ++ goto cleanup; + } ++ ret = ath12k_peer_rhash_add(ar->ab, peer); ++ if (ret) { ++ spin_unlock_bh(&ar->ab->base_lock); ++ mutex_unlock(&ar->ab->tbl_mtx_lock); ++ goto cleanup; ++ } + + peer->pdev_idx = ar->pdev_idx; + peer->sta = sta; +@@ -563,8 +698,18 @@ int ath12k_peer_create(struct ath12k *ar + ath12k_dbg(ar->ab, ATH12K_DBG_PEER, "peer created %pM\n", param->peer_addr); + + spin_unlock_bh(&ar->ab->base_lock); ++ mutex_unlock(&ar->ab->tbl_mtx_lock); + + return 0; ++ ++cleanup: ++ fbret = __ath12k_peer_delete(ar, param->vdev_id, param->peer_addr); ++ if (fbret) ++ ath12k_warn(ar->ab, "failed peer %pM delete vdev_id %d fallback ret %d\n", ++ param->peer_addr, param->vdev_id, fbret); ++ ++ return ret; ++ + } + + static u16 ath12k_mac_alloc_ml_peer_id(struct ath12k_hw *ah) +@@ -664,3 +809,204 @@ int ath12k_ml_peer_delete(struct ath12k_ + sta->addr); + return 0; + } ++int ath12k_peer_rhash_delete(struct ath12k_base *ab, struct ath12k_peer *peer) ++{ ++ int ret; ++ ++ lockdep_assert_held(&ab->base_lock); ++ lockdep_assert_held(&ab->tbl_mtx_lock); ++ ++ if (!ab->rhead_peer_id || !ab->rhead_peer_addr) ++ return -EPERM; ++ ++ if (!peer->rhash_done) ++ return 0; ++ ++ ret = ath12k_peer_rhash_remove(ab, ab->rhead_peer_addr, &peer->rhash_addr, ++ &ab->rhash_peer_addr_param); ++ if (ret) { ++ ath12k_warn(ab, "failed to remove peer %pM id %d in rhash_addr ret %d\n", ++ peer->addr, peer->peer_id, ret); ++ return ret; ++ } ++ ++ ret = ath12k_peer_rhash_remove(ab, ab->rhead_peer_id, &peer->rhash_id, ++ &ab->rhash_peer_id_param); ++ if (ret) { ++ ath12k_warn(ab, "failed to remove peer %pM id %d in rhash_id ret %d\n", ++ peer->addr, peer->peer_id, ret); ++ return ret; ++ } ++ ++ peer->rhash_done=false; ++ ++ return 0; ++} ++ ++static int ath12k_peer_rhash_id_tbl_init(struct ath12k_base *ab) ++{ ++ struct rhashtable_params *param; ++ struct rhashtable *rhash_id_tbl; ++ int ret; ++ size_t size; ++ ++ lockdep_assert_held(&ab->tbl_mtx_lock); ++ ++ if (ab->rhead_peer_id) ++ return 0; ++ ++ size = sizeof(*ab->rhead_peer_id); ++ rhash_id_tbl = kzalloc(size, GFP_KERNEL); ++ if (!rhash_id_tbl) { ++ ath12k_warn(ab, "failed to init rhash id table due to no mem (size %zu)\n", ++ size); ++ return -ENOMEM; ++ } ++ ++ param = &ab->rhash_peer_id_param; ++ ++ param->key_offset = offsetof(struct ath12k_peer, peer_id); ++ param->head_offset = offsetof(struct ath12k_peer, rhash_id); ++ param->key_len = sizeof_field(struct ath12k_peer, peer_id); ++ param->automatic_shrinking = true; ++ param->nelem_hint = ab->num_radios * TARGET_NUM_PEERS_PDEV; ++ ++ ret = rhashtable_init(rhash_id_tbl, param); ++ if (ret) { ++ ath12k_warn(ab, "failed to init peer id rhash table %d\n", ret); ++ goto err_free; ++ } ++ ++ spin_lock_bh(&ab->base_lock); ++ ++ if (!ab->rhead_peer_id) { ++ ab->rhead_peer_id = rhash_id_tbl; ++ } else { ++ spin_unlock_bh(&ab->base_lock); ++ goto cleanup_tbl; ++ } ++ ++ spin_unlock_bh(&ab->base_lock); ++ ++ return 0; ++ ++cleanup_tbl: ++ rhashtable_destroy(rhash_id_tbl); ++err_free: ++ kfree(rhash_id_tbl); ++ ++ return ret; ++} ++ ++static int ath12k_peer_rhash_addr_tbl_init(struct ath12k_base *ab) ++{ ++ struct rhashtable_params *param; ++ struct rhashtable *rhash_addr_tbl; ++ int ret; ++ size_t size; ++ ++ lockdep_assert_held(&ab->tbl_mtx_lock); ++ ++ if (ab->rhead_peer_addr) ++ return 0; ++ ++ size = sizeof(*ab->rhead_peer_addr); ++ rhash_addr_tbl = kzalloc(size, GFP_KERNEL); ++ if (!rhash_addr_tbl) { ++ ath12k_warn(ab, "failed to init rhash addr table due to no mem (size %zu)\n", ++ size); ++ return -ENOMEM; ++ } ++ param = &ab->rhash_peer_addr_param; ++ ++ param->key_offset = offsetof(struct ath12k_peer, addr); ++ param->head_offset = offsetof(struct ath12k_peer, rhash_addr); ++ param->key_len = sizeof_field(struct ath12k_peer, addr); ++ param->automatic_shrinking = true; ++ param->nelem_hint = ab->num_radios * TARGET_NUM_PEERS_PDEV; ++ ++ ret = rhashtable_init(rhash_addr_tbl, param); ++ if (ret) { ++ ath12k_warn(ab, "failed to init peer addr rhash table %d\n", ret); ++ goto err_free; ++ } ++ ++ spin_lock_bh(&ab->base_lock); ++ ++ if (!ab->rhead_peer_addr) { ++ ab->rhead_peer_addr = rhash_addr_tbl; ++ } else { ++ spin_unlock_bh(&ab->base_lock); ++ goto cleanup_tbl; ++ } ++ ++ spin_unlock_bh(&ab->base_lock); ++ ++ return 0; ++ ++cleanup_tbl: ++ rhashtable_destroy(rhash_addr_tbl); ++err_free: ++ kfree(rhash_addr_tbl); ++ ++ return ret; ++} ++ ++static inline void ath12k_peer_rhash_id_tbl_destroy(struct ath12k_base *ab) ++{ ++ lockdep_assert_held(&ab->tbl_mtx_lock); ++ ++ if (!ab->rhead_peer_id) ++ return; ++ ++ rhashtable_destroy(ab->rhead_peer_id); ++ kfree(ab->rhead_peer_id); ++ ab->rhead_peer_id = NULL; ++} ++ ++static inline void ath12k_peer_rhash_addr_tbl_destroy(struct ath12k_base *ab) ++{ ++ lockdep_assert_held(&ab->tbl_mtx_lock); ++ ++ if (!ab->rhead_peer_addr) ++ return; ++ ++ rhashtable_destroy(ab->rhead_peer_addr); ++ kfree(ab->rhead_peer_addr); ++ ab->rhead_peer_addr = NULL; ++} ++ ++int ath12k_peer_rhash_tbl_init(struct ath12k_base *ab) ++{ ++ int ret; ++ ++ mutex_lock(&ab->tbl_mtx_lock); ++ ++ ret = ath12k_peer_rhash_id_tbl_init(ab); ++ if (ret) ++ goto out; ++ ++ ret = ath12k_peer_rhash_addr_tbl_init(ab); ++ if (ret) ++ goto cleanup_tbl; ++ ++ mutex_unlock(&ab->tbl_mtx_lock); ++ ++ return 0; ++ ++cleanup_tbl: ++ ath12k_peer_rhash_id_tbl_destroy(ab); ++out: ++ mutex_unlock(&ab->tbl_mtx_lock); ++ return ret; ++} ++void ath12k_peer_rhash_tbl_destroy(struct ath12k_base *ab) ++{ ++ mutex_lock(&ab->tbl_mtx_lock); ++ ++ ath12k_peer_rhash_addr_tbl_destroy(ab); ++ ath12k_peer_rhash_id_tbl_destroy(ab); ++ ++ mutex_unlock(&ab->tbl_mtx_lock); ++} ++ +--- a/drivers/net/wireless/ath/ath12k/peer.h ++++ b/drivers/net/wireless/ath/ath12k/peer.h +@@ -45,6 +45,11 @@ struct ath12k_peer { + */ + struct ath12k_dp_rx_tid rx_tid[IEEE80211_NUM_TIDS + 1]; + ++ /* peer id based rhashtable list pointer */ ++ struct rhash_head rhash_id; ++ /* peer addr based rhashtable list pointer */ ++ struct rhash_head rhash_addr; ++ + /* Info used in MMIC verification of + * RX fragments + */ +@@ -71,6 +76,9 @@ struct ath12k_peer { + /* To ensure only certain work related to dp is done once */ + bool primary_link; + ++ /* To check if the peer entry is part of rhash table or not */ ++ bool rhash_done; ++ + /* any other ML info common for all partners can be added + * here and would be same for all partner peers + */ +@@ -88,6 +96,8 @@ void ath12k_peer_map_event(struct ath12k + u8 *mac_addr, u16 ast_hash, u16 hw_peer_id); + struct ath12k_peer *ath12k_peer_find(struct ath12k_base *ab, int vdev_id, + const u8 *addr); ++struct ath12k_peer *ath12k_peer_find_list_by_id(struct ath12k_base *ab, ++ int peer_id); + struct ath12k_peer *ath12k_peer_find_by_addr(struct ath12k_base *ab, + const u8 *addr); + struct ath12k_peer *ath12k_peer_find_by_id(struct ath12k_base *ab, int peer_id); +@@ -102,6 +112,9 @@ int ath12k_wait_for_peer_delete_done(str + const u8 *addr); + struct ath12k_peer *ath12k_peer_find_by_vdev_id(struct ath12k_base *ab, + int vdev_id); ++int ath12k_peer_rhash_tbl_init(struct ath12k_base *ab); ++void ath12k_peer_rhash_tbl_destroy(struct ath12k_base *ab); ++int ath12k_peer_rhash_delete(struct ath12k_base *ab, struct ath12k_peer *peer); + void ath12k_peer_mlo_map_event(struct ath12k_base *ab, struct sk_buff *skb); + void ath12k_peer_mlo_unmap_event(struct ath12k_base *ab, struct sk_buff *skb); + diff --git a/feeds/ipq95xx/mac80211/patches/qca/783-ath12k-Add-support-to-bring-in-debug-levels.patch b/feeds/ipq95xx/mac80211/patches/qca/783-ath12k-Add-support-to-bring-in-debug-levels.patch new file mode 100644 index 000000000..40ebe4d6d --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/783-ath12k-Add-support-to-bring-in-debug-levels.patch @@ -0,0 +1,203 @@ +From 5e89d784fb35bc3f2cda4831fbe87163781c0ed8 Mon Sep 17 00:00:00 2001 +From: Gunaal R +Date: Wed, 17 May 2023 15:21:01 +0530 +Subject: [PATCH] ath12k: Add support to bring in debug levels + +Currently there is no debug level logging mechanism present in the +driver, so when enabling debug mask all the debug logs are displayed. +Add support to bring in debug levels for every debug mask, which +only gives the log of specific level which requires and add +debug mask to view the log of mac delete id, type, subtype, map. + +Working Mechanism: + +By comparing the leftmost bit with the debug level(level0 = 0, +level1 = 1, level2 = 2), the logs of corresponding level are +shown, which enables specific logs to be shown while avoiding an +overflow of unwanted logs. + +Signed-off-by: Gunaal R +--- + drivers/net/wireless/ath/ath12k/debug.c | 51 ++++++---- + drivers/net/wireless/ath/ath12k/debug.h | 126 +++++++++++++++++++++++- + drivers/net/wireless/ath/ath12k/mac.c | 11 ++- + drivers/net/wireless/ath/ath12k/wmi.c | 16 +-- + 4 files changed, 171 insertions(+), 33 deletions(-) + +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/debug.c +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/debug.c ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/debug.c +@@ -62,26 +62,33 @@ void ath12k_warn(struct ath12k_base *ab, + #ifdef CPTCFG_ATH12K_DEBUG + + void __ath12k_dbg(struct ath12k_base *ab, enum ath12k_debug_mask mask, +- const char *fmt, ...) ++ const char *fmt, ...) + { +- struct va_format vaf; +- va_list args; +- +- va_start(args, fmt); +- +- vaf.fmt = fmt; +- vaf.va = &args; +- +- if (ath12k_debug_mask & mask) { +- if (ab) +- dev_dbg(ab->dev, "%pV", &vaf); +- else +- pr_devel("ath12k: %pV", &vaf); ++#define LEVEL_MASK GENMASK(31,28) ++#define debug_mask GENMASK(27,0) ++ u32 local_mask_level = mask & LEVEL_MASK; ++ u32 global_mask_level = ath12k_debug_mask & LEVEL_MASK; ++ struct va_format vaf; ++ va_list args; ++ ++ va_start(args, fmt); ++ ++ vaf.fmt = fmt; ++ vaf.va = &args; ++ ++ if ((mask & debug_mask) & ath12k_debug_mask) { ++ if (((local_mask_level) && (global_mask_level >= local_mask_level)) || ++ (!global_mask_level && (local_mask_level == ATH12K_DBG_L0))) { ++ if (ab) ++ dev_dbg(ab->dev, "%pV", &vaf); ++ else ++ pr_devel("ath12k: %pV", &vaf); ++ } + } + +- /* TODO: trace log */ ++ /* TODO: trace log */ + +- va_end(args); ++ va_end(args); + } + + void ath12k_dbg_dump(struct ath12k_base *ab, +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/debug.h +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/debug.h ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/debug.h +@@ -31,11 +31,18 @@ enum ath12k_debug_mask { + ATH12K_DBG_PEER = 0x00020000, + + /* keep last*/ +- ATH12K_DBG_SAWF = 0x40000000, +- ATH12K_DBG_PPE = 0x80000000, ++ ATH12K_DBG_SAWF = 0x00040000, ++ ATH12K_DBG_PPE = 0x00080000, + ATH12K_DBG_ANY = 0xffffffff, + }; + ++enum ath12k_debug_mask_level { ++ ATH12K_DBG_L0 = 0x00000000, ++ ATH12K_DBG_L1 = 0x10000000, ++ ATH12K_DBG_L2 = 0x20000000, ++ ATH12K_DBG_L3 = 0x30000000, ++}; ++ + __printf(2, 3) void ath12k_info(struct ath12k_base *ab, const char *fmt, ...); + __printf(2, 3) void ath12k_err(struct ath12k_base *ab, const char *fmt, ...); + __printf(2, 3) void ath12k_warn(struct ath12k_base *ab, const char *fmt, ...); +@@ -76,6 +83,8 @@ static inline void ath12k_err_dump(struc + } + #endif /* CPTCFG_ATH12K_DEBUG */ + ++#define ATH12K_DBG_SET(mask, level) ATH12K_DBG_##mask | ATH12K_DBG_##level ++ + #define ath12k_dbg(ar, dbg_mask, fmt, ...) \ + do { \ + typeof(dbg_mask) mask = (dbg_mask); \ +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/mac.c +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/mac.c ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/mac.c +@@ -4776,6 +4776,7 @@ static void ath12k_mac_op_bss_info_chang + + static int ath12k_mac_vdev_delete(struct ath12k *ar, struct ath12k_link_vif *arvif) + { ++ struct ath12k_vif *ahvif = arvif->ahvif; + unsigned long time_left; + int ret = 0; + +@@ -4814,6 +4815,9 @@ static int ath12k_mac_vdev_delete(struct + arvif->ahvif->num_vdev_created--; + arvif->is_created = false; + ++ ath12k_dbg(ar->ab, ATH12K_DBG_SET(MAC, L1), "mac vdev delete id %d type %d subtype %d map %llx\n", ++ arvif->vdev_id, ahvif->vdev_type, ahvif->vdev_subtype, ++ ar->ab->free_vdev_map); + clean_up: + #ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT + if (arvif->link_id != ATH12K_DEFAULT_SCAN_LINK && arvif->ndev_pvt) +@@ -10133,7 +10137,7 @@ static int ath12k_mac_vdev_create(struct + break; + } + +- ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev create id %d type %d subtype %d map %llx\n", ++ ath12k_dbg(ar->ab, ATH12K_DBG_SET(MAC, L1), "mac vdev create id %d type %d subtype %d map %llx\n", + arvif->vdev_id, ahvif->vdev_type, ahvif->vdev_subtype, + ab->free_vdev_map); + +@@ -12830,7 +12834,7 @@ ath12k_mac_op_unassign_vif_chanctx(struc + if (unlikely(test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))) + goto out; + +- ath12k_dbg(ab, ATH12K_DBG_MAC, ++ ath12k_dbg(ab, ATH12K_DBG_SET(MAC, L2), + "mac chanctx unassign ptr %pK vdev_id %i\n", + ctx, arvif->vdev_id); + +@@ -13027,7 +13031,7 @@ static void ath12k_mac_flush(struct ath1 + return; + } + +- ath12k_dbg(ab, ATH12K_DBG_MAC, ++ ath12k_dbg(ab, ATH12K_DBG_SET(MAC, L3), + "mac tx flush pending mgmt %d data %d\n", + atomic_read(&ar->num_pending_mgmt_tx), + atomic_read(&ar->dp.num_tx_pending)); +Index: backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/wmi.c +=================================================================== +--- backports-20220822-5.4.213-ef7197996efe.orig/drivers/net/wireless/ath/ath12k/wmi.c ++++ backports-20220822-5.4.213-ef7197996efe/drivers/net/wireless/ath/ath12k/wmi.c +@@ -1100,7 +1100,7 @@ int ath12k_wmi_vdev_stop(struct ath12k * + dev_kfree_skb(skb); + } + +- ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "WMI vdev stop id 0x%x\n", vdev_id); ++ ath12k_dbg(ar->ab, ATH12K_DBG_SET(WMI, L1), "WMI vdev stop id 0x%x\n", vdev_id); + + return ret; + } +@@ -1129,7 +1129,7 @@ int ath12k_wmi_vdev_down(struct ath12k * + dev_kfree_skb(skb); + } + +- ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "WMI vdev down id 0x%x\n", vdev_id); ++ ath12k_dbg(ar->ab, ATH12K_DBG_SET(WMI, L1), "WMI vdev down id 0x%x\n", vdev_id); + + return ret; + } +@@ -1746,7 +1746,7 @@ int ath12k_wmi_pdev_set_param(struct ath + dev_kfree_skb(skb); + } + +- ath12k_dbg(ar->ab, ATH12K_DBG_WMI, ++ ath12k_dbg(ar->ab, ATH12K_DBG_SET(WMI, L2), + "WMI pdev set param %d pdev id %d value %d\n", + param_id, pdev_id, param_value); + +@@ -3441,7 +3441,7 @@ int ath12k_wmi_send_wmm_update_cmd_tlv(s + wmm_param->acm = wmi_wmm_arg->acm; + wmm_param->no_ack = wmi_wmm_arg->no_ack; + +- ath12k_dbg(ar->ab, ATH12K_DBG_WMI, ++ ath12k_dbg(ar->ab, ATH12K_DBG_SET(WMI, L3), + "wmi wmm set ac %d aifs %d cwmin %d cwmax %d txop %d acm %d no_ack %d\n", + ac, wmm_param->aifs, wmm_param->cwmin, + wmm_param->cwmax, wmm_param->txoplimit, diff --git a/feeds/ipq95xx/mac80211/patches/qca/784-01-ath12k-Add-debugfs-support-to-enable-and-disable.patch b/feeds/ipq95xx/mac80211/patches/qca/784-01-ath12k-Add-debugfs-support-to-enable-and-disable.patch new file mode 100644 index 000000000..03dd8aa2f --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/784-01-ath12k-Add-debugfs-support-to-enable-and-disable.patch @@ -0,0 +1,169 @@ +From 18bcd286cb1f6f6296e13281803541eb385960cc Mon Sep 17 00:00:00 2001 +From: Nagarajan Maran +Date: Tue, 6 Jun 2023 06:55:56 +0530 +Subject: [PATCH] ath12k: Add debugfs support to enable and disable sawf stats + +Add support to enable sawf stats from debugfs + Enable Basic stats: + echo 1 > /sys/kernel/debug/ath12k//mac0/sawf_stats + Enable Advanced stats: + echo 2 > /sys/kernel/debug/ath12k//mac0/sawf_stats + Enable Latency stats: + echo 4 > /sys/kernel/debug/ath12k//mac0/sawf_stats + +Signed-off-by: Nagarajan Maran +--- + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/debugfs.c | 64 +++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/debugfs.h | 10 ++++ + drivers/net/wireless/ath/ath12k/sawf.h | 12 +++++ + 4 files changed, 87 insertions(+) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -748,6 +748,9 @@ struct ath12k_debug { + struct ath12k_dbg_htt_stats htt_stats; + u32 extd_tx_stats; + u32 extd_rx_stats; ++#ifdef CPTCFG_ATH12K_SAWF ++ u32 sawf_stats; ++#endif + u32 pktlog_filter; + u32 pktlog_mode; + u32 pktlog_peer_valid; +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -4107,6 +4107,73 @@ static const struct file_operations fops + .llseek = default_llseek, + }; + ++#ifdef CPTCFG_ATH12K_SAWF ++static ssize_t ath12k_write_sawf_stats(struct file *file, ++ const char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ u32 sawf_stats; ++ int ret; ++ ++ if (kstrtouint_from_user(ubuf, count, 0, &sawf_stats)) ++ return -EINVAL; ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ if (ar->state != ATH12K_STATE_ON) { ++ ath12k_err(ar->ab, "Netdev is down\n"); ++ ret = -ENETDOWN; ++ goto out; ++ } ++ ++ if (!ath12k_sawf_enable) ++ { ++ ath12k_err(ar->ab, "SAWF support is not enabled\n"); ++ ret = -EOPNOTSUPP; ++ goto out; ++ } ++ ++ if (sawf_stats > ATH12K_SAWF_STATS_MAX) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ ret = count; ++ ++ if (sawf_stats == ar->debug.sawf_stats) ++ goto out; ++ ++ ar->debug.sawf_stats = sawf_stats; ++ ++out: ++ mutex_unlock(&ar->conf_mutex); ++ return ret; ++} ++ ++static ssize_t ath12k_read_sawf_stats(struct file *file, ++ char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k *ar = file->private_data; ++ int len = 0; ++ char buf[32] = {0}; ++ ++ mutex_lock(&ar->conf_mutex); ++ len = scnprintf(buf, sizeof(buf) - len, "%08x\n", ++ ar->debug.sawf_stats); ++ mutex_unlock(&ar->conf_mutex); ++ ++ return simple_read_from_buffer(ubuf, count, ppos, buf, len); ++} ++ ++static const struct file_operations fops_sawf_stats = { ++ .read = ath12k_read_sawf_stats, ++ .write = ath12k_write_sawf_stats, ++ .open = simple_open ++}; ++#endif /* CPTCFG_ATH12K_SAWF */ ++ + int ath12k_debugfs_register(struct ath12k *ar) + { + struct ath12k_base *ab = ar->ab; +@@ -4205,7 +4272,11 @@ int ath12k_debugfs_register(struct ath12 + debugfs_create_file("btcoex_priority", 0600, + ar->debug.debugfs_pdev, ar, + &fops_btcoex_priority); +- ++#ifdef CPTCFG_ATH12K_SAWF ++ debugfs_create_file("sawf_stats", 0644, ++ ar->debug.debugfs_pdev, ar, ++ &fops_sawf_stats); ++#endif + return 0; + } + +--- a/drivers/net/wireless/ath/ath12k/debugfs.h ++++ b/drivers/net/wireless/ath/ath12k/debugfs.h +@@ -405,6 +405,21 @@ static inline void ath12k_debugfs_nrp_cl + } + #endif /* CPTCFG_MAC80211_DEBUGFS*/ + ++#ifdef CPTCFG_ATH12K_SAWF ++static inline unsigned int ath12k_debugfs_is_sawf_stats_enabled(struct ath12k *ar) ++{ ++ return ar->debug.sawf_stats; ++} ++ ++#else ++ ++static inline unsigned int ath12k_debugfs_is_sawf_stats_enabled(struct ath12k *ar) ++{ ++ return 0; ++} ++ ++#endif ++ + #ifdef CPTCFG_ATH12K_PKTLOG + void ath12k_init_pktlog(struct ath12k *ar); + void ath12k_deinit_pktlog(struct ath12k *ar); +--- a/drivers/net/wireless/ath/ath12k/sawf.h ++++ b/drivers/net/wireless/ath/ath12k/sawf.h +@@ -463,6 +463,20 @@ struct wmi_tid_latency_info { + __le32 latency_tid_info; + } __packed; + ++/** ++ * ath12k_sawf_stats_level - sawf stats level ++ * @ATH12K_SAWF_STATS_BASIC : sawf basic stats ++ * @ATH12K_SAWF_STATS_ADVANCED : sawf advanced stats ++ * @ATH12K_SAWF_STATS_LATENCY : sawf latency stats ++ */ ++enum ath12k_sawf_stats_level { ++ ATH12K_SAWF_STATS_BASIC = BIT(0), ++ ATH12K_SAWF_STATS_ADVNCD = BIT(1), ++ ATH12K_SAWF_STATS_LATENCY = BIT(2), ++}; ++ ++#define ATH12K_SAWF_STATS_MAX (ATH12K_SAWF_STATS_BASIC | ATH12K_SAWF_STATS_ADVNCD | ATH12K_SAWF_STATS_LATENCY) ++ + extern bool ath12k_sawf_enable; + struct ath12k_sawf_ctx *ath12k_get_sawf_context(void); + void ath12k_sawf_init(struct ath12k_base *ab); diff --git a/feeds/ipq95xx/mac80211/patches/qca/784-01-wifi-ath12k-fix-array-out-of-bound-in-undecap-native.patch b/feeds/ipq95xx/mac80211/patches/qca/784-01-wifi-ath12k-fix-array-out-of-bound-in-undecap-native.patch new file mode 100644 index 000000000..6d096547f --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/784-01-wifi-ath12k-fix-array-out-of-bound-in-undecap-native.patch @@ -0,0 +1,113 @@ +From b5d7239d873fa775420d6f36c9703999a95c032c Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Wed, 21 Jun 2023 14:55:11 +0530 +Subject: [PATCH 1/2] wifi: ath12k: fix array out of bound in undecap native + wifi frame path + +Randomly in undecap native wifi path, msdu header frame control has QoS data. +which is wrong because QoS not present in native wifi frame. so when we take +a copy of native wifi header, the destination array get out of bound access +due to the addition of unexpected QoS length from source. Fix this issue by +reset the QoS length, Order length and recalculate the header length then +proceed the undecap procedure without the local array and remove the unused +define. + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/dp_rx.c | 33 ++++++++++++++----------- + drivers/net/wireless/ath/ath12k/dp_rx.h | 3 --- + 2 files changed, 18 insertions(+), 18 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -2407,23 +2407,27 @@ static void ath12k_dp_rx_h_undecap_nwifi + { + struct ath12k_base *ab = ar->ab; + struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu); +- u8 decap_hdr[DP_MAX_NWIFI_HDR_LEN]; +- struct ieee80211_hdr *hdr; ++ struct ieee80211_hdr hdr; + size_t hdr_len; + int expand_by = 0; + u8 *crypto_hdr; +- u16 qos_ctl = 0; ++ u16 qos_ctl; + + /* pull decapped header */ +- hdr = (struct ieee80211_hdr *)msdu->data; +- hdr_len = ieee80211_hdrlen(hdr->frame_control); ++ hdr = *((struct ieee80211_hdr *)msdu->data); ++ hdr_len = ieee80211_hdrlen(hdr.frame_control); + skb_pull(msdu, hdr_len); + +- /* Rebuild qos header */ +- hdr->frame_control |= __cpu_to_le16(IEEE80211_STYPE_QOS_DATA); ++ /* FIXME Nwifi header should not exceed struct ieee80211_hdr size (30) */ ++ WARN_ON_ONCE(hdr_len > sizeof(hdr)); + +- /* Reset the order bit as the HT_Control header is stripped */ +- hdr->frame_control &= ~(__cpu_to_le16(IEEE80211_FCTL_ORDER)); ++ /* ++ * Reset the QoS bit since it is nwifi frame ++ * Reset the order bit as the HT_Control header is stripped ++ */ ++ hdr.frame_control &= ~(__cpu_to_le16(IEEE80211_STYPE_QOS_DATA) | ++ __cpu_to_le16(IEEE80211_FCTL_ORDER)); ++ hdr_len = ieee80211_hdrlen(hdr.frame_control); + + qos_ctl = rxcb->tid; + +@@ -2432,9 +2436,6 @@ static void ath12k_dp_rx_h_undecap_nwifi + + /* TODO Add other QoS ctl fields when required */ + +- /* copy decap header before overwriting for reuse below */ +- memcpy(decap_hdr, (uint8_t *)hdr, hdr_len); +- + /* Rebuild crypto header for mac80211 use */ + if (!(status->flag & RX_FLAG_IV_STRIPPED)) { + if (skb_headroom(msdu) < ath12k_dp_rx_crypto_param_len(ar, enctype)) { +@@ -2453,16 +2454,21 @@ static void ath12k_dp_rx_h_undecap_nwifi + if (WARN_ON_ONCE(pskb_expand_head(msdu, expand_by, 0, GFP_ATOMIC))) + return; + } ++ ++ /* Rebuild qos header */ + memcpy(skb_push(msdu, + IEEE80211_QOS_CTL_LEN), &qos_ctl, + IEEE80211_QOS_CTL_LEN); ++ hdr.frame_control |= __cpu_to_le16(IEEE80211_STYPE_QOS_DATA); ++ + + if (skb_headroom(msdu) < hdr_len) { + expand_by = hdr_len - skb_headroom(msdu); + if (WARN_ON_ONCE(pskb_expand_head(msdu, expand_by, 0, GFP_ATOMIC))) + return; + } +- memcpy(skb_push(msdu, hdr_len), decap_hdr, hdr_len); ++ ++ memcpy(skb_push(msdu, hdr_len), &hdr, hdr_len); + } + + static void ath12k_dp_rx_h_undecap_raw(struct ath12k *ar, struct sk_buff *msdu, +@@ -3164,7 +3170,7 @@ static bool ath12k_dp_rx_check_max_nwifi + + hdr = (struct ieee80211_hdr *)msdu->data; + hdr_len = ieee80211_hdrlen(hdr->frame_control); +- if (unlikely(hdr_len > DP_MAX_NWIFI_HDR_LEN)) { ++ if (unlikely(hdr_len > sizeof(*hdr))) { + ab->soc_stats.invalid_rbm++; + ath12k_dbg_dump(ab, ATH12K_DBG_DATA, NULL, "msdu_data", + msdu->data, msdu->len); +--- a/drivers/net/wireless/ath/ath12k/dp_rx.h ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.h +@@ -10,9 +10,6 @@ + #include "rx_desc.h" + #include "debug.h" + +-#define DP_MAX_NWIFI_HDR_LEN 30 +- +- + /* different supported pkt types for routing */ + enum ath12k_routing_pkt_type { + ATH12K_PKT_TYPE_ARP_IPV4, diff --git a/feeds/ipq95xx/mac80211/patches/qca/784-02-wifi-ath12k-Add-nwifi-header-length-check-in-tkip-pa.patch b/feeds/ipq95xx/mac80211/patches/qca/784-02-wifi-ath12k-Add-nwifi-header-length-check-in-tkip-pa.patch new file mode 100644 index 000000000..42651695b --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/784-02-wifi-ath12k-Add-nwifi-header-length-check-in-tkip-pa.patch @@ -0,0 +1,120 @@ +From ff9277b5439dfaad25138019973980994660aa8e Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Thu, 22 Jun 2023 13:05:12 +0530 +Subject: [PATCH 2/2] wifi: ath12k: Add nwifi header length check in tkip path + +Readded the missed fix on the nwifi header length check on tkip +path. Due to this it ended in array out bound issue. + +Fixes: If632f16261ef5d79 ("ath12k: Add warning to detect buffer overflow") + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/dp_rx.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -3162,8 +3162,9 @@ exit: + } + + static bool ath12k_dp_rx_check_max_nwifi_hdr_len(struct ath12k_base *ab, +- struct hal_rx_desc *rx_desc, +- struct sk_buff *msdu) ++ struct hal_rx_desc *rx_desc, ++ struct sk_buff *msdu, ++ const char *msg) + { + struct ieee80211_hdr *hdr; + u32 hdr_len; +@@ -3172,10 +3173,10 @@ static bool ath12k_dp_rx_check_max_nwifi + hdr_len = ieee80211_hdrlen(hdr->frame_control); + if (unlikely(hdr_len > sizeof(*hdr))) { + ab->soc_stats.invalid_rbm++; +- ath12k_dbg_dump(ab, ATH12K_DBG_DATA, NULL, "msdu_data", +- msdu->data, msdu->len); +- ath12k_dbg_dump(ab, ATH12K_DBG_DATA, NULL, "rx_desc", +- rx_desc, sizeof(*rx_desc)); ++ ath12k_err_dump(ab, msg, "msdu_data: ", msdu->data, msdu->len, ++ NULL); ++ ath12k_err_dump(ab, NULL, "rx_desc: ", rx_desc, sizeof(*rx_desc), ++ NULL); + return true; + } + +@@ -3246,7 +3247,9 @@ static int ath12k_dp_rx_process_msdu(str + ath12k_dp_rx_h_fetch_info(ab, rx_desc, rx_info); + + if (rx_info->decap_type == DP_RX_DECAP_TYPE_NATIVE_WIFI && +- ath12k_dp_rx_check_max_nwifi_hdr_len(ab, rx_desc, msdu)) { ++ ath12k_dp_rx_check_max_nwifi_hdr_len(ab, rx_desc, msdu, ++ "Invalid len in Rx\n")) { ++ WARN_ON_ONCE(1); + ret = -EINVAL; + goto free_out; + } +@@ -3693,6 +3696,13 @@ mic_fail: + RX_FLAG_IV_STRIPPED | RX_FLAG_DECRYPTED; + skb_pull(msdu, hal_rx_desc_sz); + ++ if (rx_info.decap_type == DP_RX_DECAP_TYPE_NATIVE_WIFI && ++ ath12k_dp_rx_check_max_nwifi_hdr_len(ab, rx_desc, msdu, ++ "Invalid len in verify tkip\n")) { ++ WARN_ON_ONCE(1); ++ return -EINVAL; ++ } ++ + ath12k_dp_rx_h_ppdu(ar, &rx_info); + ath12k_dp_rx_h_undecap(ar, msdu, rx_desc, + HAL_ENCRYPT_TYPE_TKIP_MIC, rxs, true); +@@ -4416,8 +4426,11 @@ static int ath12k_dp_rx_h_null_q_desc(st + ath12k_dp_rx_h_fetch_info(ab, desc, rx_info); + + if (rx_info->decap_type == DP_RX_DECAP_TYPE_NATIVE_WIFI && +- ath12k_dp_rx_check_max_nwifi_hdr_len(ab, desc, msdu)) ++ ath12k_dp_rx_check_max_nwifi_hdr_len(ab, desc, msdu, ++ "Invalid len in Null queue\n")) { ++ WARN_ON_ONCE(1); + return -EINVAL; ++ } + + ath12k_dp_rx_h_ppdu(ar, rx_info); + fast_rx = false; +@@ -4504,6 +4517,13 @@ static bool ath12k_dp_rx_h_tkip_mic_err( + skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len); + skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes); + ++ if (rx_info->decap_type == DP_RX_DECAP_TYPE_NATIVE_WIFI && ++ ath12k_dp_rx_check_max_nwifi_hdr_len(ab, desc, msdu, ++ "Invalid len in tkip mic err\n")) { ++ WARN_ON_ONCE(1); ++ return true; ++ } ++ + ath12k_dp_rx_h_ppdu(ar, rx_info); + + rx_info->rx_status->flag |= (RX_FLAG_MMIC_STRIPPED | RX_FLAG_MMIC_ERROR | +@@ -4547,8 +4567,11 @@ static bool ath12k_dp_rx_h_4addr_null_fr + skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes); + + if (rx_info->decap_type == DP_RX_DECAP_TYPE_NATIVE_WIFI && +- ath12k_dp_rx_check_max_nwifi_hdr_len(ab, rx_desc, msdu)) ++ ath12k_dp_rx_check_max_nwifi_hdr_len(ab, rx_desc, msdu, ++ "Invalid len in 4addr Null frame\n")) { ++ WARN_ON_ONCE(1); + return true; ++ } + + ath12k_dp_rx_h_ppdu(ar, rx_info); + +--- a/drivers/net/wireless/ath/ath12k/debug.c ++++ b/drivers/net/wireless/ath/ath12k/debug.c +@@ -143,7 +143,7 @@ void ath12k_err_dump(struct ath12k_base + dev_err(ab->dev, "%s\n", linebuf); + } + +- if (srng->ring_dir == HAL_SRNG_DIR_DST) ++ if (srng && srng->ring_dir == HAL_SRNG_DIR_DST) + dev_err(ab->dev, "ring_base_vaddr=%px tp=0x%X size=0x%X cached_hp=0x%X", + srng->ring_base_vaddr, + srng->u.dst_ring.tp, diff --git a/feeds/ipq95xx/mac80211/patches/qca/784-02-wifi-ath12k-Add-sawf-tx-stats-support.patch b/feeds/ipq95xx/mac80211/patches/qca/784-02-wifi-ath12k-Add-sawf-tx-stats-support.patch new file mode 100644 index 000000000..2e064ce18 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/784-02-wifi-ath12k-Add-sawf-tx-stats-support.patch @@ -0,0 +1,473 @@ +From f04a2abadb25d5444650d9b58af8ad758675f705 Mon Sep 17 00:00:00 2001 +From: Nagarajan Maran +Date: Tue, 6 Jun 2023 07:21:17 +0530 +Subject: [PATCH] wifi: ath12k: Add sawf tx stats support + +Add support to calculate the SAWF TX stats for SAWF packets. + +Signed-off-by: Nagarajan Maran +--- + drivers/net/wireless/ath/ath12k/dp_tx.c | 35 +++++++- + drivers/net/wireless/ath/ath12k/peer.h | 1 + + drivers/net/wireless/ath/ath12k/sawf.c | 112 ++++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/sawf.h | 74 ++++++++++++++++ + 4 files changed, 219 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -277,6 +277,9 @@ int ath12k_dp_tx_direct(struct ath12k_li + struct hal_tcl_data_cmd tcl_desc; + u8 hal_ring_id, ring_id; + dma_addr_t paddr; ++#ifdef CPTCFG_ATH12K_SAWF ++ struct ath12k_peer *peer; ++#endif + int ret; + int len = skb->fast_xmit ? 256 : skb->len; + +@@ -345,7 +348,7 @@ int ath12k_dp_tx_direct(struct ath12k_li + #ifdef CPTCFG_ATH12K_SAWF + /* SAWF */ + if (u32_get_bits(skb->mark, SAWF_TAG_ID) == SAWF_VALID_TAG) { +- u32 msduq_id = u32_get_bits(skb->mark, SAWF_MSDUQ_ID); ++ u32 msduq_id = u32_get_bits(skb->mark, SAWF_MSDUQ_ID); + + if (msduq_id < (ab->max_msduq_per_tid * ATH12K_SAWF_MAX_TID_SUPPORT)) { + u32 meta_data_flags; +@@ -355,6 +358,19 @@ int ath12k_dp_tx_direct(struct ath12k_li + tcl_desc.info1 = u32_encode_bits(meta_data_flags, + HAL_TCL_DATA_CMD_INFO1_CMD_NUM); + } ++ ++ if (unlikely(ath12k_debugfs_is_sawf_stats_enabled(ar) & ATH12K_SAWF_STATS_BASIC)) { ++ u16 peer_id = u32_get_bits(skb->mark, SAWF_PEER_ID); ++ u32 len = skb_headlen(skb); ++ spin_lock_bh(&ab->base_lock); ++ peer = ath12k_peer_find_by_id(ab, peer_id); ++ if (unlikely(!peer || !peer->sta)) ++ ath12k_dbg(ab, ATH12K_DBG_SAWF, ++ "peer_id %u not found \n", peer_id); ++ else ++ ath12k_sawf_tx_enqueue_peer_stats(ab, peer, msduq_id, len); ++ spin_unlock_bh(&ab->base_lock); ++ } + } + #endif + memcpy(hal_tcl_desc, &tcl_desc, sizeof(tcl_desc)); +@@ -450,7 +466,7 @@ int ath12k_dp_tx(struct ath12k *ar, stru + */ + #ifdef CPTCFG_ATH12K_SAWF + if (u32_get_bits(skb->mark, SAWF_TAG_ID) == SAWF_VALID_TAG) { +- u32 msduq_id = u32_get_bits(skb->mark, SAWF_MSDUQ_ID); ++ u32 msduq_id = u32_get_bits(skb->mark, SAWF_MSDUQ_ID); + if (msduq_id < (ab->max_msduq_per_tid * ATH12K_SAWF_MAX_TID_SUPPORT)) { + ti.meta_data_flags = + ath12k_sawf_get_tcl_metadata_update(skb->mark); +@@ -639,12 +655,23 @@ int ath12k_dp_tx(struct ath12k *ar, stru + #ifdef CPTCFG_ATH12K_SAWF + /* SAWF */ + if (u32_get_bits(skb->mark, SAWF_TAG_ID) == SAWF_VALID_TAG) { +- u32 msduq_id = u32_get_bits(skb->mark, SAWF_MSDUQ_ID); ++ u32 msduq_id = u32_get_bits(skb->mark, SAWF_MSDUQ_ID); + + if (msduq_id < (ab->max_msduq_per_tid * ATH12K_SAWF_MAX_TID_SUPPORT)) { + tcl_cmd->info3 |= + ath12k_sawf_get_tcl_cmd_info3_update(msduq_id); + } ++ if (unlikely(ath12k_debugfs_is_sawf_stats_enabled(ar) & ATH12K_SAWF_STATS_BASIC)) { ++ peer_id = u32_get_bits(skb->mark, SAWF_PEER_ID); ++ spin_lock_bh(&ab->base_lock); ++ peer = ath12k_peer_find_by_id(ab, peer_id); ++ if (unlikely(!peer || !peer->sta)) ++ ath12k_dbg(ab, ATH12K_DBG_SAWF, ++ "peer_id %u not found\n", peer_id); ++ else ++ ath12k_sawf_tx_enqueue_peer_stats(ab, peer, msduq_id, ti.data_len); ++ spin_unlock_bh(&ab->base_lock); ++ } + } + #endif /* CPTCFG_ATH12K_SAWF */ + +@@ -715,19 +742,52 @@ static void ath12k_dp_tx_free_txbuf(stru + ath12k_dp_tx_decrement(ab->pdevs[mac_id].ar); + } + ++static inline void ath12k_dp_tx_status_parse(struct ath12k_base *ab, ++ struct hal_wbm_completion_ring_tx *desc, ++ struct hal_tx_status *ts) ++{ ++ ts->buf_rel_source = ++ FIELD_GET(HAL_WBM_COMPL_TX_INFO0_REL_SRC_MODULE, desc->info0); ++ if (ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_FW && ++ ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM) ++ return; ++ ++ if (ts->buf_rel_source == HAL_WBM_REL_SRC_MODULE_FW) ++ return; ++ ++ ts->status = FIELD_GET(HAL_WBM_COMPL_TX_INFO0_TQM_RELEASE_REASON, ++ desc->info0); ++ ts->ppdu_id = FIELD_GET(HAL_WBM_COMPL_TX_INFO1_TQM_STATUS_NUMBER, ++ desc->info1); ++ ts->ack_rssi = FIELD_GET(HAL_WBM_COMPL_TX_INFO2_ACK_FRAME_RSSI, ++ desc->info2); ++ if (desc->rate_stats.info0 & HAL_TX_RATE_STATS_INFO0_VALID) ++ ts->rate_stats = desc->rate_stats.info0; ++ else ++ ts->rate_stats = 0; ++ ts->tid = FIELD_GET(HAL_WBM_RELEASE_TX_INFO3_TID, desc->info3); ++ ++ ts->peer_id = FIELD_GET(HAL_WBM_RELEASE_TX_INFO3_PEER_ID, desc->info3); ++ ts->flags = FIELD_GET(HAL_WBM_RELEASE_TX_INFO2_FIRST_MSDU, desc->info2) | ++ FIELD_GET(HAL_WBM_RELEASE_TX_INFO2_LAST_MSDU, desc->info2); ++} ++ + static void + ath12k_dp_tx_htt_tx_complete_buf(struct ath12k_base *ab, + struct sk_buff *msdu, + struct dp_tx_ring *tx_ring, + struct ath12k_dp_htt_wbm_tx_status *ts, +- struct sk_buff *skb_ext_desc, u8 mac_id) ++ struct sk_buff *skb_ext_desc, u8 mac_id, ++ void *desc) + { + struct ieee80211_tx_info *info; + struct ath12k_skb_cb *skb_cb; + struct ath12k *ar; + struct ieee80211_vif *vif; +- unsigned long attrs = 0; + struct ath12k_vif *ahvif; ++ struct ath12k_peer *peer; ++ struct hal_tx_status ts_status = { 0 }; ++ unsigned long attrs = 0; + u8 flags = 0; + bool drop_disable = false; + +@@ -816,6 +876,19 @@ ath12k_dp_tx_htt_tx_complete_buf(struct + } + } + ++ if (unlikely(ath12k_debugfs_is_sawf_stats_enabled(ar))) { ++ spin_lock_bh(&ab->base_lock); ++ ath12k_dp_tx_status_parse(ab, desc, &ts_status); ++ peer = ath12k_peer_find_by_id(ab, ts_status.peer_id); ++ if (unlikely(!peer || !peer->sta)) ++ ath12k_dbg(ab, ATH12K_DBG_DATA, ++ "dp_tx: failed to find the peer with peer_id %d\n", ++ ts_status.peer_id); ++ else ++ ath12k_sawf_stats_update(ar, msdu, &ts, peer); ++ spin_unlock_bh(&ab->base_lock); ++ } ++ + if (flags & ATH12K_SKB_HW_80211_ENCAP) + ieee80211_tx_status_8023(ar->ah->hw, vif, msdu); + else +@@ -847,7 +920,7 @@ ath12k_dp_tx_process_htt_tx_complete(str + ts.acked = (htt_status == HAL_WBM_REL_HTT_TX_COMP_STATUS_OK); + ts.ack_rssi = u32_get_bits(status_desc->info2, + HTT_TX_WBM_COMP_INFO2_ACK_RSSI); +- ath12k_dp_tx_htt_tx_complete_buf(ab, msdu, tx_ring, &ts, skb_ext_desc, mac_id); ++ ath12k_dp_tx_htt_tx_complete_buf(ab, msdu, tx_ring, &ts, skb_ext_desc, mac_id, desc); + + break; + case HAL_WBM_REL_HTT_TX_COMP_STATUS_REINJ: +@@ -994,36 +1067,6 @@ err_out: + spin_unlock_bh(&ab->base_lock); + } + +-static inline void ath12k_dp_tx_status_parse(struct ath12k_base *ab, +- struct hal_wbm_completion_ring_tx *desc, +- struct hal_tx_status *ts) +-{ +- ts->buf_rel_source = +- FIELD_GET(HAL_WBM_COMPL_TX_INFO0_REL_SRC_MODULE, desc->info0); +- if (ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_FW && +- ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM) +- return; +- +- if (ts->buf_rel_source == HAL_WBM_REL_SRC_MODULE_FW) +- return; +- +- ts->status = FIELD_GET(HAL_WBM_COMPL_TX_INFO0_TQM_RELEASE_REASON, +- desc->info0); +- ts->ppdu_id = FIELD_GET(HAL_WBM_COMPL_TX_INFO1_TQM_STATUS_NUMBER, +- desc->info1); +- ts->ack_rssi = FIELD_GET(HAL_WBM_COMPL_TX_INFO2_ACK_FRAME_RSSI, +- desc->info2); +- if (desc->rate_stats.info0 & HAL_TX_RATE_STATS_INFO0_VALID) +- ts->rate_stats = desc->rate_stats.info0; +- else +- ts->rate_stats = 0; +- ts->tid = FIELD_GET(HAL_WBM_RELEASE_TX_INFO3_TID, desc->info3); +- +- ts->peer_id = FIELD_GET(HAL_WBM_RELEASE_TX_INFO3_PEER_ID, desc->info3); +- ts->flags = FIELD_GET(HAL_WBM_RELEASE_TX_INFO2_FIRST_MSDU, desc->info2) | +- FIELD_GET(HAL_WBM_RELEASE_TX_INFO2_LAST_MSDU, desc->info2); +-} +- + static void ath12k_dp_tx_complete_msdu(struct ath12k *ar, + struct sk_buff *msdu, + struct hal_wbm_release_ring *tx_status, +@@ -1106,6 +1149,17 @@ static void ath12k_dp_tx_complete_msdu(s + case HAL_WBM_TQM_REL_REASON_DROP_THRESHOLD: + case HAL_WBM_TQM_REL_REASON_CMD_REMOVE_AGED_FRAMES: + case HAL_WBM_TQM_REL_REASON_CMD_REMOVE_TX: ++ if (unlikely(ath12k_debugfs_is_sawf_stats_enabled(ar))) { ++ spin_lock_bh(&ab->base_lock); ++ peer = ath12k_peer_find_by_id(ab, ts.peer_id); ++ if (unlikely(!peer || !peer->sta)) ++ ath12k_dbg(ab, ATH12K_DBG_DATA, ++ "dp_tx: failed to find the peer with peer_id %d\n", ++ ts.peer_id); ++ else ++ ath12k_sawf_stats_update(ar, msdu, &ts, peer); ++ spin_unlock_bh(&ab->base_lock); ++ } + dev_kfree_skb_any(msdu); + return; + default: +@@ -1176,6 +1230,9 @@ static void ath12k_dp_tx_complete_msdu(s + arsta->wbm_tx_stats->wbm_tx_comp_stats[wbm_status]++; + } + ++ if (unlikely(ath12k_debugfs_is_sawf_stats_enabled(ar))) ++ ath12k_sawf_stats_update(ar, msdu, &ts, peer); ++ + spin_unlock_bh(&ab->base_lock); + + if (flags & ATH12K_SKB_HW_80211_ENCAP) +--- a/drivers/net/wireless/ath/ath12k/sawf.c ++++ b/drivers/net/wireless/ath/ath12k/sawf.c +@@ -1085,3 +1085,111 @@ unlock_base_lock: + + return ret; + } ++ ++void ath12k_sawf_tx_enqueue_peer_stats(struct ath12k_base *ab, ++ struct ath12k_peer *peer, ++ u32 msduq_id, u32 len) ++{ ++ struct ath12k_sawf_stats *sawf_stats; ++ struct sawf_tx_stats *tx_stats; ++ u32 tid, q_id; ++ ++ sawf_stats = &peer->sawf_stats; ++ if(unlikely(!sawf_stats)) { ++ ath12k_err(ab, "sawf stats not available\n"); ++ return; ++ } ++ ++ if (unlikely(msduq_id >= (ab->max_msduq_per_tid * ATH12K_SAWF_MAX_TID_SUPPORT) && ++ msduq_id < (ab->default_msduq_per_tid * ATH12K_SAWF_MAX_TID_SUPPORT))) ++ return; ++ ++ tid = u32_get_bits(msduq_id, MSDUQID_TID_MASK); ++ q_id = u32_get_bits(msduq_id, MSDUQID_Q_MASK) - ab->default_msduq_per_tid; ++ ++ tx_stats = &sawf_stats->tx_stats[tid][q_id]; ++ tx_stats->queue_depth++; ++ tx_stats->tx_ingress.num_pkts++; ++ tx_stats->tx_ingress.bytes += len; ++ ++ return; ++} ++ ++void ath12k_sawf_stats_update(struct ath12k *ar, struct sk_buff *skb, ++ struct hal_tx_status *ts, ++ struct ath12k_peer *peer) ++{ ++ struct ath12k_sawf_stats *sawf_stats; ++ struct ath12k_base *ab = ar->ab; ++ struct sawf_tx_stats *tx_stats; ++ u32 msduq_id, len, q_id, tid; ++ ++ if (!ts) ++ return; ++ ++ if (u32_get_bits(skb->mark, SAWF_TAG_ID) != SAWF_VALID_TAG) ++ return; ++ ++ sawf_stats = &peer->sawf_stats; ++ if (!sawf_stats) { ++ ath12k_err(ab, "sawf stats not available\n"); ++ return; ++ } ++ ++ msduq_id = u32_get_bits(skb->mark, SAWF_MSDUQ_ID); ++ if (msduq_id >= (ab->max_msduq_per_tid * ATH12K_SAWF_MAX_TID_SUPPORT) && ++ msduq_id < (ab->default_msduq_per_tid * ATH12K_SAWF_MAX_TID_SUPPORT)) ++ return; ++ ++ tid = u32_get_bits(msduq_id, MSDUQID_TID_MASK); ++ q_id = u32_get_bits(msduq_id, MSDUQID_Q_MASK) - ab->default_msduq_per_tid; ++ ++ if (!(ath12k_debugfs_is_sawf_stats_enabled(ar) & ATH12K_SAWF_STATS_BASIC)) ++ goto latency_stats_update; ++ ++ len = skb->len; /* Need to add frag length? */ ++ ++ tx_stats = &sawf_stats->tx_stats[tid][q_id]; ++ ++ switch (ts->status) { ++ case HAL_WBM_TQM_REL_REASON_FRAME_ACKED: ++ tx_stats->tx_success.num_pkts++; ++ tx_stats->tx_success.bytes += len; ++ break; ++ case HAL_WBM_TQM_REL_REASON_CMD_REMOVE_MPDU: ++ tx_stats->dropped.fw_rem.num_pkts++; ++ tx_stats->dropped.fw_rem.bytes += len; ++ tx_stats->tx_failed++; ++ break; ++ case HAL_WBM_TQM_REL_REASON_CMD_REMOVE_TX: ++ tx_stats->dropped.fw_rem_tx++; ++ tx_stats->tx_failed++; ++ break; ++ case HAL_WBM_TQM_REL_REASON_CMD_REMOVE_NOTX: ++ tx_stats->dropped.fw_rem_notx++; ++ tx_stats->tx_failed++; ++ break; ++ case HAL_WBM_TQM_REL_REASON_CMD_REMOVE_AGED_FRAMES: ++ tx_stats->dropped.age_out++; ++ tx_stats->tx_failed++; ++ break; ++ case HAL_WBM_TQM_REL_REASON_CMD_REMOVE_RESEAON1: ++ tx_stats->dropped.fw_reason1++; ++ tx_stats->tx_failed++; ++ break; ++ case HAL_WBM_TQM_REL_REASON_CMD_REMOVE_RESEAON2: ++ tx_stats->dropped.fw_reason2++; ++ tx_stats->tx_failed++; ++ break; ++ case HAL_WBM_TQM_REL_REASON_CMD_REMOVE_RESEAON3: ++ tx_stats->dropped.fw_reason3++; ++ tx_stats->tx_failed++; ++ default: ++ break; ++ } ++ ++ tx_stats->queue_depth--; ++ ++latency_stats_update: ++ return; ++} +--- a/drivers/net/wireless/ath/ath12k/sawf.h ++++ b/drivers/net/wireless/ath/ath12k/sawf.h +@@ -6,6 +6,8 @@ + #ifndef ATH12K_SAWF_H + #define ATH12K_SAWF_H + ++struct hal_tx_status; ++ + #ifdef CPTCFG_ATH12K_SAWF + + #define ATH12K_MAC_ADDR_SIZE 6 +@@ -477,6 +479,72 @@ enum ath12k_sawf_stats_level { + + #define ATH12K_SAWF_STATS_MAX (ATH12K_SAWF_STATS_BASIC | ATH12K_SAWF_STATS_ADVNCD | ATH12K_SAWF_STATS_LATENCY) + ++/** ++ * struct sawf_fw_mpdu_stats- per-mpdu Tx success/failure snapshot ++ * @success_cnt: count of pkts successfully transmitted ++ * @failure_cnt: count of pkts failed to transmit ++ */ ++struct sawf_fw_mpdu_stats { ++ u64 success_cnt; ++ u64 failure_cnt; ++}; ++ ++/** ++ * struct dp_pkt_info - packet info ++ * @num: number of packets ++ * @bytes: total nunmber of bytes ++ */ ++struct dp_pkt_info { ++ u32 num_pkts; ++ u64 bytes; ++}; ++ ++/** ++ * struct sawf_tx_stats- Tx stats ++ * @tx_success: transmit success stats ++ * @tx_ingress: enqueue success stats ++ * @dropped: detailed information for tx-drops ++ * @svc_intval_stats: success/failure stats per service-interval ++ * @burst_size_stats: success/failure stats per burst-size ++ * @tx_failed: tx failure count ++ * @queue_depth: transmit queue-depth ++ * @throughput: throughput ++ * @ingress_rate: ingress-rate ++ * @tid: tid used for transmit ++ * @msduq: MSDU queue used for transmit ++ */ ++struct sawf_tx_stats { ++ struct dp_pkt_info tx_success; ++ struct dp_pkt_info tx_ingress; ++ struct { ++ struct dp_pkt_info fw_rem; ++ u32 fw_rem_notx; ++ u32 fw_rem_tx; ++ u32 age_out; ++ u32 fw_reason1; ++ u32 fw_reason2; ++ u32 fw_reason3; ++ } dropped; ++ struct sawf_fw_mpdu_stats svc_intval_stats; ++ struct sawf_fw_mpdu_stats burst_size_stats; ++ u32 tx_failed; ++ u32 queue_depth; ++ u32 throughput; ++ u32 ingress_rate; ++ u8 tid; ++ u8 msduq; ++}; ++ ++/** ++ * sawf_stats - sawf stats ++ * @delay: delay stats per host MSDU queue ++ * @tx_stats: Tx stats per host MSDU queue ++ * @lock: Protection for sawf-stats ++ */ ++struct ath12k_sawf_stats { ++ struct sawf_tx_stats tx_stats[ATH12K_SAWF_MAX_TID_SUPPORT][MAX_Q_PER_TID]; ++}; ++ + extern bool ath12k_sawf_enable; + struct ath12k_sawf_ctx *ath12k_get_sawf_context(void); + void ath12k_sawf_init(struct ath12k_base *ab); +@@ -511,7 +579,12 @@ int ath12k_sawf_def_qmap_report_req(stru + + void ath12k_htt_sawf_def_q_map_report_handler(struct ath12k_base *ab, + struct sk_buff *skb); +- ++void ath12k_sawf_stats_update(struct ath12k *ar, struct sk_buff *skb, ++ struct hal_tx_status *ts, ++ struct ath12k_peer *peer); ++void ath12k_sawf_tx_enqueue_peer_stats(struct ath12k_base *ab, ++ struct ath12k_peer *peer, ++ u32 msduq_id, u32 len); + #else /* CPTCFG_ATH12K_SAWF */ + + static inline void ath12k_sawf_init(struct ath12k_base *ab) { +@@ -522,5 +595,11 @@ static inline void ath12k_sawf_deinit(st + return; + } + ++static inline void ath12k_sawf_stats_update(struct ath12k *ar, struct sk_buff *skb, ++ struct hal_tx_status *ts, ++ struct ath12k_peer *peer) ++{ ++ return; ++} + #endif /* CPTCFG_ATH12K_SAWF */ + #endif /* ATH11K_SAWF_H */ +--- a/drivers/net/wireless/ath/ath12k/peer.h ++++ b/drivers/net/wireless/ath/ath12k/peer.h +@@ -27,6 +27,7 @@ struct ath12k_peer { + struct ieee80211_vif *vif; + #ifdef CPTCFG_ATH12K_SAWF + struct ath12k_sawf_peer_ctx sawf_ctx_peer; ++ struct ath12k_sawf_stats sawf_stats; + #endif /* CPTCFG_ATH12K_SAWF */ + int vdev_id; + u8 addr[ETH_ALEN]; diff --git a/feeds/ipq95xx/mac80211/patches/qca/784-03-wifi-ath12k-Add-support-to-handle-streaming-stats.patch b/feeds/ipq95xx/mac80211/patches/qca/784-03-wifi-ath12k-Add-support-to-handle-streaming-stats.patch new file mode 100644 index 000000000..628de2a82 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/784-03-wifi-ath12k-Add-support-to-handle-streaming-stats.patch @@ -0,0 +1,608 @@ +From eb43f258ad479de0a82c4779a1467d4744387021 Mon Sep 17 00:00:00 2001 +From: Nagarajan Maran +Date: Tue, 6 Jun 2023 08:25:27 +0530 +Subject: [PATCH] wifi: ath12k: Add support to handle streaming stats + +Add support to enable/disable streaming stats to target. +Also handle the streaming stats when received from target. + +Signed-off-by: Nagarajan Maran +--- + drivers/net/wireless/ath/ath12k/dp.h | 2 + + drivers/net/wireless/ath/ath12k/dp_rx.c | 3 + + drivers/net/wireless/ath/ath12k/sawf.c | 186 +++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/sawf.h | 165 ++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/vendor.c | 49 ++++++ + drivers/net/wireless/ath/ath12k/vendor.h | 11 ++ + 6 files changed, 416 insertions(+) + +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -536,6 +536,7 @@ enum htt_h2t_msg_type { + HTT_H2T_MSG_TYPE_SAWF_DEF_Q_MAP_REQ = 0x1c, + HTT_H2T_MSG_TYPE_SAWF_DEF_Q_UNMAP_REQ = 0x1d, + HTT_H2T_MSG_TYPE_SAWF_DEF_Q_MAP_REPORT_REQ = 0x1e, ++ HTT_H2T_MSG_TYPE_STREAMING_STATS_REQ = 0x20, + }; + + #define HTT_VER_REQ_INFO_MSG_ID GENMASK(7, 0) +@@ -1405,6 +1406,7 @@ enum htt_t2h_msg_type { + HTT_T2H_MSG_TYPE_VDEV_TXRX_STATS_PERIODIC_IND = 0x2c, + HTT_T2H_MSG_TYPE_SAWF_DEF_QUEUES_MAP_REPORT_CONF = 0x2d, + HTT_T2H_MSG_TYPE_SAWF_MSDUQ_INFO_IND = 0x2e, ++ HTT_T2H_MSG_TYPE_STREAMING_STATS_IND = 0x2f, + }; + + #define HTT_TARGET_VERSION_MAJOR 3 +--- a/drivers/net/wireless/ath/ath12k/sawf.c ++++ b/drivers/net/wireless/ath/ath12k/sawf.c +@@ -8,6 +8,7 @@ + #include "wmi.h" + #include "sawf.h" + #include "peer.h" ++#include "debugfs_htt_stats.h" + #include + #include + +@@ -1086,6 +1087,199 @@ unlock_base_lock: + return ret; + } + ++int ath12k_htt_sawf_streaming_stats_configure(struct ath12k *ar, ++ u8 stats_type, ++ u8 configure, ++ u32 config_param_0, ++ u32 config_param_1, ++ u32 config_param_2, ++ u32 config_param_3) ++{ ++ struct ath12k_base *ab = ar->ab; ++ struct ath12k_dp *dp = &ab->dp; ++ struct sk_buff *skb; ++ struct ath12k_htt_h2t_sawf_streaming_req *cmd; ++ int len = sizeof(*cmd); ++ int ret; ++ ++ if (!(ath12k_debugfs_is_sawf_stats_enabled(ar) & ATH12K_SAWF_STATS_ADVNCD)) ++ return -EOPNOTSUPP; ++ ++ skb = ath12k_htc_alloc_skb(ab, len); ++ if (!skb) { ++ ath12k_err(ab, "Insufficient Memory\n"); ++ return -ENOMEM; ++ } ++ ++ skb_put(skb, len); ++ cmd = (struct ath12k_htt_h2t_sawf_streaming_req*)skb->data; ++ cmd->info = u32_encode_bits(HTT_H2T_MSG_TYPE_STREAMING_STATS_REQ, ++ HTT_H2T_MSG_TYPE_ID) | ++ u32_encode_bits(stats_type, ++ HTT_H2T_MSG_TYPE_STREAMING_STATS_TYPE) | ++ u32_encode_bits(configure, ++ HTT_H2T_MSG_TYPE_STREAMING_STATS_CONFIGURE); ++ ++ cmd->config_param_0 = config_param_0; ++ cmd->config_param_1 = config_param_1; ++ cmd->config_param_2 = config_param_2; ++ cmd->config_param_3 = config_param_3; ++ ++ ath12k_dbg(ab, ATH12K_DBG_SAWF, "Configure streaming stats :0x%x\n", cmd->info); ++ ++ ret = ath12k_htc_send(&ab->htc, dp->eid, skb); ++ if (ret) ++ dev_kfree_skb_any(skb); ++ return ret; ++} ++ ++static int ath12k_fw_mpdu_stats_update(struct ath12k_base *ab, u16 peer_id, ++ u8 tid, u8 q_type, u16 svc_int_success, ++ u16 svc_int_fail, u16 burst_sz_success, ++ u16 burst_sz_fail) ++{ ++ struct ath12k *ar = NULL; ++ struct ath12k_peer *peer; ++ struct ath12k_sawf_stats *sawf_stats; ++ struct sawf_fw_mpdu_stats *svc_intval_stats; ++ struct sawf_fw_mpdu_stats *burst_size_stats; ++ int ret = 0; ++ int q_id; ++ ++ if (tid >= ATH12K_SAWF_MAX_TID_SUPPORT) ++ return -EINVAL; ++ ++ if (q_type >= ab->max_msduq_per_tid) ++ return -EINVAL; ++ ++ q_id = q_type - ab->default_msduq_per_tid; ++ ++ spin_lock_bh(&ab->base_lock); ++ peer = ath12k_peer_find_by_id(ab, peer_id); ++ if (unlikely(!peer)) { ++ ath12k_dbg(ab, ATH12K_DBG_SAWF, ++ "SAWF: failed to find the peer with peer_id %u\n", ++ peer_id); ++ ret = -ENOENT; ++ goto end; ++ } ++ ++ ar = ath12k_mac_get_ar_by_vdev_id(ab, peer->vdev_id); ++ if (!ar) { ++ ret = -ENOENT; ++ goto end; ++ } ++ ++ if (!(ath12k_debugfs_is_sawf_stats_enabled(ar) & ATH12K_SAWF_STATS_ADVNCD)) { ++ ret = -EOPNOTSUPP; ++ goto end; ++ } ++ ++ sawf_stats = &peer->sawf_stats; ++ if (!sawf_stats) { ++ ret = -ENODATA; ++ goto end; ++ } ++ ++ svc_intval_stats = &sawf_stats->tx_stats[tid][q_id].svc_intval_stats; ++ if (!svc_intval_stats) { ++ ret = -ENODATA; ++ goto end; ++ } ++ ++ burst_size_stats = &sawf_stats->tx_stats[tid][q_id].burst_size_stats; ++ if (!burst_size_stats) { ++ ret = -ENODATA; ++ goto end; ++ } ++ ++ svc_intval_stats->success_cnt += svc_int_success; ++ svc_intval_stats->failure_cnt += svc_int_fail; ++ burst_size_stats->success_cnt += burst_sz_success; ++ burst_size_stats->failure_cnt += burst_sz_fail; ++ ++end: ++ spin_unlock_bh(&ab->base_lock); ++ return ret; ++} ++ ++void ath12k_htt_sawf_streaming_stats_ind_handler(struct ath12k_base *ab, ++ struct sk_buff *skb) ++{ ++ struct htt_stats_strm_gen_mpdus_tlv *mpdus_tlv; ++ struct htt_stats_strm_gen_mpdus_details_tlv *mpdus_detail_tlv; ++ const struct htt_tlv *tlv; ++ u32 *data = NULL; ++ u32 len, tlv_tag, tlv_len; ++ u16 info; ++ u8 tid, q_type; ++ ++ data = skb->data; ++ len = skb->len; ++ ++ data++; ++ if (len > HTT_T2H_STREAMING_STATS_IND_HDR_SIZE) ++ len -= HTT_T2H_STREAMING_STATS_IND_HDR_SIZE; ++ else ++ return; ++ ++ while(len > 0) { ++ tlv = (struct htt_tlv *)data; ++ tlv_tag = u32_get_bits(*data, HTT_TLV_TAG); ++ tlv_len = u32_get_bits(*data, HTT_TLV_LEN); ++ ++ if (!tlv_len) ++ break; ++ ++ data++; ++ if (tlv_tag == HTT_STATS_STRM_GEN_MPDUS_TAG) { ++ u16 svc_interval_success, svc_interval_failure, burst_size_success, burst_size_failure, peer_id; ++ mpdus_tlv = (struct htt_stats_strm_gen_mpdus_tlv*)data; ++ ++ peer_id = __le16_to_cpu(mpdus_tlv->peer_id); ++ info = __le16_to_cpu(mpdus_tlv->info); ++ tid = u16_get_bits(info, SAWF_TTH_TID_MASK); ++ q_type = u16_get_bits(info, SAWF_TTH_QTYPE_MASK); ++ svc_interval_success = __le16_to_cpu(mpdus_tlv->svc_interval_success); ++ svc_interval_failure = __le16_to_cpu(mpdus_tlv->svc_interval_failure); ++ burst_size_success = __le16_to_cpu(mpdus_tlv->burst_size_success); ++ burst_size_failure = __le16_to_cpu(mpdus_tlv->burst_size_failure); ++ ++ ath12k_fw_mpdu_stats_update(ab, peer_id, tid, ++ q_type, svc_interval_success, ++ svc_interval_failure, ++ burst_size_success, ++ burst_size_failure); ++ } else if (tlv_tag == HTT_STATS_STRM_GEN_MPDUS_DETAILS_TAG) { ++ mpdus_detail_tlv = (struct htt_stats_strm_gen_mpdus_details_tlv *)data; ++ info = __le16_to_cpu(mpdus_detail_tlv->info); ++ tid = u16_get_bits(info, SAWF_TTH_TID_MASK); ++ q_type = u16_get_bits(info, SAWF_TTH_QTYPE_MASK); ++ ++ ath12k_dbg(ab, ATH12K_DBG_SAWF, "SAWF: peer_id %u tid %u qtype %u " ++ "svc_intvl: ts_prior %ums ts_now %ums " ++ "intvl_spec %ums margin %ums|" ++ "burst_size: consumed_bytes_orig %u " ++ "consumed_bytes_final %u remaining_bytes %u " ++ "burst_size_spec %u margin_bytes %u\n", ++ __le16_to_cpu(mpdus_detail_tlv->peer_id), ++ tid, q_type, ++ __le16_to_cpu(mpdus_detail_tlv->svc_interval_timestamp_prior_ms), ++ __le16_to_cpu(mpdus_detail_tlv->svc_interval_timestamp_now_ms), ++ __le16_to_cpu(mpdus_detail_tlv->svc_interval_interval_spec_ms), ++ __le16_to_cpu(mpdus_detail_tlv->svc_interval_interval_margin_ms), ++ __le16_to_cpu(mpdus_detail_tlv->burst_size_consumed_bytes_orig), ++ __le16_to_cpu(mpdus_detail_tlv->burst_size_consumed_bytes_final), ++ __le16_to_cpu(mpdus_detail_tlv->burst_size_remaining_bytes), ++ __le16_to_cpu(mpdus_detail_tlv->burst_size_burst_size_spec), ++ __le16_to_cpu(mpdus_detail_tlv->burst_size_margin_bytes)); ++ } ++ data += (tlv_len - 4); ++ len -= tlv_len; ++ } ++ return; ++} ++ + void ath12k_sawf_tx_enqueue_peer_stats(struct ath12k_base *ab, + struct ath12k_peer *peer, + u32 msduq_id, u32 len) +@@ -1147,7 +1341,7 @@ void ath12k_sawf_stats_update(struct ath + if (!(ath12k_debugfs_is_sawf_stats_enabled(ar) & ATH12K_SAWF_STATS_BASIC)) + goto latency_stats_update; + +- len = skb->len; /* Need to add frag length? */ ++ len = skb->len; + + tx_stats = &sawf_stats->tx_stats[tid][q_id]; + +--- a/drivers/net/wireless/ath/ath12k/sawf.h ++++ b/drivers/net/wireless/ath/ath12k/sawf.h +@@ -545,6 +545,160 @@ struct ath12k_sawf_stats { + struct sawf_tx_stats tx_stats[ATH12K_SAWF_MAX_TID_SUPPORT][MAX_Q_PER_TID]; + }; + ++/* MSG_TYPE => HTT_H2T_MSG_TYPE_STREAMING_STATS_REQ ++ * ++ * @details ++ * The following field definitions describe the format of the HTT host ++ * to target message that requests the target to start or stop producing ++ * ongoing stats of the specified type. ++ * ++ * |31|30 |23 16|15 8|7 0| ++ * |-----------------------------------------------------------| ++ * |EN| reserved | stats type | reserved | msg type | ++ * |-----------------------------------------------------------| ++ * | config param [0] | ++ * |-----------------------------------------------------------| ++ * | config param [1] | ++ * |-----------------------------------------------------------| ++ * | config param [2] | ++ * |-----------------------------------------------------------| ++ * | config param [3] | ++ * |-----------------------------------------------------------| ++ * Where: ++ * - EN is an enable/disable flag ++ * Header fields: ++ * - MSG_TYPE ++ * Bits 7:0 ++ * Purpose: identifies this is a streaming stats upload request message ++ * Value: 0x20 (HTT_H2T_MSG_TYPE_STREAMING_STATS_REQ) ++ * - STATS_TYPE ++ * Bits 23:16 ++ * Purpose: identifies which FW statistics to upload ++ * Value: Defined values are HTT_STRM_GEN_MPDUS_STATS for basic ++ * stats and HTT_STRM_GEN_MPDUS_DETAILS_STAT for extended ++ * stats. ++ * - ENABLE ++ * Bit 31 ++ * Purpose: enable/disable the target's ongoing stats of the specified type ++ * Value: ++ * 0 - disable ongoing production of the specified stats type ++ * 1 - enable ongoing production of the specified stats type ++ * - CONFIG_PARAM [0] ++ * Bits 31:0 ++ * Purpose: give an opaque configuration value to the specified stats type ++ * Value: stats-type specific configuration value ++ * - CONFIG_PARAM [1] ++ * Bits 31:0 ++ * Purpose: give an opaque configuration value to the specified stats type ++ * Value: stats-type specific configuration value ++ * - CONFIG_PARAM [2] ++ * Bits 31:0 ++ * Purpose: give an opaque configuration value to the specified stats type ++ * Value: stats-type specific configuration value ++ * - CONFIG_PARAM [3] ++ * Bits 31:0 ++ * Purpose: give an opaque configuration value to the specified stats type ++ * Value: stats-type specific configuration value ++ */ ++ ++#define HTT_STRM_GEN_MPDUS_STATS 43 ++#define HTT_STRM_GEN_MPDUS_DETAILS_STATS 44 ++#define HTT_H2T_MSG_TYPE_STREAMING_STATS_TYPE GENMASK(23,16) ++#define HTT_H2T_MSG_TYPE_STREAMING_STATS_CONFIGURE BIT(31) ++ ++struct ath12k_htt_h2t_sawf_streaming_req { ++ u32 info; ++ u32 config_param_0; ++ u32 config_param_1; ++ u32 config_param_2; ++ u32 config_param_3; ++}; ++ ++/** ++ * @brief target -> host streaming statistics upload ++ * ++ * MSG_TYPE => HTT_T2H_MSG_TYPE_STREAMING_STATS_IND ++ * ++ * @details ++ * The following field definitions describe the format of the HTT target ++ * to host streaming stats upload indication message. ++ * The host can use a HTT_H2T_MSG_TYPE_STREAMING_STATS_REQ message to enable ++ * the target to produce an ongoing series of HTT_T2H_MSG_TYPE_STREAMING_STATS_IND ++ * STREAMING_STATS_IND messages, and can also use the ++ * HTT_H2T_MSG_TYPE_STREAMING_STATS_REQ message to halt the target's production of ++ * HTT_T2H_MSG_TYPE_STREAMING_STATS_IND messages. ++ * ++ * The HTT_T2H_MSG_TYPE_STREAMING_STATS_IND message contains a payload of TLVs ++ * containing the stats enabled by the host's HTT_H2T_MSG_TYPE_STREAMING_STATS_REQ ++ * message. ++ * ++ * |31 8|7 0| ++ * |--------------------------------------------------------------| ++ * | reserved | msg type | ++ * |--------------------------------------------------------------| ++ * | type-specific stats info | ++ * |--------------------------------------------------------------| ++ * Header fields: ++ * - MSG_TYPE ++ * Bits 7:0 ++ * Purpose: Identifies this as a streaming statistics upload indication ++ * message. ++ * Value: 0x2f (HTT_T2H_MSG_TYPE_STREAMING_STATS_IND) ++ */ ++ ++#define HTT_T2H_STREAMING_STATS_IND_HDR_SIZE 4 ++#define SAWF_TTH_TID_MASK GENMASK(3,0) ++#define SAWF_TTH_QTYPE_MASK GENMASK(7,4) ++ ++struct htt_stats_strm_gen_mpdus_tlv { ++/* ++ * |31 24|23 20|19 16|15 0| ++ * |---------+----------+----------+------------------------------| ++ * |Reserved | QTYPE | TID | Peer ID | ++ * |--------------------------------------------------------------| ++ * | svc interval failure | svc interval success | ++ * |--------------------------------------------------------------| ++ * | burst size failure | burst size success | ++ * |--------------------------------------------------------------| ++*/ ++ __le16 peer_id; ++ __le16 info; ++ __le16 svc_interval_success; ++ __le16 svc_interval_failure; ++ __le16 burst_size_success; ++ __le16 burst_size_failure; ++} __packed; ++ ++struct htt_stats_strm_gen_mpdus_details_tlv { ++ __le16 peer_id; ++ __le16 info; ++ __le16 svc_interval_timestamp_prior_ms; ++ __le16 svc_interval_timestamp_now_ms; ++ __le16 svc_interval_interval_spec_ms; ++ __le16 svc_interval_interval_margin_ms; ++ /* consumed_bytes_orig: ++ * Raw count (actually estimate) of how many bytes were removed ++ * from the MSDU queue by the GEN_MPDUS operation. ++ */ ++ __le16 burst_size_consumed_bytes_orig; ++ /* consumed_bytes_final: ++ * Adjusted count of removed bytes that incorporates normalizing ++ * by the actual service interval compared to the expected ++ * service interval. ++ * This allows the burst size computation to be independent of ++ * whether the target is doing GEN_MPDUS at only the service ++ * interval, or substantially more often than the service ++ * interval. ++ * consumed_bytes_final = consumed_bytes_orig / ++ * (svc_interval / ref_svc_interval) ++ */ ++ __le16 burst_size_consumed_bytes_final; ++ __le16 burst_size_remaining_bytes; ++ __le16 burst_size_reserved; ++ __le16 burst_size_burst_size_spec; ++ __le16 burst_size_margin_bytes; ++} __packed; ++ + extern bool ath12k_sawf_enable; + struct ath12k_sawf_ctx *ath12k_get_sawf_context(void); + void ath12k_sawf_init(struct ath12k_base *ab); +@@ -585,6 +739,15 @@ void ath12k_sawf_stats_update(struct ath + void ath12k_sawf_tx_enqueue_peer_stats(struct ath12k_base *ab, + struct ath12k_peer *peer, + u32 msduq_id, u32 len); ++int ath12k_htt_sawf_streaming_stats_configure(struct ath12k *ar, ++ u8 stats_type, ++ u8 configure, ++ u32 config_param_0, ++ u32 config_param_1, ++ u32 config_param_2, ++ u32 config_param_3); ++void ath12k_htt_sawf_streaming_stats_ind_handler(struct ath12k_base *ab, ++ struct sk_buff *skb); + #else /* CPTCFG_ATH12K_SAWF */ + + static inline void ath12k_sawf_init(struct ath12k_base *ab) { +@@ -597,7 +760,7 @@ static inline void ath12k_sawf_deinit(st + + static inline void ath12k_sawf_stats_update(struct ath12k *ar, struct sk_buff *skb, + struct hal_tx_status *ts, +- struct ath12k_peer *peer) ++ struct ath12k_peer *peer) + { + return; + } +--- a/drivers/net/wireless/ath/ath12k/vendor.c ++++ b/drivers/net/wireless/ath/ath12k/vendor.c +@@ -77,6 +77,12 @@ ath12k_vendor_telemetry_sawf_sla_samples + [QCN_WLAN_VENDOR_ATTR_TELEMETRY_SLA_TIME_SEC] = {.type = NLA_U32}, + }; + ++static const struct nla_policy ++ath12k_vendor_sawf_streaming[QCA_WLAN_VENDOR_ATTR_SAWF_STREAMING_MAX + 1] = { ++ [QCA_WLAN_VENDOR_ATTR_SAWF_STREAMING_BASIC_STATS] = {.type = NLA_U8}, ++ [QCA_WLAN_VENDOR_ATTR_SAWF_STREAMING_EXTND_STATS] = {.type = NLA_U8}, ++}; ++ + static void ath12k_set_default_values(struct ath12k_sawf_svc_params *param) + { + param->min_throughput_rate = SAWF_SVC_PARAM_DEFAULT_MIN_THRUPUT; +@@ -604,6 +610,92 @@ static int ath12k_vendor_telemetry_sawf_ + + return ret; + } ++ ++static struct ath12k *ath12k_get_ar_from_wdev(struct wireless_dev *wdev, u8 link_id) ++{ ++ struct ieee80211_vif *vif = NULL; ++ struct ath12k_vif *ahvif = NULL; ++ struct ieee80211_hw *hw = NULL; ++ struct ath12k *ar = NULL; ++ ++ vif = wdev_to_ieee80211_vif(wdev); ++ if (!vif) ++ return NULL; ++ ++ ahvif = (struct ath12k_vif *)vif->drv_priv; ++ if (!ahvif) ++ return NULL; ++ ++ mutex_lock(&ahvif->ah->conf_mutex); ++ hw = ahvif->ah->hw; ++ if (!hw) { ++ mutex_unlock(&ahvif->ah->conf_mutex); ++ return NULL; ++ } ++ ++ ar = ath12k_get_ar_by_vif(hw, vif, link_id); ++ mutex_unlock(&ahvif->ah->conf_mutex); ++ ++ return ar; ++} ++ ++static int ath12k_vendor_sawf_streaming_stats_configure(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ const void *data, ++ int data_len) ++{ ++ struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAWF_STREAMING_MAX + 1]; ++ struct ath12k *ar = NULL; ++ int ret = 0; ++ u8 basic_stats_configure, extnd_stats_configure, link_id; ++ ++ if (!ath12k_sawf_enable) ++ return -EOPNOTSUPP; ++ ++ if(!wdev) ++ return -ENODATA; ++ ++ ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAWF_STREAMING_MAX, data, data_len, ++ ath12k_vendor_sawf_streaming, NULL); ++ if (ret) { ++ ath12k_warn(NULL, "invalid sawf streaming stats configuration\n"); ++ return ret; ++ } ++ ++ if (wdev->valid_links) { /* MLO case */ ++ if (!tb[QCA_WLAN_VENDOR_ATTR_MLO_LINK_ID]) ++ return -EINVAL; ++ link_id = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_MLO_LINK_ID]); ++ if (!(wdev->valid_links & BIT(link_id))) ++ return -ENOLINK; ++ } else { /* NON-MLO case */ ++ if (!tb[QCA_WLAN_VENDOR_ATTR_MLO_LINK_ID]) ++ link_id = 0; ++ else ++ return -EINVAL; ++ } ++ ++ ar = ath12k_get_ar_from_wdev(wdev, link_id); ++ if (!ar) ++ return -ENODATA; ++ ++ if (tb[QCA_WLAN_VENDOR_ATTR_SAWF_STREAMING_BASIC_STATS]) { ++ basic_stats_configure = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAWF_STREAMING_BASIC_STATS]); ++ ret = ath12k_htt_sawf_streaming_stats_configure(ar, HTT_STRM_GEN_MPDUS_STATS, ++ basic_stats_configure, 0, 0, 0, 0); ++ if (ret) ++ return ret; ++ } ++ ++ if (tb[QCA_WLAN_VENDOR_ATTR_SAWF_STREAMING_EXTND_STATS]) { ++ extnd_stats_configure = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAWF_STREAMING_EXTND_STATS]); ++ ret = ath12k_htt_sawf_streaming_stats_configure(ar, HTT_STRM_GEN_MPDUS_DETAILS_STATS, ++ extnd_stats_configure, 0, 0, 0, 0); ++ } ++ ++ return ret; ++} ++ + #endif /* CPTCFG_ATH12K_SAWF */ + static struct wiphy_vendor_command ath12k_vendor_commands[] = { + #ifdef CPTCFG_ATH12K_SAWF +@@ -673,7 +765,15 @@ static struct wiphy_vendor_command ath12 + .policy = ath12k_vendor_telemetry_sawf_sla_detect_config_policy, + .maxattr = QCA_WLAN_VENDOR_TELEMETRY_SLA_DETECT_ATTR_CONFIG_MAX, + }, +-#endif ++ { ++ .info.vendor_id = QCA_NL80211_VENDOR_ID, ++ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SAWF_STREAMING_STATS, ++ .doit = ath12k_vendor_sawf_streaming_stats_configure, ++ .policy = ath12k_vendor_sawf_streaming, ++ .maxattr = QCA_WLAN_VENDOR_ATTR_SAWF_STREAMING_MAX, ++ .flags = WIPHY_VENDOR_CMD_NEED_NETDEV, ++ }, ++#endif /* CPTCFG_ATH12K_SAWF */ + }; + + int ath12k_vendor_register(struct ath12k_hw *ah) +--- a/drivers/net/wireless/ath/ath12k/vendor.h ++++ b/drivers/net/wireless/ath/ath12k/vendor.h +@@ -20,6 +20,7 @@ enum qca_nl80211_vendor_subcmds { + QCA_NL80211_VENDOR_SUBCMD_TELEMETRY_SLA_THERSHOLD_CFG = 210, + QCA_NL80211_VENDOR_SUBCMD_TELEMETRY_SLA_SAMPLES_CFG = 211, + QCA_NL80211_VENDOR_SUBCMD_TELEMETRY_SLA_BREACH_DETECTION_CFG = 212, ++ QCA_NL80211_VENDOR_SUBCMD_SAWF_STREAMING_STATS = 213, + #endif /* CPTCFG_ATH12K_SAWF */ + }; + +@@ -105,6 +106,17 @@ enum qca_wlan_vendor_attr_telemetry_sawf + QCA_WLAN_VENDOR_TELEMETRY_SLA_THERSHOLD_CFG_AFTER_LAST - 1, + }; + ++enum ath12k_vendor_attr_sawf_streaming { ++ QCA_WLAN_VENDOR_ATTR_SAWF_STREAMING_INVALID = 0, ++ QCA_WLAN_VENDOR_ATTR_SAWF_STREAMING_BASIC_STATS = 1, ++ QCA_WLAN_VENDOR_ATTR_SAWF_STREAMING_EXTND_STATS = 2, ++ QCA_WLAN_VENDOR_ATTR_MLO_LINK_ID = 3, ++ /* keep last */ ++ QCA_WLAN_VENDOR_ATTR_SAWF_STREAMING_AFTER_LAST, ++ QCA_WLAN_VENDOR_ATTR_SAWF_STREAMING_MAX = ++ QCA_WLAN_VENDOR_ATTR_SAWF_STREAMING_AFTER_LAST - 1, ++}; ++ + #endif /* CPTCFG_ATH12K_SAWF */ + + int ath12k_vendor_register(struct ath12k_hw *ah); +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -2182,6 +2182,9 @@ void ath12k_dp_htt_htc_t2h_msg_handler(s + case HTT_T2H_MSG_TYPE_SAWF_DEF_QUEUES_MAP_REPORT_CONF: + ath12k_htt_sawf_def_q_map_report_handler(ab, skb); + break; ++ case HTT_T2H_MSG_TYPE_STREAMING_STATS_IND: ++ ath12k_htt_sawf_streaming_stats_ind_handler(ab, skb); ++ break; + #endif /* CPTCFG_ATH12K_SAWF */ + default: + ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "dp_htt event %d not handled\n", diff --git a/feeds/ipq95xx/mac80211/patches/qca/784-04-ath12k-Add-SAWF-tx-delay-stats-support.patch b/feeds/ipq95xx/mac80211/patches/qca/784-04-ath12k-Add-SAWF-tx-delay-stats-support.patch new file mode 100644 index 000000000..9383fdc45 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/784-04-ath12k-Add-SAWF-tx-delay-stats-support.patch @@ -0,0 +1,1186 @@ +From 97c64777f2c00b4967660a18afdfd7e43bda6ed2 Mon Sep 17 00:00:00 2001 +From: Tamizh Chelvam Raja +Date: Wed, 7 Jun 2023 11:14:57 +0530 +Subject: [PATCH] ath12k: Add SAWF tx delay stats support + +Signed-off-by: Tamizh Chelvam Raja +--- + drivers/net/wireless/ath/ath12k/core.h | 5 + + drivers/net/wireless/ath/ath12k/debugfs_sta.c | 317 ++++++++++++++++++ + drivers/net/wireless/ath/ath12k/dp.c | 5 + + drivers/net/wireless/ath/ath12k/dp.h | 1 + + drivers/net/wireless/ath/ath12k/dp_rx.c | 2 + + drivers/net/wireless/ath/ath12k/dp_tx.c | 17 +- + drivers/net/wireless/ath/ath12k/hal.c | 42 +++ + drivers/net/wireless/ath/ath12k/hal.h | 25 ++ + drivers/net/wireless/ath/ath12k/hal_tx.h | 2 + + drivers/net/wireless/ath/ath12k/sawf.c | 122 ++++++- + drivers/net/wireless/ath/ath12k/sawf.h | 25 +- + include/net/mac80211.h | 4 + + net/mac80211/tx.c | 1 + + 13 files changed, 563 insertions(+), 5 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -654,6 +654,7 @@ struct ath12k_link_sta { + u8 link_id; /* IEEE link id */ + u8 link_idx; /* for fw use only */ + u32 last_tx_pkt_bw; ++ u8 sawf_svc_id; + + /* For now the assoc link will be considered primary */ + bool is_assoc_link; +@@ -1014,6 +1015,10 @@ struct ath12k { + struct completion mvr_complete; + struct cfg80211_chan_def agile_chandef; + struct ath12k_mgmt_rx_reo_pdev_info rx_reo_pdev_ctx; ++ ++ u64 delta_tsf2; ++ u64 delta_tqm; ++ u64 mlo_tstamp_offset; + }; + + struct ath12k_band_cap { +@@ -1075,6 +1080,11 @@ struct ath12k_pdev { + struct mlo_timestamp timestamp; + }; + ++struct pmm_remap { ++ u32 base; ++ u32 size; ++}; ++ + struct cmem_remap { + u32 base; + u32 size; +@@ -1272,10 +1282,13 @@ struct ath12k_base { + void __iomem *mem; + void __iomem *mem_ce; + void __iomem *mem_cmem; ++ void __iomem *mem_pmm; + u32 ce_remap_base_addr; + u32 cmem_remap_base_addr; ++ u32 pmm_remap_base_addr; + bool ce_remap; + bool cmem_remap; ++ bool pmm_remap; + unsigned long mem_len; + + struct { +--- a/drivers/net/wireless/ath/ath12k/debugfs_sta.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs_sta.c +@@ -1506,6 +1506,363 @@ static const struct file_operations fops + .llseek = default_llseek, + }; + ++#ifdef CPTCFG_ATH12K_SAWF ++static int ath12k_fill_sawf_tx_delay_stats(struct ath12k_base *ab, struct ath12k_peer *peer, ++ char *buf, int len, int size, ++ u8 q_id, u8 tid) ++{ ++ struct ath12k_sawf_stats *sawf_stats; ++ struct sawf_tx_delay_stats *tx_delay_stats; ++ ++ lockdep_assert_held(&ab->base_lock); ++ ++ sawf_stats = &peer->sawf_stats; ++ if (!sawf_stats) ++ return 0; ++ ++ tx_delay_stats = &sawf_stats->tx_delay_stats[tid][q_id]; ++ ++ len += scnprintf(buf + len, size - len, "Delay Bins\n"); ++ len += scnprintf(buf + len, size - len, "Min %u\n", tx_delay_stats->delay_hist.min); ++ len += scnprintf(buf + len, size - len, "Max %u\n", tx_delay_stats->delay_hist.max); ++ len += scnprintf(buf + len, size - len, "Avg %u\n", tx_delay_stats->delay_hist.avg); ++ len += scnprintf(buf + len, size - len, "NWDelay moving avg %u\n", tx_delay_stats->nwdelay_avg); ++ len += scnprintf(buf + len, size - len, "SWDelay moving avg %u\n", tx_delay_stats->swdelay_avg); ++ len += scnprintf(buf + len, size - len, "HWDelay moving avg %u\n", tx_delay_stats->hwdelay_avg); ++ len += scnprintf(buf + len, size - len, "Delay Bound Success %llu\n", tx_delay_stats->success); ++ len += scnprintf(buf + len, size - len, "Delay Bound Failure %llu\n", tx_delay_stats->failure); ++ ++ return len; ++} ++ ++static ssize_t ath12k_dbg_sta_dump_sawf_tx_delay_stats(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ ++ struct ieee80211_link_sta *link_sta = file->private_data; ++ struct ieee80211_sta *sta = link_sta->sta; ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_sawf_peer_ctx *peer_ctx = NULL; ++ const int size = 2 * ATH12K_SAWF_STATS_SIZE; ++ struct ath12k_hw *ah = ahsta->ahvif->ah; ++ struct ath12k_sawf_ctx *sawf_ctx; ++ u8 q_id, tid, max_usr_def_q_sawf; ++ u8 link_id = link_sta->link_id; ++ struct ath12k_link_sta *arsta; ++ struct ath12k_peer *peer; ++ struct ath12k *ar; ++ int len = 0; ++ char *buf; ++ ++ mutex_lock(&ah->conf_mutex); ++ ++ if (!(BIT(link_id) & ahsta->links_map)) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } ++ ++ arsta = ahsta->link[link_id]; ++ ++ if (!arsta || !arsta->arvif->ar) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } ++ ++ ar = arsta->arvif->ar; ++ buf = kzalloc(size, GFP_KERNEL); ++ if (!buf) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOMEM; ++ } ++ ++ mutex_lock(&ar->conf_mutex); ++ spin_lock_bh(&ar->ab->base_lock); ++ ++ peer = ath12k_peer_find(ar->ab, arsta->arvif->vdev_id, arsta->addr); ++ if (!peer) { ++ ath12k_warn(ar->ab, "mac sta rc update failed to find peer %pM on vdev %i\n", ++ arsta->addr, arsta->arvif->vdev_id); ++ spin_unlock_bh(&ar->ab->base_lock); ++ len = -ENOENT; ++ goto unlock; ++ } ++ ++ peer_ctx = &peer->sawf_ctx_peer; ++ ++ sawf_ctx = ath12k_get_sawf_context(); ++ if (!sawf_ctx || !peer_ctx) { ++ spin_unlock_bh(&ar->ab->base_lock); ++ len = -EINVAL; ++ goto unlock; ++ } ++ ++ max_usr_def_q_sawf = sawf_ctx->max_msduq_per_tid - ++ sawf_ctx->default_msduq_per_tid; ++ ++ if (!arsta->sawf_svc_id) ++ goto dump_stats; ++ ++ for (tid = 0; tid < ATH12K_SAWF_MAX_TID_SUPPORT; tid++) { ++ for (q_id = 0; q_id < max_usr_def_q_sawf; q_id++) { ++ if (arsta->sawf_svc_id == peer_ctx->msduq_table[tid][q_id].svc_id) { ++ len = ath12k_fill_sawf_tx_delay_stats(ar->ab, peer, buf, len, size, q_id, tid); ++ goto exit; ++ } ++ } ++ } ++ ++dump_stats: ++ for (tid = 0; tid < ATH12K_SAWF_MAX_TID_SUPPORT; tid++) { ++ for (q_id = 0; q_id < max_usr_def_q_sawf; q_id++) ++ len = ath12k_fill_sawf_tx_delay_stats(ar->ab, peer, buf, len, size, q_id, tid); ++ } ++ ++exit: ++ spin_unlock_bh(&ar->ab->base_lock); ++ if (len > size) ++ len = size; ++ if (len) ++ len = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++unlock: ++ mutex_unlock(&ar->conf_mutex); ++ mutex_unlock(&ah->conf_mutex); ++ kfree(buf); ++ return len; ++} ++ ++static const struct file_operations fops_sawf_tx_delay_stats = { ++ .read = ath12k_dbg_sta_dump_sawf_tx_delay_stats, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++static int ath12k_fill_sawf_tx_stats(struct ath12k_base *ab, struct ath12k_peer *peer, ++ char *buf, int len, int size, ++ u8 q_id, u8 tid) ++{ ++ struct sawf_fw_mpdu_stats *svc_intval_stats; ++ struct sawf_fw_mpdu_stats *burst_size_stats; ++ struct ath12k_sawf_stats *sawf_stats; ++ struct sawf_tx_stats *tx_stats; ++ ++ lockdep_assert_held(&ab->base_lock); ++ ++ sawf_stats = &peer->sawf_stats; ++ if (!sawf_stats) ++ return 0; ++ ++ tx_stats = &sawf_stats->tx_stats[tid][q_id]; ++ ++ svc_intval_stats = &sawf_stats->tx_stats[tid][q_id].svc_intval_stats; ++ ++ burst_size_stats = &sawf_stats->tx_stats[tid][q_id].burst_size_stats; ++ ++ len += scnprintf(buf + len, size - len, "tx_succ_pkts: %u\n", ++ tx_stats->tx_success.num_pkts); ++ len += scnprintf(buf + len, size - len, "tx_succ_bytes: %llu\n", ++ tx_stats->tx_success.bytes); ++ len += scnprintf(buf + len, size - len, "tx_ingress_pkts: %u\n", ++ tx_stats->tx_ingress.num_pkts); ++ len += scnprintf(buf + len, size - len, "tx_ingress_bytes: %llu\n", ++ tx_stats->tx_ingress.bytes); ++ len += scnprintf(buf + len, size - len, "tx_remove_mpdu_pkts: %u\n", ++ tx_stats->dropped.fw_rem.num_pkts); ++ len += scnprintf(buf + len, size - len, "tx_remove_mpdu_bytes: %llu\n", ++ tx_stats->dropped.fw_rem.bytes); ++ len += scnprintf(buf + len, size - len, "tx_remove_tx_pkts: %u\n", ++ tx_stats->dropped.fw_rem_tx); ++ len += scnprintf(buf + len, size - len, "tx_remove_notx_pkts: %u\n", ++ tx_stats->dropped.fw_rem_notx); ++ len += scnprintf(buf + len, size - len, "tx_remove_aged_pkts: %u\n", ++ tx_stats->dropped.age_out); ++ len += scnprintf(buf + len, size - len, "tx_remove_fw_reason1: %u\n", ++ tx_stats->dropped.fw_reason1); ++ len += scnprintf(buf + len, size - len, "tx_remove_fw_reason2: %u\n", ++ tx_stats->dropped.fw_reason2); ++ len += scnprintf(buf + len, size - len, "tx_remove_fw_reason3: %u\n", ++ tx_stats->dropped.fw_reason3); ++ len += scnprintf(buf + len, size - len, "tx_failed: %u\n", ++ tx_stats->tx_failed); ++ len += scnprintf(buf + len, size - len, "queue_depth: %u\n", ++ tx_stats->queue_depth); ++ ++ if (svc_intval_stats) { ++ len += scnprintf(buf + len, size - len, "Service intvl success_cnt : %llu\n", ++ svc_intval_stats->success_cnt); ++ len += scnprintf(buf + len, size - len, "Service intvl failure_cnt : %llu\n", ++ svc_intval_stats->failure_cnt); ++ } ++ ++ if (burst_size_stats) { ++ len += scnprintf(buf + len, size - len, "Burst Size success_cnt : %llu\n", ++ burst_size_stats->success_cnt); ++ len += scnprintf(buf + len, size - len, "Burst Size failure_cnt : %llu\n", ++ burst_size_stats->failure_cnt); ++ } ++ ++ return len; ++} ++ ++static ssize_t ath12k_dbg_sta_dump_sawf_tx_stats(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ ++ struct ieee80211_link_sta *link_sta = file->private_data; ++ struct ieee80211_sta *sta = link_sta->sta; ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_sawf_peer_ctx *peer_ctx = NULL; ++ const int size = 2 * ATH12K_SAWF_STATS_SIZE; ++ struct ath12k_hw *ah = ahsta->ahvif->ah; ++ struct ath12k_sawf_ctx *sawf_ctx; ++ u8 q_id, tid, max_usr_def_q_sawf; ++ u8 link_id = link_sta->link_id; ++ struct ath12k_link_sta *arsta; ++ struct ath12k_peer *peer; ++ struct ath12k *ar; ++ int len = 0; ++ char *buf; ++ ++ mutex_lock(&ah->conf_mutex); ++ ++ if (!(BIT(link_id) & ahsta->links_map)) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } ++ ++ arsta = ahsta->link[link_id]; ++ ++ if (!arsta || !arsta->arvif->ar) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } ++ ++ ar = arsta->arvif->ar; ++ buf = kzalloc(size, GFP_KERNEL); ++ if (!buf) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOMEM; ++ } ++ ++ mutex_lock(&ar->conf_mutex); ++ spin_lock_bh(&ar->ab->base_lock); ++ ++ peer = ath12k_peer_find(ar->ab, arsta->arvif->vdev_id, arsta->addr); ++ if (!peer) { ++ ath12k_warn(ar->ab, "mac sta rc update failed to find peer %pM on vdev %i\n", ++ arsta->addr, arsta->arvif->vdev_id); ++ spin_unlock_bh(&ar->ab->base_lock); ++ len = -ENOENT; ++ goto unlock; ++ } ++ ++ peer_ctx = &peer->sawf_ctx_peer; ++ ++ sawf_ctx = ath12k_get_sawf_context(); ++ if (!sawf_ctx || !peer_ctx) { ++ spin_unlock_bh(&ar->ab->base_lock); ++ len = -EINVAL; ++ goto unlock; ++ } ++ ++ max_usr_def_q_sawf = sawf_ctx->max_msduq_per_tid - ++ sawf_ctx->default_msduq_per_tid; ++ ++ if (!arsta->sawf_svc_id) ++ goto dump_stats; ++ ++ for (tid = 0; tid < ATH12K_SAWF_MAX_TID_SUPPORT; tid++) { ++ for (q_id = 0; q_id < max_usr_def_q_sawf; q_id++) { ++ if (arsta->sawf_svc_id == peer_ctx->msduq_table[tid][q_id].svc_id) { ++ len = ath12k_fill_sawf_tx_stats(ar->ab, peer, buf, len, size, q_id, tid); ++ goto exit; ++ } ++ } ++ } ++ ++dump_stats: ++ for (tid = 0; tid < ATH12K_SAWF_MAX_TID_SUPPORT; tid++) { ++ for (q_id = 0; q_id < max_usr_def_q_sawf; q_id++) ++ len = ath12k_fill_sawf_tx_stats(ar->ab, peer, buf, len, size, q_id, tid); ++ } ++ ++exit: ++ spin_unlock_bh(&ar->ab->base_lock); ++ if (len > size) ++ len = size; ++ if (len) ++ len = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ ++unlock: ++ mutex_unlock(&ar->conf_mutex); ++ mutex_unlock(&ah->conf_mutex); ++ kfree(buf); ++ return len; ++} ++ ++static const struct file_operations fops_sawf_tx_stats = { ++ .read = ath12k_dbg_sta_dump_sawf_tx_stats, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++static ssize_t ath12k_dbg_sta_set_svc_id(struct file *file, ++ const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ieee80211_link_sta *link_sta = file->private_data; ++ struct ieee80211_sta *sta = link_sta->sta; ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_hw *ah = ahsta->ahvif->ah; ++ u8 link_id = link_sta->link_id; ++ struct ath12k_link_sta *arsta; ++ struct ath12k *ar; ++ int ret, svc_id; ++ ++ ret = kstrtoint_from_user(buf, count, 0, &svc_id); ++ if (ret) ++ return ret; ++ ++ if (svc_id && (svc_id < ATH12K_SAWF_SVC_CLASS_MIN || ++ svc_id > ATH12K_SAWF_SVC_CLASS_MAX)) ++ return -EINVAL; ++ ++ mutex_lock(&ah->conf_mutex); ++ ++ if (!(BIT(link_id) & ahsta->links_map)) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } ++ ++ arsta = ahsta->link[link_id]; ++ ++ if (!arsta || !arsta->arvif->ar) { ++ mutex_unlock(&ah->conf_mutex); ++ return -ENOENT; ++ } ++ ++ ar = arsta->arvif->ar; ++ ++ spin_lock_bh(&ar->ab->base_lock); ++ arsta->sawf_svc_id = svc_id; ++ spin_unlock_bh(&ar->ab->base_lock); ++ mutex_unlock(&ah->conf_mutex); ++ ++ ret = count; ++ return ret; ++} ++ ++static const struct file_operations fops_svc_id = { ++ .write = ath12k_dbg_sta_set_svc_id, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++#endif /* CPTCFG_ATH12K_SAWF */ ++ + void ath12k_debugfs_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, struct dentry *dir) + { +@@ -1558,5 +1915,15 @@ void ath12k_debugfs_link_sta_op_add(stru + debugfs_create_file("htt_peer_stats_reset", 0600, dir, link_sta, + &fops_htt_peer_stats_reset); + ++#ifdef CPTCFG_ATH12K_SAWF ++ if (ath12k_debugfs_is_sawf_stats_enabled(ar)) { ++ debugfs_create_file("svc_id", 0400, dir, link_sta, ++ &fops_svc_id); ++ debugfs_create_file("sawf_tx_stats", 0400, dir, link_sta, ++ &fops_sawf_tx_stats); ++ debugfs_create_file("sawf_tx_delay_stats", 0400, dir, link_sta, ++ &fops_sawf_tx_delay_stats); ++ } ++#endif + mutex_unlock(&ah->conf_mutex); + } +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -325,6 +325,7 @@ struct ath12k_tx_desc_info { + u8 mac_id; + u8 pool_id; + u8 recycler_fast_xmit; ++ ktime_t timestamp; + }; + + #ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -1960,6 +1960,10 @@ static void ath12k_htt_mlo_offset_event_ + pdev->timestamp.mlo_comp_clks = __le32_to_cpu(msg->mlo_comp_clks); + pdev->timestamp.mlo_comp_timer = __le32_to_cpu(msg->mlo_comp_timer); + ++ ar->mlo_tstamp_offset = ((u64)pdev->timestamp.mlo_offset_hi << 32 | pdev->timestamp.mlo_offset_lo); ++ if (ab->hw_params->hal_ops->hal_get_tsf2_scratch_reg) ++ ab->hw_params->hal_ops->hal_get_tsf2_scratch_reg(ab, ar->lmac_id, &ar->delta_tsf2); ++ + spin_unlock_bh(&ar->data_lock); + } + +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -276,10 +276,11 @@ int ath12k_dp_tx_direct(struct ath12k_li + void *hal_tcl_desc; + struct hal_tcl_data_cmd tcl_desc; + u8 hal_ring_id, ring_id; +- dma_addr_t paddr; + #ifdef CPTCFG_ATH12K_SAWF ++ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ath12k_peer *peer; + #endif ++ dma_addr_t paddr; + int ret; + int len = skb->fast_xmit ? 256 : skb->len; + +@@ -309,6 +310,7 @@ int ath12k_dp_tx_direct(struct ath12k_li + tx_desc->skb = skb; + tx_desc->mac_id = arvif->pdev_idx; + tx_desc->recycler_fast_xmit = 0; ++ tx_desc->timestamp = ktime_get_real(); + + /* the edma driver uses this flags to optimize the cache invalidation */ + skb->fast_recycled = 1; +@@ -374,6 +376,12 @@ int ath12k_dp_tx_direct(struct ath12k_li + ath12k_sawf_tx_enqueue_peer_stats(ab, peer, msduq_id, len); + spin_unlock_bh(&ab->base_lock); + } ++ /* Store the NWDELAY to skb->mark which can be fetched ++ * during tx completion ++ */ ++ if (info->sawf.nw_delay > SAWF_NW_DELAY_MAX) ++ info->sawf.nw_delay = SAWF_NW_DELAY_MAX; ++ skb->mark = (SAWF_VALID_TAG << SAWF_TAG_SHIFT) | (info->sawf.nw_delay << SAWF_NW_DELAY_SHIFT) | msduq_id; + } + #endif + memcpy(hal_tcl_desc, &tcl_desc, sizeof(tcl_desc)); +@@ -405,6 +413,9 @@ int ath12k_dp_tx(struct ath12k *ar, stru + struct ath12k_peer *peer; + struct hal_tx_info ti = {0}; + struct ath12k_tx_desc_info *tx_desc = NULL; ++#ifdef CPTCFG_ATH12K_SAWF ++ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); ++#endif + struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB(skb); + struct hal_tx_msdu_ext_desc *msg; + struct sk_buff *skb_ext_desc; +@@ -583,6 +594,7 @@ int ath12k_dp_tx(struct ath12k *ar, stru + tx_desc->skb = skb; + tx_desc->mac_id = ar->pdev_idx; + tx_desc->recycler_fast_xmit = 0; ++ tx_desc->timestamp = ktime_get_real(); + ti.desc_id = tx_desc->desc_id; + ti.data_len = skb->len - ti.pkt_offset; + skb_cb->pkt_offset = ti.pkt_offset; +@@ -675,6 +687,12 @@ int ath12k_dp_tx(struct ath12k *ar, stru + ath12k_sawf_tx_enqueue_peer_stats(ab, peer, msduq_id, ti.data_len); + spin_unlock_bh(&ab->base_lock); + } ++ /* Store the NWDELAY to skb->mark which can be fetched ++ * during tx completion ++ */ ++ if (info->sawf.nw_delay > SAWF_NW_DELAY_MAX) ++ info->sawf.nw_delay = SAWF_NW_DELAY_MAX; ++ skb->mark = (SAWF_VALID_TAG << SAWF_TAG_SHIFT) | (info->sawf.nw_delay << SAWF_NW_DELAY_SHIFT) | msduq_id; + } + #endif /* CPTCFG_ATH12K_SAWF */ + +@@ -773,6 +791,9 @@ static inline void ath12k_dp_tx_status_p + ts->peer_id = FIELD_GET(HAL_WBM_RELEASE_TX_INFO3_PEER_ID, desc->info3); + ts->flags = FIELD_GET(HAL_WBM_RELEASE_TX_INFO2_FIRST_MSDU, desc->info2) | + FIELD_GET(HAL_WBM_RELEASE_TX_INFO2_LAST_MSDU, desc->info2); ++ ts->buffer_timestamp = FIELD_GET(HAL_WBM_RELEASE_TX_INFO2_BUFFER_TIMESTAMP, ++ desc->info2); ++ ts->tsf = desc->rate_stats.tsf; + } + + static void +@@ -781,7 +802,7 @@ ath12k_dp_tx_htt_tx_complete_buf(struct + struct dp_tx_ring *tx_ring, + struct ath12k_dp_htt_wbm_tx_status *ts, + struct sk_buff *skb_ext_desc, u8 mac_id, +- void *desc) ++ void *desc, ktime_t timestamp) + { + struct ieee80211_tx_info *info; + struct ath12k_skb_cb *skb_cb; +@@ -888,7 +909,7 @@ ath12k_dp_tx_htt_tx_complete_buf(struct + "dp_tx: failed to find the peer with peer_id %d\n", + ts_status.peer_id); + else +- ath12k_sawf_stats_update(ar, msdu, &ts, peer); ++ ath12k_sawf_stats_update(ar, msdu, &ts, peer, timestamp); + spin_unlock_bh(&ab->base_lock); + } + +@@ -903,7 +924,8 @@ ath12k_dp_tx_process_htt_tx_complete(str + void *desc, u8 mac_id, + struct sk_buff *msdu, + struct dp_tx_ring *tx_ring, +- struct sk_buff *skb_ext_desc) ++ struct sk_buff *skb_ext_desc, ++ ktime_t timestamp) + { + struct htt_tx_wbm_completion *status_desc; + struct ath12k_dp_htt_wbm_tx_status ts = {0}; +@@ -923,7 +945,7 @@ ath12k_dp_tx_process_htt_tx_complete(str + ts.acked = (htt_status == HAL_WBM_REL_HTT_TX_COMP_STATUS_OK); + ts.ack_rssi = u32_get_bits(status_desc->info2, + HTT_TX_WBM_COMP_INFO2_ACK_RSSI); +- ath12k_dp_tx_htt_tx_complete_buf(ab, msdu, tx_ring, &ts, skb_ext_desc, mac_id, desc); ++ ath12k_dp_tx_htt_tx_complete_buf(ab, msdu, tx_ring, &ts, skb_ext_desc, mac_id, desc, timestamp); + + break; + case HAL_WBM_REL_HTT_TX_COMP_STATUS_REINJ: +@@ -1074,7 +1096,7 @@ static void ath12k_dp_tx_complete_msdu(s + struct sk_buff *msdu, + struct hal_wbm_release_ring *tx_status, + enum hal_wbm_rel_src_module buf_rel_source, +- int ring) ++ int ring, ktime_t timestamp) + { + struct ieee80211_tx_status status = { 0 }; + struct ieee80211_rate_status status_rate = { 0 }; +@@ -1160,7 +1182,7 @@ static void ath12k_dp_tx_complete_msdu(s + "dp_tx: failed to find the peer with peer_id %d\n", + ts.peer_id); + else +- ath12k_sawf_stats_update(ar, msdu, &ts, peer); ++ ath12k_sawf_stats_update(ar, msdu, &ts, peer, timestamp); + spin_unlock_bh(&ab->base_lock); + } + dev_kfree_skb_any(msdu); +@@ -1234,7 +1256,7 @@ static void ath12k_dp_tx_complete_msdu(s + } + + if (unlikely(ath12k_debugfs_is_sawf_stats_enabled(ar))) +- ath12k_sawf_stats_update(ar, msdu, &ts, peer); ++ ath12k_sawf_stats_update(ar, msdu, &ts, peer, timestamp); + + spin_unlock_bh(&ab->base_lock); + +@@ -1398,6 +1420,7 @@ int ath12k_dp_tx_completion_handler(stru + int orig_budget = budget; + struct hal_wbm_completion_ring_tx *tx_status; + enum hal_wbm_rel_src_module buf_rel_source; ++ ktime_t timestamp; + enum hal_wbm_tqm_rel_reason rel_status; + struct sk_buff_head free_list_head; + int recycler_fast_xmit; +@@ -1443,6 +1466,7 @@ int ath12k_dp_tx_completion_handler(stru + mac_id = tx_desc->mac_id; + recycler_fast_xmit = tx_desc->recycler_fast_xmit; + skb_ext_desc = tx_desc->skb_ext_desc; ++ timestamp = tx_desc->timestamp; + /* Release descriptor as soon as extracting necessary info + * to reduce contention + */ +@@ -1460,7 +1484,8 @@ int ath12k_dp_tx_completion_handler(stru + (void *)tx_status, + mac_id, msdu, + tx_ring, +- skb_ext_desc); ++ skb_ext_desc, ++ timestamp); + continue; + } + ar = ab->pdevs[mac_id].ar; +@@ -1516,7 +1541,7 @@ int ath12k_dp_tx_completion_handler(stru + + ath12k_dp_tx_complete_msdu(ar, msdu, tx_status, + buf_rel_source, +- tx_ring->tcl_data_ring_id); ++ tx_ring->tcl_data_ring_id, timestamp); + } + } + ath12k_hal_srng_access_umac_dst_ring_end_nolock(status_ring); +--- a/drivers/net/wireless/ath/ath12k/hal.c ++++ b/drivers/net/wireless/ath/ath12k/hal.c +@@ -513,6 +513,56 @@ static u8 ath12k_hw_qcn9274_rx_desc_get_ + RX_MSDU_END_64_TLV_SRC_LINK_ID); + } + ++#define PMM_REG_OFFSET 4 ++ ++static void ath12k_hal_get_tsf_reg(u8 mac_id, enum hal_scratch_reg_enum *tsf_enum_low, ++ enum hal_scratch_reg_enum *tsf_enum_hi) ++{ ++ if (!mac_id) { ++ *tsf_enum_low = PMM_MAC0_TSF2_OFFSET_LO_US; ++ *tsf_enum_hi = PMM_MAC0_TSF2_OFFSET_HI_US; ++ } else if (mac_id == 1) { ++ *tsf_enum_low = PMM_MAC1_TSF2_OFFSET_LO_US; ++ *tsf_enum_hi = PMM_MAC1_TSF2_OFFSET_HI_US; ++ } ++} ++ ++static void ath12k_hal_qcn9274_get_tsf2_scratch_reg(struct ath12k_base *ab, ++ u8 mac_id, u64 *value) ++{ ++ enum hal_scratch_reg_enum enum_lo, enum_hi; ++ u32 offset_lo, offset_hi; ++ ++ ath12k_hal_get_tsf_reg(mac_id, &enum_lo, &enum_hi); ++ ++ if (ab->hif.ops->pmm_read32) { ++ offset_lo = ath12k_hif_pmm_read32(ab, ATH12K_PPT_ADDR_OFFSET(enum_lo)); ++ offset_hi = ath12k_hif_pmm_read32(ab, ATH12K_PPT_ADDR_OFFSET(enum_hi)); ++ } else { ++ offset_lo = ath12k_hif_read32(ab, PMM_REG_BASE_QCN9224 + ATH12K_PPT_ADDR_OFFSET(enum_lo)); ++ offset_hi = ath12k_hif_read32(ab, PMM_REG_BASE_QCN9224 + ATH12K_PPT_ADDR_OFFSET(enum_hi)); ++ } ++ ++ *value = ((u64)(offset_hi) << 32 | offset_lo); ++} ++ ++static void ath12k_hal_qcn9274_get_tqm_scratch_reg(struct ath12k_base *ab, u64 *value) ++{ ++ u32 offset_lo, offset_hi; ++ ++ if (ab->hif.ops->pmm_read32) { ++ offset_lo = ath12k_hif_pmm_read32(ab, ATH12K_PPT_ADDR_OFFSET(PMM_TQM_CLOCK_OFFSET_LO_US)); ++ offset_hi = ath12k_hif_pmm_read32(ab, ATH12K_PPT_ADDR_OFFSET(PMM_TQM_CLOCK_OFFSET_HI_US)); ++ } else { ++ offset_lo = ath12k_hif_read32(ab, ++ PMM_REG_BASE_QCN9224 + ATH12K_PPT_ADDR_OFFSET(PMM_TQM_CLOCK_OFFSET_LO_US)); ++ offset_hi = ath12k_hif_read32(ab, ++ PMM_REG_BASE_QCN9224 + ATH12K_PPT_ADDR_OFFSET(PMM_TQM_CLOCK_OFFSET_HI_US)); ++ } ++ ++ *value = ((u64)(offset_hi) << 32 | offset_lo); ++} ++ + static int ath12k_hal_srng_create_config_qcn9274(struct ath12k_base *ab) + { + struct ath12k_hal *hal = &ab->hal; +@@ -777,6 +827,8 @@ const struct hal_ops hal_qcn9274_ops = { + .rx_get_desc_info = ath12k_hw_qcn9274_get_rx_desc_info, + .rx_get_desc_msdulen_l3pad = ath12k_hw_qcn9274_get_rx_msdulen_l3pad, + .rx_desc_get_first_last_msdu = ath12k_hw_qcn9274_get_rx_first_last_msdu, ++ .hal_get_tsf2_scratch_reg = ath12k_hal_qcn9274_get_tsf2_scratch_reg, ++ .hal_get_tqm_scratch_reg = ath12k_hal_qcn9274_get_tqm_scratch_reg, + }; + + static bool ath12k_hw_wcn7850_rx_desc_get_first_msdu(struct hal_rx_desc *desc) +--- a/drivers/net/wireless/ath/ath12k/hal.h ++++ b/drivers/net/wireless/ath/ath12k/hal.h +@@ -434,6 +434,9 @@ struct ath12k_dp_rx_info; + #define HAL_IPQ5332_CMEM_SIZE 0x40000 + #define HAL_IPQ5332_CMEM_BASE 0x100000 + ++#define HAL_IPQ5332_PMM_REG_BASE 0xCB500FC ++#define HAL_IPQ5332_PMM_SIZE 0x100 ++ + enum hal_srng_ring_id { + HAL_SRNG_RING_ID_REO2SW0 = 0, + HAL_SRNG_RING_ID_REO2SW1, +@@ -605,6 +608,28 @@ enum hal_ring_type { + HAL_MAX_RING_TYPES, + }; + ++#define PMM_REG_BASE_QCN9224 0xB500FC ++ ++enum hal_scratch_reg_enum { ++ PMM_QTIMER_GLOBAL_OFFSET_LO_US, ++ PMM_QTIMER_GLOBAL_OFFSET_HI_US, ++ PMM_MAC0_TSF1_OFFSET_LO_US, ++ PMM_MAC0_TSF1_OFFSET_HI_US, ++ PMM_MAC0_TSF2_OFFSET_LO_US, ++ PMM_MAC0_TSF2_OFFSET_HI_US, ++ PMM_MAC1_TSF1_OFFSET_LO_US, ++ PMM_MAC1_TSF1_OFFSET_HI_US, ++ PMM_MAC1_TSF2_OFFSET_LO_US, ++ PMM_MAC1_TSF2_OFFSET_HI_US, ++ PMM_MLO_OFFSET_LO_US, ++ PMM_MLO_OFFSET_HI_US, ++ PMM_TQM_CLOCK_OFFSET_LO_US, ++ PMM_TQM_CLOCK_OFFSET_HI_US, ++ PMM_Q6_CRASH_REASON, ++ PMM_SCRATCH_TWT_OFFSET, ++ PMM_PMM_REG_MAX ++}; ++ + #define WINDOW_RANGE_MASK GENMASK(18, 0) + #define HAL_RX_MAX_BA_WINDOW 256 + +@@ -1164,6 +1189,9 @@ struct hal_ops { + struct ath12k_dp_rx_info *info); + void (*rx_desc_get_first_last_msdu)(struct hal_rx_desc *desc, + struct ath12k_dp_rx_info *info); ++ void (*hal_get_tsf2_scratch_reg)(struct ath12k_base *ab, u8 mac_id, ++ u64 *value); ++ void (*hal_get_tqm_scratch_reg)(struct ath12k_base *ab, u64 *value); + }; + + extern const struct hal_ops hal_qcn9274_ops; +--- a/drivers/net/wireless/ath/ath12k/hal_tx.h ++++ b/drivers/net/wireless/ath/ath12k/hal_tx.h +@@ -64,6 +64,8 @@ struct hal_tx_status { + u8 tid; + u16 peer_id; + u32 rate_stats; ++ u32 buffer_timestamp; ++ u32 tsf; + }; + + #define HAL_TX_PHY_DESC_INFO0_BF_TYPE GENMASK(17, 16) +--- a/drivers/net/wireless/ath/ath12k/sawf.c ++++ b/drivers/net/wireless/ath/ath12k/sawf.c +@@ -269,6 +269,25 @@ bool ath12k_disable_svc_class(u8 svc_id) + return true; + } + ++struct ath12k_sawf_svc_params *ath12k_get_svc_class_params(u8 svc_id) ++{ ++ struct ath12k_sawf_svc_params *sawf_svc_class; ++ ++ if (!sawf_ctx) { ++ ath12k_err(NULL, "SAWF context unavailable\n"); ++ return NULL; ++ } ++ ++ if (!ath12k_svc_id_configured(svc_id)) { ++ ath12k_warn(NULL, "Serive id not available\n"); ++ return NULL; ++ } ++ ++ sawf_svc_class = &sawf_ctx->svc_classes[SVC_INDEX(svc_id)]; ++ ++ return sawf_svc_class; ++} ++ + /* When fimware crash occurs/simulated with firmware recovery + * enabled, the service class records in the driver will be sent + * to the crashed chip for configuring in the firmware. +@@ -1309,16 +1328,73 @@ void ath12k_sawf_tx_enqueue_peer_stats(s + return; + } + ++#define HW_TX_DELAY_MAX 0x1000000 ++ ++#define TX_COMPL_SHIFT_BUFFER_TIMESTAMP_US 10 ++#define HW_TX_DELAY_MASK 0x1FFFFFFF ++#define TX_COMPL_BUFFER_TSTAMP_US(TSTAMP) \ ++ (((TSTAMP) << TX_COMPL_SHIFT_BUFFER_TIMESTAMP_US) & \ ++ HW_TX_DELAY_MASK) ++ ++#define ATH12K_DP_SAWF_DELAY_BOUND_MS_MULTIPLER 1000 ++#define ATH12K_MOV_AVG_PKT_WIN 10 ++ ++void ath12k_sawf_compute_hw_delay(struct ath12k *ar, struct hal_tx_status *ts, ++ u32 *hw_delay) ++{ ++ u32 msdu_tqm_enqueue_tstamp_us, final_msdu_tqm_enqueue_tstamp_us; ++ u32 msdu_compl_tsf_tstamp_us, final_msdu_compl_tsf_tstamp_us; ++ u32 delta_tsf2, delta_tqm; ++ ++ ++ msdu_tqm_enqueue_tstamp_us = ++ TX_COMPL_BUFFER_TSTAMP_US(ts->buffer_timestamp); ++ msdu_compl_tsf_tstamp_us = ts->tsf; ++ delta_tsf2 = ar->mlo_tstamp_offset - ar->delta_tsf2; ++ delta_tqm = ar->mlo_tstamp_offset - ar->delta_tqm; ++ ++ final_msdu_tqm_enqueue_tstamp_us = ++ (msdu_tqm_enqueue_tstamp_us + delta_tqm) & HW_TX_DELAY_MASK; ++ final_msdu_compl_tsf_tstamp_us = ++ (msdu_compl_tsf_tstamp_us + delta_tsf2) & HW_TX_DELAY_MASK; ++ ++ *hw_delay = (final_msdu_compl_tsf_tstamp_us - ++ final_msdu_tqm_enqueue_tstamp_us) & HW_TX_DELAY_MASK; ++} ++ ++#define ATH12K_HIST_AVG_DIV 2 ++ ++void ath12k_update_hist_stats(struct ath12k_delay_hist_stats *hist_stats, u32 value) ++{ ++ if (!hist_stats->min || value < hist_stats->min) ++ hist_stats->min = value; ++ ++ if (value > hist_stats->max) ++ hist_stats->max = value; ++ ++ if (unlikely(!hist_stats->avg)) ++ hist_stats->avg = value; ++ else ++ hist_stats->avg = (hist_stats->avg + value) / ATH12K_HIST_AVG_DIV; ++ ++} ++ + void ath12k_sawf_stats_update(struct ath12k *ar, struct sk_buff *skb, + struct hal_tx_status *ts, +- struct ath12k_peer *peer) ++ struct ath12k_peer *peer, ktime_t timestamp) + { ++ struct ath12k_sawf_peer_ctx *peer_ctx = &peer->sawf_ctx_peer; ++ struct ath12k_sawf_svc_params *svc_class_param; ++ struct sawf_tx_delay_stats *tx_delay_stats; + struct ath12k_sawf_stats *sawf_stats; ++ u32 hw_delay, sw_delay, nw_delay, pkt_win; ++ u64 entry_ts, enqueue_timestamp; + struct ath12k_base *ab = ar->ab; + struct sawf_tx_stats *tx_stats; + u32 msduq_id, len, q_id, tid; ++ u8 svc_id; + +- if (!ts) ++ if (!ts || !peer_ctx) + return; + + if (u32_get_bits(skb->mark, SAWF_TAG_ID) != SAWF_VALID_TAG) +@@ -1385,5 +1461,50 @@ void ath12k_sawf_stats_update(struct ath + tx_stats->queue_depth--; + + latency_stats_update: ++ ++ tx_delay_stats = &sawf_stats->tx_delay_stats[tid][q_id]; ++ ++ ath12k_sawf_compute_hw_delay(ar, ts, &hw_delay); ++ if (hw_delay > HW_TX_DELAY_MAX) ++ return; ++ ++ tx_delay_stats->num_pkt++; ++ tx_delay_stats->hwdelay_win_total += hw_delay; ++ ath12k_update_hist_stats(&tx_delay_stats->delay_hist, hw_delay); ++ nw_delay = u32_get_bits(skb->mark, SAWF_NW_DELAY); ++ tx_delay_stats->nwdelay_win_total += nw_delay; ++ ++ enqueue_timestamp = ktime_to_us(timestamp); ++ entry_ts = ktime_to_us(skb_get_ktime(skb)); ++ ++ if (!enqueue_timestamp) ++ sw_delay = 0; ++ else ++ sw_delay = (u32) (enqueue_timestamp - entry_ts); ++ tx_delay_stats->swdelay_win_total += sw_delay; ++ ++ if (!(tx_delay_stats->num_pkt % pkt_win)) { ++ tx_delay_stats->nwdelay_avg = div_u64(tx_delay_stats->nwdelay_win_total, ++ pkt_win); ++ tx_delay_stats->swdelay_avg = div_u64(tx_delay_stats->swdelay_win_total, ++ pkt_win); ++ tx_delay_stats->hwdelay_avg = div_u64(tx_delay_stats->hwdelay_win_total, ++ pkt_win); ++ ++ tx_delay_stats->nwdelay_win_total = 0; ++ tx_delay_stats->swdelay_win_total = 0; ++ tx_delay_stats->hwdelay_win_total = 0; ++ } ++ ++ svc_id = peer_ctx->msduq_table[tid][q_id].svc_id; ++ svc_class_param = ath12k_get_svc_class_params(svc_id); ++ ++ if(svc_class_param) { ++ if (hw_delay > (svc_class_param->delay_bound * ++ ATH12K_DP_SAWF_DELAY_BOUND_MS_MULTIPLER)) ++ tx_delay_stats->failure++; ++ else ++ tx_delay_stats->success++; ++ } + return; + } +--- a/drivers/net/wireless/ath/ath12k/sawf.h ++++ b/drivers/net/wireless/ath/ath12k/sawf.h +@@ -22,12 +22,16 @@ struct hal_tx_status; + ** SAWF_metadata related information. + **/ + #define SAWF_VALID_TAG 0xAA ++#define SAWF_TAG_SHIFT 0x18 + + /* Skb mark for SAWF */ + #define SAWF_MSDUQ_ID GENMASK(5, 0) + #define SAWF_PEER_ID GENMASK(15, 6) + #define SAWF_SERVICE_CLASS_ID GENMASK(23, 16) + #define SAWF_TAG_ID GENMASK(31, 24) ++#define SAWF_NW_DELAY GENMASK(23, 6) ++#define SAWF_NW_DELAY_SHIFT 0x6 ++#define SAWF_NW_DELAY_MAX 0x3FFFF + + #define TID_FROM_Q_ID GENMASK(2, 0) + #define FLOW_OVERRIDE_FROM_Q_ID BIT(3) +@@ -100,6 +104,8 @@ struct hal_tx_status; + #define ATH12K_SAWF_MIN_MSDU_LOSS_RATE 0 + #define ATH12K_SAWF_MAX_MSDU_LOSS_RATE 10000 + ++#define ATH12K_SAWF_STATS_SIZE 4096 ++ + enum SAWF_SVC_PARAM_DEFAULTS { + SAWF_SVC_PARAM_DEFAULT_MIN_THRUPUT = 0, + SAWF_SVC_PARAM_DEFAULT_MAX_THRUPUT = 0xffffffff, +@@ -536,6 +542,46 @@ struct sawf_tx_stats { + }; + + /** ++ * struct ath12k_delay_hist_stats - Histogram of a stats ++ * @max: Max frequency ++ * @min: Minimum frequency ++ * @avg: Average frequency ++ */ ++ ++struct ath12k_delay_hist_stats { ++ int max; ++ int min; ++ int avg; ++}; ++ ++/** ++ * struct sawf_tx_delay_stats- sawf Tx-delay stats ++ * @delay_hist: histogram for various delay-buckets ++ * @nwdelay_avg: moving average for nwdelay ++ * @swdelay_avg: moving average for swdelay ++ * @hwdelay_avg: moving average for hwdelay ++ * @num_pkt: count of pkts for which delay is calculated ++ * @nwdelay_win_total: total nwdelay for a window ++ * @swdelay_win_total: total swdelay for a window ++ * @hwdelay_win_total: total hwdelay for a window ++ * @success: count of pkts that met delay-bound ++ * @failure: count of pkts that did not meet delay-bound ++ */ ++ ++struct sawf_tx_delay_stats { ++ struct ath12k_delay_hist_stats delay_hist; ++ ++ u32 nwdelay_avg; ++ u32 swdelay_avg; ++ u32 hwdelay_avg; ++ u32 num_pkt; ++ u64 nwdelay_win_total; ++ u64 swdelay_win_total; ++ u64 hwdelay_win_total; ++ u64 success; ++ u64 failure; ++}; ++/** + * sawf_stats - sawf stats + * @delay: delay stats per host MSDU queue + * @tx_stats: Tx stats per host MSDU queue +@@ -543,6 +589,7 @@ struct sawf_tx_stats { + */ + struct ath12k_sawf_stats { + struct sawf_tx_stats tx_stats[ATH12K_SAWF_MAX_TID_SUPPORT][MAX_Q_PER_TID]; ++ struct sawf_tx_delay_stats tx_delay_stats[ATH12K_SAWF_MAX_TID_SUPPORT][MAX_Q_PER_TID]; + }; + + /* MSG_TYPE => HTT_H2T_MSG_TYPE_STREAMING_STATS_REQ +@@ -735,7 +782,7 @@ void ath12k_htt_sawf_def_q_map_report_ha + struct sk_buff *skb); + void ath12k_sawf_stats_update(struct ath12k *ar, struct sk_buff *skb, + struct hal_tx_status *ts, +- struct ath12k_peer *peer); ++ struct ath12k_peer *peer, ktime_t timestamp); + void ath12k_sawf_tx_enqueue_peer_stats(struct ath12k_base *ab, + struct ath12k_peer *peer, + u32 msduq_id, u32 len); +@@ -760,7 +807,8 @@ static inline void ath12k_sawf_deinit(st + + static inline void ath12k_sawf_stats_update(struct ath12k *ar, struct sk_buff *skb, + struct hal_tx_status *ts, +- struct ath12k_peer *peer) ++ struct ath12k_peer *peer, ++ ktime_t timestamp) + { + return; + } +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -1230,6 +1230,10 @@ struct ieee80211_tx_info { + u8 pad[36]; + u32 tx_start_time; + } latency; ++ struct { ++ u8 pad[36]; ++ u32 nw_delay; ++ } sawf; + }; + }; + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -4419,6 +4419,7 @@ void __ieee80211_subif_start_xmit(struct + } + + info = IEEE80211_SKB_CB(skb); ++ info->sawf.nw_delay = (u32) ktime_to_us(net_timedelta(skb->tstamp)); + if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) { + if (sta) + key = rcu_dereference(sta->ptk[sta->ptk_idx]); +@@ -4742,6 +4743,7 @@ static void ieee80211_8023_xmit(struct i + info = IEEE80211_SKB_CB(skb); + memset(info, 0, sizeof(*info)); + info->flags |= info_flags; ++ info->sawf.nw_delay = (u32) ktime_to_us(net_timedelta(skb->tstamp)); + ieee80211_aggr_check(sdata, sta, skb); + + if (!ieee80211_hw_check(&local->hw, SUPPORTS_NSS_OFFLOAD) && sta) { +@@ -4827,6 +4829,7 @@ void ieee80211_8023_xmit_ap(struct ieee8 + + info->flags |= IEEE80211_TX_CTL_HW_80211_ENCAP; + info->control.vif = &sdata->vif; ++ info->sawf.nw_delay = (u32) ktime_to_us(net_timedelta(skb->tstamp)); + if (local->enable_tx_latency_stats) + info->latency.tx_start_time = ieee80211_txdelay_get_time(); + +--- a/drivers/net/wireless/ath/ath12k/ahb.c ++++ b/drivers/net/wireless/ath/ath12k/ahb.c +@@ -128,6 +128,14 @@ enum ext_irq_num { + tcl2host_status_ring, + }; + ++static inline u32 ath12k_ahb_pmm_read32(struct ath12k_base *ab, u32 offset) ++{ ++ ath12k_dbg(ab, ATH12K_DBG_OFFSET, "Mem_pmm :%p offset:%x\n", ++ ab->mem_pmm, offset); ++ return ioread32(ab->mem_pmm + offset); ++ ++} ++ + static inline u32 ath12k_ahb_cmem_read32(struct ath12k_base *ab, u32 offset) + { + offset = offset - HAL_IPQ5332_CMEM_BASE; +@@ -649,6 +657,7 @@ static const struct ath12k_hif_ops ath12 + .read32 = ath12k_ahb_read32, + .write32 = ath12k_ahb_write32, + .cmem_read32 = ath12k_ahb_cmem_read32, ++ .pmm_read32 = ath12k_ahb_pmm_read32, + .cmem_write32 = ath12k_ahb_cmem_write32, + .irq_enable = ath12k_ahb_ext_irq_enable, + .irq_disable = ath12k_ahb_ext_irq_disable, +@@ -1022,6 +1031,19 @@ static int ath12k_ahb_probe(struct platf + ab->cmem_remap_base_addr = HAL_IPQ5332_CMEM_REG_BASE; + } + ++ if (ab->hw_params->pmm_remap) { ++ const struct pmm_remap *pmm = ab->hw_params->pmm_remap; ++ ++ ab->mem_pmm = ioremap(pmm->base, pmm->size); ++ if (IS_ERR(ab->mem_pmm)) { ++ dev_err(&pdev->dev, "pmm ioremap error\n"); ++ ret = -ENOMEM; ++ goto err_core_free; ++ } ++ ab->pmm_remap = true; ++ ab->pmm_remap_base_addr = HAL_IPQ5332_PMM_REG_BASE; ++ } ++ + ret = ath12k_ahb_setup_resources(ab); + if (ret) + goto err_core_free; +--- a/drivers/net/wireless/ath/ath12k/hif.h ++++ b/drivers/net/wireless/ath/ath12k/hif.h +@@ -15,6 +15,7 @@ struct ath12k_hif_ops { + void (*write32)(struct ath12k_base *sc, u32 address, u32 data); + u32 (*cmem_read32)(struct ath12k_base *sc, u32 address); + void (*cmem_write32)(struct ath12k_base *sc, u32 address, u32 data); ++ u32 (*pmm_read32)(struct ath12k_base *sc, u32 address); + void (*irq_enable)(struct ath12k_base *sc); + void (*irq_disable)(struct ath12k_base *sc); + int (*start)(struct ath12k_base *sc); +@@ -205,6 +206,11 @@ static inline u32 ath12k_hif_cmem_read32 + return ab->hif.ops->cmem_read32(ab, address); + } + ++static inline u32 ath12k_hif_pmm_read32(struct ath12k_base *ab, u32 offset) ++{ ++ return ab->hif.ops->pmm_read32(ab, offset); ++} ++ + static inline void ath12k_hif_cmem_write32(struct ath12k_base *ab, u32 address, + u32 data) + { +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -1408,6 +1408,11 @@ const struct cmem_remap ath12k_cmem_ipq5 + .size = HAL_IPQ5332_CMEM_SIZE, + }; + ++const struct pmm_remap ath12k_pmm_ipq5332 = { ++ .base = HAL_IPQ5332_PMM_REG_BASE, ++ .size = HAL_IPQ5332_PMM_SIZE, ++}; ++ + static const struct ath12k_hw_hal_params ath12k_hw_hal_params_ipq5332 = { + .rx_buf_rbm = HAL_RX_BUF_RBM_SW3_BM, + .wbm2sw_cc_enable = HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW0_EN | +@@ -1717,6 +1722,7 @@ static const struct ath12k_hw_params ath + .ce_ie_addr = &ath12k_ce_ie_addr_ipq5332, + .ce_remap = &ath12k_ce_remap_ipq5332, + .cmem_remap = &ath12k_cmem_ipq5332, ++ .pmm_remap = &ath12k_pmm_ipq5332, + .send_platform_model = true, + .en_fwlog = true, + }, +--- a/drivers/net/wireless/ath/ath12k/hw.h ++++ b/drivers/net/wireless/ath/ath12k/hw.h +@@ -230,6 +230,7 @@ struct ath12k_hw_params { + const struct ce_remap *ce_remap; + const struct cmem_remap *cmem_remap; + bool compact_rx_tlv; ++ const struct pmm_remap *pmm_remap; + }; + + /* BRINGUP: move to dp.h */ +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -13134,6 +13134,8 @@ skip_lookup: + } + + ar->mlo_setup_status = ev->status; ++ if (ab->hw_params->hal_ops->hal_get_tqm_scratch_reg) ++ ab->hw_params->hal_ops->hal_get_tqm_scratch_reg(ab, &ar->delta_tqm); + complete(&ar->mlo_setup_done); + + out: diff --git a/feeds/ipq95xx/mac80211/patches/qca/784-05-wifi-ath12k-Add-support-to-view-SAWF-stats.patch b/feeds/ipq95xx/mac80211/patches/qca/784-05-wifi-ath12k-Add-support-to-view-SAWF-stats.patch new file mode 100644 index 000000000..c249c7c3a --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/784-05-wifi-ath12k-Add-support-to-view-SAWF-stats.patch @@ -0,0 +1,939 @@ +From 7885f6a28a283ff166e81b75a07edd17b8a56a13 Mon Sep 17 00:00:00 2001 +From: Nagarajan Maran +Date: Tue, 6 Jun 2023 21:30:04 +0530 +Subject: [PATCH] wifi: ath12k: Add support to view SAWF stats + +Add support to handle the get stats command via Vendor NL and +send the stats buffer to Userspace via Vendor NL. + +Signed-off-by: Nagarajan Maran +--- + drivers/net/wireless/ath/ath12k/sawf.c | 224 ++++++++++++++++++ + drivers/net/wireless/ath/ath12k/sawf.h | 7 + + drivers/net/wireless/ath/ath12k/vendor.c | 195 +++++++++++++++ + drivers/net/wireless/ath/ath12k/vendor.h | 287 +++++++++++++++++++++++ + 4 files changed, 713 insertions(+) + +--- a/drivers/net/wireless/ath/ath12k/sawf.c ++++ b/drivers/net/wireless/ath/ath12k/sawf.c +@@ -9,6 +9,7 @@ + #include "sawf.h" + #include "peer.h" + #include "debugfs_htt_stats.h" ++#include "vendor.h" + #include + #include + +@@ -462,6 +463,7 @@ struct ath12k_base *ath12k_sawf_get_ab_f + struct wireless_dev *wdev; + struct ieee80211_vif *vif; + struct ath12k_base *ab = NULL; ++ struct ath12k *ar = NULL; + struct ath12k_peer *peer; + struct ath12k_vif *ahvif; + struct ath12k_link_vif *arvif; +@@ -492,8 +494,10 @@ struct ath12k_base *ath12k_sawf_get_ab_f + + if (WARN_ON(!arvif)) + continue; +- +- ab = arvif->ar->ab; ++ ar = arvif->ar; ++ if (!ar) ++ continue; ++ ab = ar->ab; + spin_lock_bh(&ab->base_lock); + peer = ath12k_peer_find_by_addr(ab, peer_mac); + spin_unlock_bh(&ab->base_lock); +@@ -1509,3 +1513,235 @@ latency_stats_update: + } + return; + } ++ ++static int ath12k_get_msduq_id(u8 svc_id, struct ath12k_peer *peer, u8 *q_id, u8 *tid) ++{ ++ struct ath12k_sawf_ctx *sawf_ctx; ++ struct ath12k_sawf_peer_ctx *peer_ctx = NULL; ++ u8 max_usr_def_q_sawf, def_msduq_max, tid_l, q_id_l; ++ ++ sawf_ctx = ath12k_get_sawf_context(); ++ if (!sawf_ctx) ++ return -ENODATA; ++ ++ max_usr_def_q_sawf = sawf_ctx->max_msduq_per_tid - ++ sawf_ctx->default_msduq_per_tid; ++ def_msduq_max = sawf_ctx->default_msduq_per_tid * ++ ATH12K_SAWF_MAX_TID_SUPPORT; ++ ++ peer_ctx = &peer->sawf_ctx_peer; ++ if (!peer_ctx) ++ return -ENODATA; ++ ++ /* Find matching tid and q_id with svc_id in the reserved pool*/ ++ for (tid_l = 0; tid_l < ATH12K_SAWF_MAX_TID_SUPPORT; tid_l++) { ++ for (q_id_l = 0; q_id_l < max_usr_def_q_sawf; q_id_l++) { ++ if (peer_ctx->msduq_table[tid_l][q_id_l].is_reserved && ++ peer_ctx->msduq_table[tid_l][q_id_l].svc_id == svc_id) { ++ ath12k_dbg(NULL, ATH12K_DBG_SAWF, ++ "tid %u usrdefq %u\n", ++ tid_l, q_id_l); ++ *tid = tid_l; ++ *q_id = q_id_l; ++ return 0; ++ } ++ } ++ } ++ ath12k_dbg(NULL, ATH12K_DBG_SAWF, "Queue and TID not found for svc_id=%u", ++ svc_id); ++ ++ return -EINVAL; ++} ++ ++static void ath12k_copy_tx_stats(struct sawf_tx_stats *src, struct telemetry_sawf_tx_stat *dst) ++{ ++ dst->tx_success.num_pkts = src->tx_success.num_pkts; ++ dst->tx_success.bytes = src->tx_success.bytes; ++ ++ dst->tx_ingress.num_pkts = src->tx_ingress.num_pkts; ++ dst->tx_ingress.bytes = src->tx_ingress.bytes; ++ ++ dst->dropped.fw_rem.num_pkts = src->dropped.fw_rem.num_pkts; ++ dst->dropped.fw_rem.bytes = src->dropped.fw_rem.bytes; ++ dst->dropped.fw_rem_notx = src->dropped.fw_rem_notx; ++ dst->dropped.fw_rem_tx = src->dropped.fw_rem_tx; ++ dst->dropped.age_out = src->dropped.age_out; ++ dst->dropped.fw_reason1 = src->dropped.fw_reason1; ++ dst->dropped.fw_reason2 = src->dropped.fw_reason2; ++ dst->dropped.fw_reason3 = src->dropped.fw_reason3; ++ ++ dst->svc_intval_stats.success_cnt = src->svc_intval_stats.success_cnt; ++ dst->svc_intval_stats.failure_cnt = src->svc_intval_stats.failure_cnt; ++ ++ dst->burst_size_stats.success_cnt = src->burst_size_stats.success_cnt; ++ dst->burst_size_stats.failure_cnt = src->burst_size_stats.failure_cnt; ++ ++ dst->tx_failed = src->tx_failed; ++ dst->queue_depth = src->queue_depth; ++ ++ dst->throughput = src->throughput = 0; ++ dst->ingress_rate = src->ingress_rate = 0; ++} ++ ++static int ath12k_telemetry_get_txstats(struct telemetry_sawftx_stats *tx_stats, ++ struct ath12k_base *ab, ++ u8 *peer_mac, u8 svc_id) ++{ ++ struct ath12k_sawf_stats *sawf_stats; ++ struct sawf_tx_stats *stats; ++ struct telemetry_sawf_tx_stat *tx; ++ struct ath12k_peer *peer = NULL; ++ int ret = 0; ++ u8 sawf_max_user_queues; ++ ++ sawf_max_user_queues = sawf_ctx->max_msduq_per_tid - sawf_ctx->default_msduq_per_tid; ++ spin_lock_bh(&ab->base_lock); ++ peer = ath12k_peer_find_by_addr(ab, peer_mac); ++ if (!peer) { ++ ret = -ENOENT; ++ goto end_stats; ++ } ++ ++ sawf_stats = &peer->sawf_stats; ++ if(!sawf_stats) { ++ ret = -ENODATA; ++ goto end_stats; ++ } ++ ++ if (svc_id == 0) { ++ int tid, q_idx; ++ for (tid = 0; tid < ATH12K_SAWF_MAX_TID_SUPPORT; tid++) { ++ for (q_idx = 0; q_idx < sawf_max_user_queues; q_idx++) { ++ stats = &sawf_stats->tx_stats[tid][q_idx]; ++ tx = &tx_stats->tx[tid][q_idx]; ++ ath12k_copy_tx_stats(stats, tx); ++ } ++ } ++ } else { ++ u8 q_id = 0, tid = 0; ++ if (ath12k_get_msduq_id(svc_id, peer, &q_id, &tid)) { ++ ret = -EINVAL; ++ goto end_stats; ++ } ++ stats = &sawf_stats->tx_stats[tid][q_id]; ++ tx = &tx_stats->tx[0][0]; ++ ath12k_copy_tx_stats(stats, tx); ++ tx_stats->tid = tid; ++ tx_stats->msduq = q_id; ++ } ++ ++end_stats: ++ spin_unlock_bh(&ab->base_lock); ++ return ret; ++} ++ ++static void ath12k_copy_delay_stats(struct sawf_tx_delay_stats *src, struct telemetry_sawf_delay_stat *dst) ++{ ++ struct ath12k_delay_hist_stats *dst_hist_stats = &dst->delay_hist; ++ struct ath12k_delay_hist_stats *src_hist_stats = &src->delay_hist; ++ u8 index; ++ ++ for (index = 0; index < HIST_BUCKET_MAX; index++) ++ dst_hist_stats->hist.freq[index] = src_hist_stats->hist.freq[index]; ++ ++ dst_hist_stats->min = src_hist_stats->min; ++ dst_hist_stats->max = src_hist_stats->max; ++ dst_hist_stats->avg = src_hist_stats->avg; ++ ++ dst->nwdelay_avg = src->nwdelay_avg = 0; ++ dst->swdelay_avg = src->swdelay_avg = 0; ++ dst->hwdelay_avg = src->hwdelay_avg = 0; ++ dst->delay_bound_success = src->success; ++ dst->delay_bound_failure = src->failure; ++} ++ ++static int ath12k_telemetry_get_delaystats(struct telemetry_sawfdelay_stats *delay_stats, ++ struct ath12k_base *ab, ++ u8 *peer_mac, u8 svc_id) ++{ ++ struct ath12k_sawf_stats *sawf_stats; ++ struct sawf_tx_delay_stats *stats; ++ struct telemetry_sawf_delay_stat *delay; ++ struct ath12k_peer *peer; ++ int ret = 0; ++ u8 sawf_max_user_queues; ++ ++ sawf_max_user_queues = sawf_ctx->max_msduq_per_tid - sawf_ctx->default_msduq_per_tid; ++ spin_lock_bh(&ab->base_lock); ++ peer = ath12k_peer_find_by_addr(ab, peer_mac); ++ if (!peer) { ++ ret = -ENOENT; ++ goto end_stats; ++ } ++ ++ sawf_stats = &peer->sawf_stats; ++ if(!sawf_stats) { ++ ret = -ENODATA; ++ goto end_stats; ++ } ++ ++ if (svc_id == 0) { ++ int tid, q_idx; ++ for (tid = 0; tid < ATH12K_SAWF_MAX_TID_SUPPORT; tid++) { ++ for (q_idx = 0; q_idx < sawf_max_user_queues; q_idx++) { ++ stats = &sawf_stats->tx_delay_stats[tid][q_idx]; ++ delay = &delay_stats->delay[tid][q_idx]; ++ ath12k_copy_delay_stats(stats, delay); ++ } ++ } ++ } else { ++ u8 q_id, tid; ++ ++ if (ath12k_get_msduq_id(svc_id, peer, &q_id, &tid)) { ++ ret = -EINVAL; ++ goto end_stats; ++ } ++ ++ stats = &sawf_stats->tx_delay_stats[tid][q_id]; ++ delay = &delay_stats->delay[0][0]; ++ ath12k_copy_delay_stats(stats, delay); ++ delay_stats->tid = tid; ++ delay_stats->msduq = q_id; ++ } ++ ++end_stats: ++ spin_unlock_bh(&ab->base_lock); ++ return ret; ++} ++ ++int telemetry_extract_data(struct stats_config *cfg, ++ struct telemetry_sawftx_stats *tx_stats, ++ struct telemetry_sawfdelay_stats *delay_stats, ++ struct ath12k_base *ab) ++{ ++ u32 feat = 0; ++ int ret = 0; ++ u8 *mac_addr, svc_id; ++ ++ if (!sawf_ctx) ++ return -ENODATA; ++ ++ if (cfg->obj != STATS_OBJ_STA) ++ return -EINVAL; ++ ++ if (cfg->lvl != STATS_LVL_ADVANCE) ++ return -EINVAL; ++ ++ if (cfg->type != STATS_TYPE_DATA) ++ return -EINVAL; ++ ++ feat = cfg->feat; ++ svc_id = cfg->serviceid; ++ mac_addr = cfg->mac; ++ ++ if (feat & STATS_FEAT_FLG_SAWFDELAY) { ++ ret = ath12k_telemetry_get_delaystats(delay_stats, ab, mac_addr, svc_id); ++ if (ret) ++ return ret; ++ } ++ ++ if (feat & STATS_FEAT_FLG_SAWFTX) ++ ret = ath12k_telemetry_get_txstats(tx_stats, ab, mac_addr, svc_id); ++ ++ return ret; ++} +--- a/drivers/net/wireless/ath/ath12k/sawf.h ++++ b/drivers/net/wireless/ath/ath12k/sawf.h +@@ -7,6 +7,9 @@ + #define ATH12K_SAWF_H + + struct hal_tx_status; ++struct stats_config; ++struct telemetry_sawftx_stats; ++struct telemetry_sawfdelay_stats; + + #ifdef CPTCFG_ATH12K_SAWF + +@@ -547,7 +550,55 @@ struct sawf_tx_stats { + * @avg: Average frequency + */ + ++enum stats_if_hist_bucket_index { ++ HIST_BUCKET_0, ++ HIST_BUCKET_1, ++ HIST_BUCKET_2, ++ HIST_BUCKET_3, ++ HIST_BUCKET_4, ++ HIST_BUCKET_5, ++ HIST_BUCKET_6, ++ HIST_BUCKET_7, ++ HIST_BUCKET_8, ++ HIST_BUCKET_9, ++ HIST_BUCKET_10, ++ HIST_BUCKET_11, ++ HIST_BUCKET_12, ++ HIST_BUCKET_MAX, ++}; ++ ++enum stats_if_delay_bucket_index { ++ DELAY_BUCKET_0, ++ DELAY_BUCKET_1, ++ DELAY_BUCKET_2, ++ DELAY_BUCKET_3, ++ DELAY_BUCKET_4, ++ DELAY_BUCKET_5, ++ DELAY_BUCKET_6, ++ DELAY_BUCKET_7, ++ DELAY_BUCKET_8, ++ DELAY_BUCKET_9, ++ DELAY_BUCKET_10, ++ DELAY_BUCKET_11, ++ DELAY_BUCKET_12, ++ DELAY_BUCKET_MAX, ++}; ++ ++enum hist_types { ++ HIST_TYPE_SW_ENQEUE_DELAY, ++ HIST_TYPE_HW_COMP_DELAY, ++ HIST_TYPE_REAP_STACK, ++ HIST_TYPE_HW_TX_COMP_DELAY, ++ HIST_TYPE_MAX, ++}; ++ ++struct hist_bucket { ++ enum hist_types hist_type; ++ u64 freq[HIST_BUCKET_MAX]; ++}; ++ + struct ath12k_delay_hist_stats { ++ struct hist_bucket hist; + int max; + int min; + int avg; +@@ -794,6 +845,10 @@ int ath12k_htt_sawf_streaming_stats_conf + u32 config_param_3); + void ath12k_htt_sawf_streaming_stats_ind_handler(struct ath12k_base *ab, + struct sk_buff *skb); ++int telemetry_extract_data(struct stats_config *cfg, ++ struct telemetry_sawftx_stats *tx_stats, ++ struct telemetry_sawfdelay_stats *delay_stats, ++ struct ath12k_base *ab); + #else /* CPTCFG_ATH12K_SAWF */ + + static inline void ath12k_sawf_init(struct ath12k_base *ab) { +--- a/drivers/net/wireless/ath/ath12k/vendor.c ++++ b/drivers/net/wireless/ath/ath12k/vendor.c +@@ -83,6 +83,18 @@ ath12k_vendor_sawf_streaming[QCA_WLAN_VE + [QCA_WLAN_VENDOR_ATTR_SAWF_STREAMING_EXTND_STATS] = {.type = NLA_U8}, + }; + ++static const struct nla_policy ++ath12k_telemetric_req_policy[QCA_WLAN_VENDOR_ATTR_TELEMETRIC_MAX + 1] = { ++ [QCA_WLAN_VENDOR_ATTR_TELEMETRIC_LEVEL] = {.type = NLA_U8}, ++ [QCA_WLAN_VENDOR_ATTR_TELEMETRIC_OBJECT] = {.type = NLA_U8}, ++ [QCA_WLAN_VENDOR_ATTR_TELEMETRIC_TYPE] = {.type = NLA_U8}, ++ [QCA_WLAN_VENDOR_ATTR_TELEMETRIC_AGGREGATE] = {.type = NLA_FLAG}, ++ [QCA_WLAN_VENDOR_ATTR_TELEMETRIC_FEATURE_FLAG] = {.type = NLA_U64}, ++ [QCA_WLAN_VENDOR_ATTR_TELEMETRIC_STA_MAC] = {.type = NLA_BINARY, ++ .len = ETH_ALEN}, ++ [QCA_WLAN_VENDOR_ATTR_TELEMETRIC_SERVICEID] = {.type = NLA_U8}, ++}; ++ + static void ath12k_set_default_values(struct ath12k_sawf_svc_params *param) + { + param->min_throughput_rate = SAWF_SVC_PARAM_DEFAULT_MIN_THRUPUT; +@@ -696,6 +708,190 @@ static int ath12k_vendor_sawf_streaming_ + return ret; + } + ++static int telemetry_build_nd_send_reply_msg(struct wiphy *wiphy, struct stats_config *cfg, ++ u8 *mac_addr, struct unified_stats *stats) ++{ ++ struct sk_buff *skb = NULL; ++ void *data = NULL; ++ struct nlattr *attr; ++ u32 storage = 0, multiple_reply_len = 0; ++ int rem_len = 0, data_len = 0, nla_size = nla_total_size(0), ret = 0; ++ u8 i, feat = 0; ++ bool data_pending = false, multiple_reply_set = false; ++ char *vap="wifi"; ++ ++ do { ++ skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, NLMSG_DEFAULT_SIZE); ++ if (!skb) ++ return -ENOMEM; ++ ++ if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_STATS_LEVEL, cfg->lvl) || ++ nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_STATS_OBJECT, STATS_OBJ_STA) || ++ nla_put(skb, QCA_WLAN_VENDOR_ATTR_STATS_OBJ_ID, ETH_ALEN, mac_addr) || ++ nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_STATS_SERVICEID, cfg->serviceid) || ++ nla_put_string(skb, QCA_WLAN_VENDOR_ATTR_STATS_PARENT_IF, vap) || ++ nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_STATS_TYPE, cfg->type)) { ++ kfree_skb(skb); ++ return -ENOMEM; ++ } ++ ++ if (data_pending) { ++ multiple_reply_set = true; ++ data_pending = false; ++ /* Length to include the flag QCA_WLAN_VENDOR_ATTR_STATS_MULTI_REPLY */ ++ multiple_reply_len = nla_size; ++ } ++ ++ attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_STATS_RECURSIVE); ++ for (i = feat; i < STATS_FEAT_MAX; i++) { ++ if (!stats->feat[i] || !stats->size[i]) ++ continue; ++ ++ rem_len = skb_tailroom(skb); ++ if (rem_len < 0) { ++ ath12k_err(NULL, "SAWF: skb is corrupted\n"); ++ kfree_skb(skb); ++ return -ECANCELED; ++ } ++ rem_len -= multiple_reply_len; ++ rem_len -= nla_size; ++ rem_len = (rem_len > 0) ? rem_len : 0; ++ ++ if (stats->size[i] >= rem_len) { ++ data_len = rem_len; ++ data = stats->feat[i] + storage; ++ stats->size[i] -= rem_len; ++ storage += data_len; ++ feat = i; ++ data_pending = true; ++ } else { ++ data_len = stats->size[i]; ++ data = stats->feat[i] + storage; ++ storage = 0; ++ } ++ if (nla_put(skb, i+1, data_len, data)) { ++ kfree_skb(skb); ++ return -ENOMEM; ++ } ++ ++ if (data_pending) ++ break; ++ } ++ ++ nla_nest_end(skb, attr); ++ ++ if (multiple_reply_set && nla_put_flag(skb, QCA_WLAN_VENDOR_ATTR_STATS_MULTI_REPLY)) { ++ kfree_skb(skb); ++ return -ENOMEM; ++ } ++ ++ ret = cfg80211_vendor_cmd_reply(skb); ++ if (ret) { ++ kfree_skb(skb); ++ ath12k_err(NULL, "SAWF: stats msg send failed with err=%d\n", ret); ++ return ret; ++ } ++ } while(data_pending); ++ ++ return ret; ++} ++ ++static int ath12k_vendor_telemetry_getstats(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ const void *data, ++ int data_len) ++{ ++ struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TELEMETRIC_MAX + 1]; ++ struct stats_config cfg; ++ struct unified_stats *stats; ++ struct telemetry_sawfdelay_stats *delay_stats = NULL; ++ struct telemetry_sawftx_stats *tx_stats = NULL; ++ struct ath12k_base *ab = NULL; ++ int ret = 0, i; ++ u16 peer_id = 0xFFFF; ++ u8 mac_addr[ETH_ALEN] = { 0 }; ++ ++ if (!ath12k_sawf_enable) ++ return -EOPNOTSUPP; ++ ++ ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TELEMETRIC_MAX, data, data_len, ++ ath12k_telemetric_req_policy, NULL); ++ ++ if (ret) { ++ ath12k_err(NULL, "Invalid attribute with telemetry getstats command\n"); ++ return ret; ++ } ++ ++ memset(&cfg, 0, sizeof(struct stats_config)); ++ ++ if (wiphy) ++ cfg.wiphy = wiphy; ++ if (tb[QCA_WLAN_VENDOR_ATTR_TELEMETRIC_LEVEL]) ++ cfg.lvl = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_TELEMETRIC_LEVEL]); ++ if (tb[QCA_WLAN_VENDOR_ATTR_TELEMETRIC_OBJECT]) ++ cfg.obj = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_TELEMETRIC_OBJECT]); ++ if (tb[QCA_WLAN_VENDOR_ATTR_TELEMETRIC_TYPE]) ++ cfg.type = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_TELEMETRIC_TYPE]); ++ if (tb[QCA_WLAN_VENDOR_ATTR_TELEMETRIC_AGGREGATE]) ++ cfg.aggregate = true; ++ if (tb[QCA_WLAN_VENDOR_ATTR_TELEMETRIC_FEATURE_FLAG]) ++ cfg.feat = nla_get_u64(tb[QCA_WLAN_VENDOR_ATTR_TELEMETRIC_FEATURE_FLAG]); ++ if (tb[QCA_WLAN_VENDOR_ATTR_TELEMETRIC_STA_MAC] && ++ (nla_len(tb[QCA_WLAN_VENDOR_ATTR_TELEMETRIC_STA_MAC]) == ETH_ALEN)) { ++ memcpy(mac_addr, nla_data(tb[QCA_WLAN_VENDOR_ATTR_TELEMETRIC_STA_MAC]), ETH_ALEN); ++ cfg.mac = mac_addr; ++ } ++ if (tb[QCA_WLAN_VENDOR_ATTR_TELEMETRIC_SERVICEID]) ++ cfg.serviceid = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_TELEMETRIC_SERVICEID]); ++ ++ if (!(cfg.feat)) ++ return -EINVAL; ++ ++ ab = ath12k_sawf_get_ab_from_netdev(wdev->netdev, mac_addr, &peer_id); ++ if (!ab) ++ return -ENODATA; ++ ++ stats = kzalloc(sizeof(struct unified_stats), GFP_KERNEL); ++ if (!stats) ++ return -ENOMEM; ++ ++ if (cfg.feat & STATS_FEAT_FLG_SAWFTX) { ++ tx_stats = kzalloc(sizeof(struct telemetry_sawftx_stats), GFP_KERNEL); ++ if (!tx_stats) { ++ ret = -ENOMEM; ++ goto end_stats; ++ } ++ stats->feat[STATS_FEAT_SAWFTX] = tx_stats; ++ stats->size[STATS_FEAT_SAWFTX] = sizeof(struct telemetry_sawftx_stats); ++ } ++ ++ if (cfg.feat & STATS_FEAT_FLG_SAWFDELAY) { ++ delay_stats = kzalloc(sizeof(struct telemetry_sawfdelay_stats), GFP_KERNEL); ++ if (!delay_stats) { ++ ret = -ENOMEM; ++ goto end_stats; ++ } ++ stats->feat[STATS_FEAT_SAWFDELAY] = delay_stats; ++ stats->size[STATS_FEAT_SAWFDELAY] = sizeof(struct telemetry_sawfdelay_stats); ++ } ++ ++ ret = telemetry_extract_data(&cfg, tx_stats, delay_stats, ab); ++ if (ret) ++ goto end_stats; ++ ++ ret = telemetry_build_nd_send_reply_msg(wiphy, &cfg, mac_addr, stats); ++ ++end_stats: ++ for (i = 0; i < STATS_FEAT_MAX; i++) { ++ if (stats->feat[i]) ++ kfree(stats->feat[i]); ++ stats->feat[i] = NULL; ++ } ++ kfree(stats); ++ ++ return ret; ++} ++ + #endif /* CPTCFG_ATH12K_SAWF */ + static struct wiphy_vendor_command ath12k_vendor_commands[] = { + #ifdef CPTCFG_ATH12K_SAWF +@@ -773,6 +969,14 @@ static struct wiphy_vendor_command ath12 + .maxattr = QCA_WLAN_VENDOR_ATTR_SAWF_STREAMING_MAX, + .flags = WIPHY_VENDOR_CMD_NEED_NETDEV, + }, ++ { ++ .info.vendor_id = QCA_NL80211_VENDOR_ID, ++ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TELEMETRIC_DATA, ++ .doit = ath12k_vendor_telemetry_getstats, ++ .policy = ath12k_telemetric_req_policy, ++ .maxattr = QCA_WLAN_VENDOR_ATTR_TELEMETRIC_MAX, ++ .flags = WIPHY_VENDOR_CMD_NEED_NETDEV, ++ }, + #endif /* CPTCFG_ATH12K_SAWF */ + }; + +--- a/drivers/net/wireless/ath/ath12k/vendor.h ++++ b/drivers/net/wireless/ath/ath12k/vendor.h +@@ -21,6 +21,7 @@ enum qca_nl80211_vendor_subcmds { + QCA_NL80211_VENDOR_SUBCMD_TELEMETRY_SLA_SAMPLES_CFG = 211, + QCA_NL80211_VENDOR_SUBCMD_TELEMETRY_SLA_BREACH_DETECTION_CFG = 212, + QCA_NL80211_VENDOR_SUBCMD_SAWF_STREAMING_STATS = 213, ++ QCA_NL80211_VENDOR_SUBCMD_TELEMETRIC_DATA = 334, + #endif /* CPTCFG_ATH12K_SAWF */ + }; + +@@ -117,6 +118,339 @@ enum ath12k_vendor_attr_sawf_streaming { + QCA_WLAN_VENDOR_ATTR_SAWF_STREAMING_AFTER_LAST - 1, + }; + ++/** ++ * enum qca_wlan_vendor_attr_telemetric: Defines attributes to be used in ++ * request message of QCA_NL80211_VENDOR_SUBCMD_TELEMETRIC_DATA vendor command. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_TELEMETRIC_LEVEL: Defines stats levels like Basic or ++ * Advance or Debug. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_TELEMETRIC_OBJECT: Defines stats objects like STA or ++ * VAP or Radio or SoC. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_TELEMETRIC_TYPE: Defines stats types like Data or ++ * control. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_TELEMETRIC_AGGREGATE: Defines aggregation flag for ++ * driver agrregation. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_TELEMETRIC_FEATURE_FLAG: Defines feature flags for ++ * which stats is requested. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_TELEMETRIC_STA_MAC: Defines STA MAC Address if the ++ * request is for particular STA object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_TELEMETRIC_SERVICEID: Defines serviceid for sawf stats. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_TELEMETRIC_MAX: Defines maximum attribute counts to be ++ * used in QCA_NL80211_VENDOR_SUBCMD_TELEMETRIC_DATA vendor command request. ++ */ ++enum qca_wlan_vendor_attr_telemetric { ++ QCA_WLAN_VENDOR_ATTR_TELEMETRIC_LEVEL = 1, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRIC_OBJECT, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRIC_TYPE, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRIC_AGGREGATE, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRIC_FEATURE_FLAG, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRIC_STA_MAC, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRIC_SERVICEID, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRIC_MLD_LINK, ++ ++ QCA_WLAN_VENDOR_ATTR_TELEMETRIC_AFTER_LAST, ++ QCA_WLAN_VENDOR_ATTR_TELEMETRIC_MAX = ++ QCA_WLAN_VENDOR_ATTR_TELEMETRIC_AFTER_LAST -1, ++}; ++ ++/** ++ * enum qca_wlan_vendor_attr_stats: Defines attributes to be used in response of ++ * QCA_NL80211_VENDOR_SUBCMD_TELEMETRIC_DATA vendor command. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_STATS_LEVEL: Used for stats levels like Basic or ++ * Advance or Debug. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_STATS_OBJECT: Required (u8) ++ * Used with the command, carrying stats, to specify for which stats_object enum. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_STATS_OBJ_ID: Used for Object ID like for STA MAC ++ * address or for VAP or Radio or SoC respective interface name. ++ * ++ * QCA_WLAN_VENDOR_ATTR_STATS_SERVICEID: Used for sawf levels stats like per ++ * peer or per peer per serviceclass. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_STATS_PARENT_IF: Used for Parent Object interface name ++ * like for STA VAP name, for VAP Radio interface name and for Radio SoC ++ * interface name. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_STATS_TYPE: Used for stats types like Data or ++ * control. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_STATS_RECURSIVE: Required (NESTED Flag) ++ * Used with the command to specify the nested stats. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_STATS_MULTI_REPLY: Set this flag if current reply ++ * messageis holding data from previous reply. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_STATS_MAX: Defines maximum attriutes can be used in ++ * QCA_NL80211_VENDOR_SUBCMD_TELEMETRIC_DATA vendor command response. ++ */ ++ ++enum qca_wlan_vendor_attr_stats { ++ QCA_WLAN_VENDOR_ATTR_STATS_LEVEL = 1, ++ QCA_WLAN_VENDOR_ATTR_STATS_OBJECT, ++ QCA_WLAN_VENDOR_ATTR_STATS_OBJ_ID, ++ QCA_WLAN_VENDOR_ATTR_STATS_SERVICEID, ++ QCA_WLAN_VENDOR_ATTR_STATS_PARENT_IF, ++ QCA_WLAN_VENDOR_ATTR_STATS_TYPE, ++ QCA_WLAN_VENDOR_ATTR_STATS_RECURSIVE, ++ QCA_WLAN_VENDOR_ATTR_STATS_MULTI_REPLY, ++ QCA_WLAN_VENDOR_ATTR_STATS_MAX, ++}; ++ ++struct telemetry_sawf_tx_stat { ++ struct dp_pkt_info tx_success; ++ struct dp_pkt_info tx_ingress; ++ struct { ++ struct dp_pkt_info fw_rem; ++ u32 fw_rem_notx; ++ u32 fw_rem_tx; ++ u32 age_out; ++ u32 fw_reason1; ++ u32 fw_reason2; ++ u32 fw_reason3; ++ } dropped; ++ struct sawf_fw_mpdu_stats svc_intval_stats; ++ struct sawf_fw_mpdu_stats burst_size_stats; ++ u32 tx_failed; ++ u32 queue_depth; ++ u32 throughput; ++ u32 ingress_rate; ++}; ++ ++struct telemetry_sawftx_stats { ++ struct telemetry_sawf_tx_stat tx[ATH12K_SAWF_MAX_TID_SUPPORT][MAX_Q_PER_TID]; ++ u8 tid; ++ u8 msduq; ++}; ++ ++struct telemetry_sawf_delay_stat { ++ struct ath12k_delay_hist_stats delay_hist; ++ u8 cur_win; ++ u32 nwdelay_avg; ++ u32 swdelay_avg; ++ u32 hwdelay_avg; ++ u64 delay_bound_success; ++ u64 delay_bound_failure; ++}; ++ ++struct telemetry_sawfdelay_stats { ++ struct telemetry_sawf_delay_stat delay[ATH12K_SAWF_MAX_TID_SUPPORT][MAX_Q_PER_TID]; ++ u8 tid; ++ u8 msduq; ++}; ++ ++/** ++ * enum qca_wlan_vendor_attr_feat: Defines nested attributes to be used in ++ * response of QCA_NL80211_VENDOR_SUBCMD_TELEMETRIC_DATA vendor command. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_ME: Used for Multicast Enhancement stats for a ++ * particular stats object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_RX: Used for Rx stats for a particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_TX: Used for Tx stats for a particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_AST: Used for AST stats for a particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_CFR: Used for CFR stats for a particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_FWD: Used for BSS stats for a particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_RAW: Used for RAW mode stats for a particular ++ * object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_TSO: Used for TSO stats for a particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_TWT: Used for TWT stats for a particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_VOW: Used for VOW stats for a particular object. ++* ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_WDI: Used for WDI stats for a particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_WMI: Used for WMI stats for a particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_IGMP: Used for IGMP stats for a particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_LINK: Used for Link related stats for a particular ++ * object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_MESH: Used for Mesh related stats for a particular ++ * object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_RATE: Used for Rate stats for a particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_NAWDS: Used for NAWDS related stats for a ++ * particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_DELAY: Used for DELAY related stats for a ++ * particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_JITTER: Used for JITTER related stats for a ++ * particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_TXCAP: Used for TXCAP realted stats for a ++ * particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_MONITOR: Used for MONITOR realted stats for a ++ * particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_SAWFDELAY: Used for SAWFDELAY related stats for a ++ * particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_SAWFTX: Used for SAWFTX related stats for a ++ * particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_DETER: Used for DETERMINISTIC related stats for a ++ * particular object. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_FEAT_MAX: Defines Maximum count of feature attributes. ++ */ ++enum qca_wlan_vendor_attr_feat { ++ QCA_WLAN_VENDOR_ATTR_FEAT_ME = 1, ++ QCA_WLAN_VENDOR_ATTR_FEAT_RX, ++ QCA_WLAN_VENDOR_ATTR_FEAT_TX, ++ QCA_WLAN_VENDOR_ATTR_FEAT_AST, ++ QCA_WLAN_VENDOR_ATTR_FEAT_CFR, ++ QCA_WLAN_VENDOR_ATTR_FEAT_FWD, ++ QCA_WLAN_VENDOR_ATTR_FEAT_RAW, ++ QCA_WLAN_VENDOR_ATTR_FEAT_TSO, ++ QCA_WLAN_VENDOR_ATTR_FEAT_TWT, ++ QCA_WLAN_VENDOR_ATTR_FEAT_VOW, ++ QCA_WLAN_VENDOR_ATTR_FEAT_WDI, ++ QCA_WLAN_VENDOR_ATTR_FEAT_WMI, ++ QCA_WLAN_VENDOR_ATTR_FEAT_IGMP, ++ QCA_WLAN_VENDOR_ATTR_FEAT_LINK, ++ QCA_WLAN_VENDOR_ATTR_FEAT_MESH, ++ QCA_WLAN_VENDOR_ATTR_FEAT_RATE, ++ QCA_WLAN_VENDOR_ATTR_FEAT_NAWDS, ++ QCA_WLAN_VENDOR_ATTR_FEAT_DELAY, ++ QCA_WLAN_VENDOR_ATTR_FEAT_JITTER, ++ QCA_WLAN_VENDOR_ATTR_FEAT_TXCAP, ++ QCA_WLAN_VENDOR_ATTR_FEAT_MONITOR, ++ QCA_WLAN_VENDOR_ATTR_FEAT_SAWFDELAY, ++ QCA_WLAN_VENDOR_ATTR_FEAT_SAWFTX, ++ QCA_WLAN_VENDOR_ATTR_FEAT_DETER, ++ /** ++ * New attribute must be add before this. ++ * Also define the corresponding feature ++ * index in enum stats_feat. ++ */ ++ QCA_WLAN_VENDOR_ATTR_FEAT_MAX, ++}; ++ ++enum stats_feat { ++ STATS_FEAT_ME, ++ STATS_FEAT_RX, ++ STATS_FEAT_TX, ++ STATS_FEAT_AST, ++ STATS_FEAT_CFR, ++ STATS_FEAT_FWD, ++ STATS_FEAT_RAW, ++ STATS_FEAT_TSO, ++ STATS_FEAT_TWT, ++ STATS_FEAT_VOW, ++ STATS_FEAT_WDI, ++ STATS_FEAT_WMI, ++ STATS_FEAT_IGMP, ++ STATS_FEAT_LINK, ++ STATS_FEAT_MESH, ++ STATS_FEAT_RATE, ++ STATS_FEAT_NAWDS, ++ STATS_FEAT_DELAY, ++ STATS_FEAT_JITTER, ++ STATS_FEAT_TXCAP, ++ STATS_FEAT_MONITOR, ++ STATS_FEAT_SAWFDELAY, ++ STATS_FEAT_SAWFTX, ++ STATS_FEAT_DETER, ++ STATS_FEAT_MAX, ++}; ++ ++/** ++ * enum stats_level: Defines detailing levels ++ * @STATS_LVL_BASIC: Very minimal stats data ++ * @STATS_LVL_ADVANCE: Mostly feature specific stats data ++ * @STATS_LVL_DEBUG: Stats data for debug purpose ++ * @STATS_LVL_MAX: Max supported Stats levels ++ */ ++enum stats_level { ++ STATS_LVL_BASIC, ++ STATS_LVL_ADVANCE, ++ STATS_LVL_DEBUG, ++ STATS_LVL_MAX = STATS_LVL_DEBUG, ++}; ++ ++/** ++ * enum stats_object: Defines the Stats specific to object ++ * @STATS_OBJ_STA: Stats for station/peer associated to AP ++ * @STATS_OBJ_VAP: Stats for VAP ++ * @STATS_OBJ_MLD: Stats for MLD group ++ * @STATS_OBJ_RADIO: Stats for particular Radio ++ * @STATS_OBJ_AP: Stats for SoC ++ * @STATS_OBJ_MAX: Max supported objects ++ */ ++enum stats_object { ++ STATS_OBJ_STA, ++ STATS_OBJ_VAP, ++ STATS_OBJ_MLD, ++ STATS_OBJ_RADIO, ++ STATS_OBJ_AP, ++ STATS_OBJ_MAX = STATS_OBJ_AP, ++}; ++ ++/** ++ * enum stats_type: Defines the Stats for specific category ++ * @STATS_TYPE_DATA: Stats for Data frames ++ * @STATS_TYPE_CTRL: Stats for Control/Management frames ++ * @STATS_TYPE_MAX: Max supported types ++ */ ++enum stats_type { ++ STATS_TYPE_DATA, ++ STATS_TYPE_CTRL, ++ STATS_TYPE_MAX = STATS_TYPE_CTRL, ++}; ++ ++/** ++ * struct stats_config: Structure to hold user configurations ++ * @wiphy: Pointer to wiphy structure which came as part of User request ++ * @feat: Feat flag set to dedicated bit of this field ++ * @lvl: Requested level of Stats (i.e. Basic, Advance or Debug) ++ * @obj: Requested stats for object (i.e. AP, Radio, Vap or STA) ++ * @type: Requested stats category ++ * @aggregate: Aggregate in driver ++ * @serviceid: service id for checking the level of sawf stats ++ */ ++struct stats_config { ++ struct wiphy *wiphy; ++ u64 feat; ++ enum stats_level lvl; ++ enum stats_object obj; ++ enum stats_type type; ++ bool aggregate; ++ u8 serviceid; ++ u8 *mac; ++}; ++ ++#define STATS_FEAT_FLG_SAWFDELAY 0x00400000 ++#define STATS_FEAT_FLG_SAWFTX 0x00800000 ++/** ++ * struct unified_stats: Structure to carry all feature specific stats in driver ++ * level for stats response setup ++ * All features are void pointers and its corresponding sizes. ++ * This can hold Basic or Advance or Debug structures independently. ++ */ ++struct unified_stats { ++ void *feat[STATS_FEAT_MAX]; ++ u_int32_t size[STATS_FEAT_MAX]; ++}; + #endif /* CPTCFG_ATH12K_SAWF */ + + int ath12k_vendor_register(struct ath12k_hw *ah); diff --git a/feeds/ipq95xx/mac80211/patches/qca/784-06-ath12k-sawf-Add-telemetry-agent-interface-and-config.patch b/feeds/ipq95xx/mac80211/patches/qca/784-06-ath12k-sawf-Add-telemetry-agent-interface-and-config.patch new file mode 100644 index 000000000..d917fcec9 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/784-06-ath12k-sawf-Add-telemetry-agent-interface-and-config.patch @@ -0,0 +1,1829 @@ +From 89db6feadce880099794725e9a3a6415e28c683f Mon Sep 17 00:00:00 2001 +From: Mahendran P +Date: Thu, 1 Jun 2023 14:55:39 +0530 +Subject: [PATCH] ath12k: sawf: Add telemetry agent interface and configuration + +Add the telemetry agent interfaces which interacts with telemetry agent +module. These interfaces helps to configure and update the required +stats to the telemetry agent which will be processed by telemetry agent +and detect the breach and notifies the driver. + +Signed-off-by: Mahendran P +Signed-off-by: Nagarajan Maran +--- + drivers/net/wireless/ath/ath12k/Makefile | 3 +- + drivers/net/wireless/ath/ath12k/sawf.c | 12 + + drivers/net/wireless/ath/ath12k/telemetry.c | 27 +- + .../ath/ath12k/telemetry_agent_app_if.h | 193 +++++++++++ + .../wireless/ath/ath12k/telemetry_agent_if.c | 308 ++++++++++++++++++ + .../wireless/ath/ath12k/telemetry_agent_if.h | 76 +++++ + .../ath12k/telemetry_agent_wifi_driver_if.h | 208 ++++++++++++ + 7 files changed, 825 insertions(+), 2 deletions(-) + create mode 100644 drivers/net/wireless/ath/ath12k/telemetry_agent_app_if.h + create mode 100644 drivers/net/wireless/ath/ath12k/telemetry_agent_if.c + create mode 100644 drivers/net/wireless/ath/ath12k/telemetry_agent_if.h + create mode 100644 drivers/net/wireless/ath/ath12k/telemetry_agent_wifi_driver_if.h + +--- a/drivers/net/wireless/ath/ath12k/sawf.c ++++ b/drivers/net/wireless/ath/ath12k/sawf.c +@@ -12,6 +12,8 @@ + #include "vendor.h" + #include + #include ++#include "telemetry.h" ++#include "telemetry_agent_if.h" + + #define SVC_INDEX(svc_id) svc_id - 1 + #define DRV_TO_FW_SVC_ID(svc_id) (svc_id - 1) +@@ -126,6 +128,15 @@ void ath12k_update_svc_class(struct ath1 + new_param->ul_max_latency = sawf_params->ul_max_latency; + new_param->ul_ofdma_disable = sawf_params->ul_ofdma_disable; + new_param->ul_mu_mimo_disable = sawf_params->ul_mu_mimo_disable; ++ ++ ath12k_telemetry_set_svclass_cfg(true, new_param->svc_id, ++ new_param->min_throughput_rate, ++ new_param->max_throughput_rate, ++ new_param->burst_size, ++ new_param->service_interval, ++ new_param->delay_bound, ++ new_param->msdu_ttl, ++ new_param->msdu_rate_loss); + } + + bool ath12k_validate_sawf_param(struct ath12k_sawf_svc_params *params) +@@ -267,6 +278,15 @@ bool ath12k_disable_svc_class(u8 svc_id) + sawf_svc_class = &sawf_ctx->svc_classes[SVC_INDEX(svc_id)]; + memset(sawf_svc_class, 0, sizeof(*sawf_svc_class)); + ++ ath12k_telemetry_set_svclass_cfg(false, svc_id, ++ sawf_svc_class->min_throughput_rate, ++ sawf_svc_class->max_throughput_rate, ++ sawf_svc_class->burst_size, ++ sawf_svc_class->service_interval, ++ sawf_svc_class->delay_bound, ++ sawf_svc_class->msdu_ttl, ++ sawf_svc_class->msdu_rate_loss); ++ + return true; + } + +@@ -519,8 +539,8 @@ u8 ath12k_sawf_get_msduq_of_tid(struct a + { + struct ath12k_sawf_peer_ctx *peer_ctx = NULL; + struct ath12k_sawf_ctx *sawf_ctx; +- u8 max_usr_def_q_sawf, def_msduq_max, q; +- u8 msduq_id = SAWF_MSDUQ_ID_INVALID; ++ void *telemetry_peer_ctx = NULL; ++ u8 max_usr_def_q_sawf, def_msduq_max, q, msduq_id = SAWF_MSDUQ_ID_INVALID; + + sawf_ctx = ath12k_get_sawf_context(); + if (!sawf_ctx) +@@ -559,6 +579,22 @@ u8 ath12k_sawf_get_msduq_of_tid(struct a + ath12k_dbg(ab, ATH12K_DBG_SAWF, + "New:msduq_id 0x%x:tid %u usrdefq %u\n", + msduq_id, tid, q); ++ ++ if (!peer_ctx->telemetry_peer_ctx) { ++ telemetry_peer_ctx = ++ ath12k_telemetry_peer_ctx_alloc(ab, ++ &peer->sawf_stats, ++ peer->addr, ++ svc_id, ++ (msduq_id - def_msduq_max)); ++ if (telemetry_peer_ctx) { ++ peer_ctx->telemetry_peer_ctx = telemetry_peer_ctx; ++ ath12k_dbg(ab, ATH12K_DBG_SAWF, ++ "telemetry peer ctx allocation" ++ "with msduq_id:0x%x\n", ++ msduq_id - def_msduq_max); ++ } ++ } + break; + } + } +@@ -571,11 +607,10 @@ u16 ath12k_sawf_alloc_msduq(struct ath12 + u8 svc_id, + u16 peer_id) + { +- u8 msduq_id; +- u8 svc_tid; +- u16 ret_peer_msduq = SAWF_PEER_MSDUQ_INVALID; + struct ath12k_sawf_ctx *sawf_ctx; + struct ath12k_peer *peer; ++ u16 ret_peer_msduq = SAWF_PEER_MSDUQ_INVALID; ++ u8 svc_tid, msduq_id; + + sawf_ctx = ath12k_get_sawf_context(); + if (!sawf_ctx) +@@ -1395,8 +1430,9 @@ void ath12k_sawf_stats_update(struct ath + u64 entry_ts, enqueue_timestamp; + struct ath12k_base *ab = ar->ab; + struct sawf_tx_stats *tx_stats; +- u32 msduq_id, len, q_id, tid; +- u8 svc_id; ++ void *telemetry_peer_ctx; ++ u32 msduq_id, len, q_id, tid, num_pkts; ++ u8 svc_id, hostq_id; + + if (!ts || !peer_ctx) + return; +@@ -1418,6 +1454,10 @@ void ath12k_sawf_stats_update(struct ath + tid = u32_get_bits(msduq_id, MSDUQID_TID_MASK); + q_id = u32_get_bits(msduq_id, MSDUQID_Q_MASK) - ab->default_msduq_per_tid; + ++ hostq_id = msduq_id - (ab->default_msduq_per_tid * ATH12K_SAWF_MAX_TID_SUPPORT); ++ ath12k_telemetry_get_sla_num_pkts(&num_pkts); ++ telemetry_peer_ctx = peer->sawf_ctx_peer.telemetry_peer_ctx; ++ + if (!(ath12k_debugfs_is_sawf_stats_enabled(ar) & ATH12K_SAWF_STATS_BASIC)) + goto latency_stats_update; + +@@ -1464,6 +1504,13 @@ void ath12k_sawf_stats_update(struct ath + + tx_stats->queue_depth--; + ++ if ((!((tx_stats->tx_success.num_pkts + tx_stats->tx_failed) % num_pkts)) && ++ telemetry_peer_ctx) ++ ath12k_telemetry_update_msdu_drop(telemetry_peer_ctx, tid, hostq_id, ++ tx_stats->tx_success.num_pkts, ++ tx_stats->tx_failed, ++ tx_stats->dropped.age_out); ++ + latency_stats_update: + + tx_delay_stats = &sawf_stats->tx_delay_stats[tid][q_id]; +@@ -1487,6 +1534,7 @@ latency_stats_update: + sw_delay = (u32) (enqueue_timestamp - entry_ts); + tx_delay_stats->swdelay_win_total += sw_delay; + ++ ath12k_telemetry_get_sla_mov_avg_num_pkt(&pkt_win); + if (!(tx_delay_stats->num_pkt % pkt_win)) { + tx_delay_stats->nwdelay_avg = div_u64(tx_delay_stats->nwdelay_win_total, + pkt_win); +@@ -1495,6 +1543,12 @@ latency_stats_update: + tx_delay_stats->hwdelay_avg = div_u64(tx_delay_stats->hwdelay_win_total, + pkt_win); + ++ if (telemetry_peer_ctx) ++ ath12k_telemetry_update_delay_mvng(telemetry_peer_ctx, ++ tid, hostq_id, ++ tx_delay_stats->nwdelay_avg, ++ tx_delay_stats->swdelay_avg, ++ tx_delay_stats->hwdelay_avg); + tx_delay_stats->nwdelay_win_total = 0; + tx_delay_stats->swdelay_win_total = 0; + tx_delay_stats->hwdelay_win_total = 0; +@@ -1509,6 +1563,12 @@ latency_stats_update: + tx_delay_stats->failure++; + else + tx_delay_stats->success++; ++ ++ if (!(tx_delay_stats->num_pkt % num_pkts) && telemetry_peer_ctx) ++ ath12k_telemetry_update_delay(telemetry_peer_ctx, ++ tid, hostq_id, ++ tx_delay_stats->success, ++ tx_delay_stats->failure); + } + return; + } +@@ -1578,19 +1638,21 @@ static void ath12k_copy_tx_stats(struct + dst->tx_failed = src->tx_failed; + dst->queue_depth = src->queue_depth; + +- dst->throughput = src->throughput = 0; +- dst->ingress_rate = src->ingress_rate = 0; ++ dst->throughput = src->throughput; ++ dst->ingress_rate = src->ingress_rate; + } + + static int ath12k_telemetry_get_txstats(struct telemetry_sawftx_stats *tx_stats, + struct ath12k_base *ab, + u8 *peer_mac, u8 svc_id) + { +- struct ath12k_sawf_stats *sawf_stats; ++ struct ath12k_sawf_stats *sawf_stats = NULL; + struct sawf_tx_stats *stats; + struct telemetry_sawf_tx_stat *tx; + struct ath12k_peer *peer = NULL; ++ struct ath12k_sawf_peer_ctx *peer_ctx = NULL; + int ret = 0; ++ u32 throughput = 0, ingress_rate = 0, msduq = 0; + u8 sawf_max_user_queues; + + sawf_max_user_queues = sawf_ctx->max_msduq_per_tid - sawf_ctx->default_msduq_per_tid; +@@ -1601,6 +1663,12 @@ static int ath12k_telemetry_get_txstats( + goto end_stats; + } + ++ peer_ctx = &peer->sawf_ctx_peer; ++ if (!peer_ctx) { ++ ret = -ENODATA; ++ goto end_stats; ++ } ++ + sawf_stats = &peer->sawf_stats; + if(!sawf_stats) { + ret = -ENODATA; +@@ -1613,6 +1681,17 @@ static int ath12k_telemetry_get_txstats( + for (q_idx = 0; q_idx < sawf_max_user_queues; q_idx++) { + stats = &sawf_stats->tx_stats[tid][q_idx]; + tx = &tx_stats->tx[tid][q_idx]; ++ if (peer_ctx->telemetry_peer_ctx) { ++ msduq = u16_encode_bits(q_idx, MSDUQID_Q_MASK) | ++ u16_encode_bits(tid, MSDUQID_TID_MASK); ++ ath12k_telemetry_get_rate(peer_ctx->telemetry_peer_ctx, ++ tid, msduq, ++ &throughput, ++ &ingress_rate); ++ msduq = 0; ++ } ++ stats->throughput = throughput; ++ stats->ingress_rate = ingress_rate; + ath12k_copy_tx_stats(stats, tx); + } + } +@@ -1624,6 +1703,14 @@ static int ath12k_telemetry_get_txstats( + } + stats = &sawf_stats->tx_stats[tid][q_id]; + tx = &tx_stats->tx[0][0]; ++ if (peer_ctx->telemetry_peer_ctx) { ++ msduq = u16_encode_bits(q_id, MSDUQID_Q_MASK) | ++ u16_encode_bits(tid, MSDUQID_TID_MASK); ++ ath12k_telemetry_get_rate(peer_ctx->telemetry_peer_ctx, tid, msduq, ++ &throughput, &ingress_rate); ++ } ++ stats->throughput = throughput; ++ stats->ingress_rate = ingress_rate; + ath12k_copy_tx_stats(stats, tx); + tx_stats->tid = tid; + tx_stats->msduq = q_id; +@@ -1647,9 +1734,9 @@ static void ath12k_copy_delay_stats(stru + dst_hist_stats->max = src_hist_stats->max; + dst_hist_stats->avg = src_hist_stats->avg; + +- dst->nwdelay_avg = src->nwdelay_avg = 0; +- dst->swdelay_avg = src->swdelay_avg = 0; +- dst->hwdelay_avg = src->hwdelay_avg = 0; ++ dst->nwdelay_avg = src->nwdelay_avg; ++ dst->swdelay_avg = src->swdelay_avg; ++ dst->hwdelay_avg = src->hwdelay_avg; + dst->delay_bound_success = src->success; + dst->delay_bound_failure = src->failure; + } +@@ -1662,7 +1749,9 @@ static int ath12k_telemetry_get_delaysta + struct sawf_tx_delay_stats *stats; + struct telemetry_sawf_delay_stat *delay; + struct ath12k_peer *peer; ++ struct ath12k_sawf_peer_ctx *peer_ctx = NULL; + int ret = 0; ++ u32 nwdelay_avg = 0, swdelay_avg = 0, hwdelay_avg = 0, msduq = 0; + u8 sawf_max_user_queues; + + sawf_max_user_queues = sawf_ctx->max_msduq_per_tid - sawf_ctx->default_msduq_per_tid; +@@ -1679,12 +1768,29 @@ static int ath12k_telemetry_get_delaysta + goto end_stats; + } + ++ peer_ctx = &peer->sawf_ctx_peer; ++ if (!peer_ctx) { ++ ret = -ENODATA; ++ goto end_stats; ++ } ++ + if (svc_id == 0) { + int tid, q_idx; + for (tid = 0; tid < ATH12K_SAWF_MAX_TID_SUPPORT; tid++) { + for (q_idx = 0; q_idx < sawf_max_user_queues; q_idx++) { + stats = &sawf_stats->tx_delay_stats[tid][q_idx]; + delay = &delay_stats->delay[tid][q_idx]; ++ if (peer_ctx->telemetry_peer_ctx) { ++ msduq = u16_encode_bits(q_idx, MSDUQID_Q_MASK) | ++ u16_encode_bits(tid, MSDUQID_TID_MASK); ++ ath12k_telemetry_get_mov_avg(peer_ctx->telemetry_peer_ctx, ++ tid, msduq, &nwdelay_avg, ++ &swdelay_avg, &hwdelay_avg); ++ msduq = 0; ++ } ++ stats->nwdelay_avg = nwdelay_avg; ++ stats->swdelay_avg = swdelay_avg; ++ stats->hwdelay_avg = hwdelay_avg; + ath12k_copy_delay_stats(stats, delay); + } + } +@@ -1698,6 +1804,16 @@ static int ath12k_telemetry_get_delaysta + + stats = &sawf_stats->tx_delay_stats[tid][q_id]; + delay = &delay_stats->delay[0][0]; ++ if (peer_ctx->telemetry_peer_ctx) { ++ msduq = u16_encode_bits(q_id, MSDUQID_Q_MASK) | ++ u16_encode_bits(tid, MSDUQID_TID_MASK); ++ ath12k_telemetry_get_mov_avg(peer_ctx->telemetry_peer_ctx, ++ tid, msduq, &nwdelay_avg, ++ &swdelay_avg, &hwdelay_avg); ++ } ++ stats->nwdelay_avg = nwdelay_avg; ++ stats->swdelay_avg = swdelay_avg; ++ stats->hwdelay_avg = hwdelay_avg; + ath12k_copy_delay_stats(stats, delay); + delay_stats->tid = tid; + delay_stats->msduq = q_id; +@@ -1744,3 +1860,156 @@ int telemetry_extract_data(struct stats_ + + return ret; + } ++ ++int ath12k_telemetry_sla_reset_stats(u8 svc_id, u8 *peer_mac, u8 *mld_mac_addr, ++ u8 set_clear) ++{ ++ return ath12k_telemetry_reset_peer_stats(peer_mac); ++} ++ ++int ath12k_telemetry_get_sawf_tx_stats_tput(void *ptr, void *stats, u64 *in_bytes, ++ u64 *in_cnt, u64 *tx_bytes, ++ u64 *tx_cnt, u8 tid_v, u8 msduq_id) ++{ ++ struct ath12k_base *ab = (struct ath12k_base *)ptr; ++ struct ath12k_sawf_stats *sawf_stats = (struct ath12k_sawf_stats *)stats; ++ struct sawf_tx_stats *tx_stats = NULL; ++ int ret = 0; ++ u8 tid, q_id, sawf_max_q_per_tid; ++ ++ if (!ab && !sawf_stats) ++ return -ENODATA; ++ ++ spin_lock_bh(&ab->base_lock); ++ ++ tid = u8_get_bits(msduq_id, MSDUQID_TID_MASK); ++ q_id = u8_get_bits(msduq_id, MSDUQID_Q_MASK); ++ ++ sawf_max_q_per_tid = ab->max_msduq_per_tid - ab->default_msduq_per_tid; ++ ++ if (q_id > sawf_max_q_per_tid) { ++ ret = -EINVAL; ++ goto end; ++ } ++ ++ tx_stats = &sawf_stats->tx_stats[tid][q_id]; ++ if (!tx_stats) { ++ ret = -ENOENT; ++ goto end; ++ } ++ ++ *in_bytes = tx_stats->tx_ingress.bytes; ++ *in_cnt = tx_stats->tx_ingress.num_pkts; ++ *tx_bytes = tx_stats->tx_success.bytes; ++ *tx_cnt = tx_stats->tx_success.num_pkts; ++end: ++ spin_unlock_bh(&ab->base_lock); ++ return ret; ++} ++ ++int ath12k_telemetry_get_sawf_tx_stats_mpdu(void *ptr, void *stats, u64 *svc_int_pass, ++ u64 *svc_int_fail, u64 *burst_pass, ++ u64 *burst_fail, u8 tid_v, u8 msduq_id) ++{ ++ struct ath12k_base *ab = (struct ath12k_base *)ptr; ++ struct ath12k_sawf_stats *sawf_stats = (struct ath12k_sawf_stats *)stats; ++ struct sawf_tx_stats *tx_stats = NULL; ++ int ret = 0; ++ u8 tid, q_id, sawf_max_q_per_tid; ++ ++ if (!ab && !sawf_stats) ++ return -ENODATA; ++ ++ spin_lock_bh(&ab->base_lock); ++ ++ tid = u8_get_bits(msduq_id, MSDUQID_TID_MASK); ++ q_id = u8_get_bits(msduq_id, MSDUQID_Q_MASK); ++ ++ sawf_max_q_per_tid = ab->max_msduq_per_tid - ab->default_msduq_per_tid; ++ ++ if (q_id > sawf_max_q_per_tid) { ++ ret = -EINVAL; ++ goto end; ++ } ++ ++ tx_stats = &sawf_stats->tx_stats[tid][q_id]; ++ if (!tx_stats) { ++ ret = -ENOENT; ++ goto end; ++ } ++ ++ *svc_int_pass = tx_stats->svc_intval_stats.success_cnt; ++ *svc_int_fail = tx_stats->svc_intval_stats.failure_cnt; ++ *burst_pass = tx_stats->burst_size_stats.success_cnt; ++ *burst_fail = tx_stats->burst_size_stats.failure_cnt; ++end: ++ spin_unlock_bh(&ab->base_lock); ++ return ret; ++} ++ ++int ath12k_telemetry_get_sawf_tx_stats_drop(void *ptr, void *stats, u64 *pass, ++ u64 *drop, u64 *drop_ttl, ++ u8 tid_v, u8 msduq_id) ++{ ++ struct ath12k_base *ab = (struct ath12k_base *)ptr; ++ struct ath12k_sawf_stats *sawf_stats = (struct ath12k_sawf_stats *)stats; ++ struct sawf_tx_stats *tx_stats = NULL; ++ int ret = 0; ++ u8 tid, q_id, sawf_max_q_per_tid; ++ ++ if (!ab && !sawf_stats) ++ return -ENODATA; ++ ++ spin_lock_bh(&ab->base_lock); ++ ++ tid = u8_get_bits(msduq_id, MSDUQID_TID_MASK); ++ q_id = u8_get_bits(msduq_id, MSDUQID_Q_MASK); ++ ++ sawf_max_q_per_tid = ab->max_msduq_per_tid - ab->default_msduq_per_tid; ++ ++ if (q_id > sawf_max_q_per_tid) { ++ ret = -EINVAL; ++ goto end; ++ } ++ ++ tx_stats = &sawf_stats->tx_stats[tid][q_id]; ++ if (!tx_stats) { ++ ret = -ENOENT; ++ goto end; ++ } ++ ++ *pass = tx_stats->tx_success.num_pkts; ++ *drop = tx_stats->tx_failed; ++ *drop_ttl = tx_stats->dropped.age_out; ++end: ++ spin_unlock_bh(&ab->base_lock); ++ return ret; ++} ++ ++void ath12k_telemetry_notify_breach(u8 *mac_addr, u8 svc_id, u8 param, ++ bool set_clear, u8 tid) ++{ ++ struct ieee80211_vif *vif = NULL; ++ struct ath12k_base *ab = NULL; ++ struct ath12k_peer *peer = NULL; ++ u8 *mld_addr = NULL; ++ ++ if (!mac_addr) ++ return; ++ ++ peer = (struct ath12k_peer *)ath12k_get_ab_nd_peer_from_peer_mac(mac_addr, &ab); ++ if (peer && ab) { ++ spin_lock_bh(&ab->base_lock); ++ vif = peer->vif; ++ if (peer->peer_id & ATH12K_ML_PEER_ID_VALID) ++ mld_addr = peer->ml_addr; ++ spin_unlock_bh(&ab->base_lock); ++ ath12k_vendor_telemetry_notify_breach(vif, mac_addr, svc_id, param, ++ set_clear, tid, mld_addr); ++ } else { ++ ath12k_dbg(NULL, ATH12K_DBG_SAWF, "Peer(%pM) not found for notifying breach", ++ mac_addr); ++ } ++ ++ return; ++} +--- a/drivers/net/wireless/ath/ath12k/telemetry.c ++++ b/drivers/net/wireless/ath/ath12k/telemetry.c +@@ -9,7 +9,8 @@ + #include "vendor.h" + #include "telemetry.h" + #include +- ++#include "telemetry_agent_if.h" ++#include "telemetry_agent_wifi_driver_if.h" + + #define MIN_THERSHOLD_PERCENTAGE 0 + #define MAX_THERSHOLD_PERCENTAGE 100 +@@ -73,6 +74,12 @@ int ath12k_telemetry_sawf_sla_samples_co + telemetry_param->sla_num_pkt = param.sla_num_pkt; + telemetry_param->sla_time_sec = param.sla_time_sec; + ++ ath12k_telemetry_set_mov_avg_params(telemetry_param->moving_avg_pkt, ++ telemetry_param->moving_avg_win); ++ ++ ath12k_telemetry_set_sla_params(telemetry_param->sla_num_pkt, ++ telemetry_param->sla_time_sec); ++ + ath12k_info(NULL, "telemetry sla samples configuration done, " + "movavgpkt:%d movavgwin:%d slanumpkt:%d slatimesec:%d \n", + telemetry_param->moving_avg_pkt,telemetry_param->moving_avg_win, +@@ -114,6 +121,15 @@ int ath12k_telemetry_sawf_sla_thershold_ + sla_thershold_param->msdu_ttl = param.msdu_ttl; + sla_thershold_param->msdu_rate_loss = param.msdu_rate_loss; + ++ ath12k_telemetry_set_sla_cfg(sla_thershold_param->svc_id, ++ sla_thershold_param->min_throughput_rate, ++ sla_thershold_param->max_throughput_rate, ++ sla_thershold_param->burst_size, ++ sla_thershold_param->service_interval, ++ sla_thershold_param->delay_bound, ++ sla_thershold_param->msdu_ttl, ++ sla_thershold_param->msdu_rate_loss); ++ + ath12k_info(NULL, "telemetry sla thershold configuration done, " + "svcid: %d MinThrRate:%d MaxThrRate:%d BurstSize:%d " + "serviceInt:%d \n DelayBound: %d MsduTtl:%d " +@@ -172,6 +188,15 @@ int ath12k_telemetry_sawf_sla_detection_ + telemetry_param->msdu_ttl = param.msdu_ttl; + telemetry_param->msdu_rate_loss = param.msdu_rate_loss; + ++ ath12k_telemetry_set_sla_detect_cfg(telemetry_param->sla_detect, ++ telemetry_param->min_throughput_rate, ++ telemetry_param->max_throughput_rate, ++ telemetry_param->burst_size, ++ telemetry_param->service_interval, ++ telemetry_param->delay_bound, ++ telemetry_param->msdu_ttl, ++ telemetry_param->msdu_rate_loss); ++ + ath12k_info(NULL, "telemetry sla detection configuration done, detect option: %d " + "MinThrRate:%d MaxThrRate:%d BurstSize:%d ServiceInt:%d \n DelayBound: %d " + "MsduTtl:%d MsduRateLoss:%d \n", telemetry_param->sla_detect, +@@ -182,3 +207,25 @@ int ath12k_telemetry_sawf_sla_detection_ + + return ret; + } ++ ++bool ath12k_telemetry_get_sla_mov_avg_num_pkt(u32 *mov_avg) ++{ ++ if (!telemetry_ctx) { ++ mov_avg = 1; ++ return false; ++ } ++ ++ *mov_avg = telemetry_ctx->sla_samples_params.moving_avg_pkt; ++ return true; ++} ++ ++bool ath12k_telemetry_get_sla_num_pkts(u32 *pkt_num) ++{ ++ if (!telemetry_ctx) { ++ pkt_num = 1; ++ return false; ++ } ++ ++ *pkt_num = telemetry_ctx->sla_samples_params.sla_num_pkt; ++ return true; ++} +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/telemetry_agent_app_if.h +@@ -0,0 +1,188 @@ ++/* ++ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. ++ * ++ * 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 __TELEMETRY_AGENT_APP_IF_H__ ++#define __TELEMETRY_AGENT_APP_IF_H__ ++ ++#define MAX_SOCS 5 ++#define MAX_PDEV_LINKS 2 ++#define MAX_MLO_PEERS 128 ++#define NUM_TIDS 8 ++#define RFS_INIT_DATA 1 ++#define RFS_STATS_DATA 2 ++#define WLAN_VENDOR_EHTCAP_TXRX_MCS_NSS_IDX_MAX 4 ++#define MAX_T2LM_INFO 2 ++#define WLAN_AC_MAX 4 ++ ++/* ++ Buffer Format ++ -------------------------------------------- ++ | | | | ++ | HEADER | Payload (stats) | Tail Data | ++ | | | | ++ -------------------------------------------- ++ */ ++ ++#define MAX_PEERS 512 ++ ++struct emesh_peer_stats { ++ u8 peer_link_mac[6]; ++ u16 tx_airtime_consumption[WLAN_AC_MAX]; ++}; ++ ++struct emesh_link_stats { ++ u8 link_mac[6]; ++ u8 link_idle_airtime; ++ int num_peers; ++ struct emesh_peer_stats peer_stats[MAX_PEERS]; ++}; ++ ++struct emesh_soc_stats { ++ int num_links; ++ struct emesh_link_stats link_stats[MAX_PDEV_LINKS]; ++}; ++ ++ ++struct emesh_relyfs_stats { ++ int num_soc; ++ struct emesh_soc_stats soc_stats[MAX_SOCS]; ++}; ++ ++struct telemetry_agent_header { ++ u32 start_magic_num; ++ u32 stats_version; ++ u32 stats_type; ++ u32 payload_len; ++} __attribute__ ((__packed__)); ++ ++struct telemetry_emesh_buffer { ++ struct telemetry_agent_header header; ++ struct emesh_relyfs_stats relayfs_stats; ++ u32 end_magic_num; ++}; ++ ++enum wlan_vendor_channel_width { ++ WLAN_VENDOR_CHAN_WIDTH_INVALID = 0, ++ WLAN_VENDOR_CHAN_WIDTH_20MHZ = 1, ++ WLAN_VENDOR_CHAN_WIDTH_40MHZ = 2, ++ WLAN_VENDOR_CHAN_WIDTH_80MHZ = 3, ++ WLAN_VENDOR_CHAN_WIDTH_160MZ = 4, ++ WLAN_VENDOR_CHAN_WIDTH_80_80MHZ = 5, ++ WLAN_VENDOR_CHAN_WIDTH_320MHZ = 6, ++}; ++ ++enum t2lm_band_caps { ++ T2LM_BAND_INVALID, ++ T2LM_BAND_2GHz, ++ T2LM_BAND_5GHz, ++ T2LM_BAND_5GHz_LOW, ++ T2LM_BAND_5GHz_HIGH, ++ T2LM_BAND_6Ghz, ++ T2LM_BAND_6Ghz_LOW, ++ T2LM_BAND_6GHz_HIGH, ++}; ++ ++enum wlan_vendor_t2lm_direction { ++ WLAN_VENDOR_T2LM_INVALID_DIRECTION = 0, ++ WLAN_VENDOR_T2LM_DOWNLINK_DIRECTION = 1, ++ WLAN_VENDOR_T2LM_UPLINK_DIRECTION = 2, ++ WLAN_VENDOR_T2LM_BIDI_DIRECTION = 3, ++ WLAN_VENDOR_T2LM_MAX_VALID_DIRECTION = ++ WLAN_VENDOR_T2LM_BIDI_DIRECTION, ++}; ++ ++struct agent_peer_stats { ++ u8 peer_mld_mac[6]; ++ u8 peer_link_mac[6]; ++ u8 airtime_consumption[WLAN_AC_MAX]; ++ u8 m1_stats; ++ u8 m2_stats; ++ s8 rssi; ++ u16 sla_mask; /* Uses telemetry_sawf_param for bitmask */ ++}; ++ ++struct agent_link_stats { ++ u16 hw_link_id; ++ u8 link_airtime[WLAN_AC_MAX]; ++ u8 freetime; ++ u8 available_airtime[WLAN_AC_MAX]; ++ u32 m3_stats[WLAN_AC_MAX]; ++ u32 m4_stats[WLAN_AC_MAX]; ++ u16 num_peers; ++ struct agent_peer_stats peer_stats[MAX_MLO_PEERS]; ++}; ++ ++struct agent_soc_stats { ++ u8 soc_id; ++ u16 num_peers; ++ u8 num_links; ++ struct agent_link_stats link_stats[MAX_PDEV_LINKS]; ++}; ++ ++/* Periodic Stats */ ++struct relayfs_stats { ++ u8 num_soc; ++ struct agent_soc_stats soc_stats[MAX_SOCS]; ++}; ++ ++/* ++ * Init time interface information - complete view. ++ */ ++struct link_map_of_tids { ++ enum wlan_vendor_t2lm_direction direction; /* 0-DL, 1-UL, 2-BiDi */ ++ u8 default_link_mapping; ++ u8 tid_present[NUM_TIDS]; /* TID present on this link */ ++}; ++ ++struct agent_peer_init_stats { ++ u8 mld_mac_addr[6]; /* peer MLD mac */ ++ u8 link_mac_addr[6]; /* peer MLD link mac */ ++ struct link_map_of_tids t2lm_info[MAX_T2LM_INFO]; /* T2LM mapping */ ++ enum wlan_vendor_channel_width chan_bw; ++ u16 chan_freq; /* channel center frequency */ ++ u32 tx_mcs_nss_map[WLAN_VENDOR_EHTCAP_TXRX_MCS_NSS_IDX_MAX]; ++ u32 rx_mcs_nss_map[WLAN_VENDOR_EHTCAP_TXRX_MCS_NSS_IDX_MAX]; ++ u8 ieee_link_id; ++}; ++ ++struct agent_link_init_stats { ++ u16 hw_link_id; ++ /* enum t2lm_band_caps band; */ ++ u16 num_peers; ++ struct agent_peer_init_stats peer_stats[MAX_MLO_PEERS]; ++}; ++ ++struct agent_soc_init_stats { ++ u8 soc_id; ++ u16 num_peers; ++ u8 num_links; ++ struct agent_link_init_stats link_stats[MAX_PDEV_LINKS]; ++}; ++ ++struct relayfs_init_stats { ++ u8 num_soc; ++ struct agent_soc_init_stats soc_stats[MAX_SOCS]; ++}; ++ ++struct telemetry_buffer { ++ struct telemetry_agent_header header; ++ union { ++ struct relayfs_stats periodic_stats; ++ struct relayfs_init_stats init_stats; ++ } u; ++ u32 end_magic_num; ++}; ++ ++#endif /* __TELEMETRY_AGENT_APP_IF_H__ */ +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/telemetry_agent_if.c +@@ -0,0 +1,348 @@ ++// SPDX-License-Identifier: BSD-3-Clause-Clear ++/* ++ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include "core.h" ++#include "debug.h" ++#include "sawf.h" ++#include ++#include "telemetry.h" ++#include "telemetry_agent_if.h" ++#include "telemetry_agent_wifi_driver_if.h" ++#include ++ ++int ath12k_get_pdev_stats(void *obj, struct agent_link_iface_stats_obj *stats); ++int ath12k_get_peer_info(void *obj, struct agent_peer_iface_init_obj *stats); ++int ath12k_get_pdev_info(void *obj, struct agent_pdev_iface_init_obj *stats); ++int ath12k_get_peer_stats(void *obj, struct agent_peer_iface_stats_obj *stats); ++int ath12k_get_psoc_info(void *obj, struct agent_psoc_iface_init_obj *stats); ++ ++struct telemetry_agent_ops *g_agent_ops; ++EXPORT_SYMBOL(g_agent_ops); ++ ++int register_telemetry_agent_ops(struct telemetry_agent_ops *agent_ops); ++int unregister_telemetry_agent_ops(struct telemetry_agent_ops *agent_ops); ++ ++int register_telemetry_agent_ops(struct telemetry_agent_ops *agent_ops) ++{ ++ g_agent_ops = agent_ops; ++ g_agent_ops->agent_get_psoc_info = ath12k_get_psoc_info; ++ g_agent_ops->agent_get_pdev_info = ath12k_get_pdev_info; ++ g_agent_ops->agent_get_peer_info = ath12k_get_peer_info; ++ g_agent_ops->agent_get_pdev_stats = ath12k_get_pdev_stats; ++ g_agent_ops->agent_get_peer_stats = ath12k_get_peer_stats; ++ g_agent_ops->agent_get_emesh_pdev_stats = NULL; ++ g_agent_ops->agent_get_emesh_peer_stats = NULL; ++ ++ /* SAWF ops */ ++ g_agent_ops->sawf_get_tput_stats = ath12k_sawf_get_tput_stats; ++ g_agent_ops->sawf_get_mpdu_stats = ath12k_sawf_get_mpdu_stats; ++ g_agent_ops->sawf_get_drop_stats = ath12k_sawf_get_drop_stats; ++ g_agent_ops->sawf_notify_breach = ath12k_sawf_notify_breach; ++ ++ ath12k_info(NULL, "registered telemetry agent ops: %p", g_agent_ops); ++ return 0; ++} ++EXPORT_SYMBOL(register_telemetry_agent_ops); ++ ++int unregister_telemetry_agent_ops(struct telemetry_agent_ops *agent_ops) ++{ ++ g_agent_ops = NULL; ++ ath12k_info(NULL, "unregistered telemetry agent ops: %p", g_agent_ops); ++ return 0; ++} ++EXPORT_SYMBOL(unregister_telemetry_agent_ops); ++ ++u32 ath12k_telemetry_agent_init(void) ++{ ++ int status = 0; ++ /* TODO */ ++ ath12k_info(NULL, "telemetry agent init Done\n"); ++ return status; ++} ++ ++u32 ath12k_telemetry_agent_deinit(void) ++{ ++ int status = 0; ++ /* TODO */ ++ ath12k_info(NULL, "telemetry agent deinit\n"); ++ return status; ++} ++ ++int ath12k_get_pdev_stats(void *obj, struct agent_link_iface_stats_obj *stats) ++{ ++ ath12k_warn(NULL, "ath12k_get_pdev_stats - not implemented \n"); ++ return -1; ++} ++ ++int ath12k_get_peer_info(void *obj, struct agent_peer_iface_init_obj *stats) ++{ ++ ath12k_warn(NULL, "ath12k_get_peer_info - not implemented \n"); ++ return -1; ++} ++ ++int ath12k_get_pdev_info(void *obj, struct agent_pdev_iface_init_obj *stats) ++{ ++ ath12k_warn(NULL, "ath12k_get_pdev_info - not implemented \n"); ++ return -1; ++} ++ ++int ath12k_get_peer_stats(void *obj, struct agent_peer_iface_stats_obj *stats) ++{ ++ ath12k_warn(NULL, "ath12k_get_peer_stats - not implemented \n"); ++ return -1; ++} ++ ++int ath12k_get_psoc_info(void *obj, struct agent_psoc_iface_init_obj *stats) ++{ ++ ath12k_warn(NULL, "ath12k_get_peer_stats - not implemented \n"); ++ return -1; ++} ++ ++void *ath12k_telemetry_peer_ctx_alloc(void *peer, void *sawf_stats, ++ u8 *mac_addr, ++ u8 svc_id, u8 hostq_id) ++{ ++ if (g_agent_ops) ++ return g_agent_ops->sawf_alloc_peer(peer, sawf_stats, ++ mac_addr, ++ svc_id, ++ hostq_id); ++ return NULL; ++} ++ ++void ath12k_telemetry_peer_ctx_free(void *telemetry_peer_ctx) ++{ ++ if (g_agent_ops) ++ g_agent_ops->sawf_free_peer(telemetry_peer_ctx); ++} ++ ++bool ath12k_telemetry_update_tid_msduq(void *telemetry_peer_ctx, ++ u8 hostq_id, u8 tid, u8 msduq_idx) ++{ ++ if (g_agent_ops) { ++ if (g_agent_ops->sawf_updt_queue_info(telemetry_peer_ctx, ++ hostq_id, tid, ++ msduq_idx)) ++ return false; ++ } ++ ++ return true; ++} ++ ++bool ath12k_telemetry_set_mov_avg_params(u32 num_pkt, ++ u32 num_win) ++{ ++ if (g_agent_ops) { ++ if (g_agent_ops->sawf_updt_delay_mvng(num_pkt, num_win)) ++ return false; ++ } ++ ++ return true; ++} ++ ++bool ath12k_telemetry_set_sla_params(u32 num_pkt, ++ u32 time_sec) ++{ ++ if (g_agent_ops) { ++ if (g_agent_ops->sawf_updt_sla_params(num_pkt, time_sec)) ++ return false; ++ } ++ ++ return true; ++} ++ ++bool ath12k_telemetry_set_sla_cfg(u8 svc_id, ++ u8 min_tput_rate, ++ u8 max_tput_rate, ++ u8 burst_size, ++ u8 svc_interval, ++ u8 delay_bound, ++ u8 msdu_ttl, ++ u8 msdu_rate_loss) ++{ ++ if (g_agent_ops) { ++ if (g_agent_ops->sawf_set_sla_cfg(svc_id, ++ min_tput_rate, ++ max_tput_rate, ++ burst_size, ++ svc_interval, ++ delay_bound, ++ msdu_ttl, ++ msdu_rate_loss)) ++ return false; ++ } ++ ++ return true; ++} ++ ++bool ath12k_telemetry_set_svclass_cfg(bool enable, u8 svc_id, ++ u32 min_tput_rate, ++ u32 max_tput_rate, ++ u32 burst_size, ++ u32 svc_interval, ++ u32 delay_bound, ++ u32 msdu_ttl, ++ u32 msdu_rate_loss) ++{ ++ if (g_agent_ops) { ++ if (g_agent_ops->sawf_set_svclass_cfg(enable, svc_id, ++ min_tput_rate, ++ max_tput_rate, ++ burst_size, ++ svc_interval, ++ delay_bound, ++ msdu_ttl, ++ msdu_rate_loss)) ++ return false; ++ } ++ ++ return true; ++} ++ ++bool ath12k_telemetry_set_sla_detect_cfg(u8 detect_type, ++ u8 min_tput_rate, ++ u8 max_tput_rate, ++ u8 burst_size, ++ u8 svc_interval, ++ u8 delay_bound, ++ u8 msdu_ttl, ++ u8 msdu_rate_loss) ++{ ++ if (g_agent_ops) { ++ if (g_agent_ops->sawf_set_sla_dtct_cfg(detect_type, ++ min_tput_rate, ++ max_tput_rate, ++ burst_size, ++ svc_interval, ++ delay_bound, ++ msdu_ttl, ++ msdu_rate_loss)) ++ return false; ++ } ++ ++ return true; ++} ++ ++bool ath12k_telemetry_update_delay(void *telemetry_ctx, u8 tid, ++ u8 queue, u64 pass, ++ u64 fail) ++{ ++ if (g_agent_ops) { ++ if (g_agent_ops->sawf_push_delay(telemetry_ctx, tid, ++ queue, pass, fail)) ++ return false; ++ } ++ ++ return true; ++} ++ ++bool ath12k_telemetry_update_delay_mvng(void *telemetry_ctx, ++ u8 tid, u8 queue, ++ u64 nwdelay_winavg, ++ u64 swdelay_winavg, ++ u64 hwdelay_winavg) ++{ ++ if (g_agent_ops) { ++ if (g_agent_ops->sawf_push_delay_mvng(telemetry_ctx, ++ tid, queue, ++ nwdelay_winavg, ++ swdelay_winavg, ++ hwdelay_winavg)) ++ return false; ++ } ++ ++ return true; ++} ++ ++bool ath12k_telemetry_update_msdu_drop(void *telemetry_ctx, ++ u8 tid, u8 queue, ++ u64 success, ++ u64 failure_drop, ++ u64 failure_ttl) ++{ ++ if (g_agent_ops) { ++ if (g_agent_ops->sawf_push_msdu_drop(telemetry_ctx, tid, ++ queue, success, ++ failure_drop, ++ failure_ttl)) ++ return false; ++ } ++ ++ return true; ++} ++ ++bool ath12k_telemetry_get_rate(void *telemetry_ctx, u8 tid, ++ u8 queue, u32 *egress_rate, ++ u32 *ingress_rate) ++{ ++ if (g_agent_ops) { ++ if (g_agent_ops->sawf_pull_rate(telemetry_ctx, tid, queue, ++ egress_rate, ingress_rate)) ++ return false; ++ } ++ ++ return true; ++} ++ ++bool ath12k_telemetry_get_mov_avg(void *telemetry_ctx, u8 tid, ++ u8 queue, u32 *nwdelay_avg, ++ u32 *swdelay_avg, ++ u32 *hwdelay_avg) ++{ ++ if (g_agent_ops) { ++ if (g_agent_ops->sawf_pull_mov_avg(telemetry_ctx, tid, ++ queue, nwdelay_avg, ++ swdelay_avg, hwdelay_avg)) ++ return false; ++ } ++ ++ return true; ++} ++ ++int ath12k_telemetry_reset_peer_stats(u8 *peer_mac) ++{ ++ int ret = -EOPNOTSUPP; ++ ++ if (g_agent_ops) ++ ret = g_agent_ops->sawf_reset_peer_stats(peer_mac); ++ ++ return ret; ++} ++ ++int ath12k_sawf_get_tput_stats(void *soc, void *arg, u64 *in_bytes, ++ u64 *in_cnt, u64 *tx_bytes, ++ u64 *tx_cnt, u8 tid, u8 msduq) ++{ ++ return ath12k_telemetry_get_sawf_tx_stats_tput(soc, arg, ++ in_bytes, in_cnt, ++ tx_bytes, tx_cnt, ++ tid, msduq); ++} ++ ++int ath12k_sawf_get_mpdu_stats(void *soc, void *arg, u64 *svc_int_pass, ++ u64 *svc_int_fail, u64 *burst_pass, ++ u64 *burst_fail, u8 tid, u8 msduq) ++{ ++ return ath12k_telemetry_get_sawf_tx_stats_mpdu(soc, arg, svc_int_pass, ++ svc_int_fail, burst_pass, ++ burst_fail, tid, msduq); ++} ++ ++int ath12k_sawf_get_drop_stats(void *soc, void *arg, u64 *pass, ++ u64 *drop, u64 *drop_ttl, ++ u8 tid, u8 msduq) ++{ ++ return ath12k_telemetry_get_sawf_tx_stats_drop(soc, arg, pass, drop, ++ drop_ttl, tid, msduq); ++} ++ ++void ath12k_sawf_notify_breach(u8 *mac_addr, ++ u8 svc_id, ++ u8 param, ++ bool set_clear, ++ u8 tid) ++{ ++ ath12k_telemetry_notify_breach(mac_addr, svc_id, param, set_clear, tid); ++} +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/telemetry_agent_if.h +@@ -0,0 +1,67 @@ ++// SPDX-License-Identifier: BSD-3-Clause-Clear ++/* ++ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef ATH12K_TELEMETRY_AGENT_IF_H ++#define ATH12K_TELEMETRY_AGENT_IF_H ++ ++u32 ath12k_telemetry_agent_init(void); ++u32 ath12k_telemetry_agent_deinit(void); ++ ++int ath12k_sawf_get_tput_stats(void *soc, void *arg, u64 *in_bytes, ++ u64 *in_cnt, u64 *tx_bytes, ++ u64 *tx_cnt, u8 tid, u8 msduq); ++int ath12k_sawf_get_mpdu_stats(void *soc, void *arg, u64 *svc_int_pass, ++ u64 *svc_int_fail, u64 *burst_pass, ++ u64 *burst_fail, u8 tid, u8 msduq); ++int ath12k_sawf_get_drop_stats(void *soc, void *arg, u64 *pass, ++ u64 *drop, u64 *drop_ttl, ++ u8 tid, u8 msduq); ++void ath12k_sawf_notify_breach(u8 *mac_addr, u8 svc_id, u8 param, ++ bool set_clear, u8 tid); ++void *ath12k_telemetry_peer_ctx_alloc(void *peer, void *sawf_stats, ++ u8 *mac_addr, ++ u8 svc_id, u8 hostq_id); ++void ath12k_telemetry_peer_ctx_free(void *telemetry_peer_ctx); ++bool ath12k_telemetry_update_tid_msduq(void *telemetry_peer_ctx, ++ u8 hostq_id, u8 tid, u8 msduq_idx); ++bool ath12k_telemetry_set_mov_avg_params(u32 num_pkt, u32 num_win); ++bool ath12k_telemetry_set_sla_params(u32 num_pkt, u32 time_sec); ++bool ath12k_telemetry_set_sla_cfg(u8 svc_id, u8 min_tput_rate, u8 max_tput_rate, ++ u8 burst_size, u8 svc_interval, u8 delay_bound, ++ u8 msdu_ttl, u8 msdu_rate_loss); ++bool ath12k_telemetry_set_svclass_cfg(bool enable, u8 svc_id, ++ u32 min_tput_rate, ++ u32 max_tput_rate, ++ u32 burst_size, ++ u32 svc_interval, ++ u32 delay_bound, ++ u32 msdu_ttl, ++ u32 msdu_rate_loss); ++bool ath12k_telemetry_set_sla_detect_cfg(u8 detect_type, ++ u8 min_tput_rate, ++ u8 max_tput_rate, ++ u8 burst_size, ++ u8 svc_interval, ++ u8 delay_bound, ++ u8 msdu_ttl, ++ u8 msdu_rate_loss); ++bool ath12k_telemetry_update_delay(void *telemetry_ctx, u8 tid, ++ u8 queue, u64 pass, u64 fail); ++bool ath12k_telemetry_update_delay_mvng(void *telemetry_ctx, ++ u8 tid, u8 queue, ++ u64 nwdelay_winavg, ++ u64 swdelay_winavg, ++ u64 hwdelay_winavg); ++bool ath12k_telemetry_update_msdu_drop(void *telemetry_ctx, u8 tid, ++ u8 queue, u64 success, ++ u64 failure_drop, ++ u64 failure_ttl); ++bool ath12k_telemetry_get_rate(void *telemetry_ctx, u8 tid, u8 queue, ++ u32 *egress_rate, u32 *ingress_rate); ++bool ath12k_telemetry_get_mov_avg(void *telemetry_ctx, u8 tid, u8 queue, ++ u32 *nwdelay_avg, u32 *swdelay_avg, ++ u32 *hwdelay_avg); ++int ath12k_telemetry_reset_peer_stats(u8 *peer_mac); ++#endif /* ATH12K_TELEMETRY_AGENT_IF_H */ +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/telemetry_agent_wifi_driver_if.h +@@ -0,0 +1,208 @@ ++/* ++ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. ++ * ++ * 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 __TELEMETRY_AGENT_WIFI_DRIVER_IF_H__ ++#define __TELEMETRY_AGENT_WIFI_DRIVER_IF_H__ ++ ++#include "telemetry_agent_app_if.h" ++struct agent_psoc_obj { ++ void *psoc_back_pointer; ++ spinlock_t psoc_lock; ++ u8 psoc_id; ++}; ++ ++struct agent_pdev_obj { ++ void *pdev_back_pointer; ++ void *psoc_back_pointer; ++ spinlock_t pdev_lock; ++ u8 psoc_id; ++ u8 pdev_id; ++}; ++ ++struct agent_peer_obj { ++ void *peer_back_pointer; ++ void *pdev_back_pointer; ++ void *psoc_back_pointer; ++ spinlock_t peer_lock; ++ u8 psoc_id; ++ u8 pdev_id; ++ u8 peer_mac_addr[6]; ++}; ++ ++enum agent_notification_event { ++ AGENT_NOTIFY_EVENT_INIT, ++ AGENT_NOTIFY_EVENT_DEINIT, ++}; ++ ++enum agent_params { ++ AGENT_INVALID_PARAM, ++ AGENT_SET_DEBUG_LEVEL, ++}; ++ ++struct t2lm_of_tids { ++ enum wlan_vendor_t2lm_direction direction; /* 0-DL, 1-UL, 2-BiDi */ ++ u8 default_link_mapping; ++ u16 t2lm_provisioned_links[NUM_TIDS]; /*Bit0 for link0, bit1 for link1 and so on*/ ++}; ++ ++struct eht_peer_caps { ++ u32 tx_mcs_nss_map[WLAN_VENDOR_EHTCAP_TXRX_MCS_NSS_IDX_MAX]; ++ u32 rx_mcs_nss_map[WLAN_VENDOR_EHTCAP_TXRX_MCS_NSS_IDX_MAX]; ++}; ++ ++struct agent_peer_iface_init_obj { ++ u8 peer_mld_mac[6]; ++ u8 peer_link_mac[6]; ++ u8 bw; ++ u16 freq; ++ struct t2lm_of_tids t2lm_info[WLAN_VENDOR_T2LM_MAX_VALID_DIRECTION]; /* T2LM mapping */ ++ struct eht_peer_caps caps; /* Peer capabilities */ ++ u8 ieee_link_id; ++}; ++ ++struct agent_pdev_iface_init_obj { ++ /* This info is stroed in telemetry pdev object, ++ * so this can be ignored for now ++ */ ++ u16 link_id; ++ u8 soc_id; ++ u8 band; ++}; ++ ++struct agent_psoc_iface_init_obj { ++ u8 soc_id; ++ u16 max_peers; ++ u16 num_peers; ++ ++}; ++ ++struct agent_peer_iface_stats_obj { ++ u8 peer_mld_mac[6]; ++ u8 peer_link_mac[6]; ++ u8 airtime_consumption[WLAN_AC_MAX]; ++ u32 tx_mpdu_retried; ++ u32 tx_mpdu_total; ++ u32 rx_mpdu_retried; ++ u32 rx_mpdu_total; ++ u8 rssi; ++ u16 sla_mask; /* Uses telemetry_sawf_param for bitmask */ ++}; ++ ++struct agent_link_iface_stats_obj { ++ u16 link_id; ++ u8 soc_id; ++ u8 available_airtime[WLAN_AC_MAX]; ++ u32 congestion[WLAN_AC_MAX]; ++ u32 tx_mpdu_failed[WLAN_AC_MAX]; ++ u32 tx_mpdu_total[WLAN_AC_MAX]; ++ u8 link_airtime[WLAN_AC_MAX]; ++ u8 freetime; ++}; ++ ++struct emesh_peer_iface_stats_obj { ++ u8 peer_link_mac[6]; ++ u16 tx_airtime_consumption[WLAN_AC_MAX]; ++}; ++ ++struct emesh_link_iface_stats_obj { ++ u8 link_mac[6]; ++ u8 link_idle_airtime; ++}; ++ ++struct telemetry_agent_ops { ++ int (*agent_psoc_create_handler) (void *arg, struct agent_psoc_obj *psoc_obj); ++ int (*agent_psoc_destroy_handler) (void *arg, struct agent_psoc_obj *psoc_obj); ++ int (*agent_pdev_create_handler) (void *arg, struct agent_pdev_obj *pdev_obj); ++ int (*agent_pdev_destroy_handler) (void *arg, struct agent_pdev_obj *pdev_obj); ++ int (*agent_peer_create_handler) (void *arg, struct agent_peer_obj *peer_obj); ++ int (*agent_peer_destroy_handler) (void *arg, struct agent_peer_obj *peer_obj); ++ int (*agent_set_param) (int command, int value); ++ int (*agent_get_param) (int command); ++ void (*agent_notify_app_event) (enum agent_notification_event); ++ void (*agent_notify_emesh_event) (enum agent_notification_event); ++ int (*agent_get_psoc_info) (void *obj, struct agent_psoc_iface_init_obj *stats); ++ int (*agent_get_pdev_info) (void *obj, struct agent_pdev_iface_init_obj *stats); ++ int (*agent_get_peer_info) (void *obj, struct agent_peer_iface_init_obj *stats); ++ int (*agent_get_pdev_stats) (void *obj, struct agent_link_iface_stats_obj *stats); ++ int (*agent_get_peer_stats) (void *obj, struct agent_peer_iface_stats_obj *stats); ++ int (*agent_get_emesh_pdev_stats) (void *obj, struct emesh_link_iface_stats_obj *stats); ++ int (*agent_get_emesh_peer_stats) (void *obj, struct emesh_peer_iface_stats_obj *stats); ++ ++ /* SAWF ops */ ++ void * (*sawf_alloc_peer) (void *sawf_ctx, void *sawf_stats_ctx, ++ uint8_t *mac_addr, ++ uint8_t svc_id, uint8_t hostq_id); ++ void (* sawf_free_peer) (void *telemetry_sawf_ctx); ++ int (* sawf_updt_queue_info) (void *telemetry_sawf_ctx, ++ uint8_t svc_id, ++ uint8_t tid, uint8_t msduq_idx); ++ int (* sawf_updt_delay_mvng) (uint32_t num_win, uint32_t num_pkt); ++ int (* sawf_updt_sla_params) (uint32_t num_pkt, uint32_t time_sec); ++ int (* sawf_set_sla_cfg) (uint8_t svc_id, uint8_t min_thruput_rate, ++ uint8_t max_thruput_rate, ++ uint8_t burst_size, ++ uint8_t service_interval, ++ uint8_t delay_bound, uint8_t msdu_ttl, ++ uint8_t msdu_rate_loss); ++ int (* sawf_set_svclass_cfg) (bool enable, uint8_t svclass_id, ++ uint32_t min_thruput_rate, ++ uint32_t max_thruput_rate, ++ uint32_t burst_size, ++ uint32_t service_interval, ++ uint32_t delay_bound, ++ uint32_t msdu_ttl, ++ uint32_t msdu_rate_loss); ++ int (* sawf_set_sla_dtct_cfg) (uint8_t detect_type, ++ uint8_t min_thruput_rate, ++ uint8_t max_thruput_rate, ++ uint8_t burst_size, ++ uint8_t service_interval, ++ uint8_t delay_bound, ++ uint8_t msdu_ttl, ++ uint8_t msdu_rate_loss); ++ int (* sawf_push_delay) (void *telemetry_sawf_ctx, uint8_t tid, ++ uint8_t queue, uint64_t pass, ++ uint64_t fail); ++ int (* sawf_push_delay_mvng) (void *telemetry_ctx, uint8_t tid, ++ uint8_t queue, uint64_t nwdelay_avg, ++ uint64_t swdelay_avg, ++ uint64_t hwdelay_avg); ++ int (* sawf_push_msdu_drop) (void * telemetry_sawf_ctx, uint8_t tid, ++ uint8_t queue, uint64_t pass, ++ uint64_t fail_drop, uint64_t fail_ttl); ++ int (* sawf_pull_rate) (void *telemetry_sawf_ctx, uint8_t tid, ++ uint8_t queue, uint32_t *egress_rate, ++ uint32_t *ingress_rate); ++ int (* sawf_pull_mov_avg) (void *telemetry_sawf_ctx, uint8_t tid, ++ uint8_t queue, uint32_t *nwdelay_avg, ++ uint32_t *swdelay_avg, uint32_t *hwdelay_avg); ++ int (* sawf_reset_peer_stats) (uint8_t *mac_addr); ++ int (* sawf_get_tput_stats) (void *soc, void *arg, uint64_t *in_bytes, ++ uint64_t *in_cnt, uint64_t *tx_bytes, ++ uint64_t *tx_cnt, uint8_t tid, ++ uint8_t msduq); ++ int (* sawf_get_mpdu_stats) (void *soc, void *arg, uint64_t *svc_int_pass, ++ uint64_t *svc_int_fail, uint64_t *burst_pass, ++ uint64_t *burst_fail, uint8_t tid, ++ uint8_t msduq); ++ int (* sawf_get_drop_stats) (void *soc, void *arg, uint64_t *pass, ++ uint64_t *drop, uint64_t *drop_ttl, ++ uint8_t tid, uint8_t msduq); ++ void (* sawf_notify_breach) (uint8_t *mac_addr, uint8_t svc_id, ++ uint8_t param, bool set_clear, uint8_t tid); ++}; ++ ++void wlan_cfg80211_t2lm_app_reply_init_response(void); ++#endif /* __TELEMETRY_AGENT_WIFI_DRIVER_IF_H__ */ +--- a/drivers/net/wireless/ath/ath12k/Makefile ++++ b/drivers/net/wireless/ath/ath12k/Makefile +@@ -33,7 +33,7 @@ ath12k-$(CPTCFG_ATH12K_PKTLOG) += pktlog + ath12k-$(CPTCFG_ATH12K_AHB) += ahb.o + ath12k-$(CPTCFG_ATH12K_PPE_DS_SUPPORT) += ppe.o + ath12k-$(CPTCFG_ATH12K_BONDED_DS_SUPPORT) += bondif.o +-ath12k-$(CPTCFG_ATH12K_SAWF) += sawf.o telemetry.o ++ath12k-$(CPTCFG_ATH12K_SAWF) += sawf.o telemetry.o telemetry_agent_if.o + + # for tracing framework to find trace.h + CFLAGS_trace.o := -I$(src) +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -22,6 +22,7 @@ + #include "ppe.h" + #include "ahb.h" + #include "telemetry.h" ++#include "peer.h" + + #ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT + #include +@@ -2635,6 +2636,43 @@ int ath12k_core_sawf_ul_config(struct ne + return ret; + } + ++void *ath12k_get_ab_nd_peer_from_peer_mac(u8 *peer_mac, struct ath12k_base **ab_ref) ++{ ++ struct ath12k_hw_group *ag = NULL; ++ struct ath12k_base *ab = NULL; ++ void *peer = NULL; ++ int soc; ++ ++ mutex_lock(&ath12k_hw_lock); ++ list_for_each_entry(ag, &ath12k_hw_groups, list) { ++ if (!ag) { ++ ath12k_warn(NULL, "unable to fetch hw group\n"); ++ mutex_unlock(&ath12k_hw_lock); ++ return -ENODEV; ++ } ++ for (soc = ag->num_probed; soc > 0; soc--) { ++ ++ ab = ag->ab[soc - 1]; ++ if (!ab) { ++ /* Control should not reach here */ ++ ath12k_info(NULL, "SOC not initialized\n"); ++ continue; ++ } ++ spin_lock_bh(&ab->base_lock); ++ peer = ath12k_peer_find_by_addr(ab, peer_mac); ++ spin_unlock_bh(&ab->base_lock); ++ if (peer) { ++ mutex_unlock(&ath12k_hw_lock); ++ *ab_ref = ab; ++ return peer; ++ } ++ ab = NULL; ++ } ++ } ++ mutex_unlock(&ath12k_hw_lock); ++ return peer; ++} ++ + #endif /* CPTCFG_ATH12K_SAWF */ + + static int ath12k_init(void) +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -29,6 +29,7 @@ + #include "pktlog.h" + #include "sawf.h" + #include "vendor.h" ++#include "telemetry_agent_if.h" + #ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT + #include + #include +@@ -1611,6 +1612,7 @@ void ath12k_fw_stats_free(struct ath12k_ + int ath12k_send_sawf_configs_soc(struct ath12k_sawf_svc_params *new_param); + int ath12k_sawf_send_disable_soc(u8 svc_id); + int ath12k_core_sawf_ul_config(struct net_device *dev, struct ath12k_sawf_wmi_peer_latency_param *latency_info); ++void *ath12k_get_ab_nd_peer_from_peer_mac(u8 *peer_mac, struct ath12k_base **ab_ref); + #endif /* CPTCFG_ATH12K_SAWF */ + + static inline const char *ath12k_scan_state_str(enum ath12k_scan_state state) +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -2045,8 +2045,10 @@ static void ath12k_htt_sawf_info_ind_han + struct sk_buff *skb) + { + struct htt_t2h_sawf_info_ind *resp = (struct htt_t2h_sawf_info_ind *)skb->data; +- u32 htt_qtype, remapped_tid, peer_id; +- u32 hlos_tid, flow_or, ast_idx, who_cl, tgt_opaque_id; ++ struct ath12k_peer *peer = NULL; ++ u32 htt_qtype, remapped_tid, peer_id, default_msduq_per_tid, default_msduq_max, sawf_msduq_per_tid; ++ u32 hlos_tid, flow_or, ast_idx, who_cl, tgt_opaque_id, sawf_msduq_max; ++ u8 msduq_index; + + htt_qtype = u32_get_bits(__le32_to_cpu(resp->info0), + HTT_T2H_SAWF_MSDUQ_INFO_0_IND_HTT_QTYPE_ID); +@@ -2080,6 +2082,24 @@ static void ath12k_htt_sawf_info_ind_han + flow_or, + ast_idx, + tgt_opaque_id); ++ spin_lock_bh(&ab->base_lock); ++ ++ default_msduq_per_tid = ab->default_msduq_per_tid; ++ sawf_msduq_per_tid = ab->max_msduq_per_tid - ab->default_msduq_per_tid; ++ default_msduq_max = default_msduq_per_tid * ATH12K_SAWF_MAX_TID_SUPPORT; ++ sawf_msduq_max = sawf_msduq_per_tid * ATH12K_SAWF_MAX_TID_SUPPORT; ++ msduq_index = ((who_cl * default_msduq_max) + ++ (flow_or * ATH12K_SAWF_MAX_TID_SUPPORT) + hlos_tid) - ++ default_msduq_max; ++ ++ peer = ath12k_peer_find_by_id(ab, peer_id); ++ if ((msduq_index < sawf_msduq_max) && peer) { ++ if (peer->sawf_ctx_peer.telemetry_peer_ctx) ++ ath12k_telemetry_update_tid_msduq(peer->sawf_ctx_peer.telemetry_peer_ctx, ++ msduq_index ,remapped_tid, ++ (htt_qtype - default_msduq_per_tid)); ++ } ++ spin_unlock_bh(&ab->base_lock); + } + #endif /* CPTCFG_ATH12K_SAWF */ + void ath12k_dp_htt_htc_t2h_msg_handler(struct ath12k_base *ab, +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -1039,6 +1039,10 @@ void ath12k_mac_peer_cleanup_all(struct + ath12k_dp_rx_peer_tid_cleanup(ar, peer); + ath12k_peer_rhash_delete(ab, peer); + list_del(&peer->list); ++#ifdef CPTCFG_ATH12K_SAWF ++ if (peer->sawf_ctx_peer.telemetry_peer_ctx) ++ ath12k_telemetry_peer_ctx_free(peer->sawf_ctx_peer.telemetry_peer_ctx); ++#endif + kfree(peer); + } + spin_unlock_bh(&ab->base_lock); +@@ -6749,6 +6753,10 @@ static void ath12k_mac_station_post_remo + ath12k_peer_rhash_delete(ar->ab, peer); + peer->sta = NULL; + list_del(&peer->list); ++#ifdef CPTCFG_ATH12K_SAWF ++ if (peer->sawf_ctx_peer.telemetry_peer_ctx) ++ ath12k_telemetry_peer_ctx_free(peer->sawf_ctx_peer.telemetry_peer_ctx); ++#endif + kfree(peer); + ar->num_peers--; + } +--- a/drivers/net/wireless/ath/ath12k/peer.c ++++ b/drivers/net/wireless/ath/ath12k/peer.c +@@ -141,6 +141,10 @@ void ath12k_peer_unmap_event(struct ath1 + peer->vdev_id, peer->addr, peer_id); + + list_del(&peer->list); ++#ifdef CPTCFG_ATH12K_SAWF ++ if (peer->sawf_ctx_peer.telemetry_peer_ctx) ++ ath12k_telemetry_peer_ctx_free(peer->sawf_ctx_peer.telemetry_peer_ctx); ++#endif + kfree(peer); + wake_up(&ab->peer_mapping_wq); + +@@ -343,6 +347,10 @@ void ath12k_peer_cleanup(struct ath12k * + peer->addr, vdev_id); + ath12k_peer_rhash_delete(ab, peer); + list_del(&peer->list); ++#ifdef CPTCFG_ATH12K_SAWF ++ if (peer->sawf_ctx_peer.telemetry_peer_ctx) ++ ath12k_telemetry_peer_ctx_free(peer->sawf_ctx_peer.telemetry_peer_ctx); ++#endif + kfree(peer); + ar->num_peers--; + } +--- a/drivers/net/wireless/ath/ath12k/sawf.h ++++ b/drivers/net/wireless/ath/ath12k/sawf.h +@@ -217,10 +217,13 @@ struct ath12k_sawf_def_queue_report { + * The allocation is mapped with the service class ID. + * @msduq_table: map table of msduq and svc id per peer + * @def_q_map: default q map report ++ * @telemetry_peer_ctx: pointer to hold the structure reference ++ * maintained in telemetry agent module. + */ + struct ath12k_sawf_peer_ctx { + struct ath12k_msduq_map msduq_table[ATH12K_SAWF_MAX_TID_SUPPORT][MAX_Q_PER_TID]; + struct ath12k_sawf_def_queue_report def_q_map[ATH12K_SAWF_MAX_TID_SUPPORT]; ++ void *telemetry_peer_ctx; + }; + + /* MSG_TYPE => HTT_H2T_SAWF_DEF_QUEUES_MAP_REQ +@@ -850,6 +853,19 @@ int telemetry_extract_data(struct stats_ + struct telemetry_sawftx_stats *tx_stats, + struct telemetry_sawfdelay_stats *delay_stats, + struct ath12k_base *ab); ++int ath12k_telemetry_sla_reset_stats(u8 svc_id, u8 *peer_mac, u8 *mld_mac_addr, ++ u8 set_clear); ++int ath12k_telemetry_get_sawf_tx_stats_tput(void *ptr, void *stats, u64 *in_bytes, ++ u64 *in_cnt, u64 *tx_bytes, ++ u64 *tx_cnt, u8 tid_v, u8 msduq_id); ++int ath12k_telemetry_get_sawf_tx_stats_mpdu(void *ptr, void *stats, u64 *svc_int_pass, ++ u64 *svc_int_fail, u64 *burst_pass, ++ u64 *burst_fail, u8 tid_v, u8 msduq_id); ++int ath12k_telemetry_get_sawf_tx_stats_drop(void *ptr, void *stats, u64 *pass, ++ u64 *drop, u64 *drop_ttl, ++ u8 tid, u8 msduq_id); ++void ath12k_telemetry_notify_breach(u8 *mac_addr, u8 svc_id, u8 param, ++ bool set_clear, u8 tid); + #else /* CPTCFG_ATH12K_SAWF */ + + static inline void ath12k_sawf_init(struct ath12k_base *ab) { +--- a/drivers/net/wireless/ath/ath12k/telemetry.h ++++ b/drivers/net/wireless/ath/ath12k/telemetry.h +@@ -101,7 +101,8 @@ struct ath12k_telemetry_ctx *get_telemet + int ath12k_telemetry_sawf_sla_samples_config(struct ath12k_sla_samples_cfg param); + int ath12k_telemetry_sawf_sla_thershold_config(struct ath12k_sla_thershold_cfg param); + int ath12k_telemetry_sawf_sla_detection_config(struct ath12k_sla_detect_cfg param); +- ++bool ath12k_telemetry_get_sla_num_pkts(u32 *pkt_num); ++bool ath12k_telemetry_get_sla_mov_avg_num_pkt(u32 *mov_avg); + #else /* CPTCFG_ATH12K_SAWF */ + + static inline void ath12k_telemetry_init(struct ath12k_base *ab) { +--- a/drivers/net/wireless/ath/ath12k/vendor.c ++++ b/drivers/net/wireless/ath/ath12k/vendor.c +@@ -95,6 +95,18 @@ ath12k_telemetric_req_policy[QCA_WLAN_VE + [QCA_WLAN_VENDOR_ATTR_TELEMETRIC_SERVICEID] = {.type = NLA_U8}, + }; + ++static const struct nla_policy ++ath12k_telemetric_sla_policy[QCA_WLAN_VENDOR_ATTR_SLA_MAX + 1] = { ++ [QCA_WLAN_VENDOR_ATTR_SLA_PEER_MAC] = {.type = NLA_BINARY, ++ .len = ETH_ALEN}, ++ [QCA_WLAN_VENDOR_ATTR_SLA_SVC_ID] = {.type = NLA_U8}, ++ [QCA_WLAN_VENDOR_ATTR_SLA_PARAM] = {.type = NLA_U8}, ++ [QCA_WLAN_VENDOR_ATTR_SLA_SET_CLEAR] = {.type = NLA_U8}, ++ [QCA_WLAN_VENDOR_ATTR_SLA_PEER_MLD_MAC] = {.type = NLA_BINARY, ++ .len = ETH_ALEN}, ++ [QCA_WLAN_VENDOR_ATTR_SLA_AC] = {.type = NLA_U8}, ++}; ++ + static void ath12k_set_default_values(struct ath12k_sawf_svc_params *param) + { + param->min_throughput_rate = SAWF_SVC_PARAM_DEFAULT_MIN_THRUPUT; +@@ -892,6 +904,110 @@ end_stats: + return ret; + } + ++static int ath12k_vendor_telemetry_sla_reset_stats(struct wiphy *wihpy, ++ struct wireless_dev *wdev, ++ const void *data, ++ int data_len) ++{ ++ struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TELEMETRIC_MAX + 1]; ++ int ret = 0; ++ u8 svc_id, mac_addr[ETH_ALEN] = { 0 }, mld_mac_addr[ETH_ALEN] = { 0 }, set_clear; ++ ++ if (!ath12k_sawf_enable) ++ return -EOPNOTSUPP; ++ ++ ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SLA_MAX, data, data_len, ++ ath12k_telemetric_sla_policy, NULL); ++ ++ if (ret) { ++ ath12k_err(NULL, "Invalid attribute with telemetry sla reset stats command\n"); ++ return ret; ++ } ++ ++ if (tb[QCA_WLAN_VENDOR_ATTR_SLA_SVC_ID]) ++ svc_id = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SLA_SVC_ID]); ++ ++ if (tb[QCA_WLAN_VENDOR_ATTR_SLA_PEER_MAC] && ++ (nla_len(tb[QCA_WLAN_VENDOR_ATTR_SLA_PEER_MAC]) == ETH_ALEN)) ++ memcpy(mac_addr, nla_data(tb[QCA_WLAN_VENDOR_ATTR_SLA_PEER_MAC]), ++ ETH_ALEN); ++ ++ if (tb[QCA_WLAN_VENDOR_ATTR_SLA_PEER_MLD_MAC] && ++ (nla_len(tb[QCA_WLAN_VENDOR_ATTR_SLA_PEER_MLD_MAC]) == ETH_ALEN)) ++ memcpy(mld_mac_addr, nla_data(tb[QCA_WLAN_VENDOR_ATTR_SLA_PEER_MLD_MAC]), ++ ETH_ALEN); ++ ++ if (tb[QCA_WLAN_VENDOR_ATTR_SLA_SET_CLEAR]) ++ set_clear = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SLA_SET_CLEAR]); ++ ++ return ath12k_telemetry_sla_reset_stats(svc_id, mac_addr, mld_mac_addr, ++ set_clear); ++} ++ ++void ath12k_vendor_telemetry_notify_breach(struct ieee80211_vif *vif, u8 *mac_addr, ++ u8 svc_id, u8 param, bool set_clear, ++ u8 tid, u8 *mld_addr) ++{ ++ struct wireless_dev *wdev; ++ struct sk_buff *skb; ++ u8 access_category; ++ ++ wdev = ieee80211_vif_to_wdev(vif); ++ ++ if (!wdev) ++ return; ++ ++ if (!wdev->wiphy) ++ return; ++ ++ skb = cfg80211_vendor_event_alloc(wdev->wiphy, wdev, NLMSG_DEFAULT_SIZE, ++ QCA_NL80211_VENDOR_SUBCMD_SAWF_SLA_BREACH_INDEX, ++ GFP_KERNEL); ++ if (!skb) { ++ ath12k_err(NULL, "No memory available to send notify breach event\n"); ++ return; ++ } ++ ++ switch (tid) { ++ case 0: ++ case 3: ++ access_category = 0; //AC_BE ++ break; ++ case 1: ++ case 2: ++ access_category = 1; //AC_BK ++ break; ++ case 4: ++ case 5: ++ access_category = 2; //AC_VI ++ break; ++ case 6: ++ case 7: ++ access_category = 3; //AC_VO ++ break; ++ default: ++ ath12k_err(NULL, "Invalid TID = %u for notifying breach event\n", tid); ++ goto err; ++ } ++ ++ if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_SLA_PEER_MAC, ETH_ALEN, mac_addr) || ++ (mld_addr && nla_put(skb, QCA_WLAN_VENDOR_ATTR_SLA_PEER_MLD_MAC, ++ ETH_ALEN, mld_addr)) || ++ nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_SLA_SVC_ID, svc_id) || ++ nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_SLA_PARAM, param) || ++ nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_SLA_SET_CLEAR, set_clear) || ++ nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_SLA_AC, access_category)) { ++ ath12k_err(NULL, "No memory available at NL to send notify breach event\n"); ++ goto err; ++ } ++ ++ cfg80211_vendor_event(skb, GFP_KERNEL); ++ return; ++err: ++ kfree(skb); ++ return; ++} ++ + #endif /* CPTCFG_ATH12K_SAWF */ + static struct wiphy_vendor_command ath12k_vendor_commands[] = { + #ifdef CPTCFG_ATH12K_SAWF +@@ -977,12 +1093,31 @@ static struct wiphy_vendor_command ath12 + .maxattr = QCA_WLAN_VENDOR_ATTR_TELEMETRIC_MAX, + .flags = WIPHY_VENDOR_CMD_NEED_NETDEV, + }, ++ { ++ .info.vendor_id = QCA_NL80211_VENDOR_ID, ++ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SAWF_SLA_BREACH, ++ .doit = ath12k_vendor_telemetry_sla_reset_stats, ++ .policy = ath12k_telemetric_sla_policy, ++ .maxattr = QCA_WLAN_VENDOR_ATTR_SLA_MAX, ++ .flags = WIPHY_VENDOR_CMD_NEED_NETDEV, ++ }, + #endif /* CPTCFG_ATH12K_SAWF */ + }; + ++static const struct nl80211_vendor_cmd_info ath12k_vendor_events[] = { ++#ifdef CPTCFG_ATH12K_SAWF ++ [QCA_NL80211_VENDOR_SUBCMD_SAWF_SLA_BREACH_INDEX] = { ++ .vendor_id = QCA_NL80211_VENDOR_ID, ++ .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAWF_SLA_BREACH, ++ }, ++#endif ++}; ++ + int ath12k_vendor_register(struct ath12k_hw *ah) + { + ah->hw->wiphy->vendor_commands = ath12k_vendor_commands; + ah->hw->wiphy->n_vendor_commands = ARRAY_SIZE(ath12k_vendor_commands); ++ ah->hw->wiphy->vendor_events = ath12k_vendor_events; ++ ah->hw->wiphy->n_vendor_events = ARRAY_SIZE(ath12k_vendor_events); + return 0; + } +--- a/drivers/net/wireless/ath/ath12k/vendor.h ++++ b/drivers/net/wireless/ath/ath12k/vendor.h +@@ -21,6 +21,8 @@ enum qca_nl80211_vendor_subcmds { + QCA_NL80211_VENDOR_SUBCMD_TELEMETRY_SLA_SAMPLES_CFG = 211, + QCA_NL80211_VENDOR_SUBCMD_TELEMETRY_SLA_BREACH_DETECTION_CFG = 212, + QCA_NL80211_VENDOR_SUBCMD_SAWF_STREAMING_STATS = 213, ++ QCA_NL80211_VENDOR_SUBCMD_SAWF_SLA_BREACH = 214, ++ QCA_NL80211_VENDOR_SUBCMD_SAWF_SLA_BREACH_INDEX = 215, + QCA_NL80211_VENDOR_SUBCMD_TELEMETRIC_DATA = 334, + #endif /* CPTCFG_ATH12K_SAWF */ + }; +@@ -451,6 +453,42 @@ struct unified_stats { + void *feat[STATS_FEAT_MAX]; + u_int32_t size[STATS_FEAT_MAX]; + }; ++ ++/** ++ * enum qca_wlan_vendor_attr_sawf_sla_params - This enum defines ++ * attributes required for QCA_NL80211_VENDOR_SUBCMD_SAWF_SLA_BREACH ++ * Attributes are required to notify SLA breaches from driver to ++ * user application. ++ * ++ * @QCA_WLAN_VENDOR_ATTR_SLA_PEER_MAC: Unsigned 8-bit array ++ * of size 6, representing peer mac address. ++ * @QCA_WLAN_VENDOR_ATTR_SLA_SVC_ID: Unsigned 8-bit representing service ID ++ * @QCA_WLAN_VENDOR_ATTR_SLA_PARAM: Unsigned 8-bit indicaing service class ++ * from qca_vendor_attr_sla_param_type ++ * @QCA_WLAN_VENDOR_ATTR_SLA_PEER_MLD_MAC: Unsigned 8-bit array ++ * of size 6, representing peer mld mac address. Filled only for ML capable ++ * peers ++ * @QCA_WLAN_VENDOR_ATTR_SLA_AC: Unsigned 8-bit representing AC for breach ++ * ++ */ ++enum qca_wlan_vendor_attr_sawf_sla_params { ++ QCA_WLAN_VENDOR_ATTR_SLA_INVALID = 0, ++ QCA_WLAN_VENDOR_ATTR_SLA_PEER_MAC = 1, ++ QCA_WLAN_VENDOR_ATTR_SLA_SVC_ID = 2, ++ QCA_WLAN_VENDOR_ATTR_SLA_PARAM = 3, ++ QCA_WLAN_VENDOR_ATTR_SLA_SET_CLEAR = 4, ++ QCA_WLAN_VENDOR_ATTR_SLA_PEER_MLD_MAC = 5, ++ QCA_WLAN_VENDOR_ATTR_SLA_AC = 6, ++ ++ /* Keep last */ ++ QCA_WLAN_VENDOR_ATTR_SLA_AFTER_LAST, ++ QCA_WLAN_VENDOR_ATTR_SLA_MAX = ++ QCA_WLAN_VENDOR_ATTR_SLA_AFTER_LAST - 1 ++}; ++ ++void ath12k_vendor_telemetry_notify_breach(struct ieee80211_vif *vif, u8 *mac_addr, ++ u8 svc_id, u8 param, bool set_clear, ++ u8 tid, u8 *mld_addr); + #endif /* CPTCFG_ATH12K_SAWF */ + + int ath12k_vendor_register(struct ath12k_hw *ah); diff --git a/feeds/ipq95xx/mac80211/patches/qca/784-ath12k-restrict-user-country-setting-during-active-v.patch b/feeds/ipq95xx/mac80211/patches/qca/784-ath12k-restrict-user-country-setting-during-active-v.patch new file mode 100644 index 000000000..d6670ca69 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/784-ath12k-restrict-user-country-setting-during-active-v.patch @@ -0,0 +1,97 @@ +From a2c9b5f9aa65a7a6cb1016c5c644f57c8394b836 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Fri, 23 Jun 2023 12:13:08 +0530 +Subject: [PATCH] ath12k: restrict user country setting during active vdev + +Currently, if user wants, country setting can be changed on the fly after +the interface(s) have started beaconing. However, hostapd ignores this regulatory +change event since according to its state, it did not ask for it. This leads +to interfaces which were already active continue beaconing with same old data +which is wrong. + +Since there is no potential usecase of changing regulatory on the fly, hence +add change to restrict changing country setting if any of the vdev in it is +active. + +Also since regulatory applies to whole SOC, restrict this further to not allow +if any of pdev on a SOC is having an active vdev. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath12k/reg.c | 53 +++++++++++++++++++++++++++ + 1 file changed, 53 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/reg.c b/drivers/net/wireless/ath/ath12k/reg.c +index 07b46c06fc86..720bcdb436fc 100644 +--- a/drivers/net/wireless/ath/ath12k/reg.c ++++ b/drivers/net/wireless/ath/ath12k/reg.c +@@ -126,6 +126,56 @@ ath12k_reg_send_request(struct ath12k *ar, struct regulatory_request *request) + "INIT Country code set to fw failed : %d\n", ret); + } + ++static bool ath12k_reg_validate_pdev_state(struct ath12k *ar) ++{ ++ struct ath12k_base *ab = ar->ab; ++ struct ath12k_pdev *pdev; ++ struct ath12k *tmp_ar; ++ int i; ++ ++ rcu_read_lock(); ++ for (i = 0; i < ab->num_radios; i++) { ++ pdev = rcu_dereference(ab->pdevs_active[i]); ++ if (!pdev) ++ continue; ++ ++ tmp_ar = pdev->ar; ++ if (tmp_ar) { ++ mutex_lock(&tmp_ar->conf_mutex); ++ if (tmp_ar->num_started_vdevs) { ++ if (tmp_ar == ar) ++ ath12k_warn(ab, "%s has active interface, please bring down to set country code", ++ wiphy_name(ar->ah->hw->wiphy)); ++ mutex_unlock(&tmp_ar->conf_mutex); ++ rcu_read_unlock(); ++ return false; ++ } ++ mutex_unlock(&tmp_ar->conf_mutex); ++ } ++ } ++ rcu_read_unlock(); ++ return true; ++} ++ ++static bool ath12k_reg_validate_ah_state(struct ath12k_hw *ah) ++{ ++ struct ath12k *ar = ah->radio; ++ int i; ++ ++ lockdep_assert_held(&ah->conf_mutex); ++ ++ for (i = 0; i < ah->num_radio; i++, ar++) { ++ /* The SET_INIT_COUNTRY command should not be sent to firmware while any vdev is active ++ * Also it does not make sense to give the command for certain pdev's alone. ++ * Hence check all the pdev's if any have an active vdev before sending the command. ++ */ ++ if (!ath12k_reg_validate_pdev_state(ar)) ++ return false; ++ } ++ ++ return true; ++} ++ + void ath12k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) + { + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); +@@ -149,6 +199,9 @@ void ath12k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request + if (!ath12k_regdom_changes(ah, request->alpha2)) + goto exit; + ++ if (!ath12k_reg_validate_ah_state(ah)) ++ goto exit; ++ + ah->regd_updated = false; + ar = ah->radio; + +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/784-mac80211-fix-skb-and-sdata-mismatch.patch b/feeds/ipq95xx/mac80211/patches/qca/784-mac80211-fix-skb-and-sdata-mismatch.patch new file mode 100644 index 000000000..0c8436002 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/784-mac80211-fix-skb-and-sdata-mismatch.patch @@ -0,0 +1,183 @@ +From a5fe53bfa03ffb18098bd7a1617b938b40edaecd Mon Sep 17 00:00:00 2001 +From: Rahul Bhattacharjee +Date: Wed, 21 Jun 2023 22:40:02 +0530 +Subject: [PATCH] mac80211: fix skb and sdata mismatch + +Currently, skbs are getting tagged with wrong sdata, i.e even if the +sdata does not support a skb specific band, we are tagging the sdata +along with that. + +In issue scenerio, 1 DUT was having 6G Mesh(root) + 2G AP and the other DUT +was having 2G Mesh(child) , and the packets from 2G Mesh were seeing in +6G Mesh, interface. + +In this fix, we tag the sdata is the respective skb's band support is +present. + +Signed-off-by: Rahul Bhattacharjee +--- + net/mac80211/rx.c | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -4327,9 +4327,12 @@ static bool ieee80211_rx_data_set_sta(st + rx->link_sta = &sta->deflink; + } + +- if (link_id < 0) ++ if (link_id < 0) { ++ pr_err("link id %d sta addr : %pM", link_id, sta ? sta->addr : NULL); ++ print_hex_dump(KERN_ERR, "skb_data : ", DUMP_PREFIX_ADDRESS, 16, 1, rx->skb->data, rx->skb->len, true); ++ BUG_ON(1); + rx->link = &rx->sdata->deflink; +- else if (!ieee80211_rx_data_set_link(rx, link_id)) ++ } else if (!ieee80211_rx_data_set_link(rx, link_id)) + return false; + + return true; +@@ -5344,11 +5347,13 @@ static void __ieee80211_rx_handle_packet + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); + struct ieee80211_sub_if_data *sdata; + struct ieee80211_hdr *hdr; ++ struct wiphy *wiphy = hw->wiphy; + __le16 fc; + struct ieee80211_rx_data rx; + struct ieee80211_sub_if_data *prev; + struct rhlist_head *tmp; +- int err = 0; ++ int err = 0, prev_linkid; ++ bool prev_flag; + + fc = ((struct ieee80211_hdr *)skb->data)->frame_control; + memset(&rx, 0, sizeof(rx)); +@@ -5457,8 +5462,15 @@ static void __ieee80211_rx_handle_packet + } + + prev = NULL; ++ prev_linkid = -1; ++ prev_flag = false; + + list_for_each_entry_rcu(sdata, &local->interfaces, list) { ++ unsigned int link_id; ++ struct ieee80211_bss_conf *conf; ++ u16 valid_links = sdata->vif.valid_links; ++ bool flag = false; ++ + if (!ieee80211_sdata_running(sdata)) + continue; + +@@ -5466,28 +5478,103 @@ static void __ieee80211_rx_handle_packet + sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + continue; + ++ if (wiphy->num_hw) { ++ if (valid_links) { ++ for_each_set_bit(link_id, &valid_links, ++ IEEE80211_MLD_MAX_NUM_LINKS) { ++ conf = rcu_dereference(sdata->vif.link_conf[link_id]); ++ ++ if (conf && conf->chandef.chan) ++ if (cfg80211_get_hw_idx_by_freq(hw->wiphy, conf->chandef.chan->center_freq) == ++ cfg80211_get_hw_idx_by_freq(hw->wiphy, status->freq)) { ++ flag = true; ++ break; ++ } ++ } ++ } else { ++ conf = &sdata->vif.bss_conf; ++ ++ if (conf && conf->chandef.chan) ++ if (cfg80211_get_hw_idx_by_freq(hw->wiphy, conf->chandef.chan->center_freq) == ++ cfg80211_get_hw_idx_by_freq(hw->wiphy, status->freq)) ++ flag = true; ++ } ++ } ++ + /* + * frame is destined for this interface, but if it's + * not also for the previous one we handle that after + * the loop to avoid copying the SKB once too much + */ + +- if (!prev) { ++ if (!wiphy->num_hw || flag) { ++ if (!prev) { ++ prev_linkid = valid_links ? link_id : -1; ++ prev = sdata; ++ prev_flag = flag; ++ continue; ++ } ++ ++ rx.sdata = prev; ++ if (prev_flag) { ++ status->link_valid = (prev_linkid >= 0); ++ if (status->link_valid) ++ status->link_id = prev_linkid; ++ } ++ ieee80211_rx_for_interface(&rx, skb, false); ++ ++ prev_linkid = valid_links ? link_id : -1; + prev = sdata; +- continue; ++ prev_flag = flag; + } ++ } + +- rx.sdata = prev; +- ieee80211_rx_for_interface(&rx, skb, false); ++ if (wiphy->num_hw) { ++ if (prev) { ++ unsigned int link_id; ++ struct ieee80211_bss_conf *conf; ++ u16 valid_links = prev->vif.valid_links; ++ bool flag = false; ++ ++ if (valid_links) { ++ for_each_set_bit(link_id, &valid_links, ++ IEEE80211_MLD_MAX_NUM_LINKS) { ++ conf = rcu_dereference(prev->vif.link_conf[link_id]); ++ ++ if (conf && conf->chandef.chan) { ++ if (cfg80211_get_hw_idx_by_freq(hw->wiphy, conf->chandef.chan->center_freq) == ++ cfg80211_get_hw_idx_by_freq(hw->wiphy, status->freq)) { ++ flag = true; ++ break; ++ } ++ } ++ } ++ } else { ++ conf = &prev->vif.bss_conf; ++ ++ if (conf && conf->chandef.chan) ++ if (cfg80211_get_hw_idx_by_freq(hw->wiphy, conf->chandef.chan->center_freq) == ++ cfg80211_get_hw_idx_by_freq(hw->wiphy, status->freq)) ++ flag = true; ++ } + +- prev = sdata; +- } ++ if (flag) { ++ rx.sdata = prev; ++ status->link_valid = !!valid_links; ++ if (status->link_valid) ++ status->link_id = link_id; + +- if (prev) { +- rx.sdata = prev; ++ if (ieee80211_rx_for_interface(&rx, skb, true)) ++ return; ++ } ++ } ++ } else { ++ if (prev) { ++ rx.sdata = prev; + +- if (ieee80211_rx_for_interface(&rx, skb, true)) +- return; ++ if (ieee80211_rx_for_interface(&rx, skb, true)) ++ return; ++ } + } + + out: diff --git a/feeds/ipq95xx/mac80211/patches/qca/785-wifi-ath12k-Fix-deadlock-b-w-drain-tx-and-mgmt-tx-wo.patch b/feeds/ipq95xx/mac80211/patches/qca/785-wifi-ath12k-Fix-deadlock-b-w-drain-tx-and-mgmt-tx-wo.patch new file mode 100644 index 000000000..dbc807cdd --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/785-wifi-ath12k-Fix-deadlock-b-w-drain-tx-and-mgmt-tx-wo.patch @@ -0,0 +1,116 @@ +From 12445dad4747014edf3fb781167c3b1d9c8d676f Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Tue, 27 Jun 2023 16:13:32 +0530 +Subject: [PATCH] wifi: ath12k: Fix deadlock b/w drain tx and mgmt tx + worker procedure + +Rename the ath12k_mac_drain_tx() into ath12k_mac_radio_drain_tx(). + +Move the ath12k_mac_radio_drain_tx() out of ath12k_mac_radio_stop() +to run the drain tx without ath12k hw (ah) mutex lock/un. Since +it undergoes the mgmt tx pending drain procedure and the mgmt tx worker +run under the ah mutex lock/un, so drain tx should happen out of ah +mutex lock/un. Introduce the drain tx on multiple hw level under ah, +this get called out of the ath12k hw lock/un, since ah is the private +data structure of hw. + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/core.c | 2 +- + drivers/net/wireless/ath/ath12k/mac.c | 23 ++++++++++++++++++----- + drivers/net/wireless/ath/ath12k/mac.h | 2 +- + 3 files changed, 20 insertions(+), 7 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -1822,7 +1822,7 @@ static void ath12k_core_pre_reconfigure_ + if (arvif->is_started) + ath12k_debugfs_remove_interface(arvif); + +- ath12k_mac_drain_tx(ar); ++ ath12k_mac_radio_drain_tx(ar); + complete(&ar->scan.started); + complete(&ar->scan.completed); + complete(&ar->peer_assoc_done); +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -9239,7 +9239,7 @@ skip_peer_find: + + } + +-void ath12k_mac_drain_tx(struct ath12k *ar) ++void ath12k_mac_radio_drain_tx(struct ath12k *ar) + { + /* make sure rcu-protected mac80211 tx path itself is drained */ + synchronize_net(); +@@ -9424,7 +9424,6 @@ static int ath12k_mac_radio_start(struct + struct ath12k_pdev *pdev = ar->pdev; + int ret; + +- ath12k_mac_drain_tx(ar); + mutex_lock(&ar->conf_mutex); + + switch (ar->state) { +@@ -9605,8 +9604,6 @@ static void ath12k_mac_radio_stop(struct + struct htt_ppdu_stats_info *ppdu_stats, *tmp; + int ret; + +- ath12k_mac_drain_tx(ar); +- + mutex_lock(&ar->conf_mutex); + ret = ath12k_mac_config_mon_status_default(ar, false); + if (ret && (ret != -ENOTSUPP)) +@@ -9678,6 +9675,19 @@ static void ath12k_mgmt_rx_reo_deinit_ti + reo_context->timer_init_done = false; + } + ++static void ath12k_mac_drain_tx(struct ath12k_hw *ah) ++{ ++ struct ath12k *ar; ++ int i; ++ ++ ar = ah->radio; ++ ++ for (i = 0; i < ah->num_radio; i++) { ++ ath12k_mac_radio_drain_tx(ar); ++ ar++; ++ } ++} ++ + static int ath12k_mac_op_start(struct ieee80211_hw *hw) + { + struct ath12k_hw *ah = hw->priv; +@@ -9689,6 +9699,8 @@ static int ath12k_mac_op_start(struct ie + + ath12k_mgmt_rx_reo_init_timer(ag); + ++ ath12k_mac_drain_tx(ah); ++ + mutex_lock(&ah->conf_mutex); + ar = ah->radio; + ab = ar->ab; +@@ -9734,11 +9746,12 @@ static void ath12k_mac_op_stop(struct ie + + ath12k_mgmt_rx_reo_deinit_timer(ag); + ++ ath12k_mac_drain_tx(ah); ++ + mutex_lock(&ah->conf_mutex); + ar = ah->radio; + + /* TODO Maintain state for ah? */ +- + for (i = ah->num_radio - 1, ar = ar + (ah->num_radio - 1); i >= 0; i--) { + ath12k_mac_radio_stop(ar); + ar--; +--- a/drivers/net/wireless/ath/ath12k/mac.h ++++ b/drivers/net/wireless/ath/ath12k/mac.h +@@ -215,7 +215,7 @@ struct ath12k *ath12k_mac_get_ar_by_pdev + void ath12k_mac_fill_reg_tpc_info(struct ath12k *ar, + struct ath12k_link_vif *arvif, + struct ieee80211_chanctx_conf *ctx); +-void ath12k_mac_drain_tx(struct ath12k *ar); ++void ath12k_mac_radio_drain_tx(struct ath12k *ar); + void ath12k_mac_peer_cleanup_all(struct ath12k *ar); + int ath12k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx); + u8 ath12k_mac_bw_to_mac80211_bw(u8 bw); diff --git a/feeds/ipq95xx/mac80211/patches/qca/786-01-ath12k_compilation_fixes.patch b/feeds/ipq95xx/mac80211/patches/qca/786-01-ath12k_compilation_fixes.patch new file mode 100644 index 000000000..d1fbd1d13 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/786-01-ath12k_compilation_fixes.patch @@ -0,0 +1,529 @@ +From dc3d0124fe7bea10eb39318d5bcd1bd10e9c9fff Mon Sep 17 00:00:00 2001 +From: Arulanbu Balusamy +Date: Thu, 8 Jun 2023 23:36:57 +0530 +Subject: [PATCH] Overflow header changes + + +This changes has ath12k integration with OpenWRT-ginger branch, Also +fixed the various compilation issues due to kernel upgradation from 5.x to 6.x, +some API names are changed and some unsupported API are disable in the kernel 6.x +this patch support for both the kernel versions + +Signed-off-by: Arulanbu Balusamy +--- + include/linux/overflow.h | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/include/linux/overflow.h ++++ b/include/linux/overflow.h +@@ -30,7 +30,9 @@ + * https://mail-index.netbsd.org/tech-misc/2007/02/05/0000.html - + * credit to Christian Biere. + */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + #define is_signed_type(type) (((type)(-1)) < (type)1) ++#endif + #define __type_half_max(type) ((type)1 << (8*sizeof(type) - 1 - is_signed_type(type))) + #define type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T))) + #define type_min(T) ((T)((T)-type_max(T)-(T)1)) +--- a/backport-include/linux/slab.h ++++ b/backport-include/linux/slab.h +@@ -4,9 +4,8 @@ + #include + + #if LINUX_VERSION_IS_LESS(5,9,0) +-#define kfree_sensitive(x) kzfree(x) ++#define kfree_sensitive(x) kzfree(x) /* For backward compatibility */ + #endif + +-#define kfree_sensitive(x) kzfree(x) /* For backward compatibility */ + + #endif /* __BACKPORT_SLAB_H */ +--- a/drivers/net/wireless/ath/ath12k/ahb.h ++++ b/drivers/net/wireless/ath/ath12k/ahb.h +@@ -7,7 +7,7 @@ + #define ATH12K_AHB_H + + #include +- ++#include + #include "core.h" + + #define ATH12K_AHB_RECOVERY_TIMEOUT (3 * HZ) +@@ -47,24 +47,33 @@ static inline struct ath12k_ahb *ath12k_ + { + return (struct ath12k_ahb *)ab->drv_priv; + } +- +-static inline int ath12k_rproc_register_subsys_notifier(const char *name, +- struct notifier_block *nb, +- struct notifier_block *atomic_nb) ++static inline int ath12k_rproc_register_subsys_notifier(struct ath12k_base *ab) + { ++ struct ath12k_ahb *ab_ahb = ath12k_ahb_priv(ab); + #ifdef CONFIG_REMOTEPROC +- return rproc_register_subsys_notifier(name, nb, atomic_nb); ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) ++ return rproc_register_subsys_notifier(ab_ahb->tgt_rrproc->name, &ab->ssr_nb, &ab->atomic_ssr_nb); ++#else ++ ab->ssr_handle = qcom_register_ssr_notifier(ab_ahb->tgt_rrproc->name, &ab->atomic_ssr_nb); ++ if (!ab->ssr_handle) ++ return -EINVAL; ++ return 0; ++#endif + #else + return -ENODEV; + #endif + } +- +-static inline int ath12k_rproc_unregister_subsys_notifier(const char *name, +- struct notifier_block *nb, +- struct notifier_block *atomic_nb) ++static inline int ath12k_rproc_unregister_subsys_notifier(struct ath12k_base *ab) + { + #ifdef CONFIG_REMOTEPROC +- return rproc_unregister_subsys_notifier(name, nb, atomic_nb); ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) ++ struct ath12k_ahb *ab_ahb = ath12k_ahb_priv(ab); ++ return rproc_unregister_subsys_notifier(ab_ahb->tgt_rrproc->name, &ab->ssr_nb, &ab->atomic_ssr_nb); ++#else ++ if (ab->ssr_handle) ++ qcom_unregister_ssr_notifier(ab->ssr_handle, &ab->atomic_ssr_nb); ++ return 0; ++#endif + #else + return -ENODEV; + #endif +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -1671,8 +1671,7 @@ static int ath12k_core_ssr_notifier_cb(s + void *data) + { + struct ath12k_base *ab = container_of(nb, struct ath12k_base, ssr_nb); +- +- if (ab->collect_dump && (event == SUBSYS_AFTER_POWERUP)) { ++ if (ab->collect_dump && (event == ATH12K_SSR_POWERUP)) { + ab->collect_dump = false; + wake_up(&ab->ssr_dump_wq); + return NOTIFY_OK; +@@ -1693,9 +1692,7 @@ static int ath12k_core_atomic_ssr_notifi + struct device_node *rrproc_node = NULL; + struct platform_device *ssr_pdev = (struct platform_device *)data; + struct ath12k_ahb *ab_ahb = ath12k_ahb_priv(ab); +- +- +- if (event != SUBSYS_PREPARE_FOR_FATAL_SHUTDOWN) ++ if (event != ATH12K_SSR_PREPARE_SHUTDOWN) + return NOTIFY_DONE; + + ab->collect_dump = true; +@@ -1975,7 +1972,6 @@ static void ath12k_rproc_recovery_do_cor + rproc->ops->coredump(rproc); + } + } +- + static int ath12k_rproc_recovery_stop_coredump(struct ath12k_base *ab) + { + int ret; +@@ -1983,7 +1979,11 @@ static int ath12k_rproc_recovery_stop_co + + if (ab_ahb->tgt_rproc) { + ab_ahb->tgt_rproc->state = RPROC_CRASHED; ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + ret = rproc_stop(ab_ahb->tgt_rproc, true); ++#else ++ ret = rproc_shutdown(ab_ahb->tgt_rproc); ++#endif + if (ret < 0) { + ath12k_err(ab, "userpd rproc stop failed\n"); + return ret; +@@ -1992,7 +1992,11 @@ static int ath12k_rproc_recovery_stop_co + } + if (ab_ahb->tgt_rrproc) { + ab_ahb->tgt_rrproc->state = RPROC_RUNNING; ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + ret = rproc_stop(ab_ahb->tgt_rrproc, true); ++#else ++ ret = rproc_shutdown(ab_ahb->tgt_rrproc); ++#endif + if (ret < 0) { + ath12k_err(ab, "rootpd rproc stop failed\n"); + return ret; +@@ -2022,7 +2026,11 @@ static int ath12k_rproc_recovery_power_u + ath12k_err(ab, "request_firmware failed: %d\n", ret); + return ret; + } ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + ret = rproc_start(rproc_rpd, firmware_p); ++#else ++ ret = rproc_boot(rproc_rpd); ++#endif + if (ret < 0) { + ath12k_err(ab, "Root pd rproc_start failed: %d\n", ret); + return ret; +@@ -2037,7 +2045,11 @@ static int ath12k_rproc_recovery_power_u + ret); + return ret; + } ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + ret = rproc_start(rproc, firmware_p); ++#else ++ ret = rproc_boot(rproc); ++#endif + if (ret < 0) { + ath12k_err(ab, "User pd rproc_start failed: %d\n", ret); + return ret; +@@ -2088,6 +2100,7 @@ static void ath12k_core_disable_ds_rtnl_ + } + #endif + ++ + static void ath12k_core_reset(struct work_struct *work) + { + struct ath12k_base *ab = container_of(work, struct ath12k_base, reset_work); +--- a/drivers/net/wireless/ath/ath12k/dp_rx.h ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.h +@@ -9,6 +9,9 @@ + #include "core.h" + #include "rx_desc.h" + #include "debug.h" ++#if LINUX_VERSION_IS_GEQ(5,10,0) ++#include "crypto/hash.h" ++#endif + + /* different supported pkt types for routing */ + enum ath12k_routing_pkt_type { +--- a/drivers/net/wireless/ath/ath12k/hal_rx.c ++++ b/drivers/net/wireless/ath/ath12k/hal_rx.c +@@ -30,8 +30,12 @@ static int ath12k_hal_reo_cmd_queue_stat + u32_encode_bits(sizeof(*desc), HAL_TLV_HDR_LEN); + + desc = (struct hal_reo_get_queue_stats *)tlv->value; ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + memset(&desc->queue_addr_lo, 0, + (sizeof(*desc) - sizeof(struct hal_reo_cmd_hdr))); ++#else ++ memset_startat(desc, 0, queue_addr_lo); ++#endif + + desc->cmd.info0 &= ~HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED; + if (cmd->flag & HAL_REO_CMD_FLG_NEED_STATUS) +@@ -64,8 +68,12 @@ static int ath12k_hal_reo_cmd_flush_cach + u32_encode_bits(sizeof(*desc), HAL_TLV_HDR_LEN); + + desc = (struct hal_reo_flush_cache *)tlv->value; ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + memset(&desc->cache_addr_lo, 0, + (sizeof(*desc) - sizeof(struct hal_reo_cmd_hdr))); ++#else ++ memset_startat(desc, 0, cache_addr_lo); ++#endif + + desc->cmd.info0 &= ~HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED; + if (cmd->flag & HAL_REO_CMD_FLG_NEED_STATUS) +@@ -106,8 +114,12 @@ static int ath12k_hal_reo_cmd_update_rx_ + u32_encode_bits(sizeof(*desc), HAL_TLV_HDR_LEN); + + desc = (struct hal_reo_update_rx_queue *)tlv->value; ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + memset(&desc->queue_addr_lo, 0, + (sizeof(*desc) - sizeof(struct hal_reo_cmd_hdr))); ++#else ++ memset_startat(desc, 0, queue_addr_lo); ++#endif + + desc->cmd.info0 &= ~HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED; + if (cmd->flag & HAL_REO_CMD_FLG_NEED_STATUS) +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -308,12 +308,12 @@ int ath12k_dp_tx_direct(struct ath12k_li + tx_desc->mac_id = arvif->pdev_idx; + tx_desc->recycler_fast_xmit = 0; + tx_desc->timestamp = ktime_get_real(); +- ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + /* the edma driver uses this flags to optimize the cache invalidation */ + skb->fast_recycled = 1; + if (skb->is_from_recycler) + tx_desc->recycler_fast_xmit = 1; +- ++#endif + skb_cb->vif = arvif->ahvif->vif; + skb_cb->paddr = paddr; + +@@ -1638,8 +1638,9 @@ int ath12k_dp_tx_completion_handler(stru + } + } + ath12k_hal_srng_access_dst_ring_end_nolock(status_ring); ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + dev_kfree_skb_list_fast(&free_list_head); +- ++#endif + return (orig_budget - budget); + } + +--- a/drivers/net/wireless/ath/ath12k/mhi.c ++++ b/drivers/net/wireless/ath/ath12k/mhi.c +@@ -61,7 +61,9 @@ static struct mhi_channel_config ath12k_ + .offload_channel = false, + .doorbell_mode_switch = false, + .auto_queue = false, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + .auto_start = true, ++#endif + }, + { + .num = 21, +@@ -76,7 +78,9 @@ static struct mhi_channel_config ath12k_ + .offload_channel = false, + .doorbell_mode_switch = false, + .auto_queue = true, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + .auto_start = true, ++#endif + }, + }; + +@@ -447,7 +451,9 @@ int ath12k_mhi_register(struct ath12k_pc + mhi_ctrl->status_cb = ath12k_mhi_op_status_cb; + mhi_ctrl->read_reg = ath12k_mhi_op_read_reg; + mhi_ctrl->write_reg = ath12k_mhi_op_write_reg; ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + mhi_ctrl->dev_id = ab_pci->dev_id; ++#endif + + ret = mhi_register_controller(mhi_ctrl, ab->hw_params->mhi_config); + if (ret) { +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -545,9 +545,13 @@ static int ath12k_pci_ext_irq_config(str + * enqueue operation */ + if (ab->hw_params->ring_mask->tx[i]) + budget = tx_comp_budget; +- ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi, + ath12k_pci_ext_grp_napi_poll, budget); ++#else ++ netif_napi_add_weight(&irq_grp->napi_ndev, &irq_grp->napi, ++ ath12k_pci_ext_grp_napi_poll,budget); ++#endif + + if (ab->hw_params->ring_mask->tx[i] || + ab->hw_params->ring_mask->rx[i] || +--- a/drivers/net/wireless/ath/ath12k/dp_mon.c ++++ b/drivers/net/wireless/ath/ath12k/dp_mon.c +@@ -929,6 +929,8 @@ ath12k_dp_mon_hal_rx_parse_ru_allocation + HAL_RX_EHT_SIG_OFDMA_EB2_RU_ALLOC_2_3); + ppdu_info->eht_data[2] |= (ru_allocation2_3 << EHT_RU_ALLOCATION2_3_SHIFT); + /* fallthrough */ ++ fallthrough; ++ + case HAL_EHT_BW_160: + num_ru_allocation_known += 2; + ru_allocation2_2 = u64_get_bits(__le64_to_cpu(ofdma_cmn_eb2->info0), +@@ -940,6 +942,8 @@ ath12k_dp_mon_hal_rx_parse_ru_allocation + ppdu_info->eht_data[2] |= + (ru_allocation2_1 << EHT_RU_ALLOCATION2_1_SHIFT); + /* fallthrough */ ++ fallthrough; ++ + case HAL_EHT_BW_80: + num_ru_allocation_known += 1; + ru_allocation1_2 = u64_get_bits(__le64_to_cpu(ofdma_cmn_eb1->info0), +@@ -947,6 +951,8 @@ ath12k_dp_mon_hal_rx_parse_ru_allocation + ppdu_info->eht_data[1] |= + (ru_allocation1_2 << EHT_RU_ALLOCATION1_2_SHIFT); + /* fallthrough */ ++ fallthrough; ++ + case HAL_EHT_BW_40: + case HAL_EHT_BW_20: + num_ru_allocation_known += 1; +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -396,10 +396,15 @@ static const struct nla_policy nl80211_t + [NL80211_TXRATE_HE_LTF] = NLA_POLICY_RANGE(NLA_U8, + NL80211_RATE_INFO_HE_1XLTF, + NL80211_RATE_INFO_HE_4XLTF), ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) ++ + [NL80211_TXRATE_HE_UL] = { + .type = NLA_EXACT_LEN_WARN, + .len = sizeof(struct nl80211_txrate_he), + }, ++#else ++ [NL80211_TXRATE_HE_UL] = NLA_POLICY_EXACT_LEN(sizeof(struct nl80211_txrate_he)), ++#endif + [NL80211_TXRATE_EHT] = + NLA_POLICY_EXACT_LEN(sizeof(struct nl80211_txrate_eht)), + [NL80211_TXRATE_EHT_GI] = NLA_POLICY_RANGE(NLA_U8, +@@ -18180,6 +18185,7 @@ static struct genl_family nl80211_fam __ + #if LINUX_VERSION_IS_GEQ(5,10,0) + .small_ops = nl80211_small_ops, + .n_small_ops = ARRAY_SIZE(nl80211_small_ops), ++ .resv_start_op = NL80211_CMD_REMOVE_LINK_STA + 5, + #endif + .mcgrps = nl80211_mcgrps, + .n_mcgrps = ARRAY_SIZE(nl80211_mcgrps), +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -38,8 +38,10 @@ static inline void ieee80211_rx_stats(st + struct pcpu_sw_netstats *tstats = this_cpu_ptr(netdev_tstats(dev)); + + u64_stats_update_begin(&tstats->syncp); ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + tstats->rx_packets++; + tstats->rx_bytes += len; ++#endif + u64_stats_update_end(&tstats->syncp); + } + +@@ -59,7 +61,11 @@ static struct sk_buff *ieee80211_clean_s + + if (present_fcs_len) + __pskb_trim(skb, skb->len - present_fcs_len); ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + __pskb_pull(skb, rtap_space); ++#else ++ pskb_pull(skb, rtap_space); ++#endif + + hdr = (void *)skb->data; + fc = hdr->frame_control; +@@ -84,7 +90,11 @@ static struct sk_buff *ieee80211_clean_s + + memmove(skb->data + IEEE80211_HT_CTL_LEN, skb->data, + hdrlen - IEEE80211_HT_CTL_LEN); ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + __pskb_pull(skb, IEEE80211_HT_CTL_LEN); ++#else ++ pskb_pull(skb, IEEE80211_HT_CTL_LEN); ++#endif + + return skb; + } +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -48,8 +48,10 @@ static inline void ieee80211_tx_stats(st + struct pcpu_sw_netstats *tstats = this_cpu_ptr(netdev_tstats(dev)); + + u64_stats_update_begin(&tstats->syncp); ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + tstats->tx_packets++; + tstats->tx_bytes += len; ++#endif + u64_stats_update_end(&tstats->syncp); + } + /* misc utils */ +@@ -4636,7 +4638,9 @@ netdev_tx_t ieee80211_subif_start_xmit(s + #ifdef CPTCFG_MAC80211_NSS_SUPPORT + ieee80211_xmit_nss_fixup(skb, dev); + #endif ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + skb->fast_xmit = 0; ++#endif + + if (likely(!is_multicast_ether_addr(eth->h_dest))) + goto normal; +--- a/net/mac80211/rc80211_minstrel_ht.c ++++ b/net/mac80211/rc80211_minstrel_ht.c +@@ -2033,7 +2033,11 @@ static void __init init_sample_table(voi + + memset(sample_table, 0xff, sizeof(sample_table)); + for (col = 0; col < SAMPLE_COLUMNS; col++) { ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + prandom_bytes(rnd, sizeof(rnd)); ++#else ++ get_random_bytes(rnd, sizeof(rnd)); ++#endif + for (i = 0; i < MCS_GROUP_RATES; i++) { + new_idx = (i + rnd[i]) % MCS_GROUP_RATES; + while (sample_table[col][new_idx] != 0xff) +--- a/drivers/net/wireless/ath/ath12k/hal_rx.h ++++ b/drivers/net/wireless/ath/ath12k/hal_rx.h +@@ -672,7 +672,7 @@ struct hal_eht_sig_ofdma_cmn_eb1 { + __le64 info0; + } __packed; + +-#define HAL_RX_EHT_SIG_OFDMA_EB2_RU_ALLOC_2_1 GENMASK_ULL(0, 8) ++#define HAL_RX_EHT_SIG_OFDMA_EB2_RU_ALLOC_2_1 GENMASK_ULL(8, 0) + #define HAL_RX_EHT_SIG_OFDMA_EB2_RU_ALLOC_2_2 GENMASK_ULL(17, 9) + #define HAL_RX_EHT_SIG_OFDMA_EB2_RU_ALLOC_2_3 GENMASK_ULL(26, 18) + #define HAL_RX_EHT_SIG_OFDMA_EB2_RU_ALLOC_2_4 GENMASK_ULL(35, 27) +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -63,6 +63,14 @@ extern unsigned int ath12k_frame_mode; + #define ATH12K_MAX_MLO_PEERS 256 + #define ATH12K_MLO_PEER_ID_INVALID 0xFFFF + ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) ++#define ATH12K_SSR_POWERUP SUBSYS_AFTER_POWERUP ++#define ATH12K_SSR_PREPARE_SHUTDOWN SUBSYS_PREPARE_FOR_FATAL_SHUTDOWN ++#else ++#define ATH12K_SSR_POWERUP QCOM_SSR_AFTER_POWERUP ++#define ATH12K_SSR_PREPARE_SHUTDOWN QCOM_SSR_NOTIFY_CRASH ++#endif ++ + enum ath12k_supported_bw { + ATH12K_BW_20 = 0, + ATH12K_BW_40 = 1, +@@ -1391,6 +1399,7 @@ struct ath12k_base { + bool collect_dump; + struct notifier_block ssr_nb; + struct notifier_block atomic_ssr_nb; ++ void *ssr_handle; + struct completion reconfigure_complete; + unsigned long reset_fail_timeout; + /* continuous recovery fail count */ +--- a/net/mac80211/debugfs_netdev.c ++++ b/net/mac80211/debugfs_netdev.c +@@ -320,7 +320,7 @@ static ssize_t ieee80211_if_parse_smps(s + } + IEEE80211_IF_FILE_RW(smps); + +-int ieee80211_if_fmt_bmiss_threshold(const struct ieee80211_sub_if_data *sdata, ++static ssize_t ieee80211_if_fmt_bmiss_threshold(const struct ieee80211_sub_if_data *sdata, + char *buf, int buflen) + { + return snprintf(buf, buflen, "%u\n", sdata->vif.bss_conf.bmiss_threshold); +--- a/drivers/net/wireless/ath/ath12k/ahb.c ++++ b/drivers/net/wireless/ath/ath12k/ahb.c +@@ -506,9 +506,13 @@ static int ath12k_ahb_config_ext_irq(str + irq_grp->ab = ab; + irq_grp->grp_id = i; + init_dummy_netdev(&irq_grp->napi_ndev); ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) + netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi, + ath12k_ahb_ext_grp_napi_poll, NAPI_POLL_WEIGHT); +- ++#else ++ netif_napi_add_weight(&irq_grp->napi_ndev, &irq_grp->napi, ++ ath12k_ahb_ext_grp_napi_poll, NAPI_POLL_WEIGHT); ++#endif + for (j = 0; j < ATH12K_EXT_IRQ_NUM_MAX; j++) { + if (ab->hw_params->ring_mask->tx[i] && + (j <= ATH12K_MAX_TCL_RING_NUM) && +@@ -635,20 +639,12 @@ static int ath12k_ahb_map_service_to_pip + + static int ath12k_ahb_ssr_notifier_reg(struct ath12k_base *ab) + { +- struct ath12k_ahb *ab_ahb = ath12k_ahb_priv(ab); +- +- return ath12k_rproc_register_subsys_notifier(ab_ahb->tgt_rrproc->name, +- &ab->ssr_nb, +- &ab->atomic_ssr_nb); ++ return ath12k_rproc_register_subsys_notifier(ab); + } + + static int ath12k_ahb_ssr_notifier_unreg(struct ath12k_base *ab) + { +- struct ath12k_ahb *ab_ahb = ath12k_ahb_priv(ab); +- +- return ath12k_rproc_unregister_subsys_notifier(ab_ahb->tgt_rrproc->name, +- &ab->ssr_nb, +- &ab->atomic_ssr_nb); ++ return ath12k_rproc_unregister_subsys_notifier(ab); + } + + static const struct ath12k_hif_ops ath12k_ahb_hif_ops_ipq5332 = { diff --git a/feeds/ipq95xx/mac80211/patches/qca/786-02-ath11-12k-Add-define-MAC80211_SFE_SUPPORT.patch b/feeds/ipq95xx/mac80211/patches/qca/786-02-ath11-12k-Add-define-MAC80211_SFE_SUPPORT.patch new file mode 100644 index 000000000..b814790e1 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/786-02-ath11-12k-Add-define-MAC80211_SFE_SUPPORT.patch @@ -0,0 +1,165 @@ +From 69bef38c76d034d6b73e6ddb0b3576f5d0298cea Mon Sep 17 00:00:00 2001 +From: Bhagavathi Perumal S +Date: Mon, 19 Jun 2023 23:44:58 +0530 +Subject: [PATCH] ath11\12k: Add define MAC80211_SFE_SUPPORT + +This patch add define MAC80211_SFE_SUPPORT to avoid compilation +error. the nss sfe pvt changes in kernel will cause compilaiton +error when built with upstream kernel. + +Signed-off-by: Bhagavathi Perumal S +--- + drivers/net/wireless/ath/ath11k/mac.c | 2 ++ + drivers/net/wireless/ath/ath12k/bondif.c | 2 ++ + drivers/net/wireless/ath/ath12k/dp_tx.c | 6 +++++- + drivers/net/wireless/ath/ath12k/mac.c | 2 ++ + net/mac80211/tx.c | 8 +++++--- + 5 files changed, 16 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -7584,8 +7584,10 @@ + int ret; + u64 adjusted_tsf; + ++#ifdef CPTCFG_MAC80211_SFE_SUPPORT + if (skb->fast_xmit) + info_flags |= IEEE80211_TX_CTL_HW_80211_ENCAP; ++#endif + + if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { + ieee80211_free_txskb(ar->hw, skb); +--- a/drivers/net/wireless/ath/ath12k/bondif.c ++++ b/drivers/net/wireless/ath/ath12k/bondif.c +@@ -570,7 +570,9 @@ + return 0; + } + ++#ifdef CPTCFG_MAC80211_SFE_SUPPORT + skb->fast_xmit = 0; ++#endif + return link_dev->netdev_ops->ndo_start_xmit(skb, link_dev); + } + +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -282,7 +282,11 @@ + #endif + dma_addr_t paddr; + int ret; ++#ifdef CPTCFG_MAC80211_SFE_SUPPORT + int len = skb->fast_xmit ? 256 : skb->len; ++#else ++ int len = skb->len; ++#endif + + ring_id = smp_processor_id(); + +@@ -309,11 +313,13 @@ + tx_desc->recycler_fast_xmit = 0; + tx_desc->timestamp = ktime_get_real(); + #if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) ++#ifdef CPTCFG_MAC80211_SFE_SUPPORT + /* the edma driver uses this flags to optimize the cache invalidation */ + skb->fast_recycled = 1; + if (skb->is_from_recycler) + tx_desc->recycler_fast_xmit = 1; + #endif ++#endif + skb_cb->vif = arvif->ahvif->vif; + skb_cb->paddr = paddr; + +@@ -1373,11 +1379,15 @@ + skb_shinfo(msdu)->frag_list = NULL; + } + ++#ifdef CPTCFG_MAC80211_SFE_SUPPORT + if (likely(msdu->is_from_recycler)) { + __skb_queue_head(&free_list_head, msdu); + } else { + dev_kfree_skb(msdu); + } ++#else ++ dev_kfree_skb(msdu); ++#endif + + work_done++; + } +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -9054,6 +9054,7 @@ + + ar = arvif->ar; + ++#ifdef CPTCFG_MAC80211_SFE_SUPPORT + if (skb->fast_xmit) { + ret = ath12k_mac_tx_check_max_limit(ar, skb); + if (ret) { +@@ -9072,6 +9073,7 @@ + } + return; + } ++#endif + + ah = ar->ah; + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -4630,7 +4630,7 @@ + #ifdef CPTCFG_MAC80211_NSS_SUPPORT + ieee80211_xmit_nss_fixup(skb, dev); + #endif +-#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) ++#ifdef CPTCFG_MAC80211_SFE_SUPPORT + skb->fast_xmit = 0; + #endif + +@@ -4872,6 +4872,7 @@ + netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb, + struct net_device *dev) + { ++#ifdef CPTCFG_MAC80211_SFE_SUPPORT + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_tx_control control = {}; +@@ -4906,9 +4907,10 @@ + } + + return NETDEV_TX_OK; +- } else { +- return __ieee80211_subif_start_xmit_8023(skb, dev, 0, 0, NULL); + } ++#endif ++ return __ieee80211_subif_start_xmit_8023(skb, dev, 0, 0, NULL); ++ + } + + netdev_tx_t __ieee80211_subif_start_xmit_8023(struct sk_buff *skb, +--- a/local-symbols ++++ b/local-symbols +@@ -68,6 +68,7 @@ + MAC80211_NSS_SUPPORT= + MAC80211_PPE_SUPPORT= + MAC80211_BONDED_SUPPORT= ++MAC80211_SFE_SUPPORT= + WLAN= + PCMCIA_RAYCS= + PCMCIA_WL3501= +--- a/net/mac80211/Kconfig ++++ b/net/mac80211/Kconfig +@@ -131,12 +131,12 @@ + + If unsure, say N. + +-config MAC80211_BONDED_SUPPORT +- bool "QTI mac80211 bonded support" ++config MAC80211_SFE_SUPPORT ++ bool "QTI mac80211 sfe support" + depends on ATH12K + default n + ---help--- +- Enables Bonded support for ATH12K driver ++ Enables sfe support for ATH12K driver + + If unsure, say N. + diff --git a/feeds/ipq95xx/mac80211/patches/qca/786-03-mac80211-Copied-MAC-to-net_dev-structure-via-dev_add.patch b/feeds/ipq95xx/mac80211/patches/qca/786-03-mac80211-Copied-MAC-to-net_dev-structure-via-dev_add.patch new file mode 100644 index 000000000..911bfb375 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/786-03-mac80211-Copied-MAC-to-net_dev-structure-via-dev_add.patch @@ -0,0 +1,38 @@ +From 5fd9168b0170441eac4ab7934b6f5184dd4d8d07 Mon Sep 17 00:00:00 2001 +From: Rakesh Ravanan +Date: Tue, 27 Jun 2023 15:35:32 +0530 +Subject: [PATCH] mac80211: Copied MAC to net_dev structure via dev_addr_set + +Netdev warning comes if when using memcpy to copy net_dev->dev_addr. +From 5.17 version, net_dev->dev_add should be filled with dev_addr_set +to aviod netdev warning. net_dev->dev_addr MAC gets filled via +dev_addr_set(). + +Signed-off-by: Rakesh Ravanan +--- + net/mac80211/iface.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -2379,10 +2379,20 @@ + } + + ieee80211_assign_perm_addr(local, ndev->perm_addr, type); ++ ndev->addr_len = ETH_ALEN; + if (is_valid_ether_addr(params->macaddr)) ++#if KERNEL_VERSION(5, 17, 0) > LINUX_VERSION_CODE + memcpy(ndev->dev_addr, params->macaddr, ETH_ALEN); ++#else ++ dev_addr_set(ndev, params->macaddr); ++#endif ++ + else ++#if KERNEL_VERSION(5, 17, 0) > LINUX_VERSION_CODE + memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN); ++#else ++ dev_addr_set(ndev, ndev->perm_addr); ++#endif + SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); + + /* don't use IEEE80211_DEV_TO_SUB_IF -- it checks too much */ diff --git a/feeds/ipq95xx/mac80211/patches/qca/786-ath12k-add-per-histogram-count-support.patch b/feeds/ipq95xx/mac80211/patches/qca/786-ath12k-add-per-histogram-count-support.patch new file mode 100644 index 000000000..ed286c520 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/786-ath12k-add-per-histogram-count-support.patch @@ -0,0 +1,136 @@ +From d8f091827da0ac6c2da81c94f9028b3b8b9c0bc0 Mon Sep 17 00:00:00 2001 +From: Saleemuddin Shaik +Date: Mon, 3 Jul 2023 17:13:54 +0530 +Subject: [PATCH] ath12k: add per histogram count support. + +Added the tlv for accessing HTT_STATS_TX_PDEV_SAWF_RATE_STATS_TAG, +Total 100 histogram counts will be retrived. +Support to monitor PER stats measured for a set of stations added. + +To print the per_histogram_count. +commands: +echo 9 > /sys/kernel/debug/ath12k/qcn9274 hw2.0_0004:01:00.0/mac0/htt_stats_type +cat /sys/kernel/debug/ath12k/qcn9274 hw2.0_0004:01:00.0/mac0/htt_stats + +Signed-off-by: Saleemuddin Shaik +--- + .../wireless/ath/ath12k/debugfs_htt_stats.c | 71 +++++++++++++++++++ + .../wireless/ath/ath12k/debugfs_htt_stats.h | 6 ++ + 2 files changed, 77 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c +index 3b0bb4a..4f5f7af 100644 +--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c +@@ -13,6 +13,7 @@ + + #define HTT_MAX_STRING_LEN 256 + #define HTT_MAX_PRINT_CHAR_PER_ELEM 15 ++#define HTT_HISTOGRAM_STATS_LEN 512 + + + #define PRINT_ARRAY_TO_BUF(out, buflen, arr, str, len, newline) \ +@@ -8042,6 +8043,74 @@ static inline void htt_print_dlpager_stats_tlv(const void *tag_buf, + stats_req->buf_len = len; + } + ++static inline void htt_print_histogram_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_tx_histogram_stats_tlv *htt_stats_buf = tag_buf; ++ u8 i = 0; ++ u16 index = 0; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ char data[HTT_HISTOGRAM_STATS_LEN] = {0}; ++ ++ len += scnprintf(buf + len, buf_len - len, "PER_HISTOGRAM_STATS\n"); ++ ++ index = 0; ++ memset(data, 0x0, HTT_HISTOGRAM_STATS_LEN); ++ ++ for (i = 0 ; i < 25; i++) { ++ index += scnprintf(&data[index], ++ HTT_HISTOGRAM_STATS_LEN - index, ++ " %u:%u,", i, htt_stats_buf->per_histogram_cnt[i]); ++ if (index >= HTT_HISTOGRAM_STATS_LEN) ++ break; ++ } ++ ++ len += scnprintf(buf + len, buf_len - len, "Per_histogram_cnt: %s\n", data); ++ ++ index = 0; ++ memset(data, 0x0, HTT_HISTOGRAM_STATS_LEN); ++ ++ for (i = 25 ; i < 50; i++) { ++ index += scnprintf(&data[index], ++ HTT_HISTOGRAM_STATS_LEN - index, ++ " %u:%u,", i, htt_stats_buf->per_histogram_cnt[i]); ++ if (index >= HTT_HISTOGRAM_STATS_LEN) ++ break; ++ } ++ ++ len += scnprintf(buf + len, buf_len - len, " %s\n", data); ++ ++ index = 0; ++ memset(data, 0x0, HTT_HISTOGRAM_STATS_LEN); ++ ++ for (i = 50 ; i < 75; i++) { ++ index += scnprintf(&data[index], ++ HTT_HISTOGRAM_STATS_LEN - index, ++ " %u:%u,", i, htt_stats_buf->per_histogram_cnt[i]); ++ if (index >= HTT_HISTOGRAM_STATS_LEN) ++ break; ++ } ++ ++ len += scnprintf(buf + len, buf_len - len, " %s\n", data); ++ ++ index = 0; ++ memset(data, 0x0, HTT_HISTOGRAM_STATS_LEN); ++ ++ for (i = 75 ; i < HTT_TX_PDEV_STATS_NUM_PER_COUNTERS; i++) { ++ index += scnprintf(&data[index], ++ HTT_HISTOGRAM_STATS_LEN - index, ++ " %u:%u,", i, htt_stats_buf->per_histogram_cnt[i]); ++ if (index >= HTT_HISTOGRAM_STATS_LEN) ++ break; ++ } ++ ++ len += scnprintf(buf + len, buf_len - len, " %s\n", data); ++ ++ stats_req->buf_len = len; ++} ++ + static int ath12k_dbg_htt_ext_stats_parse(struct ath12k_base *ab, + u16 tag, u16 len, const void *tag_buf, + void *user_data) +@@ -8670,6 +8739,8 @@ static int ath12k_dbg_htt_ext_stats_parse(struct ath12k_base *ab, + case HTT_STATS_TX_PDEV_MLO_TXOP_ABORT_TAG: + htt_print_tx_pdev_stats_mlo_txop_abort_tlv_v(tag_buf, len, stats_req); + break; ++ case HTT_STATS_TX_PDEV_SAWF_RATE_STATS_TAG: ++ htt_print_histogram_stats_tlv(tag_buf, stats_req); + default: + break; + } +diff --git a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h +index 9f642ce..ce1ff5f 100644 +--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h ++++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h +@@ -2551,6 +2551,12 @@ struct htt_rx_pdev_be_ul_mimo_user_stats_tlv { + u32 be_rx_ulmumimo_mpdu_fail; + }; + ++struct htt_tx_histogram_stats_tlv { ++ u32 rate_retry_mcs_drop_cnt; ++ u32 mcs_drop_rate[HTT_TX_PDEV_STATS_NUM_MCS_DROP_COUNTERS]; ++ u32 per_histogram_cnt[HTT_TX_PDEV_STATS_NUM_PER_COUNTERS]; ++}; ++ + struct htt_rx_pdev_ul_mumimo_trig_be_stats_tlv { + u32 mac_id__word; + +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/786-ath12k-fix-traffic-stall-with-MLO-AP-Mon-coexist.patch b/feeds/ipq95xx/mac80211/patches/qca/786-ath12k-fix-traffic-stall-with-MLO-AP-Mon-coexist.patch new file mode 100644 index 000000000..136a9752f --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/786-ath12k-fix-traffic-stall-with-MLO-AP-Mon-coexist.patch @@ -0,0 +1,74 @@ +From f81b597ba49b561504c1593ba86399f2b5871542 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Kathirvel +Date: Tue, 18 Jul 2023 23:25:08 +0530 +Subject: [PATCH] ath12k: fix traffic stall with MLO AP+Mon coexist + +With MLO AP+Mon coexist, encap/decap of the AP interfaces gets updated only +for the deflink, for the other link, data is getting stalled due to this +incorrect encap/decap set between two links. + +Fix by properly updating encap/decap type through offload_flags to all the mlo +vif links. + +Signed-off-by: Karthikeyan Kathirvel +--- + drivers/net/wireless/ath/ath12k/mac.c | 41 +++++++++++++++++---------- + 1 file changed, 26 insertions(+), 15 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -9898,31 +9898,38 @@ static void ath12k_mac_update_vif_offloa + } + } + +-static void ath12k_mac_op_update_vif_offload(struct ieee80211_hw *hw, +- struct ieee80211_vif *vif) ++static void ath12k_mac_hdl_update_vif_offload(struct ath12k_link_vif *arvif) + { +- struct ath12k_hw *ah = hw->priv; +- struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); +- struct ath12k_link_vif *arvif; +- +- mutex_lock(&ah->conf_mutex); +- +- /* TODO ML link vifs handling, currently checking default only */ +- /* If the update_vif_offload() is received from mac80211 before +- * vdev is created, no action is needed since the flags would +- * be applied right after vdev create based on vif->offload_flags +- */ +- arvif = &ahvif->deflink; + if (!arvif->ar) { + ath12k_info(NULL, +- "unable to determine device to apply vif encap/decap flags, setting will be applied on channel assignment\n"); +- mutex_unlock(&ah->conf_mutex); ++ "unable to determine device to apply vif encap/decap flags, setting will be applied on channel assignment\n"); + return; + } + + ath12k_mac_update_vif_offload(arvif->ar, arvif); + ath12k_dp_tx_update_bank_profile(arvif); ++} + ++static void ath12k_mac_op_update_vif_offload(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif) ++{ ++ struct ath12k_hw *ah = hw->priv; ++ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); ++ struct ath12k_link_vif *arvif; ++ int link_id; ++ ++ mutex_lock(&ah->conf_mutex); ++ if (vif->valid_links) { ++ for_each_set_bit(link_id, &vif->valid_links, IEEE80211_MLD_MAX_NUM_LINKS) { ++ arvif = ahvif->link[link_id]; ++ if (!(arvif && arvif->ar)) ++ continue; ++ ++ ath12k_mac_hdl_update_vif_offload(arvif); ++ } ++ } else { ++ ath12k_mac_hdl_update_vif_offload(&ahvif->deflink); ++ } + mutex_unlock(&ah->conf_mutex); + } + diff --git a/feeds/ipq95xx/mac80211/patches/qca/786-wifi-ath12k-Fix-buffer-overflow-when-scanning-with-e.patch b/feeds/ipq95xx/mac80211/patches/qca/786-wifi-ath12k-Fix-buffer-overflow-when-scanning-with-e.patch new file mode 100644 index 000000000..8397373d2 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/786-wifi-ath12k-Fix-buffer-overflow-when-scanning-with-e.patch @@ -0,0 +1,69 @@ +From ec3f4711a4896adbc51cd2e68d2460718f87c1c4 Mon Sep 17 00:00:00 2001 +From: Wen Gong +Date: Sun, 23 Oct 2022 22:52:14 -0400 +Subject: [PATCH 027/112] wifi: ath12k: Fix buffer overflow when scanning with + extraie + +If cfg80211 is providing extraie's for a scanning process then ath12k will +copy that over to the firmware. The extraie.len is a 32 bit value in struct +element_info and describes the amount of bytes for the vendor information +elements. + +The WMI_TLV packet is having a special WMI_TAG_ARRAY_BYTE section. This +section can have a (payload) length up to 65535 bytes because the +WMI_TLV_LEN can store up to 16 bits. The code was missing such a check and +could have created a scan request which cannot be parsed correctly by the +firmware. + +But the bigger problem was the allocation of the buffer. It has to align +the TLV sections by 4 bytes. But the code was using an u8 to store the +newly calculated length of this section (with alignment). And the new +calculated length was then used to allocate the skbuff. But the actual code +to copy in the data is using the extraie.len and not the calculated +"aligned" length. + +The length of extraie with IEEE80211_HW_SINGLE_SCAN_ON_ALL_BANDS enabled +was 264 bytes during tests with a QCA Milan card. But it only allocated 8 +bytes (264 bytes % 256) for it. As consequence, the code to memcpy the +extraie into the skb was then just overwriting data after skb->end. Things +like shinfo were therefore corrupted. This could usually be seen by a crash +in skb_zcopy_clear which tried to call a ubuf_info callback (using a bogus +address). + +Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-02582-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1 + +Signed-off-by: Wen Gong +Signed-off-by: Amutha Ravikumar +--- + drivers/net/wireless/ath/ath12k/wmi.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -2950,7 +2950,7 @@ int ath12k_wmi_send_scan_start_cmd(struc + void *ptr; + int i, ret, len; + u32 *tmp_ptr; +- u8 extraie_len_with_pad = 0; ++ u16 extraie_len_with_pad = 0; + struct hint_short_ssid *s_ssid = NULL; + struct hint_bssid *hint_bssid = NULL; + +@@ -2969,7 +2969,7 @@ int ath12k_wmi_send_scan_start_cmd(struc + len += sizeof(*bssid) * params->num_bssid; + + len += TLV_HDR_SIZE; +- if (params->extraie.len) ++ if (params->extraie.len && params->extraie.len <= 0xFFFF) + extraie_len_with_pad = + roundup(params->extraie.len, sizeof(u32)); + len += extraie_len_with_pad; +@@ -3072,7 +3072,7 @@ int ath12k_wmi_send_scan_start_cmd(struc + tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, len); + ptr += TLV_HDR_SIZE; + +- if (params->extraie.len) ++ if (extraie_len_with_pad) + memcpy(ptr, params->extraie.ptr, + params->extraie.len); + diff --git a/feeds/ipq95xx/mac80211/patches/qca/787-wifi-ath12k-change-to-use-dynamic-memory-for-channel.patch b/feeds/ipq95xx/mac80211/patches/qca/787-wifi-ath12k-change-to-use-dynamic-memory-for-channel.patch new file mode 100644 index 000000000..94ac732ff --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/787-wifi-ath12k-change-to-use-dynamic-memory-for-channel.patch @@ -0,0 +1,73 @@ +From 0fed75a051fd7193ff4b1966fc3aae2eb10c5ed3 Mon Sep 17 00:00:00 2001 +From: Wen Gong +Date: Mon, 29 Nov 2021 06:09:39 -0500 +Subject: [PATCH 028/112] wifi: ath12k: change to use dynamic memory for + channel list of scan + +Currently there are about 60 channels for 6 GHz, then the size of +chan_list in struct scan_req_params which is 40 is not enough to +fill all the channel list of 6 GHz. + +Use dynamic memory to save the channel list of scan. + +Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-02582-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1 + +Signed-off-by: Wen Gong +Signed-off-by: Amutha Ravikumar +--- + drivers/net/wireless/ath/ath12k/mac.c | 10 ++++++++++ + drivers/net/wireless/ath/ath12k/wmi.h | 3 +-- + 2 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index b5a60b69b7e6..30d49fd480c1 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -2791,6 +2791,14 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw, + + if (req->n_channels) { + arg.num_chan = req->n_channels; ++ arg.chan_list = kcalloc(arg.num_chan, sizeof(*arg.chan_list), ++ GFP_KERNEL); ++ ++ if (!arg.chan_list) { ++ ret = -ENOMEM; ++ goto exit; ++ } ++ + for (i = 0; i < arg.num_chan; i++) + arg.chan_list[i] = req->channels[i]->center_freq; + } +@@ -2814,6 +2822,8 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw, + ATH12K_MAC_SCAN_TIMEOUT_MSECS)); + + exit: ++ kfree(arg.chan_list); ++ + if (req->ie_len) + kfree(arg.extraie.ptr); + +diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h +index 1cc1478efaa1..7d85b03f7d54 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -3032,7 +3032,6 @@ enum scan_dwelltime_adaptive_mode { + + #define WLAN_SCAN_MAX_NUM_SSID 10 + #define WLAN_SCAN_MAX_NUM_BSSID 10 +-#define WLAN_SCAN_MAX_NUM_CHANNELS 40 + + struct ath12k_wmi_element_info_arg { + u32 len; +@@ -3241,7 +3240,7 @@ struct ath12k_wmi_scan_req_arg { + u32 num_bssid; + u32 num_ssids; + u32 n_probes; +- u32 chan_list[WLAN_SCAN_MAX_NUM_CHANNELS]; ++ u32 *chan_list; + u32 notify_scan_events; + struct cfg80211_ssid ssid[WLAN_SCAN_MAX_NUM_SSID]; + struct ath12k_wmi_mac_addr_params bssid_list[WLAN_SCAN_MAX_NUM_BSSID]; +-- +2.31.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/788-mac80211-Add-default-wmm-values-to-individual-links.patch b/feeds/ipq95xx/mac80211/patches/qca/788-mac80211-Add-default-wmm-values-to-individual-links.patch new file mode 100755 index 000000000..007144ce3 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/788-mac80211-Add-default-wmm-values-to-individual-links.patch @@ -0,0 +1,35 @@ +From ed68b4361bd1b783a8b35ab853d1828c8da041f3 Mon Sep 17 00:00:00 2001 +From: Ramanathan Choodamani +Date: Wed, 5 Jul 2023 23:08:02 -0700 +Subject: [PATCH] mac80211: Add default wmm values to individual links + +Usually during bring up, hostapd sends wmm values only +to the first link within a BSS. + +Then the do_open() sets default wmm values only to the +deflink but not to the individual links. + +This change adds default wmm values to the individual +links in different BSS during bring up. + +Signed-off-by: Ramanathan Choodamani +--- + net/mac80211/link.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/mac80211/link.c b/net/mac80211/link.c +index ee8ba71..88ea237 100644 +--- a/net/mac80211/link.c ++++ b/net/mac80211/link.c +@@ -293,6 +293,8 @@ static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata, + link = links[link_id]; + ieee80211_link_init(sdata, link_id, &link->data, &link->conf); + ieee80211_link_setup(&link->data); ++ ieee80211_set_wmm_default(&link->data, true, ++ sdata->vif.type != NL80211_IFTYPE_STATION); + } + + if (new_links == 0) +-- +2.7.4 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/788-wifi-ath12k-move-peer-delete-after-vdev-stop-of-stat.patch b/feeds/ipq95xx/mac80211/patches/qca/788-wifi-ath12k-move-peer-delete-after-vdev-stop-of-stat.patch new file mode 100644 index 000000000..a52290d5f --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/788-wifi-ath12k-move-peer-delete-after-vdev-stop-of-stat.patch @@ -0,0 +1,133 @@ +From e276c98058882d6121e64cced3217ae79d1dd940 Mon Sep 17 00:00:00 2001 +From: Wen Gong +Date: Fri, 22 Jul 2022 06:17:52 -0400 +Subject: [PATCH 031/112] wifi: ath12k: move peer delete after vdev stop of + station for WCN7850 + +When station connect to AP, the wmi command sequence is: + +peer_create->vdev_start->vdev_up + +and sequence of station disconnect fo AP is: + +peer_delete->vdev_down->vdev_stop + +The sequence of disconnect is not opposite of connect, it caused firmware +crash when it handle wmi vdev stop cmd when the AP is support TWT of +802.11 ax, because firmware need access the bss peer for vdev stop cmd. + +[ 390.438564] ath12k_pci 0000:05:00.0: wmi cmd send 0x6001 ret 0 +[ 390.438567] ath12k_pci 0000:05:00.0: WMI peer create vdev_id 0 peer_addr c4:04:15:3b:e0:39 +[ 390.472724] ath12k_pci 0000:05:00.0: mac vdev 0 start center_freq 2437 phymode 11ax-he20-2g +[ 390.472731] ath12k_pci 0000:05:00.0: wmi cmd send 0x5003 ret 0 +[ 390.560849] ath12k_pci 0000:05:00.0: wmi cmd send 0x5005 ret 0 +[ 390.560850] ath12k_pci 0000:05:00.0: WMI mgmt vdev up id 0x0 assoc id 1 bssid c4:04:15:3b:e0:39 + +[ 399.432896] ath12k_pci 0000:05:00.0: WMI peer delete vdev_id 0 peer_addr c4:04:15:3b:e0:39 +[ 399.432902] ath12k_pci 0000:05:00.0: wmi cmd send 0x6002 ret 0 +[ 399.441380] ath12k_pci 0000:05:00.0: wmi cmd send 0x5007 ret 0 +[ 399.441381] ath12k_pci 0000:05:00.0: WMI vdev down id 0x0 +[ 399.454681] ath12k_pci 0000:05:00.0: wmi cmd send 0x5006 ret 0 +[ 399.454682] ath12k_pci 0000:05:00.0: WMI vdev stop id 0x0 + +The opposite sequence of disconnect should be: + +vdev_down->vdev_stop->peer_delete + +This patch change the sequence of disconnect for station as above +opposite sequence for WCN7850, firmware not crash again with this patch. + +Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-02582-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1 + +Signed-off-by: Wen Gong +Signed-off-by: Amutha Ravikumar +--- + drivers/net/wireless/ath/ath12k/mac.c | 39 +++++++++++++++++++++------ + 1 file changed, 31 insertions(+), 8 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -6679,6 +6679,9 @@ static void ath12k_mac_station_post_remo + struct ath12k_peer *peer; + struct ath12k_sta *ahsta = arsta->ahsta; + struct ieee80211_sta *sta; ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ieee80211_vif *vif = ahvif->vif; ++ bool skip_peer_delete; + + sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + +@@ -6686,8 +6689,13 @@ static void ath12k_mac_station_post_remo + + mutex_lock(&ar->ab->tbl_mtx_lock); + spin_lock_bh(&ar->ab->base_lock); ++ skip_peer_delete = ar->ab->hw_params->vdev_start_delay && ++ vif->type == NL80211_IFTYPE_STATION; ++ + peer = ath12k_peer_find(ar->ab, arvif->vdev_id, arsta->addr); +- if (peer && peer->sta == sta) { ++ if (skip_peer_delete && peer) { ++ peer->sta = NULL; ++ } else if (peer && peer->sta == sta) { + ath12k_warn(ar->ab, "Found peer entry %pM n vdev %i after it was supposedly removed\n", + arsta->addr, arvif->vdev_id); + ath12k_peer_rhash_delete(ar->ab, peer); +@@ -6719,6 +6727,9 @@ static int ath12k_mac_station_remove(str + struct ath12k_sta *ahsta = arsta->ahsta; + struct ieee80211_sta *sta; + int ret; ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ieee80211_vif *vif = ahvif->vif; ++ bool skip_peer_delete; + + sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + +@@ -6730,15 +6741,20 @@ static int ath12k_mac_station_remove(str + + ath12k_dp_peer_cleanup(ar, arvif->vdev_id, arsta->addr); + +- ret = ath12k_peer_delete(ar, arvif->vdev_id, arsta->addr); +- if (ret) +- ath12k_warn(ar->ab, "Failed to delete peer: %pM for VDEV: %d\n", +- arsta->addr, arvif->vdev_id); +- else +- ath12k_dbg(ar->ab, ATH12K_DBG_PEER, "Removed peer: %pM for VDEV: %d\n", +- arsta->addr, arvif->vdev_id); ++ skip_peer_delete = ar->ab->hw_params->vdev_start_delay && ++ vif->type == NL80211_IFTYPE_STATION; + +- ath12k_mac_station_post_remove(ar, arvif, arsta); ++ if (!skip_peer_delete) { ++ ret = ath12k_peer_delete(ar, arvif->vdev_id, arsta->addr); ++ if (ret) ++ ath12k_warn(ar->ab, "Failed to delete peer: %pM for VDEV: %d\n", ++ arsta->addr, arvif->vdev_id); ++ else ++ ath12k_dbg(ar->ab, ATH12K_DBG_PEER, "Removed peer: %pM for VDEV: %d\n", ++ arsta->addr, arvif->vdev_id); ++ ++ ath12k_mac_station_post_remove(ar, arvif, arsta); ++ } + + return ret; + } +@@ -12936,6 +12952,19 @@ ath12k_mac_op_unassign_vif_chanctx(struc + } + + if (ab->hw_params->vdev_start_delay && ++ ahvif->vdev_type == WMI_VDEV_TYPE_STA) { ++ ret = ath12k_peer_delete(ar, arvif->vdev_id, arvif->bssid); ++ if (ret) ++ ath12k_warn(ar->ab, ++ "failed to delete peer %pM for vdev %d: %d\n", ++ arvif->bssid, arvif->vdev_id, ret); ++ else ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, ++ "mac removed peer %pM vdev %d after vdev stop\n", ++ arvif->bssid, arvif->vdev_id); ++ } ++ ++ if (ab->hw_params->vdev_start_delay && + ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) + ath12k_wmi_vdev_down(ar, arvif->vdev_id); + diff --git a/feeds/ipq95xx/mac80211/patches/qca/789-ath12k-Enable-panic-notifer-chain-for-driver-module.patch b/feeds/ipq95xx/mac80211/patches/qca/789-ath12k-Enable-panic-notifer-chain-for-driver-module.patch new file mode 100644 index 000000000..574286734 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/789-ath12k-Enable-panic-notifer-chain-for-driver-module.patch @@ -0,0 +1,262 @@ +From 61430783d33b820bae8d538d03529607c37c0261 Mon Sep 17 00:00:00 2001 +From: P Praneesh +Date: Thu, 6 Jul 2023 23:32:02 +0530 +Subject: [PATCH] ath12k: Enable panic notifer chain for driver module + +ath12k: Enable panic notifer chain for driver module + +Currently when driver crashes due to some unexpected descriptor +from the rings, there is no logic to collect firmware rddm dump. +To debug such issues, MAC/FW needs the rddm dump. + +Add panic notifier chain callback for ath12k module during insmod. +So that whenever driver or host panics, through the notifier chain +callback we collect the rddm dump of the firmware. Since +ath12k_coredump_segment_info can be called from the atomic context (panic +notifier chain), changing vzalloc to kzalloc to avoid sleep in +atomic context. + +Signed-off-by: Balamurugan S +Signed-off-by: P Praneesh +Signed-off-by: Aishwarya R +--- + drivers/net/wireless/ath/ath12k/core.c | 52 +++++++++++++++++++--- + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/coredump.c | 14 ++++-- + drivers/net/wireless/ath/ath12k/mhi.c | 2 +- + 4 files changed, 59 insertions(+), 10 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -1635,13 +1635,22 @@ void ath12k_core_issue_bug_on(struct ath + struct ath12k_hw_group *ag = ab->ag; + + if ((ag->mlo_capable && +- (atomic_read(&ath12k_coredump_ram_info.num_chip) >= ab->ag->num_started)) || +- (!ag->mlo_capable)) ++ (atomic_read(&ath12k_coredump_ram_info.num_chip) >= ab->ag->num_started) && ++ (!ab->in_panic)) || (!ag->mlo_capable)) { ++ /* set in_panic to true to avoid multiple rddm download during ++ * firmware crash ++ */ ++ ab->in_panic = true; + BUG_ON(1); +- else ++ } else { ++ /* set in_panic to true to avoid multiple rddm download during ++ * firmware crash ++ */ ++ ab->in_panic = true; + ath12k_info(ab, + "%d chip dump collected and waiting for partner chips\n", + atomic_read(&ath12k_coredump_ram_info.num_chip)); ++ } + } + + static void ath12k_coredump_download_ahb(struct ath12k_base *ab) +@@ -1715,9 +1724,14 @@ static int ath12k_core_atomic_ssr_notifi + ath12k_warn(ab, "Failed to get pdev from device node\n"); + return NOTIFY_DONE; + } +- if (strcmp(ssr_pdev->name, pdev->name) != 0) { ++ ++ /* incase of panic notifier ssr callback, ssr_pdev->name will not be same as ++ * pdev->name because ssr_pdev->name is ab->pdev->name which is not similar ++ * as dts entry ++ */ ++ if (!ab->in_panic && (strcmp(ssr_pdev->name, pdev->name) != 0)) { + ath12k_warn(ab, "SSR notification mismatch %s pdev name:%s\n", +- (char *)data, pdev->name); ++ ssr_pdev->name, pdev->name); + return NOTIFY_DONE; + } + +@@ -2687,6 +2701,33 @@ void *ath12k_get_ab_nd_peer_from_peer_ma + + #endif /* CPTCFG_ATH12K_SAWF */ + ++static void ath12k_rddm_notifier(struct notifier_block *this, ++ unsigned long event, void *ptr) ++{ ++ struct ath12k_base *ab; ++ struct ath12k_hw_group *ag; ++ int i; ++ ++ list_for_each_entry(ag, &ath12k_hw_groups, list) { ++ for (i = 0; i < ag->num_chip; i++) { ++ ab = ag->ab[i]; ++ if (ab->in_panic) ++ return; ++ ab->in_panic = true; ++ if (ab->hif.bus == ATH12K_BUS_AHB) ++ ath12k_core_atomic_ssr_notifier_cb(&ab->atomic_ssr_nb, ++ SUBSYS_PREPARE_FOR_FATAL_SHUTDOWN, ++ ab->pdev); ++ else ++ ath12k_coredump_download_rddm(ab); ++ } ++ } ++} ++ ++static struct notifier_block rddm_notifier = { ++ .notifier_call = ath12k_rddm_notifier, ++}; ++ + static int ath12k_init(void) + { + int ret; +@@ -2697,6 +2738,10 @@ static int ath12k_init(void) + return ret; + } + ++ /* Add notifier to an atomic notifier chain to get the callback during BUG_ON ++ */ ++ atomic_notifier_chain_register(&panic_notifier_list, &rddm_notifier); ++ + ret = ath12k_ahb_init(); + if (ret) { + ret = -ENODEV; +@@ -2723,6 +2768,7 @@ error: + + static void ath12k_exit(void) + { ++ atomic_notifier_chain_unregister(&panic_notifier_list, &rddm_notifier); + ath12k_pci_exit(); + ath12k_ahb_exit(); + ath12k_debugfs_destroy(); +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -1437,6 +1437,7 @@ struct ath12k_base { + struct vendor_info id; + u32 max_msduq_per_tid; + u32 default_msduq_per_tid; ++ bool in_panic; + + #ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT + ppe_ds_wlan_handle_t *ppeds_handle; +--- a/drivers/net/wireless/ath/ath12k/coredump.c ++++ b/drivers/net/wireless/ath/ath12k/coredump.c +@@ -109,9 +109,11 @@ void ath12k_coredump_build_inline(struct + header_size = sizeof(*file_data); + header_size += num_seg * sizeof(*segments); + header_size = PAGE_ALIGN(header_size); +- buf = vzalloc(header_size); +- if (!buf) ++ buf = kzalloc(header_size, GFP_ATOMIC); ++ if (!buf) { ++ ath12k_warn(ab, "Failed to allocate memory for coredump\n"); + return; ++ } + + file_data = (struct ath12k_dump_file_data *)buf; + strscpy(file_data->df_magic, "ATH12K-FW-DUMP", +@@ -150,7 +152,7 @@ void ath12k_coredump_build_inline(struct + + /* Wait until the dump is read and free is called */ + wait_for_completion(&dump_state.dump_done); +- vfree(file_data); ++ kfree(file_data); + } + + static enum ath12k_fw_crash_dump_type +@@ -195,8 +197,12 @@ void ath12k_coredump_download_rddm(struc + struct ath12k_coredump_segment_info *chip_seg; + int dump_count; + struct ath12k_hw_group *ag = ab->ag; ++ bool state = false; ++ ++ if (ab->in_panic) ++ state = true; + +- ath12k_mhi_coredump(mhi_ctrl, false); ++ ath12k_mhi_coredump(mhi_ctrl, state); + + rddm_img = mhi_ctrl->rddm_image; + fw_img = mhi_ctrl->fbc_image; +@@ -217,9 +223,11 @@ void ath12k_coredump_download_rddm(struc + + len = num_seg * sizeof(*segment); + +- segment = vzalloc(len); +- if (!segment) ++ segment = kzalloc(len, GFP_NOWAIT); ++ if (!segment) { ++ ath12k_err(ab, " Failed to allocate memory for segment for rddm download\n"); + return; ++ } + + seg_info = segment; + for (i = 0; i < fw_img->entries ; i++) { +@@ -286,13 +294,13 @@ void ath12k_coredump_download_rddm(struc + } + + num_seg = num_seg - skip_count; ++ + if(!ab->fw_recovery_support) { + if (ag->mlo_capable) { + dump_count = atomic_read(&ath12k_coredump_ram_info.num_chip); + if (dump_count >= ATH12K_MAX_SOCS) { +- ath12k_err(ab, "invalid chip number %d\n", +- dump_count); +- return; ++ ath12k_err(ab, "invalid chip number %d\n",dump_count); ++ return; + } else { + chip_seg = &ath12k_coredump_ram_info.chip_seg_info[dump_count]; + chip_seg->chip_id = ar_pci->dev_id; +@@ -326,8 +334,44 @@ void ath12k_coredump_download_rddm(struc + } else { + /* TODO dump collection for MLO when fw_recovery set */ + ath12k_info(ab, "WLAN target is restarting"); +- ath12k_coredump_build_inline(ab, segment, num_seg); +- vfree(segment); ++ ++ if(!ab->in_panic) { ++ ath12k_coredump_build_inline(ab, segment, num_seg); ++ kfree(segment); ++ } else { ++ if (ag->mlo_capable){ ++ dump_count = atomic_read(&ath12k_coredump_ram_info.num_chip); ++ if (dump_count >= ATH12K_MAX_SOCS) { ++ ath12k_err(ab, "invalid chip number %d\n",dump_count); ++ return; ++ } else { ++ chip_seg = &ath12k_coredump_ram_info.chip_seg_info[dump_count]; ++ chip_seg->chip_id = ar_pci->dev_id; ++ chip_seg->qrtr_id = ar_pci->ab->qmi.service_ins_id; ++ chip_seg->bus_id = pci_domain_nr(ar_pci->pdev->bus); ++ chip_seg->num_seg = num_seg; ++ chip_seg->seg = segment; ++ atomic_inc(&ath12k_coredump_ram_info.num_chip); ++ } ++ } else { ++ /* This part of code for 12.2 without mlo_capable=1 */ ++ dump_count = atomic_read(&ath12k_coredump_ram_info.num_chip); ++ chip_seg = &ath12k_coredump_ram_info.chip_seg_info[dump_count]; ++ chip_seg->chip_id = ar_pci->dev_id; ++ chip_seg->qrtr_id = ar_pci->ab->qmi.service_ins_id; ++ chip_seg->bus_id = pci_domain_nr(ar_pci->pdev->bus); ++ chip_seg->num_seg = num_seg; ++ chip_seg->seg = segment; ++ atomic_inc(&ath12k_coredump_ram_info.num_chip); ++ } ++ ++ chip_seg = &ath12k_coredump_seg_info; ++ chip_seg->chip_id = ar_pci->dev_id; ++ chip_seg->qrtr_id = ar_pci->ab->qmi.service_ins_id; ++ chip_seg->bus_id = pci_domain_nr(ar_pci->pdev->bus); ++ chip_seg->num_seg = num_seg; ++ chip_seg->seg = segment; ++ } + } + + } +--- a/drivers/net/wireless/ath/ath12k/mhi.c ++++ b/drivers/net/wireless/ath/ath12k/mhi.c +@@ -686,5 +686,5 @@ void ath12k_mhi_resume(struct ath12k_pci + + void ath12k_mhi_coredump(struct mhi_controller *mhi_ctrl, bool state) + { +- mhi_download_rddm_image(mhi_ctrl, false); ++ mhi_download_rddm_image(mhi_ctrl, state); + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/789-wifi-ath12k-add-handler-for-scan-event-WMI_SCAN_EVEN.patch b/feeds/ipq95xx/mac80211/patches/qca/789-wifi-ath12k-add-handler-for-scan-event-WMI_SCAN_EVEN.patch new file mode 100644 index 000000000..df5ee2903 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/789-wifi-ath12k-add-handler-for-scan-event-WMI_SCAN_EVEN.patch @@ -0,0 +1,48 @@ +From 9bbad769bf828e2c4117d52218e0a657bc22c1d1 Mon Sep 17 00:00:00 2001 +From: Wen Gong +Date: Tue, 28 Sep 2021 14:00:45 +0300 +Subject: [PATCH 033/112] wifi: ath12k: add handler for scan event + WMI_SCAN_EVENT_DEQUEUED + +When wlan interface is up, 11d scan is sent to the firmware, and the +firmware needs to spend couple of seconds to complete the 11d scan. If +immediately a normal scan from user space arrives to ath12k, then the +normal scan request is also sent to the firmware, but the scan started +event will be reported to ath12k until the 11d scan complete. When timed +out for the scan started in ath12k, ath12k stops the normal scan and the +firmware reports WMI_SCAN_EVENT_DEQUEUED to ath12k for the normal scan. +ath12k has no handler for the event and then timed out for the scan +completed in ath12k_scan_stop(), and ath12k prints the following error +message. + +[ 1491.604750] ath12k_pci 0000:02:00.0: failed to receive scan abort comple: timed out +[ 1491.604756] ath12k_pci 0000:02:00.0: failed to stop scan: -110 +[ 1491.604758] ath12k_pci 0000:02:00.0: failed to start hw scan: -110 + +Add a handler for WMI_SCAN_EVENT_DEQUEUED and then complete the scan to +get rid of the above error message. + +Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-02582-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1 + +Signed-off-by: Wen Gong +Signed-off-by: Amutha Ravikumar +--- + drivers/net/wireless/ath/ath12k/wmi.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c +index 30ab7ba7fe4c..cea29991ef72 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -5888,6 +5888,8 @@ static void ath12k_scan_event(struct ath12k_base *ab, struct sk_buff *skb) + ath12k_wmi_event_scan_start_failed(ar); + break; + case WMI_SCAN_EVENT_DEQUEUED: ++ __ath12k_mac_scan_finish(ar); ++ break; + case WMI_SCAN_EVENT_PREEMPTED: + case WMI_SCAN_EVENT_RESTARTED: + case WMI_SCAN_EVENT_FOREIGN_CHAN_EXIT: +-- +2.31.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/790-wifi-ath12k-indicate-scan-complete-for-scan-canceled.patch b/feeds/ipq95xx/mac80211/patches/qca/790-wifi-ath12k-indicate-scan-complete-for-scan-canceled.patch new file mode 100644 index 000000000..56d334fb7 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/790-wifi-ath12k-indicate-scan-complete-for-scan-canceled.patch @@ -0,0 +1,72 @@ +From e2334bbcbcbfa38aff2768cd0325d2b440098899 Mon Sep 17 00:00:00 2001 +From: Wen Gong +Date: Tue, 28 Sep 2021 14:00:45 +0300 +Subject: [PATCH 034/112] wifi: ath12k: indicate scan complete for scan + canceled when scan running + +ath12k prints "Received scan event for unknown vdev" when doing the +following test: +1. trigger scan +2. wait 0.2 second +3. iw reg set or 11d scan complete from firmware + +Reason: When iw reg set or 11d scan complete, the new country code will +be set to the firmware, and the new regdomain info indicated to ath12k, +then the new channel list will be sent to the firmware. The firmware +will cancel the current scan after receiving WMI_SCAN_CHAN_LIST_CMDID +which is used for the new channel list, and the state of ath12k is +ATH12K_SCAN_RUNNING, then ath12k_get_ar_on_scan_abort() returns NULL and +ath12k_scan_event() returns at this point and does not indicate scan +completion to mac80211. + +Indicate scan completion to mac80211 and get rid of the "Received scan +event for unknown vdev" print for the above case. + +Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-02582-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1 + +Signed-off-by: Wen Gong +Signed-off-by: Amutha Ravikumar +--- + drivers/net/wireless/ath/ath12k/wmi.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -11110,8 +11110,9 @@ exit: + rcu_read_unlock(); + } + +-static struct ath12k *ath12k_get_ar_on_scan_abort(struct ath12k_base *ab, +- u32 vdev_id) ++static struct ath12k *ath12k_get_ar_on_scan_state(struct ath12k_base *ab, ++ u32 vdev_id, ++ enum ath12k_scan_state state) + { + int i; + struct ath12k_pdev *pdev; +@@ -11123,7 +11124,7 @@ static struct ath12k *ath12k_get_ar_on_s + ar = pdev->ar; + + spin_lock_bh(&ar->data_lock); +- if (ar->scan.state == ATH12K_SCAN_ABORTING && ++ if (ar->scan.state == state && + ar->scan.vdev_id == vdev_id) { + spin_unlock_bh(&ar->data_lock); + return ar; +@@ -11153,9 +11154,13 @@ static void ath12k_scan_event(struct ath + * aborting scan's vdev id matches this event info. + */ + if (scan_ev.event_type == WMI_SCAN_EVENT_COMPLETED && +- scan_ev.reason == WMI_SCAN_REASON_CANCELLED) +- ar = ath12k_get_ar_on_scan_abort(ab, scan_ev.vdev_id); +- else ++ scan_ev.reason == WMI_SCAN_REASON_CANCELLED) { ++ ar = ath12k_get_ar_on_scan_state(ab, le32_to_cpu(scan_ev.vdev_id), ++ ATH12K_SCAN_ABORTING); ++ if(!ar) ++ ar = ath12k_get_ar_on_scan_state(ab, le32_to_cpu(scan_ev.vdev_id), ++ ATH12K_SCAN_RUNNING); ++ } else + ar = ath12k_mac_get_ar_by_vdev_id(ab, scan_ev.vdev_id); + + if (!ar) { diff --git a/feeds/ipq95xx/mac80211/patches/qca/791-wifi-ath12k-indicate-to-mac80211-scan-complete-with-.patch b/feeds/ipq95xx/mac80211/patches/qca/791-wifi-ath12k-indicate-to-mac80211-scan-complete-with-.patch new file mode 100644 index 000000000..af2e6ab8d --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/791-wifi-ath12k-indicate-to-mac80211-scan-complete-with-.patch @@ -0,0 +1,68 @@ +From 752f80f35f4910575c6c70f1ad2b0ad8c4b09a09 Mon Sep 17 00:00:00 2001 +From: Wen Gong +Date: Tue, 28 Sep 2021 14:00:45 +0300 +Subject: [PATCH 035/112] wifi: ath12k: indicate to mac80211 scan complete with + aborted flag for ATH12K_SCAN_STARTING state + +Scan failure can not be recovered from when running a loop of the +following steps: +1. run scan: "iw wlan scan". +2. run command: echo assert > /sys/kernel/debug/ath12k/qca6490\ hw2.0/simulate_fw_crash + immediately after step 1. + +result: +scan failed and can not recover even when wlan recovery succeeds: +command failed: Device or resource busy (-16) + +reason: +When scan arrives, WMI_START_SCAN_CMDID is sent to the firmware and +function ath12k_mac_op_hw_scan() returns, then simulate_fw_crash arrives +and the scan started event does not arrive, and then it starts to do +recovery of wlan. __ath12k_mac_scan_finish() which is called from +ath12k_core_halt() is one step of recovery, it will not call +ieee80211_scan_completed() by logic currently because the scan state is +ATH12K_SCAN_STARTING. Thus it leads the scan not being completed in +mac80211, and leads all consecutive scans failing with -EBUSY in +nl80211_trigger_scan even after wlan recovery success. + +Indicate scan complete with aborted flag to mac80211 for +ATH12K_SCAN_STARTING to allow recovery from scan failed with "Device or +resource busy (-16)" after wlan recovery. + +Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-02582-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1 + +Signed-off-by: Wen Gong +Signed-off-by: Amutha Ravikumar +--- + drivers/net/wireless/ath/ath12k/mac.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -4887,18 +4887,20 @@ void __ath12k_mac_scan_finish(struct ath + break; + case ATH12K_SCAN_RUNNING: + case ATH12K_SCAN_ABORTING: ++ if (ar->scan.is_roc && ar->scan.roc_notify) ++ ieee80211_remain_on_channel_expired(ah->hw); ++ fallthrough; ++ case ATH12K_SCAN_STARTING: + if (!ar->scan.is_roc) { + struct cfg80211_scan_info info = { +- .aborted = (ar->scan.state == +- ATH12K_SCAN_ABORTING), ++ .aborted = ((ar->scan.state == ++ ATH12K_SCAN_ABORTING) || ++ (ar->scan.state == ++ ATH12K_SCAN_STARTING)) + }; + + ieee80211_scan_completed(ah->hw, &info); +- } else if (ar->scan.roc_notify) { +- ieee80211_remain_on_channel_expired(ah->hw); + } +- fallthrough; +- case ATH12K_SCAN_STARTING: + ar->scan.state = ATH12K_SCAN_IDLE; + ar->scan_channel = NULL; + ar->scan.roc_freq = 0; diff --git a/feeds/ipq95xx/mac80211/patches/qca/800-wifi-ath12k-Add-UMAC-DP-reset-support.patch b/feeds/ipq95xx/mac80211/patches/qca/800-wifi-ath12k-Add-UMAC-DP-reset-support.patch new file mode 100644 index 000000000..6f6f608a5 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/800-wifi-ath12k-Add-UMAC-DP-reset-support.patch @@ -0,0 +1,2026 @@ +From 55d2d854cc8bce739732d162a98bfbc52164a998 Mon Sep 17 00:00:00 2001 +From: Ramya Gnanasekar +Date: Wed, 21 Jun 2023 23:10:07 +0530 +Subject: [PATCH] wifi: ath12k: Add UMAC DP reset support + +The code changes are to add support for umac dp +reset of partner SOC when one SOC crashes in MLO +as a part of MODE 1 SSR + +In this process shared memory will be used by Host and +Firmware to communicate the sequence of events. Host will +clear the data structures such as tx/rx descriptors and +re-initialize the rings and reset hp/tp to 0. + +Signed-off-by: Ramya Gnanasekar +--- + drivers/net/wireless/ath/ath12k/Makefile | 3 +- + drivers/net/wireless/ath/ath12k/core.c | 7 + + drivers/net/wireless/ath/ath12k/core.h | 13 + + drivers/net/wireless/ath/ath12k/debug.h | 1 + + drivers/net/wireless/ath/ath12k/dp.c | 209 ++++++++-- + drivers/net/wireless/ath/ath12k/dp.h | 183 +++++++++ + drivers/net/wireless/ath/ath12k/dp_rx.c | 3 +- + drivers/net/wireless/ath/ath12k/dp_tx.c | 3 +- + drivers/net/wireless/ath/ath12k/hif.h | 13 + + drivers/net/wireless/ath/ath12k/hw.c | 61 ++- + drivers/net/wireless/ath/ath12k/hw.h | 7 +- + drivers/net/wireless/ath/ath12k/pci.c | 60 ++- + drivers/net/wireless/ath/ath12k/umac_reset.c | 411 +++++++++++++++++++ + 13 files changed, 933 insertions(+), 41 deletions(-) + create mode 100644 drivers/net/wireless/ath/ath12k/umac_reset.c + +--- a/drivers/net/wireless/ath/ath12k/Makefile ++++ b/drivers/net/wireless/ath/ath12k/Makefile +@@ -21,7 +21,8 @@ ath12k-y += core.o \ + mhi.o \ + pci.o \ + dp_mon.o \ +- vendor.o ++ vendor.o \ ++ umac_reset.o + + ath12k-$(CPTCFG_ATH12K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o + ath12k-$(CPTCFG_NL80211_TESTMODE) += testmode.o +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -1347,9 +1347,14 @@ static int ath12k_core_hw_group_start(st + struct ath12k_base *ab = ag->ab[0]; + int ret, i; + bool is_registered = false; ++ struct ath12k_mlo_dp_umac_reset *mlo_umac_reset; + + lockdep_assert_held(&ag->mutex_lock); + ++ mlo_umac_reset = &ag->mlo_umac_reset; ++ if (ab->hw_params->support_umac_reset) ++ spin_lock_init(&mlo_umac_reset->lock); ++ + /* Check If already registered or not, since same flow + * execute for HW restart case. + */ +@@ -1421,6 +1426,13 @@ static int ath12k_core_hw_group_start(st + } + } + ++ ret = ath12k_dp_umac_reset_init(ab); ++ if (ret) { ++ mutex_unlock(&ab->core_lock); ++ ath12k_warn(ab, "Failed to initialize UMAC RESET: %d\n", ret); ++ goto pdev_cleanup; ++ } ++ + set_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags); + + mutex_unlock(&ab->core_lock); +@@ -1439,6 +1451,7 @@ pdev_cleanup: + + ath12k_core_pdev_deinit(ab); + ath12k_hif_irq_disable(ab); ++ ath12k_dp_umac_reset_deinit(ab); + + mutex_unlock(&ab->core_lock); + } +@@ -1767,6 +1780,7 @@ static int ath12k_core_reconfigure_on_cr + + ath12k_dp_free(ab); + ath12k_hal_srng_deinit(ab); ++ ath12k_umac_reset_completion(ab); + + ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS)) - 1; + ab->num_db_cap = 0; +@@ -2438,6 +2452,7 @@ static void ath12k_core_hw_group_stop(st + ath12k_hif_irq_disable(ab); + ath12k_core_pdev_destroy(ab); + ath12k_core_stop(ab); ++ ath12k_dp_umac_reset_deinit(ab); + clear_bit(ATH12K_FLAG_CORE_REGISTERED, &ab->dev_flags); + + mutex_unlock(&ab->core_lock); +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -252,6 +252,8 @@ enum ath12k_dev_flags { + ATH12K_FLAG_FTM_SEGMENTED, + ATH12K_FLAG_PPE_DS_ENABLED, + ATH12K_FLAG_WMI_INIT_DONE, ++ ATH12K_FLAG_UMAC_PRERESET_START, ++ ATH12K_FLAG_UMAC_RESET_COMPLETE, + }; + + enum ath12k_monitor_flags { +@@ -1255,6 +1257,18 @@ enum ath12k_mlo_recovery_mode { + ATH12K_MLO_RECOVERY_MODE0, + }; + ++struct ath12k_mlo_dp_umac_reset { ++ atomic_t response_chip; ++ spinlock_t lock; ++ u8 umac_reset_info; ++ u8 initiator_chip; ++ u8 is_intr_bkup; ++ struct ath12k_hw_ring_mask intr_bkup; ++}; ++ ++#define ATH12K_UMAC_RESET_IPC 451 ++#define ATH12K_IS_UMAC_RESET_IN_PROGRESS BIT(0) ++ + /* Holds info on the group of SOCs that are registered as a single wiphy + * or single SOC where each radio registered as separate wiphy in non-MLO + */ +@@ -1278,6 +1292,7 @@ struct ath12k_hw_group { + struct ath12k_mgmt_rx_reo_context rx_reo; + struct ath12k_host_mlo_mem_arena mlomem_arena; + atomic_t num_dp_tx_pending; ++ struct ath12k_mlo_dp_umac_reset mlo_umac_reset; + }; + + /* Master structure to hold the hw data which may be used in core module */ +@@ -1357,7 +1372,7 @@ struct ath12k_base { + bool pdevs_macaddr_valid; + int bd_api; + +- const struct ath12k_hw_params *hw_params; ++ struct ath12k_hw_params *hw_params; + struct ath12k_bus_params bus_params; + bool is_qdss_tracing; + +@@ -1458,6 +1473,7 @@ struct ath12k_base { + int userpd_id; + + u32 chwidth_num_peer_caps; ++ struct ath12k_dp_umac_reset dp_umac_reset; + + /* must be last */ + u8 drv_priv[0] __aligned(sizeof(void *)); +@@ -1628,6 +1644,10 @@ int ath12k_sawf_send_disable_soc(u8 svc_ + int ath12k_core_sawf_ul_config(struct net_device *dev, struct ath12k_sawf_wmi_peer_latency_param *latency_info); + void *ath12k_get_ab_nd_peer_from_peer_mac(u8 *peer_mac, struct ath12k_base **ab_ref); + #endif /* CPTCFG_ATH12K_SAWF */ ++void ath12k_dp_umac_reset_handle(struct ath12k_base *ab); ++int ath12k_dp_umac_reset_init(struct ath12k_base *ab); ++void ath12k_dp_umac_reset_deinit(struct ath12k_base *ab); ++void ath12k_umac_reset_completion(struct ath12k_base *ab); + + static inline const char *ath12k_scan_state_str(enum ath12k_scan_state state) + { +--- a/drivers/net/wireless/ath/ath12k/debug.h ++++ b/drivers/net/wireless/ath/ath12k/debug.h +@@ -33,6 +33,7 @@ enum ath12k_debug_mask { + /* keep last*/ + ATH12K_DBG_SAWF = 0x00040000, + ATH12K_DBG_PPE = 0x00080000, ++ ATH12K_DBG_DP_UMAC_RESET= 0x00100000, + ATH12K_DBG_ANY = 0xffffffff, + }; + +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -189,49 +189,76 @@ static int ath12k_dp_srng_find_ring_in_m + return -ENOENT; + } + ++bool ath12k_dp_umac_reset_in_progress(struct ath12k_base *ab) ++{ ++ struct ath12k_hw_group *ag = ab->ag; ++ struct ath12k_mlo_dp_umac_reset *mlo_umac_reset = &ag->mlo_umac_reset; ++ bool umac_in_progress = false; ++ ++ if (!ab->hw_params->support_umac_reset) ++ return umac_in_progress; ++ ++ spin_lock_bh(&mlo_umac_reset->lock); ++ if (mlo_umac_reset->umac_reset_info & ++ ATH12K_IS_UMAC_RESET_IN_PROGRESS) ++ umac_in_progress = true; ++ spin_unlock_bh(&mlo_umac_reset->lock); ++ ++ return umac_in_progress; ++} ++ + static int ath12k_dp_srng_calculate_msi_group(struct ath12k_base *ab, + enum hal_ring_type type, int ring_num) + { + const u8 *grp_mask; ++ struct ath12k_hw_group *ag = ab->ag; ++ struct ath12k_mlo_dp_umac_reset *umac_reset; ++ struct ath12k_hw_ring_mask *ring_mask; ++ ++ umac_reset = &ag->mlo_umac_reset; ++ if (ath12k_dp_umac_reset_in_progress(ab) && umac_reset) ++ ring_mask = &umac_reset->intr_bkup; ++ else ++ ring_mask = ab->hw_params->ring_mask; + + switch (type) { + case HAL_WBM2SW_RELEASE: + if (ring_num == HAL_WBM2SW_REL_ERR_RING_NUM) { +- grp_mask = &ab->hw_params->ring_mask->rx_wbm_rel[0]; ++ grp_mask = &ring_mask->rx_wbm_rel[0]; + ring_num = 0; + #ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT + } else if (ring_num == HAL_WBM2SW_PPEDS_TX_CMPLN_RING_NUM) { +- grp_mask = &ab->hw_params->ring_mask->wbm2sw6_ppeds_tx_cmpln[0]; ++ grp_mask = &ring_mask->wbm2sw6_ppeds_tx_cmpln[0]; + ring_num = 0; + #endif + } else { +- grp_mask = &ab->hw_params->ring_mask->tx[0]; ++ grp_mask = &ring_mask->tx[0]; + } + break; + case HAL_REO_EXCEPTION: +- grp_mask = &ab->hw_params->ring_mask->rx_err[0]; ++ grp_mask = &ring_mask->rx_err[0]; + break; + case HAL_REO_DST: +- grp_mask = &ab->hw_params->ring_mask->rx[0]; ++ grp_mask = &ring_mask->rx[0]; + break; + case HAL_REO_STATUS: +- grp_mask = &ab->hw_params->ring_mask->reo_status[0]; ++ grp_mask = &ring_mask->reo_status[0]; + break; + case HAL_RXDMA_MONITOR_STATUS: + case HAL_RXDMA_MONITOR_DST: +- grp_mask = &ab->hw_params->ring_mask->rx_mon_dest[0]; ++ grp_mask = &ring_mask->rx_mon_dest[0]; + break; + case HAL_TX_MONITOR_DST: +- grp_mask = &ab->hw_params->ring_mask->tx_mon_dest[0]; ++ grp_mask = &ring_mask->tx_mon_dest[0]; + break; + case HAL_RXDMA_BUF: +- grp_mask = &ab->hw_params->ring_mask->host2rxdma[0]; ++ grp_mask = &ring_mask->host2rxdma[0]; + break; + case HAL_PPE2TCL: +- grp_mask = &ab->hw_params->ring_mask->ppe2tcl[0]; ++ grp_mask = &ring_mask->ppe2tcl[0]; + break; + case HAL_REO2PPE: +- grp_mask = &ab->hw_params->ring_mask->reo2ppe[0]; ++ grp_mask = &ring_mask->reo2ppe[0]; + break; + case HAL_RXDMA_MONITOR_BUF: + case HAL_TCL_DATA: +@@ -498,24 +525,29 @@ int ath12k_dp_srng_setup(struct ath12k_b + default: + cached = false; + } +- +- if (cached) { +- ring->vaddr_unaligned = kzalloc(ring->size, GFP_KERNEL); +- ring->paddr_unaligned = virt_to_phys(ring->vaddr_unaligned); +- } + } +- if (!cached) ++ ++ if (ath12k_dp_umac_reset_in_progress(ab)) ++ goto skip_dma_alloc; ++ ++ if (cached) { ++ ring->vaddr_unaligned = kzalloc(ring->size, GFP_KERNEL); ++ ring->paddr_unaligned = virt_to_phys(ring->vaddr_unaligned); ++ } else { + ring->vaddr_unaligned = dma_alloc_coherent(ab->dev, ring->size, + &ring->paddr_unaligned, + GFP_KERNEL); ++ } ++ + if (!ring->vaddr_unaligned) + return -ENOMEM; + +- memset(ring->vaddr_unaligned, 0, ring->size); + ring->vaddr = PTR_ALIGN(ring->vaddr_unaligned, HAL_RING_BASE_ALIGN); + ring->paddr = ring->paddr_unaligned + ((unsigned long)ring->vaddr - + (unsigned long)ring->vaddr_unaligned); + ++skip_dma_alloc: ++ memset(ring->vaddr_unaligned, 0, ring->size); + params.ring_base_vaddr = ring->vaddr; + params.ring_base_paddr = ring->paddr; + params.num_entries = num_entries; +@@ -758,6 +790,50 @@ static int ath12k_dp_init_bank_profiles( + return 0; + } + ++static void ath12k_dp_srng_hw_disable(struct ath12k_base *ab, struct dp_srng *ring) ++{ ++ struct hal_srng *srng = &ab->hal.srng_list[ring->ring_id]; ++ u32 reg_base, val, addr; ++ ++ reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R0]; ++ if (srng->ring_dir == HAL_SRNG_DIR_SRC) { ++ if (srng->ring_id == HAL_SRNG_RING_ID_WBM_IDLE_LINK) ++ addr = HAL_SEQ_WCSS_UMAC_WBM_REG + ++ HAL_WBM_IDLE_LINK_RING_MISC_ADDR(ab); ++ else ++ addr = reg_base + HAL_TCL1_RING_MISC_OFFSET(ab); ++ val = ath12k_hif_read32(ab, addr); ++ val &= ~HAL_TCL1_RING_MISC_SRNG_ENABLE; ++ ath12k_hif_write32(ab, addr, val); ++ } else { ++ val = ath12k_hif_read32(ab, reg_base + HAL_REO1_RING_MISC_OFFSET); ++ val &= ~HAL_REO1_RING_MISC_SRNG_ENABLE; ++ ath12k_hif_write32(ab , reg_base + HAL_REO1_RING_MISC_OFFSET, val); ++ } ++} ++ ++void ath12k_dp_srng_hw_ring_disable(struct ath12k_base *ab) ++{ ++ struct ath12k_dp *dp = &ab->dp; ++ int i; ++ ++ for (i = 0; i < DP_REO_DST_RING_MAX; i++) ++ ath12k_dp_srng_hw_disable(ab, &dp->reo_dst_ring[i]); ++ ath12k_dp_srng_hw_disable(ab, &dp->wbm_desc_rel_ring); ++ ath12k_dp_srng_hw_disable(ab, &dp->tcl_cmd_ring); ++ ++ for(i = 0; i < ab->hw_params->max_tx_ring; i++) { ++ ath12k_dp_srng_hw_disable(ab, &dp->tx_ring[i].tcl_data_ring); ++ ath12k_dp_srng_hw_disable(ab, &dp->tx_ring[i].tcl_comp_ring); ++ } ++ ath12k_dp_srng_hw_disable(ab, &dp->reo_reinject_ring); ++ ath12k_dp_srng_hw_disable(ab, &dp->rx_rel_ring); ++ ath12k_dp_srng_hw_disable(ab, &dp->reo_except_ring); ++ ath12k_dp_srng_hw_disable(ab, &dp->reo_cmd_ring); ++ ath12k_dp_srng_hw_disable(ab, &dp->reo_status_ring); ++ ath12k_dp_srng_hw_disable(ab, &dp->wbm_idle_ring); ++} ++ + static void ath12k_dp_srng_common_cleanup(struct ath12k_base *ab) + { + struct ath12k_dp *dp = &ab->dp; +@@ -806,11 +882,13 @@ static int ath12k_dp_srng_common_setup(s + goto err; + } + +- ret = ath12k_dp_srng_setup(ab, &dp->tcl_status_ring, HAL_TCL_STATUS, +- 0, 0, DP_TCL_STATUS_RING_SIZE); +- if (ret) { +- ath12k_warn(ab, "failed to set up tcl_status ring :%d\n", ret); +- goto err; ++ if (!ath12k_dp_umac_reset_in_progress(ab)) { ++ ret = ath12k_dp_srng_setup(ab, &dp->tcl_status_ring, HAL_TCL_STATUS, ++ 0, 0, DP_TCL_STATUS_RING_SIZE); ++ if (ret) { ++ ath12k_warn(ab, "failed to set up tcl_status ring :%d\n", ret); ++ goto err; ++ } + } + + for (i = 0; i < ab->hw_params->max_tx_ring; i++) { +@@ -879,6 +957,9 @@ static int ath12k_dp_srng_common_setup(s + goto err; + } + ++ if (ath12k_dp_umac_reset_in_progress(ab)) ++ goto skip_reo_setup; ++ + /* When hash based routing of rx packet is enabled, 32 entries to map + * the hash values to the ring will be configured. Each hash entry uses + * four bits to map to a particular ring. The ring mapping will be +@@ -896,6 +977,7 @@ static int ath12k_dp_srng_common_setup(s + + ath12k_hal_reo_hw_setup(ab, ring_hash_map); + ++skip_reo_setup: + #ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT + ret = ath12k_dp_srng_ppeds_setup(ab); + if (ret) { +@@ -955,13 +1037,15 @@ static int ath12k_dp_scatter_idle_link_d + if (num_scatter_buf > DP_IDLE_SCATTER_BUFS_MAX) + return -EINVAL; + +- for (i = 0; i < num_scatter_buf; i++) { +- slist[i].vaddr = dma_alloc_coherent(ab->dev, +- HAL_WBM_IDLE_SCATTER_BUF_SIZE_MAX, +- &slist[i].paddr, GFP_KERNEL); +- if (!slist[i].vaddr) { +- ret = -ENOMEM; +- goto err; ++ if (!ath12k_dp_umac_reset_in_progress(ab)) { ++ for (i = 0; i < num_scatter_buf; i++) { ++ slist[i].vaddr = dma_alloc_coherent(ab->dev, ++ HAL_WBM_IDLE_SCATTER_BUF_SIZE_MAX, ++ &slist[i].paddr, GFP_KERNEL); ++ if (!slist[i].vaddr) { ++ ret = -ENOMEM; ++ goto err; ++ } + } + } + +@@ -1143,10 +1227,12 @@ int ath12k_dp_link_desc_setup(struct ath + if (n_link_desc_bank > DP_LINK_DESC_BANKS_MAX) + return -EINVAL; + +- ret = ath12k_dp_link_desc_bank_alloc(ab, link_desc_banks, +- n_link_desc_bank, last_bank_sz); +- if (ret) +- return ret; ++ if (!ath12k_dp_umac_reset_in_progress(ab)) { ++ ret = ath12k_dp_link_desc_bank_alloc(ab, link_desc_banks, ++ n_link_desc_bank, last_bank_sz); ++ if (ret) ++ return ret; ++ } + + /* Setup link desc idle list for HW internal usage */ + entry_sz = ath12k_hal_srng_get_entrysize(ab, ring_type); +@@ -1522,6 +1608,61 @@ void ath12k_dp_vdev_tx_attach(struct ath + #endif + } + ++void ath12k_dp_umac_txrx_desc_cleanup(struct ath12k_base *ab) ++{ ++ struct ath12k_rx_desc_info *desc_info, *tmp; ++ struct ath12k_tx_desc_info *tx_desc_info, *tmp1; ++ struct ath12k_dp *dp = &ab->dp; ++ struct sk_buff *skb; ++ int i; ++ ++ /* RX Descriptor cleanup */ ++ spin_lock_bh(&dp->rx_desc_lock); ++ ++ list_for_each_entry_safe(desc_info, tmp, &dp->rx_desc_used_list, list) { ++ list_move_tail(&desc_info->list, &ab->dp.rx_desc_free_list); ++ skb = desc_info->skb; ++ desc_info->skb = NULL; ++ ++ if (!skb) ++ continue; ++ ++ dma_unmap_single(ab->dev, ATH12K_SKB_RXCB(skb)->paddr, ++ skb->len + skb_tailroom(skb), DMA_FROM_DEVICE); ++ dev_kfree_skb_any(skb); ++ } ++ ++ spin_unlock_bh(&dp->rx_desc_lock); ++ ++ /* TX Descriptor cleanup */ ++ for (i = 0; i < ATH12K_HW_MAX_QUEUES; i++) { ++ spin_lock_bh(&dp->tx_desc_lock[i]); ++ ++ list_for_each_entry_safe(tx_desc_info, tmp1, &dp->tx_desc_used_list[i], ++ list) { ++ list_move_tail(&tx_desc_info->list, &ab->dp.tx_desc_free_list); ++ skb = tx_desc_info->skb; ++ tx_desc_info->skb = NULL; ++ ++ if (!skb) ++ continue; ++ ++ dma_unmap_single(ab->dev, ATH12K_SKB_CB(skb)->paddr, ++ skb->len, DMA_TO_DEVICE); ++ ++ if (tx_desc_info->skb_ext_desc) { ++ dma_unmap_single(ab->dev, ATH12K_SKB_CB(skb)->paddr_ext_desc, ++ tx_desc_info->skb_ext_desc->len, DMA_TO_DEVICE); ++ dev_kfree_skb_any(tx_desc_info->skb_ext_desc); ++ } ++ ++ dev_kfree_skb_any(skb); ++ } ++ ++ spin_unlock_bh(&dp->tx_desc_lock[i]); ++ } ++} ++ + static void ath12k_dp_cc_cleanup(struct ath12k_base *ab) + { + struct ath12k_rx_desc_info *desc_info, *tmp; +@@ -1566,7 +1707,7 @@ static void ath12k_dp_cc_cleanup(struct + continue; + + kfree(dp->spt_info->rxbaddr[i]); +- } ++ } + + spin_unlock_bh(&dp->rx_desc_lock); + +@@ -2273,3 +2414,81 @@ fail_link_desc_cleanup: + + return ret; + } ++ ++int ath12k_dp_rxdma_ring_setup(struct ath12k_base *ab) ++{ ++ struct ath12k_dp *dp = &ab->dp; ++ int num_entries, ret; ++ struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring; ++ ++ ret = ath12k_dp_srng_setup(ab, ++ &dp->rx_refill_buf_ring.refill_buf_ring, ++ HAL_RXDMA_BUF, 0, 0, ++ DP_RXDMA_BUF_RING_SIZE); ++ ++ if (ret) { ++ ath12k_warn(ab, "failed to setup rx_refill_buf_ring\n"); ++ return ret; ++ } ++ ++ num_entries = rx_ring->refill_buf_ring.size / ++ ath12k_hal_srng_get_entrysize(ab, HAL_RXDMA_BUF); ++ ++ ath12k_dp_rx_bufs_replenish(ab, rx_ring, num_entries, ++ ab->hw_params->hal_params->rx_buf_rbm, ++ true); ++ return 0; ++} ++ ++void ath12k_umac_reset_handle_post_reset_start(struct ath12k_base *ab) ++{ ++ struct ath12k_dp *dp = &ab->dp; ++ struct ath12k_hw_group *ag = ab->ag; ++ struct ath12k_mlo_dp_umac_reset *mlo_umac_reset = &ag->mlo_umac_reset; ++ int i, n_link_desc, ret; ++ struct hal_srng *srng = NULL; ++ unsigned long end; ++ ++ ath12k_dp_srng_hw_ring_disable(ab); ++ ++ /* Busy wait for 2 ms to make sure the rings are ++ * in idle state before enabling it ++ */ ++ end = jiffies + msecs_to_jiffies(2); ++ while (time_before(jiffies, end)) ++ ; ++ ++ ret = ath12k_wbm_idle_ring_setup(ab, &n_link_desc); ++ ++ if (ret) ++ ath12k_warn(ab, "failed to setup wbm_idle_ring: %d\n", ret); ++ ++ srng = &ab->hal.srng_list[dp->wbm_idle_ring.ring_id]; ++ ++ ret = ath12k_dp_link_desc_setup(ab, dp->link_desc_banks, ++ HAL_WBM_IDLE_LINK, srng, n_link_desc); ++ if (ret) ++ ath12k_warn(ab, "failed to setup link desc: %d\n", ret); ++ ++ ath12k_dp_srng_common_setup(ab); ++ ath12k_dp_umac_txrx_desc_cleanup(ab); ++ ++ ath12k_dp_rxdma_ring_setup(ab); ++ ++ for (i = 0; i < DP_REO_DST_RING_MAX; i++) { ++ ret = ath12k_dp_srng_setup(ab, &dp->reo_dst_ring[i], ++ HAL_REO_DST, i, 0, ++ DP_REO_DST_RING_SIZE); ++ if (ret) ++ ath12k_warn(ab, "failed to setup reo_dst_ring\n"); ++ } ++ ++ ath12k_dp_rx_reo_cmd_list_cleanup(ab); ++ ++ ath12k_dp_tid_cleanup(ab); ++ ++ atomic_inc(&mlo_umac_reset->response_chip); ++ ath12k_umac_reset_notify_target_sync_and_send(ab, ATH12K_UMAC_RESET_TX_CMD_POST_RESET_START_DONE); ++ ++ return; ++} +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -538,6 +538,8 @@ enum htt_h2t_msg_type { + HTT_H2T_MSG_TYPE_SAWF_DEF_Q_UNMAP_REQ = 0x1d, + HTT_H2T_MSG_TYPE_SAWF_DEF_Q_MAP_REPORT_REQ = 0x1e, + HTT_H2T_MSG_TYPE_STREAMING_STATS_REQ = 0x20, ++ HTT_H2T_MSG_TYPE_UMAC_RESET_PREREQUISITE_SETUP = 0x21, ++ HTT_H2T_MSG_TYPE_UMAC_RESET_START_PRE_RESET = 0x22, + }; + + #define HTT_VER_REQ_INFO_MSG_ID GENMASK(7, 0) +@@ -2357,6 +2359,211 @@ struct ath12k_dp_htt_rxdma_ppe_cfg_param + u8 ip_frag_override; + }; + ++#define HTT_ATH12K_UMAC_RESET_T2H_DO_PRE_RESET BIT(0) ++#define HTT_ATH12K_UMAC_RESET_T2H_DO_POST_RESET_START BIT(1) ++#define HTT_ATH12K_UMAC_RESET_T2H_DO_POST_RESET_COMPLETE BIT(2) ++#define HTT_ATH12K_UMAC_RESET_T2H_INIT_UMAC_RECOVERY BIT(3) ++#define HTT_ATH12K_UMAC_RESET_T2H_INIT_TARGET_RECOVERY_SYNC_USING_UMAC BIT(4) ++ ++enum dp_umac_reset_recover_action { ++ ATH12K_UMAC_RESET_RX_EVENT_NONE, ++ ATH12K_UMAC_RESET_INIT_UMAC_RECOVERY, ++ ATH12K_UMAC_RESET_INIT_TARGET_RECOVERY_SYNC_USING_UMAC, ++ ATH12K_UMAC_RESET_DO_PRE_RESET, ++ ATH12K_UMAC_RESET_DO_POST_RESET_START, ++ ATH12K_UMAC_RESET_DO_POST_RESET_COMPLETE, ++}; ++ ++enum dp_umac_reset_tx_cmd { ++ ATH12K_UMAC_RESET_TX_CMD_TRIGGER_DONE, ++ ATH12K_UMAC_RESET_TX_CMD_PRE_RESET_DONE, ++ ATH12K_UMAC_RESET_TX_CMD_POST_RESET_START_DONE, ++ ATH12K_UMAC_RESET_TX_CMD_POST_RESET_COMPLETE_DONE, ++}; ++ ++#define ATH12K_HTT_UMAC_RESET_MSG_SHMEM_PRE_RESET_DONE_SET BIT(0) ++#define ATH12K_HTT_UMAC_RESET_MSG_SHMEM_POST_RESET_START_DONE_SET BIT(1) ++#define ATH12K_HTT_UMAC_RESET_MSG_SHMEM_POST_RESET_COMPLETE_DONE BIT(2) ++ ++struct ath12k_dp_htt_umac_reset_recovery_msg_shmem_t { ++ u32 magic_num; ++ union { ++ /* ++ * BIT [0] :- T2H msg to do pre-reset ++ * BIT [1] :- T2H msg to do post-reset start ++ * BIT [2] :- T2H msg to do post-reset complete ++ * BIT [3] :- T2H msg to indicate to Host that ++ * a trigger request for MLO UMAC Recovery ++ * is received for UMAC hang. ++ * BIT [4] :- T2H msg to indicate to Host that ++ * a trigger request for MLO UMAC Recovery ++ * is received for Mode-1 Target Recovery. ++ * BIT [31 : 5] :- reserved ++ */ ++ u32 t2h_msg; ++ u32 recovery_action; ++ }; ++ union { ++ /* ++ * BIT [0] :- H2T msg to send pre-reset done ++ * BIT [1] :- H2T msg to send post-reset start done ++ * BIT [2] :- H2T msg to send post-reset complete done ++ * BIT [3] :- H2T msg to start pre-reset. This is deprecated. ++ * BIT [31 : 4] :- reserved ++ */ ++ u32 h2t_msg; ++ u32 recovery_action_done; ++ }; ++}; ++ ++struct ath12k_umac_reset_ts { ++ u64 trigger_start; ++ u64 trigger_done; ++ u64 pre_reset_start; ++ u64 pre_reset_done; ++ u64 post_reset_start; ++ u64 post_reset_done; ++ u64 post_reset_complete_start; ++ u64 post_reset_complete_done; ++}; ++ ++struct ath12k_dp_umac_reset { ++ dma_addr_t shmem_paddr_unaligned; ++ void *shmem_vaddr_unaligned; ++ dma_addr_t shmem_paddr_aligned; ++ struct ath12k_dp_htt_umac_reset_recovery_msg_shmem_t *shmem_vaddr_aligned; ++ size_t shmem_size; ++ uint32_t magic_num; ++ int intr_offset; ++ struct tasklet_struct intr_tq; ++ int irq_num; ++ struct ath12k_umac_reset_ts ts; ++}; ++ ++struct ath12k_htt_umac_reset_setup_cmd_params { ++ uint32_t msi_data; ++ uint32_t addr_lo; ++ uint32_t addr_hi; ++}; ++ ++struct htt_h2t_paddr_size { ++ u32 size; ++ u32 addr_lo; ++ u32 addr_hi; ++}; ++ ++#define HTT_H2T_MSG_TYPE_SET GENMASK(7, 0) ++#define HTT_H2T_MSG_METHOD GENMASK(11, 8) ++#define HTT_T2H_MSG_METHOD GENMASK(15, 12) ++ ++#define ATH12K_DP_UMAC_RESET_SHMEM_MAGIC_NUM 0xDEADBEEF ++#define ATH12K_DP_UMAC_RESET_SHMEM_ALIGN 8 ++ ++/** ++ * @brief HTT_H2T_MSG_TYPE_UMAC_RESET_PREREQUISITE_SETUP message ++ * ++ * @details ++ * The HTT_H2T_MSG_TYPE_UMAC_HANG_RECOVERY_PREREQUISITE_SETUP message is sent ++ * by the host to provide prerequisite info to target for the UMAC hang ++ * recovery feature. ++ * The info sent in this H2T message are T2H message method, H2T message ++ * method, T2H MSI interrupt number and physical start address, size of ++ * the shared memory (refers to the shared memory dedicated for messaging ++ * between host and target when the DUT is in UMAC hang recovery mode). ++ * This H2T message is expected to be only sent if the WMI service bit ++ * WMI_SERVICE_UMAC_HANG_RECOVERY_SUPPORT was firstly indicated by the target. ++ * ++ * |31 16|15 12|11 8|7 0| ++ * |-------------------------------+--------------+--------------+------------| ++ * | reserved |h2t msg method|t2h msg method| msg_type | ++ * |--------------------------------------------------------------------------| ++ * | t2h msi interrupt number | ++ * |--------------------------------------------------------------------------| ++ * | shared memory area size | ++ * |--------------------------------------------------------------------------| ++ * | shared memory area physical address low | ++ * |--------------------------------------------------------------------------| ++ * | shared memory area physical address high | ++ * |--------------------------------------------------------------------------| ++ * The message is interpreted as follows: ++ * dword0 - b'0:7 - msg_type ++ * (HTT_H2T_MSG_TYPE_UMAC_RESET_PREREQUISITE_SETUP) ++ * b'8:11 - t2h_msg_method: indicates method to be used for ++ * T2H communication in UMAC hang recovery mode. ++ * Value zero indicates MSI interrupt (default method). ++ * Refer to htt_umac_hang_recovery_msg_method enum. ++ * b'12:15 - h2t_msg_method: indicates method to be used for ++ * H2T communication in UMAC hang recovery mode. ++ * Value zero indicates polling by target for this h2t msg ++ * during UMAC hang recovery mode. ++ * Refer to htt_umac_hang_recovery_msg_method enum. ++ * b'16:31 - reserved. ++ * dword1 - b'0:31 - t2h_msi_data: MSI data to be used for ++ * T2H communication in UMAC hang recovery mode. ++ * dword2 - b'0:31 - size: size of shared memory dedicated for messaging ++ * only when in UMAC hang recovery mode. ++ * This refers to size in bytes. ++ * dword3 - b'0:31 - physical_address_lo: lower 32 bit physical address ++ * of the shared memory dedicated for messaging only when ++ * in UMAC hang recovery mode. ++ * dword4 - b'0:31 - physical_address_hi: higher 32 bit physical address ++ * of the shared memory dedicated for messaging only when ++ * in UMAC hang recovery mode. ++ */ ++ ++struct htt_dp_umac_reset_setup_req_cmd { ++ u32 msg_info; ++ u32 msi_data; ++ struct htt_h2t_paddr_size msg_shared_mem; ++}__packed; ++ ++/** ++ * @brief HTT_H2T_MSG_TYPE_UMAC_RESET_START_PRE_RESET message ++ * ++ * @details ++ * The HTT_H2T_MSG_TYPE_UMAC_HANG_RECOVERY_SOC_START_PRE_RESET is a SOC level ++ * HTT message sent by the host to indicate that the target needs to start the ++ * UMAC hang recovery feature from the point of pre-reset routine. ++ * The purpose of this H2T message is to have host synchronize and trigger ++ * UMAC recovery across all targets. ++ * The info sent in this H2T message is the flag to indicate whether the ++ * target needs to execute UMAC-recovery in context of the Initiator or ++ * Non-Initiator. ++ * This H2T message is expected to be sent as response to the ++ * initiate_umac_recovery indication from the Initiator target attached to ++ * this same host. ++ * This H2T message is expected to be only sent if the WMI service bit ++ * WMI_SERVICE_UMAC_HANG_RECOVERY_SUPPORT was firstly indicated by the target ++ * and HTT_H2T_MSG_TYPE_UMAC_HANG_RECOVERY_PREREQUISITE_SETUP was sent ++ * beforehand. ++ * ++ * |31 10|9|8|7 0| ++ * |-----------------------------------------------------------| ++ * | reserved |U|I| msg_type | ++ * |-----------------------------------------------------------| ++ * Where: ++ * I = is_initiator ++ * U = is_umac_hang ++ * ++ * The message is interpreted as follows: ++ * dword0 - b'0:7 - msg_type ++ * (HTT_H2T_MSG_TYPE_UMAC_RESET_START_PRE_RESET) ++ * b'8 - is_initiator: indicates whether the target needs to ++ * execute the UMAC-recovery in context of the Initiator or ++ * Non-Initiator. ++ * The value zero indicates this target is Non-Initiator. ++ * b'9 - is_umac_hang: indicates whether MLO UMAC recovery ++ * executed in context of UMAC hang or Target recovery. ++ * b'10:31 - reserved. ++ */ ++struct h2t_umac_hang_recovery_start_pre_reset { ++ u8 hdr; ++} __packed; ++ ++#define HTT_H2T_UMAC_RESET_MSG_TYPE GENMASK(7, 0) ++#define HTT_H2T_UMAC_RESET_IS_INITIATOR_SET BIT(8) ++#define HTT_H2T_UMAC_RESET_IS_TARGET_RECOVERY_SET BIT(9) ++ + int ath12k_dp_service_srng(struct ath12k_base *ab, + struct ath12k_ext_irq_grp *irq_grp, + int budget); +@@ -2406,4 +2613,9 @@ int ath12k_dp_cc_ppeds_desc_init(struct + int ath12k_dp_cc_ppeds_desc_cleanup(struct ath12k_base *ab); + void ath12k_dp_ppeds_tx_cmem_init(struct ath12k_base *ab, struct ath12k_dp *dp); + #endif ++void ath12k_umac_reset_handle_post_reset_start(struct ath12k_base *ab); ++void ath12k_umac_reset_notify_target_sync_and_send(struct ath12k_base *ab, ++ enum dp_umac_reset_tx_cmd tx_event); ++void ath12k_dp_reset_interrupt_mask(struct ath12k_base *ab); ++void ath12k_dp_restore_interrupt_mask(struct ath12k_base *ab); + #endif +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -572,6 +572,28 @@ static void ath12k_peer_rx_tid_qref_rese + qref->info1 = u32_encode_bits(0, BUFFER_ADDR_INFO1_ADDR); + } + ++void ath12k_dp_tid_cleanup(struct ath12k_base *ab) ++{ ++ struct ath12k_peer *peer; ++ struct ath12k_dp_rx_tid *rx_tid; ++ int tid; ++ void *vaddr; ++ u32 *addr_aligned; ++ ++ spin_lock_bh(&ab->base_lock); ++ list_for_each_entry(peer, &ab->peers, list) { ++ for (tid = 0; tid <= IEEE80211_NUM_TIDS; tid++) { ++ rx_tid = &peer->rx_tid[tid]; ++ if (rx_tid->active) { ++ vaddr = rx_tid->vaddr; ++ addr_aligned = PTR_ALIGN(vaddr, HAL_LINK_DESC_ALIGN); ++ ath12k_dp_reset_rx_reo_tid_q(addr_aligned, rx_tid->ba_win_sz, tid); ++ } ++ } ++ } ++ spin_unlock_bh(&ab->base_lock); ++} ++ + static int ath12k_dp_reo_cmd_send(struct ath12k_base *ab, struct ath12k_dp_rx_tid *rx_tid, + enum hal_reo_cmd_type type, + struct ath12k_hal_reo_cmd *cmd, +@@ -583,7 +605,8 @@ static int ath12k_dp_reo_cmd_send(struct + struct hal_srng *cmd_ring; + int cmd_num; + +- if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags)) ++ if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags) || ++ test_bit(ATH12K_FLAG_UMAC_PRERESET_START, &ab->dev_flags)) + return -ESHUTDOWN; + + cmd_ring = &ab->hal.srng_list[dp->reo_cmd_ring.ring_id]; +@@ -988,7 +1011,7 @@ void ath12k_dp_rx_peer_tid_cleanup(struc + } + } + +-static int ath12k_peer_rx_tid_reo_update(struct ath12k *ar, ++static int ath12k_peer_rx_tid_reo_update(struct ath12k_base *ab, + struct ath12k_peer *peer, + struct ath12k_dp_rx_tid *rx_tid, + u32 ba_win_sz, u16 ssn, +@@ -1008,11 +1031,11 @@ static int ath12k_peer_rx_tid_reo_update + cmd.upd2 = u32_encode_bits(ssn, HAL_REO_CMD_UPD2_SSN); + } + +- ret = ath12k_dp_reo_cmd_send(ar->ab, rx_tid, ++ ret = ath12k_dp_reo_cmd_send(ab, rx_tid, + HAL_REO_CMD_UPDATE_RX_QUEUE, &cmd, + NULL); + if (ret) { +- ath12k_warn(ar->ab, "failed to update rx tid queue, tid %d (%d)\n", ++ ath12k_warn(ab, "failed to update rx tid queue, tid %d (%d)\n", + rx_tid->tid, ret); + return ret; + } +@@ -1022,6 +1045,68 @@ static int ath12k_peer_rx_tid_reo_update + return 0; + } + ++void ath12k_dp_peer_reo_tid_setup(struct ath12k_base *ab, ++ struct ath12k_link_sta *arsta) ++{ ++ struct ath12k_dp_rx_tid *rx_tid; ++ struct ath12k_peer *peer; ++ u8 tid; ++ int ret; ++ ++ spin_lock_bh(&ab->base_lock); ++ peer = ath12k_peer_find_by_addr(ab, arsta->addr); ++ if (peer) { ++ for (tid = 0; tid <= IEEE80211_NUM_TIDS; tid++) { ++ rx_tid = &peer->rx_tid[tid]; ++ if (rx_tid->active) { ++ ret = ath12k_peer_rx_tid_reo_update(ab, peer, rx_tid, ++ rx_tid->ba_win_sz, 0, false); ++ if (ret) { ++ ath12k_warn(ab, "failed to update reo for peer %pM rx tid %d\n", ++ peer->addr, tid); ++ } ++ } ++ } ++ } ++ spin_unlock_bh(&ab->base_lock); ++} ++ ++void ath12k_dp_tid_setup(void *data, struct ieee80211_sta *sta) ++{ ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_base *ab = data; ++ struct ath12k_link_sta *arsta; ++ struct ath12k_link_vif *arvif; ++ u8 link_id; ++ u16 links_map; ++ ++ if (sta->mlo) ++ return; ++ ++ links_map = ahsta->links_map; ++ for_each_set_bit(link_id, &links_map, IEEE80211_MLD_MAX_NUM_LINKS) { ++ arsta = ahsta->link[link_id]; ++ if (!arsta) ++ continue; ++ arvif = arsta->arvif; ++ if (arvif->ab == ab) ++ ath12k_dp_peer_reo_tid_setup(ab, arsta); ++ } ++} ++ ++void ath12k_dp_peer_tid_setup(struct ath12k_base *ab) ++{ ++ struct ath12k *ar; ++ int i; ++ ++ for (i = 0; i < ab->num_radios; i++) { ++ ar = ab->pdevs[i].ar; ++ ieee80211_iterate_stations_atomic(ar->ah->hw, ++ ath12k_dp_tid_setup, ++ ab); ++ } ++} ++ + int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, u8 tid, u32 ba_win_sz, u16 ssn, + enum hal_pn_type pn_type, struct ath12k_peer *peer) + { +@@ -1049,7 +1134,7 @@ int ath12k_dp_rx_peer_tid_setup(struct a + /* Update the tid queue if it is already setup */ + if (rx_tid->active) { + paddr = rx_tid->paddr; +- ret = ath12k_peer_rx_tid_reo_update(ar, peer, rx_tid, ++ ret = ath12k_peer_rx_tid_reo_update(ab, peer, rx_tid, + ba_win_sz, ssn, true); + if (ret) { + ath12k_warn(ab, "failed to update reo for peer %pM rx tid %d\n", +@@ -1195,7 +1280,7 @@ int ath12k_dp_rx_ampdu_stop(struct ath12 + return 0; + } + +- ret = ath12k_peer_rx_tid_reo_update(ar, peer, peer->rx_tid, 1, 0, false); ++ ret = ath12k_peer_rx_tid_reo_update(ab, peer, peer->rx_tid, 1, 0, false); + spin_unlock_bh(&ab->base_lock); + if (ret) { + ath12k_warn(ab, "failed to update reo for rx tid %d: %d\n", +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -437,7 +437,8 @@ int ath12k_dp_tx(struct ath12k *ar, stru + bool is_diff_encap = false; + u8 align_pad, htt_meta_size = 0; + +- if (unlikely(test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))) ++ if (unlikely(test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags)) || ++ unlikely(test_bit(ATH12K_FLAG_UMAC_PRERESET_START, &ab->dev_flags))) + return -ESHUTDOWN; + + if (unlikely(!(skb_cb->flags & ATH12K_SKB_HW_80211_ENCAP) && +--- a/drivers/net/wireless/ath/ath12k/hif.h ++++ b/drivers/net/wireless/ath/ath12k/hif.h +@@ -43,6 +43,9 @@ struct ath12k_hif_ops { + void (*ppeds_irq_enable)(struct ath12k_base *ab, enum ppeds_irq_type type); + void (*ppeds_irq_disable)(struct ath12k_base *ab, enum ppeds_irq_type type); + #endif ++ int (*dp_umac_reset_irq_config)(struct ath12k_base *ab); ++ void (*dp_umac_reset_enable_irq)(struct ath12k_base *ab); ++ void (*dp_umac_reset_free_irq)(struct ath12k_base *ab); + }; + + #ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT +@@ -228,4 +231,27 @@ static inline void ath12k_hif_power_down + ab->hif.ops->power_down(ab); + } + ++static inline int ath12k_hif_dp_umac_reset_irq_config(struct ath12k_base *ab) ++{ ++ if (ab->hif.ops->dp_umac_reset_irq_config) ++ return ab->hif.ops->dp_umac_reset_irq_config(ab); ++ ++ return 0; ++} ++ ++static inline void ath12k_hif_dp_umac_reset_enable_irq(struct ath12k_base *ab) ++{ ++ if (ab->hif.ops->dp_umac_reset_enable_irq) ++ return ab->hif.ops->dp_umac_reset_enable_irq(ab); ++ ++ return; ++} ++ ++static inline void ath12k_hif_dp_umac_reset_free_irq(struct ath12k_base *ab) ++{ ++ if (ab->hif.ops->dp_umac_reset_free_irq) ++ return ab->hif.ops->dp_umac_reset_free_irq(ab); ++ ++ return; ++} + #endif /* ATH12K_HIF_H */ +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -161,6 +161,8 @@ static const struct ath12k_hw_ops ipq533 + #define ATH12K_PPE2TCL_RING_MASK_0 0x1 + #define ATH12K_REO2PPE_RING_MASK_0 0x1 + #define ATH12K_PPE_WBM2SW_RELEASE_RING_MASK_0 0x1 ++#define ATH12K_PPE_WBM2SW_RELEASE_RING_MASK_0 0x1 ++#define ATH12K_UMAC_RESET_INTR_MASK_0 0x1 + + /* Target firmware's Copy Engine configuration. */ + static const struct ce_pipe_config ath12k_target_ce_config_wlan_qcn9274[] = { +@@ -790,7 +792,7 @@ static const struct service_to_pipe ath1 + }, + }; + +-static const struct ath12k_hw_ring_mask ath12k_hw_ring_mask_qcn9274 = { ++static struct ath12k_hw_ring_mask ath12k_hw_ring_mask_qcn9274 = { + .tx = { + ATH12K_TX_RING_MASK_0, + ATH12K_TX_RING_MASK_1, +@@ -859,9 +861,13 @@ static const struct ath12k_hw_ring_mask + 0, 0, ATH12K_PPE_WBM2SW_RELEASE_RING_MASK_0 + }, + #endif ++ .umac_dp_reset = { ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ ATH12K_UMAC_RESET_INTR_MASK_0 ++ }, + }; + +-static const struct ath12k_hw_ring_mask ath12k_hw_ring_mask_ipq5332 = { ++static struct ath12k_hw_ring_mask ath12k_hw_ring_mask_ipq5332 = { + .tx = { + ATH12K_TX_RING_MASK_0, + ATH12K_TX_RING_MASK_1, +@@ -909,7 +915,7 @@ static const struct ath12k_hw_ring_mask + }, + }; + +-static const struct ath12k_hw_ring_mask ath12k_hw_ring_mask_wcn7850 = { ++static struct ath12k_hw_ring_mask ath12k_hw_ring_mask_wcn7850 = { + .tx = { + ATH12K_TX_RING_MASK_0, + ATH12K_TX_RING_MASK_2, +@@ -1422,7 +1428,7 @@ static const struct ath12k_hw_hal_params + HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW4_EN, + }; + +-static const struct ath12k_hw_params ath12k_hw_params[] = { ++static struct ath12k_hw_params ath12k_hw_params[] = { + { + .name = "qcn9274 hw1.0", + .hw_rev = ATH12K_HW_QCN9274_HW10, +@@ -1499,6 +1505,7 @@ static const struct ath12k_hw_params ath + .compact_rx_tlv = true, + .send_platform_model = false, + .en_fwlog = true, ++ .support_umac_reset = false, + }, + { + .name = "wcn7850 hw2.0", +@@ -1568,6 +1575,7 @@ static const struct ath12k_hw_params ath + .compact_rx_tlv = false, + .send_platform_model = false, + .en_fwlog = true, ++ .support_umac_reset = false, + }, + { + .name = "qcn9274 hw2.0", +@@ -1645,6 +1653,7 @@ static const struct ath12k_hw_params ath + .compact_rx_tlv = true, + .send_platform_model = false, + .en_fwlog = true, ++ .support_umac_reset = true, + }, + { + .name = "ipq5332 hw1.0", +@@ -1725,9 +1734,69 @@ static const struct ath12k_hw_params ath + .pmm_remap = &ath12k_pmm_ipq5332, + .send_platform_model = true, + .en_fwlog = true, ++ .support_umac_reset = false, + }, + }; + ++void ath12k_dp_reset_interrupt_mask(struct ath12k_base *ab) ++{ ++ struct ath12k_hw_ring_mask *ring_mask = ab->hw_params->ring_mask; ++ struct ath12k_hw_group *ag = ab->ag; ++ struct ath12k_mlo_dp_umac_reset *umac_reset = &ag->mlo_umac_reset; ++ int i; ++ ++ if (ag->mlo_umac_reset.is_intr_bkup) ++ return; ++ ++ for (i = 0; i < ATH12K_EXT_IRQ_GRP_NUM_MAX; i++) { ++ umac_reset->intr_bkup.tx[i] = ring_mask->tx[i]; ++ ++ umac_reset->intr_bkup.rx_mon_dest[i] = ring_mask->rx_mon_dest[i]; ++ umac_reset->intr_bkup.rx[i] = ring_mask->rx[i]; ++ umac_reset->intr_bkup.rx_err[i] = ring_mask->rx_err[i]; ++ umac_reset->intr_bkup.rx_wbm_rel[i] = ring_mask->rx_wbm_rel[i]; ++ umac_reset->intr_bkup.reo_status[i] = ring_mask->reo_status[i]; ++ umac_reset->intr_bkup.host2rxdma[i] = ring_mask->host2rxdma[i]; ++ umac_reset->intr_bkup.tx_mon_dest[i] = ring_mask->tx_mon_dest[i]; ++ ++ ring_mask->tx[i] = 0; ++ ring_mask->rx_mon_dest[i] = 0; ++ ring_mask->rx[i] = 0; ++ ring_mask->rx_err[i] = 0; ++ ring_mask->rx_wbm_rel[i] = 0; ++ ring_mask->reo_status[i] = 0; ++ ring_mask->host2rxdma[i] = 0; ++ ring_mask->tx_mon_dest[i] = 0; ++ } ++ ++ ag->mlo_umac_reset.is_intr_bkup = true; ++} ++ ++void ath12k_dp_restore_interrupt_mask(struct ath12k_base *ab) ++{ ++ struct ath12k_hw_ring_mask *ring_mask = ab->hw_params->ring_mask; ++ struct ath12k_hw_group *ag = ab->ag; ++ struct ath12k_mlo_dp_umac_reset *umac_reset = &ag->mlo_umac_reset; ++ int i; ++ ++ if (!ag->mlo_umac_reset.is_intr_bkup) ++ return; ++ ++ for (i = 0; i < ATH12K_EXT_IRQ_GRP_NUM_MAX; i++) { ++ ring_mask->tx[i] = umac_reset->intr_bkup.tx[i]; ++ ring_mask->rx_mon_dest[i] = umac_reset->intr_bkup.rx_mon_dest[i]; ++ ring_mask->rx[i] = umac_reset->intr_bkup.rx[i]; ++ ring_mask->rx_err[i] = umac_reset->intr_bkup.rx_err[i]; ++ ring_mask->rx_wbm_rel[i] = umac_reset->intr_bkup.rx_wbm_rel[i]; ++ ring_mask->reo_status[i] = umac_reset->intr_bkup.reo_status[i]; ++ ring_mask->host2rxdma[i] = umac_reset->intr_bkup.host2rxdma[i]; ++ ring_mask->tx_mon_dest[i] = umac_reset->intr_bkup.tx_mon_dest[i]; ++ } ++ ++ ag->mlo_umac_reset.is_intr_bkup = false; ++ ++} ++ + int ath12k_hw_init(struct ath12k_base *ab) + { + const struct ath12k_hw_params *hw_params = NULL; +--- a/drivers/net/wireless/ath/ath12k/hw.h ++++ b/drivers/net/wireless/ath/ath12k/hw.h +@@ -117,8 +117,8 @@ enum ath12k_bus { + ATH12K_BUS_AHB, + }; + +-/* Regular 12 Host DP interrupts + 3 PPEDS interrupts */ +-#define ATH12K_EXT_IRQ_DP_NUM_VECTORS 15 ++/* Regular 12 Host DP interrupts + 3 PPEDS interrupts + 1 DP UMAC RESET interrupt*/ ++#define ATH12K_EXT_IRQ_DP_NUM_VECTORS 16 + #define ATH12K_EXT_IRQ_GRP_NUM_MAX 12 + struct hal_rx_desc; + struct hal_tcl_data_cmd; +@@ -139,6 +139,7 @@ struct ath12k_hw_ring_mask { + #ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT + u8 wbm2sw6_ppeds_tx_cmpln[ATH12K_EXT_IRQ_DP_NUM_VECTORS]; + #endif ++ u8 umac_dp_reset[ATH12K_EXT_IRQ_DP_NUM_VECTORS]; + }; + + struct ath12k_hw_hal_params { +@@ -163,7 +164,7 @@ struct ath12k_hw_params { + bool internal_sleep_clock; + + const struct ath12k_hw_ops *hw_ops; +- const struct ath12k_hw_ring_mask *ring_mask; ++ struct ath12k_hw_ring_mask *ring_mask; + const struct ath12k_hw_regs *regs; + + const struct ce_attr *host_ce_config; +@@ -231,6 +232,7 @@ struct ath12k_hw_params { + const struct cmem_remap *cmem_remap; + bool compact_rx_tlv; + const struct pmm_remap *pmm_remap; ++ bool support_umac_reset; + }; + + /* BRINGUP: move to dp.h */ +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -95,7 +95,7 @@ static const struct ath12k_msi_config at + .users = (struct ath12k_msi_user[]) { + { .name = "MHI", .num_vectors = 3, .base_vector = 0 }, + { .name = "CE", .num_vectors = 5, .base_vector = 3 }, +- { .name = "DP", .num_vectors = 15, .base_vector = 8 }, ++ { .name = "DP", .num_vectors = 16, .base_vector = 8 }, + }, + }, + }; +@@ -742,6 +742,70 @@ static int ath12k_pci_config_irq(struct + return 0; + } + ++static void ath12k_umac_reset_tasklet_handler(struct tasklet_struct *t) ++{ ++ struct ath12k_dp_umac_reset *umac_reset = from_tasklet(umac_reset, t, intr_tq); ++ struct ath12k_base *ab = container_of(umac_reset, struct ath12k_base, dp_umac_reset); ++ ++ ath12k_dp_umac_reset_handle(ab); ++ enable_irq(umac_reset->irq_num); ++} ++ ++static irqreturn_t ath12k_dp_umac_reset_interrupt_handler(int irq, void *arg) ++{ ++ struct ath12k_base *ab = arg; ++ struct ath12k_dp_umac_reset *umac_reset = &ab->dp_umac_reset; ++ ++ disable_irq_nosync(umac_reset->irq_num); ++ tasklet_schedule(&umac_reset->intr_tq); ++ return IRQ_HANDLED; ++} ++ ++static void ath12k_dp_umac_reset_enable_irq(struct ath12k_base *ab) ++{ ++ struct ath12k_dp_umac_reset *umac_reset = &ab->dp_umac_reset; ++ ++ enable_irq(umac_reset->irq_num); ++} ++ ++static int ath12k_dp_umac_pci_config_irq(struct ath12k_base *ab) ++{ ++ u32 msi_data_start, msi_data_count, msi_irq_start; ++ unsigned int msi_data; ++ int irq, ret; ++ struct ath12k_dp_umac_reset *umac_reset = &ab->dp_umac_reset; ++ ++ ret = ath12k_pci_get_user_msi_assignment(ab, ++ "DP", &msi_data_count, ++ &msi_data_start, &msi_irq_start); ++ if (ret) ++ return ret; ++ ++ msi_data = (umac_reset->intr_offset % msi_data_count) + msi_irq_start; ++ irq = ath12k_pci_get_msi_irq(ab->dev, msi_data); ++ umac_reset->irq_num = irq; ++ tasklet_setup(&umac_reset->intr_tq, ath12k_umac_reset_tasklet_handler); ++ ++ ret = request_irq(irq, ath12k_dp_umac_reset_interrupt_handler, ++ IRQF_NO_SUSPEND, "umac_dp_reset", ab); ++ if (ret) { ++ ath12k_err(ab, "failed to request irq for umac dp reset %d\n", ret); ++ return ret; ++ } ++ ++ disable_irq_nosync(umac_reset->irq_num); ++ ++ return 0; ++} ++ ++static void ath12k_dp_umac_reset_free_irq(struct ath12k_base *ab) ++{ ++ struct ath12k_dp_umac_reset *umac_reset = &ab->dp_umac_reset; ++ ++ disable_irq_nosync(umac_reset->irq_num); ++ free_irq(umac_reset->irq_num, ab); ++} ++ + static void ath12k_pci_init_qmi_ce_config(struct ath12k_base *ab) + { + struct ath12k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg; +@@ -1373,6 +1437,9 @@ static const struct ath12k_hif_ops ath12 + .ppeds_irq_enable = ath12k_pci_ppeds_irq_enable, + .ppeds_irq_disable = ath12k_pci_ppeds_irq_disable, + #endif ++ .dp_umac_reset_irq_config = ath12k_dp_umac_pci_config_irq, ++ .dp_umac_reset_enable_irq = ath12k_dp_umac_reset_enable_irq, ++ .dp_umac_reset_free_irq = ath12k_dp_umac_reset_free_irq, + }; + + static int ath12k_pci_probe(struct pci_dev *pdev, +--- /dev/null ++++ b/drivers/net/wireless/ath/ath12k/umac_reset.c +@@ -0,0 +1,468 @@ ++/* SPDX-License-Identifier: BSD-3-Clause-Clear */ ++/* ++ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "core.h" ++#include "coredump.h" ++#include "dp_tx.h" ++#include "dp_rx.h" ++#include "debug.h" ++#include "hif.h" ++ ++int ath12k_htt_umac_reset_msg_send(struct ath12k_base *ab, ++ struct ath12k_htt_umac_reset_setup_cmd_params *params) ++{ ++ struct sk_buff *skb; ++ struct htt_dp_umac_reset_setup_req_cmd *cmd; ++ int ret; ++ int len = sizeof(*cmd); ++ ++ skb = ath12k_htc_alloc_skb(ab, len); ++ if (!skb) ++ return -ENOMEM; ++ ++ skb_put(skb, len); ++ cmd = (struct htt_dp_umac_reset_setup_req_cmd *)skb->data; ++ cmd->msg_info = u32_encode_bits(HTT_H2T_MSG_TYPE_UMAC_RESET_PREREQUISITE_SETUP, ++ HTT_H2T_MSG_TYPE_SET); ++ cmd->msg_info |= u32_encode_bits(0, HTT_H2T_MSG_METHOD); ++ cmd->msg_info |= u32_encode_bits(0, HTT_T2H_MSG_METHOD); ++ cmd->msi_data = params->msi_data; ++ cmd->msg_shared_mem.size = sizeof(struct htt_h2t_paddr_size); ++ cmd->msg_shared_mem.addr_lo = params->addr_lo; ++ cmd->msg_shared_mem.addr_hi = params->addr_hi; ++ ++ ++ ret = ath12k_htc_send(&ab->htc, ab->dp.eid, skb); ++ ++ if (ret) { ++ ath12k_warn(ab, "DP UMAC INIT msg send failed ret:%d\n", ret); ++ goto err_free; ++ } ++ ++ ath12k_dbg(ab, ATH12K_DBG_DP_UMAC_RESET, "DP UMAC INIT msg sent from host\n"); ++ return 0; ++ ++err_free: ++ dev_kfree_skb_any(skb); ++ return ret; ++} ++ ++int ath12k_htt_umac_reset_send_start_pre_reset_cmd(struct ath12k_base *ab, int is_initiator, ++ int is_target_recovery) ++{ ++ struct sk_buff *skb; ++ struct h2t_umac_hang_recovery_start_pre_reset *cmd; ++ int ret; ++ int len = sizeof(*cmd); ++ ++ skb = ath12k_htc_alloc_skb(ab, len); ++ if (!skb) ++ return -ENOMEM; ++ ++ skb_put(skb, len); ++ cmd = (struct h2t_umac_hang_recovery_start_pre_reset*)skb->data; ++ memset(cmd, 0, sizeof(*cmd)); ++ cmd->hdr = u32_encode_bits(HTT_H2T_MSG_TYPE_UMAC_RESET_START_PRE_RESET, ++ HTT_H2T_UMAC_RESET_MSG_TYPE); ++ cmd->hdr |= u32_encode_bits(is_initiator, HTT_H2T_UMAC_RESET_IS_INITIATOR_SET); ++ cmd->hdr |= u32_encode_bits(is_target_recovery, HTT_H2T_UMAC_RESET_IS_TARGET_RECOVERY_SET); ++ ++ ret = ath12k_htc_send(&ab->htc, ab->dp.eid, skb); ++ if (ret) { ++ ath12k_warn(ab, "failed to send htt umac reset pre reset start: %d\n", ++ ret); ++ dev_kfree_skb_any(skb); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++int ath12k_get_umac_reset_intr_offset(struct ath12k_base *ab) ++{ ++ int i; ++ ++ for (i = 0; i < ATH12K_EXT_IRQ_NUM_MAX; i++) { ++ if (ab->hw_params->ring_mask->umac_dp_reset[i]) ++ return i; ++ } ++ return 0; ++} ++ ++int ath12k_htt_umac_reset_setup_cmd(struct ath12k_base *ab) ++{ ++ int msi_data_count; ++ struct ath12k_htt_umac_reset_setup_cmd_params params = {}; ++ u32 msi_data_start, msi_irq_start; ++ int ret, intr_ctxt; ++ struct ath12k_dp_umac_reset *umac_reset = &ab->dp_umac_reset; ++ ++ intr_ctxt = ath12k_get_umac_reset_intr_offset(ab); ++ ret = ath12k_hif_get_user_msi_vector(ab, "DP", ++ &msi_data_count, &msi_data_start, ++ &msi_irq_start); ++ if (ret) ++ params.msi_data = ATH12K_UMAC_RESET_IPC; ++ else ++ params.msi_data = (intr_ctxt % msi_data_count) + msi_data_start; ++ params.addr_lo = umac_reset->shmem_paddr_aligned & HAL_ADDR_LSB_REG_MASK; ++ params.addr_hi = (u64)umac_reset->shmem_paddr_aligned >> HAL_ADDR_MSB_REG_SHIFT; ++ ++ return ath12k_htt_umac_reset_msg_send(ab, ¶ms); ++} ++ ++int ath12k_dp_umac_reset_init(struct ath12k_base *ab) ++{ ++ struct ath12k_dp_umac_reset *umac_reset; ++ int alloc_size, ret; ++ ++ if (!ab->hw_params->support_umac_reset) ++ return 0; ++ ++ umac_reset = &ab->dp_umac_reset; ++ umac_reset->magic_num = ATH12K_DP_UMAC_RESET_SHMEM_MAGIC_NUM; ++ ++ alloc_size = sizeof(struct ath12k_dp_htt_umac_reset_recovery_msg_shmem_t) + ++ ATH12K_DP_UMAC_RESET_SHMEM_ALIGN - 1; ++ ++ umac_reset->shmem_vaddr_unaligned = dma_alloc_coherent(ab->dev, ++ alloc_size, ++ &umac_reset->shmem_paddr_unaligned, ++ GFP_KERNEL); ++ if (!umac_reset->shmem_vaddr_unaligned) { ++ ath12k_warn(ab, "Failed to allocate memory with size:%u\n", alloc_size); ++ return -ENOMEM; ++ } ++ ++ umac_reset->shmem_vaddr_aligned = ++ PTR_ALIGN(umac_reset->shmem_vaddr_unaligned, ATH12K_DP_UMAC_RESET_SHMEM_ALIGN); ++ umac_reset->shmem_paddr_aligned = ++ umac_reset->shmem_paddr_unaligned + ((unsigned long)umac_reset->shmem_vaddr_aligned - ++ (unsigned long)umac_reset->shmem_vaddr_unaligned); ++ umac_reset->shmem_size = alloc_size; ++ umac_reset->shmem_vaddr_aligned->magic_num = ATH12K_DP_UMAC_RESET_SHMEM_MAGIC_NUM; ++ umac_reset->intr_offset = ath12k_get_umac_reset_intr_offset(ab); ++ ++ ret = ath12k_hif_dp_umac_reset_irq_config(ab); ++ if (ret) { ++ ath12k_warn(ab, "Failed to register interrupt for UMAC RECOVERY\n"); ++ goto shmem_free; ++ } ++ ++ ret = ath12k_htt_umac_reset_setup_cmd(ab); ++ if (ret) { ++ ath12k_warn(ab, "Unable to setup UMAC RECOVERY\n"); ++ goto free_irq; ++ } ++ ++ ath12k_hif_dp_umac_reset_enable_irq(ab); ++ return 0; ++ ++free_irq: ++ ath12k_hif_dp_umac_reset_free_irq(ab); ++shmem_free: ++ dma_free_coherent(ab->dev, ++ umac_reset->shmem_size, ++ umac_reset->shmem_vaddr_unaligned, ++ umac_reset->shmem_paddr_unaligned); ++ umac_reset->shmem_vaddr_unaligned = NULL; ++ return ret; ++} ++ ++void ath12k_umac_reset_pre_reset_validation(struct ath12k_base *ab, bool *is_initiator, ++ bool *is_target_recovery) ++{ ++ struct ath12k_hw_group *ag = ab->ag; ++ struct ath12k_mlo_dp_umac_reset *mlo_umac_reset; ++ *is_initiator = *is_target_recovery = false; ++ ++ if (!ag) ++ return; ++ ++ mlo_umac_reset = &ag->mlo_umac_reset; ++ ++ spin_lock_bh(&mlo_umac_reset->lock); ++ if (mlo_umac_reset->initiator_chip == ab->chip_id) ++ *is_initiator = true; ++ if (mlo_umac_reset->umac_reset_info & BIT(1)) ++ *is_target_recovery = true; ++ spin_unlock_bh(&mlo_umac_reset->lock); ++} ++ ++void ath12k_umac_reset_completion(struct ath12k_base *ab) ++{ ++ struct ath12k_hw_group *ag = ab->ag; ++ struct ath12k_mlo_dp_umac_reset *mlo_umac_reset = &ag->mlo_umac_reset; ++ ++ if (!mlo_umac_reset) ++ return; ++ ++ if (!(mlo_umac_reset->umac_reset_info & BIT(0))) ++ return; ++ ++ spin_lock_bh(&mlo_umac_reset->lock); ++ mlo_umac_reset->umac_reset_info = 0; ++ mlo_umac_reset->initiator_chip = 0; ++ spin_unlock_bh(&mlo_umac_reset->lock); ++} ++ ++void ath12k_umac_reset_send_htt(struct ath12k_base *ab, int tx_event) ++{ ++ struct ath12k_dp_umac_reset *umac_reset = &ab->dp_umac_reset; ++ struct ath12k_dp_htt_umac_reset_recovery_msg_shmem_t *shmem_vaddr_aligned; ++ bool is_initiator, is_target_recovery; ++ int ret; ++ ++ shmem_vaddr_aligned = umac_reset->shmem_vaddr_aligned; ++ ++ switch(tx_event) { ++ case ATH12K_UMAC_RESET_TX_CMD_TRIGGER_DONE: ++ ath12k_umac_reset_pre_reset_validation(ab, &is_initiator, ++ &is_target_recovery); ++ ret = ath12k_htt_umac_reset_send_start_pre_reset_cmd(ab, ++ is_initiator, ++ is_target_recovery); ++ ab->dp_umac_reset.ts.trigger_done = jiffies_to_msecs(jiffies); ++ if (ret) ++ ath12k_warn(ab, "Unable to send umac trigger\n"); ++ break; ++ case ATH12K_UMAC_RESET_TX_CMD_PRE_RESET_DONE: ++ shmem_vaddr_aligned->h2t_msg = u32_encode_bits(1, ++ ATH12K_HTT_UMAC_RESET_MSG_SHMEM_PRE_RESET_DONE_SET); ++ ab->dp_umac_reset.ts.pre_reset_done = jiffies_to_msecs(jiffies); ++ break; ++ case ATH12K_UMAC_RESET_TX_CMD_POST_RESET_START_DONE: ++ shmem_vaddr_aligned->h2t_msg = u32_encode_bits(1, ++ ATH12K_HTT_UMAC_RESET_MSG_SHMEM_POST_RESET_START_DONE_SET); ++ ab->dp_umac_reset.ts.post_reset_done = jiffies_to_msecs(jiffies); ++ break; ++ case ATH12K_UMAC_RESET_TX_CMD_POST_RESET_COMPLETE_DONE: ++ shmem_vaddr_aligned->h2t_msg = u32_encode_bits(1, ++ ATH12K_HTT_UMAC_RESET_MSG_SHMEM_POST_RESET_COMPLETE_DONE); ++ ab->dp_umac_reset.ts.post_reset_complete_done = jiffies_to_msecs(jiffies); ++ break; ++ } ++ ++ if (tx_event == ATH12K_UMAC_RESET_TX_CMD_POST_RESET_COMPLETE_DONE) { ++ ath12k_info(ab, "MLO UMAC Recovery completed\n"); ++ ath12k_umac_reset_completion(ab); ++ ath12k_dbg(ab, ATH12K_DBG_DP_UMAC_RESET, "Time taken for trigger_start:%llums " ++ "trigger_done: %llums pre_reset:%llums post_reset:%llums " ++ "post_reset_complete:%llums", ++ ab->dp_umac_reset.ts.trigger_start, ab->dp_umac_reset.ts.trigger_done, ++ ab->dp_umac_reset.ts.pre_reset_done - ab->dp_umac_reset.ts.pre_reset_start, ++ ab->dp_umac_reset.ts.post_reset_done - ab->dp_umac_reset.ts.post_reset_start, ++ ab->dp_umac_reset.ts.post_reset_complete_done - ab->dp_umac_reset.ts.post_reset_complete_start); ++ memset(&umac_reset->ts, 0, sizeof(struct ath12k_umac_reset_ts)); ++ } ++ ++ return; ++} ++ ++int ath12k_umac_reset_notify_target(struct ath12k_base *ab, int tx_event) ++{ ++ struct ath12k_base *partner_ab; ++ struct ath12k_hw_group *ag = ab->ag; ++ int i; ++ ++ for (i = 0; i < ag->num_chip; i++) { ++ partner_ab = ag->ab[i]; ++ ++ if (test_bit(ATH12K_FLAG_RECOVERY, &partner_ab->dev_flags)) ++ continue; ++ ++ ath12k_umac_reset_send_htt(partner_ab, tx_event); ++ } ++ ++ return 0; ++} ++ ++void ath12k_umac_reset_initiate_recovery(struct ath12k_base *ab) ++{ ++ struct ath12k_hw_group *ag = ab->ag; ++ struct ath12k_mlo_dp_umac_reset *mlo_umac_reset = &ag->mlo_umac_reset; ++ ++ if (!mlo_umac_reset) ++ return; ++ ++ spin_lock_bh(&mlo_umac_reset->lock); ++ ++ if (mlo_umac_reset->umac_reset_info & ++ ATH12K_IS_UMAC_RESET_IN_PROGRESS) { ++ spin_unlock_bh(&mlo_umac_reset->lock); ++ ath12k_warn(ab, "UMAC RECOVERY IS IN PROGRESS\n"); ++ return; ++ } ++ mlo_umac_reset->umac_reset_info = BIT(0); /* UMAC recovery is in progress */ ++ mlo_umac_reset->umac_reset_info |= BIT(1); /* Target recovery */ ++ atomic_set(&mlo_umac_reset->response_chip, 0); ++ mlo_umac_reset->initiator_chip = ab->chip_id; ++ spin_unlock_bh(&mlo_umac_reset->lock); ++} ++ ++void ath12k_umac_reset_notify_target_sync_and_send(struct ath12k_base *ab, ++ enum dp_umac_reset_tx_cmd tx_event) ++{ ++ struct ath12k_hw_group *ag = ab->ag; ++ struct ath12k_mlo_dp_umac_reset *mlo_umac_reset = &ag->mlo_umac_reset; ++ ++ if (atomic_read(&mlo_umac_reset->response_chip) >= ab->ag->num_started) { ++ ath12k_dbg(ab, ATH12K_DBG_DP_UMAC_RESET, "response chip:%d num_started:%d sending notify\n", ++ atomic_read(&mlo_umac_reset->response_chip), ab->ag->num_started); ++ ath12k_umac_reset_notify_target(ab, tx_event); ++ atomic_set(&mlo_umac_reset->response_chip, 0); ++ } else { ++ ath12k_dbg(ab, ATH12K_DBG_DP_UMAC_RESET, "response_chip:%d num_started:%d not matching.. hold on notify\n", ++ atomic_read(&mlo_umac_reset->response_chip), ab->ag->num_started); ++ } ++ return; ++} ++ ++void ath12k_umac_reset_handle_pre_reset(struct ath12k_base *ab) ++{ ++ struct ath12k_hw_group *ag = ab->ag; ++ struct ath12k_mlo_dp_umac_reset *mlo_umac_reset = &ag->mlo_umac_reset; ++ ++ set_bit(ATH12K_FLAG_UMAC_PRERESET_START, &ab->dev_flags); ++ ath12k_dp_reset_interrupt_mask(ab); ++ atomic_inc(&mlo_umac_reset->response_chip); ++ ++ ath12k_umac_reset_notify_target_sync_and_send(ab, ATH12K_UMAC_RESET_TX_CMD_PRE_RESET_DONE); ++ return; ++} ++ ++void ath12k_umac_reset_handle_post_reset_complete(struct ath12k_base *ab) ++{ ++ struct ath12k_hw_group *ag = ab->ag; ++ struct ath12k_mlo_dp_umac_reset *mlo_umac_reset = &ag->mlo_umac_reset; ++ ++ clear_bit(ATH12K_FLAG_UMAC_PRERESET_START, &ab->dev_flags); ++ ++ atomic_inc(&mlo_umac_reset->response_chip); ++ ath12k_dp_restore_interrupt_mask(ab); ++ ath12k_umac_reset_notify_target_sync_and_send(ab, ATH12K_UMAC_RESET_TX_CMD_POST_RESET_COMPLETE_DONE); ++ ath12k_dp_peer_tid_setup(ab); ++ return; ++} ++ ++void ath12k_dp_umac_reset_action(struct ath12k_base *ab, ++ enum dp_umac_reset_recover_action rx_event) ++{ ++ switch(rx_event) { ++ case ATH12K_UMAC_RESET_INIT_UMAC_RECOVERY: ++ case ATH12K_UMAC_RESET_INIT_TARGET_RECOVERY_SYNC_USING_UMAC: ++ ath12k_umac_reset_initiate_recovery(ab); ++ ab->dp_umac_reset.ts.trigger_start = jiffies_to_msecs(jiffies); ++ ath12k_umac_reset_notify_target(ab, ATH12K_UMAC_RESET_TX_CMD_TRIGGER_DONE); ++ break; ++ case ATH12K_UMAC_RESET_DO_POST_RESET_COMPLETE: ++ ab->dp_umac_reset.ts.post_reset_complete_start = jiffies_to_msecs(jiffies); ++ ath12k_umac_reset_handle_post_reset_complete(ab); ++ break; ++ case ATH12K_UMAC_RESET_DO_POST_RESET_START: ++ ab->dp_umac_reset.ts.post_reset_start = jiffies_to_msecs(jiffies); ++ ath12k_umac_reset_handle_post_reset_start(ab); ++ break; ++ case ATH12K_UMAC_RESET_DO_PRE_RESET: ++ ab->dp_umac_reset.ts.pre_reset_start = jiffies_to_msecs(jiffies); ++ ath12k_umac_reset_handle_pre_reset(ab); ++ break; ++ default: ++ ath12k_dbg(ab, ATH12K_DBG_DP_UMAC_RESET, "Unknown UMAC RESET event received\n"); ++ break; ++ } ++ return; ++} ++ ++void ath12k_dp_umac_reset_handle(struct ath12k_base *ab) ++{ ++ struct ath12k_dp_umac_reset *umac_reset = &ab->dp_umac_reset; ++ struct ath12k_dp_htt_umac_reset_recovery_msg_shmem_t *shmem_vaddr; ++ int rx_event, num_event = 0; ++ u32 t2h_msg; ++ ++ shmem_vaddr = umac_reset->shmem_vaddr_aligned; ++ if (!shmem_vaddr) { ++ ath12k_dbg(ab, ATH12K_DBG_DP_UMAC_RESET, "Shared memory address NULL\n"); ++ return; ++ } ++ ++ if (shmem_vaddr->magic_num != umac_reset->magic_num) { ++ ath12k_dbg(ab, ATH12K_DBG_DP_UMAC_RESET, "Shared memory address is invalid shmem:0x%x u:0x%x\n", ++ shmem_vaddr->magic_num, umac_reset->magic_num); ++ return; ++ } ++ ++ t2h_msg = shmem_vaddr->t2h_msg; ++ shmem_vaddr->t2h_msg = 0; ++ ++ rx_event = ATH12K_UMAC_RESET_RX_EVENT_NONE; ++ ++ if (u32_get_bits(t2h_msg, HTT_ATH12K_UMAC_RESET_T2H_INIT_UMAC_RECOVERY)) { ++ rx_event |= ATH12K_UMAC_RESET_INIT_UMAC_RECOVERY; ++ num_event++; ++ } ++ ++ if (u32_get_bits(t2h_msg, HTT_ATH12K_UMAC_RESET_T2H_INIT_TARGET_RECOVERY_SYNC_USING_UMAC)) { ++ rx_event |= ATH12K_UMAC_RESET_INIT_TARGET_RECOVERY_SYNC_USING_UMAC; ++ num_event++; ++ } ++ ++ if (u32_get_bits(t2h_msg, HTT_ATH12K_UMAC_RESET_T2H_DO_PRE_RESET)) { ++ rx_event |= ATH12K_UMAC_RESET_DO_PRE_RESET; ++ num_event++; ++ } ++ ++ if (u32_get_bits(t2h_msg, HTT_ATH12K_UMAC_RESET_T2H_DO_POST_RESET_START)) { ++ rx_event |= ATH12K_UMAC_RESET_DO_POST_RESET_START; ++ num_event++; ++ } ++ ++ if (u32_get_bits(t2h_msg, HTT_ATH12K_UMAC_RESET_T2H_DO_POST_RESET_COMPLETE)) { ++ rx_event |= ATH12K_UMAC_RESET_DO_POST_RESET_COMPLETE; ++ num_event++; ++ } ++ ++ ath12k_dbg(ab, ATH12K_DBG_DP_UMAC_RESET, "Deduced rx event:%d num:%d\n", rx_event, num_event); ++ ++ if (num_event > 1) { ++ ath12k_dbg(ab, ATH12K_DBG_DP_UMAC_RESET, "Multiple event notified in single msg\n"); ++ WARN_ON_ONCE(1); ++ return; ++ } ++ ++ ath12k_dp_umac_reset_action(ab, rx_event); ++ return; ++} ++ ++void ath12k_dp_umac_reset_deinit(struct ath12k_base *ab) ++{ ++ struct ath12k_dp_umac_reset *umac_reset; ++ ++ if (!ab->hw_params->support_umac_reset) ++ return; ++ ++ umac_reset = &ab->dp_umac_reset; ++ ++ if (!umac_reset) ++ return; ++ ++ ath12k_hif_dp_umac_reset_free_irq(ab); ++ ++ if (umac_reset->shmem_vaddr_unaligned) { ++ dma_free_coherent(ab->dev, ++ umac_reset->shmem_size, ++ umac_reset->shmem_vaddr_unaligned, ++ umac_reset->shmem_paddr_unaligned); ++ umac_reset->shmem_vaddr_unaligned = NULL; ++ ++ } ++} +--- a/drivers/net/wireless/ath/ath12k/dp_rx.h ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.h +@@ -228,4 +228,10 @@ ath12k_dp_rx_htt_rxdma_rxole_ppe_cfg_set + int ath12k_dp_rx_pkt_type_filter(struct ath12k *ar, + enum ath12k_routing_pkt_type pkt_type, + u32 meta_data); ++void ath12k_dp_tid_cleanup(struct ath12k_base *ab); ++void ath12k_dp_peer_tid_setup(struct ath12k_base *ab); ++void ath12k_dp_peer_reo_tid_setup(struct ath12k_base *ab, struct ath12k_link_sta *arsta); ++void ath12k_dp_tid_setup(void *data, struct ieee80211_sta *sta); ++void ath12k_dp_reset_rx_reo_tid_q(void *vaddr, u32 ba_window_size, ++ u8 tid); + #endif /* ATH12K_DP_RX_H */ +--- a/drivers/net/wireless/ath/ath12k/hal_rx.c ++++ b/drivers/net/wireless/ath/ath12k/hal_rx.c +@@ -964,3 +964,51 @@ void ath12k_hal_reo_shared_qaddr_cache_c + ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + + HAL_REO1_QDESC_ADDR_READ(ab), val); + } ++ ++void ath12k_dp_reset_rx_reo_tid_q(void *vaddr, u32 ba_window_size, ++ u8 tid) ++{ ++ struct hal_rx_reo_queue *qdesc = (struct hal_rx_reo_queue *)vaddr; ++ struct hal_rx_reo_queue_ext *ext_desc; ++ u32 size, info0, info1, rx_queue_num; ++ ++ size = ath12k_hal_reo_qdesc_size(ba_window_size, tid); ++ ++ rx_queue_num = qdesc->rx_queue_num; ++ info0 = qdesc->info0; ++ info1 = qdesc->info1; ++ ++ memset(qdesc, 0, size); ++ ++ ath12k_hal_reo_set_desc_hdr(&qdesc->desc_hdr, HAL_DESC_REO_OWNED, ++ HAL_DESC_REO_QUEUE_DESC, ++ REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_0); ++ ++ qdesc->rx_queue_num = rx_queue_num; ++ qdesc->info0 = info0; ++ qdesc->info1 = info1; ++ ++ qdesc->info1 |= u32_encode_bits(0, HAL_RX_REO_QUEUE_INFO1_SVLD); ++ qdesc->info1 |= u32_encode_bits(0, ++ HAL_RX_REO_QUEUE_INFO1_SSN); ++ ++ if (tid == HAL_DESC_REO_NON_QOS_TID) ++ return; ++ ++ ext_desc = qdesc->ext_desc; ++ memset(ext_desc, 0, 3 * sizeof(*ext_desc)); ++ ++ ath12k_hal_reo_set_desc_hdr(&ext_desc->desc_hdr, HAL_DESC_REO_OWNED, ++ HAL_DESC_REO_QUEUE_EXT_DESC, ++ REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_1); ++ ext_desc++; ++ ++ ath12k_hal_reo_set_desc_hdr(&ext_desc->desc_hdr, HAL_DESC_REO_OWNED, ++ HAL_DESC_REO_QUEUE_EXT_DESC, ++ REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_2); ++ ext_desc++; ++ ++ ath12k_hal_reo_set_desc_hdr(&ext_desc->desc_hdr, HAL_DESC_REO_OWNED, ++ HAL_DESC_REO_QUEUE_EXT_DESC, ++ REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_3); ++} +--- a/drivers/net/wireless/ath/ath12k/hal.c ++++ b/drivers/net/wireless/ath/ath12k/hal.c +@@ -2233,6 +2233,12 @@ int ath12k_hal_srng_setup_idx(struct ath + memset(srng->ring_base_vaddr, 0, + (srng->entry_size * srng->num_entries) << 2); + ++ if (srng->flags & HAL_SRNG_FLAGS_CACHED) { ++ dmac_inv_range_no_dsb(srng->ring_base_vaddr, ++ srng->ring_base_vaddr + ++ ((srng->entry_size * srng->num_entries))); ++ } ++ + /* TODO: Add comments on these swap configurations */ + if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) + srng->flags |= HAL_SRNG_FLAGS_MSI_SWAP | HAL_SRNG_FLAGS_DATA_TLV_SWAP | +@@ -2247,6 +2253,10 @@ int ath12k_hal_srng_setup_idx(struct ath + srng->u.src_ring.tp_addr = (void *)(hal->rdp.vaddr + ring_id); + srng->u.src_ring.low_threshold = params->low_threshold * + srng->entry_size; ++ ++ if (srng->u.src_ring.tp_addr) ++ *srng->u.src_ring.tp_addr = 0; ++ + if (srng_config->mac_type == ATH12K_HAL_SRNG_UMAC) { + if (!ab->hw_params->supports_shadow_regs) { + srng->u.src_ring.hp_addr = +@@ -2273,6 +2283,10 @@ int ath12k_hal_srng_setup_idx(struct ath + idx = ring_id - HAL_SRNG_RING_ID_DMAC_CMN_ID_START; + srng->u.src_ring.hp_addr = (void *)(hal->wrp.vaddr + + idx); ++ ++ if (srng->u.src_ring.hp_addr) ++ *srng->u.src_ring.hp_addr = 0; ++ + srng->flags |= HAL_SRNG_FLAGS_LMAC_RING; + } + } else { +@@ -2288,6 +2302,10 @@ int ath12k_hal_srng_setup_idx(struct ath + srng->u.dst_ring.tp = 0; + srng->u.dst_ring.cached_hp = 0; + srng->u.dst_ring.hp_addr = (void *)(hal->rdp.vaddr + ring_id); ++ ++ if (srng->u.dst_ring.hp_addr) ++ *srng->u.dst_ring.hp_addr = 0; ++ + if (srng_config->mac_type == ATH12K_HAL_SRNG_UMAC) { + if (!ab->hw_params->supports_shadow_regs) { + srng->u.dst_ring.tp_addr = +@@ -2319,6 +2337,10 @@ int ath12k_hal_srng_setup_idx(struct ath + idx = ring_id - HAL_SRNG_RING_ID_DMAC_CMN_ID_START; + srng->u.dst_ring.tp_addr = (void *)(hal->wrp.vaddr + + idx); ++ ++ if (srng->u.dst_ring.tp_addr) ++ *srng->u.dst_ring.tp_addr = 0; ++ + srng->flags |= HAL_SRNG_FLAGS_LMAC_RING; + } + } +--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h ++++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h +@@ -193,6 +193,7 @@ enum htt_tlv_tag_t { + HTT_STATS_PDEV_MBSSID_CTRL_FRAME_STATS_TAG = 176, + HTT_STATS_TX_PDEV_MLO_ABORT_TAG = 177, + HTT_STATS_TX_PDEV_MLO_TXOP_ABORT_TAG = 178, ++ HTT_STATS_UMAC_SSR_TAG = 179, + HTT_STATS_MAX_TAG, + }; + +@@ -4235,4 +4236,30 @@ struct htt_pdev_sched_algo_ofdma_stats_t + u32 dlofdma_disabled_consec_no_mpdus_success[HTT_NUM_AC_WMM]; + }; + ++struct htt_umac_ssr_stats_tlv { ++ u32 total_done; ++ u32 trigger_requests_count; ++ u32 total_trig_dropped; ++ u32 umac_disengaged_count; ++ u32 umac_soft_reset_count; ++ u32 umac_engaged_count; ++ u32 last_trigger_request_ms; ++ u32 last_start_ms; ++ u32 last_start_disengage_umac_ms; ++ u32 last_enter_ssr_platform_thread_ms; ++ u32 last_exit_ssr_platform_thread_ms; ++ u32 last_start_engage_umac_ms; ++ u32 last_done_successful_ms; ++ u32 last_e2e_delta_ms; ++ u32 max_e2e_delta_ms; ++ u32 trigger_count_for_umac_hang; ++ u32 trigger_count_for_mlo_quick_ssr; ++ u32 trigger_count_for_unknown_signature; ++ u32 post_reset_tqm_sync_cmd_completion_ms; ++ u32 htt_sync_mlo_initiate_umac_recovery_ms; ++ u32 htt_sync_do_pre_reset_ms; ++ u32 htt_sync_do_post_reset_start_ms; ++ u32 htt_sync_do_post_reset_complete_ms; ++}; ++ + #endif +--- a/drivers/net/wireless/ath/ath12k/debugfs.h ++++ b/drivers/net/wireless/ath/ath12k/debugfs.h +@@ -74,6 +74,7 @@ enum ath12k_dbg_htt_ext_stats_type { + ATH12K_DBG_HTT_DBG_EXT_PHY_PROF_CAL_STATS = 52, + ATH12K_DGB_HTT_DBG_EXT_STATS_PDEV_BW_MGR = 53, + ATH12K_DGB_HTT_DBG_PDEV_MBSSID_CTRL_FRAME_STATS = 54, ++ ATH12K_DBG_HTT_UMAC_RESET_SSR_STATS = 55, + /* keep this last */ + ATH12K_DBG_HTT_NUM_EXT_STATS, + }; +--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c +@@ -8145,6 +8145,68 @@ static inline void htt_print_histogram_s + stats_req->buf_len = len; + } + ++static void htt_print_umac_ssr_stats_tlv(const void *tag_buf, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_umac_ssr_stats_tlv *htt_stats_buf = tag_buf; ++ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; ++ u32 len = stats_req->buf_len; ++ u8 *buf = stats_req->buf; ++ ++ len += scnprintf(buf + len, buf_len - len, "HTT_UMAC_SSR_STATS_TLV:\n"); ++ len += scnprintf(buf + len, buf_len - len, "total_done = %u\n", ++ htt_stats_buf->total_done); ++ len += scnprintf(buf + len, buf_len - len, "trigger_requests_count = %u\n", ++ htt_stats_buf->trigger_requests_count); ++ len += scnprintf(buf + len, buf_len - len, "total_trig_dropped = %u\n", ++ htt_stats_buf->total_trig_dropped); ++ len += scnprintf(buf + len, buf_len - len, "umac_disengaged_count = %u\n", ++ htt_stats_buf->umac_disengaged_count); ++ len += scnprintf(buf + len, buf_len - len, "umac_soft_reset_count = %u\n", ++ htt_stats_buf->umac_soft_reset_count); ++ len += scnprintf(buf + len, buf_len - len, "umac_engaged_count = %u\n", ++ htt_stats_buf->umac_engaged_count); ++ len += scnprintf(buf + len, buf_len - len, "last_trigger_request_ms = %u\n", ++ htt_stats_buf->last_trigger_request_ms); ++ len += scnprintf(buf + len, buf_len - len, "last_start_ms = %u\n", ++ htt_stats_buf->last_start_ms); ++ len += scnprintf(buf + len, buf_len - len, "last_start_disengage_umac_ms = %u\n", ++ htt_stats_buf->last_start_disengage_umac_ms); ++ len += scnprintf(buf + len, buf_len - len, "last_enter_ssr_platform_thread_ms = %u\n", ++ htt_stats_buf->last_enter_ssr_platform_thread_ms); ++ len += scnprintf(buf + len, buf_len - len, "last_exit_ssr_platform_thread_ms = %u\n", ++ htt_stats_buf->last_exit_ssr_platform_thread_ms); ++ len += scnprintf(buf + len, buf_len - len, "last_start_engage_umac_ms = %u\n", ++ htt_stats_buf->last_start_engage_umac_ms); ++ len += scnprintf(buf + len, buf_len - len, "post_reset_tqm_sync_cmd_completion_ms = %u\n", ++ htt_stats_buf->post_reset_tqm_sync_cmd_completion_ms); ++ len += scnprintf(buf + len, buf_len - len, "last_done_successful_ms = %u\n", ++ htt_stats_buf->last_done_successful_ms); ++ len += scnprintf(buf + len, buf_len - len, "last_e2e_delta_ms = %u\n", ++ htt_stats_buf->last_e2e_delta_ms); ++ len += scnprintf(buf + len, buf_len - len, "max_e2e_delta_ms = %u\n", ++ htt_stats_buf->max_e2e_delta_ms); ++ len += scnprintf(buf + len, buf_len - len, "trigger_count_for_umac_hang = %u\n", ++ htt_stats_buf->trigger_count_for_umac_hang); ++ len += scnprintf(buf + len, buf_len - len, "trigger_count_for_mlo_quick_ssr = %u\n", ++ htt_stats_buf->trigger_count_for_mlo_quick_ssr); ++ len += scnprintf(buf + len, buf_len - len, "trigger_count_for_unknown_signature = %u\n", ++ htt_stats_buf->trigger_count_for_unknown_signature); ++ len += scnprintf(buf + len, buf_len - len, "htt_sync_mlo_initiate_umac_recovery_ms = %u\n", ++ htt_stats_buf->htt_sync_mlo_initiate_umac_recovery_ms); ++ len += scnprintf(buf + len, buf_len - len, "htt_sync_do_pre_reset_ms = %u\n", ++ htt_stats_buf->htt_sync_do_pre_reset_ms); ++ len += scnprintf(buf + len, buf_len - len, "htt_sync_do_post_reset_start_ms = %u\n", ++ htt_stats_buf->htt_sync_do_post_reset_start_ms); ++ len += scnprintf(buf + len, buf_len - len, "htt_sync_do_post_reset_complete_ms = %u\n", ++ htt_stats_buf->htt_sync_do_post_reset_complete_ms); ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "=================================================\n"); ++ ++ stats_req->buf_len = len; ++} ++ + static int ath12k_dbg_htt_ext_stats_parse(struct ath12k_base *ab, + u16 tag, u16 len, const void *tag_buf, + void *user_data) +@@ -8775,6 +8837,10 @@ static int ath12k_dbg_htt_ext_stats_pars + break; + case HTT_STATS_TX_PDEV_SAWF_RATE_STATS_TAG: + htt_print_histogram_stats_tlv(tag_buf, stats_req); ++ break; ++ case HTT_STATS_UMAC_SSR_TAG: ++ htt_print_umac_ssr_stats_tlv(tag_buf, stats_req); ++ break; + default: + break; + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/800-wifi-ath12k-skip-peer-delete-if-ieee80211_sta-exsits.patch b/feeds/ipq95xx/mac80211/patches/qca/800-wifi-ath12k-skip-peer-delete-if-ieee80211_sta-exsits.patch new file mode 100644 index 000000000..426c1159f --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/800-wifi-ath12k-skip-peer-delete-if-ieee80211_sta-exsits.patch @@ -0,0 +1,154 @@ +From 8a29f081883b69f76af45754cd1a5a1b5ff63cdf Mon Sep 17 00:00:00 2001 +From: Wen Gong +Date: Tue, 15 Nov 2022 03:04:22 -0500 +Subject: [PATCH 111/112] wifi: ath12k: skip peer delete if ieee80211_sta + exsits while unassign_vif_chanctx for station + +Sometimes mac80211 will call unassign_vif_chanctx and assign_vif_chanctx +of struct ieee80211_ops from ieee80211_mgd_assoc() with below call stack. + +It leads connect fail for station as below log, because peer is delete +in unassign_vif_chanctx, and vdev is not started in assign_vif_chanctx +caused by vdev_start_delay setting in ath12k_hw_params, so the management +packet is dropped. + +Change to skip the peer delete for this condition, and connect success. + +Signed-off-by: Wen Gong +Signed-off-by: Amutha Ravikumar +--- + drivers/net/wireless/ath/ath12k/mac.c | 37 ++++++++++++++++++++------- + 1 file changed, 28 insertions(+), 9 deletions(-) + +Index: b/drivers/net/wireless/ath/ath12k/mac.c +=================================================================== +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -12906,6 +12906,7 @@ ath12k_mac_op_unassign_vif_chanctx(struc + struct ath12k_link_vif *arvif; + struct ath12k_hw *ah = hw->priv; + struct ath12k_base *ab; ++ struct ath12k_peer *peer; + struct ath12k *ar; + int ret; + u8 link_id = link_conf->link_id; +@@ -12973,17 +12974,33 @@ ath12k_mac_op_unassign_vif_chanctx(struc + ahvif->num_vdev_started--; + } + +- if (ab->hw_params->vdev_start_delay && +- ahvif->vdev_type == WMI_VDEV_TYPE_STA) { +- ret = ath12k_peer_delete(ar, arvif->vdev_id, arvif->bssid); +- if (ret) +- ath12k_warn(ar->ab, +- "failed to delete peer %pM for vdev %d: %d\n", +- arvif->bssid, arvif->vdev_id, ret); +- else +- ath12k_dbg(ar->ab, ATH12K_DBG_MAC, +- "mac removed peer %pM vdev %d after vdev stop\n", +- arvif->bssid, arvif->vdev_id); ++ peer = ath12k_peer_find_by_vdev_id(ab, arvif->vdev_id); ++ if (ahvif->vdev_type == WMI_VDEV_TYPE_STA && peer) { ++ struct ieee80211_sta *sta; ++ unsigned int sta_link_id = 0xff; ++ ++ if (vif->valid_links) ++ sta = ieee80211_find_sta_by_link_addrs(hw, peer->addr, ++ NULL, &sta_link_id); ++ else ++ sta = ieee80211_find_sta_by_ifaddr(hw, peer->addr, NULL); ++ ath12k_dbg(ab, ATH12K_DBG_MAC, ++ "peer delete check links 0x%x vdev id %i peer %pM link id %d sta %pK\n", ++ vif->valid_links, arvif->vdev_id, ++ peer->addr, sta_link_id, sta); ++ ++ if ((ab->hw_params->vdev_start_delay && !sta && !peer->sta) || ++ !ab->hw_params->vdev_start_delay) { ++ ret = ath12k_peer_delete(ar, arvif->vdev_id, arvif->bssid); ++ if (ret) ++ ath12k_warn(ar->ab, ++ "failed to delete peer %pM for vdev %d: %d\n", ++ arvif->bssid, arvif->vdev_id, ret); ++ else ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, ++ "mac removed peer %pM vdev %d\n", ++ arvif->bssid, arvif->vdev_id); ++ } + } + + if (ab->hw_params->vdev_start_delay && +Index: b/net/mac80211/sta_info.c +=================================================================== +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -1487,6 +1487,43 @@ struct ieee80211_sta *ieee80211_find_sta + } + EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_ifaddr); + ++struct ieee80211_sta * ++ieee80211_find_sta_by_link_addrs(struct ieee80211_hw *hw, ++ const u8 *addr, ++ const u8 *localaddr, ++ unsigned int *link_id) ++{ ++ struct ieee80211_local *local = hw_to_local(hw); ++ struct link_sta_info *link_sta; ++ struct rhlist_head *tmp; ++ ++ for_each_link_sta_info(local, addr, link_sta, tmp) { ++ struct sta_info *sta = link_sta->sta; ++ struct ieee80211_link_data *link; ++ u8 _link_id = link_sta->link_id; ++ ++ if (!localaddr) { ++ if (link_id) ++ *link_id = _link_id; ++ return &sta->sta; ++ } ++ ++ link = rcu_dereference(sta->sdata->link[_link_id]); ++ if (!link) ++ continue; ++ ++ if (memcmp(link->conf->addr, localaddr, ETH_ALEN)) ++ continue; ++ ++ if (link_id) ++ *link_id = _link_id; ++ return &sta->sta; ++ } ++ ++ return NULL; ++} ++EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_link_addrs); ++ + struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif, + const u8 *addr) + { +Index: b/include/net/mac80211.h +=================================================================== +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -6347,6 +6347,22 @@ struct ieee80211_sta *ieee80211_find_sta + const u8 *localaddr); + + /** ++ * ieee80211_find_sta_by_link_addrs - find STA by link addresses ++ * @hw: pointer as obtained from ieee80211_alloc_hw() ++ * @addr: remote station's link address ++ * @localaddr: local link address, use %NULL for any (but avoid that) ++ * @link_id: pointer to obtain the link ID if the STA is found, ++ * may be %NULL if the link ID is not needed ++ * ++ * Obtain the STA by link address, must use RCU protection. ++ */ ++struct ieee80211_sta * ++ieee80211_find_sta_by_link_addrs(struct ieee80211_hw *hw, ++ const u8 *addr, ++ const u8 *localaddr, ++ unsigned int *link_id); ++ ++/** + * ieee80211_sta_block_awake - block station from waking up + * @hw: the hardware + * @pubsta: the station diff --git a/feeds/ipq95xx/mac80211/patches/qca/801-01-wifi-ath12k-Add-support-to-parse-mlo-chip-crash-info.patch b/feeds/ipq95xx/mac80211/patches/qca/801-01-wifi-ath12k-Add-support-to-parse-mlo-chip-crash-info.patch new file mode 100644 index 000000000..9760acf0c --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/801-01-wifi-ath12k-Add-support-to-parse-mlo-chip-crash-info.patch @@ -0,0 +1,437 @@ +From 4b2287c78e790178d7e95c23c526ec1fcaf5ed41 Mon Sep 17 00:00:00 2001 +From: Manish Dharanenthiran +Date: Sun, 9 Jul 2023 11:37:55 +0530 +Subject: [PATCH 1/4] wifi: ath12k: Add support to parse mlo chip crash info + TLV + +Add support to parse MLO global chip crash info TLV and +per chip crash info TLV from shmem. The information parsed +will be used to identify the crash reason for corresponding +chip_id and the recovery mode used for the same. + +Signed-off-by: Manish Dharanenthiran +--- + drivers/net/wireless/ath/ath12k/core.c | 70 ++++++++++++ + drivers/net/wireless/ath/ath12k/core.h | 10 ++ + drivers/net/wireless/ath/ath12k/qmi.c | 145 ++++++++++++++++++++++++- + drivers/net/wireless/ath/ath12k/wmi.h | 69 ++++++++++++ + 4 files changed, 291 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c +index 2c8e974..1cbe9b4 100644 +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -1068,6 +1068,65 @@ static int ath12k_core_mgmt_rx_reordering_init(struct ath12k_base *ab) + ar->rx_reo_pdev_ctx.init_complete = true; + } + ++ return 0; ++} ++ ++static int ath12k_core_mlo_shmem_per_chip_crash_info_addresses( ++ struct ath12k_base *ab, ++ struct ath12k_host_mlo_glb_chip_crash_info *global_chip_crash_info, ++ int chip_id) ++{ ++ int i; ++ struct ath12k_host_mlo_glb_per_chip_crash_info *per_chip_crash_info = NULL; ++ ++ for (i = 0; i < global_chip_crash_info->no_of_chips; i++) ++ { ++ per_chip_crash_info = &global_chip_crash_info->per_chip_crash_info[i]; ++ ++ if (!per_chip_crash_info) ++ return -EINVAL; ++ ++ if (chip_id == per_chip_crash_info->chip_id) ++ break; ++ } ++ ++ if (i >= global_chip_crash_info->no_of_chips) { ++ ath12k_err(ab, "error in chip id:%d\n", chip_id); ++ return 0; ++ } ++ ++ if (!per_chip_crash_info || ++ !per_chip_crash_info->crash_reason || ++ !per_chip_crash_info->recovery_mode) { ++ ath12k_err(ab, "crash_reason address is null\n"); ++ return 0; ++ } ++ ++ ab->crash_info_address = per_chip_crash_info->crash_reason; ++ ab->recovery_mode_address = per_chip_crash_info->recovery_mode; ++ ++ return 0; ++} ++ ++static int ath12k_core_mlo_shmem_crash_info_init(struct ath12k_base *ab, int index) ++{ ++ struct ath12k_hw_group *ag = ab->ag; ++ struct ath12k_host_mlo_mem_arena *mlomem_arena_ctx; ++ struct ath12k_host_mlo_glb_chip_crash_info *global_chip_crash_info; ++ ++ mlomem_arena_ctx = &ab->ag->mlomem_arena; ++ ++ if (!(ag->mlo_mem.is_mlo_mem_avail)) ++ return 0; ++ ++ global_chip_crash_info = &mlomem_arena_ctx->global_chip_crash_info; ++ ++ if (ath12k_core_mlo_shmem_per_chip_crash_info_addresses(ab, ++ global_chip_crash_info, ++ index) < 0) { ++ ath12k_warn(ab, "per_chip_crash_info is not set\n"); ++ return -EINVAL; ++ } + + return 0; + } +@@ -1433,6 +1492,11 @@ static int ath12k_core_hw_group_start(struct ath12k_hw_group *ag) + goto pdev_cleanup; + } + ++ ret = ath12k_core_mlo_shmem_crash_info_init(ab, i); ++ if (ret) { ++ ath12k_err(ab, "failed to parse crash info %d\n", ret); ++ } ++ + set_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags); + + mutex_unlock(&ab->core_lock); +@@ -2123,6 +2187,12 @@ static void ath12k_core_reset(struct work_struct *work) + ath12k_core_disable_ds_rtnl_bond_release(ab); + } + #endif ++ ++ ag->recovery_mode = ATH12K_MLO_RECOVERY_MODE0; ++ if (ab->recovery_mode_address) { ++ ag->recovery_mode = *ab->recovery_mode_address; ++ } ++ + /* Sometimes the recovery will fail and then the next all recovery fail, + * this is to avoid infinite recovery since it can not recovery success. + */ +diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h +index f23e133..0736948 100644 +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -327,6 +327,12 @@ struct ath12k_key_conf { + struct ieee80211_key_conf *key; + }; + ++struct ath12k_recovery_cache { ++ struct ath12k_tx_conf tx_conf; ++ struct ath12k_key_conf key_conf; ++ u64 bss_conf_changed; ++}; ++ + struct ath12k_vif_cache { + struct ath12k_tx_conf tx_conf; + struct ath12k_key_conf key_conf; +@@ -1267,6 +1273,7 @@ struct ath12k_hw_group { + bool hw_queues_stopped; + bool mgmt_rx_reorder; + unsigned long dev_flags; ++ enum ath12k_mlo_recovery_mode recovery_mode; + struct ath12k_hw *ah[ATH12K_GROUP_MAX_RADIO]; + struct ath12k_base *ab[ATH12K_MAX_SOCS]; + struct ath12k __rcu *hw_links[ATH12K_GROUP_MAX_RADIO]; +@@ -1454,6 +1461,9 @@ struct ath12k_base { + u32 chwidth_num_peer_caps; + struct ath12k_dp_umac_reset dp_umac_reset; + ++ u32 *crash_info_address; ++ u32 *recovery_mode_address; ++ + /* must be last */ + u8 drv_priv[0] __aligned(sizeof(void *)); + }; +diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c +index ff6df9d..6e598e8 100644 +--- a/drivers/net/wireless/ath/ath12k/qmi.c ++++ b/drivers/net/wireless/ath/ath12k/qmi.c +@@ -3249,6 +3249,21 @@ out: + return ret; + } + ++/** ++ * ath12k_free_mlo_glb_per_chip_crash_info() - Free MLO per_chip crash info ++ * @snapshot_info: Pointer to MLO Global crash info ++ * ++ * Return: None ++ */ ++static void ath12k_free_mlo_glb_per_chip_crash_info( ++ struct ath12k_host_mlo_glb_chip_crash_info *global_chip_crash_info) ++{ ++ if (global_chip_crash_info->per_chip_crash_info) { ++ kfree(global_chip_crash_info->per_chip_crash_info); ++ global_chip_crash_info->per_chip_crash_info = NULL; ++ } ++} ++ + /** + * ath12k_free_mlo_mgmt_rx_reo_per_link_info() - Free Rx REO per-link info + * @snapshot_info: Pointer to MGMT Rx REO snapshot info +@@ -3319,6 +3334,8 @@ static void ath12k_qmi_free_mlo_mem_chunk(struct ath12k_base *ab, + mlomem_arena_ctx->init_done = false; + ath12k_free_mlo_mgmt_rx_reo_per_link_info + (&mlomem_arena_ctx->rx_reo_snapshot_info); ++ ath12k_free_mlo_glb_per_chip_crash_info ++ (&mlomem_arena_ctx->global_chip_crash_info); + } + mutex_unlock(&mlomem_arena_ctx->mutex_lock); + +@@ -3642,6 +3659,124 @@ ath12k_mgmt_rx_reo_get_num_links_from_valid_link_bitmap(u16 valid_link_bmap) + return num_links; + } + ++static int ++ath12k_mgmt_mlo_global_per_chip_crash_info_tlv(struct ath12k_base *ab, ++ u8 *data, ++ size_t remaining_len, u8 cur_chip_id, ++ struct ath12k_host_mlo_glb_per_chip_crash_info *per_chip_crash_info) ++{ ++ struct mlo_glb_per_chip_crash_info *ptlv; ++ u32 tlv_len, tlv_tag; ++ u8 *crash_reason, *recovery_mode; ++ ++ if (ath12k_mgmt_rx_reo_process_tlv_header(ab, data, remaining_len, ++ ATH12K_MLO_SHMEM_TLV_STRUCT_MLO_GLB_PER_CHIP_CRASH_INFO, ++ &tlv_len, &tlv_tag) < 0) { ++ return -EPERM; ++ } ++ ++ ptlv = (struct mlo_glb_per_chip_crash_info *)data; ++ per_chip_crash_info->chip_id = cur_chip_id; ++ crash_reason = (u8 *)get_field_pointer_in_tlv(ptlv, crash_reason, tlv_len); ++ recovery_mode = (u8 *)get_field_pointer_in_tlv(ptlv, recovery_mode, tlv_len); ++ ++ per_chip_crash_info->crash_reason = (void *)crash_reason; ++ per_chip_crash_info->recovery_mode = (void *)recovery_mode; ++ ++ return tlv_len; ++} ++ ++static int ++ath12k_mgmt_mlo_global_chip_crash_info_tlv(struct ath12k_base *ab, ++ u8 *data, ++ size_t remaining_len, ++ struct ath12k_host_mlo_glb_chip_crash_info *global_chip_crash_info) ++{ ++ struct mlo_glb_chip_crash_info *ptlv; ++ u32 tlv_len, tlv_tag; ++ u32 chip_info; ++ u8 chip_map; ++ ++ if (ath12k_mgmt_rx_reo_process_tlv_header(ab, data, remaining_len, ++ ATH12K_MLO_SHMEM_TLV_STRUCT_MLO_GLB_CHIP_CRASH_INFO, ++ &tlv_len, &tlv_tag) < 0) { ++ return -EPERM; ++ } ++ ++ ptlv = (struct mlo_glb_chip_crash_info *)data; ++ chip_info = get_field_value_in_tlv(ptlv, chip_info, tlv_len); ++ global_chip_crash_info->no_of_chips = ++ MLO_SHMEM_CHIP_CRASH_INFO_PARAM_NO_OF_CHIPS_GET(chip_info); ++ chip_map = MLO_SHMEM_CHIP_CRASH_INFO_PARAM_VALID_CHIP_BMAP_GET(chip_info); ++ ++ memcpy(&global_chip_crash_info->valid_chip_bmap, ++ &chip_map, ++ min(sizeof(global_chip_crash_info->valid_chip_bmap), ++ sizeof(chip_map))); ++ ++ /* Allocate memory to extrace per chip crash info */ ++ global_chip_crash_info->per_chip_crash_info = kmalloc_array( ++ global_chip_crash_info->no_of_chips, ++ sizeof(*global_chip_crash_info->per_chip_crash_info), ++ GFP_KERNEL); ++ ++ if (!global_chip_crash_info->per_chip_crash_info) ++ { ++ ath12k_warn(ab, "Couldn't allocate memory for per chip crash info!\n"); ++ return -ENOBUFS; ++ } ++ ++ return tlv_len; ++} ++ ++static int ++ath12k_mgmt_mlo_global_chip_crash_info(struct ath12k_base *ab, ++ u8 *data, ++ size_t remaining_len, ++ struct ath12k_host_mlo_glb_chip_crash_info *global_chip_crash_info) ++{ ++ int parsed_bytes, len, cur_chip_id; ++ u8 chip_id, valid_chip_bmap; ++ ++ len = ath12k_mgmt_mlo_global_chip_crash_info_tlv(ab, data, remaining_len, ++ global_chip_crash_info); ++ ATH12K_VALIDATE_PARSED_DATA_POINTER(len, data, remaining_len); ++ parsed_bytes = len; ++ ++ if (len < 0) ++ return len; ++ ++ memcpy(&valid_chip_bmap, ++ &global_chip_crash_info->valid_chip_bmap, ++ min(sizeof(valid_chip_bmap), ++ sizeof(global_chip_crash_info->valid_chip_bmap))); ++ ++ /* Extract per chip crash info */ ++ for (chip_id = 0; chip_id < global_chip_crash_info->no_of_chips; ++ chip_id++) { ++ cur_chip_id = find_first_bit(&valid_chip_bmap, 8); ++ __clear_bit(cur_chip_id, &valid_chip_bmap); ++ ++ if (WARN_ON(cur_chip_id < 0)) { ++ /* Exit gracefully */ ++ return 0; ++ } ++ ++ len = ath12k_mgmt_mlo_global_per_chip_crash_info_tlv(ab, data, ++ remaining_len, cur_chip_id, ++ &global_chip_crash_info->per_chip_crash_info[chip_id]); ++ if (len < 0) { ++ WARN_ON(1); ++ return len; ++ } ++ ++ ATH12K_VALIDATE_PARSED_DATA_POINTER(len, data, remaining_len); ++ parsed_bytes += len; ++ } ++ ++ return parsed_bytes; ++} ++ + /** + * ath12k_mgmt_rx_reo_extract_mlo_glb_rx_reo_snapshot_info_tlv() - extract + * ATH12K_MLO_SHMEM_TLV_STRUCT_MLO_GLB_RX_REO_SNAPSHOT_INFO TLV +@@ -3917,6 +4052,11 @@ static int ath12k_qmi_parse_mlo_mem_arena(struct ath12k_base *ab, + ATH12K_VALIDATE_PARSED_DATA_POINTER(len, data, remaining_len); + parsed_bytes += len; + ++ len = ath12k_mgmt_mlo_global_chip_crash_info(ab, data, remaining_len, ++ &mlomem_arena_ctx->global_chip_crash_info); ++ ATH12K_VALIDATE_PARSED_DATA_POINTER(len, data, remaining_len); ++ parsed_bytes += len; ++ + return parsed_bytes; + } + +@@ -3927,9 +4067,6 @@ int ath12k_qmi_mlo_global_snapshot_mem_init(struct ath12k_base *ab) + struct target_mem_chunk *mlo_chunk; + int ret = 0, mlo_idx = 0; + +- if (!ag->mgmt_rx_reorder) +- return 0; +- + if (!ag->mlo_mem.is_mlo_mem_avail) + return 0; + +@@ -3957,6 +4094,8 @@ int ath12k_qmi_mlo_global_snapshot_mem_init(struct ath12k_base *ab) + ath12k_err(ab, "parsing of mlo shared memory failed ret %d\n", ret); + ath12k_free_mlo_mgmt_rx_reo_per_link_info( + &mlomem_arena_ctx->rx_reo_snapshot_info); ++ ath12k_free_mlo_glb_per_chip_crash_info ++ (&mlomem_arena_ctx->global_chip_crash_info); + mutex_unlock(&mlomem_arena_ctx->mutex_lock); + return ret; + } +diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h +index e41f414..d385b90 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -5354,6 +5354,32 @@ struct wmi_pdev_update_muedca_event { + + #define WLAN_MGMT_TXRX_HOST_MAX_ANTENNA 4 + ++/** ++ * ath12k_host_mlo_glb_per_chip_crash_info - per chip crash ++ * information in MLO global shared memory ++ * @chip_id: MLO chip id ++ * @crash_reason: Address of the crash_reason corresponding to chip_id ++ * recovery_mode: Address of recovery mode corressponding to chip_id ++ */ ++struct ath12k_host_mlo_glb_per_chip_crash_info { ++ u8 chip_id; ++ void *crash_reason; ++ void *recovery_mode; ++}; ++ ++/** ++ * ath12k_host_mlo_glb_chip_crash_info - chip crash information in MLO ++ * global shared memory ++ * @no_of_chips: No of partner chip to which crash information is shared ++ * @valid_chip_bmap: Valid chip bitmap ++ * @per_chip_crash_info: pointer to per chip crash information. ++ */ ++struct ath12k_host_mlo_glb_chip_crash_info { ++ u8 no_of_chips; ++ u8 valid_chip_bmap; ++ struct ath12k_host_mlo_glb_per_chip_crash_info *per_chip_crash_info; ++}; ++ + /** + * ath12k_host_mlo_glb_rx_reo_snapshot_info - MGMT Rx REO information in MLO + * global shared memory +@@ -5392,6 +5418,7 @@ struct ath12k_host_ath12k_mlo_glb_shmem_params { + struct ath12k_host_mlo_mem_arena { + struct ath12k_host_ath12k_mlo_glb_shmem_params shmem_params; + struct ath12k_host_mlo_glb_rx_reo_snapshot_info rx_reo_snapshot_info; ++ struct ath12k_host_mlo_glb_chip_crash_info global_chip_crash_info; + bool init_done; + /* Protect the parallel initialization */ + struct mutex mutex_lock; +@@ -5501,6 +5528,48 @@ struct mlo_glb_link_info { + */ + }; + ++enum ath12k_mlo_chip_crash_reason { ++ ATH12K_MLO_SHMEM_CRASH_PARTNER_CHIPS = 1, ++}; ++ ++struct mlo_glb_chip_crash_info { ++ /* TLV tag and len; tag equals ++ * MLO_SHMEM_TLV_STRUCT_MLO_GLB_CHIP_CRASH_INFO */ ++ u32 tlv_header; ++ ++ /** ++ * [1:0]: no_of_chips ++ * [4:2]: valid_chip_bmap ++ * For number of chips beyond 3, extension fields are added. ++ * [9:5]: valid_chip_bmap_ext ++ * [15:12]: no_of_chips_ext ++ * [31:16]: reserved ++ */ ++ u32 chip_info; ++ /* ++ * This TLV is followed by array of mlo_glb_per_chip_crash_info: ++ * mlo_glb_per_chip_crash_info will have multiple instances equal to ++ * num of partner chips received by no_of_chips ++ * mlo_glb_per_chip_crash_info per_chip_crash_info[]; ++ */ ++}; ++ ++struct mlo_glb_per_chip_crash_info { ++ /* TLV tag and len; tag equals MLO_SHMEM_TLV_STRUCT_MLO_GLB_PER_CHIP_CRASH_INFO */ ++ u32 tlv_header; ++ ++ /* ++ * crash reason, takes value in enum ath12k_mlo_chip_crash_reason ++ */ ++ u32 crash_reason; ++ ++ /* ++ * recovery mode, takes value in enum ath12k_mlo_recovery_mode ++ */ ++ u32 recovery_mode; ++}; ++ ++ + /* Definition of the complete REO snapshot info */ + struct mlo_glb_rx_reo_snapshot_info { + /* TLV tag and len; tag equals ATH12K_MLO_SHMEM_TLV_STRUCT_MLO_GLB_RX_REO_SNAPSHOT_INFO */ +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/801-02-wifi-ath12k-Add-support-to-set-mode1-to-firmware.patch b/feeds/ipq95xx/mac80211/patches/qca/801-02-wifi-ath12k-Add-support-to-set-mode1-to-firmware.patch new file mode 100644 index 000000000..d4e0482a3 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/801-02-wifi-ath12k-Add-support-to-set-mode1-to-firmware.patch @@ -0,0 +1,107 @@ +From ab991ead97f71238557341f00c495ccc4acce90d Mon Sep 17 00:00:00 2001 +From: Manish Dharanenthiran +Date: Sun, 9 Jul 2023 11:38:59 +0530 +Subject: [PATCH 2/4] wifi: ath12k: Add support to set mode1 to firmware + +In current design, Firmware by default when asserted +will update MODE0 as the mechanism to host in shmem. +Host can modify this by sending FW_HANG command with +MODE1 value set when set_fw_recovery is called, so +that firmware when asserted, will update MODE1 as +value in shmem. + +This change adds support to enable MODE1 recovery +in firmware. If host is mlo_capable, will send +FW_HANG command to all the firmware in the same +group. + +Signed-off-by: Manish Dharanenthiran +--- + drivers/net/wireless/ath/ath12k/debugfs.c | 38 ++++++++++++++++++++++- + drivers/net/wireless/ath/ath12k/wmi.h | 6 ++++ + 2 files changed, 43 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c +index 309e5ec..bac1834 100644 +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -1901,9 +1901,11 @@ static ssize_t ath12k_debug_write_fw_recovery(struct file *file, + size_t count, loff_t *ppos) + { + struct ath12k_base *ab = file->private_data; ++ struct ath12k *ar; ++ struct ath12k_pdev *pdev; + struct ath12k_hw_group *ag; + unsigned int value; +- int ret; ++ int ret, radio_idx, radioup = 0; + int i; + + if (kstrtouint_from_user(user_buf, count, 0, &value)) +@@ -1918,12 +1920,46 @@ static ssize_t ath12k_debug_write_fw_recovery(struct file *file, + } + + ag = ab->ag; ++ ++ if (!value) ++ value = ATH12K_WMI_DISABLE_FW_RECOVERY; ++ else ++ value = (value == ATH12K_FW_RECOVERY_ENABLE_SSR_ONLY) ? ++ ATH12K_WMI_FW_HANG_RECOVERY_MODE1 : ++ ATH12K_WMI_FW_HANG_RECOVERY_MODE0; ++ + if (ag->mlo_capable) { + for (i = 0; i < ag->num_chip; i++) { + ab = ag->ab[i]; + mutex_lock(&ab->core_lock); + ab->fw_recovery_support = value ? true : false; + mutex_unlock(&ab->core_lock); ++ ++ /* ++ * Set MODE0 or MODE 1, if recovery mode addr is valid. ++ * TODO: Instead of checking recovery mode addr from ++ * TLV, need to check WMI caps once the support is ++ * added from FW. ++ */ ++ if (ab->recovery_mode_address) { ++ for (radio_idx = 0; radio_idx < ab->num_radios; radio_idx++) { ++ ++ pdev = &ab->pdevs[radio_idx]; ++ ar = pdev->ar; ++ if (ar && ar->state == ATH12K_STATE_ON) { ++ radioup = 1; ++ break; ++ } ++ } ++ ++ if (radioup) { ++ ret = ath12k_wmi_force_fw_hang_cmd(ar, ++ value, ++ ATH12K_WMI_FW_HANG_DELAY, false); ++ ath12k_info(ab, "setting FW assert mode [%d] ret [%d]\n", value, ret); ++ } else ++ continue; ++ } + } + } else + ab->fw_recovery_support = value ? true : false; +diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h +index d385b90..f8b9627 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -4105,6 +4105,12 @@ enum wmi_sta_ps_mode { + #define ATH12K_WMI_FW_HANG_ASSERT_TYPE 1 + #define ATH12K_WMI_FW_HANG_DELAY 0 + ++enum wmi_fw_hang_recovery_mode_type { ++ ATH12K_WMI_DISABLE_FW_RECOVERY = 200, ++ ATH12K_WMI_FW_HANG_RECOVERY_MODE0, ++ ATH12K_WMI_FW_HANG_RECOVERY_MODE1, ++}; ++ + /* type, 0:unused 1: ASSERT 2: not respond detect command + * delay_time_ms, the simulate will delay time + */ +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/801-03-wifi-ath12k-Add-support-to-send-umac_reset-flag.patch b/feeds/ipq95xx/mac80211/patches/qca/801-03-wifi-ath12k-Add-support-to-send-umac_reset-flag.patch new file mode 100644 index 000000000..7a5356b3e --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/801-03-wifi-ath12k-Add-support-to-send-umac_reset-flag.patch @@ -0,0 +1,288 @@ +From 52ffb81a8a5a7b81ab2fc471a61589aea26eae78 Mon Sep 17 00:00:00 2001 +From: Manish Dharanenthiran +Date: Sun, 9 Jul 2023 11:42:11 +0530 +Subject: [PATCH 3/4] wifi: ath12k: Add support to send umac_reset flag + +This change set adds support to send umac_reset +flag during mlo teardown message. This will be +utilized when MODE1 recovery is selected, thus +for the non-asserted partner chips, only umac +reset is triggered instead of triggering Q6 assert. + +Signed-off-by: Manish Dharanenthiran +--- + drivers/net/wireless/ath/ath12k/core.c | 33 +++++++++++++++- + drivers/net/wireless/ath/ath12k/core.h | 4 ++ + drivers/net/wireless/ath/ath12k/mac.c | 52 ++++++++++++++++++++++++-- + drivers/net/wireless/ath/ath12k/mac.h | 1 + + drivers/net/wireless/ath/ath12k/wmi.c | 22 ++++++++++- + drivers/net/wireless/ath/ath12k/wmi.h | 3 +- + 6 files changed, 107 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c +index 1cbe9b4..ef136f9 100644 +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -1502,8 +1502,10 @@ static int ath12k_core_hw_group_start(struct ath12k_hw_group *ag) + mutex_unlock(&ab->core_lock); + } + +- if (!is_registered) ++ if (!is_registered) { + set_bit(ATH12K_FLAG_REGISTERED, &ag->dev_flags); ++ init_completion(&ag->umac_reset_complete); ++ } + + return 0; + +@@ -2128,6 +2130,35 @@ static int ath12k_rproc_recovery_power_up(struct ath12k_base *ab) + return 0; + } + ++/* ++ * Trigger umac_reset with umac_reset flag set. This is a ++ * waiting function which will return only after UMAC reset ++ * is complete on non-asserted chip set. UMAC reset completion ++ * is identified by waiting for MLO Teardown complete for all ++ * chipsets ++ */ ++int ath12k_core_trigger_umac_reset(struct ath12k_base *ab) ++{ ++ struct ath12k_hw_group *ag = ab->ag; ++ long time_left; ++ unsigned long timeout; ++ ++ reinit_completion(&ag->umac_reset_complete); ++ ++ ath12k_mac_mlo_teardown_with_umac_reset(ab); ++ ++ timeout = jiffies + msecs_to_jiffies(ATH12K_UMAC_RESET_TIMEOUT_IN_MS); ++ ++ time_left = wait_for_completion_timeout(&ag->umac_reset_complete, ++ timeout); ++ ++ if (!time_left) { ++ ath12k_warn(ab, "UMAC reset didn't get completed within 200 ms\n"); ++ return -ETIMEDOUT; ++ } ++ return 0; ++} ++ + #ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT + static void ath12k_core_disable_ds_rtnl_bond_release(struct ath12k_base *ab) + { +diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h +index 0736948..777308e 100644 +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -57,6 +57,7 @@ extern unsigned int ath12k_frame_mode; + #define ATH12K_RESET_FAIL_TIMEOUT_HZ (20 * HZ) + #define ATH12K_RECONFIGURE_TIMEOUT_HZ (10 * HZ) + #define ATH12K_RECOVER_START_TIMEOUT_HZ (20 * HZ) ++#define ATH12K_UMAC_RESET_TIMEOUT_IN_MS 200 + + #define INVALID_CIPHER 0xFFFFFFFF + +@@ -1283,6 +1284,8 @@ struct ath12k_hw_group { + struct ath12k_host_mlo_mem_arena mlomem_arena; + atomic_t num_dp_tx_pending; + struct ath12k_mlo_dp_umac_reset mlo_umac_reset; ++ struct completion umac_reset_complete; ++ bool trigger_umac_reset; + }; + + /* Master structure to hold the hw data which may be used in core module */ +@@ -1464,6 +1467,7 @@ struct ath12k_base { + u32 *crash_info_address; + u32 *recovery_mode_address; + ++ bool mlo_complete_event; + /* must be last */ + u8 drv_priv[0] __aligned(sizeof(void *)); + }; +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index 47c1b0c..e44ba2e 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -9361,12 +9361,12 @@ static int __ath12k_mac_mlo_setup(struct ath12k *ar) + return 0; + } + +-static int __ath12k_mac_mlo_teardown(struct ath12k *ar) ++static int __ath12k_mac_mlo_teardown(struct ath12k *ar, bool umac_reset) + { + struct ath12k_base *ab = ar->ab; + int ret; + +- ret = ath12k_wmi_mlo_teardown(ar); ++ ret = ath12k_wmi_mlo_teardown(ar, umac_reset); + if (ret) { + ath12k_err(ab, "failed to teardown MLO for pdev_idx %d: %d\n", + ar->pdev_idx, ret); +@@ -9400,7 +9400,7 @@ int ath12k_mac_mlo_setup(struct ath12k_hw *ah) + err_setup: + ar = ah->radio; + for (i = i - 1; i >= 0; i--) { +- fbret = __ath12k_mac_mlo_teardown(ar); ++ fbret = __ath12k_mac_mlo_teardown(ar, false); + if (fbret) + ath12k_err(ar->ab, "MLO teardown failed %d in setup cleanup\n", + fbret); +@@ -9587,7 +9587,7 @@ int ath12k_mac_mlo_teardown(struct ath12k_hw *ah) + + ar = ah->radio; + for (i = 0; i < ah->num_radio; i++) { +- ret = __ath12k_mac_mlo_teardown(ar); ++ ret = __ath12k_mac_mlo_teardown(ar, false); + if (ret) + goto out; + +@@ -9598,6 +9598,50 @@ out: + return ret; + } + ++int ath12k_mac_mlo_teardown_with_umac_reset(struct ath12k_base *ab) ++{ ++ struct ath12k_hw_group *ag = ab->ag; ++ struct ath12k_base *partner_ab; ++ struct ath12k *ar; ++ struct ath12k_pdev *pdev; ++ int i, j, ret = 0; ++ bool umac_reset; ++ ++ for (i = 0; i < ag->num_chip; i++) { ++ partner_ab = ag->ab[i]; ++ ++ if (ab == partner_ab) { ++ /* No need to send teardown event for asserted chip, as ++ * anyway there will be no completion event from FW. ++ */ ++ ab->mlo_complete_event = true; ++ continue; ++ } ++ ++ for (j = 0; j < partner_ab->num_radios; j++) { ++ pdev = &partner_ab->pdevs[j]; ++ ar = pdev->ar; ++ ++ if (!ar) ++ continue; ++ ++ /* Need to umac_reset as 1 for only one chip */ ++ umac_reset = false; ++ if (!ag->trigger_umac_reset) { ++ umac_reset = true; ++ ag->trigger_umac_reset = true; ++ } ++ ++ ret = __ath12k_mac_mlo_teardown(ar, umac_reset); ++ if (ret) ++ goto out; ++ } ++ } ++ ++out: ++ return ret; ++} ++ + static void ath12k_mac_radio_stop(struct ath12k *ar) + { + struct ath12k_base *ab = ar->ab; +diff --git a/drivers/net/wireless/ath/ath12k/mac.h b/drivers/net/wireless/ath/ath12k/mac.h +index 3d18dd4..13d7a4a 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.h ++++ b/drivers/net/wireless/ath/ath12k/mac.h +@@ -238,4 +238,5 @@ u16 ath12k_calculate_subchannel_count(enum nl80211_chan_width width); + void ath12k_mac_background_dfs_event(struct ath12k *ar, + enum ath12k_background_dfs_events ev); + bool ath12k_mac_tx_check_max_limit(struct ath12k *ar, struct sk_buff *skb); ++int ath12k_mac_mlo_teardown_with_umac_reset(struct ath12k_base *ab); + #endif +diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c +index 8db45be..0d97d0c 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -13147,7 +13147,9 @@ static void ath12k_wmi_event_teardown_complete(struct ath12k_base *ab, + { + const void **tb; + const struct wmi_mlo_teardown_complete_fixed_param *ev; +- int ret; ++ struct ath12k_hw_group *ag = ab->ag; ++ int ret, i; ++ bool complete_flag = true; + + tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); + if (IS_ERR(tb)) { +@@ -13170,6 +13172,19 @@ static void ath12k_wmi_event_teardown_complete(struct ath12k_base *ab, + ev->pdev_id, ev->status); + + kfree(tb); ++ ++ ab->mlo_complete_event = true; ++ for (i = 0; i < ag->num_chip; i++) { ++ ab = ag->ab[i]; ++ ++ if (!ab->mlo_complete_event) ++ complete_flag = false; ++ } ++ ++ if (complete_flag) { ++ complete(&ag->umac_reset_complete); ++ ag->trigger_umac_reset = false; ++ } + } + + static void ath12k_wmi_process_mvr_event(struct ath12k *ab, u32 *vdev_id_bm, +@@ -14111,6 +14126,7 @@ int ath12k_wmi_mlo_setup(struct ath12k *ar, + dev_kfree_skb(skb); + } + ++ ar->ab->mlo_complete_event = false; + return ret; + } + +@@ -14138,10 +14154,11 @@ int ath12k_wmi_mlo_ready(struct ath12k *ar) + dev_kfree_skb(skb); + } + ++ ar->ab->mlo_complete_event = false; + return ret; + } + +-int ath12k_wmi_mlo_teardown(struct ath12k *ar) ++int ath12k_wmi_mlo_teardown(struct ath12k *ar, bool umac_reset) + { + struct ath12k_pdev_wmi *wmi = ar->wmi; + struct wmi_mlo_teardown_fixed_param *cmd; +@@ -14158,6 +14175,7 @@ int ath12k_wmi_mlo_teardown(struct ath12k *ar) + FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); + cmd->pdev_id = ar->pdev->pdev_id; + cmd->reason_code = WMI_MLO_TEARDOWN_SSR_REASON; ++ cmd->umac_reset = umac_reset; + + ret = ath12k_wmi_cmd_send(wmi, skb, WMI_MLO_TEARDOWN_CMDID); + if (ret) { +diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h +index f8b9627..e2fea00 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -8192,6 +8192,7 @@ struct wmi_mlo_teardown_fixed_param { + u32 tlv_header; + u32 pdev_id; + u32 reason_code; ++ u32 umac_reset; + } __packed; + + struct wmi_mlo_setup_complete_event_fixed_param { +@@ -8540,7 +8541,7 @@ int ath12k_wmi_send_wmi_ctrl_stats_cmd(struct ath12k *ar, + int ath12k_wmi_mlo_setup(struct ath12k *ar, + struct wmi_mlo_setup_params *mlo_params); + int ath12k_wmi_mlo_ready(struct ath12k *ar); +-int ath12k_wmi_mlo_teardown(struct ath12k *ar); ++int ath12k_wmi_mlo_teardown(struct ath12k *ar, bool umac_reset); + bool ath12k_wmi_is_mvr_supported(struct ath12k_base *ab); + int ath12k_wmi_pdev_multiple_vdev_restart(struct ath12k *ar, + struct wmi_pdev_multiple_vdev_restart_req_arg *arg); +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/801-04-wifi-ath12k-Add-support-for-Mode-1-recovery-cache.patch b/feeds/ipq95xx/mac80211/patches/qca/801-04-wifi-ath12k-Add-support-for-Mode-1-recovery-cache.patch new file mode 100644 index 000000000..6188f1c6f --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/801-04-wifi-ath12k-Add-support-for-Mode-1-recovery-cache.patch @@ -0,0 +1,2195 @@ +From ae5e678c404d727c9dba7a687bacd3b098e85f82 Mon Sep 17 00:00:00 2001 +From: Manish Dharanenthiran +Date: Mon, 10 Jul 2023 23:51:46 +0530 +Subject: [PATCH] wifi: ath12k: Add support for Mode 1 recovery cache + +This patchset adds support for Mode 1 recovery +mechanism where only asserted chip will be recovered +bypassing the mac80211 recovery mechanism. + +Client connected to asserted chip will be disconnected/traffic +will be impacted. For clients in non-asserted chips +will be differentiated between MLO and legacy clients. +All MLO clients will be disconnected and legacy client +will be in connection but there will be minimal ping +drop during umac reset. + +Signed-off-by: Manish Dharanenthiran +--- + drivers/net/wireless/ath/ath12k/core.c | 857 +++++++++++++++++++++++- + drivers/net/wireless/ath/ath12k/core.h | 13 +- + drivers/net/wireless/ath/ath12k/debug.h | 1 + + drivers/net/wireless/ath/ath12k/mac.c | 411 ++++++++---- + drivers/net/wireless/ath/ath12k/mac.h | 40 ++ + drivers/net/wireless/ath/ath12k/peer.c | 2 +- + drivers/net/wireless/ath/ath12k/peer.h | 1 + + drivers/net/wireless/ath/ath12k/wmi.c | 13 +- + drivers/net/wireless/ath/ath12k/wmi.h | 4 + + 9 files changed, 1204 insertions(+), 138 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -11,6 +11,7 @@ + #include + #include + ++#include "peer.h" + #include "core.h" + #include "coredump.h" + #include "dp_tx.h" +@@ -59,8 +60,7 @@ unsigned int ath12k_ppe_ds_enabled = fal + module_param_named(ppe_ds_enable, ath12k_ppe_ds_enabled, uint, 0644); + MODULE_PARM_DESC(ppe_ds_enable, "ppe_ds_enable: 0-disable, 1-enable"); + +-static unsigned int ath12k_recovery_mode = ATH12K_MLO_RECOVERY_MODE0; +-unsigned int ath12k_ssr_failsafe_mode = false; ++unsigned int ath12k_ssr_failsafe_mode = true; + module_param_named(ssr_failsafe_mode, ath12k_ssr_failsafe_mode, uint, 0644); + MODULE_PARM_DESC(ssr_failsafe_mode, "ssr failsafe mode: 0-disable, 1-enable"); + +@@ -162,6 +162,7 @@ ath12k_core_hw_group_alloc(u8 id, u8 max + mutex_init(&ag->mutex_lock); + mutex_init(&ag->mlomem_arena.mutex_lock); + ag->hw_queues_stopped = false; ++ ag->recovery_mode = ATH12K_MLO_RECOVERY_MODE0; + + return ag; + } +@@ -1432,6 +1433,12 @@ static int ath12k_core_hw_group_start(st + for (i = 0; i < ag->num_chip; i++) { + ab = ag->ab[i]; + ++ /* pdev create needs to be done only for recovered ++ * ab during Mode1 scenario ++ */ ++ if (ag->recovery_mode == ATH12K_MLO_RECOVERY_MODE1 && !ab->recovery_start) ++ continue; ++ + mutex_lock(&ab->core_lock); + ret = ath12k_core_pdev_create(ab); + if (ret) { +@@ -1460,6 +1467,12 @@ static int ath12k_core_hw_group_start(st + for (i = 0; i < ag->num_chip; i++) { + ab = ag->ab[i]; + ++ /* pdev init needs to be done only for recovered ++ * ab during Mode1 scenario ++ */ ++ if (ag->recovery_mode == ATH12K_MLO_RECOVERY_MODE1 && !ab->recovery_start) ++ continue; ++ + mutex_lock(&ab->core_lock); + + ret = ath12k_core_pdev_init(ab); +@@ -1575,7 +1588,7 @@ static void ath12k_core_trigger_partner( + ab->qmi.num_radios, ag->num_chip); + + if (found) { +- if (ath12k_recovery_mode == ATH12K_MLO_RECOVERY_MODE0 && ++ if (ag->recovery_mode == ATH12K_MLO_RECOVERY_MODE0 && + !test_bit(ATH12K_FLAG_QMI_HOST_CAP_SENT, &partner_ab->dev_flags)) { + ath12k_qmi_trigger_host_cap(partner_ab); + } +@@ -1846,6 +1859,7 @@ static int ath12k_core_reconfigure_on_cr + + ath12k_dp_free(ab); + ath12k_hal_srng_deinit(ab); ++ ath12k_dp_umac_reset_deinit(ab); + ath12k_umac_reset_completion(ab); + + ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS)) - 1; +@@ -1866,7 +1880,8 @@ err_hal_srng_deinit: + return ret; + } + +-static void ath12k_core_mlo_hw_queues_stop(struct ath12k_hw_group *ag) ++static void ath12k_core_mlo_hw_queues_stop(struct ath12k_hw_group *ag, ++ struct ath12k_base *block_ab) + { + struct ath12k_base *ab; + struct ath12k_hw *ah; +@@ -1883,6 +1898,12 @@ static void ath12k_core_mlo_hw_queues_st + } + ag->hw_queues_stopped = true; + ++ if (ag->recovery_mode == ATH12K_MLO_RECOVERY_MODE1) { ++ block_ab->qmi.num_radios = ATH12K_QMI_INVALID_RADIO; ++ clear_bit(ATH12K_FLAG_QMI_HOST_CAP_SENT, &block_ab->dev_flags); ++ return; ++ } ++ + for (i = 0; i < ag->num_chip; i++) { + ab = ag->ab[i]; + +@@ -1890,7 +1911,7 @@ static void ath12k_core_mlo_hw_queues_st + * In Mode0, partner chips are expected to be asserted, hence reset + * qmi.num_radios count to ensure avoiding duplicate host cap triggers. + */ +- if (ath12k_recovery_mode == ATH12K_MLO_RECOVERY_MODE0) { ++ if (ag->recovery_mode == ATH12K_MLO_RECOVERY_MODE0) { + ab->qmi.num_radios = ATH12K_QMI_INVALID_RADIO; + clear_bit(ATH12K_FLAG_QMI_HOST_CAP_SENT, &ab->dev_flags); + } +@@ -2004,6 +2025,7 @@ static void ath12k_core_post_reconfigure + void ath12k_core_halt(struct ath12k *ar) + { + struct ath12k_base *ab = ar->ab; ++ struct ath12k_hw_group *ag = ab->ag; + + lockdep_assert_held(&ar->conf_mutex); + +@@ -2014,16 +2036,730 @@ void ath12k_core_halt(struct ath12k *ar) + cancel_work_sync(&ar->regd_update_work); + rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], NULL); + synchronize_rcu(); +- INIT_LIST_HEAD(&ar->arvifs); ++ ++ if (ag->recovery_mode == ATH12K_MLO_RECOVERY_MODE0) ++ INIT_LIST_HEAD(&ar->arvifs); ++ + idr_init(&ar->txmgmt_idr); + } + ++static int ath12k_core_mode1_recovery_sta_list(void *data, ++ struct ieee80211_sta *sta) ++{ ++ struct ath12k_link_sta *arsta; ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_link_vif *arvif = (struct ath12k_link_vif *)data; ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ieee80211_vif *vif = ahvif->vif; ++ struct ath12k *ar = arvif->ar; ++ struct ath12k_base *ab = arvif->ab; ++ struct ath12k_key_conf *key_conf = NULL; ++ struct ath12k_peer *peer; ++ struct ieee80211_key_conf *key; ++ int ret = -1, key_idx; ++ u8 link_id = arvif->link_id; ++ enum ieee80211_sta_state state, prev_state; ++ bool sta_added = false; ++ ++ if (ahsta->ahvif != arvif->ahvif) ++ return -1; ++ ++ /* Check if there is a link sta in the vif link */ ++ if (!(BIT(link_id) & ahsta->links_map)) ++ return -1; ++ ++ /* From iterator, rcu_read_lock is acquired. Will be revisited ++ * later to use local list ++ */ ++ arsta = ahsta->link[link_id]; ++ ++ key_conf = container_of((void *)sta, struct ath12k_key_conf, sta); ++ ++ if (vif->type != NL80211_IFTYPE_AP && ++ vif->type != NL80211_IFTYPE_AP_VLAN) ++ return 0; ++ ++ peer = ath12k_peer_find(ar->ab, arvif->vdev_id, arsta->addr); ++ if (peer) { ++ sta_added = true; ++ goto key_add; ++ } ++ ++ prev_state = arsta->state; ++ for (state = IEEE80211_STA_NOTEXIST; ++ state < prev_state; state++) { ++ /* all station set case */ ++ /* TODO: Iterator API is called with rcu lock ++ * hence need for this unlock/lock statement. ++ * Need to revisit in next version ++ */ ++ rcu_read_unlock(); ++ ath12k_mac_update_sta_state(ar->ah->hw, arvif->ahvif->vif, sta, ++ state, (state + 1)); ++ rcu_read_lock(); ++ sta_added = true; ++ } ++ ++key_add: ++ if (sta_added) ++ for (key_idx = 0; key_idx < WMI_MAX_KEY_INDEX; key_idx++) { ++ key = arsta->keys[key_idx]; ++ ++ if (key) { ++ /* BIP needs to be done in software */ ++ if (key->cipher == WLAN_CIPHER_SUITE_AES_CMAC || ++ key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 || ++ key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 || ++ key->cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256) { ++ ret = 1; ++ goto out; ++ } ++ ++ if (test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ab->ag->dev_flags)) { ++ ret = 1; ++ goto out; ++ } ++ ++ if (!arvif->is_created) { ++ key_conf = kzalloc(sizeof(*key_conf), GFP_ATOMIC); ++ ++ if (!key_conf) { ++ ath12k_info(NULL, "failed to alloc cache key config\n"); ++ goto out; ++ } ++ ++ key_conf->cmd = SET_KEY; ++ key_conf->sta = sta; ++ key_conf->key = key; ++ ++ list_add_tail(&key_conf->list, ++ &ahvif->cache[link_id].key_conf.list); ++ ++ ath12k_info(NULL, "set key param cached since vif not assign to radio\n"); ++ goto out; ++ } ++ ++ if (sta->mlo) { ++ for_each_set_bit(link_id, &sta->valid_links, IEEE80211_MLD_MAX_NUM_LINKS) { ++ arvif = ahvif->link[link_id]; ++ arsta = ahsta->link[link_id]; ++ if (WARN_ON(!arvif || !arsta)) ++ continue; ++ ++ /* TODO: Iterator API is called with rcu lock ++ * hence need for this unlock/lock statement. ++ * Need to revisit in next version ++ */ ++ rcu_read_unlock(); ++ ret = ath12k_mac_set_key(arvif->ar, SET_KEY, arvif, arsta, key); ++ rcu_read_lock(); ++ if (ret) ++ break; ++ arsta->keys[key->keyidx] = key; ++ } ++ } else { ++ arsta = &ahsta->deflink; ++ arvif = arsta->arvif; ++ if (WARN_ON(!arvif)) ++ goto out; ++ ++ /* TODO: Iterator API is called with rcu lock ++ * hence need for this unlock/lock statement. ++ * Need to revisit in next version ++ */ ++ rcu_read_unlock(); ++ ret = ath12k_mac_set_key(arvif->ar, SET_KEY, arvif, arsta, key); ++ rcu_read_lock(); ++ arsta->keys[key->keyidx] = key; ++ } ++ } ++ } ++ ++ ath12k_dbg(ab, ATH12K_DBG_MODE1_RECOVERY, ++ "Recovered sta:%pM link_id:%d, num_sta:%d\n", ++ arsta->addr, arsta->link_id, arvif->ar->num_stations); ++ ++ ret = 0; ++out: ++ return ret; ++} ++ ++static int ath12k_mlo_recovery_link_vif_reconfig(struct ath12k *ar, ++ struct ath12k_vif *ahvif, ++ struct ath12k_link_vif *arvif, ++ struct ieee80211_vif *vif, ++ struct ieee80211_bss_conf *link_conf) ++{ ++ int i; ++ int link_id = arvif->link_id; ++ struct ath12k_hw *ah = ar->ah; ++ struct ieee80211_tx_queue_params params; ++ struct wmi_wmm_params_arg *p = NULL; ++ u64 changed = 0; ++ ++ mutex_lock(&ah->conf_mutex); ++ ++ switch (vif->type) { ++ case NL80211_IFTYPE_AP_VLAN: ++ case NL80211_IFTYPE_MONITOR: ++ break; ++ case NL80211_IFTYPE_ADHOC: ++ fallthrough; ++ default: ++ ieee80211_iterate_stations_atomic(ar->ah->hw, ++ ath12k_core_mode1_recovery_sta_list, ++ arvif); ++ fallthrough; ++ case NL80211_IFTYPE_AP: /* AP stations are handled later */ ++ for (i = 0; i < IEEE80211_NUM_ACS; i++) { ++ ++ if ((vif->active_links && ++ !(vif->active_links & BIT(link_id))) || ++ (link_id >= IEEE80211_MLD_MAX_NUM_LINKS)) ++ break; ++ ++ switch (i) { ++ case IEEE80211_AC_VO: ++ p = &arvif->wmm_params.ac_vo; ++ break; ++ case IEEE80211_AC_VI: ++ p = &arvif->wmm_params.ac_vi; ++ break; ++ case IEEE80211_AC_BE: ++ p = &arvif->wmm_params.ac_be; ++ break; ++ case IEEE80211_AC_BK: ++ p = &arvif->wmm_params.ac_bk; ++ break; ++ } ++ ++ params.cw_min = p->cwmin; ++ params.cw_max = p->cwmax; ++ params.aifs = p->aifs; ++ params.txop = p->txop; ++ ++ mutex_lock(&ar->conf_mutex); ++ ath12k_mac_conf_tx(ar, arvif, i, ¶ms); ++ mutex_unlock(&ar->conf_mutex); ++ } ++ break; ++ } ++ ++ /* common change flags for all interface types */ ++ changed = BSS_CHANGED_ERP_CTS_PROT | ++ BSS_CHANGED_ERP_PREAMBLE | ++ BSS_CHANGED_ERP_SLOT | ++ BSS_CHANGED_HT | ++ BSS_CHANGED_BASIC_RATES | ++ BSS_CHANGED_BEACON_INT | ++ BSS_CHANGED_BSSID | ++ BSS_CHANGED_CQM | ++ BSS_CHANGED_QOS | ++ BSS_CHANGED_IDLE | ++ BSS_CHANGED_TXPOWER | ++ BSS_CHANGED_MCAST_RATE; ++ ++ if (link_conf->mu_mimo_owner) ++ changed |= BSS_CHANGED_MU_GROUPS; ++ ++ switch (vif->type) { ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ case NL80211_IFTYPE_DUMMY: ++ mutex_unlock(&ah->conf_mutex); ++ return 0; ++#endif ++ case NL80211_IFTYPE_STATION: ++ changed |= BSS_CHANGED_ASSOC | ++ BSS_CHANGED_ARP_FILTER | ++ BSS_CHANGED_PS; ++ ++ /* Assume re-send beacon info report to the driver */ ++ changed |= BSS_CHANGED_BEACON_INFO; ++ ++ if (link_conf->max_idle_period || ++ link_conf->protected_keep_alive) ++ changed |= BSS_CHANGED_KEEP_ALIVE; ++ ++ if (!arvif->is_created) { ++ ath12k_info(NULL, ++ "bss info parameter changes %llx cached to apply after vdev create on channel assign\n", ++ changed); ++ ++ ahvif->cache[link_id].bss_conf_changed |= changed; ++ mutex_unlock(&ah->conf_mutex); ++ return 0; ++ } ++ ++ mutex_lock(&ar->conf_mutex); ++ ath12k_mac_bss_info_changed(ar, arvif, link_conf, changed); ++ mutex_unlock(&ar->conf_mutex); ++ break; ++ case NL80211_IFTYPE_OCB: ++ changed |= BSS_CHANGED_OCB; ++ ++ mutex_lock(&ar->conf_mutex); ++ ath12k_mac_bss_info_changed(ar, arvif, link_conf, changed); ++ mutex_unlock(&ar->conf_mutex); ++ break; ++ case NL80211_IFTYPE_ADHOC: ++ changed |= BSS_CHANGED_IBSS; ++ fallthrough; ++ case NL80211_IFTYPE_AP: ++ changed |= BSS_CHANGED_P2P_PS; ++ ++ if (vif->type == NL80211_IFTYPE_AP) { ++ changed |= BSS_CHANGED_AP_PROBE_RESP; ++ ahvif->u.ap.ssid_len = vif->cfg.ssid_len; ++ if (vif->cfg.ssid_len) ++ memcpy(ahvif->u.ap.ssid, vif->cfg.ssid, vif->cfg.ssid_len); ++ } ++ fallthrough; ++ case NL80211_IFTYPE_MESH_POINT: ++ if (link_conf->enable_beacon) { ++ changed |= BSS_CHANGED_BEACON | ++ BSS_CHANGED_BEACON_ENABLED; ++ ++ mutex_lock(&ar->conf_mutex); ++ ath12k_mac_bss_info_changed(ar, arvif, link_conf, ++ changed &~ BSS_CHANGED_IDLE); ++ mutex_unlock(&ar->conf_mutex); ++ ++ } ++ break; ++ case NL80211_IFTYPE_NAN: ++ case NL80211_IFTYPE_AP_VLAN: ++ case NL80211_IFTYPE_MONITOR: ++ case NL80211_IFTYPE_P2P_DEVICE: ++ /* nothing to do */ ++ break; ++ case NL80211_IFTYPE_UNSPECIFIED: ++ case NUM_NL80211_IFTYPES: ++ case NL80211_IFTYPE_P2P_CLIENT: ++ case NL80211_IFTYPE_P2P_GO: ++ case NL80211_IFTYPE_WDS: ++ WARN_ON(1); ++ break; ++ } ++ ++ mutex_unlock(&ah->conf_mutex); ++ ath12k_dbg(ar->ab, ATH12K_DBG_MODE1_RECOVERY, "Reconfig link vif done:type:%d\n", vif->type); ++ return 0; ++} ++ ++static int ath12k_mlo_core_recovery_reconfig_link_bss(struct ath12k *ar, ++ struct ieee80211_bss_conf *link_conf, ++ struct ath12k_vif *ahvif, ++ struct ath12k_link_vif *arvif) ++{ ++ struct ieee80211_vif *vif = arvif->ahvif->vif; ++ struct ath12k_base *ab = ar->ab; ++ struct ath12k_hw *ah = ar->ah; ++ enum ieee80211_ap_reg_power power_type; ++ struct peer_create_params param; ++ struct ieee80211_chanctx_conf *ctx = &arvif->chanctx; ++ int ret = -1; ++ u8 link_id = link_conf->link_id; ++ ++ ++ ath12k_dbg(ab, ATH12K_DBG_MODE1_RECOVERY, ++ "Recovering: link_id:%d [vif->link_id:%d] type:%d\n", ++ link_id, arvif->link_id, vif->type); ++ ++ mutex_lock(&ah->conf_mutex); ++ ++ if (vif->type == NL80211_IFTYPE_AP && ++ ar->num_peers > (ar->max_num_peers - 1)) { ++ ath12k_err(ab, "Error in peers:%d\n", ++ ar->num_peers); ++ goto exit; ++ } ++ ++ if (ar->num_created_vdevs > (TARGET_NUM_VDEVS - 1)) { ++ ath12k_err(ab, "failed to create vdev, reached max vdev limit %d[%d]\n", ++ ar->num_created_vdevs, ++ TARGET_NUM_VDEVS); ++ goto exit; ++ } ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ ret = ath12k_mac_vdev_create(ar, arvif); ++ if (!ret) ++ ath12k_mac_vif_cache_flush(ar, vif, arvif->link_id); ++ ++ if (ar->supports_6ghz && ctx->def.chan->band == NL80211_BAND_6GHZ && ++ (ahvif->vdev_type == WMI_VDEV_TYPE_STA || ++ ahvif->vdev_type == WMI_VDEV_TYPE_AP)) { ++ power_type = link_conf->power_type; ++ ath12k_dbg(ab, ATH12K_DBG_MAC, "mac chanctx power type %d\n", ++ power_type); ++ if (power_type == IEEE80211_REG_UNSET_AP) ++ power_type = IEEE80211_REG_LPI_AP; ++ ++ /* TODO: Transmit Power Envelope specification for 320 is not ++ * available yet. Need to add TPE 320 support when spec is ready ++ */ ++ if (ahvif->vdev_type == WMI_VDEV_TYPE_STA && ++ ctx->def.width != NL80211_CHAN_WIDTH_320) { ++ ath12k_mac_parse_tx_pwr_env(ar, arvif, ctx); ++ } ++ } ++ ++ /* for some targets bss peer must be created before vdev_start */ ++ if (ab->hw_params->vdev_start_delay && ++ ahvif->vdev_type != WMI_VDEV_TYPE_AP && ++ ahvif->vdev_type != WMI_VDEV_TYPE_MONITOR && ++ !ath12k_peer_find_by_vdev_id(ab, arvif->vdev_id)) { ++ ret = 0; ++ goto exit; ++ } ++ ++ if (ab->hw_params->vdev_start_delay && ++ (ahvif->vdev_type == WMI_VDEV_TYPE_AP || ++ ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR)) { ++ param.vdev_id = arvif->vdev_id; ++ param.peer_type = WMI_PEER_TYPE_DEFAULT; ++ param.peer_addr = ar->mac_addr; ++ ++ ret = ath12k_peer_create(ar, arvif, NULL, ¶m); ++ if (ret) { ++ ath12k_warn(ab, "failed to create peer after vdev start delay: %d", ++ ret); ++ goto exit; ++ } ++ } ++ ++ if (ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { ++ ret = ath12k_mac_monitor_start(ar); ++ if (ret) ++ goto exit; ++ arvif->is_started = true; ++ goto exit; ++ } ++ ++ if (ath12k_mac_is_ml_arvif(arvif) && ++ ahvif->vdev_type == WMI_VDEV_TYPE_AP) { ++ mutex_unlock(&ar->conf_mutex); ++ ret = ath12k_mac_mlo_vdev_start(arvif, false); ++ mutex_lock(&ar->conf_mutex); ++ goto exit; ++ } ++ ++ ret = ath12k_mac_vdev_start(arvif, &ctx->def, ctx->radar_enabled); ++ if (ret) { ++ ath12k_err(ab, "vdev start failed during recovery\n"); ++ goto exit; ++ } ++ ++ if (ahvif->vdev_type != WMI_VDEV_TYPE_MONITOR && ++ test_bit(MONITOR_VDEV_CREATED, &ar->monitor_flags)) ++ ath12k_mac_monitor_start(ar); ++ ++ arvif->is_started = true; ++ arvif->is_created = true; ++ ++ ret = 0; ++exit: ++ ath12k_dbg(ab, ATH12K_DBG_MODE1_RECOVERY, ++ "ret:%d No. of vdev created:%d, links_map:%d, flag:%d\n", ++ ret, ++ ahvif->num_vdev_created, ++ ahvif->links_map, ++ arvif->is_created); ++ ++ mutex_unlock(&ar->conf_mutex); ++ mutex_unlock(&ah->conf_mutex); ++ ++ return ret; ++} ++ ++/* Wrapper function for recovery after crash */ ++int ath12k_mode1_recovery_reconfig(struct ath12k_base *ab, const char *fun) ++{ ++ struct ath12k *ar = NULL; ++ struct ath12k_pdev *pdev; ++ struct ath12k_link_vif *arvif, *tmp; ++ struct ath12k_vif *ahvif ; ++ struct ieee80211_bss_conf *link; ++ struct ath12k_hw_group *ag = ab->ag; ++ struct ath12k_base *partner_ab; ++ struct ath12k_hw *ah; ++ struct ieee80211_key_conf *key; ++ int i, j, key_idx; ++ u32 changed = 0; ++ int ret = -EINVAL; ++ bool started = false; ++ ++ for (j = 0; j < ab->num_radios; j++) { ++ pdev = &ab->pdevs[j]; ++ ar = pdev->ar; ++ ++ if (WARN_ON(!ar)) ++ continue; ++ ++ if (!ath12k_ftm_mode) { ++ if (ath12k_mac_radio_start(ar)) { ++ ath12k_err(ab, "mac radio start failed\n"); ++ return ret; ++ } ++ ar->ah->in_recovery = true; ++ started = true; ++ } ++ ++ if (list_empty(&ar->arvifs)) ++ continue; ++ ++ /* Decrement number of vdev created for all the arvif ++ * under a ar ++ */ ++ list_for_each_entry_safe_reverse(arvif, tmp, &ar->arvifs, list) { ++ arvif->ahvif->num_vdev_created--; ++ } ++ } ++ ++ /* add chanctx/hw_config/filter part */ ++ for (j = 0; j < ab->num_radios; j++) { ++ pdev = &ab->pdevs[j]; ++ ar = pdev->ar; ++ ++ if (!ar) ++ continue; ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ list_for_each_entry_safe_reverse(arvif, tmp, &ar->arvifs, list) { ++ ahvif = arvif->ahvif; ++ ++ if (!ahvif) ++ continue; ++ ++ arvif->is_started = false; ++ arvif->is_created = false; ++ ++ rcu_read_lock(); ++ link = rcu_dereference(ahvif->vif->link_conf[arvif->link_id]); ++ ++ /* Not expected */ ++ if (WARN_ON(!link)) { ++ rcu_read_unlock(); ++ continue; ++ } ++ rcu_read_unlock(); ++ spin_lock_bh(&ar->data_lock); ++ ++ ar->rx_channel = link->chandef.chan; ++ spin_unlock_bh(&ar->data_lock); ++ ++ /* hw_config */ ++ changed &= ~(IEEE80211_CONF_CHANGE_CHANNEL | ++ IEEE80211_CONF_CHANGE_POWER | ++ IEEE80211_CONF_CHANGE_SMPS); ++ ++ if (ar->ah->hw->conf.flags & IEEE80211_CONF_MONITOR) { ++ set_bit(MONITOR_CONF_ENABLED, &ar->monitor_flags); ++ ++ if (test_bit(MONITOR_VDEV_CREATED, ++ &ar->monitor_flags)) { ++ ret = ath12k_mac_monitor_vdev_create(ar); ++ if (!ret && ath12k_mac_monitor_start(ar)) { ++ ath12k_err(ab, "unable to start monitor vdev\n"); ++ ath12k_mac_monitor_vdev_delete(ar); ++ } else { ++ ath12k_err(ab, "unable to create monitor vdev\n"); ++ } ++ } ++ } else { ++ clear_bit(MONITOR_CONF_ENABLED, &ar->monitor_flags); ++ if (test_bit(MONITOR_VDEV_CREATED, ++ &ar->monitor_flags)) { ++ ret = ath12k_mac_monitor_stop(ar); ++ if (!ret && ath12k_mac_monitor_vdev_delete(ar)) ++ ath12k_err(ab, "monitor vdev delete failed\n"); ++ else ++ ath12k_err(ab, "failed to stop monitor stop\n"); ++ } ++ } ++ ++ /* configure filter - we can use the same flag*/ ++ } ++ mutex_unlock(&ar->conf_mutex); ++ } ++ ++ /* assign chanctx part */ ++ for (j = 0; j < ab->num_radios; j++) { ++ pdev = &ab->pdevs[j]; ++ ar = pdev->ar; ++ ++ if (!ar) ++ continue; ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ list_for_each_entry_safe_reverse(arvif, tmp, &ar->arvifs, list) { ++ ahvif = arvif->ahvif; ++ ++ if (!ahvif) ++ continue; ++ ++ rcu_read_lock(); ++ link = rcu_dereference(ahvif->vif->link_conf[arvif->link_id]); ++ ++ /* Not expected */ ++ if (WARN_ON(!link)) { ++ rcu_read_unlock(); ++ continue; ++ } ++ rcu_read_unlock(); ++ ++ /* unlock ar mutex here since we will take ah mutex in ++ * the reconfig link API thus maintaining same order ++ * as we use in other places. ++ */ ++ mutex_unlock(&ar->conf_mutex); ++ ret = ath12k_mlo_core_recovery_reconfig_link_bss(ar, link, ahvif, arvif); ++ if (ret) { ++ ath12k_err(ab, "ERROR in reconfig link:%d\n", ++ ret); ++ return ret; ++ } ++ ath12k_dbg(ab, ATH12K_DBG_MODE1_RECOVERY, ++ "vdev_created getting incremented:%d\n", ++ ahvif->num_vdev_created); ++ mutex_lock(&ar->conf_mutex); ++ } ++ mutex_unlock(&ar->conf_mutex); ++ ath12k_dbg(ab, ATH12K_DBG_MODE1_RECOVERY, "Reconfig link bss completed\n"); ++ } ++ ++ /* reconfig_link_bss */ ++ for (j = 0; j < ab->num_radios; j++) { ++ pdev = &ab->pdevs[j]; ++ ar = pdev->ar; ++ ++ if (!ar) ++ continue; ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ list_for_each_entry_safe_reverse(arvif, tmp, &ar->arvifs, list) { ++ ahvif = arvif->ahvif; ++ ++ if (!ahvif) ++ continue; ++ ++ rcu_read_lock(); ++ ath12k_dbg(ab, ATH12K_DBG_MODE1_RECOVERY, ++ "vdev reconfig rcu_lock_acquired:\n") ; ++ ++ link = rcu_dereference(ahvif->vif->link_conf[arvif->link_id]); ++ ++ /* Not expected */ ++ if (WARN_ON(!link)) { ++ rcu_read_unlock(); ++ continue; ++ } ++ rcu_read_unlock(); ++ ++ /* unlock ar mutex here since we will take ah mutex in ++ * the reconfig link API thus maintaining same order ++ * as we use in other places. ++ */ ++ mutex_unlock(&ar->conf_mutex); ++ ret = ath12k_mlo_recovery_link_vif_reconfig(ar, ahvif, ++ arvif, ++ arvif->ahvif->vif, ++ link); ++ if (ret) { ++ ath12k_err(ab, "Failed to update reconfig_bss\n"); ++ return ret; ++ } ++ mutex_lock(&ar->conf_mutex); ++ } ++ mutex_unlock(&ar->conf_mutex); ++ ath12k_dbg(ab, ATH12K_DBG_MODE1_RECOVERY, "Recovery link vif completed\n"); ++ } ++ ++ for (i = 0; i < ag->num_chip; i++) { ++ partner_ab = ag->ab[i]; ++ if (ab == partner_ab) ++ continue; ++ ++ clear_bit(ATH12K_FLAG_UMAC_RECOVERY_START, &partner_ab->dev_flags); ++ } ++ ++ /* sta state part */ ++ for (j = 0; j < ab->num_radios; j++) { ++ pdev = &ab->pdevs[j]; ++ ar = pdev->ar; ++ ++ if (!ar) ++ continue; ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ if (list_empty(&ar->arvifs)) { ++ mutex_unlock(&ar->conf_mutex); ++ continue; ++ } ++ ++ list_for_each_entry_safe_reverse(arvif, tmp, &ar->arvifs, list) { ++ ahvif = arvif->ahvif; ++ ++ if (!ahvif) ++ continue; ++ ++ /* unlock ar mutex here as the iterator will be called ++ * within rcu lock. ++ */ ++ mutex_unlock(&ar->conf_mutex); ++ ieee80211_iterate_stations_atomic(ar->ah->hw, ++ ath12k_core_mode1_recovery_sta_list, ++ arvif); ++ mutex_lock(&ar->conf_mutex); ++ for (key_idx = 0; key_idx < WMI_MAX_KEY_INDEX; key_idx++) { ++ key = arvif->keys[key_idx]; ++ if (key) { ++ ath12k_dbg(ab, ATH12K_DBG_MODE1_RECOVERY, ++ "key:%p cipher:%d idx:%d flags:%d\n", ++ key, key->cipher, key->keyidx, key->flags); ++ ret = ath12k_mac_set_key(arvif->ar, SET_KEY, arvif, NULL, key); ++ } ++ } ++ } ++ mutex_unlock(&ar->conf_mutex); ++ ar->ah->in_recovery = false; ++ } ++ ++ for (i = 0; i < ag->num_hw; i++) { ++ ah = ag->ah[i]; ++ if (!ah) ++ continue; ++ ++ for (j = 0; j < ab->num_radios; j++) { ++ pdev = &ab->pdevs[j]; ++ ar = pdev->ar; ++ ++ if (!ar) ++ continue; ++ ++ ath12k_mac_reconfig_complete(ah->hw, ++ IEEE80211_RECONFIG_TYPE_RESTART, ++ ar); ++ } ++ } ++ ++ ab->recovery_start = false; ++ ag->recovery_mode = ATH12K_MLO_RECOVERY_MODE0; ++ return ret; ++} ++ + static void ath12k_core_restart(struct work_struct *work) + { + struct ath12k_base *ab = container_of(work, struct ath12k_base, restart_work); + struct ath12k_hw_group *ag = ab->ag; + int ret; + struct ath12k_hw *ah; ++ struct ath12k *ar; + int i; + + if (!ab->is_reset) +@@ -2036,16 +2772,20 @@ static void ath12k_core_restart(struct w + * If for any reason, reconfiguration fails, issue bug on for + * Mode 0 + */ +- if (ath12k_ssr_failsafe_mode && ath12k_recovery_mode == ATH12K_MLO_RECOVERY_MODE0) ++ if (ath12k_ssr_failsafe_mode && ag->recovery_mode == ATH12K_MLO_RECOVERY_MODE0) + BUG_ON(1); + return; + } + ++ ath12k_dbg(ab, ATH12K_DBG_MODE1_RECOVERY, ++ "ab->is_reset[%d]\n", ab->is_reset); ++ ar = ab->pdevs[0].ar; ++ + if (!ab->is_reset) + ath12k_core_post_reconfigure_recovery(ab); + + if (ath12k_core_hw_group_start_ready(ag) && +- ath12k_recovery_mode == ATH12K_MLO_RECOVERY_MODE0) { ++ ag->recovery_mode == ATH12K_MLO_RECOVERY_MODE0) { + for (i = 0; i < ag->num_hw; i++) { + ah = ag->ah[i]; + if (!ah) +@@ -2060,6 +2800,19 @@ static void ath12k_core_restart(struct w + if (ath12k_sawf_reconfigure_on_crash(ab)) + ath12k_warn(ab, "SAWF SLA reconfiguring failed\n"); + #endif /* CPTCFG_ATH12K_SAWF */ ++ ++ if (ath12k_core_hw_group_start_ready(ag) && ++ ag->recovery_mode == ATH12K_MLO_RECOVERY_MODE1) { ++ queue_work(ab->workqueue_aux, &ab->recovery_work); ++ } ++} ++ ++static void ath12k_core_mode1_recovery_work(struct work_struct *work) ++{ ++ struct ath12k_base *ab = container_of(work, struct ath12k_base, recovery_work); ++ ath12k_dbg(ab, ATH12K_DBG_MODE1_RECOVERY, ++ "queued recovery work\n"); ++ ath12k_mode1_recovery_reconfig(ab, __func__); + } + + static void ath12k_rproc_recovery_do_coredump(struct rproc *rproc) +@@ -2163,26 +2916,26 @@ static int ath12k_rproc_recovery_power_u + * is identified by waiting for MLO Teardown complete for all + * chipsets + */ +-int ath12k_core_trigger_umac_reset(struct ath12k_base *ab) ++static int ath12k_core_trigger_umac_reset(struct ath12k_base *ab) + { + struct ath12k_hw_group *ag = ab->ag; + long time_left; +- unsigned long timeout; ++ int ret = 0; + + reinit_completion(&ag->umac_reset_complete); + + ath12k_mac_mlo_teardown_with_umac_reset(ab); + +- timeout = jiffies + msecs_to_jiffies(ATH12K_UMAC_RESET_TIMEOUT_IN_MS); +- + time_left = wait_for_completion_timeout(&ag->umac_reset_complete, +- timeout); ++ msecs_to_jiffies(ATH12K_UMAC_RESET_TIMEOUT_IN_MS)); + + if (!time_left) { + ath12k_warn(ab, "UMAC reset didn't get completed within 200 ms\n"); +- return -ETIMEDOUT; ++ ret = -ETIMEDOUT; + } +- return 0; ++ ++ ag->trigger_umac_reset = false; ++ return ret; + } + + #ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT +@@ -2230,9 +2983,11 @@ static void ath12k_core_reset(struct wor + { + struct ath12k_base *ab = container_of(work, struct ath12k_base, reset_work); + struct ath12k_hw_group *ag = ab->ag; ++ struct ath12k_hw *ah; + struct ath12k_base *partner_ab; + int reset_count, fail_cont_count, i; + long time_left; ++ bool teardown = false; + + #ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT + if (!ab->is_reset) { +@@ -2243,9 +2998,21 @@ static void ath12k_core_reset(struct wor + } + #endif + +- ag->recovery_mode = ATH12K_MLO_RECOVERY_MODE0; + if (ab->recovery_mode_address) { +- ag->recovery_mode = *ab->recovery_mode_address; ++ switch (*ab->recovery_mode_address) { ++ case ATH12K_MLO_RECOVERY_MODE1: ++ ag->recovery_mode = ATH12K_MLO_RECOVERY_MODE1; ++ break; ++ case ATH12K_MLO_RECOVERY_MODE0: ++ fallthrough; ++ default: ++ ag->recovery_mode = ATH12K_MLO_RECOVERY_MODE0; ++ } ++ ath12k_dbg(ab, ATH12K_DBG_MODE1_RECOVERY, ++ "mode:%d\n", ag->recovery_mode); ++ } ++ else { ++ ag->recovery_mode = ATH12K_MLO_RECOVERY_MODE0; + } + + /* Sometimes the recovery will fail and then the next all recovery fail, +@@ -2277,7 +3044,7 @@ static void ath12k_core_reset(struct wor + */ + ath12k_warn(ab, "already resetting count %d\n", reset_count); + +- if (ath12k_ssr_failsafe_mode && ath12k_recovery_mode == ATH12K_MLO_RECOVERY_MODE0) ++ if (ath12k_ssr_failsafe_mode && ag->recovery_mode == ATH12K_MLO_RECOVERY_MODE0) + BUG_ON(1); + + reinit_completion(&ab->reset_complete); +@@ -2305,6 +3072,70 @@ static void ath12k_core_reset(struct wor + ab->is_reset = true; + atomic_set(&ab->recovery_count, 0); + ++ /* Incase recovery fails and FW asserts again, this is to prevent invalid operation. */ ++ if (ag->num_started && ab->fw_recovery_support) ++ ag->num_started--; ++ ++ if (!ag->hw_queues_stopped) ++ ath12k_core_mlo_hw_queues_stop(ag, ab); ++ ++ for (i = 0; i < ag->num_chip; i++) { ++ partner_ab = ag->ab[i]; ++ if (ab == partner_ab) ++ continue; ++ ++ teardown = false; ++ /* Need to check partner_ab and keep recovery mode ++ * in ab struct? ++ */ ++ if (ag->recovery_mode == ATH12K_MLO_RECOVERY_MODE1) { ++ if (test_bit(ATH12K_FLAG_UMAC_RECOVERY_START, &partner_ab->dev_flags) || ++ test_bit(ATH12K_FLAG_RECOVERY, &partner_ab->dev_flags)) { ++ /* On receiving MHI Interrupt for pdev which is ++ * already in UMAC Recovery, then fallback to ++ * MODE0 ++ */ ++ ag->recovery_mode = ATH12K_MLO_RECOVERY_MODE0; ++ } else if ((!test_bit(ATH12K_FLAG_RECOVERY, &partner_ab->dev_flags)) && ++ (!(test_bit(ATH12K_FLAG_UMAC_RECOVERY_START, &partner_ab->dev_flags)))) { ++ /* Set dev flags to UMAC recovery START ++ * and set flag to send teardown later ++ */ ++ ath12k_dbg(ab, ATH12K_DBG_MODE1_RECOVERY, ++ "setting teardown to true\n"); ++ set_bit(ATH12K_FLAG_UMAC_RECOVERY_START, &partner_ab->dev_flags); ++ teardown = true; ++ continue; ++ } else { ++ /* if one of the ab is already in recovery, or ++ * in UMAC recovery start phase ++ * then fall back to MODE0 ++ */ ++ ag->recovery_mode = ATH12K_MLO_RECOVERY_MODE0; ++ } ++ } ++ } ++ ++ if (teardown) { ++ if (ath12k_core_trigger_umac_reset(ab) || ++ ath12k_mac_partner_peer_cleanup(ab)) { ++ /* Fallback to Mode0 if umac reset/peer_cleanup is ++ * failed */ ++ ag->recovery_mode = ATH12K_MLO_RECOVERY_MODE0; ++ } else { ++ /* wake queues here as ping should continue for ++ * legacy clients in non-asserted chipsets ++ */ ++ for (i = 0; i < ag->num_hw; i++) { ++ ah = ag->ah[i]; ++ if (!ah) ++ continue; ++ ++ ieee80211_wake_queues(ah->hw); ++ } ++ } ++ } ++ + for (i = 0; i < ag->num_chip; i++) { + partner_ab = ag->ab[i]; + if (ab == partner_ab) +@@ -2314,16 +3145,17 @@ static void ath12k_core_reset(struct wor + * method to ensure recovery of all partner chips in MODE0 instead of + * relying on firmware to crash partner chips + */ +- if (ath12k_recovery_mode == ATH12K_MLO_RECOVERY_MODE0 && +- !test_bit(ATH12K_FLAG_RECOVERY, &partner_ab->dev_flags)) ++ if (ag->recovery_mode == ATH12K_MLO_RECOVERY_MODE0 && ++ !test_bit(ATH12K_FLAG_RECOVERY, &partner_ab->dev_flags)) { ++ ath12k_dbg(ab, ATH12K_DBG_MODE1_RECOVERY, ++ "sending fw_hang cmd ar:%p\n", ++ partner_ab->pdevs[0].ar); + ath12k_wmi_force_fw_hang_cmd(partner_ab->pdevs[0].ar, + ATH12K_WMI_FW_HANG_ASSERT_TYPE, + ATH12K_WMI_FW_HANG_DELAY, true); ++ } + } + +- if (!ag->hw_queues_stopped) +- ath12k_core_mlo_hw_queues_stop(ag); +- + ath12k_core_pre_reconfigure_recovery(ab); + + ath12k_core_post_reconfigure_recovery(ab); +@@ -2342,10 +3174,6 @@ static void ath12k_core_reset(struct wor + if (ab->is_qdss_tracing) + ab->is_qdss_tracing = false; + +- /* Incase recovery fails and FW asserts again, this is to prevent invalid operation. */ +- if (ag->num_started && ab->fw_recovery_support) +- ag->num_started--; +- + if (ab->fw_recovery_support) { + if (ab->hif.bus == ATH12K_BUS_PCI) { + ath12k_hif_power_down(ab); +@@ -2358,6 +3186,12 @@ static void ath12k_core_reset(struct wor + } + ath12k_dbg(ab, ATH12K_DBG_BOOT, "reset started\n"); + } ++ if (ag->recovery_mode == ATH12K_MLO_RECOVERY_MODE1) ++ ab->recovery_start = true; ++ ++ ab->recovery_mode_address = NULL; ++ ab->crash_info_address = NULL; ++ + mutex_unlock(&ag->mutex_lock); + } + +@@ -2674,6 +3508,7 @@ struct ath12k_base *ath12k_core_alloc(st + init_waitqueue_head(&ab->ssr_dump_wq); + INIT_WORK(&ab->restart_work, ath12k_core_restart); + INIT_WORK(&ab->reset_work, ath12k_core_reset); ++ INIT_WORK(&ab->recovery_work, ath12k_core_mode1_recovery_work); + timer_setup(&ab->rx_replenish_retry, ath12k_ce_rx_replenish_retry, 0); + init_completion(&ab->htc_suspend); + init_completion(&ab->wow.wakeup_completed); +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -255,6 +255,7 @@ enum ath12k_dev_flags { + ATH12K_FLAG_WMI_INIT_DONE, + ATH12K_FLAG_UMAC_PRERESET_START, + ATH12K_FLAG_UMAC_RESET_COMPLETE, ++ ATH12K_FLAG_UMAC_RECOVERY_START, + }; + + enum ath12k_monitor_flags { +@@ -339,6 +340,7 @@ struct ath12k_key_conf { + struct ath12k_recovery_cache { + struct ath12k_tx_conf tx_conf; + struct ath12k_key_conf key_conf; ++ struct list_head recovery_sta_list; + u64 bss_conf_changed; + }; + +@@ -441,6 +443,7 @@ struct ath12k_link_vif { + struct completion peer_ch_width_switch_send; + struct work_struct peer_ch_width_switch_work; + struct ath12k_peer_ch_width_switch_data *peer_ch_width_switch_data; ++ struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1]; + }; + + struct ath12k_vif { +@@ -680,6 +683,9 @@ struct ath12k_link_sta { + + /* For check disable fixed rate check for peer */ + bool disable_fixed_rate; ++ /* will be saved to use during recovery */ ++ struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1]; ++ enum ieee80211_sta_state state; + }; + + struct ath12k_sta { +@@ -1250,6 +1256,7 @@ struct ath12k_hw { + + /* protected by ah->data_lock */ + struct list_head ml_peers; ++ bool in_recovery; + struct ath12k radio[0] __aligned(sizeof(void *)); + }; + +@@ -1261,7 +1268,8 @@ struct ath12k_mlo_memory { + }; + + enum ath12k_mlo_recovery_mode { +- ATH12K_MLO_RECOVERY_MODE0, ++ ATH12K_MLO_RECOVERY_MODE0 = 1, ++ ATH12K_MLO_RECOVERY_MODE1 = 2, + }; + + struct ath12k_mlo_dp_umac_reset { +@@ -1417,6 +1425,7 @@ struct ath12k_base { + struct work_struct restart_work; + struct workqueue_struct *workqueue_aux; + struct work_struct reset_work; ++ struct work_struct recovery_work; + atomic_t recovery_count; + atomic_t reset_count; + bool is_reset; +@@ -1489,6 +1498,8 @@ struct ath12k_base { + u32 *recovery_mode_address; + + bool mlo_complete_event; ++ /* Mode1 specific flag to identify recovering pdev */ ++ bool recovery_start; + /* must be last */ + u8 drv_priv[0] __aligned(sizeof(void *)); + }; +--- a/drivers/net/wireless/ath/ath12k/debug.h ++++ b/drivers/net/wireless/ath/ath12k/debug.h +@@ -34,6 +34,7 @@ enum ath12k_debug_mask { + ATH12K_DBG_SAWF = 0x00040000, + ATH12K_DBG_PPE = 0x00080000, + ATH12K_DBG_DP_UMAC_RESET= 0x00100000, ++ ATH12K_DBG_MODE1_RECOVERY= 0x00200000, + ATH12K_DBG_ANY = 0xffffffff, + }; + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -265,12 +265,8 @@ static const u32 ath12k_smps_map[] = { + [WLAN_HT_CAP_SM_PS_DISABLED] = WMI_PEER_SMPS_PS_NONE, + }; + +-static int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif); + static int ath12k_start_vdev_delay(struct ath12k *ar, + struct ieee80211_vif *vif); +-static void ath12k_mac_parse_tx_pwr_env(struct ath12k *ar, +- struct ath12k_link_vif *arvif, +- struct ieee80211_chanctx_conf *ctx); + static void ath12k_update_bcn_template_work(struct work_struct *work); + static void ath12k_update_obss_color_notify_work(struct work_struct *work); + static void ath12k_mac_remove_link_interface(struct ieee80211_hw *hw, +@@ -1026,10 +1022,106 @@ static int ath12k_mac_set_kickout(struct + return 0; + } + ++static void ath12k_mac_dec_num_stations(struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta) ++{ ++ struct ath12k_vif *ahvif = arvif->ahvif; ++ struct ath12k *ar = arvif->ar; ++ struct ath12k_sta *ahsta = arsta->ahsta; ++ struct ieee80211_sta *sta; ++ ++ sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ if (!ar->num_stations) ++ return; ++ ++ if (ahvif->vdev_type == WMI_VDEV_TYPE_STA && !sta->tdls) ++ return; ++ ++ ar->num_stations--; ++} ++ ++int ath12k_mac_partner_peer_cleanup(struct ath12k_base *ab) ++{ ++ ++ struct ath12k_base *partner_ab; ++ struct ath12k *ar; ++ struct ath12k_pdev *pdev; ++ struct ath12k_hw_group *ag; ++ struct ath12k_link_vif *arvif; ++ struct ath12k_vif *ahvif; ++ struct ieee80211_sta *sta; ++ struct ieee80211_vif *vif; ++ struct ath12k_sta *ahsta; ++ struct ath12k_link_sta *arsta; ++ struct ath12k_peer *peer, *tmp; ++ int idx, rad_idx, count=0, ret = 0; ++ u8 link_id; ++ ++ ag = ab->ag; ++ ++ for (idx = 0; idx < ag->num_chip; idx++) { ++ partner_ab = ag->ab[idx]; ++ ++ if (ab == partner_ab) ++ continue; ++ ++ for (rad_idx = 0; rad_idx < partner_ab->num_radios; rad_idx++) { ++ pdev = &partner_ab->pdevs[rad_idx]; ++ ar = pdev->ar; ++ ++ /* TODO: Need to see if ab peers list is suffice for ++ * split phy case also ++ */ ++ list_for_each_entry_safe(peer, tmp, &partner_ab->peers, list) { ++ count++; ++ if (!peer->sta || !peer->mlo || !peer->vif) ++ continue; ++ ++ link_id = peer->link_id; ++ /* get arsta */ ++ sta = peer->sta; ++ ahsta = (struct ath12k_sta *)sta->drv_priv; ++ arsta = ahsta->link[link_id]; ++ ++ /* get arvif */ ++ vif = peer->vif; ++ ahvif = (struct ath12k_vif *)vif->drv_priv; ++ arvif = ahvif->link[link_id]; ++ cancel_work_sync(&arsta->update_wk); ++ ++ mutex_lock(&ar->conf_mutex); ++ ret = ath12k_peer_delete_send(ar, arvif->vdev_id, arsta->addr); ++ if (ret) { ++ mutex_unlock(&ar->conf_mutex); ++ ath12k_warn(ar->ab, ++ "failed to delete peer vdev_id %d addr %pM ret %d\n", ++ arvif->vdev_id, arsta->addr, ret); ++ continue; ++ } ++ ret = ath12k_wait_for_peer_delete_done(ar, arvif->vdev_id, arsta->addr); ++ if (ret) { ++ mutex_unlock(&ar->conf_mutex); ++ continue; ++ } ++ ar->num_peers--; ++ arvif->num_stations--; ++ ath12k_mac_dec_num_stations(arvif, arsta); ++ mutex_unlock(&ar->conf_mutex); ++ } ++ } ++ } ++ return ret; ++} ++ + void ath12k_mac_peer_cleanup_all(struct ath12k *ar) + { + struct ath12k_peer *peer, *tmp; + struct ath12k_base *ab = ar->ab; ++ struct ath12k_hw_group *ag = ab->ag; ++ struct ath12k_link_vif *arvif, *tmp_vif; + + lockdep_assert_held(&ar->conf_mutex); + +@@ -1054,6 +1146,10 @@ void ath12k_mac_peer_cleanup_all(struct + ar->num_peers = 0; + ar->num_stations = 0; + ++ if (ag->recovery_mode == ATH12K_MLO_RECOVERY_MODE1) { ++ list_for_each_entry_safe_reverse(arvif, tmp_vif, &ar->arvifs, list) ++ arvif->num_stations = 0; ++ } + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "ath12k mac peer cleanup done\n"); + } + +@@ -1191,7 +1287,7 @@ static int ath12k_mac_monitor_vdev_stop( + return ret; + } + +-static int ath12k_mac_monitor_vdev_create(struct ath12k *ar) ++int ath12k_mac_monitor_vdev_create(struct ath12k *ar) + { + struct ath12k_pdev *pdev = ar->pdev; + struct vdev_create_params param; +@@ -1267,7 +1363,7 @@ static int ath12k_mac_monitor_vdev_creat + return 0; + } + +-static int ath12k_mac_monitor_vdev_delete(struct ath12k *ar) ++int ath12k_mac_monitor_vdev_delete(struct ath12k *ar) + { + int ret = 0; + unsigned long time_left = 0; +@@ -1320,7 +1416,7 @@ ath12k_mac_get_any_chandef_iter(struct i + arg->def = &conf->def; + } + +-static int ath12k_mac_monitor_start(struct ath12k *ar) ++int ath12k_mac_monitor_start(struct ath12k *ar) + { + struct cfg80211_chan_def *chandef; + struct ath12k_mac_any_chandef_arg arg = { .ar = ar, .def = NULL}; +@@ -1364,7 +1460,7 @@ static int ath12k_mac_monitor_start(stru + return ret; + } + +-static int ath12k_mac_monitor_stop(struct ath12k *ar) ++int ath12k_mac_monitor_stop(struct ath12k *ar) + { + int ret; + +@@ -4284,10 +4380,10 @@ static int ath12k_mac_config_obss_pd(str + return 0; + } + +-static void ath12k_mac_bss_info_changed(struct ath12k *ar, +- struct ath12k_link_vif *arvif, +- struct ieee80211_bss_conf *info, +- u64 changed) ++void ath12k_mac_bss_info_changed(struct ath12k *ar, ++ struct ath12k_link_vif *arvif, ++ struct ieee80211_bss_conf *info, ++ u64 changed) + { + struct ath12k_vif *ahvif = arvif->ahvif, *tx_ahvif; + struct ath12k_link_vif *tx_arvif; +@@ -4454,7 +4550,8 @@ skip_pending_cs_up: + if (changed & BSS_CHANGED_BSSID && info->bssid && !is_zero_ether_addr(info->bssid)) + ether_addr_copy(arvif->bssid, info->bssid); + +- if (changed & BSS_CHANGED_BEACON_ENABLED && !arvif->is_started) ++ /* pending_up is not needed for recovered ab during Mode1 scenario */ ++ if (changed & BSS_CHANGED_BEACON_ENABLED && !arvif->is_started && !ar->ab->recovery_start) + arvif->pending_up = true; + + if (changed & BSS_CHANGED_BEACON_ENABLED && arvif->is_started) { +@@ -5518,10 +5615,10 @@ static int ath12k_clear_peer_keys(struct + return first_errno; + } + +-static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd, +- struct ath12k_link_vif *arvif, +- struct ath12k_link_sta *arsta, +- struct ieee80211_key_conf *key) ++int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd, ++ struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta, ++ struct ieee80211_key_conf *key) + { + struct ath12k_base *ab; + struct ath12k_peer *peer; +@@ -5540,6 +5637,10 @@ static int ath12k_mac_set_key(struct ath + sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + } + ++ if (sta && sta->mlo && ++ (test_bit(ATH12K_FLAG_UMAC_RECOVERY_START, &ar->ab->dev_flags))) ++ return 0; ++ + lockdep_assert_held(&ar->ah->conf_mutex); + + rcu_read_lock(); +@@ -5718,8 +5819,10 @@ static int ath12k_mac_op_set_key(struct + } + + if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &arvif->ar->ab->dev_flags)) { ++ ath12k_dbg(arvif->ar->ab, ATH12K_DBG_MODE1_RECOVERY, ++ "cmd:%d called for crash flush set ab\n", cmd); + mutex_unlock(&ah->conf_mutex); +- return -ESHUTDOWN; ++ return 0; + } + + if (sta) { +@@ -5735,6 +5838,7 @@ static int ath12k_mac_op_set_key(struct + mutex_unlock(&arvif->ar->conf_mutex); + if (ret) + break; ++ arsta->keys[key->keyidx] = key; + } + } else { + arsta = &ahsta->deflink; +@@ -5744,10 +5848,13 @@ static int ath12k_mac_op_set_key(struct + mutex_lock(&arvif->ar->conf_mutex); + ret = ath12k_mac_set_key(arvif->ar, cmd, arvif, arsta, key); + mutex_unlock(&arvif->ar->conf_mutex); ++ arsta->keys[key->keyidx] = key; + } + } else { + mutex_lock(&arvif->ar->conf_mutex); + ret = ath12k_mac_set_key(arvif->ar, cmd, arvif, arsta, key); ++ /* if sta is null, consider it has self peer */ ++ arvif->keys[key->keyidx] = key; + mutex_unlock(&arvif->ar->conf_mutex); + } + out: +@@ -6229,7 +6336,7 @@ static int ath12k_station_assoc(struct a + + arsta->bw = bandwidth; + arvif->num_stations++; +- ath12k_dbg(ar->ab, ATH12K_DBG_MAC, ++ ath12k_dbg(ar->ab, ATH12K_DBG_MODE1_RECOVERY, + "mac station %pM connected to vdev %u. num_stations=%u\n", + arsta->addr, arvif->vdev_id, arvif->num_stations); + +@@ -6651,33 +6758,10 @@ static int ath12k_mac_inc_num_stations(s + + ar->num_stations++; + ++ ath12k_dbg(ar->ab, ATH12K_DBG_MODE1_RECOVERY,"num_stat incremented:%d\n", ar->num_stations); + return 0; + } + +-static void ath12k_mac_dec_num_stations(struct ath12k_link_vif *arvif, +- struct ath12k_link_sta *arsta) +-{ +- struct ath12k_vif *ahvif = arvif->ahvif; +- struct ath12k *ar = arvif->ar; +- struct ath12k_sta *ahsta = arsta->ahsta; +- struct ieee80211_sta *sta; +- +- if (ar && !ar->num_stations && +- test_bit(ATH12K_FLAG_RECOVERY, &ar->ab->dev_flags)) +- return; +- +- sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); +- +- lockdep_assert_held(&ar->conf_mutex); +- +- if (ahvif->vdev_type == WMI_VDEV_TYPE_STA && !sta->tdls) +- return; +- +- WARN_ON(ar->num_stations == 0); +- if (ar->num_stations) +- ar->num_stations--; +-} +- + static void ath12k_mac_station_post_remove(struct ath12k *ar, + struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta) +@@ -6947,6 +7031,7 @@ static int ath12k_mac_assign_link_sta(st + arsta->arvif = ahvif->link[link_id]; + arsta->ahsta = ahsta; + arsta->link_id = link_id; ++ arsta->state = IEEE80211_STA_NONE; + + return 0; + } +@@ -7075,6 +7160,11 @@ static int ath12k_mac_handle_link_sta_st + + sta = container_of((void *)ahsta, struct ieee80211_sta, drv_priv); + ++ if (sta->mlo && ++ (test_bit(ATH12K_FLAG_UMAC_RECOVERY_START, &ar->ab->dev_flags))) ++ /* Shouldn't allow MLO STA assoc until UMAC_RECOVERY bit is cleared */ ++ return 0; ++ + /* cancel must be done outside the ar mutex to avoid deadlock */ + if ((old_state == IEEE80211_STA_NONE && + new_state == IEEE80211_STA_NOTEXIST)) { +@@ -7132,6 +7222,7 @@ static int ath12k_mac_handle_link_sta_st + arsta->addr); + } + ++ arsta->state = new_state; + mutex_unlock(&ar->conf_mutex); + + ath12k_dbg(ar->ab, ATH12K_DBG_PEER, "mac sta %pM old state %d new state :%d\n", +@@ -7206,11 +7297,11 @@ out: + return ret; + } + +-static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta, +- enum ieee80211_sta_state old_state, +- enum ieee80211_sta_state new_state) ++int ath12k_mac_update_sta_state(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_sta *sta, ++ enum ieee80211_sta_state old_state, ++ enum ieee80211_sta_state new_state) + { + struct ath12k_hw *ah = hw->priv; + struct ath12k_link_vif *arvif; +@@ -7269,7 +7360,7 @@ static int ath12k_mac_op_sta_state(struc + goto exit; + } + +- if (!sta->valid_links) ++ if (!sta->valid_links && !vif->valid_links) + WARN_ON(1); + + /* assign default link to the first link sta */ +@@ -7294,6 +7385,27 @@ static int ath12k_mac_op_sta_state(struc + goto exit; + } + ++ /* Reconfig links of arsta during recovery */ ++ if (ahsta->link[ahsta->assoc_link_id]->state != IEEE80211_STA_NONE && ++ old_state == IEEE80211_STA_NOTEXIST && ++ new_state == IEEE80211_STA_NONE) { ++ ahsta->num_peer = 0; ++ ++ for_each_set_bit(link_id, &ahsta->links_map, ++ IEEE80211_MLD_MAX_NUM_LINKS) { ++ arsta = ahsta->link[link_id]; ++ arvif = ahvif->link[link_id]; ++ ++ ath12k_mac_assign_link_sta(ah, ahsta, arsta, ++ ahvif, link_id); ++ } ++ ahsta->deflink.is_assoc_link = true; ++ ahsta->assoc_link_id = ahvif->deflink.link_id; ++ ++ if (ahsta->use_4addr_set) ++ ieee80211_queue_work(ah->hw, &ahsta->set_4addr_wk); ++ } ++ + for_each_set_bit(link_id, &sta->valid_links, IEEE80211_MLD_MAX_NUM_LINKS) { + arvif = ahvif->link[link_id]; + arsta = ahsta->link[link_id]; +@@ -7320,7 +7432,8 @@ static int ath12k_mac_op_sta_state(struc + ret = 0; + } + +- if (old_state == IEEE80211_STA_NOTEXIST && new_state == IEEE80211_STA_NONE) { ++ if (old_state == IEEE80211_STA_NOTEXIST && new_state == IEEE80211_STA_NONE && ++ !test_bit(ATH12K_FLAG_RECOVERY, &arvif->ar->ab->dev_flags)) { + + /* Unassign this link sta which couldnt be added to FW and + * cleanup the other link stations added earlier +@@ -7346,6 +7459,16 @@ exit: + return ret; + } + ++static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_sta *sta, ++ enum ieee80211_sta_state old_state, ++ enum ieee80211_sta_state new_state) ++{ ++ return ath12k_mac_update_sta_state(hw, vif, sta, old_state, ++ new_state); ++} ++ + static int ath12k_mac_op_change_sta_links(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, +@@ -7613,9 +7736,9 @@ exit: + return ret; + } + +-static int ath12k_mac_conf_tx(struct ath12k *ar, +- struct ath12k_link_vif *arvif, u16 ac, +- const struct ieee80211_tx_queue_params *params) ++int ath12k_mac_conf_tx(struct ath12k *ar, ++ struct ath12k_link_vif *arvif, u16 ac, ++ const struct ieee80211_tx_queue_params *params) + { + struct wmi_wmm_params_arg *p = NULL; + int ret; +@@ -9116,6 +9239,13 @@ static void ath12k_mac_op_tx(struct ieee + + ar = arvif->ar; + ++ ah = ar->ah; ++ ++ if (unlikely(test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))) { ++ ieee80211_free_txskb(ah->hw, skb); ++ return; ++ } ++ + #ifdef CPTCFG_MAC80211_SFE_SUPPORT + if (skb->fast_xmit) { + ret = ath12k_mac_tx_check_max_limit(ar, skb); +@@ -9137,13 +9267,6 @@ static void ath12k_mac_op_tx(struct ieee + } + #endif + +- ah = ar->ah; +- +- if (unlikely(test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))) { +- ieee80211_free_txskb(ah->hw, skb); +- return; +- } +- + if (key) { + skb_cb->cipher = key->cipher; + skb_cb->flags |= ATH12K_SKB_CIPHER_SET; +@@ -9231,6 +9354,9 @@ static void ath12k_mac_op_tx(struct ieee + + tmp_ar = tmp_arvif->ar; + ++ if (unlikely(test_bit(ATH12K_FLAG_CRASH_FLUSH, &tmp_ar->ab->dev_flags))) ++ continue; ++ + ret = ath12k_mac_tx_check_max_limit(tmp_ar, skb); + if (ret) { + ath12k_dbg(tmp_ar->ab, ATH12K_DBG_MAC, +@@ -9448,6 +9574,10 @@ static int __ath12k_mac_mlo_teardown(str + struct ath12k_base *ab = ar->ab; + int ret; + ++ // If we receive teardown during ab is down, then exit silently ++ if (test_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags)) ++ return 0; ++ + ret = ath12k_wmi_mlo_teardown(ar, umac_reset); + if (ret) { + ath12k_err(ab, "failed to teardown MLO for pdev_idx %d: %d\n", +@@ -9455,8 +9585,8 @@ static int __ath12k_mac_mlo_teardown(str + return ret; + } + +- ath12k_dbg(ab, ATH12K_DBG_MAC, "MLO teardown for pdev_idx %d\n", +- ar->pdev_idx); ++ ath12k_dbg(ab, ATH12K_DBG_MAC, "MLO teardown for pdev_idx %d:%d\n", ++ ar->pdev_idx, umac_reset); + return 0; + } + +@@ -9492,12 +9622,45 @@ err_setup: + return ret; + } + +-static int ath12k_mac_radio_start(struct ath12k *ar) ++static void ath12k_mac_drain_tx(struct ath12k_hw *ah, ++ struct ath12k *asserted_ar) ++{ ++ struct ath12k *ar; ++ int i; ++ ++ if (asserted_ar) { ++ /* if asserted ar is NOT NULL, consider it ++ * is during Mode1 recovery and drain only ++ * asserted pdev ++ */ ++ ath12k_mac_radio_drain_tx(asserted_ar); ++ return; ++ } ++ ++ ar = ah->radio; ++ ++ for (i = 0; i < ah->num_radio; i++) { ++ ath12k_mac_radio_drain_tx(ar); ++ ar++; ++ } ++} ++ ++int ath12k_mac_radio_start(struct ath12k *ar) + { + struct ath12k_base *ab = ar->ab; + struct ath12k_pdev *pdev = ar->pdev; ++ struct ath12k_hw_group *ag = ab->ag; ++ struct ath12k_hw *ah = ar->ah; + int ret; + ++ /* reo init/drain tx only needed for recovered ++ * ab during Mode1 scenario ++ */ ++ if (ab->recovery_start) { ++ ath12k_mgmt_rx_reo_init_timer(ag); ++ ath12k_mac_drain_tx(ah, ar); ++ } ++ + mutex_lock(&ar->conf_mutex); + + switch (ar->state) { +@@ -9768,7 +9931,7 @@ static void ath12k_mac_radio_stop(struct + spin_unlock_bh(&ar->data_lock); + } + +-static void ath12k_mgmt_rx_reo_init_timer(struct ath12k_hw_group *ag) ++void ath12k_mgmt_rx_reo_init_timer(struct ath12k_hw_group *ag) + { + struct ath12k_mgmt_rx_reo_context *reo_context = &ag->rx_reo; + +@@ -9803,19 +9966,6 @@ static void ath12k_mgmt_rx_reo_deinit_ti + reo_context->timer_init_done = false; + } + +-static void ath12k_mac_drain_tx(struct ath12k_hw *ah) +-{ +- struct ath12k *ar; +- int i; +- +- ar = ah->radio; +- +- for (i = 0; i < ah->num_radio; i++) { +- ath12k_mac_radio_drain_tx(ar); +- ar++; +- } +-} +- + static int ath12k_mac_op_start(struct ieee80211_hw *hw) + { + struct ath12k_hw *ah = hw->priv; +@@ -9827,7 +9977,7 @@ static int ath12k_mac_op_start(struct ie + + ath12k_mgmt_rx_reo_init_timer(ag); + +- ath12k_mac_drain_tx(ah); ++ ath12k_mac_drain_tx(ah, NULL); + + mutex_lock(&ah->conf_mutex); + ar = ah->radio; +@@ -9874,7 +10024,7 @@ static void ath12k_mac_op_stop(struct ie + + ath12k_mgmt_rx_reo_deinit_timer(ag); + +- ath12k_mac_drain_tx(ah); ++ ath12k_mac_drain_tx(ah, NULL); + + mutex_lock(&ah->conf_mutex); + ar = ah->radio; +@@ -10165,7 +10315,7 @@ static void ath12k_update_obss_color_not + mutex_unlock(&ar->conf_mutex); + } + +-static int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif) ++ int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif) + { + struct ieee80211_vif *vif = arvif->ahvif->vif; + struct ath12k_base *ab = ar->ab; +@@ -10315,7 +10465,14 @@ static int ath12k_mac_vdev_create(struct + ar->allocated_vdev_map |= 1LL << arvif->vdev_id; + + spin_lock_bh(&ar->data_lock); +- list_add(&arvif->list, &ar->arvifs); ++ ++ /* list added is not needed during mode1 recovery ++ * as the arvif(s) updated are from the existing ++ * list ++ */ ++ if (!ab->recovery_start) ++ list_add(&arvif->list, &ar->arvifs); ++ + spin_unlock_bh(&ar->data_lock); + + ath12k_mac_update_vif_offload(ar, arvif); +@@ -10474,8 +10631,8 @@ err: + return ret; + } + +-static void ath12k_mac_vif_cache_flush(struct ath12k *ar, struct ieee80211_vif *vif, +- u8 link_id) ++void ath12k_mac_vif_cache_flush(struct ath12k *ar, struct ieee80211_vif *vif, ++ u8 link_id) + { + struct ath12k_hw *ah = ar->ah; + struct ath12k_vif *ahvif = (void *)vif->drv_priv; +@@ -10921,6 +11078,10 @@ static int ath12k_mac_ampdu_action(struc + if (unlikely(test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))) + return -ESHUTDOWN; + ++ if (params->sta->mlo && ++ (test_bit(ATH12K_FLAG_UMAC_RECOVERY_START, &ar->ab->dev_flags))) ++ return 0; ++ + mutex_lock(&ar->conf_mutex); + + switch (params->action) { +@@ -11363,7 +11524,7 @@ err: + return ret; + } + +-static int ath12k_mac_vdev_start(struct ath12k_link_vif *arvif, ++int ath12k_mac_vdev_start(struct ath12k_link_vif *arvif, + const struct cfg80211_chan_def *chandef, + bool radar_enabled) + { +@@ -11477,7 +11638,7 @@ beacon_tmpl_setup: + return ret; + } + +-static int ath12k_mac_mlo_vdev_start(struct ath12k_link_vif *arvif) ++int ath12k_mac_mlo_vdev_start(struct ath12k_link_vif *arvif, bool flag) + { + struct ath12k_vif *ahvif = arvif->ahvif; + struct ath12k *ar = arvif->ar; +@@ -11539,7 +11700,12 @@ static int ath12k_mac_mlo_vdev_start(str + + arvif->is_started = true; + mutex_unlock(&ar->conf_mutex); +- ahvif->num_vdev_started++; ++ /* num vdev started is not needed during mode1 recovery ++ * as the arvif(s) updated are from the existing ++ * list ++ */ ++ if (!ar->ab->recovery_start) ++ ahvif->num_vdev_started++; + /* Beaconing not required in DFS channel assignment for CAC */ + return ret; + } +@@ -11563,6 +11729,9 @@ static int ath12k_mac_mlo_vdev_start(str + + ar = arvif_p->ar; + ++ if (!ar->ab->is_reset && !flag) ++ continue; ++ + /* TODO cant hold rcu lock due to call of ath12k_mac_bss_info_changed + * option is to take a backup if link info, anyways this function would + * change after FW support for dynamic add +@@ -11594,7 +11763,12 @@ static int ath12k_mac_mlo_vdev_start(str + arvif_p->pending_up = false; + } + mutex_unlock(&ar->conf_mutex); +- ahvif->num_vdev_started++; ++ /* num vdev started is not needed during mode1 recovery ++ * as the arvif(s) updated are from the existing ++ * list ++ */ ++ if (!ar->ab->recovery_start) ++ ahvif->num_vdev_started++; + } + out: + return ret; +@@ -12650,9 +12824,9 @@ void ath12k_mac_fill_reg_tpc_info(struct + ath12k_ieee80211_ap_pwr_type_convert(reg_6g_power_mode); + } + +-static void ath12k_mac_parse_tx_pwr_env(struct ath12k *ar, +- struct ath12k_link_vif *arvif, +- struct ieee80211_chanctx_conf *ctx) ++void ath12k_mac_parse_tx_pwr_env(struct ath12k *ar, ++ struct ath12k_link_vif *arvif, ++ struct ieee80211_chanctx_conf *ctx) + { + struct ath12k_base *ab = ar->ab; + struct ath12k_vif *ahvif = arvif->ahvif; +@@ -12932,11 +13106,11 @@ ath12k_mac_op_assign_vif_chanctx(struct + goto out; + } + ++ memcpy(&arvif->chanctx, ctx, sizeof(*ctx)); + if (ath12k_mac_is_ml_arvif(arvif) && + ahvif->vdev_type == WMI_VDEV_TYPE_AP) { + mutex_unlock(&ar->conf_mutex); +- memcpy(&arvif->chanctx, ctx, sizeof(*ctx)); +- ret = ath12k_mac_mlo_vdev_start(arvif); ++ ret = ath12k_mac_mlo_vdev_start(arvif, true); + mutex_unlock(&ah->conf_mutex); + return ret; + } +@@ -13130,7 +13304,7 @@ ath12k_mac_op_switch_vif_chanctx(struct + return 0; + } + +-static int ++int + ath12k_set_vdev_param_to_all_vifs(struct ath12k *ar, int param, u32 value) + { + struct ath12k_link_vif *arvif; +@@ -14233,14 +14407,68 @@ out: + mutex_unlock(&ah->conf_mutex); + return ret; + } ++static void ath12k_mac_sta_hw_restart_disconnect(struct ath12k *ar) ++{ ++ struct ath12k_vif *ahvif; ++ struct ath12k_link_vif *arvif; + +-static void +-ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw, +- enum ieee80211_reconfig_type reconfig_type) ++ list_for_each_entry(arvif, &ar->arvifs, list) { ++ ahvif = arvif->ahvif; ++ if (ahvif->vdev_type == WMI_VDEV_TYPE_STA) ++ ieee80211_hw_restart_disconnect(ahvif->vif); ++ } ++} ++ ++static void ath12k_mac_reconfig_completion(struct ath12k *ar, ++ u8 *restart_count) ++{ ++ u8 recovery_count; ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ if (ar->state == ATH12K_STATE_RESTARTED) { ++ if (ar->ab->ag->recovery_mode == ATH12K_MLO_RECOVERY_MODE0) ++ ath12k_mac_sta_hw_restart_disconnect(ar); ++ ath12k_warn(ar->ab, "pdev %d successfully recovered\n", ++ ar->pdev->pdev_id); ++ ar->state = ATH12K_STATE_ON; ++ *restart_count += 1; ++ } ++ ++ if (ar->ab->is_reset) { ++ recovery_count = atomic_inc_return(&ar->ab->recovery_count); ++ ath12k_dbg(ar->ab, ATH12K_DBG_BOOT, ++ "recovery count %d\n", recovery_count); ++ /* When there are multiple radios in an SOC, ++ * the recovery has to be done for each radio ++ */ ++ if (recovery_count == ar->ab->num_radios) { ++ atomic_dec(&ar->ab->reset_count); ++ complete(&ar->ab->reset_complete); ++ ar->ab->is_reset = false; ++ ar->ab->recovery_start = false; ++ atomic_set(&ar->ab->fail_cont_count, 0); ++ clear_bit(ATH12K_FLAG_RECOVERY, &ar->ab->dev_flags); ++ spin_lock_bh(&ar->ab->base_lock); ++ ar->ab->stats.last_recovery_time = ++ jiffies_to_msecs(jiffies - ++ ar->ab->recovery_start_time); ++ spin_unlock_bh(&ar->ab->base_lock); ++ ath12k_dbg(ar->ab, ATH12K_DBG_BOOT, "reset success\n"); ++ } ++ } ++ ++ mutex_unlock(&ar->conf_mutex); ++} ++ ++void ++ath12k_mac_reconfig_complete(struct ieee80211_hw *hw, ++ enum ieee80211_reconfig_type reconfig_type, ++ struct ath12k *asserted_radio) + { + struct ath12k_hw *ah = hw->priv; + struct ath12k *ar; +- u8 restart_count = 0, recovery_count; ++ u8 restart_count = 0; + int i; + + if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART) +@@ -14250,42 +14478,21 @@ ath12k_mac_op_reconfig_complete(struct i + + ar = ah->radio; + +- for (i = 0; i < ah->num_radio; i++) { +- mutex_lock(&ar->conf_mutex); +- +- if (ar->state == ATH12K_STATE_RESTARTED) { +- ath12k_warn(ar->ab, "pdev %d successfully recovered\n", +- ar->pdev->pdev_id); +- ar->state = ATH12K_STATE_ON; +- restart_count++; +- } +- +- if (ar->ab->is_reset) { +- recovery_count = atomic_inc_return(&ar->ab->recovery_count); +- ath12k_dbg(ar->ab, ATH12K_DBG_BOOT, +- "recovery count %d\n", recovery_count); +- /* When there are multiple radios in an SOC, +- * the recovery has to be done for each radio +- */ +- if (recovery_count == ar->ab->num_radios) { +- atomic_dec(&ar->ab->reset_count); +- complete(&ar->ab->reset_complete); +- ar->ab->is_reset = false; +- atomic_set(&ar->ab->fail_cont_count, 0); +- clear_bit(ATH12K_FLAG_RECOVERY, &ar->ab->dev_flags); +- spin_lock_bh(&ar->ab->base_lock); +- ar->ab->stats.last_recovery_time = +- jiffies_to_msecs(jiffies - +- ar->ab->recovery_start_time); +- spin_unlock_bh(&ar->ab->base_lock); +- ath12k_dbg(ar->ab, ATH12K_DBG_BOOT, "reset success\n"); +- } +- } ++ if (asserted_radio) { ++ ath12k_mac_reconfig_completion(asserted_radio, &restart_count); ++ goto out; ++ } + +- mutex_unlock(&ar->conf_mutex); ++ for (i = 0; i < ah->num_radio; i++) { ++ ath12k_mac_reconfig_completion(ar, &restart_count); + ar++; + } + ++out: ++ /* If is_one_radio flag is set, then assume other radios ++ * are up and running and wake queues once the reconfig is ++ * done ++ */ + if (restart_count == ah->num_radio) + ieee80211_wake_queues(ah->hw); + +@@ -14293,6 +14500,12 @@ ath12k_mac_op_reconfig_complete(struct i + ah->ag->hw_queues_stopped = false; + } + ++static void ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw, ++ enum ieee80211_reconfig_type reconfig_type) ++{ ++ ath12k_mac_reconfig_complete(hw, reconfig_type, NULL); ++} ++ + static void + ath12k_mac_update_bss_chan_survey(struct ath12k *ar, + struct ieee80211_channel *channel) +--- a/drivers/net/wireless/ath/ath12k/mac.h ++++ b/drivers/net/wireless/ath/ath12k/mac.h +@@ -14,6 +14,7 @@ struct ath12k; + struct ath12k_base; + struct ath12k_hw; + struct ath12k_hw_group; ++struct ath12k_link_sta; + + struct ath12k_generic_iter { + struct ath12k *ar; +@@ -242,4 +243,43 @@ void ath12k_mac_background_dfs_event(str + enum ath12k_background_dfs_events ev); + bool ath12k_mac_tx_check_max_limit(struct ath12k *ar, struct sk_buff *skb); + int ath12k_mac_mlo_teardown_with_umac_reset(struct ath12k_base *ab); ++void ath12k_mac_bss_info_changed(struct ath12k *ar, ++ struct ath12k_link_vif *arvif, ++ struct ieee80211_bss_conf *info, ++ u64 changed); ++int ath12k_mac_radio_start(struct ath12k *ar); ++int ath12k_mac_conf_tx(struct ath12k *ar, ++ struct ath12k_link_vif *arvif, u16 ac, ++ const struct ieee80211_tx_queue_params *params); ++int ath12k_mac_set_key(struct ath12k *ar, ++ enum set_key_cmd cmd, ++ struct ath12k_link_vif *arvif, ++ struct ath12k_link_sta *arsta, ++ struct ieee80211_key_conf *key); ++ ++int ath12k_mac_update_sta_state(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_sta *sta, ++ enum ieee80211_sta_state old_state, ++ enum ieee80211_sta_state new_state); ++void ath12k_mgmt_rx_reo_init_timer(struct ath12k_hw_group *ag); ++int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif); ++void ath12k_mac_vif_cache_flush(struct ath12k *ar, struct ieee80211_vif *vif, ++ u8 link_id); ++void ath12k_mac_parse_tx_pwr_env(struct ath12k *ar, ++ struct ath12k_link_vif *arvif, ++ struct ieee80211_chanctx_conf *ctx); ++int ath12k_mac_monitor_start(struct ath12k *ar); ++int ath12k_mac_mlo_vdev_start(struct ath12k_link_vif *arvif, bool flag); ++int ath12k_mac_vdev_start(struct ath12k_link_vif *arvif, ++ const struct cfg80211_chan_def *chandef, ++ bool radar_enabled); ++int ath12k_mac_monitor_vdev_create(struct ath12k *ar); ++int ath12k_mac_monitor_vdev_delete(struct ath12k *ar); ++int ath12k_mac_monitor_stop(struct ath12k *ar); ++int ath12k_set_vdev_param_to_all_vifs(struct ath12k *ar, int param, u32 value); ++void ath12k_mac_reconfig_complete(struct ieee80211_hw *hw, ++ enum ieee80211_reconfig_type reconfig_type, ++ struct ath12k *asserted_radio); ++int ath12k_mac_partner_peer_cleanup(struct ath12k_base *ab); + #endif +--- a/drivers/net/wireless/ath/ath12k/peer.c ++++ b/drivers/net/wireless/ath/ath12k/peer.c +@@ -406,7 +406,7 @@ int ath12k_wait_for_peer_delete_done(str + return 0; + } + +-static int ath12k_peer_delete_send(struct ath12k *ar, u32 vdev_id, u8 *addr) ++int ath12k_peer_delete_send(struct ath12k *ar, u32 vdev_id, u8 *addr) + { + struct ath12k_peer *peer; + struct ath12k_base *ab = ar->ab; +--- a/drivers/net/wireless/ath/ath12k/peer.h ++++ b/drivers/net/wireless/ath/ath12k/peer.h +@@ -118,6 +118,7 @@ void ath12k_peer_rhash_tbl_destroy(struc + int ath12k_peer_rhash_delete(struct ath12k_base *ab, struct ath12k_peer *peer); + void ath12k_peer_mlo_map_event(struct ath12k_base *ab, struct sk_buff *skb); + void ath12k_peer_mlo_unmap_event(struct ath12k_base *ab, struct sk_buff *skb); ++int ath12k_peer_delete_send(struct ath12k *ar, u32 vdev_id, u8 *addr); + + static inline + struct ath12k_link_sta *ath12k_peer_get_link_sta(struct ath12k_base *ab, +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -8499,6 +8499,14 @@ static const char *ath12k_wmi_vdev_resp_ + return "dfs violation"; + case WMI_VDEV_START_RESPONSE_INVALID_REGDOMAIN: + return "invalid regdomain"; ++ case WMI_VDEV_START_RESPONSE_INVALID_BAND: ++ return "invalid band"; ++ case WMI_VDEV_START_RESPONSE_INVALID_PREFERRED_TX_RX_STREAMS: ++ /** Invalid preferred tx/rx streams */ ++ return "invalid TX/RX streams"; ++ case WMI_VDEV_START_RESPONSE_INVALID_TX_VAP_CONFIG: ++ /** Invalid tx_vap config in VDEV start */ ++ return "invalid tx vap config"; + default: + return "unknown"; + } +@@ -13188,10 +13196,8 @@ static void ath12k_wmi_event_teardown_co + complete_flag = false; + } + +- if (complete_flag) { ++ if (complete_flag && ag->recovery_mode == ATH12K_MLO_RECOVERY_MODE1) + complete(&ag->umac_reset_complete); +- ag->trigger_umac_reset = false; +- } + } + + static void ath12k_wmi_process_mvr_event(struct ath12k *ab, u32 *vdev_id_bm, +@@ -14133,7 +14139,6 @@ int ath12k_wmi_mlo_setup(struct ath12k * + dev_kfree_skb(skb); + } + +- ar->ab->mlo_complete_event = false; + return ret; + } + +@@ -14161,7 +14166,6 @@ int ath12k_wmi_mlo_ready(struct ath12k * + dev_kfree_skb(skb); + } + +- ar->ab->mlo_complete_event = false; + return ret; + } + +@@ -14191,6 +14195,7 @@ int ath12k_wmi_mlo_teardown(struct ath12 + dev_kfree_skb(skb); + } + ++ ar->ab->mlo_complete_event = false; + return ret; + } + +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -4816,6 +4816,10 @@ enum wmi_vdev_start_resp_status_code { + WMI_VDEV_START_RESPONSE_NOT_SUPPORTED = 2, + WMI_VDEV_START_RESPONSE_DFS_VIOLATION = 3, + WMI_VDEV_START_RESPONSE_INVALID_REGDOMAIN = 4, ++ /** Band unsupported by current hw mode in VDEV start */ ++ WMI_VDEV_START_RESPONSE_INVALID_BAND = 5, ++ WMI_VDEV_START_RESPONSE_INVALID_PREFERRED_TX_RX_STREAMS = 6, /** Invalid preferred tx/rx streams */ ++ WMI_VDEV_START_RESPONSE_INVALID_TX_VAP_CONFIG = 7, /** Invalid tx_vap config in VDEV start */ + }; + + ; diff --git a/feeds/ipq95xx/mac80211/patches/qca/802-ath12k-validate-peer-id-for-search.patch b/feeds/ipq95xx/mac80211/patches/qca/802-ath12k-validate-peer-id-for-search.patch new file mode 100644 index 000000000..fdd3f0877 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/802-ath12k-validate-peer-id-for-search.patch @@ -0,0 +1,55 @@ +From 3c9af747ef156b4c9265a3b59d2e48d668423b8f Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Wed, 12 Jul 2023 09:37:29 +0530 +Subject: [PATCH] ath12k: validate peer id before searching for peer + +HW may pass invalid peer id(=16383) in error scenarios. +Avoid searching the peer list for this peer id, rather +return NULL. + +Signed-off-by: Sriram R +--- + drivers/net/wireless/ath/ath12k/dp.h | 2 ++ + drivers/net/wireless/ath/ath12k/peer.c | 6 ++++++ + 2 files changed, 8 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h +index 8e3654d..39d7c53 100644 +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -2309,6 +2309,8 @@ static inline void ath12k_dp_get_mac_addr(u32 addr_l32, u16 addr_h16, u8 *addr) + #define ATH12K_ML_PEER_ID GENMASK(13, 0) + #define ATH12K_ML_PEER_ID_VALID BIT(13) + ++#define ATH12K_PEER_ID_INVALID 0x3FFF ++ + #define ATH12K_HTT_MLO_PEER_MAP_TLV_LINK_INFO_TAG 0 + #define ATH12K_HTT_MAX_MLO_LINKS 3 + #define ATH12K_HTT_MLO_CHIP_ID GENMASK(2, 0) +diff --git a/drivers/net/wireless/ath/ath12k/peer.c b/drivers/net/wireless/ath/ath12k/peer.c +index 419921a..a9f41da 100644 +--- a/drivers/net/wireless/ath/ath12k/peer.c ++++ b/drivers/net/wireless/ath/ath12k/peer.c +@@ -79,6 +79,9 @@ struct ath12k_peer *ath12k_peer_find_list_by_id(struct ath12k_base *ab, + + lockdep_assert_held(&ab->base_lock); + ++ if (peer_id == ATH12K_PEER_ID_INVALID) ++ return NULL; ++ + if (peer_id & ATH12K_ML_PEER_ID_VALID) { + return ath12k_peer_find_by_ml_id(ab, peer_id); + } else { +@@ -96,6 +99,9 @@ struct ath12k_peer *ath12k_peer_find_by_id(struct ath12k_base *ab, + { + lockdep_assert_held(&ab->base_lock); + ++ if (peer_id == ATH12K_PEER_ID_INVALID) ++ return NULL; ++ + if (peer_id & ATH12K_ML_PEER_ID_VALID) { + return ath12k_peer_find_by_ml_id(ab, peer_id); + } else { +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/802-wifi-ath12k-add-support-to-enqueue-radio-measurement.patch b/feeds/ipq95xx/mac80211/patches/qca/802-wifi-ath12k-add-support-to-enqueue-radio-measurement.patch new file mode 100644 index 000000000..0de860052 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/802-wifi-ath12k-add-support-to-enqueue-radio-measurement.patch @@ -0,0 +1,143 @@ +From b0416d287b8012ca4326580cab8f71fe9cf3f70f Mon Sep 17 00:00:00 2001 +From: Rameshkumar Sundaram +Date: Mon, 24 Jul 2023 10:29:24 +0530 +Subject: [PATCH] wifi: ath12k: add support to enqueue radio measurement frame + at MLD level + +Currently, RRM action frames to a certain link station +gets transmitted by FW or dropped due to retransmissions if that +link station is inactive or in power save state. A ML client can +decide to use only one of its links or can decide to put it in +power save for longer periods while listening on the other link +as per MLD listen interval. In such cases allow FW to decide on +which link a certain management frame needs to be transmitted on. + +Curenly deauth and dissassoc frames are enqueued as link agnostic, +extend the same for RRM beacon and neighbor req/resp action frames. + +Signed-off-by: Rameshkumar Sundaram +--- + drivers/net/wireless/ath/ath12k/mac.c | 29 +++++++++++++++++---------- + include/linux/ieee80211.h | 1 + + 2 files changed, 19 insertions(+), 11 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -8778,7 +8778,7 @@ static int ath12k_mac_mgmt_action_frame_ + struct sk_buff *skb) + { + struct ath12k *ar = arvif->ar; +- struct ath12k_skb_cb *skb_cb; ++ struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB(skb); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_mgmt *mgmt; + struct ieee80211_bss_conf *link_conf; +@@ -8792,8 +8792,10 @@ static int ath12k_mac_mgmt_action_frame_ + lockdep_assert_held(&ar->conf_mutex); + + /* make sure category field is present */ +- if (skb->len < IEEE80211_MIN_ACTION_SIZE) ++ if (skb->len < IEEE80211_MIN_ACTION_SIZE) { ++ skb_cb->flags &= ~ATH12K_SKB_MGMT_LINK_AGNOSTIC; + return -EINVAL; ++ } + + has_protected = ieee80211_has_protected(hdr->frame_control); + +@@ -8801,8 +8803,10 @@ static int ath12k_mac_mgmt_action_frame_ + * we can't put in data in this case + */ + if (test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->ag->dev_flags) && +- has_protected) ++ has_protected) { ++ skb_cb->flags &= ~ATH12K_SKB_MGMT_LINK_AGNOSTIC; + return -EOPNOTSUPP; ++ } + + mgmt = (struct ieee80211_mgmt *)hdr; + buf = &mgmt->u.action; +@@ -8811,8 +8815,6 @@ static int ath12k_mac_mgmt_action_frame_ + * many bytes if it is there + */ + if (has_protected) { +- skb_cb = ATH12K_SKB_CB(skb); +- + switch (skb_cb->cipher) { + /* Currently only for CCMP cipher suite, we asked for it via + * setting %IEEE80211_KEY_FLAG_GENERATE_IV_MGMT in key. Check +@@ -8832,6 +8834,7 @@ static int ath12k_mac_mgmt_action_frame_ + iv_len = 0; + break; + default: ++ skb_cb->flags &= ~ATH12K_SKB_MGMT_LINK_AGNOSTIC; + return -EINVAL; + } + +@@ -8901,6 +8904,7 @@ check_rm_action_frame: + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, + "RRM: Link Measurement Req dialog_token=%u, cur_tx_power=%d, max_tx_power=%d\n", + dialog_token, cur_tx_power, max_tx_power); ++ skb_cb->flags &= ~ATH12K_SKB_MGMT_LINK_AGNOSTIC; + break; + case WLAN_ACTION_RADIO_MSR_LINK_MSR_REP: + /* Variable Len Format: +@@ -8916,6 +8920,7 @@ check_rm_action_frame: + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, + "RRM: Link Measurement Resp dialog_token=%u, cur_tx_power=%d\n", + dialog_token, cur_tx_power); ++ skb_cb->flags &= ~ATH12K_SKB_MGMT_LINK_AGNOSTIC; + break; + default: + return -EINVAL; +@@ -8923,6 +8928,7 @@ check_rm_action_frame: + break; + default: + /* nothing to fill */ ++ skb_cb->flags &= ~ATH12K_SKB_MGMT_LINK_AGNOSTIC; + return 0; + } + +@@ -9004,8 +9010,8 @@ static void ath12k_mgmt_over_wmi_tx_work + ath12k_mgmt_over_wmi_tx_drop(ar, skb); + } else { + ath12k_dbg(ar->ab, ATH12K_DBG_MGMT, +- "mac tx mgmt frame, vdev_id %d\n", +- arvif->vdev_id); ++ "mac tx mgmt frame, vdev_id %d link agnostic %d\n", ++ arvif->vdev_id, !!(skb_cb->flags & ATH12K_SKB_MGMT_LINK_AGNOSTIC)); + } + } else { + ath12k_warn(ar->ab, +@@ -9075,8 +9081,7 @@ static bool ath12k_mac_is_mgmt_link_agno + struct ieee80211_mgmt *mgmt; + mgmt = (struct ieee80211_mgmt *)skb->data; + +- if (ieee80211_is_deauth(mgmt->frame_control) || +- ieee80211_is_disassoc(mgmt->frame_control)) ++ if (ieee80211_is_action(mgmt->frame_control)) + return true; + + /* TODO Extend as per requirement */ +@@ -9178,9 +9183,9 @@ static u8 ath12k_mac_get_tx_link(struct + */ + if (ath12k_mac_is_mgmt_link_agnostic(skb)) { + ATH12K_SKB_CB(skb)->flags |= ATH12K_SKB_MGMT_LINK_AGNOSTIC; +- ath12k_dbg(NULL, ATH12K_DBG_MGMT, +- "Sending Mgmt Frame (fc %x) as link agnostic to ML STA %pM \n", +- hdr->frame_control, sta->addr); ++ /* For action frames this will be reset if not needed ++ * later based on action category. ++ */ + } + } + +--- a/include/linux/ieee80211.h ++++ b/include/linux/ieee80211.h +@@ -3114,6 +3114,7 @@ ieee80211_eht_oper_size_ok(const u8 *dat + #define IEEE80211_SPCT_MSR_RPRT_TYPE_BASIC 0 + #define IEEE80211_SPCT_MSR_RPRT_TYPE_CCA 1 + #define IEEE80211_SPCT_MSR_RPRT_TYPE_RPI 2 ++#define IEEE80211_SPCT_MSR_RPRT_TYPE_BCN 5 + #define IEEE80211_SPCT_MSR_RPRT_TYPE_LCI 8 + #define IEEE80211_SPCT_MSR_RPRT_TYPE_CIVIC 11 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/802-wifi-ath12k-enable-IEEE80211_VHT_EXT_NSS_BW_CAPABLE.patch b/feeds/ipq95xx/mac80211/patches/qca/802-wifi-ath12k-enable-IEEE80211_VHT_EXT_NSS_BW_CAPABLE.patch new file mode 100644 index 000000000..03072a3d7 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/802-wifi-ath12k-enable-IEEE80211_VHT_EXT_NSS_BW_CAPABLE.patch @@ -0,0 +1,52 @@ +From c20f7972e36aa1f47a0a90665da71636f9f4462a Mon Sep 17 00:00:00 2001 +From: Wen Gong +Date: Tue, 27 Dec 2022 01:24:06 -0500 +Subject: [PATCH 067/112] wifi: ath12k: enable IEEE80211_VHT_EXT_NSS_BW_CAPABLE + if NSS ratio enabled +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When NSS ratio enabled reported by firmware, SUPPORTS_VHT_EXT_NSS_BW +is set in ath12k, meanwhile IEEE80211_VHT_EXT_NSS_BW_CAPABLE also +need to be set, otherwise it is invalid because spec in IEEE Std +802.11™‐2020 as below. + +Table 9-273-Supported VHT-MCS and NSS Set subfields, it has subfield +VHT Extended NSS BW Capable, its definition is: +Indicates whether the STA is capable of interpreting the Extended NSS +BW Support subfield of the VHT Capabilities Information field. + +dmesg have a message without this patch: + +ieee80211 phy0: copying sband (band 1) due to VHT EXT NSS BW flag + +It means mac80211 will set IEEE80211_VHT_EXT_NSS_BW_CAPABLE if ath12k not +set it in ieee80211_register_hw(). So it is better to set it in ath11k. + +Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-02582-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1 + +Signed-off-by: Wen Gong +Signed-off-by: Amutha Ravikumar +--- + drivers/net/wireless/ath/ath12k/mac.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index 1a6638e764ac..731676c3f1ca 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -4354,6 +4354,10 @@ ath12k_create_vht_cap(struct ath12k *ar, u32 rate_cap_tx_chainmask, + vht_cap.vht_supported = 1; + vht_cap.cap = ar->pdev->cap.vht_cap; + ++ if (ar->pdev->cap.nss_ratio_enabled) ++ vht_cap.vht_mcs.tx_highest |= ++ cpu_to_le16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE); ++ + ath12k_set_vht_txbf_cap(ar, &vht_cap.cap); + + rxmcs_map = 0; +-- +2.31.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/803-ath12k-reap-CE-entries-if-ring-is-full-and-intrp-idl.patch b/feeds/ipq95xx/mac80211/patches/qca/803-ath12k-reap-CE-entries-if-ring-is-full-and-intrp-idl.patch new file mode 100644 index 000000000..c07d2b9cf --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/803-ath12k-reap-CE-entries-if-ring-is-full-and-intrp-idl.patch @@ -0,0 +1,151 @@ +From 07b3324b76a9cbb654666269980787127b710fa5 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Kathirvel +Date: Tue, 11 Jul 2023 15:30:51 +0530 +Subject: [PATCH 1/3] ath12k: reap CE entries if ring is full and intrp idle + for 500ms + +If there is no buffer to send packet via HTC, then check if +interrupts are not processed from that CE for last 500ms. +If so, schedule a tasklet to reap available entries. + +This change is added because there is a case where intermittently +completion interrupts are not received from CE3 and hence adding +this WAR in host to come out of this issue scenario. + +Signed-off-by: Karthikeyan Kathirvel +--- + drivers/net/wireless/ath/ath12k/ce.c | 40 ++++++++++++++++++++++++--- + drivers/net/wireless/ath/ath12k/ce.h | 4 ++- + drivers/net/wireless/ath/ath12k/hal.c | 7 +++-- + drivers/net/wireless/ath/ath12k/hw.c | 1 + + drivers/net/wireless/ath/ath12k/hw.h | 1 + + 5 files changed, 46 insertions(+), 7 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/ce.c ++++ b/drivers/net/wireless/ath/ath12k/ce.c +@@ -753,6 +753,29 @@ void ath12k_ce_poll_send_completed(struc + ath12k_ce_tx_process_cb(pipe); + } + ++#define CE_RING_FULL_THRESHOLD_TIME_MS 500 ++#define ATH12K_MAX_CE_MANUAL_RETRY 3 ++/* Ths function is called from ce_send path. Returns true If there is no buffer ++ * to send packet via HTC, then check if interrupts are not processed from that ++ * CE for last 500ms. If so, poll manually to reap available entries. ++ */ ++static bool ath12k_is_manual_ce_poll_needed(struct ath12k_base *ab, struct ath12k_ce_pipe *pipe, struct hal_srng *srng) ++{ ++ if (!ab->hw_params->support_ce_manual_poll) ++ return false; ++ ++ if (time_after ++ (jiffies, pipe->timestamp + msecs_to_jiffies(CE_RING_FULL_THRESHOLD_TIME_MS)) && ++ (srng->u.src_ring.hp == srng->u.src_ring.reap_hp) && ++ (srng->u.src_ring.reap_hp == *srng->u.src_ring.tp_addr)) { ++ pipe->ce_manual_poll_count++; ++ pipe->last_ce_manual_poll_ts = jiffies; ++ return true; ++ } ++ ++ return false; ++} ++ + int ath12k_ce_send(struct ath12k_base *ab, struct sk_buff *skb, u8 pipe_id, + u16 transfer_id) + { +@@ -763,7 +786,7 @@ int ath12k_ce_send(struct ath12k_base *a + unsigned int nentries_mask; + int ret = 0; + u8 byte_swap_data = 0; +- int num_used; ++ int num_used, retry = 0; + + /* Check if some entries could be regained by handling tx completion if + * the CE has interrupts disabled and the used entries is more than the +@@ -789,7 +812,7 @@ int ath12k_ce_send(struct ath12k_base *a + + if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags)) + return -ESHUTDOWN; +- ++retry: + spin_lock_bh(&ab->ce.ce_lock); + + write_index = pipe->src_ring->write_index; +@@ -810,8 +833,17 @@ int ath12k_ce_send(struct ath12k_base *a + desc = ath12k_hal_srng_src_get_next_reaped(ab, srng); + if (!desc) { + ath12k_hal_srng_access_end(ab, srng); +- ret = -ENOBUFS; +- goto err_unlock; ++ if (retry++ < ATH12K_MAX_CE_MANUAL_RETRY && ++ ath12k_is_manual_ce_poll_needed(ab, pipe, srng)) { ++ spin_unlock_bh(&srng->lock); ++ spin_unlock_bh(&ab->ce.ce_lock); ++ ++ ath12k_ce_tx_process_cb(pipe); ++ goto retry; ++ } else { ++ ret = -ENOBUFS; ++ goto err_unlock; ++ } + } + + if (pipe->attr_flags & CE_ATTR_BYTE_SWAP_DATA) +--- a/drivers/net/wireless/ath/ath12k/ce.h ++++ b/drivers/net/wireless/ath/ath12k/ce.h +@@ -171,7 +171,9 @@ struct ath12k_ce_pipe { + struct ath12k_ce_ring *src_ring; + struct ath12k_ce_ring *dest_ring; + struct ath12k_ce_ring *status_ring; +- u64 timestamp; ++ unsigned long timestamp; ++ u32 ce_manual_poll_count; ++ u64 last_ce_manual_poll_ts; + }; + + struct ath12k_ce { +--- a/drivers/net/wireless/ath/ath12k/hal.c ++++ b/drivers/net/wireless/ath/ath12k/hal.c +@@ -2567,9 +2567,12 @@ void ath12k_hal_dump_srng_stats(struct a + if (ath12k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) + continue; + +- ath12k_err(ab, "CE_id %d pipe_num %d %ums before\n", ++ ath12k_err(ab,"CE_id %d pipe_num %d %ums before ce_manual_poll_count %d " ++ "ce_last_manual_tasklet_schedule_ts %ums before\n", + i, ce_pipe->pipe_num, +- jiffies_to_msecs(jiffies - ce_pipe->timestamp)); ++ jiffies_to_msecs(jiffies - ce_pipe->timestamp), ++ ce_pipe->ce_manual_poll_count, ++ jiffies_to_msecs(jiffies - ce_pipe->last_ce_manual_poll_ts)); + } + + ath12k_err(ab, "\nLast interrupt received for each group:\n"); +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -1654,6 +1654,7 @@ static struct ath12k_hw_params ath12k_hw + .send_platform_model = false, + .en_fwlog = true, + .support_umac_reset = true, ++ .support_ce_manual_poll = true, + }, + { + .name = "ipq5332 hw1.0", +@@ -1735,6 +1736,7 @@ static struct ath12k_hw_params ath12k_hw + .send_platform_model = true, + .en_fwlog = true, + .support_umac_reset = false, ++ .support_ce_manual_poll=true, + }, + }; + +--- a/drivers/net/wireless/ath/ath12k/hw.h ++++ b/drivers/net/wireless/ath/ath12k/hw.h +@@ -231,6 +231,7 @@ struct ath12k_hw_params { + const struct ce_remap *ce_remap; + const struct cmem_remap *cmem_remap; + bool compact_rx_tlv; ++ bool support_ce_manual_poll; + const struct pmm_remap *pmm_remap; + bool support_umac_reset; + }; diff --git a/feeds/ipq95xx/mac80211/patches/qca/803-wifi-ath12k-Tx-compl-drop-for-NULL-desc.patch b/feeds/ipq95xx/mac80211/patches/qca/803-wifi-ath12k-Tx-compl-drop-for-NULL-desc.patch new file mode 100644 index 000000000..1baab6cb7 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/803-wifi-ath12k-Tx-compl-drop-for-NULL-desc.patch @@ -0,0 +1,91 @@ +From f111d2552435f54da812b389de2c3818c733e348 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Wed, 12 Jul 2023 22:33:09 +0530 +Subject: [PATCH] wifi: ath12k: Tx compl drop for NULL desc + +When Tx completion happen for already completed Tx buffer, skb +will be NULL. It lead to NULL crash. So added the msdu NULL check +and avoid the descriptor processing with DP Statistics account. + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/bondif.c | 2 -- + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/debugfs.c | 7 +++++++ + drivers/net/wireless/ath/ath12k/dp_tx.c | 13 +++++++++++-- + 4 files changed, 19 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -49,6 +49,7 @@ + #define ATH12K_RX_RATE_TABLE_11AX_NUM 576 + + extern unsigned int ath12k_frame_mode; ++extern bool ath12k_debug_critical; + + #define ATH12K_MON_TIMER_INTERVAL 10 + #define ATH12K_RESET_TIMEOUT_HZ (180 * HZ) +@@ -1185,6 +1186,7 @@ struct ath12k_soc_dp_stats { + u32 fw_tx_status[MAX_FW_TX_STATUS]; + u32 tx_enqueued[MAX_TCL_RING]; + u32 tx_completed[MAX_TCL_RING]; ++ u32 null_tx_complete[MAX_TCL_RING]; + u32 bond_tx_ucast_enqueued[MAX_TCL_RING]; + u32 bond_tx_mcast_enqueued[MAX_TCL_RING]; + u32 bond_tx_ucast_dropped[MAX_TCL_RING]; +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -1724,6 +1724,13 @@ static ssize_t ath12k_debugfs_dump_soc_d + soc_stats->tx_enqueued[3]); + + len += scnprintf(buf + len, size - len, ++ "\nnull tx complete: 0:%u 1:%u 2:%u 3:%u\n", ++ soc_stats->null_tx_complete[0], ++ soc_stats->null_tx_complete[1], ++ soc_stats->null_tx_complete[2], ++ soc_stats->null_tx_complete[3]); ++ ++ len += scnprintf(buf + len, size - len, + "\ntx_completed: 0:%u 1:%u 2:%u 3:%u\n", + soc_stats->tx_completed[0], + soc_stats->tx_completed[1], +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -1571,10 +1571,24 @@ int ath12k_dp_tx_completion_handler(stru + recycler_fast_xmit = tx_desc->recycler_fast_xmit; + skb_ext_desc = tx_desc->skb_ext_desc; + timestamp = tx_desc->timestamp; ++ + /* Release descriptor as soon as extracting necessary info + * to reduce contention + */ + ath12k_dp_tx_release_txbuf(dp, tx_desc, tx_desc->pool_id); ++ ++ if (unlikely(!msdu)) { ++ ab->soc_stats.null_tx_complete[tx_ring->tcl_data_ring_id]++; ++ ++ ath12k_err_dump(ab, "Null msdu\n", "Tx compl Desc: ", tx_status, ++ sizeof(*tx_status), NULL); ++ ++ if (ath12k_debug_critical) ++ BUG_ON(1); ++ ++ continue; ++ } ++ + /* Find the HAL_WBM_RELEASE_INFO0_REL_SRC_MODULE value */ + buf_rel_source = tx_status->info0 & HAL_WBM_RELEASE_INFO0_REL_SRC_MASK; + ab->soc_stats.tx_wbm_rel_source[buf_rel_source]++; +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -68,6 +68,10 @@ bool ath12k_mgmt_rx_reordering = false; + module_param_named(mgmt_rx_reorder, ath12k_mgmt_rx_reordering, bool, 0644); + MODULE_PARM_DESC(mgmt_rx_reorder, "Mgmt Rx Re-Ordering (0 - disable, 1 - enable)"); + ++bool ath12k_debug_critical = false; ++module_param_named(debug_critical, ath12k_debug_critical, bool, 0644); ++MODULE_PARM_DESC(debug_critical, "Debug critical issue (0 - disable, 1 - enable)"); ++ + static DEFINE_MUTEX(ath12k_hw_lock); + static struct list_head ath12k_hw_groups = LIST_HEAD_INIT(ath12k_hw_groups); + diff --git a/feeds/ipq95xx/mac80211/patches/qca/804-ath12k-added-a-debugfs-to-dump-hal-srng-stats.patch b/feeds/ipq95xx/mac80211/patches/qca/804-ath12k-added-a-debugfs-to-dump-hal-srng-stats.patch new file mode 100644 index 000000000..a253cf818 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/804-ath12k-added-a-debugfs-to-dump-hal-srng-stats.patch @@ -0,0 +1,152 @@ +From fade99ae4af55f8c722ce4270aab931c1af7627d Mon Sep 17 00:00:00 2001 +From: Karthikeyan Kathirvel +Date: Wed, 12 Jul 2023 11:26:53 +0530 +Subject: [PATCH 2/3] ath12k: added a debugfs to dump hal srng stats + +Added a debugfs to dump hal srng +Cmd ref, + cat /sys/kernel/debug/ath12k/ipq5332\ + hw1.0_c000000.wifi/dump_srng_stats + +Signed-off-by: Karthikeyan Kathirvel +--- + drivers/net/wireless/ath/ath12k/debugfs.c | 32 ++++++++++++ + drivers/net/wireless/ath/ath12k/hal.c | 64 +++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/hal.h | 1 + + 3 files changed, 97 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c +index d1e0a58504e9..b844eaadea0c 100644 +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -1805,6 +1805,35 @@ static const struct file_operations fops_soc_dp_stats = { + .llseek = default_llseek, + }; + ++static ssize_t ath12k_debugfs_hal_dump_srng_stats_read(struct file *file, ++ char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k_base *ab = file->private_data; ++ int len = 0, retval; ++ const int size = 4096 * 6; ++ char *buf; ++ ++ buf = kzalloc(size, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ len = ath12k_debugfs_hal_dump_srng_stats(ab, buf + len, size - len); ++ if (len > size) ++ len = size; ++ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ kfree(buf); ++ ++ return retval; ++} ++ ++static const struct file_operations fops_dump_hal_stats = { ++ .read = ath12k_debugfs_hal_dump_srng_stats_read, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ + static ssize_t ath12k_read_trace_qdss(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +@@ -2266,6 +2295,9 @@ int ath12k_debugfs_pdev_create(struct ath12k_base *ab) + debugfs_create_file("soc_dp_stats", 0600, ab->debugfs_soc, ab, + &fops_soc_dp_stats); + ++ debugfs_create_file("dump_srng_stats", 0600, ab->debugfs_soc, ab, ++ &fops_dump_hal_stats); ++ + debugfs_create_file("trace_qdss", 0600, ab->debugfs_soc, ab, + &fops_trace_qdss); + +diff --git a/drivers/net/wireless/ath/ath12k/hal.c b/drivers/net/wireless/ath/ath12k/hal.c +index cbfc69145254..d89d7603001e 100644 +--- a/drivers/net/wireless/ath/ath12k/hal.c ++++ b/drivers/net/wireless/ath/ath12k/hal.c +@@ -2532,3 +2532,67 @@ void ath12k_hal_dump_srng_stats(struct ath12k_base *ab) + jiffies_to_msecs(jiffies - srng->timestamp)); + } + } ++ ++ssize_t ath12k_debugfs_hal_dump_srng_stats(struct ath12k_base *ab, char *buf, int size) ++{ ++ struct hal_srng *srng; ++ struct ath12k_ext_irq_grp *irq_grp; ++ struct ath12k_ce_pipe *ce_pipe; ++ unsigned int len = 0; ++ int i; ++ ++ len += scnprintf(buf + len, size - len, "Last interrupt received for each CE:\n"); ++ for (i = 0; i < ab->hw_params->ce_count; i++) { ++ ce_pipe = &ab->ce.ce_pipe[i]; ++ ++ if (ath12k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) ++ continue; ++ ++ spin_lock_bh(&ab->ce.ce_lock); ++ len += scnprintf(buf + len, size - len, ++ "CE_id %d pipe_num %d %ums before ce_manual_poll_count %d ce_last_manual_tasklet_schedule_ts %ums before\n", ++ i, ce_pipe->pipe_num, ++ jiffies_to_msecs(jiffies - ce_pipe->timestamp), ++ ce_pipe->ce_manual_poll_count, ++ jiffies_to_msecs(jiffies - ce_pipe->last_ce_manual_poll_ts)); ++ spin_unlock_bh(&ab->ce.ce_lock); ++ } ++ ++ len += scnprintf(buf + len, size - len, "\nLast interrupt received for each group:\n"); ++ for (i = 0; i < ATH12K_EXT_IRQ_GRP_NUM_MAX; i++) { ++ irq_grp = &ab->ext_irq_grp[i]; ++ len += scnprintf(buf + len, size - len, "group_id %d %ums before\n", ++ irq_grp->grp_id, ++ jiffies_to_msecs(jiffies - irq_grp->timestamp)); ++ } ++ ++ for (i = 0; i < HAL_SRNG_RING_ID_MAX; i++) { ++ srng = &ab->hal.srng_list[i]; ++ ++ spin_lock_bh(&srng->lock); ++ if (!srng->initialized) { ++ spin_unlock_bh(&srng->lock); ++ continue; ++ } ++ ++ if (srng->ring_dir == HAL_SRNG_DIR_SRC) ++ len += scnprintf(buf + len, size - len, ++ "src srng id %u hp %u, reap_hp %u, cur tp %u, cached tp %u last tp %u napi processed before %ums\n", ++ srng->ring_id, srng->u.src_ring.hp, ++ srng->u.src_ring.reap_hp, ++ *srng->u.src_ring.tp_addr, srng->u.src_ring.cached_tp, ++ srng->u.src_ring.last_tp, ++ jiffies_to_msecs(jiffies - srng->timestamp)); ++ else if (srng->ring_dir == HAL_SRNG_DIR_DST) ++ len += scnprintf(buf + len, size - len, ++ "dst srng id %u tp %u, cur hp %u, cached hp %u last hp %u napi processed before %ums\n", ++ srng->ring_id, srng->u.dst_ring.tp, ++ *srng->u.dst_ring.hp_addr, ++ srng->u.dst_ring.cached_hp, ++ srng->u.dst_ring.last_hp, ++ jiffies_to_msecs(jiffies - srng->timestamp)); ++ spin_unlock_bh(&srng->lock); ++ } ++ ++ return len; ++} +diff --git a/drivers/net/wireless/ath/ath12k/hal.h b/drivers/net/wireless/ath/ath12k/hal.h +index 465da26ec61c..1b4fe8d2a20d 100644 +--- a/drivers/net/wireless/ath/ath12k/hal.h ++++ b/drivers/net/wireless/ath/ath12k/hal.h +@@ -1308,4 +1308,5 @@ void ath12k_hal_srng_access_umac_dst_ring_end_nolock(struct hal_srng *srng) + srng->timestamp = jiffies; + } + ++ssize_t ath12k_debugfs_hal_dump_srng_stats(struct ath12k_base *ab, char *buf, int size); + #endif +-- +2.38.0 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/805-wifi-ath12k-add-peer-flag-ext-WMI_PEER_EXT_320MHZ-wh.patch b/feeds/ipq95xx/mac80211/patches/qca/805-wifi-ath12k-add-peer-flag-ext-WMI_PEER_EXT_320MHZ-wh.patch new file mode 100644 index 000000000..670fbac0f --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/805-wifi-ath12k-add-peer-flag-ext-WMI_PEER_EXT_320MHZ-wh.patch @@ -0,0 +1,28 @@ +From 09fae321d324f666992c8080629be8f688ea682e Mon Sep 17 00:00:00 2001 +From: Wen Gong +Date: Thu, 14 Jul 2022 06:46:15 -0400 +Subject: [PATCH 084/112] wifi: ath12k: add peer flag ext WMI_PEER_EXT_320MHZ + when 320 MHz enabled + +Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-02582-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1 + +Signed-off-by: Wen Gong +Signed-off-by: Amutha Ravikumar +--- + drivers/net/wireless/ath/ath12k/mac.c | 3 +++ + drivers/net/wireless/ath/ath12k/wmi.c | 2 ++ + drivers/net/wireless/ath/ath12k/wmi.h | 1 + + 3 files changed, 6 insertions(+) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -2830,6 +2830,9 @@ static void ath12k_peer_assoc_h_he_6ghz( + if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160) + arg->bw_160 = true; + ++ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_320) ++ arg->bw_320 = true; ++ + arg->peer_he_caps_6ghz = le16_to_cpu(link_sta->he_6ghz_capa.capa); + arg->peer_mpdu_density = + ath12k_parse_mpdudensity(FIELD_GET(IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START, diff --git a/feeds/ipq95xx/mac80211/patches/qca/805-wifi-ath12k-handle-hw-link-id-in-Rx-err-process.patch b/feeds/ipq95xx/mac80211/patches/qca/805-wifi-ath12k-handle-hw-link-id-in-Rx-err-process.patch new file mode 100644 index 000000000..d9480c057 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/805-wifi-ath12k-handle-hw-link-id-in-Rx-err-process.patch @@ -0,0 +1,65 @@ +From 1352e21d06605b0a70c0bf1ab8f1d1213dee2703 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Sat, 15 Jul 2023 20:17:04 +0530 +Subject: [PATCH] wifi: ath12k: handle hw link id in Rx Error process + +HW reports the hw link across the group formed in QMI. So get the radio +from the hw link id information. Otherwise all frames not handled properly +which lead to idle descriptor not in idle state. + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/dp_rx.c | 29 +++++++++++++++---------- + 1 file changed, 18 insertions(+), 11 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -4355,12 +4355,12 @@ int ath12k_dp_rx_process_err(struct ath1 + struct hal_srng *srng; + struct ath12k_dp *dp; + void *link_desc_va; +- int mac_id; +- struct ath12k *ar; ++ struct ath12k *ar = NULL; + dma_addr_t paddr; + u32 *desc; + bool is_frag, drop = false; + char buf[64] = {0}; ++ u8 hw_link_id; + + tot_n_bufs_reaped = 0; + quota = budget; +@@ -4414,17 +4414,24 @@ int ath12k_dp_rx_process_err(struct ath1 + HAL_WBM_REL_BM_ACT_PUT_IN_IDLE); + } + +- for (i = 0; i < num_msdus; i++) { +- mac_id = u32_get_bits(reo_desc->info0, +- HAL_REO_DEST_RING_INFO0_SRC_LINK_ID); +- if (mac_id >= ab->num_radios) { +- tot_n_bufs_reaped++; +- ath12k_warn(ab, "invalid mac id %d on err process\n", mac_id); +- continue; +- } ++ hw_link_id = u32_get_bits(reo_desc->info0, ++ HAL_REO_DEST_RING_INFO0_SRC_LINK_ID); ++ ++ rcu_read_lock(); ++ if (hw_link_id < ATH12K_GROUP_MAX_RADIO) ++ ar = rcu_dereference(ab->ag->hw_links[hw_link_id]); ++ rcu_read_unlock(); ++ ++ if (!ar || ar->ab != ab) { ++ ath12k_err(ab, "invalid src link id %d drop %d on chip id %d err process\n", ++ hw_link_id, drop, ab->chip_id); + +- ar = ab->pdevs[mac_id].ar; ++ ath12k_err_dump(ab, NULL, "rx err desc: ", reo_desc, ++ sizeof(*reo_desc), srng); ++ BUG_ON(1); ++ } + ++ for (i = 0; i < num_msdus; i++) { + if (drop) + ar->wmm_stats.total_wmm_rx_drop[ar->wmm_stats.rx_type]++; + diff --git a/feeds/ipq95xx/mac80211/patches/qca/806-ath12k-allocate-rx_stats-while-enabling-ext_rx_stats.patch b/feeds/ipq95xx/mac80211/patches/qca/806-ath12k-allocate-rx_stats-while-enabling-ext_rx_stats.patch new file mode 100644 index 000000000..6fa2b11be --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/806-ath12k-allocate-rx_stats-while-enabling-ext_rx_stats.patch @@ -0,0 +1,34 @@ +From a0a4359342ee8847df911405880c3e2e2411d09e Mon Sep 17 00:00:00 2001 +From: P Praneesh +Date: Mon, 24 Jul 2023 14:57:25 +0530 +Subject: [PATCH] ath12k: allocate rx_stats while enabling ext_rx_stats + +rx_stats structure is specific for each station. while enabling ext_rx_stats +through debugfs, this rx_stats gets filled by the value from the monitor ring. +While station associates, without checking ext_rx_stats debugfs state, +memory for rx_stats gets allocated which is unneeded. + +Fix it by checking the ext_rx_stats state before allocating the memory for +rx_stats which helps to provide more headroom incase of multiclient scenario. + +Signed-off-by: P Praneesh +--- + drivers/net/wireless/ath/ath12k/mac.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index 3bc9fc2..1ad42b9 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -6743,7 +6743,7 @@ static int ath12k_mac_station_add(struct ath12k *ar, + goto exit; + } + +- if (!arsta->rx_stats) { ++ if (ath12k_debugfs_is_extd_rx_stats_enabled(ar) && !arsta->rx_stats) { + arsta->rx_stats = kzalloc(sizeof(*arsta->rx_stats), GFP_KERNEL); + if (!arsta->rx_stats) { + ret = -ENOMEM; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/807-a-ath12k-Enable-support-to-convert-multicast-to-unicas.patch b/feeds/ipq95xx/mac80211/patches/qca/807-a-ath12k-Enable-support-to-convert-multicast-to-unicas.patch new file mode 100644 index 000000000..fa974deca --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/807-a-ath12k-Enable-support-to-convert-multicast-to-unicas.patch @@ -0,0 +1,318 @@ +From c2f145f7cb1beb260987e12488c68dff72b0b546 Mon Sep 17 00:00:00 2001 +From: Balamurugan Mahalingam +Date: Mon, 14 Aug 2023 04:53:27 -0700 +Subject: [PATCH 1/2] ath12k: Enable support to convert multicast to unicast + during DS + +Convert the multicast frames to unicast in ath12k driver for the +Direct switch scenarios. The multicast packets are transmitted +through the SW path and its directly delivered to the ath12k layer +using the bonded interface net device operations, convert the multicast +frame to unicast within the driver and transmit it + +Signed-off-by: Balamurugan Mahalingam +--- + drivers/net/wireless/ath/ath12k/bondif.c | 152 ++++++++++++++++++++++- + drivers/net/wireless/ath/ath12k/bondif.h | 2 + + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/mac.c | 5 + + include/net/mac80211.h | 4 + + net/mac80211/cfg.c | 1 + + net/mac80211/driver-ops.h | 20 +++ + 7 files changed, 184 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath12k/bondif.c ++++ b/drivers/net/wireless/ath/ath12k/bondif.c +@@ -7,11 +7,13 @@ + #include + #include + #include ++#include + #include "core.h" + #include "ppe.h" + #include "bondif.h" + #include "debug.h" + #include "dp_tx.h" ++#include "peer.h" + + static const struct net_device_ops ieee80211_link_dataif_8023_ops; + extern struct ath12k_link_vif *ath12k_mac_assign_link_vif( struct ath12k_hw *ah, +@@ -299,6 +301,7 @@ int ath12k_mac_op_change_vif_links(struc + link_ndev_pvt->is_started = false; + link_ndev_pvt->is_bond_enslaved = false; + mldev->vif = vif; ++ mldev->ahvif = ath12k_vif_to_ahvif(vif); + mutex_lock(&vif->bond_mutex); + vif->link_ndev[link_num] = link_ndev; + mutex_unlock(&vif->bond_mutex); +@@ -566,6 +569,97 @@ fail_remove_tx_buf: + return ret; + } + ++static int ath12k_update_da(struct sk_buff *skb, u8 *ucastaddr) ++{ ++ int ret; ++ struct ethhdr *ethhdr; ++ ++ ret = skb_ensure_writable(skb, ETH_HLEN); ++ if (unlikely(ret)) ++ return ret; ++ ++ ethhdr = (void *)skb->data; ++ ether_addr_copy(ethhdr->h_dest, ucastaddr); ++ ++ return 0; ++} ++ ++static int ath12k_convert_to_unicast(struct ath12k_base *ab, struct sk_buff *skb, struct ath12k_vif *orig_ahvif, ++ struct sk_buff_head *queue) ++{ ++ const struct ethhdr *ethhdr; ++ struct ath12k_vif *ahvif; ++ struct ath12k_peer *peer; ++ struct ieee80211_vif *vif; ++ struct sk_buff *skb_new; ++ int ring_id; ++ int ret = 0; ++ ++ if (!skb) ++ return -EINVAL; ++ ++ ethhdr = (struct ethhdr *)skb->data; ++ ++ ring_id = ab->hw_params->hw_ops->get_ring_selector(skb); ++ ++ spin_lock_bh(&ab->base_lock); ++ list_for_each_entry(peer, &ab->peers, list) { ++ vif = peer->vif; ++ ahvif = ath12k_vif_to_ahvif(vif); ++ if (ahvif != orig_ahvif) ++ continue; ++ ++ if(!peer->sta) ++ continue; ++ ++ if (unlikely(ether_addr_equal(ethhdr->h_source, peer->sta->addr))) { ++ /* do not send back to source */ ++ continue; ++ } ++ ++ skb_new = skb_clone(skb, GFP_ATOMIC); ++ if (!skb_new) { ++ ret = -ENOMEM; ++ goto purge; ++ } ++ if (unlikely(ath12k_update_da(skb_new, peer->sta->addr))) { ++ dev_kfree_skb(skb_new); ++ ret = -ENOMEM; ++ goto purge; ++ } ++ __skb_queue_tail(queue, skb_new); ++ } ++ goto out; ++purge: ++ __skb_queue_purge(queue); ++out: ++ spin_unlock_bh(&ab->base_lock); ++ return ret; ++} ++ ++static bool ath12k_dp_mlo_multicast_to_unicast(struct sk_buff *skb, ++ struct net_device *bond_dev) ++{ ++ const struct ethhdr *eth = (void *)skb->data; ++ const struct vlan_ethhdr *ethvlan = (void *)skb->data; ++ __be16 ethertype; ++ ++ ethertype = eth->h_proto; ++ if (ethertype == htons(ETH_P_8021Q) && skb->len >= VLAN_ETH_HLEN) ++ ethertype = ethvlan->h_vlan_encapsulated_proto; ++ switch (ethertype) { ++ case htons(ETH_P_ARP): ++ case htons(ETH_P_IP): ++ case htons(ETH_P_IPV6): ++ break; ++ default: ++ return false; ++ } ++ ++ return true; ++} ++ ++ + int ath12k_dp_mlo_xmit_netdev(struct sk_buff *skb, struct net_device *bond_dev) + { + struct net_device *link_dev = NULL; +@@ -578,10 +672,13 @@ int ath12k_dp_mlo_xmit_netdev(struct sk_ + struct ath12k *tmp_ar; + int is_mcast; + u16 mcbc_gsn; +- int ret; ++ struct sk_buff *skb1; ++ int ret, i; ++ bool is_convert; + int link_id, ring_id = 0; + struct ath12k_skb_cb *skb_cb; + struct ieee80211_tx_info *info; ++ struct sk_buff_head queue; + + if (!(bond_dev->flags & IFF_UP)) { + dev_kfree_skb(skb); +@@ -613,6 +710,34 @@ int ath12k_dp_mlo_xmit_netdev(struct sk_ + return NETDEV_TX_OK; + } + ++ if (ahvif->mcast_to_ucast_en) { ++ is_convert = ath12k_dp_mlo_multicast_to_unicast(skb, bond_dev); ++ ++ if (is_convert) { ++ for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) { ++ arvif = ahvif->link[i]; ++ if (!arvif) ++ continue; ++ ++ __skb_queue_head_init(&queue); ++ ath12k_convert_to_unicast(arvif->ab, skb, ahvif, &queue); ++ while ((skb1 = __skb_dequeue(&queue))) { ++ eh = (struct ethhdr *)skb1->data; ++ link_dev = ath12k_mac_get_tx_link_netdev( mldev, eh->h_dest); ++#ifdef CPTCFG_MAC80211_SFE_SUPPORT ++ skb1->fast_xmit = 0; ++#endif ++ if (link_dev) ++ link_dev->netdev_ops->ndo_start_xmit(skb1, link_dev); ++ else ++ dev_kfree_skb_any(skb1); ++ } ++ } ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_OK; ++ } ++ } ++ + spin_lock(&ahvif->mcbc_gsn_lock); + mcbc_gsn = ahvif->mcbc_gsn++; + if (ahvif->mcbc_gsn > 0xFFF) +@@ -985,3 +1110,21 @@ int ath12k_bond_dev_cb(struct wireless_d + } + return 0; + } ++ ++int ath12k_mac_op_set_multicast_to_unicast(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ const bool enabled) ++{ ++ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); ++ struct wireless_dev *wdev = ieee80211_vif_to_wdev(vif); ++ ++ if (!g_bonded_interface_model) ++ return -ENOTSUPP; ++ ++ if (!wdev->bond_netdev) ++ return -ENOTSUPP; ++ ++ ahvif->mcast_to_ucast_en = enabled; ++ ++ return 0; ++} +--- a/drivers/net/wireless/ath/ath12k/bondif.h ++++ b/drivers/net/wireless/ath/ath12k/bondif.h +@@ -23,6 +23,9 @@ void ath12k_enable_ds_for_link_netdev(st + int ath12k_free_bonddev_for_sfe(struct wireless_dev *wdev, + struct ieee80211_vif *vif, + int link_num); ++int ath12k_mac_op_set_multicast_to_unicast(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ const bool enabled); + int ath12k_bond_link_enslave(struct ath12k_link_vif *arvif, struct net_device *link_dev); + void ath12k_bond_link_release(struct ath12k_link_vif *arvif); + enum ath12k_bond_state { +@@ -36,10 +39,12 @@ enum ath12k_bond_state { + struct ath12k_mld_dev { + struct net_device *netdev; + struct ieee80211_vif *vif; ++ struct ath12k_vif *ahvif; + struct wireless_dev *wdev; //dummy one for bond registration. Optimize Bond MLO API. + struct net_device *link_dev[MAX_MLO_CHIPS][MAX_PDEV_PER_SOC]; + u8 primary_chipid, primary_pdevid; + bool mcast_dev_set; ++ bool mcast_to_ucast_en; + unsigned long bond_state; + }; + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -488,6 +488,7 @@ struct ath12k_vif { + #ifdef CPTCFG_ATH12K_DEBUGFS + struct dentry *debugfs_linkstats; + #endif /* CPTCFG_ATH12K_DEBUGFS */ ++ bool mcast_to_ucast_en; + }; + + struct ath12k_vif_iter { +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -15026,6 +15026,9 @@ static const struct ieee80211_ops ath12k + #endif + .get_txpower = ath12k_mac_op_get_txpower, + .set_radar_background = ath12k_mac_op_set_radar_background, ++#ifdef CPTCFG_ATH12K_BONDED_DS_SUPPORT ++ .set_multicast_to_unicast = ath12k_mac_op_set_multicast_to_unicast, ++#endif + }; + + static void ath12k_mac_update_ch_list(struct ath12k *ar, +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -4690,6 +4690,10 @@ struct ieee80211_ops { + int (*ppeds_detach_vdev)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_ppe_vp_ds_params *vp_params); ++ int (*set_multicast_to_unicast)(struct ieee80211_hw *hw, ++ struct net_device *dev, ++ const bool enabled); ++ + }; + + /** +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -4905,6 +4905,9 @@ static int ieee80211_set_multicast_to_un + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + sdata->u.ap.multicast_to_unicast = enabled; ++#ifdef CPTCFG_MAC80211_PPE_SUPPORT ++ drv_set_multicast_to_unicast(sdata->local, sdata, dev, enabled); ++#endif + + return 0; + } +--- a/net/mac80211/driver-ops.h ++++ b/net/mac80211/driver-ops.h +@@ -1510,6 +1510,26 @@ static inline void drv_twt_teardown_requ + trace_drv_return_void(local); + } + ++#ifdef CPTCFG_MAC80211_PPE_SUPPORT ++static inline int drv_set_multicast_to_unicast(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata, ++ struct net_device *dev, ++ const bool enabled) ++{ ++ struct ieee80211_vif *vif = sdata ? &sdata->vif : NULL; ++ ++ might_sleep(); ++ ++ if (!check_sdata_in_driver(sdata)) ++ return -EIO; ++ ++ if (!local->ops->set_multicast_to_unicast) ++ return -ENOTSUPP; ++ ++ return local->ops->set_multicast_to_unicast(&local->hw, vif, enabled); ++} ++#endif ++ + static inline int drv_ppeds_attach_vdev(struct ieee80211_sub_if_data *sdata, + struct ieee80211_vif *vif, void *vp_arg, + int *ppe_vp_num, diff --git a/feeds/ipq95xx/mac80211/patches/qca/807-ath12k-add-prefetch-msdu-in-dp_tx_completion_handler.patch b/feeds/ipq95xx/mac80211/patches/qca/807-ath12k-add-prefetch-msdu-in-dp_tx_completion_handler.patch new file mode 100644 index 000000000..e13b991ec --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/807-ath12k-add-prefetch-msdu-in-dp_tx_completion_handler.patch @@ -0,0 +1,14 @@ +diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c +index d6fac62..708951d 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -1400,6 +1400,9 @@ int ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id, + continue; + } + ++ prefetch(msdu); ++ prefetch( (u8 *) msdu + 64); ++ + /* Find the HAL_WBM_RELEASE_INFO0_REL_SRC_MODULE value */ + buf_rel_source = tx_status->info0 & HAL_WBM_RELEASE_INFO0_REL_SRC_MASK; + ab->soc_stats.tx_wbm_rel_source[buf_rel_source]++; diff --git a/feeds/ipq95xx/mac80211/patches/qca/807-b-ath12k-Enable-stats-support-for-Multicast-to-Unicast.patch b/feeds/ipq95xx/mac80211/patches/qca/807-b-ath12k-Enable-stats-support-for-Multicast-to-Unicast.patch new file mode 100644 index 000000000..19f4fa383 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/807-b-ath12k-Enable-stats-support-for-Multicast-to-Unicast.patch @@ -0,0 +1,113 @@ +From b57598ed44bb7b1e2501d3692a4dcfdac7da1ca3 Mon Sep 17 00:00:00 2001 +From: Balamurugan Mahalingam +Date: Mon, 14 Aug 2023 05:09:49 -0700 +Subject: [PATCH 2/2] ath12k: Enable stats support for Multicast to Unicast + conversion + +Add stats to debug the mcast2ucast conversion feature. + +Signed-off-by: Balamurugan Mahalingam +--- + drivers/net/wireless/ath/ath12k/bondif.c | 15 +++++++--- + drivers/net/wireless/ath/ath12k/core.h | 3 ++ + drivers/net/wireless/ath/ath12k/debugfs.c | 35 +++++++++++++++++++++++ + 3 files changed, 49 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/bondif.c ++++ b/drivers/net/wireless/ath/ath12k/bondif.c +@@ -595,6 +595,7 @@ static int ath12k_convert_to_unicast(str + struct sk_buff *skb_new; + int ring_id; + int ret = 0; ++ int len = 0; + + if (!skb) + return -EINVAL; +@@ -602,6 +603,7 @@ static int ath12k_convert_to_unicast(str + ethhdr = (struct ethhdr *)skb->data; + + ring_id = ab->hw_params->hw_ops->get_ring_selector(skb); ++ ab->soc_stats.bond_mcast2ucast_tried[ring_id]++; + + spin_lock_bh(&ab->base_lock); + list_for_each_entry(peer, &ab->peers, list) { +@@ -621,16 +623,20 @@ static int ath12k_convert_to_unicast(str + + skb_new = skb_clone(skb, GFP_ATOMIC); + if (!skb_new) { ++ ab->soc_stats.bond_mcast2ucast_drop[ring_id]++; + ret = -ENOMEM; + goto purge; + } + if (unlikely(ath12k_update_da(skb_new, peer->sta->addr))) { ++ ab->soc_stats.bond_mcast2ucast_drop[ring_id]++; + dev_kfree_skb(skb_new); + ret = -ENOMEM; + goto purge; + } + __skb_queue_tail(queue, skb_new); ++ len++; + } ++ ab->soc_stats.bond_mcast2ucast_converted[ring_id] += len; + goto out; + purge: + __skb_queue_purge(queue); +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -1192,6 +1192,12 @@ struct ath12k_soc_dp_stats { + u32 bond_tx_mcast_enqueued[MAX_TCL_RING]; + u32 bond_tx_ucast_dropped[MAX_TCL_RING]; + u32 bond_tx_mcast_dropped[MAX_TCL_RING]; ++ /* Number of frames successfully converted to ucast from mcast */ ++ u32 bond_mcast2ucast_converted[MAX_TCL_RING]; ++ /* Number of mcast frames tried for ucast conversion*/ ++ u32 bond_mcast2ucast_tried[MAX_TCL_RING]; ++ /* Number of times mcast to ucast conversion failed*/ ++ u32 bond_mcast2ucast_drop[MAX_TCL_RING]; + u32 reo_rx[DP_REO_DST_RING_MAX] [ATH12K_MAX_SOCS]; + u32 fast_rx[DP_REO_DST_RING_MAX] [ATH12K_MAX_SOCS]; + u32 non_fast_rx[DP_REO_DST_RING_MAX] [ATH12K_MAX_SOCS]; +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -1738,6 +1738,41 @@ static ssize_t ath12k_debugfs_dump_soc_d + soc_stats->tx_completed[3]); + + ++ len += scnprintf(buf + len, size - len, "\nbond_tx_ucast_enqueued: "); ++ for (i = 0; i < MAX_TCL_RING; i++) ++ len += scnprintf(buf + len, size - len,"%u:%u ", ++ i, soc_stats->bond_tx_ucast_enqueued[i]); ++ ++ len += scnprintf(buf + len, size - len, "\nbond_tx_mcast_enqueued: "); ++ for (i = 0; i < MAX_TCL_RING; i++) ++ len += scnprintf(buf + len, size - len, "%u:%u ", ++ i, soc_stats->bond_tx_mcast_enqueued[i]); ++ ++ len += scnprintf(buf + len, size - len, "\nbond_tx_ucast_dropped: "); ++ for (i = 0; i < MAX_TCL_RING; i++) ++ len += scnprintf(buf + len, size - len, "%u:%u ", ++ i, soc_stats->bond_tx_ucast_dropped[i]); ++ ++ len += scnprintf(buf + len, size - len, "\nbond_tx_mcast_dropped: "); ++ for (i = 0; i < MAX_TCL_RING; i++) ++ len += scnprintf(buf + len, size - len, "%u:%u ", ++ i, soc_stats->bond_tx_mcast_dropped[i]); ++ ++ len += scnprintf(buf + len, size - len, "\nbond_mcast2ucast_tried: "); ++ for (i = 0; i < MAX_TCL_RING; i++) ++ len += scnprintf(buf + len, size - len, "%u:%u ", ++ i, soc_stats->bond_mcast2ucast_tried[i]); ++ ++ len += scnprintf(buf + len, size - len, "\nbond_mcast2ucast_converted: "); ++ for (i = 0; i < MAX_TCL_RING; i++) ++ len += scnprintf(buf + len, size - len, "%u:%u ", ++ i, soc_stats->bond_mcast2ucast_converted[i]); ++ ++ len += scnprintf(buf + len, size - len, "\nbond_mcast2ucast_drop: "); ++ for (i = 0; i < MAX_TCL_RING; i++) ++ len += scnprintf(buf + len, size - len, ++ "%u:%u ", i, soc_stats->bond_mcast2ucast_drop[i]); ++ + len += scnprintf(buf + len, size - len, + "\nag tx_pending: %u\n", + atomic_read(&ab->ag->num_dp_tx_pending)); diff --git a/feeds/ipq95xx/mac80211/patches/qca/807-wifi-Ath12k-Removing-mutex-unlock-after-free.patch b/feeds/ipq95xx/mac80211/patches/qca/807-wifi-Ath12k-Removing-mutex-unlock-after-free.patch new file mode 100644 index 000000000..36790c757 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/807-wifi-Ath12k-Removing-mutex-unlock-after-free.patch @@ -0,0 +1,82 @@ +From e1eb87f4f3990d6c8c9709a8e8e175e8ba9a40c0 Mon Sep 17 00:00:00 2001 +From: Avula Sri Charan +Date: Tue, 12 Sep 2023 10:22:34 +0530 +Subject: wifi: Ath12k: Removing mutex unlock after free + +After freeing ag in ath12k_core_hw_group_free we are still +trying to unlock ag->mutex_lock so moving locking sequence +to ath12k_core_put_hw_group to avoid acquiring lock before +ath12k_core_hw_group_free. + +Signed-off-by: Avula Sri Charan +--- + drivers/net/wireless/ath/ath12k/core.c | 31 ++++++++++---------------- + 1 file changed, 12 insertions(+), 19 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -99,15 +99,16 @@ static void ath12k_core_hw_group_free(st + mutex_unlock(&ath12k_hw_lock); + } + +-static void __ath12k_core_put_hw_group(struct ath12k_base *ab) ++void ath12k_core_put_hw_group(struct ath12k_base *ab) + { + struct ath12k_hw_group *ag = ab->ag; + u8 chip_id = ab->chip_id; ++ int num_probed; + + if (!ag) + return; + +- lockdep_assert_held(&ag->mutex_lock); ++ mutex_lock(&ag->mutex_lock); + + if (chip_id >= ag->num_chip) { + ath12k_err(ab, "failed to put Invalid chip id %d in the group id %d max chip %d\n", +@@ -130,17 +131,13 @@ static void __ath12k_core_put_hw_group(s + if (ag->num_probed) + ag->num_probed--; + +- if (!ag->num_probed) +- ath12k_core_hw_group_free(ag); +-} +- +-void ath12k_core_put_hw_group(struct ath12k_base *ab) +-{ +- struct ath12k_hw_group *ag = ab->ag; ++ num_probed = ag->num_probed; + +- mutex_lock(&ag->mutex_lock); +- __ath12k_core_put_hw_group(ab); + mutex_unlock(&ag->mutex_lock); ++ ++ if (!num_probed) ++ ath12k_core_hw_group_free(ag); ++ + } + + static struct ath12k_hw_group * +@@ -2357,9 +2354,7 @@ int ath12k_core_init(struct ath12k_base + return 0; + + err_hw_group: +- mutex_lock(&ag->mutex_lock); +- __ath12k_core_put_hw_group(ab); +- mutex_unlock(&ag->mutex_lock); ++ ath12k_core_put_hw_group(ab); + err_debugfs: + ath12k_debugfs_soc_destroy(ab); + return ret; +@@ -2494,9 +2489,9 @@ void ath12k_core_deinit(struct ath12k_ba + if (ret) + ath12k_err(ab, "failed to un-register ssr notifier callback\n"); + +- __ath12k_core_put_hw_group(ab); +- + mutex_unlock(&ag->mutex_lock); ++ ++ ath12k_core_put_hw_group(ab); + } + + void ath12k_core_free(struct ath12k_base *ab) diff --git a/feeds/ipq95xx/mac80211/patches/qca/807-wifi-mac80211-set-all-links-active-for-station-by-de.patch b/feeds/ipq95xx/mac80211/patches/qca/807-wifi-mac80211-set-all-links-active-for-station-by-de.patch new file mode 100644 index 000000000..0ef74a209 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/807-wifi-mac80211-set-all-links-active-for-station-by-de.patch @@ -0,0 +1,30 @@ +From 489104265b77e5d9b1d32ae4118acb596caa8594 Mon Sep 17 00:00:00 2001 +From: Wen Gong +Date: Thu, 8 Sep 2022 22:24:39 -0400 +Subject: [PATCH 100/112] wifi: mac80211: set all links active for station by + default - 2d37217f46b17cd7bf993e1f2d850a844a1c01b5 wifi: mac80211: isolate + driver from inactive links + +Signed-off-by: Wen Gong +Signed-off-by: Amutha Ravikumar +--- + net/mac80211/link.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/net/mac80211/link.c ++++ b/net/mac80211/link.c +@@ -209,13 +209,8 @@ static void ieee80211_set_vif_links_bitm + + switch (sdata->vif.type) { + case NL80211_IFTYPE_AP: +- /* in an AP all links are always active */ +- sdata->vif.active_links = links; +- break; + case NL80211_IFTYPE_STATION: +- if (sdata->vif.active_links) +- break; +- WARN_ON(hweight16(links) > 1); ++ /* in an AP and STA all links are always active */ + sdata->vif.active_links = links; + break; + default: diff --git a/feeds/ipq95xx/mac80211/patches/qca/808-wifi-mac80211-change-to-use-MLD-address-as-primary-l.patch b/feeds/ipq95xx/mac80211/patches/qca/808-wifi-mac80211-change-to-use-MLD-address-as-primary-l.patch new file mode 100644 index 000000000..6d2d151e8 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/808-wifi-mac80211-change-to-use-MLD-address-as-primary-l.patch @@ -0,0 +1,33 @@ +From 8f1f045ba6302f9d802ec39d163d617796d7edda Mon Sep 17 00:00:00 2001 +From: Wen Gong +Date: Mon, 24 Oct 2022 03:33:26 -0400 +Subject: [PATCH 101/112] wifi: mac80211: change to use MLD address as primary + link local address + +Changes to set MLD address as primary link address +during link setup + +Signed-off-by: Wen Gong +Signed-off-by: Amutha Ravikumar +--- + net/mac80211/mlme.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -6284,9 +6284,14 @@ void ieee80211_mgd_setup_link(struct iee + INIT_WORK(&link->u.mgd.chswitch_work, ieee80211_chswitch_work); + timer_setup(&link->u.mgd.chswitch_timer, ieee80211_chswitch_timer, 0); + +- if (sdata->u.mgd.assoc_data) ++ if (sdata->u.mgd.assoc_data) { + ether_addr_copy(link->conf->addr, + sdata->u.mgd.assoc_data->link[link_id].addr); ++ } else if (link != &sdata->deflink) { ++ ether_addr_copy(link->conf->addr, sdata->vif.addr); ++ } else if (!is_valid_ether_addr(link->conf->addr)) { ++ eth_random_addr(link->conf->addr); ++ } + } + + /* scan finished notification */ diff --git a/feeds/ipq95xx/mac80211/patches/qca/810-wifi-mac80211-update-all-links-rx-nss-by-ieee80211_s.patch b/feeds/ipq95xx/mac80211/patches/qca/810-wifi-mac80211-update-all-links-rx-nss-by-ieee80211_s.patch new file mode 100644 index 000000000..9e65f7e85 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/810-wifi-mac80211-update-all-links-rx-nss-by-ieee80211_s.patch @@ -0,0 +1,36 @@ +From 17872ee9e9dace35d820086e7aa22158ff9ecce5 Mon Sep 17 00:00:00 2001 +From: Wen Gong +Date: Sat, 10 Sep 2022 11:43:50 -0400 +Subject: [PATCH 103/112] wifi: mac80211: update all links rx nss by + ieee80211_sta_set_rx_nss() in ieee80211_assoc_success() + +Made changes to update all links rx nss by using +ieee80211_sta_set_rx_nss + +Signed-off-by: Wen Gong +Signed-off-by: Amutha Ravikumar +--- + net/mac80211/mlme.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 517ad065118d..820db02342a1 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -5081,6 +5081,13 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, + ieee80211_vif_set_links(sdata, valid_links); + + rate_control_rate_init(sta); ++ for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) { ++ if (!(sta->sta.valid_links & BIT(link_id)) || ++ sta->deflink.link_id == link_id) ++ continue; ++ ++ ieee80211_sta_set_rx_nss(sta->link[link_id]); ++ } + + if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED) { + set_sta_flag(sta, WLAN_STA_MFP); +-- +2.31.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/813-wifi-nl80211-indicate-MLO-connection-info-for-NL8021.patch b/feeds/ipq95xx/mac80211/patches/qca/813-wifi-nl80211-indicate-MLO-connection-info-for-NL8021.patch new file mode 100644 index 000000000..293be9573 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/813-wifi-nl80211-indicate-MLO-connection-info-for-NL8021.patch @@ -0,0 +1,164 @@ +From c2bc42c217f7e48269b07c08dcce38460f950eb6 Mon Sep 17 00:00:00 2001 +From: Wen Gong +Date: Thu, 15 Sep 2022 23:46:50 -0400 +Subject: [PATCH 107/112] wifi: nl80211: indicate MLO connection info for + NL80211_CMD_ASSOCIATE + +Add MLO connection information during association + +Signed-off-by: Wen Gong +Signed-off-by: Amutha Ravikumar +--- + net/wireless/mlme.c | 2 +- + net/wireless/nl80211.c | 60 ++++++++++++++++++++++++++++++++++++------ + net/wireless/nl80211.h | 3 ++- + 3 files changed, 55 insertions(+), 10 deletions(-) + +diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c +index 81d3f40d6235..346e7c03a7a9 100644 +--- a/net/wireless/mlme.c ++++ b/net/wireless/mlme.c +@@ -89,7 +89,7 @@ void cfg80211_rx_assoc_resp(struct net_device *dev, + return; + } + +- nl80211_send_rx_assoc(rdev, dev, data); ++ nl80211_send_rx_assoc(rdev, dev, data, &cr); + /* update current_bss etc., consumes the bss reference */ + __cfg80211_connect_result(dev, &cr, cr.status == WLAN_STATUS_SUCCESS); + } +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 9b342e96abd3..47ef25c9b106 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -17694,12 +17694,26 @@ static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev, + const u8 *buf, size_t len, + enum nl80211_commands cmd, gfp_t gfp, + int uapsd_queues, const u8 *req_ies, +- size_t req_ies_len, bool reconnect) ++ size_t req_ies_len, bool reconnect, ++ struct cfg80211_connect_resp_params *cr) + { + struct sk_buff *msg; + void *hdr; ++ unsigned int link; ++ size_t link_info_size = 0; + +- msg = nlmsg_new(100 + len + req_ies_len, gfp); ++ if (cr && cr->valid_links) { ++ for_each_valid_link(cr, link) { ++ /* Nested attribute header */ ++ link_info_size += NLA_HDRLEN; ++ /* Link ID */ ++ link_info_size += nla_total_size(sizeof(u8)); ++ link_info_size += cr->links[link].addr ? ++ nla_total_size(ETH_ALEN) : 0; ++ } ++ } ++ ++ msg = nlmsg_new(100 + len + req_ies_len + link_info_size, gfp); + if (!msg) + return; + +@@ -17732,6 +17746,34 @@ static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev, + nla_nest_end(msg, nla_wmm); + } + ++ if (cr && cr->valid_links) { ++ int i = 1; ++ struct nlattr *nested; ++ ++ nested = nla_nest_start(msg, NL80211_ATTR_MLO_LINKS); ++ if (!nested) ++ goto nla_put_failure; ++ ++ for_each_valid_link(cr, link) { ++ struct nlattr *nested_mlo_links; ++ ++ nested_mlo_links = nla_nest_start(msg, i); ++ if (!nested_mlo_links) ++ goto nla_put_failure; ++ ++ if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link) || ++ (cr->links[link].addr && ++ nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ++ cr->links[link].addr))) ++ goto nla_put_failure; ++ ++ nla_nest_end(msg, nested_mlo_links); ++ i++; ++ } ++ nla_nest_end(msg, nested); ++ } ++ ++ + genlmsg_end(msg, hdr); + + genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, +@@ -17748,17 +17790,19 @@ void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev, + { + nl80211_send_mlme_event(rdev, netdev, buf, len, + NL80211_CMD_AUTHENTICATE, gfp, -1, NULL, 0, +- false); ++ false, NULL); + } + + void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev, + struct net_device *netdev, +- struct cfg80211_rx_assoc_resp *data) ++ struct cfg80211_rx_assoc_resp *data, ++ struct cfg80211_connect_resp_params *cr) + { + nl80211_send_mlme_event(rdev, netdev, data->buf, data->len, + NL80211_CMD_ASSOCIATE, GFP_KERNEL, + data->uapsd_queues, +- data->req_ies, data->req_ies_len, false); ++ data->req_ies, data->req_ies_len, false, ++ cr); + } + + void nl80211_send_deauth(struct cfg80211_registered_device *rdev, +@@ -17767,7 +17811,7 @@ void nl80211_send_deauth(struct cfg80211_registered_device *rdev, + { + nl80211_send_mlme_event(rdev, netdev, buf, len, + NL80211_CMD_DEAUTHENTICATE, gfp, -1, NULL, 0, +- reconnect); ++ reconnect, NULL); + } + + void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, +@@ -17776,7 +17820,7 @@ void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, + { + nl80211_send_mlme_event(rdev, netdev, buf, len, + NL80211_CMD_DISASSOCIATE, gfp, -1, NULL, 0, +- reconnect); ++ reconnect, NULL); + } + + void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf, +@@ -17807,7 +17851,7 @@ void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf, + + trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len); + nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC, -1, +- NULL, 0, false); ++ NULL, 0, false, NULL); + } + EXPORT_SYMBOL(cfg80211_rx_unprot_mlme_mgmt); + +diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h +index 0278d817bb02..56d4b89bbea7 100644 +--- a/net/wireless/nl80211.h ++++ b/net/wireless/nl80211.h +@@ -60,7 +60,8 @@ void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev, + const u8 *buf, size_t len, gfp_t gfp); + void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev, + struct net_device *netdev, +- struct cfg80211_rx_assoc_resp *data); ++ struct cfg80211_rx_assoc_resp *data, ++ struct cfg80211_connect_resp_params *cr); + void nl80211_send_deauth(struct cfg80211_registered_device *rdev, + struct net_device *netdev, + const u8 *buf, size_t len, +-- +2.31.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/814-wifi-mac80211-fix-recovery-fail-while-firmware-crash.patch b/feeds/ipq95xx/mac80211/patches/qca/814-wifi-mac80211-fix-recovery-fail-while-firmware-crash.patch new file mode 100644 index 000000000..580ce64a7 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/814-wifi-mac80211-fix-recovery-fail-while-firmware-crash.patch @@ -0,0 +1,39 @@ +From 41202931f391c91420622c0301654647bfead311 Mon Sep 17 00:00:00 2001 +From: Wen Gong +Date: Mon, 5 Dec 2022 04:35:27 -0500 +Subject: [PATCH 043/112] wifi: mac80211: fix recovery fail while firmware + crash when doing channel switch + +When firmware crashed while channel switch running, recovery started in +ath12k, then ieee80211_sta_connection_lost() will be called by function +ieee80211_restart_work() in mac80211, then many wmi command timeout +because firmware is crashed, each WMI command cost 3 seconds, then the +total time will be large and lead recovery fail. Change to set value +ATH12K_FLAG_CRASH_FLUSH early and then ath12k_wmi_cmd_send() will not +wait 3 seconds and recovery will be started quickly and success. + +Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-02582-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1 + +Signed-off-by: Wen Gong +Signed-off-by: Amutha Ravikumar +--- + drivers/net/wireless/ath/ath12k/core.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c +index 2063a30e7c6e..0b06cc6fc30f 100644 +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -743,6 +743,9 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab) + ab->stats.fw_crash_counter++; + spin_unlock_bh(&ab->base_lock); + ++ if (ab->is_reset) ++ set_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags); ++ + for (i = 0; i < ab->num_radios; i++) { + pdev = &ab->pdevs[i]; + ar = pdev->ar; +-- +2.31.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/815-wifi-mac80211-temp-remove-link_info_changed-callback.patch b/feeds/ipq95xx/mac80211/patches/qca/815-wifi-mac80211-temp-remove-link_info_changed-callback.patch new file mode 100644 index 000000000..f8b6d8222 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/815-wifi-mac80211-temp-remove-link_info_changed-callback.patch @@ -0,0 +1,32 @@ +From b935f1ce1b13199f3327da86e5d737e55f8c2513 Mon Sep 17 00:00:00 2001 +From: Wen Gong +Date: Tue, 18 Oct 2022 04:04:35 -0400 +Subject: [PATCH 109/112] wifi: mac80211: temp remove link_info_changed + callback for single mlo link + +Temp workaround to avoid crash if sdata->vif.bss_conf +link id is 0, wherease the actual value is 2. + +Signed-off-by: Wen Gong +Signed-off-by: Amutha Ravikumar +--- + net/mac80211/main.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/mac80211/main.c b/net/mac80211/main.c +index 5c7a97921cf0..026718b276fa 100644 +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -243,7 +243,8 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, + local->ops->vif_cfg_changed(&local->hw, &sdata->vif, ch); + } + +- if (changed & ~BSS_CHANGED_VIF_CFG_FLAGS) { ++ if (((!sdata->vif.valid_links) || (sdata->vif.valid_links & BIT(0))) && ++ changed & ~BSS_CHANGED_VIF_CFG_FLAGS) { + u64 ch = changed & ~BSS_CHANGED_VIF_CFG_FLAGS; + + /* FIXME: should be for each link */ +-- +2.31.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/816-wifi-ath12k-send-vdev-down-before-vdev-stop.patch b/feeds/ipq95xx/mac80211/patches/qca/816-wifi-ath12k-send-vdev-down-before-vdev-stop.patch new file mode 100644 index 000000000..72369b11d --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/816-wifi-ath12k-send-vdev-down-before-vdev-stop.patch @@ -0,0 +1,66 @@ +From a8cd89efe40e951937c24612f82e41744929163a Mon Sep 17 00:00:00 2001 +From: Wen Gong +Date: Fri, 23 Sep 2022 06:03:18 -0400 +Subject: [PATCH 110/112] wifi: ath12k: send vdev down before vdev stop + +Made changes to send vdev_down event before vdev_stop +in ath12k_bss_disassoc() + +Signed-off-by: Wen Gong +Signed-off-by: Amutha Ravikumar +--- + drivers/net/wireless/ath/ath12k/mac.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -4055,7 +4055,8 @@ static void ath12k_bss_assoc(struct ath1 + } + + static void ath12k_bss_disassoc(struct ath12k *ar, +- struct ath12k_link_vif *arvif) ++ struct ath12k_link_vif *arvif, ++ bool do_vdev_down) + { + struct ath12k_vif *tx_ahvif; + struct ath12k_link_vif *tx_arvif; +@@ -4064,6 +4065,12 @@ static void ath12k_bss_disassoc(struct a + + lockdep_assert_held(&ar->conf_mutex); + ++ if (do_vdev_down) { ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %i disassoc bssid %pM\n", ++ arvif->vdev_id, arvif->bssid); ++ return; ++ } ++ + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %i disassoc bssid %pM\n", + arvif->vdev_id, arvif->bssid); + +@@ -4666,7 +4673,7 @@ skip_pending_cs_up: + if (vif->cfg.assoc) + ath12k_bss_assoc(ar, arvif, info); + else +- ath12k_bss_disassoc(ar, arvif); ++ ath12k_bss_disassoc(ar, arvif, false); + } + + if (changed & BSS_CHANGED_TXPOWER) { +@@ -4823,7 +4830,7 @@ static void ath12k_mac_op_vif_cfg_change + if (vif->cfg.assoc) + ath12k_bss_assoc(ar, arvif, &vif->bss_conf); + else +- ath12k_bss_disassoc(ar, arvif); ++ ath12k_bss_disassoc(ar, arvif, false); + } + } + +@@ -13153,6 +13160,8 @@ ath12k_mac_op_unassign_vif_chanctx(struc + goto unassign_exit; + } + ++ ath12k_bss_disassoc(ar, arvif, true); ++ + ret = ath12k_mac_vdev_stop(arvif); + if (ret) + ath12k_warn(ab, "failed to stop vdev %i: %d\n", diff --git a/feeds/ipq95xx/mac80211/patches/qca/817-cfg80211-mac80211-Fixes-for-sta-mlo-support.patch b/feeds/ipq95xx/mac80211/patches/qca/817-cfg80211-mac80211-Fixes-for-sta-mlo-support.patch new file mode 100644 index 000000000..ef24594e9 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/817-cfg80211-mac80211-Fixes-for-sta-mlo-support.patch @@ -0,0 +1,54 @@ +From 4859e151de0e853881ae9959c687b6e29ace66d2 Mon Sep 17 00:00:00 2001 +From: Ramasamy Kaliappan +Date: Wed, 21 Jun 2023 10:54:59 +0530 +Subject: [PATCH] cfg80211/mac80211: Fixes for sta mlo support + +Add fixes in cfg80211/80211 to support sta mlo + +Signed-off-by: Ramasamy Kaliappan +--- + net/mac80211/mlme.c | 3 ++- + net/mac80211/rx.c | 4 +++- + 2 files changed, 5 insertions(+), 2 deletions(-) + +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -6875,24 +6875,7 @@ int ieee80211_mgd_assoc(struct ieee80211 + + for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) + size += req->links[i].elems_len; +- +- if (req->ap_mld_addr) { +- for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) { +- if (!req->links[i].bss) +- continue; +- if (i == assoc_link_id) +- continue; +- /* +- * For now, support only a single link in MLO, we +- * don't have the necessary parsing of the multi- +- * link element in the association response, etc. +- */ +- sdata_info(sdata, +- "refusing MLO association with >1 links\n"); +- return -EINVAL; +- } +- } +- ++ + assoc_data = kzalloc(size, GFP_KERNEL); + if (!assoc_data) + return -ENOMEM; +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -5228,7 +5228,9 @@ static bool ieee80211_prepare_and_rx_han + hdr = (struct ieee80211_hdr *)rx->skb->data; + } + +- if (unlikely(rx->sta && rx->sta->sta.mlo)) { ++ if (unlikely(rx->sta && rx->sta->sta.mlo) && ++ is_unicast_ether_addr(hdr->addr1) && ++ !(ieee80211_is_probe_resp(hdr->frame_control))) { + /* translate to MLD addresses */ + if (ether_addr_equal(link->conf->addr, hdr->addr1)) + ether_addr_copy(hdr->addr1, rx->sdata->vif.addr); diff --git a/feeds/ipq95xx/mac80211/patches/qca/818-wifi-ath12k-Changes-for-sta-mlo-support-in-single-wiphy.patch b/feeds/ipq95xx/mac80211/patches/qca/818-wifi-ath12k-Changes-for-sta-mlo-support-in-single-wiphy.patch new file mode 100644 index 000000000..ff4316e00 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/818-wifi-ath12k-Changes-for-sta-mlo-support-in-single-wiphy.patch @@ -0,0 +1,140 @@ +From 3f9b2aecfba008204d51e8550e89493ccd532c9f Mon Sep 17 00:00:00 2001 +From: Ramasamy Kaliappan +Date: Wed, 21 Jun 2023 10:29:43 +0530 +Subject: [PATCH] wifi: ath12k: changes for sta mlo support in single wiphy + +Add the changes for sta mlo single wiphy arch from single netdev arch + +Signed-off-by: Ramasamy Kaliappan +--- + drivers/net/wireless/ath/ath12k/mac.c | 74 ++++++++++++++++----------- + 1 file changed, 43 insertions(+), 31 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -3947,18 +3947,28 @@ static void ath12k_bss_assoc(struct ath1 + bool is_auth = false; + int ret; + struct vdev_up_params params = { 0 }; ++ u8 link_id; ++ u16 he_6ghz_capa; + + lockdep_assert_held(&ar->conf_mutex); + + if (!arvif) + return; + +- ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %i assoc bssid %pM aid %d\n", +- arvif->vdev_id, arvif->bssid, ahvif->aid); ++ link_id = bss_conf->link_id; ++ ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %i link_id:%d assoc bssid %pM aid %d\n", ++ arvif->vdev_id, link_id, arvif->bssid, ahvif->aid); + + rcu_read_lock(); + +- ap_sta = ieee80211_find_sta(vif, bss_conf->bssid); ++// ap_sta = ieee80211_find_sta(vif, bss_conf->bssid); ++ /* TODO, need check correct or not while debug later. ++ * ieee80211_sta should find by MLO address for MLO ++ * or bssid for non-MLO. ++ */ ++ ap_sta = ieee80211_find_sta(vif,vif->cfg.ap_addr); ++ + if (!ap_sta) { + ath12k_warn(ar->ab, "failed to find station entry for bss %pM vdev %i\n", + bss_conf->bssid, arvif->vdev_id); +@@ -3967,10 +3977,10 @@ static void ath12k_bss_assoc(struct ath1 + } + + ahsta = (struct ath12k_sta *)ap_sta->drv_priv; +- arsta = &ahsta->deflink; ++ arsta = ahsta->link[link_id]; + + /* he_cap here is updated at assoc success for sta mode only */ +- he_cap = ap_sta->deflink.he_cap; ++ he_cap = ap_sta->link[link_id]->he_cap; + + ath12k_peer_assoc_prepare(ar, arvif, arsta, &peer_arg, false); + +@@ -3990,9 +4000,11 @@ static void ath12k_bss_assoc(struct ath1 + return; + } + ++ he_6ghz_capa = ap_sta->link[link_id]->he_6ghz_capa.capa; ++ + ret = ath12k_setup_peer_smps(ar, arvif, bss_conf->bssid, +- &ap_sta->deflink.ht_cap, +- le16_to_cpu(ap_sta->deflink.he_6ghz_capa.capa)); ++ &ap_sta->link[link_id]->ht_cap, ++ le16_to_cpu(he_6ghz_capa)); + if (ret) { + ath12k_warn(ar->ab, "failed to setup peer SMPS for vdev %d: %d\n", + arvif->vdev_id, ret); +@@ -4807,6 +4819,9 @@ static void ath12k_mac_op_vif_cfg_change + struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); + struct ath12k_link_vif *arvif; + struct ath12k *ar; ++ unsigned long links_map; ++ unsigned long link_id; ++ struct ieee80211_bss_conf *info; + + if (changed & BSS_CHANGED_SSID && + vif->type == NL80211_IFTYPE_AP) { +@@ -4815,19 +4830,21 @@ static void ath12k_mac_op_vif_cfg_change + memcpy(ahvif->u.ap.ssid, vif->cfg.ssid, vif->cfg.ssid_len); + } + ++ link_id = ahvif->deflink.link_id; ++ links_map = ahvif->links_map; ++ + if (changed & BSS_CHANGED_ASSOC) { +- /* TODO Handle STA ML assoc */ +- arvif = &ahvif->deflink; +- if (!(arvif && arvif->ar)) { +- ath12k_err(NULL, "unable to change vif config\n"); +- return; ++ for_each_set_bit(link_id, &links_map, IEEE80211_MLD_MAX_NUM_LINKS) { ++ arvif = ahvif->link[link_id]; ++ info = vif->link_conf[link_id]; ++ ar = arvif->ar; ++ if (vif->cfg.assoc) { ++ if (info) ++ ath12k_bss_assoc(ar, arvif, info); ++ } else { ++ ath12k_bss_disassoc(ar, arvif, false); ++ } + } +- ar = arvif->ar; +- +- if (vif->cfg.assoc) +- ath12k_bss_assoc(ar, arvif, &vif->bss_conf); +- else +- ath12k_bss_disassoc(ar, arvif, false); + } + } + +@@ -6835,10 +6852,6 @@ static int ath12k_mac_station_remove(str + + lockdep_assert_held(&ar->conf_mutex); + +- /* This would be done separately */ +- if (sta->mlo) +- return 0; +- + ath12k_dp_peer_cleanup(ar, arvif->vdev_id, arsta->addr); + + skip_peer_delete = ar->ab->hw_params->vdev_start_delay && +@@ -7364,12 +7377,6 @@ int ath12k_mac_update_sta_state(struct i + return ret; + } + +- /* Support only AP for now */ +- if (vif->type != NL80211_IFTYPE_AP) { +- ret = -EINVAL; +- goto exit; +- } +- + if (!sta->valid_links && !vif->valid_links) + WARN_ON(1); + diff --git a/feeds/ipq95xx/mac80211/patches/qca/819-wifi-ath12k-Fix-the-crash-during-associate-6G-slo.patch b/feeds/ipq95xx/mac80211/patches/qca/819-wifi-ath12k-Fix-the-crash-during-associate-6G-slo.patch new file mode 100644 index 000000000..fa877ffb3 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/819-wifi-ath12k-Fix-the-crash-during-associate-6G-slo.patch @@ -0,0 +1,33 @@ +From c8ab551c0c2a84b4a0d758d13a1b00d8f9f1864d Mon Sep 17 00:00:00 2001 +From: Ramasamy Kaliappan +Date: Sat, 1 Jul 2023 10:05:50 +0530 +Subject: [PATCH 3/9] wifi: ath12k: war: Fix the crash during associate 6G slo + +Due to the station's 6GHz power mode being unset(0), the station crashes +while trying to acquire a 6GHz psd channel. since the get_psd_channel +contains code to transform reg_6g_power_mode 0 based indexing for AP. + +The workaround added to aviod the crash, The patch should be remove with +potential fix. + +Signed-off-by: Ramasamy Kaliappan +--- + drivers/net/wireless/ath/ath12k/mac.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -12553,9 +12553,11 @@ void ath12k_mac_fill_reg_tpc_info(struct + * AP cant parse its own beacon. Hence, we get the 6g power mode + * from the wdev corresponding to the struct ieee80211_vif + */ +- if (ahvif->vdev_type == WMI_VDEV_TYPE_STA) ++ if (ahvif->vdev_type == WMI_VDEV_TYPE_STA) { + reg_6g_power_mode = bss_conf->power_type; +- else if (ahvif->vdev_type == WMI_VDEV_TYPE_AP) { ++ if (reg_6g_power_mode == IEEE80211_REG_UNSET_AP) ++ reg_6g_power_mode = IEEE80211_REG_LPI_AP; ++ } else if (ahvif->vdev_type == WMI_VDEV_TYPE_AP) { + struct wireless_dev *wdev = ieee80211_vif_to_wdev(vif); + /* With respect to ieee80211, the 6G AP power mode starts from index + * 1 while the power type stored in struct wireless_dev is based on diff --git a/feeds/ipq95xx/mac80211/patches/qca/821-00-wifi-cfg80211-support-reporting-failed-links.patch b/feeds/ipq95xx/mac80211/patches/qca/821-00-wifi-cfg80211-support-reporting-failed-links.patch new file mode 100644 index 000000000..c3d4442a5 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/821-00-wifi-cfg80211-support-reporting-failed-links.patch @@ -0,0 +1,134 @@ +From 20e708b386fa3e0683e2d19af69460f2b48bbffa Mon Sep 17 00:00:00 2001 +From: Ramasamy Kaliappan +Date: Mon, 3 Jul 2023 11:53:40 +0530 +Subject: [PATCH 2/2] cfg80211: support reporting failed links + +For assoc and connect result APIs, support reporting +failed links; they should still come with the BSS +pointer in the case of assoc, so they're released +correctly. In the case of connect result, this is +optional. + +Source: https://www.spinics.net/lists/linux-wireless/msg228130.html + +Signed-off-by: Johannes Berg +Signed-off-by: Ramasamy Kaliappan +--- + include/net/cfg80211.h | 7 +++++++ + net/wireless/mlme.c | 4 ++++ + net/wireless/nl80211.c | 5 ++++- + net/wireless/sme.c | 14 ++++++++++++++ + 4 files changed, 29 insertions(+), 1 deletion(-) + +diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h +index 173487b..e969ca6 100644 +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -7287,6 +7287,8 @@ void cfg80211_auth_timeout(struct net_device *dev, const u8 *addr); + * @ap_mld_addr: AP MLD address (in case of MLO) + * @links: per-link information indexed by link ID, use links[0] for + * non-MLO connections ++ * @links.status: Set this (along with a BSS pointer) for links that ++ * were rejected by the AP. + */ + struct cfg80211_rx_assoc_resp { + const u8 *buf; +@@ -7298,6 +7300,7 @@ struct cfg80211_rx_assoc_resp { + struct { + const u8 *addr; + struct cfg80211_bss *bss; ++ u16 status; + } links[IEEE80211_MLD_MAX_NUM_LINKS]; + }; + +@@ -7808,6 +7811,9 @@ struct cfg80211_fils_resp_params { + * if the bss is expired during the connection, esp. for those drivers + * implementing connect op. Only one parameter among @bssid and @bss needs + * to be specified. ++ * @links.status: per-link status code, to report a status code that's not ++ * %WLAN_STATUS_SUCCESS for a given link, it must also be in the ++ * @valid_links bitmap and may have a BSS pointer (which is then released) + */ + struct cfg80211_connect_resp_params { + int status; +@@ -7824,6 +7830,7 @@ struct cfg80211_connect_resp_params { + const u8 *addr; + const u8 *bssid; + struct cfg80211_bss *bss; ++ u16 status; + } links[IEEE80211_MLD_MAX_NUM_LINKS]; + }; + +diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c +index a14bd55..7b1299e 100644 +--- a/net/wireless/mlme.c ++++ b/net/wireless/mlme.c +@@ -42,6 +42,10 @@ void cfg80211_rx_assoc_resp(struct net_device *dev, + unsigned int link_id; + + for (link_id = 0; link_id < ARRAY_SIZE(data->links); link_id++) { ++ cr.links[link_id].status = data->links[link_id].status; ++ WARN_ON_ONCE(cr.links[link_id].status != WLAN_STATUS_SUCCESS && ++ (!cr.ap_mld_addr || !cr.links[link_id].bss)); ++ + cr.links[link_id].bss = data->links[link_id].bss; + if (!cr.links[link_id].bss) + continue; +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index fb64c2d..b666653 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -18730,6 +18730,7 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev, + link_info_size += (cr->links[link].bssid || + cr->links[link].bss) ? + nla_total_size(ETH_ALEN) : 0; ++ link_info_size += nla_total_size(sizeof(u16)); + } + } + +@@ -18798,7 +18799,9 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev, + nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, bssid)) || + (cr->links[link].addr && + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, +- cr->links[link].addr))) ++ cr->links[link].addr)) || ++ nla_put_u16(msg, NL80211_ATTR_STATUS_CODE, ++ cr->links[link].status)) + goto nla_put_failure; + + nla_nest_end(msg, nested_mlo_links); +diff --git a/net/wireless/sme.c b/net/wireless/sme.c +index 78e7104..e782a00 100644 +--- a/net/wireless/sme.c ++++ b/net/wireless/sme.c +@@ -788,6 +788,10 @@ void __cfg80211_connect_result(struct net_device *dev, + } + + for_each_valid_link(cr, link) { ++ /* don't do extra lookups for failures */ ++ if (cr->links[link].status != WLAN_STATUS_SUCCESS) ++ continue; ++ + if (cr->links[link].bss) + continue; + +@@ -824,6 +828,16 @@ void __cfg80211_connect_result(struct net_device *dev, + } + + memset(wdev->links, 0, sizeof(wdev->links)); ++ for_each_valid_link(cr, link) { ++ if (cr->links[link].status == WLAN_STATUS_SUCCESS) ++ continue; ++ cr->valid_links &= ~BIT(link); ++ /* don't require bss pointer for failed links */ ++ if (!cr->links[link].bss) ++ continue; ++ cfg80211_unhold_bss(bss_from_pub(cr->links[link].bss)); ++ cfg80211_put_bss(wdev->wiphy, cr->links[link].bss); ++ } + wdev->valid_links = cr->valid_links; + for_each_valid_link(cr, link) + wdev->links[link].client.current_bss = +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/821-01-wifi-ieee80211-Support-validating-ML-station-profile-length.patch b/feeds/ipq95xx/mac80211/patches/qca/821-01-wifi-ieee80211-Support-validating-ML-station-profile-length.patch new file mode 100644 index 000000000..5b1aaa2da --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/821-01-wifi-ieee80211-Support-validating-ML-station-profile-length.patch @@ -0,0 +1,61 @@ +wifi: ieee80211: Support validating ML station profile length + +Add a function to validate EHT Multi-Link per station profile length. + +Signed-off-by: Ilan Peer +Signed-off-by: Johannes Berg +--- + include/linux/ieee80211.h | 40 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 40 insertions(+) + +diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h +index 79690938d9a2..bdf668f9dace 100644 +--- a/include/linux/ieee80211.h ++++ b/include/linux/ieee80211.h +@@ -4685,6 +4685,46 @@ struct ieee80211_mle_per_sta_profile { + u8 variable[]; + } __packed; + ++/** ++ * ieee80211_mle_sta_prof_size_ok - validate multi-link element sta profile size ++ * @data: pointer to the sub element data ++ * @len: length of the containing sub element ++ */ ++static inline bool ieee80211_mle_sta_prof_size_ok(const u8 *data, size_t len) ++{ ++ const struct ieee80211_mle_per_sta_profile *prof = (const void *)data; ++ u16 control; ++ u8 fixed = sizeof(*prof); ++ u8 info_len = 1; ++ ++ if (len < fixed) ++ return false; ++ ++ control = le16_to_cpu(prof->control); ++ ++ if (control & IEEE80211_MLE_STA_CONTROL_STA_MAC_ADDR_PRESENT) ++ info_len += 6; ++ if (control & IEEE80211_MLE_STA_CONTROL_BEACON_INT_PRESENT) ++ info_len += 2; ++ if (control & IEEE80211_MLE_STA_CONTROL_TSF_OFFS_PRESENT) ++ info_len += 8; ++ if (control & IEEE80211_MLE_STA_CONTROL_DTIM_INFO_PRESENT) ++ info_len += 2; ++ if (control & IEEE80211_MLE_STA_CONTROL_BSS_PARAM_CHANGE_CNT_PRESENT) ++ info_len += 1; ++ ++ if (control & IEEE80211_MLE_STA_CONTROL_COMPLETE_PROFILE && ++ control & IEEE80211_MLE_STA_CONTROL_NSTR_BITMAP_SIZE) { ++ if (control & IEEE80211_MLE_STA_CONTROL_NSTR_BITMAP_SIZE) ++ info_len += 2; ++ else ++ info_len += 1; ++ } ++ ++ return prof->sta_info_len >= info_len && ++ fixed + prof->sta_info_len <= len; ++} ++ + #define for_each_mle_subelement(_elem, _data, _len) \ + if (ieee80211_mle_size_ok(_data, _len)) \ + for_each_element(_elem, \ diff --git a/feeds/ipq95xx/mac80211/patches/qca/821-02-wifi-cfg80211-mac80211-Fix-ML-element-common-size-calculation.patch b/feeds/ipq95xx/mac80211/patches/qca/821-02-wifi-cfg80211-mac80211-Fix-ML-element-common-size-calculation.patch new file mode 100644 index 000000000..e21414df3 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/821-02-wifi-cfg80211-mac80211-Fix-ML-element-common-size-calculation.patch @@ -0,0 +1,40 @@ +wifi: cfg80211/mac80211: Fix ML element common size calculation + +The common size is part of the length in the data +so don't add it again. + +Signed-off-by: Ilan Peer +Signed-off-by: Johannes Berg +Signed-off-by: Ramasamy Kaliappan +--- + include/linux/ieee80211.h | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h +index bdf668f9dace..442b13333da8 100644 +--- a/include/linux/ieee80211.h ++++ b/include/linux/ieee80211.h +@@ -4573,18 +4573,17 @@ static inline u8 ieee80211_mle_common_size(const u8 *data) + + switch (u16_get_bits(control, IEEE80211_ML_CONTROL_TYPE)) { + case IEEE80211_ML_CONTROL_TYPE_BASIC: +- common += sizeof(struct ieee80211_mle_basic_common_info); +- break; + case IEEE80211_ML_CONTROL_TYPE_PREQ: +- common += sizeof(struct ieee80211_mle_preq_common_info); ++ case IEEE80211_ML_CONTROL_TYPE_TDLS: ++ /* ++ * The length is the first octet pointed by mle->variable so no ++ * need to add anything ++ */ + break; + case IEEE80211_ML_CONTROL_TYPE_RECONF: + if (control & IEEE80211_MLC_RECONF_PRES_MLD_MAC_ADDR) + common += ETH_ALEN; + return common; +- case IEEE80211_ML_CONTROL_TYPE_TDLS: +- common += sizeof(struct ieee80211_mle_tdls_common_info); +- break; + case IEEE80211_ML_CONTROL_TYPE_PRIO_ACCESS: + if (control & IEEE80211_MLC_PRIO_ACCESS_PRES_AP_MLD_MAC_ADDR) + common += ETH_ALEN; diff --git a/feeds/ipq95xx/mac80211/patches/qca/821-03-wifi-cfg80211-mac80211-check-EHT-capability-size-cor.patch b/feeds/ipq95xx/mac80211/patches/qca/821-03-wifi-cfg80211-mac80211-check-EHT-capability-size-cor.patch new file mode 100644 index 000000000..4dd7ededd --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/821-03-wifi-cfg80211-mac80211-check-EHT-capability-size-cor.patch @@ -0,0 +1,522 @@ +From e184ecbe94e7e3d83bcefed6900916506713dfca Mon Sep 17 00:00:00 2001 +From: Ramasamy Kaliappan +Date: Mon, 3 Jul 2023 15:26:04 +0530 +Subject: [PATCH 01/16] wifi: cfg80211/mac80211: check EHT capability size + correctly + +For AP/non-AP the EHT MCS/NSS subfield size differs, the +4-octet subfield is only used for 20 MHz-only non-AP STA. +Pass an argument around everywhere to be able to parse it +properly. + +Cherry picked from the patch: +https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git/commit/?id=ea5cba269fb1fe22b84f4d01bb3d56320e6ffa3e + +Signed-off-by: Johannes Berg +Signed-off-by: Ramasamy Kaliappan +--- + drivers/net/wireless/ath/ath12k/mac.c | 3 +- + include/linux/ieee80211.h | 14 ++++++--- + net/mac80211/eht.c | 11 ++++--- + net/mac80211/ieee80211_i.h | 20 +++++++++++-- + net/mac80211/mesh.c | 2 +- + net/mac80211/mlme.c | 43 +++++++++++++++++++++------ + net/mac80211/util.c | 29 ++++++++++++------ + net/mac80211/vht.c | 3 +- + net/wireless/core.c | 16 ++++++++++ + net/wireless/nl80211.c | 22 ++++++++++---- + 10 files changed, 126 insertions(+), 37 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index 1dd4e41..9cd7fac 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -13593,7 +13593,8 @@ ath12k_mac_bitrate_mask_get_single_nss(struct ath12k *ar, + } + + mcs_nss_len = ieee80211_eht_mcs_nss_size(&sband->iftype_data->he_cap.he_cap_elem, +- &sband->iftype_data->eht_cap.eht_cap_elem); ++ &sband->iftype_data->eht_cap.eht_cap_elem, ++ false); + if (mcs_nss_len == 4) { + /* 20 MHz only STA case */ + const struct ieee80211_eht_mcs_nss_supp_20mhz_only *eht_mcs_nss = +diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h +index 82f50b1..7cc384d 100644 +--- a/include/linux/ieee80211.h ++++ b/include/linux/ieee80211.h +@@ -2922,7 +2922,8 @@ ieee80211_he_spr_size(const u8 *he_spr_ie) + /* Calculate 802.11be EHT capabilities IE Tx/Rx EHT MCS NSS Support Field size */ + static inline u8 + ieee80211_eht_mcs_nss_size(const struct ieee80211_he_cap_elem *he_cap, +- const struct ieee80211_eht_cap_elem_fixed *eht_cap) ++ const struct ieee80211_eht_cap_elem_fixed *eht_cap, ++ bool from_ap) + { + u8 count = 0; + +@@ -2945,7 +2946,10 @@ ieee80211_eht_mcs_nss_size(const struct ieee80211_he_cap_elem *he_cap, + if (eht_cap->phy_cap_info[0] & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ) + count += 3; + +- return count; ++ if (count) ++ return count; ++ ++ return from_ap ? 3 : 4; + } + + /* 802.11be EHT PPE Thresholds */ +@@ -2982,7 +2986,8 @@ ieee80211_eht_ppe_size(u16 ppe_thres_hdr, const u8 *phy_cap_info) + } + + static inline bool +-ieee80211_eht_capa_size_ok(const u8 *he_capa, const u8 *data, u8 len) ++ieee80211_eht_capa_size_ok(const u8 *he_capa, const u8 *data, u8 len, ++ bool from_ap) + { + const struct ieee80211_eht_cap_elem_fixed *elem = (const void *)data; + u8 needed = sizeof(struct ieee80211_eht_cap_elem_fixed); +@@ -2994,7 +2999,8 @@ ieee80211_eht_capa_size_ok(const u8 *he_capa, const u8 *data, u8 len) + return true; + + needed += ieee80211_eht_mcs_nss_size((const void *)he_capa, +- (const void *)data); ++ (const void *)data, ++ from_ap); + if (len < needed) + return false; + +diff --git a/net/mac80211/eht.c b/net/mac80211/eht.c +index 0e46f39..f078e97 100644 +--- a/net/mac80211/eht.c ++++ b/net/mac80211/eht.c +@@ -18,6 +18,7 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(struct ieee80211_sub_if_data *sdata, + struct link_sta_info *link_sta) + { + struct ieee80211_sta_eht_cap *eht_cap = &link_sta->pub->eht_cap; ++ struct ieee80211_he_cap_elem *he_cap_ie_elem = (void *)he_cap_ie; + u8 eht_ppe_size = 0; + u8 mcs_nss_size; + u8 eht_total_size = sizeof(eht_cap->eht_cap_elem); +@@ -31,10 +32,12 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(struct ieee80211_sub_if_data *sdata, + return; + + mcs_nss_size = eht_cap_len - sizeof(struct ieee80211_eht_cap_elem_fixed); +- /* WAR: compute based on capabilities +- * mcs_nss_size = ieee80211_eht_mcs_nss_size(he_cap_ie_elem, +- &eht_cap_ie_elem->fixed); +- */ ++ /* WAR: compute based on capabilities*/ ++ mcs_nss_size = ieee80211_eht_mcs_nss_size(he_cap_ie_elem, ++ &eht_cap_ie_elem->fixed, ++ sdata->vif.type == ++ NL80211_IFTYPE_STATION); ++ + + eht_total_size += mcs_nss_size; + +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index 9ebacaf..45b53ba 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1762,6 +1762,17 @@ struct ieee802_11_elems { + u8 eht_cap_len; + u8 eht_240mhz_len; + ++ /* mult-link element can be de-fragmented and thus u8 is not sufficient */ ++ size_t multi_link_len; ++ ++ /* ++ * store the per station profile pointer and length in case that the ++ * parsing also handled Multi-Link element parsing for a specific link ++ * ID. ++ */ ++ struct ieee80211_mle_per_sta_profile *prof; ++ size_t sta_prof_len; ++ + /* whether a parse error occurred while retrieving these elements */ + bool parse_error; + +@@ -2272,6 +2283,8 @@ static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, + * for that non-transmitting BSS is returned + * @link_id: the link ID to parse elements for, if a STA profile + * is present in the multi-link element, or -1 to ignore ++ * @from_ap: frame is received from an AP (currently used only ++ * for EHT capabilities parsing) + */ + struct ieee80211_elems_parse_params { + const u8 *start; +@@ -2281,6 +2294,7 @@ struct ieee80211_elems_parse_params { + u32 crc; + struct cfg80211_bss *bss; + int link_id; ++ bool from_ap; + }; + + struct ieee802_11_elems * +@@ -2476,7 +2490,8 @@ u8 ieee80211_ie_len_eht_cap(struct ieee80211_sub_if_data *sdata, u8 iftype); + u8 *ieee80211_ie_build_eht_cap(u8 *pos, + const struct ieee80211_sta_he_cap *he_cap, + const struct ieee80211_sta_eht_cap *eht_cap, +- u8 *end); ++ u8 *end, ++ bool for_ap); + u8 *ieee80211_ie_build_eht_oper(u8 *pos, struct cfg80211_chan_def *chandef, + const struct ieee80211_sta_eht_cap *eht_cap); + int ieee80211_parse_bitrates(enum nl80211_chan_width width, +@@ -2618,7 +2633,8 @@ u8 ieee80211_ie_len_eht_cap(struct ieee80211_sub_if_data *sdata, u8 iftype); + u8 *ieee80211_ie_build_eht_cap(u8 *pos, + const struct ieee80211_sta_he_cap *he_cap, + const struct ieee80211_sta_eht_cap *eht_cap, +- u8 *end); ++ u8 *end, ++ bool for_ap); + + void + ieee80211_eht_cap_ie_to_sta_eht_cap(struct ieee80211_sub_if_data *sdata, +diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c +index 12a04a5..170a0dc 100644 +--- a/net/mac80211/mesh.c ++++ b/net/mac80211/mesh.c +@@ -675,7 +675,7 @@ int mesh_add_eht_cap_ie(struct ieee80211_sub_if_data *sdata, + return -ENOMEM; + + pos = skb_put(skb, ie_len); +- ieee80211_ie_build_eht_cap(pos, he_cap, eht_cap, pos + ie_len); ++ ieee80211_ie_build_eht_cap(pos, he_cap, eht_cap, pos + ie_len, false); + + return 0; + } +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index e7644b2..6fa6255 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -771,11 +771,13 @@ static void ieee80211_add_eht_ie(struct ieee80211_sub_if_data *sdata, + eht_cap_size = + 2 + 1 + sizeof(eht_cap->eht_cap_elem) + + ieee80211_eht_mcs_nss_size(&he_cap->he_cap_elem, +- &eht_cap->eht_cap_elem) + ++ &eht_cap->eht_cap_elem, ++ false) + + ieee80211_eht_ppe_size(eht_cap->eht_ppe_thres[0], + eht_cap->eht_cap_elem.phy_cap_info); + pos = skb_put(skb, eht_cap_size); +- ieee80211_ie_build_eht_cap(pos, he_cap, eht_cap, pos + eht_cap_size); ++ ieee80211_ie_build_eht_cap(pos, he_cap, eht_cap, pos + eht_cap_size, ++ false); + } + + static void ieee80211_assoc_add_rates(struct sk_buff *skb, +@@ -3938,6 +3940,7 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link, + .len = elem_len, + .bss = cbss, + .link_id = link == &sdata->deflink ? -1 : link->link_id, ++ .from_ap = true, + }; + bool is_6ghz = cbss->channel->band == NL80211_BAND_6GHZ; + bool is_s1g = cbss->channel->band == NL80211_BAND_S1GHZ; +@@ -4607,6 +4610,11 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, + bool is_6ghz = cbss->channel->band == NL80211_BAND_6GHZ; + bool is_5ghz = cbss->channel->band == NL80211_BAND_5GHZ; + struct ieee80211_bss *bss = (void *)cbss->priv; ++ struct ieee80211_elems_parse_params parse_params = { ++ .bss = cbss, ++ .link_id = -1, ++ .from_ap = true, ++ }; + struct ieee802_11_elems *elems; + const struct cfg80211_bss_ies *ies; + int ret; +@@ -4615,7 +4623,9 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, + rcu_read_lock(); + + ies = rcu_dereference(cbss->ies); +- elems = ieee802_11_parse_elems(ies->data, ies->len, false, cbss); ++ parse_params.start = ies->data; ++ parse_params.len = ies->len; ++ elems = ieee802_11_parse_elems_full(&parse_params); + if (!elems) { + rcu_read_unlock(); + return -ENOMEM; +@@ -4964,6 +4974,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data; + u16 capab_info, status_code, aid; ++ struct ieee80211_elems_parse_params parse_params = { ++ .bss = NULL, ++ .link_id = -1, ++ .from_ap = true, ++ }; + struct ieee802_11_elems *elems; + int ac; + const u8 *elem_start; +@@ -5018,7 +5033,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, + return; + + elem_len = len - (elem_start - (u8 *)mgmt); +- elems = ieee802_11_parse_elems(elem_start, elem_len, false, NULL); ++ parse_params.start = elem_start; ++ parse_params.len = elem_len; ++ elems = ieee802_11_parse_elems_full(&parse_params); + if (!elems) + goto notify_driver; + +@@ -5383,6 +5400,10 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link, + u32 ncrc = 0; + u8 *bssid, *variable = mgmt->u.beacon.variable; + u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN]; ++ struct ieee80211_elems_parse_params parse_params = { ++ .link_id = -1, ++ .from_ap = true, ++ }; + + sdata_assert_lock(sdata); + +@@ -5401,6 +5422,9 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link, + if (baselen > len) + return; + ++ parse_params.start = variable; ++ parse_params.len = len - baselen; ++ + rcu_read_lock(); + chanctx_conf = rcu_dereference(link->conf->chanctx_conf); + if (!chanctx_conf) { +@@ -5419,8 +5443,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link, + if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon && + !WARN_ON(sdata->vif.valid_links) && + ieee80211_rx_our_beacon(bssid, ifmgd->assoc_data->link[0].bss)) { +- elems = ieee802_11_parse_elems(variable, len - baselen, false, +- ifmgd->assoc_data->link[0].bss); ++ parse_params.bss = ifmgd->assoc_data->link[0].bss; ++ elems = ieee802_11_parse_elems_full(&parse_params); + if (!elems) + return; + +@@ -5486,9 +5510,10 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link, + */ + if (!ieee80211_is_s1g_beacon(hdr->frame_control)) + ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4); +- elems = ieee802_11_parse_elems_crc(variable, len - baselen, +- false, care_about_ies, ncrc, +- link->u.mgd.bss); ++ parse_params.bss = link->u.mgd.bss; ++ parse_params.filter = care_about_ies; ++ parse_params.crc = ncrc; ++ elems = ieee802_11_parse_elems_full(&parse_params); + if (!elems) + return; + ncrc = elems->crc; +diff --git a/net/mac80211/util.c b/net/mac80211/util.c +index 11cce4b..d84b116 100644 +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -959,9 +959,11 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw, + } + EXPORT_SYMBOL(ieee80211_queue_delayed_work); + +-static void ieee80211_parse_extension_element(u32 *crc, +- const struct element *elem, +- struct ieee802_11_elems *elems) ++static void ++ieee80211_parse_extension_element(u32 *crc, ++ const struct element *elem, ++ struct ieee802_11_elems *elems, ++ struct ieee80211_elems_parse_params *params) + { + const void *data = elem->data + 1; + u8 len; +@@ -1018,7 +1020,8 @@ static void ieee80211_parse_extension_element(u32 *crc, + break; + case WLAN_EID_EXT_EHT_CAPABILITY: + if (ieee80211_eht_capa_size_ok(elems->he_cap, +- data, len)) { ++ data, len, ++ params->from_ap)) { + elems->eht_cap = data; + elems->eht_cap_len = len; + } +@@ -1390,7 +1393,7 @@ _ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params, + case WLAN_EID_EXTENSION: + ieee80211_parse_extension_element(calc_crc ? + &crc : NULL, +- elem, elems); ++ elem, elems, params); + break; + case WLAN_EID_S1G_CAPABILITIES: + if (elen >= sizeof(*elems->s1g_capab)) +@@ -2033,7 +2036,8 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_sub_if_data *sdata, + cfg80211_any_usable_channels(local->hw.wiphy, BIT(sband->band), + IEEE80211_CHAN_NO_HE | + IEEE80211_CHAN_NO_EHT)) { +- pos = ieee80211_ie_build_eht_cap(pos, he_cap, eht_cap, end); ++ pos = ieee80211_ie_build_eht_cap(pos, he_cap, eht_cap, end, ++ sdata->vif.type == NL80211_IFTYPE_AP); + if (!pos) + goto out_err; + } +@@ -5411,6 +5415,7 @@ u8 ieee80211_ie_len_eht_cap(struct ieee80211_sub_if_data *sdata, u8 iftype) + const struct ieee80211_sta_he_cap *he_cap; + const struct ieee80211_sta_eht_cap *eht_cap; + struct ieee80211_supported_band *sband; ++ bool is_ap; + u8 n; + + sband = ieee80211_get_sband(sdata); +@@ -5422,8 +5427,12 @@ u8 ieee80211_ie_len_eht_cap(struct ieee80211_sub_if_data *sdata, u8 iftype) + if (!he_cap || !eht_cap) + return 0; + ++ is_ap = iftype == NL80211_IFTYPE_AP || ++ iftype == NL80211_IFTYPE_P2P_GO; ++ + n = ieee80211_eht_mcs_nss_size(&he_cap->he_cap_elem, +- &eht_cap->eht_cap_elem); ++ &eht_cap->eht_cap_elem, ++ is_ap); + return 2 + 1 + + sizeof(eht_cap->eht_cap_elem) + n + + ieee80211_eht_ppe_size(eht_cap->eht_ppe_thres[0], +@@ -5434,7 +5443,8 @@ u8 ieee80211_ie_len_eht_cap(struct ieee80211_sub_if_data *sdata, u8 iftype) + u8 *ieee80211_ie_build_eht_cap(u8 *pos, + const struct ieee80211_sta_he_cap *he_cap, + const struct ieee80211_sta_eht_cap *eht_cap, +- u8 *end) ++ u8 *end, ++ bool for_ap) + { + u8 mcs_nss_len, ppet_len; + u8 ie_len; +@@ -5445,7 +5455,8 @@ u8 *ieee80211_ie_build_eht_cap(u8 *pos, + return orig_pos; + + mcs_nss_len = ieee80211_eht_mcs_nss_size(&he_cap->he_cap_elem, +- &eht_cap->eht_cap_elem); ++ &eht_cap->eht_cap_elem, ++ for_ap); + ppet_len = ieee80211_eht_ppe_size(eht_cap->eht_ppe_thres[0], + eht_cap->eht_cap_elem.phy_cap_info); + +diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c +index d5f0d5b..6f8c502 100644 +--- a/net/mac80211/vht.c ++++ b/net/mac80211/vht.c +@@ -539,7 +539,8 @@ void ieee80211_sta_set_rx_nss(struct link_sta_info *link_sta) + if (link_sta->pub->eht_cap.has_eht) { + int i; + int eht_mcs_set_size = ieee80211_eht_mcs_nss_size(&link_sta->pub->he_cap, +- &link_sta->pub->eht_cap); ++ &link_sta->pub->eht_cap, ++ false); + const u8 *rx_nss_mcs = (void *)&link_sta->pub->eht_cap.eht_mcs_nss_supp; + + /* get the max nss for EHT over all possible bandwidths and mcs */ +diff --git a/net/wireless/core.c b/net/wireless/core.c +index 510ee69..5aa97ae 100644 +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -1061,6 +1061,9 @@ int wiphy_register(struct wiphy *wiphy) + + for (i = 0; i < sband->n_iftype_data; i++) { + const struct ieee80211_sband_iftype_data *iftd; ++ bool has_ap, has_non_ap; ++ u32 ap_bits = BIT(NL80211_IFTYPE_AP) | ++ BIT(NL80211_IFTYPE_P2P_GO); + + iftd = &sband->iftype_data[i]; + +@@ -1080,6 +1083,19 @@ int wiphy_register(struct wiphy *wiphy) + else + have_he = have_he && + iftd->he_cap.has_he; ++ ++ has_ap = iftd->types_mask & ap_bits; ++ has_non_ap = iftd->types_mask & ~ap_bits; ++ ++ /* ++ * For EHT 20 MHz STA, the capabilities format differs ++ * but to simplify, don't check 20 MHz but rather check ++ * only if AP and non-AP were mentioned at the same time, ++ * reject if so. ++ */ ++ if (WARN_ON(iftd->eht_cap.has_eht && ++ has_ap && has_non_ap)) ++ return -EINVAL; + } + + if (WARN_ON(!have_he && band == NL80211_BAND_6GHZ)) +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index b666653..9d155f0 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -1966,10 +1966,15 @@ nl80211_send_iftype_data(struct sk_buff *msg, + if (eht_cap->has_eht && he_cap->has_he) { + u8 mcs_nss_size, ppe_thresh_size; + u16 ppe_thres_hdr; ++ bool is_ap; ++ ++ is_ap = iftdata->types_mask & BIT(NL80211_IFTYPE_AP) || ++ iftdata->types_mask & BIT(NL80211_IFTYPE_P2P_GO); + + mcs_nss_size = + ieee80211_eht_mcs_nss_size(&he_cap->he_cap_elem, +- &eht_cap->eht_cap_elem); ++ &eht_cap->eht_cap_elem, ++ is_ap); + + ppe_thres_hdr = get_unaligned_le16(&eht_cap->eht_ppe_thres[0]); + ppe_thresh_size = +@@ -5472,7 +5477,9 @@ static int eht_build_mcs_mask(struct genl_info *info, + unsigned int link_id = nl80211_link_id(info->attrs); + + mcs_nss_len = ieee80211_eht_mcs_nss_size(&he_cap->he_cap_elem, +- &eht_cap->eht_cap_elem); ++ &eht_cap->eht_cap_elem, ++ wdev->iftype == ++ NL80211_IFTYPE_STATION); + + if (eht_cap->eht_cap_elem.phy_cap_info[6] & + IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP) +@@ -6333,7 +6340,7 @@ static int nl80211_calculate_ap_params(struct cfg80211_ap_settings *params) + params->eht_cap = (void *)(cap->data + 1); + if (!ieee80211_eht_capa_size_ok((const u8 *)params->he_cap, + (const u8 *)params->eht_cap, +- cap->datalen - 1)) ++ cap->datalen - 1, true)) + return -EINVAL; + } + cap = cfg80211_find_ext_elem(WLAN_EID_EXT_EHT_OPERATION, ies, ies_len); +@@ -7641,7 +7648,8 @@ static int nl80211_set_station_tdls(struct genl_info *info, + + if (!ieee80211_eht_capa_size_ok((const u8 *)params->link_sta_params.he_capa, + (const u8 *)params->link_sta_params.eht_capa, +- params->link_sta_params.eht_capa_len)) ++ params->link_sta_params.eht_capa_len, ++ false)) + return -EINVAL; + } + +@@ -7975,7 +7983,8 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) + + if (!ieee80211_eht_capa_size_ok((const u8 *)params.link_sta_params.he_capa, + (const u8 *)params.link_sta_params.eht_capa, +- params.link_sta_params.eht_capa_len)) ++ params.link_sta_params.eht_capa_len, ++ false)) + return -EINVAL; + } + } +@@ -16879,7 +16888,8 @@ nl80211_add_mod_link_station(struct sk_buff *skb, struct genl_info *info, + + if (!ieee80211_eht_capa_size_ok((const u8 *)params.he_capa, + (const u8 *)params.eht_capa, +- params.eht_capa_len)) ++ params.eht_capa_len, ++ false)) + return -EINVAL; + } + +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/821-04-wifi-mac80211-Parse-station-profile-from-association.patch b/feeds/ipq95xx/mac80211/patches/qca/821-04-wifi-mac80211-Parse-station-profile-from-association.patch new file mode 100644 index 000000000..01ef89776 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/821-04-wifi-mac80211-Parse-station-profile-from-association.patch @@ -0,0 +1,275 @@ +From 1d2e4c833c74b44930f860422f89d0ecb3be3b29 Mon Sep 17 00:00:00 2001 +From: Ramasamy Kaliappan +Date: Mon, 3 Jul 2023 15:42:07 +0530 +Subject: [PATCH 02/16] wifi: mac80211: Parse station profile from association + response + +When processing an association response frame for a Multi-Link +connection, extract the per station profile for each additional +link, and use it for parsing the link elements. + +As the Multi-Link element might be fragmented, add support for +reassembling a fragmented element. To simplify memory management +logic, extend 'struct ieee802_11_elems' to hold a scratch buffer, +which is used for the defragmentation. Once an element is +reconstructed in the scratch area, point the corresponding element +pointer to it. Currently only defragmentation of Multi-Link element +and the contained per-STA profile subelement is supported. + +Signed-off-by: Ilan Peer +Signed-off-by: Johannes Berg + +Signed-off-by: Ramasamy Kaliappan +--- + include/linux/ieee80211.h | 1 + + net/mac80211/ieee80211_i.h | 1 + + net/mac80211/mlme.c | 17 ++++- + net/mac80211/util.c | 147 ++++++++++++++++++++++++++++++++++++- + 4 files changed, 161 insertions(+), 5 deletions(-) + +diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h +index 7cc384d..a40b946 100644 +--- a/include/linux/ieee80211.h ++++ b/include/linux/ieee80211.h +@@ -4723,6 +4723,7 @@ static inline bool ieee80211_mle_size_ok(const u8 *data, u8 len) + + enum ieee80211_mle_subelems { + IEEE80211_MLE_SUBELEM_PER_STA_PROFILE = 0, ++ IEEE80211_MLE_SUBELEM_FRAGMENT = 254, + }; + + #define IEEE80211_MLE_STA_CONTROL_LINK_ID 0x000f +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index 45b53ba..ec4ae55 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -2295,6 +2295,7 @@ struct ieee80211_elems_parse_params { + struct cfg80211_bss *bss; + int link_id; + bool from_ap; ++ size_t scratch_len; + }; + + struct ieee802_11_elems * +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 6fa6255..dd48b45 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -3935,11 +3935,12 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link, + struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data; + struct ieee80211_bss_conf *bss_conf = link->conf; + struct ieee80211_local *local = sdata->local; ++ unsigned int link_id = link->link_id; + struct ieee80211_elems_parse_params parse_params = { + .start = elem_start, + .len = elem_len, + .bss = cbss, +- .link_id = link == &sdata->deflink ? -1 : link->link_id, ++ .link_id = link_id == assoc_data->assoc_link_id ? -1 : link_id, + .from_ap = true, + }; + bool is_6ghz = cbss->channel->band == NL80211_BAND_6GHZ; +@@ -3954,8 +3955,18 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link, + if (!elems) + return false; + +- /* FIXME: use from STA profile element after parsing that */ +- capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); ++ if (link_id == assoc_data->assoc_link_id) { ++ capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); ++ } else if (!elems->prof) { ++ ret = false; ++ goto out; ++ } else { ++ const u8 *ptr = elems->prof->variable + ++ elems->prof->sta_info_len - 1; ++ ++ /* FIXME: need to also handle the status code */ ++ capab_info = get_unaligned_le16(ptr); ++ } + + if (!is_s1g && !elems->supp_rates) { + sdata_info(sdata, "no SuppRates element in AssocResp\n"); +diff --git a/net/mac80211/util.c b/net/mac80211/util.c +index d84b116..e512a93 100644 +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -1031,8 +1031,10 @@ ieee80211_parse_extension_element(u32 *crc, + elems->eht_operation = data; + break; + case WLAN_EID_EXT_EHT_MULTI_LINK: +- if (ieee80211_mle_size_ok(data, len)) ++ if (ieee80211_mle_size_ok(data, len)) { + elems->multi_link = (void *)data; ++ elems->multi_link_len = len; ++ } + break; + } + } +@@ -1504,6 +1506,145 @@ static size_t ieee802_11_find_bssid_profile(const u8 *start, size_t len, + return found ? profile_len : 0; + } + ++static void ieee80211_defragment_element(struct ieee802_11_elems *elems, ++ void **elem_ptr, size_t *len, ++ size_t total_len, u8 frag_id) ++{ ++ u8 *data = *elem_ptr, *pos, *start; ++ const struct element *elem; ++ ++ /* ++ * Since 'data' points to the data of the element, not the element ++ * itself, allow 254 in case it was an extended element where the ++ * extended ID isn't part of the data we see here and thus not part of ++ * 'len' either. ++ */ ++ if (!data || (*len != 254 && *len != 255)) ++ return; ++ ++ start = elems->scratch_pos; ++ ++ if (WARN_ON(*len > (elems->scratch + elems->scratch_len - ++ elems->scratch_pos))) ++ return; ++ ++ memcpy(elems->scratch_pos, data, *len); ++ elems->scratch_pos += *len; ++ ++ pos = data + *len; ++ total_len -= *len; ++ for_each_element(elem, pos, total_len) { ++ if (elem->id != frag_id) ++ break; ++ ++ if (WARN_ON(elem->datalen > ++ (elems->scratch + elems->scratch_len - ++ elems->scratch_pos))) ++ return; ++ ++ memcpy(elems->scratch_pos, elem->data, elem->datalen); ++ elems->scratch_pos += elem->datalen; ++ ++ *len += elem->datalen; ++ } ++ ++ *elem_ptr = start; ++} ++ ++static void ieee80211_mle_get_sta_prof(struct ieee802_11_elems *elems, ++ u8 link_id) ++{ ++ const struct ieee80211_multi_link_elem *ml = elems->multi_link; ++ size_t ml_len = elems->multi_link_len; ++ const struct element *sub; ++ ++ if (!ml || !ml_len) ++ return; ++ ++ if (le16_get_bits(ml->control, IEEE80211_ML_CONTROL_TYPE) != ++ IEEE80211_ML_CONTROL_TYPE_BASIC) ++ return; ++ ++ for_each_mle_subelement(sub, (u8 *)ml, ml_len) { ++ struct ieee80211_mle_per_sta_profile *prof = (void *)sub->data; ++ u16 control; ++ ++ if (sub->id != IEEE80211_MLE_SUBELEM_PER_STA_PROFILE) ++ continue; ++ ++ if (!ieee80211_mle_sta_prof_size_ok(sub->data, sub->datalen)) ++ return; ++ ++ control = le16_to_cpu(prof->control); ++ ++ if (link_id != u16_get_bits(control, ++ IEEE80211_MLE_STA_CONTROL_LINK_ID)) ++ continue; ++ ++ if (!(control & IEEE80211_MLE_STA_CONTROL_COMPLETE_PROFILE)) ++ return; ++ ++ elems->prof = prof; ++ elems->sta_prof_len = sub->datalen; ++ ++ /* the sub element can be fragmented */ ++ ieee80211_defragment_element(elems, (void **)&elems->prof, ++ &elems->sta_prof_len, ++ ml_len - (sub->data - (u8 *)ml), ++ IEEE80211_MLE_SUBELEM_FRAGMENT); ++ return; ++ } ++} ++ ++static void ieee80211_mle_parse_link(struct ieee802_11_elems *elems, ++ struct ieee80211_elems_parse_params *params) ++{ ++ struct ieee80211_mle_per_sta_profile *prof; ++ struct ieee80211_elems_parse_params sub = { ++ .action = params->action, ++ .from_ap = params->from_ap, ++ .link_id = -1, ++ }; ++ const struct element *non_inherit = NULL; ++ const u8 *end; ++ ++ if (params->link_id == -1) ++ return; ++ ++ ieee80211_defragment_element(elems, (void **)&elems->multi_link, ++ &elems->multi_link_len, ++ elems->total_len - ((u8 *)elems->multi_link - ++ elems->ie_start), ++ WLAN_EID_FRAGMENT); ++ ++ ieee80211_mle_get_sta_prof(elems, params->link_id); ++ prof = elems->prof; ++ ++ if (!prof) ++ return; ++ ++ /* check if we have the 4 bytes for the fixed part in assoc response */ ++ if (elems->sta_prof_len < sizeof(*prof) + prof->sta_info_len - 1 + 4) { ++ elems->prof = NULL; ++ elems->sta_prof_len = 0; ++ return; ++ } ++ ++ /* ++ * Skip the capability information and the status code that are expected ++ * as part of the station profile in association response frames. Note ++ * the -1 is because the 'sta_info_len' is accounted to as part of the ++ * per-STA profile, but not part of the 'u8 variable[]' portion. ++ */ ++ sub.start = prof->variable + prof->sta_info_len - 1 + 4; ++ end = (const u8 *)prof + elems->sta_prof_len; ++ sub.len = end - sub.start; ++ ++ non_inherit = cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE, ++ sub.start, sub.len); ++ _ieee802_11_parse_elems_full(&sub, elems, non_inherit); ++} ++ + struct ieee802_11_elems * + ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params) + { +@@ -1511,7 +1652,7 @@ ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params) + const struct element *non_inherit = NULL; + u8 *nontransmitted_profile; + int nontransmitted_profile_len = 0; +- size_t scratch_len = params->len; ++ size_t scratch_len = params->scratch_len ?: 2 * params->len; + + elems = kzalloc(sizeof(*elems) + scratch_len, GFP_ATOMIC); + if (!elems) +@@ -1547,6 +1688,8 @@ ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params) + _ieee802_11_parse_elems_full(&sub, elems, NULL); + } + ++ ieee80211_mle_parse_link(elems, params); ++ + if (elems->tim && !elems->parse_error) { + const struct ieee80211_tim_ie *tim_ie = elems->tim; + +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/821-05-wifi-mac80211-Process-association-status-for-affilia.patch b/feeds/ipq95xx/mac80211/patches/qca/821-05-wifi-mac80211-Process-association-status-for-affilia.patch new file mode 100644 index 000000000..3560ad246 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/821-05-wifi-mac80211-Process-association-status-for-affilia.patch @@ -0,0 +1,145 @@ +From 5bdfa3f6fbff4663be9a80a1739a73058ada5ed1 Mon Sep 17 00:00:00 2001 +From: Ramasamy Kaliappan +Date: Mon, 3 Jul 2023 15:50:47 +0530 +Subject: [PATCH 03/16] wifi: mac80211: Process association status for + affiliated links + +In case the AP returned a non success status for one of the links, +do not activate the link. + +Signed-off-by: Ilan Peer +Signed-off-by: Johannes Berg +Signed-off-by: Ramasamy Kaliappan +--- + net/mac80211/ieee80211_i.h | 2 ++ + net/mac80211/mlme.c | 40 +++++++++++++++++++++++++++++++++----- + 2 files changed, 37 insertions(+), 5 deletions(-) + +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index ec4ae55..031b667 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -430,6 +430,8 @@ struct ieee80211_mgd_assoc_data { + u8 *elems; /* pointing to inside ie[] below */ + + ieee80211_conn_flags_t conn_flags; ++ ++ u16 status; + } link[IEEE80211_MLD_MAX_NUM_LINKS]; + + u8 ap_addr[ETH_ALEN] __aligned(2); +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index dd48b45..a229f3d 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -2765,7 +2765,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, + struct cfg80211_bss *cbss = assoc_data->link[link_id].bss; + struct ieee80211_link_data *link; + +- if (!cbss) ++ if (!cbss || ++ assoc_data->link[link_id].status != WLAN_STATUS_SUCCESS) + continue; + + link = sdata_dereference(sdata->link[link_id], sdata); +@@ -2793,7 +2794,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, + struct ieee80211_link_data *link; + struct cfg80211_bss *cbss = assoc_data->link[link_id].bss; + +- if (!cbss) ++ if (!cbss || ++ assoc_data->link[link_id].status != WLAN_STATUS_SUCCESS) + continue; + + link = sdata_dereference(sdata->link[link_id], sdata); +@@ -3957,6 +3959,12 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link, + + if (link_id == assoc_data->assoc_link_id) { + capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); ++ ++ /* ++ * we should not get to this flow unless the association was ++ * successful, so set the status directly to success ++ */ ++ assoc_data->link[link_id].status = WLAN_STATUS_SUCCESS; + } else if (!elems->prof) { + ret = false; + goto out; +@@ -3964,8 +3972,19 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link, + const u8 *ptr = elems->prof->variable + + elems->prof->sta_info_len - 1; + +- /* FIXME: need to also handle the status code */ ++ /* ++ * During parsing, we validated that these fields exist, ++ * otherwise elems->prof would have been set to NULL. ++ */ + capab_info = get_unaligned_le16(ptr); ++ assoc_data->link[link_id].status = get_unaligned_le16(ptr + 2); ++ ++ if (assoc_data->link[link_id].status != WLAN_STATUS_SUCCESS) { ++ link_info(link, "association response status code=%u\n", ++ assoc_data->link[link_id].status); ++ ret = true; ++ goto out; ++ } + } + + if (!is_s1g && !elems->supp_rates) { +@@ -4837,6 +4856,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, + unsigned int link_id; + struct sta_info *sta; + u64 changed[IEEE80211_MLD_MAX_NUM_LINKS] = {}; ++ u16 valid_links = 0; + int err; + + mutex_lock(&sdata->local->sta_mtx); +@@ -4849,8 +4869,6 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, + goto out_err; + + if (sdata->vif.valid_links) { +- u16 valid_links = 0; +- + for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) { + if (!assoc_data->link[link_id].bss) + continue; +@@ -4909,6 +4927,12 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, + &changed[link_id])) + goto out_err; + ++ if (assoc_data->link[link_id].status != WLAN_STATUS_SUCCESS) { ++ valid_links &= ~BIT(link_id); ++ ieee80211_sta_remove_link(sta, link_id); ++ continue; ++ } ++ + if (link_id != assoc_data->assoc_link_id) { + err = ieee80211_sta_activate_link(sta, link_id); + if (err) +@@ -4916,6 +4940,9 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, + } + } + ++ /* links might have changed due to rejected ones, set them again */ ++ ieee80211_vif_set_links(sdata, valid_links); ++ + rate_control_rate_init(sta); + for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) { + if (!(sta->sta.valid_links & BIT(link_id)) || +@@ -5157,10 +5184,13 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, + link = sdata_dereference(sdata->link[link_id], sdata); + if (!link) + continue; ++ + if (!assoc_data->link[link_id].bss) + continue; ++ + resp.links[link_id].bss = assoc_data->link[link_id].bss; + resp.links[link_id].addr = link->conf->addr; ++ resp.links[link_id].status = assoc_data->link[link_id].status; + + /* get uapsd queues configuration - same for all links */ + resp.uapsd_queues = 0; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/821-06-wifi-mac80211-wme-use-ap_addr-instead-of-deflink-BSS.patch b/feeds/ipq95xx/mac80211/patches/qca/821-06-wifi-mac80211-wme-use-ap_addr-instead-of-deflink-BSS.patch new file mode 100644 index 000000000..858bbc36e --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/821-06-wifi-mac80211-wme-use-ap_addr-instead-of-deflink-BSS.patch @@ -0,0 +1,31 @@ +From 2f74b344d64eb8d01d1ba585f0896a5586ae8754 Mon Sep 17 00:00:00 2001 +From: Ramasamy Kaliappan +Date: Mon, 3 Jul 2023 15:54:14 +0530 +Subject: [PATCH 04/16] wifi: mac80211: wme: use ap_addr instead of deflink + BSSID + +We use this to look up the destination station, so it +needs to be the MLD address of the AP for an MLO; use +ap_addr instead of the BSSID. + +Signed-off-by: Johannes Berg +--- + net/mac80211/wme.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c +index b10ca96..b154d05 100644 +--- a/net/mac80211/wme.c ++++ b/net/mac80211/wme.c +@@ -214,7 +214,7 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, + if (sta) + break; + +- ra = sdata->deflink.u.mgd.bssid; ++ ra = sdata->vif.cfg.ap_addr; + break; + case NL80211_IFTYPE_ADHOC: + ra = skb->data; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/821-07-wifi-mac80211-advertise-TWT-requester-only-with-HW-s.patch b/feeds/ipq95xx/mac80211/patches/qca/821-07-wifi-mac80211-advertise-TWT-requester-only-with-HW-s.patch new file mode 100644 index 000000000..9342fab16 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/821-07-wifi-mac80211-advertise-TWT-requester-only-with-HW-s.patch @@ -0,0 +1,95 @@ +From 22fa039278228614ac6b2eb6956ccdfebba0b2b7 Mon Sep 17 00:00:00 2001 +From: Ramasamy Kaliappan +Date: Mon, 3 Jul 2023 16:03:04 +0530 +Subject: [PATCH 06/16] wifi: mac80211: advertise TWT requester only with HW + support + +Currently, we rely only on the AP capability. If the AP supports +TWT responder we will advertise TWT requester even if the driver +or HW doesn't support it. This this by checking the HW capability. + +Signed-off-by: Haim Dreyfuss +Signed-off-by: Johannes Berg +--- + net/mac80211/mlme.c | 30 ++++++++++++++++++++++++------ + 1 file changed, 24 insertions(+), 6 deletions(-) + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index a229f3d..4e2bca8 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -3882,9 +3882,15 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband, + } + } + +-static bool ieee80211_twt_req_supported(const struct link_sta_info *link_sta, ++static bool ieee80211_twt_req_supported(struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_supported_band *sband, ++ const struct link_sta_info *link_sta, + const struct ieee802_11_elems *elems) + { ++ const struct ieee80211_sta_he_cap *own_he_cap = ++ ieee80211_get_he_iftype_cap(sband, ++ ieee80211_vif_type_p2p(&sdata->vif)); ++ + if (elems->ext_capab_len < 10) + return false; + +@@ -3892,14 +3898,19 @@ static bool ieee80211_twt_req_supported(const struct link_sta_info *link_sta, + return false; + + return link_sta->pub->he_cap.he_cap_elem.mac_cap_info[0] & +- IEEE80211_HE_MAC_CAP0_TWT_RES; ++ IEEE80211_HE_MAC_CAP0_TWT_RES && ++ own_he_cap && ++ (own_he_cap->he_cap_elem.mac_cap_info[0] & ++ IEEE80211_HE_MAC_CAP0_TWT_REQ); + } + +-static int ieee80211_recalc_twt_req(struct ieee80211_link_data *link, ++static int ieee80211_recalc_twt_req(struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_supported_band *sband, ++ struct ieee80211_link_data *link, + struct link_sta_info *link_sta, + struct ieee802_11_elems *elems) + { +- bool twt = ieee80211_twt_req_supported(link_sta, elems); ++ bool twt = ieee80211_twt_req_supported(sdata, sband, link_sta, elems); + + if (link->conf->twt_requester != twt) { + link->conf->twt_requester = twt; +@@ -4142,7 +4153,8 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link, + else + bss_conf->twt_protected = false; + +- *changed |= ieee80211_recalc_twt_req(link, link_sta, elems); ++ *changed |= ieee80211_recalc_twt_req(sdata, sband, link, ++ link_sta, elems); + + if (elems->eht_cap && + !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_EHT)) { +@@ -5432,6 +5444,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link, + struct ieee802_11_elems *elems; + struct ieee80211_local *local = sdata->local; + struct ieee80211_chanctx_conf *chanctx_conf; ++ struct ieee80211_supported_band *sband; + struct ieee80211_channel *chan; + struct link_sta_info *link_sta; + struct sta_info *sta; +@@ -5690,7 +5703,12 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link, + if (WARN_ON(!link_sta)) + goto free; + +- changed |= ieee80211_recalc_twt_req(link, link_sta, elems); ++ if (WARN_ON(!link->conf->chandef.chan)) ++ goto free; ++ ++ sband = local->hw.wiphy->bands[link->conf->chandef.chan->band]; ++ ++ changed |= ieee80211_recalc_twt_req(sdata, sband, link, link_sta, elems); + + if (ieee80211_config_bw(link, elems->ht_cap_elem, + elems->vht_cap_elem, elems->ht_operation, +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/821-08-wifi-mac80211-transmit-AddBA-with-MLD-address.patch b/feeds/ipq95xx/mac80211/patches/qca/821-08-wifi-mac80211-transmit-AddBA-with-MLD-address.patch new file mode 100644 index 000000000..673b943e4 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/821-08-wifi-mac80211-transmit-AddBA-with-MLD-address.patch @@ -0,0 +1,32 @@ +From dc07c253df6a074cd0850cb6f7f369cdc781e7ca Mon Sep 17 00:00:00 2001 +From: Ramasamy Kaliappan +Date: Mon, 3 Jul 2023 15:55:47 +0530 +Subject: [PATCH 05/16] wifi: mac80211: transmit AddBA with MLD address + +This management frame is intended for the MLD so we +treat it in mac80211 as MLD addressed as well, and +should therefore use the MLD address of the AP for +the BSSID field in the frame, address translation +applies. + +Signed-off-by: Johannes Berg +--- + net/mac80211/agg-tx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c +index 07c892a..9c40f8d 100644 +--- a/net/mac80211/agg-tx.c ++++ b/net/mac80211/agg-tx.c +@@ -82,7 +82,7 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, + sdata->vif.type == NL80211_IFTYPE_MESH_POINT) + memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); + else if (sdata->vif.type == NL80211_IFTYPE_STATION) +- memcpy(mgmt->bssid, sdata->deflink.u.mgd.bssid, ETH_ALEN); ++ memcpy(mgmt->bssid, sdata->vif.cfg.ap_addr, ETH_ALEN); + else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) + memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN); + +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/821-09-wifi-mac80211-set-internal-scan-request-BSSID.patch b/feeds/ipq95xx/mac80211/patches/qca/821-09-wifi-mac80211-set-internal-scan-request-BSSID.patch new file mode 100644 index 000000000..cc6b994ab --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/821-09-wifi-mac80211-set-internal-scan-request-BSSID.patch @@ -0,0 +1,31 @@ +From 3904f8898d8015bc02d81ebff85c20228591b9b9 Mon Sep 17 00:00:00 2001 +From: Ramasamy Kaliappan +Date: Mon, 3 Jul 2023 16:06:29 +0530 +Subject: [PATCH 07/16] wifi: mac80211: set internal scan request BSSID + +If any driver relies entirely on the scan request BSSID, +then that would be wrong for internal scans. Initialize +it to the broadcast address since we don't otherwise use +the field. + +Signed-off-by: Johannes Berg +--- + net/mac80211/main.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/mac80211/main.c b/net/mac80211/main.c +index 1ff4d3a..f92e70b 100644 +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -1258,6 +1258,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) + if (!local->int_scan_req) + return -ENOMEM; + ++ eth_broadcast_addr(local->int_scan_req->bssid); ++ + for (band = 0; band < NUM_NL80211_BANDS; band++) { + if (!local->hw.wiphy->bands[band]) + continue; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/821-10-wifi-mac80211-fix-AddBA-response-addressing.patch b/feeds/ipq95xx/mac80211/patches/qca/821-10-wifi-mac80211-fix-AddBA-response-addressing.patch new file mode 100644 index 000000000..4fc6a31ef --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/821-10-wifi-mac80211-fix-AddBA-response-addressing.patch @@ -0,0 +1,31 @@ +From c13a3842c31dc76a6900aa4ad86e0159c876d811 Mon Sep 17 00:00:00 2001 +From: Ramasamy Kaliappan +Date: Mon, 3 Jul 2023 16:09:29 +0530 +Subject: [PATCH 08/16] wifi: mac80211: fix AddBA response addressing + +Since this frame is addressed from/to an MLD, it should be +built with the correct AP MLD address (in station mode) to +be encrypted properly. + +Signed-off-by: Johannes Berg +Signed-off-by: Ramasamy Kaliappan +--- + net/mac80211/agg-rx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c +index b4ed3ce..31ab96e 100644 +--- a/net/mac80211/agg-rx.c ++++ b/net/mac80211/agg-rx.c +@@ -239,7 +239,7 @@ static void ieee80211_send_addba_resp(struct sta_info *sta, u8 *da, u16 tid, + sdata->vif.type == NL80211_IFTYPE_MESH_POINT) { + memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); + } else if (sdata->vif.type == NL80211_IFTYPE_STATION) { +- memcpy(mgmt->bssid, sdata->deflink.u.mgd.bssid, ETH_ALEN); ++ memcpy(mgmt->bssid, sdata->vif.cfg.ap_addr, ETH_ALEN); + } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { + memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN); + } +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/821-11-wifi-mac80211-add-RCU-_check-link-access-variants.patch b/feeds/ipq95xx/mac80211/patches/qca/821-11-wifi-mac80211-add-RCU-_check-link-access-variants.patch new file mode 100644 index 000000000..a87c32c60 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/821-11-wifi-mac80211-add-RCU-_check-link-access-variants.patch @@ -0,0 +1,36 @@ +From 3c54fc6a49cdeb2d128afd406c576398eeaefefc Mon Sep 17 00:00:00 2001 +From: Ramasamy Kaliappan +Date: Mon, 3 Jul 2023 16:16:40 +0530 +Subject: [PATCH 09/16] wifi: mac80211: add RCU _check() link access variants + +We might sometimes need to use RCU and locking in the same code +path, so add the two variants link_conf_dereference_check() and +link_sta_dereference_check(). + +Signed-off-by: Johannes Berg +--- + include/net/mac80211.h | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/include/net/mac80211.h b/include/net/mac80211.h +index 7055759..dae0fa0 100644 +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -2422,6 +2422,14 @@ static inline bool lockdep_sta_mutex_held(struct ieee80211_sta *pubsta) + rcu_dereference_protected((sta)->link[link_id], \ + lockdep_sta_mutex_held(sta)) + ++#define link_conf_dereference_check(vif, link_id) \ ++ rcu_dereference_check((vif)->link_conf[link_id], \ ++ lockdep_vif_mutex_held(vif)) ++ ++#define link_sta_dereference_check(sta, link_id) \ ++ rcu_dereference_check((sta)->link[link_id], \ ++ lockdep_sta_mutex_held(sta)) ++ + #define for_each_sta_active_link(vif, sta, link_sta, link_id) \ + for (link_id = 0; link_id < ARRAY_SIZE((sta)->link); link_id++) \ + if ((!(vif)->active_links || \ +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/821-12-wifi-fix-multi-link-element-subelement-iteration.patch b/feeds/ipq95xx/mac80211/patches/qca/821-12-wifi-fix-multi-link-element-subelement-iteration.patch new file mode 100644 index 000000000..bb4cb0ae8 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/821-12-wifi-fix-multi-link-element-subelement-iteration.patch @@ -0,0 +1,33 @@ +From 6c007008a999c873b9e5a53154bd3db46bd41ea4 Mon Sep 17 00:00:00 2001 +From: Ramasamy Kaliappan +Date: Mon, 3 Jul 2023 16:17:52 +0530 +Subject: [PATCH 10/16] wifi: fix multi-link element subelement iteration + +The subelements obviously start after the common data, including +the common multi-link element structure definition itself. This +bug was possibly just hidden by the higher bits of the control +being set to 0, so the iteration just found one bogus element +and most of the code could continue anyway. + +Fixes: 0f48b8b88aa9 ("wifi: ieee80211: add definitions for multi-link element") +Signed-off-by: Johannes Berg +--- + include/linux/ieee80211.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h +index a40b946..e9e932b 100644 +--- a/include/linux/ieee80211.h ++++ b/include/linux/ieee80211.h +@@ -4650,7 +4650,7 @@ static inline u8 ieee80211_mle_common_size(const u8 *data) + return 0; + } + +- return common + mle->variable[0]; ++ return sizeof(*mle) + common + mle->variable[0]; + } + + /** +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/821-13-wifi-mac80211-mlme-fix-null-ptr-deref-on-failed-asso.patch b/feeds/ipq95xx/mac80211/patches/qca/821-13-wifi-mac80211-mlme-fix-null-ptr-deref-on-failed-asso.patch new file mode 100644 index 000000000..792fd6371 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/821-13-wifi-mac80211-mlme-fix-null-ptr-deref-on-failed-asso.patch @@ -0,0 +1,59 @@ +From 7eb2483bb4133db4c64d6bfbee942362f335da08 Mon Sep 17 00:00:00 2001 +From: Ramasamy Kaliappan +Date: Mon, 3 Jul 2023 16:21:55 +0530 +Subject: [PATCH 11/16] wifi: mac80211: mlme: fix null-ptr deref on failed + assoc + +If association to an AP without a link 0 fails, then we crash in +tracing because it assumes that either ap_mld_addr or link 0 BSS +is valid, since we clear sdata->vif.valid_links and then don't +add the ap_mld_addr to the struct. + +Since we clear also sdata->vif.cfg.ap_addr, keep a local copy of +it and assign it earlier, before clearing valid_links, to fix +this. + +Fixes: 81151ce462e5 ("wifi: mac80211: support MLO authentication/association with one link") +Signed-off-by: Johannes Berg + +Signed-off-by: Ramasamy Kaliappan +--- + net/mac80211/mlme.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 4e2bca8..e7b293b 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -5042,6 +5042,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, + struct cfg80211_rx_assoc_resp resp = { + .uapsd_queues = -1, + }; ++ u8 ap_mld_addr[ETH_ALEN] __aligned(2); + unsigned int link_id; + + sdata_assert_lock(sdata); +@@ -5211,6 +5212,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, + resp.uapsd_queues |= ieee80211_ac_to_qos_mask[ac]; + } + ++ if (sdata->vif.valid_links) { ++ ether_addr_copy(ap_mld_addr, sdata->vif.cfg.ap_addr); ++ resp.ap_mld_addr = ap_mld_addr; ++ } ++ + ieee80211_destroy_assoc_data(sdata, + status_code == WLAN_STATUS_SUCCESS ? + ASSOC_SUCCESS : +@@ -5220,8 +5226,6 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, + resp.len = len; + resp.req_ies = ifmgd->assoc_req_ies; + resp.req_ies_len = ifmgd->assoc_req_ies_len; +- if (sdata->vif.valid_links) +- resp.ap_mld_addr = assoc_data->ap_addr; + cfg80211_rx_assoc_resp(sdata->dev, &resp); + notify_driver: + drv_mgd_complete_tx(sdata->local, sdata, &info); +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/821-14-wifi-mac80211-check-link-ID-in-auth-assoc-continuati.patch b/feeds/ipq95xx/mac80211/patches/qca/821-14-wifi-mac80211-check-link-ID-in-auth-assoc-continuati.patch new file mode 100644 index 000000000..78ef03020 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/821-14-wifi-mac80211-check-link-ID-in-auth-assoc-continuati.patch @@ -0,0 +1,63 @@ +From 7c27163a66adc4076de6c0f1077c01d97e5fd013 Mon Sep 17 00:00:00 2001 +From: Ramasamy Kaliappan +Date: Mon, 3 Jul 2023 16:23:41 +0530 +Subject: [PATCH 12/16] wifi: mac80211: check link ID in auth/assoc + continuation + +Ensure that the link ID matches in auth/assoc continuation, +otherwise we need to reset all the data. + +Fixes: 81151ce462e5 ("wifi: mac80211: support MLO authentication/association with one link") +Signed-off-by: Johannes Berg +--- + net/mac80211/ieee80211_i.h | 1 + + net/mac80211/mlme.c | 7 +++++-- + 2 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index 031b667..c983529 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -408,6 +408,7 @@ struct ieee80211_mgd_auth_data { + bool done, waiting; + bool peer_confirmed; + bool timeout_started; ++ int link_id; + + u8 ap_addr[ETH_ALEN] __aligned(2); + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index e7b293b..dff90fc 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -6697,6 +6697,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, + req->ap_mld_addr ?: req->bss->bssid, + ETH_ALEN); + auth_data->bss = req->bss; ++ auth_data->link_id = req->link_id; + + if (req->auth_data_len >= 4) { + if (req->auth_type == NL80211_AUTHTYPE_SAE) { +@@ -6715,7 +6716,8 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, + * removal and re-addition of the STA entry in + * ieee80211_prep_connection(). + */ +- cont_auth = ifmgd->auth_data && req->bss == ifmgd->auth_data->bss; ++ cont_auth = ifmgd->auth_data && req->bss == ifmgd->auth_data->bss && ++ ifmgd->auth_data->link_id == req->link_id; + + if (req->ie && req->ie_len) { + memcpy(&auth_data->data[auth_data->data_len], +@@ -7053,7 +7055,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, + + /* keep sta info, bssid if matching */ + match = ether_addr_equal(ifmgd->auth_data->ap_addr, +- assoc_data->ap_addr); ++ assoc_data->ap_addr) && ++ ifmgd->auth_data->link_id == req->link_id; + ieee80211_destroy_auth_data(sdata, match); + } + +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/821-15-wifi-mac80211-mlme-mark-assoc-link-in-output.patch b/feeds/ipq95xx/mac80211/patches/qca/821-15-wifi-mac80211-mlme-mark-assoc-link-in-output.patch new file mode 100644 index 000000000..19e3dcd84 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/821-15-wifi-mac80211-mlme-mark-assoc-link-in-output.patch @@ -0,0 +1,34 @@ +From e715809a3663158b33ce8f19496c62c4d83e03c7 Mon Sep 17 00:00:00 2001 +From: Ramasamy Kaliappan +Date: Mon, 3 Jul 2023 16:25:07 +0530 +Subject: [PATCH 13/16] wifi: mac80211: mlme: mark assoc link in output + +It's useful to know which link was used for the association, +mark it when printing the links. + +Signed-off-by: Johannes Berg +--- + net/mac80211/mlme.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index dff90fc..620b3c7 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -4909,9 +4909,11 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, + + if (sdata->vif.valid_links) + link_info(link, +- "local address %pM, AP link address %pM\n", ++ "local address %pM, AP link address %pM%s\n", + link->conf->addr, +- assoc_data->link[link_id].bss->bssid); ++ assoc_data->link[link_id].bss->bssid, ++ link_id == assoc_data->assoc_link_id ? ++ " (assoc)" : ""); + + link_sta = rcu_dereference_protected(sta->link[link_id], + lockdep_is_held(&local->sta_mtx)); +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/821-16-wifi-mac80211-change-AddBA-deny-error-message.patch b/feeds/ipq95xx/mac80211/patches/qca/821-16-wifi-mac80211-change-AddBA-deny-error-message.patch new file mode 100644 index 000000000..c05c2c7a5 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/821-16-wifi-mac80211-change-AddBA-deny-error-message.patch @@ -0,0 +1,30 @@ +From 1864d995a43eb5925b3b89969f19bf62376954fa Mon Sep 17 00:00:00 2001 +From: Ramasamy Kaliappan +Date: Mon, 3 Jul 2023 16:27:24 +0530 +Subject: [PATCH 14/16] wifi: mac80211: change AddBA deny error message + +If the station has no HT, we deny the aggregation session +but the error message talks about QoS; change it to say HT +instead. + +Signed-off-by: Johannes Berg +--- + net/mac80211/agg-rx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c +index 31ab96e..b8ea025 100644 +--- a/net/mac80211/agg-rx.c ++++ b/net/mac80211/agg-rx.c +@@ -314,7 +314,7 @@ void ___ieee80211_start_rx_ba_session(struct sta_info *sta, + rcu_read_unlock(); + if (!sta->sta.deflink.ht_cap.ht_supported && band != NL80211_BAND_6GHZ) { + ht_dbg(sta->sdata, +- "STA %pM erroneously requests BA session on tid %d w/o QoS\n", ++ "STA %pM erroneously requests BA session on tid %d w/o HT\n", + sta->sta.addr, tid); + /* send a response anyway, it's an error case if we get here */ + goto end; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/821-17-wifi-mac80211-don-t-clear-DTIM-period-after-setting-.patch b/feeds/ipq95xx/mac80211/patches/qca/821-17-wifi-mac80211-don-t-clear-DTIM-period-after-setting-.patch new file mode 100644 index 000000000..ff155a0f7 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/821-17-wifi-mac80211-don-t-clear-DTIM-period-after-setting-.patch @@ -0,0 +1,80 @@ +From b9ffed9a5cdceee4f02810d8689b2c06bc04f436 Mon Sep 17 00:00:00 2001 +From: Ramasamy Kaliappan +Date: Mon, 3 Jul 2023 16:44:46 +0530 +Subject: [PATCH 15/16] wifi: mac80211: don't clear DTIM period after setting + it + +Fix the code that sets the DTIM period to always propagate it +into link->conf->dtim_period and not overwrite it, while still +preferring to set it from the beacon data if available. + +Signed-off-by: Johannes Berg +--- + net/mac80211/mlme.c | 30 +++++++++++++++++++++--------- + 1 file changed, 21 insertions(+), 9 deletions(-) + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 620b3c7..951362b 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -2728,18 +2728,10 @@ static u32 ieee80211_link_set_associated(struct ieee80211_link_data *link, + } + + if (link->u.mgd.have_beacon) { +- /* +- * If the AP is buggy we may get here with no DTIM period +- * known, so assume it's 1 which is the only safe assumption +- * in that case, although if the TIM IE is broken powersave +- * probably just won't work at all. +- */ +- bss_conf->dtim_period = link->u.mgd.dtim_period ?: 1; + bss_conf->beacon_rate = bss->beacon_rate; + changed |= BSS_CHANGED_BEACON_INFO; + } else { + bss_conf->beacon_rate = NULL; +- bss_conf->dtim_period = 0; + } + + /* Tell the driver to monitor connection quality (if supported) */ +@@ -4897,10 +4889,11 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, + } + + for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) { ++ struct cfg80211_bss *cbss = assoc_data->link[link_id].bss; + struct ieee80211_link_data *link; + struct link_sta_info *link_sta; + +- if (!assoc_data->link[link_id].bss) ++ if (!cbss) + continue; + + link = sdata_dereference(sdata->link[link_id], sdata); +@@ -4920,6 +4913,25 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, + if (WARN_ON(!link_sta)) + goto out_err; + ++ if (!link->u.mgd.have_beacon) { ++ const struct cfg80211_bss_ies *ies; ++ ++ rcu_read_lock(); ++ ies = rcu_dereference(cbss->beacon_ies); ++ if (ies) ++ link->u.mgd.have_beacon = true; ++ else ++ ies = rcu_dereference(cbss->ies); ++ ieee80211_get_dtim(ies, ++ &link->conf->sync_dtim_count, ++ &link->u.mgd.dtim_period); ++ link->conf->beacon_int = cbss->beacon_interval; ++ rcu_read_unlock(); ++ } ++ ++ link->conf->dtim_period = link->u.mgd.dtim_period ?: 1; ++ ++ + if (link_id != assoc_data->assoc_link_id) { + err = ieee80211_prep_channel(sdata, link, + assoc_data->link[link_id].bss, +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/821-18-wifi-mac80211-prohibit-IEEE80211_HT_CAP_DELAY_BA-wit.patch b/feeds/ipq95xx/mac80211/patches/qca/821-18-wifi-mac80211-prohibit-IEEE80211_HT_CAP_DELAY_BA-wit.patch new file mode 100644 index 000000000..dc4c6fc95 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/821-18-wifi-mac80211-prohibit-IEEE80211_HT_CAP_DELAY_BA-wit.patch @@ -0,0 +1,39 @@ +From ebceb1f462dea3df81dbd499fe5bb71e0f7f3f8f Mon Sep 17 00:00:00 2001 +From: Ramasamy Kaliappan +Date: Mon, 3 Jul 2023 16:46:01 +0530 +Subject: [PATCH 16/16] wifi: mac80211: prohibit IEEE80211_HT_CAP_DELAY_BA with + MLO + +This won't work right at least with the code as it is, so +at least for now just assume it's never set for MLO. It may +very well never change, almost no drivers support it. + +Signed-off-by: Johannes Berg +--- + net/mac80211/main.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/net/mac80211/main.c b/net/mac80211/main.c +index f92e70b..e486599 100644 +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -1188,6 +1188,16 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) + + channels += sband->n_channels; + ++ /* ++ * Due to the way the aggregation code handles this and it ++ * being an HT capability, we can't really support delayed ++ * BA in MLO (yet). ++ */ ++ if (WARN_ON(sband->ht_cap.ht_supported && ++ (sband->ht_cap.cap & IEEE80211_HT_CAP_DELAY_BA) && ++ hw->wiphy->flags & WIPHY_FLAG_SUPPORTS_MLO)) ++ return -EINVAL; ++ + if (max_bitrates < sband->n_bitrates) + max_bitrates = sband->n_bitrates; + supp_ht = supp_ht || sband->ht_cap.ht_supported; +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/821-19-wifi-mac80211-relocate-the-function-s-definition.patch b/feeds/ipq95xx/mac80211/patches/qca/821-19-wifi-mac80211-relocate-the-function-s-definition.patch new file mode 100644 index 000000000..7eb1e7669 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/821-19-wifi-mac80211-relocate-the-function-s-definition.patch @@ -0,0 +1,102 @@ +From 4f97a6a0a5401a329a2f8dd9c677751d7766fc46 Mon Sep 17 00:00:00 2001 +From: Ramasamy Kaliappan +Date: Tue, 4 Jul 2023 12:00:08 +0530 +Subject: [PATCH] wifi: mac80211: relocate the function's definition to fix the + compile fault + +The function "ieee80211_get_dtim" definition relocate to fix the compile fault + +Signed-off-by: Ramasamy Kaliappan +--- + net/mac80211/mlme.c | 68 ++++++++++++++++++++++----------------------- + 1 file changed, 34 insertions(+), 34 deletions(-) + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 951362b..2611d9f 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -4849,6 +4849,40 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, + return ret; + } + ++static bool ieee80211_get_dtim(const struct cfg80211_bss_ies *ies, ++ u8 *dtim_count, u8 *dtim_period) ++{ ++ const u8 *tim_ie = cfg80211_find_ie(WLAN_EID_TIM, ies->data, ies->len); ++ const u8 *idx_ie = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX, ies->data, ++ ies->len); ++ const struct ieee80211_tim_ie *tim = NULL; ++ const struct ieee80211_bssid_index *idx; ++ bool valid = tim_ie && tim_ie[1] >= 2; ++ ++ if (valid) ++ tim = (void *)(tim_ie + 2); ++ ++ if (dtim_count) ++ *dtim_count = valid ? tim->dtim_count : 0; ++ ++ if (dtim_period) ++ *dtim_period = valid ? tim->dtim_period : 0; ++ ++ /* Check if value is overridden by non-transmitted profile */ ++ if (!idx_ie || idx_ie[1] < 3) ++ return valid; ++ ++ idx = (void *)(idx_ie + 2); ++ ++ if (dtim_count) ++ *dtim_count = idx->dtim_count; ++ ++ if (dtim_period) ++ *dtim_period = idx->dtim_period; ++ ++ return true; ++} ++ + static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, + struct ieee80211_mgmt *mgmt, + struct ieee802_11_elems *elems, +@@ -6440,40 +6474,6 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) + rcu_read_unlock(); + } + +-static bool ieee80211_get_dtim(const struct cfg80211_bss_ies *ies, +- u8 *dtim_count, u8 *dtim_period) +-{ +- const u8 *tim_ie = cfg80211_find_ie(WLAN_EID_TIM, ies->data, ies->len); +- const u8 *idx_ie = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX, ies->data, +- ies->len); +- const struct ieee80211_tim_ie *tim = NULL; +- const struct ieee80211_bssid_index *idx; +- bool valid = tim_ie && tim_ie[1] >= 2; +- +- if (valid) +- tim = (void *)(tim_ie + 2); +- +- if (dtim_count) +- *dtim_count = valid ? tim->dtim_count : 0; +- +- if (dtim_period) +- *dtim_period = valid ? tim->dtim_period : 0; +- +- /* Check if value is overridden by non-transmitted profile */ +- if (!idx_ie || idx_ie[1] < 3) +- return valid; +- +- idx = (void *)(idx_ie + 2); +- +- if (dtim_count) +- *dtim_count = idx->dtim_count; +- +- if (dtim_period) +- *dtim_period = idx->dtim_period; +- +- return true; +-} +- + static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, + struct cfg80211_bss *cbss, s8 link_id, + const u8 *ap_mld_addr, bool assoc, +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/821-20-wifi-mac80211-correct-SMPS-mode-in-HE-6-GHz-capabili.patch b/feeds/ipq95xx/mac80211/patches/qca/821-20-wifi-mac80211-correct-SMPS-mode-in-HE-6-GHz-capabili.patch new file mode 100644 index 000000000..92c2e3867 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/821-20-wifi-mac80211-correct-SMPS-mode-in-HE-6-GHz-capabili.patch @@ -0,0 +1,89 @@ +From abd27d063c2e85e45ffc4390247abf47e5b55997 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Thu, 25 Aug 2022 20:57:32 +0200 +Subject: [PATCH] wifi: mac80211: correct SMPS mode in HE 6 GHz capability + +If we add 6 GHz capability in MLO, we cannot use the SMPS +mode from the deflink. Pass it separately instead since on +a second link we don't even have a link data struct yet. + +Cherry picked from the patch: https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git/commit/?id=abd27d0 + +Signed-off-by: Johannes Berg +Signed-off-by: Ramasamy Kaliappan +--- + net/mac80211/ieee80211_i.h | 1 + + net/mac80211/mesh.c | 2 +- + net/mac80211/mlme.c | 5 +++-- + net/mac80211/util.c | 3 ++- + 4 files changed, 7 insertions(+), 4 deletions(-) + +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -2488,6 +2488,7 @@ u8 *ieee80211_ie_build_he_cap(ieee80211_ + const struct ieee80211_sta_he_cap *he_cap, + u8 *end); + void ieee80211_ie_build_he_6ghz_cap(struct ieee80211_sub_if_data *sdata, ++ enum ieee80211_smps_mode smps_mode, + struct sk_buff *skb); + u8 *ieee80211_ie_build_he_oper(u8 *pos, struct cfg80211_chan_def *chandef); + u8 ieee80211_ie_len_eht_cap(struct ieee80211_sub_if_data *sdata, u8 iftype); +--- a/net/mac80211/mesh.c ++++ b/net/mac80211/mesh.c +@@ -646,7 +646,8 @@ int mesh_add_he_6ghz_cap_ie(struct ieee8 + return 0; + + if (sband->band == NL80211_BAND_6GHZ) +- ieee80211_ie_build_he_6ghz_cap(sdata, skb); ++ ieee80211_ie_build_he_6ghz_cap(sdata, ++ sdata->deflink.smps_mode, skb); + return 0; + } + +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -719,6 +719,7 @@ static bool ieee80211_add_vht_ie(struct + static void ieee80211_add_he_ie(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb, + struct ieee80211_supported_band *sband, ++ enum ieee80211_smps_mode smps_mode, + ieee80211_conn_flags_t conn_flags) + { + u8 *pos, *pre_he_pos; +@@ -744,7 +745,7 @@ static void ieee80211_add_he_ie(struct i + skb_trim(skb, skb->len - (pre_he_pos + he_cap_size - pos)); + + if (sband->band == NL80211_BAND_6GHZ) +- ieee80211_ie_build_he_6ghz_cap(sdata, skb); ++ ieee80211_ie_build_he_6ghz_cap(sdata, smps_mode, skb); + } + + static void ieee80211_add_eht_ie(struct ieee80211_sub_if_data *sdata, +@@ -1125,7 +1126,7 @@ static size_t ieee80211_assoc_link_elems + offset); + + if (!(assoc_data->link[link_id].conn_flags & IEEE80211_CONN_DISABLE_HE)) { +- ieee80211_add_he_ie(sdata, skb, sband, ++ ieee80211_add_he_ie(sdata, skb, sband, smps_mode, + assoc_data->link[link_id].conn_flags); + ADD_PRESENT_EXT_ELEM(WLAN_EID_EXT_HE_CAPABILITY); + } +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -3275,6 +3275,7 @@ end: + } + + void ieee80211_ie_build_he_6ghz_cap(struct ieee80211_sub_if_data *sdata, ++ enum ieee80211_smps_mode smps_mode, + struct sk_buff *skb) + { + struct ieee80211_supported_band *sband; +@@ -3301,7 +3302,7 @@ void ieee80211_ie_build_he_6ghz_cap(stru + cap = le16_to_cpu(iftd->he_6ghz_capa.capa); + cap &= ~IEEE80211_HE_6GHZ_CAP_SM_PS; + +- switch (sdata->deflink.smps_mode) { ++ switch (smps_mode) { + case IEEE80211_SMPS_AUTOMATIC: + case IEEE80211_SMPS_NUM_MODES: + WARN_ON(1); diff --git a/feeds/ipq95xx/mac80211/patches/qca/821-21-wifi-mac80211-change-nl80211.h-to-match-nl80211_copy.patch b/feeds/ipq95xx/mac80211/patches/qca/821-21-wifi-mac80211-change-nl80211.h-to-match-nl80211_copy.patch new file mode 100644 index 000000000..3f45fd205 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/821-21-wifi-mac80211-change-nl80211.h-to-match-nl80211_copy.patch @@ -0,0 +1,40 @@ +From 050477b7a98af9f2d65794ff5fb4ab317e57d247 Mon Sep 17 00:00:00 2001 +From: Ramasamy Kaliappan +Date: Fri, 7 Jul 2023 13:36:04 +0530 +Subject: [PATCH] wifi: mac80211: change nl80211.h to match nl80211_copy.h from + hostapd + +Change nl80211.h to match nl80211_copy.h from hostapd. + +Signed-off-by: Ramasamy Kaliappan +--- + include/uapi/linux/nl80211.h | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/include/uapi/linux/nl80211.h ++++ b/include/uapi/linux/nl80211.h +@@ -3353,6 +3353,7 @@ enum nl80211_attrs { + + NL80211_ATTR_TX_HW_TIMESTAMP, + NL80211_ATTR_RX_HW_TIMESTAMP, ++ NL80211_ATTR_TD_BITMAP, + + NL80211_ATTR_HE_MUEDCA_PARAMS, + +@@ -5143,7 +5144,7 @@ enum nl80211_bss { + NL80211_BSS_CHAIN_SIGNAL, + NL80211_BSS_FREQUENCY_OFFSET, + NL80211_BSS_MLO_LINK_ID, +- ++ NL80211_BSS_MLD_ADDR, + /* keep last */ + __NL80211_BSS_AFTER_LAST, + NL80211_BSS_MAX = __NL80211_BSS_AFTER_LAST - 1 +@@ -6588,6 +6589,7 @@ enum nl80211_ext_feature_index { + NL80211_EXT_FEATURE_RADAR_BACKGROUND, + NL80211_EXT_FEATURE_STA_MGMT_RTS_CTS, + NL80211_EXT_FEATURE_BEACON_RATE_EHT, ++ NL80211_EXT_FEATURE_POWERED_ADDR_CHANGE, + + /* add new features before the definition below */ + NUM_NL80211_EXT_FEATURES, diff --git a/feeds/ipq95xx/mac80211/patches/qca/821-22-wifi-mac80211-handle-csa-block-tx-per-link-basis-for-STA-di.patch b/feeds/ipq95xx/mac80211/patches/qca/821-22-wifi-mac80211-handle-csa-block-tx-per-link-basis-for-STA-di.patch new file mode 100644 index 000000000..b186d3501 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/821-22-wifi-mac80211-handle-csa-block-tx-per-link-basis-for-STA-di.patch @@ -0,0 +1,50 @@ +From 4e35865a758a7e7e6386a0d303276cf5bca6e165 Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Fri, 8 Sep 2023 12:42:27 +0530 +Subject: [PATCH] wifi: mac80211: handle csa block tx per link basis for STA disconnect + +In case of ML STA + AP interfaces (repeater scenario), when we do +channel change from root AP, STA interfaces are not able to join back +with root AP and fails in authentication phase. + +This is seen because, when channel switch is initiated with blocktx flag, +STA interface parses this and stops the interface queue with CSA reason. +But, since it is a repeater scenario, it was not able to finalize the +CSA because AP was in different channel context and STA was trying to move +to different channel context. When STA is not able to finalize the CSA, it +sends disassoc and brings down the STA interface, and then STA tries to start +fresh association but the authentication packets were not sent to driver. + +Because of which STA was not able to connect back. STA interface should have reset +the queue when the interface was brought down but it was only done for deflink and +not for all valid links. + +Hence, add changes to handle the reset of queue per link basis during STA disconnect + +Signed-off-by: Harshitha Prem +--- + net/mac80211/mlme.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index a6fc331..480b516 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -2996,6 +2996,14 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, + link = sdata_dereference(sdata->link[link_id], sdata); + if (!link) + continue; ++ ++ link->conf->csa_active = false; ++ if (link->csa_block_tx) { ++ ieee80211_wake_vif_queues(local, sdata, ++ IEEE80211_QUEUE_STOP_REASON_CSA); ++ link->csa_block_tx = false; ++ } ++ + ieee80211_link_release_channel(link); + } + +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/822-wifi-mac80211-handling-msdu-buffer-type.patch b/feeds/ipq95xx/mac80211/patches/qca/822-wifi-mac80211-handling-msdu-buffer-type.patch new file mode 100644 index 000000000..1bb9d91af --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/822-wifi-mac80211-handling-msdu-buffer-type.patch @@ -0,0 +1,165 @@ +From 1538131d583bd9e377831b35253a648095e276b9 Mon Sep 17 00:00:00 2001 +From: Logapriya P +Date: Thu, 27 Jul 2023 19:21:55 +0530 +Subject: [PATCH] ath12k: add handling for MSDU buffer type + +REO exception ring of IPQ5322 receives buffer type other than +MSDU descriptor type which is unexpected behaviour. This results +in triggering host BUG_ON. In the multiclient, this particular +behaviour is observed frequently. + +The above packets are sent from un-associated peers and AST lookup +for the same is expected to fail. Hence, added code to handle the same +as MSDU buffer type. + +Signed-off-by: P Praneesh +Signed-off-by: Logapriya P +--- + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/debugfs.c | 2 ++ + drivers/net/wireless/ath/ath12k/dp_rx.c | 40 +++++++++++++++++++++++ + drivers/net/wireless/ath/ath12k/dp_rx.h | 1 + + drivers/net/wireless/ath/ath12k/hal_rx.c | 6 ---- + 5 files changed, 44 insertions(+), 6 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -1198,6 +1198,7 @@ struct ath12k_soc_dp_stats { + struct ath12k_soc_dp_tx_err_stats tx_err; + struct ath12k_dp_ring_bp_stats bp_stats; + u32 first_and_last_msdu_bit_miss; ++ u32 reo_excep_msdu_buf_type; + }; + + #ifdef CPTCFG_ATH12K_PPE_DS_SUPPORT +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -1627,6 +1627,8 @@ static ssize_t ath12k_debugfs_dump_soc_d + len += scnprintf(buf + len, size - len, "%s: handled %u dropped %u\n", + reo_err[i], soc_stats->reo_error[i], + soc_stats->reo_error_drop[i]); ++ len += scnprintf(buf + len, size - len, "REO excep MSDU buf type:%u\n", ++ soc_stats->reo_excep_msdu_buf_type); + + len += scnprintf(buf + len, size - len, "\nHAL REO errors:\n"); + len += scnprintf(buf + len, size - len, +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -4388,6 +4388,37 @@ int ath12k_dp_rx_process_err(struct ath1 + sizeof(*reo_desc), srng); + BUG_ON(1); + } ++ ++ hw_link_id = u32_get_bits(reo_desc->info0, ++ HAL_REO_DEST_RING_INFO0_SRC_LINK_ID); ++ ++ rcu_read_lock(); ++ if (hw_link_id < ATH12K_GROUP_MAX_RADIO) ++ ar = rcu_dereference(ab->ag->hw_links[hw_link_id]); ++ else ++ ar = NULL; ++ ++ rcu_read_unlock(); ++ ++ if (!ar || ar->ab != ab) { ++ ath12k_err(ab, "invalid src link id %d drop %d on chip id %d err process\n", ++ hw_link_id, drop, ab->chip_id); ++ ++ ath12k_err_dump(ab, NULL, "rx err desc: ", reo_desc, ++ sizeof(*reo_desc), srng); ++ BUG_ON(1); ++ } ++ ++ /* Below case is added to handle data packet from un-associated clients. ++ * As it is expected that AST lookup will fail for ++ * un-associated station's data packets. ++ */ ++ if (u32_get_bits(reo_desc->info0, HAL_REO_DEST_RING_INFO0_BUFFER_TYPE) == ++ HAL_REO_DEST_RING_BUFFER_TYPE_MSDU) { ++ ath12k_dp_h_msdu_buffer_type(ab, desc); ++ continue; ++ } ++ + link_desc_va = link_desc_banks[desc_bank].vaddr + + (paddr - link_desc_banks[desc_bank].paddr); + ath12k_hal_rx_msdu_link_info_get(link_desc_va, &num_msdus, msdu_cookies, +@@ -4414,23 +4445,6 @@ int ath12k_dp_rx_process_err(struct ath1 + HAL_WBM_REL_BM_ACT_PUT_IN_IDLE); + } + +- hw_link_id = u32_get_bits(reo_desc->info0, +- HAL_REO_DEST_RING_INFO0_SRC_LINK_ID); +- +- rcu_read_lock(); +- if (hw_link_id < ATH12K_GROUP_MAX_RADIO) +- ar = rcu_dereference(ab->ag->hw_links[hw_link_id]); +- rcu_read_unlock(); +- +- if (!ar || ar->ab != ab) { +- ath12k_err(ab, "invalid src link id %d drop %d on chip id %d err process\n", +- hw_link_id, drop, ab->chip_id); +- +- ath12k_err_dump(ab, NULL, "rx err desc: ", reo_desc, +- sizeof(*reo_desc), srng); +- BUG_ON(1); +- } +- + for (i = 0; i < num_msdus; i++) { + if (drop) + ar->wmm_stats.total_wmm_rx_drop[ar->wmm_stats.rx_type]++; +@@ -5447,3 +5461,32 @@ int ath12k_dp_rx_pktlog_stop(struct ath1 + + return 0; + } ++ ++void ath12k_dp_h_msdu_buffer_type(struct ath12k_base *ab, u32 *rx_desc) ++{ ++ struct hal_reo_dest_ring *desc = (struct hal_reo_dest_ring *)rx_desc; ++ struct ath12k_rx_desc_info *desc_info; ++ struct sk_buff *msdu; ++ u64 desc_va; ++ ++ desc_va = ((u64)desc->buf_va_hi << 32 | desc->buf_va_lo); ++ desc_info = (struct ath12k_rx_desc_info *)((unsigned long)desc_va); ++ if (!desc_info) { ++ ath12k_warn(ab, " rx exception, hw cookie conversion failed"); ++ goto skip_skb_free; ++ } ++ ++ if (desc_info->magic != ATH12K_DP_RX_DESC_MAGIC) {\ ++ ath12k_warn(ab, " rx exception, magic check failed"); ++ goto skip_skb_free; ++ } ++ ++ msdu = desc_info->skb; ++ desc_info->skb = NULL; ++ spin_lock_bh(&ab->dp.rx_desc_lock); ++ list_move_tail(&desc_info->list, &ab->dp.rx_desc_free_list); ++ spin_unlock_bh(&ab->dp.rx_desc_lock); ++ dev_kfree_skb_any(msdu); ++skip_skb_free: ++ ab->soc_stats.reo_excep_msdu_buf_type++; ++} +--- a/drivers/net/wireless/ath/ath12k/dp_rx.h ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.h +@@ -234,4 +234,5 @@ void ath12k_dp_peer_reo_tid_setup(struct + void ath12k_dp_tid_setup(void *data, struct ieee80211_sta *sta); + void ath12k_dp_reset_rx_reo_tid_q(void *vaddr, u32 ba_window_size, + u8 tid); ++void ath12k_dp_h_msdu_buffer_type(struct ath12k_base *ab, u32 *rx_desc); + #endif /* ATH12K_DP_RX_H */ +--- a/drivers/net/wireless/ath/ath12k/hal_rx.c ++++ b/drivers/net/wireless/ath/ath12k/hal_rx.c +@@ -355,12 +355,6 @@ int ath12k_hal_desc_reo_parse_err(struct + return -EINVAL; + } + +- if (u32_get_bits(desc->info0, HAL_REO_DEST_RING_INFO0_BUFFER_TYPE) != +- HAL_REO_DEST_RING_BUFFER_TYPE_LINK_DESC) { +- ath12k_warn(ab, "expected buffer type link_desc"); +- return -EINVAL; +- } +- + ath12k_hal_rx_reo_ent_paddr_get(ab, rx_desc, paddr, &cookie); + *desc_bank = u32_get_bits(cookie, DP_LINK_DESC_BANK_MASK); + diff --git a/feeds/ipq95xx/mac80211/patches/qca/825-ath12k-Vif-Delete-Timeout-Cleanup-Fix.patch b/feeds/ipq95xx/mac80211/patches/qca/825-ath12k-Vif-Delete-Timeout-Cleanup-Fix.patch new file mode 100644 index 000000000..32ce102c6 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/825-ath12k-Vif-Delete-Timeout-Cleanup-Fix.patch @@ -0,0 +1,62 @@ +From ed202790fdd06b3b807ed920c914bd19bdf23dfc Mon Sep 17 00:00:00 2001 +From: Yuvasree Sivasankaran +Date: Tue, 25 Jul 2023 12:50:00 +0530 +Subject: [PATCH] ath12k:Virtual Interface Delete timeout Handler + +ath12k:Fix driver state in timeout cleanup of Vif Deletion + +When timeout occurs during vif delete, the cleanup only deletes the +list but driver vif state is not cleared. This leads to crash during +wifi down/ reboot where driver will still try to delete a vif which list +is already deleted. So, driver vif state clearing is included in timeout cleanup + +Observed call trace: +ath12k_mac_op_change_vif_links+0x125c/0x2268 [ath12k] +ath12k_mac_ap_ps_recalc+0x22c/0x2af4 [ath12k] +ath12k_mac_ap_ps_recalc+0x790/0x2af4 [ath12k] +drv_remove_interface+0x68/0x80 [mac80211] +ieee80211_del_virtual_monitor+0xe4/0xa04 [mac80211] +ieee80211_del_virtual_monitor+0x7d4/0xa04 [mac80211] +ieee80211_del_virtual_monitor+0x9cc/0xa04 [mac80211] +__dev_close_many+0xbc/0xec +__dev_change_flags+0xd0/0x19c +dev_change_flags+0x20/0x5c +devinet_ioctl+0x258/0x580 +inet_ioctl+0x678/0x6ac +sock_do_ioctl+0x4c/0x61c +sock_ioctl+0x80c/0x870 +vfs_ioctl+0x24/0x48 +do_vfs_ioctl+0xa3c/0xaa8 +ksys_ioctl+0x44/0x74 +__arm64_sys_ioctl+0x18/0x2c8 +el0_svc_common.constprop.0+0x98/0x114 +el0_svc_handler+0x18/0x20 + +Signed-off-by: Yuvasree Sivasankaran +--- + drivers/net/wireless/ath/ath12k/mac.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index e3aecca..0c70c11 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -4939,13 +4939,13 @@ static int ath12k_mac_vdev_delete(struct ath12k *ar, struct ath12k_link_vif *arv + ar->ab->free_vdev_stats_id_map &= ~(1LL << arvif->vdev_stats_id); + ar->num_created_vdevs--; + arvif->ahvif->num_vdev_created--; +- arvif->is_created = false; +- arvif->ar = NULL; + + ath12k_dbg(ar->ab, ATH12K_DBG_SET(MAC, L1), "mac vdev delete id %d type %d subtype %d map %llx\n", + arvif->vdev_id, ahvif->vdev_type, ahvif->vdev_subtype, + ar->ab->free_vdev_map); + clean_up: ++ arvif->is_created = false; ++ arvif->ar = NULL; + spin_lock_bh(&ar->data_lock); + list_del(&arvif->list); + spin_unlock_bh(&ar->data_lock); +-- +2.34.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/825-ath12k-optimize-ppe-ds-rx-path.patch b/feeds/ipq95xx/mac80211/patches/qca/825-ath12k-optimize-ppe-ds-rx-path.patch new file mode 100644 index 000000000..9c96a17d9 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/825-ath12k-optimize-ppe-ds-rx-path.patch @@ -0,0 +1,459 @@ +From ce5dfd5b4d7b36a87e642033979b98ec47dd5efd Mon Sep 17 00:00:00 2001 +From: Pradeep Kumar Chitrapu +Date: Thu, 27 Jul 2023 10:54:24 -0700 +Subject: [PATCH] ath12k: optimize PPE direct switch rx path + +These optimizations showed 20% CPU saved for 5GHz 160MHz + 6GHz 320MHz case. + - Decrease number of branch jumps using separate srng access functions + - Currently, rx_desc is being removed from rx_desc_used_list + and added back after rxdma srng replenish. This increases cpu consumption + as attempts to acquire locks are made multiple times for each operation. + - Avoid this by maintaining index arrays and replenish rxdma while + rx descriptors continue to be in rx_desc_used_list. When no rxdma srng + has no space, rest of descriptors will be added to rx_desc_free_list + after cleaning up the skb's. + - Group frequently accessed data structure in rx_desc to avoid cache misses. + As part of this, replace ab with just chip_id inside rx_desc which helps + to reduce rx_desc size. + - increase REO2PPE ring size to handle more number of ring descriptors. + +Signed-off-by: Pradeep Kumar Chitrapu +Signed-off-by: P Praneesh +--- + drivers/net/wireless/ath/ath12k/dp.c | 2 +- + drivers/net/wireless/ath/ath12k/dp.h | 7 +- + drivers/net/wireless/ath/ath12k/dp_rx.c | 1 + + drivers/net/wireless/ath/ath12k/hal.h | 8 +++ + drivers/net/wireless/ath/ath12k/ppe.c | 88 +++++++++++-------------- + 5 files changed, 54 insertions(+), 52 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -1686,18 +1686,6 @@ static void ath12k_dp_cc_cleanup(struct + dev_kfree_skb_any(skb); + } + +- list_for_each_entry_safe(desc_info, tmp, &dp->rx_ppeds_reuse_list, list) { +- list_del(&desc_info->list); +- skb = desc_info->skb; +- +- if (!skb) +- continue; +- +- dma_unmap_single(ab->dev, ATH12K_SKB_RXCB(skb)->paddr, +- skb->len + skb_tailroom(skb), DMA_FROM_DEVICE); +- dev_kfree_skb_any(skb); +- } +- + for (i = 0; i < ATH12K_NUM_RX_SPT_PAGES; i++) { + if (!dp->spt_info->rxbaddr[i]) + continue; +@@ -2151,7 +2139,7 @@ static int ath12k_dp_cc_desc_init(struct + for (j = 0; j < ATH12K_MAX_SPT_ENTRIES; j++) { + rx_descs[j].cookie = ath12k_dp_cc_cookie_gen(ppt_idx, j); + rx_descs[j].magic = ATH12K_DP_RX_DESC_MAGIC; +- rx_descs[j].ab = ab; ++ rx_descs[j].chip_id = ab->chip_id; + list_add_tail(&rx_descs[j].list, &dp->rx_desc_free_list); + + /* Update descriptor VA in SPT */ +@@ -2190,7 +2178,6 @@ static int ath12k_dp_cc_init(struct ath1 + + INIT_LIST_HEAD(&dp->rx_desc_free_list); + INIT_LIST_HEAD(&dp->rx_desc_used_list); +- INIT_LIST_HEAD(&dp->rx_ppeds_reuse_list); + spin_lock_init(&dp->rx_desc_lock); + + for (i = 0; i < ATH12K_HW_MAX_QUEUES; i++) { +--- a/drivers/net/wireless/ath/ath12k/dp.h ++++ b/drivers/net/wireless/ath/ath12k/dp.h +@@ -188,7 +188,7 @@ struct ath12k_pdev_dp { + #define DP_RX_BUFFER_SIZE_LITE 1024 + #define DP_RX_BUFFER_ALIGN_SIZE 128 + +-#define DP_REO2PPE_RING_SIZE 8192 ++#define DP_REO2PPE_RING_SIZE 16384 + #define DP_PPE2TCL_RING_SIZE 2048 + #define DP_PPE_WBM2SW_RING_SIZE 8192 + #define HAL_REO2PPE_DST_IND 6 +@@ -311,10 +311,11 @@ struct ath12k_hp_update_timer { + + struct ath12k_rx_desc_info { + struct list_head list; +- struct sk_buff *skb; + u32 cookie; ++ dma_addr_t paddr; ++ u8 chip_id; ++ struct sk_buff *skb; + u32 magic; +- struct ath12k_base *ab; + }; + + struct ath12k_tx_desc_info { +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -307,6 +307,7 @@ int ath12k_dp_rx_bufs_replenish(struct a + } + + rx_desc->skb = skb; ++ rx_desc->paddr = paddr; + cookie = rx_desc->cookie; + list_del(&rx_desc->list); + list_add_tail(&rx_desc->list, &dp->rx_desc_used_list); +--- a/drivers/net/wireless/ath/ath12k/hal.h ++++ b/drivers/net/wireless/ath/ath12k/hal.h +@@ -1337,5 +1337,13 @@ void ath12k_hal_srng_access_umac_dst_rin + srng->timestamp = jiffies; + } + ++static inline ++void ath12k_hal_srng_access_lmac_src_ring_end_nolock(struct hal_srng *srng) ++{ ++ 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; ++} ++ ++ + ssize_t ath12k_debugfs_hal_dump_srng_stats(struct ath12k_base *ab, char *buf, int size); + #endif +--- a/drivers/net/wireless/ath/ath12k/ppe.c ++++ b/drivers/net/wireless/ath/ath12k/ppe.c +@@ -122,109 +122,89 @@ static inline void ath12k_ppeds_enable_s + } + } + +-int ath12k_dp_rx_bufs_replenish_ppeds(struct ath12k_base *ab, +- struct dp_rxdma_ring *rx_ring, +- int req_entries, +- enum hal_rx_buf_return_buf_manager mgr) ++static bool ath12k_ppeds_free_rx_desc(struct ppe_ds_wlan_rxdesc_elem *arr, ++ struct ath12k_base *ab, int index) + { ++ struct ath12k_rx_desc_info *rx_desc; ++ struct sk_buff *skb; ++ ++ rx_desc = (struct ath12k_rx_desc_info *)arr[index].cookie; ++ if (rx_desc->chip_id != ab->chip_id) ++ return false; ++ ++ skb = rx_desc->skb; ++ rx_desc->skb= NULL; ++ spin_lock_bh(&ab->dp.rx_desc_lock); ++ list_move_tail(&rx_desc->list, &ab->dp.rx_desc_free_list); ++ spin_unlock_bh(&ab->dp.rx_desc_lock); ++ if (!skb) { ++ ath12k_err(ab, "ppeds rx desc with no skb when freeing\n"); ++ return false; ++ } ++ ++ /* When recycled_for_ds is set, packet is used by DS rings and never has ++ * touched by host. So, buffer unmap can be skipped. */ ++ if (!skb->recycled_for_ds) { ++ dmac_inv_range_no_dsb(skb->data, skb->data + (skb->len + ++ skb_tailroom(skb))); ++ dma_unmap_single_attrs(ab->dev, ATH12K_SKB_RXCB(skb)->paddr, ++ skb->len + skb_tailroom(skb), ++ DMA_FROM_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); ++ } ++ ++ skb->recycled_for_ds = 0; ++ skb->fast_recycled = 0; ++ dev_kfree_skb_any(skb); ++ return true; ++} ++ ++int ath12k_dp_rx_bufs_replenish_ppeds(struct ath12k_base *ab, int req_entries, ++ u16 *idx_of_ab, struct ppe_ds_wlan_rxdesc_elem *arr) ++{ ++ struct dp_rxdma_ring *rx_ring = &ab->dp.rx_refill_buf_ring; + struct hal_srng *rxdma_srng; + u32 *rxdma_desc; + u32 cookie; + dma_addr_t paddr; +- struct sk_buff *skb; +- struct ath12k_rx_desc_info *rx_desc, *cur; +- int count = 0, num_remain; ++ struct ath12k_rx_desc_info *rx_desc; ++ int count = 0, num_remain, i; ++ enum hal_rx_buf_return_buf_manager mgr = ab->hw_params->hal_params->rx_buf_rbm; + + rxdma_srng = &ab->hal.srng_list[rx_ring->refill_buf_ring.ring_id]; + + spin_lock_bh(&rxdma_srng->lock); +- ath12k_hal_srng_access_begin(ab, rxdma_srng); ++ ath12k_hal_srng_access_src_ring_begin_nolock(rxdma_srng); + + num_remain = req_entries; +- while (num_remain > 0) { +- spin_lock_bh(&ab->dp.rx_desc_lock); ++ for (i = 0 ; i < req_entries; i++) { ++ if ((i + 1) < (req_entries - 1)) ++ prefetch((struct ath12k_rx_desc_info *)arr[idx_of_ab[i + 1]].cookie); + +- rx_desc = list_first_entry_or_null(&ab->dp.rx_ppeds_reuse_list, +- struct ath12k_rx_desc_info, +- list); +- if (!rx_desc) { +- spin_unlock_bh(&ab->dp.rx_desc_lock); ++ rx_desc = (struct ath12k_rx_desc_info *)arr[idx_of_ab[i]].cookie; ++ if (!rx_desc) + break; +- } + +- skb = rx_desc->skb; +- if (!skb) { ++ if (!rx_desc->skb) { + ath12k_err(ab, "ppeds rx desc with no skb when reusing!\n"); +- spin_unlock_bh(&ab->dp.rx_desc_lock); + break; + } + cookie = rx_desc->cookie; +- list_move_tail(&rx_desc->list, &ab->dp.rx_desc_used_list); +- spin_unlock_bh(&ab->dp.rx_desc_lock); ++ paddr = rx_desc->paddr; + + rxdma_desc = ath12k_hal_srng_src_get_next_entry(ab, rxdma_srng); +- if (!rxdma_desc) { +- /* Remove desc from used list when no rxdma entry is available */ +- spin_lock_bh(&ab->dp.rx_desc_lock); +- list_move_tail(&rx_desc->list, &ab->dp.rx_ppeds_reuse_list); +- spin_unlock_bh(&ab->dp.rx_desc_lock); ++ if (!rxdma_desc) + break; +- } + +- paddr = ATH12K_SKB_RXCB(skb)->paddr; + ath12k_hal_rx_buf_addr_info_set(rxdma_desc, paddr, cookie, mgr); +- + num_remain--; +- count++; + } +- ath12k_hal_srng_access_end(ab, rxdma_srng); +- spin_unlock_bh(&rxdma_srng->lock); +- +- if (!ab->stats_disable) +- ab->ppeds_stats.num_rx_desc_reused += count; + +- if (count == req_entries) +- return 0; ++ ath12k_hal_srng_access_lmac_src_ring_end_nolock(rxdma_srng); ++ spin_unlock_bh(&rxdma_srng->lock); + + /* move any remaining descriptors to free list */ +- count = 0; +- while (num_remain) { +- spin_lock_bh(&ab->dp.rx_desc_lock); +- cur = list_first_entry_or_null(&ab->dp.rx_ppeds_reuse_list, +- struct ath12k_rx_desc_info, +- list); +- if (!cur) { +- /* break the loop as soon as list is empty */ +- spin_unlock_bh(&ab->dp.rx_desc_lock); +- break; +- } +- +- skb = cur->skb; +- cur->skb= NULL; +- list_move_tail(&cur->list, &ab->dp.rx_desc_free_list); +- spin_unlock_bh(&ab->dp.rx_desc_lock); +- num_remain--; +- count++; +- +- if (!skb) { +- ath12k_err(ab, "ppeds rx desc with no skb when freeing\n"); +- continue; +- } +- +- /* When recycled_for_ds is set, packet is used by DS rings and never has +- * touched by host. So, buffer unmap can be skipped. */ +- if (!skb->recycled_for_ds) { +- dmac_inv_range_no_dsb(skb->data, skb->data + (skb->len + +- skb_tailroom(skb))); +- dma_unmap_single_attrs(ab->dev, ATH12K_SKB_RXCB(skb)->paddr, +- skb->len + skb_tailroom(skb), +- DMA_FROM_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); +- } +- +- skb->recycled_for_ds = 0; +- skb->fast_recycled = 0; +- dev_kfree_skb_any(skb); +- } ++ for (; i < req_entries; i++) ++ count += ath12k_ppeds_free_rx_desc(arr, ab, i); + + if (!ab->stats_disable) + ab->ppeds_stats.num_rx_desc_freed += count; +@@ -232,47 +212,80 @@ int ath12k_dp_rx_bufs_replenish_ppeds(st + return 0; + } + ++/* TODO: Fetch this directly from ppe_ds.h file. allocating dynamically will increase CPU */ ++#ifndef PPE_DS_TXCMPL_DEF_BUDGET ++#define PPE_DS_TXCMPL_DEF_BUDGET 256 ++#endif ++ + static void ath12k_ppeds_release_rx_desc(ppe_ds_wlan_handle_t *ppeds_handle, + struct ppe_ds_wlan_rxdesc_elem *arr, u16 count) + { + struct ath12k_base *ab = *(struct ath12k_base **)ppe_ds_wlan_priv(ppeds_handle); + struct ath12k_base *src_ab = NULL; ++ struct ath12k_hw_group *ag = ab->ag; + u32 rx_bufs_reaped[ATH12K_MAX_SOCS] = {0}; + struct ath12k_rx_desc_info *rx_desc; +- struct dp_rxdma_ring *rx_ring; + int chip_id; +- int i = 0; ++ u32 i = 0, new_size, num_free_desc; ++ u16 *tmp; + + if (!ab->stats_disable) + ab->ppeds_stats.release_rx_desc_cnt += count; + ++ if (unlikely(count > ab->ppeds_rx_num_elem)) { ++ new_size = sizeof(u16) * count; ++ for (chip_id = 0; chip_id < ag->num_chip; chip_id++) { ++ tmp = krealloc(*ab->ppeds_rx_idx[chip_id], new_size, GFP_ATOMIC); ++ if (!tmp) { ++ ath12k_err(ab, "ppeds: rx desc realloc failed for size %u\n", ++ count); ++ goto err_h_alloc_failure; ++ } ++ ++ *ab->ppeds_rx_idx[chip_id] = tmp; ++ } ++ ++ ab->ppeds_rx_num_elem = count; ++ ab->ppeds_stats.num_rx_desc_realloc =+ chip_id; ++ } ++ + for (i = 0; i < count; i++) { ++ if ((i + 1) < (count - 1)) ++ prefetch((struct ath12k_rx_desc_info *)arr[i + 1].cookie); ++ + rx_desc = (struct ath12k_rx_desc_info *)arr[i].cookie; + if (rx_desc == NULL) { + ath12k_err(ab,"error: rx desc is null\n"); + continue; + } +- src_ab = rx_desc->ab; +- /* TODO: review split phy */ +- rx_bufs_reaped[src_ab->chip_id]++; +- +- spin_lock_bh(&src_ab->dp.rx_desc_lock); +- list_move_tail(&rx_desc->list, &src_ab->dp.rx_ppeds_reuse_list); +- spin_unlock_bh(&src_ab->dp.rx_desc_lock); ++ chip_id = rx_desc->chip_id; ++ /* Maintain indexes of arr per ab seperately, which can accessed easily ++ * during per ab's rxdma srng replenish ++ */ ++ ab->ppeds_rx_idx[chip_id][rx_bufs_reaped[chip_id]] = i; ++ rx_bufs_reaped[chip_id]++; + } + +- for (chip_id = 0; chip_id < ATH12K_MAX_SOCS; chip_id++) { ++ for (chip_id = 0; chip_id < ag->num_chip; chip_id++) { + if (!rx_bufs_reaped[chip_id]) + continue; + +- src_ab = ab->ag->ab[chip_id]; +- rx_ring = &src_ab->dp.rx_refill_buf_ring; +- ath12k_dp_rx_bufs_replenish_ppeds(src_ab, rx_ring, +- rx_bufs_reaped[chip_id], +- src_ab->hw_params->hal_params->rx_buf_rbm); ++ src_ab = ag->ab[chip_id]; ++ ath12k_dp_rx_bufs_replenish_ppeds(src_ab, rx_bufs_reaped[chip_id], ++ &ab->ppeds_rx_idx[chip_id][0], arr); + } + + return; ++ ++err_h_alloc_failure: ++ for (chip_id = 0; chip_id < ag->num_chip; chip_id++) { ++ src_ab = ag->ab[chip_id]; ++ num_free_desc = 0; ++ for (i = 0; i < count; i++) ++ num_free_desc += ath12k_ppeds_free_rx_desc(arr, src_ab, i); ++ if (!src_ab->stats_disable) ++ src_ab->ppeds_stats.num_rx_desc_freed += num_free_desc; ++ } + } + + static +@@ -843,7 +856,27 @@ int ath12k_ppeds_attach(struct ath12k_ba + *abptr = ab; + ath12k_dbg(ab, ATH12K_DBG_PPE, "PPEDS attach success\n"); + ++ for (i = 0; i < ab->ag->num_chip; i++) { ++ ab->ppeds_rx_idx[i] = kzalloc((sizeof(u16) * PPE_DS_TXCMPL_DEF_BUDGET), ++ GFP_ATOMIC); ++ if (!ab->ppeds_rx_idx[i]) { ++ ath12k_err(ab, "Failed to alloc mem ppeds_rx_desc\n"); ++ goto err_ppeds_attach; ++ } ++ } ++ ++ ab->ppeds_rx_num_elem = PPE_DS_TXCMPL_DEF_BUDGET; ++ + return 0; ++ ++err_ppeds_attach: ++ ab->ppeds_rx_num_elem = 0; ++ for (i = i - 1; i >= 0; i--) { ++ kfree(ab->ppeds_rx_idx[i]); ++ ab->ppeds_rx_idx[i] = NULL; ++ } ++ ++ return -ENOMEM; + } + + int ath12k_ppeds_detach(struct ath12k_base *ab) +@@ -872,6 +905,14 @@ int ath12k_ppeds_detach(struct ath12k_ba + + ath12k_dbg(ab, ATH12K_DBG_PPE, "PPEDS detach success\n"); + ++ if (ab->ppeds_rx_num_elem) { ++ ab->ppeds_rx_num_elem = 0; ++ for (i = 0; i < ab->ag->num_chip; i++) { ++ kfree(ab->ppeds_rx_idx[i]); ++ ab->ppeds_rx_idx[i] = NULL; ++ } ++ } ++ + return 0; + } + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -1223,7 +1223,7 @@ struct ath12k_ppeds_stats { + u32 release_tx_single_cnt; + u32 release_rx_desc_cnt; + u32 num_rx_desc_freed; +- u32 num_rx_desc_reused; ++ u32 num_rx_desc_realloc; + }; + + struct ath12k_ppeds_napi { +@@ -1493,6 +1493,8 @@ struct ath12k_base { + u8 ppeds_int_mode_enabled; + u8 ppeds_stopped; + struct ath12k_ppeds_stats ppeds_stats; ++ u16 *ppeds_rx_idx[ATH12K_MAX_SOCS]; ++ u16 ppeds_rx_num_elem; + #endif + + int userpd_id; +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -2332,10 +2332,10 @@ static ssize_t ath12k_debugfs_dump_ppeds + ppeds_stats->tx_desc_freed); + len += scnprintf(buf + len, size - len, "fw2wbm_pkt_drops %u\n", + ppeds_stats->fw2wbm_pkt_drops); +- len += scnprintf(buf + len, size - len, "num_rx_desc_reused %u\n", +- ppeds_stats->num_rx_desc_reused); + len += scnprintf(buf + len, size - len, "num_rx_desc_freed %u\n", + ppeds_stats->num_rx_desc_freed); ++ len += scnprintf(buf + len, size - len, "num_rx_desc_realloc %u\n", ++ ppeds_stats->num_rx_desc_realloc); + + if (len > size) + len = size; diff --git a/feeds/ipq95xx/mac80211/patches/qca/825-wifi-ath12k-Add-mhi_soc_reset-in-PCI-remove-flow.patch b/feeds/ipq95xx/mac80211/patches/qca/825-wifi-ath12k-Add-mhi_soc_reset-in-PCI-remove-flow.patch new file mode 100644 index 000000000..41958685c --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/825-wifi-ath12k-Add-mhi_soc_reset-in-PCI-remove-flow.patch @@ -0,0 +1,244 @@ +From ef37fa5e8968d96db5d891b496bf2b80812aac97 Mon Sep 17 00:00:00 2001 +From: Aishwarya R +Date: Fri, 21 Jul 2023 19:10:44 +0530 +Subject: [PATCH] ath12k: Add mhi_soc_reset in PCI remove flow + +SOC_GLOBAL_RESET would be ignored if there is any pending +PCIe transaction. To handle all pending PCIe transactions +cleanly mhi host reset request needs to be done before calling +SOC_GLOBAL_RESET. mhi_soc_reset triggers a WDOG reset on +the target which will cleanly handle any pending PCIe transactions +and put the device in RDDM mode. After device enters in RDDM mode +SOC_GLOBAL_RESET can be called safely. + +previous sequence flow +power_down -> soc_global_reset + +current sequence will be +power_down -> mhi_soc_reset -> wdog_reset -> RDDM -> soc_global_reset + +Signed-off-by: Aishwarya R +--- + drivers/net/wireless/ath/ath12k/core.c | 1 + + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/mhi.c | 85 ++++++++++++++++---------- + drivers/net/wireless/ath/ath12k/mhi.h | 4 +- + drivers/net/wireless/ath/ath12k/pci.c | 10 +++ + 5 files changed, 68 insertions(+), 33 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c +index 2770a5c..5237c96 100644 +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -3502,6 +3502,7 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size, + timer_setup(&ab->rx_replenish_retry, ath12k_ce_rx_replenish_retry, 0); + init_completion(&ab->htc_suspend); + init_completion(&ab->wow.wakeup_completed); ++ init_completion(&ab->rddm_reset_done); + + ab->dev = dev; + ab->bus_params = *bus_params; +diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h +index 1f90866..4795bc4 100644 +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -1525,6 +1525,7 @@ struct ath12k_base { + + struct ath12k_internal_pci ipci; + u32 chwidth_num_peer_caps; ++ struct completion rddm_reset_done; + struct ath12k_dp_umac_reset dp_umac_reset; + + u32 *crash_info_address; +diff --git a/drivers/net/wireless/ath/ath12k/mhi.c b/drivers/net/wireless/ath/ath12k/mhi.c +index 8fabc92..424e704 100644 +--- a/drivers/net/wireless/ath/ath12k/mhi.c ++++ b/drivers/net/wireless/ath/ath12k/mhi.c +@@ -323,28 +323,67 @@ static char *ath12k_mhi_op_callback_to_str(enum mhi_callback reason) + } + } + ++static char *ath12k_mhi_state_to_str(enum ath12k_mhi_state mhi_state) ++{ ++ switch (mhi_state) { ++ case ATH12K_MHI_INIT: ++ return "INIT"; ++ case ATH12K_MHI_DEINIT: ++ return "DEINIT"; ++ case ATH12K_MHI_POWER_ON: ++ return "POWER_ON"; ++ case ATH12K_MHI_POWER_OFF: ++ return "POWER_OFF"; ++ case ATH12K_MHI_FORCE_POWER_OFF: ++ return "FORCE_POWER_OFF"; ++ case ATH12K_MHI_SUSPEND: ++ return "SUSPEND"; ++ case ATH12K_MHI_RESUME: ++ return "RESUME"; ++ case ATH12K_MHI_TRIGGER_RDDM: ++ return "TRIGGER_RDDM"; ++ case ATH12K_MHI_RDDM_DONE: ++ return "RDDM_DONE"; ++ case ATH12K_MHI_SOC_RESET: ++ return "SOC_RESET"; ++ default: ++ return "UNKNOWN"; ++ } ++}; ++ + static void ath12k_mhi_op_status_cb(struct mhi_controller *mhi_cntrl, + enum mhi_callback cb) + { + struct ath12k_base *ab = dev_get_drvdata(mhi_cntrl->cntrl_dev); ++ struct ath12k_pci *ab_pci = ath12k_pci_priv(ab); + +- ath12k_dbg(ab, ATH12K_DBG_BOOT, "mhi notify status reason %s\n", +- ath12k_mhi_op_callback_to_str(cb)); ++ ath12k_dbg(ab, ATH12K_DBG_BOOT, "mhi notify status reason %s mhi_state:%s (0x%lx)\n", ++ ath12k_mhi_op_callback_to_str(cb), ++ ath12k_mhi_state_to_str(ab_pci->mhi_state), ab_pci->mhi_state); + + switch (cb) { + case MHI_CB_SYS_ERROR: + ath12k_warn(ab, "firmware crashed: MHI_CB_SYS_ERROR\n"); + break; + case MHI_CB_EE_RDDM: ++ /* In-case of rddm for mhi soc reset */ ++ if(test_bit(ATH12K_MHI_SOC_RESET, &ab_pci->mhi_state)) { ++ ath12k_dbg(ab, ATH12K_DBG_BOOT, "Triggering RDDM from mhi soc reset\n"); ++ clear_bit(ATH12K_MHI_SOC_RESET, &ab_pci->mhi_state); ++ complete(&ab->rddm_reset_done); ++ return; ++ } ++ ++ /* In-case of rddm for fatal error and ab is registered. */ + if (!(test_bit(ATH12K_FLAG_UNREGISTERING, &ab->ag->dev_flags))) { + set_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags); + set_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags); + queue_work(ab->workqueue_aux, &ab->reset_work); +- } +- else { ++ ath12k_dbg(ab, ATH12K_DBG_BOOT, "Schedule SSR Recovery reset work queue\n"); ++ ath12k_hal_dump_srng_stats(ab); ++ } else { + BUG_ON(1); + } +- ath12k_hal_dump_srng_stats(ab); + break; + default: + break; +@@ -476,32 +515,6 @@ void ath12k_mhi_unregister(struct ath12k_pci *ab_pci) + mhi_free_controller(mhi_ctrl); + } + +-static char *ath12k_mhi_state_to_str(enum ath12k_mhi_state mhi_state) +-{ +- switch (mhi_state) { +- case ATH12K_MHI_INIT: +- return "INIT"; +- case ATH12K_MHI_DEINIT: +- return "DEINIT"; +- case ATH12K_MHI_POWER_ON: +- return "POWER_ON"; +- case ATH12K_MHI_POWER_OFF: +- return "POWER_OFF"; +- case ATH12K_MHI_FORCE_POWER_OFF: +- return "FORCE_POWER_OFF"; +- case ATH12K_MHI_SUSPEND: +- return "SUSPEND"; +- case ATH12K_MHI_RESUME: +- return "RESUME"; +- case ATH12K_MHI_TRIGGER_RDDM: +- return "TRIGGER_RDDM"; +- case ATH12K_MHI_RDDM_DONE: +- return "RDDM_DONE"; +- default: +- return "UNKNOWN"; +- } +-}; +- + static void ath12k_mhi_set_state_bit(struct ath12k_pci *ab_pci, + enum ath12k_mhi_state mhi_state) + { +@@ -535,6 +548,9 @@ static void ath12k_mhi_set_state_bit(struct ath12k_pci *ab_pci, + case ATH12K_MHI_RDDM_DONE: + set_bit(ATH12K_MHI_RDDM_DONE, &ab_pci->mhi_state); + break; ++ case ATH12K_MHI_SOC_RESET: ++ set_bit(ATH12K_MHI_SOC_RESET, &ab_pci->mhi_state); ++ break; + default: + ath12k_err(ab, "unhandled mhi state (%d)\n", mhi_state); + } +@@ -577,6 +593,8 @@ static int ath12k_mhi_check_state_bit(struct ath12k_pci *ab_pci, + break; + case ATH12K_MHI_RDDM_DONE: + return 0; ++ case ATH12K_MHI_SOC_RESET: ++ return 0; + default: + ath12k_err(ab, "unhandled mhi state: %s(%d)\n", + ath12k_mhi_state_to_str(mhi_state), mhi_state); +@@ -589,7 +607,7 @@ static int ath12k_mhi_check_state_bit(struct ath12k_pci *ab_pci, + return -EINVAL; + } + +-static int ath12k_mhi_set_state(struct ath12k_pci *ab_pci, ++int ath12k_mhi_set_state(struct ath12k_pci *ab_pci, + enum ath12k_mhi_state mhi_state) + { + struct ath12k_base *ab = ab_pci->ab; +@@ -632,6 +650,9 @@ static int ath12k_mhi_set_state(struct ath12k_pci *ab_pci, + break; + case ATH12K_MHI_RDDM_DONE: + break; ++ case ATH12K_MHI_SOC_RESET: ++ mhi_soc_reset(ab_pci->mhi_ctrl); ++ break; + default: + ath12k_err(ab, "unhandled MHI state (%d)\n", mhi_state); + ret = -EINVAL; +diff --git a/drivers/net/wireless/ath/ath12k/mhi.h b/drivers/net/wireless/ath/ath12k/mhi.h +index e20c4f8..68d96e3 100644 +--- a/drivers/net/wireless/ath/ath12k/mhi.h ++++ b/drivers/net/wireless/ath/ath12k/mhi.h +@@ -29,6 +29,7 @@ enum ath12k_mhi_state { + ATH12K_MHI_TRIGGER_RDDM, + ATH12K_MHI_RDDM, + ATH12K_MHI_RDDM_DONE, ++ ATH12K_MHI_SOC_RESET, + }; + + extern struct mhi_controller_config ath12k_mhi_config_qcn9274; +@@ -44,5 +45,6 @@ void ath12k_mhi_clear_vector(struct ath12k_base *ab); + void ath12k_mhi_suspend(struct ath12k_pci *ar_pci); + void ath12k_mhi_resume(struct ath12k_pci *ar_pci); + void ath12k_mhi_coredump(struct mhi_controller *mhi_ctrl, bool state); +- ++int ath12k_mhi_set_state(struct ath12k_pci *ab_pci, ++ enum ath12k_mhi_state mhi_state); + #endif +diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c +index fb8686a..91a4ce2 100644 +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -839,6 +839,16 @@ void ath12k_pci_power_down(struct ath12k_base *ab) + if (!(test_bit(ATH12K_FLAG_UNREGISTERING, &ab->dev_flags))) { + ath12k_qmi_free_target_mem_chunk(ab); + } ++ ++ ath12k_mhi_set_state(ab_pci, ATH12K_MHI_SOC_RESET); ++ if (!wait_for_completion_timeout(&ab->rddm_reset_done, msecs_to_jiffies(200))) { ++ ath12k_warn(ab, "failed to set RDDM mode\n"); ++ if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags)) { ++ ath12k_warn(ab, "failed to clear MHI SOC RESET as mhi already in rddm state due to recovery in progress, clearing it here\n"); ++ clear_bit(ATH12K_MHI_SOC_RESET, &ab_pci->mhi_state); ++ reinit_completion(&ab->rddm_reset_done); ++ } ++ } + /* restore aspm in case firmware bootup fails */ + ath12k_pci_aspm_restore(ab_pci); + +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/826-ath12k-fix-ath12k_mac_op_switch_vif_chanctx-mac-ops.patch b/feeds/ipq95xx/mac80211/patches/qca/826-ath12k-fix-ath12k_mac_op_switch_vif_chanctx-mac-ops.patch new file mode 100644 index 000000000..53956c019 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/826-ath12k-fix-ath12k_mac_op_switch_vif_chanctx-mac-ops.patch @@ -0,0 +1,145 @@ +From a9b495a4534ae0ccb780f4ff3638cdd718847b0e Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Wed, 26 Jul 2023 14:21:31 +0530 +Subject: [PATCH] ath12k: fix ath12k_mac_op_switch_vif_chanctx() mac ops + +If more than 1 link switches channel at near by same time such that CSA is +not completed on the first before it starts on later, then once the CSA is +completed on both, mac80211 sends all the channel contexts in one shot to the +driver via ath12k_mac_op_switch_vif_chanctx(). This is due to the single wiphy +architecture since all channel contexts are maintained under single wiphy. + +Hence there could be a possibility that in the passed channel contexts array, +there could be contexts belonging to different underlying radios. However, +currently there is an assumption that the passed array will have channel context +belonging to a single radio and hence only 1st member of the array is used to +get the underlying radio info. This leads to sending incorrect vdev ids to +firmware as well as stack corruption since now total number of elements in array +could be more than that a radio supports. + +Modify the ath12k_mac_op_switch_vif_chanctx() mac ops to get all the consecutive +contexts belonging to the same radio and further process it in a single shot. + +While at it, if channel is moved from one underlying radio to another, which is +currently not supported, handle it accordingly and return operation not supported +to upper layer. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath12k/mac.c | 92 +++++++++++++++++++++++---- + 1 file changed, 79 insertions(+), 13 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -12365,6 +12365,10 @@ ath12k_mac_process_update_vif_chan(struc + + lockdep_assert_held(&ar->conf_mutex); + ++ /* should not happen */ ++ if (WARN_ON(n_vifs > TARGET_NUM_VDEVS)) ++ return; ++ + if (ath12k_wmi_is_mvr_supported(ab)) + ath12k_mac_update_vif_chan_mvr(ar, vifs, n_vifs); + else +@@ -13332,36 +13336,82 @@ ath12k_mac_op_switch_vif_chanctx(struct + int n_vifs, + enum ieee80211_chanctx_switch_mode mode) + { +- struct ath12k *ar; ++ struct ath12k_hw *ah = hw->priv; ++ struct ath12k *curr_ar, *new_ar, *ar; ++ struct ieee80211_chanctx_conf *prev_ctx, *curr_ctx; ++ int i, ret = 0, idx; + +- /* TODO Swiching a vif between two radios require deleting of vdev ++ mutex_lock(&ah->conf_mutex); ++ ++ /* TODO Switching a vif between two radios require deleting of vdev + * in its current ar and creating a vdev and applying its cached params +- * to the new vdev in ar. +- * Currently only switching within same band allowed, also if ar's +- * which are in same band (5G LB/HB needs to be handled) ++ * to the new vdev in ar. So instead of returning error, handle it? + */ +- if (vifs->old_ctx->def.chan->band != vifs->new_ctx->def.chan->band) { +- WARN_ON(1); +- return -EINVAL; ++ for (i = 0; i < n_vifs; i++) { ++ if (vifs[i].old_ctx->def.chan->band != ++ vifs[i].new_ctx->def.chan->band) { ++ WARN_ON(1); ++ ret = -EINVAL; ++ break; ++ } ++ ++ curr_ar = ath12k_get_ar_by_ctx(hw, vifs[i].old_ctx); ++ new_ar = ath12k_get_ar_by_ctx(hw, vifs[i].new_ctx); ++ if (!curr_ar || !new_ar) { ++ ath12k_err(NULL, ++ "unable to determine device for the passed channel ctx"); ++ ath12k_err(NULL, ++ "Old freq %d MHz (device %s) to new freq %d MHz (device %s)\n", ++ vifs[i].old_ctx->def.chan->center_freq, ++ curr_ar ? "valid" : "invalid", ++ vifs[i].new_ctx->def.chan->center_freq, ++ new_ar ? "valid" : "invalid"); ++ ret = -EINVAL; ++ break; ++ } ++ ++ /* Switching a vif between two radios is not allowed */ ++ if (curr_ar != new_ar) { ++ ath12k_dbg(curr_ar->ab, ATH12K_DBG_MAC, ++ "mac chanctx switch to another radio not supported."); ++ ret = -EOPNOTSUPP; ++ break; ++ } + } + +- ar = ath12k_get_ar_by_ctx(hw, vifs->old_ctx); +- if (!ar) { +- ath12k_err(NULL, +- "unable to determine device for the passed channel ctx\n"); +- return -EINVAL; ++ if (ret) ++ goto unlock; ++ ++ prev_ctx = vifs[0].old_ctx; ++ idx = 0; ++ ++ for (i = 1; i < n_vifs; i++) { ++ curr_ctx = vifs[i].old_ctx; ++ ++ if (curr_ctx != prev_ctx) { ++ ar = ath12k_get_ar_by_ctx(hw, prev_ctx); ++ mutex_lock(&ar->conf_mutex); ++ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, ++ "mac chanctx switch n_vifs %d mode %d\n", ++ i - idx, mode); ++ ath12k_mac_process_update_vif_chan(ar, vifs + idx, i - idx); ++ mutex_unlock(&ar->conf_mutex); ++ prev_ctx = curr_ctx; ++ idx = i; ++ } + } + ++ ar = ath12k_get_ar_by_ctx(hw, prev_ctx); + mutex_lock(&ar->conf_mutex); +- + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, + "mac chanctx switch n_vifs %d mode %d\n", +- n_vifs, mode); +- ath12k_mac_process_update_vif_chan(ar, vifs, n_vifs); +- ++ i - idx, mode); ++ ath12k_mac_process_update_vif_chan(ar, vifs + idx, i - idx); + mutex_unlock(&ar->conf_mutex); + +- return 0; ++unlock: ++ mutex_unlock(&ah->conf_mutex); ++ return ret; + } + + int diff --git a/feeds/ipq95xx/mac80211/patches/qca/828-wifi-ath12k-Debug-enhancements-for-mode1-recovery.patch b/feeds/ipq95xx/mac80211/patches/qca/828-wifi-ath12k-Debug-enhancements-for-mode1-recovery.patch new file mode 100644 index 000000000..0fb68dfe3 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/828-wifi-ath12k-Debug-enhancements-for-mode1-recovery.patch @@ -0,0 +1,152 @@ +From cdacbf02c7dc1f38fd44931178bb01f01afd4980 Mon Sep 17 00:00:00 2001 +From: Manish Dharanenthiran +Date: Fri, 25 Aug 2023 21:39:57 +0530 +Subject: [PATCH] wifi: ath12k: Debug enhancements for mode1 recovery + +This patch adds changes for the following, + 1) Info debugs to update whenever a fallback has happened + from mode1 to mode0. + 2) debugfs value will display with what user has configured. + +Signed-off-by: Manish Dharanenthiran +--- + drivers/net/wireless/ath/ath12k/core.c | 12 +++++++----- + drivers/net/wireless/ath/ath12k/core.h | 3 ++- + drivers/net/wireless/ath/ath12k/debugfs.c | 15 ++++++++------- + 3 files changed, 17 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c +index bb34104..99740d4 100644 +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -3018,12 +3018,12 @@ static void ath12k_core_reset(struct work_struct *work) + default: + ag->recovery_mode = ATH12K_MLO_RECOVERY_MODE0; + } +- ath12k_dbg(ab, ATH12K_DBG_MODE1_RECOVERY, +- "mode:%d\n", ag->recovery_mode); + } + else { + ag->recovery_mode = ATH12K_MLO_RECOVERY_MODE0; + } ++ ath12k_info(ab, "Recovery is initiated with Mode%s\n", ++ (ag->recovery_mode == ATH12K_MLO_RECOVERY_MODE0 ? "0" : "1")); + + /* Sometimes the recovery will fail and then the next all recovery fail, + * this is to avoid infinite recovery since it can not recovery success. +@@ -3123,6 +3123,7 @@ static void ath12k_core_reset(struct work_struct *work) + */ + ag->recovery_mode = ATH12K_MLO_RECOVERY_MODE0; + } ++ ath12k_info(ab, "Recovery is falling back to Mode0 as one of the partner chip is already in recovery\n"); + } + } + +@@ -3132,6 +3133,7 @@ static void ath12k_core_reset(struct work_struct *work) + /* Fallback to Mode0 if umac reset/peer_cleanup is + * failed */ + ag->recovery_mode = ATH12K_MLO_RECOVERY_MODE0; ++ ath12k_info(ab, "Recovery is falling back to Mode0\n"); + } else { + /* wake queues here as ping should continue for + * legacy clients in non-asserted chipsets +@@ -3142,6 +3144,8 @@ static void ath12k_core_reset(struct work_struct *work) + continue; + + ieee80211_wake_queues(ah->hw); ++ ath12k_dbg(ab, ATH12K_DBG_MODE1_RECOVERY, ++ "Queues are started as umac reset is completed for partner chipset\n"); + } + } + } +@@ -3157,9 +3161,7 @@ static void ath12k_core_reset(struct work_struct *work) + */ + if (ag->recovery_mode == ATH12K_MLO_RECOVERY_MODE0 && + !test_bit(ATH12K_FLAG_RECOVERY, &partner_ab->dev_flags)) { +- ath12k_dbg(ab, ATH12K_DBG_MODE1_RECOVERY, +- "sending fw_hang cmd ar:%p\n", +- partner_ab->pdevs[0].ar); ++ ath12k_info(ab, "sending fw_hang cmd to partner chipset(s)\n"); + ath12k_wmi_force_fw_hang_cmd(partner_ab->pdevs[0].ar, + ATH12K_WMI_FW_HANG_ASSERT_TYPE, + ATH12K_WMI_FW_HANG_DELAY, true); +diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h +index 53074db..0248c32 100644 +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -850,6 +850,7 @@ enum ath12k_ap_ps_state { + enum ath12k_fw_recovery_option { + ATH12K_FW_RECOVERY_DISABLE = 0, + ATH12K_FW_RECOVERY_ENABLE_AUTO, /* Automatically recover after FW assert */ ++ ATH12K_FW_RECOVERY_ENABLE_MODE1_AUTO, /* Automatically recover after FW assert through Mode1 */ + /* Enable only recovery. Send MPD SSR WMI */ + /* command to unlink UserPD assert from RootPD */ + ATH12K_FW_RECOVERY_ENABLE_SSR_ONLY, +@@ -1463,7 +1464,7 @@ struct ath12k_base { + struct timer_list mon_reap_timer; + + struct completion htc_suspend; +- bool fw_recovery_support; ++ enum ath12k_fw_recovery_option fw_recovery_support; + + u32 fw_dbglog_param; + u64 fw_dbglog_val; +diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c +index 66cb19a..596c08f 100644 +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -1980,6 +1980,7 @@ static ssize_t ath12k_debug_write_fw_recovery(struct file *file, + struct ath12k_pdev *pdev; + struct ath12k_hw_group *ag; + unsigned int value; ++ enum wmi_fw_hang_recovery_mode_type recovery_mode; + int ret, radio_idx, radioup = 0; + int i; + +@@ -1988,8 +1989,8 @@ static ssize_t ath12k_debug_write_fw_recovery(struct file *file, + + if (value < ATH12K_FW_RECOVERY_DISABLE || + value > ATH12K_FW_RECOVERY_ENABLE_SSR_ONLY) { +- ath12k_warn(ab, "Please enter: 0 = Disable, 1 = Enable (auto recover)," +- "2 = Enable SSR only"); ++ ath12k_warn(ab, "Please enter: 0 = Disable, 1 = Enable (auto recover), " ++ "2 = Enable SSR Mode1, 3 = Enable SSR only"); + ret = -EINVAL; + goto exit; + } +@@ -1997,9 +1998,9 @@ static ssize_t ath12k_debug_write_fw_recovery(struct file *file, + ag = ab->ag; + + if (!value) +- value = ATH12K_WMI_DISABLE_FW_RECOVERY; ++ recovery_mode = ATH12K_WMI_DISABLE_FW_RECOVERY; + else +- value = (value == ATH12K_FW_RECOVERY_ENABLE_SSR_ONLY) ? ++ recovery_mode = (value == ATH12K_FW_RECOVERY_ENABLE_MODE1_AUTO) ? + ATH12K_WMI_FW_HANG_RECOVERY_MODE1 : + ATH12K_WMI_FW_HANG_RECOVERY_MODE0; + +@@ -2007,7 +2008,7 @@ static ssize_t ath12k_debug_write_fw_recovery(struct file *file, + for (i = 0; i < ag->num_chip; i++) { + ab = ag->ab[i]; + mutex_lock(&ab->core_lock); +- ab->fw_recovery_support = value ? true : false; ++ ab->fw_recovery_support = value; + mutex_unlock(&ab->core_lock); + + /* +@@ -2029,9 +2030,9 @@ static ssize_t ath12k_debug_write_fw_recovery(struct file *file, + + if (radioup) { + ret = ath12k_wmi_force_fw_hang_cmd(ar, +- value, ++ recovery_mode, + ATH12K_WMI_FW_HANG_DELAY, false); +- ath12k_info(ab, "setting FW assert mode [%d] ret [%d]\n", value, ret); ++ ath12k_info(ab, "setting FW assert mode [%d] ret [%d]\n", recovery_mode, ret); + } else + continue; + } +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/829-ath12k-add-support-for-low-latency-rate-cnt.patch b/feeds/ipq95xx/mac80211/patches/qca/829-ath12k-add-support-for-low-latency-rate-cnt.patch new file mode 100644 index 000000000..d7a2b0395 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/829-ath12k-add-support-for-low-latency-rate-cnt.patch @@ -0,0 +1,185 @@ +From 9fb98a1ae8bef46c0a346cd3afe333eb56b7f799 Mon Sep 17 00:00:00 2001 +From: Saleemuddin Shaik +Date: Thu, 17 Aug 2023 16:09:50 +0530 +Subject: [PATCH] ath12k: add support for low_latency_rate_cnt + +By accessing HTT_STATS_TX_PDEV_SAWF_RATE_STATS_TAG, +can able to view the values of low_latency_rate_cnt, + +When the service class contains delay bound rate parameters which +indicate low latency and we enable latency-based RA params then +the low_latency_rate_count will be incremented. + +commands: +root@OpenWrt:/# +echo 9 > /sys/kernel/debug/ath12k/qcn9274 hw2.0_0004:01:00.0/mac0/htt_stats_type + +root@OpenWrt:/# +cat /sys/kernel/debug/ath12k/qcn9274 hw2.0_0004:01:00.0/mac0/htt_stats + +output: +HTT_TX_PDEV_RATE_STATS_TLV: +mac_id = 0 +tx_ldpc = 95675 +ac_mu_mimo_tx_ldpc = 0 +ax_mu_mimo_tx_ldpc = 0 +ofdma_tx_ldpc = 0 +rts_cnt = 129847 +rts_success = 90133 +ack_rssi = 96 +Legacy CCK Rates: 1 Mbps: 0, 2 Mbps: 0, 5.5 Mbps: 0, 11 Mbps: 0 +Legacy OFDM Rates: 6 Mbps: 287158, 9 Mbps: 0, 12 Mbps: 0, 18 Mbps: 0 + 24 Mbps: 0, 36 Mbps: 0, 48 Mbps: 0, 54 Mbps: 0 +tx_mcs = 0:5212, 1:668, 2:751, 3:1016, 4:2729, 5:7208, 6:8332, 7:14312, 8:28652, 9:35729, 10:0, 11:0, +tx_mcs_ext = 0:0, 1:0, +ac_mu_mimo_tx_mcs = 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, +ac_mu_mimo_tx_mcs_ext = 0:0, 1:0, +ax_mu_mimo_tx_mcs = 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, +ax_mu_mimo_tx_mcs_ext = 0:0, 1:0, +ofdma_tx_mcs = 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, +ofdma_tx_mcs_ext = 0:0, 1:0, +tx_nss = 0:8394, 1:96215, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, +ac_mu_mimo_tx_nss = 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, +ax_mu_mimo_tx_nss = 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, +ofdma_tx_nss = 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, +tx_bw = 0:16781, 1:4202, 2:83626, 3:0, 4:0, +ac_mu_mimo_tx_bw = 0:0, 1:0, 2:0, 3:0, +ax_mu_mimo_tx_bw = 0:0, 1:0, 2:0, 3:0, +ofdma_tx_bw = 0:0, 1:0, 2:0, 3:0, +tx_stbc = 0:0, 1:0, 2:0, 3:0, 4:0, 5:19, 6:82, 7:69, 8:46, 9:47, 10:0, 11:0, +tx_pream = 0:287398, 1:0, 2:13271, 3:145690, 4:0, 5:0, 6:0, +HE LTF: 1x: 0, 2x: 0, 4x: 0 +tx_gi[0] = + -2:0,-1:0, 0:4965, 1:376, 2:265, 3:265, 4:545, 5:1228, 6:1461, 7:702, 8:1829, 9:1862, 10:0, 11:0, + 0:0, 1:0, +tx_gi[1] = + -2:0,-1:0, 0:247, 1:292, 2:486, 3:751, 4:2184, 5:5980, 6:6871, 7:13610, 8:26823, 9:33867, 10:0, 11:0, + 0:0, 1:0, +tx_gi[2] = + -2:0,-1:0, 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, + 0:0, 1:0, +tx_gi[3] = + -2:0,-1:0, 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, + 0:0, 1:0, +ac_mu_mimo_tx_gi[0] = + 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, + 0:0, 1:0, +ac_mu_mimo_tx_gi[1] = + 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, + 0:0, 1:0, +ac_mu_mimo_tx_gi[2] = + 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, + 0:0, 1:0, +ac_mu_mimo_tx_gi[3] = + 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, + 0:0, 1:0, +ax_mu_mimo_tx_gi[0] = + 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, + 0:0, 1:0, +ax_mu_mimo_tx_gi[1] = + 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, + 0:0, 1:0, +ax_mu_mimo_tx_gi[2] = + 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, + 0:0, 1:0, +ax_mu_mimo_tx_gi[3] = + 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, + 0:0, 1:0, +ofdma_tx_gi[0] = + 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, + 0:0, 1:0, +ofdma_tx_gi[1] = + 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, + 0:0, 1:0, +ofdma_tx_gi[2] = + 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, + 0:0, 1:0, +ofdma_tx_gi[3] = + 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, + 0:0, 1:0, +ofdma_tx_ru_size = 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, +tx_dcm = 0:0, 1:0, 2:0, 3:0, 4:0, +tx_su_punctured_mode = 0:0, 1:0, 2:0, 3:0, 4:0, +half_tx_bw = 0:0, 1:0, 2:0, 3:0, +quarter_tx_bw = 0:0, 1:0, 2:0, 3:0, +half_ac_mu_mimo_tx_bw = 0:0, 1:0, 2:0, 3:0, +quarter_ac_mu_mimo_tx_bw = 0:0, 1:0, 2:0, 3:0, +half_ax_mu_mimo_tx_bw = 0:0, 1:0, 2:0, 3:0, +quarter_ax_mu_mimo_tx_bw = 0:0, 1:0, 2:0, 3:0, +half_ofdma_tx_bw 0:0, 1:0, 2:0, 3:0, +quarter_ofdma_tx_bw = 0:0, 1:0, 2:0, 3:0, +ofdma_he_sig_b_mcs = 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, +11ax_trigger_type = 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, +11be_trigger_type = 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, +ax_su_embedded_trigger_data_ppdu_cnt = 0 +ax_su_embedded_trigger_data_ppdu_err_cnt = 0 +HTT_TX_PDEV_BE_RATE_STATS_TLV: +be_mu_mimo_tx_ldpc = 0 -2:0,-1:0,be_mu_mimo_tx_mcs = 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, 12:0, 13:0, 14:0, 15:0, +be_mu_mimo_tx_nss = 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, +be_mu_mimo_tx_bw = 0:0, 1:0, 2:0, 3:0, 4:0, +be_mu_mimo_tx_gi[0] = 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, 12:0, 13:0, 14:0, 15:0, +be_mu_mimo_tx_gi[1] = 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, 12:0, 13:0, 14:0, 15:0, +be_mu_mimo_tx_gi[2] = 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, 12:0, 13:0, 14:0, 15:0, +be_mu_mimo_tx_gi[3] = 0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, 12:0, 13:0, 14:0, 15:0, + +low_latency_rate_cnt = 0 +su_burst_rate_drop_cnt = 0 +su_burst_rate_drop_fail_cnt = 0 +PER_HISTOGRAM_STATS +Per_histogram_cnt: 0:85407, 1:1, 2:2, 3:47, 4:6, 5:7, 6:3, 7:16, 8:3, 9:3, 10:1, 11:8, 12:4, 13:4, 14:8, 15:6, 16:6, 17:4, 18:4, 19:2, 20:7, 21:2, 22:2, 23:2, 24:1, + 25:29, 26:3, 27:2, 28:4, 29:1, 30:4, 31:1, 32:2, 33:49, 34:0, 35:0, 36:2, 37:2, 38:1, 39:0, 40:3, 41:0, 42:1, 43:0, 44:1, 45:1, 46:3, 47:0, 48:1, 49:0, + 50:236, 51:1, 52:0, 53:0, 54:2, 55:1, 56:0, 57:0, 58:0, 59:1, 60:3, 61:2, 62:1, 63:0, 64:0, 65:2, 66:32, 67:0, 68:2, 69:2, 70:0, 71:0, 72:0, 73:1, 74:0, + 75:20, 76:0, 77:0, 78:0, 79:0, 80:0, 81:0, 82:0, 83:1, 84:0, 85:0, 86:0, 87:0, 88:1, 89:0, 90:1, 91:0, 92:0, 93:0, 94:1, 95:1, 96:2, 97:1, 98:0, 99:0, 100:18629, +HTT_TX_PDEV_PPDU_DUR_STATS_TLV: +pdev_up_time_us_low = 1750458097 +pdev_up_time_us_high = 4 +tx_success_time_us_low = 82403051 +tx_success_time_us_high = 0 +tx_fail_time_us_low = 39273504 +tx_fail_time_us_high = 0 +tx_ppdu_dur_hist_us_0 = 0-250 : 162412, 250-500 : 3165, 500-750 : 288, 750-1000 : 3756, 1000-1250 : 145, 1250-1500 : 209, 1500-1750 : 241, 1750-2000 : 2516, +tx_ppdu_dur_hist_us_1 = 2000-2250 : 204, 2250-2500 : 0, 2500-2750 : 0, 2750-3000 : 0, 3000-3250 : 0, 3250-3500 : 0, 3500-3750 : 0, 3750-4000 : 0, + +Signed-off-by: Saleemuddin Shaik +--- + drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c | 9 +++++++++ + drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h | 3 +++ + 2 files changed, 12 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c +index b76865d..10c19c8 100644 +--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c +@@ -8088,6 +8088,15 @@ static inline void htt_print_histogram_stats_tlv(const void *tag_buf, + u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; + char data[HTT_HISTOGRAM_STATS_LEN] = {0}; + ++ len += scnprintf(buf + len, buf_len - len, "low_latency_rate_cnt = %u\n", ++ htt_stats_buf->low_latency_rate_cnt); ++ ++ len += scnprintf(buf + len, buf_len - len, "su_burst_rate_drop_cnt = %u\n", ++ htt_stats_buf->su_burst_rate_drop_cnt); ++ ++ len += scnprintf(buf + len, buf_len - len, "su_burst_rate_drop_fail_cnt = %u\n", ++ htt_stats_buf->su_burst_rate_drop_fail_cnt); ++ + len += scnprintf(buf + len, buf_len - len, "PER_HISTOGRAM_STATS\n"); + + index = 0; +diff --git a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h +index 5f8f216..62bfacf 100644 +--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h ++++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h +@@ -2556,6 +2556,9 @@ struct htt_tx_histogram_stats_tlv { + u32 rate_retry_mcs_drop_cnt; + u32 mcs_drop_rate[HTT_TX_PDEV_STATS_NUM_MCS_DROP_COUNTERS]; + u32 per_histogram_cnt[HTT_TX_PDEV_STATS_NUM_PER_COUNTERS]; ++ u32 low_latency_rate_cnt; ++ u32 su_burst_rate_drop_cnt; ++ u32 su_burst_rate_drop_fail_cnt; + }; + + struct htt_rx_pdev_ul_mumimo_trig_be_stats_tlv { +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/830-ath11k-Avoiding-memset-of-ppdu-info-for-next-skb.patch b/feeds/ipq95xx/mac80211/patches/qca/830-ath11k-Avoiding-memset-of-ppdu-info-for-next-skb.patch new file mode 100644 index 000000000..e79c882ba --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/830-ath11k-Avoiding-memset-of-ppdu-info-for-next-skb.patch @@ -0,0 +1,94 @@ +From 5b4a0de1356558f58df9c6a1f46c7c0ce2fadb03 Mon Sep 17 00:00:00 2001 +From: Yuvasree Sivasankaran +Date: Mon, 28 Aug 2023 14:48:41 +0530 +Subject: [PATCH] ath11k: Avoiding memset of ppdu-info for next skb + +While parsing mon status from skb, ppdu_info got memset with zero during +next skb fetch from queue or mon ring in case a single PPDU is more than +RX_BUFFER_SIZE. Because of this nss value got override for respective +ppdu and leads to warn_on in mac80211.Removed memset from next skb fetch +and added flag to track discontinued skb in case of fetch from skb. + +WARN_ON Reason: + +Rate marked as an HE rate but data is invalid: MCS: 0, NSS: 0 + +Below the call trace observed: + + Call trace: + ieee80211_rx_list+0x1d4/0xcc4 [mac80211] + ieee80211_rx_napi+0x58/0xcc [mac80211] + ath11k_dp_rx_deliver_msdu+0x358/0x3e4 [ath11k] + ath11k_dp_rx_mon_deliver.isra.27+0x470/0x4cc [ath11k] + ath11k_dp_rx_mon_dest_process+0x1cc/0x2bc [ath11k] + ath11k_dp_rx_process_mon_status+0x5ec/0xf90 [ath11k] + ath11k_dp_rx_process_mon_rings+0x40c/0x44c [ath11k] + ath11k_dp_service_srng+0x114/0x2c0 [ath11k] + ath11k_ahb_ext_grp_napi_poll+0x30/0xa0 [ath11k_ahb] + __napi_poll+0x30/0xa4 + net_rx_action+0x118/0x270 + __do_softirq+0x10c/0x244 + irq_exit+0x64/0xb4 + __handle_domain_irq+0x88/0xac + gic_handle_irq+0x74/0xbc + el1_irq+0xf0/0x1c0 + arch_cpu_idle+0x10/0x18 + do_idle+0x104/0x248 + cpu_startup_entry+0x20/0x64 + rest_init+0xd0/0xdc + arch_call_rest_init+0xc/0x14 + start_kernel+0x46c/0x4a4 + --[ end trace e754e9088a240857 ]--- + +Signed-off-by: Yuvasree Sivasankaran +--- + drivers/net/wireless/ath/ath11k/dp_rx.c | 6 ++++-- + drivers/net/wireless/ath/ath11k/hal_rx.h | 1 + + 2 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c +index d646521..cc835a0 100644 +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -6551,7 +6551,9 @@ int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id, + if (!num_buffs_reaped) + goto exit; + +- memset(ppdu_info, 0, sizeof(*ppdu_info)); ++ if (!ppdu_info->ppdu_continuation) ++ memset(ppdu_info, 0, sizeof(*ppdu_info)); ++ + ppdu_info->peer_id = HAL_INVALID_PEERID; + + while ((skb = __skb_dequeue(&skb_list))) { +@@ -6571,7 +6573,6 @@ int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id, + if (log_type != ATH11K_PKTLOG_TYPE_INVALID) + trace_ath11k_htt_rxdesc(ar, skb->data, log_type, rx_buf_sz); + +- memset(ppdu_info, 0, sizeof(struct hal_rx_mon_ppdu_info)); + hal_status = ath11k_hal_rx_parse_mon_status(ab, ppdu_info, skb); + + if (test_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags) && +@@ -6589,6 +6590,7 @@ int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id, + if ((ppdu_info->peer_id == HAL_INVALID_PEERID || + hal_status != HAL_RX_MON_STATUS_PPDU_DONE)) { + dev_kfree_skb_any(skb); ++ ppdu_info->ppdu_continuation = true; + continue; + } + rcu_read_lock(); +diff --git a/drivers/net/wireless/ath/ath11k/hal_rx.h b/drivers/net/wireless/ath/ath11k/hal_rx.h +index 3068285..84ed610 100644 +--- a/drivers/net/wireless/ath/ath11k/hal_rx.h ++++ b/drivers/net/wireless/ath/ath11k/hal_rx.h +@@ -227,6 +227,7 @@ struct hal_rx_mon_ppdu_info { + u8 userid; + u16 ampdu_id[HAL_MAX_UL_MU_USERS]; + u32 rx_antenna; ++ bool ppdu_continuation; + }; + + #define HAL_RX_UL_OFDMA_USER_INFO_V0_W0_VALID BIT(30) +-- +2.34.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/830-ath12k-fix-RU-puncturing-pattern-for-peers-after-CSA.patch b/feeds/ipq95xx/mac80211/patches/qca/830-ath12k-fix-RU-puncturing-pattern-for-peers-after-CSA.patch new file mode 100644 index 000000000..56fb2a480 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/830-ath12k-fix-RU-puncturing-pattern-for-peers-after-CSA.patch @@ -0,0 +1,99 @@ +From 461878d94724cdb16e815b3c50fee1339c1549e7 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Wed, 23 Aug 2023 12:36:19 +0530 +Subject: [PATCH] ath12k: fix RU puncturing pattern for peers after CSA + +If AP switches channel and with a valid puncturing pattern, the +peer at firmware level is not updated with the new value. This +leads to an issue where firmware still transmits the packets +in the whole bandwidth. + +Fix the issue by updating the ru puncturing bitmap of all EHT +capable peers by sending Peer Channel width Switch command. The +command has puncturing member and hence it can be leveraged. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath12k/mac.c | 59 +++++++++++++++++++++++++++ + 1 file changed, 59 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index 17bab9a42641..69a7ba4c451c 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -11612,6 +11612,63 @@ static int ath12k_mac_vdev_restart(struct ath12k_link_vif *arvif, + return ret; + } + ++static void ++ath12k_mac_update_peer_ru_punct_bitmap_iter(void *data, ++ struct ieee80211_sta *sta) ++{ ++ struct ath12k_link_vif *arvif = data; ++ struct ath12k *ar = arvif->ar; ++ struct ath12k_sta *ahsta = (struct ath12k_sta *)sta->drv_priv; ++ struct ath12k_link_sta *arsta; ++ struct ieee80211_link_sta *link_sta; ++ u8 link_id = arvif->link_id; ++ ++ if (ahsta->ahvif != arvif->ahvif) ++ return; ++ ++ /* Check if there is a link sta in the vif link */ ++ if (!(BIT(link_id) & ahsta->links_map)) ++ return; ++ ++ arsta = ahsta->link[link_id]; ++ link_sta = ath12k_get_link_sta(arsta); ++ if (!link_sta) { ++ ath12k_warn(ar->ab, "unable to access link sta in peer ru punct bitmap update\n"); ++ return; ++ } ++ ++ /* Puncturing in only applicable for EHT supported peers */ ++ if (!link_sta->he_cap.has_he || !link_sta->eht_cap.has_eht) ++ return; ++ ++ spin_lock_bh(&ar->data_lock); ++ /* RC_BW_CHANGED handler has infra already to send the bitmap. ++ * Hence we can leverage from the same flag ++ */ ++ arsta->changed |= IEEE80211_RC_BW_CHANGED; ++ spin_unlock_bh(&ar->data_lock); ++ ++ ieee80211_queue_work(ar->ah->hw, &arsta->update_wk); ++} ++ ++void ath12k_mac_update_ru_punct_bitmap(struct ath12k_link_vif *arvif, ++ struct ieee80211_chanctx_conf *old_ctx, ++ struct ieee80211_chanctx_conf *new_ctx) ++{ ++ struct ath12k *ar = arvif->ar; ++ struct ath12k_hw *ah = ar->ah; ++ ++ lockdep_assert_held(&ah->conf_mutex); ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ if (old_ctx->def.ru_punct_bitmap == new_ctx->def.ru_punct_bitmap) ++ return; ++ ++ ieee80211_iterate_stations_atomic(ah->hw, ++ ath12k_mac_update_peer_ru_punct_bitmap_iter, ++ arvif); ++} ++ + static int ath12k_vdev_restart_sequence(struct ath12k_link_vif *arvif, + struct ieee80211_chanctx_conf *new_ctx, + u64 vif_down_failed_map, +@@ -11655,6 +11712,8 @@ static int ath12k_vdev_restart_sequence(struct ath12k_link_vif *arvif, + } + + beacon_tmpl_setup: ++ ath12k_mac_update_ru_punct_bitmap(arvif, &old_chanctx, new_ctx); ++ + if (arvif->pending_csa_up) + return 0; + +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/831-ath12k-Add-API-to-print-q6-crash-dump.patch b/feeds/ipq95xx/mac80211/patches/qca/831-ath12k-Add-API-to-print-q6-crash-dump.patch new file mode 100644 index 000000000..da56dd739 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/831-ath12k-Add-API-to-print-q6-crash-dump.patch @@ -0,0 +1,144 @@ +From 6b9299dc69d7605d99876ecc3ccbea2b3c387567 Mon Sep 17 00:00:00 2001 +From: Narendhar Reddy +Date: Mon, 4 Sep 2023 16:29:35 +0530 +Subject: [PATCH] ath12k: Add API to print q6 crash dump + +Added the API to parse the q6 ramdump header from mhi and print +the ram dump info. This crash dump print will be called only for +pci interface. + +Signed-off-by: Narendhar Reddy +--- + drivers/net/wireless/ath/ath12k/coredump.c | 63 +++++++++++++++++++++- + drivers/net/wireless/ath/ath12k/coredump.h | 22 ++++++++ + 2 files changed, 84 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath12k/coredump.c b/drivers/net/wireless/ath/ath12k/coredump.c +index 4fa4482..b4f9605 100644 +--- a/drivers/net/wireless/ath/ath12k/coredump.c ++++ b/drivers/net/wireless/ath/ath12k/coredump.c +@@ -185,6 +185,66 @@ ath12k_coredump_get_dump_type(u32 mem_region_type) + + return dump_type; + } ++ ++static void ath12k_coredump_q6crash_reason(struct ath12k_base *ab) ++{ ++ int i = 0; ++ uint64_t coredump_offset = 0; ++ struct ath12k_pci *ar_pci = (struct ath12k_pci *)ab->drv_priv; ++ struct mhi_controller *mhi_ctrl = ar_pci->mhi_ctrl; ++ struct mhi_buf *mhi_buf; ++ struct image_info *rddm_image; ++ struct ath12k_coredump_q6ramdump_header *ramdump_header; ++ struct ath12k_coredump_q6ramdump_entry *ramdump_table; ++ char *msg = NULL; ++ struct pci_dev *pci_dev = ar_pci->pdev; ++ ++ rddm_image = mhi_ctrl->rddm_image; ++ mhi_buf = rddm_image->mhi_buf; ++ ++ ath12k_info(ab, "CRASHED - [DID:DOMAIN:BUS:SLOT] - %x:%04u:%02u:%02u\n", ++ pci_dev->device, pci_dev->bus->domain_nr, ++ pci_dev->bus->number, PCI_SLOT(pci_dev->devfn)); ++ ++ /* Get RDDM header size */ ++ ramdump_header = (struct ath12k_coredump_q6ramdump_header *)mhi_buf[0].buf; ++ ramdump_table = ramdump_header->ramdump_table; ++ coredump_offset = le32_to_cpu(ramdump_header->header_size); ++ ++ /* Traverse ramdump table to get coredump offset */ ++ while (i < MAX_RAMDUMP_TABLE_SIZE) { ++ if (!strncmp(ramdump_table->description, COREDUMP_DESC, ++ sizeof(COREDUMP_DESC)) || ++ !strncmp(ramdump_table->description, Q6_SFR_DESC, ++ sizeof(Q6_SFR_DESC))) { ++ break; ++ } ++ coredump_offset += le64_to_cpu(ramdump_table->size); ++ ramdump_table++; ++ i++; ++ } ++ ++ if (i == MAX_RAMDUMP_TABLE_SIZE) { ++ ath12k_warn(ab, "Cannot find '%s' entry in ramdump\n", ++ COREDUMP_DESC); ++ return; ++ } ++ ++ /* Locate coredump data from the ramdump segments */ ++ for (i = 0; i < rddm_image->entries; i++) { ++ if (coredump_offset < mhi_buf[i].len) { ++ msg = mhi_buf[i].buf + coredump_offset; ++ break; ++ } ++ ++ coredump_offset -= mhi_buf[i].len; ++ } ++ ++ if (msg && msg[0]) ++ ath12k_err(ab, "Fatal error received from wcss!\n%s\n", ++ msg); ++} ++ + void ath12k_coredump_download_rddm(struct ath12k_base *ab) + { + struct ath12k_pci *ar_pci = (struct ath12k_pci *)ab->drv_priv; +@@ -203,6 +263,7 @@ void ath12k_coredump_download_rddm(struct ath12k_base *ab) + state = true; + + ath12k_mhi_coredump(mhi_ctrl, state); ++ ath12k_coredump_q6crash_reason(ab); + + rddm_img = mhi_ctrl->rddm_image; + fw_img = mhi_ctrl->fbc_image; +@@ -448,4 +509,4 @@ send_resp: + ret = ath12k_qmi_m3_dump_upload_done_ind_send(ab, event_data->pdev_id, ret); + if (ret < 0) + ath12k_warn(ab, "qmi M3 dump upload done failed\n"); +-} ++} +\ No newline at end of file +diff --git a/drivers/net/wireless/ath/ath12k/coredump.h b/drivers/net/wireless/ath/ath12k/coredump.h +index 6d2f87a..59546cd 100644 +--- a/drivers/net/wireless/ath/ath12k/coredump.h ++++ b/drivers/net/wireless/ath/ath12k/coredump.h +@@ -9,6 +9,14 @@ + #define ATH12K_FW_CRASH_DUMP_VERSION 1 + #define ATH12K_FW_CRASH_DUMP_V2 2 + ++#define MAX_RAMDUMP_TABLE_SIZE 6 ++#define COREDUMP_DESC "Q6-COREDUMP" ++#define Q6_SFR_DESC "Q6-SFR" ++ ++#define DESC_STRING_SIZE 20 ++#define FILE_NAME_STRING_SIZE 20 ++ ++ + enum ath12k_fw_crash_dump_type { + ATH12K_FW_CRASH_PAGING_DATA, + ATH12K_FW_CRASH_RDDM_DATA, +@@ -81,6 +89,20 @@ struct ath12k_coredump_info { + struct ath12k_coredump_segment_info chip_seg_info[ATH12K_MAX_SOCS]; + }; + ++struct ath12k_coredump_q6ramdump_entry { ++ __le64 base_address; ++ __le64 actual_phys_address; ++ __le64 size; ++ char description[DESC_STRING_SIZE]; ++ char file_name[FILE_NAME_STRING_SIZE]; ++}; ++ ++struct ath12k_coredump_q6ramdump_header { ++ __le32 version; ++ __le32 header_size; ++ struct ath12k_coredump_q6ramdump_entry ramdump_table[MAX_RAMDUMP_TABLE_SIZE]; ++}; ++ + #ifdef CONFIG_WANT_DEV_COREDUMP + void ath12k_coredump_download_rddm(struct ath12k_base *ab); + void ath12k_coredump_build_inline(struct ath12k_base *ab, +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/831-wifi-ath12k-Add-partner-rx-replinish-support-in-wbm-.patch b/feeds/ipq95xx/mac80211/patches/qca/831-wifi-ath12k-Add-partner-rx-replinish-support-in-wbm-.patch new file mode 100644 index 000000000..25fd4c346 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/831-wifi-ath12k-Add-partner-rx-replinish-support-in-wbm-.patch @@ -0,0 +1,172 @@ +From 9457c42da9d9da067b7847c207df7a3e72d739d5 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Sat, 29 Jul 2023 20:12:18 +0530 +Subject: [PATCH] wifi: ath12k: Add partner rx replinish support in wbm error + path + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/dp_rx.c | 52 ++++++++++++++++++------- + 1 file changed, 37 insertions(+), 15 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -4827,27 +4827,27 @@ int ath12k_dp_rx_process_wbm_err(struct + struct napi_struct *napi, int budget) + { + struct ath12k *ar; ++ struct ath12k_base *src_ab; + struct ath12k_dp *dp = &ab->dp; + struct dp_rxdma_ring *rx_ring; + struct hal_rx_wbm_rel_info err_info; + struct hal_srng *srng; + struct sk_buff *msdu; +- struct sk_buff_head msdu_list; ++ struct sk_buff_head msdu_list, scatter_msdu_list; + struct ath12k_skb_rxcb *rxcb; + u32 *rx_desc; +- int mac_id; +- int num_buffs_reaped = 0; ++ int i, num_buffs_reaped[ATH12K_MAX_SOCS] = { 0 }; + int total_num_buffs_reaped = 0; + struct ath12k_rx_desc_info *desc_info; + struct ath12k_soc_dp_stats *soc_stats = &ab->soc_stats; + int ret; +- u8 src_link_id; ++ u8 hw_link_id; + char buf[64] = {0}; + + __skb_queue_head_init(&msdu_list); ++ __skb_queue_head_init(&scatter_msdu_list); + + srng = &ab->hal.srng_list[dp->rx_rel_ring.ring_id]; +- rx_ring = &dp->rx_refill_buf_ring; + + spin_lock_bh(&srng->lock); + +@@ -4882,17 +4882,19 @@ int ath12k_dp_rx_process_wbm_err(struct + + msdu = desc_info->skb; + desc_info->skb = NULL; ++ src_ab = ab->ag->ab[desc_info->chip_id]; ++ dp = &src_ab->dp; + + spin_lock_bh(&dp->rx_desc_lock); + list_move_tail(&desc_info->list, &dp->rx_desc_free_list); + spin_unlock_bh(&dp->rx_desc_lock); + + rxcb = ATH12K_SKB_RXCB(msdu); +- dma_unmap_single(ab->dev, rxcb->paddr, ++ dma_unmap_single(src_ab->dev, rxcb->paddr, + msdu->len + skb_tailroom(msdu), + DMA_FROM_DEVICE); + +- num_buffs_reaped++; ++ num_buffs_reaped[src_ab->chip_id]++; + total_num_buffs_reaped++; + + if (!err_info.continuation) +@@ -4906,13 +4908,45 @@ int ath12k_dp_rx_process_wbm_err(struct + + rxcb->err_rel_src = err_info.err_rel_src; + rxcb->err_code = err_info.err_code; +- rxcb->rx_desc = (struct hal_rx_desc *)msdu->data; +- +- __skb_queue_tail(&msdu_list, msdu); +- + rxcb->is_first_msdu = err_info.first_msdu; + rxcb->is_last_msdu = err_info.last_msdu; + rxcb->is_continuation = err_info.continuation; ++ rxcb->rx_desc = (struct hal_rx_desc *)msdu->data; ++ ++ if (!err_info.continuation) { ++ hw_link_id = ath12k_dp_rx_get_msdu_src_link(src_ab, msdu->data); ++ if (hw_link_id >= ATH12K_GROUP_MAX_RADIO) { ++ if (ath12k_debug_critical) { ++ ath12k_err(ab, "WBM Err: invalid hw link id %d\n", ++ hw_link_id); ++ ath12k_err_dump(ab, NULL, "WBM err desc: ", rx_desc, ++ sizeof(struct hal_wbm_release_ring_cc_rx), srng); ++ ath12k_err_dump(ab, NULL, "WBM Rx TLV: ", msdu->data, ++ sizeof(struct hal_rx_desc), srng); ++ dev_kfree_skb_any(msdu); ++ BUG_ON(1); ++ } else { ++ dev_kfree_skb_any(msdu); ++ } ++ continue; ++ } ++ ++ if (!skb_queue_empty(&scatter_msdu_list)) { ++ __skb_queue_tail(&scatter_msdu_list, msdu); ++ ++ skb_queue_walk(&scatter_msdu_list, msdu) { ++ rxcb = ATH12K_SKB_RXCB(msdu); ++ rxcb->hw_link_id = hw_link_id; ++ } ++ ++ skb_queue_splice_init(&scatter_msdu_list, &msdu_list); ++ } else { ++ rxcb->hw_link_id = hw_link_id; ++ __skb_queue_tail(&msdu_list, msdu); ++ } ++ } else { ++ __skb_queue_tail(&scatter_msdu_list, msdu); ++ } + } + + ath12k_hal_srng_access_end(ab, srng); +@@ -4922,20 +4956,35 @@ int ath12k_dp_rx_process_wbm_err(struct + if (!total_num_buffs_reaped) + goto done; + +- ath12k_dp_rx_bufs_replenish(ab, rx_ring, num_buffs_reaped, +- ab->hw_params->hal_params->rx_buf_rbm, true); ++ for (i = 0; i < ab->ag->num_chip; i++) { ++ if (!num_buffs_reaped[i]) ++ continue; ++ ++ src_ab = ab->ag->ab[i]; ++ if (!src_ab) ++ continue; ++ ++ rx_ring = &src_ab->dp.rx_refill_buf_ring; ++ ++ ath12k_dp_rx_bufs_replenish(src_ab, rx_ring, num_buffs_reaped[i], ++ src_ab->hw_params->hal_params->rx_buf_rbm, true); ++ } + + rcu_read_lock(); + while ((msdu = __skb_dequeue(&msdu_list)) != NULL) { + +- src_link_id = ath12k_dp_rx_get_msdu_src_link(ab, msdu->data); +- if (src_link_id < ATH12K_GROUP_MAX_RADIO) +- ar = rcu_dereference(ab->ag->hw_links[src_link_id]); +- else +- ar = NULL; ++ rxcb = ATH12K_SKB_RXCB(msdu); ++ hw_link_id = rxcb->hw_link_id; ++ ++ ar = rcu_dereference(ab->ag->hw_links[hw_link_id]); ++ if (!ar) { ++ dev_kfree_skb_any(msdu); ++ ath12k_warn(ab, "WBM Rx: invalid pdev for hw link id %d\n", ++ hw_link_id); ++ continue; ++ } + +- mac_id = ar ? ar->pdev_idx : 0; +- if (!ar || !rcu_dereference(ar->ab->pdevs_active[mac_id])) { ++ if (!rcu_dereference(ar->ab->pdevs_active[ar->pdev_idx])) { + dev_kfree_skb_any(msdu); + continue; + } +@@ -4945,8 +4994,6 @@ int ath12k_dp_rx_process_wbm_err(struct + continue; + } + +- rxcb = ATH12K_SKB_RXCB(msdu); +- + if (rxcb->err_rel_src < HAL_WBM_REL_SRC_MODULE_MAX) + soc_stats->rx_wbm_rel_source[rxcb->err_rel_src][ar->ab->chip_id]++; + diff --git a/feeds/ipq95xx/mac80211/patches/qca/832-001-wifi-nl80211-reg-add-no-EHT-regulatory-flag.patch b/feeds/ipq95xx/mac80211/patches/qca/832-001-wifi-nl80211-reg-add-no-EHT-regulatory-flag.patch new file mode 100644 index 000000000..4d00ae12b --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/832-001-wifi-nl80211-reg-add-no-EHT-regulatory-flag.patch @@ -0,0 +1,61 @@ +From e985af0076ffdb595f7be7ce6a3d4b32bc4f09fb Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Wed, 6 Sep 2023 09:31:25 +0530 +Subject: [PATCH] wifi: nl80211/reg: add no-EHT regulatory flag + +This just propagates to the channel flags, like no-HE and +similar other flags before it. + +Signed-off-by: Johannes Berg +Signed-off-by: Gregory Greenman +Signed-off-by: Aditya Kumar Singh +--- + include/uapi/linux/nl80211.h | 2 ++ + net/wireless/reg.c | 4 +++- + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h +index 13e41fa1e89b..0279307c47de 100644 +--- a/include/uapi/linux/nl80211.h ++++ b/include/uapi/linux/nl80211.h +@@ -4506,6 +4506,7 @@ enum nl80211_sched_scan_match_attr { + * @NL80211_RRF_NO_HE: HE operation not allowed + * @NL80211_RRF_NO_320MHZ: 320MHz operation not allowed + * @NL80211_RRF_PSD: channels has power spectral density value ++ * @NL80211_RRF_NO_EHT: EHT operation not allowed + */ + enum nl80211_reg_rule_flags { + NL80211_RRF_NO_OFDM = 1<<0, +@@ -4526,6 +4527,7 @@ enum nl80211_reg_rule_flags { + NL80211_RRF_NO_HE = 1<<17, + NL80211_RRF_NO_320MHZ = 1<<18, + NL80211_RRF_PSD = 1<<19, ++ NL80211_RRF_NO_EHT = 1<<20, + }; + + #define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR +diff --git a/net/wireless/reg.c b/net/wireless/reg.c +index 8148d63e20f8..2038e68d2c41 100644 +--- a/net/wireless/reg.c ++++ b/net/wireless/reg.c +@@ -5,7 +5,7 @@ + * Copyright 2008-2011 Luis R. Rodriguez + * Copyright 2013-2014 Intel Mobile Communications GmbH + * Copyright 2017 Intel Deutschland GmbH +- * Copyright (C) 2018 - 2022 Intel Corporation ++ * Copyright (C) 2018 - 2023 Intel Corporation + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above +@@ -1622,6 +1622,8 @@ static u32 map_regdom_flags(u32 rd_flags) + channel_flags |= IEEE80211_CHAN_NO_320MHZ; + if (rd_flags & NL80211_RRF_PSD) + channel_flags |= IEEE80211_CHAN_PSD; ++ if (rd_flags & NL80211_RRF_NO_EHT) ++ channel_flags |= IEEE80211_CHAN_NO_EHT; + return channel_flags; + } + +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/832-002-wifi-cfg80211-validate-AP-phy-operation-before-start.patch b/feeds/ipq95xx/mac80211/patches/qca/832-002-wifi-cfg80211-validate-AP-phy-operation-before-start.patch new file mode 100644 index 000000000..1fa5a7657 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/832-002-wifi-cfg80211-validate-AP-phy-operation-before-start.patch @@ -0,0 +1,58 @@ +From 37da99850dfda8ac23bb8e0f4a416cb4350f1754 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Wed, 6 Sep 2023 10:42:39 +0530 +Subject: [PATCH] wifi: cfg80211: validate AP phy operation before starting it + +Many regulatories can have HE/EHT Operation as not permitted. In such +cases, AP should not be allowed to start if it is using a channel +having the no operation flag set. However, currently there is no such +check in place. + +Fix this issue by validating such IEs sent during start AP against the +channel flags. + +Signed-off-by: Aditya Kumar Singh +--- + net/wireless/nl80211.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 3e6edeaeff63..917b228c4ead 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -6432,6 +6432,21 @@ static bool nl80211_valid_auth_type(struct cfg80211_registered_device *rdev, + } + } + ++static int nl80211_validate_ap_phy_operation(struct cfg80211_ap_settings *params) ++{ ++ struct ieee80211_channel *channel = params->chandef.chan; ++ ++ if ((params->he_cap || params->he_oper) && ++ (channel->flags & IEEE80211_CHAN_NO_HE)) ++ return -EOPNOTSUPP; ++ ++ if ((params->eht_cap || params->eht_oper) && ++ (channel->flags & IEEE80211_CHAN_NO_EHT)) ++ return -EOPNOTSUPP; ++ ++ return 0; ++} ++ + static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) + { + struct cfg80211_registered_device *rdev = info->user_ptr[0]; +@@ -6695,6 +6710,10 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) + if (err) + goto out_unlock; + ++ err = nl80211_validate_ap_phy_operation(params); ++ if (err) ++ goto out_unlock; ++ + if (info->attrs[NL80211_ATTR_AP_SETTINGS_FLAGS]) + params->flags = nla_get_u32( + info->attrs[NL80211_ATTR_AP_SETTINGS_FLAGS]); +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/832-003-wifi-ath12k-add-parsing-of-phy-bitmap-for-reg-rules.patch b/feeds/ipq95xx/mac80211/patches/qca/832-003-wifi-ath12k-add-parsing-of-phy-bitmap-for-reg-rules.patch new file mode 100644 index 000000000..5c9808a29 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/832-003-wifi-ath12k-add-parsing-of-phy-bitmap-for-reg-rules.patch @@ -0,0 +1,97 @@ +From 59dbb644d048926b534713b532bb149fe58455e6 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Wed, 6 Sep 2023 10:15:31 +0530 +Subject: [PATCH] wifi: ath12k: add parsing of phy bitmap for reg rules + +Certain regulatory domains could put restrictions on phy mode operation. +For example, in a few countries EHT Operation is not allowed. For such +countries, firmware indicates this via phy bitmap in each reg rule. + +Currently, there is no logic to parse this info and then pass it on to the +cfg80211/regulatory. + +Add parsing of this phy bitmap from the regulatory channel change event and +then accordingly map it to cfg80211/regulatory flags and pass it on to it. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath12k/reg.c | 14 ++++++++++++++ + drivers/net/wireless/ath/ath12k/reg.h | 11 +++++++++++ + drivers/net/wireless/ath/ath12k/wmi.c | 5 +++-- + 3 files changed, 28 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/reg.c b/drivers/net/wireless/ath/ath12k/reg.c +index 92c808628a27..5ac1b2f9c8bf 100644 +--- a/drivers/net/wireless/ath/ath12k/reg.c ++++ b/drivers/net/wireless/ath/ath12k/reg.c +@@ -580,6 +580,19 @@ static u32 ath12k_map_fw_reg_flags(u16 reg_flags) + return flags; + } + ++static u32 ath12k_map_fw_phy_flags(u32 phy_flags) ++{ ++ u32 flags = 0; ++ ++ if (phy_flags & ATH12K_REG_PHY_BITMAP_NO11AX) ++ flags |= NL80211_RRF_NO_HE; ++ ++ if (phy_flags & ATH12K_REG_PHY_BITMAP_NO11BE) ++ flags |= NL80211_RRF_NO_EHT; ++ ++ return flags; ++} ++ + /* TODO: API ath12k_reg_can_intersect() to handle whether two + * ieee80211_reg_rules can intersect or not based on their + * frequency range and power mode. */ +@@ -841,6 +854,7 @@ ath12k_reg_build_regd(struct ath12k_base *ab, + } + + flags |= ath12k_map_fw_reg_flags(reg_rule->flags); ++ flags |= ath12k_map_fw_phy_flags(reg_info->phybitmap); + + ath12k_reg_update_rule(new_regd->reg_rules + i, + reg_rule->start_freq, +diff --git a/drivers/net/wireless/ath/ath12k/reg.h b/drivers/net/wireless/ath/ath12k/reg.h +index 43edd7158077..9d9e4eb2e76e 100644 +--- a/drivers/net/wireless/ath/ath12k/reg.h ++++ b/drivers/net/wireless/ath/ath12k/reg.h +@@ -25,6 +25,17 @@ enum ath12k_dfs_region { + ATH12K_DFS_REG_UNDEF, + }; + ++/* Phybitmap supported in Firmware */ ++enum ath12k_reg_phy_bitmap { ++ ATH12K_REG_PHY_BITMAP_NO11A = 0x0001, ++ ATH12K_REG_PHY_BITMAP_NO11B = 0x0002, ++ ATH12K_REG_PHY_BITMAP_NO11G = 0x0004, ++ ATH12K_REG_PHY_BITMAP_NO11N = 0x0008, ++ ATH12K_REG_PHY_BITMAP_NO11AC = 0x0010, ++ ATH12K_REG_PHY_BITMAP_NO11AX = 0x0020, ++ ATH12K_REG_PHY_BITMAP_NO11BE = 0x0040, ++}; ++ + /* ATH12K Regulatory API's */ + void ath12k_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *request); +diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c +index 7be216a4d739..5cb1cb85b0b9 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -6687,10 +6687,11 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab, + ath12k_cc_status_to_str(reg_info->status_code)); + + ath12k_dbg(ab, ATH12K_DBG_WMI, +- "%s:cc_ext %s dsf %d BW: min_2g %d max_2g %d min_5g %d max_5g %d", ++ "%s:cc_ext %s dsf %d BW: min_2g %d max_2g %d min_5g %d max_5g %d phy_bitmap: 0x%x", + __func__, reg_info->alpha2, reg_info->dfs_region, + reg_info->min_bw_2g, reg_info->max_bw_2g, +- reg_info->min_bw_5g, reg_info->max_bw_5g); ++ reg_info->min_bw_5g, reg_info->max_bw_5g, ++ reg_info->phybitmap); + + ath12k_dbg(ab, ATH12K_DBG_WMI, + "num_2g_reg_rules %d num_5g_reg_rules %d", +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/832-ath12k-Wait-for-tx-activity-to-complete-before-delet.patch b/feeds/ipq95xx/mac80211/patches/qca/832-ath12k-Wait-for-tx-activity-to-complete-before-delet.patch new file mode 100644 index 000000000..967227eaa --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/832-ath12k-Wait-for-tx-activity-to-complete-before-delet.patch @@ -0,0 +1,144 @@ +From a99923e898ae759100df9724695f2ee40aa5eef4 Mon Sep 17 00:00:00 2001 +From: Balamurugan Mahalingam +Date: Thu, 7 Sep 2023 20:53:36 -0700 +Subject: [PATCH] ath12k: Wait for tx activity to complete before deleting + arvif + +Tx activity may be still in progress while arvif is getting deleted. +Wait for tx activity to stop before deleting arvif. + +Signed-off-by: Balamurugan Mahalingam +--- + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/mac.c | 22 +++++++++++++++++++++- + 2 files changed, 22 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -403,6 +403,7 @@ struct ath12k_link_vif { + + bool is_created; + bool is_started; ++ bool tx_in_progress; + bool is_up; + bool pending_up; + bool spectral_enabled; +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -4895,9 +4895,17 @@ static int ath12k_mac_vdev_delete(struct + struct ath12k_vif *ahvif = arvif->ahvif; + unsigned long time_left; + int ret = 0; ++ int count = 0; + + lockdep_assert_held(&ar->conf_mutex); + ++ WARN_ON(arvif->is_up); ++ ++ while (arvif->tx_in_progress && count <= 10) { ++ mdelay(20); ++ count++; ++ } ++ + reinit_completion(&ar->vdev_delete_done); + + ret = ath12k_wmi_vdev_delete(ar, arvif->vdev_id); +@@ -9224,17 +9232,21 @@ static void ath12k_mac_op_tx(struct ieee + arvif = ahvif->link[link]; + skb_cb->link_id = link; + +- if (!arvif || !arvif->ar) { ++ if (!arvif || !arvif->ar || ++ (!arvif->is_up && ahvif->vdev_type == WMI_VDEV_TYPE_AP)) { + ieee80211_free_txskb(hw, skb); + return; + } + ++ arvif->tx_in_progress = true; ++ + ar = arvif->ar; + + ah = ar->ah; + + if (unlikely(test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))) { + ieee80211_free_txskb(ah->hw, skb); ++ arvif->tx_in_progress = false; + return; + } + +@@ -9246,6 +9258,7 @@ static void ath12k_mac_op_tx(struct ieee + "failed fast tx due to limit check pdev idx %d\n", + ar->pdev_idx); + ieee80211_free_txskb(hw, skb); ++ arvif->tx_in_progress = false; + return; + } + +@@ -9255,6 +9268,7 @@ static void ath12k_mac_op_tx(struct ieee + "failed to transmit frame %d\n", ret); + ieee80211_free_txskb(hw, skb); + } ++ arvif->tx_in_progress = false; + return; + } + #endif +@@ -9287,6 +9301,7 @@ static void ath12k_mac_op_tx(struct ieee + mgmt_stats->tx_succ_cnt[frm_type]++; + spin_unlock_bh(&ar->data_lock); + } ++ arvif->tx_in_progress = false; + return; + } else + is_mcast = is_multicast_ether_addr(hdr->addr1); +@@ -9312,6 +9327,7 @@ static void ath12k_mac_op_tx(struct ieee + "failed due to limit check pdev idx %d\n", + ar->pdev_idx); + ieee80211_free_txskb(hw, skb); ++ arvif->tx_in_progress = false; + return; + } + +@@ -9343,6 +9359,7 @@ static void ath12k_mac_op_tx(struct ieee + tmp_arvif = ahvif->link[link_id]; + if (!(tmp_arvif && tmp_arvif->is_up)) + continue; ++ tmp_arvif->tx_in_progress = true; + + tmp_ar = tmp_arvif->ar; + +@@ -9354,6 +9371,7 @@ static void ath12k_mac_op_tx(struct ieee + ath12k_dbg(tmp_ar->ab, ATH12K_DBG_MAC, + "failed mcast tx due to limit check pdev idx %d\n", + tmp_ar->pdev_idx); ++ tmp_arvif->tx_in_progress = false; + continue; + } + +@@ -9362,6 +9380,7 @@ static void ath12k_mac_op_tx(struct ieee + ath12k_err(ar->ab, + "skb copy failure link_id 0x%X vdevid 0x%X\n", + link_id, tmp_arvif->vdev_id); ++ tmp_arvif->tx_in_progress = false; + continue; + } + +@@ -9387,6 +9406,7 @@ static void ath12k_mac_op_tx(struct ieee + ahvif->links_map); + WARN_ON_ONCE(1); + ieee80211_free_txskb(ah->hw, msdu_copied); ++ tmp_arvif->tx_in_progress = false; + continue; + } + +@@ -9415,9 +9435,11 @@ skip_peer_find: + + ieee80211_free_txskb(ah->hw, msdu_copied); + } ++ tmp_arvif->tx_in_progress = false; + } + ieee80211_free_txskb(ah->hw, skb); + } ++ arvif->tx_in_progress = false; + + } + diff --git a/feeds/ipq95xx/mac80211/patches/qca/833-wifi-ath12k-fix-use-of-uninitialized-variable-valid_.patch b/feeds/ipq95xx/mac80211/patches/qca/833-wifi-ath12k-fix-use-of-uninitialized-variable-valid_.patch new file mode 100644 index 000000000..633d9f1c8 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/833-wifi-ath12k-fix-use-of-uninitialized-variable-valid_.patch @@ -0,0 +1,37 @@ +From 5318c4ce35dbf9bb734be108855bbefb696989b0 Mon Sep 17 00:00:00 2001 +From: Hari Chandrakanthan +Date: Thu, 21 Sep 2023 17:37:55 +0530 +Subject: [PATCH] wifi: ath12k: fix use of uninitialized variable valid_link + +link_valid member of struct ieee80211_rx_status is set in ath12k_dp_mon_rx_deliver_msdu +only if peer is available. If peer is not available, link_valid may contain junk value. + +mac80211 consumes the link_valid member. + +Wrong value in link_valid can lead to improper handling +of rx skb in mac80211. + +Fix it by initializing the link_valid member. + +Signed-off-by: Hari Chandrakanthan +--- + drivers/net/wireless/ath/ath12k/dp_mon.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/dp_mon.c b/drivers/net/wireless/ath/ath12k/dp_mon.c +index 25a087105890..d490cac7a6f5 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_mon.c ++++ b/drivers/net/wireless/ath/ath12k/dp_mon.c +@@ -2175,6 +2175,9 @@ static void ath12k_dp_mon_rx_deliver_msdu(struct ath12k *ar, struct napi_struct + + if (!(status->flag & RX_FLAG_ONLY_MONITOR)) + decap = ppduinfo->cmn_mpdu_info.mon_mpdu[mpdu_idx].msdu_info[0].decap_format; ++ ++ status->link_valid = 0; ++ + spin_lock_bh(&ar->ab->base_lock); + peer = ath12k_dp_rx_h_find_peer(ar->ab, msdu, rx_info); + if (peer && peer->sta) { +-- +2.7.4 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/834-0001-wifi-cfg80211-export-DFS-CAC-usable-state-helper-fun.patch b/feeds/ipq95xx/mac80211/patches/qca/834-0001-wifi-cfg80211-export-DFS-CAC-usable-state-helper-fun.patch new file mode 100644 index 000000000..a3054a632 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/834-0001-wifi-cfg80211-export-DFS-CAC-usable-state-helper-fun.patch @@ -0,0 +1,86 @@ +From b54811f0c58e978aa7ec17e0efc93299b2b12c3e Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Thu, 14 Sep 2023 11:42:38 +0530 +Subject: [PATCH 1/2] wifi: cfg80211: export DFS CAC usable state helper + function + +cfg80211 has cfg80211_chandef_dfs_usable() function to know whether at +least one channel in the chandef is in usable state or not. + +Make the above function visible to drivers by exporting its symbol +to global list of kernel symbols. + +Lower level drivers can make use of this function to be aware +if CAC is required on the given chandef. For example drivers which +maintains the CAC state internally can make use of this. + +Signed-off-by: Aditya Kumar Singh +--- + include/net/cfg80211.h | 13 +++++++++++++ + net/wireless/chan.c | 1 + + net/wireless/core.h | 13 ------------- + 3 files changed, 14 insertions(+), 13 deletions(-) + +diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h +index 613ba16b9219..9dcb5487ea88 100644 +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -1070,6 +1070,19 @@ ieee80211_chandef_rate_flags(struct cfg80211_chan_def *chandef) + return ieee80211_chanwidth_rate_flags(chandef->width); + } + ++/** ++ * cfg80211_chandef_dfs_usable - checks if chandef is DFS usable ++ * @wiphy: the wiphy to validate against ++ * @chandef: the channel definition to check ++ * ++ * Checks if chandef is usable and we can/need start CAC on such channel. ++ * ++ * Return: true if all channels available and at least ++ * one channel requires CAC (NL80211_DFS_USABLE) ++ */ ++bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy, ++ const struct cfg80211_chan_def *chandef); ++ + /** + * cfg80211_chandef_dfs_cac_time - get maximum dfs cac time traversing + * through the entire channel width +diff --git a/net/wireless/chan.c b/net/wireless/chan.c +index d048d1fd98ce..3ecc646d9d67 100644 +--- a/net/wireless/chan.c ++++ b/net/wireless/chan.c +@@ -819,6 +819,7 @@ bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy, + + return (r1 + r2 > 0); + } ++EXPORT_SYMBOL(cfg80211_chandef_dfs_usable); + + /* + * Checks if center frequency of chan falls with in the bandwidth +diff --git a/net/wireless/core.h b/net/wireless/core.h +index d13eec4b87c0..72d8e4a6ccd5 100644 +--- a/net/wireless/core.h ++++ b/net/wireless/core.h +@@ -461,19 +461,6 @@ int cfg80211_scan(struct cfg80211_registered_device *rdev); + + extern struct work_struct cfg80211_disconnect_work; + +-/** +- * cfg80211_chandef_dfs_usable - checks if chandef is DFS usable +- * @wiphy: the wiphy to validate against +- * @chandef: the channel definition to check +- * +- * Checks if chandef is usable and we can/need start CAC on such channel. +- * +- * Return: true if all channels available and at least +- * one channel requires CAC (NL80211_DFS_USABLE) +- */ +-bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy, +- const struct cfg80211_chan_def *chandef); +- + void cfg80211_set_dfs_state(struct wiphy *wiphy, + const struct cfg80211_chan_def *chandef, + enum nl80211_dfs_state dfs_state); +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/834-0002-wifi-ath12k-fix-CAC-running-state-during-virtual-int.patch b/feeds/ipq95xx/mac80211/patches/qca/834-0002-wifi-ath12k-fix-CAC-running-state-during-virtual-int.patch new file mode 100644 index 000000000..284c484cc --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/834-0002-wifi-ath12k-fix-CAC-running-state-during-virtual-int.patch @@ -0,0 +1,80 @@ +From d39a4802d10f3a154e9ee4b49679fb426e940daf Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Thu, 14 Sep 2023 11:44:31 +0530 +Subject: [PATCH 2/2] wifi: ath12k: fix CAC running state during virtual + interface start + +Currently channel definition's primary channel's DFS CAC time +as well as primary channel's state i.e usable are used to set +the CAC_RUNNING flag for the ath12k radio structure. However, +this is wrong since certain channel definition are possbile +where primary channel may not be a DFS channel but, secondary +channel is a DFS channel. For example - channel 36 with 160 MHz +bandwidth. +In such cases, the flag will not be set which is wrong. + +Fix this issue by using cfg80211_chandef_dfs_usable() function +from cfg80211 which return trues if at least one channel is in +usable state. + +While at it, modify the CAC running debug log message to print +the CAC time as well in milli-seconds. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath12k/mac.c | 19 +++++++++++-------- + 1 file changed, 11 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index be588800fd82..5eaab42031ca 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -5,6 +5,7 @@ + */ + + #include ++#include + #include + #include + #include +@@ -11376,6 +11377,7 @@ ath12k_mac_vdev_config_after_start(struct ath12k_link_vif *arvif, + struct ath12k *ar = arvif->ar; + struct ath12k_base *ab = ar->ab; + int ret; ++ unsigned int dfs_cac_time; + + lockdep_assert_held(&ar->conf_mutex); + +@@ -11392,20 +11394,21 @@ ath12k_mac_vdev_config_after_start(struct ath12k_link_vif *arvif, + &arvif->reg_tpc_info); + } + +- /* Enable CAC Flag in the driver by checking the channel DFS cac time, +- * i.e dfs_cac_ms value which will be valid only for radar channels +- * and state as NL80211_DFS_USABLE which indicates CAC needs to be ++ /* Enable CAC Flag in the driver by checking all sub-channel's DFS ++ * state as NL80211_DFS_USABLE which indicates CAC needs to be + * done before channel usage. This flags is used to drop rx packets. + * during CAC. + */ + /* TODO Set the flag for other interface types as required */ +- if (ahvif->vdev_type == WMI_VDEV_TYPE_AP && +- chandef->chan->dfs_cac_ms && +- chandef->chan->dfs_state == NL80211_DFS_USABLE) { ++ if (ahvif->vdev_type == WMI_VDEV_TYPE_AP && arvif->chanctx.radar_enabled && ++ cfg80211_chandef_dfs_usable(ar->ah->hw->wiphy, chandef)) { + set_bit(ATH12K_CAC_RUNNING, &ar->dev_flags); ++ dfs_cac_time = cfg80211_chandef_dfs_cac_time(ar->ah->hw->wiphy, ++ chandef, false); + ath12k_dbg(ab, ATH12K_DBG_MAC, +- "CAC Started in chan_freq %d for vdev %d\n", +- chandef->chan->center_freq, arvif->vdev_id); ++ "CAC (for %u ms) Started in center_freq %d center_freq1 %d for vdev %d\n", ++ dfs_cac_time, chandef->chan->center_freq, ++ chandef->center_freq1, arvif->vdev_id); + } + + ret = ath12k_mac_set_txbf_conf(arvif); +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/834-wifi-mac80211-change-BUG_ON-to-conditional-BUG_ON-in.patch b/feeds/ipq95xx/mac80211/patches/qca/834-wifi-mac80211-change-BUG_ON-to-conditional-BUG_ON-in.patch new file mode 100644 index 000000000..bf9fb20ec --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/834-wifi-mac80211-change-BUG_ON-to-conditional-BUG_ON-in.patch @@ -0,0 +1,61 @@ +From 8ad16ba799eba47eb487b3620cb1b188811507c6 Mon Sep 17 00:00:00 2001 +From: Hari Chandrakanthan +Date: Sun, 24 Sep 2023 12:51:32 +0530 +Subject: [PATCH] wifi: mac80211: change BUG_ON to conditional BUG_ON in ieee80211_rx_data_set_sta + +change BUG_ON to conditional BUG_ON in ieee80211_rx_data_set_sta +as the link_id < 0 case is hit very often. + +Signed-off-by: Hari Chandrakanthan +--- + net/mac80211/mlme.c | 5 +++++ + net/mac80211/rx.c | 10 +++++++--- + 2 files changed, 12 insertions(+), 3 deletions(-) + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 480b516af933..a64323edb3d1 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -66,6 +66,11 @@ module_param(beacon_loss_count, int, 0644); + MODULE_PARM_DESC(beacon_loss_count, + "Number of beacon intervals before we decide beacon was lost."); + ++int debug_param = 0; ++module_param(debug_param, int, 0644); ++MODULE_PARM_DESC(debug_param, ++ "Debug module param to debug link id < 0"); ++ + /* + * Time the connection can be idle before we probe + * it to see if we can still talk to the AP. +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index abbe4aa4606d..17836ee5324f 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -33,6 +33,8 @@ + #include "wme.h" + #include "rate.h" + ++extern int debug_param; ++ + static inline void ieee80211_rx_stats(struct net_device *dev, u32 len) + { + struct pcpu_sw_netstats *tstats = this_cpu_ptr(netdev_tstats(dev)); +@@ -4338,9 +4340,11 @@ static bool ieee80211_rx_data_set_sta(struct ieee80211_rx_data *rx, + } + + if (link_id < 0) { +- pr_err("link id %d sta addr : %pM", link_id, sta ? sta->addr : NULL); +- print_hex_dump(KERN_ERR, "skb_data : ", DUMP_PREFIX_ADDRESS, 16, 1, rx->skb->data, rx->skb->len, true); +- BUG_ON(1); ++ if (debug_param) { ++ pr_err("link id %d sta addr : %pM", link_id, sta ? sta->addr : NULL); ++ print_hex_dump(KERN_ERR, "skb_data : ", DUMP_PREFIX_ADDRESS, 16, 1, rx->skb->data, rx->skb->len, true); ++ BUG_ON(1); ++ } + rx->link = &rx->sdata->deflink; + } else if (!ieee80211_rx_data_set_link(rx, link_id)) + return false; +-- +2.7.4 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/835-wifi-ath12k-add-module-param-to-limit-tx-data-frames.patch b/feeds/ipq95xx/mac80211/patches/qca/835-wifi-ath12k-add-module-param-to-limit-tx-data-frames.patch new file mode 100644 index 000000000..e03227eeb --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/835-wifi-ath12k-add-module-param-to-limit-tx-data-frames.patch @@ -0,0 +1,60 @@ +From f68c3ef5e15c27d42eb3c7ad9f75ead7248e63e3 Mon Sep 17 00:00:00 2001 +From: Hari Chandrakanthan +Date: Thu, 28 Sep 2023 15:28:21 +0530 +Subject: [PATCH] wifi: ath12k: add module param to limit tx data frames + +Add two new module params dp_group_tx_limit and dp_pdev_tx_limit to limit +the number of tx data frames in the driver. + +Signed-off-by: Hari Chandrakanthan +--- + drivers/net/wireless/ath/ath12k/core.c | 8 ++++++++ + drivers/net/wireless/ath/ath12k/core.h | 2 ++ + drivers/net/wireless/ath/ath12k/mac.c | 4 ++-- + 3 files changed, 12 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -72,6 +72,14 @@ bool ath12k_debug_critical = false; + module_param_named(debug_critical, ath12k_debug_critical, bool, 0644); + MODULE_PARM_DESC(debug_critical, "Debug critical issue (0 - disable, 1 - enable)"); + ++unsigned int ath12k_dp_group_tx_limit = ATH12K_DP_GROUP_TX_LIMIT; ++module_param_named(dp_group_tx_limit, ath12k_dp_group_tx_limit, uint, 0444); ++MODULE_PARM_DESC(dp_group_tx_limit, "DP hw group tx limit"); ++ ++unsigned int ath12k_dp_pdev_tx_limit = ATH12K_DP_PDEV_TX_LIMIT; ++module_param_named(dp_pdev_tx_limit, ath12k_dp_pdev_tx_limit, uint, 0444); ++MODULE_PARM_DESC(dp_pdev_tx_limit, "DP pdev tx limit"); ++ + static DEFINE_MUTEX(ath12k_hw_lock); + static struct list_head ath12k_hw_groups = LIST_HEAD_INIT(ath12k_hw_groups); + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -50,6 +50,8 @@ + + extern unsigned int ath12k_frame_mode; + extern bool ath12k_debug_critical; ++extern unsigned int ath12k_dp_group_tx_limit; ++extern unsigned int ath12k_dp_pdev_tx_limit; + + #define ATH12K_MON_TIMER_INTERVAL 10 + #define ATH12K_RESET_TIMEOUT_HZ (180 * HZ) +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -9169,12 +9169,12 @@ bool ath12k_mac_tx_check_max_limit(struc + if (skb->protocol == cpu_to_be16(ETH_P_PAE)) + return false; + +- if (atomic_read(&ab->ag->num_dp_tx_pending) > ATH12K_DP_GROUP_TX_LIMIT) { ++ if (atomic_read(&ab->ag->num_dp_tx_pending) > ath12k_dp_group_tx_limit) { + ab->soc_stats.tx_err.group_threshold_limit++; + return true; + } + +- if (atomic_read(&ar->dp.num_tx_pending) > ATH12K_DP_PDEV_TX_LIMIT) { ++ if (atomic_read(&ar->dp.num_tx_pending) > ath12k_dp_pdev_tx_limit) { + ar->ab->soc_stats.tx_err.pdev_threshold_limit++; + return true; + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/835-wifi-cfg80211-fix-non-transmitting-BSS-profile-updat.patch b/feeds/ipq95xx/mac80211/patches/qca/835-wifi-cfg80211-fix-non-transmitting-BSS-profile-updat.patch new file mode 100644 index 000000000..b90751ba2 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/835-wifi-cfg80211-fix-non-transmitting-BSS-profile-updat.patch @@ -0,0 +1,207 @@ +From 537b8446e5d39d2b1fb2cc98da3de34f691e22cc Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Sat, 16 Sep 2023 14:04:23 +0530 +Subject: [PATCH] wifi: cfg80211: fix non-transmitting BSS profile update via + scan + +Currently, when creating BSS profile for a non-transmitting profile in a +multiple BSSID set, all IEs that are present in its Non-Tx profile are +copied and rest all IEs from transmitting BSS are copied. But later, +when again transmitting profile BSS is found, it tries to update the +all other non-transmitted profile BSS via function +cfg80211_update_notlisted_nontrans(). + +In this function except for SSID IE and MBSSID IE from transmitting BSS, +rest all IEs are directly copied into non-transmitting BSS IEs which is +wrong. This leads to updating wrong info in non-transmitting BSS IEs. + +In issue case, initially when non-transmitting BSS is formed, its Multi +Link Info IE is taken from its profile which is correct. But later, when +again transmitting beacon is found, it is updated with the Multi Link IE +of the transmitting profile. Due to this, the MLD address is modified +and this leads to association issue since now this non-transmitting BSS is +carrying the MLD address of its transmitting BSS which is wrong. + +Fix this issue by not copying the IEs blindly from then transmitting BSS. +Instead use the same logic, as in during forming the BSS. + +Signed-off-by: Aditya Kumar Singh +--- + net/wireless/scan.c | 131 +++++++++++++++++++++++++++++--------------- + 1 file changed, 88 insertions(+), 43 deletions(-) + +diff --git a/net/wireless/scan.c b/net/wireless/scan.c +index 9e03cf326238..f405c30e856c 100644 +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -2282,72 +2282,116 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy, + struct cfg80211_bss *nontrans_bss, + struct ieee80211_mgmt *mgmt, size_t len) + { +- u8 *ie, *new_ie, *pos; +- const struct element *nontrans_ssid; +- const u8 *trans_ssid, *mbssid; ++ struct cfg80211_bss_ies *new_ies; ++ const struct element *elem, *sub; ++ const struct cfg80211_bss_ies *old; ++ const u8 *mbssid_index_ie; ++ const u8 *trans_bssid = mgmt->bssid; + size_t ielen = len - offsetof(struct ieee80211_mgmt, + u.probe_resp.variable); ++ u8 nontrans_bssid[ETH_ALEN]; ++ u8 *ie, *new_ie, *profile; + size_t new_ie_len; +- struct cfg80211_bss_ies *new_ies; +- const struct cfg80211_bss_ies *old; +- size_t cpy_len; ++ bool found = false; + + lockdep_assert_held(&wiphy_to_rdev(wiphy)->bss_lock); + + ie = mgmt->u.probe_resp.variable; + +- new_ie_len = ielen; +- trans_ssid = cfg80211_find_ie(WLAN_EID_SSID, ie, ielen); +- if (!trans_ssid) +- return; +- new_ie_len -= trans_ssid[1]; +- mbssid = cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ie, ielen); +- /* +- * It's not valid to have the MBSSID element before SSID +- * ignore if that happens - the code below assumes it is +- * after (while copying things inbetween). +- */ +- if (!mbssid || mbssid < trans_ssid) ++ new_ie = kzalloc(IEEE80211_MAX_DATA_LEN, GFP_ATOMIC); ++ if (!new_ie) + return; +- new_ie_len -= mbssid[1]; + +- nontrans_ssid = ieee80211_bss_get_elem(nontrans_bss, WLAN_EID_SSID); +- if (!nontrans_ssid) ++ profile = kmalloc(ielen, GFP_ATOMIC); ++ if (!profile) { ++ kfree(new_ie); + return; ++ } + +- new_ie_len += nontrans_ssid->datalen; ++ /* parse the MBSSID IEs and find the profie we want to update */ ++ for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID, ie, ielen) { ++ if (elem->datalen < 4) ++ continue; ++ if (elem->data[0] < 1 || (int)elem->data[0] > 8) ++ continue; + +- /* generate new ie for nontrans BSS +- * 1. replace SSID with nontrans BSS' SSID +- * 2. skip MBSSID IE +- */ +- new_ie = kzalloc(new_ie_len, GFP_ATOMIC); +- if (!new_ie) +- return; ++ for_each_element(sub, elem->data + 1, elem->datalen - 1) { ++ u8 profile_len; ++ ++ if (sub->id != 0 || sub->datalen < 4) { ++ /* not a valid BSS profile */ ++ continue; ++ } ++ ++ if (sub->data[0] != WLAN_EID_NON_TX_BSSID_CAP || ++ sub->data[1] != 2) { ++ /* The first element within the Nontransmitted ++ * BSSID Profile is not the Nontransmitted ++ * BSSID Capability element. ++ */ ++ continue; ++ } ++ ++ memset(profile, 0, ielen); ++ profile_len = cfg80211_merge_profile(ie, ielen, ++ elem, ++ sub, ++ profile, ++ ielen); ++ ++ /* found a Nontransmitted BSSID Profile */ ++ mbssid_index_ie = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX, ++ profile, profile_len); ++ ++ if (!mbssid_index_ie || mbssid_index_ie[1] < 1 || ++ mbssid_index_ie[2] == 0 || ++ mbssid_index_ie[2] > 46) { ++ /* No valid Multiple BSSID-Index element */ ++ continue; ++ } ++ ++ /* bssid_index should match or else this is not our ++ * required non transmitting bss */ ++ if (mbssid_index_ie[2] != nontrans_bss->bssid_index) ++ continue; ++ ++ cfg80211_gen_new_bssid(trans_bssid, ++ elem->data[0], ++ mbssid_index_ie[2], ++ nontrans_bssid); ++ ++ /* compare bssid */ ++ if (ether_addr_equal(nontrans_bssid, nontrans_bss->bssid)) ++ continue; ++ ++ new_ie_len = cfg80211_gen_new_ie(ie, ielen, ++ profile, ++ profile_len, new_ie, ++ GFP_ATOMIC); ++ if (!new_ie_len) ++ continue; ++ ++ found = true; ++ break; ++ } ++ ++ if (found) ++ break; ++ } ++ ++ if (!found) ++ goto out_free; + + new_ies = kzalloc(sizeof(*new_ies) + new_ie_len, GFP_ATOMIC); + if (!new_ies) + goto out_free; + +- pos = new_ie; +- +- /* copy the nontransmitted SSID */ +- cpy_len = nontrans_ssid->datalen + 2; +- memcpy(pos, nontrans_ssid, cpy_len); +- pos += cpy_len; +- /* copy the IEs between SSID and MBSSID */ +- cpy_len = trans_ssid[1] + 2; +- memcpy(pos, (trans_ssid + cpy_len), (mbssid - (trans_ssid + cpy_len))); +- pos += (mbssid - (trans_ssid + cpy_len)); +- /* copy the IEs after MBSSID */ +- cpy_len = mbssid[1] + 2; +- memcpy(pos, mbssid + cpy_len, ((ie + ielen) - (mbssid + cpy_len))); +- + /* update ie */ + new_ies->len = new_ie_len; + new_ies->tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp); + new_ies->from_beacon = ieee80211_is_beacon(mgmt->frame_control); + memcpy(new_ies->data, new_ie, new_ie_len); ++ + if (ieee80211_is_probe_resp(mgmt->frame_control)) { + old = rcu_access_pointer(nontrans_bss->proberesp_ies); + rcu_assign_pointer(nontrans_bss->proberesp_ies, new_ies); +@@ -2363,6 +2407,7 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy, + } + + out_free: ++ kfree(profile); + kfree(new_ie); + } + +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/836-wifi-ath12k-fix-WMI-peer-kickout-sta-event-for-link-.patch b/feeds/ipq95xx/mac80211/patches/qca/836-wifi-ath12k-fix-WMI-peer-kickout-sta-event-for-link-.patch new file mode 100644 index 000000000..94fd67b25 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/836-wifi-ath12k-fix-WMI-peer-kickout-sta-event-for-link-.patch @@ -0,0 +1,63 @@ +From af91265035ff86c72d2c5e396ce2cc4f3f98f076 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Sun, 17 Sep 2023 12:49:05 +0530 +Subject: [PATCH] wifi: ath12k: fix WMI peer kickout sta event for link sta + +Currently WMI event WMI_PEER_STA_KICKOUT_EVENTID is handled only for +non-mlo peer. However, with MLO peer, it needs to handle and search +the ieee80211_sta with the given address by treating it as link address +instead of the normal interface address. But instead it uses non-mlo +handler and hence it fails to find a valid entry and the event is +simply dropped. This ultimately leads to client dis-connectivity issue +in case of MLO STA. + +Fix the above issue by using proper handler based on whether the peer +is a ML peer or not. + +Signed-off-by: Aditya Kumar Singh +--- + drivers/net/wireless/ath/ath12k/wmi.c | 20 ++++++++++++++++---- + 1 file changed, 16 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c +index 94c081214618..aaa377548f86 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -11260,6 +11260,7 @@ static void ath12k_peer_sta_kickout_event(struct ath12k_base *ab, struct sk_buff + struct ieee80211_sta *sta; + struct ath12k_peer *peer; + struct ath12k *ar; ++ u8 link_id; + + if (ath12k_pull_peer_sta_kickout_ev(ab, skb, &arg) != 0) { + ath12k_warn(ab, "failed to extract peer sta kickout event"); +@@ -11285,11 +11286,22 @@ static void ath12k_peer_sta_kickout_event(struct ath12k_base *ab, struct sk_buff + goto exit; + } + +- sta = ieee80211_find_sta_by_ifaddr(ar->ah->hw, +- arg.mac_addr, NULL); ++ if (peer->mlo) ++ sta = ieee80211_find_sta_by_link_addrs(ar->ah->hw, arg.mac_addr, ++ NULL, &link_id); ++ else ++ sta = ieee80211_find_sta_by_ifaddr(ar->ah->hw, ++ arg.mac_addr, NULL); + if (!sta) { +- ath12k_warn(ab, "Spurious quick kickout for STA %pM\n", +- arg.mac_addr); ++ ath12k_warn(ab, "Spurious quick kickout for %sSTA %pM\n", ++ peer->mlo ? "MLO " : "", arg.mac_addr); ++ goto exit; ++ } ++ ++ if (peer->mlo && peer->link_id != link_id) { ++ ath12k_warn(ab, ++ "Spurious quick kickout for MLO STA %pM with invalid link_id, peer: %d, sta: %d\n", ++ arg.mac_addr, peer->link_id, link_id); + goto exit; + } + +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/837-mac80211-feed-the-link_id-to-cfg80211_ch_switch_notify.patch b/feeds/ipq95xx/mac80211/patches/qca/837-mac80211-feed-the-link_id-to-cfg80211_ch_switch_notify.patch new file mode 100644 index 000000000..13363ad48 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/837-mac80211-feed-the-link_id-to-cfg80211_ch_switch_notify.patch @@ -0,0 +1,32 @@ +From 554d1c4cdfc261dc67c622ee7216a8fedaef4827 Mon Sep 17 00:00:00 2001 +From: Rathees Kumar R Chinannan +Date: Mon, 25 Sep 2023 14:19:59 +0530 +Subject: [PATCH] mac80211: feed the link_id to cfg80211_ch_switch_notify + +Currently, host hardcodes link_id value to 0 and sends to user space. +Instead of that use link id stored on ieee80211_link_data. + +This change fixes the warning with invalid link ID on cfg80211_ch_switch_notify +function. + +Signed-off-by: Rathees Kumar R Chinannan +--- + net/mac80211/mlme.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 480b516..5b5955b 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -1728,7 +1728,7 @@ static void ieee80211_chswitch_post_beacon(struct ieee80211_link_data *link) + return; + } + +- cfg80211_ch_switch_notify(sdata->dev, &link->reserved_chandef, 0); ++ cfg80211_ch_switch_notify(sdata->dev, &link->reserved_chandef, link->link_id); + } + + void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success) +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/837-wifi-ath12k-Drop-dynamic-fragmentation-msdu-in-Multi.patch b/feeds/ipq95xx/mac80211/patches/qca/837-wifi-ath12k-Drop-dynamic-fragmentation-msdu-in-Multi.patch new file mode 100644 index 000000000..82673e8af --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/837-wifi-ath12k-Drop-dynamic-fragmentation-msdu-in-Multi.patch @@ -0,0 +1,131 @@ +From 007787692b3b906b9ff917d7aed6a11683b5c2f1 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Tue, 26 Sep 2023 16:57:22 +0530 +Subject: [PATCH] wifi: ath12k: Drop dynamic fragmentation msdu in Multi-link + +In MLO, dynamic fragmentation only supported. In that scenario, primary +UMAC expect partner buffer but this support not yet added. So drop the msdu +instead of panic assert. + +In process rx error handler, once drop msdu detected the subsequent +msdu get dropped unintentionally due to previous drop flag retained +across the all msdu processing, which is wrong. So fix this issue by +reset the drop flag to false before processing each descriptor. + +Signed-off-by: Karthikeyan Periyasamy +--- + drivers/net/wireless/ath/ath12k/dp_rx.c | 38 ++++++++++++++----------- + 1 file changed, 22 insertions(+), 16 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -4353,6 +4353,7 @@ int ath12k_dp_rx_process_err(struct ath1 + { + u32 msdu_cookies[HAL_NUM_RX_MSDUS_PER_LINK_DESC]; + struct dp_link_desc_bank *link_desc_banks; ++ struct ath12k_base *src_ab; + enum hal_rx_buf_return_buf_manager rbm; + int tot_n_bufs_reaped, quota, ret, i; + struct dp_rxdma_ring *rx_ring; +@@ -4364,7 +4365,7 @@ int ath12k_dp_rx_process_err(struct ath1 + struct ath12k *ar = NULL; + dma_addr_t paddr; + u32 *desc; +- bool is_frag, drop = false; ++ bool is_frag, drop; + char buf[64] = {0}; + u8 hw_link_id; + +@@ -4373,7 +4374,6 @@ int ath12k_dp_rx_process_err(struct ath1 + + dp = &ab->dp; + reo_except = &dp->reo_except_ring; +- link_desc_banks = dp->link_desc_banks; + + srng = &ab->hal.srng_list[reo_except->ring_id]; + +@@ -4403,38 +4403,41 @@ int ath12k_dp_rx_process_err(struct ath1 + ar = rcu_dereference(ab->ag->hw_links[hw_link_id]); + else + ar = NULL; +- + rcu_read_unlock(); + +- if (!ar || ar->ab != ab) { +- ath12k_err(ab, "invalid src link id %d drop %d on chip id %d err process\n", +- hw_link_id, drop, ab->chip_id); ++ if (!ar) { ++ ath12k_err(ab, "invalid src link id %d on chip id %d err process\n", ++ hw_link_id, ab->chip_id); + + ath12k_err_dump(ab, NULL, "rx err desc: ", reo_desc, + sizeof(*reo_desc), srng); + BUG_ON(1); + } + ++ src_ab = ar->ab; ++ + /* Below case is added to handle data packet from un-associated clients. + * As it is expected that AST lookup will fail for + * un-associated station's data packets. + */ + if (u32_get_bits(reo_desc->info0, HAL_REO_DEST_RING_INFO0_BUFFER_TYPE) == + HAL_REO_DEST_RING_BUFFER_TYPE_MSDU) { +- ath12k_dp_h_msdu_buffer_type(ab, desc); ++ ath12k_dp_h_msdu_buffer_type(src_ab, desc); + continue; + } + ++ dp = &src_ab->dp; ++ link_desc_banks = dp->link_desc_banks; + link_desc_va = link_desc_banks[desc_bank].vaddr + + (paddr - link_desc_banks[desc_bank].paddr); + ath12k_hal_rx_msdu_link_info_get(link_desc_va, &num_msdus, msdu_cookies, + &rbm); + if (rbm != dp->idle_link_rbm_id && + rbm != HAL_RX_BUF_RBM_SW3_BM && +- rbm != ab->hw_params->hal_params->rx_buf_rbm) { ++ rbm != src_ab->hw_params->hal_params->rx_buf_rbm) { + ab->soc_stats.invalid_rbm++; + ath12k_warn(ab, "invalid return buffer manager %d\n", rbm); +- ath12k_dp_rx_link_desc_return(ab, desc, ++ ath12k_dp_rx_link_desc_return(src_ab, desc, + HAL_WBM_REL_BM_ACT_REL_MSDU); + continue; + } +@@ -4443,18 +4446,22 @@ int ath12k_dp_rx_process_err(struct ath1 + + /* Process only rx fragments with one msdu per link desc below, and drop + * msdu's indicated due to error reasons. ++ * Dynamic fragmentation not supported in Multi-link client, so drop. + */ +- if (!is_frag || num_msdus > 1) { ++ if (!is_frag || num_msdus > 1 || src_ab != ab) + drop = true; ++ else ++ drop = false; ++ ++ if (drop) { + /* Return the link desc back to wbm idle list */ +- ath12k_dp_rx_link_desc_return(ab, desc, ++ ath12k_dp_rx_link_desc_return(src_ab, desc, + HAL_WBM_REL_BM_ACT_PUT_IN_IDLE); ++ ++ ar->wmm_stats.total_wmm_rx_drop[ar->wmm_stats.rx_type] += num_msdus; + } + + for (i = 0; i < num_msdus; i++) { +- if (drop) +- ar->wmm_stats.total_wmm_rx_drop[ar->wmm_stats.rx_type]++; +- + if (!ath12k_dp_process_rx_err_buf(ar, desc, drop, + msdu_cookies[i])) + tot_n_bufs_reaped++; +@@ -4473,6 +4480,7 @@ exit: + + spin_unlock_bh(&srng->lock); + ++ dp = &ab->dp; + rx_ring = &dp->rx_refill_buf_ring; + + ath12k_dp_rx_bufs_replenish(ab, rx_ring, tot_n_bufs_reaped, diff --git a/feeds/ipq95xx/mac80211/patches/qca/837-wifi-ath12k-Fix-beacon-rx-for-sta-associated-to-non-Tx-va.patch b/feeds/ipq95xx/mac80211/patches/qca/837-wifi-ath12k-Fix-beacon-rx-for-sta-associated-to-non-Tx-va.patch new file mode 100644 index 000000000..85c2e3234 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/837-wifi-ath12k-Fix-beacon-rx-for-sta-associated-to-non-Tx-va.patch @@ -0,0 +1,54 @@ +From 6127c206af0c0a4734c0e8725d5e0be051b22353 Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Tue, 26 Sep 2023 18:44:06 +0530 +Subject: [PATCH] wifi: ath12k: Fix beacon rx for sta associated to non Tx AP + +Currently, When a station is associated to a non Tx AP, beacons are not +received frequently from FW. This results in missing events via beacons +such as channel switch leading to sta vif not switching to new channel as +the AP and causing kickout event from FW eventually. + +This was due to missing configuration of non Tx info during STA vdev up. +Fill the info such as Tx bssid, profile index and count for addressing this +issue. + +Signed-off-by: Sriram R +--- + drivers/net/wireless/ath/ath12k/mac.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index 0435af1..2757e1b 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -4026,6 +4026,13 @@ static void ath12k_bss_assoc(struct ath12k *ar, + params.vdev_id = arvif->vdev_id; + params.aid = ahvif->aid; + params.bssid = arvif->bssid; ++ ++ if (bss_conf->nontransmitted) { ++ params.profile_idx = bss_conf->bssid_index; ++ params.profile_count = BIT(bss_conf->bssid_indicator) - 1; ++ params.tx_bssid = bss_conf->transmitter_bssid; ++ } ++ + ret = ath12k_wmi_vdev_up(ar, ¶ms); + if (ret) { + ath12k_warn(ar->ab, "failed to set vdev %d up: %d\n", +@@ -11716,6 +11723,13 @@ beacon_tmpl_setup: + params.profile_idx = ahvif->vif->bss_conf.bssid_index; + params.profile_count = tx_arvif->nontransmitting_vif_count; + } ++ ++ if (ahvif->vif->type == NL80211_IFTYPE_STATION && link->nontransmitted) { ++ params.profile_idx = link->bssid_index; ++ params.profile_count = BIT(link->bssid_indicator) - 1; ++ params.tx_bssid = link->transmitter_bssid; ++ } ++ + rcu_read_unlock(); + ret = ath12k_wmi_vdev_up(arvif->ar, ¶ms); + if (ret) { +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/837-wifi-ath12k-Send-disassoc-to-MLD-sta-during-reco.patch b/feeds/ipq95xx/mac80211/patches/qca/837-wifi-ath12k-Send-disassoc-to-MLD-sta-during-reco.patch new file mode 100644 index 000000000..d9a3eeb2c --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/837-wifi-ath12k-Send-disassoc-to-MLD-sta-during-reco.patch @@ -0,0 +1,278 @@ +From 05a2f674d578d37c04441a1fd1c41032055d3363 Mon Sep 17 00:00:00 2001 +From: Manish Dharanenthiran +Date: Mon, 25 Sep 2023 15:29:43 +0530 +Subject: [PATCH] wifi: ath12k: Send disassoc to MLD sta during recovery + +During Mode1 recovery, legacy clients will be continued +for non-asserted chipset but MLD STA will not be served +as in mode1 we will do MLO teardown between all partner +links. So, after recovery it is taking longer than the +expected time to resume the data traffic. + +Fix this by disassociating all MLD station connected +by sending EVENT_LOW_ACK to upper layer with number of +packets set to maximum of '0xFFFF', thus making it to +reassociate once the recovery is completed. + +Signed-off-by: Manish Dharanenthiran +--- + drivers/net/wireless/ath/ath12k/core.c | 70 ++++++----- + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/mac.c | 158 ++++++++++++++++++++----- + drivers/net/wireless/ath/ath12k/mac.h | 2 +- + 4 files changed, 171 insertions(+), 60 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -2691,46 +2691,50 @@ int ath12k_mode1_recovery_reconfig(struc + } + + /* sta state part */ +- for (j = 0; j < ab->num_radios; j++) { +- pdev = &ab->pdevs[j]; +- ar = pdev->ar; +- +- if (!ar) +- continue; ++ for (i = 0; i < ag->num_chip; i++) { ++ partner_ab = ag->ab[i]; + +- mutex_lock(&ar->conf_mutex); ++ for (j = 0; j < partner_ab->num_radios; j++) { ++ pdev = &partner_ab->pdevs[j]; ++ ar = pdev->ar; + +- if (list_empty(&ar->arvifs)) { +- mutex_unlock(&ar->conf_mutex); +- continue; +- } ++ if (!ar) ++ continue; + +- list_for_each_entry_safe_reverse(arvif, tmp, &ar->arvifs, list) { +- ahvif = arvif->ahvif; ++ mutex_lock(&ar->conf_mutex); + +- if (!ahvif) ++ if (list_empty(&ar->arvifs)) { ++ mutex_unlock(&ar->conf_mutex); + continue; ++ } + +- /* unlock ar mutex here as the iterator will be called +- * within rcu lock. +- */ +- mutex_unlock(&ar->conf_mutex); +- ieee80211_iterate_stations_atomic(ar->ah->hw, +- ath12k_core_mode1_recovery_sta_list, +- arvif); +- mutex_lock(&ar->conf_mutex); +- for (key_idx = 0; key_idx < WMI_MAX_KEY_INDEX; key_idx++) { +- key = arvif->keys[key_idx]; +- if (key) { +- ath12k_dbg(ab, ATH12K_DBG_MODE1_RECOVERY, +- "key:%p cipher:%d idx:%d flags:%d\n", +- key, key->cipher, key->keyidx, key->flags); +- ret = ath12k_mac_set_key(arvif->ar, SET_KEY, arvif, NULL, key); ++ list_for_each_entry_safe_reverse(arvif, tmp, &ar->arvifs, list) { ++ ahvif = arvif->ahvif; ++ ++ if (!ahvif) ++ continue; ++ ++ /* unlock ar mutex here as the iterator will be called ++ * within rcu lock. ++ */ ++ mutex_unlock(&ar->conf_mutex); ++ ieee80211_iterate_stations_atomic(ar->ah->hw, ++ ath12k_core_mode1_recovery_sta_list, ++ arvif); ++ mutex_lock(&ar->conf_mutex); ++ for (key_idx = 0; key_idx < WMI_MAX_KEY_INDEX; key_idx++) { ++ key = arvif->keys[key_idx]; ++ if (key) { ++ ath12k_dbg(ab, ATH12K_DBG_MODE1_RECOVERY, ++ "key:%p cipher:%d idx:%d flags:%d\n", ++ key, key->cipher, key->keyidx, key->flags); ++ ret = ath12k_mac_set_key(arvif->ar, SET_KEY, arvif, NULL, key); ++ } + } + } ++ mutex_unlock(&ar->conf_mutex); ++ ar->ah->in_recovery = false; + } +- mutex_unlock(&ar->conf_mutex); +- ar->ah->in_recovery = false; + } + + for (i = 0; i < ag->num_hw; i++) { +@@ -2751,6 +2755,8 @@ int ath12k_mode1_recovery_reconfig(struc + } + } + ++ /* Send disassoc to MLD STA */ ++ ath12k_mac_partner_peer_cleanup(ab, true); + ab->recovery_start = false; + ag->recovery_mode = ATH12K_MLO_RECOVERY_MODE0; + return ret; +@@ -3122,7 +3128,7 @@ static void ath12k_core_reset(struct wor + + if (teardown) { + if (ath12k_core_trigger_umac_reset(ab) || +- ath12k_mac_partner_peer_cleanup(ab)) { ++ ath12k_mac_partner_peer_cleanup(ab, false)) { + /* Fallback to Mode0 if umac reset/peer_cleanup is + * failed */ + ag->recovery_mode = ATH12K_MLO_RECOVERY_MODE0; +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -708,6 +708,10 @@ struct ath12k_sta { + u16 ml_peer_id; + u8 assoc_link_id; + u8 num_peer; ++ /* Indicates whether disassoc is sent after recovery ++ * ONLY used currently in recovery case ++ */ ++ bool low_ack_sent; + }; + #define ATH12K_HALF_20MHZ_BW 10 + #define ATH12K_2G_MIN_CENTER 2412 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -1044,7 +1044,7 @@ static void ath12k_mac_dec_num_stations( + ar->num_stations--; + } + +-int ath12k_mac_partner_peer_cleanup(struct ath12k_base *ab) ++int ath12k_mac_partner_peer_cleanup(struct ath12k_base *ab, bool disassoc) + { + + struct ath12k_base *partner_ab; +@@ -1085,32 +1085,59 @@ int ath12k_mac_partner_peer_cleanup(stru + /* get arsta */ + sta = peer->sta; + ahsta = (struct ath12k_sta *)sta->drv_priv; +- arsta = ahsta->link[link_id]; + +- /* get arvif */ +- vif = peer->vif; +- ahvif = (struct ath12k_vif *)vif->drv_priv; +- arvif = ahvif->link[link_id]; +- cancel_work_sync(&arsta->update_wk); ++ if (!disassoc) { ++ arsta = ahsta->link[link_id]; + +- mutex_lock(&ar->conf_mutex); +- ret = ath12k_peer_delete_send(ar, arvif->vdev_id, arsta->addr); +- if (ret) { +- mutex_unlock(&ar->conf_mutex); +- ath12k_warn(ar->ab, +- "failed to delete peer vdev_id %d addr %pM ret %d\n", +- arvif->vdev_id, arsta->addr, ret); +- continue; +- } +- ret = ath12k_wait_for_peer_delete_done(ar, arvif->vdev_id, arsta->addr); +- if (ret) { ++ /* get arvif */ ++ vif = peer->vif; ++ ahvif = (struct ath12k_vif *)vif->drv_priv; ++ arvif = ahvif->link[link_id]; ++ cancel_work_sync(&arsta->update_wk); ++ ++ mutex_lock(&ar->conf_mutex); ++ ret = ath12k_peer_delete_send(ar, arvif->vdev_id, arsta->addr); ++ if (ret) { ++ mutex_unlock(&ar->conf_mutex); ++ ath12k_warn(ar->ab, ++ "failed to delete peer vdev_id %d addr %pM ret %d\n", ++ arvif->vdev_id, arsta->addr, ret); ++ continue; ++ } ++ ret = ath12k_wait_for_peer_delete_done(ar, arvif->vdev_id, arsta->addr); ++ if (ret) { ++ mutex_unlock(&ar->conf_mutex); ++ continue; ++ } ++ ++ ar->num_peers--; ++ arvif->num_stations--; ++ ath12k_mac_dec_num_stations(arvif, arsta); + mutex_unlock(&ar->conf_mutex); +- continue; ++ } else { ++ /* Send low ack to disassoc the MLD station ++ * Need to check on the sequence as FW has ++ * discarded the management packet at this ++ * sequence. ++ */ ++ if (sta->mlo && !ahsta->low_ack_sent) { ++ ath12k_dbg(ar->ab, ATH12K_DBG_MODE1_RECOVERY, ++ "sending low ack for/disassoc:%pM\n", ++ sta->addr); ++ /* set num of packets to maximum so ++ * that we distinguish in the hostapd ++ * to send disassoc irrespective of ++ * hostapd conf ++ */ ++ ieee80211_report_low_ack(sta, 0xFFFF); ++ /* Using this flag to avoid certain ++ * known warnings which will be ++ * triggerred when umac reset is ++ * happening ++ */ ++ ahsta->low_ack_sent = true; ++ } + } +- ar->num_peers--; +- arvif->num_stations--; +- ath12k_mac_dec_num_stations(arvif, arsta); +- mutex_unlock(&ar->conf_mutex); + } + } + } +@@ -7215,6 +7242,7 @@ static int ath12k_mac_handle_link_sta_st + if (ret) + ath12k_warn(ar->ab, "Failed to add station: %pM for VDEV: %d\n", + arsta->addr, arvif->vdev_id); ++ ahsta->low_ack_sent = false; + } else if ((old_state == IEEE80211_STA_NONE && + new_state == IEEE80211_STA_NOTEXIST)) { + ret = ath12k_mac_station_remove(ar, arvif, arsta); +@@ -7422,8 +7450,9 @@ int ath12k_mac_update_sta_state(struct i + ret = ath12k_mac_handle_link_sta_state(hw, arvif, arsta, + old_state, new_state); + if (ret) { +- ath12k_err(NULL, "unable to move link sta %d of sta %pM from state %d to %d", +- link_id, arsta->addr, old_state, new_state); ++ if (ret != -ESHUTDOWN) ++ ath12k_err(NULL, "unable to move link sta %d of sta %pM from state %d to %d", ++ link_id, arsta->addr, old_state, new_state); + + /* If FW recovery is ongoing, no need to move down sta states + * as FW will wake up with a clean slate. Hence we set the +@@ -9108,6 +9137,16 @@ static u8 ath12k_mac_get_tx_link(struct + link = ahsta->deflink.link_id; + + if (ieee80211_is_mgmt(hdr->frame_control)) { ++ /* For MLD STA post FW recovery, sending disassoc ++ * in other link apart from primary link results in ++ * disassoc packet getting dropped always, hence as ++ * a workaround until FW enables it post recovery ++ * this is needed to send disassoc always in primary ++ * link ++ */ ++ if (ieee80211_is_disassoc(hdr->frame_control)) ++ link = ahsta->deflink.link_id; ++ + /* Perform address conversion for ML STA Tx */ + bss_conf = rcu_dereference(vif->link_conf[link]); + link_sta = rcu_dereference(sta->link[link]); +--- a/drivers/net/wireless/ath/ath12k/mac.h ++++ b/drivers/net/wireless/ath/ath12k/mac.h +@@ -281,5 +281,5 @@ int ath12k_set_vdev_param_to_all_vifs(st + void ath12k_mac_reconfig_complete(struct ieee80211_hw *hw, + enum ieee80211_reconfig_type reconfig_type, + struct ath12k *asserted_radio); +-int ath12k_mac_partner_peer_cleanup(struct ath12k_base *ab); ++int ath12k_mac_partner_peer_cleanup(struct ath12k_base *ab, bool disassoc); + #endif diff --git a/feeds/ipq95xx/mac80211/patches/qca/837-wifi-ath12k-allow-primary-link-selection.patch b/feeds/ipq95xx/mac80211/patches/qca/837-wifi-ath12k-allow-primary-link-selection.patch new file mode 100644 index 000000000..b3f41ea5e --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/837-wifi-ath12k-allow-primary-link-selection.patch @@ -0,0 +1,340 @@ +From 86f1e6c92c43dff0b3305d96c766787146ae2d88 Mon Sep 17 00:00:00 2001 +From: Maharaja Kennadyrajan +Date: Fri, 18 Aug 2023 19:51:19 +0530 +Subject: [PATCH] ath12k: allow primary link selection based on HW params + +Signed-off-by: Maharaja Kennadyrajan +--- + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/dp.c | 4 +++- + drivers/net/wireless/ath/ath12k/hw.c | 4 ++++ + drivers/net/wireless/ath/ath12k/hw.h | 1 + + drivers/net/wireless/ath/ath12k/mac.c | 30 ++++++++++++++++---------- + drivers/net/wireless/ath/ath12k/peer.c | 3 --- + 6 files changed, 28 insertions(+), 15 deletions(-) + +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -490,8 +490,10 @@ struct ath12k_vif { + u8 last_scan_link; + #ifdef CPTCFG_ATH12K_DEBUGFS + struct dentry *debugfs_linkstats; ++ struct dentry *debugfs_primary_link; + #endif /* CPTCFG_ATH12K_DEBUGFS */ + bool mcast_to_ucast_en; ++ u8 primary_link_id; + }; + + struct ath12k_vif_iter { +@@ -714,6 +716,7 @@ struct ath12k_sta { + * ONLY used currently in recovery case + */ + bool low_ack_sent; ++ u8 primary_link_id; + }; + #define ATH12K_HALF_20MHZ_BW 10 + #define ATH12K_2G_MIN_CENTER 2412 +--- a/drivers/net/wireless/ath/ath12k/dp.c ++++ b/drivers/net/wireless/ath/ath12k/dp.c +@@ -124,11 +124,14 @@ int ath12k_dp_peer_setup(struct ath12k * + goto free_shash; + } + +- if (!peer->primary_link) { ++ if (peer->mlo && peer->link_id != arsta->ahsta->primary_link_id) { + ret = 0; ++ peer->primary_link = false; + goto free_shash; + } + ++ peer->primary_link = true; ++ + for (tid = 0; tid <= IEEE80211_NUM_TIDS; tid++) { + ret = ath12k_dp_rx_peer_tid_setup(ar, tid, 1, 0, HAL_PN_TYPE_NONE, peer); + if (ret) { +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -1506,6 +1506,7 @@ static struct ath12k_hw_params ath12k_hw + .send_platform_model = false, + .en_fwlog = true, + .support_umac_reset = false, ++ .is_plink_preferrable = true, + }, + { + .name = "wcn7850 hw2.0", +@@ -1576,6 +1577,7 @@ static struct ath12k_hw_params ath12k_hw + .send_platform_model = false, + .en_fwlog = true, + .support_umac_reset = false, ++ .is_plink_preferrable = true, + }, + { + .name = "qcn9274 hw2.0", +@@ -1655,6 +1657,7 @@ static struct ath12k_hw_params ath12k_hw + .en_fwlog = true, + .support_umac_reset = true, + .support_ce_manual_poll = true, ++ .is_plink_preferrable = true, + }, + { + .name = "ipq5332 hw1.0", +@@ -1737,6 +1740,7 @@ static struct ath12k_hw_params ath12k_hw + .en_fwlog = true, + .support_umac_reset = false, + .support_ce_manual_poll=true, ++ .is_plink_preferrable = false, + }, + }; + +--- a/drivers/net/wireless/ath/ath12k/hw.h ++++ b/drivers/net/wireless/ath/ath12k/hw.h +@@ -234,6 +234,7 @@ struct ath12k_hw_params { + bool support_ce_manual_poll; + const struct pmm_remap *pmm_remap; + bool support_umac_reset; ++ bool is_plink_preferrable; + }; + + /* BRINGUP: move to dp.h */ +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -3394,7 +3394,11 @@ static void ath12k_peer_assoc_h_mlo(stru + ml->enabled = true; + ml->assoc_link = arsta->is_assoc_link; + /* For now considering the primary umac based on assoc link */ +- ml->primary_umac = arsta->is_assoc_link; ++ if (arsta->link_id == ahsta->primary_link_id) ++ ml->primary_umac = true; ++ else ++ ml->primary_umac = false; ++ + ml->peer_id_valid = true; + ml->logical_link_idx_valid = true; + +@@ -3417,7 +3421,10 @@ static void ath12k_peer_assoc_h_mlo(stru + ml->partner_info[i].vdev_id = arvif->vdev_id; + ml->partner_info[i].hw_link_id = arvif->ar->pdev->hw_link_id; + ml->partner_info[i].assoc_link = arsta_p->is_assoc_link; +- ml->partner_info[i].primary_umac = arsta_p->is_assoc_link; ++ if (arsta_p->link_id == ahsta->primary_link_id) ++ ml->partner_info[i].primary_umac = true; ++ else ++ ml->partner_info[i].primary_umac = false; + ml->partner_info[i].logical_link_idx_valid = true; + ml->partner_info[i].logical_link_idx = arsta_p->link_idx; + ml->num_partner_links++; +@@ -7020,13 +7027,6 @@ static int ath12k_mac_station_add(struct + } + } + +- ret = ath12k_dp_peer_setup(ar, arvif, arsta); +- if (ret) { +- ath12k_warn(ab, "failed to setup dp for peer %pM on vdev %i (%d)\n", +- arsta->addr, arvif->vdev_id, ret); +- goto free_tx_stats; +- } +- + if (ab->hw_params->vdev_start_delay && + !arvif->is_started && + ahvif->vdev_type != WMI_VDEV_TYPE_AP) { +@@ -7262,6 +7262,11 @@ static int ath12k_mac_handle_link_sta_st + } else if (old_state == IEEE80211_STA_AUTH && + new_state == IEEE80211_STA_ASSOC) { + ++ ret = ath12k_dp_peer_setup(ar, arvif, arsta); ++ if (ret) ++ ath12k_warn(ar->ab, "failed to setup dp for peer %pM on vdev %i (%d)\n", ++ arsta->addr, arvif->vdev_id, ret); ++ + ath12k_dp_peer_default_route_setup(ar, arvif, arsta); + + if (vif->type == NL80211_IFTYPE_AP || +@@ -7439,6 +7444,7 @@ int ath12k_mac_update_sta_state(struct i + + ahsta->deflink.is_assoc_link = true; + ahsta->assoc_link_id = link_id; ++ ahsta->primary_link_id = link_id; + } + + if (new_state == IEEE80211_STA_NOTEXIST && old_state == IEEE80211_STA_NONE) { +@@ -7544,6 +7550,30 @@ static int ath12k_mac_op_change_sta_link + /* this op is expected only after initial sta insertion with default link */ + WARN_ON(ahsta->links_map == 0); + ++ /* TODO: update the primary selection logic for STA mode */ ++ if (vif->type != NL80211_IFTYPE_AP) ++ goto skip_primary_link_selection; ++ ++ if ((test_bit(ahvif->primary_link_id, &sta->valid_links))) { ++ arvif = ahvif->link[ahvif->primary_link_id]; ++ if (arvif->ar->ab->hw_params->is_plink_preferrable) { ++ ahsta->primary_link_id = ahvif->primary_link_id; ++ } else { ++ ahsta->primary_link_id = ahsta->assoc_link_id; ++ arvif = ahvif->link[ahsta->assoc_link_id]; ++ if (!arvif->ar->ab->hw_params->is_plink_preferrable) { ++ for_each_set_bit(link_id, &sta->valid_links, ++ IEEE80211_MLD_MAX_NUM_LINKS) { ++ if (link_id != ahsta->primary_link_id) { ++ ahsta->primary_link_id = link_id; ++ break; ++ } ++ } ++ } ++ } ++ } ++ ++skip_primary_link_selection: + for_each_set_bit(link_id, &new_links, IEEE80211_MLD_MAX_NUM_LINKS) { + if (ahsta->links_map & BIT(link_id)) + continue; +@@ -9135,9 +9165,9 @@ static u8 ath12k_mac_get_tx_link(struct + + /* enqueue eth data frames on assoc link */ + if (info_flags & IEEE80211_TX_CTL_HW_80211_ENCAP) +- return ahsta->assoc_link_id; ++ return ahsta->primary_link_id; + else if (ieee80211_is_data(hdr->frame_control)) +- return ahsta->assoc_link_id; ++ return ahsta->primary_link_id; + + /* 802.11 frame cases */ + if (link == IEEE80211_LINK_UNSPECIFIED) +--- a/drivers/net/wireless/ath/ath12k/peer.c ++++ b/drivers/net/wireless/ath/ath12k/peer.c +@@ -696,13 +696,10 @@ int ath12k_peer_create(struct ath12k *ar + /* Fill ML info into created peer */ + if (sta->mlo) { + peer->ml_peer_id = ahsta->ml_peer_id | ATH12K_ML_PEER_ID_VALID; +- /* the assoc link is considered primary for now */ +- peer->primary_link = arsta->is_assoc_link; + ether_addr_copy(peer->ml_addr, sta->addr); + peer->mlo = true; + } else { + peer->ml_peer_id = ATH12K_MLO_PEER_ID_INVALID; +- peer->primary_link = true; + peer->mlo = false; + } + } +--- a/drivers/net/wireless/ath/ath12k/debugfs.c ++++ b/drivers/net/wireless/ath/ath12k/debugfs.c +@@ -4773,6 +4773,52 @@ static const struct file_operations ath1 + .llseek = default_llseek, + }; + ++static ssize_t ath12k_write_primary_link(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k_vif *ahvif = file->private_data; ++ struct ath12k_hw *ah = ahvif->ah; ++ u8 primary_link; ++ ++ if (kstrtou8_from_user(user_buf, count, 0, &primary_link)) ++ return -EINVAL; ++ ++ if (primary_link >= IEEE80211_MLD_MAX_NUM_LINKS) ++ return -EINVAL; ++ ++ mutex_lock(&ah->conf_mutex); ++ ahvif->primary_link_id = primary_link; ++ mutex_unlock(&ah->conf_mutex); ++ ++ return count; ++} ++ ++static ssize_t ath12k_read_primary_link(struct file *file, ++ char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath12k_vif *ahvif = file->private_data; ++ struct ath12k_hw *ah = ahvif->ah; ++ int len = 0; ++ char buf[32] = {0}; ++ ++ mutex_lock(&ah->conf_mutex); ++ len = scnprintf(buf, sizeof(buf) - len, "Primary link_id: %d\n", ++ ahvif->primary_link_id); ++ mutex_unlock(&ah->conf_mutex); ++ ++ return simple_read_from_buffer(ubuf, count, ppos, buf, len); ++} ++ ++static const struct file_operations ath12k_fops_primary_link = { ++ .open = simple_open, ++ .write = ath12k_write_primary_link, ++ .read = ath12k_read_primary_link, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ + int ath12k_debugfs_add_interface(struct ath12k_link_vif *arvif) + { + struct ath12k_vif *ahvif = arvif->ahvif; +@@ -4860,6 +4906,32 @@ int ath12k_debugfs_add_interface(struct + ahvif->debugfs_linkstats = NULL; + } + ++ if (ahvif->debugfs_primary_link) ++ goto exit; ++ ++ ahvif->debugfs_primary_link = debugfs_create_file("primary_link", ++ 0644, ++ vif->debugfs_dir, ++ ahvif, ++ &ath12k_fops_primary_link); ++ if (!ahvif->debugfs_primary_link || ++ IS_ERR(ahvif->debugfs_primary_link)) { ++ ath12k_warn(arvif->ar->ab, ++ "failed to create primary link file\n"); ++ ++ debugfs_remove_recursive(arvif->debugfs_twt); ++ arvif->debugfs_twt = NULL; ++ ++ if (hw->wiphy->num_hw) { ++ debugfs_remove(arvif->debugfs_rtsthreshold); ++ arvif->debugfs_rtsthreshold = NULL; ++ } ++ ++ debugfs_remove(ahvif->debugfs_linkstats); ++ ahvif->debugfs_linkstats = NULL; ++ ++ ahvif->debugfs_primary_link = NULL; ++ } + exit: + return ret; + } +@@ -4874,9 +4946,15 @@ void ath12k_debugfs_remove_interface(str + arvif->debugfs_twt = NULL; + arvif->debugfs_rtsthreshold = NULL; + ahvif->debugfs_linkstats = NULL; ++ ahvif->debugfs_primary_link = NULL; + return; + } + ++ if (ahvif->debugfs_primary_link) { ++ debugfs_remove(ahvif->debugfs_primary_link); ++ ahvif->debugfs_primary_link = NULL; ++ } ++ + if (ahvif->debugfs_linkstats) { + debugfs_remove(ahvif->debugfs_linkstats); + ahvif->debugfs_linkstats = NULL; +--- a/drivers/net/wireless/ath/ath12k/bondif.c ++++ b/drivers/net/wireless/ath/ath12k/bondif.c +@@ -388,11 +388,10 @@ static struct net_device *ath12k_mac_get + } + + if (sta) { +- /* TODO: Use Primary Link */ +- ndev = mldev->vif->link_ndev[ahsta->assoc_link_id]; +- ath12k_dbg(NULL, ATH12K_DBG_DP_TX, "[%s] %s:%d deliver packets for sta %pM ahsta->assoc_link_id %d ndev %s\n", +- current->comm, __func__, __LINE__, +- sta, ahsta->assoc_link_id, ndev->name); ++ ndev = mldev->vif->link_ndev[ahsta->primary_link_id]; ++ ath12k_dbg(NULL, ATH12K_DBG_DP_TX, "[%s] %s:%d deliver packets for sta %pM ahsta->primary_link_id %d ndev %s\n", ++ current->comm, __func__, __LINE__, ++ sta, ahsta->primary_link_id, ndev->name); + } + + dvlan_check: diff --git a/feeds/ipq95xx/mac80211/patches/qca/838-01-UPSTREAM-wifi-mac80211-call-drv_sta_state-under-sdat.patch b/feeds/ipq95xx/mac80211/patches/qca/838-01-UPSTREAM-wifi-mac80211-call-drv_sta_state-under-sdat.patch new file mode 100644 index 000000000..cfa1db7ef --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/838-01-UPSTREAM-wifi-mac80211-call-drv_sta_state-under-sdat.patch @@ -0,0 +1,63 @@ +From 3b0fc0ceaa9f964e536b9a6602b0ad80b38a3722 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Mon, 9 Oct 2023 18:03:59 +0530 +Subject: [PATCH 1/3] UPSTREAM: wifi: mac80211: call drv_sta_state() under + sdata_lock() in reconfig + +Currently, other paths calling drv_sta_state() hold the mutex +and therefore drivers can assume that, and look at links with +that protection. Fix that for the reconfig path as well; to +do it more easily use ieee80211_reconfig_stations() for the +AP/AP_VLAN station reconfig as well. + +(Cherry-picked from https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git/commit/?id=48c5d82aba65c91cbc8eff308037bf58bc012eb1) + +Signed-off-by: Johannes Berg +Signed-off-by: Sathishkumar Muruganandam +--- + net/mac80211/util.c | 26 ++++++++++++-------------- + 1 file changed, 12 insertions(+), 14 deletions(-) + +diff --git a/net/mac80211/util.c b/net/mac80211/util.c +index b452b92659bd..047586d322e5 100644 +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -2854,23 +2854,21 @@ int ieee80211_reconfig(struct ieee80211_local *local) + } + + /* APs are now beaconing, add back stations */ +- mutex_lock(&local->sta_mtx); +- list_for_each_entry(sta, &local->sta_list, list) { +- enum ieee80211_sta_state state; +- +- if (!sta->uploaded) +- continue; +- +- if (sta->sdata->vif.type != NL80211_IFTYPE_AP && +- sta->sdata->vif.type != NL80211_IFTYPE_AP_VLAN) ++ list_for_each_entry(sdata, &local->interfaces, list) { ++ if (!ieee80211_sdata_running(sdata)) + continue; + +- for (state = IEEE80211_STA_NOTEXIST; +- state < sta->sta_state; state++) +- WARN_ON(drv_sta_state(local, sta->sdata, sta, state, +- state + 1)); ++ sdata_lock(sdata); ++ switch (sdata->vif.type) { ++ case NL80211_IFTYPE_AP_VLAN: ++ case NL80211_IFTYPE_AP: ++ ieee80211_reconfig_stations(sdata); ++ break; ++ default: ++ break; ++ } ++ sdata_unlock(sdata); + } +- mutex_unlock(&local->sta_mtx); + + /* add back keys */ + list_for_each_entry(sdata, &local->interfaces, list) +-- +2.17.1 + diff --git a/feeds/ipq95xx/mac80211/patches/qca/838-02-UPSTREAM-wifi-mac80211-HW-restart-for-MLO.patch b/feeds/ipq95xx/mac80211/patches/qca/838-02-UPSTREAM-wifi-mac80211-HW-restart-for-MLO.patch new file mode 100644 index 000000000..f71de2e04 --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/838-02-UPSTREAM-wifi-mac80211-HW-restart-for-MLO.patch @@ -0,0 +1,328 @@ +From 2f7e768348dd63a0bf5ea60a728c2f4ead37d486 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Mon, 9 Oct 2023 18:55:00 +0530 +Subject: [PATCH 2/3] UPSTREAM: wifi: mac80211: HW restart for MLO + +Implement proper reconfiguration for interfaces that are +doing MLO, in order to be able to recover from HW restart +correctly. + +(Cherry-picked from https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git/commit/?id=acb8bca343f8d) + +Signed-off-by: Johannes Berg +Signed-off-by: Gregory Greenman +Link: https://lore.kernel.org/r/20230504134511.828474-6-gregory.greenman@intel.com +Signed-off-by: Johannes Berg +Signed-off-by: Sathishkumar Muruganandam +--- + net/mac80211/util.c | 265 +++++++++++++++++++++----------------------- + 1 file changed, 126 insertions(+), 139 deletions(-) + +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -2519,137 +2519,15 @@ static int ieee80211_reconfig_nan(struct + return 0; + } + +-static int ieee80211_reconfig_link_bss(struct ieee80211_sub_if_data *sdata, +- struct ieee80211_link_data *link, +- struct ieee80211_bss_conf *link_conf) +-{ +- struct ieee80211_local *local = sdata->local; +- int i, res, changed = 0; +- +- switch (sdata->vif.type) { +- case NL80211_IFTYPE_AP_VLAN: +- case NL80211_IFTYPE_MONITOR: +- break; +- case NL80211_IFTYPE_ADHOC: +- if (sdata->vif.cfg.ibss_joined) +- WARN_ON(drv_join_ibss(local, sdata)); +- fallthrough; +- default: +- ieee80211_reconfig_stations(sdata); +- fallthrough; +- case NL80211_IFTYPE_AP: /* AP stations are handled later */ +- for (i = 0; i < IEEE80211_NUM_ACS; i++) +- drv_conf_tx(local, link, i, +- &link->tx_conf[i]); +- break; +- } +- +- /* common change flags for all interface types */ +- changed = BSS_CHANGED_ERP_CTS_PROT | +- BSS_CHANGED_ERP_PREAMBLE | +- BSS_CHANGED_ERP_SLOT | +- BSS_CHANGED_HT | +- BSS_CHANGED_BASIC_RATES | +- BSS_CHANGED_BEACON_INT | +- BSS_CHANGED_BSSID | +- BSS_CHANGED_CQM | +- BSS_CHANGED_QOS | +- BSS_CHANGED_IDLE | +- BSS_CHANGED_TXPOWER | +- BSS_CHANGED_MCAST_RATE; +- +- if (link_conf->mu_mimo_owner) +- changed |= BSS_CHANGED_MU_GROUPS; +- +- switch (sdata->vif.type) { +-#ifdef CPTCFG_MAC80211_BONDED_SUPPORT +- case NL80211_IFTYPE_DUMMY: +- return 0; +-#endif +- case NL80211_IFTYPE_STATION: +- changed |= BSS_CHANGED_PS; +- changed &= ~BSS_CHANGED_IDLE; +- ieee80211_link_info_change_notify(sdata, link, changed); +- +- changed = BSS_CHANGED_ASSOC | +- BSS_CHANGED_ARP_FILTER | +- BSS_CHANGED_IDLE; +- +- ieee80211_vif_cfg_change_notify(sdata, changed); +- changed = 0; +- /* Re-send beacon info report to the driver */ +- if (link->u.mgd.have_beacon) +- changed |= BSS_CHANGED_BEACON_INFO; +- +- if (link_conf->max_idle_period || +- link_conf->protected_keep_alive) +- changed |= BSS_CHANGED_KEEP_ALIVE; +- +- ieee80211_link_info_change_notify(sdata, link, changed); +- break; +- case NL80211_IFTYPE_OCB: +- changed |= BSS_CHANGED_OCB; +- ieee80211_link_info_change_notify(sdata, link, changed); +- break; +- case NL80211_IFTYPE_ADHOC: +- changed |= BSS_CHANGED_IBSS; +- fallthrough; +- case NL80211_IFTYPE_AP: +- changed |= BSS_CHANGED_P2P_PS; +- +- if (link_conf->ftm_responder == 1 && +- wiphy_ext_feature_isset(sdata->local->hw.wiphy, +- NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER)) +- changed |= BSS_CHANGED_FTM_RESPONDER; +- +- if (sdata->vif.type == NL80211_IFTYPE_AP) { +- changed |= BSS_CHANGED_AP_PROBE_RESP; +- +- if (rcu_access_pointer(link->u.ap.beacon)) +- drv_start_ap(local, sdata, +- link->conf); +- +- ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_SSID); +- } +- fallthrough; +- case NL80211_IFTYPE_MESH_POINT: +- if (link_conf->enable_beacon) { +- changed |= BSS_CHANGED_BEACON | +- BSS_CHANGED_BEACON_ENABLED; +- ieee80211_link_info_change_notify(sdata, link, changed &~ BSS_CHANGED_IDLE); +- } +- break; +- case NL80211_IFTYPE_NAN: +- res = ieee80211_reconfig_nan(sdata); +- if (res < 0) { +- ieee80211_handle_reconfig_failure(local); +- return res; +- } +- break; +- case NL80211_IFTYPE_AP_VLAN: +- case NL80211_IFTYPE_MONITOR: +- case NL80211_IFTYPE_P2P_DEVICE: +- /* nothing to do */ +- break; +- case NL80211_IFTYPE_UNSPECIFIED: +- case NUM_NL80211_IFTYPES: +- case NL80211_IFTYPE_P2P_CLIENT: +- case NL80211_IFTYPE_P2P_GO: +- case NL80211_IFTYPE_WDS: +- WARN_ON(1); +- break; +- } +- +- return 0; +-} +- + int ieee80211_reconfig(struct ieee80211_local *local) + { + struct ieee80211_hw *hw = &local->hw; + struct ieee80211_sub_if_data *sdata; + struct ieee80211_chanctx *ctx; ++ struct ieee80211_link_data *link; + struct sta_info *sta; + int res, i; ++ u64 changed = 0; + bool reconfig_due_to_wowlan = false; + struct ieee80211_sub_if_data *sched_scan_sdata; + struct cfg80211_sched_scan_request *sched_scan_req; +@@ -2806,32 +2684,140 @@ int ieee80211_reconfig(struct ieee80211_ + continue; + + sdata_lock(sdata); +- for (link_id = 0; +- link_id < ARRAY_SIZE(sdata->vif.link_conf); +- link_id++) { +- struct ieee80211_link_data *link; +- +- link = sdata_dereference(sdata->link[link_id], sdata); +- if (link) +- ieee80211_assign_chanctx(local, sdata, link); +- } + + for (link_id = 0; + link_id < ARRAY_SIZE(sdata->vif.link_conf); + link_id++) { +- struct ieee80211_link_data *link; +- struct ieee80211_bss_conf *link_conf; ++ ++ if (sdata->vif.valid_links && ++ !(sdata->vif.active_links & BIT(link_id))) ++ continue; + + link = sdata_dereference(sdata->link[link_id], sdata); + if (!link) + continue; + +- link_conf = link->conf; +- res = ieee80211_reconfig_link_bss(sdata, link, link_conf); +- if (res < 0) +- return res; ++ ieee80211_assign_chanctx(local, sdata, link); + } ++ ++ switch (sdata->vif.type) { ++ case NL80211_IFTYPE_AP_VLAN: ++ case NL80211_IFTYPE_MONITOR: ++ break; ++ case NL80211_IFTYPE_ADHOC: ++ if (sdata->vif.cfg.ibss_joined) ++ WARN_ON(drv_join_ibss(local, sdata)); ++ fallthrough; ++ default: ++ ieee80211_reconfig_stations(sdata); ++ fallthrough; ++ case NL80211_IFTYPE_AP: /* AP stations are handled later */ ++ for (i = 0; i < IEEE80211_NUM_ACS; i++) ++ drv_conf_tx(local, &sdata->deflink, i, ++ &sdata->deflink.tx_conf[i]); ++ break; ++ } ++ + sdata_unlock(sdata); ++ ++ /* common change flags for all interface types */ ++ changed = BSS_CHANGED_ERP_CTS_PROT | ++ BSS_CHANGED_ERP_PREAMBLE | ++ BSS_CHANGED_ERP_SLOT | ++ BSS_CHANGED_HT | ++ BSS_CHANGED_BASIC_RATES | ++ BSS_CHANGED_BEACON_INT | ++ BSS_CHANGED_BSSID | ++ BSS_CHANGED_CQM | ++ BSS_CHANGED_QOS | ++ BSS_CHANGED_TXPOWER | ++ BSS_CHANGED_MCAST_RATE; ++ ++ if (sdata->vif.bss_conf.mu_mimo_owner) ++ changed |= BSS_CHANGED_MU_GROUPS; ++ ++ switch (sdata->vif.type) { ++#ifdef CPTCFG_MAC80211_BONDED_SUPPORT ++ case NL80211_IFTYPE_DUMMY: ++ return 0; ++#endif ++ case NL80211_IFTYPE_STATION: ++ if (!sdata->vif.valid_links) { ++ changed |= BSS_CHANGED_ASSOC | ++ BSS_CHANGED_ARP_FILTER | ++ BSS_CHANGED_PS; ++ ++ /* Re-send beacon info report to the driver */ ++ if (sdata->deflink.u.mgd.have_beacon) ++ changed |= BSS_CHANGED_BEACON_INFO; ++ ++ if (sdata->vif.bss_conf.max_idle_period || ++ sdata->vif.bss_conf.protected_keep_alive) ++ changed |= BSS_CHANGED_KEEP_ALIVE; ++ ++ ieee80211_bss_info_change_notify(sdata, changed); ++ } else if (!WARN_ON(!link)) { ++ ieee80211_link_info_change_notify(sdata, link, ++ changed); ++ changed = BSS_CHANGED_ASSOC | ++ BSS_CHANGED_IDLE | ++ BSS_CHANGED_PS | ++ BSS_CHANGED_ARP_FILTER; ++ ieee80211_vif_cfg_change_notify(sdata, changed); ++ } ++ break; ++ case NL80211_IFTYPE_OCB: ++ changed |= BSS_CHANGED_OCB; ++ ieee80211_link_info_change_notify(sdata, link, changed); ++ break; ++ case NL80211_IFTYPE_ADHOC: ++ changed |= BSS_CHANGED_IBSS; ++ fallthrough; ++ case NL80211_IFTYPE_AP: ++ changed |= BSS_CHANGED_P2P_PS; ++ ++ if (sdata->vif.bss_conf.ftm_responder == 1 && ++ wiphy_ext_feature_isset(sdata->local->hw.wiphy, ++ NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER)) ++ changed |= BSS_CHANGED_FTM_RESPONDER; ++ ++ if (sdata->vif.type == NL80211_IFTYPE_AP) { ++ changed |= BSS_CHANGED_AP_PROBE_RESP; ++ ++ if (rcu_access_pointer(link->u.ap.beacon)) ++ drv_start_ap(local, sdata, ++ link->conf); ++ ++ ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_SSID); ++ } ++ fallthrough; ++ case NL80211_IFTYPE_MESH_POINT: ++ if (sdata->vif.bss_conf.enable_beacon) { ++ changed |= BSS_CHANGED_BEACON | ++ BSS_CHANGED_BEACON_ENABLED; ++ ieee80211_link_info_change_notify(sdata, link, changed &~ BSS_CHANGED_IDLE); ++ } ++ break; ++ case NL80211_IFTYPE_NAN: ++ res = ieee80211_reconfig_nan(sdata); ++ if (res < 0) { ++ ieee80211_handle_reconfig_failure(local); ++ return res; ++ } ++ break; ++ case NL80211_IFTYPE_AP_VLAN: ++ case NL80211_IFTYPE_MONITOR: ++ case NL80211_IFTYPE_P2P_DEVICE: ++ /* nothing to do */ ++ break; ++ case NL80211_IFTYPE_UNSPECIFIED: ++ case NUM_NL80211_IFTYPES: ++ case NL80211_IFTYPE_P2P_CLIENT: ++ case NL80211_IFTYPE_P2P_GO: ++ case NL80211_IFTYPE_WDS: ++ WARN_ON(1); ++ break; ++ } + } + + ieee80211_recalc_ps(local); +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -202,6 +202,7 @@ int ieee80211_hw_config(struct ieee80211 + + #define BSS_CHANGED_VIF_CFG_FLAGS (BSS_CHANGED_ASSOC |\ + BSS_CHANGED_IDLE |\ ++ BSS_CHANGED_PS |\ + BSS_CHANGED_IBSS |\ + BSS_CHANGED_ARP_FILTER |\ + BSS_CHANGED_SSID) diff --git a/feeds/ipq95xx/mac80211/patches/qca/838-03-UPSTREAM-wifi-mac80211-implement-proper-AP-MLD-HW-re.patch b/feeds/ipq95xx/mac80211/patches/qca/838-03-UPSTREAM-wifi-mac80211-implement-proper-AP-MLD-HW-re.patch new file mode 100644 index 000000000..2235b8aba --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/838-03-UPSTREAM-wifi-mac80211-implement-proper-AP-MLD-HW-re.patch @@ -0,0 +1,91 @@ +From 4638ea54694874ce1d6c2d61effda4706c3139fe Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Mon, 9 Oct 2023 19:12:22 +0530 +Subject: [PATCH 3/3] UPSTREAM: wifi: mac80211: implement proper AP MLD HW + restart + +Previously, I didn't implement restarting here at all if the +interface is an MLD, so it only worked for non-MLO. Add the +needed code to restart an AP MLD correctly. + +(Cherry-picked from https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git/commit/?id=61403414e1719) + +Signed-off-by: Johannes Berg +Signed-off-by: Gregory Greenman +Link: https://lore.kernel.org/r/20230504134511.828474-12-gregory.greenman@intel.com +Signed-off-by: Johannes Berg +Signed-off-by: Sathishkumar Muruganandam +--- + net/mac80211/util.c | 46 +++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 44 insertions(+), 2 deletions(-) + +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -2519,6 +2519,35 @@ static int ieee80211_reconfig_nan(struct + return 0; + } + ++static void ieee80211_reconfig_ap_links(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata, ++ u32 changed) ++{ ++ int link_id; ++ ++ for (link_id = 0; link_id < ARRAY_SIZE(sdata->link); link_id++) { ++ struct ieee80211_link_data *link; ++ ++ if (!(sdata->vif.active_links & BIT(link_id))) ++ continue; ++ ++ link = sdata_dereference(sdata->link[link_id], sdata); ++ if (!link) ++ continue; ++ ++ if (rcu_access_pointer(link->u.ap.beacon)) ++ drv_start_ap(local, sdata, link->conf); ++ ++ if (!link->conf->enable_beacon) ++ continue; ++ ++ changed |= BSS_CHANGED_BEACON | ++ BSS_CHANGED_BEACON_ENABLED; ++ ++ ieee80211_link_info_change_notify(sdata, link, changed); ++ } ++} ++ + int ieee80211_reconfig(struct ieee80211_local *local) + { + struct ieee80211_hw *hw = &local->hw; +@@ -2777,6 +2806,12 @@ int ieee80211_reconfig(struct ieee80211_ + case NL80211_IFTYPE_AP: + changed |= BSS_CHANGED_P2P_PS; + ++ if (sdata->vif.valid_links) ++ ieee80211_vif_cfg_change_notify(sdata, ++ BSS_CHANGED_SSID); ++ else ++ changed |= BSS_CHANGED_SSID; ++ + if (sdata->vif.bss_conf.ftm_responder == 1 && + wiphy_ext_feature_isset(sdata->local->hw.wiphy, + NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER)) +@@ -2785,9 +2820,16 @@ int ieee80211_reconfig(struct ieee80211_ + if (sdata->vif.type == NL80211_IFTYPE_AP) { + changed |= BSS_CHANGED_AP_PROBE_RESP; + +- if (rcu_access_pointer(link->u.ap.beacon)) ++ if (sdata->vif.valid_links) { ++ ieee80211_reconfig_ap_links(local, ++ sdata, ++ changed); ++ break; ++ } ++ ++ if (rcu_access_pointer(sdata->deflink.u.ap.beacon)) + drv_start_ap(local, sdata, +- link->conf); ++ sdata->deflink.conf); + + ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_SSID); + } diff --git a/feeds/ipq95xx/mac80211/patches/qca/838-mac80211-Make-link-addresses-deterministic.patch b/feeds/ipq95xx/mac80211/patches/qca/838-mac80211-Make-link-addresses-deterministic.patch new file mode 100644 index 000000000..2902cb0dc --- /dev/null +++ b/feeds/ipq95xx/mac80211/patches/qca/838-mac80211-Make-link-addresses-deterministic.patch @@ -0,0 +1,78 @@ +From a82b4abad9dc473ef1c00182f258fb10f7b8fcc3 Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Wed, 4 Oct 2023 17:29:49 +0530 +Subject: [PATCH] mac80211: Make link addresses deterministic + +Currently ML Station link addresses are randomized. The link +on which association takes place uses the MLD address/vif address +and the other partner link addresses are randomized. + +Though there is no harm in using randomized addresses, it would be +better to configure deterministic addresses based on certain offsets +from the MLD address for ease of use/debug. + +Also this helps in some AP implementations which gets confused when +a link picks up another address which was used previously by another +link when ML STA moves from single to multi link or vice versa. + +Signed-off-by: Sriram R +--- + net/mac80211/mlme.c | 25 ++++++++++++++++++------- + 1 file changed, 18 insertions(+), 7 deletions(-) + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index f6d5817..0797670 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -6483,9 +6483,16 @@ void ieee80211_mgd_setup_link(struct ieee80211_link_data *link) + ether_addr_copy(link->conf->addr, + sdata->u.mgd.assoc_data->link[link_id].addr); + } else if (link != &sdata->deflink) { +- ether_addr_copy(link->conf->addr, sdata->vif.addr); ++ ether_addr_copy(link->conf->addr, sdata->vif.addr); ++ if (link_id >= 0) ++ link->conf->addr[5] += link_id; + } else if (!is_valid_ether_addr(link->conf->addr)) { +- eth_random_addr(link->conf->addr); ++ if (link_id >= 0) { ++ ether_addr_copy(link->conf->addr, sdata->vif.addr); ++ link->conf->addr[5] += link_id; ++ } else { ++ eth_random_addr(link->conf->addr); ++ } + } + } + +@@ -6540,8 +6547,10 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, + goto out_err; + } + +- if (mlo && !is_valid_ether_addr(link->conf->addr)) +- eth_random_addr(link->conf->addr); ++ if (mlo && !is_valid_ether_addr(link->conf->addr)) { ++ ether_addr_copy(link->conf->addr, sdata->vif.addr); ++ link->conf->addr[5] += link_id; ++ } + + if (WARN_ON(!ifmgd->auth_data && !ifmgd->assoc_data)) { + err = -EINVAL; +@@ -7033,11 +7042,13 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, + if (!req->links[i].bss) + continue; + link = sdata_dereference(sdata->link[i], sdata); +- if (link) ++ if (link) { + ether_addr_copy(assoc_data->link[i].addr, + link->conf->addr); +- else +- eth_random_addr(assoc_data->link[i].addr); ++ } else { ++ ether_addr_copy(assoc_data->link[i].addr, sdata->vif.addr); ++ assoc_data->link[i].addr[5] += i; ++ } + } + } else { + memcpy(assoc_data->link[0].addr, sdata->vif.addr, ETH_ALEN); +-- +2.17.1 + diff --git a/feeds/ipq95xx/qca-nss-ppe/Makefile b/feeds/ipq95xx/qca-nss-ppe/Makefile index f345f0a2b..7a1c462ed 100644 --- a/feeds/ipq95xx/qca-nss-ppe/Makefile +++ b/feeds/ipq95xx/qca-nss-ppe/Makefile @@ -6,8 +6,8 @@ PKG_SOURCE_PROTO:=git PKG_BRANCH:=master PKG_RELEASE:=2 PKG_SOURCE_URL:=https://git.codelinaro.org/clo/qsdk/oss/lklm/nss-ppe -PKG_MIRROR_HASH:=754a604e282d97af3eac8b6af0a16c4fe48fdef8f04ae593d016e1f0ba9886da -PKG_VERSION:=ffc8f2447dbb2d4a29d1fca4fad516132d5848fe +PKG_MIRROR_HASH:=1a479dd17f4d69dcde16ac923fcfed482c03f9ff884b1eb7f0d7eb70a55b14cc +PKG_VERSION:=8fd53230ede34386fe42ca2f63314e05b73d3b15 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) @@ -121,6 +121,7 @@ EXTRA_CFLAGS+= \ -I$(STAGING_DIR)/usr/include/nat46 \ -Wno-error=unused-variable \ +MAKE_OPTS+=ppe-drv=y ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-ppe-bridge-mgr),) MAKE_OPTS+=bridge-mgr=y diff --git a/feeds/ipq95xx/qca-psdk/Makefile b/feeds/ipq95xx/qca-psdk/Makefile index 1e5ba7263..3ae6fada3 100755 --- a/feeds/ipq95xx/qca-psdk/Makefile +++ b/feeds/ipq95xx/qca-psdk/Makefile @@ -6,7 +6,7 @@ PKG_SOURCE_PROTO:=git PKG_BRANCH:=master PKG_RELEASE:=2 PKG_SOURCE_URL:=https://git.codelinaro.org/clo/qsdk/oss/lklm/qca-psdk -PKG_VERSION:=ffc8f2447dbb2d4a29d1fca4fad516132d5848fe +PKG_VERSION:=402973acc8a17d9b685ed3c3490b7d6289f4798f PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) diff --git a/feeds/ipq95xx/qca-ssdk-shell/Makefile b/feeds/ipq95xx/qca-ssdk-shell/Makefile index c3a74a229..0c962c15d 100644 --- a/feeds/ipq95xx/qca-ssdk-shell/Makefile +++ b/feeds/ipq95xx/qca-ssdk-shell/Makefile @@ -7,7 +7,7 @@ PKG_SOURCE_PROTO:=git PKG_BRANCH:=master PKG_RELEASE:=1 PKG_SOURCE_URL:=https://git.codelinaro.org/clo/qsdk/oss/ssdk-shell -PKG_VERSION:=b78d6095444e22b274e8b47e10100a2f51a3b65e +PKG_VERSION:=32705902f75a5932c19b853d457ceebe5b215e23 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) diff --git a/feeds/ipq95xx/qca-ssdk/Makefile b/feeds/ipq95xx/qca-ssdk/Makefile index 4f41a3343..23cce6b10 100644 --- a/feeds/ipq95xx/qca-ssdk/Makefile +++ b/feeds/ipq95xx/qca-ssdk/Makefile @@ -7,8 +7,8 @@ PKG_SOURCE_PROTO:=git PKG_BRANCH:=master PKG_RELEASE:=1 PKG_SOURCE_URL:=https://git.codelinaro.org/clo/qsdk/oss/lklm/qca-ssdk -PKG_MIRROR_HASH:=63209e01c092bd6ee63a4094995b78772c8e4ff7cd7f81f8dba51366697a4639 -PKG_VERSION:=9e687f44ee13ce0904f291c9771172b488b7f9ed +PKG_MIRROR_HASH:=7cd25bec93197269559339b95f86238a4fb6bd2b517226bd5049ab7c9c0ef8fe +PKG_VERSION:=09cba788ef5680e3e5b9deaa376da8d6bc13a7ec PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) diff --git a/feeds/ipq95xx/qca-ssdk/patches/0001-add-RTL8261N-support.patch b/feeds/ipq95xx/qca-ssdk/patches/0001-add-RTL8261N-support.patch new file mode 100644 index 000000000..92994c5ba --- /dev/null +++ b/feeds/ipq95xx/qca-ssdk/patches/0001-add-RTL8261N-support.patch @@ -0,0 +1,5673 @@ +From ab15d4b9c6976d6184e997760c0bc71b90af0da7 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Thu, 7 Dec 2023 08:06:42 +0100 +Subject: [PATCH] add RTL8261N support + +Signed-off-by: John Crispin +--- + config | 9 + + include/hsl/phy/hsl_phy.h | 22 + + include/hsl/phy/phy_common.h | 1143 +++++++++++++++++++++ + include/hsl/phy/phy_rtl826xb.h | 320 ++++++ + make/linux_opt.mk | 4 + + src/hsl/phy/Makefile | 6 + + src/hsl/phy/hsl_phy.c | 185 +++- + src/hsl/phy/phy_rtl826xb_patch.c | 1651 ++++++++++++++++++++++++++++++ + src/hsl/phy/rtl.c | 520 ++++++++++ + src/hsl/phy/rtl826xb_phy.c | 1521 +++++++++++++++++++++++++++ + src/init/ssdk_init.c | 31 + + 11 files changed, 5410 insertions(+), 2 deletions(-) + create mode 100644 include/hsl/phy/phy_common.h + create mode 100644 include/hsl/phy/phy_rtl826xb.h + create mode 100644 src/hsl/phy/phy_rtl826xb_patch.c + create mode 100644 src/hsl/phy/rtl.c + create mode 100644 src/hsl/phy/rtl826xb_phy.c + +diff --git a/config b/config +index 7d924fbf..b649540e 100755 +--- a/config ++++ b/config +@@ -269,6 +269,7 @@ endif + ############################################# + ifeq (ALL_CHIP, $(CHIP_TYPE)) + IN_AQUANTIA_PHY=TRUE ++ IN_RTL_PHY=TRUE + IN_QCA803X_PHY=TRUE + IN_QCA808X_PHY=TRUE + IN_PHY_I2C_MODE=TRUE +@@ -277,6 +278,7 @@ ifeq (ALL_CHIP, $(CHIP_TYPE)) + IN_SFP=TRUE + else ifeq (HPPE, $(CHIP_TYPE)) + IN_AQUANTIA_PHY=TRUE ++ IN_RTL_PHY=TRUE + IN_QCA803X_PHY=TRUE + IN_QCA808X_PHY=TRUE + IN_PHY_I2C_MODE=TRUE +@@ -285,17 +287,21 @@ else ifeq (HPPE, $(CHIP_TYPE)) + IN_MALIBU_PHY=TRUE + else ifeq (CPPE, $(CHIP_TYPE)) + IN_QCA808X_PHY=TRUE ++ IN_RTL_PHY=TRUE + IN_PHY_I2C_MODE=TRUE + IN_MALIBU_PHY=TRUE + else ifeq (DESS, $(CHIP_TYPE)) + IN_MALIBU_PHY=TRUE ++ IN_RTL_PHY=TRUE + else ifeq (MP, $(CHIP_TYPE)) ++ IN_RTL_PHY=TRUE + IN_QCA803X_PHY=TRUE + IN_QCA808X_PHY=TRUE + IN_SFP_PHY=TRUE + IN_SFP=TRUE + else ifeq (APPE, $(CHIP_TYPE)) + IN_AQUANTIA_PHY=TRUE ++ IN_RTL_PHY=TRUE + IN_QCA803X_PHY=TRUE + IN_QCA808X_PHY=TRUE + IN_SFP_PHY=TRUE +@@ -303,11 +309,13 @@ else ifeq (APPE, $(CHIP_TYPE)) + IN_MALIBU_PHY=TRUE + else ifeq (MPPE, $(CHIP_TYPE)) + ifeq ($(LOWMEM_FLASH), enable) ++ IN_RTL_PHY=TRUE + IN_QCA803X_PHY=TRUE + ISISC_ENABLE=enable + MHT_ENABLE=disable + else + IN_AQUANTIA_PHY=TRUE ++ IN_RTL_PHY=TRUE + IN_QCA803X_PHY=TRUE + IN_QCA808X_PHY=TRUE + IN_SFP_PHY=TRUE +@@ -317,6 +325,7 @@ else + IN_QCA803X_PHY=FALSE + IN_QCA808X_PHY=FALSE + IN_AQUANTIA_PHY=FALSE ++ IN_RTL_PHY=FALSE + IN_MALIBU_PHY=FALSE + IN_SFP_PHY=FALSE + IN_SFP=FALSE +diff --git a/include/hsl/phy/hsl_phy.h b/include/hsl/phy/hsl_phy.h +index 6c71187c..ac4e035d 100755 +--- a/include/hsl/phy/hsl_phy.h ++++ b/include/hsl/phy/hsl_phy.h +@@ -253,6 +253,10 @@ extern "C" { + a_uint32_t phy_id, + a_uint32_t source_id, + led_ctrl_pattern_t * pattern); ++ typedef sw_error_t(*hsl_phy_pll_on) (a_uint32_t dev_id, a_uint32_t phy_id); ++ typedef sw_error_t(*hsl_phy_pll_off) (a_uint32_t dev_id, a_uint32_t phy_id); ++ typedef sw_error_t(*hsl_phy_ldo_set) (a_uint32_t dev_id, a_uint32_t phy_id, ++ a_bool_t enable); + typedef sw_error_t(*hsl_phy_ptp_security_set) (a_uint32_t dev_id, + a_uint32_t phy_id, fal_ptp_security_t *sec); + +@@ -520,6 +524,9 @@ extern "C" { + hsl_phy_led_ctrl_pattern_set phy_led_ctrl_pattern_set; + hsl_phy_led_ctrl_pattern_get phy_led_ctrl_pattern_get; + hsl_phy_led_ctrl_source_set phy_led_ctrl_source_set; ++ hsl_phy_pll_on phy_pll_on; ++ hsl_phy_pll_off phy_pll_off; ++ hsl_phy_ldo_set phy_ldo_set; + hsl_phy_ptp_ops_t phy_ptp_ops; + /*qca808x_start*/ + } hsl_phy_ops_t; +@@ -542,6 +549,7 @@ typedef enum + QCA803X_PHY_CHIP, + SFP_PHY_CHIP, + MPGE_PHY_CHIP, ++ RTL_PHY_CHIP, + /*qca808x_start*/ + QCA808X_PHY_CHIP, + MAX_PHY_CHIP, +@@ -601,6 +609,7 @@ typedef struct { + #define AQUANTIA_PHY_113C_B0 0x31c31C12 + #define AQUANTIA_PHY_113C_B1 0x31c31C13 + #define AQUANTIA_PHY_112C 0x03a1b792 ++#define RTL_PHY 0X001CCAF3 + + #define PHY_805XV2 0x004DD082 + #define PHY_805XV1 0x004DD081 +@@ -753,6 +762,12 @@ hsl_port_phy_led_ctrl_pattern_get(a_uint32_t dev_id, led_pattern_group_t group, + sw_error_t + hsl_port_phy_led_ctrl_source_set(a_uint32_t dev_id, a_uint32_t source_id, + led_ctrl_pattern_t *pattern); ++sw_error_t ++hsl_port_phy_pll_on(a_uint32_t dev_id, a_uint32_t port_id); ++sw_error_t ++hsl_port_phy_pll_off(a_uint32_t dev_id, a_uint32_t port_id); ++sw_error_t ++hsl_port_phy_ldo_set(a_uint32_t dev_id, a_uint32_t port_id, a_bool_t enable); + phy_info_t *hsl_phy_info_get(a_uint32_t dev_id); + + sw_error_t +@@ -785,6 +800,9 @@ hsl_port_mode_to_phydev_interface(a_uint32_t dev_id, a_uint32_t port_mode); + a_uint32_t + hsl_port_mode_to_uniphy_mode(a_uint32_t dev_id, a_uint32_t port_mode); + a_uint32_t ++hsl_uniphy_mode_to_port_mode(a_uint32_t dev_id, a_uint32_t port_id, ++ a_uint32_t uniphy_mode); ++a_uint32_t + hsl_port_to_uniphy(a_uint32_t dev_id, a_uint32_t port_id); + sw_error_t + hsl_port_combo_phy_link_status_get(a_uint32_t dev_id, +@@ -811,6 +829,10 @@ hsl_port_phy_autoadv_set(a_uint32_t dev_id, a_uint32_t port_id, + a_uint32_t autoadv); + sw_error_t + hsl_port_phy_autoneg_restart(a_uint32_t dev_id, a_uint32_t port_id); ++sw_error_t ++hsl_port_phy_power_on(a_uint32_t dev_id, fal_port_t port_id); ++sw_error_t ++hsl_port_phy_power_off(a_uint32_t dev_id, fal_port_t port_id); + /*qca808x_end*/ + a_uint32_t + hsl_port_force_speed_get(a_uint32_t dev_id, a_uint32_t port_id); +diff --git a/include/hsl/phy/phy_common.h b/include/hsl/phy/phy_common.h +new file mode 100644 +index 00000000..0b028355 +--- /dev/null ++++ b/include/hsl/phy/phy_common.h +@@ -0,0 +1,1143 @@ ++/* ++ * Copyright (C) 2009-2016 Realtek Semiconductor Corp. ++ * All Rights Reserved. ++ * ++ * This program is the proprietary software of Realtek Semiconductor ++ * Corporation and/or its licensors, and only be used, duplicated, ++ * modified or distributed under the authorized license from Realtek. ++ * ++ * ANY USE OF THE SOFTWARE OTHER THAN AS AUTHORIZED UNDER ++ * THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. ++ * ++ * $Revision$ ++ * $Date$ ++ * ++ * Purpose : PHY Common Driver APIs. ++ * ++ * Feature : PHY Common Driver APIs ++ * ++ */ ++ ++#ifndef __HAL_PHY_PHY_COMMON_H__ ++#define __HAL_PHY_PHY_COMMON_H__ ++ ++ ++#include ++#include ++#include ++#include ++ ++#include "hsl.h" ++#include "ssdk_plat.h" ++#include "hsl_phy.h" ++ ++/* ++ * Include Files ++ */ ++/* ++ * Symbol Definition ++ */ ++#define RTCT_ENABLE (0) ++#define RTCT_CH_A (4) ++#define RTCT_CH_B (5) ++#define RTCT_CH_C (6) ++#define RTCT_CH_D (7) ++#define RTCT_DONE (15) ++ ++#define RTCT_BASE_ADDR (0x802a) ++#define RTCT_LEN_ADDR_A (RTCT_BASE_ADDR + 0x2) ++#define RTCT_LEN_ADDR_B (RTCT_BASE_ADDR + 0x6) ++#define RTCT_LEN_ADDR_C (RTCT_BASE_ADDR + 0xa) ++#define RTCT_LEN_ADDR_D (RTCT_BASE_ADDR + 0xe) ++#define RTCT_STATUS_ADDR_A (RTCT_BASE_ADDR + 0x0) ++#define RTCT_STATUS_ADDR_B (RTCT_BASE_ADDR + 0x4) ++#define RTCT_STATUS_ADDR_C (RTCT_BASE_ADDR + 0x8) ++#define RTCT_STATUS_ADDR_D (RTCT_BASE_ADDR + 0xc) ++ ++#define RTCT_STATUS_NORMAL (5) ++#define RTCT_STATUS_SHORT (4) ++#define RTCT_STATUS_OPEN (3) ++#define RTCT_STATUS_MISSMATCH_SHORT (2) ++#define RTCT_STATUS_MISSMATCH_OPEN (1) ++#define RTCT_STATUS_LINE_DRIVER (0) ++ ++#define GIGA_LITE_CTRL_REG 0xa42 ++ ++//#define PHY_C22_MMD_PAGE 0 ++#define PHY_C22_MMD_PAGE 0x0A41 ++#define PHY_C22_MMD_DEV_REG 13 ++#define PHY_C22_MMD_ADD_REG 14 ++ ++/* MDIO Manageable Device(MDD) address*/ ++#define PHY_MMD_PMAPMD 1 ++#define PHY_MMD_PCS 3 ++#define PHY_MMD_AN 7 ++#define PHY_MMD_VEND1 30 /* Vendor specific 1 */ ++#define PHY_MMD_VEND2 31 /* Vendor specific 2 */ ++ ++typedef enum rtk_phy_intr_e ++{ ++ RTK_PHY_INTR_COMMON, /* Normal interrupt */ ++ RTK_PHY_INTR_RLFD, /* Rapid Link Fault Detection interrupt for Fast Link Down Function */ ++ RTK_PHY_INTR_TM_LOW, /* thermal meter over temperature interrupt for level low */ ++ RTK_PHY_INTR_TM_HIGH, /* thermal meter over temperature interrupt for level High */ ++ RTK_PHY_INTR_END ++} rtk_phy_intr_t; ++ ++#if defined(IN_LINUX_STD_PTP) ++#include ++enum { ++ PTP_PKT_SEQID_UNMATCHED, ++ PTP_PKT_SEQID_MATCHED, ++ PTP_PKT_SEQID_MATCH_MAX ++}; ++ ++enum { ++ MARS_PTP_MSG_SYNC, ++ MARS_PTP_MSG_DREQ, ++ MARS_PTP_MSG_PREQ, ++ MARS_PTP_MSG_PRESP, ++ MARS_PTP_MSG_MAX ++}; ++ ++typedef struct { ++ /* ptp filter class */ ++ a_int32_t ptp_type; ++ /* ptp frame type */ ++ a_int32_t pkt_type; ++} mars_ptp_cb; ++ ++/* statistics for the event packet*/ ++typedef struct { ++ /* the counter saves the packet with sequence id ++ * matched and unmatched */ ++ a_uint64_t sync_cnt[PTP_PKT_SEQID_MATCH_MAX]; ++ a_uint64_t delay_req_cnt[PTP_PKT_SEQID_MATCH_MAX]; ++ a_uint64_t pdelay_req_cnt[PTP_PKT_SEQID_MATCH_MAX]; ++ a_uint64_t pdelay_resp_cnt[PTP_PKT_SEQID_MATCH_MAX]; ++ a_uint64_t event_pkt_cnt; ++} ptp_packet_stat; ++ ++typedef struct { ++ a_uint8_t reserved0; ++ a_uint8_t reserved1; ++ a_uint8_t msg_type; ++ a_uint16_t seqid; ++ a_uint32_t reserved2; ++ a_int64_t correction; ++} rtl_embeded_ts; ++ ++struct rtl_ptp_info { ++ a_int32_t hwts_tx_type; ++ a_int32_t hwts_rx_type; ++ struct rtl_ptp_clock *clock; ++ struct delayed_work tx_ts_work; ++ struct delayed_work rx_ts_work; ++ /* work for writing ingress time to register */ ++ struct delayed_work ingress_trig_work; ++ a_int32_t ingress_time; ++ struct sk_buff_head tx_queue; ++ struct sk_buff_head rx_queue; ++ rtl_embeded_ts embeded_ts; ++}; ++#endif ++ ++struct rtl_phy_info { ++ struct list_head list; ++ a_uint32_t dev_id; ++ /* phy real address,it is the mdio addr or the i2c slave addr */ ++ a_uint32_t phy_addr; ++ /* the address of phy device, it is a fake addr for the i2c accessed phy */ ++ a_uint32_t phydev_addr; ++#if defined(IN_LINUX_STD_PTP) ++ a_int32_t speed; ++ a_uint16_t clock_mode; ++ a_uint16_t step_mode; ++ /* work for gps sencond sync */ ++ struct delayed_work ts_schedule_work; ++ a_bool_t gps_seconds_sync_en; ++ /*the statistics array records the counter of ++ * rx and tx ptp event packet */ ++ ptp_packet_stat pkt_stat[2]; ++#endif ++}; ++ ++typedef struct { ++ struct phy_device *phydev; ++ struct rtl_phy_info *phy_info; ++#if defined(IN_LINUX_STD_PTP) ++ struct rtl_ptp_info ptp_info; ++#endif ++} rtl_priv; ++ ++typedef enum rtk_enable_e ++{ ++ DISABLED = 0, ++ ENABLED, ++ RTK_ENABLE_END ++} rtk_enable_t; ++ ++typedef a_uint32_t rtk_bitmap_t; ++ ++typedef enum rtk_port_duplex_e ++{ ++ PORT_HALF_DUPLEX = 0, ++ PORT_FULL_DUPLEX, ++ PORT_DUPLEX_END ++} rtk_port_duplex_t; ++ ++typedef enum rtk_port_speed_e ++{ ++ PORT_SPEED_10M = 0, ++ PORT_SPEED_100M, ++ PORT_SPEED_1000M, ++ PORT_SPEED_500M, ++ PORT_SPEED_2G, /* Applicable to 8380 */ ++ PORT_SPEED_2_5G, ++ PORT_SPEED_5G, ++ PORT_SPEED_10G, ++ PORT_SPEED_2_5G_LITE, ++ PORT_SPEED_5G_LITE, ++ PORT_SPEED_10G_LITE, ++ PORT_SPEED_END ++} rtk_port_speed_t; ++ ++ ++typedef enum rtk_port_masterSlave_e ++{ ++ PORT_AUTO_MODE = 0, ++ PORT_SLAVE_MODE, ++ PORT_MASTER_MODE, ++ PORT_MASTER_SLAVE_END ++} rtk_port_masterSlave_t; ++ ++typedef struct rtk_port_phy_ability_s ++{ ++ a_uint32_t Half_10:1; ++ a_uint32_t Full_10:1; ++ a_uint32_t Half_100:1; ++ a_uint32_t Full_100:1; ++ a_uint32_t Half_1000:1; ++ a_uint32_t Full_1000:1; ++#if (defined(CONFIG_SDK_RTL8390) || defined(CONFIG_SDK_RTL9300)) ++ a_uint32_t Half_10G:1; ++ a_uint32_t Full_10G:1; ++#endif ++ a_uint32_t adv_2_5G:1; ++ a_uint32_t adv_5G:1; ++ a_uint32_t adv_10GBase_T:1; ++ a_uint32_t FC:1; ++ a_uint32_t AsyFC:1; ++} rtk_port_phy_ability_t; ++ ++typedef enum rtk_port_linkStatus_e ++{ ++ PORT_LINKDOWN = 0, ++ PORT_LINKUP, ++ PORT_LINKSTATUS_END ++} rtk_port_linkStatus_t; ++ ++ ++/* value for RTK_PHY_CTRL_INTR_MASK*/ ++#define RTK_PHY_CTRL_INTR_MASK_COMMON (1 << RTK_PHY_INTR_COMMON) ++#define RTK_PHY_CTRL_INTR_MASK_RLFD (1 << RTK_PHY_INTR_RLFD) ++#define RTK_PHY_CTRL_INTR_MASK_TM_LOW (1 << RTK_PHY_INTR_TM_LOW) ++#define RTK_PHY_CTRL_INTR_MASK_TM_HIGH (1 << RTK_PHY_INTR_TM_HIGH) ++ ++/* bitmap width in bits */ ++#define BITMAP_WIDTH (sizeof(rtk_bitmap_t) * 8) ++#define RTK_MAX_PORT_PER_UNIT 64 ++ ++#define BITMAP_ARRAY_CNT(_num_of_indexes) ((_num_of_indexes + (BITMAP_WIDTH - 1)) / BITMAP_WIDTH) ++ ++#define RTK_TOTAL_NUM_OF_WORD_FOR_1BIT_PORT_LIST BITMAP_ARRAY_CNT(RTK_MAX_PORT_PER_UNIT) ++ ++typedef struct rtk_portmask_s ++{ ++ rtk_bitmap_t bits[RTK_TOTAL_NUM_OF_WORD_FOR_1BIT_PORT_LIST]; ++} rtk_portmask_t; ++ ++typedef enum rt_port_ethType_id_e ++{ ++ HWP_FE_ID = 0, ++ HWP_GE_ID, ++ HWP_2_5GE_ID, ++ HWP_5GE_ID, ++ HWP_XGE_ID, ++ HWP_SXGE_ID, ++ HWP_ETHTYPE_ID_END, ++}rt_port_ethType_id_t; ++ ++/* port ethernet type */ ++typedef enum rt_port_ethType_e ++{ ++ HWP_FE = (0x1 << HWP_FE_ID), /* Fast ethernet port */ ++ HWP_GE = (0x1 << HWP_GE_ID), /* Giga ethernet port */ ++ HWP_2_5GE = (0x1 << HWP_2_5GE_ID), /* 2.5 Giga ethernet port */ ++ HWP_5GE = (0x1 << HWP_5GE_ID), /* 5 Giga ethernet port */ ++ HWP_XGE = (0x1 << HWP_XGE_ID), /* 10 Giga ethernet port */ ++ HWP_SXGE = (0x1 << HWP_SXGE_ID), /* Cascade Stack port */ ++ HWP_ETHTYPE_END = (0x1 << HWP_ETHTYPE_ID_END), /* Ether type end*/ ++}rt_port_ethType_t; ++ ++ ++/* PHY SerDes eye-monitor handler */ ++typedef a_uint32_t (*phy_sds_eyeMon_hdlr_t)(a_uint32_t xAxis, a_uint32_t yAxis, a_uint32_t frameNum, void *pDb, a_uint32_t val); ++ ++ ++/* Function Name: ++ * phy_common_unavail ++ * Description: ++ * Return chip not support ++ * Input: ++ * None ++ * Output: ++ * None ++ * Return: ++ * RT_ERR_PORT_NOT_SUPPORTED - functions not supported by this port ++ * Note: ++ * None ++ */ ++extern a_uint32_t ++phy_common_unavail(void); ++ ++/* Function Name: ++ * phy_common_AutoNegoEnable_get ++ * Description: ++ * Get auto-negotiation enable status of the specific port ++ * Input: ++ * unit - unit id ++ * port - port id ++ * Output: ++ * None ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - invalid parameter ++ * Note: ++ * None ++ */ ++extern a_uint32_t ++phy_common_autoNegoEnable_get(a_uint32_t unit, a_uint32_t port, rtk_enable_t *pEnable); ++ ++ ++/* Function Name: ++ * phy_common_autoNegoEnable_set ++ * Description: ++ * Set auto-negotiation enable status of the specific port ++ * Input: ++ * unit - unit id ++ * port - port id ++ * Output: ++ * None ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - invalid parameter ++ * Note: ++ * None ++ */ ++extern a_uint32_t ++phy_common_autoNegoEnable_set(a_uint32_t unit, a_uint32_t port, rtk_enable_t enable); ++ ++/* Function Name: ++ * phy_common_duplex_get ++ * Description: ++ * Get duplex mode status of the specific port ++ * Input: ++ * unit - unit id ++ * port - port id ++ * Output: ++ * pDuplex - pointer to PHY duplex mode status ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - invalid parameter ++ * Note: ++ * None ++ */ ++extern a_uint32_t ++phy_common_duplex_get(a_uint32_t unit, a_uint32_t port, a_uint32_t *pDuplex); ++ ++/* Function Name: ++ * phy_common_duplex_get ++ * Description: ++ * Set duplex mode status of the specific port ++ * Input: ++ * unit - unit id ++ * port - port id ++ * duplex - duplex mode of the port, full or half ++ * Output: ++ * None ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - invalid parameter ++ * Note: ++ * None ++ */ ++extern a_uint32_t ++phy_common_duplex_set(a_uint32_t unit, a_uint32_t port, a_uint32_t duplex); ++ ++/* Function Name: ++ * phy_common_enable_set ++ * Description: ++ * Set PHY interface status of the specific port ++ * Input: ++ * unit - unit id ++ * port - port id ++ * enable - admin configuration of PHY interface ++ * Output: ++ * None ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - invalid parameter ++ * Note: ++ * None ++ */ ++extern a_uint32_t ++phy_common_enable_set(a_uint32_t unit, a_uint32_t port, rtk_enable_t enable); ++/* Function Name: ++ * phy_common_enable_get ++ * Description: ++ * Get PHY interface status of the specific port ++ * Input: ++ * unit - unit id ++ * port - port id ++ * enable - admin configuration of PHY interface ++ * Output: ++ * None ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - invalid parameter ++ * Note: ++ * None ++ */ ++a_uint32_t ++phy_common_enable_get(a_uint32_t unit, a_uint32_t port, rtk_enable_t *enable); ++ ++/* Function Name: ++ * phy_common_speed_get ++ * Description: ++ * Get PHY negotiated speed of the specific port ++ * Input: ++ * unit - unit id ++ * port - port id ++ * pSpeed - PHY negotiated speed ++ * Output: ++ * None ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - invalid parameter ++ * Note: ++ * None ++ */ ++extern a_uint32_t ++phy_common_speed_get(a_uint32_t unit, a_uint32_t port, a_uint32_t *pSpeed); ++ ++/* Function Name: ++ * phy_common_speedStatusResReg_get ++ * Description: ++ * Get PHY operational link speed status from proprietary register ++ * Input: ++ * unit - unit id ++ * port - port id ++ * Output: ++ * pSpeed - pointer to PHY operational link speed ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - Failed ++ * Note: ++ * Only PHY that supports proprietary resolution register can use this driver! ++ */ ++extern a_uint32_t ++phy_common_speedStatusResReg_get(a_uint32_t unit, a_uint32_t port, rtk_port_speed_t *pSpeed); ++ ++/* Function Name: ++ * phy_common_speedDuplexStatusResReg_get ++ * Description: ++ * Get PHY operational link speed-duplex status from proprietary register ++ * Input: ++ * unit - unit id ++ * port - port id ++ * Output: ++ * pSpeed - pointer to PHY operational link speed ++ * pDuplex - pointer to PHY operational link duplex ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - Failed ++ * Note: ++ * Only PHY that supports proprietary resolution register can use this driver! ++ */ ++extern a_uint32_t ++phy_common_speedDuplexStatusResReg_get(a_uint32_t unit, a_uint32_t port, rtk_port_speed_t *pSpeed, rtk_port_duplex_t *pDuplex); ++ ++/* Function Name: ++ * phy_common_reg_get ++ * Description: ++ * Get PHY registers. ++ * Input: ++ * unit - unit id ++ * port - port id ++ * page - PHY page ++ * phy_reg - PHY register ++ * Output: ++ * pData - pointer buffer of read data ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - Failed ++ * Note: ++ * 1. port valid range is 0 ~ 27 ++ * 2. page valid range is 0 ~ 31 ++ * 3. phy_reg valid range is 0 ~ 31 ++ */ ++extern a_uint32_t ++phy_common_reg_get(a_uint32_t unit, a_uint32_t port, a_uint32_t page, a_uint32_t phy_reg, a_uint32_t *pData); ++ ++/* Function Name: ++ * phy_common_reg_set ++ * Description: ++ * Set PHY registers. ++ * Input: ++ * unit - unit id ++ * port - port id ++ * page - PHY page ++ * phy_reg - PHY register ++ * data - write data ++ * Output: ++ * None ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - Failed ++ * Note: ++ * 1. port valid range is 0 ~ 27 ++ * 2. page valid range is 0 ~ 31 ++ * 3. phy_reg valid range is 0 ~ 31 ++ */ ++extern a_uint32_t ++phy_common_reg_set(a_uint32_t unit, a_uint32_t port, a_uint32_t page, a_uint32_t phy_reg, a_uint32_t data); ++ ++/* Function Name: ++ * phy_common_reg_park_get ++ * Description: ++ * Get PHY registers. ++ * Input: ++ * unit - unit id ++ * port - port id ++ * page - PHY page ++ * parkPage - PHY park page ++ * phy_reg - PHY register ++ * Output: ++ * pData - pointer buffer of read data ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - Failed ++ * Note: ++ * 1. port valid range is 0 ~ 27 ++ * 2. page valid range is 0 ~ 31 ++ * 3. phy_reg valid range is 0 ~ 31 ++ */ ++extern a_uint32_t ++phy_common_reg_park_get(a_uint32_t unit, a_uint32_t port, a_uint32_t page, a_uint32_t parkPage, a_uint32_t phy_reg, a_uint32_t *pData); ++ ++ ++/* Function Name: ++ * phy_common_reg_park_set ++ * Description: ++ * Set PHY registers. ++ * Input: ++ * unit - unit id ++ * port - port id ++ * page - PHY page ++ * parkPage - PHY park page ++ * phy_reg - PHY register ++ * data - write data ++ * Output: ++ * None ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - Failed ++ * Note: ++ * 1. port valid range is 0 ~ 27 ++ * 2. page valid range is 0 ~ 31 ++ * 3. phy_reg valid range is 0 ~ 31 ++ */ ++extern a_uint32_t ++phy_common_reg_park_set(a_uint32_t unit, a_uint32_t port, a_uint32_t page, a_uint32_t parkPage, a_uint32_t phy_reg, a_uint32_t data); ++ ++ ++/* Function Name: ++ * phy_common_reg_mmd_portmask_set ++ * Description: ++ * Set PHY registers in those portmask. ++ * Input: ++ * unit - unit id ++ * portmask - portmask ++ * mmdAddr - mmd device address ++ * mmdReg - mmd reg id ++ * data - write data ++ * Output: ++ * None ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - Failed ++ * Note: ++ * 1. portmask valid range is bit 0 ~ 27 ++ * 2. page valid range is 0 ~ 31 ++ * 3. phy_reg valid range is 0 ~ 31 ++ */ ++extern a_uint32_t ++phy_common_reg_mmd_portmask_set( ++ a_uint32_t unit, ++ rtk_portmask_t portmask, ++ a_uint32_t mmdAddr, ++ a_uint32_t mmdReg, ++ a_uint32_t data); ++ ++ ++/* Function Name: ++ * phy_common_reg_extParkPage_get ++ * Description: ++ * Get PHY registers. ++ * Input: ++ * unit - unit id ++ * port - port id ++ * mainPage - main page id ++ * extPage - extension page id ++ * parkPage - parking page id ++ * phy_reg - PHY register ++ * Output: ++ * pData - pointer buffer of read data ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - Failed ++ * Note: ++ * 1. port valid range is 0 ~ 27 ++ * 2. page valid range is 0 ~ 31 ++ * 3. phy_reg valid range is 0 ~ 31 ++ */ ++extern a_uint32_t ++phy_common_reg_extParkPage_get( ++ a_uint32_t unit, ++ a_uint32_t port, ++ a_uint32_t mainPage, ++ a_uint32_t extPage, ++ a_uint32_t parkPage, ++ a_uint32_t phy_reg, ++ a_uint32_t *pData); ++ ++ ++/* Function Name: ++ * phy_common_reg_extParkPage_set ++ * Description: ++ * Set PHY registers. ++ * Input: ++ * unit - unit id ++ * port - port id ++ * mainPage - main page id ++ * extPage - extension page id ++ * parkPage - parking page id ++ * phy_reg - PHY register ++ * data - write data ++ * Output: ++ * None ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - Failed ++ * Note: ++ * 1. port valid range is 0 ~ 27 ++ * 2. page valid range is 0 ~ 31 ++ * 3. phy_reg valid range is 0 ~ 31 ++ */ ++extern a_uint32_t ++phy_common_reg_extParkPage_set( ++ a_uint32_t unit, ++ a_uint32_t port, ++ a_uint32_t mainPage, ++ a_uint32_t extPage, ++ a_uint32_t parkPage, ++ a_uint32_t phy_reg, ++ a_uint32_t data); ++ ++/* Function Name: ++ * phy_common_extParkPage_portmask_set ++ * Description: ++ * Set PHY registers in those portmask. ++ * Input: ++ * unit - unit id ++ * portmask - portmask ++ * mainPage - main page id ++ * extPage - extension page id ++ * parkPage - parking page id ++ * phy_reg - PHY register ++ * data - write data ++ * Output: ++ * None ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - Failed ++ * Note: ++ * 1. portmask valid range is bit 0 ~ 27 ++ * 2. page valid range is 0 ~ 31 ++ * 3. phy_reg valid range is 0 ~ 31 ++ */ ++extern a_uint32_t ++phy_common_reg_extParkPage_portmask_set( ++ a_uint32_t unit, ++ rtk_portmask_t portmask, ++ a_uint32_t mainPage, ++ a_uint32_t extPage, ++ a_uint32_t parkPage, ++ a_uint32_t phy_reg, ++ a_uint32_t data); ++ ++ ++a_uint32_t rtl_phy_driver_register(void); ++ ++/* Function Name: ++ * phy_common_masterSlave_get ++ * Description: ++ * Get PHY configuration of master/slave mode of the specific port ++ * Input: ++ * unit - unit id ++ * port - port id ++ * Output: ++ * pMasterSlaveCfg - pointer to the PHY master slave configuration ++ * pMasterSlaveActual - pointer to the PHY master slave actual link status ++ * Return: ++ * RT_ERR_OK ++ * RT_ERR_FAILED ++ * RT_ERR_PORT_ID - invalid port id ++ * RT_ERR_NULL_POINTER - input parameter may be null pointer ++ * Note: ++ * This function only works on giga/ 10g port to get its master/slave mode configuration. ++ */ ++extern a_uint32_t ++phy_common_masterSlave_get(a_uint32_t unit, a_uint32_t port, rtk_port_masterSlave_t *pMasterSlaveCfg, rtk_port_masterSlave_t *pMasterSlaveActual); ++ ++/* Function Name: ++ * phy_common_masterSlave_set ++ * Description: ++ * Set PHY configuration of master/slave mode of the specific port ++ * Input: ++ * unit - unit id ++ * port - port id ++ * masterSlave - PHY master slave configuration ++ * Output: ++ * None ++ * Return: ++ * RT_ERR_OK ++ * RT_ERR_FAILED ++ * RT_ERR_PORT_ID - invalid port id ++ * RT_ERR_INPUT - invalid input parameter ++ * Note: ++ * None ++ */ ++extern a_uint32_t ++phy_common_masterSlave_set(a_uint32_t unit, a_uint32_t port, rtk_port_masterSlave_t masterSlave); ++ ++ ++/* Function Name: ++ * phy_common_masterSlaveMmd_get ++ * Description: ++ * Get PHY configuration of master/slave mode of the specific port ++ * Input: ++ * unit - unit id ++ * port - port id ++ * Output: ++ * pMasterSlaveCfg - pointer to the PHY master slave configuration ++ * pMasterSlaveActual - pointer to the PHY master slave actual link status ++ * Return: ++ * RT_ERR_OK ++ * RT_ERR_FAILED ++ * RT_ERR_PORT_ID - invalid port id ++ * RT_ERR_NULL_POINTER - input parameter may be null pointer ++ * Note: ++ * This function only works on giga/ 10g port to get its master/slave mode configuration. ++ */ ++extern a_uint32_t ++phy_common_masterSlaveMmd_get( ++ a_uint32_t unit, ++ a_uint32_t port, ++ rtk_port_masterSlave_t *pMasterSlaveCfg, ++ rtk_port_masterSlave_t *pMasterSlaveActual); ++ ++/* Function Name: ++ * phy_common_reset_set ++ * Description: ++ * Set PHY standard register Reset bit (0.15). ++ * Input: ++ * unit - unit id ++ * port - port id ++ * Output: ++ * None ++ * Return: ++ * RT_ERR_OK ++ * RT_ERR_FAILED ++ * Note: ++ * None ++ */ ++extern a_uint32_t ++phy_common_reset_set(a_uint32_t unit, a_uint32_t port); ++ ++ ++ ++/* Function Name: ++ * phy_common_loopback_get ++ * Description: ++ * Get PHY Loopback mode of the specific port ++ * Input: ++ * unit - unit id ++ * port - port id ++ * pEnable -loopback mode status; ++ * Output: ++ * None ++ * Return: ++ * RT_ERR_OK ++ * RT_ERR_FAILED ++ * Note: ++ * None ++ */ ++extern a_uint32_t ++phy_common_loopback_get(a_uint32_t unit, a_uint32_t port, rtk_enable_t *pEnable); ++ ++/* Function Name: ++ * phy_common_loopback_set ++ * Description: ++ * Set PHY Loopback mode of the specific port ++ * Input: ++ * unit - unit id ++ * port - port id ++ * enable - ENABLED: Enable loopback; ++ * DISABLED: Disable loopback. PHY back to normal operation. ++ * Output: ++ * None ++ * Return: ++ * RT_ERR_OK ++ * RT_ERR_FAILED ++ * Note: ++ * None ++ */ ++extern a_uint32_t ++phy_common_loopback_set(a_uint32_t unit, a_uint32_t port, rtk_enable_t enable); ++ ++/* Function Name: ++ * phy_field_read ++ * Description: ++ * Read PHY register field configuration ++ * Input: ++ * unit - unit id ++ * port - port id ++ * page - page number ++ * reg - register ++ * endBit - end bit of configure field ++ * startBit - start bit of configure field ++ * Output: ++ * data - PHY register field Configuration ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - Failed ++ * Note: ++ * None ++ */ ++a_uint32_t ++phy_field_read(a_uint32_t unit, a_uint32_t port, a_uint32_t page, a_uint32_t reg, ++ a_uint32_t endBit, a_uint32_t startBit, a_uint32_t *data); ++ ++/* Function Name: ++ * phy_field_write ++ * Description: ++ * Write PHY register field configuration ++ * Input: ++ * unit - unit id ++ * port - port id ++ * page - page number ++ * reg - register ++ * endBit - end bit of configure field ++ * startBit - start bit of configure field ++ * data - PHY register field Configuration ++ * Output: ++ * None ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - Failed ++ * Note: ++ * None ++ */ ++a_uint32_t ++phy_field_write(a_uint32_t unit, a_uint32_t port, a_uint32_t page, a_uint32_t reg, ++ a_uint32_t endBit, a_uint32_t startBit, a_uint32_t data); ++ ++/* Function Name: ++ * phy_common_eyeMonPixel_get ++ * Description: ++ * PHY SerDes eye-monitor utility to set val to the database according to x,y,z ++ * Input: ++ * xAxis - x position ++ * yAxis - y position ++ * frameNum - frame number ++ * Output: ++ * pDb - 3 dimension a_uint32_t array database. E.g. a_uint32_t a[RTK_EYE_MON_FRAME_MAX][RTK_EYE_MON_X_MAX][RTK_EYE_MON_Y_MAX] ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - Failed ++ * Note: ++ * None ++ */ ++extern a_uint32_t ++phy_common_eyeMonPixel_get(a_uint32_t xAxis, a_uint32_t yAxis, a_uint32_t frameNum, void *pDb, a_uint32_t val); ++ ++ ++/* Function Name: ++ * phy_common_c45_enable_set ++ * Description: ++ * Set PHY interface status of the specific port ++ * Input: ++ * unit - unit id ++ * port - port id ++ * enable - admin configuration of PHY interface ++ * Output: ++ * None ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - invalid parameter ++ * Note: ++ * None ++ */ ++extern a_uint32_t ++phy_common_c45_enable_set(a_uint32_t unit, a_uint32_t port, rtk_enable_t enable); ++ ++/* Function Name: ++ * phy_common_c45_enable_get ++ * Description: ++ * Get PHY interface state enable/disable of the specific port ++ * Input: ++ * unit - unit id ++ * port - port id ++ * Output: ++ * pEnable - pointer to admin configuration of PHY interface ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - invalid parameter ++ * Note: ++ * None ++ */ ++extern a_uint32_t ++phy_common_c45_enable_get(a_uint32_t unit, a_uint32_t port, rtk_enable_t *pEnable); ++ ++/* Function Name: ++* phy_common_c45_linkStatus_get ++* Description: ++* Get PHY link status from standard register (1.2). ++* Input: ++* unit - unit id ++* port - port id ++* Output: ++* pStatus - pointer to the link status ++* Return: ++* RT_ERR_OK ++* RT_ERR_FAILED ++* Note: ++* The Link Status bit (Status Register 1.2) has LL (Latching Low) attribute ++* for link failure. Please refer IEEE 802.3 for detailed. ++*/ ++extern a_uint32_t ++phy_common_c45_linkStatus_get(a_uint32_t unit, a_uint32_t port, rtk_port_linkStatus_t *pStatus); ++ ++/* Function Name: ++ * phy_common_c45_loopback_get ++ * Description: ++ * Get PHY Loopback mode of the specific port ++ * Input: ++ * unit - unit id ++ * port - port id ++ * pEnable -loopback mode status; ++ * Output: ++ * None ++ * Return: ++ * RT_ERR_OK ++ * RT_ERR_FAILED ++ * Note: ++ * None ++ */ ++extern a_uint32_t ++phy_common_c45_loopback_get(a_uint32_t unit, a_uint32_t port, rtk_enable_t *pEnable); ++ ++/* Function Name: ++ * phy_common_c45_loopback_set ++ * Description: ++ * Set PHY Loopback mode of the specific port ++ * Input: ++ * unit - unit id ++ * port - port id ++ * enable - ENABLED: Enable loopback; ++ * DISABLED: Disable loopback. PHY back to normal operation. ++ * Output: ++ * None ++ * Return: ++ * RT_ERR_OK ++ * RT_ERR_FAILED ++ * Note: ++ * None ++ */ ++extern a_uint32_t ++phy_common_c45_loopback_set(a_uint32_t unit, a_uint32_t port, rtk_enable_t enable); ++ ++ ++/* Function Name: ++ * phy_common_c45_eeeEnable_get ++ * Description: ++ * Get enable status of EEE function in the specified port. ++ * Input: ++ * unit - unit id ++ * port - port id ++ * Output: ++ * pEnable - pointer to enable status of EEE ++ * Return: ++ * RT_ERR_OK ++ * RT_ERR_FAILED ++ * RT_ERR_UNIT_ID - invalid unit id ++ * RT_ERR_PORT_ID - invalid port id ++ * RT_ERR_NULL_POINTER - input parameter may be null pointer ++ * Note: ++ * None ++ */ ++extern a_uint32_t ++phy_common_c45_eeeEnable_get(a_uint32_t unit, a_uint32_t port, rtk_enable_t *pEnable); ++ ++/* Function Name: ++ * phy_common_c45_eeeEnable_set ++ * Description: ++ * Set enable status of EEE function in the specified port. ++ * Input: ++ * unit - unit id ++ * port - port id ++ * enable - enable status of EEE ++ * Output: ++ * None ++ * Return: ++ * RT_ERR_OK ++ * RT_ERR_FAILED ++ * RT_ERR_NOT_INIT - The module is not initial ++ * RT_ERR_UNIT_ID - invalid unit id ++ * RT_ERR_PORT_ID - invalid port id ++ * RT_ERR_INPUT - invalid input parameter ++ * Note: ++ * None ++ */ ++extern a_uint32_t ++phy_common_c45_eeeEnable_set(a_uint32_t unit, a_uint32_t port, rtk_enable_t enable); ++ ++ ++/* Function Name: ++ * phy_common_c45_speedDuplexStatus_get ++ * Description: ++ * Get PHY operational link speed-duplex status. ++ * Input: ++ * unit - unit id ++ * port - port id ++ * Output: ++ * pSpeed - pointer to PHY operational link speed ++ * pDuplex - pointer to PHY operational link duplex ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - Failed ++ * Note: ++ * none ++ */ ++extern a_uint32_t ++phy_common_c45_speedDuplexStatus_get(a_uint32_t unit, a_uint32_t port, rtk_port_speed_t *pSpeed, rtk_port_duplex_t *pDuplex); ++ ++/* Function Name: ++ * phy_common_c45_speedStatusResReg_get ++ * Description: ++ * Get PHY operational link speed status from proprietary register ++ * Input: ++ * unit - unit id ++ * port - port id ++ * Output: ++ * pSpeed - pointer to PHY operational link speed ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - Failed ++ * Note: ++ * Only PHY that supports proprietary resolution register can use this driver! ++ */ ++extern a_uint32_t ++phy_common_c45_speedStatusResReg_get(a_uint32_t unit, a_uint32_t port, rtk_port_speed_t *pSpeed); ++ ++ ++/* Function Name: ++ * phy_common_c45_speedDuplexStatusResReg_get ++ * Description: ++ * Get operational link speed-duplex status from proprietary register ++ * Input: ++ * unit - unit id ++ * port - port id ++ * Output: ++ * pSpeed - pointer to PHY operational link speed ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - Failed ++ * Note: ++ * Only PHY that supports proprietary resolution register can use this driver! ++ */ ++extern a_uint32_t ++phy_common_c45_speedDuplexStatusResReg_get(a_uint32_t unit, a_uint32_t port, rtk_port_speed_t *pSpeed, rtk_port_duplex_t *pDuplex); ++ ++/* Function Name: ++ * phy_common_autoNegoAbility_get ++ * Description: ++ * Get ability advertisement for auto negotiation of the specific port ++ * Input: ++ * unit - unit id ++ * port - port id ++ * Output: ++ * pAbility - pointer to PHY auto negotiation ability ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - invalid parameter ++ * Note: ++ * None ++ */ ++extern a_uint32_t ++phy_common_autoNegoAbility_get(a_uint32_t unit, a_uint32_t port, rtk_port_phy_ability_t *pAbility); ++ ++/* Function Name: ++ * phy_common_autoNegoAbility_set ++ * Description: ++ * Set ability advertisement for auto negotiation of the specific port ++ * Input: ++ * unit - unit id ++ * port - port id ++ * pAbility - auto negotiation ability that is going to set to PHY ++ * Output: ++ * None ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - invalid parameter ++ * Note: ++ * None ++ */ ++extern a_uint32_t ++phy_common_autoNegoAbility_set(a_uint32_t unit, a_uint32_t port, rtk_port_phy_ability_t *pAbility); ++ ++/* Function Name: ++ * phy_common_speed_set ++ * Description: ++ * Set speed mode status of the specific port ++ * Input: ++ * unit - unit id ++ * port - port id ++ * speed - link speed status 10/100/1000 ++ * Output: ++ * None ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - invalid parameter ++ * RT_ERR_CHIP_NOT_SUPPORTED - copper media chip is not supported Force-1000 ++ * Note: ++ * None ++ */ ++extern a_uint32_t ++phy_common_speed_set(a_uint32_t unit, a_uint32_t port, rtk_port_speed_t speed); ++ ++extern sw_error_t phy_826xb_duplex_set(a_uint32_t unit, a_uint32_t port, fal_port_duplex_t duplex); ++extern sw_error_t phy_826xb_speed_set(a_uint32_t unit, a_uint32_t port, fal_port_speed_t speed); ++#endif /* __HAL_PHY_PHY_COMMON_H__ */ +diff --git a/include/hsl/phy/phy_rtl826xb.h b/include/hsl/phy/phy_rtl826xb.h +new file mode 100644 +index 00000000..b5893ae5 +--- /dev/null ++++ b/include/hsl/phy/phy_rtl826xb.h +@@ -0,0 +1,320 @@ ++/* ++ * Copyright (C) 2021 Realtek Semiconductor Corp. ++ * All Rights Reserved. ++ * ++ * This program is the proprietary software of Realtek Semiconductor ++ * Corporation and/or its licensors, and only be used, duplicated, ++ * modified or distributed under the authorized license from Realtek. ++ * ++ * ANY USE OF THE SOFTWARE OTHER THAN AS AUTHORIZED UNDER ++ * THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. ++ * ++ * $Revision: $ ++ * $Date: $ ++ * ++ * Purpose : PHY 826XB/8261N Driver APIs. ++ * ++ * Feature : PHY 826XB/8261N Driver APIs. ++ * ++ */ ++#ifndef __HAL_PHY_PHY_RTL826XB_H__ ++#define __HAL_PHY_PHY_RTL826XB_H__ ++ ++/* ++ * Include Files ++ */ ++#include "phy_common.h" ++ ++/* ++ * Symbol Definition ++ */ ++//#define PHY_826X_CONSTRUCT_BROADCAST 1 ++ ++typedef unsigned char uint8; ++typedef signed char int8; ++typedef int uint16; ++typedef int int16; ++typedef unsigned int uint32; ++typedef signed int int32; ++ ++ ++#define RTLBIT_0 0x0001 ++#define RTLBIT_1 0x0002 ++#define RTLBIT_2 0x0004 ++#define RTLBIT_3 0x0008 ++#define RTLBIT_4 0x0010 ++#define RTLBIT_5 0x0020 ++#define RTLBIT_6 0x0040 ++#define RTLBIT_7 0x0080 ++#define RTLBIT_8 0x0100 ++#define RTLBIT_9 0x0200 ++#define RTLBIT_10 0x0400 ++#define RTLBIT_11 0x0800 ++#define RTLBIT_12 0x1000 ++#define RTLBIT_13 0x2000 ++#define RTLBIT_14 0x4000 ++#define RTLBIT_15 0x8000 ++ ++ ++ ++ ++#define REG32_FIELD_SET(_data, _val, _fOffset, _fMask) ((_data & ~(_fMask)) | ((_val << (_fOffset)) & (_fMask))) ++#define REG32_FIELD_GET(_data, _fOffset, _fMask) ((_data & (_fMask)) >> (_fOffset)) ++ ++#define RTL826XB_MII_ADDR_C45 (1<<30) ++#define RTL826XB_REG_ADDRESS(dev_ad, reg_num) (RTL826XB_MII_ADDR_C45 |\ ++ ((dev_ad & 0x1f) << 16) | (reg_num & 0xFFFF)) ++ ++ /* Speed, bits 9:7 */ ++#define RTL_STATUS_SPEED_MASK 0xc000 ++ ++#define RTK_MAX_NUM_OF_UNIT 16 ++#define RTK_MAX_PORT_PER_UNIT 64 ++ ++ ++typedef enum rtk_phy_ctrl_e { ++ RTK_PHY_CTRL_AN_COMPLETE, /* status of auto-negotiation complete, R */ ++ RTK_PHY_CTRL_LED_1_MODE, /* LED mode for LED1, RW */ ++ RTK_PHY_CTRL_LED_2_MODE, /* LED mode for LED2, RW */ ++ RTK_PHY_CTRL_LED_3_MODE, /* LED mode for LED3, RW */ ++ RTK_PHY_CTRL_LED_4_MODE, /* LED mode for LED4, RW */ ++ RTK_PHY_CTRL_LED_5_MODE, /* LED mode for LED5, RW */ ++ RTK_PHY_CTRL_LED_6_MODE, /* LED mode for LED6, RW */ ++ RTK_PHY_CTRL_LED_CFG_FLASH_RATE, /* LED flash rate, RW */ ++ RTK_PHY_CTRL_LED_CFG_BLINK_RATE, /* LED blink rate, RW */ ++ RTK_PHY_CTRL_LED_1_CFG_ACTIVE_LOW, /* active low/high for LED1, RW */ ++ RTK_PHY_CTRL_LED_2_CFG_ACTIVE_LOW, /* active low/high for LED2, RW */ ++ RTK_PHY_CTRL_LED_3_CFG_ACTIVE_LOW, /* active low/high for LED3, RW */ ++ RTK_PHY_CTRL_LED_4_CFG_ACTIVE_LOW, /* active low/high for LED4, RW */ ++ RTK_PHY_CTRL_LED_5_CFG_ACTIVE_LOW, /* active low/high for LED5, RW */ ++ RTK_PHY_CTRL_LED_6_CFG_ACTIVE_LOW, /* active low/high for LED6, RW */ ++ RTK_PHY_CTRL_LED_1_CFG_FORCE, /* LED force mode for LED1, RW */ ++ RTK_PHY_CTRL_LED_2_CFG_FORCE, /* LED force mode for LED2, RW */ ++ RTK_PHY_CTRL_LED_3_CFG_FORCE, /* LED force mode for LED3, RW */ ++ RTK_PHY_CTRL_LED_4_CFG_FORCE, /* LED force mode for LED4, RW */ ++ RTK_PHY_CTRL_LED_5_CFG_FORCE, /* LED force mode for LED5, RW */ ++ RTK_PHY_CTRL_LED_6_CFG_FORCE, /* LED force mode for LED6, RW */ ++ RTK_PHY_CTRL_NBASET_802P3BZ_MASK, /* mask 802.3bz and advert NBASE-T only, RW*/ ++ RTK_PHY_CTRL_NBASET, /* NBASET-T enable/disable, RW */ ++ RTK_PHY_CTRL_NBASET_STATUS, /* link is operated at NBASET-T, R */ ++ RTK_PHY_CTRL_LOOPBACK_INTERNAL_PMA, /* internal loopback at PMA, RW */ ++ RTK_PHY_CTRL_LOOPBACK_REMOTE, /* remote loopback, RW */ ++ RTK_PHY_CTRL_SERDES_RX_POLARITY, /* SerDes RX polarity, RW */ ++ RTK_PHY_CTRL_SERDES_TX_POLARITY, /* SerDes TX polarity, RW */ ++ RTK_PHY_CTRL_MDI_POLARITY_SWAP, /* MDI polarity swap, RW */ ++ RTK_PHY_CTRL_MDI_INVERSE, /* MDI pin sequence inverse, RW */ ++ RTK_PHY_CTRL_RAPID_LINK_FAULT_DETECT, /* rapid link fault detection enable/disable, RW */ ++ RTK_PHY_CTRL_PREAMBLE_RECOVERY, /* preamble-recovery enable, RW */ ++ RTK_PHY_CTRL_SYNCE, /* SyncE enable, RW */ ++ RTK_PHY_CTRL_SYNCE_0_CLOCK_FREQ, /* clock frequency for SyncE0, RW */ ++ RTK_PHY_CTRL_SYNCE_1_CLOCK_FREQ, /* clock frequency for SyncE1, RW */ ++ RTK_PHY_CTRL_SYNCE_0_RECOVERY_PHY, /* recovery PHY port for SyncE0, RW */ ++ RTK_PHY_CTRL_SYNCE_1_RECOVERY_PHY, /* recovery PHY port for SyncE1, RW */ ++ RTK_PHY_CTRL_SYNCE_0_IDLE_MODE, /* idle mode for SyncE0, RW */ ++ RTK_PHY_CTRL_SYNCE_1_IDLE_MODE, /* idle mode for SyncE1, RW */ ++ RTK_PHY_CTRL_TEMP, /* read temperature from thermal meter(bit[18]:sign; [17:10]:integer; [9:0]:decimal), R*/ ++ RTK_PHY_CTRL_TEMP_THRESHOLD_HIGH_LOWER, /* thermal high threshold, RW([18]:sign; [17:10]:integer(degrees Celsius); [9:0]:decimal), for trigger interrupt when temperature lower then this threshold */ ++ RTK_PHY_CTRL_TEMP_THRESHOLD_HIGH_HIGHER, /* thermal high threshold, RW([18]:sign; [17:10]:integer(degrees Celsius); [9:0]:decimal), for trigger interrupt when temperature higher then this threshold */ ++ RTK_PHY_CTRL_TEMP_THRESHOLD_LOW_LOWER, /* thermal low threshold, RW([18]:sign; [17:10]:integer(degrees Celsius); [9:0]:decimal), for trigger interrupt when temperature lower then this threshold */ ++ RTK_PHY_CTRL_TEMP_THRESHOLD_LOW_HIGHER, /* thermal low threshold, RW([18]:sign; [17:10]:integer(degrees Celsius); [9:0]:decimal), for trigger interrupt when temperature higher then this threshold */ ++ RTK_PHY_CTRL_FAST_RETRAIN, /* enable fast retrain ability, RW */ ++ RTK_PHY_CTRL_FAST_RETRAIN_LPCOUNT, /* Counts the number of fast retrains requested by the link partner, R */ ++ RTK_PHY_CTRL_FAST_RETRAIN_LDCOUNT, /* Counts the number of fast retrains requested by the local device, R */ ++ RTK_PHY_CTRL_FAST_RETRAIN_STATUS, /* fast retrain capable at current link(1 for Both local and link-partner have fast retrain capability of current speed), R */ ++ RTK_PHY_CTRL_FAST_RETRAIN_NFR, /* enable NFR ability, RW */ ++ RTK_PHY_CTRL_FAST_RETRAIN_NFR_STATUS, /* NFR capable at current link, R */ ++ RTK_PHY_CTRL_COUNTER_CLEAR, /* clear counter, W */ ++ RTK_PHY_CTRL_SERDES_MODE, /* config SerDes mode, RW */ ++ RTK_PHY_CTRL_SERDES_UPDTAE, /* update SerDes setting for those modes can't auto change speed when link up(do this after MAC side serdes mode change), W */ ++ RTK_PHY_CTRL_SERDES_USXGMII_AN, /* SerDes auto-negotiation enable(1)/disable(0) for USXGMII mode, RW */ ++ RTK_PHY_CTRL_SERDES_SGMII_AN, /* SerDes auto-negotiation enable(1)/disable(0) for SGMII mode, RW */ ++ RTK_PHY_CTRL_SERDES_BASEX_AN, /* SerDes auto-negotiation enable(1)/disable(0) for 1000BASE-X/2.5GBASE-X/5GBASE-X mode, RW */ ++ RTK_PHY_CTRL_SERDES_XSGMII_AN, /* SerDes auto-negotiation enable(1)/disable(0) for XSGMII mode, RW */ ++ RTK_PHY_CTRL_SNR_CH0, /* Get current SNR value(MSE) of Channel 0, R */ /********************************************************************************************************/ ++ RTK_PHY_CTRL_SNR_CH1, /* Get current SNR value(MSE) of Channel 1, R */ /* SNR value convertion */ ++ RTK_PHY_CTRL_SNR_CH2, /* Get current SNR value(MSE) of Channel 2, R */ /********************************************************************************************************/ ++ RTK_PHY_CTRL_SNR_CH3, /* Get current SNR value(MSE) of Channel 3, R */ /* For 10G/5G/2.5G: | For 1G/100M: */ ++ RTK_PHY_CTRL_SNR_THRESHOLD_10G_MASTER, /* SNR threshold(MSE) for 10G Master, RW */ /* bit [15:11] is integer; [10:0] is decimal | bit [15:0] is 16 bits LSB of 17-bit decimal value */ ++ RTK_PHY_CTRL_SNR_THRESHOLD_10G_SLAVE, /* SNR threshold(MSE) for 10G Slave, RW */ /* SNR = 10*log10(81/MSE) | SNR = 10*log10(2/mse) */ ++ RTK_PHY_CTRL_SNR_THRESHOLD_5G_MASTER, /* SNR threshold(MSE) for 5G Master, RW */ /* MSE = 81/(pow(10,(SNR/10)) | MSE = 2/(pow (10,(snr/10))) */ ++ RTK_PHY_CTRL_SNR_THRESHOLD_5G_SLAVE, /* SNR threshold(MSE) for 5G Slave, RW */ /* Example: | Example: */ ++ RTK_PHY_CTRL_SNR_THRESHOLD_2P5G_MASTER, /* SNR threshold(MSE) for 2.5G Master, RW */ /* 0x2E5= 0000 0.010 1110 0101= 0.361816 | 0x1000= 0.0 0001 0000 0000 0000= 0.031250 */ ++ RTK_PHY_CTRL_SNR_THRESHOLD_2P5G_SLAVE, /* SNR threshold(MSE) for 2.5G Slave, RW */ /* SNR= 10*log10(81/0.3618)= 23.499968 db | SNR= 10*log10(2/0.03125)= 18.061800 db */ ++ RTK_PHY_CTRL_SNR_THRESHOLD_1G, /* SNR threshold(MSE) for 1G/100M, RW */ /********************************************************************************************************/ ++ RTK_PHY_CTRL_REINIT, /* Set 1 to reset and reinit port, W */ ++ RTK_PHY_CTRL_SKEW_PAIR_B, /* Get current skew delay on pair B with respect to physical pair A*/ ++ RTK_PHY_CTRL_SKEW_PAIR_C, /* Get current skew delay on pair B with respect to physical pair A*/ ++ RTK_PHY_CTRL_SKEW_PAIR_D, /* Get current skew delay on pair B with respect to physical pair A*/ ++ RTK_PHY_CTRL_SERDES_LOOPBACK_REMOTE, /* remote loopback on SerDes, RW */ ++ RTK_PHY_CTRL_RTCT_CABLE_TYPE, /* RTCT cable type, W */ ++ RTK_PHY_CTRL_RTCT_CABLE_FACTOR, /* RTCT cable factor value to caculate cable length, set 0 to use driver default value, RW */ ++ RTK_PHY_CTRL_SERDES_EYE_PARAM_TYPE, /* serdes mode target for rtk_port_phySdsEyeParam_set/get API, RW */ ++ RTK_PHY_CTRL_PTP, /* PTP enable, RW */ ++ RTK_PHY_CTRL_PTP_DURATION_THRESHOLD, /* PTP duration threahold(ns) for trigger time operation (falling edge and rising edge), RW */ ++ RTK_PHY_CTRL_PTP_REFTIME_TOD_DELAY, /* PTP ToD delay(ns) for reference time in 16-bit 2's complement format, RW */ ++ RTK_PHY_CTRL_PTP_PORT_ROLE, /* PTP port role, RW */ ++ RTK_PHY_CTRL_PTP_TX_IMBAL, /* PTP TX IMBAL(ns), egressTimestamp = egressMeasuredTimestamp + TX_IMBAL, RW */ ++ RTK_PHY_CTRL_PTP_RX_IMBAL, /* PTP RX IMBAL(ns), ingressTimestamp = ingressMeasuredTimestamp - RX_IMBAL, RW */ ++ RTK_PHY_CTRL_PTP_CLOCK_SRC, /* PTP clock source select external/internal clock, RW */ ++ RTK_PHY_CTRL_LINKDOWN_CNT, /* get link down counter (read clear), R */ ++ RTK_PHY_CTRL_FATAL_STATUS, /* get fatal error status bitmap, R */ ++ RTK_PHY_CTRL_FATAL_STATUS_READ_CLEAR, /* get fatal error status bitmap(read clear), RC */ ++ RTK_PHY_CTRL_PTP_PLL_POW_SRC, /* PTP PLL power source select, RW*/ ++ RTK_PHY_CTRL_PTP_PLL_CLK, /* PTP PLL clock frequence select, RW*/ ++ RTK_PHY_CTRL_PTP_PLL, /* PTP PLL enable, RW*/ ++ RTK_PHY_CTRL_MACSEC_BYPASS, /* Set 1 to bypass MACsec, RW */ ++ /* Private/Debug options */ ++ RTK_PHY_CTRL_DEBUG_DUMP_DSP, /* used by rtk_phy_debug_get */ ++ RTK_PHY_CTRL_DEBUG_DUMP_DSP_INIT, /* used by rtk_phy_debug_get */ ++ RTK_PHY_CTRL_DEBUG_DUMP_COUPLING, /* used by rtk_phy_debug_get */ ++ RTK_PHY_CTRL_DEBUG_MDI_PLUG, /* get MDI link status, R */ ++ RTK_PHY_CTRL_DEBUG_MDIO_PARITY_CHK, /* get debug conuter for MDIO parity check, R */ ++ RTK_PHY_CTRL_MIIM_BCAST, /* enable/disable miim broadcast, W*/ ++ RTK_PHY_CTRL_MIIM_BCAST_PHYAD, /* set miim broadcast PHYAD, W*/ ++ RTK_PHY_CTRL_SYNCE_PLL, /* SyncE output clock source from PLL, W */ ++ RTK_PHY_CTRL_IPG_SHRINK, /* Enable PHY's IPG shrink when switch enables stacking on the port */ ++ RTK_PHY_CTRL_SERDES_USXGMII_AM_PERIOD, /* get/set SerDes AM period RW */ ++ RTK_PHY_CTRL_END ++} rtk_phy_ctrl_t; ++ ++ ++typedef enum rt_error_common_e ++{ ++ RT_ERR_FAILED = -1, /* General Error */ ++ ++ /* 0x0000xxxx for common error code */ ++ RT_ERR_OK = 0, /* 0x00000000, OK */ ++ RT_ERR_INPUT = 0xF001, /* 0x0000F001, invalid input parameter */ ++ RT_ERR_UNIT_ID, /* 0x0000F002, invalid unit id */ ++ RT_ERR_PORT_ID, /* 0x0000F003, invalid port id */ ++ RT_ERR_PORT_MASK, /* 0x0000F004, invalid port mask */ ++ RT_ERR_PORT_LINKDOWN, /* 0x0000F005, link down port status */ ++ RT_ERR_ENTRY_INDEX, /* 0x0000F006, invalid entry index */ ++ RT_ERR_NULL_POINTER, /* 0x0000F007, input parameter is null pointer */ ++ RT_ERR_QUEUE_ID, /* 0x0000F008, invalid queue id */ ++ RT_ERR_QUEUE_NUM, /* 0x0000F009, invalid queue number */ ++ RT_ERR_BUSYWAIT_TIMEOUT, /* 0x0000F00a, busy watting time out */ ++ RT_ERR_MAC, /* 0x0000F00b, invalid mac address */ ++ RT_ERR_OUT_OF_RANGE, /* 0x0000F00c, input parameter out of range */ ++ RT_ERR_CHIP_NOT_SUPPORTED, /* 0x0000F00d, functions not supported by this chip model */ ++ RT_ERR_SMI, /* 0x0000F00e, SMI error */ ++ RT_ERR_NOT_INIT, /* 0x0000F00f, The module is not initial */ ++ RT_ERR_CHIP_NOT_FOUND, /* 0x0000F010, The chip can not found */ ++ RT_ERR_NOT_ALLOWED, /* 0x0000F011, actions not allowed by the function */ ++ RT_ERR_DRIVER_NOT_FOUND, /* 0x0000F012, The driver can not found */ ++ RT_ERR_SEM_LOCK_FAILED, /* 0x0000F013, Failed to lock semaphore */ ++ RT_ERR_SEM_UNLOCK_FAILED, /* 0x0000F014, Failed to unlock semaphore */ ++ RT_ERR_THREAD_EXIST, /* 0x0000F015, Thread exist */ ++ RT_ERR_THREAD_CREATE_FAILED, /* 0x0000F016, Thread create fail */ ++ RT_ERR_FWD_ACTION, /* 0x0000F017, Invalid forwarding Action */ ++ RT_ERR_IPV4_ADDRESS, /* 0x0000F018, Invalid IPv4 address */ ++ RT_ERR_IPV6_ADDRESS, /* 0x0000F019, Invalid IPv6 address */ ++ RT_ERR_PRIORITY, /* 0x0000F01a, Invalid Priority value */ ++ RT_ERR_FID, /* 0x0000F01b, invalid fid */ ++ RT_ERR_ENTRY_NOTFOUND, /* 0x0000F01c, specified entry not found */ ++ RT_ERR_DROP_PRECEDENCE, /* 0x0000F01d, invalid drop precedence */ ++ RT_ERR_NOT_FINISH, /* 0x0000F01e, Action not finish, still need to wait */ ++ RT_ERR_TIMEOUT, /* 0x0000F01f, Time out */ ++ RT_ERR_REG_ARRAY_INDEX_1, /* 0x0000F020, invalid index 1 of register array */ ++ RT_ERR_REG_ARRAY_INDEX_2, /* 0x0000F021, invalid index 2 of register array */ ++ RT_ERR_ETHER_TYPE, /* 0x0000F022, invalid ether type */ ++ RT_ERR_MBUF_PKT_NOT_AVAILABLE, /* 0x0000F023, mbuf->packet is not available */ ++ RT_ERR_QOS_INVLD_RSN, /* 0x0000F024, invalid pkt to CPU reason */ ++ RT_ERR_CB_FUNCTION_EXIST, /* 0x0000F025, Callback function exist */ ++ RT_ERR_CB_FUNCTION_FULL, /* 0x0000F026, Callback function number is full */ ++ RT_ERR_CB_FUNCTION_NOT_FOUND, /* 0x0000F027, Callback function can not found */ ++ RT_ERR_TBL_FULL, /* 0x0000F028, The table is full */ ++ RT_ERR_TRUNK_ID, /* 0x0000F029, invalid trunk id */ ++ RT_ERR_TYPE, /* 0x0000F02a, invalid type */ ++ RT_ERR_ENTRY_EXIST, /* 0x0000F02b, entry exists */ ++ RT_ERR_CHIP_UNDEFINED_VALUE, /* 0x0000F02c, chip returned an undefined value */ ++ RT_ERR_EXCEEDS_CAPACITY, /* 0x0000F02d, exceeds the capacity of hardware */ ++ RT_ERR_ENTRY_REFERRED, /* 0x0000F02e, entry is still being referred */ ++ RT_ERR_OPER_DENIED, /* 0x0000F02f, operation denied */ ++ RT_ERR_PORT_NOT_SUPPORTED, /* 0x0000F030, functions not supported by this port */ ++ RT_ERR_SOCKET, /* 0x0000F031, socket error */ ++ RT_ERR_MEM_ALLOC, /* 0x0000F032, insufficient memory resource */ ++ RT_ERR_ABORT, /* 0x0000F033, operation aborted */ ++ RT_ERR_DEV_ID, /* 0x0000F034, invalid device id */ ++ RT_ERR_DRIVER_NOT_SUPPORTED, /* 0x0000F035, functions not supported by this driver */ ++ RT_ERR_NOT_SUPPORTED, /* 0x0000F036, functions not supported */ ++ ++ RT_ERR_COMMON_END = 0xFFFF /* The symbol is the latest symbol of common error */ ++} rt_error_common_t; ++ ++typedef struct rtk_phy_hwpatch_s ++{ ++ a_uint8_t patch_op; ++ a_uint8_t portmask; ++ a_uint16_t pagemmd; ++ a_uint16_t addr; ++ a_uint8_t msb; ++ a_uint8_t lsb; ++ a_uint16_t data; ++} rtk_phy_hwpatch_t; ++ ++typedef struct phy_rtl826xb_info_s ++{ ++ a_uint32_t sdsModeCfg[RTK_MAX_PORT_PER_UNIT]; ++ a_uint8_t rtctCable[RTK_MAX_PORT_PER_UNIT]; ++ a_uint32_t eyeParamTarget[RTK_MAX_PORT_PER_UNIT]; ++} phy_rtl826xb_info_t; ++ ++ ++#define PHY_826XB_LED_MODE_L_10G (1 << 0) ++#define PHY_826XB_LED_MODE_L_10G_LITE (1 << 1) ++#define PHY_826XB_LED_MODE_L_5G (1 << 2) ++#define PHY_826XB_LED_MODE_L_5G_LITE (1 << 3) ++#define PHY_826XB_LED_MODE_L_2P5G (1 << 4) ++#define PHY_826XB_LED_MODE_L_2P5G_LITE (1 << 5) ++#define PHY_826XB_LED_MODE_L_1G (1 << 6) ++#define PHY_826XB_LED_MODE_L_500M (1 << 7) ++#define PHY_826XB_LED_MODE_L_100M (1 << 8) ++#define PHY_826XB_LED_MODE_L_10G_FLASH (1 << 9) ++#define PHY_826XB_LED_MODE_L_10G_LITE_FLASH (1 << 10) ++#define PHY_826XB_LED_MODE_L_5G_FLASH (1 << 11) ++#define PHY_826XB_LED_MODE_L_5G_LITE_FLASH (1 << 12) ++#define PHY_826XB_LED_MODE_L_2P5G_FLASH (1 << 13) ++#define PHY_826XB_LED_MODE_L_2P5G_LITE_FLASH (1 << 14) ++#define PHY_826XB_LED_MODE_L_1G_FLASH (1 << 15) ++ ++#define PHY_826XB_LED_MODE_H_500M_FLASH (1 << 0) ++#define PHY_826XB_LED_MODE_H_100M_FLASH (1 << 1) ++#define PHY_826XB_LED_MODE_H_RX_ACT (1 << 2) ++#define PHY_826XB_LED_MODE_H_TX_ACT (1 << 3) ++#define PHY_826XB_LED_MODE_H_LITE_FLASH (1 << 4) ++#define PHY_826XB_LED_MODE_H_LITE (1 << 5) ++#define PHY_826XB_LED_MODE_H_DUPLEX (1 << 6) ++#define PHY_826XB_LED_MODE_H_MASTER (1 << 7) ++#define PHY_826XB_LED_MODE_H_TRAINING (1 << 8) ++#define PHY_826XB_LED_MODE_H_LINK_EN (1 << 9) ++ ++ ++a_uint16_t ++phy_common_general_reg_mmd_get(a_uint32_t unit, a_uint32_t port, a_uint16_t mmdAddr, a_uint16_t mmdReg); ++ ++sw_error_t ++phy_common_general_reg_mmd_set(a_uint32_t unit, a_uint32_t port, a_uint16_t mmdAddr, a_uint16_t mmdReg, a_uint16_t data); ++ ++sw_error_t ++phy_826xb_autoNegoEnable_set(a_uint32_t unit, a_uint32_t port); ++ ++sw_error_t rtl826x_phy_get_status(a_uint32_t dev_id, a_uint32_t phy_id, struct port_phy_status *phy_status); ++sw_error_t phy_826xb_poweroff(a_uint32_t dev_id, a_uint32_t phy_id); ++sw_error_t phy_826xb_poweron(a_uint32_t dev_id, a_uint32_t phy_id); ++sw_error_t phy_826xb_phy_id_get(a_uint32_t dev_id, a_uint32_t phy_id, a_uint32_t *phy_data); ++ ++struct rtl_phy_info* rtl_phy_info_get(a_uint32_t phy_addr); ++int rtl_phy_init(a_uint32_t dev_id, a_uint32_t port_bmp); ++void rtl_phydev_deinit(a_uint32_t dev_id, a_uint32_t port_id); ++void rtl_phy_driver_unregister(void); ++a_uint32_t phy_rtl826xb_patch(a_uint32_t unit, a_uint32_t port, a_uint8_t portOffset); ++sw_error_t phy_826xb_ctrl_set(a_uint32_t unit, a_uint32_t port, rtk_phy_ctrl_t ctrl_type, a_uint16_t value); ++a_int32_t phy_rtl826xb_broadcast_patch(a_uint32_t unit, a_uint32_t port, a_uint8_t portOffset); ++sw_error_t phy_common_c45_reset_set(a_uint32_t unit, a_uint32_t port); ++sw_error_t phy_826xb_autoNegoAbility_set(a_uint32_t dev_id, a_uint32_t phy_id, a_uint32_t autoneg); ++sw_error_t phy_826xb_restart_autoneg(a_uint32_t dev_id, a_uint32_t port); ++void rtl_phydev_init(a_uint32_t dev_id, a_uint32_t port_id); ++ ++ ++#endif /* __HAL_PHY_PHY_RTL826XB_H__ */ +\ No newline at end of file +diff --git a/make/linux_opt.mk b/make/linux_opt.mk +index 875d1b47..62115f32 100755 +--- a/make/linux_opt.mk ++++ b/make/linux_opt.mk +@@ -176,6 +176,10 @@ ifeq (TRUE, $(IN_AQUANTIA_PHY)) + MODULE_CFLAG += -DIN_AQUANTIA_PHY + endif + ++ifeq (TRUE, $(IN_RTL_PHY)) ++ MODULE_CFLAG += -DIN_RTL_PHY ++endif ++ + ifeq (TRUE, $(IN_QCA803X_PHY)) + MODULE_CFLAG += -DIN_QCA803X_PHY + endif +diff --git a/src/hsl/phy/Makefile b/src/hsl/phy/Makefile +index b36d7205..120b4643 100755 +--- a/src/hsl/phy/Makefile ++++ b/src/hsl/phy/Makefile +@@ -60,6 +60,12 @@ ifeq (TRUE, $(IN_QCA803X_PHY)) + SRC_LIST += qca803x_phy.c + endif + ++ifeq (TRUE, $(IN_RTL_PHY)) ++ SRC_LIST += rtl826xb_phy.c ++ SRC_LIST += phy_rtl826xb_patch.c ++ SRC_LIST += rtl.c ++endif ++ + ifeq (TRUE, $(IN_QCA808X_PHY)) + SRC_LIST += qca808x_phy.c + SRC_LIST += qca808x.c +diff --git a/src/hsl/phy/hsl_phy.c b/src/hsl/phy/hsl_phy.c +index 219d2302..f8e805fc 100755 +--- a/src/hsl/phy/hsl_phy.c ++++ b/src/hsl/phy/hsl_phy.c +@@ -37,6 +37,9 @@ + #ifdef IN_AQUANTIA_PHY + #include + #endif ++#ifdef IN_RTL_PHY ++#include ++#endif + #ifdef IN_QCA803X_PHY + #include + #endif +@@ -96,6 +99,11 @@ phy_driver_instance_t ssdk_phy_driver[] = + #else + {MPGE_PHY_CHIP, {0}, NULL, NULL, NULL}, + #endif ++ #ifdef IN_RTL_PHY ++ {RTL_PHY_CHIP, {0}, NULL, rtl_phy_init, NULL}, ++ #else ++ {RTL_PHY_CHIP, {0}, NULL, NULL, NULL}, ++ #endif + #ifdef IN_QCA808X_PHY + /*qca808x_start*/ + {QCA808X_PHY_CHIP, {0}, NULL, qca808x_phy_init, qca808x_phy_exit}, +@@ -290,6 +298,9 @@ phy_type_t hsl_phytype_get_by_phyid(a_uint32_t dev_id, a_uint32_t phy_id) + case MP_GEPHY: + phytype = MPGE_PHY_CHIP; + break; ++ case RTL_PHY: ++ phytype = RTL_PHY_CHIP; ++ break; + case QCA8084_PHY: + /*qca808x_start*/ + case QCA8081_PHY_V1_1: +@@ -684,8 +695,8 @@ hsl_port_phy_mode_set(a_uint32_t dev_id, a_uint32_t port_id, + a_uint32_t phy_addr = 0; + hsl_phy_ops_t *phy_drv; + +- SW_RTN_ON_NULL(phy_drv = hsl_phy_api_ops_get (dev_id, port_id)); +- if (NULL == phy_drv->phy_interface_mode_set) ++ phy_drv = hsl_phy_api_ops_get (dev_id, port_id); ++ if (NULL == phy_drv || NULL == phy_drv->phy_interface_mode_set) + { + /*PHY driver did not register phy_interface_mode_set, + so no need to configure PHY interface mode*/ +@@ -1210,6 +1221,58 @@ a_uint32_t hsl_port_mode_to_uniphy_mode(a_uint32_t dev_id, + return uniphy_mode; + } + ++a_uint32_t hsl_uniphy_mode_to_port_mode(a_uint32_t dev_id, a_uint32_t port_id, ++ a_uint32_t uniphy_mode) ++{ ++ a_uint32_t port_mode = 0; ++ ++ switch(uniphy_mode) ++ { ++ case PORT_WRAPPER_PSGMII: ++ case PORT_WRAPPER_PSGMII_FIBER: ++ if(port_id >= SSDK_PHYSICAL_PORT1 && port_id <= SSDK_PHYSICAL_PORT4) ++ port_mode = PHY_PSGMII_BASET; ++ if(port_id == SSDK_PHYSICAL_PORT5) { ++ if(uniphy_mode == PORT_WRAPPER_PSGMII) ++ port_mode = PHY_PSGMII_BASET; ++ else ++ port_mode = PHY_PSGMII_FIBER; ++ } ++ break; ++ case PORT_WRAPPER_QSGMII: ++ port_mode = PORT_QSGMII; ++ break; ++ case PORT_WRAPPER_SGMII_PLUS: ++ port_mode = PORT_SGMII_PLUS; ++ break; ++ case PORT_WRAPPER_USXGMII: ++ port_mode = PORT_USXGMII; ++ break; ++ case PORT_WRAPPER_10GBASE_R: ++ port_mode = PORT_10GBASE_R; ++ break; ++ case PORT_WRAPPER_SGMII_CHANNEL0: ++ case PORT_WRAPPER_SGMII_CHANNEL1: ++ case PORT_WRAPPER_SGMII_CHANNEL4: ++ port_mode = PHY_SGMII_BASET; ++ break; ++ case PORT_WRAPPER_SGMII_FIBER: ++ port_mode = PORT_SGMII_FIBER; ++ break; ++ case PORT_WRAPPER_UQXGMII: ++ case PORT_WRAPPER_UDXGMII: ++ port_mode = PORT_UQXGMII; ++ break; ++ case PORT_WRAPPER_MAX: ++ port_mode = PORT_INTERFACE_MODE_MAX; ++ break; ++ default: ++ return SW_NOT_SUPPORTED; ++ } ++ ++ return port_mode; ++} ++ + a_uint32_t hsl_port_to_uniphy(a_uint32_t dev_id, a_uint32_t port_id) + { + a_uint32_t uniphy_index = SSDK_MAX_UNIPHY_INSTANCE; +@@ -1319,6 +1382,124 @@ hsl_port_phy_interface_mode_status_get(a_uint32_t dev_id, a_uint32_t port_id, + return SW_OK; + } + ++sw_error_t ++hsl_port_phy_power_on(a_uint32_t dev_id, fal_port_t port_id) ++{ ++ sw_error_t rv = SW_OK; ++ a_uint32_t phy_addr = 0; ++ hsl_phy_ops_t *phy_drv = NULL; ++ ++ HSL_DEV_ID_CHECK(dev_id); ++ ++ if (A_TRUE != hsl_port_prop_check (dev_id, port_id, HSL_PP_PHY)) ++ { ++ return SW_BAD_PARAM; ++ } ++ ++ SW_RTN_ON_NULL (phy_drv = hsl_phy_api_ops_get (dev_id, port_id)); ++ if (NULL == phy_drv->phy_power_on) ++ return SW_NOT_SUPPORTED; ++ ++ rv = hsl_port_prop_get_phyid (dev_id, port_id, &phy_addr); ++ SW_RTN_ON_ERROR (rv); ++ ++ return phy_drv->phy_power_on(dev_id, phy_addr); ++} ++ ++sw_error_t ++hsl_port_phy_power_off(a_uint32_t dev_id, fal_port_t port_id) ++{ ++ sw_error_t rv = SW_OK; ++ a_uint32_t phy_addr = 0; ++ hsl_phy_ops_t *phy_drv = NULL; ++ ++ HSL_DEV_ID_CHECK(dev_id); ++ ++ if (A_TRUE != hsl_port_prop_check (dev_id, port_id, HSL_PP_PHY)) ++ { ++ return SW_BAD_PARAM; ++ } ++ ++ SW_RTN_ON_NULL (phy_drv = hsl_phy_api_ops_get (dev_id, port_id)); ++ if (NULL == phy_drv->phy_power_off) ++ return SW_NOT_SUPPORTED; ++ ++ rv = hsl_port_prop_get_phyid (dev_id, port_id, &phy_addr); ++ SW_RTN_ON_ERROR (rv); ++ ++ return phy_drv->phy_power_off(dev_id, phy_addr); ++ ++} ++/*qca808x_end*/ ++sw_error_t ++hsl_port_phy_pll_on(a_uint32_t dev_id, a_uint32_t port_id) ++{ ++ sw_error_t rv = SW_OK; ++ a_uint32_t phy_addr = 0; ++ hsl_phy_ops_t *phy_drv = NULL; ++ ++ HSL_DEV_ID_CHECK(dev_id); ++ ++ if (A_TRUE != hsl_port_prop_check(dev_id, port_id, HSL_PP_PHY)) ++ return SW_BAD_PARAM; ++ ++ SW_RTN_ON_NULL (phy_drv = hsl_phy_api_ops_get(dev_id, port_id)); ++ if (NULL == phy_drv->phy_pll_on) ++ return SW_NOT_SUPPORTED; ++ ++ rv = hsl_port_prop_get_phyid(dev_id, port_id, &phy_addr); ++ SW_RTN_ON_ERROR (rv); ++ ++ rv = phy_drv->phy_pll_on(dev_id, phy_addr); ++ return rv; ++} ++ ++sw_error_t ++hsl_port_phy_pll_off(a_uint32_t dev_id, a_uint32_t port_id) ++{ ++ sw_error_t rv = SW_OK; ++ a_uint32_t phy_addr = 0; ++ hsl_phy_ops_t *phy_drv = NULL; ++ ++ HSL_DEV_ID_CHECK(dev_id); ++ ++ if (A_TRUE != hsl_port_prop_check(dev_id, port_id, HSL_PP_PHY)) ++ return SW_BAD_PARAM; ++ ++ SW_RTN_ON_NULL (phy_drv = hsl_phy_api_ops_get(dev_id, port_id)); ++ if (NULL == phy_drv->phy_pll_off) ++ return SW_NOT_SUPPORTED; ++ ++ rv = hsl_port_prop_get_phyid(dev_id, port_id, &phy_addr); ++ SW_RTN_ON_ERROR (rv); ++ ++ rv = phy_drv->phy_pll_off(dev_id, phy_addr); ++ return rv; ++} ++ ++sw_error_t ++hsl_port_phy_ldo_set(a_uint32_t dev_id, a_uint32_t port_id, a_bool_t enable) ++{ ++ sw_error_t rv = SW_OK; ++ a_uint32_t phy_addr = 0; ++ hsl_phy_ops_t *phy_drv = NULL; ++ ++ HSL_DEV_ID_CHECK(dev_id); ++ ++ if (A_TRUE != hsl_port_prop_check(dev_id, port_id, HSL_PP_PHY)) ++ return SW_BAD_PARAM; ++ ++ SW_RTN_ON_NULL (phy_drv = hsl_phy_api_ops_get(dev_id, port_id)); ++ if (NULL == phy_drv->phy_ldo_set) ++ return SW_NOT_SUPPORTED; ++ ++ rv = hsl_port_prop_get_phyid(dev_id, port_id, &phy_addr); ++ SW_RTN_ON_ERROR (rv); ++ ++ rv = phy_drv->phy_ldo_set(dev_id, phy_addr, enable); ++ return rv; ++} ++/*qca808x_start*/ + sw_error_t + hsl_port_phy_counter_set(a_uint32_t dev_id, a_uint32_t port_id, a_bool_t enable) + { +diff --git a/src/hsl/phy/phy_rtl826xb_patch.c b/src/hsl/phy/phy_rtl826xb_patch.c +new file mode 100644 +index 00000000..21c9b38d +--- /dev/null ++++ b/src/hsl/phy/phy_rtl826xb_patch.c +@@ -0,0 +1,1651 @@ ++ ++/* ++ * Copyright (C) 2009-2021 Realtek Semiconductor Corp. ++ * All Rights Reserved. ++ * ++ * This program is the proprietary software of Realtek Semiconductor ++ * Corporation and/or its licensors, and only be used, duplicated, ++ * modified or distributed under the authorized license from Realtek. ++ * ++ * ANY USE OF THE SOFTWARE OTHER THAN AS AUTHORIZED UNDER ++ * THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. ++ * ++ * $Revision: $ ++ * $Date: $ ++ * ++ * Purpose : PHY 826XB/8261N Driver APIs. ++ * ++ * Feature : PHY 826XB/8261N Driver APIs ++ * ++ */ ++ ++/* ++ * Include Files ++ */ ++#include "phy_common.h" ++#include "phy_rtl826xb.h" ++/* ++ * Symbol Definition ++ */ ++ ++#define PHY_PATCH_OP_NORMAL 0 ++#define PHY_PATCH_OP_BCAST 1 ++#define PHY_PATCH_WAIT_TIMEOUT 1000000 ++ ++#define PHY_PATCH_LOG LOG_INFO ++ ++ ++#define RTL8261N_C_FW_VER 0x0001 ++#define RTL8261N_C_MAIN_VER 0x1 ++#define RTL8261N_C_SW_VER 0x1 ++#define RTL8261N_C_TOP_VER 0x0101 ++#define RTL8261N_C_AFEFW_VER 0x0101 ++ ++ ++#define RTK_HWPATCH_OP_UNKNOWN 0 ++#define RTK_HWPATCH_OP_SDS 1 ++#define RTK_HWPATCH_OP_PHY 2 ++#define RTK_HWPATCH_OP_PHYW 3 ++#define RTK_HWPATCH_OP_ALGO 4 ++#define RTK_HWPATCH_OP_TOP 5 ++#define RTK_HWPATCH_OP_MMD 6 ++#define RTK_HWPATCH_OP_DATARAM 7 ++ ++rtk_phy_hwpatch_t rtl8261N_C_patch_fwpr_conf[] = { ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa436, 15, 0, 0x8023}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x3802}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa436, 15, 0, 0xb82e}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0001}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb820, 15, 0, 0x0090}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa436, 15, 0, 0xa016}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0020}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa436, 15, 0, 0xa012}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa436, 15, 0, 0xa014}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1800}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8010}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1800}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8029}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1800}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8217}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1800}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x82d0}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1800}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x82f9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1800}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8322}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1800}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8322}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1800}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8322}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c03}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1502}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xcb0a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0cc7}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c03}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x9503}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x4127}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c03}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1502}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c0f}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0b05}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c38}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0d28}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x9503}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf008}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c03}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1502}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c0f}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0b0a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c38}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0d18}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x9503}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1800}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0f73}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x37c9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8034}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x33a9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8031}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd1bf}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd06d}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf006}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd1dd}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd06d}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf003}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd199}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd06e}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1418}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x5fba}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd05a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x60cf}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x60f1}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x6113}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x6135}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x6157}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf00b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xce06}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf00a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xce06}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf008}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xce06}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf006}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xce06}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf004}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xce06}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf002}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xce06}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x142d}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c03}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1502}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0ccf}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0b40}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c3f}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c24}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x9503}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa340}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x147c}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa110}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1435}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8110}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1485}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa304}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa8c0}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8810}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa00a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa120}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa310}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0cfc}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0224}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0ca0}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0480}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c03}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1502}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa340}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x9503}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd162}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd048}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1418}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x5fba}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8840}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd1c4}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd045}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1418}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x5fba}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd706}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x6127}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x5f3b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x88c0}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x800a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8120}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8350}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x84a0}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xffb6}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xb920}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xcd33}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1418}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd71f}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x7fb4}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x9920}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1418}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd71f}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x6065}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x5f94}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xffee}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xb820}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1418}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd71f}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x7fa5}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x9820}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x800a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8120}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x147c}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa108}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1435}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8108}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1485}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa2fc}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa304}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8880}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0cc0}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0440}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xcd34}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c03}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1502}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0cc0}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0b80}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xac3f}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c38}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0d08}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x9503}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa810}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa00a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa120}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa480}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa604}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x37c9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x80bb}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd049}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf003}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd19f}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd049}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1418}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd71f}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x63f4}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x5f7a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd706}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x4368}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c03}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1502}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0cc0}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0b40}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8c3f}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8d38}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x9503}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x37c9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x80d7}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x33a9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x80d4}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd1f4}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf006}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd1b7}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf003}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd1c6}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04c}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1418}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd71f}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x6074}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x5f7a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1418}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd71f}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x4056}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf004}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x61fc}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xfff9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd706}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x6048}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf00b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd702}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x4070}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1800}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x81a4}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c03}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1502}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xae80}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x9503}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1800}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x81a4}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd05a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x60cf}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x60f1}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x6113}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x6135}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x6157}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf00b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xce06}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf00a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xce06}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf008}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xce06}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf006}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xce06}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf004}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xce06}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf002}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xce06}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x142d}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c03}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1502}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0ccf}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0b40}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c3f}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c24}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x9503}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa340}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x147c}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa110}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1435}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8110}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1485}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa304}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa8c0}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8810}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa00a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa120}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa310}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0cfc}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0224}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0ca0}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0480}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8604}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xcd35}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd162}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd048}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1418}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x5fba}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8840}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd1c4}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd045}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1418}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x5fba}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd706}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x6127}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x5f3b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x88c0}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x800a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8120}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8350}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x84a0}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xffb8}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xbb80}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1418}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd71f}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x5fb4}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xb920}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xcd36}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1418}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd71f}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x7fb4}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x9920}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x9b80}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1418}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd71f}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x6065}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x5f94}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xffe8}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xb820}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1418}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd71f}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x7fa5}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x9820}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x800a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8120}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x147c}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa108}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1435}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8108}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1485}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa2fc}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa304}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8880}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0cc0}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0440}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xcd37}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c03}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1502}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0cc0}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0b80}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xac3f}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c38}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0d08}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x9503}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa810}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa00a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa120}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa480}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa604}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x37c9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x817e}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x33a9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x817b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd048}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf006}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd048}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf003}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd048}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1418}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1463}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x5f7a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd706}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x5f28}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c03}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1502}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0cc0}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0b40}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8c3f}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8d38}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x9503}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x37c9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x819a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x33a9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8197}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd199}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf006}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf003}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd189}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04c}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1418}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1463}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x5f7a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd706}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x5f28}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c03}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1502}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c0f}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0b05}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x9503}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x60cf}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x60f1}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x6113}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x6135}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x6157}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf00b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xce08}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf00a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xce08}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf008}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xce08}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf006}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xce08}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf004}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xce08}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf002}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xce08}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x142d}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa180}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xcd38}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x37c9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x81d4}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x33a9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x81cc}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd702}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x4098}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf013}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd100}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd049}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf010}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd702}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x4098}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd1b7}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd049}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf00b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd100}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd048}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf008}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd702}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x4098}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf003}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd199}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd13b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd055}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1418}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1463}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x5f7b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa302}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1418}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1463}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x5f7a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd706}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x5f28}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c03}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1502}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c3f}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c12}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x9503}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x37c9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8206}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x33a9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x81fe}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd702}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x4098}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd199}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf013}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd100}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd048}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf010}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd702}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x4098}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf00b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd100}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd040}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf008}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd702}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x4098}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd199}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf003}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd16b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1418}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1463}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x5f7a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd706}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x5f2a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1800}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x087a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x646d}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x37c9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8231}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x33a9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8227}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x40c7}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd702}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x6098}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd100}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd049}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf01a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd049}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf017}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x40c7}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd702}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x6098}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd100}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd049}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf010}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04c}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf00d}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x40c7}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd702}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x6098}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf006}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf003}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd048}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1418}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1463}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x5f7a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd706}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x5f29}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x60cf}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x60f1}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x6113}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x6135}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x6157}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf00b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xce06}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf00a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xce06}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf008}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xce06}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf006}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xce06}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf004}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xce06}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf002}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xce06}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x142d}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c03}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1502}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8bc0}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c3f}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c09}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x9503}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa120}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa310}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xa420}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xcd3b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x65ad}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x43c7}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x37c9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x827b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x33a9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8273}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd702}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x4098}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd199}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04c}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf024}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd15d}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf021}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd702}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x4098}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd1c6}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04c}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf01c}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd15d}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf019}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd702}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x4098}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd199}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04c}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf014}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04c}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf011}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x37c9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x828e}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x33a9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x828b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd1e5}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04c}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf009}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd191}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04d}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf006}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04d}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf003}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd16b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04c}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1418}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1463}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x5f7a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd706}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x5f2c}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x40e7}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c03}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1502}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c0f}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0b05}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x9503}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf006}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c03}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1502}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0c0f}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0b0a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x9503}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xcd3c}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x644d}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x43c7}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x37c9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x82c1}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x33a9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x82b9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd702}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x4098}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf019}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd048}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf016}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd702}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x4098}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf011}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd13e}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd049}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf00e}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd702}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x4098}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf009}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd049}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf006}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf003}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd048}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1800}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0956}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x2969}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x82f5}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x37c9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x82eb}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x33a9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x82e1}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x40c7}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd702}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x6098}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd15c}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf01a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd199}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf017}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x40c7}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd702}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x6098}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd13e}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf010}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd199}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf00d}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x40c7}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd702}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x6098}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04c}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf006}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd199}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04c}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf003}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1800}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x09a0}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x2969}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x831e}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x37c9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x8314}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x33a9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x830a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x40c7}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd702}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x6098}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd15d}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf01a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf017}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x40c7}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd702}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x6098}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd16b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf010}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf00d}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd700}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x40c7}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd702}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x6098}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf006}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd17a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xf003}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd1b7}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xd04a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x1800}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0a39}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa436, 15, 0, 0xa10e}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xffff}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa436, 15, 0, 0xa10c}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xffff}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa436, 15, 0, 0xa10a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0xffff}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa436, 15, 0, 0xa108}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0a12}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa436, 15, 0, 0xa106}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0979}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa436, 15, 0, 0xa104}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x089f}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa436, 15, 0, 0xa102}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0692}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa436, 15, 0, 0xa100}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0f60}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa436, 15, 0, 0xa110}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x001f}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb820, 15, 0, 0x0010}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb896, 15, 0, 0x0000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb892, 15, 0, 0x0000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb88e, 15, 0, 0xc10b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb890, 15, 0, 0xd5d5}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb88e, 15, 0, 0xc10c}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb890, 15, 0, 0xd5cd}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb88e, 15, 0, 0xc10d}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb890, 15, 0, 0xd5d5}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb88e, 15, 0, 0xc10e}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb890, 15, 0, 0xd5c9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb88e, 15, 0, 0xc10f}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb890, 15, 0, 0xd5d5}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb88e, 15, 0, 0xc110}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb890, 15, 0, 0xd5ee}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb88e, 15, 0, 0xc149}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb890, 15, 0, 0x0808}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb88e, 15, 0, 0xc14a}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb890, 15, 0, 0x0810}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb88e, 15, 0, 0xc14b}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb890, 15, 0, 0x0808}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb88e, 15, 0, 0xc14c}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb890, 15, 0, 0x0813}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb88e, 15, 0, 0xc14d}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb890, 15, 0, 0x0808}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb88e, 15, 0, 0xc14e}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb890, 15, 0, 0x08e9}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb896, 15, 0, 0x0001}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa436, 15, 0, 0x0000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb82e, 15, 0, 0x0000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa436, 15, 0, 0x8023}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0000}, ++}; ++ ++rtk_phy_hwpatch_t rtl8261N_C_patch_fwlm_conf[] = { ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb87c, 15, 0, 0x8165}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb87e, 15, 0, 0x2274}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb87c, 15, 0, 0x8167}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb87e, 15, 0, 0x3385}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb87c, 15, 0, 0x816e}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb87e, 15, 0, 0xaeca}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb87c, 15, 0, 0x8139}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb87e, 15, 0, 0x29c4}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb87c, 15, 0, 0x8125}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb87e, 15, 0, 0x6567}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb87c, 15, 0, 0x827e}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb87e, 15, 0, 0x683c}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa436, 15, 0, 0x8367}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x5d6e}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa436, 15, 0, 0x817d}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0758}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xb516, 15, 0, 0x0000}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa436, 15, 0, 0x801e}, ++ {RTK_HWPATCH_OP_PHY, 0xff ,0x00, 0xa438, 15, 0, 0x0001}, ++}; ++ ++rtk_phy_hwpatch_t rtl8261N_C_patch_afe_conf[] = { ++}; ++ ++rtk_phy_hwpatch_t rtl8261N_C_patch_sds_conf[] = { ++ {RTK_HWPATCH_OP_TOP, 0xff ,0x18, 0x0012, 15, 0, 0x881f}, ++ {RTK_HWPATCH_OP_TOP, 0xff ,0x18, 0x0013, 15, 0, 0x003f}, ++ {RTK_HWPATCH_OP_TOP, 0xff ,0x18, 0x0014, 15, 0, 0x003f}, ++ {RTK_HWPATCH_OP_TOP, 0xff ,0x18, 0x0015, 15, 0, 0x003f}, ++ {RTK_HWPATCH_OP_TOP, 0xff ,0x18, 0x0016, 15, 0, 0x001f}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x06, 0x000d, 15, 0, 0x0f00}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x06, 0x000e, 15, 0, 0x3f5a}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x07, 0x0010, 15, 0, 0x8003}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x06, 0x001d, 15, 0, 0x0600}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x21, 0x0000, 15, 0, 0x4902}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x21, 0x0008, 15, 0, 0x0fc0}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x21, 0x0009, 15, 0, 0x33f0}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x21, 0x000c, 15, 0, 0x08bf}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x21, 0x0012, 15, 0, 0x8000}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x36, 0x0007, 15, 0, 0x04c0}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x36, 0x0008, 15, 0, 0x2000}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x2e, 0x000b, 15, 0, 0x2390}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x2e, 0x000c, 15, 0, 0xaa17}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x2e, 0x000d, 15, 0, 0xfe40}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x2e, 0x000e, 15, 0, 0x12f4}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x2e, 0x0011, 15, 0, 0xf2ad}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x2e, 0x0015, 15, 0, 0x7a41}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x2e, 0x0016, 15, 0, 0x0041}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x2f, 0x0000, 15, 0, 0x1f00}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x2f, 0x0001, 15, 0, 0x2800}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x2f, 0x0002, 15, 0, 0x0fc8}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x2f, 0x0011, 15, 0, 0x3000}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x2f, 0x0013, 15, 0, 0xf400}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x2f, 0x001e, 15, 0, 0x0500}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x34, 0x000b, 15, 0, 0x2390}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x34, 0x000c, 15, 0, 0xa517}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x34, 0x000d, 15, 0, 0xfe41}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x34, 0x000e, 15, 0, 0x12f4}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x34, 0x0011, 15, 0, 0xf2ad}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x34, 0x0015, 15, 0, 0x7a41}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x34, 0x0016, 15, 0, 0x0041}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x35, 0x0000, 15, 0, 0x1f80}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x35, 0x0001, 15, 0, 0x0800}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x35, 0x0002, 15, 0, 0x0fc8}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x35, 0x0011, 15, 0, 0x3001}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x35, 0x0013, 15, 0, 0xf400}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x35, 0x001e, 15, 0, 0x0100}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x2c, 0x000b, 15, 0, 0x2390}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x2c, 0x000c, 15, 0, 0xa517}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x2c, 0x000d, 15, 0, 0xfe41}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x2c, 0x000e, 15, 0, 0x12f4}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x2c, 0x0011, 15, 0, 0xf2ad}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x2c, 0x0015, 15, 0, 0x7a61}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x2c, 0x0016, 15, 0, 0x0041}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x2d, 0x0000, 15, 0, 0x1f80}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x2d, 0x0001, 15, 0, 0x0800}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x2d, 0x0002, 15, 0, 0x0fc8}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x2d, 0x0011, 15, 0, 0x3001}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x2d, 0x0013, 15, 0, 0xf400}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x2d, 0x001e, 15, 0, 0x0100}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x28, 0x000b, 15, 0, 0x2390}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x28, 0x000c, 15, 0, 0xa514}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x28, 0x000d, 15, 0, 0xfe43}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x28, 0x000e, 15, 0, 0x12f4}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x28, 0x0011, 15, 0, 0xf2ad}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x28, 0x0015, 15, 0, 0x7a61}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x28, 0x0016, 15, 0, 0x0041}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x29, 0x0000, 15, 0, 0x1f80}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x29, 0x0001, 15, 0, 0x0800}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x29, 0x0002, 15, 0, 0x0fc8}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x29, 0x0011, 15, 0, 0x3001}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x29, 0x0013, 15, 0, 0xf400}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x29, 0x001e, 15, 0, 0x0100}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x26, 0x000b, 15, 0, 0x2390}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x26, 0x000c, 15, 0, 0xa514}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x26, 0x000d, 15, 0, 0xfe43}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x26, 0x000e, 15, 0, 0x12f4}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x26, 0x0011, 15, 0, 0xf2ad}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x26, 0x0015, 15, 0, 0x7a41}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x26, 0x0016, 15, 0, 0x0041}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x27, 0x0000, 15, 0, 0x1f80}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x27, 0x0001, 15, 0, 0x0800}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x27, 0x0002, 15, 0, 0x0fc8}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x27, 0x0011, 15, 0, 0x3001}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x27, 0x0013, 15, 0, 0xf400}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x27, 0x001e, 15, 0, 0x0100}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x24, 0x000b, 15, 0, 0x2390}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x24, 0x000c, 15, 0, 0xa514}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x24, 0x000d, 15, 0, 0xfe43}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x24, 0x000e, 15, 0, 0x12f4}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x24, 0x0011, 15, 0, 0xf2ad}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x24, 0x0015, 15, 0, 0x7a41}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x24, 0x0016, 15, 0, 0x0041}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x25, 0x0000, 15, 0, 0x1f80}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x25, 0x0001, 15, 0, 0x0800}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x25, 0x0002, 15, 0, 0x0fc8}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x25, 0x0011, 15, 0, 0x3001}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x25, 0x0013, 15, 0, 0xf400}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x25, 0x001e, 15, 0, 0x0100}, ++ {RTK_HWPATCH_OP_TOP, 0xff ,0x18, 0x0012, 15, 0, 0x880d}, ++ {RTK_HWPATCH_OP_TOP, 0xff ,0x18, 0x0013, 15, 0, 0x0024}, ++ {RTK_HWPATCH_OP_TOP, 0xff ,0x18, 0x0014, 15, 0, 0x0036}, ++ {RTK_HWPATCH_OP_TOP, 0xff ,0x18, 0x0015, 15, 0, 0x0035}, ++ {RTK_HWPATCH_OP_TOP, 0xff ,0x18, 0x0016, 15, 0, 0x001a}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x1f, 0x0000, 15, 0, 0x001b}, ++ {RTK_HWPATCH_OP_SDS, 0xff ,0x1f, 0x0000, 15, 0, 0x0000}, ++}; ++ ++rtk_phy_hwpatch_t rtl8261N_C_patch_top_conf[] = { ++ {RTK_HWPATCH_OP_TOP, 0xff ,0x02, 0x0014, 15, 0, 0x0005}, ++ {RTK_HWPATCH_OP_TOP, 0xff ,0x02, 0x0015, 15, 0, 0x0000}, ++ {RTK_HWPATCH_OP_TOP, 0xff ,0x02, 0x0016, 15, 0, 0x0280}, ++ {RTK_HWPATCH_OP_TOP, 0xff ,0x02, 0x0017, 15, 0, 0x0014}, ++ {RTK_HWPATCH_OP_TOP, 0xff ,0x03, 0x0010, 15, 0, 0x0300}, ++ {RTK_HWPATCH_OP_TOP, 0xff ,0x03, 0x0011, 15, 0, 0x01ff}, ++ {RTK_HWPATCH_OP_TOP, 0xff ,0x03, 0x0012, 15, 0, 0x000c}, ++ {RTK_HWPATCH_OP_TOP, 0xff ,0x03, 0x0013, 15, 0, 0x01ff}, ++ {RTK_HWPATCH_OP_TOP, 0xff ,0x03, 0x0014, 15, 0, 0x0200}, ++ {RTK_HWPATCH_OP_TOP, 0xff ,0x03, 0x0015, 15, 0, 0x0015}, ++ {RTK_HWPATCH_OP_TOP, 0xff ,0x03, 0x0016, 15, 0, 0x0200}, ++ {RTK_HWPATCH_OP_TOP, 0xff ,0x03, 0x0017, 15, 0, 0x0000}, ++ {RTK_HWPATCH_OP_TOP, 0xff ,0x04, 0x0010, 15, 0, 0x0000}, ++ {RTK_HWPATCH_OP_TOP, 0xff ,0x0d, 0x0017, 8, 5, 0x0006}, ++}; ++ ++ ++/* ++ * Data Declaration ++ */ ++ ++/* ++ * Macro Declaration ++ */ ++ ++/* ++ * Function Declaration ++ */ ++ ++a_uint32_t ++_phy_rtl826xb_patch_mask(a_uint8_t msb, a_uint8_t lsb) ++{ ++ a_uint16_t val = 0; ++ a_uint8_t i = 0; ++ ++ for (i = lsb; i <= msb; i++) ++ { ++ val |= (1 << i); ++ } ++ return val; ++} ++ ++a_int32_t ++_phy_rtl826xb_patch_mask_get(a_uint8_t msb, a_uint8_t lsb, a_uint16_t *mask) ++{ ++ if ((msb > 15) || (lsb > 15) || (msb < lsb)) ++ { ++ return RT_ERR_FAILED; ++ } ++ *mask = _phy_rtl826xb_patch_mask(msb, lsb); ++ return RT_ERR_OK; ++} ++ ++a_int32_t ++_phy_rtl826xb_patch_wait(a_uint32_t unit, a_uint32_t port, a_uint16_t mmdAddr, a_uint16_t mmdReg, a_uint32_t data, a_uint32_t mask, a_uint8_t bcast_op) ++{ ++ ++ a_uint16_t rData = 0; ++ a_uint32_t cnt = 0; ++ ++ ++ ++ ++ if (bcast_op == PHY_PATCH_OP_BCAST) ++ { ++ phy_826xb_ctrl_set(unit, port, RTK_PHY_CTRL_MIIM_BCAST, 0); ++ ++ ++ ++ do ++ { ++ rData = phy_common_general_reg_mmd_get(unit, port, mmdAddr, mmdReg); ++ ++ ++ if (++cnt >= PHY_PATCH_WAIT_TIMEOUT) ++ { ++ return RT_ERR_TIMEOUT; ++ } ++ }while ((rData & mask) != data); ++ ++ ++ mdelay(1); ++ //for port in same SMI bus, set mdio broadcast ENABLE ++ ++ phy_826xb_ctrl_set(unit, port, RTK_PHY_CTRL_MIIM_BCAST_PHYAD, port); ++ ++ ++ phy_826xb_ctrl_set(unit, port, RTK_PHY_CTRL_MIIM_BCAST, 1); ++ ++ } ++ else ++ { ++ do ++ { ++ rData = phy_common_general_reg_mmd_get(unit, port, mmdAddr, mmdReg); ++ ++ ++ if (++cnt >= PHY_PATCH_WAIT_TIMEOUT) ++ { ++ ++ return RT_ERR_TIMEOUT; ++ } ++ mdelay(1); ++ }while ((rData & mask) != data); ++ } ++ ++ return RT_ERR_OK; ++} ++ ++a_int32_t ++_phy_rtl826xb_patch_wait_not_equal(a_uint32_t unit, a_uint32_t port, a_uint16_t mmdAddr, a_uint16_t mmdReg, a_uint16_t data, a_uint16_t mask, a_uint8_t bcast_op) ++{ ++ ++ a_uint16_t rData = 0; ++ a_uint16_t cnt = 0; ++ ++ ++ ++ if (bcast_op == PHY_PATCH_OP_BCAST) ++ { ++ phy_826xb_ctrl_set(unit, port, RTK_PHY_CTRL_MIIM_BCAST, 0); ++ ++ do ++ { ++ rData = phy_common_general_reg_mmd_get(unit, port, mmdAddr, mmdReg); ++ ++ ++ if (++cnt >= PHY_PATCH_WAIT_TIMEOUT) ++ { ++ ++ return RT_ERR_TIMEOUT; ++ } ++ }while ((rData & mask) == data); ++ ++ ++ mdelay(1); ++ //for port in same SMI bus, set mdio broadcast ENABLE ++ ++ phy_826xb_ctrl_set(unit, port, RTK_PHY_CTRL_MIIM_BCAST_PHYAD, port); ++ ++ ++ phy_826xb_ctrl_set(unit, port, RTK_PHY_CTRL_MIIM_BCAST, 1); ++ ++ ++ } ++ else ++ { ++ do ++ { ++ rData = phy_common_general_reg_mmd_get(unit, port, mmdAddr, mmdReg); ++ ++ ++ if (++cnt >= PHY_PATCH_WAIT_TIMEOUT) ++ { ++ ++ return RT_ERR_TIMEOUT; ++ } ++ mdelay(1); ++ }while ((rData & mask) == data); ++ } ++ ++ return RT_ERR_OK; ++} ++ ++a_int32_t ++_phy_rtl826xb_patch_top_get(a_uint32_t unit, a_uint32_t port, a_uint16_t topPage, a_uint16_t topReg, a_uint16_t *pData) ++{ ++ ++ a_uint16_t rData = 0; ++ a_uint16_t topAddr = (topPage * 8) + (topReg - 16); ++ ++ rData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, topAddr); ++ ++ *pData = rData; ++ return RT_ERR_OK; ++} ++ ++a_int32_t ++_phy_rtl826xb_patch_top_set(a_uint32_t unit, a_uint32_t port, a_uint32_t topPage, a_uint32_t topReg, a_uint16_t wData) ++{ ++ ++ a_uint32_t topAddr = (topPage * 8) + (topReg - 16); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, topAddr, wData); ++ ++ return RT_ERR_OK; ++} ++ ++a_int32_t ++_phy_rtl826xb_patch_sds_get(a_uint32_t unit, a_uint32_t port, a_uint16_t sdsPage, a_uint16_t sdsReg, a_uint16_t *pData) ++{ ++ a_int32_t ret = 0; ++ a_uint16_t rData = 0; ++ a_uint16_t sdsAddr = 0x8000 + (sdsReg << 6) + sdsPage; ++ ++ if ((ret = _phy_rtl826xb_patch_top_set(unit, port, 40, 19, sdsAddr)) != RT_ERR_OK) ++ return ret; ++ if ((ret = _phy_rtl826xb_patch_top_get(unit, port, 40, 18, &rData)) != RT_ERR_OK) ++ return ret; ++ *pData = rData; ++ return _phy_rtl826xb_patch_wait(unit, port, PHY_MMD_VEND1, 0x143, 0, RTLBIT_15, PHY_PATCH_OP_NORMAL); ++} ++ ++a_int32_t ++_phy_rtl826xb_patch_sds_set(a_uint32_t unit, a_uint32_t port, a_uint16_t sdsPage, a_uint16_t sdsReg, a_uint16_t wData, a_uint8_t bcast) ++{ ++ a_int32_t ret = 0; ++ a_uint16_t sdsAddr = 0x8800 + (sdsReg << 6) + sdsPage; ++ ++ if ((ret = _phy_rtl826xb_patch_top_set(unit, port, 40, 17, wData)) != RT_ERR_OK) ++ return ret; ++ if ((ret = _phy_rtl826xb_patch_top_set(unit, port, 40, 19, sdsAddr)) != RT_ERR_OK) ++ return ret; ++ return _phy_rtl826xb_patch_wait(unit, port, PHY_MMD_VEND1, 0x143, 0, RTLBIT_15, bcast); ++} ++ ++a_int32_t _phy_rtl826xb_patch_data_ram_write(a_uint32_t unit, a_uint32_t port, a_uint32_t addr, a_uint32_t data) ++{ ++ ++ a_uint16_t rData = 0, wData = 0; ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xB88E, addr); ++ ++ ++ rData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xB890); ++ ++ ++ ++ if ((addr % 2) == 0) ++ { ++ wData = REG32_FIELD_SET(rData, data, 8, 0xFF00); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xB890, wData); ++ ++ } ++ else ++ { ++ wData = REG32_FIELD_SET(rData, data, 0, 0x00FF); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xB890, wData); ++ ++ } ++ ++ return RT_ERR_OK; ++} ++ ++a_int32_t ++phy_rtl826xb_patch_process_op(a_uint32_t unit, a_uint32_t port, a_uint8_t portOffset, rtk_phy_hwpatch_t *op, a_uint8_t bcast) ++{ ++ a_uint16_t mask = 0; ++ a_uint16_t rData = 0, wData = 0; ++ if ((op->portmask & (1 << portOffset)) == 0) ++ { ++ return RT_ERR_ABORT; ++ } ++ ++ _phy_rtl826xb_patch_mask_get(op->msb, op->lsb, &mask); ++ ++ ++ switch (op->patch_op) ++ { ++ case RTK_HWPATCH_OP_PHY: ++ if ((op->msb != 15) || (op->lsb != 0)) ++ { ++ rData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, op->addr); ++ ++ } ++ wData = REG32_FIELD_SET(rData, op->data, op->lsb, mask); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, op->addr, wData); ++ ++ ++ break; ++ ++ case RTK_HWPATCH_OP_MMD: ++ if ((op->msb != 15) || (op->lsb != 0)) ++ { ++ rData = phy_common_general_reg_mmd_get(unit, port, op->pagemmd, op->addr); ++ ++ } ++ wData = REG32_FIELD_SET(rData, op->data, op->lsb, mask); ++ phy_common_general_reg_mmd_set(unit, port, op->pagemmd, op->addr, wData); ++ ++ ++ break; ++ ++ case RTK_HWPATCH_OP_TOP: ++ if ((op->msb != 15) || (op->lsb != 0)) ++ { ++ _phy_rtl826xb_patch_top_get(unit, port, op->pagemmd, op->addr, &rData); ++ ++ } ++ wData = REG32_FIELD_SET(rData, op->data, op->lsb, mask); ++ _phy_rtl826xb_patch_top_set(unit, port, op->pagemmd, op->addr, wData); ++ ++ ++ break; ++ ++ case RTK_HWPATCH_OP_SDS: ++ if ((op->msb != 15) || (op->lsb != 0)) ++ { ++ _phy_rtl826xb_patch_sds_get(unit, port, op->pagemmd, op->addr, &rData); ++ ++ } ++ wData = REG32_FIELD_SET(rData, op->data, op->lsb, mask); ++ ++ _phy_rtl826xb_patch_sds_set(unit, port, op->pagemmd, op->addr, wData, bcast); ++ ++ ++ break; ++ ++ case RTK_HWPATCH_OP_PHYW: ++ if ((op->msb != 15) || (op->lsb != 0)) ++ { ++ rData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, op->addr); ++ ++ } ++ wData = REG32_FIELD_SET(rData, op->data, op->lsb, mask); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, op->addr, wData); ++ ++ break; ++ ++ case RTK_HWPATCH_OP_ALGO: ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xB87C, op->addr); ++ ++ if ((op->msb != 15) || (op->lsb != 0)) ++ { ++ rData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xB87E); ++ ++ } ++ wData = REG32_FIELD_SET(rData, op->data, op->lsb, mask); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xB87E, wData); ++ ++ break; ++ ++ case RTK_HWPATCH_OP_DATARAM: ++ _phy_rtl826xb_patch_data_ram_write(unit, port, op->addr, op->data); ++ ++ break; ++ ++ case RTK_HWPATCH_OP_UNKNOWN: ++ default: ++ return RT_ERR_INPUT; ++ } ++ ++ return RT_ERR_OK; ++} ++ ++a_int32_t ++phy_rtl826xb_patch_op(a_uint32_t unit, a_uint32_t port, a_uint8_t portOffset, a_uint8_t patch_op, a_uint8_t portmask, a_uint16_t pagemmd, a_uint16_t addr, a_uint8_t msb, a_uint8_t lsb, a_uint16_t data) ++{ ++ rtk_phy_hwpatch_t op; ++ ++ op.patch_op = patch_op; ++ op.portmask = portmask; ++ op.pagemmd = pagemmd; ++ op.addr = addr; ++ op.msb = msb; ++ op.lsb = lsb; ++ op.data = data; ++ ++ return phy_rtl826xb_patch_process_op(unit, port, portOffset, &op, PHY_PATCH_OP_NORMAL); ++} ++ ++a_int32_t _phy_rtl826xb_patch_process(a_uint32_t unit, a_uint32_t port, a_uint8_t portOffset, rtk_phy_hwpatch_t *pPatch, a_int32_t size, a_uint32_t *cnt, a_uint8_t bcast) ++{ ++ a_int32_t i = 0; ++ a_int32_t ret = 0; ++ a_int32_t n; ++ rtk_phy_hwpatch_t *patch = pPatch; ++ if (size <= 0) ++ { ++ *cnt = 0; ++ return RT_ERR_OK; ++ } ++ n = size/sizeof(rtk_phy_hwpatch_t); ++ ++ for (i = 0; i < n; i++) ++ { ++ ret = phy_rtl826xb_patch_process_op(unit, port, portOffset, &patch[i], bcast); ++ if ((ret != RT_ERR_ABORT) && (ret != RT_ERR_OK)) ++ { ++ ++ return ret; ++ } ++ } ++ *cnt = i; ++ return RT_ERR_OK; ++} ++ ++a_int32_t _phy_rtl826xb_patch(a_uint32_t unit, a_uint32_t port, a_uint8_t portOffset, a_uint8_t bcast) ++{ ++ a_int32_t ret = 0; ++ a_uint32_t cnt = 0; ++ a_uint16_t rData = 0; ++ ++ a_uint32_t FW_VER = 0; ++ a_uint32_t MAIN_VER = 0; ++ a_uint32_t SW_VER = 0; ++ a_uint32_t TOP_VER = 0; ++ a_uint32_t AFEFW_VER = 0; ++ rtk_phy_hwpatch_t *patch_fwpr_conf; ++ rtk_phy_hwpatch_t *patch_fwlm_conf; ++ rtk_phy_hwpatch_t *patch_afe_conf; ++ rtk_phy_hwpatch_t *patch_sds_conf; ++ rtk_phy_hwpatch_t *patch_top_conf; ++ a_uint32_t size_fwpr_conf = 0; ++ a_uint32_t size_fwlm_conf = 0; ++ a_uint32_t size_afe_conf = 0; ++ a_uint32_t size_sds_conf = 0; ++ a_uint32_t size_top_conf = 0; ++ ++ rData = phy_common_general_reg_mmd_get(unit, port, 30, 0x104); ++ ++ ++ ++ FW_VER = RTL8261N_C_FW_VER; ++ MAIN_VER = RTL8261N_C_MAIN_VER; ++ SW_VER = RTL8261N_C_SW_VER; ++ TOP_VER = RTL8261N_C_TOP_VER; ++ AFEFW_VER = RTL8261N_C_AFEFW_VER; ++ patch_fwpr_conf = rtl8261N_C_patch_fwpr_conf; ++ patch_fwlm_conf = rtl8261N_C_patch_fwlm_conf; ++ patch_afe_conf = rtl8261N_C_patch_afe_conf; ++ patch_sds_conf = rtl8261N_C_patch_sds_conf; ++ patch_top_conf = rtl8261N_C_patch_top_conf; ++ size_fwpr_conf = sizeof(rtl8261N_C_patch_fwpr_conf); ++ size_fwlm_conf = sizeof(rtl8261N_C_patch_fwlm_conf); ++ size_afe_conf = sizeof(rtl8261N_C_patch_afe_conf); ++ size_sds_conf = sizeof(rtl8261N_C_patch_sds_conf); ++ size_top_conf = sizeof(rtl8261N_C_patch_top_conf); ++ ++ ++ //PP_TOPReg w $PHYID 90 18 ,(0x2d2) ++ if ((ret = phy_rtl826xb_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_TOP, 0xff, 90, 18, 15, 0, MAIN_VER)) != RT_ERR_OK) ++ return ret; ++ //PP_TOPReg w $PHYID 90 19 ,(0x2d3) ++ if ((ret = phy_rtl826xb_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_TOP, 0xff, 90, 19, 15, 0, SW_VER)) != RT_ERR_OK) ++ return ret; ++ //PP_TOPReg w $PHYID 90 20 ,(0x2d4) ++ if ((ret = phy_rtl826xb_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_TOP, 0xff, 90, 21, 15, 0, TOP_VER)) != RT_ERR_OK) ++ return ret; ++ //PP_TOPReg w $PHYID 90 21 ,(0x2d5) ++ if ((ret = phy_rtl826xb_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_TOP, 0xff, 90, 21, 15, 0, AFEFW_VER)) != RT_ERR_OK) ++ return ret; ++ ++ //PP_PHYReg w $PHYID 0xB820 0x0010 ++ if ((ret = phy_rtl826xb_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xb820, 15, 0, 0x0010)) != RT_ERR_OK) ++ return ret; ++ ++ //PP_PHYReg_bit r $PHYID 0xB800 6 6 wait 1 ++ if ((ret = _phy_rtl826xb_patch_wait(unit, port, PHY_MMD_VEND2, 0xB800, RTLBIT_6, RTLBIT_6, bcast)) != RT_ERR_OK) ++ return ret; ++ ++ if ((ret = _phy_rtl826xb_patch_process(unit, port, portOffset, patch_fwpr_conf, size_fwpr_conf, &cnt, bcast))!= RT_ERR_OK) ++ { ++ ++ return ret; ++ } ++ ++ ++ //PP_PHYReg w $PHYID 0xB820 0x0000 ++ if ((ret = phy_rtl826xb_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xb820, 15, 0, 0x0000)) != RT_ERR_OK) ++ return ret; ++ ++ //PP_PHYReg_bit r $PHYID 0xB800 6 6 wait 0 ++ if ((ret = _phy_rtl826xb_patch_wait(unit, port, PHY_MMD_VEND2, 0xB800, 0, RTLBIT_6, bcast)) != RT_ERR_OK) ++ return ret; ++ ++ //PP_PHYReg_bit w $::broadcast_PHYID 0xA4a0 10 10 0x1 ++ if ((ret = phy_rtl826xb_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xA4A0, 10, 10, 0x1)) != RT_ERR_OK) ++ return ret; ++ ++ //[PP_PHYReg_bit r $PHYID 0xa600 7 0] ++ if ((ret = _phy_rtl826xb_patch_wait(unit, port, PHY_MMD_VEND2, 0xa600, 0x1, 0xFF, bcast)) != RT_ERR_OK) ++ return ret; ++ ++ if ((ret = _phy_rtl826xb_patch_process(unit, port, portOffset, patch_fwlm_conf, size_fwlm_conf, &cnt, bcast))!= RT_ERR_OK) ++ { ++ ++ return ret; ++ } ++ ++ ++ //xg_patch_en_flag ++ //PP_PHYReg_bit w $PHYID 0xbf86 9 9 0x1 ++ if ((ret = phy_rtl826xb_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xbf86, 9, 9, 0x1)) != RT_ERR_OK) ++ return ret; ++ //PP_PHYReg_bit w $PHYID 0xbf86 8 8 0x0 ++ if ((ret = phy_rtl826xb_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xbf86, 8, 8, 0x0)) != RT_ERR_OK) ++ return ret; ++ //PP_PHYReg_bit w $PHYID 0xbf86 7 7 0x1 ++ if ((ret = phy_rtl826xb_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xbf86, 7, 7, 0x1)) != RT_ERR_OK) ++ return ret; ++ //PP_PHYReg_bit w $PHYID 0xbf86 6 6 0x1 ++ if ((ret = phy_rtl826xb_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xbf86, 6, 6, 0x1)) != RT_ERR_OK) ++ return ret; ++ //PP_PHYReg_bit w $PHYID 0xbf86 5 5 0x1 ++ if ((ret = phy_rtl826xb_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xbf86, 5, 5, 0x1)) != RT_ERR_OK) ++ return ret; ++ //PP_PHYReg_bit w $PHYID 0xbf86 4 4 0x1; ++ if ((ret = phy_rtl826xb_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xbf86, 4, 4, 0x1)) != RT_ERR_OK) ++ return ret; ++ //PP_PHYReg_bit w $PHYID 0xbf86 6 6 0x0 ++ if ((ret = phy_rtl826xb_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xbf86, 6, 6, 0x0)) != RT_ERR_OK) ++ return ret; ++ //PP_PHYReg_bit w $PHYID 0xbf86 9 9 0x0 ++ if ((ret = phy_rtl826xb_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xbf86, 9, 9, 0x0)) != RT_ERR_OK) ++ return ret; ++ //PP_PHYReg_bit w $PHYID 0xbf86 7 7 0x0 ++ if ((ret = phy_rtl826xb_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xbf86, 7, 7, 0x0)) != RT_ERR_OK) ++ return ret; ++ ++ //PP_PHYReg_bit r $PHYID 0xbc62 12 8 ++ rData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xbc62); ++ ++ rData = REG32_FIELD_GET(rData, 8, 0x1F00); ++ for (cnt = 0; cnt <= rData; cnt++) ++ { ++ //PP_PHYReg_bit w $PHYID 0xbc62 12 8 $t ++ if ((ret = phy_rtl826xb_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xbc62, 12, 8, cnt)) != RT_ERR_OK) ++ return ret; ++ } ++ ++ //PP_PHYReg_bit w $PHYID 0xbc02 2 2 0x1 ++ if ((ret = phy_rtl826xb_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xbc02, 2, 2, 0x1)) != RT_ERR_OK) ++ return ret; ++ //PP_PHYReg_bit w $PHYID 0xbc02 3 3 0x1 ++ if ((ret = phy_rtl826xb_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xbc02, 3, 3, 0x1)) != RT_ERR_OK) ++ return ret; ++ ++ //PP_PHYReg_bit w $PHYID 0xbf86 6 6 0x1 ++ if ((ret = phy_rtl826xb_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xbf86, 6, 6, 0x1)) != RT_ERR_OK) ++ return ret; ++ //PP_PHYReg_bit w $PHYID 0xbf86 9 9 0x1 ++ if ((ret = phy_rtl826xb_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xbf86, 9, 9, 0x1)) != RT_ERR_OK) ++ return ret; ++ //PP_PHYReg_bit w $PHYID 0xbf86 7 7 0x1 ++ if ((ret = phy_rtl826xb_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xbf86, 7, 7, 0x1)) != RT_ERR_OK) ++ return ret; ++ //PP_PHYReg_bit w $PHYID 0xbc04 9 2 0xff ++ if ((ret = phy_rtl826xb_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xbc04, 9, 2, 0xff)) != RT_ERR_OK) ++ return ret; ++ ++ ++ //PP_PHYReg w $::broadcast_PHYID 0xA4a0 0x0180 ++ if ((ret = phy_rtl826xb_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xA4A0, 15, 0, 0x0180)) != RT_ERR_OK) ++ return ret; ++ ++ //[PP_PHYReg_bit r $PHYID 0xa600 7 0] ++ if ((ret = _phy_rtl826xb_patch_wait_not_equal(unit, port, PHY_MMD_VEND2, 0xa600, 0x1, 0xFF, bcast)) != RT_ERR_OK) ++ return ret; ++ ++ //PP_PHYReg w $::broadcast_PHYID 0xA436 0x801E ++ if ((ret = phy_rtl826xb_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xA436, 15, 0, 0x801E)) != RT_ERR_OK) ++ return ret; ++ //PP_PHYReg w $::broadcast_PHYID 0xA438 $currentVersion ++ if ((ret = phy_rtl826xb_patch_op(unit, port, portOffset, RTK_HWPATCH_OP_PHY, 0xff, 0x00, 0xA438, 15, 0, FW_VER)) != RT_ERR_OK) ++ return ret; ++ ++ if ((ret = _phy_rtl826xb_patch_process(unit, port, portOffset, patch_afe_conf, size_afe_conf, &cnt, bcast)) != RT_ERR_OK) ++ { ++ ++ return ret; ++ } ++ ++ ++ if ((ret = _phy_rtl826xb_patch_process(unit, port, portOffset, patch_top_conf, size_top_conf, &cnt, bcast))!= RT_ERR_OK) ++ { ++ ++ return ret; ++ } ++ ++ ++ if ((ret = _phy_rtl826xb_patch_process(unit, port, portOffset, patch_sds_conf, size_sds_conf, &cnt, bcast))!= RT_ERR_OK) ++ { ++ ++ return ret; ++ } ++ ++ ++ return ret; ++} ++ ++/* Function Name: ++ * phy_rtl826xb_broadcast_patch ++ * Description: ++ * apply patch data to PHY ++ * Input: ++ * unit - unit id ++ * baseport - base port id on the PHY chip ++ * portOffset - the index offset base on baseport for the port to patch ++ * perChip - 1 for per-chip mode, 0 for per-bus mode ++ * Output: ++ * None ++ * Return: ++ * RT_ERR_OK ++ * RT_ERR_FAILED ++ * RT_ERR_NOT_SUPPORTED ++ * RT_ERR_ABORT ++ * Note: ++ * None ++ */ ++a_int32_t phy_rtl826xb_broadcast_patch(a_uint32_t unit, a_uint32_t port, a_uint8_t portOffset) ++{ ++ return _phy_rtl826xb_patch(unit, port, portOffset, PHY_PATCH_OP_BCAST); ++} +\ No newline at end of file +diff --git a/src/hsl/phy/rtl.c b/src/hsl/phy/rtl.c +new file mode 100644 +index 00000000..d4191518 +--- /dev/null ++++ b/src/hsl/phy/rtl.c +@@ -0,0 +1,520 @@ ++/* ++ * Copyright (c) 2018-2019, 2021, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. ++ * 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. ++ */ ++ ++#include "phy_common.h" ++#include "phy_rtl826xb.h" ++#include "fal_port_ctrl.h" ++#include ++#include ++ ++ ++ ++#define RTL_PHY_LINK_UP 1 ++#define RTL_PHY_LINK_DOWN 0 ++ ++LIST_HEAD(g_rtl_phy_list); ++struct rtl_phy_info* rtl_phy_info_get(a_uint32_t phy_addr) ++{ ++ struct rtl_phy_info *pdata = NULL; ++ list_for_each_entry(pdata, &g_rtl_phy_list, list) { ++ if (pdata->phydev_addr == phy_addr) { ++ return pdata; ++ } ++ } ++ ++ SSDK_ERROR("%s can't get the data for phy addr: %d\n", __func__, phy_addr); ++ return NULL; ++} ++ ++static a_bool_t rtl_config_init_done = A_FALSE; ++static int rtl_config_init(struct phy_device *phydev) ++{ ++ a_uint32_t dev_id = 0, phy_id = 0; ++ a_uint16_t phyData; ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; ++ rtl_priv *priv = phydev->priv; ++ const struct rtl_phy_info *pdata = priv->phy_info; ++ dev_id = pdata->dev_id; ++ phy_id = pdata->phy_addr; ++ ++ linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT, mask); ++ linkmode_set_bit(ETHTOOL_LINK_MODE_MII_BIT, mask); ++ linkmode_set_bit(ETHTOOL_LINK_MODE_AUI_BIT, mask); ++ linkmode_set_bit(ETHTOOL_LINK_MODE_BNC_BIT, mask); ++ linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, mask); ++ linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, mask); ++ linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, mask); ++ linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, mask); ++ linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, mask); ++ linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, mask); ++ linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, mask); ++ linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, mask); ++ linkmode_set_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, mask); ++ linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, mask); ++ ++ linkmode_copy(phydev->supported, mask); ++ linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydev->supported); ++ linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydev->supported); ++ ++ if(linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydev->advertising)) ++ linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, mask); ++ if(linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydev->advertising)) ++ linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, mask); ++ linkmode_copy(phydev->advertising, mask); ++ ++ //close the 10G autoneg ability ++ phyData = phy_common_general_reg_mmd_get(dev_id, phy_id, PHY_MMD_AN, 32); ++ phyData &= (~(0x0080 | 0x0100 | 0x1000)); ++ phyData |= 0x0080; ++ phyData |= 0x0100; ++ phy_common_general_reg_mmd_set(dev_id, phy_id, PHY_MMD_AN, 32, phyData); ++ ++// phy_826xb_init(dev_id, phy_id); ++ ++ return 0; ++} ++ ++sw_error_t ++_phy_826x_interrupt_mask_get(a_uint32_t unit, a_uint32_t port, a_uint32_t *pEnaBitmap) ++{ ++ sw_error_t ret = RT_ERR_OK; ++ a_uint16_t phyData = 0; ++ a_uint32_t bitmap = 0; ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, 0xE1); ++ ++ ++ if (phyData & 0x0001) ++ bitmap |= RTK_PHY_CTRL_INTR_MASK_COMMON; ++ if (phyData & 0x0002) ++ bitmap |= RTK_PHY_CTRL_INTR_MASK_RLFD; ++ if (phyData & 0x0008) ++ bitmap |= RTK_PHY_CTRL_INTR_MASK_TM_LOW; ++ if (phyData & 0x0010) ++ bitmap |= RTK_PHY_CTRL_INTR_MASK_TM_HIGH; ++ *pEnaBitmap = bitmap; ++ return ret; ++} ++ ++ ++sw_error_t ++_phy_826xb_interrupt_mask_get(a_uint32_t unit, a_uint32_t port, a_uint16_t *pMask) ++{ ++ sw_error_t ret = 0; ++ a_uint32_t bitmap = 0; ++ ++ _phy_826x_interrupt_mask_get(unit, port, &bitmap); ++ ++ *pMask = (bitmap & (1 << 0)) ? (1) : (0); ++ return ret; ++} ++ ++sw_error_t ++_phy_826xb_interrupt_mask_set(a_uint32_t unit, a_uint32_t port, a_uint32_t enaBitmap) ++{ ++ sw_error_t ret = RT_ERR_OK; ++ a_uint16_t phyData = 0, currentData = 0; ++ ++ currentData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, 0xE1); ++ ++ phyData = currentData; ++ phyData &= (~(0x0001 | 0x0002 | 0x0008 | 0x0010)); ++ if (enaBitmap & RTK_PHY_CTRL_INTR_MASK_COMMON) ++ phyData |= 0x0001; ++ if (enaBitmap & RTK_PHY_CTRL_INTR_MASK_RLFD) ++ phyData |= 0x0002; ++ if (enaBitmap & RTK_PHY_CTRL_INTR_MASK_TM_LOW) ++ phyData |= 0x0008; ++ if (enaBitmap & RTK_PHY_CTRL_INTR_MASK_TM_HIGH) ++ phyData |= 0x0010; ++ ++ if (currentData != phyData) ++ { ++ ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0xE1, phyData); ++ return ret; ++ } ++ return ret; ++} ++ ++a_uint32_t ++phy_826xb_intrMask_set(a_uint32_t unit, a_uint32_t port, rtk_phy_intr_t phyIntr, a_uint32_t mask) ++{ ++ a_uint32_t ret = 0; ++ a_uint16_t bitmap = 0; ++ ++ if ((ret = _phy_826xb_interrupt_mask_get(unit, port, &bitmap)) != RT_ERR_OK) ++ return ret; ++ ++ if (mask == 0) ++ { ++ bitmap &= (~(1 << phyIntr)); ++ } ++ else ++ { ++ bitmap |= (1 << phyIntr); ++ } ++ ++ if ((ret = _phy_826xb_interrupt_mask_set(unit, port, bitmap)) != RT_ERR_OK) ++ return ret; ++ return ret; ++} ++ ++ ++static int rtl_config_intr(struct phy_device *phydev) ++{ ++ a_uint32_t dev_id = 0, phy_id = 0, bitmap = 0; ++ rtl_priv *priv = phydev->priv; ++ const struct rtl_phy_info *pdata = priv->phy_info; ++ dev_id = pdata->dev_id; ++ phy_id = pdata->phy_addr; ++ ++ if (phydev->interrupts == RTK_PHY_INTR_COMMON) ++ _phy_826xb_interrupt_mask_set(dev_id, phy_id, bitmap |(1 << RTK_PHY_INTR_COMMON)); ++ else if (phydev->interrupts == RTK_PHY_INTR_RLFD) ++ _phy_826xb_interrupt_mask_set(dev_id, phy_id, bitmap &(~(1 << RTK_PHY_INTR_RLFD))); ++ else if (phydev->interrupts == RTK_PHY_INTR_TM_LOW) ++ _phy_826xb_interrupt_mask_set(dev_id, phy_id, bitmap &(~(1 << RTK_PHY_INTR_TM_LOW))); ++ else if (phydev->interrupts == RTK_PHY_INTR_TM_HIGH) ++ _phy_826xb_interrupt_mask_set(dev_id, phy_id, bitmap &(~(1 << RTK_PHY_INTR_TM_HIGH))); ++ else if (phydev->interrupts == RTK_PHY_INTR_END) ++ _phy_826xb_interrupt_mask_set(dev_id, phy_id, bitmap &(~(1 << RTK_PHY_INTR_END))); ++ return 0; ++ ++} ++ ++static int rtl_ack_interrupt(struct phy_device *phydev) ++{ ++ return 0; ++ ++} ++ ++static a_uint32_t rtl_negtiation_cap_get(struct phy_device *phydev) ++{ ++ a_uint32_t autoneg = 0; ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(advertising) = { 0, }; ++ linkmode_and(advertising, phydev->advertising, phydev->supported); ++ ++if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, advertising)) { ++ autoneg |= FAL_PHY_ADV_PAUSE; ++ } ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, advertising)) { ++ autoneg |= FAL_PHY_ADV_ASY_PAUSE; ++ } ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, advertising)) { ++ autoneg |= FAL_PHY_ADV_10T_HD; ++ } ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, advertising)) { ++ autoneg |= FAL_PHY_ADV_10T_FD; ++ } ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, advertising)) { ++ autoneg |= FAL_PHY_ADV_100TX_HD; ++ } ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, advertising)) { ++ autoneg |= FAL_PHY_ADV_100TX_FD; ++ } ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, advertising)) { ++ autoneg |= FAL_PHY_ADV_1000T_FD; ++ } ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, advertising)) { ++ autoneg |= FAL_PHY_ADV_2500T_FD; ++ } ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, advertising)) { ++ autoneg |= FAL_PHY_ADV_5000T_FD; ++ } ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, advertising)) { ++ autoneg |= FAL_PHY_ADV_10000T_FD; ++ } ++ return autoneg; ++} ++ ++static int rtl_config_aneg(struct phy_device *phydev) ++{ ++ a_uint16_t phy_data = 0; ++ a_uint32_t dev_id = 0, phy_id = 0; ++ a_uint32_t advertise = 0; ++ rtl_priv *priv = phydev->priv; ++ const struct rtl_phy_info *pdata = priv->phy_info; ++ if (!pdata) { ++ return SW_FAIL; ++ } ++ dev_id = pdata->dev_id; ++ phy_id = pdata->phy_addr; ++ if (phydev->autoneg != AUTONEG_ENABLE) ++ { ++ /* force speed */ ++ phydev->pause = 0; ++ phydev->asym_pause = 0; ++ phy_data = phy_common_general_reg_mmd_get(dev_id, phy_id, PHY_MMD_AN, 0); ++ phy_data &= ~(0x1000); ++ ++ phy_826xb_duplex_set(dev_id, phy_id, phydev->duplex); ++ phy_826xb_speed_set(dev_id, phy_id, phydev->speed); ++ } else { ++ advertise = rtl_negtiation_cap_get(phydev); ++ /*link would be down if there is no speed adv except for pause*/ ++ if(!(advertise & ~(FAL_PHY_ADV_PAUSE | FAL_PHY_ADV_ASY_PAUSE))) { ++ return SW_BAD_VALUE; ++ } ++ ++ phy_826xb_autoNegoAbility_set(dev_id, phy_id, advertise); ++ phy_826xb_restart_autoneg(dev_id, phy_id); ++// phy_826xb_autoNegoEnable_set(dev_id, phy_id); ++ } ++ return 0; ++} ++ ++static int rtl_aneg_done(struct phy_device *phydev) ++{ ++ a_uint16_t phy_data; ++ a_uint32_t dev_id = 0, phy_id = 0; ++ rtl_priv *priv = phydev->priv; ++ const struct rtl_phy_info *pdata = priv->phy_info; ++ ++ if (!pdata) { ++ return SW_FAIL; ++ } ++ ++ dev_id = pdata->dev_id; ++ phy_id = pdata->phy_addr; ++ ++ phy_data = phy_common_general_reg_mmd_get(dev_id, phy_id, PHY_MMD_AN, 0x01); ++ ++ ++ return (phy_data < 0) ? phy_data : (phy_data & (1<<5)); ++} ++ ++static int rtl_read_status(struct phy_device *phydev) ++{ ++ struct port_phy_status phy_status; ++ a_uint32_t dev_id = 0, phy_id = 0; ++ rtl_priv *priv = phydev->priv; ++ const struct rtl_phy_info *pdata = priv->phy_info; ++ ++ if(!rtl_config_init_done) ++ { ++ if(!rtl_config_init(phydev)) ++ { ++ rtl_config_init_done = A_TRUE; ++ } ++ } ++ ++ if (!pdata) { ++ return SW_FAIL; ++ } ++ ++ ++ dev_id = pdata->dev_id; ++ phy_id = pdata->phy_addr; ++ ++ rtl826x_phy_get_status(dev_id, phy_id, &phy_status); ++ ++ if (phy_status.link_status) { ++ phydev->link = RTL_PHY_LINK_UP; ++ } else { ++ phydev->link = RTL_PHY_LINK_DOWN; ++ } ++ ++ switch (phy_status.speed) { ++ case FAL_SPEED_10000: ++ phydev->speed = SPEED_10000; ++ break; ++ case FAL_SPEED_5000: ++ phydev->speed = SPEED_5000; ++ break; ++ case FAL_SPEED_2500: ++ phydev->speed = SPEED_2500; ++ break; ++ case FAL_SPEED_1000: ++ phydev->speed = SPEED_1000; ++ break; ++ case FAL_SPEED_100: ++ phydev->speed = SPEED_100; ++ break; ++ default: ++ phydev->speed = SPEED_10; ++ break; ++ } ++ ++ if (phy_status.duplex == FAL_FULL_DUPLEX) { ++ phydev->duplex = DUPLEX_FULL; ++ } else { ++ phydev->duplex = DUPLEX_HALF; ++ } ++ return 0; ++} ++ ++static int rtl_suspend(struct phy_device *phydev) ++{ ++ a_uint32_t dev_id = 0, phy_id = 0; ++ rtl_priv *priv = phydev->priv; ++ const struct rtl_phy_info *pdata = priv->phy_info; ++ ++ if (!pdata) { ++ return SW_FAIL; ++ } ++ ++ dev_id = pdata->dev_id; ++ phy_id = pdata->phy_addr; ++ ++ return phy_826xb_poweroff(dev_id, phy_id); ++} ++ ++ ++static int rtl_resume(struct phy_device *phydev) ++{ ++ a_uint32_t dev_id = 0, phy_id = 0; ++ rtl_priv *priv = phydev->priv; ++ const struct rtl_phy_info *pdata = priv->phy_info; ++ ++ if (!pdata) { ++ return SW_FAIL; ++ } ++ ++ dev_id = pdata->dev_id; ++ phy_id = pdata->phy_addr; ++ ++ return phy_826xb_poweron(dev_id, phy_id); ++} ++ ++static a_bool_t rtl_sfp_present(struct phy_device *phydev) ++{ ++ rtl_priv *priv = phydev->priv; ++ struct rtl_phy_info *pdata = priv->phy_info; ++ a_uint32_t phy_id = 0; ++ sw_error_t rv = SW_OK; ++ ++ if (!pdata) { ++ SSDK_ERROR("pdata is null\n"); ++ return A_FALSE; ++ } ++ rv = phy_826xb_phy_id_get(pdata->dev_id, pdata->phy_addr, &phy_id); ++ if(rv == SW_READ_ERROR) { ++ return A_FALSE; ++ } ++ ++ return A_TRUE; ++} ++ ++ ++static int rtl_soft_reset(struct phy_device *phydev) ++{ ++ a_uint32_t dev_id = 0, phy_id = 0; ++ rtl_priv *priv = phydev->priv; ++ const struct rtl_phy_info *pdata = priv->phy_info; ++ ++ if(!rtl_sfp_present(phydev)) { ++ return 0; ++ } ++ ++ if (!pdata) { ++ return SW_FAIL; ++ } ++ ++ dev_id = pdata->dev_id; ++ phy_id = pdata->phy_addr; ++ ++ return phy_common_c45_reset_set(dev_id, phy_id); ++} ++ ++static void rtl_link_change_notify(struct phy_device *phydev) ++{ ++ ++ ++} ++ ++ ++ ++static int rtl_phy_probe(struct phy_device *phydev) ++{ ++ rtl_priv *priv; ++ int err = 0; ++ ++ priv = kzalloc(sizeof(rtl_priv), GFP_KERNEL); ++ if (!priv) { ++ return -ENOMEM; ++ } ++ ++ priv->phydev = phydev; ++ priv->phy_info = rtl_phy_info_get(phydev->mdio.addr); ++ ++ phydev->priv = priv; ++ ++ return err; ++} ++ ++static void rtl_phy_remove(struct phy_device *phydev) ++{ ++ rtl_priv *priv = phydev->priv; ++ kfree(priv); ++} ++ ++struct phy_driver rtl_phy_driver = { ++ .phy_id = RTL_PHY, ++ .phy_id_mask = 0xffffffff, ++ .name = "rtl ethernet", ++ .features = PHY_GBIT_FEATURES, ++ ++ .probe = rtl_phy_probe, ++ .remove = rtl_phy_remove, ++ .config_init = rtl_config_init, ++ .config_intr = rtl_config_intr, ++ .config_aneg = rtl_config_aneg, ++ .aneg_done = rtl_aneg_done, ++ .ack_interrupt = rtl_ack_interrupt, ++ .read_status = rtl_read_status, ++ .suspend = rtl_suspend, ++ .resume = rtl_resume, ++ .soft_reset = rtl_soft_reset, ++ .link_change_notify = rtl_link_change_notify, ++ .mdiodrv.driver = { .owner = THIS_MODULE }, ++}; ++ ++a_uint32_t rtl_phy_driver_register(void) ++{ ++ a_int32_t ret; ++ ret = phy_driver_register(&rtl_phy_driver, THIS_MODULE); ++ return ret; ++} ++ ++void rtl_phy_driver_unregister(void) ++{ ++ phy_driver_unregister(&rtl_phy_driver); ++} ++ ++void rtl_phydev_init(a_uint32_t dev_id, a_uint32_t port_id) ++{ ++ struct rtl_phy_info *pdata; ++ pdata = kzalloc(sizeof(struct rtl_phy_info), GFP_KERNEL); ++ ++ if (!pdata) { ++ return; ++ } ++ list_add_tail(&pdata->list, &g_rtl_phy_list); ++ pdata->dev_id = dev_id; ++ /* the phy address may be the i2c slave addr or mdio addr */ ++ pdata->phy_addr = qca_ssdk_port_to_phy_addr(dev_id, port_id); ++ pdata->phydev_addr = pdata->phy_addr; ++} ++ ++void rtl_phydev_deinit(a_uint32_t dev_id, a_uint32_t port_id) ++{ ++ struct rtl_phy_info *pdata, *pnext; ++ ++ ++ list_for_each_entry_safe(pdata, pnext, &g_rtl_phy_list, list) { ++ list_del(&pdata->list); ++ kfree(pdata); ++ } ++} +diff --git a/src/hsl/phy/rtl826xb_phy.c b/src/hsl/phy/rtl826xb_phy.c +new file mode 100644 +index 00000000..cd658e63 +--- /dev/null ++++ b/src/hsl/phy/rtl826xb_phy.c +@@ -0,0 +1,1521 @@ ++#include "sw.h" ++#include "fal_port_ctrl.h" ++#include "hsl_api.h" ++#include "hsl.h" ++#include "phy_common.h" ++#include "phy_rtl826xb.h" ++#include "hsl_phy.h" ++#include "ssdk_plat.h" ++ ++static a_bool_t phy_ops_flag = 0; ++static a_bool_t phy_dev_drv_init_flag = 0; ++ ++static struct mutex rtl_reg_lock; ++ ++#define RTL_LOCKER_INIT mutex_init(&rtl_reg_lock) ++#define RTL_REG_LOCK mutex_lock(&rtl_reg_lock) ++#define RTL_REG_UNLOCK mutex_unlock(&rtl_reg_lock) ++ ++ ++ ++#define RTK_PHY_CTRL_RTCT_CABLE_TYPE_NONE 0 ++#define RTK_PHY_CTRL_RTCT_CABLE_TYPE_CAT5E 1 ++#define RTK_PHY_CTRL_RTCT_CABLE_TYPE_CAT6A 2 ++#define RTK_PHY_CTRL_RTCT_CABLE_TYPE_CAT6A_UU 3 ++ ++#define RTK_PHY_CTRL_SERDES_MODE_USXGMII 0x0000 /* USXGMII */ ++#define RTK_PHY_CTRL_SERDES_MODE_UNKNOWN 0xFFFF ++ ++ ++ ++phy_rtl826xb_info_t *rtl826xb_info[RTK_MAX_NUM_OF_UNIT] = { NULL }; ++ ++ ++void rtl826xb_phy_lock_init(void) ++{ ++ static a_bool_t is_init = A_FALSE; ++ ++ if(!is_init) ++ { ++ RTL_LOCKER_INIT; ++ is_init = A_TRUE; ++ } ++ ++ return; ++} ++ ++ ++ ++static a_uint16_t rtl826x_phy_mmd_read(a_uint32_t dev_id, a_uint32_t phy_id, a_uint16_t reg_mmd, a_uint16_t reg_id) ++{ ++ a_uint16_t phy_data; ++ sw_error_t rv; ++ a_uint32_t reg_id_c45 = RTL826XB_REG_ADDRESS(reg_mmd, reg_id); ++ HSL_PHY_GET(rv, dev_id, phy_id, reg_id_c45, &phy_data); ++ ++ return phy_data; ++} ++ ++ ++static sw_error_t rtl826x_phy_mmd_write(a_uint32_t dev_id, a_uint32_t phy_id, a_uint16_t reg_mmd, a_uint16_t reg_id, a_uint16_t reg_val) ++{ ++ sw_error_t rv; ++ a_uint32_t reg_id_c45 = RTL826XB_REG_ADDRESS(reg_mmd, reg_id); ++ HSL_PHY_SET(rv, dev_id, phy_id, reg_id_c45, reg_val); ++ ++ return rv; ++} ++ ++ ++static a_uint16_t rtl826x_phy_reg_read(a_uint32_t dev_id, a_uint32_t phy_id, a_uint32_t reg) ++{ ++ a_uint16_t phy_data; ++ sw_error_t rv; ++ HSL_PHY_GET(rv, dev_id, phy_id, reg, &phy_data); ++ ++ return phy_data; ++} ++ ++ ++static sw_error_t rtl826x_phy_reg_write(a_uint32_t dev_id, a_uint32_t phy_id, a_uint32_t reg, a_uint16_t reg_val) ++{ ++ sw_error_t rv; ++ ++ HSL_PHY_SET(rv, dev_id, phy_id, reg, reg_val); ++ ++ return rv; ++} ++ ++ ++static a_int16_t hal_miim_mmd_read(a_uint32_t dev_id, a_uint32_t phy_id, a_uint16_t mmdAddr, a_uint16_t mmdReg) ++{ ++ a_uint16_t phy_data; ++ sw_error_t rv; ++ ++ a_uint32_t reg_id_c45 = RTL826XB_REG_ADDRESS(mmdAddr, mmdReg); ++ ++ HSL_PHY_GET(rv, dev_id, phy_id, reg_id_c45, &phy_data); ++ ++ return phy_data; ++} ++ ++ ++ ++static a_int32_t hal_miim_mmd_write(a_uint32_t dev_id, a_uint32_t phy_id, a_uint16_t mmdAddr, a_uint16_t mmdReg, a_uint16_t phy_data) ++{ ++ sw_error_t rv; ++ ++ a_uint32_t reg_id_c45 = RTL826XB_REG_ADDRESS(mmdAddr, mmdReg); ++ ++ HSL_PHY_SET(rv, dev_id, phy_id, reg_id_c45, phy_data); ++ ++ ++ return rv; ++} ++ ++ ++/* Function Name: ++ * phy_common_general_reg_mmd_get ++ * Description: ++ * Get PHY registers. Support access C45 reg by C22 format when connect to C22 MAC. ++ * Input: ++ * unit - unit id ++ * port - port id ++ * mmdAddr - mmd device address ++ * mmdReg - mmd reg id ++ * Output: ++ * pData - pointer buffer of read data ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - Failed ++ * Note: ++ * None ++ */ ++ ++ a_uint16_t ++phy_common_general_reg_mmd_get(a_uint32_t unit, a_uint32_t port, a_uint16_t mmdAddr, a_uint16_t mmdReg) ++{ ++ return hal_miim_mmd_read(unit, port, mmdAddr, mmdReg); ++} ++ ++ ++/* Function Name: ++ * phy_common_general_reg_mmd_set ++ * Description: ++ * Set PHY registers. Support access C45 reg by C22 format when connect to C22 MAC. ++ * Input: ++ * unit - unit id ++ * port - port id ++ * mmdAddr - mmd device address ++ * mmdReg - mmd reg id ++ * data - write data ++ * Output: ++ * None ++ * Return: ++ * RT_ERR_OK - OK ++ * RT_ERR_FAILED - Failed ++ * Note: ++ * None ++ */ ++a_int32_t ++phy_common_general_reg_mmd_set(a_uint32_t unit, a_uint32_t port, a_uint16_t mmdAddr, a_uint16_t mmdReg, a_uint16_t data) ++{ ++ /* temporary support C45 only */ ++ return hal_miim_mmd_write(unit, port, mmdAddr, mmdReg, data); ++} ++ ++ ++sw_error_t phy_common_c45_speed_get(a_uint32_t unit, a_uint32_t port, fal_port_speed_t *pSpeed) ++{ ++ struct port_phy_status phy_status = {0}; ++ rtl826x_phy_get_status(unit, port, &phy_status); ++ *pSpeed=phy_status.speed; ++ return SW_OK; ++} ++ ++ ++a_int32_t ++_phy_826xb_loopback_remote_set(a_uint32_t unit, a_uint32_t port, a_uint32_t ena) ++{ ++ ++ a_uint16_t phyData = 0; ++ fal_port_speed_t speed; ++ ++ phy_common_c45_speed_get(unit, port, &speed); ++ ++ ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xBCE8, 0x0040); ++ ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xC800, 0x5A02); ++ ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xC416, 0x0550); ++ ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xC464, 0x0001); ++ ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xC45E, 0x2C84); ++ ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xC45C, 0xAC61); ++ ++ ++ if (ena != 0) ++ { ++ switch (speed) ++ { ++ case FAL_SPEED_100: ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xBCE8); ++ ++ phyData |= REG32_FIELD_SET(phyData, 1, 13, 0x2000); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xBCE8, phyData); ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xC800); ++ ++ phyData = REG32_FIELD_SET(phyData, 1, 4, 0x0030); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xC800, phyData); ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xC416); ++ ++ phyData = REG32_FIELD_SET(phyData, 3, 2, 0x000C); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xC416, phyData); ++ ++ break; ++ ++ case FAL_SPEED_1000: ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xC800); ++ ++ phyData = REG32_FIELD_SET(phyData, 1, 4, 0x0030); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xC800, phyData); ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xC416); ++ ++ phyData = REG32_FIELD_SET(phyData, 3, 2, 0x000C); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xC416, phyData); ++ ++ break; ++ ++ default: ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xC464); ++ ++ phyData &= (~RTLBIT_0); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xC464, phyData); ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xC464); ++ ++ phyData |= (RTLBIT_1); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xC464, phyData); ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xC464); ++ ++ phyData |= (RTLBIT_0); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xC464, phyData); ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xC45E); ++ ++ phyData |= (RTLBIT_15); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xC45E, phyData); ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xC45C); ++ ++ phyData &= (~RTLBIT_13); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xC45C, phyData); ++ ++ break; ++ } ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, 0x2A1); ++ ++ phyData |= (RTLBIT_10); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0x2A1, phyData); ++ ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, 0x291); ++ ++ phyData |= (RTLBIT_5); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0x291, phyData); ++ ++ } ++ else ++ { ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, 0x2A1); ++ ++ phyData &= (~RTLBIT_10); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0x2A1, phyData); ++ ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, 0x291); ++ ++ phyData &= (~RTLBIT_5); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0x291, phyData); ++ ++ } ++ return SW_OK; ++} ++ ++ ++ ++a_int32_t ++phy_826xb_broadcastEnable_set(a_uint32_t unit, a_uint32_t port, rtk_enable_t enable) ++{ ++ ++ a_uint16_t phyData = 0; ++ ++ if (enable == DISABLED) ++ { ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0x9003, 0); ++ ++ } ++ else ++ { ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, 0x9003); ++ ++ phyData |= (RTLBIT_15); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0x9003, phyData); ++ ++ } ++ ++ return SW_OK; ++} ++ ++ ++a_int32_t ++phy_826xb_broadcastID_set(a_uint32_t unit, a_uint32_t port, a_uint32_t broadcastID) ++{ ++ a_uint16_t phyData = 0; ++ ++ if (broadcastID > 0x1F) ++ return SW_OUT_OF_RANGE; ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, 0x9003); ++ ++ phyData = REG32_FIELD_SET(phyData, broadcastID, 0, 0x1F); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0x9003, phyData); ++ ++ return SW_OK; ++} ++ ++a_int32_t ++_phy_826xb_rtct_cable_set(a_uint32_t unit, a_uint32_t port, a_uint32_t cableType) ++{ ++ a_int32_t ret = RT_ERR_OK; ++ ++ rtl826xb_info[unit]->rtctCable[port] = cableType; ++ return ret; ++} ++ ++/* Function Name: ++ * phy_826xb_ctrl_set ++ * Description: ++ * Set PHY settings for specific feature ++ * Input: ++ * unit - unit id ++ * port - port id ++ * ctrl_type - setting type ++ * value - setting value ++ * Output: ++ * None ++ * Return: ++ * RT_ERR_OK ++ * RT_ERR_FAILED ++ * RT_ERR_NOT_SUPPORTED ++ * Note: ++ * None ++ */ ++sw_error_t ++phy_826xb_ctrl_set(a_uint32_t unit, a_uint32_t port, rtk_phy_ctrl_t ctrl_type, a_uint16_t value) ++{ ++ // a_int32_t ret = 0; ++ a_uint16_t phyData = 0; ++ // a_uint32_t tmp = 0; ++ ++ switch (ctrl_type) ++ { ++/* case RTK_PHY_CTRL_LED_1_MODE: ++ case RTK_PHY_CTRL_LED_2_MODE: ++ case RTK_PHY_CTRL_LED_3_MODE: ++ case RTK_PHY_CTRL_LED_4_MODE: ++ case RTK_PHY_CTRL_LED_5_MODE: ++ case RTK_PHY_CTRL_LED_6_MODE: ++ ret = _phy_826xb_led_mode_set(unit, port, (ctrl_type - RTK_PHY_CTRL_LED_1_MODE), value); ++ break; ++ case RTK_PHY_CTRL_LED_CFG_FLASH_RATE: ++ ret = _phy_826xb_led_config_flash_rate_set(unit, port, value); ++ break; ++ case RTK_PHY_CTRL_LED_CFG_BLINK_RATE: ++ ret = _phy_826xb_led_config_blink_rate_set(unit, port, value); ++ break; ++ case RTK_PHY_CTRL_LED_1_CFG_ACTIVE_LOW: ++ case RTK_PHY_CTRL_LED_2_CFG_ACTIVE_LOW: ++ case RTK_PHY_CTRL_LED_3_CFG_ACTIVE_LOW: ++ case RTK_PHY_CTRL_LED_4_CFG_ACTIVE_LOW: ++ case RTK_PHY_CTRL_LED_5_CFG_ACTIVE_LOW: ++ case RTK_PHY_CTRL_LED_6_CFG_ACTIVE_LOW: ++ ret = _phy_826xb_led_config_active_low_set(unit, port, (ctrl_type - RTK_PHY_CTRL_LED_1_CFG_ACTIVE_LOW), value); ++ break; ++ case RTK_PHY_CTRL_LED_1_CFG_FORCE: ++ case RTK_PHY_CTRL_LED_2_CFG_FORCE: ++ case RTK_PHY_CTRL_LED_3_CFG_FORCE: ++ case RTK_PHY_CTRL_LED_4_CFG_FORCE: ++ case RTK_PHY_CTRL_LED_5_CFG_FORCE: ++ case RTK_PHY_CTRL_LED_6_CFG_FORCE: ++ ret = _phy_826xb_led_config_force_set(unit, port, (ctrl_type - RTK_PHY_CTRL_LED_1_CFG_FORCE), value); ++ break; ++ ++ case RTK_PHY_CTRL_LOOPBACK_INTERNAL_PMA: ++ if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_PMAPMD, 0, &phyData)) != RT_ERR_OK) ++ return ret; ++ phyData &= (~RTLBIT_0); ++ phyData |= (value == 0)? (0):(RTLBIT_0); ++ if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_PMAPMD, 0, phyData)) != RT_ERR_OK) ++ return ret; ++ break;*/ ++ ++ case RTK_PHY_CTRL_LOOPBACK_REMOTE: ++ _phy_826xb_loopback_remote_set(unit, port, value); ++ break; ++ ++ case RTK_PHY_CTRL_RAPID_LINK_FAULT_DETECT: ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xA442); ++ ++ phyData &= (~RTLBIT_15); ++ phyData |= (value == 0)? (0):(RTLBIT_15); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xA442, phyData); ++ ++ break; ++ ++ /* case RTK_PHY_CTRL_MDI_INVERSE: ++ RT_LOG(LOG_DEBUG, (MOD_DAL|MOD_PHY), "u %u,p %u,RTK_PHY_CTRL_MDI_INVERSE=0x%X ", unit, port, value); ++ if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, 0x100, &phyData)) != RT_ERR_OK) ++ return ret; ++ phyData &= (~RTLBIT_10); ++ phyData |= (value == 0)? (0):(RTLBIT_10); ++ if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0x100, phyData)) != RT_ERR_OK) ++ return ret; ++ break; ++ case RTK_PHY_CTRL_MDI_POLARITY_SWAP: ++ RT_LOG(LOG_DEBUG, (MOD_DAL|MOD_PHY), "u %u,p %u,RTK_PHY_CTRL_MDI_POLARITY_SWAP=0x%X ", unit, port, value); ++ if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, 0x31, &phyData)) != RT_ERR_OK) ++ return ret; ++ phyData &= (~(RTLBIT_0 | RTLBIT_1 | RTLBIT_2 | RTLBIT_3)); ++ phyData |= (value & RTK_PHY_CTRL_MDI_POLARITY_SWAP_CH_A)? (RTLBIT_0) : (0); ++ phyData |= (value & RTK_PHY_CTRL_MDI_POLARITY_SWAP_CH_B)? (RTLBIT_1) : (0); ++ phyData |= (value & RTK_PHY_CTRL_MDI_POLARITY_SWAP_CH_C)? (RTLBIT_2) : (0); ++ phyData |= (value & RTK_PHY_CTRL_MDI_POLARITY_SWAP_CH_D)? (RTLBIT_3) : (0); ++ if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0x31, phyData)) != RT_ERR_OK) ++ return ret; ++ break; ++ ++ case RTK_PHY_CTRL_PREAMBLE_RECOVERY: ++ if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, 0x71, &phyData)) != RT_ERR_OK) ++ return ret; ++ phyData &= (~RTLBIT_12); ++ phyData |= (value == 0)? (0):(RTLBIT_12); ++ if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0x71, phyData)) != RT_ERR_OK) ++ return ret; ++ break; ++ ++ case RTK_PHY_CTRL_SYNCE: ++ ret = _phy_826xb_synce_enable_set(unit, port, value); ++ break; ++ case RTK_PHY_CTRL_SYNCE_PLL: ++ ret = _phy_826xb_synce_pll_set(unit, port, value); ++ break; ++ case RTK_PHY_CTRL_SYNCE_0_CLOCK_FREQ: ++ case RTK_PHY_CTRL_SYNCE_1_CLOCK_FREQ: ++ ret = _phy_826xb_synce_clock_freq_set(unit, port, (ctrl_type - RTK_PHY_CTRL_SYNCE_CLOCK_FREQ), value); ++ break; ++ case RTK_PHY_CTRL_SYNCE_0_RECOVERY_PHY: ++ case RTK_PHY_CTRL_SYNCE_1_RECOVERY_PHY: ++ ret = _phy_826xb_synce_recovery_phy_set(unit, port, (ctrl_type - RTK_PHY_CTRL_SYNCE_RECOVERY_PHY), value); ++ break; ++ case RTK_PHY_CTRL_SYNCE_0_IDLE_MODE: ++ case RTK_PHY_CTRL_SYNCE_1_IDLE_MODE: ++ ret = _phy_826xb_synce_idle_mode_set(unit, port, (ctrl_type - RTK_PHY_CTRL_SYNCE_IDLE_MODE), value); ++ break; ++ ++ case RTK_PHY_CTRL_NBASET_802P3BZ_MASK: ++ if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xA5E8, &phyData)) != RT_ERR_OK) ++ return ret; ++ phyData &= (~(RTLBIT_13 | RTLBIT_14)); ++ phyData |= (value == 0)? (0):(RTLBIT_13 | RTLBIT_14); ++ if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xA5E8, phyData)) != RT_ERR_OK) ++ return ret; ++ ret = _phy_826xb_an_restart(unit, port); ++ break; ++ case RTK_PHY_CTRL_NBASET: ++ if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xA5EA, &phyData)) != RT_ERR_OK) ++ return ret; ++ phyData &= (~(RTLBIT_15)); ++ phyData |= (value == 0)? (RTLBIT_15):(0); ++ if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xA5EA, phyData)) != RT_ERR_OK) ++ return ret; ++ ret = _phy_826xb_an_restart(unit, port); ++ break; ++ ++ case RTK_PHY_CTRL_TEMP_THRESHOLD_HIGH_LOWER: ++ case RTK_PHY_CTRL_TEMP_THRESHOLD_HIGH_HIGHER: ++ case RTK_PHY_CTRL_TEMP_THRESHOLD_LOW_LOWER: ++ case RTK_PHY_CTRL_TEMP_THRESHOLD_LOW_HIGHER: ++ ret = _phy_826xb_temperature_threshold_set(unit, port, ctrl_type, value); ++ break; ++ ++ case RTK_PHY_CTRL_FAST_RETRAIN_NFR: ++ switch (value) ++ { ++ case RTK_PHY_CTRL_FAST_RETRAIN_NFR_ENABLE: ++ if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xA5EA, &phyData)) != RT_ERR_OK) ++ return ret; ++ phyData &= (~RTLBIT_14); ++ if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xA5EA, phyData)) != RT_ERR_OK) ++ return ret; ++ ++ if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xA654, &phyData)) != RT_ERR_OK) ++ return ret; ++ phyData |= (RTLBIT_11); ++ if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xA654, phyData)) != RT_ERR_OK) ++ return ret; ++ break; ++ ++ case RTK_PHY_CTRL_FAST_RETRAIN_NFR_DISABLE: ++ if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xA5EA, &phyData)) != RT_ERR_OK) ++ return ret; ++ phyData |= (RTLBIT_14); ++ if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xA5EA, phyData)) != RT_ERR_OK) ++ return ret; ++ ++ if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xA654, &phyData)) != RT_ERR_OK) ++ return ret; ++ phyData &= (~RTLBIT_11); ++ if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xA654, phyData)) != RT_ERR_OK) ++ return ret; ++ break; ++ ++ default: ++ return RT_ERR_INPUT; ++ } ++ ret = _phy_826xb_an_restart(unit, port); ++ break; ++ ++ case RTK_PHY_CTRL_FAST_RETRAIN: ++ switch (value) ++ { ++ case RTK_PHY_CTRL_FAST_RETRAIN_ENABLE: ++ if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_AN, 32, &phyData)) != RT_ERR_OK) ++ return ret; ++ phyData |= (RTLBIT_6 | RTLBIT_5 | RTLBIT_1); ++ if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_AN, 32, phyData)) != RT_ERR_OK) ++ return ret; ++ ++ if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xA6D8, &phyData)) != RT_ERR_OK) ++ return ret; ++ phyData |= (RTLBIT_7 | RTLBIT_1 | RTLBIT_0); ++ if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xA6D8, phyData)) != RT_ERR_OK) ++ return ret; ++ break; ++ ++ case RTK_PHY_CTRL_FAST_RETRAIN_DISABLE: ++ ++ if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_AN, 32, &phyData)) != RT_ERR_OK) ++ return ret; ++ phyData &= (~(RTLBIT_6 | RTLBIT_5 | RTLBIT_1)); ++ if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_AN, 32, phyData)) != RT_ERR_OK) ++ return ret; ++ ++ if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xA6D8, &phyData)) != RT_ERR_OK) ++ return ret; ++ phyData &= (~(RTLBIT_7 | RTLBIT_1 | RTLBIT_0)); ++ if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xA6D8, phyData)) != RT_ERR_OK) ++ return ret; ++ break; ++ ++ default: ++ return RT_ERR_INPUT; ++ } ++ ret = _phy_826xb_an_restart(unit, port); ++ break;*/ ++ ++ case RTK_PHY_CTRL_COUNTER_CLEAR: ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xC802); ++ ++ phyData &= (~(0xFF)); ++ phyData |= (0x73); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xC802, phyData); ++ ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, 0x1EF); ++ ++ phyData |= (RTLBIT_13 | RTLBIT_14 | RTLBIT_15); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0x1EF, phyData); ++ ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, 0x1EF); ++ ++ phyData &= (~(RTLBIT_13 | RTLBIT_14 | RTLBIT_15)); ++ ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0x1EF, phyData); ++ ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, 0x230); ++ ++ phyData |= (RTLBIT_6 | RTLBIT_7 | RTLBIT_8); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0x230, phyData); ++ ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, 0x230); ++ ++ phyData &= (~(RTLBIT_6 | RTLBIT_7 | RTLBIT_8)); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0x230, phyData); ++ ++ break; ++ ++ /* case RTK_PHY_CTRL_SERDES_MODE: ++ ret = _phy_826xb_serdes_mode_set(unit, port, value); ++ break; ++ case RTK_PHY_CTRL_SERDES_UPDTAE: ++ ret = _phy_826xb_serdes_mode_update(unit, port); ++ break; ++ case RTK_PHY_CTRL_SERDES_USXGMII_AN: ++ if ((ret = _phy_826xb_serdes_reg_read(unit, port, 7, 17, &phyData)) != RT_ERR_OK) ++ return ret; ++ tmp = (phyData & RTLBIT_0) ? (1) : (0); ++ if (tmp != value) ++ { ++ phyData &= (~RTLBIT_0); ++ phyData |= (value == 0) ? (0) : (RTLBIT_0); ++ if ((ret = _phy_826xb_serdes_reg_write(unit, port, 7, 17, phyData)) != RT_ERR_OK) ++ return ret; ++ } ++ break; ++ case RTK_PHY_CTRL_SERDES_SGMII_AN: ++ if ((ret = _phy_826xb_serdes_reg_read(unit, port, 0, 2, &phyData)) != RT_ERR_OK) ++ return ret; ++ tmp = (phyData & RTLBIT_8) ? (0) : (1); ++ if (tmp != value) ++ { ++ phyData &= (~(RTLBIT_8 | RTLBIT_9)); ++ phyData |= (value == 0) ? (RTLBIT_8) : (0); ++ if ((ret = _phy_826xb_serdes_reg_write(unit, port, 0, 2, phyData)) != RT_ERR_OK) ++ return ret; ++ } ++ break; ++ case RTK_PHY_CTRL_SERDES_BASEX_AN: ++ if ((ret = _phy_826xb_serdes_reg_read(unit, port, 2, 0, &phyData)) != RT_ERR_OK) ++ return ret; ++ tmp = (phyData & RTLBIT_12) ? (1) : (0); ++ if (tmp != value) ++ { ++ phyData &= (~RTLBIT_12); ++ phyData |= (value == 0) ? (0) : (RTLBIT_12); ++ if ((ret = _phy_826xb_serdes_reg_write(unit, port, 2, 0, phyData)) != RT_ERR_OK) ++ return ret; ++ } ++ break; ++ ++ case RTK_PHY_CTRL_SNR_THRESHOLD_10G_MASTER: ++ if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xB87C, 0x8188)) != RT_ERR_OK) ++ return ret; ++ if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xB87E, value)) != RT_ERR_OK) ++ return ret; ++ break; ++ case RTK_PHY_CTRL_SNR_THRESHOLD_10G_SLAVE: ++ if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xB87C, 0x8152)) != RT_ERR_OK) ++ return ret; ++ if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xB87E, value)) != RT_ERR_OK) ++ return ret; ++ break; ++ case RTK_PHY_CTRL_SNR_THRESHOLD_5G_MASTER: ++ if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xB87C, 0x811C)) != RT_ERR_OK) ++ return ret; ++ if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xB87E, value)) != RT_ERR_OK) ++ return ret; ++ break; ++ case RTK_PHY_CTRL_SNR_THRESHOLD_5G_SLAVE: ++ if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xB87C, 0x80E6)) != RT_ERR_OK) ++ return ret; ++ if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xB87E, value)) != RT_ERR_OK) ++ return ret; ++ break; ++ case RTK_PHY_CTRL_SNR_THRESHOLD_2P5G_MASTER: ++ if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xB87C, 0x80B0)) != RT_ERR_OK) ++ return ret; ++ if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xB87E, value)) != RT_ERR_OK) ++ return ret; ++ break; ++ case RTK_PHY_CTRL_SNR_THRESHOLD_2P5G_SLAVE: ++ if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xB87C, 0x807A)) != RT_ERR_OK) ++ return ret; ++ if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xB87E, value)) != RT_ERR_OK) ++ return ret; ++ break; ++ case RTK_PHY_CTRL_SNR_THRESHOLD_1G: ++ if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xA804, value)) != RT_ERR_OK) ++ return ret; ++ break; ++ ++ case RTK_PHY_CTRL_DEBUG_DUMP_DSP: ++ ret = _phy_826xb_debug_dump_dsp(unit, port, value); ++ break; ++ case RTK_PHY_CTRL_DEBUG_DUMP_DSP_INIT: ++ ret = _phy_826xb_debug_dump_dsp_init(unit, port, value); ++ break; ++ case RTK_PHY_CTRL_DEBUG_DUMP_COUPLING: ++ ret = _phy_826xb_debug_coupling_dump(unit, port, value); ++ break; ++ case RTK_PHY_CTRL_REINIT: ++ ret = _phy_826xb_reinit(unit, port); ++ break;*/ ++ case RTK_PHY_CTRL_MIIM_BCAST: ++ phy_826xb_broadcastEnable_set(unit, port, (value == 0)? (DISABLED):(ENABLED)); ++ break; ++ ++ case RTK_PHY_CTRL_MIIM_BCAST_PHYAD: ++ phy_826xb_broadcastID_set(unit, port, value); ++ break; ++ ++ /* case RTK_PHY_CTRL_SERDES_LOOPBACK_REMOTE: ++ ret = _phy_826xb_serdes_loopback_set(unit, port, value); ++ break; ++ ++ case RTK_PHY_CTRL_SERDES_TX_POLARITY: ++ if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, 0xC1, &phyData)) != RT_ERR_OK) ++ return ret; ++ phyData &= (~RTLBIT_7); ++ phyData |= (value == 0) ? (0) : (RTLBIT_7); ++ if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0xC1, phyData)) != RT_ERR_OK) ++ return ret; ++ break; ++ case RTK_PHY_CTRL_SERDES_RX_POLARITY: ++ if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, 0xC1, &phyData)) != RT_ERR_OK) ++ return ret; ++ phyData &= (~RTLBIT_6); ++ phyData |= (value == 0) ? (0) : (RTLBIT_6); ++ if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0xC1, phyData)) != RT_ERR_OK) ++ return ret; ++ break;*/ ++ ++ case RTK_PHY_CTRL_RTCT_CABLE_TYPE: ++ _phy_826xb_rtct_cable_set(unit, port, value); ++ break; ++ ++ /* case RTK_PHY_CTRL_SERDES_EYE_PARAM_TYPE: ++ rtl826xb_info[unit]->eyeParamTarget[port] = value; ++ ret = RT_ERR_OK; ++ break; ++ ++ case RTK_PHY_CTRL_PTP_REFTIME_TOD_DELAY: ++ if (value > 0xFFFF) ++ return RT_ERR_OUT_OF_RANGE; ++ if ((ret = _phy_826xb_topReg_write(unit, port, 42, 16, 15, 0, value)) != RT_ERR_OK) ++ return ret; ++ break; ++ ++ case RTK_PHY_CTRL_PTP_DURATION_THRESHOLD: ++ if (value > 0x3FF) ++ return RT_ERR_OUT_OF_RANGE; ++ if ((ret = _phy_826xb_topReg_write(unit, port, 42, 17, 9, 0, value)) != RT_ERR_OK) ++ return ret; ++ break; ++ ++ case RTK_PHY_CTRL_PTP_PORT_ROLE: ++ switch (value) ++ { ++ case RTK_PHY_CTRL_PTP_PORT_ROLE_NONE: ++ phyData = 0x0; ++ break; ++ case RTK_PHY_CTRL_PTP_PORT_ROLE_BC_OC: ++ phyData = 0x1; ++ break; ++ case RTK_PHY_CTRL_PTP_PORT_ROLE_E2E_TC: ++ phyData = 0x2; ++ break; ++ case RTK_PHY_CTRL_PTP_PORT_ROLE_P2P_TC: ++ phyData = 0x3; ++ break; ++ default: ++ return RT_ERR_INPUT; ++ } ++ if ((ret = _phy_826xb_topReg_write(unit, port, 50, 16, 3, 2, phyData)) != RT_ERR_OK) ++ return ret; ++ break; ++ ++ case RTK_PHY_CTRL_PTP_TX_IMBAL: ++ if (value > 0xFFF) ++ return RT_ERR_OUT_OF_RANGE; ++ if ((ret = _phy_826xb_topReg_write(unit, port, 50, 19, 11, 0, value)) != RT_ERR_OK) ++ return ret; ++ break; ++ ++ case RTK_PHY_CTRL_PTP_RX_IMBAL: ++ if (value > 0xFFF) ++ return RT_ERR_OUT_OF_RANGE; ++ if ((ret = _phy_826xb_topReg_write(unit, port, 50, 20, 11, 0, value)) != RT_ERR_OK) ++ return ret; ++ break; ++ ++ case RTK_PHY_CTRL_PTP_CLOCK_SRC: ++ if ((ret = _phy_826xb_topReg_write(unit, port, 47, 19, 0, 0, (value == RTK_PHY_CTRL_PTP_CLOCK_SRC_INT) ? 0 : 1)) != RT_ERR_OK) ++ return ret; ++ break; ++ ++ case RTK_PHY_CTRL_PTP: ++ if ((ret = phy_826xb_ptp_portPtpEnable_set(unit, port, (value == 0) ? DISABLED : ENABLED)) != RT_ERR_OK) ++ return ret; ++ break; ++ ++ case RTK_PHY_CTRL_PTP_PLL_POW_SRC: ++ if ((ret = phy_826xb_ptp_pll_pow_src_set(unit, port, value)) != RT_ERR_OK) ++ return ret; ++ break; ++ ++ case RTK_PHY_CTRL_PTP_PLL_CLK: ++ if ((ret = phy_826xb_ptp_pll_clk_set(unit, port, value)) != RT_ERR_OK) ++ return ret; ++ break; ++ ++ case RTK_PHY_CTRL_PTP_PLL: ++ if ((ret = _phy_826xb_topReg_write(unit, port, 57, 20, 4, 4, (value == 0) ? 0x0 : 0x1)) != RT_ERR_OK) ++ return ret; ++ break; ++ ++ case RTK_PHY_CTRL_MACSEC_BYPASS: ++ if ((ret = phy_826xb_macsec_bypass_set(unit, port, (value == 0) ? DISABLED : ENABLED)) != RT_ERR_OK) ++ return ret; ++ break;*/ ++ ++ default: ++ return RT_ERR_PORT_NOT_SUPPORTED; ++ } ++ ++ return SW_OK; ++} ++ ++a_int32_t ++_phy_826xb_serdes_mode_init(a_uint32_t unit, a_uint32_t port) ++{ ++ ++ a_uint16_t phyData = 0; ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, 0x105); ++ ++ ++ if(phyData & 0x1) ++ { ++ rtl826xb_info[unit]->sdsModeCfg[port] = RTK_PHY_CTRL_SERDES_MODE_UNKNOWN; ++ } ++ else ++ { ++ rtl826xb_info[unit]->sdsModeCfg[port] = RTK_PHY_CTRL_SERDES_MODE_USXGMII; ++ } ++ ++ return RT_ERR_OK; ++} ++ ++ ++a_int32_t ++_phy_826xb_interrupt_init(a_uint32_t unit, a_uint32_t port) ++{ ++ ++ a_uint16_t phyData = 0; ++ ++ /* Disable all IMR*/ ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0xE1, 0); ++ ++ /* Disable all SDS IMR*/ ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0xE3, 0); ++ ++ ++ /* Set SDS interrupt source to INT_PHY0 */ ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0xE4, 0x1); ++ ++ ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0xE0, 0x2F); ++ ++ ++ /* rlfd_en */ ++ phy_826xb_ctrl_set(unit, port, RTK_PHY_CTRL_RAPID_LINK_FAULT_DETECT, 1); ++ ++ ++ /* rlfd_fr_en */ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xA448); ++ ++ phyData |= (RTLBIT_7); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xA448, phyData); ++ ++ ++ /* clear status */ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xA43A); ++ ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0xE2, 0x3F); ++ ++ ++ return SW_OK; ++} ++ ++ ++a_int32_t ++_phy_826xb_dbgCount_init(a_uint32_t unit, a_uint32_t port) ++{ ++ a_int32_t ret = RT_ERR_OK; ++ a_uint16_t phyData = 0; ++ ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xC800, 0x5A02); ++ ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, 0x1EE); ++ ++ phyData |= RTLBIT_1; ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0x1EE, phyData); ++ ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, 0x230); ++ ++ phyData |= RTLBIT_1; ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0x230, phyData); ++ ++ ++ phy_826xb_ctrl_set(unit, port, RTK_PHY_CTRL_COUNTER_CLEAR, 1); ++ return ret; ++} ++ ++ ++a_int8_t ++_phy_826xb_is_single_port(a_uint32_t unit, a_uint32_t port) ++{ ++ ++ a_uint16_t phyData; ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, 0x103); ++ ++ ++ if ((phyData & 0xF) == 0x1) ++ { ++ return 1; ++ } ++ ++ return 0; ++} ++ ++a_int32_t ++_phy_826xb_synce_init(a_uint32_t unit, a_uint32_t port) ++{ ++ ++ a_uint16_t phyData = 0; ++ a_uint32_t is_singlePort = _phy_826xb_is_single_port(unit, port); ++ ++ if (1 == is_singlePort) ++ { ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, 0x1C8); ++ ++ phyData &= (~(RTLBIT_3)); ++ phyData |= (RTLBIT_8); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0x1C8, phyData); ++ ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, 0x1C9); ++ ++ phyData &= (~(RTLBIT_4 | RTLBIT_12)); ++ phyData |= (RTLBIT_7 | RTLBIT_15); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0x1C9, phyData); ++ ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, 0x1CA); ++ ++ phyData &= (~(RTLBIT_0 | RTLBIT_1 | RTLBIT_2 | RTLBIT_3 | RTLBIT_4 | RTLBIT_8 | RTLBIT_9 | RTLBIT_10 | RTLBIT_11 | RTLBIT_12 | RTLBIT_15)); ++ phyData |= (RTLBIT_5 | RTLBIT_13); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0x1CA, phyData); ++ ++ } ++ else ++ { ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, 0x1C9); ++ ++ phyData &= (~(RTLBIT_4 | RTLBIT_12)); ++ phyData |= (RTLBIT_7 | RTLBIT_15); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0x1C9, phyData); ++ ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, 0x1CA); ++ ++ phyData &= (~(RTLBIT_4 | RTLBIT_12)); ++ phyData |= (RTLBIT_5 | RTLBIT_13); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0x1CA, phyData); ++ ++ ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, 0x1C8); ++ ++ phyData &= (~(RTLBIT_3 | RTLBIT_0)); ++ phyData |= (RTLBIT_8); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0x1C8, phyData); ++ ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, 0x1CA); ++ ++ phyData &= (~(RTLBIT_0 | RTLBIT_1 | RTLBIT_2 | RTLBIT_3 | RTLBIT_8 | RTLBIT_9 | RTLBIT_10 | RTLBIT_11 | RTLBIT_15)); ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, 0x1CA, phyData); ++ ++ } ++ return SW_OK; ++} ++ ++ ++ ++ ++a_int32_t ++phy_826xb_init(a_uint32_t unit, a_uint32_t port) ++{ ++ ++ a_int32_t sz = sizeof(phy_rtl826xb_info_t); ++ ++ if (rtl826xb_info[unit] == NULL) ++ { ++ if ((rtl826xb_info[unit] = vzalloc(sz)) == NULL) ++ { ++ return RT_ERR_MEM_ALLOC; ++ } ++ memset(rtl826xb_info[unit], 0, sz); ++ } ++ ++ _phy_826xb_serdes_mode_init(unit, port); ++ ++ ++ _phy_826xb_interrupt_init(unit, port); ++ ++ ++ _phy_826xb_dbgCount_init(unit, port); ++ ++ ++ _phy_826xb_synce_init(unit, port); ++ ++ ++ phy_826xb_ctrl_set(unit, port, RTK_PHY_CTRL_RTCT_CABLE_TYPE ,RTK_PHY_CTRL_RTCT_CABLE_TYPE_CAT5E); ++ ++ ++ return RT_ERR_OK; ++} ++ ++ ++ ++ ++static sw_error_t ++rtl826xb_phy_init(a_uint32_t dev_id, a_uint32_t port_bmp) ++{ ++ a_uint32_t phy_addr = 0, port_id = 0; ++ sw_error_t rv = SW_OK; ++ ++ ++ for (port_id = 0; port_id < SW_MAX_NR_PORT; port_id ++) ++ { ++ if (port_bmp & (0x1 << port_id)) ++ { ++ phy_addr = qca_ssdk_port_to_phy_addr(dev_id, port_id); ++ ++ phy_826xb_ctrl_set(dev_id, phy_addr, RTK_PHY_CTRL_MIIM_BCAST_PHYAD, phy_addr); ++ phy_826xb_ctrl_set(dev_id, phy_addr, RTK_PHY_CTRL_MIIM_BCAST, 1); ++ phy_rtl826xb_broadcast_patch(dev_id, phy_addr, 0); ++ phy_826xb_ctrl_set(dev_id, phy_addr, RTK_PHY_CTRL_MIIM_BCAST, 0); ++ phy_826xb_init(dev_id, phy_addr); ++ } ++ } ++ return rv; ++} ++ ++ ++a_uint16_t phy_826x_linkStatus_get(a_uint32_t unit, a_uint32_t port) ++{ ++ a_uint16_t phyData = 0; ++ a_uint16_t Status; ++ ++ phyData = rtl826x_phy_mmd_read(unit, port, PHY_MMD_PMAPMD, 0x1); ++ Status = (phyData & RTLBIT_2) ? PORT_LINKUP : PORT_LINKDOWN; ++ return Status; ++} ++ ++ ++ ++a_int32_t phy_common_c45_speed_set(a_uint32_t unit, a_uint32_t port, fal_port_speed_t speed) ++{ ++ ++ a_uint16_t phyData = 0; ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_PMAPMD, 0); ++ ++ ++ phyData &= (~(RTLBIT_13 | RTLBIT_6 | RTLBIT_5 | RTLBIT_4 | RTLBIT_3 | RTLBIT_2)); ++ ++ switch (speed) ++ { ++ case FAL_SPEED_10: ++ break; ++ case FAL_SPEED_100: ++ phyData |= RTLBIT_13; ++ break; ++ case FAL_SPEED_1000: ++ phyData |= RTLBIT_6; ++ break; ++ case FAL_SPEED_10000: ++ phyData |= (RTLBIT_13 | RTLBIT_6); ++ break; ++ case FAL_SPEED_2500: ++ phyData |= (RTLBIT_13 | RTLBIT_6 | RTLBIT_4 | RTLBIT_3); ++ break; ++ case FAL_SPEED_5000: ++ phyData |= (RTLBIT_13 | RTLBIT_6 | RTLBIT_4 | RTLBIT_3 | RTLBIT_2); ++ break; ++ default: ++ return SW_NOT_SUPPORTED; ++ } ++ ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_PMAPMD, 0, phyData); ++ return SW_OK; ++} ++ ++a_uint32_t ++_phy_826xb_an_restart(a_uint32_t unit, a_uint32_t port) ++{ ++ a_uint16_t phyData = 0; ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_AN, 0); ++ ++ if (phyData & 0x1000) /*AN is enabled*/ ++ { ++ phyData |= 0x0200; /*AN restart*/ ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_AN, 0, phyData); ++ ++ } ++ return SW_OK; ++} ++ ++sw_error_t phy_826xb_duplex_get(a_uint32_t unit, a_uint32_t port, fal_port_duplex_t *duplex) ++{ ++ ++ a_uint16_t phyData = 0; ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xA434); ++ ++ ++ *duplex = (phyData & 0x8) ? PORT_FULL_DUPLEX : PORT_HALF_DUPLEX; ++ ++ return SW_OK; ++} ++ ++sw_error_t phy_826xb_speed_set(a_uint32_t unit, a_uint32_t port, fal_port_speed_t speed) ++{ ++ ++ a_uint16_t remote_loopback = 0; ++ a_uint16_t phyData; ++ fal_port_duplex_t old_duplex; ++ ++ ++ if (FAL_SPEED_100 != speed) ++ { ++ return SW_OUT_OF_RANGE; ++ } ++ ++ phy_826xb_duplex_get(unit, port, &old_duplex); ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, 0x2A1); ++ remote_loopback = (phyData & RTLBIT_10) ? (1) : (0); ++ ++ // phy_826xb_ctrl_get(unit, port, RTK_PHY_CTRL_LOOPBACK_REMOTE, &remote_loopback); ++ phy_common_c45_speed_set(unit, port, speed); ++ _phy_826xb_an_restart(unit, port); ++ ++ if (remote_loopback != 0) ++ { ++ phy_826xb_ctrl_set(unit, port, RTK_PHY_CTRL_LOOPBACK_REMOTE, remote_loopback); ++ ++ } ++ ++ return SW_OK; ++} ++ ++sw_error_t rtl826x_phy_get_status(a_uint32_t dev_id, a_uint32_t phy_id, struct port_phy_status *phy_status) ++{ ++ a_uint16_t phyData, spd; ++ ++ ++ phy_status->link_status = phy_826x_linkStatus_get(dev_id, phy_id); ++ if(phy_status->link_status != A_TRUE) ++ { ++ return SW_OK; ++ } ++ phyData = phy_common_general_reg_mmd_get(dev_id, phy_id, PHY_MMD_VEND2, 0xA434); ++ spd = ((phyData & (0x3 << 9)) >> (9 - 2)) | ((phyData & (0x3 << 4)) >> 4); ++ ++ ++ switch (spd) ++ { ++ case 0x0: ++ ++ phy_status->speed = FAL_SPEED_10; ++ break; ++ case 0x1: ++ ++ phy_status->speed = FAL_SPEED_100; ++ break; ++ case 0x2: ++ ++ phy_status->speed = FAL_SPEED_1000; ++ break; ++ ++ case 0x4: ++ ++ phy_status->speed = FAL_SPEED_10000; ++ break; ++ case 0x5: ++ ++ phy_status->speed = FAL_SPEED_2500; ++ break; ++ case 0x6: ++ phy_status->speed = FAL_SPEED_5000; ++ break; ++ default: ++ phy_status->speed = FAL_SPEED_10; ++ break; ++ } ++ ++ phyData = phy_common_general_reg_mmd_get(dev_id, phy_id, PHY_MMD_VEND2, 0xA434); ++ ++ ++ phy_status->duplex = (phyData & 0x8) ? FAL_FULL_DUPLEX : FAL_HALF_DUPLEX; ++ ++ phy_status->rx_flowctrl = A_FALSE; ++ ++ phy_status->tx_flowctrl = A_FALSE; ++ ++ return SW_OK; ++} ++ ++ ++sw_error_t phy_common_c45_reset_set(a_uint32_t unit, a_uint32_t port) ++{ ++ a_uint16_t phyData = 0; ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_PMAPMD, 0); ++ phyData |= RTLBIT_15; ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_PMAPMD, 0, phyData); ++ return SW_OK; ++} ++ ++sw_error_t ++phy_common_c45_autoNegoEnable_set(a_uint32_t unit, a_uint32_t port) ++{ ++ sw_error_t ret; ++ a_uint16_t phyData = 0; ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_AN, 0); ++ ++ phyData |= 0x1000; ++ ++ ++ ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_AN, 0, phyData); ++ return ret; ++} ++ ++sw_error_t phy_826xb_autoNegoEnable_set(a_uint32_t unit, a_uint32_t port) ++{ ++ return phy_common_c45_autoNegoEnable_set(unit, port); ++} ++ ++ ++sw_error_t phy_826xb_restart_autoneg(a_uint32_t dev_id, a_uint32_t port) ++{ ++ ++ a_uint16_t ctl; ++ ++ ctl = phy_common_general_reg_mmd_get(dev_id, port, PHY_MMD_AN, 0x0); ++ ++ if (ctl < 0) ++ return ctl; ++ ++ ctl |= (RTLBIT_12 | RTLBIT_9); ++ ++ phy_common_general_reg_mmd_set(dev_id, port, PHY_MMD_AN, 0x0, ctl); ++ return SW_OK; ++ ++} ++ ++a_bool_t ++phy_common_c45_autoNegoEnable_get(a_uint32_t unit, a_uint32_t port) ++{ ++ ++ a_uint16_t phyData = 0; ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_AN, 0); ++ ++ if (phyData & RTLBIT_12) { ++ return A_TRUE; ++ } ++ ++ return A_FALSE; ++} ++ ++ ++sw_error_t ++phy_826xb_autoNegoAbility_set(a_uint32_t dev_id, a_uint32_t phy_id, a_uint32_t autoneg) ++{ ++ ++ a_uint16_t phyData = 0; ++ ++ if ((autoneg & 1 << 0) || (autoneg & 1 << 1)) ++ { ++ return RT_ERR_INPUT; ++ } ++ ++ ++ phyData = phy_common_general_reg_mmd_get(dev_id, phy_id, PHY_MMD_AN, 16); ++ ++ phyData &= (~(0x0020 | 0x0040 | 0x0080 | 0x0100 | 0x0400 | 0x0800)); ++ phyData |= ((autoneg & 1 << 2)) ? (0x0080) : (0); ++ phyData |= ((autoneg & 1 << 3)) ? (0x0100) : (0); ++ phyData |= ((autoneg & 1 << 9)) ? (0x0400) : (0); ++ phyData |= ((autoneg & 1 << 10)) ? (0x0800) : (0); ++ ++ phy_common_general_reg_mmd_set(dev_id, phy_id, PHY_MMD_AN, 16, phyData); ++ ++ phyData = phy_common_general_reg_mmd_get(dev_id, phy_id, PHY_MMD_AN, 32); ++ ++ phyData &= (~(0x0080 | 0x0100 | 0x1000)); ++ phyData |= (autoneg & 1 << 6) ? (0x0080) : (0); ++ phyData |= (autoneg & 1 << 7) ? (0x0100) : (0); ++ phyData |= (autoneg & 1 << 8) ? (0x1000) : (0); ++ ++ phy_common_general_reg_mmd_set(dev_id, phy_id, PHY_MMD_AN, 32, phyData); ++ ++ ++ phyData = phy_common_general_reg_mmd_get(dev_id, phy_id, PHY_MMD_VEND2, 0xA412); ++ ++ ++ phyData &= (~(0x0100 | 0x0200)); ++ phyData |= (autoneg & 1 << 4) ? (0x0100) : (0); ++ phyData |= (autoneg & 1 << 5) ? (0x0200) : (0); ++ ++ phy_common_general_reg_mmd_set(dev_id, phy_id, PHY_MMD_VEND2, 0xA412, phyData); ++ ++ ++ _phy_826xb_an_restart(dev_id, phy_id); ++ return SW_OK; ++} ++ ++sw_error_t ++phy_common_c45_autoNegoAbility_get(a_uint32_t unit, a_uint32_t port, a_uint32_t *autoneg) ++{ ++ sw_error_t ret = SW_OK; ++ a_uint16_t phyData = 0; ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_AN, 16); ++ ++ *autoneg |= (phyData & 0x0020) ? (1) : (0); ++ *autoneg |= (phyData & 0x0040) ? (1) : (0); ++ *autoneg |= (phyData & 0x0080) ? (1) : (0); ++ *autoneg |= (phyData & 0x0100) ? (1) : (0); ++ *autoneg |= (phyData & 0x0400) ? (1) : (0); ++ *autoneg |= (phyData & 0x0800) ? (1) : (0); ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_AN, 32); ++ ++ *autoneg |= (phyData & 0x0080) ? (1) : (0); ++ *autoneg |= (phyData & 0x0100) ? (1) : (0); ++ *autoneg |= (phyData & 0x1000) ? (1) : (0); ++ ++ return ret; ++} ++ ++ ++ ++sw_error_t ++phy_826x_autoNegoAbility_get(a_uint32_t unit, a_uint32_t port, a_uint32_t *autoneg) ++{ ++ ++ a_uint16_t phyData = 0; ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xA412); ++ ++ *autoneg = (phyData & 0x0100) ? (1) : (0); ++ *autoneg = (phyData & 0x0200) ? (1) : (0); ++ ++ phy_common_c45_autoNegoAbility_get(unit, port, autoneg); ++ ++ ++ ++ return SW_OK; ++} ++ ++a_bool_t ++phy_826xb_linkStatus_get(a_uint32_t unit, a_uint32_t port) ++{ ++ a_uint16_t phyData = 0; ++ ++ a_bool_t rv = A_TRUE; ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_PMAPMD, 0x1); ++ ++ rv = (phyData & 0x0004) ? PORT_LINKUP : PORT_LINKDOWN; ++ return rv; ++} ++ ++ ++sw_error_t phy_826xb_phy_id_get(a_uint32_t dev_id, a_uint32_t phy_id, a_uint32_t *phy_data) ++{ ++ a_uint16_t org_id, rev_id; ++ org_id = phy_common_general_reg_mmd_get(dev_id, phy_id, PHY_MMD_PMAPMD, 0x2); ++ rev_id = phy_common_general_reg_mmd_get(dev_id, phy_id, PHY_MMD_PMAPMD, 0x3); ++ ++ *phy_data = ((org_id & 0xffff) << 16) | (rev_id & 0xffff); ++ ++ return SW_OK; ++} ++ ++ ++sw_error_t ++phy_826xb_interface_get_mode_status(a_uint32_t dev_id, a_uint32_t phy_id, ++ fal_port_interface_mode_t *interface_mode_status) ++{ ++ *interface_mode_status = PORT_USXGMII; ++ return SW_OK; ++} ++ ++sw_error_t phy_826xb_poweron(a_uint32_t dev_id, a_uint32_t phy_id) ++{ ++ ++ ++ return SW_OK; ++} ++ ++sw_error_t phy_826xb_poweroff(a_uint32_t dev_id, a_uint32_t phy_id) ++{ ++ ++ return SW_OK; ++} ++ ++sw_error_t phy_826xb_duplex_set(a_uint32_t unit, a_uint32_t port, fal_port_duplex_t duplex) ++{ ++ ++ a_uint16_t phyData = 0; ++ ++ phyData = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xA400); ++ ++ phyData = (duplex == FAL_FULL_DUPLEX) ? (phyData | RTLBIT_8) : (phyData & ~RTLBIT_8); ++ ++ phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND2, 0xA400, phyData); ++ return SW_OK; ++} ++ ++ ++ ++static sw_error_t rtl826xb_phy_api_ops_init(void) ++{ ++ sw_error_t ret = SW_OK; ++ hsl_phy_ops_t *rtl826xb_phy_api_ops = NULL; ++ ++ rtl826xb_phy_api_ops = kzalloc(sizeof(hsl_phy_ops_t), GFP_KERNEL); ++ if (rtl826xb_phy_api_ops == NULL) { ++ SSDK_ERROR("rtl phy ops kzalloc failed!\n"); ++ return -1; ++ } ++ ++ phy_api_ops_init(RTL_PHY_CHIP); ++ ++ rtl826xb_phy_api_ops->phy_reg_write = rtl826x_phy_reg_write; ++ rtl826xb_phy_api_ops->phy_reg_read = rtl826x_phy_reg_read; ++ rtl826xb_phy_api_ops->phy_mmd_read=rtl826x_phy_mmd_read; ++ rtl826xb_phy_api_ops->phy_mmd_write=rtl826x_phy_mmd_write; ++ ++ rtl826xb_phy_api_ops->phy_get_status=rtl826x_phy_get_status; ++ rtl826xb_phy_api_ops->phy_speed_get=phy_common_c45_speed_get; ++ rtl826xb_phy_api_ops->phy_speed_set=phy_826xb_speed_set; ++ rtl826xb_phy_api_ops->phy_duplex_get=phy_826xb_duplex_get; ++ rtl826xb_phy_api_ops->phy_duplex_set=phy_826xb_duplex_set; ++ rtl826xb_phy_api_ops->phy_reset=phy_common_c45_reset_set; ++ ++ rtl826xb_phy_api_ops->phy_autoneg_enable_set=phy_826xb_autoNegoEnable_set; ++ rtl826xb_phy_api_ops->phy_restart_autoneg=phy_826xb_restart_autoneg; ++ rtl826xb_phy_api_ops->phy_autoneg_status_get=phy_common_c45_autoNegoEnable_get; ++ rtl826xb_phy_api_ops->phy_autoneg_adv_set=phy_826xb_autoNegoAbility_set; ++ rtl826xb_phy_api_ops->phy_autoneg_adv_get=phy_826x_autoNegoAbility_get; ++ ++ rtl826xb_phy_api_ops->phy_link_status_get=phy_826xb_linkStatus_get; ++ rtl826xb_phy_api_ops->phy_power_on=phy_826xb_poweron; ++ rtl826xb_phy_api_ops->phy_power_off=phy_826xb_poweroff; ++ rtl826xb_phy_api_ops->phy_id_get=phy_826xb_phy_id_get; ++ rtl826xb_phy_api_ops->phy_interface_mode_status_get=phy_826xb_interface_get_mode_status; ++ ++ ret = hsl_phy_api_ops_register(RTL_PHY_CHIP, rtl826xb_phy_api_ops); ++ ++ if (ret == SW_OK) { ++ SSDK_INFO("qca probe rtl826xb phy driver succeeded!\n"); ++ } else { ++ SSDK_ERROR("qca probe rtl826xb phy driver failed! (code: %d)\n", ret); ++ } ++ ++ return ret; ++ ++ ++} ++ ++ ++ ++/****************************************************************************** ++* ++* rtl_phy_init - ++* ++*/ ++int rtl_phy_init(a_uint32_t dev_id, a_uint32_t port_bmp) ++{ ++ a_int32_t ret = 0; ++ a_int32_t port_id = 0; ++ ++ if(phy_ops_flag == 0) { ++ rtl826xb_phy_lock_init(); ++ rtl826xb_phy_api_ops_init(); ++ phy_ops_flag = 1; ++ } ++ rtl826xb_phy_init(dev_id, port_bmp); ++ if(phy_dev_drv_init_flag == 0) ++ { ++ for (port_id = 0; port_id < SW_MAX_NR_PORT; port_id ++) ++ { ++ if (port_bmp & (0x1 << port_id)) { ++ rtl_phydev_init(dev_id, port_id); ++ } ++ } ++ ret = rtl_phy_driver_register(); ++ phy_dev_drv_init_flag = 1; ++ } ++ ++ ++ return ret; ++} +diff --git a/src/init/ssdk_init.c b/src/init/ssdk_init.c +index 4b4ecfd1..aeb332fe 100755 +--- a/src/init/ssdk_init.c ++++ b/src/init/ssdk_init.c +@@ -511,6 +511,14 @@ qca_switch_init(a_uint32_t dev_id) + switch (chip_type) { + case CHIP_SHIVA: + return SW_OK; ++ case CHIP_APPE: ++ SSDK_DEBUG("set APPE port 2 flowctrl force mode & flowctrl enable\n"); ++ if(2 == i) ++ { ++ fal_port_flowctrl_forcemode_set(dev_id, i, A_TRUE); ++ fal_port_flowctrl_set(dev_id, i, A_TRUE); ++ } ++ break; + case CHIP_DESS: + #ifdef DESS + #ifdef IN_PORTCONTROL +@@ -620,6 +628,8 @@ qca_switch_init(a_uint32_t dev_id) + if (cpu_bmp & BIT(i)) { + #if defined(IN_PORTCONTROL) + fal_port_flowctrl_forcemode_set(dev_id, i, A_TRUE); ++// fal_port_flow_ctrl_thres_set(dev_id, i, ++// MHT_PORT0_XON_THRES, MHT_PORT0_XOFF_THRES); + fal_header_type_set(dev_id, + A_TRUE, MHT_HEADER_TYPE_VAL); + fal_port_rxhdr_mode_set(dev_id, +@@ -1413,6 +1423,27 @@ qca_phy_mib_work_stop(struct qca_phy_priv *priv) + cancel_delayed_work_sync(&priv->mib_dwork); + } + ++void ++qca_phy_mib_work_pause(struct qca_phy_priv *priv) ++{ ++ if(!priv) ++ return; ++ cancel_delayed_work_sync(&priv->mib_dwork); ++} ++ ++int ++qca_phy_mib_work_resume(struct qca_phy_priv *priv) ++{ ++#ifndef SSDK_MIB_CHANGE_WQ ++ schedule_delayed_work(&priv->mib_dwork, ++ msecs_to_jiffies(QCA_PHY_MIB_WORK_DELAY)); ++#else ++ queue_delayed_work_on(0, system_long_wq, &priv->mib_dwork, ++ msecs_to_jiffies(QCA_PHY_MIB_WORK_DELAY)); ++#endif ++ return 0; ++} ++ + #define SSDK_QM_CHANGE_WQ + + static void +-- +2.34.1 + diff --git a/feeds/ipq95xx/qca-ssdk/patches/101-aq_phy.patch b/feeds/ipq95xx/qca-ssdk/patches/101-aq_phy.patch new file mode 100644 index 000000000..b9c3399c6 --- /dev/null +++ b/feeds/ipq95xx/qca-ssdk/patches/101-aq_phy.patch @@ -0,0 +1,28 @@ +Index: qca-ssdk-09cba788ef5680e3e5b9deaa376da8d6bc13a7ec/include/hsl/phy/hsl_phy.h +=================================================================== +--- qca-ssdk-09cba788ef5680e3e5b9deaa376da8d6bc13a7ec.orig/include/hsl/phy/hsl_phy.h ++++ qca-ssdk-09cba788ef5680e3e5b9deaa376da8d6bc13a7ec/include/hsl/phy/hsl_phy.h +@@ -609,6 +609,9 @@ typedef struct { + #define AQUANTIA_PHY_113C_B0 0x31c31C12 + #define AQUANTIA_PHY_113C_B1 0x31c31C13 + #define AQUANTIA_PHY_112C 0x03a1b792 ++/*sercomm*/ ++#define AQUANTIA_PHY_114C 0x31c31c22 ++#define AQUANTIA_PHY_114C_B1 0x31c31c23 + #define RTL_PHY 0X001CCAF3 + + #define PHY_805XV2 0x004DD082 +Index: qca-ssdk-09cba788ef5680e3e5b9deaa376da8d6bc13a7ec/src/hsl/phy/hsl_phy.c +=================================================================== +--- qca-ssdk-09cba788ef5680e3e5b9deaa376da8d6bc13a7ec.orig/src/hsl/phy/hsl_phy.c ++++ qca-ssdk-09cba788ef5680e3e5b9deaa376da8d6bc13a7ec/src/hsl/phy/hsl_phy.c +@@ -285,6 +286,9 @@ phy_type_t hsl_phytype_get_by_phyid(a_ui + case AQUANTIA_PHY_113C_B0: + case AQUANTIA_PHY_113C_B1: + case AQUANTIA_PHY_112C: ++ /*sercomm*/ ++ case AQUANTIA_PHY_114C: ++ case AQUANTIA_PHY_114C_B1: + phytype = AQUANTIA_PHY_CHIP; + break; + case QCA8030_PHY: diff --git a/feeds/mcu/umcumgr/Makefile b/feeds/mcu/umcumgr/Makefile index 212159fc3..3ec3313e1 100644 --- a/feeds/mcu/umcumgr/Makefile +++ b/feeds/mcu/umcumgr/Makefile @@ -10,8 +10,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=umcumgr PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://gitlab.com/pepe2k/umcumgr -PKG_SOURCE_DATE:=2023-03-06 -PKG_SOURCE_VERSION:=966606a2868b8e6b0a2c7e129dc45a30e0d9ef87 +PKG_SOURCE_DATE:=2024-02-02 +PKG_SOURCE_VERSION:=ed34b2816f2b65ee0687944a214fdf6ffd94b85f PKG_LICENSE:=Apache-2.0 PKG_LICENSE_FILES:= @@ -23,6 +23,10 @@ include $(INCLUDE_DIR)/cmake.mk CMAKE_INSTALL:=1 +CMAKE_OPTIONS += -DTI_SERIAL_BL_SUPPORT=ON +CMAKE_OPTIONS += -DTI_SERIAL_BL_DUMPCMD=ON +CMAKE_OPTIONS += -DCONFIRM_TEST_SUPPORT=OFF + define Package/umcumgr SECTION:=utils CATEGORY:=Utilities @@ -31,8 +35,8 @@ define Package/umcumgr endef define Package/umcumgr/description - Simple user space tool for MCU management over MCUmgr SMP - (Simple Management Protocol) protocol + Simple user space tool for MCU management over MCUmgr SMP protocol + and Texas Instruments CC13x2/CC26x2 ROM serial bootloader endef define Package/umcumgr/install diff --git a/feeds/tip/certificates/files/etc/init.d/certificates b/feeds/tip/certificates/files/etc/init.d/early_boot similarity index 58% rename from feeds/tip/certificates/files/etc/init.d/certificates rename to feeds/tip/certificates/files/etc/init.d/early_boot index 9cb41c4f7..c0fcdfe98 100755 --- a/feeds/tip/certificates/files/etc/init.d/certificates +++ b/feeds/tip/certificates/files/etc/init.d/early_boot @@ -1,6 +1,6 @@ #!/bin/sh /etc/rc.common -START=80 +START=09 copy_certificates() { [ -f /certificates/key.pem ] || return @@ -10,9 +10,18 @@ copy_certificates() { chmod 0440 root.network /etc/ucentral/*.pem [ -f /certificates/gateway.json ] && cp /certificates/gateway.json /etc/ucentral/ [ -f /certificates/dev-id ] && cp /certificates/dev-id /etc/ucentral/ - [ -f /etc/ucentral/dev-id] && chmod 0400 /etc/ucentral/dev-id + [ -f /etc/ucentral/dev-id ] && chmod 0400 /etc/ucentral/dev-id [ -f /certificates/restrictions.json ] && cp /certificates/restrictions.json /etc/ucentral/ [ -f /certificates/sign_pubkey.pem ] && cp /certificates/sign_pubkey.pem /etc/ucentral/ + country=`cat /certificates/ucentral.defaults | jsonfilter -e '@.country'` + [ -z "$country" -a -f /etc/uci-defaults/30_uboot-envtools ] && { + (. /etc/uci-defaults/30_uboot-envtools) + fw_printenv + country=$(fw_printenv -n country) + } + [ -z "$country" ] && country=US + echo "options cfg80211 ieee80211_regdom="$country > /etc/modules.conf + echo -n $country > /etc/ucentral/country exit 0 } diff --git a/feeds/tip/certificates/files/usr/bin/mount_certs b/feeds/tip/certificates/files/usr/bin/mount_certs index 56d1c0ab6..a1cac22d1 100755 --- a/feeds/tip/certificates/files/usr/bin/mount_certs +++ b/feeds/tip/certificates/files/usr/bin/mount_certs @@ -44,7 +44,7 @@ actiontec,web7200) edgecore,ecw5211|\ edgecore,eap101|\ edgecore,eap102|\ -edgecore,oap102) +edgecore,oap104) if grep -q rootfs1 /proc/cmdline; then PART_NAME=rootfs2 else diff --git a/feeds/ucentral/rrmd/files/usr/share/rrmd/local.uc b/feeds/ucentral/rrmd/files/usr/share/rrmd/local.uc index 57ec076e6..d4ede8550 100644 --- a/feeds/ucentral/rrmd/files/usr/share/rrmd/local.uc +++ b/feeds/ucentral/rrmd/files/usr/share/rrmd/local.uc @@ -24,6 +24,8 @@ function channel_to_freq(cur_freq, channel) { return 5000 + channel * 5; else if (band == '5G' && channel >= 183 && channel <= 196) return 4000 + channel * 5; + else if (band == '6G' && channel >= 5) + return 5950 + channel * 5; else if (band == '60G' && channel >= 1 && channel <= 6) return 56160 + channel * 2160; diff --git a/feeds/ucentral/rrmd/files/usr/share/rrmd/scan.uc b/feeds/ucentral/rrmd/files/usr/share/rrmd/scan.uc index 0ff017dcf..abe5b4040 100644 --- a/feeds/ucentral/rrmd/files/usr/share/rrmd/scan.uc +++ b/feeds/ucentral/rrmd/files/usr/share/rrmd/scan.uc @@ -100,7 +100,7 @@ function scan_timer() { } catch(e) { printf('%.J\n', e.stacktrace[0].context); }; - return 1000; +// return 1000; } return { diff --git a/feeds/ucentral/ucentral-event/files/ucentral-event b/feeds/ucentral/ucentral-event/files/ucentral-event index b69e46e2f..5c1d38eb5 100755 --- a/feeds/ucentral/ucentral-event/files/ucentral-event +++ b/feeds/ucentral/ucentral-event/files/ucentral-event @@ -34,6 +34,7 @@ let boot_file = "/tmp/booted"; let ucentral_running = false; let pending_events = []; let relay = {}; +let net_config = {}; function config_load() { @@ -46,6 +47,8 @@ function config_load() { if (config.dhcp?.filter == '*') config.dhcp.filter = [ 'ack', 'discover', 'offer', 'request', 'solicit', 'reply', 'renew' ]; + + net_config = {}; } function match(object, type, list) { @@ -54,6 +57,31 @@ function match(object, type, list) { return false; } +function eth_find_bridge_vlan_id(ifname) { + for (let k, v in net_config) { + if (v['.type'] != "bridge-vlan") + continue; + if (ifname in v.ports) + return v.vlan; + } + + return 0; +} + +function eth_get_bridge_vlan_id(ifname) { + if (!ifname || length(ifname) == 0) + return 0; + + let vlan_id = eth_find_bridge_vlan_id(ifname); + if (!vlan_id) { + uci.load('network'); + net_config = uci.get_all('network'); + vlan_id = eth_find_bridge_vlan_id(ifname); + } + + return vlan_id; +} + function event(object, verb, payload) { let type = object; if (verb) @@ -81,6 +109,33 @@ function event(object, verb, payload) { let handlers; handlers = { 'sta-authorized': function(notify, hapd) { + if (!hapd || wildcard(hapd['ifname'], 'eth*')) { + if (!('vlan_id' in notify.data) || notify.data['vlan_id'] == 0) + return; + + if (!wildcard(notify.data.ifname, 'eth*')) + return; + + /* + * This must be a wired 802.1x client with a dynamic VLAN assigned, let's check + * if we need to workaround the bridge VLAN config + */ + + let br_vid = eth_get_bridge_vlan_id(notify.data.ifname); + if (!br_vid || br_vid == notify.data['vlan_id']) + return; + + /* + * netifd will make the bridge VLAN the untagged PVID for the port + * and will add the assigned DVLAN also as an untagged (non-PVID) to the port. + * The result of this is that the client will have access on the bridge VLAN, + * not the correct assigned VLAN. The proper fix should be in netifd, but + * that is complex and will take time, so this workaround seems to work for now + */ + system("bridge vlan del dev " + notify.data.ifname + " vid " + br_vid); + system("bridge vlan add dev " + notify.data.ifname + " vid " + notify.data.vlan_id + " pvid untagged"); + return; + } /* force FDB flush on QCA Wifi-6 silicon */ system(`echo ${notify.data.address} > /sys/kernel/debug/ssdk_flush_mac`); event('client', 'join', { @@ -132,9 +187,12 @@ handlers = { name: 'eth0.' + notify.data.vlan_id, vlan: [ `${notify.data.vlan_id}:u` ] }; - ubus.call('network.interface.up_none', 'add_device', msg); + msg = { 'devices': { } }; + msg['devices']['eth0.' + notify.data.vlan_id] = { 'ingress': true, 'egress': true }; + ubus.call('dhcpsnoop', 'add_devices', msg); + let cmd = 'swconfig dev ' + config.config.swconfig + ' vlan ' + notify.data.vlan_id + ' set ports \"' + join(' ', config.config.swconfig_ports) + '\"'; system(cmd); system('swconfig dev ' + config.config.swconfig + ' set apply'); @@ -186,6 +244,8 @@ function hapd_subscriber_notify_cb(notify) { function hostapd_event(ifname, type) { let payload = {}; + if (!(ifname in hostapd) || wildcard(ifname, 'eth*')) + return; for (let p in [ 'ssid', 'bssid', 'channel', 'band' ]) payload[p] = hostapd[ifname][p]; diff --git a/feeds/ucentral/ucentral-schema/Makefile b/feeds/ucentral/ucentral-schema/Makefile index 913a73e81..62e6b8f32 100644 --- a/feeds/ucentral/ucentral-schema/Makefile +++ b/feeds/ucentral/ucentral-schema/Makefile @@ -4,10 +4,10 @@ PKG_NAME:=ucentral-schema PKG_RELEASE:=1 PKG_SOURCE_URL=https://github.com/Telecominfraproject/wlan-ucentral-schema.git -PKG_MIRROR_HASH:=8ab9a9361415e0302c502d1e92273b4b8098bca5e469783b6813d47b284ed965 +PKG_MIRROR_HASH:=1eef8aa74fd5f675924f58bd0fc3be7e01eb6544cbadd75a07594d1cea6e3484 PKG_SOURCE_PROTO:=git PKG_SOURCE_DATE:=2022-05-29 -PKG_SOURCE_VERSION:=3093a565c4c28609089ac03a4c206fae0c89cb49 +PKG_SOURCE_VERSION:=da090931f0f12206bb86e60fc73640a2f1ee2826 PKG_MAINTAINER:=John Crispin PKG_LICENSE:=BSD-3-Clause diff --git a/feeds/ucentral/ucentral-schema/files/etc/board.d/04-regdm b/feeds/ucentral/ucentral-schema/files/etc/board.d/04-regdm index 04f697ab4..2b4d42029 100755 --- a/feeds/ucentral/ucentral-schema/files/etc/board.d/04-regdm +++ b/feeds/ucentral/ucentral-schema/files/etc/board.d/04-regdm @@ -16,9 +16,11 @@ cig,wf808|\ cig,wf660a) ucidef_set_wifi_country 'US' ;; -cig,wf188n|\ +cig,wf188n) + ucidef_set_wifi_country "US CA MY DE" + ;; cig,wf196) - ucidef_set_wifi_country "$(cat /lib/firmware/country)" + ucidef_set_wifi_country "US CA" ;; esac diff --git a/feeds/ucentral/udhcpsnoop/src/dev.c b/feeds/ucentral/udhcpsnoop/src/dev.c index 20d9a02a1..8adcfdef4 100644 --- a/feeds/ucentral/udhcpsnoop/src/dev.c +++ b/feeds/ucentral/udhcpsnoop/src/dev.c @@ -449,15 +449,19 @@ free: return; } -void dhcpsnoop_dev_config_update(struct blob_attr *data) +void dhcpsnoop_dev_config_update(struct blob_attr *data, bool add_only) { struct blob_attr *cur; int rem; - vlist_update(&devices); + if (!add_only) + vlist_update(&devices); + blobmsg_for_each_attr(cur, data, rem) dhcpsnoop_dev_config_add(cur); - vlist_flush(&devices); + + if (!add_only) + vlist_flush(&devices); } void dhcpsnoop_dev_check(void) diff --git a/feeds/ucentral/udhcpsnoop/src/dhcpsnoop.h b/feeds/ucentral/udhcpsnoop/src/dhcpsnoop.h index 2ae799c06..cc46ceb0c 100644 --- a/feeds/ucentral/udhcpsnoop/src/dhcpsnoop.h +++ b/feeds/ucentral/udhcpsnoop/src/dhcpsnoop.h @@ -16,7 +16,7 @@ int dhcpsnoop_run_cmd(char *cmd, bool ignore_error); int dhcpsnoop_dev_init(void); void dhcpsnoop_dev_done(void); -void dhcpsnoop_dev_config_update(struct blob_attr *data); +void dhcpsnoop_dev_config_update(struct blob_attr *data, bool add_only); void dhcpsnoop_dev_check(void); void dhcpsnoop_ubus_init(void); diff --git a/feeds/ucentral/udhcpsnoop/src/ubus.c b/feeds/ucentral/udhcpsnoop/src/ubus.c index e95849009..4567e1c65 100644 --- a/feeds/ucentral/udhcpsnoop/src/ubus.c +++ b/feeds/ucentral/udhcpsnoop/src/ubus.c @@ -27,7 +27,7 @@ dhcpsnoop_ubus_config(struct ubus_context *ctx, struct ubus_object *obj, blobmsg_parse(dhcpsnoop_config_policy, __DS_CONFIG_MAX, tb, blobmsg_data(msg), blobmsg_len(msg)); - dhcpsnoop_dev_config_update(tb[DS_CONFIG_DEVICES]); + dhcpsnoop_dev_config_update(tb[DS_CONFIG_DEVICES], false); dhcpsnoop_dev_check(); @@ -35,6 +35,23 @@ dhcpsnoop_ubus_config(struct ubus_context *ctx, struct ubus_object *obj, } +static int +dhcpsnoop_ubus_add_devices(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct blob_attr *tb[__DS_CONFIG_MAX]; + + blobmsg_parse(dhcpsnoop_config_policy, __DS_CONFIG_MAX, tb, + blobmsg_data(msg), blobmsg_len(msg)); + + dhcpsnoop_dev_config_update(tb[DS_CONFIG_DEVICES], true); + + dhcpsnoop_dev_check(); + + return 0; +} + static int dhcpsnoop_ubus_check_devices(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, @@ -61,6 +78,7 @@ dhcpsnoop_ubus_dump(struct ubus_context *ctx, struct ubus_object *obj, static const struct ubus_method dhcpsnoop_methods[] = { UBUS_METHOD("config", dhcpsnoop_ubus_config, dhcpsnoop_config_policy), + UBUS_METHOD("add_devices", dhcpsnoop_ubus_add_devices, dhcpsnoop_config_policy), UBUS_METHOD_NOARG("check_devices", dhcpsnoop_ubus_check_devices), UBUS_METHOD_NOARG("dump", dhcpsnoop_ubus_dump), }; diff --git a/feeds/wifi-ax/ath11k-wifi/board-cybertan-eww631-a1.bin.IPQ5018 b/feeds/wifi-ax/ath11k-wifi/board-cybertan-eww631-a1.bin.IPQ5018 index d2809f880..9a45fb464 100644 Binary files a/feeds/wifi-ax/ath11k-wifi/board-cybertan-eww631-a1.bin.IPQ5018 and b/feeds/wifi-ax/ath11k-wifi/board-cybertan-eww631-a1.bin.IPQ5018 differ diff --git a/feeds/wifi-ax/ath11k-wifi/board-cybertan-eww631-a1.bin.QCN6122 b/feeds/wifi-ax/ath11k-wifi/board-cybertan-eww631-a1.bin.QCN6122 index c4b904c72..be9248e8a 100644 Binary files a/feeds/wifi-ax/ath11k-wifi/board-cybertan-eww631-a1.bin.QCN6122 and b/feeds/wifi-ax/ath11k-wifi/board-cybertan-eww631-a1.bin.QCN6122 differ diff --git a/feeds/wifi-ax/ath11k-wifi/board-cybertan-eww631-b1.bin.IPQ5018 b/feeds/wifi-ax/ath11k-wifi/board-cybertan-eww631-b1.bin.IPQ5018 old mode 100755 new mode 100644 index 523964f96..c3c54fc3b Binary files a/feeds/wifi-ax/ath11k-wifi/board-cybertan-eww631-b1.bin.IPQ5018 and b/feeds/wifi-ax/ath11k-wifi/board-cybertan-eww631-b1.bin.IPQ5018 differ diff --git a/feeds/wifi-ax/ath11k-wifi/board-cybertan-eww631-b1.bin.QCN6122 b/feeds/wifi-ax/ath11k-wifi/board-cybertan-eww631-b1.bin.QCN6122 old mode 100755 new mode 100644 index 0edab9349..154bf666e Binary files a/feeds/wifi-ax/ath11k-wifi/board-cybertan-eww631-b1.bin.QCN6122 and b/feeds/wifi-ax/ath11k-wifi/board-cybertan-eww631-b1.bin.QCN6122 differ diff --git a/feeds/wifi-ax/hostapd/patches/x-0005-add-vlan_id-to-sta-authorized-event.patch b/feeds/wifi-ax/hostapd/patches/x-0005-add-vlan_id-to-sta-authorized-event.patch new file mode 100644 index 000000000..3632282ba --- /dev/null +++ b/feeds/wifi-ax/hostapd/patches/x-0005-add-vlan_id-to-sta-authorized-event.patch @@ -0,0 +1,11 @@ +--- a/src/ap/ubus.c ++++ b/src/ap/ubus.c +@@ -1914,6 +1914,8 @@ void hostapd_ubus_notify_authorized(stru + blob_buf_init(&b, 0); + blobmsg_add_macaddr(&b, "address", sta->addr); + blobmsg_add_string(&b, "ifname", hapd->conf->iface); ++ if (sta->vlan_id) ++ blobmsg_add_u32(&b, "vlan_id", sta->vlan_id); + if (sta->bandwidth[0] || sta->bandwidth[1]) { + void *r = blobmsg_open_array(&b, "rate-limit"); + diff --git a/patches/0038-ipq807x-prepare-tree-for-old-v4.4-kernel.patch b/patches/0038-ipq807x-prepare-tree-for-old-v4.4-kernel.patch index 6ec7632ef..4b89504ff 100644 --- a/patches/0038-ipq807x-prepare-tree-for-old-v4.4-kernel.patch +++ b/patches/0038-ipq807x-prepare-tree-for-old-v4.4-kernel.patch @@ -702,7 +702,7 @@ index 18cafe60a2..a860c557de 100644 echo "generic patches directory is present. please move your patches to the pending directory" ; \ exit 1; \ fi -+ifneq ($(CONFIG_TARGET_ipq807x)$(CONFIG_TARGET_ipq60xx)$(CONFIG_TARGET_ipq50xx)$(CONFIG_TARGET_ipq95xx),y) ++ifneq ($(CONFIG_TARGET_ipq807x)$(CONFIG_TARGET_ipq60xx)$(CONFIG_TARGET_ipq50xx)$(CONFIG_TARGET_ipq95xx)$(CONFIG_TARGET_ipq53xx),y) $(call PatchDir,$(LINUX_DIR),$(GENERIC_BACKPORT_DIR),generic-backport/) $(call PatchDir,$(LINUX_DIR),$(GENERIC_PATCH_DIR),generic/) $(call PatchDir,$(LINUX_DIR),$(GENERIC_HACK_DIR),generic-hack/) @@ -714,7 +714,7 @@ index 18cafe60a2..a860c557de 100644 echo "All kernel patches must start with either generic/ or platform/"; \ false; \ } -+ifneq ($(CONFIG_TARGET_ipq807x)$(CONFIG_TARGET_ipq60xx)$(CONFIG_TARGET_ipq50xx)$(CONFIG_TARGET_ipq95xx),y) ++ifneq ($(CONFIG_TARGET_ipq807x)$(CONFIG_TARGET_ipq60xx)$(CONFIG_TARGET_ipq50xx)$(CONFIG_TARGET_ipq95xx)$(CONFIG_TARGET_ipq53xx),y) $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(GENERIC_BACKPORT_DIR),generic-backport/) $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(GENERIC_PATCH_DIR),generic/) $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(GENERIC_HACK_DIR),generic-hack/) @@ -749,7 +749,7 @@ index b5e3e7ff6f..36e1377617 100644 endif GENERIC_PLATFORM_DIR := $(TOPDIR)/target/linux/generic -+ifeq ($(CONFIG_TARGET_ipq807x)$(CONFIG_TARGET_ipq60xx)$(CONFIG_TARGET_ipq50xx)$(CONFIG_TARGET_ipq95xx),y) ++ifeq ($(CONFIG_TARGET_ipq807x)$(CONFIG_TARGET_ipq60xx)$(CONFIG_TARGET_ipq50xx)$(CONFIG_TARGET_ipq95xx)$(CONFIG_TARGET_ipq53xx),y) +GENERIC_BACKPORT_DIR := +GENERIC_PATCH_DIR := +GENERIC_HACK_DIR := @@ -765,7 +765,7 @@ index b5e3e7ff6f..36e1377617 100644 __config_list = $(firstword $(wildcard $(call __config_name_list,$(1)))) find_kernel_config=$(if $(__config_list),$(__config_list),$(lastword $(__config_name_list))) -+ifeq ($(CONFIG_TARGET_ipq807x)$(CONFIG_TARGET_ipq60xx)$(CONFIG_TARGET_ipq50xx)$(CONFIG_TARGET_ipq95xx),y) ++ifeq ($(CONFIG_TARGET_ipq807x)$(CONFIG_TARGET_ipq60xx)$(CONFIG_TARGET_ipq50xx)$(CONFIG_TARGET_ipq95xx)$(CONFIG_TARGET_ipq53xx),y) +GENERIC_LINUX_CONFIG:=$(GENERIC_PLATFORM_DIR)/config-5.4-qsdk +else GENERIC_LINUX_CONFIG = $(call find_kernel_config,$(GENERIC_PLATFORM_DIR)) diff --git a/patches/0042-ipq807x-drop-nand.sh-from-base-files.patch b/patches/0042-ipq807x-drop-nand.sh-from-base-files.patch index fe704c23d..19460b0bf 100644 --- a/patches/0042-ipq807x-drop-nand.sh-from-base-files.patch +++ b/patches/0042-ipq807x-drop-nand.sh-from-base-files.patch @@ -16,7 +16,7 @@ index dc89de2035..dd1d0760f8 100644 endef endif -+ifeq ($(CONFIG_LINUX_4_4)$(CONFIG_TARGET_ipq95xx),y) ++ifeq ($(CONFIG_LINUX_4_4)$(CONFIG_TARGET_ipq95xx)$(CONFIG_TARGET_ipq53xx),y) + define Package/base-files/ipq807x-support + rm -f $(1)/lib/upgrade/nand.sh + endef diff --git a/patches/0045-ucode-add-TIP-specific-fixes.patch b/patches/0045-ucode-add-TIP-specific-fixes.patch index 8b62a5b8a..cf8199df9 100644 --- a/patches/0045-ucode-add-TIP-specific-fixes.patch +++ b/patches/0045-ucode-add-TIP-specific-fixes.patch @@ -20,7 +20,7 @@ index e2fe4c8bad..4bdd955832 100644 -DUCI_SUPPORT=OFF \ -DULOOP_SUPPORT=OFF -+ifeq ($(CONFIG_TARGET_ipq95xx),y) ++ifeq ($(CONFIG_TARGET_ipq95xx)$(CONFIG_TARGET_ipq53xx),y) +TARGET_CFLAGS += -DQCA_WIFI_7 +endif + diff --git a/patches/0058-kernel-add-v5.4-checksums.patch b/patches/0058-kernel-add-v5.4-checksums.patch index 55270fa13..4b823fdb7 100644 --- a/patches/0058-kernel-add-v5.4-checksums.patch +++ b/patches/0058-kernel-add-v5.4-checksums.patch @@ -21,9 +21,9 @@ index daf1f1740a..ec9733780d 100644 +LINUX_KERNEL_HASH-5.4.158 = 6e018fecdc8fc24553756e582d83b82d65b10a6b03ef36262a24911f839b8d59 +endif + -+ifeq ($(CONFIG_TARGET_ipq95xx),y) ++ifeq ($(CONFIG_TARGET_ipq95xx)$(CONFIG_TARGET_ipq53xx),y) +LINUX_VERSION-5.4 = .213 -+LINUX_KERNEL_HASH-5.4.213 = d13de2f5e02569eebeb40ee9373fc0b4d0bf6b69595b38ea95c1f878a5bd0447 ++LINUX_KERNEL_HASH-5.4.213 = 53d191b59994a3b8b5c9cac7391cbf0a4186ba4bd08b9f378e2d05bfd4921f6d +endif + -- diff --git a/patches/0060-mediatek-add-edgecore-eap111-support.patch b/patches/0060-mediatek-add-edgecore-eap111-support.patch index fa3e7f7d4..adfb7cd2d 100644 --- a/patches/0060-mediatek-add-edgecore-eap111-support.patch +++ b/patches/0060-mediatek-add-edgecore-eap111-support.patch @@ -6,7 +6,7 @@ Subject: [PATCH] mediatek: add edgecore eap111 support Signed-off-by: John Crispin --- .../uboot-envtools/files/mediatek_filogic | 1 + - .../mediatek/dts/mt7981a-edgecore-eap111.dts | 189 +++ + .../mediatek/dts/mt7981a-edgecore-eap111.dts | 194 +++ .../mediatek/files/drivers/net/phy/en8801sc.c | 1152 +++++++++++++++++ .../mediatek/files/drivers/net/phy/en8801sc.h | 255 ++++ .../filogic/base-files/etc/board.d/01_leds | 4 + @@ -37,13 +37,13 @@ new file mode 100644 index 0000000000..e22c099b34 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981a-edgecore-eap111.dts -@@ -0,0 +1,189 @@ +@@ -0,0 +1,194 @@ +/dts-v1/; + +#include "mt7981.dtsi" + +/ { -+ model = "edgecore mt7981"; ++ model = "EdgeCore EAP111"; + compatible = "edgecore,eap111", "mediatek,mt7981"; + + aliases { @@ -111,7 +111,7 @@ index 0000000000..e22c099b34 + reg = <0>; + phy-mode = "sgmii"; + phy-handle = <&phy0>; -+ nvmem-cells = <&macaddr>; ++ nvmem-cells = <&macaddr1>; + nvmem-cell-names = "mac-address"; + managed = "in-band-status"; + }; @@ -121,8 +121,7 @@ index 0000000000..e22c099b34 + reg = <1>; + phy-mode = "gmii"; + phy-handle = <&int_gbe_phy>; -+ mac-address-increment = <1>; -+ nvmem-cells = <&macaddr>; ++ nvmem-cells = <&macaddr2>; + nvmem-cell-names = "mac-address"; + }; +}; @@ -196,6 +195,12 @@ index 0000000000..e22c099b34 + macaddr: macaddr@a { + reg = <0xa 0x6>; + }; ++ macaddr1: macaddr@2a { ++ reg = <0x2a 0x6>; ++ }; ++ macaddr2: macaddr@24 { ++ reg = <0x24 0x6>; ++ }; + }; + + partition@380000 { diff --git a/patches/0068-ucode-update-to-latest-HEAD.patch b/patches/0068-ucode-update-to-latest-HEAD.patch index f4cac2393..69e0d83df 100644 --- a/patches/0068-ucode-update-to-latest-HEAD.patch +++ b/patches/0068-ucode-update-to-latest-HEAD.patch @@ -58,7 +58,7 @@ index 5cae355e68..a999d58f93 100644 + -DDEBUG_SUPPORT=ON \ + -DLOG_SUPPORT=OFF - ifeq ($(CONFIG_TARGET_ipq95xx),y) + ifeq ($(CONFIG_TARGET_ipq95xx)$(CONFIG_TARGET_ipq53xx),y) TARGET_CFLAGS += -DQCA_WIFI_7 @@ -73,115 +85,40 @@ define Package/libucode DEPENDS:=+libjson-c diff --git a/profiles/cig_wf188n.yml b/profiles/cig_wf188n.yml index 441894e25..5f7f39d29 100644 --- a/profiles/cig_wf188n.yml +++ b/profiles/cig_wf188n.yml @@ -1,9 +1,9 @@ --- -profile: cig_wf188n-us +profile: cig_wf188n target: ipq60xx subtarget: generic description: Build image for the Cigtech WF188n -image: bin/targets/ipq60xx/generic/openwrt-ipq60xx-cig_wf188n-us-squashfs-sysupgrade.tar +image: bin/targets/ipq60xx/generic/openwrt-ipq60xx-cig_wf188n-squashfs-sysupgrade.tar feeds: - name: ipq807x path: ../../feeds/ipq807x_v5.4 @@ -11,3 +11,5 @@ include: - ucentral-ap packages: - ipq60xx + - ath11k-fwtest + - ftm diff --git a/profiles/cig_wf189.yml b/profiles/cig_wf189.yml new file mode 100644 index 000000000..430d87da3 --- /dev/null +++ b/profiles/cig_wf189.yml @@ -0,0 +1,15 @@ +--- +profile: cig_wf189 +target: ipq53xx +subtarget: generic +description: Build image for the CIG WF189 +image: bin/targets/ipq53xx/generic/openwrt-ipq53xx-cig_wf189-squashfs-sysupgrade.tar +feeds: + - name: ipq95xx + path: ../../feeds/ipq95xx +packages: + - ipq53xx +include: + - ucentral-ap +diffconfig: | + CONFIG_KERNEL_IPQ_MEM_PROFILE=0 diff --git a/profiles/cig_wf196.yml b/profiles/cig_wf196.yml index 542b903cd..7baa5b34b 100644 --- a/profiles/cig_wf196.yml +++ b/profiles/cig_wf196.yml @@ -1,9 +1,9 @@ --- -profile: cig_wf196_us +profile: cig_wf196 target: ipq807x subtarget: generic -description: Build image for the CIG WF196 (US) -image: bin/targets/ipq807x/generic/openwrt-ipq807x-cig_wf196_us-squashfs-sysupgrade.tar +description: Build image for the CIG WF196 +image: bin/targets/ipq807x/generic/openwrt-ipq807x-cig_wf196-squashfs-sysupgrade.tar feeds: - name: ipq807x path: ../../feeds/ipq807x_v5.4 @@ -11,5 +11,7 @@ include: - ucentral-ap packages: - ipq807x + - ath11k-fwtest + - ftm diffconfig: | CONFIG_KERNEL_IPQ_MEM_PROFILE=0 diff --git a/profiles/cybertan_eww631-a1-legacy.yml b/profiles/cybertan_eww631-a1-legacy.yml new file mode 100644 index 000000000..c7bb1aa82 --- /dev/null +++ b/profiles/cybertan_eww631-a1-legacy.yml @@ -0,0 +1,14 @@ +--- +profile: cybertan_eww631_a1 +target: ipq807x +subtarget: ipq50xx +description: Build image for the CyberTan Ceilingmount EAP EWW631-A1 +image: bin/targets/ipq807x/ipq50xx/openwrt-ipq807x-cybertan_eww631_a1-squashfs-sysupgrade.tar +feeds: + - name: ipq807x + path: ../../feeds/ipq807x +packages: + - ipq807x +include: + - wifi-ax + - ucentral-ap diff --git a/profiles/cybertan_eww631-a1.yml b/profiles/cybertan_eww631-a1.yml index c7bb1aa82..835ffe2d5 100644 --- a/profiles/cybertan_eww631-a1.yml +++ b/profiles/cybertan_eww631-a1.yml @@ -1,14 +1,13 @@ --- profile: cybertan_eww631_a1 -target: ipq807x -subtarget: ipq50xx -description: Build image for the CyberTan Ceilingmount EAP EWW631-A1 -image: bin/targets/ipq807x/ipq50xx/openwrt-ipq807x-cybertan_eww631_a1-squashfs-sysupgrade.tar +target: ipq50xx +subtarget: generic +description: Build image for the CyberTan Ceiling Mount EAP EWW631-A1 +image: bin/targets/ipq50xx/generic/openwrt-ipq50xx-cybertan_eww631_a1-squashfs-sysupgrade.tar feeds: - name: ipq807x - path: ../../feeds/ipq807x + path: ../../feeds/ipq807x_v5.4 packages: - - ipq807x + - ipq50xx include: - - wifi-ax - ucentral-ap diff --git a/profiles/cybertan_eww631-b1-legacy.yml b/profiles/cybertan_eww631-b1-legacy.yml new file mode 100644 index 000000000..9588a3bdc --- /dev/null +++ b/profiles/cybertan_eww631-b1-legacy.yml @@ -0,0 +1,14 @@ +--- +profile: cybertan_eww631_b1 +target: ipq807x +subtarget: ipq50xx +description: Build image for the CyberTan Wallmount EAP EWW631-B1 +image: bin/targets/ipq807x/ipq50xx/openwrt-ipq807x-cybertan_eww631_b1-squashfs-sysupgrade.tar +feeds: + - name: ipq807x + path: ../../feeds/ipq807x +packages: + - ipq807x +include: + - wifi-ax + - ucentral-ap diff --git a/profiles/cybertan_eww631-b1.yml b/profiles/cybertan_eww631-b1.yml index 9588a3bdc..f200096bf 100644 --- a/profiles/cybertan_eww631-b1.yml +++ b/profiles/cybertan_eww631-b1.yml @@ -1,14 +1,13 @@ --- profile: cybertan_eww631_b1 -target: ipq807x -subtarget: ipq50xx +target: ipq50xx +subtarget: generic description: Build image for the CyberTan Wallmount EAP EWW631-B1 -image: bin/targets/ipq807x/ipq50xx/openwrt-ipq807x-cybertan_eww631_b1-squashfs-sysupgrade.tar +image: bin/targets/ipq50xx/generic/openwrt-ipq50xx-cybertan_eww631_b1-squashfs-sysupgrade.tar feeds: - name: ipq807x - path: ../../feeds/ipq807x + path: ../../feeds/ipq807x_v5.4 packages: - - ipq807x + - ipq50xx include: - - wifi-ax - ucentral-ap diff --git a/profiles/sercomm_ap72tip.yml b/profiles/sercomm_ap72tip.yml new file mode 100644 index 000000000..39efb1864 --- /dev/null +++ b/profiles/sercomm_ap72tip.yml @@ -0,0 +1,15 @@ +--- +profile: sercomm_ap72tip +target: ipq53xx +subtarget: generic +description: Build image for the Sercomm AP72 TIP +image: bin/targets/ipq53xx/generic/openwrt-ipq53xx-sercomm_ap72tip-squashfs-sysupgrade.tar +feeds: + - name: ipq95xx + path: ../../feeds/ipq95xx +packages: + - ipq53xx +include: + - ucentral-ap +diffconfig: | + CONFIG_KERNEL_IPQ_MEM_PROFILE=0 diff --git a/profiles/ucentral-ap.yml b/profiles/ucentral-ap.yml index d1a6fe782..f8ac946c7 100644 --- a/profiles/ucentral-ap.yml +++ b/profiles/ucentral-ap.yml @@ -63,6 +63,7 @@ packages: - umdns - oping - vxlan + - wireless-regdb - wpad-openssl diffconfig: | CONFIG_OPENSSL_ENGINE=y diff --git a/profiles/wallys_dr6018-v4.yml b/profiles/wallys_dr6018-v4.yml new file mode 100644 index 000000000..df0f9221f --- /dev/null +++ b/profiles/wallys_dr6018-v4.yml @@ -0,0 +1,16 @@ +--- +profile: wallys_dr6018-v4 +target: ipq60xx +subtarget: generic +description: Build image for the Wallys DR6018 V4 +image: bin/targets/ipq60xx/generic/openwrt-ipq60xx-wallys_dr6018-v4-squashfs-sysupgrade.tar +feeds: + - name: ipq807x + path: ../../feeds/ipq807x_v5.4 +include: + - wifi-ax-v54 + - ucentral-ap +packages: + - ipq60xx +diffconfig: | + CONFIG_KERNEL_IPQ_MEM_PROFILE=0 diff --git a/profiles/wallys_dr6018_v4.yml b/profiles/wallys_dr6018_v4.yml deleted file mode 100644 index 55281c7a1..000000000 --- a/profiles/wallys_dr6018_v4.yml +++ /dev/null @@ -1,16 +0,0 @@ ---- -profile: wallys_dr6018_v4 -target: ipq807x -subtarget: ipq60xx -description: Build image for the Wallys DR6018 V4 -image: bin/targets/ipq807x/ipq60xx/openwrt-ipq807x-wallys_dr6018_v4-squashfs-sysupgrade.tar -feeds: - - name: ipq807x - path: ../../feeds/ipq807x -include: - - wifi-ax - - ucentral-ap -packages: - - ipq807x -diffconfig: | - CONFIG_KERNEL_IPQ_MEM_PROFILE=0 diff --git a/profiles/yuncore_fap655-ath12.yml b/profiles/yuncore_fap655-ath12.yml deleted file mode 100644 index 8c7220dc1..000000000 --- a/profiles/yuncore_fap655-ath12.yml +++ /dev/null @@ -1,15 +0,0 @@ ---- -profile: yuncore_fap655 -target: ipq50xx -subtarget: generic -description: Build image for Yuncore FAP655 -image: bin/targets/ipq50xx/generic/openwrt-ipq50xx-yuncore_fap655-squashfs-sysupgrade.tar -feeds: - - name: ipq807x - path: ../../feeds/ipq807x_v5.4 -include: - - ucentral-ap -packages: - - ipq50xx -diffconfig: | - CONFIG_KERNEL_IPQ_MEM_PROFILE=512 diff --git a/profiles/yuncore_fap655-legacy.yml b/profiles/yuncore_fap655-legacy.yml new file mode 100644 index 000000000..730673d79 --- /dev/null +++ b/profiles/yuncore_fap655-legacy.yml @@ -0,0 +1,14 @@ +--- +profile: yuncore_fap655 +target: ipq807x +subtarget: ipq50xx +description: Build image for Yuncore FAP655 +image: bin/targets/ipq807x/ipq50xx/openwrt-ipq807x-yuncore_fap655-squashfs-sysupgrade.tar +feeds: + - name: ipq807x + path: ../../feeds/ipq807x +include: + - wifi-ax + - ucentral-ap +packages: + - ipq807x diff --git a/profiles/yuncore_fap655.yml b/profiles/yuncore_fap655.yml index 730673d79..8c7220dc1 100644 --- a/profiles/yuncore_fap655.yml +++ b/profiles/yuncore_fap655.yml @@ -1,14 +1,15 @@ --- profile: yuncore_fap655 -target: ipq807x -subtarget: ipq50xx +target: ipq50xx +subtarget: generic description: Build image for Yuncore FAP655 -image: bin/targets/ipq807x/ipq50xx/openwrt-ipq807x-yuncore_fap655-squashfs-sysupgrade.tar +image: bin/targets/ipq50xx/generic/openwrt-ipq50xx-yuncore_fap655-squashfs-sysupgrade.tar feeds: - name: ipq807x - path: ../../feeds/ipq807x + path: ../../feeds/ipq807x_v5.4 include: - - wifi-ax - ucentral-ap packages: - - ipq807x + - ipq50xx +diffconfig: | + CONFIG_KERNEL_IPQ_MEM_PROFILE=512